summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorMason Reed <mason@vector35.com>2024-11-30 19:00:49 -0500
committerMason Reed <mason@vector35.com>2024-11-30 19:01:57 -0500
commitb92dac445e18fc2cf70b3cc5da26b996efa78a1f (patch)
tree7e44b801156799e185af6008d42c3c26051e6bb9 /arch
parentbf076bf469a73c88c68e6e8d1d848ae8860ebe90 (diff)
Remove temp register in JALR RISC-V when unused
Diffstat (limited to 'arch')
-rw-r--r--arch/riscv/src/lib.rs17
1 files changed, 14 insertions, 3 deletions
diff --git a/arch/riscv/src/lib.rs b/arch/riscv/src/lib.rs
index 76e94cc2..97998239 100644
--- a/arch/riscv/src/lib.rs
+++ b/arch/riscv/src/lib.rs
@@ -1241,9 +1241,20 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> architecture::Architecture fo
(0, 1, 0) => il.ret(target).append(), // jalr zero, ra, 0
(1, _, _) => il.call(target).append(), // indirect call
(0, _, _) => il.jump(target).append(), // indirect jump
- (_, _, _) => {
+ (rd_id, rs1_id, _) if rd_id == rs1_id => {
// store the target in a temporary register so we don't clobber it when rd == rs1
- il.set_reg(max_width, llil::Register::Temp(0), target).append();
+ let tmp_reg: llil::Register<Register<D>> = llil::Register::Temp(0);
+ il.set_reg(max_width, tmp_reg, target).append();
+ // indirect jump with storage of next address to non-`ra` register
+ il.set_reg(
+ max_width,
+ Register::from(rd),
+ il.const_ptr(addr.wrapping_add(inst_len)),
+ )
+ .append();
+ il.jump(tmp_reg).append();
+ }
+ (_, _, _) => {
// indirect jump with storage of next address to non-`ra` register
il.set_reg(
max_width,
@@ -1251,7 +1262,7 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> architecture::Architecture fo
il.const_ptr(addr.wrapping_add(inst_len)),
)
.append();
- il.jump(il.reg(max_width, llil::Register::Temp(0))).append();
+ il.jump(target).append();
}
}
}