@@ -55,11 +55,18 @@ void trigger_t::tdata3_write(processor_t * const proc, const reg_t val) noexcept
5555 sselect = (sselect_t )((proc->extension_enabled_const (' S' ) && get_field (val, CSR_TEXTRA_SSELECT (xlen)) <= SSELECT_MAXVAL) ? get_field (val, CSR_TEXTRA_SSELECT (xlen)) : SSELECT_IGNORE);
5656}
5757
58+ static reg_t tcontrol_value (const state_t * state) {
59+ if (state->tcontrol )
60+ return state->tcontrol ->read ();
61+ else
62+ return 0 ;
63+ }
64+
5865bool trigger_t::common_match (processor_t * const proc, bool use_prev_prv) const noexcept {
5966 auto state = proc->get_state ();
6067 auto prv = use_prev_prv ? state->prev_prv : state->prv ;
6168 auto v = use_prev_prv ? state->prev_v : state->v ;
62- auto m_enabled = get_action () != 0 || (state-> tcontrol -> read ( ) & CSR_TCONTROL_MTE);
69+ auto m_enabled = get_action () != 0 || (tcontrol_value (state ) & CSR_TCONTROL_MTE);
6370 return (prv < PRV_M || m_enabled) && mode_match (prv, v) && textra_match (proc);
6471}
6572
@@ -110,17 +117,29 @@ bool trigger_t::textra_match(processor_t * const proc) const noexcept
110117 return true ;
111118}
112119
113- bool trigger_t::allow_action (const state_t * const state ) const
120+ bool trigger_t::allow_action (processor_t * const proc ) const
114121{
122+ const state_t *state = proc->get_state ();
115123 if (get_action () == ACTION_DEBUG_EXCEPTION) {
116- const bool mstatus_mie = state->mstatus ->read () & MSTATUS_MIE;
117- const bool sstatus_sie = state->sstatus ->read () & MSTATUS_SIE;
118- const bool vsstatus_sie = state->vsstatus ->read () & MSTATUS_SIE;
119- const bool medeleg_breakpoint = (state->medeleg ->read () >> CAUSE_BREAKPOINT) & 1 ;
120- const bool hedeleg_breakpoint = (state->hedeleg ->read () >> CAUSE_BREAKPOINT) & 1 ;
121- return (state->prv != PRV_M || mstatus_mie) &&
122- (state->prv != PRV_S || state->v || !medeleg_breakpoint || sstatus_sie) &&
123- (state->prv != PRV_S || !state->v || !medeleg_breakpoint || !hedeleg_breakpoint || vsstatus_sie);
124+ if (proc->extension_enabled (' S' )) {
125+ // The hardware prevents triggers with action=0 from matching or firing
126+ // while in M-mode and while MIE in mstatus is 0. If medeleg [3]=1 then it
127+ // prevents triggers with action=0 from matching or firing while in S-mode
128+ // and while SIE in sstatus is 0. If medeleg [3]=1 and hedeleg [3]=1 then
129+ // it prevents triggers with action=0 from matching or firing while in
130+ // VS-mode and while SIE in vstatus is 0.
131+ const bool mstatus_mie = state->mstatus ->read () & MSTATUS_MIE;
132+ const bool sstatus_sie = state->sstatus ->read () & MSTATUS_SIE;
133+ const bool vsstatus_sie = state->vsstatus ->read () & MSTATUS_SIE;
134+ const bool medeleg_breakpoint = (state->medeleg ->read () >> CAUSE_BREAKPOINT) & 1 ;
135+ const bool hedeleg_breakpoint = (state->hedeleg ->read () >> CAUSE_BREAKPOINT) & 1 ;
136+ return (state->prv != PRV_M || mstatus_mie) &&
137+ (state->prv != PRV_S || state->v || !medeleg_breakpoint || sstatus_sie) &&
138+ (state->prv != PRV_S || !state->v || !medeleg_breakpoint || !hedeleg_breakpoint || vsstatus_sie);
139+ } else {
140+ // mte and mpte in tcontrol is implemented. medeleg [3] is hard-wired to 0.
141+ return (state->prv != PRV_M) || (tcontrol_value (state) & CSR_TCONTROL_MTE);
142+ }
124143 }
125144 return true ;
126145}
@@ -235,7 +254,7 @@ std::optional<match_result_t> mcontrol_common_t::detect_memory_access_match(proc
235254 value &= 0xffffffff ;
236255 }
237256
238- if (simple_match (xlen, value) && allow_action (proc-> get_state () )) {
257+ if (simple_match (xlen, value) && allow_action (proc)) {
239258 /* This is OK because this function is only called if the trigger was not
240259 * inhibited by the previous trigger in the chain. */
241260 set_hit (timing ? HIT_IMMEDIATELY_AFTER : HIT_BEFORE);
@@ -324,7 +343,7 @@ void mcontrol6_t::tdata1_write(processor_t * const proc, const reg_t val, const
324343
325344std::optional<match_result_t > icount_t::detect_icount_fire (processor_t * const proc) noexcept
326345{
327- if (!common_match (proc) || !allow_action (proc-> get_state () ))
346+ if (!common_match (proc) || !allow_action (proc))
328347 return std::nullopt ;
329348
330349 std::optional<match_result_t > ret = std::nullopt ;
@@ -339,7 +358,7 @@ std::optional<match_result_t> icount_t::detect_icount_fire(processor_t * const p
339358
340359void icount_t::detect_icount_decrement (processor_t * const proc) noexcept
341360{
342- if (!common_match (proc) || !allow_action (proc-> get_state () ))
361+ if (!common_match (proc) || !allow_action (proc))
343362 return ;
344363
345364 if (count >= 1 ) {
@@ -431,7 +450,7 @@ std::optional<match_result_t> trap_common_t::detect_trap_match(processor_t * con
431450 bool interrupt = (t.cause () & ((reg_t )1 << (xlen - 1 ))) != 0 ;
432451 reg_t bit = t.cause () & ~((reg_t )1 << (xlen - 1 ));
433452 assert (bit < xlen);
434- if (simple_match (interrupt, bit) && allow_action (proc-> get_state () )) {
453+ if (simple_match (interrupt, bit) && allow_action (proc)) {
435454 hit = true ;
436455 return match_result_t (TIMING_AFTER, action);
437456 }
0 commit comments