diff options
Diffstat (limited to 'target-mips/helper.c')
-rw-r--r-- | target-mips/helper.c | 436 |
1 files changed, 215 insertions, 221 deletions
diff --git a/target-mips/helper.c b/target-mips/helper.c index 11f58c2..b379021 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -206,26 +206,23 @@ static int get_physical_address (CPUState *env, target_ulong *physical, return ret; } -#if defined(CONFIG_USER_ONLY) target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) { - return addr; -} -#else -target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) -{ - target_ulong phys_addr; - int prot; + if (env->user_mode_only) + return addr; + else { + target_ulong phys_addr; + int prot; - if (get_physical_address(env, &phys_addr, &prot, addr, 0, ACCESS_INT) != 0) - return -1; - return phys_addr; + if (get_physical_address(env, &phys_addr, &prot, addr, 0, ACCESS_INT) != 0) + return -1; + return phys_addr; + } } void cpu_mips_init_mmu (CPUState *env) { } -#endif /* !defined(CONFIG_USER_ONLY) */ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, int mmu_idx, int is_softmmu) @@ -318,7 +315,6 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, return ret; } -#if !defined(CONFIG_USER_ONLY) static const char * const excp_names[EXCP_LAST + 1] = { [EXCP_RESET] = "reset", [EXCP_SRESET] = "soft reset", @@ -354,232 +350,230 @@ static const char * const excp_names[EXCP_LAST + 1] = { [EXCP_C2E] = "precise coprocessor 2", [EXCP_CACHE] = "cache error", }; -#endif void do_interrupt (CPUState *env) { -#if !defined(CONFIG_USER_ONLY) - target_ulong offset; - int cause = -1; - const char *name; - - if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) { - if (env->exception_index < 0 || env->exception_index > EXCP_LAST) - name = "unknown"; - else - name = excp_names[env->exception_index]; - - fprintf(logfile, "%s enter: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx " %s exception\n", - __func__, env->active_tc.PC, env->CP0_EPC, name); - } - if (env->exception_index == EXCP_EXT_INTERRUPT && - (env->hflags & MIPS_HFLAG_DM)) - env->exception_index = EXCP_DINT; - offset = 0x180; - switch (env->exception_index) { - case EXCP_DSS: - env->CP0_Debug |= 1 << CP0DB_DSS; - /* Debug single step cannot be raised inside a delay slot and - * resume will always occur on the next instruction - * (but we assume the pc has always been updated during - * code translation). - */ - env->CP0_DEPC = env->active_tc.PC; - goto enter_debug_mode; - case EXCP_DINT: - env->CP0_Debug |= 1 << CP0DB_DINT; - goto set_DEPC; - case EXCP_DIB: - env->CP0_Debug |= 1 << CP0DB_DIB; - goto set_DEPC; - case EXCP_DBp: - env->CP0_Debug |= 1 << CP0DB_DBp; - goto set_DEPC; - case EXCP_DDBS: - env->CP0_Debug |= 1 << CP0DB_DDBS; - goto set_DEPC; - case EXCP_DDBL: - env->CP0_Debug |= 1 << CP0DB_DDBL; - set_DEPC: - if (env->hflags & MIPS_HFLAG_BMASK) { - /* If the exception was raised from a delay slot, - come back to the jump. */ - env->CP0_DEPC = env->active_tc.PC - 4; - env->hflags &= ~MIPS_HFLAG_BMASK; - } else { - env->CP0_DEPC = env->active_tc.PC; - } - enter_debug_mode: - env->hflags |= MIPS_HFLAG_DM | MIPS_HFLAG_64 | MIPS_HFLAG_CP0; - env->hflags &= ~(MIPS_HFLAG_KSU); - /* EJTAG probe trap enable is not implemented... */ - if (!(env->CP0_Status & (1 << CP0St_EXL))) - env->CP0_Cause &= ~(1 << CP0Ca_BD); - env->active_tc.PC = (int32_t)0xBFC00480; - break; - case EXCP_RESET: - cpu_reset(env); - break; - case EXCP_SRESET: - env->CP0_Status |= (1 << CP0St_SR); - memset(env->CP0_WatchLo, 0, sizeof(*env->CP0_WatchLo)); - goto set_error_EPC; - case EXCP_NMI: - env->CP0_Status |= (1 << CP0St_NMI); - set_error_EPC: - if (env->hflags & MIPS_HFLAG_BMASK) { - /* If the exception was raised from a delay slot, - come back to the jump. */ - env->CP0_ErrorEPC = env->active_tc.PC - 4; - env->hflags &= ~MIPS_HFLAG_BMASK; - } else { - env->CP0_ErrorEPC = env->active_tc.PC; - } - env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV); - env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0; - env->hflags &= ~(MIPS_HFLAG_KSU); - if (!(env->CP0_Status & (1 << CP0St_EXL))) - env->CP0_Cause &= ~(1 << CP0Ca_BD); - env->active_tc.PC = (int32_t)0xBFC00000; - break; - case EXCP_EXT_INTERRUPT: - cause = 0; - if (env->CP0_Cause & (1 << CP0Ca_IV)) - offset = 0x200; - goto set_EPC; - case EXCP_LTLBL: - cause = 1; - goto set_EPC; - case EXCP_TLBL: - cause = 2; - if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL))) { -#if defined(TARGET_MIPS64) - int R = env->CP0_BadVAddr >> 62; - int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0; - int SX = (env->CP0_Status & (1 << CP0St_SX)) != 0; - int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0; + if (!env->user_mode_only) { + target_ulong offset; + int cause = -1; + const char *name; - if ((R == 0 && UX) || (R == 1 && SX) || (R == 3 && KX)) - offset = 0x080; + if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) { + if (env->exception_index < 0 || env->exception_index > EXCP_LAST) + name = "unknown"; else -#endif - offset = 0x000; - } - goto set_EPC; - case EXCP_TLBS: - cause = 3; - if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL))) { -#if defined(TARGET_MIPS64) - int R = env->CP0_BadVAddr >> 62; - int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0; - int SX = (env->CP0_Status & (1 << CP0St_SX)) != 0; - int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0; + name = excp_names[env->exception_index]; - if ((R == 0 && UX) || (R == 1 && SX) || (R == 3 && KX)) - offset = 0x080; - else -#endif - offset = 0x000; - } - goto set_EPC; - case EXCP_AdEL: - cause = 4; - goto set_EPC; - case EXCP_AdES: - cause = 5; - goto set_EPC; - case EXCP_IBE: - cause = 6; - goto set_EPC; - case EXCP_DBE: - cause = 7; - goto set_EPC; - case EXCP_SYSCALL: - cause = 8; - goto set_EPC; - case EXCP_BREAK: - cause = 9; - goto set_EPC; - case EXCP_RI: - cause = 10; - goto set_EPC; - case EXCP_CpU: - cause = 11; - env->CP0_Cause = (env->CP0_Cause & ~(0x3 << CP0Ca_CE)) | - (env->error_code << CP0Ca_CE); - goto set_EPC; - case EXCP_OVERFLOW: - cause = 12; - goto set_EPC; - case EXCP_TRAP: - cause = 13; - goto set_EPC; - case EXCP_FPE: - cause = 15; - goto set_EPC; - case EXCP_C2E: - cause = 18; - goto set_EPC; - case EXCP_MDMX: - cause = 22; - goto set_EPC; - case EXCP_DWATCH: - cause = 23; - /* XXX: TODO: manage defered watch exceptions */ - goto set_EPC; - case EXCP_MCHECK: - cause = 24; - goto set_EPC; - case EXCP_THREAD: - cause = 25; - goto set_EPC; - case EXCP_CACHE: - cause = 30; - if (env->CP0_Status & (1 << CP0St_BEV)) { - offset = 0x100; - } else { - offset = 0x20000100; + fprintf(logfile, "%s enter: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx " %s exception\n", + __func__, env->active_tc.PC, env->CP0_EPC, name); } - set_EPC: - if (!(env->CP0_Status & (1 << CP0St_EXL))) { + if (env->exception_index == EXCP_EXT_INTERRUPT && + (env->hflags & MIPS_HFLAG_DM)) + env->exception_index = EXCP_DINT; + offset = 0x180; + switch (env->exception_index) { + case EXCP_DSS: + env->CP0_Debug |= 1 << CP0DB_DSS; + /* Debug single step cannot be raised inside a delay slot and + resume will always occur on the next instruction + (but we assume the pc has always been updated during + code translation). */ + env->CP0_DEPC = env->active_tc.PC; + goto enter_debug_mode; + case EXCP_DINT: + env->CP0_Debug |= 1 << CP0DB_DINT; + goto set_DEPC; + case EXCP_DIB: + env->CP0_Debug |= 1 << CP0DB_DIB; + goto set_DEPC; + case EXCP_DBp: + env->CP0_Debug |= 1 << CP0DB_DBp; + goto set_DEPC; + case EXCP_DDBS: + env->CP0_Debug |= 1 << CP0DB_DDBS; + goto set_DEPC; + case EXCP_DDBL: + env->CP0_Debug |= 1 << CP0DB_DDBL; + set_DEPC: if (env->hflags & MIPS_HFLAG_BMASK) { /* If the exception was raised from a delay slot, come back to the jump. */ - env->CP0_EPC = env->active_tc.PC - 4; - env->CP0_Cause |= (1 << CP0Ca_BD); + env->CP0_DEPC = env->active_tc.PC - 4; + env->hflags &= ~MIPS_HFLAG_BMASK; } else { - env->CP0_EPC = env->active_tc.PC; + env->CP0_DEPC = env->active_tc.PC; + } + enter_debug_mode: + env->hflags |= MIPS_HFLAG_DM | MIPS_HFLAG_64 | MIPS_HFLAG_CP0; + env->hflags &= ~(MIPS_HFLAG_KSU); + /* EJTAG probe trap enable is not implemented... */ + if (!(env->CP0_Status & (1 << CP0St_EXL))) env->CP0_Cause &= ~(1 << CP0Ca_BD); + env->active_tc.PC = (int32_t)0xBFC00480; + break; + case EXCP_RESET: + cpu_reset(env); + break; + case EXCP_SRESET: + env->CP0_Status |= (1 << CP0St_SR); + memset(env->CP0_WatchLo, 0, sizeof(*env->CP0_WatchLo)); + goto set_error_EPC; + case EXCP_NMI: + env->CP0_Status |= (1 << CP0St_NMI); + set_error_EPC: + if (env->hflags & MIPS_HFLAG_BMASK) { + /* If the exception was raised from a delay slot, + come back to the jump. */ + env->CP0_ErrorEPC = env->active_tc.PC - 4; + env->hflags &= ~MIPS_HFLAG_BMASK; + } else { + env->CP0_ErrorEPC = env->active_tc.PC; } - env->CP0_Status |= (1 << CP0St_EXL); + env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV); env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0; env->hflags &= ~(MIPS_HFLAG_KSU); + if (!(env->CP0_Status & (1 << CP0St_EXL))) + env->CP0_Cause &= ~(1 << CP0Ca_BD); + env->active_tc.PC = (int32_t)0xBFC00000; + break; + case EXCP_EXT_INTERRUPT: + cause = 0; + if (env->CP0_Cause & (1 << CP0Ca_IV)) + offset = 0x200; + goto set_EPC; + case EXCP_LTLBL: + cause = 1; + goto set_EPC; + case EXCP_TLBL: + cause = 2; + if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL))) { +#if defined(TARGET_MIPS64) + int R = env->CP0_BadVAddr >> 62; + int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0; + int SX = (env->CP0_Status & (1 << CP0St_SX)) != 0; + int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0; + + if ((R == 0 && UX) || (R == 1 && SX) || (R == 3 && KX)) + offset = 0x080; + else +#endif + offset = 0x000; + } + goto set_EPC; + case EXCP_TLBS: + cause = 3; + if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL))) { +#if defined(TARGET_MIPS64) + int R = env->CP0_BadVAddr >> 62; + int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0; + int SX = (env->CP0_Status & (1 << CP0St_SX)) != 0; + int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0; + + if ((R == 0 && UX) || (R == 1 && SX) || (R == 3 && KX)) + offset = 0x080; + else +#endif + offset = 0x000; + } + goto set_EPC; + case EXCP_AdEL: + cause = 4; + goto set_EPC; + case EXCP_AdES: + cause = 5; + goto set_EPC; + case EXCP_IBE: + cause = 6; + goto set_EPC; + case EXCP_DBE: + cause = 7; + goto set_EPC; + case EXCP_SYSCALL: + cause = 8; + goto set_EPC; + case EXCP_BREAK: + cause = 9; + goto set_EPC; + case EXCP_RI: + cause = 10; + goto set_EPC; + case EXCP_CpU: + cause = 11; + env->CP0_Cause = (env->CP0_Cause & ~(0x3 << CP0Ca_CE)) | + (env->error_code << CP0Ca_CE); + goto set_EPC; + case EXCP_OVERFLOW: + cause = 12; + goto set_EPC; + case EXCP_TRAP: + cause = 13; + goto set_EPC; + case EXCP_FPE: + cause = 15; + goto set_EPC; + case EXCP_C2E: + cause = 18; + goto set_EPC; + case EXCP_MDMX: + cause = 22; + goto set_EPC; + case EXCP_DWATCH: + cause = 23; + /* XXX: TODO: manage defered watch exceptions */ + goto set_EPC; + case EXCP_MCHECK: + cause = 24; + goto set_EPC; + case EXCP_THREAD: + cause = 25; + goto set_EPC; + case EXCP_CACHE: + cause = 30; + if (env->CP0_Status & (1 << CP0St_BEV)) { + offset = 0x100; + } else { + offset = 0x20000100; + } + set_EPC: + if (!(env->CP0_Status & (1 << CP0St_EXL))) { + if (env->hflags & MIPS_HFLAG_BMASK) { + /* If the exception was raised from a delay slot, + come back to the jump. */ + env->CP0_EPC = env->active_tc.PC - 4; + env->CP0_Cause |= (1 << CP0Ca_BD); + } else { + env->CP0_EPC = env->active_tc.PC; + env->CP0_Cause &= ~(1 << CP0Ca_BD); + } + env->CP0_Status |= (1 << CP0St_EXL); + env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0; + env->hflags &= ~(MIPS_HFLAG_KSU); + } + env->hflags &= ~MIPS_HFLAG_BMASK; + if (env->CP0_Status & (1 << CP0St_BEV)) { + env->active_tc.PC = (int32_t)0xBFC00200; + } else { + env->active_tc.PC = (int32_t)(env->CP0_EBase & ~0x3ff); + } + env->active_tc.PC += offset; + env->CP0_Cause = (env->CP0_Cause & ~(0x1f << CP0Ca_EC)) | (cause << CP0Ca_EC); + break; + default: + if (logfile) { + fprintf(logfile, "Invalid MIPS exception %d. Exiting\n", + env->exception_index); + } + printf("Invalid MIPS exception %d. Exiting\n", env->exception_index); + exit(1); } - env->hflags &= ~MIPS_HFLAG_BMASK; - if (env->CP0_Status & (1 << CP0St_BEV)) { - env->active_tc.PC = (int32_t)0xBFC00200; - } else { - env->active_tc.PC = (int32_t)(env->CP0_EBase & ~0x3ff); - } - env->active_tc.PC += offset; - env->CP0_Cause = (env->CP0_Cause & ~(0x1f << CP0Ca_EC)) | (cause << CP0Ca_EC); - break; - default: - if (logfile) { - fprintf(logfile, "Invalid MIPS exception %d. Exiting\n", - env->exception_index); + if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) { + fprintf(logfile, "%s: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx " cause %d\n" + " S %08x C %08x A " TARGET_FMT_lx " D " TARGET_FMT_lx "\n", + __func__, env->active_tc.PC, env->CP0_EPC, cause, + env->CP0_Status, env->CP0_Cause, env->CP0_BadVAddr, + env->CP0_DEPC); } - printf("Invalid MIPS exception %d. Exiting\n", env->exception_index); - exit(1); - } - if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) { - fprintf(logfile, "%s: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx " cause %d\n" - " S %08x C %08x A " TARGET_FMT_lx " D " TARGET_FMT_lx "\n", - __func__, env->active_tc.PC, env->CP0_EPC, cause, - env->CP0_Status, env->CP0_Cause, env->CP0_BadVAddr, - env->CP0_DEPC); } -#endif /* !defined(CONFIG_USER_ONLY) */ env->exception_index = EXCP_NONE; } |