Call most FP helpers without deroute through op.c
[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  *  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 /* Load and store */
52 #define MEMSUFFIX _raw
53 #include "op_mem.c"
54 #undef MEMSUFFIX
55 #if !defined(CONFIG_USER_ONLY)
56 #define MEMSUFFIX _user
57 #include "op_mem.c"
58 #undef MEMSUFFIX
59
60 #define MEMSUFFIX _super
61 #include "op_mem.c"
62 #undef MEMSUFFIX
63
64 #define MEMSUFFIX _kernel
65 #include "op_mem.c"
66 #undef MEMSUFFIX
67 #endif
68
69 /* 64 bits arithmetic */
70 #if TARGET_LONG_BITS > HOST_LONG_BITS
71 void op_mult (void)
72 {
73     CALL_FROM_TB0(do_mult);
74     FORCE_RET();
75 }
76
77 void op_multu (void)
78 {
79     CALL_FROM_TB0(do_multu);
80     FORCE_RET();
81 }
82
83 void op_madd (void)
84 {
85     CALL_FROM_TB0(do_madd);
86     FORCE_RET();
87 }
88
89 void op_maddu (void)
90 {
91     CALL_FROM_TB0(do_maddu);
92     FORCE_RET();
93 }
94
95 void op_msub (void)
96 {
97     CALL_FROM_TB0(do_msub);
98     FORCE_RET();
99 }
100
101 void op_msubu (void)
102 {
103     CALL_FROM_TB0(do_msubu);
104     FORCE_RET();
105 }
106
107 /* Multiplication variants of the vr54xx. */
108 void op_muls (void)
109 {
110     CALL_FROM_TB0(do_muls);
111     FORCE_RET();
112 }
113
114 void op_mulsu (void)
115 {
116     CALL_FROM_TB0(do_mulsu);
117     FORCE_RET();
118 }
119
120 void op_macc (void)
121 {
122     CALL_FROM_TB0(do_macc);
123     FORCE_RET();
124 }
125
126 void op_macchi (void)
127 {
128     CALL_FROM_TB0(do_macchi);
129     FORCE_RET();
130 }
131
132 void op_maccu (void)
133 {
134     CALL_FROM_TB0(do_maccu);
135     FORCE_RET();
136 }
137 void op_macchiu (void)
138 {
139     CALL_FROM_TB0(do_macchiu);
140     FORCE_RET();
141 }
142
143 void op_msac (void)
144 {
145     CALL_FROM_TB0(do_msac);
146     FORCE_RET();
147 }
148
149 void op_msachi (void)
150 {
151     CALL_FROM_TB0(do_msachi);
152     FORCE_RET();
153 }
154
155 void op_msacu (void)
156 {
157     CALL_FROM_TB0(do_msacu);
158     FORCE_RET();
159 }
160
161 void op_msachiu (void)
162 {
163     CALL_FROM_TB0(do_msachiu);
164     FORCE_RET();
165 }
166
167 void op_mulhi (void)
168 {
169     CALL_FROM_TB0(do_mulhi);
170     FORCE_RET();
171 }
172
173 void op_mulhiu (void)
174 {
175     CALL_FROM_TB0(do_mulhiu);
176     FORCE_RET();
177 }
178
179 void op_mulshi (void)
180 {
181     CALL_FROM_TB0(do_mulshi);
182     FORCE_RET();
183 }
184
185 void op_mulshiu (void)
186 {
187     CALL_FROM_TB0(do_mulshiu);
188     FORCE_RET();
189 }
190
191 #else /* TARGET_LONG_BITS > HOST_LONG_BITS */
192
193 static always_inline uint64_t get_HILO (void)
194 {
195     return ((uint64_t)env->HI[env->current_tc][0] << 32) |
196             ((uint64_t)(uint32_t)env->LO[env->current_tc][0]);
197 }
198
199 static always_inline void set_HILO (uint64_t HILO)
200 {
201     env->LO[env->current_tc][0] = (int32_t)(HILO & 0xFFFFFFFF);
202     env->HI[env->current_tc][0] = (int32_t)(HILO >> 32);
203 }
204
205 static always_inline void set_HIT0_LO (uint64_t HILO)
206 {
207     env->LO[env->current_tc][0] = (int32_t)(HILO & 0xFFFFFFFF);
208     T0 = env->HI[env->current_tc][0] = (int32_t)(HILO >> 32);
209 }
210
211 static always_inline void set_HI_LOT0 (uint64_t HILO)
212 {
213     T0 = env->LO[env->current_tc][0] = (int32_t)(HILO & 0xFFFFFFFF);
214     env->HI[env->current_tc][0] = (int32_t)(HILO >> 32);
215 }
216
217 void op_mult (void)
218 {
219     set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
220     FORCE_RET();
221 }
222
223 void op_multu (void)
224 {
225     set_HILO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
226     FORCE_RET();
227 }
228
229 void op_madd (void)
230 {
231     int64_t tmp;
232
233     tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
234     set_HILO((int64_t)get_HILO() + tmp);
235     FORCE_RET();
236 }
237
238 void op_maddu (void)
239 {
240     uint64_t tmp;
241
242     tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
243     set_HILO(get_HILO() + tmp);
244     FORCE_RET();
245 }
246
247 void op_msub (void)
248 {
249     int64_t tmp;
250
251     tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
252     set_HILO((int64_t)get_HILO() - tmp);
253     FORCE_RET();
254 }
255
256 void op_msubu (void)
257 {
258     uint64_t tmp;
259
260     tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
261     set_HILO(get_HILO() - tmp);
262     FORCE_RET();
263 }
264
265 /* Multiplication variants of the vr54xx. */
266 void op_muls (void)
267 {
268     set_HI_LOT0(0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
269     FORCE_RET();
270 }
271
272 void op_mulsu (void)
273 {
274     set_HI_LOT0(0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
275     FORCE_RET();
276 }
277
278 void op_macc (void)
279 {
280     set_HI_LOT0(get_HILO() + ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
281     FORCE_RET();
282 }
283
284 void op_macchi (void)
285 {
286     set_HIT0_LO(get_HILO() + ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
287     FORCE_RET();
288 }
289
290 void op_maccu (void)
291 {
292     set_HI_LOT0(get_HILO() + ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
293     FORCE_RET();
294 }
295
296 void op_macchiu (void)
297 {
298     set_HIT0_LO(get_HILO() + ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
299     FORCE_RET();
300 }
301
302 void op_msac (void)
303 {
304     set_HI_LOT0(get_HILO() - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
305     FORCE_RET();
306 }
307
308 void op_msachi (void)
309 {
310     set_HIT0_LO(get_HILO() - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
311     FORCE_RET();
312 }
313
314 void op_msacu (void)
315 {
316     set_HI_LOT0(get_HILO() - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
317     FORCE_RET();
318 }
319
320 void op_msachiu (void)
321 {
322     set_HIT0_LO(get_HILO() - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
323     FORCE_RET();
324 }
325
326 void op_mulhi (void)
327 {
328     set_HIT0_LO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
329     FORCE_RET();
330 }
331
332 void op_mulhiu (void)
333 {
334     set_HIT0_LO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
335     FORCE_RET();
336 }
337
338 void op_mulshi (void)
339 {
340     set_HIT0_LO(0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
341     FORCE_RET();
342 }
343
344 void op_mulshiu (void)
345 {
346     set_HIT0_LO(0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
347     FORCE_RET();
348 }
349
350 #endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
351
352 #if defined(TARGET_MIPS64)
353 void op_dmult (void)
354 {
355     CALL_FROM_TB4(muls64, &(env->LO[env->current_tc][0]), &(env->HI[env->current_tc][0]), T0, T1);
356     FORCE_RET();
357 }
358
359 void op_dmultu (void)
360 {
361     CALL_FROM_TB4(mulu64, &(env->LO[env->current_tc][0]), &(env->HI[env->current_tc][0]), T0, T1);
362     FORCE_RET();
363 }
364 #endif
365
366 /* CP1 functions */
367 #if 0
368 # define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env)
369 #else
370 # define DEBUG_FPU_STATE() do { } while(0)
371 #endif
372
373 /* Float support.
374    Single precition routines have a "s" suffix, double precision a
375    "d" suffix, 32bit integer "w", 64bit integer "l", paired singe "ps",
376    paired single lowwer "pl", paired single upper "pu".  */
377
378 #define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void)
379
380 FLOAT_OP(cvtps, s)
381 {
382     WT2 = WT0;
383     WTH2 = WT1;
384     DEBUG_FPU_STATE();
385     FORCE_RET();
386 }
387
388 FLOAT_OP(pll, ps)
389 {
390     DT2 = ((uint64_t)WT0 << 32) | WT1;
391     DEBUG_FPU_STATE();
392     FORCE_RET();
393 }
394 FLOAT_OP(plu, ps)
395 {
396     DT2 = ((uint64_t)WT0 << 32) | WTH1;
397     DEBUG_FPU_STATE();
398     FORCE_RET();
399 }
400 FLOAT_OP(pul, ps)
401 {
402     DT2 = ((uint64_t)WTH0 << 32) | WT1;
403     DEBUG_FPU_STATE();
404     FORCE_RET();
405 }
406 FLOAT_OP(puu, ps)
407 {
408     DT2 = ((uint64_t)WTH0 << 32) | WTH1;
409     DEBUG_FPU_STATE();
410     FORCE_RET();
411 }
412
413 FLOAT_OP(movf, d)
414 {
415     if (!(env->fpu->fcr31 & PARAM1))
416         DT2 = DT0;
417     DEBUG_FPU_STATE();
418     FORCE_RET();
419 }
420 FLOAT_OP(movf, s)
421 {
422     if (!(env->fpu->fcr31 & PARAM1))
423         WT2 = WT0;
424     DEBUG_FPU_STATE();
425     FORCE_RET();
426 }
427 FLOAT_OP(movf, ps)
428 {
429     unsigned int mask = GET_FP_COND (env->fpu) >> PARAM1;
430     if (!(mask & 1))
431         WT2 = WT0;
432     if (!(mask & 2))
433         WTH2 = WTH0;
434     DEBUG_FPU_STATE();
435     FORCE_RET();
436 }
437 FLOAT_OP(movt, d)
438 {
439     if (env->fpu->fcr31 & PARAM1)
440         DT2 = DT0;
441     DEBUG_FPU_STATE();
442     FORCE_RET();
443 }
444 FLOAT_OP(movt, s)
445 {
446     if (env->fpu->fcr31 & PARAM1)
447         WT2 = WT0;
448     DEBUG_FPU_STATE();
449     FORCE_RET();
450 }
451 FLOAT_OP(movt, ps)
452 {
453     unsigned int mask = GET_FP_COND (env->fpu) >> PARAM1;
454     if (mask & 1)
455         WT2 = WT0;
456     if (mask & 2)
457         WTH2 = WTH0;
458     DEBUG_FPU_STATE();
459     FORCE_RET();
460 }
461 FLOAT_OP(movz, d)
462 {
463     if (!T0)
464         DT2 = DT0;
465     DEBUG_FPU_STATE();
466     FORCE_RET();
467 }
468 FLOAT_OP(movz, s)
469 {
470     if (!T0)
471         WT2 = WT0;
472     DEBUG_FPU_STATE();
473     FORCE_RET();
474 }
475 FLOAT_OP(movz, ps)
476 {
477     if (!T0) {
478         WT2 = WT0;
479         WTH2 = WTH0;
480     }
481     DEBUG_FPU_STATE();
482     FORCE_RET();
483 }
484 FLOAT_OP(movn, d)
485 {
486     if (T0)
487         DT2 = DT0;
488     DEBUG_FPU_STATE();
489     FORCE_RET();
490 }
491 FLOAT_OP(movn, s)
492 {
493     if (T0)
494         WT2 = WT0;
495     DEBUG_FPU_STATE();
496     FORCE_RET();
497 }
498 FLOAT_OP(movn, ps)
499 {
500     if (T0) {
501         WT2 = WT0;
502         WTH2 = WTH0;
503     }
504     DEBUG_FPU_STATE();
505     FORCE_RET();
506 }
507
508 /* ternary operations */
509 #define FLOAT_TERNOP(name1, name2) \
510 FLOAT_OP(name1 ## name2, d)        \
511 {                                  \
512     FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status);    \
513     FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status);    \
514     DEBUG_FPU_STATE();             \
515     FORCE_RET();                   \
516 }                                  \
517 FLOAT_OP(name1 ## name2, s)        \
518 {                                  \
519     FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status);    \
520     FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status);    \
521     DEBUG_FPU_STATE();             \
522     FORCE_RET();                   \
523 }                                  \
524 FLOAT_OP(name1 ## name2, ps)       \
525 {                                  \
526     FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status);    \
527     FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \
528     FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status);    \
529     FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \
530     DEBUG_FPU_STATE();             \
531     FORCE_RET();                   \
532 }
533 FLOAT_TERNOP(mul, add)
534 FLOAT_TERNOP(mul, sub)
535 #undef FLOAT_TERNOP
536
537 /* negated ternary operations */
538 #define FLOAT_NTERNOP(name1, name2) \
539 FLOAT_OP(n ## name1 ## name2, d)    \
540 {                                   \
541     FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status);    \
542     FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status);    \
543     FDT2 = float64_chs(FDT2);       \
544     DEBUG_FPU_STATE();              \
545     FORCE_RET();                    \
546 }                                   \
547 FLOAT_OP(n ## name1 ## name2, s)    \
548 {                                   \
549     FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status);    \
550     FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status);    \
551     FST2 = float32_chs(FST2);       \
552     DEBUG_FPU_STATE();              \
553     FORCE_RET();                    \
554 }                                   \
555 FLOAT_OP(n ## name1 ## name2, ps)   \
556 {                                   \
557     FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status);    \
558     FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \
559     FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status);    \
560     FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \
561     FST2 = float32_chs(FST2);       \
562     FSTH2 = float32_chs(FSTH2);     \
563     DEBUG_FPU_STATE();              \
564     FORCE_RET();                    \
565 }
566 FLOAT_NTERNOP(mul, add)
567 FLOAT_NTERNOP(mul, sub)
568 #undef FLOAT_NTERNOP
569
570 /* unary operations, modifying fp status  */
571 #define FLOAT_UNOP(name)  \
572 FLOAT_OP(name, d)         \
573 {                         \
574     FDT2 = float64_ ## name(FDT0, &env->fpu->fp_status); \
575     DEBUG_FPU_STATE();    \
576     FORCE_RET();          \
577 }                         \
578 FLOAT_OP(name, s)         \
579 {                         \
580     FST2 = float32_ ## name(FST0, &env->fpu->fp_status); \
581     DEBUG_FPU_STATE();    \
582     FORCE_RET();          \
583 }
584 FLOAT_UNOP(sqrt)
585 #undef FLOAT_UNOP
586
587 /* unary operations, not modifying fp status  */
588 #define FLOAT_UNOP(name)  \
589 FLOAT_OP(name, d)         \
590 {                         \
591     FDT2 = float64_ ## name(FDT0);   \
592     DEBUG_FPU_STATE();    \
593     FORCE_RET();          \
594 }                         \
595 FLOAT_OP(name, s)         \
596 {                         \
597     FST2 = float32_ ## name(FST0);   \
598     DEBUG_FPU_STATE();    \
599     FORCE_RET();          \
600 }                         \
601 FLOAT_OP(name, ps)        \
602 {                         \
603     FST2 = float32_ ## name(FST0);   \
604     FSTH2 = float32_ ## name(FSTH0); \
605     DEBUG_FPU_STATE();    \
606     FORCE_RET();          \
607 }
608 FLOAT_UNOP(abs)
609 FLOAT_UNOP(chs)
610 #undef FLOAT_UNOP
611
612 FLOAT_OP(mov, d)
613 {
614     FDT2 = FDT0;
615     DEBUG_FPU_STATE();
616     FORCE_RET();
617 }
618 FLOAT_OP(mov, s)
619 {
620     FST2 = FST0;
621     DEBUG_FPU_STATE();
622     FORCE_RET();
623 }
624 FLOAT_OP(mov, ps)
625 {
626     FST2 = FST0;
627     FSTH2 = FSTH0;
628     DEBUG_FPU_STATE();
629     FORCE_RET();
630 }
631 FLOAT_OP(alnv, ps)
632 {
633     switch (T0 & 0x7) {
634     case 0:
635         FST2 = FST0;
636         FSTH2 = FSTH0;
637         break;
638     case 4:
639 #ifdef TARGET_WORDS_BIGENDIAN
640         FSTH2 = FST0;
641         FST2 = FSTH1;
642 #else
643         FSTH2 = FST1;
644         FST2 = FSTH0;
645 #endif
646         break;
647     default: /* unpredictable */
648         break;
649     }
650     DEBUG_FPU_STATE();
651     FORCE_RET();
652 }
653
654 #ifdef CONFIG_SOFTFLOAT
655 #define clear_invalid() do {                                \
656     int flags = get_float_exception_flags(&env->fpu->fp_status); \
657     flags &= ~float_flag_invalid;                           \
658     set_float_exception_flags(flags, &env->fpu->fp_status); \
659 } while(0)
660 #else
661 #define clear_invalid() do { } while(0)
662 #endif
663
664 extern void dump_fpu_s(CPUState *env);
665
666 void op_bc1f (void)
667 {
668     T0 = !!(~GET_FP_COND(env->fpu) & (0x1 << PARAM1));
669     DEBUG_FPU_STATE();
670     FORCE_RET();
671 }
672 void op_bc1any2f (void)
673 {
674     T0 = !!(~GET_FP_COND(env->fpu) & (0x3 << PARAM1));
675     DEBUG_FPU_STATE();
676     FORCE_RET();
677 }
678 void op_bc1any4f (void)
679 {
680     T0 = !!(~GET_FP_COND(env->fpu) & (0xf << PARAM1));
681     DEBUG_FPU_STATE();
682     FORCE_RET();
683 }
684
685 void op_bc1t (void)
686 {
687     T0 = !!(GET_FP_COND(env->fpu) & (0x1 << PARAM1));
688     DEBUG_FPU_STATE();
689     FORCE_RET();
690 }
691 void op_bc1any2t (void)
692 {
693     T0 = !!(GET_FP_COND(env->fpu) & (0x3 << PARAM1));
694     DEBUG_FPU_STATE();
695     FORCE_RET();
696 }
697 void op_bc1any4t (void)
698 {
699     T0 = !!(GET_FP_COND(env->fpu) & (0xf << PARAM1));
700     DEBUG_FPU_STATE();
701     FORCE_RET();
702 }
703
704 void op_tlbwi (void)
705 {
706     CALL_FROM_TB0(env->tlb->do_tlbwi);
707     FORCE_RET();
708 }
709
710 void op_tlbwr (void)
711 {
712     CALL_FROM_TB0(env->tlb->do_tlbwr);
713     FORCE_RET();
714 }
715
716 void op_tlbp (void)
717 {
718     CALL_FROM_TB0(env->tlb->do_tlbp);
719     FORCE_RET();
720 }
721
722 void op_tlbr (void)
723 {
724     CALL_FROM_TB0(env->tlb->do_tlbr);
725     FORCE_RET();
726 }
727
728 /* Specials */
729 #if defined (CONFIG_USER_ONLY)
730 void op_tls_value (void)
731 {
732     T0 = env->tls_value;
733 }
734 #endif
735
736 void op_pmon (void)
737 {
738     CALL_FROM_TB1(do_pmon, PARAM1);
739     FORCE_RET();
740 }
741
742 void op_di (void)
743 {
744     T0 = env->CP0_Status;
745     env->CP0_Status = T0 & ~(1 << CP0St_IE);
746     CALL_FROM_TB1(cpu_mips_update_irq, env);
747     FORCE_RET();
748 }
749
750 void op_ei (void)
751 {
752     T0 = env->CP0_Status;
753     env->CP0_Status = T0 | (1 << CP0St_IE);
754     CALL_FROM_TB1(cpu_mips_update_irq, env);
755     FORCE_RET();
756 }
757
758 void op_trap (void)
759 {
760     if (T0) {
761         CALL_FROM_TB1(do_raise_exception, EXCP_TRAP);
762     }
763     FORCE_RET();
764 }
765
766 void op_debug (void)
767 {
768     CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG);
769     FORCE_RET();
770 }
771
772 void debug_pre_eret (void);
773 void debug_post_eret (void);
774 void op_eret (void)
775 {
776     if (loglevel & CPU_LOG_EXEC)
777         CALL_FROM_TB0(debug_pre_eret);
778     if (env->CP0_Status & (1 << CP0St_ERL)) {
779         env->PC[env->current_tc] = env->CP0_ErrorEPC;
780         env->CP0_Status &= ~(1 << CP0St_ERL);
781     } else {
782         env->PC[env->current_tc] = env->CP0_EPC;
783         env->CP0_Status &= ~(1 << CP0St_EXL);
784     }
785     CALL_FROM_TB1(compute_hflags, env);
786     if (loglevel & CPU_LOG_EXEC)
787         CALL_FROM_TB0(debug_post_eret);
788     env->CP0_LLAddr = 1;
789     FORCE_RET();
790 }
791
792 void op_deret (void)
793 {
794     if (loglevel & CPU_LOG_EXEC)
795         CALL_FROM_TB0(debug_pre_eret);
796     env->PC[env->current_tc] = env->CP0_DEPC;
797     env->hflags &= MIPS_HFLAG_DM;
798     CALL_FROM_TB1(compute_hflags, env);
799     if (loglevel & CPU_LOG_EXEC)
800         CALL_FROM_TB0(debug_post_eret);
801     env->CP0_LLAddr = 1;
802     FORCE_RET();
803 }
804
805 void op_rdhwr_cpunum(void)
806 {
807     if ((env->hflags & MIPS_HFLAG_CP0) ||
808         (env->CP0_HWREna & (1 << 0)))
809         T0 = env->CP0_EBase & 0x3ff;
810     else
811         CALL_FROM_TB1(do_raise_exception, EXCP_RI);
812     FORCE_RET();
813 }
814
815 void op_rdhwr_synci_step(void)
816 {
817     if ((env->hflags & MIPS_HFLAG_CP0) ||
818         (env->CP0_HWREna & (1 << 1)))
819         T0 = env->SYNCI_Step;
820     else
821         CALL_FROM_TB1(do_raise_exception, EXCP_RI);
822     FORCE_RET();
823 }
824
825 void op_rdhwr_cc(void)
826 {
827     if ((env->hflags & MIPS_HFLAG_CP0) ||
828         (env->CP0_HWREna & (1 << 2)))
829         T0 = env->CP0_Count;
830     else
831         CALL_FROM_TB1(do_raise_exception, EXCP_RI);
832     FORCE_RET();
833 }
834
835 void op_rdhwr_ccres(void)
836 {
837     if ((env->hflags & MIPS_HFLAG_CP0) ||
838         (env->CP0_HWREna & (1 << 3)))
839         T0 = env->CCRes;
840     else
841         CALL_FROM_TB1(do_raise_exception, EXCP_RI);
842     FORCE_RET();
843 }
844
845 void op_save_state (void)
846 {
847     env->hflags = PARAM1;
848     FORCE_RET();
849 }
850
851 void op_wait (void)
852 {
853     env->halted = 1;
854     CALL_FROM_TB1(do_raise_exception, EXCP_HLT);
855     FORCE_RET();
856 }
857
858 /* Bitfield operations. */
859 void op_ext(void)
860 {
861     unsigned int pos = PARAM1;
862     unsigned int size = PARAM2;
863
864     T0 = (int32_t)((T1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0));
865     FORCE_RET();
866 }
867
868 void op_ins(void)
869 {
870     unsigned int pos = PARAM1;
871     unsigned int size = PARAM2;
872     target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos;
873
874     T0 = (int32_t)((T0 & ~mask) | ((T1 << pos) & mask));
875     FORCE_RET();
876 }
877
878 void op_wsbh(void)
879 {
880     T0 = (int32_t)(((T1 << 8) & ~0x00FF00FF) | ((T1 >> 8) & 0x00FF00FF));
881     FORCE_RET();
882 }
883
884 #if defined(TARGET_MIPS64)
885 void op_dext(void)
886 {
887     unsigned int pos = PARAM1;
888     unsigned int size = PARAM2;
889
890     T0 = (T1 >> pos) & ((size < 64) ? ((1ULL << size) - 1) : ~0ULL);
891     FORCE_RET();
892 }
893
894 void op_dins(void)
895 {
896     unsigned int pos = PARAM1;
897     unsigned int size = PARAM2;
898     target_ulong mask = ((size < 64) ? ((1ULL << size) - 1) : ~0ULL) << pos;
899
900     T0 = (T0 & ~mask) | ((T1 << pos) & mask);
901     FORCE_RET();
902 }
903
904 void op_dsbh(void)
905 {
906     T0 = ((T1 << 8) & ~0x00FF00FF00FF00FFULL) | ((T1 >> 8) & 0x00FF00FF00FF00FFULL);
907     FORCE_RET();
908 }
909
910 void op_dshd(void)
911 {
912     T1 = ((T1 << 16) & ~0x0000FFFF0000FFFFULL) | ((T1 >> 16) & 0x0000FFFF0000FFFFULL);
913     T0 = (T1 << 32) | (T1 >> 32);
914     FORCE_RET();
915 }
916 #endif