Skip to content

Commit

Permalink
Merge pull request #67 from lalrae/mips-updates
Browse files Browse the repository at this point in the history
  • Loading branch information
Leon Alrae committed Sep 11, 2015
2 parents 9647729 + 990b0bd commit 307010a
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 62 deletions.
8 changes: 7 additions & 1 deletion hw/mips/cputimer.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,16 @@ uint32_t cpu_mips_get_random (CPUMIPSState *env)
static uint32_t lfsr = 1;
static uint32_t prev_idx = 0;
uint32_t idx;
uint32_t nb_rand_tlb = env->tlb->nb_tlb - env->CP0_Wired;

if (nb_rand_tlb == 1) {
return env->tlb->nb_tlb - 1;
}

/* Don't return same value twice, so get another value */
do {
lfsr = (lfsr >> 1) ^ (-(lfsr & 1u) & 0xd0000001u);
idx = lfsr % (env->tlb->nb_tlb - env->CP0_Wired) + env->CP0_Wired;
idx = lfsr % nb_rand_tlb + env->CP0_Wired;
} while (idx == prev_idx);
prev_idx = idx;
return idx;
Expand Down
9 changes: 6 additions & 3 deletions target-mips/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,15 @@ static bool mips_cpu_has_work(CPUState *cs)
CPUMIPSState *env = &cpu->env;
bool has_work = false;

/* It is implementation dependent if non-enabled interrupts
wake-up the CPU, however most of the implementations only
/* Prior to MIPS Release 6 it is implementation dependent if non-enabled
interrupts wake-up the CPU, however most of the implementations only
check for interrupts that can be taken. */
if ((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
cpu_mips_hw_interrupts_pending(env)) {
has_work = true;
if (cpu_mips_hw_interrupts_enabled(env) ||
(env->insn_flags & ISA_MIPS32R6)) {
has_work = true;
}
}

/* MIPS-MT has the ability to halt the CPU. */
Expand Down
36 changes: 22 additions & 14 deletions target-mips/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -677,23 +677,24 @@ static inline int cpu_mmu_index (CPUMIPSState *env)
return env->hflags & MIPS_HFLAG_KSU;
}

static inline int cpu_mips_hw_interrupts_pending(CPUMIPSState *env)
static inline bool cpu_mips_hw_interrupts_enabled(CPUMIPSState *env)
{
int32_t pending;
int32_t status;
int r;

if (!(env->CP0_Status & (1 << CP0St_IE)) ||
(env->CP0_Status & (1 << CP0St_EXL)) ||
(env->CP0_Status & (1 << CP0St_ERL)) ||
return (env->CP0_Status & (1 << CP0St_IE)) &&
!(env->CP0_Status & (1 << CP0St_EXL)) &&
!(env->CP0_Status & (1 << CP0St_ERL)) &&
!(env->hflags & MIPS_HFLAG_DM) &&
/* Note that the TCStatus IXMT field is initialized to zero,
and only MT capable cores can set it to one. So we don't
need to check for MT capabilities here. */
(env->active_tc.CP0_TCStatus & (1 << CP0TCSt_IXMT)) ||
(env->hflags & MIPS_HFLAG_DM)) {
/* Interrupts are disabled */
return 0;
}
!(env->active_tc.CP0_TCStatus & (1 << CP0TCSt_IXMT));
}

/* Check if there is pending and not masked out interrupt */
static inline bool cpu_mips_hw_interrupts_pending(CPUMIPSState *env)
{
int32_t pending;
int32_t status;
bool r;

pending = env->CP0_Cause & CP0Ca_IP_mask;
status = env->CP0_Status & CP0Ca_IP_mask;
Expand All @@ -707,7 +708,7 @@ static inline int cpu_mips_hw_interrupts_pending(CPUMIPSState *env)
/* A MIPS configured with compatibility or VInt (Vectored Interrupts)
treats the pending lines as individual interrupt lines, the status
lines are individual masks. */
r = pending & status;
r = (pending & status) != 0;
}
return r;
}
Expand Down Expand Up @@ -1061,7 +1062,14 @@ static inline void cpu_mips_store_status(CPUMIPSState *env, target_ulong val)

if (env->insn_flags & ISA_MIPS32R6) {
bool has_supervisor = extract32(mask, CP0St_KSU, 2) == 0x3;
#if defined(TARGET_MIPS64)
uint32_t ksux;

ksux = (1 << CP0St_KX) & val;
ksux |= (ksux >> 1) & val; /* KX = 0 forces SX to be 0 */
ksux |= (ksux >> 1) & val; /* SX = 0 forces UX to be 0 */
val = (val & ~(7 << CP0St_UX)) | ksux;
#endif
if (has_supervisor && extract32(val, CP0St_KSU, 2) == 0x3) {
mask &= ~(3 << CP0St_KSU);
}
Expand Down
3 changes: 2 additions & 1 deletion target-mips/helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -1124,7 +1124,8 @@ bool mips_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
MIPSCPU *cpu = MIPS_CPU(cs);
CPUMIPSState *env = &cpu->env;

if (cpu_mips_hw_interrupts_pending(env)) {
if (cpu_mips_hw_interrupts_enabled(env) &&
cpu_mips_hw_interrupts_pending(env)) {
/* Raise it */
cs->exception_index = EXCP_EXT_INTERRUPT;
env->error_code = 0;
Expand Down
6 changes: 5 additions & 1 deletion target-mips/op_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -2351,7 +2351,11 @@ target_ulong helper_rdhwr_synci_step(CPUMIPSState *env)
target_ulong helper_rdhwr_cc(CPUMIPSState *env)
{
check_hwrena(env, 2);
return env->CP0_Count;
#ifdef CONFIG_USER_ONLY
return env->CP0_Count;
#else
return (int32_t)cpu_mips_get_count(env);
#endif
}

target_ulong helper_rdhwr_ccres(CPUMIPSState *env)
Expand Down
71 changes: 29 additions & 42 deletions target-mips/translate.c
Original file line number Diff line number Diff line change
Expand Up @@ -5061,12 +5061,6 @@ static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
tcg_temp_free_i32(t0);
}

static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
{
tcg_gen_ld_tl(arg, cpu_env, off);
tcg_gen_ext32s_tl(arg, arg);
}

static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
{
TCGv_i32 t0 = tcg_temp_new_i32();
Expand All @@ -5076,12 +5070,6 @@ static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
tcg_temp_free_i32(t0);
}

static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
{
tcg_gen_ext32s_tl(arg, arg);
tcg_gen_st_tl(arg, cpu_env, off);
}

static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
{
const char *rn = "invalid";
Expand Down Expand Up @@ -5308,17 +5296,19 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
break;
case 4:
CP0_CHECK(ctx->insn_flags & ASE_MT);
gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
tcg_gen_ld32s_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
rn = "YQMask";
break;
case 5:
CP0_CHECK(ctx->insn_flags & ASE_MT);
gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
tcg_gen_ld32s_tl(arg, cpu_env,
offsetof(CPUMIPSState, CP0_VPESchedule));
rn = "VPESchedule";
break;
case 6:
CP0_CHECK(ctx->insn_flags & ASE_MT);
gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
tcg_gen_ld32s_tl(arg, cpu_env,
offsetof(CPUMIPSState, CP0_VPEScheFBack));
rn = "VPEScheFBack";
break;
case 7:
Expand Down Expand Up @@ -5419,8 +5409,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
case 4:
switch (sel) {
case 0:
tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
tcg_gen_ext32s_tl(arg, arg);
tcg_gen_ld32s_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
rn = "Context";
break;
case 1:
Expand Down Expand Up @@ -5522,8 +5511,8 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
case 8:
switch (sel) {
case 0:
tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
tcg_gen_ext32s_tl(arg, arg);
tcg_gen_ld32s_tl(arg, cpu_env,
offsetof(CPUMIPSState, CP0_BadVAddr));
rn = "BadVAddr";
break;
case 1:
Expand Down Expand Up @@ -5564,8 +5553,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
case 10:
switch (sel) {
case 0:
tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
tcg_gen_ext32s_tl(arg, arg);
tcg_gen_ld32s_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
rn = "EntryHi";
break;
default:
Expand Down Expand Up @@ -5621,8 +5609,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
case 14:
switch (sel) {
case 0:
tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
tcg_gen_ext32s_tl(arg, arg);
tcg_gen_ld32s_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
rn = "EPC";
break;
default:
Expand Down Expand Up @@ -5728,8 +5715,8 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
case 0:
#if defined(TARGET_MIPS64)
check_insn(ctx, ISA_MIPS3);
tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
tcg_gen_ext32s_tl(arg, arg);
tcg_gen_ld32s_tl(arg, cpu_env,
offsetof(CPUMIPSState, CP0_XContext));
rn = "XContext";
break;
#endif
Expand Down Expand Up @@ -5783,8 +5770,7 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
switch (sel) {
case 0:
/* EJTAG support */
tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
tcg_gen_ext32s_tl(arg, arg);
tcg_gen_ld32s_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
rn = "DEPC";
break;
default:
Expand Down Expand Up @@ -5891,8 +5877,8 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
case 30:
switch (sel) {
case 0:
tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
tcg_gen_ext32s_tl(arg, arg);
tcg_gen_ld32s_tl(arg, cpu_env,
offsetof(CPUMIPSState, CP0_ErrorEPC));
rn = "ErrorEPC";
break;
default:
Expand All @@ -5908,9 +5894,8 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
break;
case 2 ... 7:
CP0_CHECK(ctx->kscrexist & (1 << sel));
tcg_gen_ld_tl(arg, cpu_env,
offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
tcg_gen_ext32s_tl(arg, arg);
tcg_gen_ld32s_tl(arg, cpu_env,
offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
rn = "KScratch";
break;
default:
Expand Down Expand Up @@ -5999,12 +5984,14 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
break;
case 5:
CP0_CHECK(ctx->insn_flags & ASE_MT);
gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
tcg_gen_st_tl(arg, cpu_env,
offsetof(CPUMIPSState, CP0_VPESchedule));
rn = "VPESchedule";
break;
case 6:
CP0_CHECK(ctx->insn_flags & ASE_MT);
gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
tcg_gen_st_tl(arg, cpu_env,
offsetof(CPUMIPSState, CP0_VPEScheFBack));
rn = "VPEScheFBack";
break;
case 7:
Expand Down Expand Up @@ -6279,7 +6266,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
case 14:
switch (sel) {
case 0:
gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_EPC));
tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
rn = "EPC";
break;
default:
Expand Down Expand Up @@ -6462,7 +6449,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
switch (sel) {
case 0:
/* EJTAG support */
gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_DEPC));
tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
rn = "DEPC";
break;
default:
Expand Down Expand Up @@ -6565,7 +6552,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
case 30:
switch (sel) {
case 0:
gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_ErrorEPC));
tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
rn = "ErrorEPC";
break;
default:
Expand Down Expand Up @@ -9502,7 +9489,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
opn = "movn.s";
break;
case OPC_RECIP_S:
check_cop1x(ctx);
{
TCGv_i32 fp0 = tcg_temp_new_i32();

Expand All @@ -9514,7 +9500,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
opn = "recip.s";
break;
case OPC_RSQRT_S:
check_cop1x(ctx);
{
TCGv_i32 fp0 = tcg_temp_new_i32();

Expand Down Expand Up @@ -10047,7 +10032,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
opn = "movn.d";
break;
case OPC_RECIP_D:
check_cp1_64bitmode(ctx);
check_cp1_registers(ctx, fs | fd);
{
TCGv_i64 fp0 = tcg_temp_new_i64();

Expand All @@ -10059,7 +10044,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
opn = "recip.d";
break;
case OPC_RSQRT_D:
check_cp1_64bitmode(ctx);
check_cp1_registers(ctx, fs | fd);
{
TCGv_i64 fp0 = tcg_temp_new_i64();

Expand Down Expand Up @@ -20374,7 +20359,9 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
#if defined(TARGET_MIPS64)
/* OPC_DAUI */
check_mips_64(ctx);
if (rt != 0) {
if (rs == 0) {
generate_exception(ctx, EXCP_RI);
} else if (rt != 0) {
TCGv t0 = tcg_temp_new();
gen_load_gpr(t0, rs);
tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
Expand Down

0 comments on commit 307010a

Please sign in to comment.