| 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));
|
|
|
|
|