@@ -906,6 +906,16 @@ typedef enum RISCVException {
#define JVT_BASE (~0x3F)
/* Debug Sdtrig CSR masks */
+#define TEXTRA32_MHVALUE 0xFC000000
+#define TEXTRA32_MHSELECT 0x03800000
+#define TEXTRA32_SBYTEMASK 0x000C0000
+#define TEXTRA32_SVALUE 0x0003FFFC
+#define TEXTRA32_SSELECT 0x00000003
+#define TEXTRA64_MHVALUE 0xFFF8000000000000ULL
+#define TEXTRA64_MHSELECT 0x0007000000000000ULL
+#define TEXTRA64_SBYTEMASK 0x000000F000000000ULL
+#define TEXTRA64_SVALUE 0x00000003FFFFFFFCULL
+#define TEXTRA64_SSELECT 0x0000000000000003ULL
#define MCONTEXT32 0x0000003F
#define MCONTEXT64 0x0000000000001FFFULL
#define MCONTEXT32_HCONTEXT 0x0000007F
@@ -217,6 +217,66 @@ static inline void warn_always_zero_bit(target_ulong val, target_ulong mask,
}
}
+static target_ulong textra_validate(CPURISCVState *env, target_ulong tdata3)
+{
+ target_ulong mhvalue, mhselect;
+ target_ulong mhselect_new;
+ target_ulong textra;
+ const uint32_t mhselect_no_rvh[8] = { 0, 0, 0, 0, 4, 4, 4, 4 };
+
+ switch (riscv_cpu_mxl(env)) {
+ case MXL_RV32:
+ mhvalue = get_field(tdata3, TEXTRA32_MHVALUE);
+ mhselect = get_field(tdata3, TEXTRA32_MHSELECT);
+ /* Validate unimplemented (always zero) bits */
+ warn_always_zero_bit(tdata3, (target_ulong)TEXTRA32_SBYTEMASK,
+ "sbytemask");
+ warn_always_zero_bit(tdata3, (target_ulong)TEXTRA32_SVALUE,
+ "svalue");
+ warn_always_zero_bit(tdata3, (target_ulong)TEXTRA32_SSELECT,
+ "sselect");
+ break;
+ case MXL_RV64:
+ case MXL_RV128:
+ mhvalue = get_field(tdata3, TEXTRA64_MHVALUE);
+ mhselect = get_field(tdata3, TEXTRA64_MHSELECT);
+ /* Validate unimplemented (always zero) bits */
+ warn_always_zero_bit(tdata3, (target_ulong)TEXTRA64_SBYTEMASK,
+ "sbytemask");
+ warn_always_zero_bit(tdata3, (target_ulong)TEXTRA64_SVALUE,
+ "svalue");
+ warn_always_zero_bit(tdata3, (target_ulong)TEXTRA64_SSELECT,
+ "sselect");
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ /* Validate mhselect. */
+ mhselect_new = mhselect_no_rvh[mhselect];
+ if (mhselect != mhselect_new) {
+ qemu_log_mask(LOG_UNIMP, "mhselect only supports 0 or 4 for now\n");
+ }
+
+ /* Write legal values into textra */
+ textra = 0;
+ switch (riscv_cpu_mxl(env)) {
+ case MXL_RV32:
+ textra = set_field(textra, TEXTRA32_MHVALUE, mhvalue);
+ textra = set_field(textra, TEXTRA32_MHSELECT, mhselect_new);
+ break;
+ case MXL_RV64:
+ case MXL_RV128:
+ textra = set_field(textra, TEXTRA64_MHVALUE, mhvalue);
+ textra = set_field(textra, TEXTRA64_MHSELECT, mhselect_new);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ return textra;
+}
+
static void do_trigger_action(CPURISCVState *env, target_ulong trigger_index)
{
trigger_action_t action = get_trigger_action(env, trigger_index);
@@ -441,8 +501,7 @@ static void type2_reg_write(CPURISCVState *env, target_ulong index,
}
break;
case TDATA3:
- qemu_log_mask(LOG_UNIMP,
- "tdata3 is not supported for type 2 trigger\n");
+ env->tdata3[index] = textra_validate(env, val);
break;
default:
g_assert_not_reached();
@@ -558,8 +617,7 @@ static void type6_reg_write(CPURISCVState *env, target_ulong index,
}
break;
case TDATA3:
- qemu_log_mask(LOG_UNIMP,
- "tdata3 is not supported for type 6 trigger\n");
+ env->tdata3[index] = textra_validate(env, val);
break;
default:
g_assert_not_reached();
@@ -741,8 +799,7 @@ static void itrigger_reg_write(CPURISCVState *env, target_ulong index,
"tdata2 is not supported for icount trigger\n");
break;
case TDATA3:
- qemu_log_mask(LOG_UNIMP,
- "tdata3 is not supported for icount trigger\n");
+ env->tdata3[index] = textra_validate(env, val);
break;
default:
g_assert_not_reached();