Add RISC-V RV32 support
This commit is contained in:
parent
3dba9da864
commit
c88a9016fc
@ -9,7 +9,7 @@ This library serves two purposes:
|
|||||||
1. Provide a pure Rust alternative to libgcc_eh or libunwind.
|
1. Provide a pure Rust alternative to libgcc_eh or libunwind.
|
||||||
2. Provide easier unwinding support for `#![no_std]` targets.
|
2. Provide easier unwinding support for `#![no_std]` targets.
|
||||||
|
|
||||||
Currently supports x86_64, x86, RV64 and AArch64.
|
Currently supports x86_64, x86, RV64, RV32 and AArch64.
|
||||||
|
|
||||||
## Unwinder
|
## Unwinder
|
||||||
|
|
||||||
|
@ -13,6 +13,11 @@ mod riscv64;
|
|||||||
#[cfg(target_arch = "riscv64")]
|
#[cfg(target_arch = "riscv64")]
|
||||||
pub use riscv64::*;
|
pub use riscv64::*;
|
||||||
|
|
||||||
|
#[cfg(target_arch = "riscv32")]
|
||||||
|
mod riscv32;
|
||||||
|
#[cfg(target_arch = "riscv32")]
|
||||||
|
pub use riscv32::*;
|
||||||
|
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
mod aarch64;
|
mod aarch64;
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
@ -22,6 +27,7 @@ pub use aarch64::*;
|
|||||||
target_arch = "x86_64",
|
target_arch = "x86_64",
|
||||||
target_arch = "x86",
|
target_arch = "x86",
|
||||||
target_arch = "riscv64",
|
target_arch = "riscv64",
|
||||||
|
target_arch = "riscv32",
|
||||||
target_arch = "aarch64"
|
target_arch = "aarch64"
|
||||||
)))]
|
)))]
|
||||||
compile_error!("Current architecture is not supported");
|
compile_error!("Current architecture is not supported");
|
||||||
|
203
src/unwinder/arch/riscv32.rs
Normal file
203
src/unwinder/arch/riscv32.rs
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
use core::arch::asm;
|
||||||
|
use core::fmt;
|
||||||
|
use core::ops;
|
||||||
|
use gimli::{Register, RiscV};
|
||||||
|
|
||||||
|
// Match DWARF_FRAME_REGISTERS in libgcc
|
||||||
|
pub const MAX_REG_RULES: usize = 65;
|
||||||
|
|
||||||
|
#[cfg(all(target_feature = "f", not(target_feature = "d")))]
|
||||||
|
compile_error!("RISC-V with only F extension is not supported");
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Clone, Default)]
|
||||||
|
pub struct Context {
|
||||||
|
pub gp: [usize; 32],
|
||||||
|
#[cfg(target_feature = "d")]
|
||||||
|
pub fp: [u64; 32],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for Context {
|
||||||
|
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
let mut fmt = fmt.debug_struct("Context");
|
||||||
|
for i in 0..=31 {
|
||||||
|
fmt.field(RiscV::register_name(Register(i as _)).unwrap(), &self.gp[i]);
|
||||||
|
}
|
||||||
|
#[cfg(target_feature = "d")]
|
||||||
|
for i in 0..=31 {
|
||||||
|
fmt.field(
|
||||||
|
RiscV::register_name(Register((i + 32) as _)).unwrap(),
|
||||||
|
&self.fp[i],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
fmt.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Index<Register> for Context {
|
||||||
|
type Output = usize;
|
||||||
|
|
||||||
|
fn index(&self, reg: Register) -> &usize {
|
||||||
|
match reg {
|
||||||
|
Register(0..=31) => &self.gp[reg.0 as usize],
|
||||||
|
// We cannot support indexing fp here. It is 64-bit if D extension is implemented,
|
||||||
|
// and 32-bit if only F extension is implemented.
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::IndexMut<gimli::Register> for Context {
|
||||||
|
fn index_mut(&mut self, reg: Register) -> &mut usize {
|
||||||
|
match reg {
|
||||||
|
Register(0..=31) => &mut self.gp[reg.0 as usize],
|
||||||
|
// We cannot support indexing fp here. It is 64-bit if D extension is implemented,
|
||||||
|
// and 32-bit if only F extension is implemented.
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! code {
|
||||||
|
(save_gp) => {
|
||||||
|
"
|
||||||
|
sw x0, 0x00(a0)
|
||||||
|
sw ra, 0x04(a0)
|
||||||
|
sw sp, 0x08(a0)
|
||||||
|
sw gp, 0x0C(a0)
|
||||||
|
sw tp, 0x10(a0)
|
||||||
|
sw s0, 0x20(a0)
|
||||||
|
sw s1, 0x24(a0)
|
||||||
|
sw s2, 0x48(a0)
|
||||||
|
sw s3, 0x4C(a0)
|
||||||
|
sw s4, 0x50(a0)
|
||||||
|
sw s5, 0x54(a0)
|
||||||
|
sw s6, 0x58(a0)
|
||||||
|
sw s7, 0x5C(a0)
|
||||||
|
sw s8, 0x60(a0)
|
||||||
|
sw s9, 0x64(a0)
|
||||||
|
sw s10, 0x68(a0)
|
||||||
|
sw s11, 0x6C(a0)
|
||||||
|
"
|
||||||
|
};
|
||||||
|
(save_fp) => {
|
||||||
|
"
|
||||||
|
fsd fs0, 0xC0(a0)
|
||||||
|
fsd fs1, 0xC8(a0)
|
||||||
|
fsd fs2, 0x110(a0)
|
||||||
|
fsd fs3, 0x118(a0)
|
||||||
|
fsd fs4, 0x120(a0)
|
||||||
|
fsd fs5, 0x128(a0)
|
||||||
|
fsd fs6, 0x130(a0)
|
||||||
|
fsd fs7, 0x138(a0)
|
||||||
|
fsd fs8, 0x140(a0)
|
||||||
|
fsd fs9, 0x148(a0)
|
||||||
|
fsd fs10, 0x150(a0)
|
||||||
|
fsd fs11, 0x158(a0)
|
||||||
|
"
|
||||||
|
};
|
||||||
|
(restore_gp) => {
|
||||||
|
"
|
||||||
|
lw ra, 0x04(a0)
|
||||||
|
lw sp, 0x08(a0)
|
||||||
|
lw gp, 0x0C(a0)
|
||||||
|
lw tp, 0x10(a0)
|
||||||
|
lw t0, 0x14(a0)
|
||||||
|
lw t1, 0x18(a0)
|
||||||
|
lw t2, 0x1C(a0)
|
||||||
|
lw s0, 0x20(a0)
|
||||||
|
lw s1, 0x24(a0)
|
||||||
|
lw a1, 0x2C(a0)
|
||||||
|
lw a2, 0x30(a0)
|
||||||
|
lw a3, 0x34(a0)
|
||||||
|
lw a4, 0x38(a0)
|
||||||
|
lw a5, 0x3C(a0)
|
||||||
|
lw a6, 0x40(a0)
|
||||||
|
lw a7, 0x44(a0)
|
||||||
|
lw s2, 0x48(a0)
|
||||||
|
lw s3, 0x4C(a0)
|
||||||
|
lw s4, 0x50(a0)
|
||||||
|
lw s5, 0x54(a0)
|
||||||
|
lw s6, 0x58(a0)
|
||||||
|
lw s7, 0x5C(a0)
|
||||||
|
lw s8, 0x60(a0)
|
||||||
|
lw s9, 0x64(a0)
|
||||||
|
lw s10, 0x68(a0)
|
||||||
|
lw s11, 0x6C(a0)
|
||||||
|
lw t3, 0x70(a0)
|
||||||
|
lw t4, 0x74(a0)
|
||||||
|
lw t5, 0x78(a0)
|
||||||
|
lw t6, 0x7C(a0)
|
||||||
|
"
|
||||||
|
};
|
||||||
|
(restore_fp) => {
|
||||||
|
"
|
||||||
|
fld ft0, 0x80(a0)
|
||||||
|
fld ft1, 0x88(a0)
|
||||||
|
fld ft2, 0x90(a0)
|
||||||
|
fld ft3, 0x98(a0)
|
||||||
|
fld ft4, 0xA0(a0)
|
||||||
|
fld ft5, 0xA8(a0)
|
||||||
|
fld ft6, 0xB0(a0)
|
||||||
|
fld ft7, 0xB8(a0)
|
||||||
|
fld fs0, 0xC0(a0)
|
||||||
|
fld fs1, 0xC8(a0)
|
||||||
|
fld fa0, 0xD0(a0)
|
||||||
|
fld fa1, 0xD8(a0)
|
||||||
|
fld fa2, 0xE0(a0)
|
||||||
|
fld fa3, 0xE8(a0)
|
||||||
|
fld fa4, 0xF0(a0)
|
||||||
|
fld fa5, 0xF8(a0)
|
||||||
|
fld fa6, 0x100(a0)
|
||||||
|
fld fa7, 0x108(a0)
|
||||||
|
fld fs2, 0x110(a0)
|
||||||
|
fld fs3, 0x118(a0)
|
||||||
|
fld fs4, 0x120(a0)
|
||||||
|
fld fs5, 0x128(a0)
|
||||||
|
fld fs6, 0x130(a0)
|
||||||
|
fld fs7, 0x138(a0)
|
||||||
|
fld fs8, 0x140(a0)
|
||||||
|
fld fs9, 0x148(a0)
|
||||||
|
fld fs10, 0x150(a0)
|
||||||
|
fld fs11, 0x158(a0)
|
||||||
|
fld ft8, 0x160(a0)
|
||||||
|
fld ft9, 0x168(a0)
|
||||||
|
fld ft10, 0x170(a0)
|
||||||
|
fld ft11, 0x178(a0)
|
||||||
|
"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[naked]
|
||||||
|
pub extern "C-unwind" fn save_context() -> Context {
|
||||||
|
// No need to save caller-saved registers here.
|
||||||
|
#[cfg(target_feature = "d")]
|
||||||
|
unsafe {
|
||||||
|
asm!(
|
||||||
|
concat!(code!(save_gp), code!(save_fp), "ret"),
|
||||||
|
options(noreturn)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#[cfg(not(target_feature = "d"))]
|
||||||
|
unsafe {
|
||||||
|
asm!(concat!(code!(save_gp), "ret"), options(noreturn));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[naked]
|
||||||
|
pub unsafe extern "C" fn restore_context(ctx: &Context) -> ! {
|
||||||
|
#[cfg(target_feature = "d")]
|
||||||
|
unsafe {
|
||||||
|
asm!(
|
||||||
|
concat!(code!(restore_fp), code!(restore_gp), "lw a0, 0x28(a0)\nret"),
|
||||||
|
options(noreturn)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#[cfg(not(target_feature = "d"))]
|
||||||
|
unsafe {
|
||||||
|
asm!(
|
||||||
|
concat!(code!(restore_gp), "lw a0, 0x28(a0)\nret"),
|
||||||
|
options(noreturn)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -6,6 +6,9 @@ use gimli::{Register, RiscV};
|
|||||||
// Match DWARF_FRAME_REGISTERS in libgcc
|
// Match DWARF_FRAME_REGISTERS in libgcc
|
||||||
pub const MAX_REG_RULES: usize = 65;
|
pub const MAX_REG_RULES: usize = 65;
|
||||||
|
|
||||||
|
#[cfg(all(target_feature = "f", not(target_feature = "d")))]
|
||||||
|
compile_error!("RISC-V with only F extension is not supported");
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
pub struct Context {
|
pub struct Context {
|
||||||
|
Loading…
Reference in New Issue
Block a user