2 * MIPS emulation micro-operations for qemu.
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
26 #define CALL_FROM_TB0(func) func()
29 #define CALL_FROM_TB1(func, arg0) func(arg0)
31 #ifndef CALL_FROM_TB1_CONST16
32 #define CALL_FROM_TB1_CONST16(func, arg0) CALL_FROM_TB1(func, arg0)
35 #define CALL_FROM_TB2(func, arg0, arg1) func(arg0, arg1)
37 #ifndef CALL_FROM_TB2_CONST16
38 #define CALL_FROM_TB2_CONST16(func, arg0, arg1) \
39 CALL_FROM_TB2(func, arg0, arg1)
42 #define CALL_FROM_TB3(func, arg0, arg1, arg2) func(arg0, arg1, arg2)
45 #define CALL_FROM_TB4(func, arg0, arg1, arg2, arg3) \
46 func(arg0, arg1, arg2, arg3)
50 #include "op_template.c"
53 #include "op_template.c"
56 #include "op_template.c"
59 #include "op_template.c"
62 #include "op_template.c"
65 #include "op_template.c"
68 #include "op_template.c"
71 #include "op_template.c"
74 #include "op_template.c"
77 #include "op_template.c"
80 #include "op_template.c"
83 #include "op_template.c"
86 #include "op_template.c"
89 #include "op_template.c"
92 #include "op_template.c"
95 #include "op_template.c"
98 #include "op_template.c"
101 #include "op_template.c"
104 #include "op_template.c"
107 #include "op_template.c"
110 #include "op_template.c"
113 #include "op_template.c"
116 #include "op_template.c"
119 #include "op_template.c"
122 #include "op_template.c"
125 #include "op_template.c"
128 #include "op_template.c"
131 #include "op_template.c"
134 #include "op_template.c"
137 #include "op_template.c"
140 #include "op_template.c"
144 #include "op_template.c"
148 #include "fop_template.c"
151 #include "fop_template.c"
154 #include "fop_template.c"
157 #include "fop_template.c"
160 #include "fop_template.c"
163 #include "fop_template.c"
166 #include "fop_template.c"
169 #include "fop_template.c"
172 #include "fop_template.c"
175 #include "fop_template.c"
178 #include "fop_template.c"
181 #include "fop_template.c"
184 #include "fop_template.c"
187 #include "fop_template.c"
190 #include "fop_template.c"
193 #include "fop_template.c"
196 #include "fop_template.c"
199 #include "fop_template.c"
202 #include "fop_template.c"
205 #include "fop_template.c"
208 #include "fop_template.c"
211 #include "fop_template.c"
214 #include "fop_template.c"
217 #include "fop_template.c"
220 #include "fop_template.c"
223 #include "fop_template.c"
226 #include "fop_template.c"
229 #include "fop_template.c"
232 #include "fop_template.c"
235 #include "fop_template.c"
238 #include "fop_template.c"
241 #include "fop_template.c"
245 #include "fop_template.c"
248 void op_dup_T0 (void)
254 void op_load_HI (void)
260 void op_store_HI (void)
266 void op_load_LO (void)
272 void op_store_LO (void)
279 #define MEMSUFFIX _raw
282 #if !defined(CONFIG_USER_ONLY)
283 #define MEMSUFFIX _user
287 #define MEMSUFFIX _kernel
292 /* Addresses computation */
293 void op_addr_add (void)
295 /* For compatibility with 32-bit code, data reference in user mode
296 with Status_UX = 0 should be casted to 32-bit and sign extended.
297 See the MIPS64 PRA manual, section 4.10. */
299 if ((env
->CP0_Status
& (1 << CP0St_UM
)) &&
300 !(env
->CP0_Status
& (1 << CP0St_UX
)))
301 T0
= (int64_t)(int32_t)(T0
+ T1
);
311 T0
= (int32_t)((int32_t)T0
+ (int32_t)T1
);
320 T0
= (int32_t)T0
+ (int32_t)T1
;
321 if (((tmp
^ T1
^ (-1)) & (T0
^ T1
)) >> 31) {
322 /* operands of same sign, result different sign */
323 CALL_FROM_TB1(do_raise_exception
, EXCP_OVERFLOW
);
331 T0
= (int32_t)((int32_t)T0
- (int32_t)T1
);
340 T0
= (int32_t)T0
- (int32_t)T1
;
341 if (((tmp
^ T1
) & (tmp
^ T0
)) >> 31) {
342 /* operands of different sign, first operand and result different sign */
343 CALL_FROM_TB1(do_raise_exception
, EXCP_OVERFLOW
);
351 T0
= (int32_t)((int32_t)T0
* (int32_t)T1
);
355 #if HOST_LONG_BITS < 64
358 CALL_FROM_TB0(do_div
);
365 env
->LO
= (int32_t)((int64_t)(int32_t)T0
/ (int32_t)T1
);
366 env
->HI
= (int32_t)((int64_t)(int32_t)T0
% (int32_t)T1
);
375 env
->LO
= (int32_t)((uint32_t)T0
/ (uint32_t)T1
);
376 env
->HI
= (int32_t)((uint32_t)T0
% (uint32_t)T1
);
395 if (((tmp
^ T1
^ (-1)) & (T0
^ T1
)) >> 63) {
396 /* operands of same sign, result different sign */
397 CALL_FROM_TB1(do_raise_exception
, EXCP_OVERFLOW
);
413 T0
= (int64_t)T0
- (int64_t)T1
;
414 if (((tmp
^ T1
) & (tmp
^ T0
)) >> 63) {
415 /* operands of different sign, first operand and result different sign */
416 CALL_FROM_TB1(do_raise_exception
, EXCP_OVERFLOW
);
423 T0
= (int64_t)T0
* (int64_t)T1
;
427 /* Those might call libgcc functions. */
434 #if TARGET_LONG_BITS > HOST_LONG_BITS
450 #endif /* TARGET_MIPS64 */
479 T0
= (int32_t)((uint32_t)T0
<< T1
);
485 T0
= (int32_t)((int32_t)T0
>> T1
);
491 T0
= (int32_t)((uint32_t)T0
>> T1
);
500 tmp
= (int32_t)((uint32_t)T0
<< (0x20 - T1
));
501 T0
= (int32_t)((uint32_t)T0
>> T1
) | tmp
;
508 T0
= (int32_t)((uint32_t)T1
<< ((uint32_t)T0
& 0x1F));
514 T0
= (int32_t)((int32_t)T1
>> (T0
& 0x1F));
520 T0
= (int32_t)((uint32_t)T1
>> (T0
& 0x1F));
530 tmp
= (int32_t)((uint32_t)T1
<< (0x20 - T0
));
531 T0
= (int32_t)((uint32_t)T1
>> T0
) | tmp
;
541 if (T0
== ~((target_ulong
)0)) {
544 for (n
= 0; n
< 32; n
++) {
545 if (!(T0
& (1 << 31)))
561 for (n
= 0; n
< 32; n
++) {
573 #if TARGET_LONG_BITS > HOST_LONG_BITS
574 /* Those might call libgcc functions. */
577 CALL_FROM_TB0(do_dsll
);
581 void op_dsll32 (void)
583 CALL_FROM_TB0(do_dsll32
);
589 CALL_FROM_TB0(do_dsra
);
593 void op_dsra32 (void)
595 CALL_FROM_TB0(do_dsra32
);
601 CALL_FROM_TB0(do_dsrl
);
605 void op_dsrl32 (void)
607 CALL_FROM_TB0(do_dsrl32
);
613 CALL_FROM_TB0(do_drotr
);
617 void op_drotr32 (void)
619 CALL_FROM_TB0(do_drotr32
);
625 CALL_FROM_TB0(do_dsllv
);
631 CALL_FROM_TB0(do_dsrav
);
637 CALL_FROM_TB0(do_dsrlv
);
641 void op_drotrv (void)
643 CALL_FROM_TB0(do_drotrv
);
647 #else /* TARGET_LONG_BITS > HOST_LONG_BITS */
655 void op_dsll32 (void)
657 T0
= T0
<< (T1
+ 32);
663 T0
= (int64_t)T0
>> T1
;
667 void op_dsra32 (void)
669 T0
= (int64_t)T0
>> (T1
+ 32);
679 void op_dsrl32 (void)
681 T0
= T0
>> (T1
+ 32);
690 tmp
= T0
<< (0x40 - T1
);
691 T0
= (T0
>> T1
) | tmp
;
696 void op_drotr32 (void)
701 tmp
= T0
<< (0x40 - (32 + T1
));
702 T0
= (T0
>> (32 + T1
)) | tmp
;
709 T0
= T1
<< (T0
& 0x3F);
715 T0
= (int64_t)T1
>> (T0
& 0x3F);
721 T0
= T1
>> (T0
& 0x3F);
725 void op_drotrv (void)
731 tmp
= T1
<< (0x40 - T0
);
732 T0
= (T1
>> T0
) | tmp
;
737 #endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
743 if (T0
== ~((target_ulong
)0)) {
746 for (n
= 0; n
< 64; n
++) {
747 if (!(T0
& (1ULL << 63)))
763 for (n
= 0; n
< 64; n
++) {
764 if (T0
& (1ULL << 63))
774 /* 64 bits arithmetic */
775 #if TARGET_LONG_BITS > HOST_LONG_BITS
778 CALL_FROM_TB0(do_mult
);
784 CALL_FROM_TB0(do_multu
);
790 CALL_FROM_TB0(do_madd
);
796 CALL_FROM_TB0(do_maddu
);
802 CALL_FROM_TB0(do_msub
);
808 CALL_FROM_TB0(do_msubu
);
812 #else /* TARGET_LONG_BITS > HOST_LONG_BITS */
814 static inline uint64_t get_HILO (void)
816 return ((uint64_t)env
->HI
<< 32) | ((uint64_t)(uint32_t)env
->LO
);
819 static inline void set_HILO (uint64_t HILO
)
821 env
->LO
= (int32_t)(HILO
& 0xFFFFFFFF);
822 env
->HI
= (int32_t)(HILO
>> 32);
827 set_HILO((int64_t)(int32_t)T0
* (int64_t)(int32_t)T1
);
833 set_HILO((uint64_t)(uint32_t)T0
* (uint64_t)(uint32_t)T1
);
841 tmp
= ((int64_t)(int32_t)T0
* (int64_t)(int32_t)T1
);
842 set_HILO((int64_t)get_HILO() + tmp
);
850 tmp
= ((uint64_t)(uint32_t)T0
* (uint64_t)(uint32_t)T1
);
851 set_HILO(get_HILO() + tmp
);
859 tmp
= ((int64_t)(int32_t)T0
* (int64_t)(int32_t)T1
);
860 set_HILO((int64_t)get_HILO() - tmp
);
868 tmp
= ((uint64_t)(uint32_t)T0
* (uint64_t)(uint32_t)T1
);
869 set_HILO(get_HILO() - tmp
);
872 #endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
877 CALL_FROM_TB4(muls64
, &(env
->HI
), &(env
->LO
), T0
, T1
);
881 void op_dmultu (void)
883 CALL_FROM_TB4(mulu64
, &(env
->HI
), &(env
->LO
), T0
, T1
);
888 /* Conditional moves */
892 env
->gpr
[PARAM1
] = T0
;
899 env
->gpr
[PARAM1
] = T0
;
905 if (!(env
->fcr31
& PARAM1
))
912 if (env
->fcr31
& PARAM1
)
918 #define OP_COND(name, cond) \
919 void glue(op_, name) (void) \
929 OP_COND(eq
, T0
== T1
);
930 OP_COND(ne
, T0
!= T1
);
931 OP_COND(ge
, (int32_t)T0
>= (int32_t)T1
);
932 OP_COND(geu
, T0
>= T1
);
933 OP_COND(lt
, (int32_t)T0
< (int32_t)T1
);
934 OP_COND(ltu
, T0
< T1
);
935 OP_COND(gez
, (int32_t)T0
>= 0);
936 OP_COND(gtz
, (int32_t)T0
> 0);
937 OP_COND(lez
, (int32_t)T0
<= 0);
938 OP_COND(ltz
, (int32_t)T0
< 0);
941 void OPPROTO
op_goto_tb0(void)
943 GOTO_TB(op_goto_tb0
, PARAM1
, 0);
947 void OPPROTO
op_goto_tb1(void)
949 GOTO_TB(op_goto_tb1
, PARAM1
, 1);
953 /* Branch to register */
954 void op_save_breg_target (void)
960 void op_restore_breg_target (void)
972 void op_save_btarget (void)
974 env
->btarget
= PARAM1
;
978 /* Conditional branch */
979 void op_set_bcond (void)
985 void op_save_bcond (void)
991 void op_restore_bcond (void)
997 void op_jnz_T2 (void)
1000 GOTO_LABEL_PARAM(1);
1005 void op_mfc0_index (void)
1007 T0
= env
->CP0_Index
;
1011 void op_mfc0_random (void)
1013 CALL_FROM_TB0(do_mfc0_random
);
1017 void op_mfc0_entrylo0 (void)
1019 T0
= (int32_t)env
->CP0_EntryLo0
;
1023 void op_mfc0_entrylo1 (void)
1025 T0
= (int32_t)env
->CP0_EntryLo1
;
1029 void op_mfc0_context (void)
1031 T0
= (int32_t)env
->CP0_Context
;
1035 void op_mfc0_pagemask (void)
1037 T0
= env
->CP0_PageMask
;
1041 void op_mfc0_pagegrain (void)
1043 T0
= env
->CP0_PageGrain
;
1047 void op_mfc0_wired (void)
1049 T0
= env
->CP0_Wired
;
1053 void op_mfc0_hwrena (void)
1055 T0
= env
->CP0_HWREna
;
1059 void op_mfc0_badvaddr (void)
1061 T0
= (int32_t)env
->CP0_BadVAddr
;
1065 void op_mfc0_count (void)
1067 CALL_FROM_TB0(do_mfc0_count
);
1071 void op_mfc0_entryhi (void)
1073 T0
= (int32_t)env
->CP0_EntryHi
;
1077 void op_mfc0_compare (void)
1079 T0
= env
->CP0_Compare
;
1083 void op_mfc0_status (void)
1085 T0
= env
->CP0_Status
;
1089 void op_mfc0_intctl (void)
1091 T0
= env
->CP0_IntCtl
;
1095 void op_mfc0_srsctl (void)
1097 T0
= env
->CP0_SRSCtl
;
1101 void op_mfc0_srsmap (void)
1103 T0
= env
->CP0_SRSMap
;
1107 void op_mfc0_cause (void)
1109 T0
= env
->CP0_Cause
;
1113 void op_mfc0_epc (void)
1115 T0
= (int32_t)env
->CP0_EPC
;
1119 void op_mfc0_prid (void)
1125 void op_mfc0_ebase (void)
1127 T0
= env
->CP0_EBase
;
1131 void op_mfc0_config0 (void)
1133 T0
= env
->CP0_Config0
;
1137 void op_mfc0_config1 (void)
1139 T0
= env
->CP0_Config1
;
1143 void op_mfc0_config2 (void)
1145 T0
= env
->CP0_Config2
;
1149 void op_mfc0_config3 (void)
1151 T0
= env
->CP0_Config3
;
1155 void op_mfc0_config6 (void)
1157 T0
= env
->CP0_Config6
;
1161 void op_mfc0_config7 (void)
1163 T0
= env
->CP0_Config7
;
1167 void op_mfc0_lladdr (void)
1169 T0
= (int32_t)env
->CP0_LLAddr
>> 4;
1173 void op_mfc0_watchlo0 (void)
1175 T0
= (int32_t)env
->CP0_WatchLo
;
1179 void op_mfc0_watchhi0 (void)
1181 T0
= env
->CP0_WatchHi
;
1185 void op_mfc0_xcontext (void)
1187 T0
= (int32_t)env
->CP0_XContext
;
1191 void op_mfc0_framemask (void)
1193 T0
= env
->CP0_Framemask
;
1197 void op_mfc0_debug (void)
1199 T0
= env
->CP0_Debug
;
1200 if (env
->hflags
& MIPS_HFLAG_DM
)
1201 T0
|= 1 << CP0DB_DM
;
1205 void op_mfc0_depc (void)
1207 T0
= (int32_t)env
->CP0_DEPC
;
1211 void op_mfc0_performance0 (void)
1213 T0
= env
->CP0_Performance0
;
1217 void op_mfc0_taglo (void)
1219 T0
= env
->CP0_TagLo
;
1223 void op_mfc0_datalo (void)
1225 T0
= env
->CP0_DataLo
;
1229 void op_mfc0_taghi (void)
1231 T0
= env
->CP0_TagHi
;
1235 void op_mfc0_datahi (void)
1237 T0
= env
->CP0_DataHi
;
1241 void op_mfc0_errorepc (void)
1243 T0
= (int32_t)env
->CP0_ErrorEPC
;
1247 void op_mfc0_desave (void)
1249 T0
= env
->CP0_DESAVE
;
1253 void op_mtc0_index (void)
1255 env
->CP0_Index
= (env
->CP0_Index
& 0x80000000) | (T0
% env
->nb_tlb
);
1259 void op_mtc0_entrylo0 (void)
1261 /* Large physaddr not implemented */
1262 /* 1k pages not implemented */
1263 env
->CP0_EntryLo0
= T0
& 0x3FFFFFFF;
1267 void op_mtc0_entrylo1 (void)
1269 /* Large physaddr not implemented */
1270 /* 1k pages not implemented */
1271 env
->CP0_EntryLo1
= T0
& 0x3FFFFFFF;
1275 void op_mtc0_context (void)
1277 env
->CP0_Context
= (env
->CP0_Context
& 0x007FFFFF) | (T0
& ~0x007FFFFF);
1281 void op_mtc0_pagemask (void)
1283 /* 1k pages not implemented */
1284 env
->CP0_PageMask
= T0
& (0x1FFFFFFF & (TARGET_PAGE_MASK
<< 1));
1288 void op_mtc0_pagegrain (void)
1290 /* SmartMIPS not implemented */
1291 /* Large physaddr not implemented */
1292 /* 1k pages not implemented */
1293 env
->CP0_PageGrain
= 0;
1297 void op_mtc0_wired (void)
1299 env
->CP0_Wired
= T0
% env
->nb_tlb
;
1303 void op_mtc0_hwrena (void)
1305 env
->CP0_HWREna
= T0
& 0x0000000F;
1309 void op_mtc0_count (void)
1311 CALL_FROM_TB2(cpu_mips_store_count
, env
, T0
);
1315 void op_mtc0_entryhi (void)
1317 target_ulong old
, val
;
1319 /* 1k pages not implemented */
1320 val
= T0
& ((TARGET_PAGE_MASK
<< 1) | 0xFF);
1321 #ifdef TARGET_MIPS64
1322 val
= T0
& 0xC00000FFFFFFFFFFULL
;
1324 old
= env
->CP0_EntryHi
;
1325 env
->CP0_EntryHi
= val
;
1326 /* If the ASID changes, flush qemu's TLB. */
1327 if ((old
& 0xFF) != (val
& 0xFF))
1328 CALL_FROM_TB2(cpu_mips_tlb_flush
, env
, 1);
1332 void op_mtc0_compare (void)
1334 CALL_FROM_TB2(cpu_mips_store_compare
, env
, T0
);
1338 void op_mtc0_status (void)
1341 uint32_t mask
= env
->Status_rw_bitmask
;
1343 /* No reverse endianness, no MDMX/DSP, no 64bit ops
1346 old
= env
->CP0_Status
;
1347 if (!(val
& (1 << CP0St_EXL
)) &&
1348 !(val
& (1 << CP0St_ERL
)) &&
1349 !(env
->hflags
& MIPS_HFLAG_DM
) &&
1350 (val
& (1 << CP0St_UM
)))
1351 env
->hflags
|= MIPS_HFLAG_UM
;
1352 env
->CP0_Status
= (env
->CP0_Status
& ~mask
) | val
;
1353 if (loglevel
& CPU_LOG_EXEC
)
1354 CALL_FROM_TB2(do_mtc0_status_debug
, old
, val
);
1355 CALL_FROM_TB1(cpu_mips_update_irq
, env
);
1359 void op_mtc0_intctl (void)
1361 /* vectored interrupts not implemented, timer on int 7,
1362 no performance counters. */
1363 env
->CP0_IntCtl
|= T0
& 0x000002e0;
1367 void op_mtc0_srsctl (void)
1369 /* shadow registers not implemented */
1370 env
->CP0_SRSCtl
= 0;
1374 void op_mtc0_srsmap (void)
1376 /* shadow registers not implemented */
1377 env
->CP0_SRSMap
= 0;
1381 void op_mtc0_cause (void)
1383 uint32_t mask
= 0x00C00300;
1385 if ((env
->CP0_Config0
& (0x7 << CP0C0_AR
)) == (1 << CP0C0_AR
))
1386 mask
|= 1 << CP0Ca_DC
;
1388 env
->CP0_Cause
= (env
->CP0_Cause
& ~mask
) | (T0
& mask
);
1390 /* Handle the software interrupt as an hardware one, as they
1392 if (T0
& CP0Ca_IP_mask
) {
1393 CALL_FROM_TB1(cpu_mips_update_irq
, env
);
1398 void op_mtc0_epc (void)
1404 void op_mtc0_ebase (void)
1406 /* vectored interrupts not implemented */
1407 /* Multi-CPU not implemented */
1408 env
->CP0_EBase
= 0x80000000 | (T0
& 0x3FFFF000);
1412 void op_mtc0_config0 (void)
1414 env
->CP0_Config0
= (env
->CP0_Config0
& 0x81FFFFF8) | (T0
& 0x00000001);
1418 void op_mtc0_config2 (void)
1420 /* tertiary/secondary caches not implemented */
1421 env
->CP0_Config2
= (env
->CP0_Config2
& 0x8FFF0FFF);
1425 void op_mtc0_watchlo0 (void)
1427 /* Watch exceptions for instructions, data loads, data stores
1429 env
->CP0_WatchLo
= (T0
& ~0x7);
1433 void op_mtc0_watchhi0 (void)
1435 env
->CP0_WatchHi
= (T0
& 0x40FF0FF8);
1436 env
->CP0_WatchHi
&= ~(env
->CP0_WatchHi
& T0
& 0x7);
1440 void op_mtc0_framemask (void)
1442 env
->CP0_Framemask
= T0
; /* XXX */
1446 void op_mtc0_debug (void)
1448 env
->CP0_Debug
= (env
->CP0_Debug
& 0x8C03FC1F) | (T0
& 0x13300120);
1449 if (T0
& (1 << CP0DB_DM
))
1450 env
->hflags
|= MIPS_HFLAG_DM
;
1452 env
->hflags
&= ~MIPS_HFLAG_DM
;
1456 void op_mtc0_depc (void)
1462 void op_mtc0_performance0 (void)
1464 env
->CP0_Performance0
= T0
; /* XXX */
1468 void op_mtc0_taglo (void)
1470 env
->CP0_TagLo
= T0
& 0xFFFFFCF6;
1474 void op_mtc0_datalo (void)
1476 env
->CP0_DataLo
= T0
; /* XXX */
1480 void op_mtc0_taghi (void)
1482 env
->CP0_TagHi
= T0
; /* XXX */
1486 void op_mtc0_datahi (void)
1488 env
->CP0_DataHi
= T0
; /* XXX */
1492 void op_mtc0_errorepc (void)
1494 env
->CP0_ErrorEPC
= T0
;
1498 void op_mtc0_desave (void)
1500 env
->CP0_DESAVE
= T0
;
1504 #ifdef TARGET_MIPS64
1505 void op_mtc0_xcontext (void)
1507 env
->CP0_XContext
= (env
->CP0_XContext
& 0x1ffffffffULL
) | (T0
& ~0x1ffffffffULL
);
1511 void op_dmfc0_entrylo0 (void)
1513 T0
= env
->CP0_EntryLo0
;
1517 void op_dmfc0_entrylo1 (void)
1519 T0
= env
->CP0_EntryLo1
;
1523 void op_dmfc0_context (void)
1525 T0
= env
->CP0_Context
;
1529 void op_dmfc0_badvaddr (void)
1531 T0
= env
->CP0_BadVAddr
;
1535 void op_dmfc0_entryhi (void)
1537 T0
= env
->CP0_EntryHi
;
1541 void op_dmfc0_epc (void)
1547 void op_dmfc0_lladdr (void)
1549 T0
= env
->CP0_LLAddr
>> 4;
1553 void op_dmfc0_watchlo0 (void)
1555 T0
= env
->CP0_WatchLo
;
1559 void op_dmfc0_xcontext (void)
1561 T0
= env
->CP0_XContext
;
1565 void op_dmfc0_depc (void)
1571 void op_dmfc0_errorepc (void)
1573 T0
= env
->CP0_ErrorEPC
;
1576 #endif /* TARGET_MIPS64 */
1580 # define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env)
1582 # define DEBUG_FPU_STATE() do { } while(0)
1585 void op_cp0_enabled(void)
1587 if (!(env
->CP0_Status
& (1 << CP0St_CU0
)) &&
1588 (env
->hflags
& MIPS_HFLAG_UM
)) {
1589 CALL_FROM_TB2(do_raise_exception_err
, EXCP_CpU
, 0);
1594 void op_cp1_enabled(void)
1596 if (!(env
->CP0_Status
& (1 << CP0St_CU1
))) {
1597 CALL_FROM_TB2(do_raise_exception_err
, EXCP_CpU
, 1);
1602 /* convert MIPS rounding mode in FCR31 to IEEE library */
1603 unsigned int ieee_rm
[] = {
1604 float_round_nearest_even
,
1605 float_round_to_zero
,
1610 #define RESTORE_ROUNDING_MODE \
1611 set_float_rounding_mode(ieee_rm[env->fcr31 & 3], &env->fp_status)
1613 inline char ieee_ex_to_mips(char xcpt
)
1615 return (xcpt
& float_flag_inexact
) >> 5 |
1616 (xcpt
& float_flag_underflow
) >> 3 |
1617 (xcpt
& float_flag_overflow
) >> 1 |
1618 (xcpt
& float_flag_divbyzero
) << 1 |
1619 (xcpt
& float_flag_invalid
) << 4;
1622 inline char mips_ex_to_ieee(char xcpt
)
1624 return (xcpt
& FP_INEXACT
) << 5 |
1625 (xcpt
& FP_UNDERFLOW
) << 3 |
1626 (xcpt
& FP_OVERFLOW
) << 1 |
1627 (xcpt
& FP_DIV0
) >> 1 |
1628 (xcpt
& FP_INVALID
) >> 4;
1631 inline void update_fcr31(void)
1633 int tmp
= ieee_ex_to_mips(get_float_exception_flags(&env
->fp_status
));
1635 SET_FP_CAUSE(env
->fcr31
, tmp
);
1636 if (GET_FP_ENABLE(env
->fcr31
) & tmp
)
1637 CALL_FROM_TB1(do_raise_exception
, EXCP_FPE
);
1639 UPDATE_FP_FLAGS(env
->fcr31
, tmp
);
1647 T0
= (int32_t)env
->fcr0
;
1650 T0
= ((env
->fcr31
>> 24) & 0xfe) | ((env
->fcr31
>> 23) & 0x1);
1653 T0
= env
->fcr31
& 0x0003f07c;
1656 T0
= (env
->fcr31
& 0x00000f83) | ((env
->fcr31
>> 22) & 0x4);
1659 T0
= (int32_t)env
->fcr31
;
1670 if (T0
& 0xffffff00)
1672 env
->fcr31
= (env
->fcr31
& 0x017fffff) | ((T0
& 0xfe) << 24) |
1676 if (T0
& 0x007c0000)
1678 env
->fcr31
= (env
->fcr31
& 0xfffc0f83) | (T0
& 0x0003f07c);
1681 if (T0
& 0x007c0000)
1683 env
->fcr31
= (env
->fcr31
& 0xfefff07c) | (T0
& 0x00000f83) |
1687 if (T0
& 0x007c0000)
1694 /* set rounding mode */
1695 RESTORE_ROUNDING_MODE
;
1696 set_float_exception_flags(0, &env
->fp_status
);
1697 if ((GET_FP_ENABLE(env
->fcr31
) | 0x20) & GET_FP_CAUSE(env
->fcr31
))
1698 CALL_FROM_TB1(do_raise_exception
, EXCP_FPE
);
1718 void op_dmfc1 (void)
1725 void op_dmtc1 (void)
1732 void op_mfhc1 (void)
1739 void op_mthc1 (void)
1747 Single precition routines have a "s" suffix, double precision a
1748 "d" suffix, 32bit integer "w", 64bit integer "l", paired singe "ps",
1749 paired single lowwer "pl", paired single upper "pu". */
1751 #define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void)
1755 set_float_exception_flags(0, &env
->fp_status
);
1756 FDT2
= float32_to_float64(FST0
, &env
->fp_status
);
1763 set_float_exception_flags(0, &env
->fp_status
);
1764 FDT2
= int32_to_float64(WT0
, &env
->fp_status
);
1771 set_float_exception_flags(0, &env
->fp_status
);
1772 FDT2
= int64_to_float64(DT0
, &env
->fp_status
);
1779 set_float_exception_flags(0, &env
->fp_status
);
1780 DT2
= float64_to_int64(FDT0
, &env
->fp_status
);
1782 if (GET_FP_CAUSE(env
->fcr31
) & (FP_OVERFLOW
| FP_INVALID
))
1783 DT2
= 0x7fffffffffffffffULL
;
1789 set_float_exception_flags(0, &env
->fp_status
);
1790 DT2
= float32_to_int64(FST0
, &env
->fp_status
);
1792 if (GET_FP_CAUSE(env
->fcr31
) & (FP_OVERFLOW
| FP_INVALID
))
1793 DT2
= 0x7fffffffffffffffULL
;
1806 set_float_exception_flags(0, &env
->fp_status
);
1807 FST2
= int32_to_float32(WT0
, &env
->fp_status
);
1808 FSTH2
= int32_to_float32(WTH0
, &env
->fp_status
);
1815 set_float_exception_flags(0, &env
->fp_status
);
1816 WT2
= float32_to_int32(FST0
, &env
->fp_status
);
1817 WTH2
= float32_to_int32(FSTH0
, &env
->fp_status
);
1819 if (GET_FP_CAUSE(env
->fcr31
) & (FP_OVERFLOW
| FP_INVALID
))
1826 set_float_exception_flags(0, &env
->fp_status
);
1827 FST2
= float64_to_float32(FDT0
, &env
->fp_status
);
1834 set_float_exception_flags(0, &env
->fp_status
);
1835 FST2
= int32_to_float32(WT0
, &env
->fp_status
);
1842 set_float_exception_flags(0, &env
->fp_status
);
1843 FST2
= int64_to_float32(DT0
, &env
->fp_status
);
1850 set_float_exception_flags(0, &env
->fp_status
);
1858 set_float_exception_flags(0, &env
->fp_status
);
1866 set_float_exception_flags(0, &env
->fp_status
);
1867 WT2
= float32_to_int32(FST0
, &env
->fp_status
);
1869 if (GET_FP_CAUSE(env
->fcr31
) & (FP_OVERFLOW
| FP_INVALID
))
1876 set_float_exception_flags(0, &env
->fp_status
);
1877 WT2
= float64_to_int32(FDT0
, &env
->fp_status
);
1879 if (GET_FP_CAUSE(env
->fcr31
) & (FP_OVERFLOW
| FP_INVALID
))
1887 DT2
= ((uint64_t)WT0
<< 32) | WT1
;
1893 DT2
= ((uint64_t)WT0
<< 32) | WTH1
;
1899 DT2
= ((uint64_t)WTH0
<< 32) | WT1
;
1905 DT2
= ((uint64_t)WTH0
<< 32) | WTH1
;
1912 set_float_rounding_mode(float_round_nearest_even
, &env
->fp_status
);
1913 DT2
= float64_round_to_int(FDT0
, &env
->fp_status
);
1914 RESTORE_ROUNDING_MODE
;
1916 if (GET_FP_CAUSE(env
->fcr31
) & (FP_OVERFLOW
| FP_INVALID
))
1917 DT2
= 0x7fffffffffffffffULL
;
1923 set_float_rounding_mode(float_round_nearest_even
, &env
->fp_status
);
1924 DT2
= float32_round_to_int(FST0
, &env
->fp_status
);
1925 RESTORE_ROUNDING_MODE
;
1927 if (GET_FP_CAUSE(env
->fcr31
) & (FP_OVERFLOW
| FP_INVALID
))
1928 DT2
= 0x7fffffffffffffffULL
;
1934 set_float_rounding_mode(float_round_nearest_even
, &env
->fp_status
);
1935 WT2
= float64_round_to_int(FDT0
, &env
->fp_status
);
1936 RESTORE_ROUNDING_MODE
;
1938 if (GET_FP_CAUSE(env
->fcr31
) & (FP_OVERFLOW
| FP_INVALID
))
1945 set_float_rounding_mode(float_round_nearest_even
, &env
->fp_status
);
1946 WT2
= float32_round_to_int(FST0
, &env
->fp_status
);
1947 RESTORE_ROUNDING_MODE
;
1949 if (GET_FP_CAUSE(env
->fcr31
) & (FP_OVERFLOW
| FP_INVALID
))
1957 DT2
= float64_to_int64_round_to_zero(FDT0
, &env
->fp_status
);
1959 if (GET_FP_CAUSE(env
->fcr31
) & (FP_OVERFLOW
| FP_INVALID
))
1960 DT2
= 0x7fffffffffffffffULL
;
1966 DT2
= float32_to_int64_round_to_zero(FST0
, &env
->fp_status
);
1968 if (GET_FP_CAUSE(env
->fcr31
) & (FP_OVERFLOW
| FP_INVALID
))
1969 DT2
= 0x7fffffffffffffffULL
;
1975 WT2
= float64_to_int32_round_to_zero(FDT0
, &env
->fp_status
);
1977 if (GET_FP_CAUSE(env
->fcr31
) & (FP_OVERFLOW
| FP_INVALID
))
1984 WT2
= float32_to_int32_round_to_zero(FST0
, &env
->fp_status
);
1986 if (GET_FP_CAUSE(env
->fcr31
) & (FP_OVERFLOW
| FP_INVALID
))
1994 set_float_rounding_mode(float_round_up
, &env
->fp_status
);
1995 DT2
= float64_round_to_int(FDT0
, &env
->fp_status
);
1996 RESTORE_ROUNDING_MODE
;
1998 if (GET_FP_CAUSE(env
->fcr31
) & (FP_OVERFLOW
| FP_INVALID
))
1999 DT2
= 0x7fffffffffffffffULL
;
2005 set_float_rounding_mode(float_round_up
, &env
->fp_status
);
2006 DT2
= float32_round_to_int(FST0
, &env
->fp_status
);
2007 RESTORE_ROUNDING_MODE
;
2009 if (GET_FP_CAUSE(env
->fcr31
) & (FP_OVERFLOW
| FP_INVALID
))
2010 DT2
= 0x7fffffffffffffffULL
;
2016 set_float_rounding_mode(float_round_up
, &env
->fp_status
);
2017 WT2
= float64_round_to_int(FDT0
, &env
->fp_status
);
2018 RESTORE_ROUNDING_MODE
;
2020 if (GET_FP_CAUSE(env
->fcr31
) & (FP_OVERFLOW
| FP_INVALID
))
2027 set_float_rounding_mode(float_round_up
, &env
->fp_status
);
2028 WT2
= float32_round_to_int(FST0
, &env
->fp_status
);
2029 RESTORE_ROUNDING_MODE
;
2031 if (GET_FP_CAUSE(env
->fcr31
) & (FP_OVERFLOW
| FP_INVALID
))
2039 set_float_rounding_mode(float_round_down
, &env
->fp_status
);
2040 DT2
= float64_round_to_int(FDT0
, &env
->fp_status
);
2041 RESTORE_ROUNDING_MODE
;
2043 if (GET_FP_CAUSE(env
->fcr31
) & (FP_OVERFLOW
| FP_INVALID
))
2044 DT2
= 0x7fffffffffffffffULL
;
2050 set_float_rounding_mode(float_round_down
, &env
->fp_status
);
2051 DT2
= float32_round_to_int(FST0
, &env
->fp_status
);
2052 RESTORE_ROUNDING_MODE
;
2054 if (GET_FP_CAUSE(env
->fcr31
) & (FP_OVERFLOW
| FP_INVALID
))
2055 DT2
= 0x7fffffffffffffffULL
;
2061 set_float_rounding_mode(float_round_down
, &env
->fp_status
);
2062 WT2
= float64_round_to_int(FDT0
, &env
->fp_status
);
2063 RESTORE_ROUNDING_MODE
;
2065 if (GET_FP_CAUSE(env
->fcr31
) & (FP_OVERFLOW
| FP_INVALID
))
2072 set_float_rounding_mode(float_round_down
, &env
->fp_status
);
2073 WT2
= float32_round_to_int(FST0
, &env
->fp_status
);
2074 RESTORE_ROUNDING_MODE
;
2076 if (GET_FP_CAUSE(env
->fcr31
) & (FP_OVERFLOW
| FP_INVALID
))
2084 if (!(env
->fcr31
& PARAM1
))
2091 if (!(env
->fcr31
& PARAM1
))
2098 if (!(env
->fcr31
& PARAM1
)) {
2107 if (env
->fcr31
& PARAM1
)
2114 if (env
->fcr31
& PARAM1
)
2121 if (env
->fcr31
& PARAM1
) {
2175 /* binary operations */
2176 #define FLOAT_BINOP(name) \
2179 set_float_exception_flags(0, &env->fp_status); \
2180 FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status); \
2182 DEBUG_FPU_STATE(); \
2187 set_float_exception_flags(0, &env->fp_status); \
2188 FST2 = float32_ ## name (FST0, FST1, &env->fp_status); \
2190 DEBUG_FPU_STATE(); \
2193 FLOAT_OP(name, ps) \
2195 set_float_exception_flags(0, &env->fp_status); \
2196 FST2 = float32_ ## name (FST0, FST1, &env->fp_status); \
2197 FSTH2 = float32_ ## name (FSTH0, FSTH1, &env->fp_status); \
2199 DEBUG_FPU_STATE(); \
2210 set_float_exception_flags(0, &env
->fp_status
);
2211 FST2
= float32_add (FST0
, FSTH0
, &env
->fp_status
);
2212 FSTH2
= float32_add (FST1
, FSTH1
, &env
->fp_status
);
2218 /* ternary operations */
2219 #define FLOAT_TERNOP(name1, name2) \
2220 FLOAT_OP(name1 ## name2, d) \
2222 FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fp_status); \
2223 FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fp_status); \
2224 DEBUG_FPU_STATE(); \
2227 FLOAT_OP(name1 ## name2, s) \
2229 FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \
2230 FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \
2231 DEBUG_FPU_STATE(); \
2234 FLOAT_OP(name1 ## name2, ps) \
2236 FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \
2237 FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fp_status); \
2238 FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \
2239 FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fp_status); \
2240 DEBUG_FPU_STATE(); \
2243 FLOAT_TERNOP(mul
, add
)
2244 FLOAT_TERNOP(mul
, sub
)
2247 /* negated ternary operations */
2248 #define FLOAT_NTERNOP(name1, name2) \
2249 FLOAT_OP(n ## name1 ## name2, d) \
2251 FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fp_status); \
2252 FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fp_status); \
2253 FDT2 ^= 1ULL << 63; \
2254 DEBUG_FPU_STATE(); \
2257 FLOAT_OP(n ## name1 ## name2, s) \
2259 FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \
2260 FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \
2262 DEBUG_FPU_STATE(); \
2265 FLOAT_OP(n ## name1 ## name2, ps) \
2267 FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \
2268 FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fp_status); \
2269 FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \
2270 FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fp_status); \
2273 DEBUG_FPU_STATE(); \
2276 FLOAT_NTERNOP(mul
, add
)
2277 FLOAT_NTERNOP(mul
, sub
)
2278 #undef FLOAT_NTERNOP
2280 /* unary operations, modifying fp status */
2281 #define FLOAT_UNOP(name) \
2284 FDT2 = float64_ ## name(FDT0, &env->fp_status); \
2285 DEBUG_FPU_STATE(); \
2290 FST2 = float32_ ## name(FST0, &env->fp_status); \
2291 DEBUG_FPU_STATE(); \
2294 FLOAT_OP(name, ps) \
2296 FST2 = float32_ ## name(FST0, &env->fp_status); \
2297 FSTH2 = float32_ ## name(FSTH0, &env->fp_status); \
2298 DEBUG_FPU_STATE(); \
2304 /* unary operations, not modifying fp status */
2305 #define FLOAT_UNOP(name) \
2308 FDT2 = float64_ ## name(FDT0); \
2309 DEBUG_FPU_STATE(); \
2314 FST2 = float32_ ## name(FST0); \
2315 DEBUG_FPU_STATE(); \
2318 FLOAT_OP(name, ps) \
2320 FST2 = float32_ ## name(FST0); \
2321 FSTH2 = float32_ ## name(FSTH0); \
2322 DEBUG_FPU_STATE(); \
2356 #ifdef TARGET_WORDS_BIGENDIAN
2364 default: /* unpredictable */
2371 #ifdef CONFIG_SOFTFLOAT
2372 #define clear_invalid() do { \
2373 int flags = get_float_exception_flags(&env->fp_status); \
2374 flags &= ~float_flag_invalid; \
2375 set_float_exception_flags(flags, &env->fp_status); \
2378 #define clear_invalid() do { } while(0)
2381 extern void dump_fpu_s(CPUState
*env
);
2383 #define FOP_COND_D(op, cond) \
2384 void op_cmp_d_ ## op (void) \
2389 SET_FP_COND(PARAM1, env); \
2391 CLEAR_FP_COND(PARAM1, env); \
2392 DEBUG_FPU_STATE(); \
2395 void op_cmpabs_d_ ## op (void) \
2398 FDT0 &= ~(1ULL << 63); \
2399 FDT1 &= ~(1ULL << 63); \
2403 SET_FP_COND(PARAM1, env); \
2405 CLEAR_FP_COND(PARAM1, env); \
2406 DEBUG_FPU_STATE(); \
2410 int float64_is_unordered(int sig
, float64 a
, float64 b STATUS_PARAM
)
2412 if (float64_is_signaling_nan(a
) ||
2413 float64_is_signaling_nan(b
) ||
2414 (sig
&& (float64_is_nan(a
) || float64_is_nan(b
)))) {
2415 float_raise(float_flag_invalid
, status
);
2417 } else if (float64_is_nan(a
) || float64_is_nan(b
)) {
2424 /* NOTE: the comma operator will make "cond" to eval to false,
2425 * but float*_is_unordered() is still called. */
2426 FOP_COND_D(f
, (float64_is_unordered(0, FDT1
, FDT0
, &env
->fp_status
), 0))
2427 FOP_COND_D(un
, float64_is_unordered(0, FDT1
, FDT0
, &env
->fp_status
))
2428 FOP_COND_D(eq
, !float64_is_unordered(0, FDT1
, FDT0
, &env
->fp_status
) && float64_eq(FDT0
, FDT1
, &env
->fp_status
))
2429 FOP_COND_D(ueq
, float64_is_unordered(0, FDT1
, FDT0
, &env
->fp_status
) || float64_eq(FDT0
, FDT1
, &env
->fp_status
))
2430 FOP_COND_D(olt
, !float64_is_unordered(0, FDT1
, FDT0
, &env
->fp_status
) && float64_lt(FDT0
, FDT1
, &env
->fp_status
))
2431 FOP_COND_D(ult
, float64_is_unordered(0, FDT1
, FDT0
, &env
->fp_status
) || float64_lt(FDT0
, FDT1
, &env
->fp_status
))
2432 FOP_COND_D(ole
, !float64_is_unordered(0, FDT1
, FDT0
, &env
->fp_status
) && float64_le(FDT0
, FDT1
, &env
->fp_status
))
2433 FOP_COND_D(ule
, float64_is_unordered(0, FDT1
, FDT0
, &env
->fp_status
) || float64_le(FDT0
, FDT1
, &env
->fp_status
))
2434 /* NOTE: the comma operator will make "cond" to eval to false,
2435 * but float*_is_unordered() is still called. */
2436 FOP_COND_D(sf
, (float64_is_unordered(1, FDT1
, FDT0
, &env
->fp_status
), 0))
2437 FOP_COND_D(ngle
,float64_is_unordered(1, FDT1
, FDT0
, &env
->fp_status
))
2438 FOP_COND_D(seq
, !float64_is_unordered(1, FDT1
, FDT0
, &env
->fp_status
) && float64_eq(FDT0
, FDT1
, &env
->fp_status
))
2439 FOP_COND_D(ngl
, float64_is_unordered(1, FDT1
, FDT0
, &env
->fp_status
) || float64_eq(FDT0
, FDT1
, &env
->fp_status
))
2440 FOP_COND_D(lt
, !float64_is_unordered(1, FDT1
, FDT0
, &env
->fp_status
) && float64_lt(FDT0
, FDT1
, &env
->fp_status
))
2441 FOP_COND_D(nge
, float64_is_unordered(1, FDT1
, FDT0
, &env
->fp_status
) || float64_lt(FDT0
, FDT1
, &env
->fp_status
))
2442 FOP_COND_D(le
, !float64_is_unordered(1, FDT1
, FDT0
, &env
->fp_status
) && float64_le(FDT0
, FDT1
, &env
->fp_status
))
2443 FOP_COND_D(ngt
, float64_is_unordered(1, FDT1
, FDT0
, &env
->fp_status
) || float64_le(FDT0
, FDT1
, &env
->fp_status
))
2445 #define FOP_COND_S(op, cond) \
2446 void op_cmp_s_ ## op (void) \
2451 SET_FP_COND(PARAM1, env); \
2453 CLEAR_FP_COND(PARAM1, env); \
2454 DEBUG_FPU_STATE(); \
2457 void op_cmpabs_s_ ## op (void) \
2460 FST0 &= ~(1 << 31); \
2461 FST1 &= ~(1 << 31); \
2465 SET_FP_COND(PARAM1, env); \
2467 CLEAR_FP_COND(PARAM1, env); \
2468 DEBUG_FPU_STATE(); \
2472 flag
float32_is_unordered(int sig
, float32 a
, float32 b STATUS_PARAM
)
2474 extern flag
float32_is_nan(float32 a
);
2475 if (float32_is_signaling_nan(a
) ||
2476 float32_is_signaling_nan(b
) ||
2477 (sig
&& (float32_is_nan(a
) || float32_is_nan(b
)))) {
2478 float_raise(float_flag_invalid
, status
);
2480 } else if (float32_is_nan(a
) || float32_is_nan(b
)) {
2487 /* NOTE: the comma operator will make "cond" to eval to false,
2488 * but float*_is_unordered() is still called. */
2489 FOP_COND_S(f
, (float32_is_unordered(0, FST1
, FST0
, &env
->fp_status
), 0))
2490 FOP_COND_S(un
, float32_is_unordered(0, FST1
, FST0
, &env
->fp_status
))
2491 FOP_COND_S(eq
, !float32_is_unordered(0, FST1
, FST0
, &env
->fp_status
) && float32_eq(FST0
, FST1
, &env
->fp_status
))
2492 FOP_COND_S(ueq
, float32_is_unordered(0, FST1
, FST0
, &env
->fp_status
) || float32_eq(FST0
, FST1
, &env
->fp_status
))
2493 FOP_COND_S(olt
, !float32_is_unordered(0, FST1
, FST0
, &env
->fp_status
) && float32_lt(FST0
, FST1
, &env
->fp_status
))
2494 FOP_COND_S(ult
, float32_is_unordered(0, FST1
, FST0
, &env
->fp_status
) || float32_lt(FST0
, FST1
, &env
->fp_status
))
2495 FOP_COND_S(ole
, !float32_is_unordered(0, FST1
, FST0
, &env
->fp_status
) && float32_le(FST0
, FST1
, &env
->fp_status
))
2496 FOP_COND_S(ule
, float32_is_unordered(0, FST1
, FST0
, &env
->fp_status
) || float32_le(FST0
, FST1
, &env
->fp_status
))
2497 /* NOTE: the comma operator will make "cond" to eval to false,
2498 * but float*_is_unordered() is still called. */
2499 FOP_COND_S(sf
, (float32_is_unordered(1, FST1
, FST0
, &env
->fp_status
), 0))
2500 FOP_COND_S(ngle
,float32_is_unordered(1, FST1
, FST0
, &env
->fp_status
))
2501 FOP_COND_S(seq
, !float32_is_unordered(1, FST1
, FST0
, &env
->fp_status
) && float32_eq(FST0
, FST1
, &env
->fp_status
))
2502 FOP_COND_S(ngl
, float32_is_unordered(1, FST1
, FST0
, &env
->fp_status
) || float32_eq(FST0
, FST1
, &env
->fp_status
))
2503 FOP_COND_S(lt
, !float32_is_unordered(1, FST1
, FST0
, &env
->fp_status
) && float32_lt(FST0
, FST1
, &env
->fp_status
))
2504 FOP_COND_S(nge
, float32_is_unordered(1, FST1
, FST0
, &env
->fp_status
) || float32_lt(FST0
, FST1
, &env
->fp_status
))
2505 FOP_COND_S(le
, !float32_is_unordered(1, FST1
, FST0
, &env
->fp_status
) && float32_le(FST0
, FST1
, &env
->fp_status
))
2506 FOP_COND_S(ngt
, float32_is_unordered(1, FST1
, FST0
, &env
->fp_status
) || float32_le(FST0
, FST1
, &env
->fp_status
))
2508 #define FOP_COND_PS(op, condl, condh) \
2509 void op_cmp_ps_ ## op (void) \
2515 SET_FP_COND(PARAM1, env); \
2517 CLEAR_FP_COND(PARAM1, env); \
2519 SET_FP_COND(PARAM1 + 1, env); \
2521 CLEAR_FP_COND(PARAM1 + 1, env); \
2522 DEBUG_FPU_STATE(); \
2525 void op_cmpabs_ps_ ## op (void) \
2528 FST0 &= ~(1 << 31); \
2529 FSTH0 &= ~(1 << 31); \
2530 FST1 &= ~(1 << 31); \
2531 FSTH1 &= ~(1 << 31); \
2536 SET_FP_COND(PARAM1, env); \
2538 CLEAR_FP_COND(PARAM1, env); \
2540 SET_FP_COND(PARAM1 + 1, env); \
2542 CLEAR_FP_COND(PARAM1 + 1, env); \
2543 DEBUG_FPU_STATE(); \
2547 /* NOTE: the comma operator will make "cond" to eval to false,
2548 * but float*_is_unordered() is still called. */
2549 FOP_COND_PS(f
, (float32_is_unordered(0, FST1
, FST0
, &env
->fp_status
), 0),
2550 (float32_is_unordered(0, FSTH1
, FSTH0
, &env
->fp_status
), 0))
2551 FOP_COND_PS(un
, float32_is_unordered(0, FST1
, FST0
, &env
->fp_status
),
2552 float32_is_unordered(0, FSTH1
, FSTH0
, &env
->fp_status
))
2553 FOP_COND_PS(eq
, !float32_is_unordered(0, FST1
, FST0
, &env
->fp_status
) && float32_eq(FST0
, FST1
, &env
->fp_status
),
2554 !float32_is_unordered(0, FSTH1
, FSTH0
, &env
->fp_status
) && float32_eq(FSTH0
, FSTH1
, &env
->fp_status
))
2555 FOP_COND_PS(ueq
, float32_is_unordered(0, FST1
, FST0
, &env
->fp_status
) || float32_eq(FST0
, FST1
, &env
->fp_status
),
2556 float32_is_unordered(0, FSTH1
, FSTH0
, &env
->fp_status
) || float32_eq(FSTH0
, FSTH1
, &env
->fp_status
))
2557 FOP_COND_PS(olt
, !float32_is_unordered(0, FST1
, FST0
, &env
->fp_status
) && float32_lt(FST0
, FST1
, &env
->fp_status
),
2558 !float32_is_unordered(0, FSTH1
, FSTH0
, &env
->fp_status
) && float32_lt(FSTH0
, FSTH1
, &env
->fp_status
))
2559 FOP_COND_PS(ult
, float32_is_unordered(0, FST1
, FST0
, &env
->fp_status
) || float32_lt(FST0
, FST1
, &env
->fp_status
),
2560 float32_is_unordered(0, FSTH1
, FSTH0
, &env
->fp_status
) || float32_lt(FSTH0
, FSTH1
, &env
->fp_status
))
2561 FOP_COND_PS(ole
, !float32_is_unordered(0, FST1
, FST0
, &env
->fp_status
) && float32_le(FST0
, FST1
, &env
->fp_status
),
2562 !float32_is_unordered(0, FSTH1
, FSTH0
, &env
->fp_status
) && float32_le(FSTH0
, FSTH1
, &env
->fp_status
))
2563 FOP_COND_PS(ule
, float32_is_unordered(0, FST1
, FST0
, &env
->fp_status
) || float32_le(FST0
, FST1
, &env
->fp_status
),
2564 float32_is_unordered(0, FSTH1
, FSTH0
, &env
->fp_status
) || float32_le(FSTH0
, FSTH1
, &env
->fp_status
))
2565 /* NOTE: the comma operator will make "cond" to eval to false,
2566 * but float*_is_unordered() is still called. */
2567 FOP_COND_PS(sf
, (float32_is_unordered(1, FST1
, FST0
, &env
->fp_status
), 0),
2568 (float32_is_unordered(1, FSTH1
, FSTH0
, &env
->fp_status
), 0))
2569 FOP_COND_PS(ngle
,float32_is_unordered(1, FST1
, FST0
, &env
->fp_status
),
2570 float32_is_unordered(1, FSTH1
, FSTH0
, &env
->fp_status
))
2571 FOP_COND_PS(seq
, !float32_is_unordered(1, FST1
, FST0
, &env
->fp_status
) && float32_eq(FST0
, FST1
, &env
->fp_status
),
2572 !float32_is_unordered(1, FSTH1
, FSTH0
, &env
->fp_status
) && float32_eq(FSTH0
, FSTH1
, &env
->fp_status
))
2573 FOP_COND_PS(ngl
, float32_is_unordered(1, FST1
, FST0
, &env
->fp_status
) || float32_eq(FST0
, FST1
, &env
->fp_status
),
2574 float32_is_unordered(1, FSTH1
, FSTH0
, &env
->fp_status
) || float32_eq(FSTH0
, FSTH1
, &env
->fp_status
))
2575 FOP_COND_PS(lt
, !float32_is_unordered(1, FST1
, FST0
, &env
->fp_status
) && float32_lt(FST0
, FST1
, &env
->fp_status
),
2576 !float32_is_unordered(1, FSTH1
, FSTH0
, &env
->fp_status
) && float32_lt(FSTH0
, FSTH1
, &env
->fp_status
))
2577 FOP_COND_PS(nge
, float32_is_unordered(1, FST1
, FST0
, &env
->fp_status
) || float32_lt(FST0
, FST1
, &env
->fp_status
),
2578 float32_is_unordered(1, FSTH1
, FSTH0
, &env
->fp_status
) || float32_lt(FSTH0
, FSTH1
, &env
->fp_status
))
2579 FOP_COND_PS(le
, !float32_is_unordered(1, FST1
, FST0
, &env
->fp_status
) && float32_le(FST0
, FST1
, &env
->fp_status
),
2580 !float32_is_unordered(1, FSTH1
, FSTH0
, &env
->fp_status
) && float32_le(FSTH0
, FSTH1
, &env
->fp_status
))
2581 FOP_COND_PS(ngt
, float32_is_unordered(1, FST1
, FST0
, &env
->fp_status
) || float32_le(FST0
, FST1
, &env
->fp_status
),
2582 float32_is_unordered(1, FSTH1
, FSTH0
, &env
->fp_status
) || float32_le(FSTH0
, FSTH1
, &env
->fp_status
))
2586 T0
= !IS_FP_COND_SET(PARAM1
, env
);
2590 void op_bc1fany2 (void)
2592 T0
= (!IS_FP_COND_SET(PARAM1
, env
) ||
2593 !IS_FP_COND_SET(PARAM1
+ 1, env
));
2597 void op_bc1fany4 (void)
2599 T0
= (!IS_FP_COND_SET(PARAM1
, env
) ||
2600 !IS_FP_COND_SET(PARAM1
+ 1, env
) ||
2601 !IS_FP_COND_SET(PARAM1
+ 2, env
) ||
2602 !IS_FP_COND_SET(PARAM1
+ 3, env
));
2609 T0
= IS_FP_COND_SET(PARAM1
, env
);
2613 void op_bc1tany2 (void)
2615 T0
= (IS_FP_COND_SET(PARAM1
, env
) ||
2616 IS_FP_COND_SET(PARAM1
+ 1, env
));
2620 void op_bc1tany4 (void)
2622 T0
= (IS_FP_COND_SET(PARAM1
, env
) ||
2623 IS_FP_COND_SET(PARAM1
+ 1, env
) ||
2624 IS_FP_COND_SET(PARAM1
+ 2, env
) ||
2625 IS_FP_COND_SET(PARAM1
+ 3, env
));
2630 void op_tlbwi (void)
2632 CALL_FROM_TB0(env
->do_tlbwi
);
2636 void op_tlbwr (void)
2638 CALL_FROM_TB0(env
->do_tlbwr
);
2644 CALL_FROM_TB0(env
->do_tlbp
);
2650 CALL_FROM_TB0(env
->do_tlbr
);
2655 #if defined (CONFIG_USER_ONLY)
2656 void op_tls_value (void)
2658 T0
= env
->tls_value
;
2664 CALL_FROM_TB1(do_pmon
, PARAM1
);
2670 T0
= env
->CP0_Status
;
2671 env
->CP0_Status
= T0
& ~(1 << CP0St_IE
);
2672 CALL_FROM_TB1(cpu_mips_update_irq
, env
);
2678 T0
= env
->CP0_Status
;
2679 env
->CP0_Status
= T0
| (1 << CP0St_IE
);
2680 CALL_FROM_TB1(cpu_mips_update_irq
, env
);
2687 CALL_FROM_TB1(do_raise_exception
, EXCP_TRAP
);
2692 void op_debug (void)
2694 CALL_FROM_TB1(do_raise_exception
, EXCP_DEBUG
);
2698 void op_set_lladdr (void)
2700 env
->CP0_LLAddr
= T2
;
2704 void debug_pre_eret (void);
2705 void debug_post_eret (void);
2708 if (loglevel
& CPU_LOG_EXEC
)
2709 CALL_FROM_TB0(debug_pre_eret
);
2710 if (env
->CP0_Status
& (1 << CP0St_ERL
)) {
2711 env
->PC
= env
->CP0_ErrorEPC
;
2712 env
->CP0_Status
&= ~(1 << CP0St_ERL
);
2714 env
->PC
= env
->CP0_EPC
;
2715 env
->CP0_Status
&= ~(1 << CP0St_EXL
);
2717 if (!(env
->CP0_Status
& (1 << CP0St_EXL
)) &&
2718 !(env
->CP0_Status
& (1 << CP0St_ERL
)) &&
2719 !(env
->hflags
& MIPS_HFLAG_DM
) &&
2720 (env
->CP0_Status
& (1 << CP0St_UM
)))
2721 env
->hflags
|= MIPS_HFLAG_UM
;
2722 if (loglevel
& CPU_LOG_EXEC
)
2723 CALL_FROM_TB0(debug_post_eret
);
2724 env
->CP0_LLAddr
= 1;
2728 void op_deret (void)
2730 if (loglevel
& CPU_LOG_EXEC
)
2731 CALL_FROM_TB0(debug_pre_eret
);
2732 env
->PC
= env
->CP0_DEPC
;
2733 env
->hflags
|= MIPS_HFLAG_DM
;
2734 if (!(env
->CP0_Status
& (1 << CP0St_EXL
)) &&
2735 !(env
->CP0_Status
& (1 << CP0St_ERL
)) &&
2736 !(env
->hflags
& MIPS_HFLAG_DM
) &&
2737 (env
->CP0_Status
& (1 << CP0St_UM
)))
2738 env
->hflags
|= MIPS_HFLAG_UM
;
2739 if (loglevel
& CPU_LOG_EXEC
)
2740 CALL_FROM_TB0(debug_post_eret
);
2741 env
->CP0_LLAddr
= 1;
2745 void op_rdhwr_cpunum(void)
2747 if (!(env
->hflags
& MIPS_HFLAG_UM
) ||
2748 (env
->CP0_HWREna
& (1 << 0)) ||
2749 (env
->CP0_Status
& (1 << CP0St_CU0
)))
2750 T0
= env
->CP0_EBase
& 0x3ff;
2752 CALL_FROM_TB1(do_raise_exception
, EXCP_RI
);
2756 void op_rdhwr_synci_step(void)
2758 if (!(env
->hflags
& MIPS_HFLAG_UM
) ||
2759 (env
->CP0_HWREna
& (1 << 1)) ||
2760 (env
->CP0_Status
& (1 << CP0St_CU0
)))
2761 T0
= env
->SYNCI_Step
;
2763 CALL_FROM_TB1(do_raise_exception
, EXCP_RI
);
2767 void op_rdhwr_cc(void)
2769 if (!(env
->hflags
& MIPS_HFLAG_UM
) ||
2770 (env
->CP0_HWREna
& (1 << 2)) ||
2771 (env
->CP0_Status
& (1 << CP0St_CU0
)))
2772 T0
= env
->CP0_Count
;
2774 CALL_FROM_TB1(do_raise_exception
, EXCP_RI
);
2778 void op_rdhwr_ccres(void)
2780 if (!(env
->hflags
& MIPS_HFLAG_UM
) ||
2781 (env
->CP0_HWREna
& (1 << 3)) ||
2782 (env
->CP0_Status
& (1 << CP0St_CU0
)))
2785 CALL_FROM_TB1(do_raise_exception
, EXCP_RI
);
2789 void op_save_state (void)
2791 env
->hflags
= PARAM1
;
2795 void op_save_pc (void)
2801 void op_save_fp_status (void)
2808 env
->fp_status
= fps
.f
;
2812 void op_interrupt_restart (void)
2814 if (!(env
->CP0_Status
& (1 << CP0St_EXL
)) &&
2815 !(env
->CP0_Status
& (1 << CP0St_ERL
)) &&
2816 !(env
->hflags
& MIPS_HFLAG_DM
) &&
2817 (env
->CP0_Status
& (1 << CP0St_IE
)) &&
2818 (env
->CP0_Status
& env
->CP0_Cause
& CP0Ca_IP_mask
)) {
2819 env
->CP0_Cause
&= ~(0x1f << CP0Ca_EC
);
2820 CALL_FROM_TB1(do_raise_exception
, EXCP_EXT_INTERRUPT
);
2825 void op_raise_exception (void)
2827 CALL_FROM_TB1(do_raise_exception
, PARAM1
);
2831 void op_raise_exception_err (void)
2833 CALL_FROM_TB2(do_raise_exception_err
, PARAM1
, PARAM2
);
2837 void op_exit_tb (void)
2846 CALL_FROM_TB1(do_raise_exception
, EXCP_HLT
);
2850 /* Bitfield operations. */
2853 unsigned int pos
= PARAM1
;
2854 unsigned int size
= PARAM2
;
2856 T0
= ((uint32_t)T1
>> pos
) & ((size
< 32) ? ((1 << size
) - 1) : ~0);
2862 unsigned int pos
= PARAM1
;
2863 unsigned int size
= PARAM2
;
2864 target_ulong mask
= ((size
< 32) ? ((1 << size
) - 1) : ~0) << pos
;
2866 T0
= (T0
& ~mask
) | (((uint32_t)T1
<< pos
) & mask
);
2872 T0
= ((T1
<< 8) & ~0x00FF00FF) | ((T1
>> 8) & 0x00FF00FF);
2876 #ifdef TARGET_MIPS64
2879 unsigned int pos
= PARAM1
;
2880 unsigned int size
= PARAM2
;
2882 T0
= (T1
>> pos
) & ((size
< 32) ? ((1 << size
) - 1) : ~0);
2888 unsigned int pos
= PARAM1
;
2889 unsigned int size
= PARAM2
;
2890 target_ulong mask
= ((size
< 32) ? ((1 << size
) - 1) : ~0) << pos
;
2892 T0
= (T0
& ~mask
) | ((T1
<< pos
) & mask
);
2898 T0
= ((T1
<< 8) & ~0x00FF00FF00FF00FFULL
) | ((T1
>> 8) & 0x00FF00FF00FF00FFULL
);
2904 T0
= ((T1
<< 16) & ~0x0000FFFF0000FFFFULL
) | ((T1
>> 16) & 0x0000FFFF0000FFFFULL
);
2911 T0
= ((T1
& 0xFF) ^ 0x80) - 0x80;
2917 T0
= ((T1
& 0xFFFF) ^ 0x8000) - 0x8000;