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
29 #include <wtf/Platform.h>
33 #include "X86Assembler.h"
34 #include "AbstractMacroAssembler.h"
38 class MacroAssemblerX86Common
: public AbstractMacroAssembler
<X86Assembler
> {
42 Equal
= X86Assembler::ConditionE
,
43 NotEqual
= X86Assembler::ConditionNE
,
44 Above
= X86Assembler::ConditionA
,
45 AboveOrEqual
= X86Assembler::ConditionAE
,
46 Below
= X86Assembler::ConditionB
,
47 BelowOrEqual
= X86Assembler::ConditionBE
,
48 GreaterThan
= X86Assembler::ConditionG
,
49 GreaterThanOrEqual
= X86Assembler::ConditionGE
,
50 LessThan
= X86Assembler::ConditionL
,
51 LessThanOrEqual
= X86Assembler::ConditionLE
,
52 Overflow
= X86Assembler::ConditionO
,
53 Signed
= X86Assembler::ConditionS
,
54 Zero
= X86Assembler::ConditionE
,
55 NonZero
= X86Assembler::ConditionNE
58 enum DoubleCondition
{
59 DoubleEqual
= X86Assembler::ConditionE
,
60 DoubleNotEqual
= X86Assembler::ConditionNE
,
61 DoubleGreaterThan
= X86Assembler::ConditionA
,
62 DoubleGreaterThanOrEqual
= X86Assembler::ConditionAE
,
63 DoubleLessThan
= X86Assembler::ConditionB
,
64 DoubleLessThanOrEqual
= X86Assembler::ConditionBE
,
67 static const RegisterID stackPointerRegister
= X86::esp
;
69 // Integer arithmetic operations:
71 // Operations are typically two operand - operation(source, srcDst)
72 // For many operations the source may be an Imm32, the srcDst operand
73 // may often be a memory location (explictly described using an Address
76 void add32(RegisterID src
, RegisterID dest
)
78 m_assembler
.addl_rr(src
, dest
);
81 void add32(Imm32 imm
, Address address
)
83 m_assembler
.addl_im(imm
.m_value
, address
.offset
, address
.base
);
86 void add32(Imm32 imm
, RegisterID dest
)
88 m_assembler
.addl_ir(imm
.m_value
, dest
);
91 void add32(Address src
, RegisterID dest
)
93 m_assembler
.addl_mr(src
.offset
, src
.base
, dest
);
96 void add32(RegisterID src
, Address dest
)
98 m_assembler
.addl_rm(src
, dest
.offset
, dest
.base
);
101 void and32(RegisterID src
, RegisterID dest
)
103 m_assembler
.andl_rr(src
, dest
);
106 void and32(Imm32 imm
, RegisterID dest
)
108 m_assembler
.andl_ir(imm
.m_value
, dest
);
111 void and32(RegisterID src
, Address dest
)
113 m_assembler
.andl_rm(src
, dest
.offset
, dest
.base
);
116 void and32(Address src
, RegisterID dest
)
118 m_assembler
.andl_mr(src
.offset
, src
.base
, dest
);
121 void and32(Imm32 imm
, Address address
)
123 m_assembler
.andl_im(imm
.m_value
, address
.offset
, address
.base
);
126 void lshift32(Imm32 imm
, RegisterID dest
)
128 m_assembler
.shll_i8r(imm
.m_value
, dest
);
131 void lshift32(RegisterID shift_amount
, RegisterID dest
)
133 // On x86 we can only shift by ecx; if asked to shift by another register we'll
134 // need rejig the shift amount into ecx first, and restore the registers afterwards.
135 if (shift_amount
!= X86::ecx
) {
136 swap(shift_amount
, X86::ecx
);
138 // E.g. transform "shll %eax, %eax" -> "xchgl %eax, %ecx; shll %ecx, %ecx; xchgl %eax, %ecx"
139 if (dest
== shift_amount
)
140 m_assembler
.shll_CLr(X86::ecx
);
141 // E.g. transform "shll %eax, %ecx" -> "xchgl %eax, %ecx; shll %ecx, %eax; xchgl %eax, %ecx"
142 else if (dest
== X86::ecx
)
143 m_assembler
.shll_CLr(shift_amount
);
144 // E.g. transform "shll %eax, %ebx" -> "xchgl %eax, %ecx; shll %ecx, %ebx; xchgl %eax, %ecx"
146 m_assembler
.shll_CLr(dest
);
148 swap(shift_amount
, X86::ecx
);
150 m_assembler
.shll_CLr(dest
);
153 void mul32(RegisterID src
, RegisterID dest
)
155 m_assembler
.imull_rr(src
, dest
);
158 void mul32(Address src
, RegisterID dest
)
160 m_assembler
.imull_mr(src
.offset
, src
.base
, dest
);
163 void mul32(Imm32 imm
, RegisterID src
, RegisterID dest
)
165 m_assembler
.imull_i32r(src
, imm
.m_value
, dest
);
168 void neg32(RegisterID srcDest
)
170 m_assembler
.negl_r(srcDest
);
173 void neg32(Address srcDest
)
175 m_assembler
.negl_m(srcDest
.offset
, srcDest
.base
);
178 void not32(RegisterID srcDest
)
180 m_assembler
.notl_r(srcDest
);
183 void not32(Address srcDest
)
185 m_assembler
.notl_m(srcDest
.offset
, srcDest
.base
);
188 void or32(RegisterID src
, RegisterID dest
)
190 m_assembler
.orl_rr(src
, dest
);
193 void or32(Imm32 imm
, RegisterID dest
)
195 m_assembler
.orl_ir(imm
.m_value
, dest
);
198 void or32(RegisterID src
, Address dest
)
200 m_assembler
.orl_rm(src
, dest
.offset
, dest
.base
);
203 void or32(Address src
, RegisterID dest
)
205 m_assembler
.orl_mr(src
.offset
, src
.base
, dest
);
208 void or32(Imm32 imm
, Address address
)
210 m_assembler
.orl_im(imm
.m_value
, address
.offset
, address
.base
);
213 void rshift32(RegisterID shift_amount
, RegisterID dest
)
215 // On x86 we can only shift by ecx; if asked to shift by another register we'll
216 // need rejig the shift amount into ecx first, and restore the registers afterwards.
217 if (shift_amount
!= X86::ecx
) {
218 swap(shift_amount
, X86::ecx
);
220 // E.g. transform "shll %eax, %eax" -> "xchgl %eax, %ecx; shll %ecx, %ecx; xchgl %eax, %ecx"
221 if (dest
== shift_amount
)
222 m_assembler
.sarl_CLr(X86::ecx
);
223 // E.g. transform "shll %eax, %ecx" -> "xchgl %eax, %ecx; shll %ecx, %eax; xchgl %eax, %ecx"
224 else if (dest
== X86::ecx
)
225 m_assembler
.sarl_CLr(shift_amount
);
226 // E.g. transform "shll %eax, %ebx" -> "xchgl %eax, %ecx; shll %ecx, %ebx; xchgl %eax, %ecx"
228 m_assembler
.sarl_CLr(dest
);
230 swap(shift_amount
, X86::ecx
);
232 m_assembler
.sarl_CLr(dest
);
235 void rshift32(Imm32 imm
, RegisterID dest
)
237 m_assembler
.sarl_i8r(imm
.m_value
, dest
);
240 void sub32(RegisterID src
, RegisterID dest
)
242 m_assembler
.subl_rr(src
, dest
);
245 void sub32(Imm32 imm
, RegisterID dest
)
247 m_assembler
.subl_ir(imm
.m_value
, dest
);
250 void sub32(Imm32 imm
, Address address
)
252 m_assembler
.subl_im(imm
.m_value
, address
.offset
, address
.base
);
255 void sub32(Address src
, RegisterID dest
)
257 m_assembler
.subl_mr(src
.offset
, src
.base
, dest
);
260 void sub32(RegisterID src
, Address dest
)
262 m_assembler
.subl_rm(src
, dest
.offset
, dest
.base
);
266 void xor32(RegisterID src
, RegisterID dest
)
268 m_assembler
.xorl_rr(src
, dest
);
271 void xor32(Imm32 imm
, Address dest
)
273 m_assembler
.xorl_im(imm
.m_value
, dest
.offset
, dest
.base
);
276 void xor32(Imm32 imm
, RegisterID dest
)
278 m_assembler
.xorl_ir(imm
.m_value
, dest
);
281 void xor32(RegisterID src
, Address dest
)
283 m_assembler
.xorl_rm(src
, dest
.offset
, dest
.base
);
286 void xor32(Address src
, RegisterID dest
)
288 m_assembler
.xorl_mr(src
.offset
, src
.base
, dest
);
292 // Memory access operations:
294 // Loads are of the form load(address, destination) and stores of the form
295 // store(source, address). The source for a store may be an Imm32. Address
296 // operand objects to loads and store will be implicitly constructed if a
297 // register is passed.
299 void load32(ImplicitAddress address
, RegisterID dest
)
301 m_assembler
.movl_mr(address
.offset
, address
.base
, dest
);
304 void load32(BaseIndex address
, RegisterID dest
)
306 m_assembler
.movl_mr(address
.offset
, address
.base
, address
.index
, address
.scale
, dest
);
309 DataLabel32
load32WithAddressOffsetPatch(Address address
, RegisterID dest
)
311 m_assembler
.movl_mr_disp32(address
.offset
, address
.base
, dest
);
312 return DataLabel32(this);
315 void load16(BaseIndex address
, RegisterID dest
)
317 m_assembler
.movzwl_mr(address
.offset
, address
.base
, address
.index
, address
.scale
, dest
);
320 DataLabel32
store32WithAddressOffsetPatch(RegisterID src
, Address address
)
322 m_assembler
.movl_rm_disp32(src
, address
.offset
, address
.base
);
323 return DataLabel32(this);
326 void store32(RegisterID src
, ImplicitAddress address
)
328 m_assembler
.movl_rm(src
, address
.offset
, address
.base
);
331 void store32(RegisterID src
, BaseIndex address
)
333 m_assembler
.movl_rm(src
, address
.offset
, address
.base
, address
.index
, address
.scale
);
336 void store32(Imm32 imm
, ImplicitAddress address
)
338 m_assembler
.movl_i32m(imm
.m_value
, address
.offset
, address
.base
);
342 // Floating-point operation:
344 // Presently only supports SSE, not x87 floating point.
346 void loadDouble(ImplicitAddress address
, FPRegisterID dest
)
348 ASSERT(isSSE2Present());
349 m_assembler
.movsd_mr(address
.offset
, address
.base
, dest
);
352 void storeDouble(FPRegisterID src
, ImplicitAddress address
)
354 ASSERT(isSSE2Present());
355 m_assembler
.movsd_rm(src
, address
.offset
, address
.base
);
358 void addDouble(FPRegisterID src
, FPRegisterID dest
)
360 ASSERT(isSSE2Present());
361 m_assembler
.addsd_rr(src
, dest
);
364 void addDouble(Address src
, FPRegisterID dest
)
366 ASSERT(isSSE2Present());
367 m_assembler
.addsd_mr(src
.offset
, src
.base
, dest
);
370 void divDouble(FPRegisterID src
, FPRegisterID dest
)
372 ASSERT(isSSE2Present());
373 m_assembler
.divsd_rr(src
, dest
);
376 void divDouble(Address src
, FPRegisterID dest
)
378 ASSERT(isSSE2Present());
379 m_assembler
.divsd_mr(src
.offset
, src
.base
, dest
);
382 void subDouble(FPRegisterID src
, FPRegisterID dest
)
384 ASSERT(isSSE2Present());
385 m_assembler
.subsd_rr(src
, dest
);
388 void subDouble(Address src
, FPRegisterID dest
)
390 ASSERT(isSSE2Present());
391 m_assembler
.subsd_mr(src
.offset
, src
.base
, dest
);
394 void mulDouble(FPRegisterID src
, FPRegisterID dest
)
396 ASSERT(isSSE2Present());
397 m_assembler
.mulsd_rr(src
, dest
);
400 void mulDouble(Address src
, FPRegisterID dest
)
402 ASSERT(isSSE2Present());
403 m_assembler
.mulsd_mr(src
.offset
, src
.base
, dest
);
406 void convertInt32ToDouble(RegisterID src
, FPRegisterID dest
)
408 ASSERT(isSSE2Present());
409 m_assembler
.cvtsi2sd_rr(src
, dest
);
412 void convertInt32ToDouble(Address src
, FPRegisterID dest
)
414 m_assembler
.cvtsi2sd_mr(src
.offset
, src
.base
, dest
);
417 Jump
branchDouble(DoubleCondition cond
, FPRegisterID left
, FPRegisterID right
)
419 ASSERT(isSSE2Present());
420 m_assembler
.ucomisd_rr(right
, left
);
421 return Jump(m_assembler
.jCC(x86Condition(cond
)));
424 Jump
branchDouble(DoubleCondition cond
, FPRegisterID left
, Address right
)
426 m_assembler
.ucomisd_mr(right
.offset
, right
.base
, left
);
427 return Jump(m_assembler
.jCC(x86Condition(cond
)));
430 // Truncates 'src' to an integer, and places the resulting 'dest'.
431 // If the result is not representable as a 32 bit value, branch.
432 // May also branch for some values that are representable in 32 bits
433 // (specifically, in this case, INT_MIN).
434 Jump
branchTruncateDoubleToInt32(FPRegisterID src
, RegisterID dest
)
436 ASSERT(isSSE2Present());
437 m_assembler
.cvttsd2si_rr(src
, dest
);
438 return branch32(Equal
, dest
, Imm32(0x80000000));
441 void zeroDouble(FPRegisterID srcDest
)
443 ASSERT(isSSE2Present());
444 m_assembler
.xorpd_rr(srcDest
, srcDest
);
448 // Stack manipulation operations:
450 // The ABI is assumed to provide a stack abstraction to memory,
451 // containing machine word sized units of data. Push and pop
452 // operations add and remove a single register sized unit of data
453 // to or from the stack. Peek and poke operations read or write
454 // values on the stack, without moving the current stack position.
456 void pop(RegisterID dest
)
458 m_assembler
.pop_r(dest
);
461 void push(RegisterID src
)
463 m_assembler
.push_r(src
);
466 void push(Address address
)
468 m_assembler
.push_m(address
.offset
, address
.base
);
473 m_assembler
.push_i32(imm
.m_value
);
477 // Register move operations:
479 // Move values in registers.
481 void move(Imm32 imm
, RegisterID dest
)
483 // Note: on 64-bit the Imm32 value is zero extended into the register, it
484 // may be useful to have a separate version that sign extends the value?
486 m_assembler
.xorl_rr(dest
, dest
);
488 m_assembler
.movl_i32r(imm
.m_value
, dest
);
492 void move(RegisterID src
, RegisterID dest
)
494 // Note: on 64-bit this is is a full register move; perhaps it would be
495 // useful to have separate move32 & movePtr, with move32 zero extending?
497 m_assembler
.movq_rr(src
, dest
);
500 void move(ImmPtr imm
, RegisterID dest
)
502 if (CAN_SIGN_EXTEND_U32_64(imm
.asIntptr()))
503 m_assembler
.movl_i32r(static_cast<int32_t>(imm
.asIntptr()), dest
);
505 m_assembler
.movq_i64r(imm
.asIntptr(), dest
);
508 void swap(RegisterID reg1
, RegisterID reg2
)
510 m_assembler
.xchgq_rr(reg1
, reg2
);
513 void signExtend32ToPtr(RegisterID src
, RegisterID dest
)
515 m_assembler
.movsxd_rr(src
, dest
);
518 void zeroExtend32ToPtr(RegisterID src
, RegisterID dest
)
520 m_assembler
.movl_rr(src
, dest
);
523 void move(RegisterID src
, RegisterID dest
)
526 m_assembler
.movl_rr(src
, dest
);
529 void move(ImmPtr imm
, RegisterID dest
)
531 m_assembler
.movl_i32r(imm
.asIntptr(), dest
);
534 void swap(RegisterID reg1
, RegisterID reg2
)
537 m_assembler
.xchgl_rr(reg1
, reg2
);
540 void signExtend32ToPtr(RegisterID src
, RegisterID dest
)
545 void zeroExtend32ToPtr(RegisterID src
, RegisterID dest
)
552 // Forwards / external control flow operations:
554 // This set of jump and conditional branch operations return a Jump
555 // object which may linked at a later point, allow forwards jump,
556 // or jumps that will require external linkage (after the code has been
559 // For branches, signed <, >, <= and >= are denoted as l, g, le, and ge
560 // respecitvely, for unsigned comparisons the names b, a, be, and ae are
561 // used (representing the names 'below' and 'above').
563 // Operands to the comparision are provided in the expected order, e.g.
564 // jle32(reg1, Imm32(5)) will branch if the value held in reg1, when
565 // treated as a signed 32bit value, is less than or equal to 5.
567 // jz and jnz test whether the first operand is equal to zero, and take
568 // an optional second operand of a mask under which to perform the test.
571 Jump
branch32(Condition cond
, RegisterID left
, RegisterID right
)
573 m_assembler
.cmpl_rr(right
, left
);
574 return Jump(m_assembler
.jCC(x86Condition(cond
)));
577 Jump
branch32(Condition cond
, RegisterID left
, Imm32 right
)
579 if (((cond
== Equal
) || (cond
== NotEqual
)) && !right
.m_value
)
580 m_assembler
.testl_rr(left
, left
);
582 m_assembler
.cmpl_ir(right
.m_value
, left
);
583 return Jump(m_assembler
.jCC(x86Condition(cond
)));
586 Jump
branch32(Condition cond
, RegisterID left
, Address right
)
588 m_assembler
.cmpl_mr(right
.offset
, right
.base
, left
);
589 return Jump(m_assembler
.jCC(x86Condition(cond
)));
592 Jump
branch32(Condition cond
, Address left
, RegisterID right
)
594 m_assembler
.cmpl_rm(right
, left
.offset
, left
.base
);
595 return Jump(m_assembler
.jCC(x86Condition(cond
)));
598 Jump
branch32(Condition cond
, Address left
, Imm32 right
)
600 m_assembler
.cmpl_im(right
.m_value
, left
.offset
, left
.base
);
601 return Jump(m_assembler
.jCC(x86Condition(cond
)));
604 Jump
branch32(Condition cond
, BaseIndex left
, Imm32 right
)
606 m_assembler
.cmpl_im(right
.m_value
, left
.offset
, left
.base
, left
.index
, left
.scale
);
607 return Jump(m_assembler
.jCC(x86Condition(cond
)));
610 Jump
branch16(Condition cond
, BaseIndex left
, RegisterID right
)
612 m_assembler
.cmpw_rm(right
, left
.offset
, left
.base
, left
.index
, left
.scale
);
613 return Jump(m_assembler
.jCC(x86Condition(cond
)));
616 Jump
branch16(Condition cond
, BaseIndex left
, Imm32 right
)
618 ASSERT(!(right
.m_value
& 0xFFFF0000));
620 m_assembler
.cmpw_im(right
.m_value
, left
.offset
, left
.base
, left
.index
, left
.scale
);
621 return Jump(m_assembler
.jCC(x86Condition(cond
)));
624 Jump
branchTest32(Condition cond
, RegisterID reg
, RegisterID mask
)
626 ASSERT((cond
== Zero
) || (cond
== NonZero
));
627 m_assembler
.testl_rr(reg
, mask
);
628 return Jump(m_assembler
.jCC(x86Condition(cond
)));
631 Jump
branchTest32(Condition cond
, RegisterID reg
, Imm32 mask
= Imm32(-1))
633 ASSERT((cond
== Zero
) || (cond
== NonZero
));
634 // if we are only interested in the low seven bits, this can be tested with a testb
635 if (mask
.m_value
== -1)
636 m_assembler
.testl_rr(reg
, reg
);
637 else if ((mask
.m_value
& ~0x7f) == 0)
638 m_assembler
.testb_i8r(mask
.m_value
, reg
);
640 m_assembler
.testl_i32r(mask
.m_value
, reg
);
641 return Jump(m_assembler
.jCC(x86Condition(cond
)));
644 Jump
branchTest32(Condition cond
, Address address
, Imm32 mask
= Imm32(-1))
646 ASSERT((cond
== Zero
) || (cond
== NonZero
));
647 if (mask
.m_value
== -1)
648 m_assembler
.cmpl_im(0, address
.offset
, address
.base
);
650 m_assembler
.testl_i32m(mask
.m_value
, address
.offset
, address
.base
);
651 return Jump(m_assembler
.jCC(x86Condition(cond
)));
654 Jump
branchTest32(Condition cond
, BaseIndex address
, Imm32 mask
= Imm32(-1))
656 ASSERT((cond
== Zero
) || (cond
== NonZero
));
657 if (mask
.m_value
== -1)
658 m_assembler
.cmpl_im(0, address
.offset
, address
.base
, address
.index
, address
.scale
);
660 m_assembler
.testl_i32m(mask
.m_value
, address
.offset
, address
.base
, address
.index
, address
.scale
);
661 return Jump(m_assembler
.jCC(x86Condition(cond
)));
666 return Jump(m_assembler
.jmp());
669 void jump(RegisterID target
)
671 m_assembler
.jmp_r(target
);
674 // Address is a memory location containing the address to jump to
675 void jump(Address address
)
677 m_assembler
.jmp_m(address
.offset
, address
.base
);
681 // Arithmetic control flow operations:
683 // This set of conditional branch operations branch based
684 // on the result of an arithmetic operation. The operation
685 // is performed as normal, storing the result.
687 // * jz operations branch if the result is zero.
688 // * jo operations branch if the (signed) arithmetic
689 // operation caused an overflow to occur.
691 Jump
branchAdd32(Condition cond
, RegisterID src
, RegisterID dest
)
693 ASSERT((cond
== Overflow
) || (cond
== Signed
) || (cond
== Zero
) || (cond
== NonZero
));
695 return Jump(m_assembler
.jCC(x86Condition(cond
)));
698 Jump
branchAdd32(Condition cond
, Imm32 imm
, RegisterID dest
)
700 ASSERT((cond
== Overflow
) || (cond
== Signed
) || (cond
== Zero
) || (cond
== NonZero
));
702 return Jump(m_assembler
.jCC(x86Condition(cond
)));
705 Jump
branchAdd32(Condition cond
, Imm32 src
, Address dest
)
707 ASSERT((cond
== Overflow
) || (cond
== Zero
) || (cond
== NonZero
));
709 return Jump(m_assembler
.jCC(x86Condition(cond
)));
712 Jump
branchAdd32(Condition cond
, RegisterID src
, Address dest
)
714 ASSERT((cond
== Overflow
) || (cond
== Zero
) || (cond
== NonZero
));
716 return Jump(m_assembler
.jCC(x86Condition(cond
)));
719 Jump
branchAdd32(Condition cond
, Address src
, RegisterID dest
)
721 ASSERT((cond
== Overflow
) || (cond
== Zero
) || (cond
== NonZero
));
723 return Jump(m_assembler
.jCC(x86Condition(cond
)));
726 Jump
branchMul32(Condition cond
, RegisterID src
, RegisterID dest
)
728 ASSERT(cond
== Overflow
);
730 return Jump(m_assembler
.jCC(x86Condition(cond
)));
733 Jump
branchMul32(Condition cond
, Address src
, RegisterID dest
)
735 ASSERT((cond
== Overflow
) || (cond
== Zero
) || (cond
== NonZero
));
737 return Jump(m_assembler
.jCC(x86Condition(cond
)));
740 Jump
branchMul32(Condition cond
, Imm32 imm
, RegisterID src
, RegisterID dest
)
742 ASSERT(cond
== Overflow
);
743 mul32(imm
, src
, dest
);
744 return Jump(m_assembler
.jCC(x86Condition(cond
)));
747 Jump
branchSub32(Condition cond
, RegisterID src
, RegisterID dest
)
749 ASSERT((cond
== Overflow
) || (cond
== Signed
) || (cond
== Zero
) || (cond
== NonZero
));
751 return Jump(m_assembler
.jCC(x86Condition(cond
)));
754 Jump
branchSub32(Condition cond
, Imm32 imm
, RegisterID dest
)
756 ASSERT((cond
== Overflow
) || (cond
== Signed
) || (cond
== Zero
) || (cond
== NonZero
));
758 return Jump(m_assembler
.jCC(x86Condition(cond
)));
761 Jump
branchSub32(Condition cond
, Imm32 imm
, Address dest
)
763 ASSERT((cond
== Overflow
) || (cond
== Zero
) || (cond
== NonZero
));
765 return Jump(m_assembler
.jCC(x86Condition(cond
)));
768 Jump
branchSub32(Condition cond
, RegisterID src
, Address dest
)
770 ASSERT((cond
== Overflow
) || (cond
== Zero
) || (cond
== NonZero
));
772 return Jump(m_assembler
.jCC(x86Condition(cond
)));
775 Jump
branchSub32(Condition cond
, Address src
, RegisterID dest
)
777 ASSERT((cond
== Overflow
) || (cond
== Zero
) || (cond
== NonZero
));
779 return Jump(m_assembler
.jCC(x86Condition(cond
)));
782 Jump
branchOr32(Condition cond
, RegisterID src
, RegisterID dest
)
784 ASSERT((cond
== Signed
) || (cond
== Zero
) || (cond
== NonZero
));
786 return Jump(m_assembler
.jCC(x86Condition(cond
)));
790 // Miscellaneous operations:
799 return Call(m_assembler
.call(), Call::LinkableNear
);
802 Call
call(RegisterID target
)
804 return Call(m_assembler
.call(target
), Call::None
);
807 void call(Address address
)
809 m_assembler
.call_m(address
.offset
, address
.base
);
817 void set8(Condition cond
, RegisterID left
, RegisterID right
, RegisterID dest
)
819 m_assembler
.cmpl_rr(right
, left
);
820 m_assembler
.setCC_r(x86Condition(cond
), dest
);
823 void set8(Condition cond
, Address left
, RegisterID right
, RegisterID dest
)
825 m_assembler
.cmpl_mr(left
.offset
, left
.base
, right
);
826 m_assembler
.setCC_r(x86Condition(cond
), dest
);
829 void set8(Condition cond
, RegisterID left
, Imm32 right
, RegisterID dest
)
831 if (((cond
== Equal
) || (cond
== NotEqual
)) && !right
.m_value
)
832 m_assembler
.testl_rr(left
, left
);
834 m_assembler
.cmpl_ir(right
.m_value
, left
);
835 m_assembler
.setCC_r(x86Condition(cond
), dest
);
838 void set32(Condition cond
, RegisterID left
, RegisterID right
, RegisterID dest
)
840 m_assembler
.cmpl_rr(right
, left
);
841 m_assembler
.setCC_r(x86Condition(cond
), dest
);
842 m_assembler
.movzbl_rr(dest
, dest
);
845 void set32(Condition cond
, RegisterID left
, Imm32 right
, RegisterID dest
)
847 if (((cond
== Equal
) || (cond
== NotEqual
)) && !right
.m_value
)
848 m_assembler
.testl_rr(left
, left
);
850 m_assembler
.cmpl_ir(right
.m_value
, left
);
851 m_assembler
.setCC_r(x86Condition(cond
), dest
);
852 m_assembler
.movzbl_rr(dest
, dest
);
856 // The mask should be optional... paerhaps the argument order should be
857 // dest-src, operations always have a dest? ... possibly not true, considering
858 // asm ops like test, or pseudo ops like pop().
860 void setTest8(Condition cond
, Address address
, Imm32 mask
, RegisterID dest
)
862 if (mask
.m_value
== -1)
863 m_assembler
.cmpl_im(0, address
.offset
, address
.base
);
865 m_assembler
.testl_i32m(mask
.m_value
, address
.offset
, address
.base
);
866 m_assembler
.setCC_r(x86Condition(cond
), dest
);
869 void setTest32(Condition cond
, Address address
, Imm32 mask
, RegisterID dest
)
871 if (mask
.m_value
== -1)
872 m_assembler
.cmpl_im(0, address
.offset
, address
.base
);
874 m_assembler
.testl_i32m(mask
.m_value
, address
.offset
, address
.base
);
875 m_assembler
.setCC_r(x86Condition(cond
), dest
);
876 m_assembler
.movzbl_rr(dest
, dest
);
880 X86Assembler::Condition
x86Condition(Condition cond
)
882 return static_cast<X86Assembler::Condition
>(cond
);
885 X86Assembler::Condition
x86Condition(DoubleCondition cond
)
887 return static_cast<X86Assembler::Condition
>(cond
);
891 // Only MacroAssemblerX86 should be using the following method; SSE2 is always available on
892 // x86_64, and clients & subclasses of MacroAssembler should be using 'supportsFloatingPoint()'.
893 friend class MacroAssemblerX86
;
898 // All X86 Macs are guaranteed to support at least SSE2,
899 static bool isSSE2Present()
904 #else // PLATFORM(MAC)
906 enum SSE2CheckState
{
912 static bool isSSE2Present()
914 if (s_sse2CheckState
== NotCheckedSSE2
) {
915 // Default the flags value to zero; if the compiler is
916 // not MSVC or GCC we will read this as SSE2 not present.
920 mov eax
, 1 // cpuid function 1 gives us the standard feature set
933 : "%eax", "%ecx", "%edx"
936 static const int SSE2FeatureBit
= 1 << 26;
937 s_sse2CheckState
= (flags
& SSE2FeatureBit
) ? HasSSE2
: NoSSE2
;
940 ASSERT(s_sse2CheckState
!= NotCheckedSSE2
);
942 return s_sse2CheckState
== HasSSE2
;
945 static SSE2CheckState s_sse2CheckState
;
947 #endif // PLATFORM(MAC)
948 #elif !defined(NDEBUG) // PLATFORM(X86)
950 // On x86-64 we should never be checking for SSE2 in a non-debug build,
951 // but non debug add this method to keep the asserts above happy.
952 static bool isSSE2Present()
962 #endif // ENABLE(ASSEMBLER)
964 #endif // MacroAssemblerX86Common_h