diff --git a/arch/riscv/cpu.h b/arch/riscv/cpu.h index 7b9c7240b..1885d03ac 100644 --- a/arch/riscv/cpu.h +++ b/arch/riscv/cpu.h @@ -137,7 +137,7 @@ struct CPUState { target_ulong vstart; target_ulong vxsat; target_ulong vxrm; - target_ulong vcsr; + target_ulong vcsr; /* This field is a cached view of VXRM and VXSAT. Remember to update them in sync. */ target_ulong vl; target_ulong vtype; target_ulong vlenb; diff --git a/arch/riscv/cpu_bits.h b/arch/riscv/cpu_bits.h index 5244f400f..336ec7a7a 100644 --- a/arch/riscv/cpu_bits.h +++ b/arch/riscv/cpu_bits.h @@ -312,6 +312,8 @@ #define MSTATUS_TSR 0x40000000 /* since: priv-1.10 */ #define MSTATUS_VS_INITIAL 0x00000600 +#define MSTATUS_VS_DIRTY 0x3 +#define MSTATUS_VS_OFF 0x0 #define MSTATUS_FS_INITIAL 0x00002000 #define MSTATUS_XS_INITIAL 0x00008000 @@ -402,6 +404,16 @@ #define MSECCFG_MMWP (1 << 1) #define MSECCFG_RLB (1 << 2) +/* vcsr bits */ +#define VXRM_MASK 0x3 +#define VXRM_VCSR_SHIFT 0x1 + +#define VXSAT_MASK 0x1 + +#define VCSR_VXSAT VXSAT_MASK /* starts at lsb */ +#define VCSR_VXRM (VXRM_MASK << VXRM_VCSR_SHIFT) +#define VCSR_MASK (VCSR_VXSAT | VCSR_VXRM) + /* sintthresh bits */ #define SINTTHRESH_TH 0x000000ff diff --git a/arch/riscv/op_helper.c b/arch/riscv/op_helper.c index fb898ab1a..ce3727e96 100644 --- a/arch/riscv/op_helper.c +++ b/arch/riscv/op_helper.c @@ -188,6 +188,13 @@ void helper_raise_illegal_instruction(CPUState *env) do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, 0, 1); } +static inline void validate_vector_state(CPUState *env) +{ + if(get_field(env->mstatus, MSTATUS_VS) == MSTATUS_VS_OFF) { + helper_raise_illegal_instruction(env); + } +} + static inline uint64_t get_minstret_current(CPUState *env) { if(env->privilege_architecture >= RISCV_PRIV1_11 && (env->mcountinhibit & MCOUNTINHIBIT_IR)) { @@ -734,16 +741,29 @@ inline void csr_write_helper(CPUState *env, target_ulong val_to_write, target_ul pmpaddr_csr_write(env, csrno - CSR_PMPADDR0, val_to_write); break; case CSR_VSTART: - env->vstart = val_to_write; + validate_vector_state(env); + target_ulong vstart_mask = (env->vlenb * 8) - 1; + env->vstart = val_to_write & vstart_mask; + env->mstatus = set_field(env->mstatus, MSTATUS_VS, MSTATUS_VS_DIRTY); break; case CSR_VXSAT: - env->vxsat = val_to_write; + validate_vector_state(env); + env->vxsat = val_to_write & VCSR_VXSAT; + env->vcsr = (env->vcsr & ~VCSR_VXSAT) | env->vxsat; + env->mstatus = set_field(env->mstatus, MSTATUS_VS, MSTATUS_VS_DIRTY); break; case CSR_VXRM: - env->vxrm = val_to_write; + validate_vector_state(env); + env->vxrm = val_to_write & VXRM_MASK; + env->vcsr = (env->vcsr & ~VCSR_VXRM) | ((env->vxrm & VXRM_MASK) << VXRM_VCSR_SHIFT); + env->mstatus = set_field(env->mstatus, MSTATUS_VS, MSTATUS_VS_DIRTY); break; case CSR_VCSR: - env->vcsr = val_to_write; + validate_vector_state(env); + env->vcsr = val_to_write & VCSR_MASK; + env->vxsat = env->vcsr & VCSR_VXSAT; + env->vxrm = (env->vcsr >> 1) & VXRM_MASK; + env->mstatus = set_field(env->mstatus, MSTATUS_VS, MSTATUS_VS_DIRTY); break; case CSR_MENVCFG: if(!riscv_has_ext(env, RISCV_FEATURE_RVU)) { @@ -1014,18 +1034,25 @@ static inline target_ulong csr_read_helper(CPUState *env, target_ulong csrno) case CSR_PMPADDR0 ... CSR_PMPADDR_LAST: return pmpaddr_csr_read(env, csrno - CSR_PMPADDR0); case CSR_VSTART: + validate_vector_state(env); return env->vstart; case CSR_VXSAT: - return env->vxsat; + validate_vector_state(env); + return env->vxsat & VXSAT_MASK; case CSR_VXRM: - return env->vxrm; + validate_vector_state(env); + return env->vxrm & VXRM_MASK; case CSR_VCSR: + validate_vector_state(env); return env->vcsr; case CSR_VL: + validate_vector_state(env); return env->vl; case CSR_VTYPE: + validate_vector_state(env); return env->vtype; case CSR_VLENB: + validate_vector_state(env); return env->vlenb; case CSR_SCOUNTOVF: if(!riscv_has_additional_ext(env, RISCV_FEATURE_SSCOFPMF)) { diff --git a/arch/riscv/vector_helper_template.h b/arch/riscv/vector_helper_template.h index 300526689..2fd46b757 100644 --- a/arch/riscv/vector_helper_template.h +++ b/arch/riscv/vector_helper_template.h @@ -133,6 +133,7 @@ static inline DATA_TYPE glue(clipto_u, BITS)(DATA_TYPE_DOUBLED val) { if(val > DATA_TYPE_MAX) { env->vxsat |= 1; + env->vcsr = (env->vcsr & ~VCSR_VXSAT) | env->vxsat; return DATA_TYPE_MAX; } return (DATA_TYPE)val; @@ -142,9 +143,11 @@ static inline DATA_STYPE glue(clipto_i, BITS)(DATA_STYPE_DOUBLED val) { if(val < DATA_STYPE_MIN) { env->vxsat |= 1; + env->vcsr = (env->vcsr & ~VCSR_VXSAT) | env->vxsat; return DATA_STYPE_MIN; } else if(val > DATA_STYPE_MAX) { env->vxsat |= 1; + env->vcsr = (env->vcsr & ~VCSR_VXSAT) | env->vxsat; return DATA_STYPE_MAX; } return (DATA_STYPE)val; @@ -1738,44 +1741,48 @@ void helper_vsm(CPUState *env, uint32_t vd, uint32_t rs1) #define SMAX(TYPE) (~(((TYPE)0) | (((TYPE)1) << ((sizeof(TYPE) << 3) - 1)))) -#define VOP_SADDU(A, B) \ - ({ \ - typeof(A) a = A; \ - typeof(a) b = B; \ - typeof(a) ab = a + b; \ - bool sat = ab < a; \ - env->vxsat |= sat; \ - sat ? ~0 : ab; \ +#define VOP_SADDU(A, B) \ + ({ \ + typeof(A) a = A; \ + typeof(a) b = B; \ + typeof(a) ab = a + b; \ + bool sat = ab < a; \ + env->vxsat |= sat; \ + env->vcsr = (env->vcsr & ~VCSR_VXSAT) | env->vxsat; \ + sat ? ~0 : ab; \ }) -#define VOP_SADD(A, B) \ - ({ \ - typeof(A) a = A; \ - typeof(a) b = B; \ - typeof(a) sat_value = SMAX(typeof(a)) + (a < 0); \ - bool sat = (a < 0) != (b > sat_value - a); \ - env->vxsat |= sat; \ - sat ? sat_value : a + b; \ +#define VOP_SADD(A, B) \ + ({ \ + typeof(A) a = A; \ + typeof(a) b = B; \ + typeof(a) sat_value = SMAX(typeof(a)) + (a < 0); \ + bool sat = (a < 0) != (b > sat_value - a); \ + env->vxsat |= sat; \ + env->vcsr = (env->vcsr & ~VCSR_VXSAT) | env->vxsat; \ + sat ? sat_value : a + b; \ }) -#define VOP_SSUBU(A, B) \ - ({ \ - typeof(A) a = A; \ - typeof(a) b = B; \ - bool sat = a < b; \ - env->vxsat |= sat; \ - sat ? 0 : a - b; \ +#define VOP_SSUBU(A, B) \ + ({ \ + typeof(A) a = A; \ + typeof(a) b = B; \ + bool sat = a < b; \ + env->vxsat |= sat; \ + env->vcsr = (env->vcsr & ~VCSR_VXSAT) | env->vxsat; \ + sat ? 0 : a - b; \ }) -#define VOP_SSUB(A, B) \ - ({ \ - typeof(A) a = A; \ - typeof(a) b = B; \ - typeof(a) result = a - b; \ - a = SMAX(typeof(a)) + (a < 0); \ - bool sat = ((a ^ b) & (a ^ result)) < 0; \ - env->vxsat |= sat; \ - sat ? a : result; \ +#define VOP_SSUB(A, B) \ + ({ \ + typeof(A) a = A; \ + typeof(a) b = B; \ + typeof(a) result = a - b; \ + a = SMAX(typeof(a)) + (a < 0); \ + bool sat = ((a ^ b) & (a ^ result)) < 0; \ + env->vxsat |= sat; \ + env->vcsr = (env->vcsr & ~VCSR_VXSAT) | env->vxsat; \ + sat ? a : result; \ }) VOP_UNSIGNED_VVX(vadd_ivi, OP_ADD)