Skip to content

Commit ef47f24

Browse files
committed
Implement environment call properly
Implement ecall instruction with control and status registers (CSRs). However, there may occur the situation that the elf file doesn't contain any csr instruction. It will make pc point to wrong address. To resolve this, using 0 as the initial value of mtvec. By default, the emulator executes default exception handler when an exception occurs and mtvec stores 0.
1 parent 247aa03 commit ef47f24

File tree

5 files changed

+31
-9
lines changed

5 files changed

+31
-9
lines changed

README.md

Lines changed: 0 additions & 3 deletions
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

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,25 @@ extern struct target_ops gdbstub_ops;
4040
_(breakpoint) /* Breakpoint */ \
4141
_(load_misaligned) /* Load address misaligned */ \
4242
_(load_fault) /* Load access fault */ \
43-
_(store_misaligned) /* Store/AMO address misaligned */
43+
_(store_misaligned) /* Store/AMO address misaligned */ \
44+
_(store_fault) /* Store/AMO access fault */ \
45+
_(ecall_U) /* Environment call from U-mode */ \
46+
_(ecall_S) /* Environment call from S-mode */ \
47+
_(reserved) /* Reserved */ \
48+
_(ecall_M) /* Environment call from M-mode */
4449

4550
enum {
4651
#define _(type) GET_EXCEPTION_CODE(type),
4752
RV_EXCEPTION_LIST
4853
#undef _
4954
};
5055

56+
static void rv_exception_default_handler(struct riscv_t *rv)
57+
{
58+
rv->csr_mepc += rv->insn_len;
59+
rv->PC = rv->csr_mepc; /* mret */
60+
}
61+
5162
#define EXCEPTION_HANDLER_IMPL(type) \
5263
UNUSED static void rv_except_##type(struct riscv_t *rv, uint32_t mtval) \
5364
{ \
@@ -61,9 +72,15 @@ enum {
6172
const uint32_t code = GET_EXCEPTION_CODE(type); \
6273
/* mepc (Machine Exception Program Counter) \
6374
* mtval (Machine Trap Value Register) \
75+
* mcause (Machine Cause Register): store exception code \
6476
*/ \
6577
rv->csr_mepc = rv->PC; \
6678
rv->csr_mtval = mtval; \
79+
rv->csr_mcause = code; \
80+
if (!rv->csr_mtvec) { /* elf doesn't implement csr instruction */ \
81+
rv_exception_default_handler(rv); \
82+
return; \
83+
} \
6784
switch (mode) { \
6885
case 0: /* DIRECT: All exceptions set PC to base */ \
6986
rv->PC = base; \
@@ -73,8 +90,6 @@ enum {
7390
rv->PC = base + 4 * code; \
7491
break; \
7592
} \
76-
/* mcause (Machine Cause Register): store exception code */ \
77-
rv->csr_mcause = code; \
7893
}
7994

8095
/* RISC-V exception handlers */
@@ -775,7 +790,7 @@ static inline bool op_system(struct riscv_t *rv, uint32_t insn)
775790
switch (funct12) { /* dispatch from imm field */
776791
case 0: /* ECALL: Environment Call */
777792
rv->io.on_ecall(rv);
778-
break;
793+
return true;
779794
case 1: /* EBREAK: Environment Break */
780795
rv->io.on_ebreak(rv);
781796
return true;
@@ -2118,6 +2133,7 @@ void rv_reset(struct riscv_t *rv, riscv_word_t pc)
21182133
rv->X[rv_reg_sp] = DEFAULT_STACK_ADDR;
21192134

21202135
/* reset the csrs */
2136+
rv->csr_mtvec = 0;
21212137
rv->csr_cycle = 0;
21222138
rv->csr_mstatus = 0;
21232139

@@ -2141,3 +2157,10 @@ void ebreak_handler(struct riscv_t *rv)
21412157
assert(rv);
21422158
rv_except_breakpoint(rv, rv->PC);
21432159
}
2160+
2161+
void ecall_handler(struct riscv_t *rv)
2162+
{
2163+
assert(rv);
2164+
rv_except_ecall_M(rv, 0);
2165+
syscall_handler(rv);
2166+
}

src/main.c

Lines changed: 1 addition & 1 deletion
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

Lines changed: 3 additions & 0 deletions
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

Lines changed: 0 additions & 1 deletion
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)