From 1234260be16496c4fb7202ac16ab83057edbebcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D9=85=D8=B5=D8=B7=D9=81=D9=8A=20=D9=85=D8=AD=D9=85=D9=88?= =?UTF-8?q?=D8=AF=20=D9=83=D9=85=D8=A7=D9=84=20=D8=A7=D9=84=D8=AF=D9=8A?= =?UTF-8?q?=D9=86?= <48567303+moste00@users.noreply.github.com> Date: Sat, 25 Apr 2026 23:42:01 +0300 Subject: [PATCH 1/8] lifting the base (integer) extension of RISC-V and some compressed variants of the instructions in it for 32-bit arch variant only, and add some tests --- librz/arch/il/analysis_il.c | 1 + librz/arch/isa/riscv/riscv_il.c | 292 +++++++++++++++++++++ librz/arch/isa/riscv/riscv_il.h | 20 ++ librz/arch/meson.build | 1 + librz/arch/p/analysis/analysis_riscv_cs.c | 10 +- test/db/asm/riscv_32 | 296 ++++++++++++---------- 6 files changed, 479 insertions(+), 141 deletions(-) create mode 100644 librz/arch/isa/riscv/riscv_il.c create mode 100644 librz/arch/isa/riscv/riscv_il.h diff --git a/librz/arch/il/analysis_il.c b/librz/arch/il/analysis_il.c index 8101846aa04..84cebddda77 100644 --- a/librz/arch/il/analysis_il.c +++ b/librz/arch/il/analysis_il.c @@ -140,6 +140,7 @@ static RzILRegBinding *setup_reg_binding(RzAnalysis *a, RzAnalysisILConfig *cfg) goto new_real; } succ = rz_reg_set_profile_string(reg, profile); + free(profile); if (!succ) { goto new_real; diff --git a/librz/arch/isa/riscv/riscv_il.c b/librz/arch/isa/riscv/riscv_il.c new file mode 100644 index 00000000000..37a2b1601eb --- /dev/null +++ b/librz/arch/isa/riscv/riscv_il.c @@ -0,0 +1,292 @@ +// SPDX-FileCopyrightText: 2026 Mostafa Mahmoud +// SPDX-License-Identifier: BSD-3-Clause +#include "analysis_private.h" +#include "riscv.h" +#include "rz_il/rz_il_opcodes.h" +#include "rz_types.h" +#include "rz_util/rz_assert.h" +#include +#include "riscv_il.h" + +#include +static const char *riscv_register_names[] = { + [RISCV_REG_X1] = "ra", + [RISCV_REG_X2] = "sp", + [RISCV_REG_X3] = "gp", + [RISCV_REG_X4] = "tp", + [RISCV_REG_X5] = "t0", + [RISCV_REG_X6] = "t1", + [RISCV_REG_X7] = "t2", + [RISCV_REG_X8] = "s0", + [RISCV_REG_X9] = "s1", + [RISCV_REG_X10] = "a0", + [RISCV_REG_X11] = "a1", + [RISCV_REG_X12] = "a2", + [RISCV_REG_X13] = "a3", + [RISCV_REG_X14] = "a4", + [RISCV_REG_X15] = "a5", + [RISCV_REG_X16] = "a6", + [RISCV_REG_X17] = "a7", + [RISCV_REG_X18] = "s2", + [RISCV_REG_X19] = "s3", + [RISCV_REG_X20] = "s4", + [RISCV_REG_X21] = "s5", + [RISCV_REG_X22] = "s6", + [RISCV_REG_X23] = "s7", + [RISCV_REG_X24] = "s8", + [RISCV_REG_X25] = "s9", + [RISCV_REG_X26] = "s10", + [RISCV_REG_X27] = "s11", + [RISCV_REG_X28] = "t3", + [RISCV_REG_X29] = "t4", + [RISCV_REG_X30] = "t5", + [RISCV_REG_X31] = "t6", +}; + +#define RISCV_GET_REG(reg) (((reg) != RISCV_REG_X0) ? (VARG(riscv_register_names[reg])) : UN(analysis->bits, 0)) +#define RISCV_SET_REG(reg, r) (((reg) != RISCV_REG_X0) ? (SETG(riscv_register_names[reg], r)) : ((rz_il_op_pure_free(r), NOP()))) + +#define DEFINE_LIFTER(name, decoder, result) \ + static RzILOpEffect *rz_riscv_lift_##name(RZ_BORROW RZ_NONNULL RzAnalysis *analysis, \ + RZ_NONNULL RzAnalysisOp *op, RZ_NONNULL cs_insn *insn, ut64 current_addr, int size) { \ + decoder(analysis, insn); \ + return RISCV_SET_REG(rd, result); \ + } + +// by default, a RISC-V jump both sets a destination and sets the PC (i.e., jumps) +#define DEFINE_LIFTER_FOR_JUMP(name, decoder, result, jmp_effect) \ + static RzILOpEffect *rz_riscv_lift_##name(RZ_BORROW RZ_NONNULL RzAnalysis *analysis, \ + RZ_NONNULL RzAnalysisOp *op, RZ_NONNULL cs_insn *insn, ut64 current_addr, int size) { \ + decoder(analysis, insn); \ + return SEQ2( \ + RISCV_SET_REG(rd, result), \ + jmp_effect); \ + } + +#define DEFINE_LIFTER_WITH_EFFECT(name, decoder, effect) \ + static RzILOpEffect *rz_riscv_lift_##name(RZ_BORROW RZ_NONNULL RzAnalysis *analysis, \ + RZ_NONNULL RzAnalysisOp *op, RZ_NONNULL cs_insn *insn, ut64 current_addr, int size) { \ + decoder(analysis, insn); \ + return effect; \ + } + +// oneway jumps are those that don't have a destination register +#define DEFINE_LIFTER_FOR_ONEWAY_JUMP DEFINE_LIFTER_WITH_EFFECT + +#define TWICE_FOR(name1, name2, lifter, ...) \ + lifter(name1, __VA_ARGS__) \ + lifter(name2, __VA_ARGS__) + +#define THRICE_FOR(name1, name2, name3, lifter, ...) \ + TWICE_FOR(name1, name2, lifter, __VA_ARGS__) \ + lifter(name3, __VA_ARGS__) + +#define FOR_4(name1, name2, name3, name4, lifter, ...) \ + TWICE_FOR(name1, name2, lifter, __VA_ARGS__) \ + TWICE_FOR(name3, name4, lifter, __VA_ARGS__) + +#define DECODE_RD_RS_IMM(analysis, insn) \ + uint32_t rd = insn->detail->riscv.operands[0].reg; \ + RzILOpBitVector *rs = RISCV_GET_REG(insn->detail->riscv.operands[1].reg); \ + RzILOpBitVector *imm = SN(analysis->bits, insn->detail->riscv.operands[2].imm); + +#define DECODE_RD_RS_RS(analysis, insn) \ + uint32_t rd = insn->detail->riscv.operands[0].reg; \ + RzILOpBitVector *rs1 = RISCV_GET_REG(insn->detail->riscv.operands[1].reg); \ + RzILOpBitVector *rs2 = RISCV_GET_REG(insn->detail->riscv.operands[2].reg); + +#define DECODE_RS_IMM(analysis, insn) \ + RzILOpBitVector *rs = RISCV_GET_REG(insn->detail->riscv.operands[0].reg); \ + RzILOpBitVector *imm = SN(analysis->bits, insn->detail->riscv.operands[1].imm); + +#define DECODE_RS_RS_IMM(analysis, insn) \ + RzILOpBitVector *rs1 = RISCV_GET_REG(insn->detail->riscv.operands[0].reg); \ + RzILOpBitVector *rs2 = RISCV_GET_REG(insn->detail->riscv.operands[1].reg); \ + RzILOpBitVector *imm = SN(analysis->bits, insn->detail->riscv.operands[2].imm); + +#define DECODE_RD_RS(analysis, insn) \ + uint32_t rd = insn->detail->riscv.operands[0].reg; \ + RzILOpBitVector *rs = RISCV_GET_REG(insn->detail->riscv.operands[1].reg); + +#define DECODE_IMM(analysis, insn) \ + RzILOpBitVector *imm = SN(analysis->bits, insn->detail->riscv.operands[0].imm); + +#define DECODE_RD_IMM(analysis, insn) \ + uint32_t rd = insn->detail->riscv.operands[0].reg; \ + RzILOpBitVector *imm = SN(analysis->bits, insn->detail->riscv.operands[1].imm); + +#define DECODE_RS_RS_IMM_MEM(analysis, insn) \ + RzILOpBitVector *rs1 = RISCV_GET_REG(insn->detail->riscv.operands[0].reg); \ + RzILOpBitVector *rs2 = RISCV_GET_REG(insn->detail->riscv.operands[1].mem.base); \ + RzILOpBitVector *imm = SN(analysis->bits, insn->detail->riscv.operands[1].mem.disp); + +#define DECODE_RD_RS_IMM_MEM(analysis, insn) \ + uint32_t rd = insn->detail->riscv.operands[0].reg; \ + RzILOpBitVector *rs = RISCV_GET_REG(insn->detail->riscv.operands[1].mem.base); \ + RzILOpBitVector *imm = SN(analysis->bits, insn->detail->riscv.operands[1].mem.disp); + +#define USE_LIFTER(name, uppername) [RISCV_INS_##uppername] = rz_riscv_lift_##name + +FOR_4(addi, c_addi, c_addi16sp, c_addi4spn, + DEFINE_LIFTER, DECODE_RD_RS_IMM, ADD(rs, imm)) +TWICE_FOR(slli, c_slli, + DEFINE_LIFTER, DECODE_RD_RS_IMM, SHIFTL0(rs, imm)) +TWICE_FOR(andi, c_andi, + DEFINE_LIFTER, DECODE_RD_RS_IMM, LOGAND(rs, imm)) +DEFINE_LIFTER(ori, DECODE_RD_RS_IMM, LOGOR(rs, imm)) +DEFINE_LIFTER(xori, DECODE_RD_RS_IMM, LOGXOR(rs, imm)) +DEFINE_LIFTER(slti, DECODE_RD_RS_IMM, BOOL_TO_BV(SLT(rs, imm), analysis->bits)) +DEFINE_LIFTER(sltiu, DECODE_RD_RS_IMM, BOOL_TO_BV(ULT(rs, imm), analysis->bits)) +TWICE_FOR(srli, c_srli, + DEFINE_LIFTER, DECODE_RD_RS_IMM, SHIFTR0(rs, imm)) +TWICE_FOR(srai, c_srai, + DEFINE_LIFTER, DECODE_RD_RS_IMM, SHIFTRA(rs, imm)) + +DEFINE_LIFTER(add, DECODE_RD_RS_RS, ADD(rs1, rs2)) +DEFINE_LIFTER(sub, DECODE_RD_RS_RS, SUB(rs1, rs2)) +DEFINE_LIFTER(and, DECODE_RD_RS_RS, LOGAND(rs1, rs2)) +DEFINE_LIFTER(or, DECODE_RD_RS_RS, LOGOR(rs1, rs2)) +DEFINE_LIFTER(xor, DECODE_RD_RS_RS, LOGXOR(rs1, rs2)) +DEFINE_LIFTER(slt, DECODE_RD_RS_RS, BOOL_TO_BV(SLT(rs1, rs2), analysis->bits)) +DEFINE_LIFTER(sltu, DECODE_RD_RS_RS, BOOL_TO_BV(ULT(rs1, rs2), analysis->bits)) +DEFINE_LIFTER(sll, DECODE_RD_RS_RS, SHIFTL0(rs1, rs2)) +DEFINE_LIFTER(srl, DECODE_RD_RS_RS, SHIFTR0(rs1, rs2)) +DEFINE_LIFTER(sra, DECODE_RD_RS_RS, SHIFTRA(rs1, rs2)) + +#define DEFINE_LIFTER_FOR_BRANCH(name, decoder, condition) \ + DEFINE_LIFTER_FOR_ONEWAY_JUMP(name, decoder, BRANCH(condition, JMP(imm), JMP(UN(analysis->bits, current_addr + size)))) + +DEFINE_LIFTER_FOR_BRANCH(beq, DECODE_RS_RS_IMM, EQ(rs1, rs2)) +DEFINE_LIFTER_FOR_BRANCH(bne, DECODE_RS_RS_IMM, NE(rs1, rs2)) +DEFINE_LIFTER_FOR_BRANCH(blt, DECODE_RS_RS_IMM, SLT(rs1, rs2)) +DEFINE_LIFTER_FOR_BRANCH(bge, DECODE_RS_RS_IMM, SGE(rs1, rs2)) +DEFINE_LIFTER_FOR_BRANCH(bltu, DECODE_RS_RS_IMM, ULT(rs1, rs2)) +DEFINE_LIFTER_FOR_BRANCH(bgeu, DECODE_RS_RS_IMM, UGE(rs1, rs2)) + +DEFINE_LIFTER_FOR_BRANCH(c_beqz, DECODE_RS_IMM, EQ(rs, UN(analysis->bits, 0))) +DEFINE_LIFTER_FOR_BRANCH(c_bnez, DECODE_RS_IMM, NE(rs, UN(analysis->bits, 0))) + +DEFINE_LIFTER(c_mv, DECODE_RD_RS, DUP(rs)) + +DEFINE_LIFTER_FOR_ONEWAY_JUMP(c_j, DECODE_IMM, JMP(imm)) + +DEFINE_LIFTER_FOR_JUMP(jal, DECODE_RD_IMM, + /*RETURN ADDR*/ UN(analysis->bits, current_addr + size), + /*GOTO ADDR*/ JMP(imm)) + +TWICE_FOR(jalr, c_jr, + DEFINE_LIFTER_FOR_JUMP, DECODE_RD_RS_IMM, + /*RETURN ADDR*/ UN(analysis->bits, current_addr + size), + /*GOTO ADDR*/ JMP(LOGAND(ADD(rs, imm), UN(analysis->bits, ~1ULL)))) + +TWICE_FOR(lui, c_lui, + DEFINE_LIFTER, DECODE_RD_IMM, SHIFTL0(imm, UN(analysis->bits, 12))) +DEFINE_LIFTER(c_li, DECODE_RD_IMM, DUP(imm)) +DEFINE_LIFTER(auipc, DECODE_RD_IMM, ADD(UN(analysis->bits, current_addr), SHIFTL0(imm, UN(analysis->bits, 12)))) + +DEFINE_LIFTER_WITH_EFFECT(sb, DECODE_RS_RS_IMM_MEM, STOREW(ADD(rs2, imm), CAST(8, IL_FALSE, rs1))) +DEFINE_LIFTER_WITH_EFFECT(sh, DECODE_RS_RS_IMM_MEM, STOREW(ADD(rs2, imm), CAST(16, IL_FALSE, rs1))) + +THRICE_FOR(sw, c_sw, c_swsp, + DEFINE_LIFTER_WITH_EFFECT, DECODE_RS_RS_IMM_MEM, STOREW(ADD(rs2, imm), analysis->bits == 32 ? rs1 : CAST(64, IL_FALSE, rs1))) + +TWICE_FOR(sd, c_sd, + DEFINE_LIFTER_WITH_EFFECT, DECODE_RS_RS_IMM_MEM, STOREW(ADD(rs2, imm), rs1)) + +THRICE_FOR(lw, c_lwsp, c_lw, + DEFINE_LIFTER, DECODE_RD_RS_IMM_MEM, analysis->bits == 32 ? LOADW(32, ADD(rs, imm)) : SIGNED(analysis->bits, LOADW(32, ADD(rs, imm)))) +DEFINE_LIFTER(lb, DECODE_RD_RS_IMM_MEM, SIGNED(analysis->bits, LOADW(8, ADD(rs, imm)))) +DEFINE_LIFTER(lh, DECODE_RD_RS_IMM_MEM, SIGNED(analysis->bits, LOADW(16, ADD(rs, imm)))) +DEFINE_LIFTER(lbu, DECODE_RD_RS_IMM_MEM, UNSIGNED(analysis->bits, LOADW(8, ADD(rs, imm)))) +DEFINE_LIFTER(lhu, DECODE_RD_RS_IMM_MEM, UNSIGNED(analysis->bits, LOADW(16, ADD(rs, imm)))) + +TWICE_FOR(ld, c_ld, + DEFINE_LIFTER, DECODE_RD_RS_IMM_MEM, LOADW(64, ADD(rs, imm))) + +#include + +static const RiscvInstructionLifter riscv_lifters[] = { + USE_LIFTER(addi, ADDI), + USE_LIFTER(c_addi, C_ADDI), + USE_LIFTER(c_addi16sp, C_ADDI16SP), + USE_LIFTER(c_addi4spn, C_ADDI4SPN), + USE_LIFTER(andi, ANDI), + USE_LIFTER(c_andi, C_ANDI), + USE_LIFTER(ori, ORI), + USE_LIFTER(xori, XORI), + USE_LIFTER(slti, SLTI), + USE_LIFTER(sltiu, SLTIU), + USE_LIFTER(slli, SLLI), + USE_LIFTER(srli, SRLI), + USE_LIFTER(srai, SRAI), + USE_LIFTER(c_slli, C_SLLI), + USE_LIFTER(c_srli, C_SRLI), + USE_LIFTER(c_srai, C_SRAI), + USE_LIFTER(jalr, JALR), + USE_LIFTER(c_jr, C_JR), + USE_LIFTER(lb, LB), + USE_LIFTER(lh, LH), + USE_LIFTER(lw, LW), + USE_LIFTER(lbu, LBU), + USE_LIFTER(lhu, LHU), + USE_LIFTER(c_lwsp, C_LWSP), + USE_LIFTER(c_lw, C_LW), + USE_LIFTER(ld, LD), + USE_LIFTER(c_ld, C_LD), + USE_LIFTER(lui, LUI), + USE_LIFTER(c_lui, C_LUI), + USE_LIFTER(c_li, C_LI), + USE_LIFTER(auipc, AUIPC), + USE_LIFTER(beq, BEQ), + USE_LIFTER(bne, BNE), + USE_LIFTER(blt, BLT), + USE_LIFTER(bge, BGE), + USE_LIFTER(bltu, BLTU), + USE_LIFTER(bgeu, BGEU), + USE_LIFTER(c_beqz, C_BEQZ), + USE_LIFTER(c_bnez, C_BNEZ), + USE_LIFTER(sb, SB), + USE_LIFTER(sh, SH), + USE_LIFTER(sw, SW), + USE_LIFTER(c_sw, C_SW), + USE_LIFTER(c_swsp, C_SWSP), + USE_LIFTER(sd, SD), + USE_LIFTER(c_sd, C_SD), + USE_LIFTER(add, ADD), + USE_LIFTER(sub, SUB), + USE_LIFTER(and, AND), + USE_LIFTER(or, OR), + USE_LIFTER(xor, XOR), + USE_LIFTER(slt, SLT), + USE_LIFTER(sltu, SLTU), + USE_LIFTER(sll, SLL), + USE_LIFTER(srl, SRL), + USE_LIFTER(sra, SRA), + USE_LIFTER(jal, JAL), + USE_LIFTER(c_mv, C_MV), + USE_LIFTER(c_j, C_J), +}; + +RZ_OWN RZ_IPI RzILOpEffect * +rz_riscv_lift_instr(RZ_BORROW RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzAnalysisOp *op, RZ_NONNULL cs_insn *insn, ut64 current_addr, int size) { + rz_return_val_if_fail(analysis && op && insn, NULL); + + if (insn->id > 0 && insn->id < RZ_ARRAY_SIZE(riscv_lifters)) { + RiscvInstructionLifter lifter = riscv_lifters[insn->id]; + if (lifter) { + return lifter(analysis, op, insn, current_addr, size); + } else { + RZ_LOG_ERROR("No lifter found for instruction %s (id: %d) (0x%08x)", insn->mnemonic, insn->id, rz_read_le32(insn->bytes)); + } + } + rz_warn_if_reached(); + return NULL; +} + +RZ_IPI RzAnalysisILConfig *rz_riscv_il_config(RZ_NONNULL RzAnalysis *analysis) { + rz_return_val_if_fail(analysis, NULL); + + RzAnalysisILConfig *conf = rz_analysis_il_config_new(analysis->bits, analysis->big_endian, analysis->bits); + + return conf; +} \ No newline at end of file diff --git a/librz/arch/isa/riscv/riscv_il.h b/librz/arch/isa/riscv/riscv_il.h new file mode 100644 index 00000000000..eb398ed9042 --- /dev/null +++ b/librz/arch/isa/riscv/riscv_il.h @@ -0,0 +1,20 @@ +// SPDX-FileCopyrightText: 2026 Mostafa Mahmoud +// SPDX-License-Identifier: BSD-3-Clause + +#ifndef RZ_ARCH_ISA_RISCV_IL_H +#define RZ_ARCH_ISA_RISCV_IL_H + +#include +#include + +#include +#include +typedef RzILOpEffect *(*RiscvInstructionLifter)(RZ_BORROW RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzAnalysisOp *op, RZ_NONNULL cs_insn *insn, ut64 current_addr, int size); + +RZ_OWN RZ_IPI RzILOpEffect * +rz_riscv_lift_instr(RZ_BORROW RZ_NONNULL RzAnalysis *analysis, + RZ_NONNULL RzAnalysisOp *op, RZ_NONNULL cs_insn *insn, ut64 current_addr, int size); + +RZ_IPI RzAnalysisILConfig *rz_riscv_il_config(RZ_NONNULL RzAnalysis *analysis); + +#endif \ No newline at end of file diff --git a/librz/arch/meson.build b/librz/arch/meson.build index 7d86bee3b17..a684990f4ee 100644 --- a/librz/arch/meson.build +++ b/librz/arch/meson.build @@ -302,6 +302,7 @@ arch_isa_sources = [ 'isa/pyc/opcode_analysis.c', 'isa/pyc/opcode_arg_fmt.c', 'isa/pyc/pyc_dis.c', + 'isa/riscv/riscv_il.c', 'isa/rl78/rl78.c', 'isa/rl78/rl78_instr.c', 'isa/rl78/rl78_maps.c', diff --git a/librz/arch/p/analysis/analysis_riscv_cs.c b/librz/arch/p/analysis/analysis_riscv_cs.c index aa6725346b9..545378548b4 100644 --- a/librz/arch/p/analysis/analysis_riscv_cs.c +++ b/librz/arch/p/analysis/analysis_riscv_cs.c @@ -14,6 +14,8 @@ #include "analysis_riscv_utils.h" #include +#include + #define OPERAND(x) insn->detail->riscv.operands[x] #define REGID(x) insn->detail->riscv.operands[x].reg #define REG(x) cs_reg_name(*handle, insn->detail->riscv.operands[x].reg) @@ -1922,6 +1924,11 @@ int analyze_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf set_op_family(op, insn); set_op_extra_metadata(analysis, op, ctx->hndl, insn); set_stack_effect(op, insn); + + if (mask & RZ_ANALYSIS_OP_MASK_IL) { + RzILOpEffect *il_op = rz_riscv_lift_instr(analysis, op, insn, addr, op->size); + op->il_op = il_op; + } } set_opdir(op); if (insn && mask & RZ_ANALYSIS_OP_MASK_OPEX) { @@ -2148,7 +2155,7 @@ static char *get_reg_profile(RzAnalysis *analysis) { "gpr ft9 .64 488 0\n" // =f29 "gpr ft10 .64 496 0\n" // =f30 "gpr ft11 .64 504 0\n" // =f31 - "gpr fcsr .32 512 0\n" + "gpr fcsr .64 512 0\n" // vector registers // assume each register is 512 bits (64 bytes) for maximum compatibility // TODO: make the width accurately reflect the exact width defined in the binary @@ -2276,6 +2283,7 @@ RzAnalysisPlugin rz_analysis_plugin_riscv_cs = { .archinfo = archinfo, .bits = 32 | 64, .op = &analyze_op, + .il_config = rz_riscv_il_config, .init = riscv_init, .fini = riscv_fini, }; diff --git a/test/db/asm/riscv_32 b/test/db/asm/riscv_32 index 29165a9578d..269ff99bf7a 100644 --- a/test/db/asm/riscv_32 +++ b/test/db/asm/riscv_32 @@ -1,138 +1,145 @@ -d "addi sp, sp, -0x90" 7571 -d "lui a5, 0x10" c167 -d "sw a5, 0x1c(sp)" 3ece -d "lui a5, 0x30" b7070300 -d "sw a5, 0x24(sp)" 3ed2 -d "lui a5, 0xc" b167 -d "sw a5, 0x3c(sp)" 3ede -d "lui a5, 0xffff8" e177 -d "sw s1, 0x84(sp)" 26c3 -d "sw ra, 0x8c(sp)" 06c7 -d "sw s0, 0x88(sp)" 22c5 -d "sw s2, 0x80(sp)" 4ac1 -d "sw s3, 0x7c(sp)" cede -d "sw s4, 0x78(sp)" d2dc -d "sw s5, 0x74(sp)" d6da -d "sw s6, 0x70(sp)" dad8 -d "sw s7, 0x6c(sp)" ded6 -d "sw s8, 0x68(sp)" e2d4 -d "sw s9, 0x64(sp)" e6d2 -d "sw s10, 0x60(sp)" ead0 -d "sw s11, 0x5c(sp)" eece -d "sw zero, 0x28(sp)" 02d4 -d "sw zero, 0x20(sp)" 02d0 -d "sw zero, 0x38(sp)" 02dc -d "sw zero, 0x30(sp)" 02d8 -d "sw a5, 0x34(sp)" 3eda -d "sw zero, 0x18(sp)" 02cc -d "lui s1, 0x40" b7040400 0x38 -d "lui a5, 0x10013" b7370110 -d "lw a5, 4(a5)" dc43 0x40 -d "blez a5, 0x64" 6351f002 0x42 -d "lw ra, 0x8c(sp)" ba40 0x40 -d "lw s0, 0x88(sp)" 2a44 0x40 -d "lw s1, 0x84(sp)" 9a44 0x40 -d "lw s2, 0x80(sp)" 0a49 0x40 -d "lw s3, 0x7c(sp)" f659 0x40 -d "lw s4, 0x78(sp)" 665a 0x44 -d "lw s5, 0x74(sp)" d65a 0x48 -d "lw s6, 0x70(sp)" 465b 0x40 -d "lw s7, 0x6c(sp)" b65b 0x40 -d "lw s8, 0x68(sp)" 265c 0x40 -d "lw s9, 0x64(sp)" 965c 0x40 -d "lw s10, 0x60(sp)" 065d 0x40 -d "lw s11, 0x5c(sp)" f64d 0x40 +# ----------------------------- C_ADDI16SP ----------------------------- +d "addi sp, sp, -0x90" 7571 0x0 (set sp (+ (var sp) (bv 32 0xffffff70))) +# ----------------------------- ADDI ----------------------------- +d "addi a1, a1, 0x700" 93850570 0x0 (set a1 (+ (var a1) (bv 32 0x700))) +# ----------------------------- C_ADDI4SPN ----------------------------- +d "addi s0, sp, 0x80" 0001 0x0 (set s0 (+ (var sp) (bv 32 0x80))) +# ----------------------------- C_ADDI --------------------------------- +d "addi sp, sp, -0x20" 0111 0x0 (set sp (+ (var sp) (bv 32 0xffffffe0))) +d "lui a5, 0x10" c167 0x0 (set a5 (<< (bv 32 0x10) (bv 32 0xc) false)) +d "sw a5, 0x1c(sp)" 3ece 0x0 (storew 0 (+ (var sp) (bv 32 0x1c)) (var a5)) +d "lui a5, 0x30" b7070300 0x0 (set a5 (<< (bv 32 0x30) (bv 32 0xc) false)) +d "sw a5, 0x24(sp)" 3ed2 0x0 (storew 0 (+ (var sp) (bv 32 0x24)) (var a5)) +d "lui a5, 0xc" b167 0x0 (set a5 (<< (bv 32 0xc) (bv 32 0xc) false)) +d "sw a5, 0x3c(sp)" 3ede 0x0 (storew 0 (+ (var sp) (bv 32 0x3c)) (var a5)) +d "lui a5, 0xffff8" e177 0x0 (set a5 (<< (bv 32 0xffff8) (bv 32 0xc) false)) +d "sw s1, 0x84(sp)" 26c3 0x0 (storew 0 (+ (var sp) (bv 32 0x84)) (var s1)) +d "sw ra, 0x8c(sp)" 06c7 0x0 (storew 0 (+ (var sp) (bv 32 0x8c)) (var ra)) +d "sw s0, 0x88(sp)" 22c5 0x0 (storew 0 (+ (var sp) (bv 32 0x88)) (var s0)) +d "sw s2, 0x80(sp)" 4ac1 0x0 (storew 0 (+ (var sp) (bv 32 0x80)) (var s2)) +d "sw s3, 0x7c(sp)" cede 0x0 (storew 0 (+ (var sp) (bv 32 0x7c)) (var s3)) +d "sw s4, 0x78(sp)" d2dc 0x0 (storew 0 (+ (var sp) (bv 32 0x78)) (var s4)) +d "sw s5, 0x74(sp)" d6da 0x0 (storew 0 (+ (var sp) (bv 32 0x74)) (var s5)) +d "sw s6, 0x70(sp)" dad8 0x0 (storew 0 (+ (var sp) (bv 32 0x70)) (var s6)) +d "sw s7, 0x6c(sp)" ded6 0x0 (storew 0 (+ (var sp) (bv 32 0x6c)) (var s7)) +d "sw s8, 0x68(sp)" e2d4 0x0 (storew 0 (+ (var sp) (bv 32 0x68)) (var s8)) +d "sw s9, 0x64(sp)" e6d2 0x0 (storew 0 (+ (var sp) (bv 32 0x64)) (var s9)) +d "sw s10, 0x60(sp)" ead0 0x0 (storew 0 (+ (var sp) (bv 32 0x60)) (var s10)) +d "sw s11, 0x5c(sp)" eece 0x0 (storew 0 (+ (var sp) (bv 32 0x5c)) (var s11)) +d "sw zero, 0x28(sp)" 02d4 0x0 (storew 0 (+ (var sp) (bv 32 0x28)) (bv 32 0x0)) +d "sw zero, 0x20(sp)" 02d0 0x0 (storew 0 (+ (var sp) (bv 32 0x20)) (bv 32 0x0)) +d "sw zero, 0x38(sp)" 02dc 0x0 (storew 0 (+ (var sp) (bv 32 0x38)) (bv 32 0x0)) +d "sw zero, 0x30(sp)" 02d8 0x0 (storew 0 (+ (var sp) (bv 32 0x30)) (bv 32 0x0)) +d "sw a5, 0x34(sp)" 3eda 0x0 (storew 0 (+ (var sp) (bv 32 0x34)) (var a5)) +d "sw zero, 0x18(sp)" 02cc 0x0 (storew 0 (+ (var sp) (bv 32 0x18)) (bv 32 0x0)) +d "lui s1, 0x40" b7040400 0x38 (set s1 (<< (bv 32 0x40) (bv 32 0xc) false)) +d "lui a5, 0x10013" b7370110 0x0 (set a5 (<< (bv 32 0x10013) (bv 32 0xc) false)) +d "lw a5, 4(a5)" dc43 0x40 (set a5 (loadw 0 32 (+ (var a5) (bv 32 0x4)))) +d "blez a5, 0x64" 6351f002 0x42 (branch (|| (! (sle (bv 32 0x0) (var a5))) (== (bv 32 0x0) (var a5))) (jmp (bv 32 0x64)) (jmp (bv 32 0x46))) +d "lw ra, 0x8c(sp)" ba40 0x40 (set ra (loadw 0 32 (+ (var sp) (bv 32 0x8c)))) +d "lw s0, 0x88(sp)" 2a44 0x40 (set s0 (loadw 0 32 (+ (var sp) (bv 32 0x88)))) +d "lw s1, 0x84(sp)" 9a44 0x40 (set s1 (loadw 0 32 (+ (var sp) (bv 32 0x84)))) +d "lw s2, 0x80(sp)" 0a49 0x40 (set s2 (loadw 0 32 (+ (var sp) (bv 32 0x80)))) +d "lw s3, 0x7c(sp)" f659 0x40 (set s3 (loadw 0 32 (+ (var sp) (bv 32 0x7c)))) +d "lw s4, 0x78(sp)" 665a 0x44 (set s4 (loadw 0 32 (+ (var sp) (bv 32 0x78)))) +d "lw s5, 0x74(sp)" d65a 0x48 (set s5 (loadw 0 32 (+ (var sp) (bv 32 0x74)))) +d "lw s6, 0x70(sp)" 465b 0x40 (set s6 (loadw 0 32 (+ (var sp) (bv 32 0x70)))) +d "lw s7, 0x6c(sp)" b65b 0x40 (set s7 (loadw 0 32 (+ (var sp) (bv 32 0x6c)))) +d "lw s8, 0x68(sp)" 265c 0x40 (set s8 (loadw 0 32 (+ (var sp) (bv 32 0x68)))) +d "lw s9, 0x64(sp)" 965c 0x40 (set s9 (loadw 0 32 (+ (var sp) (bv 32 0x64)))) +d "lw s10, 0x60(sp)" 065d 0x40 (set s10 (loadw 0 32 (+ (var sp) (bv 32 0x60)))) +d "lw s11, 0x5c(sp)" f64d 0x40 (set s11 (loadw 0 32 (+ (var sp) (bv 32 0x5c)))) d "addi sp, sp, 0x90" 4961 0x40 -d "ret" 8280 0x40 -d "lw a5, 0x18(sp)" e247 0x40 +d "ret" 8280 0x40 NONE +d "lw a5, 0x18(sp)" e247 0x40 (set a5 (loadw 0 32 (+ (var sp) (bv 32 0x18)))) d "beqz a5, 0x2d8" 63890726 0x66 -d "lw s0, 0x1c(sp)" 7244 0x40 -d "lw a0, 0x24(sp)" 1255 0x40 -d "lw a6, 0x28(sp)" 2258 0x40 -d "lw t3, 0x38(sp)" 625e 0x40 +d "lw s0, 0x1c(sp)" 7244 0x40 (set s0 (loadw 0 32 (+ (var sp) (bv 32 0x1c)))) +d "lw a0, 0x24(sp)" 1255 0x40 (set a0 (loadw 0 32 (+ (var sp) (bv 32 0x24)))) +d "lw a6, 0x28(sp)" 2258 0x40 (set a6 (loadw 0 32 (+ (var sp) (bv 32 0x28)))) +d "lw t3, 0x38(sp)" 625e 0x40 (set t3 (loadw 0 32 (+ (var sp) (bv 32 0x38)))) d "srai a5, s0, 0x1f" 9357f441 0x40 -d "lw a2, 0x20(sp)" 0256 0x40 -d "andi a5, a5, 0xf" bd8b 0x40 +d "lw a2, 0x20(sp)" 0256 0x40 (set a2 (loadw 0 32 (+ (var sp) (bv 32 0x20)))) +d "andi a5, a5, 0xf" bd8b 0x40 (set a5 (& (var a5) (bv 32 0xf))) d "srai a4, a0, 0x1f" 1357f541 0x40 -d "lw a7, 0x30(sp)" c258 0x40 -d "add a3, a5, a6" b3860701 0x80 -d "sub s2, t3, a6" 33090e41 0x80 -d "andi a4, a4, 0x3f" 1377f703 0x80 -d "lw a6, 0x34(sp)" 5258 0x80 -d "add a1, a4, a2" b305c700 0x80 -d "sltu a4, a1, a4" 33b7e500 0x80 -d "sub a2, a7, a2" 3386c840 0x80 -d "sltu s7, a3, a5" b3bbf600 0x80 -d "sltu a7, a7, a2" b3b8c800 0x80 -d "add a5, a4, a0" b307a700 0x80 -d "mv a4, a2" 3287 0x80 -d "sub a2, a6, a0" 3306a840 0x80 -d "sltu a6, t3, s2" 33382e01 0x80 -d "lw t3, 0x3c(sp)" 725e 0x80 -d "mv t1, a0" 2a83 0x80 -d "srli a1, a1, 6" 9981 0x80 -d "slli a0, a5, 0x1a" 1395a701 0x80 -d "sw a4, 0x40(sp)" bac0 0x80 -d "sub a4, a2, a7" 33071641 0x80 -d "add s7, s7, s0" a29b 0xc0 -d "sw a4, 0x44(sp)" bac2 0xc0 -d "srai a5, a5, 6" 9987 0xc0 -d "or a4, a0, a1" 3367b500 0xc0 -d "slli s8, s7, 0x1c" 139ccb01 0xc0 -d "sub s0, t3, s0" 33048e40 0xc0 -d "srli a3, a3, 4" 9182 0xc0 -d "sw a4, 0x10(sp)" 3ac8 0xc0 -d "sw a5, 0x14(sp)" 3eca 0xc0 -d "lui a4, 1" 0567 0xc0 -d "sub s0, s0, a6" 33040441 0xc0 -d "or s8, s8, a3" 336cdc00 0xc0 -d "srai s7, s7, 4" 93db4b40 0xc0 -d "blt t1, a4, 0x2d4" 6347e31e 0xe6 -d "lw a5, 0x1c(sp)" f247 0xc0 -d "lui a4, 1" 0567 0xc0 -d "blt a5, a4, 0x2d4" 63c3e71e 0xee -d "srli a5, s8, 0x1d" 9357dc01 0xc0 -d "slli a4, s7, 3" 13973b00 0xc0 -d "or a5, a5, a4" d98f 0xc0 -d "sw a5, 0x4c(sp)" bec6 0xc0 -d "slli a5, s8, 3" 93173c00 0xc0 -d "addi a5, sp, 8" 3c00 0x100 -d "li s11, 0xff" 930df00f 0x100 -d "sw a5, 0x48(sp)" bec4 0x100 -d "sw s2, 0xc(sp)" 4ac6 0x100 -d "li a5, 4" 9147 0x100 -d "li s2, 0" 0149 0x100 -d "mv s3, s11" ee89 0x100 -d "sw a5, 0x2c(sp)" 3ed6 0x100 -d "li s6, 0x10" 414b 0x100 -d "li s9, 8" a14c 0x100 -d "mv s11, s2" ca8d 0x100 -d "lw s10, 0x40(sp)" 064d 0x100 -d "lw s5, 0x44(sp)" 964a 0x100 -d "li s2, 0x80" 13090008 0x100 -d "mv s4, s3" 4e8a 0x100 -d "mv s3, s2" ca89 0x100 -d "lw t2, 0xc(sp)" b243 0x100 -d "mv t6, s0" a28f 0x100 -d "li ra, 0" 8140 0x100 -d "li s2, 0" 0149 0x100 -d "li a1, 0" 8145 0x100 -d "li a4, 0" 0147 0x100 -d "li t3, 0" 014e 0x100 -d "li a6, 0" 0148 0x100 -d "li a5, 0" 8147 0x100 -d "li a3, 0" 8146 0x100 -d "li t1, 0" 0143 0x100 -d "li a2, 0" 0146 0x100 -d "li a0, 0" 0145 0x100 -d "j 0x176" 25a8 0x13e +d "lw a7, 0x30(sp)" c258 0x40 (set a7 (loadw 0 32 (+ (var sp) (bv 32 0x30)))) +d "add a3, a5, a6" b3860701 0x80 (set a3 (+ (var a5) (var a6))) +d "sub s2, t3, a6" 33090e41 0x80 (set s2 (- (var t3) (var a6))) +d "andi a4, a4, 0x3f" 1377f703 0x80 (set a4 (& (var a4) (bv 32 0x3f))) +d "lw a6, 0x34(sp)" 5258 0x80 (set a6 (loadw 0 32 (+ (var sp) (bv 32 0x34)))) +d "add a1, a4, a2" b305c700 0x80 (set a1 (+ (var a4) (var a2))) +d "sltu a4, a1, a4" 33b7e500 0x80 (set a4 (ite (&& (ule (var a1) (var a4)) (! (== (var a1) (var a4)))) (bv 32 0x1) (bv 32 0x0))) +d "sub a2, a7, a2" 3386c840 0x80 (set a2 (- (var a7) (var a2))) +d "sltu s7, a3, a5" b3bbf600 0x80 (set s7 (ite (&& (ule (var a3) (var a5)) (! (== (var a3) (var a5)))) (bv 32 0x1) (bv 32 0x0))) +d "sltu a7, a7, a2" b3b8c800 0x80 (set a7 (ite (&& (ule (var a7) (var a2)) (! (== (var a7) (var a2)))) (bv 32 0x1) (bv 32 0x0))) +d "add a5, a4, a0" b307a700 0x80 (set a5 (+ (var a4) (var a0))) +d "mv a4, a2" 3287 0x80 (set a4 (var a2)) +d "sub a2, a6, a0" 3306a840 0x80 (set a2 (- (var a6) (var a0))) +d "sltu a6, t3, s2" 33382e01 0x80 (set a6 (ite (&& (ule (var t3) (var s2)) (! (== (var t3) (var s2)))) (bv 32 0x1) (bv 32 0x0))) +d "lw t3, 0x3c(sp)" 725e 0x80 (set t3 (loadw 0 32 (+ (var sp) (bv 32 0x3c)))) +d "mv t1, a0" 2a83 0x80 (set t1 (var a0)) +d "srli a1, a1, 6" 9981 0x80 (set a1 (>> (var a1) (bv 32 0x6) false)) +d "slli a0, a5, 0x1a" 1395a701 0x80 (set a0 (<< (var a5) (bv 32 0x1a) false)) +d "sw a4, 0x40(sp)" bac0 0x80 (storew 0 (+ (var sp) (bv 32 0x40)) (var a4)) +d "sub a4, a2, a7" 33071641 0x80 (set a4 (- (var a2) (var a7))) +d "add s7, s7, s0" a29b 0xc0 NONE +d "sw a4, 0x44(sp)" bac2 0xc0 (storew 0 (+ (var sp) (bv 32 0x44)) (var a4)) +d "srai a5, a5, 6" 9987 0xc0 (set a5 (>> (var a5) (bv 32 0x6) (msb (var a5)))) +d "or a4, a0, a1" 3367b500 0xc0 (set a4 (| (var a0) (var a1))) +d "slli s8, s7, 0x1c" 139ccb01 0xc0 (set s8 (<< (var s7) (bv 32 0x1c) false)) +d "sub s0, t3, s0" 33048e40 0xc0 (set s0 (- (var t3) (var s0))) +d "srli a3, a3, 4" 9182 0xc0 (set a3 (>> (var a3) (bv 32 0x4) false)) +d "sw a4, 0x10(sp)" 3ac8 0xc0 (storew 0 (+ (var sp) (bv 32 0x10)) (var a4)) +d "sw a5, 0x14(sp)" 3eca 0xc0 (storew 0 (+ (var sp) (bv 32 0x14)) (var a5)) +d "lui a4, 1" 0567 0xc0 (set a4 (<< (bv 32 0x1) (bv 32 0xc) false)) +d "sub s0, s0, a6" 33040441 0xc0 (set s0 (- (var s0) (var a6))) +d "or s8, s8, a3" 336cdc00 0xc0 (set s8 (| (var s8) (var a3))) +d "srai s7, s7, 4" 93db4b40 0xc0 (set s7 (>> (var s7) (bv 32 0x4) (msb (var s7)))) +d "blt t1, a4, 0x2d4" 6347e31e 0xe6 (branch (&& (sle (var t1) (var a4)) (! (== (var t1) (var a4)))) (jmp (bv 32 0x2d4)) (jmp (bv 32 0xea))) +d "lw a5, 0x1c(sp)" f247 0xc0 (set a5 (loadw 0 32 (+ (var sp) (bv 32 0x1c)))) +d "lui a4, 1" 0567 0xc0 (set a4 (<< (bv 32 0x1) (bv 32 0xc) false)) +d "blt a5, a4, 0x2d4" 63c3e71e 0xee (branch (&& (sle (var a5) (var a4)) (! (== (var a5) (var a4)))) (jmp (bv 32 0x2d4)) (jmp (bv 32 0xf2))) +d "srli a5, s8, 0x1d" 9357dc01 0xc0 (set a5 (>> (var s8) (bv 32 0x1d) false)) +d "slli a4, s7, 3" 13973b00 0xc0 (set a4 (<< (var s7) (bv 32 0x3) false)) +d "or a5, a5, a4" d98f 0xc0 NONE +d "sw a5, 0x4c(sp)" bec6 0xc0 (storew 0 (+ (var sp) (bv 32 0x4c)) (var a5)) +d "slli a5, s8, 3" 93173c00 0xc0 (set a5 (<< (var s8) (bv 32 0x3) false)) +d "addi a5, sp, 8" 3c00 0x100 (set a5 (+ (var sp) (bv 32 0x8))) +d "li s11, 0xff" 930df00f 0x100 (set s11 (+ (bv 32 0x0) (bv 32 0xff))) +d "sw a5, 0x48(sp)" bec4 0x100 (storew 0 (+ (var sp) (bv 32 0x48)) (var a5)) +d "sw s2, 0xc(sp)" 4ac6 0x100 (storew 0 (+ (var sp) (bv 32 0xc)) (var s2)) +d "li a5, 4" 9147 0x100 (set a5 (bv 32 0x4)) +d "li s2, 0" 0149 0x100 (set s2 (bv 32 0x0)) +d "mv s3, s11" ee89 0x100 (set s3 (var s11)) +d "sw a5, 0x2c(sp)" 3ed6 0x100 (storew 0 (+ (var sp) (bv 32 0x2c)) (var a5)) +d "li s6, 0x10" 414b 0x100 (set s6 (bv 32 0x10)) +d "li s9, 8" a14c 0x100 (set s9 (bv 32 0x8)) +d "mv s11, s2" ca8d 0x100 (set s11 (var s2)) +d "lw s10, 0x40(sp)" 064d 0x100 (set s10 (loadw 0 32 (+ (var sp) (bv 32 0x40)))) +d "lw s5, 0x44(sp)" 964a 0x100 (set s5 (loadw 0 32 (+ (var sp) (bv 32 0x44)))) +d "li s2, 0x80" 13090008 0x100 (set s2 (+ (bv 32 0x0) (bv 32 0x80))) +d "mv s4, s3" 4e8a 0x100 (set s4 (var s3)) +d "mv s3, s2" ca89 0x100 (set s3 (var s2)) +d "lw t2, 0xc(sp)" b243 0x100 (set t2 (loadw 0 32 (+ (var sp) (bv 32 0xc)))) +d "mv t6, s0" a28f 0x100 (set t6 (var s0)) +d "li ra, 0" 8140 0x100 (set ra (bv 32 0x0)) +d "li s2, 0" 0149 0x100 (set s2 (bv 32 0x0)) +d "li a1, 0" 8145 0x100 (set a1 (bv 32 0x0)) +d "li a4, 0" 0147 0x100 (set a4 (bv 32 0x0)) +d "li t3, 0" 014e 0x100 (set t3 (bv 32 0x0)) +d "li a6, 0" 0148 0x100 (set a6 (bv 32 0x0)) +d "li a5, 0" 8147 0x100 (set a5 (bv 32 0x0)) +d "li a3, 0" 8146 0x100 (set a3 (bv 32 0x0)) +d "li t1, 0" 0143 0x100 (set t1 (bv 32 0x0)) +d "li a2, 0" 0146 0x100 (set a2 (bv 32 0x0)) +d "li a0, 0" 0145 0x100 (set a0 (bv 32 0x0)) +d "j 0x176" 25a8 0x13e (jmp (bv 32 0x176)) d "mul a4, a0, a2" 3307c502 0x140 d "mulhu t1, a2, a2" 3333c602 0x140 -d "slli a4, a4, 1" 0607 0x140 +d "slli a4, a4, 1" 0607 0x140 (set a4 (<< (var a4) (bv 32 0x1) false)) d "mul a7, a5, a6" b3880703 0x140 d "add t1, t1, a4" 3a93 0x140 d "mul a3, a2, a2" b306c602 0x140 -d "slli a7, a7, 1" 8608 0x140 +d "slli a7, a7, 1" 8608 0x140 (set a7 (<< (var a7) (bv 32 0x1) false)) d "mulhu t3, a6, a6" 333e0803 0x140 d "mul a4, a6, a6" 33070803 0x140 d "add t3, t3, a7" 469e 0x140 @@ -140,8 +147,8 @@ d "add t5, t1, t3" 330fc301 0x140 d "add t4, a3, a4" b38ee600 0x140 d "sltu a7, t4, a3" b3b8de00 0x140 d "add a7, a7, t5" fa98 0x140 -d "blt s1, a7, 0x2c6" 63cc1415 0x16e -d "beq a7, s1, 0x2c2" 63889814 0x172 +d "blt s1, a7, 0x2c6" 63cc1415 0x16e (branch (&& (sle (var s1) (var a7)) (! (== (var s1) (var a7)))) (jmp (bv 32 0x2c6)) (jmp (bv 32 0x172))) +d "beq a7, s1, 0x2c2" 63889814 0x172 (branch (== (var a7) (var s1)) (jmp (bv 32 0x2c2)) (jmp (bv 32 0x176))) d "sub a4, a3, a4" 3387e640 0x140 d "sub t3, t1, t3" 330ec341 0x140 d "sltu a3, ra, zero" b3b60000 0x140 @@ -151,35 +158,44 @@ d "sltu a4, a7, a4" 33b7e800 0x180 d "add a3, a3, s5" d696 0x180 d "add a3, a3, a4" ba96 0x180 d "mul a5, a5, a2" b387c702 0x180 -d "slli t1, a3, 8" 13938600 0x180 -d "addi a1, a1, 1" 8505 0x180 +d "slli t1, a3, 8" 13938600 0x180 (set t1 (<< (var a3) (bv 32 0x8) false)) +d "addi a1, a1, 1" 8505 0x180 (set a1 (+ (var a1) (bv 32 0x1))) d "mul a4, a0, a6" 33070503 0x180 -d "srai a0, a3, 0x18" 13d58641 0x180 +d "srai a0, a3, 0x18" 13d58641 0x180 (set a0 (>> (var a3) (bv 32 0x18) (msb (var a3)))) d "mulhu a3, a6, a2" b336c802 0x180 d "add a4, a4, a5" 3e97 0x180 d "mul a6, a6, a2" 3308c802 0x180 d "add a4, a4, a3" 3697 0x180 -d "srli a2, a7, 0x18" 13d68801 0x180 -d "slli a4, a4, 1" 0607 0x180 +d "srli a2, a7, 0x18" 13d68801 0x180 (set a2 (>> (var a7) (bv 32 0x18) false)) +d "slli a4, a4, 1" 0607 0x180 (set a4 (<< (var a4) (bv 32 0x1) false)) d "or a2, t1, a2" 3366c300 0x180 -d "slli a7, a6, 1" 93181800 0x180 -d "srli a3, a6, 0x1f" 9356f801 0x180 +d "slli a7, a6, 1" 93181800 0x180 (set a7 (<< (var a6) (bv 32 0x1) false)) +d "srli a3, a6, 0x1f" 9356f801 0x180 (set a3 (>> (var a6) (bv 32 0x1f) false)) d "add a5, a7, t2" b3877800 0x1c0 d "or a4, a4, a3" 558f 0x1c0 -d "srli a6, a5, 0x18" 13d88701 0x1c0 +d "srli a6, a5, 0x18" 13d88701 0x1c0 (set a6 (>> (var a5) (bv 32 0x18) false)) d "add a4, a4, t6" 7e97 0x1c0 d "sltu a5, a5, a7" b3b71701 0x1c0 d "add a4, a4, a5" 3e97 0x1c0 -d "slli a5, a4, 8" 93178700 0x1c0 +d "slli a5, a4, 8" 93178700 0x1c0 (set a5 (<< (var a4) (bv 32 0x8) false)) d "or a6, a5, a6" 33e80701 0x1c0 d "srai a5, a4, 0x18" 93578741 0x1c0 -d "bne a1, s6, 0x140" e39065f7 0x1e0 +d "bne a1, s6, 0x140" e39065f7 0x1e0 (branch (! (== (var a1) (var s6))) (jmp (bv 32 0x140)) (jmp (bv 32 0x1e4))) d "li a5, 0" 8147 0x1c0 d "add a4, t2, s8" 33878301 0x1c0 d "sltu a3, a4, t2" b3367700 0x1c0 d "or s2, a5, s2" 33e92701 0x1c0 d "add t6, t6, s7" de9f 0x1c0 -d "addi ra, ra, 1" 8500 0x1c0 -d "andi s2, s2, 0xff" 1379f90f 0x1c0 +d "addi ra, ra, 1" 8500 0x1c0 (set ra (+ (var ra) (bv 32 0x1))) +d "andi s2, s2, 0xff" 1379f90f 0x1c0 (set s2 (& (var s2) (bv 32 0xff))) d "mv t2, a4" ba83 0x1c0 d "add t6, t6, a3" b69f 0x1c0 +d "ori a5, a5, 0x89" 93e79708 0x0 (set a5 (| (var a5) (bv 32 0x89))) +d "xori a5, a5, 0x431" 93c71743 0x0 (set a5 (^ (var a5) (bv 32 0x431))) +d "jalr ra" e7800000 0x30 (seq (set ra (bv 32 0x34)) (jmp (& (+ (var ra) (bv 32 0x0)) (bv 32 0xfffffffe)))) +d "slti zero, ra, 0xc" 13a0c000 0x0 nop +d "sltiu zero, ra, 0xc" 13b0c000 0x0 nop +d "slti t0, ra, 0xc" 93a2c000 0x0 (set t0 (ite (&& (sle (var ra) (bv 32 0xc)) (! (== (var ra) (bv 32 0xc)))) (bv 32 0x1) (bv 32 0x0))) +d "sltiu t1, sp, 0x14" 13334101 0x0 (set t1 (ite (&& (ule (var sp) (bv 32 0x14)) (! (== (var sp) (bv 32 0x14)))) (bv 32 0x1) (bv 32 0x0))) +d "jal t0, 0x14" ef024001 0x0 (seq (set t0 (bv 32 0x4)) (jmp (bv 32 0x14))) +d "jal t0, 0x4a" ef024001 0x36 (seq (set t0 (bv 32 0x3a)) (jmp (bv 32 0x4a))) From ed82aac7aa84dde1f85b93fcd7c94dceaf4da6ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D9=85=D8=B5=D8=B7=D9=81=D9=8A=20=D9=85=D8=AD=D9=85=D9=88?= =?UTF-8?q?=D8=AF=20=D9=83=D9=85=D8=A7=D9=84=20=D8=A7=D9=84=D8=AF=D9=8A?= =?UTF-8?q?=D9=86?= <48567303+moste00@users.noreply.github.com> Date: Thu, 14 May 2026 22:02:17 +0300 Subject: [PATCH 2/8] refactor implementation to more declarative style --- librz/arch/isa/riscv/riscv_il.c | 318 +++++------------- librz/arch/isa/riscv/riscv_il.h | 4 +- librz/arch/isa/riscv/riscv_il_base.h | 199 +++++++++++ librz/arch/isa/riscv/riscv_il_compressed.h | 71 ++++ librz/arch/isa/riscv/riscv_il_integer.h | 99 ++++++ .../isa/riscv/riscv_il_integer_reg_names.h | 53 +++ librz/arch/isa/riscv/riscv_il_m.h | 21 ++ test/db/asm/riscv_32 | 96 +++--- 8 files changed, 577 insertions(+), 284 deletions(-) create mode 100644 librz/arch/isa/riscv/riscv_il_base.h create mode 100644 librz/arch/isa/riscv/riscv_il_compressed.h create mode 100644 librz/arch/isa/riscv/riscv_il_integer.h create mode 100644 librz/arch/isa/riscv/riscv_il_integer_reg_names.h create mode 100644 librz/arch/isa/riscv/riscv_il_m.h diff --git a/librz/arch/isa/riscv/riscv_il.c b/librz/arch/isa/riscv/riscv_il.c index 37a2b1601eb..61f99b2fb14 100644 --- a/librz/arch/isa/riscv/riscv_il.c +++ b/librz/arch/isa/riscv/riscv_il.c @@ -1,217 +1,20 @@ // SPDX-FileCopyrightText: 2026 Mostafa Mahmoud // SPDX-License-Identifier: BSD-3-Clause -#include "analysis_private.h" -#include "riscv.h" -#include "rz_il/rz_il_opcodes.h" -#include "rz_types.h" -#include "rz_util/rz_assert.h" -#include -#include "riscv_il.h" - -#include -static const char *riscv_register_names[] = { - [RISCV_REG_X1] = "ra", - [RISCV_REG_X2] = "sp", - [RISCV_REG_X3] = "gp", - [RISCV_REG_X4] = "tp", - [RISCV_REG_X5] = "t0", - [RISCV_REG_X6] = "t1", - [RISCV_REG_X7] = "t2", - [RISCV_REG_X8] = "s0", - [RISCV_REG_X9] = "s1", - [RISCV_REG_X10] = "a0", - [RISCV_REG_X11] = "a1", - [RISCV_REG_X12] = "a2", - [RISCV_REG_X13] = "a3", - [RISCV_REG_X14] = "a4", - [RISCV_REG_X15] = "a5", - [RISCV_REG_X16] = "a6", - [RISCV_REG_X17] = "a7", - [RISCV_REG_X18] = "s2", - [RISCV_REG_X19] = "s3", - [RISCV_REG_X20] = "s4", - [RISCV_REG_X21] = "s5", - [RISCV_REG_X22] = "s6", - [RISCV_REG_X23] = "s7", - [RISCV_REG_X24] = "s8", - [RISCV_REG_X25] = "s9", - [RISCV_REG_X26] = "s10", - [RISCV_REG_X27] = "s11", - [RISCV_REG_X28] = "t3", - [RISCV_REG_X29] = "t4", - [RISCV_REG_X30] = "t5", - [RISCV_REG_X31] = "t6", -}; - -#define RISCV_GET_REG(reg) (((reg) != RISCV_REG_X0) ? (VARG(riscv_register_names[reg])) : UN(analysis->bits, 0)) -#define RISCV_SET_REG(reg, r) (((reg) != RISCV_REG_X0) ? (SETG(riscv_register_names[reg], r)) : ((rz_il_op_pure_free(r), NOP()))) - -#define DEFINE_LIFTER(name, decoder, result) \ - static RzILOpEffect *rz_riscv_lift_##name(RZ_BORROW RZ_NONNULL RzAnalysis *analysis, \ - RZ_NONNULL RzAnalysisOp *op, RZ_NONNULL cs_insn *insn, ut64 current_addr, int size) { \ - decoder(analysis, insn); \ - return RISCV_SET_REG(rd, result); \ - } - -// by default, a RISC-V jump both sets a destination and sets the PC (i.e., jumps) -#define DEFINE_LIFTER_FOR_JUMP(name, decoder, result, jmp_effect) \ - static RzILOpEffect *rz_riscv_lift_##name(RZ_BORROW RZ_NONNULL RzAnalysis *analysis, \ - RZ_NONNULL RzAnalysisOp *op, RZ_NONNULL cs_insn *insn, ut64 current_addr, int size) { \ - decoder(analysis, insn); \ - return SEQ2( \ - RISCV_SET_REG(rd, result), \ - jmp_effect); \ - } - -#define DEFINE_LIFTER_WITH_EFFECT(name, decoder, effect) \ - static RzILOpEffect *rz_riscv_lift_##name(RZ_BORROW RZ_NONNULL RzAnalysis *analysis, \ - RZ_NONNULL RzAnalysisOp *op, RZ_NONNULL cs_insn *insn, ut64 current_addr, int size) { \ - decoder(analysis, insn); \ - return effect; \ - } - -// oneway jumps are those that don't have a destination register -#define DEFINE_LIFTER_FOR_ONEWAY_JUMP DEFINE_LIFTER_WITH_EFFECT - -#define TWICE_FOR(name1, name2, lifter, ...) \ - lifter(name1, __VA_ARGS__) \ - lifter(name2, __VA_ARGS__) - -#define THRICE_FOR(name1, name2, name3, lifter, ...) \ - TWICE_FOR(name1, name2, lifter, __VA_ARGS__) \ - lifter(name3, __VA_ARGS__) - -#define FOR_4(name1, name2, name3, name4, lifter, ...) \ - TWICE_FOR(name1, name2, lifter, __VA_ARGS__) \ - TWICE_FOR(name3, name4, lifter, __VA_ARGS__) - -#define DECODE_RD_RS_IMM(analysis, insn) \ - uint32_t rd = insn->detail->riscv.operands[0].reg; \ - RzILOpBitVector *rs = RISCV_GET_REG(insn->detail->riscv.operands[1].reg); \ - RzILOpBitVector *imm = SN(analysis->bits, insn->detail->riscv.operands[2].imm); - -#define DECODE_RD_RS_RS(analysis, insn) \ - uint32_t rd = insn->detail->riscv.operands[0].reg; \ - RzILOpBitVector *rs1 = RISCV_GET_REG(insn->detail->riscv.operands[1].reg); \ - RzILOpBitVector *rs2 = RISCV_GET_REG(insn->detail->riscv.operands[2].reg); - -#define DECODE_RS_IMM(analysis, insn) \ - RzILOpBitVector *rs = RISCV_GET_REG(insn->detail->riscv.operands[0].reg); \ - RzILOpBitVector *imm = SN(analysis->bits, insn->detail->riscv.operands[1].imm); - -#define DECODE_RS_RS_IMM(analysis, insn) \ - RzILOpBitVector *rs1 = RISCV_GET_REG(insn->detail->riscv.operands[0].reg); \ - RzILOpBitVector *rs2 = RISCV_GET_REG(insn->detail->riscv.operands[1].reg); \ - RzILOpBitVector *imm = SN(analysis->bits, insn->detail->riscv.operands[2].imm); - -#define DECODE_RD_RS(analysis, insn) \ - uint32_t rd = insn->detail->riscv.operands[0].reg; \ - RzILOpBitVector *rs = RISCV_GET_REG(insn->detail->riscv.operands[1].reg); - -#define DECODE_IMM(analysis, insn) \ - RzILOpBitVector *imm = SN(analysis->bits, insn->detail->riscv.operands[0].imm); - -#define DECODE_RD_IMM(analysis, insn) \ - uint32_t rd = insn->detail->riscv.operands[0].reg; \ - RzILOpBitVector *imm = SN(analysis->bits, insn->detail->riscv.operands[1].imm); - -#define DECODE_RS_RS_IMM_MEM(analysis, insn) \ - RzILOpBitVector *rs1 = RISCV_GET_REG(insn->detail->riscv.operands[0].reg); \ - RzILOpBitVector *rs2 = RISCV_GET_REG(insn->detail->riscv.operands[1].mem.base); \ - RzILOpBitVector *imm = SN(analysis->bits, insn->detail->riscv.operands[1].mem.disp); - -#define DECODE_RD_RS_IMM_MEM(analysis, insn) \ - uint32_t rd = insn->detail->riscv.operands[0].reg; \ - RzILOpBitVector *rs = RISCV_GET_REG(insn->detail->riscv.operands[1].mem.base); \ - RzILOpBitVector *imm = SN(analysis->bits, insn->detail->riscv.operands[1].mem.disp); - -#define USE_LIFTER(name, uppername) [RISCV_INS_##uppername] = rz_riscv_lift_##name - -FOR_4(addi, c_addi, c_addi16sp, c_addi4spn, - DEFINE_LIFTER, DECODE_RD_RS_IMM, ADD(rs, imm)) -TWICE_FOR(slli, c_slli, - DEFINE_LIFTER, DECODE_RD_RS_IMM, SHIFTL0(rs, imm)) -TWICE_FOR(andi, c_andi, - DEFINE_LIFTER, DECODE_RD_RS_IMM, LOGAND(rs, imm)) -DEFINE_LIFTER(ori, DECODE_RD_RS_IMM, LOGOR(rs, imm)) -DEFINE_LIFTER(xori, DECODE_RD_RS_IMM, LOGXOR(rs, imm)) -DEFINE_LIFTER(slti, DECODE_RD_RS_IMM, BOOL_TO_BV(SLT(rs, imm), analysis->bits)) -DEFINE_LIFTER(sltiu, DECODE_RD_RS_IMM, BOOL_TO_BV(ULT(rs, imm), analysis->bits)) -TWICE_FOR(srli, c_srli, - DEFINE_LIFTER, DECODE_RD_RS_IMM, SHIFTR0(rs, imm)) -TWICE_FOR(srai, c_srai, - DEFINE_LIFTER, DECODE_RD_RS_IMM, SHIFTRA(rs, imm)) - -DEFINE_LIFTER(add, DECODE_RD_RS_RS, ADD(rs1, rs2)) -DEFINE_LIFTER(sub, DECODE_RD_RS_RS, SUB(rs1, rs2)) -DEFINE_LIFTER(and, DECODE_RD_RS_RS, LOGAND(rs1, rs2)) -DEFINE_LIFTER(or, DECODE_RD_RS_RS, LOGOR(rs1, rs2)) -DEFINE_LIFTER(xor, DECODE_RD_RS_RS, LOGXOR(rs1, rs2)) -DEFINE_LIFTER(slt, DECODE_RD_RS_RS, BOOL_TO_BV(SLT(rs1, rs2), analysis->bits)) -DEFINE_LIFTER(sltu, DECODE_RD_RS_RS, BOOL_TO_BV(ULT(rs1, rs2), analysis->bits)) -DEFINE_LIFTER(sll, DECODE_RD_RS_RS, SHIFTL0(rs1, rs2)) -DEFINE_LIFTER(srl, DECODE_RD_RS_RS, SHIFTR0(rs1, rs2)) -DEFINE_LIFTER(sra, DECODE_RD_RS_RS, SHIFTRA(rs1, rs2)) -#define DEFINE_LIFTER_FOR_BRANCH(name, decoder, condition) \ - DEFINE_LIFTER_FOR_ONEWAY_JUMP(name, decoder, BRANCH(condition, JMP(imm), JMP(UN(analysis->bits, current_addr + size)))) - -DEFINE_LIFTER_FOR_BRANCH(beq, DECODE_RS_RS_IMM, EQ(rs1, rs2)) -DEFINE_LIFTER_FOR_BRANCH(bne, DECODE_RS_RS_IMM, NE(rs1, rs2)) -DEFINE_LIFTER_FOR_BRANCH(blt, DECODE_RS_RS_IMM, SLT(rs1, rs2)) -DEFINE_LIFTER_FOR_BRANCH(bge, DECODE_RS_RS_IMM, SGE(rs1, rs2)) -DEFINE_LIFTER_FOR_BRANCH(bltu, DECODE_RS_RS_IMM, ULT(rs1, rs2)) -DEFINE_LIFTER_FOR_BRANCH(bgeu, DECODE_RS_RS_IMM, UGE(rs1, rs2)) - -DEFINE_LIFTER_FOR_BRANCH(c_beqz, DECODE_RS_IMM, EQ(rs, UN(analysis->bits, 0))) -DEFINE_LIFTER_FOR_BRANCH(c_bnez, DECODE_RS_IMM, NE(rs, UN(analysis->bits, 0))) - -DEFINE_LIFTER(c_mv, DECODE_RD_RS, DUP(rs)) - -DEFINE_LIFTER_FOR_ONEWAY_JUMP(c_j, DECODE_IMM, JMP(imm)) - -DEFINE_LIFTER_FOR_JUMP(jal, DECODE_RD_IMM, - /*RETURN ADDR*/ UN(analysis->bits, current_addr + size), - /*GOTO ADDR*/ JMP(imm)) - -TWICE_FOR(jalr, c_jr, - DEFINE_LIFTER_FOR_JUMP, DECODE_RD_RS_IMM, - /*RETURN ADDR*/ UN(analysis->bits, current_addr + size), - /*GOTO ADDR*/ JMP(LOGAND(ADD(rs, imm), UN(analysis->bits, ~1ULL)))) - -TWICE_FOR(lui, c_lui, - DEFINE_LIFTER, DECODE_RD_IMM, SHIFTL0(imm, UN(analysis->bits, 12))) -DEFINE_LIFTER(c_li, DECODE_RD_IMM, DUP(imm)) -DEFINE_LIFTER(auipc, DECODE_RD_IMM, ADD(UN(analysis->bits, current_addr), SHIFTL0(imm, UN(analysis->bits, 12)))) - -DEFINE_LIFTER_WITH_EFFECT(sb, DECODE_RS_RS_IMM_MEM, STOREW(ADD(rs2, imm), CAST(8, IL_FALSE, rs1))) -DEFINE_LIFTER_WITH_EFFECT(sh, DECODE_RS_RS_IMM_MEM, STOREW(ADD(rs2, imm), CAST(16, IL_FALSE, rs1))) - -THRICE_FOR(sw, c_sw, c_swsp, - DEFINE_LIFTER_WITH_EFFECT, DECODE_RS_RS_IMM_MEM, STOREW(ADD(rs2, imm), analysis->bits == 32 ? rs1 : CAST(64, IL_FALSE, rs1))) - -TWICE_FOR(sd, c_sd, - DEFINE_LIFTER_WITH_EFFECT, DECODE_RS_RS_IMM_MEM, STOREW(ADD(rs2, imm), rs1)) - -THRICE_FOR(lw, c_lwsp, c_lw, - DEFINE_LIFTER, DECODE_RD_RS_IMM_MEM, analysis->bits == 32 ? LOADW(32, ADD(rs, imm)) : SIGNED(analysis->bits, LOADW(32, ADD(rs, imm)))) -DEFINE_LIFTER(lb, DECODE_RD_RS_IMM_MEM, SIGNED(analysis->bits, LOADW(8, ADD(rs, imm)))) -DEFINE_LIFTER(lh, DECODE_RD_RS_IMM_MEM, SIGNED(analysis->bits, LOADW(16, ADD(rs, imm)))) -DEFINE_LIFTER(lbu, DECODE_RD_RS_IMM_MEM, UNSIGNED(analysis->bits, LOADW(8, ADD(rs, imm)))) -DEFINE_LIFTER(lhu, DECODE_RD_RS_IMM_MEM, UNSIGNED(analysis->bits, LOADW(16, ADD(rs, imm)))) - -TWICE_FOR(ld, c_ld, - DEFINE_LIFTER, DECODE_RD_RS_IMM_MEM, LOADW(64, ADD(rs, imm))) +#include "riscv_il.h" +#include "riscv_il_integer.h" +#include "riscv_il_m.h" +#include "riscv_il_compressed.h" -#include +static void label_ecall(RzILVM *vm, RzILOpEffect *op) { + // stub: ecall is handled at the analysis layer +} static const RiscvInstructionLifter riscv_lifters[] = { + /* ---------------------------------- Integer ---------------------------------*/ + // arithmetic, immediate USE_LIFTER(addi, ADDI), - USE_LIFTER(c_addi, C_ADDI), - USE_LIFTER(c_addi16sp, C_ADDI16SP), - USE_LIFTER(c_addi4spn, C_ADDI4SPN), USE_LIFTER(andi, ANDI), - USE_LIFTER(c_andi, C_ANDI), USE_LIFTER(ori, ORI), USE_LIFTER(xori, XORI), USE_LIFTER(slti, SLTI), @@ -219,56 +22,99 @@ static const RiscvInstructionLifter riscv_lifters[] = { USE_LIFTER(slli, SLLI), USE_LIFTER(srli, SRLI), USE_LIFTER(srai, SRAI), - USE_LIFTER(c_slli, C_SLLI), - USE_LIFTER(c_srli, C_SRLI), - USE_LIFTER(c_srai, C_SRAI), - USE_LIFTER(jalr, JALR), - USE_LIFTER(c_jr, C_JR), + // immediate constants + USE_LIFTER(lui, LUI), + USE_LIFTER(auipc, AUIPC), + // arithmetic + USE_LIFTER(add, ADD), + USE_LIFTER(sub, SUB), + USE_LIFTER(and, AND), + USE_LIFTER(or, OR), + USE_LIFTER(xor, XOR), + USE_LIFTER(slt, SLT), + USE_LIFTER(sltu, SLTU), + USE_LIFTER(sll, SLL), + USE_LIFTER(srl, SRL), + USE_LIFTER(sra, SRA), + // arithmetic, 32-bit operations in 64-bit mode + USE_LIFTER(addw, ADDW), + USE_LIFTER(subw, SUBW), + USE_LIFTER(sllw, SLLW), + USE_LIFTER(srlw, SRLW), + USE_LIFTER(sraw, SRAW), + USE_LIFTER(addiw, ADDIW), + USE_LIFTER(slliw, SLLIW), + USE_LIFTER(srliw, SRLIW), + USE_LIFTER(sraiw, SRAIW), + // memory USE_LIFTER(lb, LB), USE_LIFTER(lh, LH), USE_LIFTER(lw, LW), USE_LIFTER(lbu, LBU), USE_LIFTER(lhu, LHU), - USE_LIFTER(c_lwsp, C_LWSP), - USE_LIFTER(c_lw, C_LW), USE_LIFTER(ld, LD), - USE_LIFTER(c_ld, C_LD), - USE_LIFTER(lui, LUI), - USE_LIFTER(c_lui, C_LUI), - USE_LIFTER(c_li, C_LI), - USE_LIFTER(auipc, AUIPC), + USE_LIFTER(sb, SB), + USE_LIFTER(sh, SH), + USE_LIFTER(sw, SW), + USE_LIFTER(sd, SD), + // branches USE_LIFTER(beq, BEQ), USE_LIFTER(bne, BNE), USE_LIFTER(blt, BLT), USE_LIFTER(bge, BGE), USE_LIFTER(bltu, BLTU), USE_LIFTER(bgeu, BGEU), + USE_LIFTER(jalr, JALR), + USE_LIFTER(jal, JAL), + // concurrency, no-ops in RzIL + USE_LIFTER(fence, FENCE), + USE_LIFTER(fence_i, FENCE_I), + // system + USE_LIFTER(ecall, ECALL), + // RV64I extra loads + USE_LIFTER(lwu, LWU), + // M extension + USE_LIFTER(mul, MUL), + USE_LIFTER(mulhu, MULHU), + USE_LIFTER(divu, DIVU), + USE_LIFTER(remu, REMU), + USE_LIFTER(remuw, REMUW), + /* ---------------------------------- Compressed ---------------------------------*/ + USE_LIFTER(c_addi, C_ADDI), + USE_LIFTER(c_addi16sp, C_ADDI16SP), + USE_LIFTER(c_addi4spn, C_ADDI4SPN), + USE_LIFTER(c_add, C_ADD), + USE_LIFTER(c_andi, C_ANDI), + USE_LIFTER(c_slli, C_SLLI), + USE_LIFTER(c_srli, C_SRLI), + USE_LIFTER(c_srai, C_SRAI), + USE_LIFTER(c_jr, C_JR), + USE_LIFTER(c_jalr, C_JALR), + USE_LIFTER(c_lwsp, C_LWSP), + USE_LIFTER(c_lw, C_LW), + USE_LIFTER(c_ld, C_LD), + USE_LIFTER(c_lui, C_LUI), + USE_LIFTER(c_li, C_LI), USE_LIFTER(c_beqz, C_BEQZ), USE_LIFTER(c_bnez, C_BNEZ), - USE_LIFTER(sb, SB), - USE_LIFTER(sh, SH), - USE_LIFTER(sw, SW), USE_LIFTER(c_sw, C_SW), USE_LIFTER(c_swsp, C_SWSP), - USE_LIFTER(sd, SD), USE_LIFTER(c_sd, C_SD), - USE_LIFTER(add, ADD), - USE_LIFTER(sub, SUB), - USE_LIFTER(and, AND), - USE_LIFTER(or, OR), - USE_LIFTER(xor, XOR), - USE_LIFTER(slt, SLT), - USE_LIFTER(sltu, SLTU), - USE_LIFTER(sll, SLL), - USE_LIFTER(srl, SRL), - USE_LIFTER(sra, SRA), - USE_LIFTER(jal, JAL), USE_LIFTER(c_mv, C_MV), USE_LIFTER(c_j, C_J), + USE_LIFTER(c_or, C_OR), + USE_LIFTER(c_ldsp, C_LDSP), + USE_LIFTER(c_sdsp, C_SDSP), + USE_LIFTER(c_sub, C_SUB), + USE_LIFTER(c_and, C_AND), + USE_LIFTER(c_xor, C_XOR), + USE_LIFTER(c_addw, C_ADDW), + USE_LIFTER(c_addiw, C_ADDIW), + USE_LIFTER(c_subw, C_SUBW), }; RZ_OWN RZ_IPI RzILOpEffect * -rz_riscv_lift_instr(RZ_BORROW RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzAnalysisOp *op, RZ_NONNULL cs_insn *insn, ut64 current_addr, int size) { +rz_riscv_lift_instr(RZ_BORROW RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzAnalysisOp *op, RZ_NONNULL cs_insn *insn, ut64 current_addr, size_t size) { rz_return_val_if_fail(analysis && op && insn, NULL); if (insn->id > 0 && insn->id < RZ_ARRAY_SIZE(riscv_lifters)) { @@ -288,5 +134,9 @@ RZ_IPI RzAnalysisILConfig *rz_riscv_il_config(RZ_NONNULL RzAnalysis *analysis) { RzAnalysisILConfig *conf = rz_analysis_il_config_new(analysis->bits, analysis->big_endian, analysis->bits); + RzILEffectLabel *ecall_label = rz_il_effect_label_new("ecall", EFFECT_LABEL_SYSCALL); + ecall_label->hook = label_ecall; + rz_analysis_il_config_add_label(conf, ecall_label); + return conf; } \ No newline at end of file diff --git a/librz/arch/isa/riscv/riscv_il.h b/librz/arch/isa/riscv/riscv_il.h index eb398ed9042..03c42770f59 100644 --- a/librz/arch/isa/riscv/riscv_il.h +++ b/librz/arch/isa/riscv/riscv_il.h @@ -9,11 +9,11 @@ #include #include -typedef RzILOpEffect *(*RiscvInstructionLifter)(RZ_BORROW RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzAnalysisOp *op, RZ_NONNULL cs_insn *insn, ut64 current_addr, int size); +typedef RzILOpEffect *(*RiscvInstructionLifter)(RZ_BORROW RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzAnalysisOp *op, RZ_NONNULL cs_insn *insn, ut64 current_addr, size_t size); RZ_OWN RZ_IPI RzILOpEffect * rz_riscv_lift_instr(RZ_BORROW RZ_NONNULL RzAnalysis *analysis, - RZ_NONNULL RzAnalysisOp *op, RZ_NONNULL cs_insn *insn, ut64 current_addr, int size); + RZ_NONNULL RzAnalysisOp *op, RZ_NONNULL cs_insn *insn, ut64 current_addr, size_t size); RZ_IPI RzAnalysisILConfig *rz_riscv_il_config(RZ_NONNULL RzAnalysis *analysis); diff --git a/librz/arch/isa/riscv/riscv_il_base.h b/librz/arch/isa/riscv/riscv_il_base.h new file mode 100644 index 00000000000..c52516ed77e --- /dev/null +++ b/librz/arch/isa/riscv/riscv_il_base.h @@ -0,0 +1,199 @@ +// SPDX-FileCopyrightText: 2026 Mostafa Mahmoud +// SPDX-License-Identifier: BSD-3-Clause + +#ifndef RISCV_IL_BASE_H +#define RISCV_IL_BASE_H + +#include "riscv.h" +#include "rz_types.h" +#include + +#include "riscv_il.h" +#include "riscv_il_integer_reg_names.h" + +#include + +#define RISCV_GET_REG(reg) (((reg) != RISCV_REG_X0) ? (VARG(riscv_integer_reg_name(reg))) : UN(analysis->bits, 0)) +#define RISCV_SET_REG(reg, r) (((reg) != RISCV_REG_X0) ? (SETG(riscv_integer_reg_name(reg), r)) : ((rz_il_op_pure_free(r), NOP()))) + +#define DEFINE_LIFTER(name, decoder, result) \ + static RzILOpEffect *rz_riscv_lift_##name(RZ_BORROW RZ_NONNULL RzAnalysis *analysis, \ + RZ_NONNULL RzAnalysisOp *op, RZ_NONNULL cs_insn *insn, ut64 current_addr, size_t size) { \ + decoder(analysis, insn); \ + return RISCV_SET_REG(rd, result); \ + } + +// by default, a RISC-V jump both sets a destination and sets the PC (i.e., jumps) +#define DEFINE_LIFTER_FOR_JUMP(name, decoder, result, jmp_effect) \ + static RzILOpEffect *rz_riscv_lift_##name(RZ_BORROW RZ_NONNULL RzAnalysis *analysis, \ + RZ_NONNULL RzAnalysisOp *op, RZ_NONNULL cs_insn *insn, ut64 current_addr, size_t size) { \ + decoder(analysis, insn); \ + return SEQ2( \ + RISCV_SET_REG(rd, result), \ + jmp_effect); \ + } + +#define DEFINE_LIFTER_WITH_EFFECT(name, decoder, effect) \ + static RzILOpEffect *rz_riscv_lift_##name(RZ_BORROW RZ_NONNULL RzAnalysis *analysis, \ + RZ_NONNULL RzAnalysisOp *op, RZ_NONNULL cs_insn *insn, ut64 current_addr, size_t size) { \ + decoder(analysis, insn); \ + return effect; \ + } + +// oneway jumps are those that don't have a destination register +#define DEFINE_LIFTER_FOR_ONEWAY_JUMP DEFINE_LIFTER_WITH_EFFECT + +// A more intuitive definition would be: +// static const RiscvInstructionLifter rz_riscv_lift_##alias = ...; +// but C (unlike C++) does not treat const-qualified variables as constant expressions +// (C11 §6.6), so they cannot appear in a static array initializer. Most compilers +// accept it tolerantly, but TCC enforces the standard strictly and rejects it. +// A forced-inline wrapper is an alternative for 0-indirection aliasing. +#define DEFINE_ALIAS_LIFTER(alias, name) \ + static inline FUNC_ATTR_ALWAYS_INLINE RzILOpEffect *rz_riscv_lift_##alias(RZ_BORROW RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzAnalysisOp *op, RZ_NONNULL cs_insn *insn, ut64 current_addr, size_t size) { \ + return rz_riscv_lift_##name(analysis, op, insn, current_addr, size); \ + } + +#define TWICE_FOR(name1, name2, def_lifter, ...) \ + def_lifter(name1, __VA_ARGS__) \ + def_lifter(name2, __VA_ARGS__) + +#define THRICE_FOR(name1, name2, name3, def_lifter, ...) \ + TWICE_FOR(name1, name2, def_lifter, __VA_ARGS__) \ + def_lifter(name3, __VA_ARGS__) + +#define FOR_4(name1, name2, name3, name4, def_lifter, ...) \ + TWICE_FOR(name1, name2, def_lifter, __VA_ARGS__) \ + TWICE_FOR(name3, name4, def_lifter, __VA_ARGS__) + +#if RZ_CHECKS_LEVEL > 0 +#define REQUIRE_OP(idx, t) \ + if (insn->detail->riscv.operands[idx].type != (t) || insn->detail->riscv.operands[idx].type == RISCV_OP_INVALID) { \ + RZ_LOG_ERROR("[%s (%d) @ 0x%08" PFMT64x "] Expected type %d (%s) at index %d, found type %d instead\n", insn->mnemonic, insn->id, current_addr, t, #t, idx, insn->detail->riscv.operands[idx].type); \ + RZ_LOG_ERROR("op_str: %s\n", insn->op_str); \ + RZ_LOG_ERROR("need_effective_addr: %d\n", insn->detail->riscv.need_effective_addr); \ + RZ_LOG_ERROR("op_count: %u\n", insn->detail->riscv.op_count); \ + for (int _i = 0; _i < insn->detail->riscv.op_count; _i++) { \ + RZ_LOG_ERROR("operands[%d].type: %d\n", _i, insn->detail->riscv.operands[_i].type); \ + if (insn->detail->riscv.operands[_i].type == RISCV_OP_REG) { \ + RZ_LOG_ERROR(" REG = %d\n", insn->detail->riscv.operands[_i].reg); \ + } else if (insn->detail->riscv.operands[_i].type == RISCV_OP_IMM) { \ + RZ_LOG_ERROR(" IMM = 0x%" PFMT64x "\n", (ut64)insn->detail->riscv.operands[_i].imm); \ + } else if (insn->detail->riscv.operands[_i].type == RISCV_OP_MEM) { \ + RZ_LOG_ERROR(" MEM base = %d, disp = 0x%" PFMT64x "\n", insn->detail->riscv.operands[_i].mem.base, (ut64)insn->detail->riscv.operands[_i].mem.disp); \ + } \ + } \ + return NULL; \ + } + +#define REQUIRE_64_BIT(analysis) \ + if (analysis->bits != 64) { \ + RZ_LOG_ERROR("[%s (%d)] Expected 64-bit analysis, found %d bits\n", insn->mnemonic, insn->id, analysis->bits); \ + return NULL; \ + } +#else +#define REQUIRE_OP(idx, t) \ + do { \ + } while (0) +#define REQUIRE_64_BIT(analysis) \ + do { \ + } while (0) +#endif + +// Decoders, every instruction defines how its own transformation of capstone operands to IL operands + +#define DECODE_RD_RS_IMM(analysis, insn) \ + REQUIRE_OP(0, RISCV_OP_REG); \ + REQUIRE_OP(1, RISCV_OP_REG); \ + REQUIRE_OP(2, RISCV_OP_IMM); \ + uint32_t rd = insn->detail->riscv.operands[0].reg; \ + RzILOpBitVector *rs = RISCV_GET_REG(insn->detail->riscv.operands[1].reg); \ + RzILOpBitVector *imm = SN(analysis->bits, insn->detail->riscv.operands[2].imm); + +#define DECODE_RD_RS_RS(analysis, insn) \ + REQUIRE_OP(0, RISCV_OP_REG); \ + REQUIRE_OP(1, RISCV_OP_REG); \ + REQUIRE_OP(2, RISCV_OP_REG); \ + uint32_t rd = insn->detail->riscv.operands[0].reg; \ + RzILOpBitVector *rs1 = RISCV_GET_REG(insn->detail->riscv.operands[1].reg); \ + RzILOpBitVector *rs2 = RISCV_GET_REG(insn->detail->riscv.operands[2].reg); + +#define DECODE_RS_IMM(analysis, insn) \ + REQUIRE_OP(0, RISCV_OP_REG); \ + REQUIRE_OP(1, RISCV_OP_IMM); \ + RzILOpBitVector *rs = RISCV_GET_REG(insn->detail->riscv.operands[0].reg); \ + RzILOpBitVector *imm = SN(analysis->bits, insn->detail->riscv.operands[1].imm); + +#define DECODE_RS_RS_IMM(analysis, insn) \ + REQUIRE_OP(0, RISCV_OP_REG); \ + REQUIRE_OP(1, RISCV_OP_REG); \ + REQUIRE_OP(2, RISCV_OP_IMM); \ + RzILOpBitVector *rs1 = RISCV_GET_REG(insn->detail->riscv.operands[0].reg); \ + RzILOpBitVector *rs2 = RISCV_GET_REG(insn->detail->riscv.operands[1].reg); \ + RzILOpBitVector *imm = SN(analysis->bits, insn->detail->riscv.operands[2].imm); + +#define DECODE_RD_RS(analysis, insn) \ + REQUIRE_OP(0, RISCV_OP_REG); \ + REQUIRE_OP(1, RISCV_OP_REG); \ + uint32_t rd = insn->detail->riscv.operands[0].reg; \ + RzILOpBitVector *rs = RISCV_GET_REG(insn->detail->riscv.operands[1].reg); + +#define DECODE_IMM(analysis, insn) \ + REQUIRE_OP(0, RISCV_OP_IMM); \ + RzILOpBitVector *imm = SN(analysis->bits, insn->detail->riscv.operands[0].imm); + +#define DECODE_RD_IMM(analysis, insn) \ + REQUIRE_OP(0, RISCV_OP_REG); \ + REQUIRE_OP(1, RISCV_OP_IMM); \ + uint32_t rd = insn->detail->riscv.operands[0].reg; \ + RzILOpBitVector *imm = SN(analysis->bits, insn->detail->riscv.operands[1].imm); + +#define DECODE_RS_RS_IMM_MEM(analysis, insn) \ + REQUIRE_OP(0, RISCV_OP_REG); \ + REQUIRE_OP(1, RISCV_OP_MEM); \ + RzILOpBitVector *rs1 = RISCV_GET_REG(insn->detail->riscv.operands[0].reg); \ + RzILOpBitVector *rs2 = RISCV_GET_REG(insn->detail->riscv.operands[1].mem.base); \ + RzILOpBitVector *imm = SN(analysis->bits, insn->detail->riscv.operands[1].mem.disp); + +#define DECODE_RD_RS_IMM_MEM(analysis, insn) \ + REQUIRE_OP(0, RISCV_OP_REG); \ + REQUIRE_OP(1, RISCV_OP_MEM); \ + uint32_t rd = insn->detail->riscv.operands[0].reg; \ + RzILOpBitVector *rs = RISCV_GET_REG(insn->detail->riscv.operands[1].mem.base); \ + RzILOpBitVector *imm = SN(analysis->bits, insn->detail->riscv.operands[1].mem.disp); + +// used for *w instructions in RV64 that truncate the operands to 32 bits then does the operation +#define DECODE_RD_RS_RS_TRUNCATE32(analysis, insn) \ + REQUIRE_64_BIT(analysis); \ + REQUIRE_OP(0, RISCV_OP_REG); \ + REQUIRE_OP(1, RISCV_OP_REG); \ + REQUIRE_OP(2, RISCV_OP_REG); \ + uint32_t rd = insn->detail->riscv.operands[0].reg; \ + RzILOpBitVector *rs1 = CAST(32, IL_FALSE, RISCV_GET_REG(insn->detail->riscv.operands[1].reg)); \ + RzILOpBitVector *rs2 = CAST(32, IL_FALSE, RISCV_GET_REG(insn->detail->riscv.operands[2].reg)); + +#define DECODE_RD_RS_IMM_TRUNCATE32(analysis, insn) \ + REQUIRE_64_BIT(analysis); \ + REQUIRE_OP(0, RISCV_OP_REG); \ + REQUIRE_OP(1, RISCV_OP_REG); \ + REQUIRE_OP(2, RISCV_OP_IMM); \ + uint32_t rd = insn->detail->riscv.operands[0].reg; \ + RzILOpBitVector *rs = CAST(32, IL_FALSE, RISCV_GET_REG(insn->detail->riscv.operands[1].reg)); \ + RzILOpBitVector *imm = SN(32, insn->detail->riscv.operands[2].imm); + +#define DECODE_RD_IMM_TRUNCATE32(analysis, insn) \ + REQUIRE_64_BIT(analysis); \ + REQUIRE_OP(0, RISCV_OP_REG); \ + REQUIRE_OP(1, RISCV_OP_IMM); \ + uint32_t rd = insn->detail->riscv.operands[0].reg; \ + RzILOpBitVector *imm = SN(32, insn->detail->riscv.operands[1].imm); + +#define DECODE_NONE(analysis, insn) \ + (void)analysis; \ + (void)insn; + +#define USE_LIFTER(name, uppername) [RISCV_INS_##uppername] = rz_riscv_lift_##name + +#include + +#endif // RISCV_IL_BASE_H \ No newline at end of file diff --git a/librz/arch/isa/riscv/riscv_il_compressed.h b/librz/arch/isa/riscv/riscv_il_compressed.h new file mode 100644 index 00000000000..955a112a31f --- /dev/null +++ b/librz/arch/isa/riscv/riscv_il_compressed.h @@ -0,0 +1,71 @@ +// SPDX-FileCopyrightText: 2026 Mostafa Mahmoud +// SPDX-License-Identifier: BSD-3-Clause + +#ifndef RISCV_IL_COMPRESSED_H +#define RISCV_IL_COMPRESSED_H + +#include "riscv/riscv_il_base.h" +#include "riscv_il_integer.h" +#include "rz_util/rz_buf.h" + +#include + +// Compressed instruction decoder variants that suppress operands not consumed by the lifter +#define DECODE_RD_RS_IMM_NO_RS(analysis, insn) \ + DECODE_RD_RS_IMM(analysis, insn) \ + (void)(rs); + +#define DECODE_RD_IMM_NO_RD(analysis, insn) \ + DECODE_RD_IMM(analysis, insn) \ + (void)(rd); + +#define DECODE_RS_RS_IMM_NO_RS2(analysis, insn) \ + DECODE_RS_RS_IMM(analysis, insn) \ + (void)(rs2); + +DEFINE_ALIAS_LIFTER(c_addi, addi) +DEFINE_ALIAS_LIFTER(c_addi16sp, addi) +DEFINE_ALIAS_LIFTER(c_addi4spn, addi) +DEFINE_ALIAS_LIFTER(c_add, add) +DEFINE_ALIAS_LIFTER(c_slli, slli) +DEFINE_ALIAS_LIFTER(c_andi, andi) +DEFINE_ALIAS_LIFTER(c_srli, srli) +DEFINE_ALIAS_LIFTER(c_srai, srai) +DEFINE_ALIAS_LIFTER(c_or, or) +DEFINE_ALIAS_LIFTER(c_sub, sub) +DEFINE_ALIAS_LIFTER(c_and, and) +DEFINE_ALIAS_LIFTER(c_xor, xor) +DEFINE_ALIAS_LIFTER(c_addw, addw) + +DEFINE_ALIAS_LIFTER(c_addiw, addiw) + +DEFINE_ALIAS_LIFTER(c_subw, subw) + +DEFINE_LIFTER(c_mv, DECODE_RD_RS, DUP(rs)) +DEFINE_LIFTER(c_li, DECODE_RD_RS_IMM_NO_RS, DUP(imm)) + +DEFINE_LIFTER_FOR_ONEWAY_JUMP(c_j, DECODE_RD_IMM_NO_RD, JMP(imm)) +DEFINE_ALIAS_LIFTER(c_jr, jalr) + +DEFINE_ALIAS_LIFTER(c_jalr, jalr) + +DEFINE_ALIAS_LIFTER(c_lui, lui) + +DEFINE_ALIAS_LIFTER(c_sw, sw) +DEFINE_ALIAS_LIFTER(c_swsp, sw) + +DEFINE_ALIAS_LIFTER(c_sd, sd) +DEFINE_ALIAS_LIFTER(c_sdsp, sd) + +DEFINE_ALIAS_LIFTER(c_lwsp, lw) +DEFINE_ALIAS_LIFTER(c_lw, lw) + +DEFINE_ALIAS_LIFTER(c_ld, ld) +DEFINE_ALIAS_LIFTER(c_ldsp, ld) + +DEFINE_LIFTER_FOR_BRANCH(c_beqz, DECODE_RS_RS_IMM_NO_RS2, EQ(rs1, UN(analysis->bits, 0))) +DEFINE_LIFTER_FOR_BRANCH(c_bnez, DECODE_RS_RS_IMM_NO_RS2, NE(rs1, UN(analysis->bits, 0))) + +#include + +#endif // RISCV_IL_COMPRESSED_H diff --git a/librz/arch/isa/riscv/riscv_il_integer.h b/librz/arch/isa/riscv/riscv_il_integer.h new file mode 100644 index 00000000000..6159636594f --- /dev/null +++ b/librz/arch/isa/riscv/riscv_il_integer.h @@ -0,0 +1,99 @@ +// SPDX-FileCopyrightText: 2026 Mostafa Mahmoud +// SPDX-License-Identifier: BSD-3-Clause + +#ifndef RISCV_IL_INTEGER_H +#define RISCV_IL_INTEGER_H + +#include "analysis_private.h" +#include "capstone.h" +#include "riscv_il_base.h" + +#include + +DEFINE_LIFTER(addi, DECODE_RD_RS_IMM, ADD(rs, imm)) +DEFINE_LIFTER(slli, DECODE_RD_RS_IMM, SHIFTL0(rs, imm)) +DEFINE_LIFTER(andi, DECODE_RD_RS_IMM, LOGAND(rs, imm)) +DEFINE_LIFTER(ori, DECODE_RD_RS_IMM, LOGOR(rs, imm)) +DEFINE_LIFTER(xori, DECODE_RD_RS_IMM, LOGXOR(rs, imm)) +DEFINE_LIFTER(slti, DECODE_RD_RS_IMM, BOOL_TO_BV(SLT(rs, imm), analysis->bits)) +DEFINE_LIFTER(sltiu, DECODE_RD_RS_IMM, BOOL_TO_BV(ULT(rs, imm), analysis->bits)) +DEFINE_LIFTER(srli, DECODE_RD_RS_IMM, SHIFTR0(rs, imm)) +DEFINE_LIFTER(srai, DECODE_RD_RS_IMM, SHIFTRA(rs, imm)) + +DEFINE_LIFTER(add, DECODE_RD_RS_RS, ADD(rs1, rs2)) +DEFINE_LIFTER(sub, DECODE_RD_RS_RS, SUB(rs1, rs2)) +DEFINE_LIFTER(and, DECODE_RD_RS_RS, LOGAND(rs1, rs2)) +DEFINE_LIFTER(or, DECODE_RD_RS_RS, LOGOR(rs1, rs2)) +DEFINE_LIFTER(xor, DECODE_RD_RS_RS, LOGXOR(rs1, rs2)) +DEFINE_LIFTER(slt, DECODE_RD_RS_RS, BOOL_TO_BV(SLT(rs1, rs2), analysis->bits)) +DEFINE_LIFTER(sltu, DECODE_RD_RS_RS, BOOL_TO_BV(ULT(rs1, rs2), analysis->bits)) +DEFINE_LIFTER(sll, DECODE_RD_RS_RS, SHIFTL0(rs1, LOGAND(rs2, UN(analysis->bits, analysis->bits - 1)))) +DEFINE_LIFTER(srl, DECODE_RD_RS_RS, SHIFTR0(rs1, LOGAND(rs2, UN(analysis->bits, analysis->bits - 1)))) +DEFINE_LIFTER(sra, DECODE_RD_RS_RS, SHIFTRA(rs1, LOGAND(rs2, UN(analysis->bits, analysis->bits - 1)))) + +#define DEFINE_LIFTER_FOR_BRANCH(name, decoder, condition) \ + DEFINE_LIFTER_FOR_ONEWAY_JUMP(name, decoder, BRANCH(condition, JMP(imm), JMP(UN(analysis->bits, current_addr + size)))) + +DEFINE_LIFTER_FOR_BRANCH(beq, DECODE_RS_RS_IMM, EQ(rs1, rs2)) +DEFINE_LIFTER_FOR_BRANCH(bne, DECODE_RS_RS_IMM, NE(rs1, rs2)) +DEFINE_LIFTER_FOR_BRANCH(blt, DECODE_RS_RS_IMM, SLT(rs1, rs2)) +DEFINE_LIFTER_FOR_BRANCH(bge, DECODE_RS_RS_IMM, SGE(rs1, rs2)) +DEFINE_LIFTER_FOR_BRANCH(bltu, DECODE_RS_RS_IMM, ULT(rs1, rs2)) +DEFINE_LIFTER_FOR_BRANCH(bgeu, DECODE_RS_RS_IMM, UGE(rs1, rs2)) + +DEFINE_LIFTER_FOR_JUMP(jal, DECODE_RD_IMM, + /*RETURN ADDR*/ UN(analysis->bits, current_addr + size), + /*GOTO ADDR*/ JMP(imm)) + +DEFINE_LIFTER_FOR_JUMP(jalr, DECODE_RD_RS_IMM, + /*RETURN ADDR*/ UN(analysis->bits, current_addr + size), + /*GOTO ADDR*/ JMP(LOGAND(ADD(rs, imm), UN(analysis->bits, ~1ULL)))) + +// Intentional: on RV32 imm is already 32-bit and the result needs no sign-extension, +// so CAST(32) and SIGNED(32) would both be no-ops; on RV64 CAST(32) truncates imm and SIGNED(64) +// sign-extends the shifted 32-bit result to XLEN. +DEFINE_LIFTER(lui, DECODE_RD_IMM, + analysis->bits == 32 + ? SHIFTL0(imm, UN(32, 12)) + : SIGNED(analysis->bits, SHIFTL0(CAST(32, IL_FALSE, imm), UN(32, 12)))) +DEFINE_LIFTER(auipc, DECODE_RD_IMM, ADD(UN(analysis->bits, current_addr), SIGNED(analysis->bits, SHIFTL0(CAST(32, IL_FALSE, imm), UN(32, 12))))) + +DEFINE_LIFTER_WITH_EFFECT(sb, DECODE_RS_RS_IMM_MEM, STOREW(ADD(rs2, imm), CAST(8, IL_FALSE, rs1))) +DEFINE_LIFTER_WITH_EFFECT(sh, DECODE_RS_RS_IMM_MEM, STOREW(ADD(rs2, imm), CAST(16, IL_FALSE, rs1))) +// Intentional: on RV32 rs1 is already 32-bit so CAST(32) would be a redundant no-op; +// on RV64 it is needed to truncate the 64-bit register value to 32 bits before storing. +DEFINE_LIFTER_WITH_EFFECT(sw, DECODE_RS_RS_IMM_MEM, + analysis->bits == 32 + ? STOREW(ADD(rs2, imm), rs1) + : STOREW(ADD(rs2, imm), CAST(32, IL_FALSE, rs1))) +DEFINE_LIFTER_WITH_EFFECT(sd, DECODE_RS_RS_IMM_MEM, STOREW(ADD(rs2, imm), rs1)) + +DEFINE_LIFTER(lw, DECODE_RD_RS_IMM_MEM, analysis->bits == 32 ? LOADW(32, ADD(rs, imm)) : SIGNED(analysis->bits, LOADW(32, ADD(rs, imm)))) +DEFINE_LIFTER(lb, DECODE_RD_RS_IMM_MEM, SIGNED(analysis->bits, LOADW(8, ADD(rs, imm)))) +DEFINE_LIFTER(lh, DECODE_RD_RS_IMM_MEM, SIGNED(analysis->bits, LOADW(16, ADD(rs, imm)))) +DEFINE_LIFTER(lbu, DECODE_RD_RS_IMM_MEM, UNSIGNED(analysis->bits, LOADW(8, ADD(rs, imm)))) +DEFINE_LIFTER(lhu, DECODE_RD_RS_IMM_MEM, UNSIGNED(analysis->bits, LOADW(16, ADD(rs, imm)))) +DEFINE_LIFTER(ld, DECODE_RD_RS_IMM_MEM, LOADW(64, ADD(rs, imm))) + +TWICE_FOR(fence, fence_i, + DEFINE_LIFTER_WITH_EFFECT, DECODE_NONE, NOP()) + +DEFINE_LIFTER(addw, DECODE_RD_RS_RS_TRUNCATE32, SIGNED(analysis->bits, ADD(rs1, rs2))) +DEFINE_LIFTER(subw, DECODE_RD_RS_RS_TRUNCATE32, SIGNED(analysis->bits, SUB(rs1, rs2))) +DEFINE_LIFTER(sllw, DECODE_RD_RS_RS_TRUNCATE32, SIGNED(analysis->bits, SHIFTL0(rs1, LOGAND(rs2, UN(32, 31))))) +DEFINE_LIFTER(srlw, DECODE_RD_RS_RS_TRUNCATE32, SIGNED(analysis->bits, SHIFTR0(rs1, LOGAND(rs2, UN(32, 31))))) +DEFINE_LIFTER(sraw, DECODE_RD_RS_RS_TRUNCATE32, SIGNED(analysis->bits, SHIFTRA(rs1, LOGAND(rs2, UN(32, 31))))) +DEFINE_LIFTER(addiw, DECODE_RD_RS_IMM_TRUNCATE32, SIGNED(analysis->bits, ADD(rs, imm))) +DEFINE_LIFTER(slliw, DECODE_RD_RS_IMM_TRUNCATE32, SIGNED(analysis->bits, SHIFTL0(rs, imm))) +DEFINE_LIFTER(srliw, DECODE_RD_RS_IMM_TRUNCATE32, SIGNED(analysis->bits, SHIFTR0(rs, imm))) +DEFINE_LIFTER(sraiw, DECODE_RD_RS_IMM_TRUNCATE32, SIGNED(analysis->bits, SHIFTRA(rs, imm))) + +// RV64I: load word unsigned (zero-extend 32-bit load to XLEN) +DEFINE_LIFTER(lwu, DECODE_RD_RS_IMM_MEM, UNSIGNED(analysis->bits, LOADW(32, ADD(rs, imm)))) + +// System: environment call (trap to OS / hypervisor) +DEFINE_LIFTER_WITH_EFFECT(ecall, DECODE_NONE, GOTO("ecall")) + +#include + +#endif // RISCV_IL_INTEGER_H \ No newline at end of file diff --git a/librz/arch/isa/riscv/riscv_il_integer_reg_names.h b/librz/arch/isa/riscv/riscv_il_integer_reg_names.h new file mode 100644 index 00000000000..80cadb58790 --- /dev/null +++ b/librz/arch/isa/riscv/riscv_il_integer_reg_names.h @@ -0,0 +1,53 @@ +// SPDX-FileCopyrightText: 2026 Mostafa Mahmoud +// SPDX-License-Identifier: BSD-3-Clause + +#ifndef RISCV_IL_INTEGER_REG_NAMES_H +#define RISCV_IL_INTEGER_REG_NAMES_H + +#include +#include + +static const char *riscv_integer_reg_names[] = { + /* x0 */ "zero", + /* x1 */ "ra", + /* x2 */ "sp", + /* x3 */ "gp", + /* x4 */ "tp", + /* x5 */ "t0", + /* x6 */ "t1", + /* x7 */ "t2", + /* x8 */ "s0", + /* x9 */ "s1", + /* x10 */ "a0", + /* x11 */ "a1", + /* x12 */ "a2", + /* x13 */ "a3", + /* x14 */ "a4", + /* x15 */ "a5", + /* x16 */ "a6", + /* x17 */ "a7", + /* x18 */ "s2", + /* x19 */ "s3", + /* x20 */ "s4", + /* x21 */ "s5", + /* x22 */ "s6", + /* x23 */ "s7", + /* x24 */ "s8", + /* x25 */ "s9", + /* x26 */ "s10", + /* x27 */ "s11", + /* x28 */ "t3", + /* x29 */ "t4", + /* x30 */ "t5", + /* x31 */ "t6", +}; + +static inline const char *riscv_integer_reg_name(uint32_t reg) { + int idx = (int)reg - RISCV_REG_X0; + if (idx < 0 || idx >= 32) { + return ""; + } + return riscv_integer_reg_names[idx]; +} + +#endif // RISCV_IL_INTEGER_REG_NAMES_H diff --git a/librz/arch/isa/riscv/riscv_il_m.h b/librz/arch/isa/riscv/riscv_il_m.h new file mode 100644 index 00000000000..e3f666f6a44 --- /dev/null +++ b/librz/arch/isa/riscv/riscv_il_m.h @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: 2026 Mostafa Mahmoud +// SPDX-License-Identifier: BSD-3-Clause + +#ifndef RISCV_IL_M_H +#define RISCV_IL_M_H + +#include "riscv_il_base.h" + +#include + +// M extension: multiply/divide/remainder (RV32M / RV64M) +DEFINE_LIFTER(mul, DECODE_RD_RS_RS, MUL(rs1, rs2)) +DEFINE_LIFTER(mulhu, DECODE_RD_RS_RS, CAST(analysis->bits, IL_FALSE, SHIFTR0(MUL(UNSIGNED(analysis->bits * 2, rs1), UNSIGNED(analysis->bits * 2, rs2)), UN(8, analysis->bits)))) +DEFINE_LIFTER(divu, DECODE_RD_RS_RS, DIV(rs1, rs2)) +DEFINE_LIFTER(remu, DECODE_RD_RS_RS, MOD(rs1, rs2)) +// RV64M: unsigned remainder of 32-bit operands, result sign-extended to 64 bits +DEFINE_LIFTER(remuw, DECODE_RD_RS_RS_TRUNCATE32, SIGNED(analysis->bits, MOD(rs1, rs2))) + +#include + +#endif // RISCV_IL_M_H diff --git a/test/db/asm/riscv_32 b/test/db/asm/riscv_32 index 269ff99bf7a..87831e4ba54 100644 --- a/test/db/asm/riscv_32 +++ b/test/db/asm/riscv_32 @@ -49,18 +49,18 @@ d "lw s8, 0x68(sp)" 265c 0x40 (set s8 (loadw 0 32 (+ (var sp) (bv 32 0x68)))) d "lw s9, 0x64(sp)" 965c 0x40 (set s9 (loadw 0 32 (+ (var sp) (bv 32 0x64)))) d "lw s10, 0x60(sp)" 065d 0x40 (set s10 (loadw 0 32 (+ (var sp) (bv 32 0x60)))) d "lw s11, 0x5c(sp)" f64d 0x40 (set s11 (loadw 0 32 (+ (var sp) (bv 32 0x5c)))) -d "addi sp, sp, 0x90" 4961 0x40 -d "ret" 8280 0x40 NONE +d "addi sp, sp, 0x90" 4961 0x40 (set sp (+ (var sp) (bv 32 0x90))) +d "ret" 8280 0x40 (seq nop (jmp (& (+ (var ra) (bv 32 0x0)) (bv 32 0xfffffffe)))) d "lw a5, 0x18(sp)" e247 0x40 (set a5 (loadw 0 32 (+ (var sp) (bv 32 0x18)))) -d "beqz a5, 0x2d8" 63890726 0x66 +d "beqz a5, 0x2d8" 63890726 0x66 (branch (== (var a5) (bv 32 0x0)) (jmp (bv 32 0x2d8)) (jmp (bv 32 0x6a))) d "lw s0, 0x1c(sp)" 7244 0x40 (set s0 (loadw 0 32 (+ (var sp) (bv 32 0x1c)))) d "lw a0, 0x24(sp)" 1255 0x40 (set a0 (loadw 0 32 (+ (var sp) (bv 32 0x24)))) d "lw a6, 0x28(sp)" 2258 0x40 (set a6 (loadw 0 32 (+ (var sp) (bv 32 0x28)))) d "lw t3, 0x38(sp)" 625e 0x40 (set t3 (loadw 0 32 (+ (var sp) (bv 32 0x38)))) -d "srai a5, s0, 0x1f" 9357f441 0x40 +d "srai a5, s0, 0x1f" 9357f441 0x40 (set a5 (>> (var s0) (bv 32 0x1f) (msb (var s0)))) d "lw a2, 0x20(sp)" 0256 0x40 (set a2 (loadw 0 32 (+ (var sp) (bv 32 0x20)))) d "andi a5, a5, 0xf" bd8b 0x40 (set a5 (& (var a5) (bv 32 0xf))) -d "srai a4, a0, 0x1f" 1357f541 0x40 +d "srai a4, a0, 0x1f" 1357f541 0x40 (set a4 (>> (var a0) (bv 32 0x1f) (msb (var a0)))) d "lw a7, 0x30(sp)" c258 0x40 (set a7 (loadw 0 32 (+ (var sp) (bv 32 0x30)))) d "add a3, a5, a6" b3860701 0x80 (set a3 (+ (var a5) (var a6))) d "sub s2, t3, a6" 33090e41 0x80 (set s2 (- (var t3) (var a6))) @@ -81,7 +81,7 @@ d "srli a1, a1, 6" 9981 0x80 (set a1 (>> (var a1) (bv 32 0x6) false)) d "slli a0, a5, 0x1a" 1395a701 0x80 (set a0 (<< (var a5) (bv 32 0x1a) false)) d "sw a4, 0x40(sp)" bac0 0x80 (storew 0 (+ (var sp) (bv 32 0x40)) (var a4)) d "sub a4, a2, a7" 33071641 0x80 (set a4 (- (var a2) (var a7))) -d "add s7, s7, s0" a29b 0xc0 NONE +d "add s7, s7, s0" a29b 0xc0 (set s7 (+ (var s7) (var s0))) d "sw a4, 0x44(sp)" bac2 0xc0 (storew 0 (+ (var sp) (bv 32 0x44)) (var a4)) d "srai a5, a5, 6" 9987 0xc0 (set a5 (>> (var a5) (bv 32 0x6) (msb (var a5)))) d "or a4, a0, a1" 3367b500 0xc0 (set a4 (| (var a0) (var a1))) @@ -100,7 +100,7 @@ d "lui a4, 1" 0567 0xc0 (set a4 (<< (bv 32 0x1) (bv 32 0xc) false)) d "blt a5, a4, 0x2d4" 63c3e71e 0xee (branch (&& (sle (var a5) (var a4)) (! (== (var a5) (var a4)))) (jmp (bv 32 0x2d4)) (jmp (bv 32 0xf2))) d "srli a5, s8, 0x1d" 9357dc01 0xc0 (set a5 (>> (var s8) (bv 32 0x1d) false)) d "slli a4, s7, 3" 13973b00 0xc0 (set a4 (<< (var s7) (bv 32 0x3) false)) -d "or a5, a5, a4" d98f 0xc0 NONE +d "or a5, a5, a4" d98f 0xc0 (set a5 (| (var a5) (var a4))) d "sw a5, 0x4c(sp)" bec6 0xc0 (storew 0 (+ (var sp) (bv 32 0x4c)) (var a5)) d "slli a5, s8, 3" 93173c00 0xc0 (set a5 (<< (var s8) (bv 32 0x3) false)) d "addi a5, sp, 8" 3c00 0x100 (set a5 (+ (var sp) (bv 32 0x8))) @@ -133,63 +133,63 @@ d "li t1, 0" 0143 0x100 (set t1 (bv 32 0x0)) d "li a2, 0" 0146 0x100 (set a2 (bv 32 0x0)) d "li a0, 0" 0145 0x100 (set a0 (bv 32 0x0)) d "j 0x176" 25a8 0x13e (jmp (bv 32 0x176)) -d "mul a4, a0, a2" 3307c502 0x140 -d "mulhu t1, a2, a2" 3333c602 0x140 +d "mul a4, a0, a2" 3307c502 0x140 (set a4 (* (var a0) (var a2))) +d "mulhu t1, a2, a2" 3333c602 0x140 (set t1 (cast 32 false (>> (* (cast 64 false (var a2)) (cast 64 false (var a2))) (bv 8 0x20) false))) d "slli a4, a4, 1" 0607 0x140 (set a4 (<< (var a4) (bv 32 0x1) false)) -d "mul a7, a5, a6" b3880703 0x140 -d "add t1, t1, a4" 3a93 0x140 -d "mul a3, a2, a2" b306c602 0x140 +d "mul a7, a5, a6" b3880703 0x140 (set a7 (* (var a5) (var a6))) +d "add t1, t1, a4" 3a93 0x140 (set t1 (+ (var t1) (var a4))) +d "mul a3, a2, a2" b306c602 0x140 (set a3 (* (var a2) (var a2))) d "slli a7, a7, 1" 8608 0x140 (set a7 (<< (var a7) (bv 32 0x1) false)) -d "mulhu t3, a6, a6" 333e0803 0x140 -d "mul a4, a6, a6" 33070803 0x140 -d "add t3, t3, a7" 469e 0x140 -d "add t5, t1, t3" 330fc301 0x140 -d "add t4, a3, a4" b38ee600 0x140 -d "sltu a7, t4, a3" b3b8de00 0x140 -d "add a7, a7, t5" fa98 0x140 +d "mulhu t3, a6, a6" 333e0803 0x140 (set t3 (cast 32 false (>> (* (cast 64 false (var a6)) (cast 64 false (var a6))) (bv 8 0x20) false))) +d "mul a4, a6, a6" 33070803 0x140 (set a4 (* (var a6) (var a6))) +d "add t3, t3, a7" 469e 0x140 (set t3 (+ (var t3) (var a7))) +d "add t5, t1, t3" 330fc301 0x140 (set t5 (+ (var t1) (var t3))) +d "add t4, a3, a4" b38ee600 0x140 (set t4 (+ (var a3) (var a4))) +d "sltu a7, t4, a3" b3b8de00 0x140 (set a7 (ite (&& (ule (var t4) (var a3)) (! (== (var t4) (var a3)))) (bv 32 0x1) (bv 32 0x0))) +d "add a7, a7, t5" fa98 0x140 (set a7 (+ (var a7) (var t5))) d "blt s1, a7, 0x2c6" 63cc1415 0x16e (branch (&& (sle (var s1) (var a7)) (! (== (var s1) (var a7)))) (jmp (bv 32 0x2c6)) (jmp (bv 32 0x172))) d "beq a7, s1, 0x2c2" 63889814 0x172 (branch (== (var a7) (var s1)) (jmp (bv 32 0x2c2)) (jmp (bv 32 0x176))) -d "sub a4, a3, a4" 3387e640 0x140 -d "sub t3, t1, t3" 330ec341 0x140 -d "sltu a3, ra, zero" b3b60000 0x140 -d "add a7, a4, s10" b308a701 0x180 -d "sub a3, t3, a3" b306de40 0x180 -d "sltu a4, a7, a4" 33b7e800 0x180 -d "add a3, a3, s5" d696 0x180 -d "add a3, a3, a4" ba96 0x180 -d "mul a5, a5, a2" b387c702 0x180 +d "sub a4, a3, a4" 3387e640 0x140 (set a4 (- (var a3) (var a4))) +d "sub t3, t1, t3" 330ec341 0x140 (set t3 (- (var t1) (var t3))) +d "sltu a3, ra, zero" b3b60000 0x140 (set a3 (ite (&& (ule (var ra) (bv 32 0x0)) (! (== (var ra) (bv 32 0x0)))) (bv 32 0x1) (bv 32 0x0))) +d "add a7, a4, s10" b308a701 0x180 (set a7 (+ (var a4) (var s10))) +d "sub a3, t3, a3" b306de40 0x180 (set a3 (- (var t3) (var a3))) +d "sltu a4, a7, a4" 33b7e800 0x180 (set a4 (ite (&& (ule (var a7) (var a4)) (! (== (var a7) (var a4)))) (bv 32 0x1) (bv 32 0x0))) +d "add a3, a3, s5" d696 0x180 (set a3 (+ (var a3) (var s5))) +d "add a3, a3, a4" ba96 0x180 (set a3 (+ (var a3) (var a4))) +d "mul a5, a5, a2" b387c702 0x180 (set a5 (* (var a5) (var a2))) d "slli t1, a3, 8" 13938600 0x180 (set t1 (<< (var a3) (bv 32 0x8) false)) d "addi a1, a1, 1" 8505 0x180 (set a1 (+ (var a1) (bv 32 0x1))) -d "mul a4, a0, a6" 33070503 0x180 +d "mul a4, a0, a6" 33070503 0x180 (set a4 (* (var a0) (var a6))) d "srai a0, a3, 0x18" 13d58641 0x180 (set a0 (>> (var a3) (bv 32 0x18) (msb (var a3)))) -d "mulhu a3, a6, a2" b336c802 0x180 -d "add a4, a4, a5" 3e97 0x180 -d "mul a6, a6, a2" 3308c802 0x180 -d "add a4, a4, a3" 3697 0x180 +d "mulhu a3, a6, a2" b336c802 0x180 (set a3 (cast 32 false (>> (* (cast 64 false (var a6)) (cast 64 false (var a2))) (bv 8 0x20) false))) +d "add a4, a4, a5" 3e97 0x180 (set a4 (+ (var a4) (var a5))) +d "mul a6, a6, a2" 3308c802 0x180 (set a6 (* (var a6) (var a2))) +d "add a4, a4, a3" 3697 0x180 (set a4 (+ (var a4) (var a3))) d "srli a2, a7, 0x18" 13d68801 0x180 (set a2 (>> (var a7) (bv 32 0x18) false)) d "slli a4, a4, 1" 0607 0x180 (set a4 (<< (var a4) (bv 32 0x1) false)) -d "or a2, t1, a2" 3366c300 0x180 +d "or a2, t1, a2" 3366c300 0x180 (set a2 (| (var t1) (var a2))) d "slli a7, a6, 1" 93181800 0x180 (set a7 (<< (var a6) (bv 32 0x1) false)) d "srli a3, a6, 0x1f" 9356f801 0x180 (set a3 (>> (var a6) (bv 32 0x1f) false)) -d "add a5, a7, t2" b3877800 0x1c0 -d "or a4, a4, a3" 558f 0x1c0 +d "add a5, a7, t2" b3877800 0x1c0 (set a5 (+ (var a7) (var t2))) +d "or a4, a4, a3" 558f 0x1c0 (set a4 (| (var a4) (var a3))) d "srli a6, a5, 0x18" 13d88701 0x1c0 (set a6 (>> (var a5) (bv 32 0x18) false)) -d "add a4, a4, t6" 7e97 0x1c0 -d "sltu a5, a5, a7" b3b71701 0x1c0 -d "add a4, a4, a5" 3e97 0x1c0 +d "add a4, a4, t6" 7e97 0x1c0 (set a4 (+ (var a4) (var t6))) +d "sltu a5, a5, a7" b3b71701 0x1c0 (set a5 (ite (&& (ule (var a5) (var a7)) (! (== (var a5) (var a7)))) (bv 32 0x1) (bv 32 0x0))) +d "add a4, a4, a5" 3e97 0x1c0 (set a4 (+ (var a4) (var a5))) d "slli a5, a4, 8" 93178700 0x1c0 (set a5 (<< (var a4) (bv 32 0x8) false)) -d "or a6, a5, a6" 33e80701 0x1c0 -d "srai a5, a4, 0x18" 93578741 0x1c0 +d "or a6, a5, a6" 33e80701 0x1c0 (set a6 (| (var a5) (var a6))) +d "srai a5, a4, 0x18" 93578741 0x1c0 (set a5 (>> (var a4) (bv 32 0x18) (msb (var a4)))) d "bne a1, s6, 0x140" e39065f7 0x1e0 (branch (! (== (var a1) (var s6))) (jmp (bv 32 0x140)) (jmp (bv 32 0x1e4))) -d "li a5, 0" 8147 0x1c0 -d "add a4, t2, s8" 33878301 0x1c0 -d "sltu a3, a4, t2" b3367700 0x1c0 -d "or s2, a5, s2" 33e92701 0x1c0 -d "add t6, t6, s7" de9f 0x1c0 +d "li a5, 0" 8147 0x1c0 (set a5 (bv 32 0x0)) +d "add a4, t2, s8" 33878301 0x1c0 (set a4 (+ (var t2) (var s8))) +d "sltu a3, a4, t2" b3367700 0x1c0 (set a3 (ite (&& (ule (var a4) (var t2)) (! (== (var a4) (var t2)))) (bv 32 0x1) (bv 32 0x0))) +d "or s2, a5, s2" 33e92701 0x1c0 (set s2 (| (var a5) (var s2))) +d "add t6, t6, s7" de9f 0x1c0 (set t6 (+ (var t6) (var s7))) d "addi ra, ra, 1" 8500 0x1c0 (set ra (+ (var ra) (bv 32 0x1))) d "andi s2, s2, 0xff" 1379f90f 0x1c0 (set s2 (& (var s2) (bv 32 0xff))) -d "mv t2, a4" ba83 0x1c0 -d "add t6, t6, a3" b69f 0x1c0 +d "mv t2, a4" ba83 0x1c0 (set t2 (var a4)) +d "add t6, t6, a3" b69f 0x1c0 (set t6 (+ (var t6) (var a3))) d "ori a5, a5, 0x89" 93e79708 0x0 (set a5 (| (var a5) (bv 32 0x89))) d "xori a5, a5, 0x431" 93c71743 0x0 (set a5 (^ (var a5) (bv 32 0x431))) d "jalr ra" e7800000 0x30 (seq (set ra (bv 32 0x34)) (jmp (& (+ (var ra) (bv 32 0x0)) (bv 32 0xfffffffe)))) From f83db8a75ec67e10d075224d55d94f52812b547b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D9=85=D8=B5=D8=B7=D9=81=D9=8A=20=D9=85=D8=AD=D9=85=D9=88?= =?UTF-8?q?=D8=AF=20=D9=83=D9=85=D8=A7=D9=84=20=D8=A7=D9=84=D8=AF=D9=8A?= =?UTF-8?q?=D9=86?= <48567303+moste00@users.noreply.github.com> Date: Wed, 17 Jun 2026 00:55:02 +0300 Subject: [PATCH 3/8] cut down on macro usage --- librz/arch/isa/riscv/riscv_il_base.h | 149 ++++++++++++++++----------- 1 file changed, 88 insertions(+), 61 deletions(-) diff --git a/librz/arch/isa/riscv/riscv_il_base.h b/librz/arch/isa/riscv/riscv_il_base.h index c52516ed77e..5c31ce4ce80 100644 --- a/librz/arch/isa/riscv/riscv_il_base.h +++ b/librz/arch/isa/riscv/riscv_il_base.h @@ -13,14 +13,19 @@ #include -#define RISCV_GET_REG(reg) (((reg) != RISCV_REG_X0) ? (VARG(riscv_integer_reg_name(reg))) : UN(analysis->bits, 0)) -#define RISCV_SET_REG(reg, r) (((reg) != RISCV_REG_X0) ? (SETG(riscv_integer_reg_name(reg), r)) : ((rz_il_op_pure_free(r), NOP()))) +static inline RzILOpBitVector *riscv_il_get_reg(ut32 bits, uint32_t reg) { + return reg != RISCV_REG_X0 ? VARG(riscv_integer_reg_name(reg)) : UN(bits, 0); +} + +static inline RzILOpEffect *riscv_il_set_reg(uint32_t reg, RZ_OWN RZ_NONNULL RzILOpBitVector *value) { + return reg != RISCV_REG_X0 ? SETG(riscv_integer_reg_name(reg), value) : ((rz_il_op_pure_free(value), NOP())); +} #define DEFINE_LIFTER(name, decoder, result) \ static RzILOpEffect *rz_riscv_lift_##name(RZ_BORROW RZ_NONNULL RzAnalysis *analysis, \ RZ_NONNULL RzAnalysisOp *op, RZ_NONNULL cs_insn *insn, ut64 current_addr, size_t size) { \ decoder(analysis, insn); \ - return RISCV_SET_REG(rd, result); \ + return riscv_il_set_reg(rd, result); \ } // by default, a RISC-V jump both sets a destination and sets the PC (i.e., jumps) @@ -29,7 +34,7 @@ RZ_NONNULL RzAnalysisOp *op, RZ_NONNULL cs_insn *insn, ut64 current_addr, size_t size) { \ decoder(analysis, insn); \ return SEQ2( \ - RISCV_SET_REG(rd, result), \ + riscv_il_set_reg(rd, result), \ jmp_effect); \ } @@ -67,30 +72,62 @@ TWICE_FOR(name3, name4, def_lifter, __VA_ARGS__) #if RZ_CHECKS_LEVEL > 0 +static inline void riscv_il_dump_operands(RZ_NONNULL cs_insn *insn) { + RZ_LOG_ERROR("op_str: %s\n", insn->op_str); + RZ_LOG_ERROR("need_effective_addr: %d\n", insn->detail->riscv.need_effective_addr); + RZ_LOG_ERROR("op_count: %u\n", insn->detail->riscv.op_count); + for (int i = 0; i < insn->detail->riscv.op_count; i++) { + RZ_LOG_ERROR("operands[%d].type: %d\n", i, insn->detail->riscv.operands[i].type); + if (insn->detail->riscv.operands[i].type == RISCV_OP_REG) { + RZ_LOG_ERROR(" REG = %d\n", insn->detail->riscv.operands[i].reg); + } else if (insn->detail->riscv.operands[i].type == RISCV_OP_IMM) { + RZ_LOG_ERROR(" IMM = 0x%" PFMT64x "\n", (ut64)insn->detail->riscv.operands[i].imm); + } else if (insn->detail->riscv.operands[i].type == RISCV_OP_MEM) { + RZ_LOG_ERROR(" MEM base = %d, disp = 0x%" PFMT64x "\n", insn->detail->riscv.operands[i].mem.base, (ut64)insn->detail->riscv.operands[i].mem.disp); + } + } +} + +static inline void riscv_il_log_operand_mismatch(RZ_NONNULL cs_insn *insn, ut64 current_addr, int idx, int type, const char *type_name) { + RZ_LOG_ERROR("[%s (%d) @ 0x%08" PFMT64x "] Expected type %d (%s) at index %d, found type %d instead\n", + insn->mnemonic, insn->id, current_addr, type, type_name, idx, insn->detail->riscv.operands[idx].type); + riscv_il_dump_operands(insn); +} + +static inline bool riscv_il_require_op(RZ_NONNULL cs_insn *insn, ut64 current_addr, int idx, int type, const char *type_name) { + if (insn->detail->riscv.operands[idx].type == type && insn->detail->riscv.operands[idx].type != RISCV_OP_INVALID) { + return true; + } + riscv_il_log_operand_mismatch(insn, current_addr, idx, type, type_name); + return false; +} + +static inline bool riscv_il_require_64_bit(RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL cs_insn *insn) { + if (analysis->bits == 64) { + return true; + } + RZ_LOG_ERROR("[%s (%d)] Expected 64-bit analysis, found %d bits\n", insn->mnemonic, insn->id, analysis->bits); + return false; +} + #define REQUIRE_OP(idx, t) \ - if (insn->detail->riscv.operands[idx].type != (t) || insn->detail->riscv.operands[idx].type == RISCV_OP_INVALID) { \ - RZ_LOG_ERROR("[%s (%d) @ 0x%08" PFMT64x "] Expected type %d (%s) at index %d, found type %d instead\n", insn->mnemonic, insn->id, current_addr, t, #t, idx, insn->detail->riscv.operands[idx].type); \ - RZ_LOG_ERROR("op_str: %s\n", insn->op_str); \ - RZ_LOG_ERROR("need_effective_addr: %d\n", insn->detail->riscv.need_effective_addr); \ - RZ_LOG_ERROR("op_count: %u\n", insn->detail->riscv.op_count); \ - for (int _i = 0; _i < insn->detail->riscv.op_count; _i++) { \ - RZ_LOG_ERROR("operands[%d].type: %d\n", _i, insn->detail->riscv.operands[_i].type); \ - if (insn->detail->riscv.operands[_i].type == RISCV_OP_REG) { \ - RZ_LOG_ERROR(" REG = %d\n", insn->detail->riscv.operands[_i].reg); \ - } else if (insn->detail->riscv.operands[_i].type == RISCV_OP_IMM) { \ - RZ_LOG_ERROR(" IMM = 0x%" PFMT64x "\n", (ut64)insn->detail->riscv.operands[_i].imm); \ - } else if (insn->detail->riscv.operands[_i].type == RISCV_OP_MEM) { \ - RZ_LOG_ERROR(" MEM base = %d, disp = 0x%" PFMT64x "\n", insn->detail->riscv.operands[_i].mem.base, (ut64)insn->detail->riscv.operands[_i].mem.disp); \ - } \ - } \ + if (!riscv_il_require_op(insn, current_addr, idx, t, #t)) { \ return NULL; \ } #define REQUIRE_64_BIT(analysis) \ - if (analysis->bits != 64) { \ - RZ_LOG_ERROR("[%s (%d)] Expected 64-bit analysis, found %d bits\n", insn->mnemonic, insn->id, analysis->bits); \ + if (!riscv_il_require_64_bit(analysis, insn)) { \ return NULL; \ } + +#define REQUIRE_2OPS(t0, t1) \ + REQUIRE_OP(0, t0); \ + REQUIRE_OP(1, t1) + +#define REQUIRE_3OPS(t0, t1, t2) \ + REQUIRE_OP(0, t0); \ + REQUIRE_OP(1, t1); \ + REQUIRE_OP(2, t2) #else #define REQUIRE_OP(idx, t) \ do { \ @@ -98,93 +135,83 @@ #define REQUIRE_64_BIT(analysis) \ do { \ } while (0) +#define REQUIRE_2OPS(t0, t1) \ + do { \ + } while (0) +#define REQUIRE_3OPS(t0, t1, t2) \ + do { \ + } while (0) #endif // Decoders, every instruction defines how its own transformation of capstone operands to IL operands #define DECODE_RD_RS_IMM(analysis, insn) \ - REQUIRE_OP(0, RISCV_OP_REG); \ - REQUIRE_OP(1, RISCV_OP_REG); \ - REQUIRE_OP(2, RISCV_OP_IMM); \ + REQUIRE_3OPS(RISCV_OP_REG, RISCV_OP_REG, RISCV_OP_IMM); \ uint32_t rd = insn->detail->riscv.operands[0].reg; \ - RzILOpBitVector *rs = RISCV_GET_REG(insn->detail->riscv.operands[1].reg); \ + RzILOpBitVector *rs = riscv_il_get_reg(analysis->bits, insn->detail->riscv.operands[1].reg); \ RzILOpBitVector *imm = SN(analysis->bits, insn->detail->riscv.operands[2].imm); #define DECODE_RD_RS_RS(analysis, insn) \ - REQUIRE_OP(0, RISCV_OP_REG); \ - REQUIRE_OP(1, RISCV_OP_REG); \ - REQUIRE_OP(2, RISCV_OP_REG); \ + REQUIRE_3OPS(RISCV_OP_REG, RISCV_OP_REG, RISCV_OP_REG); \ uint32_t rd = insn->detail->riscv.operands[0].reg; \ - RzILOpBitVector *rs1 = RISCV_GET_REG(insn->detail->riscv.operands[1].reg); \ - RzILOpBitVector *rs2 = RISCV_GET_REG(insn->detail->riscv.operands[2].reg); + RzILOpBitVector *rs1 = riscv_il_get_reg(analysis->bits, insn->detail->riscv.operands[1].reg); \ + RzILOpBitVector *rs2 = riscv_il_get_reg(analysis->bits, insn->detail->riscv.operands[2].reg); #define DECODE_RS_IMM(analysis, insn) \ - REQUIRE_OP(0, RISCV_OP_REG); \ - REQUIRE_OP(1, RISCV_OP_IMM); \ - RzILOpBitVector *rs = RISCV_GET_REG(insn->detail->riscv.operands[0].reg); \ + REQUIRE_2OPS(RISCV_OP_REG, RISCV_OP_IMM); \ + RzILOpBitVector *rs = riscv_il_get_reg(analysis->bits, insn->detail->riscv.operands[0].reg); \ RzILOpBitVector *imm = SN(analysis->bits, insn->detail->riscv.operands[1].imm); #define DECODE_RS_RS_IMM(analysis, insn) \ - REQUIRE_OP(0, RISCV_OP_REG); \ - REQUIRE_OP(1, RISCV_OP_REG); \ - REQUIRE_OP(2, RISCV_OP_IMM); \ - RzILOpBitVector *rs1 = RISCV_GET_REG(insn->detail->riscv.operands[0].reg); \ - RzILOpBitVector *rs2 = RISCV_GET_REG(insn->detail->riscv.operands[1].reg); \ + REQUIRE_3OPS(RISCV_OP_REG, RISCV_OP_REG, RISCV_OP_IMM); \ + RzILOpBitVector *rs1 = riscv_il_get_reg(analysis->bits, insn->detail->riscv.operands[0].reg); \ + RzILOpBitVector *rs2 = riscv_il_get_reg(analysis->bits, insn->detail->riscv.operands[1].reg); \ RzILOpBitVector *imm = SN(analysis->bits, insn->detail->riscv.operands[2].imm); #define DECODE_RD_RS(analysis, insn) \ - REQUIRE_OP(0, RISCV_OP_REG); \ - REQUIRE_OP(1, RISCV_OP_REG); \ + REQUIRE_2OPS(RISCV_OP_REG, RISCV_OP_REG); \ uint32_t rd = insn->detail->riscv.operands[0].reg; \ - RzILOpBitVector *rs = RISCV_GET_REG(insn->detail->riscv.operands[1].reg); + RzILOpBitVector *rs = riscv_il_get_reg(analysis->bits, insn->detail->riscv.operands[1].reg); #define DECODE_IMM(analysis, insn) \ REQUIRE_OP(0, RISCV_OP_IMM); \ RzILOpBitVector *imm = SN(analysis->bits, insn->detail->riscv.operands[0].imm); #define DECODE_RD_IMM(analysis, insn) \ - REQUIRE_OP(0, RISCV_OP_REG); \ - REQUIRE_OP(1, RISCV_OP_IMM); \ + REQUIRE_2OPS(RISCV_OP_REG, RISCV_OP_IMM); \ uint32_t rd = insn->detail->riscv.operands[0].reg; \ RzILOpBitVector *imm = SN(analysis->bits, insn->detail->riscv.operands[1].imm); #define DECODE_RS_RS_IMM_MEM(analysis, insn) \ - REQUIRE_OP(0, RISCV_OP_REG); \ - REQUIRE_OP(1, RISCV_OP_MEM); \ - RzILOpBitVector *rs1 = RISCV_GET_REG(insn->detail->riscv.operands[0].reg); \ - RzILOpBitVector *rs2 = RISCV_GET_REG(insn->detail->riscv.operands[1].mem.base); \ + REQUIRE_2OPS(RISCV_OP_REG, RISCV_OP_MEM); \ + RzILOpBitVector *rs1 = riscv_il_get_reg(analysis->bits, insn->detail->riscv.operands[0].reg); \ + RzILOpBitVector *rs2 = riscv_il_get_reg(analysis->bits, insn->detail->riscv.operands[1].mem.base); \ RzILOpBitVector *imm = SN(analysis->bits, insn->detail->riscv.operands[1].mem.disp); #define DECODE_RD_RS_IMM_MEM(analysis, insn) \ - REQUIRE_OP(0, RISCV_OP_REG); \ - REQUIRE_OP(1, RISCV_OP_MEM); \ + REQUIRE_2OPS(RISCV_OP_REG, RISCV_OP_MEM); \ uint32_t rd = insn->detail->riscv.operands[0].reg; \ - RzILOpBitVector *rs = RISCV_GET_REG(insn->detail->riscv.operands[1].mem.base); \ + RzILOpBitVector *rs = riscv_il_get_reg(analysis->bits, insn->detail->riscv.operands[1].mem.base); \ RzILOpBitVector *imm = SN(analysis->bits, insn->detail->riscv.operands[1].mem.disp); // used for *w instructions in RV64 that truncate the operands to 32 bits then does the operation #define DECODE_RD_RS_RS_TRUNCATE32(analysis, insn) \ REQUIRE_64_BIT(analysis); \ - REQUIRE_OP(0, RISCV_OP_REG); \ - REQUIRE_OP(1, RISCV_OP_REG); \ - REQUIRE_OP(2, RISCV_OP_REG); \ + REQUIRE_3OPS(RISCV_OP_REG, RISCV_OP_REG, RISCV_OP_REG); \ uint32_t rd = insn->detail->riscv.operands[0].reg; \ - RzILOpBitVector *rs1 = CAST(32, IL_FALSE, RISCV_GET_REG(insn->detail->riscv.operands[1].reg)); \ - RzILOpBitVector *rs2 = CAST(32, IL_FALSE, RISCV_GET_REG(insn->detail->riscv.operands[2].reg)); + RzILOpBitVector *rs1 = CAST(32, IL_FALSE, riscv_il_get_reg(analysis->bits, insn->detail->riscv.operands[1].reg)); \ + RzILOpBitVector *rs2 = CAST(32, IL_FALSE, riscv_il_get_reg(analysis->bits, insn->detail->riscv.operands[2].reg)); #define DECODE_RD_RS_IMM_TRUNCATE32(analysis, insn) \ REQUIRE_64_BIT(analysis); \ - REQUIRE_OP(0, RISCV_OP_REG); \ - REQUIRE_OP(1, RISCV_OP_REG); \ - REQUIRE_OP(2, RISCV_OP_IMM); \ + REQUIRE_3OPS(RISCV_OP_REG, RISCV_OP_REG, RISCV_OP_IMM); \ uint32_t rd = insn->detail->riscv.operands[0].reg; \ - RzILOpBitVector *rs = CAST(32, IL_FALSE, RISCV_GET_REG(insn->detail->riscv.operands[1].reg)); \ + RzILOpBitVector *rs = CAST(32, IL_FALSE, riscv_il_get_reg(analysis->bits, insn->detail->riscv.operands[1].reg)); \ RzILOpBitVector *imm = SN(32, insn->detail->riscv.operands[2].imm); #define DECODE_RD_IMM_TRUNCATE32(analysis, insn) \ REQUIRE_64_BIT(analysis); \ - REQUIRE_OP(0, RISCV_OP_REG); \ - REQUIRE_OP(1, RISCV_OP_IMM); \ + REQUIRE_2OPS(RISCV_OP_REG, RISCV_OP_IMM); \ uint32_t rd = insn->detail->riscv.operands[0].reg; \ RzILOpBitVector *imm = SN(32, insn->detail->riscv.operands[1].imm); From 3623b68da7a39473e910de89052cf8c21e627927 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D9=85=D8=B5=D8=B7=D9=81=D9=8A=20=D9=85=D8=AD=D9=85=D9=88?= =?UTF-8?q?=D8=AF=20=D9=83=D9=85=D8=A7=D9=84=20=D8=A7=D9=84=D8=AF=D9=8A?= =?UTF-8?q?=D9=86?= <48567303+moste00@users.noreply.github.com> Date: Sat, 20 Jun 2026 22:38:16 +0300 Subject: [PATCH 4/8] fix some tests --- librz/arch/isa/riscv/riscv_il.c | 12 ++++++++---- test/db/cmd/cmd_aL | 2 +- test/db/cmd/cmd_list | 11 ++++++----- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/librz/arch/isa/riscv/riscv_il.c b/librz/arch/isa/riscv/riscv_il.c index 61f99b2fb14..08036b7319f 100644 --- a/librz/arch/isa/riscv/riscv_il.c +++ b/librz/arch/isa/riscv/riscv_il.c @@ -117,15 +117,19 @@ RZ_OWN RZ_IPI RzILOpEffect * rz_riscv_lift_instr(RZ_BORROW RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzAnalysisOp *op, RZ_NONNULL cs_insn *insn, ut64 current_addr, size_t size) { rz_return_val_if_fail(analysis && op && insn, NULL); - if (insn->id > 0 && insn->id < RZ_ARRAY_SIZE(riscv_lifters)) { + if (insn->id == RISCV_INS_INVALID) { + return NULL; + } + if (insn->id >= RISCV_INS_ENDING) { + RZ_LOG_ERROR("Invalid RISC-V instruction id %u (0x%08x)\n", insn->id, rz_read_le32(insn->bytes)); + return NULL; + } + if (insn->id < RZ_ARRAY_SIZE(riscv_lifters)) { RiscvInstructionLifter lifter = riscv_lifters[insn->id]; if (lifter) { return lifter(analysis, op, insn, current_addr, size); - } else { - RZ_LOG_ERROR("No lifter found for instruction %s (id: %d) (0x%08x)", insn->mnemonic, insn->id, rz_read_le32(insn->bytes)); } } - rz_warn_if_reached(); return NULL; } diff --git a/test/db/cmd/cmd_aL b/test/db/cmd/cmd_aL index 891249440f0..eeaac958313 100644 --- a/test/db/cmd/cmd_aL +++ b/test/db/cmd/cmd_aL @@ -48,7 +48,7 @@ _dAeI 32 64 ppc BSD PowerPC Capstone-based disassembler (by pan a____ 32 64 ppc.as LGPL3 as PPC Assembler (use RZ_PPC_AS environment) (by eagleoflqj) _dA__ 32 propeller LGPL3 Parallax Propeller disassembler _dA__ 8 16 pyc LGPL3 Python bytecode (PYC) disassembler -_dA__ 32 64 riscv BSD RISC-V Capstone-based disassembler +_dA_I 32 64 riscv BSD RISC-V Capstone-based disassembler adA__ 32 rl78 LGPL3 Renesas RL78 disassembler (by Bastian Engel) _dA__ 32 rsp LGPL3 Nintendo N64 Reality Signal Processor disassembler _dA__ 32 rx LGPL3 Renesas RX Family disassembler (by Heersin) diff --git a/test/db/cmd/cmd_list b/test/db/cmd/cmd_list index 08a5332423a..2e3689d44df 100644 --- a/test/db/cmd/cmd_list +++ b/test/db/cmd/cmd_list @@ -787,7 +787,7 @@ _dAeI 32 64 ppc BSD PowerPC Capstone-based disassembler (by pan a____ 32 64 ppc.as LGPL3 as PPC Assembler (use RZ_PPC_AS environment) (by eagleoflqj) _dA__ 32 propeller LGPL3 Parallax Propeller disassembler _dA__ 8 16 pyc LGPL3 Python bytecode (PYC) disassembler -_dA__ 32 64 riscv BSD RISC-V Capstone-based disassembler +_dA_I 32 64 riscv BSD RISC-V Capstone-based disassembler adA__ 32 rl78 LGPL3 Renesas RL78 disassembler (by Bastian Engel) _dA__ 32 rsp LGPL3 Nintendo N64 Reality Signal Processor disassembler _dA__ 32 rx LGPL3 Renesas RX Family disassembler (by Heersin) @@ -810,7 +810,7 @@ _dA__ 16 xap PD Cambridge Consultants XAP4 RISC (CSR) disas _dA__ 32 xcore BSD XCore Capstone-based disassembler (by pancake) _dAeI 32 xtensa LGPL3 Tensilica Xtensa Capstone-based disassembler (by billow) adA__ 8 z80 GPL3 Zilog Z80 disassembler (by condret) -["6502":{"bits":"8 16 ","license":"LGPL3","description":"6502/NES/C64/Tamagotchi/T-1000 CPU","features":"_dAeI"},"8051":{"bits":"8 ","license":"PD","description":"Intel 8051 disassembler","features":"adAeI"},"alpha":{"bits":"32 64","license":"LGPL3","description":"DEC Alpha Capstone-based disassembler","features":"_dA__"},"amd29k":{"bits":"32 ","license":"LGPL3","description":"AMD 29k RISC disassembler","features":"_dA__","author":"deroad"},"arc":{"bits":"16 32 ","license":"GPL3","description":"Argonaut RISC Core","features":"_dA__"},"arm":{"bits":"16 32 64","license":"BSD","description":"ARM Capstone-based disassembler","features":"adAeI"},"arm.as":{"bits":"16 32 64","license":"LGPL3","description":"as ARM Assembler (use RZ_ARM32_AS and RZ_ARM64_AS environment)","features":"a____","author":"pancake"},"avr":{"bits":"8 16 ","license":"LGPL3","description":"Atmel AVR disassembler","features":"adAeI"},"bf":{"bits":"16 32 64","license":"LGPL3","description":"Brainfuck","features":"adA_I","author":"pancake, nibble","version":"4.0.0"},"c166":{"bits":"16 ","license":"LGPL3","description":"Siemens/Infineon C166 microcontroller disassembler","features":"_dA__"},"cbpf":{"bits":"32 ","license":"LGPL3","description":"CBPF disassembly plugin","features":"_dA__"},"chip8":{"bits":"32 ","license":"LGPL3","description":"Chip8 disassembler","features":"_dA__"},"cil":{"bits":"16 32 64","license":"LGPL3","description":".NET CIL/MSIL (Common Intermediate Language) bytecode disassembler","features":"_dA__"},"cr16":{"bits":"16 ","license":"LGPL3","description":"CompactRISC CR16 disassembler","features":"_dA__"},"cris":{"bits":"32 ","license":"GPL3","description":"Axis Communications 32-bit embedded processor disassembler","features":"_dA__","author":"pancake"},"dalvik":{"bits":"32 64","license":"LGPL3","description":"Dalvik (Android VM) bytecode disassembler","features":"adA__"},"dcpu16":{"bits":"16 ","license":"PD","description":"Mojang's DCPU-16 disassembler","features":"ad___"},"ebc":{"bits":"32 64","license":"LGPL3","description":"EFI bytecode disassembler","features":"_dA__","author":"Fedor Sakharov"},"gb":{"bits":"16 ","license":"LGPL3","description":"GameBoy(TM) (z80-like)","features":"adAeI","author":"condret"},"h8300":{"bits":"16 ","license":"LGPL3","description":"Hitachi/Renesas H8/300 disassembly plugin","features":"_dAeI"},"h8500":{"bits":"16 ","license":"LGPL3","description":"Hitachi/Renesas H8/500 disassembler","features":"_dA__","author":"billow"},"hexagon":{"bits":"32 ","license":"LGPL3","description":"Qualcomm Hexagon (QDSP6) V6","features":"_dA_I","author":"Rot127"},"hppa":{"bits":"32 64","license":"LGPL3","description":"HP PA-RISC Capstone-based disassembler","features":"_dA__","author":"xvilka"},"i4004":{"bits":"4 ","license":"LGPL3","description":"Intel 4004 disassembler","features":"_dA__"},"i8080":{"bits":"8 ","license":"BSD","description":"Intel 8080 disassembler","features":"_dA__"},"java":{"bits":"32 ","license":"LGPL-3","description":"Java bytecode disassembler","features":"adA__","author":"deroad"},"lanai":{"bits":"32 ","license":"GPL3","description":"Google LANAI disassembler","features":"_d___"},"lh5801":{"bits":"8 ","license":"LGPL3","description":"SHARP LH5801 disassembler","features":"_d___"},"lm32":{"bits":"32 ","license":"BSD","description":"Lattice Micro 32 ISA disassembler","features":"_d___","author":"Felix Held"},"loongarch":{"bits":"32 64","license":"LGPL3","description":"Loongson LoongArch disassembler","features":"_dA__"},"luac":{"bits":"32 ","license":"LGPL3","description":"Lua bytecode (LUAC) disassembler","features":"adA__"},"m680x":{"bits":"8 32 ","license":"BSD","description":"Motorola 680X Capstone-based disassembler","features":"_dA__"},"m68k":{"bits":"32 ","license":"BSD","description":"Motorola 68K Capstone-based disassembler","features":"_dA__"},"malbolge":{"bits":"32 ","license":"LGPL3","description":"Malbolge Ternary VM bytecode disassembler","features":"_dA__","author":"condret"},"mcore":{"bits":"32 ","license":"LGPL3","description":"Motorola MCORE disassembler","features":"_dA__"},"mcs96":{"bits":"16 ","license":"LGPL3","description":"Intel MCS-96 disassembler","features":"_dA__","author":"condret"},"milstd1750":{"bits":"8 ","license":"MIT","description":"MIL-STD 1750 ISA disassembler","features":"_dA__"},"mips":{"bits":"16 32 64","license":"BSD","description":"MIPS Capstone-based disassembler","features":"adAeI"},"msp430":{"bits":"16 ","license":"LGPL3","description":"Texas Instruments MSP430 disassembler","features":"_dA_I"},"null":{"bits":"16 32 64","license":"MIT","description":"NULL (empty) disassembler","features":"adA__","author":"pancake","version":"1.0.0"},"or1k":{"bits":"32 ","license":"LGPL3","description":"OpenRISC 1000 disassembler","features":"_dA__"},"pic":{"bits":"16 32 ","license":"LGPL3","description":"Microchip PIC disassembler","features":"_dAeI"},"ppc":{"bits":"32 64","license":"BSD","description":"PowerPC Capstone-based disassembler","features":"_dAeI","author":"pancake"},"ppc.as":{"bits":"32 64","license":"LGPL3","description":"as PPC Assembler (use RZ_PPC_AS environment)","features":"a____","author":"eagleoflqj"},"propeller":{"bits":"32 ","license":"LGPL3","description":"Parallax Propeller disassembler","features":"_dA__"},"pyc":{"bits":"8 16 ","license":"LGPL3","description":"Python bytecode (PYC) disassembler","features":"_dA__"},"riscv":{"bits":"32 64","license":"BSD","description":"RISC-V Capstone-based disassembler","features":"_dA__"},"rl78":{"bits":"32 ","license":"LGPL3","description":"Renesas RL78 disassembler","features":"adA__","author":"Bastian Engel"},"rsp":{"bits":"32 ","license":"LGPL3","description":"Nintendo N64 Reality Signal Processor disassembler","features":"_dA__"},"rx":{"bits":"32 ","license":"LGPL3","description":"Renesas RX Family disassembler","features":"_dA__","author":"Heersin"},"sh":{"bits":"32 ","license":"LGPL3","description":"Hitachi/Renesas SuperH-4/SuperH-3 disassembler","features":"adAeI","author":"DMaroo"},"snes":{"bits":"8 16 ","license":"LGPL3","description":"SuperNES CPU disassembler","features":"_dA__"},"sparc":{"bits":"32 64","license":"BSD","description":"Sun SPARC Capstone-based disassembler","features":"_dA_I"},"spc700":{"bits":"16 ","license":"LGPL3","description":"Sony SPC700 (Nintendo SuperNES sound-chip) disassembler","features":"_dA__"},"sysz":{"bits":"32 64","license":"BSD","description":"IBM SystemZ (S/390) Capstone-based disassembler","features":"_dA__"},"tms320":{"bits":"32 ","license":"LGPL3","description":"Texas Instruments TMS320 DSP family (c54x,c55x,c55x+,c64x) disassembler","features":"_dA_I"},"tricore":{"bits":"32 ","license":"BSD","description":"Siemens TriCore Capstone-based disassembler","features":"_dA_I","author":"billow"},"v810":{"bits":"32 ","license":"LGPL3","description":"NEC V810 disassembler","features":"_dAeI","author":"pancake"},"v850":{"bits":"32 ","license":"LGPL3","description":"NEC/Renesas V850 disassembler","features":"_dAeI"},"vax":{"bits":"32 ","license":"LGPL3","description":"DEC VAX-11 disassembler","features":"_dA__","author":"xvilka"},"wasm":{"bits":"32 ","license":"MIT","description":"WebAssembly disassembler","features":"adA__","author":"cgvwzq","version":"0.1.0"},"x86":{"bits":"16 32 64","license":"MIT","description":"X86/X86_64 Zydis-based disassembler","features":"_dAeI"},"x86.as":{"bits":"16 32 64","license":"LGPL3","description":"Intel X86 GNU Assembler (Use RZ_X86_AS env)","features":"a____"},"x86.nasm":{"bits":"16 32 64","license":"LGPL3","description":"X86 nasm assembler","features":"a____"},"x86.nz":{"bits":"16 32 64","license":"LGPL3","description":"x86 handmade assembler","features":"a____"},"xap":{"bits":"16 ","license":"PD","description":"Cambridge Consultants XAP4 RISC (CSR) disassembler","features":"_dA__"},"xcore":{"bits":"32 ","license":"BSD","description":"XCore Capstone-based disassembler","features":"_dA__","author":"pancake"},"xtensa":{"bits":"32 ","license":"LGPL3","description":"Tensilica Xtensa Capstone-based disassembler","features":"_dAeI","author":"billow"},"z80":{"bits":"8 ","license":"GPL3","description":"Zilog Z80 disassembler","features":"adA__","author":"condret"}] +["6502":{"bits":"8 16 ","license":"LGPL3","description":"6502/NES/C64/Tamagotchi/T-1000 CPU","features":"_dAeI"},"8051":{"bits":"8 ","license":"PD","description":"Intel 8051 disassembler","features":"adAeI"},"alpha":{"bits":"32 64","license":"LGPL3","description":"DEC Alpha Capstone-based disassembler","features":"_dA__"},"amd29k":{"bits":"32 ","license":"LGPL3","description":"AMD 29k RISC disassembler","features":"_dA__","author":"deroad"},"arc":{"bits":"16 32 ","license":"GPL3","description":"Argonaut RISC Core","features":"_dA__"},"arm":{"bits":"16 32 64","license":"BSD","description":"ARM Capstone-based disassembler","features":"adAeI"},"arm.as":{"bits":"16 32 64","license":"LGPL3","description":"as ARM Assembler (use RZ_ARM32_AS and RZ_ARM64_AS environment)","features":"a____","author":"pancake"},"avr":{"bits":"8 16 ","license":"LGPL3","description":"Atmel AVR disassembler","features":"adAeI"},"bf":{"bits":"16 32 64","license":"LGPL3","description":"Brainfuck","features":"adA_I","author":"pancake, nibble","version":"4.0.0"},"c166":{"bits":"16 ","license":"LGPL3","description":"Siemens/Infineon C166 microcontroller disassembler","features":"_dA__"},"cbpf":{"bits":"32 ","license":"LGPL3","description":"CBPF disassembly plugin","features":"_dA__"},"chip8":{"bits":"32 ","license":"LGPL3","description":"Chip8 disassembler","features":"_dA__"},"cil":{"bits":"16 32 64","license":"LGPL3","description":".NET CIL/MSIL (Common Intermediate Language) bytecode disassembler","features":"_dA__"},"cr16":{"bits":"16 ","license":"LGPL3","description":"CompactRISC CR16 disassembler","features":"_dA__"},"cris":{"bits":"32 ","license":"GPL3","description":"Axis Communications 32-bit embedded processor disassembler","features":"_dA__","author":"pancake"},"dalvik":{"bits":"32 64","license":"LGPL3","description":"Dalvik (Android VM) bytecode disassembler","features":"adA__"},"dcpu16":{"bits":"16 ","license":"PD","description":"Mojang's DCPU-16 disassembler","features":"ad___"},"ebc":{"bits":"32 64","license":"LGPL3","description":"EFI bytecode disassembler","features":"_dA__","author":"Fedor Sakharov"},"gb":{"bits":"16 ","license":"LGPL3","description":"GameBoy(TM) (z80-like)","features":"adAeI","author":"condret"},"h8300":{"bits":"16 ","license":"LGPL3","description":"Hitachi/Renesas H8/300 disassembly plugin","features":"_dAeI"},"h8500":{"bits":"16 ","license":"LGPL3","description":"Hitachi/Renesas H8/500 disassembler","features":"_dA__","author":"billow"},"hexagon":{"bits":"32 ","license":"LGPL3","description":"Qualcomm Hexagon (QDSP6) V6","features":"_dA_I","author":"Rot127"},"hppa":{"bits":"32 64","license":"LGPL3","description":"HP PA-RISC Capstone-based disassembler","features":"_dA__","author":"xvilka"},"i4004":{"bits":"4 ","license":"LGPL3","description":"Intel 4004 disassembler","features":"_dA__"},"i8080":{"bits":"8 ","license":"BSD","description":"Intel 8080 disassembler","features":"_dA__"},"java":{"bits":"32 ","license":"LGPL-3","description":"Java bytecode disassembler","features":"adA__","author":"deroad"},"lanai":{"bits":"32 ","license":"GPL3","description":"Google LANAI disassembler","features":"_d___"},"lh5801":{"bits":"8 ","license":"LGPL3","description":"SHARP LH5801 disassembler","features":"_d___"},"lm32":{"bits":"32 ","license":"BSD","description":"Lattice Micro 32 ISA disassembler","features":"_d___","author":"Felix Held"},"loongarch":{"bits":"32 64","license":"LGPL3","description":"Loongson LoongArch disassembler","features":"_dA__"},"luac":{"bits":"32 ","license":"LGPL3","description":"Lua bytecode (LUAC) disassembler","features":"adA__"},"m680x":{"bits":"8 32 ","license":"BSD","description":"Motorola 680X Capstone-based disassembler","features":"_dA__"},"m68k":{"bits":"32 ","license":"BSD","description":"Motorola 68K Capstone-based disassembler","features":"_dA__"},"malbolge":{"bits":"32 ","license":"LGPL3","description":"Malbolge Ternary VM bytecode disassembler","features":"_dA__","author":"condret"},"mcore":{"bits":"32 ","license":"LGPL3","description":"Motorola MCORE disassembler","features":"_dA__"},"mcs96":{"bits":"16 ","license":"LGPL3","description":"Intel MCS-96 disassembler","features":"_dA__","author":"condret"},"milstd1750":{"bits":"8 ","license":"MIT","description":"MIL-STD 1750 ISA disassembler","features":"_dA__"},"mips":{"bits":"16 32 64","license":"BSD","description":"MIPS Capstone-based disassembler","features":"adAeI"},"msp430":{"bits":"16 ","license":"LGPL3","description":"Texas Instruments MSP430 disassembler","features":"_dA_I"},"null":{"bits":"16 32 64","license":"MIT","description":"NULL (empty) disassembler","features":"adA__","author":"pancake","version":"1.0.0"},"or1k":{"bits":"32 ","license":"LGPL3","description":"OpenRISC 1000 disassembler","features":"_dA__"},"pic":{"bits":"16 32 ","license":"LGPL3","description":"Microchip PIC disassembler","features":"_dAeI"},"ppc":{"bits":"32 64","license":"BSD","description":"PowerPC Capstone-based disassembler","features":"_dAeI","author":"pancake"},"ppc.as":{"bits":"32 64","license":"LGPL3","description":"as PPC Assembler (use RZ_PPC_AS environment)","features":"a____","author":"eagleoflqj"},"propeller":{"bits":"32 ","license":"LGPL3","description":"Parallax Propeller disassembler","features":"_dA__"},"pyc":{"bits":"8 16 ","license":"LGPL3","description":"Python bytecode (PYC) disassembler","features":"_dA__"},"riscv":{"bits":"32 64","license":"BSD","description":"RISC-V Capstone-based disassembler","features":"_dA_I"},"rl78":{"bits":"32 ","license":"LGPL3","description":"Renesas RL78 disassembler","features":"adA__","author":"Bastian Engel"},"rsp":{"bits":"32 ","license":"LGPL3","description":"Nintendo N64 Reality Signal Processor disassembler","features":"_dA__"},"rx":{"bits":"32 ","license":"LGPL3","description":"Renesas RX Family disassembler","features":"_dA__","author":"Heersin"},"sh":{"bits":"32 ","license":"LGPL3","description":"Hitachi/Renesas SuperH-4/SuperH-3 disassembler","features":"adAeI","author":"DMaroo"},"snes":{"bits":"8 16 ","license":"LGPL3","description":"SuperNES CPU disassembler","features":"_dA__"},"sparc":{"bits":"32 64","license":"BSD","description":"Sun SPARC Capstone-based disassembler","features":"_dA_I"},"spc700":{"bits":"16 ","license":"LGPL3","description":"Sony SPC700 (Nintendo SuperNES sound-chip) disassembler","features":"_dA__"},"sysz":{"bits":"32 64","license":"BSD","description":"IBM SystemZ (S/390) Capstone-based disassembler","features":"_dA__"},"tms320":{"bits":"32 ","license":"LGPL3","description":"Texas Instruments TMS320 DSP family (c54x,c55x,c55x+,c64x) disassembler","features":"_dA_I"},"tricore":{"bits":"32 ","license":"BSD","description":"Siemens TriCore Capstone-based disassembler","features":"_dA_I","author":"billow"},"v810":{"bits":"32 ","license":"LGPL3","description":"NEC V810 disassembler","features":"_dAeI","author":"pancake"},"v850":{"bits":"32 ","license":"LGPL3","description":"NEC/Renesas V850 disassembler","features":"_dAeI"},"vax":{"bits":"32 ","license":"LGPL3","description":"DEC VAX-11 disassembler","features":"_dA__","author":"xvilka"},"wasm":{"bits":"32 ","license":"MIT","description":"WebAssembly disassembler","features":"adA__","author":"cgvwzq","version":"0.1.0"},"x86":{"bits":"16 32 64","license":"MIT","description":"X86/X86_64 Zydis-based disassembler","features":"_dAeI"},"x86.as":{"bits":"16 32 64","license":"LGPL3","description":"Intel X86 GNU Assembler (Use RZ_X86_AS env)","features":"a____"},"x86.nasm":{"bits":"16 32 64","license":"LGPL3","description":"X86 nasm assembler","features":"a____"},"x86.nz":{"bits":"16 32 64","license":"LGPL3","description":"x86 handmade assembler","features":"a____"},"xap":{"bits":"16 ","license":"PD","description":"Cambridge Consultants XAP4 RISC (CSR) disassembler","features":"_dA__"},"xcore":{"bits":"32 ","license":"BSD","description":"XCore Capstone-based disassembler","features":"_dA__","author":"pancake"},"xtensa":{"bits":"32 ","license":"LGPL3","description":"Tensilica Xtensa Capstone-based disassembler","features":"_dAeI","author":"billow"},"z80":{"bits":"8 ","license":"GPL3","description":"Zilog Z80 disassembler","features":"adA__","author":"condret"}] name bits features license version author description ---------------------------------------------------------------------------------------------------------------------------------- _dAeI 8 16 6502 LGPL3 6502/NES/C64/Tamagotchi/T-1000 CPU @@ -859,7 +859,7 @@ _dAeI 32 64 ppc BSD pancake PowerPC Capstone-based a____ 32 64 ppc.as LGPL3 eagleoflqj as PPC Assembler (use RZ_PPC_AS environment) _dA__ 32 propeller LGPL3 Parallax Propeller disassembler _dA__ 8 16 pyc LGPL3 Python bytecode (PYC) disassembler -_dA__ 32 64 riscv BSD RISC-V Capstone-based disassembler +_dA_I 32 64 riscv BSD RISC-V Capstone-based disassembler adA__ 32 rl78 LGPL3 Bastian Engel Renesas RL78 disassembler _dA__ 32 rsp LGPL3 Nintendo N64 Reality Signal Processor disassembler _dA__ 32 rx LGPL3 Heersin Renesas RX Family disassembler @@ -994,6 +994,7 @@ adAeI 16 32 64 mips BSD MIPS Capstone-based disassembler _dA_I 16 msp430 LGPL3 Texas Instruments MSP430 disassembler _dAeI 16 32 pic LGPL3 Microchip PIC disassembler _dAeI 32 64 ppc BSD PowerPC Capstone-based disassembler (by pancake) +_dA_I 32 64 riscv BSD RISC-V Capstone-based disassembler adAeI 32 sh LGPL3 Hitachi/Renesas SuperH-4/SuperH-3 disassembler (by DMaroo) _dA_I 32 64 sparc BSD Sun SPARC Capstone-based disassembler _dA_I 32 tms320 LGPL3 Texas Instruments TMS320 DSP family (c54x,c55x,c55x+,c64x) disassembler @@ -1124,7 +1125,7 @@ a____ 16 32 64 x86.as LGPL3 Intel X86 GNU Assembler (Use RZ_X86_AS env) a____ 16 32 64 x86.nasm LGPL3 X86 nasm assembler a____ 16 32 64 x86.nz LGPL3 x86 handmade assembler adA__ 8 z80 GPL3 Zilog Z80 disassembler (by condret) -["6502":{"bits":"8 16 ","license":"LGPL3","description":"6502/NES/C64/Tamagotchi/T-1000 CPU","features":"_dAeI"},"8051":{"bits":"8 ","license":"PD","description":"Intel 8051 disassembler","features":"adAeI"},"arm":{"bits":"16 32 64","license":"BSD","description":"ARM Capstone-based disassembler","features":"adAeI"},"avr":{"bits":"8 16 ","license":"LGPL3","description":"Atmel AVR disassembler","features":"adAeI"},"bf":{"bits":"16 32 64","license":"LGPL3","description":"Brainfuck","features":"adA_I","author":"pancake, nibble","version":"4.0.0"},"gb":{"bits":"16 ","license":"LGPL3","description":"GameBoy(TM) (z80-like)","features":"adAeI","author":"condret"},"h8300":{"bits":"16 ","license":"LGPL3","description":"Hitachi/Renesas H8/300 disassembly plugin","features":"_dAeI"},"hexagon":{"bits":"32 ","license":"LGPL3","description":"Qualcomm Hexagon (QDSP6) V6","features":"_dA_I","author":"Rot127"},"mips":{"bits":"16 32 64","license":"BSD","description":"MIPS Capstone-based disassembler","features":"adAeI"},"msp430":{"bits":"16 ","license":"LGPL3","description":"Texas Instruments MSP430 disassembler","features":"_dA_I"},"pic":{"bits":"16 32 ","license":"LGPL3","description":"Microchip PIC disassembler","features":"_dAeI"},"ppc":{"bits":"32 64","license":"BSD","description":"PowerPC Capstone-based disassembler","features":"_dAeI","author":"pancake"},"sh":{"bits":"32 ","license":"LGPL3","description":"Hitachi/Renesas SuperH-4/SuperH-3 disassembler","features":"adAeI","author":"DMaroo"},"sparc":{"bits":"32 64","license":"BSD","description":"Sun SPARC Capstone-based disassembler","features":"_dA_I"},"tms320":{"bits":"32 ","license":"LGPL3","description":"Texas Instruments TMS320 DSP family (c54x,c55x,c55x+,c64x) disassembler","features":"_dA_I"},"tricore":{"bits":"32 ","license":"BSD","description":"Siemens TriCore Capstone-based disassembler","features":"_dA_I","author":"billow"},"v810":{"bits":"32 ","license":"LGPL3","description":"NEC V810 disassembler","features":"_dAeI","author":"pancake"},"v850":{"bits":"32 ","license":"LGPL3","description":"NEC/Renesas V850 disassembler","features":"_dAeI"},"x86":{"bits":"16 32 64","license":"MIT","description":"X86/X86_64 Zydis-based disassembler","features":"_dAeI"},"xtensa":{"bits":"32 ","license":"LGPL3","description":"Tensilica Xtensa Capstone-based disassembler","features":"_dAeI","author":"billow"}] +["6502":{"bits":"8 16 ","license":"LGPL3","description":"6502/NES/C64/Tamagotchi/T-1000 CPU","features":"_dAeI"},"8051":{"bits":"8 ","license":"PD","description":"Intel 8051 disassembler","features":"adAeI"},"arm":{"bits":"16 32 64","license":"BSD","description":"ARM Capstone-based disassembler","features":"adAeI"},"avr":{"bits":"8 16 ","license":"LGPL3","description":"Atmel AVR disassembler","features":"adAeI"},"bf":{"bits":"16 32 64","license":"LGPL3","description":"Brainfuck","features":"adA_I","author":"pancake, nibble","version":"4.0.0"},"gb":{"bits":"16 ","license":"LGPL3","description":"GameBoy(TM) (z80-like)","features":"adAeI","author":"condret"},"h8300":{"bits":"16 ","license":"LGPL3","description":"Hitachi/Renesas H8/300 disassembly plugin","features":"_dAeI"},"hexagon":{"bits":"32 ","license":"LGPL3","description":"Qualcomm Hexagon (QDSP6) V6","features":"_dA_I","author":"Rot127"},"mips":{"bits":"16 32 64","license":"BSD","description":"MIPS Capstone-based disassembler","features":"adAeI"},"msp430":{"bits":"16 ","license":"LGPL3","description":"Texas Instruments MSP430 disassembler","features":"_dA_I"},"pic":{"bits":"16 32 ","license":"LGPL3","description":"Microchip PIC disassembler","features":"_dAeI"},"ppc":{"bits":"32 64","license":"BSD","description":"PowerPC Capstone-based disassembler","features":"_dAeI","author":"pancake"},"riscv":{"bits":"32 64","license":"BSD","description":"RISC-V Capstone-based disassembler","features":"_dA_I"},"sh":{"bits":"32 ","license":"LGPL3","description":"Hitachi/Renesas SuperH-4/SuperH-3 disassembler","features":"adAeI","author":"DMaroo"},"sparc":{"bits":"32 64","license":"BSD","description":"Sun SPARC Capstone-based disassembler","features":"_dA_I"},"tms320":{"bits":"32 ","license":"LGPL3","description":"Texas Instruments TMS320 DSP family (c54x,c55x,c55x+,c64x) disassembler","features":"_dA_I"},"tricore":{"bits":"32 ","license":"BSD","description":"Siemens TriCore Capstone-based disassembler","features":"_dA_I","author":"billow"},"v810":{"bits":"32 ","license":"LGPL3","description":"NEC V810 disassembler","features":"_dAeI","author":"pancake"},"v850":{"bits":"32 ","license":"LGPL3","description":"NEC/Renesas V850 disassembler","features":"_dAeI"},"x86":{"bits":"16 32 64","license":"MIT","description":"X86/X86_64 Zydis-based disassembler","features":"_dAeI"},"xtensa":{"bits":"32 ","license":"LGPL3","description":"Tensilica Xtensa Capstone-based disassembler","features":"_dAeI","author":"billow"}] name bits features license version author description ----------------------------------------------------------------------------------------------- _dAeI 8 16 6502 LGPL3 6502/NES/C64/Tamagotchi/T-1000 CPU @@ -1162,7 +1163,7 @@ NAME=Print the asm/analysis plugins in JSON FILE== CMDS=Laj EXPECT=< Date: Wed, 24 Jun 2026 02:16:55 +0300 Subject: [PATCH 5/8] address review --- librz/arch/isa/riscv/riscv_il.c | 35 +++- librz/arch/isa/riscv/riscv_il_base.h | 27 ++- librz/arch/isa/riscv/riscv_il_compressed.c | 73 ++++++++ librz/arch/isa/riscv/riscv_il_compressed.h | 105 +++++------ librz/arch/isa/riscv/riscv_il_integer.c | 102 +++++++++++ librz/arch/isa/riscv/riscv_il_integer.h | 165 ++++++++---------- .../isa/riscv/riscv_il_integer_reg_names.h | 3 +- librz/arch/isa/riscv/riscv_il_m.c | 31 ++++ librz/arch/isa/riscv/riscv_il_m.h | 28 +-- librz/arch/meson.build | 3 + 10 files changed, 382 insertions(+), 190 deletions(-) create mode 100644 librz/arch/isa/riscv/riscv_il_compressed.c create mode 100644 librz/arch/isa/riscv/riscv_il_integer.c create mode 100644 librz/arch/isa/riscv/riscv_il_m.c diff --git a/librz/arch/isa/riscv/riscv_il.c b/librz/arch/isa/riscv/riscv_il.c index 08036b7319f..35ff0001cc5 100644 --- a/librz/arch/isa/riscv/riscv_il.c +++ b/librz/arch/isa/riscv/riscv_il.c @@ -2,6 +2,8 @@ // SPDX-License-Identifier: BSD-3-Clause #include "riscv_il.h" +#include "analysis_private.h" +#include "riscv_il_base.h" #include "riscv_il_integer.h" #include "riscv_il_m.h" #include "riscv_il_compressed.h" @@ -10,6 +12,10 @@ static void label_ecall(RzILVM *vm, RzILOpEffect *op) { // stub: ecall is handled at the analysis layer } +static void label_ebreak(RzILVM *vm, RzILOpEffect *op) { + // stub: ebreak is handled at the analysis layer +} + static const RiscvInstructionLifter riscv_lifters[] = { /* ---------------------------------- Integer ---------------------------------*/ // arithmetic, immediate @@ -71,15 +77,25 @@ static const RiscvInstructionLifter riscv_lifters[] = { USE_LIFTER(fence_i, FENCE_I), // system USE_LIFTER(ecall, ECALL), + USE_LIFTER(ebreak, EBREAK), // RV64I extra loads USE_LIFTER(lwu, LWU), // M extension USE_LIFTER(mul, MUL), + USE_LIFTER(mulh, MULH), + USE_LIFTER(mulhsu, MULHSU), USE_LIFTER(mulhu, MULHU), + USE_LIFTER(div, DIV), USE_LIFTER(divu, DIVU), + USE_LIFTER(rem, REM), USE_LIFTER(remu, REMU), + USE_LIFTER(mulw, MULW), + USE_LIFTER(divw, DIVW), + USE_LIFTER(divuw, DIVUW), + USE_LIFTER(remw, REMW), USE_LIFTER(remuw, REMUW), /* ---------------------------------- Compressed ---------------------------------*/ + USE_LIFTER(c_nop, C_NOP), USE_LIFTER(c_addi, C_ADDI), USE_LIFTER(c_addi16sp, C_ADDI16SP), USE_LIFTER(c_addi4spn, C_ADDI4SPN), @@ -90,6 +106,7 @@ static const RiscvInstructionLifter riscv_lifters[] = { USE_LIFTER(c_srai, C_SRAI), USE_LIFTER(c_jr, C_JR), USE_LIFTER(c_jalr, C_JALR), + USE_LIFTER(c_ebreak, C_EBREAK), USE_LIFTER(c_lwsp, C_LWSP), USE_LIFTER(c_lw, C_LW), USE_LIFTER(c_ld, C_LD), @@ -102,6 +119,7 @@ static const RiscvInstructionLifter riscv_lifters[] = { USE_LIFTER(c_sd, C_SD), USE_LIFTER(c_mv, C_MV), USE_LIFTER(c_j, C_J), + USE_LIFTER(c_jal, C_JAL), USE_LIFTER(c_or, C_OR), USE_LIFTER(c_ldsp, C_LDSP), USE_LIFTER(c_sdsp, C_SDSP), @@ -124,13 +142,14 @@ rz_riscv_lift_instr(RZ_BORROW RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzAnal RZ_LOG_ERROR("Invalid RISC-V instruction id %u (0x%08x)\n", insn->id, rz_read_le32(insn->bytes)); return NULL; } - if (insn->id < RZ_ARRAY_SIZE(riscv_lifters)) { - RiscvInstructionLifter lifter = riscv_lifters[insn->id]; - if (lifter) { - return lifter(analysis, op, insn, current_addr, size); - } + if (insn->id >= RZ_ARRAY_SIZE(riscv_lifters)) { + return NULL; + } + RiscvInstructionLifter lifter = riscv_lifters[insn->id]; + if (!lifter) { + return NULL; } - return NULL; + return lifter(analysis, op, insn, current_addr, size); } RZ_IPI RzAnalysisILConfig *rz_riscv_il_config(RZ_NONNULL RzAnalysis *analysis) { @@ -142,5 +161,9 @@ RZ_IPI RzAnalysisILConfig *rz_riscv_il_config(RZ_NONNULL RzAnalysis *analysis) { ecall_label->hook = label_ecall; rz_analysis_il_config_add_label(conf, ecall_label); + RzILEffectLabel *ebreak_label = rz_il_effect_label_new("ebreak", EFFECT_LABEL_SYSCALL); + ebreak_label->hook = label_ebreak; + rz_analysis_il_config_add_label(conf, ebreak_label); + return conf; } \ No newline at end of file diff --git a/librz/arch/isa/riscv/riscv_il_base.h b/librz/arch/isa/riscv/riscv_il_base.h index 5c31ce4ce80..86c0ee3d78c 100644 --- a/librz/arch/isa/riscv/riscv_il_base.h +++ b/librz/arch/isa/riscv/riscv_il_base.h @@ -18,11 +18,16 @@ static inline RzILOpBitVector *riscv_il_get_reg(ut32 bits, uint32_t reg) { } static inline RzILOpEffect *riscv_il_set_reg(uint32_t reg, RZ_OWN RZ_NONNULL RzILOpBitVector *value) { - return reg != RISCV_REG_X0 ? SETG(riscv_integer_reg_name(reg), value) : ((rz_il_op_pure_free(value), NOP())); + if (reg != RISCV_REG_X0) { + return SETG(riscv_integer_reg_name(reg), value); + } + // assigning to x0 is a no-op, so the value will never be referenced in the IL tree + rz_il_op_pure_free(value); + return NOP(); } #define DEFINE_LIFTER(name, decoder, result) \ - static RzILOpEffect *rz_riscv_lift_##name(RZ_BORROW RZ_NONNULL RzAnalysis *analysis, \ + RzILOpEffect *rz_riscv_lift_##name(RZ_BORROW RZ_NONNULL RzAnalysis *analysis, \ RZ_NONNULL RzAnalysisOp *op, RZ_NONNULL cs_insn *insn, ut64 current_addr, size_t size) { \ decoder(analysis, insn); \ return riscv_il_set_reg(rd, result); \ @@ -30,7 +35,7 @@ static inline RzILOpEffect *riscv_il_set_reg(uint32_t reg, RZ_OWN RZ_NONNULL RzI // by default, a RISC-V jump both sets a destination and sets the PC (i.e., jumps) #define DEFINE_LIFTER_FOR_JUMP(name, decoder, result, jmp_effect) \ - static RzILOpEffect *rz_riscv_lift_##name(RZ_BORROW RZ_NONNULL RzAnalysis *analysis, \ + RzILOpEffect *rz_riscv_lift_##name(RZ_BORROW RZ_NONNULL RzAnalysis *analysis, \ RZ_NONNULL RzAnalysisOp *op, RZ_NONNULL cs_insn *insn, ut64 current_addr, size_t size) { \ decoder(analysis, insn); \ return SEQ2( \ @@ -39,7 +44,7 @@ static inline RzILOpEffect *riscv_il_set_reg(uint32_t reg, RZ_OWN RZ_NONNULL RzI } #define DEFINE_LIFTER_WITH_EFFECT(name, decoder, effect) \ - static RzILOpEffect *rz_riscv_lift_##name(RZ_BORROW RZ_NONNULL RzAnalysis *analysis, \ + RzILOpEffect *rz_riscv_lift_##name(RZ_BORROW RZ_NONNULL RzAnalysis *analysis, \ RZ_NONNULL RzAnalysisOp *op, RZ_NONNULL cs_insn *insn, ut64 current_addr, size_t size) { \ decoder(analysis, insn); \ return effect; \ @@ -55,22 +60,10 @@ static inline RzILOpEffect *riscv_il_set_reg(uint32_t reg, RZ_OWN RZ_NONNULL RzI // accept it tolerantly, but TCC enforces the standard strictly and rejects it. // A forced-inline wrapper is an alternative for 0-indirection aliasing. #define DEFINE_ALIAS_LIFTER(alias, name) \ - static inline FUNC_ATTR_ALWAYS_INLINE RzILOpEffect *rz_riscv_lift_##alias(RZ_BORROW RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzAnalysisOp *op, RZ_NONNULL cs_insn *insn, ut64 current_addr, size_t size) { \ + RzILOpEffect *rz_riscv_lift_##alias(RZ_BORROW RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzAnalysisOp *op, RZ_NONNULL cs_insn *insn, ut64 current_addr, size_t size) { \ return rz_riscv_lift_##name(analysis, op, insn, current_addr, size); \ } -#define TWICE_FOR(name1, name2, def_lifter, ...) \ - def_lifter(name1, __VA_ARGS__) \ - def_lifter(name2, __VA_ARGS__) - -#define THRICE_FOR(name1, name2, name3, def_lifter, ...) \ - TWICE_FOR(name1, name2, def_lifter, __VA_ARGS__) \ - def_lifter(name3, __VA_ARGS__) - -#define FOR_4(name1, name2, name3, name4, def_lifter, ...) \ - TWICE_FOR(name1, name2, def_lifter, __VA_ARGS__) \ - TWICE_FOR(name3, name4, def_lifter, __VA_ARGS__) - #if RZ_CHECKS_LEVEL > 0 static inline void riscv_il_dump_operands(RZ_NONNULL cs_insn *insn) { RZ_LOG_ERROR("op_str: %s\n", insn->op_str); diff --git a/librz/arch/isa/riscv/riscv_il_compressed.c b/librz/arch/isa/riscv/riscv_il_compressed.c new file mode 100644 index 00000000000..c8127570c51 --- /dev/null +++ b/librz/arch/isa/riscv/riscv_il_compressed.c @@ -0,0 +1,73 @@ +// SPDX-FileCopyrightText: 2026 Mostafa Mahmoud +// SPDX-License-Identifier: BSD-3-Clause + +#include "riscv_il_compressed.h" + +#include "analysis_private.h" +#include "riscv/riscv_il_base.h" +#include "riscv_il_integer.h" +#include "rz_util/rz_buf.h" + +#include + +// Compressed instruction decoder variants that suppress operands not consumed by the lifter +#define DECODE_RD_RS_IMM_NO_RS(analysis, insn) \ + DECODE_RD_RS_IMM(analysis, insn) \ + (void)(rs); + +#define DECODE_RD_IMM_NO_RD(analysis, insn) \ + DECODE_RD_IMM(analysis, insn) \ + (void)(rd); + +#define DECODE_RS_RS_IMM_NO_RS2(analysis, insn) \ + DECODE_RS_RS_IMM(analysis, insn) \ + (void)(rs2); + +DEFINE_LIFTER_WITH_EFFECT(c_nop, DECODE_NONE, NOP()) +DEFINE_ALIAS_LIFTER(c_addi, addi) +DEFINE_ALIAS_LIFTER(c_addi16sp, addi) +DEFINE_ALIAS_LIFTER(c_addi4spn, addi) +DEFINE_ALIAS_LIFTER(c_add, add) +DEFINE_ALIAS_LIFTER(c_slli, slli) +DEFINE_ALIAS_LIFTER(c_andi, andi) +DEFINE_ALIAS_LIFTER(c_srli, srli) +DEFINE_ALIAS_LIFTER(c_srai, srai) +DEFINE_ALIAS_LIFTER(c_or, or) +DEFINE_ALIAS_LIFTER(c_sub, sub) +DEFINE_ALIAS_LIFTER(c_and, and) +DEFINE_ALIAS_LIFTER(c_xor, xor) +DEFINE_ALIAS_LIFTER(c_addw, addw) + +DEFINE_ALIAS_LIFTER(c_addiw, addiw) + +DEFINE_ALIAS_LIFTER(c_subw, subw) + +DEFINE_LIFTER(c_mv, DECODE_RD_RS, DUP(rs)) +DEFINE_LIFTER(c_li, DECODE_RD_RS_IMM_NO_RS, DUP(imm)) + +DEFINE_LIFTER_FOR_ONEWAY_JUMP(c_j, DECODE_IMM, JMP(imm)) +DEFINE_LIFTER_FOR_JUMP(c_jal, DECODE_RD_IMM, UN(analysis->bits, current_addr + size), JMP(imm)) +DEFINE_ALIAS_LIFTER(c_jr, jalr) + +DEFINE_ALIAS_LIFTER(c_jalr, jalr) +DEFINE_ALIAS_LIFTER(c_ebreak, ebreak) + +DEFINE_ALIAS_LIFTER(c_lui, lui) + +DEFINE_ALIAS_LIFTER(c_sw, sw) +DEFINE_ALIAS_LIFTER(c_swsp, sw) + +DEFINE_ALIAS_LIFTER(c_sd, sd) +DEFINE_ALIAS_LIFTER(c_sdsp, sd) + +DEFINE_ALIAS_LIFTER(c_lwsp, lw) +DEFINE_ALIAS_LIFTER(c_lw, lw) + +DEFINE_ALIAS_LIFTER(c_ld, ld) +DEFINE_ALIAS_LIFTER(c_ldsp, ld) + +DEFINE_LIFTER_FOR_ONEWAY_JUMP(c_beqz, DECODE_RS_RS_IMM_NO_RS2, BRANCH(EQ(rs1, UN(analysis->bits, 0)), JMP(imm), JMP(UN(analysis->bits, current_addr + size)))) +DEFINE_LIFTER_FOR_ONEWAY_JUMP(c_bnez, DECODE_RS_RS_IMM_NO_RS2, BRANCH(NE(rs1, UN(analysis->bits, 0)), JMP(imm), JMP(UN(analysis->bits, current_addr + size)))) + +#include + diff --git a/librz/arch/isa/riscv/riscv_il_compressed.h b/librz/arch/isa/riscv/riscv_il_compressed.h index 955a112a31f..f998f4acc5f 100644 --- a/librz/arch/isa/riscv/riscv_il_compressed.h +++ b/librz/arch/isa/riscv/riscv_il_compressed.h @@ -4,68 +4,47 @@ #ifndef RISCV_IL_COMPRESSED_H #define RISCV_IL_COMPRESSED_H -#include "riscv/riscv_il_base.h" -#include "riscv_il_integer.h" -#include "rz_util/rz_buf.h" - -#include - -// Compressed instruction decoder variants that suppress operands not consumed by the lifter -#define DECODE_RD_RS_IMM_NO_RS(analysis, insn) \ - DECODE_RD_RS_IMM(analysis, insn) \ - (void)(rs); - -#define DECODE_RD_IMM_NO_RD(analysis, insn) \ - DECODE_RD_IMM(analysis, insn) \ - (void)(rd); - -#define DECODE_RS_RS_IMM_NO_RS2(analysis, insn) \ - DECODE_RS_RS_IMM(analysis, insn) \ - (void)(rs2); - -DEFINE_ALIAS_LIFTER(c_addi, addi) -DEFINE_ALIAS_LIFTER(c_addi16sp, addi) -DEFINE_ALIAS_LIFTER(c_addi4spn, addi) -DEFINE_ALIAS_LIFTER(c_add, add) -DEFINE_ALIAS_LIFTER(c_slli, slli) -DEFINE_ALIAS_LIFTER(c_andi, andi) -DEFINE_ALIAS_LIFTER(c_srli, srli) -DEFINE_ALIAS_LIFTER(c_srai, srai) -DEFINE_ALIAS_LIFTER(c_or, or) -DEFINE_ALIAS_LIFTER(c_sub, sub) -DEFINE_ALIAS_LIFTER(c_and, and) -DEFINE_ALIAS_LIFTER(c_xor, xor) -DEFINE_ALIAS_LIFTER(c_addw, addw) - -DEFINE_ALIAS_LIFTER(c_addiw, addiw) - -DEFINE_ALIAS_LIFTER(c_subw, subw) - -DEFINE_LIFTER(c_mv, DECODE_RD_RS, DUP(rs)) -DEFINE_LIFTER(c_li, DECODE_RD_RS_IMM_NO_RS, DUP(imm)) - -DEFINE_LIFTER_FOR_ONEWAY_JUMP(c_j, DECODE_RD_IMM_NO_RD, JMP(imm)) -DEFINE_ALIAS_LIFTER(c_jr, jalr) - -DEFINE_ALIAS_LIFTER(c_jalr, jalr) - -DEFINE_ALIAS_LIFTER(c_lui, lui) - -DEFINE_ALIAS_LIFTER(c_sw, sw) -DEFINE_ALIAS_LIFTER(c_swsp, sw) - -DEFINE_ALIAS_LIFTER(c_sd, sd) -DEFINE_ALIAS_LIFTER(c_sdsp, sd) - -DEFINE_ALIAS_LIFTER(c_lwsp, lw) -DEFINE_ALIAS_LIFTER(c_lw, lw) - -DEFINE_ALIAS_LIFTER(c_ld, ld) -DEFINE_ALIAS_LIFTER(c_ldsp, ld) - -DEFINE_LIFTER_FOR_BRANCH(c_beqz, DECODE_RS_RS_IMM_NO_RS2, EQ(rs1, UN(analysis->bits, 0))) -DEFINE_LIFTER_FOR_BRANCH(c_bnez, DECODE_RS_RS_IMM_NO_RS2, NE(rs1, UN(analysis->bits, 0))) - -#include +#include "riscv_il.h" + +#define DECL_LIFTER(name) \ + RzILOpEffect *rz_riscv_lift_##name(RZ_BORROW RZ_NONNULL RzAnalysis *analysis, \ + RZ_NONNULL RzAnalysisOp *op, RZ_NONNULL cs_insn *insn, ut64 current_addr, size_t size) + +DECL_LIFTER(c_nop); +DECL_LIFTER(c_addi); +DECL_LIFTER(c_addi16sp); +DECL_LIFTER(c_addi4spn); +DECL_LIFTER(c_add); +DECL_LIFTER(c_andi); +DECL_LIFTER(c_slli); +DECL_LIFTER(c_srli); +DECL_LIFTER(c_srai); +DECL_LIFTER(c_or); +DECL_LIFTER(c_sub); +DECL_LIFTER(c_and); +DECL_LIFTER(c_xor); +DECL_LIFTER(c_addw); +DECL_LIFTER(c_addiw); +DECL_LIFTER(c_subw); +DECL_LIFTER(c_mv); +DECL_LIFTER(c_li); +DECL_LIFTER(c_jal); +DECL_LIFTER(c_j); +DECL_LIFTER(c_jr); +DECL_LIFTER(c_ebreak); +DECL_LIFTER(c_jalr); +DECL_LIFTER(c_lui); +DECL_LIFTER(c_sw); +DECL_LIFTER(c_swsp); +DECL_LIFTER(c_sd); +DECL_LIFTER(c_sdsp); +DECL_LIFTER(c_lwsp); +DECL_LIFTER(c_lw); +DECL_LIFTER(c_ld); +DECL_LIFTER(c_ldsp); +DECL_LIFTER(c_beqz); +DECL_LIFTER(c_bnez); + +#undef DECL_LIFTER #endif // RISCV_IL_COMPRESSED_H diff --git a/librz/arch/isa/riscv/riscv_il_integer.c b/librz/arch/isa/riscv/riscv_il_integer.c new file mode 100644 index 00000000000..da2cf589f65 --- /dev/null +++ b/librz/arch/isa/riscv/riscv_il_integer.c @@ -0,0 +1,102 @@ +// SPDX-FileCopyrightText: 2026 Mostafa Mahmoud +// SPDX-License-Identifier: BSD-3-Clause + +#include "riscv_il_integer.h" + +#include "analysis_private.h" +#include "capstone.h" + +#include "riscv_il_base.h" + +#include + +DEFINE_LIFTER(addi, DECODE_RD_RS_IMM, ADD(rs, imm)) +DEFINE_LIFTER(slli, DECODE_RD_RS_IMM, SHIFTL0(rs, imm)) +DEFINE_LIFTER(andi, DECODE_RD_RS_IMM, LOGAND(rs, imm)) +DEFINE_LIFTER(ori, DECODE_RD_RS_IMM, LOGOR(rs, imm)) +DEFINE_LIFTER(xori, DECODE_RD_RS_IMM, LOGXOR(rs, imm)) +DEFINE_LIFTER(slti, DECODE_RD_RS_IMM, BOOL_TO_BV(SLT(rs, imm), analysis->bits)) +DEFINE_LIFTER(sltiu, DECODE_RD_RS_IMM, BOOL_TO_BV(ULT(rs, imm), analysis->bits)) +DEFINE_LIFTER(srli, DECODE_RD_RS_IMM, SHIFTR0(rs, imm)) +DEFINE_LIFTER(srai, DECODE_RD_RS_IMM, SHIFTRA(rs, imm)) + +DEFINE_LIFTER(add, DECODE_RD_RS_RS, ADD(rs1, rs2)) +DEFINE_LIFTER(sub, DECODE_RD_RS_RS, SUB(rs1, rs2)) +DEFINE_LIFTER(and, DECODE_RD_RS_RS, LOGAND(rs1, rs2)) +DEFINE_LIFTER(or, DECODE_RD_RS_RS, LOGOR(rs1, rs2)) +DEFINE_LIFTER(xor, DECODE_RD_RS_RS, LOGXOR(rs1, rs2)) +DEFINE_LIFTER(slt, DECODE_RD_RS_RS, BOOL_TO_BV(SLT(rs1, rs2), analysis->bits)) +DEFINE_LIFTER(sltu, DECODE_RD_RS_RS, BOOL_TO_BV(ULT(rs1, rs2), analysis->bits)) +DEFINE_LIFTER(sll, DECODE_RD_RS_RS, SHIFTL0(rs1, LOGAND(rs2, UN(analysis->bits, analysis->bits - 1)))) +DEFINE_LIFTER(srl, DECODE_RD_RS_RS, SHIFTR0(rs1, LOGAND(rs2, UN(analysis->bits, analysis->bits - 1)))) +DEFINE_LIFTER(sra, DECODE_RD_RS_RS, SHIFTRA(rs1, LOGAND(rs2, UN(analysis->bits, analysis->bits - 1)))) + +#define DEFINE_LIFTER_FOR_BRANCH(name, decoder, condition) \ + DEFINE_LIFTER_FOR_ONEWAY_JUMP(name, decoder, BRANCH(condition, JMP(imm), JMP(UN(analysis->bits, current_addr + size)))) + +DEFINE_LIFTER_FOR_BRANCH(beq, DECODE_RS_RS_IMM, EQ(rs1, rs2)) +DEFINE_LIFTER_FOR_BRANCH(bne, DECODE_RS_RS_IMM, NE(rs1, rs2)) +DEFINE_LIFTER_FOR_BRANCH(blt, DECODE_RS_RS_IMM, SLT(rs1, rs2)) +DEFINE_LIFTER_FOR_BRANCH(bge, DECODE_RS_RS_IMM, SGE(rs1, rs2)) +DEFINE_LIFTER_FOR_BRANCH(bltu, DECODE_RS_RS_IMM, ULT(rs1, rs2)) +DEFINE_LIFTER_FOR_BRANCH(bgeu, DECODE_RS_RS_IMM, UGE(rs1, rs2)) + +DEFINE_LIFTER_FOR_JUMP(jal, DECODE_RD_IMM, + /*RETURN ADDR*/ UN(analysis->bits, current_addr + size), + /*GOTO ADDR*/ JMP(imm)) + +DEFINE_LIFTER_FOR_JUMP(jalr, DECODE_RD_RS_IMM, + /*RETURN ADDR*/ UN(analysis->bits, current_addr + size), + /*GOTO ADDR*/ JMP(LOGAND(ADD(rs, imm), UN(analysis->bits, ~1ULL)))) + +// Intentional: on RV32 imm is already 32-bit and the result needs no sign-extension, +// so CAST(32) and SIGNED(32) would both be no-ops; on RV64 CAST(32) truncates imm and SIGNED(64) +// sign-extends the shifted 32-bit result to XLEN. +DEFINE_LIFTER(lui, DECODE_RD_IMM, + analysis->bits == 32 + ? SHIFTL0(imm, UN(32, 12)) + : SIGNED(analysis->bits, SHIFTL0(CAST(32, IL_FALSE, imm), UN(32, 12)))) +DEFINE_LIFTER(auipc, DECODE_RD_IMM, + ADD(UN(analysis->bits, current_addr), + analysis->bits == 32 + ? SHIFTL0(imm, UN(32, 12)) + : SIGNED(analysis->bits, SHIFTL0(CAST(32, IL_FALSE, imm), UN(32, 12))))) + +DEFINE_LIFTER_WITH_EFFECT(sb, DECODE_RS_RS_IMM_MEM, STOREW(ADD(rs2, imm), CAST(8, IL_FALSE, rs1))) +DEFINE_LIFTER_WITH_EFFECT(sh, DECODE_RS_RS_IMM_MEM, STOREW(ADD(rs2, imm), CAST(16, IL_FALSE, rs1))) +// Intentional: on RV32 rs1 is already 32-bit so CAST(32) would be a redundant no-op; +// on RV64 it is needed to truncate the 64-bit register value to 32 bits before storing. +DEFINE_LIFTER_WITH_EFFECT(sw, DECODE_RS_RS_IMM_MEM, + analysis->bits == 32 + ? STOREW(ADD(rs2, imm), rs1) + : STOREW(ADD(rs2, imm), CAST(32, IL_FALSE, rs1))) +DEFINE_LIFTER_WITH_EFFECT(sd, DECODE_RS_RS_IMM_MEM, STOREW(ADD(rs2, imm), rs1)) + +DEFINE_LIFTER(lw, DECODE_RD_RS_IMM_MEM, analysis->bits == 32 ? LOADW(32, ADD(rs, imm)) : SIGNED(analysis->bits, LOADW(32, ADD(rs, imm)))) +DEFINE_LIFTER(lb, DECODE_RD_RS_IMM_MEM, SIGNED(analysis->bits, LOADW(8, ADD(rs, imm)))) +DEFINE_LIFTER(lh, DECODE_RD_RS_IMM_MEM, SIGNED(analysis->bits, LOADW(16, ADD(rs, imm)))) +DEFINE_LIFTER(lbu, DECODE_RD_RS_IMM_MEM, UNSIGNED(analysis->bits, LOADW(8, ADD(rs, imm)))) +DEFINE_LIFTER(lhu, DECODE_RD_RS_IMM_MEM, UNSIGNED(analysis->bits, LOADW(16, ADD(rs, imm)))) +DEFINE_LIFTER(ld, DECODE_RD_RS_IMM_MEM, LOADW(64, ADD(rs, imm))) + +DEFINE_LIFTER_WITH_EFFECT(fence, DECODE_NONE, NOP()) +DEFINE_LIFTER_WITH_EFFECT(fence_i, DECODE_NONE, NOP()) + +DEFINE_LIFTER(addw, DECODE_RD_RS_RS_TRUNCATE32, SIGNED(analysis->bits, ADD(rs1, rs2))) +DEFINE_LIFTER(subw, DECODE_RD_RS_RS_TRUNCATE32, SIGNED(analysis->bits, SUB(rs1, rs2))) +DEFINE_LIFTER(sllw, DECODE_RD_RS_RS_TRUNCATE32, SIGNED(analysis->bits, SHIFTL0(rs1, LOGAND(rs2, UN(32, 31))))) +DEFINE_LIFTER(srlw, DECODE_RD_RS_RS_TRUNCATE32, SIGNED(analysis->bits, SHIFTR0(rs1, LOGAND(rs2, UN(32, 31))))) +DEFINE_LIFTER(sraw, DECODE_RD_RS_RS_TRUNCATE32, SIGNED(analysis->bits, SHIFTRA(rs1, LOGAND(rs2, UN(32, 31))))) +DEFINE_LIFTER(addiw, DECODE_RD_RS_IMM_TRUNCATE32, SIGNED(analysis->bits, ADD(rs, imm))) +DEFINE_LIFTER(slliw, DECODE_RD_RS_IMM_TRUNCATE32, SIGNED(analysis->bits, SHIFTL0(rs, imm))) +DEFINE_LIFTER(srliw, DECODE_RD_RS_IMM_TRUNCATE32, SIGNED(analysis->bits, SHIFTR0(rs, imm))) +DEFINE_LIFTER(sraiw, DECODE_RD_RS_IMM_TRUNCATE32, SIGNED(analysis->bits, SHIFTRA(rs, imm))) + +// RV64I: load word unsigned (zero-extend 32-bit load to XLEN) +DEFINE_LIFTER(lwu, DECODE_RD_RS_IMM_MEM, UNSIGNED(analysis->bits, LOADW(32, ADD(rs, imm)))) + +// System: environment call / breakpoint (trap to OS / debugger) +DEFINE_LIFTER_WITH_EFFECT(ecall, DECODE_NONE, GOTO("ecall")) +DEFINE_LIFTER_WITH_EFFECT(ebreak, DECODE_NONE, GOTO("ebreak")) + +#include diff --git a/librz/arch/isa/riscv/riscv_il_integer.h b/librz/arch/isa/riscv/riscv_il_integer.h index 6159636594f..135531f057a 100644 --- a/librz/arch/isa/riscv/riscv_il_integer.h +++ b/librz/arch/isa/riscv/riscv_il_integer.h @@ -4,96 +4,75 @@ #ifndef RISCV_IL_INTEGER_H #define RISCV_IL_INTEGER_H -#include "analysis_private.h" -#include "capstone.h" -#include "riscv_il_base.h" - -#include - -DEFINE_LIFTER(addi, DECODE_RD_RS_IMM, ADD(rs, imm)) -DEFINE_LIFTER(slli, DECODE_RD_RS_IMM, SHIFTL0(rs, imm)) -DEFINE_LIFTER(andi, DECODE_RD_RS_IMM, LOGAND(rs, imm)) -DEFINE_LIFTER(ori, DECODE_RD_RS_IMM, LOGOR(rs, imm)) -DEFINE_LIFTER(xori, DECODE_RD_RS_IMM, LOGXOR(rs, imm)) -DEFINE_LIFTER(slti, DECODE_RD_RS_IMM, BOOL_TO_BV(SLT(rs, imm), analysis->bits)) -DEFINE_LIFTER(sltiu, DECODE_RD_RS_IMM, BOOL_TO_BV(ULT(rs, imm), analysis->bits)) -DEFINE_LIFTER(srli, DECODE_RD_RS_IMM, SHIFTR0(rs, imm)) -DEFINE_LIFTER(srai, DECODE_RD_RS_IMM, SHIFTRA(rs, imm)) - -DEFINE_LIFTER(add, DECODE_RD_RS_RS, ADD(rs1, rs2)) -DEFINE_LIFTER(sub, DECODE_RD_RS_RS, SUB(rs1, rs2)) -DEFINE_LIFTER(and, DECODE_RD_RS_RS, LOGAND(rs1, rs2)) -DEFINE_LIFTER(or, DECODE_RD_RS_RS, LOGOR(rs1, rs2)) -DEFINE_LIFTER(xor, DECODE_RD_RS_RS, LOGXOR(rs1, rs2)) -DEFINE_LIFTER(slt, DECODE_RD_RS_RS, BOOL_TO_BV(SLT(rs1, rs2), analysis->bits)) -DEFINE_LIFTER(sltu, DECODE_RD_RS_RS, BOOL_TO_BV(ULT(rs1, rs2), analysis->bits)) -DEFINE_LIFTER(sll, DECODE_RD_RS_RS, SHIFTL0(rs1, LOGAND(rs2, UN(analysis->bits, analysis->bits - 1)))) -DEFINE_LIFTER(srl, DECODE_RD_RS_RS, SHIFTR0(rs1, LOGAND(rs2, UN(analysis->bits, analysis->bits - 1)))) -DEFINE_LIFTER(sra, DECODE_RD_RS_RS, SHIFTRA(rs1, LOGAND(rs2, UN(analysis->bits, analysis->bits - 1)))) - -#define DEFINE_LIFTER_FOR_BRANCH(name, decoder, condition) \ - DEFINE_LIFTER_FOR_ONEWAY_JUMP(name, decoder, BRANCH(condition, JMP(imm), JMP(UN(analysis->bits, current_addr + size)))) - -DEFINE_LIFTER_FOR_BRANCH(beq, DECODE_RS_RS_IMM, EQ(rs1, rs2)) -DEFINE_LIFTER_FOR_BRANCH(bne, DECODE_RS_RS_IMM, NE(rs1, rs2)) -DEFINE_LIFTER_FOR_BRANCH(blt, DECODE_RS_RS_IMM, SLT(rs1, rs2)) -DEFINE_LIFTER_FOR_BRANCH(bge, DECODE_RS_RS_IMM, SGE(rs1, rs2)) -DEFINE_LIFTER_FOR_BRANCH(bltu, DECODE_RS_RS_IMM, ULT(rs1, rs2)) -DEFINE_LIFTER_FOR_BRANCH(bgeu, DECODE_RS_RS_IMM, UGE(rs1, rs2)) - -DEFINE_LIFTER_FOR_JUMP(jal, DECODE_RD_IMM, - /*RETURN ADDR*/ UN(analysis->bits, current_addr + size), - /*GOTO ADDR*/ JMP(imm)) - -DEFINE_LIFTER_FOR_JUMP(jalr, DECODE_RD_RS_IMM, - /*RETURN ADDR*/ UN(analysis->bits, current_addr + size), - /*GOTO ADDR*/ JMP(LOGAND(ADD(rs, imm), UN(analysis->bits, ~1ULL)))) - -// Intentional: on RV32 imm is already 32-bit and the result needs no sign-extension, -// so CAST(32) and SIGNED(32) would both be no-ops; on RV64 CAST(32) truncates imm and SIGNED(64) -// sign-extends the shifted 32-bit result to XLEN. -DEFINE_LIFTER(lui, DECODE_RD_IMM, - analysis->bits == 32 - ? SHIFTL0(imm, UN(32, 12)) - : SIGNED(analysis->bits, SHIFTL0(CAST(32, IL_FALSE, imm), UN(32, 12)))) -DEFINE_LIFTER(auipc, DECODE_RD_IMM, ADD(UN(analysis->bits, current_addr), SIGNED(analysis->bits, SHIFTL0(CAST(32, IL_FALSE, imm), UN(32, 12))))) - -DEFINE_LIFTER_WITH_EFFECT(sb, DECODE_RS_RS_IMM_MEM, STOREW(ADD(rs2, imm), CAST(8, IL_FALSE, rs1))) -DEFINE_LIFTER_WITH_EFFECT(sh, DECODE_RS_RS_IMM_MEM, STOREW(ADD(rs2, imm), CAST(16, IL_FALSE, rs1))) -// Intentional: on RV32 rs1 is already 32-bit so CAST(32) would be a redundant no-op; -// on RV64 it is needed to truncate the 64-bit register value to 32 bits before storing. -DEFINE_LIFTER_WITH_EFFECT(sw, DECODE_RS_RS_IMM_MEM, - analysis->bits == 32 - ? STOREW(ADD(rs2, imm), rs1) - : STOREW(ADD(rs2, imm), CAST(32, IL_FALSE, rs1))) -DEFINE_LIFTER_WITH_EFFECT(sd, DECODE_RS_RS_IMM_MEM, STOREW(ADD(rs2, imm), rs1)) - -DEFINE_LIFTER(lw, DECODE_RD_RS_IMM_MEM, analysis->bits == 32 ? LOADW(32, ADD(rs, imm)) : SIGNED(analysis->bits, LOADW(32, ADD(rs, imm)))) -DEFINE_LIFTER(lb, DECODE_RD_RS_IMM_MEM, SIGNED(analysis->bits, LOADW(8, ADD(rs, imm)))) -DEFINE_LIFTER(lh, DECODE_RD_RS_IMM_MEM, SIGNED(analysis->bits, LOADW(16, ADD(rs, imm)))) -DEFINE_LIFTER(lbu, DECODE_RD_RS_IMM_MEM, UNSIGNED(analysis->bits, LOADW(8, ADD(rs, imm)))) -DEFINE_LIFTER(lhu, DECODE_RD_RS_IMM_MEM, UNSIGNED(analysis->bits, LOADW(16, ADD(rs, imm)))) -DEFINE_LIFTER(ld, DECODE_RD_RS_IMM_MEM, LOADW(64, ADD(rs, imm))) - -TWICE_FOR(fence, fence_i, - DEFINE_LIFTER_WITH_EFFECT, DECODE_NONE, NOP()) - -DEFINE_LIFTER(addw, DECODE_RD_RS_RS_TRUNCATE32, SIGNED(analysis->bits, ADD(rs1, rs2))) -DEFINE_LIFTER(subw, DECODE_RD_RS_RS_TRUNCATE32, SIGNED(analysis->bits, SUB(rs1, rs2))) -DEFINE_LIFTER(sllw, DECODE_RD_RS_RS_TRUNCATE32, SIGNED(analysis->bits, SHIFTL0(rs1, LOGAND(rs2, UN(32, 31))))) -DEFINE_LIFTER(srlw, DECODE_RD_RS_RS_TRUNCATE32, SIGNED(analysis->bits, SHIFTR0(rs1, LOGAND(rs2, UN(32, 31))))) -DEFINE_LIFTER(sraw, DECODE_RD_RS_RS_TRUNCATE32, SIGNED(analysis->bits, SHIFTRA(rs1, LOGAND(rs2, UN(32, 31))))) -DEFINE_LIFTER(addiw, DECODE_RD_RS_IMM_TRUNCATE32, SIGNED(analysis->bits, ADD(rs, imm))) -DEFINE_LIFTER(slliw, DECODE_RD_RS_IMM_TRUNCATE32, SIGNED(analysis->bits, SHIFTL0(rs, imm))) -DEFINE_LIFTER(srliw, DECODE_RD_RS_IMM_TRUNCATE32, SIGNED(analysis->bits, SHIFTR0(rs, imm))) -DEFINE_LIFTER(sraiw, DECODE_RD_RS_IMM_TRUNCATE32, SIGNED(analysis->bits, SHIFTRA(rs, imm))) - -// RV64I: load word unsigned (zero-extend 32-bit load to XLEN) -DEFINE_LIFTER(lwu, DECODE_RD_RS_IMM_MEM, UNSIGNED(analysis->bits, LOADW(32, ADD(rs, imm)))) - -// System: environment call (trap to OS / hypervisor) -DEFINE_LIFTER_WITH_EFFECT(ecall, DECODE_NONE, GOTO("ecall")) - -#include - -#endif // RISCV_IL_INTEGER_H \ No newline at end of file +#include "riscv_il.h" + +#define DECL_LIFTER(name) \ + RzILOpEffect *rz_riscv_lift_##name(RZ_BORROW RZ_NONNULL RzAnalysis *analysis, \ + RZ_NONNULL RzAnalysisOp *op, RZ_NONNULL cs_insn *insn, ut64 current_addr, size_t size) + +DECL_LIFTER(addi); +DECL_LIFTER(slli); +DECL_LIFTER(andi); +DECL_LIFTER(ori); +DECL_LIFTER(xori); +DECL_LIFTER(slti); +DECL_LIFTER(sltiu); +DECL_LIFTER(srli); +DECL_LIFTER(srai); + +DECL_LIFTER(add); +DECL_LIFTER(sub); +DECL_LIFTER(and); +DECL_LIFTER(or); +DECL_LIFTER(xor); +DECL_LIFTER(slt); +DECL_LIFTER(sltu); +DECL_LIFTER(sll); +DECL_LIFTER(srl); +DECL_LIFTER(sra); + +DECL_LIFTER(beq); +DECL_LIFTER(bne); +DECL_LIFTER(blt); +DECL_LIFTER(bge); +DECL_LIFTER(bltu); +DECL_LIFTER(bgeu); + +DECL_LIFTER(jal); +DECL_LIFTER(jalr); + +DECL_LIFTER(lui); +DECL_LIFTER(auipc); + +DECL_LIFTER(sb); +DECL_LIFTER(sh); +DECL_LIFTER(sw); +DECL_LIFTER(sd); + +DECL_LIFTER(lw); +DECL_LIFTER(lb); +DECL_LIFTER(lh); +DECL_LIFTER(lbu); +DECL_LIFTER(lhu); +DECL_LIFTER(ld); + +DECL_LIFTER(fence); +DECL_LIFTER(fence_i); + +DECL_LIFTER(addw); +DECL_LIFTER(subw); +DECL_LIFTER(sllw); +DECL_LIFTER(srlw); +DECL_LIFTER(sraw); +DECL_LIFTER(addiw); +DECL_LIFTER(slliw); +DECL_LIFTER(srliw); +DECL_LIFTER(sraiw); + +DECL_LIFTER(lwu); +DECL_LIFTER(ecall); +DECL_LIFTER(ebreak); + +#undef DECL_LIFTER + +#endif // RISCV_IL_INTEGER_H diff --git a/librz/arch/isa/riscv/riscv_il_integer_reg_names.h b/librz/arch/isa/riscv/riscv_il_integer_reg_names.h index 80cadb58790..7206899e17a 100644 --- a/librz/arch/isa/riscv/riscv_il_integer_reg_names.h +++ b/librz/arch/isa/riscv/riscv_il_integer_reg_names.h @@ -44,7 +44,8 @@ static const char *riscv_integer_reg_names[] = { static inline const char *riscv_integer_reg_name(uint32_t reg) { int idx = (int)reg - RISCV_REG_X0; - if (idx < 0 || idx >= 32) { + if (idx < 0 || idx >= RZ_ARRAY_SIZE(riscv_integer_reg_names)) { + RZ_LOG_ERROR("Invalid RISC-V integer register index %d, returning empty str\n", idx); return ""; } return riscv_integer_reg_names[idx]; diff --git a/librz/arch/isa/riscv/riscv_il_m.c b/librz/arch/isa/riscv/riscv_il_m.c new file mode 100644 index 00000000000..34e6199bbd1 --- /dev/null +++ b/librz/arch/isa/riscv/riscv_il_m.c @@ -0,0 +1,31 @@ +// SPDX-FileCopyrightText: 2026 Mostafa Mahmoud +// SPDX-License-Identifier: BSD-3-Clause + +#include "riscv_il_m.h" + +#include "analysis_private.h" + +#include "riscv_il_base.h" + +#include + +// M extension: multiply/divide/remainder (RV32M / RV64M) + +// RV32M +DEFINE_LIFTER(mul, DECODE_RD_RS_RS, MUL(rs1, rs2)) +DEFINE_LIFTER(mulh, DECODE_RD_RS_RS, CAST(analysis->bits, IL_FALSE, SHIFTR0(MUL(SIGNED(analysis->bits * 2, rs1), SIGNED(analysis->bits * 2, rs2)), UN(8, analysis->bits)))) +DEFINE_LIFTER(mulhsu, DECODE_RD_RS_RS, CAST(analysis->bits, IL_FALSE, SHIFTR0(MUL(SIGNED(analysis->bits * 2, rs1), UNSIGNED(analysis->bits * 2, rs2)), UN(8, analysis->bits)))) +DEFINE_LIFTER(mulhu, DECODE_RD_RS_RS, CAST(analysis->bits, IL_FALSE, SHIFTR0(MUL(UNSIGNED(analysis->bits * 2, rs1), UNSIGNED(analysis->bits * 2, rs2)), UN(8, analysis->bits)))) +DEFINE_LIFTER(div, DECODE_RD_RS_RS, SDIV(rs1, rs2)) +DEFINE_LIFTER(divu, DECODE_RD_RS_RS, DIV(rs1, rs2)) +DEFINE_LIFTER(rem, DECODE_RD_RS_RS, SMOD(rs1, rs2)) +DEFINE_LIFTER(remu, DECODE_RD_RS_RS, MOD(rs1, rs2)) + +// RV64M: *w instructions operate on lower 32 bits, result sign-extended to 64 bits +DEFINE_LIFTER(mulw, DECODE_RD_RS_RS_TRUNCATE32, SIGNED(analysis->bits, MUL(rs1, rs2))) +DEFINE_LIFTER(divw, DECODE_RD_RS_RS_TRUNCATE32, SIGNED(analysis->bits, SDIV(rs1, rs2))) +DEFINE_LIFTER(divuw, DECODE_RD_RS_RS_TRUNCATE32, SIGNED(analysis->bits, DIV(rs1, rs2))) +DEFINE_LIFTER(remw, DECODE_RD_RS_RS_TRUNCATE32, SIGNED(analysis->bits, SMOD(rs1, rs2))) +DEFINE_LIFTER(remuw, DECODE_RD_RS_RS_TRUNCATE32, SIGNED(analysis->bits, MOD(rs1, rs2))) + +#include diff --git a/librz/arch/isa/riscv/riscv_il_m.h b/librz/arch/isa/riscv/riscv_il_m.h index e3f666f6a44..7e0d66dca00 100644 --- a/librz/arch/isa/riscv/riscv_il_m.h +++ b/librz/arch/isa/riscv/riscv_il_m.h @@ -4,18 +4,26 @@ #ifndef RISCV_IL_M_H #define RISCV_IL_M_H -#include "riscv_il_base.h" +#include "riscv_il.h" -#include +#define DECL_LIFTER(name) \ + RzILOpEffect *rz_riscv_lift_##name(RZ_BORROW RZ_NONNULL RzAnalysis *analysis, \ + RZ_NONNULL RzAnalysisOp *op, RZ_NONNULL cs_insn *insn, ut64 current_addr, size_t size) -// M extension: multiply/divide/remainder (RV32M / RV64M) -DEFINE_LIFTER(mul, DECODE_RD_RS_RS, MUL(rs1, rs2)) -DEFINE_LIFTER(mulhu, DECODE_RD_RS_RS, CAST(analysis->bits, IL_FALSE, SHIFTR0(MUL(UNSIGNED(analysis->bits * 2, rs1), UNSIGNED(analysis->bits * 2, rs2)), UN(8, analysis->bits)))) -DEFINE_LIFTER(divu, DECODE_RD_RS_RS, DIV(rs1, rs2)) -DEFINE_LIFTER(remu, DECODE_RD_RS_RS, MOD(rs1, rs2)) -// RV64M: unsigned remainder of 32-bit operands, result sign-extended to 64 bits -DEFINE_LIFTER(remuw, DECODE_RD_RS_RS_TRUNCATE32, SIGNED(analysis->bits, MOD(rs1, rs2))) +DECL_LIFTER(mul); +DECL_LIFTER(mulh); +DECL_LIFTER(mulhsu); +DECL_LIFTER(mulhu); +DECL_LIFTER(div); +DECL_LIFTER(divu); +DECL_LIFTER(rem); +DECL_LIFTER(remu); +DECL_LIFTER(mulw); +DECL_LIFTER(divw); +DECL_LIFTER(divuw); +DECL_LIFTER(remw); +DECL_LIFTER(remuw); -#include +#undef DECL_LIFTER #endif // RISCV_IL_M_H diff --git a/librz/arch/meson.build b/librz/arch/meson.build index a684990f4ee..04cfdd6c3be 100644 --- a/librz/arch/meson.build +++ b/librz/arch/meson.build @@ -303,6 +303,9 @@ arch_isa_sources = [ 'isa/pyc/opcode_arg_fmt.c', 'isa/pyc/pyc_dis.c', 'isa/riscv/riscv_il.c', + 'isa/riscv/riscv_il_integer.c', + 'isa/riscv/riscv_il_m.c', + 'isa/riscv/riscv_il_compressed.c', 'isa/rl78/rl78.c', 'isa/rl78/rl78_instr.c', 'isa/rl78/rl78_maps.c', From c5f2fe79abe097425764df0ace04f47ea1cc0c4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D9=85=D8=B5=D8=B7=D9=81=D9=8A=20=D9=85=D8=AD=D9=85=D9=88?= =?UTF-8?q?=D8=AF=20=D9=83=D9=85=D8=A7=D9=84=20=D8=A7=D9=84=D8=AF=D9=8A?= =?UTF-8?q?=D9=86?= <48567303+moste00@users.noreply.github.com> Date: Fri, 26 Jun 2026 03:14:25 +0300 Subject: [PATCH 6/8] add tests for 64-bit --- librz/arch/isa/riscv/riscv_il_compressed.c | 4 +- test/db/asm/riscv_32 | 2 +- test/db/asm/riscv_64 | 201 +++++++++++++++++++++ 3 files changed, 204 insertions(+), 3 deletions(-) create mode 100644 test/db/asm/riscv_64 diff --git a/librz/arch/isa/riscv/riscv_il_compressed.c b/librz/arch/isa/riscv/riscv_il_compressed.c index c8127570c51..8d8a0c67a61 100644 --- a/librz/arch/isa/riscv/riscv_il_compressed.c +++ b/librz/arch/isa/riscv/riscv_il_compressed.c @@ -45,8 +45,8 @@ DEFINE_ALIAS_LIFTER(c_subw, subw) DEFINE_LIFTER(c_mv, DECODE_RD_RS, DUP(rs)) DEFINE_LIFTER(c_li, DECODE_RD_RS_IMM_NO_RS, DUP(imm)) -DEFINE_LIFTER_FOR_ONEWAY_JUMP(c_j, DECODE_IMM, JMP(imm)) -DEFINE_LIFTER_FOR_JUMP(c_jal, DECODE_RD_IMM, UN(analysis->bits, current_addr + size), JMP(imm)) +DEFINE_ALIAS_LIFTER(c_j, jal) +DEFINE_ALIAS_LIFTER(c_jal, jal) DEFINE_ALIAS_LIFTER(c_jr, jalr) DEFINE_ALIAS_LIFTER(c_jalr, jalr) diff --git a/test/db/asm/riscv_32 b/test/db/asm/riscv_32 index 87831e4ba54..d2036956000 100644 --- a/test/db/asm/riscv_32 +++ b/test/db/asm/riscv_32 @@ -132,7 +132,7 @@ d "li a3, 0" 8146 0x100 (set a3 (bv 32 0x0)) d "li t1, 0" 0143 0x100 (set t1 (bv 32 0x0)) d "li a2, 0" 0146 0x100 (set a2 (bv 32 0x0)) d "li a0, 0" 0145 0x100 (set a0 (bv 32 0x0)) -d "j 0x176" 25a8 0x13e (jmp (bv 32 0x176)) +d "j 0x176" 25a8 0x13e (seq nop (jmp (bv 32 0x176))) d "mul a4, a0, a2" 3307c502 0x140 (set a4 (* (var a0) (var a2))) d "mulhu t1, a2, a2" 3333c602 0x140 (set t1 (cast 32 false (>> (* (cast 64 false (var a2)) (cast 64 false (var a2))) (bv 8 0x20) false))) d "slli a4, a4, 1" 0607 0x140 (set a4 (<< (var a4) (bv 32 0x1) false)) diff --git a/test/db/asm/riscv_64 b/test/db/asm/riscv_64 new file mode 100644 index 00000000000..d13c2a527dc --- /dev/null +++ b/test/db/asm/riscv_64 @@ -0,0 +1,201 @@ +# ----------------------------- C_ADDI16SP ----------------------------- +d "addi sp, sp, -0x90" 7571 0x0 (set sp (+ (var sp) (bv 64 0xffffffffffffff70))) +# ----------------------------- ADDI ----------------------------- +d "addi a1, a1, 0x700" 93850570 0x0 (set a1 (+ (var a1) (bv 64 0x700))) +# ----------------------------- C_ADDI4SPN ----------------------------- +d "addi s0, sp, 0x80" 0001 0x0 (set s0 (+ (var sp) (bv 64 0x80))) +# ----------------------------- C_ADDI --------------------------------- +d "addi sp, sp, -0x20" 0111 0x0 (set sp (+ (var sp) (bv 64 0xffffffffffffffe0))) +d "lui a5, 0x10" c167 0x0 (set a5 (cast 64 (msb (<< (cast 32 false (bv 64 0x10)) (bv 32 0xc) false)) (<< (cast 32 false (bv 64 0x10)) (bv 32 0xc) false))) +d "sw a5, 0x1c(sp)" 3ece 0x0 (storew 0 (+ (var sp) (bv 64 0x1c)) (cast 32 false (var a5))) +d "lui a5, 0x30" b7070300 0x0 (set a5 (cast 64 (msb (<< (cast 32 false (bv 64 0x30)) (bv 32 0xc) false)) (<< (cast 32 false (bv 64 0x30)) (bv 32 0xc) false))) +d "sw a5, 0x24(sp)" 3ed2 0x0 (storew 0 (+ (var sp) (bv 64 0x24)) (cast 32 false (var a5))) +d "lui a5, 0xc" b167 0x0 (set a5 (cast 64 (msb (<< (cast 32 false (bv 64 0xc)) (bv 32 0xc) false)) (<< (cast 32 false (bv 64 0xc)) (bv 32 0xc) false))) +d "sw a5, 0x3c(sp)" 3ede 0x0 (storew 0 (+ (var sp) (bv 64 0x3c)) (cast 32 false (var a5))) +d "lui a5, 0xffff8" e177 0x0 (set a5 (cast 64 (msb (<< (cast 32 false (bv 64 0xffff8)) (bv 32 0xc) false)) (<< (cast 32 false (bv 64 0xffff8)) (bv 32 0xc) false))) +d "sw s1, 0x84(sp)" 26c3 0x0 (storew 0 (+ (var sp) (bv 64 0x84)) (cast 32 false (var s1))) +d "sw ra, 0x8c(sp)" 06c7 0x0 (storew 0 (+ (var sp) (bv 64 0x8c)) (cast 32 false (var ra))) +d "sw s0, 0x88(sp)" 22c5 0x0 (storew 0 (+ (var sp) (bv 64 0x88)) (cast 32 false (var s0))) +d "sw s2, 0x80(sp)" 4ac1 0x0 (storew 0 (+ (var sp) (bv 64 0x80)) (cast 32 false (var s2))) +d "sw s3, 0x7c(sp)" cede 0x0 (storew 0 (+ (var sp) (bv 64 0x7c)) (cast 32 false (var s3))) +d "sw s4, 0x78(sp)" d2dc 0x0 (storew 0 (+ (var sp) (bv 64 0x78)) (cast 32 false (var s4))) +d "sw s5, 0x74(sp)" d6da 0x0 (storew 0 (+ (var sp) (bv 64 0x74)) (cast 32 false (var s5))) +d "sw s6, 0x70(sp)" dad8 0x0 (storew 0 (+ (var sp) (bv 64 0x70)) (cast 32 false (var s6))) +d "sw s7, 0x6c(sp)" ded6 0x0 (storew 0 (+ (var sp) (bv 64 0x6c)) (cast 32 false (var s7))) +d "sw s8, 0x68(sp)" e2d4 0x0 (storew 0 (+ (var sp) (bv 64 0x68)) (cast 32 false (var s8))) +d "sw s9, 0x64(sp)" e6d2 0x0 (storew 0 (+ (var sp) (bv 64 0x64)) (cast 32 false (var s9))) +d "sw s10, 0x60(sp)" ead0 0x0 (storew 0 (+ (var sp) (bv 64 0x60)) (cast 32 false (var s10))) +d "sw s11, 0x5c(sp)" eece 0x0 (storew 0 (+ (var sp) (bv 64 0x5c)) (cast 32 false (var s11))) +d "sw zero, 0x28(sp)" 02d4 0x0 (storew 0 (+ (var sp) (bv 64 0x28)) (cast 32 false (bv 64 0x0))) +d "sw zero, 0x20(sp)" 02d0 0x0 (storew 0 (+ (var sp) (bv 64 0x20)) (cast 32 false (bv 64 0x0))) +d "sw zero, 0x38(sp)" 02dc 0x0 (storew 0 (+ (var sp) (bv 64 0x38)) (cast 32 false (bv 64 0x0))) +d "sw zero, 0x30(sp)" 02d8 0x0 (storew 0 (+ (var sp) (bv 64 0x30)) (cast 32 false (bv 64 0x0))) +d "sw a5, 0x34(sp)" 3eda 0x0 (storew 0 (+ (var sp) (bv 64 0x34)) (cast 32 false (var a5))) +d "sw zero, 0x18(sp)" 02cc 0x0 (storew 0 (+ (var sp) (bv 64 0x18)) (cast 32 false (bv 64 0x0))) +d "lui s1, 0x40" b7040400 0x38 (set s1 (cast 64 (msb (<< (cast 32 false (bv 64 0x40)) (bv 32 0xc) false)) (<< (cast 32 false (bv 64 0x40)) (bv 32 0xc) false))) +d "lui a5, 0x10013" b7370110 0x0 (set a5 (cast 64 (msb (<< (cast 32 false (bv 64 0x10013)) (bv 32 0xc) false)) (<< (cast 32 false (bv 64 0x10013)) (bv 32 0xc) false))) +d "lw a5, 4(a5)" dc43 0x40 (set a5 (cast 64 (msb (loadw 0 32 (+ (var a5) (bv 64 0x4)))) (loadw 0 32 (+ (var a5) (bv 64 0x4))))) +d "blez a5, 0x64" 6351f002 0x42 (branch (|| (! (sle (bv 64 0x0) (var a5))) (== (bv 64 0x0) (var a5))) (jmp (bv 64 0x64)) (jmp (bv 64 0x46))) +d "lw ra, 0x8c(sp)" ba40 0x40 (set ra (cast 64 (msb (loadw 0 32 (+ (var sp) (bv 64 0x8c)))) (loadw 0 32 (+ (var sp) (bv 64 0x8c))))) +d "lw s0, 0x88(sp)" 2a44 0x40 (set s0 (cast 64 (msb (loadw 0 32 (+ (var sp) (bv 64 0x88)))) (loadw 0 32 (+ (var sp) (bv 64 0x88))))) +d "lw s1, 0x84(sp)" 9a44 0x40 (set s1 (cast 64 (msb (loadw 0 32 (+ (var sp) (bv 64 0x84)))) (loadw 0 32 (+ (var sp) (bv 64 0x84))))) +d "lw s2, 0x80(sp)" 0a49 0x40 (set s2 (cast 64 (msb (loadw 0 32 (+ (var sp) (bv 64 0x80)))) (loadw 0 32 (+ (var sp) (bv 64 0x80))))) +d "lw s3, 0x7c(sp)" f659 0x40 (set s3 (cast 64 (msb (loadw 0 32 (+ (var sp) (bv 64 0x7c)))) (loadw 0 32 (+ (var sp) (bv 64 0x7c))))) +d "lw s4, 0x78(sp)" 665a 0x44 (set s4 (cast 64 (msb (loadw 0 32 (+ (var sp) (bv 64 0x78)))) (loadw 0 32 (+ (var sp) (bv 64 0x78))))) +d "lw s5, 0x74(sp)" d65a 0x48 (set s5 (cast 64 (msb (loadw 0 32 (+ (var sp) (bv 64 0x74)))) (loadw 0 32 (+ (var sp) (bv 64 0x74))))) +d "lw s6, 0x70(sp)" 465b 0x40 (set s6 (cast 64 (msb (loadw 0 32 (+ (var sp) (bv 64 0x70)))) (loadw 0 32 (+ (var sp) (bv 64 0x70))))) +d "lw s7, 0x6c(sp)" b65b 0x40 (set s7 (cast 64 (msb (loadw 0 32 (+ (var sp) (bv 64 0x6c)))) (loadw 0 32 (+ (var sp) (bv 64 0x6c))))) +d "lw s8, 0x68(sp)" 265c 0x40 (set s8 (cast 64 (msb (loadw 0 32 (+ (var sp) (bv 64 0x68)))) (loadw 0 32 (+ (var sp) (bv 64 0x68))))) +d "lw s9, 0x64(sp)" 965c 0x40 (set s9 (cast 64 (msb (loadw 0 32 (+ (var sp) (bv 64 0x64)))) (loadw 0 32 (+ (var sp) (bv 64 0x64))))) +d "lw s10, 0x60(sp)" 065d 0x40 (set s10 (cast 64 (msb (loadw 0 32 (+ (var sp) (bv 64 0x60)))) (loadw 0 32 (+ (var sp) (bv 64 0x60))))) +d "lw s11, 0x5c(sp)" f64d 0x40 (set s11 (cast 64 (msb (loadw 0 32 (+ (var sp) (bv 64 0x5c)))) (loadw 0 32 (+ (var sp) (bv 64 0x5c))))) +d "addi sp, sp, 0x90" 4961 0x40 (set sp (+ (var sp) (bv 64 0x90))) +d "ret" 8280 0x40 (seq nop (jmp (& (+ (var ra) (bv 64 0x0)) (bv 64 0xfffffffffffffffe)))) +d "lw a5, 0x18(sp)" e247 0x40 (set a5 (cast 64 (msb (loadw 0 32 (+ (var sp) (bv 64 0x18)))) (loadw 0 32 (+ (var sp) (bv 64 0x18))))) +d "beqz a5, 0x2d8" 63890726 0x66 (branch (== (var a5) (bv 64 0x0)) (jmp (bv 64 0x2d8)) (jmp (bv 64 0x6a))) +d "lw s0, 0x1c(sp)" 7244 0x40 (set s0 (cast 64 (msb (loadw 0 32 (+ (var sp) (bv 64 0x1c)))) (loadw 0 32 (+ (var sp) (bv 64 0x1c))))) +d "lw a0, 0x24(sp)" 1255 0x40 (set a0 (cast 64 (msb (loadw 0 32 (+ (var sp) (bv 64 0x24)))) (loadw 0 32 (+ (var sp) (bv 64 0x24))))) +d "lw a6, 0x28(sp)" 2258 0x40 (set a6 (cast 64 (msb (loadw 0 32 (+ (var sp) (bv 64 0x28)))) (loadw 0 32 (+ (var sp) (bv 64 0x28))))) +d "lw t3, 0x38(sp)" 625e 0x40 (set t3 (cast 64 (msb (loadw 0 32 (+ (var sp) (bv 64 0x38)))) (loadw 0 32 (+ (var sp) (bv 64 0x38))))) +d "srai a5, s0, 0x1f" 9357f441 0x40 (set a5 (>> (var s0) (bv 64 0x1f) (msb (var s0)))) +d "lw a2, 0x20(sp)" 0256 0x40 (set a2 (cast 64 (msb (loadw 0 32 (+ (var sp) (bv 64 0x20)))) (loadw 0 32 (+ (var sp) (bv 64 0x20))))) +d "andi a5, a5, 0xf" bd8b 0x40 (set a5 (& (var a5) (bv 64 0xf))) +d "srai a4, a0, 0x1f" 1357f541 0x40 (set a4 (>> (var a0) (bv 64 0x1f) (msb (var a0)))) +d "lw a7, 0x30(sp)" c258 0x40 (set a7 (cast 64 (msb (loadw 0 32 (+ (var sp) (bv 64 0x30)))) (loadw 0 32 (+ (var sp) (bv 64 0x30))))) +d "add a3, a5, a6" b3860701 0x80 (set a3 (+ (var a5) (var a6))) +d "sub s2, t3, a6" 33090e41 0x80 (set s2 (- (var t3) (var a6))) +d "andi a4, a4, 0x3f" 1377f703 0x80 (set a4 (& (var a4) (bv 64 0x3f))) +d "lw a6, 0x34(sp)" 5258 0x80 (set a6 (cast 64 (msb (loadw 0 32 (+ (var sp) (bv 64 0x34)))) (loadw 0 32 (+ (var sp) (bv 64 0x34))))) +d "add a1, a4, a2" b305c700 0x80 (set a1 (+ (var a4) (var a2))) +d "sltu a4, a1, a4" 33b7e500 0x80 (set a4 (ite (&& (ule (var a1) (var a4)) (! (== (var a1) (var a4)))) (bv 64 0x1) (bv 64 0x0))) +d "sub a2, a7, a2" 3386c840 0x80 (set a2 (- (var a7) (var a2))) +d "sltu s7, a3, a5" b3bbf600 0x80 (set s7 (ite (&& (ule (var a3) (var a5)) (! (== (var a3) (var a5)))) (bv 64 0x1) (bv 64 0x0))) +d "sltu a7, a7, a2" b3b8c800 0x80 (set a7 (ite (&& (ule (var a7) (var a2)) (! (== (var a7) (var a2)))) (bv 64 0x1) (bv 64 0x0))) +d "add a5, a4, a0" b307a700 0x80 (set a5 (+ (var a4) (var a0))) +d "mv a4, a2" 3287 0x80 (set a4 (var a2)) +d "sub a2, a6, a0" 3306a840 0x80 (set a2 (- (var a6) (var a0))) +d "sltu a6, t3, s2" 33382e01 0x80 (set a6 (ite (&& (ule (var t3) (var s2)) (! (== (var t3) (var s2)))) (bv 64 0x1) (bv 64 0x0))) +d "lw t3, 0x3c(sp)" 725e 0x80 (set t3 (cast 64 (msb (loadw 0 32 (+ (var sp) (bv 64 0x3c)))) (loadw 0 32 (+ (var sp) (bv 64 0x3c))))) +d "mv t1, a0" 2a83 0x80 (set t1 (var a0)) +d "srli a1, a1, 6" 9981 0x80 (set a1 (>> (var a1) (bv 64 0x6) false)) +d "slli a0, a5, 0x1a" 1395a701 0x80 (set a0 (<< (var a5) (bv 64 0x1a) false)) +d "sw a4, 0x40(sp)" bac0 0x80 (storew 0 (+ (var sp) (bv 64 0x40)) (cast 32 false (var a4))) +d "sub a4, a2, a7" 33071641 0x80 (set a4 (- (var a2) (var a7))) +d "add s7, s7, s0" a29b 0xc0 (set s7 (+ (var s7) (var s0))) +d "sw a4, 0x44(sp)" bac2 0xc0 (storew 0 (+ (var sp) (bv 64 0x44)) (cast 32 false (var a4))) +d "srai a5, a5, 6" 9987 0xc0 (set a5 (>> (var a5) (bv 64 0x6) (msb (var a5)))) +d "or a4, a0, a1" 3367b500 0xc0 (set a4 (| (var a0) (var a1))) +d "slli s8, s7, 0x1c" 139ccb01 0xc0 (set s8 (<< (var s7) (bv 64 0x1c) false)) +d "sub s0, t3, s0" 33048e40 0xc0 (set s0 (- (var t3) (var s0))) +d "srli a3, a3, 4" 9182 0xc0 (set a3 (>> (var a3) (bv 64 0x4) false)) +d "sw a4, 0x10(sp)" 3ac8 0xc0 (storew 0 (+ (var sp) (bv 64 0x10)) (cast 32 false (var a4))) +d "sw a5, 0x14(sp)" 3eca 0xc0 (storew 0 (+ (var sp) (bv 64 0x14)) (cast 32 false (var a5))) +d "lui a4, 1" 0567 0xc0 (set a4 (cast 64 (msb (<< (cast 32 false (bv 64 0x1)) (bv 32 0xc) false)) (<< (cast 32 false (bv 64 0x1)) (bv 32 0xc) false))) +d "sub s0, s0, a6" 33040441 0xc0 (set s0 (- (var s0) (var a6))) +d "or s8, s8, a3" 336cdc00 0xc0 (set s8 (| (var s8) (var a3))) +d "srai s7, s7, 4" 93db4b40 0xc0 (set s7 (>> (var s7) (bv 64 0x4) (msb (var s7)))) +d "blt t1, a4, 0x2d4" 6347e31e 0xe6 (branch (&& (sle (var t1) (var a4)) (! (== (var t1) (var a4)))) (jmp (bv 64 0x2d4)) (jmp (bv 64 0xea))) +d "lw a5, 0x1c(sp)" f247 0xc0 (set a5 (cast 64 (msb (loadw 0 32 (+ (var sp) (bv 64 0x1c)))) (loadw 0 32 (+ (var sp) (bv 64 0x1c))))) +d "lui a4, 1" 0567 0xc0 (set a4 (cast 64 (msb (<< (cast 32 false (bv 64 0x1)) (bv 32 0xc) false)) (<< (cast 32 false (bv 64 0x1)) (bv 32 0xc) false))) +d "blt a5, a4, 0x2d4" 63c3e71e 0xee (branch (&& (sle (var a5) (var a4)) (! (== (var a5) (var a4)))) (jmp (bv 64 0x2d4)) (jmp (bv 64 0xf2))) +d "srli a5, s8, 0x1d" 9357dc01 0xc0 (set a5 (>> (var s8) (bv 64 0x1d) false)) +d "slli a4, s7, 3" 13973b00 0xc0 (set a4 (<< (var s7) (bv 64 0x3) false)) +d "or a5, a5, a4" d98f 0xc0 (set a5 (| (var a5) (var a4))) +d "sw a5, 0x4c(sp)" bec6 0xc0 (storew 0 (+ (var sp) (bv 64 0x4c)) (cast 32 false (var a5))) +d "slli a5, s8, 3" 93173c00 0xc0 (set a5 (<< (var s8) (bv 64 0x3) false)) +d "addi a5, sp, 8" 3c00 0x100 (set a5 (+ (var sp) (bv 64 0x8))) +d "li s11, 0xff" 930df00f 0x100 (set s11 (+ (bv 64 0x0) (bv 64 0xff))) +d "sw a5, 0x48(sp)" bec4 0x100 (storew 0 (+ (var sp) (bv 64 0x48)) (cast 32 false (var a5))) +d "sw s2, 0xc(sp)" 4ac6 0x100 (storew 0 (+ (var sp) (bv 64 0xc)) (cast 32 false (var s2))) +d "li a5, 4" 9147 0x100 (set a5 (bv 64 0x4)) +d "li s2, 0" 0149 0x100 (set s2 (bv 64 0x0)) +d "mv s3, s11" ee89 0x100 (set s3 (var s11)) +d "sw a5, 0x2c(sp)" 3ed6 0x100 (storew 0 (+ (var sp) (bv 64 0x2c)) (cast 32 false (var a5))) +d "li s6, 0x10" 414b 0x100 (set s6 (bv 64 0x10)) +d "li s9, 8" a14c 0x100 (set s9 (bv 64 0x8)) +d "mv s11, s2" ca8d 0x100 (set s11 (var s2)) +d "lw s10, 0x40(sp)" 064d 0x100 (set s10 (cast 64 (msb (loadw 0 32 (+ (var sp) (bv 64 0x40)))) (loadw 0 32 (+ (var sp) (bv 64 0x40))))) +d "lw s5, 0x44(sp)" 964a 0x100 (set s5 (cast 64 (msb (loadw 0 32 (+ (var sp) (bv 64 0x44)))) (loadw 0 32 (+ (var sp) (bv 64 0x44))))) +d "li s2, 0x80" 13090008 0x100 (set s2 (+ (bv 64 0x0) (bv 64 0x80))) +d "mv s4, s3" 4e8a 0x100 (set s4 (var s3)) +d "mv s3, s2" ca89 0x100 (set s3 (var s2)) +d "lw t2, 0xc(sp)" b243 0x100 (set t2 (cast 64 (msb (loadw 0 32 (+ (var sp) (bv 64 0xc)))) (loadw 0 32 (+ (var sp) (bv 64 0xc))))) +d "mv t6, s0" a28f 0x100 (set t6 (var s0)) +d "li ra, 0" 8140 0x100 (set ra (bv 64 0x0)) +d "li s2, 0" 0149 0x100 (set s2 (bv 64 0x0)) +d "li a1, 0" 8145 0x100 (set a1 (bv 64 0x0)) +d "li a4, 0" 0147 0x100 (set a4 (bv 64 0x0)) +d "li t3, 0" 014e 0x100 (set t3 (bv 64 0x0)) +d "li a6, 0" 0148 0x100 (set a6 (bv 64 0x0)) +d "li a5, 0" 8147 0x100 (set a5 (bv 64 0x0)) +d "li a3, 0" 8146 0x100 (set a3 (bv 64 0x0)) +d "li t1, 0" 0143 0x100 (set t1 (bv 64 0x0)) +d "li a2, 0" 0146 0x100 (set a2 (bv 64 0x0)) +d "li a0, 0" 0145 0x100 (set a0 (bv 64 0x0)) +d "j 0x176" 25a8 0x13e (seq nop (jmp (bv 64 0x176))) +d "mul a4, a0, a2" 3307c502 0x140 (set a4 (* (var a0) (var a2))) +d "mulhu t1, a2, a2" 3333c602 0x140 (set t1 (cast 64 false (>> (* (cast 128 false (var a2)) (cast 128 false (var a2))) (bv 8 0x40) false))) +d "slli a4, a4, 1" 0607 0x140 (set a4 (<< (var a4) (bv 64 0x1) false)) +d "mul a7, a5, a6" b3880703 0x140 (set a7 (* (var a5) (var a6))) +d "add t1, t1, a4" 3a93 0x140 (set t1 (+ (var t1) (var a4))) +d "mul a3, a2, a2" b306c602 0x140 (set a3 (* (var a2) (var a2))) +d "slli a7, a7, 1" 8608 0x140 (set a7 (<< (var a7) (bv 64 0x1) false)) +d "mulhu t3, a6, a6" 333e0803 0x140 (set t3 (cast 64 false (>> (* (cast 128 false (var a6)) (cast 128 false (var a6))) (bv 8 0x40) false))) +d "mul a4, a6, a6" 33070803 0x140 (set a4 (* (var a6) (var a6))) +d "add t3, t3, a7" 469e 0x140 (set t3 (+ (var t3) (var a7))) +d "add t5, t1, t3" 330fc301 0x140 (set t5 (+ (var t1) (var t3))) +d "add t4, a3, a4" b38ee600 0x140 (set t4 (+ (var a3) (var a4))) +d "sltu a7, t4, a3" b3b8de00 0x140 (set a7 (ite (&& (ule (var t4) (var a3)) (! (== (var t4) (var a3)))) (bv 64 0x1) (bv 64 0x0))) +d "add a7, a7, t5" fa98 0x140 (set a7 (+ (var a7) (var t5))) +d "blt s1, a7, 0x2c6" 63cc1415 0x16e (branch (&& (sle (var s1) (var a7)) (! (== (var s1) (var a7)))) (jmp (bv 64 0x2c6)) (jmp (bv 64 0x172))) +d "beq a7, s1, 0x2c2" 63889814 0x172 (branch (== (var a7) (var s1)) (jmp (bv 64 0x2c2)) (jmp (bv 64 0x176))) +d "sub a4, a3, a4" 3387e640 0x140 (set a4 (- (var a3) (var a4))) +d "sub t3, t1, t3" 330ec341 0x140 (set t3 (- (var t1) (var t3))) +d "sltu a3, ra, zero" b3b60000 0x140 (set a3 (ite (&& (ule (var ra) (bv 64 0x0)) (! (== (var ra) (bv 64 0x0)))) (bv 64 0x1) (bv 64 0x0))) +d "add a7, a4, s10" b308a701 0x180 (set a7 (+ (var a4) (var s10))) +d "sub a3, t3, a3" b306de40 0x180 (set a3 (- (var t3) (var a3))) +d "sltu a4, a7, a4" 33b7e800 0x180 (set a4 (ite (&& (ule (var a7) (var a4)) (! (== (var a7) (var a4)))) (bv 64 0x1) (bv 64 0x0))) +d "add a3, a3, s5" d696 0x180 (set a3 (+ (var a3) (var s5))) +d "add a3, a3, a4" ba96 0x180 (set a3 (+ (var a3) (var a4))) +d "mul a5, a5, a2" b387c702 0x180 (set a5 (* (var a5) (var a2))) +d "slli t1, a3, 8" 13938600 0x180 (set t1 (<< (var a3) (bv 64 0x8) false)) +d "addi a1, a1, 1" 8505 0x180 (set a1 (+ (var a1) (bv 64 0x1))) +d "mul a4, a0, a6" 33070503 0x180 (set a4 (* (var a0) (var a6))) +d "srai a0, a3, 0x18" 13d58641 0x180 (set a0 (>> (var a3) (bv 64 0x18) (msb (var a3)))) +d "mulhu a3, a6, a2" b336c802 0x180 (set a3 (cast 64 false (>> (* (cast 128 false (var a6)) (cast 128 false (var a2))) (bv 8 0x40) false))) +d "add a4, a4, a5" 3e97 0x180 (set a4 (+ (var a4) (var a5))) +d "mul a6, a6, a2" 3308c802 0x180 (set a6 (* (var a6) (var a2))) +d "add a4, a4, a3" 3697 0x180 (set a4 (+ (var a4) (var a3))) +d "srli a2, a7, 0x18" 13d68801 0x180 (set a2 (>> (var a7) (bv 64 0x18) false)) +d "slli a4, a4, 1" 0607 0x180 (set a4 (<< (var a4) (bv 64 0x1) false)) +d "or a2, t1, a2" 3366c300 0x180 (set a2 (| (var t1) (var a2))) +d "slli a7, a6, 1" 93181800 0x180 (set a7 (<< (var a6) (bv 64 0x1) false)) +d "srli a3, a6, 0x1f" 9356f801 0x180 (set a3 (>> (var a6) (bv 64 0x1f) false)) +d "add a5, a7, t2" b3877800 0x1c0 (set a5 (+ (var a7) (var t2))) +d "or a4, a4, a3" 558f 0x1c0 (set a4 (| (var a4) (var a3))) +d "srli a6, a5, 0x18" 13d88701 0x1c0 (set a6 (>> (var a5) (bv 64 0x18) false)) +d "add a4, a4, t6" 7e97 0x1c0 (set a4 (+ (var a4) (var t6))) +d "sltu a5, a5, a7" b3b71701 0x1c0 (set a5 (ite (&& (ule (var a5) (var a7)) (! (== (var a5) (var a7)))) (bv 64 0x1) (bv 64 0x0))) +d "add a4, a4, a5" 3e97 0x1c0 (set a4 (+ (var a4) (var a5))) +d "slli a5, a4, 8" 93178700 0x1c0 (set a5 (<< (var a4) (bv 64 0x8) false)) +d "or a6, a5, a6" 33e80701 0x1c0 (set a6 (| (var a5) (var a6))) +d "srai a5, a4, 0x18" 93578741 0x1c0 (set a5 (>> (var a4) (bv 64 0x18) (msb (var a4)))) +d "bne a1, s6, 0x140" e39065f7 0x1e0 (branch (! (== (var a1) (var s6))) (jmp (bv 64 0x140)) (jmp (bv 64 0x1e4))) +d "li a5, 0" 8147 0x1c0 (set a5 (bv 64 0x0)) +d "add a4, t2, s8" 33878301 0x1c0 (set a4 (+ (var t2) (var s8))) +d "sltu a3, a4, t2" b3367700 0x1c0 (set a3 (ite (&& (ule (var a4) (var t2)) (! (== (var a4) (var t2)))) (bv 64 0x1) (bv 64 0x0))) +d "or s2, a5, s2" 33e92701 0x1c0 (set s2 (| (var a5) (var s2))) +d "add t6, t6, s7" de9f 0x1c0 (set t6 (+ (var t6) (var s7))) +d "addi ra, ra, 1" 8500 0x1c0 (set ra (+ (var ra) (bv 64 0x1))) +d "andi s2, s2, 0xff" 1379f90f 0x1c0 (set s2 (& (var s2) (bv 64 0xff))) +d "mv t2, a4" ba83 0x1c0 (set t2 (var a4)) +d "add t6, t6, a3" b69f 0x1c0 (set t6 (+ (var t6) (var a3))) +d "ori a5, a5, 0x89" 93e79708 0x0 (set a5 (| (var a5) (bv 64 0x89))) +d "xori a5, a5, 0x431" 93c71743 0x0 (set a5 (^ (var a5) (bv 64 0x431))) +d "jalr ra" e7800000 0x30 (seq (set ra (bv 64 0x34)) (jmp (& (+ (var ra) (bv 64 0x0)) (bv 64 0xfffffffffffffffe)))) +d "slti zero, ra, 0xc" 13a0c000 0x0 nop +d "sltiu zero, ra, 0xc" 13b0c000 0x0 nop +d "slti t0, ra, 0xc" 93a2c000 0x0 (set t0 (ite (&& (sle (var ra) (bv 64 0xc)) (! (== (var ra) (bv 64 0xc)))) (bv 64 0x1) (bv 64 0x0))) +d "sltiu t1, sp, 0x14" 13334101 0x0 (set t1 (ite (&& (ule (var sp) (bv 64 0x14)) (! (== (var sp) (bv 64 0x14)))) (bv 64 0x1) (bv 64 0x0))) +d "jal t0, 0x14" ef024001 0x0 (seq (set t0 (bv 64 0x4)) (jmp (bv 64 0x14))) +d "jal t0, 0x4a" ef024001 0x36 (seq (set t0 (bv 64 0x3a)) (jmp (bv 64 0x4a))) From 3275ee2b1bcbadd45be9af811f3acafa64f6e321 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D9=85=D8=B5=D8=B7=D9=81=D9=8A=20=D9=85=D8=AD=D9=85=D9=88?= =?UTF-8?q?=D8=AF=20=D9=83=D9=85=D8=A7=D9=84=20=D8=A7=D9=84=D8=AF=D9=8A?= =?UTF-8?q?=D9=86?= <48567303+moste00@users.noreply.github.com> Date: Sun, 28 Jun 2026 00:44:48 +0300 Subject: [PATCH 7/8] add previously untested instructions test cases for lifting --- test/db/asm/riscv_32 | 148 +++++++++++++++++++++++++++++++++++++++++++ test/db/asm/riscv_64 | 148 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 296 insertions(+) diff --git a/test/db/asm/riscv_32 b/test/db/asm/riscv_32 index d2036956000..aafac96179f 100644 --- a/test/db/asm/riscv_32 +++ b/test/db/asm/riscv_32 @@ -199,3 +199,151 @@ d "slti t0, ra, 0xc" 93a2c000 0x0 (set t0 (ite (&& (sle (var ra) (bv 32 0xc)) (! d "sltiu t1, sp, 0x14" 13334101 0x0 (set t1 (ite (&& (ule (var sp) (bv 32 0x14)) (! (== (var sp) (bv 32 0x14)))) (bv 32 0x1) (bv 32 0x0))) d "jal t0, 0x14" ef024001 0x0 (seq (set t0 (bv 32 0x4)) (jmp (bv 32 0x14))) d "jal t0, 0x4a" ef024001 0x36 (seq (set t0 (bv 32 0x3a)) (jmp (bv 32 0x4a))) +# ----------------------------- AUIPC ----------------------------- +d "auipc a0, 0x4a" 17a50400 0x0 (set a0 (+ (bv 32 0x0) (<< (bv 32 0x4a) (bv 32 0xc) false))) +d "auipc s5, 0xc8" 978a0c00 0x0 (set s5 (+ (bv 32 0x0) (<< (bv 32 0xc8) (bv 32 0xc) false))) +d "auipc s9, 0x2c" 97cc0200 0x0 (set s9 (+ (bv 32 0x0) (<< (bv 32 0x2c) (bv 32 0xc) false))) +# ----------------------------- AND ----------------------------- +d "and s4, a2, a4" 337ae600 0x0 (set s4 (& (var a2) (var a4))) +d "and a4, a5, s5" 33f75701 0x0 (set a4 (& (var a5) (var s5))) +d "and a5, a5, s10" b3f7a701 0x0 (set a5 (& (var a5) (var s10))) +# ----------------------------- XOR ----------------------------- +d "xor a5, a3, a4" b3c7e600 0x0 (set a5 (^ (var a3) (var a4))) +d "xor a0, a1, a6" 33c50501 0x0 (set a0 (^ (var a1) (var a6))) +d "xor t4, s11, s2" b3ce2d01 0x0 (set t4 (^ (var s11) (var s2))) +# ----------------------------- SLT ----------------------------- +d "slt a5, s4, a5" b327fa00 0x0 (set a5 (ite (&& (sle (var s4) (var a5)) (! (== (var s4) (var a5)))) (bv 32 0x1) (bv 32 0x0))) +d "slt t3, a2, a4" 332ee600 0x0 (set t3 (ite (&& (sle (var a2) (var a4)) (! (== (var a2) (var a4)))) (bv 32 0x1) (bv 32 0x0))) +d "slt a3, a5, a3" b3a6d700 0x0 (set a3 (ite (&& (sle (var a5) (var a3)) (! (== (var a5) (var a3)))) (bv 32 0x1) (bv 32 0x0))) +# ----------------------------- SLL ----------------------------- +d "sll a5, a5, a1" b397b700 0x0 (set a5 (<< (var a5) (& (var a1) (bv 32 0x1f)) false)) +d "sll s10, s3, s10" 339da901 0x0 (set s10 (<< (var s3) (& (var s10) (bv 32 0x1f)) false)) +d "sll a1, a1, t5" b395e501 0x0 (set a1 (<< (var a1) (& (var t5) (bv 32 0x1f)) false)) +# ----------------------------- SRL ----------------------------- +d "srl a5, a5, a4" b3d7e700 0x0 (set a5 (>> (var a5) (& (var a4) (bv 32 0x1f)) false)) +d "srl a6, a3, a4" 33d8e600 0x0 (set a6 (>> (var a3) (& (var a4) (bv 32 0x1f)) false)) +d "srl t3, t3, t4" 335ede01 0x0 (set t3 (>> (var t3) (& (var t4) (bv 32 0x1f)) false)) +# ----------------------------- SRA ----------------------------- +d "sra a4, a0, a4" 3357e540 0x0 (set a4 (>> (var a0) (& (var a4) (bv 32 0x1f)) (msb (var a0)))) +d "sra a4, a1, a4" 33d7e540 0x0 (set a4 (>> (var a1) (& (var a4) (bv 32 0x1f)) (msb (var a1)))) +d "sra a2, a0, a2" 3356c540 0x0 (set a2 (>> (var a0) (& (var a2) (bv 32 0x1f)) (msb (var a0)))) +# ----------------------------- LB ----------------------------- +d "lb a4, 0x108(a0)" 03078510 0x0 (set a4 (cast 32 (msb (loadw 0 8 (+ (var a0) (bv 32 0x108)))) (loadw 0 8 (+ (var a0) (bv 32 0x108))))) +d "lb a7, 0(t3)" 83080e00 0x0 (set a7 (cast 32 (msb (loadw 0 8 (+ (var t3) (bv 32 0x0)))) (loadw 0 8 (+ (var t3) (bv 32 0x0))))) +d "lb a2, 1(a4)" 03061700 0x0 (set a2 (cast 32 (msb (loadw 0 8 (+ (var a4) (bv 32 0x1)))) (loadw 0 8 (+ (var a4) (bv 32 0x1))))) +# ----------------------------- LH ----------------------------- +d "lh a5, 6(a6)" 83176800 0x0 (set a5 (cast 32 (msb (loadw 0 16 (+ (var a6) (bv 32 0x6)))) (loadw 0 16 (+ (var a6) (bv 32 0x6))))) +d "lh a5, 0x334(s7)" 83974b33 0x0 (set a5 (cast 32 (msb (loadw 0 16 (+ (var s7) (bv 32 0x334)))) (loadw 0 16 (+ (var s7) (bv 32 0x334))))) +d "lh a4, -0x148(a4)" 031787eb 0x0 (set a4 (cast 32 (msb (loadw 0 16 (+ (var a4) (bv 32 0xfffffeb8)))) (loadw 0 16 (+ (var a4) (bv 32 0xfffffeb8))))) +# ----------------------------- LW ----------------------------- +d "lw s1, 8(s7)" 83a48b00 0x0 (set s1 (loadw 0 32 (+ (var s7) (bv 32 0x8)))) +d "lw a1, 0x18(sp)" e245 0x0 (set a1 (loadw 0 32 (+ (var sp) (bv 32 0x18)))) +d "lw a4, 0x9c(a4)" 0327c709 0x0 (set a4 (loadw 0 32 (+ (var a4) (bv 32 0x9c)))) +# ----------------------------- LBU ----------------------------- +d "lbu a4, 0x337(s1)" 03c77433 0x0 (set a4 (cast 32 false (loadw 0 8 (+ (var s1) (bv 32 0x337))))) +d "lbu a4, 0x50(sp)" 03470105 0x0 (set a4 (cast 32 false (loadw 0 8 (+ (var sp) (bv 32 0x50))))) +d "lbu a3, -0x77(s0)" 834694f8 0x0 (set a3 (cast 32 false (loadw 0 8 (+ (var s0) (bv 32 0xffffff89))))) +# ----------------------------- LHU ----------------------------- +d "lhu a5, 4(s0)" 83574400 0x0 (set a5 (cast 32 false (loadw 0 16 (+ (var s0) (bv 32 0x4))))) +d "lhu a5, 0xc(s11)" 83d7cd00 0x0 (set a5 (cast 32 false (loadw 0 16 (+ (var s11) (bv 32 0xc))))) +d "lhu a2, 0xa4(sp)" 0356410a 0x0 (set a2 (cast 32 false (loadw 0 16 (+ (var sp) (bv 32 0xa4))))) +# ----------------------------- SB ----------------------------- +d "sb a1, 3(s0)" a301b400 0x0 (storew 0 (+ (var s0) (bv 32 0x3)) (cast 8 false (var a1))) +d "sb a1, -0x74(s0)" 2306b4f8 0x0 (storew 0 (+ (var s0) (bv 32 0xffffff8c)) (cast 8 false (var a1))) +d "sb a3, -1(a4)" a30fd7fe 0x0 (storew 0 (+ (var a4) (bv 32 0xffffffff)) (cast 8 false (var a3))) +# ----------------------------- SH ----------------------------- +d "sh a5, 0(s1)" 2390f400 0x0 (storew 0 (+ (var s1) (bv 32 0x0)) (cast 16 false (var a5))) +d "sh a0, 0x80(s1)" 2390a408 0x0 (storew 0 (+ (var s1) (bv 32 0x80)) (cast 16 false (var a0))) +d "sh s1, 0x32(a5)" 23999702 0x0 (storew 0 (+ (var a5) (bv 32 0x32)) (cast 16 false (var s1))) +# ----------------------------- SW ----------------------------- +d "sw a5, 0x9c(s1)" 23aef408 0x0 (storew 0 (+ (var s1) (bv 32 0x9c)) (var a5)) +d "sw a5, 0(a4)" 1cc3 0x0 (storew 0 (+ (var a4) (bv 32 0x0)) (var a5)) +d "sw s3, -0x6c0(a5)" 23a03795 0x0 (storew 0 (+ (var a5) (bv 32 0xfffff940)) (var s3)) +# ----------------------------- BLTU ----------------------------- +d "bltu a5, s4, 0x48" 63e44705 0x0 (branch (&& (ule (var a5) (var s4)) (! (== (var a5) (var s4)))) (jmp (bv 32 0x48)) (jmp (bv 32 0x4))) +d "bltu a5, a3, 0xfffffff0" e3e8d7fe 0x0 (branch (&& (ule (var a5) (var a3)) (! (== (var a5) (var a3)))) (jmp (bv 32 0xfffffff0)) (jmp (bv 32 0x4))) +d "bltu t3, a1, 0xffffffe6" e363befe 0x0 (branch (&& (ule (var t3) (var a1)) (! (== (var t3) (var a1)))) (jmp (bv 32 0xffffffe6)) (jmp (bv 32 0x4))) +# ----------------------------- BGEU ----------------------------- +d "bgeu a3, a4, 0x1ae" 63f7e61a 0x0 (branch (|| (! (ule (var a3) (var a4))) (== (var a3) (var a4))) (jmp (bv 32 0x1ae)) (jmp (bv 32 0x4))) +d "bgeu s2, a5, 0xfffffff6" e37bf9fe 0x0 (branch (|| (! (ule (var s2) (var a5))) (== (var s2) (var a5))) (jmp (bv 32 0xfffffff6)) (jmp (bv 32 0x4))) +d "bgeu s7, s0, 0xffffff64" e3f28bf6 0x0 (branch (|| (! (ule (var s7) (var s0))) (== (var s7) (var s0))) (jmp (bv 32 0xffffff64)) (jmp (bv 32 0x4))) +# ----------------------------- FENCE ----------------------------- +d "fence rw, rw" 0f003003 0x0 nop +d "fence rw, w" 0f001003 0x0 nop +d "fence r, rw" 0f003002 0x0 nop +# ----------------------------- FENCE_I ----------------------------- +d "fence.i" 0f100000 0x0 nop +d "fence.i" 0f100000 0x0 nop +d "fence.i" 0f100000 0x0 nop +# ----------------------------- ECALL ----------------------------- +d "ecall" 73000000 0x0 (goto ecall) +d "ecall" 73000000 0x0 (goto ecall) +d "ecall" 73000000 0x0 (goto ecall) +# ----------------------------- EBREAK ----------------------------- +d "ebreak" 73001000 0x0 (goto ebreak) +d "ebreak" 73001000 0x0 (goto ebreak) +d "ebreak" 73001000 0x0 (goto ebreak) +# ----------------------------- MULH ----------------------------- +d "mulh t0, t1, t2" b3127302 0x0 (set t0 (cast 32 false (>> (* (cast 64 (msb (var t1)) (var t1)) (cast 64 (msb (var t2)) (var t2))) (bv 8 0x20) false))) +d "mulh a0, a1, a2" 3395c502 0x0 (set a0 (cast 32 false (>> (* (cast 64 (msb (var a1)) (var a1)) (cast 64 (msb (var a2)) (var a2))) (bv 8 0x20) false))) +d "mulh t3, t4, t5" 339eee03 0x0 (set t3 (cast 32 false (>> (* (cast 64 (msb (var t4)) (var t4)) (cast 64 (msb (var t5)) (var t5))) (bv 8 0x20) false))) +# ----------------------------- MULHSU ----------------------------- +d "mulhsu t0, t1, t2" b3227302 0x0 (set t0 (cast 32 false (>> (* (cast 64 (msb (var t1)) (var t1)) (cast 64 false (var t2))) (bv 8 0x20) false))) +d "mulhsu a0, a1, a2" 33a5c502 0x0 (set a0 (cast 32 false (>> (* (cast 64 (msb (var a1)) (var a1)) (cast 64 false (var a2))) (bv 8 0x20) false))) +d "mulhsu t3, t4, t5" 33aeee03 0x0 (set t3 (cast 32 false (>> (* (cast 64 (msb (var t4)) (var t4)) (cast 64 false (var t5))) (bv 8 0x20) false))) +# ----------------------------- DIV ----------------------------- +d "div a3, a3, a7" b3c61603 0x0 (set a3 (sdiv (var a3) (var a7))) +d "div t4, t6, t4" b3cedf03 0x0 (set t4 (sdiv (var t6) (var t4))) +d "div a4, a4, a3" 3347d702 0x0 (set a4 (sdiv (var a4) (var a3))) +# ----------------------------- DIVU ----------------------------- +d "divu a6, s2, s10" 3358a903 0x0 (set a6 (div (var s2) (var s10))) +d "divu s7, a5, t5" b3dbe703 0x0 (set s7 (div (var a5) (var t5))) +d "divu s1, a0, s2" b3542503 0x0 (set s1 (div (var a0) (var s2))) +# ----------------------------- REM ----------------------------- +d "rem t6, a4, a7" b36f1703 0x0 (set t6 (smod (var a4) (var a7))) +d "rem a5, a0, a4" b367e502 0x0 (set a5 (smod (var a0) (var a4))) +d "rem a5, t0, a5" b3e7f202 0x0 (set a5 (smod (var t0) (var a5))) +# ----------------------------- REMU ----------------------------- +d "remu a3, s1, a3" b3f6d402 0x0 (set a3 (mod (var s1) (var a3))) +d "remu a6, a6, s4" 33784803 0x0 (set a6 (mod (var a6) (var s4))) +d "remu a1, s7, s2" b3f52b03 0x0 (set a1 (mod (var s7) (var s2))) +# ----------------------------- C_NOP ----------------------------- +d "nop" 0100 0x0 nop +d "c.nop 1" 0500 0x0 nop +d "c.nop 2" 0900 0x0 nop +# ----------------------------- C_JALR ----------------------------- +d "jalr ra" 8290 0x0 (seq (set ra (bv 32 0x2)) (jmp (& (+ (var ra) (bv 32 0x0)) (bv 32 0xfffffffe)))) +d "jalr s0" 0294 0x0 (seq (set ra (bv 32 0x2)) (jmp (& (+ (var s0) (bv 32 0x0)) (bv 32 0xfffffffe)))) +d "jalr a5" 8297 0x0 (seq (set ra (bv 32 0x2)) (jmp (& (+ (var a5) (bv 32 0x0)) (bv 32 0xfffffffe)))) +# ----------------------------- C_EBREAK ----------------------------- +d "ebreak" 0290 0x0 (goto ebreak) +d "ebreak" 0290 0x0 (goto ebreak) +d "ebreak" 0290 0x0 (goto ebreak) +# ----------------------------- C_BEQZ ----------------------------- +d "beqz a0, 0" 01c1 0x0 (branch (== (var a0) (bv 32 0x0)) (jmp (bv 32 0x0)) (jmp (bv 32 0x2))) +d "beqz a1, 2" 89c1 0x0 (branch (== (var a1) (bv 32 0x0)) (jmp (bv 32 0x2)) (jmp (bv 32 0x2))) +d "beqz a5, 0xfffffffc" f5df 0x0 (branch (== (var a5) (bv 32 0x0)) (jmp (bv 32 0xfffffffc)) (jmp (bv 32 0x2))) +# ----------------------------- C_BNEZ ----------------------------- +d "bnez a0, 0" 01e1 0x0 (branch (! (== (var a0) (bv 32 0x0))) (jmp (bv 32 0x0)) (jmp (bv 32 0x2))) +d "bnez a1, 2" 89e1 0x0 (branch (! (== (var a1) (bv 32 0x0))) (jmp (bv 32 0x2)) (jmp (bv 32 0x2))) +d "bnez a5, 0xfffffffc" f5ff 0x0 (branch (! (== (var a5) (bv 32 0x0))) (jmp (bv 32 0xfffffffc)) (jmp (bv 32 0x2))) +# ----------------------------- C_SW ----------------------------- +d "sw a0, 0(s0)" 08c0 0x0 (storew 0 (+ (var s0) (bv 32 0x0)) (var a0)) +d "sw a1, 4(s1)" ccc0 0x0 (storew 0 (+ (var s1) (bv 32 0x4)) (var a1)) +d "sw a5, 0x7c(a5)" fcdf 0x0 (storew 0 (+ (var a5) (bv 32 0x7c)) (var a5)) +# ----------------------------- C_JAL ----------------------------- +d "jal 0xfffffff4" d53f 0x0 (seq (set ra (bv 32 0x2)) (jmp (bv 32 0xfffffff4))) +d "jal 2" 0920 0x0 (seq (set ra (bv 32 0x2)) (jmp (bv 32 0x2))) +d "jal 0xfffffff6" dd3f 0x0 (seq (set ra (bv 32 0x2)) (jmp (bv 32 0xfffffff6))) +# ----------------------------- C_SUB ----------------------------- +d "sub a0, a0, a1" 0d8d 0x0 (set a0 (- (var a0) (var a1))) +d "sub a2, a2, a3" 158e 0x0 (set a2 (- (var a2) (var a3))) +d "sub a5, a5, a4" 998f 0x0 (set a5 (- (var a5) (var a4))) +# ----------------------------- C_AND ----------------------------- +d "and a0, a0, a1" 6d8d 0x0 (set a0 (& (var a0) (var a1))) +d "and a2, a2, a3" 758e 0x0 (set a2 (& (var a2) (var a3))) +d "and a5, a5, a4" f98f 0x0 (set a5 (& (var a5) (var a4))) +# ----------------------------- C_XOR ----------------------------- +d "xor a0, a0, a1" 2d8d 0x0 (set a0 (^ (var a0) (var a1))) +d "xor a2, a2, a3" 358e 0x0 (set a2 (^ (var a2) (var a3))) +d "xor a5, a5, a4" b98f 0x0 (set a5 (^ (var a5) (var a4))) diff --git a/test/db/asm/riscv_64 b/test/db/asm/riscv_64 index d13c2a527dc..278a07e9a82 100644 --- a/test/db/asm/riscv_64 +++ b/test/db/asm/riscv_64 @@ -199,3 +199,151 @@ d "slti t0, ra, 0xc" 93a2c000 0x0 (set t0 (ite (&& (sle (var ra) (bv 64 0xc)) (! d "sltiu t1, sp, 0x14" 13334101 0x0 (set t1 (ite (&& (ule (var sp) (bv 64 0x14)) (! (== (var sp) (bv 64 0x14)))) (bv 64 0x1) (bv 64 0x0))) d "jal t0, 0x14" ef024001 0x0 (seq (set t0 (bv 64 0x4)) (jmp (bv 64 0x14))) d "jal t0, 0x4a" ef024001 0x36 (seq (set t0 (bv 64 0x3a)) (jmp (bv 64 0x4a))) +# ----------------------------- AUIPC ----------------------------- +d "auipc a0, 0x4a" 17a50400 0x0 (set a0 (+ (bv 64 0x0) (cast 64 (msb (<< (cast 32 false (bv 64 0x4a)) (bv 32 0xc) false)) (<< (cast 32 false (bv 64 0x4a)) (bv 32 0xc) false)))) +d "auipc s5, 0xc8" 978a0c00 0x0 (set s5 (+ (bv 64 0x0) (cast 64 (msb (<< (cast 32 false (bv 64 0xc8)) (bv 32 0xc) false)) (<< (cast 32 false (bv 64 0xc8)) (bv 32 0xc) false)))) +d "auipc s9, 0x2c" 97cc0200 0x0 (set s9 (+ (bv 64 0x0) (cast 64 (msb (<< (cast 32 false (bv 64 0x2c)) (bv 32 0xc) false)) (<< (cast 32 false (bv 64 0x2c)) (bv 32 0xc) false)))) +# ----------------------------- AND ----------------------------- +d "and s4, a2, a4" 337ae600 0x0 (set s4 (& (var a2) (var a4))) +d "and a4, a5, s5" 33f75701 0x0 (set a4 (& (var a5) (var s5))) +d "and a5, a5, s10" b3f7a701 0x0 (set a5 (& (var a5) (var s10))) +# ----------------------------- XOR ----------------------------- +d "xor a5, a3, a4" b3c7e600 0x0 (set a5 (^ (var a3) (var a4))) +d "xor a0, a1, a6" 33c50501 0x0 (set a0 (^ (var a1) (var a6))) +d "xor t4, s11, s2" b3ce2d01 0x0 (set t4 (^ (var s11) (var s2))) +# ----------------------------- SLT ----------------------------- +d "slt a5, s4, a5" b327fa00 0x0 (set a5 (ite (&& (sle (var s4) (var a5)) (! (== (var s4) (var a5)))) (bv 64 0x1) (bv 64 0x0))) +d "slt t3, a2, a4" 332ee600 0x0 (set t3 (ite (&& (sle (var a2) (var a4)) (! (== (var a2) (var a4)))) (bv 64 0x1) (bv 64 0x0))) +d "slt a3, a5, a3" b3a6d700 0x0 (set a3 (ite (&& (sle (var a5) (var a3)) (! (== (var a5) (var a3)))) (bv 64 0x1) (bv 64 0x0))) +# ----------------------------- SLL ----------------------------- +d "sll a5, a5, a1" b397b700 0x0 (set a5 (<< (var a5) (& (var a1) (bv 64 0x3f)) false)) +d "sll s10, s3, s10" 339da901 0x0 (set s10 (<< (var s3) (& (var s10) (bv 64 0x3f)) false)) +d "sll a1, a1, t5" b395e501 0x0 (set a1 (<< (var a1) (& (var t5) (bv 64 0x3f)) false)) +# ----------------------------- SRL ----------------------------- +d "srl a5, a5, a4" b3d7e700 0x0 (set a5 (>> (var a5) (& (var a4) (bv 64 0x3f)) false)) +d "srl a6, a3, a4" 33d8e600 0x0 (set a6 (>> (var a3) (& (var a4) (bv 64 0x3f)) false)) +d "srl t3, t3, t4" 335ede01 0x0 (set t3 (>> (var t3) (& (var t4) (bv 64 0x3f)) false)) +# ----------------------------- SRA ----------------------------- +d "sra a4, a0, a4" 3357e540 0x0 (set a4 (>> (var a0) (& (var a4) (bv 64 0x3f)) (msb (var a0)))) +d "sra a4, a1, a4" 33d7e540 0x0 (set a4 (>> (var a1) (& (var a4) (bv 64 0x3f)) (msb (var a1)))) +d "sra a2, a0, a2" 3356c540 0x0 (set a2 (>> (var a0) (& (var a2) (bv 64 0x3f)) (msb (var a0)))) +# ----------------------------- LB ----------------------------- +d "lb a4, 0x108(a0)" 03078510 0x0 (set a4 (cast 64 (msb (loadw 0 8 (+ (var a0) (bv 64 0x108)))) (loadw 0 8 (+ (var a0) (bv 64 0x108))))) +d "lb a7, 0(t3)" 83080e00 0x0 (set a7 (cast 64 (msb (loadw 0 8 (+ (var t3) (bv 64 0x0)))) (loadw 0 8 (+ (var t3) (bv 64 0x0))))) +d "lb a2, 1(a4)" 03061700 0x0 (set a2 (cast 64 (msb (loadw 0 8 (+ (var a4) (bv 64 0x1)))) (loadw 0 8 (+ (var a4) (bv 64 0x1))))) +# ----------------------------- LH ----------------------------- +d "lh a5, 6(a6)" 83176800 0x0 (set a5 (cast 64 (msb (loadw 0 16 (+ (var a6) (bv 64 0x6)))) (loadw 0 16 (+ (var a6) (bv 64 0x6))))) +d "lh a5, 0x334(s7)" 83974b33 0x0 (set a5 (cast 64 (msb (loadw 0 16 (+ (var s7) (bv 64 0x334)))) (loadw 0 16 (+ (var s7) (bv 64 0x334))))) +d "lh a4, -0x148(a4)" 031787eb 0x0 (set a4 (cast 64 (msb (loadw 0 16 (+ (var a4) (bv 64 0xfffffffffffffeb8)))) (loadw 0 16 (+ (var a4) (bv 64 0xfffffffffffffeb8))))) +# ----------------------------- LW ----------------------------- +d "lw s1, 8(s7)" 83a48b00 0x0 (set s1 (cast 64 (msb (loadw 0 32 (+ (var s7) (bv 64 0x8)))) (loadw 0 32 (+ (var s7) (bv 64 0x8))))) +d "lw a1, 0x18(sp)" e245 0x0 (set a1 (cast 64 (msb (loadw 0 32 (+ (var sp) (bv 64 0x18)))) (loadw 0 32 (+ (var sp) (bv 64 0x18))))) +d "lw a4, 0x9c(a4)" 0327c709 0x0 (set a4 (cast 64 (msb (loadw 0 32 (+ (var a4) (bv 64 0x9c)))) (loadw 0 32 (+ (var a4) (bv 64 0x9c))))) +# ----------------------------- LBU ----------------------------- +d "lbu a4, 0x337(s1)" 03c77433 0x0 (set a4 (cast 64 false (loadw 0 8 (+ (var s1) (bv 64 0x337))))) +d "lbu a4, 0x50(sp)" 03470105 0x0 (set a4 (cast 64 false (loadw 0 8 (+ (var sp) (bv 64 0x50))))) +d "lbu a3, -0x77(s0)" 834694f8 0x0 (set a3 (cast 64 false (loadw 0 8 (+ (var s0) (bv 64 0xffffffffffffff89))))) +# ----------------------------- LHU ----------------------------- +d "lhu a5, 4(s0)" 83574400 0x0 (set a5 (cast 64 false (loadw 0 16 (+ (var s0) (bv 64 0x4))))) +d "lhu a5, 0xc(s11)" 83d7cd00 0x0 (set a5 (cast 64 false (loadw 0 16 (+ (var s11) (bv 64 0xc))))) +d "lhu a2, 0xa4(sp)" 0356410a 0x0 (set a2 (cast 64 false (loadw 0 16 (+ (var sp) (bv 64 0xa4))))) +# ----------------------------- SB ----------------------------- +d "sb a1, 3(s0)" a301b400 0x0 (storew 0 (+ (var s0) (bv 64 0x3)) (cast 8 false (var a1))) +d "sb a1, -0x74(s0)" 2306b4f8 0x0 (storew 0 (+ (var s0) (bv 64 0xffffffffffffff8c)) (cast 8 false (var a1))) +d "sb a3, -1(a4)" a30fd7fe 0x0 (storew 0 (+ (var a4) (bv 64 0xffffffffffffffff)) (cast 8 false (var a3))) +# ----------------------------- SH ----------------------------- +d "sh a5, 0(s1)" 2390f400 0x0 (storew 0 (+ (var s1) (bv 64 0x0)) (cast 16 false (var a5))) +d "sh a0, 0x80(s1)" 2390a408 0x0 (storew 0 (+ (var s1) (bv 64 0x80)) (cast 16 false (var a0))) +d "sh s1, 0x32(a5)" 23999702 0x0 (storew 0 (+ (var a5) (bv 64 0x32)) (cast 16 false (var s1))) +# ----------------------------- SW ----------------------------- +d "sw a5, 0x9c(s1)" 23aef408 0x0 (storew 0 (+ (var s1) (bv 64 0x9c)) (cast 32 false (var a5))) +d "sw a5, 0(a4)" 1cc3 0x0 (storew 0 (+ (var a4) (bv 64 0x0)) (cast 32 false (var a5))) +d "sw s3, -0x6c0(a5)" 23a03795 0x0 (storew 0 (+ (var a5) (bv 64 0xfffffffffffff940)) (cast 32 false (var s3))) +# ----------------------------- BLTU ----------------------------- +d "bltu a5, s4, 0x48" 63e44705 0x0 (branch (&& (ule (var a5) (var s4)) (! (== (var a5) (var s4)))) (jmp (bv 64 0x48)) (jmp (bv 64 0x4))) +d "bltu a5, a3, 0xfffffffffffffff0" e3e8d7fe 0x0 (branch (&& (ule (var a5) (var a3)) (! (== (var a5) (var a3)))) (jmp (bv 64 0xfffffffffffffff0)) (jmp (bv 64 0x4))) +d "bltu t3, a1, 0xffffffffffffffe6" e363befe 0x0 (branch (&& (ule (var t3) (var a1)) (! (== (var t3) (var a1)))) (jmp (bv 64 0xffffffffffffffe6)) (jmp (bv 64 0x4))) +# ----------------------------- BGEU ----------------------------- +d "bgeu a3, a4, 0x1ae" 63f7e61a 0x0 (branch (|| (! (ule (var a3) (var a4))) (== (var a3) (var a4))) (jmp (bv 64 0x1ae)) (jmp (bv 64 0x4))) +d "bgeu s2, a5, 0xfffffffffffffff6" e37bf9fe 0x0 (branch (|| (! (ule (var s2) (var a5))) (== (var s2) (var a5))) (jmp (bv 64 0xfffffffffffffff6)) (jmp (bv 64 0x4))) +d "bgeu s7, s0, 0xffffffffffffff64" e3f28bf6 0x0 (branch (|| (! (ule (var s7) (var s0))) (== (var s7) (var s0))) (jmp (bv 64 0xffffffffffffff64)) (jmp (bv 64 0x4))) +# ----------------------------- FENCE ----------------------------- +d "fence rw, rw" 0f003003 0x0 nop +d "fence rw, w" 0f001003 0x0 nop +d "fence r, rw" 0f003002 0x0 nop +# ----------------------------- FENCE_I ----------------------------- +d "fence.i" 0f100000 0x0 nop +d "fence.i" 0f100000 0x0 nop +d "fence.i" 0f100000 0x0 nop +# ----------------------------- ECALL ----------------------------- +d "ecall" 73000000 0x0 (goto ecall) +d "ecall" 73000000 0x0 (goto ecall) +d "ecall" 73000000 0x0 (goto ecall) +# ----------------------------- EBREAK ----------------------------- +d "ebreak" 73001000 0x0 (goto ebreak) +d "ebreak" 73001000 0x0 (goto ebreak) +d "ebreak" 73001000 0x0 (goto ebreak) +# ----------------------------- MULH ----------------------------- +d "mulh t0, t1, t2" b3127302 0x0 (set t0 (cast 64 false (>> (* (cast 128 (msb (var t1)) (var t1)) (cast 128 (msb (var t2)) (var t2))) (bv 8 0x40) false))) +d "mulh a0, a1, a2" 3395c502 0x0 (set a0 (cast 64 false (>> (* (cast 128 (msb (var a1)) (var a1)) (cast 128 (msb (var a2)) (var a2))) (bv 8 0x40) false))) +d "mulh t3, t4, t5" 339eee03 0x0 (set t3 (cast 64 false (>> (* (cast 128 (msb (var t4)) (var t4)) (cast 128 (msb (var t5)) (var t5))) (bv 8 0x40) false))) +# ----------------------------- MULHSU ----------------------------- +d "mulhsu t0, t1, t2" b3227302 0x0 (set t0 (cast 64 false (>> (* (cast 128 (msb (var t1)) (var t1)) (cast 128 false (var t2))) (bv 8 0x40) false))) +d "mulhsu a0, a1, a2" 33a5c502 0x0 (set a0 (cast 64 false (>> (* (cast 128 (msb (var a1)) (var a1)) (cast 128 false (var a2))) (bv 8 0x40) false))) +d "mulhsu t3, t4, t5" 33aeee03 0x0 (set t3 (cast 64 false (>> (* (cast 128 (msb (var t4)) (var t4)) (cast 128 false (var t5))) (bv 8 0x40) false))) +# ----------------------------- DIV ----------------------------- +d "div a3, a3, a7" b3c61603 0x0 (set a3 (sdiv (var a3) (var a7))) +d "div t4, t6, t4" b3cedf03 0x0 (set t4 (sdiv (var t6) (var t4))) +d "div a4, a4, a3" 3347d702 0x0 (set a4 (sdiv (var a4) (var a3))) +# ----------------------------- DIVU ----------------------------- +d "divu a6, s2, s10" 3358a903 0x0 (set a6 (div (var s2) (var s10))) +d "divu s7, a5, t5" b3dbe703 0x0 (set s7 (div (var a5) (var t5))) +d "divu s1, a0, s2" b3542503 0x0 (set s1 (div (var a0) (var s2))) +# ----------------------------- REM ----------------------------- +d "rem t6, a4, a7" b36f1703 0x0 (set t6 (smod (var a4) (var a7))) +d "rem a5, a0, a4" b367e502 0x0 (set a5 (smod (var a0) (var a4))) +d "rem a5, t0, a5" b3e7f202 0x0 (set a5 (smod (var t0) (var a5))) +# ----------------------------- REMU ----------------------------- +d "remu a3, s1, a3" b3f6d402 0x0 (set a3 (mod (var s1) (var a3))) +d "remu a6, a6, s4" 33784803 0x0 (set a6 (mod (var a6) (var s4))) +d "remu a1, s7, s2" b3f52b03 0x0 (set a1 (mod (var s7) (var s2))) +# ----------------------------- C_NOP ----------------------------- +d "nop" 0100 0x0 nop +d "c.nop 1" 0500 0x0 nop +d "c.nop 2" 0900 0x0 nop +# ----------------------------- C_JALR ----------------------------- +d "jalr ra" 8290 0x0 (seq (set ra (bv 64 0x2)) (jmp (& (+ (var ra) (bv 64 0x0)) (bv 64 0xfffffffffffffffe)))) +d "jalr s0" 0294 0x0 (seq (set ra (bv 64 0x2)) (jmp (& (+ (var s0) (bv 64 0x0)) (bv 64 0xfffffffffffffffe)))) +d "jalr a5" 8297 0x0 (seq (set ra (bv 64 0x2)) (jmp (& (+ (var a5) (bv 64 0x0)) (bv 64 0xfffffffffffffffe)))) +# ----------------------------- C_EBREAK ----------------------------- +d "ebreak" 0290 0x0 (goto ebreak) +d "ebreak" 0290 0x0 (goto ebreak) +d "ebreak" 0290 0x0 (goto ebreak) +# ----------------------------- C_BEQZ ----------------------------- +d "beqz a0, 0" 01c1 0x0 (branch (== (var a0) (bv 64 0x0)) (jmp (bv 64 0x0)) (jmp (bv 64 0x2))) +d "beqz a1, 2" 89c1 0x0 (branch (== (var a1) (bv 64 0x0)) (jmp (bv 64 0x2)) (jmp (bv 64 0x2))) +d "beqz a5, 0xfffffffffffffffc" f5df 0x0 (branch (== (var a5) (bv 64 0x0)) (jmp (bv 64 0xfffffffffffffffc)) (jmp (bv 64 0x2))) +# ----------------------------- C_BNEZ ----------------------------- +d "bnez a0, 0" 01e1 0x0 (branch (! (== (var a0) (bv 64 0x0))) (jmp (bv 64 0x0)) (jmp (bv 64 0x2))) +d "bnez a1, 2" 89e1 0x0 (branch (! (== (var a1) (bv 64 0x0))) (jmp (bv 64 0x2)) (jmp (bv 64 0x2))) +d "bnez a5, 0xfffffffffffffffc" f5ff 0x0 (branch (! (== (var a5) (bv 64 0x0))) (jmp (bv 64 0xfffffffffffffffc)) (jmp (bv 64 0x2))) +# ----------------------------- C_SW ----------------------------- +d "sw a0, 0(s0)" 08c0 0x0 (storew 0 (+ (var s0) (bv 64 0x0)) (cast 32 false (var a0))) +d "sw a1, 4(s1)" ccc0 0x0 (storew 0 (+ (var s1) (bv 64 0x4)) (cast 32 false (var a1))) +d "sw a5, 0x7c(a5)" fcdf 0x0 (storew 0 (+ (var a5) (bv 64 0x7c)) (cast 32 false (var a5))) +# ----------------------------- C_JAL ----------------------------- +d "addiw t6, t6, -0xb" d53f 0x0 (set t6 (cast 64 (msb (+ (cast 32 false (var t6)) (bv 32 0xfffffff5))) (+ (cast 32 false (var t6)) (bv 32 0xfffffff5)))) +d "jal 2" 0920 0x0 (seq (set ra (bv 32 0x2)) (jmp (bv 32 0x2))) +d "addiw t6, t6, -9" dd3f 0x0 (set t6 (cast 64 (msb (+ (cast 32 false (var t6)) (bv 32 0xfffffff7))) (+ (cast 32 false (var t6)) (bv 32 0xfffffff7)))) +# ----------------------------- C_SUB ----------------------------- +d "sub a0, a0, a1" 0d8d 0x0 (set a0 (- (var a0) (var a1))) +d "sub a2, a2, a3" 158e 0x0 (set a2 (- (var a2) (var a3))) +d "sub a5, a5, a4" 998f 0x0 (set a5 (- (var a5) (var a4))) +# ----------------------------- C_AND ----------------------------- +d "and a0, a0, a1" 6d8d 0x0 (set a0 (& (var a0) (var a1))) +d "and a2, a2, a3" 758e 0x0 (set a2 (& (var a2) (var a3))) +d "and a5, a5, a4" f98f 0x0 (set a5 (& (var a5) (var a4))) +# ----------------------------- C_XOR ----------------------------- +d "xor a0, a0, a1" 2d8d 0x0 (set a0 (^ (var a0) (var a1))) +d "xor a2, a2, a3" 358e 0x0 (set a2 (^ (var a2) (var a3))) +d "xor a5, a5, a4" b98f 0x0 (set a5 (^ (var a5) (var a4))) From 4dd29c883212d3cb4c82aad33b96342532e895e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D9=85=D8=B5=D8=B7=D9=81=D9=8A=20=D9=85=D8=AD=D9=85=D9=88?= =?UTF-8?q?=D8=AF=20=D9=83=D9=85=D8=A7=D9=84=20=D8=A7=D9=84=D8=AF=D9=8A?= =?UTF-8?q?=D9=86?= <48567303+moste00@users.noreply.github.com> Date: Thu, 14 May 2026 22:02:17 +0300 Subject: [PATCH 8/8] implement the atomic extension trivially by ignoring concurrency guards --- librz/arch/isa/riscv/riscv_il.c | 100 ++++++++++++ librz/arch/isa/riscv/riscv_il_a.h | 226 +++++++++++++++++++++++++++ librz/arch/isa/riscv/riscv_il_base.h | 22 ++- 3 files changed, 343 insertions(+), 5 deletions(-) create mode 100644 librz/arch/isa/riscv/riscv_il_a.h diff --git a/librz/arch/isa/riscv/riscv_il.c b/librz/arch/isa/riscv/riscv_il.c index 35ff0001cc5..65b67d0b013 100644 --- a/librz/arch/isa/riscv/riscv_il.c +++ b/librz/arch/isa/riscv/riscv_il.c @@ -6,6 +6,7 @@ #include "riscv_il_base.h" #include "riscv_il_integer.h" #include "riscv_il_m.h" +#include "riscv_il_a.h" #include "riscv_il_compressed.h" static void label_ecall(RzILVM *vm, RzILOpEffect *op) { @@ -94,6 +95,105 @@ static const RiscvInstructionLifter riscv_lifters[] = { USE_LIFTER(divuw, DIVUW), USE_LIFTER(remw, REMW), USE_LIFTER(remuw, REMUW), + /* ---------------------------------- A extension ---------------------------------*/ + // Load-Reserved / Store-Conditional + USE_LIFTER(lr_w, LR_W), + USE_LIFTER(lr_w_aq, LR_W_AQ), + USE_LIFTER(lr_w_rl, LR_W_RL), + USE_LIFTER(lr_w_aqrl, LR_W_AQRL), + USE_LIFTER(lr_d, LR_D), + USE_LIFTER(lr_d_aq, LR_D_AQ), + USE_LIFTER(lr_d_rl, LR_D_RL), + USE_LIFTER(lr_d_aqrl, LR_D_AQRL), + USE_LIFTER(sc_w, SC_W), + USE_LIFTER(sc_w_aq, SC_W_AQ), + USE_LIFTER(sc_w_rl, SC_W_RL), + USE_LIFTER(sc_w_aqrl, SC_W_AQRL), + USE_LIFTER(sc_d, SC_D), + USE_LIFTER(sc_d_aq, SC_D_AQ), + USE_LIFTER(sc_d_rl, SC_D_RL), + USE_LIFTER(sc_d_aqrl, SC_D_AQRL), + // AMO swap + USE_LIFTER(amoswap_w, AMOSWAP_W), + USE_LIFTER(amoswap_w_aq, AMOSWAP_W_AQ), + USE_LIFTER(amoswap_w_rl, AMOSWAP_W_RL), + USE_LIFTER(amoswap_w_aqrl, AMOSWAP_W_AQRL), + USE_LIFTER(amoswap_d, AMOSWAP_D), + USE_LIFTER(amoswap_d_aq, AMOSWAP_D_AQ), + USE_LIFTER(amoswap_d_rl, AMOSWAP_D_RL), + USE_LIFTER(amoswap_d_aqrl, AMOSWAP_D_AQRL), + // AMO add + USE_LIFTER(amoadd_w, AMOADD_W), + USE_LIFTER(amoadd_w_aq, AMOADD_W_AQ), + USE_LIFTER(amoadd_w_rl, AMOADD_W_RL), + USE_LIFTER(amoadd_w_aqrl, AMOADD_W_AQRL), + USE_LIFTER(amoadd_d, AMOADD_D), + USE_LIFTER(amoadd_d_aq, AMOADD_D_AQ), + USE_LIFTER(amoadd_d_rl, AMOADD_D_RL), + USE_LIFTER(amoadd_d_aqrl, AMOADD_D_AQRL), + // AMO xor + USE_LIFTER(amoxor_w, AMOXOR_W), + USE_LIFTER(amoxor_w_aq, AMOXOR_W_AQ), + USE_LIFTER(amoxor_w_rl, AMOXOR_W_RL), + USE_LIFTER(amoxor_w_aqrl, AMOXOR_W_AQRL), + USE_LIFTER(amoxor_d, AMOXOR_D), + USE_LIFTER(amoxor_d_aq, AMOXOR_D_AQ), + USE_LIFTER(amoxor_d_rl, AMOXOR_D_RL), + USE_LIFTER(amoxor_d_aqrl, AMOXOR_D_AQRL), + // AMO and + USE_LIFTER(amoand_w, AMOAND_W), + USE_LIFTER(amoand_w_aq, AMOAND_W_AQ), + USE_LIFTER(amoand_w_rl, AMOAND_W_RL), + USE_LIFTER(amoand_w_aqrl, AMOAND_W_AQRL), + USE_LIFTER(amoand_d, AMOAND_D), + USE_LIFTER(amoand_d_aq, AMOAND_D_AQ), + USE_LIFTER(amoand_d_rl, AMOAND_D_RL), + USE_LIFTER(amoand_d_aqrl, AMOAND_D_AQRL), + // AMO or + USE_LIFTER(amoor_w, AMOOR_W), + USE_LIFTER(amoor_w_aq, AMOOR_W_AQ), + USE_LIFTER(amoor_w_rl, AMOOR_W_RL), + USE_LIFTER(amoor_w_aqrl, AMOOR_W_AQRL), + USE_LIFTER(amoor_d, AMOOR_D), + USE_LIFTER(amoor_d_aq, AMOOR_D_AQ), + USE_LIFTER(amoor_d_rl, AMOOR_D_RL), + USE_LIFTER(amoor_d_aqrl, AMOOR_D_AQRL), + // AMO signed min + USE_LIFTER(amomin_w, AMOMIN_W), + USE_LIFTER(amomin_w_aq, AMOMIN_W_AQ), + USE_LIFTER(amomin_w_rl, AMOMIN_W_RL), + USE_LIFTER(amomin_w_aqrl, AMOMIN_W_AQRL), + USE_LIFTER(amomin_d, AMOMIN_D), + USE_LIFTER(amomin_d_aq, AMOMIN_D_AQ), + USE_LIFTER(amomin_d_rl, AMOMIN_D_RL), + USE_LIFTER(amomin_d_aqrl, AMOMIN_D_AQRL), + // AMO signed max + USE_LIFTER(amomax_w, AMOMAX_W), + USE_LIFTER(amomax_w_aq, AMOMAX_W_AQ), + USE_LIFTER(amomax_w_rl, AMOMAX_W_RL), + USE_LIFTER(amomax_w_aqrl, AMOMAX_W_AQRL), + USE_LIFTER(amomax_d, AMOMAX_D), + USE_LIFTER(amomax_d_aq, AMOMAX_D_AQ), + USE_LIFTER(amomax_d_rl, AMOMAX_D_RL), + USE_LIFTER(amomax_d_aqrl, AMOMAX_D_AQRL), + // AMO unsigned min + USE_LIFTER(amominu_w, AMOMINU_W), + USE_LIFTER(amominu_w_aq, AMOMINU_W_AQ), + USE_LIFTER(amominu_w_rl, AMOMINU_W_RL), + USE_LIFTER(amominu_w_aqrl, AMOMINU_W_AQRL), + USE_LIFTER(amominu_d, AMOMINU_D), + USE_LIFTER(amominu_d_aq, AMOMINU_D_AQ), + USE_LIFTER(amominu_d_rl, AMOMINU_D_RL), + USE_LIFTER(amominu_d_aqrl, AMOMINU_D_AQRL), + // AMO unsigned max + USE_LIFTER(amomaxu_w, AMOMAXU_W), + USE_LIFTER(amomaxu_w_aq, AMOMAXU_W_AQ), + USE_LIFTER(amomaxu_w_rl, AMOMAXU_W_RL), + USE_LIFTER(amomaxu_w_aqrl, AMOMAXU_W_AQRL), + USE_LIFTER(amomaxu_d, AMOMAXU_D), + USE_LIFTER(amomaxu_d_aq, AMOMAXU_D_AQ), + USE_LIFTER(amomaxu_d_rl, AMOMAXU_D_RL), + USE_LIFTER(amomaxu_d_aqrl, AMOMAXU_D_AQRL), /* ---------------------------------- Compressed ---------------------------------*/ USE_LIFTER(c_nop, C_NOP), USE_LIFTER(c_addi, C_ADDI), diff --git a/librz/arch/isa/riscv/riscv_il_a.h b/librz/arch/isa/riscv/riscv_il_a.h new file mode 100644 index 00000000000..692ad2781a2 --- /dev/null +++ b/librz/arch/isa/riscv/riscv_il_a.h @@ -0,0 +1,226 @@ +// SPDX-FileCopyrightText: 2026 Mostafa Mahmoud +// SPDX-License-Identifier: BSD-3-Clause + +#ifndef RISCV_IL_A_H +#define RISCV_IL_A_H + +#include "riscv_il_base.h" + +#include + +// Decoder: rd=REG[0], addr=MEM[1].base (lr.w / lr.d) +#define DECODE_RD_MEM(analysis, insn) \ + REQUIRE_OP(0, RISCV_OP_REG); \ + REQUIRE_OP(1, RISCV_OP_MEM); \ + uint32_t rd = insn->detail->riscv.operands[0].reg; \ + RzILOpBitVector *addr = riscv_il_get_reg(analysis->bits, insn->detail->riscv.operands[1].mem.base); + +// Decoder: rd=REG[0], addr=MEM[1].base, rs2=REG[2] (sc.* / amo*.*) +#define DECODE_RD_MEM_RS(analysis, insn) \ + REQUIRE_OP(0, RISCV_OP_REG); \ + REQUIRE_OP(1, RISCV_OP_MEM); \ + REQUIRE_OP(2, RISCV_OP_REG); \ + uint32_t rd = insn->detail->riscv.operands[0].reg; \ + RzILOpBitVector *addr = riscv_il_get_reg(analysis->bits, insn->detail->riscv.operands[1].mem.base); \ + RzILOpBitVector *rs2 = riscv_il_get_reg(analysis->bits, insn->detail->riscv.operands[2].reg); + +// 64-bit-only variants (RV64A .d instructions) +#define DECODE_RD_MEM_64(analysis, insn) \ + REQUIRE_64_BIT(analysis); \ + DECODE_RD_MEM(analysis, insn) + +#define DECODE_RD_MEM_RS_64(analysis, insn) \ + REQUIRE_64_BIT(analysis); \ + DECODE_RD_MEM_RS(analysis, insn) + +// A extension: atomic instructions (RV32A / RV64A) +// +// Sequential-execution assumption +// -------------------------------- +// This entire file assumes the RzIL VM is completely sequential with no parallelism or +// asynchrony of any kind. Under that assumption every "atomic" concern reduces as follows: +// +// Acquire/release ordering (.aq / .rl / .aqrl variants) +// Collapse to no-ops. Ordering constraints only matter when multiple execution flows +// share memory concurrently. All ordering variants are therefore aliased to the base +// instruction with no extra fence or barrier logic. +// +// Load-Reserved / Store-Conditional reservations +// Are trivially always valid. The only execution flow that could invalidate a reservation +// between lr and sc are external ones — another hart, a DMA engine, an interrupt +// handler that writes to the same address, memory-mapped I/O side-effects, etc. — +// none of which exist in this model. lr.* is therefore a plain load and sc.* +// is an unconditional store that always reports success (rd = 0). +// +// AMO read-modify-write atomicity +// Is trivially preserved. There is no window in which another execution flow could observe +// or modify memory between the internal load and store, so the straightforward +// SEQ-based implementation is fully correct and complete. +// +// If the VM ever gains any form of parallelism or asynchrony — including but not limited +// to hardware threads (harts), DMA engines, memory-mapped I/O with side-effects, interrupt +// delivery modelled between individual instructions, or speculative / out-of-order execution +// — this file MUST be revisited. + +// Load-Reserved: plain load as in riscv_il_integer.h; reservation is not modelled +DEFINE_LIFTER(lr_w, DECODE_RD_MEM, + analysis->bits == 32 ? LOADW(32, addr) : SIGNED(analysis->bits, LOADW(32, addr))) +DEFINE_ALIAS_LIFTER(lr_w_aq, lr_w) +DEFINE_ALIAS_LIFTER(lr_w_rl, lr_w) +DEFINE_ALIAS_LIFTER(lr_w_aqrl, lr_w) + +DEFINE_LIFTER(lr_d, DECODE_RD_MEM_64, LOADW(64, addr)) +DEFINE_ALIAS_LIFTER(lr_d_aq, lr_d) +DEFINE_ALIAS_LIFTER(lr_d_rl, lr_d) +DEFINE_ALIAS_LIFTER(lr_d_aqrl, lr_d) + +// Store-Conditional: unconditional store as in riscv_il_integer.h, rd = 0 (always succeeds; see sequential assumption above) +DEFINE_LIFTER_WITH_PRE_EFFECT(sc_w, DECODE_RD_MEM_RS, + STOREW(addr, CAST(32, IL_FALSE, rs2)), + UN(analysis->bits, 0)) +DEFINE_ALIAS_LIFTER(sc_w_aq, sc_w) +DEFINE_ALIAS_LIFTER(sc_w_rl, sc_w) +DEFINE_ALIAS_LIFTER(sc_w_aqrl, sc_w) + +DEFINE_LIFTER_WITH_PRE_EFFECT(sc_d, DECODE_RD_MEM_RS_64, + STOREW(addr, rs2), + UN(analysis->bits, 0)) +DEFINE_ALIAS_LIFTER(sc_d_aq, sc_d) +DEFINE_ALIAS_LIFTER(sc_d_rl, sc_d) +DEFINE_ALIAS_LIFTER(sc_d_aqrl, sc_d) + +// AMO .w helper: atomically read-modify-write 32-bit memory, return old value sign-extended to XLEN. +// new32 may reference VARL("_v32") (old 32-bit mem val) and VARL("_r32") (rs2 lower 32 bits). +#define AMO_W(rd, addr, rs2, new32) \ + SEQ5( \ + SETL("_a", (addr)), \ + SETL("_v32", LOADW(32, VARL("_a"))), \ + SETL("_r32", CAST(32, IL_FALSE, (rs2))), \ + STOREW(VARL("_a"), (new32)), \ + riscv_il_set_reg((rd), SIGNED(analysis->bits, VARL("_v32")))) + +// AMO .d helper: atomically read-modify-write 64-bit memory, return old value in rd. +// new64 may reference VARL("_v") (old 64-bit mem val) and VARL("_r") (rs2). +#define AMO_D(rd, addr, rs2, new64) \ + SEQ5( \ + SETL("_a", (addr)), \ + SETL("_v", LOADW(64, VARL("_a"))), \ + SETL("_r", (rs2)), \ + STOREW(VARL("_a"), (new64)), \ + riscv_il_set_reg((rd), VARL("_v"))) + +// AMO swap: mem = rs2, rd = old_mem +DEFINE_LIFTER_WITH_EFFECT(amoswap_w, DECODE_RD_MEM_RS, AMO_W(rd, addr, rs2, VARL("_r32"))) +DEFINE_ALIAS_LIFTER(amoswap_w_aq, amoswap_w) +DEFINE_ALIAS_LIFTER(amoswap_w_rl, amoswap_w) +DEFINE_ALIAS_LIFTER(amoswap_w_aqrl, amoswap_w) + +DEFINE_LIFTER_WITH_EFFECT(amoswap_d, DECODE_RD_MEM_RS_64, AMO_D(rd, addr, rs2, VARL("_r"))) +DEFINE_ALIAS_LIFTER(amoswap_d_aq, amoswap_d) +DEFINE_ALIAS_LIFTER(amoswap_d_rl, amoswap_d) +DEFINE_ALIAS_LIFTER(amoswap_d_aqrl, amoswap_d) + +// AMO add +DEFINE_LIFTER_WITH_EFFECT(amoadd_w, DECODE_RD_MEM_RS, AMO_W(rd, addr, rs2, ADD(VARL("_v32"), VARL("_r32")))) +DEFINE_ALIAS_LIFTER(amoadd_w_aq, amoadd_w) +DEFINE_ALIAS_LIFTER(amoadd_w_rl, amoadd_w) +DEFINE_ALIAS_LIFTER(amoadd_w_aqrl, amoadd_w) + +DEFINE_LIFTER_WITH_EFFECT(amoadd_d, DECODE_RD_MEM_RS_64, AMO_D(rd, addr, rs2, ADD(VARL("_v"), VARL("_r")))) +DEFINE_ALIAS_LIFTER(amoadd_d_aq, amoadd_d) +DEFINE_ALIAS_LIFTER(amoadd_d_rl, amoadd_d) +DEFINE_ALIAS_LIFTER(amoadd_d_aqrl, amoadd_d) + +// AMO xor +DEFINE_LIFTER_WITH_EFFECT(amoxor_w, DECODE_RD_MEM_RS, AMO_W(rd, addr, rs2, LOGXOR(VARL("_v32"), VARL("_r32")))) +DEFINE_ALIAS_LIFTER(amoxor_w_aq, amoxor_w) +DEFINE_ALIAS_LIFTER(amoxor_w_rl, amoxor_w) +DEFINE_ALIAS_LIFTER(amoxor_w_aqrl, amoxor_w) + +DEFINE_LIFTER_WITH_EFFECT(amoxor_d, DECODE_RD_MEM_RS_64, AMO_D(rd, addr, rs2, LOGXOR(VARL("_v"), VARL("_r")))) +DEFINE_ALIAS_LIFTER(amoxor_d_aq, amoxor_d) +DEFINE_ALIAS_LIFTER(amoxor_d_rl, amoxor_d) +DEFINE_ALIAS_LIFTER(amoxor_d_aqrl, amoxor_d) + +// AMO and +DEFINE_LIFTER_WITH_EFFECT(amoand_w, DECODE_RD_MEM_RS, AMO_W(rd, addr, rs2, LOGAND(VARL("_v32"), VARL("_r32")))) +DEFINE_ALIAS_LIFTER(amoand_w_aq, amoand_w) +DEFINE_ALIAS_LIFTER(amoand_w_rl, amoand_w) +DEFINE_ALIAS_LIFTER(amoand_w_aqrl, amoand_w) + +DEFINE_LIFTER_WITH_EFFECT(amoand_d, DECODE_RD_MEM_RS_64, AMO_D(rd, addr, rs2, LOGAND(VARL("_v"), VARL("_r")))) +DEFINE_ALIAS_LIFTER(amoand_d_aq, amoand_d) +DEFINE_ALIAS_LIFTER(amoand_d_rl, amoand_d) +DEFINE_ALIAS_LIFTER(amoand_d_aqrl, amoand_d) + +// AMO or +DEFINE_LIFTER_WITH_EFFECT(amoor_w, DECODE_RD_MEM_RS, AMO_W(rd, addr, rs2, LOGOR(VARL("_v32"), VARL("_r32")))) +DEFINE_ALIAS_LIFTER(amoor_w_aq, amoor_w) +DEFINE_ALIAS_LIFTER(amoor_w_rl, amoor_w) +DEFINE_ALIAS_LIFTER(amoor_w_aqrl, amoor_w) + +DEFINE_LIFTER_WITH_EFFECT(amoor_d, DECODE_RD_MEM_RS_64, AMO_D(rd, addr, rs2, LOGOR(VARL("_v"), VARL("_r")))) +DEFINE_ALIAS_LIFTER(amoor_d_aq, amoor_d) +DEFINE_ALIAS_LIFTER(amoor_d_rl, amoor_d) +DEFINE_ALIAS_LIFTER(amoor_d_aqrl, amoor_d) + +// AMO signed min/max: operands are 32-bit bitvectors (_v32, _r32), so SLT/SGT is 32-bit signed +DEFINE_LIFTER_WITH_EFFECT(amomin_w, DECODE_RD_MEM_RS, + AMO_W(rd, addr, rs2, ITE(SLT(VARL("_v32"), VARL("_r32")), VARL("_v32"), VARL("_r32")))) +DEFINE_ALIAS_LIFTER(amomin_w_aq, amomin_w) +DEFINE_ALIAS_LIFTER(amomin_w_rl, amomin_w) +DEFINE_ALIAS_LIFTER(amomin_w_aqrl, amomin_w) + +DEFINE_LIFTER_WITH_EFFECT(amomin_d, DECODE_RD_MEM_RS_64, + AMO_D(rd, addr, rs2, ITE(SLT(VARL("_v"), VARL("_r")), VARL("_v"), VARL("_r")))) +DEFINE_ALIAS_LIFTER(amomin_d_aq, amomin_d) +DEFINE_ALIAS_LIFTER(amomin_d_rl, amomin_d) +DEFINE_ALIAS_LIFTER(amomin_d_aqrl, amomin_d) + +DEFINE_LIFTER_WITH_EFFECT(amomax_w, DECODE_RD_MEM_RS, + AMO_W(rd, addr, rs2, ITE(SGT(VARL("_v32"), VARL("_r32")), VARL("_v32"), VARL("_r32")))) +DEFINE_ALIAS_LIFTER(amomax_w_aq, amomax_w) +DEFINE_ALIAS_LIFTER(amomax_w_rl, amomax_w) +DEFINE_ALIAS_LIFTER(amomax_w_aqrl, amomax_w) + +DEFINE_LIFTER_WITH_EFFECT(amomax_d, DECODE_RD_MEM_RS_64, + AMO_D(rd, addr, rs2, ITE(SGT(VARL("_v"), VARL("_r")), VARL("_v"), VARL("_r")))) +DEFINE_ALIAS_LIFTER(amomax_d_aq, amomax_d) +DEFINE_ALIAS_LIFTER(amomax_d_rl, amomax_d) +DEFINE_ALIAS_LIFTER(amomax_d_aqrl, amomax_d) + +// AMO unsigned min/max: _v32/_r32 are 32-bit bitvectors, so ULT/UGT is 32-bit unsigned +DEFINE_LIFTER_WITH_EFFECT(amominu_w, DECODE_RD_MEM_RS, + AMO_W(rd, addr, rs2, ITE(ULT(VARL("_v32"), VARL("_r32")), VARL("_v32"), VARL("_r32")))) +DEFINE_ALIAS_LIFTER(amominu_w_aq, amominu_w) +DEFINE_ALIAS_LIFTER(amominu_w_rl, amominu_w) +DEFINE_ALIAS_LIFTER(amominu_w_aqrl, amominu_w) + +DEFINE_LIFTER_WITH_EFFECT(amominu_d, DECODE_RD_MEM_RS_64, + AMO_D(rd, addr, rs2, ITE(ULT(VARL("_v"), VARL("_r")), VARL("_v"), VARL("_r")))) +DEFINE_ALIAS_LIFTER(amominu_d_aq, amominu_d) +DEFINE_ALIAS_LIFTER(amominu_d_rl, amominu_d) +DEFINE_ALIAS_LIFTER(amominu_d_aqrl, amominu_d) + +DEFINE_LIFTER_WITH_EFFECT(amomaxu_w, DECODE_RD_MEM_RS, + AMO_W(rd, addr, rs2, ITE(UGT(VARL("_v32"), VARL("_r32")), VARL("_v32"), VARL("_r32")))) +DEFINE_ALIAS_LIFTER(amomaxu_w_aq, amomaxu_w) +DEFINE_ALIAS_LIFTER(amomaxu_w_rl, amomaxu_w) +DEFINE_ALIAS_LIFTER(amomaxu_w_aqrl, amomaxu_w) + +DEFINE_LIFTER_WITH_EFFECT(amomaxu_d, DECODE_RD_MEM_RS_64, + AMO_D(rd, addr, rs2, ITE(UGT(VARL("_v"), VARL("_r")), VARL("_v"), VARL("_r")))) +DEFINE_ALIAS_LIFTER(amomaxu_d_aq, amomaxu_d) +DEFINE_ALIAS_LIFTER(amomaxu_d_rl, amomaxu_d) +DEFINE_ALIAS_LIFTER(amomaxu_d_aqrl, amomaxu_d) + +#undef DECODE_RD_MEM +#undef DECODE_RD_MEM_RS +#undef DECODE_RD_MEM_64 +#undef DECODE_RD_MEM_RS_64 +#undef AMO_W +#undef AMO_D + +#include + +#endif // RISCV_IL_A_H diff --git a/librz/arch/isa/riscv/riscv_il_base.h b/librz/arch/isa/riscv/riscv_il_base.h index 86c0ee3d78c..96a094419b1 100644 --- a/librz/arch/isa/riscv/riscv_il_base.h +++ b/librz/arch/isa/riscv/riscv_il_base.h @@ -33,14 +33,24 @@ static inline RzILOpEffect *riscv_il_set_reg(uint32_t reg, RZ_OWN RZ_NONNULL RzI return riscv_il_set_reg(rd, result); \ } -// by default, a RISC-V jump both sets a destination and sets the PC (i.e., jumps) -#define DEFINE_LIFTER_FOR_JUMP(name, decoder, result, jmp_effect) \ - RzILOpEffect *rz_riscv_lift_##name(RZ_BORROW RZ_NONNULL RzAnalysis *analysis, \ +// rd = result, then post_effect (e.g. jump: set return address, then redirect PC) +#define DEFINE_LIFTER_WITH_POST_EFFECT(name, decoder, result, post_effect) \ + static RzILOpEffect *rz_riscv_lift_##name(RZ_BORROW RZ_NONNULL RzAnalysis *analysis, \ RZ_NONNULL RzAnalysisOp *op, RZ_NONNULL cs_insn *insn, ut64 current_addr, size_t size) { \ decoder(analysis, insn); \ return SEQ2( \ riscv_il_set_reg(rd, result), \ - jmp_effect); \ + post_effect); \ + } + +// pre_effect, then rd = result (e.g. store-conditional: store first, then write success flag) +#define DEFINE_LIFTER_WITH_PRE_EFFECT(name, decoder, pre_effect, result) \ + static RzILOpEffect *rz_riscv_lift_##name(RZ_BORROW RZ_NONNULL RzAnalysis *analysis, \ + RZ_NONNULL RzAnalysisOp *op, RZ_NONNULL cs_insn *insn, ut64 current_addr, size_t size) { \ + decoder(analysis, insn); \ + return SEQ2( \ + pre_effect, \ + riscv_il_set_reg(rd, result)); \ } #define DEFINE_LIFTER_WITH_EFFECT(name, decoder, effect) \ @@ -50,8 +60,10 @@ static inline RzILOpEffect *riscv_il_set_reg(uint32_t reg, RZ_OWN RZ_NONNULL RzI return effect; \ } +// by default, a RISC-V jump both sets a destination and sets the PC (i.e., jumps) +#define DEFINE_LIFTER_FOR_JUMP DEFINE_LIFTER_WITH_POST_EFFECT // oneway jumps are those that don't have a destination register -#define DEFINE_LIFTER_FOR_ONEWAY_JUMP DEFINE_LIFTER_WITH_EFFECT +#define DEFINE_LIFTER_FOR_ONEWAY_JUMP DEFINE_LIFTER_WITH_EFFECT // A more intuitive definition would be: // static const RiscvInstructionLifter rz_riscv_lift_##alias = ...;