summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cpu-exec.c2
-rw-r--r--gdbstub.c34
-rw-r--r--hw/mips_r4k.c2
-rw-r--r--hw/mips_timer.c2
-rw-r--r--linux-user/main.c24
-rw-r--r--linux-user/signal.c36
-rw-r--r--linux-user/syscall.c7
-rw-r--r--monitor.c4
-rw-r--r--target-mips/cpu.h239
-rw-r--r--target-mips/exec.h39
-rw-r--r--target-mips/fop_template.c20
-rw-r--r--target-mips/helper.c57
-rw-r--r--target-mips/op.c875
-rw-r--r--target-mips/op_helper.c605
-rw-r--r--target-mips/op_template.c23
-rw-r--r--target-mips/translate.c949
-rw-r--r--target-mips/translate_init.c211
-rw-r--r--translate-all.c2
18 files changed, 2305 insertions, 826 deletions
diff --git a/cpu-exec.c b/cpu-exec.c
index 543ec09ef7..4f1cee616e 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -194,7 +194,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;
+ pc = env->PC[env->current_tc];
#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 48c0c56c84..37347da0b7 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -559,17 +559,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[i]);
+ *(target_ulong *)ptr = tswapl(env->gpr[i][env->current_tc]);
ptr += sizeof(target_ulong);
}
*(target_ulong *)ptr = tswapl(env->CP0_Status);
ptr += sizeof(target_ulong);
- *(target_ulong *)ptr = tswapl(env->LO);
+ *(target_ulong *)ptr = tswapl(env->LO[0][env->current_tc]);
ptr += sizeof(target_ulong);
- *(target_ulong *)ptr = tswapl(env->HI);
+ *(target_ulong *)ptr = tswapl(env->HI[0][env->current_tc]);
ptr += sizeof(target_ulong);
*(target_ulong *)ptr = tswapl(env->CP0_BadVAddr);
@@ -578,21 +578,21 @@ static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
*(target_ulong *)ptr = tswapl(env->CP0_Cause);
ptr += sizeof(target_ulong);
- *(target_ulong *)ptr = tswapl(env->PC);
+ *(target_ulong *)ptr = tswapl(env->PC[env->current_tc]);
ptr += sizeof(target_ulong);
if (env->CP0_Config1 & (1 << CP0C1_FP))
{
for (i = 0; i < 32; i++)
{
- *(target_ulong *)ptr = tswapl(env->fpr[i].fs[FP_ENDIAN_IDX]);
+ *(target_ulong *)ptr = tswapl(env->fpu->fpr[i].fs[FP_ENDIAN_IDX]);
ptr += sizeof(target_ulong);
}
- *(target_ulong *)ptr = tswapl(env->fcr31);
+ *(target_ulong *)ptr = tswapl(env->fpu->fcr31);
ptr += sizeof(target_ulong);
- *(target_ulong *)ptr = tswapl(env->fcr0);
+ *(target_ulong *)ptr = tswapl(env->fpu->fcr0);
ptr += sizeof(target_ulong);
}
@@ -611,7 +611,7 @@ static unsigned int ieee_rm[] =
float_round_down
};
#define RESTORE_ROUNDING_MODE \
- set_float_rounding_mode(ieee_rm[env->fcr31 & 3], &env->fp_status)
+ set_float_rounding_mode(ieee_rm[env->fpu->fcr31 & 3], &env->fpu->fp_status)
static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
{
@@ -621,17 +621,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[i] = tswapl(*(target_ulong *)ptr);
+ env->gpr[i][env->current_tc] = tswapl(*(target_ulong *)ptr);
ptr += sizeof(target_ulong);
}
env->CP0_Status = tswapl(*(target_ulong *)ptr);
ptr += sizeof(target_ulong);
- env->LO = tswapl(*(target_ulong *)ptr);
+ env->LO[0][env->current_tc] = tswapl(*(target_ulong *)ptr);
ptr += sizeof(target_ulong);
- env->HI = tswapl(*(target_ulong *)ptr);
+ env->HI[0][env->current_tc] = tswapl(*(target_ulong *)ptr);
ptr += sizeof(target_ulong);
env->CP0_BadVAddr = tswapl(*(target_ulong *)ptr);
@@ -640,21 +640,21 @@ 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 = tswapl(*(target_ulong *)ptr);
+ env->PC[env->current_tc] = tswapl(*(target_ulong *)ptr);
ptr += sizeof(target_ulong);
if (env->CP0_Config1 & (1 << CP0C1_FP))
{
for (i = 0; i < 32; i++)
{
- env->fpr[i].fs[FP_ENDIAN_IDX] = tswapl(*(target_ulong *)ptr);
+ env->fpu->fpr[i].fs[FP_ENDIAN_IDX] = tswapl(*(target_ulong *)ptr);
ptr += sizeof(target_ulong);
}
- env->fcr31 = tswapl(*(target_ulong *)ptr) & 0x0183FFFF;
+ env->fpu->fcr31 = tswapl(*(target_ulong *)ptr) & 0x0183FFFF;
ptr += sizeof(target_ulong);
- env->fcr0 = tswapl(*(target_ulong *)ptr);
+ env->fpu->fcr0 = tswapl(*(target_ulong *)ptr);
ptr += sizeof(target_ulong);
/* set rounding mode */
@@ -775,7 +775,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 = addr;
+ env->PC[env->current_tc] = addr;
#endif
}
#ifdef CONFIG_USER_ONLY
@@ -799,7 +799,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 = addr;
+ env->PC[env->current_tc] = addr;
#endif
}
cpu_single_step(env, 1);
diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c
index 2208922a75..82782273b5 100644
--- a/hw/mips_r4k.c
+++ b/hw/mips_r4k.c
@@ -77,7 +77,7 @@ void load_kernel (CPUState *env, int ram_size, const char *kernel_filename,
if (kernel_size >= 0) {
if ((entry & ~0x7fffffffULL) == 0x80000000)
entry = (int32_t)entry;
- env->PC = entry;
+ env->PC[env->current_tc] = entry;
} else {
fprintf(stderr, "qemu: could not load kernel '%s'\n",
kernel_filename);
diff --git a/hw/mips_timer.c b/hw/mips_timer.c
index 6a517e1841..2fe5e29c58 100644
--- a/hw/mips_timer.c
+++ b/hw/mips_timer.c
@@ -10,7 +10,7 @@ uint32_t cpu_mips_get_random (CPUState *env)
static uint32_t seed = 0;
uint32_t idx;
seed = seed * 314159 + 1;
- idx = (seed >> 16) % (env->nb_tlb - env->CP0_Wired) + env->CP0_Wired;
+ idx = (seed >> 16) % (env->tlb->nb_tlb - env->CP0_Wired) + env->CP0_Wired;
return idx;
}
diff --git a/linux-user/main.c b/linux-user/main.c
index 32fa43d476..edcb68b8d4 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -1374,8 +1374,8 @@ void cpu_loop(CPUMIPSState *env)
trapnr = cpu_mips_exec(env);
switch(trapnr) {
case EXCP_SYSCALL:
- syscall_num = env->gpr[2] - 4000;
- env->PC += 4;
+ syscall_num = env->gpr[2][env->current_tc] - 4000;
+ env->PC[env->current_tc] += 4;
if (syscall_num >= sizeof(mips_syscall_args)) {
ret = -ENOSYS;
} else {
@@ -1384,7 +1384,7 @@ void cpu_loop(CPUMIPSState *env)
target_ulong arg5 = 0, arg6 = 0, arg7 = 0, arg8 = 0;
nb_args = mips_syscall_args[syscall_num];
- sp_reg = env->gpr[29];
+ sp_reg = env->gpr[29][env->current_tc];
switch (nb_args) {
/* these arguments are taken from the stack */
case 8: arg8 = tgetl(sp_reg + 28);
@@ -1394,18 +1394,20 @@ void cpu_loop(CPUMIPSState *env)
default:
break;
}
- ret = do_syscall(env, env->gpr[2],
- env->gpr[4], env->gpr[5],
- env->gpr[6], env->gpr[7],
+ ret = do_syscall(env, env->gpr[2][env->current_tc],
+ env->gpr[4][env->current_tc],
+ env->gpr[5][env->current_tc],
+ env->gpr[6][env->current_tc],
+ env->gpr[7][env->current_tc],
arg5, arg6/*, arg7, arg8*/);
}
if ((unsigned int)ret >= (unsigned int)(-1133)) {
- env->gpr[7] = 1; /* error flag */
+ env->gpr[7][env->current_tc] = 1; /* error flag */
ret = -ret;
} else {
- env->gpr[7] = 0; /* error flag */
+ env->gpr[7][env->current_tc] = 0; /* error flag */
}
- env->gpr[2] = ret;
+ env->gpr[2][env->current_tc] = ret;
break;
case EXCP_TLBL:
case EXCP_TLBS:
@@ -2053,9 +2055,9 @@ int main(int argc, char **argv)
cpu_mips_register(env, def);
for(i = 0; i < 32; i++) {
- env->gpr[i] = regs->regs[i];
+ env->gpr[i][env->current_tc] = regs->regs[i];
}
- env->PC = regs->cp0_epc;
+ env->PC[env->current_tc] = regs->cp0_epc;
}
#elif defined(TARGET_SH4)
{
diff --git a/linux-user/signal.c b/linux-user/signal.c
index eea73470fa..f73d50516f 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1686,10 +1686,10 @@ setup_sigcontext(CPUState *regs, struct target_sigcontext *sc)
{
int err = 0;
- err |= __put_user(regs->PC, &sc->sc_pc);
+ err |= __put_user(regs->PC[regs->current_tc], &sc->sc_pc);
-#define save_gp_reg(i) do { \
- err |= __put_user(regs->gpr[i], &sc->sc_regs[i]); \
+#define save_gp_reg(i) do { \
+ err |= __put_user(regs->gpr[i][regs->current_tc], &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);
@@ -1702,8 +1702,8 @@ setup_sigcontext(CPUState *regs, struct target_sigcontext *sc)
save_gp_reg(31);
#undef save_gp_reg
- err |= __put_user(regs->HI, &sc->sc_mdhi);
- err |= __put_user(regs->LO, &sc->sc_mdlo);
+ err |= __put_user(regs->HI[0][regs->current_tc], &sc->sc_mdhi);
+ err |= __put_user(regs->LO[0][regs->current_tc], &sc->sc_mdlo);
/* Not used yet, but might be useful if we ever have DSP suppport */
#if 0
@@ -1763,11 +1763,11 @@ restore_sigcontext(CPUState *regs, struct target_sigcontext *sc)
err |= __get_user(regs->CP0_EPC, &sc->sc_pc);
- err |= __get_user(regs->HI, &sc->sc_mdhi);
- err |= __get_user(regs->LO, &sc->sc_mdlo);
+ err |= __get_user(regs->HI[0][regs->current_tc], &sc->sc_mdhi);
+ err |= __get_user(regs->LO[0][regs->current_tc], &sc->sc_mdlo);
-#define restore_gp_reg(i) do { \
- err |= __get_user(regs->gpr[i], &sc->sc_regs[i]); \
+#define restore_gp_reg(i) do { \
+ err |= __get_user(regs->gpr[i][regs->current_tc], &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);
@@ -1833,7 +1833,7 @@ get_sigframe(struct emulated_sigaction *ka, CPUState *regs, size_t frame_size)
unsigned long sp;
/* Default to using normal stack */
- sp = regs->gpr[29];
+ sp = regs->gpr[29][regs->current_tc];
/*
* FPU emulator may have it's own trampoline active just
@@ -1881,15 +1881,15 @@ static void setup_frame(int sig, struct emulated_sigaction * ka,
* $25 and PC point to the signal handler, $29 points to the
* struct sigframe.
*/
- regs->gpr[ 4] = sig;
- regs->gpr[ 5] = 0;
- regs->gpr[ 6] = h2g(&frame->sf_sc);
- regs->gpr[29] = h2g(frame);
- regs->gpr[31] = h2g(frame->sf_code);
+ regs->gpr[ 4][regs->current_tc] = sig;
+ regs->gpr[ 5][regs->current_tc] = 0;
+ regs->gpr[ 6][regs->current_tc] = h2g(&frame->sf_sc);
+ regs->gpr[29][regs->current_tc] = h2g(frame);
+ regs->gpr[31][regs->current_tc] = h2g(frame->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->gpr[25] = ka->sa._sa_handler;
+ regs->PC[regs->current_tc] = regs->gpr[25][regs->current_tc] = ka->sa._sa_handler;
return;
give_sigsegv:
@@ -1907,7 +1907,7 @@ long do_sigreturn(CPUState *regs)
#if defined(DEBUG_SIGNAL)
fprintf(stderr, "do_sigreturn\n");
#endif
- frame = (struct sigframe *) regs->gpr[29];
+ frame = (struct sigframe *) regs->gpr[29][regs->current_tc];
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
@@ -1934,7 +1934,7 @@ long do_sigreturn(CPUState *regs)
/* Unreached */
#endif
- regs->PC = regs->CP0_EPC;
+ regs->PC[regs->current_tc] = 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 e23a684e76..cd956aa1ac 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -2189,8 +2189,8 @@ int do_fork(CPUState *env, unsigned int flags, unsigned long newsp)
/* ??? is this sufficient? */
#elif defined(TARGET_MIPS)
if (!newsp)
- newsp = env->gpr[29];
- new_env->gpr[29] = newsp;
+ newsp = env->gpr[29][env->current_tc];
+ new_env->gpr[29][env->current_tc] = newsp;
#elif defined(TARGET_PPC)
if (!newsp)
newsp = env->gpr[1];
@@ -2777,7 +2777,8 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
ret = get_errno(pipe(host_pipe));
if (!is_error(ret)) {
#if defined(TARGET_MIPS)
- ((CPUMIPSState*)cpu_env)->gpr[3] = host_pipe[1];
+ CPUMIPSState *env = (CPUMIPSState*)cpu_env;
+ env->gpr[3][env->current_tc] = host_pipe[1];
ret = host_pipe[0];
#else
tput32(arg1, host_pipe[0]);
diff --git a/monitor.c b/monitor.c
index 3b9408b557..9ff63130dc 100644
--- a/monitor.c
+++ b/monitor.c
@@ -309,6 +309,10 @@ static void do_info_cpus(void)
term_printf(" pc=0x" TARGET_FMT_lx " npc=0x" TARGET_FMT_lx, env->pc, env->npc);
if (env->halted)
term_printf(" (halted)");
+#elif defined(TARGET_MIPS)
+ term_printf(" PC=0x" TARGET_FMT_lx, env->PC[env->current_tc]);
+ if (env->halted)
+ term_printf(" (halted)");
#endif
term_printf("\n");
}
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index f5f35e1223..f8b4b18583 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -17,21 +17,7 @@ typedef unsigned char uint_fast8_t;
typedef unsigned int uint_fast16_t;
#endif
-typedef union fpr_t fpr_t;
-union fpr_t {
- float64 fd; /* ieee double precision */
- float32 fs[2];/* ieee single precision */
- uint64_t d; /* binary double fixed-point */
- uint32_t w[2]; /* binary single fixed-point */
-};
-/* define FP_ENDIAN_IDX to access the same location
- * in the fpr_t union regardless of the host endianess
- */
-#if defined(WORDS_BIGENDIAN)
-# define FP_ENDIAN_IDX 1
-#else
-# define FP_ENDIAN_IDX 0
-#endif
+struct CPUMIPSState;
typedef struct r4k_tlb_t r4k_tlb_t;
struct r4k_tlb_t {
@@ -48,20 +34,40 @@ struct r4k_tlb_t {
target_ulong PFN[2];
};
-typedef struct mips_def_t mips_def_t;
+typedef struct CPUMIPSTLBContext CPUMIPSTLBContext;
+struct CPUMIPSTLBContext {
+ uint32_t nb_tlb;
+ uint32_t tlb_in_use;
+ int (*map_address) (struct CPUMIPSState *env, target_ulong *physical, int *prot, target_ulong address, int rw, int access_type);
+ void (*do_tlbwi) (void);
+ void (*do_tlbwr) (void);
+ void (*do_tlbp) (void);
+ void (*do_tlbr) (void);
+ union {
+ struct {
+ r4k_tlb_t tlb[MIPS_TLB_MAX];
+ } r4k;
+ } mmu;
+};
-typedef struct CPUMIPSState CPUMIPSState;
-struct CPUMIPSState {
- /* General integer registers */
- target_ulong gpr[32];
- /* Special registers */
- target_ulong PC;
-#if TARGET_LONG_BITS > HOST_LONG_BITS
- target_ulong t0;
- target_ulong t1;
- target_ulong t2;
+typedef union fpr_t fpr_t;
+union fpr_t {
+ float64 fd; /* ieee double precision */
+ float32 fs[2];/* ieee single precision */
+ uint64_t d; /* binary double fixed-point */
+ uint32_t w[2]; /* binary single fixed-point */
+};
+/* define FP_ENDIAN_IDX to access the same location
+ * in the fpr_t union regardless of the host endianess
+ */
+#if defined(WORDS_BIGENDIAN)
+# define FP_ENDIAN_IDX 1
+#else
+# define FP_ENDIAN_IDX 0
#endif
- target_ulong HI, LO;
+
+typedef struct CPUMIPSFPUContext CPUMIPSFPUContext;
+struct CPUMIPSFPUContext {
/* Floating point registers */
fpr_t fpr[32];
#ifndef USE_HOST_FLOAT_REGS
@@ -99,30 +105,161 @@ struct CPUMIPSState {
#define FP_DIV0 8
#define FP_INVALID 16
#define FP_UNIMPLEMENTED 32
+};
+
+typedef struct CPUMIPSMVPContext CPUMIPSMVPContext;
+struct CPUMIPSMVPContext {
+ int32_t CP0_MVPControl;
+#define CP0MVPCo_CPA 3
+#define CP0MVPCo_STLB 2
+#define CP0MVPCo_VPC 1
+#define CP0MVPCo_EVP 0
+ int32_t CP0_MVPConf0;
+#define CP0MVPC0_M 31
+#define CP0MVPC0_TLBS 29
+#define CP0MVPC0_GS 28
+#define CP0MVPC0_PCP 27
+#define CP0MVPC0_PTLBE 16
+#define CP0MVPC0_TCA 15
+#define CP0MVPC0_PVPE 10
+#define CP0MVPC0_PTC 0
+ int32_t CP0_MVPConf1;
+#define CP0MVPC1_CIM 31
+#define CP0MVPC1_CIF 30
+#define CP0MVPC1_PCX 20
+#define CP0MVPC1_PCP2 10
+#define CP0MVPC1_PCP1 0
+};
+
+typedef struct mips_def_t mips_def_t;
+
+#define MIPS_SHADOW_SET_MAX 16
+#define MIPS_TC_MAX 5
+#define MIPS_DSP_ACC 4
+
+typedef struct CPUMIPSState CPUMIPSState;
+struct CPUMIPSState {
+ /* General integer registers */
+ target_ulong gpr[32][MIPS_SHADOW_SET_MAX];
+ /* Special registers */
+ target_ulong PC[MIPS_TC_MAX];
+#if TARGET_LONG_BITS > HOST_LONG_BITS
+ target_ulong t0;
+ target_ulong t1;
+ target_ulong t2;
+#endif
+ target_ulong HI[MIPS_DSP_ACC][MIPS_TC_MAX];
+ target_ulong LO[MIPS_DSP_ACC][MIPS_TC_MAX];
+ target_ulong ACX[MIPS_DSP_ACC][MIPS_TC_MAX];
+ target_ulong DSPControl[MIPS_TC_MAX];
+
+ CPUMIPSMVPContext *mvp;
+ CPUMIPSTLBContext *tlb;
+ CPUMIPSFPUContext *fpu;
+ uint32_t current_tc;
- uint32_t nb_tlb;
- uint32_t tlb_in_use;
uint32_t SEGBITS;
target_ulong SEGMask;
- int (*map_address) (CPUMIPSState *env, target_ulong *physical, int *prot, target_ulong address, int rw, int access_type);
- void (*do_tlbwi) (void);
- void (*do_tlbwr) (void);
- void (*do_tlbp) (void);
- void (*do_tlbr) (void);
- union {
- struct {
- r4k_tlb_t tlb[MIPS_TLB_MAX];
- } r4k;
- } mmu;
int32_t CP0_Index;
+ /* CP0_MVP* are per MVP registers. */
int32_t CP0_Random;
+ int32_t CP0_VPEControl;
+#define CP0VPECo_YSI 21
+#define CP0VPECo_GSI 20
+#define CP0VPECo_EXCPT 16
+#define CP0VPECo_TE 15
+#define CP0VPECo_TargTC 0
+ int32_t CP0_VPEConf0;
+#define CP0VPEC0_M 31
+#define CP0VPEC0_XTC 21
+#define CP0VPEC0_TCS 19
+#define CP0VPEC0_SCS 18
+#define CP0VPEC0_DSC 17
+#define CP0VPEC0_ICS 16
+#define CP0VPEC0_MVP 1
+#define CP0VPEC0_VPA 0
+ int32_t CP0_VPEConf1;
+#define CP0VPEC1_NCX 20
+#define CP0VPEC1_NCP2 10
+#define CP0VPEC1_NCP1 0
+ target_ulong CP0_YQMask;
+ target_ulong CP0_VPESchedule;
+ target_ulong CP0_VPEScheFBack;
+ int32_t CP0_VPEOpt;
+#define CP0VPEOpt_IWX7 15
+#define CP0VPEOpt_IWX6 14
+#define CP0VPEOpt_IWX5 13
+#define CP0VPEOpt_IWX4 12
+#define CP0VPEOpt_IWX3 11
+#define CP0VPEOpt_IWX2 10
+#define CP0VPEOpt_IWX1 9
+#define CP0VPEOpt_IWX0 8
+#define CP0VPEOpt_DWX7 7
+#define CP0VPEOpt_DWX6 6
+#define CP0VPEOpt_DWX5 5
+#define CP0VPEOpt_DWX4 4
+#define CP0VPEOpt_DWX3 3
+#define CP0VPEOpt_DWX2 2
+#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;
int32_t CP0_PageGrain;
int32_t CP0_Wired;
+ int32_t CP0_SRSConf0_rw_bitmask;
+ int32_t CP0_SRSConf0;
+#define CP0SRSC0_M 31
+#define CP0SRSC0_SRS3 20
+#define CP0SRSC0_SRS2 10
+#define CP0SRSC0_SRS1 0
+ int32_t CP0_SRSConf1_rw_bitmask;
+ int32_t CP0_SRSConf1;
+#define CP0SRSC1_M 31
+#define CP0SRSC1_SRS6 20
+#define CP0SRSC1_SRS5 10
+#define CP0SRSC1_SRS4 0
+ int32_t CP0_SRSConf2_rw_bitmask;
+ int32_t CP0_SRSConf2;
+#define CP0SRSC2_M 31
+#define CP0SRSC2_SRS9 20
+#define CP0SRSC2_SRS8 10
+#define CP0SRSC2_SRS7 0
+ int32_t CP0_SRSConf3_rw_bitmask;
+ int32_t CP0_SRSConf3;
+#define CP0SRSC3_M 31
+#define CP0SRSC3_SRS12 20
+#define CP0SRSC3_SRS11 10
+#define CP0SRSC3_SRS10 0
+ int32_t CP0_SRSConf4_rw_bitmask;
+ int32_t CP0_SRSConf4;
+#define CP0SRSC4_SRS15 20
+#define CP0SRSC4_SRS14 10
+#define CP0SRSC4_SRS13 0
int32_t CP0_HWREna;
target_ulong CP0_BadVAddr;
int32_t CP0_Count;
@@ -152,8 +289,24 @@ struct CPUMIPSState {
#define CP0St_EXL 1
#define CP0St_IE 0
int32_t CP0_IntCtl;
+#define CP0IntCtl_IPTI 29
+#define CP0IntCtl_IPPC1 26
+#define CP0IntCtl_VS 5
int32_t CP0_SRSCtl;
+#define CP0SRSCtl_HSS 26
+#define CP0SRSCtl_EICSS 18
+#define CP0SRSCtl_ESS 12
+#define CP0SRSCtl_PSS 6
+#define CP0SRSCtl_CSS 0
int32_t CP0_SRSMap;
+#define CP0SRSMap_SSV7 28
+#define CP0SRSMap_SSV6 24
+#define CP0SRSMap_SSV5 20
+#define CP0SRSMap_SSV4 16
+#define CP0SRSMap_SSV3 12
+#define CP0SRSMap_SSV2 8
+#define CP0SRSMap_SSV1 4
+#define CP0SRSMap_SSV0 0
int32_t CP0_Cause;
#define CP0Ca_BD 31
#define CP0Ca_TI 30
@@ -219,13 +372,14 @@ struct CPUMIPSState {
#define CP0C3_TL 0
int32_t CP0_Config6;
int32_t CP0_Config7;
+ /* XXX: Maybe make LLAddr per-TC? */
target_ulong CP0_LLAddr;
target_ulong CP0_WatchLo[8];
int32_t CP0_WatchHi[8];
target_ulong CP0_XContext;
int32_t CP0_Framemask;
int32_t CP0_Debug;
-#define CPDB_DBD 31
+#define CP0DB_DBD 31
#define CP0DB_DM 30
#define CP0DB_LSNM 28
#define CP0DB_Doze 27
@@ -243,6 +397,7 @@ 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;
@@ -284,7 +439,8 @@ struct CPUMIPSState {
int SYNCI_Step; /* Address step size for SYNCI */
int CCRes; /* Cycle count resolution/divisor */
- int Status_rw_bitmask; /* Read/write bits in CP0_Status */
+ uint32_t CP0_Status_rw_bitmask; /* Read/write bits in CP0_Status */
+ uint32_t CP0_TCStatus_rw_bitmask; /* Read/write bits in CP0_TCStatus */
#ifdef CONFIG_USER_ONLY
target_ulong tls_value;
@@ -376,6 +532,7 @@ enum {
EXCP_TLBS,
EXCP_DBE,
EXCP_DDBL,
+ EXCP_THREAD,
EXCP_MTCP0 = 0x104, /* mtmsr instruction: */
/* may change privilege level */
EXCP_BRANCH = 0x108, /* branch instruction */
diff --git a/target-mips/exec.h b/target-mips/exec.h
index 5b0c833848..53c4189a51 100644
--- a/target-mips/exec.h
+++ b/target-mips/exec.h
@@ -23,24 +23,24 @@ register target_ulong T2 asm(AREG3);
#if defined (USE_HOST_FLOAT_REGS)
#error "implement me."
#else
-#define FDT0 (env->ft0.fd)
-#define FDT1 (env->ft1.fd)
-#define FDT2 (env->ft2.fd)
-#define FST0 (env->ft0.fs[FP_ENDIAN_IDX])
-#define FST1 (env->ft1.fs[FP_ENDIAN_IDX])
-#define FST2 (env->ft2.fs[FP_ENDIAN_IDX])
-#define FSTH0 (env->ft0.fs[!FP_ENDIAN_IDX])
-#define FSTH1 (env->ft1.fs[!FP_ENDIAN_IDX])
-#define FSTH2 (env->ft2.fs[!FP_ENDIAN_IDX])
-#define DT0 (env->ft0.d)
-#define DT1 (env->ft1.d)
-#define DT2 (env->ft2.d)
-#define WT0 (env->ft0.w[FP_ENDIAN_IDX])
-#define WT1 (env->ft1.w[FP_ENDIAN_IDX])
-#define WT2 (env->ft2.w[FP_ENDIAN_IDX])
-#define WTH0 (env->ft0.w[!FP_ENDIAN_IDX])
-#define WTH1 (env->ft1.w[!FP_ENDIAN_IDX])
-#define WTH2 (env->ft2.w[!FP_ENDIAN_IDX])
+#define FDT0 (env->fpu->ft0.fd)
+#define FDT1 (env->fpu->ft1.fd)
+#define FDT2 (env->fpu->ft2.fd)
+#define FST0 (env->fpu->ft0.fs[FP_ENDIAN_IDX])
+#define FST1 (env->fpu->ft1.fs[FP_ENDIAN_IDX])
+#define FST2 (env->fpu->ft2.fs[FP_ENDIAN_IDX])
+#define FSTH0 (env->fpu->ft0.fs[!FP_ENDIAN_IDX])
+#define FSTH1 (env->fpu->ft1.fs[!FP_ENDIAN_IDX])
+#define FSTH2 (env->fpu->ft2.fs[!FP_ENDIAN_IDX])
+#define DT0 (env->fpu->ft0.d)
+#define DT1 (env->fpu->ft1.d)
+#define DT2 (env->fpu->ft2.d)
+#define WT0 (env->fpu->ft0.w[FP_ENDIAN_IDX])
+#define WT1 (env->fpu->ft1.w[FP_ENDIAN_IDX])
+#define WT2 (env->fpu->ft2.w[FP_ENDIAN_IDX])
+#define WTH0 (env->fpu->ft0.w[!FP_ENDIAN_IDX])
+#define WTH1 (env->fpu->ft1.w[!FP_ENDIAN_IDX])
+#define WTH2 (env->fpu->ft2.w[!FP_ENDIAN_IDX])
#endif
#if defined (DEBUG_OP)
@@ -157,7 +157,8 @@ void cpu_mips_update_irq (CPUState *env);
void cpu_mips_clock_init (CPUState *env);
void cpu_mips_tlb_flush (CPUState *env, int flush_global);
-void do_ctc1 (void);
+void do_cfc1 (int reg);
+void do_ctc1 (int reg);
#define FOP_PROTO(op) \
void do_float_ ## op ## _s(void); \
diff --git a/target-mips/fop_template.c b/target-mips/fop_template.c
index 0f1595ff87..bbdcb28903 100644
--- a/target-mips/fop_template.c
+++ b/target-mips/fop_template.c
@@ -24,14 +24,14 @@
#define OP_WLOAD_FREG(treg, tregname, FREG) \
void glue(glue(op_load_fpr_,tregname), FREG) (void) \
{ \
- treg = env->fpr[FREG].fs[FP_ENDIAN_IDX]; \
+ treg = env->fpu->fpr[FREG].fs[FP_ENDIAN_IDX]; \
RETURN(); \
}
#define OP_WSTORE_FREG(treg, tregname, FREG) \
void glue(glue(op_store_fpr_,tregname), FREG) (void) \
{ \
- env->fpr[FREG].fs[FP_ENDIAN_IDX] = treg; \
+ env->fpu->fpr[FREG].fs[FP_ENDIAN_IDX] = treg; \
RETURN(); \
}
@@ -50,10 +50,10 @@ OP_WSTORE_FREG(WT2, WT2_fpr, FREG)
void glue(glue(op_load_fpr_,tregname), FREG) (void) \
{ \
if (env->hflags & MIPS_HFLAG_F64) \
- treg = env->fpr[FREG].fd; \
+ treg = env->fpu->fpr[FREG].fd; \
else \
- treg = (uint64_t)(env->fpr[FREG | 1].fs[FP_ENDIAN_IDX]) << 32 | \
- env->fpr[FREG & ~1].fs[FP_ENDIAN_IDX]; \
+ treg = (uint64_t)(env->fpu->fpr[FREG | 1].fs[FP_ENDIAN_IDX]) << 32 | \
+ env->fpu->fpr[FREG & ~1].fs[FP_ENDIAN_IDX]; \
RETURN(); \
}
@@ -61,10 +61,10 @@ OP_WSTORE_FREG(WT2, WT2_fpr, FREG)
void glue(glue(op_store_fpr_,tregname), FREG) (void) \
{ \
if (env->hflags & MIPS_HFLAG_F64) \
- env->fpr[FREG].fd = treg; \
+ env->fpu->fpr[FREG].fd = treg; \
else { \
- env->fpr[FREG | 1].fs[FP_ENDIAN_IDX] = treg >> 32; \
- env->fpr[FREG & ~1].fs[FP_ENDIAN_IDX] = treg; \
+ env->fpu->fpr[FREG | 1].fs[FP_ENDIAN_IDX] = treg >> 32; \
+ env->fpu->fpr[FREG & ~1].fs[FP_ENDIAN_IDX] = treg; \
} \
RETURN(); \
}
@@ -81,14 +81,14 @@ OP_DSTORE_FREG(DT2, DT2_fpr, FREG)
#define OP_PSLOAD_FREG(treg, tregname, FREG) \
void glue(glue(op_load_fpr_,tregname), FREG) (void) \
{ \
- treg = env->fpr[FREG].fs[!FP_ENDIAN_IDX]; \
+ treg = env->fpu->fpr[FREG].fs[!FP_ENDIAN_IDX]; \
RETURN(); \
}
#define OP_PSSTORE_FREG(treg, tregname, FREG) \
void glue(glue(op_store_fpr_,tregname), FREG) (void) \
{ \
- env->fpr[FREG].fs[!FP_ENDIAN_IDX] = treg; \
+ env->fpu->fpr[FREG].fs[!FP_ENDIAN_IDX] = treg; \
RETURN(); \
}
diff --git a/target-mips/helper.c b/target-mips/helper.c
index 1c83704705..6d0be10156 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -70,8 +70,8 @@ int r4k_map_address (CPUState *env, target_ulong *physical, int *prot,
uint8_t ASID = env->CP0_EntryHi & 0xFF;
int i;
- for (i = 0; i < env->tlb_in_use; i++) {
- r4k_tlb_t *tlb = &env->mmu.r4k.tlb[i];
+ for (i = 0; i < env->tlb->tlb_in_use; i++) {
+ r4k_tlb_t *tlb = &env->tlb->mmu.r4k.tlb[i];
/* 1k pages are not supported. */
target_ulong mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
target_ulong tag = address & ~mask;
@@ -134,7 +134,7 @@ static int get_physical_address (CPUState *env, target_ulong *physical,
*physical = address & 0xFFFFFFFF;
*prot = PAGE_READ | PAGE_WRITE;
} else {
- ret = env->map_address(env, physical, prot, address, rw, access_type);
+ ret = env->tlb->map_address(env, physical, prot, address, rw, access_type);
}
#ifdef TARGET_MIPS64
/*
@@ -144,14 +144,14 @@ static int get_physical_address (CPUState *env, target_ulong *physical,
} else if (address < 0x3FFFFFFFFFFFFFFFULL) {
/* xuseg */
if (UX && address < (0x3FFFFFFFFFFFFFFFULL & env->SEGMask)) {
- ret = env->map_address(env, physical, prot, address, rw, access_type);
+ ret = env->tlb->map_address(env, physical, prot, address, rw, access_type);
} else {
ret = TLBRET_BADADDR;
}
} else if (address < 0x7FFFFFFFFFFFFFFFULL) {
/* xsseg */
if (SX && address < (0x7FFFFFFFFFFFFFFFULL & env->SEGMask)) {
- ret = env->map_address(env, physical, prot, address, rw, access_type);
+ ret = env->tlb->map_address(env, physical, prot, address, rw, access_type);
} else {
ret = TLBRET_BADADDR;
}
@@ -169,7 +169,7 @@ static int get_physical_address (CPUState *env, target_ulong *physical,
/* xkseg */
/* XXX: check supervisor mode */
if (KX && address < (0xFFFFFFFF7FFFFFFFULL & env->SEGMask)) {
- ret = env->map_address(env, physical, prot, address, rw, access_type);
+ ret = env->tlb->map_address(env, physical, prot, address, rw, access_type);
} else {
ret = TLBRET_BADADDR;
}
@@ -186,12 +186,12 @@ static int get_physical_address (CPUState *env, target_ulong *physical,
*prot = PAGE_READ | PAGE_WRITE;
} else if (address < (int32_t)0xE0000000UL) {
/* kseg2 */
- ret = env->map_address(env, physical, prot, address, rw, access_type);
+ ret = env->tlb->map_address(env, physical, prot, address, rw, access_type);
} else {
/* kseg3 */
/* XXX: check supervisor mode */
/* XXX: debug segment is not emulated */
- ret = env->map_address(env, physical, prot, address, rw, access_type);
+ ret = env->tlb->map_address(env, physical, prot, address, rw, access_type);
}
#if 0
if (logfile) {
@@ -238,7 +238,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 is_user %d smmu %d\n",
- __func__, env->PC, address, rw, is_user, is_softmmu);
+ __func__, env->PC[env->current_tc], address, rw, is_user, is_softmmu);
}
rw &= 1;
@@ -328,7 +328,7 @@ void do_interrupt (CPUState *env)
if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) {
fprintf(logfile, "%s enter: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx " cause %d excp %d\n",
- __func__, env->PC, env->CP0_EPC, cause, env->exception_index);
+ __func__, env->PC[env->current_tc], env->CP0_EPC, cause, env->exception_index);
}
if (env->exception_index == EXCP_EXT_INTERRUPT &&
(env->hflags & MIPS_HFLAG_DM))
@@ -342,7 +342,7 @@ void do_interrupt (CPUState *env)
* (but we assume the pc has always been updated during
* code translation).
*/
- env->CP0_DEPC = env->PC;
+ env->CP0_DEPC = env->PC[env->current_tc];
goto enter_debug_mode;
case EXCP_DINT:
env->CP0_Debug |= 1 << CP0DB_DINT;
@@ -362,10 +362,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 - 4;
+ env->CP0_DEPC = env->PC[env->current_tc] - 4;
env->hflags &= ~MIPS_HFLAG_BMASK;
} else {
- env->CP0_DEPC = env->PC;
+ env->CP0_DEPC = env->PC[env->current_tc];
}
enter_debug_mode:
env->hflags |= MIPS_HFLAG_DM;
@@ -375,7 +375,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 = (int32_t)0xBFC00480;
+ env->PC[env->current_tc] = (int32_t)0xBFC00480;
break;
case EXCP_RESET:
cpu_reset(env);
@@ -390,10 +390,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_ErrorEPC = env->PC - 4;
+ env->CP0_ErrorEPC = env->PC[env->current_tc] - 4;
env->hflags &= ~MIPS_HFLAG_BMASK;
} else {
- env->CP0_ErrorEPC = env->PC;
+ env->CP0_ErrorEPC = env->PC[env->current_tc];
}
env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
if ((env->CP0_Config0 & (0x3 << CP0C0_AT)))
@@ -401,7 +401,7 @@ void do_interrupt (CPUState *env)
env->hflags &= ~MIPS_HFLAG_UM;
if (!(env->CP0_Status & (1 << CP0St_EXL)))
env->CP0_Cause &= ~(1 << CP0Ca_BD);
- env->PC = (int32_t)0xBFC00000;
+ env->PC[env->current_tc] = (int32_t)0xBFC00000;
break;
case EXCP_MCHECK:
cause = 24;
@@ -471,6 +471,9 @@ void do_interrupt (CPUState *env)
goto set_EPC;
case EXCP_TLBS:
cause = 3;
+ goto set_EPC;
+ case EXCP_THREAD:
+ cause = 25;
if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL))) {
#ifdef TARGET_MIPS64
int R = env->CP0_BadVAddr >> 62;
@@ -489,10 +492,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 - 4;
+ env->CP0_EPC = env->PC[env->current_tc] - 4;
env->CP0_Cause |= (1 << CP0Ca_BD);
} else {
- env->CP0_EPC = env->PC;
+ env->CP0_EPC = env->PC[env->current_tc];
env->CP0_Cause &= ~(1 << CP0Ca_BD);
}
env->CP0_Status |= (1 << CP0St_EXL);
@@ -502,11 +505,11 @@ void do_interrupt (CPUState *env)
}
env->hflags &= ~MIPS_HFLAG_BMASK;
if (env->CP0_Status & (1 << CP0St_BEV)) {
- env->PC = (int32_t)0xBFC00200;
+ env->PC[env->current_tc] = (int32_t)0xBFC00200;
} else {
- env->PC = (int32_t)(env->CP0_EBase & ~0x3ff);
+ env->PC[env->current_tc] = (int32_t)(env->CP0_EBase & ~0x3ff);
}
- env->PC += offset;
+ env->PC[env->current_tc] += offset;
env->CP0_Cause = (env->CP0_Cause & ~(0x1f << CP0Ca_EC)) | (cause << CP0Ca_EC);
break;
default:
@@ -520,7 +523,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 excp %d\n"
" S %08x C %08x A " TARGET_FMT_lx " D " TARGET_FMT_lx "\n",
- __func__, env->PC, env->CP0_EPC, cause, env->exception_index,
+ __func__, env->PC[env->current_tc], env->CP0_EPC, cause, env->exception_index,
env->CP0_Status, env->CP0_Cause, env->CP0_BadVAddr,
env->CP0_DEPC);
}
@@ -536,19 +539,19 @@ void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra)
uint8_t ASID = env->CP0_EntryHi & 0xFF;
target_ulong mask;
- tlb = &env->mmu.r4k.tlb[idx];
+ tlb = &env->tlb->mmu.r4k.tlb[idx];
/* The qemu TLB is flushed when the ASID changes, so no need to
flush these entries again. */
if (tlb->G == 0 && tlb->ASID != ASID) {
return;
}
- if (use_extra && env->tlb_in_use < MIPS_TLB_MAX) {
+ if (use_extra && env->tlb->tlb_in_use < MIPS_TLB_MAX) {
/* For tlbwr, we can shadow the discarded entry into
a new (fake) TLB entry, as long as the guest can not
tell that it's there. */
- env->mmu.r4k.tlb[env->tlb_in_use] = *tlb;
- env->tlb_in_use++;
+ env->tlb->mmu.r4k.tlb[env->tlb->tlb_in_use] = *tlb;
+ env->tlb->tlb_in_use++;
return;
}
diff --git a/target-mips/op.c b/target-mips/op.c
index 12498d0335..3f52f59d34 100644
--- a/target-mips/op.c
+++ b/target-mips/op.c
@@ -254,25 +254,25 @@ void op_dup_T0 (void)
void op_load_HI (void)
{
- T0 = env->HI;
+ T0 = env->HI[PARAM1][env->current_tc];
RETURN();
}
void op_store_HI (void)
{
- env->HI = T0;
+ env->HI[PARAM1][env->current_tc] = T0;
RETURN();
}
void op_load_LO (void)
{
- T0 = env->LO;
+ T0 = env->LO[PARAM1][env->current_tc];
RETURN();
}
void op_store_LO (void)
{
- env->LO = T0;
+ env->LO[PARAM1][env->current_tc] = T0;
RETURN();
}
@@ -363,8 +363,8 @@ void op_div (void)
void op_div (void)
{
if (T1 != 0) {
- env->LO = (int32_t)((int64_t)(int32_t)T0 / (int32_t)T1);
- env->HI = (int32_t)((int64_t)(int32_t)T0 % (int32_t)T1);
+ env->LO[0][env->current_tc] = (int32_t)((int64_t)(int32_t)T0 / (int32_t)T1);
+ env->HI[0][env->current_tc] = (int32_t)((int64_t)(int32_t)T0 % (int32_t)T1);
}
RETURN();
}
@@ -373,8 +373,8 @@ void op_div (void)
void op_divu (void)
{
if (T1 != 0) {
- env->LO = (int32_t)((uint32_t)T0 / (uint32_t)T1);
- env->HI = (int32_t)((uint32_t)T0 % (uint32_t)T1);
+ env->LO[0][env->current_tc] = (int32_t)((uint32_t)T0 / (uint32_t)T1);
+ env->HI[0][env->current_tc] = (int32_t)((uint32_t)T0 % (uint32_t)T1);
}
RETURN();
}
@@ -442,8 +442,8 @@ void op_ddivu (void)
void op_ddivu (void)
{
if (T1 != 0) {
- env->LO = T0 / T1;
- env->HI = T0 % T1;
+ env->LO[0][env->current_tc] = T0 / T1;
+ env->HI[0][env->current_tc] = T0 % T1;
}
RETURN();
}
@@ -814,13 +814,14 @@ void op_msubu (void)
static inline uint64_t get_HILO (void)
{
- return ((uint64_t)env->HI << 32) | ((uint64_t)(uint32_t)env->LO);
+ return ((uint64_t)env->HI[0][env->current_tc] << 32) |
+ ((uint64_t)(uint32_t)env->LO[0][env->current_tc]);
}
static inline void set_HILO (uint64_t HILO)
{
- env->LO = (int32_t)(HILO & 0xFFFFFFFF);
- env->HI = (int32_t)(HILO >> 32);
+ env->LO[0][env->current_tc] = (int32_t)(HILO & 0xFFFFFFFF);
+ env->HI[0][env->current_tc] = (int32_t)(HILO >> 32);
}
void op_mult (void)
@@ -875,13 +876,13 @@ void op_msubu (void)
#ifdef TARGET_MIPS64
void op_dmult (void)
{
- CALL_FROM_TB4(muls64, &(env->HI), &(env->LO), T0, T1);
+ CALL_FROM_TB4(muls64, &(env->HI[0][env->current_tc]), &(env->LO[0][env->current_tc]), T0, T1);
RETURN();
}
void op_dmultu (void)
{
- CALL_FROM_TB4(mulu64, &(env->HI), &(env->LO), T0, T1);
+ CALL_FROM_TB4(mulu64, &(env->HI[0][env->current_tc]), &(env->LO[0][env->current_tc]), T0, T1);
RETURN();
}
#endif
@@ -890,27 +891,27 @@ void op_dmultu (void)
void op_movn (void)
{
if (T1 != 0)
- env->gpr[PARAM1] = T0;
+ env->gpr[PARAM1][env->current_tc] = T0;
RETURN();
}
void op_movz (void)
{
if (T1 == 0)
- env->gpr[PARAM1] = T0;
+ env->gpr[PARAM1][env->current_tc] = T0;
RETURN();
}
void op_movf (void)
{
- if (!(env->fcr31 & PARAM1))
+ if (!(env->fpu->fcr31 & PARAM1))
T0 = T1;
RETURN();
}
void op_movt (void)
{
- if (env->fcr31 & PARAM1)
+ if (env->fpu->fcr31 & PARAM1)
T0 = T1;
RETURN();
}
@@ -966,7 +967,7 @@ void op_restore_breg_target (void)
void op_breg (void)
{
- env->PC = T2;
+ env->PC[env->current_tc] = T2;
RETURN();
}
@@ -1017,18 +1018,176 @@ void op_mfc0_index (void)
RETURN();
}
+void op_mfc0_mvpcontrol (void)
+{
+ T0 = env->mvp->CP0_MVPControl;
+ RETURN();
+}
+
+void op_mfc0_mvpconf0 (void)
+{
+ T0 = env->mvp->CP0_MVPConf0;
+ RETURN();
+}
+
+void op_mfc0_mvpconf1 (void)
+{
+ T0 = env->mvp->CP0_MVPConf1;
+ RETURN();
+}
+
void op_mfc0_random (void)
{
CALL_FROM_TB0(do_mfc0_random);
RETURN();
}
+void op_mfc0_vpecontrol (void)
+{
+ T0 = env->CP0_VPEControl;
+ RETURN();
+}
+
+void op_mfc0_vpeconf0 (void)
+{
+ T0 = env->CP0_VPEConf0;
+ RETURN();
+}
+
+void op_mfc0_vpeconf1 (void)
+{
+ T0 = env->CP0_VPEConf1;
+ RETURN();
+}
+
+void op_mfc0_yqmask (void)
+{
+ T0 = env->CP0_YQMask;
+ RETURN();
+}
+
+void op_mfc0_vpeschedule (void)
+{
+ T0 = env->CP0_VPESchedule;
+ RETURN();
+}
+
+void op_mfc0_vpeschefback (void)
+{
+ T0 = env->CP0_VPEScheFBack;
+ RETURN();
+}
+
+void op_mfc0_vpeopt (void)
+{
+ T0 = env->CP0_VPEOpt;
+ RETURN();
+}
+
void op_mfc0_entrylo0 (void)
{
T0 = (int32_t)env->CP0_EntryLo0;
RETURN();
}
+void op_mfc0_tcstatus (void)
+{
+ T0 = env->CP0_TCStatus[env->current_tc];
+ RETURN();
+}
+
+void op_mftc0_tcstatus(void)
+{
+ int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
+
+ T0 = env->CP0_TCStatus[other_tc];
+ RETURN();
+}
+
+void op_mfc0_tcbind (void)
+{
+ T0 = env->CP0_TCBind[env->current_tc];
+ RETURN();
+}
+
+void op_mftc0_tcbind(void)
+{
+ int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
+
+ T0 = env->CP0_TCBind[other_tc];
+ RETURN();
+}
+
+void op_mfc0_tcrestart (void)
+{
+ T0 = env->PC[env->current_tc];
+ RETURN();
+}
+
+void op_mftc0_tcrestart(void)
+{
+ int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
+
+ T0 = env->PC[other_tc];
+ RETURN();
+}
+
+void op_mfc0_tchalt (void)
+{
+ T0 = env->CP0_TCHalt[env->current_tc];
+ RETURN();
+}
+
+void op_mftc0_tchalt(void)
+{
+ int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
+
+ T0 = env->CP0_TCHalt[other_tc];
+ RETURN();
+}
+
+void op_mfc0_tccontext (void)
+{
+ T0 = env->CP0_TCContext[env->current_tc];
+ RETURN();
+}
+
+void op_mftc0_tccontext(void)
+{
+ int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
+
+ T0 = env->CP0_TCContext[other_tc];
+ RETURN();
+}
+
+void op_mfc0_tcschedule (void)
+{
+ T0 = env->CP0_TCSchedule[env->current_tc];
+ RETURN();
+}
+
+void op_mftc0_tcschedule(void)
+{
+ int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
+
+ T0 = env->CP0_TCSchedule[other_tc];
+ RETURN();
+}
+
+void op_mfc0_tcschefback (void)
+{
+ T0 = env->CP0_TCScheFBack[env->current_tc];
+ RETURN();
+}
+
+void op_mftc0_tcschefback(void)
+{
+ int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
+
+ T0 = env->CP0_TCScheFBack[other_tc];
+ RETURN();
+}
+
void op_mfc0_entrylo1 (void)
{
T0 = (int32_t)env->CP0_EntryLo1;
@@ -1059,6 +1218,36 @@ void op_mfc0_wired (void)
RETURN();
}
+void op_mfc0_srsconf0 (void)
+{
+ T0 = env->CP0_SRSConf0;
+ RETURN();
+}
+
+void op_mfc0_srsconf1 (void)
+{
+ T0 = env->CP0_SRSConf1;
+ RETURN();
+}
+
+void op_mfc0_srsconf2 (void)
+{
+ T0 = env->CP0_SRSConf2;
+ RETURN();
+}
+
+void op_mfc0_srsconf3 (void)
+{
+ T0 = env->CP0_SRSConf3;
+ RETURN();
+}
+
+void op_mfc0_srsconf4 (void)
+{
+ T0 = env->CP0_SRSConf4;
+ RETURN();
+}
+
void op_mfc0_hwrena (void)
{
T0 = env->CP0_HWREna;
@@ -1083,6 +1272,14 @@ void op_mfc0_entryhi (void)
RETURN();
}
+void op_mftc0_entryhi(void)
+{
+ int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
+
+ T0 = (env->CP0_EntryHi & ~0xff) | (env->CP0_TCStatus[other_tc] & 0xff);
+ RETURN();
+}
+
void op_mfc0_compare (void)
{
T0 = env->CP0_Compare;
@@ -1095,6 +1292,18 @@ void op_mfc0_status (void)
RETURN();
}
+void op_mftc0_status(void)
+{
+ int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
+ uint32_t tcstatus = env->CP0_TCStatus[other_tc];
+
+ T0 = env->CP0_Status & ~0xf1000018;
+ T0 |= tcstatus & (0xf << CP0TCSt_TCU0);
+ T0 |= (tcstatus & (1 << CP0TCSt_TMX)) >> (CP0TCSt_TMX - CP0St_MX);
+ T0 |= (tcstatus & (0x3 << CP0TCSt_TKSU)) >> (CP0TCSt_TKSU - CP0St_R0);
+ RETURN();
+}
+
void op_mfc0_intctl (void)
{
T0 = env->CP0_IntCtl;
@@ -1211,6 +1420,17 @@ void op_mfc0_debug (void)
RETURN();
}
+void op_mftc0_debug(void)
+{
+ int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
+
+ /* XXX: Might be wrong, check with EJTAG spec. */
+ T0 = (env->CP0_Debug & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
+ (env->CP0_Debug_tcstatus[other_tc] &
+ ((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
+ RETURN();
+}
+
void op_mfc0_depc (void)
{
T0 = (int32_t)env->CP0_DEPC;
@@ -1261,7 +1481,105 @@ void op_mfc0_desave (void)
void op_mtc0_index (void)
{
- env->CP0_Index = (env->CP0_Index & 0x80000000) | (T0 % env->nb_tlb);
+ env->CP0_Index = (env->CP0_Index & 0x80000000) | (T0 % env->tlb->nb_tlb);
+ RETURN();
+}
+
+void op_mtc0_mvpcontrol (void)
+{
+ uint32_t mask = 0;
+ uint32_t newval;
+
+ if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP))
+ mask |= (1 << CP0MVPCo_CPA) | (1 << CP0MVPCo_VPC) |
+ (1 << CP0MVPCo_EVP);
+ if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
+ mask |= (1 << CP0MVPCo_STLB);
+ newval = (env->mvp->CP0_MVPControl & ~mask) | (T0 & mask);
+
+ // TODO: Enable/disable shared TLB, enable/disable VPEs.
+
+ env->mvp->CP0_MVPControl = newval;
+ RETURN();
+}
+
+void op_mtc0_vpecontrol (void)
+{
+ uint32_t mask;
+ uint32_t newval;
+
+ mask = (1 << CP0VPECo_YSI) | (1 << CP0VPECo_GSI) |
+ (1 << CP0VPECo_TE) | (0xff << CP0VPECo_TargTC);
+ newval = (env->CP0_VPEControl & ~mask) | (T0 & mask);
+
+ /* Yield scheduler intercept not implemented. */
+ /* Gating storage scheduler intercept not implemented. */
+
+ // TODO: Enable/disable TCs.
+
+ env->CP0_VPEControl = newval;
+ RETURN();
+}
+
+void op_mtc0_vpeconf0 (void)
+{
+ uint32_t mask = 0;
+ uint32_t newval;
+
+ if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) {
+ if (env->CP0_VPEConf0 & (1 << CP0VPEC0_VPA))
+ mask |= (0xff << CP0VPEC0_XTC);
+ mask |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
+ }
+ newval = (env->CP0_VPEConf0 & ~mask) | (T0 & mask);
+
+ // TODO: TC exclusive handling due to ERL/EXL.
+
+ env->CP0_VPEConf0 = newval;
+ RETURN();
+}
+
+void op_mtc0_vpeconf1 (void)
+{
+ uint32_t mask = 0;
+ uint32_t newval;
+
+ if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
+ mask |= (0xff << CP0VPEC1_NCX) | (0xff << CP0VPEC1_NCP2) |
+ (0xff << CP0VPEC1_NCP1);
+ newval = (env->CP0_VPEConf1 & ~mask) | (T0 & mask);
+
+ /* UDI not implemented. */
+ /* CP2 not implemented. */
+
+ // TODO: Handle FPU (CP1) binding.
+
+ env->CP0_VPEConf1 = newval;
+ RETURN();
+}
+
+void op_mtc0_yqmask (void)
+{
+ /* Yield qualifier inputs not implemented. */
+ env->CP0_YQMask = 0x00000000;
+ RETURN();
+}
+
+void op_mtc0_vpeschedule (void)
+{
+ env->CP0_VPESchedule = T0;
+ RETURN();
+}
+
+void op_mtc0_vpeschefback (void)
+{
+ env->CP0_VPEScheFBack = T0;
+ RETURN();
+}
+
+void op_mtc0_vpeopt (void)
+{
+ env->CP0_VPEOpt = T0 & 0x0000ffff;
RETURN();
}
@@ -1273,6 +1591,135 @@ void op_mtc0_entrylo0 (void)
RETURN();
}
+void op_mtc0_tcstatus (void)
+{
+ uint32_t mask = env->CP0_TCStatus_rw_bitmask;
+ uint32_t newval;
+
+ newval = (env->CP0_TCStatus[env->current_tc] & ~mask) | (T0 & mask);
+
+ // TODO: Sync with CP0_Status.
+
+ env->CP0_TCStatus[env->current_tc] = newval;
+ RETURN();
+}
+
+void op_mttc0_tcstatus (void)
+{
+ int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
+
+ // TODO: Sync with CP0_Status.
+
+ env->CP0_TCStatus[other_tc] = T0;
+ RETURN();
+}
+
+void op_mtc0_tcbind (void)
+{
+ uint32_t mask = (1 << CP0TCBd_TBE);
+ uint32_t newval;
+
+ 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;
+ RETURN();
+}
+
+void op_mttc0_tcbind (void)
+{
+ int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
+ uint32_t mask = (1 << CP0TCBd_TBE);
+ uint32_t newval;
+
+ 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;
+ RETURN();
+}
+
+void op_mtc0_tcrestart (void)
+{
+ env->PC[env->current_tc] = T0;
+ env->CP0_TCStatus[env->current_tc] &= ~(1 << CP0TCSt_TDS);
+ env->CP0_LLAddr = 0ULL;
+ /* MIPS16 not implemented. */
+ RETURN();
+}
+
+void op_mttc0_tcrestart (void)
+{
+ 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. */
+ RETURN();
+}
+
+void op_mtc0_tchalt (void)
+{
+ env->CP0_TCHalt[env->current_tc] = T0 & 0x1;
+
+ // TODO: Halt TC / Restart (if allocated+active) TC.
+
+ RETURN();
+}
+
+void op_mttc0_tchalt (void)
+{
+ int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
+
+ // TODO: Halt TC / Restart (if allocated+active) TC.
+
+ env->CP0_TCHalt[other_tc] = T0;
+ RETURN();
+}
+
+void op_mtc0_tccontext (void)
+{
+ env->CP0_TCContext[env->current_tc] = T0;
+ RETURN();
+}
+
+void op_mttc0_tccontext (void)
+{
+ int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
+
+ env->CP0_TCContext[other_tc] = T0;
+ RETURN();
+}
+
+void op_mtc0_tcschedule (void)
+{
+ env->CP0_TCSchedule[env->current_tc] = T0;
+ RETURN();
+}
+
+void op_mttc0_tcschedule (void)
+{
+ int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
+
+ env->CP0_TCSchedule[other_tc] = T0;
+ RETURN();
+}
+
+void op_mtc0_tcschefback (void)
+{
+ env->CP0_TCScheFBack[env->current_tc] = T0;
+ RETURN();
+}
+
+void op_mttc0_tcschefback (void)
+{
+ int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
+
+ env->CP0_TCScheFBack[other_tc] = T0;
+ RETURN();
+}
+
void op_mtc0_entrylo1 (void)
{
/* Large physaddr not implemented */
@@ -1305,7 +1752,37 @@ void op_mtc0_pagegrain (void)
void op_mtc0_wired (void)
{
- env->CP0_Wired = T0 % env->nb_tlb;
+ env->CP0_Wired = T0 % env->tlb->nb_tlb;
+ RETURN();
+}
+
+void op_mtc0_srsconf0 (void)
+{
+ env->CP0_SRSConf0 |= T0 & env->CP0_SRSConf0_rw_bitmask;
+ RETURN();
+}
+
+void op_mtc0_srsconf1 (void)
+{
+ env->CP0_SRSConf1 |= T0 & env->CP0_SRSConf1_rw_bitmask;
+ RETURN();
+}
+
+void op_mtc0_srsconf2 (void)
+{
+ env->CP0_SRSConf2 |= T0 & env->CP0_SRSConf2_rw_bitmask;
+ RETURN();
+}
+
+void op_mtc0_srsconf3 (void)
+{
+ env->CP0_SRSConf3 |= T0 & env->CP0_SRSConf3_rw_bitmask;
+ RETURN();
+}
+
+void op_mtc0_srsconf4 (void)
+{
+ env->CP0_SRSConf4 |= T0 & env->CP0_SRSConf4_rw_bitmask;
RETURN();
}
@@ -1332,12 +1809,25 @@ void op_mtc0_entryhi (void)
#endif
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);
+ }
/* If the ASID changes, flush qemu's TLB. */
if ((old & 0xFF) != (val & 0xFF))
CALL_FROM_TB2(cpu_mips_tlb_flush, env, 1);
RETURN();
}
+void op_mttc0_entryhi(void)
+{
+ int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
+
+ env->CP0_EntryHi = (env->CP0_EntryHi & 0xff) | (T0 & ~0xff);
+ env->CP0_TCStatus[other_tc] = (env->CP0_TCStatus[other_tc] & ~0xff) | (T0 & 0xff);
+ RETURN();
+}
+
void op_mtc0_compare (void)
{
CALL_FROM_TB2(cpu_mips_store_compare, env, T0);
@@ -1347,9 +1837,8 @@ void op_mtc0_compare (void)
void op_mtc0_status (void)
{
uint32_t val, old;
- uint32_t mask = env->Status_rw_bitmask;
+ uint32_t mask = env->CP0_Status_rw_bitmask;
- /* No reverse endianness, no MDMX/DSP implemented. */
val = T0 & mask;
old = env->CP0_Status;
if (!(val & (1 << CP0St_EXL)) &&
@@ -1379,6 +1868,19 @@ void op_mtc0_status (void)
RETURN();
}
+void op_mttc0_status(void)
+{
+ int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
+ uint32_t tcstatus = env->CP0_TCStatus[other_tc];
+
+ 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_R0)) << (CP0TCSt_TKSU - CP0St_R0));
+ env->CP0_TCStatus[other_tc] = tcstatus;
+ RETURN();
+}
+
void op_mtc0_intctl (void)
{
/* vectored interrupts not implemented, timer on int 7,
@@ -1389,15 +1891,14 @@ void op_mtc0_intctl (void)
void op_mtc0_srsctl (void)
{
- /* shadow registers not implemented */
- env->CP0_SRSCtl = 0;
+ uint32_t mask = (0xf << CP0SRSCtl_ESS) | (0xf << CP0SRSCtl_PSS);
+ env->CP0_SRSCtl = (env->CP0_SRSCtl & ~mask) | (T0 & mask);
RETURN();
}
void op_mtc0_srsmap (void)
{
- /* shadow registers not implemented */
- env->CP0_SRSMap = 0;
+ env->CP0_SRSMap = T0;
RETURN();
}
@@ -1460,6 +1961,13 @@ void op_mtc0_watchhi (void)
RETURN();
}
+void op_mtc0_xcontext (void)
+{
+ target_ulong mask = (1ULL << (env->SEGBITS - 7)) - 1;
+ env->CP0_XContext = (env->CP0_XContext & mask) | (T0 & ~mask);
+ RETURN();
+}
+
void op_mtc0_framemask (void)
{
env->CP0_Framemask = T0; /* XXX */
@@ -1476,6 +1984,17 @@ void op_mtc0_debug (void)
RETURN();
}
+void op_mttc0_debug(void)
+{
+ int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
+
+ /* XXX: Might be wrong, check with EJTAG spec. */
+ env->CP0_Debug_tcstatus[other_tc] = T0 & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt));
+ env->CP0_Debug = (env->CP0_Debug & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
+ (T0 & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
+ RETURN();
+}
+
void op_mtc0_depc (void)
{
env->CP0_DEPC = T0;
@@ -1525,10 +2044,21 @@ void op_mtc0_desave (void)
}
#ifdef TARGET_MIPS64
-void op_mtc0_xcontext (void)
+void op_dmfc0_yqmask (void)
{
- target_ulong mask = (1ULL << (env->SEGBITS - 7)) - 1;
- env->CP0_XContext = (env->CP0_XContext & mask) | (T0 & ~mask);
+ T0 = env->CP0_YQMask;
+ RETURN();
+}
+
+void op_dmfc0_vpeschedule (void)
+{
+ T0 = env->CP0_VPESchedule;
+ RETURN();
+}
+
+void op_dmfc0_vpeschefback (void)
+{
+ T0 = env->CP0_VPEScheFBack;
RETURN();
}
@@ -1538,6 +2068,36 @@ void op_dmfc0_entrylo0 (void)
RETURN();
}
+void op_dmfc0_tcrestart (void)
+{
+ T0 = env->PC[env->current_tc];
+ RETURN();
+}
+
+void op_dmfc0_tchalt (void)
+{
+ T0 = env->CP0_TCHalt[env->current_tc];
+ RETURN();
+}
+
+void op_dmfc0_tccontext (void)
+{
+ T0 = env->CP0_TCContext[env->current_tc];
+ RETURN();
+}
+
+void op_dmfc0_tcschedule (void)
+{
+ T0 = env->CP0_TCSchedule[env->current_tc];
+ RETURN();
+}
+
+void op_dmfc0_tcschefback (void)
+{
+ T0 = env->CP0_TCScheFBack[env->current_tc];
+ RETURN();
+}
+
void op_dmfc0_entrylo1 (void)
{
T0 = env->CP0_EntryLo1;
@@ -1599,6 +2159,157 @@ void op_dmfc0_errorepc (void)
}
#endif /* TARGET_MIPS64 */
+/* MIPS MT functions */
+void op_mftgpr(void)
+{
+ int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
+
+ T0 = env->gpr[PARAM1][other_tc];
+ RETURN();
+}
+
+void op_mftlo(void)
+{
+ int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
+
+ T0 = env->LO[PARAM1][other_tc];
+ RETURN();
+}
+
+void op_mfthi(void)
+{
+ int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
+
+ T0 = env->HI[PARAM1][other_tc];
+ RETURN();
+}
+
+void op_mftacx(void)
+{
+ int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
+
+ T0 = env->ACX[PARAM1][other_tc];
+ RETURN();
+}
+
+void op_mftdsp(void)
+{
+ int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
+
+ T0 = env->DSPControl[other_tc];
+ RETURN();
+}
+
+void op_mttgpr(void)
+{
+ int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
+
+ T0 = env->gpr[PARAM1][other_tc];
+ RETURN();
+}
+
+void op_mttlo(void)
+{
+ int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
+
+ T0 = env->LO[PARAM1][other_tc];
+ RETURN();
+}
+
+void op_mtthi(void)
+{
+ int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
+
+ T0 = env->HI[PARAM1][other_tc];
+ RETURN();
+}
+
+void op_mttacx(void)
+{
+ int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
+
+ T0 = env->ACX[PARAM1][other_tc];
+ RETURN();
+}
+
+void op_mttdsp(void)
+{
+ int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
+
+ T0 = env->DSPControl[other_tc];
+ RETURN();
+}
+
+
+void op_dmt(void)
+{
+ // TODO
+ T0 = 0;
+ // rt = T0
+ RETURN();
+}
+
+void op_emt(void)
+{
+ // TODO
+ T0 = 0;
+ // rt = T0
+ RETURN();
+}
+
+void op_dvpe(void)
+{
+ // TODO
+ T0 = 0;
+ // rt = T0
+ RETURN();
+}
+
+void op_evpe(void)
+{
+ // TODO
+ T0 = 0;
+ // rt = T0
+ RETURN();
+}
+
+void op_fork(void)
+{
+ // T0 = rt, T1 = rs
+ T0 = 0;
+ // TODO: store to TC register
+ RETURN();
+}
+
+void op_yield(void)
+{
+ if (T0 < 0) {
+ /* No scheduling policy implemented. */
+ if (T0 != -2) {
+ if (env->CP0_VPEControl & (1 << CP0VPECo_YSI) &&
+ env->CP0_TCStatus[env->current_tc] & (1 << CP0TCSt_DT)) {
+ env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
+ env->CP0_VPEControl |= 4 << CP0VPECo_EXCPT;
+ CALL_FROM_TB1(do_raise_exception, EXCP_THREAD);
+ }
+ }
+ } else if (T0 == 0) {
+ if (0 /* TODO: TC underflow */) {
+ env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
+ CALL_FROM_TB1(do_raise_exception, EXCP_THREAD);
+ } else {
+ // TODO: Deallocate TC
+ }
+ } else if (T0 > 0) {
+ /* Yield qualifier inputs not implemented. */
+ env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
+ env->CP0_VPEControl |= 2 << CP0VPECo_EXCPT;
+ CALL_FROM_TB1(do_raise_exception, EXCP_THREAD);
+ }
+ T0 = env->CP0_YQMask;
+ RETURN();
+}
+
/* CP1 functions */
#if 0
# define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env)
@@ -1617,30 +2328,14 @@ void op_cp0_enabled(void)
void op_cfc1 (void)
{
- switch (T1) {
- case 0:
- T0 = (int32_t)env->fcr0;
- break;
- case 25:
- T0 = ((env->fcr31 >> 24) & 0xfe) | ((env->fcr31 >> 23) & 0x1);
- break;
- case 26:
- T0 = env->fcr31 & 0x0003f07c;
- break;
- case 28:
- T0 = (env->fcr31 & 0x00000f83) | ((env->fcr31 >> 22) & 0x4);
- break;
- default:
- T0 = (int32_t)env->fcr31;
- break;
- }
+ CALL_FROM_TB1(do_cfc1, PARAM1);
DEBUG_FPU_STATE();
RETURN();
}
void op_ctc1 (void)
{
- CALL_FROM_TB0(do_ctc1);
+ CALL_FROM_TB1(do_ctc1, PARAM1);
DEBUG_FPU_STATE();
RETURN();
}
@@ -1842,21 +2537,21 @@ FLOAT_ROUNDOP(floor, w, s)
FLOAT_OP(movf, d)
{
- if (!(env->fcr31 & PARAM1))
+ if (!(env->fpu->fcr31 & PARAM1))
DT2 = DT0;
DEBUG_FPU_STATE();
RETURN();
}
FLOAT_OP(movf, s)
{
- if (!(env->fcr31 & PARAM1))
+ if (!(env->fpu->fcr31 & PARAM1))
WT2 = WT0;
DEBUG_FPU_STATE();
RETURN();
}
FLOAT_OP(movf, ps)
{
- if (!(env->fcr31 & PARAM1)) {
+ if (!(env->fpu->fcr31 & PARAM1)) {
WT2 = WT0;
WTH2 = WTH0;
}
@@ -1865,21 +2560,21 @@ FLOAT_OP(movf, ps)
}
FLOAT_OP(movt, d)
{
- if (env->fcr31 & PARAM1)
+ if (env->fpu->fcr31 & PARAM1)
DT2 = DT0;
DEBUG_FPU_STATE();
RETURN();
}
FLOAT_OP(movt, s)
{
- if (env->fcr31 & PARAM1)
+ if (env->fpu->fcr31 & PARAM1)
WT2 = WT0;
DEBUG_FPU_STATE();
RETURN();
}
FLOAT_OP(movt, ps)
{
- if (env->fcr31 & PARAM1) {
+ if (env->fpu->fcr31 & PARAM1) {
WT2 = WT0;
WTH2 = WTH0;
}
@@ -1997,24 +2692,24 @@ FLOAT_HOP(mulr)
#define FLOAT_TERNOP(name1, name2) \
FLOAT_OP(name1 ## name2, d) \
{ \
- FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fp_status); \
- FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fp_status); \
+ FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status); \
+ FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status); \
DEBUG_FPU_STATE(); \
RETURN(); \
} \
FLOAT_OP(name1 ## name2, s) \
{ \
- FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \
- FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \
+ FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
+ FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
DEBUG_FPU_STATE(); \
RETURN(); \
} \
FLOAT_OP(name1 ## name2, ps) \
{ \
- FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \
- FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fp_status); \
- FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \
- FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fp_status); \
+ FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
+ FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \
+ FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
+ FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \
DEBUG_FPU_STATE(); \
RETURN(); \
}
@@ -2026,26 +2721,26 @@ FLOAT_TERNOP(mul, sub)
#define FLOAT_NTERNOP(name1, name2) \
FLOAT_OP(n ## name1 ## name2, d) \
{ \
- FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fp_status); \
- FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fp_status); \
+ FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status); \
+ FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status); \
FDT2 ^= 1ULL << 63; \
DEBUG_FPU_STATE(); \
RETURN(); \
} \
FLOAT_OP(n ## name1 ## name2, s) \
{ \
- FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \
- FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \
+ FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
+ FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
FST2 ^= 1 << 31; \
DEBUG_FPU_STATE(); \
RETURN(); \
} \
FLOAT_OP(n ## name1 ## name2, ps) \
{ \
- FST0 = float32_ ## name1 (FST0, FST1, &env->fp_status); \
- FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fp_status); \
- FST2 = float32_ ## name2 (FST0, FST2, &env->fp_status); \
- FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fp_status); \
+ FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status); \
+ FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \
+ FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status); \
+ FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \
FST2 ^= 1 << 31; \
FSTH2 ^= 1 << 31; \
DEBUG_FPU_STATE(); \
@@ -2059,13 +2754,13 @@ FLOAT_NTERNOP(mul, sub)
#define FLOAT_UNOP(name) \
FLOAT_OP(name, d) \
{ \
- FDT2 = float64_ ## name(FDT0, &env->fp_status); \
+ FDT2 = float64_ ## name(FDT0, &env->fpu->fp_status); \
DEBUG_FPU_STATE(); \
RETURN(); \
} \
FLOAT_OP(name, s) \
{ \
- FST2 = float32_ ## name(FST0, &env->fp_status); \
+ FST2 = float32_ ## name(FST0, &env->fpu->fp_status); \
DEBUG_FPU_STATE(); \
RETURN(); \
}
@@ -2141,9 +2836,9 @@ FLOAT_OP(alnv, ps)
#ifdef CONFIG_SOFTFLOAT
#define clear_invalid() do { \
- int flags = get_float_exception_flags(&env->fp_status); \
+ int flags = get_float_exception_flags(&env->fpu->fp_status); \
flags &= ~float_flag_invalid; \
- set_float_exception_flags(flags, &env->fp_status); \
+ set_float_exception_flags(flags, &env->fpu->fp_status); \
} while(0)
#else
#define clear_invalid() do { } while(0)
@@ -2190,63 +2885,63 @@ CMP_OPS(ngt)
void op_bc1f (void)
{
- T0 = !!(~GET_FP_COND(env) & (0x1 << PARAM1));
+ T0 = !!(~GET_FP_COND(env->fpu) & (0x1 << PARAM1));
DEBUG_FPU_STATE();
RETURN();
}
void op_bc1any2f (void)
{
- T0 = !!(~GET_FP_COND(env) & (0x3 << PARAM1));
+ T0 = !!(~GET_FP_COND(env->fpu) & (0x3 << PARAM1));
DEBUG_FPU_STATE();
RETURN();
}
void op_bc1any4f (void)
{
- T0 = !!(~GET_FP_COND(env) & (0xf << PARAM1));
+ T0 = !!(~GET_FP_COND(env->fpu) & (0xf << PARAM1));
DEBUG_FPU_STATE();
RETURN();
}
void op_bc1t (void)
{
- T0 = !!(GET_FP_COND(env) & (0x1 << PARAM1));
+ T0 = !!(GET_FP_COND(env->fpu) & (0x1 << PARAM1));
DEBUG_FPU_STATE();
RETURN();
}
void op_bc1any2t (void)
{
- T0 = !!(GET_FP_COND(env) & (0x3 << PARAM1));
+ T0 = !!(GET_FP_COND(env->fpu) & (0x3 << PARAM1));
DEBUG_FPU_STATE();
RETURN();
}
void op_bc1any4t (void)
{
- T0 = !!(GET_FP_COND(env) & (0xf << PARAM1));
+ T0 = !!(GET_FP_COND(env->fpu) & (0xf << PARAM1));
DEBUG_FPU_STATE();
RETURN();
}
void op_tlbwi (void)
{
- CALL_FROM_TB0(env->do_tlbwi);
+ CALL_FROM_TB0(env->tlb->do_tlbwi);
RETURN();
}
void op_tlbwr (void)
{
- CALL_FROM_TB0(env->do_tlbwr);
+ CALL_FROM_TB0(env->tlb->do_tlbwr);
RETURN();
}
void op_tlbp (void)
{
- CALL_FROM_TB0(env->do_tlbp);
+ CALL_FROM_TB0(env->tlb->do_tlbp);
RETURN();
}
void op_tlbr (void)
{
- CALL_FROM_TB0(env->do_tlbr);
+ CALL_FROM_TB0(env->tlb->do_tlbr);
RETURN();
}
@@ -2307,10 +3002,10 @@ void op_eret (void)
if (loglevel & CPU_LOG_EXEC)
CALL_FROM_TB0(debug_pre_eret);
if (env->CP0_Status & (1 << CP0St_ERL)) {
- env->PC = env->CP0_ErrorEPC;
+ env->PC[env->current_tc] = env->CP0_ErrorEPC;
env->CP0_Status &= ~(1 << CP0St_ERL);
} else {
- env->PC = env->CP0_EPC;
+ env->PC[env->current_tc] = env->CP0_EPC;
env->CP0_Status &= ~(1 << CP0St_EXL);
}
if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
@@ -2335,7 +3030,7 @@ void op_deret (void)
{
if (loglevel & CPU_LOG_EXEC)
CALL_FROM_TB0(debug_pre_eret);
- env->PC = env->CP0_DEPC;
+ env->PC[env->current_tc] = env->CP0_DEPC;
env->hflags |= MIPS_HFLAG_DM;
if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
!(env->CP0_Status & (1 << CP0St_ERL)) &&
@@ -2407,14 +3102,14 @@ void op_save_state (void)
void op_save_pc (void)
{
- env->PC = PARAM1;
+ env->PC[env->current_tc] = PARAM1;
RETURN();
}
#ifdef TARGET_MIPS64
void op_save_pc64 (void)
{
- env->PC = ((uint64_t)PARAM1 << 32) | (uint32_t)PARAM2;
+ env->PC[env->current_tc] = ((uint64_t)PARAM1 << 32) | (uint32_t)PARAM2;
RETURN();
}
#endif
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 477b80d516..c87317a44f 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -160,13 +160,13 @@ void do_drotrv (void)
#if TARGET_LONG_BITS > HOST_LONG_BITS
static inline uint64_t get_HILO (void)
{
- return (env->HI << 32) | (uint32_t)env->LO;
+ return (env->HI[0][env->current_tc] << 32) | (uint32_t)env->LO[0][env->current_tc];
}
static inline void set_HILO (uint64_t HILO)
{
- env->LO = (int32_t)HILO;
- env->HI = (int32_t)(HILO >> 32);
+ env->LO[0][env->current_tc] = (int32_t)HILO;
+ env->HI[0][env->current_tc] = (int32_t)(HILO >> 32);
}
void do_mult (void)
@@ -217,8 +217,8 @@ void do_div (void)
{
/* 64bit datatypes because we may see overflow/underflow. */
if (T1 != 0) {
- env->LO = (int32_t)((int64_t)(int32_t)T0 / (int32_t)T1);
- env->HI = (int32_t)((int64_t)(int32_t)T0 % (int32_t)T1);
+ env->LO[0][env->current_tc] = (int32_t)((int64_t)(int32_t)T0 / (int32_t)T1);
+ env->HI[0][env->current_tc] = (int32_t)((int64_t)(int32_t)T0 % (int32_t)T1);
}
}
#endif
@@ -228,8 +228,8 @@ void do_ddiv (void)
{
if (T1 != 0) {
lldiv_t res = lldiv((int64_t)T0, (int64_t)T1);
- env->LO = res.quot;
- env->HI = res.rem;
+ env->LO[0][env->current_tc] = res.quot;
+ env->HI[0][env->current_tc] = res.rem;
}
}
@@ -237,8 +237,8 @@ void do_ddiv (void)
void do_ddivu (void)
{
if (T1 != 0) {
- env->LO = T0 / T1;
- env->HI = T0 % T1;
+ env->LO[0][env->current_tc] = T0 / T1;
+ env->HI[0][env->current_tc] = T0 % T1;
}
}
#endif
@@ -316,10 +316,10 @@ void do_mtc0_status_irqraise_debug(void)
void fpu_handle_exception(void)
{
#ifdef CONFIG_SOFTFLOAT
- int flags = get_float_exception_flags(&env->fp_status);
+ int flags = get_float_exception_flags(&env->fpu->fp_status);
unsigned int cpuflags = 0, enable, cause = 0;
- enable = GET_FP_ENABLE(env->fcr31);
+ enable = GET_FP_ENABLE(env->fpu->fcr31);
/* determine current flags */
if (flags & float_flag_invalid) {
@@ -342,11 +342,11 @@ void fpu_handle_exception(void)
cpuflags |= FP_INEXACT;
cause |= FP_INEXACT & enable;
}
- SET_FP_FLAGS(env->fcr31, cpuflags);
- SET_FP_CAUSE(env->fcr31, cause);
+ SET_FP_FLAGS(env->fpu->fcr31, cpuflags);
+ SET_FP_CAUSE(env->fpu->fcr31, cause);
#else
- SET_FP_FLAGS(env->fcr31, 0);
- SET_FP_CAUSE(env->fcr31, 0);
+ SET_FP_FLAGS(env->fpu->fcr31, 0);
+ SET_FP_CAUSE(env->fpu->fcr31, 0);
#endif
}
@@ -355,14 +355,14 @@ void cpu_mips_tlb_flush (CPUState *env, int flush_global)
{
/* Flush qemu's TLB and discard all shadowed entries. */
tlb_flush (env, flush_global);
- env->tlb_in_use = env->nb_tlb;
+ env->tlb->tlb_in_use = env->tlb->nb_tlb;
}
static void r4k_mips_tlb_flush_extra (CPUState *env, int first)
{
/* Discard entries from env->tlb[first] onwards. */
- while (env->tlb_in_use > first) {
- r4k_invalidate_tlb(env, --env->tlb_in_use, 0);
+ while (env->tlb->tlb_in_use > first) {
+ r4k_invalidate_tlb(env, --env->tlb->tlb_in_use, 0);
}
}
@@ -371,7 +371,7 @@ static void r4k_fill_tlb (int idx)
r4k_tlb_t *tlb;
/* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */
- tlb = &env->mmu.r4k.tlb[idx];
+ tlb = &env->tlb->mmu.r4k.tlb[idx];
tlb->VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1);
#ifdef TARGET_MIPS64
tlb->VPN &= env->SEGMask;
@@ -394,10 +394,10 @@ void r4k_do_tlbwi (void)
/* Discard cached TLB entries. We could avoid doing this if the
tlbwi is just upgrading access permissions on the current entry;
that might be a further win. */
- r4k_mips_tlb_flush_extra (env, env->nb_tlb);
+ r4k_mips_tlb_flush_extra (env, env->tlb->nb_tlb);
- r4k_invalidate_tlb(env, env->CP0_Index % env->nb_tlb, 0);
- r4k_fill_tlb(env->CP0_Index % env->nb_tlb);
+ r4k_invalidate_tlb(env, env->CP0_Index % env->tlb->nb_tlb, 0);
+ r4k_fill_tlb(env->CP0_Index % env->tlb->nb_tlb);
}
void r4k_do_tlbwr (void)
@@ -418,8 +418,8 @@ void r4k_do_tlbp (void)
int i;
ASID = env->CP0_EntryHi & 0xFF;
- for (i = 0; i < env->nb_tlb; i++) {
- tlb = &env->mmu.r4k.tlb[i];
+ for (i = 0; i < env->tlb->nb_tlb; i++) {
+ tlb = &env->tlb->mmu.r4k.tlb[i];
/* 1k pages are not supported. */
mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
tag = env->CP0_EntryHi & ~mask;
@@ -431,10 +431,10 @@ void r4k_do_tlbp (void)
break;
}
}
- if (i == env->nb_tlb) {
+ if (i == env->tlb->nb_tlb) {
/* No match. Discard any shadow entries, if any of them match. */
- for (i = env->nb_tlb; i < env->tlb_in_use; i++) {
- tlb = &env->mmu.r4k.tlb[i];
+ for (i = env->tlb->nb_tlb; i < env->tlb->tlb_in_use; i++) {
+ tlb = &env->tlb->mmu.r4k.tlb[i];
/* 1k pages are not supported. */
mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
tag = env->CP0_EntryHi & ~mask;
@@ -456,13 +456,13 @@ void r4k_do_tlbr (void)
uint8_t ASID;
ASID = env->CP0_EntryHi & 0xFF;
- tlb = &env->mmu.r4k.tlb[env->CP0_Index % env->nb_tlb];
+ tlb = &env->tlb->mmu.r4k.tlb[env->CP0_Index % env->tlb->nb_tlb];
/* If this will change the current ASID, flush qemu's TLB. */
if (ASID != tlb->ASID)
cpu_mips_tlb_flush (env, 1);
- r4k_mips_tlb_flush_extra(env, env->nb_tlb);
+ r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb);
env->CP0_EntryHi = tlb->VPN | tlb->ASID;
env->CP0_PageMask = tlb->PageMask;
@@ -491,7 +491,7 @@ void dump_sc (void)
void debug_pre_eret (void)
{
fprintf(logfile, "ERET: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
- env->PC, env->CP0_EPC);
+ env->PC[env->current_tc], 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)
@@ -502,7 +502,7 @@ void debug_pre_eret (void)
void debug_post_eret (void)
{
fprintf(logfile, " => PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
- env->PC, env->CP0_EPC);
+ env->PC[env->current_tc], 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)
@@ -518,21 +518,21 @@ void do_pmon (int function)
function /= 2;
switch (function) {
case 2: /* TODO: char inbyte(int waitflag); */
- if (env->gpr[4] == 0)
- env->gpr[2] = -1;
+ if (env->gpr[4][env->current_tc] == 0)
+ env->gpr[2][env->current_tc] = -1;
/* Fall through */
case 11: /* TODO: char inbyte (void); */
- env->gpr[2] = -1;
+ env->gpr[2][env->current_tc] = -1;
break;
case 3:
case 12:
- printf("%c", (char)(env->gpr[4] & 0xFF));
+ printf("%c", (char)(env->gpr[4][env->current_tc] & 0xFF));
break;
case 17:
break;
case 158:
{
- unsigned char *fmt = (void *)(unsigned long)env->gpr[4];
+ unsigned char *fmt = (void *)(unsigned long)env->gpr[4][env->current_tc];
printf("%s", fmt);
}
break;
@@ -613,40 +613,61 @@ unsigned int ieee_rm[] = {
};
#define RESTORE_ROUNDING_MODE \
- set_float_rounding_mode(ieee_rm[env->fcr31 & 3], &env->fp_status)
+ set_float_rounding_mode(ieee_rm[env->fpu->fcr31 & 3], &env->fpu->fp_status)
-void do_ctc1 (void)
+void do_cfc1 (int reg)
{
- switch(T1) {
+ switch (reg) {
+ case 0:
+ T0 = (int32_t)env->fpu->fcr0;
+ break;
+ case 25:
+ T0 = ((env->fpu->fcr31 >> 24) & 0xfe) | ((env->fpu->fcr31 >> 23) & 0x1);
+ break;
+ case 26:
+ T0 = env->fpu->fcr31 & 0x0003f07c;
+ break;
+ case 28:
+ T0 = (env->fpu->fcr31 & 0x00000f83) | ((env->fpu->fcr31 >> 22) & 0x4);
+ break;
+ default:
+ T0 = (int32_t)env->fpu->fcr31;
+ break;
+ }
+}
+
+void do_ctc1 (int reg)
+{
+ switch(reg) {
case 25:
if (T0 & 0xffffff00)
return;
- env->fcr31 = (env->fcr31 & 0x017fffff) | ((T0 & 0xfe) << 24) |
+ env->fpu->fcr31 = (env->fpu->fcr31 & 0x017fffff) | ((T0 & 0xfe) << 24) |
((T0 & 0x1) << 23);
break;
case 26:
if (T0 & 0x007c0000)
return;
- env->fcr31 = (env->fcr31 & 0xfffc0f83) | (T0 & 0x0003f07c);
+ env->fpu->fcr31 = (env->fpu->fcr31 & 0xfffc0f83) | (T0 & 0x0003f07c);
break;
case 28:
if (T0 & 0x007c0000)
return;
- env->fcr31 = (env->fcr31 & 0xfefff07c) | (T0 & 0x00000f83) |
+ env->fpu->fcr31 = (env->fpu->fcr31 & 0xfefff07c) | (T0 & 0x00000f83) |
((T0 & 0x4) << 22);
break;
case 31:
if (T0 & 0x007c0000)
return;
- env->fcr31 = T0;
+ env->fpu->fcr31 = T0;
break;
default:
return;
}
/* set rounding mode */
RESTORE_ROUNDING_MODE;
- set_float_exception_flags(0, &env->fp_status);
- if ((GET_FP_ENABLE(env->fcr31) | 0x20) & GET_FP_CAUSE(env->fcr31))
+ set_float_exception_flags(0, &env->fpu->fp_status);
+ if ((GET_FP_ENABLE(env->fpu->fcr31) | 0x20) & GET_FP_CAUSE(env->fpu->fcr31))
do_raise_exception(EXCP_FPE);
}
@@ -670,325 +691,325 @@ inline char mips_ex_to_ieee(char xcpt)
inline void update_fcr31(void)
{
- int tmp = ieee_ex_to_mips(get_float_exception_flags(&env->fp_status));
+ int tmp = ieee_ex_to_mips(get_float_exception_flags(&env->fpu->fp_status));
- SET_FP_CAUSE(env->fcr31, tmp);
- if (GET_FP_ENABLE(env->fcr31) & tmp)
+ SET_FP_CAUSE(env->fpu->fcr31, tmp);
+ if (GET_FP_ENABLE(env->fpu->fcr31) & tmp)
do_raise_exception(EXCP_FPE);
else
- UPDATE_FP_FLAGS(env->fcr31, tmp);
+ UPDATE_FP_FLAGS(env->fpu->fcr31, tmp);
}
#define FLOAT_OP(name, p) void do_float_##name##_##p(void)
FLOAT_OP(cvtd, s)
{
- set_float_exception_flags(0, &env->fp_status);
- FDT2 = float32_to_float64(FST0, &env->fp_status);
+ set_float_exception_flags(0, &env->fpu->fp_status);
+ FDT2 = float32_to_float64(FST0, &env->fpu->fp_status);
update_fcr31();
}
FLOAT_OP(cvtd, w)
{
- set_float_exception_flags(0, &env->fp_status);
- FDT2 = int32_to_float64(WT0, &env->fp_status);
+ set_float_exception_flags(0, &env->fpu->fp_status);
+ FDT2 = int32_to_float64(WT0, &env->fpu->fp_status);
update_fcr31();
}
FLOAT_OP(cvtd, l)
{
- set_float_exception_flags(0, &env->fp_status);
- FDT2 = int64_to_float64(DT0, &env->fp_status);
+ set_float_exception_flags(0, &env->fpu->fp_status);
+ FDT2 = int64_to_float64(DT0, &env->fpu->fp_status);
update_fcr31();
}
FLOAT_OP(cvtl, d)
{
- set_float_exception_flags(0, &env->fp_status);
- DT2 = float64_to_int64(FDT0, &env->fp_status);
+ set_float_exception_flags(0, &env->fpu->fp_status);
+ DT2 = float64_to_int64(FDT0, &env->fpu->fp_status);
update_fcr31();
- if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
+ if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
DT2 = 0x7fffffffffffffffULL;
}
FLOAT_OP(cvtl, s)
{
- set_float_exception_flags(0, &env->fp_status);
- DT2 = float32_to_int64(FST0, &env->fp_status);
+ set_float_exception_flags(0, &env->fpu->fp_status);
+ DT2 = float32_to_int64(FST0, &env->fpu->fp_status);
update_fcr31();
- if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
+ if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
DT2 = 0x7fffffffffffffffULL;
}
FLOAT_OP(cvtps, pw)
{
- set_float_exception_flags(0, &env->fp_status);
- FST2 = int32_to_float32(WT0, &env->fp_status);
- FSTH2 = int32_to_float32(WTH0, &env->fp_status);
+ set_float_exception_flags(0, &env->fpu->fp_status);
+ FST2 = int32_to_float32(WT0, &env->fpu->fp_status);
+ FSTH2 = int32_to_float32(WTH0, &env->fpu->fp_status);
update_fcr31();
}
FLOAT_OP(cvtpw, ps)
{
- set_float_exception_flags(0, &env->fp_status);
- WT2 = float32_to_int32(FST0, &env->fp_status);
- WTH2 = float32_to_int32(FSTH0, &env->fp_status);
+ set_float_exception_flags(0, &env->fpu->fp_status);
+ WT2 = float32_to_int32(FST0, &env->fpu->fp_status);
+ WTH2 = float32_to_int32(FSTH0, &env->fpu->fp_status);
update_fcr31();
- if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
+ if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
WT2 = 0x7fffffff;
}
FLOAT_OP(cvts, d)
{
- set_float_exception_flags(0, &env->fp_status);
- FST2 = float64_to_float32(FDT0, &env->fp_status);
+ set_float_exception_flags(0, &env->fpu->fp_status);
+ FST2 = float64_to_float32(FDT0, &env->fpu->fp_status);
update_fcr31();
}
FLOAT_OP(cvts, w)
{
- set_float_exception_flags(0, &env->fp_status);
- FST2 = int32_to_float32(WT0, &env->fp_status);
+ set_float_exception_flags(0, &env->fpu->fp_status);
+ FST2 = int32_to_float32(WT0, &env->fpu->fp_status);
update_fcr31();
}
FLOAT_OP(cvts, l)
{
- set_float_exception_flags(0, &env->fp_status);
- FST2 = int64_to_float32(DT0, &env->fp_status);
+ set_float_exception_flags(0, &env->fpu->fp_status);
+ FST2 = int64_to_float32(DT0, &env->fpu->fp_status);
update_fcr31();
}
FLOAT_OP(cvts, pl)
{
- set_float_exception_flags(0, &env->fp_status);
+ set_float_exception_flags(0, &env->fpu->fp_status);
WT2 = WT0;
update_fcr31();
}
FLOAT_OP(cvts, pu)
{
- set_float_exception_flags(0, &env->fp_status);
+ set_float_exception_flags(0, &env->fpu->fp_status);
WT2 = WTH0;
update_fcr31();
}
FLOAT_OP(cvtw, s)
{
- set_float_exception_flags(0, &env->fp_status);
- WT2 = float32_to_int32(FST0, &env->fp_status);
+ set_float_exception_flags(0, &env->fpu->fp_status);
+ WT2 = float32_to_int32(FST0, &env->fpu->fp_status);
update_fcr31();
- if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
+ if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
WT2 = 0x7fffffff;
}
FLOAT_OP(cvtw, d)
{
- set_float_exception_flags(0, &env->fp_status);
- WT2 = float64_to_int32(FDT0, &env->fp_status);
+ set_float_exception_flags(0, &env->fpu->fp_status);
+ WT2 = float64_to_int32(FDT0, &env->fpu->fp_status);
update_fcr31();
- if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
+ if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
WT2 = 0x7fffffff;
}
FLOAT_OP(roundl, d)
{
- set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
- DT2 = float64_to_int64(FDT0, &env->fp_status);
+ set_float_rounding_mode(float_round_nearest_even, &env->fpu->fp_status);
+ DT2 = float64_to_int64(FDT0, &env->fpu->fp_status);
RESTORE_ROUNDING_MODE;
update_fcr31();
- if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
+ if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
DT2 = 0x7fffffffffffffffULL;
}
FLOAT_OP(roundl, s)
{
- set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
- DT2 = float32_to_int64(FST0, &env->fp_status);
+ set_float_rounding_mode(float_round_nearest_even, &env->fpu->fp_status);
+ DT2 = float32_to_int64(FST0, &env->fpu->fp_status);
RESTORE_ROUNDING_MODE;
update_fcr31();
- if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
+ if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
DT2 = 0x7fffffffffffffffULL;
}
FLOAT_OP(roundw, d)
{
- set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
- WT2 = float64_to_int32(FDT0, &env->fp_status);
+ set_float_rounding_mode(float_round_nearest_even, &env->fpu->fp_status);
+ WT2 = float64_to_int32(FDT0, &env->fpu->fp_status);
RESTORE_ROUNDING_MODE;
update_fcr31();
- if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
+ if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
WT2 = 0x7fffffff;
}
FLOAT_OP(roundw, s)
{
- set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
- WT2 = float32_to_int32(FST0, &env->fp_status);
+ set_float_rounding_mode(float_round_nearest_even, &env->fpu->fp_status);
+ WT2 = float32_to_int32(FST0, &env->fpu->fp_status);
RESTORE_ROUNDING_MODE;
update_fcr31();
- if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
+ if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
WT2 = 0x7fffffff;
}
FLOAT_OP(truncl, d)
{
- DT2 = float64_to_int64_round_to_zero(FDT0, &env->fp_status);
+ DT2 = float64_to_int64_round_to_zero(FDT0, &env->fpu->fp_status);
update_fcr31();
- if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
+ if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
DT2 = 0x7fffffffffffffffULL;
}
FLOAT_OP(truncl, s)
{
- DT2 = float32_to_int64_round_to_zero(FST0, &env->fp_status);
+ DT2 = float32_to_int64_round_to_zero(FST0, &env->fpu->fp_status);
update_fcr31();
- if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
+ if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
DT2 = 0x7fffffffffffffffULL;
}
FLOAT_OP(truncw, d)
{
- WT2 = float64_to_int32_round_to_zero(FDT0, &env->fp_status);
+ WT2 = float64_to_int32_round_to_zero(FDT0, &env->fpu->fp_status);
update_fcr31();
- if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
+ if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
WT2 = 0x7fffffff;
}
FLOAT_OP(truncw, s)
{
- WT2 = float32_to_int32_round_to_zero(FST0, &env->fp_status);
+ WT2 = float32_to_int32_round_to_zero(FST0, &env->fpu->fp_status);
update_fcr31();
- if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
+ if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
WT2 = 0x7fffffff;
}
FLOAT_OP(ceill, d)
{
- set_float_rounding_mode(float_round_up, &env->fp_status);
- DT2 = float64_to_int64(FDT0, &env->fp_status);
+ set_float_rounding_mode(float_round_up, &env->fpu->fp_status);
+ DT2 = float64_to_int64(FDT0, &env->fpu->fp_status);
RESTORE_ROUNDING_MODE;
update_fcr31();
- if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
+ if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
DT2 = 0x7fffffffffffffffULL;
}
FLOAT_OP(ceill, s)
{
- set_float_rounding_mode(float_round_up, &env->fp_status);
- DT2 = float32_to_int64(FST0, &env->fp_status);
+ set_float_rounding_mode(float_round_up, &env->fpu->fp_status);
+ DT2 = float32_to_int64(FST0, &env->fpu->fp_status);
RESTORE_ROUNDING_MODE;
update_fcr31();
- if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
+ if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
DT2 = 0x7fffffffffffffffULL;
}
FLOAT_OP(ceilw, d)
{
- set_float_rounding_mode(float_round_up, &env->fp_status);
- WT2 = float64_to_int32(FDT0, &env->fp_status);
+ set_float_rounding_mode(float_round_up, &env->fpu->fp_status);
+ WT2 = float64_to_int32(FDT0, &env->fpu->fp_status);
RESTORE_ROUNDING_MODE;
update_fcr31();
- if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
+ if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
WT2 = 0x7fffffff;
}
FLOAT_OP(ceilw, s)
{
- set_float_rounding_mode(float_round_up, &env->fp_status);
- WT2 = float32_to_int32(FST0, &env->fp_status);
+ set_float_rounding_mode(float_round_up, &env->fpu->fp_status);
+ WT2 = float32_to_int32(FST0, &env->fpu->fp_status);
RESTORE_ROUNDING_MODE;
update_fcr31();
- if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
+ if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
WT2 = 0x7fffffff;
}
FLOAT_OP(floorl, d)
{
- set_float_rounding_mode(float_round_down, &env->fp_status);
- DT2 = float64_to_int64(FDT0, &env->fp_status);
+ set_float_rounding_mode(float_round_down, &env->fpu->fp_status);
+ DT2 = float64_to_int64(FDT0, &env->fpu->fp_status);
RESTORE_ROUNDING_MODE;
update_fcr31();
- if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
+ if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
DT2 = 0x7fffffffffffffffULL;
}
FLOAT_OP(floorl, s)
{
- set_float_rounding_mode(float_round_down, &env->fp_status);
- DT2 = float32_to_int64(FST0, &env->fp_status);
+ set_float_rounding_mode(float_round_down, &env->fpu->fp_status);
+ DT2 = float32_to_int64(FST0, &env->fpu->fp_status);
RESTORE_ROUNDING_MODE;
update_fcr31();
- if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
+ if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
DT2 = 0x7fffffffffffffffULL;
}
FLOAT_OP(floorw, d)
{
- set_float_rounding_mode(float_round_down, &env->fp_status);
- WT2 = float64_to_int32(FDT0, &env->fp_status);
+ set_float_rounding_mode(float_round_down, &env->fpu->fp_status);
+ WT2 = float64_to_int32(FDT0, &env->fpu->fp_status);
RESTORE_ROUNDING_MODE;
update_fcr31();
- if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
+ if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
WT2 = 0x7fffffff;
}
FLOAT_OP(floorw, s)
{
- set_float_rounding_mode(float_round_down, &env->fp_status);
- WT2 = float32_to_int32(FST0, &env->fp_status);
+ set_float_rounding_mode(float_round_down, &env->fpu->fp_status);
+ WT2 = float32_to_int32(FST0, &env->fpu->fp_status);
RESTORE_ROUNDING_MODE;
update_fcr31();
- if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
+ if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
WT2 = 0x7fffffff;
}
/* MIPS specific unary operations */
FLOAT_OP(recip, d)
{
- set_float_exception_flags(0, &env->fp_status);
- FDT2 = float64_div(FLOAT_ONE64, FDT0, &env->fp_status);
+ set_float_exception_flags(0, &env->fpu->fp_status);
+ FDT2 = float64_div(FLOAT_ONE64, FDT0, &env->fpu->fp_status);
update_fcr31();
}
FLOAT_OP(recip, s)
{
- set_float_exception_flags(0, &env->fp_status);
- FST2 = float32_div(FLOAT_ONE32, FST0, &env->fp_status);
+ set_float_exception_flags(0, &env->fpu->fp_status);
+ FST2 = float32_div(FLOAT_ONE32, FST0, &env->fpu->fp_status);
update_fcr31();
}
FLOAT_OP(rsqrt, d)
{
- set_float_exception_flags(0, &env->fp_status);
- FDT2 = float64_sqrt(FDT0, &env->fp_status);
- FDT2 = float64_div(FLOAT_ONE64, FDT2, &env->fp_status);
+ set_float_exception_flags(0, &env->fpu->fp_status);
+ FDT2 = float64_sqrt(FDT0, &env->fpu->fp_status);
+ FDT2 = float64_div(FLOAT_ONE64, FDT2, &env->fpu->fp_status);
update_fcr31();
}
FLOAT_OP(rsqrt, s)
{
- set_float_exception_flags(0, &env->fp_status);
- FST2 = float32_sqrt(FST0, &env->fp_status);
- FST2 = float32_div(FLOAT_ONE32, FST2, &env->fp_status);
+ set_float_exception_flags(0, &env->fpu->fp_status);
+ FST2 = float32_sqrt(FST0, &env->fpu->fp_status);
+ FST2 = float32_div(FLOAT_ONE32, FST2, &env->fpu->fp_status);
update_fcr31();
}
FLOAT_OP(recip1, d)
{
- set_float_exception_flags(0, &env->fp_status);
- FDT2 = float64_div(FLOAT_ONE64, FDT0, &env->fp_status);
+ set_float_exception_flags(0, &env->fpu->fp_status);
+ FDT2 = float64_div(FLOAT_ONE64, FDT0, &env->fpu->fp_status);
update_fcr31();
}
FLOAT_OP(recip1, s)
{
- set_float_exception_flags(0, &env->fp_status);
- FST2 = float32_div(FLOAT_ONE32, FST0, &env->fp_status);
+ set_float_exception_flags(0, &env->fpu->fp_status);
+ FST2 = float32_div(FLOAT_ONE32, FST0, &env->fpu->fp_status);
update_fcr31();
}
FLOAT_OP(recip1, ps)
{
- set_float_exception_flags(0, &env->fp_status);
- FST2 = float32_div(FLOAT_ONE32, FST0, &env->fp_status);
- FSTH2 = float32_div(FLOAT_ONE32, FSTH0, &env->fp_status);
+ set_float_exception_flags(0, &env->fpu->fp_status);
+ FST2 = float32_div(FLOAT_ONE32, FST0, &env->fpu->fp_status);
+ FSTH2 = float32_div(FLOAT_ONE32, FSTH0, &env->fpu->fp_status);
update_fcr31();
}
FLOAT_OP(rsqrt1, d)
{
- set_float_exception_flags(0, &env->fp_status);
- FDT2 = float64_sqrt(FDT0, &env->fp_status);
- FDT2 = float64_div(FLOAT_ONE64, FDT2, &env->fp_status);
+ set_float_exception_flags(0, &env->fpu->fp_status);
+ FDT2 = float64_sqrt(FDT0, &env->fpu->fp_status);
+ FDT2 = float64_div(FLOAT_ONE64, FDT2, &env->fpu->fp_status);
update_fcr31();
}
FLOAT_OP(rsqrt1, s)
{
- set_float_exception_flags(0, &env->fp_status);
- FST2 = float32_sqrt(FST0, &env->fp_status);
- FST2 = float32_div(FLOAT_ONE32, FST2, &env->fp_status);
+ set_float_exception_flags(0, &env->fpu->fp_status);
+ FST2 = float32_sqrt(FST0, &env->fpu->fp_status);
+ FST2 = float32_div(FLOAT_ONE32, FST2, &env->fpu->fp_status);
update_fcr31();
}
FLOAT_OP(rsqrt1, ps)
{
- set_float_exception_flags(0, &env->fp_status);
- FST2 = float32_sqrt(FST0, &env->fp_status);
- FSTH2 = float32_sqrt(FSTH0, &env->fp_status);
- FST2 = float32_div(FLOAT_ONE32, FST2, &env->fp_status);
- FSTH2 = float32_div(FLOAT_ONE32, FSTH2, &env->fp_status);
+ set_float_exception_flags(0, &env->fpu->fp_status);
+ FST2 = float32_sqrt(FST0, &env->fpu->fp_status);
+ FSTH2 = float32_sqrt(FSTH0, &env->fpu->fp_status);
+ FST2 = float32_div(FLOAT_ONE32, FST2, &env->fpu->fp_status);
+ FSTH2 = float32_div(FLOAT_ONE32, FSTH2, &env->fpu->fp_status);
update_fcr31();
}
@@ -996,41 +1017,41 @@ FLOAT_OP(rsqrt1, ps)
#define FLOAT_BINOP(name) \
FLOAT_OP(name, d) \
{ \
- set_float_exception_flags(0, &env->fp_status); \
- FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status); \
- update_fcr31(); \
- if (GET_FP_CAUSE(env->fcr31) & FP_INVALID) \
- FDT2 = 0x7ff7ffffffffffffULL; \
- else if (GET_FP_CAUSE(env->fcr31) & FP_UNDERFLOW) { \
- if ((env->fcr31 & 0x3) == 0) \
- FDT2 &= FLOAT_SIGN64; \
+ set_float_exception_flags(0, &env->fpu->fp_status); \
+ FDT2 = float64_ ## name (FDT0, FDT1, &env->fpu->fp_status); \
+ update_fcr31(); \
+ if (GET_FP_CAUSE(env->fpu->fcr31) & FP_INVALID) \
+ FDT2 = 0x7ff7ffffffffffffULL; \
+ else if (GET_FP_CAUSE(env->fpu->fcr31) & FP_UNDERFLOW) { \
+ if ((env->fpu->fcr31 & 0x3) == 0) \
+ FDT2 &= FLOAT_SIGN64; \
} \
} \
FLOAT_OP(name, s) \
{ \
- set_float_exception_flags(0, &env->fp_status); \
- FST2 = float32_ ## name (FST0, FST1, &env->fp_status); \
- update_fcr31(); \
- if (GET_FP_CAUSE(env->fcr31) & FP_INVALID) \
- FST2 = 0x7fbfffff; \
- else if (GET_FP_CAUSE(env->fcr31) & FP_UNDERFLOW) { \
- if ((env->fcr31 & 0x3) == 0) \
- FST2 &= FLOAT_SIGN32; \
+ set_float_exception_flags(0, &env->fpu->fp_status); \
+ FST2 = float32_ ## name (FST0, FST1, &env->fpu->fp_status); \
+ update_fcr31(); \
+ if (GET_FP_CAUSE(env->fpu->fcr31) & FP_INVALID) \
+ FST2 = 0x7fbfffff; \
+ else if (GET_FP_CAUSE(env->fpu->fcr31) & FP_UNDERFLOW) { \
+ if ((env->fpu->fcr31 & 0x3) == 0) \
+ FST2 &= FLOAT_SIGN32; \
} \
} \
FLOAT_OP(name, ps) \
{ \
- set_float_exception_flags(0, &env->fp_status); \
- FST2 = float32_ ## name (FST0, FST1, &env->fp_status); \
- FSTH2 = float32_ ## name (FSTH0, FSTH1, &env->fp_status); \
+ set_float_exception_flags(0, &env->fpu->fp_status); \
+ FST2 = float32_ ## name (FST0, FST1, &env->fpu->fp_status); \
+ FSTH2 = float32_ ## name (FSTH0, FSTH1, &env->fpu->fp_status); \
update_fcr31(); \
- if (GET_FP_CAUSE(env->fcr31) & FP_INVALID) { \
- FST2 = 0x7fbfffff; \
- FSTH2 = 0x7fbfffff; \
- } else if (GET_FP_CAUSE(env->fcr31) & FP_UNDERFLOW) { \
- if ((env->fcr31 & 0x3) == 0) { \
- FST2 &= FLOAT_SIGN32; \
- FSTH2 &= FLOAT_SIGN32; \
+ if (GET_FP_CAUSE(env->fpu->fcr31) & FP_INVALID) { \
+ FST2 = 0x7fbfffff; \
+ FSTH2 = 0x7fbfffff; \
+ } else if (GET_FP_CAUSE(env->fpu->fcr31) & FP_UNDERFLOW) { \
+ if ((env->fpu->fcr31 & 0x3) == 0) { \
+ FST2 &= FLOAT_SIGN32; \
+ FSTH2 &= FLOAT_SIGN32; \
} \
} \
}
@@ -1043,69 +1064,69 @@ FLOAT_BINOP(div)
/* MIPS specific binary operations */
FLOAT_OP(recip2, d)
{
- set_float_exception_flags(0, &env->fp_status);
- FDT2 = float64_mul(FDT0, FDT2, &env->fp_status);
- FDT2 = float64_sub(FDT2, FLOAT_ONE64, &env->fp_status) ^ FLOAT_SIGN64;
+ set_float_exception_flags(0, &env->fpu->fp_status);
+ FDT2 = float64_mul(FDT0, FDT2, &env->fpu->fp_status);
+ FDT2 = float64_sub(FDT2, FLOAT_ONE64, &env->fpu->fp_status) ^ FLOAT_SIGN64;
update_fcr31();
}
FLOAT_OP(recip2, s)
{
- set_float_exception_flags(0, &env->fp_status);
- FST2 = float32_mul(FST0, FST2, &env->fp_status);
- FST2 = float32_sub(FST2, FLOAT_ONE32, &env->fp_status) ^ FLOAT_SIGN32;
+ set_float_exception_flags(0, &env->fpu->fp_status);
+ FST2 = float32_mul(FST0, FST2, &env->fpu->fp_status);
+ FST2 = float32_sub(FST2, FLOAT_ONE32, &env->fpu->fp_status) ^ FLOAT_SIGN32;
update_fcr31();
}
FLOAT_OP(recip2, ps)
{
- set_float_exception_flags(0, &env->fp_status);
- FST2 = float32_mul(FST0, FST2, &env->fp_status);
- FSTH2 = float32_mul(FSTH0, FSTH2, &env->fp_status);
- FST2 = float32_sub(FST2, FLOAT_ONE32, &env->fp_status) ^ FLOAT_SIGN32;
- FSTH2 = float32_sub(FSTH2, FLOAT_ONE32, &env->fp_status) ^ FLOAT_SIGN32;
+ set_float_exception_flags(0, &env->fpu->fp_status);
+ FST2 = float32_mul(FST0, FST2, &env->fpu->fp_status);
+ FSTH2 = float32_mul(FSTH0, FSTH2, &env->fpu->fp_status);
+ FST2 = float32_sub(FST2, FLOAT_ONE32, &env->fpu->fp_status) ^ FLOAT_SIGN32;
+ FSTH2 = float32_sub(FSTH2, FLOAT_ONE32, &env->fpu->fp_status) ^ FLOAT_SIGN32;
update_fcr31();
}
FLOAT_OP(rsqrt2, d)
{
- set_float_exception_flags(0, &env->fp_status);
- FDT2 = float64_mul(FDT0, FDT2, &env->fp_status);
- FDT2 = float64_sub(FDT2, FLOAT_ONE64, &env->fp_status);
- FDT2 = float64_div(FDT2, FLOAT_TWO64, &env->fp_status) ^ FLOAT_SIGN64;
+ set_float_exception_flags(0, &env->fpu->fp_status);
+ FDT2 = float64_mul(FDT0, FDT2, &env->fpu->fp_status);
+ FDT2 = float64_sub(FDT2, FLOAT_ONE64, &env->fpu->fp_status);
+ FDT2 = float64_div(FDT2, FLOAT_TWO64, &env->fpu->fp_status) ^ FLOAT_SIGN64;
update_fcr31();
}
FLOAT_OP(rsqrt2, s)
{
- set_float_exception_flags(0, &env->fp_status);
- FST2 = float32_mul(FST0, FST2, &env->fp_status);
- FST2 = float32_sub(FST2, FLOAT_ONE32, &env->fp_status);
- FST2 = float32_div(FST2, FLOAT_TWO32, &env->fp_status) ^ FLOAT_SIGN32;
+ set_float_exception_flags(0, &env->fpu->fp_status);
+ FST2 = float32_mul(FST0, FST2, &env->fpu->fp_status);
+ FST2 = float32_sub(FST2, FLOAT_ONE32, &env->fpu->fp_status);
+ FST2 = float32_div(FST2, FLOAT_TWO32, &env->fpu->fp_status) ^ FLOAT_SIGN32;
update_fcr31();
}
FLOAT_OP(rsqrt2, ps)
{
- set_float_exception_flags(0, &env->fp_status);
- FST2 = float32_mul(FST0, FST2, &env->fp_status);
- FSTH2 = float32_mul(FSTH0, FSTH2, &env->fp_status);
- FST2 = float32_sub(FST2, FLOAT_ONE32, &env->fp_status);
- FSTH2 = float32_sub(FSTH2, FLOAT_ONE32, &env->fp_status);
- FST2 = float32_div(FST2, FLOAT_TWO32, &env->fp_status) ^ FLOAT_SIGN32;
- FSTH2 = float32_div(FSTH2, FLOAT_TWO32, &env->fp_status) ^ FLOAT_SIGN32;
+ set_float_exception_flags(0, &env->fpu->fp_status);
+ FST2 = float32_mul(FST0, FST2, &env->fpu->fp_status);
+ FSTH2 = float32_mul(FSTH0, FSTH2, &env->fpu->fp_status);
+ FST2 = float32_sub(FST2, FLOAT_ONE32, &env->fpu->fp_status);
+ FSTH2 = float32_sub(FSTH2, FLOAT_ONE32, &env->fpu->fp_status);
+ FST2 = float32_div(FST2, FLOAT_TWO32, &env->fpu->fp_status) ^ FLOAT_SIGN32;
+ FSTH2 = float32_div(FSTH2, FLOAT_TWO32, &env->fpu->fp_status) ^ FLOAT_SIGN32;
update_fcr31();
}
FLOAT_OP(addr, ps)
{
- set_float_exception_flags(0, &env->fp_status);
- FST2 = float32_add (FST0, FSTH0, &env->fp_status);
- FSTH2 = float32_add (FST1, FSTH1, &env->fp_status);
+ set_float_exception_flags(0, &env->fpu->fp_status);
+ FST2 = float32_add (FST0, FSTH0, &env->fpu->fp_status);
+ FSTH2 = float32_add (FST1, FSTH1, &env->fpu->fp_status);
update_fcr31();
}
FLOAT_OP(mulr, ps)
{
- set_float_exception_flags(0, &env->fp_status);
- FST2 = float32_mul (FST0, FSTH0, &env->fp_status);
- FSTH2 = float32_mul (FST1, FSTH1, &env->fp_status);
+ set_float_exception_flags(0, &env->fpu->fp_status);
+ FST2 = float32_mul (FST0, FSTH0, &env->fpu->fp_status);
+ FSTH2 = float32_mul (FST1, FSTH1, &env->fpu->fp_status);
update_fcr31();
}
@@ -1116,9 +1137,9 @@ void do_cmp_d_ ## op (long cc) \
int c = cond; \
update_fcr31(); \
if (c) \
- SET_FP_COND(cc, env); \
+ SET_FP_COND(cc, env->fpu); \
else \
- CLEAR_FP_COND(cc, env); \
+ CLEAR_FP_COND(cc, env->fpu); \
} \
void do_cmpabs_d_ ## op (long cc) \
{ \
@@ -1128,9 +1149,9 @@ void do_cmpabs_d_ ## op (long cc) \
c = cond; \
update_fcr31(); \
if (c) \
- SET_FP_COND(cc, env); \
+ SET_FP_COND(cc, env->fpu); \
else \
- CLEAR_FP_COND(cc, env); \
+ CLEAR_FP_COND(cc, env->fpu); \
}
int float64_is_unordered(int sig, float64 a, float64 b STATUS_PARAM)
@@ -1149,24 +1170,24 @@ int float64_is_unordered(int sig, float64 a, float64 b STATUS_PARAM)
/* NOTE: the comma operator will make "cond" to eval to false,
* but float*_is_unordered() is still called. */
-FOP_COND_D(f, (float64_is_unordered(0, FDT1, FDT0, &env->fp_status), 0))
-FOP_COND_D(un, float64_is_unordered(0, FDT1, FDT0, &env->fp_status))
-FOP_COND_D(eq, !float64_is_unordered(0, FDT1, FDT0, &env->fp_status) && float64_eq(FDT0, FDT1, &env->fp_status))
-FOP_COND_D(ueq, float64_is_unordered(0, FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status))
-FOP_COND_D(olt, !float64_is_unordered(0, FDT1, FDT0, &env->fp_status) && float64_lt(FDT0, FDT1, &env->fp_status))
-FOP_COND_D(ult, float64_is_unordered(0, FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status))
-FOP_COND_D(ole, !float64_is_unordered(0, FDT1, FDT0, &env->fp_status) && float64_le(FDT0, FDT1, &env->fp_status))
-FOP_COND_D(ule, float64_is_unordered(0, FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status))
+FOP_COND_D(f, (float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status), 0))
+FOP_COND_D(un, float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status))
+FOP_COND_D(eq, !float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status) && float64_eq(FDT0, FDT1, &env->fpu->fp_status))
+FOP_COND_D(ueq, float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status) || float64_eq(FDT0, FDT1, &env->fpu->fp_status))
+FOP_COND_D(olt, !float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status) && float64_lt(FDT0, FDT1, &env->fpu->fp_status))
+FOP_COND_D(ult, float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status) || float64_lt(FDT0, FDT1, &env->fpu->fp_status))
+FOP_COND_D(ole, !float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status) && float64_le(FDT0, FDT1, &env->fpu->fp_status))
+FOP_COND_D(ule, float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status) || float64_le(FDT0, FDT1, &env->fpu->fp_status))
/* NOTE: the comma operator will make "cond" to eval to false,
* but float*_is_unordered() is still called. */
-FOP_COND_D(sf, (float64_is_unordered(1, FDT1, FDT0, &env->fp_status), 0))
-FOP_COND_D(ngle,float64_is_unordered(1, FDT1, FDT0, &env->fp_status))
-FOP_COND_D(seq, !float64_is_unordered(1, FDT1, FDT0, &env->fp_status) && float64_eq(FDT0, FDT1, &env->fp_status))
-FOP_COND_D(ngl, float64_is_unordered(1, FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status))
-FOP_COND_D(lt, !float64_is_unordered(1, FDT1, FDT0, &env->fp_status) && float64_lt(FDT0, FDT1, &env->fp_status))
-FOP_COND_D(nge, float64_is_unordered(1, FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status))
-FOP_COND_D(le, !float64_is_unordered(1, FDT1, FDT0, &env->fp_status) && float64_le(FDT0, FDT1, &env->fp_status))
-FOP_COND_D(ngt, float64_is_unordered(1, FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status))
+FOP_COND_D(sf, (float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status), 0))
+FOP_COND_D(ngle,float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status))
+FOP_COND_D(seq, !float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status) && float64_eq(FDT0, FDT1, &env->fpu->fp_status))
+FOP_COND_D(ngl, float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status) || float64_eq(FDT0, FDT1, &env->fpu->fp_status))
+FOP_COND_D(lt, !float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status) && float64_lt(FDT0, FDT1, &env->fpu->fp_status))
+FOP_COND_D(nge, float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status) || float64_lt(FDT0, FDT1, &env->fpu->fp_status))
+FOP_COND_D(le, !float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status) && float64_le(FDT0, FDT1, &env->fpu->fp_status))
+FOP_COND_D(ngt, float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status) || float64_le(FDT0, FDT1, &env->fpu->fp_status))
#define FOP_COND_S(op, cond) \
void do_cmp_s_ ## op (long cc) \
@@ -1174,9 +1195,9 @@ void do_cmp_s_ ## op (long cc) \
int c = cond; \
update_fcr31(); \
if (c) \
- SET_FP_COND(cc, env); \
+ SET_FP_COND(cc, env->fpu); \
else \
- CLEAR_FP_COND(cc, env); \
+ CLEAR_FP_COND(cc, env->fpu); \
} \
void do_cmpabs_s_ ## op (long cc) \
{ \
@@ -1186,9 +1207,9 @@ void do_cmpabs_s_ ## op (long cc) \
c = cond; \
update_fcr31(); \
if (c) \
- SET_FP_COND(cc, env); \
+ SET_FP_COND(cc, env->fpu); \
else \
- CLEAR_FP_COND(cc, env); \
+ CLEAR_FP_COND(cc, env->fpu); \
}
flag float32_is_unordered(int sig, float32 a, float32 b STATUS_PARAM)
@@ -1207,24 +1228,24 @@ flag float32_is_unordered(int sig, float32 a, float32 b STATUS_PARAM)
/* NOTE: the comma operator will make "cond" to eval to false,
* but float*_is_unordered() is still called. */
-FOP_COND_S(f, (float32_is_unordered(0, FST1, FST0, &env->fp_status), 0))
-FOP_COND_S(un, float32_is_unordered(0, FST1, FST0, &env->fp_status))
-FOP_COND_S(eq, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_eq(FST0, FST1, &env->fp_status))
-FOP_COND_S(ueq, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status))
-FOP_COND_S(olt, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_lt(FST0, FST1, &env->fp_status))
-FOP_COND_S(ult, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status))
-FOP_COND_S(ole, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_le(FST0, FST1, &env->fp_status))
-FOP_COND_S(ule, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status))
+FOP_COND_S(f, (float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status), 0))
+FOP_COND_S(un, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status))
+FOP_COND_S(eq, !float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) && float32_eq(FST0, FST1, &env->fpu->fp_status))
+FOP_COND_S(ueq, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) || float32_eq(FST0, FST1, &env->fpu->fp_status))
+FOP_COND_S(olt, !float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) && float32_lt(FST0, FST1, &env->fpu->fp_status))
+FOP_COND_S(ult, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) || float32_lt(FST0, FST1, &env->fpu->fp_status))
+FOP_COND_S(ole, !float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) && float32_le(FST0, FST1, &env->fpu->fp_status))
+FOP_COND_S(ule, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) || float32_le(FST0, FST1, &env->fpu->fp_status))
/* NOTE: the comma operator will make "cond" to eval to false,
* but float*_is_unordered() is still called. */
-FOP_COND_S(sf, (float32_is_unordered(1, FST1, FST0, &env->fp_status), 0))
-FOP_COND_S(ngle,float32_is_unordered(1, FST1, FST0, &env->fp_status))
-FOP_COND_S(seq, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_eq(FST0, FST1, &env->fp_status))
-FOP_COND_S(ngl, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status))
-FOP_COND_S(lt, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_lt(FST0, FST1, &env->fp_status))
-FOP_COND_S(nge, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status))
-FOP_COND_S(le, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_le(FST0, FST1, &env->fp_status))
-FOP_COND_S(ngt, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status))
+FOP_COND_S(sf, (float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status), 0))
+FOP_COND_S(ngle,float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status))
+FOP_COND_S(seq, !float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) && float32_eq(FST0, FST1, &env->fpu->fp_status))
+FOP_COND_S(ngl, float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) || float32_eq(FST0, FST1, &env->fpu->fp_status))
+FOP_COND_S(lt, !float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) && float32_lt(FST0, FST1, &env->fpu->fp_status))
+FOP_COND_S(nge, float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) || float32_lt(FST0, FST1, &env->fpu->fp_status))
+FOP_COND_S(le, !float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) && float32_le(FST0, FST1, &env->fpu->fp_status))
+FOP_COND_S(ngt, float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) || float32_le(FST0, FST1, &env->fpu->fp_status))
#define FOP_COND_PS(op, condl, condh) \
void do_cmp_ps_ ## op (long cc) \
@@ -1233,13 +1254,13 @@ void do_cmp_ps_ ## op (long cc) \
int ch = condh; \
update_fcr31(); \
if (cl) \
- SET_FP_COND(cc, env); \
+ SET_FP_COND(cc, env->fpu); \
else \
- CLEAR_FP_COND(cc, env); \
+ CLEAR_FP_COND(cc, env->fpu); \
if (ch) \
- SET_FP_COND(cc + 1, env); \
+ SET_FP_COND(cc + 1, env->fpu); \
else \
- CLEAR_FP_COND(cc + 1, env); \
+ CLEAR_FP_COND(cc + 1, env->fpu); \
} \
void do_cmpabs_ps_ ## op (long cc) \
{ \
@@ -1252,48 +1273,48 @@ void do_cmpabs_ps_ ## op (long cc) \
ch = condh; \
update_fcr31(); \
if (cl) \
- SET_FP_COND(cc, env); \
+ SET_FP_COND(cc, env->fpu); \
else \
- CLEAR_FP_COND(cc, env); \
+ CLEAR_FP_COND(cc, env->fpu); \
if (ch) \
- SET_FP_COND(cc + 1, env); \
+ SET_FP_COND(cc + 1, env->fpu); \
else \
- CLEAR_FP_COND(cc + 1, env); \
+ CLEAR_FP_COND(cc + 1, env->fpu); \
}
/* NOTE: the comma operator will make "cond" to eval to false,
* but float*_is_unordered() is still called. */
-FOP_COND_PS(f, (float32_is_unordered(0, FST1, FST0, &env->fp_status), 0),
- (float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status), 0))
-FOP_COND_PS(un, float32_is_unordered(0, FST1, FST0, &env->fp_status),
- float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status))
-FOP_COND_PS(eq, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_eq(FST0, FST1, &env->fp_status),
- !float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) && float32_eq(FSTH0, FSTH1, &env->fp_status))
-FOP_COND_PS(ueq, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status),
- float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) || float32_eq(FSTH0, FSTH1, &env->fp_status))
-FOP_COND_PS(olt, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_lt(FST0, FST1, &env->fp_status),
- !float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) && float32_lt(FSTH0, FSTH1, &env->fp_status))
-FOP_COND_PS(ult, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status),
- float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) || float32_lt(FSTH0, FSTH1, &env->fp_status))
-FOP_COND_PS(ole, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_le(FST0, FST1, &env->fp_status),
- !float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) && float32_le(FSTH0, FSTH1, &env->fp_status))
-FOP_COND_PS(ule, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status),
- float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) || float32_le(FSTH0, FSTH1, &env->fp_status))
+FOP_COND_PS(f, (float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status), 0),
+ (float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status), 0))
+FOP_COND_PS(un, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status),
+ float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status))
+FOP_COND_PS(eq, !float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) && float32_eq(FST0, FST1, &env->fpu->fp_status),
+ !float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status) && float32_eq(FSTH0, FSTH1, &env->fpu->fp_status))
+FOP_COND_PS(ueq, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) || float32_eq(FST0, FST1, &env->fpu->fp_status),
+ float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status) || float32_eq(FSTH0, FSTH1, &env->fpu->fp_status))
+FOP_COND_PS(olt, !float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) && float32_lt(FST0, FST1, &env->fpu->fp_status),
+ !float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status) && float32_lt(FSTH0, FSTH1, &env->fpu->fp_status))
+FOP_COND_PS(ult, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) || float32_lt(FST0, FST1, &env->fpu->fp_status),
+ float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status) || float32_lt(FSTH0, FSTH1, &env->fpu->fp_status))
+FOP_COND_PS(ole, !float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) && float32_le(FST0, FST1, &env->fpu->fp_status),
+ !float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status) && float32_le(FSTH0, FSTH1, &env->fpu->fp_status))
+FOP_COND_PS(ule, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) || float32_le(FST0, FST1, &env->fpu->fp_status),
+ float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status) || float32_le(FSTH0, FSTH1, &env->fpu->fp_status))
/* NOTE: the comma operator will make "cond" to eval to false,
* but float*_is_unordered() is still called. */
-FOP_COND_PS(sf, (float32_is_unordered(1, FST1, FST0, &env->fp_status), 0),
- (float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status), 0))
-FOP_COND_PS(ngle,float32_is_unordered(1, FST1, FST0, &env->fp_status),
- float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status))
-FOP_COND_PS(seq, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_eq(FST0, FST1, &env->fp_status),
- !float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) && float32_eq(FSTH0, FSTH1, &env->fp_status))
-FOP_COND_PS(ngl, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status),
- float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) || float32_eq(FSTH0, FSTH1, &env->fp_status))
-FOP_COND_PS(lt, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_lt(FST0, FST1, &env->fp_status),
- !float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) && float32_lt(FSTH0, FSTH1, &env->fp_status))
-FOP_COND_PS(nge, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status),
- float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) || float32_lt(FSTH0, FSTH1, &env->fp_status))
-FOP_COND_PS(le, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_le(FST0, FST1, &env->fp_status),
- !float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) && float32_le(FSTH0, FSTH1, &env->fp_status))
-FOP_COND_PS(ngt, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status),
- float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) || float32_le(FSTH0, FSTH1, &env->fp_status))
+FOP_COND_PS(sf, (float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status), 0),
+ (float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status), 0))
+FOP_COND_PS(ngle,float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status),
+ float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status))
+FOP_COND_PS(seq, !float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) && float32_eq(FST0, FST1, &env->fpu->fp_status),
+ !float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status) && float32_eq(FSTH0, FSTH1, &env->fpu->fp_status))
+FOP_COND_PS(ngl, float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) || float32_eq(FST0, FST1, &env->fpu->fp_status),
+ float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status) || float32_eq(FSTH0, FSTH1, &env->fpu->fp_status))
+FOP_COND_PS(lt, !float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) && float32_lt(FST0, FST1, &env->fpu->fp_status),
+ !float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status) && float32_lt(FSTH0, FSTH1, &env->fpu->fp_status))
+FOP_COND_PS(nge, float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) || float32_lt(FST0, FST1, &env->fpu->fp_status),
+ float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status) || float32_lt(FSTH0, FSTH1, &env->fpu->fp_status))
+FOP_COND_PS(le, !float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) && float32_le(FST0, FST1, &env->fpu->fp_status),
+ !float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status) && float32_le(FSTH0, FSTH1, &env->fpu->fp_status))
+FOP_COND_PS(ngt, float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) || float32_le(FST0, FST1, &env->fpu->fp_status),
+ float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status) || float32_le(FSTH0, FSTH1, &env->fpu->fp_status))
diff --git a/target-mips/op_template.c b/target-mips/op_template.c
index 8236acc18e..41d954c1db 100644
--- a/target-mips/op_template.c
+++ b/target-mips/op_template.c
@@ -21,31 +21,44 @@
#if defined(REG)
void glue(op_load_gpr_T0_gpr, REG) (void)
{
- T0 = env->gpr[REG];
+ T0 = env->gpr[REG][env->current_tc];
RETURN();
}
void glue(op_store_T0_gpr_gpr, REG) (void)
{
- env->gpr[REG] = T0;
+ env->gpr[REG][env->current_tc] = T0;
RETURN();
}
void glue(op_load_gpr_T1_gpr, REG) (void)
{
- T1 = env->gpr[REG];
+ T1 = env->gpr[REG][env->current_tc];
RETURN();
}
void glue(op_store_T1_gpr_gpr, REG) (void)
{
- env->gpr[REG] = T1;
+ env->gpr[REG][env->current_tc] = T1;
RETURN();
}
void glue(op_load_gpr_T2_gpr, REG) (void)
{
- T2 = env->gpr[REG];
+ T2 = env->gpr[REG][env->current_tc];
+ RETURN();
+}
+
+
+void glue(op_load_srsgpr_T0_gpr, REG) (void)
+{
+ T0 = env->gpr[REG][(env->CP0_SRSCtl >> CP0SRSCtl_PSS) & 0xf];
+ RETURN();
+}
+
+void glue(op_store_T0_srsgpr_gpr, REG) (void)
+{
+ env->gpr[REG][(env->CP0_SRSCtl >> CP0SRSCtl_PSS) & 0xf] = T0;
RETURN();
}
#endif
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 07dca14595..c87f2c9874 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -266,6 +266,8 @@ enum {
OPC_DINSM = 0x05 | OPC_SPECIAL3,
OPC_DINSU = 0x06 | OPC_SPECIAL3,
OPC_DINS = 0x07 | OPC_SPECIAL3,
+ OPC_FORK = 0x08 | OPC_SPECIAL3,
+ OPC_YIELD = 0x09 | OPC_SPECIAL3,
OPC_BSHFL = 0x20 | OPC_SPECIAL3,
OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
OPC_RDHWR = 0x3B | OPC_SPECIAL3,
@@ -296,8 +298,10 @@ enum {
OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
OPC_MTC0 = (0x04 << 21) | OPC_CP0,
OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
+ OPC_MFTR = (0x08 << 21) | OPC_CP0,
OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
+ OPC_MTTR = (0x0C << 21) | OPC_CP0,
OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
OPC_C0 = (0x10 << 21) | OPC_CP0,
OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
@@ -308,6 +312,10 @@ enum {
#define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
enum {
+ OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
+ OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
+ OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
+ OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
};
@@ -441,6 +449,10 @@ GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr);
GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr);
GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr);
+/* Moves to/from shadow registers */
+GEN32(gen_op_load_srsgpr_T0, gen_op_load_srsgpr_T0_gpr);
+GEN32(gen_op_store_T0_srsgpr, gen_op_store_T0_srsgpr_gpr);
+
static const char *fregnames[] =
{ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
"f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
@@ -569,6 +581,15 @@ do { \
} \
} while (0)
+#define GEN_LOAD_SRSREG_TN(Tn, Rn) \
+do { \
+ if (Rn == 0) { \
+ glue(gen_op_reset_, Tn)(); \
+ } else { \
+ glue(gen_op_load_srsgpr_, Tn)(Rn); \
+ } \
+} while (0)
+
#ifdef TARGET_MIPS64
#define GEN_LOAD_IMM_TN(Tn, Imm) \
do { \
@@ -598,6 +619,13 @@ do { \
} \
} while (0)
+#define GEN_STORE_TN_SRSREG(Rn, Tn) \
+do { \
+ if (Rn != 0) { \
+ glue(glue(gen_op_store_, Tn),_srsgpr)(Rn); \
+ } \
+} while (0)
+
#define GEN_LOAD_FREG_FTN(FTn, Fn) \
do { \
glue(gen_op_load_fpr_, FTn)(Fn); \
@@ -740,6 +768,14 @@ static inline void check_mips_r2(CPUState *env, DisasContext *ctx)
generate_exception(ctx, EXCP_RI);
}
+/* This code generates a "reserved instruction" exception if the
+ CPU is not MIPS MT capable. */
+static inline void check_mips_mt(CPUState *env, DisasContext *ctx)
+{
+ if (!(env->CP0_Config3 & (1 << CP0C3_MT)))
+ generate_exception(ctx, EXCP_RI);
+}
+
#if defined(CONFIG_USER_ONLY)
#define op_ldst(name) gen_op_##name##_raw()
#define OP_LD_TABLE(width)
@@ -806,8 +842,7 @@ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
gen_op_addr_add();
}
/* Don't do NOP if destination is zero: we must perform the actual
- * memory access
- */
+ memory access. */
switch (opc) {
#ifdef TARGET_MIPS64
case OPC_LWU:
@@ -958,8 +993,7 @@ static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
gen_op_addr_add();
}
/* Don't do NOP if destination is zero: we must perform the actual
- * memory access
- */
+ memory access. */
switch (opc) {
case OPC_LWC1:
op_ldst(lwc1);
@@ -997,9 +1031,8 @@ static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt,
const char *opn = "imm arith";
if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
- /* if no destination, treat it as a NOP
- * For addi, we must generate the overflow exception when needed.
- */
+ /* If no destination, treat it as a NOP.
+ For addi, we must generate the overflow exception when needed. */
MIPS_DEBUG("NOP");
return;
}
@@ -1175,9 +1208,8 @@ static void gen_arith (DisasContext *ctx, uint32_t opc,
if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
&& opc != OPC_DADD && opc != OPC_DSUB) {
- /* if no destination, treat it as a NOP
- * For add & sub, we must generate the overflow exception when needed.
- */
+ /* If no destination, treat it as a NOP.
+ For add & sub, we must generate the overflow exception when needed. */
MIPS_DEBUG("NOP");
return;
}
@@ -1324,29 +1356,29 @@ static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
const char *opn = "hilo";
if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
- /* Treat as a NOP */
+ /* Treat as NOP. */
MIPS_DEBUG("NOP");
return;
}
switch (opc) {
case OPC_MFHI:
- gen_op_load_HI();
+ gen_op_load_HI(0);
GEN_STORE_TN_REG(reg, T0);
opn = "mfhi";
break;
case OPC_MFLO:
- gen_op_load_LO();
+ gen_op_load_LO(0);
GEN_STORE_TN_REG(reg, T0);
opn = "mflo";
break;
case OPC_MTHI:
GEN_LOAD_REG_TN(T0, reg);
- gen_op_store_HI();
+ gen_op_store_HI(0);
opn = "mthi";
break;
case OPC_MTLO:
GEN_LOAD_REG_TN(T0, reg);
- gen_op_store_LO();
+ gen_op_store_LO(0);
opn = "mtlo";
break;
default:
@@ -1428,7 +1460,7 @@ static void gen_cl (DisasContext *ctx, uint32_t opc,
{
const char *opn = "CLx";
if (rd == 0) {
- /* Treat as a NOP */
+ /* Treat as NOP. */
MIPS_DEBUG("NOP");
return;
}
@@ -1514,7 +1546,7 @@ static void gen_trap (DisasContext *ctx, uint32_t opc,
case OPC_TLTIU: /* r0 < 0 unsigned */
case OPC_TNE: /* rs != rs */
case OPC_TNEI: /* r0 != 0 */
- /* Never trap: treat as NOP */
+ /* Never trap: treat as NOP. */
return;
default:
MIPS_INVAL("trap");
@@ -1674,7 +1706,7 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
case OPC_BNE: /* rx != rx */
case OPC_BGTZ: /* 0 > 0 */
case OPC_BLTZ: /* 0 < 0 */
- /* Treated as NOP */
+ /* Treat as NOP. */
MIPS_DEBUG("bnever (NOP)");
return;
case OPC_BLTZAL: /* 0 < 0 */
@@ -1886,17 +1918,20 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
rn = "Index";
break;
case 1:
-// gen_op_mfc0_mvpcontrol(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mfc0_mvpcontrol();
rn = "MVPControl";
-// break;
+ break;
case 2:
-// gen_op_mfc0_mvpconf0(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mfc0_mvpconf0();
rn = "MVPConf0";
-// break;
+ break;
case 3:
-// gen_op_mfc0_mvpconf1(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mfc0_mvpconf1();
rn = "MVPConf1";
-// break;
+ break;
default:
goto die;
}
@@ -1908,33 +1943,40 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
rn = "Random";
break;
case 1:
-// gen_op_mfc0_vpecontrol(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mfc0_vpecontrol();
rn = "VPEControl";
-// break;
+ break;
case 2:
-// gen_op_mfc0_vpeconf0(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mfc0_vpeconf0();
rn = "VPEConf0";
-// break;
+ break;
case 3:
-// gen_op_mfc0_vpeconf1(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mfc0_vpeconf1();
rn = "VPEConf1";
-// break;
+ break;
case 4:
-// gen_op_mfc0_YQMask(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mfc0_yqmask();
rn = "YQMask";
-// break;
+ break;
case 5:
-// gen_op_mfc0_vpeschedule(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mfc0_vpeschedule();
rn = "VPESchedule";
-// break;
+ break;
case 6:
-// gen_op_mfc0_vpeschefback(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mfc0_vpeschefback();
rn = "VPEScheFBack";
-// break;
+ break;
case 7:
-// gen_op_mfc0_vpeopt(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mfc0_vpeopt();
rn = "VPEOpt";
-// break;
+ break;
default:
goto die;
}
@@ -1946,33 +1988,40 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
rn = "EntryLo0";
break;
case 1:
-// gen_op_mfc0_tcstatus(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mfc0_tcstatus();
rn = "TCStatus";
-// break;
+ break;
case 2:
-// gen_op_mfc0_tcbind(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mfc0_tcbind();
rn = "TCBind";
-// break;
+ break;
case 3:
-// gen_op_mfc0_tcrestart(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mfc0_tcrestart();
rn = "TCRestart";
-// break;
+ break;
case 4:
-// gen_op_mfc0_tchalt(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mfc0_tchalt();
rn = "TCHalt";
-// break;
+ break;
case 5:
-// gen_op_mfc0_tccontext(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mfc0_tccontext();
rn = "TCContext";
-// break;
+ break;
case 6:
-// gen_op_mfc0_tcschedule(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mfc0_tcschedule();
rn = "TCSchedule";
-// break;
+ break;
case 7:
-// gen_op_mfc0_tcschefback(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mfc0_tcschefback();
rn = "TCScheFBack";
-// break;
+ break;
default:
goto die;
}
@@ -2023,25 +2072,25 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
rn = "Wired";
break;
case 1:
-// gen_op_mfc0_srsconf0(); /* shadow registers */
+ gen_op_mfc0_srsconf0();
rn = "SRSConf0";
-// break;
+ break;
case 2:
-// gen_op_mfc0_srsconf1(); /* shadow registers */
+ gen_op_mfc0_srsconf1();
rn = "SRSConf1";
-// break;
+ break;
case 3:
-// gen_op_mfc0_srsconf2(); /* shadow registers */
+ gen_op_mfc0_srsconf2();
rn = "SRSConf2";
-// break;
+ break;
case 4:
-// gen_op_mfc0_srsconf3(); /* shadow registers */
+ gen_op_mfc0_srsconf3();
rn = "SRSConf3";
-// break;
+ break;
case 5:
-// gen_op_mfc0_srsconf4(); /* shadow registers */
+ gen_op_mfc0_srsconf4();
rn = "SRSConf4";
-// break;
+ break;
default:
goto die;
}
@@ -2430,17 +2479,20 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
rn = "Index";
break;
case 1:
-// gen_op_mtc0_mvpcontrol(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mtc0_mvpcontrol();
rn = "MVPControl";
-// break;
+ break;
case 2:
-// gen_op_mtc0_mvpconf0(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ /* ignored */
rn = "MVPConf0";
-// break;
+ break;
case 3:
-// gen_op_mtc0_mvpconf1(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ /* ignored */
rn = "MVPConf1";
-// break;
+ break;
default:
goto die;
}
@@ -2452,33 +2504,40 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
rn = "Random";
break;
case 1:
-// gen_op_mtc0_vpecontrol(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mtc0_vpecontrol();
rn = "VPEControl";
-// break;
+ break;
case 2:
-// gen_op_mtc0_vpeconf0(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mtc0_vpeconf0();
rn = "VPEConf0";
-// break;
+ break;
case 3:
-// gen_op_mtc0_vpeconf1(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mtc0_vpeconf1();
rn = "VPEConf1";
-// break;
+ break;
case 4:
-// gen_op_mtc0_YQMask(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mtc0_yqmask();
rn = "YQMask";
-// break;
+ break;
case 5:
-// gen_op_mtc0_vpeschedule(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mtc0_vpeschedule();
rn = "VPESchedule";
-// break;
+ break;
case 6:
-// gen_op_mtc0_vpeschefback(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mtc0_vpeschefback();
rn = "VPEScheFBack";
-// break;
+ break;
case 7:
-// gen_op_mtc0_vpeopt(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mtc0_vpeopt();
rn = "VPEOpt";
-// break;
+ break;
default:
goto die;
}
@@ -2490,33 +2549,40 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
rn = "EntryLo0";
break;
case 1:
-// gen_op_mtc0_tcstatus(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mtc0_tcstatus();
rn = "TCStatus";
-// break;
+ break;
case 2:
-// gen_op_mtc0_tcbind(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mtc0_tcbind();
rn = "TCBind";
-// break;
+ break;
case 3:
-// gen_op_mtc0_tcrestart(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mtc0_tcrestart();
rn = "TCRestart";
-// break;
+ break;
case 4:
-// gen_op_mtc0_tchalt(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mtc0_tchalt();
rn = "TCHalt";
-// break;
+ break;
case 5:
-// gen_op_mtc0_tccontext(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mtc0_tccontext();
rn = "TCContext";
-// break;
+ break;
case 6:
-// gen_op_mtc0_tcschedule(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mtc0_tcschedule();
rn = "TCSchedule";
-// break;
+ break;
case 7:
-// gen_op_mtc0_tcschefback(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mtc0_tcschefback();
rn = "TCScheFBack";
-// break;
+ break;
default:
goto die;
}
@@ -2567,25 +2633,25 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
rn = "Wired";
break;
case 1:
-// gen_op_mtc0_srsconf0(); /* shadow registers */
+ gen_op_mtc0_srsconf0();
rn = "SRSConf0";
-// break;
+ break;
case 2:
-// gen_op_mtc0_srsconf1(); /* shadow registers */
+ gen_op_mtc0_srsconf1();
rn = "SRSConf1";
-// break;
+ break;
case 3:
-// gen_op_mtc0_srsconf2(); /* shadow registers */
+ gen_op_mtc0_srsconf2();
rn = "SRSConf2";
-// break;
+ break;
case 4:
-// gen_op_mtc0_srsconf3(); /* shadow registers */
+ gen_op_mtc0_srsconf3();
rn = "SRSConf3";
-// break;
+ break;
case 5:
-// gen_op_mtc0_srsconf4(); /* shadow registers */
+ gen_op_mtc0_srsconf4();
rn = "SRSConf4";
-// break;
+ break;
default:
goto die;
}
@@ -3006,17 +3072,20 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
rn = "Index";
break;
case 1:
-// gen_op_dmfc0_mvpcontrol(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mfc0_mvpcontrol();
rn = "MVPControl";
-// break;
+ break;
case 2:
-// gen_op_dmfc0_mvpconf0(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mfc0_mvpconf0();
rn = "MVPConf0";
-// break;
+ break;
case 3:
-// gen_op_dmfc0_mvpconf1(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mfc0_mvpconf1();
rn = "MVPConf1";
-// break;
+ break;
default:
goto die;
}
@@ -3028,33 +3097,40 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
rn = "Random";
break;
case 1:
-// gen_op_dmfc0_vpecontrol(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mfc0_vpecontrol();
rn = "VPEControl";
-// break;
+ break;
case 2:
-// gen_op_dmfc0_vpeconf0(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mfc0_vpeconf0();
rn = "VPEConf0";
-// break;
+ break;
case 3:
-// gen_op_dmfc0_vpeconf1(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mfc0_vpeconf1();
rn = "VPEConf1";
-// break;
+ break;
case 4:
-// gen_op_dmfc0_YQMask(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_dmfc0_yqmask();
rn = "YQMask";
-// break;
+ break;
case 5:
-// gen_op_dmfc0_vpeschedule(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_dmfc0_vpeschedule();
rn = "VPESchedule";
-// break;
+ break;
case 6:
-// gen_op_dmfc0_vpeschefback(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_dmfc0_vpeschefback();
rn = "VPEScheFBack";
-// break;
+ break;
case 7:
-// gen_op_dmfc0_vpeopt(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mfc0_vpeopt();
rn = "VPEOpt";
-// break;
+ break;
default:
goto die;
}
@@ -3066,33 +3142,40 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
rn = "EntryLo0";
break;
case 1:
-// gen_op_dmfc0_tcstatus(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mfc0_tcstatus();
rn = "TCStatus";
-// break;
+ break;
case 2:
-// gen_op_dmfc0_tcbind(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mfc0_tcbind();
rn = "TCBind";
-// break;
+ break;
case 3:
-// gen_op_dmfc0_tcrestart(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_dmfc0_tcrestart();
rn = "TCRestart";
-// break;
+ break;
case 4:
-// gen_op_dmfc0_tchalt(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_dmfc0_tchalt();
rn = "TCHalt";
-// break;
+ break;
case 5:
-// gen_op_dmfc0_tccontext(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_dmfc0_tccontext();
rn = "TCContext";
-// break;
+ break;
case 6:
-// gen_op_dmfc0_tcschedule(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_dmfc0_tcschedule();
rn = "TCSchedule";
-// break;
+ break;
case 7:
-// gen_op_dmfc0_tcschefback(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_dmfc0_tcschefback();
rn = "TCScheFBack";
-// break;
+ break;
default:
goto die;
}
@@ -3143,25 +3226,25 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
rn = "Wired";
break;
case 1:
-// gen_op_dmfc0_srsconf0(); /* shadow registers */
+ gen_op_mfc0_srsconf0();
rn = "SRSConf0";
-// break;
+ break;
case 2:
-// gen_op_dmfc0_srsconf1(); /* shadow registers */
+ gen_op_mfc0_srsconf1();
rn = "SRSConf1";
-// break;
+ break;
case 3:
-// gen_op_dmfc0_srsconf2(); /* shadow registers */
+ gen_op_mfc0_srsconf2();
rn = "SRSConf2";
-// break;
+ break;
case 4:
-// gen_op_dmfc0_srsconf3(); /* shadow registers */
+ gen_op_mfc0_srsconf3();
rn = "SRSConf3";
-// break;
+ break;
case 5:
-// gen_op_dmfc0_srsconf4(); /* shadow registers */
+ gen_op_mfc0_srsconf4();
rn = "SRSConf4";
-// break;
+ break;
default:
goto die;
}
@@ -3237,7 +3320,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
break;
case 3:
check_mips_r2(env, ctx);
- gen_op_mfc0_srsmap(); /* shadow registers */
+ gen_op_mfc0_srsmap();
rn = "SRSMap";
break;
default:
@@ -3537,17 +3620,20 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
rn = "Index";
break;
case 1:
-// gen_op_mtc0_mvpcontrol(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mtc0_mvpcontrol();
rn = "MVPControl";
-// break;
+ break;
case 2:
-// gen_op_mtc0_mvpconf0(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ /* ignored */
rn = "MVPConf0";
-// break;
+ break;
case 3:
-// gen_op_mtc0_mvpconf1(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ /* ignored */
rn = "MVPConf1";
-// break;
+ break;
default:
goto die;
}
@@ -3559,33 +3645,40 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
rn = "Random";
break;
case 1:
-// gen_op_mtc0_vpecontrol(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mtc0_vpecontrol();
rn = "VPEControl";
-// break;
+ break;
case 2:
-// gen_op_mtc0_vpeconf0(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mtc0_vpeconf0();
rn = "VPEConf0";
-// break;
+ break;
case 3:
-// gen_op_mtc0_vpeconf1(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mtc0_vpeconf1();
rn = "VPEConf1";
-// break;
+ break;
case 4:
-// gen_op_mtc0_YQMask(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mtc0_yqmask();
rn = "YQMask";
-// break;
+ break;
case 5:
-// gen_op_mtc0_vpeschedule(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mtc0_vpeschedule();
rn = "VPESchedule";
-// break;
+ break;
case 6:
-// gen_op_mtc0_vpeschefback(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mtc0_vpeschefback();
rn = "VPEScheFBack";
-// break;
+ break;
case 7:
-// gen_op_mtc0_vpeopt(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mtc0_vpeopt();
rn = "VPEOpt";
-// break;
+ break;
default:
goto die;
}
@@ -3597,33 +3690,40 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
rn = "EntryLo0";
break;
case 1:
-// gen_op_mtc0_tcstatus(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mtc0_tcstatus();
rn = "TCStatus";
-// break;
+ break;
case 2:
-// gen_op_mtc0_tcbind(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mtc0_tcbind();
rn = "TCBind";
-// break;
+ break;
case 3:
-// gen_op_mtc0_tcrestart(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mtc0_tcrestart();
rn = "TCRestart";
-// break;
+ break;
case 4:
-// gen_op_mtc0_tchalt(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mtc0_tchalt();
rn = "TCHalt";
-// break;
+ break;
case 5:
-// gen_op_mtc0_tccontext(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mtc0_tccontext();
rn = "TCContext";
-// break;
+ break;
case 6:
-// gen_op_mtc0_tcschedule(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mtc0_tcschedule();
rn = "TCSchedule";
-// break;
+ break;
case 7:
-// gen_op_mtc0_tcschefback(); /* MT ASE */
+ check_mips_mt(env, ctx);
+ gen_op_mtc0_tcschefback();
rn = "TCScheFBack";
-// break;
+ break;
default:
goto die;
}
@@ -3674,25 +3774,25 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
rn = "Wired";
break;
case 1:
-// gen_op_mtc0_srsconf0(); /* shadow registers */
+ gen_op_mtc0_srsconf0();
rn = "SRSConf0";
-// break;
+ break;
case 2:
-// gen_op_mtc0_srsconf1(); /* shadow registers */
+ gen_op_mtc0_srsconf1();
rn = "SRSConf1";
-// break;
+ break;
case 3:
-// gen_op_mtc0_srsconf2(); /* shadow registers */
+ gen_op_mtc0_srsconf2();
rn = "SRSConf2";
-// break;
+ break;
case 4:
-// gen_op_mtc0_srsconf3(); /* shadow registers */
+ gen_op_mtc0_srsconf3();
rn = "SRSConf3";
-// break;
+ break;
case 5:
-// gen_op_mtc0_srsconf4(); /* shadow registers */
+ gen_op_mtc0_srsconf4();
rn = "SRSConf4";
-// break;
+ break;
default:
goto die;
}
@@ -4086,6 +4186,334 @@ die:
}
#endif /* TARGET_MIPS64 */
+static void gen_mftr(CPUState *env, DisasContext *ctx, int rt,
+ int u, int sel, int h)
+{
+ int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
+
+ 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))))
+ gen_op_set_T0(-1);
+ else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
+ (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
+ gen_op_set_T0(-1);
+ else if (u == 0) {
+ switch (rt) {
+ case 2:
+ switch (sel) {
+ case 1:
+ gen_op_mftc0_tcstatus();
+ break;
+ case 2:
+ gen_op_mftc0_tcbind();
+ break;
+ case 3:
+ gen_op_mftc0_tcrestart();
+ break;
+ case 4:
+ gen_op_mftc0_tchalt();
+ break;
+ case 5:
+ gen_op_mftc0_tccontext();
+ break;
+ case 6:
+ gen_op_mftc0_tcschedule();
+ break;
+ case 7:
+ gen_op_mftc0_tcschefback();
+ break;
+ default:
+ gen_mfc0(env, ctx, rt, sel);
+ break;
+ }
+ break;
+ case 10:
+ switch (sel) {
+ case 0:
+ gen_op_mftc0_entryhi();
+ break;
+ default:
+ gen_mfc0(env, ctx, rt, sel);
+ break;
+ }
+ case 12:
+ switch (sel) {
+ case 0:
+ gen_op_mftc0_status();
+ break;
+ default:
+ gen_mfc0(env, ctx, rt, sel);
+ break;
+ }
+ case 23:
+ switch (sel) {
+ case 0:
+ gen_op_mftc0_debug();
+ break;
+ default:
+ gen_mfc0(env, ctx, rt, sel);
+ break;
+ }
+ break;
+ default:
+ gen_mfc0(env, ctx, rt, sel);
+ }
+ } else switch (sel) {
+ /* GPR registers. */
+ case 0:
+ gen_op_mftgpr(rt);
+ break;
+ /* Auxiliary CPU registers */
+ case 1:
+ switch (rt) {
+ case 0:
+ gen_op_mftlo(0);
+ break;
+ case 1:
+ gen_op_mfthi(0);
+ break;
+ case 2:
+ gen_op_mftacx(0);
+ break;
+ case 4:
+ gen_op_mftlo(1);
+ break;
+ case 5:
+ gen_op_mfthi(1);
+ break;
+ case 6:
+ gen_op_mftacx(1);
+ break;
+ case 8:
+ gen_op_mftlo(2);
+ break;
+ case 9:
+ gen_op_mfthi(2);
+ break;
+ case 10:
+ gen_op_mftacx(2);
+ break;
+ case 12:
+ gen_op_mftlo(3);
+ break;
+ case 13:
+ gen_op_mfthi(3);
+ break;
+ case 14:
+ gen_op_mftacx(3);
+ break;
+ case 16:
+ gen_op_mftdsp();
+ break;
+ default:
+ goto die;
+ }
+ break;
+ /* Floating point (COP1). */
+ case 2:
+ /* XXX: For now we support only a single FPU context. */
+ if (h == 0) {
+ GEN_LOAD_FREG_FTN(WT0, rt);
+ gen_op_mfc1();
+ } else {
+ GEN_LOAD_FREG_FTN(WTH0, rt);
+ gen_op_mfhc1();
+ }
+ break;
+ case 3:
+ /* XXX: For now we support only a single FPU context. */
+ gen_op_cfc1(rt);
+ break;
+ /* COP2: Not implemented. */
+ case 4:
+ case 5:
+ /* fall through */
+ default:
+ goto die;
+ }
+#if defined MIPS_DEBUG_DISAS
+ if (loglevel & CPU_LOG_TB_IN_ASM) {
+ fprintf(logfile, "mftr (reg %d u %d sel %d h %d)\n",
+ rt, u, sel, h);
+ }
+#endif
+ return;
+
+die:
+#if defined MIPS_DEBUG_DISAS
+ if (loglevel & CPU_LOG_TB_IN_ASM) {
+ fprintf(logfile, "mftr (reg %d u %d sel %d h %d)\n",
+ rt, u, sel, h);
+ }
+#endif
+ generate_exception(ctx, EXCP_RI);
+}
+
+static void gen_mttr(CPUState *env, DisasContext *ctx, int rd,
+ int u, int sel, int h)
+{
+ int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
+
+ 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))))
+ /* NOP */ ;
+ else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
+ (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
+ /* NOP */ ;
+ else if (u == 0) {
+ switch (rd) {
+ case 2:
+ switch (sel) {
+ case 1:
+ gen_op_mttc0_tcstatus();
+ break;
+ case 2:
+ gen_op_mttc0_tcbind();
+ break;
+ case 3:
+ gen_op_mttc0_tcrestart();
+ break;
+ case 4:
+ gen_op_mttc0_tchalt();
+ break;
+ case 5:
+ gen_op_mttc0_tccontext();
+ break;
+ case 6:
+ gen_op_mttc0_tcschedule();
+ break;
+ case 7:
+ gen_op_mttc0_tcschefback();
+ break;
+ default:
+ gen_mtc0(env, ctx, rd, sel);
+ break;
+ }
+ break;
+ case 10:
+ switch (sel) {
+ case 0:
+ gen_op_mttc0_entryhi();
+ break;
+ default:
+ gen_mtc0(env, ctx, rd, sel);
+ break;
+ }
+ case 12:
+ switch (sel) {
+ case 0:
+ gen_op_mttc0_status();
+ break;
+ default:
+ gen_mtc0(env, ctx, rd, sel);
+ break;
+ }
+ case 23:
+ switch (sel) {
+ case 0:
+ gen_op_mttc0_debug();
+ break;
+ default:
+ gen_mtc0(env, ctx, rd, sel);
+ break;
+ }
+ break;
+ default:
+ gen_mtc0(env, ctx, rd, sel);
+ }
+ } else switch (sel) {
+ /* GPR registers. */
+ case 0:
+ gen_op_mttgpr(rd);
+ break;
+ /* Auxiliary CPU registers */
+ case 1:
+ switch (rd) {
+ case 0:
+ gen_op_mttlo(0);
+ break;
+ case 1:
+ gen_op_mtthi(0);
+ break;
+ case 2:
+ gen_op_mttacx(0);
+ break;
+ case 4:
+ gen_op_mttlo(1);
+ break;
+ case 5:
+ gen_op_mtthi(1);
+ break;
+ case 6:
+ gen_op_mttacx(1);
+ break;
+ case 8:
+ gen_op_mttlo(2);
+ break;
+ case 9:
+ gen_op_mtthi(2);
+ break;
+ case 10:
+ gen_op_mttacx(2);
+ break;
+ case 12:
+ gen_op_mttlo(3);
+ break;
+ case 13:
+ gen_op_mtthi(3);
+ break;
+ case 14:
+ gen_op_mttacx(3);
+ break;
+ case 16:
+ gen_op_mttdsp();
+ break;
+ default:
+ goto die;
+ }
+ break;
+ /* Floating point (COP1). */
+ case 2:
+ /* XXX: For now we support only a single FPU context. */
+ if (h == 0) {
+ gen_op_mtc1();
+ GEN_STORE_FTN_FREG(rd, WT0);
+ } else {
+ gen_op_mthc1();
+ GEN_STORE_FTN_FREG(rd, WTH0);
+ }
+ break;
+ case 3:
+ /* XXX: For now we support only a single FPU context. */
+ gen_op_ctc1(rd);
+ break;
+ /* COP2: Not implemented. */
+ case 4:
+ case 5:
+ /* fall through */
+ default:
+ goto die;
+ }
+#if defined MIPS_DEBUG_DISAS
+ if (loglevel & CPU_LOG_TB_IN_ASM) {
+ fprintf(logfile, "mttr (reg %d u %d sel %d h %d)\n",
+ rd, u, sel, h);
+ }
+#endif
+ return;
+
+die:
+#if defined MIPS_DEBUG_DISAS
+ if (loglevel & CPU_LOG_TB_IN_ASM) {
+ fprintf(logfile, "mttr (reg %d u %d sel %d h %d)\n",
+ rd, u, sel, h);
+ }
+#endif
+ generate_exception(ctx, EXCP_RI);
+}
+
static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
{
const char *opn = "ldst";
@@ -4093,7 +4521,7 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int
switch (opc) {
case OPC_MFC0:
if (rt == 0) {
- /* Treat as NOP */
+ /* Treat as NOP. */
return;
}
gen_mfc0(env, ctx, rd, ctx->opcode & 0x7);
@@ -4110,7 +4538,7 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int
if (!(ctx->hflags & MIPS_HFLAG_64))
generate_exception(ctx, EXCP_RI);
if (rt == 0) {
- /* Treat as NOP */
+ /* Treat as NOP. */
return;
}
gen_dmfc0(env, ctx, rd, ctx->opcode & 0x7);
@@ -4121,31 +4549,49 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int
if (!(ctx->hflags & MIPS_HFLAG_64))
generate_exception(ctx, EXCP_RI);
GEN_LOAD_REG_TN(T0, rt);
- gen_dmtc0(env,ctx, rd, ctx->opcode & 0x7);
+ gen_dmtc0(env, ctx, rd, ctx->opcode & 0x7);
opn = "dmtc0";
break;
#endif
+ case OPC_MFTR:
+ check_mips_mt(env, ctx);
+ if (rd == 0) {
+ /* Treat as NOP. */
+ return;
+ }
+ gen_mftr(env, ctx, rt, (ctx->opcode >> 5) & 1,
+ ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
+ gen_op_store_T0_gpr(rd);
+ opn = "mftr";
+ break;
+ case OPC_MTTR:
+ check_mips_mt(env, ctx);
+ GEN_LOAD_REG_TN(T0, rt);
+ gen_mttr(env, ctx, rd, (ctx->opcode >> 5) & 1,
+ ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
+ opn = "mttr";
+ break;
case OPC_TLBWI:
opn = "tlbwi";
- if (!env->do_tlbwi)
+ if (!env->tlb->do_tlbwi)
goto die;
gen_op_tlbwi();
break;
case OPC_TLBWR:
opn = "tlbwr";
- if (!env->do_tlbwr)
+ if (!env->tlb->do_tlbwr)
goto die;
gen_op_tlbwr();
break;
case OPC_TLBP:
opn = "tlbp";
- if (!env->do_tlbp)
+ if (!env->tlb->do_tlbp)
goto die;
gen_op_tlbp();
break;
case OPC_TLBR:
opn = "tlbr";
- if (!env->do_tlbr)
+ if (!env->tlb->do_tlbr)
goto die;
gen_op_tlbr();
break;
@@ -4263,15 +4709,13 @@ static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
opn = "mtc1";
break;
case OPC_CFC1:
- GEN_LOAD_IMM_TN(T1, fs);
- gen_op_cfc1();
+ gen_op_cfc1(fs);
GEN_STORE_TN_REG(rt, T0);
opn = "cfc1";
break;
case OPC_CTC1:
- GEN_LOAD_IMM_TN(T1, fs);
GEN_LOAD_REG_TN(T0, rt);
- gen_op_ctc1();
+ gen_op_ctc1(fs);
opn = "ctc1";
break;
case OPC_DMFC1:
@@ -5171,8 +5615,7 @@ static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
gen_op_addr_add();
}
/* Don't do NOP if destination is zero: we must perform the actual
- * memory access
- */
+ memory access. */
switch (opc) {
case OPC_LWXC1:
op_ldst(lwc1);
@@ -5456,7 +5899,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
#endif
break;
case OPC_SYNC:
- /* Treat as a noop. */
+ /* Treat as NOP. */
break;
case OPC_MOVCI:
@@ -5521,7 +5964,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
} else {
generate_exception(ctx, EXCP_DBp);
}
- /* Treat as a noop */
+ /* Treat as NOP. */
break;
#ifdef TARGET_MIPS64
case OPC_DCLZ ... OPC_DCLO:
@@ -5586,7 +6029,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
break;
case 29:
#if defined (CONFIG_USER_ONLY)
- gen_op_tls_value ();
+ gen_op_tls_value();
break;
#endif
default: /* Invalid */
@@ -5596,6 +6039,18 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
}
GEN_STORE_TN_REG(rt, T0);
break;
+ case OPC_FORK:
+ check_mips_mt(env, ctx);
+ GEN_LOAD_REG_TN(T0, rt);
+ GEN_LOAD_REG_TN(T1, rs);
+ gen_op_fork();
+ break;
+ case OPC_YIELD:
+ check_mips_mt(env, ctx);
+ GEN_LOAD_REG_TN(T0, rs);
+ gen_op_yield();
+ GEN_STORE_TN_REG(rd, T0);
+ break;
#ifdef TARGET_MIPS64
case OPC_DEXTM ... OPC_DEXT:
case OPC_DINSM ... OPC_DINS:
@@ -5642,7 +6097,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
break;
case OPC_SYNCI:
check_mips_r2(env, ctx);
- /* treat as noop */
+ /* Treat as NOP. */
break;
default: /* Invalid */
MIPS_INVAL("regimm");
@@ -5657,6 +6112,8 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
switch (op1) {
case OPC_MFC0:
case OPC_MTC0:
+ case OPC_MFTR:
+ case OPC_MTTR:
#ifdef TARGET_MIPS64
case OPC_DMFC0:
case OPC_DMTC0:
@@ -5670,6 +6127,22 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
check_mips_r2(env, ctx);
op2 = MASK_MFMC0(ctx->opcode);
switch (op2) {
+ case OPC_DMT:
+ check_mips_mt(env, ctx);
+ gen_op_dmt();
+ break;
+ case OPC_EMT:
+ check_mips_mt(env, ctx);
+ gen_op_emt();
+ break;
+ case OPC_DVPE:
+ check_mips_mt(env, ctx);
+ gen_op_dvpe();
+ break;
+ case OPC_EVPE:
+ check_mips_mt(env, ctx);
+ gen_op_evpe();
+ break;
case OPC_DI:
gen_op_di();
/* Stop translation as we may have switched the execution mode */
@@ -5688,11 +6161,14 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
GEN_STORE_TN_REG(rt, T0);
break;
case OPC_RDPGPR:
+ check_mips_r2(env, ctx);
+ GEN_LOAD_SRSREG_TN(T0, rt);
+ GEN_STORE_TN_REG(rd, T0);
+ break;
case OPC_WRPGPR:
check_mips_r2(env, ctx);
- /* Shadow registers not implemented. */
GEN_LOAD_REG_TN(T0, rt);
- GEN_STORE_TN_REG(rd, T0);
+ GEN_STORE_TN_SRSREG(rd, T0);
break;
default:
MIPS_INVAL("cp0");
@@ -5719,10 +6195,10 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
gen_ldst(ctx, op, rt, rs, imm);
break;
case OPC_CACHE:
- /* Treat as a noop */
+ /* Treat as NOP. */
break;
case OPC_PREF:
- /* Treat as a noop */
+ /* Treat as NOP. */
break;
/* Floating point (COP1). */
@@ -5807,7 +6283,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
break;
case OPC_PREFX:
- /* treat as noop */
+ /* Treat as NOP. */
break;
case OPC_ALNV_PS:
case OPC_MADD_S:
@@ -6079,13 +6555,14 @@ void fpu_dump_state(CPUState *env, FILE *f,
fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%08x(0x%02x)\n",
- env->fcr0, env->fcr31, is_fpu64, env->fp_status, get_float_exception_flags(&env->fp_status));
- fpu_fprintf(f, "FT0: "); printfpr(&env->ft0);
- fpu_fprintf(f, "FT1: "); printfpr(&env->ft1);
- fpu_fprintf(f, "FT2: "); printfpr(&env->ft2);
+ env->fpu->fcr0, env->fpu->fcr31, is_fpu64, env->fpu->fp_status,
+ get_float_exception_flags(&env->fpu->fp_status));
+ fpu_fprintf(f, "FT0: "); printfpr(&env->fpu->ft0);
+ fpu_fprintf(f, "FT1: "); printfpr(&env->fpu->ft1);
+ fpu_fprintf(f, "FT2: "); printfpr(&env->fpu->ft2);
for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
fpu_fprintf(f, "%3s: ", fregnames[i]);
- printfpr(&env->fpr[i]);
+ printfpr(&env->fpu->fpr[i]);
}
#undef printfpr
@@ -6095,7 +6572,7 @@ void dump_fpu (CPUState *env)
{
if (loglevel) {
fprintf(logfile, "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->HI, env->LO, env->hflags, env->btarget, env->bcond);
+ env->PC[env->current_tc], env->HI[0][env->current_tc], env->LO[0][env->current_tc], env->hflags, env->btarget, env->bcond);
fpu_dump_state(env, logfile, fprintf, 0);
}
}
@@ -6112,18 +6589,18 @@ void cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
{
int i;
- if (!SIGN_EXT_P(env->PC))
- cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->PC);
- if (!SIGN_EXT_P(env->HI))
- cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->HI);
- if (!SIGN_EXT_P(env->LO))
- cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->LO);
+ 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]))
+ cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->HI[env->current_tc]);
+ if (!SIGN_EXT_P(env->LO[env->current_tc]))
+ cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->LO[env->current_tc]);
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[i]))
- cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->gpr[i]);
+ if (!SIGN_EXT_P(env->gpr[i][env->current_tc]))
+ cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->gpr[i][env->current_tc]);
}
if (!SIGN_EXT_P(env->CP0_EPC))
@@ -6140,11 +6617,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->HI, env->LO, env->hflags, env->btarget, env->bcond);
+ env->PC[env->current_tc], env->HI[env->current_tc], env->LO[env->current_tc], 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[i]);
+ cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->gpr[i][env->current_tc]);
if ((i & 3) == 3)
cpu_fprintf(f, "\n");
}
@@ -6183,12 +6660,12 @@ 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 - 4;
+ env->CP0_ErrorEPC = env->PC[env->current_tc] - 4;
} else {
- env->CP0_ErrorEPC = env->PC;
+ env->CP0_ErrorEPC = env->PC[env->current_tc];
}
env->hflags = 0;
- env->PC = (int32_t)0xBFC00000;
+ env->PC[env->current_tc] = (int32_t)0xBFC00000;
env->CP0_Wired = 0;
/* SMP not implemented */
env->CP0_EBase = 0x80000000;
diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c
index d327312e55..a9e9312642 100644
--- a/target-mips/translate_init.c
+++ b/target-mips/translate_init.c
@@ -43,11 +43,11 @@
/* No config4, no DSP ASE, no large physaddr,
no external interrupt controller, no vectored interupts,
- no 1kb pages, no MT ASE, no SmartMIPS ASE, no trace logic */
+ no 1kb pages, no SmartMIPS ASE, no trace logic */
#define MIPS_CONFIG3 \
((0 << CP0C3_M) | (0 << CP0C3_DSPP) | (0 << CP0C3_LPA) | \
(0 << CP0C3_VEIC) | (0 << CP0C3_VInt) | (0 << CP0C3_SP) | \
- (0 << CP0C3_MT) | (0 << CP0C3_SM) | (0 << CP0C3_TL))
+ (0 << CP0C3_SM) | (0 << CP0C3_TL))
/* Define a implementation number of 1.
Define a major version 1, minor version 0. */
@@ -65,9 +65,21 @@ struct mips_def_t {
int32_t CP0_Config7;
int32_t SYNCI_Step;
int32_t CCRes;
- int32_t Status_rw_bitmask;
+ int32_t CP0_Status_rw_bitmask;
+ int32_t CP0_TCStatus_rw_bitmask;
+ int32_t CP0_SRSCtl;
int32_t CP1_fcr0;
int32_t SEGBITS;
+ int32_t CP0_SRSConf0_rw_bitmask;
+ int32_t CP0_SRSConf0;
+ int32_t CP0_SRSConf1_rw_bitmask;
+ int32_t CP0_SRSConf1;
+ int32_t CP0_SRSConf2_rw_bitmask;
+ int32_t CP0_SRSConf2;
+ int32_t CP0_SRSConf3_rw_bitmask;
+ int32_t CP0_SRSConf3;
+ int32_t CP0_SRSConf4_rw_bitmask;
+ int32_t CP0_SRSConf4;
};
/*****************************************************************************/
@@ -85,7 +97,7 @@ static mips_def_t mips_defs[] =
.CP0_Config3 = MIPS_CONFIG3,
.SYNCI_Step = 32,
.CCRes = 2,
- .Status_rw_bitmask = 0x3278FF17,
+ .CP0_Status_rw_bitmask = 0x1278FF17,
},
{
.name = "4KEcR1",
@@ -98,7 +110,7 @@ static mips_def_t mips_defs[] =
.CP0_Config3 = MIPS_CONFIG3,
.SYNCI_Step = 32,
.CCRes = 2,
- .Status_rw_bitmask = 0x3278FF17,
+ .CP0_Status_rw_bitmask = 0x1278FF17,
},
{
.name = "4KEc",
@@ -108,10 +120,10 @@ static mips_def_t mips_defs[] =
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA),
.CP0_Config2 = MIPS_CONFIG2,
- .CP0_Config3 = MIPS_CONFIG3,
+ .CP0_Config3 = MIPS_CONFIG3 | (0 << CP0C3_VInt),
.SYNCI_Step = 32,
.CCRes = 2,
- .Status_rw_bitmask = 0x3278FF17,
+ .CP0_Status_rw_bitmask = 0x1278FF17,
},
{
.name = "24Kc",
@@ -121,10 +133,11 @@ static mips_def_t mips_defs[] =
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA),
.CP0_Config2 = MIPS_CONFIG2,
- .CP0_Config3 = MIPS_CONFIG3,
+ .CP0_Config3 = MIPS_CONFIG3 | (0 << CP0C3_VInt),
.SYNCI_Step = 32,
.CCRes = 2,
- .Status_rw_bitmask = 0x3278FF17,
+ /* No DSP implemented. */
+ .CP0_Status_rw_bitmask = 0x1278FF17,
},
{
.name = "24Kf",
@@ -134,13 +147,53 @@ static mips_def_t mips_defs[] =
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA),
.CP0_Config2 = MIPS_CONFIG2,
- .CP0_Config3 = MIPS_CONFIG3,
+ .CP0_Config3 = MIPS_CONFIG3 | (0 << CP0C3_VInt),
.SYNCI_Step = 32,
.CCRes = 2,
- .Status_rw_bitmask = 0x3678FF17,
+ /* No DSP implemented. */
+ .CP0_Status_rw_bitmask = 0x3678FF17,
.CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
(1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID),
},
+ {
+ .name = "34Kf",
+ .CP0_PRid = 0x00019500,
+ .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR),
+ .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (15 << CP0C1_MMU) |
+ (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
+ (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA),
+ .CP0_Config2 = MIPS_CONFIG2,
+ .CP0_Config3 = MIPS_CONFIG3 | (0 << CP0C3_VInt) | (1 << CP0C3_MT),
+ .SYNCI_Step = 32,
+ .CCRes = 2,
+ /* No DSP implemented. */
+ .CP0_Status_rw_bitmask = 0x3678FF17,
+ /* No DSP implemented. */
+ .CP0_TCStatus_rw_bitmask = (0 << CP0TCSt_TCU3) | (0 << CP0TCSt_TCU2) |
+ (1 << CP0TCSt_TCU1) | (1 << CP0TCSt_TCU0) |
+ (0 << CP0TCSt_TMX) | (1 << CP0TCSt_DT) |
+ (1 << CP0TCSt_DA) | (1 << CP0TCSt_A) |
+ (0x3 << CP0TCSt_TKSU) | (1 << CP0TCSt_IXMT) |
+ (0xff << CP0TCSt_TASID),
+ .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
+ (1 << FCR0_D) | (1 << FCR0_S) | (0x95 << FCR0_PRID),
+ .CP0_SRSCtl = (0xf << CP0SRSCtl_HSS),
+ .CP0_SRSConf0_rw_bitmask = 0x3fffffff,
+ .CP0_SRSConf0 = (1 << CP0SRSC0_M) | (0x3fe << CP0SRSC0_SRS3) |
+ (0x3fe << CP0SRSC0_SRS2) | (0x3fe << CP0SRSC0_SRS1),
+ .CP0_SRSConf1_rw_bitmask = 0x3fffffff,
+ .CP0_SRSConf1 = (1 << CP0SRSC1_M) | (0x3fe << CP0SRSC1_SRS6) |
+ (0x3fe << CP0SRSC1_SRS5) | (0x3fe << CP0SRSC1_SRS4),
+ .CP0_SRSConf2_rw_bitmask = 0x3fffffff,
+ .CP0_SRSConf2 = (1 << CP0SRSC2_M) | (0x3fe << CP0SRSC2_SRS9) |
+ (0x3fe << CP0SRSC2_SRS8) | (0x3fe << CP0SRSC2_SRS7),
+ .CP0_SRSConf3_rw_bitmask = 0x3fffffff,
+ .CP0_SRSConf3 = (1 << CP0SRSC3_M) | (0x3fe << CP0SRSC3_SRS12) |
+ (0x3fe << CP0SRSC3_SRS11) | (0x3fe << CP0SRSC3_SRS10),
+ .CP0_SRSConf4_rw_bitmask = 0x3fffffff,
+ .CP0_SRSConf4 = (0x3fe << CP0SRSC4_SRS15) |
+ (0x3fe << CP0SRSC4_SRS14) | (0x3fe << CP0SRSC4_SRS13),
+ },
#ifdef TARGET_MIPS64
{
.name = "R4000",
@@ -153,7 +206,7 @@ static mips_def_t mips_defs[] =
.CP0_Config3 = MIPS_CONFIG3,
.SYNCI_Step = 16,
.CCRes = 2,
- .Status_rw_bitmask = 0x3678FFFF,
+ .CP0_Status_rw_bitmask = 0x3678FFFF,
/* The R4000 has a full 64bit FPU doesn't use the fcr0 bits. */
.CP1_fcr0 = (0x5 << FCR0_PRID) | (0x0 << FCR0_REV),
.SEGBITS = 40,
@@ -170,7 +223,7 @@ static mips_def_t mips_defs[] =
.CP0_Config3 = MIPS_CONFIG3,
.SYNCI_Step = 32,
.CCRes = 2,
- .Status_rw_bitmask = 0x32F8FFFF,
+ .CP0_Status_rw_bitmask = 0x32F8FFFF,
.SEGBITS = 42,
},
{
@@ -185,7 +238,7 @@ static mips_def_t mips_defs[] =
.CP0_Config3 = MIPS_CONFIG3,
.SYNCI_Step = 32,
.CCRes = 2,
- .Status_rw_bitmask = 0x36F8FFFF,
+ .CP0_Status_rw_bitmask = 0x36F8FFFF,
/* The 5Kf has F64 / L / W but doesn't use the fcr0 bits. */
.CP1_fcr0 = (1 << FCR0_D) | (1 << FCR0_S) |
(0x81 << FCR0_PRID) | (0x0 << FCR0_REV),
@@ -205,7 +258,7 @@ static mips_def_t mips_defs[] =
.CP0_Config3 = MIPS_CONFIG3,
.SYNCI_Step = 32,
.CCRes = 2,
- .Status_rw_bitmask = 0x36FBFFFF,
+ .CP0_Status_rw_bitmask = 0x36FBFFFF,
/* The 20Kc has F64 / L / W but doesn't use the fcr0 bits. */
.CP1_fcr0 = (1 << FCR0_3D) | (1 << FCR0_PS) |
(1 << FCR0_D) | (1 << FCR0_S) |
@@ -245,27 +298,88 @@ void mips_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
#ifndef CONFIG_USER_ONLY
static void no_mmu_init (CPUMIPSState *env, mips_def_t *def)
{
- env->nb_tlb = 1;
- env->map_address = &no_mmu_map_address;
+ env->tlb->nb_tlb = 1;
+ env->tlb->map_address = &no_mmu_map_address;
}
static void fixed_mmu_init (CPUMIPSState *env, mips_def_t *def)
{
- env->nb_tlb = 1;
- env->map_address = &fixed_mmu_map_address;
+ env->tlb->nb_tlb = 1;
+ env->tlb->map_address = &fixed_mmu_map_address;
}
static void r4k_mmu_init (CPUMIPSState *env, mips_def_t *def)
{
- env->nb_tlb = 1 + ((def->CP0_Config1 >> CP0C1_MMU) & 63);
- env->map_address = &r4k_map_address;
- env->do_tlbwi = r4k_do_tlbwi;
- env->do_tlbwr = r4k_do_tlbwr;
- env->do_tlbp = r4k_do_tlbp;
- env->do_tlbr = r4k_do_tlbr;
+ env->tlb->nb_tlb = 1 + ((def->CP0_Config1 >> CP0C1_MMU) & 63);
+ env->tlb->map_address = &r4k_map_address;
+ env->tlb->do_tlbwi = r4k_do_tlbwi;
+ env->tlb->do_tlbwr = r4k_do_tlbwr;
+ env->tlb->do_tlbp = r4k_do_tlbp;
+ env->tlb->do_tlbr = r4k_do_tlbr;
+}
+
+static void mmu_init (CPUMIPSState *env, mips_def_t *def)
+{
+ env->tlb = qemu_mallocz(sizeof(CPUMIPSTLBContext));
+
+ /* There are more full-featured MMU variants in older MIPS CPUs,
+ R3000, R6000 and R8000 come to mind. If we ever support them,
+ this check will need to look up a different place than those
+ newfangled config registers. */
+ switch ((env->CP0_Config0 >> CP0C0_MT) & 3) {
+ case 0:
+ no_mmu_init(env, def);
+ break;
+ case 1:
+ r4k_mmu_init(env, def);
+ break;
+ case 3:
+ fixed_mmu_init(env, def);
+ break;
+ default:
+ cpu_abort(env, "MMU type not supported\n");
+ }
+ env->CP0_Random = env->tlb->nb_tlb - 1;
+ env->tlb->tlb_in_use = env->tlb->nb_tlb;
}
#endif /* CONFIG_USER_ONLY */
+static void fpu_init (CPUMIPSState *env, mips_def_t *def)
+{
+ env->fpu = qemu_mallocz(sizeof(CPUMIPSFPUContext));
+
+ env->fpu->fcr0 = def->CP1_fcr0;
+#ifdef CONFIG_USER_ONLY
+ if (env->CP0_Config1 & (1 << CP0C1_FP))
+ env->hflags |= MIPS_HFLAG_FPU;
+ if (env->fpu->fcr0 & (1 << FCR0_F64))
+ env->hflags |= MIPS_HFLAG_F64;
+#endif
+}
+
+static void mvp_init (CPUMIPSState *env, mips_def_t *def)
+{
+ env->mvp = qemu_mallocz(sizeof(CPUMIPSMVPContext));
+
+ /* MVPConf1 implemented, TLB sharable, no gating storage support,
+ programmable cache partitioning implemented, number of allocatable
+ and sharable TLB entries, MVP has allocatable TCs, 2 VPEs
+ implemented, 5 TCs implemented. */
+ env->mvp->CP0_MVPConf0 = (1 << CP0MVPC0_M) | (1 << CP0MVPC0_TLBS) |
+ (0 << CP0MVPC0_GS) | (1 << CP0MVPC0_PCP) |
+ (env->tlb->nb_tlb << CP0MVPC0_PTLBE) |
+// TODO: actually do 2 VPEs.
+// (1 << CP0MVPC0_TCA) | (0x1 << CP0MVPC0_PVPE) |
+// (0x04 << CP0MVPC0_PTC);
+ (1 << CP0MVPC0_TCA) | (0x0 << CP0MVPC0_PVPE) |
+ (0x04 << CP0MVPC0_PTC);
+ /* Allocatable CP1 have media extensions, allocatable CP1 have FP support,
+ no UDI implemented, no CP2 implemented, 1 CP1 implemented. */
+ env->mvp->CP0_MVPConf1 = (1 << CP0MVPC1_CIM) | (1 << CP0MVPC1_CIF) |
+ (0x0 << CP0MVPC1_PCX) | (0x0 << CP0MVPC1_PCP2) |
+ (0x1 << CP0MVPC1_PCP1);
+}
+
int cpu_mips_register (CPUMIPSState *env, mips_def_t *def)
{
if (!def)
@@ -285,8 +399,9 @@ int cpu_mips_register (CPUMIPSState *env, mips_def_t *def)
env->CP0_Config7 = def->CP0_Config7;
env->SYNCI_Step = def->SYNCI_Step;
env->CCRes = def->CCRes;
- env->Status_rw_bitmask = def->Status_rw_bitmask;
- env->fcr0 = def->CP1_fcr0;
+ env->CP0_Status_rw_bitmask = def->CP0_Status_rw_bitmask;
+ env->CP0_TCStatus_rw_bitmask = def->CP0_TCStatus_rw_bitmask;
+ env->CP0_SRSCtl = def->CP0_SRSCtl;
#ifdef TARGET_MIPS64
if ((env->CP0_Config0 & (0x3 << CP0C0_AT)))
{
@@ -298,31 +413,21 @@ int cpu_mips_register (CPUMIPSState *env, mips_def_t *def)
env->SEGMask = 0xFFFFFFFF;
}
#endif
-#ifdef CONFIG_USER_ONLY
- if (env->CP0_Config1 & (1 << CP0C1_FP))
- env->hflags |= MIPS_HFLAG_FPU;
- if (env->fcr0 & (1 << FCR0_F64))
- env->hflags |= MIPS_HFLAG_F64;
-#else
- /* There are more full-featured MMU variants in older MIPS CPUs,
- R3000, R6000 and R8000 come to mind. If we ever support them,
- this check will need to look up a different place than those
- newfangled config registers. */
- switch ((env->CP0_Config0 >> CP0C0_MT) & 3) {
- case 0:
- no_mmu_init(env, def);
- break;
- case 1:
- r4k_mmu_init(env, def);
- break;
- case 3:
- fixed_mmu_init(env, def);
- break;
- default:
- cpu_abort(env, "MMU type not supported\n");
- }
- env->CP0_Random = env->nb_tlb - 1;
- env->tlb_in_use = env->nb_tlb;
-#endif /* CONFIG_USER_ONLY */
+ env->CP0_SRSConf0_rw_bitmask = def->CP0_SRSConf0_rw_bitmask;
+ env->CP0_SRSConf0 = def->CP0_SRSConf0;
+ env->CP0_SRSConf1_rw_bitmask = def->CP0_SRSConf1_rw_bitmask;
+ env->CP0_SRSConf1 = def->CP0_SRSConf1;
+ env->CP0_SRSConf2_rw_bitmask = def->CP0_SRSConf2_rw_bitmask;
+ env->CP0_SRSConf2 = def->CP0_SRSConf2;
+ env->CP0_SRSConf3_rw_bitmask = def->CP0_SRSConf3_rw_bitmask;
+ env->CP0_SRSConf3 = def->CP0_SRSConf3;
+ env->CP0_SRSConf4_rw_bitmask = def->CP0_SRSConf4_rw_bitmask;
+ env->CP0_SRSConf4 = def->CP0_SRSConf4;
+
+#ifndef CONFIG_USER_ONLY
+ mmu_init(env, def);
+#endif
+ fpu_init(env, def);
+ mvp_init(env, def);
return 0;
}
diff --git a/translate-all.c b/translate-all.c
index 491b3b3d33..bd5286f2a1 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -305,7 +305,7 @@ int cpu_restore_state(TranslationBlock *tb,
#elif defined(TARGET_M68K)
env->pc = gen_opc_pc[j];
#elif defined(TARGET_MIPS)
- env->PC = gen_opc_pc[j];
+ env->PC[env->current_tc] = gen_opc_pc[j];
env->hflags &= ~MIPS_HFLAG_BMASK;
env->hflags |= gen_opc_hflags[j];
#elif defined(TARGET_ALPHA)