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

* remotes/lalrae/tags/mips-20141103: (34 commits)
  target-mips: add MSA support to mips32r5-generic
  disas/mips.c: disassemble MSA instructions
  target-mips: add MSA MI10 format instructions
  target-mips: add MSA 2RF format instructions
  target-mips: add MSA VEC/2R format instructions
  target-mips: add MSA 3RF format instructions
  target-mips: add MSA ELM format instructions
  target-mips: add MSA 3R format instructions
  target-mips: add MSA BIT format instructions
  target-mips: add MSA I5 format instruction
  target-mips: add MSA I8 format instructions
  target-mips: add MSA branch instructions
  target-mips: add msa_helper.c
  target-mips: add msa_reset(), global msa register
  target-mips: add MSA opcode enum
  target-mips: stop translation after ctc1
  target-mips: remove duplicated mips/ieee mapping function
  target-mips: add MSA exceptions
  target-mips: add MSA defines and data structure
  target-mips: enable features in MIPS64R6-generic CPU
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell
2014-11-04 00:17:45 +00:00
14 changed files with 6873 additions and 470 deletions
+716 -2
View File
File diff suppressed because it is too large Load Diff
+6
View File
@@ -26,6 +26,12 @@ typedef struct CPUListState {
FILE *file;
} CPUListState;
typedef enum MMUAccessType {
MMU_DATA_LOAD = 0,
MMU_DATA_STORE = 1,
MMU_INST_FETCH = 2
} MMUAccessType;
#if !defined(CONFIG_USER_ONLY)
enum device_endian {
+16 -10
View File
@@ -67,10 +67,10 @@
#endif
#ifdef SOFTMMU_CODE_ACCESS
#define READ_ACCESS_TYPE 2
#define READ_ACCESS_TYPE MMU_INST_FETCH
#define ADDR_READ addr_code
#else
#define READ_ACCESS_TYPE 0
#define READ_ACCESS_TYPE MMU_DATA_LOAD
#define ADDR_READ addr_read
#endif
@@ -396,11 +396,12 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
!= (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
#ifdef ALIGNED_ONLY
if ((addr & (DATA_SIZE - 1)) != 0) {
cpu_unaligned_access(ENV_GET_CPU(env), addr, 1, mmu_idx, retaddr);
cpu_unaligned_access(ENV_GET_CPU(env), addr, MMU_DATA_STORE,
mmu_idx, retaddr);
}
#endif
if (!VICTIM_TLB_HIT(addr_write)) {
tlb_fill(ENV_GET_CPU(env), addr, 1, mmu_idx, retaddr);
tlb_fill(ENV_GET_CPU(env), addr, MMU_DATA_STORE, mmu_idx, retaddr);
}
tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
}
@@ -427,7 +428,8 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
int i;
do_unaligned_access:
#ifdef ALIGNED_ONLY
cpu_unaligned_access(ENV_GET_CPU(env), addr, 1, mmu_idx, retaddr);
cpu_unaligned_access(ENV_GET_CPU(env), addr, MMU_DATA_STORE,
mmu_idx, retaddr);
#endif
/* XXX: not efficient, but simple */
/* Note: relies on the fact that tlb_fill() does not remove the
@@ -446,7 +448,8 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
/* Handle aligned access or unaligned access in the same page. */
#ifdef ALIGNED_ONLY
if ((addr & (DATA_SIZE - 1)) != 0) {
cpu_unaligned_access(ENV_GET_CPU(env), addr, 1, mmu_idx, retaddr);
cpu_unaligned_access(ENV_GET_CPU(env), addr, MMU_DATA_STORE,
mmu_idx, retaddr);
}
#endif
@@ -474,11 +477,12 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
!= (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
#ifdef ALIGNED_ONLY
if ((addr & (DATA_SIZE - 1)) != 0) {
cpu_unaligned_access(ENV_GET_CPU(env), addr, 1, mmu_idx, retaddr);
cpu_unaligned_access(ENV_GET_CPU(env), addr, MMU_DATA_STORE,
mmu_idx, retaddr);
}
#endif
if (!VICTIM_TLB_HIT(addr_write)) {
tlb_fill(ENV_GET_CPU(env), addr, 1, mmu_idx, retaddr);
tlb_fill(ENV_GET_CPU(env), addr, MMU_DATA_STORE, mmu_idx, retaddr);
}
tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
}
@@ -505,7 +509,8 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
int i;
do_unaligned_access:
#ifdef ALIGNED_ONLY
cpu_unaligned_access(ENV_GET_CPU(env), addr, 1, mmu_idx, retaddr);
cpu_unaligned_access(ENV_GET_CPU(env), addr, MMU_DATA_STORE,
mmu_idx, retaddr);
#endif
/* XXX: not efficient, but simple */
/* Note: relies on the fact that tlb_fill() does not remove the
@@ -524,7 +529,8 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
/* Handle aligned access or unaligned access in the same page. */
#ifdef ALIGNED_ONLY
if ((addr & (DATA_SIZE - 1)) != 0) {
cpu_unaligned_access(ENV_GET_CPU(env), addr, 1, mmu_idx, retaddr);
cpu_unaligned_access(ENV_GET_CPU(env), addr, MMU_DATA_STORE,
mmu_idx, retaddr);
}
#endif
+1 -1
View File
@@ -1,4 +1,4 @@
obj-y += translate.o dsp_helper.o op_helper.o lmi_helper.o helper.o cpu.o
obj-y += gdbstub.o
obj-y += gdbstub.o msa_helper.o
obj-$(CONFIG_SOFTMMU) += machine.o
obj-$(CONFIG_KVM) += kvm.o
+101 -6
View File
@@ -30,6 +30,11 @@ struct r4k_tlb_t {
uint_fast16_t V1:1;
uint_fast16_t D0:1;
uint_fast16_t D1:1;
uint_fast16_t XI0:1;
uint_fast16_t XI1:1;
uint_fast16_t RI0:1;
uint_fast16_t RI1:1;
uint_fast16_t EHINV:1;
target_ulong PFN[2];
};
@@ -43,6 +48,8 @@ struct CPUMIPSTLBContext {
void (*helper_tlbwr)(struct CPUMIPSState *env);
void (*helper_tlbp)(struct CPUMIPSState *env);
void (*helper_tlbr)(struct CPUMIPSState *env);
void (*helper_tlbinv)(struct CPUMIPSState *env);
void (*helper_tlbinvf)(struct CPUMIPSState *env);
union {
struct {
r4k_tlb_t tlb[MIPS_TLB_MAX];
@@ -51,12 +58,32 @@ struct CPUMIPSTLBContext {
};
#endif
/* MSA Context */
#define MSA_WRLEN (128)
enum CPUMIPSMSADataFormat {
DF_BYTE = 0,
DF_HALF,
DF_WORD,
DF_DOUBLE
};
typedef union wr_t wr_t;
union wr_t {
int8_t b[MSA_WRLEN/8];
int16_t h[MSA_WRLEN/16];
int32_t w[MSA_WRLEN/32];
int64_t d[MSA_WRLEN/64];
};
typedef union fpr_t fpr_t;
union fpr_t {
float64 fd; /* ieee double precision */
float32 fs[2];/* ieee single precision */
uint64_t d; /* binary double fixed-point */
uint32_t w[2]; /* binary single fixed-point */
/* FPU/MSA register mapping is not tested on big-endian hosts. */
wr_t wr; /* vector data */
};
/* define FP_ENDIAN_IDX to access the same location
* in the fpr_t union regardless of the host endianness
@@ -136,6 +163,7 @@ typedef struct mips_def_t mips_def_t;
#define MIPS_TC_MAX 5
#define MIPS_FPU_MAX 1
#define MIPS_DSP_ACC 4
#define MIPS_KSCRATCH_NUM 6
typedef struct TCState TCState;
struct TCState {
@@ -169,6 +197,21 @@ struct TCState {
target_ulong CP0_TCScheFBack;
int32_t CP0_Debug_tcstatus;
target_ulong CP0_UserLocal;
int32_t msacsr;
#define MSACSR_FS 24
#define MSACSR_FS_MASK (1 << MSACSR_FS)
#define MSACSR_NX 18
#define MSACSR_NX_MASK (1 << MSACSR_NX)
#define MSACSR_CEF 2
#define MSACSR_CEF_MASK (0xffff << MSACSR_CEF)
#define MSACSR_RM 0
#define MSACSR_RM_MASK (0x3 << MSACSR_RM)
#define MSACSR_MASK (MSACSR_RM_MASK | MSACSR_CEF_MASK | MSACSR_NX_MASK | \
MSACSR_FS_MASK)
float_status msa_fp_status;
};
typedef struct CPUMIPSState CPUMIPSState;
@@ -184,6 +227,10 @@ struct CPUMIPSState {
target_ulong SEGMask;
target_ulong PAMask;
int32_t msair;
#define MSAIR_ProcID 8
#define MSAIR_Rev 0
int32_t CP0_Index;
/* CP0_MVP* are per MVP registers. */
int32_t CP0_Random;
@@ -228,9 +275,21 @@ struct CPUMIPSState {
#define CP0VPEOpt_DWX0 0
target_ulong CP0_EntryLo0;
target_ulong CP0_EntryLo1;
#if defined(TARGET_MIPS64)
# define CP0EnLo_RI 63
# define CP0EnLo_XI 62
#else
# define CP0EnLo_RI 31
# define CP0EnLo_XI 30
#endif
target_ulong CP0_Context;
target_ulong CP0_KScratch[MIPS_KSCRATCH_NUM];
int32_t CP0_PageMask;
int32_t CP0_PageGrain_rw_bitmask;
int32_t CP0_PageGrain;
#define CP0PG_RIE 31
#define CP0PG_XIE 30
#define CP0PG_IEC 27
int32_t CP0_Wired;
int32_t CP0_SRSConf0_rw_bitmask;
int32_t CP0_SRSConf0;
@@ -263,8 +322,11 @@ struct CPUMIPSState {
#define CP0SRSC4_SRS13 0
int32_t CP0_HWREna;
target_ulong CP0_BadVAddr;
uint32_t CP0_BadInstr;
uint32_t CP0_BadInstrP;
int32_t CP0_Count;
target_ulong CP0_EntryHi;
#define CP0EnHi_EHINV 10
int32_t CP0_Compare;
int32_t CP0_Status;
#define CP0St_CU3 31
@@ -362,8 +424,12 @@ struct CPUMIPSState {
#define CP0C2_SA 0
int32_t CP0_Config3;
#define CP0C3_M 31
#define CP0C3_MSAP 28
#define CP0C3_BP 27
#define CP0C3_BI 26
#define CP0C3_ISA_ON_EXC 16
#define CP0C3_ULRI 13
#define CP0C3_RXI 12
#define CP0C3_DSPP 10
#define CP0C3_LPA 7
#define CP0C3_VEIC 6
@@ -375,6 +441,8 @@ struct CPUMIPSState {
uint32_t CP0_Config4;
uint32_t CP0_Config4_rw_bitmask;
#define CP0C4_M 31
#define CP0C4_IE 29
#define CP0C4_KScrExist 16
uint32_t CP0_Config5;
uint32_t CP0_Config5_rw_bitmask;
#define CP0C5_M 31
@@ -382,6 +450,7 @@ struct CPUMIPSState {
#define CP0C5_CV 29
#define CP0C5_EVA 28
#define CP0C5_MSAEn 27
#define CP0C5_SBRI 6
#define CP0C5_UFR 2
#define CP0C5_NFExists 0
int32_t CP0_Config6;
@@ -429,9 +498,11 @@ struct CPUMIPSState {
CPUMIPSFPUContext fpus[MIPS_FPU_MAX];
/* QEMU */
int error_code;
#define EXCP_TLB_NOMATCH 0x1
#define EXCP_INST_NOTAVAIL 0x2 /* No valid instruction word for BadInstr */
uint32_t hflags; /* CPU State */
/* TMASK defines different execution modes */
#define MIPS_HFLAG_TMASK 0x1807FF
#define MIPS_HFLAG_TMASK 0x15807FF
#define MIPS_HFLAG_MODE 0x00007 /* execution modes */
/* The KSU flags must be the lowest bits in hflags. The flag order
must be the same as defined for CP0 Status. This allows to use
@@ -457,7 +528,7 @@ struct CPUMIPSState {
* the delay slot, record what type of branch it is so that we can
* resume translation properly. It might be possible to reduce
* this from three bits to two. */
#define MIPS_HFLAG_BMASK_BASE 0x03800
#define MIPS_HFLAG_BMASK_BASE 0x803800
#define MIPS_HFLAG_B 0x00800 /* Unconditional branch */
#define MIPS_HFLAG_BC 0x01000 /* Conditional branch */
#define MIPS_HFLAG_BL 0x01800 /* Likely branch */
@@ -475,6 +546,9 @@ struct CPUMIPSState {
#define MIPS_HFLAG_DSPR2 0x100000 /* Enable access to MIPS DSPR2 resources. */
/* Extra flag about HWREna register. */
#define MIPS_HFLAG_HWRENA_ULR 0x200000 /* ULR bit from HWREna is set. */
#define MIPS_HFLAG_SBRI 0x400000 /* R6 SDBBP causes RI excpt. in user mode */
#define MIPS_HFLAG_FBNSLOT 0x800000 /* Forbidden slot */
#define MIPS_HFLAG_MSA 0x1000000
target_ulong btarget; /* Jump / branch target */
target_ulong bcond; /* Branch condition (if needed) */
@@ -510,6 +584,8 @@ void r4k_helper_tlbwi(CPUMIPSState *env);
void r4k_helper_tlbwr(CPUMIPSState *env);
void r4k_helper_tlbp(CPUMIPSState *env);
void r4k_helper_tlbr(CPUMIPSState *env);
void r4k_helper_tlbinv(CPUMIPSState *env);
void r4k_helper_tlbinvf(CPUMIPSState *env);
void mips_cpu_unassigned_access(CPUState *cpu, hwaddr addr,
bool is_write, bool is_exec, int unused,
@@ -526,7 +602,7 @@ void mips_cpu_list (FILE *f, fprintf_function cpu_fprintf);
extern void cpu_wrdsp(uint32_t rs, uint32_t mask_num, CPUMIPSState *env);
extern uint32_t cpu_rddsp(uint32_t mask_num, CPUMIPSState *env);
#define CPU_SAVE_VERSION 4
#define CPU_SAVE_VERSION 5
/* MMU modes definitions. We carefully match the indices with our
hflags layout. */
@@ -628,8 +704,12 @@ enum {
EXCP_C2E,
EXCP_CACHE, /* 32 */
EXCP_DSPDIS,
EXCP_MSADIS,
EXCP_MSAFPE,
EXCP_TLBXI,
EXCP_TLBRI,
EXCP_LAST = EXCP_DSPDIS,
EXCP_LAST = EXCP_TLBRI,
};
/* Dummy exception for conditional stores. */
#define EXCP_SC 0x100
@@ -680,6 +760,10 @@ hwaddr cpu_mips_translate_address (CPUMIPSState *env, target_ulong address,
#endif
target_ulong exception_resume_pc (CPUMIPSState *env);
/* op_helper.c */
extern unsigned int ieee_rm[];
int ieee_ex_to_mips(int xcpt);
static inline void cpu_get_tb_cpu_state(CPUMIPSState *env, target_ulong *pc,
target_ulong *cs_base, int *flags)
{
@@ -726,7 +810,8 @@ static inline void compute_hflags(CPUMIPSState *env)
{
env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 |
MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU |
MIPS_HFLAG_AWRAP | MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2);
MIPS_HFLAG_AWRAP | MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2 |
MIPS_HFLAG_SBRI | MIPS_HFLAG_MSA);
if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
!(env->CP0_Status & (1 << CP0St_ERL)) &&
!(env->hflags & MIPS_HFLAG_DM)) {
@@ -752,7 +837,8 @@ static inline void compute_hflags(CPUMIPSState *env)
}
}
#endif
if ((env->CP0_Status & (1 << CP0St_CU0)) ||
if (((env->CP0_Status & (1 << CP0St_CU0)) &&
!(env->insn_flags & ISA_MIPS32R6)) ||
!(env->hflags & MIPS_HFLAG_KSU)) {
env->hflags |= MIPS_HFLAG_CP0;
}
@@ -762,6 +848,10 @@ static inline void compute_hflags(CPUMIPSState *env)
if (env->CP0_Status & (1 << CP0St_FR)) {
env->hflags |= MIPS_HFLAG_F64;
}
if (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_KM) &&
(env->CP0_Config5 & (1 << CP0C5_SBRI))) {
env->hflags |= MIPS_HFLAG_SBRI;
}
if (env->insn_flags & ASE_DSPR2) {
/* Enables access MIPS DSP resources, now our cpu is DSP ASER2,
so enable to access DSPR2 resources. */
@@ -794,6 +884,11 @@ static inline void compute_hflags(CPUMIPSState *env)
env->hflags |= MIPS_HFLAG_COP1X;
}
}
if (env->insn_flags & ASE_MSA) {
if (env->CP0_Config5 & (1 << CP0C5_MSAEn)) {
env->hflags |= MIPS_HFLAG_MSA;
}
}
}
#endif /* !defined (__MIPS_CPU_H__) */
-7
View File
@@ -73,13 +73,6 @@ int mips_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
return 0;
}
/* convert MIPS rounding mode in FCR31 to IEEE library */
static unsigned int ieee_rm[] = {
float_round_nearest_even,
float_round_to_zero,
float_round_up,
float_round_down
};
#define RESTORE_ROUNDING_MODE \
set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3], \
&env->active_fpu.fp_status)
+97 -17
View File
@@ -25,8 +25,11 @@
#include "cpu.h"
#include "sysemu/kvm.h"
#include "exec/cpu_ldst.h"
enum {
TLBRET_XI = -6,
TLBRET_RI = -5,
TLBRET_DIRTY = -4,
TLBRET_INVALID = -3,
TLBRET_NOMATCH = -2,
@@ -81,13 +84,20 @@ int r4k_map_address (CPUMIPSState *env, hwaddr *physical, int *prot,
#endif
/* Check ASID, virtual page number & size */
if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag && !tlb->EHINV) {
/* TLB match */
int n = !!(address & mask & ~(mask >> 1));
/* Check access rights */
if (!(n ? tlb->V1 : tlb->V0))
if (!(n ? tlb->V1 : tlb->V0)) {
return TLBRET_INVALID;
if (rw == 0 || (n ? tlb->D1 : tlb->D0)) {
}
if (rw == MMU_INST_FETCH && (n ? tlb->XI1 : tlb->XI0)) {
return TLBRET_XI;
}
if (rw == MMU_DATA_LOAD && (n ? tlb->RI1 : tlb->RI0)) {
return TLBRET_RI;
}
if (rw != MMU_DATA_STORE || (n ? tlb->D1 : tlb->D0)) {
*physical = tlb->PFN[n] | (address & (mask >> 1));
*prot = PAGE_READ;
if (n ? tlb->D1 : tlb->D0)
@@ -232,36 +242,58 @@ static void raise_mmu_exception(CPUMIPSState *env, target_ulong address,
CPUState *cs = CPU(mips_env_get_cpu(env));
int exception = 0, error_code = 0;
if (rw == MMU_INST_FETCH) {
error_code |= EXCP_INST_NOTAVAIL;
}
switch (tlb_error) {
default:
case TLBRET_BADADDR:
/* Reference to kernel address from user mode or supervisor mode */
/* Reference to supervisor address from user mode */
if (rw)
if (rw == MMU_DATA_STORE) {
exception = EXCP_AdES;
else
} else {
exception = EXCP_AdEL;
}
break;
case TLBRET_NOMATCH:
/* No TLB match for a mapped address */
if (rw)
if (rw == MMU_DATA_STORE) {
exception = EXCP_TLBS;
else
} else {
exception = EXCP_TLBL;
error_code = 1;
}
error_code |= EXCP_TLB_NOMATCH;
break;
case TLBRET_INVALID:
/* TLB match with no valid bit */
if (rw)
if (rw == MMU_DATA_STORE) {
exception = EXCP_TLBS;
else
} else {
exception = EXCP_TLBL;
}
break;
case TLBRET_DIRTY:
/* TLB match but 'D' bit is cleared */
exception = EXCP_LTLBL;
break;
case TLBRET_XI:
/* Execute-Inhibit Exception */
if (env->CP0_PageGrain & (1 << CP0PG_IEC)) {
exception = EXCP_TLBXI;
} else {
exception = EXCP_TLBL;
}
break;
case TLBRET_RI:
/* Read-Inhibit Exception */
if (env->CP0_PageGrain & (1 << CP0PG_IEC)) {
exception = EXCP_TLBRI;
} else {
exception = EXCP_TLBL;
}
break;
}
/* Raise exception */
env->CP0_BadVAddr = address;
@@ -312,8 +344,6 @@ int mips_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
qemu_log("%s pc " TARGET_FMT_lx " ad %" VADDR_PRIx " rw %d mmu_idx %d\n",
__func__, env->active_tc.PC, address, rw, mmu_idx);
rw &= 1;
/* data access */
#if !defined(CONFIG_USER_ONLY)
/* XXX: put correct access by using cpu_restore_state()
@@ -347,8 +377,6 @@ hwaddr cpu_mips_translate_address(CPUMIPSState *env, target_ulong address, int r
int access_type;
int ret = 0;
rw &= 1;
/* data access */
access_type = ACCESS_INT;
ret = get_physical_address(env, &physical, &prot,
@@ -396,6 +424,10 @@ static const char * const excp_names[EXCP_LAST + 1] = {
[EXCP_MDMX] = "MDMX",
[EXCP_C2E] = "precise coprocessor 2",
[EXCP_CACHE] = "cache error",
[EXCP_TLBXI] = "TLB execute-inhibit",
[EXCP_TLBRI] = "TLB read-inhibit",
[EXCP_MSADIS] = "MSA disabled",
[EXCP_MSAFPE] = "MSA floating point",
};
target_ulong exception_resume_pc (CPUMIPSState *env)
@@ -426,6 +458,21 @@ static void set_hflags_for_handler (CPUMIPSState *env)
<< MIPS_HFLAG_M16_SHIFT);
}
}
static inline void set_badinstr_registers(CPUMIPSState *env)
{
if (env->hflags & MIPS_HFLAG_M16) {
/* TODO: add BadInstr support for microMIPS */
return;
}
if (env->CP0_Config3 & (1 << CP0C3_BI)) {
env->CP0_BadInstr = cpu_ldl_code(env, env->active_tc.PC);
}
if ((env->CP0_Config3 & (1 << CP0C3_BP)) &&
(env->hflags & MIPS_HFLAG_BMASK)) {
env->CP0_BadInstrP = cpu_ldl_code(env, env->active_tc.PC - 4);
}
}
#endif
void mips_cpu_do_interrupt(CPUState *cs)
@@ -433,6 +480,7 @@ void mips_cpu_do_interrupt(CPUState *cs)
#if !defined(CONFIG_USER_ONLY)
MIPSCPU *cpu = MIPS_CPU(cs);
CPUMIPSState *env = &cpu->env;
bool update_badinstr = 0;
target_ulong offset;
int cause = -1;
const char *name;
@@ -541,10 +589,13 @@ void mips_cpu_do_interrupt(CPUState *cs)
goto set_EPC;
case EXCP_LTLBL:
cause = 1;
update_badinstr = !(env->error_code & EXCP_INST_NOTAVAIL);
goto set_EPC;
case EXCP_TLBL:
cause = 2;
if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL))) {
update_badinstr = !(env->error_code & EXCP_INST_NOTAVAIL);
if ((env->error_code & EXCP_TLB_NOMATCH) &&
!(env->CP0_Status & (1 << CP0St_EXL))) {
#if defined(TARGET_MIPS64)
int R = env->CP0_BadVAddr >> 62;
int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0;
@@ -561,7 +612,9 @@ void mips_cpu_do_interrupt(CPUState *cs)
goto set_EPC;
case EXCP_TLBS:
cause = 3;
if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL))) {
update_badinstr = 1;
if ((env->error_code & EXCP_TLB_NOMATCH) &&
!(env->CP0_Status & (1 << CP0St_EXL))) {
#if defined(TARGET_MIPS64)
int R = env->CP0_BadVAddr >> 62;
int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0;
@@ -578,9 +631,11 @@ void mips_cpu_do_interrupt(CPUState *cs)
goto set_EPC;
case EXCP_AdEL:
cause = 4;
update_badinstr = !(env->error_code & EXCP_INST_NOTAVAIL);
goto set_EPC;
case EXCP_AdES:
cause = 5;
update_badinstr = 1;
goto set_EPC;
case EXCP_IBE:
cause = 6;
@@ -590,30 +645,52 @@ void mips_cpu_do_interrupt(CPUState *cs)
goto set_EPC;
case EXCP_SYSCALL:
cause = 8;
update_badinstr = 1;
goto set_EPC;
case EXCP_BREAK:
cause = 9;
update_badinstr = 1;
goto set_EPC;
case EXCP_RI:
cause = 10;
update_badinstr = 1;
goto set_EPC;
case EXCP_CpU:
cause = 11;
update_badinstr = 1;
env->CP0_Cause = (env->CP0_Cause & ~(0x3 << CP0Ca_CE)) |
(env->error_code << CP0Ca_CE);
goto set_EPC;
case EXCP_OVERFLOW:
cause = 12;
update_badinstr = 1;
goto set_EPC;
case EXCP_TRAP:
cause = 13;
update_badinstr = 1;
goto set_EPC;
case EXCP_MSAFPE:
cause = 14;
update_badinstr = 1;
goto set_EPC;
case EXCP_FPE:
cause = 15;
update_badinstr = 1;
goto set_EPC;
case EXCP_C2E:
cause = 18;
goto set_EPC;
case EXCP_TLBRI:
cause = 19;
update_badinstr = 1;
goto set_EPC;
case EXCP_TLBXI:
cause = 20;
goto set_EPC;
case EXCP_MSADIS:
cause = 21;
update_badinstr = 1;
goto set_EPC;
case EXCP_MDMX:
cause = 22;
goto set_EPC;
@@ -640,6 +717,9 @@ void mips_cpu_do_interrupt(CPUState *cs)
set_EPC:
if (!(env->CP0_Status & (1 << CP0St_EXL))) {
env->CP0_EPC = exception_resume_pc(env);
if (update_badinstr) {
set_badinstr_registers(env);
}
if (env->hflags & MIPS_HFLAG_BMASK) {
env->CP0_Cause |= (1U << CP0Ca_BD);
} else {
+191
View File
@@ -152,6 +152,11 @@ DEF_HELPER_2(mtc0_datalo, void, env, tl)
DEF_HELPER_2(mtc0_taghi, void, env, tl)
DEF_HELPER_2(mtc0_datahi, void, env, tl)
#if defined(TARGET_MIPS64)
DEF_HELPER_2(dmtc0_entrylo0, void, env, i64)
DEF_HELPER_2(dmtc0_entrylo1, void, env, i64)
#endif
/* MIPS MT functions */
DEF_HELPER_2(mftgpr, tl, env, i32)
DEF_HELPER_2(mftlo, tl, env, i32)
@@ -337,6 +342,8 @@ DEF_HELPER_1(tlbwi, void, env)
DEF_HELPER_1(tlbwr, void, env)
DEF_HELPER_1(tlbp, void, env)
DEF_HELPER_1(tlbr, void, env)
DEF_HELPER_1(tlbinv, void, env)
DEF_HELPER_1(tlbinvf, void, env)
DEF_HELPER_1(di, tl, env)
DEF_HELPER_1(ei, tl, env)
DEF_HELPER_1(eret, void, env)
@@ -741,3 +748,187 @@ DEF_HELPER_FLAGS_3(dmthlip, 0, void, tl, tl, env)
#endif
DEF_HELPER_FLAGS_3(wrdsp, 0, void, tl, tl, env)
DEF_HELPER_FLAGS_2(rddsp, 0, tl, tl, env)
/* MIPS SIMD Architecture */
DEF_HELPER_4(msa_andi_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ori_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_nori_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_xori_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bmnzi_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bmzi_b, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bseli_b, void, env, i32, i32, i32)
DEF_HELPER_5(msa_shf_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_addvi_df, void, env, i32, i32, i32, s32)
DEF_HELPER_5(msa_subvi_df, void, env, i32, i32, i32, s32)
DEF_HELPER_5(msa_maxi_s_df, void, env, i32, i32, i32, s32)
DEF_HELPER_5(msa_maxi_u_df, void, env, i32, i32, i32, s32)
DEF_HELPER_5(msa_mini_s_df, void, env, i32, i32, i32, s32)
DEF_HELPER_5(msa_mini_u_df, void, env, i32, i32, i32, s32)
DEF_HELPER_5(msa_ceqi_df, void, env, i32, i32, i32, s32)
DEF_HELPER_5(msa_clti_s_df, void, env, i32, i32, i32, s32)
DEF_HELPER_5(msa_clti_u_df, void, env, i32, i32, i32, s32)
DEF_HELPER_5(msa_clei_s_df, void, env, i32, i32, i32, s32)
DEF_HELPER_5(msa_clei_u_df, void, env, i32, i32, i32, s32)
DEF_HELPER_4(msa_ldi_df, void, env, i32, i32, s32)
DEF_HELPER_5(msa_slli_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_srai_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_srli_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_bclri_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_bseti_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_bnegi_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_binsli_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_binsri_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_sat_s_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_sat_u_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_srari_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_srlri_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_sll_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_sra_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_srl_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_bclr_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_bset_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_bneg_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_binsl_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_binsr_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_addv_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_subv_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_max_s_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_max_u_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_min_s_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_min_u_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_max_a_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_min_a_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_ceq_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_clt_s_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_clt_u_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_cle_s_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_cle_u_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_add_a_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_adds_a_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_adds_s_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_adds_u_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_ave_s_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_ave_u_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_aver_s_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_aver_u_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_subs_s_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_subs_u_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_subsus_u_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_subsuu_s_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_asub_s_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_asub_u_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_mulv_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_maddv_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_msubv_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_div_s_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_div_u_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_mod_s_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_mod_u_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_dotp_s_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_dotp_u_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_dpadd_s_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_dpadd_u_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_dpsub_s_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_dpsub_u_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_sld_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_splat_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_pckev_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_pckod_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_ilvl_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_ilvr_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_ilvev_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_ilvod_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_vshf_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_srar_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_srlr_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_hadd_s_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_hadd_u_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_hsub_s_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_hsub_u_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_sldi_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_splati_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_copy_s_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_copy_u_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_insert_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_insve_df, void, env, i32, i32, i32, i32)
DEF_HELPER_3(msa_ctcmsa, void, env, tl, i32)
DEF_HELPER_2(msa_cfcmsa, tl, env, i32)
DEF_HELPER_3(msa_move_v, void, env, i32, i32)
DEF_HELPER_5(msa_fcaf_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fcun_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fceq_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fcueq_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fclt_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fcult_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fcle_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fcule_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsaf_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsun_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fseq_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsueq_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fslt_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsult_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsle_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsule_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fadd_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsub_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fmul_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fdiv_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fmadd_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fmsub_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fexp2_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fexdo_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_ftq_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fmin_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fmin_a_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fmax_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fmax_a_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fcor_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fcune_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fcne_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_mul_q_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_madd_q_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_msub_q_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsor_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsune_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_fsne_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_mulr_q_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_maddr_q_df, void, env, i32, i32, i32, i32)
DEF_HELPER_5(msa_msubr_q_df, void, env, i32, i32, i32, i32)
DEF_HELPER_4(msa_and_v, void, env, i32, i32, i32)
DEF_HELPER_4(msa_or_v, void, env, i32, i32, i32)
DEF_HELPER_4(msa_nor_v, void, env, i32, i32, i32)
DEF_HELPER_4(msa_xor_v, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bmnz_v, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bmz_v, void, env, i32, i32, i32)
DEF_HELPER_4(msa_bsel_v, void, env, i32, i32, i32)
DEF_HELPER_4(msa_fill_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_pcnt_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_nloc_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_nlzc_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_fclass_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ftrunc_s_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ftrunc_u_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_fsqrt_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_frsqrt_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_frcp_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_frint_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_flog2_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_fexupl_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_fexupr_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ffql_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ffqr_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ftint_s_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ftint_u_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ffint_s_df, void, env, i32, i32, i32)
DEF_HELPER_4(msa_ffint_u_df, void, env, i32, i32, i32)
DEF_HELPER_5(msa_ld_df, void, env, i32, i32, i32, s32)
DEF_HELPER_5(msa_st_df, void, env, i32, i32, i32, s32)
+25 -1
View File
@@ -61,7 +61,12 @@ void cpu_save(QEMUFile *f, void *opaque)
qemu_put_be32s(f, &env->tlb->nb_tlb);
qemu_put_be32s(f, &env->tlb->tlb_in_use);
for(i = 0; i < MIPS_TLB_MAX; i++) {
uint16_t flags = ((env->tlb->mmu.r4k.tlb[i].G << 10) |
uint16_t flags = ((env->tlb->mmu.r4k.tlb[i].EHINV << 15) |
(env->tlb->mmu.r4k.tlb[i].RI1 << 14) |
(env->tlb->mmu.r4k.tlb[i].RI0 << 13) |
(env->tlb->mmu.r4k.tlb[i].XI1 << 12) |
(env->tlb->mmu.r4k.tlb[i].XI0 << 11) |
(env->tlb->mmu.r4k.tlb[i].G << 10) |
(env->tlb->mmu.r4k.tlb[i].C0 << 7) |
(env->tlb->mmu.r4k.tlb[i].C1 << 4) |
(env->tlb->mmu.r4k.tlb[i].V0 << 3) |
@@ -111,6 +116,8 @@ void cpu_save(QEMUFile *f, void *opaque)
qemu_put_sbe32s(f, &env->CP0_SRSConf4);
qemu_put_sbe32s(f, &env->CP0_HWREna);
qemu_put_betls(f, &env->CP0_BadVAddr);
qemu_put_be32s(f, &env->CP0_BadInstr);
qemu_put_be32s(f, &env->CP0_BadInstrP);
qemu_put_sbe32s(f, &env->CP0_Count);
qemu_put_betls(f, &env->CP0_EntryHi);
qemu_put_sbe32s(f, &env->CP0_Compare);
@@ -144,6 +151,9 @@ void cpu_save(QEMUFile *f, void *opaque)
qemu_put_sbe32s(f, &env->CP0_DataHi);
qemu_put_betls(f, &env->CP0_ErrorEPC);
qemu_put_sbe32s(f, &env->CP0_DESAVE);
for (i = 0; i < MIPS_KSCRATCH_NUM; i++) {
qemu_put_betls(f, &env->CP0_KScratch[i]);
}
/* Save inactive TC state */
for (i = 0; i < MIPS_SHADOW_SET_MAX; i++)
@@ -232,6 +242,13 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
env->tlb->mmu.r4k.tlb[i].V1 = (flags >> 2) & 1;
env->tlb->mmu.r4k.tlb[i].D0 = (flags >> 1) & 1;
env->tlb->mmu.r4k.tlb[i].D1 = (flags >> 0) & 1;
if (version_id >= 5) {
env->tlb->mmu.r4k.tlb[i].EHINV = (flags >> 15) & 1;
env->tlb->mmu.r4k.tlb[i].RI1 = (flags >> 14) & 1;
env->tlb->mmu.r4k.tlb[i].RI0 = (flags >> 13) & 1;
env->tlb->mmu.r4k.tlb[i].XI1 = (flags >> 12) & 1;
env->tlb->mmu.r4k.tlb[i].XI0 = (flags >> 11) & 1;
}
qemu_get_betls(f, &env->tlb->mmu.r4k.tlb[i].PFN[0]);
qemu_get_betls(f, &env->tlb->mmu.r4k.tlb[i].PFN[1]);
}
@@ -301,6 +318,13 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
qemu_get_sbe32s(f, &env->CP0_DataHi);
qemu_get_betls(f, &env->CP0_ErrorEPC);
qemu_get_sbe32s(f, &env->CP0_DESAVE);
if (version_id >= 5) {
qemu_get_be32s(f, &env->CP0_BadInstr);
qemu_get_be32s(f, &env->CP0_BadInstrP);
for (i = 0; i < MIPS_KSCRATCH_NUM; i++) {
qemu_get_betls(f, &env->CP0_KScratch[i]);
}
}
/* Load inactive TC state */
for (i = 0; i < MIPS_SHADOW_SET_MAX; i++) {
+1
View File
@@ -45,6 +45,7 @@
#define ASE_MT 0x00200000
#define ASE_SMARTMIPS 0x00400000
#define ASE_MICROMIPS 0x00800000
#define ASE_MSA 0x01000000
/* Chip specific instructions. */
#define INSN_LOONGSON2E 0x20000000
File diff suppressed because it is too large Load Diff
+238 -34
View File
@@ -90,10 +90,10 @@ static inline type do_##name(CPUMIPSState *env, target_ulong addr, \
} \
}
#endif
HELPER_LD(lbu, ldub, uint8_t)
HELPER_LD(lhu, lduw, uint16_t)
HELPER_LD(lw, ldl, int32_t)
#ifdef TARGET_MIPS64
HELPER_LD(ld, ldq, int64_t)
#endif
#undef HELPER_LD
#if defined(CONFIG_USER_ONLY)
@@ -118,10 +118,9 @@ static inline void do_##name(CPUMIPSState *env, target_ulong addr, \
}
#endif
HELPER_ST(sb, stb, uint8_t)
HELPER_ST(sh, stw, uint16_t)
HELPER_ST(sw, stl, uint32_t)
#ifdef TARGET_MIPS64
HELPER_ST(sd, stq, uint64_t)
#endif
#undef HELPER_ST
target_ulong helper_clo (target_ulong arg1)
@@ -959,14 +958,14 @@ target_ulong helper_dmfc0_watchlo(CPUMIPSState *env, uint32_t sel)
void helper_mtc0_index(CPUMIPSState *env, target_ulong arg1)
{
int num = 1;
unsigned int tmp = env->tlb->nb_tlb;
do {
tmp >>= 1;
num <<= 1;
} while (tmp);
env->CP0_Index = (env->CP0_Index & 0x80000000) | (arg1 & (num - 1));
uint32_t index_p = env->CP0_Index & 0x80000000;
uint32_t tlb_index = arg1 & 0x7fffffff;
if (tlb_index < env->tlb->nb_tlb) {
if (env->insn_flags & ISA_MIPS32R6) {
index_p |= arg1 & 0x80000000;
}
env->CP0_Index = index_p | tlb_index;
}
}
void helper_mtc0_mvpcontrol(CPUMIPSState *env, target_ulong arg1)
@@ -1099,9 +1098,18 @@ void helper_mtc0_entrylo0(CPUMIPSState *env, target_ulong arg1)
{
/* Large physaddr (PABITS) not implemented */
/* 1k pages not implemented */
env->CP0_EntryLo0 = arg1 & 0x3FFFFFFF;
target_ulong rxi = arg1 & (env->CP0_PageGrain & (3u << CP0PG_XIE));
env->CP0_EntryLo0 = (arg1 & 0x3FFFFFFF) | (rxi << (CP0EnLo_XI - 30));
}
#if defined(TARGET_MIPS64)
void helper_dmtc0_entrylo0(CPUMIPSState *env, uint64_t arg1)
{
uint64_t rxi = arg1 & ((env->CP0_PageGrain & (3ull << CP0PG_XIE)) << 32);
env->CP0_EntryLo0 = (arg1 & 0x3FFFFFFF) | rxi;
}
#endif
void helper_mtc0_tcstatus(CPUMIPSState *env, target_ulong arg1)
{
uint32_t mask = env->CP0_TCStatus_rw_bitmask;
@@ -1266,9 +1274,18 @@ void helper_mtc0_entrylo1(CPUMIPSState *env, target_ulong arg1)
{
/* Large physaddr (PABITS) not implemented */
/* 1k pages not implemented */
env->CP0_EntryLo1 = arg1 & 0x3FFFFFFF;
target_ulong rxi = arg1 & (env->CP0_PageGrain & (3u << CP0PG_XIE));
env->CP0_EntryLo1 = (arg1 & 0x3FFFFFFF) | (rxi << (CP0EnLo_XI - 30));
}
#if defined(TARGET_MIPS64)
void helper_dmtc0_entrylo1(CPUMIPSState *env, uint64_t arg1)
{
uint64_t rxi = arg1 & ((env->CP0_PageGrain & (3ull << CP0PG_XIE)) << 32);
env->CP0_EntryLo1 = (arg1 & 0x3FFFFFFF) | rxi;
}
#endif
void helper_mtc0_context(CPUMIPSState *env, target_ulong arg1)
{
env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (arg1 & ~0x007FFFFF);
@@ -1276,8 +1293,13 @@ void helper_mtc0_context(CPUMIPSState *env, target_ulong arg1)
void helper_mtc0_pagemask(CPUMIPSState *env, target_ulong arg1)
{
/* 1k pages not implemented */
env->CP0_PageMask = arg1 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
uint64_t mask = arg1 >> (TARGET_PAGE_BITS + 1);
if (!(env->insn_flags & ISA_MIPS32R6) || (arg1 == ~0) ||
(mask == 0x0000 || mask == 0x0003 || mask == 0x000F ||
mask == 0x003F || mask == 0x00FF || mask == 0x03FF ||
mask == 0x0FFF || mask == 0x3FFF || mask == 0xFFFF)) {
env->CP0_PageMask = arg1 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
}
}
void helper_mtc0_pagegrain(CPUMIPSState *env, target_ulong arg1)
@@ -1285,12 +1307,19 @@ void helper_mtc0_pagegrain(CPUMIPSState *env, target_ulong arg1)
/* SmartMIPS not implemented */
/* Large physaddr (PABITS) not implemented */
/* 1k pages not implemented */
env->CP0_PageGrain = 0;
env->CP0_PageGrain = (arg1 & env->CP0_PageGrain_rw_bitmask) |
(env->CP0_PageGrain & ~env->CP0_PageGrain_rw_bitmask);
}
void helper_mtc0_wired(CPUMIPSState *env, target_ulong arg1)
{
env->CP0_Wired = arg1 % env->tlb->nb_tlb;
if (env->insn_flags & ISA_MIPS32R6) {
if (arg1 < env->tlb->nb_tlb) {
env->CP0_Wired = arg1;
}
} else {
env->CP0_Wired = arg1 % env->tlb->nb_tlb;
}
}
void helper_mtc0_srsconf0(CPUMIPSState *env, target_ulong arg1)
@@ -1342,14 +1371,28 @@ void helper_mtc0_count(CPUMIPSState *env, target_ulong arg1)
void helper_mtc0_entryhi(CPUMIPSState *env, target_ulong arg1)
{
target_ulong old, val;
target_ulong old, val, mask;
mask = (TARGET_PAGE_MASK << 1) | 0xFF;
if (((env->CP0_Config4 >> CP0C4_IE) & 0x3) >= 2) {
mask |= 1 << CP0EnHi_EHINV;
}
/* 1k pages not implemented */
val = arg1 & ((TARGET_PAGE_MASK << 1) | 0xFF);
#if defined(TARGET_MIPS64)
val &= env->SEGMask;
if (env->insn_flags & ISA_MIPS32R6) {
int entryhi_r = extract64(arg1, 62, 2);
int config0_at = extract32(env->CP0_Config0, 13, 2);
bool no_supervisor = (env->CP0_Status_rw_bitmask & 0x8) == 0;
if ((entryhi_r == 2) ||
(entryhi_r == 1 && (no_supervisor || config0_at == 1))) {
/* skip EntryHi.R field if new value is reserved */
mask &= ~(0x3ull << 62);
}
}
mask &= env->SEGMask;
#endif
old = env->CP0_EntryHi;
val = (arg1 & mask) | (old & ~mask);
env->CP0_EntryHi = val;
if (env->CP0_Config3 & (1 << CP0C3_MT)) {
sync_c0_entryhi(env, env->current_tc);
@@ -1379,6 +1422,13 @@ void helper_mtc0_status(CPUMIPSState *env, target_ulong arg1)
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;
@@ -1434,6 +1484,9 @@ static void mtc0_cause(CPUMIPSState *cpu, target_ulong arg1)
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);
@@ -1535,6 +1588,7 @@ void helper_mtc0_config5(CPUMIPSState *env, target_ulong arg1)
{
env->CP0_Config5 = (env->CP0_Config5 & (~env->CP0_Config5_rw_bitmask)) |
(arg1 & env->CP0_Config5_rw_bitmask);
compute_hflags(env);
}
void helper_mtc0_lladdr(CPUMIPSState *env, target_ulong arg1)
@@ -1839,6 +1893,11 @@ static void r4k_fill_tlb(CPUMIPSState *env, int idx)
/* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */
tlb = &env->tlb->mmu.r4k.tlb[idx];
if (env->CP0_EntryHi & (1 << CP0EnHi_EHINV)) {
tlb->EHINV = 1;
return;
}
tlb->EHINV = 0;
tlb->VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1);
#if defined(TARGET_MIPS64)
tlb->VPN &= env->SEGMask;
@@ -1849,13 +1908,42 @@ static void r4k_fill_tlb(CPUMIPSState *env, int idx)
tlb->V0 = (env->CP0_EntryLo0 & 2) != 0;
tlb->D0 = (env->CP0_EntryLo0 & 4) != 0;
tlb->C0 = (env->CP0_EntryLo0 >> 3) & 0x7;
tlb->XI0 = (env->CP0_EntryLo0 >> CP0EnLo_XI) & 1;
tlb->RI0 = (env->CP0_EntryLo0 >> CP0EnLo_RI) & 1;
tlb->PFN[0] = (env->CP0_EntryLo0 >> 6) << 12;
tlb->V1 = (env->CP0_EntryLo1 & 2) != 0;
tlb->D1 = (env->CP0_EntryLo1 & 4) != 0;
tlb->C1 = (env->CP0_EntryLo1 >> 3) & 0x7;
tlb->XI1 = (env->CP0_EntryLo1 >> CP0EnLo_XI) & 1;
tlb->RI1 = (env->CP0_EntryLo1 >> CP0EnLo_RI) & 1;
tlb->PFN[1] = (env->CP0_EntryLo1 >> 6) << 12;
}
void r4k_helper_tlbinv(CPUMIPSState *env)
{
int idx;
r4k_tlb_t *tlb;
uint8_t ASID = env->CP0_EntryHi & 0xFF;
for (idx = 0; idx < env->tlb->nb_tlb; idx++) {
tlb = &env->tlb->mmu.r4k.tlb[idx];
if (!tlb->G && tlb->ASID == ASID) {
tlb->EHINV = 1;
}
}
cpu_mips_tlb_flush(env, 1);
}
void r4k_helper_tlbinvf(CPUMIPSState *env)
{
int idx;
for (idx = 0; idx < env->tlb->nb_tlb; idx++) {
env->tlb->mmu.r4k.tlb[idx].EHINV = 1;
}
cpu_mips_tlb_flush(env, 1);
}
void r4k_helper_tlbwi(CPUMIPSState *env)
{
r4k_tlb_t *tlb;
@@ -1917,7 +2005,7 @@ void r4k_helper_tlbp(CPUMIPSState *env)
tag &= env->SEGMask;
#endif
/* Check ASID, virtual page number & size */
if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag && !tlb->EHINV) {
/* TLB match */
env->CP0_Index = i;
break;
@@ -1961,12 +2049,23 @@ void r4k_helper_tlbr(CPUMIPSState *env)
r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb);
env->CP0_EntryHi = tlb->VPN | tlb->ASID;
env->CP0_PageMask = tlb->PageMask;
env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) |
if (tlb->EHINV) {
env->CP0_EntryHi = 1 << CP0EnHi_EHINV;
env->CP0_PageMask = 0;
env->CP0_EntryLo0 = 0;
env->CP0_EntryLo1 = 0;
} else {
env->CP0_EntryHi = tlb->VPN | tlb->ASID;
env->CP0_PageMask = tlb->PageMask;
env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) |
((target_ulong)tlb->RI0 << CP0EnLo_RI) |
((target_ulong)tlb->XI0 << CP0EnLo_XI) |
(tlb->C0 << 3) | (tlb->PFN[0] >> 6);
env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) |
env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) |
((target_ulong)tlb->RI1 << CP0EnLo_RI) |
((target_ulong)tlb->XI1 << CP0EnLo_XI) |
(tlb->C1 << 3) | (tlb->PFN[1] >> 6);
}
}
void helper_tlbwi(CPUMIPSState *env)
@@ -1989,6 +2088,16 @@ void helper_tlbr(CPUMIPSState *env)
env->tlb->helper_tlbr(env);
}
void helper_tlbinv(CPUMIPSState *env)
{
env->tlb->helper_tlbinv(env);
}
void helper_tlbinvf(CPUMIPSState *env)
{
env->tlb->helper_tlbinvf(env);
}
/* Specials */
target_ulong helper_di(CPUMIPSState *env)
{
@@ -2160,13 +2269,26 @@ void helper_wait(CPUMIPSState *env)
#if !defined(CONFIG_USER_ONLY)
void mips_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
int is_write, int is_user, uintptr_t retaddr)
int access_type, int is_user,
uintptr_t retaddr)
{
MIPSCPU *cpu = MIPS_CPU(cs);
CPUMIPSState *env = &cpu->env;
int error_code = 0;
int excp;
env->CP0_BadVAddr = addr;
do_raise_exception(env, (is_write == 1) ? EXCP_AdES : EXCP_AdEL, retaddr);
if (access_type == MMU_DATA_STORE) {
excp = EXCP_AdES;
} else {
excp = EXCP_AdEL;
if (access_type == MMU_INST_FETCH) {
error_code |= EXCP_INST_NOTAVAIL;
}
}
do_raise_exception_err(env, excp, error_code, retaddr);
}
void tlb_fill(CPUState *cs, target_ulong addr, int is_write, int mmu_idx,
@@ -2217,7 +2339,7 @@ void mips_cpu_unassigned_access(CPUState *cs, hwaddr addr,
#define FP_TO_INT64_OVERFLOW 0x7fffffffffffffffULL
/* convert MIPS rounding mode in FCR31 to IEEE library */
static unsigned int ieee_rm[] = {
unsigned int ieee_rm[] = {
float_round_nearest_even,
float_round_to_zero,
float_round_up,
@@ -2300,8 +2422,9 @@ void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t fs, uint32_t rt)
}
break;
case 25:
if (arg1 & 0xffffff00)
if ((env->insn_flags & ISA_MIPS32R6) || (arg1 & 0xffffff00)) {
return;
}
env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0x017fffff) | ((arg1 & 0xfe) << 24) |
((arg1 & 0x1) << 23);
break;
@@ -2317,9 +2440,13 @@ void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t fs, uint32_t rt)
((arg1 & 0x4) << 22);
break;
case 31:
if (arg1 & 0x007c0000)
return;
env->active_fpu.fcr31 = arg1;
if (env->insn_flags & ISA_MIPS32R6) {
uint32_t mask = 0xfefc0000;
env->active_fpu.fcr31 = (arg1 & ~mask) |
(env->active_fpu.fcr31 & mask);
} else if (!(arg1 & 0x007c0000)) {
env->active_fpu.fcr31 = arg1;
}
break;
default:
return;
@@ -2333,7 +2460,7 @@ void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t fs, uint32_t rt)
do_raise_exception(env, EXCP_FPE, GETPC());
}
static inline int ieee_ex_to_mips(int xcpt)
int ieee_ex_to_mips(int xcpt)
{
int ret = 0;
if (xcpt) {
@@ -3498,3 +3625,80 @@ FOP_CONDN_S(sune, (float32_unordered(fst1, fst0, &env->active_fpu.fp_status)
|| float32_lt(fst0, fst1, &env->active_fpu.fp_status)))
FOP_CONDN_S(sne, (float32_lt(fst1, fst0, &env->active_fpu.fp_status)
|| float32_lt(fst0, fst1, &env->active_fpu.fp_status)))
/* MSA */
/* Data format min and max values */
#define DF_BITS(df) (1 << ((df) + 3))
/* Element-by-element access macros */
#define DF_ELEMENTS(df) (MSA_WRLEN / DF_BITS(df))
void helper_msa_ld_df(CPUMIPSState *env, uint32_t df, uint32_t wd, uint32_t rs,
int32_t s10)
{
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
target_ulong addr = env->active_tc.gpr[rs] + (s10 << df);
int i;
switch (df) {
case DF_BYTE:
for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) {
pwd->b[i] = do_lbu(env, addr + (i << DF_BYTE),
env->hflags & MIPS_HFLAG_KSU);
}
break;
case DF_HALF:
for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) {
pwd->h[i] = do_lhu(env, addr + (i << DF_HALF),
env->hflags & MIPS_HFLAG_KSU);
}
break;
case DF_WORD:
for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
pwd->w[i] = do_lw(env, addr + (i << DF_WORD),
env->hflags & MIPS_HFLAG_KSU);
}
break;
case DF_DOUBLE:
for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
pwd->d[i] = do_ld(env, addr + (i << DF_DOUBLE),
env->hflags & MIPS_HFLAG_KSU);
}
break;
}
}
void helper_msa_st_df(CPUMIPSState *env, uint32_t df, uint32_t wd, uint32_t rs,
int32_t s10)
{
wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
target_ulong addr = env->active_tc.gpr[rs] + (s10 << df);
int i;
switch (df) {
case DF_BYTE:
for (i = 0; i < DF_ELEMENTS(DF_BYTE); i++) {
do_sb(env, addr + (i << DF_BYTE), pwd->b[i],
env->hflags & MIPS_HFLAG_KSU);
}
break;
case DF_HALF:
for (i = 0; i < DF_ELEMENTS(DF_HALF); i++) {
do_sh(env, addr + (i << DF_HALF), pwd->h[i],
env->hflags & MIPS_HFLAG_KSU);
}
break;
case DF_WORD:
for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
do_sw(env, addr + (i << DF_WORD), pwd->w[i],
env->hflags & MIPS_HFLAG_KSU);
}
break;
case DF_DOUBLE:
for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
do_sd(env, addr + (i << DF_DOUBLE), pwd->d[i],
env->hflags & MIPS_HFLAG_KSU);
}
break;
}
}
+1996 -388
View File
File diff suppressed because it is too large Load Diff
+49 -4
View File
@@ -84,6 +84,7 @@ struct mips_def_t {
int32_t CP0_TCStatus_rw_bitmask;
int32_t CP0_SRSCtl;
int32_t CP1_fcr0;
int32_t MSAIR;
int32_t SEGBITS;
int32_t PABITS;
int32_t CP0_SRSConf0_rw_bitmask;
@@ -96,6 +97,8 @@ struct mips_def_t {
int32_t CP0_SRSConf3;
int32_t CP0_SRSConf4_rw_bitmask;
int32_t CP0_SRSConf4;
int32_t CP0_PageGrain_rw_bitmask;
int32_t CP0_PageGrain;
int insn_flags;
enum mips_mmu_types mmu_type;
};
@@ -355,7 +358,7 @@ static const mips_def_t mips_defs[] =
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) |
(1 << CP0C1_CA),
.CP0_Config2 = MIPS_CONFIG2,
.CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M),
.CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M) | (1 << CP0C3_MSAP),
.CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M),
.CP0_Config4_rw_bitmask = 0,
.CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_UFR),
@@ -373,7 +376,7 @@ static const mips_def_t mips_defs[] =
(0x93 << FCR0_PRID),
.SEGBITS = 32,
.PABITS = 32,
.insn_flags = CPU_MIPS32R5 | ASE_MIPS16 | ASE_DSP | ASE_DSPR2,
.insn_flags = CPU_MIPS32R5 | ASE_MIPS16 | ASE_DSP | ASE_DSPR2 | ASE_MSA,
.mmu_type = MMU_TYPE_R4000,
},
#if defined(TARGET_MIPS64)
@@ -517,7 +520,7 @@ static const mips_def_t mips_defs[] =
},
{
/* A generic CPU supporting MIPS64 Release 6 ISA.
FIXME: It does not support all the MIPS64R6 features yet.
FIXME: Support IEEE 754-2008 FP and misaligned memory accesses.
Eventually this should be replaced by a real CPU model. */
.name = "MIPS64R6-generic",
.CP0_PRid = 0x00010000,
@@ -528,12 +531,19 @@ static const mips_def_t mips_defs[] =
(2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) |
(0 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
.CP0_Config2 = MIPS_CONFIG2,
.CP0_Config3 = MIPS_CONFIG3,
.CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_RXI) | (1 << CP0C3_BP) |
(1 << CP0C3_BI) | (1 << CP0C3_ULRI) | (1U << CP0C3_M),
.CP0_Config4 = MIPS_CONFIG4 | (0xfc << CP0C4_KScrExist) |
(3 << CP0C4_IE) | (1 << CP0C4_M),
.CP0_Config5_rw_bitmask = (1 << CP0C5_SBRI),
.CP0_LLAddr_rw_bitmask = 0,
.CP0_LLAddr_shift = 0,
.SYNCI_Step = 32,
.CCRes = 2,
.CP0_Status_rw_bitmask = 0x30D8FFFF,
.CP0_PageGrain = (1 << CP0PG_IEC) | (1 << CP0PG_XIE) |
(1U << CP0PG_RIE),
.CP0_PageGrain_rw_bitmask = 0,
.CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
(1 << FCR0_D) | (1 << FCR0_S) | (0x00 << FCR0_PRID) |
(0x0 << FCR0_REV),
@@ -655,6 +665,8 @@ static void r4k_mmu_init (CPUMIPSState *env, const mips_def_t *def)
env->tlb->helper_tlbwr = r4k_helper_tlbwr;
env->tlb->helper_tlbp = r4k_helper_tlbp;
env->tlb->helper_tlbr = r4k_helper_tlbr;
env->tlb->helper_tlbinv = r4k_helper_tlbinv;
env->tlb->helper_tlbinvf = r4k_helper_tlbinvf;
}
static void mmu_init (CPUMIPSState *env, const mips_def_t *def)
@@ -718,3 +730,36 @@ static void mvp_init (CPUMIPSState *env, const mips_def_t *def)
(0x0 << CP0MVPC1_PCX) | (0x0 << CP0MVPC1_PCP2) |
(0x1 << CP0MVPC1_PCP1);
}
static void msa_reset(CPUMIPSState *env)
{
#ifdef CONFIG_USER_ONLY
/* MSA access enabled */
env->CP0_Config5 |= 1 << CP0C5_MSAEn;
env->CP0_Status |= (1 << CP0St_CU1) | (1 << CP0St_FR);
#endif
/* MSA CSR:
- non-signaling floating point exception mode off (NX bit is 0)
- Cause, Enables, and Flags are all 0
- round to nearest / ties to even (RM bits are 0) */
env->active_tc.msacsr = 0;
/* tininess detected after rounding.*/
set_float_detect_tininess(float_tininess_after_rounding,
&env->active_tc.msa_fp_status);
/* clear float_status exception flags */
set_float_exception_flags(0, &env->active_tc.msa_fp_status);
/* set float_status rounding mode */
set_float_rounding_mode(float_round_nearest_even,
&env->active_tc.msa_fp_status);
/* set float_status flush modes */
set_flush_to_zero(0, &env->active_tc.msa_fp_status);
set_flush_inputs_to_zero(0, &env->active_tc.msa_fp_status);
/* clear float_status nan mode */
set_default_nan_mode(0, &env->active_tc.msa_fp_status);
}