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: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
84afc4dd56
10
disas/mips.c
10
disas/mips.c
@ -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",
|
||||
|
@ -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
|
||||
|
@ -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) ||
|
||||
(env->CP0_Status & (1 << CP0St_PX)) ||
|
||||
(env->CP0_Status & (1 << CP0St_UX))) {
|
||||
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->hflags |= MIPS_HFLAG_64;
|
||||
}
|
||||
|
||||
if (((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
|
||||
!(env->CP0_Status & (1 << CP0St_UX))) {
|
||||
if (!(env->insn_flags & ISA_MIPS3)) {
|
||||
env->hflags |= MIPS_HFLAG_AWRAP;
|
||||
} else if (env->insn_flags & ISA_MIPS32R6) {
|
||||
} 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_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,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);
|
||||
}
|
||||
if (n >= 73 && n <= 88) {
|
||||
default:
|
||||
if (n > 89) {
|
||||
return 0;
|
||||
}
|
||||
/* 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_Config1 & (1 << CP0C1_FP) && n >= 38 && n < 72) {
|
||||
switch (n) {
|
||||
case 70:
|
||||
env->active_fpu.fcr31 = tmp & 0xFF83FFFF;
|
||||
/* set rounding mode */
|
||||
restore_rounding_mode(env);
|
||||
/* set flush-to-zero mode */
|
||||
restore_flush_mode(env);
|
||||
break;
|
||||
case 71:
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
switch (n) {
|
||||
case 70:
|
||||
env->active_fpu.fcr31 = tmp & 0xFF83FFFF;
|
||||
/* set rounding mode */
|
||||
RESTORE_ROUNDING_MODE;
|
||||
break;
|
||||
case 71:
|
||||
env->active_fpu.fcr0 = 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;
|
||||
|
@ -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;
|
||||
|
@ -137,6 +137,7 @@ DEF_HELPER_2(mtc0_ebase, void, env, tl)
|
||||
DEF_HELPER_2(mttc0_ebase, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_config0, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_config2, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_config3, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_config4, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_config5, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_lladdr, void, env, tl)
|
||||
|
@ -1782,15 +1782,14 @@ static inline int32 float64_to_q32(float64 a STATUS_PARAM)
|
||||
|
||||
#define MSA_FLOAT_COND(DEST, OP, ARG1, ARG2, BITS, QUIET) \
|
||||
do { \
|
||||
float_status *status = &env->active_tc.msa_fp_status; \
|
||||
int c; \
|
||||
int64_t cond; \
|
||||
set_float_exception_flags(0, &env->active_tc.msa_fp_status); \
|
||||
set_float_exception_flags(0, status); \
|
||||
if (!QUIET) { \
|
||||
cond = float ## BITS ## _ ## OP(ARG1, ARG2, \
|
||||
&env->active_tc.msa_fp_status); \
|
||||
cond = float ## BITS ## _ ## OP(ARG1, ARG2, status); \
|
||||
} else { \
|
||||
cond = float ## BITS ## _ ## OP ## _quiet(ARG1, ARG2, \
|
||||
&env->active_tc.msa_fp_status); \
|
||||
cond = float ## BITS ## _ ## OP ## _quiet(ARG1, ARG2, status); \
|
||||
} \
|
||||
DEST = cond ? M_MAX_UINT(BITS) : 0; \
|
||||
c = update_msacsr(env, CLEAR_IS_INEXACT, 0); \
|
||||
@ -2375,11 +2374,11 @@ void helper_msa_fsne_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
|
||||
|
||||
#define MSA_FLOAT_BINOP(DEST, OP, ARG1, ARG2, BITS) \
|
||||
do { \
|
||||
float_status *status = &env->active_tc.msa_fp_status; \
|
||||
int c; \
|
||||
\
|
||||
set_float_exception_flags(0, &env->active_tc.msa_fp_status); \
|
||||
DEST = float ## BITS ## _ ## OP(ARG1, ARG2, \
|
||||
&env->active_tc.msa_fp_status); \
|
||||
set_float_exception_flags(0, status); \
|
||||
DEST = float ## BITS ## _ ## OP(ARG1, ARG2, status); \
|
||||
c = update_msacsr(env, 0, IS_DENORMAL(DEST, BITS)); \
|
||||
\
|
||||
if (get_enabled_exceptions(env, c)) { \
|
||||
@ -2511,11 +2510,11 @@ void helper_msa_fdiv_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
|
||||
|
||||
#define MSA_FLOAT_MULADD(DEST, ARG1, ARG2, ARG3, NEGATE, BITS) \
|
||||
do { \
|
||||
float_status *status = &env->active_tc.msa_fp_status; \
|
||||
int c; \
|
||||
\
|
||||
set_float_exception_flags(0, &env->active_tc.msa_fp_status); \
|
||||
DEST = float ## BITS ## _muladd(ARG2, ARG3, ARG1, NEGATE, \
|
||||
&env->active_tc.msa_fp_status); \
|
||||
set_float_exception_flags(0, status); \
|
||||
DEST = float ## BITS ## _muladd(ARG2, ARG3, ARG1, NEGATE, status); \
|
||||
c = update_msacsr(env, 0, IS_DENORMAL(DEST, BITS)); \
|
||||
\
|
||||
if (get_enabled_exceptions(env, c)) { \
|
||||
@ -2630,10 +2629,11 @@ void helper_msa_fexp2_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
|
||||
|
||||
#define MSA_FLOAT_UNOP(DEST, OP, ARG, BITS) \
|
||||
do { \
|
||||
float_status *status = &env->active_tc.msa_fp_status; \
|
||||
int c; \
|
||||
\
|
||||
set_float_exception_flags(0, &env->active_tc.msa_fp_status); \
|
||||
DEST = float ## BITS ## _ ## OP(ARG, &env->active_tc.msa_fp_status);\
|
||||
set_float_exception_flags(0, status); \
|
||||
DEST = float ## BITS ## _ ## OP(ARG, status); \
|
||||
c = update_msacsr(env, 0, IS_DENORMAL(DEST, BITS)); \
|
||||
\
|
||||
if (get_enabled_exceptions(env, c)) { \
|
||||
@ -2678,10 +2678,11 @@ void helper_msa_fexdo_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
|
||||
|
||||
#define MSA_FLOAT_UNOP_XD(DEST, OP, ARG, BITS, XBITS) \
|
||||
do { \
|
||||
float_status *status = &env->active_tc.msa_fp_status; \
|
||||
int c; \
|
||||
\
|
||||
set_float_exception_flags(0, &env->active_tc.msa_fp_status); \
|
||||
DEST = float ## BITS ## _ ## OP(ARG, &env->active_tc.msa_fp_status);\
|
||||
set_float_exception_flags(0, status); \
|
||||
DEST = float ## BITS ## _ ## OP(ARG, status); \
|
||||
c = update_msacsr(env, CLEAR_FS_UNDERFLOW, 0); \
|
||||
\
|
||||
if (get_enabled_exceptions(env, c)) { \
|
||||
@ -2728,11 +2729,11 @@ void helper_msa_ftq_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
|
||||
|
||||
#define MSA_FLOAT_MAXOP(DEST, OP, ARG1, ARG2, BITS) \
|
||||
do { \
|
||||
float_status *status = &env->active_tc.msa_fp_status; \
|
||||
int c; \
|
||||
\
|
||||
set_float_exception_flags(0, &env->active_tc.msa_fp_status); \
|
||||
DEST = float ## BITS ## _ ## OP(ARG1, ARG2, \
|
||||
&env->active_tc.msa_fp_status); \
|
||||
set_float_exception_flags(0, status); \
|
||||
DEST = float ## BITS ## _ ## OP(ARG1, ARG2, status); \
|
||||
c = update_msacsr(env, 0, 0); \
|
||||
\
|
||||
if (get_enabled_exceptions(env, c)) { \
|
||||
@ -2924,10 +2925,11 @@ void helper_msa_fclass_df(CPUMIPSState *env, uint32_t df,
|
||||
|
||||
#define MSA_FLOAT_UNOP0(DEST, OP, ARG, BITS) \
|
||||
do { \
|
||||
float_status *status = &env->active_tc.msa_fp_status; \
|
||||
int c; \
|
||||
\
|
||||
set_float_exception_flags(0, &env->active_tc.msa_fp_status); \
|
||||
DEST = float ## BITS ## _ ## OP(ARG, &env->active_tc.msa_fp_status);\
|
||||
set_float_exception_flags(0, status); \
|
||||
DEST = float ## BITS ## _ ## OP(ARG, status); \
|
||||
c = update_msacsr(env, CLEAR_FS_UNDERFLOW, 0); \
|
||||
\
|
||||
if (get_enabled_exceptions(env, c)) { \
|
||||
@ -3029,11 +3031,11 @@ void helper_msa_fsqrt_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
|
||||
|
||||
#define MSA_FLOAT_RECIPROCAL(DEST, ARG, BITS) \
|
||||
do { \
|
||||
float_status *status = &env->active_tc.msa_fp_status; \
|
||||
int c; \
|
||||
\
|
||||
set_float_exception_flags(0, &env->active_tc.msa_fp_status); \
|
||||
DEST = float ## BITS ## _ ## div(FLOAT_ONE ## BITS, ARG, \
|
||||
&env->active_tc.msa_fp_status); \
|
||||
set_float_exception_flags(0, status); \
|
||||
DEST = float ## BITS ## _ ## div(FLOAT_ONE ## BITS, ARG, status); \
|
||||
c = update_msacsr(env, float ## BITS ## _is_infinity(ARG) || \
|
||||
float ## BITS ## _is_quiet_nan(DEST) ? \
|
||||
0 : RECIPROCAL_INEXACT, \
|
||||
@ -3138,23 +3140,20 @@ void helper_msa_frint_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
|
||||
|
||||
#define MSA_FLOAT_LOGB(DEST, ARG, BITS) \
|
||||
do { \
|
||||
float_status *status = &env->active_tc.msa_fp_status; \
|
||||
int c; \
|
||||
\
|
||||
set_float_exception_flags(0, &env->active_tc.msa_fp_status); \
|
||||
set_float_rounding_mode(float_round_down, \
|
||||
&env->active_tc.msa_fp_status); \
|
||||
DEST = float ## BITS ## _ ## log2(ARG, \
|
||||
&env->active_tc.msa_fp_status); \
|
||||
DEST = float ## BITS ## _ ## round_to_int(DEST, \
|
||||
&env->active_tc.msa_fp_status); \
|
||||
set_float_exception_flags(0, status); \
|
||||
set_float_rounding_mode(float_round_down, status); \
|
||||
DEST = float ## BITS ## _ ## log2(ARG, status); \
|
||||
DEST = float ## BITS ## _ ## round_to_int(DEST, status); \
|
||||
set_float_rounding_mode(ieee_rm[(env->active_tc.msacsr & \
|
||||
MSACSR_RM_MASK) >> MSACSR_RM], \
|
||||
&env->active_tc.msa_fp_status); \
|
||||
status); \
|
||||
\
|
||||
set_float_exception_flags( \
|
||||
get_float_exception_flags(&env->active_tc.msa_fp_status) \
|
||||
& (~float_flag_inexact), \
|
||||
&env->active_tc.msa_fp_status); \
|
||||
set_float_exception_flags(get_float_exception_flags(status) & \
|
||||
(~float_flag_inexact), \
|
||||
status); \
|
||||
\
|
||||
c = update_msacsr(env, 0, IS_DENORMAL(DEST, BITS)); \
|
||||
\
|
||||
|
@ -625,40 +625,9 @@ static CPUMIPSState *mips_cpu_map_tc(CPUMIPSState *env, int *tc)
|
||||
|
||||
These helper call synchronizes the regs for a given cpu. */
|
||||
|
||||
/* Called for updates to CP0_Status. */
|
||||
static 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);
|
||||
}
|
||||
/* Called for updates to CP0_Status. Defined in "cpu.h" for gdbstub.c. */
|
||||
/* static inline void sync_c0_status(CPUMIPSState *env, CPUMIPSState *cpu,
|
||||
int tc); */
|
||||
|
||||
/* Called for updates to CP0_TCStatus. */
|
||||
static void sync_c0_tcstatus(CPUMIPSState *cpu, int tc,
|
||||
@ -1420,23 +1389,10 @@ void helper_mtc0_status(CPUMIPSState *env, target_ulong arg1)
|
||||
{
|
||||
MIPSCPU *cpu = mips_env_get_cpu(env);
|
||||
uint32_t val, old;
|
||||
uint32_t mask = env->CP0_Status_rw_bitmask;
|
||||
|
||||
if (env->insn_flags & ISA_MIPS32R6) {
|
||||
if (extract32(env->CP0_Status, CP0St_KSU, 2) == 0x3) {
|
||||
mask &= ~(3 << CP0St_KSU);
|
||||
}
|
||||
mask &= ~(0x00180000 & arg1);
|
||||
}
|
||||
|
||||
val = arg1 & mask;
|
||||
old = env->CP0_Status;
|
||||
env->CP0_Status = (env->CP0_Status & ~mask) | val;
|
||||
if (env->CP0_Config3 & (1 << CP0C3_MT)) {
|
||||
sync_c0_status(env, env, env->current_tc);
|
||||
} else {
|
||||
compute_hflags(env);
|
||||
}
|
||||
cpu_mips_store_status(env, arg1);
|
||||
val = env->CP0_Status;
|
||||
|
||||
if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
|
||||
qemu_log("Status %08x (%08x) => %08x (%08x) Cause %08x",
|
||||
@ -1457,9 +1413,10 @@ void helper_mtc0_status(CPUMIPSState *env, target_ulong arg1)
|
||||
void helper_mttc0_status(CPUMIPSState *env, target_ulong arg1)
|
||||
{
|
||||
int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
|
||||
uint32_t mask = env->CP0_Status_rw_bitmask & ~0xf1000018;
|
||||
CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
|
||||
|
||||
other->CP0_Status = arg1 & ~0xf1000018;
|
||||
other->CP0_Status = (other->CP0_Status & ~mask) | (arg1 & mask);
|
||||
sync_c0_status(env, other, other_tc);
|
||||
}
|
||||
|
||||
@ -1475,40 +1432,9 @@ void helper_mtc0_srsctl(CPUMIPSState *env, target_ulong arg1)
|
||||
env->CP0_SRSCtl = (env->CP0_SRSCtl & ~mask) | (arg1 & mask);
|
||||
}
|
||||
|
||||
static void mtc0_cause(CPUMIPSState *cpu, target_ulong arg1)
|
||||
{
|
||||
uint32_t mask = 0x00C00300;
|
||||
uint32_t old = cpu->CP0_Cause;
|
||||
int i;
|
||||
|
||||
if (cpu->insn_flags & ISA_MIPS32R2) {
|
||||
mask |= 1 << CP0Ca_DC;
|
||||
}
|
||||
if (cpu->insn_flags & ISA_MIPS32R6) {
|
||||
mask &= ~((1 << CP0Ca_WP) & arg1);
|
||||
}
|
||||
|
||||
cpu->CP0_Cause = (cpu->CP0_Cause & ~mask) | (arg1 & mask);
|
||||
|
||||
if ((old ^ cpu->CP0_Cause) & (1 << CP0Ca_DC)) {
|
||||
if (cpu->CP0_Cause & (1 << CP0Ca_DC)) {
|
||||
cpu_mips_stop_count(cpu);
|
||||
} else {
|
||||
cpu_mips_start_count(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set/reset software interrupts */
|
||||
for (i = 0 ; i < 2 ; i++) {
|
||||
if ((old ^ cpu->CP0_Cause) & (1 << (CP0Ca_IP + i))) {
|
||||
cpu_mips_soft_irq(cpu, i, cpu->CP0_Cause & (1 << (CP0Ca_IP + i)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void helper_mtc0_cause(CPUMIPSState *env, target_ulong arg1)
|
||||
{
|
||||
mtc0_cause(env, arg1);
|
||||
cpu_mips_store_cause(env, arg1);
|
||||
}
|
||||
|
||||
void helper_mttc0_cause(CPUMIPSState *env, target_ulong arg1)
|
||||
@ -1516,7 +1442,7 @@ void helper_mttc0_cause(CPUMIPSState *env, target_ulong arg1)
|
||||
int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
|
||||
CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
|
||||
|
||||
mtc0_cause(other, arg1);
|
||||
cpu_mips_store_cause(other, arg1);
|
||||
}
|
||||
|
||||
target_ulong helper_mftc0_epc(CPUMIPSState *env)
|
||||
@ -1578,6 +1504,14 @@ void helper_mtc0_config2(CPUMIPSState *env, target_ulong arg1)
|
||||
env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
|
||||
}
|
||||
|
||||
void helper_mtc0_config3(CPUMIPSState *env, target_ulong arg1)
|
||||
{
|
||||
if (env->insn_flags & ASE_MICROMIPS) {
|
||||
env->CP0_Config3 = (env->CP0_Config3 & ~(1 << CP0C3_ISA_ON_EXC)) |
|
||||
(arg1 & (1 << CP0C3_ISA_ON_EXC));
|
||||
}
|
||||
}
|
||||
|
||||
void helper_mtc0_config4(CPUMIPSState *env, target_ulong arg1)
|
||||
{
|
||||
env->CP0_Config4 = (env->CP0_Config4 & (~env->CP0_Config4_rw_bitmask)) |
|
||||
@ -2346,18 +2280,6 @@ unsigned int ieee_rm[] = {
|
||||
float_round_down
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
target_ulong helper_cfc1(CPUMIPSState *env, uint32_t reg)
|
||||
{
|
||||
target_ulong arg1 = 0;
|
||||
@ -2659,11 +2581,11 @@ uint32_t helper_float_cvtw_s(CPUMIPSState *env, uint32_t fst0)
|
||||
uint32_t wt2;
|
||||
|
||||
wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
|
||||
update_fcr31(env, GETPC());
|
||||
if (get_float_exception_flags(&env->active_fpu.fp_status)
|
||||
& (float_flag_invalid | float_flag_overflow)) {
|
||||
wt2 = FP_TO_INT32_OVERFLOW;
|
||||
}
|
||||
update_fcr31(env, GETPC());
|
||||
return wt2;
|
||||
}
|
||||
|
||||
@ -2935,110 +2857,6 @@ FLOAT_UNOP(abs)
|
||||
FLOAT_UNOP(chs)
|
||||
#undef FLOAT_UNOP
|
||||
|
||||
#define FLOAT_FMADDSUB(name, bits, muladd_arg) \
|
||||
uint ## bits ## _t helper_float_ ## name (CPUMIPSState *env, \
|
||||
uint ## bits ## _t fs, \
|
||||
uint ## bits ## _t ft, \
|
||||
uint ## bits ## _t fd) \
|
||||
{ \
|
||||
uint ## bits ## _t fdret; \
|
||||
\
|
||||
fdret = float ## bits ## _muladd(fs, ft, fd, muladd_arg, \
|
||||
&env->active_fpu.fp_status); \
|
||||
update_fcr31(env, GETPC()); \
|
||||
return fdret; \
|
||||
}
|
||||
|
||||
FLOAT_FMADDSUB(maddf_s, 32, 0)
|
||||
FLOAT_FMADDSUB(maddf_d, 64, 0)
|
||||
FLOAT_FMADDSUB(msubf_s, 32, float_muladd_negate_product)
|
||||
FLOAT_FMADDSUB(msubf_d, 64, float_muladd_negate_product)
|
||||
#undef FLOAT_FMADDSUB
|
||||
|
||||
#define FLOAT_MINMAX(name, bits, minmaxfunc) \
|
||||
uint ## bits ## _t helper_float_ ## name (CPUMIPSState *env, \
|
||||
uint ## bits ## _t fs, \
|
||||
uint ## bits ## _t ft) \
|
||||
{ \
|
||||
uint ## bits ## _t fdret; \
|
||||
\
|
||||
fdret = float ## bits ## _ ## minmaxfunc(fs, ft, \
|
||||
&env->active_fpu.fp_status); \
|
||||
update_fcr31(env, GETPC()); \
|
||||
return fdret; \
|
||||
}
|
||||
|
||||
FLOAT_MINMAX(max_s, 32, maxnum)
|
||||
FLOAT_MINMAX(max_d, 64, maxnum)
|
||||
FLOAT_MINMAX(maxa_s, 32, maxnummag)
|
||||
FLOAT_MINMAX(maxa_d, 64, maxnummag)
|
||||
|
||||
FLOAT_MINMAX(min_s, 32, minnum)
|
||||
FLOAT_MINMAX(min_d, 64, minnum)
|
||||
FLOAT_MINMAX(mina_s, 32, minnummag)
|
||||
FLOAT_MINMAX(mina_d, 64, minnummag)
|
||||
#undef FLOAT_MINMAX
|
||||
|
||||
#define FLOAT_RINT(name, bits) \
|
||||
uint ## bits ## _t helper_float_ ## name (CPUMIPSState *env, \
|
||||
uint ## bits ## _t fs) \
|
||||
{ \
|
||||
uint ## bits ## _t fdret; \
|
||||
\
|
||||
fdret = float ## bits ## _round_to_int(fs, &env->active_fpu.fp_status); \
|
||||
update_fcr31(env, GETPC()); \
|
||||
return fdret; \
|
||||
}
|
||||
|
||||
FLOAT_RINT(rint_s, 32)
|
||||
FLOAT_RINT(rint_d, 64)
|
||||
#undef FLOAT_RINT
|
||||
|
||||
#define FLOAT_CLASS_SIGNALING_NAN 0x001
|
||||
#define FLOAT_CLASS_QUIET_NAN 0x002
|
||||
#define FLOAT_CLASS_NEGATIVE_INFINITY 0x004
|
||||
#define FLOAT_CLASS_NEGATIVE_NORMAL 0x008
|
||||
#define FLOAT_CLASS_NEGATIVE_SUBNORMAL 0x010
|
||||
#define FLOAT_CLASS_NEGATIVE_ZERO 0x020
|
||||
#define FLOAT_CLASS_POSITIVE_INFINITY 0x040
|
||||
#define FLOAT_CLASS_POSITIVE_NORMAL 0x080
|
||||
#define FLOAT_CLASS_POSITIVE_SUBNORMAL 0x100
|
||||
#define FLOAT_CLASS_POSITIVE_ZERO 0x200
|
||||
|
||||
#define FLOAT_CLASS(name, bits) \
|
||||
uint ## bits ## _t helper_float_ ## name (uint ## bits ## _t arg) \
|
||||
{ \
|
||||
if (float ## bits ## _is_signaling_nan(arg)) { \
|
||||
return FLOAT_CLASS_SIGNALING_NAN; \
|
||||
} else if (float ## bits ## _is_quiet_nan(arg)) { \
|
||||
return FLOAT_CLASS_QUIET_NAN; \
|
||||
} else if (float ## bits ## _is_neg(arg)) { \
|
||||
if (float ## bits ## _is_infinity(arg)) { \
|
||||
return FLOAT_CLASS_NEGATIVE_INFINITY; \
|
||||
} else if (float ## bits ## _is_zero(arg)) { \
|
||||
return FLOAT_CLASS_NEGATIVE_ZERO; \
|
||||
} else if (float ## bits ## _is_zero_or_denormal(arg)) { \
|
||||
return FLOAT_CLASS_NEGATIVE_SUBNORMAL; \
|
||||
} else { \
|
||||
return FLOAT_CLASS_NEGATIVE_NORMAL; \
|
||||
} \
|
||||
} else { \
|
||||
if (float ## bits ## _is_infinity(arg)) { \
|
||||
return FLOAT_CLASS_POSITIVE_INFINITY; \
|
||||
} else if (float ## bits ## _is_zero(arg)) { \
|
||||
return FLOAT_CLASS_POSITIVE_ZERO; \
|
||||
} else if (float ## bits ## _is_zero_or_denormal(arg)) { \
|
||||
return FLOAT_CLASS_POSITIVE_SUBNORMAL; \
|
||||
} else { \
|
||||
return FLOAT_CLASS_POSITIVE_NORMAL; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
FLOAT_CLASS(class_s, 32)
|
||||
FLOAT_CLASS(class_d, 64)
|
||||
#undef FLOAT_CLASS
|
||||
|
||||
/* MIPS specific unary operations */
|
||||
uint64_t helper_float_recip_d(CPUMIPSState *env, uint64_t fdt0)
|
||||
{
|
||||
@ -3140,7 +2958,65 @@ uint64_t helper_float_rsqrt1_ps(CPUMIPSState *env, uint64_t fdt0)
|
||||
return ((uint64_t)fsth2 << 32) | fst2;
|
||||
}
|
||||
|
||||
#define FLOAT_OP(name, p) void helper_float_##name##_##p(CPUMIPSState *env)
|
||||
#define FLOAT_RINT(name, bits) \
|
||||
uint ## bits ## _t helper_float_ ## name (CPUMIPSState *env, \
|
||||
uint ## bits ## _t fs) \
|
||||
{ \
|
||||
uint ## bits ## _t fdret; \
|
||||
\
|
||||
fdret = float ## bits ## _round_to_int(fs, &env->active_fpu.fp_status); \
|
||||
update_fcr31(env, GETPC()); \
|
||||
return fdret; \
|
||||
}
|
||||
|
||||
FLOAT_RINT(rint_s, 32)
|
||||
FLOAT_RINT(rint_d, 64)
|
||||
#undef FLOAT_RINT
|
||||
|
||||
#define FLOAT_CLASS_SIGNALING_NAN 0x001
|
||||
#define FLOAT_CLASS_QUIET_NAN 0x002
|
||||
#define FLOAT_CLASS_NEGATIVE_INFINITY 0x004
|
||||
#define FLOAT_CLASS_NEGATIVE_NORMAL 0x008
|
||||
#define FLOAT_CLASS_NEGATIVE_SUBNORMAL 0x010
|
||||
#define FLOAT_CLASS_NEGATIVE_ZERO 0x020
|
||||
#define FLOAT_CLASS_POSITIVE_INFINITY 0x040
|
||||
#define FLOAT_CLASS_POSITIVE_NORMAL 0x080
|
||||
#define FLOAT_CLASS_POSITIVE_SUBNORMAL 0x100
|
||||
#define FLOAT_CLASS_POSITIVE_ZERO 0x200
|
||||
|
||||
#define FLOAT_CLASS(name, bits) \
|
||||
uint ## bits ## _t helper_float_ ## name (uint ## bits ## _t arg) \
|
||||
{ \
|
||||
if (float ## bits ## _is_signaling_nan(arg)) { \
|
||||
return FLOAT_CLASS_SIGNALING_NAN; \
|
||||
} else if (float ## bits ## _is_quiet_nan(arg)) { \
|
||||
return FLOAT_CLASS_QUIET_NAN; \
|
||||
} else if (float ## bits ## _is_neg(arg)) { \
|
||||
if (float ## bits ## _is_infinity(arg)) { \
|
||||
return FLOAT_CLASS_NEGATIVE_INFINITY; \
|
||||
} else if (float ## bits ## _is_zero(arg)) { \
|
||||
return FLOAT_CLASS_NEGATIVE_ZERO; \
|
||||
} else if (float ## bits ## _is_zero_or_denormal(arg)) { \
|
||||
return FLOAT_CLASS_NEGATIVE_SUBNORMAL; \
|
||||
} else { \
|
||||
return FLOAT_CLASS_NEGATIVE_NORMAL; \
|
||||
} \
|
||||
} else { \
|
||||
if (float ## bits ## _is_infinity(arg)) { \
|
||||
return FLOAT_CLASS_POSITIVE_INFINITY; \
|
||||
} else if (float ## bits ## _is_zero(arg)) { \
|
||||
return FLOAT_CLASS_POSITIVE_ZERO; \
|
||||
} else if (float ## bits ## _is_zero_or_denormal(arg)) { \
|
||||
return FLOAT_CLASS_POSITIVE_SUBNORMAL; \
|
||||
} else { \
|
||||
return FLOAT_CLASS_POSITIVE_NORMAL; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
FLOAT_CLASS(class_s, 32)
|
||||
FLOAT_CLASS(class_d, 64)
|
||||
#undef FLOAT_CLASS
|
||||
|
||||
/* binary operations */
|
||||
#define FLOAT_BINOP(name) \
|
||||
@ -3187,61 +3063,6 @@ FLOAT_BINOP(mul)
|
||||
FLOAT_BINOP(div)
|
||||
#undef FLOAT_BINOP
|
||||
|
||||
#define UNFUSED_FMA(prefix, a, b, c, flags) \
|
||||
{ \
|
||||
a = prefix##_mul(a, b, &env->active_fpu.fp_status); \
|
||||
if ((flags) & float_muladd_negate_c) { \
|
||||
a = prefix##_sub(a, c, &env->active_fpu.fp_status); \
|
||||
} else { \
|
||||
a = prefix##_add(a, c, &env->active_fpu.fp_status); \
|
||||
} \
|
||||
if ((flags) & float_muladd_negate_result) { \
|
||||
a = prefix##_chs(a); \
|
||||
} \
|
||||
}
|
||||
|
||||
/* FMA based operations */
|
||||
#define FLOAT_FMA(name, type) \
|
||||
uint64_t helper_float_ ## name ## _d(CPUMIPSState *env, \
|
||||
uint64_t fdt0, uint64_t fdt1, \
|
||||
uint64_t fdt2) \
|
||||
{ \
|
||||
UNFUSED_FMA(float64, fdt0, fdt1, fdt2, type); \
|
||||
update_fcr31(env, GETPC()); \
|
||||
return fdt0; \
|
||||
} \
|
||||
\
|
||||
uint32_t helper_float_ ## name ## _s(CPUMIPSState *env, \
|
||||
uint32_t fst0, uint32_t fst1, \
|
||||
uint32_t fst2) \
|
||||
{ \
|
||||
UNFUSED_FMA(float32, fst0, fst1, fst2, type); \
|
||||
update_fcr31(env, GETPC()); \
|
||||
return fst0; \
|
||||
} \
|
||||
\
|
||||
uint64_t helper_float_ ## name ## _ps(CPUMIPSState *env, \
|
||||
uint64_t fdt0, uint64_t fdt1, \
|
||||
uint64_t fdt2) \
|
||||
{ \
|
||||
uint32_t fst0 = fdt0 & 0XFFFFFFFF; \
|
||||
uint32_t fsth0 = fdt0 >> 32; \
|
||||
uint32_t fst1 = fdt1 & 0XFFFFFFFF; \
|
||||
uint32_t fsth1 = fdt1 >> 32; \
|
||||
uint32_t fst2 = fdt2 & 0XFFFFFFFF; \
|
||||
uint32_t fsth2 = fdt2 >> 32; \
|
||||
\
|
||||
UNFUSED_FMA(float32, fst0, fst1, fst2, type); \
|
||||
UNFUSED_FMA(float32, fsth0, fsth1, fsth2, type); \
|
||||
update_fcr31(env, GETPC()); \
|
||||
return ((uint64_t)fsth0 << 32) | fst0; \
|
||||
}
|
||||
FLOAT_FMA(madd, 0)
|
||||
FLOAT_FMA(msub, float_muladd_negate_c)
|
||||
FLOAT_FMA(nmadd, float_muladd_negate_result)
|
||||
FLOAT_FMA(nmsub, float_muladd_negate_result | float_muladd_negate_c)
|
||||
#undef FLOAT_FMA
|
||||
|
||||
/* MIPS specific binary operations */
|
||||
uint64_t helper_float_recip2_d(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2)
|
||||
{
|
||||
@ -3339,6 +3160,106 @@ uint64_t helper_float_mulr_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt1)
|
||||
return ((uint64_t)fsth2 << 32) | fst2;
|
||||
}
|
||||
|
||||
#define FLOAT_MINMAX(name, bits, minmaxfunc) \
|
||||
uint ## bits ## _t helper_float_ ## name (CPUMIPSState *env, \
|
||||
uint ## bits ## _t fs, \
|
||||
uint ## bits ## _t ft) \
|
||||
{ \
|
||||
uint ## bits ## _t fdret; \
|
||||
\
|
||||
fdret = float ## bits ## _ ## minmaxfunc(fs, ft, \
|
||||
&env->active_fpu.fp_status); \
|
||||
update_fcr31(env, GETPC()); \
|
||||
return fdret; \
|
||||
}
|
||||
|
||||
FLOAT_MINMAX(max_s, 32, maxnum)
|
||||
FLOAT_MINMAX(max_d, 64, maxnum)
|
||||
FLOAT_MINMAX(maxa_s, 32, maxnummag)
|
||||
FLOAT_MINMAX(maxa_d, 64, maxnummag)
|
||||
|
||||
FLOAT_MINMAX(min_s, 32, minnum)
|
||||
FLOAT_MINMAX(min_d, 64, minnum)
|
||||
FLOAT_MINMAX(mina_s, 32, minnummag)
|
||||
FLOAT_MINMAX(mina_d, 64, minnummag)
|
||||
#undef FLOAT_MINMAX
|
||||
|
||||
/* ternary operations */
|
||||
#define UNFUSED_FMA(prefix, a, b, c, flags) \
|
||||
{ \
|
||||
a = prefix##_mul(a, b, &env->active_fpu.fp_status); \
|
||||
if ((flags) & float_muladd_negate_c) { \
|
||||
a = prefix##_sub(a, c, &env->active_fpu.fp_status); \
|
||||
} else { \
|
||||
a = prefix##_add(a, c, &env->active_fpu.fp_status); \
|
||||
} \
|
||||
if ((flags) & float_muladd_negate_result) { \
|
||||
a = prefix##_chs(a); \
|
||||
} \
|
||||
}
|
||||
|
||||
/* FMA based operations */
|
||||
#define FLOAT_FMA(name, type) \
|
||||
uint64_t helper_float_ ## name ## _d(CPUMIPSState *env, \
|
||||
uint64_t fdt0, uint64_t fdt1, \
|
||||
uint64_t fdt2) \
|
||||
{ \
|
||||
UNFUSED_FMA(float64, fdt0, fdt1, fdt2, type); \
|
||||
update_fcr31(env, GETPC()); \
|
||||
return fdt0; \
|
||||
} \
|
||||
\
|
||||
uint32_t helper_float_ ## name ## _s(CPUMIPSState *env, \
|
||||
uint32_t fst0, uint32_t fst1, \
|
||||
uint32_t fst2) \
|
||||
{ \
|
||||
UNFUSED_FMA(float32, fst0, fst1, fst2, type); \
|
||||
update_fcr31(env, GETPC()); \
|
||||
return fst0; \
|
||||
} \
|
||||
\
|
||||
uint64_t helper_float_ ## name ## _ps(CPUMIPSState *env, \
|
||||
uint64_t fdt0, uint64_t fdt1, \
|
||||
uint64_t fdt2) \
|
||||
{ \
|
||||
uint32_t fst0 = fdt0 & 0XFFFFFFFF; \
|
||||
uint32_t fsth0 = fdt0 >> 32; \
|
||||
uint32_t fst1 = fdt1 & 0XFFFFFFFF; \
|
||||
uint32_t fsth1 = fdt1 >> 32; \
|
||||
uint32_t fst2 = fdt2 & 0XFFFFFFFF; \
|
||||
uint32_t fsth2 = fdt2 >> 32; \
|
||||
\
|
||||
UNFUSED_FMA(float32, fst0, fst1, fst2, type); \
|
||||
UNFUSED_FMA(float32, fsth0, fsth1, fsth2, type); \
|
||||
update_fcr31(env, GETPC()); \
|
||||
return ((uint64_t)fsth0 << 32) | fst0; \
|
||||
}
|
||||
FLOAT_FMA(madd, 0)
|
||||
FLOAT_FMA(msub, float_muladd_negate_c)
|
||||
FLOAT_FMA(nmadd, float_muladd_negate_result)
|
||||
FLOAT_FMA(nmsub, float_muladd_negate_result | float_muladd_negate_c)
|
||||
#undef FLOAT_FMA
|
||||
|
||||
#define FLOAT_FMADDSUB(name, bits, muladd_arg) \
|
||||
uint ## bits ## _t helper_float_ ## name (CPUMIPSState *env, \
|
||||
uint ## bits ## _t fs, \
|
||||
uint ## bits ## _t ft, \
|
||||
uint ## bits ## _t fd) \
|
||||
{ \
|
||||
uint ## bits ## _t fdret; \
|
||||
\
|
||||
fdret = float ## bits ## _muladd(fs, ft, fd, muladd_arg, \
|
||||
&env->active_fpu.fp_status); \
|
||||
update_fcr31(env, GETPC()); \
|
||||
return fdret; \
|
||||
}
|
||||
|
||||
FLOAT_FMADDSUB(maddf_s, 32, 0)
|
||||
FLOAT_FMADDSUB(maddf_d, 64, 0)
|
||||
FLOAT_FMADDSUB(msubf_s, 32, float_muladd_negate_product)
|
||||
FLOAT_FMADDSUB(msubf_d, 64, float_muladd_negate_product)
|
||||
#undef FLOAT_FMADDSUB
|
||||
|
||||
/* compare operations */
|
||||
#define FOP_COND_D(op, cond) \
|
||||
void helper_cmp_d_ ## op(CPUMIPSState *env, uint64_t fdt0, \
|
||||
|
@ -1882,10 +1882,8 @@ static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
|
||||
{ \
|
||||
TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
|
||||
TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
|
||||
switch (ifmt) { \
|
||||
case FMT_D: \
|
||||
if (ifmt == FMT_D) { \
|
||||
check_cp1_registers(ctx, fs | ft | fd); \
|
||||
break; \
|
||||
} \
|
||||
gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
|
||||
gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
|
||||
@ -2398,7 +2396,14 @@ static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
|
||||
{
|
||||
if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
|
||||
check_cp1_enabled(ctx);
|
||||
gen_flt_ldst(ctx, op, rt, rs, imm);
|
||||
switch (op) {
|
||||
case OPC_LDC1:
|
||||
case OPC_SDC1:
|
||||
check_insn(ctx, ISA_MIPS2);
|
||||
/* Fallthrough */
|
||||
default:
|
||||
gen_flt_ldst(ctx, op, rt, rs, imm);
|
||||
}
|
||||
} else {
|
||||
generate_exception_err(ctx, EXCP_CpU, 1);
|
||||
}
|
||||
@ -5846,8 +5851,10 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
|
||||
ctx->bstate = BS_STOP;
|
||||
break;
|
||||
case 3:
|
||||
/* ignored, read only */
|
||||
gen_helper_mtc0_config3(cpu_env, arg);
|
||||
rn = "Config3";
|
||||
/* Stop translation as we may have switched the execution mode */
|
||||
ctx->bstate = BS_STOP;
|
||||
break;
|
||||
case 4:
|
||||
gen_helper_mtc0_config4(cpu_env, arg);
|
||||
@ -7097,8 +7104,10 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
|
||||
ctx->bstate = BS_STOP;
|
||||
break;
|
||||
case 3:
|
||||
/* ignored */
|
||||
gen_helper_mtc0_config3(cpu_env, arg);
|
||||
rn = "Config3";
|
||||
/* Stop translation as we may have switched the execution mode */
|
||||
ctx->bstate = BS_STOP;
|
||||
break;
|
||||
case 4:
|
||||
/* currently ignored */
|
||||
@ -10717,6 +10726,7 @@ static void gen_mips16_save (DisasContext *ctx,
|
||||
{
|
||||
TCGv t0 = tcg_temp_new();
|
||||
TCGv t1 = tcg_temp_new();
|
||||
TCGv t2 = tcg_temp_new();
|
||||
int args, astatic;
|
||||
|
||||
switch (aregs) {
|
||||
@ -10775,7 +10785,8 @@ static void gen_mips16_save (DisasContext *ctx,
|
||||
gen_load_gpr(t0, 29);
|
||||
|
||||
#define DECR_AND_STORE(reg) do { \
|
||||
tcg_gen_subi_tl(t0, t0, 4); \
|
||||
tcg_gen_movi_tl(t2, -4); \
|
||||
gen_op_addr_add(ctx, t0, t0, t2); \
|
||||
gen_load_gpr(t1, reg); \
|
||||
tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
|
||||
} while (0)
|
||||
@ -10859,9 +10870,11 @@ static void gen_mips16_save (DisasContext *ctx,
|
||||
}
|
||||
#undef DECR_AND_STORE
|
||||
|
||||
tcg_gen_subi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
|
||||
tcg_gen_movi_tl(t2, -framesize);
|
||||
gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
|
||||
tcg_temp_free(t0);
|
||||
tcg_temp_free(t1);
|
||||
tcg_temp_free(t2);
|
||||
}
|
||||
|
||||
static void gen_mips16_restore (DisasContext *ctx,
|
||||
@ -10872,11 +10885,14 @@ static void gen_mips16_restore (DisasContext *ctx,
|
||||
int astatic;
|
||||
TCGv t0 = tcg_temp_new();
|
||||
TCGv t1 = tcg_temp_new();
|
||||
TCGv t2 = tcg_temp_new();
|
||||
|
||||
tcg_gen_addi_tl(t0, cpu_gpr[29], framesize);
|
||||
tcg_gen_movi_tl(t2, framesize);
|
||||
gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
|
||||
|
||||
#define DECR_AND_LOAD(reg) do { \
|
||||
tcg_gen_subi_tl(t0, t0, 4); \
|
||||
tcg_gen_movi_tl(t2, -4); \
|
||||
gen_op_addr_add(ctx, t0, t0, t2); \
|
||||
tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
|
||||
gen_store_gpr(t1, reg); \
|
||||
} while (0)
|
||||
@ -10960,9 +10976,11 @@ static void gen_mips16_restore (DisasContext *ctx,
|
||||
}
|
||||
#undef DECR_AND_LOAD
|
||||
|
||||
tcg_gen_addi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
|
||||
tcg_gen_movi_tl(t2, framesize);
|
||||
gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
|
||||
tcg_temp_free(t0);
|
||||
tcg_temp_free(t1);
|
||||
tcg_temp_free(t2);
|
||||
}
|
||||
|
||||
static void gen_addiupc (DisasContext *ctx, int rx, int imm,
|
||||
@ -10993,26 +11011,32 @@ static void decode_i64_mips16 (DisasContext *ctx,
|
||||
{
|
||||
switch (funct) {
|
||||
case I64_LDSP:
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
offset = extended ? offset : offset << 3;
|
||||
gen_ld(ctx, OPC_LD, ry, 29, offset);
|
||||
break;
|
||||
case I64_SDSP:
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
offset = extended ? offset : offset << 3;
|
||||
gen_st(ctx, OPC_SD, ry, 29, offset);
|
||||
break;
|
||||
case I64_SDRASP:
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
offset = extended ? offset : (ctx->opcode & 0xff) << 3;
|
||||
gen_st(ctx, OPC_SD, 31, 29, offset);
|
||||
break;
|
||||
case I64_DADJSP:
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
|
||||
gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
|
||||
break;
|
||||
case I64_LDPC:
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
|
||||
generate_exception(ctx, EXCP_RI);
|
||||
} else {
|
||||
@ -11021,16 +11045,19 @@ static void decode_i64_mips16 (DisasContext *ctx,
|
||||
}
|
||||
break;
|
||||
case I64_DADDIU5:
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
|
||||
gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
|
||||
break;
|
||||
case I64_DADDIUPC:
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
offset = extended ? offset : offset << 2;
|
||||
gen_addiupc(ctx, ry, offset, 1, extended);
|
||||
break;
|
||||
case I64_DADDIUSP:
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
offset = extended ? offset : offset << 2;
|
||||
gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
|
||||
@ -11099,7 +11126,8 @@ static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
|
||||
break;
|
||||
#if defined(TARGET_MIPS64)
|
||||
case M16_OPC_LD:
|
||||
check_mips_64(ctx);
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
gen_ld(ctx, OPC_LD, ry, rx, offset);
|
||||
break;
|
||||
#endif
|
||||
@ -11143,6 +11171,7 @@ static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
|
||||
gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
|
||||
break;
|
||||
case I8_SVRS:
|
||||
check_insn(ctx, ISA_MIPS32);
|
||||
{
|
||||
int xsregs = (ctx->opcode >> 24) & 0x7;
|
||||
int aregs = (ctx->opcode >> 16) & 0xf;
|
||||
@ -11176,6 +11205,8 @@ static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
|
||||
break;
|
||||
#if defined(TARGET_MIPS64)
|
||||
case M16_OPC_SD:
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
gen_st(ctx, OPC_SD, ry, rx, offset);
|
||||
break;
|
||||
#endif
|
||||
@ -11202,6 +11233,8 @@ static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
|
||||
break;
|
||||
#if defined(TARGET_MIPS64)
|
||||
case M16_OPC_LWU:
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
gen_ld(ctx, OPC_LWU, ry, rx, offset);
|
||||
break;
|
||||
#endif
|
||||
@ -11291,6 +11324,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
|
||||
break;
|
||||
case 0x1:
|
||||
#if defined(TARGET_MIPS64)
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
|
||||
#else
|
||||
@ -11307,6 +11341,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
|
||||
break;
|
||||
#if defined(TARGET_MIPS64)
|
||||
case M16_OPC_LD:
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
|
||||
break;
|
||||
@ -11317,6 +11352,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
|
||||
|
||||
if ((ctx->opcode >> 4) & 1) {
|
||||
#if defined(TARGET_MIPS64)
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
|
||||
#else
|
||||
@ -11368,6 +11404,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
|
||||
((int8_t)ctx->opcode) << 3);
|
||||
break;
|
||||
case I8_SVRS:
|
||||
check_insn(ctx, ISA_MIPS32);
|
||||
{
|
||||
int do_ra = ctx->opcode & (1 << 6);
|
||||
int do_s0 = ctx->opcode & (1 << 5);
|
||||
@ -11423,6 +11460,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
|
||||
break;
|
||||
#if defined(TARGET_MIPS64)
|
||||
case M16_OPC_SD:
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
gen_st(ctx, OPC_SD, ry, rx, offset << 3);
|
||||
break;
|
||||
@ -11450,6 +11488,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
|
||||
break;
|
||||
#if defined (TARGET_MIPS64)
|
||||
case M16_OPC_LWU:
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
|
||||
break;
|
||||
@ -11481,10 +11520,12 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
|
||||
#if defined(TARGET_MIPS64)
|
||||
case RRR_DADDU:
|
||||
mips32_op = OPC_DADDU;
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
break;
|
||||
case RRR_DSUBU:
|
||||
mips32_op = OPC_DSUBU;
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
break;
|
||||
#endif
|
||||
@ -11506,6 +11547,10 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
|
||||
int link = (ctx->opcode >> 6) & 0x1;
|
||||
int ra = (ctx->opcode >> 5) & 0x1;
|
||||
|
||||
if (nd) {
|
||||
check_insn(ctx, ISA_MIPS32);
|
||||
}
|
||||
|
||||
if (link) {
|
||||
op = OPC_JALR;
|
||||
} else {
|
||||
@ -11547,6 +11592,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
|
||||
break;
|
||||
#if defined (TARGET_MIPS64)
|
||||
case RR_DSRL:
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
|
||||
break;
|
||||
@ -11573,6 +11619,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
|
||||
gen_HILO(ctx, OPC_MFHI, 0, rx);
|
||||
break;
|
||||
case RR_CNVT:
|
||||
check_insn(ctx, ISA_MIPS32);
|
||||
switch (cnvt_op) {
|
||||
case RR_RY_CNVT_ZEB:
|
||||
tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
|
||||
@ -11588,10 +11635,12 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
|
||||
break;
|
||||
#if defined (TARGET_MIPS64)
|
||||
case RR_RY_CNVT_ZEW:
|
||||
check_insn(ctx, ISA_MIPS64);
|
||||
check_mips_64(ctx);
|
||||
tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
|
||||
break;
|
||||
case RR_RY_CNVT_SEW:
|
||||
check_insn(ctx, ISA_MIPS64);
|
||||
check_mips_64(ctx);
|
||||
tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
|
||||
break;
|
||||
@ -11606,18 +11655,22 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
|
||||
break;
|
||||
#if defined (TARGET_MIPS64)
|
||||
case RR_DSRA:
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
|
||||
break;
|
||||
case RR_DSLLV:
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
|
||||
break;
|
||||
case RR_DSRLV:
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
|
||||
break;
|
||||
case RR_DSRAV:
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
|
||||
break;
|
||||
@ -11636,18 +11689,22 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
|
||||
break;
|
||||
#if defined (TARGET_MIPS64)
|
||||
case RR_DMULT:
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
|
||||
break;
|
||||
case RR_DMULTU:
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
|
||||
break;
|
||||
case RR_DDIV:
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
|
||||
break;
|
||||
case RR_DDIVU:
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
|
||||
break;
|
||||
@ -13212,20 +13269,26 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
|
||||
/* COP2: Not implemented. */
|
||||
generate_exception_err(ctx, EXCP_CpU, 2);
|
||||
break;
|
||||
case LWP:
|
||||
case SWP:
|
||||
#ifdef TARGET_MIPS64
|
||||
case LDP:
|
||||
case SDP:
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
/* Fallthrough */
|
||||
#endif
|
||||
case LWP:
|
||||
case SWP:
|
||||
gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
|
||||
break;
|
||||
case LWM32:
|
||||
case SWM32:
|
||||
#ifdef TARGET_MIPS64
|
||||
case LDM:
|
||||
case SDM:
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
/* Fallthrough */
|
||||
#endif
|
||||
case LWM32:
|
||||
case SWM32:
|
||||
gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
|
||||
break;
|
||||
default:
|
||||
@ -13649,21 +13712,33 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
|
||||
goto do_st_lr;
|
||||
#if defined(TARGET_MIPS64)
|
||||
case LDL:
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
mips32_op = OPC_LDL;
|
||||
goto do_ld_lr;
|
||||
case SDL:
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
mips32_op = OPC_SDL;
|
||||
goto do_st_lr;
|
||||
case LDR:
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
mips32_op = OPC_LDR;
|
||||
goto do_ld_lr;
|
||||
case SDR:
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
mips32_op = OPC_SDR;
|
||||
goto do_st_lr;
|
||||
case LWU:
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
mips32_op = OPC_LWU;
|
||||
goto do_ld_lr;
|
||||
case LLD:
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
mips32_op = OPC_LLD;
|
||||
goto do_ld_lr;
|
||||
#endif
|
||||
@ -13681,6 +13756,8 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
|
||||
break;
|
||||
#if defined(TARGET_MIPS64)
|
||||
case SCD:
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
gen_st_cond(ctx, OPC_SCD, rt, rs, SIMM(ctx->opcode, 0, 12));
|
||||
break;
|
||||
#endif
|
||||
@ -13790,9 +13867,13 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
|
||||
goto do_ld;
|
||||
#ifdef TARGET_MIPS64
|
||||
case LD32:
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
mips32_op = OPC_LD;
|
||||
goto do_ld;
|
||||
case SD32:
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
mips32_op = OPC_SD;
|
||||
goto do_st;
|
||||
#endif
|
||||
@ -13936,8 +14017,8 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
|
||||
rs = rs_rt_enc[enc_rs];
|
||||
rt = rs_rt_enc[enc_rt];
|
||||
|
||||
gen_arith_imm(ctx, OPC_ADDIU, rd, rs, 0);
|
||||
gen_arith_imm(ctx, OPC_ADDIU, re, rt, 0);
|
||||
gen_arith(ctx, OPC_ADDU, rd, rs, 0);
|
||||
gen_arith(ctx, OPC_ADDU, re, rt, 0);
|
||||
}
|
||||
break;
|
||||
case LBU16:
|
||||
@ -14018,7 +14099,7 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
|
||||
int rd = uMIPS_RD5(ctx->opcode);
|
||||
int rs = uMIPS_RS5(ctx->opcode);
|
||||
|
||||
gen_arith_imm(ctx, OPC_ADDIU, rd, rs, 0);
|
||||
gen_arith(ctx, OPC_ADDU, rd, rs, 0);
|
||||
}
|
||||
break;
|
||||
case ANDI16:
|
||||
@ -16322,6 +16403,7 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
|
||||
break;
|
||||
case OPC_TGE ... OPC_TEQ: /* Traps */
|
||||
case OPC_TNE:
|
||||
check_insn(ctx, ISA_MIPS2);
|
||||
gen_trap(ctx, op1, rs, rt, -1);
|
||||
break;
|
||||
case OPC_LSA: /* OPC_PMON */
|
||||
@ -16346,6 +16428,7 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
|
||||
generate_exception(ctx, EXCP_BREAK);
|
||||
break;
|
||||
case OPC_SYNC:
|
||||
check_insn(ctx, ISA_MIPS2);
|
||||
/* Treat as NOP. */
|
||||
break;
|
||||
|
||||
@ -18340,7 +18423,7 @@ static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
|
||||
|
||||
}
|
||||
|
||||
static void decode_opc (CPUMIPSState *env, DisasContext *ctx)
|
||||
static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
|
||||
{
|
||||
int32_t offset;
|
||||
int rs, rt, rd, sa;
|
||||
@ -18392,7 +18475,9 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx)
|
||||
case OPC_BGEZL:
|
||||
case OPC_BLTZALL:
|
||||
case OPC_BGEZALL:
|
||||
check_insn(ctx, ISA_MIPS2);
|
||||
check_insn_opc_removed(ctx, ISA_MIPS32R6);
|
||||
/* Fallthrough */
|
||||
case OPC_BLTZ:
|
||||
case OPC_BGEZ:
|
||||
gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
|
||||
@ -18412,6 +18497,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx)
|
||||
break;
|
||||
case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
|
||||
case OPC_TNEI:
|
||||
check_insn(ctx, ISA_MIPS2);
|
||||
check_insn_opc_removed(ctx, ISA_MIPS32R6);
|
||||
gen_trap(ctx, op1, rs, -1, imm);
|
||||
break;
|
||||
@ -18506,7 +18592,8 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx)
|
||||
save_cpu_state(ctx, 1);
|
||||
gen_helper_di(t0, cpu_env);
|
||||
gen_store_gpr(t0, rt);
|
||||
/* Stop translation as we may have switched the execution mode */
|
||||
/* Stop translation as we may have switched
|
||||
the execution mode. */
|
||||
ctx->bstate = BS_STOP;
|
||||
break;
|
||||
case OPC_EI:
|
||||
@ -18514,7 +18601,8 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx)
|
||||
save_cpu_state(ctx, 1);
|
||||
gen_helper_ei(t0, cpu_env);
|
||||
gen_store_gpr(t0, rt);
|
||||
/* Stop translation as we may have switched the execution mode */
|
||||
/* Stop translation as we may have switched
|
||||
the execution mode. */
|
||||
ctx->bstate = BS_STOP;
|
||||
break;
|
||||
default: /* Invalid */
|
||||
@ -18616,15 +18704,20 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx)
|
||||
break;
|
||||
case OPC_BEQL:
|
||||
case OPC_BNEL:
|
||||
check_insn(ctx, ISA_MIPS2);
|
||||
check_insn_opc_removed(ctx, ISA_MIPS32R6);
|
||||
/* Fallthrough */
|
||||
case OPC_BEQ:
|
||||
case OPC_BNE:
|
||||
gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
|
||||
break;
|
||||
case OPC_LWL: /* Load and stores */
|
||||
case OPC_LL: /* Load and stores */
|
||||
check_insn(ctx, ISA_MIPS2);
|
||||
/* Fallthrough */
|
||||
case OPC_LWL:
|
||||
case OPC_LWR:
|
||||
case OPC_LL:
|
||||
check_insn_opc_removed(ctx, ISA_MIPS32R6);
|
||||
/* Fallthrough */
|
||||
case OPC_LB ... OPC_LH:
|
||||
case OPC_LW ... OPC_LHU:
|
||||
gen_ld(ctx, op, rt, rs, imm);
|
||||
@ -18637,6 +18730,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx)
|
||||
gen_st(ctx, op, rt, rs, imm);
|
||||
break;
|
||||
case OPC_SC:
|
||||
check_insn(ctx, ISA_MIPS2);
|
||||
check_insn_opc_removed(ctx, ISA_MIPS32R6);
|
||||
gen_st_cond(ctx, op, rt, rs, imm);
|
||||
break;
|
||||
@ -18680,6 +18774,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx)
|
||||
case OPC_DMTC1:
|
||||
check_cp1_enabled(ctx);
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
gen_cp1(ctx, op1, rt, rd);
|
||||
break;
|
||||
#endif
|
||||
@ -18780,8 +18875,9 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx)
|
||||
gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
|
||||
break;
|
||||
default:
|
||||
gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
|
||||
(imm >> 8) & 0x7);
|
||||
gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
|
||||
rt, rd, sa, (imm >> 8) & 0x7);
|
||||
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@ -18852,18 +18948,24 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx)
|
||||
check_cp1_enabled(ctx);
|
||||
op1 = MASK_CP3(ctx->opcode);
|
||||
switch (op1) {
|
||||
case OPC_LUXC1:
|
||||
case OPC_SUXC1:
|
||||
check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
|
||||
/* Fallthrough */
|
||||
case OPC_LWXC1:
|
||||
case OPC_LDXC1:
|
||||
case OPC_LUXC1:
|
||||
case OPC_SWXC1:
|
||||
case OPC_SDXC1:
|
||||
case OPC_SUXC1:
|
||||
check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
|
||||
gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
|
||||
break;
|
||||
case OPC_PREFX:
|
||||
check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
|
||||
/* Treat as NOP. */
|
||||
break;
|
||||
case OPC_ALNV_PS:
|
||||
check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
|
||||
/* Fallthrough */
|
||||
case OPC_MADD_S:
|
||||
case OPC_MADD_D:
|
||||
case OPC_MADD_PS:
|
||||
@ -18876,6 +18978,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx)
|
||||
case OPC_NMSUB_S:
|
||||
case OPC_NMSUB_D:
|
||||
case OPC_NMSUB_PS:
|
||||
check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
|
||||
gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
|
||||
break;
|
||||
default:
|
||||
@ -19011,7 +19114,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
|
||||
ctx.bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
|
||||
/* Restore delay slot state from the tb context. */
|
||||
ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
|
||||
ctx.ulri = env->CP0_Config3 & (1 << CP0C3_ULRI);
|
||||
ctx.ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
|
||||
restore_cpu_state(env, &ctx);
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
ctx.mem_idx = MIPS_HFLAG_UM;
|
||||
@ -19261,6 +19364,10 @@ void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
|
||||
env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
|
||||
cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
|
||||
env->CP0_Config0, env->CP0_Config1, env->lladdr);
|
||||
cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
|
||||
env->CP0_Config2, env->CP0_Config3);
|
||||
cpu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
|
||||
env->CP0_Config4, env->CP0_Config5);
|
||||
if (env->hflags & MIPS_HFLAG_FPU)
|
||||
fpu_dump_state(env, f, cpu_fprintf, flags);
|
||||
#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
|
||||
@ -19436,7 +19543,8 @@ void cpu_state_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->active_tc.PC - 4;
|
||||
env->CP0_ErrorEPC = (env->active_tc.PC
|
||||
- (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
|
||||
} else {
|
||||
env->CP0_ErrorEPC = env->active_tc.PC;
|
||||
}
|
||||
@ -19507,6 +19615,8 @@ void cpu_state_reset(CPUMIPSState *env)
|
||||
}
|
||||
|
||||
compute_hflags(env);
|
||||
restore_rounding_mode(env);
|
||||
restore_flush_mode(env);
|
||||
cs->exception_index = EXCP_NONE;
|
||||
}
|
||||
|
||||
|
@ -334,7 +334,7 @@ static const mips_def_t mips_defs[] =
|
||||
(1 << CP0C1_CA),
|
||||
.CP0_Config2 = MIPS_CONFIG2,
|
||||
.CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_DSP2P) | (1 << CP0C3_DSPP) |
|
||||
(0 << CP0C3_VInt),
|
||||
(1 << CP0C3_VInt),
|
||||
.CP0_LLAddr_rw_bitmask = 0,
|
||||
.CP0_LLAddr_shift = 4,
|
||||
.SYNCI_Step = 32,
|
||||
@ -347,6 +347,47 @@ static const mips_def_t mips_defs[] =
|
||||
.insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP | ASE_DSPR2,
|
||||
.mmu_type = MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
.name = "M14K",
|
||||
.CP0_PRid = 0x00019b00,
|
||||
/* Config1 implemented, fixed mapping MMU,
|
||||
no virtual icache, uncached coherency. */
|
||||
.CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_KU) | (0x2 << CP0C0_K23) |
|
||||
(0x1 << CP0C0_AR) | (MMU_TYPE_FMT << CP0C0_MT),
|
||||
.CP0_Config1 = MIPS_CONFIG1,
|
||||
.CP0_Config2 = MIPS_CONFIG2,
|
||||
.CP0_Config3 = MIPS_CONFIG3 | (0x2 << CP0C3_ISA) | (1 << CP0C3_VInt),
|
||||
.CP0_LLAddr_rw_bitmask = 0,
|
||||
.CP0_LLAddr_shift = 4,
|
||||
.SYNCI_Step = 32,
|
||||
.CCRes = 2,
|
||||
.CP0_Status_rw_bitmask = 0x1258FF17,
|
||||
.SEGBITS = 32,
|
||||
.PABITS = 32,
|
||||
.insn_flags = CPU_MIPS32R2 | ASE_MICROMIPS,
|
||||
.mmu_type = MMU_TYPE_FMT,
|
||||
},
|
||||
{
|
||||
.name = "M14Kc",
|
||||
/* This is the TLB-based MMU core. */
|
||||
.CP0_PRid = 0x00019c00,
|
||||
.CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) |
|
||||
(MMU_TYPE_R4000 << CP0C0_MT),
|
||||
.CP0_Config1 = MIPS_CONFIG1 | (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 | (0x2 << CP0C3_ISA) | (0 << CP0C3_VInt),
|
||||
.CP0_LLAddr_rw_bitmask = 0,
|
||||
.CP0_LLAddr_shift = 4,
|
||||
.SYNCI_Step = 32,
|
||||
.CCRes = 2,
|
||||
.CP0_Status_rw_bitmask = 0x1278FF17,
|
||||
.SEGBITS = 32,
|
||||
.PABITS = 32,
|
||||
.insn_flags = CPU_MIPS32R2 | ASE_MICROMIPS,
|
||||
.mmu_type = MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
/* A generic CPU providing MIPS32 Release 5 features.
|
||||
FIXME: Eventually this should be replaced by a real CPU model. */
|
||||
@ -519,6 +560,51 @@ static const mips_def_t mips_defs[] =
|
||||
.insn_flags = CPU_MIPS64R2 | ASE_MIPS3D,
|
||||
.mmu_type = MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
.name = "5KEc",
|
||||
.CP0_PRid = 0x00018900,
|
||||
.CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (0x2 << CP0C0_AT) |
|
||||
(MMU_TYPE_R4000 << CP0C0_MT),
|
||||
.CP0_Config1 = MIPS_CONFIG1 | (31 << CP0C1_MMU) |
|
||||
(1 << CP0C1_IS) | (4 << CP0C1_IL) | (1 << CP0C1_IA) |
|
||||
(1 << CP0C1_DS) | (4 << CP0C1_DL) | (1 << CP0C1_DA) |
|
||||
(1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
|
||||
.CP0_Config2 = MIPS_CONFIG2,
|
||||
.CP0_Config3 = MIPS_CONFIG3,
|
||||
.CP0_LLAddr_rw_bitmask = 0,
|
||||
.CP0_LLAddr_shift = 4,
|
||||
.SYNCI_Step = 32,
|
||||
.CCRes = 2,
|
||||
.CP0_Status_rw_bitmask = 0x32F8FFFF,
|
||||
.SEGBITS = 42,
|
||||
.PABITS = 36,
|
||||
.insn_flags = CPU_MIPS64R2,
|
||||
.mmu_type = MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
.name = "5KEf",
|
||||
.CP0_PRid = 0x00018900,
|
||||
.CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (0x2 << CP0C0_AT) |
|
||||
(MMU_TYPE_R4000 << CP0C0_MT),
|
||||
.CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (31 << CP0C1_MMU) |
|
||||
(1 << CP0C1_IS) | (4 << CP0C1_IL) | (1 << CP0C1_IA) |
|
||||
(1 << CP0C1_DS) | (4 << CP0C1_DL) | (1 << CP0C1_DA) |
|
||||
(1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
|
||||
.CP0_Config2 = MIPS_CONFIG2,
|
||||
.CP0_Config3 = MIPS_CONFIG3,
|
||||
.CP0_LLAddr_rw_bitmask = 0,
|
||||
.CP0_LLAddr_shift = 4,
|
||||
.SYNCI_Step = 32,
|
||||
.CCRes = 2,
|
||||
.CP0_Status_rw_bitmask = 0x36F8FFFF,
|
||||
.CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
|
||||
(1 << FCR0_D) | (1 << FCR0_S) |
|
||||
(0x89 << FCR0_PRID) | (0x0 << FCR0_REV),
|
||||
.SEGBITS = 42,
|
||||
.PABITS = 36,
|
||||
.insn_flags = CPU_MIPS64R2,
|
||||
.mmu_type = MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
/* A generic CPU supporting MIPS64 Release 6 ISA.
|
||||
FIXME: Support IEEE 754-2008 FP and misaligned memory accesses.
|
||||
@ -559,10 +645,11 @@ static const mips_def_t mips_defs[] =
|
||||
{
|
||||
.name = "Loongson-2E",
|
||||
.CP0_PRid = 0x6302,
|
||||
/*64KB I-cache and d-cache. 4 way with 32 bit cache line size*/
|
||||
.CP0_Config0 = (0x1<<17) | (0x1<<16) | (0x1<<11) | (0x1<<8) | (0x1<<5) |
|
||||
(0x1<<4) | (0x1<<1),
|
||||
/* Note: Config1 is only used internally, Loongson-2E has only Config0. */
|
||||
/* 64KB I-cache and d-cache. 4 way with 32 bit cache line size. */
|
||||
.CP0_Config0 = (0x1<<17) | (0x1<<16) | (0x1<<11) | (0x1<<8) |
|
||||
(0x1<<5) | (0x1<<4) | (0x1<<1),
|
||||
/* Note: Config1 is only used internally,
|
||||
Loongson-2E has only Config0. */
|
||||
.CP0_Config1 = (1 << CP0C1_FP) | (47 << CP0C1_MMU),
|
||||
.SYNCI_Step = 16,
|
||||
.CCRes = 2,
|
||||
@ -574,21 +661,22 @@ static const mips_def_t mips_defs[] =
|
||||
.mmu_type = MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
.name = "Loongson-2F",
|
||||
.CP0_PRid = 0x6303,
|
||||
/*64KB I-cache and d-cache. 4 way with 32 bit cache line size*/
|
||||
.CP0_Config0 = (0x1<<17) | (0x1<<16) | (0x1<<11) | (0x1<<8) | (0x1<<5) |
|
||||
(0x1<<4) | (0x1<<1),
|
||||
/* Note: Config1 is only used internally, Loongson-2F has only Config0. */
|
||||
.CP0_Config1 = (1 << CP0C1_FP) | (47 << CP0C1_MMU),
|
||||
.SYNCI_Step = 16,
|
||||
.CCRes = 2,
|
||||
.CP0_Status_rw_bitmask = 0xF5D0FF1F, /*bit5:7 not writable*/
|
||||
.CP1_fcr0 = (0x5 << FCR0_PRID) | (0x1 << FCR0_REV),
|
||||
.SEGBITS = 40,
|
||||
.PABITS = 40,
|
||||
.insn_flags = CPU_LOONGSON2F,
|
||||
.mmu_type = MMU_TYPE_R4000,
|
||||
.name = "Loongson-2F",
|
||||
.CP0_PRid = 0x6303,
|
||||
/* 64KB I-cache and d-cache. 4 way with 32 bit cache line size. */
|
||||
.CP0_Config0 = (0x1<<17) | (0x1<<16) | (0x1<<11) | (0x1<<8) |
|
||||
(0x1<<5) | (0x1<<4) | (0x1<<1),
|
||||
/* Note: Config1 is only used internally,
|
||||
Loongson-2F has only Config0. */
|
||||
.CP0_Config1 = (1 << CP0C1_FP) | (47 << CP0C1_MMU),
|
||||
.SYNCI_Step = 16,
|
||||
.CCRes = 2,
|
||||
.CP0_Status_rw_bitmask = 0xF5D0FF1F, /* Bits 7:5 not writable. */
|
||||
.CP1_fcr0 = (0x5 << FCR0_PRID) | (0x1 << FCR0_REV),
|
||||
.SEGBITS = 40,
|
||||
.PABITS = 40,
|
||||
.insn_flags = CPU_LOONGSON2F,
|
||||
.mmu_type = MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
/* A generic CPU providing MIPS64 ASE DSP 2 features.
|
||||
|
@ -1540,7 +1540,7 @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr)
|
||||
branch. */
|
||||
#if defined(TARGET_MIPS)
|
||||
if ((env->hflags & MIPS_HFLAG_BMASK) != 0 && n > 1) {
|
||||
env->active_tc.PC -= 4;
|
||||
env->active_tc.PC -= (env->hflags & MIPS_HFLAG_B16 ? 2 : 4);
|
||||
cpu->icount_decr.u16.low++;
|
||||
env->hflags &= ~MIPS_HFLAG_BMASK;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user