14
14
#include <emscripten.h>
15
15
#endif
16
16
17
+ #if RV32_HAS (SYSTEM )
18
+ #include "system.h"
19
+ #endif /* RV32_HAS(SYSTEM) */
20
+
17
21
#if RV32_HAS (EXT_F )
18
22
#include <math.h>
19
23
#include "softfloat.h"
@@ -41,18 +45,21 @@ extern struct target_ops gdbstub_ops;
41
45
#define IF_rs2 (i , r ) (i->rs2 == rv_reg_##r)
42
46
#define IF_imm (i , v ) (i->imm == v)
43
47
44
- /* RISC-V exception code list */
48
+ /* RISC-V trap code list */
45
49
/* 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 */ \
56
63
)
57
64
/* clang-format on */
58
65
@@ -68,20 +75,9 @@ static void rv_trap_default_handler(riscv_t *rv)
68
75
rv -> PC = rv -> csr_mepc ; /* mret */
69
76
}
70
77
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
- */
82
78
#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 */
85
81
86
82
/* When a trap occurs in M-mode/S-mode, m/stval is either initialized to zero or
87
83
* populated with exception-specific details to assist software in managing
@@ -158,7 +154,7 @@ static void trap_handler(riscv_t *rv);
158
154
rv -> PC = base + 4 * (code & MASK (31 )); \
159
155
break ; \
160
156
} \
161
- IIF (RV32_HAS (SYSTEM ))(if (rv -> is_trapped ) trap_handler (rv );, ) \
157
+ IIF (RV32_HAS (SYSTEM ))(if (rv -> is_trapped ) __trap_handler (rv );, ) \
162
158
}
163
159
164
160
/* RISC-V exception handlers */
@@ -180,8 +176,8 @@ RV_TRAP_LIST
180
176
rv->compressed = compress; \
181
177
rv->csr_cycle = cycle; \
182
178
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)); \
185
181
return false; \
186
182
}
187
183
@@ -531,8 +527,8 @@ static bool do_fuse3(riscv_t *rv, rv_insn_t *ir, uint64_t cycle, uint32_t PC)
531
527
*/
532
528
for (int i = 0 ; i < ir -> imm2 ; i ++ ) {
533
529
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 ]);
536
532
}
537
533
PC += ir -> imm2 * 4 ;
538
534
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)
555
551
*/
556
552
for (int i = 0 ; i < ir -> imm2 ; i ++ ) {
557
553
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 );
560
556
}
561
557
PC += ir -> imm2 * 4 ;
562
558
if (unlikely (RVOP_NO_NEXT (ir ))) {
@@ -666,12 +662,12 @@ static void block_translate(riscv_t *rv, block_t *block)
666
662
prev_ir -> next = ir ;
667
663
668
664
/* 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 );
670
666
671
667
/* decode the instruction */
672
668
if (!rv_decode (ir , insn )) {
673
669
rv -> compressed = is_compressed (insn );
674
- rv_trap_illegal_insn (rv , insn );
670
+ SET_CAUSE_AND_TVAL_THEN_TRAP (rv , INSN_MISALIGNED , insn );
675
671
break ;
676
672
}
677
673
ir -> impl = dispatch_table [ir -> opcode ];
@@ -1122,15 +1118,14 @@ void rv_step(void *arg)
1122
1118
}
1123
1119
1124
1120
#if RV32_HAS (SYSTEM )
1125
- static void trap_handler (riscv_t * rv )
1121
+ static void __trap_handler (riscv_t * rv )
1126
1122
{
1127
1123
rv_insn_t * ir = mpool_alloc (rv -> block_ir_mp );
1128
1124
assert (ir );
1129
1125
1130
- /* set to false by sret/mret implementation */
1131
- uint32_t insn ;
1126
+ /* set to false by sret implementation */
1132
1127
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 );
1134
1129
assert (insn );
1135
1130
1136
1131
rv_decode (ir , insn );
@@ -1139,12 +1134,63 @@ static void trap_handler(riscv_t *rv)
1139
1134
ir -> impl (rv , ir , rv -> csr_cycle , rv -> PC );
1140
1135
}
1141
1136
}
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
+ }
1143
1189
1144
1190
void ebreak_handler (riscv_t * rv )
1145
1191
{
1146
1192
assert (rv );
1147
- rv_trap_breakpoint (rv , rv -> PC );
1193
+ SET_CAUSE_AND_TVAL_THEN_TRAP (rv , BREAKPOINT , rv -> PC );
1148
1194
}
1149
1195
1150
1196
void ecall_handler (riscv_t * rv )
@@ -1154,7 +1200,7 @@ void ecall_handler(riscv_t *rv)
1154
1200
syscall_handler (rv );
1155
1201
rv -> PC += 4 ;
1156
1202
#else
1157
- rv_trap_ecall_M (rv , 0 );
1203
+ SET_CAUSE_AND_TVAL_THEN_TRAP (rv , ECALL_M , 0 );
1158
1204
syscall_handler (rv );
1159
1205
#endif
1160
1206
}
0 commit comments