Revision 8c0fdd85
b/target-mips/exec.h | ||
---|---|---|
68 | 68 |
#endif |
69 | 69 |
void do_mfc0_random(void); |
70 | 70 |
void do_mfc0_count(void); |
71 |
void do_mtc0(int reg, int sel); |
|
71 |
void do_mtc0_status_debug(uint32_t old, uint32_t val); |
|
72 |
void do_mtc0_status_irqraise_debug(void); |
|
72 | 73 |
void do_tlbwi (void); |
73 | 74 |
void do_tlbwr (void); |
74 | 75 |
void do_tlbp (void); |
b/target-mips/op.c | ||
---|---|---|
852 | 852 |
RETURN(); |
853 | 853 |
} |
854 | 854 |
|
855 |
void op_mtc0 (void) |
|
855 |
void op_mtc0_index (void)
|
|
856 | 856 |
{ |
857 |
CALL_FROM_TB2(do_mtc0, PARAM1, PARAM2); |
|
857 |
env->CP0_index = (env->CP0_index & 0x80000000) | (T0 & 0x0000000F); |
|
858 |
RETURN(); |
|
859 |
} |
|
860 |
|
|
861 |
void op_mtc0_entrylo0 (void) |
|
862 |
{ |
|
863 |
env->CP0_EntryLo0 = T0 & 0x3FFFFFFF; |
|
864 |
RETURN(); |
|
865 |
} |
|
866 |
|
|
867 |
void op_mtc0_entrylo1 (void) |
|
868 |
{ |
|
869 |
env->CP0_EntryLo1 = T0 & 0x3FFFFFFF; |
|
870 |
RETURN(); |
|
871 |
} |
|
872 |
|
|
873 |
void op_mtc0_context (void) |
|
874 |
{ |
|
875 |
env->CP0_Context = (env->CP0_Context & 0xFF800000) | (T0 & 0x007FFFF0); |
|
876 |
RETURN(); |
|
877 |
} |
|
878 |
|
|
879 |
void op_mtc0_pagemask (void) |
|
880 |
{ |
|
881 |
env->CP0_PageMask = T0 & 0x01FFE000; |
|
882 |
RETURN(); |
|
883 |
} |
|
884 |
|
|
885 |
void op_mtc0_wired (void) |
|
886 |
{ |
|
887 |
env->CP0_Wired = T0 & 0x0000000F; |
|
888 |
RETURN(); |
|
889 |
} |
|
890 |
|
|
891 |
void op_mtc0_count (void) |
|
892 |
{ |
|
893 |
CALL_FROM_TB2(cpu_mips_store_count, env, T0); |
|
894 |
RETURN(); |
|
895 |
} |
|
896 |
|
|
897 |
void op_mtc0_entryhi (void) |
|
898 |
{ |
|
899 |
uint32_t old, val; |
|
900 |
|
|
901 |
val = T0 & 0xFFFFE0FF; |
|
902 |
old = env->CP0_EntryHi; |
|
903 |
env->CP0_EntryHi = val; |
|
904 |
/* If the ASID changes, flush qemu's TLB. */ |
|
905 |
if ((old & 0xFF) != (val & 0xFF)) |
|
906 |
CALL_FROM_TB2(cpu_mips_tlb_flush, env, 1); |
|
907 |
RETURN(); |
|
908 |
} |
|
909 |
|
|
910 |
void op_mtc0_compare (void) |
|
911 |
{ |
|
912 |
CALL_FROM_TB2(cpu_mips_store_compare, env, T0); |
|
913 |
RETURN(); |
|
914 |
} |
|
915 |
|
|
916 |
void op_mtc0_status (void) |
|
917 |
{ |
|
918 |
uint32_t val, old, mask; |
|
919 |
|
|
920 |
val = T0 & 0xFA78FF01; |
|
921 |
old = env->CP0_Status; |
|
922 |
if (T0 & (1 << CP0St_UM)) |
|
923 |
env->hflags |= MIPS_HFLAG_UM; |
|
924 |
else |
|
925 |
env->hflags &= ~MIPS_HFLAG_UM; |
|
926 |
if (T0 & (1 << CP0St_ERL)) |
|
927 |
env->hflags |= MIPS_HFLAG_ERL; |
|
928 |
else |
|
929 |
env->hflags &= ~MIPS_HFLAG_ERL; |
|
930 |
if (T0 & (1 << CP0St_EXL)) |
|
931 |
env->hflags |= MIPS_HFLAG_EXL; |
|
932 |
else |
|
933 |
env->hflags &= ~MIPS_HFLAG_EXL; |
|
934 |
env->CP0_Status = val; |
|
935 |
/* If we unmasked an asserted IRQ, raise it */ |
|
936 |
mask = 0x0000FF00; |
|
937 |
if (loglevel & CPU_LOG_TB_IN_ASM) |
|
938 |
CALL_FROM_TB2(do_mtc0_status_debug, old, val); |
|
939 |
if ((val & (1 << CP0St_IE)) && !(old & (1 << CP0St_IE)) && |
|
940 |
!(env->hflags & MIPS_HFLAG_EXL) && |
|
941 |
!(env->hflags & MIPS_HFLAG_ERL) && |
|
942 |
!(env->hflags & MIPS_HFLAG_DM) && |
|
943 |
(env->CP0_Status & env->CP0_Cause & mask)) { |
|
944 |
env->interrupt_request |= CPU_INTERRUPT_HARD; |
|
945 |
if (logfile) |
|
946 |
CALL_FROM_TB0(do_mtc0_status_irqraise_debug); |
|
947 |
} else if (!(val & (1 << CP0St_IE)) && (old & (1 << CP0St_IE))) { |
|
948 |
env->interrupt_request &= ~CPU_INTERRUPT_HARD; |
|
949 |
} |
|
950 |
RETURN(); |
|
951 |
} |
|
952 |
|
|
953 |
void op_mtc0_cause (void) |
|
954 |
{ |
|
955 |
uint32_t val, old; |
|
956 |
|
|
957 |
val = (env->CP0_Cause & 0xB000F87C) | (T0 & 0x000C00300); |
|
958 |
old = env->CP0_Cause; |
|
959 |
env->CP0_Cause = val; |
|
960 |
#if 0 |
|
961 |
{ |
|
962 |
int i, mask; |
|
963 |
|
|
964 |
/* Check if we ever asserted a software IRQ */ |
|
965 |
for (i = 0; i < 2; i++) { |
|
966 |
mask = 0x100 << i; |
|
967 |
if ((val & mask) & !(old & mask)) |
|
968 |
CALL_FROM_TB1(mips_set_irq, i); |
|
969 |
} |
|
970 |
} |
|
971 |
#endif |
|
972 |
RETURN(); |
|
973 |
} |
|
974 |
|
|
975 |
void op_mtc0_epc (void) |
|
976 |
{ |
|
977 |
env->CP0_EPC = T0; |
|
978 |
RETURN(); |
|
979 |
} |
|
980 |
|
|
981 |
void op_mtc0_config0 (void) |
|
982 |
{ |
|
983 |
#if defined(MIPS_USES_R4K_TLB) |
|
984 |
env->CP0_Config0 = (env->CP0_Config0 & 0x8017FF80) | (T0 & 0x7E000001); |
|
985 |
#else |
|
986 |
env->CP0_Config0 = (env->CP0_Config0 & 0xFE17FF80) | (T0 & 0x00000001); |
|
987 |
#endif |
|
988 |
RETURN(); |
|
989 |
} |
|
990 |
|
|
991 |
void op_mtc0_watchlo (void) |
|
992 |
{ |
|
993 |
env->CP0_WatchLo = T0; |
|
994 |
RETURN(); |
|
995 |
} |
|
996 |
|
|
997 |
void op_mtc0_watchhi (void) |
|
998 |
{ |
|
999 |
env->CP0_WatchHi = T0 & 0x40FF0FF8; |
|
1000 |
RETURN(); |
|
1001 |
} |
|
1002 |
|
|
1003 |
void op_mtc0_debug (void) |
|
1004 |
{ |
|
1005 |
env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120); |
|
1006 |
if (T0 & (1 << CP0DB_DM)) |
|
1007 |
env->hflags |= MIPS_HFLAG_DM; |
|
1008 |
else |
|
1009 |
env->hflags &= ~MIPS_HFLAG_DM; |
|
1010 |
RETURN(); |
|
1011 |
} |
|
1012 |
|
|
1013 |
void op_mtc0_depc (void) |
|
1014 |
{ |
|
1015 |
env->CP0_DEPC = T0; |
|
1016 |
RETURN(); |
|
1017 |
} |
|
1018 |
|
|
1019 |
void op_mtc0_taglo (void) |
|
1020 |
{ |
|
1021 |
env->CP0_TagLo = T0 & 0xFFFFFCF6; |
|
1022 |
RETURN(); |
|
1023 |
} |
|
1024 |
|
|
1025 |
void op_mtc0_errorepc (void) |
|
1026 |
{ |
|
1027 |
env->CP0_ErrorEPC = T0; |
|
1028 |
RETURN(); |
|
1029 |
} |
|
1030 |
|
|
1031 |
void op_mtc0_desave (void) |
|
1032 |
{ |
|
1033 |
env->CP0_DESAVE = T0; |
|
858 | 1034 |
RETURN(); |
859 | 1035 |
} |
860 | 1036 |
|
b/target-mips/op_helper.c | ||
---|---|---|
141 | 141 |
cpu_abort(env, "mfc0 count\n"); |
142 | 142 |
} |
143 | 143 |
|
144 |
void do_mtc0 (int reg, int sel)
|
|
144 |
void cpu_mips_store_count(CPUState *env, uint32_t value)
|
|
145 | 145 |
{ |
146 |
cpu_abort(env, "mtc0 reg=%d sel=%d\n", reg, sel); |
|
146 |
cpu_abort(env, "mtc0 count\n"); |
|
147 |
} |
|
148 |
|
|
149 |
void cpu_mips_store_compare(CPUState *env, uint32_t value) |
|
150 |
{ |
|
151 |
cpu_abort(env, "mtc0 compare\n"); |
|
152 |
} |
|
153 |
|
|
154 |
void do_mtc0_status_debug(uint32_t old, uint32_t val) |
|
155 |
{ |
|
156 |
cpu_abort(env, "mtc0 status\n"); |
|
157 |
} |
|
158 |
|
|
159 |
void do_mtc0_status_irqraise_debug(void) |
|
160 |
{ |
|
161 |
cpu_abort(env, "mtc0 status\n"); |
|
147 | 162 |
} |
148 | 163 |
|
149 | 164 |
void do_tlbwi (void) |
... | ... | |
166 | 181 |
cpu_abort(env, "tlbr\n"); |
167 | 182 |
} |
168 | 183 |
|
184 |
void cpu_mips_tlb_flush (CPUState *env, int flush_global) |
|
185 |
{ |
|
186 |
cpu_abort(env, "mips_tlb_flush\n"); |
|
187 |
} |
|
188 |
|
|
169 | 189 |
#else |
170 | 190 |
|
171 | 191 |
/* CP0 helpers */ |
... | ... | |
179 | 199 |
T0 = cpu_mips_get_count(env); |
180 | 200 |
} |
181 | 201 |
|
182 |
void do_mtc0 (int reg, int sel)
|
|
202 |
void do_mtc0_status_debug(uint32_t old, uint32_t val)
|
|
183 | 203 |
{ |
184 |
const unsigned char *rn; |
|
185 |
uint32_t val, old, mask; |
|
204 |
const uint32_t mask = 0x0000FF00; |
|
205 |
fprintf(logfile, "Status %08x => %08x Cause %08x (%08x %08x %08x)\n", |
|
206 |
old, val, env->CP0_Cause, old & mask, val & mask, |
|
207 |
env->CP0_Cause & mask); |
|
208 |
} |
|
186 | 209 |
|
187 |
if (sel != 0 && reg != 16 && reg != 28) { |
|
188 |
val = -1; |
|
189 |
old = -1; |
|
190 |
rn = "invalid"; |
|
191 |
goto print; |
|
192 |
} |
|
193 |
switch (reg) { |
|
194 |
case 0: |
|
195 |
val = (env->CP0_index & 0x80000000) | (T0 & 0x0000000F); |
|
196 |
old = env->CP0_index; |
|
197 |
env->CP0_index = val; |
|
198 |
rn = "Index"; |
|
199 |
break; |
|
200 |
case 2: |
|
201 |
val = T0 & 0x3FFFFFFF; |
|
202 |
old = env->CP0_EntryLo0; |
|
203 |
env->CP0_EntryLo0 = val; |
|
204 |
rn = "EntryLo0"; |
|
205 |
break; |
|
206 |
case 3: |
|
207 |
val = T0 & 0x3FFFFFFF; |
|
208 |
old = env->CP0_EntryLo1; |
|
209 |
env->CP0_EntryLo1 = val; |
|
210 |
rn = "EntryLo1"; |
|
211 |
break; |
|
212 |
case 4: |
|
213 |
val = (env->CP0_Context & 0xFF800000) | (T0 & 0x007FFFF0); |
|
214 |
old = env->CP0_Context; |
|
215 |
env->CP0_Context = val; |
|
216 |
rn = "Context"; |
|
217 |
break; |
|
218 |
case 5: |
|
219 |
val = T0 & 0x01FFE000; |
|
220 |
old = env->CP0_PageMask; |
|
221 |
env->CP0_PageMask = val; |
|
222 |
rn = "PageMask"; |
|
223 |
break; |
|
224 |
case 6: |
|
225 |
val = T0 & 0x0000000F; |
|
226 |
old = env->CP0_Wired; |
|
227 |
env->CP0_Wired = val; |
|
228 |
rn = "Wired"; |
|
229 |
break; |
|
230 |
case 9: |
|
231 |
val = T0; |
|
232 |
old = cpu_mips_get_count(env); |
|
233 |
cpu_mips_store_count(env, val); |
|
234 |
rn = "Count"; |
|
235 |
break; |
|
236 |
case 10: |
|
237 |
val = T0 & 0xFFFFE0FF; |
|
238 |
old = env->CP0_EntryHi; |
|
239 |
env->CP0_EntryHi = val; |
|
240 |
/* If the ASID changes, flush qemu's TLB. */ |
|
241 |
if ((old & 0xFF) != (val & 0xFF)) |
|
242 |
cpu_mips_tlb_flush (env, 1); |
|
243 |
rn = "EntryHi"; |
|
244 |
break; |
|
245 |
case 11: |
|
246 |
val = T0; |
|
247 |
old = env->CP0_Compare; |
|
248 |
cpu_mips_store_compare(env, val); |
|
249 |
rn = "Compare"; |
|
250 |
break; |
|
251 |
case 12: |
|
252 |
val = T0 & 0xFA78FF01; |
|
253 |
if (T0 & (1 << CP0St_UM)) |
|
254 |
env->hflags |= MIPS_HFLAG_UM; |
|
255 |
else |
|
256 |
env->hflags &= ~MIPS_HFLAG_UM; |
|
257 |
if (T0 & (1 << CP0St_ERL)) |
|
258 |
env->hflags |= MIPS_HFLAG_ERL; |
|
259 |
else |
|
260 |
env->hflags &= ~MIPS_HFLAG_ERL; |
|
261 |
if (T0 & (1 << CP0St_EXL)) |
|
262 |
env->hflags |= MIPS_HFLAG_EXL; |
|
263 |
else |
|
264 |
env->hflags &= ~MIPS_HFLAG_EXL; |
|
265 |
old = env->CP0_Status; |
|
266 |
env->CP0_Status = val; |
|
267 |
/* If we unmasked an asserted IRQ, raise it */ |
|
268 |
mask = 0x0000FF00; |
|
269 |
if (loglevel & CPU_LOG_TB_IN_ASM) { |
|
270 |
fprintf(logfile, "Status %08x => %08x Cause %08x (%08x %08x %08x)\n", |
|
271 |
old, val, env->CP0_Cause, old & mask, val & mask, |
|
272 |
env->CP0_Cause & mask); |
|
273 |
} |
|
274 |
if ((val & (1 << CP0St_IE)) && !(old & (1 << CP0St_IE)) && |
|
275 |
!(env->hflags & MIPS_HFLAG_EXL) && |
|
276 |
!(env->hflags & MIPS_HFLAG_ERL) && |
|
277 |
!(env->hflags & MIPS_HFLAG_DM) && |
|
278 |
(env->CP0_Status & env->CP0_Cause & mask)) { |
|
279 |
if (logfile) |
|
280 |
fprintf(logfile, "Raise pending IRQs\n"); |
|
281 |
env->interrupt_request |= CPU_INTERRUPT_HARD; |
|
282 |
} else if (!(val & (1 << CP0St_IE)) && (old & (1 << CP0St_IE))) { |
|
283 |
env->interrupt_request &= ~CPU_INTERRUPT_HARD; |
|
284 |
} |
|
285 |
rn = "Status"; |
|
286 |
break; |
|
287 |
case 13: |
|
288 |
val = (env->CP0_Cause & 0xB000F87C) | (T0 & 0x000C00300); |
|
289 |
old = env->CP0_Cause; |
|
290 |
env->CP0_Cause = val; |
|
291 |
#if 0 |
|
292 |
{ |
|
293 |
int i; |
|
294 |
/* Check if we ever asserted a software IRQ */ |
|
295 |
for (i = 0; i < 2; i++) { |
|
296 |
mask = 0x100 << i; |
|
297 |
if ((val & mask) & !(old & mask)) |
|
298 |
mips_set_irq(i); |
|
299 |
} |
|
300 |
} |
|
301 |
#endif |
|
302 |
rn = "Cause"; |
|
303 |
break; |
|
304 |
case 14: |
|
305 |
val = T0; |
|
306 |
old = env->CP0_EPC; |
|
307 |
env->CP0_EPC = val; |
|
308 |
rn = "EPC"; |
|
309 |
break; |
|
310 |
case 16: |
|
311 |
switch (sel) { |
|
312 |
case 0: |
|
313 |
#if defined(MIPS_USES_R4K_TLB) |
|
314 |
val = (env->CP0_Config0 & 0x8017FF80) | (T0 & 0x7E000001); |
|
315 |
#else |
|
316 |
val = (env->CP0_Config0 & 0xFE17FF80) | (T0 & 0x00000001); |
|
317 |
#endif |
|
318 |
old = env->CP0_Config0; |
|
319 |
env->CP0_Config0 = val; |
|
320 |
rn = "Config0"; |
|
321 |
break; |
|
322 |
default: |
|
323 |
val = -1; |
|
324 |
old = -1; |
|
325 |
rn = "bad config selector"; |
|
326 |
break; |
|
327 |
} |
|
328 |
break; |
|
329 |
case 18: |
|
330 |
val = T0; |
|
331 |
old = env->CP0_WatchLo; |
|
332 |
env->CP0_WatchLo = val; |
|
333 |
rn = "WatchLo"; |
|
334 |
break; |
|
335 |
case 19: |
|
336 |
val = T0 & 0x40FF0FF8; |
|
337 |
old = env->CP0_WatchHi; |
|
338 |
env->CP0_WatchHi = val; |
|
339 |
rn = "WatchHi"; |
|
340 |
break; |
|
341 |
case 23: |
|
342 |
val = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120); |
|
343 |
if (T0 & (1 << CP0DB_DM)) |
|
344 |
env->hflags |= MIPS_HFLAG_DM; |
|
345 |
else |
|
346 |
env->hflags &= ~MIPS_HFLAG_DM; |
|
347 |
old = env->CP0_Debug; |
|
348 |
env->CP0_Debug = val; |
|
349 |
rn = "Debug"; |
|
350 |
break; |
|
351 |
case 24: |
|
352 |
val = T0; |
|
353 |
old = env->CP0_DEPC; |
|
354 |
env->CP0_DEPC = val; |
|
355 |
rn = "DEPC"; |
|
356 |
break; |
|
357 |
case 28: |
|
358 |
switch (sel) { |
|
359 |
case 0: |
|
360 |
val = T0 & 0xFFFFFCF6; |
|
361 |
old = env->CP0_TagLo; |
|
362 |
env->CP0_TagLo = val; |
|
363 |
rn = "TagLo"; |
|
364 |
break; |
|
365 |
default: |
|
366 |
val = -1; |
|
367 |
old = -1; |
|
368 |
rn = "invalid sel"; |
|
369 |
break; |
|
370 |
} |
|
371 |
break; |
|
372 |
case 30: |
|
373 |
val = T0; |
|
374 |
old = env->CP0_ErrorEPC; |
|
375 |
env->CP0_ErrorEPC = val; |
|
376 |
rn = "EPC"; |
|
377 |
break; |
|
378 |
case 31: |
|
379 |
val = T0; |
|
380 |
old = env->CP0_DESAVE; |
|
381 |
env->CP0_DESAVE = val; |
|
382 |
rn = "DESAVE"; |
|
383 |
break; |
|
384 |
default: |
|
385 |
val = -1; |
|
386 |
old = -1; |
|
387 |
rn = "unknown"; |
|
388 |
break; |
|
389 |
} |
|
390 |
print: |
|
391 |
#if defined MIPS_DEBUG_DISAS |
|
392 |
if (loglevel & CPU_LOG_TB_IN_ASM) { |
|
393 |
fprintf(logfile, "%08x mtc0 %s %08x => %08x (%d %d %08x)\n", |
|
394 |
env->PC, rn, T0, val, reg, sel, old); |
|
395 |
} |
|
396 |
#endif |
|
397 |
return; |
|
210 |
void do_mtc0_status_irqraise_debug(void) |
|
211 |
{ |
|
212 |
fprintf(logfile, "Raise pending IRQs\n"); |
|
398 | 213 |
} |
399 | 214 |
|
400 | 215 |
#ifdef MIPS_USES_FPU |
b/target-mips/translate.c | ||
---|---|---|
1371 | 1371 |
rn = "EntryLo0"; |
1372 | 1372 |
break; |
1373 | 1373 |
case 3: |
1374 |
/* also CONF */ |
|
1374 | 1375 |
gen_op_mfc0_entrylo1(); |
1375 | 1376 |
rn = "EntryLo1"; |
1376 | 1377 |
break; |
... | ... | |
1386 | 1387 |
gen_op_mfc0_wired(); |
1387 | 1388 |
rn = "Wired"; |
1388 | 1389 |
break; |
1390 |
case 7: |
|
1391 |
// gen_op_mfc0_info(); |
|
1392 |
rn = "Info"; |
|
1393 |
break; |
|
1389 | 1394 |
case 8: |
1390 | 1395 |
gen_op_mfc0_badvaddr(); |
1391 | 1396 |
rn = "BadVaddr"; |
... | ... | |
1445 | 1450 |
gen_op_mfc0_watchhi(); |
1446 | 1451 |
rn = "WatchHi"; |
1447 | 1452 |
break; |
1453 |
case 20: |
|
1454 |
/* 64 bit only */ |
|
1455 |
// gen_op_mfc0_xcontext(); |
|
1456 |
rn = "XContext"; |
|
1457 |
break; |
|
1458 |
case 21: |
|
1459 |
// gen_op_mfc0_framemask(); |
|
1460 |
rn = "Framemask"; |
|
1461 |
break; |
|
1462 |
case 22: |
|
1463 |
// gen_op_mfc0_diagnostic(); |
|
1464 |
rn = "'Diagnostic"; |
|
1465 |
break; |
|
1448 | 1466 |
case 23: |
1449 | 1467 |
gen_op_mfc0_debug(); |
1450 | 1468 |
rn = "Debug"; |
... | ... | |
1453 | 1471 |
gen_op_mfc0_depc(); |
1454 | 1472 |
rn = "DEPC"; |
1455 | 1473 |
break; |
1474 |
case 25: |
|
1475 |
// gen_op_mfc0_performance(); |
|
1476 |
rn = "Performance"; |
|
1477 |
break; |
|
1478 |
case 26: |
|
1479 |
// gen_op_mfc0_ecc(); |
|
1480 |
rn = "ECC"; |
|
1481 |
break; |
|
1482 |
case 27: |
|
1483 |
// gen_op_mfc0_cacheerr(); |
|
1484 |
rn = "CacheErr"; |
|
1485 |
break; |
|
1456 | 1486 |
case 28: |
1457 | 1487 |
switch (sel) { |
1458 | 1488 |
case 0: |
... | ... | |
1468 | 1498 |
goto die; |
1469 | 1499 |
} |
1470 | 1500 |
break; |
1501 |
case 29: |
|
1502 |
// gen_op_mfc0_taghi(); |
|
1503 |
rn = "TagHi"; |
|
1504 |
break; |
|
1471 | 1505 |
case 30: |
1472 | 1506 |
gen_op_mfc0_errorepc(); |
1473 | 1507 |
rn = "ErrorEPC"; |
... | ... | |
1498 | 1532 |
generate_exception(ctx, EXCP_RI); |
1499 | 1533 |
} |
1500 | 1534 |
|
1535 |
static void gen_mtc0 (DisasContext *ctx, int reg, int sel) |
|
1536 |
{ |
|
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 |
} |
|
1546 |
switch (reg) { |
|
1547 |
case 0: |
|
1548 |
gen_op_mtc0_index(); |
|
1549 |
rn = "Index"; |
|
1550 |
break; |
|
1551 |
case 1: |
|
1552 |
// ignore or except? |
|
1553 |
rn = "Random"; |
|
1554 |
break; |
|
1555 |
case 2: |
|
1556 |
gen_op_mtc0_entrylo0(); |
|
1557 |
rn = "EntryLo0"; |
|
1558 |
break; |
|
1559 |
case 3: |
|
1560 |
gen_op_mtc0_entrylo1(); |
|
1561 |
rn = "EntryLo1"; |
|
1562 |
break; |
|
1563 |
case 4: |
|
1564 |
gen_op_mtc0_context(); |
|
1565 |
rn = "Context"; |
|
1566 |
break; |
|
1567 |
case 5: |
|
1568 |
gen_op_mtc0_pagemask(); |
|
1569 |
rn = "PageMask"; |
|
1570 |
break; |
|
1571 |
case 6: |
|
1572 |
gen_op_mtc0_wired(); |
|
1573 |
rn = "Wired"; |
|
1574 |
break; |
|
1575 |
case 7: |
|
1576 |
// ignore or except? |
|
1577 |
rn = "Info"; |
|
1578 |
break; |
|
1579 |
case 8: |
|
1580 |
// ignore or except? |
|
1581 |
rn = "BadVaddr"; |
|
1582 |
break; |
|
1583 |
case 9: |
|
1584 |
gen_op_mtc0_count(); |
|
1585 |
rn = "Count"; |
|
1586 |
break; |
|
1587 |
case 10: |
|
1588 |
gen_op_mtc0_entryhi(); |
|
1589 |
rn = "EntryHi"; |
|
1590 |
break; |
|
1591 |
case 11: |
|
1592 |
gen_op_mtc0_compare(); |
|
1593 |
rn = "Compare"; |
|
1594 |
break; |
|
1595 |
case 12: |
|
1596 |
gen_op_mtc0_status(); |
|
1597 |
rn = "Status"; |
|
1598 |
break; |
|
1599 |
case 13: |
|
1600 |
gen_op_mtc0_cause(); |
|
1601 |
rn = "Cause"; |
|
1602 |
break; |
|
1603 |
case 14: |
|
1604 |
gen_op_mtc0_epc(); |
|
1605 |
rn = "EPC"; |
|
1606 |
break; |
|
1607 |
case 15: |
|
1608 |
// ignore or except? |
|
1609 |
rn = "PRid"; |
|
1610 |
break; |
|
1611 |
case 16: |
|
1612 |
switch (sel) { |
|
1613 |
case 0: |
|
1614 |
gen_op_mtc0_config0(); |
|
1615 |
rn = "Config0"; |
|
1616 |
break; |
|
1617 |
default: |
|
1618 |
rn = "Invalid config selector"; |
|
1619 |
goto die; |
|
1620 |
} |
|
1621 |
break; |
|
1622 |
case 17: |
|
1623 |
// ignore or except? |
|
1624 |
rn = "LLaddr"; |
|
1625 |
break; |
|
1626 |
case 18: |
|
1627 |
gen_op_mtc0_watchlo(); |
|
1628 |
rn = "WatchLo"; |
|
1629 |
break; |
|
1630 |
case 19: |
|
1631 |
gen_op_mtc0_watchhi(); |
|
1632 |
rn = "WatchHi"; |
|
1633 |
break; |
|
1634 |
case 20: |
|
1635 |
/* 64 bit only */ |
|
1636 |
// gen_op_mtc0_xcontext(); |
|
1637 |
rn = "XContext"; |
|
1638 |
break; |
|
1639 |
case 21: |
|
1640 |
// gen_op_mtc0_framemask(); |
|
1641 |
rn = "Framemask"; |
|
1642 |
break; |
|
1643 |
case 22: |
|
1644 |
// ignore or except? |
|
1645 |
rn = "Diagnostic"; |
|
1646 |
break; |
|
1647 |
case 23: |
|
1648 |
gen_op_mtc0_debug(); |
|
1649 |
rn = "Debug"; |
|
1650 |
break; |
|
1651 |
case 24: |
|
1652 |
gen_op_mtc0_depc(); |
|
1653 |
rn = "DEPC"; |
|
1654 |
break; |
|
1655 |
case 25: |
|
1656 |
// ignore or except? |
|
1657 |
rn = "Performance"; |
|
1658 |
break; |
|
1659 |
case 26: |
|
1660 |
// ignore or except? |
|
1661 |
rn = "ECC"; |
|
1662 |
break; |
|
1663 |
case 27: |
|
1664 |
// ignore or except? |
|
1665 |
rn = "CacheErr"; |
|
1666 |
break; |
|
1667 |
case 28: |
|
1668 |
switch (sel) { |
|
1669 |
case 0: |
|
1670 |
gen_op_mtc0_taglo(); |
|
1671 |
rn = "TagLo"; |
|
1672 |
break; |
|
1673 |
default: |
|
1674 |
rn = "invalid sel"; |
|
1675 |
goto die; |
|
1676 |
} |
|
1677 |
break; |
|
1678 |
case 29: |
|
1679 |
// gen_op_mtc0_taghi(); |
|
1680 |
rn = "TagHi"; |
|
1681 |
break; |
|
1682 |
case 30: |
|
1683 |
gen_op_mtc0_errorepc(); |
|
1684 |
rn = "ErrorEPC"; |
|
1685 |
break; |
|
1686 |
case 31: |
|
1687 |
gen_op_mtc0_desave(); |
|
1688 |
rn = "DESAVE"; |
|
1689 |
break; |
|
1690 |
default: |
|
1691 |
rn = "unknown"; |
|
1692 |
goto die; |
|
1693 |
} |
|
1694 |
#if defined MIPS_DEBUG_DISAS |
|
1695 |
if (loglevel & CPU_LOG_TB_IN_ASM) { |
|
1696 |
fprintf(logfile, "%08x mtc0 %s => %08x (%d %d)\n", |
|
1697 |
env->PC, rn, T0, reg, sel); |
|
1698 |
} |
|
1699 |
#endif |
|
1700 |
return; |
|
1701 |
|
|
1702 |
die: |
|
1703 |
#if defined MIPS_DEBUG_DISAS |
|
1704 |
if (loglevel & CPU_LOG_TB_IN_ASM) { |
|
1705 |
fprintf(logfile, "%08x mtc0 %s => %08x (%d %d)\n", |
|
1706 |
env->PC, rn, T0, reg, sel); |
|
1707 |
} |
|
1708 |
#endif |
|
1709 |
generate_exception(ctx, EXCP_RI); |
|
1710 |
} |
|
1711 |
|
|
1501 | 1712 |
static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd) |
1502 | 1713 |
{ |
1503 | 1714 |
const unsigned char *opn = "unk"; |
... | ... | |
1529 | 1740 |
save_cpu_state(ctx, 1); |
1530 | 1741 |
ctx->pc -= 4; |
1531 | 1742 |
GEN_LOAD_REG_TN(T0, rt); |
1532 |
gen_op_mtc0(rd, ctx->opcode & 0x7);
|
|
1743 |
gen_mtc0(ctx, rd, ctx->opcode & 0x7);
|
|
1533 | 1744 |
/* Stop translation as we may have switched the execution mode */ |
1534 | 1745 |
ctx->bstate = BS_STOP; |
1535 | 1746 |
opn = "mtc0"; |
Also available in: Unified diff