@@ -52,7 +52,9 @@ extern struct target_ops gdbstub_ops;
5252 _(breakpoint, 3) /* Breakpoint */ \
5353 _ (load_misaligned , 4 ) /* Load address misaligned */ \
5454 _ (store_misaligned , 6 ) /* Store/AMO address misaligned */ \
55- _ (ecall_M , 11 ) /* Environment call from M-mode */
55+ IIF (RV32_HAS (SYSTEM ))(, \
56+ _ (ecall_M , 11 ) /* Environment call from M-mode */ \
57+ )
5658/* clang-format on */
5759
5860enum {
@@ -67,56 +69,57 @@ static void rv_trap_default_handler(riscv_t *rv)
6769 rv -> PC = rv -> csr_mepc ; /* mret */
6870}
6971
70- /* Trap might occurs during block emulation. For instance, page fault.
72+ /*
73+ * Trap might occurs during block emulation. For instance, page fault.
7174 * In order to handle trap, we have to escape from block and execute
7275 * registered trap handler. This trap_handler function helps to execute
7376 * the registered trap handler, PC by PC. Once the trap is handled,
7477 * resume the previous execution flow where cause the trap.
78+ *
79+ * Since the system emulation has not yet included in rv32emu, the page
80+ * fault is not practical in current test suite. Instead, we try to
81+ * emulate the misaligned handling in the test suite.
7582 */
7683#if RV32_HAS (SYSTEM )
7784static void trap_handler (riscv_t * rv );
78- #else
79- /* should not be called in non-SYSTEM mode since default trap handler is capable
80- * to handle traps
81- */
82- static void trap_handler (riscv_t * rv UNUSED ) {}
8385#endif
8486
85- /* When a trap occurs in M-mode, mtval is either initialized to zero or
87+ /* When a trap occurs in M-mode/S-mode, m/stval is either initialized to zero or
8688 * populated with exception-specific details to assist software in managing
87- * the trap. Otherwise, the implementation never modifies mtval , although
89+ * the trap. Otherwise, the implementation never modifies m/stval , although
8890 * software can explicitly write to it. The hardware platform will define
8991 * which exceptions are required to informatively set mtval and which may
9092 * consistently set it to zero.
9193 *
9294 * When a hardware breakpoint is triggered or an exception like address
9395 * misalignment, access fault, or page fault occurs during an instruction
94- * fetch, load, or store operation, mtval is updated with the virtual address
95- * that caused the fault. In the case of an illegal instruction trap, mtval
96+ * fetch, load, or store operation, m/stval is updated with the virtual address
97+ * that caused the fault. In the case of an illegal instruction trap, m/stval
9698 * might be updated with the first XLEN or ILEN bits of the offending
97- * instruction. For all other traps, mtval is simply set to zero. However,
98- * it is worth noting that a future standard could redefine how mtval is
99+ * instruction. For all other traps, m/stval is simply set to zero. However,
100+ * it is worth noting that a future standard could redefine how m/stval is
99101 * handled for different types of traps.
102+ *
103+ * For simplicity and clarity, abstracting stval and mtval into a single
104+ * identifier called tval, as both are handled by TRAP_HANDLER_IMPL.
100105 */
101- static jmp_buf env ;
106+ /* clang-format off */
102107#define TRAP_HANDLER_IMPL (type , code ) \
103- static void rv_trap_##type(riscv_t *rv, uint32_t mtval) \
108+ static void rv_trap_##type(riscv_t *rv, uint32_t tval) \
104109 { \
105110 /* m/stvec (Machine/Supervisor Trap-Vector Base Address Register) \
106111 * m/stvec[MXLEN-1:2]: vector base address \
107112 * m/stvec[1:0] : vector mode \
108- */ \
109- uint32_t base ; \
110- uint32_t mode ; \
111- /* m/sepc (Machine/Supervisor Exception Program Counter) \
113+ * m/sepc (Machine/Supervisor Exception Program Counter) \
112114 * m/stval (Machine/Supervisor Trap Value Register) \
113115 * m/scause (Machine/Supervisor Cause Register): store exception code \
114116 * m/sstatus (Machine/Supervisor Status Register): keep track of and \
115117 * controls the hart’s current operating state \
116118 */ \
117- /* supervisor */ \
118- if (rv -> csr_medeleg & (1U << code ) || \
119- rv -> csr_mideleg & (1U << code )) { \
119+ uint32_t base ; \
120+ uint32_t mode ; \
121+ /* user or supervisor */ \
122+ if (RV_PRIV_IS_U_OR_S_MODE ()) { \
120123 const uint32_t sstatus_sie = \
121124 (rv -> csr_sstatus & SSTATUS_SIE ) >> SSTATUS_SIE_SHIFT ; \
122125 rv -> csr_sstatus |= (sstatus_sie << SSTATUS_SPIE_SHIFT ); \
@@ -126,10 +129,9 @@ static jmp_buf env;
126129 base = rv -> csr_stvec & ~0x3 ; \
127130 mode = rv -> csr_stvec & 0x3 ; \
128131 rv -> csr_sepc = rv -> PC ; \
129- rv -> csr_stval = mtval ; \
132+ rv -> csr_stval = tval ; \
130133 rv -> csr_scause = code ; \
131- rv -> csr_sstatus |= SSTATUS_SPP ; /* set privilege mode */ \
132- } else { /* machine */ \
134+ } else { /* machine */ \
133135 const uint32_t mstatus_mie = \
134136 (rv -> csr_mstatus & MSTATUS_MIE ) >> MSTATUS_MIE_SHIFT ; \
135137 rv -> csr_mstatus |= (mstatus_mie << MSTATUS_MPIE_SHIFT ); \
@@ -139,9 +141,8 @@ static jmp_buf env;
139141 base = rv -> csr_mtvec & ~0x3 ; \
140142 mode = rv -> csr_mtvec & 0x3 ; \
141143 rv -> csr_mepc = rv -> PC ; \
142- rv -> csr_mtval = mtval ; \
144+ rv -> csr_mtval = tval ; \
143145 rv -> csr_mcause = code ; \
144- rv -> csr_mstatus |= MSTATUS_MPP ; /* set privilege mode */ \
145146 if (!rv -> csr_mtvec ) { /* in case CSR is not configured */ \
146147 rv_trap_default_handler (rv ); \
147148 return ; \
@@ -159,15 +160,12 @@ static jmp_buf env;
159160 rv -> PC = base + 4 * (code & MASK (31 )); \
160161 break ; \
161162 } \
162- /* block escaping for trap handling */ \
163- if (rv -> is_trapped ) { \
164- if (setjmp (env ) == 0 ) { \
165- trap_handler (rv ); \
166- } else { \
167- fprintf (stderr , "setjmp failed" ); \
168- } \
169- } \
163+ IIF (RV32_HAS (SYSTEM ))( \
164+ if (rv -> is_trapped ) \
165+ trap_handler (rv );, \
166+ ) \
170167 }
168+ /* clang-format off */
171169
172170/* RISC-V exception handlers */
173171#define _ (type , code ) TRAP_HANDLER_IMPL(type, code)
@@ -188,7 +186,7 @@ RV_TRAP_LIST
188186 rv->compressed = compress; \
189187 rv->csr_cycle = cycle; \
190188 rv->PC = PC; \
191- rv->is_trapped = true; \
189+ IIF(RV32_HAS(SYSTEM))( rv->is_trapped = true, ); \
192190 rv_trap_##type##_misaligned(rv, IIF(IO)(addr, mask_or_pc)); \
193191 return false; \
194192 }
@@ -455,9 +453,10 @@ enum {
455453};
456454
457455#if RV32_HAS (GDBSTUB )
458- #define RVOP_NO_NEXT (ir ) (!ir->next | rv->debug_mode | rv->is_trapped)
456+ #define RVOP_NO_NEXT (ir ) \
457+ (!ir->next | rv->debug_mode IIF(RV32_HAS(SYSTEM))(| rv->is_trapped,))
459458#else
460- #define RVOP_NO_NEXT (ir ) (!ir->next | rv->is_trapped)
459+ #define RVOP_NO_NEXT (ir ) (!ir->next IIF(RV32_HAS(SYSTEM))( | rv->is_trapped,) )
461460#endif
462461
463462/* record whether the branch is taken or not during emulation */
@@ -643,8 +642,10 @@ FORCE_INLINE bool insn_is_unconditional_branch(uint8_t opcode)
643642 case rv_insn_ebreak :
644643 case rv_insn_jal :
645644 case rv_insn_jalr :
646- case rv_insn_sret :
647645 case rv_insn_mret :
646+ #if RV32_HAS (SYSTEM )
647+ case rv_insn_sret :
648+ #endif
648649#if RV32_HAS (EXT_C )
649650 case rv_insn_cj :
650651 case rv_insn_cjalr :
@@ -1132,9 +1133,12 @@ static void trap_handler(riscv_t *rv)
11321133 rv_insn_t * ir = mpool_alloc (rv -> block_ir_mp );
11331134 assert (ir );
11341135
1136+ /* set to false by sret/mret implementation */
11351137 uint32_t insn ;
1136- while (rv -> is_trapped ) { /* set to false by sret/mret implementation */
1137- insn = rv -> io .mem_ifetch (rv , rv -> PC );
1138+ while (rv -> is_trapped && !rv_has_halted (rv )) {
1139+ insn = rv -> io .mem_ifetch (rv -> PC );
1140+ assert (insn );
1141+
11381142 rv_decode (ir , insn );
11391143 ir -> impl = dispatch_table [ir -> opcode ];
11401144 rv -> compressed = is_compressed (insn );
@@ -1152,8 +1156,13 @@ void ebreak_handler(riscv_t *rv)
11521156void ecall_handler (riscv_t * rv )
11531157{
11541158 assert (rv );
1159+ #if RV32_HAS (SYSTEM )
1160+ syscall_handler (rv );
1161+ rv -> PC += 4 ;
1162+ #else
11551163 rv_trap_ecall_M (rv , 0 );
11561164 syscall_handler (rv );
1165+ #endif
11571166}
11581167
11591168void memset_handler (riscv_t * rv )
0 commit comments