From 63fb05163de52495309394320ca4b9feb74bb0ae Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 1 Oct 2025 16:20:15 +0000 Subject: [PATCH 1/4] Initial plan From 57647da77253bf610957178b8e747833078e9e05 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 1 Oct 2025 16:25:54 +0000 Subject: [PATCH 2/4] Fix li instruction to properly initialize register to 0 Co-authored-by: petitstrawberry <14030185+petitstrawberry@users.noreply.github.com> --- src/riscv64/builder.rs | 8 +++++- src/riscv64/tests.rs | 56 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/src/riscv64/builder.rs b/src/riscv64/builder.rs index cbdf9de..47a75cb 100644 --- a/src/riscv64/builder.rs +++ b/src/riscv64/builder.rs @@ -571,7 +571,13 @@ impl Riscv64InstructionBuilder { self.lui(rd, upper as u32); } if lower != 0 || upper == 0 { - self.addi(rd, rd, lower as i16); + // Special case: when imm is 0, use x0 (zero register) as source + // to properly initialize rd to 0, rather than adding 0 to rd's current value + if imm == 0 { + self.addi(rd, super::reg::X0, 0); + } else { + self.addi(rd, rd, lower as i16); + } } self } diff --git a/src/riscv64/tests.rs b/src/riscv64/tests.rs index 638e608..bf07272 100644 --- a/src/riscv64/tests.rs +++ b/src/riscv64/tests.rs @@ -1605,6 +1605,62 @@ fn test_binary_correctness_multiline_macro_comparison() { "lui x1, 0x12345\naddi x2, x1, 100\nadd x3, x1, x2\nsub x4, x3, x1\nxor x5, x3, x4\n"); } +// Test li pseudo-instruction +#[cfg(feature = "std")] +#[test] +fn test_li_pseudo_instruction() { + // Test li with imm=0 (should generate "addi rd, x0, 0", not "addi rd, rd, 0") + let mut builder = Riscv64InstructionBuilder::new(); + builder.li(reg::X1, 0); + let instructions = builder.instructions(); + + // Debug: print what was actually generated + println!("li(x1, 0) generated {} instructions:", instructions.len()); + for (i, instr) in instructions.iter().enumerate() { + let val = instr.value() as u32; + println!(" Instruction {}: 0x{:08x}", i, val); + let opcode = val & 0x7F; + let rd = (val >> 7) & 0x1F; + let rs1 = (val >> 15) & 0x1F; + let imm = ((val as i32) >> 20); + println!(" opcode=0x{:02x}, rd=x{}, rs1=x{}, imm={}", opcode, rd, rs1, imm); + } + + compare_instruction(instructions[0], "addi x1, x0, 0\n"); + + // Test li with small positive immediate + let mut builder = Riscv64InstructionBuilder::new(); + builder.li(reg::X2, 100); + let instructions = builder.instructions(); + compare_instruction(instructions[0], "addi x2, x0, 100\n"); + + // Test li with small negative immediate + let mut builder = Riscv64InstructionBuilder::new(); + builder.li(reg::X3, -50); + let instructions = builder.instructions(); + compare_instruction(instructions[0], "addi x3, x0, -50\n"); + + // Test li with large immediate requiring lui+addi + let mut builder = Riscv64InstructionBuilder::new(); + builder.li(reg::X4, 0x12345678); + let instructions = builder.instructions(); + // Large immediates should use lui followed by addi + assert_eq!(instructions.len(), 2); + compare_instructions(&instructions, "lui x4, 0x12346\naddi x4, x4, 0x678\n"); + + // Test li with max 12-bit immediate (fits in single addi) + let mut builder = Riscv64InstructionBuilder::new(); + builder.li(reg::X5, 2047); + let instructions = builder.instructions(); + compare_instruction(instructions[0], "addi x5, x0, 2047\n"); + + // Test li with min 12-bit immediate (fits in single addi) + let mut builder = Riscv64InstructionBuilder::new(); + builder.li(reg::X6, -2048); + let instructions = builder.instructions(); + compare_instruction(instructions[0], "addi x6, x0, -2048\n"); +} + // JIT execution tests #[cfg(feature = "std")] #[test] From 2b578501eccedfcfca8c5bc8e7e8847276cdae3b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 1 Oct 2025 16:27:53 +0000 Subject: [PATCH 3/4] Fix li instruction for all small immediates (when upper==0) Co-authored-by: petitstrawberry <14030185+petitstrawberry@users.noreply.github.com> --- src/riscv64/builder.rs | 8 ++++---- src/riscv64/tests.rs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/riscv64/builder.rs b/src/riscv64/builder.rs index 47a75cb..020a4bc 100644 --- a/src/riscv64/builder.rs +++ b/src/riscv64/builder.rs @@ -571,10 +571,10 @@ impl Riscv64InstructionBuilder { self.lui(rd, upper as u32); } if lower != 0 || upper == 0 { - // Special case: when imm is 0, use x0 (zero register) as source - // to properly initialize rd to 0, rather than adding 0 to rd's current value - if imm == 0 { - self.addi(rd, super::reg::X0, 0); + // When upper == 0, rd has not been initialized by lui, + // so we must use x0 (zero register) as source to properly initialize rd + if upper == 0 { + self.addi(rd, super::reg::X0, lower as i16); } else { self.addi(rd, rd, lower as i16); } diff --git a/src/riscv64/tests.rs b/src/riscv64/tests.rs index bf07272..5068248 100644 --- a/src/riscv64/tests.rs +++ b/src/riscv64/tests.rs @@ -1622,7 +1622,7 @@ fn test_li_pseudo_instruction() { let opcode = val & 0x7F; let rd = (val >> 7) & 0x1F; let rs1 = (val >> 15) & 0x1F; - let imm = ((val as i32) >> 20); + let imm = (val as i32) >> 20; println!(" opcode=0x{:02x}, rd=x{}, rs1=x{}, imm={}", opcode, rd, rs1, imm); } From 1fc7ea995c7a8c1c4246b862d165ba6ec7e1143b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 1 Oct 2025 23:33:30 +0000 Subject: [PATCH 4/4] Fix test expectation for li instruction with large immediate Co-authored-by: petitstrawberry <14030185+petitstrawberry@users.noreply.github.com> --- src/riscv64/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/riscv64/tests.rs b/src/riscv64/tests.rs index 5068248..6f41482 100644 --- a/src/riscv64/tests.rs +++ b/src/riscv64/tests.rs @@ -1646,7 +1646,7 @@ fn test_li_pseudo_instruction() { let instructions = builder.instructions(); // Large immediates should use lui followed by addi assert_eq!(instructions.len(), 2); - compare_instructions(&instructions, "lui x4, 0x12346\naddi x4, x4, 0x678\n"); + compare_instructions(&instructions, "lui x4, 0x12345\naddi x4, x4, 0x678\n"); // Test li with max 12-bit immediate (fits in single addi) let mut builder = Riscv64InstructionBuilder::new();