1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sw=4 et tw=79:
4 * ***** BEGIN LICENSE BLOCK *****
5 * Copyright (C) 2008 Apple Inc. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
24 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * ***** END LICENSE BLOCK ***** */
30 #ifndef MacroAssemblerX86Common_h
31 #define MacroAssemblerX86Common_h
33 #include "assembler/wtf/Platform.h"
37 #include "X86Assembler.h"
38 #include "AbstractMacroAssembler.h"
49 class MacroAssemblerX86Common : public AbstractMacroAssembler<X86Assembler> {
50 static const int DoubleConditionBitInvert = 0x10;
51 static const int DoubleConditionBitSpecial = 0x20;
52 static const int DoubleConditionBits = DoubleConditionBitInvert | DoubleConditionBitSpecial;
56 static const X86Registers::RegisterID scratchRegister = X86Registers::r11;
62 Equal = X86Assembler::ConditionE,
63 NotEqual = X86Assembler::ConditionNE,
64 Above = X86Assembler::ConditionA,
65 AboveOrEqual = X86Assembler::ConditionAE,
66 Below = X86Assembler::ConditionB,
67 BelowOrEqual = X86Assembler::ConditionBE,
68 GreaterThan = X86Assembler::ConditionG,
69 GreaterThanOrEqual = X86Assembler::ConditionGE,
70 LessThan = X86Assembler::ConditionL,
71 LessThanOrEqual = X86Assembler::ConditionLE,
72 Overflow = X86Assembler::ConditionO,
73 Signed = X86Assembler::ConditionS,
74 Zero = X86Assembler::ConditionE,
75 NonZero = X86Assembler::ConditionNE
78 enum DoubleCondition {
79 // These conditions will only evaluate to true if the comparison is ordered - i.e. neither operand is NaN.
80 DoubleEqual = X86Assembler::ConditionE | DoubleConditionBitSpecial,
81 DoubleNotEqual = X86Assembler::ConditionNE,
82 DoubleGreaterThan = X86Assembler::ConditionA,
83 DoubleGreaterThanOrEqual = X86Assembler::ConditionAE,
84 DoubleLessThan = X86Assembler::ConditionA | DoubleConditionBitInvert,
85 DoubleLessThanOrEqual = X86Assembler::ConditionAE | DoubleConditionBitInvert,
86 // If either operand is NaN, these conditions always evaluate to true.
87 DoubleEqualOrUnordered = X86Assembler::ConditionE,
88 DoubleNotEqualOrUnordered = X86Assembler::ConditionNE | DoubleConditionBitSpecial,
89 DoubleGreaterThanOrUnordered = X86Assembler::ConditionB | DoubleConditionBitInvert,
90 DoubleGreaterThanOrEqualOrUnordered = X86Assembler::ConditionBE | DoubleConditionBitInvert,
91 DoubleLessThanOrUnordered = X86Assembler::ConditionB,
92 DoubleLessThanOrEqualOrUnordered = X86Assembler::ConditionBE
95 !((X86Assembler::ConditionE | X86Assembler::ConditionNE | X86Assembler::ConditionA | X86Assembler::ConditionAE | X86Assembler::ConditionB | X86Assembler::ConditionBE) & DoubleConditionBits),
96 DoubleConditionBits_should_not_interfere_with_X86Assembler_Condition_codes);
98 static const RegisterID stackPointerRegister = X86Registers::esp;
100 static inline bool CanUse8Bit(RegisterID reg) {
101 return !!((1 << reg) & ~((1 << X86Registers::esp) |
102 (1 << X86Registers::edi) |
103 (1 << X86Registers::esi) |
104 (1 << X86Registers::ebp)));
107 // Integer arithmetic operations:
109 // Operations are typically two operand - operation(source, srcDst)
110 // For many operations the source may be an Imm32, the srcDst operand
111 // may often be a memory location (explictly described using an Address
114 void add32(RegisterID src, RegisterID dest)
116 m_assembler.addl_rr(src, dest);
119 void add32(Imm32 imm, Address address)
121 m_assembler.addl_im(imm.m_value, address.offset, address.base);
124 void add32(Imm32 imm, RegisterID dest)
126 m_assembler.addl_ir(imm.m_value, dest);
129 void add32(Address src, RegisterID dest)
131 m_assembler.addl_mr(src.offset, src.base, dest);
134 void add32(RegisterID src, Address dest)
136 m_assembler.addl_rm(src, dest.offset, dest.base);
139 void and32(RegisterID src, RegisterID dest)
141 m_assembler.andl_rr(src, dest);
144 void and32(Imm32 imm, RegisterID dest)
146 m_assembler.andl_ir(imm.m_value, dest);
149 void and32(RegisterID src, Address dest)
151 m_assembler.andl_rm(src, dest.offset, dest.base);
154 void and32(Address src, RegisterID dest)
156 m_assembler.andl_mr(src.offset, src.base, dest);
159 void and32(Imm32 imm, Address address)
161 m_assembler.andl_im(imm.m_value, address.offset, address.base);
164 void lshift32(Imm32 imm, RegisterID dest)
166 m_assembler.shll_i8r(imm.m_value, dest);
169 void lshift32(RegisterID shift_amount, RegisterID dest)
171 // On x86 we can only shift by ecx; if asked to shift by another register we'll
172 // need rejig the shift amount into ecx first, and restore the registers afterwards.
173 if (shift_amount != X86Registers::ecx) {
174 swap(shift_amount, X86Registers::ecx);
176 // E.g. transform "shll %eax, %eax" -> "xchgl %eax, %ecx; shll %ecx, %ecx; xchgl %eax, %ecx"
177 if (dest == shift_amount)
178 m_assembler.shll_CLr(X86Registers::ecx);
179 // E.g. transform "shll %eax, %ecx" -> "xchgl %eax, %ecx; shll %ecx, %eax; xchgl %eax, %ecx"
180 else if (dest == X86Registers::ecx)
181 m_assembler.shll_CLr(shift_amount);
182 // E.g. transform "shll %eax, %ebx" -> "xchgl %eax, %ecx; shll %ecx, %ebx; xchgl %eax, %ecx"
184 m_assembler.shll_CLr(dest);
186 swap(shift_amount, X86Registers::ecx);
188 m_assembler.shll_CLr(dest);
191 void mul32(RegisterID src, RegisterID dest)
193 m_assembler.imull_rr(src, dest);
196 void mul32(Address src, RegisterID dest)
198 m_assembler.imull_mr(src.offset, src.base, dest);
201 void mul32(Imm32 imm, RegisterID src, RegisterID dest)
203 m_assembler.imull_i32r(src, imm.m_value, dest);
206 void neg32(RegisterID srcDest)
208 m_assembler.negl_r(srcDest);
211 void neg32(Address srcDest)
213 m_assembler.negl_m(srcDest.offset, srcDest.base);
216 void not32(RegisterID srcDest)
218 m_assembler.notl_r(srcDest);
221 void not32(Address srcDest)
223 m_assembler.notl_m(srcDest.offset, srcDest.base);
226 void or32(RegisterID src, RegisterID dest)
228 m_assembler.orl_rr(src, dest);
231 void or32(Imm32 imm, RegisterID dest)
233 m_assembler.orl_ir(imm.m_value, dest);
236 void or32(RegisterID src, Address dest)
238 m_assembler.orl_rm(src, dest.offset, dest.base);
241 void or32(Address src, RegisterID dest)
243 m_assembler.orl_mr(src.offset, src.base, dest);
246 void or32(Imm32 imm, Address address)
248 m_assembler.orl_im(imm.m_value, address.offset, address.base);
251 void rshift32(RegisterID shift_amount, RegisterID dest)
253 // On x86 we can only shift by ecx; if asked to shift by another register we'll
254 // need rejig the shift amount into ecx first, and restore the registers afterwards.
255 if (shift_amount != X86Registers::ecx) {
256 swap(shift_amount, X86Registers::ecx);
258 // E.g. transform "shll %eax, %eax" -> "xchgl %eax, %ecx; shll %ecx, %ecx; xchgl %eax, %ecx"
259 if (dest == shift_amount)
260 m_assembler.sarl_CLr(X86Registers::ecx);
261 // E.g. transform "shll %eax, %ecx" -> "xchgl %eax, %ecx; shll %ecx, %eax; xchgl %eax, %ecx"
262 else if (dest == X86Registers::ecx)
263 m_assembler.sarl_CLr(shift_amount);
264 // E.g. transform "shll %eax, %ebx" -> "xchgl %eax, %ecx; shll %ecx, %ebx; xchgl %eax, %ecx"
266 m_assembler.sarl_CLr(dest);
268 swap(shift_amount, X86Registers::ecx);
270 m_assembler.sarl_CLr(dest);
273 void rshift32(Imm32 imm, RegisterID dest)
275 m_assembler.sarl_i8r(imm.m_value, dest);
278 void urshift32(RegisterID shift_amount, RegisterID dest)
280 // On x86 we can only shift by ecx; if asked to shift by another register we'll
281 // need rejig the shift amount into ecx first, and restore the registers afterwards.
282 if (shift_amount != X86Registers::ecx) {
283 swap(shift_amount, X86Registers::ecx);
285 // E.g. transform "shrl %eax, %eax" -> "xchgl %eax, %ecx; shrl %ecx, %ecx; xchgl %eax, %ecx"
286 if (dest == shift_amount)
287 m_assembler.shrl_CLr(X86Registers::ecx);
288 // E.g. transform "shrl %eax, %ecx" -> "xchgl %eax, %ecx; shrl %ecx, %eax; xchgl %eax, %ecx"
289 else if (dest == X86Registers::ecx)
290 m_assembler.shrl_CLr(shift_amount);
291 // E.g. transform "shrl %eax, %ebx" -> "xchgl %eax, %ecx; shrl %ecx, %ebx; xchgl %eax, %ecx"
293 m_assembler.shrl_CLr(dest);
295 swap(shift_amount, X86Registers::ecx);
297 m_assembler.shrl_CLr(dest);
300 void urshift32(Imm32 imm, RegisterID dest)
302 m_assembler.shrl_i8r(imm.m_value, dest);
305 void sub32(RegisterID src, RegisterID dest)
307 m_assembler.subl_rr(src, dest);
310 void sub32(Imm32 imm, RegisterID dest)
312 m_assembler.subl_ir(imm.m_value, dest);
315 void sub32(Imm32 imm, Address address)
317 m_assembler.subl_im(imm.m_value, address.offset, address.base);
320 void sub32(Address src, RegisterID dest)
322 m_assembler.subl_mr(src.offset, src.base, dest);
325 void sub32(RegisterID src, Address dest)
327 m_assembler.subl_rm(src, dest.offset, dest.base);
331 void xor32(RegisterID src, RegisterID dest)
333 m_assembler.xorl_rr(src, dest);
336 void xor32(Imm32 imm, Address dest)
338 m_assembler.xorl_im(imm.m_value, dest.offset, dest.base);
341 void xor32(Imm32 imm, RegisterID dest)
343 m_assembler.xorl_ir(imm.m_value, dest);
346 void xor32(RegisterID src, Address dest)
348 m_assembler.xorl_rm(src, dest.offset, dest.base);
351 void xor32(Address src, RegisterID dest)
353 m_assembler.xorl_mr(src.offset, src.base, dest);
356 void sqrtDouble(FPRegisterID src, FPRegisterID dst)
358 m_assembler.sqrtsd_rr(src, dst);
361 // Memory access operations:
363 // Loads are of the form load(address, destination) and stores of the form
364 // store(source, address). The source for a store may be an Imm32. Address
365 // operand objects to loads and store will be implicitly constructed if a
366 // register is passed.
368 void load32(ImplicitAddress address, RegisterID dest)
370 m_assembler.movl_mr(address.offset, address.base, dest);
373 void load32(BaseIndex address, RegisterID dest)
375 m_assembler.movl_mr(address.offset, address.base, address.index, address.scale, dest);
378 void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
380 load32(address, dest);
383 DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
385 m_assembler.movl_mr_disp32(address.offset, address.base, dest);
386 return DataLabel32(this);
389 void store8(RegisterID src, Address address)
391 m_assembler.movb_rm(src, address.offset, address.base);
394 void store8(RegisterID src, BaseIndex address)
396 m_assembler.movb_rm(src, address.offset, address.base, address.index, address.scale);
399 void store16(RegisterID src, Address address)
401 m_assembler.movw_rm(src, address.offset, address.base);
404 void store16(RegisterID src, BaseIndex address)
406 m_assembler.movw_rm(src, address.offset, address.base, address.index, address.scale);
409 void load8ZeroExtend(BaseIndex address, RegisterID dest)
411 m_assembler.movzbl_mr(address.offset, address.base, address.index, address.scale, dest);
414 void load8ZeroExtend(Address address, RegisterID dest)
416 m_assembler.movzbl_mr(address.offset, address.base, dest);
419 void load8SignExtend(BaseIndex address, RegisterID dest)
421 m_assembler.movxbl_mr(address.offset, address.base, address.index, address.scale, dest);
424 void load8SignExtend(Address address, RegisterID dest)
426 m_assembler.movxbl_mr(address.offset, address.base, dest);
429 void load16SignExtend(BaseIndex address, RegisterID dest)
431 m_assembler.movxwl_mr(address.offset, address.base, address.index, address.scale, dest);
434 void load16SignExtend(Address address, RegisterID dest)
436 m_assembler.movxwl_mr(address.offset, address.base, dest);
439 void load16(BaseIndex address, RegisterID dest)
441 m_assembler.movzwl_mr(address.offset, address.base, address.index, address.scale, dest);
444 void load16(Address address, RegisterID dest)
446 m_assembler.movzwl_mr(address.offset, address.base, dest);
449 DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
451 m_assembler.movl_rm_disp32(src, address.offset, address.base);
452 return DataLabel32(this);
455 void store32(RegisterID src, ImplicitAddress address)
457 m_assembler.movl_rm(src, address.offset, address.base);
460 void store32(RegisterID src, BaseIndex address)
462 m_assembler.movl_rm(src, address.offset, address.base, address.index, address.scale);
465 void store32(Imm32 imm, BaseIndex address)
467 m_assembler.movl_i32m(imm.m_value, address.offset, address.base, address.index, address.scale);
470 void store16(Imm32 imm, BaseIndex address)
472 m_assembler.movw_i16m(imm.m_value, address.offset, address.base, address.index, address.scale);
475 void store8(Imm32 imm, BaseIndex address)
477 m_assembler.movb_i8m(imm.m_value, address.offset, address.base, address.index, address.scale);
480 void store32(Imm32 imm, ImplicitAddress address)
482 m_assembler.movl_i32m(imm.m_value, address.offset, address.base);
485 void store16(Imm32 imm, ImplicitAddress address)
487 m_assembler.movw_i16m(imm.m_value, address.offset, address.base);
490 void store8(Imm32 imm, ImplicitAddress address)
492 m_assembler.movb_i8m(imm.m_value, address.offset, address.base);
496 // Floating-point operation:
498 // Presently only supports SSE, not x87 floating point.
500 void moveDouble(FPRegisterID src, FPRegisterID dest)
502 ASSERT(isSSE2Present());
503 m_assembler.movsd_rr(src, dest);
506 void loadFloat(ImplicitAddress address, FPRegisterID dest)
508 ASSERT(isSSE2Present());
509 m_assembler.movss_mr(address.offset, address.base, dest);
510 m_assembler.cvtss2sd_rr(dest, dest);
513 void loadFloat(BaseIndex address, FPRegisterID dest)
515 ASSERT(isSSE2Present());
516 m_assembler.movss_mr(address.offset, address.base, address.index, address.scale, dest);
517 m_assembler.cvtss2sd_rr(dest, dest);
520 void convertDoubleToFloat(FPRegisterID src, FPRegisterID dest)
522 ASSERT(isSSE2Present());
523 m_assembler.cvtsd2ss_rr(src, dest);
526 void loadDouble(ImplicitAddress address, FPRegisterID dest)
528 ASSERT(isSSE2Present());
529 m_assembler.movsd_mr(address.offset, address.base, dest);
532 void loadDouble(BaseIndex address, FPRegisterID dest)
534 ASSERT(isSSE2Present());
535 m_assembler.movsd_mr(address.offset, address.base, address.index, address.scale, dest);
538 void storeFloat(ImmDouble imm, Address address)
545 store32(Imm32(u.u32), address);
548 void storeFloat(ImmDouble imm, BaseIndex address)
555 store32(Imm32(u.u32), address);
558 void storeDouble(FPRegisterID src, ImplicitAddress address)
560 ASSERT(isSSE2Present());
561 m_assembler.movsd_rm(src, address.offset, address.base);
564 void storeFloat(FPRegisterID src, ImplicitAddress address)
566 ASSERT(isSSE2Present());
567 m_assembler.movss_rm(src, address.offset, address.base);
570 void storeDouble(FPRegisterID src, BaseIndex address)
572 ASSERT(isSSE2Present());
573 m_assembler.movsd_rm(src, address.offset, address.base, address.index, address.scale);
576 void storeFloat(FPRegisterID src, BaseIndex address)
578 ASSERT(isSSE2Present());
579 m_assembler.movss_rm(src, address.offset, address.base, address.index, address.scale);
582 void addDouble(FPRegisterID src, FPRegisterID dest)
584 ASSERT(isSSE2Present());
585 m_assembler.addsd_rr(src, dest);
588 void addDouble(Address src, FPRegisterID dest)
590 ASSERT(isSSE2Present());
591 m_assembler.addsd_mr(src.offset, src.base, dest);
594 void divDouble(FPRegisterID src, FPRegisterID dest)
596 ASSERT(isSSE2Present());
597 m_assembler.divsd_rr(src, dest);
600 void divDouble(Address src, FPRegisterID dest)
602 ASSERT(isSSE2Present());
603 m_assembler.divsd_mr(src.offset, src.base, dest);
606 void subDouble(FPRegisterID src, FPRegisterID dest)
608 ASSERT(isSSE2Present());
609 m_assembler.subsd_rr(src, dest);
612 void subDouble(Address src, FPRegisterID dest)
614 ASSERT(isSSE2Present());
615 m_assembler.subsd_mr(src.offset, src.base, dest);
618 void mulDouble(FPRegisterID src, FPRegisterID dest)
620 ASSERT(isSSE2Present());
621 m_assembler.mulsd_rr(src, dest);
624 void mulDouble(Address src, FPRegisterID dest)
626 ASSERT(isSSE2Present());
627 m_assembler.mulsd_mr(src.offset, src.base, dest);
630 void xorDouble(FPRegisterID src, FPRegisterID dest)
632 ASSERT(isSSE2Present());
633 m_assembler.xorpd_rr(src, dest);
636 void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
638 ASSERT(isSSE2Present());
639 m_assembler.cvtsi2sd_rr(src, dest);
642 void convertInt32ToDouble(Address src, FPRegisterID dest)
644 ASSERT(isSSE2Present());
645 m_assembler.cvtsi2sd_mr(src.offset, src.base, dest);
648 Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
650 ASSERT(isSSE2Present());
652 if (cond & DoubleConditionBitInvert)
653 m_assembler.ucomisd_rr(left, right);
655 m_assembler.ucomisd_rr(right, left);
657 if (cond == DoubleEqual) {
658 Jump isUnordered(m_assembler.jp());
659 Jump result = Jump(m_assembler.je());
660 isUnordered.link(this);
662 } else if (cond == DoubleNotEqualOrUnordered) {
663 Jump isUnordered(m_assembler.jp());
664 Jump isEqual(m_assembler.je());
665 isUnordered.link(this);
666 Jump result = jump();
671 ASSERT(!(cond & DoubleConditionBitSpecial));
672 return Jump(m_assembler.jCC(static_cast<X86Assembler::Condition>(cond & ~DoubleConditionBits)));
675 // Truncates 'src' to an integer, and places the resulting 'dest'.
676 // If the result is not representable as a 32 bit value, branch.
677 // May also branch for some values that are representable in 32 bits
678 // (specifically, in this case, INT_MIN).
679 Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest)
681 ASSERT(isSSE2Present());
682 m_assembler.cvttsd2si_rr(src, dest);
683 return branch32(Equal, dest, Imm32(0x80000000));
686 // Convert 'src' to an integer, and places the resulting 'dest'.
687 // If the result is not representable as a 32 bit value, branch.
688 // May also branch for some values that are representable in 32 bits
689 // (specifically, in this case, 0).
690 void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp)
692 ASSERT(isSSE2Present());
693 m_assembler.cvttsd2si_rr(src, dest);
695 // If the result is zero, it might have been -0.0, and the double comparison won't catch this!
696 failureCases.append(branchTest32(Zero, dest));
698 // Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump.
699 convertInt32ToDouble(dest, fpTemp);
700 m_assembler.ucomisd_rr(fpTemp, src);
701 failureCases.append(m_assembler.jp());
702 failureCases.append(m_assembler.jne());
705 void zeroDouble(FPRegisterID srcDest)
707 ASSERT(isSSE2Present());
708 m_assembler.xorpd_rr(srcDest, srcDest);
712 // Stack manipulation operations:
714 // The ABI is assumed to provide a stack abstraction to memory,
715 // containing machine word sized units of data. Push and pop
716 // operations add and remove a single register sized unit of data
717 // to or from the stack. Peek and poke operations read or write
718 // values on the stack, without moving the current stack position.
720 void pop(RegisterID dest)
722 m_assembler.pop_r(dest);
725 void push(RegisterID src)
727 m_assembler.push_r(src);
730 void push(Address address)
732 m_assembler.push_m(address.offset, address.base);
737 m_assembler.push_i32(imm.m_value);
741 // Register move operations:
743 // Move values in registers.
745 void move(Imm32 imm, RegisterID dest)
747 // Note: on 64-bit the Imm32 value is zero extended into the register, it
748 // may be useful to have a separate version that sign extends the value?
750 m_assembler.xorl_rr(dest, dest);
752 m_assembler.movl_i32r(imm.m_value, dest);
756 void move(RegisterID src, RegisterID dest)
758 // Note: on 64-bit this is is a full register move; perhaps it would be
759 // useful to have separate move32 & movePtr, with move32 zero extending?
761 m_assembler.movq_rr(src, dest);
764 void move(ImmPtr imm, RegisterID dest)
766 m_assembler.movq_i64r(imm.asIntptr(), dest);
769 void swap(RegisterID reg1, RegisterID reg2)
771 // XCHG is extremely slow. Don't use XCHG.
773 m_assembler.movq_rr(reg1, scratchRegister);
774 m_assembler.movq_rr(reg2, reg1);
775 m_assembler.movq_rr(scratchRegister, reg2);
779 void signExtend32ToPtr(RegisterID src, RegisterID dest)
781 m_assembler.movsxd_rr(src, dest);
784 void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
786 m_assembler.movl_rr(src, dest);
789 void move(RegisterID src, RegisterID dest)
792 m_assembler.movl_rr(src, dest);
795 void move(ImmPtr imm, RegisterID dest)
797 m_assembler.movl_i32r(imm.asIntptr(), dest);
800 void swap(RegisterID reg1, RegisterID reg2)
803 m_assembler.xchgl_rr(reg1, reg2);
806 void signExtend32ToPtr(RegisterID src, RegisterID dest)
811 void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
818 // Forwards / external control flow operations:
820 // This set of jump and conditional branch operations return a Jump
821 // object which may linked at a later point, allow forwards jump,
822 // or jumps that will require external linkage (after the code has been
825 // For branches, signed <, >, <= and >= are denoted as l, g, le, and ge
826 // respecitvely, for unsigned comparisons the names b, a, be, and ae are
827 // used (representing the names 'below' and 'above').
829 // Operands to the comparision are provided in the expected order, e.g.
830 // jle32(reg1, Imm32(5)) will branch if the value held in reg1, when
831 // treated as a signed 32bit value, is less than or equal to 5.
833 // jz and jnz test whether the first operand is equal to zero, and take
834 // an optional second operand of a mask under which to perform the test.
837 Jump branch8(Condition cond, Address left, Imm32 right)
839 m_assembler.cmpb_im(right.m_value, left.offset, left.base);
840 return Jump(m_assembler.jCC(x86Condition(cond)));
843 Jump branch32(Condition cond, RegisterID left, RegisterID right)
845 m_assembler.cmpl_rr(right, left);
846 return Jump(m_assembler.jCC(x86Condition(cond)));
849 Jump branch32(Condition cond, RegisterID left, Imm32 right)
851 if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
852 m_assembler.testl_rr(left, left);
854 m_assembler.cmpl_ir(right.m_value, left);
855 return Jump(m_assembler.jCC(x86Condition(cond)));
858 // Branch based on a 32-bit comparison, forcing the size of the
859 // immediate operand to 32 bits in the native code stream to ensure that
860 // the length of code emitted by this instruction is consistent.
861 Jump branch32FixedLength(Condition cond, RegisterID left, Imm32 right)
863 m_assembler.cmpl_ir_force32(right.m_value, left);
864 return Jump(m_assembler.jCC(x86Condition(cond)));
867 // Branch and record a label after the comparison.
868 Jump branch32WithPatch(Condition cond, RegisterID left, Imm32 right, DataLabel32 &dataLabel)
870 // Always use cmpl, since the value is to be patched.
871 m_assembler.cmpl_ir_force32(right.m_value, left);
872 dataLabel = DataLabel32(this);
873 return Jump(m_assembler.jCC(x86Condition(cond)));
876 Jump branch32WithPatch(Condition cond, Address left, Imm32 right, DataLabel32 &dataLabel)
878 m_assembler.cmpl_im_force32(right.m_value, left.offset, left.base);
879 dataLabel = DataLabel32(this);
880 return Jump(m_assembler.jCC(x86Condition(cond)));
883 Jump branch32(Condition cond, RegisterID left, Address right)
885 m_assembler.cmpl_mr(right.offset, right.base, left);
886 return Jump(m_assembler.jCC(x86Condition(cond)));
889 Jump branch32(Condition cond, Address left, RegisterID right)
891 m_assembler.cmpl_rm(right, left.offset, left.base);
892 return Jump(m_assembler.jCC(x86Condition(cond)));
895 Jump branch32(Condition cond, Address left, Imm32 right)
897 m_assembler.cmpl_im(right.m_value, left.offset, left.base);
898 return Jump(m_assembler.jCC(x86Condition(cond)));
901 Jump branch32(Condition cond, BaseIndex left, Imm32 right)
903 m_assembler.cmpl_im(right.m_value, left.offset, left.base, left.index, left.scale);
904 return Jump(m_assembler.jCC(x86Condition(cond)));
907 Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, Imm32 right)
909 return branch32(cond, left, right);
912 Jump branch16(Condition cond, BaseIndex left, RegisterID right)
914 m_assembler.cmpw_rm(right, left.offset, left.base, left.index, left.scale);
915 return Jump(m_assembler.jCC(x86Condition(cond)));
918 Jump branch16(Condition cond, BaseIndex left, Imm32 right)
920 ASSERT(!(right.m_value & 0xFFFF0000));
922 m_assembler.cmpw_im(right.m_value, left.offset, left.base, left.index, left.scale);
923 return Jump(m_assembler.jCC(x86Condition(cond)));
926 Jump branchTest32(Condition cond, RegisterID reg, RegisterID mask)
928 ASSERT((cond == Zero) || (cond == NonZero));
929 m_assembler.testl_rr(reg, mask);
930 return Jump(m_assembler.jCC(x86Condition(cond)));
933 Jump branchTest32(Condition cond, RegisterID reg, Imm32 mask = Imm32(-1))
935 ASSERT((cond == Zero) || (cond == NonZero));
936 // if we are only interested in the low seven bits, this can be tested with a testb
937 if (mask.m_value == -1)
938 m_assembler.testl_rr(reg, reg);
939 else if (CanUse8Bit(reg) && (mask.m_value & ~0x7f) == 0)
940 m_assembler.testb_i8r(mask.m_value, reg);
942 m_assembler.testl_i32r(mask.m_value, reg);
943 return Jump(m_assembler.jCC(x86Condition(cond)));
946 Jump branchTest32(Condition cond, Address address, Imm32 mask = Imm32(-1))
948 ASSERT((cond == Zero) || (cond == NonZero));
949 if (mask.m_value == -1)
950 m_assembler.cmpl_im(0, address.offset, address.base);
952 m_assembler.testl_i32m(mask.m_value, address.offset, address.base);
953 return Jump(m_assembler.jCC(x86Condition(cond)));
956 Jump branchTest32(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1))
958 ASSERT((cond == Zero) || (cond == NonZero));
959 if (mask.m_value == -1)
960 m_assembler.cmpl_im(0, address.offset, address.base, address.index, address.scale);
962 m_assembler.testl_i32m(mask.m_value, address.offset, address.base, address.index, address.scale);
963 return Jump(m_assembler.jCC(x86Condition(cond)));
966 Jump branchTest8(Condition cond, Address address, Imm32 mask = Imm32(-1))
968 ASSERT((cond == Zero) || (cond == NonZero));
969 if (mask.m_value == -1)
970 m_assembler.cmpb_im(0, address.offset, address.base);
972 m_assembler.testb_im(mask.m_value, address.offset, address.base);
973 return Jump(m_assembler.jCC(x86Condition(cond)));
976 Jump branchTest8(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1))
978 ASSERT((cond == Zero) || (cond == NonZero));
979 if (mask.m_value == -1)
980 m_assembler.cmpb_im(0, address.offset, address.base, address.index, address.scale);
982 m_assembler.testb_im(mask.m_value, address.offset, address.base, address.index, address.scale);
983 return Jump(m_assembler.jCC(x86Condition(cond)));
988 return Jump(m_assembler.jmp());
991 void jump(RegisterID target)
993 m_assembler.jmp_r(target);
996 // Address is a memory location containing the address to jump to
997 void jump(Address address)
999 m_assembler.jmp_m(address.offset, address.base);
1002 void jump(BaseIndex address)
1004 m_assembler.jmp_m(address.offset, address.base, address.index, address.scale);
1007 // Arithmetic control flow operations:
1009 // This set of conditional branch operations branch based
1010 // on the result of an arithmetic operation. The operation
1011 // is performed as normal, storing the result.
1013 // * jz operations branch if the result is zero.
1014 // * jo operations branch if the (signed) arithmetic
1015 // operation caused an overflow to occur.
1017 Jump branchAdd32(Condition cond, RegisterID src, RegisterID dest)
1019 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
1021 return Jump(m_assembler.jCC(x86Condition(cond)));
1024 Jump branchAdd32(Condition cond, Imm32 imm, RegisterID dest)
1026 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
1028 return Jump(m_assembler.jCC(x86Condition(cond)));
1031 Jump branchAdd32(Condition cond, Imm32 src, Address dest)
1033 ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
1035 return Jump(m_assembler.jCC(x86Condition(cond)));
1038 Jump branchAdd32(Condition cond, RegisterID src, Address dest)
1040 ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
1042 return Jump(m_assembler.jCC(x86Condition(cond)));
1045 Jump branchAdd32(Condition cond, Address src, RegisterID dest)
1047 ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
1049 return Jump(m_assembler.jCC(x86Condition(cond)));
1052 Jump branchMul32(Condition cond, RegisterID src, RegisterID dest)
1054 ASSERT(cond == Overflow);
1056 return Jump(m_assembler.jCC(x86Condition(cond)));
1059 Jump branchMul32(Condition cond, Address src, RegisterID dest)
1061 ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
1063 return Jump(m_assembler.jCC(x86Condition(cond)));
1066 Jump branchMul32(Condition cond, Imm32 imm, RegisterID src, RegisterID dest)
1068 ASSERT(cond == Overflow);
1069 mul32(imm, src, dest);
1070 return Jump(m_assembler.jCC(x86Condition(cond)));
1073 Jump branchSub32(Condition cond, RegisterID src, RegisterID dest)
1075 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
1077 return Jump(m_assembler.jCC(x86Condition(cond)));
1080 Jump branchSub32(Condition cond, Imm32 imm, RegisterID dest)
1082 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
1084 return Jump(m_assembler.jCC(x86Condition(cond)));
1087 Jump branchSub32(Condition cond, Imm32 imm, Address dest)
1089 ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
1091 return Jump(m_assembler.jCC(x86Condition(cond)));
1094 Jump branchSub32(Condition cond, RegisterID src, Address dest)
1096 ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
1098 return Jump(m_assembler.jCC(x86Condition(cond)));
1101 Jump branchSub32(Condition cond, Address src, RegisterID dest)
1103 ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
1105 return Jump(m_assembler.jCC(x86Condition(cond)));
1108 Jump branchNeg32(Condition cond, RegisterID srcDest)
1110 ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
1112 return Jump(m_assembler.jCC(x86Condition(cond)));
1115 Jump branchOr32(Condition cond, RegisterID src, RegisterID dest)
1117 ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero));
1119 return Jump(m_assembler.jCC(x86Condition(cond)));
1123 // Miscellaneous operations:
1132 return Call(m_assembler.call(), Call::LinkableNear);
1135 Call call(RegisterID target)
1137 return Call(m_assembler.call(target), Call::None);
1140 void call(Address address)
1142 m_assembler.call_m(address.offset, address.base);
1150 void set8(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
1152 m_assembler.cmpl_rr(right, left);
1153 m_assembler.setCC_r(x86Condition(cond), dest);
1156 void set8(Condition cond, Address left, RegisterID right, RegisterID dest)
1158 m_assembler.cmpl_mr(left.offset, left.base, right);
1159 m_assembler.setCC_r(x86Condition(cond), dest);
1162 void set8(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
1164 if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
1165 m_assembler.testl_rr(left, left);
1167 m_assembler.cmpl_ir(right.m_value, left);
1168 m_assembler.setCC_r(x86Condition(cond), dest);
1171 void set32(Condition cond, Address left, RegisterID right, RegisterID dest)
1173 m_assembler.cmpl_rm(right, left.offset, left.base);
1174 m_assembler.setCC_r(x86Condition(cond), dest);
1175 m_assembler.movzbl_rr(dest, dest);
1178 void set32(Condition cond, RegisterID left, Address right, RegisterID dest)
1180 m_assembler.cmpl_mr(right.offset, right.base, left);
1181 m_assembler.setCC_r(x86Condition(cond), dest);
1182 m_assembler.movzbl_rr(dest, dest);
1185 void set32(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
1187 m_assembler.cmpl_rr(right, left);
1188 m_assembler.setCC_r(x86Condition(cond), dest);
1189 m_assembler.movzbl_rr(dest, dest);
1192 void set32(Condition cond, Address left, Imm32 right, RegisterID dest)
1194 m_assembler.cmpl_im(right.m_value, left.offset, left.base);
1195 m_assembler.setCC_r(x86Condition(cond), dest);
1196 m_assembler.movzbl_rr(dest, dest);
1199 void set32(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
1201 if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
1202 m_assembler.testl_rr(left, left);
1204 m_assembler.cmpl_ir(right.m_value, left);
1205 m_assembler.setCC_r(x86Condition(cond), dest);
1206 m_assembler.movzbl_rr(dest, dest);
1210 // The mask should be optional... paerhaps the argument order should be
1211 // dest-src, operations always have a dest? ... possibly not true, considering
1212 // asm ops like test, or pseudo ops like pop().
1214 void setTest8(Condition cond, Address address, Imm32 mask, RegisterID dest)
1216 if (mask.m_value == -1)
1217 m_assembler.cmpb_im(0, address.offset, address.base);
1219 m_assembler.testb_im(mask.m_value, address.offset, address.base);
1220 m_assembler.setCC_r(x86Condition(cond), dest);
1221 m_assembler.movzbl_rr(dest, dest);
1224 void setTest32(Condition cond, Address address, Imm32 mask, RegisterID dest)
1226 if (mask.m_value == -1)
1227 m_assembler.cmpl_im(0, address.offset, address.base);
1229 m_assembler.testl_i32m(mask.m_value, address.offset, address.base);
1230 m_assembler.setCC_r(x86Condition(cond), dest);
1231 m_assembler.movzbl_rr(dest, dest);
1234 // As the SSE's were introduced in order, the presence of a later SSE implies
1235 // the presence of an earlier SSE. For example, SSE4_2 support implies SSE2 support.
1236 enum SSECheckState {
1247 static SSECheckState getSSEState()
1249 if (s_sseCheckState == NotCheckedSSE) {
1250 MacroAssemblerX86Common::setSSECheckState();
1253 ASSERT(s_sseCheckState != NotCheckedSSE);
1255 return s_sseCheckState;
1259 X86Assembler::Condition x86Condition(Condition cond)
1261 return static_cast<X86Assembler::Condition>(cond);
1265 friend class MacroAssemblerX86;
1267 static SSECheckState s_sseCheckState;
1269 static void setSSECheckState()
1271 // Default the flags value to zero; if the compiler is
1272 // not MSVC or GCC we will read this as SSE2 not present.
1273 volatile int flags_edx = 0;
1274 volatile int flags_ecx = 0;
1275 #if WTF_COMPILER_MSVC
1279 __cpuid(cpuinfo, 1);
1280 flags_ecx = cpuinfo[2];
1281 flags_edx = cpuinfo[3];
1284 mov eax, 1 // cpuid function 1 gives us the standard feature set
1290 #elif WTF_COMPILER_GCC
1299 : "=g" (flags_ecx), "=g" (flags_edx)
1301 : "%eax", "%ecx", "%edx"
1311 : "=g" (flags_ecx), "=g" (flags_edx)
1313 : "%eax", "%ecx", "%edx"
1316 #elif WTF_COMPILER_SUNPRO
1323 "movl %%ecx, (%rsi);"
1324 "movl %%edx, (%rdi);"
1326 : "S" (&flags_ecx), "D" (&flags_edx)
1327 : "%eax", "%ecx", "%edx"
1335 "movl %ecx, (%esi);"
1336 "movl %edx, (%edi);"
1338 : "S" (&flags_ecx), "D" (&flags_edx)
1339 : "%eax", "%ecx", "%edx"
1343 static const int SSEFeatureBit = 1 << 25;
1344 static const int SSE2FeatureBit = 1 << 26;
1345 static const int SSE3FeatureBit = 1 << 0;
1346 static const int SSSE3FeatureBit = 1 << 9;
1347 static const int SSE41FeatureBit = 1 << 19;
1348 static const int SSE42FeatureBit = 1 << 20;
1349 if (flags_ecx & SSE42FeatureBit)
1350 s_sseCheckState = HasSSE4_2;
1351 else if (flags_ecx & SSE41FeatureBit)
1352 s_sseCheckState = HasSSE4_1;
1353 else if (flags_ecx & SSSE3FeatureBit)
1354 s_sseCheckState = HasSSSE3;
1355 else if (flags_ecx & SSE3FeatureBit)
1356 s_sseCheckState = HasSSE3;
1357 else if (flags_edx & SSE2FeatureBit)
1358 s_sseCheckState = HasSSE2;
1359 else if (flags_edx & SSEFeatureBit)
1360 s_sseCheckState = HasSSE;
1362 s_sseCheckState = NoSSE;
1366 #if WTF_PLATFORM_MAC
1368 // All X86 Macs are guaranteed to support at least SSE2
1369 static bool isSSEPresent()
1374 static bool isSSE2Present()
1379 #else // PLATFORM(MAC)
1381 static bool isSSEPresent()
1383 if (s_sseCheckState == NotCheckedSSE) {
1387 ASSERT(s_sseCheckState != NotCheckedSSE);
1389 return s_sseCheckState >= HasSSE;
1392 static bool isSSE2Present()
1394 if (s_sseCheckState == NotCheckedSSE) {
1398 ASSERT(s_sseCheckState != NotCheckedSSE);
1400 return s_sseCheckState >= HasSSE2;
1404 #endif // PLATFORM(MAC)
1405 #elif !defined(NDEBUG) // CPU(X86)
1407 // On x86-64 we should never be checking for SSE2 in a non-debug build,
1408 // but non debug add this method to keep the asserts above happy.
1409 static bool isSSE2Present()
1415 static bool isSSE3Present()
1417 if (s_sseCheckState == NotCheckedSSE) {
1421 ASSERT(s_sseCheckState != NotCheckedSSE);
1423 return s_sseCheckState >= HasSSE3;
1426 static bool isSSSE3Present()
1428 if (s_sseCheckState == NotCheckedSSE) {
1432 ASSERT(s_sseCheckState != NotCheckedSSE);
1434 return s_sseCheckState >= HasSSSE3;
1437 static bool isSSE41Present()
1439 if (s_sseCheckState == NotCheckedSSE) {
1443 ASSERT(s_sseCheckState != NotCheckedSSE);
1445 return s_sseCheckState >= HasSSE4_1;
1448 static bool isSSE42Present()
1450 if (s_sseCheckState == NotCheckedSSE) {
1454 ASSERT(s_sseCheckState != NotCheckedSSE);
1456 return s_sseCheckState >= HasSSE4_2;
1462 #endif // ENABLE(ASSEMBLER)
1464 #endif // MacroAssemblerX86Common_h