diff --git a/hosts/host-gdbstub/host-gdbstub.c b/hosts/host-gdbstub/host-gdbstub.c index 145f7bb..540d6e7 100644 --- a/hosts/host-gdbstub/host-gdbstub.c +++ b/hosts/host-gdbstub/host-gdbstub.c @@ -58,6 +58,7 @@ int main(int argc, char *argv[]) { } uvm32_init(&vmst); + uvm32_useBreak(&vmst, true); // enable ebreak if (!uvm32_load(&vmst, rom, romlen)) { fprintf(stderr, "load failed!\n"); diff --git a/test/meter/test/tests.c b/test/meter/test/tests.c index bc5f646..3199238 100644 --- a/test/meter/test/tests.c +++ b/test/meter/test/tests.c @@ -40,6 +40,8 @@ uint32_t metered_run(uint32_t num_instr) { case UVM32_EVT_END: TEST_ASSERT_EQUAL(0, 1); // trigger an assert, we didn't get to 100000 yet break; + case UVM32_EVT_BREAK: + break; } } diff --git a/uvm32/uvm32.c b/uvm32/uvm32.c index 7fed1b3..ba4f779 100644 --- a/uvm32/uvm32.c +++ b/uvm32/uvm32.c @@ -313,14 +313,15 @@ uint32_t uvm32_run(uvm32_state_t *vmst, uvm32_evt_t *evt, uint32_t instr_meter) setStatusErr(vmst, UVM32_ERR_MEM_WR); setup_err_evt(vmst, evt); break; - case 3: // ebreak - vmst->_ioevt.typ = UVM32_EVT_BREAK; - setStatus(vmst, UVM32_STATUS_PAUSED); - break; default: - // unhandled exception - setStatusErr(vmst, UVM32_ERR_INTERNAL_CORE); - setup_err_evt(vmst, evt); + if (vmst->useBreak && ret == 3) { // ebreak + vmst->_ioevt.typ = UVM32_EVT_BREAK; + setStatus(vmst, UVM32_STATUS_PAUSED); + } else { + // unhandled exception + setStatusErr(vmst, UVM32_ERR_INTERNAL_CORE); + setup_err_evt(vmst, evt); + } break; } @@ -351,6 +352,10 @@ uint32_t uvm32_run(uvm32_state_t *vmst, uvm32_evt_t *evt, uint32_t instr_meter) } } +void uvm32_useBreak(uvm32_state_t *vmst, bool enabled) { + vmst->useBreak = enabled; +} + bool uvm32_hasEnded(const uvm32_state_t *vmst) { return vmst->_status == UVM32_STATUS_ENDED; } diff --git a/uvm32/uvm32.h b/uvm32/uvm32.h index 802746f..f68e2f2 100644 --- a/uvm32/uvm32.h +++ b/uvm32/uvm32.h @@ -151,6 +151,7 @@ typedef struct { uint32_t _extramLen; /*! Length of external RAM */ bool _extramDirty; /*! Flag to indicate VM code has modified extram since last run */ uint32_t garbage; /*! Used for returning valid pointer when operations fail */ + bool useBreak; /*! produce UVM32_EVT_BREAK */ } uvm32_state_t; /*! Initialise a VM instance */ @@ -196,6 +197,8 @@ uvm32_slice_t uvm32_arg_getslice(uvm32_state_t *vmst, uvm32_evt_t *evt, uvm32_ar /*! Read a syscall argument pointer as a slice of known length */ uvm32_slice_t uvm32_arg_getslice_fixed(uvm32_state_t *vmst, uvm32_evt_t *evt, uvm32_arg_t arg, uint32_t len); +/*! Allow ebreak in code, will generate UVM32_EVT_BREAK */ +void uvm32_useBreak(uvm32_state_t *vmst, bool enabled); /*! Setup a block of memory to act as external RAM, it will be available on in VM code at address `UVM32_EXTRAM_BASE`. The memory is not copied, so the caller must ensure it remains available until `uvm32_extram()` is called to setup a different region or the VM is ended. */ void uvm32_extram(uvm32_state_t *vmst, uint8_t *extram, uint32_t len);