#![allow(unused)] #[allow(non_camel_case_types)] pub enum Mnemonic { /// add with carry /// two operands adc, /// integer add /// two operands add, /// signed multiply /// two operands imul, /// two operands mov, /// multiply /// two operands mul, /// one operand pop, /// one operand push, ret, /// subtract /// two operands sub, jmp, /// swap registers /// two operands xchg, /// interrupt int, /// bitwise shift left /// two operands shl, /// bitwise shift right /// two operands shr, /// arithmetic bitwise shift left /// two operands sal, /// arithmetic bitwise shift right /// two operands sar, // pseudo instructions /// one operand alloca, } #[allow(non_camel_case_types)] #[cfg_attr(rustfmt, rustfmt_skip)] #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, PartialOrd, Ord)] #[repr(u8)] pub enum Register { rax,eax,ax,al,ah, rbx,ebx,bx,bl,bh, rcx,ecx,cx,cl,ch, rdx,edx,dx,dl,dh, rsi,esi,si,sil, rdi,edi,di,dil, rsp,esp,sp,spl, rbp,ebp,bp,bpl, 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, rip,eip,ip,__ipl, st0,st1,st2,st3,st4,st5,st6,st7, mm0,mm1,mm2,mm3,mm4,mm5,mm6,mm7, xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7, xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15, ymm0,ymm1,ymm2,ymm3,ymm4,ymm5,ymm6,ymm7, ymm8,ymm9,ymm10,ymm11,ymm12,ymm13,ymm14,ymm15, // zmm0,zmm1,zmm2,zmm3,zmm4,zmm5,zmm6,zmm7, // zmm8,zmm9,zmm10,zmm11,zmm12,zmm13,zmm14,zmm15, } impl core::fmt::Display for Register { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let name = match self { Register::rax => "rax", Register::eax => "eax", Register::ax => "ax", Register::al => "al", Register::ah => "ah", Register::rbx => "rbx", Register::ebx => "ebx", Register::bx => "bx", Register::bl => "bl", Register::bh => "bh", Register::rcx => "rcx", Register::ecx => "ecx", Register::cx => "cx", Register::cl => "cl", Register::ch => "ch", Register::rdx => "rdx", Register::edx => "edx", Register::dx => "dx", Register::dl => "dl", Register::dh => "dh", Register::rsi => "rsi", Register::esi => "esi", Register::si => "si", Register::sil => "sil", Register::rdi => "rdi", Register::edi => "edi", Register::di => "di", Register::dil => "dil", Register::rsp => "rsp", Register::esp => "esp", Register::sp => "sp", Register::spl => "spl", Register::rbp => "rbp", Register::ebp => "ebp", Register::bp => "bp", Register::bpl => "bpl", Register::r8 => "r8", Register::r8d => "r8d", Register::r8w => "r8w", Register::r8b => "r8b", Register::r9 => "r9", Register::r9d => "r9d", Register::r9w => "r9w", Register::r9b => "r9b", Register::r10 => "r10", Register::r10d => "r10d", Register::r10w => "r10w", Register::r10b => "r10b", Register::r11 => "r11", Register::r11d => "r11d", Register::r11w => "r11w", Register::r11b => "r11b", Register::r12 => "r12", Register::r12d => "r12d", Register::r12w => "r12w", Register::r12b => "r12b", Register::r13 => "r13", Register::r13d => "r13d", Register::r13w => "r13w", Register::r13b => "r13b", Register::r14 => "r14", Register::r14d => "r14d", Register::r14w => "r14w", Register::r14b => "r14b", Register::r15 => "r15", Register::r15d => "r15d", Register::r15w => "r15w", Register::r15b => "r15b", Register::rip => "rip", Register::eip => "eip", Register::ip => "ip", Register::__ipl => "__ipl", Register::st0 => "st0", Register::st1 => "st1", Register::st2 => "st2", Register::st3 => "st3", Register::st4 => "st4", Register::st5 => "st5", Register::st6 => "st6", Register::st7 => "st7", Register::mm0 => "mm0", Register::mm1 => "mm1", Register::mm2 => "mm2", Register::mm3 => "mm3", Register::mm4 => "mm4", Register::mm5 => "mm5", Register::mm6 => "mm6", Register::mm7 => "mm7", Register::xmm0 => "xmm0", Register::xmm1 => "xmm1", Register::xmm2 => "xmm2", Register::xmm3 => "xmm3", Register::xmm4 => "xmm4", Register::xmm5 => "xmm5", Register::xmm6 => "xmm6", Register::xmm7 => "xmm7", Register::xmm8 => "xmm8", Register::xmm9 => "xmm9", Register::xmm10 => "xmm10", Register::xmm11 => "xmm11", Register::xmm12 => "xmm12", Register::xmm13 => "xmm13", Register::xmm14 => "xmm14", Register::xmm15 => "xmm15", Register::ymm0 => "ymm0", Register::ymm1 => "ymm1", Register::ymm2 => "ymm2", Register::ymm3 => "ymm3", Register::ymm4 => "ymm4", Register::ymm5 => "ymm5", Register::ymm6 => "ymm6", Register::ymm7 => "ymm7", Register::ymm8 => "ymm8", Register::ymm9 => "ymm9", Register::ymm10 => "ymm10", Register::ymm11 => "ymm11", Register::ymm12 => "ymm12", Register::ymm13 => "ymm13", Register::ymm14 => "ymm14", Register::ymm15 => "ymm15", }; write!(f, "{name}") } } impl Register { const fn bit_size(self) -> u32 { use Register::*; match self { ah | bh | ch | dh | al | bl | cl | dl | sil | dil | spl | bpl | r8b | r9b | r10b | r11b | r12b | r13b | r14b | r15b => 8, ax | bx | cx | dx | si | di | sp | bp | ip | r8w | r9w | r10w | r11w | r12w | r13w | r14w | r15w => 16, eax | ebx | ecx | edx | esi | edi | esp | ebp | eip | r8d | r9d | r10d | r11d | r12d | r13d | r14d | r15d => 32, rax | rbx | rcx | rdx | rsi | rdi | rsp | rbp | rip | r8 | r9 | r10 | r11 | r12 | r13 | r14 | r15 => 64, mm0 | mm1 | mm2 | mm3 | mm4 | mm5 | mm6 | mm7 => 64, st0 | st1 | st2 | st3 | st4 | st5 | st6 | st7 => 80, xmm0 | xmm1 | xmm2 | xmm3 | xmm4 | xmm5 | xmm6 | xmm7 | xmm8 | xmm9 | xmm10 | xmm11 | xmm12 | xmm13 | xmm14 | xmm15 => 128, ymm0 | ymm1 | ymm2 | ymm3 | ymm4 | ymm5 | ymm6 | ymm7 | ymm8 | ymm9 | ymm10 | ymm11 | ymm12 | ymm13 | ymm14 | ymm15 => 256, _ => unreachable!(), } } pub const fn byte_size(self) -> u32 { self.bit_size().div_ceil(8) } pub const fn parent_reg(self) -> Self { use Register::*; match self { rax | eax | ax | ah | al => rax, rbx | ebx | bx | bh | bl => rbx, rcx | ecx | cx | ch | cl => rcx, rdx | edx | dx | dh | dl => rdx, rsi | esi | si | sil => rsi, rdi | edi | di | dil => rdi, rsp | esp | sp | spl => rsp, rbp | ebp | bp | bpl => rbp, rip | eip | ip => rip, r8 | r8d | r8w | r8b => r8, r9 | r9d | r9w | r9b => r9, r10 | r10d | r10w | r10b => r10, r11 | r11d | r11w | r11b => r11, r12 | r12d | r12w | r12b => r12, r13 | r13d | r13w | r13b => r13, r14 | r14d | r14w | r14b => r14, r15 | r15d | r15w | r15b => r15, reg => reg, } } const fn from_u8(val: u8) -> Self { unsafe { *(&val as *const u8 as *const Self) } } pub const fn into_qword(self) -> Self { Self::from_u8(self.parent_reg() as u8) } pub const fn into_dword(self) -> Self { Self::from_u8(self.parent_reg() as u8 + 1) } pub const fn into_word(self) -> Self { Self::from_u8(self.parent_reg() as u8 + 2) } pub const fn into_byte(self) -> Self { Self::from_u8(self.parent_reg() as u8 + 3) } fn into_bitsize(self, size: u32) -> Self { assert!(self < Self::__ipl); match size { 8 => self.into_byte(), 16 => self.into_word(), 32 => self.into_dword(), 64 => self.into_qword(), _ => panic!("unsupported bitsize {size}"), } } pub fn into_bytesize(self, size: u32) -> Self { self.into_bitsize(size * 8) } pub const SYSV_CALLEE_SAVED: [Register; 5] = { use Register::*; [r12, r13, r14, r15, rbx] }; pub const SYSV_SCRATCH_GPRS: [Register; 8] = { use Register::*; [rax, rsi, rdx, rcx, r8, r9, r10, r11] }; pub const GPR: [Register; 14] = { use Register::*; [ rax, rbx, rcx, rdx, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15, ] }; pub const SYSV_ARG_GPR: [Register; 6] = { use Register::*; [rdi, rsi, rdx, rcx, r8, r9] }; pub const SYSV_ARG_SSE: [Register; 8] = { use Register::*; [xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7] }; pub const SSE: [Register; 16] = { use Register::*; [ xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, ] }; pub const fn is_gp(self) -> bool { use Register::*; match self { rax | eax | ax | ah | al | rbx | ebx | bx | bh | bl | rcx | ecx | cx | ch | cl | rdx | edx | dx | dh | dl | 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 => true, _ => false, } } pub const fn is_sse(self) -> bool { use Register::*; match self { xmm0 | xmm1 | xmm2 | xmm3 | xmm4 | xmm5 | xmm6 | xmm7 | xmm8 | xmm9 | xmm10 | xmm11 | xmm12 | xmm13 | xmm14 | xmm15 | ymm0 | ymm1 | ymm2 | ymm3 | ymm4 | ymm5 | ymm6 | ymm7 | ymm8 | ymm9 | ymm10 | ymm11 | ymm12 | ymm13 | ymm14 | ymm15 => true, _ => false, } } } pub enum Operands { One(Operand), Two(Operand, Operand), Three(Operand, Operand, Operand), } #[allow(non_camel_case_types)] pub enum Operand { imm8(u8), imm16(u16), imm32(u32), imm64(u64), reg8(u32), reg16(u32), reg32(u32), reg64(u32), mem8(u32), mem16(u32), mem32(u32), mem64(u32), moffset64(u64), } impl Operand { pub fn imm8(i: u8) -> Self { Operand::imm8(i) } pub fn imm16(i: u16) -> Self { Operand::imm16(i) } pub fn imm32(i: u32) -> Self { Operand::imm32(i) } pub fn imm64(i: u64) -> Self { Operand::imm64(i) } pub fn reg8(i: u32) -> Self { Operand::reg8(i) } pub fn reg16(i: u32) -> Self { Operand::reg16(i) } pub fn reg32(i: u32) -> Self { Operand::reg32(i) } pub fn reg64(i: u32) -> Self { Operand::reg64(i) } pub fn mem8(i: u32) -> Self { Operand::mem8(i) } pub fn mem16(i: u32) -> Self { Operand::mem16(i) } pub fn mem32(i: u32) -> Self { Operand::mem32(i) } pub fn mem64(i: u32) -> Self { Operand::mem64(i) } pub fn moffset64(i: u64) -> Self { Operand::moffset64(i) } } pub enum Imm { Byte(u8), Word(u16), DWord(u32), /// only allowed for `mov` QWord(u64), } /// r := register, m := memory, i := immediate #[allow(non_camel_case_types)] pub enum Payload { rr(Register, Register), rm, ri, r(Register), m, i, }