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)
696 tmp
= T0
<< (0x40 - (32 + T1
));
697 T0
= (T0
>> (32 + T1
)) | tmp
;
703 T0
= T1
<< (T0
& 0x3F);
709 T0
= (int64_t)T1
>> (T0
& 0x3F);
715 T0
= T1
>> (T0
& 0x3F);
719 void op_drotrv (void)
725 tmp
= T1
<< (0x40 - T0
);
726 T0
= (T1
>> T0
) | tmp
;
743 #endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
744 #endif /* TARGET_MIPS64 */
746 /* 64 bits arithmetic */
747 #if TARGET_LONG_BITS > HOST_LONG_BITS
750 CALL_FROM_TB0(do_mult
);
756 CALL_FROM_TB0(do_multu
);
762 CALL_FROM_TB0(do_madd
);
768 CALL_FROM_TB0(do_maddu
);
774 CALL_FROM_TB0(do_msub
);
780 CALL_FROM_TB0(do_msubu
);
784 #else /* TARGET_LONG_BITS > HOST_LONG_BITS */
786 static always_inline
uint64_t get_HILO (void)
788 return ((uint64_t)env
->HI
[0][env
->current_tc
] << 32) |
789 ((uint64_t)(uint32_t)env
->LO
[0][env
->current_tc
]);
792 static always_inline
void set_HILO (uint64_t HILO
)
794 env
->LO
[0][env
->current_tc
] = (int32_t)(HILO
& 0xFFFFFFFF);
795 env
->HI
[0][env
->current_tc
] = (int32_t)(HILO
>> 32);
800 set_HILO((int64_t)(int32_t)T0
* (int64_t)(int32_t)T1
);
806 set_HILO((uint64_t)(uint32_t)T0
* (uint64_t)(uint32_t)T1
);
814 tmp
= ((int64_t)(int32_t)T0
* (int64_t)(int32_t)T1
);
815 set_HILO((int64_t)get_HILO() + tmp
);
823 tmp
= ((uint64_t)(uint32_t)T0
* (uint64_t)(uint32_t)T1
);
824 set_HILO(get_HILO() + tmp
);
832 tmp
= ((int64_t)(int32_t)T0
* (int64_t)(int32_t)T1
);
833 set_HILO((int64_t)get_HILO() - tmp
);
841 tmp
= ((uint64_t)(uint32_t)T0
* (uint64_t)(uint32_t)T1
);
842 set_HILO(get_HILO() - tmp
);
845 #endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
847 #if defined(TARGET_MIPS64)
850 CALL_FROM_TB4(muls64
, &(env
->LO
[0][env
->current_tc
]), &(env
->HI
[0][env
->current_tc
]), T0
, T1
);
854 void op_dmultu (void)
856 CALL_FROM_TB4(mulu64
, &(env
->LO
[0][env
->current_tc
]), &(env
->HI
[0][env
->current_tc
]), T0
, T1
);
861 /* Conditional moves */
865 env
->gpr
[PARAM1
][env
->current_tc
] = T0
;
872 env
->gpr
[PARAM1
][env
->current_tc
] = T0
;
878 if (!(env
->fpu
->fcr31
& PARAM1
))
885 if (env
->fpu
->fcr31
& PARAM1
)
891 #define OP_COND(name, cond) \
892 void glue(op_, name) (void) \
902 OP_COND(eq
, T0
== T1
);
903 OP_COND(ne
, T0
!= T1
);
904 OP_COND(ge
, (target_long
)T0
>= (target_long
)T1
);
905 OP_COND(geu
, T0
>= T1
);
906 OP_COND(lt
, (target_long
)T0
< (target_long
)T1
);
907 OP_COND(ltu
, T0
< T1
);
908 OP_COND(gez
, (target_long
)T0
>= 0);
909 OP_COND(gtz
, (target_long
)T0
> 0);
910 OP_COND(lez
, (target_long
)T0
<= 0);
911 OP_COND(ltz
, (target_long
)T0
< 0);
914 void OPPROTO
op_goto_tb0(void)
916 GOTO_TB(op_goto_tb0
, PARAM1
, 0);
920 void OPPROTO
op_goto_tb1(void)
922 GOTO_TB(op_goto_tb1
, PARAM1
, 1);
926 /* Branch to register */
927 void op_save_breg_target (void)
933 void op_restore_breg_target (void)
941 env
->PC
[env
->current_tc
] = T2
;
945 void op_save_btarget (void)
947 env
->btarget
= PARAM1
;
951 #if defined(TARGET_MIPS64)
952 void op_save_btarget64 (void)
954 env
->btarget
= ((uint64_t)PARAM1
<< 32) | (uint32_t)PARAM2
;
959 /* Conditional branch */
960 void op_set_bcond (void)
966 void op_save_bcond (void)
972 void op_restore_bcond (void)
978 void op_jnz_T2 (void)
986 void op_mfc0_index (void)
992 void op_mfc0_mvpcontrol (void)
994 T0
= env
->mvp
->CP0_MVPControl
;
998 void op_mfc0_mvpconf0 (void)
1000 T0
= env
->mvp
->CP0_MVPConf0
;
1004 void op_mfc0_mvpconf1 (void)
1006 T0
= env
->mvp
->CP0_MVPConf1
;
1010 void op_mfc0_random (void)
1012 CALL_FROM_TB0(do_mfc0_random
);
1016 void op_mfc0_vpecontrol (void)
1018 T0
= env
->CP0_VPEControl
;
1022 void op_mfc0_vpeconf0 (void)
1024 T0
= env
->CP0_VPEConf0
;
1028 void op_mfc0_vpeconf1 (void)
1030 T0
= env
->CP0_VPEConf1
;
1034 void op_mfc0_yqmask (void)
1036 T0
= env
->CP0_YQMask
;
1040 void op_mfc0_vpeschedule (void)
1042 T0
= env
->CP0_VPESchedule
;
1046 void op_mfc0_vpeschefback (void)
1048 T0
= env
->CP0_VPEScheFBack
;
1052 void op_mfc0_vpeopt (void)
1054 T0
= env
->CP0_VPEOpt
;
1058 void op_mfc0_entrylo0 (void)
1060 T0
= (int32_t)env
->CP0_EntryLo0
;
1064 void op_mfc0_tcstatus (void)
1066 T0
= env
->CP0_TCStatus
[env
->current_tc
];
1070 void op_mftc0_tcstatus(void)
1072 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1074 T0
= env
->CP0_TCStatus
[other_tc
];
1078 void op_mfc0_tcbind (void)
1080 T0
= env
->CP0_TCBind
[env
->current_tc
];
1084 void op_mftc0_tcbind(void)
1086 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1088 T0
= env
->CP0_TCBind
[other_tc
];
1092 void op_mfc0_tcrestart (void)
1094 T0
= env
->PC
[env
->current_tc
];
1098 void op_mftc0_tcrestart(void)
1100 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1102 T0
= env
->PC
[other_tc
];
1106 void op_mfc0_tchalt (void)
1108 T0
= env
->CP0_TCHalt
[env
->current_tc
];
1112 void op_mftc0_tchalt(void)
1114 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1116 T0
= env
->CP0_TCHalt
[other_tc
];
1120 void op_mfc0_tccontext (void)
1122 T0
= env
->CP0_TCContext
[env
->current_tc
];
1126 void op_mftc0_tccontext(void)
1128 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1130 T0
= env
->CP0_TCContext
[other_tc
];
1134 void op_mfc0_tcschedule (void)
1136 T0
= env
->CP0_TCSchedule
[env
->current_tc
];
1140 void op_mftc0_tcschedule(void)
1142 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1144 T0
= env
->CP0_TCSchedule
[other_tc
];
1148 void op_mfc0_tcschefback (void)
1150 T0
= env
->CP0_TCScheFBack
[env
->current_tc
];
1154 void op_mftc0_tcschefback(void)
1156 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1158 T0
= env
->CP0_TCScheFBack
[other_tc
];
1162 void op_mfc0_entrylo1 (void)
1164 T0
= (int32_t)env
->CP0_EntryLo1
;
1168 void op_mfc0_context (void)
1170 T0
= (int32_t)env
->CP0_Context
;
1174 void op_mfc0_pagemask (void)
1176 T0
= env
->CP0_PageMask
;
1180 void op_mfc0_pagegrain (void)
1182 T0
= env
->CP0_PageGrain
;
1186 void op_mfc0_wired (void)
1188 T0
= env
->CP0_Wired
;
1192 void op_mfc0_srsconf0 (void)
1194 T0
= env
->CP0_SRSConf0
;
1198 void op_mfc0_srsconf1 (void)
1200 T0
= env
->CP0_SRSConf1
;
1204 void op_mfc0_srsconf2 (void)
1206 T0
= env
->CP0_SRSConf2
;
1210 void op_mfc0_srsconf3 (void)
1212 T0
= env
->CP0_SRSConf3
;
1216 void op_mfc0_srsconf4 (void)
1218 T0
= env
->CP0_SRSConf4
;
1222 void op_mfc0_hwrena (void)
1224 T0
= env
->CP0_HWREna
;
1228 void op_mfc0_badvaddr (void)
1230 T0
= (int32_t)env
->CP0_BadVAddr
;
1234 void op_mfc0_count (void)
1236 CALL_FROM_TB0(do_mfc0_count
);
1240 void op_mfc0_entryhi (void)
1242 T0
= (int32_t)env
->CP0_EntryHi
;
1246 void op_mftc0_entryhi(void)
1248 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1250 T0
= (env
->CP0_EntryHi
& ~0xff) | (env
->CP0_TCStatus
[other_tc
] & 0xff);
1254 void op_mfc0_compare (void)
1256 T0
= env
->CP0_Compare
;
1260 void op_mfc0_status (void)
1262 T0
= env
->CP0_Status
;
1266 void op_mftc0_status(void)
1268 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1269 uint32_t tcstatus
= env
->CP0_TCStatus
[other_tc
];
1271 T0
= env
->CP0_Status
& ~0xf1000018;
1272 T0
|= tcstatus
& (0xf << CP0TCSt_TCU0
);
1273 T0
|= (tcstatus
& (1 << CP0TCSt_TMX
)) >> (CP0TCSt_TMX
- CP0St_MX
);
1274 T0
|= (tcstatus
& (0x3 << CP0TCSt_TKSU
)) >> (CP0TCSt_TKSU
- CP0St_KSU
);
1278 void op_mfc0_intctl (void)
1280 T0
= env
->CP0_IntCtl
;
1284 void op_mfc0_srsctl (void)
1286 T0
= env
->CP0_SRSCtl
;
1290 void op_mfc0_srsmap (void)
1292 T0
= env
->CP0_SRSMap
;
1296 void op_mfc0_cause (void)
1298 T0
= env
->CP0_Cause
;
1302 void op_mfc0_epc (void)
1304 T0
= (int32_t)env
->CP0_EPC
;
1308 void op_mfc0_prid (void)
1314 void op_mfc0_ebase (void)
1316 T0
= env
->CP0_EBase
;
1320 void op_mfc0_config0 (void)
1322 T0
= env
->CP0_Config0
;
1326 void op_mfc0_config1 (void)
1328 T0
= env
->CP0_Config1
;
1332 void op_mfc0_config2 (void)
1334 T0
= env
->CP0_Config2
;
1338 void op_mfc0_config3 (void)
1340 T0
= env
->CP0_Config3
;
1344 void op_mfc0_config6 (void)
1346 T0
= env
->CP0_Config6
;
1350 void op_mfc0_config7 (void)
1352 T0
= env
->CP0_Config7
;
1356 void op_mfc0_lladdr (void)
1358 T0
= (int32_t)env
->CP0_LLAddr
>> 4;
1362 void op_mfc0_watchlo (void)
1364 T0
= (int32_t)env
->CP0_WatchLo
[PARAM1
];
1368 void op_mfc0_watchhi (void)
1370 T0
= env
->CP0_WatchHi
[PARAM1
];
1374 void op_mfc0_xcontext (void)
1376 T0
= (int32_t)env
->CP0_XContext
;
1380 void op_mfc0_framemask (void)
1382 T0
= env
->CP0_Framemask
;
1386 void op_mfc0_debug (void)
1388 T0
= env
->CP0_Debug
;
1389 if (env
->hflags
& MIPS_HFLAG_DM
)
1390 T0
|= 1 << CP0DB_DM
;
1394 void op_mftc0_debug(void)
1396 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1398 /* XXX: Might be wrong, check with EJTAG spec. */
1399 T0
= (env
->CP0_Debug
& ~((1 << CP0DB_SSt
) | (1 << CP0DB_Halt
))) |
1400 (env
->CP0_Debug_tcstatus
[other_tc
] &
1401 ((1 << CP0DB_SSt
) | (1 << CP0DB_Halt
)));
1405 void op_mfc0_depc (void)
1407 T0
= (int32_t)env
->CP0_DEPC
;
1411 void op_mfc0_performance0 (void)
1413 T0
= env
->CP0_Performance0
;
1417 void op_mfc0_taglo (void)
1419 T0
= env
->CP0_TagLo
;
1423 void op_mfc0_datalo (void)
1425 T0
= env
->CP0_DataLo
;
1429 void op_mfc0_taghi (void)
1431 T0
= env
->CP0_TagHi
;
1435 void op_mfc0_datahi (void)
1437 T0
= env
->CP0_DataHi
;
1441 void op_mfc0_errorepc (void)
1443 T0
= (int32_t)env
->CP0_ErrorEPC
;
1447 void op_mfc0_desave (void)
1449 T0
= env
->CP0_DESAVE
;
1453 void op_mtc0_index (void)
1456 unsigned int tmp
= env
->tlb
->nb_tlb
;
1462 env
->CP0_Index
= (env
->CP0_Index
& 0x80000000) | (T0
& (num
- 1));
1466 void op_mtc0_mvpcontrol (void)
1471 if (env
->CP0_VPEConf0
& (1 << CP0VPEC0_MVP
))
1472 mask
|= (1 << CP0MVPCo_CPA
) | (1 << CP0MVPCo_VPC
) |
1473 (1 << CP0MVPCo_EVP
);
1474 if (env
->mvp
->CP0_MVPControl
& (1 << CP0MVPCo_VPC
))
1475 mask
|= (1 << CP0MVPCo_STLB
);
1476 newval
= (env
->mvp
->CP0_MVPControl
& ~mask
) | (T0
& mask
);
1478 // TODO: Enable/disable shared TLB, enable/disable VPEs.
1480 env
->mvp
->CP0_MVPControl
= newval
;
1484 void op_mtc0_vpecontrol (void)
1489 mask
= (1 << CP0VPECo_YSI
) | (1 << CP0VPECo_GSI
) |
1490 (1 << CP0VPECo_TE
) | (0xff << CP0VPECo_TargTC
);
1491 newval
= (env
->CP0_VPEControl
& ~mask
) | (T0
& mask
);
1493 /* Yield scheduler intercept not implemented. */
1494 /* Gating storage scheduler intercept not implemented. */
1496 // TODO: Enable/disable TCs.
1498 env
->CP0_VPEControl
= newval
;
1502 void op_mtc0_vpeconf0 (void)
1507 if (env
->CP0_VPEConf0
& (1 << CP0VPEC0_MVP
)) {
1508 if (env
->CP0_VPEConf0
& (1 << CP0VPEC0_VPA
))
1509 mask
|= (0xff << CP0VPEC0_XTC
);
1510 mask
|= (1 << CP0VPEC0_MVP
) | (1 << CP0VPEC0_VPA
);
1512 newval
= (env
->CP0_VPEConf0
& ~mask
) | (T0
& mask
);
1514 // TODO: TC exclusive handling due to ERL/EXL.
1516 env
->CP0_VPEConf0
= newval
;
1520 void op_mtc0_vpeconf1 (void)
1525 if (env
->mvp
->CP0_MVPControl
& (1 << CP0MVPCo_VPC
))
1526 mask
|= (0xff << CP0VPEC1_NCX
) | (0xff << CP0VPEC1_NCP2
) |
1527 (0xff << CP0VPEC1_NCP1
);
1528 newval
= (env
->CP0_VPEConf1
& ~mask
) | (T0
& mask
);
1530 /* UDI not implemented. */
1531 /* CP2 not implemented. */
1533 // TODO: Handle FPU (CP1) binding.
1535 env
->CP0_VPEConf1
= newval
;
1539 void op_mtc0_yqmask (void)
1541 /* Yield qualifier inputs not implemented. */
1542 env
->CP0_YQMask
= 0x00000000;
1546 void op_mtc0_vpeschedule (void)
1548 env
->CP0_VPESchedule
= T0
;
1552 void op_mtc0_vpeschefback (void)
1554 env
->CP0_VPEScheFBack
= T0
;
1558 void op_mtc0_vpeopt (void)
1560 env
->CP0_VPEOpt
= T0
& 0x0000ffff;
1564 void op_mtc0_entrylo0 (void)
1566 /* Large physaddr not implemented */
1567 /* 1k pages not implemented */
1568 env
->CP0_EntryLo0
= T0
& 0x3FFFFFFF;
1572 void op_mtc0_tcstatus (void)
1574 uint32_t mask
= env
->CP0_TCStatus_rw_bitmask
;
1577 newval
= (env
->CP0_TCStatus
[env
->current_tc
] & ~mask
) | (T0
& mask
);
1579 // TODO: Sync with CP0_Status.
1581 env
->CP0_TCStatus
[env
->current_tc
] = newval
;
1585 void op_mttc0_tcstatus (void)
1587 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1589 // TODO: Sync with CP0_Status.
1591 env
->CP0_TCStatus
[other_tc
] = T0
;
1595 void op_mtc0_tcbind (void)
1597 uint32_t mask
= (1 << CP0TCBd_TBE
);
1600 if (env
->mvp
->CP0_MVPControl
& (1 << CP0MVPCo_VPC
))
1601 mask
|= (1 << CP0TCBd_CurVPE
);
1602 newval
= (env
->CP0_TCBind
[env
->current_tc
] & ~mask
) | (T0
& mask
);
1603 env
->CP0_TCBind
[env
->current_tc
] = newval
;
1607 void op_mttc0_tcbind (void)
1609 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1610 uint32_t mask
= (1 << CP0TCBd_TBE
);
1613 if (env
->mvp
->CP0_MVPControl
& (1 << CP0MVPCo_VPC
))
1614 mask
|= (1 << CP0TCBd_CurVPE
);
1615 newval
= (env
->CP0_TCBind
[other_tc
] & ~mask
) | (T0
& mask
);
1616 env
->CP0_TCBind
[other_tc
] = newval
;
1620 void op_mtc0_tcrestart (void)
1622 env
->PC
[env
->current_tc
] = T0
;
1623 env
->CP0_TCStatus
[env
->current_tc
] &= ~(1 << CP0TCSt_TDS
);
1624 env
->CP0_LLAddr
= 0ULL;
1625 /* MIPS16 not implemented. */
1629 void op_mttc0_tcrestart (void)
1631 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1633 env
->PC
[other_tc
] = T0
;
1634 env
->CP0_TCStatus
[other_tc
] &= ~(1 << CP0TCSt_TDS
);
1635 env
->CP0_LLAddr
= 0ULL;
1636 /* MIPS16 not implemented. */
1640 void op_mtc0_tchalt (void)
1642 env
->CP0_TCHalt
[env
->current_tc
] = T0
& 0x1;
1644 // TODO: Halt TC / Restart (if allocated+active) TC.
1649 void op_mttc0_tchalt (void)
1651 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1653 // TODO: Halt TC / Restart (if allocated+active) TC.
1655 env
->CP0_TCHalt
[other_tc
] = T0
;
1659 void op_mtc0_tccontext (void)
1661 env
->CP0_TCContext
[env
->current_tc
] = T0
;
1665 void op_mttc0_tccontext (void)
1667 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1669 env
->CP0_TCContext
[other_tc
] = T0
;
1673 void op_mtc0_tcschedule (void)
1675 env
->CP0_TCSchedule
[env
->current_tc
] = T0
;
1679 void op_mttc0_tcschedule (void)
1681 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1683 env
->CP0_TCSchedule
[other_tc
] = T0
;
1687 void op_mtc0_tcschefback (void)
1689 env
->CP0_TCScheFBack
[env
->current_tc
] = T0
;
1693 void op_mttc0_tcschefback (void)
1695 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1697 env
->CP0_TCScheFBack
[other_tc
] = T0
;
1701 void op_mtc0_entrylo1 (void)
1703 /* Large physaddr not implemented */
1704 /* 1k pages not implemented */
1705 env
->CP0_EntryLo1
= T0
& 0x3FFFFFFF;
1709 void op_mtc0_context (void)
1711 env
->CP0_Context
= (env
->CP0_Context
& 0x007FFFFF) | (T0
& ~0x007FFFFF);
1715 void op_mtc0_pagemask (void)
1717 /* 1k pages not implemented */
1718 env
->CP0_PageMask
= T0
& (0x1FFFFFFF & (TARGET_PAGE_MASK
<< 1));
1722 void op_mtc0_pagegrain (void)
1724 /* SmartMIPS not implemented */
1725 /* Large physaddr not implemented */
1726 /* 1k pages not implemented */
1727 env
->CP0_PageGrain
= 0;
1731 void op_mtc0_wired (void)
1733 env
->CP0_Wired
= T0
% env
->tlb
->nb_tlb
;
1737 void op_mtc0_srsconf0 (void)
1739 env
->CP0_SRSConf0
|= T0
& env
->CP0_SRSConf0_rw_bitmask
;
1743 void op_mtc0_srsconf1 (void)
1745 env
->CP0_SRSConf1
|= T0
& env
->CP0_SRSConf1_rw_bitmask
;
1749 void op_mtc0_srsconf2 (void)
1751 env
->CP0_SRSConf2
|= T0
& env
->CP0_SRSConf2_rw_bitmask
;
1755 void op_mtc0_srsconf3 (void)
1757 env
->CP0_SRSConf3
|= T0
& env
->CP0_SRSConf3_rw_bitmask
;
1761 void op_mtc0_srsconf4 (void)
1763 env
->CP0_SRSConf4
|= T0
& env
->CP0_SRSConf4_rw_bitmask
;
1767 void op_mtc0_hwrena (void)
1769 env
->CP0_HWREna
= T0
& 0x0000000F;
1773 void op_mtc0_count (void)
1775 CALL_FROM_TB2(cpu_mips_store_count
, env
, T0
);
1779 void op_mtc0_entryhi (void)
1781 target_ulong old
, val
;
1783 /* 1k pages not implemented */
1784 val
= T0
& ((TARGET_PAGE_MASK
<< 1) | 0xFF);
1785 #if defined(TARGET_MIPS64)
1786 val
&= env
->SEGMask
;
1788 old
= env
->CP0_EntryHi
;
1789 env
->CP0_EntryHi
= val
;
1790 if (env
->CP0_Config3
& (1 << CP0C3_MT
)) {
1791 uint32_t tcst
= env
->CP0_TCStatus
[env
->current_tc
] & ~0xff;
1792 env
->CP0_TCStatus
[env
->current_tc
] = tcst
| (val
& 0xff);
1794 /* If the ASID changes, flush qemu's TLB. */
1795 if ((old
& 0xFF) != (val
& 0xFF))
1796 CALL_FROM_TB2(cpu_mips_tlb_flush
, env
, 1);
1800 void op_mttc0_entryhi(void)
1802 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1804 env
->CP0_EntryHi
= (env
->CP0_EntryHi
& 0xff) | (T0
& ~0xff);
1805 env
->CP0_TCStatus
[other_tc
] = (env
->CP0_TCStatus
[other_tc
] & ~0xff) | (T0
& 0xff);
1809 void op_mtc0_compare (void)
1811 CALL_FROM_TB2(cpu_mips_store_compare
, env
, T0
);
1815 void op_mtc0_status (void)
1818 uint32_t mask
= env
->CP0_Status_rw_bitmask
;
1821 old
= env
->CP0_Status
;
1822 env
->CP0_Status
= (env
->CP0_Status
& ~mask
) | val
;
1823 CALL_FROM_TB1(compute_hflags
, env
);
1824 if (loglevel
& CPU_LOG_EXEC
)
1825 CALL_FROM_TB2(do_mtc0_status_debug
, old
, val
);
1826 CALL_FROM_TB1(cpu_mips_update_irq
, env
);
1830 void op_mttc0_status(void)
1832 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1833 uint32_t tcstatus
= env
->CP0_TCStatus
[other_tc
];
1835 env
->CP0_Status
= T0
& ~0xf1000018;
1836 tcstatus
= (tcstatus
& ~(0xf << CP0TCSt_TCU0
)) | (T0
& (0xf << CP0St_CU0
));
1837 tcstatus
= (tcstatus
& ~(1 << CP0TCSt_TMX
)) | ((T0
& (1 << CP0St_MX
)) << (CP0TCSt_TMX
- CP0St_MX
));
1838 tcstatus
= (tcstatus
& ~(0x3 << CP0TCSt_TKSU
)) | ((T0
& (0x3 << CP0St_KSU
)) << (CP0TCSt_TKSU
- CP0St_KSU
));
1839 env
->CP0_TCStatus
[other_tc
] = tcstatus
;
1843 void op_mtc0_intctl (void)
1845 /* vectored interrupts not implemented, no performance counters. */
1846 env
->CP0_IntCtl
= (env
->CP0_IntCtl
& ~0x000002e0) | (T0
& 0x000002e0);
1850 void op_mtc0_srsctl (void)
1852 uint32_t mask
= (0xf << CP0SRSCtl_ESS
) | (0xf << CP0SRSCtl_PSS
);
1853 env
->CP0_SRSCtl
= (env
->CP0_SRSCtl
& ~mask
) | (T0
& mask
);
1857 void op_mtc0_srsmap (void)
1859 env
->CP0_SRSMap
= T0
;
1863 void op_mtc0_cause (void)
1865 uint32_t mask
= 0x00C00300;
1866 uint32_t old
= env
->CP0_Cause
;
1868 if (env
->insn_flags
& ISA_MIPS32R2
)
1869 mask
|= 1 << CP0Ca_DC
;
1871 env
->CP0_Cause
= (env
->CP0_Cause
& ~mask
) | (T0
& mask
);
1873 if ((old
^ env
->CP0_Cause
) & (1 << CP0Ca_DC
)) {
1874 if (env
->CP0_Cause
& (1 << CP0Ca_DC
))
1875 CALL_FROM_TB1(cpu_mips_stop_count
, env
);
1877 CALL_FROM_TB1(cpu_mips_start_count
, env
);
1880 /* Handle the software interrupt as an hardware one, as they
1882 if (T0
& CP0Ca_IP_mask
) {
1883 CALL_FROM_TB1(cpu_mips_update_irq
, env
);
1888 void op_mtc0_epc (void)
1894 void op_mtc0_ebase (void)
1896 /* vectored interrupts not implemented */
1897 /* Multi-CPU not implemented */
1898 env
->CP0_EBase
= 0x80000000 | (T0
& 0x3FFFF000);
1902 void op_mtc0_config0 (void)
1904 env
->CP0_Config0
= (env
->CP0_Config0
& 0x81FFFFF8) | (T0
& 0x00000007);
1908 void op_mtc0_config2 (void)
1910 /* tertiary/secondary caches not implemented */
1911 env
->CP0_Config2
= (env
->CP0_Config2
& 0x8FFF0FFF);
1915 void op_mtc0_watchlo (void)
1917 /* Watch exceptions for instructions, data loads, data stores
1919 env
->CP0_WatchLo
[PARAM1
] = (T0
& ~0x7);
1923 void op_mtc0_watchhi (void)
1925 env
->CP0_WatchHi
[PARAM1
] = (T0
& 0x40FF0FF8);
1926 env
->CP0_WatchHi
[PARAM1
] &= ~(env
->CP0_WatchHi
[PARAM1
] & T0
& 0x7);
1930 void op_mtc0_xcontext (void)
1932 target_ulong mask
= (1ULL << (env
->SEGBITS
- 7)) - 1;
1933 env
->CP0_XContext
= (env
->CP0_XContext
& mask
) | (T0
& ~mask
);
1937 void op_mtc0_framemask (void)
1939 env
->CP0_Framemask
= T0
; /* XXX */
1943 void op_mtc0_debug (void)
1945 env
->CP0_Debug
= (env
->CP0_Debug
& 0x8C03FC1F) | (T0
& 0x13300120);
1946 if (T0
& (1 << CP0DB_DM
))
1947 env
->hflags
|= MIPS_HFLAG_DM
;
1949 env
->hflags
&= ~MIPS_HFLAG_DM
;
1953 void op_mttc0_debug(void)
1955 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1957 /* XXX: Might be wrong, check with EJTAG spec. */
1958 env
->CP0_Debug_tcstatus
[other_tc
] = T0
& ((1 << CP0DB_SSt
) | (1 << CP0DB_Halt
));
1959 env
->CP0_Debug
= (env
->CP0_Debug
& ((1 << CP0DB_SSt
) | (1 << CP0DB_Halt
))) |
1960 (T0
& ~((1 << CP0DB_SSt
) | (1 << CP0DB_Halt
)));
1964 void op_mtc0_depc (void)
1970 void op_mtc0_performance0 (void)
1972 env
->CP0_Performance0
= T0
& 0x000007ff;
1976 void op_mtc0_taglo (void)
1978 env
->CP0_TagLo
= T0
& 0xFFFFFCF6;
1982 void op_mtc0_datalo (void)
1984 env
->CP0_DataLo
= T0
; /* XXX */
1988 void op_mtc0_taghi (void)
1990 env
->CP0_TagHi
= T0
; /* XXX */
1994 void op_mtc0_datahi (void)
1996 env
->CP0_DataHi
= T0
; /* XXX */
2000 void op_mtc0_errorepc (void)
2002 env
->CP0_ErrorEPC
= T0
;
2006 void op_mtc0_desave (void)
2008 env
->CP0_DESAVE
= T0
;
2012 #if defined(TARGET_MIPS64)
2013 void op_dmfc0_yqmask (void)
2015 T0
= env
->CP0_YQMask
;
2019 void op_dmfc0_vpeschedule (void)
2021 T0
= env
->CP0_VPESchedule
;
2025 void op_dmfc0_vpeschefback (void)
2027 T0
= env
->CP0_VPEScheFBack
;
2031 void op_dmfc0_entrylo0 (void)
2033 T0
= env
->CP0_EntryLo0
;
2037 void op_dmfc0_tcrestart (void)
2039 T0
= env
->PC
[env
->current_tc
];
2043 void op_dmfc0_tchalt (void)
2045 T0
= env
->CP0_TCHalt
[env
->current_tc
];
2049 void op_dmfc0_tccontext (void)
2051 T0
= env
->CP0_TCContext
[env
->current_tc
];
2055 void op_dmfc0_tcschedule (void)
2057 T0
= env
->CP0_TCSchedule
[env
->current_tc
];
2061 void op_dmfc0_tcschefback (void)
2063 T0
= env
->CP0_TCScheFBack
[env
->current_tc
];
2067 void op_dmfc0_entrylo1 (void)
2069 T0
= env
->CP0_EntryLo1
;
2073 void op_dmfc0_context (void)
2075 T0
= env
->CP0_Context
;
2079 void op_dmfc0_badvaddr (void)
2081 T0
= env
->CP0_BadVAddr
;
2085 void op_dmfc0_entryhi (void)
2087 T0
= env
->CP0_EntryHi
;
2091 void op_dmfc0_epc (void)
2097 void op_dmfc0_lladdr (void)
2099 T0
= env
->CP0_LLAddr
>> 4;
2103 void op_dmfc0_watchlo (void)
2105 T0
= env
->CP0_WatchLo
[PARAM1
];
2109 void op_dmfc0_xcontext (void)
2111 T0
= env
->CP0_XContext
;
2115 void op_dmfc0_depc (void)
2121 void op_dmfc0_errorepc (void)
2123 T0
= env
->CP0_ErrorEPC
;
2126 #endif /* TARGET_MIPS64 */
2128 /* MIPS MT functions */
2129 void op_mftgpr(void)
2131 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
2133 T0
= env
->gpr
[PARAM1
][other_tc
];
2139 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
2141 T0
= env
->LO
[PARAM1
][other_tc
];
2147 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
2149 T0
= env
->HI
[PARAM1
][other_tc
];
2153 void op_mftacx(void)
2155 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
2157 T0
= env
->ACX
[PARAM1
][other_tc
];
2161 void op_mftdsp(void)
2163 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
2165 T0
= env
->DSPControl
[other_tc
];
2169 void op_mttgpr(void)
2171 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
2173 T0
= env
->gpr
[PARAM1
][other_tc
];
2179 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
2181 T0
= env
->LO
[PARAM1
][other_tc
];
2187 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
2189 T0
= env
->HI
[PARAM1
][other_tc
];
2193 void op_mttacx(void)
2195 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
2197 T0
= env
->ACX
[PARAM1
][other_tc
];
2201 void op_mttdsp(void)
2203 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
2205 T0
= env
->DSPControl
[other_tc
];
2246 // TODO: store to TC register
2253 /* No scheduling policy implemented. */
2255 if (env
->CP0_VPEControl
& (1 << CP0VPECo_YSI
) &&
2256 env
->CP0_TCStatus
[env
->current_tc
] & (1 << CP0TCSt_DT
)) {
2257 env
->CP0_VPEControl
&= ~(0x7 << CP0VPECo_EXCPT
);
2258 env
->CP0_VPEControl
|= 4 << CP0VPECo_EXCPT
;
2259 CALL_FROM_TB1(do_raise_exception
, EXCP_THREAD
);
2262 } else if (T0
== 0) {
2263 if (0 /* TODO: TC underflow */) {
2264 env
->CP0_VPEControl
&= ~(0x7 << CP0VPECo_EXCPT
);
2265 CALL_FROM_TB1(do_raise_exception
, EXCP_THREAD
);
2267 // TODO: Deallocate TC
2269 } else if (T0
> 0) {
2270 /* Yield qualifier inputs not implemented. */
2271 env
->CP0_VPEControl
&= ~(0x7 << CP0VPECo_EXCPT
);
2272 env
->CP0_VPEControl
|= 2 << CP0VPECo_EXCPT
;
2273 CALL_FROM_TB1(do_raise_exception
, EXCP_THREAD
);
2275 T0
= env
->CP0_YQMask
;
2281 # define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env)
2283 # define DEBUG_FPU_STATE() do { } while(0)
2288 CALL_FROM_TB1(do_cfc1
, PARAM1
);
2295 CALL_FROM_TB1(do_ctc1
, PARAM1
);
2314 void op_dmfc1 (void)
2321 void op_dmtc1 (void)
2328 void op_mfhc1 (void)
2335 void op_mthc1 (void)
2343 Single precition routines have a "s" suffix, double precision a
2344 "d" suffix, 32bit integer "w", 64bit integer "l", paired singe "ps",
2345 paired single lowwer "pl", paired single upper "pu". */
2347 #define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void)
2351 CALL_FROM_TB0(do_float_cvtd_s
);
2357 CALL_FROM_TB0(do_float_cvtd_w
);
2363 CALL_FROM_TB0(do_float_cvtd_l
);
2369 CALL_FROM_TB0(do_float_cvtl_d
);
2375 CALL_FROM_TB0(do_float_cvtl_s
);
2388 CALL_FROM_TB0(do_float_cvtps_pw
);
2394 CALL_FROM_TB0(do_float_cvtpw_ps
);
2400 CALL_FROM_TB0(do_float_cvts_d
);
2406 CALL_FROM_TB0(do_float_cvts_w
);
2412 CALL_FROM_TB0(do_float_cvts_l
);
2418 CALL_FROM_TB0(do_float_cvts_pl
);
2424 CALL_FROM_TB0(do_float_cvts_pu
);
2430 CALL_FROM_TB0(do_float_cvtw_s
);
2436 CALL_FROM_TB0(do_float_cvtw_d
);
2443 DT2
= ((uint64_t)WT0
<< 32) | WT1
;
2449 DT2
= ((uint64_t)WT0
<< 32) | WTH1
;
2455 DT2
= ((uint64_t)WTH0
<< 32) | WT1
;
2461 DT2
= ((uint64_t)WTH0
<< 32) | WTH1
;
2466 #define FLOAT_ROUNDOP(op, ttype, stype) \
2467 FLOAT_OP(op ## ttype, stype) \
2469 CALL_FROM_TB0(do_float_ ## op ## ttype ## _ ## stype); \
2470 DEBUG_FPU_STATE(); \
2474 FLOAT_ROUNDOP(round
, l
, d
)
2475 FLOAT_ROUNDOP(round
, l
, s
)
2476 FLOAT_ROUNDOP(round
, w
, d
)
2477 FLOAT_ROUNDOP(round
, w
, s
)
2479 FLOAT_ROUNDOP(trunc
, l
, d
)
2480 FLOAT_ROUNDOP(trunc
, l
, s
)
2481 FLOAT_ROUNDOP(trunc
, w
, d
)
2482 FLOAT_ROUNDOP(trunc
, w
, s
)
2484 FLOAT_ROUNDOP(ceil
, l
, d
)
2485 FLOAT_ROUNDOP(ceil
, l
, s
)
2486 FLOAT_ROUNDOP(ceil
, w
, d
)
2487 FLOAT_ROUNDOP(ceil
, w
, s
)
2489 FLOAT_ROUNDOP(floor
, l
, d
)
2490 FLOAT_ROUNDOP(floor
, l
, s
)
2491 FLOAT_ROUNDOP(floor
, w
, d
)
2492 FLOAT_ROUNDOP(floor
, w
, s
)
2493 #undef FLOAR_ROUNDOP
2497 if (!(env
->fpu
->fcr31
& PARAM1
))
2504 if (!(env
->fpu
->fcr31
& PARAM1
))
2511 if (!(env
->fpu
->fcr31
& PARAM1
)) {
2520 if (env
->fpu
->fcr31
& PARAM1
)
2527 if (env
->fpu
->fcr31
& PARAM1
)
2534 if (env
->fpu
->fcr31
& PARAM1
) {
2588 /* operations calling helpers, for s, d and ps */
2589 #define FLOAT_HOP(name) \
2592 CALL_FROM_TB0(do_float_ ## name ## _d); \
2593 DEBUG_FPU_STATE(); \
2598 CALL_FROM_TB0(do_float_ ## name ## _s); \
2599 DEBUG_FPU_STATE(); \
2602 FLOAT_OP(name, ps) \
2604 CALL_FROM_TB0(do_float_ ## name ## _ps); \
2605 DEBUG_FPU_STATE(); \
2618 /* operations calling helpers, for s and d */
2619 #define FLOAT_HOP(name) \
2622 CALL_FROM_TB0(do_float_ ## name ## _d); \
2623 DEBUG_FPU_STATE(); \
2628 CALL_FROM_TB0(do_float_ ## name ## _s); \
2629 DEBUG_FPU_STATE(); \
2636 /* operations calling helpers, for ps */
2637 #define FLOAT_HOP(name) \
2638 FLOAT_OP(name, ps) \
2640 CALL_FROM_TB0(do_float_ ## name ## _ps); \
2641 DEBUG_FPU_STATE(); \
2648 /* ternary operations */
2649 #define FLOAT_TERNOP(name1, name2) \
2650 FLOAT_OP(name1 ## name2, d) \
2652 FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status); \
2653 FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status); \
2654 DEBUG_FPU_STATE(); \
2657 FLOAT_OP(name1 ## name2, s) \
2659 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
2660 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
2661 DEBUG_FPU_STATE(); \
2664 FLOAT_OP(name1 ## name2, ps) \
2666 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
2667 FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \
2668 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
2669 FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \
2670 DEBUG_FPU_STATE(); \
2673 FLOAT_TERNOP(mul
, add
)
2674 FLOAT_TERNOP(mul
, sub
)
2677 /* negated ternary operations */
2678 #define FLOAT_NTERNOP(name1, name2) \
2679 FLOAT_OP(n ## name1 ## name2, d) \
2681 FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status); \
2682 FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status); \
2683 FDT2 = float64_chs(FDT2); \
2684 DEBUG_FPU_STATE(); \
2687 FLOAT_OP(n ## name1 ## name2, s) \
2689 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
2690 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
2691 FST2 = float32_chs(FST2); \
2692 DEBUG_FPU_STATE(); \
2695 FLOAT_OP(n ## name1 ## name2, ps) \
2697 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
2698 FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \
2699 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
2700 FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \
2701 FST2 = float32_chs(FST2); \
2702 FSTH2 = float32_chs(FSTH2); \
2703 DEBUG_FPU_STATE(); \
2706 FLOAT_NTERNOP(mul
, add
)
2707 FLOAT_NTERNOP(mul
, sub
)
2708 #undef FLOAT_NTERNOP
2710 /* unary operations, modifying fp status */
2711 #define FLOAT_UNOP(name) \
2714 FDT2 = float64_ ## name(FDT0, &env->fpu->fp_status); \
2715 DEBUG_FPU_STATE(); \
2720 FST2 = float32_ ## name(FST0, &env->fpu->fp_status); \
2721 DEBUG_FPU_STATE(); \
2727 /* unary operations, not modifying fp status */
2728 #define FLOAT_UNOP(name) \
2731 FDT2 = float64_ ## name(FDT0); \
2732 DEBUG_FPU_STATE(); \
2737 FST2 = float32_ ## name(FST0); \
2738 DEBUG_FPU_STATE(); \
2741 FLOAT_OP(name, ps) \
2743 FST2 = float32_ ## name(FST0); \
2744 FSTH2 = float32_ ## name(FSTH0); \
2745 DEBUG_FPU_STATE(); \
2779 #ifdef TARGET_WORDS_BIGENDIAN
2787 default: /* unpredictable */
2794 #ifdef CONFIG_SOFTFLOAT
2795 #define clear_invalid() do { \
2796 int flags = get_float_exception_flags(&env->fpu->fp_status); \
2797 flags &= ~float_flag_invalid; \
2798 set_float_exception_flags(flags, &env->fpu->fp_status); \
2801 #define clear_invalid() do { } while(0)
2804 extern void dump_fpu_s(CPUState
*env
);
2806 #define CMP_OP(fmt, op) \
2807 void OPPROTO op_cmp ## _ ## fmt ## _ ## op(void) \
2809 CALL_FROM_TB1(do_cmp ## _ ## fmt ## _ ## op, PARAM1); \
2810 DEBUG_FPU_STATE(); \
2813 void OPPROTO op_cmpabs ## _ ## fmt ## _ ## op(void) \
2815 CALL_FROM_TB1(do_cmpabs ## _ ## fmt ## _ ## op, PARAM1); \
2816 DEBUG_FPU_STATE(); \
2819 #define CMP_OPS(op) \
2845 T0
= !!(~GET_FP_COND(env
->fpu
) & (0x1 << PARAM1
));
2849 void op_bc1any2f (void)
2851 T0
= !!(~GET_FP_COND(env
->fpu
) & (0x3 << PARAM1
));
2855 void op_bc1any4f (void)
2857 T0
= !!(~GET_FP_COND(env
->fpu
) & (0xf << PARAM1
));
2864 T0
= !!(GET_FP_COND(env
->fpu
) & (0x1 << PARAM1
));
2868 void op_bc1any2t (void)
2870 T0
= !!(GET_FP_COND(env
->fpu
) & (0x3 << PARAM1
));
2874 void op_bc1any4t (void)
2876 T0
= !!(GET_FP_COND(env
->fpu
) & (0xf << PARAM1
));
2881 void op_tlbwi (void)
2883 CALL_FROM_TB0(env
->tlb
->do_tlbwi
);
2887 void op_tlbwr (void)
2889 CALL_FROM_TB0(env
->tlb
->do_tlbwr
);
2895 CALL_FROM_TB0(env
->tlb
->do_tlbp
);
2901 CALL_FROM_TB0(env
->tlb
->do_tlbr
);
2906 #if defined (CONFIG_USER_ONLY)
2907 void op_tls_value (void)
2909 T0
= env
->tls_value
;
2915 CALL_FROM_TB1(do_pmon
, PARAM1
);
2921 T0
= env
->CP0_Status
;
2922 env
->CP0_Status
= T0
& ~(1 << CP0St_IE
);
2923 CALL_FROM_TB1(cpu_mips_update_irq
, env
);
2929 T0
= env
->CP0_Status
;
2930 env
->CP0_Status
= T0
| (1 << CP0St_IE
);
2931 CALL_FROM_TB1(cpu_mips_update_irq
, env
);
2938 CALL_FROM_TB1(do_raise_exception
, EXCP_TRAP
);
2943 void op_debug (void)
2945 CALL_FROM_TB1(do_raise_exception
, EXCP_DEBUG
);
2949 void op_set_lladdr (void)
2951 env
->CP0_LLAddr
= T2
;
2955 void debug_pre_eret (void);
2956 void debug_post_eret (void);
2959 if (loglevel
& CPU_LOG_EXEC
)
2960 CALL_FROM_TB0(debug_pre_eret
);
2961 if (env
->CP0_Status
& (1 << CP0St_ERL
)) {
2962 env
->PC
[env
->current_tc
] = env
->CP0_ErrorEPC
;
2963 env
->CP0_Status
&= ~(1 << CP0St_ERL
);
2965 env
->PC
[env
->current_tc
] = env
->CP0_EPC
;
2966 env
->CP0_Status
&= ~(1 << CP0St_EXL
);
2968 CALL_FROM_TB1(compute_hflags
, env
);
2969 if (loglevel
& CPU_LOG_EXEC
)
2970 CALL_FROM_TB0(debug_post_eret
);
2971 env
->CP0_LLAddr
= 1;
2975 void op_deret (void)
2977 if (loglevel
& CPU_LOG_EXEC
)
2978 CALL_FROM_TB0(debug_pre_eret
);
2979 env
->PC
[env
->current_tc
] = env
->CP0_DEPC
;
2980 env
->hflags
&= MIPS_HFLAG_DM
;
2981 CALL_FROM_TB1(compute_hflags
, env
);
2982 if (loglevel
& CPU_LOG_EXEC
)
2983 CALL_FROM_TB0(debug_post_eret
);
2984 env
->CP0_LLAddr
= 1;
2988 void op_rdhwr_cpunum(void)
2990 if ((env
->hflags
& MIPS_HFLAG_CP0
) ||
2991 (env
->CP0_HWREna
& (1 << 0)))
2992 T0
= env
->CP0_EBase
& 0x3ff;
2994 CALL_FROM_TB1(do_raise_exception
, EXCP_RI
);
2998 void op_rdhwr_synci_step(void)
3000 if ((env
->hflags
& MIPS_HFLAG_CP0
) ||
3001 (env
->CP0_HWREna
& (1 << 1)))
3002 T0
= env
->SYNCI_Step
;
3004 CALL_FROM_TB1(do_raise_exception
, EXCP_RI
);
3008 void op_rdhwr_cc(void)
3010 if ((env
->hflags
& MIPS_HFLAG_CP0
) ||
3011 (env
->CP0_HWREna
& (1 << 2)))
3012 T0
= env
->CP0_Count
;
3014 CALL_FROM_TB1(do_raise_exception
, EXCP_RI
);
3018 void op_rdhwr_ccres(void)
3020 if ((env
->hflags
& MIPS_HFLAG_CP0
) ||
3021 (env
->CP0_HWREna
& (1 << 3)))
3024 CALL_FROM_TB1(do_raise_exception
, EXCP_RI
);
3028 void op_save_state (void)
3030 env
->hflags
= PARAM1
;
3034 void op_save_pc (void)
3036 env
->PC
[env
->current_tc
] = PARAM1
;
3040 #if defined(TARGET_MIPS64)
3041 void op_save_pc64 (void)
3043 env
->PC
[env
->current_tc
] = ((uint64_t)PARAM1
<< 32) | (uint32_t)PARAM2
;
3048 void op_interrupt_restart (void)
3050 if (!(env
->CP0_Status
& (1 << CP0St_EXL
)) &&
3051 !(env
->CP0_Status
& (1 << CP0St_ERL
)) &&
3052 !(env
->hflags
& MIPS_HFLAG_DM
) &&
3053 (env
->CP0_Status
& (1 << CP0St_IE
)) &&
3054 (env
->CP0_Status
& env
->CP0_Cause
& CP0Ca_IP_mask
)) {
3055 env
->CP0_Cause
&= ~(0x1f << CP0Ca_EC
);
3056 CALL_FROM_TB1(do_raise_exception
, EXCP_EXT_INTERRUPT
);
3061 void op_raise_exception (void)
3063 CALL_FROM_TB1(do_raise_exception
, PARAM1
);
3067 void op_raise_exception_err (void)
3069 CALL_FROM_TB2(do_raise_exception_err
, PARAM1
, PARAM2
);
3073 void op_exit_tb (void)
3082 CALL_FROM_TB1(do_raise_exception
, EXCP_HLT
);
3086 /* Bitfield operations. */
3089 unsigned int pos
= PARAM1
;
3090 unsigned int size
= PARAM2
;
3092 T0
= (int32_t)((T1
>> pos
) & ((size
< 32) ? ((1 << size
) - 1) : ~0));
3098 unsigned int pos
= PARAM1
;
3099 unsigned int size
= PARAM2
;
3100 target_ulong mask
= ((size
< 32) ? ((1 << size
) - 1) : ~0) << pos
;
3102 T0
= (int32_t)((T0
& ~mask
) | ((T1
<< pos
) & mask
));
3108 T0
= (int32_t)(((T1
<< 8) & ~0x00FF00FF) | ((T1
>> 8) & 0x00FF00FF));
3112 #if defined(TARGET_MIPS64)
3115 unsigned int pos
= PARAM1
;
3116 unsigned int size
= PARAM2
;
3118 T0
= (T1
>> pos
) & ((size
< 64) ? ((1ULL << size
) - 1) : ~0ULL);
3124 unsigned int pos
= PARAM1
;
3125 unsigned int size
= PARAM2
;
3126 target_ulong mask
= ((size
< 64) ? ((1ULL << size
) - 1) : ~0ULL) << pos
;
3128 T0
= (T0
& ~mask
) | ((T1
<< pos
) & mask
);
3134 T0
= ((T1
<< 8) & ~0x00FF00FF00FF00FFULL
) | ((T1
>> 8) & 0x00FF00FF00FF00FFULL
);
3140 T1
= ((T1
<< 16) & ~0x0000FFFF0000FFFFULL
) | ((T1
>> 16) & 0x0000FFFF0000FFFFULL
);
3141 T0
= (T1
<< 32) | (T1
>> 32);
3148 T0
= ((T1
& 0xFF) ^ 0x80) - 0x80;
3154 T0
= ((T1
& 0xFFFF) ^ 0x8000) - 0x8000;