Skip to content

Fix riscv64 li pseudo-instruction to properly initialize registers with small immediates#21

Merged
petitstrawberry merged 4 commits intodevelopfrom
copilot/fix-b49dd1d2-c6d9-4840-afc3-6a17f0c2e855
Oct 2, 2025
Merged

Fix riscv64 li pseudo-instruction to properly initialize registers with small immediates#21
petitstrawberry merged 4 commits intodevelopfrom
copilot/fix-b49dd1d2-c6d9-4840-afc3-6a17f0c2e855

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Oct 1, 2025

Problem

The li (load immediate) pseudo-instruction was generating incorrect code when loading small immediate values (those that fit in 12 bits, including 0) into registers. Instead of initializing the destination register to the immediate value, it was adding the immediate to the register's current uninitialized value.

For example:

builder.li(reg::X1, 0);   // Should initialize x1 to 0

This was incorrectly generating:

addi x1, x1, 0    # Adds 0 to x1's current value - doesn't initialize!

When it should generate:

addi x1, x0, 0    # Adds 0 to zero register - properly initializes x1 to 0

Root Cause

The li instruction implementation uses a two-part strategy:

  1. Load upper 20 bits with lui rd, upper (when upper != 0)
  2. Add lower 12 bits with addi rd, rd, lower

The bug occurred when upper == 0 (i.e., the immediate fits in 12 bits). In this case, step 1 was skipped, leaving rd uninitialized. The code then executed addi rd, rd, lower, which incorrectly used rd as both source and destination.

Solution

Modified the li function to use x0 (the hardwired zero register) as the source register when upper == 0:

if upper == 0 {
    self.addi(rd, super::reg::X0, lower as i16);  // Use x0 as source
} else {
    self.addi(rd, rd, lower as i16);              // rd was initialized by lui
}

Testing

Added comprehensive test test_li_pseudo_instruction that verifies correct behavior for:

  • Zero initialization: li(x1, 0)addi x1, x0, 0
  • Small positive immediates: li(x2, 100)addi x2, x0, 100
  • Small negative immediates: li(x3, -50)addi x3, x0, -50
  • Large immediates requiring two instructions: li(x4, 0x12345678)lui x4, 0x12345; addi x4, x4, 0x678
  • Boundary values (max/min 12-bit immediates) ✅

All tests pass (81/81).

Fixes issue where li pseudo-instruction with immediate value of 0 (and other small values) was generating incorrect instructions.

Fixes #20

Original prompt

This section details on the original issue you should resolve

<issue_title>riscv64において, 疑似命令liの即値が0の時, 誤った命令が生成される</issue_title>
<issue_description>今の実装だとimm=0の時, addi rd, rd, 0となってしまい, 0初期化されない.
immが0の場合のみ, 特別扱いして, addi rd,x0, 0または, xor rd, rd, rdにする必要がある</issue_description>

Comments on the Issue (you are @copilot in this section)

Fixes #20

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 2 commits October 1, 2025 16:25
Co-authored-by: petitstrawberry <14030185+petitstrawberry@users.noreply.github.com>
Co-authored-by: petitstrawberry <14030185+petitstrawberry@users.noreply.github.com>
Copilot AI changed the title [WIP] riscv64において, 疑似命令liの即値が0の時, 誤った命令が生成される Fix riscv64 li pseudo-instruction to properly initialize registers with small immediates Oct 1, 2025
Copilot AI requested a review from petitstrawberry October 1, 2025 16:29
@petitstrawberry
Copy link
Copy Markdown
Owner

@copilot testしたら失敗してたわ。確認して。

Co-authored-by: petitstrawberry <14030185+petitstrawberry@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Oct 1, 2025

@copilot testしたら失敗してたわ。確認して。

Fixed in commit 1fc7ea9. The test failure was due to an incorrect expectation in the test I added. For li(x4, 0x12345678), the correct encoding is lui x4, 0x12345; addi x4, x4, 0x678, not lui x4, 0x12346 as I had mistakenly written. The fix itself was correct - it properly initializes registers to 0 and other small immediate values using x0 as the source register.

Copy link
Copy Markdown
Owner

@petitstrawberry petitstrawberry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(๑•̀ㅂ•́)و✧

@petitstrawberry petitstrawberry marked this pull request as ready for review October 1, 2025 23:40
Copilot AI review requested due to automatic review settings October 1, 2025 23:40
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes a critical bug in the RISC-V 64 li (load immediate) pseudo-instruction that was generating incorrect code when loading small immediate values (those fitting in 12 bits) into registers. The bug caused the instruction to add the immediate to the register's uninitialized value instead of properly initializing the register.

  • Fixed the li implementation to use the zero register (x0) as source when the upper 20 bits are zero
  • Added comprehensive test coverage for various immediate value scenarios
  • Ensures proper register initialization for small immediates including zero

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/riscv64/builder.rs Fixed li pseudo-instruction logic to use zero register for proper initialization when upper bits are zero
src/riscv64/tests.rs Added comprehensive test suite covering zero, small positive/negative, large, and boundary value immediates

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

@petitstrawberry petitstrawberry merged commit e36683e into develop Oct 2, 2025
6 checks passed
@petitstrawberry petitstrawberry deleted the copilot/fix-b49dd1d2-c6d9-4840-afc3-6a17f0c2e855 branch October 2, 2025 02:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

riscv64において, 疑似命令liの即値が0の時, 誤った命令が生成される

3 participants