Commit 84afc4dd authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/lalrae/tags/mips-20141216' into staging



* remotes/lalrae/tags/mips-20141216: (30 commits)
  target-mips: remove excp_names[] from linux-user as it is unused
  disas/mips: disable unused mips16_to_32_reg_map[]
  disas/mips: remove unused mips_msa_control_names_numeric[32]
  target-mips: convert single case switch into if statement
  target-mips: Fix DisasContext's ulri member initialization
  target-mips: Use local float status pointer across MSA macros
  target-mips: Add missing calls to synchronise SoftFloat status
  linux-user: Use the 5KEf processor for 64-bit emulation
  target-mips: Also apply the CP0.Status mask to MTTC0
  target-mips: gdbstub: Clean up FPU register handling
  target-mips: Correct 32-bit address space wrapping
  target-mips: Tighten ISA level checks
  target-mips: Fix CP0.Config3.ISAOnExc write accesses
  target-mips: Output CP0.Config2-5 in the register dump
  target-mips: Fix the 64-bit case for microMIPS MOVE16 and MOVEP
  target-mips: Correct the writes to Status and Cause registers via gdbstub
  target-mips: Correct the handling of writes to CP0.Status for MIPSr6
  target-mips: Correct MIPS16/microMIPS branch size calculation
  target-mips: Restore the order of helpers
  target-mips: Remove unused `FLOAT_OP' macro
  ...

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 339aaf5b d4fa5354
Loading
Loading
Loading
Loading
+2 −8
Original line number Diff line number Diff line
@@ -3511,6 +3511,7 @@ struct mips_cp0sel_name
  const char * const name;
};

#if 0
/* The mips16 registers.  */
static const unsigned int mips16_to_32_reg_map[] =
{
@@ -3518,7 +3519,7 @@ static const unsigned int mips16_to_32_reg_map[] =
};

#define mips16_reg_names(rn)	mips_gpr_names[mips16_to_32_reg_map[rn]]

#endif

static const char * const mips_gpr_names_numeric[32] =
{
@@ -3801,13 +3802,6 @@ static const char * const mips_hwr_names_mips3264r2[32] =
  "$24",  "$25",  "$26",  "$27",  "$28",  "$29",  "$30",  "$31"
};

static const char * const mips_msa_control_names_numeric[32] = {
  "$0",   "$1",   "$2",   "$3",   "$4",   "$5",   "$6",   "$7",
  "$8",   "$9",   "$10",  "$11",  "$12",  "$13",  "$14",  "$15",
  "$16",  "$17",  "$18",  "$19",  "$20",  "$21",  "$22",  "$23",
  "$24",  "$25",  "$26",  "$27",  "$28",  "$29",  "$30",  "$31"
};

static const char * const mips_msa_control_names_mips3264r2[32] = {
  "MSAIR", "MSACSR", "$2", "$3",  "$4",   "$5",   "$6",   "$7",
  "$8",   "$9",   "$10",  "$11",  "$12",  "$13",  "$14",  "$15",
+1 −1
Original line number Diff line number Diff line
@@ -3905,7 +3905,7 @@ int main(int argc, char **argv, char **envp)
#endif
#elif defined(TARGET_MIPS)
#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64)
        cpu_model = "20Kc";
        cpu_model = "5KEf";
#else
        cpu_model = "24Kf";
#endif
+114 −10
Original line number Diff line number Diff line
@@ -446,8 +446,8 @@ struct CPUMIPSState {
#define CP0C3_MT   2
#define CP0C3_SM   1
#define CP0C3_TL   0
    uint32_t CP0_Config4;
    uint32_t CP0_Config4_rw_bitmask;
    int32_t CP0_Config4;
    int32_t CP0_Config4_rw_bitmask;
#define CP0C4_M    31
#define CP0C4_IE   29
#define CP0C4_KScrExist 16
@@ -456,8 +456,8 @@ struct CPUMIPSState {
#define CP0C4_FTLBWays 4
#define CP0C4_FTLBSets 0
#define CP0C4_MMUSizeExt 0
    uint32_t CP0_Config5;
    uint32_t CP0_Config5_rw_bitmask;
    int32_t CP0_Config5;
    int32_t CP0_Config5_rw_bitmask;
#define CP0C5_M          31
#define CP0C5_K          30
#define CP0C5_CV         29
@@ -777,6 +777,18 @@ target_ulong exception_resume_pc (CPUMIPSState *env);
extern unsigned int ieee_rm[];
int ieee_ex_to_mips(int xcpt);

static inline void restore_rounding_mode(CPUMIPSState *env)
{
    set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3],
                            &env->active_fpu.fp_status);
}

static inline void restore_flush_mode(CPUMIPSState *env)
{
    set_flush_to_zero((env->active_fpu.fcr31 & (1 << 24)) != 0,
                      &env->active_fpu.fp_status);
}

static inline void cpu_get_tb_cpu_state(CPUMIPSState *env, target_ulong *pc,
                                        target_ulong *cs_base, int *flags)
{
@@ -831,16 +843,19 @@ static inline void compute_hflags(CPUMIPSState *env)
        env->hflags |= (env->CP0_Status >> CP0St_KSU) & MIPS_HFLAG_KSU;
    }
#if defined(TARGET_MIPS64)
    if (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_UM) ||
    if ((env->insn_flags & ISA_MIPS3) &&
        (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_UM) ||
         (env->CP0_Status & (1 << CP0St_PX)) ||
        (env->CP0_Status & (1 << CP0St_UX))) {
         (env->CP0_Status & (1 << CP0St_UX)))) {
        env->hflags |= MIPS_HFLAG_64;
    }

    if (((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
    if (!(env->insn_flags & ISA_MIPS3)) {
        env->hflags |= MIPS_HFLAG_AWRAP;
    } else if (((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
               !(env->CP0_Status & (1 << CP0St_UX))) {
        env->hflags |= MIPS_HFLAG_AWRAP;
    } else if (env->insn_flags & ISA_MIPS32R6) {
    } else if (env->insn_flags & ISA_MIPS64R6) {
        /* Address wrapping for Supervisor and Kernel is specified in R6 */
        if ((((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_SM) &&
             !(env->CP0_Status & (1 << CP0St_SX))) ||
@@ -904,4 +919,93 @@ static inline void compute_hflags(CPUMIPSState *env)
    }
}

#ifndef CONFIG_USER_ONLY
/* Called for updates to CP0_Status.  */
static inline void sync_c0_status(CPUMIPSState *env, CPUMIPSState *cpu, int tc)
{
    int32_t tcstatus, *tcst;
    uint32_t v = cpu->CP0_Status;
    uint32_t cu, mx, asid, ksu;
    uint32_t mask = ((1 << CP0TCSt_TCU3)
                       | (1 << CP0TCSt_TCU2)
                       | (1 << CP0TCSt_TCU1)
                       | (1 << CP0TCSt_TCU0)
                       | (1 << CP0TCSt_TMX)
                       | (3 << CP0TCSt_TKSU)
                       | (0xff << CP0TCSt_TASID));

    cu = (v >> CP0St_CU0) & 0xf;
    mx = (v >> CP0St_MX) & 0x1;
    ksu = (v >> CP0St_KSU) & 0x3;
    asid = env->CP0_EntryHi & 0xff;

    tcstatus = cu << CP0TCSt_TCU0;
    tcstatus |= mx << CP0TCSt_TMX;
    tcstatus |= ksu << CP0TCSt_TKSU;
    tcstatus |= asid;

    if (tc == cpu->current_tc) {
        tcst = &cpu->active_tc.CP0_TCStatus;
    } else {
        tcst = &cpu->tcs[tc].CP0_TCStatus;
    }

    *tcst &= ~mask;
    *tcst |= tcstatus;
    compute_hflags(cpu);
}

static inline void cpu_mips_store_status(CPUMIPSState *env, target_ulong val)
{
    uint32_t mask = env->CP0_Status_rw_bitmask;

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

        if (has_supervisor && extract32(val, CP0St_KSU, 2) == 0x3) {
            mask &= ~(3 << CP0St_KSU);
        }
        mask &= ~(((1 << CP0St_SR) | (1 << CP0St_NMI)) & val);
    }

    env->CP0_Status = (env->CP0_Status & ~mask) | (val & mask);
    if (env->CP0_Config3 & (1 << CP0C3_MT)) {
        sync_c0_status(env, env, env->current_tc);
    } else {
        compute_hflags(env);
    }
}

static inline void cpu_mips_store_cause(CPUMIPSState *env, target_ulong val)
{
    uint32_t mask = 0x00C00300;
    uint32_t old = env->CP0_Cause;
    int i;

    if (env->insn_flags & ISA_MIPS32R2) {
        mask |= 1 << CP0Ca_DC;
    }
    if (env->insn_flags & ISA_MIPS32R6) {
        mask &= ~((1 << CP0Ca_WP) & val);
    }

    env->CP0_Cause = (env->CP0_Cause & ~mask) | (val & mask);

    if ((old ^ env->CP0_Cause) & (1 << CP0Ca_DC)) {
        if (env->CP0_Cause & (1 << CP0Ca_DC)) {
            cpu_mips_stop_count(env);
        } else {
            cpu_mips_start_count(env);
        }
    }

    /* Set/reset software interrupts */
    for (i = 0 ; i < 2 ; i++) {
        if ((old ^ env->CP0_Cause) & (1 << (CP0Ca_IP + i))) {
            cpu_mips_soft_irq(env, i, env->CP0_Cause & (1 << (CP0Ca_IP + i)));
        }
    }
}
#endif

#endif /* !defined (__MIPS_CPU_H__) */
+29 −27
Original line number Diff line number Diff line
@@ -29,8 +29,13 @@ int mips_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
    if (n < 32) {
        return gdb_get_regl(mem_buf, env->active_tc.gpr[n]);
    }
    if (env->CP0_Config1 & (1 << CP0C1_FP)) {
        if (n >= 38 && n < 70) {
    if (env->CP0_Config1 & (1 << CP0C1_FP) && n >= 38 && n < 72) {
        switch (n) {
        case 70:
            return gdb_get_regl(mem_buf, (int32_t)env->active_fpu.fcr31);
        case 71:
            return gdb_get_regl(mem_buf, (int32_t)env->active_fpu.fcr0);
        default:
            if (env->CP0_Status & (1 << CP0St_FR)) {
                return gdb_get_regl(mem_buf,
                    env->active_fpu.fpr[n - 38].d);
@@ -39,12 +44,6 @@ int mips_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
                    env->active_fpu.fpr[n - 38].w[FP_ENDIAN_IDX]);
            }
        }
        switch (n) {
        case 70:
            return gdb_get_regl(mem_buf, (int32_t)env->active_fpu.fcr31);
        case 71:
            return gdb_get_regl(mem_buf, (int32_t)env->active_fpu.fcr0);
        }
    }
    switch (n) {
    case 32:
@@ -64,8 +63,10 @@ int mips_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
        return gdb_get_regl(mem_buf, 0); /* fp */
    case 89:
        return gdb_get_regl(mem_buf, (int32_t)env->CP0_PRid);
    default:
        if (n > 89) {
            return 0;
        }
    if (n >= 73 && n <= 88) {
        /* 16 embedded regs.  */
        return gdb_get_regl(mem_buf, 0);
    }
@@ -73,10 +74,6 @@ int mips_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
    return 0;
}

#define RESTORE_ROUNDING_MODE \
    set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3], \
                            &env->active_fpu.fp_status)

int mips_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
{
    MIPSCPU *cpu = MIPS_CPU(cs);
@@ -89,30 +86,33 @@ int mips_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
        env->active_tc.gpr[n] = tmp;
        return sizeof(target_ulong);
    }
    if (env->CP0_Config1 & (1 << CP0C1_FP)
            && n >= 38 && n < 73) {
        if (n < 70) {
            if (env->CP0_Status & (1 << CP0St_FR)) {
                env->active_fpu.fpr[n - 38].d = tmp;
            } else {
                env->active_fpu.fpr[n - 38].w[FP_ENDIAN_IDX] = tmp;
            }
        }
    if (env->CP0_Config1 & (1 << CP0C1_FP) && n >= 38 && n < 72) {
        switch (n) {
        case 70:
            env->active_fpu.fcr31 = tmp & 0xFF83FFFF;
            /* set rounding mode */
            RESTORE_ROUNDING_MODE;
            restore_rounding_mode(env);
            /* set flush-to-zero mode */
            restore_flush_mode(env);
            break;
        case 71:
            env->active_fpu.fcr0 = tmp;
            /* FIR is read-only.  Ignore writes.  */
            break;
        default:
            if (env->CP0_Status & (1 << CP0St_FR)) {
                env->active_fpu.fpr[n - 38].d = tmp;
            } else {
                env->active_fpu.fpr[n - 38].w[FP_ENDIAN_IDX] = tmp;
            }
            break;
        }
        return sizeof(target_ulong);
    }
    switch (n) {
    case 32:
        env->CP0_Status = tmp;
#ifndef CONFIG_USER_ONLY
        cpu_mips_store_status(env, tmp);
#endif
        break;
    case 33:
        env->active_tc.LO[0] = tmp;
@@ -124,7 +124,9 @@ int mips_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
        env->CP0_BadVAddr = tmp;
        break;
    case 36:
        env->CP0_Cause = tmp;
#ifndef CONFIG_USER_ONLY
        cpu_mips_store_cause(env, tmp);
#endif
        break;
    case 37:
        env->active_tc.PC = tmp & ~(target_ulong)1;
+13 −4
Original line number Diff line number Diff line
@@ -390,7 +390,6 @@ hwaddr cpu_mips_translate_address(CPUMIPSState *env, target_ulong address, int r
        return physical;
    }
}
#endif

static const char * const excp_names[EXCP_LAST + 1] = {
    [EXCP_RESET] = "reset",
@@ -431,6 +430,7 @@ static const char * const excp_names[EXCP_LAST + 1] = {
    [EXCP_MSADIS] = "MSA disabled",
    [EXCP_MSAFPE] = "MSA floating point",
};
#endif

target_ulong exception_resume_pc (CPUMIPSState *env)
{
@@ -529,7 +529,10 @@ void mips_cpu_do_interrupt(CPUState *cs)
        env->CP0_DEPC = exception_resume_pc(env);
        env->hflags &= ~MIPS_HFLAG_BMASK;
 enter_debug_mode:
        env->hflags |= MIPS_HFLAG_DM | MIPS_HFLAG_64 | MIPS_HFLAG_CP0;
        if (env->insn_flags & ISA_MIPS3) {
            env->hflags |= MIPS_HFLAG_64;
        }
        env->hflags |= MIPS_HFLAG_DM | MIPS_HFLAG_CP0;
        env->hflags &= ~(MIPS_HFLAG_KSU);
        /* EJTAG probe trap enable is not implemented... */
        if (!(env->CP0_Status & (1 << CP0St_EXL)))
@@ -550,7 +553,10 @@ void mips_cpu_do_interrupt(CPUState *cs)
        env->CP0_ErrorEPC = exception_resume_pc(env);
        env->hflags &= ~MIPS_HFLAG_BMASK;
        env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
        env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0;
        if (env->insn_flags & ISA_MIPS3) {
            env->hflags |= MIPS_HFLAG_64;
        }
        env->hflags |= MIPS_HFLAG_CP0;
        env->hflags &= ~(MIPS_HFLAG_KSU);
        if (!(env->CP0_Status & (1 << CP0St_EXL)))
            env->CP0_Cause &= ~(1U << CP0Ca_BD);
@@ -728,7 +734,10 @@ void mips_cpu_do_interrupt(CPUState *cs)
                env->CP0_Cause &= ~(1U << CP0Ca_BD);
            }
            env->CP0_Status |= (1 << CP0St_EXL);
            env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0;
            if (env->insn_flags & ISA_MIPS3) {
                env->hflags |= MIPS_HFLAG_64;
            }
            env->hflags |= MIPS_HFLAG_CP0;
            env->hflags &= ~(MIPS_HFLAG_KSU);
        }
        env->hflags &= ~MIPS_HFLAG_BMASK;
Loading