Index: src/assembler_ia32.cpp |
diff --git a/src/assembler_ia32.cpp b/src/assembler_ia32.cpp |
index a245ca99dcbe948e25e76fbad62a698a35665698..8a2b4494bb04d8808a0af93b639d0177153e70d0 100644 |
--- a/src/assembler_ia32.cpp |
+++ b/src/assembler_ia32.cpp |
@@ -340,12 +340,20 @@ void AssemblerX86::movd(const Address &dst, XmmRegister src) { |
EmitOperand(src, dst); |
} |
+void AssemblerX86::movq(XmmRegister dst, XmmRegister src) { |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ EmitUint8(0xF3); |
+ EmitUint8(0x0F); |
+ EmitUint8(0x7E); |
+ EmitRegisterOperand(dst, src); |
+} |
+ |
void AssemblerX86::movq(const Address &dst, XmmRegister src) { |
AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
EmitUint8(0x66); |
EmitUint8(0x0F); |
EmitUint8(0xD6); |
- EmitOperand(src, Operand(dst)); |
+ EmitOperand(src, dst); |
} |
void AssemblerX86::movq(XmmRegister dst, const Address &src) { |
@@ -353,7 +361,7 @@ void AssemblerX86::movq(XmmRegister dst, const Address &src) { |
EmitUint8(0xF3); |
EmitUint8(0x0F); |
EmitUint8(0x7E); |
- EmitOperand(dst, Operand(src)); |
+ EmitOperand(dst, src); |
} |
void AssemblerX86::addss(Type Ty, XmmRegister dst, XmmRegister src) { |
@@ -463,6 +471,13 @@ void AssemblerX86::movaps(XmmRegister dst, XmmRegister src) { |
EmitXmmRegisterOperand(dst, src); |
} |
+void AssemblerX86::movups(XmmRegister dst, XmmRegister src) { |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ EmitUint8(0x0F); |
+ EmitUint8(0x10); |
+ EmitRegisterOperand(dst, src); |
+} |
+ |
void AssemblerX86::movups(XmmRegister dst, const Address &src) { |
AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
EmitUint8(0x0F); |
@@ -1289,52 +1304,90 @@ void AssemblerX86::fincstp() { |
EmitUint8(0xF7); |
} |
-void AssemblerX86::cmpl(GPRRegister reg, const Immediate &imm) { |
+void AssemblerX86::cmp(Type Ty, GPRRegister reg, const Immediate &imm) { |
AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
- EmitComplex(BrokenType, 7, Operand(reg), imm); |
+ if (isByteSizedType(Ty)) { |
+ EmitComplexI8(7, Operand(reg), imm); |
+ return; |
+ } |
+ if (Ty == IceType_i16) |
+ EmitOperandSizeOverride(); |
+ EmitComplex(Ty, 7, Operand(reg), imm); |
} |
-void AssemblerX86::cmpl(GPRRegister reg0, GPRRegister reg1) { |
+void AssemblerX86::cmp(Type Ty, GPRRegister reg0, GPRRegister reg1) { |
AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
- EmitUint8(0x3B); |
- EmitOperand(reg0, Operand(reg1)); |
+ if (Ty == IceType_i16) |
+ EmitOperandSizeOverride(); |
+ if (isByteSizedType(Ty)) |
+ EmitUint8(0x3A); |
+ else |
+ EmitUint8(0x3B); |
+ EmitRegisterOperand(reg0, reg1); |
} |
-void AssemblerX86::cmpl(GPRRegister reg, const Address &address) { |
+void AssemblerX86::cmp(Type Ty, GPRRegister reg, const Address &address) { |
AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
- EmitUint8(0x3B); |
+ if (Ty == IceType_i16) |
+ EmitOperandSizeOverride(); |
+ if (isByteSizedType(Ty)) |
+ EmitUint8(0x3A); |
+ else |
+ EmitUint8(0x3B); |
EmitOperand(reg, address); |
} |
-void AssemblerX86::cmpl(const Address &address, GPRRegister reg) { |
+void AssemblerX86::cmp(Type Ty, const Address &address, GPRRegister reg) { |
AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
- EmitUint8(0x39); |
+ if (Ty == IceType_i16) |
+ EmitOperandSizeOverride(); |
+ if (isByteSizedType(Ty)) |
+ EmitUint8(0x38); |
+ else |
+ EmitUint8(0x39); |
EmitOperand(reg, address); |
} |
-void AssemblerX86::cmpl(const Address &address, const Immediate &imm) { |
+void AssemblerX86::cmp(Type Ty, const Address &address, const Immediate &imm) { |
AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
- EmitComplex(BrokenType, 7, address, imm); |
+ if (isByteSizedType(Ty)) { |
+ EmitComplexI8(7, address, imm); |
+ return; |
+ } |
+ if (Ty == IceType_i16) |
+ EmitOperandSizeOverride(); |
+ EmitComplex(Ty, 7, address, imm); |
} |
-void AssemblerX86::cmpb(const Address &address, const Immediate &imm) { |
- assert(imm.is_int8()); |
+void AssemblerX86::test(Type Ty, GPRRegister reg1, GPRRegister reg2) { |
AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
- EmitUint8(0x80); |
- EmitOperand(7, address); |
- EmitUint8(imm.value() & 0xFF); |
+ if (Ty == IceType_i16) |
+ EmitOperandSizeOverride(); |
+ if (isByteSizedType(Ty)) |
+ EmitUint8(0x84); |
+ else |
+ EmitUint8(0x85); |
+ EmitRegisterOperand(reg1, reg2); |
} |
-void AssemblerX86::testl(GPRRegister reg1, GPRRegister reg2) { |
+void AssemblerX86::test(Type Ty, const Address &addr, GPRRegister reg) { |
AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
- EmitUint8(0x85); |
- EmitRegisterOperand(reg1, reg2); |
+ if (Ty == IceType_i16) |
+ EmitOperandSizeOverride(); |
+ if (isByteSizedType(Ty)) |
+ EmitUint8(0x84); |
+ else |
+ EmitUint8(0x85); |
+ EmitOperand(reg, addr); |
} |
-void AssemblerX86::testl(GPRRegister reg, const Immediate &immediate) { |
+void AssemblerX86::test(Type Ty, GPRRegister reg, const Immediate &immediate) { |
AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
// For registers that have a byte variant (EAX, EBX, ECX, and EDX) |
// we only test the byte register to keep the encoding short. |
+ // This is legal even if the register had high bits set since |
+ // this only sets flags registers based on the "AND" of the two operands, |
+ // and the immediate had zeros at those high bits. |
if (immediate.is_uint8() && reg < 4) { |
// Use zero-extended 8-bit immediate. |
if (reg == RegX8632::Encoded_Reg_eax) { |
@@ -1346,12 +1399,35 @@ void AssemblerX86::testl(GPRRegister reg, const Immediate &immediate) { |
EmitUint8(immediate.value() & 0xFF); |
} else if (reg == RegX8632::Encoded_Reg_eax) { |
// Use short form if the destination is EAX. |
+ if (Ty == IceType_i16) |
+ EmitOperandSizeOverride(); |
EmitUint8(0xA9); |
- EmitImmediate(BrokenType, immediate); |
+ EmitImmediate(Ty, immediate); |
+ } else { |
+ if (Ty == IceType_i16) |
+ EmitOperandSizeOverride(); |
+ EmitUint8(0xF7); |
+ EmitRegisterOperand(0, reg); |
+ EmitImmediate(Ty, immediate); |
+ } |
+} |
+ |
+void AssemblerX86::test(Type Ty, const Address &addr, |
+ const Immediate &immediate) { |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ // If the immediate is short, we only test the byte addr to keep the |
+ // encoding short. |
+ if (immediate.is_uint8()) { |
+ // Use zero-extended 8-bit immediate. |
+ EmitUint8(0xF6); |
+ EmitOperand(0, addr); |
+ EmitUint8(immediate.value() & 0xFF); |
} else { |
+ if (Ty == IceType_i16) |
+ EmitOperandSizeOverride(); |
EmitUint8(0xF7); |
- EmitOperand(0, Operand(reg)); |
- EmitImmediate(BrokenType, immediate); |
+ EmitOperand(0, addr); |
+ EmitImmediate(Ty, immediate); |
} |
} |
@@ -2013,6 +2089,12 @@ void AssemblerX86::hlt() { |
EmitUint8(0xF4); |
} |
+void AssemblerX86::ud2() { |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ EmitUint8(0x0F); |
+ EmitUint8(0x0B); |
+} |
+ |
void AssemblerX86::j(CondX86::BrCond condition, Label *label, bool near) { |
AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
if (label->IsBound()) { |