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"
250 void op_dup_T0 (void)
256 void op_load_HI (void)
258 T0 = env->HI[PARAM1][env->current_tc];
262 void op_store_HI (void)
264 env->HI[PARAM1][env->current_tc] = T0;
268 void op_load_LO (void)
270 T0 = env->LO[PARAM1][env->current_tc];
274 void op_store_LO (void)
276 env->LO[PARAM1][env->current_tc] = T0;
281 #define MEMSUFFIX _raw
284 #if !defined(CONFIG_USER_ONLY)
285 #define MEMSUFFIX _user
289 #define MEMSUFFIX _super
293 #define MEMSUFFIX _kernel
298 /* Addresses computation */
299 void op_addr_add (void)
301 /* For compatibility with 32-bit code, data reference in user mode
302 with Status_UX = 0 should be casted to 32-bit and sign extended.
303 See the MIPS64 PRA manual, section 4.10. */
304 #if defined(TARGET_MIPS64)
305 if (((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
306 !(env->CP0_Status & (1 << CP0St_UX)))
307 T0 = (int64_t)(int32_t)(T0 + T1);
317 T0 = (int32_t)((int32_t)T0 + (int32_t)T1);
326 T0 = (int32_t)T0 + (int32_t)T1;
327 if (((tmp ^ T1 ^ (-1)) & (T0 ^ T1)) >> 31) {
328 /* operands of same sign, result different sign */
329 CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
337 T0 = (int32_t)((int32_t)T0 - (int32_t)T1);
346 T0 = (int32_t)T0 - (int32_t)T1;
347 if (((tmp ^ T1) & (tmp ^ T0)) >> 31) {
348 /* operands of different sign, first operand and result different sign */
349 CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
357 T0 = (int32_t)((int32_t)T0 * (int32_t)T1);
361 #if HOST_LONG_BITS < 64
364 CALL_FROM_TB0(do_div);
371 env->LO[0][env->current_tc] = (int32_t)((int64_t)(int32_t)T0 / (int32_t)T1);
372 env->HI[0][env->current_tc] = (int32_t)((int64_t)(int32_t)T0 % (int32_t)T1);
381 env->LO[0][env->current_tc] = (int32_t)((uint32_t)T0 / (uint32_t)T1);
382 env->HI[0][env->current_tc] = (int32_t)((uint32_t)T0 % (uint32_t)T1);
387 #if defined(TARGET_MIPS64)
401 if (((tmp ^ T1 ^ (-1)) & (T0 ^ T1)) >> 63) {
402 /* operands of same sign, result different sign */
403 CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
419 T0 = (int64_t)T0 - (int64_t)T1;
420 if (((tmp ^ T1) & (tmp ^ T0)) >> 63) {
421 /* operands of different sign, first operand and result different sign */
422 CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
429 T0 = (int64_t)T0 * (int64_t)T1;
433 /* Those might call libgcc functions. */
440 #if TARGET_LONG_BITS > HOST_LONG_BITS
450 env->LO[0][env->current_tc] = T0 / T1;
451 env->HI[0][env->current_tc] = T0 % T1;
456 #endif /* TARGET_MIPS64 */
485 T0 = (int32_t)((uint32_t)T0 << T1);
491 T0 = (int32_t)((int32_t)T0 >> T1);
497 T0 = (int32_t)((uint32_t)T0 >> T1);
506 tmp = (int32_t)((uint32_t)T0 << (0x20 - T1));
507 T0 = (int32_t)((uint32_t)T0 >> T1) | tmp;
514 T0 = (int32_t)((uint32_t)T1 << ((uint32_t)T0 & 0x1F));
520 T0 = (int32_t)((int32_t)T1 >> (T0 & 0x1F));
526 T0 = (int32_t)((uint32_t)T1 >> (T0 & 0x1F));
536 tmp = (int32_t)((uint32_t)T1 << (0x20 - T0));
537 T0 = (int32_t)((uint32_t)T1 >> T0) | tmp;
555 #if defined(TARGET_MIPS64)
557 #if TARGET_LONG_BITS > HOST_LONG_BITS
558 /* Those might call libgcc functions. */
561 CALL_FROM_TB0(do_dsll);
565 void op_dsll32 (void)
567 CALL_FROM_TB0(do_dsll32);
573 CALL_FROM_TB0(do_dsra);
577 void op_dsra32 (void)
579 CALL_FROM_TB0(do_dsra32);
585 CALL_FROM_TB0(do_dsrl);
589 void op_dsrl32 (void)
591 CALL_FROM_TB0(do_dsrl32);
597 CALL_FROM_TB0(do_drotr);
601 void op_drotr32 (void)
603 CALL_FROM_TB0(do_drotr32);
609 CALL_FROM_TB0(do_dsllv);
615 CALL_FROM_TB0(do_dsrav);
621 CALL_FROM_TB0(do_dsrlv);
625 void op_drotrv (void)
627 CALL_FROM_TB0(do_drotrv);
633 CALL_FROM_TB0(do_dclo);
639 CALL_FROM_TB0(do_dclz);
643 #else /* TARGET_LONG_BITS > HOST_LONG_BITS */
651 void op_dsll32 (void)
653 T0 = T0 << (T1 + 32);
659 T0 = (int64_t)T0 >> T1;
663 void op_dsra32 (void)
665 T0 = (int64_t)T0 >> (T1 + 32);
675 void op_dsrl32 (void)
677 T0 = T0 >> (T1 + 32);
686 tmp = T0 << (0x40 - T1);
687 T0 = (T0 >> T1) | tmp;
692 void op_drotr32 (void)
697 tmp = T0 << (0x40 - (32 + T1));
698 T0 = (T0 >> (32 + T1)) | tmp;
705 T0 = T1 << (T0 & 0x3F);
711 T0 = (int64_t)T1 >> (T0 & 0x3F);
717 T0 = T1 >> (T0 & 0x3F);
721 void op_drotrv (void)
727 tmp = T1 << (0x40 - T0);
728 T0 = (T1 >> T0) | tmp;
745 #endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
746 #endif /* TARGET_MIPS64 */
748 /* 64 bits arithmetic */
749 #if TARGET_LONG_BITS > HOST_LONG_BITS
752 CALL_FROM_TB0(do_mult);
758 CALL_FROM_TB0(do_multu);
764 CALL_FROM_TB0(do_madd);
770 CALL_FROM_TB0(do_maddu);
776 CALL_FROM_TB0(do_msub);
782 CALL_FROM_TB0(do_msubu);
786 #else /* TARGET_LONG_BITS > HOST_LONG_BITS */
788 static always_inline uint64_t get_HILO (void)
790 return ((uint64_t)env->HI[0][env->current_tc] << 32) |
791 ((uint64_t)(uint32_t)env->LO[0][env->current_tc]);
794 static always_inline void set_HILO (uint64_t HILO)
796 env->LO[0][env->current_tc] = (int32_t)(HILO & 0xFFFFFFFF);
797 env->HI[0][env->current_tc] = (int32_t)(HILO >> 32);
802 set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
808 set_HILO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
816 tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
817 set_HILO((int64_t)get_HILO() + tmp);
825 tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
826 set_HILO(get_HILO() + tmp);
834 tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
835 set_HILO((int64_t)get_HILO() - tmp);
843 tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
844 set_HILO(get_HILO() - tmp);
847 #endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
849 #if defined(TARGET_MIPS64)
852 CALL_FROM_TB4(muls64, &(env->LO[0][env->current_tc]), &(env->HI[0][env->current_tc]), T0, T1);
856 void op_dmultu (void)
858 CALL_FROM_TB4(mulu64, &(env->LO[0][env->current_tc]), &(env->HI[0][env->current_tc]), T0, T1);
863 /* Conditional moves */
867 env->gpr[PARAM1][env->current_tc] = T0;
874 env->gpr[PARAM1][env->current_tc] = T0;
880 if (!(env->fpu->fcr31 & PARAM1))
887 if (env->fpu->fcr31 & PARAM1)
893 #define OP_COND(name, cond) \
894 void glue(op_, name) (void) \
904 OP_COND(eq, T0 == T1);
905 OP_COND(ne, T0 != T1);
906 OP_COND(ge, (target_long)T0 >= (target_long)T1);
907 OP_COND(geu, T0 >= T1);
908 OP_COND(lt, (target_long)T0 < (target_long)T1);
909 OP_COND(ltu, T0 < T1);
910 OP_COND(gez, (target_long)T0 >= 0);
911 OP_COND(gtz, (target_long)T0 > 0);
912 OP_COND(lez, (target_long)T0 <= 0);
913 OP_COND(ltz, (target_long)T0 < 0);
916 void OPPROTO op_goto_tb0(void)
918 GOTO_TB(op_goto_tb0, PARAM1, 0);
922 void OPPROTO op_goto_tb1(void)
924 GOTO_TB(op_goto_tb1, PARAM1, 1);
928 /* Branch to register */
929 void op_save_breg_target (void)
935 void op_restore_breg_target (void)
943 env->PC[env->current_tc] = T2;
947 void op_save_btarget (void)
949 env->btarget = PARAM1;
953 #if defined(TARGET_MIPS64)
954 void op_save_btarget64 (void)
956 env->btarget = ((uint64_t)PARAM1 << 32) | (uint32_t)PARAM2;
961 /* Conditional branch */
962 void op_set_bcond (void)
968 void op_save_bcond (void)
974 void op_restore_bcond (void)
980 void op_jnz_T2 (void)
988 void op_mfc0_index (void)
994 void op_mfc0_mvpcontrol (void)
996 T0 = env->mvp->CP0_MVPControl;
1000 void op_mfc0_mvpconf0 (void)
1002 T0 = env->mvp->CP0_MVPConf0;
1006 void op_mfc0_mvpconf1 (void)
1008 T0 = env->mvp->CP0_MVPConf1;
1012 void op_mfc0_random (void)
1014 CALL_FROM_TB0(do_mfc0_random);
1018 void op_mfc0_vpecontrol (void)
1020 T0 = env->CP0_VPEControl;
1024 void op_mfc0_vpeconf0 (void)
1026 T0 = env->CP0_VPEConf0;
1030 void op_mfc0_vpeconf1 (void)
1032 T0 = env->CP0_VPEConf1;
1036 void op_mfc0_yqmask (void)
1038 T0 = env->CP0_YQMask;
1042 void op_mfc0_vpeschedule (void)
1044 T0 = env->CP0_VPESchedule;
1048 void op_mfc0_vpeschefback (void)
1050 T0 = env->CP0_VPEScheFBack;
1054 void op_mfc0_vpeopt (void)
1056 T0 = env->CP0_VPEOpt;
1060 void op_mfc0_entrylo0 (void)
1062 T0 = (int32_t)env->CP0_EntryLo0;
1066 void op_mfc0_tcstatus (void)
1068 T0 = env->CP0_TCStatus[env->current_tc];
1072 void op_mftc0_tcstatus(void)
1074 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1076 T0 = env->CP0_TCStatus[other_tc];
1080 void op_mfc0_tcbind (void)
1082 T0 = env->CP0_TCBind[env->current_tc];
1086 void op_mftc0_tcbind(void)
1088 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1090 T0 = env->CP0_TCBind[other_tc];
1094 void op_mfc0_tcrestart (void)
1096 T0 = env->PC[env->current_tc];
1100 void op_mftc0_tcrestart(void)
1102 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1104 T0 = env->PC[other_tc];
1108 void op_mfc0_tchalt (void)
1110 T0 = env->CP0_TCHalt[env->current_tc];
1114 void op_mftc0_tchalt(void)
1116 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1118 T0 = env->CP0_TCHalt[other_tc];
1122 void op_mfc0_tccontext (void)
1124 T0 = env->CP0_TCContext[env->current_tc];
1128 void op_mftc0_tccontext(void)
1130 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1132 T0 = env->CP0_TCContext[other_tc];
1136 void op_mfc0_tcschedule (void)
1138 T0 = env->CP0_TCSchedule[env->current_tc];
1142 void op_mftc0_tcschedule(void)
1144 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1146 T0 = env->CP0_TCSchedule[other_tc];
1150 void op_mfc0_tcschefback (void)
1152 T0 = env->CP0_TCScheFBack[env->current_tc];
1156 void op_mftc0_tcschefback(void)
1158 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1160 T0 = env->CP0_TCScheFBack[other_tc];
1164 void op_mfc0_entrylo1 (void)
1166 T0 = (int32_t)env->CP0_EntryLo1;
1170 void op_mfc0_context (void)
1172 T0 = (int32_t)env->CP0_Context;
1176 void op_mfc0_pagemask (void)
1178 T0 = env->CP0_PageMask;
1182 void op_mfc0_pagegrain (void)
1184 T0 = env->CP0_PageGrain;
1188 void op_mfc0_wired (void)
1190 T0 = env->CP0_Wired;
1194 void op_mfc0_srsconf0 (void)
1196 T0 = env->CP0_SRSConf0;
1200 void op_mfc0_srsconf1 (void)
1202 T0 = env->CP0_SRSConf1;
1206 void op_mfc0_srsconf2 (void)
1208 T0 = env->CP0_SRSConf2;
1212 void op_mfc0_srsconf3 (void)
1214 T0 = env->CP0_SRSConf3;
1218 void op_mfc0_srsconf4 (void)
1220 T0 = env->CP0_SRSConf4;
1224 void op_mfc0_hwrena (void)
1226 T0 = env->CP0_HWREna;
1230 void op_mfc0_badvaddr (void)
1232 T0 = (int32_t)env->CP0_BadVAddr;
1236 void op_mfc0_count (void)
1238 CALL_FROM_TB0(do_mfc0_count);
1242 void op_mfc0_entryhi (void)
1244 T0 = (int32_t)env->CP0_EntryHi;
1248 void op_mftc0_entryhi(void)
1250 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1252 T0 = (env->CP0_EntryHi & ~0xff) | (env->CP0_TCStatus[other_tc] & 0xff);
1256 void op_mfc0_compare (void)
1258 T0 = env->CP0_Compare;
1262 void op_mfc0_status (void)
1264 T0 = env->CP0_Status;
1268 void op_mftc0_status(void)
1270 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1271 uint32_t tcstatus = env->CP0_TCStatus[other_tc];
1273 T0 = env->CP0_Status & ~0xf1000018;
1274 T0 |= tcstatus & (0xf << CP0TCSt_TCU0);
1275 T0 |= (tcstatus & (1 << CP0TCSt_TMX)) >> (CP0TCSt_TMX - CP0St_MX);
1276 T0 |= (tcstatus & (0x3 << CP0TCSt_TKSU)) >> (CP0TCSt_TKSU - CP0St_KSU);
1280 void op_mfc0_intctl (void)
1282 T0 = env->CP0_IntCtl;
1286 void op_mfc0_srsctl (void)
1288 T0 = env->CP0_SRSCtl;
1292 void op_mfc0_srsmap (void)
1294 T0 = env->CP0_SRSMap;
1298 void op_mfc0_cause (void)
1300 T0 = env->CP0_Cause;
1304 void op_mfc0_epc (void)
1306 T0 = (int32_t)env->CP0_EPC;
1310 void op_mfc0_prid (void)
1316 void op_mfc0_ebase (void)
1318 T0 = env->CP0_EBase;
1322 void op_mfc0_config0 (void)
1324 T0 = env->CP0_Config0;
1328 void op_mfc0_config1 (void)
1330 T0 = env->CP0_Config1;
1334 void op_mfc0_config2 (void)
1336 T0 = env->CP0_Config2;
1340 void op_mfc0_config3 (void)
1342 T0 = env->CP0_Config3;
1346 void op_mfc0_config6 (void)
1348 T0 = env->CP0_Config6;
1352 void op_mfc0_config7 (void)
1354 T0 = env->CP0_Config7;
1358 void op_mfc0_lladdr (void)
1360 T0 = (int32_t)env->CP0_LLAddr >> 4;
1364 void op_mfc0_watchlo (void)
1366 T0 = (int32_t)env->CP0_WatchLo[PARAM1];
1370 void op_mfc0_watchhi (void)
1372 T0 = env->CP0_WatchHi[PARAM1];
1376 void op_mfc0_xcontext (void)
1378 T0 = (int32_t)env->CP0_XContext;
1382 void op_mfc0_framemask (void)
1384 T0 = env->CP0_Framemask;
1388 void op_mfc0_debug (void)
1390 T0 = env->CP0_Debug;
1391 if (env->hflags & MIPS_HFLAG_DM)
1392 T0 |= 1 << CP0DB_DM;
1396 void op_mftc0_debug(void)
1398 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1400 /* XXX: Might be wrong, check with EJTAG spec. */
1401 T0 = (env->CP0_Debug & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
1402 (env->CP0_Debug_tcstatus[other_tc] &
1403 ((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
1407 void op_mfc0_depc (void)
1409 T0 = (int32_t)env->CP0_DEPC;
1413 void op_mfc0_performance0 (void)
1415 T0 = env->CP0_Performance0;
1419 void op_mfc0_taglo (void)
1421 T0 = env->CP0_TagLo;
1425 void op_mfc0_datalo (void)
1427 T0 = env->CP0_DataLo;
1431 void op_mfc0_taghi (void)
1433 T0 = env->CP0_TagHi;
1437 void op_mfc0_datahi (void)
1439 T0 = env->CP0_DataHi;
1443 void op_mfc0_errorepc (void)
1445 T0 = (int32_t)env->CP0_ErrorEPC;
1449 void op_mfc0_desave (void)
1451 T0 = env->CP0_DESAVE;
1455 void op_mtc0_index (void)
1458 unsigned int tmp = env->tlb->nb_tlb;
1464 env->CP0_Index = (env->CP0_Index & 0x80000000) | (T0 & (num - 1));
1468 void op_mtc0_mvpcontrol (void)
1473 if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP))
1474 mask |= (1 << CP0MVPCo_CPA) | (1 << CP0MVPCo_VPC) |
1475 (1 << CP0MVPCo_EVP);
1476 if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1477 mask |= (1 << CP0MVPCo_STLB);
1478 newval = (env->mvp->CP0_MVPControl & ~mask) | (T0 & mask);
1480 // TODO: Enable/disable shared TLB, enable/disable VPEs.
1482 env->mvp->CP0_MVPControl = newval;
1486 void op_mtc0_vpecontrol (void)
1491 mask = (1 << CP0VPECo_YSI) | (1 << CP0VPECo_GSI) |
1492 (1 << CP0VPECo_TE) | (0xff << CP0VPECo_TargTC);
1493 newval = (env->CP0_VPEControl & ~mask) | (T0 & mask);
1495 /* Yield scheduler intercept not implemented. */
1496 /* Gating storage scheduler intercept not implemented. */
1498 // TODO: Enable/disable TCs.
1500 env->CP0_VPEControl = newval;
1504 void op_mtc0_vpeconf0 (void)
1509 if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) {
1510 if (env->CP0_VPEConf0 & (1 << CP0VPEC0_VPA))
1511 mask |= (0xff << CP0VPEC0_XTC);
1512 mask |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
1514 newval = (env->CP0_VPEConf0 & ~mask) | (T0 & mask);
1516 // TODO: TC exclusive handling due to ERL/EXL.
1518 env->CP0_VPEConf0 = newval;
1522 void op_mtc0_vpeconf1 (void)
1527 if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1528 mask |= (0xff << CP0VPEC1_NCX) | (0xff << CP0VPEC1_NCP2) |
1529 (0xff << CP0VPEC1_NCP1);
1530 newval = (env->CP0_VPEConf1 & ~mask) | (T0 & mask);
1532 /* UDI not implemented. */
1533 /* CP2 not implemented. */
1535 // TODO: Handle FPU (CP1) binding.
1537 env->CP0_VPEConf1 = newval;
1541 void op_mtc0_yqmask (void)
1543 /* Yield qualifier inputs not implemented. */
1544 env->CP0_YQMask = 0x00000000;
1548 void op_mtc0_vpeschedule (void)
1550 env->CP0_VPESchedule = T0;
1554 void op_mtc0_vpeschefback (void)
1556 env->CP0_VPEScheFBack = T0;
1560 void op_mtc0_vpeopt (void)
1562 env->CP0_VPEOpt = T0 & 0x0000ffff;
1566 void op_mtc0_entrylo0 (void)
1568 /* Large physaddr not implemented */
1569 /* 1k pages not implemented */
1570 env->CP0_EntryLo0 = T0 & 0x3FFFFFFF;
1574 void op_mtc0_tcstatus (void)
1576 uint32_t mask = env->CP0_TCStatus_rw_bitmask;
1579 newval = (env->CP0_TCStatus[env->current_tc] & ~mask) | (T0 & mask);
1581 // TODO: Sync with CP0_Status.
1583 env->CP0_TCStatus[env->current_tc] = newval;
1587 void op_mttc0_tcstatus (void)
1589 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1591 // TODO: Sync with CP0_Status.
1593 env->CP0_TCStatus[other_tc] = T0;
1597 void op_mtc0_tcbind (void)
1599 uint32_t mask = (1 << CP0TCBd_TBE);
1602 if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1603 mask |= (1 << CP0TCBd_CurVPE);
1604 newval = (env->CP0_TCBind[env->current_tc] & ~mask) | (T0 & mask);
1605 env->CP0_TCBind[env->current_tc] = newval;
1609 void op_mttc0_tcbind (void)
1611 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1612 uint32_t mask = (1 << CP0TCBd_TBE);
1615 if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1616 mask |= (1 << CP0TCBd_CurVPE);
1617 newval = (env->CP0_TCBind[other_tc] & ~mask) | (T0 & mask);
1618 env->CP0_TCBind[other_tc] = newval;
1622 void op_mtc0_tcrestart (void)
1624 env->PC[env->current_tc] = T0;
1625 env->CP0_TCStatus[env->current_tc] &= ~(1 << CP0TCSt_TDS);
1626 env->CP0_LLAddr = 0ULL;
1627 /* MIPS16 not implemented. */
1631 void op_mttc0_tcrestart (void)
1633 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1635 env->PC[other_tc] = T0;
1636 env->CP0_TCStatus[other_tc] &= ~(1 << CP0TCSt_TDS);
1637 env->CP0_LLAddr = 0ULL;
1638 /* MIPS16 not implemented. */
1642 void op_mtc0_tchalt (void)
1644 env->CP0_TCHalt[env->current_tc] = T0 & 0x1;
1646 // TODO: Halt TC / Restart (if allocated+active) TC.
1651 void op_mttc0_tchalt (void)
1653 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1655 // TODO: Halt TC / Restart (if allocated+active) TC.
1657 env->CP0_TCHalt[other_tc] = T0;
1661 void op_mtc0_tccontext (void)
1663 env->CP0_TCContext[env->current_tc] = T0;
1667 void op_mttc0_tccontext (void)
1669 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1671 env->CP0_TCContext[other_tc] = T0;
1675 void op_mtc0_tcschedule (void)
1677 env->CP0_TCSchedule[env->current_tc] = T0;
1681 void op_mttc0_tcschedule (void)
1683 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1685 env->CP0_TCSchedule[other_tc] = T0;
1689 void op_mtc0_tcschefback (void)
1691 env->CP0_TCScheFBack[env->current_tc] = T0;
1695 void op_mttc0_tcschefback (void)
1697 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1699 env->CP0_TCScheFBack[other_tc] = T0;
1703 void op_mtc0_entrylo1 (void)
1705 /* Large physaddr not implemented */
1706 /* 1k pages not implemented */
1707 env->CP0_EntryLo1 = T0 & 0x3FFFFFFF;
1711 void op_mtc0_context (void)
1713 env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (T0 & ~0x007FFFFF);
1717 void op_mtc0_pagemask (void)
1719 /* 1k pages not implemented */
1720 env->CP0_PageMask = T0 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
1724 void op_mtc0_pagegrain (void)
1726 /* SmartMIPS not implemented */
1727 /* Large physaddr not implemented */
1728 /* 1k pages not implemented */
1729 env->CP0_PageGrain = 0;
1733 void op_mtc0_wired (void)
1735 env->CP0_Wired = T0 % env->tlb->nb_tlb;
1739 void op_mtc0_srsconf0 (void)
1741 env->CP0_SRSConf0 |= T0 & env->CP0_SRSConf0_rw_bitmask;
1745 void op_mtc0_srsconf1 (void)
1747 env->CP0_SRSConf1 |= T0 & env->CP0_SRSConf1_rw_bitmask;
1751 void op_mtc0_srsconf2 (void)
1753 env->CP0_SRSConf2 |= T0 & env->CP0_SRSConf2_rw_bitmask;
1757 void op_mtc0_srsconf3 (void)
1759 env->CP0_SRSConf3 |= T0 & env->CP0_SRSConf3_rw_bitmask;
1763 void op_mtc0_srsconf4 (void)
1765 env->CP0_SRSConf4 |= T0 & env->CP0_SRSConf4_rw_bitmask;
1769 void op_mtc0_hwrena (void)
1771 env->CP0_HWREna = T0 & 0x0000000F;
1775 void op_mtc0_count (void)
1777 CALL_FROM_TB2(cpu_mips_store_count, env, T0);
1781 void op_mtc0_entryhi (void)
1783 target_ulong old, val;
1785 /* 1k pages not implemented */
1786 val = T0 & ((TARGET_PAGE_MASK << 1) | 0xFF);
1787 #if defined(TARGET_MIPS64)
1788 val &= env->SEGMask;
1790 old = env->CP0_EntryHi;
1791 env->CP0_EntryHi = val;
1792 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
1793 uint32_t tcst = env->CP0_TCStatus[env->current_tc] & ~0xff;
1794 env->CP0_TCStatus[env->current_tc] = tcst | (val & 0xff);
1796 /* If the ASID changes, flush qemu's TLB. */
1797 if ((old & 0xFF) != (val & 0xFF))
1798 CALL_FROM_TB2(cpu_mips_tlb_flush, env, 1);
1802 void op_mttc0_entryhi(void)
1804 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1806 env->CP0_EntryHi = (env->CP0_EntryHi & 0xff) | (T0 & ~0xff);
1807 env->CP0_TCStatus[other_tc] = (env->CP0_TCStatus[other_tc] & ~0xff) | (T0 & 0xff);
1811 void op_mtc0_compare (void)
1813 CALL_FROM_TB2(cpu_mips_store_compare, env, T0);
1817 void op_mtc0_status (void)
1820 uint32_t mask = env->CP0_Status_rw_bitmask;
1823 old = env->CP0_Status;
1824 env->CP0_Status = (env->CP0_Status & ~mask) | val;
1825 CALL_FROM_TB1(compute_hflags, env);
1826 if (loglevel & CPU_LOG_EXEC)
1827 CALL_FROM_TB2(do_mtc0_status_debug, old, val);
1828 CALL_FROM_TB1(cpu_mips_update_irq, env);
1832 void op_mttc0_status(void)
1834 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1835 uint32_t tcstatus = env->CP0_TCStatus[other_tc];
1837 env->CP0_Status = T0 & ~0xf1000018;
1838 tcstatus = (tcstatus & ~(0xf << CP0TCSt_TCU0)) | (T0 & (0xf << CP0St_CU0));
1839 tcstatus = (tcstatus & ~(1 << CP0TCSt_TMX)) | ((T0 & (1 << CP0St_MX)) << (CP0TCSt_TMX - CP0St_MX));
1840 tcstatus = (tcstatus & ~(0x3 << CP0TCSt_TKSU)) | ((T0 & (0x3 << CP0St_KSU)) << (CP0TCSt_TKSU - CP0St_KSU));
1841 env->CP0_TCStatus[other_tc] = tcstatus;
1845 void op_mtc0_intctl (void)
1847 /* vectored interrupts not implemented, no performance counters. */
1848 env->CP0_IntCtl = (env->CP0_IntCtl & ~0x000002e0) | (T0 & 0x000002e0);
1852 void op_mtc0_srsctl (void)
1854 uint32_t mask = (0xf << CP0SRSCtl_ESS) | (0xf << CP0SRSCtl_PSS);
1855 env->CP0_SRSCtl = (env->CP0_SRSCtl & ~mask) | (T0 & mask);
1859 void op_mtc0_srsmap (void)
1861 env->CP0_SRSMap = T0;
1865 void op_mtc0_cause (void)
1867 uint32_t mask = 0x00C00300;
1868 uint32_t old = env->CP0_Cause;
1870 if (env->insn_flags & ISA_MIPS32R2)
1871 mask |= 1 << CP0Ca_DC;
1873 env->CP0_Cause = (env->CP0_Cause & ~mask) | (T0 & mask);
1875 if ((old ^ env->CP0_Cause) & (1 << CP0Ca_DC)) {
1876 if (env->CP0_Cause & (1 << CP0Ca_DC))
1877 CALL_FROM_TB1(cpu_mips_stop_count, env);
1879 CALL_FROM_TB1(cpu_mips_start_count, env);
1882 /* Handle the software interrupt as an hardware one, as they
1884 if (T0 & CP0Ca_IP_mask) {
1885 CALL_FROM_TB1(cpu_mips_update_irq, env);
1890 void op_mtc0_epc (void)
1896 void op_mtc0_ebase (void)
1898 /* vectored interrupts not implemented */
1899 /* Multi-CPU not implemented */
1900 env->CP0_EBase = 0x80000000 | (T0 & 0x3FFFF000);
1904 void op_mtc0_config0 (void)
1906 env->CP0_Config0 = (env->CP0_Config0 & 0x81FFFFF8) | (T0 & 0x00000007);
1910 void op_mtc0_config2 (void)
1912 /* tertiary/secondary caches not implemented */
1913 env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
1917 void op_mtc0_watchlo (void)
1919 /* Watch exceptions for instructions, data loads, data stores
1921 env->CP0_WatchLo[PARAM1] = (T0 & ~0x7);
1925 void op_mtc0_watchhi (void)
1927 env->CP0_WatchHi[PARAM1] = (T0 & 0x40FF0FF8);
1928 env->CP0_WatchHi[PARAM1] &= ~(env->CP0_WatchHi[PARAM1] & T0 & 0x7);
1932 void op_mtc0_xcontext (void)
1934 target_ulong mask = (1ULL << (env->SEGBITS - 7)) - 1;
1935 env->CP0_XContext = (env->CP0_XContext & mask) | (T0 & ~mask);
1939 void op_mtc0_framemask (void)
1941 env->CP0_Framemask = T0; /* XXX */
1945 void op_mtc0_debug (void)
1947 env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120);
1948 if (T0 & (1 << CP0DB_DM))
1949 env->hflags |= MIPS_HFLAG_DM;
1951 env->hflags &= ~MIPS_HFLAG_DM;
1955 void op_mttc0_debug(void)
1957 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1959 /* XXX: Might be wrong, check with EJTAG spec. */
1960 env->CP0_Debug_tcstatus[other_tc] = T0 & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt));
1961 env->CP0_Debug = (env->CP0_Debug & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
1962 (T0 & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
1966 void op_mtc0_depc (void)
1972 void op_mtc0_performance0 (void)
1974 env->CP0_Performance0 = T0 & 0x000007ff;
1978 void op_mtc0_taglo (void)
1980 env->CP0_TagLo = T0 & 0xFFFFFCF6;
1984 void op_mtc0_datalo (void)
1986 env->CP0_DataLo = T0; /* XXX */
1990 void op_mtc0_taghi (void)
1992 env->CP0_TagHi = T0; /* XXX */
1996 void op_mtc0_datahi (void)
1998 env->CP0_DataHi = T0; /* XXX */
2002 void op_mtc0_errorepc (void)
2004 env->CP0_ErrorEPC = T0;
2008 void op_mtc0_desave (void)
2010 env->CP0_DESAVE = T0;
2014 #if defined(TARGET_MIPS64)
2015 void op_dmfc0_yqmask (void)
2017 T0 = env->CP0_YQMask;
2021 void op_dmfc0_vpeschedule (void)
2023 T0 = env->CP0_VPESchedule;
2027 void op_dmfc0_vpeschefback (void)
2029 T0 = env->CP0_VPEScheFBack;
2033 void op_dmfc0_entrylo0 (void)
2035 T0 = env->CP0_EntryLo0;
2039 void op_dmfc0_tcrestart (void)
2041 T0 = env->PC[env->current_tc];
2045 void op_dmfc0_tchalt (void)
2047 T0 = env->CP0_TCHalt[env->current_tc];
2051 void op_dmfc0_tccontext (void)
2053 T0 = env->CP0_TCContext[env->current_tc];
2057 void op_dmfc0_tcschedule (void)
2059 T0 = env->CP0_TCSchedule[env->current_tc];
2063 void op_dmfc0_tcschefback (void)
2065 T0 = env->CP0_TCScheFBack[env->current_tc];
2069 void op_dmfc0_entrylo1 (void)
2071 T0 = env->CP0_EntryLo1;
2075 void op_dmfc0_context (void)
2077 T0 = env->CP0_Context;
2081 void op_dmfc0_badvaddr (void)
2083 T0 = env->CP0_BadVAddr;
2087 void op_dmfc0_entryhi (void)
2089 T0 = env->CP0_EntryHi;
2093 void op_dmfc0_epc (void)
2099 void op_dmfc0_lladdr (void)
2101 T0 = env->CP0_LLAddr >> 4;
2105 void op_dmfc0_watchlo (void)
2107 T0 = env->CP0_WatchLo[PARAM1];
2111 void op_dmfc0_xcontext (void)
2113 T0 = env->CP0_XContext;
2117 void op_dmfc0_depc (void)
2123 void op_dmfc0_errorepc (void)
2125 T0 = env->CP0_ErrorEPC;
2128 #endif /* TARGET_MIPS64 */
2130 /* MIPS MT functions */
2131 void op_mftgpr(void)
2133 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2135 T0 = env->gpr[PARAM1][other_tc];
2141 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2143 T0 = env->LO[PARAM1][other_tc];
2149 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2151 T0 = env->HI[PARAM1][other_tc];
2155 void op_mftacx(void)
2157 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2159 T0 = env->ACX[PARAM1][other_tc];
2163 void op_mftdsp(void)
2165 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2167 T0 = env->DSPControl[other_tc];
2171 void op_mttgpr(void)
2173 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2175 T0 = env->gpr[PARAM1][other_tc];
2181 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2183 T0 = env->LO[PARAM1][other_tc];
2189 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2191 T0 = env->HI[PARAM1][other_tc];
2195 void op_mttacx(void)
2197 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2199 T0 = env->ACX[PARAM1][other_tc];
2203 void op_mttdsp(void)
2205 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
2207 T0 = env->DSPControl[other_tc];
2248 // TODO: store to TC register
2255 /* No scheduling policy implemented. */
2257 if (env->CP0_VPEControl & (1 << CP0VPECo_YSI) &&
2258 env->CP0_TCStatus[env->current_tc] & (1 << CP0TCSt_DT)) {
2259 env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
2260 env->CP0_VPEControl |= 4 << CP0VPECo_EXCPT;
2261 CALL_FROM_TB1(do_raise_exception, EXCP_THREAD);
2264 } else if (T0 == 0) {
2265 if (0 /* TODO: TC underflow */) {
2266 env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
2267 CALL_FROM_TB1(do_raise_exception, EXCP_THREAD);
2269 // TODO: Deallocate TC
2271 } else if (T0 > 0) {
2272 /* Yield qualifier inputs not implemented. */
2273 env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
2274 env->CP0_VPEControl |= 2 << CP0VPECo_EXCPT;
2275 CALL_FROM_TB1(do_raise_exception, EXCP_THREAD);
2277 T0 = env->CP0_YQMask;
2283 # define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env)
2285 # define DEBUG_FPU_STATE() do { } while(0)
2290 CALL_FROM_TB1(do_cfc1, PARAM1);
2297 CALL_FROM_TB1(do_ctc1, PARAM1);
2316 void op_dmfc1 (void)
2323 void op_dmtc1 (void)
2330 void op_mfhc1 (void)
2337 void op_mthc1 (void)
2345 Single precition routines have a "s" suffix, double precision a
2346 "d" suffix, 32bit integer "w", 64bit integer "l", paired singe "ps",
2347 paired single lowwer "pl", paired single upper "pu". */
2349 #define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void)
2353 CALL_FROM_TB0(do_float_cvtd_s);
2359 CALL_FROM_TB0(do_float_cvtd_w);
2365 CALL_FROM_TB0(do_float_cvtd_l);
2371 CALL_FROM_TB0(do_float_cvtl_d);
2377 CALL_FROM_TB0(do_float_cvtl_s);
2390 CALL_FROM_TB0(do_float_cvtps_pw);
2396 CALL_FROM_TB0(do_float_cvtpw_ps);
2402 CALL_FROM_TB0(do_float_cvts_d);
2408 CALL_FROM_TB0(do_float_cvts_w);
2414 CALL_FROM_TB0(do_float_cvts_l);
2420 CALL_FROM_TB0(do_float_cvts_pl);
2426 CALL_FROM_TB0(do_float_cvts_pu);
2432 CALL_FROM_TB0(do_float_cvtw_s);
2438 CALL_FROM_TB0(do_float_cvtw_d);
2445 DT2 = ((uint64_t)WT0 << 32) | WT1;
2451 DT2 = ((uint64_t)WT0 << 32) | WTH1;
2457 DT2 = ((uint64_t)WTH0 << 32) | WT1;
2463 DT2 = ((uint64_t)WTH0 << 32) | WTH1;
2468 #define FLOAT_ROUNDOP(op, ttype, stype) \
2469 FLOAT_OP(op ## ttype, stype) \
2471 CALL_FROM_TB0(do_float_ ## op ## ttype ## _ ## stype); \
2472 DEBUG_FPU_STATE(); \
2476 FLOAT_ROUNDOP(round, l, d)
2477 FLOAT_ROUNDOP(round, l, s)
2478 FLOAT_ROUNDOP(round, w, d)
2479 FLOAT_ROUNDOP(round, w, s)
2481 FLOAT_ROUNDOP(trunc, l, d)
2482 FLOAT_ROUNDOP(trunc, l, s)
2483 FLOAT_ROUNDOP(trunc, w, d)
2484 FLOAT_ROUNDOP(trunc, w, s)
2486 FLOAT_ROUNDOP(ceil, l, d)
2487 FLOAT_ROUNDOP(ceil, l, s)
2488 FLOAT_ROUNDOP(ceil, w, d)
2489 FLOAT_ROUNDOP(ceil, w, s)
2491 FLOAT_ROUNDOP(floor, l, d)
2492 FLOAT_ROUNDOP(floor, l, s)
2493 FLOAT_ROUNDOP(floor, w, d)
2494 FLOAT_ROUNDOP(floor, w, s)
2495 #undef FLOAR_ROUNDOP
2499 if (!(env->fpu->fcr31 & PARAM1))
2506 if (!(env->fpu->fcr31 & PARAM1))
2513 if (!(env->fpu->fcr31 & PARAM1)) {
2522 if (env->fpu->fcr31 & PARAM1)
2529 if (env->fpu->fcr31 & PARAM1)
2536 if (env->fpu->fcr31 & PARAM1) {
2590 /* operations calling helpers, for s, d and ps */
2591 #define FLOAT_HOP(name) \
2594 CALL_FROM_TB0(do_float_ ## name ## _d); \
2595 DEBUG_FPU_STATE(); \
2600 CALL_FROM_TB0(do_float_ ## name ## _s); \
2601 DEBUG_FPU_STATE(); \
2604 FLOAT_OP(name, ps) \
2606 CALL_FROM_TB0(do_float_ ## name ## _ps); \
2607 DEBUG_FPU_STATE(); \
2620 /* operations calling helpers, for s and d */
2621 #define FLOAT_HOP(name) \
2624 CALL_FROM_TB0(do_float_ ## name ## _d); \
2625 DEBUG_FPU_STATE(); \
2630 CALL_FROM_TB0(do_float_ ## name ## _s); \
2631 DEBUG_FPU_STATE(); \
2638 /* operations calling helpers, for ps */
2639 #define FLOAT_HOP(name) \
2640 FLOAT_OP(name, ps) \
2642 CALL_FROM_TB0(do_float_ ## name ## _ps); \
2643 DEBUG_FPU_STATE(); \
2650 /* ternary operations */
2651 #define FLOAT_TERNOP(name1, name2) \
2652 FLOAT_OP(name1 ## name2, d) \
2654 FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status); \
2655 FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status); \
2656 DEBUG_FPU_STATE(); \
2659 FLOAT_OP(name1 ## name2, s) \
2661 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
2662 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
2663 DEBUG_FPU_STATE(); \
2666 FLOAT_OP(name1 ## name2, ps) \
2668 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
2669 FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \
2670 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
2671 FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \
2672 DEBUG_FPU_STATE(); \
2675 FLOAT_TERNOP(mul, add)
2676 FLOAT_TERNOP(mul, sub)
2679 /* negated ternary operations */
2680 #define FLOAT_NTERNOP(name1, name2) \
2681 FLOAT_OP(n ## name1 ## name2, d) \
2683 FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status); \
2684 FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status); \
2685 FDT2 = float64_chs(FDT2); \
2686 DEBUG_FPU_STATE(); \
2689 FLOAT_OP(n ## name1 ## name2, s) \
2691 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
2692 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
2693 FST2 = float32_chs(FST2); \
2694 DEBUG_FPU_STATE(); \
2697 FLOAT_OP(n ## name1 ## name2, ps) \
2699 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
2700 FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \
2701 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
2702 FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \
2703 FST2 = float32_chs(FST2); \
2704 FSTH2 = float32_chs(FSTH2); \
2705 DEBUG_FPU_STATE(); \
2708 FLOAT_NTERNOP(mul, add)
2709 FLOAT_NTERNOP(mul, sub)
2710 #undef FLOAT_NTERNOP
2712 /* unary operations, modifying fp status */
2713 #define FLOAT_UNOP(name) \
2716 FDT2 = float64_ ## name(FDT0, &env->fpu->fp_status); \
2717 DEBUG_FPU_STATE(); \
2722 FST2 = float32_ ## name(FST0, &env->fpu->fp_status); \
2723 DEBUG_FPU_STATE(); \
2729 /* unary operations, not modifying fp status */
2730 #define FLOAT_UNOP(name) \
2733 FDT2 = float64_ ## name(FDT0); \
2734 DEBUG_FPU_STATE(); \
2739 FST2 = float32_ ## name(FST0); \
2740 DEBUG_FPU_STATE(); \
2743 FLOAT_OP(name, ps) \
2745 FST2 = float32_ ## name(FST0); \
2746 FSTH2 = float32_ ## name(FSTH0); \
2747 DEBUG_FPU_STATE(); \
2781 #ifdef TARGET_WORDS_BIGENDIAN
2789 default: /* unpredictable */
2796 #ifdef CONFIG_SOFTFLOAT
2797 #define clear_invalid() do { \
2798 int flags = get_float_exception_flags(&env->fpu->fp_status); \
2799 flags &= ~float_flag_invalid; \
2800 set_float_exception_flags(flags, &env->fpu->fp_status); \
2803 #define clear_invalid() do { } while(0)
2806 extern void dump_fpu_s(CPUState *env);
2808 #define CMP_OP(fmt, op) \
2809 void OPPROTO op_cmp ## _ ## fmt ## _ ## op(void) \
2811 CALL_FROM_TB1(do_cmp ## _ ## fmt ## _ ## op, PARAM1); \
2812 DEBUG_FPU_STATE(); \
2815 void OPPROTO op_cmpabs ## _ ## fmt ## _ ## op(void) \
2817 CALL_FROM_TB1(do_cmpabs ## _ ## fmt ## _ ## op, PARAM1); \
2818 DEBUG_FPU_STATE(); \
2821 #define CMP_OPS(op) \
2847 T0 = !!(~GET_FP_COND(env->fpu) & (0x1 << PARAM1));
2851 void op_bc1any2f (void)
2853 T0 = !!(~GET_FP_COND(env->fpu) & (0x3 << PARAM1));
2857 void op_bc1any4f (void)
2859 T0 = !!(~GET_FP_COND(env->fpu) & (0xf << PARAM1));
2866 T0 = !!(GET_FP_COND(env->fpu) & (0x1 << PARAM1));
2870 void op_bc1any2t (void)
2872 T0 = !!(GET_FP_COND(env->fpu) & (0x3 << PARAM1));
2876 void op_bc1any4t (void)
2878 T0 = !!(GET_FP_COND(env->fpu) & (0xf << PARAM1));
2883 void op_tlbwi (void)
2885 CALL_FROM_TB0(env->tlb->do_tlbwi);
2889 void op_tlbwr (void)
2891 CALL_FROM_TB0(env->tlb->do_tlbwr);
2897 CALL_FROM_TB0(env->tlb->do_tlbp);
2903 CALL_FROM_TB0(env->tlb->do_tlbr);
2908 #if defined (CONFIG_USER_ONLY)
2909 void op_tls_value (void)
2911 T0 = env->tls_value;
2917 CALL_FROM_TB1(do_pmon, PARAM1);
2923 T0 = env->CP0_Status;
2924 env->CP0_Status = T0 & ~(1 << CP0St_IE);
2925 CALL_FROM_TB1(cpu_mips_update_irq, env);
2931 T0 = env->CP0_Status;
2932 env->CP0_Status = T0 | (1 << CP0St_IE);
2933 CALL_FROM_TB1(cpu_mips_update_irq, env);
2940 CALL_FROM_TB1(do_raise_exception, EXCP_TRAP);
2945 void op_debug (void)
2947 CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG);
2951 void op_set_lladdr (void)
2953 env->CP0_LLAddr = T2;
2957 void debug_pre_eret (void);
2958 void debug_post_eret (void);
2961 if (loglevel & CPU_LOG_EXEC)
2962 CALL_FROM_TB0(debug_pre_eret);
2963 if (env->CP0_Status & (1 << CP0St_ERL)) {
2964 env->PC[env->current_tc] = env->CP0_ErrorEPC;
2965 env->CP0_Status &= ~(1 << CP0St_ERL);
2967 env->PC[env->current_tc] = env->CP0_EPC;
2968 env->CP0_Status &= ~(1 << CP0St_EXL);
2970 CALL_FROM_TB1(compute_hflags, env);
2971 if (loglevel & CPU_LOG_EXEC)
2972 CALL_FROM_TB0(debug_post_eret);
2973 env->CP0_LLAddr = 1;
2977 void op_deret (void)
2979 if (loglevel & CPU_LOG_EXEC)
2980 CALL_FROM_TB0(debug_pre_eret);
2981 env->PC[env->current_tc] = env->CP0_DEPC;
2982 env->hflags &= MIPS_HFLAG_DM;
2983 CALL_FROM_TB1(compute_hflags, env);
2984 if (loglevel & CPU_LOG_EXEC)
2985 CALL_FROM_TB0(debug_post_eret);
2986 env->CP0_LLAddr = 1;
2990 void op_rdhwr_cpunum(void)
2992 if ((env->hflags & MIPS_HFLAG_CP0) ||
2993 (env->CP0_HWREna & (1 << 0)))
2994 T0 = env->CP0_EBase & 0x3ff;
2996 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
3000 void op_rdhwr_synci_step(void)
3002 if ((env->hflags & MIPS_HFLAG_CP0) ||
3003 (env->CP0_HWREna & (1 << 1)))
3004 T0 = env->SYNCI_Step;
3006 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
3010 void op_rdhwr_cc(void)
3012 if ((env->hflags & MIPS_HFLAG_CP0) ||
3013 (env->CP0_HWREna & (1 << 2)))
3014 T0 = env->CP0_Count;
3016 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
3020 void op_rdhwr_ccres(void)
3022 if ((env->hflags & MIPS_HFLAG_CP0) ||
3023 (env->CP0_HWREna & (1 << 3)))
3026 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
3030 void op_save_state (void)
3032 env->hflags = PARAM1;
3036 void op_save_pc (void)
3038 env->PC[env->current_tc] = PARAM1;
3042 #if defined(TARGET_MIPS64)
3043 void op_save_pc64 (void)
3045 env->PC[env->current_tc] = ((uint64_t)PARAM1 << 32) | (uint32_t)PARAM2;
3050 void op_interrupt_restart (void)
3052 if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
3053 !(env->CP0_Status & (1 << CP0St_ERL)) &&
3054 !(env->hflags & MIPS_HFLAG_DM) &&
3055 (env->CP0_Status & (1 << CP0St_IE)) &&
3056 (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask)) {
3057 env->CP0_Cause &= ~(0x1f << CP0Ca_EC);
3058 CALL_FROM_TB1(do_raise_exception, EXCP_EXT_INTERRUPT);
3063 void op_raise_exception (void)
3065 CALL_FROM_TB1(do_raise_exception, PARAM1);
3069 void op_raise_exception_err (void)
3071 CALL_FROM_TB2(do_raise_exception_err, PARAM1, PARAM2);
3075 void op_exit_tb (void)
3084 CALL_FROM_TB1(do_raise_exception, EXCP_HLT);
3088 /* Bitfield operations. */
3091 unsigned int pos = PARAM1;
3092 unsigned int size = PARAM2;
3094 T0 = ((uint32_t)T1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0);
3100 unsigned int pos = PARAM1;
3101 unsigned int size = PARAM2;
3102 target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos;
3104 T0 = (T0 & ~mask) | (((uint32_t)T1 << pos) & mask);
3110 T0 = ((T1 << 8) & ~0x00FF00FF) | ((T1 >> 8) & 0x00FF00FF);
3114 #if defined(TARGET_MIPS64)
3117 unsigned int pos = PARAM1;
3118 unsigned int size = PARAM2;
3120 T0 = (T1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0);
3126 unsigned int pos = PARAM1;
3127 unsigned int size = PARAM2;
3128 target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos;
3130 T0 = (T0 & ~mask) | ((T1 << pos) & mask);
3136 T0 = ((T1 << 8) & ~0x00FF00FF00FF00FFULL) | ((T1 >> 8) & 0x00FF00FF00FF00FFULL);
3142 T0 = ((T1 << 16) & ~0x0000FFFF0000FFFFULL) | ((T1 >> 16) & 0x0000FFFF0000FFFFULL);
3149 T0 = ((T1 & 0xFF) ^ 0x80) - 0x80;
3155 T0 = ((T1 & 0xFFFF) ^ 0x8000) - 0x8000;