[machinst x64]: add extractlane implementation
This commit is contained in:
@@ -404,6 +404,9 @@ pub enum SseOpcode {
|
||||
Paddw,
|
||||
Pavgb,
|
||||
Pavgw,
|
||||
Pextrb,
|
||||
Pextrw,
|
||||
Pextrd,
|
||||
Pinsrb,
|
||||
Pinsrw,
|
||||
Pinsrd,
|
||||
@@ -422,6 +425,7 @@ pub enum SseOpcode {
|
||||
Pmulld,
|
||||
Pmullw,
|
||||
Pmuludq,
|
||||
Pshufd,
|
||||
Psllw,
|
||||
Pslld,
|
||||
Psllq,
|
||||
@@ -524,6 +528,7 @@ impl SseOpcode {
|
||||
| SseOpcode::Paddw
|
||||
| SseOpcode::Pavgb
|
||||
| SseOpcode::Pavgw
|
||||
| SseOpcode::Pextrw
|
||||
| SseOpcode::Pinsrw
|
||||
| SseOpcode::Pmaxsw
|
||||
| SseOpcode::Pmaxub
|
||||
@@ -531,6 +536,7 @@ impl SseOpcode {
|
||||
| SseOpcode::Pminub
|
||||
| SseOpcode::Pmullw
|
||||
| SseOpcode::Pmuludq
|
||||
| SseOpcode::Pshufd
|
||||
| SseOpcode::Psllw
|
||||
| SseOpcode::Pslld
|
||||
| SseOpcode::Psllq
|
||||
@@ -554,6 +560,8 @@ impl SseOpcode {
|
||||
SseOpcode::Pabsb | SseOpcode::Pabsw | SseOpcode::Pabsd => SSSE3,
|
||||
|
||||
SseOpcode::Insertps
|
||||
| SseOpcode::Pextrb
|
||||
| SseOpcode::Pextrd
|
||||
| SseOpcode::Pinsrb
|
||||
| SseOpcode::Pinsrd
|
||||
| SseOpcode::Pmaxsb
|
||||
@@ -643,6 +651,9 @@ impl fmt::Debug for SseOpcode {
|
||||
SseOpcode::Paddw => "paddw",
|
||||
SseOpcode::Pavgb => "pavgb",
|
||||
SseOpcode::Pavgw => "pavgw",
|
||||
SseOpcode::Pextrb => "pextrb",
|
||||
SseOpcode::Pextrw => "pextrw",
|
||||
SseOpcode::Pextrd => "pextrd",
|
||||
SseOpcode::Pinsrb => "pinsrb",
|
||||
SseOpcode::Pinsrw => "pinsrw",
|
||||
SseOpcode::Pinsrd => "pinsrd",
|
||||
@@ -661,6 +672,7 @@ impl fmt::Debug for SseOpcode {
|
||||
SseOpcode::Pmulld => "pmulld",
|
||||
SseOpcode::Pmullw => "pmullw",
|
||||
SseOpcode::Pmuludq => "pmuludq",
|
||||
SseOpcode::Pshufd => "pshufd",
|
||||
SseOpcode::Psllw => "psllw",
|
||||
SseOpcode::Pslld => "pslld",
|
||||
SseOpcode::Psllq => "psllq",
|
||||
|
||||
@@ -1915,7 +1915,7 @@ pub(crate) fn emit(
|
||||
imm,
|
||||
is64: w,
|
||||
} => {
|
||||
let (prefix, opcode, num_opcodes) = match op {
|
||||
let (prefix, opcode, len) = match op {
|
||||
SseOpcode::Cmpps => (LegacyPrefixes::None, 0x0FC2, 2),
|
||||
SseOpcode::Cmppd => (LegacyPrefixes::_66, 0x0FC2, 2),
|
||||
SseOpcode::Cmpss => (LegacyPrefixes::_F3, 0x0FC2, 2),
|
||||
@@ -1924,6 +1924,10 @@ pub(crate) fn emit(
|
||||
SseOpcode::Pinsrb => (LegacyPrefixes::_66, 0x0F3A20, 3),
|
||||
SseOpcode::Pinsrw => (LegacyPrefixes::_66, 0x0FC4, 2),
|
||||
SseOpcode::Pinsrd => (LegacyPrefixes::_66, 0x0F3A22, 3),
|
||||
SseOpcode::Pextrb => (LegacyPrefixes::_66, 0x0F3A14, 3),
|
||||
SseOpcode::Pextrw => (LegacyPrefixes::_66, 0x0FC5, 2),
|
||||
SseOpcode::Pextrd => (LegacyPrefixes::_66, 0x0F3A16, 3),
|
||||
SseOpcode::Pshufd => (LegacyPrefixes::_66, 0x0F70, 2),
|
||||
_ => unimplemented!("Opcode {:?} not implemented", op),
|
||||
};
|
||||
let rex = if *w {
|
||||
@@ -1931,13 +1935,29 @@ pub(crate) fn emit(
|
||||
} else {
|
||||
RexFlags::clear_w()
|
||||
};
|
||||
let regs_swapped = match *op {
|
||||
// These opcodes (and not the SSE2 version of PEXTRW) flip the operand
|
||||
// encoding: `dst` in ModRM's r/m, `src` in ModRM's reg field.
|
||||
SseOpcode::Pextrb | SseOpcode::Pextrd => true,
|
||||
// The rest of the opcodes have the customary encoding: `dst` in ModRM's reg,
|
||||
// `src` in ModRM's r/m field.
|
||||
_ => false,
|
||||
};
|
||||
match src {
|
||||
RegMem::Reg { reg } => {
|
||||
emit_std_reg_reg(sink, prefix, opcode, num_opcodes, dst.to_reg(), *reg, rex);
|
||||
if regs_swapped {
|
||||
emit_std_reg_reg(sink, prefix, opcode, len, *reg, dst.to_reg(), rex);
|
||||
} else {
|
||||
emit_std_reg_reg(sink, prefix, opcode, len, dst.to_reg(), *reg, rex);
|
||||
}
|
||||
}
|
||||
RegMem::Mem { addr } => {
|
||||
let addr = &addr.finalize(state);
|
||||
emit_std_reg_mem(sink, prefix, opcode, num_opcodes, dst.to_reg(), addr, rex);
|
||||
assert!(
|
||||
!regs_swapped,
|
||||
"No existing way to encode a mem argument in the ModRM r/m field."
|
||||
);
|
||||
emit_std_reg_mem(sink, prefix, opcode, len, dst.to_reg(), addr, rex);
|
||||
}
|
||||
}
|
||||
sink.put1(*imm)
|
||||
|
||||
@@ -788,8 +788,6 @@ impl Inst {
|
||||
imm: u8,
|
||||
w: bool,
|
||||
) -> Inst {
|
||||
debug_assert!(dst.to_reg().get_class() == RegClass::V128);
|
||||
debug_assert!(imm < 8);
|
||||
Inst::XmmRmRImm {
|
||||
op,
|
||||
src,
|
||||
@@ -1736,10 +1734,17 @@ fn x64_get_regs(inst: &Inst, collector: &mut RegUsageCollector) {
|
||||
collector.add_mod(*dst);
|
||||
}
|
||||
}
|
||||
Inst::XmmRmRImm { src, dst, .. } => {
|
||||
Inst::XmmRmRImm { op, src, dst, .. } => {
|
||||
if inst.produces_const() {
|
||||
// No need to account for src, since src == dst.
|
||||
collector.add_def(*dst);
|
||||
} else if *op == SseOpcode::Pextrb
|
||||
|| *op == SseOpcode::Pextrw
|
||||
|| *op == SseOpcode::Pextrd
|
||||
|| *op == SseOpcode::Pshufd
|
||||
{
|
||||
src.get_regs_as_uses(collector);
|
||||
collector.add_def(*dst);
|
||||
} else {
|
||||
src.get_regs_as_uses(collector);
|
||||
collector.add_mod(*dst);
|
||||
@@ -2038,6 +2043,7 @@ fn x64_map_regs<RUM: RegUsageMapper>(inst: &mut Inst, mapper: &RUM) {
|
||||
map_def(mapper, dst);
|
||||
}
|
||||
Inst::XmmRmRImm {
|
||||
ref op,
|
||||
ref mut src,
|
||||
ref mut dst,
|
||||
..
|
||||
@@ -2045,6 +2051,13 @@ fn x64_map_regs<RUM: RegUsageMapper>(inst: &mut Inst, mapper: &RUM) {
|
||||
if produces_const {
|
||||
src.map_as_def(mapper);
|
||||
map_def(mapper, dst);
|
||||
} else if *op == SseOpcode::Pextrb
|
||||
|| *op == SseOpcode::Pextrw
|
||||
|| *op == SseOpcode::Pextrd
|
||||
|| *op == SseOpcode::Pshufd
|
||||
{
|
||||
src.map_uses(mapper);
|
||||
map_def(mapper, dst);
|
||||
} else {
|
||||
src.map_uses(mapper);
|
||||
map_mod(mapper, dst);
|
||||
|
||||
Reference in New Issue
Block a user