1414#include <emscripten.h>
1515#endif
1616
17+ #if RV32_HAS (SYSTEM )
18+ #include "system.h"
19+ #endif /* RV32_HAS(SYSTEM) */
20+
1721#if RV32_HAS (EXT_F )
1822#include <math.h>
1923#include "softfloat.h"
@@ -41,18 +45,21 @@ extern struct target_ops gdbstub_ops;
4145#define IF_rs2 (i , r ) (i->rs2 == rv_reg_##r)
4246#define IF_imm (i , v ) (i->imm == v)
4347
44- /* RISC-V exception code list */
48+ /* RISC-V trap code list */
4549/* clang-format off */
46- #define RV_TRAP_LIST \
47- IIF(RV32_HAS(EXT_C))(, \
48- _(insn_misaligned, 0) /* Instruction address misaligned */ \
49- ) \
50- _ (illegal_insn , 2 ) /* Illegal instruction */ \
51- _(breakpoint, 3) /* Breakpoint */ \
52- _ (load_misaligned , 4 ) /* Load address misaligned */ \
53- _ (store_misaligned , 6 ) /* Store/AMO address misaligned */ \
54- IIF (RV32_HAS (SYSTEM ))(, \
55- _ (ecall_M , 11 ) /* Environment call from M-mode */ \
50+ #define RV_TRAP_LIST \
51+ IIF(RV32_HAS(EXT_C))(, \
52+ _(insn_misaligned, INSN_MISALIGNED) /* Instruction address misaligned */ \
53+ ) \
54+ _ (illegal_insn , ILLEGAL_INSN ) /* Illegal instruction */ \
55+ _(breakpoint, BREAKPOINT) /* Breakpoint */ \
56+ _ (load_misaligned , LOAD_MISALIGNED ) /* Load address misaligned */ \
57+ _(store_misaligned, STORE_MISALIGNED) /* Store/AMO address misaligned */ \
58+ IIF (RV32_HAS (SYSTEM ))( \
59+ _ (pagefault_insn , PAGEFAULT_INSN ) /* Instruction page fault */ \
60+ _ (pagefault_load , PAGEFAULT_LOAD ) /* Load page fault */ \
61+ _ (pagefault_store , PAGEFAULT_STORE ), /* Store page fault */ \
62+ _ (ecall_M , ECALL_M ) /* Environment call from M-mode */ \
5663 )
5764/* clang-format on */
5865
@@ -68,20 +75,9 @@ static void rv_trap_default_handler(riscv_t *rv)
6875 rv -> PC = rv -> csr_mepc ; /* mret */
6976}
7077
71- /*
72- * Trap might occurs during block emulation. For instance, page fault.
73- * In order to handle trap, we have to escape from block and execute
74- * registered trap handler. This trap_handler function helps to execute
75- * the registered trap handler, PC by PC. Once the trap is handled,
76- * resume the previous execution flow where cause the trap.
77- *
78- * Since the system emulation has not yet included in rv32emu, the page
79- * fault is not practical in current test suite. Instead, we try to
80- * emulate the misaligned handling in the test suite.
81- */
8278#if RV32_HAS (SYSTEM )
83- static void trap_handler (riscv_t * rv );
84- #endif
79+ static void __trap_handler (riscv_t * rv );
80+ #endif /* SYSTEM */
8581
8682/* When a trap occurs in M-mode/S-mode, m/stval is either initialized to zero or
8783 * populated with exception-specific details to assist software in managing
@@ -158,7 +154,7 @@ static void trap_handler(riscv_t *rv);
158154 rv -> PC = base + 4 * (code & MASK (31 )); \
159155 break ; \
160156 } \
161- IIF (RV32_HAS (SYSTEM ))(if (rv -> is_trapped ) trap_handler (rv );, ) \
157+ IIF (RV32_HAS (SYSTEM ))(if (rv -> is_trapped ) __trap_handler (rv );, ) \
162158 }
163159
164160/* RISC-V exception handlers */
@@ -180,8 +176,8 @@ RV_TRAP_LIST
180176 rv->compressed = compress; \
181177 rv->csr_cycle = cycle; \
182178 rv->PC = PC; \
183- IIF(RV32_HAS(SYSTEM))(rv->is_trapped = true, ); \
184- rv_trap_##type##_misaligned(rv, IIF(IO)(addr, mask_or_pc)); \
179+ SET_CAUSE_AND_TVAL_THEN_TRAP(rv, type##_MISALIGNED, \
180+ IIF(IO)(addr, mask_or_pc)); \
185181 return false; \
186182 }
187183
@@ -531,8 +527,8 @@ static bool do_fuse3(riscv_t *rv, rv_insn_t *ir, uint64_t cycle, uint32_t PC)
531527 */
532528 for (int i = 0 ; i < ir -> imm2 ; i ++ ) {
533529 uint32_t addr = rv -> X [fuse [i ].rs1 ] + fuse [i ].imm ;
534- RV_EXC_MISALIGN_HANDLER (3 , store , false, 1 );
535- rv -> io .mem_write_w (addr , rv -> X [fuse [i ].rs2 ]);
530+ RV_EXC_MISALIGN_HANDLER (3 , STORE , false, 1 );
531+ rv -> io .mem_write_w (rv , addr , rv -> X [fuse [i ].rs2 ]);
536532 }
537533 PC += ir -> imm2 * 4 ;
538534 if (unlikely (RVOP_NO_NEXT (ir ))) {
@@ -555,8 +551,8 @@ static bool do_fuse4(riscv_t *rv, rv_insn_t *ir, uint64_t cycle, uint32_t PC)
555551 */
556552 for (int i = 0 ; i < ir -> imm2 ; i ++ ) {
557553 uint32_t addr = rv -> X [fuse [i ].rs1 ] + fuse [i ].imm ;
558- RV_EXC_MISALIGN_HANDLER (3 , load , false, 1 );
559- rv -> X [fuse [i ].rd ] = rv -> io .mem_read_w (addr );
554+ RV_EXC_MISALIGN_HANDLER (3 , LOAD , false, 1 );
555+ rv -> X [fuse [i ].rd ] = rv -> io .mem_read_w (rv , addr );
560556 }
561557 PC += ir -> imm2 * 4 ;
562558 if (unlikely (RVOP_NO_NEXT (ir ))) {
@@ -666,12 +662,12 @@ static void block_translate(riscv_t *rv, block_t *block)
666662 prev_ir -> next = ir ;
667663
668664 /* fetch the next instruction */
669- const uint32_t insn = rv -> io .mem_ifetch (block -> pc_end );
665+ const uint32_t insn = rv -> io .mem_ifetch (rv , block -> pc_end );
670666
671667 /* decode the instruction */
672668 if (!rv_decode (ir , insn )) {
673669 rv -> compressed = is_compressed (insn );
674- rv_trap_illegal_insn (rv , insn );
670+ SET_CAUSE_AND_TVAL_THEN_TRAP (rv , INSN_MISALIGNED , insn );
675671 break ;
676672 }
677673 ir -> impl = dispatch_table [ir -> opcode ];
@@ -1122,15 +1118,14 @@ void rv_step(void *arg)
11221118}
11231119
11241120#if RV32_HAS (SYSTEM )
1125- static void trap_handler (riscv_t * rv )
1121+ static void __trap_handler (riscv_t * rv )
11261122{
11271123 rv_insn_t * ir = mpool_alloc (rv -> block_ir_mp );
11281124 assert (ir );
11291125
1130- /* set to false by sret/mret implementation */
1131- uint32_t insn ;
1126+ /* set to false by sret implementation */
11321127 while (rv -> is_trapped && !rv_has_halted (rv )) {
1133- insn = rv -> io .mem_ifetch (rv -> PC );
1128+ uint32_t insn = rv -> io .mem_ifetch (rv , rv -> PC );
11341129 assert (insn );
11351130
11361131 rv_decode (ir , insn );
@@ -1139,12 +1134,63 @@ static void trap_handler(riscv_t *rv)
11391134 ir -> impl (rv , ir , rv -> csr_cycle , rv -> PC );
11401135 }
11411136}
1142- #endif
1137+ #endif /* SYSTEM */
1138+
1139+ static void _trap_handler (riscv_t * rv )
1140+ {
1141+ uint32_t cause = RV_PRIV_IS_U_OR_S_MODE () ? rv -> csr_scause : rv -> csr_mcause ;
1142+ uint32_t tval = RV_PRIV_IS_U_OR_S_MODE () ? rv -> csr_stval : rv -> csr_mtval ;
1143+
1144+ switch (cause ) {
1145+ #if !RV32_HAS (EXT_C )
1146+ case INSN_MISALIGNED :
1147+ rv_trap_insn_misaligned (rv , tval );
1148+ break ;
1149+ #endif /* EXT_C */
1150+ case ILLEGAL_INSN :
1151+ rv_trap_illegal_insn (rv , tval );
1152+ break ;
1153+ case BREAKPOINT :
1154+ rv_trap_breakpoint (rv , tval );
1155+ break ;
1156+ case LOAD_MISALIGNED :
1157+ rv_trap_load_misaligned (rv , tval );
1158+ break ;
1159+ case STORE_MISALIGNED :
1160+ rv_trap_store_misaligned (rv , tval );
1161+ break ;
1162+ #if RV32_HAS (SYSTEM )
1163+ case PAGEFAULT_INSN :
1164+ rv_trap_pagefault_insn (rv , tval );
1165+ break ;
1166+ case PAGEFAULT_LOAD :
1167+ rv_trap_pagefault_load (rv , tval );
1168+ break ;
1169+ case PAGEFAULT_STORE :
1170+ rv_trap_pagefault_store (rv , tval );
1171+ break ;
1172+ #endif /* SYSTEM */
1173+ #if !RV32_HAS (SYSTEM )
1174+ case ECALL_M :
1175+ rv_trap_ecall_M (rv , tval );
1176+ break ;
1177+ #endif /* SYSTEM */
1178+ default :
1179+ __UNREACHABLE ;
1180+ break ;
1181+ }
1182+ }
1183+
1184+ void trap_handler (riscv_t * rv )
1185+ {
1186+ assert (rv );
1187+ _trap_handler (rv );
1188+ }
11431189
11441190void ebreak_handler (riscv_t * rv )
11451191{
11461192 assert (rv );
1147- rv_trap_breakpoint (rv , rv -> PC );
1193+ SET_CAUSE_AND_TVAL_THEN_TRAP (rv , BREAKPOINT , rv -> PC );
11481194}
11491195
11501196void ecall_handler (riscv_t * rv )
@@ -1154,7 +1200,7 @@ void ecall_handler(riscv_t *rv)
11541200 syscall_handler (rv );
11551201 rv -> PC += 4 ;
11561202#else
1157- rv_trap_ecall_M (rv , 0 );
1203+ SET_CAUSE_AND_TVAL_THEN_TRAP (rv , ECALL_M , 0 );
11581204 syscall_handler (rv );
11591205#endif
11601206}
0 commit comments