diff --git a/README.md b/README.md index a022804d..8da3dbe4 100644 --- a/README.md +++ b/README.md @@ -82,10 +82,9 @@ Current progress of this emulator in riscv-arch-test(RV32): * Passed Tests - `I`: Base Integer Instruction Set - `M`: Standard Extension for Integer Multiplication and Division + - `C`: Standard Extension for Compressed Instruction - `Zifencei`: Instruction-Fetch Fence * Failed Tests - - `C`: Standard Extension for Compressed Instruction - + `cebreak` - `privilege`: RISCV Privileged Specification + 2 system calls * `ebreak` diff --git a/src/emulate.c b/src/emulate.c index 305ac1d9..0707b298 100644 --- a/src/emulate.c +++ b/src/emulate.c @@ -148,6 +148,37 @@ static void rv_except_illegal_insn(struct riscv_t *rv, uint32_t insn) rv->csr_mcause = code; } +static void rv_except_breakpoint(struct riscv_t *rv, uint32_t old_pc) +{ + /* mtvec (Machine Trap-Vector Base Address Register) + * mtvec[MXLEN-1:2]: vector base address + * mtvec[1:0] : vector mode + */ + const uint32_t base = rv->csr_mtvec & ~0x3; + const uint32_t mode = rv->csr_mtvec & 0x3; + + /* Exception Code: Breakpoint */ + const uint32_t code = 3; + + /* mepc (Machine Exception Program Counter) + * mtval(Machine Trap Value Register) : Breakpoint + */ + rv->csr_mepc = old_pc; + rv->csr_mtval = old_pc; + + switch (mode) { + case 0: /* DIRECT: All exceptions set PC to base */ + rv->PC = base; + break; + case 1: /* VECTORED: Asynchronous interrupts set PC to base + 4 * code */ + rv->PC = base + 4 * code; + break; + } + + /* mcause (Machine Cause Register): store exception code */ + rv->csr_mcause = code; +} + /* RV32I Base Instruction Set * * bits 0-6: opcode @@ -2189,3 +2220,9 @@ void rv_reset(struct riscv_t *rv, riscv_word_t pc) rv->halt = false; } + +void ebreak_handler(struct riscv_t *rv) +{ + assert(rv); + rv_except_breakpoint(rv, rv->PC); +} \ No newline at end of file diff --git a/src/main.c b/src/main.c index 33b8a098..4d7acfb5 100644 --- a/src/main.c +++ b/src/main.c @@ -186,7 +186,7 @@ int main(int argc, char **args) /* system */ .on_ecall = syscall_handler, - .on_ebreak = rv_halt, + .on_ebreak = ebreak_handler, }; state_t *state = state_new(); diff --git a/src/riscv.h b/src/riscv.h index 44381ce3..15809815 100644 --- a/src/riscv.h +++ b/src/riscv.h @@ -125,6 +125,9 @@ riscv_word_t rv_get_reg(struct riscv_t *, uint32_t reg); /* system call handler */ void syscall_handler(struct riscv_t *rv); +/* breakpoint exception handler */ +void ebreak_handler(struct riscv_t *rv); + /* halt the core */ void rv_halt(struct riscv_t *);