MIPS queue October 2018, part1, v2
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJbyNNEAAoJENSXKoln91plgPMH/iHilm6MrW7r6tvJloYEBwfZ e8AkQzWcWq6rpWYhbiuGvWY2Qn1EWoTWFfohEvJ96gkJIZCVwO7sTqD2//58tksp wWpgeQwLxRCd+pB6zBMmYkpPD4WNEHGq7RYTzA+0pBIjwTEjdct0POgmLaiXBnFP mE5m6wohyAlxPpLLfluYEPz6cTIm20M191tv9scDoztKJnd/8u5M3j+yP8t2zbFs pRdOk68YsJl2fOKxgmnLsg83VxpoQahEzOgX1Zi396tcISZMCnuK+4GWJJ9MbPMl b1a9TdjHoNjx0v0qzNWk3RzECE7fBnnxpa8p1pil9Ff5MCq9gwFjxHvnCLZzY0s= =uRwj -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/amarkovic/tags/mips-queue-october-2018-part1-v2' into staging MIPS queue October 2018, part1, v2 # gpg: Signature made Thu 18 Oct 2018 19:39:00 BST # gpg: using RSA key D4972A8967F75A65 # gpg: Good signature from "Aleksandar Markovic <amarkovic@wavecomp.com>" # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 8526 FBF1 5DA3 811F 4A01 DD75 D497 2A89 67F7 5A65 * remotes/amarkovic/tags/mips-queue-october-2018-part1-v2: (28 commits) target/mips: Add opcodes for nanoMIPS EVA instructions target/mips: Fix misplaced 'break' in handling of NM_SHRA_R_PH target/mips: Fix emulation of microMIPS R6 <SELEQZ|SELNEZ>.<D|S> target/mips: Implement hardware page table walker for MIPS32 target/mips: Add reset state for PWSize and PWField registers target/mips: Add CP0 PWCtl register target/mips: Add CP0 PWSize register target/mips: Add CP0 PWField register target/mips: Add CP0 PWBase register target/mips: Add CP0 Config2 to DisasContext target/mips: Improve DSP R2/R3-related naming target/mips: Add availability control for DSP R3 ASE target/mips: Add bit definitions for DSP R3 ASE target/mips: Reorganize bit definitions for insn_flags (ISAs/ASEs flags) target/mips: Increase 'supported ISAs/ASEs' flag holder size target/mips: Add opcode values of MXU ASE target/mips: Add organizational chart of MXU ASE target/mips: Add assembler mnemonics list for MXU ASE target/mips: Add basic description of MXU ASE target/mips: Add a comment before each CP0 register section in cpu.h ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
2ec24af237
1
.mailmap
1
.mailmap
@ -12,6 +12,7 @@ Fabrice Bellard <fabrice@bellard.org> bellard <bellard@c046a42c-6fe2-441c-8c8c-7
|
||||
James Hogan <jhogan@kernel.org> <james.hogan@imgtec.com>
|
||||
Jocelyn Mayer <l_indien@magic.fr> j_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>
|
||||
Paul Brook <paul@codesourcery.com> pbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>
|
||||
Yongbok Kim <yongbok.kim@mips.com> <yongbok.kim@imgtec.com>
|
||||
Aleksandar Markovic <amarkovic@wavecomp.com> <aleksandar.markovic@mips.com>
|
||||
Aleksandar Markovic <amarkovic@wavecomp.com> <aleksandar.markovic@imgtec.com>
|
||||
Paul Burton <pburton@wavecomp.com> <paul.burton@mips.com>
|
||||
|
@ -28,8 +28,11 @@ typedef int64_t Elf64_Sxword;
|
||||
#define PT_PHDR 6
|
||||
#define PT_LOPROC 0x70000000
|
||||
#define PT_HIPROC 0x7fffffff
|
||||
#define PT_MIPS_REGINFO 0x70000000
|
||||
#define PT_MIPS_OPTIONS 0x70000001
|
||||
|
||||
#define PT_MIPS_REGINFO 0x70000000
|
||||
#define PT_MIPS_RTPROC 0x70000001
|
||||
#define PT_MIPS_OPTIONS 0x70000002
|
||||
#define PT_MIPS_ABIFLAGS 0x70000003
|
||||
|
||||
/* Flags in the e_flags field of the header */
|
||||
/* MIPS architecture level. */
|
||||
@ -76,14 +79,38 @@ typedef int64_t Elf64_Sxword;
|
||||
#define EF_MIPS_MACH_OCTEON2 0x008d0000 /* Cavium Networks Octeon2 */
|
||||
#define EF_MIPS_MACH_OCTEON3 0x008e0000 /* Cavium Networks Octeon3 */
|
||||
#define EF_MIPS_MACH_5400 0x00910000 /* NEC VR5400 */
|
||||
#define EF_MIPS_MACH_5900 0x00920000 /* MIPS R5900 */
|
||||
#define EF_MIPS_MACH_5900 0x00920000 /* Toshiba/Sony R5900 */
|
||||
#define EF_MIPS_MACH_5500 0x00980000 /* NEC VR5500 */
|
||||
#define EF_MIPS_MACH_9000 0x00990000 /* PMC-Sierra's RM9000 */
|
||||
#define EF_MIPS_MACH_9000 0x00990000 /* PMC-Sierra RM9000 */
|
||||
#define EF_MIPS_MACH_LS2E 0x00a00000 /* ST Microelectronics Loongson 2E */
|
||||
#define EF_MIPS_MACH_LS2F 0x00a10000 /* ST Microelectronics Loongson 2F */
|
||||
#define EF_MIPS_MACH_LS3A 0x00a20000 /* ST Microelectronics Loongson 3A */
|
||||
#define EF_MIPS_MACH 0x00ff0000 /* EF_MIPS_MACH_xxx selection mask */
|
||||
|
||||
#define MIPS_ABI_FP_ANY 0x0 /* FP ABI doesn't matter */
|
||||
#define MIPS_ABI_FP_DOUBLE 0x1 /* -mdouble-float */
|
||||
#define MIPS_ABI_FP_SINGLE 0x2 /* -msingle-float */
|
||||
#define MIPS_ABI_FP_SOFT 0x3 /* -msoft-float */
|
||||
#define MIPS_ABI_FP_OLD_64 0x4 /* -mips32r2 -mfp64 */
|
||||
#define MIPS_ABI_FP_XX 0x5 /* -mfpxx */
|
||||
#define MIPS_ABI_FP_64 0x6 /* -mips32r2 -mfp64 */
|
||||
#define MIPS_ABI_FP_64A 0x7 /* -mips32r2 -mfp64 -mno-odd-spreg */
|
||||
|
||||
typedef struct mips_elf_abiflags_v0 {
|
||||
uint16_t version; /* Version of flags structure */
|
||||
uint8_t isa_level; /* The level of the ISA: 1-5, 32, 64 */
|
||||
uint8_t isa_rev; /* The revision of ISA: */
|
||||
/* - 0 for MIPS V and below, */
|
||||
/* - 1-n otherwise. */
|
||||
uint8_t gpr_size; /* The size of general purpose registers */
|
||||
uint8_t cpr1_size; /* The size of co-processor 1 registers */
|
||||
uint8_t cpr2_size; /* The size of co-processor 2 registers */
|
||||
uint8_t fp_abi; /* The floating-point ABI */
|
||||
uint32_t isa_ext; /* Mask of processor-specific extensions */
|
||||
uint32_t ases; /* Mask of ASEs used */
|
||||
uint32_t flags1; /* Mask of general flags */
|
||||
uint32_t flags2;
|
||||
} Mips_elf_abiflags_v0;
|
||||
|
||||
/* These constants define the different elf file types */
|
||||
#define ET_NONE 0
|
||||
|
@ -244,4 +244,8 @@ static inline abi_ulong target_shmlba(CPUMIPSState *env)
|
||||
return 0x40000;
|
||||
}
|
||||
|
||||
/* MIPS-specific prctl() options */
|
||||
#define TARGET_PR_SET_FP_MODE 45
|
||||
#define TARGET_PR_GET_FP_MODE 46
|
||||
|
||||
#endif /* MIPS_TARGET_SYSCALL_H */
|
||||
|
@ -241,4 +241,8 @@ static inline abi_ulong target_shmlba(CPUMIPSState *env)
|
||||
return 0x40000;
|
||||
}
|
||||
|
||||
/* MIPS-specific prctl() options */
|
||||
#define TARGET_PR_SET_FP_MODE 45
|
||||
#define TARGET_PR_GET_FP_MODE 46
|
||||
|
||||
#endif /* MIPS64_TARGET_SYSCALL_H */
|
||||
|
@ -9347,6 +9347,14 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
#ifdef TARGET_MIPS
|
||||
case TARGET_PR_GET_FP_MODE:
|
||||
/* TODO: Implement TARGET_PR_SET_FP_MODE handling.*/
|
||||
return -TARGET_EINVAL;
|
||||
case TARGET_PR_SET_FP_MODE:
|
||||
/* TODO: Implement TARGET_PR_GET_FP_MODE handling.*/
|
||||
return -TARGET_EINVAL;
|
||||
#endif /* MIPS */
|
||||
#ifdef TARGET_AARCH64
|
||||
case TARGET_PR_SVE_SET_VL:
|
||||
/*
|
||||
|
@ -195,10 +195,125 @@ struct CPUMIPSState {
|
||||
#define MSAIR_ProcID 8
|
||||
#define MSAIR_Rev 0
|
||||
|
||||
/*
|
||||
* Summary of CP0 registers
|
||||
* ========================
|
||||
*
|
||||
*
|
||||
* Register 0 Register 1 Register 2 Register 3
|
||||
* ---------- ---------- ---------- ----------
|
||||
*
|
||||
* 0 Index Random EntryLo0 EntryLo1
|
||||
* 1 MVPControl VPEControl TCStatus GlobalNumber
|
||||
* 2 MVPConf0 VPEConf0 TCBind
|
||||
* 3 MVPConf1 VPEConf1 TCRestart
|
||||
* 4 VPControl YQMask TCHalt
|
||||
* 5 VPESchedule TCContext
|
||||
* 6 VPEScheFBack TCSchedule
|
||||
* 7 VPEOpt TCScheFBack TCOpt
|
||||
*
|
||||
*
|
||||
* Register 4 Register 5 Register 6 Register 7
|
||||
* ---------- ---------- ---------- ----------
|
||||
*
|
||||
* 0 Context PageMask Wired HWREna
|
||||
* 1 ContextConfig PageGrain SRSConf0
|
||||
* 2 UserLocal SegCtl0 SRSConf1
|
||||
* 3 XContextConfig SegCtl1 SRSConf2
|
||||
* 4 DebugContextID SegCtl2 SRSConf3
|
||||
* 5 MemoryMapID PWBase SRSConf4
|
||||
* 6 PWField PWCtl
|
||||
* 7 PWSize
|
||||
*
|
||||
*
|
||||
* Register 8 Register 9 Register 10 Register 11
|
||||
* ---------- ---------- ----------- -----------
|
||||
*
|
||||
* 0 BadVAddr Count EntryHi Compare
|
||||
* 1 BadInstr
|
||||
* 2 BadInstrP
|
||||
* 3 BadInstrX
|
||||
* 4 GuestCtl1 GuestCtl0Ext
|
||||
* 5 GuestCtl2
|
||||
* 6 GuestCtl3
|
||||
* 7
|
||||
*
|
||||
*
|
||||
* Register 12 Register 13 Register 14 Register 15
|
||||
* ----------- ----------- ----------- -----------
|
||||
*
|
||||
* 0 Status Cause EPC PRId
|
||||
* 1 IntCtl EBase
|
||||
* 2 SRSCtl NestedEPC CDMMBase
|
||||
* 3 SRSMap CMGCRBase
|
||||
* 4 View_IPL View_RIPL BEVVA
|
||||
* 5 SRSMap2 NestedExc
|
||||
* 6 GuestCtl0
|
||||
* 7 GTOffset
|
||||
*
|
||||
*
|
||||
* Register 16 Register 17 Register 18 Register 19
|
||||
* ----------- ----------- ----------- -----------
|
||||
*
|
||||
* 0 Config LLAddr WatchLo WatchHi
|
||||
* 1 Config1 MAAR WatchLo WatchHi
|
||||
* 2 Config2 MAARI WatchLo WatchHi
|
||||
* 3 Config3 WatchLo WatchHi
|
||||
* 4 Config4 WatchLo WatchHi
|
||||
* 5 Config5 WatchLo WatchHi
|
||||
* 6 WatchLo WatchHi
|
||||
* 7 WatchLo WatchHi
|
||||
*
|
||||
*
|
||||
* Register 20 Register 21 Register 22 Register 23
|
||||
* ----------- ----------- ----------- -----------
|
||||
*
|
||||
* 0 XContext Debug
|
||||
* 1 TraceControl
|
||||
* 2 TraceControl2
|
||||
* 3 UserTraceData1
|
||||
* 4 TraceIBPC
|
||||
* 5 TraceDBPC
|
||||
* 6 Debug2
|
||||
* 7
|
||||
*
|
||||
*
|
||||
* Register 24 Register 25 Register 26 Register 27
|
||||
* ----------- ----------- ----------- -----------
|
||||
*
|
||||
* 0 DEPC PerfCnt ErrCtl CacheErr
|
||||
* 1 PerfCnt
|
||||
* 2 TraceControl3 PerfCnt
|
||||
* 3 UserTraceData2 PerfCnt
|
||||
* 4 PerfCnt
|
||||
* 5 PerfCnt
|
||||
* 6 PerfCnt
|
||||
* 7 PerfCnt
|
||||
*
|
||||
*
|
||||
* Register 28 Register 29 Register 30 Register 31
|
||||
* ----------- ----------- ----------- -----------
|
||||
*
|
||||
* 0 DataLo DataHi ErrorEPC DESAVE
|
||||
* 1 TagLo TagHi
|
||||
* 2 DataLo DataHi KScratch<n>
|
||||
* 3 TagLo TagHi KScratch<n>
|
||||
* 4 DataLo DataHi KScratch<n>
|
||||
* 5 TagLo TagHi KScratch<n>
|
||||
* 6 DataLo DataHi KScratch<n>
|
||||
* 7 TagLo TagHi KScratch<n>
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* CP0 Register 0
|
||||
*/
|
||||
int32_t CP0_Index;
|
||||
/* CP0_MVP* are per MVP registers. */
|
||||
int32_t CP0_VPControl;
|
||||
#define CP0VPCtl_DIS 0
|
||||
/*
|
||||
* CP0 Register 1
|
||||
*/
|
||||
int32_t CP0_Random;
|
||||
int32_t CP0_VPEControl;
|
||||
#define CP0VPECo_YSI 21
|
||||
@ -239,7 +354,13 @@ struct CPUMIPSState {
|
||||
#define CP0VPEOpt_DWX2 2
|
||||
#define CP0VPEOpt_DWX1 1
|
||||
#define CP0VPEOpt_DWX0 0
|
||||
/*
|
||||
* CP0 Register 2
|
||||
*/
|
||||
uint64_t CP0_EntryLo0;
|
||||
/*
|
||||
* CP0 Register 3
|
||||
*/
|
||||
uint64_t CP0_EntryLo1;
|
||||
#if defined(TARGET_MIPS64)
|
||||
# define CP0EnLo_RI 63
|
||||
@ -250,8 +371,14 @@ struct CPUMIPSState {
|
||||
#endif
|
||||
int32_t CP0_GlobalNumber;
|
||||
#define CP0GN_VPId 0
|
||||
/*
|
||||
* CP0 Register 4
|
||||
*/
|
||||
target_ulong CP0_Context;
|
||||
target_ulong CP0_KScratch[MIPS_KSCRATCH_NUM];
|
||||
/*
|
||||
* CP0 Register 5
|
||||
*/
|
||||
int32_t CP0_PageMask;
|
||||
int32_t CP0_PageGrain_rw_bitmask;
|
||||
int32_t CP0_PageGrain;
|
||||
@ -289,7 +416,47 @@ struct CPUMIPSState {
|
||||
#define CP0SC2_XR 56
|
||||
#define CP0SC2_XR_MASK (0xFFULL << CP0SC2_XR)
|
||||
#define CP0SC2_MASK (CP0SC_1GMASK | (CP0SC_1GMASK << 16) | CP0SC2_XR_MASK)
|
||||
target_ulong CP0_PWBase;
|
||||
target_ulong CP0_PWField;
|
||||
#if defined(TARGET_MIPS64)
|
||||
#define CP0PF_BDI 32 /* 37..32 */
|
||||
#define CP0PF_GDI 24 /* 29..24 */
|
||||
#define CP0PF_UDI 18 /* 23..18 */
|
||||
#define CP0PF_MDI 12 /* 17..12 */
|
||||
#define CP0PF_PTI 6 /* 11..6 */
|
||||
#define CP0PF_PTEI 0 /* 5..0 */
|
||||
#else
|
||||
#define CP0PF_GDW 24 /* 29..24 */
|
||||
#define CP0PF_UDW 18 /* 23..18 */
|
||||
#define CP0PF_MDW 12 /* 17..12 */
|
||||
#define CP0PF_PTW 6 /* 11..6 */
|
||||
#define CP0PF_PTEW 0 /* 5..0 */
|
||||
#endif
|
||||
target_ulong CP0_PWSize;
|
||||
#if defined(TARGET_MIPS64)
|
||||
#define CP0PS_BDW 32 /* 37..32 */
|
||||
#endif
|
||||
#define CP0PS_PS 30
|
||||
#define CP0PS_GDW 24 /* 29..24 */
|
||||
#define CP0PS_UDW 18 /* 23..18 */
|
||||
#define CP0PS_MDW 12 /* 17..12 */
|
||||
#define CP0PS_PTW 6 /* 11..6 */
|
||||
#define CP0PS_PTEW 0 /* 5..0 */
|
||||
/*
|
||||
* CP0 Register 6
|
||||
*/
|
||||
int32_t CP0_Wired;
|
||||
int32_t CP0_PWCtl;
|
||||
#define CP0PC_PWEN 31
|
||||
#if defined(TARGET_MIPS64)
|
||||
#define CP0PC_PWDIREXT 30
|
||||
#define CP0PC_XK 28
|
||||
#define CP0PC_XS 27
|
||||
#define CP0PC_XU 26
|
||||
#endif
|
||||
#define CP0PC_DPH 7
|
||||
#define CP0PC_HUGEPG 6
|
||||
#define CP0PC_PSN 0 /* 5..0 */
|
||||
int32_t CP0_SRSConf0_rw_bitmask;
|
||||
int32_t CP0_SRSConf0;
|
||||
#define CP0SRSC0_M 31
|
||||
@ -319,16 +486,34 @@ struct CPUMIPSState {
|
||||
#define CP0SRSC4_SRS15 20
|
||||
#define CP0SRSC4_SRS14 10
|
||||
#define CP0SRSC4_SRS13 0
|
||||
/*
|
||||
* CP0 Register 7
|
||||
*/
|
||||
int32_t CP0_HWREna;
|
||||
/*
|
||||
* CP0 Register 8
|
||||
*/
|
||||
target_ulong CP0_BadVAddr;
|
||||
uint32_t CP0_BadInstr;
|
||||
uint32_t CP0_BadInstrP;
|
||||
uint32_t CP0_BadInstrX;
|
||||
/*
|
||||
* CP0 Register 9
|
||||
*/
|
||||
int32_t CP0_Count;
|
||||
/*
|
||||
* CP0 Register 10
|
||||
*/
|
||||
target_ulong CP0_EntryHi;
|
||||
#define CP0EnHi_EHINV 10
|
||||
target_ulong CP0_EntryHi_ASID_mask;
|
||||
/*
|
||||
* CP0 Register 11
|
||||
*/
|
||||
int32_t CP0_Compare;
|
||||
/*
|
||||
* CP0 Register 12
|
||||
*/
|
||||
int32_t CP0_Status;
|
||||
#define CP0St_CU3 31
|
||||
#define CP0St_CU2 30
|
||||
@ -370,6 +555,9 @@ struct CPUMIPSState {
|
||||
#define CP0SRSMap_SSV2 8
|
||||
#define CP0SRSMap_SSV1 4
|
||||
#define CP0SRSMap_SSV0 0
|
||||
/*
|
||||
* CP0 Register 13
|
||||
*/
|
||||
int32_t CP0_Cause;
|
||||
#define CP0Ca_BD 31
|
||||
#define CP0Ca_TI 30
|
||||
@ -381,12 +569,21 @@ struct CPUMIPSState {
|
||||
#define CP0Ca_IP 8
|
||||
#define CP0Ca_IP_mask 0x0000FF00
|
||||
#define CP0Ca_EC 2
|
||||
/*
|
||||
* CP0 Register 14
|
||||
*/
|
||||
target_ulong CP0_EPC;
|
||||
/*
|
||||
* CP0 Register 15
|
||||
*/
|
||||
int32_t CP0_PRid;
|
||||
target_ulong CP0_EBase;
|
||||
target_ulong CP0_EBaseWG_rw_bitmask;
|
||||
#define CP0EBase_WG 11
|
||||
target_ulong CP0_CMGCRBase;
|
||||
/*
|
||||
* CP0 Register 16
|
||||
*/
|
||||
int32_t CP0_Config0;
|
||||
#define CP0C0_M 31
|
||||
#define CP0C0_K23 28 /* 30..28 */
|
||||
@ -503,6 +700,9 @@ struct CPUMIPSState {
|
||||
uint64_t CP0_MAAR[MIPS_MAAR_MAX];
|
||||
int32_t CP0_MAARI;
|
||||
/* XXX: Maybe make LLAddr per-TC? */
|
||||
/*
|
||||
* CP0 Register 17
|
||||
*/
|
||||
uint64_t lladdr;
|
||||
target_ulong llval;
|
||||
target_ulong llnewval;
|
||||
@ -511,11 +711,23 @@ struct CPUMIPSState {
|
||||
target_ulong llreg;
|
||||
uint64_t CP0_LLAddr_rw_bitmask;
|
||||
int CP0_LLAddr_shift;
|
||||
/*
|
||||
* CP0 Register 18
|
||||
*/
|
||||
target_ulong CP0_WatchLo[8];
|
||||
/*
|
||||
* CP0 Register 19
|
||||
*/
|
||||
int32_t CP0_WatchHi[8];
|
||||
#define CP0WH_ASID 16
|
||||
/*
|
||||
* CP0 Register 20
|
||||
*/
|
||||
target_ulong CP0_XContext;
|
||||
int32_t CP0_Framemask;
|
||||
/*
|
||||
* CP0 Register 23
|
||||
*/
|
||||
int32_t CP0_Debug;
|
||||
#define CP0DB_DBD 31
|
||||
#define CP0DB_DM 30
|
||||
@ -535,18 +747,40 @@ struct CPUMIPSState {
|
||||
#define CP0DB_DDBL 2
|
||||
#define CP0DB_DBp 1
|
||||
#define CP0DB_DSS 0
|
||||
/*
|
||||
* CP0 Register 24
|
||||
*/
|
||||
target_ulong CP0_DEPC;
|
||||
/*
|
||||
* CP0 Register 25
|
||||
*/
|
||||
int32_t CP0_Performance0;
|
||||
/*
|
||||
* CP0 Register 26
|
||||
*/
|
||||
int32_t CP0_ErrCtl;
|
||||
#define CP0EC_WST 29
|
||||
#define CP0EC_SPR 28
|
||||
#define CP0EC_ITC 26
|
||||
/*
|
||||
* CP0 Register 28
|
||||
*/
|
||||
uint64_t CP0_TagLo;
|
||||
int32_t CP0_DataLo;
|
||||
/*
|
||||
* CP0 Register 29
|
||||
*/
|
||||
int32_t CP0_TagHi;
|
||||
int32_t CP0_DataHi;
|
||||
/*
|
||||
* CP0 Register 30
|
||||
*/
|
||||
target_ulong CP0_ErrorEPC;
|
||||
/*
|
||||
* CP0 Register 31
|
||||
*/
|
||||
int32_t CP0_DESAVE;
|
||||
|
||||
/* We waste some space so we can handle shadow registers like TCs. */
|
||||
TCState tcs[MIPS_SHADOW_SET_MAX];
|
||||
CPUMIPSFPUContext fpus[MIPS_FPU_MAX];
|
||||
@ -596,8 +830,9 @@ struct CPUMIPSState {
|
||||
#define MIPS_HFLAG_BX 0x40000 /* branch exchanges execution mode */
|
||||
#define MIPS_HFLAG_BMASK (MIPS_HFLAG_BMASK_BASE | MIPS_HFLAG_BMASK_EXT)
|
||||
/* MIPS DSP resources access. */
|
||||
#define MIPS_HFLAG_DSP 0x080000 /* Enable access to MIPS DSP resources. */
|
||||
#define MIPS_HFLAG_DSPR2 0x100000 /* Enable access to MIPS DSPR2 resources. */
|
||||
#define MIPS_HFLAG_DSP 0x080000 /* Enable access to DSP resources. */
|
||||
#define MIPS_HFLAG_DSP_R2 0x100000 /* Enable access to DSP R2 resources. */
|
||||
#define MIPS_HFLAG_DSP_R3 0x20000000 /* Enable access to DSP R3 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 */
|
||||
@ -614,7 +849,7 @@ struct CPUMIPSState {
|
||||
int CCRes; /* Cycle count resolution/divisor */
|
||||
uint32_t CP0_Status_rw_bitmask; /* Read/write bits in CP0_Status */
|
||||
uint32_t CP0_TCStatus_rw_bitmask; /* Read/write bits in CP0_TCStatus */
|
||||
int insn_flags; /* Supported instruction set */
|
||||
uint64_t insn_flags; /* Supported instruction set */
|
||||
|
||||
/* Fields up to this point are cleared by a CPU reset */
|
||||
struct {} end_reset_fields;
|
||||
|
@ -537,6 +537,342 @@ hwaddr mips_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
#if !defined(TARGET_MIPS64)
|
||||
|
||||
/*
|
||||
* Perform hardware page table walk
|
||||
*
|
||||
* Memory accesses are performed using the KERNEL privilege level.
|
||||
* Synchronous exceptions detected on memory accesses cause a silent exit
|
||||
* from page table walking, resulting in a TLB or XTLB Refill exception.
|
||||
*
|
||||
* Implementations are not required to support page table walk memory
|
||||
* accesses from mapped memory regions. When an unsupported access is
|
||||
* attempted, a silent exit is taken, resulting in a TLB or XTLB Refill
|
||||
* exception.
|
||||
*
|
||||
* Note that if an exception is caused by AddressTranslation or LoadMemory
|
||||
* functions, the exception is not taken, a silent exit is taken,
|
||||
* resulting in a TLB or XTLB Refill exception.
|
||||
*/
|
||||
|
||||
static bool get_pte(CPUMIPSState *env, uint64_t vaddr, int entry_size,
|
||||
uint64_t *pte)
|
||||
{
|
||||
if ((vaddr & ((entry_size >> 3) - 1)) != 0) {
|
||||
return false;
|
||||
}
|
||||
if (entry_size == 64) {
|
||||
*pte = cpu_ldq_code(env, vaddr);
|
||||
} else {
|
||||
*pte = cpu_ldl_code(env, vaddr);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint64_t get_tlb_entry_layout(CPUMIPSState *env, uint64_t entry,
|
||||
int entry_size, int ptei)
|
||||
{
|
||||
uint64_t result = entry;
|
||||
uint64_t rixi;
|
||||
if (ptei > entry_size) {
|
||||
ptei -= 32;
|
||||
}
|
||||
result >>= (ptei - 2);
|
||||
rixi = result & 3;
|
||||
result >>= 2;
|
||||
result |= rixi << CP0EnLo_XI;
|
||||
return result;
|
||||
}
|
||||
|
||||
static int walk_directory(CPUMIPSState *env, uint64_t *vaddr,
|
||||
int directory_index, bool *huge_page, bool *hgpg_directory_hit,
|
||||
uint64_t *pw_entrylo0, uint64_t *pw_entrylo1)
|
||||
{
|
||||
int dph = (env->CP0_PWCtl >> CP0PC_DPH) & 0x1;
|
||||
int psn = (env->CP0_PWCtl >> CP0PC_PSN) & 0x3F;
|
||||
int hugepg = (env->CP0_PWCtl >> CP0PC_HUGEPG) & 0x1;
|
||||
int pf_ptew = (env->CP0_PWField >> CP0PF_PTEW) & 0x3F;
|
||||
int ptew = (env->CP0_PWSize >> CP0PS_PTEW) & 0x3F;
|
||||
int native_shift = (((env->CP0_PWSize >> CP0PS_PS) & 1) == 0) ? 2 : 3;
|
||||
int directory_shift = (ptew > 1) ? -1 :
|
||||
(hugepg && (ptew == 1)) ? native_shift + 1 : native_shift;
|
||||
int leaf_shift = (ptew > 1) ? -1 :
|
||||
(ptew == 1) ? native_shift + 1 : native_shift;
|
||||
uint32_t direntry_size = 1 << (directory_shift + 3);
|
||||
uint32_t leafentry_size = 1 << (leaf_shift + 3);
|
||||
uint64_t entry;
|
||||
uint64_t paddr;
|
||||
int prot;
|
||||
uint64_t lsb = 0;
|
||||
uint64_t w = 0;
|
||||
|
||||
if (get_physical_address(env, &paddr, &prot, *vaddr, MMU_DATA_LOAD,
|
||||
ACCESS_INT, cpu_mmu_index(env, false)) !=
|
||||
TLBRET_MATCH) {
|
||||
/* wrong base address */
|
||||
return 0;
|
||||
}
|
||||
if (!get_pte(env, *vaddr, direntry_size, &entry)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((entry & (1 << psn)) && hugepg) {
|
||||
*huge_page = true;
|
||||
*hgpg_directory_hit = true;
|
||||
entry = get_tlb_entry_layout(env, entry, leafentry_size, pf_ptew);
|
||||
w = directory_index - 1;
|
||||
if (directory_index & 0x1) {
|
||||
/* Generate adjacent page from same PTE for odd TLB page */
|
||||
lsb = (1 << w) >> 6;
|
||||
*pw_entrylo0 = entry & ~lsb; /* even page */
|
||||
*pw_entrylo1 = entry | lsb; /* odd page */
|
||||
} else if (dph) {
|
||||
int oddpagebit = 1 << leaf_shift;
|
||||
uint64_t vaddr2 = *vaddr ^ oddpagebit;
|
||||
if (*vaddr & oddpagebit) {
|
||||
*pw_entrylo1 = entry;
|
||||
} else {
|
||||
*pw_entrylo0 = entry;
|
||||
}
|
||||
if (get_physical_address(env, &paddr, &prot, vaddr2, MMU_DATA_LOAD,
|
||||
ACCESS_INT, cpu_mmu_index(env, false)) !=
|
||||
TLBRET_MATCH) {
|
||||
return 0;
|
||||
}
|
||||
if (!get_pte(env, vaddr2, leafentry_size, &entry)) {
|
||||
return 0;
|
||||
}
|
||||
entry = get_tlb_entry_layout(env, entry, leafentry_size, pf_ptew);
|
||||
if (*vaddr & oddpagebit) {
|
||||
*pw_entrylo0 = entry;
|
||||
} else {
|
||||
*pw_entrylo1 = entry;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
} else {
|
||||
*vaddr = entry;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
static bool page_table_walk_refill(CPUMIPSState *env, vaddr address, int rw,
|
||||
int mmu_idx)
|
||||
{
|
||||
int gdw = (env->CP0_PWSize >> CP0PS_GDW) & 0x3F;
|
||||
int udw = (env->CP0_PWSize >> CP0PS_UDW) & 0x3F;
|
||||
int mdw = (env->CP0_PWSize >> CP0PS_MDW) & 0x3F;
|
||||
int ptw = (env->CP0_PWSize >> CP0PS_PTW) & 0x3F;
|
||||
int ptew = (env->CP0_PWSize >> CP0PS_PTEW) & 0x3F;
|
||||
|
||||
/* Initial values */
|
||||
bool huge_page = false;
|
||||
bool hgpg_bdhit = false;
|
||||
bool hgpg_gdhit = false;
|
||||
bool hgpg_udhit = false;
|
||||
bool hgpg_mdhit = false;
|
||||
|
||||
int32_t pw_pagemask = 0;
|
||||
target_ulong pw_entryhi = 0;
|
||||
uint64_t pw_entrylo0 = 0;
|
||||
uint64_t pw_entrylo1 = 0;
|
||||
|
||||
/* Native pointer size */
|
||||
/*For the 32-bit architectures, this bit is fixed to 0.*/
|
||||
int native_shift = (((env->CP0_PWSize >> CP0PS_PS) & 1) == 0) ? 2 : 3;
|
||||
|
||||
/* Indices from PWField */
|
||||
int pf_gdw = (env->CP0_PWField >> CP0PF_GDW) & 0x3F;
|
||||
int pf_udw = (env->CP0_PWField >> CP0PF_UDW) & 0x3F;
|
||||
int pf_mdw = (env->CP0_PWField >> CP0PF_MDW) & 0x3F;
|
||||
int pf_ptw = (env->CP0_PWField >> CP0PF_PTW) & 0x3F;
|
||||
int pf_ptew = (env->CP0_PWField >> CP0PF_PTEW) & 0x3F;
|
||||
|
||||
/* Indices computed from faulting address */
|
||||
int gindex = (address >> pf_gdw) & ((1 << gdw) - 1);
|
||||
int uindex = (address >> pf_udw) & ((1 << udw) - 1);
|
||||
int mindex = (address >> pf_mdw) & ((1 << mdw) - 1);
|
||||
int ptindex = (address >> pf_ptw) & ((1 << ptw) - 1);
|
||||
|
||||
/* Other HTW configs */
|
||||
int hugepg = (env->CP0_PWCtl >> CP0PC_HUGEPG) & 0x1;
|
||||
|
||||
/* HTW Shift values (depend on entry size) */
|
||||
int directory_shift = (ptew > 1) ? -1 :
|
||||
(hugepg && (ptew == 1)) ? native_shift + 1 : native_shift;
|
||||
int leaf_shift = (ptew > 1) ? -1 :
|
||||
(ptew == 1) ? native_shift + 1 : native_shift;
|
||||
|
||||
/* Offsets into tables */
|
||||
int goffset = gindex << directory_shift;
|
||||
int uoffset = uindex << directory_shift;
|
||||
int moffset = mindex << directory_shift;
|
||||
int ptoffset0 = (ptindex >> 1) << (leaf_shift + 1);
|
||||
int ptoffset1 = ptoffset0 | (1 << (leaf_shift));
|
||||
|
||||
uint32_t leafentry_size = 1 << (leaf_shift + 3);
|
||||
|
||||
/* Starting address - Page Table Base */
|
||||
uint64_t vaddr = env->CP0_PWBase;
|
||||
|
||||
uint64_t dir_entry;
|
||||
uint64_t paddr;
|
||||
int prot;
|
||||
int m;
|
||||
|
||||
if (!(env->CP0_Config3 & (1 << CP0C3_PW))) {
|
||||
/* walker is unimplemented */
|
||||
return false;
|
||||
}
|
||||
if (!(env->CP0_PWCtl & (1 << CP0PC_PWEN))) {
|
||||
/* walker is disabled */
|
||||
return false;
|
||||
}
|
||||
if (!(gdw > 0 || udw > 0 || mdw > 0)) {
|
||||
/* no structure to walk */
|
||||
return false;
|
||||
}
|
||||
if ((directory_shift == -1) || (leaf_shift == -1)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Global Directory */
|
||||
if (gdw > 0) {
|
||||
vaddr |= goffset;
|
||||
switch (walk_directory(env, &vaddr, pf_gdw, &huge_page, &hgpg_gdhit,
|
||||
&pw_entrylo0, &pw_entrylo1))
|
||||
{
|
||||
case 0:
|
||||
return false;
|
||||
case 1:
|
||||
goto refill;
|
||||
case 2:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Upper directory */
|
||||
if (udw > 0) {
|
||||
vaddr |= uoffset;
|
||||
switch (walk_directory(env, &vaddr, pf_udw, &huge_page, &hgpg_udhit,
|
||||
&pw_entrylo0, &pw_entrylo1))
|
||||
{
|
||||
case 0:
|
||||
return false;
|
||||
case 1:
|
||||
goto refill;
|
||||
case 2:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Middle directory */
|
||||
if (mdw > 0) {
|
||||
vaddr |= moffset;
|
||||
switch (walk_directory(env, &vaddr, pf_mdw, &huge_page, &hgpg_mdhit,
|
||||
&pw_entrylo0, &pw_entrylo1))
|
||||
{
|
||||
case 0:
|
||||
return false;
|
||||
case 1:
|
||||
goto refill;
|
||||
case 2:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Leaf Level Page Table - First half of PTE pair */
|
||||
vaddr |= ptoffset0;
|
||||
if (get_physical_address(env, &paddr, &prot, vaddr, MMU_DATA_LOAD,
|
||||
ACCESS_INT, cpu_mmu_index(env, false)) !=
|
||||
TLBRET_MATCH) {
|
||||
return false;
|
||||
}
|
||||
if (!get_pte(env, vaddr, leafentry_size, &dir_entry)) {
|
||||
return false;
|
||||
}
|
||||
dir_entry = get_tlb_entry_layout(env, dir_entry, leafentry_size, pf_ptew);
|
||||
pw_entrylo0 = dir_entry;
|
||||
|
||||
/* Leaf Level Page Table - Second half of PTE pair */
|
||||
vaddr |= ptoffset1;
|
||||
if (get_physical_address(env, &paddr, &prot, vaddr, MMU_DATA_LOAD,
|
||||
ACCESS_INT, cpu_mmu_index(env, false)) !=
|
||||
TLBRET_MATCH) {
|
||||
return false;
|
||||
}
|
||||
if (!get_pte(env, vaddr, leafentry_size, &dir_entry)) {
|
||||
return false;
|
||||
}
|
||||
dir_entry = get_tlb_entry_layout(env, dir_entry, leafentry_size, pf_ptew);
|
||||
pw_entrylo1 = dir_entry;
|
||||
|
||||
refill:
|
||||
|
||||
m = (1 << pf_ptw) - 1;
|
||||
|
||||
if (huge_page) {
|
||||
switch (hgpg_bdhit << 3 | hgpg_gdhit << 2 | hgpg_udhit << 1 |
|
||||
hgpg_mdhit)
|
||||
{
|
||||
case 4:
|
||||
m = (1 << pf_gdw) - 1;
|
||||
if (pf_gdw & 1) {
|
||||
m >>= 1;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
m = (1 << pf_udw) - 1;
|
||||
if (pf_udw & 1) {
|
||||
m >>= 1;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
m = (1 << pf_mdw) - 1;
|
||||
if (pf_mdw & 1) {
|
||||
m >>= 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
pw_pagemask = m >> 12;
|
||||
update_pagemask(env, pw_pagemask << 13, &pw_pagemask);
|
||||
pw_entryhi = (address & ~0x1fff) | (env->CP0_EntryHi & 0xFF);
|
||||
{
|
||||
target_ulong tmp_entryhi = env->CP0_EntryHi;
|
||||
int32_t tmp_pagemask = env->CP0_PageMask;
|
||||
uint64_t tmp_entrylo0 = env->CP0_EntryLo0;
|
||||
uint64_t tmp_entrylo1 = env->CP0_EntryLo1;
|
||||
|
||||
env->CP0_EntryHi = pw_entryhi;
|
||||
env->CP0_PageMask = pw_pagemask;
|
||||
env->CP0_EntryLo0 = pw_entrylo0;
|
||||
env->CP0_EntryLo1 = pw_entrylo1;
|
||||
|
||||
/*
|
||||
* The hardware page walker inserts a page into the TLB in a manner
|
||||
* identical to a TLBWR instruction as executed by the software refill
|
||||
* handler.
|
||||
*/
|
||||
r4k_helper_tlbwr(env);
|
||||
|
||||
env->CP0_EntryHi = tmp_entryhi;
|
||||
env->CP0_PageMask = tmp_pagemask;
|
||||
env->CP0_EntryLo0 = tmp_entrylo0;
|
||||
env->CP0_EntryLo1 = tmp_entrylo1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int mips_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
|
||||
int mmu_idx)
|
||||
{
|
||||
@ -558,8 +894,7 @@ int mips_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
|
||||
|
||||
/* data access */
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
/* XXX: put correct access by using cpu_restore_state()
|
||||
correctly */
|
||||
/* XXX: put correct access by using cpu_restore_state() correctly */
|
||||
access_type = ACCESS_INT;
|
||||
ret = get_physical_address(env, &physical, &prot,
|
||||
address, rw, access_type, mmu_idx);
|
||||
@ -583,6 +918,32 @@ int mips_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
|
||||
} else if (ret < 0)
|
||||
#endif
|
||||
{
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
#if !defined(TARGET_MIPS64)
|
||||
if ((ret == TLBRET_NOMATCH) && (env->tlb->nb_tlb > 1)) {
|
||||
/*
|
||||
* Memory reads during hardware page table walking are performed
|
||||
* as if they were kernel-mode load instructions.
|
||||
*/
|
||||
int mode = (env->hflags & MIPS_HFLAG_KSU);
|
||||
bool ret_walker;
|
||||
env->hflags &= ~MIPS_HFLAG_KSU;
|
||||
ret_walker = page_table_walk_refill(env, address, rw, mmu_idx);
|
||||
env->hflags |= mode;
|
||||
if (ret_walker) {
|
||||
ret = get_physical_address(env, &physical, &prot,
|
||||
address, rw, access_type, mmu_idx);
|
||||
if (ret == TLBRET_MATCH) {
|
||||
tlb_set_page(cs, address & TARGET_PAGE_MASK,
|
||||
physical & TARGET_PAGE_MASK, prot | PAGE_EXEC,
|
||||
mmu_idx, TARGET_PAGE_SIZE);
|
||||
ret = 0;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
raise_mmu_exception(env, address, rw, ret);
|
||||
ret = 1;
|
||||
}
|
||||
|
@ -120,6 +120,8 @@ DEF_HELPER_2(mtc0_pagegrain, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_segctl0, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_segctl1, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_segctl2, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_pwfield, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_pwsize, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_wired, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_srsconf0, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_srsconf1, void, env, tl)
|
||||
@ -127,6 +129,7 @@ DEF_HELPER_2(mtc0_srsconf2, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_srsconf3, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_srsconf4, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_hwrena, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_pwctl, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_count, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_entryhi, void, env, tl)
|
||||
DEF_HELPER_2(mttc0_entryhi, void, env, tl)
|
||||
|
@ -59,7 +59,7 @@ struct mips_def_t {
|
||||
int32_t CP0_PageGrain_rw_bitmask;
|
||||
int32_t CP0_PageGrain;
|
||||
target_ulong CP0_EBaseWG_rw_bitmask;
|
||||
int insn_flags;
|
||||
uint64_t insn_flags;
|
||||
enum mips_mmu_types mmu_type;
|
||||
};
|
||||
|
||||
@ -211,6 +211,7 @@ uint64_t float_class_d(uint64_t arg, float_status *fst);
|
||||
|
||||
extern unsigned int ieee_rm[];
|
||||
int ieee_ex_to_mips(int xcpt);
|
||||
void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask);
|
||||
|
||||
static inline void restore_rounding_mode(CPUMIPSState *env)
|
||||
{
|
||||
@ -306,9 +307,9 @@ 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_SBRI | MIPS_HFLAG_MSA | MIPS_HFLAG_FRE |
|
||||
MIPS_HFLAG_ELPA | MIPS_HFLAG_ERL);
|
||||
MIPS_HFLAG_AWRAP | MIPS_HFLAG_DSP | MIPS_HFLAG_DSP_R2 |
|
||||
MIPS_HFLAG_DSP_R3 | MIPS_HFLAG_SBRI | MIPS_HFLAG_MSA |
|
||||
MIPS_HFLAG_FRE | MIPS_HFLAG_ELPA | MIPS_HFLAG_ERL);
|
||||
if (env->CP0_Status & (1 << CP0St_ERL)) {
|
||||
env->hflags |= MIPS_HFLAG_ERL;
|
||||
}
|
||||
@ -355,16 +356,29 @@ static inline void compute_hflags(CPUMIPSState *env)
|
||||
(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. */
|
||||
if (env->insn_flags & ASE_DSP_R3) {
|
||||
/*
|
||||
* Our cpu supports DSP R3 ASE, so enable
|
||||
* access to DSP R3 resources.
|
||||
*/
|
||||
if (env->CP0_Status & (1 << CP0St_MX)) {
|
||||
env->hflags |= MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2;
|
||||
env->hflags |= MIPS_HFLAG_DSP | MIPS_HFLAG_DSP_R2 |
|
||||
MIPS_HFLAG_DSP_R3;
|
||||
}
|
||||
} else if (env->insn_flags & ASE_DSP_R2) {
|
||||
/*
|
||||
* Our cpu supports DSP R2 ASE, so enable
|
||||
* access to DSP R2 resources.
|
||||
*/
|
||||
if (env->CP0_Status & (1 << CP0St_MX)) {
|
||||
env->hflags |= MIPS_HFLAG_DSP | MIPS_HFLAG_DSP_R2;
|
||||
}
|
||||
|
||||
} else if (env->insn_flags & ASE_DSP) {
|
||||
/* Enables access MIPS DSP resources, now our cpu is DSP ASE,
|
||||
so enable to access DSP resources. */
|
||||
/*
|
||||
* Our cpu supports DSP ASE, so enable
|
||||
* access to DSP resources.
|
||||
*/
|
||||
if (env->CP0_Status & (1 << CP0St_MX)) {
|
||||
env->hflags |= MIPS_HFLAG_DSP;
|
||||
}
|
||||
|
@ -212,8 +212,8 @@ const VMStateDescription vmstate_tlb = {
|
||||
|
||||
const VMStateDescription vmstate_mips_cpu = {
|
||||
.name = "cpu",
|
||||
.version_id = 11,
|
||||
.minimum_version_id = 11,
|
||||
.version_id = 15,
|
||||
.minimum_version_id = 15,
|
||||
.post_load = cpu_post_load,
|
||||
.fields = (VMStateField[]) {
|
||||
/* Active TC */
|
||||
@ -256,7 +256,11 @@ const VMStateDescription vmstate_mips_cpu = {
|
||||
VMSTATE_UINTTL(env.CP0_SegCtl0, MIPSCPU),
|
||||
VMSTATE_UINTTL(env.CP0_SegCtl1, MIPSCPU),
|
||||
VMSTATE_UINTTL(env.CP0_SegCtl2, MIPSCPU),
|
||||
VMSTATE_UINTTL(env.CP0_PWBase, MIPSCPU),
|
||||
VMSTATE_UINTTL(env.CP0_PWField, MIPSCPU),
|
||||
VMSTATE_UINTTL(env.CP0_PWSize, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_Wired, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_PWCtl, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_SRSConf0, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_SRSConf1, MIPSCPU),
|
||||
VMSTATE_INT32(env.CP0_SRSConf2, MIPSCPU),
|
||||
|
@ -22,40 +22,51 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Masks used to mark instructions to indicate which ISA level they
|
||||
were introduced in. */
|
||||
#define ISA_MIPS1 0x00000001
|
||||
#define ISA_MIPS2 0x00000002
|
||||
#define ISA_MIPS3 0x00000004
|
||||
#define ISA_MIPS4 0x00000008
|
||||
#define ISA_MIPS5 0x00000010
|
||||
#define ISA_MIPS32 0x00000020
|
||||
#define ISA_MIPS32R2 0x00000040
|
||||
#define ISA_MIPS64 0x00000080
|
||||
#define ISA_MIPS64R2 0x00000100
|
||||
#define ISA_MIPS32R3 0x00000200
|
||||
#define ISA_MIPS64R3 0x00000400
|
||||
#define ISA_MIPS32R5 0x00000800
|
||||
#define ISA_MIPS64R5 0x00001000
|
||||
#define ISA_MIPS32R6 0x00002000
|
||||
#define ISA_MIPS64R6 0x00004000
|
||||
#define ISA_NANOMIPS32 0x00008000
|
||||
|
||||
/* MIPS ASEs. */
|
||||
#define ASE_MIPS16 0x00010000
|
||||
#define ASE_MIPS3D 0x00020000
|
||||
#define ASE_MDMX 0x00040000
|
||||
#define ASE_DSP 0x00080000
|
||||
#define ASE_DSPR2 0x00100000
|
||||
#define ASE_MT 0x00200000
|
||||
#define ASE_SMARTMIPS 0x00400000
|
||||
#define ASE_MICROMIPS 0x00800000
|
||||
#define ASE_MSA 0x01000000
|
||||
|
||||
/* Chip specific instructions. */
|
||||
#define INSN_LOONGSON2E 0x20000000
|
||||
#define INSN_LOONGSON2F 0x40000000
|
||||
#define INSN_VR54XX 0x80000000
|
||||
/*
|
||||
* bit definitions for insn_flags (ISAs/ASEs flags)
|
||||
* ------------------------------------------------
|
||||
*/
|
||||
/*
|
||||
* bits 0-31: MIPS base instruction sets
|
||||
*/
|
||||
#define ISA_MIPS1 0x0000000000000001ULL
|
||||
#define ISA_MIPS2 0x0000000000000002ULL
|
||||
#define ISA_MIPS3 0x0000000000000004ULL
|
||||
#define ISA_MIPS4 0x0000000000000008ULL
|
||||
#define ISA_MIPS5 0x0000000000000010ULL
|
||||
#define ISA_MIPS32 0x0000000000000020ULL
|
||||
#define ISA_MIPS32R2 0x0000000000000040ULL
|
||||
#define ISA_MIPS64 0x0000000000000080ULL
|
||||
#define ISA_MIPS64R2 0x0000000000000100ULL
|
||||
#define ISA_MIPS32R3 0x0000000000000200ULL
|
||||
#define ISA_MIPS64R3 0x0000000000000400ULL
|
||||
#define ISA_MIPS32R5 0x0000000000000800ULL
|
||||
#define ISA_MIPS64R5 0x0000000000001000ULL
|
||||
#define ISA_MIPS32R6 0x0000000000002000ULL
|
||||
#define ISA_MIPS64R6 0x0000000000004000ULL
|
||||
#define ISA_NANOMIPS32 0x0000000000008000ULL
|
||||
/*
|
||||
* bits 32-47: MIPS ASEs
|
||||
*/
|
||||
#define ASE_MIPS16 0x0000000100000000ULL
|
||||
#define ASE_MIPS3D 0x0000000200000000ULL
|
||||
#define ASE_MDMX 0x0000000400000000ULL
|
||||
#define ASE_DSP 0x0000000800000000ULL
|
||||
#define ASE_DSP_R2 0x0000001000000000ULL
|
||||
#define ASE_DSP_R3 0x0000002000000000ULL
|
||||
#define ASE_MT 0x0000004000000000ULL
|
||||
#define ASE_SMARTMIPS 0x0000008000000000ULL
|
||||
#define ASE_MICROMIPS 0x0000010000000000ULL
|
||||
#define ASE_MSA 0x0000020000000000ULL
|
||||
/*
|
||||
* bits 48-55: vendor-specific base instruction sets
|
||||
*/
|
||||
#define INSN_LOONGSON2E 0x0001000000000000ULL
|
||||
#define INSN_LOONGSON2F 0x0002000000000000ULL
|
||||
#define INSN_VR54XX 0x0004000000000000ULL
|
||||
/*
|
||||
* bits 56-63: vendor-specific ASEs
|
||||
*/
|
||||
|
||||
/* MIPS CPU defines. */
|
||||
#define CPU_MIPS1 (ISA_MIPS1)
|
||||
|
@ -1400,7 +1400,7 @@ void helper_mtc0_context(CPUMIPSState *env, target_ulong arg1)
|
||||
env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (arg1 & ~0x007FFFFF);
|
||||
}
|
||||
|
||||
void helper_mtc0_pagemask(CPUMIPSState *env, target_ulong arg1)
|
||||
void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask)
|
||||
{
|
||||
uint64_t mask = arg1 >> (TARGET_PAGE_BITS + 1);
|
||||
if (!(env->insn_flags & ISA_MIPS32R6) || (arg1 == ~0) ||
|
||||
@ -1411,6 +1411,11 @@ void helper_mtc0_pagemask(CPUMIPSState *env, target_ulong arg1)
|
||||
}
|
||||
}
|
||||
|
||||
void helper_mtc0_pagemask(CPUMIPSState *env, target_ulong arg1)
|
||||
{
|
||||
update_pagemask(env, arg1, &env->CP0_PageMask);
|
||||
}
|
||||
|
||||
void helper_mtc0_pagegrain(CPUMIPSState *env, target_ulong arg1)
|
||||
{
|
||||
/* SmartMIPS not implemented */
|
||||
@ -1445,6 +1450,77 @@ void helper_mtc0_segctl2(CPUMIPSState *env, target_ulong arg1)
|
||||
tlb_flush(cs);
|
||||
}
|
||||
|
||||
void helper_mtc0_pwfield(CPUMIPSState *env, target_ulong arg1)
|
||||
{
|
||||
#if defined(TARGET_MIPS64)
|
||||
uint64_t mask = 0x3F3FFFFFFFULL;
|
||||
uint32_t old_ptei = (env->CP0_PWField >> CP0PF_PTEI) & 0x3FULL;
|
||||
uint32_t new_ptei = (arg1 >> CP0PF_PTEI) & 0x3FULL;
|
||||
|
||||
if ((env->insn_flags & ISA_MIPS32R6)) {
|
||||
if (((arg1 >> CP0PF_BDI) & 0x3FULL) < 12) {
|
||||
mask &= ~(0x3FULL << CP0PF_BDI);
|
||||
}
|
||||
if (((arg1 >> CP0PF_GDI) & 0x3FULL) < 12) {
|
||||
mask &= ~(0x3FULL << CP0PF_GDI);
|
||||
}
|
||||
if (((arg1 >> CP0PF_UDI) & 0x3FULL) < 12) {
|
||||
mask &= ~(0x3FULL << CP0PF_UDI);
|
||||
}
|
||||
if (((arg1 >> CP0PF_MDI) & 0x3FULL) < 12) {
|
||||
mask &= ~(0x3FULL << CP0PF_MDI);
|
||||
}
|
||||
if (((arg1 >> CP0PF_PTI) & 0x3FULL) < 12) {
|
||||
mask &= ~(0x3FULL << CP0PF_PTI);
|
||||
}
|
||||
}
|
||||
env->CP0_PWField = arg1 & mask;
|
||||
|
||||
if ((new_ptei >= 32) ||
|
||||
((env->insn_flags & ISA_MIPS32R6) &&
|
||||
(new_ptei == 0 || new_ptei == 1))) {
|
||||
env->CP0_PWField = (env->CP0_PWField & ~0x3FULL) |
|
||||
(old_ptei << CP0PF_PTEI);
|
||||
}
|
||||
#else
|
||||
uint32_t mask = 0x3FFFFFFF;
|
||||
uint32_t old_ptew = (env->CP0_PWField >> CP0PF_PTEW) & 0x3F;
|
||||
uint32_t new_ptew = (arg1 >> CP0PF_PTEW) & 0x3F;
|
||||
|
||||
if ((env->insn_flags & ISA_MIPS32R6)) {
|
||||
if (((arg1 >> CP0PF_GDW) & 0x3F) < 12) {
|
||||
mask &= ~(0x3F << CP0PF_GDW);
|
||||
}
|
||||
if (((arg1 >> CP0PF_UDW) & 0x3F) < 12) {
|
||||
mask &= ~(0x3F << CP0PF_UDW);
|
||||
}
|
||||
if (((arg1 >> CP0PF_MDW) & 0x3F) < 12) {
|
||||
mask &= ~(0x3F << CP0PF_MDW);
|
||||
}
|
||||
if (((arg1 >> CP0PF_PTW) & 0x3F) < 12) {
|
||||
mask &= ~(0x3F << CP0PF_PTW);
|
||||
}
|
||||
}
|
||||
env->CP0_PWField = arg1 & mask;
|
||||
|
||||
if ((new_ptew >= 32) ||
|
||||
((env->insn_flags & ISA_MIPS32R6) &&
|
||||
(new_ptew == 0 || new_ptew == 1))) {
|
||||
env->CP0_PWField = (env->CP0_PWField & ~0x3F) |
|
||||
(old_ptew << CP0PF_PTEW);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void helper_mtc0_pwsize(CPUMIPSState *env, target_ulong arg1)
|
||||
{
|
||||
#if defined(TARGET_MIPS64)
|
||||
env->CP0_PWSize = arg1 & 0x3F7FFFFFFFULL;
|
||||
#else
|
||||
env->CP0_PWSize = arg1 & 0x3FFFFFFF;
|
||||
#endif
|
||||
}
|
||||
|
||||
void helper_mtc0_wired(CPUMIPSState *env, target_ulong arg1)
|
||||
{
|
||||
if (env->insn_flags & ISA_MIPS32R6) {
|
||||
@ -1456,6 +1532,16 @@ void helper_mtc0_wired(CPUMIPSState *env, target_ulong arg1)
|
||||
}
|
||||
}
|
||||
|
||||
void helper_mtc0_pwctl(CPUMIPSState *env, target_ulong arg1)
|
||||
{
|
||||
#if defined(TARGET_MIPS64)
|
||||
/* PWEn = 0. Hardware page table walking is not implemented. */
|
||||
env->CP0_PWCtl = (env->CP0_PWCtl & 0x000000C0) | (arg1 & 0x5C00003F);
|
||||
#else
|
||||
env->CP0_PWCtl = (arg1 & 0x800000FF);
|
||||
#endif
|
||||
}
|
||||
|
||||
void helper_mtc0_srsconf0(CPUMIPSState *env, target_ulong arg1)
|
||||
{
|
||||
env->CP0_SRSConf0 |= arg1 & env->CP0_SRSConf0_rw_bitmask;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -320,7 +320,7 @@ const mips_def_t mips_defs[] =
|
||||
.CP1_fcr31_rw_bitmask = 0xFF83FFFF,
|
||||
.SEGBITS = 32,
|
||||
.PABITS = 32,
|
||||
.insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP | ASE_DSPR2,
|
||||
.insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP | ASE_DSP_R2,
|
||||
.mmu_type = MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
@ -485,7 +485,8 @@ const mips_def_t mips_defs[] =
|
||||
.CP1_fcr31 = (1 << FCR31_ABS2008) | (1 << FCR31_NAN2008),
|
||||
.SEGBITS = 32,
|
||||
.PABITS = 32,
|
||||
.insn_flags = CPU_NANOMIPS32 | ASE_DSP | ASE_DSPR2 | ASE_MT,
|
||||
.insn_flags = CPU_NANOMIPS32 | ASE_DSP | ASE_DSP_R2 | ASE_DSP_R3 |
|
||||
ASE_MT,
|
||||
.mmu_type = MMU_TYPE_R4000,
|
||||
},
|
||||
#if defined(TARGET_MIPS64)
|
||||
@ -761,7 +762,7 @@ const mips_def_t mips_defs[] =
|
||||
.mmu_type = MMU_TYPE_R4000,
|
||||
},
|
||||
{
|
||||
/* A generic CPU providing MIPS64 ASE DSP 2 features.
|
||||
/* A generic CPU providing MIPS64 DSP R2 ASE features.
|
||||
FIXME: Eventually this should be replaced by a real CPU model. */
|
||||
.name = "mips64dspr2",
|
||||
.CP0_PRid = 0x00010000,
|
||||
@ -786,7 +787,7 @@ const mips_def_t mips_defs[] =
|
||||
.CP1_fcr31_rw_bitmask = 0xFF83FFFF,
|
||||
.SEGBITS = 42,
|
||||
.PABITS = 36,
|
||||
.insn_flags = CPU_MIPS64R2 | ASE_DSP | ASE_DSPR2,
|
||||
.insn_flags = CPU_MIPS64R2 | ASE_DSP | ASE_DSP_R2,
|
||||
.mmu_type = MMU_TYPE_R4000,
|
||||
},
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user