#define DCSR_XDEBUGVER (3U<<30)
#define DCSR_NDRESET (1<<29)
#define DCSR_FULLRESET (1<<28)
-#define DCSR_HWBPCOUNT (0xfff<<16)
#define DCSR_EBREAKM (1<<15)
#define DCSR_EBREAKH (1<<14)
#define DCSR_EBREAKS (1<<13)
#define DCSR_CAUSE_STEP 4
#define DCSR_CAUSE_HALT 5
+#define MCONTROL_TYPE(xlen) (0xfULL<<((xlen)-4))
+#define MCONTROL_DMODE(xlen) (1ULL<<((xlen)-5))
+#define MCONTROL_MASKMAX(xlen) (0x3fULL<<((xlen)-11))
+
#define MCONTROL_SELECT (1<<19)
-#define MCONTROL_ACTION (0x7f<<12)
+#define MCONTROL_TIMING (1<<18)
+#define MCONTROL_ACTION (0x3f<<12)
#define MCONTROL_CHAIN (1<<11)
#define MCONTROL_MATCH (0xf<<7)
#define MCONTROL_M (1<<6)
#define MCONTROL_STORE (1<<1)
#define MCONTROL_LOAD (1<<0)
-#define MCONTROL_ACTION_NONE 0
-#define MCONTROL_ACTION_DEBUG_EXCEPTION 1
-#define MCONTROL_ACTION_DEBUG_MODE 2
-#define MCONTROL_ACTION_TRACE_START 3
-#define MCONTROL_ACTION_TRACE_STOP 4
-#define MCONTROL_ACTION_TRACE_EMIT 5
+#define MCONTROL_ACTION_DEBUG_EXCEPTION 0
+#define MCONTROL_ACTION_DEBUG_MODE 1
+#define MCONTROL_ACTION_TRACE_START 2
+#define MCONTROL_ACTION_TRACE_STOP 3
+#define MCONTROL_ACTION_TRACE_EMIT 4
-#define MCONTROL_MATCH_EQUAL 0
-#define MCONTROL_MATCH_NAPOT 1
-#define MCONTROL_MATCH_GE 2
-#define MCONTROL_MATCH_LT 3
-#define MCONTROL_MATCH_MASK_LOW 4
-#define MCONTROL_MATCH_MASK_HIGH 5
+#define MCONTROL_MATCH_EQUAL 0
+#define MCONTROL_MATCH_NAPOT 1
+#define MCONTROL_MATCH_GE 2
+#define MCONTROL_MATCH_LT 3
+#define MCONTROL_MATCH_MASK_LOW 4
+#define MCONTROL_MATCH_MASK_HIGH 5
#define MIP_SSIP (1 << IRQ_S_SOFT)
#define MIP_HSIP (1 << IRQ_H_SOFT)
#define EXT_IO_BASE 0x40000000
#define DRAM_BASE 0x80000000
-// breakpoint control fields
-#define BPCONTROL_X 0x00000001
-#define BPCONTROL_W 0x00000002
-#define BPCONTROL_R 0x00000004
-#define BPCONTROL_U 0x00000008
-#define BPCONTROL_S 0x00000010
-#define BPCONTROL_H 0x00000020
-#define BPCONTROL_M 0x00000040
-#define BPCONTROL_BPMATCH 0x00000780
-#ifdef __riscv64
-# define BPCONTROL_BPAMASKMAX 0x0F80000000000000
-# define BPCONTROL_TDRTYPE 0xF000000000000000
-#else
-# define BPCONTROL_BPAMASKMAX 0x0F800000
-# define BPCONTROL_TDRTYPE 0xF0000000
-#endif
-
// page table entry (PTE) fields
#define PTE_V 0x001 // Valid
#define PTE_R 0x002 // Read
delete mmu->matched_trigger;
mmu->matched_trigger = NULL;
}
- assert(state.mcontrol[t.index].action != ACTION_NONE);
switch (state.mcontrol[t.index].action) {
case ACTION_DEBUG_MODE:
enter_debug_mode(DCSR_CAUSE_HWBP);
break;
+ case ACTION_DEBUG_EXCEPTION: {
+ mem_trap_t trap(CAUSE_BREAKPOINT, t.address);
+ take_trap(trap, pc);
+ break;
+ }
default:
- assert(0);
+ abort();
}
}
}
if (type == 2 &&
- get_field(mcontrol, MCONTROL_ACTION) == MCONTROL_ACTION_NONE) {
+ !get_field(mcontrol, MCONTROL_EXECUTE) &&
+ !get_field(mcontrol, MCONTROL_LOAD) &&
+ !get_field(mcontrol, MCONTROL_STORE)) {
// Found an unused trigger.
gs.dr_write_load(0, S0, SLOT_DATA1);
gs.dr_write32(1, csrw(S0, CSR_TDATA0));
mtvec = DEFAULT_MTVEC;
load_reservation = -1;
tselect = 0;
- for (unsigned int i = 0; i < num_triggers; i++) {
+ for (unsigned int i = 0; i < num_triggers; i++)
mcontrol[i].type = 2;
- mcontrol[i].action = ACTION_NONE;
- tdata1[i] = 0;
- }
}
void processor_t::set_debug(bool value)
if (state.tselect < state.num_triggers) {
reg_t v = 0;
mcontrol_t *mc = &state.mcontrol[state.tselect];
- v = set_field(v, 0xfL << (xlen-4), mc->type);
- v = set_field(v, 0x3fL << (xlen-10), mc->maskmax);
+ v = set_field(v, MCONTROL_TYPE(xlen), mc->type);
+ v = set_field(v, MCONTROL_MASKMAX(xlen), mc->maskmax);
v = set_field(v, MCONTROL_SELECT, mc->select);
v = set_field(v, MCONTROL_ACTION, mc->action);
v = set_field(v, MCONTROL_CHAIN, mc->chain);
mmu->check_triggers_store = false;
for (unsigned i = 0; i < state.num_triggers; i++) {
- if (state.mcontrol[i].action == ACTION_NONE)
- continue;
if (state.mcontrol[i].execute) {
mmu->check_triggers_fetch = true;
}
typedef enum
{
- ACTION_NONE = MCONTROL_ACTION_NONE,
ACTION_DEBUG_EXCEPTION = MCONTROL_ACTION_DEBUG_EXCEPTION,
ACTION_DEBUG_MODE = MCONTROL_ACTION_DEBUG_MODE,
ACTION_TRACE_START = MCONTROL_ACTION_TRACE_START,
if (state.dcsr.cause)
return -1;
- bool chain_ok = false;
+ bool chain_ok = true;
for (unsigned int i = 0; i < state.num_triggers; i++) {
- if (state.mcontrol[i].action == ACTION_NONE ||
- (operation == OPERATION_EXECUTE && !state.mcontrol[i].execute) ||
+ if (!chain_ok) {
+ chain_ok |= !state.mcontrol[i].chain;
+ continue;
+ }
+
+ if ((operation == OPERATION_EXECUTE && !state.mcontrol[i].execute) ||
(operation == OPERATION_STORE && !state.mcontrol[i].store) ||
(operation == OPERATION_LOAD && !state.mcontrol[i].load) ||
(state.prv == PRV_M && !state.mcontrol[i].m) ||
(state.prv == PRV_H && !state.mcontrol[i].h) ||
(state.prv == PRV_S && !state.mcontrol[i].s) ||
(state.prv == PRV_U && !state.mcontrol[i].u)) {
- goto next;
+ continue;
}
reg_t value;
switch (state.mcontrol[i].match) {
case MATCH_EQUAL:
if (value != state.tdata1[i])
- goto next;
+ continue;
break;
case MATCH_NAPOT:
{
reg_t mask = ~((1 << cto(state.tdata1[i])) - 1);
if ((value & mask) != (state.tdata1[i] & mask))
- goto next;
+ continue;
}
break;
case MATCH_GE:
if (value < state.tdata1[i])
- goto next;
+ continue;
break;
case MATCH_LT:
if (value >= state.tdata1[i])
- goto next;
+ continue;
break;
case MATCH_MASK_LOW:
{
reg_t mask = state.tdata1[i] >> (xlen/2);
if ((value & mask) != (state.tdata1[i] & mask))
- goto next;
+ continue;
}
break;
case MATCH_MASK_HIGH:
{
reg_t mask = state.tdata1[i] >> (xlen/2);
if (((value >> (xlen/2)) & mask) != (state.tdata1[i] & mask))
- goto next;
+ continue;
}
break;
}
- if (state.mcontrol[i].chain && !chain_ok) {
- goto next;
- }
-
- // We got here, so this trigger matches. But if the next trigger has
- // chain set, then we can't perform the action.
- if (i+1 < state.num_triggers && state.mcontrol[i+1].chain) {
- chain_ok = true;
- continue;
- } else {
+ if (!state.mcontrol[i].chain)
return i;
- }
-
-next:
- chain_ok = false;
+ chain_ok = true;
}
return -1;
}