pub const R0: u16 = 7000;
pub const R1: u16 = 7001;
pub const R2: u16 = 7002;
pub const R3: u16 = 7003;
pub const R4: u16 = 7004;
pub const R5: u16 = 7005;
pub const R6: u16 = 7006;
pub const R7: u16 = 7007;
pub const R8: u16 = 7008;
pub const R9: u16 = 7009;
pub const R10: u16 = 7010;
pub const R11: u16 = 7011;
pub const R12: u16 = 7012;
pub const R13: u16 = 7013;
pub const R14: u16 = 7014;
pub const R15: u16 = 7015;
pub const R16: u16 = 7016;
pub const R17: u16 = 7017;
pub const R18: u16 = 7018;
pub const R19: u16 = 7019;
pub const R20: u16 = 7020;
pub const R21: u16 = 7021;
pub const R22: u16 = 7022;
pub const R23: u16 = 7023;
pub const R24: u16 = 7024;
pub const R25: u16 = 7025;
pub const R26: u16 = 7026;
pub const R27: u16 = 7027;
pub const R28: u16 = 7028;
pub const R29: u16 = 7029; pub const R30: u16 = 7030; pub const R31: u16 = 7031;
pub const SP: u16 = R29;
pub const FP: u16 = R30;
pub const LR: u16 = R31;
pub const P0: u16 = 7032; pub const P1: u16 = 7033;
pub const P2: u16 = 7034;
pub const P3: u16 = 7035;
pub const V0: u16 = 7040;
pub const V1: u16 = 7041;
pub const V2: u16 = 7042;
pub const V3: u16 = 7043;
pub const V4: u16 = 7044;
pub const V5: u16 = 7045;
pub const V6: u16 = 7046;
pub const V7: u16 = 7047;
pub const V8: u16 = 7048;
pub const V9: u16 = 7049;
pub const V10: u16 = 7050;
pub const V11: u16 = 7051;
pub const V12: u16 = 7052;
pub const V13: u16 = 7053;
pub const V14: u16 = 7054;
pub const V15: u16 = 7055;
pub const V16: u16 = 7056;
pub const V17: u16 = 7057;
pub const V18: u16 = 7058;
pub const V19: u16 = 7059;
pub const V20: u16 = 7060;
pub const V21: u16 = 7061;
pub const V22: u16 = 7062;
pub const V23: u16 = 7063;
pub const V24: u16 = 7064;
pub const V25: u16 = 7065;
pub const V26: u16 = 7066;
pub const V27: u16 = 7067;
pub const V28: u16 = 7068;
pub const V29: u16 = 7069;
pub const V30: u16 = 7070;
pub const V31: u16 = 7071;
pub const HEXAGON_GPR_COUNT: usize = 32;
pub const HEXAGON_PRED_COUNT: usize = 4;
pub const HEXAGON_VEC_COUNT: usize = 32;
pub const HEXAGON_MAX_REG_ID: u16 = 7071;
pub const HEXAGON_GPR_BASE: u16 = 7000;
pub const HEXAGON_PRED_BASE: u16 = 7032;
pub const HEXAGON_VEC_BASE: u16 = 7040;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum HexagonRegClass {
GPR,
PRED,
VEC,
}
impl std::fmt::Display for HexagonRegClass {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
HexagonRegClass::GPR => write!(f, "GPR"),
HexagonRegClass::PRED => write!(f, "PRED"),
HexagonRegClass::VEC => write!(f, "VEC"),
}
}
}
pub struct HexagonRegisterInfo;
impl HexagonRegisterInfo {
pub fn get_asm_name(reg_id: u16) -> String {
match reg_id {
R0 => "r0".into(),
R1 => "r1".into(),
R2 => "r2".into(),
R3 => "r3".into(),
R4 => "r4".into(),
R5 => "r5".into(),
R6 => "r6".into(),
R7 => "r7".into(),
R8 => "r8".into(),
R9 => "r9".into(),
R10 => "r10".into(),
R11 => "r11".into(),
R12 => "r12".into(),
R13 => "r13".into(),
R14 => "r14".into(),
R15 => "r15".into(),
R16 => "r16".into(),
R17 => "r17".into(),
R18 => "r18".into(),
R19 => "r19".into(),
R20 => "r20".into(),
R21 => "r21".into(),
R22 => "r22".into(),
R23 => "r23".into(),
R24 => "r24".into(),
R25 => "r25".into(),
R26 => "r26".into(),
R27 => "r27".into(),
R28 => "r28".into(),
R29 => "r29".into(),
R30 => "r30".into(),
R31 => "r31".into(),
P0 => "p0".into(),
P1 => "p1".into(),
P2 => "p2".into(),
P3 => "p3".into(),
_ if reg_id >= V0 && reg_id <= V31 => {
format!("v{}", reg_id - V0)
}
_ => format!("r{}", reg_id),
}
}
pub fn get_abi_name(reg_id: u16) -> String {
match reg_id {
R29 => "sp".into(),
R30 => "fp".into(),
R31 => "lr".into(),
_ => Self::get_asm_name(reg_id),
}
}
pub fn get_reg_class(reg_id: u16) -> HexagonRegClass {
if reg_id >= HEXAGON_GPR_BASE && reg_id < HEXAGON_GPR_BASE + 32 {
HexagonRegClass::GPR
} else if reg_id >= HEXAGON_PRED_BASE && reg_id < HEXAGON_PRED_BASE + 4 {
HexagonRegClass::PRED
} else if reg_id >= HEXAGON_VEC_BASE && reg_id < HEXAGON_VEC_BASE + 32 {
HexagonRegClass::VEC
} else {
HexagonRegClass::GPR
}
}
pub fn get_reg_width(reg_id: u16, _is_64bit: bool) -> u32 {
match Self::get_reg_class(reg_id) {
HexagonRegClass::GPR => 32,
HexagonRegClass::PRED => 1,
HexagonRegClass::VEC => 512,
}
}
pub fn get_dwarf_num(reg_id: u16) -> i32 {
match reg_id {
_ if reg_id >= R0 && reg_id <= R31 => (reg_id - R0) as i32,
_ => -1,
}
}
pub fn is_callee_saved(reg_id: u16) -> bool {
matches!(
reg_id,
R16 | R17
| R18
| R19
| R20
| R21
| R22
| R23
| R24
| R25
| R26
| R27
| R28
| R30
| R31
| R29
)
}
pub fn is_caller_saved(reg_id: u16) -> bool {
matches!(
reg_id,
R0 | R1 | R2 | R3 | R4 | R5 | R6 | R7 | R8 | R9 | R10 | R11 | R12 | R13 | R14 | R15
)
}
pub fn is_reserved(reg_id: u16) -> bool {
reg_id == R29 || reg_id == R31 || reg_id == P3
}
pub fn get_allocatable_gprs() -> Vec<u16> {
let mut regs = Vec::new();
for i in 0..32 {
let r = HEXAGON_GPR_BASE + i as u16;
if !Self::is_reserved(r) {
regs.push(r);
}
}
regs
}
pub fn get_allocatable_vecs() -> Vec<u16> {
(V0..=V31).collect()
}
pub fn get_argument_regs() -> Vec<u16> {
vec![R0, R1, R2, R3, R4, R5]
}
pub fn get_return_regs() -> Vec<u16> {
vec![R0, R1]
}
pub fn get_frame_pointer_reg() -> u16 {
FP
}
pub fn get_return_address_reg() -> u16 {
LR
}
pub fn get_stack_pointer_reg() -> u16 {
SP
}
pub fn get_zero_reg() -> u16 {
R0
}
pub fn is_gpr(reg_id: u16) -> bool {
Self::get_reg_class(reg_id) == HexagonRegClass::GPR
}
pub fn is_pred(reg_id: u16) -> bool {
Self::get_reg_class(reg_id) == HexagonRegClass::PRED
}
pub fn is_vec(reg_id: u16) -> bool {
Self::get_reg_class(reg_id) == HexagonRegClass::VEC
}
pub fn get_reg_index(reg_id: u16) -> u8 {
if reg_id >= HEXAGON_GPR_BASE && reg_id < HEXAGON_GPR_BASE + 32 {
(reg_id - HEXAGON_GPR_BASE) as u8
} else if reg_id >= HEXAGON_PRED_BASE && reg_id < HEXAGON_PRED_BASE + 4 {
(reg_id - HEXAGON_PRED_BASE) as u8
} else if reg_id >= HEXAGON_VEC_BASE && reg_id < HEXAGON_VEC_BASE + 32 {
(reg_id - HEXAGON_VEC_BASE) as u8
} else {
0
}
}
pub fn can_be_base_reg(reg_id: u16) -> bool {
Self::is_gpr(reg_id)
}
pub fn get_caller_saved_gprs() -> Vec<u16> {
let mut regs = Vec::new();
for i in 0..32 {
let r = HEXAGON_GPR_BASE + i as u16;
if Self::is_caller_saved(r) {
regs.push(r);
}
}
regs
}
pub fn get_callee_saved_gprs() -> Vec<u16> {
let mut regs = Vec::new();
for i in 0..32 {
let r = HEXAGON_GPR_BASE + i as u16;
if Self::is_callee_saved(r) {
regs.push(r);
}
}
regs
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_register_count_constants() {
assert_eq!(HEXAGON_GPR_COUNT, 32);
assert_eq!(HEXAGON_PRED_COUNT, 4);
assert_eq!(HEXAGON_VEC_COUNT, 32);
assert_eq!(HEXAGON_MAX_REG_ID, 7071);
}
#[test]
fn test_abi_names() {
assert_eq!(HexagonRegisterInfo::get_asm_name(R0), "r0");
assert_eq!(HexagonRegisterInfo::get_asm_name(R29), "r29");
assert_eq!(HexagonRegisterInfo::get_asm_name(R31), "r31");
assert_eq!(HexagonRegisterInfo::get_abi_name(R29), "sp");
assert_eq!(HexagonRegisterInfo::get_abi_name(R30), "fp");
assert_eq!(HexagonRegisterInfo::get_abi_name(R31), "lr");
}
#[test]
fn test_pred_names() {
assert_eq!(HexagonRegisterInfo::get_asm_name(P0), "p0");
assert_eq!(HexagonRegisterInfo::get_asm_name(P3), "p3");
}
#[test]
fn test_vec_names() {
assert_eq!(HexagonRegisterInfo::get_asm_name(V0), "v0");
assert_eq!(HexagonRegisterInfo::get_asm_name(V31), "v31");
}
#[test]
fn test_get_reg_class() {
assert_eq!(HexagonRegisterInfo::get_reg_class(R0), HexagonRegClass::GPR);
assert_eq!(
HexagonRegisterInfo::get_reg_class(P0),
HexagonRegClass::PRED
);
assert_eq!(HexagonRegisterInfo::get_reg_class(V0), HexagonRegClass::VEC);
}
#[test]
fn test_get_reg_width() {
assert_eq!(HexagonRegisterInfo::get_reg_width(R0, false), 32);
assert_eq!(HexagonRegisterInfo::get_reg_width(P0, false), 1);
assert_eq!(HexagonRegisterInfo::get_reg_width(V0, false), 512);
}
#[test]
fn test_is_callee_saved() {
assert!(HexagonRegisterInfo::is_callee_saved(R16));
assert!(HexagonRegisterInfo::is_callee_saved(FP));
assert!(!HexagonRegisterInfo::is_callee_saved(R0));
}
#[test]
fn test_is_caller_saved() {
assert!(HexagonRegisterInfo::is_caller_saved(R0));
assert!(HexagonRegisterInfo::is_caller_saved(R5));
assert!(!HexagonRegisterInfo::is_caller_saved(R16));
}
#[test]
fn test_is_reserved() {
assert!(HexagonRegisterInfo::is_reserved(R29));
assert!(HexagonRegisterInfo::is_reserved(R31));
assert!(HexagonRegisterInfo::is_reserved(P3));
assert!(!HexagonRegisterInfo::is_reserved(R0));
}
#[test]
fn test_get_argument_regs() {
let regs = HexagonRegisterInfo::get_argument_regs();
assert_eq!(regs, vec![R0, R1, R2, R3, R4, R5]);
}
#[test]
fn test_get_return_regs() {
let regs = HexagonRegisterInfo::get_return_regs();
assert_eq!(regs, vec![R0, R1]);
}
#[test]
fn test_get_reg_index() {
assert_eq!(HexagonRegisterInfo::get_reg_index(R0), 0);
assert_eq!(HexagonRegisterInfo::get_reg_index(R31), 31);
assert_eq!(HexagonRegisterInfo::get_reg_index(P0), 0);
assert_eq!(HexagonRegisterInfo::get_reg_index(V0), 0);
assert_eq!(HexagonRegisterInfo::get_reg_index(V31), 31);
}
}