|
|
|
@ -81,6 +81,57 @@ bool mcontrol_t::tdata2_write(processor_t *proc, const reg_t val) noexcept { |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
bool mcontrol_t::memory_access_match(processor_t *proc, operation_t operation, reg_t address, reg_t data) { |
|
|
|
state_t *state = proc->get_state(); |
|
|
|
if ((operation == triggers::OPERATION_EXECUTE && !execute) || |
|
|
|
(operation == triggers::OPERATION_STORE && !store) || |
|
|
|
(operation == triggers::OPERATION_LOAD && !load) || |
|
|
|
(state->prv == PRV_M && !m) || |
|
|
|
(state->prv == PRV_S && !s) || |
|
|
|
(state->prv == PRV_U && !u)) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
reg_t value; |
|
|
|
if (select) { |
|
|
|
value = data; |
|
|
|
} else { |
|
|
|
value = address; |
|
|
|
} |
|
|
|
|
|
|
|
// We need this because in 32-bit mode sometimes the PC bits get sign
|
|
|
|
// extended.
|
|
|
|
auto xlen = proc->get_xlen(); |
|
|
|
if (xlen == 32) { |
|
|
|
value &= 0xffffffff; |
|
|
|
} |
|
|
|
|
|
|
|
switch (match) { |
|
|
|
case triggers::mcontrol_t::MATCH_EQUAL: |
|
|
|
return value == tdata2; |
|
|
|
case triggers::mcontrol_t::MATCH_NAPOT: |
|
|
|
{ |
|
|
|
reg_t mask = ~((1 << (cto(tdata2)+1)) - 1); |
|
|
|
return (value & mask) == (tdata2 & mask); |
|
|
|
} |
|
|
|
case triggers::mcontrol_t::MATCH_GE: |
|
|
|
return value >= tdata2; |
|
|
|
case triggers::mcontrol_t::MATCH_LT: |
|
|
|
return value < tdata2; |
|
|
|
case triggers::mcontrol_t::MATCH_MASK_LOW: |
|
|
|
{ |
|
|
|
reg_t mask = tdata2 >> (xlen/2); |
|
|
|
return (value & mask) == (tdata2 & mask); |
|
|
|
} |
|
|
|
case triggers::mcontrol_t::MATCH_MASK_HIGH: |
|
|
|
{ |
|
|
|
reg_t mask = tdata2 >> (xlen/2); |
|
|
|
return ((value >> (xlen/2)) & mask) == (tdata2 & mask); |
|
|
|
} |
|
|
|
} |
|
|
|
assert(0); |
|
|
|
} |
|
|
|
|
|
|
|
module_t::module_t(unsigned count) : triggers(count) { |
|
|
|
for (unsigned i = 0; i < count; i++) { |
|
|
|
triggers[i] = new mcontrol_t(); |
|
|
|
@ -95,7 +146,6 @@ int module_t::trigger_match(triggers::operation_t operation, reg_t address, reg_ |
|
|
|
return -1; |
|
|
|
|
|
|
|
bool chain_ok = true; |
|
|
|
auto xlen = proc->get_xlen(); |
|
|
|
|
|
|
|
for (unsigned int i = 0; i < triggers.size(); i++) { |
|
|
|
if (!chain_ok) { |
|
|
|
@ -103,68 +153,11 @@ int module_t::trigger_match(triggers::operation_t operation, reg_t address, reg_ |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
if ((operation == triggers::OPERATION_EXECUTE && !triggers[i]->execute) || |
|
|
|
(operation == triggers::OPERATION_STORE && !triggers[i]->store) || |
|
|
|
(operation == triggers::OPERATION_LOAD && !triggers[i]->load) || |
|
|
|
(state->prv == PRV_M && !triggers[i]->m) || |
|
|
|
(state->prv == PRV_S && !triggers[i]->s) || |
|
|
|
(state->prv == PRV_U && !triggers[i]->u)) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
reg_t value; |
|
|
|
if (triggers[i]->select) { |
|
|
|
value = data; |
|
|
|
} else { |
|
|
|
value = address; |
|
|
|
} |
|
|
|
|
|
|
|
// We need this because in 32-bit mode sometimes the PC bits get sign
|
|
|
|
// extended.
|
|
|
|
if (xlen == 32) { |
|
|
|
value &= 0xffffffff; |
|
|
|
} |
|
|
|
|
|
|
|
auto tdata2 = triggers[i]->tdata2; |
|
|
|
switch (triggers[i]->match) { |
|
|
|
case triggers::mcontrol_t::MATCH_EQUAL: |
|
|
|
if (value != tdata2) |
|
|
|
continue; |
|
|
|
break; |
|
|
|
case triggers::mcontrol_t::MATCH_NAPOT: |
|
|
|
{ |
|
|
|
reg_t mask = ~((1 << (cto(tdata2)+1)) - 1); |
|
|
|
if ((value & mask) != (tdata2 & mask)) |
|
|
|
continue; |
|
|
|
} |
|
|
|
break; |
|
|
|
case triggers::mcontrol_t::MATCH_GE: |
|
|
|
if (value < tdata2) |
|
|
|
continue; |
|
|
|
break; |
|
|
|
case triggers::mcontrol_t::MATCH_LT: |
|
|
|
if (value >= tdata2) |
|
|
|
continue; |
|
|
|
break; |
|
|
|
case triggers::mcontrol_t::MATCH_MASK_LOW: |
|
|
|
{ |
|
|
|
reg_t mask = tdata2 >> (xlen/2); |
|
|
|
if ((value & mask) != (tdata2 & mask)) |
|
|
|
continue; |
|
|
|
} |
|
|
|
break; |
|
|
|
case triggers::mcontrol_t::MATCH_MASK_HIGH: |
|
|
|
{ |
|
|
|
reg_t mask = tdata2 >> (xlen/2); |
|
|
|
if (((value >> (xlen/2)) & mask) != (tdata2 & mask)) |
|
|
|
continue; |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
if (!triggers[i]->chain) { |
|
|
|
if (triggers[i]->memory_access_match(proc, operation, address, data) && |
|
|
|
!triggers[i]->chain) { |
|
|
|
return i; |
|
|
|
} |
|
|
|
|
|
|
|
chain_ok = true; |
|
|
|
} |
|
|
|
return -1; |
|
|
|
|