@@ -47,19 +47,19 @@ extern struct target_ops gdbstub_ops;
47
47
48
48
/* RISC-V trap code list */
49
49
/* 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 */ \
63
63
)
64
64
/* clang-format on */
65
65
@@ -75,6 +75,10 @@ static void rv_trap_default_handler(riscv_t *rv)
75
75
rv -> PC = rv -> csr_mepc ; /* mret */
76
76
}
77
77
78
+ #if RV32_HAS (SYSTEM )
79
+ static void __trap_handler (riscv_t * rv );
80
+ #endif /* SYSTEM */
81
+
78
82
/* When a trap occurs in M-mode/S-mode, m/stval is either initialized to zero or
79
83
* populated with exception-specific details to assist software in managing
80
84
* the trap. Otherwise, the implementation never modifies m/stval, although
@@ -95,7 +99,7 @@ static void rv_trap_default_handler(riscv_t *rv)
95
99
* identifier called tval, as both are handled by TRAP_HANDLER_IMPL.
96
100
*/
97
101
#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) \
99
103
{ \
100
104
/* m/stvec (Machine/Supervisor Trap-Vector Base Address Register) \
101
105
* m/stvec[MXLEN-1:2]: vector base address \
@@ -150,7 +154,7 @@ static void rv_trap_default_handler(riscv_t *rv)
150
154
rv -> PC = base + 4 * (code & MASK (31 )); \
151
155
break ; \
152
156
} \
153
- IIF (RV32_HAS (SYSTEM ))(if (rv -> is_trapped ) trap_handler (rv );, ) \
157
+ IIF (RV32_HAS (SYSTEM ))(if (rv -> is_trapped ) __trap_handler (rv );, ) \
154
158
}
155
159
156
160
/* RISC-V exception handlers */
@@ -173,7 +177,8 @@ RV_TRAP_LIST
173
177
rv->csr_cycle = cycle; \
174
178
rv->PC = PC; \
175
179
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)); \
177
182
return false; \
178
183
}
179
184
@@ -523,7 +528,7 @@ static bool do_fuse3(riscv_t *rv, rv_insn_t *ir, uint64_t cycle, uint32_t PC)
523
528
*/
524
529
for (int i = 0 ; i < ir -> imm2 ; i ++ ) {
525
530
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 );
527
532
rv -> io .mem_write_w (rv , addr , rv -> X [fuse [i ].rs2 ]);
528
533
}
529
534
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)
547
552
*/
548
553
for (int i = 0 ; i < ir -> imm2 ; i ++ ) {
549
554
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 );
551
556
rv -> X [fuse [i ].rd ] = rv -> io .mem_read_w (rv , addr );
552
557
}
553
558
PC += ir -> imm2 * 4 ;
@@ -581,7 +586,7 @@ static bool do_fuse5(riscv_t *rv,
581
586
}
582
587
583
588
/* clang-format off */
584
- const void * dispatch_table [] = {
589
+ static const void * dispatch_table [] = {
585
590
/* RV32 instructions */
586
591
#define _ (inst , can_branch , insn_len , translatable , reg_mask ) [rv_insn_ ##inst ] = do_ ##inst ,
587
592
RV_INSN_LIST
@@ -663,7 +668,7 @@ static void block_translate(riscv_t *rv, block_t *block)
663
668
/* decode the instruction */
664
669
if (!rv_decode (ir , insn )) {
665
670
rv -> compressed = is_compressed (insn );
666
- rv_trap_illegal_insn (rv , insn );
671
+ SET_SCAUSE_AND_STVAL_THEN_TRAP (rv , INSN_MISALIGNED , insn );
667
672
break ;
668
673
}
669
674
ir -> impl = dispatch_table [ir -> opcode ];
@@ -1113,10 +1118,75 @@ void rv_step(void *arg)
1113
1118
#endif
1114
1119
}
1115
1120
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
+
1116
1186
void ebreak_handler (riscv_t * rv )
1117
1187
{
1118
1188
assert (rv );
1119
- rv_trap_breakpoint (rv , rv -> PC );
1189
+ SET_SCAUSE_AND_STVAL_THEN_TRAP (rv , BREAKPOINT , rv -> PC );
1120
1190
}
1121
1191
1122
1192
void ecall_handler (riscv_t * rv )
@@ -1126,7 +1196,7 @@ void ecall_handler(riscv_t *rv)
1126
1196
syscall_handler (rv );
1127
1197
rv -> PC += 4 ;
1128
1198
#else
1129
- rv_trap_ecall_M (rv , 0 );
1199
+ SET_SCAUSE_AND_STVAL_THEN_TRAP (rv , ECALL_M , 0 );
1130
1200
syscall_handler (rv );
1131
1201
#endif
1132
1202
}
0 commit comments