2 * Copyright (C) 2008, 2014-2016 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #ifndef MacroAssemblerX86Common_h
27 #define MacroAssemblerX86Common_h
31 #include "X86Assembler.h"
32 #include "AbstractMacroAssembler.h"
33 #include <wtf/Optional.h>
37 class MacroAssemblerX86Common : public AbstractMacroAssembler<X86Assembler, MacroAssemblerX86Common> {
40 // Use this directly only if you're not generating code with it.
41 static const X86Registers::RegisterID s_scratchRegister = X86Registers::r11;
43 // Use this when generating code so that we get enforcement of the disallowing of scratch register
45 X86Registers::RegisterID scratchRegister()
47 RELEASE_ASSERT(m_allowScratchRegister);
48 return s_scratchRegister;
53 static const int DoubleConditionBitInvert = 0x10;
54 static const int DoubleConditionBitSpecial = 0x20;
55 static const int DoubleConditionBits = DoubleConditionBitInvert | DoubleConditionBitSpecial;
58 typedef X86Assembler::XMMRegisterID XMMRegisterID;
60 static bool isCompactPtrAlignedAddressOffset(ptrdiff_t value)
62 return value >= -128 && value <= 127;
65 enum RelationalCondition {
66 Equal = X86Assembler::ConditionE,
67 NotEqual = X86Assembler::ConditionNE,
68 Above = X86Assembler::ConditionA,
69 AboveOrEqual = X86Assembler::ConditionAE,
70 Below = X86Assembler::ConditionB,
71 BelowOrEqual = X86Assembler::ConditionBE,
72 GreaterThan = X86Assembler::ConditionG,
73 GreaterThanOrEqual = X86Assembler::ConditionGE,
74 LessThan = X86Assembler::ConditionL,
75 LessThanOrEqual = X86Assembler::ConditionLE
78 enum ResultCondition {
79 Overflow = X86Assembler::ConditionO,
80 Signed = X86Assembler::ConditionS,
81 PositiveOrZero = X86Assembler::ConditionNS,
82 Zero = X86Assembler::ConditionE,
83 NonZero = X86Assembler::ConditionNE
86 // FIXME: it would be neat to rename this to FloatingPointCondition in every assembler.
87 enum DoubleCondition {
88 // These conditions will only evaluate to true if the comparison is ordered - i.e. neither operand is NaN.
89 DoubleEqual = X86Assembler::ConditionE | DoubleConditionBitSpecial,
90 DoubleNotEqual = X86Assembler::ConditionNE,
91 DoubleGreaterThan = X86Assembler::ConditionA,
92 DoubleGreaterThanOrEqual = X86Assembler::ConditionAE,
93 DoubleLessThan = X86Assembler::ConditionA | DoubleConditionBitInvert,
94 DoubleLessThanOrEqual = X86Assembler::ConditionAE | DoubleConditionBitInvert,
95 // If either operand is NaN, these conditions always evaluate to true.
96 DoubleEqualOrUnordered = X86Assembler::ConditionE,
97 DoubleNotEqualOrUnordered = X86Assembler::ConditionNE | DoubleConditionBitSpecial,
98 DoubleGreaterThanOrUnordered = X86Assembler::ConditionB | DoubleConditionBitInvert,
99 DoubleGreaterThanOrEqualOrUnordered = X86Assembler::ConditionBE | DoubleConditionBitInvert,
100 DoubleLessThanOrUnordered = X86Assembler::ConditionB,
101 DoubleLessThanOrEqualOrUnordered = X86Assembler::ConditionBE,
104 !((X86Assembler::ConditionE | X86Assembler::ConditionNE | X86Assembler::ConditionA | X86Assembler::ConditionAE | X86Assembler::ConditionB | X86Assembler::ConditionBE) & DoubleConditionBits),
105 DoubleConditionBits_should_not_interfere_with_X86Assembler_Condition_codes);
107 static const RegisterID stackPointerRegister = X86Registers::esp;
108 static const RegisterID framePointerRegister = X86Registers::ebp;
110 static bool canBlind() { return true; }
111 static bool shouldBlindForSpecificArch(uint32_t value) { return value >= 0x00ffffff; }
112 static bool shouldBlindForSpecificArch(uint64_t value) { return value >= 0x00ffffff; }
114 // Integer arithmetic operations:
116 // Operations are typically two operand - operation(source, srcDst)
117 // For many operations the source may be an TrustedImm32, the srcDst operand
118 // may often be a memory location (explictly described using an Address
121 void add32(RegisterID src, RegisterID dest)
123 m_assembler.addl_rr(src, dest);
126 void add32(TrustedImm32 imm, Address address)
128 m_assembler.addl_im(imm.m_value, address.offset, address.base);
131 void add32(TrustedImm32 imm, BaseIndex address)
133 m_assembler.addl_im(imm.m_value, address.offset, address.base, address.index, address.scale);
136 void add8(TrustedImm32 imm, Address address)
138 m_assembler.addb_im(imm.m_value, address.offset, address.base);
141 void add8(TrustedImm32 imm, BaseIndex address)
143 m_assembler.addb_im(imm.m_value, address.offset, address.base, address.index, address.scale);
146 void add16(TrustedImm32 imm, Address address)
148 m_assembler.addw_im(imm.m_value, address.offset, address.base);
151 void add16(TrustedImm32 imm, BaseIndex address)
153 m_assembler.addw_im(imm.m_value, address.offset, address.base, address.index, address.scale);
156 void add32(TrustedImm32 imm, RegisterID dest)
158 if (imm.m_value == 1)
159 m_assembler.inc_r(dest);
161 m_assembler.addl_ir(imm.m_value, dest);
164 void add32(Address src, RegisterID dest)
166 m_assembler.addl_mr(src.offset, src.base, dest);
169 void add32(RegisterID src, Address dest)
171 m_assembler.addl_rm(src, dest.offset, dest.base);
174 void add32(RegisterID src, BaseIndex dest)
176 m_assembler.addl_rm(src, dest.offset, dest.base, dest.index, dest.scale);
179 void add8(RegisterID src, Address dest)
181 m_assembler.addb_rm(src, dest.offset, dest.base);
184 void add8(RegisterID src, BaseIndex dest)
186 m_assembler.addb_rm(src, dest.offset, dest.base, dest.index, dest.scale);
189 void add16(RegisterID src, Address dest)
191 m_assembler.addw_rm(src, dest.offset, dest.base);
194 void add16(RegisterID src, BaseIndex dest)
196 m_assembler.addw_rm(src, dest.offset, dest.base, dest.index, dest.scale);
199 void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
202 zeroExtend32ToPtr(src, dest);
211 m_assembler.leal_mr(imm.m_value, src, dest);
214 void add32(RegisterID a, RegisterID b, RegisterID dest)
216 x86Lea32(BaseIndex(a, b, TimesOne), dest);
219 void x86Lea32(BaseIndex index, RegisterID dest)
221 if (!index.scale && !index.offset) {
222 if (index.base == dest) {
223 add32(index.index, dest);
226 if (index.index == dest) {
227 add32(index.base, dest);
231 m_assembler.leal_mr(index.offset, index.base, index.index, index.scale, dest);
234 void and32(RegisterID src, RegisterID dest)
236 m_assembler.andl_rr(src, dest);
239 void and32(TrustedImm32 imm, RegisterID dest)
241 m_assembler.andl_ir(imm.m_value, dest);
244 void and32(RegisterID src, Address dest)
246 m_assembler.andl_rm(src, dest.offset, dest.base);
249 void and32(Address src, RegisterID dest)
251 m_assembler.andl_mr(src.offset, src.base, dest);
254 void and32(TrustedImm32 imm, Address address)
256 m_assembler.andl_im(imm.m_value, address.offset, address.base);
259 void and32(RegisterID op1, RegisterID op2, RegisterID dest)
262 zeroExtend32ToPtr(op1, dest);
263 else if (op1 == dest)
266 move32IfNeeded(op2, dest);
271 void and32(Address op1, RegisterID op2, RegisterID dest)
275 else if (op1.base == dest) {
279 zeroExtend32ToPtr(op2, dest);
284 void and32(RegisterID op1, Address op2, RegisterID dest)
286 and32(op2, op1, dest);
289 void and32(TrustedImm32 imm, RegisterID src, RegisterID dest)
291 move32IfNeeded(src, dest);
295 void countLeadingZeros32(RegisterID src, RegisterID dst)
297 if (supportsLZCNT()) {
298 m_assembler.lzcnt_rr(src, dst);
301 m_assembler.bsr_rr(src, dst);
305 void countLeadingZeros32(Address src, RegisterID dst)
307 if (supportsLZCNT()) {
308 m_assembler.lzcnt_mr(src.offset, src.base, dst);
311 m_assembler.bsr_mr(src.offset, src.base, dst);
315 void lshift32(RegisterID shift_amount, RegisterID dest)
317 if (shift_amount == X86Registers::ecx)
318 m_assembler.shll_CLr(dest);
320 ASSERT(shift_amount != dest);
321 // On x86 we can only shift by ecx; if asked to shift by another register we'll
322 // need rejig the shift amount into ecx first, and restore the registers afterwards.
323 // If we dest is ecx, then shift the swapped register!
324 swap(shift_amount, X86Registers::ecx);
325 m_assembler.shll_CLr(dest == X86Registers::ecx ? shift_amount : dest);
326 swap(shift_amount, X86Registers::ecx);
330 void lshift32(RegisterID src, RegisterID shift_amount, RegisterID dest)
332 ASSERT(shift_amount != dest);
334 move32IfNeeded(src, dest);
335 lshift32(shift_amount, dest);
338 void lshift32(TrustedImm32 imm, RegisterID dest)
340 m_assembler.shll_i8r(imm.m_value, dest);
343 void lshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
345 move32IfNeeded(src, dest);
349 void mul32(RegisterID src, RegisterID dest)
351 m_assembler.imull_rr(src, dest);
354 void mul32(RegisterID src1, RegisterID src2, RegisterID dest)
357 m_assembler.imull_rr(src1, dest);
360 move32IfNeeded(src1, dest);
361 m_assembler.imull_rr(src2, dest);
364 void mul32(Address src, RegisterID dest)
366 m_assembler.imull_mr(src.offset, src.base, dest);
369 void mul32(Address op1, RegisterID op2, RegisterID dest)
373 else if (op1.base == dest) {
377 zeroExtend32ToPtr(op2, dest);
382 void mul32(RegisterID src1, Address src2, RegisterID dest)
384 mul32(src2, src1, dest);
387 void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest)
389 m_assembler.imull_i32r(src, imm.m_value, dest);
392 void x86ConvertToDoubleWord32()
397 void x86ConvertToDoubleWord32(RegisterID eax, RegisterID edx)
399 ASSERT_UNUSED(eax, eax == X86Registers::eax);
400 ASSERT_UNUSED(edx, edx == X86Registers::edx);
401 x86ConvertToDoubleWord32();
404 void x86Div32(RegisterID denominator)
406 m_assembler.idivl_r(denominator);
409 void x86Div32(RegisterID eax, RegisterID edx, RegisterID denominator)
411 ASSERT_UNUSED(eax, eax == X86Registers::eax);
412 ASSERT_UNUSED(edx, edx == X86Registers::edx);
413 x86Div32(denominator);
416 void neg32(RegisterID srcDest)
418 m_assembler.negl_r(srcDest);
421 void neg32(Address srcDest)
423 m_assembler.negl_m(srcDest.offset, srcDest.base);
426 void or32(RegisterID src, RegisterID dest)
428 m_assembler.orl_rr(src, dest);
431 void or32(TrustedImm32 imm, RegisterID dest)
433 m_assembler.orl_ir(imm.m_value, dest);
436 void or32(RegisterID src, Address dest)
438 m_assembler.orl_rm(src, dest.offset, dest.base);
441 void or32(Address src, RegisterID dest)
443 m_assembler.orl_mr(src.offset, src.base, dest);
446 void or32(TrustedImm32 imm, Address address)
448 m_assembler.orl_im(imm.m_value, address.offset, address.base);
451 void or32(RegisterID op1, RegisterID op2, RegisterID dest)
454 zeroExtend32ToPtr(op1, dest);
455 else if (op1 == dest)
458 move32IfNeeded(op2, dest);
463 void or32(Address op1, RegisterID op2, RegisterID dest)
467 else if (op1.base == dest) {
471 zeroExtend32ToPtr(op2, dest);
476 void or32(RegisterID op1, Address op2, RegisterID dest)
478 or32(op2, op1, dest);
481 void or32(TrustedImm32 imm, RegisterID src, RegisterID dest)
483 move32IfNeeded(src, dest);
487 void rshift32(RegisterID shift_amount, RegisterID dest)
489 if (shift_amount == X86Registers::ecx)
490 m_assembler.sarl_CLr(dest);
492 ASSERT(shift_amount != dest);
494 // On x86 we can only shift by ecx; if asked to shift by another register we'll
495 // need rejig the shift amount into ecx first, and restore the registers afterwards.
496 // If we dest is ecx, then shift the swapped register!
497 swap(shift_amount, X86Registers::ecx);
498 m_assembler.sarl_CLr(dest == X86Registers::ecx ? shift_amount : dest);
499 swap(shift_amount, X86Registers::ecx);
503 void rshift32(RegisterID src, RegisterID shift_amount, RegisterID dest)
505 ASSERT(shift_amount != dest);
507 move32IfNeeded(src, dest);
508 rshift32(shift_amount, dest);
511 void rshift32(TrustedImm32 imm, RegisterID dest)
513 m_assembler.sarl_i8r(imm.m_value, dest);
516 void rshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
518 move32IfNeeded(src, dest);
522 void urshift32(RegisterID shift_amount, RegisterID dest)
524 if (shift_amount == X86Registers::ecx)
525 m_assembler.shrl_CLr(dest);
527 ASSERT(shift_amount != dest);
529 // On x86 we can only shift by ecx; if asked to shift by another register we'll
530 // need rejig the shift amount into ecx first, and restore the registers afterwards.
531 // If we dest is ecx, then shift the swapped register!
532 swap(shift_amount, X86Registers::ecx);
533 m_assembler.shrl_CLr(dest == X86Registers::ecx ? shift_amount : dest);
534 swap(shift_amount, X86Registers::ecx);
538 void urshift32(RegisterID src, RegisterID shift_amount, RegisterID dest)
540 ASSERT(shift_amount != dest);
542 move32IfNeeded(src, dest);
543 urshift32(shift_amount, dest);
546 void urshift32(TrustedImm32 imm, RegisterID dest)
548 m_assembler.shrl_i8r(imm.m_value, dest);
551 void urshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
553 move32IfNeeded(src, dest);
554 urshift32(imm, dest);
557 void sub32(RegisterID src, RegisterID dest)
559 m_assembler.subl_rr(src, dest);
562 void sub32(TrustedImm32 imm, RegisterID dest)
564 if (imm.m_value == 1)
565 m_assembler.dec_r(dest);
567 m_assembler.subl_ir(imm.m_value, dest);
570 void sub32(TrustedImm32 imm, Address address)
572 m_assembler.subl_im(imm.m_value, address.offset, address.base);
575 void sub32(Address src, RegisterID dest)
577 m_assembler.subl_mr(src.offset, src.base, dest);
580 void sub32(RegisterID src, Address dest)
582 m_assembler.subl_rm(src, dest.offset, dest.base);
585 void xor32(RegisterID src, RegisterID dest)
587 m_assembler.xorl_rr(src, dest);
590 void xor32(TrustedImm32 imm, Address dest)
592 if (imm.m_value == -1)
593 m_assembler.notl_m(dest.offset, dest.base);
595 m_assembler.xorl_im(imm.m_value, dest.offset, dest.base);
598 void xor32(TrustedImm32 imm, RegisterID dest)
600 if (imm.m_value == -1)
601 m_assembler.notl_r(dest);
603 m_assembler.xorl_ir(imm.m_value, dest);
606 void xor32(RegisterID src, Address dest)
608 m_assembler.xorl_rm(src, dest.offset, dest.base);
611 void xor32(Address src, RegisterID dest)
613 m_assembler.xorl_mr(src.offset, src.base, dest);
616 void xor32(RegisterID op1, RegisterID op2, RegisterID dest)
619 move(TrustedImm32(0), dest);
620 else if (op1 == dest)
623 move32IfNeeded(op2, dest);
628 void xor32(Address op1, RegisterID op2, RegisterID dest)
632 else if (op1.base == dest) {
636 zeroExtend32ToPtr(op2, dest);
641 void xor32(RegisterID op1, Address op2, RegisterID dest)
643 xor32(op2, op1, dest);
646 void xor32(TrustedImm32 imm, RegisterID src, RegisterID dest)
648 move32IfNeeded(src, dest);
652 void not32(RegisterID srcDest)
654 m_assembler.notl_r(srcDest);
657 void not32(Address dest)
659 m_assembler.notl_m(dest.offset, dest.base);
662 void sqrtDouble(FPRegisterID src, FPRegisterID dst)
664 m_assembler.sqrtsd_rr(src, dst);
667 void sqrtDouble(Address src, FPRegisterID dst)
669 m_assembler.sqrtsd_mr(src.offset, src.base, dst);
672 void sqrtFloat(FPRegisterID src, FPRegisterID dst)
674 m_assembler.sqrtss_rr(src, dst);
677 void sqrtFloat(Address src, FPRegisterID dst)
679 m_assembler.sqrtss_mr(src.offset, src.base, dst);
682 void absDouble(FPRegisterID src, FPRegisterID dst)
685 static const double negativeZeroConstant = -0.0;
686 loadDouble(TrustedImmPtr(&negativeZeroConstant), dst);
687 m_assembler.andnpd_rr(src, dst);
690 void negateDouble(FPRegisterID src, FPRegisterID dst)
693 static const double negativeZeroConstant = -0.0;
694 loadDouble(TrustedImmPtr(&negativeZeroConstant), dst);
695 m_assembler.xorpd_rr(src, dst);
698 void ceilDouble(FPRegisterID src, FPRegisterID dst)
700 m_assembler.roundsd_rr(src, dst, X86Assembler::RoundingType::TowardInfiniti);
703 void ceilDouble(Address src, FPRegisterID dst)
705 m_assembler.roundsd_mr(src.offset, src.base, dst, X86Assembler::RoundingType::TowardInfiniti);
708 void ceilFloat(FPRegisterID src, FPRegisterID dst)
710 m_assembler.roundss_rr(src, dst, X86Assembler::RoundingType::TowardInfiniti);
713 void ceilFloat(Address src, FPRegisterID dst)
715 m_assembler.roundss_mr(src.offset, src.base, dst, X86Assembler::RoundingType::TowardInfiniti);
718 void floorDouble(FPRegisterID src, FPRegisterID dst)
720 m_assembler.roundsd_rr(src, dst, X86Assembler::RoundingType::TowardNegativeInfiniti);
723 void floorDouble(Address src, FPRegisterID dst)
725 m_assembler.roundsd_mr(src.offset, src.base, dst, X86Assembler::RoundingType::TowardNegativeInfiniti);
728 void floorFloat(FPRegisterID src, FPRegisterID dst)
730 m_assembler.roundss_rr(src, dst, X86Assembler::RoundingType::TowardNegativeInfiniti);
733 void floorFloat(Address src, FPRegisterID dst)
735 m_assembler.roundss_mr(src.offset, src.base, dst, X86Assembler::RoundingType::TowardNegativeInfiniti);
738 void roundTowardZeroDouble(FPRegisterID src, FPRegisterID dst)
740 m_assembler.roundsd_rr(src, dst, X86Assembler::RoundingType::TowardZero);
743 void roundTowardZeroDouble(Address src, FPRegisterID dst)
745 m_assembler.roundsd_mr(src.offset, src.base, dst, X86Assembler::RoundingType::TowardZero);
748 void roundTowardZeroFloat(FPRegisterID src, FPRegisterID dst)
750 m_assembler.roundss_rr(src, dst, X86Assembler::RoundingType::TowardZero);
753 void roundTowardZeroFloat(Address src, FPRegisterID dst)
755 m_assembler.roundss_mr(src.offset, src.base, dst, X86Assembler::RoundingType::TowardZero);
758 // Memory access operations:
760 // Loads are of the form load(address, destination) and stores of the form
761 // store(source, address). The source for a store may be an TrustedImm32. Address
762 // operand objects to loads and store will be implicitly constructed if a
763 // register is passed.
765 void load32(ImplicitAddress address, RegisterID dest)
767 m_assembler.movl_mr(address.offset, address.base, dest);
770 void load32(BaseIndex address, RegisterID dest)
772 m_assembler.movl_mr(address.offset, address.base, address.index, address.scale, dest);
775 void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
777 load32(address, dest);
780 void load16Unaligned(BaseIndex address, RegisterID dest)
782 load16(address, dest);
785 DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
788 m_assembler.movl_mr_disp32(address.offset, address.base, dest);
789 return DataLabel32(this);
792 DataLabelCompact load32WithCompactAddressOffsetPatch(Address address, RegisterID dest)
795 m_assembler.movl_mr_disp8(address.offset, address.base, dest);
796 return DataLabelCompact(this);
799 static void repatchCompact(CodeLocationDataLabelCompact dataLabelCompact, int32_t value)
801 ASSERT(isCompactPtrAlignedAddressOffset(value));
802 AssemblerType_T::repatchCompact(dataLabelCompact.dataLocation(), value);
805 DataLabelCompact loadCompactWithAddressOffsetPatch(Address address, RegisterID dest)
808 m_assembler.movl_mr_disp8(address.offset, address.base, dest);
809 return DataLabelCompact(this);
812 void load8(BaseIndex address, RegisterID dest)
814 m_assembler.movzbl_mr(address.offset, address.base, address.index, address.scale, dest);
817 void load8(ImplicitAddress address, RegisterID dest)
819 m_assembler.movzbl_mr(address.offset, address.base, dest);
822 void load8SignedExtendTo32(BaseIndex address, RegisterID dest)
824 m_assembler.movsbl_mr(address.offset, address.base, address.index, address.scale, dest);
827 void load8SignedExtendTo32(ImplicitAddress address, RegisterID dest)
829 m_assembler.movsbl_mr(address.offset, address.base, dest);
832 void zeroExtend8To32(RegisterID src, RegisterID dest)
834 m_assembler.movzbl_rr(src, dest);
837 void signExtend8To32(RegisterID src, RegisterID dest)
839 m_assembler.movsbl_rr(src, dest);
842 void load16(BaseIndex address, RegisterID dest)
844 m_assembler.movzwl_mr(address.offset, address.base, address.index, address.scale, dest);
847 void load16(Address address, RegisterID dest)
849 m_assembler.movzwl_mr(address.offset, address.base, dest);
852 void load16SignedExtendTo32(BaseIndex address, RegisterID dest)
854 m_assembler.movswl_mr(address.offset, address.base, address.index, address.scale, dest);
857 void load16SignedExtendTo32(Address address, RegisterID dest)
859 m_assembler.movswl_mr(address.offset, address.base, dest);
862 void zeroExtend16To32(RegisterID src, RegisterID dest)
864 m_assembler.movzwl_rr(src, dest);
867 void signExtend16To32(RegisterID src, RegisterID dest)
869 m_assembler.movswl_rr(src, dest);
872 DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
875 m_assembler.movl_rm_disp32(src, address.offset, address.base);
876 return DataLabel32(this);
879 void store32(RegisterID src, ImplicitAddress address)
881 m_assembler.movl_rm(src, address.offset, address.base);
884 void store32(RegisterID src, BaseIndex address)
886 m_assembler.movl_rm(src, address.offset, address.base, address.index, address.scale);
889 void store32(TrustedImm32 imm, ImplicitAddress address)
891 m_assembler.movl_i32m(imm.m_value, address.offset, address.base);
894 void store32(TrustedImm32 imm, BaseIndex address)
896 m_assembler.movl_i32m(imm.m_value, address.offset, address.base, address.index, address.scale);
899 void storeZero32(ImplicitAddress address)
901 store32(TrustedImm32(0), address);
904 void storeZero32(BaseIndex address)
906 store32(TrustedImm32(0), address);
909 void store8(TrustedImm32 imm, Address address)
911 m_assembler.movb_i8m(static_cast<int8_t>(imm.m_value), address.offset, address.base);
914 void store8(TrustedImm32 imm, BaseIndex address)
916 m_assembler.movb_i8m(static_cast<int8_t>(imm.m_value), address.offset, address.base, address.index, address.scale);
919 static ALWAYS_INLINE RegisterID getUnusedRegister(BaseIndex address)
921 if (address.base != X86Registers::eax && address.index != X86Registers::eax)
922 return X86Registers::eax;
924 if (address.base != X86Registers::ebx && address.index != X86Registers::ebx)
925 return X86Registers::ebx;
927 ASSERT(address.base != X86Registers::ecx && address.index != X86Registers::ecx);
928 return X86Registers::ecx;
931 static ALWAYS_INLINE RegisterID getUnusedRegister(Address address)
933 if (address.base != X86Registers::eax)
934 return X86Registers::eax;
936 ASSERT(address.base != X86Registers::edx);
937 return X86Registers::edx;
940 void store8(RegisterID src, BaseIndex address)
943 // On 32-bit x86 we can only store from the first 4 registers;
944 // esp..edi are mapped to the 'h' registers!
946 // Pick a temporary register.
947 RegisterID temp = getUnusedRegister(address);
949 // Swap to the temporary register to perform the store.
951 m_assembler.movb_rm(temp, address.offset, address.base, address.index, address.scale);
956 m_assembler.movb_rm(src, address.offset, address.base, address.index, address.scale);
959 void store8(RegisterID src, Address address)
962 // On 32-bit x86 we can only store from the first 4 registers;
963 // esp..edi are mapped to the 'h' registers!
965 // Pick a temporary register.
966 RegisterID temp = getUnusedRegister(address);
968 // Swap to the temporary register to perform the store.
970 m_assembler.movb_rm(temp, address.offset, address.base);
975 m_assembler.movb_rm(src, address.offset, address.base);
978 void store16(RegisterID src, BaseIndex address)
981 // On 32-bit x86 we can only store from the first 4 registers;
982 // esp..edi are mapped to the 'h' registers!
984 // Pick a temporary register.
985 RegisterID temp = getUnusedRegister(address);
987 // Swap to the temporary register to perform the store.
989 m_assembler.movw_rm(temp, address.offset, address.base, address.index, address.scale);
994 m_assembler.movw_rm(src, address.offset, address.base, address.index, address.scale);
997 void store16(RegisterID src, Address address)
1000 // On 32-bit x86 we can only store from the first 4 registers;
1001 // esp..edi are mapped to the 'h' registers!
1003 // Pick a temporary register.
1004 RegisterID temp = getUnusedRegister(address);
1006 // Swap to the temporary register to perform the store.
1008 m_assembler.movw_rm(temp, address.offset, address.base);
1013 m_assembler.movw_rm(src, address.offset, address.base);
1017 // Floating-point operation:
1019 // Presently only supports SSE, not x87 floating point.
1021 void moveDouble(FPRegisterID src, FPRegisterID dest)
1023 ASSERT(isSSE2Present());
1025 m_assembler.movaps_rr(src, dest);
1028 void loadDouble(TrustedImmPtr address, FPRegisterID dest)
1031 ASSERT(isSSE2Present());
1032 m_assembler.movsd_mr(address.m_value, dest);
1034 move(address, scratchRegister());
1035 loadDouble(scratchRegister(), dest);
1039 void loadDouble(ImplicitAddress address, FPRegisterID dest)
1041 ASSERT(isSSE2Present());
1042 m_assembler.movsd_mr(address.offset, address.base, dest);
1045 void loadDouble(BaseIndex address, FPRegisterID dest)
1047 ASSERT(isSSE2Present());
1048 m_assembler.movsd_mr(address.offset, address.base, address.index, address.scale, dest);
1051 void loadFloat(ImplicitAddress address, FPRegisterID dest)
1053 ASSERT(isSSE2Present());
1054 m_assembler.movss_mr(address.offset, address.base, dest);
1057 void loadFloat(BaseIndex address, FPRegisterID dest)
1059 ASSERT(isSSE2Present());
1060 m_assembler.movss_mr(address.offset, address.base, address.index, address.scale, dest);
1063 void storeDouble(FPRegisterID src, ImplicitAddress address)
1065 ASSERT(isSSE2Present());
1066 m_assembler.movsd_rm(src, address.offset, address.base);
1069 void storeDouble(FPRegisterID src, BaseIndex address)
1071 ASSERT(isSSE2Present());
1072 m_assembler.movsd_rm(src, address.offset, address.base, address.index, address.scale);
1075 void storeFloat(FPRegisterID src, ImplicitAddress address)
1077 ASSERT(isSSE2Present());
1078 m_assembler.movss_rm(src, address.offset, address.base);
1081 void storeFloat(FPRegisterID src, BaseIndex address)
1083 ASSERT(isSSE2Present());
1084 m_assembler.movss_rm(src, address.offset, address.base, address.index, address.scale);
1087 void convertDoubleToFloat(FPRegisterID src, FPRegisterID dst)
1089 ASSERT(isSSE2Present());
1090 m_assembler.cvtsd2ss_rr(src, dst);
1093 void convertDoubleToFloat(Address address, FPRegisterID dst)
1095 ASSERT(isSSE2Present());
1096 m_assembler.cvtsd2ss_mr(address.offset, address.base, dst);
1099 void convertFloatToDouble(FPRegisterID src, FPRegisterID dst)
1101 ASSERT(isSSE2Present());
1102 m_assembler.cvtss2sd_rr(src, dst);
1105 void convertFloatToDouble(Address address, FPRegisterID dst)
1107 ASSERT(isSSE2Present());
1108 m_assembler.cvtss2sd_mr(address.offset, address.base, dst);
1111 void addDouble(FPRegisterID src, FPRegisterID dest)
1113 addDouble(src, dest, dest);
1116 void addDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
1119 m_assembler.vaddsd_rr(op1, op2, dest);
1121 ASSERT(isSSE2Present());
1123 m_assembler.addsd_rr(op2, dest);
1125 moveDouble(op2, dest);
1126 m_assembler.addsd_rr(op1, dest);
1131 void addDouble(Address src, FPRegisterID dest)
1133 addDouble(src, dest, dest);
1136 void addDouble(Address op1, FPRegisterID op2, FPRegisterID dest)
1139 m_assembler.vaddsd_mr(op1.offset, op1.base, op2, dest);
1141 ASSERT(isSSE2Present());
1143 m_assembler.addsd_mr(op1.offset, op1.base, dest);
1147 loadDouble(op1, dest);
1148 addDouble(op2, dest);
1152 void addDouble(FPRegisterID op1, Address op2, FPRegisterID dest)
1154 addDouble(op2, op1, dest);
1157 void addDouble(BaseIndex op1, FPRegisterID op2, FPRegisterID dest)
1160 m_assembler.vaddsd_mr(op1.offset, op1.base, op1.index, op1.scale, op2, dest);
1162 ASSERT(isSSE2Present());
1164 m_assembler.addsd_mr(op1.offset, op1.base, op1.index, op1.scale, dest);
1167 loadDouble(op1, dest);
1168 addDouble(op2, dest);
1172 void addFloat(FPRegisterID src, FPRegisterID dest)
1174 addFloat(src, dest, dest);
1177 void addFloat(Address src, FPRegisterID dest)
1179 addFloat(src, dest, dest);
1182 void addFloat(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
1185 m_assembler.vaddss_rr(op1, op2, dest);
1187 ASSERT(isSSE2Present());
1189 m_assembler.addss_rr(op2, dest);
1191 moveDouble(op2, dest);
1192 m_assembler.addss_rr(op1, dest);
1197 void addFloat(Address op1, FPRegisterID op2, FPRegisterID dest)
1200 m_assembler.vaddss_mr(op1.offset, op1.base, op2, dest);
1202 ASSERT(isSSE2Present());
1204 m_assembler.addss_mr(op1.offset, op1.base, dest);
1208 loadFloat(op1, dest);
1209 addFloat(op2, dest);
1213 void addFloat(FPRegisterID op1, Address op2, FPRegisterID dest)
1215 addFloat(op2, op1, dest);
1218 void addFloat(BaseIndex op1, FPRegisterID op2, FPRegisterID dest)
1221 m_assembler.vaddss_mr(op1.offset, op1.base, op1.index, op1.scale, op2, dest);
1223 ASSERT(isSSE2Present());
1225 m_assembler.addss_mr(op1.offset, op1.base, op1.index, op1.scale, dest);
1228 loadFloat(op1, dest);
1229 addFloat(op2, dest);
1233 void divDouble(FPRegisterID src, FPRegisterID dest)
1235 ASSERT(isSSE2Present());
1236 m_assembler.divsd_rr(src, dest);
1239 void divDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
1241 // B := A / B is invalid.
1242 ASSERT(op1 == dest || op2 != dest);
1244 moveDouble(op1, dest);
1245 divDouble(op2, dest);
1248 void divDouble(Address src, FPRegisterID dest)
1250 ASSERT(isSSE2Present());
1251 m_assembler.divsd_mr(src.offset, src.base, dest);
1254 void divFloat(FPRegisterID src, FPRegisterID dest)
1256 ASSERT(isSSE2Present());
1257 m_assembler.divss_rr(src, dest);
1260 void divFloat(Address src, FPRegisterID dest)
1262 ASSERT(isSSE2Present());
1263 m_assembler.divss_mr(src.offset, src.base, dest);
1266 void subDouble(FPRegisterID src, FPRegisterID dest)
1268 subDouble(dest, src, dest);
1271 void subDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
1274 m_assembler.vsubsd_rr(op1, op2, dest);
1276 ASSERT(isSSE2Present());
1278 // B := A - B is invalid.
1279 ASSERT(op1 == dest || op2 != dest);
1280 moveDouble(op1, dest);
1281 m_assembler.subsd_rr(op2, dest);
1285 void subDouble(FPRegisterID op1, Address op2, FPRegisterID dest)
1288 m_assembler.vsubsd_mr(op1, op2.offset, op2.base, dest);
1290 moveDouble(op1, dest);
1291 m_assembler.subsd_mr(op2.offset, op2.base, dest);
1295 void subDouble(FPRegisterID op1, BaseIndex op2, FPRegisterID dest)
1298 m_assembler.vsubsd_mr(op1, op2.offset, op2.base, op2.index, op2.scale, dest);
1300 moveDouble(op1, dest);
1301 m_assembler.subsd_mr(op2.offset, op2.base, op2.index, op2.scale, dest);
1305 void subDouble(Address src, FPRegisterID dest)
1307 subDouble(dest, src, dest);
1310 void subFloat(FPRegisterID src, FPRegisterID dest)
1312 subFloat(dest, src, dest);
1315 void subFloat(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
1318 m_assembler.vsubss_rr(op1, op2, dest);
1320 ASSERT(isSSE2Present());
1321 // B := A - B is invalid.
1322 ASSERT(op1 == dest || op2 != dest);
1323 moveDouble(op1, dest);
1324 m_assembler.subss_rr(op2, dest);
1328 void subFloat(FPRegisterID op1, Address op2, FPRegisterID dest)
1331 m_assembler.vsubss_mr(op1, op2.offset, op2.base, dest);
1333 moveDouble(op1, dest);
1334 m_assembler.subss_mr(op2.offset, op2.base, dest);
1338 void subFloat(FPRegisterID op1, BaseIndex op2, FPRegisterID dest)
1341 m_assembler.vsubss_mr(op1, op2.offset, op2.base, op2.index, op2.scale, dest);
1343 moveDouble(op1, dest);
1344 m_assembler.subss_mr(op2.offset, op2.base, op2.index, op2.scale, dest);
1348 void subFloat(Address src, FPRegisterID dest)
1350 subFloat(dest, src, dest);
1353 void mulDouble(FPRegisterID src, FPRegisterID dest)
1355 mulDouble(src, dest, dest);
1358 void mulDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
1361 m_assembler.vmulsd_rr(op1, op2, dest);
1363 ASSERT(isSSE2Present());
1365 m_assembler.mulsd_rr(op2, dest);
1367 moveDouble(op2, dest);
1368 m_assembler.mulsd_rr(op1, dest);
1373 void mulDouble(Address src, FPRegisterID dest)
1375 mulDouble(src, dest, dest);
1378 void mulDouble(Address op1, FPRegisterID op2, FPRegisterID dest)
1381 m_assembler.vmulsd_mr(op1.offset, op1.base, op2, dest);
1383 ASSERT(isSSE2Present());
1385 m_assembler.mulsd_mr(op1.offset, op1.base, dest);
1388 loadDouble(op1, dest);
1389 mulDouble(op2, dest);
1393 void mulDouble(FPRegisterID op1, Address op2, FPRegisterID dest)
1395 return mulDouble(op2, op1, dest);
1398 void mulDouble(BaseIndex op1, FPRegisterID op2, FPRegisterID dest)
1401 m_assembler.vmulsd_mr(op1.offset, op1.base, op1.index, op1.scale, op2, dest);
1403 ASSERT(isSSE2Present());
1405 m_assembler.mulsd_mr(op1.offset, op1.base, op1.index, op1.scale, dest);
1408 loadDouble(op1, dest);
1409 mulDouble(op2, dest);
1413 void mulFloat(FPRegisterID src, FPRegisterID dest)
1415 mulFloat(src, dest, dest);
1418 void mulFloat(Address src, FPRegisterID dest)
1420 mulFloat(src, dest, dest);
1423 void mulFloat(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
1426 m_assembler.vmulss_rr(op1, op2, dest);
1428 ASSERT(isSSE2Present());
1430 m_assembler.mulss_rr(op2, dest);
1432 moveDouble(op2, dest);
1433 m_assembler.mulss_rr(op1, dest);
1438 void mulFloat(Address op1, FPRegisterID op2, FPRegisterID dest)
1441 m_assembler.vmulss_mr(op1.offset, op1.base, op2, dest);
1443 ASSERT(isSSE2Present());
1445 m_assembler.mulss_mr(op1.offset, op1.base, dest);
1448 loadFloat(op1, dest);
1449 mulFloat(op2, dest);
1453 void mulFloat(FPRegisterID op1, Address op2, FPRegisterID dest)
1455 mulFloat(op2, op1, dest);
1458 void mulFloat(BaseIndex op1, FPRegisterID op2, FPRegisterID dest)
1461 m_assembler.vmulss_mr(op1.offset, op1.base, op1.index, op1.scale, op2, dest);
1463 ASSERT(isSSE2Present());
1465 m_assembler.mulss_mr(op1.offset, op1.base, op1.index, op1.scale, dest);
1468 loadFloat(op1, dest);
1469 mulFloat(op2, dest);
1473 void andDouble(FPRegisterID src, FPRegisterID dst)
1475 // ANDPS is defined on 128bits and is shorter than ANDPD.
1476 m_assembler.andps_rr(src, dst);
1479 void andDouble(FPRegisterID src1, FPRegisterID src2, FPRegisterID dst)
1482 andDouble(src2, dst);
1484 moveDouble(src2, dst);
1485 andDouble(src1, dst);
1489 void andFloat(FPRegisterID src, FPRegisterID dst)
1491 m_assembler.andps_rr(src, dst);
1494 void andFloat(FPRegisterID src1, FPRegisterID src2, FPRegisterID dst)
1497 andFloat(src2, dst);
1499 moveDouble(src2, dst);
1500 andFloat(src1, dst);
1504 void xorDouble(FPRegisterID src, FPRegisterID dst)
1506 m_assembler.xorps_rr(src, dst);
1509 void xorDouble(FPRegisterID src1, FPRegisterID src2, FPRegisterID dst)
1512 xorDouble(src2, dst);
1514 moveDouble(src2, dst);
1515 xorDouble(src1, dst);
1519 void xorFloat(FPRegisterID src, FPRegisterID dst)
1521 m_assembler.xorps_rr(src, dst);
1524 void xorFloat(FPRegisterID src1, FPRegisterID src2, FPRegisterID dst)
1527 xorFloat(src2, dst);
1529 moveDouble(src2, dst);
1530 xorFloat(src1, dst);
1534 void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
1536 ASSERT(isSSE2Present());
1537 m_assembler.cvtsi2sd_rr(src, dest);
1540 void convertInt32ToDouble(Address src, FPRegisterID dest)
1542 ASSERT(isSSE2Present());
1543 m_assembler.cvtsi2sd_mr(src.offset, src.base, dest);
1546 Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
1548 ASSERT(isSSE2Present());
1550 if (cond & DoubleConditionBitInvert)
1551 m_assembler.ucomisd_rr(left, right);
1553 m_assembler.ucomisd_rr(right, left);
1554 return jumpAfterFloatingPointCompare(cond, left, right);
1557 Jump branchFloat(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
1559 ASSERT(isSSE2Present());
1561 if (cond & DoubleConditionBitInvert)
1562 m_assembler.ucomiss_rr(left, right);
1564 m_assembler.ucomiss_rr(right, left);
1565 return jumpAfterFloatingPointCompare(cond, left, right);
1568 // Truncates 'src' to an integer, and places the resulting 'dest'.
1569 // If the result is not representable as a 32 bit value, branch.
1570 // May also branch for some values that are representable in 32 bits
1571 // (specifically, in this case, INT_MIN).
1572 enum BranchTruncateType { BranchIfTruncateFailed, BranchIfTruncateSuccessful };
1573 Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed)
1575 ASSERT(isSSE2Present());
1576 m_assembler.cvttsd2si_rr(src, dest);
1577 return branch32(branchType ? NotEqual : Equal, dest, TrustedImm32(0x80000000));
1580 void truncateDoubleToInt32(FPRegisterID src, RegisterID dest)
1582 ASSERT(isSSE2Present());
1583 m_assembler.cvttsd2si_rr(src, dest);
1587 void truncateDoubleToUint32(FPRegisterID src, RegisterID dest)
1589 ASSERT(isSSE2Present());
1590 m_assembler.cvttsd2siq_rr(src, dest);
1594 // Convert 'src' to an integer, and places the resulting 'dest'.
1595 // If the result is not representable as a 32 bit value, branch.
1596 // May also branch for some values that are representable in 32 bits
1597 // (specifically, in this case, 0).
1598 void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp, bool negZeroCheck = true)
1600 ASSERT(isSSE2Present());
1601 m_assembler.cvttsd2si_rr(src, dest);
1603 // If the result is zero, it might have been -0.0, and the double comparison won't catch this!
1606 Jump valueIsNonZero = branchTest32(NonZero, dest);
1607 m_assembler.movmskpd_rr(src, scratchRegister());
1608 failureCases.append(branchTest32(NonZero, scratchRegister(), TrustedImm32(1)));
1609 valueIsNonZero.link(this);
1613 failureCases.append(branchTest32(Zero, dest));
1616 // Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump.
1617 convertInt32ToDouble(dest, fpTemp);
1618 m_assembler.ucomisd_rr(fpTemp, src);
1619 failureCases.append(m_assembler.jp());
1620 failureCases.append(m_assembler.jne());
1623 void moveZeroToDouble(FPRegisterID reg)
1625 m_assembler.xorps_rr(reg, reg);
1628 Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID scratch)
1630 ASSERT(isSSE2Present());
1631 m_assembler.xorpd_rr(scratch, scratch);
1632 return branchDouble(DoubleNotEqual, reg, scratch);
1635 Jump branchDoubleZeroOrNaN(FPRegisterID reg, FPRegisterID scratch)
1637 ASSERT(isSSE2Present());
1638 m_assembler.xorpd_rr(scratch, scratch);
1639 return branchDouble(DoubleEqualOrUnordered, reg, scratch);
1642 void lshiftPacked(TrustedImm32 imm, XMMRegisterID reg)
1644 ASSERT(isSSE2Present());
1645 m_assembler.psllq_i8r(imm.m_value, reg);
1648 void rshiftPacked(TrustedImm32 imm, XMMRegisterID reg)
1650 ASSERT(isSSE2Present());
1651 m_assembler.psrlq_i8r(imm.m_value, reg);
1654 void orPacked(XMMRegisterID src, XMMRegisterID dst)
1656 ASSERT(isSSE2Present());
1657 m_assembler.por_rr(src, dst);
1660 void move32ToFloat(RegisterID src, XMMRegisterID dst)
1662 ASSERT(isSSE2Present());
1663 m_assembler.movd_rr(src, dst);
1666 void moveFloatTo32(XMMRegisterID src, RegisterID dst)
1668 ASSERT(isSSE2Present());
1669 m_assembler.movd_rr(src, dst);
1672 // Stack manipulation operations:
1674 // The ABI is assumed to provide a stack abstraction to memory,
1675 // containing machine word sized units of data. Push and pop
1676 // operations add and remove a single register sized unit of data
1677 // to or from the stack. Peek and poke operations read or write
1678 // values on the stack, without moving the current stack position.
1680 void pop(RegisterID dest)
1682 m_assembler.pop_r(dest);
1685 void push(RegisterID src)
1687 m_assembler.push_r(src);
1690 void push(Address address)
1692 m_assembler.push_m(address.offset, address.base);
1695 void push(TrustedImm32 imm)
1697 m_assembler.push_i32(imm.m_value);
1701 // Register move operations:
1703 // Move values in registers.
1705 void move(TrustedImm32 imm, RegisterID dest)
1707 // Note: on 64-bit the TrustedImm32 value is zero extended into the register, it
1708 // may be useful to have a separate version that sign extends the value?
1710 m_assembler.xorl_rr(dest, dest);
1712 m_assembler.movl_i32r(imm.m_value, dest);
1716 void move(RegisterID src, RegisterID dest)
1718 // Note: on 64-bit this is is a full register move; perhaps it would be
1719 // useful to have separate move32 & movePtr, with move32 zero extending?
1721 m_assembler.movq_rr(src, dest);
1724 void move(TrustedImmPtr imm, RegisterID dest)
1727 m_assembler.xorq_rr(dest, dest);
1729 m_assembler.movq_i64r(imm.asIntptr(), dest);
1732 void move(TrustedImm64 imm, RegisterID dest)
1735 m_assembler.xorq_rr(dest, dest);
1737 m_assembler.movq_i64r(imm.m_value, dest);
1740 void moveConditionallyDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right, RegisterID src, RegisterID dest)
1742 ASSERT(isSSE2Present());
1744 if (cond & DoubleConditionBitInvert)
1745 m_assembler.ucomisd_rr(left, right);
1747 m_assembler.ucomisd_rr(right, left);
1748 moveConditionallyAfterFloatingPointCompare(cond, left, right, src, dest);
1751 void moveConditionallyDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right, RegisterID thenCase, RegisterID elseCase, RegisterID dest)
1753 ASSERT(isSSE2Present());
1755 if (thenCase != dest && elseCase != dest) {
1756 move(elseCase, dest);
1761 if (elseCase == dest)
1764 cond = invert(cond);
1768 if (cond & DoubleConditionBitInvert)
1769 m_assembler.ucomisd_rr(left, right);
1771 m_assembler.ucomisd_rr(right, left);
1772 moveConditionallyAfterFloatingPointCompare(cond, left, right, src, dest);
1775 void moveConditionallyFloat(DoubleCondition cond, FPRegisterID left, FPRegisterID right, RegisterID src, RegisterID dest)
1777 ASSERT(isSSE2Present());
1779 if (cond & DoubleConditionBitInvert)
1780 m_assembler.ucomiss_rr(left, right);
1782 m_assembler.ucomiss_rr(right, left);
1783 moveConditionallyAfterFloatingPointCompare(cond, left, right, src, dest);
1786 void moveConditionallyFloat(DoubleCondition cond, FPRegisterID left, FPRegisterID right, RegisterID thenCase, RegisterID elseCase, RegisterID dest)
1788 ASSERT(isSSE2Present());
1790 if (thenCase != dest && elseCase != dest) {
1791 move(elseCase, dest);
1796 if (elseCase == dest)
1799 cond = invert(cond);
1803 if (cond & DoubleConditionBitInvert)
1804 m_assembler.ucomiss_rr(left, right);
1806 m_assembler.ucomiss_rr(right, left);
1807 moveConditionallyAfterFloatingPointCompare(cond, left, right, src, dest);
1810 void swap(RegisterID reg1, RegisterID reg2)
1813 m_assembler.xchgq_rr(reg1, reg2);
1816 void signExtend32ToPtr(TrustedImm32 imm, RegisterID dest)
1819 m_assembler.xorq_rr(dest, dest);
1821 m_assembler.mov_i32r(imm.m_value, dest);
1824 void signExtend32ToPtr(RegisterID src, RegisterID dest)
1826 m_assembler.movsxd_rr(src, dest);
1829 void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
1831 m_assembler.movl_rr(src, dest);
1834 void zeroExtend32ToPtr(TrustedImm32 src, RegisterID dest)
1836 m_assembler.movl_i32r(src.m_value, dest);
1839 void move(RegisterID src, RegisterID dest)
1842 m_assembler.movl_rr(src, dest);
1845 void move(TrustedImmPtr imm, RegisterID dest)
1848 m_assembler.xorl_rr(dest, dest);
1850 m_assembler.movl_i32r(imm.asIntptr(), dest);
1853 void moveConditionallyDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right, RegisterID src, RegisterID dest)
1855 ASSERT(isSSE2Present());
1857 if (cond & DoubleConditionBitInvert)
1858 m_assembler.ucomisd_rr(left, right);
1860 m_assembler.ucomisd_rr(right, left);
1862 if (cond == DoubleEqual) {
1863 if (left == right) {
1864 m_assembler.cmovnpl_rr(src, dest);
1868 Jump isUnordered(m_assembler.jp());
1869 m_assembler.cmovel_rr(src, dest);
1870 isUnordered.link(this);
1874 if (cond == DoubleNotEqualOrUnordered) {
1875 if (left == right) {
1876 m_assembler.cmovpl_rr(src, dest);
1880 m_assembler.cmovpl_rr(src, dest);
1881 m_assembler.cmovnel_rr(src, dest);
1885 ASSERT(!(cond & DoubleConditionBitSpecial));
1886 m_assembler.cmovl_rr(static_cast<X86Assembler::Condition>(cond & ~DoubleConditionBits), src, dest);
1889 void swap(RegisterID reg1, RegisterID reg2)
1892 m_assembler.xchgl_rr(reg1, reg2);
1895 void signExtend32ToPtr(RegisterID src, RegisterID dest)
1900 void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
1906 void swap32(RegisterID src, RegisterID dest)
1908 m_assembler.xchgl_rr(src, dest);
1911 void swap32(RegisterID src, Address dest)
1913 m_assembler.xchgl_rm(src, dest.offset, dest.base);
1916 void moveConditionally32(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID src, RegisterID dest)
1918 m_assembler.cmpl_rr(right, left);
1919 cmov(x86Condition(cond), src, dest);
1922 void moveConditionally32(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID thenCase, RegisterID elseCase, RegisterID dest)
1924 m_assembler.cmpl_rr(right, left);
1926 if (thenCase != dest && elseCase != dest) {
1927 move(elseCase, dest);
1931 if (elseCase == dest)
1932 cmov(x86Condition(cond), thenCase, dest);
1934 cmov(x86Condition(invert(cond)), elseCase, dest);
1937 void moveConditionally32(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID thenCase, RegisterID elseCase, RegisterID dest)
1939 if (!right.m_value) {
1940 if (auto resultCondition = commuteCompareToZeroIntoTest(cond)) {
1941 moveConditionallyTest32(*resultCondition, left, left, thenCase, elseCase, dest);
1946 m_assembler.cmpl_ir(right.m_value, left);
1948 if (thenCase != dest && elseCase != dest) {
1949 move(elseCase, dest);
1953 if (elseCase == dest)
1954 cmov(x86Condition(cond), thenCase, dest);
1956 cmov(x86Condition(invert(cond)), elseCase, dest);
1959 void moveConditionallyTest32(ResultCondition cond, RegisterID testReg, RegisterID mask, RegisterID src, RegisterID dest)
1961 m_assembler.testl_rr(testReg, mask);
1962 cmov(x86Condition(cond), src, dest);
1965 void moveConditionallyTest32(ResultCondition cond, RegisterID left, RegisterID right, RegisterID thenCase, RegisterID elseCase, RegisterID dest)
1967 ASSERT(isInvertible(cond));
1968 ASSERT_WITH_MESSAGE(cond != Overflow, "TEST does not set the Overflow Flag.");
1970 m_assembler.testl_rr(right, left);
1972 if (thenCase != dest && elseCase != dest) {
1973 move(elseCase, dest);
1977 if (elseCase == dest)
1978 cmov(x86Condition(cond), thenCase, dest);
1980 cmov(x86Condition(invert(cond)), elseCase, dest);
1983 void moveConditionallyTest32(ResultCondition cond, RegisterID testReg, TrustedImm32 mask, RegisterID src, RegisterID dest)
1985 test32(testReg, mask);
1986 cmov(x86Condition(cond), src, dest);
1989 void moveConditionallyTest32(ResultCondition cond, RegisterID testReg, TrustedImm32 mask, RegisterID thenCase, RegisterID elseCase, RegisterID dest)
1991 ASSERT(isInvertible(cond));
1992 ASSERT_WITH_MESSAGE(cond != Overflow, "TEST does not set the Overflow Flag.");
1994 test32(testReg, mask);
1996 if (thenCase != dest && elseCase != dest) {
1997 move(elseCase, dest);
2001 if (elseCase == dest)
2002 cmov(x86Condition(cond), thenCase, dest);
2004 cmov(x86Condition(invert(cond)), elseCase, dest);
2007 template<typename LeftType, typename RightType>
2008 void moveDoubleConditionally32(RelationalCondition cond, LeftType left, RightType right, FPRegisterID thenCase, FPRegisterID elseCase, FPRegisterID dest)
2010 static_assert(!std::is_same<LeftType, FPRegisterID>::value && !std::is_same<RightType, FPRegisterID>::value, "One of the tested argument could be aliased on dest. Use moveDoubleConditionallyDouble().");
2012 if (thenCase != dest && elseCase != dest) {
2013 moveDouble(elseCase, dest);
2017 if (elseCase == dest) {
2018 Jump falseCase = branch32(invert(cond), left, right);
2019 moveDouble(thenCase, dest);
2020 falseCase.link(this);
2022 Jump trueCase = branch32(cond, left, right);
2023 moveDouble(elseCase, dest);
2024 trueCase.link(this);
2028 template<typename TestType, typename MaskType>
2029 void moveDoubleConditionallyTest32(ResultCondition cond, TestType test, MaskType mask, FPRegisterID thenCase, FPRegisterID elseCase, FPRegisterID dest)
2031 static_assert(!std::is_same<TestType, FPRegisterID>::value && !std::is_same<MaskType, FPRegisterID>::value, "One of the tested argument could be aliased on dest. Use moveDoubleConditionallyDouble().");
2033 if (elseCase == dest && isInvertible(cond)) {
2034 Jump falseCase = branchTest32(invert(cond), test, mask);
2035 moveDouble(thenCase, dest);
2036 falseCase.link(this);
2037 } else if (thenCase == dest) {
2038 Jump trueCase = branchTest32(cond, test, mask);
2039 moveDouble(elseCase, dest);
2040 trueCase.link(this);
2043 Jump trueCase = branchTest32(cond, test, mask);
2044 moveDouble(elseCase, dest);
2045 Jump falseCase = jump();
2046 trueCase.link(this);
2047 moveDouble(thenCase, dest);
2048 falseCase.link(this);
2051 void moveDoubleConditionallyDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right, FPRegisterID thenCase, FPRegisterID elseCase, FPRegisterID dest)
2053 if (elseCase == dest) {
2054 Jump falseCase = branchDouble(invert(cond), left, right);
2055 moveDouble(thenCase, dest);
2056 falseCase.link(this);
2057 } else if (thenCase == dest) {
2058 Jump trueCase = branchDouble(cond, left, right);
2059 moveDouble(elseCase, dest);
2060 trueCase.link(this);
2062 Jump trueCase = branchDouble(cond, left, right);
2063 moveDouble(elseCase, dest);
2064 Jump falseCase = jump();
2065 trueCase.link(this);
2066 moveDouble(thenCase, dest);
2067 falseCase.link(this);
2071 void moveDoubleConditionallyFloat(DoubleCondition cond, FPRegisterID left, FPRegisterID right, FPRegisterID thenCase, FPRegisterID elseCase, FPRegisterID dest)
2073 if (elseCase == dest) {
2074 Jump falseCase = branchFloat(invert(cond), left, right);
2075 moveDouble(thenCase, dest);
2076 falseCase.link(this);
2077 } else if (thenCase == dest) {
2078 Jump trueCase = branchFloat(cond, left, right);
2079 moveDouble(elseCase, dest);
2080 trueCase.link(this);
2082 Jump trueCase = branchFloat(cond, left, right);
2083 moveDouble(elseCase, dest);
2084 Jump falseCase = jump();
2085 trueCase.link(this);
2086 moveDouble(thenCase, dest);
2087 falseCase.link(this);
2091 // Forwards / external control flow operations:
2093 // This set of jump and conditional branch operations return a Jump
2094 // object which may linked at a later point, allow forwards jump,
2095 // or jumps that will require external linkage (after the code has been
2098 // For branches, signed <, >, <= and >= are denoted as l, g, le, and ge
2099 // respecitvely, for unsigned comparisons the names b, a, be, and ae are
2100 // used (representing the names 'below' and 'above').
2102 // Operands to the comparision are provided in the expected order, e.g.
2103 // jle32(reg1, TrustedImm32(5)) will branch if the value held in reg1, when
2104 // treated as a signed 32bit value, is less than or equal to 5.
2106 // jz and jnz test whether the first operand is equal to zero, and take
2107 // an optional second operand of a mask under which to perform the test.
2110 Jump branch8(RelationalCondition cond, Address left, TrustedImm32 right)
2112 m_assembler.cmpb_im(right.m_value, left.offset, left.base);
2113 return Jump(m_assembler.jCC(x86Condition(cond)));
2116 Jump branch32(RelationalCondition cond, RegisterID left, RegisterID right)
2118 m_assembler.cmpl_rr(right, left);
2119 return Jump(m_assembler.jCC(x86Condition(cond)));
2122 Jump branch32(RelationalCondition cond, RegisterID left, TrustedImm32 right)
2124 if (!right.m_value) {
2125 if (auto resultCondition = commuteCompareToZeroIntoTest(cond))
2126 return branchTest32(*resultCondition, left, left);
2129 m_assembler.cmpl_ir(right.m_value, left);
2130 return Jump(m_assembler.jCC(x86Condition(cond)));
2133 Jump branch32(RelationalCondition cond, RegisterID left, Address right)
2135 m_assembler.cmpl_mr(right.offset, right.base, left);
2136 return Jump(m_assembler.jCC(x86Condition(cond)));
2139 Jump branch32(RelationalCondition cond, Address left, RegisterID right)
2141 m_assembler.cmpl_rm(right, left.offset, left.base);
2142 return Jump(m_assembler.jCC(x86Condition(cond)));
2145 Jump branch32(RelationalCondition cond, Address left, TrustedImm32 right)
2147 m_assembler.cmpl_im(right.m_value, left.offset, left.base);
2148 return Jump(m_assembler.jCC(x86Condition(cond)));
2151 Jump branch32(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
2153 m_assembler.cmpl_im(right.m_value, left.offset, left.base, left.index, left.scale);
2154 return Jump(m_assembler.jCC(x86Condition(cond)));
2157 Jump branch32WithUnalignedHalfWords(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
2159 return branch32(cond, left, right);
2162 Jump branchTest32(ResultCondition cond, RegisterID reg, RegisterID mask)
2164 m_assembler.testl_rr(reg, mask);
2165 return Jump(m_assembler.jCC(x86Condition(cond)));
2168 void test32(RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
2170 if (mask.m_value == -1)
2171 m_assembler.testl_rr(reg, reg);
2172 else if (!(mask.m_value & ~0xff) && reg < X86Registers::esp) { // Using esp and greater as a byte register yields the upper half of the 16 bit registers ax, cx, dx and bx, e.g. esp, register 4, is actually ah.
2173 if (mask.m_value == 0xff)
2174 m_assembler.testb_rr(reg, reg);
2176 m_assembler.testb_i8r(mask.m_value, reg);
2178 m_assembler.testl_i32r(mask.m_value, reg);
2181 Jump branch(ResultCondition cond)
2183 return Jump(m_assembler.jCC(x86Condition(cond)));
2186 Jump branchTest32(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
2189 return branch(cond);
2192 Jump branchTest32(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
2194 generateTest32(address, mask);
2195 return Jump(m_assembler.jCC(x86Condition(cond)));
2198 Jump branchTest32(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
2200 if (mask.m_value == -1)
2201 m_assembler.cmpl_im(0, address.offset, address.base, address.index, address.scale);
2203 m_assembler.testl_i32m(mask.m_value, address.offset, address.base, address.index, address.scale);
2204 return Jump(m_assembler.jCC(x86Condition(cond)));
2207 Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
2209 // Byte in TrustedImm32 is not well defined, so be a little permisive here, but don't accept nonsense values.
2210 ASSERT(mask.m_value >= -128 && mask.m_value <= 255);
2211 if (mask.m_value == -1)
2212 m_assembler.cmpb_im(0, address.offset, address.base);
2214 m_assembler.testb_im(mask.m_value, address.offset, address.base);
2215 return Jump(m_assembler.jCC(x86Condition(cond)));
2218 Jump branchTest8(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
2220 // Byte in TrustedImm32 is not well defined, so be a little permisive here, but don't accept nonsense values.
2221 ASSERT(mask.m_value >= -128 && mask.m_value <= 255);
2222 if (mask.m_value == -1)
2223 m_assembler.cmpb_im(0, address.offset, address.base, address.index, address.scale);
2225 m_assembler.testb_im(mask.m_value, address.offset, address.base, address.index, address.scale);
2226 return Jump(m_assembler.jCC(x86Condition(cond)));
2229 Jump branch8(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
2231 ASSERT(std::numeric_limits<int8_t>::min() <= right.m_value && right.m_value <= std::numeric_limits<int8_t>::max());
2233 m_assembler.cmpb_im(right.m_value, left.offset, left.base, left.index, left.scale);
2234 return Jump(m_assembler.jCC(x86Condition(cond)));
2239 return Jump(m_assembler.jmp());
2242 void jump(RegisterID target)
2244 m_assembler.jmp_r(target);
2247 // Address is a memory location containing the address to jump to
2248 void jump(Address address)
2250 m_assembler.jmp_m(address.offset, address.base);
2254 // Arithmetic control flow operations:
2256 // This set of conditional branch operations branch based
2257 // on the result of an arithmetic operation. The operation
2258 // is performed as normal, storing the result.
2260 // * jz operations branch if the result is zero.
2261 // * jo operations branch if the (signed) arithmetic
2262 // operation caused an overflow to occur.
2264 Jump branchAdd32(ResultCondition cond, RegisterID src, RegisterID dest)
2267 return Jump(m_assembler.jCC(x86Condition(cond)));
2270 Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
2273 return Jump(m_assembler.jCC(x86Condition(cond)));
2276 Jump branchAdd32(ResultCondition cond, TrustedImm32 src, Address dest)
2279 return Jump(m_assembler.jCC(x86Condition(cond)));
2282 Jump branchAdd32(ResultCondition cond, RegisterID src, Address dest)
2285 return Jump(m_assembler.jCC(x86Condition(cond)));
2288 Jump branchAdd32(ResultCondition cond, Address src, RegisterID dest)
2291 return Jump(m_assembler.jCC(x86Condition(cond)));
2294 Jump branchAdd32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest)
2297 return branchAdd32(cond, src2, dest);
2298 move32IfNeeded(src2, dest);
2299 return branchAdd32(cond, src1, dest);
2302 Jump branchAdd32(ResultCondition cond, Address op1, RegisterID op2, RegisterID dest)
2305 return branchAdd32(cond, op1, dest);
2306 if (op1.base == dest) {
2308 return branchAdd32(cond, op2, dest);
2310 zeroExtend32ToPtr(op2, dest);
2311 return branchAdd32(cond, op1, dest);
2314 Jump branchAdd32(ResultCondition cond, RegisterID src1, Address src2, RegisterID dest)
2316 return branchAdd32(cond, src2, src1, dest);
2319 Jump branchAdd32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest)
2321 move32IfNeeded(src, dest);
2322 return branchAdd32(cond, imm, dest);
2325 Jump branchMul32(ResultCondition cond, RegisterID src, RegisterID dest)
2328 if (cond != Overflow)
2329 m_assembler.testl_rr(dest, dest);
2330 return Jump(m_assembler.jCC(x86Condition(cond)));
2333 Jump branchMul32(ResultCondition cond, Address src, RegisterID dest)
2336 if (cond != Overflow)
2337 m_assembler.testl_rr(dest, dest);
2338 return Jump(m_assembler.jCC(x86Condition(cond)));
2341 Jump branchMul32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest)
2343 mul32(imm, src, dest);
2344 if (cond != Overflow)
2345 m_assembler.testl_rr(dest, dest);
2346 return Jump(m_assembler.jCC(x86Condition(cond)));
2349 Jump branchMul32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest)
2352 return branchMul32(cond, src2, dest);
2353 move32IfNeeded(src2, dest);
2354 return branchMul32(cond, src1, dest);
2357 Jump branchSub32(ResultCondition cond, RegisterID src, RegisterID dest)
2360 return Jump(m_assembler.jCC(x86Condition(cond)));
2363 Jump branchSub32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
2366 return Jump(m_assembler.jCC(x86Condition(cond)));
2369 Jump branchSub32(ResultCondition cond, TrustedImm32 imm, Address dest)
2372 return Jump(m_assembler.jCC(x86Condition(cond)));
2375 Jump branchSub32(ResultCondition cond, RegisterID src, Address dest)
2378 return Jump(m_assembler.jCC(x86Condition(cond)));
2381 Jump branchSub32(ResultCondition cond, Address src, RegisterID dest)
2384 return Jump(m_assembler.jCC(x86Condition(cond)));
2387 Jump branchSub32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest)
2389 // B := A - B is invalid.
2390 ASSERT(src1 == dest || src2 != dest);
2392 move32IfNeeded(src1, dest);
2393 return branchSub32(cond, src2, dest);
2396 Jump branchSub32(ResultCondition cond, RegisterID src1, TrustedImm32 src2, RegisterID dest)
2398 move32IfNeeded(src1, dest);
2399 return branchSub32(cond, src2, dest);
2402 Jump branchNeg32(ResultCondition cond, RegisterID srcDest)
2405 return Jump(m_assembler.jCC(x86Condition(cond)));
2408 Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest)
2411 return Jump(m_assembler.jCC(x86Condition(cond)));
2415 // Miscellaneous operations:
2424 return Call(m_assembler.jmp(), Call::LinkableNearTail);
2429 return Call(m_assembler.call(), Call::LinkableNear);
2432 Call call(RegisterID target)
2434 return Call(m_assembler.call(target), Call::None);
2437 void call(Address address)
2439 m_assembler.call_m(address.offset, address.base);
2447 void compare8(RelationalCondition cond, Address left, TrustedImm32 right, RegisterID dest)
2449 m_assembler.cmpb_im(right.m_value, left.offset, left.base);
2450 set32(x86Condition(cond), dest);
2453 void compare32(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID dest)
2455 m_assembler.cmpl_rr(right, left);
2456 set32(x86Condition(cond), dest);
2459 void compare32(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
2461 if (!right.m_value) {
2462 if (auto resultCondition = commuteCompareToZeroIntoTest(cond)) {
2463 test32(*resultCondition, left, left, dest);
2468 m_assembler.cmpl_ir(right.m_value, left);
2469 set32(x86Condition(cond), dest);
2473 // The mask should be optional... perhaps the argument order should be
2474 // dest-src, operations always have a dest? ... possibly not true, considering
2475 // asm ops like test, or pseudo ops like pop().
2477 void test8(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest)
2479 if (mask.m_value == -1)
2480 m_assembler.cmpb_im(0, address.offset, address.base);
2482 m_assembler.testb_im(mask.m_value, address.offset, address.base);
2483 set32(x86Condition(cond), dest);
2486 void test32(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest)
2488 generateTest32(address, mask);
2489 set32(x86Condition(cond), dest);
2492 void test32(ResultCondition cond, RegisterID reg, RegisterID mask, RegisterID dest)
2494 m_assembler.testl_rr(reg, mask);
2495 set32(x86Condition(cond), dest);
2498 void test32(ResultCondition cond, RegisterID reg, TrustedImm32 mask, RegisterID dest)
2501 set32(x86Condition(cond), dest);
2504 void setCarry(RegisterID dest)
2506 set32(X86Assembler::ConditionC, dest);
2509 // Invert a relational condition, e.g. == becomes !=, < becomes >=, etc.
2510 static RelationalCondition invert(RelationalCondition cond)
2512 return static_cast<RelationalCondition>(cond ^ 1);
2515 static DoubleCondition invert(DoubleCondition cond)
2519 return DoubleNotEqualOrUnordered;
2520 case DoubleNotEqual:
2521 return DoubleEqualOrUnordered;
2522 case DoubleGreaterThan:
2523 return DoubleLessThanOrEqualOrUnordered;
2524 case DoubleGreaterThanOrEqual:
2525 return DoubleLessThanOrUnordered;
2526 case DoubleLessThan:
2527 return DoubleGreaterThanOrEqualOrUnordered;
2528 case DoubleLessThanOrEqual:
2529 return DoubleGreaterThanOrUnordered;
2530 case DoubleEqualOrUnordered:
2531 return DoubleNotEqual;
2532 case DoubleNotEqualOrUnordered:
2534 case DoubleGreaterThanOrUnordered:
2535 return DoubleLessThanOrEqual;
2536 case DoubleGreaterThanOrEqualOrUnordered:
2537 return DoubleLessThan;
2538 case DoubleLessThanOrUnordered:
2539 return DoubleGreaterThanOrEqual;
2540 case DoubleLessThanOrEqualOrUnordered:
2541 return DoubleGreaterThan;
2543 RELEASE_ASSERT_NOT_REACHED();
2544 return DoubleEqual; // make compiler happy
2547 static bool isInvertible(ResultCondition cond)
2553 case PositiveOrZero:
2560 static ResultCondition invert(ResultCondition cond)
2568 return PositiveOrZero;
2569 case PositiveOrZero:
2572 RELEASE_ASSERT_NOT_REACHED();
2573 return Zero; // Make compiler happy for release builds.
2577 static Optional<ResultCondition> commuteCompareToZeroIntoTest(RelationalCondition cond)
2586 case GreaterThanOrEqual:
2587 return PositiveOrZero;
2601 m_assembler.mfence();
2604 static void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination)
2606 X86Assembler::replaceWithJump(instructionStart.executableAddress(), destination.executableAddress());
2609 static ptrdiff_t maxJumpReplacementSize()
2611 return X86Assembler::maxJumpReplacementSize();
2614 static bool supportsFloatingPointRounding()
2616 if (s_sse4_1CheckState == CPUIDCheckState::NotChecked)
2617 updateEax1EcxFlags();
2618 return s_sse4_1CheckState == CPUIDCheckState::Set;
2621 static bool supportsAVX()
2623 // AVX still causes mysterious regressions and those regressions can be massive.
2627 static void updateEax1EcxFlags()
2632 __cpuid(cpuInfo, 0x1);
2634 #elif COMPILER(GCC_OR_CLANG)
2642 : "%eax", "%ebx", "%ecx", "%edx"
2653 : "%eax", "%ecx", "%edx"
2656 #endif // COMPILER(GCC_OR_CLANG)
2657 s_sse4_1CheckState = (flags & (1 << 19)) ? CPUIDCheckState::Set : CPUIDCheckState::Clear;
2658 s_avxCheckState = (flags & (1 << 28)) ? CPUIDCheckState::Set : CPUIDCheckState::Clear;
2661 #if ENABLE(MASM_PROBE)
2662 void probe(ProbeFunction, void* arg1, void* arg2);
2663 #endif // ENABLE(MASM_PROBE)
2666 X86Assembler::Condition x86Condition(RelationalCondition cond)
2668 return static_cast<X86Assembler::Condition>(cond);
2671 X86Assembler::Condition x86Condition(ResultCondition cond)
2673 return static_cast<X86Assembler::Condition>(cond);
2676 void set32(X86Assembler::Condition cond, RegisterID dest)
2679 // On 32-bit x86 we can only set the first 4 registers;
2680 // esp..edi are mapped to the 'h' registers!
2682 m_assembler.xchgl_rr(dest, X86Registers::eax);
2683 m_assembler.setCC_r(cond, X86Registers::eax);
2684 m_assembler.movzbl_rr(X86Registers::eax, X86Registers::eax);
2685 m_assembler.xchgl_rr(dest, X86Registers::eax);
2689 m_assembler.setCC_r(cond, dest);
2690 m_assembler.movzbl_rr(dest, dest);
2693 void cmov(X86Assembler::Condition cond, RegisterID src, RegisterID dest)
2696 m_assembler.cmovq_rr(cond, src, dest);
2698 m_assembler.cmovl_rr(cond, src, dest);
2702 static bool supportsLZCNT()
2704 if (s_lzcntCheckState == CPUIDCheckState::NotChecked) {
2708 __cpuid(cpuInfo, 0x80000001);
2710 #elif COMPILER(GCC_OR_CLANG)
2713 "movl $0x80000001, %%eax;"
2718 : "%eax", "%ebx", "%ecx", "%edx"
2722 "movl $0x80000001, %%eax;"
2729 : "%eax", "%ecx", "%edx"
2732 #endif // COMPILER(GCC_OR_CLANG)
2733 s_lzcntCheckState = (flags & 0x20) ? CPUIDCheckState::Set : CPUIDCheckState::Clear;
2735 return s_lzcntCheckState == CPUIDCheckState::Set;
2739 // Only MacroAssemblerX86 should be using the following method; SSE2 is always available on
2740 // x86_64, and clients & subclasses of MacroAssembler should be using 'supportsFloatingPoint()'.
2741 friend class MacroAssemblerX86;
2743 ALWAYS_INLINE void generateTest32(Address address, TrustedImm32 mask = TrustedImm32(-1))
2745 if (mask.m_value == -1)
2746 m_assembler.cmpl_im(0, address.offset, address.base);
2747 else if (!(mask.m_value & ~0xff))
2748 m_assembler.testb_im(mask.m_value, address.offset, address.base);
2749 else if (!(mask.m_value & ~0xff00))
2750 m_assembler.testb_im(mask.m_value >> 8, address.offset + 1, address.base);
2751 else if (!(mask.m_value & ~0xff0000))
2752 m_assembler.testb_im(mask.m_value >> 16, address.offset + 2, address.base);
2753 else if (!(mask.m_value & ~0xff000000))
2754 m_assembler.testb_im(mask.m_value >> 24, address.offset + 3, address.base);
2756 m_assembler.testl_i32m(mask.m_value, address.offset, address.base);
2759 // If lzcnt is not available, use this after BSR
2760 // to count the leading zeros.
2761 void clz32AfterBsr(RegisterID dst)
2763 Jump srcIsNonZero = m_assembler.jCC(x86Condition(NonZero));
2764 move(TrustedImm32(32), dst);
2766 Jump skipNonZeroCase = jump();
2767 srcIsNonZero.link(this);
2768 xor32(TrustedImm32(0x1f), dst);
2769 skipNonZeroCase.link(this);
2772 Jump jumpAfterFloatingPointCompare(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
2774 if (cond == DoubleEqual) {
2776 return Jump(m_assembler.jnp());
2777 Jump isUnordered(m_assembler.jp());
2778 Jump result = Jump(m_assembler.je());
2779 isUnordered.link(this);
2782 if (cond == DoubleNotEqualOrUnordered) {
2784 return Jump(m_assembler.jp());
2785 Jump isUnordered(m_assembler.jp());
2786 Jump isEqual(m_assembler.je());
2787 isUnordered.link(this);
2788 Jump result = jump();
2793 ASSERT(!(cond & DoubleConditionBitSpecial));
2794 return Jump(m_assembler.jCC(static_cast<X86Assembler::Condition>(cond & ~DoubleConditionBits)));
2797 // The 32bit Move does not need the REX byte for low registers, making it shorter.
2798 // Use this if the top bits are irrelevant because they will be reset by the next instruction.
2799 void move32IfNeeded(RegisterID src, RegisterID dest)
2803 m_assembler.movl_rr(src, dest);
2807 void moveConditionallyAfterFloatingPointCompare(DoubleCondition cond, FPRegisterID left, FPRegisterID right, RegisterID src, RegisterID dest)
2809 if (cond == DoubleEqual) {
2810 if (left == right) {
2811 m_assembler.cmovnpq_rr(src, dest);
2815 Jump isUnordered(m_assembler.jp());
2816 m_assembler.cmoveq_rr(src, dest);
2817 isUnordered.link(this);
2821 if (cond == DoubleNotEqualOrUnordered) {
2822 if (left == right) {
2823 m_assembler.cmovpq_rr(src, dest);
2827 m_assembler.cmovpq_rr(src, dest);
2828 m_assembler.cmovneq_rr(src, dest);
2832 ASSERT(!(cond & DoubleConditionBitSpecial));
2833 cmov(static_cast<X86Assembler::Condition>(cond & ~DoubleConditionBits), src, dest);
2840 // All X86 Macs are guaranteed to support at least SSE2,
2841 static bool isSSE2Present()
2846 #else // OS(MAC_OS_X)
2848 enum SSE2CheckState {
2854 static bool isSSE2Present()
2856 if (s_sse2CheckState == NotCheckedSSE2) {
2857 // Default the flags value to zero; if the compiler is
2858 // not MSVC or GCC we will read this as SSE2 not present.
2862 mov eax, 1 // cpuid function 1 gives us the standard feature set
2866 #elif COMPILER(GCC_OR_CLANG)
2875 : "%eax", "%ecx", "%edx"
2878 static const int SSE2FeatureBit = 1 << 26;
2879 s_sse2CheckState = (flags & SSE2FeatureBit) ? HasSSE2 : NoSSE2;
2882 ASSERT(s_sse2CheckState != NotCheckedSSE2);
2884 return s_sse2CheckState == HasSSE2;
2887 static SSE2CheckState s_sse2CheckState;
2889 #endif // OS(MAC_OS_X)
2890 #elif !defined(NDEBUG) // CPU(X86)
2892 // On x86-64 we should never be checking for SSE2 in a non-debug build,
2893 // but non debug add this method to keep the asserts above happy.
2894 static bool isSSE2Present()
2901 enum class CPUIDCheckState {
2906 JS_EXPORT_PRIVATE static CPUIDCheckState s_sse4_1CheckState;
2907 JS_EXPORT_PRIVATE static CPUIDCheckState s_avxCheckState;
2908 static CPUIDCheckState s_lzcntCheckState;
2913 #endif // ENABLE(ASSEMBLER)
2915 #endif // MacroAssemblerX86Common_h