use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct X86Reg(pub u16);
impl X86Reg {
pub const fn new(id: u16) -> Self {
X86Reg(id)
}
pub fn is_valid(&self) -> bool {
self.0 < TOTAL_REG_COUNT
}
pub fn as_index(&self) -> usize {
self.0 as usize
}
}
pub const TOTAL_REG_COUNT: u16 = 256;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum RegClass {
GPR8, GPR16, GPR32, GPR64, X87, MMX, XMM, YMM, ZMM, SEGMENT, CONTROL, DEBUG, BND, KMASK, FLAGS, IP, }
impl fmt::Display for RegClass {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
RegClass::GPR8 => write!(f, "GPR8"),
RegClass::GPR16 => write!(f, "GPR16"),
RegClass::GPR32 => write!(f, "GPR32"),
RegClass::GPR64 => write!(f, "GPR64"),
RegClass::X87 => write!(f, "X87"),
RegClass::MMX => write!(f, "MMX"),
RegClass::XMM => write!(f, "XMM"),
RegClass::YMM => write!(f, "YMM"),
RegClass::ZMM => write!(f, "ZMM"),
RegClass::SEGMENT => write!(f, "SEG"),
RegClass::CONTROL => write!(f, "CR"),
RegClass::DEBUG => write!(f, "DR"),
RegClass::BND => write!(f, "BND"),
RegClass::KMASK => write!(f, "K"),
RegClass::FLAGS => write!(f, "FLAGS"),
RegClass::IP => write!(f, "IP"),
}
}
}
#[derive(Debug, Clone)]
pub struct X86RegDesc {
pub id: u16,
pub asm_name: &'static str,
pub intel_name: &'static str,
pub dwarf_num: i16,
pub class: RegClass,
pub bit_width: u16,
pub cost: u16,
pub is_allocatable: bool,
pub aliases: &'static [u16],
pub sub_regs: &'static [u16],
pub super_regs: &'static [u16],
pub is_callee_saved_sysv: bool,
pub is_callee_saved_win64: bool,
pub is_reserved: bool,
}
pub const RAX: u16 = 0;
pub const RCX: u16 = 1;
pub const RDX: u16 = 2;
pub const RBX: u16 = 3;
pub const RSP: u16 = 4;
pub const RBP: u16 = 5;
pub const RSI: u16 = 6;
pub const RDI: u16 = 7;
pub const R8: u16 = 8;
pub const R9: u16 = 9;
pub const R10: u16 = 10;
pub const R11: u16 = 11;
pub const R12: u16 = 12;
pub const R13: u16 = 13;
pub const R14: u16 = 14;
pub const R15: u16 = 15;
pub const EAX: u16 = 16;
pub const ECX: u16 = 17;
pub const EDX: u16 = 18;
pub const EBX: u16 = 19;
pub const ESP: u16 = 20;
pub const EBP: u16 = 21;
pub const ESI: u16 = 22;
pub const EDI: u16 = 23;
pub const R8D: u16 = 24;
pub const R9D: u16 = 25;
pub const R10D: u16 = 26;
pub const R11D: u16 = 27;
pub const R12D: u16 = 28;
pub const R13D: u16 = 29;
pub const R14D: u16 = 30;
pub const R15D: u16 = 31;
pub const AX: u16 = 32;
pub const CX: u16 = 33;
pub const DX: u16 = 34;
pub const BX: u16 = 35;
pub const SP: u16 = 36;
pub const BP: u16 = 37;
pub const SI: u16 = 38;
pub const DI: u16 = 39;
pub const R8W: u16 = 40;
pub const R9W: u16 = 41;
pub const R10W: u16 = 42;
pub const R11W: u16 = 43;
pub const R12W: u16 = 44;
pub const R13W: u16 = 45;
pub const R14W: u16 = 46;
pub const R15W: u16 = 47;
pub const AL: u16 = 48;
pub const CL: u16 = 49;
pub const DL: u16 = 50;
pub const BL: u16 = 51;
pub const SPL: u16 = 52; pub const BPL: u16 = 53; pub const SIL: u16 = 54; pub const DIL: u16 = 55; pub const R8B: u16 = 56;
pub const R9B: u16 = 57;
pub const R10B: u16 = 58;
pub const R11B: u16 = 59;
pub const R12B: u16 = 60;
pub const R13B: u16 = 61;
pub const R14B: u16 = 62;
pub const R15B: u16 = 63;
pub const AH: u16 = 64;
pub const CH: u16 = 65;
pub const DH: u16 = 66;
pub const BH: u16 = 67;
pub const CS: u16 = 68;
pub const DS: u16 = 69;
pub const SS: u16 = 70;
pub const ES: u16 = 71;
pub const FS: u16 = 72;
pub const GS: u16 = 73;
pub const ST0: u16 = 74;
pub const ST1: u16 = 75;
pub const ST2: u16 = 76;
pub const ST3: u16 = 77;
pub const ST4: u16 = 78;
pub const ST5: u16 = 79;
pub const ST6: u16 = 80;
pub const ST7: u16 = 81;
pub const FPR0: u16 = 82;
pub const FPR1: u16 = 83;
pub const FPR2: u16 = 84;
pub const FPR3: u16 = 85;
pub const FPR4: u16 = 86;
pub const FPR5: u16 = 87;
pub const FPR6: u16 = 88;
pub const FPR7: u16 = 89;
pub const MM0: u16 = 90;
pub const MM1: u16 = 91;
pub const MM2: u16 = 92;
pub const MM3: u16 = 93;
pub const MM4: u16 = 94;
pub const MM5: u16 = 95;
pub const MM6: u16 = 96;
pub const MM7: u16 = 97;
pub const XMM0: u16 = 98;
pub const XMM1: u16 = 99;
pub const XMM2: u16 = 100;
pub const XMM3: u16 = 101;
pub const XMM4: u16 = 102;
pub const XMM5: u16 = 103;
pub const XMM6: u16 = 104;
pub const XMM7: u16 = 105;
pub const XMM8: u16 = 106;
pub const XMM9: u16 = 107;
pub const XMM10: u16 = 108;
pub const XMM11: u16 = 109;
pub const XMM12: u16 = 110;
pub const XMM13: u16 = 111;
pub const XMM14: u16 = 112;
pub const XMM15: u16 = 113;
pub const XMM16: u16 = 114;
pub const XMM17: u16 = 115;
pub const XMM18: u16 = 116;
pub const XMM19: u16 = 117;
pub const XMM20: u16 = 118;
pub const XMM21: u16 = 119;
pub const XMM22: u16 = 120;
pub const XMM23: u16 = 121;
pub const XMM24: u16 = 122;
pub const XMM25: u16 = 123;
pub const XMM26: u16 = 124;
pub const XMM27: u16 = 125;
pub const XMM28: u16 = 126;
pub const XMM29: u16 = 127;
pub const XMM30: u16 = 128;
pub const XMM31: u16 = 129;
pub const YMM0: u16 = 130;
pub const YMM1: u16 = 131;
pub const YMM2: u16 = 132;
pub const YMM3: u16 = 133;
pub const YMM4: u16 = 134;
pub const YMM5: u16 = 135;
pub const YMM6: u16 = 136;
pub const YMM7: u16 = 137;
pub const YMM8: u16 = 138;
pub const YMM9: u16 = 139;
pub const YMM10: u16 = 140;
pub const YMM11: u16 = 141;
pub const YMM12: u16 = 142;
pub const YMM13: u16 = 143;
pub const YMM14: u16 = 144;
pub const YMM15: u16 = 145;
pub const YMM16: u16 = 146;
pub const YMM17: u16 = 147;
pub const YMM18: u16 = 148;
pub const YMM19: u16 = 149;
pub const YMM20: u16 = 150;
pub const YMM21: u16 = 151;
pub const YMM22: u16 = 152;
pub const YMM23: u16 = 153;
pub const YMM24: u16 = 154;
pub const YMM25: u16 = 155;
pub const YMM26: u16 = 156;
pub const YMM27: u16 = 157;
pub const YMM28: u16 = 158;
pub const YMM29: u16 = 159;
pub const YMM30: u16 = 160;
pub const YMM31: u16 = 161;
pub const ZMM0: u16 = 162;
pub const ZMM1: u16 = 163;
pub const ZMM2: u16 = 164;
pub const ZMM3: u16 = 165;
pub const ZMM4: u16 = 166;
pub const ZMM5: u16 = 167;
pub const ZMM6: u16 = 168;
pub const ZMM7: u16 = 169;
pub const ZMM8: u16 = 170;
pub const ZMM9: u16 = 171;
pub const ZMM10: u16 = 172;
pub const ZMM11: u16 = 173;
pub const ZMM12: u16 = 174;
pub const ZMM13: u16 = 175;
pub const ZMM14: u16 = 176;
pub const ZMM15: u16 = 177;
pub const ZMM16: u16 = 178;
pub const ZMM17: u16 = 179;
pub const ZMM18: u16 = 180;
pub const ZMM19: u16 = 181;
pub const ZMM20: u16 = 182;
pub const ZMM21: u16 = 183;
pub const ZMM22: u16 = 184;
pub const ZMM23: u16 = 185;
pub const ZMM24: u16 = 186;
pub const ZMM25: u16 = 187;
pub const ZMM26: u16 = 188;
pub const ZMM27: u16 = 189;
pub const ZMM28: u16 = 190;
pub const ZMM29: u16 = 191;
pub const ZMM30: u16 = 192;
pub const ZMM31: u16 = 193;
pub const CR0: u16 = 194;
pub const CR1: u16 = 195;
pub const CR2: u16 = 196;
pub const CR3: u16 = 197;
pub const CR4: u16 = 198;
pub const CR5: u16 = 199; pub const CR6: u16 = 200; pub const CR7: u16 = 201; pub const CR8: u16 = 202;
pub const DR0: u16 = 203;
pub const DR1: u16 = 204;
pub const DR2: u16 = 205;
pub const DR3: u16 = 206;
pub const DR4: u16 = 207; pub const DR5: u16 = 208; pub const DR6: u16 = 209; pub const DR7: u16 = 210;
pub const BND0: u16 = 211;
pub const BND1: u16 = 212;
pub const BND2: u16 = 213;
pub const BND3: u16 = 214;
pub const K0: u16 = 215;
pub const K1: u16 = 216;
pub const K2: u16 = 217;
pub const K3: u16 = 218;
pub const K4: u16 = 219;
pub const K5: u16 = 220;
pub const K6: u16 = 221;
pub const K7: u16 = 222;
pub const RFLAGS: u16 = 223;
pub const EFLAGS: u16 = 223; pub const RIP: u16 = 224;
pub const EIP: u16 = 224;
pub const X86_64_REG_COUNT: usize = 225;
pub const X86_32_REG_COUNT: usize = 208;
pub fn get_super_reg_64(reg: u16) -> u16 {
match reg {
EAX | AX | AL | AH => RAX,
ECX | CX | CL | CH => RCX,
EDX | DX | DL | DH => RDX,
EBX | BX | BL | BH => RBX,
ESP | SP | SPL => RSP,
EBP | BP | BPL => RBP,
ESI | SI | SIL => RSI,
EDI | DI | DIL => RDI,
R8D | R8W | R8B => R8,
R9D | R9W | R9B => R9,
R10D | R10W | R10B => R10,
R11D | R11W | R11B => R11,
R12D | R12W | R12B => R12,
R13D | R13W | R13B => R13,
R14D | R14W | R14B => R14,
R15D | R15W | R15B => R15,
_ => reg, }
}
pub fn get_sub_reg_32(reg: u16) -> u16 {
match reg {
RAX => EAX,
RCX => ECX,
RDX => EDX,
RBX => EBX,
RSP => ESP,
RBP => EBP,
RSI => ESI,
RDI => EDI,
R8 => R8D,
R9 => R9D,
R10 => R10D,
R11 => R11D,
R12 => R12D,
R13 => R13D,
R14 => R14D,
R15 => R15D,
_ => reg,
}
}
pub fn get_sub_reg_16(reg: u16) -> u16 {
match reg {
RAX | EAX => AX,
RCX | ECX => CX,
RDX | EDX => DX,
RBX | EBX => BX,
RSP | ESP => SP,
RBP | EBP => BP,
RSI | ESI => SI,
RDI | EDI => DI,
R8 | R8D => R8W,
R9 | R9D => R9W,
R10 | R10D => R10W,
R11 | R11D => R11W,
R12 | R12D => R12W,
R13 | R13D => R13W,
R14 | R14D => R14W,
R15 | R15D => R15W,
_ => reg,
}
}
pub fn get_sub_reg_8(reg: u16) -> u16 {
match reg {
RAX | EAX | AX => AL,
RCX | ECX | CX => CL,
RDX | EDX | DX => DL,
RBX | EBX | BX => BL,
RSP | ESP | SP => SPL,
RBP | EBP | BP => BPL,
RSI | ESI | SI => SIL,
RDI | EDI | DI => DIL,
R8 | R8D | R8W => R8B,
R9 | R9D | R9W => R9B,
R10 | R10D | R10W => R10B,
R11 | R11D | R11W => R11B,
R12 | R12D | R12W => R12B,
R13 | R13D | R13W => R13B,
R14 | R14D | R14W => R14B,
R15 | R15D | R15W => R15B,
_ => reg,
}
}
pub fn get_super_ymm(reg: u16) -> u16 {
match reg {
XMM0 => YMM0,
XMM1 => YMM1,
XMM2 => YMM2,
XMM3 => YMM3,
XMM4 => YMM4,
XMM5 => YMM5,
XMM6 => YMM6,
XMM7 => YMM7,
XMM8 => YMM8,
XMM9 => YMM9,
XMM10 => YMM10,
XMM11 => YMM11,
XMM12 => YMM12,
XMM13 => YMM13,
XMM14 => YMM14,
XMM15 => YMM15,
XMM16 => YMM16,
XMM17 => YMM17,
XMM18 => YMM18,
XMM19 => YMM19,
XMM20 => YMM20,
XMM21 => YMM21,
XMM22 => YMM22,
XMM23 => YMM23,
XMM24 => YMM24,
XMM25 => YMM25,
XMM26 => YMM26,
XMM27 => YMM27,
XMM28 => YMM28,
XMM29 => YMM29,
XMM30 => YMM30,
XMM31 => YMM31,
_ => reg,
}
}
pub fn get_super_zmm(reg: u16) -> u16 {
match reg {
XMM0 | YMM0 => ZMM0,
XMM1 | YMM1 => ZMM1,
XMM2 | YMM2 => ZMM2,
XMM3 | YMM3 => ZMM3,
XMM4 | YMM4 => ZMM4,
XMM5 | YMM5 => ZMM5,
XMM6 | YMM6 => ZMM6,
XMM7 | YMM7 => ZMM7,
XMM8 | YMM8 => ZMM8,
XMM9 | YMM9 => ZMM9,
XMM10 | YMM10 => ZMM10,
XMM11 | YMM11 => ZMM11,
XMM12 | YMM12 => ZMM12,
XMM13 | YMM13 => ZMM13,
XMM14 | YMM14 => ZMM14,
XMM15 | YMM15 => ZMM15,
XMM16 | YMM16 => ZMM16,
XMM17 | YMM17 => ZMM17,
XMM18 | YMM18 => ZMM18,
XMM19 | YMM19 => ZMM19,
XMM20 | YMM20 => ZMM20,
XMM21 | YMM21 => ZMM21,
XMM22 | YMM22 => ZMM22,
XMM23 | YMM23 => ZMM23,
XMM24 | YMM24 => ZMM24,
XMM25 | YMM25 => ZMM25,
XMM26 | YMM26 => ZMM26,
XMM27 | YMM27 => ZMM27,
XMM28 | YMM28 => ZMM28,
XMM29 | YMM29 => ZMM29,
XMM30 | YMM30 => ZMM30,
XMM31 | YMM31 => ZMM31,
_ => reg,
}
}
#[derive(Debug, Clone)]
pub struct X86RegisterInfo;
impl X86RegisterInfo {
pub fn get_asm_name(reg_id: u16) -> &'static str {
match reg_id {
RAX => "%rax",
RCX => "%rcx",
RDX => "%rdx",
RBX => "%rbx",
RSP => "%rsp",
RBP => "%rbp",
RSI => "%rsi",
RDI => "%rdi",
R8 => "%r8",
R9 => "%r9",
R10 => "%r10",
R11 => "%r11",
R12 => "%r12",
R13 => "%r13",
R14 => "%r14",
R15 => "%r15",
EAX => "%eax",
ECX => "%ecx",
EDX => "%edx",
EBX => "%ebx",
ESP => "%esp",
EBP => "%ebp",
ESI => "%esi",
EDI => "%edi",
R8D => "%r8d",
R9D => "%r9d",
R10D => "%r10d",
R11D => "%r11d",
R12D => "%r12d",
R13D => "%r13d",
R14D => "%r14d",
R15D => "%r15d",
AX => "%ax",
CX => "%cx",
DX => "%dx",
BX => "%bx",
SP => "%sp",
BP => "%bp",
SI => "%si",
DI => "%di",
R8W => "%r8w",
R9W => "%r9w",
R10W => "%r10w",
R11W => "%r11w",
R12W => "%r12w",
R13W => "%r13w",
R14W => "%r14w",
R15W => "%r15w",
AL => "%al",
CL => "%cl",
DL => "%dl",
BL => "%bl",
SPL => "%spl",
BPL => "%bpl",
SIL => "%sil",
DIL => "%dil",
R8B => "%r8b",
R9B => "%r9b",
R10B => "%r10b",
R11B => "%r11b",
R12B => "%r12b",
R13B => "%r13b",
R14B => "%r14b",
R15B => "%r15b",
AH => "%ah",
CH => "%ch",
DH => "%dh",
BH => "%bh",
CS => "%cs",
DS => "%ds",
SS => "%ss",
ES => "%es",
FS => "%fs",
GS => "%gs",
ST0 => "%st(0)",
ST1 => "%st(1)",
ST2 => "%st(2)",
ST3 => "%st(3)",
ST4 => "%st(4)",
ST5 => "%st(5)",
ST6 => "%st(6)",
ST7 => "%st(7)",
MM0 => "%mm0",
MM1 => "%mm1",
MM2 => "%mm2",
MM3 => "%mm3",
MM4 => "%mm4",
MM5 => "%mm5",
MM6 => "%mm6",
MM7 => "%mm7",
XMM0 => "%xmm0",
XMM1 => "%xmm1",
XMM2 => "%xmm2",
XMM3 => "%xmm3",
XMM4 => "%xmm4",
XMM5 => "%xmm5",
XMM6 => "%xmm6",
XMM7 => "%xmm7",
XMM8 => "%xmm8",
XMM9 => "%xmm9",
XMM10 => "%xmm10",
XMM11 => "%xmm11",
XMM12 => "%xmm12",
XMM13 => "%xmm13",
XMM14 => "%xmm14",
XMM15 => "%xmm15",
XMM16 => "%xmm16",
XMM17 => "%xmm17",
XMM18 => "%xmm18",
XMM19 => "%xmm19",
XMM20 => "%xmm20",
XMM21 => "%xmm21",
XMM22 => "%xmm22",
XMM23 => "%xmm23",
XMM24 => "%xmm24",
XMM25 => "%xmm25",
XMM26 => "%xmm26",
XMM27 => "%xmm27",
XMM28 => "%xmm28",
XMM29 => "%xmm29",
XMM30 => "%xmm30",
XMM31 => "%xmm31",
YMM0 => "%ymm0",
YMM1 => "%ymm1",
YMM2 => "%ymm2",
YMM3 => "%ymm3",
YMM4 => "%ymm4",
YMM5 => "%ymm5",
YMM6 => "%ymm6",
YMM7 => "%ymm7",
YMM8 => "%ymm8",
YMM9 => "%ymm9",
YMM10 => "%ymm10",
YMM11 => "%ymm11",
YMM12 => "%ymm12",
YMM13 => "%ymm13",
YMM14 => "%ymm14",
YMM15 => "%ymm15",
YMM16 => "%ymm16",
YMM17 => "%ymm17",
YMM18 => "%ymm18",
YMM19 => "%ymm19",
YMM20 => "%ymm20",
YMM21 => "%ymm21",
YMM22 => "%ymm22",
YMM23 => "%ymm23",
YMM24 => "%ymm24",
YMM25 => "%ymm25",
YMM26 => "%ymm26",
YMM27 => "%ymm27",
YMM28 => "%ymm28",
YMM29 => "%ymm29",
YMM30 => "%ymm30",
YMM31 => "%ymm31",
ZMM0 => "%zmm0",
ZMM1 => "%zmm1",
ZMM2 => "%zmm2",
ZMM3 => "%zmm3",
ZMM4 => "%zmm4",
ZMM5 => "%zmm5",
ZMM6 => "%zmm6",
ZMM7 => "%zmm7",
ZMM8 => "%zmm8",
ZMM9 => "%zmm9",
ZMM10 => "%zmm10",
ZMM11 => "%zmm11",
ZMM12 => "%zmm12",
ZMM13 => "%zmm13",
ZMM14 => "%zmm14",
ZMM15 => "%zmm15",
ZMM16 => "%zmm16",
ZMM17 => "%zmm17",
ZMM18 => "%zmm18",
ZMM19 => "%zmm19",
ZMM20 => "%zmm20",
ZMM21 => "%zmm21",
ZMM22 => "%zmm22",
ZMM23 => "%zmm23",
ZMM24 => "%zmm24",
ZMM25 => "%zmm25",
ZMM26 => "%zmm26",
ZMM27 => "%zmm27",
ZMM28 => "%zmm28",
ZMM29 => "%zmm29",
ZMM30 => "%zmm30",
ZMM31 => "%zmm31",
CR0 => "%cr0",
CR1 => "%cr1",
CR2 => "%cr2",
CR3 => "%cr3",
CR4 => "%cr4",
CR8 => "%cr8",
DR0 => "%dr0",
DR1 => "%dr1",
DR2 => "%dr2",
DR3 => "%dr3",
DR6 => "%dr6",
DR7 => "%dr7",
BND0 => "%bnd0",
BND1 => "%bnd1",
BND2 => "%bnd2",
BND3 => "%bnd3",
K0 => "%k0",
K1 => "%k1",
K2 => "%k2",
K3 => "%k3",
K4 => "%k4",
K5 => "%k5",
K6 => "%k6",
K7 => "%k7",
RFLAGS => "%rflags",
RIP => "%rip",
_ => "%unknown",
}
}
pub fn get_intel_name(reg_id: u16) -> &'static str {
let asm = Self::get_asm_name(reg_id);
if asm.starts_with('%') {
&asm[1..]
} else {
asm
}
}
pub fn get_reg_class(reg_id: u16) -> RegClass {
match reg_id {
0..=15 => RegClass::GPR64,
16..=31 => RegClass::GPR32,
32..=47 => RegClass::GPR16,
48..=67 => RegClass::GPR8,
68..=73 => RegClass::SEGMENT,
74..=89 => RegClass::X87,
90..=97 => RegClass::MMX,
98..=129 => RegClass::XMM,
130..=161 => RegClass::YMM,
162..=193 => RegClass::ZMM,
194..=202 => RegClass::CONTROL,
203..=210 => RegClass::DEBUG,
211..=214 => RegClass::BND,
215..=222 => RegClass::KMASK,
223 => RegClass::FLAGS,
224 => RegClass::IP,
_ => RegClass::GPR64, }
}
pub fn get_reg_width(reg_id: u16) -> u16 {
match reg_id {
0..=15 => 64, 16..=31 => 32, 32..=47 => 16, 48..=67 => 8, 68..=73 => 16, 74..=89 => 80, 90..=97 => 64, 98..=129 => 128, 130..=161 => 256, 162..=193 => 512, 194..=202 => 64, 203..=210 => 64, 211..=214 => 128, 215..=222 => 64, 223 => 64, 224 => 64, _ => 0,
}
}
pub fn get_dwarf_num(reg_id: u16) -> i16 {
match reg_id {
RAX => 0,
RDX => 1,
RCX => 2,
RBX => 3,
RSI => 4,
RDI => 5,
RBP => 6,
RSP => 7,
R8 => 8,
R9 => 9,
R10 => 10,
R11 => 11,
R12 => 12,
R13 => 13,
R14 => 14,
R15 => 15,
RIP => 16,
XMM0 => 17,
XMM1 => 18,
XMM2 => 19,
XMM3 => 20,
XMM4 => 21,
XMM5 => 22,
XMM6 => 23,
XMM7 => 24,
XMM8 => 25,
XMM9 => 26,
XMM10 => 27,
XMM11 => 28,
XMM12 => 29,
XMM13 => 30,
XMM14 => 31,
XMM15 => 32,
ST0 => 33,
ST1 => 34,
ST2 => 35,
ST3 => 36,
ST4 => 37,
ST5 => 38,
ST6 => 39,
ST7 => 40,
MM0 => 41,
MM1 => 42,
MM2 => 43,
MM3 => 44,
MM4 => 45,
MM5 => 46,
MM6 => 47,
MM7 => 48,
RFLAGS => 49,
ES => 50,
CS => 51,
SS => 52,
DS => 53,
FS => 54,
GS => 55,
XMM16 => 67,
XMM17 => 68,
XMM18 => 69,
XMM19 => 70,
XMM20 => 71,
XMM21 => 72,
XMM22 => 73,
XMM23 => 74,
XMM24 => 75,
XMM25 => 76,
XMM26 => 77,
XMM27 => 78,
XMM28 => 79,
XMM29 => 80,
XMM30 => 81,
XMM31 => 82,
_ => -1,
}
}
pub fn is_callee_saved_sysv(reg_id: u16) -> bool {
matches!(reg_id, RBX | RBP | R12 | R13 | R14 | R15)
}
pub fn is_callee_saved_win64(reg_id: u16) -> bool {
matches!(
reg_id,
RBX | RBP
| RDI
| RSI
| RSP
| R12
| R13
| R14
| R15
| XMM6
| XMM7
| XMM8
| XMM9
| XMM10
| XMM11
| XMM12
| XMM13
| XMM14
| XMM15
)
}
pub fn is_reserved(reg_id: u16) -> bool {
matches!(reg_id, RSP | RBP | RIP | RFLAGS)
}
pub fn get_allocatable_gprs_64() -> Vec<u16> {
vec![
RAX, RCX, RDX, RBX, RSI, RDI, R8, R9, R10, R11, R12, R13, R14, R15,
]
}
pub fn get_allocatable_gprs_32() -> Vec<u16> {
vec![EAX, ECX, EDX, EBX, ESI, EDI]
}
pub fn get_allocatable_xmms() -> Vec<u16> {
vec![
XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, XMM8, XMM9, XMM10, XMM11, XMM12, XMM13,
XMM14, XMM15,
]
}
pub fn get_caller_saved_sysv() -> Vec<u16> {
vec![
RAX, RCX, RDX, RSI, RDI, R8, R9, R10, R11, XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6,
XMM7, XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15,
]
}
pub fn get_callee_saved_sysv() -> Vec<u16> {
vec![RBX, RBP, R12, R13, R14, R15]
}
pub fn change_width(reg_id: u16, new_width: u16) -> u16 {
let base = get_super_reg_64(reg_id);
match new_width {
8 => get_sub_reg_8(base),
16 => get_sub_reg_16(base),
32 => get_sub_reg_32(base),
64 => base,
_ => reg_id,
}
}
}
pub const GPR64_TO_GPR32: &[(u16, u16)] = &[
(RAX, EAX),
(RCX, ECX),
(RDX, EDX),
(RBX, EBX),
(RSP, ESP),
(RBP, EBP),
(RSI, ESI),
(RDI, EDI),
(R8, R8D),
(R9, R9D),
(R10, R10D),
(R11, R11D),
(R12, R12D),
(R13, R13D),
(R14, R14D),
(R15, R15D),
];
pub const GPR32_TO_GPR16: &[(u16, u16)] = &[
(EAX, AX),
(ECX, CX),
(EDX, DX),
(EBX, BX),
(ESP, SP),
(EBP, BP),
(ESI, SI),
(EDI, DI),
(R8D, R8W),
(R9D, R9W),
(R10D, R10W),
(R11D, R11W),
(R12D, R12W),
(R13D, R13W),
(R14D, R14W),
(R15D, R15W),
];
pub const GPR16_TO_GPR8L: &[(u16, u16)] = &[
(AX, AL),
(CX, CL),
(DX, DL),
(BX, BL),
(SP, SPL),
(BP, BPL),
(SI, SIL),
(DI, DIL),
(R8W, R8B),
(R9W, R9B),
(R10W, R10B),
(R11W, R11B),
(R12W, R12B),
(R13W, R13B),
(R14W, R14B),
(R15W, R15B),
];
pub const GPR16_TO_GPR8H: &[(u16, u16)] = &[(AX, AH), (CX, CH), (DX, DH), (BX, BH)];
pub const XMM_TO_YMM: &[(u16, u16)] = &[
(XMM0, YMM0),
(XMM1, YMM1),
(XMM2, YMM2),
(XMM3, YMM3),
(XMM4, YMM4),
(XMM5, YMM5),
(XMM6, YMM6),
(XMM7, YMM7),
(XMM8, YMM8),
(XMM9, YMM9),
(XMM10, YMM10),
(XMM11, YMM11),
(XMM12, YMM12),
(XMM13, YMM13),
(XMM14, YMM14),
(XMM15, YMM15),
(XMM16, YMM16),
(XMM17, YMM17),
(XMM18, YMM18),
(XMM19, YMM19),
(XMM20, YMM20),
(XMM21, YMM21),
(XMM22, YMM22),
(XMM23, YMM23),
(XMM24, YMM24),
(XMM25, YMM25),
(XMM26, YMM26),
(XMM27, YMM27),
(XMM28, YMM28),
(XMM29, YMM29),
(XMM30, YMM30),
(XMM31, YMM31),
];
pub const YMM_TO_ZMM: &[(u16, u16)] = &[
(YMM0, ZMM0),
(YMM1, ZMM1),
(YMM2, ZMM2),
(YMM3, ZMM3),
(YMM4, ZMM4),
(YMM5, ZMM5),
(YMM6, ZMM6),
(YMM7, ZMM7),
(YMM8, ZMM8),
(YMM9, ZMM9),
(YMM10, ZMM10),
(YMM11, ZMM11),
(YMM12, ZMM12),
(YMM13, ZMM13),
(YMM14, ZMM14),
(YMM15, ZMM15),
(YMM16, ZMM16),
(YMM17, ZMM17),
(YMM18, ZMM18),
(YMM19, ZMM19),
(YMM20, ZMM20),
(YMM21, ZMM21),
(YMM22, ZMM22),
(YMM23, ZMM23),
(YMM24, ZMM24),
(YMM25, ZMM25),
(YMM26, ZMM26),
(YMM27, ZMM27),
(YMM28, ZMM28),
(YMM29, ZMM29),
(YMM30, ZMM30),
(YMM31, ZMM31),
];
pub fn get_alias_set(reg: u16) -> Vec<u16> {
let mut aliases = vec![reg];
let base64 = get_super_reg_64(reg);
let sub32 = get_sub_reg_32(base64);
let sub16 = get_sub_reg_16(base64);
let sub8 = get_sub_reg_8(base64);
if sub32 != 0 && sub32 != base64 {
aliases.push(sub32);
}
if sub16 != 0 && sub16 != base64 && sub16 != sub32 {
aliases.push(sub16);
}
if sub8 != 0 && sub8 != base64 && sub8 != sub32 && sub8 != sub16 {
aliases.push(sub8);
}
match base64 {
RAX => aliases.push(AH),
RCX => aliases.push(CH),
RDX => aliases.push(DH),
RBX => aliases.push(BH),
_ => {}
}
aliases.sort();
aliases.dedup();
aliases
}
pub fn registers_alias(reg_a: u16, reg_b: u16) -> bool {
if reg_a == reg_b {
return true;
}
let base_a = get_super_reg_64(reg_a);
let base_b = get_super_reg_64(reg_b);
if base_a == base_b {
return true;
}
let aliases_a = get_alias_set(reg_a);
aliases_a.contains(®_b)
}
#[derive(Debug, Clone)]
pub struct RegClassInfo {
pub class: RegClass,
pub name: &'static str,
pub num_regs: usize,
pub bit_width: u16,
pub alignment: u16,
pub copy_cost: u32,
pub allocatable: bool,
pub base_register: u16,
pub spill_size: u16,
pub spill_alignment: u16,
}
pub const REG_CLASSES: &[RegClassInfo] = &[
RegClassInfo {
class: RegClass::GPR8,
name: "GR8",
num_regs: 16,
bit_width: 8,
alignment: 1,
copy_cost: 1,
allocatable: true,
base_register: AL,
spill_size: 4, spill_alignment: 4,
},
RegClassInfo {
class: RegClass::GPR16,
name: "GR16",
num_regs: 16,
bit_width: 16,
alignment: 2,
copy_cost: 1,
allocatable: true,
base_register: AX,
spill_size: 4, spill_alignment: 4,
},
RegClassInfo {
class: RegClass::GPR32,
name: "GR32",
num_regs: 16,
bit_width: 32,
alignment: 4,
copy_cost: 1,
allocatable: true,
base_register: EAX,
spill_size: 4,
spill_alignment: 4,
},
RegClassInfo {
class: RegClass::GPR64,
name: "GR64",
num_regs: 16,
bit_width: 64,
alignment: 8,
copy_cost: 1,
allocatable: true,
base_register: RAX,
spill_size: 8,
spill_alignment: 8,
},
RegClassInfo {
class: RegClass::X87,
name: "RFP",
num_regs: 8,
bit_width: 80,
alignment: 4,
copy_cost: 3,
allocatable: false, base_register: ST0,
spill_size: 10,
spill_alignment: 4,
},
RegClassInfo {
class: RegClass::MMX,
name: "VR64",
num_regs: 8,
bit_width: 64,
alignment: 8,
copy_cost: 2,
allocatable: true,
base_register: MM0,
spill_size: 8,
spill_alignment: 8,
},
RegClassInfo {
class: RegClass::XMM,
name: "VR128",
num_regs: 32,
bit_width: 128,
alignment: 16,
copy_cost: 2,
allocatable: true,
base_register: XMM0,
spill_size: 16,
spill_alignment: 16,
},
RegClassInfo {
class: RegClass::YMM,
name: "VR256",
num_regs: 32,
bit_width: 256,
alignment: 32,
copy_cost: 3,
allocatable: true,
base_register: YMM0,
spill_size: 32,
spill_alignment: 32,
},
RegClassInfo {
class: RegClass::ZMM,
name: "VR512",
num_regs: 32,
bit_width: 512,
alignment: 64,
copy_cost: 4,
allocatable: true,
base_register: ZMM0,
spill_size: 64,
spill_alignment: 64,
},
RegClassInfo {
class: RegClass::SEGMENT,
name: "SEG",
num_regs: 6,
bit_width: 16,
alignment: 2,
copy_cost: 2,
allocatable: false,
base_register: CS,
spill_size: 2,
spill_alignment: 2,
},
RegClassInfo {
class: RegClass::CONTROL,
name: "CR",
num_regs: 9,
bit_width: 64,
alignment: 8,
copy_cost: 10,
allocatable: false,
base_register: CR0,
spill_size: 8,
spill_alignment: 8,
},
RegClassInfo {
class: RegClass::DEBUG,
name: "DR",
num_regs: 8,
bit_width: 64,
alignment: 8,
copy_cost: 10,
allocatable: false,
base_register: DR0,
spill_size: 8,
spill_alignment: 8,
},
RegClassInfo {
class: RegClass::BND,
name: "BND",
num_regs: 4,
bit_width: 128,
alignment: 16,
copy_cost: 3,
allocatable: false,
base_register: BND0,
spill_size: 16,
spill_alignment: 16,
},
RegClassInfo {
class: RegClass::KMASK,
name: "KMASK",
num_regs: 8,
bit_width: 64,
alignment: 8,
copy_cost: 1,
allocatable: true,
base_register: K0,
spill_size: 8,
spill_alignment: 8,
},
RegClassInfo {
class: RegClass::FLAGS,
name: "FLAGS",
num_regs: 2,
bit_width: 64,
alignment: 8,
copy_cost: 2,
allocatable: false,
base_register: RFLAGS,
spill_size: 8,
spill_alignment: 8,
},
RegClassInfo {
class: RegClass::IP,
name: "IP",
num_regs: 2,
bit_width: 64,
alignment: 8,
copy_cost: 1,
allocatable: false,
base_register: RIP,
spill_size: 8,
spill_alignment: 8,
},
];
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RegisterRole {
CalleeSaved,
CallerSaved,
Reserved,
Conditional,
}
pub struct SysV64RegisterInfo;
impl SysV64RegisterInfo {
pub fn get_gpr_role(reg: u16) -> RegisterRole {
match reg {
RAX | RCX | RDX | RSI | RDI | R8 | R9 | R10 | R11 => RegisterRole::CallerSaved,
RBX | RBP | R12 | R13 | R14 | R15 => RegisterRole::CalleeSaved,
RSP => RegisterRole::Reserved,
_ => RegisterRole::CallerSaved,
}
}
pub fn get_xmm_role(_reg: u16) -> RegisterRole {
RegisterRole::CallerSaved
}
pub fn is_argument_register(reg: u16) -> bool {
matches!(reg, RDI | RSI | RDX | RCX | R8 | R9)
}
pub fn is_return_register(reg: u16) -> bool {
matches!(reg, RAX | RDX)
}
pub fn int_arg_regs() -> Vec<u16> {
vec![RDI, RSI, RDX, RCX, R8, R9]
}
pub fn xmm_arg_regs() -> Vec<u16> {
vec![XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7]
}
}
pub struct Win64RegisterInfo;
impl Win64RegisterInfo {
pub fn get_gpr_role(reg: u16) -> RegisterRole {
match reg {
RAX | RCX | RDX | R8 | R9 | R10 | R11 => RegisterRole::CallerSaved,
RBX | RBP | RDI | RSI | R12 | R13 | R14 | R15 => RegisterRole::CalleeSaved,
RSP => RegisterRole::Reserved,
_ => RegisterRole::CallerSaved,
}
}
pub fn get_xmm_role(reg: u16) -> RegisterRole {
let xmm_base = reg.saturating_sub(XMM0);
if xmm_base <= 5 {
RegisterRole::CallerSaved
} else {
RegisterRole::CalleeSaved
}
}
pub fn is_argument_register(reg: u16) -> bool {
matches!(reg, RCX | RDX | R8 | R9)
}
pub fn is_return_register(reg: u16) -> bool {
matches!(reg, RAX)
}
pub fn int_arg_regs() -> Vec<u16> {
vec![RCX, RDX, R8, R9]
}
pub fn xmm_arg_regs() -> Vec<u16> {
vec![XMM0, XMM1, XMM2, XMM3]
}
}
pub fn get_regs_in_class(class: RegClass) -> Vec<u16> {
match class {
RegClass::GPR8 => (0..16).map(|i| AL + i).collect(),
RegClass::GPR16 => (0..16).map(|i| AX + i).collect(),
RegClass::GPR32 => (0..16).map(|i| EAX + i).collect(),
RegClass::GPR64 => (0..16).map(|i| RAX + i).collect(),
RegClass::X87 => (0..8).map(|i| ST0 + i).collect(),
RegClass::MMX => (0..8).map(|i| MM0 + i).collect(),
RegClass::XMM => (0..32).map(|i| XMM0 + i).collect(),
RegClass::YMM => (0..32).map(|i| YMM0 + i).collect(),
RegClass::ZMM => (0..32).map(|i| ZMM0 + i).collect(),
RegClass::SEGMENT => vec![CS, DS, SS, ES, FS, GS],
RegClass::CONTROL => (0..9).map(|i| CR0 + i).collect(),
RegClass::DEBUG => (0..8).map(|i| DR0 + i).collect(),
RegClass::BND => (0..4).map(|i| BND0 + i).collect(),
RegClass::KMASK => (0..8).map(|i| K0 + i).collect(),
RegClass::FLAGS => vec![RFLAGS, EFLAGS],
RegClass::IP => vec![RIP, EIP],
}
}
pub fn is_reg_in_class(reg: u16, class: RegClass) -> bool {
get_regs_in_class(class).contains(®)
}
pub fn get_reg_class_for_id(reg: u16) -> Option<RegClass> {
if is_reg_in_class(reg, RegClass::GPR8) {
Some(RegClass::GPR8)
} else if is_reg_in_class(reg, RegClass::GPR16) {
Some(RegClass::GPR16)
} else if is_reg_in_class(reg, RegClass::GPR32) {
Some(RegClass::GPR32)
} else if is_reg_in_class(reg, RegClass::GPR64) {
Some(RegClass::GPR64)
} else if is_reg_in_class(reg, RegClass::XMM) {
Some(RegClass::XMM)
} else if is_reg_in_class(reg, RegClass::YMM) {
Some(RegClass::YMM)
} else if is_reg_in_class(reg, RegClass::ZMM) {
Some(RegClass::ZMM)
} else if is_reg_in_class(reg, RegClass::X87) {
Some(RegClass::X87)
} else if is_reg_in_class(reg, RegClass::MMX) {
Some(RegClass::MMX)
} else if is_reg_in_class(reg, RegClass::SEGMENT) {
Some(RegClass::SEGMENT)
} else if is_reg_in_class(reg, RegClass::CONTROL) {
Some(RegClass::CONTROL)
} else if is_reg_in_class(reg, RegClass::DEBUG) {
Some(RegClass::DEBUG)
} else if is_reg_in_class(reg, RegClass::BND) {
Some(RegClass::BND)
} else if is_reg_in_class(reg, RegClass::KMASK) {
Some(RegClass::KMASK)
} else if is_reg_in_class(reg, RegClass::FLAGS) {
Some(RegClass::FLAGS)
} else if is_reg_in_class(reg, RegClass::IP) {
Some(RegClass::IP)
} else {
None
}
}
pub fn get_reg_bit_width(reg: u16) -> u16 {
if let Some(class) = get_reg_class_for_id(reg) {
match class {
RegClass::GPR8 => 8,
RegClass::GPR16 => 16,
RegClass::GPR32 => 32,
RegClass::GPR64 => 64,
RegClass::X87 => 80,
RegClass::MMX => 64,
RegClass::XMM => 128,
RegClass::YMM => 256,
RegClass::ZMM => 512,
RegClass::SEGMENT => 16,
RegClass::CONTROL => 64,
RegClass::DEBUG => 64,
RegClass::BND => 128,
RegClass::KMASK => 64,
RegClass::FLAGS => 64,
RegClass::IP => 64,
}
} else {
0
}
}
pub fn is_reserved_register(reg: u16) -> bool {
match reg {
RSP | ESP | SP => true, _ => false,
}
}
pub fn get_reserved_regs(is_64bit: bool) -> Vec<u16> {
if is_64bit {
vec![RSP]
} else {
vec![ESP, SP]
}
}
pub fn get_thread_pointer_reg(is_windows: bool) -> u16 {
if is_windows {
GS
} else {
FS
}
}
pub fn get_frame_pointer_reg(is_64bit: bool) -> u16 {
if is_64bit {
RBP
} else {
EBP
}
}
pub fn get_stack_pointer_reg(is_64bit: bool) -> u16 {
if is_64bit {
RSP
} else {
ESP
}
}
pub const INTEL_NAMES: &[(u16, &str)] = &[
(RAX, "rax"),
(RCX, "rcx"),
(RDX, "rdx"),
(RBX, "rbx"),
(RSP, "rsp"),
(RBP, "rbp"),
(RSI, "rsi"),
(RDI, "rdi"),
(R8, "r8"),
(R9, "r9"),
(R10, "r10"),
(R11, "r11"),
(R12, "r12"),
(R13, "r13"),
(R14, "r14"),
(R15, "r15"),
(EAX, "eax"),
(ECX, "ecx"),
(EDX, "edx"),
(EBX, "ebx"),
(ESP, "esp"),
(EBP, "ebp"),
(ESI, "esi"),
(EDI, "edi"),
(AX, "ax"),
(CX, "cx"),
(DX, "dx"),
(BX, "bx"),
(AL, "al"),
(CL, "cl"),
(DL, "dl"),
(BL, "bl"),
(AH, "ah"),
(CH, "ch"),
(DH, "dh"),
(BH, "bh"),
(XMM0, "xmm0"),
(XMM1, "xmm1"),
(XMM2, "xmm2"),
(XMM3, "xmm3"),
(XMM4, "xmm4"),
(XMM5, "xmm5"),
(XMM6, "xmm6"),
(XMM7, "xmm7"),
(XMM8, "xmm8"),
(XMM9, "xmm9"),
(XMM10, "xmm10"),
(XMM11, "xmm11"),
(XMM12, "xmm12"),
(XMM13, "xmm13"),
(XMM14, "xmm14"),
(XMM15, "xmm15"),
(YMM0, "ymm0"),
(YMM1, "ymm1"),
(YMM2, "ymm2"),
(YMM3, "ymm3"),
(YMM4, "ymm4"),
(YMM5, "ymm5"),
(YMM6, "ymm6"),
(YMM7, "ymm7"),
(YMM8, "ymm8"),
(YMM9, "ymm9"),
(YMM10, "ymm10"),
(YMM11, "ymm11"),
(YMM12, "ymm12"),
(YMM13, "ymm13"),
(YMM14, "ymm14"),
(YMM15, "ymm15"),
(ZMM0, "zmm0"),
(ZMM1, "zmm1"),
(ZMM2, "zmm2"),
(ZMM3, "zmm3"),
(ZMM4, "zmm4"),
(ZMM5, "zmm5"),
(ZMM6, "zmm6"),
(ZMM7, "zmm7"),
(ZMM8, "zmm8"),
(ZMM9, "zmm9"),
(ZMM10, "zmm10"),
(ZMM11, "zmm11"),
(ZMM12, "zmm12"),
(ZMM13, "zmm13"),
(ZMM14, "zmm14"),
(ZMM15, "zmm15"),
];
pub const ATT_NAMES: &[(u16, &str)] = &[
(RAX, "%rax"),
(RCX, "%rcx"),
(RDX, "%rdx"),
(RBX, "%rbx"),
(RSP, "%rsp"),
(RBP, "%rbp"),
(RSI, "%rsi"),
(RDI, "%rdi"),
(R8, "%r8"),
(R9, "%r9"),
(R10, "%r10"),
(R11, "%r11"),
(R12, "%r12"),
(R13, "%r13"),
(R14, "%r14"),
(R15, "%r15"),
(EAX, "%eax"),
(ECX, "%ecx"),
(EDX, "%edx"),
(EBX, "%ebx"),
(ESP, "%esp"),
(EBP, "%ebp"),
(ESI, "%esi"),
(EDI, "%edi"),
(AX, "%ax"),
(CX, "%cx"),
(DX, "%dx"),
(BX, "%bx"),
(AL, "%al"),
(CL, "%cl"),
(DL, "%dl"),
(BL, "%bl"),
(AH, "%ah"),
(CH, "%ch"),
(DH, "%dh"),
(BH, "%bh"),
];
pub fn get_intel_name(reg: u16) -> Option<&'static str> {
INTEL_NAMES
.iter()
.find(|&&(r, _)| r == reg)
.map(|&(_, name)| name)
}
pub fn get_att_name(reg: u16) -> Option<&'static str> {
ATT_NAMES
.iter()
.find(|&&(r, _)| r == reg)
.map(|&(_, name)| name)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_register_counts() {
assert!(X86_64_REG_COUNT > 200);
assert!(X86_32_REG_COUNT > 150);
assert!(X86_64_REG_COUNT > X86_32_REG_COUNT);
}
#[test]
fn test_register_names() {
assert_eq!(X86RegisterInfo::get_asm_name(RAX), "%rax");
assert_eq!(X86RegisterInfo::get_asm_name(RCX), "%rcx");
assert_eq!(X86RegisterInfo::get_asm_name(RSP), "%rsp");
assert_eq!(X86RegisterInfo::get_asm_name(RBP), "%rbp");
assert_eq!(X86RegisterInfo::get_asm_name(EAX), "%eax");
assert_eq!(X86RegisterInfo::get_asm_name(AL), "%al");
assert_eq!(X86RegisterInfo::get_asm_name(AH), "%ah");
assert_eq!(X86RegisterInfo::get_asm_name(XMM0), "%xmm0");
assert_eq!(X86RegisterInfo::get_asm_name(YMM0), "%ymm0");
assert_eq!(X86RegisterInfo::get_asm_name(ZMM0), "%zmm0");
}
#[test]
fn test_intel_names() {
assert_eq!(X86RegisterInfo::get_intel_name(RAX), "rax");
assert_eq!(X86RegisterInfo::get_intel_name(EAX), "eax");
assert_eq!(X86RegisterInfo::get_intel_name(XMM0), "xmm0");
}
#[test]
fn test_super_reg_64() {
assert_eq!(get_super_reg_64(EAX), RAX);
assert_eq!(get_super_reg_64(AX), RAX);
assert_eq!(get_super_reg_64(AL), RAX);
assert_eq!(get_super_reg_64(AH), RAX);
assert_eq!(get_super_reg_64(ESI), RSI);
assert_eq!(get_super_reg_64(R8D), R8);
assert_eq!(get_super_reg_64(R8B), R8);
}
#[test]
fn test_sub_regs() {
assert_eq!(get_sub_reg_32(RAX), EAX);
assert_eq!(get_sub_reg_16(RAX), AX);
assert_eq!(get_sub_reg_8(RAX), AL);
assert_eq!(get_sub_reg_32(R8), R8D);
assert_eq!(get_sub_reg_16(R8), R8W);
assert_eq!(get_sub_reg_8(R8), R8B);
}
#[test]
fn test_reg_classes() {
assert_eq!(X86RegisterInfo::get_reg_class(RAX), RegClass::GPR64);
assert_eq!(X86RegisterInfo::get_reg_class(EAX), RegClass::GPR32);
assert_eq!(X86RegisterInfo::get_reg_class(AX), RegClass::GPR16);
assert_eq!(X86RegisterInfo::get_reg_class(AL), RegClass::GPR8);
assert_eq!(X86RegisterInfo::get_reg_class(XMM0), RegClass::XMM);
assert_eq!(X86RegisterInfo::get_reg_class(YMM0), RegClass::YMM);
assert_eq!(X86RegisterInfo::get_reg_class(ZMM0), RegClass::ZMM);
assert_eq!(X86RegisterInfo::get_reg_class(CS), RegClass::SEGMENT);
assert_eq!(X86RegisterInfo::get_reg_class(CR0), RegClass::CONTROL);
assert_eq!(X86RegisterInfo::get_reg_class(DR0), RegClass::DEBUG);
assert_eq!(X86RegisterInfo::get_reg_class(K0), RegClass::KMASK);
}
#[test]
fn test_reg_widths() {
assert_eq!(X86RegisterInfo::get_reg_width(RAX), 64);
assert_eq!(X86RegisterInfo::get_reg_width(EAX), 32);
assert_eq!(X86RegisterInfo::get_reg_width(AX), 16);
assert_eq!(X86RegisterInfo::get_reg_width(AL), 8);
assert_eq!(X86RegisterInfo::get_reg_width(XMM0), 128);
assert_eq!(X86RegisterInfo::get_reg_width(YMM0), 256);
assert_eq!(X86RegisterInfo::get_reg_width(ZMM0), 512);
}
#[test]
fn test_dwarf_numbers() {
assert_eq!(X86RegisterInfo::get_dwarf_num(RAX), 0);
assert_eq!(X86RegisterInfo::get_dwarf_num(RBP), 6);
assert_eq!(X86RegisterInfo::get_dwarf_num(RSP), 7);
assert_eq!(X86RegisterInfo::get_dwarf_num(RIP), 16);
assert_eq!(X86RegisterInfo::get_dwarf_num(XMM0), 17);
}
#[test]
fn test_callee_saved() {
assert!(X86RegisterInfo::is_callee_saved_sysv(RBX));
assert!(X86RegisterInfo::is_callee_saved_sysv(RBP));
assert!(X86RegisterInfo::is_callee_saved_sysv(R12));
assert!(X86RegisterInfo::is_callee_saved_sysv(R13));
assert!(X86RegisterInfo::is_callee_saved_sysv(R14));
assert!(X86RegisterInfo::is_callee_saved_sysv(R15));
assert!(!X86RegisterInfo::is_callee_saved_sysv(RAX));
assert!(!X86RegisterInfo::is_callee_saved_sysv(RCX));
assert!(!X86RegisterInfo::is_callee_saved_sysv(RDI));
}
#[test]
fn test_reserved() {
assert!(X86RegisterInfo::is_reserved(RSP));
assert!(X86RegisterInfo::is_reserved(RBP));
assert!(X86RegisterInfo::is_reserved(RIP));
assert!(X86RegisterInfo::is_reserved(RFLAGS));
assert!(!X86RegisterInfo::is_reserved(RAX));
}
#[test]
fn test_change_width() {
assert_eq!(X86RegisterInfo::change_width(RAX, 32), EAX);
assert_eq!(X86RegisterInfo::change_width(EAX, 64), RAX);
assert_eq!(X86RegisterInfo::change_width(AX, 32), EAX);
assert_eq!(X86RegisterInfo::change_width(R8D, 64), R8);
assert_eq!(X86RegisterInfo::change_width(R8B, 16), R8W);
}
#[test]
fn test_super_ymm_zmm() {
assert_eq!(get_super_ymm(XMM0), YMM0);
assert_eq!(get_super_ymm(XMM15), YMM15);
assert_eq!(get_super_zmm(XMM0), ZMM0);
assert_eq!(get_super_zmm(YMM0), ZMM0);
assert_eq!(get_super_zmm(XMM31), ZMM31);
}
#[test]
fn test_allocatable_regs() {
let gprs = X86RegisterInfo::get_allocatable_gprs_64();
assert_eq!(gprs.len(), 14); assert!(!gprs.contains(&RSP));
assert!(!gprs.contains(&RBP));
let xmms = X86RegisterInfo::get_allocatable_xmms();
assert_eq!(xmms.len(), 16); }
}
pub use RegClass::*;