Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 100 additions & 0 deletions librz/arch/isa/riscv/riscv_il.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "riscv_il.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) {
Expand Down Expand Up @@ -87,6 +88,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_addi, C_ADDI),
USE_LIFTER(c_addi16sp, C_ADDI16SP),
Expand Down
226 changes: 226 additions & 0 deletions librz/arch/isa/riscv/riscv_il_a.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
// SPDX-FileCopyrightText: 2026 Mostafa Mahmoud <ubermenchun@gmail.com>
// SPDX-License-Identifier: BSD-3-Clause

#ifndef RISCV_IL_A_H
#define RISCV_IL_A_H

#include "riscv_il_base.h"

#include <rz_il/rz_il_opbuilder_begin.h>

// 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_GET_REG(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_GET_REG(insn->detail->riscv.operands[1].mem.base); \
RzILOpBitVector *rs2 = RISCV_GET_REG(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_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_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 <rz_il/rz_il_opbuilder_end.h>

#endif // RISCV_IL_A_H
20 changes: 16 additions & 4 deletions librz/arch/isa/riscv/riscv_il_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,24 @@ static const char *riscv_register_names[] = {
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) \
// 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, int size) { \
decoder(analysis, insn); \
return SEQ2( \
RISCV_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, int size) { \
decoder(analysis, insn); \
return SEQ2( \
pre_effect, \
RISCV_SET_REG(rd, result)); \
}

#define DEFINE_LIFTER_WITH_EFFECT(name, decoder, effect) \
Expand All @@ -70,8 +80,10 @@ static const char *riscv_register_names[] = {
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

#define DEFINE_ALIAS_LIFTER(alias, name) static const RiscvInstructionLifter rz_riscv_lift_##alias = rz_riscv_lift_##name;

Expand Down
Loading