Add MIPS32R2 instructions, and generally straighten out the instruction
[qemu] / 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  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include "config.h"
23 #include "exec.h"
24
25 #ifndef CALL_FROM_TB0
26 #define CALL_FROM_TB0(func) func();
27 #endif
28 #ifndef CALL_FROM_TB1
29 #define CALL_FROM_TB1(func, arg0) func(arg0);
30 #endif
31 #ifndef CALL_FROM_TB1_CONST16
32 #define CALL_FROM_TB1_CONST16(func, arg0) CALL_FROM_TB1(func, arg0);
33 #endif
34 #ifndef CALL_FROM_TB2
35 #define CALL_FROM_TB2(func, arg0, arg1) func(arg0, arg1);
36 #endif
37 #ifndef CALL_FROM_TB2_CONST16
38 #define CALL_FROM_TB2_CONST16(func, arg0, arg1)     \
39 CALL_FROM_TB2(func, arg0, arg1);
40 #endif
41 #ifndef CALL_FROM_TB3
42 #define CALL_FROM_TB3(func, arg0, arg1, arg2) func(arg0, arg1, arg2);
43 #endif
44 #ifndef CALL_FROM_TB4
45 #define CALL_FROM_TB4(func, arg0, arg1, arg2, arg3) \
46         func(arg0, arg1, arg2, arg3);
47 #endif
48
49 #define REG 1
50 #include "op_template.c"
51 #undef REG
52 #define REG 2
53 #include "op_template.c"
54 #undef REG
55 #define REG 3
56 #include "op_template.c"
57 #undef REG
58 #define REG 4
59 #include "op_template.c"
60 #undef REG
61 #define REG 5
62 #include "op_template.c"
63 #undef REG
64 #define REG 6
65 #include "op_template.c"
66 #undef REG
67 #define REG 7
68 #include "op_template.c"
69 #undef REG
70 #define REG 8
71 #include "op_template.c"
72 #undef REG
73 #define REG 9
74 #include "op_template.c"
75 #undef REG
76 #define REG 10
77 #include "op_template.c"
78 #undef REG
79 #define REG 11
80 #include "op_template.c"
81 #undef REG
82 #define REG 12
83 #include "op_template.c"
84 #undef REG
85 #define REG 13
86 #include "op_template.c"
87 #undef REG
88 #define REG 14
89 #include "op_template.c"
90 #undef REG
91 #define REG 15
92 #include "op_template.c"
93 #undef REG
94 #define REG 16
95 #include "op_template.c"
96 #undef REG
97 #define REG 17
98 #include "op_template.c"
99 #undef REG
100 #define REG 18
101 #include "op_template.c"
102 #undef REG
103 #define REG 19
104 #include "op_template.c"
105 #undef REG
106 #define REG 20
107 #include "op_template.c"
108 #undef REG
109 #define REG 21
110 #include "op_template.c"
111 #undef REG
112 #define REG 22
113 #include "op_template.c"
114 #undef REG
115 #define REG 23
116 #include "op_template.c"
117 #undef REG
118 #define REG 24
119 #include "op_template.c"
120 #undef REG
121 #define REG 25
122 #include "op_template.c"
123 #undef REG
124 #define REG 26
125 #include "op_template.c"
126 #undef REG
127 #define REG 27
128 #include "op_template.c"
129 #undef REG
130 #define REG 28
131 #include "op_template.c"
132 #undef REG
133 #define REG 29
134 #include "op_template.c"
135 #undef REG
136 #define REG 30
137 #include "op_template.c"
138 #undef REG
139 #define REG 31
140 #include "op_template.c"
141 #undef REG
142
143 #define TN T0
144 #include "op_template.c"
145 #undef TN
146 #define TN T1
147 #include "op_template.c"
148 #undef TN
149 #define TN T2
150 #include "op_template.c"
151 #undef TN
152
153 #ifdef MIPS_USES_FPU
154
155 #define SFREG 0
156 #define DFREG 0
157 #include "fop_template.c"
158 #undef SFREG
159 #undef DFREG
160 #define SFREG 1
161 #include "fop_template.c"
162 #undef SFREG
163 #define SFREG 2
164 #define DFREG 2
165 #include "fop_template.c"
166 #undef SFREG
167 #undef DFREG
168 #define SFREG 3
169 #include "fop_template.c"
170 #undef SFREG
171 #define SFREG 4
172 #define DFREG 4
173 #include "fop_template.c"
174 #undef SFREG
175 #undef DFREG
176 #define SFREG 5
177 #include "fop_template.c"
178 #undef SFREG
179 #define SFREG 6
180 #define DFREG 6
181 #include "fop_template.c"
182 #undef SFREG
183 #undef DFREG
184 #define SFREG 7
185 #include "fop_template.c"
186 #undef SFREG
187 #define SFREG 8
188 #define DFREG 8
189 #include "fop_template.c"
190 #undef SFREG
191 #undef DFREG
192 #define SFREG 9
193 #include "fop_template.c"
194 #undef SFREG
195 #define SFREG 10
196 #define DFREG 10
197 #include "fop_template.c"
198 #undef SFREG
199 #undef DFREG
200 #define SFREG 11
201 #include "fop_template.c"
202 #undef SFREG
203 #define SFREG 12
204 #define DFREG 12
205 #include "fop_template.c"
206 #undef SFREG
207 #undef DFREG
208 #define SFREG 13
209 #include "fop_template.c"
210 #undef SFREG
211 #define SFREG 14
212 #define DFREG 14
213 #include "fop_template.c"
214 #undef SFREG
215 #undef DFREG
216 #define SFREG 15
217 #include "fop_template.c"
218 #undef SFREG
219 #define SFREG 16
220 #define DFREG 16
221 #include "fop_template.c"
222 #undef SFREG
223 #undef DFREG
224 #define SFREG 17
225 #include "fop_template.c"
226 #undef SFREG
227 #define SFREG 18
228 #define DFREG 18
229 #include "fop_template.c"
230 #undef SFREG
231 #undef DFREG
232 #define SFREG 19
233 #include "fop_template.c"
234 #undef SFREG
235 #define SFREG 20
236 #define DFREG 20
237 #include "fop_template.c"
238 #undef SFREG
239 #undef DFREG
240 #define SFREG 21
241 #include "fop_template.c"
242 #undef SFREG
243 #define SFREG 22
244 #define DFREG 22
245 #include "fop_template.c"
246 #undef SFREG
247 #undef DFREG
248 #define SFREG 23
249 #include "fop_template.c"
250 #undef SFREG
251 #define SFREG 24
252 #define DFREG 24
253 #include "fop_template.c"
254 #undef SFREG
255 #undef DFREG
256 #define SFREG 25
257 #include "fop_template.c"
258 #undef SFREG
259 #define SFREG 26
260 #define DFREG 26
261 #include "fop_template.c"
262 #undef SFREG
263 #undef DFREG
264 #define SFREG 27
265 #include "fop_template.c"
266 #undef SFREG
267 #define SFREG 28
268 #define DFREG 28
269 #include "fop_template.c"
270 #undef SFREG
271 #undef DFREG
272 #define SFREG 29
273 #include "fop_template.c"
274 #undef SFREG
275 #define SFREG 30
276 #define DFREG 30
277 #include "fop_template.c"
278 #undef SFREG
279 #undef DFREG
280 #define SFREG 31
281 #include "fop_template.c"
282 #undef SFREG
283
284 #define FTN
285 #include "fop_template.c"
286 #undef FTN
287
288 #endif
289
290 void op_dup_T0 (void)
291 {
292     T2 = T0;
293     RETURN();
294 }
295
296 void op_load_HI (void)
297 {
298     T0 = env->HI;
299     RETURN();
300 }
301
302 void op_store_HI (void)
303 {
304     env->HI = T0;
305     RETURN();
306 }
307
308 void op_load_LO (void)
309 {
310     T0 = env->LO;
311     RETURN();
312 }
313
314 void op_store_LO (void)
315 {
316     env->LO = T0;
317     RETURN();
318 }
319
320 /* Load and store */
321 #define MEMSUFFIX _raw
322 #include "op_mem.c"
323 #undef MEMSUFFIX
324 #if !defined(CONFIG_USER_ONLY)
325 #define MEMSUFFIX _user
326 #include "op_mem.c"
327 #undef MEMSUFFIX
328
329 #define MEMSUFFIX _kernel
330 #include "op_mem.c"
331 #undef MEMSUFFIX
332 #endif
333
334 /* Arithmetic */
335 void op_add (void)
336 {
337     T0 += T1;
338     RETURN();
339 }
340
341 void op_addo (void)
342 {
343     target_ulong tmp;
344
345     tmp = T0;
346     T0 += T1;
347     if (((tmp ^ T1 ^ (-1)) & (T0 ^ T1)) >> 31) {
348        /* operands of same sign, result different sign */
349         CALL_FROM_TB1(do_raise_exception_direct, EXCP_OVERFLOW);
350     }
351     RETURN();
352 }
353
354 void op_sub (void)
355 {
356     T0 -= T1;
357     RETURN();
358 }
359
360 void op_subo (void)
361 {
362     target_ulong tmp;
363
364     tmp = T0;
365     T0 = (int32_t)T0 - (int32_t)T1;
366     if (((tmp ^ T1) & (tmp ^ T0)) >> 31) {
367        /* operands of different sign, first operand and result different sign */
368         CALL_FROM_TB1(do_raise_exception_direct, EXCP_OVERFLOW);
369     }
370     RETURN();
371 }
372
373 void op_mul (void)
374 {
375     T0 = (int32_t)T0 * (int32_t)T1;
376     RETURN();
377 }
378
379 void op_div (void)
380 {
381     if (T1 != 0) {
382         env->LO = (int32_t)T0 / (int32_t)T1;
383         env->HI = (int32_t)T0 % (int32_t)T1;
384     }
385     RETURN();
386 }
387
388 void op_divu (void)
389 {
390     if (T1 != 0) {
391         env->LO = T0 / T1;
392         env->HI = T0 % T1;
393     }
394     RETURN();
395 }
396
397 /* Logical */
398 void op_and (void)
399 {
400     T0 &= T1;
401     RETURN();
402 }
403
404 void op_nor (void)
405 {
406     T0 = ~(T0 | T1);
407     RETURN();
408 }
409
410 void op_or (void)
411 {
412     T0 |= T1;
413     RETURN();
414 }
415
416 void op_xor (void)
417 {
418     T0 ^= T1;
419     RETURN();
420 }
421
422 void op_sll (void)
423 {
424     T0 = T0 << T1;
425     RETURN();
426 }
427
428 void op_sra (void)
429 {
430     T0 = (int32_t)T0 >> T1;
431     RETURN();
432 }
433
434 void op_srl (void)
435 {
436     T0 = T0 >> T1;
437     RETURN();
438 }
439
440 void op_rotr (void)
441 {
442     target_ulong tmp;
443
444     if (T1) {
445        tmp = T0 << (0x20 - T1);
446        T0 = (T0 >> T1) | tmp;
447     } else
448        T0 = T1;
449     RETURN();
450 }
451
452 void op_sllv (void)
453 {
454     T0 = T1 << (T0 & 0x1F);
455     RETURN();
456 }
457
458 void op_srav (void)
459 {
460     T0 = (int32_t)T1 >> (T0 & 0x1F);
461     RETURN();
462 }
463
464 void op_srlv (void)
465 {
466     T0 = T1 >> (T0 & 0x1F);
467     RETURN();
468 }
469
470 void op_rotrv (void)
471 {
472     target_ulong tmp;
473
474     T0 &= 0x1F;
475     if (T0) {
476        tmp = T1 << (0x20 - T0);
477        T0 = (T1 >> T0) | tmp;
478     } else
479        T0 = T1;
480     RETURN();
481 }
482
483 void op_clo (void)
484 {
485     int n;
486
487     if (T0 == (target_ulong)-1) {
488         T0 = 32;
489     } else {
490         for (n = 0; n < 32; n++) {
491             if (!(T0 & (1 << 31)))
492                 break;
493             T0 = T0 << 1;
494         }
495         T0 = n;
496     }
497     RETURN();
498 }
499
500 void op_clz (void)
501 {
502     int n;
503
504     if (T0 == 0) {
505         T0 = 32;
506     } else {
507         for (n = 0; n < 32; n++) {
508             if (T0 & (1 << 31))
509                 break;
510             T0 = T0 << 1;
511         }
512         T0 = n;
513     }
514     RETURN();
515 }
516
517 /* 64 bits arithmetic */
518 #if (HOST_LONG_BITS == 64)
519 static inline uint64_t get_HILO (void)
520 {
521     return ((uint64_t)env->HI << 32) | (uint64_t)env->LO;
522 }
523
524 static inline void set_HILO (uint64_t HILO)
525 {
526     env->LO = HILO & 0xFFFFFFFF;
527     env->HI = HILO >> 32;
528 }
529
530 void op_mult (void)
531 {
532     set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
533     RETURN();
534 }
535
536 void op_multu (void)
537 {
538     set_HILO((uint64_t)T0 * (uint64_t)T1);
539     RETURN();
540 }
541
542 void op_madd (void)
543 {
544     int64_t tmp;
545
546     tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
547     set_HILO((int64_t)get_HILO() + tmp);
548     RETURN();
549 }
550
551 void op_maddu (void)
552 {
553     uint64_t tmp;
554
555     tmp = ((uint64_t)T0 * (uint64_t)T1);
556     set_HILO(get_HILO() + tmp);
557     RETURN();
558 }
559
560 void op_msub (void)
561 {
562     int64_t tmp;
563
564     tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
565     set_HILO((int64_t)get_HILO() - tmp);
566     RETURN();
567 }
568
569 void op_msubu (void)
570 {
571     uint64_t tmp;
572
573     tmp = ((uint64_t)T0 * (uint64_t)T1);
574     set_HILO(get_HILO() - tmp);
575     RETURN();
576 }
577 #else
578 void op_mult (void)
579 {
580     CALL_FROM_TB0(do_mult);
581     RETURN();
582 }
583
584 void op_multu (void)
585 {
586     CALL_FROM_TB0(do_multu);
587     RETURN();
588 }
589
590 void op_madd (void)
591 {
592     CALL_FROM_TB0(do_madd);
593     RETURN();
594 }
595
596 void op_maddu (void)
597 {
598     CALL_FROM_TB0(do_maddu);
599     RETURN();
600 }
601
602 void op_msub (void)
603 {
604     CALL_FROM_TB0(do_msub);
605     RETURN();
606 }
607
608 void op_msubu (void)
609 {
610     CALL_FROM_TB0(do_msubu);
611     RETURN();
612 }
613 #endif
614
615 /* Conditional moves */
616 void op_movn (void)
617 {
618     if (T1 != 0)
619         env->gpr[PARAM1] = T0;
620     RETURN();
621 }
622
623 void op_movz (void)
624 {
625     if (T1 == 0)
626         env->gpr[PARAM1] = T0;
627     RETURN();
628 }
629
630 void op_movf (void)
631 {
632     if (!(env->fcr31 & PARAM1))
633         env->gpr[PARAM2] = env->gpr[PARAM3];
634     RETURN();
635 }
636
637 void op_movt (void)
638 {
639     if (env->fcr31 & PARAM1)
640         env->gpr[PARAM2] = env->gpr[PARAM3];
641     RETURN();
642 }
643
644 /* Tests */
645 #define OP_COND(name, cond) \
646 void glue(op_, name) (void) \
647 {                           \
648     if (cond) {             \
649         T0 = 1;             \
650     } else {                \
651         T0 = 0;             \
652     }                       \
653     RETURN();               \
654 }
655
656 OP_COND(eq, T0 == T1);
657 OP_COND(ne, T0 != T1);
658 OP_COND(ge, (int32_t)T0 >= (int32_t)T1);
659 OP_COND(geu, T0 >= T1);
660 OP_COND(lt, (int32_t)T0 < (int32_t)T1);
661 OP_COND(ltu, T0 < T1);
662 OP_COND(gez, (int32_t)T0 >= 0);
663 OP_COND(gtz, (int32_t)T0 > 0);
664 OP_COND(lez, (int32_t)T0 <= 0);
665 OP_COND(ltz, (int32_t)T0 < 0);
666
667 /* Branches */
668 //#undef USE_DIRECT_JUMP
669
670 void OPPROTO op_goto_tb0(void)
671 {
672     GOTO_TB(op_goto_tb0, PARAM1, 0);
673     RETURN();
674 }
675
676 void OPPROTO op_goto_tb1(void)
677 {
678     GOTO_TB(op_goto_tb1, PARAM1, 1);
679     RETURN();
680 }
681
682 /* Branch to register */
683 void op_save_breg_target (void)
684 {
685     env->btarget = T2;
686     RETURN();
687 }
688
689 void op_restore_breg_target (void)
690 {
691     T2 = env->btarget;
692     RETURN();
693 }
694
695 void op_breg (void)
696 {
697     env->PC = T2;
698     RETURN();
699 }
700
701 void op_save_btarget (void)
702 {
703     env->btarget = PARAM1;
704     RETURN();
705 }
706
707 /* Conditional branch */
708 void op_set_bcond (void)
709 {
710     T2 = T0;
711     RETURN();
712 }
713
714 void op_save_bcond (void)
715 {
716     env->bcond = T2;
717     RETURN();
718 }
719
720 void op_restore_bcond (void)
721 {
722     T2 = env->bcond;
723     RETURN();
724 }
725
726 void op_jnz_T2 (void)
727 {
728     if (T2)
729         GOTO_LABEL_PARAM(1);
730     RETURN();
731 }
732
733 /* CP0 functions */
734 void op_mfc0_index (void)
735 {
736     T0 = env->CP0_index;
737     RETURN();
738 }
739
740 void op_mfc0_random (void)
741 {
742     CALL_FROM_TB0(do_mfc0_random);
743     RETURN();
744 }
745
746 void op_mfc0_entrylo0 (void)
747 {
748     T0 = env->CP0_EntryLo0;
749     RETURN();
750 }
751
752 void op_mfc0_entrylo1 (void)
753 {
754     T0 = env->CP0_EntryLo1;
755     RETURN();
756 }
757
758 void op_mfc0_context (void)
759 {
760     T0 = env->CP0_Context;
761     RETURN();
762 }
763
764 void op_mfc0_pagemask (void)
765 {
766     T0 = env->CP0_PageMask;
767     RETURN();
768 }
769
770 void op_mfc0_pagegrain (void)
771 {
772     T0 = env->CP0_PageGrain;
773     RETURN();
774 }
775
776 void op_mfc0_wired (void)
777 {
778     T0 = env->CP0_Wired;
779     RETURN();
780 }
781
782 void op_mfc0_hwrena (void)
783 {
784     T0 = env->CP0_HWREna;
785     RETURN();
786 }
787
788 void op_mfc0_badvaddr (void)
789 {
790     T0 = env->CP0_BadVAddr;
791     RETURN();
792 }
793
794 void op_mfc0_count (void)
795 {
796     CALL_FROM_TB0(do_mfc0_count);
797     RETURN();
798 }
799
800 void op_mfc0_entryhi (void)
801 {
802     T0 = env->CP0_EntryHi;
803     RETURN();
804 }
805
806 void op_mfc0_compare (void)
807 {
808     T0 = env->CP0_Compare;
809     RETURN();
810 }
811
812 void op_mfc0_status (void)
813 {
814     T0 = env->CP0_Status;
815     if (env->hflags & MIPS_HFLAG_UM)
816         T0 |= (1 << CP0St_UM);
817     if (env->hflags & MIPS_HFLAG_ERL)
818         T0 |= (1 << CP0St_ERL);
819     if (env->hflags & MIPS_HFLAG_EXL)
820         T0 |= (1 << CP0St_EXL);
821     RETURN();
822 }
823
824 void op_mfc0_intctl (void)
825 {
826     T0 = env->CP0_IntCtl;
827     RETURN();
828 }
829
830 void op_mfc0_srsctl (void)
831 {
832     T0 = env->CP0_SRSCtl;
833     RETURN();
834 }
835
836 void op_mfc0_cause (void)
837 {
838     T0 = env->CP0_Cause;
839     RETURN();
840 }
841
842 void op_mfc0_epc (void)
843 {
844     T0 = env->CP0_EPC;
845     RETURN();
846 }
847
848 void op_mfc0_prid (void)
849 {
850     T0 = env->CP0_PRid;
851     RETURN();
852 }
853
854 void op_mfc0_ebase (void)
855 {
856     T0 = env->CP0_EBase;
857     RETURN();
858 }
859
860 void op_mfc0_config0 (void)
861 {
862     T0 = env->CP0_Config0;
863     RETURN();
864 }
865
866 void op_mfc0_config1 (void)
867 {
868     T0 = env->CP0_Config1;
869     RETURN();
870 }
871
872 void op_mfc0_config2 (void)
873 {
874     T0 = env->CP0_Config2;
875     RETURN();
876 }
877
878 void op_mfc0_config3 (void)
879 {
880     T0 = env->CP0_Config3;
881     RETURN();
882 }
883
884 void op_mfc0_lladdr (void)
885 {
886     T0 = env->CP0_LLAddr >> 4;
887     RETURN();
888 }
889
890 void op_mfc0_watchlo0 (void)
891 {
892     T0 = env->CP0_WatchLo;
893     RETURN();
894 }
895
896 void op_mfc0_watchhi0 (void)
897 {
898     T0 = env->CP0_WatchHi;
899     RETURN();
900 }
901
902 void op_mfc0_xcontext (void)
903 {
904     T0 = env->CP0_XContext;
905     RETURN();
906 }
907
908 void op_mfc0_framemask (void)
909 {
910     T0 = env->CP0_Framemask;
911     RETURN();
912 }
913
914 void op_mfc0_debug (void)
915 {
916     T0 = env->CP0_Debug;
917     if (env->hflags & MIPS_HFLAG_DM)
918         T0 |= 1 << CP0DB_DM;
919     RETURN();
920 }
921
922 void op_mfc0_depc (void)
923 {
924     T0 = env->CP0_DEPC;
925     RETURN();
926 }
927
928 void op_mfc0_performance0 (void)
929 {
930     T0 = env->CP0_Performance0;
931     RETURN();
932 }
933
934 void op_mfc0_taglo (void)
935 {
936     T0 = env->CP0_TagLo;
937     RETURN();
938 }
939
940 void op_mfc0_datalo (void)
941 {
942     T0 = env->CP0_DataLo;
943     RETURN();
944 }
945
946 void op_mfc0_taghi (void)
947 {
948     T0 = env->CP0_TagHi;
949     RETURN();
950 }
951
952 void op_mfc0_datahi (void)
953 {
954     T0 = env->CP0_DataHi;
955     RETURN();
956 }
957
958 void op_mfc0_errorepc (void)
959 {
960     T0 = env->CP0_ErrorEPC;
961     RETURN();
962 }
963
964 void op_mfc0_desave (void)
965 {
966     T0 = env->CP0_DESAVE;
967     RETURN();
968 }
969
970 void op_mtc0_index (void)
971 {
972     env->CP0_index = (env->CP0_index & 0x80000000) | (T0 & (MIPS_TLB_NB - 1));
973     RETURN();
974 }
975
976 void op_mtc0_entrylo0 (void)
977 {
978     /* Large physaddr not implemented */
979     /* 1k pages not implemented */
980     env->CP0_EntryLo0 = T0 & 0x3FFFFFFFUL;
981     RETURN();
982 }
983
984 void op_mtc0_entrylo1 (void)
985 {
986     /* Large physaddr not implemented */
987     /* 1k pages not implemented */
988     env->CP0_EntryLo1 = T0 & 0x3FFFFFFFUL;
989     RETURN();
990 }
991
992 void op_mtc0_context (void)
993 {
994     env->CP0_Context = (env->CP0_Context & ~0x007FFFFF) | (T0 & 0x007FFFF0);
995     RETURN();
996 }
997
998 void op_mtc0_pagemask (void)
999 {
1000     /* 1k pages not implemented */
1001     env->CP0_PageMask = T0 & 0x1FFFE000;
1002     RETURN();
1003 }
1004
1005 void op_mtc0_pagegrain (void)
1006 {
1007     /* SmartMIPS not implemented */
1008     /* Large physaddr not implemented */
1009     /* 1k pages not implemented */
1010     env->CP0_PageGrain = 0;
1011     RETURN();
1012 }
1013
1014 void op_mtc0_wired (void)
1015 {
1016     env->CP0_Wired = T0 & (MIPS_TLB_NB - 1);
1017     RETURN();
1018 }
1019
1020 void op_mtc0_hwrena (void)
1021 {
1022     env->CP0_HWREna = T0 & 0x0000000F;
1023     RETURN();
1024 }
1025
1026 void op_mtc0_count (void)
1027 {
1028     CALL_FROM_TB2(cpu_mips_store_count, env, T0);
1029     RETURN();
1030 }
1031
1032 void op_mtc0_entryhi (void)
1033 {
1034     uint32_t old, val;
1035
1036     /* 1k pages not implemented */
1037     /* Ignore MIPS64 TLB for now */
1038     val = T0 & 0xFFFFE0FF;
1039     old = env->CP0_EntryHi;
1040     env->CP0_EntryHi = val;
1041     /* If the ASID changes, flush qemu's TLB.  */
1042     if ((old & 0xFF) != (val & 0xFF))
1043         CALL_FROM_TB2(cpu_mips_tlb_flush, env, 1);
1044     RETURN();
1045 }
1046
1047 void op_mtc0_compare (void)
1048 {
1049     CALL_FROM_TB2(cpu_mips_store_compare, env, T0);
1050     RETURN();
1051 }
1052
1053 void op_mtc0_status (void)
1054 {
1055     uint32_t val, old, mask;
1056
1057     val = T0 & 0xFA78FF01;
1058     old = env->CP0_Status;
1059     if (T0 & (1 << CP0St_UM))
1060         env->hflags |= MIPS_HFLAG_UM;
1061     else
1062         env->hflags &= ~MIPS_HFLAG_UM;
1063     if (T0 & (1 << CP0St_ERL))
1064         env->hflags |= MIPS_HFLAG_ERL;
1065     else
1066         env->hflags &= ~MIPS_HFLAG_ERL;
1067     if (T0 & (1 << CP0St_EXL))
1068         env->hflags |= MIPS_HFLAG_EXL;
1069     else
1070         env->hflags &= ~MIPS_HFLAG_EXL;
1071     env->CP0_Status = val;
1072     /* If we unmasked an asserted IRQ, raise it */
1073     mask = 0x0000FF00;
1074     if (loglevel & CPU_LOG_TB_IN_ASM)
1075        CALL_FROM_TB2(do_mtc0_status_debug, old, val);
1076     if ((val & (1 << CP0St_IE)) && !(old & (1 << CP0St_IE)) &&
1077         !(env->hflags & MIPS_HFLAG_EXL) &&
1078         !(env->hflags & MIPS_HFLAG_ERL) &&
1079         !(env->hflags & MIPS_HFLAG_DM) &&
1080         (env->CP0_Status & env->CP0_Cause & mask)) {
1081         env->interrupt_request |= CPU_INTERRUPT_HARD;
1082        if (logfile)
1083            CALL_FROM_TB0(do_mtc0_status_irqraise_debug);
1084     } else if (!(val & (1 << CP0St_IE)) && (old & (1 << CP0St_IE))) {
1085         env->interrupt_request &= ~CPU_INTERRUPT_HARD;
1086     }
1087     RETURN();
1088 }
1089
1090 void op_mtc0_intctl (void)
1091 {
1092     /* vectored interrupts not implemented */
1093     env->CP0_IntCtl = 0;
1094     RETURN();
1095 }
1096
1097 void op_mtc0_srsctl (void)
1098 {
1099     /* shadow registers not implemented */
1100     env->CP0_SRSCtl = 0;
1101     RETURN();
1102 }
1103
1104 void op_mtc0_cause (void)
1105 {
1106     uint32_t val, old;
1107
1108     val = (env->CP0_Cause & 0xB000F87C) | (T0 & 0x000C00300);
1109     old = env->CP0_Cause;
1110     env->CP0_Cause = val;
1111 #if 0
1112     {
1113         int i, mask;
1114        /* Check if we ever asserted a software IRQ */
1115         for (i = 0; i < 2; i++) {
1116             mask = 0x100 << i;
1117             if ((val & mask) & !(old & mask))
1118                 CALL_FROM_TB1(mips_set_irq, i);
1119         }
1120     }
1121 #endif
1122     RETURN();
1123 }
1124
1125 void op_mtc0_epc (void)
1126 {
1127     env->CP0_EPC = T0;
1128     RETURN();
1129 }
1130
1131 void op_mtc0_ebase (void)
1132 {
1133     /* vectored interrupts not implemented */
1134     /* Multi-CPU not implemented */
1135     env->CP0_EBase = 0x80000000 | (T0 & 0x3FFFF000);
1136     RETURN();
1137 }
1138
1139 void op_mtc0_config0 (void)
1140 {
1141 #if defined(MIPS_USES_R4K_TLB)
1142      /* Fixed mapping MMU not implemented */
1143     env->CP0_Config0 = (env->CP0_Config0 & 0x8017FF88) | (T0 & 0x00000001);
1144 #else
1145     env->CP0_Config0 = (env->CP0_Config0 & 0xFE17FF88) | (T0 & 0x00000001);
1146 #endif
1147     RETURN();
1148 }
1149
1150 void op_mtc0_config2 (void)
1151 {
1152     /* tertiary/secondary caches not implemented */
1153     env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
1154     RETURN();
1155 }
1156
1157 void op_mtc0_watchlo0 (void)
1158 {
1159     env->CP0_WatchLo = T0;
1160     RETURN();
1161 }
1162
1163 void op_mtc0_watchhi0 (void)
1164 {
1165     env->CP0_WatchHi = T0 & 0x40FF0FF8;
1166     RETURN();
1167 }
1168
1169 void op_mtc0_xcontext (void)
1170 {
1171     env->CP0_XContext = T0; /* XXX */
1172     RETURN();
1173 }
1174
1175 void op_mtc0_framemask (void)
1176 {
1177     env->CP0_Framemask = T0; /* XXX */
1178     RETURN();
1179 }
1180
1181 void op_mtc0_debug (void)
1182 {
1183     env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120);
1184     if (T0 & (1 << CP0DB_DM))
1185         env->hflags |= MIPS_HFLAG_DM;
1186     else
1187         env->hflags &= ~MIPS_HFLAG_DM;
1188     RETURN();
1189 }
1190
1191 void op_mtc0_depc (void)
1192 {
1193     env->CP0_DEPC = T0;
1194     RETURN();
1195 }
1196
1197 void op_mtc0_performance0 (void)
1198 {
1199     env->CP0_Performance0 = T0; /* XXX */
1200     RETURN();
1201 }
1202
1203 void op_mtc0_taglo (void)
1204 {
1205     env->CP0_TagLo = T0 & 0xFFFFFCF6;
1206     RETURN();
1207 }
1208
1209 void op_mtc0_datalo (void)
1210 {
1211     env->CP0_DataLo = T0; /* XXX */
1212     RETURN();
1213 }
1214
1215 void op_mtc0_taghi (void)
1216 {
1217     env->CP0_TagHi = T0; /* XXX */
1218     RETURN();
1219 }
1220
1221 void op_mtc0_datahi (void)
1222 {
1223     env->CP0_DataHi = T0; /* XXX */
1224     RETURN();
1225 }
1226
1227 void op_mtc0_errorepc (void)
1228 {
1229     env->CP0_ErrorEPC = T0;
1230     RETURN();
1231 }
1232
1233 void op_mtc0_desave (void)
1234 {
1235     env->CP0_DESAVE = T0;
1236     RETURN();
1237 }
1238
1239 #ifdef MIPS_USES_FPU
1240
1241 #if 0
1242 # define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env)
1243 #else
1244 # define DEBUG_FPU_STATE() do { } while(0)
1245 #endif
1246
1247 void op_cp1_enabled(void)
1248 {
1249     if (!(env->CP0_Status & (1 << CP0St_CU1))) {
1250         CALL_FROM_TB2(do_raise_exception_err, EXCP_CpU, 1);
1251     }
1252     RETURN();
1253 }
1254
1255 /* CP1 functions */
1256 void op_cfc1 (void)
1257 {
1258     if (T1 == 0) {
1259         T0 = env->fcr0;
1260     }
1261     else {
1262         /* fetch fcr31, masking unused bits */
1263         T0 = env->fcr31 & 0x0183FFFF;
1264     }
1265     DEBUG_FPU_STATE();
1266     RETURN();
1267 }
1268
1269 /* convert MIPS rounding mode in FCR31 to IEEE library */
1270 unsigned int ieee_rm[] = { 
1271     float_round_nearest_even,
1272     float_round_to_zero,
1273     float_round_up,
1274     float_round_down
1275 };
1276
1277 #define RESTORE_ROUNDING_MODE \
1278     set_float_rounding_mode(ieee_rm[env->fcr31 & 3], &env->fp_status)
1279
1280 void op_ctc1 (void)
1281 {
1282     if (T1 == 0) {
1283         /* XXX should this throw an exception?
1284          * don't write to FCR0.
1285          * env->fcr0 = T0; 
1286          */
1287     }
1288     else {
1289         /* store new fcr31, masking unused bits */  
1290         env->fcr31 = T0 & 0x0183FFFF;
1291
1292         /* set rounding mode */
1293         RESTORE_ROUNDING_MODE;
1294
1295 #ifndef CONFIG_SOFTFLOAT
1296         /* no floating point exception for native float */
1297         SET_FP_ENABLE(env->fcr31, 0);
1298 #endif
1299     }
1300     DEBUG_FPU_STATE();
1301     RETURN();
1302 }
1303
1304 void op_mfc1 (void)
1305 {
1306     T0 = WT0;
1307     DEBUG_FPU_STATE();
1308     RETURN();
1309 }
1310
1311 void op_mtc1 (void)
1312 {
1313     WT0 = T0;
1314     DEBUG_FPU_STATE();
1315     RETURN();
1316 }
1317
1318 /* Float support.
1319    Single precition routines have a "s" suffix, double precision a
1320    "d" suffix.  */
1321
1322 #define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void)
1323
1324 FLOAT_OP(cvtd, s)
1325 {
1326     FDT2 = float32_to_float64(WT0, &env->fp_status);
1327     DEBUG_FPU_STATE();
1328     RETURN();
1329 }
1330 FLOAT_OP(cvtd, w)
1331 {
1332     FDT2 = int32_to_float64(WT0, &env->fp_status);
1333     DEBUG_FPU_STATE();
1334     RETURN();
1335 }
1336 FLOAT_OP(cvts, d)
1337 {
1338     FST2 = float64_to_float32(FDT0, &env->fp_status);
1339     DEBUG_FPU_STATE();
1340     RETURN();
1341 }
1342 FLOAT_OP(cvts, w)
1343 {
1344     FST2 = int32_to_float32(WT0, &env->fp_status);
1345     DEBUG_FPU_STATE();
1346     RETURN();
1347 }
1348 FLOAT_OP(cvtw, s)
1349 {
1350     WT2 = float32_to_int32(FST0, &env->fp_status);
1351     DEBUG_FPU_STATE();
1352     RETURN();
1353 }
1354 FLOAT_OP(cvtw, d)
1355 {
1356     WT2 = float64_to_int32(FDT0, &env->fp_status);
1357     DEBUG_FPU_STATE();
1358     RETURN();
1359 }
1360
1361 FLOAT_OP(roundw, d)
1362 {
1363     set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
1364     WT2 = float64_round_to_int(FDT0, &env->fp_status);
1365     RESTORE_ROUNDING_MODE;
1366
1367     DEBUG_FPU_STATE();
1368     RETURN();
1369 }
1370 FLOAT_OP(roundw, s)
1371 {
1372     set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
1373     WT2 = float32_round_to_int(FST0, &env->fp_status);
1374     RESTORE_ROUNDING_MODE;
1375     DEBUG_FPU_STATE();
1376     RETURN();
1377 }
1378
1379 FLOAT_OP(truncw, d)
1380 {
1381     WT2 = float64_to_int32_round_to_zero(FDT0, &env->fp_status);
1382     DEBUG_FPU_STATE();
1383     RETURN();
1384 }
1385 FLOAT_OP(truncw, s)
1386 {
1387     WT2 = float32_to_int32_round_to_zero(FST0, &env->fp_status);
1388     DEBUG_FPU_STATE();
1389     RETURN();
1390 }
1391
1392 FLOAT_OP(ceilw, d)
1393 {
1394     set_float_rounding_mode(float_round_up, &env->fp_status);
1395     WT2 = float64_round_to_int(FDT0, &env->fp_status);
1396     RESTORE_ROUNDING_MODE;
1397
1398     DEBUG_FPU_STATE();
1399     RETURN();
1400 }
1401 FLOAT_OP(ceilw, s)
1402 {
1403     set_float_rounding_mode(float_round_up, &env->fp_status);
1404     WT2 = float32_round_to_int(FST0, &env->fp_status);
1405     RESTORE_ROUNDING_MODE;
1406     DEBUG_FPU_STATE();
1407     RETURN();
1408 }
1409
1410 FLOAT_OP(floorw, d)
1411 {
1412     set_float_rounding_mode(float_round_down, &env->fp_status);
1413     WT2 = float64_round_to_int(FDT0, &env->fp_status);
1414     RESTORE_ROUNDING_MODE;
1415
1416     DEBUG_FPU_STATE();
1417     RETURN();
1418 }
1419 FLOAT_OP(floorw, s)
1420 {
1421     set_float_rounding_mode(float_round_down, &env->fp_status);
1422     WT2 = float32_round_to_int(FST0, &env->fp_status);
1423     RESTORE_ROUNDING_MODE;
1424     DEBUG_FPU_STATE();
1425     RETURN();
1426 }
1427
1428 /* binary operations */
1429 #define FLOAT_BINOP(name) \
1430 FLOAT_OP(name, d)         \
1431 {                         \
1432     FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status);    \
1433     DEBUG_FPU_STATE();    \
1434 }                         \
1435 FLOAT_OP(name, s)         \
1436 {                         \
1437     FST2 = float32_ ## name (FST0, FST1, &env->fp_status);    \
1438     DEBUG_FPU_STATE();    \
1439 }
1440 FLOAT_BINOP(add)
1441 FLOAT_BINOP(sub)
1442 FLOAT_BINOP(mul)
1443 FLOAT_BINOP(div)
1444 #undef FLOAT_BINOP
1445
1446 /* unary operations, modifying fp status  */
1447 #define FLOAT_UNOP(name)  \
1448 FLOAT_OP(name, d)         \
1449 {                         \
1450     FDT2 = float64_ ## name(FDT0, &env->fp_status);   \
1451     DEBUG_FPU_STATE();    \
1452 }                         \
1453 FLOAT_OP(name, s)         \
1454 {                         \
1455     FST2 = float32_ ## name(FST0, &env->fp_status);   \
1456     DEBUG_FPU_STATE();    \
1457 }
1458 FLOAT_UNOP(sqrt)
1459 #undef FLOAT_UNOP
1460
1461 /* unary operations, not modifying fp status  */
1462 #define FLOAT_UNOP(name)  \
1463 FLOAT_OP(name, d)         \
1464 {                         \
1465     FDT2 = float64_ ## name(FDT0);   \
1466     DEBUG_FPU_STATE();    \
1467 }                         \
1468 FLOAT_OP(name, s)         \
1469 {                         \
1470     FST2 = float32_ ## name(FST0);   \
1471     DEBUG_FPU_STATE();    \
1472 }
1473 FLOAT_UNOP(abs)
1474 FLOAT_UNOP(chs)
1475 #undef FLOAT_UNOP
1476
1477 FLOAT_OP(mov, d)
1478 {
1479     FDT2 = FDT0;
1480     DEBUG_FPU_STATE();
1481     RETURN();
1482 }
1483 FLOAT_OP(mov, s)
1484 {
1485     FST2 = FST0;
1486     DEBUG_FPU_STATE();
1487     RETURN();
1488 }
1489
1490 #ifdef CONFIG_SOFTFLOAT
1491 #define clear_invalid() do {                                \
1492     int flags = get_float_exception_flags(&env->fp_status); \
1493     flags &= ~float_flag_invalid;                           \
1494     set_float_exception_flags(flags, &env->fp_status);      \
1495 } while(0)
1496 #else
1497 #define clear_invalid() do { } while(0)
1498 #endif
1499
1500 extern void dump_fpu_s(CPUState *env);
1501
1502 #define FOP_COND(fmt, op, sig, cond)           \
1503 void op_cmp_ ## fmt ## _ ## op (void)          \
1504 {                                              \
1505     if (cond)                                  \
1506         SET_FP_COND(env->fcr31);               \
1507     else                                       \
1508         CLEAR_FP_COND(env->fcr31);             \
1509     if (!sig)                                  \
1510         clear_invalid();                       \
1511     /*CALL_FROM_TB1(dump_fpu_s, env);*/ \
1512     DEBUG_FPU_STATE();                         \
1513     RETURN();                                  \
1514 }
1515
1516 int float64_is_unordered(float64 a, float64 b STATUS_PARAM)
1517 {
1518     if (float64_is_nan(a) || float64_is_nan(b)) {
1519         float_raise(float_flag_invalid, status);
1520         return 1;
1521     }
1522     else {
1523         return 0;
1524     }
1525 }
1526
1527 FOP_COND(d, f,   0,                                                      0) 
1528 FOP_COND(d, un,  0, float64_is_unordered(FDT1, FDT0, &env->fp_status))
1529 FOP_COND(d, eq,  0,                                                      float64_eq(FDT0, FDT1, &env->fp_status))
1530 FOP_COND(d, ueq, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status))
1531 FOP_COND(d, olt, 0,                                                      float64_lt(FDT0, FDT1, &env->fp_status))
1532 FOP_COND(d, ult, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status))
1533 FOP_COND(d, ole, 0,                                                      float64_le(FDT0, FDT1, &env->fp_status))
1534 FOP_COND(d, ule, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status))
1535 /* NOTE: the comma operator will make "cond" to eval to false,
1536  * but float*_is_unordered() is still called
1537  */
1538 FOP_COND(d, sf,  1,                                                      (float64_is_unordered(FDT0, FDT1, &env->fp_status), 0))
1539 FOP_COND(d, ngle,1, float64_is_unordered(FDT1, FDT0, &env->fp_status))
1540 FOP_COND(d, seq, 1,                                                      float64_eq(FDT0, FDT1, &env->fp_status))
1541 FOP_COND(d, ngl, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status))
1542 FOP_COND(d, lt,  1,                                                      float64_lt(FDT0, FDT1, &env->fp_status))
1543 FOP_COND(d, nge, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status))
1544 FOP_COND(d, le,  1,                                                      float64_le(FDT0, FDT1, &env->fp_status))
1545 FOP_COND(d, ngt, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status))
1546
1547 flag float32_is_unordered(float32 a, float32 b STATUS_PARAM)
1548 {
1549     extern flag float32_is_nan( float32 a );
1550     if (float32_is_nan(a) || float32_is_nan(b)) {
1551         float_raise(float_flag_invalid, status);
1552         return 1;
1553     }
1554     else {
1555         return 0;
1556     }
1557 }
1558
1559 /* NOTE: the comma operator will make "cond" to eval to false,
1560  * but float*_is_unordered() is still called
1561  */
1562 FOP_COND(s, f,   0,                                                      0) 
1563 FOP_COND(s, un,  0, float32_is_unordered(FST1, FST0, &env->fp_status))
1564 FOP_COND(s, eq,  0,                                                      float32_eq(FST0, FST1, &env->fp_status))
1565 FOP_COND(s, ueq, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status))
1566 FOP_COND(s, olt, 0,                                                      float32_lt(FST0, FST1, &env->fp_status))
1567 FOP_COND(s, ult, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status))
1568 FOP_COND(s, ole, 0,                                                      float32_le(FST0, FST1, &env->fp_status))
1569 FOP_COND(s, ule, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status))
1570 /* NOTE: the comma operator will make "cond" to eval to false,
1571  * but float*_is_unordered() is still called
1572  */
1573 FOP_COND(s, sf,  1,                                                      (float32_is_unordered(FST0, FST1, &env->fp_status), 0))
1574 FOP_COND(s, ngle,1, float32_is_unordered(FST1, FST0, &env->fp_status))
1575 FOP_COND(s, seq, 1,                                                      float32_eq(FST0, FST1, &env->fp_status))
1576 FOP_COND(s, ngl, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status))
1577 FOP_COND(s, lt,  1,                                                      float32_lt(FST0, FST1, &env->fp_status))
1578 FOP_COND(s, nge, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status))
1579 FOP_COND(s, le,  1,                                                      float32_le(FST0, FST1, &env->fp_status))
1580 FOP_COND(s, ngt, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status))
1581
1582 void op_bc1f (void)
1583 {
1584     T0 = ! IS_FP_COND_SET(env->fcr31);
1585     DEBUG_FPU_STATE();
1586     RETURN();
1587 }
1588
1589 void op_bc1t (void)
1590 {
1591     T0 = IS_FP_COND_SET(env->fcr31);
1592     DEBUG_FPU_STATE();
1593     RETURN();
1594 }
1595 #endif /* MIPS_USES_FPU */
1596
1597 #if defined(MIPS_USES_R4K_TLB)
1598 void op_tlbwi (void)
1599 {
1600     CALL_FROM_TB0(do_tlbwi);
1601     RETURN();
1602 }
1603
1604 void op_tlbwr (void)
1605 {
1606     CALL_FROM_TB0(do_tlbwr);
1607     RETURN();
1608 }
1609
1610 void op_tlbp (void)
1611 {
1612     CALL_FROM_TB0(do_tlbp);
1613     RETURN();
1614 }
1615
1616 void op_tlbr (void)
1617 {
1618     CALL_FROM_TB0(do_tlbr);
1619     RETURN();
1620 }
1621 #endif
1622
1623 /* Specials */
1624 void op_pmon (void)
1625 {
1626     CALL_FROM_TB1(do_pmon, PARAM1);
1627     RETURN();
1628 }
1629
1630 void op_di (void)
1631 {
1632     uint32_t val;
1633
1634     T0 = env->CP0_Status;
1635     val = T0 & ~(1 << CP0St_IE);
1636     if (val != T0) {
1637         env->interrupt_request &= ~CPU_INTERRUPT_HARD;
1638         env->CP0_Status = val;
1639     }
1640     RETURN();
1641 }
1642
1643 void op_ei (void)
1644 {
1645     uint32_t val;
1646
1647     T0 = env->CP0_Status;
1648     val = T0 | (1 << CP0St_IE);
1649     if (val != T0) {
1650        const uint32_t mask = 0x0000FF00;
1651
1652        env->CP0_Status = val;
1653        if (!(env->hflags & MIPS_HFLAG_EXL) &&
1654            !(env->hflags & MIPS_HFLAG_ERL) &&
1655            !(env->hflags & MIPS_HFLAG_DM) &&
1656            (env->CP0_Status & env->CP0_Cause & mask)) {
1657                env->interrupt_request |= CPU_INTERRUPT_HARD;
1658                if (logfile)
1659                    CALL_FROM_TB0(do_mtc0_status_irqraise_debug);
1660        }
1661     }
1662     RETURN();
1663 }
1664
1665 void op_trap (void)
1666 {
1667     if (T0) {
1668         CALL_FROM_TB1(do_raise_exception_direct, EXCP_TRAP);
1669     }
1670     RETURN();
1671 }
1672
1673 void op_debug (void)
1674 {
1675     CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG);
1676     RETURN();
1677 }
1678
1679 void op_set_lladdr (void)
1680 {
1681     env->CP0_LLAddr = T2;
1682     RETURN();
1683 }
1684
1685 void debug_eret (void);
1686 void op_eret (void)
1687 {
1688     CALL_FROM_TB0(debug_eret);
1689     if (env->hflags & MIPS_HFLAG_ERL) {
1690         env->PC = env->CP0_ErrorEPC;
1691         env->hflags &= ~MIPS_HFLAG_ERL;
1692         env->CP0_Status &= ~(1 << CP0St_ERL);
1693     } else {
1694         env->PC = env->CP0_EPC;
1695         env->hflags &= ~MIPS_HFLAG_EXL;
1696         env->CP0_Status &= ~(1 << CP0St_EXL);
1697     }
1698     env->CP0_LLAddr = 1;
1699     RETURN();
1700 }
1701
1702 void op_deret (void)
1703 {
1704     CALL_FROM_TB0(debug_eret);
1705     env->PC = env->CP0_DEPC;
1706     RETURN();
1707 }
1708
1709 void op_rdhwr_cpunum(void)
1710 {
1711     if (env->CP0_HWREna & (1 << 0))
1712        T0 = env->CP0_EBase & 0x2ff;
1713     else
1714        CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI);
1715     RETURN();
1716 }
1717
1718 void op_rdhwr_synci_step(void)
1719 {
1720     if (env->CP0_HWREna & (1 << 1))
1721        T0 = env->SYNCI_Step;
1722     else
1723        CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI);
1724     RETURN();
1725 }
1726
1727 void op_rdhwr_cc(void)
1728 {
1729     if (env->CP0_HWREna & (1 << 2))
1730        T0 = env->CP0_Count;
1731     else
1732        CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI);
1733     RETURN();
1734 }
1735
1736 void op_rdhwr_ccres(void)
1737 {
1738     if (env->CP0_HWREna & (1 << 3))
1739        T0 = env->CCRes;
1740     else
1741        CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI);
1742     RETURN();
1743 }
1744
1745 void op_save_state (void)
1746 {
1747     env->hflags = PARAM1;
1748     RETURN();
1749 }
1750
1751 void op_save_pc (void)
1752 {
1753     env->PC = PARAM1;
1754     RETURN();
1755 }
1756
1757 void op_raise_exception (void)
1758 {
1759     CALL_FROM_TB1(do_raise_exception, PARAM1);
1760     RETURN();
1761 }
1762
1763 void op_raise_exception_err (void)
1764 {
1765     CALL_FROM_TB2(do_raise_exception_err, PARAM1, PARAM2);
1766     RETURN();
1767 }
1768
1769 void op_exit_tb (void)
1770 {
1771     EXIT_TB();
1772     RETURN();
1773 }
1774
1775 void op_wait (void)
1776 {
1777     env->halted = 1;
1778     CALL_FROM_TB1(do_raise_exception, EXCP_HLT);
1779     RETURN();
1780 }
1781
1782 /* Bitfield operations. */
1783 void op_ext(void)
1784 {
1785     unsigned int pos = PARAM1;
1786     unsigned int size = PARAM2;
1787
1788     T0 = (T1 >> pos) & ((1 << size) - 1);
1789     RETURN();
1790 }
1791
1792 void op_ins(void)
1793 {
1794     unsigned int pos = PARAM1;
1795     unsigned int size = PARAM2;
1796     target_ulong mask = ((1 << size) - 1) << pos;
1797
1798     T0 = (T2 & ~mask) | ((T1 << pos) & mask);
1799     RETURN();
1800 }
1801
1802 void op_wsbh(void)
1803 {
1804     T0 = ((T1 << 8) & ~0x00FF00FF) | ((T1 >> 8) & 0x00FF00FF);
1805     RETURN();
1806 }
1807
1808 void op_dsbh(void)
1809 {
1810     T0 = ((T1 << 8) & ~0x00FF00FF00FF00FFULL) | ((T1 >> 8) & 0x00FF00FF00FF00FFULL);
1811     RETURN();
1812 }
1813
1814 void op_dshd(void)
1815 {
1816     T0 = ((T1 << 16) & ~0x0000FFFF0000FFFFULL) | ((T1 >> 16) & 0x0000FFFF0000FFFFULL);
1817     RETURN();
1818 }
1819
1820 void op_seb(void)
1821 {
1822     T0 = ((T1 & 0xFF) ^ 0x80) - 0x80;
1823     RETURN();
1824 }
1825
1826 void op_seh(void)
1827 {
1828     T0 = ((T1 & 0xFFFF) ^ 0x8000) - 0x8000;
1829     RETURN();
1830 }