Skip to content

Commit e69cc1a

Browse files
authored
Merge pull request #66 from Risheng1128/pr
Implement environment call properly
2 parents 247aa03 + c54dcde commit e69cc1a

File tree

5 files changed

+57
-44
lines changed

5 files changed

+57
-44
lines changed

README.md

-3
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,7 @@ Current progress of this emulator in riscv-arch-test(RV32):
8484
- `M`: Standard Extension for Integer Multiplication and Division
8585
- `C`: Standard Extension for Compressed Instruction
8686
- `Zifencei`: Instruction-Fetch Fence
87-
* Failed Tests
8887
- `privilege`: RISCV Privileged Specification
89-
+ 1 system calls
90-
* `ecall`
9188
* Unsupported tests (runnable but incomplete)
9289
- `F` Standard Extension for Single-Precision Floating-Point
9390

src/emulate.c

+53-39
Original file line numberDiff line numberDiff line change
@@ -32,53 +32,59 @@ extern struct target_ops gdbstub_ops;
3232
#include "riscv_private.h"
3333

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

4543
enum {
46-
#define _(type) GET_EXCEPTION_CODE(type),
44+
#define _(type, code) rv_exception_code##type = code,
4745
RV_EXCEPTION_LIST
4846
#undef _
4947
};
5048

51-
#define EXCEPTION_HANDLER_IMPL(type) \
52-
UNUSED static void rv_except_##type(struct riscv_t *rv, uint32_t mtval) \
53-
{ \
54-
/* mtvec (Machine Trap-Vector Base Address Register) \
55-
* mtvec[MXLEN-1:2]: vector base address \
56-
* mtvec[1:0] : vector mode \
57-
*/ \
58-
const uint32_t base = rv->csr_mtvec & ~0x3; \
59-
const uint32_t mode = rv->csr_mtvec & 0x3; \
60-
/* Exception Code */ \
61-
const uint32_t code = GET_EXCEPTION_CODE(type); \
62-
/* mepc (Machine Exception Program Counter) \
63-
* mtval (Machine Trap Value Register) \
64-
*/ \
65-
rv->csr_mepc = rv->PC; \
66-
rv->csr_mtval = mtval; \
67-
switch (mode) { \
68-
case 0: /* DIRECT: All exceptions set PC to base */ \
69-
rv->PC = base; \
70-
break; \
71-
/* VECTORED: Asynchronous interrupts set PC to base + 4 * code */ \
72-
case 1: \
73-
rv->PC = base + 4 * code; \
74-
break; \
75-
} \
76-
/* mcause (Machine Cause Register): store exception code */ \
77-
rv->csr_mcause = code; \
49+
static void rv_exception_default_handler(struct riscv_t *rv)
50+
{
51+
rv->csr_mepc += rv->insn_len;
52+
rv->PC = rv->csr_mepc; /* mret */
53+
}
54+
55+
#define EXCEPTION_HANDLER_IMPL(type, code) \
56+
static void rv_except_##type(struct riscv_t *rv, uint32_t mtval) \
57+
{ \
58+
/* mtvec (Machine Trap-Vector Base Address Register) \
59+
* mtvec[MXLEN-1:2]: vector base address \
60+
* mtvec[1:0] : vector mode \
61+
*/ \
62+
const uint32_t base = rv->csr_mtvec & ~0x3; \
63+
const uint32_t mode = rv->csr_mtvec & 0x3; \
64+
/* mepc (Machine Exception Program Counter) \
65+
* mtval (Machine Trap Value Register) \
66+
* mcause (Machine Cause Register): store exception code \
67+
*/ \
68+
rv->csr_mepc = rv->PC; \
69+
rv->csr_mtval = mtval; \
70+
rv->csr_mcause = code; \
71+
if (!rv->csr_mtvec) { /* in case CSR is not configured */ \
72+
rv_exception_default_handler(rv); \
73+
return; \
74+
} \
75+
switch (mode) { \
76+
case 0: /* DIRECT: All exceptions set PC to base */ \
77+
rv->PC = base; \
78+
break; \
79+
/* VECTORED: Asynchronous interrupts set PC to base + 4 * code */ \
80+
case 1: \
81+
rv->PC = base + 4 * code; \
82+
break; \
83+
} \
7884
}
7985

8086
/* RISC-V exception handlers */
81-
#define _(type) EXCEPTION_HANDLER_IMPL(type)
87+
#define _(type, code) EXCEPTION_HANDLER_IMPL(type, code)
8288
RV_EXCEPTION_LIST
8389
#undef _
8490

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

21202126
/* reset the csrs */
2127+
rv->csr_mtvec = 0;
21212128
rv->csr_cycle = 0;
21222129
rv->csr_mstatus = 0;
21232130

@@ -2141,3 +2148,10 @@ void ebreak_handler(struct riscv_t *rv)
21412148
assert(rv);
21422149
rv_except_breakpoint(rv, rv->PC);
21432150
}
2151+
2152+
void ecall_handler(struct riscv_t *rv)
2153+
{
2154+
assert(rv);
2155+
rv_except_ecall_M(rv, 0);
2156+
syscall_handler(rv);
2157+
}

src/main.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ int main(int argc, char **args)
199199
.mem_write_b = MEMIO(write_b),
200200

201201
/* system */
202-
.on_ecall = syscall_handler,
202+
.on_ecall = ecall_handler,
203203
.on_ebreak = ebreak_handler,
204204
};
205205

src/riscv.h

+3
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@ riscv_word_t rv_get_reg(struct riscv_t *, uint32_t reg);
130130
/* system call handler */
131131
void syscall_handler(struct riscv_t *rv);
132132

133+
/* environment call handler */
134+
void ecall_handler(struct riscv_t *rv);
135+
133136
/* breakpoint exception handler */
134137
void ebreak_handler(struct riscv_t *rv);
135138

src/syscall.c

-1
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,6 @@ void syscall_handler(struct riscv_t *rv)
336336
#undef _
337337
default:
338338
fprintf(stderr, "unknown syscall %d\n", (int) syscall);
339-
rv_halt(rv);
340339
break;
341340
}
342341
}

0 commit comments

Comments
 (0)