Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,7 @@ Current progress of this emulator in riscv-arch-test(RV32):
- `M`: Standard Extension for Integer Multiplication and Division
- `C`: Standard Extension for Compressed Instruction
- `Zifencei`: Instruction-Fetch Fence
* Failed Tests
- `privilege`: RISCV Privileged Specification
+ 1 system calls
* `ecall`
* Unsupported tests (runnable but incomplete)
- `F` Standard Extension for Single-Precision Floating-Point

Expand Down
92 changes: 53 additions & 39 deletions src/emulate.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,53 +32,59 @@ extern struct target_ops gdbstub_ops;
#include "riscv_private.h"

/* RISC-V exception code list */
#define GET_EXCEPTION_CODE(type) rv_exception_code_##type
#define RV_EXCEPTION_LIST \
_(insn_misaligned) /* Instruction address misaligned */ \
_(insn_fault) /* Instruction access fault */ \
_(illegal_insn) /* Illegal instruction */ \
_(breakpoint) /* Breakpoint */ \
_(load_misaligned) /* Load address misaligned */ \
_(load_fault) /* Load access fault */ \
_(store_misaligned) /* Store/AMO address misaligned */
#define RV_EXCEPTION_LIST \
_(insn_misaligned, 0) /* Instruction address misaligned */ \
_(illegal_insn, 2) /* Illegal instruction */ \
_(breakpoint, 3) /* Breakpoint */ \
_(load_misaligned, 4) /* Load address misaligned */ \
_(store_misaligned, 6) /* Store/AMO address misaligned */ \
_(ecall_M, 11) /* Environment call from M-mode */

enum {
#define _(type) GET_EXCEPTION_CODE(type),
#define _(type, code) rv_exception_code##type = code,
RV_EXCEPTION_LIST
#undef _
};

#define EXCEPTION_HANDLER_IMPL(type) \
UNUSED static void rv_except_##type(struct riscv_t *rv, uint32_t mtval) \
{ \
/* 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 */ \
const uint32_t code = GET_EXCEPTION_CODE(type); \
/* mepc (Machine Exception Program Counter) \
* mtval (Machine Trap Value Register) \
*/ \
rv->csr_mepc = rv->PC; \
rv->csr_mtval = mtval; \
switch (mode) { \
case 0: /* DIRECT: All exceptions set PC to base */ \
rv->PC = base; \
break; \
/* VECTORED: Asynchronous interrupts set PC to base + 4 * code */ \
case 1: \
rv->PC = base + 4 * code; \
break; \
} \
/* mcause (Machine Cause Register): store exception code */ \
rv->csr_mcause = code; \
static void rv_exception_default_handler(struct riscv_t *rv)
{
rv->csr_mepc += rv->insn_len;
rv->PC = rv->csr_mepc; /* mret */
}

#define EXCEPTION_HANDLER_IMPL(type, code) \
static void rv_except_##type(struct riscv_t *rv, uint32_t mtval) \
{ \
/* 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; \
/* mepc (Machine Exception Program Counter) \
* mtval (Machine Trap Value Register) \
* mcause (Machine Cause Register): store exception code \
*/ \
rv->csr_mepc = rv->PC; \
rv->csr_mtval = mtval; \
rv->csr_mcause = code; \
if (!rv->csr_mtvec) { /* in case CSR is not configured */ \
rv_exception_default_handler(rv); \
return; \
} \
switch (mode) { \
case 0: /* DIRECT: All exceptions set PC to base */ \
rv->PC = base; \
break; \
/* VECTORED: Asynchronous interrupts set PC to base + 4 * code */ \
case 1: \
rv->PC = base + 4 * code; \
break; \
} \
}

/* RISC-V exception handlers */
#define _(type) EXCEPTION_HANDLER_IMPL(type)
#define _(type, code) EXCEPTION_HANDLER_IMPL(type, code)
RV_EXCEPTION_LIST
#undef _

Expand Down Expand Up @@ -775,7 +781,7 @@ static inline bool op_system(struct riscv_t *rv, uint32_t insn)
switch (funct12) { /* dispatch from imm field */
case 0: /* ECALL: Environment Call */
rv->io.on_ecall(rv);
break;
return true;
case 1: /* EBREAK: Environment Break */
rv->io.on_ebreak(rv);
return true;
Expand Down Expand Up @@ -2118,6 +2124,7 @@ void rv_reset(struct riscv_t *rv, riscv_word_t pc)
rv->X[rv_reg_sp] = DEFAULT_STACK_ADDR;

/* reset the csrs */
rv->csr_mtvec = 0;
rv->csr_cycle = 0;
rv->csr_mstatus = 0;

Expand All @@ -2141,3 +2148,10 @@ void ebreak_handler(struct riscv_t *rv)
assert(rv);
rv_except_breakpoint(rv, rv->PC);
}

void ecall_handler(struct riscv_t *rv)
{
assert(rv);
rv_except_ecall_M(rv, 0);
syscall_handler(rv);
}
2 changes: 1 addition & 1 deletion src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ int main(int argc, char **args)
.mem_write_b = MEMIO(write_b),

/* system */
.on_ecall = syscall_handler,
.on_ecall = ecall_handler,
.on_ebreak = ebreak_handler,
};

Expand Down
3 changes: 3 additions & 0 deletions src/riscv.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ riscv_word_t rv_get_reg(struct riscv_t *, uint32_t reg);
/* system call handler */
void syscall_handler(struct riscv_t *rv);

/* environment call handler */
void ecall_handler(struct riscv_t *rv);

/* breakpoint exception handler */
void ebreak_handler(struct riscv_t *rv);

Expand Down
1 change: 0 additions & 1 deletion src/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,6 @@ void syscall_handler(struct riscv_t *rv)
#undef _
default:
fprintf(stderr, "unknown syscall %d\n", (int) syscall);
rv_halt(rv);
break;
}
}