From 2279248acf9534e64c31f5076b1dc9c5261ea0c6 Mon Sep 17 00:00:00 2001 From: Emma Turner Date: Tue, 18 Feb 2025 13:56:42 +0000 Subject: [PATCH 1/2] RISC-V: support OpCode::Li in JIT --- src/riscv/lib/src/instruction_context.rs | 8 +++ src/riscv/lib/src/interpreter.rs | 1 + src/riscv/lib/src/interpreter/load_store.rs | 50 +++++++++++++++++++ src/riscv/lib/src/interpreter/rv32c.rs | 38 -------------- src/riscv/lib/src/interpreter/rv32i.rs | 9 ---- src/riscv/lib/src/jit.rs | 24 ++++----- src/riscv/lib/src/jit/builder.rs | 6 ++- .../lib/src/machine_state/instruction.rs | 14 +++++- 8 files changed, 88 insertions(+), 62 deletions(-) create mode 100644 src/riscv/lib/src/interpreter/load_store.rs diff --git a/src/riscv/lib/src/instruction_context.rs b/src/riscv/lib/src/instruction_context.rs index a22d85c0de51..9808048b7a9d 100644 --- a/src/riscv/lib/src/instruction_context.rs +++ b/src/riscv/lib/src/instruction_context.rs @@ -41,6 +41,9 @@ pub trait ICB { /// registers that are guaranteed not to be x0. fn xregister_write(&mut self, reg: NonZeroXRegister, value: Self::XValue); + /// Construct an [`ICB::XValue`] from an `imm: i64`. + fn xvalue_of_imm(&mut self, imm: i64) -> Self::XValue; + /// Perform a wrapping add of two **XValues**, returning the new value. /// /// This behaves identically for both signed & unsigned values. @@ -76,6 +79,11 @@ impl ICB for MachineCoreState self.hart.xregisters.write_nz(reg, value) } + #[inline(always)] + fn xvalue_of_imm(&mut self, imm: i64) -> Self::XValue { + imm as u64 + } + #[inline(always)] fn xvalue_wrapping_add(&mut self, lhs: Self::XValue, rhs: Self::XValue) -> Self::XValue { // Wrapped addition in two's complement behaves the same for signed and unsigned diff --git a/src/riscv/lib/src/interpreter.rs b/src/riscv/lib/src/interpreter.rs index 3e8b15874b7c..1eeba9034d5e 100644 --- a/src/riscv/lib/src/interpreter.rs +++ b/src/riscv/lib/src/interpreter.rs @@ -9,6 +9,7 @@ mod common_memory; pub mod float; pub mod i; pub mod integer; +pub mod load_store; pub mod rv32a; pub mod rv32c; pub mod rv32i; diff --git a/src/riscv/lib/src/interpreter/load_store.rs b/src/riscv/lib/src/interpreter/load_store.rs new file mode 100644 index 000000000000..bbbdace76d21 --- /dev/null +++ b/src/riscv/lib/src/interpreter/load_store.rs @@ -0,0 +1,50 @@ +use crate::{instruction_context::ICB, machine_state::registers::NonZeroXRegister}; + +/// Loads the immediate `imm` into register `rd_rs1`. +/// +/// Relevant RISC-V opcodes: +/// - C.LI +/// - ADD +/// - ADDI +/// - ANDI +/// - ORI +/// - XORI +/// - SLLI +/// - SRLI +/// - SRAI +/// - AND +/// - C.AND +/// - OR +/// - XOR +/// - SLL +/// - SRL +/// - SRA +/// - SUB +pub fn run_li(icb: &mut impl ICB, imm: i64, rd_rs1: NonZeroXRegister) { + let imm = icb.xvalue_of_imm(imm); + icb.xregister_write(rd_rs1, imm) +} + +#[cfg(test)] +mod test { + use crate::{ + backend_test, create_state, + machine_state::{ + MachineCoreState, MachineCoreStateLayout, main_memory::tests::T1K, registers::nz, + }, + }; + + backend_test!(test_run_li, F, { + let imm_rdrs1_res = [ + (0_i64, nz::t3, 0_u64), + (0xFFF0_0420, nz::t2, 0xFFF0_0420), + (-1, nz::t4, 0xFFFF_FFFF_FFFF_FFFF), + ]; + + for (imm, rd_rs1, res) in imm_rdrs1_res { + let mut state = create_state!(MachineCoreState, MachineCoreStateLayout, F, T1K); + super::run_li(&mut state, imm, rd_rs1); + assert_eq!(state.hart.xregisters.read_nz(rd_rs1), res); + } + }); +} diff --git a/src/riscv/lib/src/interpreter/rv32c.rs b/src/riscv/lib/src/interpreter/rv32c.rs index eb4fc7ddc041..4baa7c64ac9f 100644 --- a/src/riscv/lib/src/interpreter/rv32c.rs +++ b/src/riscv/lib/src/interpreter/rv32c.rs @@ -119,30 +119,6 @@ impl XRegisters where M: backend::ManagerReadWrite, { - /// Loads the immediate `imm` into register `rd_rs1`. - /// - /// Relevant RISC-V opcodes: - /// - C.LI - /// - ADD - /// - ADDI - /// - ANDI - /// - ORI - /// - XORI - /// - SLLI - /// - SRLI - /// - SRAI - /// - AND - /// - C.AND - /// - OR - /// - XOR - /// - SLL - /// - SRL - /// - SRA - /// - SUB - pub fn run_li(&mut self, imm: i64, rd_rs1: NonZeroXRegister) { - self.write_nz(rd_rs1, imm as u64) - } - /// `C.LUI` CI-type compressed instruction /// /// Loads the non-zero 6-bit immediate into bits 17–12 of the @@ -287,20 +263,6 @@ mod tests { } }); - backend_test!(test_run_cli, F, { - let imm_rdrs1_res = [ - (0_i64, nz::t3, 0_u64), - (0xFFF0_0420, nz::t2, 0xFFF0_0420), - (-1, nz::t4, 0xFFFF_FFFF_FFFF_FFFF), - ]; - - for (imm, rd_rs1, res) in imm_rdrs1_res { - let mut state = create_state!(HartState, F); - state.xregisters.run_li(imm, rd_rs1); - assert_eq!(state.xregisters.read_nz(rd_rs1), res); - } - }); - backend_test!(test_run_clui, F, { proptest!(|(imm in any::())| { let mut xregs = create_state!(XRegisters, F); diff --git a/src/riscv/lib/src/interpreter/rv32i.rs b/src/riscv/lib/src/interpreter/rv32i.rs index d124d1f41989..54a083aa3aab 100644 --- a/src/riscv/lib/src/interpreter/rv32i.rs +++ b/src/riscv/lib/src/interpreter/rv32i.rs @@ -51,15 +51,6 @@ where self.write_nz(rd, result) } - /// `LUI` U-type instruction - /// - /// Set the upper 20 bits of the `rd` register with the `U-type` formatted immediate `imm` - pub fn run_lui(&mut self, imm: i64, rd: NonZeroXRegister) { - // Being a `U-type` operation, the immediate is correctly formatted - // (lower 12 bits cleared and the value is sign-extended) - self.write_nz(rd, imm as u64); - } - /// Saves in `rd` the bitwise AND between the value in `rs1` and `imm` /// /// Relevant RISC-V opcodes: diff --git a/src/riscv/lib/src/jit.rs b/src/riscv/lib/src/jit.rs index 297bfc049931..8c3cffaf461b 100644 --- a/src/riscv/lib/src/jit.rs +++ b/src/riscv/lib/src/jit.rs @@ -337,9 +337,16 @@ mod tests { // Arrange let scenarios: &[&[I]] = &[ - &[I::new_mv(x2, x1, Compressed)], - &[I::new_mv(x2, x1, Uncompressed)], &[ + I::new_li(x1, 1, Compressed), + I::new_mv(x2, x1, Compressed), + ], + &[ + I::new_li(x1, 1, Uncompressed), + I::new_mv(x2, x1, Uncompressed), + ], + &[ + I::new_li(x1, 1, Uncompressed), I::new_mv(x2, x1, Compressed), I::new_mv(x3, x2, Uncompressed), ], @@ -365,13 +372,10 @@ mod tests { interpreted.hart.pc.write(initial_pc); jitted.hart.pc.write(initial_pc); - interpreted.hart.xregisters.write_nz(x1, 1); - jitted.hart.xregisters.write_nz(x1, 1); - // Act let fun = jit .compile(instructions(&block).as_slice()) - .expect("Compilation of CNop should succeed"); + .expect("Compilation should succeed"); let interpreted_res = block.callable().unwrap().run_block( &mut interpreted, @@ -413,6 +417,7 @@ mod tests { // calculate fibonacci(4) == 5 let scenario: &[I] = &[ + I::new_li(x1, 1, Uncompressed), I::new_add(x2, x2, x1, Compressed), I::new_add(x1, x1, x2, Uncompressed), I::new_add(x2, x2, x1, Uncompressed), @@ -437,13 +442,10 @@ mod tests { interpreted.hart.pc.write(initial_pc); jitted.hart.pc.write(initial_pc); - interpreted.hart.xregisters.write_nz(x1, 1); - jitted.hart.xregisters.write_nz(x1, 1); - // Act let fun = jit .compile(instructions(&block).as_slice()) - .expect("Compilation of CNop should succeed"); + .expect("Compilation should succeed"); let interpreted_res = block.callable().unwrap().run_block( &mut interpreted, @@ -503,8 +505,6 @@ mod tests { let initial_pc = 0; jitted.hart.pc.write(initial_pc); - jitted.hart.xregisters.write_nz(x1, 1); - // Act let res = jit.compile(instructions(&block).as_slice()); diff --git a/src/riscv/lib/src/jit/builder.rs b/src/riscv/lib/src/jit/builder.rs index a8ef52ed05e3..8d5d8cab04f9 100644 --- a/src/riscv/lib/src/jit/builder.rs +++ b/src/riscv/lib/src/jit/builder.rs @@ -7,7 +7,7 @@ //! [instructions]: crate::machine_state::instruction::Instruction use cranelift::{ - codegen::ir::{InstBuilder, MemFlags, Type, Value}, + codegen::ir::{InstBuilder, MemFlags, Type, Value, types::I64}, frontend::FunctionBuilder, }; @@ -97,6 +97,10 @@ impl<'a, ML: MainMemoryLayout, JSA: JitStateAccess> ICB for Builder<'a, ML, JSA> .xreg_write(&mut self.builder, self.core_ptr_val, reg, value) } + fn xvalue_of_imm(&mut self, imm: i64) -> Self::XValue { + self.builder.ins().iconst(I64, imm) + } + fn xvalue_wrapping_add(&mut self, lhs: Self::XValue, rhs: Self::XValue) -> Self::XValue { // wrapping add; does not depend on whether operands are signed self.builder.ins().iadd(lhs, rhs) diff --git a/src/riscv/lib/src/machine_state/instruction.rs b/src/riscv/lib/src/machine_state/instruction.rs index ec47cf2f9182..bbb66a85a5a7 100644 --- a/src/riscv/lib/src/machine_state/instruction.rs +++ b/src/riscv/lib/src/machine_state/instruction.rs @@ -29,7 +29,7 @@ use super::{ use crate::{ default::ConstDefault, instruction_context::{ICB, IcbLoweringFn}, - interpreter::{c, i}, + interpreter::{c, i, load_store}, machine_state::ProgramCounterUpdate::{Next, Set}, parser::instruction::{ AmoArgs, CIBDTypeArgs, CIBNZTypeArgs, CIBTypeArgs, CJTypeArgs, CNZRTypeArgs, CRJTypeArgs, @@ -574,6 +574,7 @@ impl OpCode { Self::Mv => Some(Args::run_mv), Self::Nop => Some(Args::run_nop), Self::Add => Some(Args::run_add), + Self::Li => Some(Args::run_li), _ => None, } } @@ -885,6 +886,15 @@ macro_rules! impl_ci_type { Ok(ProgramCounterUpdate::Next(self.width)) } }; + + ($impl: path, $fn: ident, non_zero) => { + /// SAFETY: This function must only be called on an `Args` belonging + /// to the same OpCode as the OpCode used to derive this function. + unsafe fn $fn(&self, icb: &mut I) -> ::IResult { + $impl(icb, self.imm, self.rd.nzx); + icb.ok(ProgramCounterUpdate::Next(self.width)) + } + }; } macro_rules! impl_cr_type { @@ -1319,7 +1329,7 @@ impl Args { impl_store_type!(run_csw); impl_cb_type!(run_beqz); impl_cb_type!(run_bnez); - impl_ci_type!(run_li, non_zero); + impl_ci_type!(load_store::run_li, run_li, non_zero); impl_ci_type!(run_clui, non_zero); impl_cr_type!(run_neg, non_zero); impl_css_type!(run_cswsp); -- GitLab From dac2af123f3e24fd259cf2161931e92c2144cb68 Mon Sep 17 00:00:00 2001 From: Emma Turner Date: Tue, 18 Feb 2025 15:30:13 +0000 Subject: [PATCH 2/2] RISC-V: deduplicate Lui, CLui --- src/riscv/lib/src/interpreter/load_store.rs | 24 ++++++++++++- src/riscv/lib/src/interpreter/rv32c.rs | 34 +------------------ src/riscv/lib/src/interpreter/rv32i.rs | 21 +----------- src/riscv/lib/src/jit.rs | 5 +-- src/riscv/lib/src/machine_state.rs | 2 +- .../lib/src/machine_state/instruction.rs | 30 ++++------------ .../instruction/tagged_instruction.rs | 6 ++-- src/riscv/lib/src/parser/instruction.rs | 11 ++++++ .../lib/tests/expected/jstz/state_hash_final | 2 +- 9 files changed, 48 insertions(+), 87 deletions(-) diff --git a/src/riscv/lib/src/interpreter/load_store.rs b/src/riscv/lib/src/interpreter/load_store.rs index bbbdace76d21..001d807da72e 100644 --- a/src/riscv/lib/src/interpreter/load_store.rs +++ b/src/riscv/lib/src/interpreter/load_store.rs @@ -4,6 +4,7 @@ use crate::{instruction_context::ICB, machine_state::registers::NonZeroXRegister /// /// Relevant RISC-V opcodes: /// - C.LI +/// - C.LUI /// - ADD /// - ADDI /// - ANDI @@ -27,10 +28,14 @@ pub fn run_li(icb: &mut impl ICB, imm: i64, rd_rs1: NonZeroXRegister) { #[cfg(test)] mod test { + use proptest::{arbitrary::any, prop_assert_eq, proptest}; + use crate::{ backend_test, create_state, machine_state::{ - MachineCoreState, MachineCoreStateLayout, main_memory::tests::T1K, registers::nz, + MachineCoreState, MachineCoreStateLayout, + main_memory::tests::T1K, + registers::{a2, a3, a4, nz}, }, }; @@ -47,4 +52,21 @@ mod test { assert_eq!(state.hart.xregisters.read_nz(rd_rs1), res); } }); + + backend_test!(test_lui, F, { + proptest!(|(imm in any::())| { + let mut state = create_state!(MachineCoreState, MachineCoreStateLayout, F, T1K); + state.hart.xregisters.write(a2, 0); + state.hart.xregisters.write(a4, 0); + + // U-type immediate sets imm[31:20] + let imm = imm & 0xFFFF_F000; + super::run_li(&mut state, imm, nz::a3); + // read value is the expected one + prop_assert_eq!(state.hart.xregisters.read(a3), imm as u64); + // it doesn't modify other registers + prop_assert_eq!(state.hart.xregisters.read(a2), 0); + prop_assert_eq!(state.hart.xregisters.read(a4), 0); + }); + }); } diff --git a/src/riscv/lib/src/interpreter/rv32c.rs b/src/riscv/lib/src/interpreter/rv32c.rs index 4baa7c64ac9f..b0830e73ce63 100644 --- a/src/riscv/lib/src/interpreter/rv32c.rs +++ b/src/riscv/lib/src/interpreter/rv32c.rs @@ -12,7 +12,7 @@ use crate::{ MachineCoreState, ProgramCounterUpdate, hart_state::HartState, main_memory::{Address, MainMemoryLayout}, - registers::{NonZeroXRegister, XRegister, XRegisters, sp}, + registers::{NonZeroXRegister, XRegister, sp}, }, parser::instruction::InstrWidth, state_backend as backend, @@ -115,20 +115,6 @@ where } } -impl XRegisters -where - M: backend::ManagerReadWrite, -{ - /// `C.LUI` CI-type compressed instruction - /// - /// Loads the non-zero 6-bit immediate into bits 17–12 of the - /// register `rd_rs1`, clears the bottom 12 bits, and sign-extends bit 17 - /// into all higher bits of `rd_rs1`. - pub fn run_clui(&mut self, imm: i64, rd_rs1: NonZeroXRegister) { - self.write_nz(rd_rs1, imm as u64) - } -} - impl MachineCoreState where ML: MainMemoryLayout, @@ -195,7 +181,6 @@ mod tests { hart_state::{HartState, HartStateLayout}, main_memory::tests::T1K, registers::{ - XRegisters, XRegistersLayout, nz::{self, a0}, t1, }, @@ -263,23 +248,6 @@ mod tests { } }); - backend_test!(test_run_clui, F, { - proptest!(|(imm in any::())| { - let mut xregs = create_state!(XRegisters, F); - xregs.write_nz(nz::a2, 0); - xregs.write_nz(nz::a4, 0); - - // U-type immediate sets imm[31:20] - let imm = imm & 0xFFFF_F000; - xregs.run_clui(imm, nz::a3); - // read value is the expected one - prop_assert_eq!(xregs.read_nz(nz::a3), imm as u64); - // it doesn't modify other registers - prop_assert_eq!(xregs.read_nz(nz::a2), 0); - prop_assert_eq!(xregs.read_nz(nz::a4), 0); - }); - }); - macro_rules! test_shift_instr { ($state:ident, $shift_fn:tt, $imm:expr, $rd_rs1:ident, $r1_val:expr, $expected_val:expr diff --git a/src/riscv/lib/src/interpreter/rv32i.rs b/src/riscv/lib/src/interpreter/rv32i.rs index 54a083aa3aab..72303884fdfb 100644 --- a/src/riscv/lib/src/interpreter/rv32i.rs +++ b/src/riscv/lib/src/interpreter/rv32i.rs @@ -383,9 +383,7 @@ mod tests { hart_state::{HartState, HartStateLayout}, main_memory::{Address, tests::T1K}, mode::Mode, - registers::{ - XRegisters, XRegistersLayout, a0, a1, a2, a3, a4, fa0, nz, t0, t1, t2, t3, - }, + registers::{XRegisters, XRegistersLayout, a0, a1, a2, fa0, nz, t0, t1, t2, t3}, }, parser::instruction::{FenceSet, InstrWidth}, traps::Exception, @@ -801,23 +799,6 @@ mod tests { } }); - backend_test!(test_lui, F, { - proptest!(|(imm in any::())| { - let mut xregs = create_state!(XRegisters, F); - xregs.write(a2, 0); - xregs.write(a4, 0); - - // U-type immediate sets imm[31:20] - let imm = imm & 0xFFFF_F000; - xregs.run_lui(imm, nz::a3); - // read value is the expected one - prop_assert_eq!(xregs.read(a3), imm as u64); - // it doesn't modify other registers - prop_assert_eq!(xregs.read(a2), 0); - prop_assert_eq!(xregs.read(a4), 0); - }); - }); - backend_test!(test_slt, F, { let mut xregs = create_state!(XRegisters, F); diff --git a/src/riscv/lib/src/jit.rs b/src/riscv/lib/src/jit.rs index 8c3cffaf461b..3705c28f9e95 100644 --- a/src/riscv/lib/src/jit.rs +++ b/src/riscv/lib/src/jit.rs @@ -337,10 +337,7 @@ mod tests { // Arrange let scenarios: &[&[I]] = &[ - &[ - I::new_li(x1, 1, Compressed), - I::new_mv(x2, x1, Compressed), - ], + &[I::new_li(x1, 1, Compressed), I::new_mv(x2, x1, Compressed)], &[ I::new_li(x1, 1, Uncompressed), I::new_mv(x2, x1, Uncompressed), diff --git a/src/riscv/lib/src/machine_state.rs b/src/riscv/lib/src/machine_state.rs index 0bc697d39596..537849bccaf3 100644 --- a/src/riscv/lib/src/machine_state.rs +++ b/src/riscv/lib/src/machine_state.rs @@ -1419,7 +1419,7 @@ mod tests { let jalr_bytes: u32 = 0x50067; let block_b = [ Instruction::try_from(TaggedInstruction { - opcode: OpCode::CLui, + opcode: OpCode::Li, args: TaggedArgs { rd: nz::a1.into(), imm: (u16::bits_subset(overwrite_bytes, 15, 12) as i64) << 12, diff --git a/src/riscv/lib/src/machine_state/instruction.rs b/src/riscv/lib/src/machine_state/instruction.rs index bbb66a85a5a7..535283b5bf2f 100644 --- a/src/riscv/lib/src/machine_state/instruction.rs +++ b/src/riscv/lib/src/machine_state/instruction.rs @@ -209,7 +209,6 @@ pub enum OpCode { Bgeu, // RV64I U-type instructions - Lui, Auipc, // RV64I jump instructions @@ -336,7 +335,6 @@ pub enum OpCode { CSwsp, CJr, CJalr, - CLui, CAddw, CSubw, @@ -421,7 +419,6 @@ impl OpCode { Self::Bge => Args::run_bge, Self::Bltu => Args::run_bltu, Self::Bgeu => Args::run_bgeu, - Self::Lui => Args::run_lui, Self::Auipc => Args::run_auipc, Self::Jal => Args::run_jal, Self::Jalr => Args::run_jalr, @@ -538,7 +535,6 @@ impl OpCode { Self::Beqz => Args::run_beqz, Self::Bnez => Args::run_bnez, Self::Li => Args::run_li, - Self::CLui => Args::run_clui, Self::Mv => Args::run_mv, Self::CAddw => Args::run_caddw, Self::CSubw => Args::run_csubw, @@ -1168,17 +1164,6 @@ impl Args { impl_b_type!(run_bgeu); // RV64I U-type instructions - // - /// SAFETY: This function must only be called on an `Args` belonging - /// to the same OpCode as the OpCode used to derive this function. - unsafe fn run_lui( - &self, - core: &mut MachineCoreState, - ) -> Result { - core.hart.xregisters.run_lui(self.imm, self.rd.nzx); - Ok(Next(self.width)) - } - /// SAFETY: This function must only be called on an `Args` belonging /// to the same OpCode as the OpCode used to derive this function. unsafe fn run_auipc( @@ -1330,7 +1315,6 @@ impl Args { impl_cb_type!(run_beqz); impl_cb_type!(run_bnez); impl_ci_type!(load_store::run_li, run_li, non_zero); - impl_ci_type!(run_clui, non_zero); impl_cr_type!(run_neg, non_zero); impl_css_type!(run_cswsp); @@ -1528,10 +1512,9 @@ impl From<&InstrCacheable> for Instruction { }, // RV64I U-type instructions - InstrCacheable::Lui(args) => Instruction { - opcode: OpCode::Lui, - args: args.into(), - }, + InstrCacheable::Lui(args) => { + Instruction::new_li(args.rd, args.imm, InstrWidth::Uncompressed) + } InstrCacheable::Auipc(args) => Instruction { opcode: OpCode::Auipc, args: args.into(), @@ -1997,10 +1980,9 @@ impl From<&InstrCacheable> for Instruction { InstrCacheable::CLi(args) => { Instruction::new_li(args.rd_rs1, args.imm, InstrWidth::Compressed) } - InstrCacheable::CLui(args) => Instruction { - opcode: OpCode::CLui, - args: args.into(), - }, + InstrCacheable::CLui(args) => { + Instruction::new_li(args.rd_rs1, args.imm, InstrWidth::Compressed) + } InstrCacheable::CAddi(args) => { Instruction::new_addi(args.rd_rs1, args.rd_rs1, args.imm, InstrWidth::Compressed) } diff --git a/src/riscv/lib/src/machine_state/instruction/tagged_instruction.rs b/src/riscv/lib/src/machine_state/instruction/tagged_instruction.rs index 5d639fa23b85..3e87c8363642 100644 --- a/src/riscv/lib/src/machine_state/instruction/tagged_instruction.rs +++ b/src/riscv/lib/src/machine_state/instruction/tagged_instruction.rs @@ -355,11 +355,11 @@ pub fn opcode_to_argsshape(opcode: &OpCode) -> ArgsShape { Fsw | Fsd | CFsd | CFsdsp => ArgsShape::XSrcFSrc, Addi | Andi | Ori | Xori | Slli | Srli | Srai | Add | Sub | Mv | Neg | And | Or | Xor - | Sll | Srl | Sra | Jal | J | CJr | CJalr | CAddiw | Li | CLui | CLdsp | CLwsp | Nop - | Beq | Beqz | Bne | Bnez => ArgsShape::NZXSrcNZXDest, + | Sll | Srl | Sra | Jal | J | CJr | CJalr | CAddiw | Li | CLdsp | CLwsp | Nop | Beq + | Beqz | Bne | Bnez => ArgsShape::NZXSrcNZXDest, Addiw | Addw | Subw | Sllw | Srlw | Sraw | Slti | Sltiu | Slliw | Srliw | Sraiw | Slt - | Sltu | Lui | Auipc => ArgsShape::XSrcNZXDest, + | Sltu | Auipc => ArgsShape::XSrcNZXDest, } } diff --git a/src/riscv/lib/src/parser/instruction.rs b/src/riscv/lib/src/parser/instruction.rs index 9fc1cc02c73d..4b1d3eecf918 100644 --- a/src/riscv/lib/src/parser/instruction.rs +++ b/src/riscv/lib/src/parser/instruction.rs @@ -362,6 +362,12 @@ pub enum InstrCacheable { Bgeu(SBTypeArgs), // RV64I U-type instructions + /// `LUI` U-type instruction + /// + /// Set the upper 20 bits of the `rd` register with the `U-type` formatted immediate `imm`. + /// + /// Being a `U-type` operation, the immediate is correctly formatted + /// (lower 12 bits cleared and the value is sign-extended). Lui(NonZeroRdUJTypeArgs), Auipc(NonZeroRdUJTypeArgs), @@ -506,6 +512,11 @@ pub enum InstrCacheable { CBnez(CIBTypeArgs), /// `C.LI` - Loads the sign-extended 6-bit immediate into register `rd_rs1`. CLi(CIBNZTypeArgs), + /// `C.LUI` CI-type compressed instruction + /// + /// Loads the non-zero 6-bit immediate into bits 17–12 of the + /// register `rd_rs1`, clears the bottom 12 bits, and sign-extends bit 17 + /// into all higher bits of `rd_rs1`. CLui(CIBNZTypeArgs), /// `C.ADDI` - Adds the non-zero sign-extended 6-bit `imm` /// to the value in `rd_rs1` then writes the result to `rd_rs1`. diff --git a/src/riscv/lib/tests/expected/jstz/state_hash_final b/src/riscv/lib/tests/expected/jstz/state_hash_final index acf8c0619f08..d60a189a8274 100644 --- a/src/riscv/lib/tests/expected/jstz/state_hash_final +++ b/src/riscv/lib/tests/expected/jstz/state_hash_final @@ -1 +1 @@ -Hash { digest: [71, 131, 248, 200, 18, 129, 220, 238, 41, 211, 109, 199, 226, 60, 74, 80, 136, 192, 202, 0, 221, 78, 90, 209, 250, 212, 184, 168, 117, 8, 62, 31] } +Hash { digest: [20, 134, 41, 70, 168, 216, 54, 120, 23, 45, 169, 180, 229, 90, 3, 58, 60, 110, 10, 22, 198, 183, 164, 159, 145, 187, 219, 228, 129, 89, 17, 131] } -- GitLab