2 * Copyright (C) 2008 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"
36 class MacroAssemblerX86Common : public AbstractMacroAssembler<X86Assembler> {
39 static const X86Registers::RegisterID scratchRegister = X86Registers::r11;
42 static const int DoubleConditionBitInvert = 0x10;
43 static const int DoubleConditionBitSpecial = 0x20;
44 static const int DoubleConditionBits = DoubleConditionBitInvert | DoubleConditionBitSpecial;
47 typedef X86Assembler::FPRegisterID FPRegisterID;
48 typedef X86Assembler::XMMRegisterID XMMRegisterID;
50 static bool isCompactPtrAlignedAddressOffset(ptrdiff_t value)
52 return value >= -128 && value <= 127;
55 enum RelationalCondition {
56 Equal = X86Assembler::ConditionE,
57 NotEqual = X86Assembler::ConditionNE,
58 Above = X86Assembler::ConditionA,
59 AboveOrEqual = X86Assembler::ConditionAE,
60 Below = X86Assembler::ConditionB,
61 BelowOrEqual = X86Assembler::ConditionBE,
62 GreaterThan = X86Assembler::ConditionG,
63 GreaterThanOrEqual = X86Assembler::ConditionGE,
64 LessThan = X86Assembler::ConditionL,
65 LessThanOrEqual = X86Assembler::ConditionLE
68 enum ResultCondition {
69 Overflow = X86Assembler::ConditionO,
70 Signed = X86Assembler::ConditionS,
71 Zero = X86Assembler::ConditionE,
72 NonZero = X86Assembler::ConditionNE
75 enum DoubleCondition {
76 // These conditions will only evaluate to true if the comparison is ordered - i.e. neither operand is NaN.
77 DoubleEqual = X86Assembler::ConditionE | DoubleConditionBitSpecial,
78 DoubleNotEqual = X86Assembler::ConditionNE,
79 DoubleGreaterThan = X86Assembler::ConditionA,
80 DoubleGreaterThanOrEqual = X86Assembler::ConditionAE,
81 DoubleLessThan = X86Assembler::ConditionA | DoubleConditionBitInvert,
82 DoubleLessThanOrEqual = X86Assembler::ConditionAE | DoubleConditionBitInvert,
83 // If either operand is NaN, these conditions always evaluate to true.
84 DoubleEqualOrUnordered = X86Assembler::ConditionE,
85 DoubleNotEqualOrUnordered = X86Assembler::ConditionNE | DoubleConditionBitSpecial,
86 DoubleGreaterThanOrUnordered = X86Assembler::ConditionB | DoubleConditionBitInvert,
87 DoubleGreaterThanOrEqualOrUnordered = X86Assembler::ConditionBE | DoubleConditionBitInvert,
88 DoubleLessThanOrUnordered = X86Assembler::ConditionB,
89 DoubleLessThanOrEqualOrUnordered = X86Assembler::ConditionBE,
92 !((X86Assembler::ConditionE | X86Assembler::ConditionNE | X86Assembler::ConditionA | X86Assembler::ConditionAE | X86Assembler::ConditionB | X86Assembler::ConditionBE) & DoubleConditionBits),
93 DoubleConditionBits_should_not_interfere_with_X86Assembler_Condition_codes);
95 static const RegisterID stackPointerRegister = X86Registers::esp;
97 #if ENABLE(JIT_CONSTANT_BLINDING)
98 static bool shouldBlindForSpecificArch(uint32_t value) { return value >= 0x00ffffff; }
100 static bool shouldBlindForSpecificArch(uintptr_t value) { return value >= 0x00ffffff; }
104 // Integer arithmetic operations:
106 // Operations are typically two operand - operation(source, srcDst)
107 // For many operations the source may be an TrustedImm32, the srcDst operand
108 // may often be a memory location (explictly described using an Address
111 void add32(RegisterID src, RegisterID dest)
113 m_assembler.addl_rr(src, dest);
116 void add32(TrustedImm32 imm, Address address)
118 m_assembler.addl_im(imm.m_value, address.offset, address.base);
121 void add32(TrustedImm32 imm, RegisterID dest)
123 m_assembler.addl_ir(imm.m_value, dest);
126 void add32(Address src, RegisterID dest)
128 m_assembler.addl_mr(src.offset, src.base, dest);
131 void add32(RegisterID src, Address dest)
133 m_assembler.addl_rm(src, dest.offset, dest.base);
136 void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
138 m_assembler.leal_mr(imm.m_value, src, dest);
141 void and32(RegisterID src, RegisterID dest)
143 m_assembler.andl_rr(src, dest);
146 void and32(TrustedImm32 imm, RegisterID dest)
148 m_assembler.andl_ir(imm.m_value, dest);
151 void and32(RegisterID src, Address dest)
153 m_assembler.andl_rm(src, dest.offset, dest.base);
156 void and32(Address src, RegisterID dest)
158 m_assembler.andl_mr(src.offset, src.base, dest);
161 void and32(TrustedImm32 imm, Address address)
163 m_assembler.andl_im(imm.m_value, address.offset, address.base);
166 void and32(RegisterID op1, RegisterID op2, RegisterID dest)
169 zeroExtend32ToPtr(op1, dest);
170 else if (op1 == dest)
178 void and32(TrustedImm32 imm, RegisterID src, RegisterID dest)
184 void lshift32(RegisterID shift_amount, RegisterID dest)
186 ASSERT(shift_amount != dest);
188 if (shift_amount == X86Registers::ecx)
189 m_assembler.shll_CLr(dest);
191 // On x86 we can only shift by ecx; if asked to shift by another register we'll
192 // need rejig the shift amount into ecx first, and restore the registers afterwards.
193 // If we dest is ecx, then shift the swapped register!
194 swap(shift_amount, X86Registers::ecx);
195 m_assembler.shll_CLr(dest == X86Registers::ecx ? shift_amount : dest);
196 swap(shift_amount, X86Registers::ecx);
200 void lshift32(RegisterID src, RegisterID shift_amount, RegisterID dest)
202 ASSERT(shift_amount != dest);
206 lshift32(shift_amount, dest);
209 void lshift32(TrustedImm32 imm, RegisterID dest)
211 m_assembler.shll_i8r(imm.m_value, dest);
214 void lshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
221 void mul32(RegisterID src, RegisterID dest)
223 m_assembler.imull_rr(src, dest);
226 void mul32(Address src, RegisterID dest)
228 m_assembler.imull_mr(src.offset, src.base, dest);
231 void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest)
233 m_assembler.imull_i32r(src, imm.m_value, dest);
236 void neg32(RegisterID srcDest)
238 m_assembler.negl_r(srcDest);
241 void neg32(Address srcDest)
243 m_assembler.negl_m(srcDest.offset, srcDest.base);
246 void or32(RegisterID src, RegisterID dest)
248 m_assembler.orl_rr(src, dest);
251 void or32(TrustedImm32 imm, RegisterID dest)
253 m_assembler.orl_ir(imm.m_value, dest);
256 void or32(RegisterID src, Address dest)
258 m_assembler.orl_rm(src, dest.offset, dest.base);
261 void or32(Address src, RegisterID dest)
263 m_assembler.orl_mr(src.offset, src.base, dest);
266 void or32(TrustedImm32 imm, Address address)
268 m_assembler.orl_im(imm.m_value, address.offset, address.base);
271 void or32(RegisterID op1, RegisterID op2, RegisterID dest)
274 zeroExtend32ToPtr(op1, dest);
275 else if (op1 == dest)
283 void or32(TrustedImm32 imm, RegisterID src, RegisterID dest)
289 void rshift32(RegisterID shift_amount, RegisterID dest)
291 ASSERT(shift_amount != dest);
293 if (shift_amount == X86Registers::ecx)
294 m_assembler.sarl_CLr(dest);
296 // On x86 we can only shift by ecx; if asked to shift by another register we'll
297 // need rejig the shift amount into ecx first, and restore the registers afterwards.
298 // If we dest is ecx, then shift the swapped register!
299 swap(shift_amount, X86Registers::ecx);
300 m_assembler.sarl_CLr(dest == X86Registers::ecx ? shift_amount : dest);
301 swap(shift_amount, X86Registers::ecx);
305 void rshift32(RegisterID src, RegisterID shift_amount, RegisterID dest)
307 ASSERT(shift_amount != dest);
311 rshift32(shift_amount, dest);
314 void rshift32(TrustedImm32 imm, RegisterID dest)
316 m_assembler.sarl_i8r(imm.m_value, dest);
319 void rshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
326 void urshift32(RegisterID shift_amount, RegisterID dest)
328 ASSERT(shift_amount != dest);
330 if (shift_amount == X86Registers::ecx)
331 m_assembler.shrl_CLr(dest);
333 // On x86 we can only shift by ecx; if asked to shift by another register we'll
334 // need rejig the shift amount into ecx first, and restore the registers afterwards.
335 // If we dest is ecx, then shift the swapped register!
336 swap(shift_amount, X86Registers::ecx);
337 m_assembler.shrl_CLr(dest == X86Registers::ecx ? shift_amount : dest);
338 swap(shift_amount, X86Registers::ecx);
342 void urshift32(RegisterID src, RegisterID shift_amount, RegisterID dest)
344 ASSERT(shift_amount != dest);
348 urshift32(shift_amount, dest);
351 void urshift32(TrustedImm32 imm, RegisterID dest)
353 m_assembler.shrl_i8r(imm.m_value, dest);
356 void urshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
360 urshift32(imm, dest);
363 void sub32(RegisterID src, RegisterID dest)
365 m_assembler.subl_rr(src, dest);
368 void sub32(TrustedImm32 imm, RegisterID dest)
370 m_assembler.subl_ir(imm.m_value, dest);
373 void sub32(TrustedImm32 imm, Address address)
375 m_assembler.subl_im(imm.m_value, address.offset, address.base);
378 void sub32(Address src, RegisterID dest)
380 m_assembler.subl_mr(src.offset, src.base, dest);
383 void sub32(RegisterID src, Address dest)
385 m_assembler.subl_rm(src, dest.offset, dest.base);
388 void xor32(RegisterID src, RegisterID dest)
390 m_assembler.xorl_rr(src, dest);
393 void xor32(TrustedImm32 imm, Address dest)
395 if (imm.m_value == -1)
396 m_assembler.notl_m(dest.offset, dest.base);
398 m_assembler.xorl_im(imm.m_value, dest.offset, dest.base);
401 void xor32(TrustedImm32 imm, RegisterID dest)
403 if (imm.m_value == -1)
404 m_assembler.notl_r(dest);
406 m_assembler.xorl_ir(imm.m_value, dest);
409 void xor32(RegisterID src, Address dest)
411 m_assembler.xorl_rm(src, dest.offset, dest.base);
414 void xor32(Address src, RegisterID dest)
416 m_assembler.xorl_mr(src.offset, src.base, dest);
419 void xor32(RegisterID op1, RegisterID op2, RegisterID dest)
422 move(TrustedImm32(0), dest);
423 else if (op1 == dest)
431 void xor32(TrustedImm32 imm, RegisterID src, RegisterID dest)
437 void sqrtDouble(FPRegisterID src, FPRegisterID dst)
439 m_assembler.sqrtsd_rr(src, dst);
442 void absDouble(FPRegisterID src, FPRegisterID dst)
445 static const double negativeZeroConstant = -0.0;
446 loadDouble(&negativeZeroConstant, dst);
447 m_assembler.andnpd_rr(src, dst);
450 void negateDouble(FPRegisterID src, FPRegisterID dst)
453 static const double negativeZeroConstant = -0.0;
454 loadDouble(&negativeZeroConstant, dst);
455 m_assembler.xorpd_rr(src, dst);
459 // Memory access operations:
461 // Loads are of the form load(address, destination) and stores of the form
462 // store(source, address). The source for a store may be an TrustedImm32. Address
463 // operand objects to loads and store will be implicitly constructed if a
464 // register is passed.
466 void load32(ImplicitAddress address, RegisterID dest)
468 m_assembler.movl_mr(address.offset, address.base, dest);
471 void load32(BaseIndex address, RegisterID dest)
473 m_assembler.movl_mr(address.offset, address.base, address.index, address.scale, dest);
476 void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
478 load32(address, dest);
481 void load16Unaligned(BaseIndex address, RegisterID dest)
483 load16(address, dest);
486 DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
488 m_assembler.movl_mr_disp32(address.offset, address.base, dest);
489 return DataLabel32(this);
492 DataLabelCompact load32WithCompactAddressOffsetPatch(Address address, RegisterID dest)
494 m_assembler.movl_mr_disp8(address.offset, address.base, dest);
495 return DataLabelCompact(this);
498 static void repatchCompact(CodeLocationDataLabelCompact dataLabelCompact, int32_t value)
500 ASSERT(isCompactPtrAlignedAddressOffset(value));
501 AssemblerType_T::repatchCompact(dataLabelCompact.dataLocation(), value);
504 DataLabelCompact loadCompactWithAddressOffsetPatch(Address address, RegisterID dest)
506 m_assembler.movl_mr_disp8(address.offset, address.base, dest);
507 return DataLabelCompact(this);
510 void load8(BaseIndex address, RegisterID dest)
512 m_assembler.movzbl_mr(address.offset, address.base, address.index, address.scale, dest);
515 void load8(ImplicitAddress address, RegisterID dest)
517 m_assembler.movzbl_mr(address.offset, address.base, dest);
520 void load8Signed(BaseIndex address, RegisterID dest)
522 m_assembler.movsbl_mr(address.offset, address.base, address.index, address.scale, dest);
525 void load8Signed(ImplicitAddress address, RegisterID dest)
527 m_assembler.movsbl_mr(address.offset, address.base, dest);
530 void load16(BaseIndex address, RegisterID dest)
532 m_assembler.movzwl_mr(address.offset, address.base, address.index, address.scale, dest);
535 void load16(Address address, RegisterID dest)
537 m_assembler.movzwl_mr(address.offset, address.base, dest);
540 void load16Signed(BaseIndex address, RegisterID dest)
542 m_assembler.movswl_mr(address.offset, address.base, address.index, address.scale, dest);
545 void load16Signed(Address address, RegisterID dest)
547 m_assembler.movswl_mr(address.offset, address.base, dest);
550 DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
552 m_assembler.movl_rm_disp32(src, address.offset, address.base);
553 return DataLabel32(this);
556 void store32(RegisterID src, ImplicitAddress address)
558 m_assembler.movl_rm(src, address.offset, address.base);
561 void store32(RegisterID src, BaseIndex address)
563 m_assembler.movl_rm(src, address.offset, address.base, address.index, address.scale);
566 void store32(TrustedImm32 imm, ImplicitAddress address)
568 m_assembler.movl_i32m(imm.m_value, address.offset, address.base);
571 void store32(TrustedImm32 imm, BaseIndex address)
573 m_assembler.movl_i32m(imm.m_value, address.offset, address.base, address.index, address.scale);
576 void store8(TrustedImm32 imm, Address address)
578 ASSERT(-128 <= imm.m_value && imm.m_value < 128);
579 m_assembler.movb_i8m(imm.m_value, address.offset, address.base);
582 void store8(TrustedImm32 imm, BaseIndex address)
584 ASSERT(-128 <= imm.m_value && imm.m_value < 128);
585 m_assembler.movb_i8m(imm.m_value, address.offset, address.base, address.index, address.scale);
588 void store8(RegisterID src, BaseIndex address)
591 // On 32-bit x86 we can only store from the first 4 registers;
592 // esp..edi are mapped to the 'h' registers!
594 // Pick a temporary register.
596 if (address.base != X86Registers::eax && address.index != X86Registers::eax)
597 temp = X86Registers::eax;
598 else if (address.base != X86Registers::ebx && address.index != X86Registers::ebx)
599 temp = X86Registers::ebx;
601 ASSERT(address.base != X86Registers::ecx && address.index != X86Registers::ecx);
602 temp = X86Registers::ecx;
605 // Swap to the temporary register to perform the store.
607 m_assembler.movb_rm(temp, address.offset, address.base, address.index, address.scale);
612 m_assembler.movb_rm(src, address.offset, address.base, address.index, address.scale);
615 void store16(RegisterID src, BaseIndex address)
618 // On 32-bit x86 we can only store from the first 4 registers;
619 // esp..edi are mapped to the 'h' registers!
621 // Pick a temporary register.
623 if (address.base != X86Registers::eax && address.index != X86Registers::eax)
624 temp = X86Registers::eax;
625 else if (address.base != X86Registers::ebx && address.index != X86Registers::ebx)
626 temp = X86Registers::ebx;
628 ASSERT(address.base != X86Registers::ecx && address.index != X86Registers::ecx);
629 temp = X86Registers::ecx;
632 // Swap to the temporary register to perform the store.
634 m_assembler.movw_rm(temp, address.offset, address.base, address.index, address.scale);
639 m_assembler.movw_rm(src, address.offset, address.base, address.index, address.scale);
643 // Floating-point operation:
645 // Presently only supports SSE, not x87 floating point.
647 void moveDouble(FPRegisterID src, FPRegisterID dest)
649 ASSERT(isSSE2Present());
651 m_assembler.movsd_rr(src, dest);
654 void loadDouble(const void* address, FPRegisterID dest)
657 ASSERT(isSSE2Present());
658 m_assembler.movsd_mr(address, dest);
660 move(TrustedImmPtr(address), scratchRegister);
661 loadDouble(scratchRegister, dest);
665 void loadDouble(ImplicitAddress address, FPRegisterID dest)
667 ASSERT(isSSE2Present());
668 m_assembler.movsd_mr(address.offset, address.base, dest);
671 void loadDouble(BaseIndex address, FPRegisterID dest)
673 ASSERT(isSSE2Present());
674 m_assembler.movsd_mr(address.offset, address.base, address.index, address.scale, dest);
676 void loadFloat(BaseIndex address, FPRegisterID dest)
678 ASSERT(isSSE2Present());
679 m_assembler.movss_mr(address.offset, address.base, address.index, address.scale, dest);
682 void storeDouble(FPRegisterID src, ImplicitAddress address)
684 ASSERT(isSSE2Present());
685 m_assembler.movsd_rm(src, address.offset, address.base);
688 void storeDouble(FPRegisterID src, BaseIndex address)
690 ASSERT(isSSE2Present());
691 m_assembler.movsd_rm(src, address.offset, address.base, address.index, address.scale);
694 void storeFloat(FPRegisterID src, BaseIndex address)
696 ASSERT(isSSE2Present());
697 m_assembler.movss_rm(src, address.offset, address.base, address.index, address.scale);
700 void convertDoubleToFloat(FPRegisterID src, FPRegisterID dst)
702 ASSERT(isSSE2Present());
703 m_assembler.cvtsd2ss_rr(src, dst);
706 void convertFloatToDouble(FPRegisterID src, FPRegisterID dst)
708 ASSERT(isSSE2Present());
709 m_assembler.cvtss2sd_rr(src, dst);
712 void addDouble(FPRegisterID src, FPRegisterID dest)
714 ASSERT(isSSE2Present());
715 m_assembler.addsd_rr(src, dest);
718 void addDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
720 ASSERT(isSSE2Present());
722 addDouble(op2, dest);
724 moveDouble(op2, dest);
725 addDouble(op1, dest);
729 void addDouble(Address src, FPRegisterID dest)
731 ASSERT(isSSE2Present());
732 m_assembler.addsd_mr(src.offset, src.base, dest);
735 void divDouble(FPRegisterID src, FPRegisterID dest)
737 ASSERT(isSSE2Present());
738 m_assembler.divsd_rr(src, dest);
741 void divDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
743 // B := A / B is invalid.
744 ASSERT(op1 == dest || op2 != dest);
746 moveDouble(op1, dest);
747 divDouble(op2, dest);
750 void divDouble(Address src, FPRegisterID dest)
752 ASSERT(isSSE2Present());
753 m_assembler.divsd_mr(src.offset, src.base, dest);
756 void subDouble(FPRegisterID src, FPRegisterID dest)
758 ASSERT(isSSE2Present());
759 m_assembler.subsd_rr(src, dest);
762 void subDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
764 // B := A - B is invalid.
765 ASSERT(op1 == dest || op2 != dest);
767 moveDouble(op1, dest);
768 subDouble(op2, dest);
771 void subDouble(Address src, FPRegisterID dest)
773 ASSERT(isSSE2Present());
774 m_assembler.subsd_mr(src.offset, src.base, dest);
777 void mulDouble(FPRegisterID src, FPRegisterID dest)
779 ASSERT(isSSE2Present());
780 m_assembler.mulsd_rr(src, dest);
783 void mulDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
785 ASSERT(isSSE2Present());
787 mulDouble(op2, dest);
789 moveDouble(op2, dest);
790 mulDouble(op1, dest);
794 void mulDouble(Address src, FPRegisterID dest)
796 ASSERT(isSSE2Present());
797 m_assembler.mulsd_mr(src.offset, src.base, dest);
800 void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
802 ASSERT(isSSE2Present());
803 m_assembler.cvtsi2sd_rr(src, dest);
806 void convertInt32ToDouble(Address src, FPRegisterID dest)
808 ASSERT(isSSE2Present());
809 m_assembler.cvtsi2sd_mr(src.offset, src.base, dest);
812 Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
814 ASSERT(isSSE2Present());
816 if (cond & DoubleConditionBitInvert)
817 m_assembler.ucomisd_rr(left, right);
819 m_assembler.ucomisd_rr(right, left);
821 if (cond == DoubleEqual) {
822 Jump isUnordered(m_assembler.jp());
823 Jump result = Jump(m_assembler.je());
824 isUnordered.link(this);
826 } else if (cond == DoubleNotEqualOrUnordered) {
827 Jump isUnordered(m_assembler.jp());
828 Jump isEqual(m_assembler.je());
829 isUnordered.link(this);
830 Jump result = jump();
835 ASSERT(!(cond & DoubleConditionBitSpecial));
836 return Jump(m_assembler.jCC(static_cast<X86Assembler::Condition>(cond & ~DoubleConditionBits)));
839 // Truncates 'src' to an integer, and places the resulting 'dest'.
840 // If the result is not representable as a 32 bit value, branch.
841 // May also branch for some values that are representable in 32 bits
842 // (specifically, in this case, INT_MIN).
843 enum BranchTruncateType { BranchIfTruncateFailed, BranchIfTruncateSuccessful };
844 Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed)
846 ASSERT(isSSE2Present());
847 m_assembler.cvttsd2si_rr(src, dest);
848 return branch32(branchType ? NotEqual : Equal, dest, TrustedImm32(0x80000000));
851 Jump branchTruncateDoubleToUint32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed)
853 ASSERT(isSSE2Present());
854 m_assembler.cvttsd2si_rr(src, dest);
855 return branch32(branchType ? GreaterThanOrEqual : LessThan, dest, TrustedImm32(0));
858 void truncateDoubleToInt32(FPRegisterID src, RegisterID dest)
860 ASSERT(isSSE2Present());
861 m_assembler.cvttsd2si_rr(src, dest);
865 void truncateDoubleToUint32(FPRegisterID src, RegisterID dest)
867 ASSERT(isSSE2Present());
868 m_assembler.cvttsd2siq_rr(src, dest);
872 // Convert 'src' to an integer, and places the resulting 'dest'.
873 // If the result is not representable as a 32 bit value, branch.
874 // May also branch for some values that are representable in 32 bits
875 // (specifically, in this case, 0).
876 void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp)
878 ASSERT(isSSE2Present());
879 m_assembler.cvttsd2si_rr(src, dest);
881 // If the result is zero, it might have been -0.0, and the double comparison won't catch this!
882 failureCases.append(branchTest32(Zero, dest));
884 // Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump.
885 convertInt32ToDouble(dest, fpTemp);
886 m_assembler.ucomisd_rr(fpTemp, src);
887 failureCases.append(m_assembler.jp());
888 failureCases.append(m_assembler.jne());
891 Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID scratch)
893 ASSERT(isSSE2Present());
894 m_assembler.xorpd_rr(scratch, scratch);
895 return branchDouble(DoubleNotEqual, reg, scratch);
898 Jump branchDoubleZeroOrNaN(FPRegisterID reg, FPRegisterID scratch)
900 ASSERT(isSSE2Present());
901 m_assembler.xorpd_rr(scratch, scratch);
902 return branchDouble(DoubleEqualOrUnordered, reg, scratch);
905 void lshiftPacked(TrustedImm32 imm, XMMRegisterID reg)
907 ASSERT(isSSE2Present());
908 m_assembler.psllq_i8r(imm.m_value, reg);
911 void rshiftPacked(TrustedImm32 imm, XMMRegisterID reg)
913 ASSERT(isSSE2Present());
914 m_assembler.psrlq_i8r(imm.m_value, reg);
917 void orPacked(XMMRegisterID src, XMMRegisterID dst)
919 ASSERT(isSSE2Present());
920 m_assembler.por_rr(src, dst);
923 void moveInt32ToPacked(RegisterID src, XMMRegisterID dst)
925 ASSERT(isSSE2Present());
926 m_assembler.movd_rr(src, dst);
929 void movePackedToInt32(XMMRegisterID src, RegisterID dst)
931 ASSERT(isSSE2Present());
932 m_assembler.movd_rr(src, dst);
935 // Stack manipulation operations:
937 // The ABI is assumed to provide a stack abstraction to memory,
938 // containing machine word sized units of data. Push and pop
939 // operations add and remove a single register sized unit of data
940 // to or from the stack. Peek and poke operations read or write
941 // values on the stack, without moving the current stack position.
943 void pop(RegisterID dest)
945 m_assembler.pop_r(dest);
948 void push(RegisterID src)
950 m_assembler.push_r(src);
953 void push(Address address)
955 m_assembler.push_m(address.offset, address.base);
958 void push(TrustedImm32 imm)
960 m_assembler.push_i32(imm.m_value);
964 // Register move operations:
966 // Move values in registers.
968 void move(TrustedImm32 imm, RegisterID dest)
970 // Note: on 64-bit the TrustedImm32 value is zero extended into the register, it
971 // may be useful to have a separate version that sign extends the value?
973 m_assembler.xorl_rr(dest, dest);
975 m_assembler.movl_i32r(imm.m_value, dest);
979 void move(RegisterID src, RegisterID dest)
981 // Note: on 64-bit this is is a full register move; perhaps it would be
982 // useful to have separate move32 & movePtr, with move32 zero extending?
984 m_assembler.movq_rr(src, dest);
987 void move(TrustedImmPtr imm, RegisterID dest)
989 m_assembler.movq_i64r(imm.asIntptr(), dest);
992 void swap(RegisterID reg1, RegisterID reg2)
995 m_assembler.xchgq_rr(reg1, reg2);
998 void signExtend32ToPtr(RegisterID src, RegisterID dest)
1000 m_assembler.movsxd_rr(src, dest);
1003 void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
1005 m_assembler.movl_rr(src, dest);
1008 void move(RegisterID src, RegisterID dest)
1011 m_assembler.movl_rr(src, dest);
1014 void move(TrustedImmPtr imm, RegisterID dest)
1016 m_assembler.movl_i32r(imm.asIntptr(), dest);
1019 void swap(RegisterID reg1, RegisterID reg2)
1022 m_assembler.xchgl_rr(reg1, reg2);
1025 void signExtend32ToPtr(RegisterID src, RegisterID dest)
1030 void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
1037 // Forwards / external control flow operations:
1039 // This set of jump and conditional branch operations return a Jump
1040 // object which may linked at a later point, allow forwards jump,
1041 // or jumps that will require external linkage (after the code has been
1044 // For branches, signed <, >, <= and >= are denoted as l, g, le, and ge
1045 // respecitvely, for unsigned comparisons the names b, a, be, and ae are
1046 // used (representing the names 'below' and 'above').
1048 // Operands to the comparision are provided in the expected order, e.g.
1049 // jle32(reg1, TrustedImm32(5)) will branch if the value held in reg1, when
1050 // treated as a signed 32bit value, is less than or equal to 5.
1052 // jz and jnz test whether the first operand is equal to zero, and take
1053 // an optional second operand of a mask under which to perform the test.
1056 Jump branch8(RelationalCondition cond, Address left, TrustedImm32 right)
1058 m_assembler.cmpb_im(right.m_value, left.offset, left.base);
1059 return Jump(m_assembler.jCC(x86Condition(cond)));
1062 Jump branch32(RelationalCondition cond, RegisterID left, RegisterID right)
1064 m_assembler.cmpl_rr(right, left);
1065 return Jump(m_assembler.jCC(x86Condition(cond)));
1068 Jump branch32(RelationalCondition cond, RegisterID left, TrustedImm32 right)
1070 if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
1071 m_assembler.testl_rr(left, left);
1073 m_assembler.cmpl_ir(right.m_value, left);
1074 return Jump(m_assembler.jCC(x86Condition(cond)));
1077 Jump branch32(RelationalCondition cond, RegisterID left, Address right)
1079 m_assembler.cmpl_mr(right.offset, right.base, left);
1080 return Jump(m_assembler.jCC(x86Condition(cond)));
1083 Jump branch32(RelationalCondition cond, Address left, RegisterID right)
1085 m_assembler.cmpl_rm(right, left.offset, left.base);
1086 return Jump(m_assembler.jCC(x86Condition(cond)));
1089 Jump branch32(RelationalCondition cond, Address left, TrustedImm32 right)
1091 m_assembler.cmpl_im(right.m_value, left.offset, left.base);
1092 return Jump(m_assembler.jCC(x86Condition(cond)));
1095 Jump branch32(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
1097 m_assembler.cmpl_im(right.m_value, left.offset, left.base, left.index, left.scale);
1098 return Jump(m_assembler.jCC(x86Condition(cond)));
1101 Jump branch32WithUnalignedHalfWords(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
1103 return branch32(cond, left, right);
1106 Jump branchTest32(ResultCondition cond, RegisterID reg, RegisterID mask)
1108 m_assembler.testl_rr(reg, mask);
1109 return Jump(m_assembler.jCC(x86Condition(cond)));
1112 Jump branchTest32(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
1114 // if we are only interested in the low seven bits, this can be tested with a testb
1115 if (mask.m_value == -1)
1116 m_assembler.testl_rr(reg, reg);
1118 m_assembler.testl_i32r(mask.m_value, reg);
1119 return Jump(m_assembler.jCC(x86Condition(cond)));
1122 Jump branchTest32(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
1124 if (mask.m_value == -1)
1125 m_assembler.cmpl_im(0, address.offset, address.base);
1127 m_assembler.testl_i32m(mask.m_value, address.offset, address.base);
1128 return Jump(m_assembler.jCC(x86Condition(cond)));
1131 Jump branchTest32(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
1133 if (mask.m_value == -1)
1134 m_assembler.cmpl_im(0, address.offset, address.base, address.index, address.scale);
1136 m_assembler.testl_i32m(mask.m_value, address.offset, address.base, address.index, address.scale);
1137 return Jump(m_assembler.jCC(x86Condition(cond)));
1140 Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
1142 // Byte in TrustedImm32 is not well defined, so be a little permisive here, but don't accept nonsense values.
1143 ASSERT(mask.m_value >= -128 && mask.m_value <= 255);
1144 if (mask.m_value == -1)
1145 m_assembler.cmpb_im(0, address.offset, address.base);
1147 m_assembler.testb_im(mask.m_value, address.offset, address.base);
1148 return Jump(m_assembler.jCC(x86Condition(cond)));
1151 Jump branchTest8(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
1153 // Byte in TrustedImm32 is not well defined, so be a little permisive here, but don't accept nonsense values.
1154 ASSERT(mask.m_value >= -128 && mask.m_value <= 255);
1155 if (mask.m_value == -1)
1156 m_assembler.cmpb_im(0, address.offset, address.base, address.index, address.scale);
1158 m_assembler.testb_im(mask.m_value, address.offset, address.base, address.index, address.scale);
1159 return Jump(m_assembler.jCC(x86Condition(cond)));
1162 Jump branch8(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
1164 ASSERT(!(right.m_value & 0xFFFFFF00));
1166 m_assembler.cmpb_im(right.m_value, left.offset, left.base, left.index, left.scale);
1167 return Jump(m_assembler.jCC(x86Condition(cond)));
1172 return Jump(m_assembler.jmp());
1175 void jump(RegisterID target)
1177 m_assembler.jmp_r(target);
1180 // Address is a memory location containing the address to jump to
1181 void jump(Address address)
1183 m_assembler.jmp_m(address.offset, address.base);
1187 // Arithmetic control flow operations:
1189 // This set of conditional branch operations branch based
1190 // on the result of an arithmetic operation. The operation
1191 // is performed as normal, storing the result.
1193 // * jz operations branch if the result is zero.
1194 // * jo operations branch if the (signed) arithmetic
1195 // operation caused an overflow to occur.
1197 Jump branchAdd32(ResultCondition cond, RegisterID src, RegisterID dest)
1200 return Jump(m_assembler.jCC(x86Condition(cond)));
1203 Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
1206 return Jump(m_assembler.jCC(x86Condition(cond)));
1209 Jump branchAdd32(ResultCondition cond, TrustedImm32 src, Address dest)
1212 return Jump(m_assembler.jCC(x86Condition(cond)));
1215 Jump branchAdd32(ResultCondition cond, RegisterID src, Address dest)
1218 return Jump(m_assembler.jCC(x86Condition(cond)));
1221 Jump branchAdd32(ResultCondition cond, Address src, RegisterID dest)
1224 return Jump(m_assembler.jCC(x86Condition(cond)));
1227 Jump branchAdd32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest)
1230 return branchAdd32(cond, src2, dest);
1232 return branchAdd32(cond, src1, dest);
1235 Jump branchAdd32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest)
1238 return branchAdd32(cond, imm, dest);
1241 Jump branchMul32(ResultCondition cond, RegisterID src, RegisterID dest)
1244 if (cond != Overflow)
1245 m_assembler.testl_rr(dest, dest);
1246 return Jump(m_assembler.jCC(x86Condition(cond)));
1249 Jump branchMul32(ResultCondition cond, Address src, RegisterID dest)
1252 if (cond != Overflow)
1253 m_assembler.testl_rr(dest, dest);
1254 return Jump(m_assembler.jCC(x86Condition(cond)));
1257 Jump branchMul32(ResultCondition cond, TrustedImm32 imm, RegisterID src, RegisterID dest)
1259 mul32(imm, src, dest);
1260 if (cond != Overflow)
1261 m_assembler.testl_rr(dest, dest);
1262 return Jump(m_assembler.jCC(x86Condition(cond)));
1265 Jump branchMul32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest)
1268 return branchMul32(cond, src2, dest);
1270 return branchMul32(cond, src1, dest);
1273 Jump branchSub32(ResultCondition cond, RegisterID src, RegisterID dest)
1276 return Jump(m_assembler.jCC(x86Condition(cond)));
1279 Jump branchSub32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
1282 return Jump(m_assembler.jCC(x86Condition(cond)));
1285 Jump branchSub32(ResultCondition cond, TrustedImm32 imm, Address dest)
1288 return Jump(m_assembler.jCC(x86Condition(cond)));
1291 Jump branchSub32(ResultCondition cond, RegisterID src, Address dest)
1294 return Jump(m_assembler.jCC(x86Condition(cond)));
1297 Jump branchSub32(ResultCondition cond, Address src, RegisterID dest)
1300 return Jump(m_assembler.jCC(x86Condition(cond)));
1303 Jump branchSub32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest)
1305 // B := A - B is invalid.
1306 ASSERT(src1 == dest || src2 != dest);
1309 return branchSub32(cond, src2, dest);
1312 Jump branchSub32(ResultCondition cond, RegisterID src1, TrustedImm32 src2, RegisterID dest)
1315 return branchSub32(cond, src2, dest);
1318 Jump branchNeg32(ResultCondition cond, RegisterID srcDest)
1321 return Jump(m_assembler.jCC(x86Condition(cond)));
1324 Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest)
1327 return Jump(m_assembler.jCC(x86Condition(cond)));
1331 // Miscellaneous operations:
1340 return Call(m_assembler.call(), Call::LinkableNear);
1343 Call call(RegisterID target)
1345 return Call(m_assembler.call(target), Call::None);
1348 void call(Address address)
1350 m_assembler.call_m(address.offset, address.base);
1358 void compare8(RelationalCondition cond, Address left, TrustedImm32 right, RegisterID dest)
1360 m_assembler.cmpb_im(right.m_value, left.offset, left.base);
1361 set32(x86Condition(cond), dest);
1364 void compare32(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID dest)
1366 m_assembler.cmpl_rr(right, left);
1367 set32(x86Condition(cond), dest);
1370 void compare32(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
1372 if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
1373 m_assembler.testl_rr(left, left);
1375 m_assembler.cmpl_ir(right.m_value, left);
1376 set32(x86Condition(cond), dest);
1380 // The mask should be optional... perhaps the argument order should be
1381 // dest-src, operations always have a dest? ... possibly not true, considering
1382 // asm ops like test, or pseudo ops like pop().
1384 void test8(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest)
1386 if (mask.m_value == -1)
1387 m_assembler.cmpb_im(0, address.offset, address.base);
1389 m_assembler.testb_im(mask.m_value, address.offset, address.base);
1390 set32(x86Condition(cond), dest);
1393 void test32(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest)
1395 if (mask.m_value == -1)
1396 m_assembler.cmpl_im(0, address.offset, address.base);
1398 m_assembler.testl_i32m(mask.m_value, address.offset, address.base);
1399 set32(x86Condition(cond), dest);
1402 // Invert a relational condition, e.g. == becomes !=, < becomes >=, etc.
1403 static RelationalCondition invert(RelationalCondition cond)
1405 return static_cast<RelationalCondition>(cond ^ 1);
1413 static void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination)
1415 X86Assembler::replaceWithJump(instructionStart.executableAddress(), destination.executableAddress());
1418 static ptrdiff_t maxJumpReplacementSize()
1420 return X86Assembler::maxJumpReplacementSize();
1424 X86Assembler::Condition x86Condition(RelationalCondition cond)
1426 return static_cast<X86Assembler::Condition>(cond);
1429 X86Assembler::Condition x86Condition(ResultCondition cond)
1431 return static_cast<X86Assembler::Condition>(cond);
1434 void set32(X86Assembler::Condition cond, RegisterID dest)
1437 // On 32-bit x86 we can only set the first 4 registers;
1438 // esp..edi are mapped to the 'h' registers!
1440 m_assembler.xchgl_rr(dest, X86Registers::eax);
1441 m_assembler.setCC_r(cond, X86Registers::eax);
1442 m_assembler.movzbl_rr(X86Registers::eax, X86Registers::eax);
1443 m_assembler.xchgl_rr(dest, X86Registers::eax);
1447 m_assembler.setCC_r(cond, dest);
1448 m_assembler.movzbl_rr(dest, dest);
1452 // Only MacroAssemblerX86 should be using the following method; SSE2 is always available on
1453 // x86_64, and clients & subclasses of MacroAssembler should be using 'supportsFloatingPoint()'.
1454 friend class MacroAssemblerX86;
1459 // All X86 Macs are guaranteed to support at least SSE2,
1460 static bool isSSE2Present()
1465 #else // OS(MAC_OS_X)
1467 enum SSE2CheckState {
1473 static bool isSSE2Present()
1475 if (s_sse2CheckState == NotCheckedSSE2) {
1476 // Default the flags value to zero; if the compiler is
1477 // not MSVC or GCC we will read this as SSE2 not present.
1481 mov eax, 1 // cpuid function 1 gives us the standard feature set
1494 : "%eax", "%ecx", "%edx"
1497 static const int SSE2FeatureBit = 1 << 26;
1498 s_sse2CheckState = (flags & SSE2FeatureBit) ? HasSSE2 : NoSSE2;
1501 ASSERT(s_sse2CheckState != NotCheckedSSE2);
1503 return s_sse2CheckState == HasSSE2;
1506 static SSE2CheckState s_sse2CheckState;
1508 #endif // OS(MAC_OS_X)
1509 #elif !defined(NDEBUG) // CPU(X86)
1511 // On x86-64 we should never be checking for SSE2 in a non-debug build,
1512 // but non debug add this method to keep the asserts above happy.
1513 static bool isSSE2Present()
1523 #endif // ENABLE(ASSEMBLER)
1525 #endif // MacroAssemblerX86Common_h