Enable SH bFLT loader.
[qemu/mini2440.git] / target-mips / op.c
blobbc7f81949f5c3d1b7698c7d8ab403f0458d44c10
1 /*
2 * MIPS emulation micro-operations for qemu.
3 *
4 * Copyright (c) 2004-2005 Jocelyn Mayer
5 * Copyright (c) 2006 Marius Groeger (FPU operations)
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.
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.
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
22 #include "config.h"
23 #include "exec.h"
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
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
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
153 #ifdef MIPS_USES_FPU
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
284 #define FTN
285 #include "fop_template.c"
286 #undef FTN
288 #endif
290 void op_dup_T0 (void)
292 T2 = T0;
293 RETURN();
296 void op_load_HI (void)
298 T0 = env->HI;
299 RETURN();
302 void op_store_HI (void)
304 env->HI = T0;
305 RETURN();
308 void op_load_LO (void)
310 T0 = env->LO;
311 RETURN();
314 void op_store_LO (void)
316 env->LO = T0;
317 RETURN();
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
329 #define MEMSUFFIX _kernel
330 #include "op_mem.c"
331 #undef MEMSUFFIX
332 #endif
334 /* Arithmetic */
335 void op_add (void)
337 T0 += T1;
338 RETURN();
341 void op_addo (void)
343 target_ulong tmp;
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);
351 RETURN();
354 void op_sub (void)
356 T0 -= T1;
357 RETURN();
360 void op_subo (void)
362 target_ulong tmp;
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);
370 RETURN();
373 void op_mul (void)
375 T0 = (int32_t)T0 * (int32_t)T1;
376 RETURN();
379 void op_div (void)
381 if (T1 != 0) {
382 env->LO = (int32_t)T0 / (int32_t)T1;
383 env->HI = (int32_t)T0 % (int32_t)T1;
385 RETURN();
388 void op_divu (void)
390 if (T1 != 0) {
391 env->LO = T0 / T1;
392 env->HI = T0 % T1;
394 RETURN();
397 /* Logical */
398 void op_and (void)
400 T0 &= T1;
401 RETURN();
404 void op_nor (void)
406 T0 = ~(T0 | T1);
407 RETURN();
410 void op_or (void)
412 T0 |= T1;
413 RETURN();
416 void op_xor (void)
418 T0 ^= T1;
419 RETURN();
422 void op_sll (void)
424 T0 = T0 << T1;
425 RETURN();
428 void op_sra (void)
430 T0 = (int32_t)T0 >> T1;
431 RETURN();
434 void op_srl (void)
436 T0 = T0 >> T1;
437 RETURN();
440 void op_sllv (void)
442 T0 = T1 << (T0 & 0x1F);
443 RETURN();
446 void op_srav (void)
448 T0 = (int32_t)T1 >> (T0 & 0x1F);
449 RETURN();
452 void op_srlv (void)
454 T0 = T1 >> (T0 & 0x1F);
455 RETURN();
458 void op_clo (void)
460 int n;
462 if (T0 == (target_ulong)-1) {
463 T0 = 32;
464 } else {
465 for (n = 0; n < 32; n++) {
466 if (!(T0 & (1 << 31)))
467 break;
468 T0 = T0 << 1;
470 T0 = n;
472 RETURN();
475 void op_clz (void)
477 int n;
479 if (T0 == 0) {
480 T0 = 32;
481 } else {
482 for (n = 0; n < 32; n++) {
483 if (T0 & (1 << 31))
484 break;
485 T0 = T0 << 1;
487 T0 = n;
489 RETURN();
492 /* 64 bits arithmetic */
493 #if (HOST_LONG_BITS == 64)
494 static inline uint64_t get_HILO (void)
496 return ((uint64_t)env->HI << 32) | (uint64_t)env->LO;
499 static inline void set_HILO (uint64_t HILO)
501 env->LO = HILO & 0xFFFFFFFF;
502 env->HI = HILO >> 32;
505 void op_mult (void)
507 set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
508 RETURN();
511 void op_multu (void)
513 set_HILO((uint64_t)T0 * (uint64_t)T1);
514 RETURN();
517 void op_madd (void)
519 int64_t tmp;
521 tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
522 set_HILO((int64_t)get_HILO() + tmp);
523 RETURN();
526 void op_maddu (void)
528 uint64_t tmp;
530 tmp = ((uint64_t)T0 * (uint64_t)T1);
531 set_HILO(get_HILO() + tmp);
532 RETURN();
535 void op_msub (void)
537 int64_t tmp;
539 tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
540 set_HILO((int64_t)get_HILO() - tmp);
541 RETURN();
544 void op_msubu (void)
546 uint64_t tmp;
548 tmp = ((uint64_t)T0 * (uint64_t)T1);
549 set_HILO(get_HILO() - tmp);
550 RETURN();
552 #else
553 void op_mult (void)
555 CALL_FROM_TB0(do_mult);
556 RETURN();
559 void op_multu (void)
561 CALL_FROM_TB0(do_multu);
562 RETURN();
565 void op_madd (void)
567 CALL_FROM_TB0(do_madd);
568 RETURN();
571 void op_maddu (void)
573 CALL_FROM_TB0(do_maddu);
574 RETURN();
577 void op_msub (void)
579 CALL_FROM_TB0(do_msub);
580 RETURN();
583 void op_msubu (void)
585 CALL_FROM_TB0(do_msubu);
586 RETURN();
588 #endif
590 /* Conditional moves */
591 void op_movn (void)
593 if (T1 != 0)
594 env->gpr[PARAM1] = T0;
595 RETURN();
598 void op_movz (void)
600 if (T1 == 0)
601 env->gpr[PARAM1] = T0;
602 RETURN();
605 /* Tests */
606 #define OP_COND(name, cond) \
607 void glue(op_, name) (void) \
609 if (cond) { \
610 T0 = 1; \
611 } else { \
612 T0 = 0; \
614 RETURN(); \
617 OP_COND(eq, T0 == T1);
618 OP_COND(ne, T0 != T1);
619 OP_COND(ge, (int32_t)T0 >= (int32_t)T1);
620 OP_COND(geu, T0 >= T1);
621 OP_COND(lt, (int32_t)T0 < (int32_t)T1);
622 OP_COND(ltu, T0 < T1);
623 OP_COND(gez, (int32_t)T0 >= 0);
624 OP_COND(gtz, (int32_t)T0 > 0);
625 OP_COND(lez, (int32_t)T0 <= 0);
626 OP_COND(ltz, (int32_t)T0 < 0);
628 /* Branchs */
629 //#undef USE_DIRECT_JUMP
631 void OPPROTO op_goto_tb0(void)
633 GOTO_TB(op_goto_tb0, PARAM1, 0);
636 void OPPROTO op_goto_tb1(void)
638 GOTO_TB(op_goto_tb1, PARAM1, 1);
641 /* Branch to register */
642 void op_save_breg_target (void)
644 env->btarget = T2;
647 void op_restore_breg_target (void)
649 T2 = env->btarget;
652 void op_breg (void)
654 env->PC = T2;
655 RETURN();
658 void op_save_btarget (void)
660 env->btarget = PARAM1;
661 RETURN();
664 /* Conditional branch */
665 void op_set_bcond (void)
667 T2 = T0;
668 RETURN();
671 void op_save_bcond (void)
673 env->bcond = T2;
674 RETURN();
677 void op_restore_bcond (void)
679 T2 = env->bcond;
680 RETURN();
683 void op_jnz_T2 (void)
685 if (T2)
686 GOTO_LABEL_PARAM(1);
687 RETURN();
690 /* CP0 functions */
691 void op_mfc0 (void)
693 CALL_FROM_TB2(do_mfc0, PARAM1, PARAM2);
694 RETURN();
697 void op_mtc0 (void)
699 CALL_FROM_TB2(do_mtc0, PARAM1, PARAM2);
700 RETURN();
703 #ifdef MIPS_USES_FPU
705 #if 0
706 # define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env)
707 #else
708 # define DEBUG_FPU_STATE() do { } while(0)
709 #endif
711 void op_cp1_enabled(void)
713 if (!(env->CP0_Status & (1 << CP0St_CU1))) {
714 CALL_FROM_TB2(do_raise_exception_err, EXCP_CpU, 1);
716 RETURN();
719 /* CP1 functions */
720 void op_cfc1 (void)
722 if (T1 == 0) {
723 T0 = env->fcr0;
725 else {
726 /* fetch fcr31, masking unused bits */
727 T0 = env->fcr31 & 0x0183FFFF;
729 DEBUG_FPU_STATE();
730 RETURN();
733 /* convert MIPS rounding mode in FCR31 to IEEE library */
734 unsigned int ieee_rm[] = {
735 float_round_nearest_even,
736 float_round_to_zero,
737 float_round_up,
738 float_round_down
741 #define RESTORE_ROUNDING_MODE \
742 set_float_rounding_mode(ieee_rm[env->fcr31 & 3], &env->fp_status)
744 void op_ctc1 (void)
746 if (T1 == 0) {
747 /* XXX should this throw an exception?
748 * don't write to FCR0.
749 * env->fcr0 = T0;
752 else {
753 /* store new fcr31, masking unused bits */
754 env->fcr31 = T0 & 0x0183FFFF;
756 /* set rounding mode */
757 RESTORE_ROUNDING_MODE;
759 #ifndef CONFIG_SOFTFLOAT
760 /* no floating point exception for native float */
761 SET_FP_ENABLE(env->fcr31, 0);
762 #endif
764 DEBUG_FPU_STATE();
765 RETURN();
768 void op_mfc1 (void)
770 T0 = WT0;
771 DEBUG_FPU_STATE();
772 RETURN();
775 void op_mtc1 (void)
777 WT0 = T0;
778 DEBUG_FPU_STATE();
779 RETURN();
782 /* Float support.
783 Single precition routines have a "s" suffix, double precision a
784 "d" suffix. */
786 #define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void)
788 FLOAT_OP(cvtd, w)
790 FDT2 = int32_to_float64(WT0, &env->fp_status);
791 DEBUG_FPU_STATE();
792 RETURN();
794 FLOAT_OP(cvts, w)
796 FST2 = int32_to_float32(WT0, &env->fp_status);
797 DEBUG_FPU_STATE();
798 RETURN();
800 FLOAT_OP(cvtw, s)
802 WT2 = float32_to_int32(FST0, &env->fp_status);
803 DEBUG_FPU_STATE();
804 RETURN();
806 FLOAT_OP(cvtw, d)
808 WT2 = float64_to_int32(FDT0, &env->fp_status);
809 DEBUG_FPU_STATE();
810 RETURN();
813 FLOAT_OP(roundw, d)
815 set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
816 WT2 = float64_round_to_int(FDT0, &env->fp_status);
817 RESTORE_ROUNDING_MODE;
819 DEBUG_FPU_STATE();
820 RETURN();
822 FLOAT_OP(roundw, s)
824 set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
825 WT2 = float32_round_to_int(FST0, &env->fp_status);
826 RESTORE_ROUNDING_MODE;
827 DEBUG_FPU_STATE();
828 RETURN();
831 FLOAT_OP(truncw, d)
833 WT2 = float64_to_int32_round_to_zero(FDT0, &env->fp_status);
834 DEBUG_FPU_STATE();
835 RETURN();
837 FLOAT_OP(truncw, s)
839 WT2 = float32_to_int32_round_to_zero(FST0, &env->fp_status);
840 DEBUG_FPU_STATE();
841 RETURN();
844 FLOAT_OP(ceilw, d)
846 set_float_rounding_mode(float_round_up, &env->fp_status);
847 WT2 = float64_round_to_int(FDT0, &env->fp_status);
848 RESTORE_ROUNDING_MODE;
850 DEBUG_FPU_STATE();
851 RETURN();
853 FLOAT_OP(ceilw, s)
855 set_float_rounding_mode(float_round_up, &env->fp_status);
856 WT2 = float32_round_to_int(FST0, &env->fp_status);
857 RESTORE_ROUNDING_MODE;
858 DEBUG_FPU_STATE();
859 RETURN();
862 FLOAT_OP(floorw, d)
864 set_float_rounding_mode(float_round_down, &env->fp_status);
865 WT2 = float64_round_to_int(FDT0, &env->fp_status);
866 RESTORE_ROUNDING_MODE;
868 DEBUG_FPU_STATE();
869 RETURN();
871 FLOAT_OP(floorw, s)
873 set_float_rounding_mode(float_round_down, &env->fp_status);
874 WT2 = float32_round_to_int(FST0, &env->fp_status);
875 RESTORE_ROUNDING_MODE;
876 DEBUG_FPU_STATE();
877 RETURN();
880 /* binary operations */
881 #define FLOAT_BINOP(name) \
882 FLOAT_OP(name, d) \
884 FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status); \
885 DEBUG_FPU_STATE(); \
887 FLOAT_OP(name, s) \
889 FST2 = float32_ ## name (FST0, FST1, &env->fp_status); \
890 DEBUG_FPU_STATE(); \
892 FLOAT_BINOP(add)
893 FLOAT_BINOP(sub)
894 FLOAT_BINOP(mul)
895 FLOAT_BINOP(div)
896 #undef FLOAT_BINOP
898 /* unary operations, modifying fp status */
899 #define FLOAT_UNOP(name) \
900 FLOAT_OP(name, d) \
902 FDT2 = float64_ ## name(FDT0, &env->fp_status); \
903 DEBUG_FPU_STATE(); \
905 FLOAT_OP(name, s) \
907 FST2 = float32_ ## name(FST0, &env->fp_status); \
908 DEBUG_FPU_STATE(); \
910 FLOAT_UNOP(sqrt)
911 #undef FLOAT_UNOP
913 /* unary operations, not modifying fp status */
914 #define FLOAT_UNOP(name) \
915 FLOAT_OP(name, d) \
917 FDT2 = float64_ ## name(FDT0); \
918 DEBUG_FPU_STATE(); \
920 FLOAT_OP(name, s) \
922 FST2 = float32_ ## name(FST0); \
923 DEBUG_FPU_STATE(); \
925 FLOAT_UNOP(abs)
926 FLOAT_UNOP(chs)
927 #undef FLOAT_UNOP
929 FLOAT_OP(mov, d)
931 FDT2 = FDT0;
932 DEBUG_FPU_STATE();
933 RETURN();
935 FLOAT_OP(mov, s)
937 FST2 = FST0;
938 DEBUG_FPU_STATE();
939 RETURN();
942 #ifdef CONFIG_SOFTFLOAT
943 #define clear_invalid() do { \
944 int flags = get_float_exception_flags(&env->fp_status); \
945 flags &= ~float_flag_invalid; \
946 set_float_exception_flags(flags, &env->fp_status); \
947 } while(0)
948 #else
949 #define clear_invalid() do { } while(0)
950 #endif
952 extern void dump_fpu_s(CPUState *env);
954 #define FOP_COND(fmt, op, sig, cond) \
955 void op_cmp_ ## fmt ## _ ## op (void) \
957 if (cond) \
958 SET_FP_COND(env->fcr31); \
959 else \
960 CLEAR_FP_COND(env->fcr31); \
961 if (!sig) \
962 clear_invalid(); \
963 /*CALL_FROM_TB1(dump_fpu_s, env);*/ \
964 DEBUG_FPU_STATE(); \
965 RETURN(); \
968 flag float64_is_unordered(float64 a, float64 b STATUS_PARAM)
970 extern flag float64_is_nan( float64 a );
971 if (float64_is_nan(a) || float64_is_nan(b)) {
972 float_raise(float_flag_invalid, status);
973 return 1;
975 else {
976 return 0;
980 FOP_COND(d, f, 0, 0)
981 FOP_COND(d, un, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status))
982 FOP_COND(d, eq, 0, float64_eq(FDT0, FDT1, &env->fp_status))
983 FOP_COND(d, ueq, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status))
984 FOP_COND(d, olt, 0, float64_lt(FDT0, FDT1, &env->fp_status))
985 FOP_COND(d, ult, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status))
986 FOP_COND(d, ole, 0, float64_le(FDT0, FDT1, &env->fp_status))
987 FOP_COND(d, ule, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status))
988 /* NOTE: the comma operator will make "cond" to eval to false,
989 * but float*_is_unordered() is still called
991 FOP_COND(d, sf, 1, (float64_is_unordered(FDT0, FDT1, &env->fp_status), 0))
992 FOP_COND(d, ngle,1, float64_is_unordered(FDT1, FDT0, &env->fp_status))
993 FOP_COND(d, seq, 1, float64_eq(FDT0, FDT1, &env->fp_status))
994 FOP_COND(d, ngl, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status))
995 FOP_COND(d, lt, 1, float64_lt(FDT0, FDT1, &env->fp_status))
996 FOP_COND(d, nge, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status))
997 FOP_COND(d, le, 1, float64_le(FDT0, FDT1, &env->fp_status))
998 FOP_COND(d, ngt, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status))
1000 flag float32_is_unordered(float32 a, float32 b STATUS_PARAM)
1002 extern flag float32_is_nan( float32 a );
1003 if (float32_is_nan(a) || float32_is_nan(b)) {
1004 float_raise(float_flag_invalid, status);
1005 return 1;
1007 else {
1008 return 0;
1012 /* NOTE: the comma operator will make "cond" to eval to false,
1013 * but float*_is_unordered() is still called
1015 FOP_COND(s, f, 0, 0)
1016 FOP_COND(s, un, 0, float32_is_unordered(FST1, FST0, &env->fp_status))
1017 FOP_COND(s, eq, 0, float32_eq(FST0, FST1, &env->fp_status))
1018 FOP_COND(s, ueq, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status))
1019 FOP_COND(s, olt, 0, float32_lt(FST0, FST1, &env->fp_status))
1020 FOP_COND(s, ult, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status))
1021 FOP_COND(s, ole, 0, float32_le(FST0, FST1, &env->fp_status))
1022 FOP_COND(s, ule, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status))
1023 /* NOTE: the comma operator will make "cond" to eval to false,
1024 * but float*_is_unordered() is still called
1026 FOP_COND(s, sf, 1, (float32_is_unordered(FST0, FST1, &env->fp_status), 0))
1027 FOP_COND(s, ngle,1, float32_is_unordered(FST1, FST0, &env->fp_status))
1028 FOP_COND(s, seq, 1, float32_eq(FST0, FST1, &env->fp_status))
1029 FOP_COND(s, ngl, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status))
1030 FOP_COND(s, lt, 1, float32_lt(FST0, FST1, &env->fp_status))
1031 FOP_COND(s, nge, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status))
1032 FOP_COND(s, le, 1, float32_le(FST0, FST1, &env->fp_status))
1033 FOP_COND(s, ngt, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status))
1035 void op_bc1f (void)
1037 T0 = ! IS_FP_COND_SET(env->fcr31);
1038 DEBUG_FPU_STATE();
1039 RETURN();
1042 void op_bc1t (void)
1044 T0 = IS_FP_COND_SET(env->fcr31);
1045 DEBUG_FPU_STATE();
1046 RETURN();
1048 #endif /* MIPS_USES_FPU */
1050 #if defined(MIPS_USES_R4K_TLB)
1051 void op_tlbwi (void)
1053 CALL_FROM_TB0(do_tlbwi);
1054 RETURN();
1057 void op_tlbwr (void)
1059 CALL_FROM_TB0(do_tlbwr);
1060 RETURN();
1063 void op_tlbp (void)
1065 CALL_FROM_TB0(do_tlbp);
1066 RETURN();
1069 void op_tlbr (void)
1071 CALL_FROM_TB0(do_tlbr);
1072 RETURN();
1074 #endif
1076 /* Specials */
1077 void op_pmon (void)
1079 CALL_FROM_TB1(do_pmon, PARAM1);
1082 void op_trap (void)
1084 if (T0) {
1085 CALL_FROM_TB1(do_raise_exception_direct, EXCP_TRAP);
1087 RETURN();
1090 void op_debug (void)
1092 CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG);
1095 void op_set_lladdr (void)
1097 env->CP0_LLAddr = T2;
1100 void debug_eret (void);
1101 void op_eret (void)
1103 CALL_FROM_TB0(debug_eret);
1104 if (env->hflags & MIPS_HFLAG_ERL) {
1105 env->PC = env->CP0_ErrorEPC;
1106 env->hflags &= ~MIPS_HFLAG_ERL;
1107 } else {
1108 env->PC = env->CP0_EPC;
1109 env->hflags &= ~MIPS_HFLAG_EXL;
1111 env->CP0_LLAddr = 1;
1114 void op_deret (void)
1116 CALL_FROM_TB0(debug_eret);
1117 env->PC = env->CP0_DEPC;
1120 void op_save_state (void)
1122 env->hflags = PARAM1;
1123 RETURN();
1126 void op_save_pc (void)
1128 env->PC = PARAM1;
1129 RETURN();
1132 void op_raise_exception (void)
1134 CALL_FROM_TB1(do_raise_exception, PARAM1);
1135 RETURN();
1138 void op_raise_exception_err (void)
1140 CALL_FROM_TB2(do_raise_exception_err, PARAM1, PARAM2);
1141 RETURN();
1144 void op_exit_tb (void)
1146 EXIT_TB();
1149 void op_wait (void)
1151 env->halted = 1;
1152 CALL_FROM_TB1(do_raise_exception, EXCP_HLT);