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_load_HI (void)
252 T0
= env
->HI
[env
->current_tc
][PARAM1
];
256 void op_store_HI (void)
258 env
->HI
[env
->current_tc
][PARAM1
] = T0
;
262 void op_load_LO (void)
264 T0
= env
->LO
[env
->current_tc
][PARAM1
];
268 void op_store_LO (void)
270 env
->LO
[env
->current_tc
][PARAM1
] = T0
;
275 #define MEMSUFFIX _raw
278 #if !defined(CONFIG_USER_ONLY)
279 #define MEMSUFFIX _user
283 #define MEMSUFFIX _super
287 #define MEMSUFFIX _kernel
292 /* Addresses computation */
293 void op_addr_add (void)
295 /* For compatibility with 32-bit code, data reference in user mode
296 with Status_UX = 0 should be casted to 32-bit and sign extended.
297 See the MIPS64 PRA manual, section 4.10. */
298 #if defined(TARGET_MIPS64)
299 if (((env
->hflags
& MIPS_HFLAG_KSU
) == MIPS_HFLAG_UM
) &&
300 !(env
->CP0_Status
& (1 << CP0St_UX
)))
301 T0
= (int64_t)(int32_t)(T0
+ T1
);
311 T0
= (int32_t)((int32_t)T0
+ (int32_t)T1
);
320 T0
= (int32_t)T0
+ (int32_t)T1
;
321 if (((tmp
^ T1
^ (-1)) & (T0
^ T1
)) >> 31) {
322 /* operands of same sign, result different sign */
323 CALL_FROM_TB1(do_raise_exception
, EXCP_OVERFLOW
);
331 T0
= (int32_t)((int32_t)T0
- (int32_t)T1
);
340 T0
= (int32_t)T0
- (int32_t)T1
;
341 if (((tmp
^ T1
) & (tmp
^ T0
)) >> 31) {
342 /* operands of different sign, first operand and result different sign */
343 CALL_FROM_TB1(do_raise_exception
, EXCP_OVERFLOW
);
351 T0
= (int32_t)((int32_t)T0
* (int32_t)T1
);
355 #if HOST_LONG_BITS < 64
358 CALL_FROM_TB0(do_div
);
365 env
->LO
[env
->current_tc
][0] = (int32_t)((int64_t)(int32_t)T0
/ (int32_t)T1
);
366 env
->HI
[env
->current_tc
][0] = (int32_t)((int64_t)(int32_t)T0
% (int32_t)T1
);
375 env
->LO
[env
->current_tc
][0] = (int32_t)((uint32_t)T0
/ (uint32_t)T1
);
376 env
->HI
[env
->current_tc
][0] = (int32_t)((uint32_t)T0
% (uint32_t)T1
);
381 #if defined(TARGET_MIPS64)
395 if (((tmp
^ T1
^ (-1)) & (T0
^ T1
)) >> 63) {
396 /* operands of same sign, result different sign */
397 CALL_FROM_TB1(do_raise_exception
, EXCP_OVERFLOW
);
413 T0
= (int64_t)T0
- (int64_t)T1
;
414 if (((tmp
^ T1
) & (tmp
^ T0
)) >> 63) {
415 /* operands of different sign, first operand and result different sign */
416 CALL_FROM_TB1(do_raise_exception
, EXCP_OVERFLOW
);
423 T0
= (int64_t)T0
* (int64_t)T1
;
427 /* Those might call libgcc functions. */
434 #if TARGET_LONG_BITS > HOST_LONG_BITS
444 env
->LO
[env
->current_tc
][0] = T0
/ T1
;
445 env
->HI
[env
->current_tc
][0] = T0
% T1
;
450 #endif /* TARGET_MIPS64 */
479 T0
= (int32_t)((uint32_t)T0
<< T1
);
485 T0
= (int32_t)((int32_t)T0
>> T1
);
491 T0
= (int32_t)((uint32_t)T0
>> T1
);
500 tmp
= (int32_t)((uint32_t)T0
<< (0x20 - T1
));
501 T0
= (int32_t)((uint32_t)T0
>> T1
) | tmp
;
508 T0
= (int32_t)((uint32_t)T1
<< ((uint32_t)T0
& 0x1F));
514 T0
= (int32_t)((int32_t)T1
>> (T0
& 0x1F));
520 T0
= (int32_t)((uint32_t)T1
>> (T0
& 0x1F));
530 tmp
= (int32_t)((uint32_t)T1
<< (0x20 - T0
));
531 T0
= (int32_t)((uint32_t)T1
>> T0
) | tmp
;
549 #if defined(TARGET_MIPS64)
551 #if TARGET_LONG_BITS > HOST_LONG_BITS
552 /* Those might call libgcc functions. */
555 CALL_FROM_TB0(do_dsll
);
559 void op_dsll32 (void)
561 CALL_FROM_TB0(do_dsll32
);
567 CALL_FROM_TB0(do_dsra
);
571 void op_dsra32 (void)
573 CALL_FROM_TB0(do_dsra32
);
579 CALL_FROM_TB0(do_dsrl
);
583 void op_dsrl32 (void)
585 CALL_FROM_TB0(do_dsrl32
);
591 CALL_FROM_TB0(do_drotr
);
595 void op_drotr32 (void)
597 CALL_FROM_TB0(do_drotr32
);
603 CALL_FROM_TB0(do_dsllv
);
609 CALL_FROM_TB0(do_dsrav
);
615 CALL_FROM_TB0(do_dsrlv
);
619 void op_drotrv (void)
621 CALL_FROM_TB0(do_drotrv
);
627 CALL_FROM_TB0(do_dclo
);
633 CALL_FROM_TB0(do_dclz
);
637 #else /* TARGET_LONG_BITS > HOST_LONG_BITS */
645 void op_dsll32 (void)
647 T0
= T0
<< (T1
+ 32);
653 T0
= (int64_t)T0
>> T1
;
657 void op_dsra32 (void)
659 T0
= (int64_t)T0
>> (T1
+ 32);
669 void op_dsrl32 (void)
671 T0
= T0
>> (T1
+ 32);
680 tmp
= T0
<< (0x40 - T1
);
681 T0
= (T0
>> T1
) | tmp
;
686 void op_drotr32 (void)
690 tmp
= T0
<< (0x40 - (32 + T1
));
691 T0
= (T0
>> (32 + T1
)) | tmp
;
697 T0
= T1
<< (T0
& 0x3F);
703 T0
= (int64_t)T1
>> (T0
& 0x3F);
709 T0
= T1
>> (T0
& 0x3F);
713 void op_drotrv (void)
719 tmp
= T1
<< (0x40 - T0
);
720 T0
= (T1
>> T0
) | tmp
;
737 #endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
738 #endif /* TARGET_MIPS64 */
740 /* 64 bits arithmetic */
741 #if TARGET_LONG_BITS > HOST_LONG_BITS
744 CALL_FROM_TB0(do_mult
);
750 CALL_FROM_TB0(do_multu
);
756 CALL_FROM_TB0(do_madd
);
762 CALL_FROM_TB0(do_maddu
);
768 CALL_FROM_TB0(do_msub
);
774 CALL_FROM_TB0(do_msubu
);
778 /* Multiplication variants of the vr54xx. */
781 CALL_FROM_TB0(do_muls
);
787 CALL_FROM_TB0(do_mulsu
);
793 CALL_FROM_TB0(do_macc
);
797 void op_macchi (void)
799 CALL_FROM_TB0(do_macchi
);
805 CALL_FROM_TB0(do_maccu
);
808 void op_macchiu (void)
810 CALL_FROM_TB0(do_macchiu
);
816 CALL_FROM_TB0(do_msac
);
820 void op_msachi (void)
822 CALL_FROM_TB0(do_msachi
);
828 CALL_FROM_TB0(do_msacu
);
832 void op_msachiu (void)
834 CALL_FROM_TB0(do_msachiu
);
840 CALL_FROM_TB0(do_mulhi
);
844 void op_mulhiu (void)
846 CALL_FROM_TB0(do_mulhiu
);
850 void op_mulshi (void)
852 CALL_FROM_TB0(do_mulshi
);
856 void op_mulshiu (void)
858 CALL_FROM_TB0(do_mulshiu
);
862 #else /* TARGET_LONG_BITS > HOST_LONG_BITS */
864 static always_inline
uint64_t get_HILO (void)
866 return ((uint64_t)env
->HI
[env
->current_tc
][0] << 32) |
867 ((uint64_t)(uint32_t)env
->LO
[env
->current_tc
][0]);
870 static always_inline
void set_HILO (uint64_t HILO
)
872 env
->LO
[env
->current_tc
][0] = (int32_t)(HILO
& 0xFFFFFFFF);
873 env
->HI
[env
->current_tc
][0] = (int32_t)(HILO
>> 32);
876 static always_inline
void set_HIT0_LO (uint64_t HILO
)
878 env
->LO
[env
->current_tc
][0] = (int32_t)(HILO
& 0xFFFFFFFF);
879 T0
= env
->HI
[env
->current_tc
][0] = (int32_t)(HILO
>> 32);
882 static always_inline
void set_HI_LOT0 (uint64_t HILO
)
884 T0
= env
->LO
[env
->current_tc
][0] = (int32_t)(HILO
& 0xFFFFFFFF);
885 env
->HI
[env
->current_tc
][0] = (int32_t)(HILO
>> 32);
890 set_HILO((int64_t)(int32_t)T0
* (int64_t)(int32_t)T1
);
896 set_HILO((uint64_t)(uint32_t)T0
* (uint64_t)(uint32_t)T1
);
904 tmp
= ((int64_t)(int32_t)T0
* (int64_t)(int32_t)T1
);
905 set_HILO((int64_t)get_HILO() + tmp
);
913 tmp
= ((uint64_t)(uint32_t)T0
* (uint64_t)(uint32_t)T1
);
914 set_HILO(get_HILO() + tmp
);
922 tmp
= ((int64_t)(int32_t)T0
* (int64_t)(int32_t)T1
);
923 set_HILO((int64_t)get_HILO() - tmp
);
931 tmp
= ((uint64_t)(uint32_t)T0
* (uint64_t)(uint32_t)T1
);
932 set_HILO(get_HILO() - tmp
);
936 /* Multiplication variants of the vr54xx. */
939 set_HI_LOT0(0 - ((int64_t)(int32_t)T0
* (int64_t)(int32_t)T1
));
945 set_HI_LOT0(0 - ((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_macchi (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_macchiu (void)
969 set_HIT0_LO(get_HILO() + ((uint64_t)(uint32_t)T0
* (uint64_t)(uint32_t)T1
));
975 set_HI_LOT0(get_HILO() - ((int64_t)(int32_t)T0
* (int64_t)(int32_t)T1
));
979 void op_msachi (void)
981 set_HIT0_LO(get_HILO() - ((int64_t)(int32_t)T0
* (int64_t)(int32_t)T1
));
987 set_HI_LOT0(get_HILO() - ((uint64_t)(uint32_t)T0
* (uint64_t)(uint32_t)T1
));
991 void op_msachiu (void)
993 set_HIT0_LO(get_HILO() - ((uint64_t)(uint32_t)T0
* (uint64_t)(uint32_t)T1
));
999 set_HIT0_LO((int64_t)(int32_t)T0
* (int64_t)(int32_t)T1
);
1003 void op_mulhiu (void)
1005 set_HIT0_LO((uint64_t)(uint32_t)T0
* (uint64_t)(uint32_t)T1
);
1009 void op_mulshi (void)
1011 set_HIT0_LO(0 - ((int64_t)(int32_t)T0
* (int64_t)(int32_t)T1
));
1015 void op_mulshiu (void)
1017 set_HIT0_LO(0 - ((uint64_t)(uint32_t)T0
* (uint64_t)(uint32_t)T1
));
1021 #endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
1023 #if defined(TARGET_MIPS64)
1024 void op_dmult (void)
1026 CALL_FROM_TB4(muls64
, &(env
->LO
[env
->current_tc
][0]), &(env
->HI
[env
->current_tc
][0]), T0
, T1
);
1030 void op_dmultu (void)
1032 CALL_FROM_TB4(mulu64
, &(env
->LO
[env
->current_tc
][0]), &(env
->HI
[env
->current_tc
][0]), T0
, T1
);
1037 /* Conditional moves */
1041 env
->gpr
[env
->current_tc
][PARAM1
] = T0
;
1048 env
->gpr
[env
->current_tc
][PARAM1
] = T0
;
1054 if (!(env
->fpu
->fcr31
& PARAM1
))
1061 if (env
->fpu
->fcr31
& PARAM1
)
1067 #define OP_COND(name, cond) \
1068 void glue(op_, name) (void) \
1078 OP_COND(eq
, T0
== T1
);
1079 OP_COND(ne
, T0
!= T1
);
1080 OP_COND(ge
, (target_long
)T0
>= (target_long
)T1
);
1081 OP_COND(geu
, T0
>= T1
);
1082 OP_COND(lt
, (target_long
)T0
< (target_long
)T1
);
1083 OP_COND(ltu
, T0
< T1
);
1084 OP_COND(gez
, (target_long
)T0
>= 0);
1085 OP_COND(gtz
, (target_long
)T0
> 0);
1086 OP_COND(lez
, (target_long
)T0
<= 0);
1087 OP_COND(ltz
, (target_long
)T0
< 0);
1090 /* Branch to register */
1091 void op_save_breg_target (void)
1099 env
->PC
[env
->current_tc
] = env
->btarget
;
1103 void op_save_btarget (void)
1105 env
->btarget
= PARAM1
;
1109 #if defined(TARGET_MIPS64)
1110 void op_save_btarget64 (void)
1112 env
->btarget
= ((uint64_t)PARAM1
<< 32) | (uint32_t)PARAM2
;
1117 /* Conditional branch */
1118 void op_set_bcond (void)
1124 void op_jnz_bcond (void)
1127 GOTO_LABEL_PARAM(1);
1132 void op_mfc0_index (void)
1134 T0
= env
->CP0_Index
;
1138 void op_mfc0_mvpcontrol (void)
1140 T0
= env
->mvp
->CP0_MVPControl
;
1144 void op_mfc0_mvpconf0 (void)
1146 T0
= env
->mvp
->CP0_MVPConf0
;
1150 void op_mfc0_mvpconf1 (void)
1152 T0
= env
->mvp
->CP0_MVPConf1
;
1156 void op_mfc0_random (void)
1158 CALL_FROM_TB0(do_mfc0_random
);
1162 void op_mfc0_vpecontrol (void)
1164 T0
= env
->CP0_VPEControl
;
1168 void op_mfc0_vpeconf0 (void)
1170 T0
= env
->CP0_VPEConf0
;
1174 void op_mfc0_vpeconf1 (void)
1176 T0
= env
->CP0_VPEConf1
;
1180 void op_mfc0_yqmask (void)
1182 T0
= env
->CP0_YQMask
;
1186 void op_mfc0_vpeschedule (void)
1188 T0
= env
->CP0_VPESchedule
;
1192 void op_mfc0_vpeschefback (void)
1194 T0
= env
->CP0_VPEScheFBack
;
1198 void op_mfc0_vpeopt (void)
1200 T0
= env
->CP0_VPEOpt
;
1204 void op_mfc0_entrylo0 (void)
1206 T0
= (int32_t)env
->CP0_EntryLo0
;
1210 void op_mfc0_tcstatus (void)
1212 T0
= env
->CP0_TCStatus
[env
->current_tc
];
1216 void op_mftc0_tcstatus(void)
1218 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1220 T0
= env
->CP0_TCStatus
[other_tc
];
1224 void op_mfc0_tcbind (void)
1226 T0
= env
->CP0_TCBind
[env
->current_tc
];
1230 void op_mftc0_tcbind(void)
1232 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1234 T0
= env
->CP0_TCBind
[other_tc
];
1238 void op_mfc0_tcrestart (void)
1240 T0
= env
->PC
[env
->current_tc
];
1244 void op_mftc0_tcrestart(void)
1246 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1248 T0
= env
->PC
[other_tc
];
1252 void op_mfc0_tchalt (void)
1254 T0
= env
->CP0_TCHalt
[env
->current_tc
];
1258 void op_mftc0_tchalt(void)
1260 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1262 T0
= env
->CP0_TCHalt
[other_tc
];
1266 void op_mfc0_tccontext (void)
1268 T0
= env
->CP0_TCContext
[env
->current_tc
];
1272 void op_mftc0_tccontext(void)
1274 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1276 T0
= env
->CP0_TCContext
[other_tc
];
1280 void op_mfc0_tcschedule (void)
1282 T0
= env
->CP0_TCSchedule
[env
->current_tc
];
1286 void op_mftc0_tcschedule(void)
1288 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1290 T0
= env
->CP0_TCSchedule
[other_tc
];
1294 void op_mfc0_tcschefback (void)
1296 T0
= env
->CP0_TCScheFBack
[env
->current_tc
];
1300 void op_mftc0_tcschefback(void)
1302 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1304 T0
= env
->CP0_TCScheFBack
[other_tc
];
1308 void op_mfc0_entrylo1 (void)
1310 T0
= (int32_t)env
->CP0_EntryLo1
;
1314 void op_mfc0_context (void)
1316 T0
= (int32_t)env
->CP0_Context
;
1320 void op_mfc0_pagemask (void)
1322 T0
= env
->CP0_PageMask
;
1326 void op_mfc0_pagegrain (void)
1328 T0
= env
->CP0_PageGrain
;
1332 void op_mfc0_wired (void)
1334 T0
= env
->CP0_Wired
;
1338 void op_mfc0_srsconf0 (void)
1340 T0
= env
->CP0_SRSConf0
;
1344 void op_mfc0_srsconf1 (void)
1346 T0
= env
->CP0_SRSConf1
;
1350 void op_mfc0_srsconf2 (void)
1352 T0
= env
->CP0_SRSConf2
;
1356 void op_mfc0_srsconf3 (void)
1358 T0
= env
->CP0_SRSConf3
;
1362 void op_mfc0_srsconf4 (void)
1364 T0
= env
->CP0_SRSConf4
;
1368 void op_mfc0_hwrena (void)
1370 T0
= env
->CP0_HWREna
;
1374 void op_mfc0_badvaddr (void)
1376 T0
= (int32_t)env
->CP0_BadVAddr
;
1380 void op_mfc0_count (void)
1382 CALL_FROM_TB0(do_mfc0_count
);
1386 void op_mfc0_entryhi (void)
1388 T0
= (int32_t)env
->CP0_EntryHi
;
1392 void op_mftc0_entryhi(void)
1394 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1396 T0
= (env
->CP0_EntryHi
& ~0xff) | (env
->CP0_TCStatus
[other_tc
] & 0xff);
1400 void op_mfc0_compare (void)
1402 T0
= env
->CP0_Compare
;
1406 void op_mfc0_status (void)
1408 T0
= env
->CP0_Status
;
1412 void op_mftc0_status(void)
1414 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1415 uint32_t tcstatus
= env
->CP0_TCStatus
[other_tc
];
1417 T0
= env
->CP0_Status
& ~0xf1000018;
1418 T0
|= tcstatus
& (0xf << CP0TCSt_TCU0
);
1419 T0
|= (tcstatus
& (1 << CP0TCSt_TMX
)) >> (CP0TCSt_TMX
- CP0St_MX
);
1420 T0
|= (tcstatus
& (0x3 << CP0TCSt_TKSU
)) >> (CP0TCSt_TKSU
- CP0St_KSU
);
1424 void op_mfc0_intctl (void)
1426 T0
= env
->CP0_IntCtl
;
1430 void op_mfc0_srsctl (void)
1432 T0
= env
->CP0_SRSCtl
;
1436 void op_mfc0_srsmap (void)
1438 T0
= env
->CP0_SRSMap
;
1442 void op_mfc0_cause (void)
1444 T0
= env
->CP0_Cause
;
1448 void op_mfc0_epc (void)
1450 T0
= (int32_t)env
->CP0_EPC
;
1454 void op_mfc0_prid (void)
1460 void op_mfc0_ebase (void)
1462 T0
= env
->CP0_EBase
;
1466 void op_mfc0_config0 (void)
1468 T0
= env
->CP0_Config0
;
1472 void op_mfc0_config1 (void)
1474 T0
= env
->CP0_Config1
;
1478 void op_mfc0_config2 (void)
1480 T0
= env
->CP0_Config2
;
1484 void op_mfc0_config3 (void)
1486 T0
= env
->CP0_Config3
;
1490 void op_mfc0_config6 (void)
1492 T0
= env
->CP0_Config6
;
1496 void op_mfc0_config7 (void)
1498 T0
= env
->CP0_Config7
;
1502 void op_mfc0_lladdr (void)
1504 T0
= (int32_t)env
->CP0_LLAddr
>> 4;
1508 void op_mfc0_watchlo (void)
1510 T0
= (int32_t)env
->CP0_WatchLo
[PARAM1
];
1514 void op_mfc0_watchhi (void)
1516 T0
= env
->CP0_WatchHi
[PARAM1
];
1520 void op_mfc0_xcontext (void)
1522 T0
= (int32_t)env
->CP0_XContext
;
1526 void op_mfc0_framemask (void)
1528 T0
= env
->CP0_Framemask
;
1532 void op_mfc0_debug (void)
1534 T0
= env
->CP0_Debug
;
1535 if (env
->hflags
& MIPS_HFLAG_DM
)
1536 T0
|= 1 << CP0DB_DM
;
1540 void op_mftc0_debug(void)
1542 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1544 /* XXX: Might be wrong, check with EJTAG spec. */
1545 T0
= (env
->CP0_Debug
& ~((1 << CP0DB_SSt
) | (1 << CP0DB_Halt
))) |
1546 (env
->CP0_Debug_tcstatus
[other_tc
] &
1547 ((1 << CP0DB_SSt
) | (1 << CP0DB_Halt
)));
1551 void op_mfc0_depc (void)
1553 T0
= (int32_t)env
->CP0_DEPC
;
1557 void op_mfc0_performance0 (void)
1559 T0
= env
->CP0_Performance0
;
1563 void op_mfc0_taglo (void)
1565 T0
= env
->CP0_TagLo
;
1569 void op_mfc0_datalo (void)
1571 T0
= env
->CP0_DataLo
;
1575 void op_mfc0_taghi (void)
1577 T0
= env
->CP0_TagHi
;
1581 void op_mfc0_datahi (void)
1583 T0
= env
->CP0_DataHi
;
1587 void op_mfc0_errorepc (void)
1589 T0
= (int32_t)env
->CP0_ErrorEPC
;
1593 void op_mfc0_desave (void)
1595 T0
= env
->CP0_DESAVE
;
1599 void op_mtc0_index (void)
1602 unsigned int tmp
= env
->tlb
->nb_tlb
;
1608 env
->CP0_Index
= (env
->CP0_Index
& 0x80000000) | (T0
& (num
- 1));
1612 void op_mtc0_mvpcontrol (void)
1617 if (env
->CP0_VPEConf0
& (1 << CP0VPEC0_MVP
))
1618 mask
|= (1 << CP0MVPCo_CPA
) | (1 << CP0MVPCo_VPC
) |
1619 (1 << CP0MVPCo_EVP
);
1620 if (env
->mvp
->CP0_MVPControl
& (1 << CP0MVPCo_VPC
))
1621 mask
|= (1 << CP0MVPCo_STLB
);
1622 newval
= (env
->mvp
->CP0_MVPControl
& ~mask
) | (T0
& mask
);
1624 // TODO: Enable/disable shared TLB, enable/disable VPEs.
1626 env
->mvp
->CP0_MVPControl
= newval
;
1630 void op_mtc0_vpecontrol (void)
1635 mask
= (1 << CP0VPECo_YSI
) | (1 << CP0VPECo_GSI
) |
1636 (1 << CP0VPECo_TE
) | (0xff << CP0VPECo_TargTC
);
1637 newval
= (env
->CP0_VPEControl
& ~mask
) | (T0
& mask
);
1639 /* Yield scheduler intercept not implemented. */
1640 /* Gating storage scheduler intercept not implemented. */
1642 // TODO: Enable/disable TCs.
1644 env
->CP0_VPEControl
= newval
;
1648 void op_mtc0_vpeconf0 (void)
1653 if (env
->CP0_VPEConf0
& (1 << CP0VPEC0_MVP
)) {
1654 if (env
->CP0_VPEConf0
& (1 << CP0VPEC0_VPA
))
1655 mask
|= (0xff << CP0VPEC0_XTC
);
1656 mask
|= (1 << CP0VPEC0_MVP
) | (1 << CP0VPEC0_VPA
);
1658 newval
= (env
->CP0_VPEConf0
& ~mask
) | (T0
& mask
);
1660 // TODO: TC exclusive handling due to ERL/EXL.
1662 env
->CP0_VPEConf0
= newval
;
1666 void op_mtc0_vpeconf1 (void)
1671 if (env
->mvp
->CP0_MVPControl
& (1 << CP0MVPCo_VPC
))
1672 mask
|= (0xff << CP0VPEC1_NCX
) | (0xff << CP0VPEC1_NCP2
) |
1673 (0xff << CP0VPEC1_NCP1
);
1674 newval
= (env
->CP0_VPEConf1
& ~mask
) | (T0
& mask
);
1676 /* UDI not implemented. */
1677 /* CP2 not implemented. */
1679 // TODO: Handle FPU (CP1) binding.
1681 env
->CP0_VPEConf1
= newval
;
1685 void op_mtc0_yqmask (void)
1687 /* Yield qualifier inputs not implemented. */
1688 env
->CP0_YQMask
= 0x00000000;
1692 void op_mtc0_vpeschedule (void)
1694 env
->CP0_VPESchedule
= T0
;
1698 void op_mtc0_vpeschefback (void)
1700 env
->CP0_VPEScheFBack
= T0
;
1704 void op_mtc0_vpeopt (void)
1706 env
->CP0_VPEOpt
= T0
& 0x0000ffff;
1710 void op_mtc0_entrylo0 (void)
1712 /* Large physaddr (PABITS) not implemented */
1713 /* 1k pages not implemented */
1714 env
->CP0_EntryLo0
= T0
& 0x3FFFFFFF;
1718 void op_mtc0_tcstatus (void)
1720 uint32_t mask
= env
->CP0_TCStatus_rw_bitmask
;
1723 newval
= (env
->CP0_TCStatus
[env
->current_tc
] & ~mask
) | (T0
& mask
);
1725 // TODO: Sync with CP0_Status.
1727 env
->CP0_TCStatus
[env
->current_tc
] = newval
;
1731 void op_mttc0_tcstatus (void)
1733 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1735 // TODO: Sync with CP0_Status.
1737 env
->CP0_TCStatus
[other_tc
] = T0
;
1741 void op_mtc0_tcbind (void)
1743 uint32_t mask
= (1 << CP0TCBd_TBE
);
1746 if (env
->mvp
->CP0_MVPControl
& (1 << CP0MVPCo_VPC
))
1747 mask
|= (1 << CP0TCBd_CurVPE
);
1748 newval
= (env
->CP0_TCBind
[env
->current_tc
] & ~mask
) | (T0
& mask
);
1749 env
->CP0_TCBind
[env
->current_tc
] = newval
;
1753 void op_mttc0_tcbind (void)
1755 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1756 uint32_t mask
= (1 << CP0TCBd_TBE
);
1759 if (env
->mvp
->CP0_MVPControl
& (1 << CP0MVPCo_VPC
))
1760 mask
|= (1 << CP0TCBd_CurVPE
);
1761 newval
= (env
->CP0_TCBind
[other_tc
] & ~mask
) | (T0
& mask
);
1762 env
->CP0_TCBind
[other_tc
] = newval
;
1766 void op_mtc0_tcrestart (void)
1768 env
->PC
[env
->current_tc
] = T0
;
1769 env
->CP0_TCStatus
[env
->current_tc
] &= ~(1 << CP0TCSt_TDS
);
1770 env
->CP0_LLAddr
= 0ULL;
1771 /* MIPS16 not implemented. */
1775 void op_mttc0_tcrestart (void)
1777 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1779 env
->PC
[other_tc
] = T0
;
1780 env
->CP0_TCStatus
[other_tc
] &= ~(1 << CP0TCSt_TDS
);
1781 env
->CP0_LLAddr
= 0ULL;
1782 /* MIPS16 not implemented. */
1786 void op_mtc0_tchalt (void)
1788 env
->CP0_TCHalt
[env
->current_tc
] = T0
& 0x1;
1790 // TODO: Halt TC / Restart (if allocated+active) TC.
1795 void op_mttc0_tchalt (void)
1797 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1799 // TODO: Halt TC / Restart (if allocated+active) TC.
1801 env
->CP0_TCHalt
[other_tc
] = T0
;
1805 void op_mtc0_tccontext (void)
1807 env
->CP0_TCContext
[env
->current_tc
] = T0
;
1811 void op_mttc0_tccontext (void)
1813 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1815 env
->CP0_TCContext
[other_tc
] = T0
;
1819 void op_mtc0_tcschedule (void)
1821 env
->CP0_TCSchedule
[env
->current_tc
] = T0
;
1825 void op_mttc0_tcschedule (void)
1827 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1829 env
->CP0_TCSchedule
[other_tc
] = T0
;
1833 void op_mtc0_tcschefback (void)
1835 env
->CP0_TCScheFBack
[env
->current_tc
] = T0
;
1839 void op_mttc0_tcschefback (void)
1841 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1843 env
->CP0_TCScheFBack
[other_tc
] = T0
;
1847 void op_mtc0_entrylo1 (void)
1849 /* Large physaddr (PABITS) not implemented */
1850 /* 1k pages not implemented */
1851 env
->CP0_EntryLo1
= T0
& 0x3FFFFFFF;
1855 void op_mtc0_context (void)
1857 env
->CP0_Context
= (env
->CP0_Context
& 0x007FFFFF) | (T0
& ~0x007FFFFF);
1861 void op_mtc0_pagemask (void)
1863 /* 1k pages not implemented */
1864 env
->CP0_PageMask
= T0
& (0x1FFFFFFF & (TARGET_PAGE_MASK
<< 1));
1868 void op_mtc0_pagegrain (void)
1870 /* SmartMIPS not implemented */
1871 /* Large physaddr (PABITS) not implemented */
1872 /* 1k pages not implemented */
1873 env
->CP0_PageGrain
= 0;
1877 void op_mtc0_wired (void)
1879 env
->CP0_Wired
= T0
% env
->tlb
->nb_tlb
;
1883 void op_mtc0_srsconf0 (void)
1885 env
->CP0_SRSConf0
|= T0
& env
->CP0_SRSConf0_rw_bitmask
;
1889 void op_mtc0_srsconf1 (void)
1891 env
->CP0_SRSConf1
|= T0
& env
->CP0_SRSConf1_rw_bitmask
;
1895 void op_mtc0_srsconf2 (void)
1897 env
->CP0_SRSConf2
|= T0
& env
->CP0_SRSConf2_rw_bitmask
;
1901 void op_mtc0_srsconf3 (void)
1903 env
->CP0_SRSConf3
|= T0
& env
->CP0_SRSConf3_rw_bitmask
;
1907 void op_mtc0_srsconf4 (void)
1909 env
->CP0_SRSConf4
|= T0
& env
->CP0_SRSConf4_rw_bitmask
;
1913 void op_mtc0_hwrena (void)
1915 env
->CP0_HWREna
= T0
& 0x0000000F;
1919 void op_mtc0_count (void)
1921 CALL_FROM_TB2(cpu_mips_store_count
, env
, T0
);
1925 void op_mtc0_entryhi (void)
1927 target_ulong old
, val
;
1929 /* 1k pages not implemented */
1930 val
= T0
& ((TARGET_PAGE_MASK
<< 1) | 0xFF);
1931 #if defined(TARGET_MIPS64)
1932 val
&= env
->SEGMask
;
1934 old
= env
->CP0_EntryHi
;
1935 env
->CP0_EntryHi
= val
;
1936 if (env
->CP0_Config3
& (1 << CP0C3_MT
)) {
1937 uint32_t tcst
= env
->CP0_TCStatus
[env
->current_tc
] & ~0xff;
1938 env
->CP0_TCStatus
[env
->current_tc
] = tcst
| (val
& 0xff);
1940 /* If the ASID changes, flush qemu's TLB. */
1941 if ((old
& 0xFF) != (val
& 0xFF))
1942 CALL_FROM_TB2(cpu_mips_tlb_flush
, env
, 1);
1946 void op_mttc0_entryhi(void)
1948 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1950 env
->CP0_EntryHi
= (env
->CP0_EntryHi
& 0xff) | (T0
& ~0xff);
1951 env
->CP0_TCStatus
[other_tc
] = (env
->CP0_TCStatus
[other_tc
] & ~0xff) | (T0
& 0xff);
1955 void op_mtc0_compare (void)
1957 CALL_FROM_TB2(cpu_mips_store_compare
, env
, T0
);
1961 void op_mtc0_status (void)
1964 uint32_t mask
= env
->CP0_Status_rw_bitmask
;
1967 old
= env
->CP0_Status
;
1968 env
->CP0_Status
= (env
->CP0_Status
& ~mask
) | val
;
1969 CALL_FROM_TB1(compute_hflags
, env
);
1970 if (loglevel
& CPU_LOG_EXEC
)
1971 CALL_FROM_TB2(do_mtc0_status_debug
, old
, val
);
1972 CALL_FROM_TB1(cpu_mips_update_irq
, env
);
1976 void op_mttc0_status(void)
1978 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
1979 uint32_t tcstatus
= env
->CP0_TCStatus
[other_tc
];
1981 env
->CP0_Status
= T0
& ~0xf1000018;
1982 tcstatus
= (tcstatus
& ~(0xf << CP0TCSt_TCU0
)) | (T0
& (0xf << CP0St_CU0
));
1983 tcstatus
= (tcstatus
& ~(1 << CP0TCSt_TMX
)) | ((T0
& (1 << CP0St_MX
)) << (CP0TCSt_TMX
- CP0St_MX
));
1984 tcstatus
= (tcstatus
& ~(0x3 << CP0TCSt_TKSU
)) | ((T0
& (0x3 << CP0St_KSU
)) << (CP0TCSt_TKSU
- CP0St_KSU
));
1985 env
->CP0_TCStatus
[other_tc
] = tcstatus
;
1989 void op_mtc0_intctl (void)
1991 /* vectored interrupts not implemented, no performance counters. */
1992 env
->CP0_IntCtl
= (env
->CP0_IntCtl
& ~0x000002e0) | (T0
& 0x000002e0);
1996 void op_mtc0_srsctl (void)
1998 uint32_t mask
= (0xf << CP0SRSCtl_ESS
) | (0xf << CP0SRSCtl_PSS
);
1999 env
->CP0_SRSCtl
= (env
->CP0_SRSCtl
& ~mask
) | (T0
& mask
);
2003 void op_mtc0_srsmap (void)
2005 env
->CP0_SRSMap
= T0
;
2009 void op_mtc0_cause (void)
2011 uint32_t mask
= 0x00C00300;
2012 uint32_t old
= env
->CP0_Cause
;
2014 if (env
->insn_flags
& ISA_MIPS32R2
)
2015 mask
|= 1 << CP0Ca_DC
;
2017 env
->CP0_Cause
= (env
->CP0_Cause
& ~mask
) | (T0
& mask
);
2019 if ((old
^ env
->CP0_Cause
) & (1 << CP0Ca_DC
)) {
2020 if (env
->CP0_Cause
& (1 << CP0Ca_DC
))
2021 CALL_FROM_TB1(cpu_mips_stop_count
, env
);
2023 CALL_FROM_TB1(cpu_mips_start_count
, env
);
2026 /* Handle the software interrupt as an hardware one, as they
2028 if (T0
& CP0Ca_IP_mask
) {
2029 CALL_FROM_TB1(cpu_mips_update_irq
, env
);
2034 void op_mtc0_epc (void)
2040 void op_mtc0_ebase (void)
2042 /* vectored interrupts not implemented */
2043 /* Multi-CPU not implemented */
2044 env
->CP0_EBase
= 0x80000000 | (T0
& 0x3FFFF000);
2048 void op_mtc0_config0 (void)
2050 env
->CP0_Config0
= (env
->CP0_Config0
& 0x81FFFFF8) | (T0
& 0x00000007);
2054 void op_mtc0_config2 (void)
2056 /* tertiary/secondary caches not implemented */
2057 env
->CP0_Config2
= (env
->CP0_Config2
& 0x8FFF0FFF);
2061 void op_mtc0_watchlo (void)
2063 /* Watch exceptions for instructions, data loads, data stores
2065 env
->CP0_WatchLo
[PARAM1
] = (T0
& ~0x7);
2069 void op_mtc0_watchhi (void)
2071 env
->CP0_WatchHi
[PARAM1
] = (T0
& 0x40FF0FF8);
2072 env
->CP0_WatchHi
[PARAM1
] &= ~(env
->CP0_WatchHi
[PARAM1
] & T0
& 0x7);
2076 void op_mtc0_xcontext (void)
2078 target_ulong mask
= (1ULL << (env
->SEGBITS
- 7)) - 1;
2079 env
->CP0_XContext
= (env
->CP0_XContext
& mask
) | (T0
& ~mask
);
2083 void op_mtc0_framemask (void)
2085 env
->CP0_Framemask
= T0
; /* XXX */
2089 void op_mtc0_debug (void)
2091 env
->CP0_Debug
= (env
->CP0_Debug
& 0x8C03FC1F) | (T0
& 0x13300120);
2092 if (T0
& (1 << CP0DB_DM
))
2093 env
->hflags
|= MIPS_HFLAG_DM
;
2095 env
->hflags
&= ~MIPS_HFLAG_DM
;
2099 void op_mttc0_debug(void)
2101 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
2103 /* XXX: Might be wrong, check with EJTAG spec. */
2104 env
->CP0_Debug_tcstatus
[other_tc
] = T0
& ((1 << CP0DB_SSt
) | (1 << CP0DB_Halt
));
2105 env
->CP0_Debug
= (env
->CP0_Debug
& ((1 << CP0DB_SSt
) | (1 << CP0DB_Halt
))) |
2106 (T0
& ~((1 << CP0DB_SSt
) | (1 << CP0DB_Halt
)));
2110 void op_mtc0_depc (void)
2116 void op_mtc0_performance0 (void)
2118 env
->CP0_Performance0
= T0
& 0x000007ff;
2122 void op_mtc0_taglo (void)
2124 env
->CP0_TagLo
= T0
& 0xFFFFFCF6;
2128 void op_mtc0_datalo (void)
2130 env
->CP0_DataLo
= T0
; /* XXX */
2134 void op_mtc0_taghi (void)
2136 env
->CP0_TagHi
= T0
; /* XXX */
2140 void op_mtc0_datahi (void)
2142 env
->CP0_DataHi
= T0
; /* XXX */
2146 void op_mtc0_errorepc (void)
2148 env
->CP0_ErrorEPC
= T0
;
2152 void op_mtc0_desave (void)
2154 env
->CP0_DESAVE
= T0
;
2158 #if defined(TARGET_MIPS64)
2159 void op_dmfc0_yqmask (void)
2161 T0
= env
->CP0_YQMask
;
2165 void op_dmfc0_vpeschedule (void)
2167 T0
= env
->CP0_VPESchedule
;
2171 void op_dmfc0_vpeschefback (void)
2173 T0
= env
->CP0_VPEScheFBack
;
2177 void op_dmfc0_entrylo0 (void)
2179 T0
= env
->CP0_EntryLo0
;
2183 void op_dmfc0_tcrestart (void)
2185 T0
= env
->PC
[env
->current_tc
];
2189 void op_dmfc0_tchalt (void)
2191 T0
= env
->CP0_TCHalt
[env
->current_tc
];
2195 void op_dmfc0_tccontext (void)
2197 T0
= env
->CP0_TCContext
[env
->current_tc
];
2201 void op_dmfc0_tcschedule (void)
2203 T0
= env
->CP0_TCSchedule
[env
->current_tc
];
2207 void op_dmfc0_tcschefback (void)
2209 T0
= env
->CP0_TCScheFBack
[env
->current_tc
];
2213 void op_dmfc0_entrylo1 (void)
2215 T0
= env
->CP0_EntryLo1
;
2219 void op_dmfc0_context (void)
2221 T0
= env
->CP0_Context
;
2225 void op_dmfc0_badvaddr (void)
2227 T0
= env
->CP0_BadVAddr
;
2231 void op_dmfc0_entryhi (void)
2233 T0
= env
->CP0_EntryHi
;
2237 void op_dmfc0_epc (void)
2243 void op_dmfc0_lladdr (void)
2245 T0
= env
->CP0_LLAddr
>> 4;
2249 void op_dmfc0_watchlo (void)
2251 T0
= env
->CP0_WatchLo
[PARAM1
];
2255 void op_dmfc0_xcontext (void)
2257 T0
= env
->CP0_XContext
;
2261 void op_dmfc0_depc (void)
2267 void op_dmfc0_errorepc (void)
2269 T0
= env
->CP0_ErrorEPC
;
2272 #endif /* TARGET_MIPS64 */
2274 /* MIPS MT functions */
2275 void op_mftgpr(void)
2277 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
2279 T0
= env
->gpr
[other_tc
][PARAM1
];
2285 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
2287 T0
= env
->LO
[other_tc
][PARAM1
];
2293 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
2295 T0
= env
->HI
[other_tc
][PARAM1
];
2299 void op_mftacx(void)
2301 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
2303 T0
= env
->ACX
[other_tc
][PARAM1
];
2307 void op_mftdsp(void)
2309 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
2311 T0
= env
->DSPControl
[other_tc
];
2315 void op_mttgpr(void)
2317 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
2319 T0
= env
->gpr
[other_tc
][PARAM1
];
2325 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
2327 T0
= env
->LO
[other_tc
][PARAM1
];
2333 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
2335 T0
= env
->HI
[other_tc
][PARAM1
];
2339 void op_mttacx(void)
2341 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
2343 T0
= env
->ACX
[other_tc
][PARAM1
];
2347 void op_mttdsp(void)
2349 int other_tc
= env
->CP0_VPEControl
& (0xff << CP0VPECo_TargTC
);
2351 T0
= env
->DSPControl
[other_tc
];
2392 // TODO: store to TC register
2399 /* No scheduling policy implemented. */
2401 if (env
->CP0_VPEControl
& (1 << CP0VPECo_YSI
) &&
2402 env
->CP0_TCStatus
[env
->current_tc
] & (1 << CP0TCSt_DT
)) {
2403 env
->CP0_VPEControl
&= ~(0x7 << CP0VPECo_EXCPT
);
2404 env
->CP0_VPEControl
|= 4 << CP0VPECo_EXCPT
;
2405 CALL_FROM_TB1(do_raise_exception
, EXCP_THREAD
);
2408 } else if (T0
== 0) {
2409 if (0 /* TODO: TC underflow */) {
2410 env
->CP0_VPEControl
&= ~(0x7 << CP0VPECo_EXCPT
);
2411 CALL_FROM_TB1(do_raise_exception
, EXCP_THREAD
);
2413 // TODO: Deallocate TC
2415 } else if (T0
> 0) {
2416 /* Yield qualifier inputs not implemented. */
2417 env
->CP0_VPEControl
&= ~(0x7 << CP0VPECo_EXCPT
);
2418 env
->CP0_VPEControl
|= 2 << CP0VPECo_EXCPT
;
2419 CALL_FROM_TB1(do_raise_exception
, EXCP_THREAD
);
2421 T0
= env
->CP0_YQMask
;
2427 # define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env)
2429 # define DEBUG_FPU_STATE() do { } while(0)
2434 CALL_FROM_TB1(do_cfc1
, PARAM1
);
2441 CALL_FROM_TB1(do_ctc1
, PARAM1
);
2460 void op_dmfc1 (void)
2467 void op_dmtc1 (void)
2474 void op_mfhc1 (void)
2481 void op_mthc1 (void)
2489 Single precition routines have a "s" suffix, double precision a
2490 "d" suffix, 32bit integer "w", 64bit integer "l", paired singe "ps",
2491 paired single lowwer "pl", paired single upper "pu". */
2493 #define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void)
2497 CALL_FROM_TB0(do_float_cvtd_s
);
2503 CALL_FROM_TB0(do_float_cvtd_w
);
2509 CALL_FROM_TB0(do_float_cvtd_l
);
2515 CALL_FROM_TB0(do_float_cvtl_d
);
2521 CALL_FROM_TB0(do_float_cvtl_s
);
2534 CALL_FROM_TB0(do_float_cvtps_pw
);
2540 CALL_FROM_TB0(do_float_cvtpw_ps
);
2546 CALL_FROM_TB0(do_float_cvts_d
);
2552 CALL_FROM_TB0(do_float_cvts_w
);
2558 CALL_FROM_TB0(do_float_cvts_l
);
2564 CALL_FROM_TB0(do_float_cvts_pl
);
2570 CALL_FROM_TB0(do_float_cvts_pu
);
2576 CALL_FROM_TB0(do_float_cvtw_s
);
2582 CALL_FROM_TB0(do_float_cvtw_d
);
2589 DT2
= ((uint64_t)WT0
<< 32) | WT1
;
2595 DT2
= ((uint64_t)WT0
<< 32) | WTH1
;
2601 DT2
= ((uint64_t)WTH0
<< 32) | WT1
;
2607 DT2
= ((uint64_t)WTH0
<< 32) | WTH1
;
2612 #define FLOAT_ROUNDOP(op, ttype, stype) \
2613 FLOAT_OP(op ## ttype, stype) \
2615 CALL_FROM_TB0(do_float_ ## op ## ttype ## _ ## stype); \
2616 DEBUG_FPU_STATE(); \
2620 FLOAT_ROUNDOP(round
, l
, d
)
2621 FLOAT_ROUNDOP(round
, l
, s
)
2622 FLOAT_ROUNDOP(round
, w
, d
)
2623 FLOAT_ROUNDOP(round
, w
, s
)
2625 FLOAT_ROUNDOP(trunc
, l
, d
)
2626 FLOAT_ROUNDOP(trunc
, l
, s
)
2627 FLOAT_ROUNDOP(trunc
, w
, d
)
2628 FLOAT_ROUNDOP(trunc
, w
, s
)
2630 FLOAT_ROUNDOP(ceil
, l
, d
)
2631 FLOAT_ROUNDOP(ceil
, l
, s
)
2632 FLOAT_ROUNDOP(ceil
, w
, d
)
2633 FLOAT_ROUNDOP(ceil
, w
, s
)
2635 FLOAT_ROUNDOP(floor
, l
, d
)
2636 FLOAT_ROUNDOP(floor
, l
, s
)
2637 FLOAT_ROUNDOP(floor
, w
, d
)
2638 FLOAT_ROUNDOP(floor
, w
, s
)
2639 #undef FLOAR_ROUNDOP
2643 if (!(env
->fpu
->fcr31
& PARAM1
))
2650 if (!(env
->fpu
->fcr31
& PARAM1
))
2657 if (!(env
->fpu
->fcr31
& PARAM1
)) {
2666 if (env
->fpu
->fcr31
& PARAM1
)
2673 if (env
->fpu
->fcr31
& PARAM1
)
2680 if (env
->fpu
->fcr31
& PARAM1
) {
2734 /* operations calling helpers, for s, d and ps */
2735 #define FLOAT_HOP(name) \
2738 CALL_FROM_TB0(do_float_ ## name ## _d); \
2739 DEBUG_FPU_STATE(); \
2744 CALL_FROM_TB0(do_float_ ## name ## _s); \
2745 DEBUG_FPU_STATE(); \
2748 FLOAT_OP(name, ps) \
2750 CALL_FROM_TB0(do_float_ ## name ## _ps); \
2751 DEBUG_FPU_STATE(); \
2764 /* operations calling helpers, for s and d */
2765 #define FLOAT_HOP(name) \
2768 CALL_FROM_TB0(do_float_ ## name ## _d); \
2769 DEBUG_FPU_STATE(); \
2774 CALL_FROM_TB0(do_float_ ## name ## _s); \
2775 DEBUG_FPU_STATE(); \
2782 /* operations calling helpers, for ps */
2783 #define FLOAT_HOP(name) \
2784 FLOAT_OP(name, ps) \
2786 CALL_FROM_TB0(do_float_ ## name ## _ps); \
2787 DEBUG_FPU_STATE(); \
2794 /* ternary operations */
2795 #define FLOAT_TERNOP(name1, name2) \
2796 FLOAT_OP(name1 ## name2, d) \
2798 FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status); \
2799 FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status); \
2800 DEBUG_FPU_STATE(); \
2803 FLOAT_OP(name1 ## name2, s) \
2805 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
2806 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
2807 DEBUG_FPU_STATE(); \
2810 FLOAT_OP(name1 ## name2, ps) \
2812 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
2813 FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \
2814 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
2815 FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \
2816 DEBUG_FPU_STATE(); \
2819 FLOAT_TERNOP(mul
, add
)
2820 FLOAT_TERNOP(mul
, sub
)
2823 /* negated ternary operations */
2824 #define FLOAT_NTERNOP(name1, name2) \
2825 FLOAT_OP(n ## name1 ## name2, d) \
2827 FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status); \
2828 FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status); \
2829 FDT2 = float64_chs(FDT2); \
2830 DEBUG_FPU_STATE(); \
2833 FLOAT_OP(n ## name1 ## name2, s) \
2835 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
2836 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
2837 FST2 = float32_chs(FST2); \
2838 DEBUG_FPU_STATE(); \
2841 FLOAT_OP(n ## name1 ## name2, ps) \
2843 FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
2844 FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \
2845 FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
2846 FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \
2847 FST2 = float32_chs(FST2); \
2848 FSTH2 = float32_chs(FSTH2); \
2849 DEBUG_FPU_STATE(); \
2852 FLOAT_NTERNOP(mul
, add
)
2853 FLOAT_NTERNOP(mul
, sub
)
2854 #undef FLOAT_NTERNOP
2856 /* unary operations, modifying fp status */
2857 #define FLOAT_UNOP(name) \
2860 FDT2 = float64_ ## name(FDT0, &env->fpu->fp_status); \
2861 DEBUG_FPU_STATE(); \
2866 FST2 = float32_ ## name(FST0, &env->fpu->fp_status); \
2867 DEBUG_FPU_STATE(); \
2873 /* unary operations, not modifying fp status */
2874 #define FLOAT_UNOP(name) \
2877 FDT2 = float64_ ## name(FDT0); \
2878 DEBUG_FPU_STATE(); \
2883 FST2 = float32_ ## name(FST0); \
2884 DEBUG_FPU_STATE(); \
2887 FLOAT_OP(name, ps) \
2889 FST2 = float32_ ## name(FST0); \
2890 FSTH2 = float32_ ## name(FSTH0); \
2891 DEBUG_FPU_STATE(); \
2925 #ifdef TARGET_WORDS_BIGENDIAN
2933 default: /* unpredictable */
2940 #ifdef CONFIG_SOFTFLOAT
2941 #define clear_invalid() do { \
2942 int flags = get_float_exception_flags(&env->fpu->fp_status); \
2943 flags &= ~float_flag_invalid; \
2944 set_float_exception_flags(flags, &env->fpu->fp_status); \
2947 #define clear_invalid() do { } while(0)
2950 extern void dump_fpu_s(CPUState
*env
);
2952 #define CMP_OP(fmt, op) \
2953 void OPPROTO op_cmp ## _ ## fmt ## _ ## op(void) \
2955 CALL_FROM_TB1(do_cmp ## _ ## fmt ## _ ## op, PARAM1); \
2956 DEBUG_FPU_STATE(); \
2959 void OPPROTO op_cmpabs ## _ ## fmt ## _ ## op(void) \
2961 CALL_FROM_TB1(do_cmpabs ## _ ## fmt ## _ ## op, PARAM1); \
2962 DEBUG_FPU_STATE(); \
2965 #define CMP_OPS(op) \
2991 T0
= !!(~GET_FP_COND(env
->fpu
) & (0x1 << PARAM1
));
2995 void op_bc1any2f (void)
2997 T0
= !!(~GET_FP_COND(env
->fpu
) & (0x3 << PARAM1
));
3001 void op_bc1any4f (void)
3003 T0
= !!(~GET_FP_COND(env
->fpu
) & (0xf << PARAM1
));
3010 T0
= !!(GET_FP_COND(env
->fpu
) & (0x1 << PARAM1
));
3014 void op_bc1any2t (void)
3016 T0
= !!(GET_FP_COND(env
->fpu
) & (0x3 << PARAM1
));
3020 void op_bc1any4t (void)
3022 T0
= !!(GET_FP_COND(env
->fpu
) & (0xf << PARAM1
));
3027 void op_tlbwi (void)
3029 CALL_FROM_TB0(env
->tlb
->do_tlbwi
);
3033 void op_tlbwr (void)
3035 CALL_FROM_TB0(env
->tlb
->do_tlbwr
);
3041 CALL_FROM_TB0(env
->tlb
->do_tlbp
);
3047 CALL_FROM_TB0(env
->tlb
->do_tlbr
);
3052 #if defined (CONFIG_USER_ONLY)
3053 void op_tls_value (void)
3055 T0
= env
->tls_value
;
3061 CALL_FROM_TB1(do_pmon
, PARAM1
);
3067 T0
= env
->CP0_Status
;
3068 env
->CP0_Status
= T0
& ~(1 << CP0St_IE
);
3069 CALL_FROM_TB1(cpu_mips_update_irq
, env
);
3075 T0
= env
->CP0_Status
;
3076 env
->CP0_Status
= T0
| (1 << CP0St_IE
);
3077 CALL_FROM_TB1(cpu_mips_update_irq
, env
);
3084 CALL_FROM_TB1(do_raise_exception
, EXCP_TRAP
);
3089 void op_debug (void)
3091 CALL_FROM_TB1(do_raise_exception
, EXCP_DEBUG
);
3095 void debug_pre_eret (void);
3096 void debug_post_eret (void);
3099 if (loglevel
& CPU_LOG_EXEC
)
3100 CALL_FROM_TB0(debug_pre_eret
);
3101 if (env
->CP0_Status
& (1 << CP0St_ERL
)) {
3102 env
->PC
[env
->current_tc
] = env
->CP0_ErrorEPC
;
3103 env
->CP0_Status
&= ~(1 << CP0St_ERL
);
3105 env
->PC
[env
->current_tc
] = env
->CP0_EPC
;
3106 env
->CP0_Status
&= ~(1 << CP0St_EXL
);
3108 CALL_FROM_TB1(compute_hflags
, env
);
3109 if (loglevel
& CPU_LOG_EXEC
)
3110 CALL_FROM_TB0(debug_post_eret
);
3111 env
->CP0_LLAddr
= 1;
3115 void op_deret (void)
3117 if (loglevel
& CPU_LOG_EXEC
)
3118 CALL_FROM_TB0(debug_pre_eret
);
3119 env
->PC
[env
->current_tc
] = env
->CP0_DEPC
;
3120 env
->hflags
&= MIPS_HFLAG_DM
;
3121 CALL_FROM_TB1(compute_hflags
, env
);
3122 if (loglevel
& CPU_LOG_EXEC
)
3123 CALL_FROM_TB0(debug_post_eret
);
3124 env
->CP0_LLAddr
= 1;
3128 void op_rdhwr_cpunum(void)
3130 if ((env
->hflags
& MIPS_HFLAG_CP0
) ||
3131 (env
->CP0_HWREna
& (1 << 0)))
3132 T0
= env
->CP0_EBase
& 0x3ff;
3134 CALL_FROM_TB1(do_raise_exception
, EXCP_RI
);
3138 void op_rdhwr_synci_step(void)
3140 if ((env
->hflags
& MIPS_HFLAG_CP0
) ||
3141 (env
->CP0_HWREna
& (1 << 1)))
3142 T0
= env
->SYNCI_Step
;
3144 CALL_FROM_TB1(do_raise_exception
, EXCP_RI
);
3148 void op_rdhwr_cc(void)
3150 if ((env
->hflags
& MIPS_HFLAG_CP0
) ||
3151 (env
->CP0_HWREna
& (1 << 2)))
3152 T0
= env
->CP0_Count
;
3154 CALL_FROM_TB1(do_raise_exception
, EXCP_RI
);
3158 void op_rdhwr_ccres(void)
3160 if ((env
->hflags
& MIPS_HFLAG_CP0
) ||
3161 (env
->CP0_HWREna
& (1 << 3)))
3164 CALL_FROM_TB1(do_raise_exception
, EXCP_RI
);
3168 void op_save_state (void)
3170 env
->hflags
= PARAM1
;
3174 void op_save_pc (void)
3176 env
->PC
[env
->current_tc
] = PARAM1
;
3180 #if defined(TARGET_MIPS64)
3181 void op_save_pc64 (void)
3183 env
->PC
[env
->current_tc
] = ((uint64_t)PARAM1
<< 32) | (uint32_t)PARAM2
;
3188 void op_interrupt_restart (void)
3190 if (!(env
->CP0_Status
& (1 << CP0St_EXL
)) &&
3191 !(env
->CP0_Status
& (1 << CP0St_ERL
)) &&
3192 !(env
->hflags
& MIPS_HFLAG_DM
) &&
3193 (env
->CP0_Status
& (1 << CP0St_IE
)) &&
3194 (env
->CP0_Status
& env
->CP0_Cause
& CP0Ca_IP_mask
)) {
3195 env
->CP0_Cause
&= ~(0x1f << CP0Ca_EC
);
3196 CALL_FROM_TB1(do_raise_exception
, EXCP_EXT_INTERRUPT
);
3201 void op_raise_exception (void)
3203 CALL_FROM_TB1(do_raise_exception
, PARAM1
);
3207 void op_raise_exception_err (void)
3209 CALL_FROM_TB2(do_raise_exception_err
, PARAM1
, PARAM2
);
3216 CALL_FROM_TB1(do_raise_exception
, EXCP_HLT
);
3220 /* Bitfield operations. */
3223 unsigned int pos
= PARAM1
;
3224 unsigned int size
= PARAM2
;
3226 T0
= (int32_t)((T1
>> pos
) & ((size
< 32) ? ((1 << size
) - 1) : ~0));
3232 unsigned int pos
= PARAM1
;
3233 unsigned int size
= PARAM2
;
3234 target_ulong mask
= ((size
< 32) ? ((1 << size
) - 1) : ~0) << pos
;
3236 T0
= (int32_t)((T0
& ~mask
) | ((T1
<< pos
) & mask
));
3242 T0
= (int32_t)(((T1
<< 8) & ~0x00FF00FF) | ((T1
>> 8) & 0x00FF00FF));
3246 #if defined(TARGET_MIPS64)
3249 unsigned int pos
= PARAM1
;
3250 unsigned int size
= PARAM2
;
3252 T0
= (T1
>> pos
) & ((size
< 64) ? ((1ULL << size
) - 1) : ~0ULL);
3258 unsigned int pos
= PARAM1
;
3259 unsigned int size
= PARAM2
;
3260 target_ulong mask
= ((size
< 64) ? ((1ULL << size
) - 1) : ~0ULL) << pos
;
3262 T0
= (T0
& ~mask
) | ((T1
<< pos
) & mask
);
3268 T0
= ((T1
<< 8) & ~0x00FF00FF00FF00FFULL
) | ((T1
>> 8) & 0x00FF00FF00FF00FFULL
);
3274 T1
= ((T1
<< 16) & ~0x0000FFFF0000FFFFULL
) | ((T1
>> 16) & 0x0000FFFF0000FFFFULL
);
3275 T0
= (T1
<< 32) | (T1
>> 32);
3282 T0
= ((T1
& 0xFF) ^ 0x80) - 0x80;
3288 T0
= ((T1
& 0xFFFF) ^ 0x8000) - 0x8000;