@@ -735,6 +735,8 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
void riscv_cpu_update_mask(CPURISCVState *env);
bool riscv_cpu_is_32bit(RISCVCPU *cpu);
+RISCVException riscv_csrr(CPURISCVState *env, int csrno,
+ target_ulong *ret_value);
RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
target_ulong *ret_value,
target_ulong new_value, target_ulong write_mask);
@@ -767,6 +769,8 @@ typedef RISCVException (*riscv_csr_op_fn)(CPURISCVState *env, int csrno,
target_ulong new_value,
target_ulong write_mask);
+RISCVException riscv_csrr_i128(CPURISCVState *env, int csrno,
+ Int128 *ret_value);
RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno,
Int128 *ret_value,
Int128 new_value, Int128 write_mask);
@@ -4368,7 +4368,7 @@ static RISCVException rmw_seed(CPURISCVState *env, int csrno,
static inline RISCVException riscv_csrrw_check(CPURISCVState *env,
int csrno,
- bool write_mask)
+ bool write)
{
/* check privileges and return RISCV_EXCP_ILLEGAL_INST if check fails */
bool read_only = get_field(csrno, 0xC00) == 3;
@@ -4390,7 +4390,7 @@ static inline RISCVException riscv_csrrw_check(CPURISCVState *env,
}
/* read / write check */
- if (write_mask && read_only) {
+ if (write && read_only) {
return RISCV_EXCP_ILLEGAL_INST;
}
@@ -4477,11 +4477,22 @@ static RISCVException riscv_csrrw_do64(CPURISCVState *env, int csrno,
return RISCV_EXCP_NONE;
}
+RISCVException riscv_csrr(CPURISCVState *env, int csrno,
+ target_ulong *ret_value)
+{
+ RISCVException ret = riscv_csrrw_check(env, csrno, false);
+ if (ret != RISCV_EXCP_NONE) {
+ return ret;
+ }
+
+ return riscv_csrrw_do64(env, csrno, ret_value, 0, 0);
+}
+
RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
target_ulong *ret_value,
target_ulong new_value, target_ulong write_mask)
{
- RISCVException ret = riscv_csrrw_check(env, csrno, write_mask);
+ RISCVException ret = riscv_csrrw_check(env, csrno, true);
if (ret != RISCV_EXCP_NONE) {
return ret;
}
@@ -4529,13 +4540,45 @@ static RISCVException riscv_csrrw_do128(CPURISCVState *env, int csrno,
return RISCV_EXCP_NONE;
}
+RISCVException riscv_csrr_i128(CPURISCVState *env, int csrno,
+ Int128 *ret_value)
+{
+ RISCVException ret;
+
+ ret = riscv_csrrw_check(env, csrno, false);
+ if (ret != RISCV_EXCP_NONE) {
+ return ret;
+ }
+
+ if (csr_ops[csrno].read128) {
+ return riscv_csrrw_do128(env, csrno, ret_value,
+ int128_zero(), int128_zero());
+ }
+
+ /*
+ * Fall back to 64-bit version for now, if the 128-bit alternative isn't
+ * at all defined.
+ * Note, some CSRs don't need to extend to MXLEN (64 upper bits non
+ * significant), for those, this fallback is correctly handling the
+ * accesses
+ */
+ target_ulong old_value;
+ ret = riscv_csrrw_do64(env, csrno, &old_value,
+ (target_ulong)0,
+ (target_ulong)0);
+ if (ret == RISCV_EXCP_NONE && ret_value) {
+ *ret_value = int128_make64(old_value);
+ }
+ return ret;
+}
+
RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno,
Int128 *ret_value,
Int128 new_value, Int128 write_mask)
{
RISCVException ret;
- ret = riscv_csrrw_check(env, csrno, int128_nz(write_mask));
+ ret = riscv_csrrw_check(env, csrno, true);
if (ret != RISCV_EXCP_NONE) {
return ret;
}
@@ -4574,7 +4617,11 @@ RISCVException riscv_csrrw_debug(CPURISCVState *env, int csrno,
#if !defined(CONFIG_USER_ONLY)
env->debugger = true;
#endif
- ret = riscv_csrrw(env, csrno, ret_value, new_value, write_mask);
+ if (!write_mask) {
+ ret = riscv_csrr(env, csrno, ret_value);
+ } else {
+ ret = riscv_csrrw(env, csrno, ret_value, new_value, write_mask);
+ }
#if !defined(CONFIG_USER_ONLY)
env->debugger = false;
#endif
@@ -51,7 +51,7 @@ target_ulong helper_csrr(CPURISCVState *env, int csr)
}
target_ulong val = 0;
- RISCVException ret = riscv_csrrw(env, csr, &val, 0, 0);
+ RISCVException ret = riscv_csrr(env, csr, &val);
if (ret != RISCV_EXCP_NONE) {
riscv_raise_exception(env, ret, GETPC());
@@ -84,9 +84,7 @@ target_ulong helper_csrrw(CPURISCVState *env, int csr,
target_ulong helper_csrr_i128(CPURISCVState *env, int csr)
{
Int128 rv = int128_zero();
- RISCVException ret = riscv_csrrw_i128(env, csr, &rv,
- int128_zero(),
- int128_zero());
+ RISCVException ret = riscv_csrr_i128(env, csr, &rv);
if (ret != RISCV_EXCP_NONE) {
riscv_raise_exception(env, ret, GETPC());