diff options
author | ths <ths@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-03-30 16:44:54 +0000 |
---|---|---|
committer | ths <ths@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-03-30 16:44:54 +0000 |
commit | 24c7b0e330fdbfcfe87f515d79e67156c57cbc4f (patch) | |
tree | 50ed71bd4fc4c3fc0e6fc5cccb222417244b5baa /target-mips/op.c | |
parent | e69f67b6d58f366ffaa83a0973948edd1f74b370 (diff) |
Sanitize mips exception handling.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2546 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-mips/op.c')
-rw-r--r-- | target-mips/op.c | 51 |
1 files changed, 27 insertions, 24 deletions
diff --git a/target-mips/op.c b/target-mips/op.c index f97ec42928..fecf18cc6a 100644 --- a/target-mips/op.c +++ b/target-mips/op.c @@ -1105,12 +1105,6 @@ void op_mfc0_compare (void) void op_mfc0_status (void) { T0 = env->CP0_Status; - if (env->hflags & MIPS_HFLAG_UM) - T0 |= (1 << CP0St_UM); - if (env->hflags & MIPS_HFLAG_ERL) - T0 |= (1 << CP0St_ERL); - if (env->hflags & MIPS_HFLAG_EXL) - T0 |= (1 << CP0St_EXL); RETURN(); } @@ -1365,20 +1359,10 @@ void op_mtc0_status (void) { uint32_t val, old; - val = (int32_t)T0 & 0xFA78FF01; + /* No 64bit FPU, no reverse endianness, no MDMX/DSP, no 64bit ops, + no 64bit addressing implemented. */ + val = (int32_t)T0 & 0xF878FF17; old = env->CP0_Status; - if (T0 & (1 << CP0St_UM)) - env->hflags |= MIPS_HFLAG_UM; - else - env->hflags &= ~MIPS_HFLAG_UM; - if (T0 & (1 << CP0St_ERL)) - env->hflags |= MIPS_HFLAG_ERL; - else - env->hflags &= ~MIPS_HFLAG_ERL; - if (T0 & (1 << CP0St_EXL)) - env->hflags |= MIPS_HFLAG_EXL; - else - env->hflags &= ~MIPS_HFLAG_EXL; env->CP0_Status = val; if (loglevel & CPU_LOG_TB_IN_ASM) CALL_FROM_TB2(do_mtc0_status_debug, old, val); @@ -1662,6 +1646,15 @@ void op_dmtc0_errorepc (void) # define DEBUG_FPU_STATE() do { } while(0) #endif +void op_cp0_enabled(void) +{ + if (!(env->CP0_Status & (1 << CP0St_CU0)) && + (env->hflags & MIPS_HFLAG_UM)) { + CALL_FROM_TB2(do_raise_exception_direct_err, EXCP_CpU, 0); + } + RETURN(); +} + void op_cp1_enabled(void) { if (!(env->CP0_Status & (1 << CP0St_CU1))) { @@ -2091,15 +2084,18 @@ void debug_eret (void); void op_eret (void) { CALL_FROM_TB0(debug_eret); - if (env->hflags & MIPS_HFLAG_ERL) { + if (env->CP0_Status & (1 << CP0St_ERL)) { env->PC = env->CP0_ErrorEPC; - env->hflags &= ~MIPS_HFLAG_ERL; - env->CP0_Status &= ~(1 << CP0St_ERL); + env->CP0_Status &= ~(1 << CP0St_ERL); } else { env->PC = env->CP0_EPC; - env->hflags &= ~MIPS_HFLAG_EXL; - env->CP0_Status &= ~(1 << CP0St_EXL); + env->CP0_Status &= ~(1 << CP0St_EXL); } + if (!(env->CP0_Status & (1 << CP0St_EXL)) && + !(env->CP0_Status & (1 << CP0St_ERL)) && + !(env->hflags & MIPS_HFLAG_DM) && + (env->CP0_Status & (1 << CP0St_UM))) + env->hflags |= MIPS_HFLAG_UM; env->CP0_LLAddr = 1; RETURN(); } @@ -2108,6 +2104,13 @@ void op_deret (void) { CALL_FROM_TB0(debug_eret); env->PC = env->CP0_DEPC; + env->hflags |= MIPS_HFLAG_DM; + if (!(env->CP0_Status & (1 << CP0St_EXL)) && + !(env->CP0_Status & (1 << CP0St_ERL)) && + !(env->hflags & MIPS_HFLAG_DM) && + (env->CP0_Status & (1 << CP0St_UM))) + env->hflags |= MIPS_HFLAG_UM; + env->CP0_LLAddr = 1; RETURN(); } |