Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion arch/riscv/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
12 changes: 12 additions & 0 deletions arch/riscv/cpu_bits.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down
39 changes: 33 additions & 6 deletions arch/riscv/op_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down Expand Up @@ -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)) {
Expand Down Expand Up @@ -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)) {
Expand Down
71 changes: 39 additions & 32 deletions arch/riscv/vector_helper_template.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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)
Expand Down