@@ -624,10 +624,80 @@ void riscv_itrigger_update_priv(CPURISCVState *env)
riscv_itrigger_update_count(env);
}
+static target_ulong itrigger_validate(CPURISCVState *env,
+ target_ulong ctrl)
+{
+ target_ulong val;
+
+ /* validate the generic part first */
+ val = tdata1_validate(env, ctrl, TRIGGER_TYPE_INST_CNT);
+
+ /* validate unimplemented (always zero) bits */
+ warn_always_zero_bit(ctrl, ITRIGGER_ACTION, "action");
+ warn_always_zero_bit(ctrl, ITRIGGER_HIT, "hit");
+ warn_always_zero_bit(ctrl, ITRIGGER_PENDING, "pending");
+
+ /* keep the mode and attribute bits */
+ val |= ctrl & (ITRIGGER_VU | ITRIGGER_VS | ITRIGGER_U | ITRIGGER_S |
+ ITRIGGER_M | ITRIGGER_COUNT);
+
+ return val;
+}
+
+static void itrigger_reg_write(CPURISCVState *env, target_ulong index,
+ int tdata_index, target_ulong val)
+{
+ target_ulong new_val;
+
+ switch (tdata_index) {
+ case TDATA1:
+ /* set timer for icount */
+ new_val = itrigger_validate(env, val);
+ if (new_val != env->tdata1[index]) {
+ env->tdata1[index] = new_val;
+ if (icount_enabled()) {
+ env->last_icount = icount_get_raw();
+ /* set the count to timer */
+ timer_mod(env->itrigger_timer[index],
+ env->last_icount + itrigger_get_count(env, index));
+ }
+ }
+ break;
+ case TDATA2:
+ qemu_log_mask(LOG_UNIMP,
+ "tdata2 is not supported for icount trigger\n");
+ break;
+ case TDATA3:
+ qemu_log_mask(LOG_UNIMP,
+ "tdata3 is not supported for icount trigger\n");
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ return;
+}
+
+static int itrigger_get_adjust_count(CPURISCVState *env)
+{
+ int count = itrigger_get_count(env, env->trigger_cur), executed;
+ if ((count != 0) && check_itrigger_priv(env, env->trigger_cur)) {
+ executed = icount_get_raw() - env->last_icount;
+ count += executed;
+ }
+ return count;
+}
+
target_ulong tdata_csr_read(CPURISCVState *env, int tdata_index)
{
+ int trigger_type;
switch (tdata_index) {
case TDATA1:
+ trigger_type = extract_trigger_type(env, env->tdata1[env->trigger_cur]);
+ if ((trigger_type == TRIGGER_TYPE_INST_CNT) && icount_enabled()) {
+ return deposit64(env->tdata1[env->trigger_cur], 10, 14,
+ itrigger_get_adjust_count(env));
+ }
return env->tdata1[env->trigger_cur];
case TDATA2:
return env->tdata2[env->trigger_cur];
@@ -656,6 +726,8 @@ void tdata_csr_write(CPURISCVState *env, int tdata_index, target_ulong val)
type6_reg_write(env, env->trigger_cur, tdata_index, val);
break;
case TRIGGER_TYPE_INST_CNT:
+ itrigger_reg_write(env, env->trigger_cur, tdata_index, val);
+ break;
case TRIGGER_TYPE_INT:
case TRIGGER_TYPE_EXCP:
case TRIGGER_TYPE_EXT_SRC: