@@ -47,19 +47,19 @@ extern struct target_ops gdbstub_ops;
4747
4848/* RISC-V trap code list */
4949/* clang-format off */
50- #define RV_TRAP_LIST \
51- IIF(RV32_HAS(EXT_C))(, \
52- _(insn_misaligned, 0) /* Instruction address misaligned */ \
53- ) \
54- _ (illegal_insn , 2 ) /* Illegal instruction */ \
55- _ (breakpoint , 3 ) /* Breakpoint */ \
56- _(load_misaligned, 4) /* Load address misaligned */ \
57- _ (store_misaligned , 6 ) /* Store/AMO address misaligned */ \
58- IIF (RV32_HAS (SYSTEM ))( \
59- _ (pagefault_insn , 12 ) /* Instruction page fault */ \
60- _ (pagefault_load , 13 ) /* Load page fault */ \
61- _ (pagefault_store , 15 ), /* Store page fault */ \
62- _ (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 */ \
6363 )
6464/* clang-format on */
6565
@@ -75,6 +75,10 @@ static void rv_trap_default_handler(riscv_t *rv)
7575 rv -> PC = rv -> csr_mepc ; /* mret */
7676}
7777
78+ #if RV32_HAS (SYSTEM )
79+ static void __trap_handler (riscv_t * rv );
80+ #endif /* SYSTEM */
81+
7882/* When a trap occurs in M-mode/S-mode, m/stval is either initialized to zero or
7983 * populated with exception-specific details to assist software in managing
8084 * the trap. Otherwise, the implementation never modifies m/stval, although
@@ -95,7 +99,7 @@ static void rv_trap_default_handler(riscv_t *rv)
9599 * identifier called tval, as both are handled by TRAP_HANDLER_IMPL.
96100 */
97101#define TRAP_HANDLER_IMPL (type , code ) \
98- void rv_trap_##type(riscv_t *rv, uint32_t tval) \
102+ static void rv_trap_##type(riscv_t *rv, uint32_t tval) \
99103 { \
100104 /* m/stvec (Machine/Supervisor Trap-Vector Base Address Register) \
101105 * m/stvec[MXLEN-1:2]: vector base address \
@@ -150,7 +154,7 @@ static void rv_trap_default_handler(riscv_t *rv)
150154 rv -> PC = base + 4 * (code & MASK (31 )); \
151155 break ; \
152156 } \
153- IIF (RV32_HAS (SYSTEM ))(if (rv -> is_trapped ) trap_handler (rv );, ) \
157+ IIF (RV32_HAS (SYSTEM ))(if (rv -> is_trapped ) __trap_handler (rv );, ) \
154158 }
155159
156160/* RISC-V exception handlers */
@@ -173,7 +177,8 @@ RV_TRAP_LIST
173177 rv->csr_cycle = cycle; \
174178 rv->PC = PC; \
175179 IIF(RV32_HAS(SYSTEM))(rv->is_trapped = true, ); \
176- rv_trap_##type##_misaligned(rv, IIF(IO)(addr, mask_or_pc)); \
180+ SET_SCAUSE_AND_STVAL_THEN_TRAP(rv, type##_MISALIGNED, \
181+ IIF(IO)(addr, mask_or_pc)); \
177182 return false; \
178183 }
179184
@@ -523,7 +528,7 @@ static bool do_fuse3(riscv_t *rv, rv_insn_t *ir, uint64_t cycle, uint32_t PC)
523528 */
524529 for (int i = 0 ; i < ir -> imm2 ; i ++ ) {
525530 uint32_t addr = rv -> X [fuse [i ].rs1 ] + fuse [i ].imm ;
526- RV_EXC_MISALIGN_HANDLER (3 , store , false, 1 );
531+ RV_EXC_MISALIGN_HANDLER (3 , STORE , false, 1 );
527532 rv -> io .mem_write_w (rv , addr , rv -> X [fuse [i ].rs2 ]);
528533 }
529534 PC += ir -> imm2 * 4 ;
@@ -547,7 +552,7 @@ static bool do_fuse4(riscv_t *rv, rv_insn_t *ir, uint64_t cycle, uint32_t PC)
547552 */
548553 for (int i = 0 ; i < ir -> imm2 ; i ++ ) {
549554 uint32_t addr = rv -> X [fuse [i ].rs1 ] + fuse [i ].imm ;
550- RV_EXC_MISALIGN_HANDLER (3 , load , false, 1 );
555+ RV_EXC_MISALIGN_HANDLER (3 , LOAD , false, 1 );
551556 rv -> X [fuse [i ].rd ] = rv -> io .mem_read_w (rv , addr );
552557 }
553558 PC += ir -> imm2 * 4 ;
@@ -581,7 +586,7 @@ static bool do_fuse5(riscv_t *rv,
581586}
582587
583588/* clang-format off */
584- const void * dispatch_table [] = {
589+ static const void * dispatch_table [] = {
585590 /* RV32 instructions */
586591#define _ (inst , can_branch , insn_len , translatable , reg_mask ) [rv_insn_ ##inst ] = do_ ##inst ,
587592 RV_INSN_LIST
@@ -663,7 +668,7 @@ static void block_translate(riscv_t *rv, block_t *block)
663668 /* decode the instruction */
664669 if (!rv_decode (ir , insn )) {
665670 rv -> compressed = is_compressed (insn );
666- rv_trap_illegal_insn (rv , insn );
671+ SET_SCAUSE_AND_STVAL_THEN_TRAP (rv , INSN_MISALIGNED , insn );
667672 break ;
668673 }
669674 ir -> impl = dispatch_table [ir -> opcode ];
@@ -1113,10 +1118,75 @@ void rv_step(void *arg)
11131118#endif
11141119}
11151120
1121+ static void __trap_handler (riscv_t * rv )
1122+ {
1123+ rv_insn_t * ir = mpool_alloc (rv -> block_ir_mp );
1124+ assert (ir );
1125+
1126+ /* set to false by sret implementation */
1127+ while (rv -> is_trapped && !rv_has_halted (rv )) {
1128+ uint32_t insn = rv -> io .mem_ifetch (rv , rv -> PC );
1129+ assert (insn );
1130+
1131+ rv_decode (ir , insn );
1132+ ir -> impl = dispatch_table [ir -> opcode ];
1133+ rv -> compressed = is_compressed (insn );
1134+ ir -> impl (rv , ir , rv -> csr_cycle , rv -> PC );
1135+ }
1136+ }
1137+
1138+ static void _trap_handler (riscv_t * rv )
1139+ {
1140+ uint32_t scause = rv -> csr_scause ;
1141+ uint32_t stval = rv -> csr_stval ;
1142+
1143+ switch (scause ) {
1144+ #if !RV32_HAS (EXT_C )
1145+ case INSN_MISALIGNED :
1146+ rv_trap_insn_misaligned (rv , stval );
1147+ break ;
1148+ #endif /* EXT_C */
1149+ case ILLEGAL_INSN :
1150+ rv_trap_illegal_insn (rv , stval );
1151+ break ;
1152+ case BREAKPOINT :
1153+ rv_trap_breakpoint (rv , stval );
1154+ break ;
1155+ case LOAD_MISALIGNED :
1156+ rv_trap_load_misaligned (rv , stval );
1157+ break ;
1158+ case STORE_MISALIGNED :
1159+ rv_trap_store_misaligned (rv , stval );
1160+ break ;
1161+ #if RV32_HAS (SYSTEM )
1162+ case PAGEFAULT_INSN :
1163+ rv_trap_pagefault_insn (rv , stval );
1164+ break ;
1165+ case PAGEFAULT_LOAD :
1166+ rv_trap_pagefault_load (rv , stval );
1167+ break ;
1168+ case PAGEFAULT_STORE :
1169+ rv_trap_pagefault_store (rv , stval );
1170+ break ;
1171+ #endif /* SYSTEM */
1172+ case ECALL_M :
1173+ break ;
1174+ default :
1175+ __UNREACHABLE ;
1176+ break ;
1177+ }
1178+ }
1179+
1180+ void trap_handler (riscv_t * rv )
1181+ {
1182+ assert (rv );
1183+ _trap_handler (rv );
1184+ }
1185+
11161186void ebreak_handler (riscv_t * rv )
11171187{
11181188 assert (rv );
1119- rv_trap_breakpoint (rv , rv -> PC );
1189+ SET_SCAUSE_AND_STVAL_THEN_TRAP (rv , BREAKPOINT , rv -> PC );
11201190}
11211191
11221192void ecall_handler (riscv_t * rv )
@@ -1126,7 +1196,7 @@ void ecall_handler(riscv_t *rv)
11261196 syscall_handler (rv );
11271197 rv -> PC += 4 ;
11281198#else
1129- rv_trap_ecall_M (rv , 0 );
1199+ SET_SCAUSE_AND_STVAL_THEN_TRAP (rv , ECALL_M , 0 );
11301200 syscall_handler (rv );
11311201#endif
11321202}
0 commit comments