From b5dc7732e1cc2fb549e48b7b5d664f2c79628e2e Mon Sep 17 00:00:00 2001 From: ths Date: Fri, 27 Jun 2008 10:02:35 +0000 Subject: [PATCH] More efficient target register / TC accesses. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4794 c046a42c-6fe2-441c-8c8c-71466251a162 --- cpu-exec.c | 2 +- gdbstub.c | 20 +-- hw/mips_mipssim.c | 4 +- hw/mips_r4k.c | 2 +- linux-user/main.c | 26 ++-- linux-user/mips/target_signal.h | 2 +- linux-user/mips64/target_signal.h | 2 +- linux-user/mipsn32/target_signal.h | 2 +- linux-user/signal.c | 34 ++--- linux-user/syscall.c | 2 +- monitor.c | 2 +- target-mips/cpu.h | 77 ++++++----- target-mips/helper.c | 30 ++-- target-mips/op_helper.c | 268 +++++++++++++++++++++++++----------- target-mips/translate.c | 98 +++++-------- target-mips/translate_init.c | 2 - 16 files changed, 327 insertions(+), 246 deletions(-) diff --git a/cpu-exec.c b/cpu-exec.c index b8c208b..9d00cff 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -197,7 +197,7 @@ static inline TranslationBlock *tb_find_fast(void) #elif defined(TARGET_MIPS) flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK); cs_base = 0; - pc = env->PC[env->current_tc]; + pc = env->active_tc.PC; #elif defined(TARGET_M68K) flags = (env->fpcr & M68K_FPCR_PREC) /* Bit 6 */ | (env->sr & SR_S) /* Bit 13 */ diff --git a/gdbstub.c b/gdbstub.c index d4ca6f3..3f062be 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -704,17 +704,17 @@ static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf) ptr = mem_buf; for (i = 0; i < 32; i++) { - *(target_ulong *)ptr = tswapl(env->gpr[env->current_tc][i]); + *(target_ulong *)ptr = tswapl(env->active_tc.gpr[i]); ptr += sizeof(target_ulong); } *(target_ulong *)ptr = (int32_t)tswap32(env->CP0_Status); ptr += sizeof(target_ulong); - *(target_ulong *)ptr = tswapl(env->LO[env->current_tc][0]); + *(target_ulong *)ptr = tswapl(env->active_tc.LO[0]); ptr += sizeof(target_ulong); - *(target_ulong *)ptr = tswapl(env->HI[env->current_tc][0]); + *(target_ulong *)ptr = tswapl(env->active_tc.HI[0]); ptr += sizeof(target_ulong); *(target_ulong *)ptr = tswapl(env->CP0_BadVAddr); @@ -723,7 +723,7 @@ static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf) *(target_ulong *)ptr = (int32_t)tswap32(env->CP0_Cause); ptr += sizeof(target_ulong); - *(target_ulong *)ptr = tswapl(env->PC[env->current_tc]); + *(target_ulong *)ptr = tswapl(env->active_tc.PC); ptr += sizeof(target_ulong); if (env->CP0_Config1 & (1 << CP0C1_FP)) @@ -781,17 +781,17 @@ static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size) ptr = mem_buf; for (i = 0; i < 32; i++) { - env->gpr[env->current_tc][i] = tswapl(*(target_ulong *)ptr); + env->active_tc.gpr[i] = tswapl(*(target_ulong *)ptr); ptr += sizeof(target_ulong); } env->CP0_Status = tswapl(*(target_ulong *)ptr); ptr += sizeof(target_ulong); - env->LO[env->current_tc][0] = tswapl(*(target_ulong *)ptr); + env->active_tc.LO[0] = tswapl(*(target_ulong *)ptr); ptr += sizeof(target_ulong); - env->HI[env->current_tc][0] = tswapl(*(target_ulong *)ptr); + env->active_tc.HI[0] = tswapl(*(target_ulong *)ptr); ptr += sizeof(target_ulong); env->CP0_BadVAddr = tswapl(*(target_ulong *)ptr); @@ -800,7 +800,7 @@ static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size) env->CP0_Cause = tswapl(*(target_ulong *)ptr); ptr += sizeof(target_ulong); - env->PC[env->current_tc] = tswapl(*(target_ulong *)ptr); + env->active_tc.PC = tswapl(*(target_ulong *)ptr); ptr += sizeof(target_ulong); if (env->CP0_Config1 & (1 << CP0C1_FP)) @@ -1003,7 +1003,7 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf) #elif defined (TARGET_SH4) env->pc = addr; #elif defined (TARGET_MIPS) - env->PC[env->current_tc] = addr; + env->active_tc.PC = addr; #elif defined (TARGET_CRIS) env->pc = addr; #endif @@ -1040,7 +1040,7 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf) #elif defined (TARGET_SH4) env->pc = addr; #elif defined (TARGET_MIPS) - env->PC[env->current_tc] = addr; + env->active_tc.PC = addr; #elif defined (TARGET_CRIS) env->pc = addr; #endif diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c index e29d8af..af09d95 100644 --- a/hw/mips_mipssim.c +++ b/hw/mips_mipssim.c @@ -65,7 +65,7 @@ static void load_kernel (CPUState *env) if (kernel_size >= 0) { if ((entry & ~0x7fffffffULL) == 0x80000000) entry = (int32_t)entry; - env->PC[env->current_tc] = entry; + env->active_tc.PC = entry; } else { fprintf(stderr, "qemu: could not load kernel '%s'\n", loaderparams.kernel_filename); @@ -152,7 +152,7 @@ mips_mipssim_init (ram_addr_t ram_size, int vga_ram_size, cpu_register_physical_memory(0x1fc00000LL, bios_size, bios_offset | IO_MEM_ROM); /* We have a boot vector start address. */ - env->PC[env->current_tc] = (target_long)(int32_t)0xbfc00000; + env->active_tc.PC = (target_long)(int32_t)0xbfc00000; } if (kernel_filename) { diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c index 66ae135..4540cbf 100644 --- a/hw/mips_r4k.c +++ b/hw/mips_r4k.c @@ -87,7 +87,7 @@ static void load_kernel (CPUState *env) if (kernel_size >= 0) { if ((entry & ~0x7fffffffULL) == 0x80000000) entry = (int32_t)entry; - env->PC[env->current_tc] = entry; + env->active_tc.PC = entry; } else { fprintf(stderr, "qemu: could not load kernel '%s'\n", loaderparams.kernel_filename); diff --git a/linux-user/main.c b/linux-user/main.c index a4ffea3..060ef82 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -1779,8 +1779,8 @@ void cpu_loop(CPUMIPSState *env) trapnr = cpu_mips_exec(env); switch(trapnr) { case EXCP_SYSCALL: - syscall_num = env->gpr[env->current_tc][2] - 4000; - env->PC[env->current_tc] += 4; + syscall_num = env->active_tc.gpr[2] - 4000; + env->active_tc.PC += 4; if (syscall_num >= sizeof(mips_syscall_args)) { ret = -ENOSYS; } else { @@ -1789,7 +1789,7 @@ void cpu_loop(CPUMIPSState *env) abi_ulong arg5 = 0, arg6 = 0, arg7 = 0, arg8 = 0; nb_args = mips_syscall_args[syscall_num]; - sp_reg = env->gpr[env->current_tc][29]; + sp_reg = env->active_tc.gpr[29]; switch (nb_args) { /* these arguments are taken from the stack */ /* FIXME - what to do if get_user() fails? */ @@ -1800,20 +1800,20 @@ void cpu_loop(CPUMIPSState *env) default: break; } - ret = do_syscall(env, env->gpr[env->current_tc][2], - env->gpr[env->current_tc][4], - env->gpr[env->current_tc][5], - env->gpr[env->current_tc][6], - env->gpr[env->current_tc][7], + ret = do_syscall(env, env->active_tc.gpr[2], + env->active_tc.gpr[4], + env->active_tc.gpr[5], + env->active_tc.gpr[6], + env->active_tc.gpr[7], arg5, arg6/*, arg7, arg8*/); } if ((unsigned int)ret >= (unsigned int)(-1133)) { - env->gpr[env->current_tc][7] = 1; /* error flag */ + env->active_tc.gpr[7] = 1; /* error flag */ ret = -ret; } else { - env->gpr[env->current_tc][7] = 0; /* error flag */ + env->active_tc.gpr[7] = 0; /* error flag */ } - env->gpr[env->current_tc][2] = ret; + env->active_tc.gpr[2] = ret; break; case EXCP_TLBL: case EXCP_TLBS: @@ -2566,9 +2566,9 @@ int main(int argc, char **argv) int i; for(i = 0; i < 32; i++) { - env->gpr[env->current_tc][i] = regs->regs[i]; + env->active_tc.gpr[i] = regs->regs[i]; } - env->PC[env->current_tc] = regs->cp0_epc; + env->active_tc.PC = regs->cp0_epc; } #elif defined(TARGET_SH4) { diff --git a/linux-user/mips/target_signal.h b/linux-user/mips/target_signal.h index f3ef38d..6e1dc8b 100644 --- a/linux-user/mips/target_signal.h +++ b/linux-user/mips/target_signal.h @@ -23,7 +23,7 @@ typedef struct target_sigaltstack { static inline abi_ulong get_sp_from_cpustate(CPUMIPSState *state) { - return state->gpr[state->current_tc][29]; + return state->active_tc.gpr[29]; } #endif /* TARGET_SIGNAL_H */ diff --git a/linux-user/mips64/target_signal.h b/linux-user/mips64/target_signal.h index f3ef38d..6e1dc8b 100644 --- a/linux-user/mips64/target_signal.h +++ b/linux-user/mips64/target_signal.h @@ -23,7 +23,7 @@ typedef struct target_sigaltstack { static inline abi_ulong get_sp_from_cpustate(CPUMIPSState *state) { - return state->gpr[state->current_tc][29]; + return state->active_tc.gpr[29]; } #endif /* TARGET_SIGNAL_H */ diff --git a/linux-user/mipsn32/target_signal.h b/linux-user/mipsn32/target_signal.h index 5da8411..ff20d9e 100644 --- a/linux-user/mipsn32/target_signal.h +++ b/linux-user/mipsn32/target_signal.h @@ -23,7 +23,7 @@ typedef struct target_sigaltstack { static inline target_ulong get_sp_from_cpustate(CPUMIPSState *state) { - return state->gpr[state->current_tc][29]; + return state->active_tc.gpr[29]; } #endif /* TARGET_SIGNAL_H */ diff --git a/linux-user/signal.c b/linux-user/signal.c index 623a5e3..599b8af 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -2290,10 +2290,10 @@ setup_sigcontext(CPUState *regs, struct target_sigcontext *sc) { int err = 0; - err |= __put_user(regs->PC[regs->current_tc], &sc->sc_pc); + err |= __put_user(regs->active_tc.PC, &sc->sc_pc); -#define save_gp_reg(i) do { \ - err |= __put_user(regs->gpr[regs->current_tc][i], &sc->sc_regs[i]); \ +#define save_gp_reg(i) do { \ + err |= __put_user(regs->active_tc.gpr[i], &sc->sc_regs[i]); \ } while(0) __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2); save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6); @@ -2306,8 +2306,8 @@ setup_sigcontext(CPUState *regs, struct target_sigcontext *sc) save_gp_reg(31); #undef save_gp_reg - err |= __put_user(regs->HI[regs->current_tc][0], &sc->sc_mdhi); - err |= __put_user(regs->LO[regs->current_tc][0], &sc->sc_mdlo); + err |= __put_user(regs->active_tc.HI[0], &sc->sc_mdhi); + err |= __put_user(regs->active_tc.LO[0], &sc->sc_mdlo); /* Not used yet, but might be useful if we ever have DSP suppport */ #if 0 @@ -2367,11 +2367,11 @@ restore_sigcontext(CPUState *regs, struct target_sigcontext *sc) err |= __get_user(regs->CP0_EPC, &sc->sc_pc); - err |= __get_user(regs->HI[regs->current_tc][0], &sc->sc_mdhi); - err |= __get_user(regs->LO[regs->current_tc][0], &sc->sc_mdlo); + err |= __get_user(regs->active_tc.HI[0], &sc->sc_mdhi); + err |= __get_user(regs->active_tc.LO[0], &sc->sc_mdlo); #define restore_gp_reg(i) do { \ - err |= __get_user(regs->gpr[regs->current_tc][i], &sc->sc_regs[i]); \ + err |= __get_user(regs->active_tc.gpr[i], &sc->sc_regs[i]); \ } while(0) restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3); restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6); @@ -2437,7 +2437,7 @@ get_sigframe(struct target_sigaction *ka, CPUState *regs, size_t frame_size) unsigned long sp; /* Default to using normal stack */ - sp = regs->gpr[regs->current_tc][29]; + sp = regs->active_tc.gpr[29]; /* * FPU emulator may have it's own trampoline active just @@ -2486,15 +2486,15 @@ static void setup_frame(int sig, struct target_sigaction * ka, * $25 and PC point to the signal handler, $29 points to the * struct sigframe. */ - regs->gpr[regs->current_tc][ 4] = sig; - regs->gpr[regs->current_tc][ 5] = 0; - regs->gpr[regs->current_tc][ 6] = frame_addr + offsetof(struct sigframe, sf_sc); - regs->gpr[regs->current_tc][29] = frame_addr; - regs->gpr[regs->current_tc][31] = frame_addr + offsetof(struct sigframe, sf_code); + regs->active_tc.gpr[ 4] = sig; + regs->active_tc.gpr[ 5] = 0; + regs->active_tc.gpr[ 6] = frame_addr + offsetof(struct sigframe, sf_sc); + regs->active_tc.gpr[29] = frame_addr; + regs->active_tc.gpr[31] = frame_addr + offsetof(struct sigframe, sf_code); /* The original kernel code sets CP0_EPC to the handler * since it returns to userland using eret * we cannot do this here, and we must set PC directly */ - regs->PC[regs->current_tc] = regs->gpr[regs->current_tc][25] = ka->_sa_handler; + regs->active_tc.PC = regs->active_tc.gpr[25] = ka->_sa_handler; unlock_user_struct(frame, frame_addr, 1); return; @@ -2515,7 +2515,7 @@ long do_sigreturn(CPUState *regs) #if defined(DEBUG_SIGNAL) fprintf(stderr, "do_sigreturn\n"); #endif - frame_addr = regs->gpr[regs->current_tc][29]; + frame_addr = regs->active_tc.gpr[29]; if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) goto badframe; @@ -2542,7 +2542,7 @@ long do_sigreturn(CPUState *regs) /* Unreached */ #endif - regs->PC[regs->current_tc] = regs->CP0_EPC; + regs->active_tc.PC = regs->CP0_EPC; /* I am not sure this is right, but it seems to work * maybe a problem with nested signals ? */ regs->CP0_EPC = 0; diff --git a/linux-user/syscall.c b/linux-user/syscall.c index cd90946..839ac7f 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -3686,7 +3686,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, if (!is_error(ret)) { #if defined(TARGET_MIPS) CPUMIPSState *env = (CPUMIPSState*)cpu_env; - env->gpr[env->current_tc][3] = host_pipe[1]; + env->active_tc.gpr[3] = host_pipe[1]; ret = host_pipe[0]; #elif defined(TARGET_SH4) ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1]; diff --git a/monitor.c b/monitor.c index 914f4c6..fc135ca 100644 --- a/monitor.c +++ b/monitor.c @@ -316,7 +316,7 @@ static void do_info_cpus(void) #elif defined(TARGET_SPARC) term_printf(" pc=0x" TARGET_FMT_lx " npc=0x" TARGET_FMT_lx, env->pc, env->npc); #elif defined(TARGET_MIPS) - term_printf(" PC=0x" TARGET_FMT_lx, env->PC[env->current_tc]); + term_printf(" PC=0x" TARGET_FMT_lx, env->active_tc.PC); #endif if (env->halted) term_printf(" (halted)"); diff --git a/target-mips/cpu.h b/target-mips/cpu.h index fdb05cc..78851ed 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -134,29 +134,53 @@ typedef struct mips_def_t mips_def_t; #define MIPS_TC_MAX 5 #define MIPS_DSP_ACC 4 +typedef struct TCState TCState; +struct TCState { + target_ulong gpr[32]; + target_ulong PC; + target_ulong HI[MIPS_DSP_ACC]; + target_ulong LO[MIPS_DSP_ACC]; + target_ulong ACX[MIPS_DSP_ACC]; + target_ulong DSPControl; + int32_t CP0_TCStatus; +#define CP0TCSt_TCU3 31 +#define CP0TCSt_TCU2 30 +#define CP0TCSt_TCU1 29 +#define CP0TCSt_TCU0 28 +#define CP0TCSt_TMX 27 +#define CP0TCSt_RNST 23 +#define CP0TCSt_TDS 21 +#define CP0TCSt_DT 20 +#define CP0TCSt_DA 15 +#define CP0TCSt_A 13 +#define CP0TCSt_TKSU 11 +#define CP0TCSt_IXMT 10 +#define CP0TCSt_TASID 0 + int32_t CP0_TCBind; +#define CP0TCBd_CurTC 21 +#define CP0TCBd_TBE 17 +#define CP0TCBd_CurVPE 0 + target_ulong CP0_TCHalt; + target_ulong CP0_TCContext; + target_ulong CP0_TCSchedule; + target_ulong CP0_TCScheFBack; + int32_t CP0_Debug_tcstatus; +}; + typedef struct CPUMIPSState CPUMIPSState; struct CPUMIPSState { - /* General integer registers */ - target_ulong gpr[MIPS_SHADOW_SET_MAX][32]; - /* Special registers */ - target_ulong PC[MIPS_TC_MAX]; + TCState active_tc; + /* temporary hack for FP globals */ #ifndef USE_HOST_FLOAT_REGS fpr_t ft0; fpr_t ft1; fpr_t ft2; #endif - target_ulong HI[MIPS_TC_MAX][MIPS_DSP_ACC]; - target_ulong LO[MIPS_TC_MAX][MIPS_DSP_ACC]; - target_ulong ACX[MIPS_TC_MAX][MIPS_DSP_ACC]; - target_ulong DSPControl[MIPS_TC_MAX]; - CPUMIPSMVPContext *mvp; CPUMIPSTLBContext *tlb; CPUMIPSFPUContext *fpu; uint32_t current_tc; - target_ulong *current_tc_gprs; - target_ulong *current_tc_hi; uint32_t SEGBITS; target_ulong SEGMask; @@ -206,28 +230,6 @@ struct CPUMIPSState { #define CP0VPEOpt_DWX1 1 #define CP0VPEOpt_DWX0 0 target_ulong CP0_EntryLo0; - int32_t CP0_TCStatus[MIPS_TC_MAX]; -#define CP0TCSt_TCU3 31 -#define CP0TCSt_TCU2 30 -#define CP0TCSt_TCU1 29 -#define CP0TCSt_TCU0 28 -#define CP0TCSt_TMX 27 -#define CP0TCSt_RNST 23 -#define CP0TCSt_TDS 21 -#define CP0TCSt_DT 20 -#define CP0TCSt_DA 15 -#define CP0TCSt_A 13 -#define CP0TCSt_TKSU 11 -#define CP0TCSt_IXMT 10 -#define CP0TCSt_TASID 0 - int32_t CP0_TCBind[MIPS_TC_MAX]; -#define CP0TCBd_CurTC 21 -#define CP0TCBd_TBE 17 -#define CP0TCBd_CurVPE 0 - target_ulong CP0_TCHalt[MIPS_TC_MAX]; - target_ulong CP0_TCContext[MIPS_TC_MAX]; - target_ulong CP0_TCSchedule[MIPS_TC_MAX]; - target_ulong CP0_TCScheFBack[MIPS_TC_MAX]; target_ulong CP0_EntryLo1; target_ulong CP0_Context; int32_t CP0_PageMask; @@ -398,7 +400,6 @@ struct CPUMIPSState { #define CP0DB_DDBL 2 #define CP0DB_DBp 1 #define CP0DB_DSS 0 - int32_t CP0_Debug_tcstatus[MIPS_TC_MAX]; target_ulong CP0_DEPC; int32_t CP0_Performance0; int32_t CP0_TagLo; @@ -407,6 +408,8 @@ struct CPUMIPSState { int32_t CP0_DataHi; target_ulong CP0_ErrorEPC; int32_t CP0_DESAVE; + /* We waste some space so we can handle shadow registers like TCs. */ + TCState tcs[MIPS_SHADOW_SET_MAX]; /* Qemu */ int interrupt_request; int error_code; @@ -501,9 +504,9 @@ static inline int cpu_mmu_index (CPUState *env) static inline void cpu_clone_regs(CPUState *env, target_ulong newsp) { if (newsp) - env->gpr[env->current_tc][29] = newsp; - env->gpr[env->current_tc][7] = 0; - env->gpr[env->current_tc][2] = 0; + env->active_tc.gpr[29] = newsp; + env->active_tc.gpr[7] = 0; + env->active_tc.gpr[2] = 0; } #endif diff --git a/target-mips/helper.c b/target-mips/helper.c index b962295..11f58c2 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -241,7 +241,7 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, cpu_dump_state(env, logfile, fprintf, 0); #endif fprintf(logfile, "%s pc " TARGET_FMT_lx " ad " TARGET_FMT_lx " rw %d mmu_idx %d smmu %d\n", - __func__, env->PC[env->current_tc], address, rw, mmu_idx, is_softmmu); + __func__, env->active_tc.PC, address, rw, mmu_idx, is_softmmu); } rw &= 1; @@ -370,7 +370,7 @@ void do_interrupt (CPUState *env) name = excp_names[env->exception_index]; fprintf(logfile, "%s enter: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx " %s exception\n", - __func__, env->PC[env->current_tc], env->CP0_EPC, name); + __func__, env->active_tc.PC, env->CP0_EPC, name); } if (env->exception_index == EXCP_EXT_INTERRUPT && (env->hflags & MIPS_HFLAG_DM)) @@ -384,7 +384,7 @@ void do_interrupt (CPUState *env) * (but we assume the pc has always been updated during * code translation). */ - env->CP0_DEPC = env->PC[env->current_tc]; + env->CP0_DEPC = env->active_tc.PC; goto enter_debug_mode; case EXCP_DINT: env->CP0_Debug |= 1 << CP0DB_DINT; @@ -404,10 +404,10 @@ void do_interrupt (CPUState *env) if (env->hflags & MIPS_HFLAG_BMASK) { /* If the exception was raised from a delay slot, come back to the jump. */ - env->CP0_DEPC = env->PC[env->current_tc] - 4; + env->CP0_DEPC = env->active_tc.PC - 4; env->hflags &= ~MIPS_HFLAG_BMASK; } else { - env->CP0_DEPC = env->PC[env->current_tc]; + env->CP0_DEPC = env->active_tc.PC; } enter_debug_mode: env->hflags |= MIPS_HFLAG_DM | MIPS_HFLAG_64 | MIPS_HFLAG_CP0; @@ -415,7 +415,7 @@ void do_interrupt (CPUState *env) /* EJTAG probe trap enable is not implemented... */ if (!(env->CP0_Status & (1 << CP0St_EXL))) env->CP0_Cause &= ~(1 << CP0Ca_BD); - env->PC[env->current_tc] = (int32_t)0xBFC00480; + env->active_tc.PC = (int32_t)0xBFC00480; break; case EXCP_RESET: cpu_reset(env); @@ -430,17 +430,17 @@ void do_interrupt (CPUState *env) if (env->hflags & MIPS_HFLAG_BMASK) { /* If the exception was raised from a delay slot, come back to the jump. */ - env->CP0_ErrorEPC = env->PC[env->current_tc] - 4; + env->CP0_ErrorEPC = env->active_tc.PC - 4; env->hflags &= ~MIPS_HFLAG_BMASK; } else { - env->CP0_ErrorEPC = env->PC[env->current_tc]; + 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->PC[env->current_tc] = (int32_t)0xBFC00000; + env->active_tc.PC = (int32_t)0xBFC00000; break; case EXCP_EXT_INTERRUPT: cause = 0; @@ -545,10 +545,10 @@ void do_interrupt (CPUState *env) if (env->hflags & MIPS_HFLAG_BMASK) { /* If the exception was raised from a delay slot, come back to the jump. */ - env->CP0_EPC = env->PC[env->current_tc] - 4; + env->CP0_EPC = env->active_tc.PC - 4; env->CP0_Cause |= (1 << CP0Ca_BD); } else { - env->CP0_EPC = env->PC[env->current_tc]; + env->CP0_EPC = env->active_tc.PC; env->CP0_Cause &= ~(1 << CP0Ca_BD); } env->CP0_Status |= (1 << CP0St_EXL); @@ -557,11 +557,11 @@ void do_interrupt (CPUState *env) } env->hflags &= ~MIPS_HFLAG_BMASK; if (env->CP0_Status & (1 << CP0St_BEV)) { - env->PC[env->current_tc] = (int32_t)0xBFC00200; + env->active_tc.PC = (int32_t)0xBFC00200; } else { - env->PC[env->current_tc] = (int32_t)(env->CP0_EBase & ~0x3ff); + env->active_tc.PC = (int32_t)(env->CP0_EBase & ~0x3ff); } - env->PC[env->current_tc] += offset; + env->active_tc.PC += offset; env->CP0_Cause = (env->CP0_Cause & ~(0x1f << CP0Ca_EC)) | (cause << CP0Ca_EC); break; default: @@ -575,7 +575,7 @@ void do_interrupt (CPUState *env) 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->PC[env->current_tc], env->CP0_EPC, cause, + __func__, env->active_tc.PC, env->CP0_EPC, cause, env->CP0_Status, env->CP0_Cause, env->CP0_BadVAddr, env->CP0_DEPC); } diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index eae5b74..fe3bbd4 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -89,25 +89,25 @@ target_ulong do_dclz (target_ulong t0) /* 64 bits arithmetic for 32 bits hosts */ static always_inline uint64_t get_HILO (void) { - return ((uint64_t)(env->HI[env->current_tc][0]) << 32) | (uint32_t)env->LO[env->current_tc][0]; + return ((uint64_t)(env->active_tc.HI[0]) << 32) | (uint32_t)env->active_tc.LO[0]; } static always_inline void set_HILO (uint64_t HILO) { - env->LO[env->current_tc][0] = (int32_t)HILO; - env->HI[env->current_tc][0] = (int32_t)(HILO >> 32); + env->active_tc.LO[0] = (int32_t)HILO; + env->active_tc.HI[0] = (int32_t)(HILO >> 32); } static always_inline void set_HIT0_LO (target_ulong t0, uint64_t HILO) { - env->LO[env->current_tc][0] = (int32_t)(HILO & 0xFFFFFFFF); - t0 = env->HI[env->current_tc][0] = (int32_t)(HILO >> 32); + env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF); + t0 = env->active_tc.HI[0] = (int32_t)(HILO >> 32); } static always_inline void set_HI_LOT0 (target_ulong t0, uint64_t HILO) { - t0 = env->LO[env->current_tc][0] = (int32_t)(HILO & 0xFFFFFFFF); - env->HI[env->current_tc][0] = (int32_t)(HILO >> 32); + t0 = env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF); + env->active_tc.HI[0] = (int32_t)(HILO >> 32); } #if TARGET_LONG_BITS > HOST_LONG_BITS @@ -246,12 +246,12 @@ target_ulong do_mulshiu (target_ulong t0, target_ulong t1) #ifdef TARGET_MIPS64 void do_dmult (target_ulong t0, target_ulong t1) { - muls64(&(env->LO[env->current_tc][0]), &(env->HI[env->current_tc][0]), t0, t1); + muls64(&(env->active_tc.LO[0]), &(env->active_tc.HI[0]), t0, t1); } void do_dmultu (target_ulong t0, target_ulong t1) { - mulu64(&(env->LO[env->current_tc][0]), &(env->HI[env->current_tc][0]), t0, t1); + mulu64(&(env->active_tc.LO[0]), &(env->active_tc.HI[0]), t0, t1); } #endif @@ -672,86 +672,107 @@ target_ulong do_mfc0_random (void) target_ulong do_mfc0_tcstatus (void) { - return env->CP0_TCStatus[env->current_tc]; + return env->active_tc.CP0_TCStatus; } target_ulong do_mftc0_tcstatus(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - return env->CP0_TCStatus[other_tc]; + if (other_tc == env->current_tc) + return env->active_tc.CP0_TCStatus; + else + return env->tcs[other_tc].CP0_TCStatus; } target_ulong do_mfc0_tcbind (void) { - return env->CP0_TCBind[env->current_tc]; + return env->active_tc.CP0_TCBind; } target_ulong do_mftc0_tcbind(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - return env->CP0_TCBind[other_tc]; + if (other_tc == env->current_tc) + return env->active_tc.CP0_TCBind; + else + return env->tcs[other_tc].CP0_TCBind; } target_ulong do_mfc0_tcrestart (void) { - return env->PC[env->current_tc]; + return env->active_tc.PC; } target_ulong do_mftc0_tcrestart(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - return env->PC[other_tc]; + if (other_tc == env->current_tc) + return env->active_tc.PC; + else + return env->tcs[other_tc].PC; } target_ulong do_mfc0_tchalt (void) { - return env->CP0_TCHalt[env->current_tc]; + return env->active_tc.CP0_TCHalt; } target_ulong do_mftc0_tchalt(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - return env->CP0_TCHalt[other_tc]; + if (other_tc == env->current_tc) + return env->active_tc.CP0_TCHalt; + else + return env->tcs[other_tc].CP0_TCHalt; } target_ulong do_mfc0_tccontext (void) { - return env->CP0_TCContext[env->current_tc]; + return env->active_tc.CP0_TCContext; } target_ulong do_mftc0_tccontext(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - return env->CP0_TCContext[other_tc]; + if (other_tc == env->current_tc) + return env->active_tc.CP0_TCContext; + else + return env->tcs[other_tc].CP0_TCContext; } target_ulong do_mfc0_tcschedule (void) { - return env->CP0_TCSchedule[env->current_tc]; + return env->active_tc.CP0_TCSchedule; } target_ulong do_mftc0_tcschedule(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - return env->CP0_TCSchedule[other_tc]; + if (other_tc == env->current_tc) + return env->active_tc.CP0_TCSchedule; + else + return env->tcs[other_tc].CP0_TCSchedule; } target_ulong do_mfc0_tcschefback (void) { - return env->CP0_TCScheFBack[env->current_tc]; + return env->active_tc.CP0_TCScheFBack; } target_ulong do_mftc0_tcschefback(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - return env->CP0_TCScheFBack[other_tc]; + if (other_tc == env->current_tc) + return env->active_tc.CP0_TCScheFBack; + else + return env->tcs[other_tc].CP0_TCScheFBack; } target_ulong do_mfc0_count (void) @@ -762,15 +783,26 @@ target_ulong do_mfc0_count (void) target_ulong do_mftc0_entryhi(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + int32_t tcstatus; - return (env->CP0_EntryHi & ~0xff) | (env->CP0_TCStatus[other_tc] & 0xff); + if (other_tc == env->current_tc) + tcstatus = env->active_tc.CP0_TCStatus; + else + tcstatus = env->tcs[other_tc].CP0_TCStatus; + + return (env->CP0_EntryHi & ~0xff) | (tcstatus & 0xff); } target_ulong do_mftc0_status(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - uint32_t tcstatus = env->CP0_TCStatus[other_tc]; target_ulong t0; + int32_t tcstatus; + + if (other_tc == env->current_tc) + tcstatus = env->active_tc.CP0_TCStatus; + else + tcstatus = env->tcs[other_tc].CP0_TCStatus; t0 = env->CP0_Status & ~0xf1000018; t0 |= tcstatus & (0xf << CP0TCSt_TCU0); @@ -807,37 +839,42 @@ target_ulong do_mfc0_debug (void) target_ulong do_mftc0_debug(void) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + int32_t tcstatus; + + if (other_tc == env->current_tc) + tcstatus = env->active_tc.CP0_Debug_tcstatus; + else + tcstatus = env->tcs[other_tc].CP0_Debug_tcstatus; /* XXX: Might be wrong, check with EJTAG spec. */ return (env->CP0_Debug & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) | - (env->CP0_Debug_tcstatus[other_tc] & - ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))); + (tcstatus & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))); } #if defined(TARGET_MIPS64) target_ulong do_dmfc0_tcrestart (void) { - return env->PC[env->current_tc]; + return env->active_tc.PC; } target_ulong do_dmfc0_tchalt (void) { - return env->CP0_TCHalt[env->current_tc]; + return env->active_tc.CP0_TCHalt; } target_ulong do_dmfc0_tccontext (void) { - return env->CP0_TCContext[env->current_tc]; + return env->active_tc.CP0_TCContext; } target_ulong do_dmfc0_tcschedule (void) { - return env->CP0_TCSchedule[env->current_tc]; + return env->active_tc.CP0_TCSchedule; } target_ulong do_dmfc0_tcschefback (void) { - return env->CP0_TCScheFBack[env->current_tc]; + return env->active_tc.CP0_TCScheFBack; } target_ulong do_dmfc0_lladdr (void) @@ -955,11 +992,11 @@ void do_mtc0_tcstatus (target_ulong t0) uint32_t mask = env->CP0_TCStatus_rw_bitmask; uint32_t newval; - newval = (env->CP0_TCStatus[env->current_tc] & ~mask) | (t0 & mask); + newval = (env->active_tc.CP0_TCStatus & ~mask) | (t0 & mask); // TODO: Sync with CP0_Status. - env->CP0_TCStatus[env->current_tc] = newval; + env->active_tc.CP0_TCStatus = newval; } void do_mttc0_tcstatus (target_ulong t0) @@ -968,7 +1005,10 @@ void do_mttc0_tcstatus (target_ulong t0) // TODO: Sync with CP0_Status. - env->CP0_TCStatus[other_tc] = t0; + if (other_tc == env->current_tc) + env->active_tc.CP0_TCStatus = t0; + else + env->tcs[other_tc].CP0_TCStatus = t0; } void do_mtc0_tcbind (target_ulong t0) @@ -978,8 +1018,8 @@ void do_mtc0_tcbind (target_ulong t0) if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC)) mask |= (1 << CP0TCBd_CurVPE); - newval = (env->CP0_TCBind[env->current_tc] & ~mask) | (t0 & mask); - env->CP0_TCBind[env->current_tc] = newval; + newval = (env->active_tc.CP0_TCBind & ~mask) | (t0 & mask); + env->active_tc.CP0_TCBind = newval; } void do_mttc0_tcbind (target_ulong t0) @@ -990,14 +1030,19 @@ void do_mttc0_tcbind (target_ulong t0) if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC)) mask |= (1 << CP0TCBd_CurVPE); - newval = (env->CP0_TCBind[other_tc] & ~mask) | (t0 & mask); - env->CP0_TCBind[other_tc] = newval; + if (other_tc == env->current_tc) { + newval = (env->active_tc.CP0_TCBind & ~mask) | (t0 & mask); + env->active_tc.CP0_TCBind = newval; + } else { + newval = (env->tcs[other_tc].CP0_TCBind & ~mask) | (t0 & mask); + env->tcs[other_tc].CP0_TCBind = newval; + } } void do_mtc0_tcrestart (target_ulong t0) { - env->PC[env->current_tc] = t0; - env->CP0_TCStatus[env->current_tc] &= ~(1 << CP0TCSt_TDS); + env->active_tc.PC = t0; + env->active_tc.CP0_TCStatus &= ~(1 << CP0TCSt_TDS); env->CP0_LLAddr = 0ULL; /* MIPS16 not implemented. */ } @@ -1006,15 +1051,22 @@ void do_mttc0_tcrestart (target_ulong t0) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - env->PC[other_tc] = t0; - env->CP0_TCStatus[other_tc] &= ~(1 << CP0TCSt_TDS); - env->CP0_LLAddr = 0ULL; - /* MIPS16 not implemented. */ + if (other_tc == env->current_tc) { + env->active_tc.PC = t0; + env->active_tc.CP0_TCStatus &= ~(1 << CP0TCSt_TDS); + env->CP0_LLAddr = 0ULL; + /* MIPS16 not implemented. */ + } else { + env->tcs[other_tc].PC = t0; + env->tcs[other_tc].CP0_TCStatus &= ~(1 << CP0TCSt_TDS); + env->CP0_LLAddr = 0ULL; + /* MIPS16 not implemented. */ + } } void do_mtc0_tchalt (target_ulong t0) { - env->CP0_TCHalt[env->current_tc] = t0 & 0x1; + env->active_tc.CP0_TCHalt = t0 & 0x1; // TODO: Halt TC / Restart (if allocated+active) TC. } @@ -1025,43 +1077,55 @@ void do_mttc0_tchalt (target_ulong t0) // TODO: Halt TC / Restart (if allocated+active) TC. - env->CP0_TCHalt[other_tc] = t0; + if (other_tc == env->current_tc) + env->active_tc.CP0_TCHalt = t0; + else + env->tcs[other_tc].CP0_TCHalt = t0; } void do_mtc0_tccontext (target_ulong t0) { - env->CP0_TCContext[env->current_tc] = t0; + env->active_tc.CP0_TCContext = t0; } void do_mttc0_tccontext (target_ulong t0) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - env->CP0_TCContext[other_tc] = t0; + if (other_tc == env->current_tc) + env->active_tc.CP0_TCContext = t0; + else + env->tcs[other_tc].CP0_TCContext = t0; } void do_mtc0_tcschedule (target_ulong t0) { - env->CP0_TCSchedule[env->current_tc] = t0; + env->active_tc.CP0_TCSchedule = t0; } void do_mttc0_tcschedule (target_ulong t0) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - env->CP0_TCSchedule[other_tc] = t0; + if (other_tc == env->current_tc) + env->active_tc.CP0_TCSchedule = t0; + else + env->tcs[other_tc].CP0_TCSchedule = t0; } void do_mtc0_tcschefback (target_ulong t0) { - env->CP0_TCScheFBack[env->current_tc] = t0; + env->active_tc.CP0_TCScheFBack = t0; } void do_mttc0_tcschefback (target_ulong t0) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - env->CP0_TCScheFBack[other_tc] = t0; + if (other_tc == env->current_tc) + env->active_tc.CP0_TCScheFBack = t0; + else + env->tcs[other_tc].CP0_TCScheFBack = t0; } void do_mtc0_entrylo1 (target_ulong t0) @@ -1142,8 +1206,8 @@ void do_mtc0_entryhi (target_ulong t0) old = env->CP0_EntryHi; env->CP0_EntryHi = val; if (env->CP0_Config3 & (1 << CP0C3_MT)) { - uint32_t tcst = env->CP0_TCStatus[env->current_tc] & ~0xff; - env->CP0_TCStatus[env->current_tc] = tcst | (val & 0xff); + uint32_t tcst = env->active_tc.CP0_TCStatus & ~0xff; + env->active_tc.CP0_TCStatus = tcst | (val & 0xff); } /* If the ASID changes, flush qemu's TLB. */ if ((old & 0xFF) != (val & 0xFF)) @@ -1153,9 +1217,16 @@ void do_mtc0_entryhi (target_ulong t0) void do_mttc0_entryhi(target_ulong t0) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + int32_t tcstatus; env->CP0_EntryHi = (env->CP0_EntryHi & 0xff) | (t0 & ~0xff); - env->CP0_TCStatus[other_tc] = (env->CP0_TCStatus[other_tc] & ~0xff) | (t0 & 0xff); + if (other_tc == env->current_tc) { + tcstatus = (env->active_tc.CP0_TCStatus & ~0xff) | (t0 & 0xff); + env->active_tc.CP0_TCStatus = tcstatus; + } else { + tcstatus = (env->tcs[other_tc].CP0_TCStatus & ~0xff) | (t0 & 0xff); + env->tcs[other_tc].CP0_TCStatus = tcstatus; + } } void do_mtc0_compare (target_ulong t0) @@ -1180,13 +1251,16 @@ void do_mtc0_status (target_ulong t0) void do_mttc0_status(target_ulong t0) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - uint32_t tcstatus = env->CP0_TCStatus[other_tc]; + int32_t tcstatus = env->tcs[other_tc].CP0_TCStatus; env->CP0_Status = t0 & ~0xf1000018; tcstatus = (tcstatus & ~(0xf << CP0TCSt_TCU0)) | (t0 & (0xf << CP0St_CU0)); tcstatus = (tcstatus & ~(1 << CP0TCSt_TMX)) | ((t0 & (1 << CP0St_MX)) << (CP0TCSt_TMX - CP0St_MX)); tcstatus = (tcstatus & ~(0x3 << CP0TCSt_TKSU)) | ((t0 & (0x3 << CP0St_KSU)) << (CP0TCSt_TKSU - CP0St_KSU)); - env->CP0_TCStatus[other_tc] = tcstatus; + if (other_tc == env->current_tc) + env->active_tc.CP0_TCStatus = tcstatus; + else + env->tcs[other_tc].CP0_TCStatus = tcstatus; } void do_mtc0_intctl (target_ulong t0) @@ -1279,9 +1353,13 @@ void do_mtc0_debug (target_ulong t0) void do_mttc0_debug(target_ulong t0) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); + uint32_t val = t0 & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt)); /* XXX: Might be wrong, check with EJTAG spec. */ - env->CP0_Debug_tcstatus[other_tc] = t0 & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt)); + if (other_tc == env->current_tc) + env->active_tc.CP0_Debug_tcstatus = val; + else + env->tcs[other_tc].CP0_Debug_tcstatus = val; env->CP0_Debug = (env->CP0_Debug & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) | (t0 & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))); } @@ -1336,70 +1414,100 @@ target_ulong do_mftgpr(target_ulong t0, uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - return env->gpr[other_tc][sel]; + if (other_tc == env->current_tc) + return env->active_tc.gpr[sel]; + else + return env->tcs[other_tc].gpr[sel]; } target_ulong do_mftlo(target_ulong t0, uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - return env->LO[other_tc][sel]; + if (other_tc == env->current_tc) + return env->active_tc.LO[sel]; + else + return env->tcs[other_tc].LO[sel]; } target_ulong do_mfthi(target_ulong t0, uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - return env->HI[other_tc][sel]; + if (other_tc == env->current_tc) + return env->active_tc.HI[sel]; + else + return env->tcs[other_tc].HI[sel]; } target_ulong do_mftacx(target_ulong t0, uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - return env->ACX[other_tc][sel]; + if (other_tc == env->current_tc) + return env->active_tc.ACX[sel]; + else + return env->tcs[other_tc].ACX[sel]; } target_ulong do_mftdsp(target_ulong t0) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - return env->DSPControl[other_tc]; + if (other_tc == env->current_tc) + return env->active_tc.DSPControl; + else + return env->tcs[other_tc].DSPControl; } void do_mttgpr(target_ulong t0, uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - env->gpr[other_tc][sel] = t0; + if (other_tc == env->current_tc) + env->active_tc.gpr[sel] = t0; + else + env->tcs[other_tc].gpr[sel] = t0; } void do_mttlo(target_ulong t0, uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - env->LO[other_tc][sel] = t0; + if (other_tc == env->current_tc) + env->active_tc.LO[sel] = t0; + else + env->tcs[other_tc].LO[sel] = t0; } void do_mtthi(target_ulong t0, uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - env->HI[other_tc][sel] = t0; + if (other_tc == env->current_tc) + env->active_tc.HI[sel] = t0; + else + env->tcs[other_tc].HI[sel] = t0; } void do_mttacx(target_ulong t0, uint32_t sel) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - env->ACX[other_tc][sel] = t0; + if (other_tc == env->current_tc) + env->active_tc.ACX[sel] = t0; + else + env->tcs[other_tc].ACX[sel] = t0; } void do_mttdsp(target_ulong t0) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); - env->DSPControl[other_tc] = t0; + if (other_tc == env->current_tc) + env->active_tc.DSPControl = t0; + else + env->tcs[other_tc].DSPControl = t0; } /* MIPS MT functions */ @@ -1452,7 +1560,7 @@ target_ulong do_yield(target_ulong t0) /* No scheduling policy implemented. */ if (t0 != -2) { if (env->CP0_VPEControl & (1 << CP0VPECo_YSI) && - env->CP0_TCStatus[env->current_tc] & (1 << CP0TCSt_DT)) { + env->active_tc.CP0_TCStatus & (1 << CP0TCSt_DT)) { env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT); env->CP0_VPEControl |= 4 << CP0VPECo_EXCPT; do_raise_exception(EXCP_THREAD); @@ -1659,7 +1767,7 @@ target_ulong do_ei (target_ulong t0) void debug_pre_eret (void) { fprintf(logfile, "ERET: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx, - env->PC[env->current_tc], env->CP0_EPC); + env->active_tc.PC, env->CP0_EPC); if (env->CP0_Status & (1 << CP0St_ERL)) fprintf(logfile, " ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC); if (env->hflags & MIPS_HFLAG_DM) @@ -1670,7 +1778,7 @@ void debug_pre_eret (void) void debug_post_eret (void) { fprintf(logfile, " => PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx, - env->PC[env->current_tc], env->CP0_EPC); + env->active_tc.PC, env->CP0_EPC); if (env->CP0_Status & (1 << CP0St_ERL)) fprintf(logfile, " ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC); if (env->hflags & MIPS_HFLAG_DM) @@ -1688,10 +1796,10 @@ void do_eret (void) if (loglevel & CPU_LOG_EXEC) debug_pre_eret(); if (env->CP0_Status & (1 << CP0St_ERL)) { - env->PC[env->current_tc] = env->CP0_ErrorEPC; + env->active_tc.PC = env->CP0_ErrorEPC; env->CP0_Status &= ~(1 << CP0St_ERL); } else { - env->PC[env->current_tc] = env->CP0_EPC; + env->active_tc.PC = env->CP0_EPC; env->CP0_Status &= ~(1 << CP0St_EXL); } compute_hflags(env); @@ -1704,7 +1812,7 @@ void do_deret (void) { if (loglevel & CPU_LOG_EXEC) debug_pre_eret(); - env->PC[env->current_tc] = env->CP0_DEPC; + env->active_tc.PC = env->CP0_DEPC; env->hflags &= MIPS_HFLAG_DM; compute_hflags(env); if (loglevel & CPU_LOG_EXEC) @@ -1804,21 +1912,21 @@ void do_pmon (int function) function /= 2; switch (function) { case 2: /* TODO: char inbyte(int waitflag); */ - if (env->gpr[env->current_tc][4] == 0) - env->gpr[env->current_tc][2] = -1; + if (env->active_tc.gpr[4] == 0) + env->active_tc.gpr[2] = -1; /* Fall through */ case 11: /* TODO: char inbyte (void); */ - env->gpr[env->current_tc][2] = -1; + env->active_tc.gpr[2] = -1; break; case 3: case 12: - printf("%c", (char)(env->gpr[env->current_tc][4] & 0xFF)); + printf("%c", (char)(env->active_tc.gpr[4] & 0xFF)); break; case 17: break; case 158: { - unsigned char *fmt = (void *)(unsigned long)env->gpr[env->current_tc][4]; + unsigned char *fmt = (void *)(unsigned long)env->active_tc.gpr[4]; printf("%s", fmt); } break; diff --git a/target-mips/translate.c b/target-mips/translate.c index 41a27b4..c4d91f0 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -423,7 +423,7 @@ enum { }; /* global register indices */ -static TCGv cpu_env, current_tc_gprs, current_tc_hi, current_fpu; +static TCGv cpu_env, current_fpu; /* FPU TNs, global for now. */ static TCGv fpu32_T[3], fpu64_T[3], fpu32h_T[3]; @@ -563,40 +563,40 @@ static inline void gen_load_gpr (TCGv t, int reg) if (reg == 0) tcg_gen_movi_tl(t, 0); else - tcg_gen_ld_tl(t, current_tc_gprs, sizeof(target_ulong) * reg); + tcg_gen_ld_tl(t, cpu_env, offsetof(CPUState, active_tc.gpr) + + sizeof(target_ulong) * reg); } static inline void gen_store_gpr (TCGv t, int reg) { if (reg != 0) - tcg_gen_st_tl(t, current_tc_gprs, sizeof(target_ulong) * reg); + tcg_gen_st_tl(t, cpu_env, offsetof(CPUState, active_tc.gpr) + + sizeof(target_ulong) * reg); } /* Moves to/from HI and LO registers. */ static inline void gen_load_LO (TCGv t, int reg) { - tcg_gen_ld_tl(t, current_tc_hi, - offsetof(CPUState, LO) - - offsetof(CPUState, HI) - + sizeof(target_ulong) * reg); + tcg_gen_ld_tl(t, cpu_env, offsetof(CPUState, active_tc.LO) + + sizeof(target_ulong) * reg); } static inline void gen_store_LO (TCGv t, int reg) { - tcg_gen_st_tl(t, current_tc_hi, - offsetof(CPUState, LO) - - offsetof(CPUState, HI) - + sizeof(target_ulong) * reg); + tcg_gen_st_tl(t, cpu_env, offsetof(CPUState, active_tc.LO) + + sizeof(target_ulong) * reg); } static inline void gen_load_HI (TCGv t, int reg) { - tcg_gen_ld_tl(t, current_tc_hi, sizeof(target_ulong) * reg); + tcg_gen_ld_tl(t, cpu_env, offsetof(CPUState, active_tc.HI) + + sizeof(target_ulong) * reg); } static inline void gen_store_HI (TCGv t, int reg) { - tcg_gen_st_tl(t, current_tc_hi, sizeof(target_ulong) * reg); + tcg_gen_st_tl(t, cpu_env, offsetof(CPUState, active_tc.HI) + + sizeof(target_ulong) * reg); } /* Moves to/from shadow registers. */ @@ -805,38 +805,18 @@ OP_CONDZ(ltz, TCG_COND_LT); static inline void gen_save_pc(target_ulong pc) { TCGv r_tmp = tcg_temp_new(TCG_TYPE_TL); - TCGv r_tc_off = tcg_temp_new(TCG_TYPE_I32); - TCGv r_tc_off_ptr = tcg_temp_new(TCG_TYPE_PTR); - TCGv r_ptr = tcg_temp_new(TCG_TYPE_PTR); tcg_gen_movi_tl(r_tmp, pc); - tcg_gen_ld_i32(r_tc_off, cpu_env, offsetof(CPUState, current_tc)); - tcg_gen_muli_i32(r_tc_off, r_tc_off, sizeof(target_ulong)); - tcg_gen_ext_i32_ptr(r_tc_off_ptr, r_tc_off); - tcg_gen_add_ptr(r_ptr, cpu_env, r_tc_off_ptr); - tcg_gen_st_tl(r_tmp, r_ptr, offsetof(CPUState, PC)); - tcg_temp_free(r_tc_off); - tcg_temp_free(r_tc_off_ptr); - tcg_temp_free(r_ptr); + tcg_gen_st_tl(r_tmp, cpu_env, offsetof(CPUState, active_tc.PC)); tcg_temp_free(r_tmp); } static inline void gen_breg_pc(void) { TCGv r_tmp = tcg_temp_new(TCG_TYPE_TL); - TCGv r_tc_off = tcg_temp_new(TCG_TYPE_I32); - TCGv r_tc_off_ptr = tcg_temp_new(TCG_TYPE_PTR); - TCGv r_ptr = tcg_temp_new(TCG_TYPE_PTR); tcg_gen_ld_tl(r_tmp, cpu_env, offsetof(CPUState, btarget)); - tcg_gen_ld_i32(r_tc_off, cpu_env, offsetof(CPUState, current_tc)); - tcg_gen_muli_i32(r_tc_off, r_tc_off, sizeof(target_ulong)); - tcg_gen_ext_i32_ptr(r_tc_off_ptr, r_tc_off); - tcg_gen_add_ptr(r_ptr, cpu_env, r_tc_off_ptr); - tcg_gen_st_tl(r_tmp, r_ptr, offsetof(CPUState, PC)); - tcg_temp_free(r_tc_off); - tcg_temp_free(r_tc_off_ptr); - tcg_temp_free(r_ptr); + tcg_gen_st_tl(r_tmp, cpu_env, offsetof(CPUState, active_tc.PC)); tcg_temp_free(r_tmp); } @@ -5202,8 +5182,8 @@ static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd, TCGv t0 = tcg_temp_local_new(TCG_TYPE_TL); if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 && - ((env->CP0_TCBind[other_tc] & (0xf << CP0TCBd_CurVPE)) != - (env->CP0_TCBind[env->current_tc] & (0xf << CP0TCBd_CurVPE)))) + ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) != + (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) tcg_gen_movi_tl(t0, -1); else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) > (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) @@ -5371,8 +5351,8 @@ static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt, gen_load_gpr(t0, rt); if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 && - ((env->CP0_TCBind[other_tc] & (0xf << CP0TCBd_CurVPE)) != - (env->CP0_TCBind[env->current_tc] & (0xf << CP0TCBd_CurVPE)))) + ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) != + (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) /* NOP */ ; else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) > (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) @@ -8009,8 +7989,8 @@ void dump_fpu (CPUState *env) "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx " LO=0x" TARGET_FMT_lx " ds %04x " TARGET_FMT_lx " %04x\n", - env->PC[env->current_tc], env->HI[env->current_tc][0], - env->LO[env->current_tc][0], env->hflags, env->btarget, + env->active_tc.PC, env->active_tc.HI[0], + env->active_tc.LO[0], env->hflags, env->btarget, env->bcond); fpu_dump_state(env, logfile, fprintf, 0); } @@ -8028,18 +8008,18 @@ void cpu_mips_check_sign_extensions (CPUState *env, FILE *f, { int i; - if (!SIGN_EXT_P(env->PC[env->current_tc])) - cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->PC[env->current_tc]); - if (!SIGN_EXT_P(env->HI[env->current_tc][0])) - cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->HI[env->current_tc][0]); - if (!SIGN_EXT_P(env->LO[env->current_tc][0])) - cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->LO[env->current_tc][0]); + if (!SIGN_EXT_P(env->active_tc.PC)) + cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC); + if (!SIGN_EXT_P(env->active_tc.HI[0])) + cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]); + if (!SIGN_EXT_P(env->active_tc.LO[0])) + cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]); if (!SIGN_EXT_P(env->btarget)) cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget); for (i = 0; i < 32; i++) { - if (!SIGN_EXT_P(env->gpr[env->current_tc][i])) - cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->gpr[env->current_tc][i]); + if (!SIGN_EXT_P(env->active_tc.gpr[i])) + cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]); } if (!SIGN_EXT_P(env->CP0_EPC)) @@ -8056,11 +8036,11 @@ void cpu_dump_state (CPUState *env, FILE *f, int i; cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx " LO=0x" TARGET_FMT_lx " ds %04x " TARGET_FMT_lx " %d\n", - env->PC[env->current_tc], env->HI[env->current_tc], env->LO[env->current_tc], env->hflags, env->btarget, env->bcond); + env->active_tc.PC, env->active_tc.HI, env->active_tc.LO, env->hflags, env->btarget, env->bcond); for (i = 0; i < 32; i++) { if ((i & 3) == 0) cpu_fprintf(f, "GPR%02d:", i); - cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->gpr[env->current_tc][i]); + cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]); if ((i & 3) == 3) cpu_fprintf(f, "\n"); } @@ -8085,14 +8065,6 @@ static void mips_tcg_init(void) return; cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env"); - current_tc_gprs = tcg_global_mem_new(TCG_TYPE_PTR, - TCG_AREG0, - offsetof(CPUState, current_tc_gprs), - "current_tc_gprs"); - current_tc_hi = tcg_global_mem_new(TCG_TYPE_PTR, - TCG_AREG0, - offsetof(CPUState, current_tc_hi), - "current_tc_hi"); current_fpu = tcg_global_mem_new(TCG_TYPE_PTR, TCG_AREG0, offsetof(CPUState, fpu), @@ -8149,11 +8121,11 @@ void cpu_reset (CPUMIPSState *env) if (env->hflags & MIPS_HFLAG_BMASK) { /* If the exception was raised from a delay slot, * come back to the jump. */ - env->CP0_ErrorEPC = env->PC[env->current_tc] - 4; + env->CP0_ErrorEPC = env->active_tc.PC - 4; } else { - env->CP0_ErrorEPC = env->PC[env->current_tc]; + env->CP0_ErrorEPC = env->active_tc.PC; } - env->PC[env->current_tc] = (int32_t)0xBFC00000; + env->active_tc.PC = (int32_t)0xBFC00000; env->CP0_Wired = 0; /* SMP not implemented */ env->CP0_EBase = 0x80000000; @@ -8187,7 +8159,7 @@ void cpu_reset (CPUMIPSState *env) void gen_pc_load(CPUState *env, TranslationBlock *tb, unsigned long searched_pc, int pc_pos, void *puc) { - env->PC[env->current_tc] = gen_opc_pc[pc_pos]; + env->active_tc.PC = gen_opc_pc[pc_pos]; env->hflags &= ~MIPS_HFLAG_BMASK; env->hflags |= gen_opc_hflags[pc_pos]; } diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c index d84bee0..b7d68cc 100644 --- a/target-mips/translate_init.c +++ b/target-mips/translate_init.c @@ -546,8 +546,6 @@ static int cpu_mips_register (CPUMIPSState *env, const mips_def_t *def) env->CP0_TCStatus_rw_bitmask = def->CP0_TCStatus_rw_bitmask; env->CP0_SRSCtl = def->CP0_SRSCtl; env->current_tc = 0; - env->current_tc_gprs = &env->gpr[env->current_tc][0]; - env->current_tc_hi = &env->HI[env->current_tc][0]; env->SEGBITS = def->SEGBITS; env->SEGMask = (target_ulong)((1ULL << def->SEGBITS) - 1); #if defined(TARGET_MIPS64) -- 1.7.9.5