make helpers generic

This commit is contained in:
satotake 2021-12-08 12:52:56 +00:00 committed by GitHub
parent 11daeb4374
commit 521ccbbb0e
3 changed files with 57 additions and 61 deletions

View file

@ -45,7 +45,11 @@ pub enum AArch64GeneralReg {
ZRSP = 31, ZRSP = 31,
} }
impl RegTrait for AArch64GeneralReg {} impl RegTrait for AArch64GeneralReg {
fn value(&self) -> u8 {
*self as u8
}
}
impl AArch64GeneralReg { impl AArch64GeneralReg {
#[inline(always)] #[inline(always)]
@ -57,7 +61,11 @@ impl AArch64GeneralReg {
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
#[allow(dead_code)] #[allow(dead_code)]
pub enum AArch64FloatReg {} pub enum AArch64FloatReg {}
impl RegTrait for AArch64FloatReg {} impl RegTrait for AArch64FloatReg {
fn value(&self) -> u8 {
*self as u8
}
}
pub struct AArch64Assembler {} pub struct AArch64Assembler {}

View file

@ -222,7 +222,9 @@ pub enum SymbolStorage<GeneralReg: RegTrait, FloatReg: RegTrait> {
}, },
} }
pub trait RegTrait: Copy + Eq + std::hash::Hash + std::fmt::Debug + 'static {} pub trait RegTrait: Copy + Eq + std::hash::Hash + std::fmt::Debug + 'static {
fn value(&self) -> u8;
}
pub struct Backend64Bit< pub struct Backend64Bit<
'a, 'a,

View file

@ -30,7 +30,11 @@ pub enum X86_64GeneralReg {
R14 = 14, R14 = 14,
R15 = 15, R15 = 15,
} }
impl RegTrait for X86_64GeneralReg {} impl RegTrait for X86_64GeneralReg {
fn value(&self) -> u8 {
*self as u8
}
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub enum X86_64FloatReg { pub enum X86_64FloatReg {
@ -51,7 +55,11 @@ pub enum X86_64FloatReg {
XMM14 = 14, XMM14 = 14,
XMM15 = 15, XMM15 = 15,
} }
impl RegTrait for X86_64FloatReg {} impl RegTrait for X86_64FloatReg {
fn value(&self) -> u8 {
*self as u8
}
}
pub struct X86_64Assembler {} pub struct X86_64Assembler {}
pub struct X86_64WindowsFastcall {} pub struct X86_64WindowsFastcall {}
@ -1129,26 +1137,9 @@ impl X86_64Assembler {
const REX: u8 = 0x40; const REX: u8 = 0x40;
const REX_W: u8 = REX + 0x8; const REX_W: u8 = REX + 0x8;
/// alias of add_rm_extension_reg
#[inline(always)] #[inline(always)]
const fn add_rm_extension(reg: X86_64GeneralReg, byte: u8) -> u8 { fn add_rm_extension<T: RegTrait>(reg: T, byte: u8) -> u8 {
add_rm_extension_reg(reg, byte) if reg.value() > 7 {
}
#[inline(always)]
const fn add_rm_extension_reg(reg: X86_64GeneralReg, byte: u8) -> u8 {
add_rm_extension_u8(reg as u8, byte)
}
#[allow(dead_code)]
#[inline(always)]
const fn add_rm_extension_freg(freg: X86_64FloatReg, byte: u8) -> u8 {
add_rm_extension_u8(freg as u8, byte)
}
#[inline(always)]
const fn add_rm_extension_u8(reg: u8, byte: u8) -> u8 {
if reg > 7 {
byte + 1 byte + 1
} else { } else {
byte byte
@ -1156,30 +1147,13 @@ const fn add_rm_extension_u8(reg: u8, byte: u8) -> u8 {
} }
#[inline(always)] #[inline(always)]
const fn add_opcode_extension(reg: X86_64GeneralReg, byte: u8) -> u8 { fn add_opcode_extension(reg: X86_64GeneralReg, byte: u8) -> u8 {
add_rm_extension_reg(reg, byte) add_rm_extension(reg, byte)
}
/// alias of add_reg_extension_reg
#[inline(always)]
const fn add_reg_extension(reg: X86_64GeneralReg, byte: u8) -> u8 {
add_reg_extension_reg(reg, byte)
} }
#[inline(always)] #[inline(always)]
const fn add_reg_extension_reg(reg: X86_64GeneralReg, byte: u8) -> u8 { fn add_reg_extension<T: RegTrait>(reg: T, byte: u8) -> u8 {
add_reg_extension_u8(reg as u8, byte) if reg.value() > 7 {
}
#[allow(dead_code)]
#[inline(always)]
const fn add_reg_extension_freg(freg: X86_64FloatReg, byte: u8) -> u8 {
add_reg_extension_u8(freg as u8, byte)
}
#[inline(always)]
const fn add_reg_extension_u8(reg: u8, byte: u8) -> u8 {
if reg > 7 {
byte + 4 byte + 4
} else { } else {
byte byte
@ -1530,19 +1504,31 @@ fn set_reg64_help(op_code: u8, buf: &mut Vec<'_, u8>, reg: X86_64GeneralReg) {
} }
#[inline(always)] #[inline(always)]
fn cvtsi2_help(buf: &mut Vec<'_, u8>, op_code1: u8, op_code2: u8, reg1: u8, reg2: u8) { fn cvtsi2_help<T: RegTrait, U: RegTrait>(
let rex = add_rm_extension_u8(reg2, REX_W); buf: &mut Vec<'_, u8>,
let rex = add_reg_extension_u8(reg1, rex); op_code1: u8,
let mod1 = (reg1 % 8) << 3; op_code2: u8,
let mod2 = reg2 % 8; dst: T,
src: U,
) {
let rex = add_rm_extension(src, REX_W);
let rex = add_reg_extension(dst, rex);
let mod1 = (dst.value() % 8) << 3;
let mod2 = src.value() % 8;
buf.extend(&[op_code1, rex, 0x0F, op_code2, 0xC0 + mod1 + mod2]) buf.extend(&[op_code1, rex, 0x0F, op_code2, 0xC0 + mod1 + mod2])
} }
#[inline(always)] #[inline(always)]
fn cvtsx2_help(buf: &mut Vec<'_, u8>, op_code1: u8, op_code2: u8, reg1: u8, reg2: u8) { fn cvtsx2_help<T: RegTrait, V: RegTrait>(
let mod1 = (reg1 % 8) << 3; buf: &mut Vec<'_, u8>,
let mod2 = reg2 % 8; op_code1: u8,
op_code2: u8,
dst: T,
src: V,
) {
let mod1 = (dst.value() % 8) << 3;
let mod2 = src.value() % 8;
buf.extend(&[op_code1, 0x0F, op_code2, 0xC0 + mod1 + mod2]) buf.extend(&[op_code1, 0x0F, op_code2, 0xC0 + mod1 + mod2])
} }
@ -1556,33 +1542,33 @@ fn sete_reg64(buf: &mut Vec<'_, u8>, reg: X86_64GeneralReg) {
/// `CVTSS2SD xmm` -> Convert one single-precision floating-point value in xmm/m32 to one double-precision floating-point value in xmm. /// `CVTSS2SD xmm` -> Convert one single-precision floating-point value in xmm/m32 to one double-precision floating-point value in xmm.
#[inline(always)] #[inline(always)]
fn cvtss2sd_freg64_freg32(buf: &mut Vec<'_, u8>, dst: X86_64FloatReg, src: X86_64FloatReg) { fn cvtss2sd_freg64_freg32(buf: &mut Vec<'_, u8>, dst: X86_64FloatReg, src: X86_64FloatReg) {
cvtsx2_help(buf, 0xF3, 0x5A, dst as u8, src as u8) cvtsx2_help(buf, 0xF3, 0x5A, dst, src)
} }
/// `CVTSD2SS xmm` -> Convert one double-precision floating-point value in xmm to one single-precision floating-point value and merge with high bits. /// `CVTSD2SS xmm` -> Convert one double-precision floating-point value in xmm to one single-precision floating-point value and merge with high bits.
#[inline(always)] #[inline(always)]
fn cvtsd2ss_freg32_freg64(buf: &mut Vec<'_, u8>, dst: X86_64FloatReg, src: X86_64FloatReg) { fn cvtsd2ss_freg32_freg64(buf: &mut Vec<'_, u8>, dst: X86_64FloatReg, src: X86_64FloatReg) {
cvtsx2_help(buf, 0xF2, 0x5A, dst as u8, src as u8) cvtsx2_help(buf, 0xF2, 0x5A, dst, src)
} }
/// `CVTSI2SD r/m64` -> Convert one signed quadword integer from r/m64 to one double-precision floating-point value in xmm. /// `CVTSI2SD r/m64` -> Convert one signed quadword integer from r/m64 to one double-precision floating-point value in xmm.
#[inline(always)] #[inline(always)]
fn cvtsi2sd_freg64_reg64(buf: &mut Vec<'_, u8>, dst: X86_64FloatReg, src: X86_64GeneralReg) { fn cvtsi2sd_freg64_reg64(buf: &mut Vec<'_, u8>, dst: X86_64FloatReg, src: X86_64GeneralReg) {
cvtsi2_help(buf, 0xF2, 0x2A, dst as u8, src as u8) cvtsi2_help(buf, 0xF2, 0x2A, dst, src)
} }
/// `CVTSI2SS r/m64` -> Convert one signed quadword integer from r/m64 to one single-precision floating-point value in xmm. /// `CVTSI2SS r/m64` -> Convert one signed quadword integer from r/m64 to one single-precision floating-point value in xmm.
#[allow(dead_code)] #[allow(dead_code)]
#[inline(always)] #[inline(always)]
fn cvtsi2ss_freg64_reg64(buf: &mut Vec<'_, u8>, dst: X86_64FloatReg, src: X86_64GeneralReg) { fn cvtsi2ss_freg64_reg64(buf: &mut Vec<'_, u8>, dst: X86_64FloatReg, src: X86_64GeneralReg) {
cvtsi2_help(buf, 0xF3, 0x2A, dst as u8, src as u8) cvtsi2_help(buf, 0xF3, 0x2A, dst, src)
} }
/// `CVTTSS2SI xmm/m32` -> Convert one single-precision floating-point value from xmm/m32 to one signed quadword integer in r64 using truncation. /// `CVTTSS2SI xmm/m32` -> Convert one single-precision floating-point value from xmm/m32 to one signed quadword integer in r64 using truncation.
#[allow(dead_code)] #[allow(dead_code)]
#[inline(always)] #[inline(always)]
fn cvttss2si_reg64_freg64(buf: &mut Vec<'_, u8>, dst: X86_64GeneralReg, src: X86_64FloatReg) { fn cvttss2si_reg64_freg64(buf: &mut Vec<'_, u8>, dst: X86_64GeneralReg, src: X86_64FloatReg) {
cvtsi2_help(buf, 0xF3, 0x2C, dst as u8, src as u8) cvtsi2_help(buf, 0xF3, 0x2C, dst, src)
} }
/// `SETNE r/m64` -> Set byte if not equal (ZF=0). /// `SETNE r/m64` -> Set byte if not equal (ZF=0).
@ -2214,7 +2200,7 @@ mod tests {
), ),
] { ] {
buf.clear(); buf.clear();
cvtsi2_help(&mut buf, 0xF3, *op_code, *reg1 as u8, *reg2 as u8); cvtsi2_help(&mut buf, 0xF3, *op_code, *reg1, *reg2);
assert_eq!(expected, &buf[..]); assert_eq!(expected, &buf[..]);
} }
@ -2245,7 +2231,7 @@ mod tests {
), ),
] { ] {
buf.clear(); buf.clear();
cvtsi2_help(&mut buf, 0xF3, *op_code, *reg1 as u8, *reg2 as u8); cvtsi2_help(&mut buf, 0xF3, *op_code, *reg1, *reg2);
assert_eq!(expected, &buf[..]); assert_eq!(expected, &buf[..]);
} }
} }
@ -2263,7 +2249,7 @@ mod tests {
[0xF3, 0x0F, 0x5A, 0xC8], [0xF3, 0x0F, 0x5A, 0xC8],
)] { )] {
buf.clear(); buf.clear();
cvtsx2_help(&mut buf, 0xF3, *op_code, *reg1 as u8, *reg2 as u8); cvtsx2_help(&mut buf, 0xF3, *op_code, *reg1, *reg2);
assert_eq!(expected, &buf[..]); assert_eq!(expected, &buf[..]);
} }
} }