2 * MIPS emulation micro-operations for qemu.
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)
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.
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.
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
25 #include "host-utils.h"
28 #define CALL_FROM_TB0(func) func()
31 #define CALL_FROM_TB1(func, arg0) func(arg0)
33 #ifndef CALL_FROM_TB1_CONST16
34 #define CALL_FROM_TB1_CONST16(func, arg0) CALL_FROM_TB1(func, arg0)
37 #define CALL_FROM_TB2(func, arg0, arg1) func(arg0, arg1)
39 #ifndef CALL_FROM_TB2_CONST16
40 #define CALL_FROM_TB2_CONST16(func, arg0, arg1) \
41 CALL_FROM_TB2(func, arg0, arg1)
44 #define CALL_FROM_TB3(func, arg0, arg1, arg2) func(arg0, arg1, arg2)
47 #define CALL_FROM_TB4(func, arg0, arg1, arg2, arg3) \
48 func(arg0, arg1, arg2, arg3)
52 #include "op_template.c"
55 #include "op_template.c"
58 #include "op_template.c"
61 #include "op_template.c"
64 #include "op_template.c"
67 #include "op_template.c"
70 #include "op_template.c"
73 #include "op_template.c"
76 #include "op_template.c"
79 #include "op_template.c"
82 #include "op_template.c"
85 #include "op_template.c"
88 #include "op_template.c"
91 #include "op_template.c"
94 #include "op_template.c"
97 #include "op_template.c"
100 #include "op_template.c"
103 #include "op_template.c"
106 #include "op_template.c"
109 #include "op_template.c"
112 #include "op_template.c"
115 #include "op_template.c"
118 #include "op_template.c"
121 #include "op_template.c"
124 #include "op_template.c"
127 #include "op_template.c"
130 #include "op_template.c"
133 #include "op_template.c"
136 #include "op_template.c"
139 #include "op_template.c"
142 #include "op_template.c"
146 #include "op_template.c"
150 #include "fop_template.c"
153 #include "fop_template.c"
156 #include "fop_template.c"
159 #include "fop_template.c"
162 #include "fop_template.c"
165 #include "fop_template.c"
168 #include "fop_template.c"
171 #include "fop_template.c"
174 #include "fop_template.c"
177 #include "fop_template.c"
180 #include "fop_template.c"
183 #include "fop_template.c"
186 #include "fop_template.c"
189 #include "fop_template.c"
192 #include "fop_template.c"
195 #include "fop_template.c"
198 #include "fop_template.c"
201 #include "fop_template.c"
204 #include "fop_template.c"
207 #include "fop_template.c"
210 #include "fop_template.c"
213 #include "fop_template.c"
216 #include "fop_template.c"
219 #include "fop_template.c"
222 #include "fop_template.c"
225 #include "fop_template.c"
228 #include "fop_template.c"
231 #include "fop_template.c"
234 #include "fop_template.c"
237 #include "fop_template.c"
240 #include "fop_template.c"
243 #include "fop_template.c"
247 #include "fop_template.c"
251 #define MEMSUFFIX _raw
254 #if !defined(CONFIG_USER_ONLY)
255 #define MEMSUFFIX _user
259 #define MEMSUFFIX _super
263 #define MEMSUFFIX _kernel
268 /* Addresses computation */
269 void op_addr_add (void)
271 /* For compatibility with 32-bit code, data reference in user mode
272 with Status_UX = 0 should be casted to 32-bit and sign extended.
273 See the MIPS64 PRA manual, section 4.10. */
274 #if defined(TARGET_MIPS64)
275 if (((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
276 !(env->CP0_Status & (1 << CP0St_UX)))
277 T0 = (int64_t)(int32_t)(T0 + T1);
287 T0 = (int32_t)((int32_t)T0 + (int32_t)T1);
296 T0 = (int32_t)T0 + (int32_t)T1;
297 if (((tmp ^ T1 ^ (-1)) & (T0 ^ T1)) >> 31) {
298 /* operands of same sign, result different sign */
299 CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
307 T0 = (int32_t)((int32_t)T0 - (int32_t)T1);
316 T0 = (int32_t)T0 - (int32_t)T1;
317 if (((tmp ^ T1) & (tmp ^ T0)) >> 31) {
318 /* operands of different sign, first operand and result different sign */
319 CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
327 T0 = (int32_t)((int32_t)T0 * (int32_t)T1);
331 #if HOST_LONG_BITS < 64
334 CALL_FROM_TB0(do_div);
341 env->LO[env->current_tc][0] = (int32_t)((int64_t)(int32_t)T0 / (int32_t)T1);
342 env->HI[env->current_tc][0] = (int32_t)((int64_t)(int32_t)T0 % (int32_t)T1);
351 env->LO[env->current_tc][0] = (int32_t)((uint32_t)T0 / (uint32_t)T1);
352 env->HI[env->current_tc][0] = (int32_t)((uint32_t)T0 % (uint32_t)T1);
357 #if defined(TARGET_MIPS64)
371 if (((tmp ^ T1 ^ (-1)) & (T0 ^ T1)) >> 63) {
372 /* operands of same sign, result different sign */
373 CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
389 T0 = (int64_t)T0 - (int64_t)T1;
390 if (((tmp ^ T1) & (tmp ^ T0)) >> 63) {
391 /* operands of different sign, first operand and result different sign */
392 CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
399 T0 = (int64_t)T0 * (int64_t)T1;
403 /* Those might call libgcc functions. */
410 #if TARGET_LONG_BITS > HOST_LONG_BITS
420 env->LO[env->current_tc][0] = T0 / T1;
421 env->HI[env->current_tc][0] = T0 % T1;
426 #endif /* TARGET_MIPS64 */
455 T0 = (int32_t)((uint32_t)T0 << T1);
461 T0 = (int32_t)((int32_t)T0 >> T1);
467 T0 = (int32_t)((uint32_t)T0 >> T1);
476 tmp = (int32_t)((uint32_t)T0 << (0x20 - T1));
477 T0 = (int32_t)((uint32_t)T0 >> T1) | tmp;
484 T0 = (int32_t)((uint32_t)T1 << ((uint32_t)T0 & 0x1F));
490 T0 = (int32_t)((int32_t)T1 >> (T0 & 0x1F));
496 T0 = (int32_t)((uint32_t)T1 >> (T0 & 0x1F));
506 tmp = (int32_t)((uint32_t)T1 << (0x20 - T0));
507 T0 = (int32_t)((uint32_t)T1 >> T0) | tmp;
525 #if defined(TARGET_MIPS64)
527 #if TARGET_LONG_BITS > HOST_LONG_BITS
528 /* Those might call libgcc functions. */
531 CALL_FROM_TB0(do_dsll);
535 void op_dsll32 (void)
537 CALL_FROM_TB0(do_dsll32);
543 CALL_FROM_TB0(do_dsra);
547 void op_dsra32 (void)
549 CALL_FROM_TB0(do_dsra32);
555 CALL_FROM_TB0(do_dsrl);
559 void op_dsrl32 (void)
561 CALL_FROM_TB0(do_dsrl32);
567 CALL_FROM_TB0(do_drotr);
571 void op_drotr32 (void)
573 CALL_FROM_TB0(do_drotr32);
579 CALL_FROM_TB0(do_dsllv);
585 CALL_FROM_TB0(do_dsrav);
591 CALL_FROM_TB0(do_dsrlv);
595 void op_drotrv (void)
597 CALL_FROM_TB0(do_drotrv);
603 CALL_FROM_TB0(do_dclo);
609 CALL_FROM_TB0(do_dclz);
613 #else /* TARGET_LONG_BITS > HOST_LONG_BITS */
621 void op_dsll32 (void)
623 T0 = T0 << (T1 + 32);
629 T0 = (int64_t)T0 >> T1;
633 void op_dsra32 (void)
635 T0 = (int64_t)T0 >> (T1 + 32);
645 void op_dsrl32 (void)
647 T0 = T0 >> (T1 + 32);
656 tmp = T0 << (0x40 - T1);
657 T0 = (T0 >> T1) | tmp;
662 void op_drotr32 (void)
666 tmp = T0 << (0x40 - (32 + T1));
667 T0 = (T0 >> (32 + T1)) | tmp;
673 T0 = T1 << (T0 & 0x3F);
679 T0 = (int64_t)T1 >> (T0 & 0x3F);
685 T0 = T1 >> (T0 & 0x3F);
689 void op_drotrv (void)
695 tmp = T1 << (0x40 - T0);
696 T0 = (T1 >> T0) | tmp;
713 #endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
714 #endif /* TARGET_MIPS64 */
716 /* 64 bits arithmetic */
717 #if TARGET_LONG_BITS > HOST_LONG_BITS
720 CALL_FROM_TB0(do_mult);
726 CALL_FROM_TB0(do_multu);
732 CALL_FROM_TB0(do_madd);
738 CALL_FROM_TB0(do_maddu);
744 CALL_FROM_TB0(do_msub);
750 CALL_FROM_TB0(do_msubu);
754 /* Multiplication variants of the vr54xx. */
757 CALL_FROM_TB0(do_muls);
763 CALL_FROM_TB0(do_mulsu);
769 CALL_FROM_TB0(do_macc);
773 void op_macchi (void)
775 CALL_FROM_TB0(do_macchi);
781 CALL_FROM_TB0(do_maccu);
784 void op_macchiu (void)
786 CALL_FROM_TB0(do_macchiu);
792 CALL_FROM_TB0(do_msac);
796 void op_msachi (void)
798 CALL_FROM_TB0(do_msachi);
804 CALL_FROM_TB0(do_msacu);
808 void op_msachiu (void)
810 CALL_FROM_TB0(do_msachiu);
816 CALL_FROM_TB0(do_mulhi);
820 void op_mulhiu (void)
822 CALL_FROM_TB0(do_mulhiu);
826 void op_mulshi (void)
828 CALL_FROM_TB0(do_mulshi);
832 void op_mulshiu (void)
834 CALL_FROM_TB0(do_mulshiu);
838 #else /* TARGET_LONG_BITS > HOST_LONG_BITS */
840 static always_inline uint64_t get_HILO (void)
842 return ((uint64_t)env->HI[env->current_tc][0] << 32) |
843 ((uint64_t)(uint32_t)env->LO[env->current_tc][0]);
846 static always_inline void set_HILO (uint64_t HILO)
848 env->LO[env->current_tc][0] = (int32_t)(HILO & 0xFFFFFFFF);
849 env->HI[env->current_tc][0] = (int32_t)(HILO >> 32);
852 static always_inline void set_HIT0_LO (uint64_t HILO)
854 env->LO[env->current_tc][0] = (int32_t)(HILO & 0xFFFFFFFF);
855 T0 = env->HI[env->current_tc][0] = (int32_t)(HILO >> 32);
858 static always_inline void set_HI_LOT0 (uint64_t HILO)
860 T0 = env->LO[env->current_tc][0] = (int32_t)(HILO & 0xFFFFFFFF);
861 env->HI[env->current_tc][0] = (int32_t)(HILO >> 32);
866 set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
872 set_HILO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
880 tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
881 set_HILO((int64_t)get_HILO() + tmp);
889 tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
890 set_HILO(get_HILO() + tmp);
898 tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
899 set_HILO((int64_t)get_HILO() - tmp);
907 tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
908 set_HILO(get_HILO() - tmp);
912 /* Multiplication variants of the vr54xx. */
915 set_HI_LOT0(0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
921 set_HI_LOT0(0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
927 set_HI_LOT0(get_HILO() + ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
931 void op_macchi (void)
933 set_HIT0_LO(get_HILO() + ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
939 set_HI_LOT0(get_HILO() + ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
943 void op_macchiu (void)
945 set_HIT0_LO(get_HILO() + ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
951 set_HI_LOT0(get_HILO() - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
955 void op_msachi (void)
957 set_HIT0_LO(get_HILO() - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
963 set_HI_LOT0(get_HILO() - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
967 void op_msachiu (void)
969 set_HIT0_LO(get_HILO() - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
975 set_HIT0_LO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
979 void op_mulhiu (void)
981 set_HIT0_LO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
985 void op_mulshi (void)
987 set_HIT0_LO(0 - ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1));
991 void op_mulshiu (void)
993 set_HIT0_LO(0 - ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1));
997 #endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
999 #if defined(TARGET_MIPS64)
1000 void op_dmult (void)
1002 CALL_FROM_TB4(muls64, &(env->LO[env->current_tc][0]), &(env->HI[env->current_tc][0]), T0, T1);
1006 void op_dmultu (void)
1008 CALL_FROM_TB4(mulu64, &(env->LO[env->current_tc][0]), &(env->HI[env->current_tc][0]), T0, T1);
1013 /* Conditional moves */
1017 env->gpr[env->current_tc][PARAM1] = T0;
1024 env->gpr[env->current_tc][PARAM1] = T0;
1030 if (!(env->fpu->fcr31 & PARAM1))
1037 if (env->fpu->fcr31 & PARAM1)
1043 #define OP_COND(name, cond) \
1044 void glue(op_, name) (void) \
1054 OP_COND(eq, T0 == T1);
1055 OP_COND(ne, T0 != T1);
1056 OP_COND(ge, (target_long)T0 >= (target_long)T1);
1057 OP_COND(geu, T0 >= T1);
1058 OP_COND(lt, (target_long)T0 < (target_long)T1);
1059 OP_COND(ltu, T0 < T1);
1060 OP_COND(gez, (target_long)T0 >= 0);
1061 OP_COND(gtz, (target_long)T0 > 0);
1062 OP_COND(lez, (target_long)T0 <= 0);
1063 OP_COND(ltz, (target_long)T0 < 0);
1066 /* Branch to register */
1067 void op_save_breg_target (void)
1075 env->PC[env->current_tc] = env->btarget;
1079 void op_save_btarget (void)
1081 env->btarget = PARAM1;
1085 #if defined(TARGET_MIPS64)
1086 void op_save_btarget64 (void)
1088 env->btarget = ((uint64_t)PARAM1 << 32) | (uint32_t)PARAM2;
1093 /* Conditional branch */
1094 void op_set_bcond (void)
1100 void op_jnz_bcond (void)
1103 GOTO_LABEL_PARAM(1);
1108 void op_mfc0_index (void)
1110 T0 = env->CP0_Index;
1114 void op_mfc0_mvpcontrol (void)
1116 T0 = env->mvp->CP0_MVPControl;
1120 void op_mfc0_mvpconf0 (void)
1122 T0 = env->mvp->CP0_MVPConf0;
1126 void op_mfc0_mvpconf1 (void)
1128 T0 = env->mvp->CP0_MVPConf1;
1132 void op_mfc0_random (void)
1134 CALL_FROM_TB0(do_mfc0_random);
1138 void op_mfc0_vpecontrol (void)
1140 T0 = env->CP0_VPEControl;
1144 void op_mfc0_vpeconf0 (void)
1146 T0 = env->CP0_VPEConf0;
1150 void op_mfc0_vpeconf1 (void)
1152 T0 = env->CP0_VPEConf1;
1156 void op_mfc0_yqmask (void)
1158 T0 = env->CP0_YQMask;
1162 void op_mfc0_vpeschedule (void)
1164 T0 = env->CP0_VPESchedule;
1168 void op_mfc0_vpeschefback (void)
1170 T0 = env->CP0_VPEScheFBack;
1174 void op_mfc0_vpeopt (void)
1176 T0 = env->CP0_VPEOpt;
1180 void op_mfc0_entrylo0 (void)
1182 T0 = (int32_t)env->CP0_EntryLo0;
1186 void op_mfc0_tcstatus (void)
1188 T0 = env->CP0_TCStatus[env->current_tc];
1192 void op_mftc0_tcstatus(void)
1194 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1196 T0 = env->CP0_TCStatus[other_tc];
1200 void op_mfc0_tcbind (void)
1202 T0 = env->CP0_TCBind[env->current_tc];
1206 void op_mftc0_tcbind(void)
1208 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1210 T0 = env->CP0_TCBind[other_tc];
1214 void op_mfc0_tcrestart (void)
1216 T0 = env->PC[env->current_tc];
1220 void op_mftc0_tcrestart(void)
1222 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1224 T0 = env->PC[other_tc];
1228 void op_mfc0_tchalt (void)
1230 T0 = env->CP0_TCHalt[env->current_tc];
1234 void op_mftc0_tchalt(void)
1236 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1238 T0 = env->CP0_TCHalt[other_tc];
1242 void op_mfc0_tccontext (void)
1244 T0 = env->CP0_TCContext[env->current_tc];
1248 void op_mftc0_tccontext(void)
1250 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1252 T0 = env->CP0_TCContext[other_tc];
1256 void op_mfc0_tcschedule (void)
1258 T0 = env->CP0_TCSchedule[env->current_tc];
1262 void op_mftc0_tcschedule(void)
1264 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1266 T0 = env->CP0_TCSchedule[other_tc];
1270 void op_mfc0_tcschefback (void)
1272 T0 = env->CP0_TCScheFBack[env->current_tc];
1276 void op_mftc0_tcschefback(void)
1278 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1280 T0 = env->CP0_TCScheFBack[other_tc];
1284 void op_mfc0_entrylo1 (void)
1286 T0 = (int32_t)env->CP0_EntryLo1;
1290 void op_mfc0_context (void)
1292 T0 = (int32_t)env->CP0_Context;
1296 void op_mfc0_pagemask (void)
1298 T0 = env->CP0_PageMask;
1302 void op_mfc0_pagegrain (void)
1304 T0 = env->CP0_PageGrain;
1308 void op_mfc0_wired (void)
1310 T0 = env->CP0_Wired;
1314 void op_mfc0_srsconf0 (void)
1316 T0 = env->CP0_SRSConf0;
1320 void op_mfc0_srsconf1 (void)
1322 T0 = env->CP0_SRSConf1;
1326 void op_mfc0_srsconf2 (void)
1328 T0 = env->CP0_SRSConf2;
1332 void op_mfc0_srsconf3 (void)
1334 T0 = env->CP0_SRSConf3;
1338 void op_mfc0_srsconf4 (void)
1340 T0 = env->CP0_SRSConf4;
1344 void op_mfc0_hwrena (void)
1346 T0 = env->CP0_HWREna;
1350 void op_mfc0_badvaddr (void)
1352 T0 = (int32_t)env->CP0_BadVAddr;
1356 void op_mfc0_count (void)
1358 CALL_FROM_TB0(do_mfc0_count);
1362 void op_mfc0_entryhi (void)
1364 T0 = (int32_t)env->CP0_EntryHi;
1368 void op_mftc0_entryhi(void)
1370 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1372 T0 = (env->CP0_EntryHi & ~0xff) | (env->CP0_TCStatus[other_tc] & 0xff);
1376 void op_mfc0_compare (void)
1378 T0 = env->CP0_Compare;
1382 void op_mfc0_status (void)
1384 T0 = env->CP0_Status;
1388 void op_mftc0_status(void)
1390 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1391 uint32_t tcstatus = env->CP0_TCStatus[other_tc];
1393 T0 = env->CP0_Status & ~0xf1000018;
1394 T0 |= tcstatus & (0xf << CP0TCSt_TCU0);
1395 T0 |= (tcstatus & (1 << CP0TCSt_TMX)) >> (CP0TCSt_TMX - CP0St_MX);
1396 T0 |= (tcstatus & (0x3 << CP0TCSt_TKSU)) >> (CP0TCSt_TKSU - CP0St_KSU);
1400 void op_mfc0_intctl (void)
1402 T0 = env->CP0_IntCtl;
1406 void op_mfc0_srsctl (void)
1408 T0 = env->CP0_SRSCtl;
1412 void op_mfc0_srsmap (void)
1414 T0 = env->CP0_SRSMap;
1418 void op_mfc0_cause (void)
1420 T0 = env->CP0_Cause;
1424 void op_mfc0_epc (void)
1426 T0 = (int32_t)env->CP0_EPC;
1430 void op_mfc0_prid (void)
1436 void op_mfc0_ebase (void)
1438 T0 = env->CP0_EBase;
1442 void op_mfc0_config0 (void)
1444 T0 = env->CP0_Config0;
1448 void op_mfc0_config1 (void)
1450 T0 = env->CP0_Config1;
1454 void op_mfc0_config2 (void)
1456 T0 = env->CP0_Config2;
1460 void op_mfc0_config3 (void)
1462 T0 = env->CP0_Config3;
1466 void op_mfc0_config6 (void)
1468 T0 = env->CP0_Config6;
1472 void op_mfc0_config7 (void)
1474 T0 = env->CP0_Config7;
1478 void op_mfc0_lladdr (void)
1480 T0 = (int32_t)env->CP0_LLAddr >> 4;
1484 void op_mfc0_watchlo (void)
1486 T0 = (int32_t)env->CP0_WatchLo[PARAM1];
1490 void op_mfc0_watchhi (void)
1492 T0 = env->CP0_WatchHi[PARAM1];
1496 void op_mfc0_xcontext (void)
1498 T0 = (int32_t)env->CP0_XContext;
1502 void op_mfc0_framemask (void)
1504 T0 = env->CP0_Framemask;
1508 void op_mfc0_debug (void)
1510 T0 = env->CP0_Debug;
1511 if (env->hflags & MIPS_HFLAG_DM)
1512 T0 |= 1 << CP0DB_DM;
1516 void op_mftc0_debug(void)
1518 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1520 /* XXX: Might be wrong, check with EJTAG spec. */
1521 T0 = (env->CP0_Debug & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
1522 (env->CP0_Debug_tcstatus[other_tc] &
1523 ((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
1527 void op_mfc0_depc (void)
1529 T0 = (int32_t)env->CP0_DEPC;
1533 void op_mfc0_performance0 (void)
1535 T0 = env->CP0_Performance0;
1539 void op_mfc0_taglo (void)
1541 T0 = env->CP0_TagLo;
1545 void op_mfc0_datalo (void)
1547 T0 = env->CP0_DataLo;
1551 void op_mfc0_taghi (void)
1553 T0 = env->CP0_TagHi;
1557 void op_mfc0_datahi (void)
1559 T0 = env->CP0_DataHi;
1563 void op_mfc0_errorepc (void)
1565 T0 = (int32_t)env->CP0_ErrorEPC;
1569 void op_mfc0_desave (void)
1571 T0 = env->CP0_DESAVE;
1575 void op_mtc0_index (void)
1578 unsigned int tmp = env->tlb->nb_tlb;
1584 env->CP0_Index = (env->CP0_Index & 0x80000000) | (T0 & (num - 1));
1588 void op_mtc0_mvpcontrol (void)
1593 if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP))
1594 mask |= (1 << CP0MVPCo_CPA) | (1 << CP0MVPCo_VPC) |
1595 (1 << CP0MVPCo_EVP);
1596 if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1597 mask |= (1 << CP0MVPCo_STLB);
1598 newval = (env->mvp->CP0_MVPControl & ~mask) | (T0 & mask);
1600 // TODO: Enable/disable shared TLB, enable/disable VPEs.
1602 env->mvp->CP0_MVPControl = newval;
1606 void op_mtc0_vpecontrol (void)
1611 mask = (1 << CP0VPECo_YSI) | (1 << CP0VPECo_GSI) |
1612 (1 << CP0VPECo_TE) | (0xff << CP0VPECo_TargTC);
1613 newval = (env->CP0_VPEControl & ~mask) | (T0 & mask);
1615 /* Yield scheduler intercept not implemented. */
1616 /* Gating storage scheduler intercept not implemented. */
1618 // TODO: Enable/disable TCs.
1620 env->CP0_VPEControl = newval;
1624 void op_mtc0_vpeconf0 (void)
1629 if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) {
1630 if (env->CP0_VPEConf0 & (1 << CP0VPEC0_VPA))
1631 mask |= (0xff << CP0VPEC0_XTC);
1632 mask |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
1634 newval = (env->CP0_VPEConf0 & ~mask) | (T0 & mask);
1636 // TODO: TC exclusive handling due to ERL/EXL.
1638 env->CP0_VPEConf0 = newval;
1642 void op_mtc0_vpeconf1 (void)
1647 if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1648 mask |= (0xff << CP0VPEC1_NCX) | (0xff << CP0VPEC1_NCP2) |
1649 (0xff << CP0VPEC1_NCP1);
1650 newval = (env->CP0_VPEConf1 & ~mask) | (T0 & mask);
1652 /* UDI not implemented. */
1653 /* CP2 not implemented. */
1655 // TODO: Handle FPU (CP1) binding.
1657 env->CP0_VPEConf1 = newval;
1661 void op_mtc0_yqmask (void)
1663 /* Yield qualifier inputs not implemented. */
1664 env->CP0_YQMask = 0x00000000;
1668 void op_mtc0_vpeschedule (void)
1670 env->CP0_VPESchedule = T0;
1674 void op_mtc0_vpeschefback (void)
1676 env->CP0_VPEScheFBack = T0;
1680 void op_mtc0_vpeopt (void)
1682 env->CP0_VPEOpt = T0 & 0x0000ffff;
1686 void op_mtc0_entrylo0 (void)
1688 /* Large physaddr (PABITS) not implemented */
1689 /* 1k pages not implemented */
1690 env->CP0_EntryLo0 = T0 & 0x3FFFFFFF;
1694 void op_mtc0_tcstatus (void)
1696 uint32_t mask = env->CP0_TCStatus_rw_bitmask;
1699 newval = (env->CP0_TCStatus[env->current_tc] & ~mask) | (T0 & mask);
1701 // TODO: Sync with CP0_Status.
1703 env->CP0_TCStatus[env->current_tc] = newval;
1707 void op_mttc0_tcstatus (void)
1709 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1711 // TODO: Sync with CP0_Status.
1713 env->CP0_TCStatus[other_tc] = T0;
1717 void op_mtc0_tcbind (void)
1719 uint32_t mask = (1 << CP0TCBd_TBE);
1722 if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1723 mask |= (1 << CP0TCBd_CurVPE);
1724 newval = (env->CP0_TCBind[env->current_tc] & ~mask) | (T0 & mask);
1725 env->CP0_TCBind[env->current_tc] = newval;
1729 void op_mttc0_tcbind (void)
1731 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1732 uint32_t mask = (1 << CP0TCBd_TBE);
1735 if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1736 mask |= (1 << CP0TCBd_CurVPE);
1737 newval = (env->CP0_TCBind[other_tc] & ~mask) | (T0 & mask);
1738 env->CP0_TCBind[other_tc] = newval;
1742 void op_mtc0_tcrestart (void)
1744 env->PC[env->current_tc] = T0;
1745 env->CP0_TCStatus[env->current_tc] &= ~(1 << CP0TCSt_TDS);
1746 env->CP0_LLAddr = 0ULL;
1747 /* MIPS16 not implemented. */
1751 void op_mttc0_tcrestart (void)
1753 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1755 env->PC[other_tc] = T0;
1756 env->CP0_TCStatus[other_tc] &= ~(1 << CP0TCSt_TDS);
1757 env->CP0_LLAddr = 0ULL;
1758 /* MIPS16 not implemented. */
1762 void op_mtc0_tchalt (void)
1764 env->CP0_TCHalt[env->current_tc] = T0 & 0x1;
1766 // TODO: Halt TC / Restart (if allocated+active) TC.
1771 void op_mttc0_tchalt (void)
1773 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1775 // TODO: Halt TC / Restart (if allocated+active) TC.
1777 env->CP0_TCHalt[other_tc] = T0;
1781 void op_mtc0_tccontext (void)
1783 env->CP0_TCContext[env->current_tc] = T0;
1787 void op_mttc0_tccontext (void)
1789 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1791 env->CP0_TCContext[other_tc] = T0;
1795 void op_mtc0_tcschedule (void)
1797 env->CP0_TCSchedule[env->current_tc] = T0;
1801 void op_mttc0_tcschedule (void)
1803 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1805 env->CP0_TCSchedule[other_tc] = T0;
1809 void op_mtc0_tcschefback (void)
1811 env->CP0_TCScheFBack[env->current_tc] = T0;
1815 void op_mttc0_tcschefback (void)
1817 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1819 env->CP0_TCScheFBack[other_tc] = T0;
1823 void op_mtc0_entrylo1 (void)
1825 /* Large physaddr (PABITS) not implemented */
1826 /* 1k pages not implemented */
1827 env->CP0_EntryLo1 = T0 & 0x3FFFFFFF;
1831 void op_mtc0_context (void)
1833 env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (T0 & ~0x007FFFFF);
1837 void op_mtc0_pagemask (void)
1839 /* 1k pages not implemented */
1840 env->CP0_PageMask = T0 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
1844 void op_mtc0_pagegrain (void)
1846 /* SmartMIPS not implemented */
1847 /* Large physaddr (PABITS) not implemented */
1848 /* 1k pages not implemented */
1849 env->CP0_PageGrain = 0;
1853 void op_mtc0_wired (void)
1855 env->CP0_Wired = T0 % env->tlb->nb_tlb;
1859 void op_mtc0_srsconf0 (void)
1861 env->CP0_SRSConf0 |= T0 & env->CP0_SRSConf0_rw_bitmask;
1865 void op_mtc0_srsconf1 (void)
1867 env->CP0_SRSConf1 |= T0 & env->CP0_SRSConf1_rw_bitmask;
1871 void op_mtc0_srsconf2 (void)
1873 env->CP0_SRSConf2 |= T0 & env->CP0_SRSConf2_rw_bitmask;
1877 void op_mtc0_srsconf3 (void)
1879 env->CP0_SRSConf3 |= T0 & env->CP0_SRSConf3_rw_bitmask;
1883 void op_mtc0_srsconf4 (void)
1885 env->CP0_SRSConf4 |= T0 & env->CP0_SRSConf4_rw_bitmask;
1889 void op_mtc0_hwrena (void)
1891 env->CP0_HWREna = T0 & 0x0000000F;
1895 void op_mtc0_count (void)
1897 CALL_FROM_TB2(cpu_mips_store_count, env, T0);
1901 void op_mtc0_entryhi (void)
1903 target_ulong old, val;
1905 /* 1k pages not implemented */
1906 val = T0 & ((TARGET_PAGE_MASK << 1) | 0xFF);
1907 #if defined(TARGET_MIPS64)
1908 val &= env->SEGMask;
1910 old = env->CP0_EntryHi;
1911 env->CP0_EntryHi = val;
1912 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
1913 uint32_t tcst = env->CP0_TCStatus[env->current_tc] & ~0xff;
1914 env->CP0_TCStatus[env->current_tc] = tcst | (val & 0xff);
1916 /* If the ASID changes, flush qemu's TLB. */
1917 if ((old & 0xFF) != (val & 0xFF))
1918 CALL_FROM_TB2(cpu_mips_tlb_flush, env, 1);
1922 void op_mttc0_entryhi(void)
1924 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1926 env->CP0_EntryHi = (env->CP0_EntryHi & 0xff) | (T0 & ~0xff);
1927 env->CP0_TCStatus[other_tc] = (env->CP0_TCStatus[other_tc] & ~0xff) | (T0 & 0xff);
1931 void op_mtc0_compare (void)
1933 CALL_FROM_TB2(cpu_mips_store_compare, env, T0);
1937 void op_mtc0_status (void)
1940 uint32_t mask = env->CP0_Status_rw_bitmask;
1943 old = env->CP0_Status;
1944 env->CP0_Status = (env->CP0_Status & ~mask) | val;
1945 CALL_FROM_TB1(compute_hflags, env);
1946 if (loglevel & CPU_LOG_EXEC)
1947 CALL_FROM_TB2(do_mtc0_status_debug, old, val);
1948 CALL_FROM_TB1(cpu_mips_update_irq, env);
1952 void op_mttc0_status(void)
1954 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1955 uint32_t tcstatus = env->CP0_TCStatus[other_tc];
1957 env->CP0_Status = T0 & ~0xf1000018;
1958 tcstatus = (tcstatus & ~(0xf << CP0TCSt_TCU0)) | (T0 & (0xf << CP0St_CU0));
1959 tcstatus = (tcstatus & ~(1 << CP0TCSt_TMX)) | ((T0 & (1 << CP0St_MX)) << (CP0TCSt_TMX - CP0St_MX));
1960 tcstatus = (tcstatus & ~(0x3 << CP0TCSt_TKSU)) | ((T0 & (0x3 << CP0St_KSU)) << (CP0TCSt_TKSU - CP0St_KSU));
1961 env->CP0_TCStatus[other_tc] = tcstatus;
1965 void op_mtc0_intctl (void)
1967 /* vectored interrupts not implemented, no performance counters. */
1968 env->CP0_IntCtl = (env->CP0_IntCtl & ~0x000002e0) | (T0 & 0x000002e0);
1972 void op_mtc0_srsctl (void)
1974 uint32_t mask = (0xf << CP0SRSCtl_ESS) | (0xf << CP0SRSCtl_PSS);
1975 env->CP0_SRSCtl = (env->CP0_SRSCtl & ~mask) | (T0 & mask);
1979 void op_mtc0_srsmap (void)
1981 env->CP0_SRSMap = T0;
1985 void op_mtc0_cause (void)
1987 uint32_t mask = 0x00C00300;
1988 uint32_t old = env->CP0_Cause;
1990 if (env->insn_flags & ISA_MIPS32R2)
1991 mask |= 1 << CP0Ca_DC;
1993 env->CP0_Cause = (env->CP0_Cause & ~mask) | (T0 & mask);
1995 if ((old ^ env->CP0_Cause) & (1 << CP0Ca_DC)) {
1996 if (env->CP0_Cause & (1 << CP0Ca_DC))
1997 CALL_FROM_TB1(cpu_mips_stop_count, env);
1999 CALL_FROM_TB1(cpu_mips_start_count, env);
2002 /* Handle the software interrupt as an hardware one, as they
2004 if (T0 & CP0Ca_IP_mask) {
2005 CALL_FROM_TB1(cpu_mips_update_irq, env);
2010 void op_mtc0_epc (void)
2016 void op_mtc0_ebase (void)
2018 /* vectored interrupts not implemented */
2019 /* Multi-CPU not implemented */
2020 env->CP0_EBase = 0x80000000 | (T0 & 0x3FFFF000);
2024 void op_mtc0_config0 (void)
2026 env->CP0_Config0 = (env->CP0_Config0 & 0x81FFFFF8) | (T0 & 0x00000007);
2030 void op_mtc0_config2 (void)
2032 /* tertiary/secondary caches not implemented */
2033 env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
2037 void op_mtc0_watchlo (void)
2039 /* Watch exceptions for instructions, data loads, data stores
2041 env->CP0_WatchLo[PARAM1] = (T0 & ~0x7);
2045 void op_mtc0_watchhi (void)
2047 env->CP0_WatchHi[PARAM1] = (T0 & 0x40FF0FF8);
2048 env->CP0_WatchHi[PARAM1] &= ~(env->CP0_WatchHi[PARAM1] & T0 & 0x7);
2052 void op_mtc0_xcontext (void)
2054 target_ulong mask = (1ULL << (env->SEGBITS - 7)) - 1;
2055 env->CP0_XContext = (env->CP0_XContext & mask) | (T0 & ~mask);
2059 void op_mtc0_framemask (void)
2061 env->CP0_Framemask = T0; /* XXX */
2065 void op_mtc0_debug (void)
2067 env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120);
2068 if (T0 & (1 << CP0DB_DM))
2069 env->hflags |= MIPS_HFLAG_DM;
2071 env->hflags &= ~MIPS_HFLAG_DM;
2075 void op_mttc0_debug(void)
2077 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2079 /* XXX: Might be wrong, check with EJTAG spec. */
2080 env->CP0_Debug_tcstatus[other_tc] = T0 & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt));
2081 env->CP0_Debug = (env->CP0_Debug & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
2082 (T0 & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
2086 void op_mtc0_depc (void)
2092 void op_mtc0_performance0 (void)
2094 env->CP0_Performance0 = T0 & 0x000007ff;
2098 void op_mtc0_taglo (void)
2100 env->CP0_TagLo = T0 & 0xFFFFFCF6;
2104 void op_mtc0_datalo (void)
2106 env->CP0_DataLo = T0; /* XXX */
2110 void op_mtc0_taghi (void)
2112 env->CP0_TagHi = T0; /* XXX */
2116 void op_mtc0_datahi (void)
2118 env->CP0_DataHi = T0; /* XXX */
2122 void op_mtc0_errorepc (void)
2124 env->CP0_ErrorEPC = T0;
2128 void op_mtc0_desave (void)
2130 env->CP0_DESAVE = T0;
2134 #if defined(TARGET_MIPS64)
2135 void op_dmfc0_yqmask (void)
2137 T0 = env->CP0_YQMask;
2141 void op_dmfc0_vpeschedule (void)
2143 T0 = env->CP0_VPESchedule;
2147 void op_dmfc0_vpeschefback (void)
2149 T0 = env->CP0_VPEScheFBack;
2153 void op_dmfc0_entrylo0 (void)
2155 T0 = env->CP0_EntryLo0;
2159 void op_dmfc0_tcrestart (void)
2161 T0 = env->PC[env->current_tc];
2165 void op_dmfc0_tchalt (void)
2167 T0 = env->CP0_TCHalt[env->current_tc];
2171 void op_dmfc0_tccontext (void)
2173 T0 = env->CP0_TCContext[env->current_tc];
2177 void op_dmfc0_tcschedule (void)
2179 T0 = env->CP0_TCSchedule[env->current_tc];
2183 void op_dmfc0_tcschefback (void)
2185 T0 = env->CP0_TCScheFBack[env->current_tc];
2189 void op_dmfc0_entrylo1 (void)
2191 T0 = env->CP0_EntryLo1;
2195 void op_dmfc0_context (void)
2197 T0 = env->CP0_Context;
2201 void op_dmfc0_badvaddr (void)
2203 T0 = env->CP0_BadVAddr;
2207 void op_dmfc0_entryhi (void)
2209 T0 = env->CP0_EntryHi;
2213 void op_dmfc0_epc (void)
2219 void op_dmfc0_lladdr (void)
2221 T0 = env->CP0_LLAddr >> 4;
2225 void op_dmfc0_watchlo (void)
2227 T0 = env->CP0_WatchLo[PARAM1];
2231 void op_dmfc0_xcontext (void)
2233 T0 = env->CP0_XContext;
2237 void op_dmfc0_depc (void)
2243 void op_dmfc0_errorepc (void)
2245 T0 = env->CP0_ErrorEPC;
2248 #endif /* TARGET_MIPS64 */
2250 /* MIPS MT functions */
2251 void op_mftgpr(void)
2253 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2255 T0 = env->gpr[other_tc][PARAM1];
2261 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2263 T0 = env->LO[other_tc][PARAM1];
2269 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2271 T0 = env->HI[other_tc][PARAM1];
2275 void op_mftacx(void)
2277 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2279 T0 = env->ACX[other_tc][PARAM1];
2283 void op_mftdsp(void)
2285 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2287 T0 = env->DSPControl[other_tc];
2291 void op_mttgpr(void)
2293 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2295 T0 = env->gpr[other_tc][PARAM1];
2301 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2303 T0 = env->LO[other_tc][PARAM1];
2309 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2311 T0 = env->HI[other_tc][PARAM1];
2315 void op_mttacx(void)
2317 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2319 T0 = env->ACX[other_tc][PARAM1];
2323 void op_mttdsp(void)
2325 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2327 T0 = env->DSPControl[other_tc];
2368 // TODO: store to TC register
2375 /* No scheduling policy implemented. */
2377 if (env->CP0_VPEControl & (1 << CP0VPECo_YSI) &&
2378 env->CP0_TCStatus[env->current_tc] & (1 << CP0TCSt_DT)) {
2379 env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
2380 env->CP0_VPEControl |= 4 << CP0VPECo_EXCPT;
2381 CALL_FROM_TB1(do_raise_exception, EXCP_THREAD);
2384 } else if (T0 == 0) {
2385 if (0 /* TODO: TC underflow */) {
2386 env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
2387 CALL_FROM_TB1(do_raise_exception, EXCP_THREAD);
2389 // TODO: Deallocate TC
2391 } else if (T0 > 0) {
2392 /* Yield qualifier inputs not implemented. */
2393 env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
2394 env->CP0_VPEControl |= 2 << CP0VPECo_EXCPT;
2395 CALL_FROM_TB1(do_raise_exception, EXCP_THREAD);
2397 T0 = env->CP0_YQMask;
2403 # define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env)
2405 # define DEBUG_FPU_STATE() do { } while(0)
2410 CALL_FROM_TB1(do_cfc1, PARAM1);
2417 CALL_FROM_TB1(do_ctc1, PARAM1);
2436 void op_dmfc1 (void)
2443 void op_dmtc1 (void)
2450 void op_mfhc1 (void)
2457 void op_mthc1 (void)
2465 Single precition routines have a "s" suffix, double precision a
2466 "d" suffix, 32bit integer "w", 64bit integer "l", paired singe "ps",
2467 paired single lowwer "pl", paired single upper "pu". */
2469 #define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void)
2473 CALL_FROM_TB0(do_float_cvtd_s);
2479 CALL_FROM_TB0(do_float_cvtd_w);
2485 CALL_FROM_TB0(do_float_cvtd_l);
2491 CALL_FROM_TB0(do_float_cvtl_d);
2497 CALL_FROM_TB0(do_float_cvtl_s);
2510 CALL_FROM_TB0(do_float_cvtps_pw);
2516 CALL_FROM_TB0(do_float_cvtpw_ps);
2522 CALL_FROM_TB0(do_float_cvts_d);
2528 CALL_FROM_TB0(do_float_cvts_w);
2534 CALL_FROM_TB0(do_float_cvts_l);
2540 CALL_FROM_TB0(do_float_cvts_pl);
2546 CALL_FROM_TB0(do_float_cvts_pu);
2552 CALL_FROM_TB0(do_float_cvtw_s);
2558 CALL_FROM_TB0(do_float_cvtw_d);
2565 DT2 = ((uint64_t)WT0 << 32) | WT1;
2571 DT2 = ((uint64_t)WT0 << 32) | WTH1;
2577 DT2 = ((uint64_t)WTH0 << 32) | WT1;
2583 DT2 = ((uint64_t)WTH0 << 32) | WTH1;
2588 #define FLOAT_ROUNDOP(op, ttype, stype) \
2589 FLOAT_OP(op ## ttype, stype) \
2591 CALL_FROM_TB0(do_float_ ## op ## ttype ## _ ## stype); \
2592 DEBUG_FPU_STATE(); \
2596 FLOAT_ROUNDOP(round, l, d)
2597 FLOAT_ROUNDOP(round, l, s)
2598 FLOAT_ROUNDOP(round, w, d)
2599 FLOAT_ROUNDOP(round, w, s)
2601 FLOAT_ROUNDOP(trunc, l, d)
2602 FLOAT_ROUNDOP(trunc, l, s)
2603 FLOAT_ROUNDOP(trunc, w, d)
2604 FLOAT_ROUNDOP(trunc, w, s)
2606 FLOAT_ROUNDOP(ceil, l, d)
2607 FLOAT_ROUNDOP(ceil, l, s)
2608 FLOAT_ROUNDOP(ceil, w, d)
2609 FLOAT_ROUNDOP(ceil, w, s)
2611 FLOAT_ROUNDOP(floor, l, d)
2612 FLOAT_ROUNDOP(floor, l, s)
2613 FLOAT_ROUNDOP(floor, w, d)
2614 FLOAT_ROUNDOP(floor, w, s)
2615 #undef FLOAR_ROUNDOP
2619 if (!(env->fpu->fcr31 & PARAM1))
2626 if (!(env->fpu->fcr31 & PARAM1))
2633 if (!(env->fpu->fcr31 & PARAM1)) {
2642 if (env->fpu->fcr31 & PARAM1)
2649 if (env->fpu->fcr31 & PARAM1)
2656 if (env->fpu->fcr31 & PARAM1) {
2710 /* operations calling helpers, for s, d and ps */
2711 #define FLOAT_HOP(name) \
2714 CALL_FROM_TB0(do_float_ ## name ## _d); \
2715 DEBUG_FPU_STATE(); \
2720 CALL_FROM_TB0(do_float_ ## name ## _s); \
2721 DEBUG_FPU_STATE(); \
2724 FLOAT_OP(name, ps) \
2726 CALL_FROM_TB0(do_float_ ## name ## _ps); \
2727 DEBUG_FPU_STATE(); \
2740 /* operations calling helpers, for s and d */
2741 #define FLOAT_HOP(name) \
2744 CALL_FROM_TB0(do_float_ ## name ## _d); \
2745 DEBUG_FPU_STATE(); \
2750 CALL_FROM_TB0(do_float_ ## name ## _s); \
2751 DEBUG_FPU_STATE(); \
2758 /* operations calling helpers, for ps */
2759 #define FLOAT_HOP(name) \
2760 FLOAT_OP(name, ps) \
2762 CALL_FROM_TB0(do_float_ ## name ## _ps); \
2763 DEBUG_FPU_STATE(); \
2770 /* ternary operations */
2771 #define FLOAT_TERNOP(name1, name2) \
2772 FLOAT_OP(name1 ## name2, d) \
2774 FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status); \
2775 FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status); \
2776 DEBUG_FPU_STATE(); \
2779 FLOAT_OP(name1 ## name2, s) \
2781 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
2782 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
2783 DEBUG_FPU_STATE(); \
2786 FLOAT_OP(name1 ## name2, ps) \
2788 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
2789 FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \
2790 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
2791 FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \
2792 DEBUG_FPU_STATE(); \
2795 FLOAT_TERNOP(mul, add)
2796 FLOAT_TERNOP(mul, sub)
2799 /* negated ternary operations */
2800 #define FLOAT_NTERNOP(name1, name2) \
2801 FLOAT_OP(n ## name1 ## name2, d) \
2803 FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status); \
2804 FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status); \
2805 FDT2 = float64_chs(FDT2); \
2806 DEBUG_FPU_STATE(); \
2809 FLOAT_OP(n ## name1 ## name2, s) \
2811 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
2812 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
2813 FST2 = float32_chs(FST2); \
2814 DEBUG_FPU_STATE(); \
2817 FLOAT_OP(n ## name1 ## name2, ps) \
2819 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
2820 FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \
2821 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
2822 FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \
2823 FST2 = float32_chs(FST2); \
2824 FSTH2 = float32_chs(FSTH2); \
2825 DEBUG_FPU_STATE(); \
2828 FLOAT_NTERNOP(mul, add)
2829 FLOAT_NTERNOP(mul, sub)
2830 #undef FLOAT_NTERNOP
2832 /* unary operations, modifying fp status */
2833 #define FLOAT_UNOP(name) \
2836 FDT2 = float64_ ## name(FDT0, &env->fpu->fp_status); \
2837 DEBUG_FPU_STATE(); \
2842 FST2 = float32_ ## name(FST0, &env->fpu->fp_status); \
2843 DEBUG_FPU_STATE(); \
2849 /* unary operations, not modifying fp status */
2850 #define FLOAT_UNOP(name) \
2853 FDT2 = float64_ ## name(FDT0); \
2854 DEBUG_FPU_STATE(); \
2859 FST2 = float32_ ## name(FST0); \
2860 DEBUG_FPU_STATE(); \
2863 FLOAT_OP(name, ps) \
2865 FST2 = float32_ ## name(FST0); \
2866 FSTH2 = float32_ ## name(FSTH0); \
2867 DEBUG_FPU_STATE(); \
2901 #ifdef TARGET_WORDS_BIGENDIAN
2909 default: /* unpredictable */
2916 #ifdef CONFIG_SOFTFLOAT
2917 #define clear_invalid() do { \
2918 int flags = get_float_exception_flags(&env->fpu->fp_status); \
2919 flags &= ~float_flag_invalid; \
2920 set_float_exception_flags(flags, &env->fpu->fp_status); \
2923 #define clear_invalid() do { } while(0)
2926 extern void dump_fpu_s(CPUState *env);
2928 #define CMP_OP(fmt, op) \
2929 void OPPROTO op_cmp ## _ ## fmt ## _ ## op(void) \
2931 CALL_FROM_TB1(do_cmp ## _ ## fmt ## _ ## op, PARAM1); \
2932 DEBUG_FPU_STATE(); \
2935 void OPPROTO op_cmpabs ## _ ## fmt ## _ ## op(void) \
2937 CALL_FROM_TB1(do_cmpabs ## _ ## fmt ## _ ## op, PARAM1); \
2938 DEBUG_FPU_STATE(); \
2941 #define CMP_OPS(op) \
2967 T0 = !!(~GET_FP_COND(env->fpu) & (0x1 << PARAM1));
2971 void op_bc1any2f (void)
2973 T0 = !!(~GET_FP_COND(env->fpu) & (0x3 << PARAM1));
2977 void op_bc1any4f (void)
2979 T0 = !!(~GET_FP_COND(env->fpu) & (0xf << PARAM1));
2986 T0 = !!(GET_FP_COND(env->fpu) & (0x1 << PARAM1));
2990 void op_bc1any2t (void)
2992 T0 = !!(GET_FP_COND(env->fpu) & (0x3 << PARAM1));
2996 void op_bc1any4t (void)
2998 T0 = !!(GET_FP_COND(env->fpu) & (0xf << PARAM1));
3003 void op_tlbwi (void)
3005 CALL_FROM_TB0(env->tlb->do_tlbwi);
3009 void op_tlbwr (void)
3011 CALL_FROM_TB0(env->tlb->do_tlbwr);
3017 CALL_FROM_TB0(env->tlb->do_tlbp);
3023 CALL_FROM_TB0(env->tlb->do_tlbr);
3028 #if defined (CONFIG_USER_ONLY)
3029 void op_tls_value (void)
3031 T0 = env->tls_value;
3037 CALL_FROM_TB1(do_pmon, PARAM1);
3043 T0 = env->CP0_Status;
3044 env->CP0_Status = T0 & ~(1 << CP0St_IE);
3045 CALL_FROM_TB1(cpu_mips_update_irq, env);
3051 T0 = env->CP0_Status;
3052 env->CP0_Status = T0 | (1 << CP0St_IE);
3053 CALL_FROM_TB1(cpu_mips_update_irq, env);
3060 CALL_FROM_TB1(do_raise_exception, EXCP_TRAP);
3065 void op_debug (void)
3067 CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG);
3071 void debug_pre_eret (void);
3072 void debug_post_eret (void);
3075 if (loglevel & CPU_LOG_EXEC)
3076 CALL_FROM_TB0(debug_pre_eret);
3077 if (env->CP0_Status & (1 << CP0St_ERL)) {
3078 env->PC[env->current_tc] = env->CP0_ErrorEPC;
3079 env->CP0_Status &= ~(1 << CP0St_ERL);
3081 env->PC[env->current_tc] = env->CP0_EPC;
3082 env->CP0_Status &= ~(1 << CP0St_EXL);
3084 CALL_FROM_TB1(compute_hflags, env);
3085 if (loglevel & CPU_LOG_EXEC)
3086 CALL_FROM_TB0(debug_post_eret);
3087 env->CP0_LLAddr = 1;
3091 void op_deret (void)
3093 if (loglevel & CPU_LOG_EXEC)
3094 CALL_FROM_TB0(debug_pre_eret);
3095 env->PC[env->current_tc] = env->CP0_DEPC;
3096 env->hflags &= MIPS_HFLAG_DM;
3097 CALL_FROM_TB1(compute_hflags, env);
3098 if (loglevel & CPU_LOG_EXEC)
3099 CALL_FROM_TB0(debug_post_eret);
3100 env->CP0_LLAddr = 1;
3104 void op_rdhwr_cpunum(void)
3106 if ((env->hflags & MIPS_HFLAG_CP0) ||
3107 (env->CP0_HWREna & (1 << 0)))
3108 T0 = env->CP0_EBase & 0x3ff;
3110 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
3114 void op_rdhwr_synci_step(void)
3116 if ((env->hflags & MIPS_HFLAG_CP0) ||
3117 (env->CP0_HWREna & (1 << 1)))
3118 T0 = env->SYNCI_Step;
3120 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
3124 void op_rdhwr_cc(void)
3126 if ((env->hflags & MIPS_HFLAG_CP0) ||
3127 (env->CP0_HWREna & (1 << 2)))
3128 T0 = env->CP0_Count;
3130 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
3134 void op_rdhwr_ccres(void)
3136 if ((env->hflags & MIPS_HFLAG_CP0) ||
3137 (env->CP0_HWREna & (1 << 3)))
3140 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
3144 void op_save_state (void)
3146 env->hflags = PARAM1;
3150 void op_save_pc (void)
3152 env->PC[env->current_tc] = PARAM1;
3156 #if defined(TARGET_MIPS64)
3157 void op_save_pc64 (void)
3159 env->PC[env->current_tc] = ((uint64_t)PARAM1 << 32) | (uint32_t)PARAM2;
3164 void op_interrupt_restart (void)
3166 if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
3167 !(env->CP0_Status & (1 << CP0St_ERL)) &&
3168 !(env->hflags & MIPS_HFLAG_DM) &&
3169 (env->CP0_Status & (1 << CP0St_IE)) &&
3170 (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask)) {
3171 env->CP0_Cause &= ~(0x1f << CP0Ca_EC);
3172 CALL_FROM_TB1(do_raise_exception, EXCP_EXT_INTERRUPT);
3177 void op_raise_exception (void)
3179 CALL_FROM_TB1(do_raise_exception, PARAM1);
3183 void op_raise_exception_err (void)
3185 CALL_FROM_TB2(do_raise_exception_err, PARAM1, PARAM2);
3192 CALL_FROM_TB1(do_raise_exception, EXCP_HLT);
3196 /* Bitfield operations. */
3199 unsigned int pos = PARAM1;
3200 unsigned int size = PARAM2;
3202 T0 = (int32_t)((T1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0));
3208 unsigned int pos = PARAM1;
3209 unsigned int size = PARAM2;
3210 target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos;
3212 T0 = (int32_t)((T0 & ~mask) | ((T1 << pos) & mask));
3218 T0 = (int32_t)(((T1 << 8) & ~0x00FF00FF) | ((T1 >> 8) & 0x00FF00FF));
3222 #if defined(TARGET_MIPS64)
3225 unsigned int pos = PARAM1;
3226 unsigned int size = PARAM2;
3228 T0 = (T1 >> pos) & ((size < 64) ? ((1ULL << size) - 1) : ~0ULL);
3234 unsigned int pos = PARAM1;
3235 unsigned int size = PARAM2;
3236 target_ulong mask = ((size < 64) ? ((1ULL << size) - 1) : ~0ULL) << pos;
3238 T0 = (T0 & ~mask) | ((T1 << pos) & mask);
3244 T0 = ((T1 << 8) & ~0x00FF00FF00FF00FFULL) | ((T1 >> 8) & 0x00FF00FF00FF00FFULL);
3250 T1 = ((T1 << 16) & ~0x0000FFFF0000FFFFULL) | ((T1 >> 16) & 0x0000FFFF0000FFFFULL);
3251 T0 = (T1 << 32) | (T1 >> 32);
3258 T0 = ((T1 & 0xFF) ^ 0x80) - 0x80;
3264 T0 = ((T1 & 0xFFFF) ^ 0x8000) - 0x8000;