More efficient target register / TC accesses.

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4794 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
ths 2008-06-27 10:02:35 +00:00
parent a37ee56cb7
commit b5dc7732e1
16 changed files with 327 additions and 246 deletions

View File

@ -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 */

View File

@ -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

View File

@ -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) {

View File

@ -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);

View File

@ -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)
{

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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;

View File

@ -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];

View File

@ -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)");

View File

@ -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

View File

@ -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);
}

View File

@ -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;

View File

@ -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];
}

View File

@ -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)