Revision 24c7b0e3
b/cpu-exec.c | ||
---|---|---|
461 | 461 |
} |
462 | 462 |
#elif defined(TARGET_MIPS) |
463 | 463 |
if ((interrupt_request & CPU_INTERRUPT_HARD) && |
464 |
(env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) && |
|
464 | 465 |
(env->CP0_Status & (1 << CP0St_IE)) && |
465 |
(env->CP0_Status & env->CP0_Cause & 0x0000FF00) && |
|
466 |
!(env->hflags & MIPS_HFLAG_EXL) && |
|
467 |
!(env->hflags & MIPS_HFLAG_ERL) && |
|
466 |
!(env->CP0_Status & (1 << CP0St_EXL)) && |
|
467 |
!(env->CP0_Status & (1 << CP0St_ERL)) && |
|
468 | 468 |
!(env->hflags & MIPS_HFLAG_DM)) { |
469 | 469 |
/* Raise it */ |
470 | 470 |
env->exception_index = EXCP_EXT_INTERRUPT; |
b/dyngen-exec.h | ||
---|---|---|
80 | 80 |
|
81 | 81 |
typedef struct FILE FILE; |
82 | 82 |
extern int fprintf(FILE *, const char *, ...); |
83 |
extern int fputs(const char *, FILE *); |
|
83 | 84 |
extern int printf(const char *, ...); |
84 | 85 |
#undef NULL |
85 | 86 |
#define NULL 0 |
b/hw/mips_int.c | ||
---|---|---|
5 | 5 |
IRQ may change */ |
6 | 6 |
void cpu_mips_update_irq(CPUState *env) |
7 | 7 |
{ |
8 |
if ((env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
|
|
9 |
(env->CP0_Status & (1 << CP0St_IE)) &&
|
|
10 |
!(env->hflags & MIPS_HFLAG_EXL) &&
|
|
11 |
!(env->hflags & MIPS_HFLAG_ERL) &&
|
|
12 |
!(env->hflags & MIPS_HFLAG_DM)) {
|
|
13 |
if (! (env->interrupt_request & CPU_INTERRUPT_HARD)) {
|
|
8 |
if ((env->CP0_Status & (1 << CP0St_IE)) &&
|
|
9 |
!(env->CP0_Status & (1 << CP0St_EXL)) &&
|
|
10 |
!(env->CP0_Status & (1 << CP0St_ERL)) &&
|
|
11 |
!(env->hflags & MIPS_HFLAG_DM)) {
|
|
12 |
if ((env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
|
|
13 |
!(env->interrupt_request & CPU_INTERRUPT_HARD)) {
|
|
14 | 14 |
cpu_interrupt(env, CPU_INTERRUPT_HARD); |
15 | 15 |
} |
16 |
} else {
|
|
16 |
} else |
|
17 | 17 |
cpu_reset_interrupt(env, CPU_INTERRUPT_HARD); |
18 |
} |
|
19 | 18 |
} |
20 | 19 |
|
21 | 20 |
void cpu_mips_irq_request(void *opaque, int irq, int level) |
b/target-mips/cpu.h | ||
---|---|---|
248 | 248 |
#define MIPS_HFLAG_TMASK 0x007F |
249 | 249 |
#define MIPS_HFLAG_MODE 0x001F /* execution modes */ |
250 | 250 |
#define MIPS_HFLAG_UM 0x0001 /* user mode */ |
251 |
#define MIPS_HFLAG_ERL 0x0002 /* Error mode */ |
|
252 |
#define MIPS_HFLAG_EXL 0x0004 /* Exception mode */ |
|
253 | 251 |
#define MIPS_HFLAG_DM 0x0008 /* Debug mode */ |
254 | 252 |
#define MIPS_HFLAG_SM 0x0010 /* Supervisor mode */ |
255 | 253 |
#define MIPS_HFLAG_RE 0x0040 /* Reversed endianness */ |
b/target-mips/helper.c | ||
---|---|---|
90 | 90 |
if (user_mode && address > 0x7FFFFFFFUL) |
91 | 91 |
return TLBRET_BADADDR; |
92 | 92 |
if (address < (int32_t)0x80000000UL) { |
93 |
if (!(env->hflags & MIPS_HFLAG_ERL)) {
|
|
93 |
if (!(env->CP0_Status & (1 << CP0St_ERL))) {
|
|
94 | 94 |
#ifdef MIPS_USES_R4K_TLB |
95 | 95 |
ret = map_address(env, physical, prot, address, rw, access_type); |
96 | 96 |
#else |
... | ... | |
289 | 289 |
goto set_DEPC; |
290 | 290 |
case EXCP_DDBL: |
291 | 291 |
env->CP0_Debug |= 1 << CP0DB_DDBL; |
292 |
goto set_DEPC; |
|
293 | 292 |
set_DEPC: |
294 | 293 |
if (env->hflags & MIPS_HFLAG_BMASK) { |
295 | 294 |
/* If the exception was raised from a delay slot, |
296 | 295 |
come back to the jump. */ |
297 | 296 |
env->CP0_DEPC = env->PC - 4; |
298 |
if (!(env->hflags & MIPS_HFLAG_EXL)) |
|
299 |
env->CP0_Cause |= (1 << CP0Ca_BD); |
|
300 | 297 |
env->hflags &= ~MIPS_HFLAG_BMASK; |
301 | 298 |
} else { |
302 | 299 |
env->CP0_DEPC = env->PC; |
303 |
env->CP0_Cause &= ~(1 << CP0Ca_BD); |
|
304 | 300 |
} |
305 | 301 |
enter_debug_mode: |
306 | 302 |
env->hflags |= MIPS_HFLAG_DM; |
303 |
env->hflags &= ~MIPS_HFLAG_UM; |
|
307 | 304 |
/* EJTAG probe trap enable is not implemented... */ |
308 | 305 |
env->PC = (int32_t)0xBFC00480; |
309 | 306 |
break; |
... | ... | |
311 | 308 |
cpu_reset(env); |
312 | 309 |
break; |
313 | 310 |
case EXCP_SRESET: |
314 |
env->CP0_Status = (1 << CP0St_SR); |
|
311 |
env->CP0_Status |= (1 << CP0St_SR);
|
|
315 | 312 |
env->CP0_WatchLo = 0; |
316 | 313 |
goto set_error_EPC; |
317 | 314 |
case EXCP_NMI: |
318 |
env->CP0_Status = (1 << CP0St_NMI); |
|
315 |
env->CP0_Status |= (1 << CP0St_NMI);
|
|
319 | 316 |
set_error_EPC: |
320 | 317 |
if (env->hflags & MIPS_HFLAG_BMASK) { |
321 | 318 |
/* If the exception was raised from a delay slot, |
322 | 319 |
come back to the jump. */ |
323 | 320 |
env->CP0_ErrorEPC = env->PC - 4; |
324 |
if (!(env->hflags & MIPS_HFLAG_EXL)) |
|
325 |
env->CP0_Cause |= (1 << CP0Ca_BD); |
|
326 | 321 |
env->hflags &= ~MIPS_HFLAG_BMASK; |
327 | 322 |
} else { |
328 | 323 |
env->CP0_ErrorEPC = env->PC; |
329 |
env->CP0_Cause &= ~(1 << CP0Ca_BD); |
|
330 | 324 |
} |
331 |
env->hflags |= MIPS_HFLAG_ERL;
|
|
332 |
env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
|
|
325 |
env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
|
|
326 |
env->hflags &= ~MIPS_HFLAG_UM;
|
|
333 | 327 |
env->PC = (int32_t)0xBFC00000; |
334 | 328 |
break; |
335 | 329 |
case EXCP_MCHECK: |
... | ... | |
350 | 344 |
goto set_EPC; |
351 | 345 |
case EXCP_TLBL: |
352 | 346 |
cause = 2; |
353 |
if (env->error_code == 1 && !(env->hflags & MIPS_HFLAG_EXL))
|
|
347 |
if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL)))
|
|
354 | 348 |
offset = 0x000; |
355 | 349 |
goto set_EPC; |
356 | 350 |
case EXCP_IBE: |
... | ... | |
384 | 378 |
goto set_EPC; |
385 | 379 |
case EXCP_TLBS: |
386 | 380 |
cause = 3; |
387 |
if (env->error_code == 1 && !(env->hflags & MIPS_HFLAG_EXL))
|
|
381 |
if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL)))
|
|
388 | 382 |
offset = 0x000; |
389 |
goto set_EPC; |
|
390 | 383 |
set_EPC: |
391 |
if (env->hflags & MIPS_HFLAG_BMASK) {
|
|
392 |
/* If the exception was raised from a delay slot,
|
|
393 |
come back to the jump. */
|
|
394 |
env->CP0_EPC = env->PC - 4;
|
|
395 |
if (!(env->hflags & MIPS_HFLAG_EXL))
|
|
384 |
if (!(env->CP0_Status & (1 << CP0St_EXL))) {
|
|
385 |
if (env->hflags & MIPS_HFLAG_BMASK) {
|
|
386 |
/* If the exception was raised from a delay slot,
|
|
387 |
come back to the jump. */
|
|
388 |
env->CP0_EPC = env->PC - 4;
|
|
396 | 389 |
env->CP0_Cause |= (1 << CP0Ca_BD); |
397 |
env->hflags &= ~MIPS_HFLAG_BMASK; |
|
390 |
env->hflags &= ~MIPS_HFLAG_BMASK; |
|
391 |
} else { |
|
392 |
env->CP0_EPC = env->PC; |
|
393 |
env->CP0_Cause &= ~(1 << CP0Ca_BD); |
|
394 |
} |
|
398 | 395 |
} else { |
399 |
env->CP0_EPC = env->PC;
|
|
400 |
env->CP0_Cause &= ~(1 << CP0Ca_BD);
|
|
396 |
env->CP0_Status |= (1 << CP0St_EXL);
|
|
397 |
env->hflags &= ~MIPS_HFLAG_UM;
|
|
401 | 398 |
} |
402 | 399 |
if (env->CP0_Status & (1 << CP0St_BEV)) { |
403 | 400 |
env->PC = (int32_t)0xBFC00200; |
404 | 401 |
} else { |
405 | 402 |
env->PC = (int32_t)0x80000000; |
406 | 403 |
} |
407 |
env->hflags |= MIPS_HFLAG_EXL; |
|
408 |
env->CP0_Status |= (1 << CP0St_EXL); |
|
409 | 404 |
env->PC += offset; |
410 | 405 |
env->CP0_Cause = (env->CP0_Cause & ~0x7C) | (cause << 2); |
411 | 406 |
break; |
b/target-mips/op.c | ||
---|---|---|
1105 | 1105 |
void op_mfc0_status (void) |
1106 | 1106 |
{ |
1107 | 1107 |
T0 = env->CP0_Status; |
1108 |
if (env->hflags & MIPS_HFLAG_UM) |
|
1109 |
T0 |= (1 << CP0St_UM); |
|
1110 |
if (env->hflags & MIPS_HFLAG_ERL) |
|
1111 |
T0 |= (1 << CP0St_ERL); |
|
1112 |
if (env->hflags & MIPS_HFLAG_EXL) |
|
1113 |
T0 |= (1 << CP0St_EXL); |
|
1114 | 1108 |
RETURN(); |
1115 | 1109 |
} |
1116 | 1110 |
|
... | ... | |
1365 | 1359 |
{ |
1366 | 1360 |
uint32_t val, old; |
1367 | 1361 |
|
1368 |
val = (int32_t)T0 & 0xFA78FF01; |
|
1362 |
/* No 64bit FPU, no reverse endianness, no MDMX/DSP, no 64bit ops, |
|
1363 |
no 64bit addressing implemented. */ |
|
1364 |
val = (int32_t)T0 & 0xF878FF17; |
|
1369 | 1365 |
old = env->CP0_Status; |
1370 |
if (T0 & (1 << CP0St_UM)) |
|
1371 |
env->hflags |= MIPS_HFLAG_UM; |
|
1372 |
else |
|
1373 |
env->hflags &= ~MIPS_HFLAG_UM; |
|
1374 |
if (T0 & (1 << CP0St_ERL)) |
|
1375 |
env->hflags |= MIPS_HFLAG_ERL; |
|
1376 |
else |
|
1377 |
env->hflags &= ~MIPS_HFLAG_ERL; |
|
1378 |
if (T0 & (1 << CP0St_EXL)) |
|
1379 |
env->hflags |= MIPS_HFLAG_EXL; |
|
1380 |
else |
|
1381 |
env->hflags &= ~MIPS_HFLAG_EXL; |
|
1382 | 1366 |
env->CP0_Status = val; |
1383 | 1367 |
if (loglevel & CPU_LOG_TB_IN_ASM) |
1384 | 1368 |
CALL_FROM_TB2(do_mtc0_status_debug, old, val); |
... | ... | |
1662 | 1646 |
# define DEBUG_FPU_STATE() do { } while(0) |
1663 | 1647 |
#endif |
1664 | 1648 |
|
1649 |
void op_cp0_enabled(void) |
|
1650 |
{ |
|
1651 |
if (!(env->CP0_Status & (1 << CP0St_CU0)) && |
|
1652 |
(env->hflags & MIPS_HFLAG_UM)) { |
|
1653 |
CALL_FROM_TB2(do_raise_exception_direct_err, EXCP_CpU, 0); |
|
1654 |
} |
|
1655 |
RETURN(); |
|
1656 |
} |
|
1657 |
|
|
1665 | 1658 |
void op_cp1_enabled(void) |
1666 | 1659 |
{ |
1667 | 1660 |
if (!(env->CP0_Status & (1 << CP0St_CU1))) { |
... | ... | |
2091 | 2084 |
void op_eret (void) |
2092 | 2085 |
{ |
2093 | 2086 |
CALL_FROM_TB0(debug_eret); |
2094 |
if (env->hflags & MIPS_HFLAG_ERL) {
|
|
2087 |
if (env->CP0_Status & (1 << CP0St_ERL)) {
|
|
2095 | 2088 |
env->PC = env->CP0_ErrorEPC; |
2096 |
env->hflags &= ~MIPS_HFLAG_ERL; |
|
2097 |
env->CP0_Status &= ~(1 << CP0St_ERL); |
|
2089 |
env->CP0_Status &= ~(1 << CP0St_ERL); |
|
2098 | 2090 |
} else { |
2099 | 2091 |
env->PC = env->CP0_EPC; |
2100 |
env->hflags &= ~MIPS_HFLAG_EXL; |
|
2101 |
env->CP0_Status &= ~(1 << CP0St_EXL); |
|
2092 |
env->CP0_Status &= ~(1 << CP0St_EXL); |
|
2102 | 2093 |
} |
2094 |
if (!(env->CP0_Status & (1 << CP0St_EXL)) && |
|
2095 |
!(env->CP0_Status & (1 << CP0St_ERL)) && |
|
2096 |
!(env->hflags & MIPS_HFLAG_DM) && |
|
2097 |
(env->CP0_Status & (1 << CP0St_UM))) |
|
2098 |
env->hflags |= MIPS_HFLAG_UM; |
|
2103 | 2099 |
env->CP0_LLAddr = 1; |
2104 | 2100 |
RETURN(); |
2105 | 2101 |
} |
... | ... | |
2108 | 2104 |
{ |
2109 | 2105 |
CALL_FROM_TB0(debug_eret); |
2110 | 2106 |
env->PC = env->CP0_DEPC; |
2107 |
env->hflags |= MIPS_HFLAG_DM; |
|
2108 |
if (!(env->CP0_Status & (1 << CP0St_EXL)) && |
|
2109 |
!(env->CP0_Status & (1 << CP0St_ERL)) && |
|
2110 |
!(env->hflags & MIPS_HFLAG_DM) && |
|
2111 |
(env->CP0_Status & (1 << CP0St_UM))) |
|
2112 |
env->hflags |= MIPS_HFLAG_UM; |
|
2113 |
env->CP0_LLAddr = 1; |
|
2111 | 2114 |
RETURN(); |
2112 | 2115 |
} |
2113 | 2116 |
|
b/target-mips/op_helper.c | ||
---|---|---|
509 | 509 |
void debug_eret (void) |
510 | 510 |
{ |
511 | 511 |
if (loglevel) { |
512 |
fprintf(logfile, "ERET: pc " TARGET_FMT_lx " EPC " TARGET_FMT_lx " ErrorEPC " TARGET_FMT_lx " (%d)\n", |
|
513 |
env->PC, env->CP0_EPC, env->CP0_ErrorEPC, |
|
514 |
env->hflags & MIPS_HFLAG_ERL ? 1 : 0); |
|
512 |
fprintf(logfile, "ERET: pc " TARGET_FMT_lx " EPC " TARGET_FMT_lx, |
|
513 |
env->PC, env->CP0_EPC); |
|
514 |
if (env->CP0_Status & (1 << CP0St_ERL)) |
|
515 |
fprintf(logfile, " ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC); |
|
516 |
fputs("\n", logfile); |
|
515 | 517 |
} |
516 | 518 |
} |
517 | 519 |
|
b/target-mips/translate.c | ||
---|---|---|
4022 | 4022 |
{ |
4023 | 4023 |
const char *opn = "unk"; |
4024 | 4024 |
|
4025 |
if ((!ctx->CP0_Status & (1 << CP0St_CU0) && |
|
4026 |
(ctx->hflags & MIPS_HFLAG_UM)) && |
|
4027 |
!(ctx->hflags & MIPS_HFLAG_ERL) && |
|
4028 |
!(ctx->hflags & MIPS_HFLAG_EXL)) { |
|
4029 |
if (loglevel & CPU_LOG_TB_IN_ASM) { |
|
4030 |
fprintf(logfile, "CP0 is not usable\n"); |
|
4031 |
} |
|
4032 |
generate_exception (ctx, EXCP_CpU); |
|
4033 |
return; |
|
4034 |
} |
|
4035 |
|
|
4036 | 4025 |
switch (opc) { |
4037 | 4026 |
case OPC_MFC0: |
4038 | 4027 |
if (rt == 0) { |
... | ... | |
4809 | 4798 |
gen_trap(ctx, op1, rs, -1, imm); |
4810 | 4799 |
break; |
4811 | 4800 |
case OPC_SYNCI: |
4812 |
/* treat as noop */ |
|
4801 |
/* treat as noop */
|
|
4813 | 4802 |
break; |
4814 | 4803 |
default: /* Invalid */ |
4815 | 4804 |
MIPS_INVAL("REGIMM"); |
... | ... | |
4818 | 4807 |
} |
4819 | 4808 |
break; |
4820 | 4809 |
case OPC_CP0: |
4810 |
gen_op_cp0_enabled(); |
|
4821 | 4811 |
op1 = MASK_CP0(ctx->opcode); |
4822 | 4812 |
switch (op1) { |
4823 | 4813 |
case OPC_MFC0: |
... | ... | |
5258 | 5248 |
} |
5259 | 5249 |
|
5260 | 5250 |
c0_status = env->CP0_Status; |
5261 |
if (env->hflags & MIPS_HFLAG_UM) |
|
5262 |
c0_status |= (1 << CP0St_UM); |
|
5263 |
if (env->hflags & MIPS_HFLAG_ERL) |
|
5264 |
c0_status |= (1 << CP0St_ERL); |
|
5265 |
if (env->hflags & MIPS_HFLAG_EXL) |
|
5266 |
c0_status |= (1 << CP0St_EXL); |
|
5267 | 5251 |
|
5268 | 5252 |
cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n", |
5269 | 5253 |
c0_status, env->CP0_Cause, env->CP0_EPC); |
... | ... | |
5304 | 5288 |
} else { |
5305 | 5289 |
env->CP0_ErrorEPC = env->PC; |
5306 | 5290 |
} |
5291 |
env->hflags = 0; |
|
5307 | 5292 |
env->PC = (int32_t)0xBFC00000; |
5308 | 5293 |
#if defined (MIPS_USES_R4K_TLB) |
5309 | 5294 |
env->CP0_Random = MIPS_TLB_NB - 1; |
... | ... | |
5314 | 5299 |
env->CP0_EBase = 0x80000000; |
5315 | 5300 |
env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL); |
5316 | 5301 |
env->CP0_WatchLo = 0; |
5317 |
env->hflags = MIPS_HFLAG_ERL; |
|
5318 | 5302 |
/* Count register increments in debug mode, EJTAG version 1 */ |
5319 | 5303 |
env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER); |
5320 | 5304 |
#endif |
Also available in: Unified diff