Fix tap device counting.
[qemu/mini2440.git] / target-mips / op.c
blob8f67041ca2cb76ca2fa911e35acaa03fff1add1d
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->CP0_Status & (1 << CP0St_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 /* Conditional branch */
980 void op_set_bcond (void)
982 T2 = T0;
983 RETURN();
986 void op_save_bcond (void)
988 env->bcond = T2;
989 RETURN();
992 void op_restore_bcond (void)
994 T2 = env->bcond;
995 RETURN();
998 void op_jnz_T2 (void)
1000 if (T2)
1001 GOTO_LABEL_PARAM(1);
1002 RETURN();
1005 /* CP0 functions */
1006 void op_mfc0_index (void)
1008 T0 = env->CP0_Index;
1009 RETURN();
1012 void op_mfc0_random (void)
1014 CALL_FROM_TB0(do_mfc0_random);
1015 RETURN();
1018 void op_mfc0_entrylo0 (void)
1020 T0 = (int32_t)env->CP0_EntryLo0;
1021 RETURN();
1024 void op_mfc0_entrylo1 (void)
1026 T0 = (int32_t)env->CP0_EntryLo1;
1027 RETURN();
1030 void op_mfc0_context (void)
1032 T0 = (int32_t)env->CP0_Context;
1033 RETURN();
1036 void op_mfc0_pagemask (void)
1038 T0 = env->CP0_PageMask;
1039 RETURN();
1042 void op_mfc0_pagegrain (void)
1044 T0 = env->CP0_PageGrain;
1045 RETURN();
1048 void op_mfc0_wired (void)
1050 T0 = env->CP0_Wired;
1051 RETURN();
1054 void op_mfc0_hwrena (void)
1056 T0 = env->CP0_HWREna;
1057 RETURN();
1060 void op_mfc0_badvaddr (void)
1062 T0 = (int32_t)env->CP0_BadVAddr;
1063 RETURN();
1066 void op_mfc0_count (void)
1068 CALL_FROM_TB0(do_mfc0_count);
1069 RETURN();
1072 void op_mfc0_entryhi (void)
1074 T0 = (int32_t)env->CP0_EntryHi;
1075 RETURN();
1078 void op_mfc0_compare (void)
1080 T0 = env->CP0_Compare;
1081 RETURN();
1084 void op_mfc0_status (void)
1086 T0 = env->CP0_Status;
1087 RETURN();
1090 void op_mfc0_intctl (void)
1092 T0 = env->CP0_IntCtl;
1093 RETURN();
1096 void op_mfc0_srsctl (void)
1098 T0 = env->CP0_SRSCtl;
1099 RETURN();
1102 void op_mfc0_srsmap (void)
1104 T0 = env->CP0_SRSMap;
1105 RETURN();
1108 void op_mfc0_cause (void)
1110 T0 = env->CP0_Cause;
1111 RETURN();
1114 void op_mfc0_epc (void)
1116 T0 = (int32_t)env->CP0_EPC;
1117 RETURN();
1120 void op_mfc0_prid (void)
1122 T0 = env->CP0_PRid;
1123 RETURN();
1126 void op_mfc0_ebase (void)
1128 T0 = env->CP0_EBase;
1129 RETURN();
1132 void op_mfc0_config0 (void)
1134 T0 = env->CP0_Config0;
1135 RETURN();
1138 void op_mfc0_config1 (void)
1140 T0 = env->CP0_Config1;
1141 RETURN();
1144 void op_mfc0_config2 (void)
1146 T0 = env->CP0_Config2;
1147 RETURN();
1150 void op_mfc0_config3 (void)
1152 T0 = env->CP0_Config3;
1153 RETURN();
1156 void op_mfc0_config6 (void)
1158 T0 = env->CP0_Config6;
1159 RETURN();
1162 void op_mfc0_config7 (void)
1164 T0 = env->CP0_Config7;
1165 RETURN();
1168 void op_mfc0_lladdr (void)
1170 T0 = (int32_t)env->CP0_LLAddr >> 4;
1171 RETURN();
1174 void op_mfc0_watchlo (void)
1176 T0 = (int32_t)env->CP0_WatchLo[PARAM1];
1177 RETURN();
1180 void op_mfc0_watchhi (void)
1182 T0 = env->CP0_WatchHi[PARAM1];
1183 RETURN();
1186 void op_mfc0_xcontext (void)
1188 T0 = (int32_t)env->CP0_XContext;
1189 RETURN();
1192 void op_mfc0_framemask (void)
1194 T0 = env->CP0_Framemask;
1195 RETURN();
1198 void op_mfc0_debug (void)
1200 T0 = env->CP0_Debug;
1201 if (env->hflags & MIPS_HFLAG_DM)
1202 T0 |= 1 << CP0DB_DM;
1203 RETURN();
1206 void op_mfc0_depc (void)
1208 T0 = (int32_t)env->CP0_DEPC;
1209 RETURN();
1212 void op_mfc0_performance0 (void)
1214 T0 = env->CP0_Performance0;
1215 RETURN();
1218 void op_mfc0_taglo (void)
1220 T0 = env->CP0_TagLo;
1221 RETURN();
1224 void op_mfc0_datalo (void)
1226 T0 = env->CP0_DataLo;
1227 RETURN();
1230 void op_mfc0_taghi (void)
1232 T0 = env->CP0_TagHi;
1233 RETURN();
1236 void op_mfc0_datahi (void)
1238 T0 = env->CP0_DataHi;
1239 RETURN();
1242 void op_mfc0_errorepc (void)
1244 T0 = (int32_t)env->CP0_ErrorEPC;
1245 RETURN();
1248 void op_mfc0_desave (void)
1250 T0 = env->CP0_DESAVE;
1251 RETURN();
1254 void op_mtc0_index (void)
1256 env->CP0_Index = (env->CP0_Index & 0x80000000) | (T0 % env->nb_tlb);
1257 RETURN();
1260 void op_mtc0_entrylo0 (void)
1262 /* Large physaddr not implemented */
1263 /* 1k pages not implemented */
1264 env->CP0_EntryLo0 = T0 & 0x3FFFFFFF;
1265 RETURN();
1268 void op_mtc0_entrylo1 (void)
1270 /* Large physaddr not implemented */
1271 /* 1k pages not implemented */
1272 env->CP0_EntryLo1 = T0 & 0x3FFFFFFF;
1273 RETURN();
1276 void op_mtc0_context (void)
1278 env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (T0 & ~0x007FFFFF);
1279 RETURN();
1282 void op_mtc0_pagemask (void)
1284 /* 1k pages not implemented */
1285 env->CP0_PageMask = T0 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
1286 RETURN();
1289 void op_mtc0_pagegrain (void)
1291 /* SmartMIPS not implemented */
1292 /* Large physaddr not implemented */
1293 /* 1k pages not implemented */
1294 env->CP0_PageGrain = 0;
1295 RETURN();
1298 void op_mtc0_wired (void)
1300 env->CP0_Wired = T0 % env->nb_tlb;
1301 RETURN();
1304 void op_mtc0_hwrena (void)
1306 env->CP0_HWREna = T0 & 0x0000000F;
1307 RETURN();
1310 void op_mtc0_count (void)
1312 CALL_FROM_TB2(cpu_mips_store_count, env, T0);
1313 RETURN();
1316 void op_mtc0_entryhi (void)
1318 target_ulong old, val;
1320 /* 1k pages not implemented */
1321 val = T0 & ((TARGET_PAGE_MASK << 1) | 0xFF);
1322 #ifdef TARGET_MIPS64
1323 val = T0 & 0xC00000FFFFFFFFFFULL;
1324 #endif
1325 old = env->CP0_EntryHi;
1326 env->CP0_EntryHi = val;
1327 /* If the ASID changes, flush qemu's TLB. */
1328 if ((old & 0xFF) != (val & 0xFF))
1329 CALL_FROM_TB2(cpu_mips_tlb_flush, env, 1);
1330 RETURN();
1333 void op_mtc0_compare (void)
1335 CALL_FROM_TB2(cpu_mips_store_compare, env, T0);
1336 RETURN();
1339 void op_mtc0_status (void)
1341 uint32_t val, old;
1342 uint32_t mask = env->Status_rw_bitmask;
1344 /* No reverse endianness, no MDMX/DSP, no 64bit ops
1345 implemented. */
1346 val = T0 & mask;
1347 old = env->CP0_Status;
1348 if (!(val & (1 << CP0St_EXL)) &&
1349 !(val & (1 << CP0St_ERL)) &&
1350 !(env->hflags & MIPS_HFLAG_DM) &&
1351 (val & (1 << CP0St_UM)))
1352 env->hflags |= MIPS_HFLAG_UM;
1353 env->CP0_Status = (env->CP0_Status & ~mask) | val;
1354 if (loglevel & CPU_LOG_EXEC)
1355 CALL_FROM_TB2(do_mtc0_status_debug, old, val);
1356 CALL_FROM_TB1(cpu_mips_update_irq, env);
1357 RETURN();
1360 void op_mtc0_intctl (void)
1362 /* vectored interrupts not implemented, timer on int 7,
1363 no performance counters. */
1364 env->CP0_IntCtl |= T0 & 0x000002e0;
1365 RETURN();
1368 void op_mtc0_srsctl (void)
1370 /* shadow registers not implemented */
1371 env->CP0_SRSCtl = 0;
1372 RETURN();
1375 void op_mtc0_srsmap (void)
1377 /* shadow registers not implemented */
1378 env->CP0_SRSMap = 0;
1379 RETURN();
1382 void op_mtc0_cause (void)
1384 uint32_t mask = 0x00C00300;
1386 if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) == (1 << CP0C0_AR))
1387 mask |= 1 << CP0Ca_DC;
1389 env->CP0_Cause = (env->CP0_Cause & ~mask) | (T0 & mask);
1391 /* Handle the software interrupt as an hardware one, as they
1392 are very similar */
1393 if (T0 & CP0Ca_IP_mask) {
1394 CALL_FROM_TB1(cpu_mips_update_irq, env);
1396 RETURN();
1399 void op_mtc0_epc (void)
1401 env->CP0_EPC = T0;
1402 RETURN();
1405 void op_mtc0_ebase (void)
1407 /* vectored interrupts not implemented */
1408 /* Multi-CPU not implemented */
1409 env->CP0_EBase = 0x80000000 | (T0 & 0x3FFFF000);
1410 RETURN();
1413 void op_mtc0_config0 (void)
1415 env->CP0_Config0 = (env->CP0_Config0 & 0x81FFFFF8) | (T0 & 0x00000001);
1416 RETURN();
1419 void op_mtc0_config2 (void)
1421 /* tertiary/secondary caches not implemented */
1422 env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
1423 RETURN();
1426 void op_mtc0_watchlo (void)
1428 /* Watch exceptions for instructions, data loads, data stores
1429 not implemented. */
1430 env->CP0_WatchLo[PARAM1] = (T0 & ~0x7);
1431 RETURN();
1434 void op_mtc0_watchhi (void)
1436 env->CP0_WatchHi[PARAM1] = (T0 & 0x40FF0FF8);
1437 env->CP0_WatchHi[PARAM1] &= ~(env->CP0_WatchHi[PARAM1] & T0 & 0x7);
1438 RETURN();
1441 void op_mtc0_framemask (void)
1443 env->CP0_Framemask = T0; /* XXX */
1444 RETURN();
1447 void op_mtc0_debug (void)
1449 env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120);
1450 if (T0 & (1 << CP0DB_DM))
1451 env->hflags |= MIPS_HFLAG_DM;
1452 else
1453 env->hflags &= ~MIPS_HFLAG_DM;
1454 RETURN();
1457 void op_mtc0_depc (void)
1459 env->CP0_DEPC = T0;
1460 RETURN();
1463 void op_mtc0_performance0 (void)
1465 env->CP0_Performance0 = T0; /* XXX */
1466 RETURN();
1469 void op_mtc0_taglo (void)
1471 env->CP0_TagLo = T0 & 0xFFFFFCF6;
1472 RETURN();
1475 void op_mtc0_datalo (void)
1477 env->CP0_DataLo = T0; /* XXX */
1478 RETURN();
1481 void op_mtc0_taghi (void)
1483 env->CP0_TagHi = T0; /* XXX */
1484 RETURN();
1487 void op_mtc0_datahi (void)
1489 env->CP0_DataHi = T0; /* XXX */
1490 RETURN();
1493 void op_mtc0_errorepc (void)
1495 env->CP0_ErrorEPC = T0;
1496 RETURN();
1499 void op_mtc0_desave (void)
1501 env->CP0_DESAVE = T0;
1502 RETURN();
1505 #ifdef TARGET_MIPS64
1506 void op_mtc0_xcontext (void)
1508 env->CP0_XContext = (env->CP0_XContext & 0x1ffffffffULL) | (T0 & ~0x1ffffffffULL);
1509 RETURN();
1512 void op_dmfc0_entrylo0 (void)
1514 T0 = env->CP0_EntryLo0;
1515 RETURN();
1518 void op_dmfc0_entrylo1 (void)
1520 T0 = env->CP0_EntryLo1;
1521 RETURN();
1524 void op_dmfc0_context (void)
1526 T0 = env->CP0_Context;
1527 RETURN();
1530 void op_dmfc0_badvaddr (void)
1532 T0 = env->CP0_BadVAddr;
1533 RETURN();
1536 void op_dmfc0_entryhi (void)
1538 T0 = env->CP0_EntryHi;
1539 RETURN();
1542 void op_dmfc0_epc (void)
1544 T0 = env->CP0_EPC;
1545 RETURN();
1548 void op_dmfc0_lladdr (void)
1550 T0 = env->CP0_LLAddr >> 4;
1551 RETURN();
1554 void op_dmfc0_watchlo (void)
1556 T0 = env->CP0_WatchLo[PARAM1];
1557 RETURN();
1560 void op_dmfc0_xcontext (void)
1562 T0 = env->CP0_XContext;
1563 RETURN();
1566 void op_dmfc0_depc (void)
1568 T0 = env->CP0_DEPC;
1569 RETURN();
1572 void op_dmfc0_errorepc (void)
1574 T0 = env->CP0_ErrorEPC;
1575 RETURN();
1577 #endif /* TARGET_MIPS64 */
1579 /* CP1 functions */
1580 #if 0
1581 # define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env)
1582 #else
1583 # define DEBUG_FPU_STATE() do { } while(0)
1584 #endif
1586 void op_cp0_enabled(void)
1588 if (!(env->CP0_Status & (1 << CP0St_CU0)) &&
1589 (env->hflags & MIPS_HFLAG_UM)) {
1590 CALL_FROM_TB2(do_raise_exception_err, EXCP_CpU, 0);
1592 RETURN();
1595 void op_cp1_enabled(void)
1597 if (!(env->CP0_Status & (1 << CP0St_CU1))) {
1598 CALL_FROM_TB2(do_raise_exception_err, EXCP_CpU, 1);
1600 RETURN();
1603 void op_cp1_64bitmode(void)
1605 if (!(env->CP0_Status & (1 << CP0St_FR))) {
1606 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
1608 RETURN();
1612 * Verify if floating point register is valid; an operation is not defined
1613 * if bit 0 of any register specification is set and the FR bit in the
1614 * Status register equals zero, since the register numbers specify an
1615 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1616 * in the Status register equals one, both even and odd register numbers
1617 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1619 * Multiple 64 bit wide registers can be checked by calling
1620 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1622 void op_cp1_registers(void)
1624 if (!(env->CP0_Status & (1 << CP0St_FR)) && (PARAM1 & 1)) {
1625 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
1627 RETURN();
1630 void op_cfc1 (void)
1632 switch (T1) {
1633 case 0:
1634 T0 = (int32_t)env->fcr0;
1635 break;
1636 case 25:
1637 T0 = ((env->fcr31 >> 24) & 0xfe) | ((env->fcr31 >> 23) & 0x1);
1638 break;
1639 case 26:
1640 T0 = env->fcr31 & 0x0003f07c;
1641 break;
1642 case 28:
1643 T0 = (env->fcr31 & 0x00000f83) | ((env->fcr31 >> 22) & 0x4);
1644 break;
1645 default:
1646 T0 = (int32_t)env->fcr31;
1647 break;
1649 DEBUG_FPU_STATE();
1650 RETURN();
1653 void op_ctc1 (void)
1655 CALL_FROM_TB0(do_ctc1);
1656 DEBUG_FPU_STATE();
1657 RETURN();
1660 void op_mfc1 (void)
1662 T0 = WT0;
1663 DEBUG_FPU_STATE();
1664 RETURN();
1667 void op_mtc1 (void)
1669 WT0 = T0;
1670 DEBUG_FPU_STATE();
1671 RETURN();
1674 void op_dmfc1 (void)
1676 T0 = DT0;
1677 DEBUG_FPU_STATE();
1678 RETURN();
1681 void op_dmtc1 (void)
1683 DT0 = T0;
1684 DEBUG_FPU_STATE();
1685 RETURN();
1688 void op_mfhc1 (void)
1690 T0 = WTH0;
1691 DEBUG_FPU_STATE();
1692 RETURN();
1695 void op_mthc1 (void)
1697 WTH0 = T0;
1698 DEBUG_FPU_STATE();
1699 RETURN();
1702 /* Float support.
1703 Single precition routines have a "s" suffix, double precision a
1704 "d" suffix, 32bit integer "w", 64bit integer "l", paired singe "ps",
1705 paired single lowwer "pl", paired single upper "pu". */
1707 #define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void)
1709 FLOAT_OP(cvtd, s)
1711 CALL_FROM_TB0(do_float_cvtd_s);
1712 DEBUG_FPU_STATE();
1713 RETURN();
1715 FLOAT_OP(cvtd, w)
1717 CALL_FROM_TB0(do_float_cvtd_w);
1718 DEBUG_FPU_STATE();
1719 RETURN();
1721 FLOAT_OP(cvtd, l)
1723 CALL_FROM_TB0(do_float_cvtd_l);
1724 DEBUG_FPU_STATE();
1725 RETURN();
1727 FLOAT_OP(cvtl, d)
1729 CALL_FROM_TB0(do_float_cvtl_d);
1730 DEBUG_FPU_STATE();
1731 RETURN();
1733 FLOAT_OP(cvtl, s)
1735 CALL_FROM_TB0(do_float_cvtl_s);
1736 DEBUG_FPU_STATE();
1737 RETURN();
1739 FLOAT_OP(cvtps, s)
1741 WT2 = WT0;
1742 WTH2 = WT1;
1743 DEBUG_FPU_STATE();
1744 RETURN();
1746 FLOAT_OP(cvtps, pw)
1748 CALL_FROM_TB0(do_float_cvtps_pw);
1749 DEBUG_FPU_STATE();
1750 RETURN();
1752 FLOAT_OP(cvtpw, ps)
1754 CALL_FROM_TB0(do_float_cvtpw_ps);
1755 DEBUG_FPU_STATE();
1756 RETURN();
1758 FLOAT_OP(cvts, d)
1760 CALL_FROM_TB0(do_float_cvts_d);
1761 DEBUG_FPU_STATE();
1762 RETURN();
1764 FLOAT_OP(cvts, w)
1766 CALL_FROM_TB0(do_float_cvts_w);
1767 DEBUG_FPU_STATE();
1768 RETURN();
1770 FLOAT_OP(cvts, l)
1772 CALL_FROM_TB0(do_float_cvts_l);
1773 DEBUG_FPU_STATE();
1774 RETURN();
1776 FLOAT_OP(cvts, pl)
1778 CALL_FROM_TB0(do_float_cvts_pl);
1779 DEBUG_FPU_STATE();
1780 RETURN();
1782 FLOAT_OP(cvts, pu)
1784 CALL_FROM_TB0(do_float_cvts_pu);
1785 DEBUG_FPU_STATE();
1786 RETURN();
1788 FLOAT_OP(cvtw, s)
1790 CALL_FROM_TB0(do_float_cvtw_s);
1791 DEBUG_FPU_STATE();
1792 RETURN();
1794 FLOAT_OP(cvtw, d)
1796 CALL_FROM_TB0(do_float_cvtw_d);
1797 DEBUG_FPU_STATE();
1798 RETURN();
1801 FLOAT_OP(pll, ps)
1803 DT2 = ((uint64_t)WT0 << 32) | WT1;
1804 DEBUG_FPU_STATE();
1805 RETURN();
1807 FLOAT_OP(plu, ps)
1809 DT2 = ((uint64_t)WT0 << 32) | WTH1;
1810 DEBUG_FPU_STATE();
1811 RETURN();
1813 FLOAT_OP(pul, ps)
1815 DT2 = ((uint64_t)WTH0 << 32) | WT1;
1816 DEBUG_FPU_STATE();
1817 RETURN();
1819 FLOAT_OP(puu, ps)
1821 DT2 = ((uint64_t)WTH0 << 32) | WTH1;
1822 DEBUG_FPU_STATE();
1823 RETURN();
1826 #define FLOAT_ROUNDOP(op, ttype, stype) \
1827 FLOAT_OP(op ## ttype, stype) \
1829 CALL_FROM_TB0(do_float_ ## op ## ttype ## _ ## stype); \
1830 DEBUG_FPU_STATE(); \
1831 RETURN(); \
1834 FLOAT_ROUNDOP(round, l, d)
1835 FLOAT_ROUNDOP(round, l, s)
1836 FLOAT_ROUNDOP(round, w, d)
1837 FLOAT_ROUNDOP(round, w, s)
1839 FLOAT_ROUNDOP(trunc, l, d)
1840 FLOAT_ROUNDOP(trunc, l, s)
1841 FLOAT_ROUNDOP(trunc, w, d)
1842 FLOAT_ROUNDOP(trunc, w, s)
1844 FLOAT_ROUNDOP(ceil, l, d)
1845 FLOAT_ROUNDOP(ceil, l, s)
1846 FLOAT_ROUNDOP(ceil, w, d)
1847 FLOAT_ROUNDOP(ceil, w, s)
1849 FLOAT_ROUNDOP(floor, l, d)
1850 FLOAT_ROUNDOP(floor, l, s)
1851 FLOAT_ROUNDOP(floor, w, d)
1852 FLOAT_ROUNDOP(floor, w, s)
1853 #undef FLOAR_ROUNDOP
1855 FLOAT_OP(movf, d)
1857 if (!(env->fcr31 & PARAM1))
1858 DT2 = DT0;
1859 DEBUG_FPU_STATE();
1860 RETURN();
1862 FLOAT_OP(movf, s)
1864 if (!(env->fcr31 & PARAM1))
1865 WT2 = WT0;
1866 DEBUG_FPU_STATE();
1867 RETURN();
1869 FLOAT_OP(movf, ps)
1871 if (!(env->fcr31 & PARAM1)) {
1872 WT2 = WT0;
1873 WTH2 = WTH0;
1875 DEBUG_FPU_STATE();
1876 RETURN();
1878 FLOAT_OP(movt, d)
1880 if (env->fcr31 & PARAM1)
1881 DT2 = DT0;
1882 DEBUG_FPU_STATE();
1883 RETURN();
1885 FLOAT_OP(movt, s)
1887 if (env->fcr31 & PARAM1)
1888 WT2 = WT0;
1889 DEBUG_FPU_STATE();
1890 RETURN();
1892 FLOAT_OP(movt, ps)
1894 if (env->fcr31 & PARAM1) {
1895 WT2 = WT0;
1896 WTH2 = WTH0;
1898 DEBUG_FPU_STATE();
1899 RETURN();
1901 FLOAT_OP(movz, d)
1903 if (!T0)
1904 DT2 = DT0;
1905 DEBUG_FPU_STATE();
1906 RETURN();
1908 FLOAT_OP(movz, s)
1910 if (!T0)
1911 WT2 = WT0;
1912 DEBUG_FPU_STATE();
1913 RETURN();
1915 FLOAT_OP(movz, ps)
1917 if (!T0) {
1918 WT2 = WT0;
1919 WTH2 = WTH0;
1921 DEBUG_FPU_STATE();
1922 RETURN();
1924 FLOAT_OP(movn, d)
1926 if (T0)
1927 DT2 = DT0;
1928 DEBUG_FPU_STATE();
1929 RETURN();
1931 FLOAT_OP(movn, s)
1933 if (T0)
1934 WT2 = WT0;
1935 DEBUG_FPU_STATE();
1936 RETURN();
1938 FLOAT_OP(movn, ps)
1940 if (T0) {
1941 WT2 = WT0;
1942 WTH2 = WTH0;
1944 DEBUG_FPU_STATE();
1945 RETURN();
1948 /* operations calling helpers, for s, d and ps */
1949 #define FLOAT_HOP(name) \
1950 FLOAT_OP(name, d) \
1952 CALL_FROM_TB0(do_float_ ## name ## _d); \
1953 DEBUG_FPU_STATE(); \
1954 RETURN(); \
1956 FLOAT_OP(name, s) \
1958 CALL_FROM_TB0(do_float_ ## name ## _s); \
1959 DEBUG_FPU_STATE(); \
1960 RETURN(); \
1962 FLOAT_OP(name, ps) \
1964 CALL_FROM_TB0(do_float_ ## name ## _ps); \
1965 DEBUG_FPU_STATE(); \
1966 RETURN(); \
1968 FLOAT_HOP(add)
1969 FLOAT_HOP(sub)
1970 FLOAT_HOP(mul)
1971 FLOAT_HOP(div)
1972 FLOAT_HOP(recip2)
1973 FLOAT_HOP(rsqrt2)
1974 FLOAT_HOP(rsqrt1)
1975 FLOAT_HOP(recip1)
1976 #undef FLOAT_HOP
1978 /* operations calling helpers, for s and d */
1979 #define FLOAT_HOP(name) \
1980 FLOAT_OP(name, d) \
1982 CALL_FROM_TB0(do_float_ ## name ## _d); \
1983 DEBUG_FPU_STATE(); \
1984 RETURN(); \
1986 FLOAT_OP(name, s) \
1988 CALL_FROM_TB0(do_float_ ## name ## _s); \
1989 DEBUG_FPU_STATE(); \
1990 RETURN(); \
1992 FLOAT_HOP(rsqrt)
1993 FLOAT_HOP(recip)
1994 #undef FLOAT_HOP
1996 /* operations calling helpers, for ps */
1997 #define FLOAT_HOP(name) \
1998 FLOAT_OP(name, ps) \
2000 CALL_FROM_TB0(do_float_ ## name ## _ps); \
2001 DEBUG_FPU_STATE(); \
2002 RETURN(); \
2004 FLOAT_HOP(addr)
2005 FLOAT_HOP(mulr)
2006 #undef FLOAT_HOP
2008 /* ternary operations */
2009 #define FLOAT_TERNOP(name1, name2) \
2010 FLOAT_OP(name1 ## name2, d) \
2012 FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fp_status); \
2013 FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fp_status); \
2014 DEBUG_FPU_STATE(); \
2015 RETURN(); \
2017 FLOAT_OP(name1 ## name2, s) \
2019 FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \
2020 FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \
2021 DEBUG_FPU_STATE(); \
2022 RETURN(); \
2024 FLOAT_OP(name1 ## name2, ps) \
2026 FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \
2027 FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fp_status); \
2028 FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \
2029 FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fp_status); \
2030 DEBUG_FPU_STATE(); \
2031 RETURN(); \
2033 FLOAT_TERNOP(mul, add)
2034 FLOAT_TERNOP(mul, sub)
2035 #undef FLOAT_TERNOP
2037 /* negated ternary operations */
2038 #define FLOAT_NTERNOP(name1, name2) \
2039 FLOAT_OP(n ## name1 ## name2, d) \
2041 FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fp_status); \
2042 FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fp_status); \
2043 FDT2 ^= 1ULL << 63; \
2044 DEBUG_FPU_STATE(); \
2045 RETURN(); \
2047 FLOAT_OP(n ## name1 ## name2, s) \
2049 FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \
2050 FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \
2051 FST2 ^= 1 << 31; \
2052 DEBUG_FPU_STATE(); \
2053 RETURN(); \
2055 FLOAT_OP(n ## name1 ## name2, ps) \
2057 FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \
2058 FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fp_status); \
2059 FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \
2060 FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fp_status); \
2061 FST2 ^= 1 << 31; \
2062 FSTH2 ^= 1 << 31; \
2063 DEBUG_FPU_STATE(); \
2064 RETURN(); \
2066 FLOAT_NTERNOP(mul, add)
2067 FLOAT_NTERNOP(mul, sub)
2068 #undef FLOAT_NTERNOP
2070 /* unary operations, modifying fp status */
2071 #define FLOAT_UNOP(name) \
2072 FLOAT_OP(name, d) \
2074 FDT2 = float64_ ## name(FDT0, &env->fp_status); \
2075 DEBUG_FPU_STATE(); \
2076 RETURN(); \
2078 FLOAT_OP(name, s) \
2080 FST2 = float32_ ## name(FST0, &env->fp_status); \
2081 DEBUG_FPU_STATE(); \
2082 RETURN(); \
2084 FLOAT_UNOP(sqrt)
2085 #undef FLOAT_UNOP
2087 /* unary operations, not modifying fp status */
2088 #define FLOAT_UNOP(name) \
2089 FLOAT_OP(name, d) \
2091 FDT2 = float64_ ## name(FDT0); \
2092 DEBUG_FPU_STATE(); \
2093 RETURN(); \
2095 FLOAT_OP(name, s) \
2097 FST2 = float32_ ## name(FST0); \
2098 DEBUG_FPU_STATE(); \
2099 RETURN(); \
2101 FLOAT_OP(name, ps) \
2103 FST2 = float32_ ## name(FST0); \
2104 FSTH2 = float32_ ## name(FSTH0); \
2105 DEBUG_FPU_STATE(); \
2106 RETURN(); \
2108 FLOAT_UNOP(abs)
2109 FLOAT_UNOP(chs)
2110 #undef FLOAT_UNOP
2112 FLOAT_OP(mov, d)
2114 FDT2 = FDT0;
2115 DEBUG_FPU_STATE();
2116 RETURN();
2118 FLOAT_OP(mov, s)
2120 FST2 = FST0;
2121 DEBUG_FPU_STATE();
2122 RETURN();
2124 FLOAT_OP(mov, ps)
2126 FST2 = FST0;
2127 FSTH2 = FSTH0;
2128 DEBUG_FPU_STATE();
2129 RETURN();
2131 FLOAT_OP(alnv, ps)
2133 switch (T0 & 0x7) {
2134 case 0:
2135 FST2 = FST0;
2136 FSTH2 = FSTH0;
2137 break;
2138 case 4:
2139 #ifdef TARGET_WORDS_BIGENDIAN
2140 FSTH2 = FST0;
2141 FST2 = FSTH1;
2142 #else
2143 FSTH2 = FST1;
2144 FST2 = FSTH0;
2145 #endif
2146 break;
2147 default: /* unpredictable */
2148 break;
2150 DEBUG_FPU_STATE();
2151 RETURN();
2154 #ifdef CONFIG_SOFTFLOAT
2155 #define clear_invalid() do { \
2156 int flags = get_float_exception_flags(&env->fp_status); \
2157 flags &= ~float_flag_invalid; \
2158 set_float_exception_flags(flags, &env->fp_status); \
2159 } while(0)
2160 #else
2161 #define clear_invalid() do { } while(0)
2162 #endif
2164 extern void dump_fpu_s(CPUState *env);
2166 #define CMP_OP(fmt, op) \
2167 void OPPROTO op_cmp ## _ ## fmt ## _ ## op(void) \
2169 CALL_FROM_TB1(do_cmp ## _ ## fmt ## _ ## op, PARAM1); \
2170 DEBUG_FPU_STATE(); \
2171 RETURN(); \
2173 void OPPROTO op_cmpabs ## _ ## fmt ## _ ## op(void) \
2175 CALL_FROM_TB1(do_cmpabs ## _ ## fmt ## _ ## op, PARAM1); \
2176 DEBUG_FPU_STATE(); \
2177 RETURN(); \
2179 #define CMP_OPS(op) \
2180 CMP_OP(d, op) \
2181 CMP_OP(s, op) \
2182 CMP_OP(ps, op)
2184 CMP_OPS(f)
2185 CMP_OPS(un)
2186 CMP_OPS(eq)
2187 CMP_OPS(ueq)
2188 CMP_OPS(olt)
2189 CMP_OPS(ult)
2190 CMP_OPS(ole)
2191 CMP_OPS(ule)
2192 CMP_OPS(sf)
2193 CMP_OPS(ngle)
2194 CMP_OPS(seq)
2195 CMP_OPS(ngl)
2196 CMP_OPS(lt)
2197 CMP_OPS(nge)
2198 CMP_OPS(le)
2199 CMP_OPS(ngt)
2200 #undef CMP_OPS
2201 #undef CMP_OP
2203 void op_bc1f (void)
2205 T0 = !!(~GET_FP_COND(env) & (0x1 << PARAM1));
2206 DEBUG_FPU_STATE();
2207 RETURN();
2209 void op_bc1any2f (void)
2211 T0 = !!(~GET_FP_COND(env) & (0x3 << PARAM1));
2212 DEBUG_FPU_STATE();
2213 RETURN();
2215 void op_bc1any4f (void)
2217 T0 = !!(~GET_FP_COND(env) & (0xf << PARAM1));
2218 DEBUG_FPU_STATE();
2219 RETURN();
2222 void op_bc1t (void)
2224 T0 = !!(GET_FP_COND(env) & (0x1 << PARAM1));
2225 DEBUG_FPU_STATE();
2226 RETURN();
2228 void op_bc1any2t (void)
2230 T0 = !!(GET_FP_COND(env) & (0x3 << PARAM1));
2231 DEBUG_FPU_STATE();
2232 RETURN();
2234 void op_bc1any4t (void)
2236 T0 = !!(GET_FP_COND(env) & (0xf << PARAM1));
2237 DEBUG_FPU_STATE();
2238 RETURN();
2241 void op_tlbwi (void)
2243 CALL_FROM_TB0(env->do_tlbwi);
2244 RETURN();
2247 void op_tlbwr (void)
2249 CALL_FROM_TB0(env->do_tlbwr);
2250 RETURN();
2253 void op_tlbp (void)
2255 CALL_FROM_TB0(env->do_tlbp);
2256 RETURN();
2259 void op_tlbr (void)
2261 CALL_FROM_TB0(env->do_tlbr);
2262 RETURN();
2265 /* Specials */
2266 #if defined (CONFIG_USER_ONLY)
2267 void op_tls_value (void)
2269 T0 = env->tls_value;
2271 #endif
2273 void op_pmon (void)
2275 CALL_FROM_TB1(do_pmon, PARAM1);
2276 RETURN();
2279 void op_di (void)
2281 T0 = env->CP0_Status;
2282 env->CP0_Status = T0 & ~(1 << CP0St_IE);
2283 CALL_FROM_TB1(cpu_mips_update_irq, env);
2284 RETURN();
2287 void op_ei (void)
2289 T0 = env->CP0_Status;
2290 env->CP0_Status = T0 | (1 << CP0St_IE);
2291 CALL_FROM_TB1(cpu_mips_update_irq, env);
2292 RETURN();
2295 void op_trap (void)
2297 if (T0) {
2298 CALL_FROM_TB1(do_raise_exception, EXCP_TRAP);
2300 RETURN();
2303 void op_debug (void)
2305 CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG);
2306 RETURN();
2309 void op_set_lladdr (void)
2311 env->CP0_LLAddr = T2;
2312 RETURN();
2315 void debug_pre_eret (void);
2316 void debug_post_eret (void);
2317 void op_eret (void)
2319 if (loglevel & CPU_LOG_EXEC)
2320 CALL_FROM_TB0(debug_pre_eret);
2321 if (env->CP0_Status & (1 << CP0St_ERL)) {
2322 env->PC = env->CP0_ErrorEPC;
2323 env->CP0_Status &= ~(1 << CP0St_ERL);
2324 } else {
2325 env->PC = env->CP0_EPC;
2326 env->CP0_Status &= ~(1 << CP0St_EXL);
2328 if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
2329 !(env->CP0_Status & (1 << CP0St_ERL)) &&
2330 !(env->hflags & MIPS_HFLAG_DM) &&
2331 (env->CP0_Status & (1 << CP0St_UM)))
2332 env->hflags |= MIPS_HFLAG_UM;
2333 if (loglevel & CPU_LOG_EXEC)
2334 CALL_FROM_TB0(debug_post_eret);
2335 env->CP0_LLAddr = 1;
2336 RETURN();
2339 void op_deret (void)
2341 if (loglevel & CPU_LOG_EXEC)
2342 CALL_FROM_TB0(debug_pre_eret);
2343 env->PC = env->CP0_DEPC;
2344 env->hflags |= MIPS_HFLAG_DM;
2345 if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
2346 !(env->CP0_Status & (1 << CP0St_ERL)) &&
2347 !(env->hflags & MIPS_HFLAG_DM) &&
2348 (env->CP0_Status & (1 << CP0St_UM)))
2349 env->hflags |= MIPS_HFLAG_UM;
2350 if (loglevel & CPU_LOG_EXEC)
2351 CALL_FROM_TB0(debug_post_eret);
2352 env->CP0_LLAddr = 1;
2353 RETURN();
2356 void op_rdhwr_cpunum(void)
2358 if (!(env->hflags & MIPS_HFLAG_UM) ||
2359 (env->CP0_HWREna & (1 << 0)) ||
2360 (env->CP0_Status & (1 << CP0St_CU0)))
2361 T0 = env->CP0_EBase & 0x3ff;
2362 else
2363 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
2364 RETURN();
2367 void op_rdhwr_synci_step(void)
2369 if (!(env->hflags & MIPS_HFLAG_UM) ||
2370 (env->CP0_HWREna & (1 << 1)) ||
2371 (env->CP0_Status & (1 << CP0St_CU0)))
2372 T0 = env->SYNCI_Step;
2373 else
2374 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
2375 RETURN();
2378 void op_rdhwr_cc(void)
2380 if (!(env->hflags & MIPS_HFLAG_UM) ||
2381 (env->CP0_HWREna & (1 << 2)) ||
2382 (env->CP0_Status & (1 << CP0St_CU0)))
2383 T0 = env->CP0_Count;
2384 else
2385 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
2386 RETURN();
2389 void op_rdhwr_ccres(void)
2391 if (!(env->hflags & MIPS_HFLAG_UM) ||
2392 (env->CP0_HWREna & (1 << 3)) ||
2393 (env->CP0_Status & (1 << CP0St_CU0)))
2394 T0 = env->CCRes;
2395 else
2396 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
2397 RETURN();
2400 void op_save_state (void)
2402 env->hflags = PARAM1;
2403 RETURN();
2406 void op_save_pc (void)
2408 env->PC = PARAM1;
2409 RETURN();
2412 void op_interrupt_restart (void)
2414 if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
2415 !(env->CP0_Status & (1 << CP0St_ERL)) &&
2416 !(env->hflags & MIPS_HFLAG_DM) &&
2417 (env->CP0_Status & (1 << CP0St_IE)) &&
2418 (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask)) {
2419 env->CP0_Cause &= ~(0x1f << CP0Ca_EC);
2420 CALL_FROM_TB1(do_raise_exception, EXCP_EXT_INTERRUPT);
2422 RETURN();
2425 void op_raise_exception (void)
2427 CALL_FROM_TB1(do_raise_exception, PARAM1);
2428 RETURN();
2431 void op_raise_exception_err (void)
2433 CALL_FROM_TB2(do_raise_exception_err, PARAM1, PARAM2);
2434 RETURN();
2437 void op_exit_tb (void)
2439 EXIT_TB();
2440 RETURN();
2443 void op_wait (void)
2445 env->halted = 1;
2446 CALL_FROM_TB1(do_raise_exception, EXCP_HLT);
2447 RETURN();
2450 /* Bitfield operations. */
2451 void op_ext(void)
2453 unsigned int pos = PARAM1;
2454 unsigned int size = PARAM2;
2456 T0 = ((uint32_t)T1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0);
2457 RETURN();
2460 void op_ins(void)
2462 unsigned int pos = PARAM1;
2463 unsigned int size = PARAM2;
2464 target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos;
2466 T0 = (T0 & ~mask) | (((uint32_t)T1 << pos) & mask);
2467 RETURN();
2470 void op_wsbh(void)
2472 T0 = ((T1 << 8) & ~0x00FF00FF) | ((T1 >> 8) & 0x00FF00FF);
2473 RETURN();
2476 #ifdef TARGET_MIPS64
2477 void op_dext(void)
2479 unsigned int pos = PARAM1;
2480 unsigned int size = PARAM2;
2482 T0 = (T1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0);
2483 RETURN();
2486 void op_dins(void)
2488 unsigned int pos = PARAM1;
2489 unsigned int size = PARAM2;
2490 target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos;
2492 T0 = (T0 & ~mask) | ((T1 << pos) & mask);
2493 RETURN();
2496 void op_dsbh(void)
2498 T0 = ((T1 << 8) & ~0x00FF00FF00FF00FFULL) | ((T1 >> 8) & 0x00FF00FF00FF00FFULL);
2499 RETURN();
2502 void op_dshd(void)
2504 T0 = ((T1 << 16) & ~0x0000FFFF0000FFFFULL) | ((T1 >> 16) & 0x0000FFFF0000FFFFULL);
2505 RETURN();
2507 #endif
2509 void op_seb(void)
2511 T0 = ((T1 & 0xFF) ^ 0x80) - 0x80;
2512 RETURN();
2515 void op_seh(void)
2517 T0 = ((T1 & 0xFFFF) ^ 0x8000) - 0x8000;
2518 RETURN();