Skip to content

Commit 6ba1546

Browse files
committed
test
1 parent b35f744 commit 6ba1546

File tree

5 files changed

+174
-91
lines changed

5 files changed

+174
-91
lines changed

src/emulate.c

Lines changed: 92 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
11161186
void 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

11221192
void 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
}

src/riscv.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,7 @@ typedef void (*riscv_on_ecall)(riscv_t *rv);
339339
typedef void (*riscv_on_ebreak)(riscv_t *rv);
340340
typedef void (*riscv_on_memset)(riscv_t *rv);
341341
typedef void (*riscv_on_memcpy)(riscv_t *rv);
342+
typedef void (*riscv_on_trap)(riscv_t *rv);
342343
/* RISC-V emulator I/O interface */
343344
typedef struct {
344345
/* memory read interface */
@@ -359,6 +360,7 @@ typedef struct {
359360
riscv_on_ebreak on_ebreak;
360361
riscv_on_memset on_memset;
361362
riscv_on_memcpy on_memcpy;
363+
riscv_on_trap on_trap;
362364
} riscv_io_t;
363365

364366
/* run emulation */
@@ -407,6 +409,9 @@ void syscall_handler(riscv_t *rv);
407409
/* environment call handler */
408410
void ecall_handler(riscv_t *rv);
409411

412+
/* trap handler */
413+
void trap_handler(riscv_t *rv);
414+
410415
/* memset handler */
411416
void memset_handler(riscv_t *rv);
412417

0 commit comments

Comments
 (0)