451 lines
12 KiB
Rust
451 lines
12 KiB
Rust
#![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,
|
|
}
|