diff --git a/src/emulate.c b/src/emulate.c index b267fff6..035f8877 100644 --- a/src/emulate.c +++ b/src/emulate.c @@ -90,6 +90,19 @@ static void rv_exception_default_handler(riscv_t *rv) RV_EXCEPTION_LIST #undef _ +/* wrap load/store and insn misaligned handler */ +#define RV_EXC_MISAGLIN_HANDLER(mask_or_pc, type, compress, IO) \ + IIF(IO) \ + (if (!rv->io.allow_misalign && unlikely(addr & (mask_or_pc))), \ + if (unlikely(insn_is_misaligned(rv->PC)))) \ + { \ + rv->compressed = compress; \ + IIF(IO) \ + (rv_except_##type##_misaligned(rv, addr), \ + rv_except_##type##_misaligned(rv, mask_or_pc)); \ + return false; \ + } + /* Get current time in microsecnds and update csr_time register */ static inline void update_time(riscv_t *rv) { @@ -310,11 +323,7 @@ RVOP(jal, { if (ir->rd) rv->X[ir->rd] = pc + ir->insn_len; /* check instruction misaligned */ - if (unlikely(insn_is_misaligned(rv->PC))) { - rv->compressed = false; - rv_except_insn_misaligned(rv, pc); - return false; - } + RV_EXC_MISAGLIN_HANDLER(pc, insn, false, 0); return true; }) @@ -333,11 +342,7 @@ RVOP(jalr, { if (ir->rd) rv->X[ir->rd] = pc + ir->insn_len; /* check instruction misaligned */ - if (unlikely(insn_is_misaligned(rv->PC))) { - rv->compressed = false; - rv_except_insn_misaligned(rv, pc); - return false; - } + RV_EXC_MISAGLIN_HANDLER(pc, insn, false, 0); return true; }) @@ -352,11 +357,7 @@ RVOP(beq, { } rv->PC += ir->imm; /* check instruction misaligned */ - if (unlikely(insn_is_misaligned(rv->PC))) { - rv->compressed = false; - rv_except_insn_misaligned(rv, pc); - return false; - } + RV_EXC_MISAGLIN_HANDLER(pc, insn, false, 0); if (ir->branch_taken) return ir->branch_taken->impl(rv, ir->branch_taken); return true; @@ -373,11 +374,7 @@ RVOP(bne, { } rv->PC += ir->imm; /* check instruction misaligned */ - if (unlikely(insn_is_misaligned(rv->PC))) { - rv->compressed = false; - rv_except_insn_misaligned(rv, pc); - return false; - } + RV_EXC_MISAGLIN_HANDLER(pc, insn, false, 0); if (ir->branch_taken) return ir->branch_taken->impl(rv, ir->branch_taken); return true; @@ -394,11 +391,7 @@ RVOP(blt, { } rv->PC += ir->imm; /* check instruction misaligned */ - if (unlikely(insn_is_misaligned(rv->PC))) { - rv->compressed = false; - rv_except_insn_misaligned(rv, pc); - return false; - } + RV_EXC_MISAGLIN_HANDLER(pc, insn, false, 0); if (ir->branch_taken) return ir->branch_taken->impl(rv, ir->branch_taken); return true; @@ -415,11 +408,7 @@ RVOP(bge, { } rv->PC += ir->imm; /* check instruction misaligned */ - if (unlikely(insn_is_misaligned(rv->PC))) { - rv->compressed = false; - rv_except_insn_misaligned(rv, pc); - return false; - } + RV_EXC_MISAGLIN_HANDLER(pc, insn, false, 0); if (ir->branch_taken) return ir->branch_taken->impl(rv, ir->branch_taken); return true; @@ -436,11 +425,7 @@ RVOP(bltu, { } rv->PC += ir->imm; /* check instruction misaligned */ - if (unlikely(insn_is_misaligned(rv->PC))) { - rv->compressed = false; - rv_except_insn_misaligned(rv, pc); - return false; - } + RV_EXC_MISAGLIN_HANDLER(pc, insn, false, 0); if (ir->branch_taken) return ir->branch_taken->impl(rv, ir->branch_taken); return true; @@ -457,11 +442,7 @@ RVOP(bgeu, { } rv->PC += ir->imm; /* check instruction misaligned */ - if (unlikely(insn_is_misaligned(rv->PC))) { - rv->compressed = false; - rv_except_insn_misaligned(rv, pc); - return false; - } + RV_EXC_MISAGLIN_HANDLER(pc, insn, false, 0); if (ir->branch_taken) return ir->branch_taken->impl(rv, ir->branch_taken); return true; @@ -476,22 +457,14 @@ RVOP(lb, { /* LH: Load Halfword */ RVOP(lh, { const uint32_t addr = rv->X[ir->rs1] + ir->imm; - if (unlikely(addr & 1)) { - rv->compressed = false; - rv_except_load_misaligned(rv, addr); - return false; - } + RV_EXC_MISAGLIN_HANDLER(1, load, false, 1); rv->X[ir->rd] = sign_extend_h(rv->io.mem_read_s(rv, addr)); }) /* LW: Load Word */ RVOP(lw, { const uint32_t addr = rv->X[ir->rs1] + ir->imm; - if (unlikely(addr & 3)) { - rv->compressed = false; - rv_except_load_misaligned(rv, addr); - return false; - } + RV_EXC_MISAGLIN_HANDLER(3, load, false, 1); rv->X[ir->rd] = rv->io.mem_read_w(rv, addr); }) @@ -501,11 +474,7 @@ RVOP(lbu, { rv->X[ir->rd] = rv->io.mem_read_b(rv, rv->X[ir->rs1] + ir->imm); }) /* LHU: Load Halfword Unsigned */ RVOP(lhu, { const uint32_t addr = rv->X[ir->rs1] + ir->imm; - if (unlikely(addr & 1)) { - rv->compressed = false; - rv_except_load_misaligned(rv, addr); - return false; - } + RV_EXC_MISAGLIN_HANDLER(1, load, false, 1); rv->X[ir->rd] = rv->io.mem_read_s(rv, addr); }) @@ -515,22 +484,14 @@ RVOP(sb, { rv->io.mem_write_b(rv, rv->X[ir->rs1] + ir->imm, rv->X[ir->rs2]); }) /* SH: Store Halfword */ RVOP(sh, { const uint32_t addr = rv->X[ir->rs1] + ir->imm; - if (unlikely(addr & 1)) { - rv->compressed = false; - rv_except_store_misaligned(rv, addr); - return false; - } + RV_EXC_MISAGLIN_HANDLER(1, store, false, 1); rv->io.mem_write_s(rv, addr, rv->X[ir->rs2]); }) /* SW: Store Word */ RVOP(sw, { const uint32_t addr = rv->X[ir->rs1] + ir->imm; - if (unlikely(addr & 3)) { - rv->compressed = false; - rv_except_store_misaligned(rv, addr); - return false; - } + RV_EXC_MISAGLIN_HANDLER(3, store, false, 1); rv->io.mem_write_w(rv, addr, rv->X[ir->rs2]); }) @@ -1088,11 +1049,7 @@ RVOP(caddi4spn, { rv->X[ir->rd] = rv->X[2] + (uint16_t) ir->imm; }) */ RVOP(clw, { const uint32_t addr = rv->X[ir->rs1] + (uint32_t) ir->imm; - if (unlikely(addr & 3)) { - rv->compressed = true; - rv_except_load_misaligned(rv, addr); - return false; - } + RV_EXC_MISAGLIN_HANDLER(3, load, true, 1); rv->X[ir->rd] = rv->io.mem_read_w(rv, addr); }) @@ -1103,11 +1060,7 @@ RVOP(clw, { */ RVOP(csw, { const uint32_t addr = rv->X[ir->rs1] + (uint32_t) ir->imm; - if (unlikely(addr & 3)) { - rv->compressed = true; - rv_except_store_misaligned(rv, addr); - return false; - } + RV_EXC_MISAGLIN_HANDLER(3, store, true, 1); rv->io.mem_write_w(rv, addr, rv->X[ir->rs2]); }) @@ -1126,11 +1079,7 @@ RVOP(caddi, { rv->X[ir->rd] += (int16_t) ir->imm; }) RVOP(cjal, { rv->X[1] = rv->PC + ir->insn_len; rv->PC += ir->imm; - if (unlikely(rv->PC & 0x1)) { - rv->compressed = true; - rv_except_insn_misaligned(rv, rv->PC); - return false; - } + RV_EXC_MISAGLIN_HANDLER(rv->PC, insn, true, 0); return true; }) @@ -1198,11 +1147,7 @@ RVOP(cand, { rv->X[ir->rd] = rv->X[ir->rs1] & rv->X[ir->rs2]; }) */ RVOP(cj, { rv->PC += ir->imm; - if (unlikely(rv->PC & 0x1)) { - rv->compressed = true; - rv_except_insn_misaligned(rv, rv->PC); - return false; - } + RV_EXC_MISAGLIN_HANDLER(rv->PC, insn, true, 0); return true; }) @@ -1249,11 +1194,7 @@ RVOP(cslli, { rv->X[ir->rd] <<= (uint8_t) ir->imm; }) /* C.LWSP */ RVOP(clwsp, { const uint32_t addr = rv->X[rv_reg_sp] + ir->imm; - if (unlikely(addr & 3)) { - rv->compressed = true; - rv_except_load_misaligned(rv, addr); - return false; - } + RV_EXC_MISAGLIN_HANDLER(3, load, true, 1); rv->X[ir->rd] = rv->io.mem_read_w(rv, addr); }) @@ -1279,11 +1220,7 @@ RVOP(cjalr, { const int32_t jump_to = rv->X[ir->rs1]; rv->X[rv_reg_ra] = rv->PC + ir->insn_len; rv->PC = jump_to; - if (unlikely(rv->PC & 0x1)) { - rv->compressed = true; - rv_except_insn_misaligned(rv, rv->PC); - return false; - } + RV_EXC_MISAGLIN_HANDLER(rv->PC, insn, true, 0); return true; }) @@ -1299,11 +1236,7 @@ RVOP(cadd, { rv->X[ir->rd] = rv->X[ir->rs1] + rv->X[ir->rs2]; }) /* C.SWSP */ RVOP(cswsp, { const uint32_t addr = rv->X[2] + ir->imm; - if (unlikely(addr & 3)) { - rv->compressed = true; - rv_except_store_misaligned(rv, addr); - return false; - } + RV_EXC_MISAGLIN_HANDLER(3, store, true, 1); rv->io.mem_write_w(rv, addr, rv->X[ir->rs2]); }) #endif diff --git a/src/main.c b/src/main.c index 14945c19..6a615498 100644 --- a/src/main.c +++ b/src/main.c @@ -25,6 +25,9 @@ static char *signature_out_file; /* target executable */ static const char *opt_prog_name = "a.out"; +/* enable misaligned memory access */ +static bool opt_misaligned = false; + #define MEMIO(op) on_mem_##op #define IO_HANDLER_IMPL(type, op, RW) \ static IIF(RW)( \ @@ -123,6 +126,12 @@ static bool parse_args(int argc, char **args) signature_out_file = args[++i]; continue; } + + if (!strcmp(arg, "--misalign")) { + opt_misaligned = true; + continue; + } + /* otherwise, error */ fprintf(stderr, "Unknown argument '%s'\n", arg); return false; @@ -192,6 +201,7 @@ int main(int argc, char **args) /* system */ .on_ecall = ecall_handler, .on_ebreak = ebreak_handler, + .allow_misalign = opt_misaligned, }; state_t *state = state_new(); diff --git a/src/riscv.h b/src/riscv.h index cb96847d..271bdc24 100644 --- a/src/riscv.h +++ b/src/riscv.h @@ -107,6 +107,9 @@ typedef struct { /* system */ riscv_on_ecall on_ecall; riscv_on_ebreak on_ebreak; + + /* enable misaligned memory access */ + bool allow_misalign; } riscv_io_t; /* create a RISC-V emulator */