Add file missed in last commit.
[qemu/dscho.git] / target-mips / op.c
blob12498d033507d3ad083dbac0a5ecc8f04d95fa14
1 /*
2 * MIPS emulation micro-operations for qemu.
3 *
4 * Copyright (c) 2004-2005 Jocelyn Mayer
5 * Copyright (c) 2006 Marius Groeger (FPU operations)
6 * Copyright (c) 2007 Thiemo Seufer (64-bit FPU support)
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "config.h"
24 #include "exec.h"
26 #ifndef CALL_FROM_TB0
27 #define CALL_FROM_TB0(func) func()
28 #endif
29 #ifndef CALL_FROM_TB1
30 #define CALL_FROM_TB1(func, arg0) func(arg0)
31 #endif
32 #ifndef CALL_FROM_TB1_CONST16
33 #define CALL_FROM_TB1_CONST16(func, arg0) CALL_FROM_TB1(func, arg0)
34 #endif
35 #ifndef CALL_FROM_TB2
36 #define CALL_FROM_TB2(func, arg0, arg1) func(arg0, arg1)
37 #endif
38 #ifndef CALL_FROM_TB2_CONST16
39 #define CALL_FROM_TB2_CONST16(func, arg0, arg1) \
40 CALL_FROM_TB2(func, arg0, arg1)
41 #endif
42 #ifndef CALL_FROM_TB3
43 #define CALL_FROM_TB3(func, arg0, arg1, arg2) func(arg0, arg1, arg2)
44 #endif
45 #ifndef CALL_FROM_TB4
46 #define CALL_FROM_TB4(func, arg0, arg1, arg2, arg3) \
47 func(arg0, arg1, arg2, arg3)
48 #endif
50 #define REG 1
51 #include "op_template.c"
52 #undef REG
53 #define REG 2
54 #include "op_template.c"
55 #undef REG
56 #define REG 3
57 #include "op_template.c"
58 #undef REG
59 #define REG 4
60 #include "op_template.c"
61 #undef REG
62 #define REG 5
63 #include "op_template.c"
64 #undef REG
65 #define REG 6
66 #include "op_template.c"
67 #undef REG
68 #define REG 7
69 #include "op_template.c"
70 #undef REG
71 #define REG 8
72 #include "op_template.c"
73 #undef REG
74 #define REG 9
75 #include "op_template.c"
76 #undef REG
77 #define REG 10
78 #include "op_template.c"
79 #undef REG
80 #define REG 11
81 #include "op_template.c"
82 #undef REG
83 #define REG 12
84 #include "op_template.c"
85 #undef REG
86 #define REG 13
87 #include "op_template.c"
88 #undef REG
89 #define REG 14
90 #include "op_template.c"
91 #undef REG
92 #define REG 15
93 #include "op_template.c"
94 #undef REG
95 #define REG 16
96 #include "op_template.c"
97 #undef REG
98 #define REG 17
99 #include "op_template.c"
100 #undef REG
101 #define REG 18
102 #include "op_template.c"
103 #undef REG
104 #define REG 19
105 #include "op_template.c"
106 #undef REG
107 #define REG 20
108 #include "op_template.c"
109 #undef REG
110 #define REG 21
111 #include "op_template.c"
112 #undef REG
113 #define REG 22
114 #include "op_template.c"
115 #undef REG
116 #define REG 23
117 #include "op_template.c"
118 #undef REG
119 #define REG 24
120 #include "op_template.c"
121 #undef REG
122 #define REG 25
123 #include "op_template.c"
124 #undef REG
125 #define REG 26
126 #include "op_template.c"
127 #undef REG
128 #define REG 27
129 #include "op_template.c"
130 #undef REG
131 #define REG 28
132 #include "op_template.c"
133 #undef REG
134 #define REG 29
135 #include "op_template.c"
136 #undef REG
137 #define REG 30
138 #include "op_template.c"
139 #undef REG
140 #define REG 31
141 #include "op_template.c"
142 #undef REG
144 #define TN
145 #include "op_template.c"
146 #undef TN
148 #define FREG 0
149 #include "fop_template.c"
150 #undef FREG
151 #define FREG 1
152 #include "fop_template.c"
153 #undef FREG
154 #define FREG 2
155 #include "fop_template.c"
156 #undef FREG
157 #define FREG 3
158 #include "fop_template.c"
159 #undef FREG
160 #define FREG 4
161 #include "fop_template.c"
162 #undef FREG
163 #define FREG 5
164 #include "fop_template.c"
165 #undef FREG
166 #define FREG 6
167 #include "fop_template.c"
168 #undef FREG
169 #define FREG 7
170 #include "fop_template.c"
171 #undef FREG
172 #define FREG 8
173 #include "fop_template.c"
174 #undef FREG
175 #define FREG 9
176 #include "fop_template.c"
177 #undef FREG
178 #define FREG 10
179 #include "fop_template.c"
180 #undef FREG
181 #define FREG 11
182 #include "fop_template.c"
183 #undef FREG
184 #define FREG 12
185 #include "fop_template.c"
186 #undef FREG
187 #define FREG 13
188 #include "fop_template.c"
189 #undef FREG
190 #define FREG 14
191 #include "fop_template.c"
192 #undef FREG
193 #define FREG 15
194 #include "fop_template.c"
195 #undef FREG
196 #define FREG 16
197 #include "fop_template.c"
198 #undef FREG
199 #define FREG 17
200 #include "fop_template.c"
201 #undef FREG
202 #define FREG 18
203 #include "fop_template.c"
204 #undef FREG
205 #define FREG 19
206 #include "fop_template.c"
207 #undef FREG
208 #define FREG 20
209 #include "fop_template.c"
210 #undef FREG
211 #define FREG 21
212 #include "fop_template.c"
213 #undef FREG
214 #define FREG 22
215 #include "fop_template.c"
216 #undef FREG
217 #define FREG 23
218 #include "fop_template.c"
219 #undef FREG
220 #define FREG 24
221 #include "fop_template.c"
222 #undef FREG
223 #define FREG 25
224 #include "fop_template.c"
225 #undef FREG
226 #define FREG 26
227 #include "fop_template.c"
228 #undef FREG
229 #define FREG 27
230 #include "fop_template.c"
231 #undef FREG
232 #define FREG 28
233 #include "fop_template.c"
234 #undef FREG
235 #define FREG 29
236 #include "fop_template.c"
237 #undef FREG
238 #define FREG 30
239 #include "fop_template.c"
240 #undef FREG
241 #define FREG 31
242 #include "fop_template.c"
243 #undef FREG
245 #define FTN
246 #include "fop_template.c"
247 #undef FTN
249 void op_dup_T0 (void)
251 T2 = T0;
252 RETURN();
255 void op_load_HI (void)
257 T0 = env->HI;
258 RETURN();
261 void op_store_HI (void)
263 env->HI = T0;
264 RETURN();
267 void op_load_LO (void)
269 T0 = env->LO;
270 RETURN();
273 void op_store_LO (void)
275 env->LO = T0;
276 RETURN();
279 /* Load and store */
280 #define MEMSUFFIX _raw
281 #include "op_mem.c"
282 #undef MEMSUFFIX
283 #if !defined(CONFIG_USER_ONLY)
284 #define MEMSUFFIX _user
285 #include "op_mem.c"
286 #undef MEMSUFFIX
288 #define MEMSUFFIX _kernel
289 #include "op_mem.c"
290 #undef MEMSUFFIX
291 #endif
293 /* Addresses computation */
294 void op_addr_add (void)
296 /* For compatibility with 32-bit code, data reference in user mode
297 with Status_UX = 0 should be casted to 32-bit and sign extended.
298 See the MIPS64 PRA manual, section 4.10. */
299 #ifdef TARGET_MIPS64
300 if ((env->hflags & MIPS_HFLAG_UM) &&
301 !(env->CP0_Status & (1 << CP0St_UX)))
302 T0 = (int64_t)(int32_t)(T0 + T1);
303 else
304 #endif
305 T0 += T1;
306 RETURN();
309 /* Arithmetic */
310 void op_add (void)
312 T0 = (int32_t)((int32_t)T0 + (int32_t)T1);
313 RETURN();
316 void op_addo (void)
318 target_ulong tmp;
320 tmp = (int32_t)T0;
321 T0 = (int32_t)T0 + (int32_t)T1;
322 if (((tmp ^ T1 ^ (-1)) & (T0 ^ T1)) >> 31) {
323 /* operands of same sign, result different sign */
324 CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
326 T0 = (int32_t)T0;
327 RETURN();
330 void op_sub (void)
332 T0 = (int32_t)((int32_t)T0 - (int32_t)T1);
333 RETURN();
336 void op_subo (void)
338 target_ulong tmp;
340 tmp = (int32_t)T0;
341 T0 = (int32_t)T0 - (int32_t)T1;
342 if (((tmp ^ T1) & (tmp ^ T0)) >> 31) {
343 /* operands of different sign, first operand and result different sign */
344 CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
346 T0 = (int32_t)T0;
347 RETURN();
350 void op_mul (void)
352 T0 = (int32_t)((int32_t)T0 * (int32_t)T1);
353 RETURN();
356 #if HOST_LONG_BITS < 64
357 void op_div (void)
359 CALL_FROM_TB0(do_div);
360 RETURN();
362 #else
363 void op_div (void)
365 if (T1 != 0) {
366 env->LO = (int32_t)((int64_t)(int32_t)T0 / (int32_t)T1);
367 env->HI = (int32_t)((int64_t)(int32_t)T0 % (int32_t)T1);
369 RETURN();
371 #endif
373 void op_divu (void)
375 if (T1 != 0) {
376 env->LO = (int32_t)((uint32_t)T0 / (uint32_t)T1);
377 env->HI = (int32_t)((uint32_t)T0 % (uint32_t)T1);
379 RETURN();
382 #ifdef TARGET_MIPS64
383 /* Arithmetic */
384 void op_dadd (void)
386 T0 += T1;
387 RETURN();
390 void op_daddo (void)
392 target_long tmp;
394 tmp = T0;
395 T0 += T1;
396 if (((tmp ^ T1 ^ (-1)) & (T0 ^ T1)) >> 63) {
397 /* operands of same sign, result different sign */
398 CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
400 RETURN();
403 void op_dsub (void)
405 T0 -= T1;
406 RETURN();
409 void op_dsubo (void)
411 target_long tmp;
413 tmp = T0;
414 T0 = (int64_t)T0 - (int64_t)T1;
415 if (((tmp ^ T1) & (tmp ^ T0)) >> 63) {
416 /* operands of different sign, first operand and result different sign */
417 CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
419 RETURN();
422 void op_dmul (void)
424 T0 = (int64_t)T0 * (int64_t)T1;
425 RETURN();
428 /* Those might call libgcc functions. */
429 void op_ddiv (void)
431 do_ddiv();
432 RETURN();
435 #if TARGET_LONG_BITS > HOST_LONG_BITS
436 void op_ddivu (void)
438 do_ddivu();
439 RETURN();
441 #else
442 void op_ddivu (void)
444 if (T1 != 0) {
445 env->LO = T0 / T1;
446 env->HI = T0 % T1;
448 RETURN();
450 #endif
451 #endif /* TARGET_MIPS64 */
453 /* Logical */
454 void op_and (void)
456 T0 &= T1;
457 RETURN();
460 void op_nor (void)
462 T0 = ~(T0 | T1);
463 RETURN();
466 void op_or (void)
468 T0 |= T1;
469 RETURN();
472 void op_xor (void)
474 T0 ^= T1;
475 RETURN();
478 void op_sll (void)
480 T0 = (int32_t)((uint32_t)T0 << T1);
481 RETURN();
484 void op_sra (void)
486 T0 = (int32_t)((int32_t)T0 >> T1);
487 RETURN();
490 void op_srl (void)
492 T0 = (int32_t)((uint32_t)T0 >> T1);
493 RETURN();
496 void op_rotr (void)
498 target_ulong tmp;
500 if (T1) {
501 tmp = (int32_t)((uint32_t)T0 << (0x20 - T1));
502 T0 = (int32_t)((uint32_t)T0 >> T1) | tmp;
504 RETURN();
507 void op_sllv (void)
509 T0 = (int32_t)((uint32_t)T1 << ((uint32_t)T0 & 0x1F));
510 RETURN();
513 void op_srav (void)
515 T0 = (int32_t)((int32_t)T1 >> (T0 & 0x1F));
516 RETURN();
519 void op_srlv (void)
521 T0 = (int32_t)((uint32_t)T1 >> (T0 & 0x1F));
522 RETURN();
525 void op_rotrv (void)
527 target_ulong tmp;
529 T0 &= 0x1F;
530 if (T0) {
531 tmp = (int32_t)((uint32_t)T1 << (0x20 - T0));
532 T0 = (int32_t)((uint32_t)T1 >> T0) | tmp;
533 } else
534 T0 = T1;
535 RETURN();
538 void op_clo (void)
540 int n;
542 if (T0 == ~((target_ulong)0)) {
543 T0 = 32;
544 } else {
545 for (n = 0; n < 32; n++) {
546 if (!(T0 & (1 << 31)))
547 break;
548 T0 = T0 << 1;
550 T0 = n;
552 RETURN();
555 void op_clz (void)
557 int n;
559 if (T0 == 0) {
560 T0 = 32;
561 } else {
562 for (n = 0; n < 32; n++) {
563 if (T0 & (1 << 31))
564 break;
565 T0 = T0 << 1;
567 T0 = n;
569 RETURN();
572 #ifdef TARGET_MIPS64
574 #if TARGET_LONG_BITS > HOST_LONG_BITS
575 /* Those might call libgcc functions. */
576 void op_dsll (void)
578 CALL_FROM_TB0(do_dsll);
579 RETURN();
582 void op_dsll32 (void)
584 CALL_FROM_TB0(do_dsll32);
585 RETURN();
588 void op_dsra (void)
590 CALL_FROM_TB0(do_dsra);
591 RETURN();
594 void op_dsra32 (void)
596 CALL_FROM_TB0(do_dsra32);
597 RETURN();
600 void op_dsrl (void)
602 CALL_FROM_TB0(do_dsrl);
603 RETURN();
606 void op_dsrl32 (void)
608 CALL_FROM_TB0(do_dsrl32);
609 RETURN();
612 void op_drotr (void)
614 CALL_FROM_TB0(do_drotr);
615 RETURN();
618 void op_drotr32 (void)
620 CALL_FROM_TB0(do_drotr32);
621 RETURN();
624 void op_dsllv (void)
626 CALL_FROM_TB0(do_dsllv);
627 RETURN();
630 void op_dsrav (void)
632 CALL_FROM_TB0(do_dsrav);
633 RETURN();
636 void op_dsrlv (void)
638 CALL_FROM_TB0(do_dsrlv);
639 RETURN();
642 void op_drotrv (void)
644 CALL_FROM_TB0(do_drotrv);
645 RETURN();
648 #else /* TARGET_LONG_BITS > HOST_LONG_BITS */
650 void op_dsll (void)
652 T0 = T0 << T1;
653 RETURN();
656 void op_dsll32 (void)
658 T0 = T0 << (T1 + 32);
659 RETURN();
662 void op_dsra (void)
664 T0 = (int64_t)T0 >> T1;
665 RETURN();
668 void op_dsra32 (void)
670 T0 = (int64_t)T0 >> (T1 + 32);
671 RETURN();
674 void op_dsrl (void)
676 T0 = T0 >> T1;
677 RETURN();
680 void op_dsrl32 (void)
682 T0 = T0 >> (T1 + 32);
683 RETURN();
686 void op_drotr (void)
688 target_ulong tmp;
690 if (T1) {
691 tmp = T0 << (0x40 - T1);
692 T0 = (T0 >> T1) | tmp;
694 RETURN();
697 void op_drotr32 (void)
699 target_ulong tmp;
701 if (T1) {
702 tmp = T0 << (0x40 - (32 + T1));
703 T0 = (T0 >> (32 + T1)) | tmp;
705 RETURN();
708 void op_dsllv (void)
710 T0 = T1 << (T0 & 0x3F);
711 RETURN();
714 void op_dsrav (void)
716 T0 = (int64_t)T1 >> (T0 & 0x3F);
717 RETURN();
720 void op_dsrlv (void)
722 T0 = T1 >> (T0 & 0x3F);
723 RETURN();
726 void op_drotrv (void)
728 target_ulong tmp;
730 T0 &= 0x3F;
731 if (T0) {
732 tmp = T1 << (0x40 - T0);
733 T0 = (T1 >> T0) | tmp;
734 } else
735 T0 = T1;
736 RETURN();
738 #endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
740 void op_dclo (void)
742 int n;
744 if (T0 == ~((target_ulong)0)) {
745 T0 = 64;
746 } else {
747 for (n = 0; n < 64; n++) {
748 if (!(T0 & (1ULL << 63)))
749 break;
750 T0 = T0 << 1;
752 T0 = n;
754 RETURN();
757 void op_dclz (void)
759 int n;
761 if (T0 == 0) {
762 T0 = 64;
763 } else {
764 for (n = 0; n < 64; n++) {
765 if (T0 & (1ULL << 63))
766 break;
767 T0 = T0 << 1;
769 T0 = n;
771 RETURN();
773 #endif
775 /* 64 bits arithmetic */
776 #if TARGET_LONG_BITS > HOST_LONG_BITS
777 void op_mult (void)
779 CALL_FROM_TB0(do_mult);
780 RETURN();
783 void op_multu (void)
785 CALL_FROM_TB0(do_multu);
786 RETURN();
789 void op_madd (void)
791 CALL_FROM_TB0(do_madd);
792 RETURN();
795 void op_maddu (void)
797 CALL_FROM_TB0(do_maddu);
798 RETURN();
801 void op_msub (void)
803 CALL_FROM_TB0(do_msub);
804 RETURN();
807 void op_msubu (void)
809 CALL_FROM_TB0(do_msubu);
810 RETURN();
813 #else /* TARGET_LONG_BITS > HOST_LONG_BITS */
815 static inline uint64_t get_HILO (void)
817 return ((uint64_t)env->HI << 32) | ((uint64_t)(uint32_t)env->LO);
820 static inline void set_HILO (uint64_t HILO)
822 env->LO = (int32_t)(HILO & 0xFFFFFFFF);
823 env->HI = (int32_t)(HILO >> 32);
826 void op_mult (void)
828 set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
829 RETURN();
832 void op_multu (void)
834 set_HILO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
835 RETURN();
838 void op_madd (void)
840 int64_t tmp;
842 tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
843 set_HILO((int64_t)get_HILO() + tmp);
844 RETURN();
847 void op_maddu (void)
849 uint64_t tmp;
851 tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
852 set_HILO(get_HILO() + tmp);
853 RETURN();
856 void op_msub (void)
858 int64_t tmp;
860 tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
861 set_HILO((int64_t)get_HILO() - tmp);
862 RETURN();
865 void op_msubu (void)
867 uint64_t tmp;
869 tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
870 set_HILO(get_HILO() - tmp);
871 RETURN();
873 #endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
875 #ifdef TARGET_MIPS64
876 void op_dmult (void)
878 CALL_FROM_TB4(muls64, &(env->HI), &(env->LO), T0, T1);
879 RETURN();
882 void op_dmultu (void)
884 CALL_FROM_TB4(mulu64, &(env->HI), &(env->LO), T0, T1);
885 RETURN();
887 #endif
889 /* Conditional moves */
890 void op_movn (void)
892 if (T1 != 0)
893 env->gpr[PARAM1] = T0;
894 RETURN();
897 void op_movz (void)
899 if (T1 == 0)
900 env->gpr[PARAM1] = T0;
901 RETURN();
904 void op_movf (void)
906 if (!(env->fcr31 & PARAM1))
907 T0 = T1;
908 RETURN();
911 void op_movt (void)
913 if (env->fcr31 & PARAM1)
914 T0 = T1;
915 RETURN();
918 /* Tests */
919 #define OP_COND(name, cond) \
920 void glue(op_, name) (void) \
922 if (cond) { \
923 T0 = 1; \
924 } else { \
925 T0 = 0; \
927 RETURN(); \
930 OP_COND(eq, T0 == T1);
931 OP_COND(ne, T0 != T1);
932 OP_COND(ge, (target_long)T0 >= (target_long)T1);
933 OP_COND(geu, T0 >= T1);
934 OP_COND(lt, (target_long)T0 < (target_long)T1);
935 OP_COND(ltu, T0 < T1);
936 OP_COND(gez, (target_long)T0 >= 0);
937 OP_COND(gtz, (target_long)T0 > 0);
938 OP_COND(lez, (target_long)T0 <= 0);
939 OP_COND(ltz, (target_long)T0 < 0);
941 /* Branches */
942 void OPPROTO op_goto_tb0(void)
944 GOTO_TB(op_goto_tb0, PARAM1, 0);
945 RETURN();
948 void OPPROTO op_goto_tb1(void)
950 GOTO_TB(op_goto_tb1, PARAM1, 1);
951 RETURN();
954 /* Branch to register */
955 void op_save_breg_target (void)
957 env->btarget = T2;
958 RETURN();
961 void op_restore_breg_target (void)
963 T2 = env->btarget;
964 RETURN();
967 void op_breg (void)
969 env->PC = T2;
970 RETURN();
973 void op_save_btarget (void)
975 env->btarget = PARAM1;
976 RETURN();
979 #ifdef TARGET_MIPS64
980 void op_save_btarget64 (void)
982 env->btarget = ((uint64_t)PARAM1 << 32) | (uint32_t)PARAM2;
983 RETURN();
985 #endif
987 /* Conditional branch */
988 void op_set_bcond (void)
990 T2 = T0;
991 RETURN();
994 void op_save_bcond (void)
996 env->bcond = T2;
997 RETURN();
1000 void op_restore_bcond (void)
1002 T2 = env->bcond;
1003 RETURN();
1006 void op_jnz_T2 (void)
1008 if (T2)
1009 GOTO_LABEL_PARAM(1);
1010 RETURN();
1013 /* CP0 functions */
1014 void op_mfc0_index (void)
1016 T0 = env->CP0_Index;
1017 RETURN();
1020 void op_mfc0_random (void)
1022 CALL_FROM_TB0(do_mfc0_random);
1023 RETURN();
1026 void op_mfc0_entrylo0 (void)
1028 T0 = (int32_t)env->CP0_EntryLo0;
1029 RETURN();
1032 void op_mfc0_entrylo1 (void)
1034 T0 = (int32_t)env->CP0_EntryLo1;
1035 RETURN();
1038 void op_mfc0_context (void)
1040 T0 = (int32_t)env->CP0_Context;
1041 RETURN();
1044 void op_mfc0_pagemask (void)
1046 T0 = env->CP0_PageMask;
1047 RETURN();
1050 void op_mfc0_pagegrain (void)
1052 T0 = env->CP0_PageGrain;
1053 RETURN();
1056 void op_mfc0_wired (void)
1058 T0 = env->CP0_Wired;
1059 RETURN();
1062 void op_mfc0_hwrena (void)
1064 T0 = env->CP0_HWREna;
1065 RETURN();
1068 void op_mfc0_badvaddr (void)
1070 T0 = (int32_t)env->CP0_BadVAddr;
1071 RETURN();
1074 void op_mfc0_count (void)
1076 CALL_FROM_TB0(do_mfc0_count);
1077 RETURN();
1080 void op_mfc0_entryhi (void)
1082 T0 = (int32_t)env->CP0_EntryHi;
1083 RETURN();
1086 void op_mfc0_compare (void)
1088 T0 = env->CP0_Compare;
1089 RETURN();
1092 void op_mfc0_status (void)
1094 T0 = env->CP0_Status;
1095 RETURN();
1098 void op_mfc0_intctl (void)
1100 T0 = env->CP0_IntCtl;
1101 RETURN();
1104 void op_mfc0_srsctl (void)
1106 T0 = env->CP0_SRSCtl;
1107 RETURN();
1110 void op_mfc0_srsmap (void)
1112 T0 = env->CP0_SRSMap;
1113 RETURN();
1116 void op_mfc0_cause (void)
1118 T0 = env->CP0_Cause;
1119 RETURN();
1122 void op_mfc0_epc (void)
1124 T0 = (int32_t)env->CP0_EPC;
1125 RETURN();
1128 void op_mfc0_prid (void)
1130 T0 = env->CP0_PRid;
1131 RETURN();
1134 void op_mfc0_ebase (void)
1136 T0 = env->CP0_EBase;
1137 RETURN();
1140 void op_mfc0_config0 (void)
1142 T0 = env->CP0_Config0;
1143 RETURN();
1146 void op_mfc0_config1 (void)
1148 T0 = env->CP0_Config1;
1149 RETURN();
1152 void op_mfc0_config2 (void)
1154 T0 = env->CP0_Config2;
1155 RETURN();
1158 void op_mfc0_config3 (void)
1160 T0 = env->CP0_Config3;
1161 RETURN();
1164 void op_mfc0_config6 (void)
1166 T0 = env->CP0_Config6;
1167 RETURN();
1170 void op_mfc0_config7 (void)
1172 T0 = env->CP0_Config7;
1173 RETURN();
1176 void op_mfc0_lladdr (void)
1178 T0 = (int32_t)env->CP0_LLAddr >> 4;
1179 RETURN();
1182 void op_mfc0_watchlo (void)
1184 T0 = (int32_t)env->CP0_WatchLo[PARAM1];
1185 RETURN();
1188 void op_mfc0_watchhi (void)
1190 T0 = env->CP0_WatchHi[PARAM1];
1191 RETURN();
1194 void op_mfc0_xcontext (void)
1196 T0 = (int32_t)env->CP0_XContext;
1197 RETURN();
1200 void op_mfc0_framemask (void)
1202 T0 = env->CP0_Framemask;
1203 RETURN();
1206 void op_mfc0_debug (void)
1208 T0 = env->CP0_Debug;
1209 if (env->hflags & MIPS_HFLAG_DM)
1210 T0 |= 1 << CP0DB_DM;
1211 RETURN();
1214 void op_mfc0_depc (void)
1216 T0 = (int32_t)env->CP0_DEPC;
1217 RETURN();
1220 void op_mfc0_performance0 (void)
1222 T0 = env->CP0_Performance0;
1223 RETURN();
1226 void op_mfc0_taglo (void)
1228 T0 = env->CP0_TagLo;
1229 RETURN();
1232 void op_mfc0_datalo (void)
1234 T0 = env->CP0_DataLo;
1235 RETURN();
1238 void op_mfc0_taghi (void)
1240 T0 = env->CP0_TagHi;
1241 RETURN();
1244 void op_mfc0_datahi (void)
1246 T0 = env->CP0_DataHi;
1247 RETURN();
1250 void op_mfc0_errorepc (void)
1252 T0 = (int32_t)env->CP0_ErrorEPC;
1253 RETURN();
1256 void op_mfc0_desave (void)
1258 T0 = env->CP0_DESAVE;
1259 RETURN();
1262 void op_mtc0_index (void)
1264 env->CP0_Index = (env->CP0_Index & 0x80000000) | (T0 % env->nb_tlb);
1265 RETURN();
1268 void op_mtc0_entrylo0 (void)
1270 /* Large physaddr not implemented */
1271 /* 1k pages not implemented */
1272 env->CP0_EntryLo0 = T0 & 0x3FFFFFFF;
1273 RETURN();
1276 void op_mtc0_entrylo1 (void)
1278 /* Large physaddr not implemented */
1279 /* 1k pages not implemented */
1280 env->CP0_EntryLo1 = T0 & 0x3FFFFFFF;
1281 RETURN();
1284 void op_mtc0_context (void)
1286 env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (T0 & ~0x007FFFFF);
1287 RETURN();
1290 void op_mtc0_pagemask (void)
1292 /* 1k pages not implemented */
1293 env->CP0_PageMask = T0 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
1294 RETURN();
1297 void op_mtc0_pagegrain (void)
1299 /* SmartMIPS not implemented */
1300 /* Large physaddr not implemented */
1301 /* 1k pages not implemented */
1302 env->CP0_PageGrain = 0;
1303 RETURN();
1306 void op_mtc0_wired (void)
1308 env->CP0_Wired = T0 % env->nb_tlb;
1309 RETURN();
1312 void op_mtc0_hwrena (void)
1314 env->CP0_HWREna = T0 & 0x0000000F;
1315 RETURN();
1318 void op_mtc0_count (void)
1320 CALL_FROM_TB2(cpu_mips_store_count, env, T0);
1321 RETURN();
1324 void op_mtc0_entryhi (void)
1326 target_ulong old, val;
1328 /* 1k pages not implemented */
1329 val = T0 & ((TARGET_PAGE_MASK << 1) | 0xFF);
1330 #ifdef TARGET_MIPS64
1331 val &= env->SEGMask;
1332 #endif
1333 old = env->CP0_EntryHi;
1334 env->CP0_EntryHi = val;
1335 /* If the ASID changes, flush qemu's TLB. */
1336 if ((old & 0xFF) != (val & 0xFF))
1337 CALL_FROM_TB2(cpu_mips_tlb_flush, env, 1);
1338 RETURN();
1341 void op_mtc0_compare (void)
1343 CALL_FROM_TB2(cpu_mips_store_compare, env, T0);
1344 RETURN();
1347 void op_mtc0_status (void)
1349 uint32_t val, old;
1350 uint32_t mask = env->Status_rw_bitmask;
1352 /* No reverse endianness, no MDMX/DSP implemented. */
1353 val = T0 & mask;
1354 old = env->CP0_Status;
1355 if (!(val & (1 << CP0St_EXL)) &&
1356 !(val & (1 << CP0St_ERL)) &&
1357 !(env->hflags & MIPS_HFLAG_DM) &&
1358 (val & (1 << CP0St_UM)))
1359 env->hflags |= MIPS_HFLAG_UM;
1360 #ifdef TARGET_MIPS64
1361 if (!(env->CP0_Config0 & (0x3 << CP0C0_AT)) ||
1362 ((env->hflags & MIPS_HFLAG_UM) &&
1363 !(val & (1 << CP0St_PX)) &&
1364 !(val & (1 << CP0St_UX))))
1365 env->hflags &= ~MIPS_HFLAG_64;
1366 #endif
1367 if (val & (1 << CP0St_CU1))
1368 env->hflags |= MIPS_HFLAG_FPU;
1369 else
1370 env->hflags &= ~MIPS_HFLAG_FPU;
1371 if (val & (1 << CP0St_FR))
1372 env->hflags |= MIPS_HFLAG_F64;
1373 else
1374 env->hflags &= ~MIPS_HFLAG_F64;
1375 env->CP0_Status = (env->CP0_Status & ~mask) | val;
1376 if (loglevel & CPU_LOG_EXEC)
1377 CALL_FROM_TB2(do_mtc0_status_debug, old, val);
1378 CALL_FROM_TB1(cpu_mips_update_irq, env);
1379 RETURN();
1382 void op_mtc0_intctl (void)
1384 /* vectored interrupts not implemented, timer on int 7,
1385 no performance counters. */
1386 env->CP0_IntCtl |= T0 & 0x000002e0;
1387 RETURN();
1390 void op_mtc0_srsctl (void)
1392 /* shadow registers not implemented */
1393 env->CP0_SRSCtl = 0;
1394 RETURN();
1397 void op_mtc0_srsmap (void)
1399 /* shadow registers not implemented */
1400 env->CP0_SRSMap = 0;
1401 RETURN();
1404 void op_mtc0_cause (void)
1406 uint32_t mask = 0x00C00300;
1408 if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) == (1 << CP0C0_AR))
1409 mask |= 1 << CP0Ca_DC;
1411 env->CP0_Cause = (env->CP0_Cause & ~mask) | (T0 & mask);
1413 /* Handle the software interrupt as an hardware one, as they
1414 are very similar */
1415 if (T0 & CP0Ca_IP_mask) {
1416 CALL_FROM_TB1(cpu_mips_update_irq, env);
1418 RETURN();
1421 void op_mtc0_epc (void)
1423 env->CP0_EPC = T0;
1424 RETURN();
1427 void op_mtc0_ebase (void)
1429 /* vectored interrupts not implemented */
1430 /* Multi-CPU not implemented */
1431 env->CP0_EBase = 0x80000000 | (T0 & 0x3FFFF000);
1432 RETURN();
1435 void op_mtc0_config0 (void)
1437 env->CP0_Config0 = (env->CP0_Config0 & 0x81FFFFF8) | (T0 & 0x00000007);
1438 RETURN();
1441 void op_mtc0_config2 (void)
1443 /* tertiary/secondary caches not implemented */
1444 env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
1445 RETURN();
1448 void op_mtc0_watchlo (void)
1450 /* Watch exceptions for instructions, data loads, data stores
1451 not implemented. */
1452 env->CP0_WatchLo[PARAM1] = (T0 & ~0x7);
1453 RETURN();
1456 void op_mtc0_watchhi (void)
1458 env->CP0_WatchHi[PARAM1] = (T0 & 0x40FF0FF8);
1459 env->CP0_WatchHi[PARAM1] &= ~(env->CP0_WatchHi[PARAM1] & T0 & 0x7);
1460 RETURN();
1463 void op_mtc0_framemask (void)
1465 env->CP0_Framemask = T0; /* XXX */
1466 RETURN();
1469 void op_mtc0_debug (void)
1471 env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120);
1472 if (T0 & (1 << CP0DB_DM))
1473 env->hflags |= MIPS_HFLAG_DM;
1474 else
1475 env->hflags &= ~MIPS_HFLAG_DM;
1476 RETURN();
1479 void op_mtc0_depc (void)
1481 env->CP0_DEPC = T0;
1482 RETURN();
1485 void op_mtc0_performance0 (void)
1487 env->CP0_Performance0 = T0; /* XXX */
1488 RETURN();
1491 void op_mtc0_taglo (void)
1493 env->CP0_TagLo = T0 & 0xFFFFFCF6;
1494 RETURN();
1497 void op_mtc0_datalo (void)
1499 env->CP0_DataLo = T0; /* XXX */
1500 RETURN();
1503 void op_mtc0_taghi (void)
1505 env->CP0_TagHi = T0; /* XXX */
1506 RETURN();
1509 void op_mtc0_datahi (void)
1511 env->CP0_DataHi = T0; /* XXX */
1512 RETURN();
1515 void op_mtc0_errorepc (void)
1517 env->CP0_ErrorEPC = T0;
1518 RETURN();
1521 void op_mtc0_desave (void)
1523 env->CP0_DESAVE = T0;
1524 RETURN();
1527 #ifdef TARGET_MIPS64
1528 void op_mtc0_xcontext (void)
1530 target_ulong mask = (1ULL << (env->SEGBITS - 7)) - 1;
1531 env->CP0_XContext = (env->CP0_XContext & mask) | (T0 & ~mask);
1532 RETURN();
1535 void op_dmfc0_entrylo0 (void)
1537 T0 = env->CP0_EntryLo0;
1538 RETURN();
1541 void op_dmfc0_entrylo1 (void)
1543 T0 = env->CP0_EntryLo1;
1544 RETURN();
1547 void op_dmfc0_context (void)
1549 T0 = env->CP0_Context;
1550 RETURN();
1553 void op_dmfc0_badvaddr (void)
1555 T0 = env->CP0_BadVAddr;
1556 RETURN();
1559 void op_dmfc0_entryhi (void)
1561 T0 = env->CP0_EntryHi;
1562 RETURN();
1565 void op_dmfc0_epc (void)
1567 T0 = env->CP0_EPC;
1568 RETURN();
1571 void op_dmfc0_lladdr (void)
1573 T0 = env->CP0_LLAddr >> 4;
1574 RETURN();
1577 void op_dmfc0_watchlo (void)
1579 T0 = env->CP0_WatchLo[PARAM1];
1580 RETURN();
1583 void op_dmfc0_xcontext (void)
1585 T0 = env->CP0_XContext;
1586 RETURN();
1589 void op_dmfc0_depc (void)
1591 T0 = env->CP0_DEPC;
1592 RETURN();
1595 void op_dmfc0_errorepc (void)
1597 T0 = env->CP0_ErrorEPC;
1598 RETURN();
1600 #endif /* TARGET_MIPS64 */
1602 /* CP1 functions */
1603 #if 0
1604 # define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env)
1605 #else
1606 # define DEBUG_FPU_STATE() do { } while(0)
1607 #endif
1609 void op_cp0_enabled(void)
1611 if (!(env->CP0_Status & (1 << CP0St_CU0)) &&
1612 (env->hflags & MIPS_HFLAG_UM)) {
1613 CALL_FROM_TB2(do_raise_exception_err, EXCP_CpU, 0);
1615 RETURN();
1618 void op_cfc1 (void)
1620 switch (T1) {
1621 case 0:
1622 T0 = (int32_t)env->fcr0;
1623 break;
1624 case 25:
1625 T0 = ((env->fcr31 >> 24) & 0xfe) | ((env->fcr31 >> 23) & 0x1);
1626 break;
1627 case 26:
1628 T0 = env->fcr31 & 0x0003f07c;
1629 break;
1630 case 28:
1631 T0 = (env->fcr31 & 0x00000f83) | ((env->fcr31 >> 22) & 0x4);
1632 break;
1633 default:
1634 T0 = (int32_t)env->fcr31;
1635 break;
1637 DEBUG_FPU_STATE();
1638 RETURN();
1641 void op_ctc1 (void)
1643 CALL_FROM_TB0(do_ctc1);
1644 DEBUG_FPU_STATE();
1645 RETURN();
1648 void op_mfc1 (void)
1650 T0 = WT0;
1651 DEBUG_FPU_STATE();
1652 RETURN();
1655 void op_mtc1 (void)
1657 WT0 = T0;
1658 DEBUG_FPU_STATE();
1659 RETURN();
1662 void op_dmfc1 (void)
1664 T0 = DT0;
1665 DEBUG_FPU_STATE();
1666 RETURN();
1669 void op_dmtc1 (void)
1671 DT0 = T0;
1672 DEBUG_FPU_STATE();
1673 RETURN();
1676 void op_mfhc1 (void)
1678 T0 = WTH0;
1679 DEBUG_FPU_STATE();
1680 RETURN();
1683 void op_mthc1 (void)
1685 WTH0 = T0;
1686 DEBUG_FPU_STATE();
1687 RETURN();
1690 /* Float support.
1691 Single precition routines have a "s" suffix, double precision a
1692 "d" suffix, 32bit integer "w", 64bit integer "l", paired singe "ps",
1693 paired single lowwer "pl", paired single upper "pu". */
1695 #define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void)
1697 FLOAT_OP(cvtd, s)
1699 CALL_FROM_TB0(do_float_cvtd_s);
1700 DEBUG_FPU_STATE();
1701 RETURN();
1703 FLOAT_OP(cvtd, w)
1705 CALL_FROM_TB0(do_float_cvtd_w);
1706 DEBUG_FPU_STATE();
1707 RETURN();
1709 FLOAT_OP(cvtd, l)
1711 CALL_FROM_TB0(do_float_cvtd_l);
1712 DEBUG_FPU_STATE();
1713 RETURN();
1715 FLOAT_OP(cvtl, d)
1717 CALL_FROM_TB0(do_float_cvtl_d);
1718 DEBUG_FPU_STATE();
1719 RETURN();
1721 FLOAT_OP(cvtl, s)
1723 CALL_FROM_TB0(do_float_cvtl_s);
1724 DEBUG_FPU_STATE();
1725 RETURN();
1727 FLOAT_OP(cvtps, s)
1729 WT2 = WT0;
1730 WTH2 = WT1;
1731 DEBUG_FPU_STATE();
1732 RETURN();
1734 FLOAT_OP(cvtps, pw)
1736 CALL_FROM_TB0(do_float_cvtps_pw);
1737 DEBUG_FPU_STATE();
1738 RETURN();
1740 FLOAT_OP(cvtpw, ps)
1742 CALL_FROM_TB0(do_float_cvtpw_ps);
1743 DEBUG_FPU_STATE();
1744 RETURN();
1746 FLOAT_OP(cvts, d)
1748 CALL_FROM_TB0(do_float_cvts_d);
1749 DEBUG_FPU_STATE();
1750 RETURN();
1752 FLOAT_OP(cvts, w)
1754 CALL_FROM_TB0(do_float_cvts_w);
1755 DEBUG_FPU_STATE();
1756 RETURN();
1758 FLOAT_OP(cvts, l)
1760 CALL_FROM_TB0(do_float_cvts_l);
1761 DEBUG_FPU_STATE();
1762 RETURN();
1764 FLOAT_OP(cvts, pl)
1766 CALL_FROM_TB0(do_float_cvts_pl);
1767 DEBUG_FPU_STATE();
1768 RETURN();
1770 FLOAT_OP(cvts, pu)
1772 CALL_FROM_TB0(do_float_cvts_pu);
1773 DEBUG_FPU_STATE();
1774 RETURN();
1776 FLOAT_OP(cvtw, s)
1778 CALL_FROM_TB0(do_float_cvtw_s);
1779 DEBUG_FPU_STATE();
1780 RETURN();
1782 FLOAT_OP(cvtw, d)
1784 CALL_FROM_TB0(do_float_cvtw_d);
1785 DEBUG_FPU_STATE();
1786 RETURN();
1789 FLOAT_OP(pll, ps)
1791 DT2 = ((uint64_t)WT0 << 32) | WT1;
1792 DEBUG_FPU_STATE();
1793 RETURN();
1795 FLOAT_OP(plu, ps)
1797 DT2 = ((uint64_t)WT0 << 32) | WTH1;
1798 DEBUG_FPU_STATE();
1799 RETURN();
1801 FLOAT_OP(pul, ps)
1803 DT2 = ((uint64_t)WTH0 << 32) | WT1;
1804 DEBUG_FPU_STATE();
1805 RETURN();
1807 FLOAT_OP(puu, ps)
1809 DT2 = ((uint64_t)WTH0 << 32) | WTH1;
1810 DEBUG_FPU_STATE();
1811 RETURN();
1814 #define FLOAT_ROUNDOP(op, ttype, stype) \
1815 FLOAT_OP(op ## ttype, stype) \
1817 CALL_FROM_TB0(do_float_ ## op ## ttype ## _ ## stype); \
1818 DEBUG_FPU_STATE(); \
1819 RETURN(); \
1822 FLOAT_ROUNDOP(round, l, d)
1823 FLOAT_ROUNDOP(round, l, s)
1824 FLOAT_ROUNDOP(round, w, d)
1825 FLOAT_ROUNDOP(round, w, s)
1827 FLOAT_ROUNDOP(trunc, l, d)
1828 FLOAT_ROUNDOP(trunc, l, s)
1829 FLOAT_ROUNDOP(trunc, w, d)
1830 FLOAT_ROUNDOP(trunc, w, s)
1832 FLOAT_ROUNDOP(ceil, l, d)
1833 FLOAT_ROUNDOP(ceil, l, s)
1834 FLOAT_ROUNDOP(ceil, w, d)
1835 FLOAT_ROUNDOP(ceil, w, s)
1837 FLOAT_ROUNDOP(floor, l, d)
1838 FLOAT_ROUNDOP(floor, l, s)
1839 FLOAT_ROUNDOP(floor, w, d)
1840 FLOAT_ROUNDOP(floor, w, s)
1841 #undef FLOAR_ROUNDOP
1843 FLOAT_OP(movf, d)
1845 if (!(env->fcr31 & PARAM1))
1846 DT2 = DT0;
1847 DEBUG_FPU_STATE();
1848 RETURN();
1850 FLOAT_OP(movf, s)
1852 if (!(env->fcr31 & PARAM1))
1853 WT2 = WT0;
1854 DEBUG_FPU_STATE();
1855 RETURN();
1857 FLOAT_OP(movf, ps)
1859 if (!(env->fcr31 & PARAM1)) {
1860 WT2 = WT0;
1861 WTH2 = WTH0;
1863 DEBUG_FPU_STATE();
1864 RETURN();
1866 FLOAT_OP(movt, d)
1868 if (env->fcr31 & PARAM1)
1869 DT2 = DT0;
1870 DEBUG_FPU_STATE();
1871 RETURN();
1873 FLOAT_OP(movt, s)
1875 if (env->fcr31 & PARAM1)
1876 WT2 = WT0;
1877 DEBUG_FPU_STATE();
1878 RETURN();
1880 FLOAT_OP(movt, ps)
1882 if (env->fcr31 & PARAM1) {
1883 WT2 = WT0;
1884 WTH2 = WTH0;
1886 DEBUG_FPU_STATE();
1887 RETURN();
1889 FLOAT_OP(movz, d)
1891 if (!T0)
1892 DT2 = DT0;
1893 DEBUG_FPU_STATE();
1894 RETURN();
1896 FLOAT_OP(movz, s)
1898 if (!T0)
1899 WT2 = WT0;
1900 DEBUG_FPU_STATE();
1901 RETURN();
1903 FLOAT_OP(movz, ps)
1905 if (!T0) {
1906 WT2 = WT0;
1907 WTH2 = WTH0;
1909 DEBUG_FPU_STATE();
1910 RETURN();
1912 FLOAT_OP(movn, d)
1914 if (T0)
1915 DT2 = DT0;
1916 DEBUG_FPU_STATE();
1917 RETURN();
1919 FLOAT_OP(movn, s)
1921 if (T0)
1922 WT2 = WT0;
1923 DEBUG_FPU_STATE();
1924 RETURN();
1926 FLOAT_OP(movn, ps)
1928 if (T0) {
1929 WT2 = WT0;
1930 WTH2 = WTH0;
1932 DEBUG_FPU_STATE();
1933 RETURN();
1936 /* operations calling helpers, for s, d and ps */
1937 #define FLOAT_HOP(name) \
1938 FLOAT_OP(name, d) \
1940 CALL_FROM_TB0(do_float_ ## name ## _d); \
1941 DEBUG_FPU_STATE(); \
1942 RETURN(); \
1944 FLOAT_OP(name, s) \
1946 CALL_FROM_TB0(do_float_ ## name ## _s); \
1947 DEBUG_FPU_STATE(); \
1948 RETURN(); \
1950 FLOAT_OP(name, ps) \
1952 CALL_FROM_TB0(do_float_ ## name ## _ps); \
1953 DEBUG_FPU_STATE(); \
1954 RETURN(); \
1956 FLOAT_HOP(add)
1957 FLOAT_HOP(sub)
1958 FLOAT_HOP(mul)
1959 FLOAT_HOP(div)
1960 FLOAT_HOP(recip2)
1961 FLOAT_HOP(rsqrt2)
1962 FLOAT_HOP(rsqrt1)
1963 FLOAT_HOP(recip1)
1964 #undef FLOAT_HOP
1966 /* operations calling helpers, for s and d */
1967 #define FLOAT_HOP(name) \
1968 FLOAT_OP(name, d) \
1970 CALL_FROM_TB0(do_float_ ## name ## _d); \
1971 DEBUG_FPU_STATE(); \
1972 RETURN(); \
1974 FLOAT_OP(name, s) \
1976 CALL_FROM_TB0(do_float_ ## name ## _s); \
1977 DEBUG_FPU_STATE(); \
1978 RETURN(); \
1980 FLOAT_HOP(rsqrt)
1981 FLOAT_HOP(recip)
1982 #undef FLOAT_HOP
1984 /* operations calling helpers, for ps */
1985 #define FLOAT_HOP(name) \
1986 FLOAT_OP(name, ps) \
1988 CALL_FROM_TB0(do_float_ ## name ## _ps); \
1989 DEBUG_FPU_STATE(); \
1990 RETURN(); \
1992 FLOAT_HOP(addr)
1993 FLOAT_HOP(mulr)
1994 #undef FLOAT_HOP
1996 /* ternary operations */
1997 #define FLOAT_TERNOP(name1, name2) \
1998 FLOAT_OP(name1 ## name2, d) \
2000 FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fp_status); \
2001 FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fp_status); \
2002 DEBUG_FPU_STATE(); \
2003 RETURN(); \
2005 FLOAT_OP(name1 ## name2, s) \
2007 FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \
2008 FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \
2009 DEBUG_FPU_STATE(); \
2010 RETURN(); \
2012 FLOAT_OP(name1 ## name2, ps) \
2014 FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \
2015 FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fp_status); \
2016 FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \
2017 FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fp_status); \
2018 DEBUG_FPU_STATE(); \
2019 RETURN(); \
2021 FLOAT_TERNOP(mul, add)
2022 FLOAT_TERNOP(mul, sub)
2023 #undef FLOAT_TERNOP
2025 /* negated ternary operations */
2026 #define FLOAT_NTERNOP(name1, name2) \
2027 FLOAT_OP(n ## name1 ## name2, d) \
2029 FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fp_status); \
2030 FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fp_status); \
2031 FDT2 ^= 1ULL << 63; \
2032 DEBUG_FPU_STATE(); \
2033 RETURN(); \
2035 FLOAT_OP(n ## name1 ## name2, s) \
2037 FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \
2038 FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \
2039 FST2 ^= 1 << 31; \
2040 DEBUG_FPU_STATE(); \
2041 RETURN(); \
2043 FLOAT_OP(n ## name1 ## name2, ps) \
2045 FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \
2046 FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fp_status); \
2047 FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \
2048 FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fp_status); \
2049 FST2 ^= 1 << 31; \
2050 FSTH2 ^= 1 << 31; \
2051 DEBUG_FPU_STATE(); \
2052 RETURN(); \
2054 FLOAT_NTERNOP(mul, add)
2055 FLOAT_NTERNOP(mul, sub)
2056 #undef FLOAT_NTERNOP
2058 /* unary operations, modifying fp status */
2059 #define FLOAT_UNOP(name) \
2060 FLOAT_OP(name, d) \
2062 FDT2 = float64_ ## name(FDT0, &env->fp_status); \
2063 DEBUG_FPU_STATE(); \
2064 RETURN(); \
2066 FLOAT_OP(name, s) \
2068 FST2 = float32_ ## name(FST0, &env->fp_status); \
2069 DEBUG_FPU_STATE(); \
2070 RETURN(); \
2072 FLOAT_UNOP(sqrt)
2073 #undef FLOAT_UNOP
2075 /* unary operations, not modifying fp status */
2076 #define FLOAT_UNOP(name) \
2077 FLOAT_OP(name, d) \
2079 FDT2 = float64_ ## name(FDT0); \
2080 DEBUG_FPU_STATE(); \
2081 RETURN(); \
2083 FLOAT_OP(name, s) \
2085 FST2 = float32_ ## name(FST0); \
2086 DEBUG_FPU_STATE(); \
2087 RETURN(); \
2089 FLOAT_OP(name, ps) \
2091 FST2 = float32_ ## name(FST0); \
2092 FSTH2 = float32_ ## name(FSTH0); \
2093 DEBUG_FPU_STATE(); \
2094 RETURN(); \
2096 FLOAT_UNOP(abs)
2097 FLOAT_UNOP(chs)
2098 #undef FLOAT_UNOP
2100 FLOAT_OP(mov, d)
2102 FDT2 = FDT0;
2103 DEBUG_FPU_STATE();
2104 RETURN();
2106 FLOAT_OP(mov, s)
2108 FST2 = FST0;
2109 DEBUG_FPU_STATE();
2110 RETURN();
2112 FLOAT_OP(mov, ps)
2114 FST2 = FST0;
2115 FSTH2 = FSTH0;
2116 DEBUG_FPU_STATE();
2117 RETURN();
2119 FLOAT_OP(alnv, ps)
2121 switch (T0 & 0x7) {
2122 case 0:
2123 FST2 = FST0;
2124 FSTH2 = FSTH0;
2125 break;
2126 case 4:
2127 #ifdef TARGET_WORDS_BIGENDIAN
2128 FSTH2 = FST0;
2129 FST2 = FSTH1;
2130 #else
2131 FSTH2 = FST1;
2132 FST2 = FSTH0;
2133 #endif
2134 break;
2135 default: /* unpredictable */
2136 break;
2138 DEBUG_FPU_STATE();
2139 RETURN();
2142 #ifdef CONFIG_SOFTFLOAT
2143 #define clear_invalid() do { \
2144 int flags = get_float_exception_flags(&env->fp_status); \
2145 flags &= ~float_flag_invalid; \
2146 set_float_exception_flags(flags, &env->fp_status); \
2147 } while(0)
2148 #else
2149 #define clear_invalid() do { } while(0)
2150 #endif
2152 extern void dump_fpu_s(CPUState *env);
2154 #define CMP_OP(fmt, op) \
2155 void OPPROTO op_cmp ## _ ## fmt ## _ ## op(void) \
2157 CALL_FROM_TB1(do_cmp ## _ ## fmt ## _ ## op, PARAM1); \
2158 DEBUG_FPU_STATE(); \
2159 RETURN(); \
2161 void OPPROTO op_cmpabs ## _ ## fmt ## _ ## op(void) \
2163 CALL_FROM_TB1(do_cmpabs ## _ ## fmt ## _ ## op, PARAM1); \
2164 DEBUG_FPU_STATE(); \
2165 RETURN(); \
2167 #define CMP_OPS(op) \
2168 CMP_OP(d, op) \
2169 CMP_OP(s, op) \
2170 CMP_OP(ps, op)
2172 CMP_OPS(f)
2173 CMP_OPS(un)
2174 CMP_OPS(eq)
2175 CMP_OPS(ueq)
2176 CMP_OPS(olt)
2177 CMP_OPS(ult)
2178 CMP_OPS(ole)
2179 CMP_OPS(ule)
2180 CMP_OPS(sf)
2181 CMP_OPS(ngle)
2182 CMP_OPS(seq)
2183 CMP_OPS(ngl)
2184 CMP_OPS(lt)
2185 CMP_OPS(nge)
2186 CMP_OPS(le)
2187 CMP_OPS(ngt)
2188 #undef CMP_OPS
2189 #undef CMP_OP
2191 void op_bc1f (void)
2193 T0 = !!(~GET_FP_COND(env) & (0x1 << PARAM1));
2194 DEBUG_FPU_STATE();
2195 RETURN();
2197 void op_bc1any2f (void)
2199 T0 = !!(~GET_FP_COND(env) & (0x3 << PARAM1));
2200 DEBUG_FPU_STATE();
2201 RETURN();
2203 void op_bc1any4f (void)
2205 T0 = !!(~GET_FP_COND(env) & (0xf << PARAM1));
2206 DEBUG_FPU_STATE();
2207 RETURN();
2210 void op_bc1t (void)
2212 T0 = !!(GET_FP_COND(env) & (0x1 << PARAM1));
2213 DEBUG_FPU_STATE();
2214 RETURN();
2216 void op_bc1any2t (void)
2218 T0 = !!(GET_FP_COND(env) & (0x3 << PARAM1));
2219 DEBUG_FPU_STATE();
2220 RETURN();
2222 void op_bc1any4t (void)
2224 T0 = !!(GET_FP_COND(env) & (0xf << PARAM1));
2225 DEBUG_FPU_STATE();
2226 RETURN();
2229 void op_tlbwi (void)
2231 CALL_FROM_TB0(env->do_tlbwi);
2232 RETURN();
2235 void op_tlbwr (void)
2237 CALL_FROM_TB0(env->do_tlbwr);
2238 RETURN();
2241 void op_tlbp (void)
2243 CALL_FROM_TB0(env->do_tlbp);
2244 RETURN();
2247 void op_tlbr (void)
2249 CALL_FROM_TB0(env->do_tlbr);
2250 RETURN();
2253 /* Specials */
2254 #if defined (CONFIG_USER_ONLY)
2255 void op_tls_value (void)
2257 T0 = env->tls_value;
2259 #endif
2261 void op_pmon (void)
2263 CALL_FROM_TB1(do_pmon, PARAM1);
2264 RETURN();
2267 void op_di (void)
2269 T0 = env->CP0_Status;
2270 env->CP0_Status = T0 & ~(1 << CP0St_IE);
2271 CALL_FROM_TB1(cpu_mips_update_irq, env);
2272 RETURN();
2275 void op_ei (void)
2277 T0 = env->CP0_Status;
2278 env->CP0_Status = T0 | (1 << CP0St_IE);
2279 CALL_FROM_TB1(cpu_mips_update_irq, env);
2280 RETURN();
2283 void op_trap (void)
2285 if (T0) {
2286 CALL_FROM_TB1(do_raise_exception, EXCP_TRAP);
2288 RETURN();
2291 void op_debug (void)
2293 CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG);
2294 RETURN();
2297 void op_set_lladdr (void)
2299 env->CP0_LLAddr = T2;
2300 RETURN();
2303 void debug_pre_eret (void);
2304 void debug_post_eret (void);
2305 void op_eret (void)
2307 if (loglevel & CPU_LOG_EXEC)
2308 CALL_FROM_TB0(debug_pre_eret);
2309 if (env->CP0_Status & (1 << CP0St_ERL)) {
2310 env->PC = env->CP0_ErrorEPC;
2311 env->CP0_Status &= ~(1 << CP0St_ERL);
2312 } else {
2313 env->PC = env->CP0_EPC;
2314 env->CP0_Status &= ~(1 << CP0St_EXL);
2316 if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
2317 !(env->CP0_Status & (1 << CP0St_ERL)) &&
2318 !(env->hflags & MIPS_HFLAG_DM) &&
2319 (env->CP0_Status & (1 << CP0St_UM)))
2320 env->hflags |= MIPS_HFLAG_UM;
2321 #ifdef TARGET_MIPS64
2322 if (!(env->CP0_Config0 & (0x3 << CP0C0_AT)) ||
2323 ((env->hflags & MIPS_HFLAG_UM) &&
2324 !(env->CP0_Status & (1 << CP0St_PX)) &&
2325 !(env->CP0_Status & (1 << CP0St_UX))))
2326 env->hflags &= ~MIPS_HFLAG_64;
2327 #endif
2328 if (loglevel & CPU_LOG_EXEC)
2329 CALL_FROM_TB0(debug_post_eret);
2330 env->CP0_LLAddr = 1;
2331 RETURN();
2334 void op_deret (void)
2336 if (loglevel & CPU_LOG_EXEC)
2337 CALL_FROM_TB0(debug_pre_eret);
2338 env->PC = env->CP0_DEPC;
2339 env->hflags |= MIPS_HFLAG_DM;
2340 if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
2341 !(env->CP0_Status & (1 << CP0St_ERL)) &&
2342 !(env->hflags & MIPS_HFLAG_DM) &&
2343 (env->CP0_Status & (1 << CP0St_UM)))
2344 env->hflags |= MIPS_HFLAG_UM;
2345 #ifdef TARGET_MIPS64
2346 if (!(env->CP0_Config0 & (0x3 << CP0C0_AT)) ||
2347 ((env->hflags & MIPS_HFLAG_UM) &&
2348 !(env->CP0_Status & (1 << CP0St_PX)) &&
2349 !(env->CP0_Status & (1 << CP0St_UX))))
2350 env->hflags &= ~MIPS_HFLAG_64;
2351 #endif
2352 if (loglevel & CPU_LOG_EXEC)
2353 CALL_FROM_TB0(debug_post_eret);
2354 env->CP0_LLAddr = 1;
2355 RETURN();
2358 void op_rdhwr_cpunum(void)
2360 if (!(env->hflags & MIPS_HFLAG_UM) ||
2361 (env->CP0_HWREna & (1 << 0)) ||
2362 (env->CP0_Status & (1 << CP0St_CU0)))
2363 T0 = env->CP0_EBase & 0x3ff;
2364 else
2365 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
2366 RETURN();
2369 void op_rdhwr_synci_step(void)
2371 if (!(env->hflags & MIPS_HFLAG_UM) ||
2372 (env->CP0_HWREna & (1 << 1)) ||
2373 (env->CP0_Status & (1 << CP0St_CU0)))
2374 T0 = env->SYNCI_Step;
2375 else
2376 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
2377 RETURN();
2380 void op_rdhwr_cc(void)
2382 if (!(env->hflags & MIPS_HFLAG_UM) ||
2383 (env->CP0_HWREna & (1 << 2)) ||
2384 (env->CP0_Status & (1 << CP0St_CU0)))
2385 T0 = env->CP0_Count;
2386 else
2387 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
2388 RETURN();
2391 void op_rdhwr_ccres(void)
2393 if (!(env->hflags & MIPS_HFLAG_UM) ||
2394 (env->CP0_HWREna & (1 << 3)) ||
2395 (env->CP0_Status & (1 << CP0St_CU0)))
2396 T0 = env->CCRes;
2397 else
2398 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
2399 RETURN();
2402 void op_save_state (void)
2404 env->hflags = PARAM1;
2405 RETURN();
2408 void op_save_pc (void)
2410 env->PC = PARAM1;
2411 RETURN();
2414 #ifdef TARGET_MIPS64
2415 void op_save_pc64 (void)
2417 env->PC = ((uint64_t)PARAM1 << 32) | (uint32_t)PARAM2;
2418 RETURN();
2420 #endif
2422 void op_interrupt_restart (void)
2424 if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
2425 !(env->CP0_Status & (1 << CP0St_ERL)) &&
2426 !(env->hflags & MIPS_HFLAG_DM) &&
2427 (env->CP0_Status & (1 << CP0St_IE)) &&
2428 (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask)) {
2429 env->CP0_Cause &= ~(0x1f << CP0Ca_EC);
2430 CALL_FROM_TB1(do_raise_exception, EXCP_EXT_INTERRUPT);
2432 RETURN();
2435 void op_raise_exception (void)
2437 CALL_FROM_TB1(do_raise_exception, PARAM1);
2438 RETURN();
2441 void op_raise_exception_err (void)
2443 CALL_FROM_TB2(do_raise_exception_err, PARAM1, PARAM2);
2444 RETURN();
2447 void op_exit_tb (void)
2449 EXIT_TB();
2450 RETURN();
2453 void op_wait (void)
2455 env->halted = 1;
2456 CALL_FROM_TB1(do_raise_exception, EXCP_HLT);
2457 RETURN();
2460 /* Bitfield operations. */
2461 void op_ext(void)
2463 unsigned int pos = PARAM1;
2464 unsigned int size = PARAM2;
2466 T0 = ((uint32_t)T1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0);
2467 RETURN();
2470 void op_ins(void)
2472 unsigned int pos = PARAM1;
2473 unsigned int size = PARAM2;
2474 target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos;
2476 T0 = (T0 & ~mask) | (((uint32_t)T1 << pos) & mask);
2477 RETURN();
2480 void op_wsbh(void)
2482 T0 = ((T1 << 8) & ~0x00FF00FF) | ((T1 >> 8) & 0x00FF00FF);
2483 RETURN();
2486 #ifdef TARGET_MIPS64
2487 void op_dext(void)
2489 unsigned int pos = PARAM1;
2490 unsigned int size = PARAM2;
2492 T0 = (T1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0);
2493 RETURN();
2496 void op_dins(void)
2498 unsigned int pos = PARAM1;
2499 unsigned int size = PARAM2;
2500 target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos;
2502 T0 = (T0 & ~mask) | ((T1 << pos) & mask);
2503 RETURN();
2506 void op_dsbh(void)
2508 T0 = ((T1 << 8) & ~0x00FF00FF00FF00FFULL) | ((T1 >> 8) & 0x00FF00FF00FF00FFULL);
2509 RETURN();
2512 void op_dshd(void)
2514 T0 = ((T1 << 16) & ~0x0000FFFF0000FFFFULL) | ((T1 >> 16) & 0x0000FFFF0000FFFFULL);
2515 RETURN();
2517 #endif
2519 void op_seb(void)
2521 T0 = ((T1 & 0xFF) ^ 0x80) - 0x80;
2522 RETURN();
2525 void op_seh(void)
2527 T0 = ((T1 & 0xFFFF) ^ 0x8000) - 0x8000;
2528 RETURN();