From a542d0c9cd33fed5919c3cd9d598bb8d1a300ae8 Mon Sep 17 00:00:00 2001 From: Pete Dietl Date: Sun, 18 Feb 2024 13:58:38 -0800 Subject: Fix RISC-V CSRRW, CSRRS, and CSRRC instr disass Make the CSR instructions show the CSR 12-bit immediate operand as an unsigned integer. This is a special case of the I-instruction format, where it is same except that the 12-bit immediate is treated as unsigned rather than signed. --- arch/riscv/disasm/src/lib.rs | 53 ++++++++++++++++++++++++++++++++++++++------ arch/riscv/src/lib.rs | 6 ++--- 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/arch/riscv/disasm/src/lib.rs b/arch/riscv/disasm/src/lib.rs index b9505724..af7cd9a6 100644 --- a/arch/riscv/disasm/src/lib.rs +++ b/arch/riscv/disasm/src/lib.rs @@ -87,9 +87,9 @@ pub enum Op { // SYSTEM Ecall, Ebreak, - Csrrw(ITypeIntInst), - Csrrs(ITypeIntInst), - Csrrc(ITypeIntInst), + Csrrw(CsrTypeInst), + Csrrs(CsrTypeInst), + Csrrc(CsrTypeInst), CsrrwI(CsrITypeInst), CsrrsI(CsrITypeInst), CsrrcI(CsrITypeInst), @@ -732,6 +732,45 @@ impl CsrITypeInst { } } +#[derive(Copy, Clone, Debug)] +pub struct CsrTypeInst { + inst: Instr32, + _dis: PhantomData, + _rs1: PhantomData>, +} + +impl CsrTypeInst { + #[inline(always)] + fn new(inst: Instr32) -> DisResult { + let ret = Self { + inst, + _dis: PhantomData, + _rs1: PhantomData, + }; + + if !ret.rd().valid() || !ret.rs1().valid() { + return Err(Error::BadRegister); + } + + Ok(ret) + } + + #[inline(always)] + pub fn rd(&self) -> IntReg { + IntReg::new(self.inst.rd()) + } + + #[inline(always)] + pub fn rs1(&self) -> IntReg { + IntReg::new(self.inst.rs1()) + } + + #[inline(always)] + pub fn csr(&self) -> u32 { + self.inst.i_imm() as u32 & 0xfff + } +} + #[derive(Copy, Clone, Debug)] pub struct RTypeInst where @@ -1834,7 +1873,7 @@ impl Instr { } Op::Csrrw(ref i) | Op::Csrrs(ref i) | Op::Csrrc(ref i) => { ops.push(Operand::R(i.rd())); - ops.push(Operand::I(i.imm())); + ops.push(Operand::I(i.csr() as i32)); ops.push(Operand::R(i.rs1())); } Op::CsrrwI(ref i) | Op::CsrrsI(ref i) | Op::CsrrcI(ref i) => { @@ -3111,9 +3150,9 @@ pub trait RiscVDisassembler: Sized + Copy + Clone { _ => return Err(InvalidSubop), } } - 0b001 => Op::Csrrw(ITypeIntInst::new(inst)?), - 0b010 => Op::Csrrs(ITypeIntInst::new(inst)?), - 0b011 => Op::Csrrc(ITypeIntInst::new(inst)?), + 0b001 => Op::Csrrw(CsrTypeInst::new(inst)?), + 0b010 => Op::Csrrs(CsrTypeInst::new(inst)?), + 0b011 => Op::Csrrc(CsrTypeInst::new(inst)?), 0b101 => Op::CsrrwI(CsrITypeInst::new(inst)?), 0b110 => Op::CsrrsI(CsrITypeInst::new(inst)?), 0b111 => Op::CsrrcI(CsrITypeInst::new(inst)?), diff --git a/arch/riscv/src/lib.rs b/arch/riscv/src/lib.rs index d8f6cff5..8b9fde31 100644 --- a/arch/riscv/src/lib.rs +++ b/arch/riscv/src/lib.rs @@ -1314,7 +1314,7 @@ impl architecture::Architecture fo Op::Csrrw(i) => { let rd = Register::from(i.rd()); let rs1 = Liftable::lift(il, Register::from(i.rs1())); - let csr = il.const_int(4, i.imm() as u64); + let csr = il.const_int(4, i.csr() as u64); if i.rd().id() == 0 { il.intrinsic(Lifter::::NO_OUTPUTS, Intrinsic::Csrwr, [csr, rs1]) @@ -1326,7 +1326,7 @@ impl architecture::Architecture fo Op::Csrrs(i) => { let rd = Register::from(i.rd()); let rs1 = Liftable::lift(il, Register::from(i.rs1())); - let csr = il.const_int(4, i.imm() as u64); + let csr = il.const_int(4, i.csr() as u64); if i.rs1().id() == 0 { il.intrinsic([rd], Intrinsic::Csrrd, [csr]).append(); @@ -1337,7 +1337,7 @@ impl architecture::Architecture fo Op::Csrrc(i) => { let rd = Register::from(i.rd()); let rs1 = Liftable::lift(il, Register::from(i.rs1())); - let csr = il.const_int(4, i.imm() as u64); + let csr = il.const_int(4, i.csr() as u64); if i.rs1().id() == 0 { il.intrinsic([rd], Intrinsic::Csrrd, [csr]).append(); -- cgit v1.3.1