From 4bbb2c3a70d6adb4dbd98acf0ede601ad9e72576 Mon Sep 17 00:00:00 2001 From: qwe661234 Date: Sun, 11 Dec 2022 23:08:58 +0800 Subject: [PATCH] Shorten the time spent checking instruction length To avoid frequent instruction length checking, move checking into exception handler inoking block. Previously, we had to check the instruction length each time the function 'emulate' was called. Actually, we only need to check it when the exception occurs; otherwise, we can simply set 'rv->compressed' to the appropriate value before running the exception handler. By doing so, we can avoid the overhead of checking instruction length if an exception does not happen. Resolves: #92 --- src/emulate.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/emulate.c b/src/emulate.c index fa7515a7..6ea5ceef 100644 --- a/src/emulate.c +++ b/src/emulate.c @@ -256,9 +256,6 @@ static bool insn_is_misaligned(uint32_t pc) static bool emulate(riscv_t *rv, rv_insn_t *ir) { - /* check instruction is compressed or not */ - rv->compressed = (ir->insn_len == INSN_16); - switch (ir->opcode) { /* RV32I Base Instruction Set */ case rv_insn_lui: /* LUI: Load Upper Immediate */ @@ -290,6 +287,7 @@ static bool emulate(riscv_t *rv, rv_insn_t *ir) rv->X[ir->rd] = pc + ir->insn_len; /* check instruction misaligned */ if (insn_is_misaligned(rv->PC)) { + rv->compressed = false; rv_except_insn_misaligned(rv, pc); return false; } @@ -312,6 +310,7 @@ static bool emulate(riscv_t *rv, rv_insn_t *ir) rv->X[ir->rd] = pc + ir->insn_len; /* check instruction misaligned */ if (insn_is_misaligned(rv->PC)) { + rv->compressed = false; rv_except_insn_misaligned(rv, pc); return false; } @@ -324,6 +323,7 @@ static bool emulate(riscv_t *rv, rv_insn_t *ir) rv->PC += ir->imm; /* check instruction misaligned */ if (insn_is_misaligned(rv->PC)) { + rv->compressed = false; rv_except_insn_misaligned(rv, pc); return false; } @@ -338,6 +338,7 @@ static bool emulate(riscv_t *rv, rv_insn_t *ir) rv->PC += ir->imm; /* check instruction misaligned */ if (insn_is_misaligned(rv->PC)) { + rv->compressed = false; rv_except_insn_misaligned(rv, pc); return false; } @@ -352,6 +353,7 @@ static bool emulate(riscv_t *rv, rv_insn_t *ir) rv->PC += ir->imm; /* check instruction misaligned */ if (insn_is_misaligned(rv->PC)) { + rv->compressed = false; rv_except_insn_misaligned(rv, pc); return false; } @@ -366,6 +368,7 @@ static bool emulate(riscv_t *rv, rv_insn_t *ir) rv->PC += ir->imm; /* check instruction misaligned */ if (insn_is_misaligned(rv->PC)) { + rv->compressed = false; rv_except_insn_misaligned(rv, pc); return false; } @@ -380,6 +383,7 @@ static bool emulate(riscv_t *rv, rv_insn_t *ir) rv->PC += ir->imm; /* check instruction misaligned */ if (insn_is_misaligned(rv->PC)) { + rv->compressed = false; rv_except_insn_misaligned(rv, pc); return false; } @@ -394,6 +398,7 @@ static bool emulate(riscv_t *rv, rv_insn_t *ir) rv->PC += ir->imm; /* check instruction misaligned */ if (insn_is_misaligned(rv->PC)) { + rv->compressed = false; rv_except_insn_misaligned(rv, pc); return false; } @@ -409,6 +414,7 @@ static bool emulate(riscv_t *rv, rv_insn_t *ir) case rv_insn_lh: { /* LH: Load Halfword */ const uint32_t addr = rv->X[ir->rs1] + ir->imm; if (addr & 1) { + rv->compressed = false; rv_except_load_misaligned(rv, addr); return false; } @@ -418,6 +424,7 @@ static bool emulate(riscv_t *rv, rv_insn_t *ir) case rv_insn_lw: { /* LW: Load Word */ const uint32_t addr = rv->X[ir->rs1] + ir->imm; if (addr & 3) { + rv->compressed = false; rv_except_load_misaligned(rv, addr); return false; } @@ -430,6 +437,7 @@ static bool emulate(riscv_t *rv, rv_insn_t *ir) case rv_insn_lhu: { /* LHU: Load Halfword Unsigned */ const uint32_t addr = rv->X[ir->rs1] + ir->imm; if (addr & 1) { + rv->compressed = false; rv_except_load_misaligned(rv, addr); return false; } @@ -442,6 +450,7 @@ static bool emulate(riscv_t *rv, rv_insn_t *ir) case rv_insn_sh: { /* SH: Store Halfword */ const uint32_t addr = rv->X[ir->rs1] + ir->imm; if (addr & 1) { + rv->compressed = false; rv_except_store_misaligned(rv, addr); return false; } @@ -451,6 +460,7 @@ static bool emulate(riscv_t *rv, rv_insn_t *ir) case rv_insn_sw: { /* SW: Store Word */ const uint32_t addr = rv->X[ir->rs1] + ir->imm; if (addr & 3) { + rv->compressed = false; rv_except_store_misaligned(rv, addr); return false; } @@ -541,9 +551,11 @@ static bool emulate(riscv_t *rv, rv_insn_t *ir) rv->X[ir->rd] = rv->X[ir->rs1] & rv->X[ir->rs2]; break; case rv_insn_ecall: /* ECALL: Environment Call */ + rv->compressed = false; rv->io.on_ecall(rv); return true; case rv_insn_ebreak: /* EBREAK: Environment Break */ + rv->compressed = false; rv->io.on_ebreak(rv); return true; case rv_insn_wfi: /* WFI: Wait for Interrupt */ @@ -931,6 +943,7 @@ static bool emulate(riscv_t *rv, rv_insn_t *ir) */ const uint32_t addr = rv->X[ir->rs1] + (uint32_t) ir->imm; if (addr & 3) { + rv->compressed = true; rv_except_load_misaligned(rv, addr); return false; } @@ -945,6 +958,7 @@ static bool emulate(riscv_t *rv, rv_insn_t *ir) */ const uint32_t addr = rv->X[ir->rs1] + (uint32_t) ir->imm; if (addr & 3) { + rv->compressed = true; rv_except_store_misaligned(rv, addr); return false; } @@ -967,6 +981,7 @@ static bool emulate(riscv_t *rv, rv_insn_t *ir) rv->X[1] = rv->PC + ir->insn_len; rv->PC += ir->imm; if (rv->PC & 0x1) { + rv->compressed = true; rv_except_insn_misaligned(rv, rv->PC); return false; } @@ -1044,6 +1059,7 @@ static bool emulate(riscv_t *rv, rv_insn_t *ir) */ rv->PC += ir->imm; if (rv->PC & 0x1) { + rv->compressed = true; rv_except_insn_misaligned(rv, rv->PC); return false; } @@ -1074,6 +1090,7 @@ static bool emulate(riscv_t *rv, rv_insn_t *ir) case rv_insn_clwsp: { /* C.LWSP */ const uint32_t addr = rv->X[rv_reg_sp] + ir->imm; if (addr & 3) { + rv->compressed = true; rv_except_load_misaligned(rv, addr); return false; } @@ -1088,6 +1105,7 @@ static bool emulate(riscv_t *rv, rv_insn_t *ir) rv->X[ir->rd] = rv->X[ir->rs2]; break; case rv_insn_cebreak: /* C.EBREAK */ + rv->compressed = true; rv->io.on_ebreak(rv); /* can branch */ return true; @@ -1097,6 +1115,7 @@ static bool emulate(riscv_t *rv, rv_insn_t *ir) rv->X[rv_reg_ra] = rv->PC + ir->insn_len; rv->PC = jump_to; if (rv->PC & 0x1) { + rv->compressed = true; rv_except_insn_misaligned(rv, rv->PC); return false; } @@ -1116,6 +1135,7 @@ static bool emulate(riscv_t *rv, rv_insn_t *ir) case rv_insn_cswsp: { /* C.SWSP */ const uint32_t addr = rv->X[2] + ir->imm; if (addr & 3) { + rv->compressed = true; rv_except_store_misaligned(rv, addr); return false; } @@ -1252,6 +1272,7 @@ static void block_translate(riscv_t *rv, block_t *block) /* decode the instruction */ if (!rv_decode(ir, insn)) { + rv->compressed = (ir->insn_len == INSN_16); rv_except_illegal_insn(rv, insn); break; }