pub const X0: u16 = 3000;
pub const ZERO: u16 = 3000;
pub const X1: u16 = 3001;
pub const RA: u16 = 3001;
pub const X2: u16 = 3002;
pub const SP: u16 = 3002;
pub const X3: u16 = 3003;
pub const GP: u16 = 3003;
pub const X4: u16 = 3004;
pub const TP: u16 = 3004;
pub const X5: u16 = 3005;
pub const T0: u16 = 3005;
pub const X6: u16 = 3006;
pub const T1: u16 = 3006;
pub const X7: u16 = 3007;
pub const T2: u16 = 3007;
pub const X8: u16 = 3008;
pub const S0: u16 = 3008;
pub const FP: u16 = 3008;
pub const X9: u16 = 3009;
pub const S1: u16 = 3009;
pub const X10: u16 = 3010;
pub const A0: u16 = 3010;
pub const X11: u16 = 3011;
pub const A1: u16 = 3011;
pub const X12: u16 = 3012;
pub const A2: u16 = 3012;
pub const X13: u16 = 3013;
pub const A3: u16 = 3013;
pub const X14: u16 = 3014;
pub const A4: u16 = 3014;
pub const X15: u16 = 3015;
pub const A5: u16 = 3015;
pub const X16: u16 = 3016;
pub const A6: u16 = 3016;
pub const X17: u16 = 3017;
pub const A7: u16 = 3017;
pub const X18: u16 = 3018;
pub const S2: u16 = 3018;
pub const X19: u16 = 3019;
pub const S3: u16 = 3019;
pub const X20: u16 = 3020;
pub const S4: u16 = 3020;
pub const X21: u16 = 3021;
pub const S5: u16 = 3021;
pub const X22: u16 = 3022;
pub const S6: u16 = 3022;
pub const X23: u16 = 3023;
pub const S7: u16 = 3023;
pub const X24: u16 = 3024;
pub const S8: u16 = 3024;
pub const X25: u16 = 3025;
pub const S9: u16 = 3025;
pub const X26: u16 = 3026;
pub const S10: u16 = 3026;
pub const X27: u16 = 3027;
pub const S11: u16 = 3027;
pub const X28: u16 = 3028;
pub const T3: u16 = 3028;
pub const X29: u16 = 3029;
pub const T4: u16 = 3029;
pub const X30: u16 = 3030;
pub const T5: u16 = 3030;
pub const X31: u16 = 3031;
pub const T6: u16 = 3031;
pub const F0: u16 = 3050;
pub const FT0: u16 = 3050;
pub const F1: u16 = 3051;
pub const FT1: u16 = 3051;
pub const F2: u16 = 3052;
pub const FT2: u16 = 3052;
pub const F3: u16 = 3053;
pub const FT3: u16 = 3053;
pub const F4: u16 = 3054;
pub const FT4: u16 = 3054;
pub const F5: u16 = 3055;
pub const FT5: u16 = 3055;
pub const F6: u16 = 3056;
pub const FT6: u16 = 3056;
pub const F7: u16 = 3057;
pub const FT7: u16 = 3057;
pub const F8: u16 = 3058;
pub const FS0: u16 = 3058;
pub const F9: u16 = 3059;
pub const FS1: u16 = 3059;
pub const F10: u16 = 3060;
pub const FA0: u16 = 3060;
pub const F11: u16 = 3061;
pub const FA1: u16 = 3061;
pub const F12: u16 = 3062;
pub const FA2: u16 = 3062;
pub const F13: u16 = 3063;
pub const FA3: u16 = 3063;
pub const F14: u16 = 3064;
pub const FA4: u16 = 3064;
pub const F15: u16 = 3065;
pub const FA5: u16 = 3065;
pub const F16: u16 = 3066;
pub const FA6: u16 = 3066;
pub const F17: u16 = 3067;
pub const FA7: u16 = 3067;
pub const F18: u16 = 3068;
pub const FS2: u16 = 3068;
pub const F19: u16 = 3069;
pub const FS3: u16 = 3069;
pub const F20: u16 = 3070;
pub const FS4: u16 = 3070;
pub const F21: u16 = 3071;
pub const FS5: u16 = 3071;
pub const F22: u16 = 3072;
pub const FS6: u16 = 3072;
pub const F23: u16 = 3073;
pub const FS7: u16 = 3073;
pub const F24: u16 = 3074;
pub const FS8: u16 = 3074;
pub const F25: u16 = 3075;
pub const FS9: u16 = 3075;
pub const F26: u16 = 3076;
pub const FS10: u16 = 3076;
pub const F27: u16 = 3077;
pub const FS11: u16 = 3077;
pub const F28: u16 = 3078;
pub const FT8: u16 = 3078;
pub const F29: u16 = 3079;
pub const FT9: u16 = 3079;
pub const F30: u16 = 3080;
pub const FT10: u16 = 3080;
pub const F31: u16 = 3081;
pub const FT11: u16 = 3081;
pub const RV_GPR_COUNT: usize = 32;
pub const RV_FPR_COUNT: usize = 32;
pub const RV_MAX_REG_ID: u16 = 3081;
pub const GPR_BASE: u16 = 3000;
pub const FPR_BASE: u16 = 3050;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum RiscVRegClass {
GPR,
FPR32,
FPR64,
}
impl std::fmt::Display for RiscVRegClass {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
RiscVRegClass::GPR => write!(f, "GPR"),
RiscVRegClass::FPR32 => write!(f, "FPR32"),
RiscVRegClass::FPR64 => write!(f, "FPR64"),
}
}
}
pub struct RiscVRegisterInfo;
impl RiscVRegisterInfo {
pub fn get_asm_name(reg_id: u16) -> &'static str {
match reg_id {
X0 => "zero",
X1 => "ra",
X2 => "sp",
X3 => "gp",
X4 => "tp",
X5 => "t0",
X6 => "t1",
X7 => "t2",
X8 => "s0",
X9 => "s1",
X10 => "a0",
X11 => "a1",
X12 => "a2",
X13 => "a3",
X14 => "a4",
X15 => "a5",
X16 => "a6",
X17 => "a7",
X18 => "s2",
X19 => "s3",
X20 => "s4",
X21 => "s5",
X22 => "s6",
X23 => "s7",
X24 => "s8",
X25 => "s9",
X26 => "s10",
X27 => "s11",
X28 => "t3",
X29 => "t4",
X30 => "t5",
X31 => "t6",
F0 => "f0",
F1 => "f1",
F2 => "f2",
F3 => "f3",
F4 => "f4",
F5 => "f5",
F6 => "f6",
F7 => "f7",
F8 => "f8",
F9 => "f9",
F10 => "f10",
F11 => "f11",
F12 => "f12",
F13 => "f13",
F14 => "f14",
F15 => "f15",
F16 => "f16",
F17 => "f17",
F18 => "f18",
F19 => "f19",
F20 => "f20",
F21 => "f21",
F22 => "f22",
F23 => "f23",
F24 => "f24",
F25 => "f25",
F26 => "f26",
F27 => "f27",
F28 => "f28",
F29 => "f29",
F30 => "f30",
F31 => "f31",
_ => "?",
}
}
pub fn get_abi_name(reg_id: u16) -> &'static str {
match reg_id {
X0 => "zero",
X1 => "ra",
X2 => "sp",
X3 => "gp",
X4 => "tp",
X5 => "t0",
X6 => "t1",
X7 => "t2",
X8 => "s0",
X9 => "s1",
X10 => "a0",
X11 => "a1",
X12 => "a2",
X13 => "a3",
X14 => "a4",
X15 => "a5",
X16 => "a6",
X17 => "a7",
X18 => "s2",
X19 => "s3",
X20 => "s4",
X21 => "s5",
X22 => "s6",
X23 => "s7",
X24 => "s8",
X25 => "s9",
X26 => "s10",
X27 => "s11",
X28 => "t3",
X29 => "t4",
X30 => "t5",
X31 => "t6",
F0 => "ft0",
F1 => "ft1",
F2 => "ft2",
F3 => "ft3",
F4 => "ft4",
F5 => "ft5",
F6 => "ft6",
F7 => "ft7",
F8 => "fs0",
F9 => "fs1",
F10 => "fa0",
F11 => "fa1",
F12 => "fa2",
F13 => "fa3",
F14 => "fa4",
F15 => "fa5",
F16 => "fa6",
F17 => "fa7",
F18 => "fs2",
F19 => "fs3",
F20 => "fs4",
F21 => "fs5",
F22 => "fs6",
F23 => "fs7",
F24 => "fs8",
F25 => "fs9",
F26 => "fs10",
F27 => "fs11",
F28 => "ft8",
F29 => "ft9",
F30 => "ft10",
F31 => "ft11",
_ => "?",
}
}
pub fn get_reg_class(reg_id: u16) -> RiscVRegClass {
match reg_id {
3000..=3031 => RiscVRegClass::GPR,
3050..=3081 => RiscVRegClass::FPR64,
_ => RiscVRegClass::GPR,
}
}
pub fn get_reg_width(reg_id: u16, is_rv64: bool) -> u16 {
match reg_id {
3000..=3031 => {
if is_rv64 {
64
} else {
32
}
}
3050..=3081 => 64, _ => 64,
}
}
pub fn get_dwarf_num(reg_id: u16) -> i16 {
match reg_id {
3000..=3031 => (reg_id - 3000) as i16,
3050..=3081 => (32 + (reg_id - 3050)) as i16,
_ => -1,
}
}
pub fn is_callee_saved(reg_id: u16) -> bool {
match reg_id {
SP => true,
X8 | S0 | FP => true,
X9 | S1 => true,
X18..=X27 => true, F8 | FS0 => true,
F9 | FS1 => true,
F18..=F27 => true, _ => false,
}
}
pub fn is_caller_saved(reg_id: u16) -> bool {
match reg_id {
X1 | RA => true,
X5..=X7 => true, X10..=X17 => true, X28..=X31 => true, F0..=F7 => true, F10..=F17 => true, F28..=F31 => true, _ => false,
}
}
pub fn is_reserved(reg_id: u16) -> bool {
matches!(reg_id, X0 | ZERO | X2 | SP | X3 | GP | X4 | TP)
}
pub fn get_allocatable_gprs() -> Vec<u16> {
let mut regs = Vec::with_capacity(32);
for id in 3000u16..=3031u16 {
if !RiscVRegisterInfo::is_reserved(id) && id != RA {
regs.push(id);
}
}
regs
}
pub fn get_allocatable_fprs() -> Vec<u16> {
(3050u16..=3081u16).collect()
}
pub fn get_argument_regs() -> Vec<u16> {
vec![A0, A1, A2, A3, A4, A5, A6, A7]
}
pub fn get_fp_argument_regs() -> Vec<u16> {
vec![FA0, FA1, FA2, FA3, FA4, FA5, FA6, FA7]
}
pub fn get_return_regs() -> Vec<u16> {
vec![A0, A1]
}
pub fn get_fp_return_regs() -> Vec<u16> {
vec![FA0, FA1]
}
pub fn get_frame_pointer_reg() -> u16 {
S0
}
pub fn get_return_address_reg() -> u16 {
RA
}
pub fn get_stack_pointer_reg() -> u16 {
SP
}
pub fn get_global_pointer_reg() -> u16 {
GP
}
pub fn get_thread_pointer_reg() -> u16 {
TP
}
pub fn get_zero_reg() -> u16 {
ZERO
}
pub fn is_gpr(reg_id: u16) -> bool {
(3000..=3031).contains(®_id)
}
pub fn is_fpr(reg_id: u16) -> bool {
(3050..=3081).contains(®_id)
}
pub fn get_reg_index(reg_id: u16) -> u8 {
match reg_id {
3000..=3031 => (reg_id - 3000) as u8,
3050..=3081 => (reg_id - 3050) as u8,
_ => 0,
}
}
pub fn get_x_name(reg_id: u16) -> String {
if RiscVRegisterInfo::is_gpr(reg_id) {
format!("x{}", RiscVRegisterInfo::get_reg_index(reg_id))
} else {
"?".to_string()
}
}
pub fn get_f_name(reg_id: u16) -> String {
if RiscVRegisterInfo::is_fpr(reg_id) {
format!("f{}", RiscVRegisterInfo::get_reg_index(reg_id))
} else {
"?".to_string()
}
}
pub fn can_be_base_reg(reg_id: u16) -> bool {
RiscVRegisterInfo::is_gpr(reg_id) && reg_id != ZERO
}
pub fn get_caller_saved_gprs() -> Vec<u16> {
vec![
RA, T0, T1, T2, A0, A1, A2, A3, A4, A5, A6, A7, T3, T4, T5, T6, ]
}
pub fn get_callee_saved_gprs() -> Vec<u16> {
vec![
SP, S0, S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, ]
}
pub fn get_caller_saved_fprs() -> Vec<u16> {
vec![
FT0, FT1, FT2, FT3, FT4, FT5, FT6, FT7, FA0, FA1, FA2, FA3, FA4, FA5, FA6, FA7, FT8, FT9, FT10, FT11, ]
}
pub fn get_callee_saved_fprs() -> Vec<u16> {
vec![
FS0, FS1, FS2, FS3, FS4, FS5, FS6, FS7, FS8, FS9, FS10, FS11, ]
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_register_count_constants() {
assert_eq!(RV_GPR_COUNT, 32);
assert_eq!(RV_FPR_COUNT, 32);
assert_eq!(RV_MAX_REG_ID, 3081);
assert_eq!(GPR_BASE, 3000);
assert_eq!(FPR_BASE, 3050);
}
#[test]
fn test_register_ids_unique() {
let gpr_ids = [
X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18,
X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31,
];
let mut sorted: Vec<u16> = gpr_ids.to_vec();
sorted.sort_unstable();
sorted.dedup();
assert_eq!(sorted.len(), 32);
let fpr_ids = [
F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17, F18,
F19, F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F30, F31,
];
let mut sorted_fpr: Vec<u16> = fpr_ids.to_vec();
sorted_fpr.sort_unstable();
sorted_fpr.dedup();
assert_eq!(sorted_fpr.len(), 32);
}
#[test]
fn test_abi_name_aliases() {
assert_eq!(ZERO, X0);
assert_eq!(RA, X1);
assert_eq!(SP, X2);
assert_eq!(GP, X3);
assert_eq!(TP, X4);
assert_eq!(T0, X5);
assert_eq!(T1, X6);
assert_eq!(T2, X7);
assert_eq!(S0, X8);
assert_eq!(FP, X8);
assert_eq!(S1, X9);
assert_eq!(A0, X10);
assert_eq!(A1, X11);
assert_eq!(A2, X12);
assert_eq!(A3, X13);
assert_eq!(A4, X14);
assert_eq!(A5, X15);
assert_eq!(A6, X16);
assert_eq!(A7, X17);
assert_eq!(S2, X18);
assert_eq!(S3, X19);
assert_eq!(S4, X20);
assert_eq!(S5, X21);
assert_eq!(S6, X22);
assert_eq!(S7, X23);
assert_eq!(S8, X24);
assert_eq!(S9, X25);
assert_eq!(S10, X26);
assert_eq!(S11, X27);
assert_eq!(T3, X28);
assert_eq!(T4, X29);
assert_eq!(T5, X30);
assert_eq!(T6, X31);
}
#[test]
fn test_fpr_name_aliases() {
assert_eq!(FT0, F0);
assert_eq!(FT1, F1);
assert_eq!(FT2, F2);
assert_eq!(FT3, F3);
assert_eq!(FT4, F4);
assert_eq!(FT5, F5);
assert_eq!(FT6, F6);
assert_eq!(FT7, F7);
assert_eq!(FS0, F8);
assert_eq!(FS1, F9);
assert_eq!(FA0, F10);
assert_eq!(FA1, F11);
assert_eq!(FA2, F12);
assert_eq!(FA3, F13);
assert_eq!(FA4, F14);
assert_eq!(FA5, F15);
assert_eq!(FA6, F16);
assert_eq!(FA7, F17);
assert_eq!(FS2, F18);
assert_eq!(FS3, F19);
assert_eq!(FS4, F20);
assert_eq!(FS5, F21);
assert_eq!(FS6, F22);
assert_eq!(FS7, F23);
assert_eq!(FS8, F24);
assert_eq!(FS9, F25);
assert_eq!(FS10, F26);
assert_eq!(FS11, F27);
assert_eq!(FT8, F28);
assert_eq!(FT9, F29);
assert_eq!(FT10, F30);
assert_eq!(FT11, F31);
}
#[test]
fn test_get_asm_name() {
assert_eq!(RiscVRegisterInfo::get_asm_name(X0), "zero");
assert_eq!(RiscVRegisterInfo::get_asm_name(RA), "ra");
assert_eq!(RiscVRegisterInfo::get_asm_name(SP), "sp");
assert_eq!(RiscVRegisterInfo::get_asm_name(GP), "gp");
assert_eq!(RiscVRegisterInfo::get_asm_name(TP), "tp");
assert_eq!(RiscVRegisterInfo::get_asm_name(T0), "t0");
assert_eq!(RiscVRegisterInfo::get_asm_name(S0), "s0");
assert_eq!(RiscVRegisterInfo::get_asm_name(A0), "a0");
assert_eq!(RiscVRegisterInfo::get_asm_name(A7), "a7");
assert_eq!(RiscVRegisterInfo::get_asm_name(T6), "t6");
assert_eq!(RiscVRegisterInfo::get_asm_name(F0), "f0");
assert_eq!(RiscVRegisterInfo::get_asm_name(F31), "f31");
assert_eq!(RiscVRegisterInfo::get_asm_name(9999), "?");
}
#[test]
fn test_get_abi_name() {
assert_eq!(RiscVRegisterInfo::get_abi_name(X0), "zero");
assert_eq!(RiscVRegisterInfo::get_abi_name(RA), "ra");
assert_eq!(RiscVRegisterInfo::get_abi_name(SP), "sp");
assert_eq!(RiscVRegisterInfo::get_abi_name(T0), "t0");
assert_eq!(RiscVRegisterInfo::get_abi_name(S0), "s0");
assert_eq!(RiscVRegisterInfo::get_abi_name(A0), "a0");
assert_eq!(RiscVRegisterInfo::get_abi_name(FT0), "ft0");
assert_eq!(RiscVRegisterInfo::get_abi_name(FS0), "fs0");
assert_eq!(RiscVRegisterInfo::get_abi_name(FA0), "fa0");
assert_eq!(RiscVRegisterInfo::get_abi_name(FT11), "ft11");
}
#[test]
fn test_get_reg_class() {
assert_eq!(RiscVRegisterInfo::get_reg_class(X0), RiscVRegClass::GPR);
assert_eq!(RiscVRegisterInfo::get_reg_class(X31), RiscVRegClass::GPR);
assert_eq!(RiscVRegisterInfo::get_reg_class(A0), RiscVRegClass::GPR);
assert_eq!(RiscVRegisterInfo::get_reg_class(SP), RiscVRegClass::GPR);
assert_eq!(RiscVRegisterInfo::get_reg_class(F0), RiscVRegClass::FPR64);
assert_eq!(RiscVRegisterInfo::get_reg_class(F31), RiscVRegClass::FPR64);
}
#[test]
fn test_get_reg_width() {
assert_eq!(RiscVRegisterInfo::get_reg_width(X0, true), 64);
assert_eq!(RiscVRegisterInfo::get_reg_width(A0, true), 64);
assert_eq!(RiscVRegisterInfo::get_reg_width(X0, false), 32);
assert_eq!(RiscVRegisterInfo::get_reg_width(A1, false), 32);
assert_eq!(RiscVRegisterInfo::get_reg_width(F0, true), 64);
assert_eq!(RiscVRegisterInfo::get_reg_width(F31, false), 64);
}
#[test]
fn test_get_dwarf_num() {
assert_eq!(RiscVRegisterInfo::get_dwarf_num(X0), 0);
assert_eq!(RiscVRegisterInfo::get_dwarf_num(X1), 1);
assert_eq!(RiscVRegisterInfo::get_dwarf_num(X31), 31);
assert_eq!(RiscVRegisterInfo::get_dwarf_num(F0), 32);
assert_eq!(RiscVRegisterInfo::get_dwarf_num(F1), 33);
assert_eq!(RiscVRegisterInfo::get_dwarf_num(F31), 63);
assert_eq!(RiscVRegisterInfo::get_dwarf_num(9999), -1);
}
#[test]
fn test_is_callee_saved() {
assert!(RiscVRegisterInfo::is_callee_saved(SP));
assert!(RiscVRegisterInfo::is_callee_saved(S0));
assert!(RiscVRegisterInfo::is_callee_saved(FP));
assert!(RiscVRegisterInfo::is_callee_saved(S1));
assert!(RiscVRegisterInfo::is_callee_saved(S2));
assert!(RiscVRegisterInfo::is_callee_saved(S11));
assert!(RiscVRegisterInfo::is_callee_saved(FS0));
assert!(RiscVRegisterInfo::is_callee_saved(FS1));
assert!(RiscVRegisterInfo::is_callee_saved(FS2));
assert!(RiscVRegisterInfo::is_callee_saved(FS11));
assert!(!RiscVRegisterInfo::is_callee_saved(X0));
assert!(!RiscVRegisterInfo::is_callee_saved(RA));
assert!(!RiscVRegisterInfo::is_callee_saved(A0));
assert!(!RiscVRegisterInfo::is_callee_saved(T0));
assert!(!RiscVRegisterInfo::is_callee_saved(FT0));
assert!(!RiscVRegisterInfo::is_callee_saved(FA0));
}
#[test]
fn test_is_caller_saved() {
assert!(RiscVRegisterInfo::is_caller_saved(RA));
assert!(RiscVRegisterInfo::is_caller_saved(T0));
assert!(RiscVRegisterInfo::is_caller_saved(T2));
assert!(RiscVRegisterInfo::is_caller_saved(A0));
assert!(RiscVRegisterInfo::is_caller_saved(A7));
assert!(RiscVRegisterInfo::is_caller_saved(T3));
assert!(RiscVRegisterInfo::is_caller_saved(T6));
assert!(RiscVRegisterInfo::is_caller_saved(FT0));
assert!(RiscVRegisterInfo::is_caller_saved(FT7));
assert!(RiscVRegisterInfo::is_caller_saved(FA0));
assert!(RiscVRegisterInfo::is_caller_saved(FA7));
assert!(RiscVRegisterInfo::is_caller_saved(FT8));
assert!(RiscVRegisterInfo::is_caller_saved(FT11));
assert!(!RiscVRegisterInfo::is_caller_saved(SP));
assert!(!RiscVRegisterInfo::is_caller_saved(S0));
assert!(!RiscVRegisterInfo::is_caller_saved(FS0));
assert!(!RiscVRegisterInfo::is_caller_saved(X0));
}
#[test]
fn test_is_reserved() {
assert!(RiscVRegisterInfo::is_reserved(ZERO));
assert!(RiscVRegisterInfo::is_reserved(SP));
assert!(RiscVRegisterInfo::is_reserved(GP));
assert!(RiscVRegisterInfo::is_reserved(TP));
assert!(!RiscVRegisterInfo::is_reserved(RA));
assert!(!RiscVRegisterInfo::is_reserved(A0));
assert!(!RiscVRegisterInfo::is_reserved(T0));
assert!(!RiscVRegisterInfo::is_reserved(F0));
}
#[test]
fn test_get_allocatable_gprs() {
let gprs = RiscVRegisterInfo::get_allocatable_gprs();
assert!(!gprs.contains(&ZERO));
assert!(!gprs.contains(&SP));
assert!(!gprs.contains(&GP));
assert!(!gprs.contains(&TP));
assert!(!gprs.contains(&RA));
assert!(gprs.contains(&A0));
assert!(gprs.contains(&T0));
assert!(gprs.contains(&S0));
}
#[test]
fn test_get_allocatable_fprs() {
let fprs = RiscVRegisterInfo::get_allocatable_fprs();
assert_eq!(fprs.len(), 32);
assert!(fprs.contains(&F0));
assert!(fprs.contains(&F31));
}
#[test]
fn test_get_argument_regs() {
let arg_regs = RiscVRegisterInfo::get_argument_regs();
assert_eq!(arg_regs.len(), 8);
assert_eq!(arg_regs[0], A0);
assert_eq!(arg_regs[7], A7);
}
#[test]
fn test_get_fp_argument_regs() {
let fp_arg_regs = RiscVRegisterInfo::get_fp_argument_regs();
assert_eq!(fp_arg_regs.len(), 8);
assert_eq!(fp_arg_regs[0], FA0);
assert_eq!(fp_arg_regs[7], FA7);
}
#[test]
fn test_get_return_regs() {
let ret_regs = RiscVRegisterInfo::get_return_regs();
assert_eq!(ret_regs.len(), 2);
assert_eq!(ret_regs[0], A0);
assert_eq!(ret_regs[1], A1);
}
#[test]
fn test_get_fp_return_regs() {
let fp_ret_regs = RiscVRegisterInfo::get_fp_return_regs();
assert_eq!(fp_ret_regs.len(), 2);
assert_eq!(fp_ret_regs[0], FA0);
assert_eq!(fp_ret_regs[1], FA1);
}
#[test]
fn test_special_regs() {
assert_eq!(RiscVRegisterInfo::get_frame_pointer_reg(), S0);
assert_eq!(RiscVRegisterInfo::get_return_address_reg(), RA);
assert_eq!(RiscVRegisterInfo::get_stack_pointer_reg(), SP);
assert_eq!(RiscVRegisterInfo::get_global_pointer_reg(), GP);
assert_eq!(RiscVRegisterInfo::get_thread_pointer_reg(), TP);
assert_eq!(RiscVRegisterInfo::get_zero_reg(), ZERO);
}
#[test]
fn test_is_gpr_and_fpr() {
assert!(RiscVRegisterInfo::is_gpr(X0));
assert!(RiscVRegisterInfo::is_gpr(X31));
assert!(!RiscVRegisterInfo::is_gpr(F0));
assert!(RiscVRegisterInfo::is_fpr(F0));
assert!(RiscVRegisterInfo::is_fpr(F31));
assert!(!RiscVRegisterInfo::is_fpr(X0));
}
#[test]
fn test_get_reg_index() {
assert_eq!(RiscVRegisterInfo::get_reg_index(X0), 0);
assert_eq!(RiscVRegisterInfo::get_reg_index(X31), 31);
assert_eq!(RiscVRegisterInfo::get_reg_index(A0), 10);
assert_eq!(RiscVRegisterInfo::get_reg_index(F0), 0);
assert_eq!(RiscVRegisterInfo::get_reg_index(F31), 31);
}
#[test]
fn test_get_x_name() {
assert_eq!(RiscVRegisterInfo::get_x_name(X0), "x0");
assert_eq!(RiscVRegisterInfo::get_x_name(X10), "x10");
assert_eq!(RiscVRegisterInfo::get_x_name(X31), "x31");
assert_eq!(RiscVRegisterInfo::get_x_name(SP), "x2");
assert_eq!(RiscVRegisterInfo::get_x_name(F0), "?");
}
#[test]
fn test_get_f_name() {
assert_eq!(RiscVRegisterInfo::get_f_name(F0), "f0");
assert_eq!(RiscVRegisterInfo::get_f_name(F15), "f15");
assert_eq!(RiscVRegisterInfo::get_f_name(F31), "f31");
assert_eq!(RiscVRegisterInfo::get_f_name(X0), "?");
}
#[test]
fn test_can_be_base_reg() {
assert!(!RiscVRegisterInfo::can_be_base_reg(X0));
assert!(!RiscVRegisterInfo::can_be_base_reg(ZERO));
assert!(RiscVRegisterInfo::can_be_base_reg(X1));
assert!(RiscVRegisterInfo::can_be_base_reg(SP));
assert!(RiscVRegisterInfo::can_be_base_reg(A0));
assert!(!RiscVRegisterInfo::can_be_base_reg(F0));
}
#[test]
fn test_reg_class_display() {
assert_eq!(format!("{}", RiscVRegClass::GPR), "GPR");
assert_eq!(format!("{}", RiscVRegClass::FPR32), "FPR32");
assert_eq!(format!("{}", RiscVRegClass::FPR64), "FPR64");
}
#[test]
fn test_caller_saved_gprs_count() {
let regs = RiscVRegisterInfo::get_caller_saved_gprs();
assert_eq!(regs.len(), 16);
}
#[test]
fn test_callee_saved_gprs_count() {
let regs = RiscVRegisterInfo::get_callee_saved_gprs();
assert_eq!(regs.len(), 13);
}
#[test]
fn test_caller_saved_fprs_count() {
let regs = RiscVRegisterInfo::get_caller_saved_fprs();
assert_eq!(regs.len(), 20);
}
#[test]
fn test_callee_saved_fprs_count() {
let regs = RiscVRegisterInfo::get_callee_saved_fprs();
assert_eq!(regs.len(), 12);
}
#[test]
fn test_all_gpr_ids_in_range() {
for id in 3000u16..=3031u16 {
assert!(RiscVRegisterInfo::is_gpr(id));
assert!(!RiscVRegisterInfo::is_fpr(id));
}
}
#[test]
fn test_all_fpr_ids_in_range() {
for id in 3050u16..=3081u16 {
assert!(RiscVRegisterInfo::is_fpr(id));
assert!(!RiscVRegisterInfo::is_gpr(id));
}
}
}