x64: Migrate brff and I128 branching instructions to ISLE (#4599)

https://github.com/bytecodealliance/wasmtime/pull/4599
This commit is contained in:
Trevor Elliott
2022-08-04 08:58:50 -07:00
committed by GitHub
parent 12a9705fbc
commit 1fc11bbe51
12 changed files with 254 additions and 356 deletions

View File

@@ -701,12 +701,6 @@ pub enum AluRmiROpcode {
Xor,
/// The signless, non-extending (N x N -> N, for N in {32,64}) variant.
Mul,
/// 8-bit form of And. Handled separately as we don't have full 8-bit op
/// support (we just use wider instructions). Used only with some sequences
/// with SETcc.
And8,
/// 8-bit form of Or.
Or8,
}
impl fmt::Debug for AluRmiROpcode {
@@ -720,8 +714,6 @@ impl fmt::Debug for AluRmiROpcode {
AluRmiROpcode::Or => "or",
AluRmiROpcode::Xor => "xor",
AluRmiROpcode::Mul => "imul",
AluRmiROpcode::And8 => "and",
AluRmiROpcode::Or8 => "or",
};
write!(fmt, "{}", name)
}
@@ -733,16 +725,6 @@ impl fmt::Display for AluRmiROpcode {
}
}
impl AluRmiROpcode {
/// Is this a special-cased 8-bit ALU op?
pub fn is_8bit(self) -> bool {
match self {
AluRmiROpcode::And8 | AluRmiROpcode::Or8 => true,
_ => false,
}
}
}
#[derive(Clone, PartialEq)]
pub enum UnaryRmROpcode {
/// Bit-scan reverse.
@@ -1704,32 +1686,6 @@ impl CC {
}
}
pub(crate) fn from_floatcc(floatcc: FloatCC) -> Self {
match floatcc {
FloatCC::Ordered => CC::NP,
FloatCC::Unordered => CC::P,
// Alias for NE
FloatCC::OrderedNotEqual => CC::NZ,
// Alias for E
FloatCC::UnorderedOrEqual => CC::Z,
// Alias for A
FloatCC::GreaterThan => CC::NBE,
// Alias for AE
FloatCC::GreaterThanOrEqual => CC::NB,
FloatCC::UnorderedOrLessThan => CC::B,
FloatCC::UnorderedOrLessThanOrEqual => CC::BE,
FloatCC::Equal
| FloatCC::NotEqual
| FloatCC::LessThan
| FloatCC::LessThanOrEqual
| FloatCC::UnorderedOrGreaterThan
| FloatCC::UnorderedOrGreaterThanOrEqual => panic!(
"{:?} can't be lowered to a CC code; treat as special case.",
floatcc
),
}
}
pub(crate) fn get_enc(self) -> u8 {
self as u8
}

View File

@@ -158,7 +158,7 @@ pub(crate) fn emit(
(reg_g, src2)
};
let mut rex = RexFlags::from(*size);
let rex = RexFlags::from(*size);
if *op == AluRmiROpcode::Mul {
// We kinda freeloaded Mul into RMI_R_Op, but it doesn't fit the usual pattern, so
// we have to special-case it.
@@ -191,26 +191,19 @@ pub(crate) fn emit(
}
}
} else {
let (opcode_r, opcode_m, subopcode_i, is_8bit) = match op {
AluRmiROpcode::Add => (0x01, 0x03, 0, false),
AluRmiROpcode::Adc => (0x11, 0x03, 0, false),
AluRmiROpcode::Sub => (0x29, 0x2B, 5, false),
AluRmiROpcode::Sbb => (0x19, 0x2B, 5, false),
AluRmiROpcode::And => (0x21, 0x23, 4, false),
AluRmiROpcode::Or => (0x09, 0x0B, 1, false),
AluRmiROpcode::Xor => (0x31, 0x33, 6, false),
AluRmiROpcode::And8 => (0x20, 0x22, 4, true),
AluRmiROpcode::Or8 => (0x08, 0x0A, 1, true),
let (opcode_r, opcode_m, subopcode_i) = match op {
AluRmiROpcode::Add => (0x01, 0x03, 0),
AluRmiROpcode::Adc => (0x11, 0x03, 0),
AluRmiROpcode::Sub => (0x29, 0x2B, 5),
AluRmiROpcode::Sbb => (0x19, 0x2B, 5),
AluRmiROpcode::And => (0x21, 0x23, 4),
AluRmiROpcode::Or => (0x09, 0x0B, 1),
AluRmiROpcode::Xor => (0x31, 0x33, 6),
AluRmiROpcode::Mul => panic!("unreachable"),
};
assert!(!(is_8bit && *size == OperandSize::Size64));
match src2 {
RegMemImm::Reg { reg: reg_e } => {
if is_8bit {
rex.always_emit_if_8bit_needed(reg_e);
rex.always_emit_if_8bit_needed(reg_g);
}
// GCC/llvm use the swapped operand encoding (viz., the R/RM vs RM/R
// duality). Do this too, so as to be able to compare generated machine
// code easily.
@@ -227,9 +220,6 @@ pub(crate) fn emit(
RegMemImm::Mem { addr } => {
let amode = addr.finalize(state, sink);
if is_8bit {
rex.always_emit_if_8bit_needed(reg_g);
}
// Here we revert to the "normal" G-E ordering.
emit_std_reg_mem(
sink,
@@ -245,7 +235,6 @@ pub(crate) fn emit(
}
RegMemImm::Imm { simm32 } => {
assert!(!is_8bit);
let use_imm8 = low8_will_sign_extend_to_32(simm32);
let opcode = if use_imm8 { 0x83 } else { 0x81 };
// And also here we use the "normal" G-E ordering.

View File

@@ -1258,86 +1258,6 @@ fn test_x64_emit() {
"4C09FA",
"orq %rdx, %r15, %rdx",
));
insns.push((
Inst::alu_rmi_r(
OperandSize::Size32,
AluRmiROpcode::And8,
RegMemImm::reg(r15),
w_rdx,
),
"4420FA",
"andb %dl, %r15b, %dl",
));
insns.push((
Inst::alu_rmi_r(
OperandSize::Size32,
AluRmiROpcode::And8,
RegMemImm::reg(rax),
w_rsi,
),
"4020C6",
"andb %sil, %al, %sil",
));
insns.push((
Inst::alu_rmi_r(
OperandSize::Size32,
AluRmiROpcode::And8,
RegMemImm::reg(rax),
w_rbx,
),
"20C3",
"andb %bl, %al, %bl",
));
insns.push((
Inst::alu_rmi_r(
OperandSize::Size32,
AluRmiROpcode::And8,
RegMemImm::mem(Amode::imm_reg(0, rax)),
w_rbx,
),
"2218",
"andb %bl, 0(%rax), %bl",
));
insns.push((
Inst::alu_rmi_r(
OperandSize::Size32,
AluRmiROpcode::Or8,
RegMemImm::reg(r15),
w_rdx,
),
"4408FA",
"orb %dl, %r15b, %dl",
));
insns.push((
Inst::alu_rmi_r(
OperandSize::Size32,
AluRmiROpcode::Or8,
RegMemImm::reg(rax),
w_rsi,
),
"4008C6",
"orb %sil, %al, %sil",
));
insns.push((
Inst::alu_rmi_r(
OperandSize::Size32,
AluRmiROpcode::Or8,
RegMemImm::reg(rax),
w_rbx,
),
"08C3",
"orb %bl, %al, %bl",
));
insns.push((
Inst::alu_rmi_r(
OperandSize::Size32,
AluRmiROpcode::Or8,
RegMemImm::mem(Amode::imm_reg(0, rax)),
w_rbx,
),
"0A18",
"orb %bl, 0(%rax), %bl",
));
insns.push((
Inst::alu_rmi_r(
OperandSize::Size64,

View File

@@ -729,10 +729,6 @@ impl Inst {
Inst::JmpKnown { dst }
}
pub(crate) fn jmp_if(cc: CC, taken: MachLabel) -> Inst {
Inst::JmpIf { cc, taken }
}
pub(crate) fn jmp_cond(cc: CC, taken: MachLabel, not_taken: MachLabel) -> Inst {
Inst::JmpCond {
cc,
@@ -892,23 +888,15 @@ impl PrettyPrint for Inst {
.to_string()
}
fn suffix_lqb(size: OperandSize, is_8: bool) -> String {
match (size, is_8) {
(_, true) => "b",
(OperandSize::Size32, false) => "l",
(OperandSize::Size64, false) => "q",
fn suffix_lqb(size: OperandSize) -> String {
match size {
OperandSize::Size32 => "l",
OperandSize::Size64 => "q",
_ => unreachable!(),
}
.to_string()
}
fn size_lqb(size: OperandSize, is_8: bool) -> u8 {
if is_8 {
return 1;
}
size.to_bytes()
}
fn suffix_bwlq(size: OperandSize) -> String {
match size {
OperandSize::Size8 => "b".to_string(),
@@ -922,11 +910,10 @@ impl PrettyPrint for Inst {
Inst::Nop { len } => format!("{} len={}", ljustify("nop".to_string()), len),
Inst::AluRmiR { size, op, dst, .. } if self.produces_const() => {
let dst =
pretty_print_reg(dst.to_reg().to_reg(), size_lqb(*size, op.is_8bit()), allocs);
let dst = pretty_print_reg(dst.to_reg().to_reg(), size.to_bytes(), allocs);
format!(
"{} {}, {}, {}",
ljustify2(op.to_string(), suffix_lqb(*size, op.is_8bit())),
ljustify2(op.to_string(), suffix_lqb(*size)),
dst,
dst,
dst
@@ -939,13 +926,13 @@ impl PrettyPrint for Inst {
src2,
dst,
} => {
let size_bytes = size_lqb(*size, op.is_8bit());
let size_bytes = size.to_bytes();
let src1 = pretty_print_reg(src1.to_reg(), size_bytes, allocs);
let dst = pretty_print_reg(dst.to_reg().to_reg(), size_bytes, allocs);
let src2 = src2.pretty_print(size_bytes, allocs);
format!(
"{} {}, {}, {}",
ljustify2(op.to_string(), suffix_lqb(*size, op.is_8bit())),
ljustify2(op.to_string(), suffix_lqb(*size)),
src1,
src2,
dst
@@ -957,12 +944,12 @@ impl PrettyPrint for Inst {
src1_dst,
src2,
} => {
let size_bytes = size_lqb(*size, op.is_8bit());
let size_bytes = size.to_bytes();
let src2 = pretty_print_reg(src2.to_reg(), size_bytes, allocs);
let src1_dst = src1_dst.pretty_print(size_bytes, allocs);
format!(
"{} {}, {}",
ljustify2(op.to_string(), suffix_lqb(*size, op.is_8bit())),
ljustify2(op.to_string(), suffix_lqb(*size)),
src2,
src1_dst,
)