Fix setting counter limit to 0 (Robert Reif)
[qemu/qemu_0_9_1_stable.git] / target-mips / op.c
blobad619c9b4603ad1951225ba5629cd0219076e4e2
1 /*
2 * MIPS emulation micro-operations for qemu.
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"
25 #include "host-utils.h"
27 #ifndef CALL_FROM_TB0
28 #define CALL_FROM_TB0(func) func()
29 #endif
30 #ifndef CALL_FROM_TB1
31 #define CALL_FROM_TB1(func, arg0) func(arg0)
32 #endif
33 #ifndef CALL_FROM_TB1_CONST16
34 #define CALL_FROM_TB1_CONST16(func, arg0) CALL_FROM_TB1(func, arg0)
35 #endif
36 #ifndef CALL_FROM_TB2
37 #define CALL_FROM_TB2(func, arg0, arg1) func(arg0, arg1)
38 #endif
39 #ifndef CALL_FROM_TB2_CONST16
40 #define CALL_FROM_TB2_CONST16(func, arg0, arg1) \
41 CALL_FROM_TB2(func, arg0, arg1)
42 #endif
43 #ifndef CALL_FROM_TB3
44 #define CALL_FROM_TB3(func, arg0, arg1, arg2) func(arg0, arg1, arg2)
45 #endif
46 #ifndef CALL_FROM_TB4
47 #define CALL_FROM_TB4(func, arg0, arg1, arg2, arg3) \
48 func(arg0, arg1, arg2, arg3)
49 #endif
51 #define REG 1
52 #include "op_template.c"
53 #undef REG
54 #define REG 2
55 #include "op_template.c"
56 #undef REG
57 #define REG 3
58 #include "op_template.c"
59 #undef REG
60 #define REG 4
61 #include "op_template.c"
62 #undef REG
63 #define REG 5
64 #include "op_template.c"
65 #undef REG
66 #define REG 6
67 #include "op_template.c"
68 #undef REG
69 #define REG 7
70 #include "op_template.c"
71 #undef REG
72 #define REG 8
73 #include "op_template.c"
74 #undef REG
75 #define REG 9
76 #include "op_template.c"
77 #undef REG
78 #define REG 10
79 #include "op_template.c"
80 #undef REG
81 #define REG 11
82 #include "op_template.c"
83 #undef REG
84 #define REG 12
85 #include "op_template.c"
86 #undef REG
87 #define REG 13
88 #include "op_template.c"
89 #undef REG
90 #define REG 14
91 #include "op_template.c"
92 #undef REG
93 #define REG 15
94 #include "op_template.c"
95 #undef REG
96 #define REG 16
97 #include "op_template.c"
98 #undef REG
99 #define REG 17
100 #include "op_template.c"
101 #undef REG
102 #define REG 18
103 #include "op_template.c"
104 #undef REG
105 #define REG 19
106 #include "op_template.c"
107 #undef REG
108 #define REG 20
109 #include "op_template.c"
110 #undef REG
111 #define REG 21
112 #include "op_template.c"
113 #undef REG
114 #define REG 22
115 #include "op_template.c"
116 #undef REG
117 #define REG 23
118 #include "op_template.c"
119 #undef REG
120 #define REG 24
121 #include "op_template.c"
122 #undef REG
123 #define REG 25
124 #include "op_template.c"
125 #undef REG
126 #define REG 26
127 #include "op_template.c"
128 #undef REG
129 #define REG 27
130 #include "op_template.c"
131 #undef REG
132 #define REG 28
133 #include "op_template.c"
134 #undef REG
135 #define REG 29
136 #include "op_template.c"
137 #undef REG
138 #define REG 30
139 #include "op_template.c"
140 #undef REG
141 #define REG 31
142 #include "op_template.c"
143 #undef REG
145 #define TN
146 #include "op_template.c"
147 #undef TN
149 #define FREG 0
150 #include "fop_template.c"
151 #undef FREG
152 #define FREG 1
153 #include "fop_template.c"
154 #undef FREG
155 #define FREG 2
156 #include "fop_template.c"
157 #undef FREG
158 #define FREG 3
159 #include "fop_template.c"
160 #undef FREG
161 #define FREG 4
162 #include "fop_template.c"
163 #undef FREG
164 #define FREG 5
165 #include "fop_template.c"
166 #undef FREG
167 #define FREG 6
168 #include "fop_template.c"
169 #undef FREG
170 #define FREG 7
171 #include "fop_template.c"
172 #undef FREG
173 #define FREG 8
174 #include "fop_template.c"
175 #undef FREG
176 #define FREG 9
177 #include "fop_template.c"
178 #undef FREG
179 #define FREG 10
180 #include "fop_template.c"
181 #undef FREG
182 #define FREG 11
183 #include "fop_template.c"
184 #undef FREG
185 #define FREG 12
186 #include "fop_template.c"
187 #undef FREG
188 #define FREG 13
189 #include "fop_template.c"
190 #undef FREG
191 #define FREG 14
192 #include "fop_template.c"
193 #undef FREG
194 #define FREG 15
195 #include "fop_template.c"
196 #undef FREG
197 #define FREG 16
198 #include "fop_template.c"
199 #undef FREG
200 #define FREG 17
201 #include "fop_template.c"
202 #undef FREG
203 #define FREG 18
204 #include "fop_template.c"
205 #undef FREG
206 #define FREG 19
207 #include "fop_template.c"
208 #undef FREG
209 #define FREG 20
210 #include "fop_template.c"
211 #undef FREG
212 #define FREG 21
213 #include "fop_template.c"
214 #undef FREG
215 #define FREG 22
216 #include "fop_template.c"
217 #undef FREG
218 #define FREG 23
219 #include "fop_template.c"
220 #undef FREG
221 #define FREG 24
222 #include "fop_template.c"
223 #undef FREG
224 #define FREG 25
225 #include "fop_template.c"
226 #undef FREG
227 #define FREG 26
228 #include "fop_template.c"
229 #undef FREG
230 #define FREG 27
231 #include "fop_template.c"
232 #undef FREG
233 #define FREG 28
234 #include "fop_template.c"
235 #undef FREG
236 #define FREG 29
237 #include "fop_template.c"
238 #undef FREG
239 #define FREG 30
240 #include "fop_template.c"
241 #undef FREG
242 #define FREG 31
243 #include "fop_template.c"
244 #undef FREG
246 #define FTN
247 #include "fop_template.c"
248 #undef FTN
250 void op_dup_T0 (void)
252 T2 = T0;
253 FORCE_RET();
256 void op_load_HI (void)
258 T0 = env->HI[PARAM1][env->current_tc];
259 FORCE_RET();
262 void op_store_HI (void)
264 env->HI[PARAM1][env->current_tc] = T0;
265 FORCE_RET();
268 void op_load_LO (void)
270 T0 = env->LO[PARAM1][env->current_tc];
271 FORCE_RET();
274 void op_store_LO (void)
276 env->LO[PARAM1][env->current_tc] = T0;
277 FORCE_RET();
280 /* Load and store */
281 #define MEMSUFFIX _raw
282 #include "op_mem.c"
283 #undef MEMSUFFIX
284 #if !defined(CONFIG_USER_ONLY)
285 #define MEMSUFFIX _user
286 #include "op_mem.c"
287 #undef MEMSUFFIX
289 #define MEMSUFFIX _super
290 #include "op_mem.c"
291 #undef MEMSUFFIX
293 #define MEMSUFFIX _kernel
294 #include "op_mem.c"
295 #undef MEMSUFFIX
296 #endif
298 /* Addresses computation */
299 void op_addr_add (void)
301 /* For compatibility with 32-bit code, data reference in user mode
302 with Status_UX = 0 should be casted to 32-bit and sign extended.
303 See the MIPS64 PRA manual, section 4.10. */
304 #if defined(TARGET_MIPS64)
305 if (((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
306 !(env->CP0_Status & (1 << CP0St_UX)))
307 T0 = (int64_t)(int32_t)(T0 + T1);
308 else
309 #endif
310 T0 += T1;
311 FORCE_RET();
314 /* Arithmetic */
315 void op_add (void)
317 T0 = (int32_t)((int32_t)T0 + (int32_t)T1);
318 FORCE_RET();
321 void op_addo (void)
323 target_ulong tmp;
325 tmp = (int32_t)T0;
326 T0 = (int32_t)T0 + (int32_t)T1;
327 if (((tmp ^ T1 ^ (-1)) & (T0 ^ T1)) >> 31) {
328 /* operands of same sign, result different sign */
329 CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
331 T0 = (int32_t)T0;
332 FORCE_RET();
335 void op_sub (void)
337 T0 = (int32_t)((int32_t)T0 - (int32_t)T1);
338 FORCE_RET();
341 void op_subo (void)
343 target_ulong tmp;
345 tmp = (int32_t)T0;
346 T0 = (int32_t)T0 - (int32_t)T1;
347 if (((tmp ^ T1) & (tmp ^ T0)) >> 31) {
348 /* operands of different sign, first operand and result different sign */
349 CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
351 T0 = (int32_t)T0;
352 FORCE_RET();
355 void op_mul (void)
357 T0 = (int32_t)((int32_t)T0 * (int32_t)T1);
358 FORCE_RET();
361 #if HOST_LONG_BITS < 64
362 void op_div (void)
364 CALL_FROM_TB0(do_div);
365 FORCE_RET();
367 #else
368 void op_div (void)
370 if (T1 != 0) {
371 env->LO[0][env->current_tc] = (int32_t)((int64_t)(int32_t)T0 / (int32_t)T1);
372 env->HI[0][env->current_tc] = (int32_t)((int64_t)(int32_t)T0 % (int32_t)T1);
374 FORCE_RET();
376 #endif
378 void op_divu (void)
380 if (T1 != 0) {
381 env->LO[0][env->current_tc] = (int32_t)((uint32_t)T0 / (uint32_t)T1);
382 env->HI[0][env->current_tc] = (int32_t)((uint32_t)T0 % (uint32_t)T1);
384 FORCE_RET();
387 #if defined(TARGET_MIPS64)
388 /* Arithmetic */
389 void op_dadd (void)
391 T0 += T1;
392 FORCE_RET();
395 void op_daddo (void)
397 target_long tmp;
399 tmp = T0;
400 T0 += T1;
401 if (((tmp ^ T1 ^ (-1)) & (T0 ^ T1)) >> 63) {
402 /* operands of same sign, result different sign */
403 CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
405 FORCE_RET();
408 void op_dsub (void)
410 T0 -= T1;
411 FORCE_RET();
414 void op_dsubo (void)
416 target_long tmp;
418 tmp = T0;
419 T0 = (int64_t)T0 - (int64_t)T1;
420 if (((tmp ^ T1) & (tmp ^ T0)) >> 63) {
421 /* operands of different sign, first operand and result different sign */
422 CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
424 FORCE_RET();
427 void op_dmul (void)
429 T0 = (int64_t)T0 * (int64_t)T1;
430 FORCE_RET();
433 /* Those might call libgcc functions. */
434 void op_ddiv (void)
436 do_ddiv();
437 FORCE_RET();
440 #if TARGET_LONG_BITS > HOST_LONG_BITS
441 void op_ddivu (void)
443 do_ddivu();
444 FORCE_RET();
446 #else
447 void op_ddivu (void)
449 if (T1 != 0) {
450 env->LO[0][env->current_tc] = T0 / T1;
451 env->HI[0][env->current_tc] = T0 % T1;
453 FORCE_RET();
455 #endif
456 #endif /* TARGET_MIPS64 */
458 /* Logical */
459 void op_and (void)
461 T0 &= T1;
462 FORCE_RET();
465 void op_nor (void)
467 T0 = ~(T0 | T1);
468 FORCE_RET();
471 void op_or (void)
473 T0 |= T1;
474 FORCE_RET();
477 void op_xor (void)
479 T0 ^= T1;
480 FORCE_RET();
483 void op_sll (void)
485 T0 = (int32_t)((uint32_t)T0 << T1);
486 FORCE_RET();
489 void op_sra (void)
491 T0 = (int32_t)((int32_t)T0 >> T1);
492 FORCE_RET();
495 void op_srl (void)
497 T0 = (int32_t)((uint32_t)T0 >> T1);
498 FORCE_RET();
501 void op_rotr (void)
503 target_ulong tmp;
505 if (T1) {
506 tmp = (int32_t)((uint32_t)T0 << (0x20 - T1));
507 T0 = (int32_t)((uint32_t)T0 >> T1) | tmp;
509 FORCE_RET();
512 void op_sllv (void)
514 T0 = (int32_t)((uint32_t)T1 << ((uint32_t)T0 & 0x1F));
515 FORCE_RET();
518 void op_srav (void)
520 T0 = (int32_t)((int32_t)T1 >> (T0 & 0x1F));
521 FORCE_RET();
524 void op_srlv (void)
526 T0 = (int32_t)((uint32_t)T1 >> (T0 & 0x1F));
527 FORCE_RET();
530 void op_rotrv (void)
532 target_ulong tmp;
534 T0 &= 0x1F;
535 if (T0) {
536 tmp = (int32_t)((uint32_t)T1 << (0x20 - T0));
537 T0 = (int32_t)((uint32_t)T1 >> T0) | tmp;
538 } else
539 T0 = T1;
540 FORCE_RET();
543 void op_clo (void)
545 T0 = clo32(T0);
546 FORCE_RET();
549 void op_clz (void)
551 T0 = clz32(T0);
552 FORCE_RET();
555 #if defined(TARGET_MIPS64)
557 #if TARGET_LONG_BITS > HOST_LONG_BITS
558 /* Those might call libgcc functions. */
559 void op_dsll (void)
561 CALL_FROM_TB0(do_dsll);
562 FORCE_RET();
565 void op_dsll32 (void)
567 CALL_FROM_TB0(do_dsll32);
568 FORCE_RET();
571 void op_dsra (void)
573 CALL_FROM_TB0(do_dsra);
574 FORCE_RET();
577 void op_dsra32 (void)
579 CALL_FROM_TB0(do_dsra32);
580 FORCE_RET();
583 void op_dsrl (void)
585 CALL_FROM_TB0(do_dsrl);
586 FORCE_RET();
589 void op_dsrl32 (void)
591 CALL_FROM_TB0(do_dsrl32);
592 FORCE_RET();
595 void op_drotr (void)
597 CALL_FROM_TB0(do_drotr);
598 FORCE_RET();
601 void op_drotr32 (void)
603 CALL_FROM_TB0(do_drotr32);
604 FORCE_RET();
607 void op_dsllv (void)
609 CALL_FROM_TB0(do_dsllv);
610 FORCE_RET();
613 void op_dsrav (void)
615 CALL_FROM_TB0(do_dsrav);
616 FORCE_RET();
619 void op_dsrlv (void)
621 CALL_FROM_TB0(do_dsrlv);
622 FORCE_RET();
625 void op_drotrv (void)
627 CALL_FROM_TB0(do_drotrv);
628 FORCE_RET();
631 void op_dclo (void)
633 CALL_FROM_TB0(do_dclo);
634 FORCE_RET();
637 void op_dclz (void)
639 CALL_FROM_TB0(do_dclz);
640 FORCE_RET();
643 #else /* TARGET_LONG_BITS > HOST_LONG_BITS */
645 void op_dsll (void)
647 T0 = T0 << T1;
648 FORCE_RET();
651 void op_dsll32 (void)
653 T0 = T0 << (T1 + 32);
654 FORCE_RET();
657 void op_dsra (void)
659 T0 = (int64_t)T0 >> T1;
660 FORCE_RET();
663 void op_dsra32 (void)
665 T0 = (int64_t)T0 >> (T1 + 32);
666 FORCE_RET();
669 void op_dsrl (void)
671 T0 = T0 >> T1;
672 FORCE_RET();
675 void op_dsrl32 (void)
677 T0 = T0 >> (T1 + 32);
678 FORCE_RET();
681 void op_drotr (void)
683 target_ulong tmp;
685 if (T1) {
686 tmp = T0 << (0x40 - T1);
687 T0 = (T0 >> T1) | tmp;
689 FORCE_RET();
692 void op_drotr32 (void)
694 target_ulong tmp;
696 tmp = T0 << (0x40 - (32 + T1));
697 T0 = (T0 >> (32 + T1)) | tmp;
698 FORCE_RET();
701 void op_dsllv (void)
703 T0 = T1 << (T0 & 0x3F);
704 FORCE_RET();
707 void op_dsrav (void)
709 T0 = (int64_t)T1 >> (T0 & 0x3F);
710 FORCE_RET();
713 void op_dsrlv (void)
715 T0 = T1 >> (T0 & 0x3F);
716 FORCE_RET();
719 void op_drotrv (void)
721 target_ulong tmp;
723 T0 &= 0x3F;
724 if (T0) {
725 tmp = T1 << (0x40 - T0);
726 T0 = (T1 >> T0) | tmp;
727 } else
728 T0 = T1;
729 FORCE_RET();
732 void op_dclo (void)
734 T0 = clo64(T0);
735 FORCE_RET();
738 void op_dclz (void)
740 T0 = clz64(T0);
741 FORCE_RET();
743 #endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
744 #endif /* TARGET_MIPS64 */
746 /* 64 bits arithmetic */
747 #if TARGET_LONG_BITS > HOST_LONG_BITS
748 void op_mult (void)
750 CALL_FROM_TB0(do_mult);
751 FORCE_RET();
754 void op_multu (void)
756 CALL_FROM_TB0(do_multu);
757 FORCE_RET();
760 void op_madd (void)
762 CALL_FROM_TB0(do_madd);
763 FORCE_RET();
766 void op_maddu (void)
768 CALL_FROM_TB0(do_maddu);
769 FORCE_RET();
772 void op_msub (void)
774 CALL_FROM_TB0(do_msub);
775 FORCE_RET();
778 void op_msubu (void)
780 CALL_FROM_TB0(do_msubu);
781 FORCE_RET();
784 #else /* TARGET_LONG_BITS > HOST_LONG_BITS */
786 static always_inline uint64_t get_HILO (void)
788 return ((uint64_t)env->HI[0][env->current_tc] << 32) |
789 ((uint64_t)(uint32_t)env->LO[0][env->current_tc]);
792 static always_inline void set_HILO (uint64_t HILO)
794 env->LO[0][env->current_tc] = (int32_t)(HILO & 0xFFFFFFFF);
795 env->HI[0][env->current_tc] = (int32_t)(HILO >> 32);
798 void op_mult (void)
800 set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
801 FORCE_RET();
804 void op_multu (void)
806 set_HILO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
807 FORCE_RET();
810 void op_madd (void)
812 int64_t tmp;
814 tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
815 set_HILO((int64_t)get_HILO() + tmp);
816 FORCE_RET();
819 void op_maddu (void)
821 uint64_t tmp;
823 tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
824 set_HILO(get_HILO() + tmp);
825 FORCE_RET();
828 void op_msub (void)
830 int64_t tmp;
832 tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
833 set_HILO((int64_t)get_HILO() - tmp);
834 FORCE_RET();
837 void op_msubu (void)
839 uint64_t tmp;
841 tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
842 set_HILO(get_HILO() - tmp);
843 FORCE_RET();
845 #endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
847 #if defined(TARGET_MIPS64)
848 void op_dmult (void)
850 CALL_FROM_TB4(muls64, &(env->LO[0][env->current_tc]), &(env->HI[0][env->current_tc]), T0, T1);
851 FORCE_RET();
854 void op_dmultu (void)
856 CALL_FROM_TB4(mulu64, &(env->LO[0][env->current_tc]), &(env->HI[0][env->current_tc]), T0, T1);
857 FORCE_RET();
859 #endif
861 /* Conditional moves */
862 void op_movn (void)
864 if (T1 != 0)
865 env->gpr[PARAM1][env->current_tc] = T0;
866 FORCE_RET();
869 void op_movz (void)
871 if (T1 == 0)
872 env->gpr[PARAM1][env->current_tc] = T0;
873 FORCE_RET();
876 void op_movf (void)
878 if (!(env->fpu->fcr31 & PARAM1))
879 T0 = T1;
880 FORCE_RET();
883 void op_movt (void)
885 if (env->fpu->fcr31 & PARAM1)
886 T0 = T1;
887 FORCE_RET();
890 /* Tests */
891 #define OP_COND(name, cond) \
892 void glue(op_, name) (void) \
894 if (cond) { \
895 T0 = 1; \
896 } else { \
897 T0 = 0; \
899 FORCE_RET(); \
902 OP_COND(eq, T0 == T1);
903 OP_COND(ne, T0 != T1);
904 OP_COND(ge, (target_long)T0 >= (target_long)T1);
905 OP_COND(geu, T0 >= T1);
906 OP_COND(lt, (target_long)T0 < (target_long)T1);
907 OP_COND(ltu, T0 < T1);
908 OP_COND(gez, (target_long)T0 >= 0);
909 OP_COND(gtz, (target_long)T0 > 0);
910 OP_COND(lez, (target_long)T0 <= 0);
911 OP_COND(ltz, (target_long)T0 < 0);
913 /* Branches */
914 void OPPROTO op_goto_tb0(void)
916 GOTO_TB(op_goto_tb0, PARAM1, 0);
917 FORCE_RET();
920 void OPPROTO op_goto_tb1(void)
922 GOTO_TB(op_goto_tb1, PARAM1, 1);
923 FORCE_RET();
926 /* Branch to register */
927 void op_save_breg_target (void)
929 env->btarget = T2;
930 FORCE_RET();
933 void op_restore_breg_target (void)
935 T2 = env->btarget;
936 FORCE_RET();
939 void op_breg (void)
941 env->PC[env->current_tc] = T2;
942 FORCE_RET();
945 void op_save_btarget (void)
947 env->btarget = PARAM1;
948 FORCE_RET();
951 #if defined(TARGET_MIPS64)
952 void op_save_btarget64 (void)
954 env->btarget = ((uint64_t)PARAM1 << 32) | (uint32_t)PARAM2;
955 FORCE_RET();
957 #endif
959 /* Conditional branch */
960 void op_set_bcond (void)
962 T2 = T0;
963 FORCE_RET();
966 void op_save_bcond (void)
968 env->bcond = T2;
969 FORCE_RET();
972 void op_restore_bcond (void)
974 T2 = env->bcond;
975 FORCE_RET();
978 void op_jnz_T2 (void)
980 if (T2)
981 GOTO_LABEL_PARAM(1);
982 FORCE_RET();
985 /* CP0 functions */
986 void op_mfc0_index (void)
988 T0 = env->CP0_Index;
989 FORCE_RET();
992 void op_mfc0_mvpcontrol (void)
994 T0 = env->mvp->CP0_MVPControl;
995 FORCE_RET();
998 void op_mfc0_mvpconf0 (void)
1000 T0 = env->mvp->CP0_MVPConf0;
1001 FORCE_RET();
1004 void op_mfc0_mvpconf1 (void)
1006 T0 = env->mvp->CP0_MVPConf1;
1007 FORCE_RET();
1010 void op_mfc0_random (void)
1012 CALL_FROM_TB0(do_mfc0_random);
1013 FORCE_RET();
1016 void op_mfc0_vpecontrol (void)
1018 T0 = env->CP0_VPEControl;
1019 FORCE_RET();
1022 void op_mfc0_vpeconf0 (void)
1024 T0 = env->CP0_VPEConf0;
1025 FORCE_RET();
1028 void op_mfc0_vpeconf1 (void)
1030 T0 = env->CP0_VPEConf1;
1031 FORCE_RET();
1034 void op_mfc0_yqmask (void)
1036 T0 = env->CP0_YQMask;
1037 FORCE_RET();
1040 void op_mfc0_vpeschedule (void)
1042 T0 = env->CP0_VPESchedule;
1043 FORCE_RET();
1046 void op_mfc0_vpeschefback (void)
1048 T0 = env->CP0_VPEScheFBack;
1049 FORCE_RET();
1052 void op_mfc0_vpeopt (void)
1054 T0 = env->CP0_VPEOpt;
1055 FORCE_RET();
1058 void op_mfc0_entrylo0 (void)
1060 T0 = (int32_t)env->CP0_EntryLo0;
1061 FORCE_RET();
1064 void op_mfc0_tcstatus (void)
1066 T0 = env->CP0_TCStatus[env->current_tc];
1067 FORCE_RET();
1070 void op_mftc0_tcstatus(void)
1072 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1074 T0 = env->CP0_TCStatus[other_tc];
1075 FORCE_RET();
1078 void op_mfc0_tcbind (void)
1080 T0 = env->CP0_TCBind[env->current_tc];
1081 FORCE_RET();
1084 void op_mftc0_tcbind(void)
1086 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1088 T0 = env->CP0_TCBind[other_tc];
1089 FORCE_RET();
1092 void op_mfc0_tcrestart (void)
1094 T0 = env->PC[env->current_tc];
1095 FORCE_RET();
1098 void op_mftc0_tcrestart(void)
1100 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1102 T0 = env->PC[other_tc];
1103 FORCE_RET();
1106 void op_mfc0_tchalt (void)
1108 T0 = env->CP0_TCHalt[env->current_tc];
1109 FORCE_RET();
1112 void op_mftc0_tchalt(void)
1114 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1116 T0 = env->CP0_TCHalt[other_tc];
1117 FORCE_RET();
1120 void op_mfc0_tccontext (void)
1122 T0 = env->CP0_TCContext[env->current_tc];
1123 FORCE_RET();
1126 void op_mftc0_tccontext(void)
1128 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1130 T0 = env->CP0_TCContext[other_tc];
1131 FORCE_RET();
1134 void op_mfc0_tcschedule (void)
1136 T0 = env->CP0_TCSchedule[env->current_tc];
1137 FORCE_RET();
1140 void op_mftc0_tcschedule(void)
1142 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1144 T0 = env->CP0_TCSchedule[other_tc];
1145 FORCE_RET();
1148 void op_mfc0_tcschefback (void)
1150 T0 = env->CP0_TCScheFBack[env->current_tc];
1151 FORCE_RET();
1154 void op_mftc0_tcschefback(void)
1156 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1158 T0 = env->CP0_TCScheFBack[other_tc];
1159 FORCE_RET();
1162 void op_mfc0_entrylo1 (void)
1164 T0 = (int32_t)env->CP0_EntryLo1;
1165 FORCE_RET();
1168 void op_mfc0_context (void)
1170 T0 = (int32_t)env->CP0_Context;
1171 FORCE_RET();
1174 void op_mfc0_pagemask (void)
1176 T0 = env->CP0_PageMask;
1177 FORCE_RET();
1180 void op_mfc0_pagegrain (void)
1182 T0 = env->CP0_PageGrain;
1183 FORCE_RET();
1186 void op_mfc0_wired (void)
1188 T0 = env->CP0_Wired;
1189 FORCE_RET();
1192 void op_mfc0_srsconf0 (void)
1194 T0 = env->CP0_SRSConf0;
1195 FORCE_RET();
1198 void op_mfc0_srsconf1 (void)
1200 T0 = env->CP0_SRSConf1;
1201 FORCE_RET();
1204 void op_mfc0_srsconf2 (void)
1206 T0 = env->CP0_SRSConf2;
1207 FORCE_RET();
1210 void op_mfc0_srsconf3 (void)
1212 T0 = env->CP0_SRSConf3;
1213 FORCE_RET();
1216 void op_mfc0_srsconf4 (void)
1218 T0 = env->CP0_SRSConf4;
1219 FORCE_RET();
1222 void op_mfc0_hwrena (void)
1224 T0 = env->CP0_HWREna;
1225 FORCE_RET();
1228 void op_mfc0_badvaddr (void)
1230 T0 = (int32_t)env->CP0_BadVAddr;
1231 FORCE_RET();
1234 void op_mfc0_count (void)
1236 CALL_FROM_TB0(do_mfc0_count);
1237 FORCE_RET();
1240 void op_mfc0_entryhi (void)
1242 T0 = (int32_t)env->CP0_EntryHi;
1243 FORCE_RET();
1246 void op_mftc0_entryhi(void)
1248 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1250 T0 = (env->CP0_EntryHi & ~0xff) | (env->CP0_TCStatus[other_tc] & 0xff);
1251 FORCE_RET();
1254 void op_mfc0_compare (void)
1256 T0 = env->CP0_Compare;
1257 FORCE_RET();
1260 void op_mfc0_status (void)
1262 T0 = env->CP0_Status;
1263 FORCE_RET();
1266 void op_mftc0_status(void)
1268 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1269 uint32_t tcstatus = env->CP0_TCStatus[other_tc];
1271 T0 = env->CP0_Status & ~0xf1000018;
1272 T0 |= tcstatus & (0xf << CP0TCSt_TCU0);
1273 T0 |= (tcstatus & (1 << CP0TCSt_TMX)) >> (CP0TCSt_TMX - CP0St_MX);
1274 T0 |= (tcstatus & (0x3 << CP0TCSt_TKSU)) >> (CP0TCSt_TKSU - CP0St_KSU);
1275 FORCE_RET();
1278 void op_mfc0_intctl (void)
1280 T0 = env->CP0_IntCtl;
1281 FORCE_RET();
1284 void op_mfc0_srsctl (void)
1286 T0 = env->CP0_SRSCtl;
1287 FORCE_RET();
1290 void op_mfc0_srsmap (void)
1292 T0 = env->CP0_SRSMap;
1293 FORCE_RET();
1296 void op_mfc0_cause (void)
1298 T0 = env->CP0_Cause;
1299 FORCE_RET();
1302 void op_mfc0_epc (void)
1304 T0 = (int32_t)env->CP0_EPC;
1305 FORCE_RET();
1308 void op_mfc0_prid (void)
1310 T0 = env->CP0_PRid;
1311 FORCE_RET();
1314 void op_mfc0_ebase (void)
1316 T0 = env->CP0_EBase;
1317 FORCE_RET();
1320 void op_mfc0_config0 (void)
1322 T0 = env->CP0_Config0;
1323 FORCE_RET();
1326 void op_mfc0_config1 (void)
1328 T0 = env->CP0_Config1;
1329 FORCE_RET();
1332 void op_mfc0_config2 (void)
1334 T0 = env->CP0_Config2;
1335 FORCE_RET();
1338 void op_mfc0_config3 (void)
1340 T0 = env->CP0_Config3;
1341 FORCE_RET();
1344 void op_mfc0_config6 (void)
1346 T0 = env->CP0_Config6;
1347 FORCE_RET();
1350 void op_mfc0_config7 (void)
1352 T0 = env->CP0_Config7;
1353 FORCE_RET();
1356 void op_mfc0_lladdr (void)
1358 T0 = (int32_t)env->CP0_LLAddr >> 4;
1359 FORCE_RET();
1362 void op_mfc0_watchlo (void)
1364 T0 = (int32_t)env->CP0_WatchLo[PARAM1];
1365 FORCE_RET();
1368 void op_mfc0_watchhi (void)
1370 T0 = env->CP0_WatchHi[PARAM1];
1371 FORCE_RET();
1374 void op_mfc0_xcontext (void)
1376 T0 = (int32_t)env->CP0_XContext;
1377 FORCE_RET();
1380 void op_mfc0_framemask (void)
1382 T0 = env->CP0_Framemask;
1383 FORCE_RET();
1386 void op_mfc0_debug (void)
1388 T0 = env->CP0_Debug;
1389 if (env->hflags & MIPS_HFLAG_DM)
1390 T0 |= 1 << CP0DB_DM;
1391 FORCE_RET();
1394 void op_mftc0_debug(void)
1396 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1398 /* XXX: Might be wrong, check with EJTAG spec. */
1399 T0 = (env->CP0_Debug & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
1400 (env->CP0_Debug_tcstatus[other_tc] &
1401 ((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
1402 FORCE_RET();
1405 void op_mfc0_depc (void)
1407 T0 = (int32_t)env->CP0_DEPC;
1408 FORCE_RET();
1411 void op_mfc0_performance0 (void)
1413 T0 = env->CP0_Performance0;
1414 FORCE_RET();
1417 void op_mfc0_taglo (void)
1419 T0 = env->CP0_TagLo;
1420 FORCE_RET();
1423 void op_mfc0_datalo (void)
1425 T0 = env->CP0_DataLo;
1426 FORCE_RET();
1429 void op_mfc0_taghi (void)
1431 T0 = env->CP0_TagHi;
1432 FORCE_RET();
1435 void op_mfc0_datahi (void)
1437 T0 = env->CP0_DataHi;
1438 FORCE_RET();
1441 void op_mfc0_errorepc (void)
1443 T0 = (int32_t)env->CP0_ErrorEPC;
1444 FORCE_RET();
1447 void op_mfc0_desave (void)
1449 T0 = env->CP0_DESAVE;
1450 FORCE_RET();
1453 void op_mtc0_index (void)
1455 int num = 1;
1456 unsigned int tmp = env->tlb->nb_tlb;
1458 do {
1459 tmp >>= 1;
1460 num <<= 1;
1461 } while (tmp);
1462 env->CP0_Index = (env->CP0_Index & 0x80000000) | (T0 & (num - 1));
1463 FORCE_RET();
1466 void op_mtc0_mvpcontrol (void)
1468 uint32_t mask = 0;
1469 uint32_t newval;
1471 if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP))
1472 mask |= (1 << CP0MVPCo_CPA) | (1 << CP0MVPCo_VPC) |
1473 (1 << CP0MVPCo_EVP);
1474 if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1475 mask |= (1 << CP0MVPCo_STLB);
1476 newval = (env->mvp->CP0_MVPControl & ~mask) | (T0 & mask);
1478 // TODO: Enable/disable shared TLB, enable/disable VPEs.
1480 env->mvp->CP0_MVPControl = newval;
1481 FORCE_RET();
1484 void op_mtc0_vpecontrol (void)
1486 uint32_t mask;
1487 uint32_t newval;
1489 mask = (1 << CP0VPECo_YSI) | (1 << CP0VPECo_GSI) |
1490 (1 << CP0VPECo_TE) | (0xff << CP0VPECo_TargTC);
1491 newval = (env->CP0_VPEControl & ~mask) | (T0 & mask);
1493 /* Yield scheduler intercept not implemented. */
1494 /* Gating storage scheduler intercept not implemented. */
1496 // TODO: Enable/disable TCs.
1498 env->CP0_VPEControl = newval;
1499 FORCE_RET();
1502 void op_mtc0_vpeconf0 (void)
1504 uint32_t mask = 0;
1505 uint32_t newval;
1507 if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) {
1508 if (env->CP0_VPEConf0 & (1 << CP0VPEC0_VPA))
1509 mask |= (0xff << CP0VPEC0_XTC);
1510 mask |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
1512 newval = (env->CP0_VPEConf0 & ~mask) | (T0 & mask);
1514 // TODO: TC exclusive handling due to ERL/EXL.
1516 env->CP0_VPEConf0 = newval;
1517 FORCE_RET();
1520 void op_mtc0_vpeconf1 (void)
1522 uint32_t mask = 0;
1523 uint32_t newval;
1525 if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1526 mask |= (0xff << CP0VPEC1_NCX) | (0xff << CP0VPEC1_NCP2) |
1527 (0xff << CP0VPEC1_NCP1);
1528 newval = (env->CP0_VPEConf1 & ~mask) | (T0 & mask);
1530 /* UDI not implemented. */
1531 /* CP2 not implemented. */
1533 // TODO: Handle FPU (CP1) binding.
1535 env->CP0_VPEConf1 = newval;
1536 FORCE_RET();
1539 void op_mtc0_yqmask (void)
1541 /* Yield qualifier inputs not implemented. */
1542 env->CP0_YQMask = 0x00000000;
1543 FORCE_RET();
1546 void op_mtc0_vpeschedule (void)
1548 env->CP0_VPESchedule = T0;
1549 FORCE_RET();
1552 void op_mtc0_vpeschefback (void)
1554 env->CP0_VPEScheFBack = T0;
1555 FORCE_RET();
1558 void op_mtc0_vpeopt (void)
1560 env->CP0_VPEOpt = T0 & 0x0000ffff;
1561 FORCE_RET();
1564 void op_mtc0_entrylo0 (void)
1566 /* Large physaddr not implemented */
1567 /* 1k pages not implemented */
1568 env->CP0_EntryLo0 = T0 & 0x3FFFFFFF;
1569 FORCE_RET();
1572 void op_mtc0_tcstatus (void)
1574 uint32_t mask = env->CP0_TCStatus_rw_bitmask;
1575 uint32_t newval;
1577 newval = (env->CP0_TCStatus[env->current_tc] & ~mask) | (T0 & mask);
1579 // TODO: Sync with CP0_Status.
1581 env->CP0_TCStatus[env->current_tc] = newval;
1582 FORCE_RET();
1585 void op_mttc0_tcstatus (void)
1587 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1589 // TODO: Sync with CP0_Status.
1591 env->CP0_TCStatus[other_tc] = T0;
1592 FORCE_RET();
1595 void op_mtc0_tcbind (void)
1597 uint32_t mask = (1 << CP0TCBd_TBE);
1598 uint32_t newval;
1600 if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1601 mask |= (1 << CP0TCBd_CurVPE);
1602 newval = (env->CP0_TCBind[env->current_tc] & ~mask) | (T0 & mask);
1603 env->CP0_TCBind[env->current_tc] = newval;
1604 FORCE_RET();
1607 void op_mttc0_tcbind (void)
1609 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1610 uint32_t mask = (1 << CP0TCBd_TBE);
1611 uint32_t newval;
1613 if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1614 mask |= (1 << CP0TCBd_CurVPE);
1615 newval = (env->CP0_TCBind[other_tc] & ~mask) | (T0 & mask);
1616 env->CP0_TCBind[other_tc] = newval;
1617 FORCE_RET();
1620 void op_mtc0_tcrestart (void)
1622 env->PC[env->current_tc] = T0;
1623 env->CP0_TCStatus[env->current_tc] &= ~(1 << CP0TCSt_TDS);
1624 env->CP0_LLAddr = 0ULL;
1625 /* MIPS16 not implemented. */
1626 FORCE_RET();
1629 void op_mttc0_tcrestart (void)
1631 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1633 env->PC[other_tc] = T0;
1634 env->CP0_TCStatus[other_tc] &= ~(1 << CP0TCSt_TDS);
1635 env->CP0_LLAddr = 0ULL;
1636 /* MIPS16 not implemented. */
1637 FORCE_RET();
1640 void op_mtc0_tchalt (void)
1642 env->CP0_TCHalt[env->current_tc] = T0 & 0x1;
1644 // TODO: Halt TC / Restart (if allocated+active) TC.
1646 FORCE_RET();
1649 void op_mttc0_tchalt (void)
1651 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1653 // TODO: Halt TC / Restart (if allocated+active) TC.
1655 env->CP0_TCHalt[other_tc] = T0;
1656 FORCE_RET();
1659 void op_mtc0_tccontext (void)
1661 env->CP0_TCContext[env->current_tc] = T0;
1662 FORCE_RET();
1665 void op_mttc0_tccontext (void)
1667 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1669 env->CP0_TCContext[other_tc] = T0;
1670 FORCE_RET();
1673 void op_mtc0_tcschedule (void)
1675 env->CP0_TCSchedule[env->current_tc] = T0;
1676 FORCE_RET();
1679 void op_mttc0_tcschedule (void)
1681 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1683 env->CP0_TCSchedule[other_tc] = T0;
1684 FORCE_RET();
1687 void op_mtc0_tcschefback (void)
1689 env->CP0_TCScheFBack[env->current_tc] = T0;
1690 FORCE_RET();
1693 void op_mttc0_tcschefback (void)
1695 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1697 env->CP0_TCScheFBack[other_tc] = T0;
1698 FORCE_RET();
1701 void op_mtc0_entrylo1 (void)
1703 /* Large physaddr not implemented */
1704 /* 1k pages not implemented */
1705 env->CP0_EntryLo1 = T0 & 0x3FFFFFFF;
1706 FORCE_RET();
1709 void op_mtc0_context (void)
1711 env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (T0 & ~0x007FFFFF);
1712 FORCE_RET();
1715 void op_mtc0_pagemask (void)
1717 /* 1k pages not implemented */
1718 env->CP0_PageMask = T0 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
1719 FORCE_RET();
1722 void op_mtc0_pagegrain (void)
1724 /* SmartMIPS not implemented */
1725 /* Large physaddr not implemented */
1726 /* 1k pages not implemented */
1727 env->CP0_PageGrain = 0;
1728 FORCE_RET();
1731 void op_mtc0_wired (void)
1733 env->CP0_Wired = T0 % env->tlb->nb_tlb;
1734 FORCE_RET();
1737 void op_mtc0_srsconf0 (void)
1739 env->CP0_SRSConf0 |= T0 & env->CP0_SRSConf0_rw_bitmask;
1740 FORCE_RET();
1743 void op_mtc0_srsconf1 (void)
1745 env->CP0_SRSConf1 |= T0 & env->CP0_SRSConf1_rw_bitmask;
1746 FORCE_RET();
1749 void op_mtc0_srsconf2 (void)
1751 env->CP0_SRSConf2 |= T0 & env->CP0_SRSConf2_rw_bitmask;
1752 FORCE_RET();
1755 void op_mtc0_srsconf3 (void)
1757 env->CP0_SRSConf3 |= T0 & env->CP0_SRSConf3_rw_bitmask;
1758 FORCE_RET();
1761 void op_mtc0_srsconf4 (void)
1763 env->CP0_SRSConf4 |= T0 & env->CP0_SRSConf4_rw_bitmask;
1764 FORCE_RET();
1767 void op_mtc0_hwrena (void)
1769 env->CP0_HWREna = T0 & 0x0000000F;
1770 FORCE_RET();
1773 void op_mtc0_count (void)
1775 CALL_FROM_TB2(cpu_mips_store_count, env, T0);
1776 FORCE_RET();
1779 void op_mtc0_entryhi (void)
1781 target_ulong old, val;
1783 /* 1k pages not implemented */
1784 val = T0 & ((TARGET_PAGE_MASK << 1) | 0xFF);
1785 #if defined(TARGET_MIPS64)
1786 val &= env->SEGMask;
1787 #endif
1788 old = env->CP0_EntryHi;
1789 env->CP0_EntryHi = val;
1790 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
1791 uint32_t tcst = env->CP0_TCStatus[env->current_tc] & ~0xff;
1792 env->CP0_TCStatus[env->current_tc] = tcst | (val & 0xff);
1794 /* If the ASID changes, flush qemu's TLB. */
1795 if ((old & 0xFF) != (val & 0xFF))
1796 CALL_FROM_TB2(cpu_mips_tlb_flush, env, 1);
1797 FORCE_RET();
1800 void op_mttc0_entryhi(void)
1802 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1804 env->CP0_EntryHi = (env->CP0_EntryHi & 0xff) | (T0 & ~0xff);
1805 env->CP0_TCStatus[other_tc] = (env->CP0_TCStatus[other_tc] & ~0xff) | (T0 & 0xff);
1806 FORCE_RET();
1809 void op_mtc0_compare (void)
1811 CALL_FROM_TB2(cpu_mips_store_compare, env, T0);
1812 FORCE_RET();
1815 void op_mtc0_status (void)
1817 uint32_t val, old;
1818 uint32_t mask = env->CP0_Status_rw_bitmask;
1820 val = T0 & mask;
1821 old = env->CP0_Status;
1822 env->CP0_Status = (env->CP0_Status & ~mask) | val;
1823 CALL_FROM_TB1(compute_hflags, env);
1824 if (loglevel & CPU_LOG_EXEC)
1825 CALL_FROM_TB2(do_mtc0_status_debug, old, val);
1826 CALL_FROM_TB1(cpu_mips_update_irq, env);
1827 FORCE_RET();
1830 void op_mttc0_status(void)
1832 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1833 uint32_t tcstatus = env->CP0_TCStatus[other_tc];
1835 env->CP0_Status = T0 & ~0xf1000018;
1836 tcstatus = (tcstatus & ~(0xf << CP0TCSt_TCU0)) | (T0 & (0xf << CP0St_CU0));
1837 tcstatus = (tcstatus & ~(1 << CP0TCSt_TMX)) | ((T0 & (1 << CP0St_MX)) << (CP0TCSt_TMX - CP0St_MX));
1838 tcstatus = (tcstatus & ~(0x3 << CP0TCSt_TKSU)) | ((T0 & (0x3 << CP0St_KSU)) << (CP0TCSt_TKSU - CP0St_KSU));
1839 env->CP0_TCStatus[other_tc] = tcstatus;
1840 FORCE_RET();
1843 void op_mtc0_intctl (void)
1845 /* vectored interrupts not implemented, no performance counters. */
1846 env->CP0_IntCtl = (env->CP0_IntCtl & ~0x000002e0) | (T0 & 0x000002e0);
1847 FORCE_RET();
1850 void op_mtc0_srsctl (void)
1852 uint32_t mask = (0xf << CP0SRSCtl_ESS) | (0xf << CP0SRSCtl_PSS);
1853 env->CP0_SRSCtl = (env->CP0_SRSCtl & ~mask) | (T0 & mask);
1854 FORCE_RET();
1857 void op_mtc0_srsmap (void)
1859 env->CP0_SRSMap = T0;
1860 FORCE_RET();
1863 void op_mtc0_cause (void)
1865 uint32_t mask = 0x00C00300;
1866 uint32_t old = env->CP0_Cause;
1868 if (env->insn_flags & ISA_MIPS32R2)
1869 mask |= 1 << CP0Ca_DC;
1871 env->CP0_Cause = (env->CP0_Cause & ~mask) | (T0 & mask);
1873 if ((old ^ env->CP0_Cause) & (1 << CP0Ca_DC)) {
1874 if (env->CP0_Cause & (1 << CP0Ca_DC))
1875 CALL_FROM_TB1(cpu_mips_stop_count, env);
1876 else
1877 CALL_FROM_TB1(cpu_mips_start_count, env);
1880 /* Handle the software interrupt as an hardware one, as they
1881 are very similar */
1882 if (T0 & CP0Ca_IP_mask) {
1883 CALL_FROM_TB1(cpu_mips_update_irq, env);
1885 FORCE_RET();
1888 void op_mtc0_epc (void)
1890 env->CP0_EPC = T0;
1891 FORCE_RET();
1894 void op_mtc0_ebase (void)
1896 /* vectored interrupts not implemented */
1897 /* Multi-CPU not implemented */
1898 env->CP0_EBase = 0x80000000 | (T0 & 0x3FFFF000);
1899 FORCE_RET();
1902 void op_mtc0_config0 (void)
1904 env->CP0_Config0 = (env->CP0_Config0 & 0x81FFFFF8) | (T0 & 0x00000007);
1905 FORCE_RET();
1908 void op_mtc0_config2 (void)
1910 /* tertiary/secondary caches not implemented */
1911 env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
1912 FORCE_RET();
1915 void op_mtc0_watchlo (void)
1917 /* Watch exceptions for instructions, data loads, data stores
1918 not implemented. */
1919 env->CP0_WatchLo[PARAM1] = (T0 & ~0x7);
1920 FORCE_RET();
1923 void op_mtc0_watchhi (void)
1925 env->CP0_WatchHi[PARAM1] = (T0 & 0x40FF0FF8);
1926 env->CP0_WatchHi[PARAM1] &= ~(env->CP0_WatchHi[PARAM1] & T0 & 0x7);
1927 FORCE_RET();
1930 void op_mtc0_xcontext (void)
1932 target_ulong mask = (1ULL << (env->SEGBITS - 7)) - 1;
1933 env->CP0_XContext = (env->CP0_XContext & mask) | (T0 & ~mask);
1934 FORCE_RET();
1937 void op_mtc0_framemask (void)
1939 env->CP0_Framemask = T0; /* XXX */
1940 FORCE_RET();
1943 void op_mtc0_debug (void)
1945 env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120);
1946 if (T0 & (1 << CP0DB_DM))
1947 env->hflags |= MIPS_HFLAG_DM;
1948 else
1949 env->hflags &= ~MIPS_HFLAG_DM;
1950 FORCE_RET();
1953 void op_mttc0_debug(void)
1955 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1957 /* XXX: Might be wrong, check with EJTAG spec. */
1958 env->CP0_Debug_tcstatus[other_tc] = T0 & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt));
1959 env->CP0_Debug = (env->CP0_Debug & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
1960 (T0 & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
1961 FORCE_RET();
1964 void op_mtc0_depc (void)
1966 env->CP0_DEPC = T0;
1967 FORCE_RET();
1970 void op_mtc0_performance0 (void)
1972 env->CP0_Performance0 = T0 & 0x000007ff;
1973 FORCE_RET();
1976 void op_mtc0_taglo (void)
1978 env->CP0_TagLo = T0 & 0xFFFFFCF6;
1979 FORCE_RET();
1982 void op_mtc0_datalo (void)
1984 env->CP0_DataLo = T0; /* XXX */
1985 FORCE_RET();
1988 void op_mtc0_taghi (void)
1990 env->CP0_TagHi = T0; /* XXX */
1991 FORCE_RET();
1994 void op_mtc0_datahi (void)
1996 env->CP0_DataHi = T0; /* XXX */
1997 FORCE_RET();
2000 void op_mtc0_errorepc (void)
2002 env->CP0_ErrorEPC = T0;
2003 FORCE_RET();
2006 void op_mtc0_desave (void)
2008 env->CP0_DESAVE = T0;
2009 FORCE_RET();
2012 #if defined(TARGET_MIPS64)
2013 void op_dmfc0_yqmask (void)
2015 T0 = env->CP0_YQMask;
2016 FORCE_RET();
2019 void op_dmfc0_vpeschedule (void)
2021 T0 = env->CP0_VPESchedule;
2022 FORCE_RET();
2025 void op_dmfc0_vpeschefback (void)
2027 T0 = env->CP0_VPEScheFBack;
2028 FORCE_RET();
2031 void op_dmfc0_entrylo0 (void)
2033 T0 = env->CP0_EntryLo0;
2034 FORCE_RET();
2037 void op_dmfc0_tcrestart (void)
2039 T0 = env->PC[env->current_tc];
2040 FORCE_RET();
2043 void op_dmfc0_tchalt (void)
2045 T0 = env->CP0_TCHalt[env->current_tc];
2046 FORCE_RET();
2049 void op_dmfc0_tccontext (void)
2051 T0 = env->CP0_TCContext[env->current_tc];
2052 FORCE_RET();
2055 void op_dmfc0_tcschedule (void)
2057 T0 = env->CP0_TCSchedule[env->current_tc];
2058 FORCE_RET();
2061 void op_dmfc0_tcschefback (void)
2063 T0 = env->CP0_TCScheFBack[env->current_tc];
2064 FORCE_RET();
2067 void op_dmfc0_entrylo1 (void)
2069 T0 = env->CP0_EntryLo1;
2070 FORCE_RET();
2073 void op_dmfc0_context (void)
2075 T0 = env->CP0_Context;
2076 FORCE_RET();
2079 void op_dmfc0_badvaddr (void)
2081 T0 = env->CP0_BadVAddr;
2082 FORCE_RET();
2085 void op_dmfc0_entryhi (void)
2087 T0 = env->CP0_EntryHi;
2088 FORCE_RET();
2091 void op_dmfc0_epc (void)
2093 T0 = env->CP0_EPC;
2094 FORCE_RET();
2097 void op_dmfc0_lladdr (void)
2099 T0 = env->CP0_LLAddr >> 4;
2100 FORCE_RET();
2103 void op_dmfc0_watchlo (void)
2105 T0 = env->CP0_WatchLo[PARAM1];
2106 FORCE_RET();
2109 void op_dmfc0_xcontext (void)
2111 T0 = env->CP0_XContext;
2112 FORCE_RET();
2115 void op_dmfc0_depc (void)
2117 T0 = env->CP0_DEPC;
2118 FORCE_RET();
2121 void op_dmfc0_errorepc (void)
2123 T0 = env->CP0_ErrorEPC;
2124 FORCE_RET();
2126 #endif /* TARGET_MIPS64 */
2128 /* MIPS MT functions */
2129 void op_mftgpr(void)
2131 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2133 T0 = env->gpr[PARAM1][other_tc];
2134 FORCE_RET();
2137 void op_mftlo(void)
2139 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2141 T0 = env->LO[PARAM1][other_tc];
2142 FORCE_RET();
2145 void op_mfthi(void)
2147 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2149 T0 = env->HI[PARAM1][other_tc];
2150 FORCE_RET();
2153 void op_mftacx(void)
2155 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2157 T0 = env->ACX[PARAM1][other_tc];
2158 FORCE_RET();
2161 void op_mftdsp(void)
2163 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2165 T0 = env->DSPControl[other_tc];
2166 FORCE_RET();
2169 void op_mttgpr(void)
2171 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2173 T0 = env->gpr[PARAM1][other_tc];
2174 FORCE_RET();
2177 void op_mttlo(void)
2179 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2181 T0 = env->LO[PARAM1][other_tc];
2182 FORCE_RET();
2185 void op_mtthi(void)
2187 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2189 T0 = env->HI[PARAM1][other_tc];
2190 FORCE_RET();
2193 void op_mttacx(void)
2195 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2197 T0 = env->ACX[PARAM1][other_tc];
2198 FORCE_RET();
2201 void op_mttdsp(void)
2203 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2205 T0 = env->DSPControl[other_tc];
2206 FORCE_RET();
2210 void op_dmt(void)
2212 // TODO
2213 T0 = 0;
2214 // rt = T0
2215 FORCE_RET();
2218 void op_emt(void)
2220 // TODO
2221 T0 = 0;
2222 // rt = T0
2223 FORCE_RET();
2226 void op_dvpe(void)
2228 // TODO
2229 T0 = 0;
2230 // rt = T0
2231 FORCE_RET();
2234 void op_evpe(void)
2236 // TODO
2237 T0 = 0;
2238 // rt = T0
2239 FORCE_RET();
2242 void op_fork(void)
2244 // T0 = rt, T1 = rs
2245 T0 = 0;
2246 // TODO: store to TC register
2247 FORCE_RET();
2250 void op_yield(void)
2252 if (T0 < 0) {
2253 /* No scheduling policy implemented. */
2254 if (T0 != -2) {
2255 if (env->CP0_VPEControl & (1 << CP0VPECo_YSI) &&
2256 env->CP0_TCStatus[env->current_tc] & (1 << CP0TCSt_DT)) {
2257 env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
2258 env->CP0_VPEControl |= 4 << CP0VPECo_EXCPT;
2259 CALL_FROM_TB1(do_raise_exception, EXCP_THREAD);
2262 } else if (T0 == 0) {
2263 if (0 /* TODO: TC underflow */) {
2264 env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
2265 CALL_FROM_TB1(do_raise_exception, EXCP_THREAD);
2266 } else {
2267 // TODO: Deallocate TC
2269 } else if (T0 > 0) {
2270 /* Yield qualifier inputs not implemented. */
2271 env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
2272 env->CP0_VPEControl |= 2 << CP0VPECo_EXCPT;
2273 CALL_FROM_TB1(do_raise_exception, EXCP_THREAD);
2275 T0 = env->CP0_YQMask;
2276 FORCE_RET();
2279 /* CP1 functions */
2280 #if 0
2281 # define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env)
2282 #else
2283 # define DEBUG_FPU_STATE() do { } while(0)
2284 #endif
2286 void op_cfc1 (void)
2288 CALL_FROM_TB1(do_cfc1, PARAM1);
2289 DEBUG_FPU_STATE();
2290 FORCE_RET();
2293 void op_ctc1 (void)
2295 CALL_FROM_TB1(do_ctc1, PARAM1);
2296 DEBUG_FPU_STATE();
2297 FORCE_RET();
2300 void op_mfc1 (void)
2302 T0 = (int32_t)WT0;
2303 DEBUG_FPU_STATE();
2304 FORCE_RET();
2307 void op_mtc1 (void)
2309 WT0 = T0;
2310 DEBUG_FPU_STATE();
2311 FORCE_RET();
2314 void op_dmfc1 (void)
2316 T0 = DT0;
2317 DEBUG_FPU_STATE();
2318 FORCE_RET();
2321 void op_dmtc1 (void)
2323 DT0 = T0;
2324 DEBUG_FPU_STATE();
2325 FORCE_RET();
2328 void op_mfhc1 (void)
2330 T0 = (int32_t)WTH0;
2331 DEBUG_FPU_STATE();
2332 FORCE_RET();
2335 void op_mthc1 (void)
2337 WTH0 = T0;
2338 DEBUG_FPU_STATE();
2339 FORCE_RET();
2342 /* Float support.
2343 Single precition routines have a "s" suffix, double precision a
2344 "d" suffix, 32bit integer "w", 64bit integer "l", paired singe "ps",
2345 paired single lowwer "pl", paired single upper "pu". */
2347 #define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void)
2349 FLOAT_OP(cvtd, s)
2351 CALL_FROM_TB0(do_float_cvtd_s);
2352 DEBUG_FPU_STATE();
2353 FORCE_RET();
2355 FLOAT_OP(cvtd, w)
2357 CALL_FROM_TB0(do_float_cvtd_w);
2358 DEBUG_FPU_STATE();
2359 FORCE_RET();
2361 FLOAT_OP(cvtd, l)
2363 CALL_FROM_TB0(do_float_cvtd_l);
2364 DEBUG_FPU_STATE();
2365 FORCE_RET();
2367 FLOAT_OP(cvtl, d)
2369 CALL_FROM_TB0(do_float_cvtl_d);
2370 DEBUG_FPU_STATE();
2371 FORCE_RET();
2373 FLOAT_OP(cvtl, s)
2375 CALL_FROM_TB0(do_float_cvtl_s);
2376 DEBUG_FPU_STATE();
2377 FORCE_RET();
2379 FLOAT_OP(cvtps, s)
2381 WT2 = WT0;
2382 WTH2 = WT1;
2383 DEBUG_FPU_STATE();
2384 FORCE_RET();
2386 FLOAT_OP(cvtps, pw)
2388 CALL_FROM_TB0(do_float_cvtps_pw);
2389 DEBUG_FPU_STATE();
2390 FORCE_RET();
2392 FLOAT_OP(cvtpw, ps)
2394 CALL_FROM_TB0(do_float_cvtpw_ps);
2395 DEBUG_FPU_STATE();
2396 FORCE_RET();
2398 FLOAT_OP(cvts, d)
2400 CALL_FROM_TB0(do_float_cvts_d);
2401 DEBUG_FPU_STATE();
2402 FORCE_RET();
2404 FLOAT_OP(cvts, w)
2406 CALL_FROM_TB0(do_float_cvts_w);
2407 DEBUG_FPU_STATE();
2408 FORCE_RET();
2410 FLOAT_OP(cvts, l)
2412 CALL_FROM_TB0(do_float_cvts_l);
2413 DEBUG_FPU_STATE();
2414 FORCE_RET();
2416 FLOAT_OP(cvts, pl)
2418 CALL_FROM_TB0(do_float_cvts_pl);
2419 DEBUG_FPU_STATE();
2420 FORCE_RET();
2422 FLOAT_OP(cvts, pu)
2424 CALL_FROM_TB0(do_float_cvts_pu);
2425 DEBUG_FPU_STATE();
2426 FORCE_RET();
2428 FLOAT_OP(cvtw, s)
2430 CALL_FROM_TB0(do_float_cvtw_s);
2431 DEBUG_FPU_STATE();
2432 FORCE_RET();
2434 FLOAT_OP(cvtw, d)
2436 CALL_FROM_TB0(do_float_cvtw_d);
2437 DEBUG_FPU_STATE();
2438 FORCE_RET();
2441 FLOAT_OP(pll, ps)
2443 DT2 = ((uint64_t)WT0 << 32) | WT1;
2444 DEBUG_FPU_STATE();
2445 FORCE_RET();
2447 FLOAT_OP(plu, ps)
2449 DT2 = ((uint64_t)WT0 << 32) | WTH1;
2450 DEBUG_FPU_STATE();
2451 FORCE_RET();
2453 FLOAT_OP(pul, ps)
2455 DT2 = ((uint64_t)WTH0 << 32) | WT1;
2456 DEBUG_FPU_STATE();
2457 FORCE_RET();
2459 FLOAT_OP(puu, ps)
2461 DT2 = ((uint64_t)WTH0 << 32) | WTH1;
2462 DEBUG_FPU_STATE();
2463 FORCE_RET();
2466 #define FLOAT_ROUNDOP(op, ttype, stype) \
2467 FLOAT_OP(op ## ttype, stype) \
2469 CALL_FROM_TB0(do_float_ ## op ## ttype ## _ ## stype); \
2470 DEBUG_FPU_STATE(); \
2471 FORCE_RET(); \
2474 FLOAT_ROUNDOP(round, l, d)
2475 FLOAT_ROUNDOP(round, l, s)
2476 FLOAT_ROUNDOP(round, w, d)
2477 FLOAT_ROUNDOP(round, w, s)
2479 FLOAT_ROUNDOP(trunc, l, d)
2480 FLOAT_ROUNDOP(trunc, l, s)
2481 FLOAT_ROUNDOP(trunc, w, d)
2482 FLOAT_ROUNDOP(trunc, w, s)
2484 FLOAT_ROUNDOP(ceil, l, d)
2485 FLOAT_ROUNDOP(ceil, l, s)
2486 FLOAT_ROUNDOP(ceil, w, d)
2487 FLOAT_ROUNDOP(ceil, w, s)
2489 FLOAT_ROUNDOP(floor, l, d)
2490 FLOAT_ROUNDOP(floor, l, s)
2491 FLOAT_ROUNDOP(floor, w, d)
2492 FLOAT_ROUNDOP(floor, w, s)
2493 #undef FLOAR_ROUNDOP
2495 FLOAT_OP(movf, d)
2497 if (!(env->fpu->fcr31 & PARAM1))
2498 DT2 = DT0;
2499 DEBUG_FPU_STATE();
2500 FORCE_RET();
2502 FLOAT_OP(movf, s)
2504 if (!(env->fpu->fcr31 & PARAM1))
2505 WT2 = WT0;
2506 DEBUG_FPU_STATE();
2507 FORCE_RET();
2509 FLOAT_OP(movf, ps)
2511 if (!(env->fpu->fcr31 & PARAM1)) {
2512 WT2 = WT0;
2513 WTH2 = WTH0;
2515 DEBUG_FPU_STATE();
2516 FORCE_RET();
2518 FLOAT_OP(movt, d)
2520 if (env->fpu->fcr31 & PARAM1)
2521 DT2 = DT0;
2522 DEBUG_FPU_STATE();
2523 FORCE_RET();
2525 FLOAT_OP(movt, s)
2527 if (env->fpu->fcr31 & PARAM1)
2528 WT2 = WT0;
2529 DEBUG_FPU_STATE();
2530 FORCE_RET();
2532 FLOAT_OP(movt, ps)
2534 if (env->fpu->fcr31 & PARAM1) {
2535 WT2 = WT0;
2536 WTH2 = WTH0;
2538 DEBUG_FPU_STATE();
2539 FORCE_RET();
2541 FLOAT_OP(movz, d)
2543 if (!T0)
2544 DT2 = DT0;
2545 DEBUG_FPU_STATE();
2546 FORCE_RET();
2548 FLOAT_OP(movz, s)
2550 if (!T0)
2551 WT2 = WT0;
2552 DEBUG_FPU_STATE();
2553 FORCE_RET();
2555 FLOAT_OP(movz, ps)
2557 if (!T0) {
2558 WT2 = WT0;
2559 WTH2 = WTH0;
2561 DEBUG_FPU_STATE();
2562 FORCE_RET();
2564 FLOAT_OP(movn, d)
2566 if (T0)
2567 DT2 = DT0;
2568 DEBUG_FPU_STATE();
2569 FORCE_RET();
2571 FLOAT_OP(movn, s)
2573 if (T0)
2574 WT2 = WT0;
2575 DEBUG_FPU_STATE();
2576 FORCE_RET();
2578 FLOAT_OP(movn, ps)
2580 if (T0) {
2581 WT2 = WT0;
2582 WTH2 = WTH0;
2584 DEBUG_FPU_STATE();
2585 FORCE_RET();
2588 /* operations calling helpers, for s, d and ps */
2589 #define FLOAT_HOP(name) \
2590 FLOAT_OP(name, d) \
2592 CALL_FROM_TB0(do_float_ ## name ## _d); \
2593 DEBUG_FPU_STATE(); \
2594 FORCE_RET(); \
2596 FLOAT_OP(name, s) \
2598 CALL_FROM_TB0(do_float_ ## name ## _s); \
2599 DEBUG_FPU_STATE(); \
2600 FORCE_RET(); \
2602 FLOAT_OP(name, ps) \
2604 CALL_FROM_TB0(do_float_ ## name ## _ps); \
2605 DEBUG_FPU_STATE(); \
2606 FORCE_RET(); \
2608 FLOAT_HOP(add)
2609 FLOAT_HOP(sub)
2610 FLOAT_HOP(mul)
2611 FLOAT_HOP(div)
2612 FLOAT_HOP(recip2)
2613 FLOAT_HOP(rsqrt2)
2614 FLOAT_HOP(rsqrt1)
2615 FLOAT_HOP(recip1)
2616 #undef FLOAT_HOP
2618 /* operations calling helpers, for s and d */
2619 #define FLOAT_HOP(name) \
2620 FLOAT_OP(name, d) \
2622 CALL_FROM_TB0(do_float_ ## name ## _d); \
2623 DEBUG_FPU_STATE(); \
2624 FORCE_RET(); \
2626 FLOAT_OP(name, s) \
2628 CALL_FROM_TB0(do_float_ ## name ## _s); \
2629 DEBUG_FPU_STATE(); \
2630 FORCE_RET(); \
2632 FLOAT_HOP(rsqrt)
2633 FLOAT_HOP(recip)
2634 #undef FLOAT_HOP
2636 /* operations calling helpers, for ps */
2637 #define FLOAT_HOP(name) \
2638 FLOAT_OP(name, ps) \
2640 CALL_FROM_TB0(do_float_ ## name ## _ps); \
2641 DEBUG_FPU_STATE(); \
2642 FORCE_RET(); \
2644 FLOAT_HOP(addr)
2645 FLOAT_HOP(mulr)
2646 #undef FLOAT_HOP
2648 /* ternary operations */
2649 #define FLOAT_TERNOP(name1, name2) \
2650 FLOAT_OP(name1 ## name2, d) \
2652 FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status); \
2653 FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status); \
2654 DEBUG_FPU_STATE(); \
2655 FORCE_RET(); \
2657 FLOAT_OP(name1 ## name2, s) \
2659 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
2660 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
2661 DEBUG_FPU_STATE(); \
2662 FORCE_RET(); \
2664 FLOAT_OP(name1 ## name2, ps) \
2666 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
2667 FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \
2668 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
2669 FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \
2670 DEBUG_FPU_STATE(); \
2671 FORCE_RET(); \
2673 FLOAT_TERNOP(mul, add)
2674 FLOAT_TERNOP(mul, sub)
2675 #undef FLOAT_TERNOP
2677 /* negated ternary operations */
2678 #define FLOAT_NTERNOP(name1, name2) \
2679 FLOAT_OP(n ## name1 ## name2, d) \
2681 FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status); \
2682 FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status); \
2683 FDT2 = float64_chs(FDT2); \
2684 DEBUG_FPU_STATE(); \
2685 FORCE_RET(); \
2687 FLOAT_OP(n ## name1 ## name2, s) \
2689 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
2690 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
2691 FST2 = float32_chs(FST2); \
2692 DEBUG_FPU_STATE(); \
2693 FORCE_RET(); \
2695 FLOAT_OP(n ## name1 ## name2, ps) \
2697 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
2698 FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \
2699 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
2700 FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \
2701 FST2 = float32_chs(FST2); \
2702 FSTH2 = float32_chs(FSTH2); \
2703 DEBUG_FPU_STATE(); \
2704 FORCE_RET(); \
2706 FLOAT_NTERNOP(mul, add)
2707 FLOAT_NTERNOP(mul, sub)
2708 #undef FLOAT_NTERNOP
2710 /* unary operations, modifying fp status */
2711 #define FLOAT_UNOP(name) \
2712 FLOAT_OP(name, d) \
2714 FDT2 = float64_ ## name(FDT0, &env->fpu->fp_status); \
2715 DEBUG_FPU_STATE(); \
2716 FORCE_RET(); \
2718 FLOAT_OP(name, s) \
2720 FST2 = float32_ ## name(FST0, &env->fpu->fp_status); \
2721 DEBUG_FPU_STATE(); \
2722 FORCE_RET(); \
2724 FLOAT_UNOP(sqrt)
2725 #undef FLOAT_UNOP
2727 /* unary operations, not modifying fp status */
2728 #define FLOAT_UNOP(name) \
2729 FLOAT_OP(name, d) \
2731 FDT2 = float64_ ## name(FDT0); \
2732 DEBUG_FPU_STATE(); \
2733 FORCE_RET(); \
2735 FLOAT_OP(name, s) \
2737 FST2 = float32_ ## name(FST0); \
2738 DEBUG_FPU_STATE(); \
2739 FORCE_RET(); \
2741 FLOAT_OP(name, ps) \
2743 FST2 = float32_ ## name(FST0); \
2744 FSTH2 = float32_ ## name(FSTH0); \
2745 DEBUG_FPU_STATE(); \
2746 FORCE_RET(); \
2748 FLOAT_UNOP(abs)
2749 FLOAT_UNOP(chs)
2750 #undef FLOAT_UNOP
2752 FLOAT_OP(mov, d)
2754 FDT2 = FDT0;
2755 DEBUG_FPU_STATE();
2756 FORCE_RET();
2758 FLOAT_OP(mov, s)
2760 FST2 = FST0;
2761 DEBUG_FPU_STATE();
2762 FORCE_RET();
2764 FLOAT_OP(mov, ps)
2766 FST2 = FST0;
2767 FSTH2 = FSTH0;
2768 DEBUG_FPU_STATE();
2769 FORCE_RET();
2771 FLOAT_OP(alnv, ps)
2773 switch (T0 & 0x7) {
2774 case 0:
2775 FST2 = FST0;
2776 FSTH2 = FSTH0;
2777 break;
2778 case 4:
2779 #ifdef TARGET_WORDS_BIGENDIAN
2780 FSTH2 = FST0;
2781 FST2 = FSTH1;
2782 #else
2783 FSTH2 = FST1;
2784 FST2 = FSTH0;
2785 #endif
2786 break;
2787 default: /* unpredictable */
2788 break;
2790 DEBUG_FPU_STATE();
2791 FORCE_RET();
2794 #ifdef CONFIG_SOFTFLOAT
2795 #define clear_invalid() do { \
2796 int flags = get_float_exception_flags(&env->fpu->fp_status); \
2797 flags &= ~float_flag_invalid; \
2798 set_float_exception_flags(flags, &env->fpu->fp_status); \
2799 } while(0)
2800 #else
2801 #define clear_invalid() do { } while(0)
2802 #endif
2804 extern void dump_fpu_s(CPUState *env);
2806 #define CMP_OP(fmt, op) \
2807 void OPPROTO op_cmp ## _ ## fmt ## _ ## op(void) \
2809 CALL_FROM_TB1(do_cmp ## _ ## fmt ## _ ## op, PARAM1); \
2810 DEBUG_FPU_STATE(); \
2811 FORCE_RET(); \
2813 void OPPROTO op_cmpabs ## _ ## fmt ## _ ## op(void) \
2815 CALL_FROM_TB1(do_cmpabs ## _ ## fmt ## _ ## op, PARAM1); \
2816 DEBUG_FPU_STATE(); \
2817 FORCE_RET(); \
2819 #define CMP_OPS(op) \
2820 CMP_OP(d, op) \
2821 CMP_OP(s, op) \
2822 CMP_OP(ps, op)
2824 CMP_OPS(f)
2825 CMP_OPS(un)
2826 CMP_OPS(eq)
2827 CMP_OPS(ueq)
2828 CMP_OPS(olt)
2829 CMP_OPS(ult)
2830 CMP_OPS(ole)
2831 CMP_OPS(ule)
2832 CMP_OPS(sf)
2833 CMP_OPS(ngle)
2834 CMP_OPS(seq)
2835 CMP_OPS(ngl)
2836 CMP_OPS(lt)
2837 CMP_OPS(nge)
2838 CMP_OPS(le)
2839 CMP_OPS(ngt)
2840 #undef CMP_OPS
2841 #undef CMP_OP
2843 void op_bc1f (void)
2845 T0 = !!(~GET_FP_COND(env->fpu) & (0x1 << PARAM1));
2846 DEBUG_FPU_STATE();
2847 FORCE_RET();
2849 void op_bc1any2f (void)
2851 T0 = !!(~GET_FP_COND(env->fpu) & (0x3 << PARAM1));
2852 DEBUG_FPU_STATE();
2853 FORCE_RET();
2855 void op_bc1any4f (void)
2857 T0 = !!(~GET_FP_COND(env->fpu) & (0xf << PARAM1));
2858 DEBUG_FPU_STATE();
2859 FORCE_RET();
2862 void op_bc1t (void)
2864 T0 = !!(GET_FP_COND(env->fpu) & (0x1 << PARAM1));
2865 DEBUG_FPU_STATE();
2866 FORCE_RET();
2868 void op_bc1any2t (void)
2870 T0 = !!(GET_FP_COND(env->fpu) & (0x3 << PARAM1));
2871 DEBUG_FPU_STATE();
2872 FORCE_RET();
2874 void op_bc1any4t (void)
2876 T0 = !!(GET_FP_COND(env->fpu) & (0xf << PARAM1));
2877 DEBUG_FPU_STATE();
2878 FORCE_RET();
2881 void op_tlbwi (void)
2883 CALL_FROM_TB0(env->tlb->do_tlbwi);
2884 FORCE_RET();
2887 void op_tlbwr (void)
2889 CALL_FROM_TB0(env->tlb->do_tlbwr);
2890 FORCE_RET();
2893 void op_tlbp (void)
2895 CALL_FROM_TB0(env->tlb->do_tlbp);
2896 FORCE_RET();
2899 void op_tlbr (void)
2901 CALL_FROM_TB0(env->tlb->do_tlbr);
2902 FORCE_RET();
2905 /* Specials */
2906 #if defined (CONFIG_USER_ONLY)
2907 void op_tls_value (void)
2909 T0 = env->tls_value;
2911 #endif
2913 void op_pmon (void)
2915 CALL_FROM_TB1(do_pmon, PARAM1);
2916 FORCE_RET();
2919 void op_di (void)
2921 T0 = env->CP0_Status;
2922 env->CP0_Status = T0 & ~(1 << CP0St_IE);
2923 CALL_FROM_TB1(cpu_mips_update_irq, env);
2924 FORCE_RET();
2927 void op_ei (void)
2929 T0 = env->CP0_Status;
2930 env->CP0_Status = T0 | (1 << CP0St_IE);
2931 CALL_FROM_TB1(cpu_mips_update_irq, env);
2932 FORCE_RET();
2935 void op_trap (void)
2937 if (T0) {
2938 CALL_FROM_TB1(do_raise_exception, EXCP_TRAP);
2940 FORCE_RET();
2943 void op_debug (void)
2945 CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG);
2946 FORCE_RET();
2949 void op_set_lladdr (void)
2951 env->CP0_LLAddr = T2;
2952 FORCE_RET();
2955 void debug_pre_eret (void);
2956 void debug_post_eret (void);
2957 void op_eret (void)
2959 if (loglevel & CPU_LOG_EXEC)
2960 CALL_FROM_TB0(debug_pre_eret);
2961 if (env->CP0_Status & (1 << CP0St_ERL)) {
2962 env->PC[env->current_tc] = env->CP0_ErrorEPC;
2963 env->CP0_Status &= ~(1 << CP0St_ERL);
2964 } else {
2965 env->PC[env->current_tc] = env->CP0_EPC;
2966 env->CP0_Status &= ~(1 << CP0St_EXL);
2968 CALL_FROM_TB1(compute_hflags, env);
2969 if (loglevel & CPU_LOG_EXEC)
2970 CALL_FROM_TB0(debug_post_eret);
2971 env->CP0_LLAddr = 1;
2972 FORCE_RET();
2975 void op_deret (void)
2977 if (loglevel & CPU_LOG_EXEC)
2978 CALL_FROM_TB0(debug_pre_eret);
2979 env->PC[env->current_tc] = env->CP0_DEPC;
2980 env->hflags &= MIPS_HFLAG_DM;
2981 CALL_FROM_TB1(compute_hflags, env);
2982 if (loglevel & CPU_LOG_EXEC)
2983 CALL_FROM_TB0(debug_post_eret);
2984 env->CP0_LLAddr = 1;
2985 FORCE_RET();
2988 void op_rdhwr_cpunum(void)
2990 if ((env->hflags & MIPS_HFLAG_CP0) ||
2991 (env->CP0_HWREna & (1 << 0)))
2992 T0 = env->CP0_EBase & 0x3ff;
2993 else
2994 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
2995 FORCE_RET();
2998 void op_rdhwr_synci_step(void)
3000 if ((env->hflags & MIPS_HFLAG_CP0) ||
3001 (env->CP0_HWREna & (1 << 1)))
3002 T0 = env->SYNCI_Step;
3003 else
3004 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
3005 FORCE_RET();
3008 void op_rdhwr_cc(void)
3010 if ((env->hflags & MIPS_HFLAG_CP0) ||
3011 (env->CP0_HWREna & (1 << 2)))
3012 T0 = env->CP0_Count;
3013 else
3014 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
3015 FORCE_RET();
3018 void op_rdhwr_ccres(void)
3020 if ((env->hflags & MIPS_HFLAG_CP0) ||
3021 (env->CP0_HWREna & (1 << 3)))
3022 T0 = env->CCRes;
3023 else
3024 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
3025 FORCE_RET();
3028 void op_save_state (void)
3030 env->hflags = PARAM1;
3031 FORCE_RET();
3034 void op_save_pc (void)
3036 env->PC[env->current_tc] = PARAM1;
3037 FORCE_RET();
3040 #if defined(TARGET_MIPS64)
3041 void op_save_pc64 (void)
3043 env->PC[env->current_tc] = ((uint64_t)PARAM1 << 32) | (uint32_t)PARAM2;
3044 FORCE_RET();
3046 #endif
3048 void op_interrupt_restart (void)
3050 if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
3051 !(env->CP0_Status & (1 << CP0St_ERL)) &&
3052 !(env->hflags & MIPS_HFLAG_DM) &&
3053 (env->CP0_Status & (1 << CP0St_IE)) &&
3054 (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask)) {
3055 env->CP0_Cause &= ~(0x1f << CP0Ca_EC);
3056 CALL_FROM_TB1(do_raise_exception, EXCP_EXT_INTERRUPT);
3058 FORCE_RET();
3061 void op_raise_exception (void)
3063 CALL_FROM_TB1(do_raise_exception, PARAM1);
3064 FORCE_RET();
3067 void op_raise_exception_err (void)
3069 CALL_FROM_TB2(do_raise_exception_err, PARAM1, PARAM2);
3070 FORCE_RET();
3073 void op_exit_tb (void)
3075 EXIT_TB();
3076 FORCE_RET();
3079 void op_wait (void)
3081 env->halted = 1;
3082 CALL_FROM_TB1(do_raise_exception, EXCP_HLT);
3083 FORCE_RET();
3086 /* Bitfield operations. */
3087 void op_ext(void)
3089 unsigned int pos = PARAM1;
3090 unsigned int size = PARAM2;
3092 T0 = (int32_t)((T1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0));
3093 FORCE_RET();
3096 void op_ins(void)
3098 unsigned int pos = PARAM1;
3099 unsigned int size = PARAM2;
3100 target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos;
3102 T0 = (int32_t)((T0 & ~mask) | ((T1 << pos) & mask));
3103 FORCE_RET();
3106 void op_wsbh(void)
3108 T0 = (int32_t)(((T1 << 8) & ~0x00FF00FF) | ((T1 >> 8) & 0x00FF00FF));
3109 FORCE_RET();
3112 #if defined(TARGET_MIPS64)
3113 void op_dext(void)
3115 unsigned int pos = PARAM1;
3116 unsigned int size = PARAM2;
3118 T0 = (T1 >> pos) & ((size < 64) ? ((1ULL << size) - 1) : ~0ULL);
3119 FORCE_RET();
3122 void op_dins(void)
3124 unsigned int pos = PARAM1;
3125 unsigned int size = PARAM2;
3126 target_ulong mask = ((size < 64) ? ((1ULL << size) - 1) : ~0ULL) << pos;
3128 T0 = (T0 & ~mask) | ((T1 << pos) & mask);
3129 FORCE_RET();
3132 void op_dsbh(void)
3134 T0 = ((T1 << 8) & ~0x00FF00FF00FF00FFULL) | ((T1 >> 8) & 0x00FF00FF00FF00FFULL);
3135 FORCE_RET();
3138 void op_dshd(void)
3140 T1 = ((T1 << 16) & ~0x0000FFFF0000FFFFULL) | ((T1 >> 16) & 0x0000FFFF0000FFFFULL);
3141 T0 = (T1 << 32) | (T1 >> 32);
3142 FORCE_RET();
3144 #endif
3146 void op_seb(void)
3148 T0 = ((T1 & 0xFF) ^ 0x80) - 0x80;
3149 FORCE_RET();
3152 void op_seh(void)
3154 T0 = ((T1 & 0xFFFF) ^ 0x8000) - 0x8000;
3155 FORCE_RET();