use std::fmt;
pub const X0: u16 = 2000;
pub const X1: u16 = 2001;
pub const X2: u16 = 2002;
pub const X3: u16 = 2003;
pub const X4: u16 = 2004;
pub const X5: u16 = 2005;
pub const X6: u16 = 2006;
pub const X7: u16 = 2007;
pub const X8: u16 = 2008;
pub const X9: u16 = 2009;
pub const X10: u16 = 2010;
pub const X11: u16 = 2011;
pub const X12: u16 = 2012;
pub const X13: u16 = 2013;
pub const X14: u16 = 2014;
pub const X15: u16 = 2015;
pub const X16: u16 = 2016;
pub const X17: u16 = 2017;
pub const X18: u16 = 2018;
pub const X19: u16 = 2019;
pub const X20: u16 = 2020;
pub const X21: u16 = 2021;
pub const X22: u16 = 2022;
pub const X23: u16 = 2023;
pub const X24: u16 = 2024;
pub const X25: u16 = 2025;
pub const X26: u16 = 2026;
pub const X27: u16 = 2027;
pub const X28: u16 = 2028;
pub const X29: u16 = 2029;
pub const X30: u16 = 2030;
pub const SP: u16 = 2031;
pub const XZR: u16 = 2032;
pub const PC_AARCH64: u16 = 2033;
pub const FP: u16 = 2029; pub const LR: u16 = 2030;
pub const W0: u16 = 2040;
pub const W1: u16 = 2041;
pub const W2: u16 = 2042;
pub const W3: u16 = 2043;
pub const W4: u16 = 2044;
pub const W5: u16 = 2045;
pub const W6: u16 = 2046;
pub const W7: u16 = 2047;
pub const W8: u16 = 2048;
pub const W9: u16 = 2049;
pub const W10: u16 = 2050;
pub const W11: u16 = 2051;
pub const W12: u16 = 2052;
pub const W13: u16 = 2053;
pub const W14: u16 = 2054;
pub const W15: u16 = 2055;
pub const W16: u16 = 2056;
pub const W17: u16 = 2057;
pub const W18: u16 = 2058;
pub const W19: u16 = 2059;
pub const W20: u16 = 2060;
pub const W21: u16 = 2061;
pub const W22: u16 = 2062;
pub const W23: u16 = 2063;
pub const W24: u16 = 2064;
pub const W25: u16 = 2065;
pub const W26: u16 = 2066;
pub const W27: u16 = 2067;
pub const W28: u16 = 2068;
pub const W29: u16 = 2069;
pub const W30: u16 = 2070;
pub const WSP: u16 = 2071;
pub const WZR: u16 = 2072;
pub const R0: u16 = 2100;
pub const R1: u16 = 2101;
pub const R2: u16 = 2102;
pub const R3: u16 = 2103;
pub const R4: u16 = 2104;
pub const R5: u16 = 2105;
pub const R6: u16 = 2106;
pub const R7: u16 = 2107;
pub const R8: u16 = 2108;
pub const R9: u16 = 2109;
pub const R10: u16 = 2110;
pub const R11: u16 = 2111;
pub const R12: u16 = 2112;
pub const R13: u16 = 2113;
pub const R14: u16 = 2114;
pub const R15: u16 = 2115;
pub const SP_ARM32: u16 = 2113; pub const LR_ARM32: u16 = 2114; pub const PC_ARM32: u16 = 2115; pub const CPSR: u16 = 2116;
pub const V0: u16 = 2200;
pub const V1: u16 = 2201;
pub const V2: u16 = 2202;
pub const V3: u16 = 2203;
pub const V4: u16 = 2204;
pub const V5: u16 = 2205;
pub const V6: u16 = 2206;
pub const V7: u16 = 2207;
pub const V8: u16 = 2208;
pub const V9: u16 = 2209;
pub const V10: u16 = 2210;
pub const V11: u16 = 2211;
pub const V12: u16 = 2212;
pub const V13: u16 = 2213;
pub const V14: u16 = 2214;
pub const V15: u16 = 2215;
pub const V16: u16 = 2216;
pub const V17: u16 = 2217;
pub const V18: u16 = 2218;
pub const V19: u16 = 2219;
pub const V20: u16 = 2220;
pub const V21: u16 = 2221;
pub const V22: u16 = 2222;
pub const V23: u16 = 2223;
pub const V24: u16 = 2224;
pub const V25: u16 = 2225;
pub const V26: u16 = 2226;
pub const V27: u16 = 2227;
pub const V28: u16 = 2228;
pub const V29: u16 = 2229;
pub const V30: u16 = 2230;
pub const V31: u16 = 2231;
pub const Q0: u16 = 2250;
pub const Q1: u16 = 2251;
pub const Q2: u16 = 2252;
pub const Q3: u16 = 2253;
pub const Q4: u16 = 2254;
pub const Q5: u16 = 2255;
pub const Q6: u16 = 2256;
pub const Q7: u16 = 2257;
pub const Q8: u16 = 2258;
pub const Q9: u16 = 2259;
pub const Q10: u16 = 2260;
pub const Q11: u16 = 2261;
pub const Q12: u16 = 2262;
pub const Q13: u16 = 2263;
pub const Q14: u16 = 2264;
pub const Q15: u16 = 2265;
pub const Q16: u16 = 2266;
pub const Q17: u16 = 2267;
pub const Q18: u16 = 2268;
pub const Q19: u16 = 2269;
pub const Q20: u16 = 2270;
pub const Q21: u16 = 2271;
pub const Q22: u16 = 2272;
pub const Q23: u16 = 2273;
pub const Q24: u16 = 2274;
pub const Q25: u16 = 2275;
pub const Q26: u16 = 2276;
pub const Q27: u16 = 2277;
pub const Q28: u16 = 2278;
pub const Q29: u16 = 2279;
pub const Q30: u16 = 2280;
pub const Q31: u16 = 2281;
pub const D0: u16 = 2300;
pub const D1: u16 = 2301;
pub const D2: u16 = 2302;
pub const D3: u16 = 2303;
pub const D4: u16 = 2304;
pub const D5: u16 = 2305;
pub const D6: u16 = 2306;
pub const D7: u16 = 2307;
pub const D8: u16 = 2308;
pub const D9: u16 = 2309;
pub const D10: u16 = 2310;
pub const D11: u16 = 2311;
pub const D12: u16 = 2312;
pub const D13: u16 = 2313;
pub const D14: u16 = 2314;
pub const D15: u16 = 2315;
pub const D16: u16 = 2316;
pub const D17: u16 = 2317;
pub const D18: u16 = 2318;
pub const D19: u16 = 2319;
pub const D20: u16 = 2320;
pub const D21: u16 = 2321;
pub const D22: u16 = 2322;
pub const D23: u16 = 2323;
pub const D24: u16 = 2324;
pub const D25: u16 = 2325;
pub const D26: u16 = 2326;
pub const D27: u16 = 2327;
pub const D28: u16 = 2328;
pub const D29: u16 = 2329;
pub const D30: u16 = 2330;
pub const D31: u16 = 2331;
pub const S0: u16 = 2350;
pub const S1: u16 = 2351;
pub const S2: u16 = 2352;
pub const S3: u16 = 2353;
pub const S4: u16 = 2354;
pub const S5: u16 = 2355;
pub const S6: u16 = 2356;
pub const S7: u16 = 2357;
pub const S8: u16 = 2358;
pub const S9: u16 = 2359;
pub const S10: u16 = 2360;
pub const S11: u16 = 2361;
pub const S12: u16 = 2362;
pub const S13: u16 = 2363;
pub const S14: u16 = 2364;
pub const S15: u16 = 2365;
pub const S16: u16 = 2366;
pub const S17: u16 = 2367;
pub const S18: u16 = 2368;
pub const S19: u16 = 2369;
pub const S20: u16 = 2370;
pub const S21: u16 = 2371;
pub const S22: u16 = 2372;
pub const S23: u16 = 2373;
pub const S24: u16 = 2374;
pub const S25: u16 = 2375;
pub const S26: u16 = 2376;
pub const S27: u16 = 2377;
pub const S28: u16 = 2378;
pub const S29: u16 = 2379;
pub const S30: u16 = 2380;
pub const S31: u16 = 2381;
pub const H0: u16 = 2400;
pub const H1: u16 = 2401;
pub const H2: u16 = 2402;
pub const H3: u16 = 2403;
pub const H4: u16 = 2404;
pub const H5: u16 = 2405;
pub const H6: u16 = 2406;
pub const H7: u16 = 2407;
pub const H8: u16 = 2408;
pub const H9: u16 = 2409;
pub const H10: u16 = 2410;
pub const H11: u16 = 2411;
pub const H12: u16 = 2412;
pub const H13: u16 = 2413;
pub const H14: u16 = 2414;
pub const H15: u16 = 2415;
pub const H16: u16 = 2416;
pub const H17: u16 = 2417;
pub const H18: u16 = 2418;
pub const H19: u16 = 2419;
pub const H20: u16 = 2420;
pub const H21: u16 = 2421;
pub const H22: u16 = 2422;
pub const H23: u16 = 2423;
pub const H24: u16 = 2424;
pub const H25: u16 = 2425;
pub const H26: u16 = 2426;
pub const H27: u16 = 2427;
pub const H28: u16 = 2428;
pub const H29: u16 = 2429;
pub const H30: u16 = 2430;
pub const H31: u16 = 2431;
pub const B0: u16 = 2450;
pub const B1: u16 = 2451;
pub const B2: u16 = 2452;
pub const B3: u16 = 2453;
pub const B4: u16 = 2454;
pub const B5: u16 = 2455;
pub const B6: u16 = 2456;
pub const B7: u16 = 2457;
pub const B8: u16 = 2458;
pub const B9: u16 = 2459;
pub const B10: u16 = 2460;
pub const B11: u16 = 2461;
pub const B12: u16 = 2462;
pub const B13: u16 = 2463;
pub const B14: u16 = 2464;
pub const B15: u16 = 2465;
pub const B16: u16 = 2466;
pub const B17: u16 = 2467;
pub const B18: u16 = 2468;
pub const B19: u16 = 2469;
pub const B20: u16 = 2470;
pub const B21: u16 = 2471;
pub const B22: u16 = 2472;
pub const B23: u16 = 2473;
pub const B24: u16 = 2474;
pub const B25: u16 = 2475;
pub const B26: u16 = 2476;
pub const B27: u16 = 2477;
pub const B28: u16 = 2478;
pub const B29: u16 = 2479;
pub const B30: u16 = 2480;
pub const B31: u16 = 2481;
pub const D0_ARM32: u16 = 2500;
pub const D1_ARM32: u16 = 2501;
pub const D2_ARM32: u16 = 2502;
pub const D3_ARM32: u16 = 2503;
pub const D4_ARM32: u16 = 2504;
pub const D5_ARM32: u16 = 2505;
pub const D6_ARM32: u16 = 2506;
pub const D7_ARM32: u16 = 2507;
pub const D8_ARM32: u16 = 2508;
pub const D9_ARM32: u16 = 2509;
pub const D10_ARM32: u16 = 2510;
pub const D11_ARM32: u16 = 2511;
pub const D12_ARM32: u16 = 2512;
pub const D13_ARM32: u16 = 2513;
pub const D14_ARM32: u16 = 2514;
pub const D15_ARM32: u16 = 2515;
pub const D16_ARM32: u16 = 2516;
pub const D17_ARM32: u16 = 2517;
pub const D18_ARM32: u16 = 2518;
pub const D19_ARM32: u16 = 2519;
pub const D20_ARM32: u16 = 2520;
pub const D21_ARM32: u16 = 2521;
pub const D22_ARM32: u16 = 2522;
pub const D23_ARM32: u16 = 2523;
pub const D24_ARM32: u16 = 2524;
pub const D25_ARM32: u16 = 2525;
pub const D26_ARM32: u16 = 2526;
pub const D27_ARM32: u16 = 2527;
pub const D28_ARM32: u16 = 2528;
pub const D29_ARM32: u16 = 2529;
pub const D30_ARM32: u16 = 2530;
pub const D31_ARM32: u16 = 2531;
pub const S0_ARM32: u16 = 2550;
pub const S1_ARM32: u16 = 2551;
pub const S2_ARM32: u16 = 2552;
pub const S3_ARM32: u16 = 2553;
pub const S4_ARM32: u16 = 2554;
pub const S5_ARM32: u16 = 2555;
pub const S6_ARM32: u16 = 2556;
pub const S7_ARM32: u16 = 2557;
pub const S8_ARM32: u16 = 2558;
pub const S9_ARM32: u16 = 2559;
pub const S10_ARM32: u16 = 2560;
pub const S11_ARM32: u16 = 2561;
pub const S12_ARM32: u16 = 2562;
pub const S13_ARM32: u16 = 2563;
pub const S14_ARM32: u16 = 2564;
pub const S15_ARM32: u16 = 2565;
pub const S16_ARM32: u16 = 2566;
pub const S17_ARM32: u16 = 2567;
pub const S18_ARM32: u16 = 2568;
pub const S19_ARM32: u16 = 2569;
pub const S20_ARM32: u16 = 2570;
pub const S21_ARM32: u16 = 2571;
pub const S22_ARM32: u16 = 2572;
pub const S23_ARM32: u16 = 2573;
pub const S24_ARM32: u16 = 2574;
pub const S25_ARM32: u16 = 2575;
pub const S26_ARM32: u16 = 2576;
pub const S27_ARM32: u16 = 2577;
pub const S28_ARM32: u16 = 2578;
pub const S29_ARM32: u16 = 2579;
pub const S30_ARM32: u16 = 2580;
pub const S31_ARM32: u16 = 2581;
pub const NZCV: u16 = 2117;
pub const AARCH64_REG_COUNT: usize = 282;
pub const ARM32_REG_COUNT: usize = 180;
pub const ARM_MAX_REG_ID: u16 = 2581;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ArmRegClass {
GPR64,
GPR32,
GPR32ARM,
FPR128,
FPR64,
FPR32,
FPR16,
FPR8,
SPR,
Flags,
}
impl fmt::Display for ArmRegClass {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ArmRegClass::GPR64 => write!(f, "GPR64"),
ArmRegClass::GPR32 => write!(f, "GPR32"),
ArmRegClass::GPR32ARM => write!(f, "GPR32ARM"),
ArmRegClass::FPR128 => write!(f, "FPR128"),
ArmRegClass::FPR64 => write!(f, "FPR64"),
ArmRegClass::FPR32 => write!(f, "FPR32"),
ArmRegClass::FPR16 => write!(f, "FPR16"),
ArmRegClass::FPR8 => write!(f, "FPR8"),
ArmRegClass::SPR => write!(f, "SPR"),
ArmRegClass::Flags => write!(f, "Flags"),
}
}
}
#[derive(Debug, Clone)]
pub struct ArmRegisterInfo;
impl ArmRegisterInfo {
pub fn get_asm_name(reg_id: u16) -> &'static str {
match reg_id {
X0..=X30 => {
let idx = (reg_id - X0) as usize;
X64_NAMES[idx]
}
SP => "sp",
XZR => "xzr",
PC_AARCH64 => "pc",
W0..=W30 => {
let idx = (reg_id - W0) as usize;
W32_NAMES[idx]
}
WSP => "wsp",
WZR => "wzr",
R0..=R15 => {
let idx = (reg_id - R0) as usize;
ARM32_NAMES[idx]
}
CPSR => "cpsr",
NZCV => "nzcv",
V0..=V31 => {
let idx = (reg_id - V0) as usize;
V128_NAMES[idx]
}
Q0..=Q31 => {
let idx = (reg_id - Q0) as usize;
Q128_NAMES[idx]
}
D0..=D31 => {
let idx = (reg_id - D0) as usize;
D64_NAMES[idx]
}
S0..=S31 => {
let idx = (reg_id - S0) as usize;
S32_NAMES[idx]
}
H0..=H31 => {
let idx = (reg_id - H0) as usize;
H16_NAMES[idx]
}
B0..=B31 => {
let idx = (reg_id - B0) as usize;
B8_NAMES[idx]
}
D0_ARM32..=D31_ARM32 => {
let idx = (reg_id - D0_ARM32) as usize;
D64_NAMES[idx]
}
S0_ARM32..=S31_ARM32 => {
let idx = (reg_id - S0_ARM32) as usize;
S32_NAMES[idx]
}
_ => "??",
}
}
pub fn get_reg_class(reg_id: u16) -> ArmRegClass {
match reg_id {
X0..=X30 | SP | XZR | PC_AARCH64 => ArmRegClass::GPR64,
W0..=W30 | WSP | WZR => ArmRegClass::GPR32,
R0..=R15 | CPSR => ArmRegClass::GPR32ARM,
V0..=V31 | Q0..=Q31 => ArmRegClass::FPR128,
D0..=D31 => ArmRegClass::FPR64,
S0..=S31 => ArmRegClass::FPR32,
H0..=H31 => ArmRegClass::FPR16,
B0..=B31 => ArmRegClass::FPR8,
D0_ARM32..=D31_ARM32 => ArmRegClass::FPR64,
S0_ARM32..=S31_ARM32 => ArmRegClass::SPR,
NZCV => ArmRegClass::Flags,
_ => ArmRegClass::GPR64, }
}
pub fn get_reg_width(reg_id: u16) -> u16 {
match reg_id {
X0..=X30 | SP | XZR | PC_AARCH64 => 64,
W0..=W30 | WSP | WZR => 32,
R0..=R15 | CPSR => 32,
V0..=V31 | Q0..=Q31 => 128,
D0..=D31 => 64,
S0..=S31 => 32,
H0..=H31 => 16,
B0..=B31 => 8,
D0_ARM32..=D31_ARM32 => 64,
S0_ARM32..=S31_ARM32 => 32,
NZCV => 4,
_ => 0,
}
}
pub fn get_dwarf_num(reg_id: u16) -> i16 {
match reg_id {
X0..=X30 => (reg_id - X0) as i16,
SP => 31,
XZR => -1, PC_AARCH64 => 32,
W0..=W30 => (reg_id - W0) as i16,
WSP => 31,
WZR => -1,
R0..=R15 => (reg_id - R0) as i16,
CPSR => 25, NZCV => -1,
V0..=V31 => 64 + (reg_id - V0) as i16,
Q0..=Q31 => 64 + (reg_id - Q0) as i16,
D0..=D31 => 64 + (reg_id - D0) as i16,
S0..=S31 => 64 + (reg_id - S0) as i16,
H0..=H31 => 64 + (reg_id - H0) as i16,
B0..=B31 => 64 + (reg_id - B0) as i16,
D0_ARM32..=D31_ARM32 => 256 + (reg_id - D0_ARM32) as i16,
S0_ARM32..=S31_ARM32 => 64 + (reg_id - S0_ARM32) as i16,
_ => -1,
}
}
pub fn is_callee_saved(reg_id: u16, is_aapcs64: bool) -> bool {
if is_aapcs64 {
match reg_id {
X19..=X28 | X29 | X30 => true,
V8..=V15 | Q8..=Q15 | D8..=D15 => true,
SP | XZR => true, _ => false,
}
} else {
match reg_id {
R4..=R11 | R13 => true,
D8_ARM32..=D15_ARM32 => true,
_ => false,
}
}
}
pub fn is_reserved(reg_id: u16) -> bool {
match reg_id {
SP | XZR | WSP | WZR | PC_AARCH64 => true,
R13 | R14 | R15 => true, CPSR | NZCV => true,
_ => false,
}
}
pub fn get_sub_reg_32(reg64: u16) -> u16 {
match reg64 {
X0..=X30 => W0 + (reg64 - X0),
SP => WSP,
XZR => WZR,
_ => reg64,
}
}
pub fn get_super_reg_64(reg32: u16) -> u16 {
match reg32 {
W0..=W30 => X0 + (reg32 - W0),
WSP => SP,
WZR => XZR,
_ => reg32,
}
}
pub fn get_sub_reg_64(reg128: u16) -> u16 {
match reg128 {
V0..=V31 => D0 + (reg128 - V0),
Q0..=Q31 => D0 + (reg128 - Q0),
_ => reg128,
}
}
pub fn get_super_reg_128(reg64: u16) -> u16 {
match reg64 {
D0..=D31 => V0 + (reg64 - D0),
_ => reg64,
}
}
pub fn change_width(reg_id: u16, new_width: u16) -> u16 {
let current_width = Self::get_reg_width(reg_id);
if new_width == current_width {
return reg_id;
}
if matches!(
Self::get_reg_class(reg_id),
ArmRegClass::GPR64 | ArmRegClass::GPR32
) {
match (current_width, new_width) {
(64, 32) => return Self::get_sub_reg_32(reg_id),
(32, 64) => return Self::get_super_reg_64(reg_id),
_ => {}
}
}
if matches!(
Self::get_reg_class(reg_id),
ArmRegClass::FPR128
| ArmRegClass::FPR64
| ArmRegClass::FPR32
| ArmRegClass::FPR16
| ArmRegClass::FPR8
) {
let v_index = match reg_id {
V0..=V31 => reg_id - V0,
Q0..=Q31 => reg_id - Q0,
D0..=D31 => reg_id - D0,
S0..=S31 => reg_id - S0,
H0..=H31 => reg_id - H0,
B0..=B31 => reg_id - B0,
_ => return reg_id,
};
match new_width {
128 => V0 + v_index,
64 => D0 + v_index,
32 => S0 + v_index,
16 => H0 + v_index,
8 => B0 + v_index,
_ => reg_id,
}
} else {
reg_id
}
}
pub fn get_allocatable_gprs_aarch64() -> Vec<u16> {
let mut regs = Vec::with_capacity(29);
for i in 0..=15 {
regs.push(X0 + i); }
regs.push(X16);
regs.push(X17);
regs.push(X18);
for i in 19..=28 {
regs.push(X0 + i); }
regs
}
pub fn get_allocatable_gprs_arm32() -> Vec<u16> {
let mut regs = Vec::with_capacity(13);
for i in 0..=3 {
regs.push(R0 + i); }
regs.push(R12); for i in 4..=11 {
regs.push(R0 + i); }
regs
}
pub fn get_allocatable_fprs() -> Vec<u16> {
let mut regs = Vec::with_capacity(32);
for i in 0..=7 {
regs.push(V0 + i);
}
for i in 16..=31 {
regs.push(V0 + i);
}
for i in 8..=15 {
regs.push(V0 + i);
}
regs
}
pub fn get_caller_saved_aapcs64() -> Vec<u16> {
let mut regs = Vec::with_capacity(43);
for i in 0..=18 {
regs.push(X0 + i);
}
for i in 0..=7 {
regs.push(V0 + i);
}
for i in 16..=31 {
regs.push(V0 + i);
}
regs
}
pub fn get_callee_saved_aapcs64() -> Vec<u16> {
let mut regs = Vec::with_capacity(18);
for i in 19..=28 {
regs.push(X0 + i);
}
regs.push(X29); regs.push(X30); for i in 8..=15 {
regs.push(V0 + i);
}
regs
}
pub fn get_callee_saved_aapcs() -> Vec<u16> {
let mut regs = Vec::with_capacity(8);
for i in 4..=11 {
regs.push(R0 + i);
}
regs
}
pub fn get_caller_saved_aapcs() -> Vec<u16> {
let mut regs = Vec::with_capacity(5);
for i in 0..=3 {
regs.push(R0 + i);
}
regs.push(R12); regs
}
pub fn is_gpr(reg_id: u16) -> bool {
matches!(
Self::get_reg_class(reg_id),
ArmRegClass::GPR64 | ArmRegClass::GPR32 | ArmRegClass::GPR32ARM
)
}
pub fn is_fpr(reg_id: u16) -> bool {
matches!(
Self::get_reg_class(reg_id),
ArmRegClass::FPR128
| ArmRegClass::FPR64
| ArmRegClass::FPR32
| ArmRegClass::FPR16
| ArmRegClass::FPR8
| ArmRegClass::SPR
)
}
pub fn is_aarch64_reg(reg_id: u16) -> bool {
matches!(
reg_id,
X0..=X30
| SP
| XZR
| PC_AARCH64
| W0..=W30
| WSP
| WZR
| V0..=V31
| Q0..=Q31
| D0..=D31
| S0..=S31
| H0..=H31
| B0..=B31
| NZCV
)
}
pub fn is_arm32_reg(reg_id: u16) -> bool {
matches!(
reg_id,
R0..=R15 | CPSR | D0_ARM32..=D31_ARM32 | S0_ARM32..=S31_ARM32
)
}
pub fn get_v_reg_index(reg_id: u16) -> Option<u16> {
match reg_id {
V0..=V31 => Some(reg_id - V0),
Q0..=Q31 => Some(reg_id - Q0),
D0..=D31 => Some(reg_id - D0),
S0..=S31 => Some(reg_id - S0),
H0..=H31 => Some(reg_id - H0),
B0..=B31 => Some(reg_id - B0),
_ => None,
}
}
pub fn describe(reg_id: u16) -> String {
format!(
"{} (id={}, class={:?}, width={})",
Self::get_asm_name(reg_id),
reg_id,
Self::get_reg_class(reg_id),
Self::get_reg_width(reg_id)
)
}
}
#[rustfmt::skip]
static X64_NAMES: [&str; 31] = [
"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",
];
#[rustfmt::skip]
static W32_NAMES: [&str; 31] = [
"w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7",
"w8", "w9", "w10", "w11", "w12", "w13", "w14", "w15",
"w16", "w17", "w18", "w19", "w20", "w21", "w22", "w23",
"w24", "w25", "w26", "w27", "w28", "w29", "w30",
];
#[rustfmt::skip]
static ARM32_NAMES: [&str; 16] = [
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
"r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc",
];
#[rustfmt::skip]
static V128_NAMES: [&str; 32] = [
"v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
"v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
"v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
"v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
];
#[rustfmt::skip]
static Q128_NAMES: [&str; 32] = [
"q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7",
"q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15",
"q16", "q17", "q18", "q19", "q20", "q21", "q22", "q23",
"q24", "q25", "q26", "q27", "q28", "q29", "q30", "q31",
];
#[rustfmt::skip]
static D64_NAMES: [&str; 32] = [
"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
"d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15",
"d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
"d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
];
#[rustfmt::skip]
static S32_NAMES: [&str; 32] = [
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
"s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15",
"s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23",
"s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
];
#[rustfmt::skip]
static H16_NAMES: [&str; 32] = [
"h0", "h1", "h2", "h3", "h4", "h5", "h6", "h7",
"h8", "h9", "h10", "h11", "h12", "h13", "h14", "h15",
"h16", "h17", "h18", "h19", "h20", "h21", "h22", "h23",
"h24", "h25", "h26", "h27", "h28", "h29", "h30", "h31",
];
#[rustfmt::skip]
static B8_NAMES: [&str; 32] = [
"b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7",
"b8", "b9", "b10", "b11", "b12", "b13", "b14", "b15",
"b16", "b17", "b18", "b19", "b20", "b21", "b22", "b23",
"b24", "b25", "b26", "b27", "b28", "b29", "b30", "b31",
];
pub fn canonical_reg(reg_id: u16) -> u16 {
if ArmRegisterInfo::is_fpr(reg_id) {
if let Some(idx) = ArmRegisterInfo::get_v_reg_index(reg_id) {
return V0 + idx;
}
}
reg_id
}
pub fn same_physical_reg(a: u16, b: u16) -> bool {
if a == b {
return true;
}
let va = ArmRegisterInfo::get_v_reg_index(a);
let vb = ArmRegisterInfo::get_v_reg_index(b);
if let (Some(ia), Some(ib)) = (va, vb) {
return ia == ib;
}
if ArmRegisterInfo::get_super_reg_64(a) == ArmRegisterInfo::get_super_reg_64(b) {
return true;
}
false
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_x0_register_id() {
assert_eq!(X0, 2000);
assert_eq!(X30, 2030);
}
#[test]
fn test_w0_register_id() {
assert_eq!(W0, 2040);
assert_eq!(W30, 2070);
}
#[test]
fn test_r0_register_id() {
assert_eq!(R0, 2100);
assert_eq!(R15, 2115);
}
#[test]
fn test_v0_register_id() {
assert_eq!(V0, 2200);
assert_eq!(V31, 2231);
}
#[test]
fn test_sp_aliases() {
assert_eq!(SP, 2031);
assert_eq!(SP_ARM32, 2113);
assert_eq!(SP_ARM32, R13);
}
#[test]
fn test_lr_aliases() {
assert_eq!(LR, X30);
assert_eq!(LR_ARM32, R14);
}
#[test]
fn test_fp_alias() {
assert_eq!(FP, X29);
}
#[test]
fn test_get_asm_name_x_regs() {
assert_eq!(ArmRegisterInfo::get_asm_name(X0), "x0");
assert_eq!(ArmRegisterInfo::get_asm_name(X10), "x10");
assert_eq!(ArmRegisterInfo::get_asm_name(X29), "x29");
assert_eq!(ArmRegisterInfo::get_asm_name(X30), "x30");
}
#[test]
fn test_get_asm_name_w_regs() {
assert_eq!(ArmRegisterInfo::get_asm_name(W0), "w0");
assert_eq!(ArmRegisterInfo::get_asm_name(W15), "w15");
assert_eq!(ArmRegisterInfo::get_asm_name(W30), "w30");
}
#[test]
fn test_get_asm_name_special() {
assert_eq!(ArmRegisterInfo::get_asm_name(SP), "sp");
assert_eq!(ArmRegisterInfo::get_asm_name(XZR), "xzr");
assert_eq!(ArmRegisterInfo::get_asm_name(WSP), "wsp");
assert_eq!(ArmRegisterInfo::get_asm_name(WZR), "wzr");
}
#[test]
fn test_get_asm_name_arm32() {
assert_eq!(ArmRegisterInfo::get_asm_name(R0), "r0");
assert_eq!(ArmRegisterInfo::get_asm_name(R13), "sp");
assert_eq!(ArmRegisterInfo::get_asm_name(R14), "lr");
assert_eq!(ArmRegisterInfo::get_asm_name(R15), "pc");
}
#[test]
fn test_get_asm_name_simd() {
assert_eq!(ArmRegisterInfo::get_asm_name(V0), "v0");
assert_eq!(ArmRegisterInfo::get_asm_name(V31), "v31");
assert_eq!(ArmRegisterInfo::get_asm_name(Q0), "q0");
assert_eq!(ArmRegisterInfo::get_asm_name(D0), "d0");
assert_eq!(ArmRegisterInfo::get_asm_name(S0), "s0");
assert_eq!(ArmRegisterInfo::get_asm_name(H0), "h0");
assert_eq!(ArmRegisterInfo::get_asm_name(B0), "b0");
}
#[test]
fn test_get_reg_class_gpr64() {
assert_eq!(ArmRegisterInfo::get_reg_class(X0), ArmRegClass::GPR64);
assert_eq!(ArmRegisterInfo::get_reg_class(X30), ArmRegClass::GPR64);
assert_eq!(ArmRegisterInfo::get_reg_class(SP), ArmRegClass::GPR64);
assert_eq!(ArmRegisterInfo::get_reg_class(XZR), ArmRegClass::GPR64);
}
#[test]
fn test_get_reg_class_gpr32() {
assert_eq!(ArmRegisterInfo::get_reg_class(W0), ArmRegClass::GPR32);
assert_eq!(ArmRegisterInfo::get_reg_class(WSP), ArmRegClass::GPR32);
}
#[test]
fn test_get_reg_class_simd() {
assert_eq!(ArmRegisterInfo::get_reg_class(V0), ArmRegClass::FPR128);
assert_eq!(ArmRegisterInfo::get_reg_class(D0), ArmRegClass::FPR64);
assert_eq!(ArmRegisterInfo::get_reg_class(S0), ArmRegClass::FPR32);
assert_eq!(ArmRegisterInfo::get_reg_class(H0), ArmRegClass::FPR16);
assert_eq!(ArmRegisterInfo::get_reg_class(B0), ArmRegClass::FPR8);
}
#[test]
fn test_get_reg_width() {
assert_eq!(ArmRegisterInfo::get_reg_width(X0), 64);
assert_eq!(ArmRegisterInfo::get_reg_width(W0), 32);
assert_eq!(ArmRegisterInfo::get_reg_width(V0), 128);
assert_eq!(ArmRegisterInfo::get_reg_width(D0), 64);
assert_eq!(ArmRegisterInfo::get_reg_width(S0), 32);
assert_eq!(ArmRegisterInfo::get_reg_width(H0), 16);
assert_eq!(ArmRegisterInfo::get_reg_width(B0), 8);
assert_eq!(ArmRegisterInfo::get_reg_width(R0), 32);
}
#[test]
fn test_get_dwarf_num() {
assert_eq!(ArmRegisterInfo::get_dwarf_num(X0), 0);
assert_eq!(ArmRegisterInfo::get_dwarf_num(X30), 30);
assert_eq!(ArmRegisterInfo::get_dwarf_num(SP), 31);
assert_eq!(ArmRegisterInfo::get_dwarf_num(PC_AARCH64), 32);
assert_eq!(ArmRegisterInfo::get_dwarf_num(V0), 64);
assert_eq!(ArmRegisterInfo::get_dwarf_num(V31), 95);
assert_eq!(ArmRegisterInfo::get_dwarf_num(XZR), -1);
}
#[test]
fn test_is_callee_saved_aapcs64() {
assert!(!ArmRegisterInfo::is_callee_saved(X0, true));
assert!(!ArmRegisterInfo::is_callee_saved(X1, true));
assert!(!ArmRegisterInfo::is_callee_saved(X7, true));
assert!(!ArmRegisterInfo::is_callee_saved(X18, true));
assert!(ArmRegisterInfo::is_callee_saved(X19, true));
assert!(ArmRegisterInfo::is_callee_saved(X28, true));
assert!(ArmRegisterInfo::is_callee_saved(X29, true)); assert!(ArmRegisterInfo::is_callee_saved(X30, true)); assert!(ArmRegisterInfo::is_callee_saved(V8, true));
assert!(ArmRegisterInfo::is_callee_saved(D15, true));
assert!(!ArmRegisterInfo::is_callee_saved(V0, true));
}
#[test]
fn test_is_callee_saved_aapcs() {
assert!(!ArmRegisterInfo::is_callee_saved(R0, false));
assert!(!ArmRegisterInfo::is_callee_saved(R1, false));
assert!(!ArmRegisterInfo::is_callee_saved(R3, false));
assert!(!ArmRegisterInfo::is_callee_saved(R12, false));
assert!(ArmRegisterInfo::is_callee_saved(R4, false));
assert!(ArmRegisterInfo::is_callee_saved(R11, false));
assert!(ArmRegisterInfo::is_callee_saved(R13, false)); }
#[test]
fn test_is_reserved() {
assert!(ArmRegisterInfo::is_reserved(SP));
assert!(ArmRegisterInfo::is_reserved(XZR));
assert!(ArmRegisterInfo::is_reserved(WSP));
assert!(ArmRegisterInfo::is_reserved(WZR));
assert!(ArmRegisterInfo::is_reserved(PC_AARCH64));
assert!(!ArmRegisterInfo::is_reserved(X0));
assert!(!ArmRegisterInfo::is_reserved(X10));
}
#[test]
fn test_get_sub_reg_32() {
assert_eq!(ArmRegisterInfo::get_sub_reg_32(X0), W0);
assert_eq!(ArmRegisterInfo::get_sub_reg_32(X10), W10);
assert_eq!(ArmRegisterInfo::get_sub_reg_32(X30), W30);
assert_eq!(ArmRegisterInfo::get_sub_reg_32(SP), WSP);
assert_eq!(ArmRegisterInfo::get_sub_reg_32(XZR), WZR);
assert_eq!(ArmRegisterInfo::get_sub_reg_32(V0), V0);
}
#[test]
fn test_get_super_reg_64() {
assert_eq!(ArmRegisterInfo::get_super_reg_64(W0), X0);
assert_eq!(ArmRegisterInfo::get_super_reg_64(W10), X10);
assert_eq!(ArmRegisterInfo::get_super_reg_64(W30), X30);
assert_eq!(ArmRegisterInfo::get_super_reg_64(WSP), SP);
assert_eq!(ArmRegisterInfo::get_super_reg_64(WZR), XZR);
}
#[test]
fn test_change_width_gpr() {
assert_eq!(ArmRegisterInfo::change_width(X0, 32), W0);
assert_eq!(ArmRegisterInfo::change_width(W5, 64), X5);
assert_eq!(ArmRegisterInfo::change_width(X10, 64), X10); }
#[test]
fn test_change_width_simd() {
assert_eq!(ArmRegisterInfo::change_width(V0, 64), D0);
assert_eq!(ArmRegisterInfo::change_width(D3, 128), V3);
assert_eq!(ArmRegisterInfo::change_width(S5, 128), V5);
assert_eq!(ArmRegisterInfo::change_width(H7, 64), D7);
assert_eq!(ArmRegisterInfo::change_width(B10, 32), S10);
assert_eq!(ArmRegisterInfo::change_width(V15, 16), H15);
assert_eq!(ArmRegisterInfo::change_width(D20, 8), B20);
}
#[test]
fn test_allocatable_gprs_aarch64_count() {
let regs = ArmRegisterInfo::get_allocatable_gprs_aarch64();
assert_eq!(regs.len(), 29); assert!(!regs.contains(&SP));
assert!(!regs.contains(&XZR));
}
#[test]
fn test_allocatable_gprs_arm32_count() {
let regs = ArmRegisterInfo::get_allocatable_gprs_arm32();
assert_eq!(regs.len(), 13); }
#[test]
fn test_allocatable_fprs_count() {
let regs = ArmRegisterInfo::get_allocatable_fprs();
assert_eq!(regs.len(), 32);
}
#[test]
fn test_caller_saved_aapcs64() {
let regs = ArmRegisterInfo::get_caller_saved_aapcs64();
assert!(regs.contains(&X0));
assert!(regs.contains(&X18));
assert!(regs.contains(&V0));
assert!(!regs.contains(&X19)); }
#[test]
fn test_callee_saved_aapcs64() {
let regs = ArmRegisterInfo::get_callee_saved_aapcs64();
assert!(regs.contains(&X19));
assert!(regs.contains(&X28));
assert!(regs.contains(&X29)); assert!(regs.contains(&X30)); assert!(regs.contains(&V8));
}
}