use the TCG code generator
[sdk/emulator/qemu.git] / target-mips / op.c
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)
7  *
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.
12  *
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.
17  *
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
21  */
22
23 #include "config.h"
24 #include "exec.h"
25 #include "host-utils.h"
26
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
50
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
144
145 #define TN
146 #include "op_template.c"
147 #undef TN
148
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
245
246 #define FTN
247 #include "fop_template.c"
248 #undef FTN
249
250 void op_dup_T0 (void)
251 {
252     T2 = T0;
253     FORCE_RET();
254 }
255
256 void op_load_HI (void)
257 {
258     T0 = env->HI[PARAM1][env->current_tc];
259     FORCE_RET();
260 }
261
262 void op_store_HI (void)
263 {
264     env->HI[PARAM1][env->current_tc] = T0;
265     FORCE_RET();
266 }
267
268 void op_load_LO (void)
269 {
270     T0 = env->LO[PARAM1][env->current_tc];
271     FORCE_RET();
272 }
273
274 void op_store_LO (void)
275 {
276     env->LO[PARAM1][env->current_tc] = T0;
277     FORCE_RET();
278 }
279
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
288
289 #define MEMSUFFIX _super
290 #include "op_mem.c"
291 #undef MEMSUFFIX
292
293 #define MEMSUFFIX _kernel
294 #include "op_mem.c"
295 #undef MEMSUFFIX
296 #endif
297
298 /* Addresses computation */
299 void op_addr_add (void)
300 {
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();
312 }
313
314 /* Arithmetic */
315 void op_add (void)
316 {
317     T0 = (int32_t)((int32_t)T0 + (int32_t)T1);
318     FORCE_RET();
319 }
320
321 void op_addo (void)
322 {
323     target_ulong tmp;
324
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);
330     }
331     T0 = (int32_t)T0;
332     FORCE_RET();
333 }
334
335 void op_sub (void)
336 {
337     T0 = (int32_t)((int32_t)T0 - (int32_t)T1);
338     FORCE_RET();
339 }
340
341 void op_subo (void)
342 {
343     target_ulong tmp;
344
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);
350     }
351     T0 = (int32_t)T0;
352     FORCE_RET();
353 }
354
355 void op_mul (void)
356 {
357     T0 = (int32_t)((int32_t)T0 * (int32_t)T1);
358     FORCE_RET();
359 }
360
361 #if HOST_LONG_BITS < 64
362 void op_div (void)
363 {
364     CALL_FROM_TB0(do_div);
365     FORCE_RET();
366 }
367 #else
368 void op_div (void)
369 {
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);
373     }
374     FORCE_RET();
375 }
376 #endif
377
378 void op_divu (void)
379 {
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);
383     }
384     FORCE_RET();
385 }
386
387 #if defined(TARGET_MIPS64)
388 /* Arithmetic */
389 void op_dadd (void)
390 {
391     T0 += T1;
392     FORCE_RET();
393 }
394
395 void op_daddo (void)
396 {
397     target_long tmp;
398
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);
404     }
405     FORCE_RET();
406 }
407
408 void op_dsub (void)
409 {
410     T0 -= T1;
411     FORCE_RET();
412 }
413
414 void op_dsubo (void)
415 {
416     target_long tmp;
417
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);
423     }
424     FORCE_RET();
425 }
426
427 void op_dmul (void)
428 {
429     T0 = (int64_t)T0 * (int64_t)T1;
430     FORCE_RET();
431 }
432
433 /* Those might call libgcc functions.  */
434 void op_ddiv (void)
435 {
436     do_ddiv();
437     FORCE_RET();
438 }
439
440 #if TARGET_LONG_BITS > HOST_LONG_BITS
441 void op_ddivu (void)
442 {
443     do_ddivu();
444     FORCE_RET();
445 }
446 #else
447 void op_ddivu (void)
448 {
449     if (T1 != 0) {
450         env->LO[0][env->current_tc] = T0 / T1;
451         env->HI[0][env->current_tc] = T0 % T1;
452     }
453     FORCE_RET();
454 }
455 #endif
456 #endif /* TARGET_MIPS64 */
457
458 /* Logical */
459 void op_and (void)
460 {
461     T0 &= T1;
462     FORCE_RET();
463 }
464
465 void op_nor (void)
466 {
467     T0 = ~(T0 | T1);
468     FORCE_RET();
469 }
470
471 void op_or (void)
472 {
473     T0 |= T1;
474     FORCE_RET();
475 }
476
477 void op_xor (void)
478 {
479     T0 ^= T1;
480     FORCE_RET();
481 }
482
483 void op_sll (void)
484 {
485     T0 = (int32_t)((uint32_t)T0 << T1);
486     FORCE_RET();
487 }
488
489 void op_sra (void)
490 {
491     T0 = (int32_t)((int32_t)T0 >> T1);
492     FORCE_RET();
493 }
494
495 void op_srl (void)
496 {
497     T0 = (int32_t)((uint32_t)T0 >> T1);
498     FORCE_RET();
499 }
500
501 void op_rotr (void)
502 {
503     target_ulong tmp;
504
505     if (T1) {
506        tmp = (int32_t)((uint32_t)T0 << (0x20 - T1));
507        T0 = (int32_t)((uint32_t)T0 >> T1) | tmp;
508     }
509     FORCE_RET();
510 }
511
512 void op_sllv (void)
513 {
514     T0 = (int32_t)((uint32_t)T1 << ((uint32_t)T0 & 0x1F));
515     FORCE_RET();
516 }
517
518 void op_srav (void)
519 {
520     T0 = (int32_t)((int32_t)T1 >> (T0 & 0x1F));
521     FORCE_RET();
522 }
523
524 void op_srlv (void)
525 {
526     T0 = (int32_t)((uint32_t)T1 >> (T0 & 0x1F));
527     FORCE_RET();
528 }
529
530 void op_rotrv (void)
531 {
532     target_ulong tmp;
533
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();
541 }
542
543 void op_clo (void)
544 {
545     T0 = clo32(T0);
546     FORCE_RET();
547 }
548
549 void op_clz (void)
550 {
551     T0 = clz32(T0);
552     FORCE_RET();
553 }
554
555 #if defined(TARGET_MIPS64)
556
557 #if TARGET_LONG_BITS > HOST_LONG_BITS
558 /* Those might call libgcc functions.  */
559 void op_dsll (void)
560 {
561     CALL_FROM_TB0(do_dsll);
562     FORCE_RET();
563 }
564
565 void op_dsll32 (void)
566 {
567     CALL_FROM_TB0(do_dsll32);
568     FORCE_RET();
569 }
570
571 void op_dsra (void)
572 {
573     CALL_FROM_TB0(do_dsra);
574     FORCE_RET();
575 }
576
577 void op_dsra32 (void)
578 {
579     CALL_FROM_TB0(do_dsra32);
580     FORCE_RET();
581 }
582
583 void op_dsrl (void)
584 {
585     CALL_FROM_TB0(do_dsrl);
586     FORCE_RET();
587 }
588
589 void op_dsrl32 (void)
590 {
591     CALL_FROM_TB0(do_dsrl32);
592     FORCE_RET();
593 }
594
595 void op_drotr (void)
596 {
597     CALL_FROM_TB0(do_drotr);
598     FORCE_RET();
599 }
600
601 void op_drotr32 (void)
602 {
603     CALL_FROM_TB0(do_drotr32);
604     FORCE_RET();
605 }
606
607 void op_dsllv (void)
608 {
609     CALL_FROM_TB0(do_dsllv);
610     FORCE_RET();
611 }
612
613 void op_dsrav (void)
614 {
615     CALL_FROM_TB0(do_dsrav);
616     FORCE_RET();
617 }
618
619 void op_dsrlv (void)
620 {
621     CALL_FROM_TB0(do_dsrlv);
622     FORCE_RET();
623 }
624
625 void op_drotrv (void)
626 {
627     CALL_FROM_TB0(do_drotrv);
628     FORCE_RET();
629 }
630
631 void op_dclo (void)
632 {
633     CALL_FROM_TB0(do_dclo);
634     FORCE_RET();
635 }
636
637 void op_dclz (void)
638 {
639     CALL_FROM_TB0(do_dclz);
640     FORCE_RET();
641 }
642
643 #else /* TARGET_LONG_BITS > HOST_LONG_BITS */
644
645 void op_dsll (void)
646 {
647     T0 = T0 << T1;
648     FORCE_RET();
649 }
650
651 void op_dsll32 (void)
652 {
653     T0 = T0 << (T1 + 32);
654     FORCE_RET();
655 }
656
657 void op_dsra (void)
658 {
659     T0 = (int64_t)T0 >> T1;
660     FORCE_RET();
661 }
662
663 void op_dsra32 (void)
664 {
665     T0 = (int64_t)T0 >> (T1 + 32);
666     FORCE_RET();
667 }
668
669 void op_dsrl (void)
670 {
671     T0 = T0 >> T1;
672     FORCE_RET();
673 }
674
675 void op_dsrl32 (void)
676 {
677     T0 = T0 >> (T1 + 32);
678     FORCE_RET();
679 }
680
681 void op_drotr (void)
682 {
683     target_ulong tmp;
684
685     if (T1) {
686         tmp = T0 << (0x40 - T1);
687         T0 = (T0 >> T1) | tmp;
688     }
689     FORCE_RET();
690 }
691
692 void op_drotr32 (void)
693 {
694     target_ulong tmp;
695
696     tmp = T0 << (0x40 - (32 + T1));
697     T0 = (T0 >> (32 + T1)) | tmp;
698     FORCE_RET();
699 }
700
701 void op_dsllv (void)
702 {
703     T0 = T1 << (T0 & 0x3F);
704     FORCE_RET();
705 }
706
707 void op_dsrav (void)
708 {
709     T0 = (int64_t)T1 >> (T0 & 0x3F);
710     FORCE_RET();
711 }
712
713 void op_dsrlv (void)
714 {
715     T0 = T1 >> (T0 & 0x3F);
716     FORCE_RET();
717 }
718
719 void op_drotrv (void)
720 {
721     target_ulong tmp;
722
723     T0 &= 0x3F;
724     if (T0) {
725         tmp = T1 << (0x40 - T0);
726         T0 = (T1 >> T0) | tmp;
727     } else
728         T0 = T1;
729     FORCE_RET();
730 }
731
732 void op_dclo (void)
733 {
734     T0 = clo64(T0);
735     FORCE_RET();
736 }
737
738 void op_dclz (void)
739 {
740     T0 = clz64(T0);
741     FORCE_RET();
742 }
743 #endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
744 #endif /* TARGET_MIPS64 */
745
746 /* 64 bits arithmetic */
747 #if TARGET_LONG_BITS > HOST_LONG_BITS
748 void op_mult (void)
749 {
750     CALL_FROM_TB0(do_mult);
751     FORCE_RET();
752 }
753
754 void op_multu (void)
755 {
756     CALL_FROM_TB0(do_multu);
757     FORCE_RET();
758 }
759
760 void op_madd (void)
761 {
762     CALL_FROM_TB0(do_madd);
763     FORCE_RET();
764 }
765
766 void op_maddu (void)
767 {
768     CALL_FROM_TB0(do_maddu);
769     FORCE_RET();
770 }
771
772 void op_msub (void)
773 {
774     CALL_FROM_TB0(do_msub);
775     FORCE_RET();
776 }
777
778 void op_msubu (void)
779 {
780     CALL_FROM_TB0(do_msubu);
781     FORCE_RET();
782 }
783
784 /* Multiplication variants of the vr54xx. */
785 void op_muls (void)
786 {
787     CALL_FROM_TB0(do_muls);
788     FORCE_RET();
789 }
790
791 void op_mulsu (void)
792 {
793     CALL_FROM_TB0(do_mulsu);
794     FORCE_RET();
795 }
796
797 void op_macc (void)
798 {
799     CALL_FROM_TB0(do_macc);
800     FORCE_RET();
801 }
802
803 void op_macchi (void)
804 {
805     CALL_FROM_TB0(do_macchi);
806     FORCE_RET();
807 }
808
809 void op_maccu (void)
810 {
811     CALL_FROM_TB0(do_maccu);
812     FORCE_RET();
813 }
814 void op_macchiu (void)
815 {
816     CALL_FROM_TB0(do_macchiu);
817     FORCE_RET();
818 }
819
820 void op_msac (void)
821 {
822     CALL_FROM_TB0(do_msac);
823     FORCE_RET();
824 }
825
826 void op_msachi (void)
827 {
828     CALL_FROM_TB0(do_msachi);
829     FORCE_RET();
830 }
831
832 void op_msacu (void)
833 {
834     CALL_FROM_TB0(do_msacu);
835     FORCE_RET();
836 }
837
838 void op_msachiu (void)
839 {
840     CALL_FROM_TB0(do_msachiu);
841     FORCE_RET();
842 }
843
844 void op_mulhi (void)
845 {
846     CALL_FROM_TB0(do_mulhi);
847     FORCE_RET();
848 }
849
850 void op_mulhiu (void)
851 {
852     CALL_FROM_TB0(do_mulhiu);
853     FORCE_RET();
854 }
855
856 void op_mulshi (void)
857 {
858     CALL_FROM_TB0(do_mulshi);
859     FORCE_RET();
860 }
861
862 void op_mulshiu (void)
863 {
864     CALL_FROM_TB0(do_mulshiu);
865     FORCE_RET();
866 }
867
868 #else /* TARGET_LONG_BITS > HOST_LONG_BITS */
869
870 static always_inline uint64_t get_HILO (void)
871 {
872     return ((uint64_t)env->HI[0][env->current_tc] << 32) |
873             ((uint64_t)(uint32_t)env->LO[0][env->current_tc]);
874 }
875
876 static always_inline void set_HILO (uint64_t HILO)
877 {
878     env->LO[0][env->current_tc] = (int32_t)(HILO & 0xFFFFFFFF);
879     env->HI[0][env->current_tc] = (int32_t)(HILO >> 32);
880 }
881
882 static always_inline void set_HIT0_LO (uint64_t HILO)
883 {
884     env->LO[0][env->current_tc] = (int32_t)(HILO & 0xFFFFFFFF);
885     T0 = env->HI[0][env->current_tc] = (int32_t)(HILO >> 32);
886 }
887
888 static always_inline void set_HI_LOT0 (uint64_t HILO)
889 {
890     T0 = env->LO[0][env->current_tc] = (int32_t)(HILO & 0xFFFFFFFF);
891     env->HI[0][env->current_tc] = (int32_t)(HILO >> 32);
892 }
893
894 void op_mult (void)
895 {
896     set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
897     FORCE_RET();
898 }
899
900 void op_multu (void)
901 {
902     set_HILO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
903     FORCE_RET();
904 }
905
906 void op_madd (void)
907 {
908     int64_t tmp;
909
910     tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
911     set_HILO((int64_t)get_HILO() + tmp);
912     FORCE_RET();
913 }
914
915 void op_maddu (void)
916 {
917     uint64_t tmp;
918
919     tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
920     set_HILO(get_HILO() + tmp);
921     FORCE_RET();
922 }
923
924 void op_msub (void)
925 {
926     int64_t tmp;
927
928     tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
929     set_HILO((int64_t)get_HILO() - tmp);
930     FORCE_RET();
931 }
932
933 void op_msubu (void)
934 {
935     uint64_t tmp;
936
937     tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
938     set_HILO(get_HILO() - tmp);
939     FORCE_RET();
940 }
941
942 /* Multiplication variants of the vr54xx. */
943 void op_muls (void)
944 {
945     set_HI_LOT0(0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
946     FORCE_RET();
947 }
948
949 void op_mulsu (void)
950 {
951     set_HI_LOT0(0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
952     FORCE_RET();
953 }
954
955 void op_macc (void)
956 {
957     set_HI_LOT0(get_HILO() + ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
958     FORCE_RET();
959 }
960
961 void op_macchi (void)
962 {
963     set_HIT0_LO(get_HILO() + ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
964     FORCE_RET();
965 }
966
967 void op_maccu (void)
968 {
969     set_HI_LOT0(get_HILO() + ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
970     FORCE_RET();
971 }
972
973 void op_macchiu (void)
974 {
975     set_HIT0_LO(get_HILO() + ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
976     FORCE_RET();
977 }
978
979 void op_msac (void)
980 {
981     set_HI_LOT0(get_HILO() - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
982     FORCE_RET();
983 }
984
985 void op_msachi (void)
986 {
987     set_HIT0_LO(get_HILO() - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
988     FORCE_RET();
989 }
990
991 void op_msacu (void)
992 {
993     set_HI_LOT0(get_HILO() - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
994     FORCE_RET();
995 }
996
997 void op_msachiu (void)
998 {
999     set_HIT0_LO(get_HILO() - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
1000     FORCE_RET();
1001 }
1002
1003 void op_mulhi (void)
1004 {
1005     set_HIT0_LO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
1006     FORCE_RET();
1007 }
1008
1009 void op_mulhiu (void)
1010 {
1011     set_HIT0_LO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
1012     FORCE_RET();
1013 }
1014
1015 void op_mulshi (void)
1016 {
1017     set_HIT0_LO(0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
1018     FORCE_RET();
1019 }
1020
1021 void op_mulshiu (void)
1022 {
1023     set_HIT0_LO(0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
1024     FORCE_RET();
1025 }
1026
1027 #endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
1028
1029 #if defined(TARGET_MIPS64)
1030 void op_dmult (void)
1031 {
1032     CALL_FROM_TB4(muls64, &(env->LO[0][env->current_tc]), &(env->HI[0][env->current_tc]), T0, T1);
1033     FORCE_RET();
1034 }
1035
1036 void op_dmultu (void)
1037 {
1038     CALL_FROM_TB4(mulu64, &(env->LO[0][env->current_tc]), &(env->HI[0][env->current_tc]), T0, T1);
1039     FORCE_RET();
1040 }
1041 #endif
1042
1043 /* Conditional moves */
1044 void op_movn (void)
1045 {
1046     if (T1 != 0)
1047         env->gpr[PARAM1][env->current_tc] = T0;
1048     FORCE_RET();
1049 }
1050
1051 void op_movz (void)
1052 {
1053     if (T1 == 0)
1054         env->gpr[PARAM1][env->current_tc] = T0;
1055     FORCE_RET();
1056 }
1057
1058 void op_movf (void)
1059 {
1060     if (!(env->fpu->fcr31 & PARAM1))
1061         T0 = T1;
1062     FORCE_RET();
1063 }
1064
1065 void op_movt (void)
1066 {
1067     if (env->fpu->fcr31 & PARAM1)
1068         T0 = T1;
1069     FORCE_RET();
1070 }
1071
1072 /* Tests */
1073 #define OP_COND(name, cond) \
1074 void glue(op_, name) (void) \
1075 {                           \
1076     if (cond) {             \
1077         T0 = 1;             \
1078     } else {                \
1079         T0 = 0;             \
1080     }                       \
1081     FORCE_RET();            \
1082 }
1083
1084 OP_COND(eq, T0 == T1);
1085 OP_COND(ne, T0 != T1);
1086 OP_COND(ge, (target_long)T0 >= (target_long)T1);
1087 OP_COND(geu, T0 >= T1);
1088 OP_COND(lt, (target_long)T0 < (target_long)T1);
1089 OP_COND(ltu, T0 < T1);
1090 OP_COND(gez, (target_long)T0 >= 0);
1091 OP_COND(gtz, (target_long)T0 > 0);
1092 OP_COND(lez, (target_long)T0 <= 0);
1093 OP_COND(ltz, (target_long)T0 < 0);
1094
1095 /* Branches */
1096 /* Branch to register */
1097 void op_save_breg_target (void)
1098 {
1099     env->btarget = T2;
1100     FORCE_RET();
1101 }
1102
1103 void op_restore_breg_target (void)
1104 {
1105     T2 = env->btarget;
1106     FORCE_RET();
1107 }
1108
1109 void op_breg (void)
1110 {
1111     env->PC[env->current_tc] = T2;
1112     FORCE_RET();
1113 }
1114
1115 void op_save_btarget (void)
1116 {
1117     env->btarget = PARAM1;
1118     FORCE_RET();
1119 }
1120
1121 #if defined(TARGET_MIPS64)
1122 void op_save_btarget64 (void)
1123 {
1124     env->btarget = ((uint64_t)PARAM1 << 32) | (uint32_t)PARAM2;
1125     FORCE_RET();
1126 }
1127 #endif
1128
1129 /* Conditional branch */
1130 void op_set_bcond (void)
1131 {
1132     T2 = T0;
1133     FORCE_RET();
1134 }
1135
1136 void op_save_bcond (void)
1137 {
1138     env->bcond = T2;
1139     FORCE_RET();
1140 }
1141
1142 void op_restore_bcond (void)
1143 {
1144     T2 = env->bcond;
1145     FORCE_RET();
1146 }
1147
1148 void op_jnz_T2 (void)
1149 {
1150     if (T2)
1151         GOTO_LABEL_PARAM(1);
1152     FORCE_RET();
1153 }
1154
1155 /* CP0 functions */
1156 void op_mfc0_index (void)
1157 {
1158     T0 = env->CP0_Index;
1159     FORCE_RET();
1160 }
1161
1162 void op_mfc0_mvpcontrol (void)
1163 {
1164     T0 = env->mvp->CP0_MVPControl;
1165     FORCE_RET();
1166 }
1167
1168 void op_mfc0_mvpconf0 (void)
1169 {
1170     T0 = env->mvp->CP0_MVPConf0;
1171     FORCE_RET();
1172 }
1173
1174 void op_mfc0_mvpconf1 (void)
1175 {
1176     T0 = env->mvp->CP0_MVPConf1;
1177     FORCE_RET();
1178 }
1179
1180 void op_mfc0_random (void)
1181 {
1182     CALL_FROM_TB0(do_mfc0_random);
1183     FORCE_RET();
1184 }
1185
1186 void op_mfc0_vpecontrol (void)
1187 {
1188     T0 = env->CP0_VPEControl;
1189     FORCE_RET();
1190 }
1191
1192 void op_mfc0_vpeconf0 (void)
1193 {
1194     T0 = env->CP0_VPEConf0;
1195     FORCE_RET();
1196 }
1197
1198 void op_mfc0_vpeconf1 (void)
1199 {
1200     T0 = env->CP0_VPEConf1;
1201     FORCE_RET();
1202 }
1203
1204 void op_mfc0_yqmask (void)
1205 {
1206     T0 = env->CP0_YQMask;
1207     FORCE_RET();
1208 }
1209
1210 void op_mfc0_vpeschedule (void)
1211 {
1212     T0 = env->CP0_VPESchedule;
1213     FORCE_RET();
1214 }
1215
1216 void op_mfc0_vpeschefback (void)
1217 {
1218     T0 = env->CP0_VPEScheFBack;
1219     FORCE_RET();
1220 }
1221
1222 void op_mfc0_vpeopt (void)
1223 {
1224     T0 = env->CP0_VPEOpt;
1225     FORCE_RET();
1226 }
1227
1228 void op_mfc0_entrylo0 (void)
1229 {
1230     T0 = (int32_t)env->CP0_EntryLo0;
1231     FORCE_RET();
1232 }
1233
1234 void op_mfc0_tcstatus (void)
1235 {
1236     T0 = env->CP0_TCStatus[env->current_tc];
1237     FORCE_RET();
1238 }
1239
1240 void op_mftc0_tcstatus(void)
1241 {
1242     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1243
1244     T0 = env->CP0_TCStatus[other_tc];
1245     FORCE_RET();
1246 }
1247
1248 void op_mfc0_tcbind (void)
1249 {
1250     T0 = env->CP0_TCBind[env->current_tc];
1251     FORCE_RET();
1252 }
1253
1254 void op_mftc0_tcbind(void)
1255 {
1256     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1257
1258     T0 = env->CP0_TCBind[other_tc];
1259     FORCE_RET();
1260 }
1261
1262 void op_mfc0_tcrestart (void)
1263 {
1264     T0 = env->PC[env->current_tc];
1265     FORCE_RET();
1266 }
1267
1268 void op_mftc0_tcrestart(void)
1269 {
1270     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1271
1272     T0 = env->PC[other_tc];
1273     FORCE_RET();
1274 }
1275
1276 void op_mfc0_tchalt (void)
1277 {
1278     T0 = env->CP0_TCHalt[env->current_tc];
1279     FORCE_RET();
1280 }
1281
1282 void op_mftc0_tchalt(void)
1283 {
1284     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1285
1286     T0 = env->CP0_TCHalt[other_tc];
1287     FORCE_RET();
1288 }
1289
1290 void op_mfc0_tccontext (void)
1291 {
1292     T0 = env->CP0_TCContext[env->current_tc];
1293     FORCE_RET();
1294 }
1295
1296 void op_mftc0_tccontext(void)
1297 {
1298     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1299
1300     T0 = env->CP0_TCContext[other_tc];
1301     FORCE_RET();
1302 }
1303
1304 void op_mfc0_tcschedule (void)
1305 {
1306     T0 = env->CP0_TCSchedule[env->current_tc];
1307     FORCE_RET();
1308 }
1309
1310 void op_mftc0_tcschedule(void)
1311 {
1312     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1313
1314     T0 = env->CP0_TCSchedule[other_tc];
1315     FORCE_RET();
1316 }
1317
1318 void op_mfc0_tcschefback (void)
1319 {
1320     T0 = env->CP0_TCScheFBack[env->current_tc];
1321     FORCE_RET();
1322 }
1323
1324 void op_mftc0_tcschefback(void)
1325 {
1326     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1327
1328     T0 = env->CP0_TCScheFBack[other_tc];
1329     FORCE_RET();
1330 }
1331
1332 void op_mfc0_entrylo1 (void)
1333 {
1334     T0 = (int32_t)env->CP0_EntryLo1;
1335     FORCE_RET();
1336 }
1337
1338 void op_mfc0_context (void)
1339 {
1340     T0 = (int32_t)env->CP0_Context;
1341     FORCE_RET();
1342 }
1343
1344 void op_mfc0_pagemask (void)
1345 {
1346     T0 = env->CP0_PageMask;
1347     FORCE_RET();
1348 }
1349
1350 void op_mfc0_pagegrain (void)
1351 {
1352     T0 = env->CP0_PageGrain;
1353     FORCE_RET();
1354 }
1355
1356 void op_mfc0_wired (void)
1357 {
1358     T0 = env->CP0_Wired;
1359     FORCE_RET();
1360 }
1361
1362 void op_mfc0_srsconf0 (void)
1363 {
1364     T0 = env->CP0_SRSConf0;
1365     FORCE_RET();
1366 }
1367
1368 void op_mfc0_srsconf1 (void)
1369 {
1370     T0 = env->CP0_SRSConf1;
1371     FORCE_RET();
1372 }
1373
1374 void op_mfc0_srsconf2 (void)
1375 {
1376     T0 = env->CP0_SRSConf2;
1377     FORCE_RET();
1378 }
1379
1380 void op_mfc0_srsconf3 (void)
1381 {
1382     T0 = env->CP0_SRSConf3;
1383     FORCE_RET();
1384 }
1385
1386 void op_mfc0_srsconf4 (void)
1387 {
1388     T0 = env->CP0_SRSConf4;
1389     FORCE_RET();
1390 }
1391
1392 void op_mfc0_hwrena (void)
1393 {
1394     T0 = env->CP0_HWREna;
1395     FORCE_RET();
1396 }
1397
1398 void op_mfc0_badvaddr (void)
1399 {
1400     T0 = (int32_t)env->CP0_BadVAddr;
1401     FORCE_RET();
1402 }
1403
1404 void op_mfc0_count (void)
1405 {
1406     CALL_FROM_TB0(do_mfc0_count);
1407     FORCE_RET();
1408 }
1409
1410 void op_mfc0_entryhi (void)
1411 {
1412     T0 = (int32_t)env->CP0_EntryHi;
1413     FORCE_RET();
1414 }
1415
1416 void op_mftc0_entryhi(void)
1417 {
1418     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1419
1420     T0 = (env->CP0_EntryHi & ~0xff) | (env->CP0_TCStatus[other_tc] & 0xff);
1421     FORCE_RET();
1422 }
1423
1424 void op_mfc0_compare (void)
1425 {
1426     T0 = env->CP0_Compare;
1427     FORCE_RET();
1428 }
1429
1430 void op_mfc0_status (void)
1431 {
1432     T0 = env->CP0_Status;
1433     FORCE_RET();
1434 }
1435
1436 void op_mftc0_status(void)
1437 {
1438     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1439     uint32_t tcstatus = env->CP0_TCStatus[other_tc];
1440
1441     T0 = env->CP0_Status & ~0xf1000018;
1442     T0 |= tcstatus & (0xf << CP0TCSt_TCU0);
1443     T0 |= (tcstatus & (1 << CP0TCSt_TMX)) >> (CP0TCSt_TMX - CP0St_MX);
1444     T0 |= (tcstatus & (0x3 << CP0TCSt_TKSU)) >> (CP0TCSt_TKSU - CP0St_KSU);
1445     FORCE_RET();
1446 }
1447
1448 void op_mfc0_intctl (void)
1449 {
1450     T0 = env->CP0_IntCtl;
1451     FORCE_RET();
1452 }
1453
1454 void op_mfc0_srsctl (void)
1455 {
1456     T0 = env->CP0_SRSCtl;
1457     FORCE_RET();
1458 }
1459
1460 void op_mfc0_srsmap (void)
1461 {
1462     T0 = env->CP0_SRSMap;
1463     FORCE_RET();
1464 }
1465
1466 void op_mfc0_cause (void)
1467 {
1468     T0 = env->CP0_Cause;
1469     FORCE_RET();
1470 }
1471
1472 void op_mfc0_epc (void)
1473 {
1474     T0 = (int32_t)env->CP0_EPC;
1475     FORCE_RET();
1476 }
1477
1478 void op_mfc0_prid (void)
1479 {
1480     T0 = env->CP0_PRid;
1481     FORCE_RET();
1482 }
1483
1484 void op_mfc0_ebase (void)
1485 {
1486     T0 = env->CP0_EBase;
1487     FORCE_RET();
1488 }
1489
1490 void op_mfc0_config0 (void)
1491 {
1492     T0 = env->CP0_Config0;
1493     FORCE_RET();
1494 }
1495
1496 void op_mfc0_config1 (void)
1497 {
1498     T0 = env->CP0_Config1;
1499     FORCE_RET();
1500 }
1501
1502 void op_mfc0_config2 (void)
1503 {
1504     T0 = env->CP0_Config2;
1505     FORCE_RET();
1506 }
1507
1508 void op_mfc0_config3 (void)
1509 {
1510     T0 = env->CP0_Config3;
1511     FORCE_RET();
1512 }
1513
1514 void op_mfc0_config6 (void)
1515 {
1516     T0 = env->CP0_Config6;
1517     FORCE_RET();
1518 }
1519
1520 void op_mfc0_config7 (void)
1521 {
1522     T0 = env->CP0_Config7;
1523     FORCE_RET();
1524 }
1525
1526 void op_mfc0_lladdr (void)
1527 {
1528     T0 = (int32_t)env->CP0_LLAddr >> 4;
1529     FORCE_RET();
1530 }
1531
1532 void op_mfc0_watchlo (void)
1533 {
1534     T0 = (int32_t)env->CP0_WatchLo[PARAM1];
1535     FORCE_RET();
1536 }
1537
1538 void op_mfc0_watchhi (void)
1539 {
1540     T0 = env->CP0_WatchHi[PARAM1];
1541     FORCE_RET();
1542 }
1543
1544 void op_mfc0_xcontext (void)
1545 {
1546     T0 = (int32_t)env->CP0_XContext;
1547     FORCE_RET();
1548 }
1549
1550 void op_mfc0_framemask (void)
1551 {
1552     T0 = env->CP0_Framemask;
1553     FORCE_RET();
1554 }
1555
1556 void op_mfc0_debug (void)
1557 {
1558     T0 = env->CP0_Debug;
1559     if (env->hflags & MIPS_HFLAG_DM)
1560         T0 |= 1 << CP0DB_DM;
1561     FORCE_RET();
1562 }
1563
1564 void op_mftc0_debug(void)
1565 {
1566     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1567
1568     /* XXX: Might be wrong, check with EJTAG spec. */
1569     T0 = (env->CP0_Debug & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
1570          (env->CP0_Debug_tcstatus[other_tc] &
1571           ((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
1572     FORCE_RET();
1573 }
1574
1575 void op_mfc0_depc (void)
1576 {
1577     T0 = (int32_t)env->CP0_DEPC;
1578     FORCE_RET();
1579 }
1580
1581 void op_mfc0_performance0 (void)
1582 {
1583     T0 = env->CP0_Performance0;
1584     FORCE_RET();
1585 }
1586
1587 void op_mfc0_taglo (void)
1588 {
1589     T0 = env->CP0_TagLo;
1590     FORCE_RET();
1591 }
1592
1593 void op_mfc0_datalo (void)
1594 {
1595     T0 = env->CP0_DataLo;
1596     FORCE_RET();
1597 }
1598
1599 void op_mfc0_taghi (void)
1600 {
1601     T0 = env->CP0_TagHi;
1602     FORCE_RET();
1603 }
1604
1605 void op_mfc0_datahi (void)
1606 {
1607     T0 = env->CP0_DataHi;
1608     FORCE_RET();
1609 }
1610
1611 void op_mfc0_errorepc (void)
1612 {
1613     T0 = (int32_t)env->CP0_ErrorEPC;
1614     FORCE_RET();
1615 }
1616
1617 void op_mfc0_desave (void)
1618 {
1619     T0 = env->CP0_DESAVE;
1620     FORCE_RET();
1621 }
1622
1623 void op_mtc0_index (void)
1624 {
1625     int num = 1;
1626     unsigned int tmp = env->tlb->nb_tlb;
1627
1628     do {
1629         tmp >>= 1;
1630         num <<= 1;
1631     } while (tmp);
1632     env->CP0_Index = (env->CP0_Index & 0x80000000) | (T0 & (num - 1));
1633     FORCE_RET();
1634 }
1635
1636 void op_mtc0_mvpcontrol (void)
1637 {
1638     uint32_t mask = 0;
1639     uint32_t newval;
1640
1641     if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP))
1642         mask |= (1 << CP0MVPCo_CPA) | (1 << CP0MVPCo_VPC) |
1643                 (1 << CP0MVPCo_EVP);
1644     if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1645         mask |= (1 << CP0MVPCo_STLB);
1646     newval = (env->mvp->CP0_MVPControl & ~mask) | (T0 & mask);
1647
1648     // TODO: Enable/disable shared TLB, enable/disable VPEs.
1649
1650     env->mvp->CP0_MVPControl = newval;
1651     FORCE_RET();
1652 }
1653
1654 void op_mtc0_vpecontrol (void)
1655 {
1656     uint32_t mask;
1657     uint32_t newval;
1658
1659     mask = (1 << CP0VPECo_YSI) | (1 << CP0VPECo_GSI) |
1660            (1 << CP0VPECo_TE) | (0xff << CP0VPECo_TargTC);
1661     newval = (env->CP0_VPEControl & ~mask) | (T0 & mask);
1662
1663     /* Yield scheduler intercept not implemented. */
1664     /* Gating storage scheduler intercept not implemented. */
1665
1666     // TODO: Enable/disable TCs.
1667
1668     env->CP0_VPEControl = newval;
1669     FORCE_RET();
1670 }
1671
1672 void op_mtc0_vpeconf0 (void)
1673 {
1674     uint32_t mask = 0;
1675     uint32_t newval;
1676
1677     if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) {
1678         if (env->CP0_VPEConf0 & (1 << CP0VPEC0_VPA))
1679             mask |= (0xff << CP0VPEC0_XTC);
1680         mask |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
1681     }
1682     newval = (env->CP0_VPEConf0 & ~mask) | (T0 & mask);
1683
1684     // TODO: TC exclusive handling due to ERL/EXL.
1685
1686     env->CP0_VPEConf0 = newval;
1687     FORCE_RET();
1688 }
1689
1690 void op_mtc0_vpeconf1 (void)
1691 {
1692     uint32_t mask = 0;
1693     uint32_t newval;
1694
1695     if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1696         mask |= (0xff << CP0VPEC1_NCX) | (0xff << CP0VPEC1_NCP2) |
1697                 (0xff << CP0VPEC1_NCP1);
1698     newval = (env->CP0_VPEConf1 & ~mask) | (T0 & mask);
1699
1700     /* UDI not implemented. */
1701     /* CP2 not implemented. */
1702
1703     // TODO: Handle FPU (CP1) binding.
1704
1705     env->CP0_VPEConf1 = newval;
1706     FORCE_RET();
1707 }
1708
1709 void op_mtc0_yqmask (void)
1710 {
1711     /* Yield qualifier inputs not implemented. */
1712     env->CP0_YQMask = 0x00000000;
1713     FORCE_RET();
1714 }
1715
1716 void op_mtc0_vpeschedule (void)
1717 {
1718     env->CP0_VPESchedule = T0;
1719     FORCE_RET();
1720 }
1721
1722 void op_mtc0_vpeschefback (void)
1723 {
1724     env->CP0_VPEScheFBack = T0;
1725     FORCE_RET();
1726 }
1727
1728 void op_mtc0_vpeopt (void)
1729 {
1730     env->CP0_VPEOpt = T0 & 0x0000ffff;
1731     FORCE_RET();
1732 }
1733
1734 void op_mtc0_entrylo0 (void)
1735 {
1736     /* Large physaddr (PABITS) not implemented */
1737     /* 1k pages not implemented */
1738     env->CP0_EntryLo0 = T0 & 0x3FFFFFFF;
1739     FORCE_RET();
1740 }
1741
1742 void op_mtc0_tcstatus (void)
1743 {
1744     uint32_t mask = env->CP0_TCStatus_rw_bitmask;
1745     uint32_t newval;
1746
1747     newval = (env->CP0_TCStatus[env->current_tc] & ~mask) | (T0 & mask);
1748
1749     // TODO: Sync with CP0_Status.
1750
1751     env->CP0_TCStatus[env->current_tc] = newval;
1752     FORCE_RET();
1753 }
1754
1755 void op_mttc0_tcstatus (void)
1756 {
1757     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1758
1759     // TODO: Sync with CP0_Status.
1760
1761     env->CP0_TCStatus[other_tc] = T0;
1762     FORCE_RET();
1763 }
1764
1765 void op_mtc0_tcbind (void)
1766 {
1767     uint32_t mask = (1 << CP0TCBd_TBE);
1768     uint32_t newval;
1769
1770     if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1771         mask |= (1 << CP0TCBd_CurVPE);
1772     newval = (env->CP0_TCBind[env->current_tc] & ~mask) | (T0 & mask);
1773     env->CP0_TCBind[env->current_tc] = newval;
1774     FORCE_RET();
1775 }
1776
1777 void op_mttc0_tcbind (void)
1778 {
1779     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1780     uint32_t mask = (1 << CP0TCBd_TBE);
1781     uint32_t newval;
1782
1783     if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1784         mask |= (1 << CP0TCBd_CurVPE);
1785     newval = (env->CP0_TCBind[other_tc] & ~mask) | (T0 & mask);
1786     env->CP0_TCBind[other_tc] = newval;
1787     FORCE_RET();
1788 }
1789
1790 void op_mtc0_tcrestart (void)
1791 {
1792     env->PC[env->current_tc] = T0;
1793     env->CP0_TCStatus[env->current_tc] &= ~(1 << CP0TCSt_TDS);
1794     env->CP0_LLAddr = 0ULL;
1795     /* MIPS16 not implemented. */
1796     FORCE_RET();
1797 }
1798
1799 void op_mttc0_tcrestart (void)
1800 {
1801     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1802
1803     env->PC[other_tc] = T0;
1804     env->CP0_TCStatus[other_tc] &= ~(1 << CP0TCSt_TDS);
1805     env->CP0_LLAddr = 0ULL;
1806     /* MIPS16 not implemented. */
1807     FORCE_RET();
1808 }
1809
1810 void op_mtc0_tchalt (void)
1811 {
1812     env->CP0_TCHalt[env->current_tc] = T0 & 0x1;
1813
1814     // TODO: Halt TC / Restart (if allocated+active) TC.
1815
1816     FORCE_RET();
1817 }
1818
1819 void op_mttc0_tchalt (void)
1820 {
1821     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1822
1823     // TODO: Halt TC / Restart (if allocated+active) TC.
1824
1825     env->CP0_TCHalt[other_tc] = T0;
1826     FORCE_RET();
1827 }
1828
1829 void op_mtc0_tccontext (void)
1830 {
1831     env->CP0_TCContext[env->current_tc] = T0;
1832     FORCE_RET();
1833 }
1834
1835 void op_mttc0_tccontext (void)
1836 {
1837     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1838
1839     env->CP0_TCContext[other_tc] = T0;
1840     FORCE_RET();
1841 }
1842
1843 void op_mtc0_tcschedule (void)
1844 {
1845     env->CP0_TCSchedule[env->current_tc] = T0;
1846     FORCE_RET();
1847 }
1848
1849 void op_mttc0_tcschedule (void)
1850 {
1851     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1852
1853     env->CP0_TCSchedule[other_tc] = T0;
1854     FORCE_RET();
1855 }
1856
1857 void op_mtc0_tcschefback (void)
1858 {
1859     env->CP0_TCScheFBack[env->current_tc] = T0;
1860     FORCE_RET();
1861 }
1862
1863 void op_mttc0_tcschefback (void)
1864 {
1865     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1866
1867     env->CP0_TCScheFBack[other_tc] = T0;
1868     FORCE_RET();
1869 }
1870
1871 void op_mtc0_entrylo1 (void)
1872 {
1873     /* Large physaddr (PABITS) not implemented */
1874     /* 1k pages not implemented */
1875     env->CP0_EntryLo1 = T0 & 0x3FFFFFFF;
1876     FORCE_RET();
1877 }
1878
1879 void op_mtc0_context (void)
1880 {
1881     env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (T0 & ~0x007FFFFF);
1882     FORCE_RET();
1883 }
1884
1885 void op_mtc0_pagemask (void)
1886 {
1887     /* 1k pages not implemented */
1888     env->CP0_PageMask = T0 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
1889     FORCE_RET();
1890 }
1891
1892 void op_mtc0_pagegrain (void)
1893 {
1894     /* SmartMIPS not implemented */
1895     /* Large physaddr (PABITS) not implemented */
1896     /* 1k pages not implemented */
1897     env->CP0_PageGrain = 0;
1898     FORCE_RET();
1899 }
1900
1901 void op_mtc0_wired (void)
1902 {
1903     env->CP0_Wired = T0 % env->tlb->nb_tlb;
1904     FORCE_RET();
1905 }
1906
1907 void op_mtc0_srsconf0 (void)
1908 {
1909     env->CP0_SRSConf0 |= T0 & env->CP0_SRSConf0_rw_bitmask;
1910     FORCE_RET();
1911 }
1912
1913 void op_mtc0_srsconf1 (void)
1914 {
1915     env->CP0_SRSConf1 |= T0 & env->CP0_SRSConf1_rw_bitmask;
1916     FORCE_RET();
1917 }
1918
1919 void op_mtc0_srsconf2 (void)
1920 {
1921     env->CP0_SRSConf2 |= T0 & env->CP0_SRSConf2_rw_bitmask;
1922     FORCE_RET();
1923 }
1924
1925 void op_mtc0_srsconf3 (void)
1926 {
1927     env->CP0_SRSConf3 |= T0 & env->CP0_SRSConf3_rw_bitmask;
1928     FORCE_RET();
1929 }
1930
1931 void op_mtc0_srsconf4 (void)
1932 {
1933     env->CP0_SRSConf4 |= T0 & env->CP0_SRSConf4_rw_bitmask;
1934     FORCE_RET();
1935 }
1936
1937 void op_mtc0_hwrena (void)
1938 {
1939     env->CP0_HWREna = T0 & 0x0000000F;
1940     FORCE_RET();
1941 }
1942
1943 void op_mtc0_count (void)
1944 {
1945     CALL_FROM_TB2(cpu_mips_store_count, env, T0);
1946     FORCE_RET();
1947 }
1948
1949 void op_mtc0_entryhi (void)
1950 {
1951     target_ulong old, val;
1952
1953     /* 1k pages not implemented */
1954     val = T0 & ((TARGET_PAGE_MASK << 1) | 0xFF);
1955 #if defined(TARGET_MIPS64)
1956     val &= env->SEGMask;
1957 #endif
1958     old = env->CP0_EntryHi;
1959     env->CP0_EntryHi = val;
1960     if (env->CP0_Config3 & (1 << CP0C3_MT)) {
1961         uint32_t tcst = env->CP0_TCStatus[env->current_tc] & ~0xff;
1962         env->CP0_TCStatus[env->current_tc] = tcst | (val & 0xff);
1963     }
1964     /* If the ASID changes, flush qemu's TLB.  */
1965     if ((old & 0xFF) != (val & 0xFF))
1966         CALL_FROM_TB2(cpu_mips_tlb_flush, env, 1);
1967     FORCE_RET();
1968 }
1969
1970 void op_mttc0_entryhi(void)
1971 {
1972     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1973
1974     env->CP0_EntryHi = (env->CP0_EntryHi & 0xff) | (T0 & ~0xff);
1975     env->CP0_TCStatus[other_tc] = (env->CP0_TCStatus[other_tc] & ~0xff) | (T0 & 0xff);
1976     FORCE_RET();
1977 }
1978
1979 void op_mtc0_compare (void)
1980 {
1981     CALL_FROM_TB2(cpu_mips_store_compare, env, T0);
1982     FORCE_RET();
1983 }
1984
1985 void op_mtc0_status (void)
1986 {
1987     uint32_t val, old;
1988     uint32_t mask = env->CP0_Status_rw_bitmask;
1989
1990     val = T0 & mask;
1991     old = env->CP0_Status;
1992     env->CP0_Status = (env->CP0_Status & ~mask) | val;
1993     CALL_FROM_TB1(compute_hflags, env);
1994     if (loglevel & CPU_LOG_EXEC)
1995         CALL_FROM_TB2(do_mtc0_status_debug, old, val);
1996     CALL_FROM_TB1(cpu_mips_update_irq, env);
1997     FORCE_RET();
1998 }
1999
2000 void op_mttc0_status(void)
2001 {
2002     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2003     uint32_t tcstatus = env->CP0_TCStatus[other_tc];
2004
2005     env->CP0_Status = T0 & ~0xf1000018;
2006     tcstatus = (tcstatus & ~(0xf << CP0TCSt_TCU0)) | (T0 & (0xf << CP0St_CU0));
2007     tcstatus = (tcstatus & ~(1 << CP0TCSt_TMX)) | ((T0 & (1 << CP0St_MX)) << (CP0TCSt_TMX - CP0St_MX));
2008     tcstatus = (tcstatus & ~(0x3 << CP0TCSt_TKSU)) | ((T0 & (0x3 << CP0St_KSU)) << (CP0TCSt_TKSU - CP0St_KSU));
2009     env->CP0_TCStatus[other_tc] = tcstatus;
2010     FORCE_RET();
2011 }
2012
2013 void op_mtc0_intctl (void)
2014 {
2015     /* vectored interrupts not implemented, no performance counters. */
2016     env->CP0_IntCtl = (env->CP0_IntCtl & ~0x000002e0) | (T0 & 0x000002e0);
2017     FORCE_RET();
2018 }
2019
2020 void op_mtc0_srsctl (void)
2021 {
2022     uint32_t mask = (0xf << CP0SRSCtl_ESS) | (0xf << CP0SRSCtl_PSS);
2023     env->CP0_SRSCtl = (env->CP0_SRSCtl & ~mask) | (T0 & mask);
2024     FORCE_RET();
2025 }
2026
2027 void op_mtc0_srsmap (void)
2028 {
2029     env->CP0_SRSMap = T0;
2030     FORCE_RET();
2031 }
2032
2033 void op_mtc0_cause (void)
2034 {
2035     uint32_t mask = 0x00C00300;
2036     uint32_t old = env->CP0_Cause;
2037
2038     if (env->insn_flags & ISA_MIPS32R2)
2039         mask |= 1 << CP0Ca_DC;
2040
2041     env->CP0_Cause = (env->CP0_Cause & ~mask) | (T0 & mask);
2042
2043     if ((old ^ env->CP0_Cause) & (1 << CP0Ca_DC)) {
2044         if (env->CP0_Cause & (1 << CP0Ca_DC))
2045             CALL_FROM_TB1(cpu_mips_stop_count, env);
2046         else
2047             CALL_FROM_TB1(cpu_mips_start_count, env);
2048     }
2049
2050     /* Handle the software interrupt as an hardware one, as they
2051        are very similar */
2052     if (T0 & CP0Ca_IP_mask) {
2053         CALL_FROM_TB1(cpu_mips_update_irq, env);
2054     }
2055     FORCE_RET();
2056 }
2057
2058 void op_mtc0_epc (void)
2059 {
2060     env->CP0_EPC = T0;
2061     FORCE_RET();
2062 }
2063
2064 void op_mtc0_ebase (void)
2065 {
2066     /* vectored interrupts not implemented */
2067     /* Multi-CPU not implemented */
2068     env->CP0_EBase = 0x80000000 | (T0 & 0x3FFFF000);
2069     FORCE_RET();
2070 }
2071
2072 void op_mtc0_config0 (void)
2073 {
2074     env->CP0_Config0 = (env->CP0_Config0 & 0x81FFFFF8) | (T0 & 0x00000007);
2075     FORCE_RET();
2076 }
2077
2078 void op_mtc0_config2 (void)
2079 {
2080     /* tertiary/secondary caches not implemented */
2081     env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
2082     FORCE_RET();
2083 }
2084
2085 void op_mtc0_watchlo (void)
2086 {
2087     /* Watch exceptions for instructions, data loads, data stores
2088        not implemented. */
2089     env->CP0_WatchLo[PARAM1] = (T0 & ~0x7);
2090     FORCE_RET();
2091 }
2092
2093 void op_mtc0_watchhi (void)
2094 {
2095     env->CP0_WatchHi[PARAM1] = (T0 & 0x40FF0FF8);
2096     env->CP0_WatchHi[PARAM1] &= ~(env->CP0_WatchHi[PARAM1] & T0 & 0x7);
2097     FORCE_RET();
2098 }
2099
2100 void op_mtc0_xcontext (void)
2101 {
2102     target_ulong mask = (1ULL << (env->SEGBITS - 7)) - 1;
2103     env->CP0_XContext = (env->CP0_XContext & mask) | (T0 & ~mask);
2104     FORCE_RET();
2105 }
2106
2107 void op_mtc0_framemask (void)
2108 {
2109     env->CP0_Framemask = T0; /* XXX */
2110     FORCE_RET();
2111 }
2112
2113 void op_mtc0_debug (void)
2114 {
2115     env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120);
2116     if (T0 & (1 << CP0DB_DM))
2117         env->hflags |= MIPS_HFLAG_DM;
2118     else
2119         env->hflags &= ~MIPS_HFLAG_DM;
2120     FORCE_RET();
2121 }
2122
2123 void op_mttc0_debug(void)
2124 {
2125     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2126
2127     /* XXX: Might be wrong, check with EJTAG spec. */
2128     env->CP0_Debug_tcstatus[other_tc] = T0 & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt));
2129     env->CP0_Debug = (env->CP0_Debug & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
2130                      (T0 & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
2131     FORCE_RET();
2132 }
2133
2134 void op_mtc0_depc (void)
2135 {
2136     env->CP0_DEPC = T0;
2137     FORCE_RET();
2138 }
2139
2140 void op_mtc0_performance0 (void)
2141 {
2142     env->CP0_Performance0 = T0 & 0x000007ff;
2143     FORCE_RET();
2144 }
2145
2146 void op_mtc0_taglo (void)
2147 {
2148     env->CP0_TagLo = T0 & 0xFFFFFCF6;
2149     FORCE_RET();
2150 }
2151
2152 void op_mtc0_datalo (void)
2153 {
2154     env->CP0_DataLo = T0; /* XXX */
2155     FORCE_RET();
2156 }
2157
2158 void op_mtc0_taghi (void)
2159 {
2160     env->CP0_TagHi = T0; /* XXX */
2161     FORCE_RET();
2162 }
2163
2164 void op_mtc0_datahi (void)
2165 {
2166     env->CP0_DataHi = T0; /* XXX */
2167     FORCE_RET();
2168 }
2169
2170 void op_mtc0_errorepc (void)
2171 {
2172     env->CP0_ErrorEPC = T0;
2173     FORCE_RET();
2174 }
2175
2176 void op_mtc0_desave (void)
2177 {
2178     env->CP0_DESAVE = T0;
2179     FORCE_RET();
2180 }
2181
2182 #if defined(TARGET_MIPS64)
2183 void op_dmfc0_yqmask (void)
2184 {
2185     T0 = env->CP0_YQMask;
2186     FORCE_RET();
2187 }
2188
2189 void op_dmfc0_vpeschedule (void)
2190 {
2191     T0 = env->CP0_VPESchedule;
2192     FORCE_RET();
2193 }
2194
2195 void op_dmfc0_vpeschefback (void)
2196 {
2197     T0 = env->CP0_VPEScheFBack;
2198     FORCE_RET();
2199 }
2200
2201 void op_dmfc0_entrylo0 (void)
2202 {
2203     T0 = env->CP0_EntryLo0;
2204     FORCE_RET();
2205 }
2206
2207 void op_dmfc0_tcrestart (void)
2208 {
2209     T0 = env->PC[env->current_tc];
2210     FORCE_RET();
2211 }
2212
2213 void op_dmfc0_tchalt (void)
2214 {
2215     T0 = env->CP0_TCHalt[env->current_tc];
2216     FORCE_RET();
2217 }
2218
2219 void op_dmfc0_tccontext (void)
2220 {
2221     T0 = env->CP0_TCContext[env->current_tc];
2222     FORCE_RET();
2223 }
2224
2225 void op_dmfc0_tcschedule (void)
2226 {
2227     T0 = env->CP0_TCSchedule[env->current_tc];
2228     FORCE_RET();
2229 }
2230
2231 void op_dmfc0_tcschefback (void)
2232 {
2233     T0 = env->CP0_TCScheFBack[env->current_tc];
2234     FORCE_RET();
2235 }
2236
2237 void op_dmfc0_entrylo1 (void)
2238 {
2239     T0 = env->CP0_EntryLo1;
2240     FORCE_RET();
2241 }
2242
2243 void op_dmfc0_context (void)
2244 {
2245     T0 = env->CP0_Context;
2246     FORCE_RET();
2247 }
2248
2249 void op_dmfc0_badvaddr (void)
2250 {
2251     T0 = env->CP0_BadVAddr;
2252     FORCE_RET();
2253 }
2254
2255 void op_dmfc0_entryhi (void)
2256 {
2257     T0 = env->CP0_EntryHi;
2258     FORCE_RET();
2259 }
2260
2261 void op_dmfc0_epc (void)
2262 {
2263     T0 = env->CP0_EPC;
2264     FORCE_RET();
2265 }
2266
2267 void op_dmfc0_lladdr (void)
2268 {
2269     T0 = env->CP0_LLAddr >> 4;
2270     FORCE_RET();
2271 }
2272
2273 void op_dmfc0_watchlo (void)
2274 {
2275     T0 = env->CP0_WatchLo[PARAM1];
2276     FORCE_RET();
2277 }
2278
2279 void op_dmfc0_xcontext (void)
2280 {
2281     T0 = env->CP0_XContext;
2282     FORCE_RET();
2283 }
2284
2285 void op_dmfc0_depc (void)
2286 {
2287     T0 = env->CP0_DEPC;
2288     FORCE_RET();
2289 }
2290
2291 void op_dmfc0_errorepc (void)
2292 {
2293     T0 = env->CP0_ErrorEPC;
2294     FORCE_RET();
2295 }
2296 #endif /* TARGET_MIPS64 */
2297
2298 /* MIPS MT functions */
2299 void op_mftgpr(void)
2300 {
2301     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2302
2303     T0 = env->gpr[PARAM1][other_tc];
2304     FORCE_RET();
2305 }
2306
2307 void op_mftlo(void)
2308 {
2309     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2310
2311     T0 = env->LO[PARAM1][other_tc];
2312     FORCE_RET();
2313 }
2314
2315 void op_mfthi(void)
2316 {
2317     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2318
2319     T0 = env->HI[PARAM1][other_tc];
2320     FORCE_RET();
2321 }
2322
2323 void op_mftacx(void)
2324 {
2325     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2326
2327     T0 = env->ACX[PARAM1][other_tc];
2328     FORCE_RET();
2329 }
2330
2331 void op_mftdsp(void)
2332 {
2333     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2334
2335     T0 = env->DSPControl[other_tc];
2336     FORCE_RET();
2337 }
2338
2339 void op_mttgpr(void)
2340 {
2341     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2342
2343     T0 = env->gpr[PARAM1][other_tc];
2344     FORCE_RET();
2345 }
2346
2347 void op_mttlo(void)
2348 {
2349     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2350
2351     T0 = env->LO[PARAM1][other_tc];
2352     FORCE_RET();
2353 }
2354
2355 void op_mtthi(void)
2356 {
2357     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2358
2359     T0 = env->HI[PARAM1][other_tc];
2360     FORCE_RET();
2361 }
2362
2363 void op_mttacx(void)
2364 {
2365     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2366
2367     T0 = env->ACX[PARAM1][other_tc];
2368     FORCE_RET();
2369 }
2370
2371 void op_mttdsp(void)
2372 {
2373     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2374
2375     T0 = env->DSPControl[other_tc];
2376     FORCE_RET();
2377 }
2378
2379
2380 void op_dmt(void)
2381 {
2382     // TODO
2383     T0 = 0;
2384     // rt = T0
2385     FORCE_RET();
2386 }
2387
2388 void op_emt(void)
2389 {
2390     // TODO
2391     T0 = 0;
2392     // rt = T0
2393     FORCE_RET();
2394 }
2395
2396 void op_dvpe(void)
2397 {
2398     // TODO
2399     T0 = 0;
2400     // rt = T0
2401     FORCE_RET();
2402 }
2403
2404 void op_evpe(void)
2405 {
2406     // TODO
2407     T0 = 0;
2408     // rt = T0
2409     FORCE_RET();
2410 }
2411
2412 void op_fork(void)
2413 {
2414     // T0 = rt, T1 = rs
2415     T0 = 0;
2416     // TODO: store to TC register
2417     FORCE_RET();
2418 }
2419
2420 void op_yield(void)
2421 {
2422     if (T0 < 0) {
2423         /* No scheduling policy implemented. */
2424         if (T0 != -2) {
2425             if (env->CP0_VPEControl & (1 << CP0VPECo_YSI) &&
2426                 env->CP0_TCStatus[env->current_tc] & (1 << CP0TCSt_DT)) {
2427                 env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
2428                 env->CP0_VPEControl |= 4 << CP0VPECo_EXCPT;
2429                 CALL_FROM_TB1(do_raise_exception, EXCP_THREAD);
2430             }
2431         }
2432     } else if (T0 == 0) {
2433         if (0 /* TODO: TC underflow */) {
2434             env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
2435             CALL_FROM_TB1(do_raise_exception, EXCP_THREAD);
2436         } else {
2437             // TODO: Deallocate TC
2438         }
2439     } else if (T0 > 0) {
2440         /* Yield qualifier inputs not implemented. */
2441         env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
2442         env->CP0_VPEControl |= 2 << CP0VPECo_EXCPT;
2443         CALL_FROM_TB1(do_raise_exception, EXCP_THREAD);
2444     }
2445     T0 = env->CP0_YQMask;
2446     FORCE_RET();
2447 }
2448
2449 /* CP1 functions */
2450 #if 0
2451 # define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env)
2452 #else
2453 # define DEBUG_FPU_STATE() do { } while(0)
2454 #endif
2455
2456 void op_cfc1 (void)
2457 {
2458     CALL_FROM_TB1(do_cfc1, PARAM1);
2459     DEBUG_FPU_STATE();
2460     FORCE_RET();
2461 }
2462
2463 void op_ctc1 (void)
2464 {
2465     CALL_FROM_TB1(do_ctc1, PARAM1);
2466     DEBUG_FPU_STATE();
2467     FORCE_RET();
2468 }
2469
2470 void op_mfc1 (void)
2471 {
2472     T0 = (int32_t)WT0;
2473     DEBUG_FPU_STATE();
2474     FORCE_RET();
2475 }
2476
2477 void op_mtc1 (void)
2478 {
2479     WT0 = T0;
2480     DEBUG_FPU_STATE();
2481     FORCE_RET();
2482 }
2483
2484 void op_dmfc1 (void)
2485 {
2486     T0 = DT0;
2487     DEBUG_FPU_STATE();
2488     FORCE_RET();
2489 }
2490
2491 void op_dmtc1 (void)
2492 {
2493     DT0 = T0;
2494     DEBUG_FPU_STATE();
2495     FORCE_RET();
2496 }
2497
2498 void op_mfhc1 (void)
2499 {
2500     T0 = (int32_t)WTH0;
2501     DEBUG_FPU_STATE();
2502     FORCE_RET();
2503 }
2504
2505 void op_mthc1 (void)
2506 {
2507     WTH0 = T0;
2508     DEBUG_FPU_STATE();
2509     FORCE_RET();
2510 }
2511
2512 /* Float support.
2513    Single precition routines have a "s" suffix, double precision a
2514    "d" suffix, 32bit integer "w", 64bit integer "l", paired singe "ps",
2515    paired single lowwer "pl", paired single upper "pu".  */
2516
2517 #define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void)
2518
2519 FLOAT_OP(cvtd, s)
2520 {
2521     CALL_FROM_TB0(do_float_cvtd_s);
2522     DEBUG_FPU_STATE();
2523     FORCE_RET();
2524 }
2525 FLOAT_OP(cvtd, w)
2526 {
2527     CALL_FROM_TB0(do_float_cvtd_w);
2528     DEBUG_FPU_STATE();
2529     FORCE_RET();
2530 }
2531 FLOAT_OP(cvtd, l)
2532 {
2533     CALL_FROM_TB0(do_float_cvtd_l);
2534     DEBUG_FPU_STATE();
2535     FORCE_RET();
2536 }
2537 FLOAT_OP(cvtl, d)
2538 {
2539     CALL_FROM_TB0(do_float_cvtl_d);
2540     DEBUG_FPU_STATE();
2541     FORCE_RET();
2542 }
2543 FLOAT_OP(cvtl, s)
2544 {
2545     CALL_FROM_TB0(do_float_cvtl_s);
2546     DEBUG_FPU_STATE();
2547     FORCE_RET();
2548 }
2549 FLOAT_OP(cvtps, s)
2550 {
2551     WT2 = WT0;
2552     WTH2 = WT1;
2553     DEBUG_FPU_STATE();
2554     FORCE_RET();
2555 }
2556 FLOAT_OP(cvtps, pw)
2557 {
2558     CALL_FROM_TB0(do_float_cvtps_pw);
2559     DEBUG_FPU_STATE();
2560     FORCE_RET();
2561 }
2562 FLOAT_OP(cvtpw, ps)
2563 {
2564     CALL_FROM_TB0(do_float_cvtpw_ps);
2565     DEBUG_FPU_STATE();
2566     FORCE_RET();
2567 }
2568 FLOAT_OP(cvts, d)
2569 {
2570     CALL_FROM_TB0(do_float_cvts_d);
2571     DEBUG_FPU_STATE();
2572     FORCE_RET();
2573 }
2574 FLOAT_OP(cvts, w)
2575 {
2576     CALL_FROM_TB0(do_float_cvts_w);
2577     DEBUG_FPU_STATE();
2578     FORCE_RET();
2579 }
2580 FLOAT_OP(cvts, l)
2581 {
2582     CALL_FROM_TB0(do_float_cvts_l);
2583     DEBUG_FPU_STATE();
2584     FORCE_RET();
2585 }
2586 FLOAT_OP(cvts, pl)
2587 {
2588     CALL_FROM_TB0(do_float_cvts_pl);
2589     DEBUG_FPU_STATE();
2590     FORCE_RET();
2591 }
2592 FLOAT_OP(cvts, pu)
2593 {
2594     CALL_FROM_TB0(do_float_cvts_pu);
2595     DEBUG_FPU_STATE();
2596     FORCE_RET();
2597 }
2598 FLOAT_OP(cvtw, s)
2599 {
2600     CALL_FROM_TB0(do_float_cvtw_s);
2601     DEBUG_FPU_STATE();
2602     FORCE_RET();
2603 }
2604 FLOAT_OP(cvtw, d)
2605 {
2606     CALL_FROM_TB0(do_float_cvtw_d);
2607     DEBUG_FPU_STATE();
2608     FORCE_RET();
2609 }
2610
2611 FLOAT_OP(pll, ps)
2612 {
2613     DT2 = ((uint64_t)WT0 << 32) | WT1;
2614     DEBUG_FPU_STATE();
2615     FORCE_RET();
2616 }
2617 FLOAT_OP(plu, ps)
2618 {
2619     DT2 = ((uint64_t)WT0 << 32) | WTH1;
2620     DEBUG_FPU_STATE();
2621     FORCE_RET();
2622 }
2623 FLOAT_OP(pul, ps)
2624 {
2625     DT2 = ((uint64_t)WTH0 << 32) | WT1;
2626     DEBUG_FPU_STATE();
2627     FORCE_RET();
2628 }
2629 FLOAT_OP(puu, ps)
2630 {
2631     DT2 = ((uint64_t)WTH0 << 32) | WTH1;
2632     DEBUG_FPU_STATE();
2633     FORCE_RET();
2634 }
2635
2636 #define FLOAT_ROUNDOP(op, ttype, stype)                    \
2637 FLOAT_OP(op ## ttype, stype)                               \
2638 {                                                          \
2639     CALL_FROM_TB0(do_float_ ## op ## ttype ## _ ## stype); \
2640     DEBUG_FPU_STATE();                                     \
2641     FORCE_RET();                                           \
2642 }
2643
2644 FLOAT_ROUNDOP(round, l, d)
2645 FLOAT_ROUNDOP(round, l, s)
2646 FLOAT_ROUNDOP(round, w, d)
2647 FLOAT_ROUNDOP(round, w, s)
2648
2649 FLOAT_ROUNDOP(trunc, l, d)
2650 FLOAT_ROUNDOP(trunc, l, s)
2651 FLOAT_ROUNDOP(trunc, w, d)
2652 FLOAT_ROUNDOP(trunc, w, s)
2653
2654 FLOAT_ROUNDOP(ceil, l, d)
2655 FLOAT_ROUNDOP(ceil, l, s)
2656 FLOAT_ROUNDOP(ceil, w, d)
2657 FLOAT_ROUNDOP(ceil, w, s)
2658
2659 FLOAT_ROUNDOP(floor, l, d)
2660 FLOAT_ROUNDOP(floor, l, s)
2661 FLOAT_ROUNDOP(floor, w, d)
2662 FLOAT_ROUNDOP(floor, w, s)
2663 #undef FLOAR_ROUNDOP
2664
2665 FLOAT_OP(movf, d)
2666 {
2667     if (!(env->fpu->fcr31 & PARAM1))
2668         DT2 = DT0;
2669     DEBUG_FPU_STATE();
2670     FORCE_RET();
2671 }
2672 FLOAT_OP(movf, s)
2673 {
2674     if (!(env->fpu->fcr31 & PARAM1))
2675         WT2 = WT0;
2676     DEBUG_FPU_STATE();
2677     FORCE_RET();
2678 }
2679 FLOAT_OP(movf, ps)
2680 {
2681     if (!(env->fpu->fcr31 & PARAM1)) {
2682         WT2 = WT0;
2683         WTH2 = WTH0;
2684     }
2685     DEBUG_FPU_STATE();
2686     FORCE_RET();
2687 }
2688 FLOAT_OP(movt, d)
2689 {
2690     if (env->fpu->fcr31 & PARAM1)
2691         DT2 = DT0;
2692     DEBUG_FPU_STATE();
2693     FORCE_RET();
2694 }
2695 FLOAT_OP(movt, s)
2696 {
2697     if (env->fpu->fcr31 & PARAM1)
2698         WT2 = WT0;
2699     DEBUG_FPU_STATE();
2700     FORCE_RET();
2701 }
2702 FLOAT_OP(movt, ps)
2703 {
2704     if (env->fpu->fcr31 & PARAM1) {
2705         WT2 = WT0;
2706         WTH2 = WTH0;
2707     }
2708     DEBUG_FPU_STATE();
2709     FORCE_RET();
2710 }
2711 FLOAT_OP(movz, d)
2712 {
2713     if (!T0)
2714         DT2 = DT0;
2715     DEBUG_FPU_STATE();
2716     FORCE_RET();
2717 }
2718 FLOAT_OP(movz, s)
2719 {
2720     if (!T0)
2721         WT2 = WT0;
2722     DEBUG_FPU_STATE();
2723     FORCE_RET();
2724 }
2725 FLOAT_OP(movz, ps)
2726 {
2727     if (!T0) {
2728         WT2 = WT0;
2729         WTH2 = WTH0;
2730     }
2731     DEBUG_FPU_STATE();
2732     FORCE_RET();
2733 }
2734 FLOAT_OP(movn, d)
2735 {
2736     if (T0)
2737         DT2 = DT0;
2738     DEBUG_FPU_STATE();
2739     FORCE_RET();
2740 }
2741 FLOAT_OP(movn, s)
2742 {
2743     if (T0)
2744         WT2 = WT0;
2745     DEBUG_FPU_STATE();
2746     FORCE_RET();
2747 }
2748 FLOAT_OP(movn, ps)
2749 {
2750     if (T0) {
2751         WT2 = WT0;
2752         WTH2 = WTH0;
2753     }
2754     DEBUG_FPU_STATE();
2755     FORCE_RET();
2756 }
2757
2758 /* operations calling helpers, for s, d and ps */
2759 #define FLOAT_HOP(name)   \
2760 FLOAT_OP(name, d)         \
2761 {                         \
2762     CALL_FROM_TB0(do_float_ ## name ## _d);  \
2763     DEBUG_FPU_STATE();    \
2764     FORCE_RET();          \
2765 }                         \
2766 FLOAT_OP(name, s)         \
2767 {                         \
2768     CALL_FROM_TB0(do_float_ ## name ## _s);  \
2769     DEBUG_FPU_STATE();    \
2770     FORCE_RET();          \
2771 }                         \
2772 FLOAT_OP(name, ps)        \
2773 {                         \
2774     CALL_FROM_TB0(do_float_ ## name ## _ps); \
2775     DEBUG_FPU_STATE();    \
2776     FORCE_RET();          \
2777 }
2778 FLOAT_HOP(add)
2779 FLOAT_HOP(sub)
2780 FLOAT_HOP(mul)
2781 FLOAT_HOP(div)
2782 FLOAT_HOP(recip2)
2783 FLOAT_HOP(rsqrt2)
2784 FLOAT_HOP(rsqrt1)
2785 FLOAT_HOP(recip1)
2786 #undef FLOAT_HOP
2787
2788 /* operations calling helpers, for s and d */
2789 #define FLOAT_HOP(name)   \
2790 FLOAT_OP(name, d)         \
2791 {                         \
2792     CALL_FROM_TB0(do_float_ ## name ## _d);  \
2793     DEBUG_FPU_STATE();    \
2794     FORCE_RET();          \
2795 }                         \
2796 FLOAT_OP(name, s)         \
2797 {                         \
2798     CALL_FROM_TB0(do_float_ ## name ## _s);  \
2799     DEBUG_FPU_STATE();    \
2800     FORCE_RET();          \
2801 }
2802 FLOAT_HOP(rsqrt)
2803 FLOAT_HOP(recip)
2804 #undef FLOAT_HOP
2805
2806 /* operations calling helpers, for ps */
2807 #define FLOAT_HOP(name)   \
2808 FLOAT_OP(name, ps)        \
2809 {                         \
2810     CALL_FROM_TB0(do_float_ ## name ## _ps); \
2811     DEBUG_FPU_STATE();    \
2812     FORCE_RET();          \
2813 }
2814 FLOAT_HOP(addr)
2815 FLOAT_HOP(mulr)
2816 #undef FLOAT_HOP
2817
2818 /* ternary operations */
2819 #define FLOAT_TERNOP(name1, name2) \
2820 FLOAT_OP(name1 ## name2, d)        \
2821 {                                  \
2822     FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status);    \
2823     FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status);    \
2824     DEBUG_FPU_STATE();             \
2825     FORCE_RET();                   \
2826 }                                  \
2827 FLOAT_OP(name1 ## name2, s)        \
2828 {                                  \
2829     FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status);    \
2830     FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status);    \
2831     DEBUG_FPU_STATE();             \
2832     FORCE_RET();                   \
2833 }                                  \
2834 FLOAT_OP(name1 ## name2, ps)       \
2835 {                                  \
2836     FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status);    \
2837     FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \
2838     FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status);    \
2839     FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \
2840     DEBUG_FPU_STATE();             \
2841     FORCE_RET();                   \
2842 }
2843 FLOAT_TERNOP(mul, add)
2844 FLOAT_TERNOP(mul, sub)
2845 #undef FLOAT_TERNOP
2846
2847 /* negated ternary operations */
2848 #define FLOAT_NTERNOP(name1, name2) \
2849 FLOAT_OP(n ## name1 ## name2, d)    \
2850 {                                   \
2851     FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status);    \
2852     FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status);    \
2853     FDT2 = float64_chs(FDT2);       \
2854     DEBUG_FPU_STATE();              \
2855     FORCE_RET();                    \
2856 }                                   \
2857 FLOAT_OP(n ## name1 ## name2, s)    \
2858 {                                   \
2859     FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status);    \
2860     FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status);    \
2861     FST2 = float32_chs(FST2);       \
2862     DEBUG_FPU_STATE();              \
2863     FORCE_RET();                    \
2864 }                                   \
2865 FLOAT_OP(n ## name1 ## name2, ps)   \
2866 {                                   \
2867     FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status);    \
2868     FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \
2869     FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status);    \
2870     FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \
2871     FST2 = float32_chs(FST2);       \
2872     FSTH2 = float32_chs(FSTH2);     \
2873     DEBUG_FPU_STATE();              \
2874     FORCE_RET();                    \
2875 }
2876 FLOAT_NTERNOP(mul, add)
2877 FLOAT_NTERNOP(mul, sub)
2878 #undef FLOAT_NTERNOP
2879
2880 /* unary operations, modifying fp status  */
2881 #define FLOAT_UNOP(name)  \
2882 FLOAT_OP(name, d)         \
2883 {                         \
2884     FDT2 = float64_ ## name(FDT0, &env->fpu->fp_status); \
2885     DEBUG_FPU_STATE();    \
2886     FORCE_RET();          \
2887 }                         \
2888 FLOAT_OP(name, s)         \
2889 {                         \
2890     FST2 = float32_ ## name(FST0, &env->fpu->fp_status); \
2891     DEBUG_FPU_STATE();    \
2892     FORCE_RET();          \
2893 }
2894 FLOAT_UNOP(sqrt)
2895 #undef FLOAT_UNOP
2896
2897 /* unary operations, not modifying fp status  */
2898 #define FLOAT_UNOP(name)  \
2899 FLOAT_OP(name, d)         \
2900 {                         \
2901     FDT2 = float64_ ## name(FDT0);   \
2902     DEBUG_FPU_STATE();    \
2903     FORCE_RET();          \
2904 }                         \
2905 FLOAT_OP(name, s)         \
2906 {                         \
2907     FST2 = float32_ ## name(FST0);   \
2908     DEBUG_FPU_STATE();    \
2909     FORCE_RET();          \
2910 }                         \
2911 FLOAT_OP(name, ps)        \
2912 {                         \
2913     FST2 = float32_ ## name(FST0);   \
2914     FSTH2 = float32_ ## name(FSTH0); \
2915     DEBUG_FPU_STATE();    \
2916     FORCE_RET();          \
2917 }
2918 FLOAT_UNOP(abs)
2919 FLOAT_UNOP(chs)
2920 #undef FLOAT_UNOP
2921
2922 FLOAT_OP(mov, d)
2923 {
2924     FDT2 = FDT0;
2925     DEBUG_FPU_STATE();
2926     FORCE_RET();
2927 }
2928 FLOAT_OP(mov, s)
2929 {
2930     FST2 = FST0;
2931     DEBUG_FPU_STATE();
2932     FORCE_RET();
2933 }
2934 FLOAT_OP(mov, ps)
2935 {
2936     FST2 = FST0;
2937     FSTH2 = FSTH0;
2938     DEBUG_FPU_STATE();
2939     FORCE_RET();
2940 }
2941 FLOAT_OP(alnv, ps)
2942 {
2943     switch (T0 & 0x7) {
2944     case 0:
2945         FST2 = FST0;
2946         FSTH2 = FSTH0;
2947         break;
2948     case 4:
2949 #ifdef TARGET_WORDS_BIGENDIAN
2950         FSTH2 = FST0;
2951         FST2 = FSTH1;
2952 #else
2953         FSTH2 = FST1;
2954         FST2 = FSTH0;
2955 #endif
2956         break;
2957     default: /* unpredictable */
2958         break;
2959     }
2960     DEBUG_FPU_STATE();
2961     FORCE_RET();
2962 }
2963
2964 #ifdef CONFIG_SOFTFLOAT
2965 #define clear_invalid() do {                                \
2966     int flags = get_float_exception_flags(&env->fpu->fp_status); \
2967     flags &= ~float_flag_invalid;                           \
2968     set_float_exception_flags(flags, &env->fpu->fp_status); \
2969 } while(0)
2970 #else
2971 #define clear_invalid() do { } while(0)
2972 #endif
2973
2974 extern void dump_fpu_s(CPUState *env);
2975
2976 #define CMP_OP(fmt, op)                                \
2977 void OPPROTO op_cmp ## _ ## fmt ## _ ## op(void)       \
2978 {                                                      \
2979     CALL_FROM_TB1(do_cmp ## _ ## fmt ## _ ## op, PARAM1); \
2980     DEBUG_FPU_STATE();                                 \
2981     FORCE_RET();                                       \
2982 }                                                      \
2983 void OPPROTO op_cmpabs ## _ ## fmt ## _ ## op(void)    \
2984 {                                                      \
2985     CALL_FROM_TB1(do_cmpabs ## _ ## fmt ## _ ## op, PARAM1); \
2986     DEBUG_FPU_STATE();                                 \
2987     FORCE_RET();                                       \
2988 }
2989 #define CMP_OPS(op)   \
2990 CMP_OP(d, op)         \
2991 CMP_OP(s, op)         \
2992 CMP_OP(ps, op)
2993
2994 CMP_OPS(f)
2995 CMP_OPS(un)
2996 CMP_OPS(eq)
2997 CMP_OPS(ueq)
2998 CMP_OPS(olt)
2999 CMP_OPS(ult)
3000 CMP_OPS(ole)
3001 CMP_OPS(ule)
3002 CMP_OPS(sf)
3003 CMP_OPS(ngle)
3004 CMP_OPS(seq)
3005 CMP_OPS(ngl)
3006 CMP_OPS(lt)
3007 CMP_OPS(nge)
3008 CMP_OPS(le)
3009 CMP_OPS(ngt)
3010 #undef CMP_OPS
3011 #undef CMP_OP
3012
3013 void op_bc1f (void)
3014 {
3015     T0 = !!(~GET_FP_COND(env->fpu) & (0x1 << PARAM1));
3016     DEBUG_FPU_STATE();
3017     FORCE_RET();
3018 }
3019 void op_bc1any2f (void)
3020 {
3021     T0 = !!(~GET_FP_COND(env->fpu) & (0x3 << PARAM1));
3022     DEBUG_FPU_STATE();
3023     FORCE_RET();
3024 }
3025 void op_bc1any4f (void)
3026 {
3027     T0 = !!(~GET_FP_COND(env->fpu) & (0xf << PARAM1));
3028     DEBUG_FPU_STATE();
3029     FORCE_RET();
3030 }
3031
3032 void op_bc1t (void)
3033 {
3034     T0 = !!(GET_FP_COND(env->fpu) & (0x1 << PARAM1));
3035     DEBUG_FPU_STATE();
3036     FORCE_RET();
3037 }
3038 void op_bc1any2t (void)
3039 {
3040     T0 = !!(GET_FP_COND(env->fpu) & (0x3 << PARAM1));
3041     DEBUG_FPU_STATE();
3042     FORCE_RET();
3043 }
3044 void op_bc1any4t (void)
3045 {
3046     T0 = !!(GET_FP_COND(env->fpu) & (0xf << PARAM1));
3047     DEBUG_FPU_STATE();
3048     FORCE_RET();
3049 }
3050
3051 void op_tlbwi (void)
3052 {
3053     CALL_FROM_TB0(env->tlb->do_tlbwi);
3054     FORCE_RET();
3055 }
3056
3057 void op_tlbwr (void)
3058 {
3059     CALL_FROM_TB0(env->tlb->do_tlbwr);
3060     FORCE_RET();
3061 }
3062
3063 void op_tlbp (void)
3064 {
3065     CALL_FROM_TB0(env->tlb->do_tlbp);
3066     FORCE_RET();
3067 }
3068
3069 void op_tlbr (void)
3070 {
3071     CALL_FROM_TB0(env->tlb->do_tlbr);
3072     FORCE_RET();
3073 }
3074
3075 /* Specials */
3076 #if defined (CONFIG_USER_ONLY)
3077 void op_tls_value (void)
3078 {
3079     T0 = env->tls_value;
3080 }
3081 #endif
3082
3083 void op_pmon (void)
3084 {
3085     CALL_FROM_TB1(do_pmon, PARAM1);
3086     FORCE_RET();
3087 }
3088
3089 void op_di (void)
3090 {
3091     T0 = env->CP0_Status;
3092     env->CP0_Status = T0 & ~(1 << CP0St_IE);
3093     CALL_FROM_TB1(cpu_mips_update_irq, env);
3094     FORCE_RET();
3095 }
3096
3097 void op_ei (void)
3098 {
3099     T0 = env->CP0_Status;
3100     env->CP0_Status = T0 | (1 << CP0St_IE);
3101     CALL_FROM_TB1(cpu_mips_update_irq, env);
3102     FORCE_RET();
3103 }
3104
3105 void op_trap (void)
3106 {
3107     if (T0) {
3108         CALL_FROM_TB1(do_raise_exception, EXCP_TRAP);
3109     }
3110     FORCE_RET();
3111 }
3112
3113 void op_debug (void)
3114 {
3115     CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG);
3116     FORCE_RET();
3117 }
3118
3119 void op_set_lladdr (void)
3120 {
3121     env->CP0_LLAddr = T2;
3122     FORCE_RET();
3123 }
3124
3125 void debug_pre_eret (void);
3126 void debug_post_eret (void);
3127 void op_eret (void)
3128 {
3129     if (loglevel & CPU_LOG_EXEC)
3130         CALL_FROM_TB0(debug_pre_eret);
3131     if (env->CP0_Status & (1 << CP0St_ERL)) {
3132         env->PC[env->current_tc] = env->CP0_ErrorEPC;
3133         env->CP0_Status &= ~(1 << CP0St_ERL);
3134     } else {
3135         env->PC[env->current_tc] = env->CP0_EPC;
3136         env->CP0_Status &= ~(1 << CP0St_EXL);
3137     }
3138     CALL_FROM_TB1(compute_hflags, env);
3139     if (loglevel & CPU_LOG_EXEC)
3140         CALL_FROM_TB0(debug_post_eret);
3141     env->CP0_LLAddr = 1;
3142     FORCE_RET();
3143 }
3144
3145 void op_deret (void)
3146 {
3147     if (loglevel & CPU_LOG_EXEC)
3148         CALL_FROM_TB0(debug_pre_eret);
3149     env->PC[env->current_tc] = env->CP0_DEPC;
3150     env->hflags &= MIPS_HFLAG_DM;
3151     CALL_FROM_TB1(compute_hflags, env);
3152     if (loglevel & CPU_LOG_EXEC)
3153         CALL_FROM_TB0(debug_post_eret);
3154     env->CP0_LLAddr = 1;
3155     FORCE_RET();
3156 }
3157
3158 void op_rdhwr_cpunum(void)
3159 {
3160     if ((env->hflags & MIPS_HFLAG_CP0) ||
3161         (env->CP0_HWREna & (1 << 0)))
3162         T0 = env->CP0_EBase & 0x3ff;
3163     else
3164         CALL_FROM_TB1(do_raise_exception, EXCP_RI);
3165     FORCE_RET();
3166 }
3167
3168 void op_rdhwr_synci_step(void)
3169 {
3170     if ((env->hflags & MIPS_HFLAG_CP0) ||
3171         (env->CP0_HWREna & (1 << 1)))
3172         T0 = env->SYNCI_Step;
3173     else
3174         CALL_FROM_TB1(do_raise_exception, EXCP_RI);
3175     FORCE_RET();
3176 }
3177
3178 void op_rdhwr_cc(void)
3179 {
3180     if ((env->hflags & MIPS_HFLAG_CP0) ||
3181         (env->CP0_HWREna & (1 << 2)))
3182         T0 = env->CP0_Count;
3183     else
3184         CALL_FROM_TB1(do_raise_exception, EXCP_RI);
3185     FORCE_RET();
3186 }
3187
3188 void op_rdhwr_ccres(void)
3189 {
3190     if ((env->hflags & MIPS_HFLAG_CP0) ||
3191         (env->CP0_HWREna & (1 << 3)))
3192         T0 = env->CCRes;
3193     else
3194         CALL_FROM_TB1(do_raise_exception, EXCP_RI);
3195     FORCE_RET();
3196 }
3197
3198 void op_save_state (void)
3199 {
3200     env->hflags = PARAM1;
3201     FORCE_RET();
3202 }
3203
3204 void op_save_pc (void)
3205 {
3206     env->PC[env->current_tc] = PARAM1;
3207     FORCE_RET();
3208 }
3209
3210 #if defined(TARGET_MIPS64)
3211 void op_save_pc64 (void)
3212 {
3213     env->PC[env->current_tc] = ((uint64_t)PARAM1 << 32) | (uint32_t)PARAM2;
3214     FORCE_RET();
3215 }
3216 #endif
3217
3218 void op_interrupt_restart (void)
3219 {
3220     if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
3221         !(env->CP0_Status & (1 << CP0St_ERL)) &&
3222         !(env->hflags & MIPS_HFLAG_DM) &&
3223         (env->CP0_Status & (1 << CP0St_IE)) &&
3224         (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask)) {
3225         env->CP0_Cause &= ~(0x1f << CP0Ca_EC);
3226         CALL_FROM_TB1(do_raise_exception, EXCP_EXT_INTERRUPT);
3227     }
3228     FORCE_RET();
3229 }
3230
3231 void op_raise_exception (void)
3232 {
3233     CALL_FROM_TB1(do_raise_exception, PARAM1);
3234     FORCE_RET();
3235 }
3236
3237 void op_raise_exception_err (void)
3238 {
3239     CALL_FROM_TB2(do_raise_exception_err, PARAM1, PARAM2);
3240     FORCE_RET();
3241 }
3242
3243 void op_wait (void)
3244 {
3245     env->halted = 1;
3246     CALL_FROM_TB1(do_raise_exception, EXCP_HLT);
3247     FORCE_RET();
3248 }
3249
3250 /* Bitfield operations. */
3251 void op_ext(void)
3252 {
3253     unsigned int pos = PARAM1;
3254     unsigned int size = PARAM2;
3255
3256     T0 = (int32_t)((T1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0));
3257     FORCE_RET();
3258 }
3259
3260 void op_ins(void)
3261 {
3262     unsigned int pos = PARAM1;
3263     unsigned int size = PARAM2;
3264     target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos;
3265
3266     T0 = (int32_t)((T0 & ~mask) | ((T1 << pos) & mask));
3267     FORCE_RET();
3268 }
3269
3270 void op_wsbh(void)
3271 {
3272     T0 = (int32_t)(((T1 << 8) & ~0x00FF00FF) | ((T1 >> 8) & 0x00FF00FF));
3273     FORCE_RET();
3274 }
3275
3276 #if defined(TARGET_MIPS64)
3277 void op_dext(void)
3278 {
3279     unsigned int pos = PARAM1;
3280     unsigned int size = PARAM2;
3281
3282     T0 = (T1 >> pos) & ((size < 64) ? ((1ULL << size) - 1) : ~0ULL);
3283     FORCE_RET();
3284 }
3285
3286 void op_dins(void)
3287 {
3288     unsigned int pos = PARAM1;
3289     unsigned int size = PARAM2;
3290     target_ulong mask = ((size < 64) ? ((1ULL << size) - 1) : ~0ULL) << pos;
3291
3292     T0 = (T0 & ~mask) | ((T1 << pos) & mask);
3293     FORCE_RET();
3294 }
3295
3296 void op_dsbh(void)
3297 {
3298     T0 = ((T1 << 8) & ~0x00FF00FF00FF00FFULL) | ((T1 >> 8) & 0x00FF00FF00FF00FFULL);
3299     FORCE_RET();
3300 }
3301
3302 void op_dshd(void)
3303 {
3304     T1 = ((T1 << 16) & ~0x0000FFFF0000FFFFULL) | ((T1 >> 16) & 0x0000FFFF0000FFFFULL);
3305     T0 = (T1 << 32) | (T1 >> 32);
3306     FORCE_RET();
3307 }
3308 #endif
3309
3310 void op_seb(void)
3311 {
3312     T0 = ((T1 & 0xFF) ^ 0x80) - 0x80;
3313     FORCE_RET();
3314 }
3315
3316 void op_seh(void)
3317 {
3318     T0 = ((T1 & 0xFFFF) ^ 0x8000) - 0x8000;
3319     FORCE_RET();
3320 }