Partial support for 34K multithreading, not functional yet.

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3156 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
ths 2007-09-06 00:18:15 +00:00
parent 606b41e702
commit ead9360e2f
18 changed files with 2305 additions and 826 deletions

View File

@ -194,7 +194,7 @@ static inline TranslationBlock *tb_find_fast(void)
#elif defined(TARGET_MIPS) #elif defined(TARGET_MIPS)
flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK); flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK);
cs_base = 0; cs_base = 0;
pc = env->PC; pc = env->PC[env->current_tc];
#elif defined(TARGET_M68K) #elif defined(TARGET_M68K)
flags = (env->fpcr & M68K_FPCR_PREC) /* Bit 6 */ flags = (env->fpcr & M68K_FPCR_PREC) /* Bit 6 */
| (env->sr & SR_S) /* Bit 13 */ | (env->sr & SR_S) /* Bit 13 */

View File

@ -559,17 +559,17 @@ static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
ptr = mem_buf; ptr = mem_buf;
for (i = 0; i < 32; i++) 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); ptr += sizeof(target_ulong);
} }
*(target_ulong *)ptr = tswapl(env->CP0_Status); *(target_ulong *)ptr = tswapl(env->CP0_Status);
ptr += sizeof(target_ulong); ptr += sizeof(target_ulong);
*(target_ulong *)ptr = tswapl(env->LO); *(target_ulong *)ptr = tswapl(env->LO[0][env->current_tc]);
ptr += sizeof(target_ulong); ptr += sizeof(target_ulong);
*(target_ulong *)ptr = tswapl(env->HI); *(target_ulong *)ptr = tswapl(env->HI[0][env->current_tc]);
ptr += sizeof(target_ulong); ptr += sizeof(target_ulong);
*(target_ulong *)ptr = tswapl(env->CP0_BadVAddr); *(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); *(target_ulong *)ptr = tswapl(env->CP0_Cause);
ptr += sizeof(target_ulong); ptr += sizeof(target_ulong);
*(target_ulong *)ptr = tswapl(env->PC); *(target_ulong *)ptr = tswapl(env->PC[env->current_tc]);
ptr += sizeof(target_ulong); ptr += sizeof(target_ulong);
if (env->CP0_Config1 & (1 << CP0C1_FP)) if (env->CP0_Config1 & (1 << CP0C1_FP))
{ {
for (i = 0; i < 32; i++) 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); ptr += sizeof(target_ulong);
} }
*(target_ulong *)ptr = tswapl(env->fcr31); *(target_ulong *)ptr = tswapl(env->fpu->fcr31);
ptr += sizeof(target_ulong); ptr += sizeof(target_ulong);
*(target_ulong *)ptr = tswapl(env->fcr0); *(target_ulong *)ptr = tswapl(env->fpu->fcr0);
ptr += sizeof(target_ulong); ptr += sizeof(target_ulong);
} }
@ -611,7 +611,7 @@ static unsigned int ieee_rm[] =
float_round_down float_round_down
}; };
#define RESTORE_ROUNDING_MODE \ #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) 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; ptr = mem_buf;
for (i = 0; i < 32; i++) 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); ptr += sizeof(target_ulong);
} }
env->CP0_Status = tswapl(*(target_ulong *)ptr); env->CP0_Status = tswapl(*(target_ulong *)ptr);
ptr += sizeof(target_ulong); ptr += sizeof(target_ulong);
env->LO = tswapl(*(target_ulong *)ptr); env->LO[0][env->current_tc] = tswapl(*(target_ulong *)ptr);
ptr += sizeof(target_ulong); ptr += sizeof(target_ulong);
env->HI = tswapl(*(target_ulong *)ptr); env->HI[0][env->current_tc] = tswapl(*(target_ulong *)ptr);
ptr += sizeof(target_ulong); ptr += sizeof(target_ulong);
env->CP0_BadVAddr = tswapl(*(target_ulong *)ptr); 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); env->CP0_Cause = tswapl(*(target_ulong *)ptr);
ptr += sizeof(target_ulong); ptr += sizeof(target_ulong);
env->PC = tswapl(*(target_ulong *)ptr); env->PC[env->current_tc] = tswapl(*(target_ulong *)ptr);
ptr += sizeof(target_ulong); ptr += sizeof(target_ulong);
if (env->CP0_Config1 & (1 << CP0C1_FP)) if (env->CP0_Config1 & (1 << CP0C1_FP))
{ {
for (i = 0; i < 32; i++) 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); ptr += sizeof(target_ulong);
} }
env->fcr31 = tswapl(*(target_ulong *)ptr) & 0x0183FFFF; env->fpu->fcr31 = tswapl(*(target_ulong *)ptr) & 0x0183FFFF;
ptr += sizeof(target_ulong); ptr += sizeof(target_ulong);
env->fcr0 = tswapl(*(target_ulong *)ptr); env->fpu->fcr0 = tswapl(*(target_ulong *)ptr);
ptr += sizeof(target_ulong); ptr += sizeof(target_ulong);
/* set rounding mode */ /* set rounding mode */
@ -775,7 +775,7 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf)
#elif defined (TARGET_SH4) #elif defined (TARGET_SH4)
env->pc = addr; env->pc = addr;
#elif defined (TARGET_MIPS) #elif defined (TARGET_MIPS)
env->PC = addr; env->PC[env->current_tc] = addr;
#endif #endif
} }
#ifdef CONFIG_USER_ONLY #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) #elif defined (TARGET_SH4)
env->pc = addr; env->pc = addr;
#elif defined (TARGET_MIPS) #elif defined (TARGET_MIPS)
env->PC = addr; env->PC[env->current_tc] = addr;
#endif #endif
} }
cpu_single_step(env, 1); cpu_single_step(env, 1);

View File

@ -77,7 +77,7 @@ void load_kernel (CPUState *env, int ram_size, const char *kernel_filename,
if (kernel_size >= 0) { if (kernel_size >= 0) {
if ((entry & ~0x7fffffffULL) == 0x80000000) if ((entry & ~0x7fffffffULL) == 0x80000000)
entry = (int32_t)entry; entry = (int32_t)entry;
env->PC = entry; env->PC[env->current_tc] = entry;
} else { } else {
fprintf(stderr, "qemu: could not load kernel '%s'\n", fprintf(stderr, "qemu: could not load kernel '%s'\n",
kernel_filename); kernel_filename);

View File

@ -10,7 +10,7 @@ uint32_t cpu_mips_get_random (CPUState *env)
static uint32_t seed = 0; static uint32_t seed = 0;
uint32_t idx; uint32_t idx;
seed = seed * 314159 + 1; 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; return idx;
} }

View File

@ -1374,8 +1374,8 @@ void cpu_loop(CPUMIPSState *env)
trapnr = cpu_mips_exec(env); trapnr = cpu_mips_exec(env);
switch(trapnr) { switch(trapnr) {
case EXCP_SYSCALL: case EXCP_SYSCALL:
syscall_num = env->gpr[2] - 4000; syscall_num = env->gpr[2][env->current_tc] - 4000;
env->PC += 4; env->PC[env->current_tc] += 4;
if (syscall_num >= sizeof(mips_syscall_args)) { if (syscall_num >= sizeof(mips_syscall_args)) {
ret = -ENOSYS; ret = -ENOSYS;
} else { } else {
@ -1384,7 +1384,7 @@ void cpu_loop(CPUMIPSState *env)
target_ulong arg5 = 0, arg6 = 0, arg7 = 0, arg8 = 0; target_ulong arg5 = 0, arg6 = 0, arg7 = 0, arg8 = 0;
nb_args = mips_syscall_args[syscall_num]; nb_args = mips_syscall_args[syscall_num];
sp_reg = env->gpr[29]; sp_reg = env->gpr[29][env->current_tc];
switch (nb_args) { switch (nb_args) {
/* these arguments are taken from the stack */ /* these arguments are taken from the stack */
case 8: arg8 = tgetl(sp_reg + 28); case 8: arg8 = tgetl(sp_reg + 28);
@ -1394,18 +1394,20 @@ void cpu_loop(CPUMIPSState *env)
default: default:
break; break;
} }
ret = do_syscall(env, env->gpr[2], ret = do_syscall(env, env->gpr[2][env->current_tc],
env->gpr[4], env->gpr[5], env->gpr[4][env->current_tc],
env->gpr[6], env->gpr[7], env->gpr[5][env->current_tc],
env->gpr[6][env->current_tc],
env->gpr[7][env->current_tc],
arg5, arg6/*, arg7, arg8*/); arg5, arg6/*, arg7, arg8*/);
} }
if ((unsigned int)ret >= (unsigned int)(-1133)) { if ((unsigned int)ret >= (unsigned int)(-1133)) {
env->gpr[7] = 1; /* error flag */ env->gpr[7][env->current_tc] = 1; /* error flag */
ret = -ret; ret = -ret;
} else { } 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; break;
case EXCP_TLBL: case EXCP_TLBL:
case EXCP_TLBS: case EXCP_TLBS:
@ -2053,9 +2055,9 @@ int main(int argc, char **argv)
cpu_mips_register(env, def); cpu_mips_register(env, def);
for(i = 0; i < 32; i++) { 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) #elif defined(TARGET_SH4)
{ {

View File

@ -1686,10 +1686,10 @@ setup_sigcontext(CPUState *regs, struct target_sigcontext *sc)
{ {
int err = 0; 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 { \ #define save_gp_reg(i) do { \
err |= __put_user(regs->gpr[i], &sc->sc_regs[i]); \ err |= __put_user(regs->gpr[i][regs->current_tc], &sc->sc_regs[i]); \
} while(0) } while(0)
__put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2); __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); 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); save_gp_reg(31);
#undef save_gp_reg #undef save_gp_reg
err |= __put_user(regs->HI, &sc->sc_mdhi); err |= __put_user(regs->HI[0][regs->current_tc], &sc->sc_mdhi);
err |= __put_user(regs->LO, &sc->sc_mdlo); 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 */ /* Not used yet, but might be useful if we ever have DSP suppport */
#if 0 #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->CP0_EPC, &sc->sc_pc);
err |= __get_user(regs->HI, &sc->sc_mdhi); err |= __get_user(regs->HI[0][regs->current_tc], &sc->sc_mdhi);
err |= __get_user(regs->LO, &sc->sc_mdlo); err |= __get_user(regs->LO[0][regs->current_tc], &sc->sc_mdlo);
#define restore_gp_reg(i) do { \ #define restore_gp_reg(i) do { \
err |= __get_user(regs->gpr[i], &sc->sc_regs[i]); \ err |= __get_user(regs->gpr[i][regs->current_tc], &sc->sc_regs[i]); \
} while(0) } while(0)
restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3); restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3);
restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6); 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; unsigned long sp;
/* Default to using normal stack */ /* 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 * 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 * $25 and PC point to the signal handler, $29 points to the
* struct sigframe. * struct sigframe.
*/ */
regs->gpr[ 4] = sig; regs->gpr[ 4][regs->current_tc] = sig;
regs->gpr[ 5] = 0; regs->gpr[ 5][regs->current_tc] = 0;
regs->gpr[ 6] = h2g(&frame->sf_sc); regs->gpr[ 6][regs->current_tc] = h2g(&frame->sf_sc);
regs->gpr[29] = h2g(frame); regs->gpr[29][regs->current_tc] = h2g(frame);
regs->gpr[31] = h2g(frame->sf_code); regs->gpr[31][regs->current_tc] = h2g(frame->sf_code);
/* The original kernel code sets CP0_EPC to the handler /* The original kernel code sets CP0_EPC to the handler
* since it returns to userland using eret * since it returns to userland using eret
* we cannot do this here, and we must set PC directly */ * 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; return;
give_sigsegv: give_sigsegv:
@ -1907,7 +1907,7 @@ long do_sigreturn(CPUState *regs)
#if defined(DEBUG_SIGNAL) #if defined(DEBUG_SIGNAL)
fprintf(stderr, "do_sigreturn\n"); fprintf(stderr, "do_sigreturn\n");
#endif #endif
frame = (struct sigframe *) regs->gpr[29]; frame = (struct sigframe *) regs->gpr[29][regs->current_tc];
if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe; goto badframe;
@ -1934,7 +1934,7 @@ long do_sigreturn(CPUState *regs)
/* Unreached */ /* Unreached */
#endif #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 /* I am not sure this is right, but it seems to work
* maybe a problem with nested signals ? */ * maybe a problem with nested signals ? */
regs->CP0_EPC = 0; regs->CP0_EPC = 0;

View File

@ -2189,8 +2189,8 @@ int do_fork(CPUState *env, unsigned int flags, unsigned long newsp)
/* ??? is this sufficient? */ /* ??? is this sufficient? */
#elif defined(TARGET_MIPS) #elif defined(TARGET_MIPS)
if (!newsp) if (!newsp)
newsp = env->gpr[29]; newsp = env->gpr[29][env->current_tc];
new_env->gpr[29] = newsp; new_env->gpr[29][env->current_tc] = newsp;
#elif defined(TARGET_PPC) #elif defined(TARGET_PPC)
if (!newsp) if (!newsp)
newsp = env->gpr[1]; 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)); ret = get_errno(pipe(host_pipe));
if (!is_error(ret)) { if (!is_error(ret)) {
#if defined(TARGET_MIPS) #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]; ret = host_pipe[0];
#else #else
tput32(arg1, host_pipe[0]); tput32(arg1, host_pipe[0]);

View File

@ -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); term_printf(" pc=0x" TARGET_FMT_lx " npc=0x" TARGET_FMT_lx, env->pc, env->npc);
if (env->halted) if (env->halted)
term_printf(" (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 #endif
term_printf("\n"); term_printf("\n");
} }

View File

@ -17,21 +17,7 @@ typedef unsigned char uint_fast8_t;
typedef unsigned int uint_fast16_t; typedef unsigned int uint_fast16_t;
#endif #endif
typedef union fpr_t fpr_t; struct CPUMIPSState;
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
typedef struct r4k_tlb_t r4k_tlb_t; typedef struct r4k_tlb_t r4k_tlb_t;
struct r4k_tlb_t { struct r4k_tlb_t {
@ -48,20 +34,40 @@ struct r4k_tlb_t {
target_ulong PFN[2]; 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; typedef union fpr_t fpr_t;
struct CPUMIPSState { union fpr_t {
/* General integer registers */ float64 fd; /* ieee double precision */
target_ulong gpr[32]; float32 fs[2];/* ieee single precision */
/* Special registers */ uint64_t d; /* binary double fixed-point */
target_ulong PC; uint32_t w[2]; /* binary single fixed-point */
#if TARGET_LONG_BITS > HOST_LONG_BITS };
target_ulong t0; /* define FP_ENDIAN_IDX to access the same location
target_ulong t1; * in the fpr_t union regardless of the host endianess
target_ulong t2; */
#if defined(WORDS_BIGENDIAN)
# define FP_ENDIAN_IDX 1
#else
# define FP_ENDIAN_IDX 0
#endif #endif
target_ulong HI, LO;
typedef struct CPUMIPSFPUContext CPUMIPSFPUContext;
struct CPUMIPSFPUContext {
/* Floating point registers */ /* Floating point registers */
fpr_t fpr[32]; fpr_t fpr[32];
#ifndef USE_HOST_FLOAT_REGS #ifndef USE_HOST_FLOAT_REGS
@ -99,30 +105,161 @@ struct CPUMIPSState {
#define FP_DIV0 8 #define FP_DIV0 8
#define FP_INVALID 16 #define FP_INVALID 16
#define FP_UNIMPLEMENTED 32 #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; uint32_t SEGBITS;
target_ulong SEGMask; 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; int32_t CP0_Index;
/* CP0_MVP* are per MVP registers. */
int32_t CP0_Random; 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; 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_EntryLo1;
target_ulong CP0_Context; target_ulong CP0_Context;
int32_t CP0_PageMask; int32_t CP0_PageMask;
int32_t CP0_PageGrain; int32_t CP0_PageGrain;
int32_t CP0_Wired; 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; int32_t CP0_HWREna;
target_ulong CP0_BadVAddr; target_ulong CP0_BadVAddr;
int32_t CP0_Count; int32_t CP0_Count;
@ -152,8 +289,24 @@ struct CPUMIPSState {
#define CP0St_EXL 1 #define CP0St_EXL 1
#define CP0St_IE 0 #define CP0St_IE 0
int32_t CP0_IntCtl; int32_t CP0_IntCtl;
#define CP0IntCtl_IPTI 29
#define CP0IntCtl_IPPC1 26
#define CP0IntCtl_VS 5
int32_t CP0_SRSCtl; 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; 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; int32_t CP0_Cause;
#define CP0Ca_BD 31 #define CP0Ca_BD 31
#define CP0Ca_TI 30 #define CP0Ca_TI 30
@ -219,13 +372,14 @@ struct CPUMIPSState {
#define CP0C3_TL 0 #define CP0C3_TL 0
int32_t CP0_Config6; int32_t CP0_Config6;
int32_t CP0_Config7; int32_t CP0_Config7;
/* XXX: Maybe make LLAddr per-TC? */
target_ulong CP0_LLAddr; target_ulong CP0_LLAddr;
target_ulong CP0_WatchLo[8]; target_ulong CP0_WatchLo[8];
int32_t CP0_WatchHi[8]; int32_t CP0_WatchHi[8];
target_ulong CP0_XContext; target_ulong CP0_XContext;
int32_t CP0_Framemask; int32_t CP0_Framemask;
int32_t CP0_Debug; int32_t CP0_Debug;
#define CPDB_DBD 31 #define CP0DB_DBD 31
#define CP0DB_DM 30 #define CP0DB_DM 30
#define CP0DB_LSNM 28 #define CP0DB_LSNM 28
#define CP0DB_Doze 27 #define CP0DB_Doze 27
@ -243,6 +397,7 @@ struct CPUMIPSState {
#define CP0DB_DDBL 2 #define CP0DB_DDBL 2
#define CP0DB_DBp 1 #define CP0DB_DBp 1
#define CP0DB_DSS 0 #define CP0DB_DSS 0
int32_t CP0_Debug_tcstatus[MIPS_TC_MAX];
target_ulong CP0_DEPC; target_ulong CP0_DEPC;
int32_t CP0_Performance0; int32_t CP0_Performance0;
int32_t CP0_TagLo; int32_t CP0_TagLo;
@ -284,7 +439,8 @@ struct CPUMIPSState {
int SYNCI_Step; /* Address step size for SYNCI */ int SYNCI_Step; /* Address step size for SYNCI */
int CCRes; /* Cycle count resolution/divisor */ 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 #ifdef CONFIG_USER_ONLY
target_ulong tls_value; target_ulong tls_value;
@ -376,6 +532,7 @@ enum {
EXCP_TLBS, EXCP_TLBS,
EXCP_DBE, EXCP_DBE,
EXCP_DDBL, EXCP_DDBL,
EXCP_THREAD,
EXCP_MTCP0 = 0x104, /* mtmsr instruction: */ EXCP_MTCP0 = 0x104, /* mtmsr instruction: */
/* may change privilege level */ /* may change privilege level */
EXCP_BRANCH = 0x108, /* branch instruction */ EXCP_BRANCH = 0x108, /* branch instruction */

View File

@ -23,24 +23,24 @@ register target_ulong T2 asm(AREG3);
#if defined (USE_HOST_FLOAT_REGS) #if defined (USE_HOST_FLOAT_REGS)
#error "implement me." #error "implement me."
#else #else
#define FDT0 (env->ft0.fd) #define FDT0 (env->fpu->ft0.fd)
#define FDT1 (env->ft1.fd) #define FDT1 (env->fpu->ft1.fd)
#define FDT2 (env->ft2.fd) #define FDT2 (env->fpu->ft2.fd)
#define FST0 (env->ft0.fs[FP_ENDIAN_IDX]) #define FST0 (env->fpu->ft0.fs[FP_ENDIAN_IDX])
#define FST1 (env->ft1.fs[FP_ENDIAN_IDX]) #define FST1 (env->fpu->ft1.fs[FP_ENDIAN_IDX])
#define FST2 (env->ft2.fs[FP_ENDIAN_IDX]) #define FST2 (env->fpu->ft2.fs[FP_ENDIAN_IDX])
#define FSTH0 (env->ft0.fs[!FP_ENDIAN_IDX]) #define FSTH0 (env->fpu->ft0.fs[!FP_ENDIAN_IDX])
#define FSTH1 (env->ft1.fs[!FP_ENDIAN_IDX]) #define FSTH1 (env->fpu->ft1.fs[!FP_ENDIAN_IDX])
#define FSTH2 (env->ft2.fs[!FP_ENDIAN_IDX]) #define FSTH2 (env->fpu->ft2.fs[!FP_ENDIAN_IDX])
#define DT0 (env->ft0.d) #define DT0 (env->fpu->ft0.d)
#define DT1 (env->ft1.d) #define DT1 (env->fpu->ft1.d)
#define DT2 (env->ft2.d) #define DT2 (env->fpu->ft2.d)
#define WT0 (env->ft0.w[FP_ENDIAN_IDX]) #define WT0 (env->fpu->ft0.w[FP_ENDIAN_IDX])
#define WT1 (env->ft1.w[FP_ENDIAN_IDX]) #define WT1 (env->fpu->ft1.w[FP_ENDIAN_IDX])
#define WT2 (env->ft2.w[FP_ENDIAN_IDX]) #define WT2 (env->fpu->ft2.w[FP_ENDIAN_IDX])
#define WTH0 (env->ft0.w[!FP_ENDIAN_IDX]) #define WTH0 (env->fpu->ft0.w[!FP_ENDIAN_IDX])
#define WTH1 (env->ft1.w[!FP_ENDIAN_IDX]) #define WTH1 (env->fpu->ft1.w[!FP_ENDIAN_IDX])
#define WTH2 (env->ft2.w[!FP_ENDIAN_IDX]) #define WTH2 (env->fpu->ft2.w[!FP_ENDIAN_IDX])
#endif #endif
#if defined (DEBUG_OP) #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_clock_init (CPUState *env);
void cpu_mips_tlb_flush (CPUState *env, int flush_global); 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) \ #define FOP_PROTO(op) \
void do_float_ ## op ## _s(void); \ void do_float_ ## op ## _s(void); \

View File

@ -24,14 +24,14 @@
#define OP_WLOAD_FREG(treg, tregname, FREG) \ #define OP_WLOAD_FREG(treg, tregname, FREG) \
void glue(glue(op_load_fpr_,tregname), FREG) (void) \ 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(); \ RETURN(); \
} }
#define OP_WSTORE_FREG(treg, tregname, FREG) \ #define OP_WSTORE_FREG(treg, tregname, FREG) \
void glue(glue(op_store_fpr_,tregname), FREG) (void) \ 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(); \ RETURN(); \
} }
@ -50,10 +50,10 @@ OP_WSTORE_FREG(WT2, WT2_fpr, FREG)
void glue(glue(op_load_fpr_,tregname), FREG) (void) \ void glue(glue(op_load_fpr_,tregname), FREG) (void) \
{ \ { \
if (env->hflags & MIPS_HFLAG_F64) \ if (env->hflags & MIPS_HFLAG_F64) \
treg = env->fpr[FREG].fd; \ treg = env->fpu->fpr[FREG].fd; \
else \ else \
treg = (uint64_t)(env->fpr[FREG | 1].fs[FP_ENDIAN_IDX]) << 32 | \ treg = (uint64_t)(env->fpu->fpr[FREG | 1].fs[FP_ENDIAN_IDX]) << 32 | \
env->fpr[FREG & ~1].fs[FP_ENDIAN_IDX]; \ env->fpu->fpr[FREG & ~1].fs[FP_ENDIAN_IDX]; \
RETURN(); \ RETURN(); \
} }
@ -61,10 +61,10 @@ OP_WSTORE_FREG(WT2, WT2_fpr, FREG)
void glue(glue(op_store_fpr_,tregname), FREG) (void) \ void glue(glue(op_store_fpr_,tregname), FREG) (void) \
{ \ { \
if (env->hflags & MIPS_HFLAG_F64) \ if (env->hflags & MIPS_HFLAG_F64) \
env->fpr[FREG].fd = treg; \ env->fpu->fpr[FREG].fd = treg; \
else { \ else { \
env->fpr[FREG | 1].fs[FP_ENDIAN_IDX] = treg >> 32; \ env->fpu->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; \
} \ } \
RETURN(); \ RETURN(); \
} }
@ -81,14 +81,14 @@ OP_DSTORE_FREG(DT2, DT2_fpr, FREG)
#define OP_PSLOAD_FREG(treg, tregname, FREG) \ #define OP_PSLOAD_FREG(treg, tregname, FREG) \
void glue(glue(op_load_fpr_,tregname), FREG) (void) \ 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(); \ RETURN(); \
} }
#define OP_PSSTORE_FREG(treg, tregname, FREG) \ #define OP_PSSTORE_FREG(treg, tregname, FREG) \
void glue(glue(op_store_fpr_,tregname), FREG) (void) \ 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(); \ RETURN(); \
} }

View File

@ -70,8 +70,8 @@ int r4k_map_address (CPUState *env, target_ulong *physical, int *prot,
uint8_t ASID = env->CP0_EntryHi & 0xFF; uint8_t ASID = env->CP0_EntryHi & 0xFF;
int i; int i;
for (i = 0; i < env->tlb_in_use; i++) { for (i = 0; i < env->tlb->tlb_in_use; i++) {
r4k_tlb_t *tlb = &env->mmu.r4k.tlb[i]; r4k_tlb_t *tlb = &env->tlb->mmu.r4k.tlb[i];
/* 1k pages are not supported. */ /* 1k pages are not supported. */
target_ulong mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1); target_ulong mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
target_ulong tag = address & ~mask; target_ulong tag = address & ~mask;
@ -134,7 +134,7 @@ static int get_physical_address (CPUState *env, target_ulong *physical,
*physical = address & 0xFFFFFFFF; *physical = address & 0xFFFFFFFF;
*prot = PAGE_READ | PAGE_WRITE; *prot = PAGE_READ | PAGE_WRITE;
} else { } 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 #ifdef TARGET_MIPS64
/* /*
@ -144,14 +144,14 @@ static int get_physical_address (CPUState *env, target_ulong *physical,
} else if (address < 0x3FFFFFFFFFFFFFFFULL) { } else if (address < 0x3FFFFFFFFFFFFFFFULL) {
/* xuseg */ /* xuseg */
if (UX && address < (0x3FFFFFFFFFFFFFFFULL & env->SEGMask)) { 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 { } else {
ret = TLBRET_BADADDR; ret = TLBRET_BADADDR;
} }
} else if (address < 0x7FFFFFFFFFFFFFFFULL) { } else if (address < 0x7FFFFFFFFFFFFFFFULL) {
/* xsseg */ /* xsseg */
if (SX && address < (0x7FFFFFFFFFFFFFFFULL & env->SEGMask)) { 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 { } else {
ret = TLBRET_BADADDR; ret = TLBRET_BADADDR;
} }
@ -169,7 +169,7 @@ static int get_physical_address (CPUState *env, target_ulong *physical,
/* xkseg */ /* xkseg */
/* XXX: check supervisor mode */ /* XXX: check supervisor mode */
if (KX && address < (0xFFFFFFFF7FFFFFFFULL & env->SEGMask)) { 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 { } else {
ret = TLBRET_BADADDR; ret = TLBRET_BADADDR;
} }
@ -186,12 +186,12 @@ static int get_physical_address (CPUState *env, target_ulong *physical,
*prot = PAGE_READ | PAGE_WRITE; *prot = PAGE_READ | PAGE_WRITE;
} else if (address < (int32_t)0xE0000000UL) { } else if (address < (int32_t)0xE0000000UL) {
/* kseg2 */ /* 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 { } else {
/* kseg3 */ /* kseg3 */
/* XXX: check supervisor mode */ /* XXX: check supervisor mode */
/* XXX: debug segment is not emulated */ /* 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 0
if (logfile) { 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); cpu_dump_state(env, logfile, fprintf, 0);
#endif #endif
fprintf(logfile, "%s pc " TARGET_FMT_lx " ad " TARGET_FMT_lx " rw %d is_user %d smmu %d\n", 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; rw &= 1;
@ -328,7 +328,7 @@ void do_interrupt (CPUState *env)
if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) { 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", 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 && if (env->exception_index == EXCP_EXT_INTERRUPT &&
(env->hflags & MIPS_HFLAG_DM)) (env->hflags & MIPS_HFLAG_DM))
@ -342,7 +342,7 @@ void do_interrupt (CPUState *env)
* (but we assume the pc has always been updated during * (but we assume the pc has always been updated during
* code translation). * code translation).
*/ */
env->CP0_DEPC = env->PC; env->CP0_DEPC = env->PC[env->current_tc];
goto enter_debug_mode; goto enter_debug_mode;
case EXCP_DINT: case EXCP_DINT:
env->CP0_Debug |= 1 << CP0DB_DINT; env->CP0_Debug |= 1 << CP0DB_DINT;
@ -362,10 +362,10 @@ void do_interrupt (CPUState *env)
if (env->hflags & MIPS_HFLAG_BMASK) { if (env->hflags & MIPS_HFLAG_BMASK) {
/* If the exception was raised from a delay slot, /* If the exception was raised from a delay slot,
come back to the jump. */ 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; env->hflags &= ~MIPS_HFLAG_BMASK;
} else { } else {
env->CP0_DEPC = env->PC; env->CP0_DEPC = env->PC[env->current_tc];
} }
enter_debug_mode: enter_debug_mode:
env->hflags |= MIPS_HFLAG_DM; env->hflags |= MIPS_HFLAG_DM;
@ -375,7 +375,7 @@ void do_interrupt (CPUState *env)
/* EJTAG probe trap enable is not implemented... */ /* EJTAG probe trap enable is not implemented... */
if (!(env->CP0_Status & (1 << CP0St_EXL))) if (!(env->CP0_Status & (1 << CP0St_EXL)))
env->CP0_Cause &= ~(1 << CP0Ca_BD); env->CP0_Cause &= ~(1 << CP0Ca_BD);
env->PC = (int32_t)0xBFC00480; env->PC[env->current_tc] = (int32_t)0xBFC00480;
break; break;
case EXCP_RESET: case EXCP_RESET:
cpu_reset(env); cpu_reset(env);
@ -390,10 +390,10 @@ void do_interrupt (CPUState *env)
if (env->hflags & MIPS_HFLAG_BMASK) { if (env->hflags & MIPS_HFLAG_BMASK) {
/* If the exception was raised from a delay slot, /* If the exception was raised from a delay slot,
come back to the jump. */ 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; env->hflags &= ~MIPS_HFLAG_BMASK;
} else { } else {
env->CP0_ErrorEPC = env->PC; env->CP0_ErrorEPC = env->PC[env->current_tc];
} }
env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV); env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
if ((env->CP0_Config0 & (0x3 << CP0C0_AT))) if ((env->CP0_Config0 & (0x3 << CP0C0_AT)))
@ -401,7 +401,7 @@ void do_interrupt (CPUState *env)
env->hflags &= ~MIPS_HFLAG_UM; env->hflags &= ~MIPS_HFLAG_UM;
if (!(env->CP0_Status & (1 << CP0St_EXL))) if (!(env->CP0_Status & (1 << CP0St_EXL)))
env->CP0_Cause &= ~(1 << CP0Ca_BD); env->CP0_Cause &= ~(1 << CP0Ca_BD);
env->PC = (int32_t)0xBFC00000; env->PC[env->current_tc] = (int32_t)0xBFC00000;
break; break;
case EXCP_MCHECK: case EXCP_MCHECK:
cause = 24; cause = 24;
@ -471,6 +471,9 @@ void do_interrupt (CPUState *env)
goto set_EPC; goto set_EPC;
case EXCP_TLBS: case EXCP_TLBS:
cause = 3; cause = 3;
goto set_EPC;
case EXCP_THREAD:
cause = 25;
if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL))) { if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL))) {
#ifdef TARGET_MIPS64 #ifdef TARGET_MIPS64
int R = env->CP0_BadVAddr >> 62; int R = env->CP0_BadVAddr >> 62;
@ -489,10 +492,10 @@ void do_interrupt (CPUState *env)
if (env->hflags & MIPS_HFLAG_BMASK) { if (env->hflags & MIPS_HFLAG_BMASK) {
/* If the exception was raised from a delay slot, /* If the exception was raised from a delay slot,
come back to the jump. */ 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); env->CP0_Cause |= (1 << CP0Ca_BD);
} else { } else {
env->CP0_EPC = env->PC; env->CP0_EPC = env->PC[env->current_tc];
env->CP0_Cause &= ~(1 << CP0Ca_BD); env->CP0_Cause &= ~(1 << CP0Ca_BD);
} }
env->CP0_Status |= (1 << CP0St_EXL); env->CP0_Status |= (1 << CP0St_EXL);
@ -502,11 +505,11 @@ void do_interrupt (CPUState *env)
} }
env->hflags &= ~MIPS_HFLAG_BMASK; env->hflags &= ~MIPS_HFLAG_BMASK;
if (env->CP0_Status & (1 << CP0St_BEV)) { if (env->CP0_Status & (1 << CP0St_BEV)) {
env->PC = (int32_t)0xBFC00200; env->PC[env->current_tc] = (int32_t)0xBFC00200;
} else { } 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); env->CP0_Cause = (env->CP0_Cause & ~(0x1f << CP0Ca_EC)) | (cause << CP0Ca_EC);
break; break;
default: default:
@ -520,7 +523,7 @@ void do_interrupt (CPUState *env)
if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) { if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) {
fprintf(logfile, "%s: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx " cause %d excp %d\n" 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", " 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_Status, env->CP0_Cause, env->CP0_BadVAddr,
env->CP0_DEPC); 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; uint8_t ASID = env->CP0_EntryHi & 0xFF;
target_ulong mask; 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 /* The qemu TLB is flushed when the ASID changes, so no need to
flush these entries again. */ flush these entries again. */
if (tlb->G == 0 && tlb->ASID != ASID) { if (tlb->G == 0 && tlb->ASID != ASID) {
return; 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 /* For tlbwr, we can shadow the discarded entry into
a new (fake) TLB entry, as long as the guest can not a new (fake) TLB entry, as long as the guest can not
tell that it's there. */ tell that it's there. */
env->mmu.r4k.tlb[env->tlb_in_use] = *tlb; env->tlb->mmu.r4k.tlb[env->tlb->tlb_in_use] = *tlb;
env->tlb_in_use++; env->tlb->tlb_in_use++;
return; return;
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -21,31 +21,44 @@
#if defined(REG) #if defined(REG)
void glue(op_load_gpr_T0_gpr, REG) (void) void glue(op_load_gpr_T0_gpr, REG) (void)
{ {
T0 = env->gpr[REG]; T0 = env->gpr[REG][env->current_tc];
RETURN(); RETURN();
} }
void glue(op_store_T0_gpr_gpr, REG) (void) void glue(op_store_T0_gpr_gpr, REG) (void)
{ {
env->gpr[REG] = T0; env->gpr[REG][env->current_tc] = T0;
RETURN(); RETURN();
} }
void glue(op_load_gpr_T1_gpr, REG) (void) void glue(op_load_gpr_T1_gpr, REG) (void)
{ {
T1 = env->gpr[REG]; T1 = env->gpr[REG][env->current_tc];
RETURN(); RETURN();
} }
void glue(op_store_T1_gpr_gpr, REG) (void) void glue(op_store_T1_gpr_gpr, REG) (void)
{ {
env->gpr[REG] = T1; env->gpr[REG][env->current_tc] = T1;
RETURN(); RETURN();
} }
void glue(op_load_gpr_T2_gpr, REG) (void) 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(); RETURN();
} }
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -43,11 +43,11 @@
/* No config4, no DSP ASE, no large physaddr, /* No config4, no DSP ASE, no large physaddr,
no external interrupt controller, no vectored interupts, 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 \ #define MIPS_CONFIG3 \
((0 << CP0C3_M) | (0 << CP0C3_DSPP) | (0 << CP0C3_LPA) | \ ((0 << CP0C3_M) | (0 << CP0C3_DSPP) | (0 << CP0C3_LPA) | \
(0 << CP0C3_VEIC) | (0 << CP0C3_VInt) | (0 << CP0C3_SP) | \ (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 implementation number of 1.
Define a major version 1, minor version 0. */ Define a major version 1, minor version 0. */
@ -65,9 +65,21 @@ struct mips_def_t {
int32_t CP0_Config7; int32_t CP0_Config7;
int32_t SYNCI_Step; int32_t SYNCI_Step;
int32_t CCRes; 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 CP1_fcr0;
int32_t SEGBITS; 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, .CP0_Config3 = MIPS_CONFIG3,
.SYNCI_Step = 32, .SYNCI_Step = 32,
.CCRes = 2, .CCRes = 2,
.Status_rw_bitmask = 0x3278FF17, .CP0_Status_rw_bitmask = 0x1278FF17,
}, },
{ {
.name = "4KEcR1", .name = "4KEcR1",
@ -98,7 +110,7 @@ static mips_def_t mips_defs[] =
.CP0_Config3 = MIPS_CONFIG3, .CP0_Config3 = MIPS_CONFIG3,
.SYNCI_Step = 32, .SYNCI_Step = 32,
.CCRes = 2, .CCRes = 2,
.Status_rw_bitmask = 0x3278FF17, .CP0_Status_rw_bitmask = 0x1278FF17,
}, },
{ {
.name = "4KEc", .name = "4KEc",
@ -108,10 +120,10 @@ static mips_def_t mips_defs[] =
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) | (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA), (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA),
.CP0_Config2 = MIPS_CONFIG2, .CP0_Config2 = MIPS_CONFIG2,
.CP0_Config3 = MIPS_CONFIG3, .CP0_Config3 = MIPS_CONFIG3 | (0 << CP0C3_VInt),
.SYNCI_Step = 32, .SYNCI_Step = 32,
.CCRes = 2, .CCRes = 2,
.Status_rw_bitmask = 0x3278FF17, .CP0_Status_rw_bitmask = 0x1278FF17,
}, },
{ {
.name = "24Kc", .name = "24Kc",
@ -121,10 +133,11 @@ static mips_def_t mips_defs[] =
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) | (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA), (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA),
.CP0_Config2 = MIPS_CONFIG2, .CP0_Config2 = MIPS_CONFIG2,
.CP0_Config3 = MIPS_CONFIG3, .CP0_Config3 = MIPS_CONFIG3 | (0 << CP0C3_VInt),
.SYNCI_Step = 32, .SYNCI_Step = 32,
.CCRes = 2, .CCRes = 2,
.Status_rw_bitmask = 0x3278FF17, /* No DSP implemented. */
.CP0_Status_rw_bitmask = 0x1278FF17,
}, },
{ {
.name = "24Kf", .name = "24Kf",
@ -134,13 +147,53 @@ static mips_def_t mips_defs[] =
(0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) | (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA), (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA),
.CP0_Config2 = MIPS_CONFIG2, .CP0_Config2 = MIPS_CONFIG2,
.CP0_Config3 = MIPS_CONFIG3, .CP0_Config3 = MIPS_CONFIG3 | (0 << CP0C3_VInt),
.SYNCI_Step = 32, .SYNCI_Step = 32,
.CCRes = 2, .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) | .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
(1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID), (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 #ifdef TARGET_MIPS64
{ {
.name = "R4000", .name = "R4000",
@ -153,7 +206,7 @@ static mips_def_t mips_defs[] =
.CP0_Config3 = MIPS_CONFIG3, .CP0_Config3 = MIPS_CONFIG3,
.SYNCI_Step = 16, .SYNCI_Step = 16,
.CCRes = 2, .CCRes = 2,
.Status_rw_bitmask = 0x3678FFFF, .CP0_Status_rw_bitmask = 0x3678FFFF,
/* The R4000 has a full 64bit FPU doesn't use the fcr0 bits. */ /* The R4000 has a full 64bit FPU doesn't use the fcr0 bits. */
.CP1_fcr0 = (0x5 << FCR0_PRID) | (0x0 << FCR0_REV), .CP1_fcr0 = (0x5 << FCR0_PRID) | (0x0 << FCR0_REV),
.SEGBITS = 40, .SEGBITS = 40,
@ -170,7 +223,7 @@ static mips_def_t mips_defs[] =
.CP0_Config3 = MIPS_CONFIG3, .CP0_Config3 = MIPS_CONFIG3,
.SYNCI_Step = 32, .SYNCI_Step = 32,
.CCRes = 2, .CCRes = 2,
.Status_rw_bitmask = 0x32F8FFFF, .CP0_Status_rw_bitmask = 0x32F8FFFF,
.SEGBITS = 42, .SEGBITS = 42,
}, },
{ {
@ -185,7 +238,7 @@ static mips_def_t mips_defs[] =
.CP0_Config3 = MIPS_CONFIG3, .CP0_Config3 = MIPS_CONFIG3,
.SYNCI_Step = 32, .SYNCI_Step = 32,
.CCRes = 2, .CCRes = 2,
.Status_rw_bitmask = 0x36F8FFFF, .CP0_Status_rw_bitmask = 0x36F8FFFF,
/* The 5Kf has F64 / L / W but doesn't use the fcr0 bits. */ /* The 5Kf has F64 / L / W but doesn't use the fcr0 bits. */
.CP1_fcr0 = (1 << FCR0_D) | (1 << FCR0_S) | .CP1_fcr0 = (1 << FCR0_D) | (1 << FCR0_S) |
(0x81 << FCR0_PRID) | (0x0 << FCR0_REV), (0x81 << FCR0_PRID) | (0x0 << FCR0_REV),
@ -205,7 +258,7 @@ static mips_def_t mips_defs[] =
.CP0_Config3 = MIPS_CONFIG3, .CP0_Config3 = MIPS_CONFIG3,
.SYNCI_Step = 32, .SYNCI_Step = 32,
.CCRes = 2, .CCRes = 2,
.Status_rw_bitmask = 0x36FBFFFF, .CP0_Status_rw_bitmask = 0x36FBFFFF,
/* The 20Kc has F64 / L / W but doesn't use the fcr0 bits. */ /* The 20Kc has F64 / L / W but doesn't use the fcr0 bits. */
.CP1_fcr0 = (1 << FCR0_3D) | (1 << FCR0_PS) | .CP1_fcr0 = (1 << FCR0_3D) | (1 << FCR0_PS) |
(1 << FCR0_D) | (1 << FCR0_S) | (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 #ifndef CONFIG_USER_ONLY
static void no_mmu_init (CPUMIPSState *env, mips_def_t *def) static void no_mmu_init (CPUMIPSState *env, mips_def_t *def)
{ {
env->nb_tlb = 1; env->tlb->nb_tlb = 1;
env->map_address = &no_mmu_map_address; env->tlb->map_address = &no_mmu_map_address;
} }
static void fixed_mmu_init (CPUMIPSState *env, mips_def_t *def) static void fixed_mmu_init (CPUMIPSState *env, mips_def_t *def)
{ {
env->nb_tlb = 1; env->tlb->nb_tlb = 1;
env->map_address = &fixed_mmu_map_address; env->tlb->map_address = &fixed_mmu_map_address;
} }
static void r4k_mmu_init (CPUMIPSState *env, mips_def_t *def) static void r4k_mmu_init (CPUMIPSState *env, mips_def_t *def)
{ {
env->nb_tlb = 1 + ((def->CP0_Config1 >> CP0C1_MMU) & 63); env->tlb->nb_tlb = 1 + ((def->CP0_Config1 >> CP0C1_MMU) & 63);
env->map_address = &r4k_map_address; env->tlb->map_address = &r4k_map_address;
env->do_tlbwi = r4k_do_tlbwi; env->tlb->do_tlbwi = r4k_do_tlbwi;
env->do_tlbwr = r4k_do_tlbwr; env->tlb->do_tlbwr = r4k_do_tlbwr;
env->do_tlbp = r4k_do_tlbp; env->tlb->do_tlbp = r4k_do_tlbp;
env->do_tlbr = r4k_do_tlbr; 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 */ #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) int cpu_mips_register (CPUMIPSState *env, mips_def_t *def)
{ {
if (!def) if (!def)
@ -285,8 +399,9 @@ int cpu_mips_register (CPUMIPSState *env, mips_def_t *def)
env->CP0_Config7 = def->CP0_Config7; env->CP0_Config7 = def->CP0_Config7;
env->SYNCI_Step = def->SYNCI_Step; env->SYNCI_Step = def->SYNCI_Step;
env->CCRes = def->CCRes; env->CCRes = def->CCRes;
env->Status_rw_bitmask = def->Status_rw_bitmask; env->CP0_Status_rw_bitmask = def->CP0_Status_rw_bitmask;
env->fcr0 = def->CP1_fcr0; env->CP0_TCStatus_rw_bitmask = def->CP0_TCStatus_rw_bitmask;
env->CP0_SRSCtl = def->CP0_SRSCtl;
#ifdef TARGET_MIPS64 #ifdef TARGET_MIPS64
if ((env->CP0_Config0 & (0x3 << CP0C0_AT))) if ((env->CP0_Config0 & (0x3 << CP0C0_AT)))
{ {
@ -298,31 +413,21 @@ int cpu_mips_register (CPUMIPSState *env, mips_def_t *def)
env->SEGMask = 0xFFFFFFFF; env->SEGMask = 0xFFFFFFFF;
} }
#endif #endif
#ifdef CONFIG_USER_ONLY env->CP0_SRSConf0_rw_bitmask = def->CP0_SRSConf0_rw_bitmask;
if (env->CP0_Config1 & (1 << CP0C1_FP)) env->CP0_SRSConf0 = def->CP0_SRSConf0;
env->hflags |= MIPS_HFLAG_FPU; env->CP0_SRSConf1_rw_bitmask = def->CP0_SRSConf1_rw_bitmask;
if (env->fcr0 & (1 << FCR0_F64)) env->CP0_SRSConf1 = def->CP0_SRSConf1;
env->hflags |= MIPS_HFLAG_F64; env->CP0_SRSConf2_rw_bitmask = def->CP0_SRSConf2_rw_bitmask;
#else env->CP0_SRSConf2 = def->CP0_SRSConf2;
/* There are more full-featured MMU variants in older MIPS CPUs, env->CP0_SRSConf3_rw_bitmask = def->CP0_SRSConf3_rw_bitmask;
R3000, R6000 and R8000 come to mind. If we ever support them, env->CP0_SRSConf3 = def->CP0_SRSConf3;
this check will need to look up a different place than those env->CP0_SRSConf4_rw_bitmask = def->CP0_SRSConf4_rw_bitmask;
newfangled config registers. */ env->CP0_SRSConf4 = def->CP0_SRSConf4;
switch ((env->CP0_Config0 >> CP0C0_MT) & 3) {
case 0: #ifndef CONFIG_USER_ONLY
no_mmu_init(env, def); mmu_init(env, def);
break; #endif
case 1: fpu_init(env, def);
r4k_mmu_init(env, def); mvp_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 */
return 0; return 0;
} }

View File

@ -305,7 +305,7 @@ int cpu_restore_state(TranslationBlock *tb,
#elif defined(TARGET_M68K) #elif defined(TARGET_M68K)
env->pc = gen_opc_pc[j]; env->pc = gen_opc_pc[j];
#elif defined(TARGET_MIPS) #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 &= ~MIPS_HFLAG_BMASK;
env->hflags |= gen_opc_hflags[j]; env->hflags |= gen_opc_hflags[j];
#elif defined(TARGET_ALPHA) #elif defined(TARGET_ALPHA)