diff options
Diffstat (limited to 'riscv')
-rw-r--r-- | riscv/triggers.cc | 21 | ||||
-rw-r--r-- | riscv/triggers.h | 1 |
2 files changed, 19 insertions, 3 deletions
diff --git a/riscv/triggers.cc b/riscv/triggers.cc index 07cd6bf..86dcc81 100644 --- a/riscv/triggers.cc +++ b/riscv/triggers.cc @@ -106,6 +106,21 @@ bool trigger_t::textra_match(processor_t * const proc) const noexcept return true; } +bool trigger_t::allow_action(const state_t * const state) const +{ + if (get_action() == ACTION_DEBUG_EXCEPTION) { + const bool mstatus_mie = state->mstatus->read() & MSTATUS_MIE; + const bool sstatus_sie = state->sstatus->read() & MSTATUS_SIE; + const bool vsstatus_sie = state->vsstatus->read() & MSTATUS_SIE; + const bool medeleg_breakpoint = (state->medeleg->read() >> CAUSE_BREAKPOINT) & 1; + const bool hedeleg_breakpoint = (state->hedeleg->read() >> CAUSE_BREAKPOINT) & 1; + return (state->prv != PRV_M || mstatus_mie) && + (state->prv != PRV_S || state->v || !medeleg_breakpoint || sstatus_sie) && + (state->prv != PRV_S || !state->v || !medeleg_breakpoint || !hedeleg_breakpoint || vsstatus_sie); + } + return true; +} + reg_t disabled_trigger_t::tdata1_read(const processor_t * const proc) const noexcept { auto xlen = proc->get_xlen(); @@ -212,7 +227,7 @@ std::optional<match_result_t> mcontrol_common_t::detect_memory_access_match(proc value &= 0xffffffff; } - if (simple_match(xlen, value)) { + if (simple_match(xlen, value) && allow_action(proc->get_state())) { /* This is OK because this function is only called if the trigger was not * inhibited by the previous trigger in the chain. */ hit = true; @@ -289,7 +304,7 @@ void mcontrol6_t::tdata1_write(processor_t * const proc, const reg_t val, const std::optional<match_result_t> icount_t::detect_icount_match(processor_t * const proc) noexcept { - if (!common_match(proc)) + if (!common_match(proc) || !allow_action(proc->get_state())) return std::nullopt; std::optional<match_result_t> ret = std::nullopt; @@ -389,7 +404,7 @@ std::optional<match_result_t> trap_common_t::detect_trap_match(processor_t * con bool interrupt = (t.cause() & ((reg_t)1 << (xlen - 1))) != 0; reg_t bit = t.cause() & ~((reg_t)1 << (xlen - 1)); assert(bit < xlen); - if (simple_match(interrupt, bit)) { + if (simple_match(interrupt, bit) && allow_action(proc->get_state())) { hit = true; return match_result_t(TIMING_AFTER, action); } diff --git a/riscv/triggers.h b/riscv/triggers.h index 0c9dabc..6e3d74d 100644 --- a/riscv/triggers.h +++ b/riscv/triggers.h @@ -90,6 +90,7 @@ public: protected: static action_t legalize_action(reg_t val, reg_t action_mask, reg_t dmode_mask) noexcept; bool common_match(processor_t * const proc) const noexcept; + bool allow_action(const state_t * const state) const; reg_t tdata2; bool vs = false; |