Skip to content

Support RV32I with only F extension and RV32E#53

Merged
nbdd0121 merged 2 commits intonbdd0121:trunkfrom
taiki-e:rv32
Jan 14, 2026
Merged

Support RV32I with only F extension and RV32E#53
nbdd0121 merged 2 commits intonbdd0121:trunkfrom
taiki-e:rv32

Conversation

@taiki-e
Copy link
Contributor

@taiki-e taiki-e commented Jan 13, 2026

This supports the following builtin RISC-V RV32 targets. (This allows all the current builtin bare-metal RISC-V targets to be supported by this crate.)

  • RV32I with only F extension:
    • riscv32imafc-unknown-none-elf
  • RV32E:
    • riscv32e-unknown-none-elf
    • riscv32em-unknown-none-elf
    • riscv32emc-unknown-none-elf

As with my PR that added RV32 support (#14), I tested catch_unwind + backtrace using the semihosting crate's test suite (taiki-e/semihosting@7199732).

Copy link
Owner

@nbdd0121 nbdd0121 left a comment

Choose a reason for hiding this comment

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

Thanks for the PR! Overall LGTM, some suggestions:

Comment on lines 29 to 33
for i in 0..=15 {
fmt.field(RiscV::register_name(Register(i as _)).unwrap(), &self.gp[i]);
}
#[cfg(not(target_feature = "e"))]
for i in 16..=31 {
Copy link
Owner

Choose a reason for hiding this comment

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

I think this can be written as for (i, gp) in self.gp.enumerate()?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated to use enumerate.

fn index(&self, reg: Register) -> &usize {
match reg {
Register(0..=31) => &self.gp[reg.0 as usize],
Register(0..=15) => &self.gp[reg.0 as usize],
Copy link
Owner

Choose a reason for hiding this comment

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

This can just be 0..=31 I think. The meaning of 16..=31 should still mean GP even in RV32? Turning a unimplemented!() panic into OOB panic is fine; the caller of C unwind API wouldn't pass in illegal register values anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Reverted this and similar changes.

Comment on lines 101 to 107
sw x0, 0x00(sp)
sw ra, 0x04(sp)
sw t0, 0x08(sp)
sw gp, 0x0C(sp)
sw tp, 0x10(sp)
sw s0, 0x20(sp)
sw s1, 0x24(sp)
Copy link
Owner

Choose a reason for hiding this comment

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

This part can be shared between E & I? IIUC the calling convention doesn't change the caller/callee-saved status of first 16 registers.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@nbdd0121 nbdd0121 merged commit 79d0ea1 into nbdd0121:trunk Jan 14, 2026
5 checks passed
@nbdd0121
Copy link
Owner

Thank you!

@taiki-e taiki-e deleted the rv32 branch January 14, 2026 16:23
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.

2 participants