pub const SZ_GPR_COUNT: u32 = 16;
pub const SZ_FPR_COUNT: u32 = 16;
pub const SZ_AR_COUNT: u32 = 16;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum SystemzRegister {
R0,
R1,
R2,
R3,
R4,
R5,
R6,
R7,
R8,
R9,
R10,
R11,
R12,
R13,
R14,
R15,
F0,
F1,
F2,
F3,
F4,
F5,
F6,
F7,
F8,
F9,
F10,
F11,
F12,
F13,
F14,
F15,
A0,
A1,
A2,
A3,
A4,
A5,
A6,
A7,
A8,
A9,
A10,
A11,
A12,
A13,
A14,
A15,
PSW, CC, PC, }
pub struct SystemzRegisterInfo;
impl SystemzRegisterInfo {
pub fn get_name(reg: SystemzRegister) -> &'static str {
match reg {
SystemzRegister::R0 => "%r0",
SystemzRegister::R1 => "%r1",
SystemzRegister::R2 => "%r2",
SystemzRegister::R3 => "%r3",
SystemzRegister::R4 => "%r4",
SystemzRegister::R5 => "%r5",
SystemzRegister::R6 => "%r6",
SystemzRegister::R7 => "%r7",
SystemzRegister::R8 => "%r8",
SystemzRegister::R9 => "%r9",
SystemzRegister::R10 => "%r10",
SystemzRegister::R11 => "%r11",
SystemzRegister::R12 => "%r12",
SystemzRegister::R13 => "%r13",
SystemzRegister::R14 => "%r14",
SystemzRegister::R15 => "%r15",
SystemzRegister::F0 => "%f0",
SystemzRegister::F1 => "%f1",
SystemzRegister::F2 => "%f2",
SystemzRegister::F3 => "%f3",
SystemzRegister::F4 => "%f4",
SystemzRegister::F5 => "%f5",
SystemzRegister::F6 => "%f6",
SystemzRegister::F7 => "%f7",
SystemzRegister::F8 => "%f8",
SystemzRegister::F9 => "%f9",
SystemzRegister::F10 => "%f10",
SystemzRegister::F11 => "%f11",
SystemzRegister::F12 => "%f12",
SystemzRegister::F13 => "%f13",
SystemzRegister::F14 => "%f14",
SystemzRegister::F15 => "%f15",
SystemzRegister::A0 => "%a0",
SystemzRegister::A1 => "%a1",
SystemzRegister::A2 => "%a2",
SystemzRegister::A3 => "%a3",
SystemzRegister::A4 => "%a4",
SystemzRegister::A5 => "%a5",
SystemzRegister::A6 => "%a6",
SystemzRegister::A7 => "%a7",
SystemzRegister::A8 => "%a8",
SystemzRegister::A9 => "%a9",
SystemzRegister::A10 => "%a10",
SystemzRegister::A11 => "%a11",
SystemzRegister::A12 => "%a12",
SystemzRegister::A13 => "%a13",
SystemzRegister::A14 => "%a14",
SystemzRegister::A15 => "%a15",
SystemzRegister::PSW => "%psw",
SystemzRegister::CC => "%cc",
SystemzRegister::PC => "%pc",
}
}
pub fn get_dwarf_num(reg: SystemzRegister) -> u16 {
match reg {
SystemzRegister::R0 => 0,
SystemzRegister::R1 => 1,
SystemzRegister::R2 => 2,
SystemzRegister::R3 => 3,
SystemzRegister::R4 => 4,
SystemzRegister::R5 => 5,
SystemzRegister::R6 => 6,
SystemzRegister::R7 => 7,
SystemzRegister::R8 => 8,
SystemzRegister::R9 => 9,
SystemzRegister::R10 => 10,
SystemzRegister::R11 => 11,
SystemzRegister::R12 => 12,
SystemzRegister::R13 => 13,
SystemzRegister::R14 => 14,
SystemzRegister::R15 => 15,
SystemzRegister::F0 => 16,
SystemzRegister::F1 => 17,
SystemzRegister::F2 => 18,
SystemzRegister::F3 => 19,
SystemzRegister::F4 => 20,
SystemzRegister::F5 => 21,
SystemzRegister::F6 => 22,
SystemzRegister::F7 => 23,
SystemzRegister::F8 => 24,
SystemzRegister::F9 => 25,
SystemzRegister::F10 => 26,
SystemzRegister::F11 => 27,
SystemzRegister::F12 => 28,
SystemzRegister::F13 => 29,
SystemzRegister::F14 => 30,
SystemzRegister::F15 => 31,
SystemzRegister::A0 => 48,
SystemzRegister::A1 => 49,
SystemzRegister::A2 => 50,
SystemzRegister::A3 => 51,
SystemzRegister::A4 => 52,
SystemzRegister::A5 => 53,
SystemzRegister::A6 => 54,
SystemzRegister::A7 => 55,
SystemzRegister::A8 => 56,
SystemzRegister::A9 => 57,
SystemzRegister::A10 => 58,
SystemzRegister::A11 => 59,
SystemzRegister::A12 => 60,
SystemzRegister::A13 => 61,
SystemzRegister::A14 => 62,
SystemzRegister::A15 => 63,
_ => 0xFFFF,
}
}
pub fn get_width(reg: SystemzRegister) -> u32 {
if Self::is_gpr(reg) {
return 64;
}
if Self::is_fpr(reg) {
return 64;
}
if Self::is_ar(reg) {
return 32;
}
match reg {
SystemzRegister::PSW => 128,
SystemzRegister::CC => 2,
SystemzRegister::PC => 64,
_ => 0,
}
}
pub fn is_gpr(reg: SystemzRegister) -> bool {
matches!(
reg,
SystemzRegister::R0
| SystemzRegister::R1
| SystemzRegister::R2
| SystemzRegister::R3
| SystemzRegister::R4
| SystemzRegister::R5
| SystemzRegister::R6
| SystemzRegister::R7
| SystemzRegister::R8
| SystemzRegister::R9
| SystemzRegister::R10
| SystemzRegister::R11
| SystemzRegister::R12
| SystemzRegister::R13
| SystemzRegister::R14
| SystemzRegister::R15
)
}
pub fn is_fpr(reg: SystemzRegister) -> bool {
matches!(
reg,
SystemzRegister::F0
| SystemzRegister::F1
| SystemzRegister::F2
| SystemzRegister::F3
| SystemzRegister::F4
| SystemzRegister::F5
| SystemzRegister::F6
| SystemzRegister::F7
| SystemzRegister::F8
| SystemzRegister::F9
| SystemzRegister::F10
| SystemzRegister::F11
| SystemzRegister::F12
| SystemzRegister::F13
| SystemzRegister::F14
| SystemzRegister::F15
)
}
pub fn is_ar(reg: SystemzRegister) -> bool {
matches!(
reg,
SystemzRegister::A0
| SystemzRegister::A1
| SystemzRegister::A2
| SystemzRegister::A3
| SystemzRegister::A4
| SystemzRegister::A5
| SystemzRegister::A6
| SystemzRegister::A7
| SystemzRegister::A8
| SystemzRegister::A9
| SystemzRegister::A10
| SystemzRegister::A11
| SystemzRegister::A12
| SystemzRegister::A13
| SystemzRegister::A14
| SystemzRegister::A15
)
}
pub fn get_index(reg: SystemzRegister) -> u8 {
match reg {
SystemzRegister::R0 => 0,
SystemzRegister::R1 => 1,
SystemzRegister::R2 => 2,
SystemzRegister::R3 => 3,
SystemzRegister::R4 => 4,
SystemzRegister::R5 => 5,
SystemzRegister::R6 => 6,
SystemzRegister::R7 => 7,
SystemzRegister::R8 => 8,
SystemzRegister::R9 => 9,
SystemzRegister::R10 => 10,
SystemzRegister::R11 => 11,
SystemzRegister::R12 => 12,
SystemzRegister::R13 => 13,
SystemzRegister::R14 => 14,
SystemzRegister::R15 => 15,
_ => 0,
}
}
pub fn get_fpr_index(reg: SystemzRegister) -> u8 {
match reg {
SystemzRegister::F0 => 0,
SystemzRegister::F1 => 1,
SystemzRegister::F2 => 2,
SystemzRegister::F3 => 3,
SystemzRegister::F4 => 4,
SystemzRegister::F5 => 5,
SystemzRegister::F6 => 6,
SystemzRegister::F7 => 7,
SystemzRegister::F8 => 8,
SystemzRegister::F9 => 9,
SystemzRegister::F10 => 10,
SystemzRegister::F11 => 11,
SystemzRegister::F12 => 12,
SystemzRegister::F13 => 13,
SystemzRegister::F14 => 14,
SystemzRegister::F15 => 15,
_ => 0,
}
}
pub fn is_callee_saved(reg: SystemzRegister) -> bool {
matches!(
reg,
SystemzRegister::R6
| SystemzRegister::R7
| SystemzRegister::R8
| SystemzRegister::R9
| SystemzRegister::R10
| SystemzRegister::R11
| SystemzRegister::R12
| SystemzRegister::R13
| SystemzRegister::R14
| SystemzRegister::R15
| SystemzRegister::F8
| SystemzRegister::F9
| SystemzRegister::F10
| SystemzRegister::F11
| SystemzRegister::F12
| SystemzRegister::F13
| SystemzRegister::F14
| SystemzRegister::F15
)
}
pub fn is_caller_saved(reg: SystemzRegister) -> bool {
Self::is_gpr(reg) || Self::is_fpr(reg) && !Self::is_callee_saved(reg)
}
pub fn get_stack_pointer() -> SystemzRegister {
SystemzRegister::R15
}
pub fn get_frame_pointer() -> SystemzRegister {
SystemzRegister::R11
}
pub fn get_return_address() -> SystemzRegister {
SystemzRegister::R14
}
pub fn get_zero_reg() -> SystemzRegister {
SystemzRegister::R0
}
pub fn get_arg_regs() -> Vec<SystemzRegister> {
vec![
SystemzRegister::R2,
SystemzRegister::R3,
SystemzRegister::R4,
SystemzRegister::R5,
SystemzRegister::R6,
]
}
pub fn get_fp_arg_regs() -> Vec<SystemzRegister> {
vec![
SystemzRegister::F0,
SystemzRegister::F2,
SystemzRegister::F4,
SystemzRegister::F6,
]
}
pub fn get_return_regs() -> Vec<SystemzRegister> {
vec![SystemzRegister::R2, SystemzRegister::R3]
}
pub fn get_fp_return_regs() -> Vec<SystemzRegister> {
vec![SystemzRegister::F0]
}
pub fn get_caller_saved_gprs() -> Vec<SystemzRegister> {
vec![
SystemzRegister::R0,
SystemzRegister::R1,
SystemzRegister::R2,
SystemzRegister::R3,
SystemzRegister::R4,
SystemzRegister::R5,
SystemzRegister::R14,
]
}
pub fn get_callee_saved_gprs() -> Vec<SystemzRegister> {
vec![
SystemzRegister::R6,
SystemzRegister::R7,
SystemzRegister::R8,
SystemzRegister::R9,
SystemzRegister::R10,
SystemzRegister::R11,
SystemzRegister::R12,
SystemzRegister::R13,
SystemzRegister::R15,
]
}
pub fn get_allocatable_gprs() -> Vec<SystemzRegister> {
vec![
SystemzRegister::R1,
SystemzRegister::R2,
SystemzRegister::R3,
SystemzRegister::R4,
SystemzRegister::R5,
SystemzRegister::R6,
SystemzRegister::R7,
SystemzRegister::R8,
SystemzRegister::R9,
SystemzRegister::R10,
SystemzRegister::R11,
SystemzRegister::R12,
SystemzRegister::R13,
SystemzRegister::R14,
]
}
pub fn get_allocatable_fprs() -> Vec<SystemzRegister> {
vec![
SystemzRegister::F0,
SystemzRegister::F1,
SystemzRegister::F2,
SystemzRegister::F3,
SystemzRegister::F4,
SystemzRegister::F5,
SystemzRegister::F6,
SystemzRegister::F7,
SystemzRegister::F8,
SystemzRegister::F9,
SystemzRegister::F10,
SystemzRegister::F11,
SystemzRegister::F12,
SystemzRegister::F13,
SystemzRegister::F14,
SystemzRegister::F15,
]
}
pub fn can_be_base_reg(reg: SystemzRegister) -> bool {
reg != SystemzRegister::R0 && Self::is_gpr(reg)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_register_count_constants() {
assert_eq!(SZ_GPR_COUNT, 16);
assert_eq!(SZ_FPR_COUNT, 16);
assert_eq!(SZ_AR_COUNT, 16);
}
#[test]
fn test_register_names() {
assert_eq!(SystemzRegisterInfo::get_name(SystemzRegister::R0), "%r0");
assert_eq!(SystemzRegisterInfo::get_name(SystemzRegister::R15), "%r15");
assert_eq!(SystemzRegisterInfo::get_name(SystemzRegister::F0), "%f0");
assert_eq!(SystemzRegisterInfo::get_name(SystemzRegister::PSW), "%psw");
}
#[test]
fn test_dwarf_numbers() {
assert_eq!(SystemzRegisterInfo::get_dwarf_num(SystemzRegister::R0), 0);
assert_eq!(SystemzRegisterInfo::get_dwarf_num(SystemzRegister::R15), 15);
assert_eq!(SystemzRegisterInfo::get_dwarf_num(SystemzRegister::F0), 16);
assert_eq!(SystemzRegisterInfo::get_dwarf_num(SystemzRegister::F15), 31);
assert_eq!(SystemzRegisterInfo::get_dwarf_num(SystemzRegister::A0), 48);
}
#[test]
fn test_register_width() {
assert_eq!(SystemzRegisterInfo::get_width(SystemzRegister::R0), 64);
assert_eq!(SystemzRegisterInfo::get_width(SystemzRegister::A0), 32);
assert_eq!(SystemzRegisterInfo::get_width(SystemzRegister::PSW), 128);
}
#[test]
fn test_is_gpr() {
assert!(SystemzRegisterInfo::is_gpr(SystemzRegister::R0));
assert!(!SystemzRegisterInfo::is_gpr(SystemzRegister::F0));
assert!(!SystemzRegisterInfo::is_gpr(SystemzRegister::A0));
}
#[test]
fn test_is_fpr() {
assert!(SystemzRegisterInfo::is_fpr(SystemzRegister::F0));
assert!(!SystemzRegisterInfo::is_fpr(SystemzRegister::R0));
assert!(!SystemzRegisterInfo::is_fpr(SystemzRegister::A0));
}
#[test]
fn test_is_ar() {
assert!(SystemzRegisterInfo::is_ar(SystemzRegister::A0));
assert!(!SystemzRegisterInfo::is_ar(SystemzRegister::R0));
}
#[test]
fn test_callee_saved() {
assert!(SystemzRegisterInfo::is_callee_saved(SystemzRegister::R6));
assert!(SystemzRegisterInfo::is_callee_saved(SystemzRegister::R15));
assert!(!SystemzRegisterInfo::is_callee_saved(SystemzRegister::R2));
}
#[test]
fn test_caller_saved() {
assert!(SystemzRegisterInfo::is_caller_saved(SystemzRegister::R0));
assert!(SystemzRegisterInfo::is_caller_saved(SystemzRegister::R2));
}
#[test]
fn test_special_registers() {
assert_eq!(
SystemzRegisterInfo::get_stack_pointer(),
SystemzRegister::R15
);
assert_eq!(
SystemzRegisterInfo::get_frame_pointer(),
SystemzRegister::R11
);
assert_eq!(
SystemzRegisterInfo::get_return_address(),
SystemzRegister::R14
);
assert_eq!(SystemzRegisterInfo::get_zero_reg(), SystemzRegister::R0);
}
#[test]
fn test_arg_regs() {
let args = SystemzRegisterInfo::get_arg_regs();
assert_eq!(args.len(), 5);
assert_eq!(args[0], SystemzRegister::R2);
}
#[test]
fn test_fp_arg_regs() {
let args = SystemzRegisterInfo::get_fp_arg_regs();
assert_eq!(args.len(), 4);
assert_eq!(args[0], SystemzRegister::F0);
}
#[test]
fn test_return_regs() {
let ret = SystemzRegisterInfo::get_return_regs();
assert_eq!(ret, vec![SystemzRegister::R2, SystemzRegister::R3]);
}
#[test]
fn test_can_be_base_reg() {
assert!(SystemzRegisterInfo::can_be_base_reg(SystemzRegister::R1));
assert!(!SystemzRegisterInfo::can_be_base_reg(SystemzRegister::R0));
assert!(!SystemzRegisterInfo::can_be_base_reg(SystemzRegister::F0));
}
#[test]
fn test_allocatable_gprs_count() {
let gprs = SystemzRegisterInfo::get_allocatable_gprs();
assert_eq!(gprs.len(), 14); }
#[test]
fn test_allocatable_fprs_count() {
let fprs = SystemzRegisterInfo::get_allocatable_fprs();
assert_eq!(fprs.len(), 16);
}
#[test]
fn test_caller_saved_gprs_count() {
let gprs = SystemzRegisterInfo::get_caller_saved_gprs();
assert_eq!(gprs.len(), 7);
}
}