@@ -55,12 +55,54 @@ 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);
63- return (prv < PRV_M || m_enabled) && mode_match (prv, v) && textra_match (proc);
69+
70+ if (!mode_match (prv, v))
71+ return false ;
72+
73+ if (!textra_match (proc))
74+ return false ;
75+
76+ if (get_action () == ACTION_DEBUG_EXCEPTION) {
77+ if (proc->extension_enabled (' S' )) {
78+ // The hardware prevents triggers with action=0 from matching or firing
79+ // while in M-mode and while MIE in mstatus is 0. If medeleg [3]=1 then it
80+ // prevents triggers with action=0 from matching or firing while in S-mode
81+ // and while SIE in sstatus is 0. If medeleg [3]=1 and hedeleg [3]=1 then
82+ // it prevents triggers with action=0 from matching or firing while in
83+ // VS-mode and while SIE in vstatus is 0.
84+
85+ const bool mstatus_mie = state->mstatus ->read () & MSTATUS_MIE;
86+ if (prv == PRV_M && !mstatus_mie)
87+ return false ;
88+
89+ const bool sstatus_sie = state->sstatus ->read () & MSTATUS_SIE;
90+ const bool medeleg_breakpoint = (state->medeleg ->read () >> CAUSE_BREAKPOINT) & 1 ;
91+ if (prv == PRV_S && !v && medeleg_breakpoint && !sstatus_sie)
92+ return false ;
93+
94+ const bool vsstatus_sie = state->vsstatus ->read () & MSTATUS_SIE;
95+ const bool hedeleg_breakpoint = (state->hedeleg ->read () >> CAUSE_BREAKPOINT) & 1 ;
96+ if (prv == PRV_S && v && medeleg_breakpoint && hedeleg_breakpoint && !vsstatus_sie)
97+ return false ;
98+ } else {
99+ // mte and mpte in tcontrol is implemented. medeleg [3] is hard-wired to 0.
100+ if (prv == PRV_M && !(tcontrol_value (state) & CSR_TCONTROL_MTE))
101+ return false ;
102+ }
103+ }
104+
105+ return true ;
64106}
65107
66108bool trigger_t::mode_match (reg_t prv, bool v) const noexcept
@@ -110,21 +152,6 @@ bool trigger_t::textra_match(processor_t * const proc) const noexcept
110152 return true ;
111153}
112154
113- bool trigger_t::allow_action (const state_t * const state) const
114- {
115- 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- }
125- return true ;
126- }
127-
128155reg_t disabled_trigger_t::tdata1_read (const processor_t * const proc) const noexcept
129156{
130157 auto xlen = proc->get_xlen ();
@@ -235,7 +262,7 @@ std::optional<match_result_t> mcontrol_common_t::detect_memory_access_match(proc
235262 value &= 0xffffffff ;
236263 }
237264
238- if (simple_match (xlen, value) && allow_action (proc-> get_state ()) ) {
265+ if (simple_match (xlen, value)) {
239266 /* This is OK because this function is only called if the trigger was not
240267 * inhibited by the previous trigger in the chain. */
241268 set_hit (timing ? HIT_IMMEDIATELY_AFTER : HIT_BEFORE);
@@ -324,7 +351,7 @@ void mcontrol6_t::tdata1_write(processor_t * const proc, const reg_t val, const
324351
325352std::optional<match_result_t > icount_t::detect_icount_fire (processor_t * const proc) noexcept
326353{
327- if (!common_match (proc) || ! allow_action (proc-> get_state ()) )
354+ if (!common_match (proc))
328355 return std::nullopt ;
329356
330357 std::optional<match_result_t > ret = std::nullopt ;
@@ -339,7 +366,7 @@ std::optional<match_result_t> icount_t::detect_icount_fire(processor_t * const p
339366
340367void icount_t::detect_icount_decrement (processor_t * const proc) noexcept
341368{
342- if (!common_match (proc) || ! allow_action (proc-> get_state ()) )
369+ if (!common_match (proc))
343370 return ;
344371
345372 if (count >= 1 ) {
@@ -431,7 +458,7 @@ std::optional<match_result_t> trap_common_t::detect_trap_match(processor_t * con
431458 bool interrupt = (t.cause () & ((reg_t )1 << (xlen - 1 ))) != 0 ;
432459 reg_t bit = t.cause () & ~((reg_t )1 << (xlen - 1 ));
433460 assert (bit < xlen);
434- if (simple_match (interrupt, bit) && allow_action (proc-> get_state ()) ) {
461+ if (simple_match (interrupt, bit)) {
435462 hit = true ;
436463 return match_result_t (TIMING_AFTER, action);
437464 }
0 commit comments