Commit 7a387fffce508fedae82e3e81b90d1f20c02c783
1 parent
8c0fdd85
Add MIPS32R2 instructions, and generally straighten out the instruction
decoding. This is also the first percent towards MIPS64 support. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2224 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
7 changed files
with
2235 additions
and
591 deletions
target-mips/cpu.h
@@ -99,14 +99,16 @@ struct CPUMIPSState { | @@ -99,14 +99,16 @@ struct CPUMIPSState { | ||
99 | #endif | 99 | #endif |
100 | uint32_t CP0_index; | 100 | uint32_t CP0_index; |
101 | uint32_t CP0_random; | 101 | uint32_t CP0_random; |
102 | - uint32_t CP0_EntryLo0; | ||
103 | - uint32_t CP0_EntryLo1; | ||
104 | - uint32_t CP0_Context; | 102 | + uint64_t CP0_EntryLo0; |
103 | + uint64_t CP0_EntryLo1; | ||
104 | + uint64_t CP0_Context; | ||
105 | uint32_t CP0_PageMask; | 105 | uint32_t CP0_PageMask; |
106 | + uint32_t CP0_PageGrain; | ||
106 | uint32_t CP0_Wired; | 107 | uint32_t CP0_Wired; |
108 | + uint32_t CP0_HWREna; | ||
107 | uint32_t CP0_BadVAddr; | 109 | uint32_t CP0_BadVAddr; |
108 | uint32_t CP0_Count; | 110 | uint32_t CP0_Count; |
109 | - uint32_t CP0_EntryHi; | 111 | + uint64_t CP0_EntryHi; |
110 | uint32_t CP0_Compare; | 112 | uint32_t CP0_Compare; |
111 | uint32_t CP0_Status; | 113 | uint32_t CP0_Status; |
112 | #define CP0St_CU3 31 | 114 | #define CP0St_CU3 31 |
@@ -116,19 +118,36 @@ struct CPUMIPSState { | @@ -116,19 +118,36 @@ struct CPUMIPSState { | ||
116 | #define CP0St_RP 27 | 118 | #define CP0St_RP 27 |
117 | #define CP0St_FR 26 | 119 | #define CP0St_FR 26 |
118 | #define CP0St_RE 25 | 120 | #define CP0St_RE 25 |
121 | +#define CP0St_MX 24 | ||
122 | +#define CP0St_PX 23 | ||
119 | #define CP0St_BEV 22 | 123 | #define CP0St_BEV 22 |
120 | #define CP0St_TS 21 | 124 | #define CP0St_TS 21 |
121 | #define CP0St_SR 20 | 125 | #define CP0St_SR 20 |
122 | #define CP0St_NMI 19 | 126 | #define CP0St_NMI 19 |
123 | #define CP0St_IM 8 | 127 | #define CP0St_IM 8 |
128 | +#define CP0St_KX 7 | ||
129 | +#define CP0St_SX 6 | ||
130 | +#define CP0St_UX 5 | ||
124 | #define CP0St_UM 4 | 131 | #define CP0St_UM 4 |
132 | +#define CP0St_R0 3 | ||
125 | #define CP0St_ERL 2 | 133 | #define CP0St_ERL 2 |
126 | #define CP0St_EXL 1 | 134 | #define CP0St_EXL 1 |
127 | #define CP0St_IE 0 | 135 | #define CP0St_IE 0 |
136 | + uint32_t CP0_IntCtl; | ||
137 | + uint32_t CP0_SRSCtl; | ||
128 | uint32_t CP0_Cause; | 138 | uint32_t CP0_Cause; |
139 | +#define CP0Ca_BD 31 | ||
140 | +#define CP0Ca_TI 30 | ||
141 | +#define CP0Ca_CE 28 | ||
142 | +#define CP0Ca_DC 27 | ||
143 | +#define CP0Ca_PCI 26 | ||
129 | #define CP0Ca_IV 23 | 144 | #define CP0Ca_IV 23 |
145 | +#define CP0Ca_WP 22 | ||
146 | +#define CP0Ca_IP 8 | ||
147 | +#define CP0Ca_EC 2 | ||
130 | uint32_t CP0_EPC; | 148 | uint32_t CP0_EPC; |
131 | uint32_t CP0_PRid; | 149 | uint32_t CP0_PRid; |
150 | + uint32_t CP0_EBase; | ||
132 | uint32_t CP0_Config0; | 151 | uint32_t CP0_Config0; |
133 | #define CP0C0_M 31 | 152 | #define CP0C0_M 31 |
134 | #define CP0C0_K23 28 | 153 | #define CP0C0_K23 28 |
@@ -140,8 +159,10 @@ struct CPUMIPSState { | @@ -140,8 +159,10 @@ struct CPUMIPSState { | ||
140 | #define CP0C0_AT 13 | 159 | #define CP0C0_AT 13 |
141 | #define CP0C0_AR 10 | 160 | #define CP0C0_AR 10 |
142 | #define CP0C0_MT 7 | 161 | #define CP0C0_MT 7 |
162 | +#define CP0C0_VI 3 | ||
143 | #define CP0C0_K0 0 | 163 | #define CP0C0_K0 0 |
144 | uint32_t CP0_Config1; | 164 | uint32_t CP0_Config1; |
165 | +#define CP0C1_M 31 | ||
145 | #define CP0C1_MMU 25 | 166 | #define CP0C1_MMU 25 |
146 | #define CP0C1_IS 22 | 167 | #define CP0C1_IS 22 |
147 | #define CP0C1_IL 19 | 168 | #define CP0C1_IL 19 |
@@ -149,14 +170,38 @@ struct CPUMIPSState { | @@ -149,14 +170,38 @@ struct CPUMIPSState { | ||
149 | #define CP0C1_DS 13 | 170 | #define CP0C1_DS 13 |
150 | #define CP0C1_DL 10 | 171 | #define CP0C1_DL 10 |
151 | #define CP0C1_DA 7 | 172 | #define CP0C1_DA 7 |
173 | +#define CP0C1_C2 6 | ||
174 | +#define CP0C1_MD 5 | ||
152 | #define CP0C1_PC 4 | 175 | #define CP0C1_PC 4 |
153 | #define CP0C1_WR 3 | 176 | #define CP0C1_WR 3 |
154 | #define CP0C1_CA 2 | 177 | #define CP0C1_CA 2 |
155 | #define CP0C1_EP 1 | 178 | #define CP0C1_EP 1 |
156 | #define CP0C1_FP 0 | 179 | #define CP0C1_FP 0 |
180 | + uint32_t CP0_Config2; | ||
181 | +#define CP0C2_M 31 | ||
182 | +#define CP0C2_TU 28 | ||
183 | +#define CP0C2_TS 24 | ||
184 | +#define CP0C2_TL 20 | ||
185 | +#define CP0C2_TA 16 | ||
186 | +#define CP0C2_SU 12 | ||
187 | +#define CP0C2_SS 8 | ||
188 | +#define CP0C2_SL 4 | ||
189 | +#define CP0C2_SA 0 | ||
190 | + uint32_t CP0_Config3; | ||
191 | +#define CP0C3_M 31 | ||
192 | +#define CP0C3_DSPP 10 | ||
193 | +#define CP0C3_LPA 7 | ||
194 | +#define CP0C3_VEIC 6 | ||
195 | +#define CP0C3_VInt 5 | ||
196 | +#define CP0C3_SP 4 | ||
197 | +#define CP0C3_MT 2 | ||
198 | +#define CP0C3_SM 1 | ||
199 | +#define CP0C3_TL 0 | ||
157 | uint32_t CP0_LLAddr; | 200 | uint32_t CP0_LLAddr; |
158 | uint32_t CP0_WatchLo; | 201 | uint32_t CP0_WatchLo; |
159 | uint32_t CP0_WatchHi; | 202 | uint32_t CP0_WatchHi; |
203 | + uint32_t CP0_XContext; | ||
204 | + uint32_t CP0_Framemask; | ||
160 | uint32_t CP0_Debug; | 205 | uint32_t CP0_Debug; |
161 | #define CPDB_DBD 31 | 206 | #define CPDB_DBD 31 |
162 | #define CP0DB_DM 30 | 207 | #define CP0DB_DM 30 |
@@ -177,8 +222,11 @@ struct CPUMIPSState { | @@ -177,8 +222,11 @@ struct CPUMIPSState { | ||
177 | #define CP0DB_DBp 1 | 222 | #define CP0DB_DBp 1 |
178 | #define CP0DB_DSS 0 | 223 | #define CP0DB_DSS 0 |
179 | uint32_t CP0_DEPC; | 224 | uint32_t CP0_DEPC; |
225 | + uint32_t CP0_Performance0; | ||
180 | uint32_t CP0_TagLo; | 226 | uint32_t CP0_TagLo; |
181 | uint32_t CP0_DataLo; | 227 | uint32_t CP0_DataLo; |
228 | + uint32_t CP0_TagHi; | ||
229 | + uint32_t CP0_DataHi; | ||
182 | uint32_t CP0_ErrorEPC; | 230 | uint32_t CP0_ErrorEPC; |
183 | uint32_t CP0_DESAVE; | 231 | uint32_t CP0_DESAVE; |
184 | /* Qemu */ | 232 | /* Qemu */ |
@@ -211,6 +259,9 @@ struct CPUMIPSState { | @@ -211,6 +259,9 @@ struct CPUMIPSState { | ||
211 | 259 | ||
212 | int halted; /* TRUE if the CPU is in suspend state */ | 260 | int halted; /* TRUE if the CPU is in suspend state */ |
213 | 261 | ||
262 | + int SYNCI_Step; /* Address step size for SYNCI */ | ||
263 | + int CCRes; /* Cycle count resolution/divisor */ | ||
264 | + | ||
214 | CPU_COMMON | 265 | CPU_COMMON |
215 | 266 | ||
216 | int ram_size; | 267 | int ram_size; |
target-mips/exec.h
@@ -68,6 +68,7 @@ void do_msubu (void); | @@ -68,6 +68,7 @@ void do_msubu (void); | ||
68 | #endif | 68 | #endif |
69 | void do_mfc0_random(void); | 69 | void do_mfc0_random(void); |
70 | void do_mfc0_count(void); | 70 | void do_mfc0_count(void); |
71 | +void do_mtc0_entryhi(uint32_t in); | ||
71 | void do_mtc0_status_debug(uint32_t old, uint32_t val); | 72 | void do_mtc0_status_debug(uint32_t old, uint32_t val); |
72 | void do_mtc0_status_irqraise_debug(void); | 73 | void do_mtc0_status_irqraise_debug(void); |
73 | void do_tlbwi (void); | 74 | void do_tlbwi (void); |
target-mips/helper.c
@@ -302,15 +302,9 @@ void do_interrupt (CPUState *env) | @@ -302,15 +302,9 @@ void do_interrupt (CPUState *env) | ||
302 | #endif | 302 | #endif |
303 | env->CP0_Wired = 0; | 303 | env->CP0_Wired = 0; |
304 | env->CP0_Config0 = MIPS_CONFIG0; | 304 | env->CP0_Config0 = MIPS_CONFIG0; |
305 | -#if defined (MIPS_CONFIG1) | ||
306 | env->CP0_Config1 = MIPS_CONFIG1; | 305 | env->CP0_Config1 = MIPS_CONFIG1; |
307 | -#endif | ||
308 | -#if defined (MIPS_CONFIG2) | ||
309 | env->CP0_Config2 = MIPS_CONFIG2; | 306 | env->CP0_Config2 = MIPS_CONFIG2; |
310 | -#endif | ||
311 | -#if defined (MIPS_CONFIG3) | ||
312 | env->CP0_Config3 = MIPS_CONFIG3; | 307 | env->CP0_Config3 = MIPS_CONFIG3; |
313 | -#endif | ||
314 | env->CP0_WatchLo = 0; | 308 | env->CP0_WatchLo = 0; |
315 | env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV); | 309 | env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV); |
316 | goto set_error_EPC; | 310 | goto set_error_EPC; |
target-mips/mips-defs.h
@@ -29,26 +29,44 @@ | @@ -29,26 +29,44 @@ | ||
29 | * Define a major version 1, minor version 0. | 29 | * Define a major version 1, minor version 0. |
30 | */ | 30 | */ |
31 | #define MIPS_FCR0 ((0 << 16) | (1 << 8) | (1 << 4) | 0) | 31 | #define MIPS_FCR0 ((0 << 16) | (1 << 8) | (1 << 4) | 0) |
32 | -/* Have config1, uses TLB */ | ||
33 | -#define MIPS_CONFIG0_1 \ | ||
34 | -((1 << CP0C0_M) | (0 << CP0C0_K23) | (0 << CP0C0_KU) | \ | ||
35 | - (1 << CP0C0_MT) | (2 << CP0C0_K0)) | 32 | + /* Have config1, is MIPS32R1, uses TLB, no virtual icache, |
33 | + uncached coherency */ | ||
34 | +#define MIPS_CONFIG0_1 \ | ||
35 | + ((1 << CP0C0_M) | (0x0 << CP0C0_K23) | (0x0 << CP0C0_KU) | \ | ||
36 | + (0x0 << CP0C0_AT) | (0x0 << CP0C0_AR) | (0x1 << CP0C0_MT) | \ | ||
37 | + (0x2 << CP0C0_K0)) | ||
36 | #ifdef TARGET_WORDS_BIGENDIAN | 38 | #ifdef TARGET_WORDS_BIGENDIAN |
37 | #define MIPS_CONFIG0 (MIPS_CONFIG0_1 | (1 << CP0C0_BE)) | 39 | #define MIPS_CONFIG0 (MIPS_CONFIG0_1 | (1 << CP0C0_BE)) |
38 | #else | 40 | #else |
39 | #define MIPS_CONFIG0 MIPS_CONFIG0_1 | 41 | #define MIPS_CONFIG0 MIPS_CONFIG0_1 |
40 | #endif | 42 | #endif |
41 | -/* 16 TLBs, 64 sets Icache, 16 bytes Icache line, 2-way Icache, | ||
42 | - * 64 sets Dcache, 16 bytes Dcache line, 2-way Dcache, | ||
43 | - * no performance counters, watch registers present, no code compression, | ||
44 | - * EJTAG present, FPU enable bit depending on MIPS_USES_FPU | ||
45 | - */ | ||
46 | -#define MIPS_CONFIG1 \ | ||
47 | -((15 << CP0C1_MMU) | \ | ||
48 | - (0x000 << CP0C1_IS) | (0x3 << CP0C1_IL) | (0x01 << CP0C1_IA) | \ | ||
49 | - (0x000 << CP0C1_DS) | (0x3 << CP0C1_DL) | (0x01 << CP0C1_DA) | \ | ||
50 | - (0 << CP0C1_PC) | (1 << CP0C1_WR) | (0 << CP0C1_CA) | \ | ||
51 | - (1 << CP0C1_EP) | (MIPS_USES_FPU << CP0C1_FP)) | 43 | +/* Have config2, 16 TLB entries, 64 sets Icache, 16 bytes Icache line, |
44 | + 2-way Icache, 64 sets Dcache, 16 bytes Dcache line, 2-way Dcache, | ||
45 | + no coprocessor2 attached, no MDMX support attached, | ||
46 | + no performance counters, watch registers present, | ||
47 | + no code compression, EJTAG present, FPU enable bit depending on | ||
48 | + MIPS_USES_FPU */ | ||
49 | +#define MIPS_CONFIG1_1 \ | ||
50 | +((1 << CP0C1_M) | ((MIPS_TLB_NB - 1) << CP0C1_MMU) | \ | ||
51 | + (0x0 << CP0C1_IS) | (0x3 << CP0C1_IL) | (0x1 << CP0C1_IA) | \ | ||
52 | + (0x0 << CP0C1_DS) | (0x3 << CP0C1_DL) | (0x1 << CP0C1_DA) | \ | ||
53 | + (0 << CP0C1_C2) | (0 << CP0C1_MD) | (0 << CP0C1_PC) | \ | ||
54 | + (1 << CP0C1_WR) | (0 << CP0C1_CA) | (1 << CP0C1_EP)) | ||
55 | +#ifdef MIPS_USES_FPU | ||
56 | +#define MIPS_CONFIG1 (MIPS_CONFIG1_1 | (1 << CP0C1_FP)) | ||
57 | +#else | ||
58 | +#define MIPS_CONFIG1 (MIPS_CONFIG1_1 | (0 << CP0C1_FP)) | ||
59 | +#endif | ||
60 | +/* Have config3, no tertiary/secondary caches implemented */ | ||
61 | +#define MIPS_CONFIG2 \ | ||
62 | +((1 << CP0C2_M)) | ||
63 | +/* No config4, no DSP ASE, no large physaddr, | ||
64 | + no external interrupt controller, no vectored interupts, | ||
65 | + no 1kb pages, no MT ASE, no SmartMIPS ASE, no trace logic */ | ||
66 | +#define MIPS_CONFIG3 \ | ||
67 | +((0 << CP0C3_M) | (0 << CP0C3_DSPP) | (0 << CP0C3_LPA) | \ | ||
68 | + (0 << CP0C3_VEIC) | (0 << CP0C3_VInt) | (0 << CP0C3_SP) | \ | ||
69 | + (0 << CP0C3_MT) | (0 << CP0C3_SM) | (0 << CP0C3_TL)) | ||
52 | #elif (MIPS_CPU == MIPS_R4Kp) | 70 | #elif (MIPS_CPU == MIPS_R4Kp) |
53 | /* 32 bits target */ | 71 | /* 32 bits target */ |
54 | #define TARGET_LONG_BITS 32 | 72 | #define TARGET_LONG_BITS 32 |
@@ -60,7 +78,7 @@ | @@ -60,7 +78,7 @@ | ||
60 | #define MIPS_USES_R4K_FPM | 78 | #define MIPS_USES_R4K_FPM |
61 | #else | 79 | #else |
62 | #error "MIPS CPU not defined" | 80 | #error "MIPS CPU not defined" |
63 | -/* Remainder for other flags */ | 81 | +/* Reminder for other flags */ |
64 | //#define TARGET_MIPS64 | 82 | //#define TARGET_MIPS64 |
65 | //#define MIPS_USES_FPU | 83 | //#define MIPS_USES_FPU |
66 | #endif | 84 | #endif |
target-mips/op.c
@@ -437,6 +437,18 @@ void op_srl (void) | @@ -437,6 +437,18 @@ void op_srl (void) | ||
437 | RETURN(); | 437 | RETURN(); |
438 | } | 438 | } |
439 | 439 | ||
440 | +void op_rotr (void) | ||
441 | +{ | ||
442 | + target_ulong tmp; | ||
443 | + | ||
444 | + if (T1) { | ||
445 | + tmp = T0 << (0x20 - T1); | ||
446 | + T0 = (T0 >> T1) | tmp; | ||
447 | + } else | ||
448 | + T0 = T1; | ||
449 | + RETURN(); | ||
450 | +} | ||
451 | + | ||
440 | void op_sllv (void) | 452 | void op_sllv (void) |
441 | { | 453 | { |
442 | T0 = T1 << (T0 & 0x1F); | 454 | T0 = T1 << (T0 & 0x1F); |
@@ -455,6 +467,19 @@ void op_srlv (void) | @@ -455,6 +467,19 @@ void op_srlv (void) | ||
455 | RETURN(); | 467 | RETURN(); |
456 | } | 468 | } |
457 | 469 | ||
470 | +void op_rotrv (void) | ||
471 | +{ | ||
472 | + target_ulong tmp; | ||
473 | + | ||
474 | + T0 &= 0x1F; | ||
475 | + if (T0) { | ||
476 | + tmp = T1 << (0x20 - T0); | ||
477 | + T0 = (T1 >> T0) | tmp; | ||
478 | + } else | ||
479 | + T0 = T1; | ||
480 | + RETURN(); | ||
481 | +} | ||
482 | + | ||
458 | void op_clo (void) | 483 | void op_clo (void) |
459 | { | 484 | { |
460 | int n; | 485 | int n; |
@@ -602,6 +627,20 @@ void op_movz (void) | @@ -602,6 +627,20 @@ void op_movz (void) | ||
602 | RETURN(); | 627 | RETURN(); |
603 | } | 628 | } |
604 | 629 | ||
630 | +void op_movf (void) | ||
631 | +{ | ||
632 | + if (!(env->fcr31 & PARAM1)) | ||
633 | + env->gpr[PARAM2] = env->gpr[PARAM3]; | ||
634 | + RETURN(); | ||
635 | +} | ||
636 | + | ||
637 | +void op_movt (void) | ||
638 | +{ | ||
639 | + if (env->fcr31 & PARAM1) | ||
640 | + env->gpr[PARAM2] = env->gpr[PARAM3]; | ||
641 | + RETURN(); | ||
642 | +} | ||
643 | + | ||
605 | /* Tests */ | 644 | /* Tests */ |
606 | #define OP_COND(name, cond) \ | 645 | #define OP_COND(name, cond) \ |
607 | void glue(op_, name) (void) \ | 646 | void glue(op_, name) (void) \ |
@@ -625,28 +664,32 @@ OP_COND(gtz, (int32_t)T0 > 0); | @@ -625,28 +664,32 @@ OP_COND(gtz, (int32_t)T0 > 0); | ||
625 | OP_COND(lez, (int32_t)T0 <= 0); | 664 | OP_COND(lez, (int32_t)T0 <= 0); |
626 | OP_COND(ltz, (int32_t)T0 < 0); | 665 | OP_COND(ltz, (int32_t)T0 < 0); |
627 | 666 | ||
628 | -/* Branchs */ | 667 | +/* Branches */ |
629 | //#undef USE_DIRECT_JUMP | 668 | //#undef USE_DIRECT_JUMP |
630 | 669 | ||
631 | void OPPROTO op_goto_tb0(void) | 670 | void OPPROTO op_goto_tb0(void) |
632 | { | 671 | { |
633 | GOTO_TB(op_goto_tb0, PARAM1, 0); | 672 | GOTO_TB(op_goto_tb0, PARAM1, 0); |
673 | + RETURN(); | ||
634 | } | 674 | } |
635 | 675 | ||
636 | void OPPROTO op_goto_tb1(void) | 676 | void OPPROTO op_goto_tb1(void) |
637 | { | 677 | { |
638 | GOTO_TB(op_goto_tb1, PARAM1, 1); | 678 | GOTO_TB(op_goto_tb1, PARAM1, 1); |
679 | + RETURN(); | ||
639 | } | 680 | } |
640 | 681 | ||
641 | /* Branch to register */ | 682 | /* Branch to register */ |
642 | void op_save_breg_target (void) | 683 | void op_save_breg_target (void) |
643 | { | 684 | { |
644 | env->btarget = T2; | 685 | env->btarget = T2; |
686 | + RETURN(); | ||
645 | } | 687 | } |
646 | 688 | ||
647 | void op_restore_breg_target (void) | 689 | void op_restore_breg_target (void) |
648 | { | 690 | { |
649 | T2 = env->btarget; | 691 | T2 = env->btarget; |
692 | + RETURN(); | ||
650 | } | 693 | } |
651 | 694 | ||
652 | void op_breg (void) | 695 | void op_breg (void) |
@@ -724,12 +767,24 @@ void op_mfc0_pagemask (void) | @@ -724,12 +767,24 @@ void op_mfc0_pagemask (void) | ||
724 | RETURN(); | 767 | RETURN(); |
725 | } | 768 | } |
726 | 769 | ||
770 | +void op_mfc0_pagegrain (void) | ||
771 | +{ | ||
772 | + T0 = env->CP0_PageGrain; | ||
773 | + RETURN(); | ||
774 | +} | ||
775 | + | ||
727 | void op_mfc0_wired (void) | 776 | void op_mfc0_wired (void) |
728 | { | 777 | { |
729 | T0 = env->CP0_Wired; | 778 | T0 = env->CP0_Wired; |
730 | RETURN(); | 779 | RETURN(); |
731 | } | 780 | } |
732 | 781 | ||
782 | +void op_mfc0_hwrena (void) | ||
783 | +{ | ||
784 | + T0 = env->CP0_HWREna; | ||
785 | + RETURN(); | ||
786 | +} | ||
787 | + | ||
733 | void op_mfc0_badvaddr (void) | 788 | void op_mfc0_badvaddr (void) |
734 | { | 789 | { |
735 | T0 = env->CP0_BadVAddr; | 790 | T0 = env->CP0_BadVAddr; |
@@ -766,6 +821,18 @@ void op_mfc0_status (void) | @@ -766,6 +821,18 @@ void op_mfc0_status (void) | ||
766 | RETURN(); | 821 | RETURN(); |
767 | } | 822 | } |
768 | 823 | ||
824 | +void op_mfc0_intctl (void) | ||
825 | +{ | ||
826 | + T0 = env->CP0_IntCtl; | ||
827 | + RETURN(); | ||
828 | +} | ||
829 | + | ||
830 | +void op_mfc0_srsctl (void) | ||
831 | +{ | ||
832 | + T0 = env->CP0_SRSCtl; | ||
833 | + RETURN(); | ||
834 | +} | ||
835 | + | ||
769 | void op_mfc0_cause (void) | 836 | void op_mfc0_cause (void) |
770 | { | 837 | { |
771 | T0 = env->CP0_Cause; | 838 | T0 = env->CP0_Cause; |
@@ -784,6 +851,12 @@ void op_mfc0_prid (void) | @@ -784,6 +851,12 @@ void op_mfc0_prid (void) | ||
784 | RETURN(); | 851 | RETURN(); |
785 | } | 852 | } |
786 | 853 | ||
854 | +void op_mfc0_ebase (void) | ||
855 | +{ | ||
856 | + T0 = env->CP0_EBase; | ||
857 | + RETURN(); | ||
858 | +} | ||
859 | + | ||
787 | void op_mfc0_config0 (void) | 860 | void op_mfc0_config0 (void) |
788 | { | 861 | { |
789 | T0 = env->CP0_Config0; | 862 | T0 = env->CP0_Config0; |
@@ -796,24 +869,48 @@ void op_mfc0_config1 (void) | @@ -796,24 +869,48 @@ void op_mfc0_config1 (void) | ||
796 | RETURN(); | 869 | RETURN(); |
797 | } | 870 | } |
798 | 871 | ||
872 | +void op_mfc0_config2 (void) | ||
873 | +{ | ||
874 | + T0 = env->CP0_Config2; | ||
875 | + RETURN(); | ||
876 | +} | ||
877 | + | ||
878 | +void op_mfc0_config3 (void) | ||
879 | +{ | ||
880 | + T0 = env->CP0_Config3; | ||
881 | + RETURN(); | ||
882 | +} | ||
883 | + | ||
799 | void op_mfc0_lladdr (void) | 884 | void op_mfc0_lladdr (void) |
800 | { | 885 | { |
801 | T0 = env->CP0_LLAddr >> 4; | 886 | T0 = env->CP0_LLAddr >> 4; |
802 | RETURN(); | 887 | RETURN(); |
803 | } | 888 | } |
804 | 889 | ||
805 | -void op_mfc0_watchlo (void) | 890 | +void op_mfc0_watchlo0 (void) |
806 | { | 891 | { |
807 | T0 = env->CP0_WatchLo; | 892 | T0 = env->CP0_WatchLo; |
808 | RETURN(); | 893 | RETURN(); |
809 | } | 894 | } |
810 | 895 | ||
811 | -void op_mfc0_watchhi (void) | 896 | +void op_mfc0_watchhi0 (void) |
812 | { | 897 | { |
813 | T0 = env->CP0_WatchHi; | 898 | T0 = env->CP0_WatchHi; |
814 | RETURN(); | 899 | RETURN(); |
815 | } | 900 | } |
816 | 901 | ||
902 | +void op_mfc0_xcontext (void) | ||
903 | +{ | ||
904 | + T0 = env->CP0_XContext; | ||
905 | + RETURN(); | ||
906 | +} | ||
907 | + | ||
908 | +void op_mfc0_framemask (void) | ||
909 | +{ | ||
910 | + T0 = env->CP0_Framemask; | ||
911 | + RETURN(); | ||
912 | +} | ||
913 | + | ||
817 | void op_mfc0_debug (void) | 914 | void op_mfc0_debug (void) |
818 | { | 915 | { |
819 | T0 = env->CP0_Debug; | 916 | T0 = env->CP0_Debug; |
@@ -828,6 +925,12 @@ void op_mfc0_depc (void) | @@ -828,6 +925,12 @@ void op_mfc0_depc (void) | ||
828 | RETURN(); | 925 | RETURN(); |
829 | } | 926 | } |
830 | 927 | ||
928 | +void op_mfc0_performance0 (void) | ||
929 | +{ | ||
930 | + T0 = env->CP0_Performance0; | ||
931 | + RETURN(); | ||
932 | +} | ||
933 | + | ||
831 | void op_mfc0_taglo (void) | 934 | void op_mfc0_taglo (void) |
832 | { | 935 | { |
833 | T0 = env->CP0_TagLo; | 936 | T0 = env->CP0_TagLo; |
@@ -840,6 +943,18 @@ void op_mfc0_datalo (void) | @@ -840,6 +943,18 @@ void op_mfc0_datalo (void) | ||
840 | RETURN(); | 943 | RETURN(); |
841 | } | 944 | } |
842 | 945 | ||
946 | +void op_mfc0_taghi (void) | ||
947 | +{ | ||
948 | + T0 = env->CP0_TagHi; | ||
949 | + RETURN(); | ||
950 | +} | ||
951 | + | ||
952 | +void op_mfc0_datahi (void) | ||
953 | +{ | ||
954 | + T0 = env->CP0_DataHi; | ||
955 | + RETURN(); | ||
956 | +} | ||
957 | + | ||
843 | void op_mfc0_errorepc (void) | 958 | void op_mfc0_errorepc (void) |
844 | { | 959 | { |
845 | T0 = env->CP0_ErrorEPC; | 960 | T0 = env->CP0_ErrorEPC; |
@@ -854,37 +969,57 @@ void op_mfc0_desave (void) | @@ -854,37 +969,57 @@ void op_mfc0_desave (void) | ||
854 | 969 | ||
855 | void op_mtc0_index (void) | 970 | void op_mtc0_index (void) |
856 | { | 971 | { |
857 | - env->CP0_index = (env->CP0_index & 0x80000000) | (T0 & 0x0000000F); | 972 | + env->CP0_index = (env->CP0_index & 0x80000000) | (T0 & (MIPS_TLB_NB - 1)); |
858 | RETURN(); | 973 | RETURN(); |
859 | } | 974 | } |
860 | 975 | ||
861 | void op_mtc0_entrylo0 (void) | 976 | void op_mtc0_entrylo0 (void) |
862 | { | 977 | { |
863 | - env->CP0_EntryLo0 = T0 & 0x3FFFFFFF; | 978 | + /* Large physaddr not implemented */ |
979 | + /* 1k pages not implemented */ | ||
980 | + env->CP0_EntryLo0 = T0 & 0x3FFFFFFFUL; | ||
864 | RETURN(); | 981 | RETURN(); |
865 | } | 982 | } |
866 | 983 | ||
867 | void op_mtc0_entrylo1 (void) | 984 | void op_mtc0_entrylo1 (void) |
868 | { | 985 | { |
869 | - env->CP0_EntryLo1 = T0 & 0x3FFFFFFF; | 986 | + /* Large physaddr not implemented */ |
987 | + /* 1k pages not implemented */ | ||
988 | + env->CP0_EntryLo1 = T0 & 0x3FFFFFFFUL; | ||
870 | RETURN(); | 989 | RETURN(); |
871 | } | 990 | } |
872 | 991 | ||
873 | void op_mtc0_context (void) | 992 | void op_mtc0_context (void) |
874 | { | 993 | { |
875 | - env->CP0_Context = (env->CP0_Context & 0xFF800000) | (T0 & 0x007FFFF0); | 994 | + env->CP0_Context = (env->CP0_Context & ~0x007FFFFF) | (T0 & 0x007FFFF0); |
876 | RETURN(); | 995 | RETURN(); |
877 | } | 996 | } |
878 | 997 | ||
879 | void op_mtc0_pagemask (void) | 998 | void op_mtc0_pagemask (void) |
880 | { | 999 | { |
881 | - env->CP0_PageMask = T0 & 0x01FFE000; | 1000 | + /* 1k pages not implemented */ |
1001 | + env->CP0_PageMask = T0 & 0x1FFFE000; | ||
1002 | + RETURN(); | ||
1003 | +} | ||
1004 | + | ||
1005 | +void op_mtc0_pagegrain (void) | ||
1006 | +{ | ||
1007 | + /* SmartMIPS not implemented */ | ||
1008 | + /* Large physaddr not implemented */ | ||
1009 | + /* 1k pages not implemented */ | ||
1010 | + env->CP0_PageGrain = 0; | ||
882 | RETURN(); | 1011 | RETURN(); |
883 | } | 1012 | } |
884 | 1013 | ||
885 | void op_mtc0_wired (void) | 1014 | void op_mtc0_wired (void) |
886 | { | 1015 | { |
887 | - env->CP0_Wired = T0 & 0x0000000F; | 1016 | + env->CP0_Wired = T0 & (MIPS_TLB_NB - 1); |
1017 | + RETURN(); | ||
1018 | +} | ||
1019 | + | ||
1020 | +void op_mtc0_hwrena (void) | ||
1021 | +{ | ||
1022 | + env->CP0_HWREna = T0 & 0x0000000F; | ||
888 | RETURN(); | 1023 | RETURN(); |
889 | } | 1024 | } |
890 | 1025 | ||
@@ -898,6 +1033,8 @@ void op_mtc0_entryhi (void) | @@ -898,6 +1033,8 @@ void op_mtc0_entryhi (void) | ||
898 | { | 1033 | { |
899 | uint32_t old, val; | 1034 | uint32_t old, val; |
900 | 1035 | ||
1036 | + /* 1k pages not implemented */ | ||
1037 | + /* Ignore MIPS64 TLB for now */ | ||
901 | val = T0 & 0xFFFFE0FF; | 1038 | val = T0 & 0xFFFFE0FF; |
902 | old = env->CP0_EntryHi; | 1039 | old = env->CP0_EntryHi; |
903 | env->CP0_EntryHi = val; | 1040 | env->CP0_EntryHi = val; |
@@ -950,6 +1087,20 @@ void op_mtc0_status (void) | @@ -950,6 +1087,20 @@ void op_mtc0_status (void) | ||
950 | RETURN(); | 1087 | RETURN(); |
951 | } | 1088 | } |
952 | 1089 | ||
1090 | +void op_mtc0_intctl (void) | ||
1091 | +{ | ||
1092 | + /* vectored interrupts not implemented */ | ||
1093 | + env->CP0_IntCtl = 0; | ||
1094 | + RETURN(); | ||
1095 | +} | ||
1096 | + | ||
1097 | +void op_mtc0_srsctl (void) | ||
1098 | +{ | ||
1099 | + /* shadow registers not implemented */ | ||
1100 | + env->CP0_SRSCtl = 0; | ||
1101 | + RETURN(); | ||
1102 | +} | ||
1103 | + | ||
953 | void op_mtc0_cause (void) | 1104 | void op_mtc0_cause (void) |
954 | { | 1105 | { |
955 | uint32_t val, old; | 1106 | uint32_t val, old; |
@@ -960,7 +1111,6 @@ void op_mtc0_cause (void) | @@ -960,7 +1111,6 @@ void op_mtc0_cause (void) | ||
960 | #if 0 | 1111 | #if 0 |
961 | { | 1112 | { |
962 | int i, mask; | 1113 | int i, mask; |
963 | - | ||
964 | /* Check if we ever asserted a software IRQ */ | 1114 | /* Check if we ever asserted a software IRQ */ |
965 | for (i = 0; i < 2; i++) { | 1115 | for (i = 0; i < 2; i++) { |
966 | mask = 0x100 << i; | 1116 | mask = 0x100 << i; |
@@ -978,28 +1128,56 @@ void op_mtc0_epc (void) | @@ -978,28 +1128,56 @@ void op_mtc0_epc (void) | ||
978 | RETURN(); | 1128 | RETURN(); |
979 | } | 1129 | } |
980 | 1130 | ||
1131 | +void op_mtc0_ebase (void) | ||
1132 | +{ | ||
1133 | + /* vectored interrupts not implemented */ | ||
1134 | + /* Multi-CPU not implemented */ | ||
1135 | + env->CP0_EBase = 0x80000000 | (T0 & 0x3FFFF000); | ||
1136 | + RETURN(); | ||
1137 | +} | ||
1138 | + | ||
981 | void op_mtc0_config0 (void) | 1139 | void op_mtc0_config0 (void) |
982 | { | 1140 | { |
983 | #if defined(MIPS_USES_R4K_TLB) | 1141 | #if defined(MIPS_USES_R4K_TLB) |
984 | - env->CP0_Config0 = (env->CP0_Config0 & 0x8017FF80) | (T0 & 0x7E000001); | 1142 | + /* Fixed mapping MMU not implemented */ |
1143 | + env->CP0_Config0 = (env->CP0_Config0 & 0x8017FF88) | (T0 & 0x00000001); | ||
985 | #else | 1144 | #else |
986 | - env->CP0_Config0 = (env->CP0_Config0 & 0xFE17FF80) | (T0 & 0x00000001); | 1145 | + env->CP0_Config0 = (env->CP0_Config0 & 0xFE17FF88) | (T0 & 0x00000001); |
987 | #endif | 1146 | #endif |
988 | RETURN(); | 1147 | RETURN(); |
989 | } | 1148 | } |
990 | 1149 | ||
991 | -void op_mtc0_watchlo (void) | 1150 | +void op_mtc0_config2 (void) |
1151 | +{ | ||
1152 | + /* tertiary/secondary caches not implemented */ | ||
1153 | + env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF); | ||
1154 | + RETURN(); | ||
1155 | +} | ||
1156 | + | ||
1157 | +void op_mtc0_watchlo0 (void) | ||
992 | { | 1158 | { |
993 | env->CP0_WatchLo = T0; | 1159 | env->CP0_WatchLo = T0; |
994 | RETURN(); | 1160 | RETURN(); |
995 | } | 1161 | } |
996 | 1162 | ||
997 | -void op_mtc0_watchhi (void) | 1163 | +void op_mtc0_watchhi0 (void) |
998 | { | 1164 | { |
999 | env->CP0_WatchHi = T0 & 0x40FF0FF8; | 1165 | env->CP0_WatchHi = T0 & 0x40FF0FF8; |
1000 | RETURN(); | 1166 | RETURN(); |
1001 | } | 1167 | } |
1002 | 1168 | ||
1169 | +void op_mtc0_xcontext (void) | ||
1170 | +{ | ||
1171 | + env->CP0_XContext = T0; /* XXX */ | ||
1172 | + RETURN(); | ||
1173 | +} | ||
1174 | + | ||
1175 | +void op_mtc0_framemask (void) | ||
1176 | +{ | ||
1177 | + env->CP0_Framemask = T0; /* XXX */ | ||
1178 | + RETURN(); | ||
1179 | +} | ||
1180 | + | ||
1003 | void op_mtc0_debug (void) | 1181 | void op_mtc0_debug (void) |
1004 | { | 1182 | { |
1005 | env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120); | 1183 | env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120); |
@@ -1016,12 +1194,36 @@ void op_mtc0_depc (void) | @@ -1016,12 +1194,36 @@ void op_mtc0_depc (void) | ||
1016 | RETURN(); | 1194 | RETURN(); |
1017 | } | 1195 | } |
1018 | 1196 | ||
1197 | +void op_mtc0_performance0 (void) | ||
1198 | +{ | ||
1199 | + env->CP0_Performance0 = T0; /* XXX */ | ||
1200 | + RETURN(); | ||
1201 | +} | ||
1202 | + | ||
1019 | void op_mtc0_taglo (void) | 1203 | void op_mtc0_taglo (void) |
1020 | { | 1204 | { |
1021 | env->CP0_TagLo = T0 & 0xFFFFFCF6; | 1205 | env->CP0_TagLo = T0 & 0xFFFFFCF6; |
1022 | RETURN(); | 1206 | RETURN(); |
1023 | } | 1207 | } |
1024 | 1208 | ||
1209 | +void op_mtc0_datalo (void) | ||
1210 | +{ | ||
1211 | + env->CP0_DataLo = T0; /* XXX */ | ||
1212 | + RETURN(); | ||
1213 | +} | ||
1214 | + | ||
1215 | +void op_mtc0_taghi (void) | ||
1216 | +{ | ||
1217 | + env->CP0_TagHi = T0; /* XXX */ | ||
1218 | + RETURN(); | ||
1219 | +} | ||
1220 | + | ||
1221 | +void op_mtc0_datahi (void) | ||
1222 | +{ | ||
1223 | + env->CP0_DataHi = T0; /* XXX */ | ||
1224 | + RETURN(); | ||
1225 | +} | ||
1226 | + | ||
1025 | void op_mtc0_errorepc (void) | 1227 | void op_mtc0_errorepc (void) |
1026 | { | 1228 | { |
1027 | env->CP0_ErrorEPC = T0; | 1229 | env->CP0_ErrorEPC = T0; |
@@ -1422,6 +1624,42 @@ void op_tlbr (void) | @@ -1422,6 +1624,42 @@ void op_tlbr (void) | ||
1422 | void op_pmon (void) | 1624 | void op_pmon (void) |
1423 | { | 1625 | { |
1424 | CALL_FROM_TB1(do_pmon, PARAM1); | 1626 | CALL_FROM_TB1(do_pmon, PARAM1); |
1627 | + RETURN(); | ||
1628 | +} | ||
1629 | + | ||
1630 | +void op_di (void) | ||
1631 | +{ | ||
1632 | + uint32_t val; | ||
1633 | + | ||
1634 | + T0 = env->CP0_Status; | ||
1635 | + val = T0 & ~(1 << CP0St_IE); | ||
1636 | + if (val != T0) { | ||
1637 | + env->interrupt_request &= ~CPU_INTERRUPT_HARD; | ||
1638 | + env->CP0_Status = val; | ||
1639 | + } | ||
1640 | + RETURN(); | ||
1641 | +} | ||
1642 | + | ||
1643 | +void op_ei (void) | ||
1644 | +{ | ||
1645 | + uint32_t val; | ||
1646 | + | ||
1647 | + T0 = env->CP0_Status; | ||
1648 | + val = T0 | (1 << CP0St_IE); | ||
1649 | + if (val != T0) { | ||
1650 | + const uint32_t mask = 0x0000FF00; | ||
1651 | + | ||
1652 | + env->CP0_Status = val; | ||
1653 | + if (!(env->hflags & MIPS_HFLAG_EXL) && | ||
1654 | + !(env->hflags & MIPS_HFLAG_ERL) && | ||
1655 | + !(env->hflags & MIPS_HFLAG_DM) && | ||
1656 | + (env->CP0_Status & env->CP0_Cause & mask)) { | ||
1657 | + env->interrupt_request |= CPU_INTERRUPT_HARD; | ||
1658 | + if (logfile) | ||
1659 | + CALL_FROM_TB0(do_mtc0_status_irqraise_debug); | ||
1660 | + } | ||
1661 | + } | ||
1662 | + RETURN(); | ||
1425 | } | 1663 | } |
1426 | 1664 | ||
1427 | void op_trap (void) | 1665 | void op_trap (void) |
@@ -1434,12 +1672,14 @@ void op_trap (void) | @@ -1434,12 +1672,14 @@ void op_trap (void) | ||
1434 | 1672 | ||
1435 | void op_debug (void) | 1673 | void op_debug (void) |
1436 | { | 1674 | { |
1437 | - CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG); | 1675 | + CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG); |
1676 | + RETURN(); | ||
1438 | } | 1677 | } |
1439 | 1678 | ||
1440 | void op_set_lladdr (void) | 1679 | void op_set_lladdr (void) |
1441 | { | 1680 | { |
1442 | env->CP0_LLAddr = T2; | 1681 | env->CP0_LLAddr = T2; |
1682 | + RETURN(); | ||
1443 | } | 1683 | } |
1444 | 1684 | ||
1445 | void debug_eret (void); | 1685 | void debug_eret (void); |
@@ -1456,12 +1696,50 @@ void op_eret (void) | @@ -1456,12 +1696,50 @@ void op_eret (void) | ||
1456 | env->CP0_Status &= ~(1 << CP0St_EXL); | 1696 | env->CP0_Status &= ~(1 << CP0St_EXL); |
1457 | } | 1697 | } |
1458 | env->CP0_LLAddr = 1; | 1698 | env->CP0_LLAddr = 1; |
1699 | + RETURN(); | ||
1459 | } | 1700 | } |
1460 | 1701 | ||
1461 | void op_deret (void) | 1702 | void op_deret (void) |
1462 | { | 1703 | { |
1463 | CALL_FROM_TB0(debug_eret); | 1704 | CALL_FROM_TB0(debug_eret); |
1464 | env->PC = env->CP0_DEPC; | 1705 | env->PC = env->CP0_DEPC; |
1706 | + RETURN(); | ||
1707 | +} | ||
1708 | + | ||
1709 | +void op_rdhwr_cpunum(void) | ||
1710 | +{ | ||
1711 | + if (env->CP0_HWREna & (1 << 0)) | ||
1712 | + T0 = env->CP0_EBase & 0x2ff; | ||
1713 | + else | ||
1714 | + CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI); | ||
1715 | + RETURN(); | ||
1716 | +} | ||
1717 | + | ||
1718 | +void op_rdhwr_synci_step(void) | ||
1719 | +{ | ||
1720 | + if (env->CP0_HWREna & (1 << 1)) | ||
1721 | + T0 = env->SYNCI_Step; | ||
1722 | + else | ||
1723 | + CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI); | ||
1724 | + RETURN(); | ||
1725 | +} | ||
1726 | + | ||
1727 | +void op_rdhwr_cc(void) | ||
1728 | +{ | ||
1729 | + if (env->CP0_HWREna & (1 << 2)) | ||
1730 | + T0 = env->CP0_Count; | ||
1731 | + else | ||
1732 | + CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI); | ||
1733 | + RETURN(); | ||
1734 | +} | ||
1735 | + | ||
1736 | +void op_rdhwr_ccres(void) | ||
1737 | +{ | ||
1738 | + if (env->CP0_HWREna & (1 << 3)) | ||
1739 | + T0 = env->CCRes; | ||
1740 | + else | ||
1741 | + CALL_FROM_TB1(do_raise_exception_direct, EXCP_RI); | ||
1742 | + RETURN(); | ||
1465 | } | 1743 | } |
1466 | 1744 | ||
1467 | void op_save_state (void) | 1745 | void op_save_state (void) |
@@ -1491,10 +1769,62 @@ void op_raise_exception_err (void) | @@ -1491,10 +1769,62 @@ void op_raise_exception_err (void) | ||
1491 | void op_exit_tb (void) | 1769 | void op_exit_tb (void) |
1492 | { | 1770 | { |
1493 | EXIT_TB(); | 1771 | EXIT_TB(); |
1772 | + RETURN(); | ||
1494 | } | 1773 | } |
1495 | 1774 | ||
1496 | void op_wait (void) | 1775 | void op_wait (void) |
1497 | { | 1776 | { |
1498 | env->halted = 1; | 1777 | env->halted = 1; |
1499 | CALL_FROM_TB1(do_raise_exception, EXCP_HLT); | 1778 | CALL_FROM_TB1(do_raise_exception, EXCP_HLT); |
1779 | + RETURN(); | ||
1780 | +} | ||
1781 | + | ||
1782 | +/* Bitfield operations. */ | ||
1783 | +void op_ext(void) | ||
1784 | +{ | ||
1785 | + unsigned int pos = PARAM1; | ||
1786 | + unsigned int size = PARAM2; | ||
1787 | + | ||
1788 | + T0 = (T1 >> pos) & ((1 << size) - 1); | ||
1789 | + RETURN(); | ||
1790 | +} | ||
1791 | + | ||
1792 | +void op_ins(void) | ||
1793 | +{ | ||
1794 | + unsigned int pos = PARAM1; | ||
1795 | + unsigned int size = PARAM2; | ||
1796 | + target_ulong mask = ((1 << size) - 1) << pos; | ||
1797 | + | ||
1798 | + T0 = (T2 & ~mask) | ((T1 << pos) & mask); | ||
1799 | + RETURN(); | ||
1800 | +} | ||
1801 | + | ||
1802 | +void op_wsbh(void) | ||
1803 | +{ | ||
1804 | + T0 = ((T1 << 8) & ~0x00FF00FF) | ((T1 >> 8) & 0x00FF00FF); | ||
1805 | + RETURN(); | ||
1806 | +} | ||
1807 | + | ||
1808 | +void op_dsbh(void) | ||
1809 | +{ | ||
1810 | + T0 = ((T1 << 8) & ~0x00FF00FF00FF00FFULL) | ((T1 >> 8) & 0x00FF00FF00FF00FFULL); | ||
1811 | + RETURN(); | ||
1812 | +} | ||
1813 | + | ||
1814 | +void op_dshd(void) | ||
1815 | +{ | ||
1816 | + T0 = ((T1 << 16) & ~0x0000FFFF0000FFFFULL) | ((T1 >> 16) & 0x0000FFFF0000FFFFULL); | ||
1817 | + RETURN(); | ||
1818 | +} | ||
1819 | + | ||
1820 | +void op_seb(void) | ||
1821 | +{ | ||
1822 | + T0 = ((T1 & 0xFF) ^ 0x80) - 0x80; | ||
1823 | + RETURN(); | ||
1824 | +} | ||
1825 | + | ||
1826 | +void op_seh(void) | ||
1827 | +{ | ||
1828 | + T0 = ((T1 & 0xFFFF) ^ 0x8000) - 0x8000; | ||
1829 | + RETURN(); | ||
1500 | } | 1830 | } |
target-mips/op_helper.c
@@ -153,12 +153,12 @@ void cpu_mips_store_compare(CPUState *env, uint32_t value) | @@ -153,12 +153,12 @@ void cpu_mips_store_compare(CPUState *env, uint32_t value) | ||
153 | 153 | ||
154 | void do_mtc0_status_debug(uint32_t old, uint32_t val) | 154 | void do_mtc0_status_debug(uint32_t old, uint32_t val) |
155 | { | 155 | { |
156 | - cpu_abort(env, "mtc0 status\n"); | 156 | + cpu_abort(env, "mtc0 status debug\n"); |
157 | } | 157 | } |
158 | 158 | ||
159 | -void do_mtc0_status_irqraise_debug(void) | 159 | +void do_mtc0_status_irqraise_debug (void) |
160 | { | 160 | { |
161 | - cpu_abort(env, "mtc0 status\n"); | 161 | + cpu_abort(env, "mtc0 status irqraise debug\n"); |
162 | } | 162 | } |
163 | 163 | ||
164 | void do_tlbwi (void) | 164 | void do_tlbwi (void) |
target-mips/translate.c
@@ -50,184 +50,313 @@ static uint32_t *gen_opparam_ptr; | @@ -50,184 +50,313 @@ static uint32_t *gen_opparam_ptr; | ||
50 | 50 | ||
51 | #include "gen-op.h" | 51 | #include "gen-op.h" |
52 | 52 | ||
53 | -/* MIPS opcodes */ | ||
54 | -#define EXT_SPECIAL 0x100 | ||
55 | -#define EXT_SPECIAL2 0x200 | ||
56 | -#define EXT_REGIMM 0x300 | ||
57 | -#define EXT_CP0 0x400 | ||
58 | -#define EXT_CP1 0x500 | ||
59 | -#define EXT_CP2 0x600 | ||
60 | -#define EXT_CP3 0x700 | 53 | +/* MIPS major opcodes */ |
54 | +#define MASK_OP_MAJOR(op) (op & (0x3F << 26)) | ||
61 | 55 | ||
62 | enum { | 56 | enum { |
63 | /* indirect opcode tables */ | 57 | /* indirect opcode tables */ |
64 | - OPC_SPECIAL = 0x00, | ||
65 | - OPC_BREGIMM = 0x01, | ||
66 | - OPC_CP0 = 0x10, | ||
67 | - OPC_CP1 = 0x11, | ||
68 | - OPC_CP2 = 0x12, | ||
69 | - OPC_CP3 = 0x13, | ||
70 | - OPC_SPECIAL2 = 0x1C, | 58 | + OPC_SPECIAL = (0x00 << 26), |
59 | + OPC_REGIMM = (0x01 << 26), | ||
60 | + OPC_CP0 = (0x10 << 26), | ||
61 | + OPC_CP1 = (0x11 << 26), | ||
62 | + OPC_CP2 = (0x12 << 26), | ||
63 | + OPC_CP3 = (0x13 << 26), | ||
64 | + OPC_SPECIAL2 = (0x1C << 26), | ||
65 | + OPC_SPECIAL3 = (0x1F << 26), | ||
71 | /* arithmetic with immediate */ | 66 | /* arithmetic with immediate */ |
72 | - OPC_ADDI = 0x08, | ||
73 | - OPC_ADDIU = 0x09, | ||
74 | - OPC_SLTI = 0x0A, | ||
75 | - OPC_SLTIU = 0x0B, | ||
76 | - OPC_ANDI = 0x0C, | ||
77 | - OPC_ORI = 0x0D, | ||
78 | - OPC_XORI = 0x0E, | ||
79 | - OPC_LUI = 0x0F, | 67 | + OPC_ADDI = (0x08 << 26), |
68 | + OPC_ADDIU = (0x09 << 26), | ||
69 | + OPC_SLTI = (0x0A << 26), | ||
70 | + OPC_SLTIU = (0x0B << 26), | ||
71 | + OPC_ANDI = (0x0C << 26), | ||
72 | + OPC_ORI = (0x0D << 26), | ||
73 | + OPC_XORI = (0x0E << 26), | ||
74 | + OPC_LUI = (0x0F << 26), | ||
75 | + OPC_DADDI = (0x18 << 26), | ||
76 | + OPC_DADDIU = (0x19 << 26), | ||
80 | /* Jump and branches */ | 77 | /* Jump and branches */ |
81 | - OPC_J = 0x02, | ||
82 | - OPC_JAL = 0x03, | ||
83 | - OPC_BEQ = 0x04, /* Unconditional if rs = rt = 0 (B) */ | ||
84 | - OPC_BEQL = 0x14, | ||
85 | - OPC_BNE = 0x05, | ||
86 | - OPC_BNEL = 0x15, | ||
87 | - OPC_BLEZ = 0x06, | ||
88 | - OPC_BLEZL = 0x16, | ||
89 | - OPC_BGTZ = 0x07, | ||
90 | - OPC_BGTZL = 0x17, | ||
91 | - OPC_JALX = 0x1D, /* MIPS 16 only */ | 78 | + OPC_J = (0x02 << 26), |
79 | + OPC_JAL = (0x03 << 26), | ||
80 | + OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */ | ||
81 | + OPC_BEQL = (0x14 << 26), | ||
82 | + OPC_BNE = (0x05 << 26), | ||
83 | + OPC_BNEL = (0x15 << 26), | ||
84 | + OPC_BLEZ = (0x06 << 26), | ||
85 | + OPC_BLEZL = (0x16 << 26), | ||
86 | + OPC_BGTZ = (0x07 << 26), | ||
87 | + OPC_BGTZL = (0x17 << 26), | ||
88 | + OPC_JALX = (0x1D << 26), /* MIPS 16 only */ | ||
92 | /* Load and stores */ | 89 | /* Load and stores */ |
93 | - OPC_LB = 0x20, | ||
94 | - OPC_LH = 0x21, | ||
95 | - OPC_LWL = 0x22, | ||
96 | - OPC_LW = 0x23, | ||
97 | - OPC_LBU = 0x24, | ||
98 | - OPC_LHU = 0x25, | ||
99 | - OPC_LWR = 0x26, | ||
100 | - OPC_LWU = 0x27, | ||
101 | - OPC_SB = 0x28, | ||
102 | - OPC_SH = 0x29, | ||
103 | - OPC_SWL = 0x2A, | ||
104 | - OPC_SW = 0x2B, | ||
105 | - OPC_SWR = 0x2E, | ||
106 | - OPC_LL = 0x30, | ||
107 | - OPC_SC = 0x38, | 90 | + OPC_LDL = (0x1A << 26), |
91 | + OPC_LDR = (0x1B << 26), | ||
92 | + OPC_LB = (0x20 << 26), | ||
93 | + OPC_LH = (0x21 << 26), | ||
94 | + OPC_LWL = (0x22 << 26), | ||
95 | + OPC_LW = (0x23 << 26), | ||
96 | + OPC_LBU = (0x24 << 26), | ||
97 | + OPC_LHU = (0x25 << 26), | ||
98 | + OPC_LWR = (0x26 << 26), | ||
99 | + OPC_LWU = (0x27 << 26), | ||
100 | + OPC_SB = (0x28 << 26), | ||
101 | + OPC_SH = (0x29 << 26), | ||
102 | + OPC_SWL = (0x2A << 26), | ||
103 | + OPC_SW = (0x2B << 26), | ||
104 | + OPC_SDL = (0x2C << 26), | ||
105 | + OPC_SDR = (0x2D << 26), | ||
106 | + OPC_SWR = (0x2E << 26), | ||
107 | + OPC_LL = (0x30 << 26), | ||
108 | + OPC_LLD = (0x34 << 26), | ||
109 | + OPC_LD = (0x37 << 26), | ||
110 | + OPC_SC = (0x38 << 26), | ||
111 | + OPC_SCD = (0x3C << 26), | ||
112 | + OPC_SD = (0x3F << 26), | ||
108 | /* Floating point load/store */ | 113 | /* Floating point load/store */ |
109 | - OPC_LWC1 = 0x31, | ||
110 | - OPC_LWC2 = 0x32, | ||
111 | - OPC_LDC1 = 0x35, | ||
112 | - OPC_LDC2 = 0x36, | ||
113 | - OPC_SWC1 = 0x39, | ||
114 | - OPC_SWC2 = 0x3A, | ||
115 | - OPC_SDC1 = 0x3D, | ||
116 | - OPC_SDC2 = 0x3E, | 114 | + OPC_LWC1 = (0x31 << 26), |
115 | + OPC_LWC2 = (0x32 << 26), | ||
116 | + OPC_LDC1 = (0x35 << 26), | ||
117 | + OPC_LDC2 = (0x36 << 26), | ||
118 | + OPC_SWC1 = (0x39 << 26), | ||
119 | + OPC_SWC2 = (0x3A << 26), | ||
120 | + OPC_SDC1 = (0x3D << 26), | ||
121 | + OPC_SDC2 = (0x3E << 26), | ||
122 | + /* MDMX ASE specific */ | ||
123 | + OPC_MDMX = (0x1E << 26), | ||
117 | /* Cache and prefetch */ | 124 | /* Cache and prefetch */ |
118 | - OPC_CACHE = 0x2F, | ||
119 | - OPC_PREF = 0x33, | 125 | + OPC_CACHE = (0x2F << 26), |
126 | + OPC_PREF = (0x33 << 26), | ||
127 | + /* Reserved major opcode */ | ||
128 | + OPC_MAJOR3B_RESERVED = (0x3B << 26), | ||
120 | }; | 129 | }; |
121 | 130 | ||
122 | /* MIPS special opcodes */ | 131 | /* MIPS special opcodes */ |
132 | +#define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F) | ||
133 | + | ||
123 | enum { | 134 | enum { |
124 | /* Shifts */ | 135 | /* Shifts */ |
125 | - OPC_SLL = 0x00 | EXT_SPECIAL, | 136 | + OPC_SLL = 0x00 | OPC_SPECIAL, |
126 | /* NOP is SLL r0, r0, 0 */ | 137 | /* NOP is SLL r0, r0, 0 */ |
127 | /* SSNOP is SLL r0, r0, 1 */ | 138 | /* SSNOP is SLL r0, r0, 1 */ |
128 | - OPC_SRL = 0x02 | EXT_SPECIAL, | ||
129 | - OPC_SRA = 0x03 | EXT_SPECIAL, | ||
130 | - OPC_SLLV = 0x04 | EXT_SPECIAL, | ||
131 | - OPC_SRLV = 0x06 | EXT_SPECIAL, | ||
132 | - OPC_SRAV = 0x07 | EXT_SPECIAL, | 139 | + /* EHB is SLL r0, r0, 3 */ |
140 | + OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */ | ||
141 | + OPC_SRA = 0x03 | OPC_SPECIAL, | ||
142 | + OPC_SLLV = 0x04 | OPC_SPECIAL, | ||
143 | + OPC_SRLV = 0x06 | OPC_SPECIAL, | ||
144 | + OPC_SRAV = 0x07 | OPC_SPECIAL, | ||
145 | + OPC_DSLLV = 0x14 | OPC_SPECIAL, | ||
146 | + OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */ | ||
147 | + OPC_DSRAV = 0x17 | OPC_SPECIAL, | ||
148 | + OPC_DSLL = 0x38 | OPC_SPECIAL, | ||
149 | + OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */ | ||
150 | + OPC_DSRA = 0x3B | OPC_SPECIAL, | ||
151 | + OPC_DSLL32 = 0x3C | OPC_SPECIAL, | ||
152 | + OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */ | ||
153 | + OPC_DSRA32 = 0x3F | OPC_SPECIAL, | ||
133 | /* Multiplication / division */ | 154 | /* Multiplication / division */ |
134 | - OPC_MULT = 0x18 | EXT_SPECIAL, | ||
135 | - OPC_MULTU = 0x19 | EXT_SPECIAL, | ||
136 | - OPC_DIV = 0x1A | EXT_SPECIAL, | ||
137 | - OPC_DIVU = 0x1B | EXT_SPECIAL, | 155 | + OPC_MULT = 0x18 | OPC_SPECIAL, |
156 | + OPC_MULTU = 0x19 | OPC_SPECIAL, | ||
157 | + OPC_DIV = 0x1A | OPC_SPECIAL, | ||
158 | + OPC_DIVU = 0x1B | OPC_SPECIAL, | ||
159 | + OPC_DMULT = 0x1C | OPC_SPECIAL, | ||
160 | + OPC_DMULTU = 0x1D | OPC_SPECIAL, | ||
161 | + OPC_DDIV = 0x1E | OPC_SPECIAL, | ||
162 | + OPC_DDIVU = 0x1F | OPC_SPECIAL, | ||
138 | /* 2 registers arithmetic / logic */ | 163 | /* 2 registers arithmetic / logic */ |
139 | - OPC_ADD = 0x20 | EXT_SPECIAL, | ||
140 | - OPC_ADDU = 0x21 | EXT_SPECIAL, | ||
141 | - OPC_SUB = 0x22 | EXT_SPECIAL, | ||
142 | - OPC_SUBU = 0x23 | EXT_SPECIAL, | ||
143 | - OPC_AND = 0x24 | EXT_SPECIAL, | ||
144 | - OPC_OR = 0x25 | EXT_SPECIAL, | ||
145 | - OPC_XOR = 0x26 | EXT_SPECIAL, | ||
146 | - OPC_NOR = 0x27 | EXT_SPECIAL, | ||
147 | - OPC_SLT = 0x2A | EXT_SPECIAL, | ||
148 | - OPC_SLTU = 0x2B | EXT_SPECIAL, | 164 | + OPC_ADD = 0x20 | OPC_SPECIAL, |
165 | + OPC_ADDU = 0x21 | OPC_SPECIAL, | ||
166 | + OPC_SUB = 0x22 | OPC_SPECIAL, | ||
167 | + OPC_SUBU = 0x23 | OPC_SPECIAL, | ||
168 | + OPC_AND = 0x24 | OPC_SPECIAL, | ||
169 | + OPC_OR = 0x25 | OPC_SPECIAL, | ||
170 | + OPC_XOR = 0x26 | OPC_SPECIAL, | ||
171 | + OPC_NOR = 0x27 | OPC_SPECIAL, | ||
172 | + OPC_SLT = 0x2A | OPC_SPECIAL, | ||
173 | + OPC_SLTU = 0x2B | OPC_SPECIAL, | ||
174 | + OPC_DADD = 0x2C | OPC_SPECIAL, | ||
175 | + OPC_DADDU = 0x2D | OPC_SPECIAL, | ||
176 | + OPC_DSUB = 0x2E | OPC_SPECIAL, | ||
177 | + OPC_DSUBU = 0x2F | OPC_SPECIAL, | ||
149 | /* Jumps */ | 178 | /* Jumps */ |
150 | - OPC_JR = 0x08 | EXT_SPECIAL, | ||
151 | - OPC_JALR = 0x09 | EXT_SPECIAL, | 179 | + OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */ |
180 | + OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */ | ||
152 | /* Traps */ | 181 | /* Traps */ |
153 | - OPC_TGE = 0x30 | EXT_SPECIAL, | ||
154 | - OPC_TGEU = 0x31 | EXT_SPECIAL, | ||
155 | - OPC_TLT = 0x32 | EXT_SPECIAL, | ||
156 | - OPC_TLTU = 0x33 | EXT_SPECIAL, | ||
157 | - OPC_TEQ = 0x34 | EXT_SPECIAL, | ||
158 | - OPC_TNE = 0x36 | EXT_SPECIAL, | 182 | + OPC_TGE = 0x30 | OPC_SPECIAL, |
183 | + OPC_TGEU = 0x31 | OPC_SPECIAL, | ||
184 | + OPC_TLT = 0x32 | OPC_SPECIAL, | ||
185 | + OPC_TLTU = 0x33 | OPC_SPECIAL, | ||
186 | + OPC_TEQ = 0x34 | OPC_SPECIAL, | ||
187 | + OPC_TNE = 0x36 | OPC_SPECIAL, | ||
159 | /* HI / LO registers load & stores */ | 188 | /* HI / LO registers load & stores */ |
160 | - OPC_MFHI = 0x10 | EXT_SPECIAL, | ||
161 | - OPC_MTHI = 0x11 | EXT_SPECIAL, | ||
162 | - OPC_MFLO = 0x12 | EXT_SPECIAL, | ||
163 | - OPC_MTLO = 0x13 | EXT_SPECIAL, | 189 | + OPC_MFHI = 0x10 | OPC_SPECIAL, |
190 | + OPC_MTHI = 0x11 | OPC_SPECIAL, | ||
191 | + OPC_MFLO = 0x12 | OPC_SPECIAL, | ||
192 | + OPC_MTLO = 0x13 | OPC_SPECIAL, | ||
164 | /* Conditional moves */ | 193 | /* Conditional moves */ |
165 | - OPC_MOVZ = 0x0A | EXT_SPECIAL, | ||
166 | - OPC_MOVN = 0x0B | EXT_SPECIAL, | 194 | + OPC_MOVZ = 0x0A | OPC_SPECIAL, |
195 | + OPC_MOVN = 0x0B | OPC_SPECIAL, | ||
167 | 196 | ||
168 | - OPC_MOVCI = 0x01 | EXT_SPECIAL, | 197 | + OPC_MOVCI = 0x01 | OPC_SPECIAL, |
169 | 198 | ||
170 | /* Special */ | 199 | /* Special */ |
171 | - OPC_PMON = 0x05 | EXT_SPECIAL, | ||
172 | - OPC_SYSCALL = 0x0C | EXT_SPECIAL, | ||
173 | - OPC_BREAK = 0x0D | EXT_SPECIAL, | ||
174 | - OPC_SYNC = 0x0F | EXT_SPECIAL, | 200 | + OPC_PMON = 0x05 | OPC_SPECIAL, /* inofficial */ |
201 | + OPC_SYSCALL = 0x0C | OPC_SPECIAL, | ||
202 | + OPC_BREAK = 0x0D | OPC_SPECIAL, | ||
203 | + OPC_SPIM = 0x0E | OPC_SPECIAL, /* inofficial */ | ||
204 | + OPC_SYNC = 0x0F | OPC_SPECIAL, | ||
205 | + | ||
206 | + OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL, | ||
207 | + OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL, | ||
208 | + OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL, | ||
209 | + OPC_SPECIAL35_RESERVED = 0x35 | OPC_SPECIAL, | ||
210 | + OPC_SPECIAL37_RESERVED = 0x37 | OPC_SPECIAL, | ||
211 | + OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL, | ||
212 | + OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL, | ||
213 | +}; | ||
214 | + | ||
215 | +/* REGIMM (rt field) opcodes */ | ||
216 | +#define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16)) | ||
217 | + | ||
218 | +enum { | ||
219 | + OPC_BLTZ = (0x00 << 16) | OPC_REGIMM, | ||
220 | + OPC_BLTZL = (0x02 << 16) | OPC_REGIMM, | ||
221 | + OPC_BGEZ = (0x01 << 16) | OPC_REGIMM, | ||
222 | + OPC_BGEZL = (0x03 << 16) | OPC_REGIMM, | ||
223 | + OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM, | ||
224 | + OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM, | ||
225 | + OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM, | ||
226 | + OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM, | ||
227 | + OPC_TGEI = (0x08 << 16) | OPC_REGIMM, | ||
228 | + OPC_TGEIU = (0x09 << 16) | OPC_REGIMM, | ||
229 | + OPC_TLTI = (0x0A << 16) | OPC_REGIMM, | ||
230 | + OPC_TLTIU = (0x0B << 16) | OPC_REGIMM, | ||
231 | + OPC_TEQI = (0x0C << 16) | OPC_REGIMM, | ||
232 | + OPC_TNEI = (0x0E << 16) | OPC_REGIMM, | ||
233 | + OPC_SYNCI = (0x1F << 16) | OPC_REGIMM, | ||
175 | }; | 234 | }; |
176 | 235 | ||
236 | +/* Special2 opcodes */ | ||
237 | +#define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F) | ||
238 | + | ||
177 | enum { | 239 | enum { |
178 | - /* Mutiply & xxx operations */ | ||
179 | - OPC_MADD = 0x00 | EXT_SPECIAL2, | ||
180 | - OPC_MADDU = 0x01 | EXT_SPECIAL2, | ||
181 | - OPC_MUL = 0x02 | EXT_SPECIAL2, | ||
182 | - OPC_MSUB = 0x04 | EXT_SPECIAL2, | ||
183 | - OPC_MSUBU = 0x05 | EXT_SPECIAL2, | 240 | + /* Multiply & xxx operations */ |
241 | + OPC_MADD = 0x00 | OPC_SPECIAL2, | ||
242 | + OPC_MADDU = 0x01 | OPC_SPECIAL2, | ||
243 | + OPC_MUL = 0x02 | OPC_SPECIAL2, | ||
244 | + OPC_MSUB = 0x04 | OPC_SPECIAL2, | ||
245 | + OPC_MSUBU = 0x05 | OPC_SPECIAL2, | ||
184 | /* Misc */ | 246 | /* Misc */ |
185 | - OPC_CLZ = 0x20 | EXT_SPECIAL2, | ||
186 | - OPC_CLO = 0x21 | EXT_SPECIAL2, | 247 | + OPC_CLZ = 0x20 | OPC_SPECIAL2, |
248 | + OPC_CLO = 0x21 | OPC_SPECIAL2, | ||
249 | + OPC_DCLZ = 0x24 | OPC_SPECIAL2, | ||
250 | + OPC_DCLO = 0x25 | OPC_SPECIAL2, | ||
187 | /* Special */ | 251 | /* Special */ |
188 | - OPC_SDBBP = 0x3F | EXT_SPECIAL2, | 252 | + OPC_SDBBP = 0x3F | OPC_SPECIAL2, |
253 | +}; | ||
254 | + | ||
255 | +/* Special3 opcodes */ | ||
256 | +#define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F) | ||
257 | + | ||
258 | +enum { | ||
259 | + OPC_EXT = 0x00 | OPC_SPECIAL3, | ||
260 | + OPC_DEXTM = 0x01 | OPC_SPECIAL3, | ||
261 | + OPC_DEXTU = 0x02 | OPC_SPECIAL3, | ||
262 | + OPC_DEXT = 0x03 | OPC_SPECIAL3, | ||
263 | + OPC_INS = 0x04 | OPC_SPECIAL3, | ||
264 | + OPC_DINSM = 0x05 | OPC_SPECIAL3, | ||
265 | + OPC_DINSU = 0x06 | OPC_SPECIAL3, | ||
266 | + OPC_DINS = 0x07 | OPC_SPECIAL3, | ||
267 | + OPC_BSHFL = 0x20 | OPC_SPECIAL3, | ||
268 | + OPC_DBSHFL = 0x24 | OPC_SPECIAL3, | ||
269 | + OPC_RDHWR = 0x3B | OPC_SPECIAL3, | ||
189 | }; | 270 | }; |
190 | 271 | ||
191 | -/* Branch REGIMM */ | 272 | +/* BSHFL opcodes */ |
273 | +#define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6)) | ||
274 | + | ||
192 | enum { | 275 | enum { |
193 | - OPC_BLTZ = 0x00 | EXT_REGIMM, | ||
194 | - OPC_BLTZL = 0x02 | EXT_REGIMM, | ||
195 | - OPC_BGEZ = 0x01 | EXT_REGIMM, | ||
196 | - OPC_BGEZL = 0x03 | EXT_REGIMM, | ||
197 | - OPC_BLTZAL = 0x10 | EXT_REGIMM, | ||
198 | - OPC_BLTZALL = 0x12 | EXT_REGIMM, | ||
199 | - OPC_BGEZAL = 0x11 | EXT_REGIMM, | ||
200 | - OPC_BGEZALL = 0x13 | EXT_REGIMM, | ||
201 | - OPC_TGEI = 0x08 | EXT_REGIMM, | ||
202 | - OPC_TGEIU = 0x09 | EXT_REGIMM, | ||
203 | - OPC_TLTI = 0x0A | EXT_REGIMM, | ||
204 | - OPC_TLTIU = 0x0B | EXT_REGIMM, | ||
205 | - OPC_TEQI = 0x0C | EXT_REGIMM, | ||
206 | - OPC_TNEI = 0x0E | EXT_REGIMM, | 276 | + OPC_WSBH = (0x02 << 6) | OPC_BSHFL, |
277 | + OPC_SEB = (0x10 << 6) | OPC_BSHFL, | ||
278 | + OPC_SEH = (0x18 << 6) | OPC_BSHFL, | ||
207 | }; | 279 | }; |
208 | 280 | ||
281 | +/* DBSHFL opcodes */ | ||
282 | +#define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6)) | ||
283 | + | ||
209 | enum { | 284 | enum { |
210 | - /* Coprocessor 0 (MMU) */ | ||
211 | - OPC_MFC0 = 0x00 | EXT_CP0, | ||
212 | - OPC_MTC0 = 0x04 | EXT_CP0, | ||
213 | - OPC_TLBR = 0x01 | EXT_CP0, | ||
214 | - OPC_TLBWI = 0x02 | EXT_CP0, | ||
215 | - OPC_TLBWR = 0x06 | EXT_CP0, | ||
216 | - OPC_TLBP = 0x08 | EXT_CP0, | ||
217 | - OPC_ERET = 0x18 | EXT_CP0, | ||
218 | - OPC_DERET = 0x1F | EXT_CP0, | ||
219 | - OPC_WAIT = 0x20 | EXT_CP0, | 285 | + OPC_DSBH = (0x02 << 6) | OPC_DBSHFL, |
286 | + OPC_DSHD = (0x05 << 6) | OPC_DBSHFL, | ||
220 | }; | 287 | }; |
221 | 288 | ||
222 | -#ifdef MIPS_USES_FPU | 289 | +/* Coprocessor 0 (rs field) */ |
290 | +#define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | ||
291 | + | ||
223 | enum { | 292 | enum { |
224 | - /* Coprocessor 1 (FPU) */ | ||
225 | - OPC_MFC1 = 0x00 | EXT_CP1, | ||
226 | - OPC_MTC1 = 0x04 | EXT_CP1, | ||
227 | - OPC_CFC1 = 0x02 | EXT_CP1, | ||
228 | - OPC_CTC1 = 0x06 | EXT_CP1, | 293 | + OPC_MFC0 = (0x00 << 21) | OPC_CP0, |
294 | + OPC_DMFC0 = (0x01 << 21) | OPC_CP0, | ||
295 | + OPC_MTC0 = (0x04 << 21) | OPC_CP0, | ||
296 | + OPC_DMTC0 = (0x05 << 21) | OPC_CP0, | ||
297 | + OPC_RDPGPR = (0x0A << 21) | OPC_CP0, | ||
298 | + OPC_MFMC0 = (0x0B << 21) | OPC_CP0, | ||
299 | + OPC_WRPGPR = (0x0E << 21) | OPC_CP0, | ||
300 | + OPC_C0 = (0x10 << 21) | OPC_CP0, | ||
301 | + OPC_C0_FIRST = (0x10 << 21) | OPC_CP0, | ||
302 | + OPC_C0_LAST = (0x1F << 21) | OPC_CP0, | ||
229 | }; | 303 | }; |
230 | -#endif | 304 | + |
305 | +/* MFMC0 opcodes */ | ||
306 | +#define MASK_MFMC0(op) MASK_CP0(op) | (op & ((0x0C << 11) | (1 << 5))) | ||
307 | + | ||
308 | +enum { | ||
309 | + OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0, | ||
310 | + OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0, | ||
311 | +}; | ||
312 | + | ||
313 | +/* Coprocessor 0 (with rs == C0) */ | ||
314 | +#define MASK_C0(op) MASK_CP0(op) | (op & 0x3F) | ||
315 | + | ||
316 | +enum { | ||
317 | + OPC_TLBR = 0x01 | OPC_C0, | ||
318 | + OPC_TLBWI = 0x02 | OPC_C0, | ||
319 | + OPC_TLBWR = 0x06 | OPC_C0, | ||
320 | + OPC_TLBP = 0x08 | OPC_C0, | ||
321 | + OPC_RFE = 0x10 | OPC_C0, | ||
322 | + OPC_ERET = 0x18 | OPC_C0, | ||
323 | + OPC_DERET = 0x1F | OPC_C0, | ||
324 | + OPC_WAIT = 0x20 | OPC_C0, | ||
325 | +}; | ||
326 | + | ||
327 | +/* Coprocessor 1 (rs field) */ | ||
328 | +#define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | ||
329 | + | ||
330 | +enum { | ||
331 | + OPC_MFC1 = (0x00 << 21) | OPC_CP1, | ||
332 | + OPC_DMFC1 = (0x01 << 21) | OPC_CP1, | ||
333 | + OPC_CFC1 = (0x02 << 21) | OPC_CP1, | ||
334 | + OPC_MFHCI = (0x03 << 21) | OPC_CP1, | ||
335 | + OPC_MTC1 = (0x04 << 21) | OPC_CP1, | ||
336 | + OPC_DMTC1 = (0x05 << 21) | OPC_CP1, | ||
337 | + OPC_CTC1 = (0x06 << 21) | OPC_CP1, | ||
338 | + OPC_MTHCI = (0x07 << 21) | OPC_CP1, | ||
339 | + OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */ | ||
340 | + OPC_S_FMT = (0x10 << 21) | OPC_CP1, /* 16: fmt=single fp */ | ||
341 | + OPC_D_FMT = (0x11 << 21) | OPC_CP1, /* 17: fmt=double fp */ | ||
342 | + OPC_E_FMT = (0x12 << 21) | OPC_CP1, /* 18: fmt=extended fp */ | ||
343 | + OPC_Q_FMT = (0x13 << 21) | OPC_CP1, /* 19: fmt=quad fp */ | ||
344 | + OPC_W_FMT = (0x14 << 21) | OPC_CP1, /* 20: fmt=32bit fixed */ | ||
345 | + OPC_L_FMT = (0x15 << 21) | OPC_CP1, /* 21: fmt=64bit fixed */ | ||
346 | +}; | ||
347 | + | ||
348 | +enum { | ||
349 | + OPC_BC1F = (0x00 << 16) | OPC_BC1, | ||
350 | + OPC_BC1T = (0x01 << 16) | OPC_BC1, | ||
351 | + OPC_BC1FL = (0x02 << 16) | OPC_BC1, | ||
352 | + OPC_BC1TL = (0x03 << 16) | OPC_BC1, | ||
353 | +}; | ||
354 | + | ||
355 | +#define MASK_CP1_BCOND(op) MASK_CP1(op) | (op & ((0x1F << 21) | (0x3 << 16))) | ||
356 | +#define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & ((0x1F << 21) | 0x3F)) | ||
357 | + | ||
358 | +#define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | ||
359 | +#define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | ||
231 | 360 | ||
232 | const unsigned char *regnames[] = | 361 | const unsigned char *regnames[] = |
233 | { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3", | 362 | { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3", |
@@ -260,8 +389,7 @@ GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr); | @@ -260,8 +389,7 @@ GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr); | ||
260 | GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr); | 389 | GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr); |
261 | GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr); | 390 | GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr); |
262 | 391 | ||
263 | -#ifdef MIPS_USES_FPU | ||
264 | -const unsigned char *fregnames[] = | 392 | +static const char *fregnames[] = |
265 | { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", | 393 | { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", |
266 | "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", | 394 | "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", |
267 | "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", | 395 | "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", |
@@ -344,8 +472,6 @@ static inline void gen_cmp_ ## fmt(int n) \ | @@ -344,8 +472,6 @@ static inline void gen_cmp_ ## fmt(int n) \ | ||
344 | FOP_CONDS(d) | 472 | FOP_CONDS(d) |
345 | FOP_CONDS(s) | 473 | FOP_CONDS(s) |
346 | 474 | ||
347 | -#endif | ||
348 | - | ||
349 | typedef struct DisasContext { | 475 | typedef struct DisasContext { |
350 | struct TranslationBlock *tb; | 476 | struct TranslationBlock *tb; |
351 | target_ulong pc, saved_pc; | 477 | target_ulong pc, saved_pc; |
@@ -410,9 +536,7 @@ do { \ | @@ -410,9 +536,7 @@ do { \ | ||
410 | } \ | 536 | } \ |
411 | } while (0) | 537 | } while (0) |
412 | 538 | ||
413 | -#ifdef MIPS_USES_FPU | ||
414 | - | ||
415 | -# define GEN_LOAD_FREG_FTN(FTn, Fn) \ | 539 | +#define GEN_LOAD_FREG_FTN(FTn, Fn) \ |
416 | do { \ | 540 | do { \ |
417 | glue(gen_op_load_fpr_, FTn)(Fn); \ | 541 | glue(gen_op_load_fpr_, FTn)(Fn); \ |
418 | } while (0) | 542 | } while (0) |
@@ -422,8 +546,6 @@ do { \ | @@ -422,8 +546,6 @@ do { \ | ||
422 | glue(gen_op_store_fpr_, FTn)(Fn); \ | 546 | glue(gen_op_store_fpr_, FTn)(Fn); \ |
423 | } while (0) | 547 | } while (0) |
424 | 548 | ||
425 | -#endif | ||
426 | - | ||
427 | static inline void save_cpu_state (DisasContext *ctx, int do_save_pc) | 549 | static inline void save_cpu_state (DisasContext *ctx, int do_save_pc) |
428 | { | 550 | { |
429 | #if defined MIPS_DEBUG_DISAS | 551 | #if defined MIPS_DEBUG_DISAS |
@@ -487,7 +609,7 @@ static GenOpFunc *gen_op_s##width[] = { \ | @@ -487,7 +609,7 @@ static GenOpFunc *gen_op_s##width[] = { \ | ||
487 | } | 609 | } |
488 | #endif | 610 | #endif |
489 | 611 | ||
490 | -#ifdef TARGET_MIPS64 | 612 | +#ifdef MIPS_HAS_MIPS64 |
491 | OP_LD_TABLE(d); | 613 | OP_LD_TABLE(d); |
492 | OP_LD_TABLE(dl); | 614 | OP_LD_TABLE(dl); |
493 | OP_LD_TABLE(dr); | 615 | OP_LD_TABLE(dr); |
@@ -510,18 +632,16 @@ OP_LD_TABLE(bu); | @@ -510,18 +632,16 @@ OP_LD_TABLE(bu); | ||
510 | OP_ST_TABLE(b); | 632 | OP_ST_TABLE(b); |
511 | OP_LD_TABLE(l); | 633 | OP_LD_TABLE(l); |
512 | OP_ST_TABLE(c); | 634 | OP_ST_TABLE(c); |
513 | -#ifdef MIPS_USES_FPU | ||
514 | OP_LD_TABLE(wc1); | 635 | OP_LD_TABLE(wc1); |
515 | OP_ST_TABLE(wc1); | 636 | OP_ST_TABLE(wc1); |
516 | OP_LD_TABLE(dc1); | 637 | OP_LD_TABLE(dc1); |
517 | OP_ST_TABLE(dc1); | 638 | OP_ST_TABLE(dc1); |
518 | -#endif | ||
519 | 639 | ||
520 | /* Load and store */ | 640 | /* Load and store */ |
521 | -static void gen_ldst (DisasContext *ctx, uint16_t opc, int rt, | 641 | +static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt, |
522 | int base, int16_t offset) | 642 | int base, int16_t offset) |
523 | { | 643 | { |
524 | - const unsigned char *opn = "unk"; | 644 | + const char *opn = "unk"; |
525 | 645 | ||
526 | if (base == 0) { | 646 | if (base == 0) { |
527 | GEN_LOAD_IMM_TN(T0, offset); | 647 | GEN_LOAD_IMM_TN(T0, offset); |
@@ -536,23 +656,27 @@ static void gen_ldst (DisasContext *ctx, uint16_t opc, int rt, | @@ -536,23 +656,27 @@ static void gen_ldst (DisasContext *ctx, uint16_t opc, int rt, | ||
536 | * memory access | 656 | * memory access |
537 | */ | 657 | */ |
538 | switch (opc) { | 658 | switch (opc) { |
539 | -#if defined(TARGET_MIPS64) | 659 | +#ifdef MIPS_HAS_MIPS64 |
540 | case OPC_LD: | 660 | case OPC_LD: |
541 | -#if defined (MIPS_HAS_UNALIGNED_LS) | ||
542 | - case OPC_ULD: | ||
543 | -#endif | ||
544 | op_ldst(ld); | 661 | op_ldst(ld); |
545 | GEN_STORE_TN_REG(rt, T0); | 662 | GEN_STORE_TN_REG(rt, T0); |
546 | opn = "ld"; | 663 | opn = "ld"; |
547 | break; | 664 | break; |
665 | + case OPC_LLD: | ||
666 | + op_ldst(lld); | ||
667 | + GEN_STORE_TN_REG(rt, T0); | ||
668 | + opn = "lld"; | ||
669 | + break; | ||
548 | case OPC_SD: | 670 | case OPC_SD: |
549 | -#if defined (MIPS_HAS_UNALIGNED_LS) | ||
550 | - case OPC_USD: | ||
551 | -#endif | ||
552 | GEN_LOAD_REG_TN(T1, rt); | 671 | GEN_LOAD_REG_TN(T1, rt); |
553 | op_ldst(sd); | 672 | op_ldst(sd); |
554 | opn = "sd"; | 673 | opn = "sd"; |
555 | break; | 674 | break; |
675 | + case OPC_SCD: | ||
676 | + GEN_LOAD_REG_TN(T1, rt); | ||
677 | + op_ldst(scd); | ||
678 | + opn = "scd"; | ||
679 | + break; | ||
556 | case OPC_LDL: | 680 | case OPC_LDL: |
557 | op_ldst(ldl); | 681 | op_ldst(ldl); |
558 | GEN_STORE_TN_REG(rt, T0); | 682 | GEN_STORE_TN_REG(rt, T0); |
@@ -575,9 +699,6 @@ static void gen_ldst (DisasContext *ctx, uint16_t opc, int rt, | @@ -575,9 +699,6 @@ static void gen_ldst (DisasContext *ctx, uint16_t opc, int rt, | ||
575 | break; | 699 | break; |
576 | #endif | 700 | #endif |
577 | case OPC_LW: | 701 | case OPC_LW: |
578 | -#if defined (MIPS_HAS_UNALIGNED_LS) | ||
579 | - case OPC_ULW: | ||
580 | -#endif | ||
581 | op_ldst(lw); | 702 | op_ldst(lw); |
582 | GEN_STORE_TN_REG(rt, T0); | 703 | GEN_STORE_TN_REG(rt, T0); |
583 | opn = "lw"; | 704 | opn = "lw"; |
@@ -588,33 +709,21 @@ static void gen_ldst (DisasContext *ctx, uint16_t opc, int rt, | @@ -588,33 +709,21 @@ static void gen_ldst (DisasContext *ctx, uint16_t opc, int rt, | ||
588 | opn = "lwu"; | 709 | opn = "lwu"; |
589 | break; | 710 | break; |
590 | case OPC_SW: | 711 | case OPC_SW: |
591 | -#if defined (MIPS_HAS_UNALIGNED_LS) | ||
592 | - case OPC_USW: | ||
593 | -#endif | ||
594 | GEN_LOAD_REG_TN(T1, rt); | 712 | GEN_LOAD_REG_TN(T1, rt); |
595 | op_ldst(sw); | 713 | op_ldst(sw); |
596 | opn = "sw"; | 714 | opn = "sw"; |
597 | break; | 715 | break; |
598 | case OPC_LH: | 716 | case OPC_LH: |
599 | -#if defined (MIPS_HAS_UNALIGNED_LS) | ||
600 | - case OPC_ULH: | ||
601 | -#endif | ||
602 | op_ldst(lh); | 717 | op_ldst(lh); |
603 | GEN_STORE_TN_REG(rt, T0); | 718 | GEN_STORE_TN_REG(rt, T0); |
604 | opn = "lh"; | 719 | opn = "lh"; |
605 | break; | 720 | break; |
606 | case OPC_SH: | 721 | case OPC_SH: |
607 | -#if defined (MIPS_HAS_UNALIGNED_LS) | ||
608 | - case OPC_USH: | ||
609 | -#endif | ||
610 | GEN_LOAD_REG_TN(T1, rt); | 722 | GEN_LOAD_REG_TN(T1, rt); |
611 | op_ldst(sh); | 723 | op_ldst(sh); |
612 | opn = "sh"; | 724 | opn = "sh"; |
613 | break; | 725 | break; |
614 | case OPC_LHU: | 726 | case OPC_LHU: |
615 | -#if defined (MIPS_HAS_UNALIGNED_LS) | ||
616 | - case OPC_ULHU: | ||
617 | -#endif | ||
618 | op_ldst(lhu); | 727 | op_ldst(lhu); |
619 | GEN_STORE_TN_REG(rt, T0); | 728 | GEN_STORE_TN_REG(rt, T0); |
620 | opn = "lhu"; | 729 | opn = "lhu"; |
@@ -675,13 +784,11 @@ static void gen_ldst (DisasContext *ctx, uint16_t opc, int rt, | @@ -675,13 +784,11 @@ static void gen_ldst (DisasContext *ctx, uint16_t opc, int rt, | ||
675 | MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]); | 784 | MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]); |
676 | } | 785 | } |
677 | 786 | ||
678 | -#ifdef MIPS_USES_FPU | ||
679 | - | ||
680 | /* Load and store */ | 787 | /* Load and store */ |
681 | -static void gen_flt_ldst (DisasContext *ctx, uint16_t opc, int ft, | 788 | +static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft, |
682 | int base, int16_t offset) | 789 | int base, int16_t offset) |
683 | { | 790 | { |
684 | - const unsigned char *opn = "unk"; | 791 | + const char *opn = "unk"; |
685 | 792 | ||
686 | if (base == 0) { | 793 | if (base == 0) { |
687 | GEN_LOAD_IMM_TN(T0, offset); | 794 | GEN_LOAD_IMM_TN(T0, offset); |
@@ -718,21 +825,20 @@ static void gen_flt_ldst (DisasContext *ctx, uint16_t opc, int ft, | @@ -718,21 +825,20 @@ static void gen_flt_ldst (DisasContext *ctx, uint16_t opc, int ft, | ||
718 | break; | 825 | break; |
719 | default: | 826 | default: |
720 | MIPS_INVAL("float load/store"); | 827 | MIPS_INVAL("float load/store"); |
721 | - generate_exception(ctx, EXCP_CpU); | 828 | + generate_exception_err(ctx, EXCP_CpU, 1); |
722 | return; | 829 | return; |
723 | } | 830 | } |
724 | MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]); | 831 | MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]); |
725 | } | 832 | } |
726 | -#endif | ||
727 | 833 | ||
728 | /* Arithmetic with immediate operand */ | 834 | /* Arithmetic with immediate operand */ |
729 | -static void gen_arith_imm (DisasContext *ctx, uint16_t opc, int rt, | 835 | +static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt, |
730 | int rs, int16_t imm) | 836 | int rs, int16_t imm) |
731 | { | 837 | { |
732 | uint32_t uimm; | 838 | uint32_t uimm; |
733 | - const unsigned char *opn = "unk"; | 839 | + const char *opn = "unk"; |
734 | 840 | ||
735 | - if (rt == 0 && opc != OPC_ADDI) { | 841 | + if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) { |
736 | /* if no destination, treat it as a NOP | 842 | /* if no destination, treat it as a NOP |
737 | * For addi, we must generate the overflow exception when needed. | 843 | * For addi, we must generate the overflow exception when needed. |
738 | */ | 844 | */ |
@@ -740,8 +846,9 @@ static void gen_arith_imm (DisasContext *ctx, uint16_t opc, int rt, | @@ -740,8 +846,9 @@ static void gen_arith_imm (DisasContext *ctx, uint16_t opc, int rt, | ||
740 | return; | 846 | return; |
741 | } | 847 | } |
742 | if (opc == OPC_ADDI || opc == OPC_ADDIU || | 848 | if (opc == OPC_ADDI || opc == OPC_ADDIU || |
849 | + opc == OPC_DADDI || opc == OPC_DADDIU || | ||
743 | opc == OPC_SLTI || opc == OPC_SLTIU) | 850 | opc == OPC_SLTI || opc == OPC_SLTIU) |
744 | - uimm = (int32_t)imm; /* Sign extent to 32 bits */ | 851 | + uimm = (int32_t)imm; /* Sign extend to 32 bits */ |
745 | else | 852 | else |
746 | uimm = (uint16_t)imm; | 853 | uimm = (uint16_t)imm; |
747 | if (opc != OPC_LUI) { | 854 | if (opc != OPC_LUI) { |
@@ -761,6 +868,17 @@ static void gen_arith_imm (DisasContext *ctx, uint16_t opc, int rt, | @@ -761,6 +868,17 @@ static void gen_arith_imm (DisasContext *ctx, uint16_t opc, int rt, | ||
761 | gen_op_add(); | 868 | gen_op_add(); |
762 | opn = "addiu"; | 869 | opn = "addiu"; |
763 | break; | 870 | break; |
871 | +#ifdef MIPS_HAS_MIPS64 | ||
872 | + case OPC_DADDI: | ||
873 | + save_cpu_state(ctx, 1); | ||
874 | + gen_op_daddo(); | ||
875 | + opn = "daddi"; | ||
876 | + break; | ||
877 | + case OPC_DADDIU: | ||
878 | + gen_op_dadd(); | ||
879 | + opn = "daddiu"; | ||
880 | + break; | ||
881 | +#endif | ||
764 | case OPC_SLTI: | 882 | case OPC_SLTI: |
765 | gen_op_lt(); | 883 | gen_op_lt(); |
766 | opn = "slti"; | 884 | opn = "slti"; |
@@ -793,9 +911,50 @@ static void gen_arith_imm (DisasContext *ctx, uint16_t opc, int rt, | @@ -793,9 +911,50 @@ static void gen_arith_imm (DisasContext *ctx, uint16_t opc, int rt, | ||
793 | opn = "sra"; | 911 | opn = "sra"; |
794 | break; | 912 | break; |
795 | case OPC_SRL: | 913 | case OPC_SRL: |
796 | - gen_op_srl(); | ||
797 | - opn = "srl"; | 914 | + if ((ctx->opcode >> 21) & 1) { |
915 | + gen_op_rotr(); | ||
916 | + opn = "rotr"; | ||
917 | + } else { | ||
918 | + gen_op_srl(); | ||
919 | + opn = "srl"; | ||
920 | + } | ||
921 | + break; | ||
922 | +#ifdef MIPS_HAS_MIPS64 | ||
923 | + case OPC_DSLL: | ||
924 | + gen_op_dsll(); | ||
925 | + opn = "dsll"; | ||
926 | + break; | ||
927 | + case OPC_DSRA: | ||
928 | + gen_op_dsra(); | ||
929 | + opn = "dsra"; | ||
930 | + break; | ||
931 | + case OPC_DSRL: | ||
932 | + if ((ctx->opcode >> 21) & 1) { | ||
933 | + gen_op_drotr(); | ||
934 | + opn = "drotr"; | ||
935 | + } else { | ||
936 | + gen_op_dsrl(); | ||
937 | + opn = "dsrl"; | ||
938 | + } | ||
939 | + break; | ||
940 | + case OPC_DSLL32: | ||
941 | + gen_op_dsll32(); | ||
942 | + opn = "dsll32"; | ||
943 | + break; | ||
944 | + case OPC_DSRA32: | ||
945 | + gen_op_dsra32(); | ||
946 | + opn = "dsra32"; | ||
947 | + break; | ||
948 | + case OPC_DSRL32: | ||
949 | + if ((ctx->opcode >> 21) & 1) { | ||
950 | + gen_op_drotr32(); | ||
951 | + opn = "drotr32"; | ||
952 | + } else { | ||
953 | + gen_op_dsrl32(); | ||
954 | + opn = "dsrl32"; | ||
955 | + } | ||
798 | break; | 956 | break; |
957 | +#endif | ||
799 | default: | 958 | default: |
800 | MIPS_INVAL("imm arith"); | 959 | MIPS_INVAL("imm arith"); |
801 | generate_exception(ctx, EXCP_RI); | 960 | generate_exception(ctx, EXCP_RI); |
@@ -806,12 +965,13 @@ static void gen_arith_imm (DisasContext *ctx, uint16_t opc, int rt, | @@ -806,12 +965,13 @@ static void gen_arith_imm (DisasContext *ctx, uint16_t opc, int rt, | ||
806 | } | 965 | } |
807 | 966 | ||
808 | /* Arithmetic */ | 967 | /* Arithmetic */ |
809 | -static void gen_arith (DisasContext *ctx, uint16_t opc, | 968 | +static void gen_arith (DisasContext *ctx, uint32_t opc, |
810 | int rd, int rs, int rt) | 969 | int rd, int rs, int rt) |
811 | { | 970 | { |
812 | - const unsigned char *opn = "unk"; | 971 | + const char *opn = "unk"; |
813 | 972 | ||
814 | - if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB) { | 973 | + if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB |
974 | + && opc != OPC_DADD && opc != OPC_DSUB) { | ||
815 | /* if no destination, treat it as a NOP | 975 | /* if no destination, treat it as a NOP |
816 | * For add & sub, we must generate the overflow exception when needed. | 976 | * For add & sub, we must generate the overflow exception when needed. |
817 | */ | 977 | */ |
@@ -839,6 +999,26 @@ static void gen_arith (DisasContext *ctx, uint16_t opc, | @@ -839,6 +999,26 @@ static void gen_arith (DisasContext *ctx, uint16_t opc, | ||
839 | gen_op_sub(); | 999 | gen_op_sub(); |
840 | opn = "subu"; | 1000 | opn = "subu"; |
841 | break; | 1001 | break; |
1002 | +#ifdef MIPS_HAS_MIPS64 | ||
1003 | + case OPC_DADD: | ||
1004 | + save_cpu_state(ctx, 1); | ||
1005 | + gen_op_daddo(); | ||
1006 | + opn = "dadd"; | ||
1007 | + break; | ||
1008 | + case OPC_DADDU: | ||
1009 | + gen_op_dadd(); | ||
1010 | + opn = "daddu"; | ||
1011 | + break; | ||
1012 | + case OPC_DSUB: | ||
1013 | + save_cpu_state(ctx, 1); | ||
1014 | + gen_op_dsubo(); | ||
1015 | + opn = "dsub"; | ||
1016 | + break; | ||
1017 | + case OPC_DSUBU: | ||
1018 | + gen_op_dsub(); | ||
1019 | + opn = "dsubu"; | ||
1020 | + break; | ||
1021 | +#endif | ||
842 | case OPC_SLT: | 1022 | case OPC_SLT: |
843 | gen_op_lt(); | 1023 | gen_op_lt(); |
844 | opn = "slt"; | 1024 | opn = "slt"; |
@@ -884,9 +1064,33 @@ static void gen_arith (DisasContext *ctx, uint16_t opc, | @@ -884,9 +1064,33 @@ static void gen_arith (DisasContext *ctx, uint16_t opc, | ||
884 | opn = "srav"; | 1064 | opn = "srav"; |
885 | break; | 1065 | break; |
886 | case OPC_SRLV: | 1066 | case OPC_SRLV: |
887 | - gen_op_srlv(); | ||
888 | - opn = "srlv"; | 1067 | + if ((ctx->opcode >> 6) & 1) { |
1068 | + gen_op_rotrv(); | ||
1069 | + opn = "rotrv"; | ||
1070 | + } else { | ||
1071 | + gen_op_srlv(); | ||
1072 | + opn = "srlv"; | ||
1073 | + } | ||
1074 | + break; | ||
1075 | +#ifdef MIPS_HAS_MIPS64 | ||
1076 | + case OPC_DSLLV: | ||
1077 | + gen_op_dsllv(); | ||
1078 | + opn = "dsllv"; | ||
1079 | + break; | ||
1080 | + case OPC_DSRAV: | ||
1081 | + gen_op_dsrav(); | ||
1082 | + opn = "dsrav"; | ||
1083 | + break; | ||
1084 | + case OPC_DSRLV: | ||
1085 | + if ((ctx->opcode >> 6) & 1) { | ||
1086 | + gen_op_drotrv(); | ||
1087 | + opn = "drotrv"; | ||
1088 | + } else { | ||
1089 | + gen_op_dsrlv(); | ||
1090 | + opn = "dsrlv"; | ||
1091 | + } | ||
889 | break; | 1092 | break; |
1093 | +#endif | ||
890 | default: | 1094 | default: |
891 | MIPS_INVAL("arith"); | 1095 | MIPS_INVAL("arith"); |
892 | generate_exception(ctx, EXCP_RI); | 1096 | generate_exception(ctx, EXCP_RI); |
@@ -898,9 +1102,9 @@ static void gen_arith (DisasContext *ctx, uint16_t opc, | @@ -898,9 +1102,9 @@ static void gen_arith (DisasContext *ctx, uint16_t opc, | ||
898 | } | 1102 | } |
899 | 1103 | ||
900 | /* Arithmetic on HI/LO registers */ | 1104 | /* Arithmetic on HI/LO registers */ |
901 | -static void gen_HILO (DisasContext *ctx, uint16_t opc, int reg) | 1105 | +static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg) |
902 | { | 1106 | { |
903 | - const unsigned char *opn = "unk"; | 1107 | + const char *opn = "unk"; |
904 | 1108 | ||
905 | if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) { | 1109 | if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) { |
906 | /* Treat as a NOP */ | 1110 | /* Treat as a NOP */ |
@@ -936,10 +1140,10 @@ static void gen_HILO (DisasContext *ctx, uint16_t opc, int reg) | @@ -936,10 +1140,10 @@ static void gen_HILO (DisasContext *ctx, uint16_t opc, int reg) | ||
936 | MIPS_DEBUG("%s %s", opn, regnames[reg]); | 1140 | MIPS_DEBUG("%s %s", opn, regnames[reg]); |
937 | } | 1141 | } |
938 | 1142 | ||
939 | -static void gen_muldiv (DisasContext *ctx, uint16_t opc, | 1143 | +static void gen_muldiv (DisasContext *ctx, uint32_t opc, |
940 | int rs, int rt) | 1144 | int rs, int rt) |
941 | { | 1145 | { |
942 | - const unsigned char *opn = "unk"; | 1146 | + const char *opn = "unk"; |
943 | 1147 | ||
944 | GEN_LOAD_REG_TN(T0, rs); | 1148 | GEN_LOAD_REG_TN(T0, rs); |
945 | GEN_LOAD_REG_TN(T1, rt); | 1149 | GEN_LOAD_REG_TN(T1, rt); |
@@ -960,6 +1164,24 @@ static void gen_muldiv (DisasContext *ctx, uint16_t opc, | @@ -960,6 +1164,24 @@ static void gen_muldiv (DisasContext *ctx, uint16_t opc, | ||
960 | gen_op_multu(); | 1164 | gen_op_multu(); |
961 | opn = "multu"; | 1165 | opn = "multu"; |
962 | break; | 1166 | break; |
1167 | +#ifdef MIPS_HAS_MIPS64 | ||
1168 | + case OPC_DDIV: | ||
1169 | + gen_op_ddiv(); | ||
1170 | + opn = "ddiv"; | ||
1171 | + break; | ||
1172 | + case OPC_DDIVU: | ||
1173 | + gen_op_ddivu(); | ||
1174 | + opn = "ddivu"; | ||
1175 | + break; | ||
1176 | + case OPC_DMULT: | ||
1177 | + gen_op_dmult(); | ||
1178 | + opn = "dmult"; | ||
1179 | + break; | ||
1180 | + case OPC_DMULTU: | ||
1181 | + gen_op_dmultu(); | ||
1182 | + opn = "dmultu"; | ||
1183 | + break; | ||
1184 | +#endif | ||
963 | case OPC_MADD: | 1185 | case OPC_MADD: |
964 | gen_op_madd(); | 1186 | gen_op_madd(); |
965 | opn = "madd"; | 1187 | opn = "madd"; |
@@ -984,10 +1206,10 @@ static void gen_muldiv (DisasContext *ctx, uint16_t opc, | @@ -984,10 +1206,10 @@ static void gen_muldiv (DisasContext *ctx, uint16_t opc, | ||
984 | MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]); | 1206 | MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]); |
985 | } | 1207 | } |
986 | 1208 | ||
987 | -static void gen_cl (DisasContext *ctx, uint16_t opc, | 1209 | +static void gen_cl (DisasContext *ctx, uint32_t opc, |
988 | int rd, int rs) | 1210 | int rd, int rs) |
989 | { | 1211 | { |
990 | - const unsigned char *opn = "unk"; | 1212 | + const char *opn = "unk"; |
991 | if (rd == 0) { | 1213 | if (rd == 0) { |
992 | /* Treat as a NOP */ | 1214 | /* Treat as a NOP */ |
993 | MIPS_DEBUG("NOP"); | 1215 | MIPS_DEBUG("NOP"); |
@@ -996,15 +1218,23 @@ static void gen_cl (DisasContext *ctx, uint16_t opc, | @@ -996,15 +1218,23 @@ static void gen_cl (DisasContext *ctx, uint16_t opc, | ||
996 | GEN_LOAD_REG_TN(T0, rs); | 1218 | GEN_LOAD_REG_TN(T0, rs); |
997 | switch (opc) { | 1219 | switch (opc) { |
998 | case OPC_CLO: | 1220 | case OPC_CLO: |
999 | - /* CLO */ | ||
1000 | gen_op_clo(); | 1221 | gen_op_clo(); |
1001 | opn = "clo"; | 1222 | opn = "clo"; |
1002 | break; | 1223 | break; |
1003 | case OPC_CLZ: | 1224 | case OPC_CLZ: |
1004 | - /* CLZ */ | ||
1005 | gen_op_clz(); | 1225 | gen_op_clz(); |
1006 | opn = "clz"; | 1226 | opn = "clz"; |
1007 | break; | 1227 | break; |
1228 | +#ifdef MIPS_HAS_MIPS64 | ||
1229 | + case OPC_DCLO: | ||
1230 | + gen_op_dclo(); | ||
1231 | + opn = "dclo"; | ||
1232 | + break; | ||
1233 | + case OPC_DCLZ: | ||
1234 | + gen_op_dclz(); | ||
1235 | + opn = "dclz"; | ||
1236 | + break; | ||
1237 | +#endif | ||
1008 | default: | 1238 | default: |
1009 | MIPS_INVAL("CLx"); | 1239 | MIPS_INVAL("CLx"); |
1010 | generate_exception(ctx, EXCP_RI); | 1240 | generate_exception(ctx, EXCP_RI); |
@@ -1015,7 +1245,7 @@ static void gen_cl (DisasContext *ctx, uint16_t opc, | @@ -1015,7 +1245,7 @@ static void gen_cl (DisasContext *ctx, uint16_t opc, | ||
1015 | } | 1245 | } |
1016 | 1246 | ||
1017 | /* Traps */ | 1247 | /* Traps */ |
1018 | -static void gen_trap (DisasContext *ctx, uint16_t opc, | 1248 | +static void gen_trap (DisasContext *ctx, uint32_t opc, |
1019 | int rs, int rt, int16_t imm) | 1249 | int rs, int rt, int16_t imm) |
1020 | { | 1250 | { |
1021 | int cond; | 1251 | int cond; |
@@ -1130,7 +1360,7 @@ static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) | @@ -1130,7 +1360,7 @@ static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) | ||
1130 | } | 1360 | } |
1131 | 1361 | ||
1132 | /* Branches (before delay slot) */ | 1362 | /* Branches (before delay slot) */ |
1133 | -static void gen_compute_branch (DisasContext *ctx, uint16_t opc, | 1363 | +static void gen_compute_branch (DisasContext *ctx, uint32_t opc, |
1134 | int rs, int rt, int32_t offset) | 1364 | int rs, int rt, int32_t offset) |
1135 | { | 1365 | { |
1136 | target_ulong btarget; | 1366 | target_ulong btarget; |
@@ -1180,8 +1410,9 @@ static void gen_compute_branch (DisasContext *ctx, uint16_t opc, | @@ -1180,8 +1410,9 @@ static void gen_compute_branch (DisasContext *ctx, uint16_t opc, | ||
1180 | case OPC_JR: | 1410 | case OPC_JR: |
1181 | case OPC_JALR: | 1411 | case OPC_JALR: |
1182 | /* Jump to register */ | 1412 | /* Jump to register */ |
1183 | - if (offset != 0) { | ||
1184 | - /* Only hint = 0 is valid */ | 1413 | + if (offset != 0 && offset != 16) { |
1414 | + /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the | ||
1415 | + others are reserved. */ | ||
1185 | generate_exception(ctx, EXCP_RI); | 1416 | generate_exception(ctx, EXCP_RI); |
1186 | return; | 1417 | return; |
1187 | } | 1418 | } |
@@ -1348,80 +1579,342 @@ static void gen_compute_branch (DisasContext *ctx, uint16_t opc, | @@ -1348,80 +1579,342 @@ static void gen_compute_branch (DisasContext *ctx, uint16_t opc, | ||
1348 | return; | 1579 | return; |
1349 | } | 1580 | } |
1350 | 1581 | ||
1582 | +/* special3 bitfield operations */ | ||
1583 | +static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt, | ||
1584 | + int rs, int lsb, int msb) | ||
1585 | +{ | ||
1586 | + GEN_LOAD_REG_TN(T1, rs); | ||
1587 | + switch (opc) { | ||
1588 | + case OPC_EXT: | ||
1589 | + if (lsb + msb > 31) | ||
1590 | + goto fail; | ||
1591 | + gen_op_ext(lsb, msb + 1); | ||
1592 | + break; | ||
1593 | + case OPC_DEXTM: | ||
1594 | + if (lsb + msb > 63) | ||
1595 | + goto fail; | ||
1596 | + gen_op_ext(lsb, msb + 1 + 32); | ||
1597 | + break; | ||
1598 | + case OPC_DEXTU: | ||
1599 | + if (lsb + msb > 63) | ||
1600 | + goto fail; | ||
1601 | + gen_op_ext(lsb + 32, msb + 1); | ||
1602 | + break; | ||
1603 | + case OPC_DEXT: | ||
1604 | + gen_op_ext(lsb, msb + 1); | ||
1605 | + break; | ||
1606 | + case OPC_INS: | ||
1607 | + if (lsb > msb) | ||
1608 | + goto fail; | ||
1609 | + GEN_LOAD_REG_TN(T2, rt); | ||
1610 | + gen_op_ins(lsb, msb - lsb + 1); | ||
1611 | + break; | ||
1612 | + case OPC_DINSM: | ||
1613 | + if (lsb > msb) | ||
1614 | + goto fail; | ||
1615 | + GEN_LOAD_REG_TN(T2, rt); | ||
1616 | + gen_op_ins(lsb, msb - lsb + 1 + 32); | ||
1617 | + break; | ||
1618 | + case OPC_DINSU: | ||
1619 | + if (lsb > msb) | ||
1620 | + goto fail; | ||
1621 | + GEN_LOAD_REG_TN(T2, rt); | ||
1622 | + gen_op_ins(lsb + 32, msb - lsb + 1); | ||
1623 | + break; | ||
1624 | + case OPC_DINS: | ||
1625 | + if (lsb > msb) | ||
1626 | + goto fail; | ||
1627 | + GEN_LOAD_REG_TN(T2, rt); | ||
1628 | + gen_op_ins(lsb, msb - lsb + 1); | ||
1629 | + break; | ||
1630 | + default: | ||
1631 | +fail: | ||
1632 | + MIPS_INVAL("bitops"); | ||
1633 | + generate_exception(ctx, EXCP_RI); | ||
1634 | + return; | ||
1635 | + } | ||
1636 | + GEN_STORE_TN_REG(rt, T0); | ||
1637 | +} | ||
1638 | + | ||
1351 | /* CP0 (MMU and control) */ | 1639 | /* CP0 (MMU and control) */ |
1352 | static void gen_mfc0 (DisasContext *ctx, int reg, int sel) | 1640 | static void gen_mfc0 (DisasContext *ctx, int reg, int sel) |
1353 | { | 1641 | { |
1354 | - const unsigned char *rn; | 1642 | + const char *rn = "invalid"; |
1355 | 1643 | ||
1356 | - if (sel != 0 && reg != 16 && reg != 28) { | ||
1357 | - rn = "invalid"; | ||
1358 | - goto die; | ||
1359 | - } | ||
1360 | switch (reg) { | 1644 | switch (reg) { |
1361 | case 0: | 1645 | case 0: |
1362 | - gen_op_mfc0_index(); | ||
1363 | - rn = "Index"; | 1646 | + switch (sel) { |
1647 | + case 0: | ||
1648 | + gen_op_mfc0_index(); | ||
1649 | + rn = "Index"; | ||
1650 | + break; | ||
1651 | + case 1: | ||
1652 | +// gen_op_mfc0_mvpcontrol(); /* MT ASE */ | ||
1653 | + rn = "MVPControl"; | ||
1654 | +// break; | ||
1655 | + case 2: | ||
1656 | +// gen_op_mfc0_mvpconf0(); /* MT ASE */ | ||
1657 | + rn = "MVPConf0"; | ||
1658 | +// break; | ||
1659 | + case 3: | ||
1660 | +// gen_op_mfc0_mvpconf1(); /* MT ASE */ | ||
1661 | + rn = "MVPConf1"; | ||
1662 | +// break; | ||
1663 | + default: | ||
1664 | + goto die; | ||
1665 | + } | ||
1364 | break; | 1666 | break; |
1365 | case 1: | 1667 | case 1: |
1366 | - gen_op_mfc0_random(); | ||
1367 | - rn = "Random"; | 1668 | + switch (sel) { |
1669 | + case 0: | ||
1670 | + gen_op_mfc0_random(); | ||
1671 | + rn = "Random"; | ||
1672 | + break; | ||
1673 | + case 1: | ||
1674 | +// gen_op_mfc0_vpecontrol(); /* MT ASE */ | ||
1675 | + rn = "VPEControl"; | ||
1676 | +// break; | ||
1677 | + case 2: | ||
1678 | +// gen_op_mfc0_vpeconf0(); /* MT ASE */ | ||
1679 | + rn = "VPEConf0"; | ||
1680 | +// break; | ||
1681 | + case 3: | ||
1682 | +// gen_op_mfc0_vpeconf1(); /* MT ASE */ | ||
1683 | + rn = "VPEConf1"; | ||
1684 | +// break; | ||
1685 | + case 4: | ||
1686 | +// gen_op_mfc0_YQMask(); /* MT ASE */ | ||
1687 | + rn = "YQMask"; | ||
1688 | +// break; | ||
1689 | + case 5: | ||
1690 | +// gen_op_mfc0_vpeschedule(); /* MT ASE */ | ||
1691 | + rn = "VPESchedule"; | ||
1692 | +// break; | ||
1693 | + case 6: | ||
1694 | +// gen_op_mfc0_vpeschefback(); /* MT ASE */ | ||
1695 | + rn = "VPEScheFBack"; | ||
1696 | +// break; | ||
1697 | + case 7: | ||
1698 | +// gen_op_mfc0_vpeopt(); /* MT ASE */ | ||
1699 | + rn = "VPEOpt"; | ||
1700 | +// break; | ||
1701 | + default: | ||
1702 | + goto die; | ||
1703 | + } | ||
1368 | break; | 1704 | break; |
1369 | case 2: | 1705 | case 2: |
1370 | - gen_op_mfc0_entrylo0(); | ||
1371 | - rn = "EntryLo0"; | 1706 | + switch (sel) { |
1707 | + case 0: | ||
1708 | + gen_op_mfc0_entrylo0(); | ||
1709 | + rn = "EntryLo0"; | ||
1710 | + break; | ||
1711 | + case 1: | ||
1712 | +// gen_op_mfc0_tcstatus(); /* MT ASE */ | ||
1713 | + rn = "TCStatus"; | ||
1714 | +// break; | ||
1715 | + case 2: | ||
1716 | +// gen_op_mfc0_tcbind(); /* MT ASE */ | ||
1717 | + rn = "TCBind"; | ||
1718 | +// break; | ||
1719 | + case 3: | ||
1720 | +// gen_op_mfc0_tcrestart(); /* MT ASE */ | ||
1721 | + rn = "TCRestart"; | ||
1722 | +// break; | ||
1723 | + case 4: | ||
1724 | +// gen_op_mfc0_tchalt(); /* MT ASE */ | ||
1725 | + rn = "TCHalt"; | ||
1726 | +// break; | ||
1727 | + case 5: | ||
1728 | +// gen_op_mfc0_tccontext(); /* MT ASE */ | ||
1729 | + rn = "TCContext"; | ||
1730 | +// break; | ||
1731 | + case 6: | ||
1732 | +// gen_op_mfc0_tcschedule(); /* MT ASE */ | ||
1733 | + rn = "TCSchedule"; | ||
1734 | +// break; | ||
1735 | + case 7: | ||
1736 | +// gen_op_mfc0_tcschefback(); /* MT ASE */ | ||
1737 | + rn = "TCScheFBack"; | ||
1738 | +// break; | ||
1739 | + default: | ||
1740 | + goto die; | ||
1741 | + } | ||
1372 | break; | 1742 | break; |
1373 | case 3: | 1743 | case 3: |
1374 | - /* also CONF */ | ||
1375 | - gen_op_mfc0_entrylo1(); | ||
1376 | - rn = "EntryLo1"; | 1744 | + switch (sel) { |
1745 | + case 0: | ||
1746 | + gen_op_mfc0_entrylo1(); | ||
1747 | + rn = "EntryLo1"; | ||
1748 | + break; | ||
1749 | + default: | ||
1750 | + goto die; | ||
1751 | + } | ||
1377 | break; | 1752 | break; |
1378 | case 4: | 1753 | case 4: |
1379 | - gen_op_mfc0_context(); | ||
1380 | - rn = "Context"; | 1754 | + switch (sel) { |
1755 | + case 0: | ||
1756 | + gen_op_mfc0_context(); | ||
1757 | + rn = "Context"; | ||
1758 | + break; | ||
1759 | + case 1: | ||
1760 | +// gen_op_mfc0_contextconfig(); /* SmartMIPS ASE */ | ||
1761 | + rn = "ContextConfig"; | ||
1762 | +// break; | ||
1763 | + default: | ||
1764 | + goto die; | ||
1765 | + } | ||
1381 | break; | 1766 | break; |
1382 | case 5: | 1767 | case 5: |
1383 | - gen_op_mfc0_pagemask(); | ||
1384 | - rn = "PageMask"; | 1768 | + switch (sel) { |
1769 | + case 0: | ||
1770 | + gen_op_mfc0_pagemask(); | ||
1771 | + rn = "PageMask"; | ||
1772 | + break; | ||
1773 | + case 1: | ||
1774 | + gen_op_mfc0_pagegrain(); | ||
1775 | + rn = "PageGrain"; | ||
1776 | + break; | ||
1777 | + default: | ||
1778 | + goto die; | ||
1779 | + } | ||
1385 | break; | 1780 | break; |
1386 | case 6: | 1781 | case 6: |
1387 | - gen_op_mfc0_wired(); | ||
1388 | - rn = "Wired"; | 1782 | + switch (sel) { |
1783 | + case 0: | ||
1784 | + gen_op_mfc0_wired(); | ||
1785 | + rn = "Wired"; | ||
1786 | + break; | ||
1787 | + case 1: | ||
1788 | +// gen_op_mfc0_srsconf0(); /* shadow registers */ | ||
1789 | + rn = "SRSConf0"; | ||
1790 | +// break; | ||
1791 | + case 2: | ||
1792 | +// gen_op_mfc0_srsconf1(); /* shadow registers */ | ||
1793 | + rn = "SRSConf1"; | ||
1794 | +// break; | ||
1795 | + case 3: | ||
1796 | +// gen_op_mfc0_srsconf2(); /* shadow registers */ | ||
1797 | + rn = "SRSConf2"; | ||
1798 | +// break; | ||
1799 | + case 4: | ||
1800 | +// gen_op_mfc0_srsconf3(); /* shadow registers */ | ||
1801 | + rn = "SRSConf3"; | ||
1802 | +// break; | ||
1803 | + case 5: | ||
1804 | +// gen_op_mfc0_srsconf4(); /* shadow registers */ | ||
1805 | + rn = "SRSConf4"; | ||
1806 | +// break; | ||
1807 | + default: | ||
1808 | + goto die; | ||
1809 | + } | ||
1389 | break; | 1810 | break; |
1390 | case 7: | 1811 | case 7: |
1391 | -// gen_op_mfc0_info(); | ||
1392 | - rn = "Info"; | 1812 | + switch (sel) { |
1813 | + case 0: | ||
1814 | + gen_op_mfc0_hwrena(); | ||
1815 | + rn = "HWREna"; | ||
1816 | + break; | ||
1817 | + default: | ||
1818 | + goto die; | ||
1819 | + } | ||
1393 | break; | 1820 | break; |
1394 | case 8: | 1821 | case 8: |
1395 | - gen_op_mfc0_badvaddr(); | ||
1396 | - rn = "BadVaddr"; | 1822 | + switch (sel) { |
1823 | + case 0: | ||
1824 | + gen_op_mfc0_badvaddr(); | ||
1825 | + rn = "BadVaddr"; | ||
1826 | + break; | ||
1827 | + default: | ||
1828 | + goto die; | ||
1829 | + } | ||
1397 | break; | 1830 | break; |
1398 | case 9: | 1831 | case 9: |
1399 | - gen_op_mfc0_count(); | ||
1400 | - rn = "Count"; | 1832 | + switch (sel) { |
1833 | + case 0: | ||
1834 | + gen_op_mfc0_count(); | ||
1835 | + rn = "Count"; | ||
1836 | + break; | ||
1837 | + /* 6,7 are implementation dependent */ | ||
1838 | + default: | ||
1839 | + goto die; | ||
1840 | + } | ||
1401 | break; | 1841 | break; |
1402 | case 10: | 1842 | case 10: |
1403 | - gen_op_mfc0_entryhi(); | ||
1404 | - rn = "EntryHi"; | 1843 | + switch (sel) { |
1844 | + case 0: | ||
1845 | + gen_op_mfc0_entryhi(); | ||
1846 | + rn = "EntryHi"; | ||
1847 | + break; | ||
1848 | + default: | ||
1849 | + goto die; | ||
1850 | + } | ||
1405 | break; | 1851 | break; |
1406 | case 11: | 1852 | case 11: |
1407 | - gen_op_mfc0_compare(); | ||
1408 | - rn = "Compare"; | 1853 | + switch (sel) { |
1854 | + case 0: | ||
1855 | + gen_op_mfc0_compare(); | ||
1856 | + rn = "Compare"; | ||
1857 | + break; | ||
1858 | + /* 6,7 are implementation dependent */ | ||
1859 | + default: | ||
1860 | + goto die; | ||
1861 | + } | ||
1409 | break; | 1862 | break; |
1410 | case 12: | 1863 | case 12: |
1411 | - gen_op_mfc0_status(); | ||
1412 | - rn = "Status"; | 1864 | + switch (sel) { |
1865 | + case 0: | ||
1866 | + gen_op_mfc0_status(); | ||
1867 | + rn = "Status"; | ||
1868 | + break; | ||
1869 | + case 1: | ||
1870 | + gen_op_mfc0_intctl(); | ||
1871 | + rn = "IntCtl"; | ||
1872 | + break; | ||
1873 | + case 2: | ||
1874 | + gen_op_mfc0_srsctl(); | ||
1875 | + rn = "SRSCtl"; | ||
1876 | + break; | ||
1877 | + case 3: | ||
1878 | +// gen_op_mfc0_srsmap(); /* shadow registers */ | ||
1879 | + rn = "SRSMap"; | ||
1880 | +// break; | ||
1881 | + default: | ||
1882 | + goto die; | ||
1883 | + } | ||
1413 | break; | 1884 | break; |
1414 | case 13: | 1885 | case 13: |
1415 | - gen_op_mfc0_cause(); | ||
1416 | - rn = "Cause"; | 1886 | + switch (sel) { |
1887 | + case 0: | ||
1888 | + gen_op_mfc0_cause(); | ||
1889 | + rn = "Cause"; | ||
1890 | + break; | ||
1891 | + default: | ||
1892 | + goto die; | ||
1893 | + } | ||
1417 | break; | 1894 | break; |
1418 | case 14: | 1895 | case 14: |
1419 | - gen_op_mfc0_epc(); | ||
1420 | - rn = "EPC"; | 1896 | + switch (sel) { |
1897 | + case 0: | ||
1898 | + gen_op_mfc0_epc(); | ||
1899 | + rn = "EPC"; | ||
1900 | + break; | ||
1901 | + default: | ||
1902 | + goto die; | ||
1903 | + } | ||
1421 | break; | 1904 | break; |
1422 | case 15: | 1905 | case 15: |
1423 | - gen_op_mfc0_prid(); | ||
1424 | - rn = "PRid"; | 1906 | + switch (sel) { |
1907 | + case 0: | ||
1908 | + gen_op_mfc0_prid(); | ||
1909 | + rn = "PRid"; | ||
1910 | + break; | ||
1911 | + case 1: | ||
1912 | + gen_op_mfc0_ebase(); | ||
1913 | + rn = "EBase"; | ||
1914 | + break; | ||
1915 | + default: | ||
1916 | + goto die; | ||
1917 | + } | ||
1425 | break; | 1918 | break; |
1426 | case 16: | 1919 | case 16: |
1427 | switch (sel) { | 1920 | switch (sel) { |
@@ -1433,91 +1926,285 @@ static void gen_mfc0 (DisasContext *ctx, int reg, int sel) | @@ -1433,91 +1926,285 @@ static void gen_mfc0 (DisasContext *ctx, int reg, int sel) | ||
1433 | gen_op_mfc0_config1(); | 1926 | gen_op_mfc0_config1(); |
1434 | rn = "Config1"; | 1927 | rn = "Config1"; |
1435 | break; | 1928 | break; |
1929 | + case 2: | ||
1930 | + gen_op_mfc0_config2(); | ||
1931 | + rn = "Config2"; | ||
1932 | + break; | ||
1933 | + case 3: | ||
1934 | + gen_op_mfc0_config3(); | ||
1935 | + rn = "Config3"; | ||
1936 | + break; | ||
1937 | + /* 6,7 are implementation dependent */ | ||
1436 | default: | 1938 | default: |
1437 | - rn = "Unknown config register"; | ||
1438 | goto die; | 1939 | goto die; |
1439 | } | 1940 | } |
1440 | break; | 1941 | break; |
1441 | case 17: | 1942 | case 17: |
1442 | - gen_op_mfc0_lladdr(); | ||
1443 | - rn = "LLAddr"; | 1943 | + switch (sel) { |
1944 | + case 0: | ||
1945 | + gen_op_mfc0_lladdr(); | ||
1946 | + rn = "LLAddr"; | ||
1947 | + break; | ||
1948 | + default: | ||
1949 | + goto die; | ||
1950 | + } | ||
1444 | break; | 1951 | break; |
1445 | case 18: | 1952 | case 18: |
1446 | - gen_op_mfc0_watchlo(); | ||
1447 | - rn = "WatchLo"; | 1953 | + switch (sel) { |
1954 | + case 0: | ||
1955 | + gen_op_mfc0_watchlo0(); | ||
1956 | + rn = "WatchLo"; | ||
1957 | + break; | ||
1958 | + case 1: | ||
1959 | +// gen_op_mfc0_watchlo1(); | ||
1960 | + rn = "WatchLo1"; | ||
1961 | +// break; | ||
1962 | + case 2: | ||
1963 | +// gen_op_mfc0_watchlo2(); | ||
1964 | + rn = "WatchLo2"; | ||
1965 | +// break; | ||
1966 | + case 3: | ||
1967 | +// gen_op_mfc0_watchlo3(); | ||
1968 | + rn = "WatchLo3"; | ||
1969 | +// break; | ||
1970 | + case 4: | ||
1971 | +// gen_op_mfc0_watchlo4(); | ||
1972 | + rn = "WatchLo4"; | ||
1973 | +// break; | ||
1974 | + case 5: | ||
1975 | +// gen_op_mfc0_watchlo5(); | ||
1976 | + rn = "WatchLo5"; | ||
1977 | +// break; | ||
1978 | + case 6: | ||
1979 | +// gen_op_mfc0_watchlo6(); | ||
1980 | + rn = "WatchLo6"; | ||
1981 | +// break; | ||
1982 | + case 7: | ||
1983 | +// gen_op_mfc0_watchlo7(); | ||
1984 | + rn = "WatchLo7"; | ||
1985 | +// break; | ||
1986 | + default: | ||
1987 | + goto die; | ||
1988 | + } | ||
1448 | break; | 1989 | break; |
1449 | case 19: | 1990 | case 19: |
1450 | - gen_op_mfc0_watchhi(); | ||
1451 | - rn = "WatchHi"; | 1991 | + switch (sel) { |
1992 | + case 0: | ||
1993 | + gen_op_mfc0_watchhi0(); | ||
1994 | + rn = "WatchHi"; | ||
1995 | + break; | ||
1996 | + case 1: | ||
1997 | +// gen_op_mfc0_watchhi1(); | ||
1998 | + rn = "WatchHi1"; | ||
1999 | +// break; | ||
2000 | + case 2: | ||
2001 | +// gen_op_mfc0_watchhi2(); | ||
2002 | + rn = "WatchHi2"; | ||
2003 | +// break; | ||
2004 | + case 3: | ||
2005 | +// gen_op_mfc0_watchhi3(); | ||
2006 | + rn = "WatchHi3"; | ||
2007 | +// break; | ||
2008 | + case 4: | ||
2009 | +// gen_op_mfc0_watchhi4(); | ||
2010 | + rn = "WatchHi4"; | ||
2011 | +// break; | ||
2012 | + case 5: | ||
2013 | +// gen_op_mfc0_watchhi5(); | ||
2014 | + rn = "WatchHi5"; | ||
2015 | +// break; | ||
2016 | + case 6: | ||
2017 | +// gen_op_mfc0_watchhi6(); | ||
2018 | + rn = "WatchHi6"; | ||
2019 | +// break; | ||
2020 | + case 7: | ||
2021 | +// gen_op_mfc0_watchhi7(); | ||
2022 | + rn = "WatchHi7"; | ||
2023 | +// break; | ||
2024 | + default: | ||
2025 | + goto die; | ||
2026 | + } | ||
1452 | break; | 2027 | break; |
1453 | case 20: | 2028 | case 20: |
1454 | - /* 64 bit only */ | ||
1455 | -// gen_op_mfc0_xcontext(); | ||
1456 | - rn = "XContext"; | 2029 | + switch (sel) { |
2030 | + case 0: | ||
2031 | + /* 64 bit MMU only */ | ||
2032 | + gen_op_mfc0_xcontext(); | ||
2033 | + rn = "XContext"; | ||
2034 | + break; | ||
2035 | + default: | ||
2036 | + goto die; | ||
2037 | + } | ||
1457 | break; | 2038 | break; |
1458 | case 21: | 2039 | case 21: |
1459 | -// gen_op_mfc0_framemask(); | ||
1460 | - rn = "Framemask"; | 2040 | + /* Officially reserved, but sel 0 is used for R1x000 framemask */ |
2041 | + switch (sel) { | ||
2042 | + case 0: | ||
2043 | + gen_op_mfc0_framemask(); | ||
2044 | + rn = "Framemask"; | ||
2045 | + break; | ||
2046 | + default: | ||
2047 | + goto die; | ||
2048 | + } | ||
1461 | break; | 2049 | break; |
1462 | case 22: | 2050 | case 22: |
1463 | -// gen_op_mfc0_diagnostic(); | ||
1464 | - rn = "'Diagnostic"; | ||
1465 | - break; | 2051 | + /* ignored */ |
2052 | + rn = "'Diagnostic"; /* implementation dependent */ | ||
2053 | + break; | ||
1466 | case 23: | 2054 | case 23: |
1467 | - gen_op_mfc0_debug(); | ||
1468 | - rn = "Debug"; | 2055 | + switch (sel) { |
2056 | + case 0: | ||
2057 | + gen_op_mfc0_debug(); /* EJTAG support */ | ||
2058 | + rn = "Debug"; | ||
2059 | + break; | ||
2060 | + case 1: | ||
2061 | +// gen_op_mfc0_tracecontrol(); /* PDtrace support */ | ||
2062 | + rn = "TraceControl"; | ||
2063 | +// break; | ||
2064 | + case 2: | ||
2065 | +// gen_op_mfc0_tracecontrol2(); /* PDtrace support */ | ||
2066 | + rn = "TraceControl2"; | ||
2067 | +// break; | ||
2068 | + case 3: | ||
2069 | +// gen_op_mfc0_usertracedata(); /* PDtrace support */ | ||
2070 | + rn = "UserTraceData"; | ||
2071 | +// break; | ||
2072 | + case 4: | ||
2073 | +// gen_op_mfc0_debug(); /* PDtrace support */ | ||
2074 | + rn = "TraceBPC"; | ||
2075 | +// break; | ||
2076 | + default: | ||
2077 | + goto die; | ||
2078 | + } | ||
1469 | break; | 2079 | break; |
1470 | case 24: | 2080 | case 24: |
1471 | - gen_op_mfc0_depc(); | ||
1472 | - rn = "DEPC"; | 2081 | + switch (sel) { |
2082 | + case 0: | ||
2083 | + gen_op_mfc0_depc(); /* EJTAG support */ | ||
2084 | + rn = "DEPC"; | ||
2085 | + break; | ||
2086 | + default: | ||
2087 | + goto die; | ||
2088 | + } | ||
1473 | break; | 2089 | break; |
1474 | case 25: | 2090 | case 25: |
1475 | -// gen_op_mfc0_performance(); | ||
1476 | - rn = "Performance"; | 2091 | + switch (sel) { |
2092 | + case 0: | ||
2093 | + gen_op_mfc0_performance0(); | ||
2094 | + rn = "Performance0"; | ||
2095 | + break; | ||
2096 | + case 1: | ||
2097 | +// gen_op_mfc0_performance1(); | ||
2098 | + rn = "Performance1"; | ||
2099 | +// break; | ||
2100 | + case 2: | ||
2101 | +// gen_op_mfc0_performance2(); | ||
2102 | + rn = "Performance2"; | ||
2103 | +// break; | ||
2104 | + case 3: | ||
2105 | +// gen_op_mfc0_performance3(); | ||
2106 | + rn = "Performance3"; | ||
2107 | +// break; | ||
2108 | + case 4: | ||
2109 | +// gen_op_mfc0_performance4(); | ||
2110 | + rn = "Performance4"; | ||
2111 | +// break; | ||
2112 | + case 5: | ||
2113 | +// gen_op_mfc0_performance5(); | ||
2114 | + rn = "Performance5"; | ||
2115 | +// break; | ||
2116 | + case 6: | ||
2117 | +// gen_op_mfc0_performance6(); | ||
2118 | + rn = "Performance6"; | ||
2119 | +// break; | ||
2120 | + case 7: | ||
2121 | +// gen_op_mfc0_performance7(); | ||
2122 | + rn = "Performance7"; | ||
2123 | +// break; | ||
2124 | + default: | ||
2125 | + goto die; | ||
2126 | + } | ||
1477 | break; | 2127 | break; |
1478 | case 26: | 2128 | case 26: |
1479 | -// gen_op_mfc0_ecc(); | ||
1480 | - rn = "ECC"; | ||
1481 | - break; | 2129 | + rn = "ECC"; |
2130 | + break; | ||
1482 | case 27: | 2131 | case 27: |
1483 | -// gen_op_mfc0_cacheerr(); | ||
1484 | - rn = "CacheErr"; | 2132 | + switch (sel) { |
2133 | + /* ignored */ | ||
2134 | + case 0 ... 3: | ||
2135 | + rn = "CacheErr"; | ||
2136 | + break; | ||
2137 | + default: | ||
2138 | + goto die; | ||
2139 | + } | ||
1485 | break; | 2140 | break; |
1486 | case 28: | 2141 | case 28: |
1487 | switch (sel) { | 2142 | switch (sel) { |
1488 | case 0: | 2143 | case 0: |
2144 | + case 2: | ||
2145 | + case 4: | ||
2146 | + case 6: | ||
1489 | gen_op_mfc0_taglo(); | 2147 | gen_op_mfc0_taglo(); |
1490 | rn = "TagLo"; | 2148 | rn = "TagLo"; |
1491 | break; | 2149 | break; |
1492 | case 1: | 2150 | case 1: |
2151 | + case 3: | ||
2152 | + case 5: | ||
2153 | + case 7: | ||
1493 | gen_op_mfc0_datalo(); | 2154 | gen_op_mfc0_datalo(); |
1494 | rn = "DataLo"; | 2155 | rn = "DataLo"; |
1495 | break; | 2156 | break; |
1496 | default: | 2157 | default: |
1497 | - rn = "unknown sel"; | ||
1498 | goto die; | 2158 | goto die; |
1499 | } | 2159 | } |
1500 | break; | 2160 | break; |
1501 | case 29: | 2161 | case 29: |
1502 | -// gen_op_mfc0_taghi(); | ||
1503 | - rn = "TagHi"; | 2162 | + switch (sel) { |
2163 | + case 0: | ||
2164 | + case 2: | ||
2165 | + case 4: | ||
2166 | + case 6: | ||
2167 | + gen_op_mfc0_taghi(); | ||
2168 | + rn = "TagHi"; | ||
2169 | + break; | ||
2170 | + case 1: | ||
2171 | + case 3: | ||
2172 | + case 5: | ||
2173 | + case 7: | ||
2174 | + gen_op_mfc0_datahi(); | ||
2175 | + rn = "DataHi"; | ||
2176 | + break; | ||
2177 | + default: | ||
2178 | + goto die; | ||
2179 | + } | ||
1504 | break; | 2180 | break; |
1505 | case 30: | 2181 | case 30: |
1506 | - gen_op_mfc0_errorepc(); | ||
1507 | - rn = "ErrorEPC"; | 2182 | + switch (sel) { |
2183 | + case 0: | ||
2184 | + gen_op_mfc0_errorepc(); | ||
2185 | + rn = "ErrorEPC"; | ||
2186 | + break; | ||
2187 | + default: | ||
2188 | + goto die; | ||
2189 | + } | ||
1508 | break; | 2190 | break; |
1509 | case 31: | 2191 | case 31: |
1510 | - gen_op_mfc0_desave(); | ||
1511 | - rn = "DESAVE"; | 2192 | + switch (sel) { |
2193 | + case 0: | ||
2194 | + gen_op_mfc0_desave(); /* EJTAG support */ | ||
2195 | + rn = "DESAVE"; | ||
2196 | + break; | ||
2197 | + default: | ||
2198 | + goto die; | ||
2199 | + } | ||
1512 | break; | 2200 | break; |
1513 | default: | 2201 | default: |
1514 | - rn = "unknown"; | ||
1515 | goto die; | 2202 | goto die; |
1516 | } | 2203 | } |
1517 | #if defined MIPS_DEBUG_DISAS | 2204 | #if defined MIPS_DEBUG_DISAS |
1518 | if (loglevel & CPU_LOG_TB_IN_ASM) { | 2205 | if (loglevel & CPU_LOG_TB_IN_ASM) { |
1519 | - fprintf(logfile, "%08x mfc0 %s => %08x (%d %d)\n", | ||
1520 | - env->PC, rn, T0, reg, sel); | 2206 | + fprintf(logfile, "mfc0 %s (reg %d sel %d)\n", |
2207 | + rn, reg, sel); | ||
1521 | } | 2208 | } |
1522 | #endif | 2209 | #endif |
1523 | return; | 2210 | return; |
@@ -1525,8 +2212,8 @@ static void gen_mfc0 (DisasContext *ctx, int reg, int sel) | @@ -1525,8 +2212,8 @@ static void gen_mfc0 (DisasContext *ctx, int reg, int sel) | ||
1525 | die: | 2212 | die: |
1526 | #if defined MIPS_DEBUG_DISAS | 2213 | #if defined MIPS_DEBUG_DISAS |
1527 | if (loglevel & CPU_LOG_TB_IN_ASM) { | 2214 | if (loglevel & CPU_LOG_TB_IN_ASM) { |
1528 | - fprintf(logfile, "%08x mfc0 %s => %08x (%d %d)\n", | ||
1529 | - env->PC, rn, T0, reg, sel); | 2215 | + fprintf(logfile, "mfc0 %s (reg %d sel %d)\n", |
2216 | + rn, reg, sel); | ||
1530 | } | 2217 | } |
1531 | #endif | 2218 | #endif |
1532 | generate_exception(ctx, EXCP_RI); | 2219 | generate_exception(ctx, EXCP_RI); |
@@ -1534,167 +2221,583 @@ die: | @@ -1534,167 +2221,583 @@ die: | ||
1534 | 2221 | ||
1535 | static void gen_mtc0 (DisasContext *ctx, int reg, int sel) | 2222 | static void gen_mtc0 (DisasContext *ctx, int reg, int sel) |
1536 | { | 2223 | { |
1537 | - const unsigned char *rn; | ||
1538 | - uint32_t val, old; | ||
1539 | - | ||
1540 | - if (sel != 0 && reg != 16 && reg != 28) { | ||
1541 | - val = -1; | ||
1542 | - old = -1; | ||
1543 | - rn = "invalid"; | ||
1544 | - goto die; | ||
1545 | - } | 2224 | + const char *rn = "invalid"; |
2225 | + | ||
1546 | switch (reg) { | 2226 | switch (reg) { |
1547 | case 0: | 2227 | case 0: |
1548 | - gen_op_mtc0_index(); | ||
1549 | - rn = "Index"; | 2228 | + switch (sel) { |
2229 | + case 0: | ||
2230 | + gen_op_mtc0_index(); | ||
2231 | + rn = "Index"; | ||
2232 | + break; | ||
2233 | + case 1: | ||
2234 | +// gen_op_mtc0_mvpcontrol(); /* MT ASE */ | ||
2235 | + rn = "MVPControl"; | ||
2236 | +// break; | ||
2237 | + case 2: | ||
2238 | +// gen_op_mtc0_mvpconf0(); /* MT ASE */ | ||
2239 | + rn = "MVPConf0"; | ||
2240 | +// break; | ||
2241 | + case 3: | ||
2242 | +// gen_op_mtc0_mvpconf1(); /* MT ASE */ | ||
2243 | + rn = "MVPConf1"; | ||
2244 | +// break; | ||
2245 | + default: | ||
2246 | + goto die; | ||
2247 | + } | ||
1550 | break; | 2248 | break; |
1551 | case 1: | 2249 | case 1: |
1552 | -// ignore or except? | ||
1553 | - rn = "Random"; | 2250 | + switch (sel) { |
2251 | + case 0: | ||
2252 | + /* ignored */ | ||
2253 | + rn = "Random"; | ||
2254 | + break; | ||
2255 | + case 1: | ||
2256 | +// gen_op_mtc0_vpecontrol(); /* MT ASE */ | ||
2257 | + rn = "VPEControl"; | ||
2258 | +// break; | ||
2259 | + case 2: | ||
2260 | +// gen_op_mtc0_vpeconf0(); /* MT ASE */ | ||
2261 | + rn = "VPEConf0"; | ||
2262 | +// break; | ||
2263 | + case 3: | ||
2264 | +// gen_op_mtc0_vpeconf1(); /* MT ASE */ | ||
2265 | + rn = "VPEConf1"; | ||
2266 | +// break; | ||
2267 | + case 4: | ||
2268 | +// gen_op_mtc0_YQMask(); /* MT ASE */ | ||
2269 | + rn = "YQMask"; | ||
2270 | +// break; | ||
2271 | + case 5: | ||
2272 | +// gen_op_mtc0_vpeschedule(); /* MT ASE */ | ||
2273 | + rn = "VPESchedule"; | ||
2274 | +// break; | ||
2275 | + case 6: | ||
2276 | +// gen_op_mtc0_vpeschefback(); /* MT ASE */ | ||
2277 | + rn = "VPEScheFBack"; | ||
2278 | +// break; | ||
2279 | + case 7: | ||
2280 | +// gen_op_mtc0_vpeopt(); /* MT ASE */ | ||
2281 | + rn = "VPEOpt"; | ||
2282 | +// break; | ||
2283 | + default: | ||
2284 | + goto die; | ||
2285 | + } | ||
1554 | break; | 2286 | break; |
1555 | case 2: | 2287 | case 2: |
1556 | - gen_op_mtc0_entrylo0(); | ||
1557 | - rn = "EntryLo0"; | 2288 | + switch (sel) { |
2289 | + case 0: | ||
2290 | + gen_op_mtc0_entrylo0(); | ||
2291 | + rn = "EntryLo0"; | ||
2292 | + break; | ||
2293 | + case 1: | ||
2294 | +// gen_op_mtc0_tcstatus(); /* MT ASE */ | ||
2295 | + rn = "TCStatus"; | ||
2296 | +// break; | ||
2297 | + case 2: | ||
2298 | +// gen_op_mtc0_tcbind(); /* MT ASE */ | ||
2299 | + rn = "TCBind"; | ||
2300 | +// break; | ||
2301 | + case 3: | ||
2302 | +// gen_op_mtc0_tcrestart(); /* MT ASE */ | ||
2303 | + rn = "TCRestart"; | ||
2304 | +// break; | ||
2305 | + case 4: | ||
2306 | +// gen_op_mtc0_tchalt(); /* MT ASE */ | ||
2307 | + rn = "TCHalt"; | ||
2308 | +// break; | ||
2309 | + case 5: | ||
2310 | +// gen_op_mtc0_tccontext(); /* MT ASE */ | ||
2311 | + rn = "TCContext"; | ||
2312 | +// break; | ||
2313 | + case 6: | ||
2314 | +// gen_op_mtc0_tcschedule(); /* MT ASE */ | ||
2315 | + rn = "TCSchedule"; | ||
2316 | +// break; | ||
2317 | + case 7: | ||
2318 | +// gen_op_mtc0_tcschefback(); /* MT ASE */ | ||
2319 | + rn = "TCScheFBack"; | ||
2320 | +// break; | ||
2321 | + default: | ||
2322 | + goto die; | ||
2323 | + } | ||
1558 | break; | 2324 | break; |
1559 | case 3: | 2325 | case 3: |
1560 | - gen_op_mtc0_entrylo1(); | ||
1561 | - rn = "EntryLo1"; | 2326 | + switch (sel) { |
2327 | + case 0: | ||
2328 | + gen_op_mtc0_entrylo1(); | ||
2329 | + rn = "EntryLo1"; | ||
2330 | + break; | ||
2331 | + default: | ||
2332 | + goto die; | ||
2333 | + } | ||
1562 | break; | 2334 | break; |
1563 | case 4: | 2335 | case 4: |
1564 | - gen_op_mtc0_context(); | ||
1565 | - rn = "Context"; | 2336 | + switch (sel) { |
2337 | + case 0: | ||
2338 | + gen_op_mtc0_context(); | ||
2339 | + rn = "Context"; | ||
2340 | + break; | ||
2341 | + case 1: | ||
2342 | +// gen_op_mtc0_contextconfig(); /* SmartMIPS ASE */ | ||
2343 | + rn = "ContextConfig"; | ||
2344 | +// break; | ||
2345 | + default: | ||
2346 | + goto die; | ||
2347 | + } | ||
1566 | break; | 2348 | break; |
1567 | case 5: | 2349 | case 5: |
1568 | - gen_op_mtc0_pagemask(); | ||
1569 | - rn = "PageMask"; | 2350 | + switch (sel) { |
2351 | + case 0: | ||
2352 | + gen_op_mtc0_pagemask(); | ||
2353 | + rn = "PageMask"; | ||
2354 | + break; | ||
2355 | + case 1: | ||
2356 | + gen_op_mtc0_pagegrain(); | ||
2357 | + rn = "PageGrain"; | ||
2358 | + break; | ||
2359 | + default: | ||
2360 | + goto die; | ||
2361 | + } | ||
1570 | break; | 2362 | break; |
1571 | case 6: | 2363 | case 6: |
1572 | - gen_op_mtc0_wired(); | ||
1573 | - rn = "Wired"; | 2364 | + switch (sel) { |
2365 | + case 0: | ||
2366 | + gen_op_mtc0_wired(); | ||
2367 | + rn = "Wired"; | ||
2368 | + break; | ||
2369 | + case 1: | ||
2370 | +// gen_op_mtc0_srsconf0(); /* shadow registers */ | ||
2371 | + rn = "SRSConf0"; | ||
2372 | +// break; | ||
2373 | + case 2: | ||
2374 | +// gen_op_mtc0_srsconf1(); /* shadow registers */ | ||
2375 | + rn = "SRSConf1"; | ||
2376 | +// break; | ||
2377 | + case 3: | ||
2378 | +// gen_op_mtc0_srsconf2(); /* shadow registers */ | ||
2379 | + rn = "SRSConf2"; | ||
2380 | +// break; | ||
2381 | + case 4: | ||
2382 | +// gen_op_mtc0_srsconf3(); /* shadow registers */ | ||
2383 | + rn = "SRSConf3"; | ||
2384 | +// break; | ||
2385 | + case 5: | ||
2386 | +// gen_op_mtc0_srsconf4(); /* shadow registers */ | ||
2387 | + rn = "SRSConf4"; | ||
2388 | +// break; | ||
2389 | + default: | ||
2390 | + goto die; | ||
2391 | + } | ||
1574 | break; | 2392 | break; |
1575 | case 7: | 2393 | case 7: |
1576 | -// ignore or except? | ||
1577 | - rn = "Info"; | 2394 | + switch (sel) { |
2395 | + case 0: | ||
2396 | + gen_op_mtc0_hwrena(); | ||
2397 | + rn = "HWREna"; | ||
2398 | + break; | ||
2399 | + default: | ||
2400 | + goto die; | ||
2401 | + } | ||
1578 | break; | 2402 | break; |
1579 | case 8: | 2403 | case 8: |
1580 | -// ignore or except? | 2404 | + /* ignored */ |
1581 | rn = "BadVaddr"; | 2405 | rn = "BadVaddr"; |
1582 | break; | 2406 | break; |
1583 | case 9: | 2407 | case 9: |
1584 | - gen_op_mtc0_count(); | ||
1585 | - rn = "Count"; | 2408 | + switch (sel) { |
2409 | + case 0: | ||
2410 | + gen_op_mtc0_count(); | ||
2411 | + rn = "Count"; | ||
2412 | + break; | ||
2413 | + /* 6,7 are implementation dependent */ | ||
2414 | + default: | ||
2415 | + goto die; | ||
2416 | + } | ||
2417 | + /* Stop translation as we may have switched the execution mode */ | ||
2418 | + ctx->bstate = BS_STOP; | ||
1586 | break; | 2419 | break; |
1587 | case 10: | 2420 | case 10: |
1588 | - gen_op_mtc0_entryhi(); | ||
1589 | - rn = "EntryHi"; | 2421 | + switch (sel) { |
2422 | + case 0: | ||
2423 | + gen_op_mtc0_entryhi(); | ||
2424 | + rn = "EntryHi"; | ||
2425 | + break; | ||
2426 | + default: | ||
2427 | + goto die; | ||
2428 | + } | ||
1590 | break; | 2429 | break; |
1591 | case 11: | 2430 | case 11: |
1592 | - gen_op_mtc0_compare(); | ||
1593 | - rn = "Compare"; | 2431 | + switch (sel) { |
2432 | + case 0: | ||
2433 | + gen_op_mtc0_compare(); | ||
2434 | + rn = "Compare"; | ||
2435 | + break; | ||
2436 | + /* 6,7 are implementation dependent */ | ||
2437 | + default: | ||
2438 | + goto die; | ||
2439 | + } | ||
2440 | + /* Stop translation as we may have switched the execution mode */ | ||
2441 | + ctx->bstate = BS_STOP; | ||
1594 | break; | 2442 | break; |
1595 | case 12: | 2443 | case 12: |
1596 | - gen_op_mtc0_status(); | ||
1597 | - rn = "Status"; | 2444 | + switch (sel) { |
2445 | + case 0: | ||
2446 | + gen_op_mtc0_status(); | ||
2447 | + rn = "Status"; | ||
2448 | + break; | ||
2449 | + case 1: | ||
2450 | + gen_op_mtc0_intctl(); | ||
2451 | + rn = "IntCtl"; | ||
2452 | + break; | ||
2453 | + case 2: | ||
2454 | + gen_op_mtc0_srsctl(); | ||
2455 | + rn = "SRSCtl"; | ||
2456 | + break; | ||
2457 | + case 3: | ||
2458 | +// gen_op_mtc0_srsmap(); /* shadow registers */ | ||
2459 | + rn = "SRSMap"; | ||
2460 | +// break; | ||
2461 | + default: | ||
2462 | + goto die; | ||
2463 | + } | ||
2464 | + /* Stop translation as we may have switched the execution mode */ | ||
2465 | + ctx->bstate = BS_STOP; | ||
1598 | break; | 2466 | break; |
1599 | case 13: | 2467 | case 13: |
1600 | - gen_op_mtc0_cause(); | ||
1601 | - rn = "Cause"; | 2468 | + switch (sel) { |
2469 | + case 0: | ||
2470 | + gen_op_mtc0_cause(); | ||
2471 | + rn = "Cause"; | ||
2472 | + break; | ||
2473 | + default: | ||
2474 | + goto die; | ||
2475 | + } | ||
2476 | + /* Stop translation as we may have switched the execution mode */ | ||
2477 | + ctx->bstate = BS_STOP; | ||
1602 | break; | 2478 | break; |
1603 | case 14: | 2479 | case 14: |
1604 | - gen_op_mtc0_epc(); | ||
1605 | - rn = "EPC"; | 2480 | + switch (sel) { |
2481 | + case 0: | ||
2482 | + gen_op_mtc0_epc(); | ||
2483 | + rn = "EPC"; | ||
2484 | + break; | ||
2485 | + default: | ||
2486 | + goto die; | ||
2487 | + } | ||
1606 | break; | 2488 | break; |
1607 | case 15: | 2489 | case 15: |
1608 | -// ignore or except? | ||
1609 | - rn = "PRid"; | 2490 | + switch (sel) { |
2491 | + case 0: | ||
2492 | + /* ignored */ | ||
2493 | + rn = "PRid"; | ||
2494 | + break; | ||
2495 | + case 1: | ||
2496 | + gen_op_mtc0_ebase(); | ||
2497 | + rn = "EBase"; | ||
2498 | + break; | ||
2499 | + default: | ||
2500 | + goto die; | ||
2501 | + } | ||
1610 | break; | 2502 | break; |
1611 | case 16: | 2503 | case 16: |
1612 | switch (sel) { | 2504 | switch (sel) { |
1613 | case 0: | 2505 | case 0: |
1614 | gen_op_mtc0_config0(); | 2506 | gen_op_mtc0_config0(); |
1615 | - rn = "Config0"; | 2507 | + rn = "Config"; |
2508 | + break; | ||
2509 | + case 1: | ||
2510 | + /* ignored */ | ||
2511 | + rn = "Config1"; | ||
2512 | + break; | ||
2513 | + case 2: | ||
2514 | + gen_op_mtc0_config2(); | ||
2515 | + rn = "Config2"; | ||
1616 | break; | 2516 | break; |
2517 | + case 3: | ||
2518 | + /* ignored */ | ||
2519 | + rn = "Config3"; | ||
2520 | + break; | ||
2521 | + /* 6,7 are implementation dependent */ | ||
1617 | default: | 2522 | default: |
1618 | rn = "Invalid config selector"; | 2523 | rn = "Invalid config selector"; |
1619 | goto die; | 2524 | goto die; |
1620 | } | 2525 | } |
2526 | + /* Stop translation as we may have switched the execution mode */ | ||
2527 | + ctx->bstate = BS_STOP; | ||
1621 | break; | 2528 | break; |
1622 | case 17: | 2529 | case 17: |
1623 | -// ignore or except? | ||
1624 | - rn = "LLaddr"; | 2530 | + switch (sel) { |
2531 | + case 0: | ||
2532 | + /* ignored */ | ||
2533 | + rn = "LLAddr"; | ||
2534 | + break; | ||
2535 | + default: | ||
2536 | + goto die; | ||
2537 | + } | ||
1625 | break; | 2538 | break; |
1626 | case 18: | 2539 | case 18: |
1627 | - gen_op_mtc0_watchlo(); | ||
1628 | - rn = "WatchLo"; | 2540 | + switch (sel) { |
2541 | + case 0: | ||
2542 | + gen_op_mtc0_watchlo0(); | ||
2543 | + rn = "WatchLo"; | ||
2544 | + break; | ||
2545 | + case 1: | ||
2546 | +// gen_op_mtc0_watchlo1(); | ||
2547 | + rn = "WatchLo1"; | ||
2548 | +// break; | ||
2549 | + case 2: | ||
2550 | +// gen_op_mtc0_watchlo2(); | ||
2551 | + rn = "WatchLo2"; | ||
2552 | +// break; | ||
2553 | + case 3: | ||
2554 | +// gen_op_mtc0_watchlo3(); | ||
2555 | + rn = "WatchLo3"; | ||
2556 | +// break; | ||
2557 | + case 4: | ||
2558 | +// gen_op_mtc0_watchlo4(); | ||
2559 | + rn = "WatchLo4"; | ||
2560 | +// break; | ||
2561 | + case 5: | ||
2562 | +// gen_op_mtc0_watchlo5(); | ||
2563 | + rn = "WatchLo5"; | ||
2564 | +// break; | ||
2565 | + case 6: | ||
2566 | +// gen_op_mtc0_watchlo6(); | ||
2567 | + rn = "WatchLo6"; | ||
2568 | +// break; | ||
2569 | + case 7: | ||
2570 | +// gen_op_mtc0_watchlo7(); | ||
2571 | + rn = "WatchLo7"; | ||
2572 | +// break; | ||
2573 | + default: | ||
2574 | + goto die; | ||
2575 | + } | ||
1629 | break; | 2576 | break; |
1630 | case 19: | 2577 | case 19: |
1631 | - gen_op_mtc0_watchhi(); | ||
1632 | - rn = "WatchHi"; | 2578 | + switch (sel) { |
2579 | + case 0: | ||
2580 | + gen_op_mtc0_watchhi0(); | ||
2581 | + rn = "WatchHi"; | ||
2582 | + break; | ||
2583 | + case 1: | ||
2584 | +// gen_op_mtc0_watchhi1(); | ||
2585 | + rn = "WatchHi1"; | ||
2586 | +// break; | ||
2587 | + case 2: | ||
2588 | +// gen_op_mtc0_watchhi2(); | ||
2589 | + rn = "WatchHi2"; | ||
2590 | +// break; | ||
2591 | + case 3: | ||
2592 | +// gen_op_mtc0_watchhi3(); | ||
2593 | + rn = "WatchHi3"; | ||
2594 | +// break; | ||
2595 | + case 4: | ||
2596 | +// gen_op_mtc0_watchhi4(); | ||
2597 | + rn = "WatchHi4"; | ||
2598 | +// break; | ||
2599 | + case 5: | ||
2600 | +// gen_op_mtc0_watchhi5(); | ||
2601 | + rn = "WatchHi5"; | ||
2602 | +// break; | ||
2603 | + case 6: | ||
2604 | +// gen_op_mtc0_watchhi6(); | ||
2605 | + rn = "WatchHi6"; | ||
2606 | +// break; | ||
2607 | + case 7: | ||
2608 | +// gen_op_mtc0_watchhi7(); | ||
2609 | + rn = "WatchHi7"; | ||
2610 | +// break; | ||
2611 | + default: | ||
2612 | + goto die; | ||
2613 | + } | ||
1633 | break; | 2614 | break; |
1634 | case 20: | 2615 | case 20: |
1635 | - /* 64 bit only */ | ||
1636 | -// gen_op_mtc0_xcontext(); | ||
1637 | - rn = "XContext"; | 2616 | + switch (sel) { |
2617 | + case 0: | ||
2618 | + /* 64 bit MMU only */ | ||
2619 | + gen_op_mtc0_xcontext(); | ||
2620 | + rn = "XContext"; | ||
2621 | + break; | ||
2622 | + default: | ||
2623 | + goto die; | ||
2624 | + } | ||
1638 | break; | 2625 | break; |
1639 | case 21: | 2626 | case 21: |
1640 | -// gen_op_mtc0_framemask(); | ||
1641 | - rn = "Framemask"; | ||
1642 | - break; | 2627 | + /* Officially reserved, but sel 0 is used for R1x000 framemask */ |
2628 | + switch (sel) { | ||
2629 | + case 0: | ||
2630 | + gen_op_mtc0_framemask(); | ||
2631 | + rn = "Framemask"; | ||
2632 | + break; | ||
2633 | + default: | ||
2634 | + goto die; | ||
2635 | + } | ||
2636 | + break; | ||
1643 | case 22: | 2637 | case 22: |
1644 | -// ignore or except? | ||
1645 | - rn = "Diagnostic"; | 2638 | + /* ignored */ |
2639 | + rn = "Diagnostic"; /* implementation dependent */ | ||
1646 | break; | 2640 | break; |
1647 | case 23: | 2641 | case 23: |
1648 | - gen_op_mtc0_debug(); | ||
1649 | - rn = "Debug"; | 2642 | + switch (sel) { |
2643 | + case 0: | ||
2644 | + gen_op_mtc0_debug(); /* EJTAG support */ | ||
2645 | + rn = "Debug"; | ||
2646 | + break; | ||
2647 | + case 1: | ||
2648 | +// gen_op_mtc0_tracecontrol(); /* PDtrace support */ | ||
2649 | + rn = "TraceControl"; | ||
2650 | +// break; | ||
2651 | + case 2: | ||
2652 | +// gen_op_mtc0_tracecontrol2(); /* PDtrace support */ | ||
2653 | + rn = "TraceControl2"; | ||
2654 | +// break; | ||
2655 | + case 3: | ||
2656 | +// gen_op_mtc0_usertracedata(); /* PDtrace support */ | ||
2657 | + rn = "UserTraceData"; | ||
2658 | +// break; | ||
2659 | + case 4: | ||
2660 | +// gen_op_mtc0_debug(); /* PDtrace support */ | ||
2661 | + rn = "TraceBPC"; | ||
2662 | +// break; | ||
2663 | + default: | ||
2664 | + goto die; | ||
2665 | + } | ||
2666 | + /* Stop translation as we may have switched the execution mode */ | ||
2667 | + ctx->bstate = BS_STOP; | ||
1650 | break; | 2668 | break; |
1651 | case 24: | 2669 | case 24: |
1652 | - gen_op_mtc0_depc(); | ||
1653 | - rn = "DEPC"; | 2670 | + switch (sel) { |
2671 | + case 0: | ||
2672 | + gen_op_mtc0_depc(); /* EJTAG support */ | ||
2673 | + rn = "DEPC"; | ||
2674 | + break; | ||
2675 | + default: | ||
2676 | + goto die; | ||
2677 | + } | ||
1654 | break; | 2678 | break; |
1655 | case 25: | 2679 | case 25: |
1656 | -// ignore or except? | ||
1657 | - rn = "Performance"; | 2680 | + switch (sel) { |
2681 | + case 0: | ||
2682 | + gen_op_mtc0_performance0(); | ||
2683 | + rn = "Performance0"; | ||
2684 | + break; | ||
2685 | + case 1: | ||
2686 | +// gen_op_mtc0_performance1(); | ||
2687 | + rn = "Performance1"; | ||
2688 | +// break; | ||
2689 | + case 2: | ||
2690 | +// gen_op_mtc0_performance2(); | ||
2691 | + rn = "Performance2"; | ||
2692 | +// break; | ||
2693 | + case 3: | ||
2694 | +// gen_op_mtc0_performance3(); | ||
2695 | + rn = "Performance3"; | ||
2696 | +// break; | ||
2697 | + case 4: | ||
2698 | +// gen_op_mtc0_performance4(); | ||
2699 | + rn = "Performance4"; | ||
2700 | +// break; | ||
2701 | + case 5: | ||
2702 | +// gen_op_mtc0_performance5(); | ||
2703 | + rn = "Performance5"; | ||
2704 | +// break; | ||
2705 | + case 6: | ||
2706 | +// gen_op_mtc0_performance6(); | ||
2707 | + rn = "Performance6"; | ||
2708 | +// break; | ||
2709 | + case 7: | ||
2710 | +// gen_op_mtc0_performance7(); | ||
2711 | + rn = "Performance7"; | ||
2712 | +// break; | ||
2713 | + default: | ||
2714 | + goto die; | ||
2715 | + } | ||
1658 | break; | 2716 | break; |
1659 | case 26: | 2717 | case 26: |
1660 | -// ignore or except? | 2718 | + /* ignored */ |
1661 | rn = "ECC"; | 2719 | rn = "ECC"; |
1662 | break; | 2720 | break; |
1663 | case 27: | 2721 | case 27: |
1664 | -// ignore or except? | ||
1665 | - rn = "CacheErr"; | 2722 | + switch (sel) { |
2723 | + case 0 ... 3: | ||
2724 | + /* ignored */ | ||
2725 | + rn = "CacheErr"; | ||
2726 | + break; | ||
2727 | + default: | ||
2728 | + goto die; | ||
2729 | + } | ||
1666 | break; | 2730 | break; |
1667 | case 28: | 2731 | case 28: |
1668 | switch (sel) { | 2732 | switch (sel) { |
1669 | case 0: | 2733 | case 0: |
2734 | + case 2: | ||
2735 | + case 4: | ||
2736 | + case 6: | ||
1670 | gen_op_mtc0_taglo(); | 2737 | gen_op_mtc0_taglo(); |
1671 | rn = "TagLo"; | 2738 | rn = "TagLo"; |
1672 | break; | 2739 | break; |
2740 | + case 1: | ||
2741 | + case 3: | ||
2742 | + case 5: | ||
2743 | + case 7: | ||
2744 | + gen_op_mtc0_datalo(); | ||
2745 | + rn = "DataLo"; | ||
2746 | + break; | ||
1673 | default: | 2747 | default: |
1674 | - rn = "invalid sel"; | ||
1675 | goto die; | 2748 | goto die; |
1676 | } | 2749 | } |
1677 | break; | 2750 | break; |
1678 | case 29: | 2751 | case 29: |
1679 | -// gen_op_mtc0_taghi(); | ||
1680 | - rn = "TagHi"; | 2752 | + switch (sel) { |
2753 | + case 0: | ||
2754 | + case 2: | ||
2755 | + case 4: | ||
2756 | + case 6: | ||
2757 | + gen_op_mtc0_taghi(); | ||
2758 | + rn = "TagHi"; | ||
2759 | + break; | ||
2760 | + case 1: | ||
2761 | + case 3: | ||
2762 | + case 5: | ||
2763 | + case 7: | ||
2764 | + gen_op_mtc0_datahi(); | ||
2765 | + rn = "DataHi"; | ||
2766 | + break; | ||
2767 | + default: | ||
2768 | + rn = "invalid sel"; | ||
2769 | + goto die; | ||
2770 | + } | ||
1681 | break; | 2771 | break; |
1682 | case 30: | 2772 | case 30: |
1683 | - gen_op_mtc0_errorepc(); | ||
1684 | - rn = "ErrorEPC"; | 2773 | + switch (sel) { |
2774 | + case 0: | ||
2775 | + gen_op_mtc0_errorepc(); | ||
2776 | + rn = "ErrorEPC"; | ||
2777 | + break; | ||
2778 | + default: | ||
2779 | + goto die; | ||
2780 | + } | ||
1685 | break; | 2781 | break; |
1686 | case 31: | 2782 | case 31: |
1687 | - gen_op_mtc0_desave(); | ||
1688 | - rn = "DESAVE"; | 2783 | + switch (sel) { |
2784 | + case 0: | ||
2785 | + gen_op_mtc0_desave(); /* EJTAG support */ | ||
2786 | + rn = "DESAVE"; | ||
2787 | + break; | ||
2788 | + default: | ||
2789 | + goto die; | ||
2790 | + } | ||
2791 | + /* Stop translation as we may have switched the execution mode */ | ||
2792 | + ctx->bstate = BS_STOP; | ||
1689 | break; | 2793 | break; |
1690 | default: | 2794 | default: |
1691 | - rn = "unknown"; | ||
1692 | goto die; | 2795 | goto die; |
1693 | } | 2796 | } |
1694 | #if defined MIPS_DEBUG_DISAS | 2797 | #if defined MIPS_DEBUG_DISAS |
1695 | if (loglevel & CPU_LOG_TB_IN_ASM) { | 2798 | if (loglevel & CPU_LOG_TB_IN_ASM) { |
1696 | - fprintf(logfile, "%08x mtc0 %s => %08x (%d %d)\n", | ||
1697 | - env->PC, rn, T0, reg, sel); | 2799 | + fprintf(logfile, "mtc0 %s (reg %d sel %d)\n", |
2800 | + rn, reg, sel); | ||
1698 | } | 2801 | } |
1699 | #endif | 2802 | #endif |
1700 | return; | 2803 | return; |
@@ -1702,16 +2805,16 @@ static void gen_mtc0 (DisasContext *ctx, int reg, int sel) | @@ -1702,16 +2805,16 @@ static void gen_mtc0 (DisasContext *ctx, int reg, int sel) | ||
1702 | die: | 2805 | die: |
1703 | #if defined MIPS_DEBUG_DISAS | 2806 | #if defined MIPS_DEBUG_DISAS |
1704 | if (loglevel & CPU_LOG_TB_IN_ASM) { | 2807 | if (loglevel & CPU_LOG_TB_IN_ASM) { |
1705 | - fprintf(logfile, "%08x mtc0 %s => %08x (%d %d)\n", | ||
1706 | - env->PC, rn, T0, reg, sel); | 2808 | + fprintf(logfile, "mtc0 %s (reg %d sel %d)\n", |
2809 | + rn, reg, sel); | ||
1707 | } | 2810 | } |
1708 | #endif | 2811 | #endif |
1709 | generate_exception(ctx, EXCP_RI); | 2812 | generate_exception(ctx, EXCP_RI); |
1710 | } | 2813 | } |
1711 | 2814 | ||
1712 | -static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd) | 2815 | +static void gen_cp0 (DisasContext *ctx, uint32_t opc, int rt, int rd) |
1713 | { | 2816 | { |
1714 | - const unsigned char *opn = "unk"; | 2817 | + const char *opn = "unk"; |
1715 | 2818 | ||
1716 | if (!(ctx->CP0_Status & (1 << CP0St_CU0)) && | 2819 | if (!(ctx->CP0_Status & (1 << CP0St_CU0)) && |
1717 | (ctx->hflags & MIPS_HFLAG_UM) && | 2820 | (ctx->hflags & MIPS_HFLAG_UM) && |
@@ -1720,7 +2823,7 @@ static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd) | @@ -1720,7 +2823,7 @@ static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd) | ||
1720 | if (loglevel & CPU_LOG_TB_IN_ASM) { | 2823 | if (loglevel & CPU_LOG_TB_IN_ASM) { |
1721 | fprintf(logfile, "CP0 is not usable\n"); | 2824 | fprintf(logfile, "CP0 is not usable\n"); |
1722 | } | 2825 | } |
1723 | - generate_exception_err (ctx, EXCP_CpU, 0); | 2826 | + generate_exception (ctx, EXCP_CpU); |
1724 | return; | 2827 | return; |
1725 | } | 2828 | } |
1726 | 2829 | ||
@@ -1736,13 +2839,12 @@ static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd) | @@ -1736,13 +2839,12 @@ static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd) | ||
1736 | break; | 2839 | break; |
1737 | case OPC_MTC0: | 2840 | case OPC_MTC0: |
1738 | /* If we get an exception, we want to restart at next instruction */ | 2841 | /* If we get an exception, we want to restart at next instruction */ |
2842 | + /* XXX: breaks for mtc in delay slot */ | ||
1739 | ctx->pc += 4; | 2843 | ctx->pc += 4; |
1740 | save_cpu_state(ctx, 1); | 2844 | save_cpu_state(ctx, 1); |
1741 | ctx->pc -= 4; | 2845 | ctx->pc -= 4; |
1742 | GEN_LOAD_REG_TN(T0, rt); | 2846 | GEN_LOAD_REG_TN(T0, rt); |
1743 | gen_mtc0(ctx, rd, ctx->opcode & 0x7); | 2847 | gen_mtc0(ctx, rd, ctx->opcode & 0x7); |
1744 | - /* Stop translation as we may have switched the execution mode */ | ||
1745 | - ctx->bstate = BS_STOP; | ||
1746 | opn = "mtc0"; | 2848 | opn = "mtc0"; |
1747 | break; | 2849 | break; |
1748 | #if defined(MIPS_USES_R4K_TLB) | 2850 | #if defined(MIPS_USES_R4K_TLB) |
@@ -1800,31 +2902,30 @@ static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd) | @@ -1800,31 +2902,30 @@ static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd) | ||
1800 | MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd); | 2902 | MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd); |
1801 | } | 2903 | } |
1802 | 2904 | ||
1803 | -#ifdef MIPS_USES_FPU | ||
1804 | /* CP1 Branches (before delay slot) */ | 2905 | /* CP1 Branches (before delay slot) */ |
1805 | -static void gen_compute_branch1 (DisasContext *ctx, uint16_t cond, | 2906 | +static void gen_compute_branch1 (DisasContext *ctx, uint32_t op, |
1806 | int32_t offset) | 2907 | int32_t offset) |
1807 | { | 2908 | { |
1808 | target_ulong btarget; | 2909 | target_ulong btarget; |
1809 | 2910 | ||
1810 | btarget = ctx->pc + 4 + offset; | 2911 | btarget = ctx->pc + 4 + offset; |
1811 | 2912 | ||
1812 | - switch (cond) { | ||
1813 | - case 0x0000: /* bc1f */ | 2913 | + switch (op) { |
2914 | + case OPC_BC1F: | ||
1814 | gen_op_bc1f(); | 2915 | gen_op_bc1f(); |
1815 | MIPS_DEBUG("bc1f %08x", btarget); | 2916 | MIPS_DEBUG("bc1f %08x", btarget); |
1816 | goto not_likely; | 2917 | goto not_likely; |
1817 | - case 0x0002: /* bc1fl */ | 2918 | + case OPC_BC1FL: |
1818 | gen_op_bc1f(); | 2919 | gen_op_bc1f(); |
1819 | MIPS_DEBUG("bc1fl %08x", btarget); | 2920 | MIPS_DEBUG("bc1fl %08x", btarget); |
1820 | goto likely; | 2921 | goto likely; |
1821 | - case 0x0001: /* bc1t */ | 2922 | + case OPC_BC1T: |
1822 | gen_op_bc1t(); | 2923 | gen_op_bc1t(); |
1823 | MIPS_DEBUG("bc1t %08x", btarget); | 2924 | MIPS_DEBUG("bc1t %08x", btarget); |
1824 | not_likely: | 2925 | not_likely: |
1825 | ctx->hflags |= MIPS_HFLAG_BC; | 2926 | ctx->hflags |= MIPS_HFLAG_BC; |
1826 | break; | 2927 | break; |
1827 | - case 0x0003: /* bc1tl */ | 2928 | + case OPC_BC1TL: |
1828 | gen_op_bc1t(); | 2929 | gen_op_bc1t(); |
1829 | MIPS_DEBUG("bc1tl %08x", btarget); | 2930 | MIPS_DEBUG("bc1tl %08x", btarget); |
1830 | likely: | 2931 | likely: |
@@ -1832,7 +2933,7 @@ static void gen_compute_branch1 (DisasContext *ctx, uint16_t cond, | @@ -1832,7 +2933,7 @@ static void gen_compute_branch1 (DisasContext *ctx, uint16_t cond, | ||
1832 | break; | 2933 | break; |
1833 | default: | 2934 | default: |
1834 | MIPS_INVAL("cp1 branch/jump"); | 2935 | MIPS_INVAL("cp1 branch/jump"); |
1835 | - generate_exception(ctx, EXCP_RI); | 2936 | + generate_exception_err (ctx, EXCP_RI, 1); |
1836 | return; | 2937 | return; |
1837 | } | 2938 | } |
1838 | gen_op_set_bcond(); | 2939 | gen_op_set_bcond(); |
@@ -1845,9 +2946,9 @@ static void gen_compute_branch1 (DisasContext *ctx, uint16_t cond, | @@ -1845,9 +2946,9 @@ static void gen_compute_branch1 (DisasContext *ctx, uint16_t cond, | ||
1845 | } | 2946 | } |
1846 | 2947 | ||
1847 | /* Coprocessor 1 (FPU) */ | 2948 | /* Coprocessor 1 (FPU) */ |
1848 | -static void gen_cp1 (DisasContext *ctx, uint16_t opc, int rt, int fs) | 2949 | +static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs) |
1849 | { | 2950 | { |
1850 | - const unsigned char *opn = "unk"; | 2951 | + const char *opn = "unk"; |
1851 | 2952 | ||
1852 | switch (opc) { | 2953 | switch (opc) { |
1853 | case OPC_MFC1: | 2954 | case OPC_MFC1: |
@@ -1865,7 +2966,7 @@ static void gen_cp1 (DisasContext *ctx, uint16_t opc, int rt, int fs) | @@ -1865,7 +2966,7 @@ static void gen_cp1 (DisasContext *ctx, uint16_t opc, int rt, int fs) | ||
1865 | case OPC_CFC1: | 2966 | case OPC_CFC1: |
1866 | if (fs != 0 && fs != 31) { | 2967 | if (fs != 0 && fs != 31) { |
1867 | MIPS_INVAL("cfc1 freg"); | 2968 | MIPS_INVAL("cfc1 freg"); |
1868 | - generate_exception(ctx, EXCP_RI); | 2969 | + generate_exception_err (ctx, EXCP_RI, 1); |
1869 | return; | 2970 | return; |
1870 | } | 2971 | } |
1871 | GEN_LOAD_IMM_TN(T1, fs); | 2972 | GEN_LOAD_IMM_TN(T1, fs); |
@@ -1874,9 +2975,9 @@ static void gen_cp1 (DisasContext *ctx, uint16_t opc, int rt, int fs) | @@ -1874,9 +2975,9 @@ static void gen_cp1 (DisasContext *ctx, uint16_t opc, int rt, int fs) | ||
1874 | opn = "cfc1"; | 2975 | opn = "cfc1"; |
1875 | break; | 2976 | break; |
1876 | case OPC_CTC1: | 2977 | case OPC_CTC1: |
1877 | - if (fs != 0 && fs != 31) { | 2978 | + if (fs != 0 && fs != 31) { |
1878 | MIPS_INVAL("ctc1 freg"); | 2979 | MIPS_INVAL("ctc1 freg"); |
1879 | - generate_exception(ctx, EXCP_RI); | 2980 | + generate_exception_err (ctx, EXCP_RI, 1); |
1880 | return; | 2981 | return; |
1881 | } | 2982 | } |
1882 | GEN_LOAD_IMM_TN(T1, fs); | 2983 | GEN_LOAD_IMM_TN(T1, fs); |
@@ -1890,7 +2991,7 @@ static void gen_cp1 (DisasContext *ctx, uint16_t opc, int rt, int fs) | @@ -1890,7 +2991,7 @@ static void gen_cp1 (DisasContext *ctx, uint16_t opc, int rt, int fs) | ||
1890 | ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F, | 2991 | ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F, |
1891 | ((ctx->opcode >> 16) & 0x1F)); | 2992 | ((ctx->opcode >> 16) & 0x1F)); |
1892 | } | 2993 | } |
1893 | - generate_exception(ctx, EXCP_RI); | 2994 | + generate_exception_err (ctx, EXCP_RI, 1); |
1894 | return; | 2995 | return; |
1895 | } | 2996 | } |
1896 | MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]); | 2997 | MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]); |
@@ -1908,16 +3009,16 @@ static void gen_cp1 (DisasContext *ctx, uint16_t opc, int rt, int fs) | @@ -1908,16 +3009,16 @@ static void gen_cp1 (DisasContext *ctx, uint16_t opc, int rt, int fs) | ||
1908 | */ | 3009 | */ |
1909 | #define CHECK_FR(ctx, freg) do { \ | 3010 | #define CHECK_FR(ctx, freg) do { \ |
1910 | if (!((ctx)->CP0_Status & (1<<CP0St_FR)) && ((freg) & 1)) { \ | 3011 | if (!((ctx)->CP0_Status & (1<<CP0St_FR)) && ((freg) & 1)) { \ |
1911 | - generate_exception(ctx, EXCP_RI); \ | 3012 | + generate_exception_err (ctx, EXCP_RI, 1); \ |
1912 | return; \ | 3013 | return; \ |
1913 | } \ | 3014 | } \ |
1914 | } while(0) | 3015 | } while(0) |
1915 | 3016 | ||
1916 | #define FOP(func, fmt) (((fmt) << 21) | (func)) | 3017 | #define FOP(func, fmt) (((fmt) << 21) | (func)) |
1917 | 3018 | ||
1918 | -static void gen_farith (DisasContext *ctx, int fmt, int ft, int fs, int fd, int func) | 3019 | +static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, int fs, int fd) |
1919 | { | 3020 | { |
1920 | - const unsigned char *opn = "unk"; | 3021 | + const char *opn = "unk"; |
1921 | const char *condnames[] = { | 3022 | const char *condnames[] = { |
1922 | "c.f", | 3023 | "c.f", |
1923 | "c.un", | 3024 | "c.un", |
@@ -1937,7 +3038,8 @@ static void gen_farith (DisasContext *ctx, int fmt, int ft, int fs, int fd, int | @@ -1937,7 +3038,8 @@ static void gen_farith (DisasContext *ctx, int fmt, int ft, int fs, int fd, int | ||
1937 | "c.ngt", | 3038 | "c.ngt", |
1938 | }; | 3039 | }; |
1939 | int binary = 0; | 3040 | int binary = 0; |
1940 | - | 3041 | + uint32_t func = ctx->opcode & 0x3f; |
3042 | + | ||
1941 | switch (ctx->opcode & FOP(0x3f, 0x1f)) { | 3043 | switch (ctx->opcode & FOP(0x3f, 0x1f)) { |
1942 | case FOP(0, 17): | 3044 | case FOP(0, 17): |
1943 | CHECK_FR(ctx, fs | ft | fd); | 3045 | CHECK_FR(ctx, fs | ft | fd); |
@@ -2033,7 +3135,7 @@ static void gen_farith (DisasContext *ctx, int fmt, int ft, int fs, int fd, int | @@ -2033,7 +3135,7 @@ static void gen_farith (DisasContext *ctx, int fmt, int ft, int fs, int fd, int | ||
2033 | GEN_LOAD_FREG_FTN(DT0, fs); | 3135 | GEN_LOAD_FREG_FTN(DT0, fs); |
2034 | gen_op_float_floorw_d(); | 3136 | gen_op_float_floorw_d(); |
2035 | GEN_STORE_FTN_FREG(fd, WT2); | 3137 | GEN_STORE_FTN_FREG(fd, WT2); |
2036 | - opn = "ceil.w.d"; | 3138 | + opn = "floor.w.d"; |
2037 | break; | 3139 | break; |
2038 | case FOP(33, 16): /* cvt.d.s */ | 3140 | case FOP(33, 16): /* cvt.d.s */ |
2039 | CHECK_FR(ctx, fs | fd); | 3141 | CHECK_FR(ctx, fs | fd); |
@@ -2201,11 +3303,11 @@ static void gen_farith (DisasContext *ctx, int fmt, int ft, int fs, int fd, int | @@ -2201,11 +3303,11 @@ static void gen_farith (DisasContext *ctx, int fmt, int ft, int fs, int fd, int | ||
2201 | break; | 3303 | break; |
2202 | default: | 3304 | default: |
2203 | if (loglevel & CPU_LOG_TB_IN_ASM) { | 3305 | if (loglevel & CPU_LOG_TB_IN_ASM) { |
2204 | - fprintf(logfile, "Invalid arith function: %08x %03x %03x %03x\n", | 3306 | + fprintf(logfile, "Invalid FP arith function: %08x %03x %03x %03x\n", |
2205 | ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F, | 3307 | ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F, |
2206 | ((ctx->opcode >> 16) & 0x1F)); | 3308 | ((ctx->opcode >> 16) & 0x1F)); |
2207 | } | 3309 | } |
2208 | - generate_exception(ctx, EXCP_RI); | 3310 | + generate_exception_err (ctx, EXCP_RI, 1); |
2209 | return; | 3311 | return; |
2210 | } | 3312 | } |
2211 | if (binary) | 3313 | if (binary) |
@@ -2213,14 +3315,27 @@ static void gen_farith (DisasContext *ctx, int fmt, int ft, int fs, int fd, int | @@ -2213,14 +3315,27 @@ static void gen_farith (DisasContext *ctx, int fmt, int ft, int fs, int fd, int | ||
2213 | else | 3315 | else |
2214 | MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]); | 3316 | MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]); |
2215 | } | 3317 | } |
2216 | -#endif | ||
2217 | 3318 | ||
2218 | -/* ISA extensions */ | 3319 | +static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf) |
3320 | +{ | ||
3321 | + uint32_t ccbit; | ||
3322 | + | ||
3323 | + if (cc) | ||
3324 | + ccbit = 1 << (24 + cc); | ||
3325 | + else | ||
3326 | + ccbit = 1 << 23; | ||
3327 | + if (!tf) | ||
3328 | + gen_op_movf(ccbit, rd, rs); | ||
3329 | + else | ||
3330 | + gen_op_movt(ccbit, rd, rs); | ||
3331 | +} | ||
3332 | + | ||
3333 | +/* ISA extensions (ASEs) */ | ||
2219 | /* MIPS16 extension to MIPS32 */ | 3334 | /* MIPS16 extension to MIPS32 */ |
2220 | /* SmartMIPS extension to MIPS32 */ | 3335 | /* SmartMIPS extension to MIPS32 */ |
2221 | 3336 | ||
2222 | -#ifdef TARGET_MIPS64 | ||
2223 | -static void gen_arith64 (DisasContext *ctx, uint16_t opc) | 3337 | +#ifdef MIPS_HAS_MIPS64 |
3338 | +static void gen_arith64 (DisasContext *ctx, uint32_t opc) | ||
2224 | { | 3339 | { |
2225 | if (func == 0x02 && rd == 0) { | 3340 | if (func == 0x02 && rd == 0) { |
2226 | /* NOP */ | 3341 | /* NOP */ |
@@ -2265,7 +3380,7 @@ static void decode_opc (DisasContext *ctx) | @@ -2265,7 +3380,7 @@ static void decode_opc (DisasContext *ctx) | ||
2265 | { | 3380 | { |
2266 | int32_t offset; | 3381 | int32_t offset; |
2267 | int rs, rt, rd, sa; | 3382 | int rs, rt, rd, sa; |
2268 | - uint16_t op, op1; | 3383 | + uint32_t op, op1, op2; |
2269 | int16_t imm; | 3384 | int16_t imm; |
2270 | 3385 | ||
2271 | /* make sure instructions are on a word boundary */ | 3386 | /* make sure instructions are on a word boundary */ |
@@ -2279,76 +3394,86 @@ static void decode_opc (DisasContext *ctx) | @@ -2279,76 +3394,86 @@ static void decode_opc (DisasContext *ctx) | ||
2279 | MIPS_DEBUG("blikely condition (%08x)", ctx->pc + 4); | 3394 | MIPS_DEBUG("blikely condition (%08x)", ctx->pc + 4); |
2280 | gen_blikely(ctx); | 3395 | gen_blikely(ctx); |
2281 | } | 3396 | } |
2282 | - op = ctx->opcode >> 26; | ||
2283 | - rs = ((ctx->opcode >> 21) & 0x1F); | ||
2284 | - rt = ((ctx->opcode >> 16) & 0x1F); | ||
2285 | - rd = ((ctx->opcode >> 11) & 0x1F); | ||
2286 | - sa = ((ctx->opcode >> 6) & 0x1F); | 3397 | + op = MASK_OP_MAJOR(ctx->opcode); |
3398 | + rs = (ctx->opcode >> 21) & 0x1f; | ||
3399 | + rt = (ctx->opcode >> 16) & 0x1f; | ||
3400 | + rd = (ctx->opcode >> 11) & 0x1f; | ||
3401 | + sa = (ctx->opcode >> 6) & 0x1f; | ||
2287 | imm = (int16_t)ctx->opcode; | 3402 | imm = (int16_t)ctx->opcode; |
2288 | switch (op) { | 3403 | switch (op) { |
2289 | - case 0x00: /* Special opcode */ | ||
2290 | - op1 = ctx->opcode & 0x3F; | 3404 | + case OPC_SPECIAL: |
3405 | + op1 = MASK_SPECIAL(ctx->opcode); | ||
2291 | switch (op1) { | 3406 | switch (op1) { |
2292 | - case 0x00: /* Arithmetic with immediate */ | ||
2293 | - case 0x02 ... 0x03: | ||
2294 | - gen_arith_imm(ctx, op1 | EXT_SPECIAL, rd, rt, sa); | ||
2295 | - break; | ||
2296 | - case 0x04: /* Arithmetic */ | ||
2297 | - case 0x06 ... 0x07: | ||
2298 | - case 0x0A ... 0x0B: | ||
2299 | - case 0x20 ... 0x27: | ||
2300 | - case 0x2A ... 0x2B: | ||
2301 | - gen_arith(ctx, op1 | EXT_SPECIAL, rd, rs, rt); | ||
2302 | - break; | ||
2303 | - case 0x18 ... 0x1B: /* MULT / DIV */ | ||
2304 | - gen_muldiv(ctx, op1 | EXT_SPECIAL, rs, rt); | ||
2305 | - break; | ||
2306 | - case 0x08 ... 0x09: /* Jumps */ | ||
2307 | - gen_compute_branch(ctx, op1 | EXT_SPECIAL, rs, rd, sa); | 3407 | + case OPC_SLL: /* Arithmetic with immediate */ |
3408 | + case OPC_SRL ... OPC_SRA: | ||
3409 | + gen_arith_imm(ctx, op1, rd, rt, sa); | ||
3410 | + break; | ||
3411 | + case OPC_SLLV: /* Arithmetic */ | ||
3412 | + case OPC_SRLV ... OPC_SRAV: | ||
3413 | + case OPC_MOVZ ... OPC_MOVN: | ||
3414 | + case OPC_ADD ... OPC_NOR: | ||
3415 | + case OPC_SLT ... OPC_SLTU: | ||
3416 | + gen_arith(ctx, op1, rd, rs, rt); | ||
3417 | + break; | ||
3418 | + case OPC_MULT ... OPC_DIVU: | ||
3419 | + gen_muldiv(ctx, op1, rs, rt); | ||
3420 | + break; | ||
3421 | + case OPC_JR ... OPC_JALR: | ||
3422 | + gen_compute_branch(ctx, op1, rs, rd, sa); | ||
2308 | return; | 3423 | return; |
2309 | - case 0x30 ... 0x34: /* Traps */ | ||
2310 | - case 0x36: | ||
2311 | - gen_trap(ctx, op1 | EXT_SPECIAL, rs, rt, -1); | 3424 | + case OPC_TGE ... OPC_TEQ: /* Traps */ |
3425 | + case OPC_TNE: | ||
3426 | + gen_trap(ctx, op1, rs, rt, -1); | ||
2312 | break; | 3427 | break; |
2313 | - case 0x10: /* Move from HI/LO */ | ||
2314 | - case 0x12: | ||
2315 | - gen_HILO(ctx, op1 | EXT_SPECIAL, rd); | 3428 | + case OPC_MFHI: /* Move from HI/LO */ |
3429 | + case OPC_MFLO: | ||
3430 | + gen_HILO(ctx, op1, rd); | ||
2316 | break; | 3431 | break; |
2317 | - case 0x11: | ||
2318 | - case 0x13: /* Move to HI/LO */ | ||
2319 | - gen_HILO(ctx, op1 | EXT_SPECIAL, rs); | 3432 | + case OPC_MTHI: |
3433 | + case OPC_MTLO: /* Move to HI/LO */ | ||
3434 | + gen_HILO(ctx, op1, rs); | ||
2320 | break; | 3435 | break; |
2321 | - case 0x0C: /* SYSCALL */ | 3436 | + case OPC_PMON: /* Pmon entry point */ |
3437 | + gen_op_pmon(sa); | ||
3438 | + break; | ||
3439 | + case OPC_SYSCALL: | ||
2322 | generate_exception(ctx, EXCP_SYSCALL); | 3440 | generate_exception(ctx, EXCP_SYSCALL); |
3441 | + ctx->bstate = BS_EXCP; | ||
2323 | break; | 3442 | break; |
2324 | - case 0x0D: /* BREAK */ | 3443 | + case OPC_BREAK: |
2325 | generate_exception(ctx, EXCP_BREAK); | 3444 | generate_exception(ctx, EXCP_BREAK); |
2326 | break; | 3445 | break; |
2327 | - case 0x0F: /* SYNC */ | ||
2328 | - /* Treat as a noop */ | 3446 | + case OPC_SPIM: /* SPIM ? */ |
3447 | + /* Implemented as RI exception for now. */ | ||
3448 | + MIPS_INVAL("spim (unofficial)"); | ||
3449 | + generate_exception(ctx, EXCP_RI); | ||
2329 | break; | 3450 | break; |
2330 | - case 0x05: /* Pmon entry point */ | ||
2331 | - gen_op_pmon((ctx->opcode >> 6) & 0x1F); | 3451 | + case OPC_SYNC: |
3452 | + /* Treat as a noop. */ | ||
2332 | break; | 3453 | break; |
2333 | 3454 | ||
2334 | - case 0x01: /* MOVCI */ | ||
2335 | -#if defined (MIPS_HAS_MOVCI) | ||
2336 | - /* XXX */ | ||
2337 | -#else | ||
2338 | - /* Not implemented */ | ||
2339 | - generate_exception_err (ctx, EXCP_CpU, 1); | ||
2340 | -#endif | 3455 | + case OPC_MOVCI: |
3456 | + gen_op_cp1_enabled(); | ||
3457 | + gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7, | ||
3458 | + (ctx->opcode >> 16) & 1); | ||
2341 | break; | 3459 | break; |
2342 | 3460 | ||
2343 | -#if defined (TARGET_MIPS64) | ||
2344 | - case 0x14: /* MIPS64 specific opcodes */ | ||
2345 | - case 0x16: | ||
2346 | - case 0x17: | ||
2347 | - case 0x1C ... 0x1F: | ||
2348 | - case 0x2C ... 0x2F: | ||
2349 | - case 0x37: | ||
2350 | - case 0x39 ... 0x3B: | ||
2351 | - case 0x3E ... 0x3F: | 3461 | +#ifdef MIPS_HAS_MIPS64 |
3462 | + /* MIPS64 specific opcodes */ | ||
3463 | + case OPC_DSLL: | ||
3464 | + case OPC_DSRL ... OPC_DSRA: | ||
3465 | + case OPC_DSLL32: | ||
3466 | + case OPC_DSRL32 ... OPC_DSRA32: | ||
3467 | + gen_arith_imm(ctx, op1, rd, rt, sa); | ||
3468 | + break; | ||
3469 | + case OPC_DSLLV: | ||
3470 | + case OPC_DSRLV ... OPC_DSRAV: | ||
3471 | + case OPC_DADD ... OPC_DSUBU: | ||
3472 | + gen_arith(ctx, op1, rd, rs, rt); | ||
3473 | + break; | ||
3474 | + case OPC_DMULT ... OPC_DDIVU: | ||
3475 | + gen_muldiv(ctx, op1, rs, rt); | ||
3476 | + break; | ||
2352 | #endif | 3477 | #endif |
2353 | default: /* Invalid */ | 3478 | default: /* Invalid */ |
2354 | MIPS_INVAL("special"); | 3479 | MIPS_INVAL("special"); |
@@ -2356,23 +3481,20 @@ static void decode_opc (DisasContext *ctx) | @@ -2356,23 +3481,20 @@ static void decode_opc (DisasContext *ctx) | ||
2356 | break; | 3481 | break; |
2357 | } | 3482 | } |
2358 | break; | 3483 | break; |
2359 | - case 0x1C: /* Special2 opcode */ | ||
2360 | - op1 = ctx->opcode & 0x3F; | 3484 | + case OPC_SPECIAL2: |
3485 | + op1 = MASK_SPECIAL2(ctx->opcode); | ||
2361 | switch (op1) { | 3486 | switch (op1) { |
2362 | -#if defined (MIPS_USES_R4K_EXT) | ||
2363 | - /* Those instructions are not part of MIPS32 core */ | ||
2364 | - case 0x00 ... 0x01: /* Multiply and add/sub */ | ||
2365 | - case 0x04 ... 0x05: | ||
2366 | - gen_muldiv(ctx, op1 | EXT_SPECIAL2, rs, rt); | 3487 | + case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */ |
3488 | + case OPC_MSUB ... OPC_MSUBU: | ||
3489 | + gen_muldiv(ctx, op1, rs, rt); | ||
2367 | break; | 3490 | break; |
2368 | - case 0x02: /* MUL */ | ||
2369 | - gen_arith(ctx, op1 | EXT_SPECIAL2, rd, rs, rt); | 3491 | + case OPC_MUL: |
3492 | + gen_arith(ctx, op1, rd, rs, rt); | ||
2370 | break; | 3493 | break; |
2371 | - case 0x20 ... 0x21: /* CLO / CLZ */ | ||
2372 | - gen_cl(ctx, op1 | EXT_SPECIAL2, rd, rs); | 3494 | + case OPC_CLZ ... OPC_CLO: |
3495 | + gen_cl(ctx, op1, rd, rs); | ||
2373 | break; | 3496 | break; |
2374 | -#endif | ||
2375 | - case 0x3F: /* SDBBP */ | 3497 | + case OPC_SDBBP: |
2376 | /* XXX: not clear which exception should be raised | 3498 | /* XXX: not clear which exception should be raised |
2377 | * when in debug mode... | 3499 | * when in debug mode... |
2378 | */ | 3500 | */ |
@@ -2383,22 +3505,109 @@ static void decode_opc (DisasContext *ctx) | @@ -2383,22 +3505,109 @@ static void decode_opc (DisasContext *ctx) | ||
2383 | } | 3505 | } |
2384 | /* Treat as a noop */ | 3506 | /* Treat as a noop */ |
2385 | break; | 3507 | break; |
3508 | +#ifdef MIPS_HAS_MIPS64 | ||
3509 | + case OPC_DCLZ ... OPC_DCLO: | ||
3510 | + gen_cl(ctx, op1, rd, rs); | ||
3511 | + break; | ||
3512 | +#endif | ||
2386 | default: /* Invalid */ | 3513 | default: /* Invalid */ |
2387 | MIPS_INVAL("special2"); | 3514 | MIPS_INVAL("special2"); |
2388 | generate_exception(ctx, EXCP_RI); | 3515 | generate_exception(ctx, EXCP_RI); |
2389 | break; | 3516 | break; |
2390 | } | 3517 | } |
2391 | break; | 3518 | break; |
2392 | - case 0x01: /* B REGIMM opcode */ | ||
2393 | - op1 = ((ctx->opcode >> 16) & 0x1F); | 3519 | + case OPC_SPECIAL3: |
3520 | + op1 = MASK_SPECIAL3(ctx->opcode); | ||
2394 | switch (op1) { | 3521 | switch (op1) { |
2395 | - case 0x00 ... 0x03: /* REGIMM branches */ | ||
2396 | - case 0x10 ... 0x13: | ||
2397 | - gen_compute_branch(ctx, op1 | EXT_REGIMM, rs, -1, imm << 2); | 3522 | + case OPC_EXT: |
3523 | + case OPC_INS: | ||
3524 | + gen_bitops(ctx, op1, rt, rs, sa, rd); | ||
3525 | + break; | ||
3526 | + case OPC_BSHFL: | ||
3527 | + op2 = MASK_BSHFL(ctx->opcode); | ||
3528 | + switch (op2) { | ||
3529 | + case OPC_WSBH: | ||
3530 | + GEN_LOAD_REG_TN(T1, rt); | ||
3531 | + gen_op_wsbh(); | ||
3532 | + break; | ||
3533 | + case OPC_SEB: | ||
3534 | + GEN_LOAD_REG_TN(T1, rt); | ||
3535 | + gen_op_seb(); | ||
3536 | + break; | ||
3537 | + case OPC_SEH: | ||
3538 | + GEN_LOAD_REG_TN(T1, rt); | ||
3539 | + gen_op_seh(); | ||
3540 | + break; | ||
3541 | + default: /* Invalid */ | ||
3542 | + MIPS_INVAL("bshfl"); | ||
3543 | + generate_exception(ctx, EXCP_RI); | ||
3544 | + break; | ||
3545 | + } | ||
3546 | + GEN_STORE_TN_REG(rd, T0); | ||
3547 | + break; | ||
3548 | + case OPC_RDHWR: | ||
3549 | + switch (rd) { | ||
3550 | + case 0: | ||
3551 | + gen_op_rdhwr_cpunum(); | ||
3552 | + break; | ||
3553 | + case 1: | ||
3554 | + gen_op_rdhwr_synci_step(); | ||
3555 | + break; | ||
3556 | + case 2: | ||
3557 | + gen_op_rdhwr_cc(); | ||
3558 | + break; | ||
3559 | + case 3: | ||
3560 | + gen_op_rdhwr_ccres(); | ||
3561 | + break; | ||
3562 | + default: /* Invalid */ | ||
3563 | + MIPS_INVAL("rdhwr"); | ||
3564 | + generate_exception(ctx, EXCP_RI); | ||
3565 | + break; | ||
3566 | + } | ||
3567 | + GEN_STORE_TN_REG(rt, T0); | ||
3568 | + break; | ||
3569 | +#ifdef MIPS_HAS_MIPS64 | ||
3570 | + case OPC_DEXTM ... OPC_DEXT: | ||
3571 | + case OPC_DINSM ... OPC_DINS: | ||
3572 | + gen_bitops(ctx, op1, rt, rs, sa, rd); | ||
3573 | + break; | ||
3574 | + case OPC_DBSHFL: | ||
3575 | + op2 = MASK_DBSHFL(ctx->opcode); | ||
3576 | + switch (op2) { | ||
3577 | + case OPC_DSBH: | ||
3578 | + GEN_LOAD_REG_TN(T1, rt); | ||
3579 | + gen_op_dsbh(); | ||
3580 | + break; | ||
3581 | + case OPC_DSHD: | ||
3582 | + GEN_LOAD_REG_TN(T1, rt); | ||
3583 | + gen_op_dshd(); | ||
3584 | + break; | ||
3585 | + default: /* Invalid */ | ||
3586 | + MIPS_INVAL("dbshfl"); | ||
3587 | + generate_exception(ctx, EXCP_RI); | ||
3588 | + break; | ||
3589 | + } | ||
3590 | + GEN_STORE_TN_REG(rd, T0); | ||
3591 | +#endif | ||
3592 | + default: /* Invalid */ | ||
3593 | + MIPS_INVAL("special3"); | ||
3594 | + generate_exception(ctx, EXCP_RI); | ||
3595 | + break; | ||
3596 | + } | ||
3597 | + break; | ||
3598 | + case OPC_REGIMM: | ||
3599 | + op1 = MASK_REGIMM(ctx->opcode); | ||
3600 | + switch (op1) { | ||
3601 | + case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */ | ||
3602 | + case OPC_BLTZAL ... OPC_BGEZALL: | ||
3603 | + gen_compute_branch(ctx, op1, rs, -1, imm << 2); | ||
2398 | return; | 3604 | return; |
2399 | - case 0x08 ... 0x0C: /* Traps */ | ||
2400 | - case 0x0E: | ||
2401 | - gen_trap(ctx, op1 | EXT_REGIMM, rs, -1, imm); | 3605 | + case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */ |
3606 | + case OPC_TNEI: | ||
3607 | + gen_trap(ctx, op1, rs, -1, imm); | ||
3608 | + break; | ||
3609 | + case OPC_SYNCI: | ||
3610 | + /* treat as noop */ | ||
2402 | break; | 3611 | break; |
2403 | default: /* Invalid */ | 3612 | default: /* Invalid */ |
2404 | MIPS_INVAL("REGIMM"); | 3613 | MIPS_INVAL("REGIMM"); |
@@ -2406,48 +3615,78 @@ static void decode_opc (DisasContext *ctx) | @@ -2406,48 +3615,78 @@ static void decode_opc (DisasContext *ctx) | ||
2406 | break; | 3615 | break; |
2407 | } | 3616 | } |
2408 | break; | 3617 | break; |
2409 | - case 0x10: /* CP0 opcode */ | ||
2410 | - op1 = ((ctx->opcode >> 21) & 0x1F); | 3618 | + case OPC_CP0: |
3619 | + op1 = MASK_CP0(ctx->opcode); | ||
2411 | switch (op1) { | 3620 | switch (op1) { |
2412 | - case 0x00: | ||
2413 | - case 0x04: | ||
2414 | - gen_cp0(ctx, op1 | EXT_CP0, rt, rd); | 3621 | + case OPC_MFC0: |
3622 | + case OPC_MTC0: | ||
3623 | +#ifdef MIPS_HAS_MIPS64 | ||
3624 | + case OPC_DMFC0: | ||
3625 | + case OPC_DMTC0: | ||
3626 | +#endif | ||
3627 | + gen_cp0(ctx, op1, rt, rd); | ||
3628 | + break; | ||
3629 | + case OPC_C0_FIRST ... OPC_C0_LAST: | ||
3630 | + gen_cp0(ctx, MASK_C0(ctx->opcode), rt, rd); | ||
3631 | + break; | ||
3632 | + case OPC_MFMC0: | ||
3633 | + op2 = MASK_MFMC0(ctx->opcode); | ||
3634 | + switch (op2) { | ||
3635 | + case OPC_DI: | ||
3636 | + gen_op_di(); | ||
3637 | + /* Stop translation as we may have switched the execution mode */ | ||
3638 | + ctx->bstate = BS_STOP; | ||
3639 | + break; | ||
3640 | + case OPC_EI: | ||
3641 | + gen_op_ei(); | ||
3642 | + /* Stop translation as we may have switched the execution mode */ | ||
3643 | + ctx->bstate = BS_STOP; | ||
3644 | + break; | ||
3645 | + default: /* Invalid */ | ||
3646 | + MIPS_INVAL("MFMC0"); | ||
3647 | + generate_exception(ctx, EXCP_RI); | ||
3648 | + break; | ||
3649 | + } | ||
3650 | + GEN_STORE_TN_REG(rt, T0); | ||
2415 | break; | 3651 | break; |
3652 | + /* Shadow registers (not implemented). */ | ||
3653 | + case OPC_RDPGPR: | ||
3654 | + case OPC_WRPGPR: | ||
2416 | default: | 3655 | default: |
2417 | - gen_cp0(ctx, (ctx->opcode & 0x3F) | EXT_CP0, rt, rd); | 3656 | + generate_exception(ctx, EXCP_RI); |
2418 | break; | 3657 | break; |
2419 | } | 3658 | } |
2420 | break; | 3659 | break; |
2421 | - case 0x08 ... 0x0F: /* Arithmetic with immediate opcode */ | ||
2422 | - gen_arith_imm(ctx, op, rt, rs, imm); | ||
2423 | - break; | ||
2424 | - case 0x02 ... 0x03: /* Jump */ | ||
2425 | - offset = (int32_t)(ctx->opcode & 0x03FFFFFF) << 2; | ||
2426 | - gen_compute_branch(ctx, op, rs, rt, offset); | ||
2427 | - return; | ||
2428 | - case 0x04 ... 0x07: /* Branch */ | ||
2429 | - case 0x14 ... 0x17: | ||
2430 | - gen_compute_branch(ctx, op, rs, rt, imm << 2); | ||
2431 | - return; | ||
2432 | - case 0x20 ... 0x2E: /* Load and stores */ | ||
2433 | - case 0x30: | ||
2434 | - case 0x38: | ||
2435 | - gen_ldst(ctx, op, rt, rs, imm); | ||
2436 | - break; | ||
2437 | - case 0x2F: /* Cache operation */ | ||
2438 | - /* Treat as a noop */ | ||
2439 | - break; | ||
2440 | - case 0x33: /* Prefetch */ | 3660 | + case OPC_ADDI ... OPC_LUI: /* Arithmetic with immediate opcode */ |
3661 | + gen_arith_imm(ctx, op, rt, rs, imm); | ||
3662 | + break; | ||
3663 | + case OPC_J ... OPC_JAL: /* Jump */ | ||
3664 | + offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2; | ||
3665 | + gen_compute_branch(ctx, op, rs, rt, offset); | ||
3666 | + return; | ||
3667 | + case OPC_BEQ ... OPC_BGTZ: /* Branch */ | ||
3668 | + case OPC_BEQL ... OPC_BGTZL: | ||
3669 | + gen_compute_branch(ctx, op, rs, rt, imm << 2); | ||
3670 | + return; | ||
3671 | + case OPC_LB ... OPC_LWR: /* Load and stores */ | ||
3672 | + case OPC_SB ... OPC_SW: | ||
3673 | + case OPC_SWR: | ||
3674 | + case OPC_LL: | ||
3675 | + case OPC_SC: | ||
3676 | + gen_ldst(ctx, op, rt, rs, imm); | ||
3677 | + break; | ||
3678 | + case OPC_CACHE: | ||
3679 | + /* Treat as a noop */ | ||
3680 | + break; | ||
3681 | + case OPC_PREF: | ||
2441 | /* Treat as a noop */ | 3682 | /* Treat as a noop */ |
2442 | break; | 3683 | break; |
2443 | - case 0x3F: /* HACK */ | ||
2444 | - break; | ||
2445 | 3684 | ||
2446 | /* Floating point. */ | 3685 | /* Floating point. */ |
2447 | - case 0x31: /* LWC1 */ | ||
2448 | - case 0x35: /* LDC1 */ | ||
2449 | - case 0x39: /* SWC1 */ | ||
2450 | - case 0x3D: /* SDC1 */ | 3686 | + case OPC_LWC1: |
3687 | + case OPC_LDC1: | ||
3688 | + case OPC_SWC1: | ||
3689 | + case OPC_SDC1: | ||
2451 | #if defined(MIPS_USES_FPU) | 3690 | #if defined(MIPS_USES_FPU) |
2452 | save_cpu_state(ctx, 1); | 3691 | save_cpu_state(ctx, 1); |
2453 | gen_op_cp1_enabled(); | 3692 | gen_op_cp1_enabled(); |
@@ -2457,65 +3696,80 @@ static void decode_opc (DisasContext *ctx) | @@ -2457,65 +3696,80 @@ static void decode_opc (DisasContext *ctx) | ||
2457 | #endif | 3696 | #endif |
2458 | break; | 3697 | break; |
2459 | 3698 | ||
2460 | - case 0x11: /* CP1 opcode */ | 3699 | + case OPC_CP1: |
2461 | #if defined(MIPS_USES_FPU) | 3700 | #if defined(MIPS_USES_FPU) |
2462 | save_cpu_state(ctx, 1); | 3701 | save_cpu_state(ctx, 1); |
2463 | gen_op_cp1_enabled(); | 3702 | gen_op_cp1_enabled(); |
2464 | - op1 = ((ctx->opcode >> 21) & 0x1F); | 3703 | + op1 = MASK_CP1(ctx->opcode); |
2465 | switch (op1) { | 3704 | switch (op1) { |
2466 | - case 0x00: /* mfc1 */ | ||
2467 | - case 0x02: /* cfc1 */ | ||
2468 | - case 0x04: /* mtc1 */ | ||
2469 | - case 0x06: /* ctc1 */ | ||
2470 | - gen_cp1(ctx, op1 | EXT_CP1, rt, rd); | ||
2471 | - break; | ||
2472 | - case 0x08: /* bc */ | ||
2473 | - gen_compute_branch1(ctx, rt, imm << 2); | 3705 | + case OPC_MFC1: |
3706 | + case OPC_CFC1: | ||
3707 | + case OPC_MTC1: | ||
3708 | + case OPC_CTC1: | ||
3709 | + gen_cp1(ctx, op1, rt, rd); | ||
3710 | + break; | ||
3711 | + case OPC_BC1: | ||
3712 | + gen_compute_branch1(ctx, MASK_CP1_BCOND(ctx->opcode), imm << 2); | ||
2474 | return; | 3713 | return; |
2475 | - case 0x10: /* 16: fmt=single fp */ | ||
2476 | - case 0x11: /* 17: fmt=double fp */ | ||
2477 | - case 0x14: /* 20: fmt=32bit fixed */ | ||
2478 | - case 0x15: /* 21: fmt=64bit fixed */ | ||
2479 | - gen_farith(ctx, op1, rt, rd, sa, ctx->opcode & 0x3f); | 3714 | + case OPC_S_FMT: |
3715 | + case OPC_D_FMT: | ||
3716 | + case OPC_W_FMT: | ||
3717 | + case OPC_L_FMT: | ||
3718 | + gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa); | ||
2480 | break; | 3719 | break; |
2481 | default: | 3720 | default: |
2482 | generate_exception_err(ctx, EXCP_RI, 1); | 3721 | generate_exception_err(ctx, EXCP_RI, 1); |
2483 | break; | 3722 | break; |
2484 | } | 3723 | } |
2485 | - break; | ||
2486 | #else | 3724 | #else |
2487 | generate_exception_err(ctx, EXCP_CpU, 1); | 3725 | generate_exception_err(ctx, EXCP_CpU, 1); |
2488 | #endif | 3726 | #endif |
2489 | break; | 3727 | break; |
2490 | 3728 | ||
2491 | /* COP2. */ | 3729 | /* COP2. */ |
2492 | - case 0x32: /* LWC2 */ | ||
2493 | - case 0x36: /* LDC2 */ | ||
2494 | - case 0x3A: /* SWC2 */ | ||
2495 | - case 0x3E: /* SDC2 */ | ||
2496 | - case 0x12: /* CP2 opcode */ | ||
2497 | - /* Not implemented */ | 3730 | + case OPC_LWC2: |
3731 | + case OPC_LDC2: | ||
3732 | + case OPC_SWC2: | ||
3733 | + case OPC_SDC2: | ||
3734 | + case OPC_CP2: | ||
3735 | + /* COP2: Not implemented. */ | ||
2498 | generate_exception_err(ctx, EXCP_CpU, 2); | 3736 | generate_exception_err(ctx, EXCP_CpU, 2); |
2499 | break; | 3737 | break; |
2500 | 3738 | ||
2501 | - case 0x13: /* CP3 opcode */ | 3739 | + case OPC_CP3: |
3740 | + gen_op_cp1_enabled(); | ||
3741 | + op1 = MASK_CP3(ctx->opcode); | ||
3742 | + switch (op1) { | ||
2502 | /* Not implemented */ | 3743 | /* Not implemented */ |
2503 | - generate_exception_err(ctx, EXCP_CpU, 3); | 3744 | + default: |
3745 | + generate_exception_err(ctx, EXCP_RI, 1); | ||
3746 | + break; | ||
3747 | + } | ||
2504 | break; | 3748 | break; |
2505 | 3749 | ||
2506 | -#if defined (TARGET_MIPS64) | ||
2507 | - case 0x18 ... 0x1B: | ||
2508 | - case 0x27: | ||
2509 | - case 0x34: | ||
2510 | - case 0x37: | ||
2511 | - /* MIPS64 opcodes */ | 3750 | +#ifdef MIPS_HAS_MIPS64 |
3751 | + /* MIPS64 opcodes */ | ||
3752 | + case OPC_LWU: | ||
3753 | + case OPC_LDL ... OPC_LDR: | ||
3754 | + case OPC_SDL ... OPC_SDR: | ||
3755 | + case OPC_LLD: | ||
3756 | + case OPC_LD: | ||
3757 | + case OPC_SCD: | ||
3758 | + case OPC_SD: | ||
3759 | + gen_ldst(ctx, op, rt, rs, imm); | ||
3760 | + break; | ||
3761 | + case OPC_DADDI ... OPC_DADDIU: | ||
3762 | + gen_arith_imm(ctx, op, rt, rs, imm); | ||
3763 | + break; | ||
2512 | #endif | 3764 | #endif |
2513 | -#if defined (MIPS_HAS_JALX) | ||
2514 | - case 0x1D: | ||
2515 | - /* JALX: not implemented */ | 3765 | +#ifdef MIPS_HAS_MIPS16 |
3766 | + case OPC_JALX: | ||
3767 | + /* MIPS16: Not implemented. */ | ||
3768 | +#endif | ||
3769 | +#ifdef MIPS_HAS_MDMX | ||
3770 | + case OPC_MDMX: | ||
3771 | + /* MDMX: Not implemented. */ | ||
2516 | #endif | 3772 | #endif |
2517 | - case 0x1E: | ||
2518 | - /* ASE specific */ | ||
2519 | default: /* Invalid */ | 3773 | default: /* Invalid */ |
2520 | MIPS_INVAL(""); | 3774 | MIPS_INVAL(""); |
2521 | generate_exception(ctx, EXCP_RI); | 3775 | generate_exception(ctx, EXCP_RI); |
@@ -2707,7 +3961,6 @@ int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb) | @@ -2707,7 +3961,6 @@ int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb) | ||
2707 | return gen_intermediate_code_internal(env, tb, 1); | 3961 | return gen_intermediate_code_internal(env, tb, 1); |
2708 | } | 3962 | } |
2709 | 3963 | ||
2710 | -#ifdef MIPS_USES_FPU | ||
2711 | void fpu_dump_state(CPUState *env, FILE *f, | 3964 | void fpu_dump_state(CPUState *env, FILE *f, |
2712 | int (*fpu_fprintf)(FILE *f, const char *fmt, ...), | 3965 | int (*fpu_fprintf)(FILE *f, const char *fmt, ...), |
2713 | int flags) | 3966 | int flags) |
@@ -2721,19 +3974,19 @@ void fpu_dump_state(CPUState *env, FILE *f, | @@ -2721,19 +3974,19 @@ void fpu_dump_state(CPUState *env, FILE *f, | ||
2721 | 3974 | ||
2722 | fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d\n", | 3975 | fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d\n", |
2723 | env->fcr0, env->fcr31, | 3976 | env->fcr0, env->fcr31, |
2724 | - (env->CP0_Status & (1<<CP0St_FR)) != 0); | 3977 | + (env->CP0_Status & (1 << CP0St_FR)) != 0); |
2725 | fpu_fprintf(f, "FT0: "); printfpr(&env->ft0); | 3978 | fpu_fprintf(f, "FT0: "); printfpr(&env->ft0); |
2726 | fpu_fprintf(f, "FT1: "); printfpr(&env->ft1); | 3979 | fpu_fprintf(f, "FT1: "); printfpr(&env->ft1); |
2727 | fpu_fprintf(f, "FT2: "); printfpr(&env->ft2); | 3980 | fpu_fprintf(f, "FT2: "); printfpr(&env->ft2); |
2728 | - for(i=0; i < 32; i+=2) { | ||
2729 | - fpu_fprintf(f, "f%02d: ", i); | 3981 | + for(i = 0; i < 32; i += 2) { |
3982 | + fpu_fprintf(f, "%s: ", fregnames[i]); | ||
2730 | printfpr(FPR(env, i)); | 3983 | printfpr(FPR(env, i)); |
2731 | } | 3984 | } |
2732 | 3985 | ||
2733 | #undef printfpr | 3986 | #undef printfpr |
2734 | } | 3987 | } |
2735 | 3988 | ||
2736 | -void dump_fpu(CPUState *env) | 3989 | +void dump_fpu (CPUState *env) |
2737 | { | 3990 | { |
2738 | if (loglevel) { | 3991 | if (loglevel) { |
2739 | fprintf(logfile, "pc=0x%08x HI=0x%08x LO=0x%08x ds %04x %08x %d\n", | 3992 | fprintf(logfile, "pc=0x%08x HI=0x%08x LO=0x%08x ds %04x %08x %d\n", |
@@ -2741,7 +3994,6 @@ void dump_fpu(CPUState *env) | @@ -2741,7 +3994,6 @@ void dump_fpu(CPUState *env) | ||
2741 | fpu_dump_state(env, logfile, fprintf, 0); | 3994 | fpu_dump_state(env, logfile, fprintf, 0); |
2742 | } | 3995 | } |
2743 | } | 3996 | } |
2744 | -#endif /* MIPS_USES_FPU */ | ||
2745 | 3997 | ||
2746 | void cpu_dump_state (CPUState *env, FILE *f, | 3998 | void cpu_dump_state (CPUState *env, FILE *f, |
2747 | int (*cpu_fprintf)(FILE *f, const char *fmt, ...), | 3999 | int (*cpu_fprintf)(FILE *f, const char *fmt, ...), |
@@ -2772,9 +4024,8 @@ void cpu_dump_state (CPUState *env, FILE *f, | @@ -2772,9 +4024,8 @@ void cpu_dump_state (CPUState *env, FILE *f, | ||
2772 | c0_status, env->CP0_Cause, env->CP0_EPC); | 4024 | c0_status, env->CP0_Cause, env->CP0_EPC); |
2773 | cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%08x\n", | 4025 | cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%08x\n", |
2774 | env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr); | 4026 | env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr); |
2775 | -#ifdef MIPS_USES_FPU | ||
2776 | - fpu_dump_state(env, f, cpu_fprintf, flags); | ||
2777 | -#endif | 4027 | + if (c0_status & (1 << CP0St_CU1)) |
4028 | + fpu_dump_state(env, f, cpu_fprintf, flags); | ||
2778 | } | 4029 | } |
2779 | 4030 | ||
2780 | CPUMIPSState *cpu_mips_init (void) | 4031 | CPUMIPSState *cpu_mips_init (void) |
@@ -2802,16 +4053,12 @@ void cpu_reset (CPUMIPSState *env) | @@ -2802,16 +4053,12 @@ void cpu_reset (CPUMIPSState *env) | ||
2802 | env->tlb_in_use = MIPS_TLB_NB; | 4053 | env->tlb_in_use = MIPS_TLB_NB; |
2803 | #endif | 4054 | #endif |
2804 | env->CP0_Wired = 0; | 4055 | env->CP0_Wired = 0; |
4056 | + /* SMP not implemented */ | ||
4057 | + env->CP0_EBase = 0x80000000; | ||
2805 | env->CP0_Config0 = MIPS_CONFIG0; | 4058 | env->CP0_Config0 = MIPS_CONFIG0; |
2806 | -#if defined (MIPS_CONFIG1) | ||
2807 | - env->CP0_Config1 = MIPS_CONFIG1; | ||
2808 | -#endif | ||
2809 | -#if defined (MIPS_CONFIG2) | ||
2810 | - env->CP0_Config2 = MIPS_CONFIG2; | ||
2811 | -#endif | ||
2812 | -#if defined (MIPS_CONFIG3) | ||
2813 | - env->CP0_Config3 = MIPS_CONFIG3; | ||
2814 | -#endif | 4059 | + env->CP0_Config1 = MIPS_CONFIG1; |
4060 | + env->CP0_Config2 = MIPS_CONFIG2; | ||
4061 | + env->CP0_Config3 = MIPS_CONFIG3; | ||
2815 | env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV); | 4062 | env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV); |
2816 | env->CP0_WatchLo = 0; | 4063 | env->CP0_WatchLo = 0; |
2817 | env->hflags = MIPS_HFLAG_ERL; | 4064 | env->hflags = MIPS_HFLAG_ERL; |
@@ -2825,4 +4072,7 @@ void cpu_reset (CPUMIPSState *env) | @@ -2825,4 +4072,7 @@ void cpu_reset (CPUMIPSState *env) | ||
2825 | #ifdef MIPS_USES_FPU | 4072 | #ifdef MIPS_USES_FPU |
2826 | env->fcr0 = MIPS_FCR0; | 4073 | env->fcr0 = MIPS_FCR0; |
2827 | #endif | 4074 | #endif |
4075 | + /* XXX some guesswork here, values are CPU specific */ | ||
4076 | + env->SYNCI_Step = 16; | ||
4077 | + env->CCRes = 2; | ||
2828 | } | 4078 | } |