mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
target-mips: add Config5.FRE support allowing Status.FR=0 emulation
This relatively small architectural feature adds the following:
FIR.FREP: Read-only. If FREP=1, then Config5.FRE and Config5.UFE are
available.
Config5.FRE: When enabled all single-precision FP arithmetic instructions,
LWC1/LWXC1/MTC1, SWC1/SWXC1/MFC1 cause a Reserved Instructions
exception.
Config5.UFE: Allows user to write/read Config5.FRE using CTC1/CFC1
instructions.
Enable the feature in MIPS64R6-generic CPU.
Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
This commit is contained in:
+11
-2
@@ -100,6 +100,7 @@ struct CPUMIPSFPUContext {
|
||||
float_status fp_status;
|
||||
/* fpu implementation/revision register (fir) */
|
||||
uint32_t fcr0;
|
||||
#define FCR0_FREP 29
|
||||
#define FCR0_UFRP 28
|
||||
#define FCR0_F64 22
|
||||
#define FCR0_L 21
|
||||
@@ -462,6 +463,8 @@ struct CPUMIPSState {
|
||||
#define CP0C5_CV 29
|
||||
#define CP0C5_EVA 28
|
||||
#define CP0C5_MSAEn 27
|
||||
#define CP0C5_UFE 9
|
||||
#define CP0C5_FRE 8
|
||||
#define CP0C5_SBRI 6
|
||||
#define CP0C5_UFR 2
|
||||
#define CP0C5_NFExists 0
|
||||
@@ -514,7 +517,7 @@ struct CPUMIPSState {
|
||||
#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 0x15807FF
|
||||
#define MIPS_HFLAG_TMASK 0x35807FF
|
||||
#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
|
||||
@@ -561,6 +564,7 @@ struct CPUMIPSState {
|
||||
#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
|
||||
#define MIPS_HFLAG_FRE 0x2000000 /* FRE enabled */
|
||||
target_ulong btarget; /* Jump / branch target */
|
||||
target_ulong bcond; /* Branch condition (if needed) */
|
||||
|
||||
@@ -843,7 +847,7 @@ 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_SBRI | MIPS_HFLAG_MSA | MIPS_HFLAG_FRE);
|
||||
if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
|
||||
!(env->CP0_Status & (1 << CP0St_ERL)) &&
|
||||
!(env->hflags & MIPS_HFLAG_DM)) {
|
||||
@@ -924,6 +928,11 @@ static inline void compute_hflags(CPUMIPSState *env)
|
||||
env->hflags |= MIPS_HFLAG_MSA;
|
||||
}
|
||||
}
|
||||
if (env->active_fpu.fcr0 & (1 << FCR0_FREP)) {
|
||||
if (env->CP0_Config5 & (1 << CP0C5_FRE)) {
|
||||
env->hflags |= MIPS_HFLAG_FRE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
|
||||
@@ -2303,6 +2303,16 @@ target_ulong helper_cfc1(CPUMIPSState *env, uint32_t reg)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
/* FRE Support - read Config5.FRE bit */
|
||||
if (env->active_fpu.fcr0 & (1 << FCR0_FREP)) {
|
||||
if (env->CP0_Config5 & (1 << CP0C5_UFE)) {
|
||||
arg1 = (env->CP0_Config5 >> CP0C5_FRE) & 1;
|
||||
} else {
|
||||
helper_raise_exception(env, EXCP_RI);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 25:
|
||||
arg1 = ((env->active_fpu.fcr31 >> 24) & 0xfe) | ((env->active_fpu.fcr31 >> 23) & 0x1);
|
||||
break;
|
||||
@@ -2347,6 +2357,30 @@ void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t fs, uint32_t rt)
|
||||
helper_raise_exception(env, EXCP_RI);
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
/* FRE Support - clear Config5.FRE bit */
|
||||
if (!((env->active_fpu.fcr0 & (1 << FCR0_FREP)) && (rt == 0))) {
|
||||
return;
|
||||
}
|
||||
if (env->CP0_Config5 & (1 << CP0C5_UFE)) {
|
||||
env->CP0_Config5 &= ~(1 << CP0C5_FRE);
|
||||
compute_hflags(env);
|
||||
} else {
|
||||
helper_raise_exception(env, EXCP_RI);
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
/* FRE Support - set Config5.FRE bit */
|
||||
if (!((env->active_fpu.fcr0 & (1 << FCR0_FREP)) && (rt == 0))) {
|
||||
return;
|
||||
}
|
||||
if (env->CP0_Config5 & (1 << CP0C5_UFE)) {
|
||||
env->CP0_Config5 |= (1 << CP0C5_FRE);
|
||||
compute_hflags(env);
|
||||
} else {
|
||||
helper_raise_exception(env, EXCP_RI);
|
||||
}
|
||||
break;
|
||||
case 25:
|
||||
if ((env->insn_flags & ISA_MIPS32R6) || (arg1 & 0xffffff00)) {
|
||||
return;
|
||||
|
||||
+158
-150
File diff suppressed because it is too large
Load Diff
@@ -622,7 +622,8 @@ static const mips_def_t mips_defs[] =
|
||||
(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_Config5_rw_bitmask = (1 << CP0C5_SBRI) | (1 << CP0C5_FRE) |
|
||||
(1 << CP0C5_UFE),
|
||||
.CP0_LLAddr_rw_bitmask = 0,
|
||||
.CP0_LLAddr_shift = 0,
|
||||
.SYNCI_Step = 32,
|
||||
@@ -631,9 +632,9 @@ static const mips_def_t mips_defs[] =
|
||||
.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),
|
||||
.CP1_fcr0 = (1 << FCR0_FREP) | (1 << FCR0_F64) | (1 << FCR0_L) |
|
||||
(1 << FCR0_W) | (1 << FCR0_D) | (1 << FCR0_S) |
|
||||
(0x00 << FCR0_PRID) | (0x0 << FCR0_REV),
|
||||
.SEGBITS = 42,
|
||||
/* The architectural limit is 59, but we have hardcoded 36 bit
|
||||
in some places...
|
||||
|
||||
Reference in New Issue
Block a user