Index: src/assembler_ia32.cpp |
diff --git a/src/assembler_ia32.cpp b/src/assembler_ia32.cpp |
index 16d01ce7cc1773c0d9671bac1615910329c1fdcb..550bc998761760f621a85da79977bf682979d8a4 100644 |
--- a/src/assembler_ia32.cpp |
+++ b/src/assembler_ia32.cpp |
@@ -940,6 +940,48 @@ void AssemblerX86::shufps(XmmRegister dst, XmmRegister src, |
EmitUint8(imm.value()); |
} |
+void AssemblerX86::pshufd(Type /* Ty */, XmmRegister dst, XmmRegister src, |
+ const Immediate &imm) { |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ EmitUint8(0x66); |
+ EmitUint8(0x0F); |
+ EmitUint8(0x70); |
+ EmitXmmRegisterOperand(dst, src); |
+ assert(imm.is_uint8()); |
+ EmitUint8(imm.value()); |
+} |
+ |
+void AssemblerX86::pshufd(Type /* Ty */, XmmRegister dst, const Address &src, |
+ const Immediate &imm) { |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ EmitUint8(0x66); |
+ EmitUint8(0x0F); |
+ EmitUint8(0x70); |
+ EmitOperand(dst, src); |
+ assert(imm.is_uint8()); |
+ EmitUint8(imm.value()); |
+} |
+ |
+void AssemblerX86::shufps(Type /* Ty */, XmmRegister dst, XmmRegister src, |
+ const Immediate &imm) { |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ EmitUint8(0x0F); |
+ EmitUint8(0xC6); |
+ EmitXmmRegisterOperand(dst, src); |
+ assert(imm.is_uint8()); |
+ EmitUint8(imm.value()); |
+} |
+ |
+void AssemblerX86::shufps(Type /* Ty */, XmmRegister dst, const Address &src, |
+ const Immediate &imm) { |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ EmitUint8(0x0F); |
+ EmitUint8(0xC6); |
+ EmitOperand(dst, src); |
+ assert(imm.is_uint8()); |
+ EmitUint8(imm.value()); |
+} |
+ |
void AssemblerX86::minpd(XmmRegister dst, XmmRegister src) { |
AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
EmitUint8(0x66); |
@@ -1163,18 +1205,96 @@ void AssemblerX86::andpd(XmmRegister dst, XmmRegister src) { |
EmitXmmRegisterOperand(dst, src); |
} |
-void AssemblerX86::pextrd(GPRRegister dst, XmmRegister src, |
- const Immediate &imm) { |
+void AssemblerX86::insertps(Type Ty, XmmRegister dst, XmmRegister src, |
+ const Immediate &imm) { |
AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ assert(imm.is_uint8()); |
+ assert(isVectorFloatingType(Ty)); |
+ (void)Ty; |
EmitUint8(0x66); |
EmitUint8(0x0F); |
EmitUint8(0x3A); |
- EmitUint8(0x16); |
- EmitOperand(src, Operand(dst)); |
+ EmitUint8(0x21); |
+ EmitXmmRegisterOperand(dst, src); |
+ EmitUint8(imm.value()); |
+} |
+ |
+void AssemblerX86::insertps(Type Ty, XmmRegister dst, const Address &src, |
+ const Immediate &imm) { |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
assert(imm.is_uint8()); |
+ assert(isVectorFloatingType(Ty)); |
+ (void)Ty; |
+ EmitUint8(0x66); |
+ EmitUint8(0x0F); |
+ EmitUint8(0x3A); |
+ EmitUint8(0x21); |
+ EmitOperand(dst, src); |
EmitUint8(imm.value()); |
} |
+void AssemblerX86::pinsr(Type Ty, XmmRegister dst, GPRRegister src, |
+ const Immediate &imm) { |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ assert(imm.is_uint8()); |
+ if (Ty == IceType_i16) { |
+ EmitUint8(0x66); |
+ EmitUint8(0x0F); |
+ EmitUint8(0xC4); |
+ EmitXmmRegisterOperand(dst, XmmRegister(src)); |
+ EmitUint8(imm.value()); |
+ } else { |
+ EmitUint8(0x66); |
+ EmitUint8(0x0F); |
+ EmitUint8(0x3A); |
+ EmitUint8(isByteSizedType(Ty) ? 0x20 : 0x22); |
+ EmitXmmRegisterOperand(dst, XmmRegister(src)); |
+ EmitUint8(imm.value()); |
+ } |
+} |
+ |
+void AssemblerX86::pinsr(Type Ty, XmmRegister dst, const Address &src, |
+ const Immediate &imm) { |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ assert(imm.is_uint8()); |
+ if (Ty == IceType_i16) { |
+ EmitUint8(0x66); |
+ EmitUint8(0x0F); |
+ EmitUint8(0xC4); |
+ EmitOperand(dst, src); |
+ EmitUint8(imm.value()); |
+ } else { |
+ EmitUint8(0x66); |
+ EmitUint8(0x0F); |
+ EmitUint8(0x3A); |
+ EmitUint8(isByteSizedType(Ty) ? 0x20 : 0x22); |
+ EmitOperand(dst, src); |
+ EmitUint8(imm.value()); |
+ } |
+} |
+ |
+void AssemblerX86::pextr(Type Ty, GPRRegister dst, XmmRegister src, |
+ const Immediate &imm) { |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ assert(imm.is_uint8()); |
+ if (Ty == IceType_i16) { |
+ EmitUint8(0x66); |
+ EmitUint8(0x0F); |
+ EmitUint8(0xC5); |
+ EmitXmmRegisterOperand(XmmRegister(dst), src); |
+ EmitUint8(imm.value()); |
+ } else { |
+ EmitUint8(0x66); |
+ EmitUint8(0x0F); |
+ EmitUint8(0x3A); |
+ EmitUint8(isByteSizedType(Ty) ? 0x14 : 0x16); |
+ // SSE 4.1 versions are "MRI" because dst can be mem, while |
+ // pextrw (SSE2) is RMI because dst must be reg. |
+ EmitXmmRegisterOperand(src, XmmRegister(dst)); |
+ EmitUint8(imm.value()); |
+ } |
+} |
+ |
void AssemblerX86::pmovsxdq(XmmRegister dst, XmmRegister src) { |
AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
EmitUint8(0x66); |
@@ -1863,52 +1983,70 @@ void AssemblerX86::sar(Type Ty, const Address &address, GPRRegister shifter) { |
EmitGenericShift(7, Ty, address, shifter); |
} |
-void AssemblerX86::shld(GPRRegister dst, GPRRegister src) { |
+void AssemblerX86::shld(Type Ty, GPRRegister dst, GPRRegister src) { |
AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ assert(Ty == IceType_i16 || Ty == IceType_i32); |
+ if (Ty == IceType_i16) |
+ EmitOperandSizeOverride(); |
EmitUint8(0x0F); |
EmitUint8(0xA5); |
EmitRegisterOperand(src, dst); |
} |
-void AssemblerX86::shld(GPRRegister dst, GPRRegister src, |
+void AssemblerX86::shld(Type Ty, GPRRegister dst, GPRRegister src, |
const Immediate &imm) { |
AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ assert(Ty == IceType_i16 || Ty == IceType_i32); |
assert(imm.is_int8()); |
+ if (Ty == IceType_i16) |
+ EmitOperandSizeOverride(); |
EmitUint8(0x0F); |
EmitUint8(0xA4); |
EmitRegisterOperand(src, dst); |
EmitUint8(imm.value() & 0xFF); |
} |
-void AssemblerX86::shld(const Address &operand, GPRRegister src) { |
+void AssemblerX86::shld(Type Ty, const Address &operand, GPRRegister src) { |
AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ assert(Ty == IceType_i16 || Ty == IceType_i32); |
+ if (Ty == IceType_i16) |
+ EmitOperandSizeOverride(); |
EmitUint8(0x0F); |
EmitUint8(0xA5); |
- EmitOperand(src, Operand(operand)); |
+ EmitOperand(src, operand); |
} |
-void AssemblerX86::shrd(GPRRegister dst, GPRRegister src) { |
+void AssemblerX86::shrd(Type Ty, GPRRegister dst, GPRRegister src) { |
AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ assert(Ty == IceType_i16 || Ty == IceType_i32); |
+ if (Ty == IceType_i16) |
+ EmitOperandSizeOverride(); |
EmitUint8(0x0F); |
EmitUint8(0xAD); |
EmitRegisterOperand(src, dst); |
} |
-void AssemblerX86::shrd(GPRRegister dst, GPRRegister src, |
+void AssemblerX86::shrd(Type Ty, GPRRegister dst, GPRRegister src, |
const Immediate &imm) { |
AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ assert(Ty == IceType_i16 || Ty == IceType_i32); |
assert(imm.is_int8()); |
+ if (Ty == IceType_i16) |
+ EmitOperandSizeOverride(); |
EmitUint8(0x0F); |
EmitUint8(0xAC); |
EmitRegisterOperand(src, dst); |
EmitUint8(imm.value() & 0xFF); |
} |
-void AssemblerX86::shrd(const Address &dst, GPRRegister src) { |
+void AssemblerX86::shrd(Type Ty, const Address &dst, GPRRegister src) { |
AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ assert(Ty == IceType_i16 || Ty == IceType_i32); |
+ if (Ty == IceType_i16) |
+ EmitOperandSizeOverride(); |
EmitUint8(0x0F); |
EmitUint8(0xAD); |
- EmitOperand(src, Operand(dst)); |
+ EmitOperand(src, dst); |
} |
void AssemblerX86::neg(Type Ty, GPRRegister reg) { |