Index: runtime/vm/assembler_x64.cc |
diff --git a/runtime/vm/assembler_x64.cc b/runtime/vm/assembler_x64.cc |
index 1b270aa310ca1481c42d22864fbf1bb5a80fbe66..a872ac5ba94fa259d6d1e219eb346fdb3d860fea 100644 |
--- a/runtime/vm/assembler_x64.cc |
+++ b/runtime/vm/assembler_x64.cc |
@@ -529,6 +529,24 @@ void Assembler::movaps(XmmRegister dst, XmmRegister src) { |
} |
+void Assembler::movups(XmmRegister dst, const Address& src) { |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ EmitREX_RB(dst, src); |
+ EmitUint8(0x0F); |
+ EmitUint8(0x10); |
+ EmitOperand(dst & 7, src); |
+} |
+ |
+ |
+void Assembler::movups(const Address& dst, XmmRegister src) { |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ EmitREX_RB(src, dst); |
+ EmitUint8(0x0F); |
+ EmitUint8(0x11); |
+ EmitOperand(src & 7, dst); |
+} |
+ |
+ |
void Assembler::addsd(XmmRegister dst, XmmRegister src) { |
ASSERT(src <= XMM15); |
ASSERT(dst <= XMM15); |
@@ -576,6 +594,245 @@ void Assembler::divsd(XmmRegister dst, XmmRegister src) { |
EmitXmmRegisterOperand(dst & 7, src); |
} |
+void Assembler::addps(XmmRegister dst, XmmRegister src) { |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ EmitREX_RB(dst, src); |
+ EmitUint8(0x0F); |
+ EmitUint8(0x58); |
+ EmitXmmRegisterOperand(dst & 7, src); |
+} |
+ |
+ |
+void Assembler::subps(XmmRegister dst, XmmRegister src) { |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ EmitREX_RB(dst, src); |
+ EmitUint8(0x0F); |
+ EmitUint8(0x5C); |
+ EmitXmmRegisterOperand(dst & 7, src); |
+} |
+ |
+ |
+void Assembler::divps(XmmRegister dst, XmmRegister src) { |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ EmitREX_RB(dst, src); |
+ EmitUint8(0x0F); |
+ EmitUint8(0x5E); |
+ EmitXmmRegisterOperand(dst & 7, src); |
+} |
+ |
+ |
+void Assembler::mulps(XmmRegister dst, XmmRegister src) { |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ EmitREX_RB(dst, src); |
+ EmitUint8(0x0F); |
+ EmitUint8(0x59); |
+ EmitXmmRegisterOperand(dst & 7, src); |
+} |
+ |
+ |
+void Assembler::minps(XmmRegister dst, XmmRegister src) { |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ EmitREX_RB(dst, src); |
+ EmitUint8(0x0F); |
+ EmitUint8(0x5D); |
+ EmitXmmRegisterOperand(dst & 7, src); |
+} |
+ |
+ |
+void Assembler::maxps(XmmRegister dst, XmmRegister src) { |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ EmitREX_RB(dst, src); |
+ EmitUint8(0x0F); |
+ EmitUint8(0x5F); |
+ EmitXmmRegisterOperand(dst & 7, src); |
+} |
+ |
+ |
+void Assembler::andps(XmmRegister dst, XmmRegister src) { |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ EmitREX_RB(dst, src); |
+ EmitUint8(0x0F); |
+ EmitUint8(0x54); |
+ EmitXmmRegisterOperand(dst & 7, src); |
+} |
+ |
+ |
+void Assembler::andps(XmmRegister dst, const Address& src) { |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ EmitREX_RB(dst, src); |
+ EmitUint8(0x0F); |
+ EmitUint8(0x54); |
+ EmitOperand(dst & 7, src); |
+} |
+ |
+ |
+void Assembler::orps(XmmRegister dst, XmmRegister src) { |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ EmitREX_RB(dst, src); |
+ EmitUint8(0x0F); |
+ EmitUint8(0x56); |
+ EmitXmmRegisterOperand(dst & 7, src); |
+} |
+ |
+void Assembler::notps(XmmRegister dst) { |
+ static const struct ALIGN16 { |
+ uint32_t a; |
+ uint32_t b; |
+ uint32_t c; |
+ uint32_t d; |
+ } float_not_constant = |
+ { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; |
+ movq(TMP, Immediate(reinterpret_cast<intptr_t>(&float_not_constant))); |
+ xorps(dst, Address(TMP, 0)); |
+} |
+ |
+ |
+void Assembler::negateps(XmmRegister dst) { |
+ static const struct ALIGN16 { |
+ uint32_t a; |
+ uint32_t b; |
+ uint32_t c; |
+ uint32_t d; |
+ } float_negate_constant = |
+ { 0x80000000, 0x80000000, 0x80000000, 0x80000000 }; |
+ movq(TMP, Immediate(reinterpret_cast<intptr_t>(&float_negate_constant))); |
+ xorps(dst, Address(TMP, 0)); |
+} |
+ |
+ |
+void Assembler::absps(XmmRegister dst) { |
+ static const struct ALIGN16 { |
+ uint32_t a; |
+ uint32_t b; |
+ uint32_t c; |
+ uint32_t d; |
+ } float_absolute_constant = |
+ { 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF }; |
+ movq(TMP, Immediate(reinterpret_cast<intptr_t>(&float_absolute_constant))); |
+ andps(dst, Address(TMP, 0)); |
+} |
+ |
+ |
+void Assembler::zerowps(XmmRegister dst) { |
+ static const struct ALIGN16 { |
+ uint32_t a; |
+ uint32_t b; |
+ uint32_t c; |
+ uint32_t d; |
+ } float_zerow_constant = |
+ { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000 }; |
+ movq(TMP, Immediate(reinterpret_cast<intptr_t>(&float_zerow_constant))); |
+ andps(dst, Address(TMP, 0)); |
+} |
+ |
+ |
+void Assembler::cmppseq(XmmRegister dst, XmmRegister src) { |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ EmitREX_RB(dst, src); |
+ EmitUint8(0x0F); |
+ EmitUint8(0xC2); |
+ EmitXmmRegisterOperand(dst & 7, src); |
+ EmitUint8(0x0); |
+} |
+ |
+ |
+void Assembler::cmppsneq(XmmRegister dst, XmmRegister src) { |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ EmitREX_RB(dst, src); |
+ EmitUint8(0x0F); |
+ EmitUint8(0xC2); |
+ EmitXmmRegisterOperand(dst & 7, src); |
+ EmitUint8(0x4); |
+} |
+ |
+ |
+void Assembler::cmppslt(XmmRegister dst, XmmRegister src) { |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ EmitREX_RB(dst, src); |
+ EmitUint8(0x0F); |
+ EmitUint8(0xC2); |
+ EmitXmmRegisterOperand(dst & 7, src); |
+ EmitUint8(0x1); |
+} |
+ |
+ |
+void Assembler::cmppsle(XmmRegister dst, XmmRegister src) { |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ EmitREX_RB(dst, src); |
+ EmitUint8(0x0F); |
+ EmitUint8(0xC2); |
+ EmitXmmRegisterOperand(dst & 7, src); |
+ EmitUint8(0x2); |
+} |
+ |
+ |
+void Assembler::cmppsnlt(XmmRegister dst, XmmRegister src) { |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ EmitREX_RB(dst, src); |
+ EmitUint8(0x0F); |
+ EmitUint8(0xC2); |
+ EmitXmmRegisterOperand(dst & 7, src); |
+ EmitUint8(0x5); |
+} |
+ |
+ |
+void Assembler::cmppsnle(XmmRegister dst, XmmRegister src) { |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ EmitREX_RB(dst, src); |
+ EmitUint8(0x0F); |
+ EmitUint8(0xC2); |
+ EmitXmmRegisterOperand(dst & 7, src); |
+ EmitUint8(0x6); |
+} |
+ |
+ |
+void Assembler::sqrtps(XmmRegister dst) { |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ EmitREX_RB(dst, dst); |
+ EmitUint8(0x0F); |
+ EmitUint8(0x51); |
+ EmitXmmRegisterOperand(dst & 7, dst); |
+} |
+ |
+ |
+void Assembler::rsqrtps(XmmRegister dst) { |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ EmitREX_RB(dst, dst); |
+ EmitUint8(0x0F); |
+ EmitUint8(0x52); |
+ EmitXmmRegisterOperand(dst & 7, dst); |
+} |
+ |
+ |
+void Assembler::reciprocalps(XmmRegister dst) { |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ EmitREX_RB(dst, dst); |
+ EmitUint8(0x0F); |
+ EmitUint8(0x53); |
+ EmitXmmRegisterOperand(dst & 7, dst); |
+} |
+ |
+ |
+void Assembler::set1ps(XmmRegister dst, Register tmp1, const Immediate& imm) { |
+ // Load 32-bit immediate value into tmp1. |
+ movl(tmp1, imm); |
+ // Move value from tmp1 into dst. |
+ movd(dst, tmp1); |
+ // Broadcast low lane into other three lanes. |
+ shufps(dst, dst, Immediate(0x0)); |
+} |
+ |
+ |
+void Assembler::shufps(XmmRegister dst, XmmRegister src, const Immediate& imm) { |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ EmitREX_RB(dst, src); |
+ EmitUint8(0x0F); |
+ EmitUint8(0xC6); |
+ EmitXmmRegisterOperand(dst & 7, src); |
+ ASSERT(imm.is_uint8()); |
+ EmitUint8(imm.value()); |
+} |
+ |
void Assembler::comisd(XmmRegister a, XmmRegister b) { |
ASSERT(a <= XMM15); |
@@ -600,6 +857,16 @@ void Assembler::movmskpd(Register dst, XmmRegister src) { |
} |
+void Assembler::movmskps(Register dst, XmmRegister src) { |
+ ASSERT(src <= XMM15); |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ EmitREX_RB(dst, src); |
+ EmitUint8(0x0F); |
+ EmitUint8(0x50); |
+ EmitXmmRegisterOperand(dst & 7, src); |
+} |
+ |
+ |
void Assembler::sqrtsd(XmmRegister dst, XmmRegister src) { |
ASSERT(dst <= XMM15); |
ASSERT(src <= XMM15); |
@@ -635,6 +902,23 @@ void Assembler::xorpd(XmmRegister dst, XmmRegister src) { |
} |
+void Assembler::xorps(XmmRegister dst, const Address& src) { |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ EmitREX_RB(dst, src); |
+ EmitUint8(0x0F); |
+ EmitUint8(0x57); |
+ EmitOperand(dst & 7, src); |
+} |
+ |
+ |
+void Assembler::xorps(XmmRegister dst, XmmRegister src) { |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ EmitREX_RB(dst, src); |
+ EmitUint8(0x0F); |
+ EmitUint8(0x57); |
+ EmitXmmRegisterOperand(dst & 7, src); |
+} |
+ |
void Assembler::andpd(XmmRegister dst, const Address& src) { |
ASSERT(dst <= XMM15); |
AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
@@ -1923,14 +2207,14 @@ void Assembler::EnterCallRuntimeFrame(intptr_t frame_space) { |
} |
// Preserve all XMM registers except XMM0 |
- subq(RSP, Immediate((kNumberOfXmmRegisters - 1) * kDoubleSize)); |
+ subq(RSP, Immediate((kNumberOfXmmRegisters - 1) * kFpuRegisterSize)); |
// Store XMM registers with the lowest register number at the lowest |
// address. |
intptr_t offset = 0; |
for (intptr_t reg_idx = 1; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { |
XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); |
- movsd(Address(RSP, offset), xmm_reg); |
- offset += kDoubleSize; |
+ movups(Address(RSP, offset), xmm_reg); |
+ offset += kFpuRegisterSize; |
} |
ReserveAlignedFrameSpace(frame_space); |
@@ -1943,7 +2227,7 @@ void Assembler::LeaveCallRuntimeFrame() { |
// We need to restore it before restoring registers. |
const intptr_t kPushedRegistersSize = |
kNumberOfVolatileCpuRegisters * kWordSize + |
- kNumberOfVolatileXmmRegisters * kDoubleSize; |
+ kNumberOfVolatileXmmRegisters * kFpuRegisterSize; |
leaq(RSP, Address(RBP, -kPushedRegistersSize)); |
// Restore all XMM registers except XMM0 |
@@ -1951,8 +2235,8 @@ void Assembler::LeaveCallRuntimeFrame() { |
intptr_t offset = 0; |
for (intptr_t reg_idx = 1; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { |
XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); |
- movsd(xmm_reg, Address(RSP, offset)); |
- offset += kDoubleSize; |
+ movups(xmm_reg, Address(RSP, offset)); |
+ offset += kFpuRegisterSize; |
} |
addq(RSP, Immediate(offset)); |