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:
Peter Maydell 2014-12-17 16:25:21 +00:00
commit 84afc4dd56
11 changed files with 621 additions and 393 deletions

View File

@ -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",

View File

@ -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

View File

@ -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__) */

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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)); \
\

View File

@ -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, \

View File

@ -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;
}

View File

@ -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.

View File

@ -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;
}