Home | History | Annotate | Download | only in assembler
      1 /*
      2  * Copyright (C) 2008 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      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.
     12  *
     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.
     24  */
     25 
     26 #ifndef MacroAssemblerX86Common_h
     27 #define MacroAssemblerX86Common_h
     28 
     29 #if ENABLE(ASSEMBLER)
     30 
     31 #include "X86Assembler.h"
     32 #include "AbstractMacroAssembler.h"
     33 
     34 namespace JSC {
     35 
     36 class MacroAssemblerX86Common : public AbstractMacroAssembler<X86Assembler> {
     37     static const int DoubleConditionBitInvert = 0x10;
     38     static const int DoubleConditionBitSpecial = 0x20;
     39     static const int DoubleConditionBits = DoubleConditionBitInvert | DoubleConditionBitSpecial;
     40 
     41 public:
     42     typedef X86Assembler::FPRegisterID FPRegisterID;
     43 
     44     enum Condition {
     45         Equal = X86Assembler::ConditionE,
     46         NotEqual = X86Assembler::ConditionNE,
     47         Above = X86Assembler::ConditionA,
     48         AboveOrEqual = X86Assembler::ConditionAE,
     49         Below = X86Assembler::ConditionB,
     50         BelowOrEqual = X86Assembler::ConditionBE,
     51         GreaterThan = X86Assembler::ConditionG,
     52         GreaterThanOrEqual = X86Assembler::ConditionGE,
     53         LessThan = X86Assembler::ConditionL,
     54         LessThanOrEqual = X86Assembler::ConditionLE,
     55         Overflow = X86Assembler::ConditionO,
     56         Signed = X86Assembler::ConditionS,
     57         Zero = X86Assembler::ConditionE,
     58         NonZero = X86Assembler::ConditionNE
     59     };
     60 
     61     enum DoubleCondition {
     62         // These conditions will only evaluate to true if the comparison is ordered - i.e. neither operand is NaN.
     63         DoubleEqual = X86Assembler::ConditionE | DoubleConditionBitSpecial,
     64         DoubleNotEqual = X86Assembler::ConditionNE,
     65         DoubleGreaterThan = X86Assembler::ConditionA,
     66         DoubleGreaterThanOrEqual = X86Assembler::ConditionAE,
     67         DoubleLessThan = X86Assembler::ConditionA | DoubleConditionBitInvert,
     68         DoubleLessThanOrEqual = X86Assembler::ConditionAE | DoubleConditionBitInvert,
     69         // If either operand is NaN, these conditions always evaluate to true.
     70         DoubleEqualOrUnordered = X86Assembler::ConditionE,
     71         DoubleNotEqualOrUnordered = X86Assembler::ConditionNE | DoubleConditionBitSpecial,
     72         DoubleGreaterThanOrUnordered = X86Assembler::ConditionB | DoubleConditionBitInvert,
     73         DoubleGreaterThanOrEqualOrUnordered = X86Assembler::ConditionBE | DoubleConditionBitInvert,
     74         DoubleLessThanOrUnordered = X86Assembler::ConditionB,
     75         DoubleLessThanOrEqualOrUnordered = X86Assembler::ConditionBE,
     76     };
     77     COMPILE_ASSERT(
     78         !((X86Assembler::ConditionE | X86Assembler::ConditionNE | X86Assembler::ConditionA | X86Assembler::ConditionAE | X86Assembler::ConditionB | X86Assembler::ConditionBE) & DoubleConditionBits),
     79         DoubleConditionBits_should_not_interfere_with_X86Assembler_Condition_codes);
     80 
     81     static const RegisterID stackPointerRegister = X86Registers::esp;
     82 
     83     // Integer arithmetic operations:
     84     //
     85     // Operations are typically two operand - operation(source, srcDst)
     86     // For many operations the source may be an TrustedImm32, the srcDst operand
     87     // may often be a memory location (explictly described using an Address
     88     // object).
     89 
     90     void add32(RegisterID src, RegisterID dest)
     91     {
     92         m_assembler.addl_rr(src, dest);
     93     }
     94 
     95     void add32(TrustedImm32 imm, Address address)
     96     {
     97         m_assembler.addl_im(imm.m_value, address.offset, address.base);
     98     }
     99 
    100     void add32(TrustedImm32 imm, RegisterID dest)
    101     {
    102         m_assembler.addl_ir(imm.m_value, dest);
    103     }
    104 
    105     void add32(Address src, RegisterID dest)
    106     {
    107         m_assembler.addl_mr(src.offset, src.base, dest);
    108     }
    109 
    110     void add32(RegisterID src, Address dest)
    111     {
    112         m_assembler.addl_rm(src, dest.offset, dest.base);
    113     }
    114 
    115     void and32(RegisterID src, RegisterID dest)
    116     {
    117         m_assembler.andl_rr(src, dest);
    118     }
    119 
    120     void and32(TrustedImm32 imm, RegisterID dest)
    121     {
    122         m_assembler.andl_ir(imm.m_value, dest);
    123     }
    124 
    125     void and32(RegisterID src, Address dest)
    126     {
    127         m_assembler.andl_rm(src, dest.offset, dest.base);
    128     }
    129 
    130     void and32(Address src, RegisterID dest)
    131     {
    132         m_assembler.andl_mr(src.offset, src.base, dest);
    133     }
    134 
    135     void and32(TrustedImm32 imm, Address address)
    136     {
    137         m_assembler.andl_im(imm.m_value, address.offset, address.base);
    138     }
    139 
    140     void and32(RegisterID op1, RegisterID op2, RegisterID dest)
    141     {
    142         if (op1 == op2)
    143             zeroExtend32ToPtr(op1, dest);
    144         else if (op1 == dest)
    145             and32(op2, dest);
    146         else {
    147             move(op2, dest);
    148             and32(op1, dest);
    149         }
    150     }
    151 
    152     void and32(TrustedImm32 imm, RegisterID src, RegisterID dest)
    153     {
    154         move(src, dest);
    155         and32(imm, dest);
    156     }
    157 
    158     void lshift32(RegisterID shift_amount, RegisterID dest)
    159     {
    160         ASSERT(shift_amount != dest);
    161 
    162         if (shift_amount == X86Registers::ecx)
    163             m_assembler.shll_CLr(dest);
    164         else {
    165             // On x86 we can only shift by ecx; if asked to shift by another register we'll
    166             // need rejig the shift amount into ecx first, and restore the registers afterwards.
    167             // If we dest is ecx, then shift the swapped register!
    168             swap(shift_amount, X86Registers::ecx);
    169             m_assembler.shll_CLr(dest == X86Registers::ecx ? shift_amount : dest);
    170             swap(shift_amount, X86Registers::ecx);
    171         }
    172     }
    173 
    174     void lshift32(RegisterID src, RegisterID shift_amount, RegisterID dest)
    175     {
    176         ASSERT(shift_amount != dest);
    177 
    178         if (src != dest)
    179             move(src, dest);
    180         lshift32(shift_amount, dest);
    181     }
    182 
    183     void lshift32(TrustedImm32 imm, RegisterID dest)
    184     {
    185         m_assembler.shll_i8r(imm.m_value, dest);
    186     }
    187 
    188     void lshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
    189     {
    190         if (src != dest)
    191             move(src, dest);
    192         lshift32(imm, dest);
    193     }
    194 
    195     void mul32(RegisterID src, RegisterID dest)
    196     {
    197         m_assembler.imull_rr(src, dest);
    198     }
    199 
    200     void mul32(Address src, RegisterID dest)
    201     {
    202         m_assembler.imull_mr(src.offset, src.base, dest);
    203     }
    204 
    205     void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest)
    206     {
    207         m_assembler.imull_i32r(src, imm.m_value, dest);
    208     }
    209 
    210     void neg32(RegisterID srcDest)
    211     {
    212         m_assembler.negl_r(srcDest);
    213     }
    214 
    215     void neg32(Address srcDest)
    216     {
    217         m_assembler.negl_m(srcDest.offset, srcDest.base);
    218     }
    219 
    220     void not32(RegisterID srcDest)
    221     {
    222         m_assembler.notl_r(srcDest);
    223     }
    224 
    225     void not32(Address srcDest)
    226     {
    227         m_assembler.notl_m(srcDest.offset, srcDest.base);
    228     }
    229 
    230     void or32(RegisterID src, RegisterID dest)
    231     {
    232         m_assembler.orl_rr(src, dest);
    233     }
    234 
    235     void or32(TrustedImm32 imm, RegisterID dest)
    236     {
    237         m_assembler.orl_ir(imm.m_value, dest);
    238     }
    239 
    240     void or32(RegisterID src, Address dest)
    241     {
    242         m_assembler.orl_rm(src, dest.offset, dest.base);
    243     }
    244 
    245     void or32(Address src, RegisterID dest)
    246     {
    247         m_assembler.orl_mr(src.offset, src.base, dest);
    248     }
    249 
    250     void or32(TrustedImm32 imm, Address address)
    251     {
    252         m_assembler.orl_im(imm.m_value, address.offset, address.base);
    253     }
    254 
    255     void or32(RegisterID op1, RegisterID op2, RegisterID dest)
    256     {
    257         if (op1 == op2)
    258             zeroExtend32ToPtr(op1, dest);
    259         else if (op1 == dest)
    260             or32(op2, dest);
    261         else {
    262             move(op2, dest);
    263             or32(op1, dest);
    264         }
    265     }
    266 
    267     void or32(TrustedImm32 imm, RegisterID src, RegisterID dest)
    268     {
    269         move(src, dest);
    270         or32(imm, dest);
    271     }
    272 
    273     void rshift32(RegisterID shift_amount, RegisterID dest)
    274     {
    275         ASSERT(shift_amount != dest);
    276 
    277         if (shift_amount == X86Registers::ecx)
    278             m_assembler.sarl_CLr(dest);
    279         else {
    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 we dest is ecx, then shift the swapped register!
    283             swap(shift_amount, X86Registers::ecx);
    284             m_assembler.sarl_CLr(dest == X86Registers::ecx ? shift_amount : dest);
    285             swap(shift_amount, X86Registers::ecx);
    286         }
    287     }
    288 
    289     void rshift32(RegisterID src, RegisterID shift_amount, RegisterID dest)
    290     {
    291         ASSERT(shift_amount != dest);
    292 
    293         if (src != dest)
    294             move(src, dest);
    295         rshift32(shift_amount, dest);
    296     }
    297 
    298     void rshift32(TrustedImm32 imm, RegisterID dest)
    299     {
    300         m_assembler.sarl_i8r(imm.m_value, dest);
    301     }
    302 
    303     void rshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
    304     {
    305         if (src != dest)
    306             move(src, dest);
    307         rshift32(imm, dest);
    308     }
    309 
    310     void urshift32(RegisterID shift_amount, RegisterID dest)
    311     {
    312         ASSERT(shift_amount != dest);
    313 
    314         if (shift_amount == X86Registers::ecx)
    315             m_assembler.shrl_CLr(dest);
    316         else {
    317             // On x86 we can only shift by ecx; if asked to shift by another register we'll
    318             // need rejig the shift amount into ecx first, and restore the registers afterwards.
    319             // If we dest is ecx, then shift the swapped register!
    320             swap(shift_amount, X86Registers::ecx);
    321             m_assembler.shrl_CLr(dest == X86Registers::ecx ? shift_amount : dest);
    322             swap(shift_amount, X86Registers::ecx);
    323         }
    324     }
    325 
    326     void urshift32(RegisterID src, RegisterID shift_amount, RegisterID dest)
    327     {
    328         ASSERT(shift_amount != dest);
    329 
    330         if (src != dest)
    331             move(src, dest);
    332         urshift32(shift_amount, dest);
    333     }
    334 
    335     void urshift32(TrustedImm32 imm, RegisterID dest)
    336     {
    337         m_assembler.shrl_i8r(imm.m_value, dest);
    338     }
    339 
    340     void urshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
    341     {
    342         if (src != dest)
    343             move(src, dest);
    344         urshift32(imm, dest);
    345     }
    346 
    347     void sub32(RegisterID src, RegisterID dest)
    348     {
    349         m_assembler.subl_rr(src, dest);
    350     }
    351 
    352     void sub32(TrustedImm32 imm, RegisterID dest)
    353     {
    354         m_assembler.subl_ir(imm.m_value, dest);
    355     }
    356 
    357     void sub32(TrustedImm32 imm, Address address)
    358     {
    359         m_assembler.subl_im(imm.m_value, address.offset, address.base);
    360     }
    361 
    362     void sub32(Address src, RegisterID dest)
    363     {
    364         m_assembler.subl_mr(src.offset, src.base, dest);
    365     }
    366 
    367     void sub32(RegisterID src, Address dest)
    368     {
    369         m_assembler.subl_rm(src, dest.offset, dest.base);
    370     }
    371 
    372 
    373     void xor32(RegisterID src, RegisterID dest)
    374     {
    375         m_assembler.xorl_rr(src, dest);
    376     }
    377 
    378     void xor32(TrustedImm32 imm, Address dest)
    379     {
    380         m_assembler.xorl_im(imm.m_value, dest.offset, dest.base);
    381     }
    382 
    383     void xor32(TrustedImm32 imm, RegisterID dest)
    384     {
    385         m_assembler.xorl_ir(imm.m_value, dest);
    386     }
    387 
    388     void xor32(RegisterID src, Address dest)
    389     {
    390         m_assembler.xorl_rm(src, dest.offset, dest.base);
    391     }
    392 
    393     void xor32(Address src, RegisterID dest)
    394     {
    395         m_assembler.xorl_mr(src.offset, src.base, dest);
    396     }
    397 
    398     void xor32(RegisterID op1, RegisterID op2, RegisterID dest)
    399     {
    400         if (op1 == op2)
    401             move(TrustedImm32(0), dest);
    402         else if (op1 == dest)
    403             xor32(op2, dest);
    404         else {
    405             move(op2, dest);
    406             xor32(op1, dest);
    407         }
    408     }
    409 
    410     void xor32(TrustedImm32 imm, RegisterID src, RegisterID dest)
    411     {
    412         move(src, dest);
    413         xor32(imm, dest);
    414     }
    415 
    416     void sqrtDouble(FPRegisterID src, FPRegisterID dst)
    417     {
    418         m_assembler.sqrtsd_rr(src, dst);
    419     }
    420 
    421     // Memory access operations:
    422     //
    423     // Loads are of the form load(address, destination) and stores of the form
    424     // store(source, address).  The source for a store may be an TrustedImm32.  Address
    425     // operand objects to loads and store will be implicitly constructed if a
    426     // register is passed.
    427 
    428     void load32(ImplicitAddress address, RegisterID dest)
    429     {
    430         m_assembler.movl_mr(address.offset, address.base, dest);
    431     }
    432 
    433     void load32(BaseIndex address, RegisterID dest)
    434     {
    435         m_assembler.movl_mr(address.offset, address.base, address.index, address.scale, dest);
    436     }
    437 
    438     void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
    439     {
    440         load32(address, dest);
    441     }
    442 
    443     DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
    444     {
    445         m_assembler.movl_mr_disp32(address.offset, address.base, dest);
    446         return DataLabel32(this);
    447     }
    448 
    449     void load16(BaseIndex address, RegisterID dest)
    450     {
    451         m_assembler.movzwl_mr(address.offset, address.base, address.index, address.scale, dest);
    452     }
    453 
    454     void load16(Address address, RegisterID dest)
    455     {
    456         m_assembler.movzwl_mr(address.offset, address.base, dest);
    457     }
    458 
    459     DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
    460     {
    461         m_assembler.movl_rm_disp32(src, address.offset, address.base);
    462         return DataLabel32(this);
    463     }
    464 
    465     void store32(RegisterID src, ImplicitAddress address)
    466     {
    467         m_assembler.movl_rm(src, address.offset, address.base);
    468     }
    469 
    470     void store32(RegisterID src, BaseIndex address)
    471     {
    472         m_assembler.movl_rm(src, address.offset, address.base, address.index, address.scale);
    473     }
    474 
    475     void store32(TrustedImm32 imm, ImplicitAddress address)
    476     {
    477         m_assembler.movl_i32m(imm.m_value, address.offset, address.base);
    478     }
    479 
    480 
    481     // Floating-point operation:
    482     //
    483     // Presently only supports SSE, not x87 floating point.
    484 
    485     void moveDouble(FPRegisterID src, FPRegisterID dest)
    486     {
    487         ASSERT(isSSE2Present());
    488         if (src != dest)
    489             m_assembler.movsd_rr(src, dest);
    490     }
    491 
    492     void loadDouble(ImplicitAddress address, FPRegisterID dest)
    493     {
    494         ASSERT(isSSE2Present());
    495         m_assembler.movsd_mr(address.offset, address.base, dest);
    496     }
    497 
    498     void storeDouble(FPRegisterID src, ImplicitAddress address)
    499     {
    500         ASSERT(isSSE2Present());
    501         m_assembler.movsd_rm(src, address.offset, address.base);
    502     }
    503 
    504     void addDouble(FPRegisterID src, FPRegisterID dest)
    505     {
    506         ASSERT(isSSE2Present());
    507         m_assembler.addsd_rr(src, dest);
    508     }
    509 
    510     void addDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
    511     {
    512         ASSERT(isSSE2Present());
    513         if (op1 == dest)
    514             addDouble(op2, dest);
    515         else {
    516             moveDouble(op2, dest);
    517             addDouble(op1, dest);
    518         }
    519     }
    520 
    521     void addDouble(Address src, FPRegisterID dest)
    522     {
    523         ASSERT(isSSE2Present());
    524         m_assembler.addsd_mr(src.offset, src.base, dest);
    525     }
    526 
    527     void divDouble(FPRegisterID src, FPRegisterID dest)
    528     {
    529         ASSERT(isSSE2Present());
    530         m_assembler.divsd_rr(src, dest);
    531     }
    532 
    533     void divDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
    534     {
    535         // B := A / B is invalid.
    536         ASSERT(op1 == dest || op2 != dest);
    537 
    538         moveDouble(op1, dest);
    539         divDouble(op2, dest);
    540     }
    541 
    542     void divDouble(Address src, FPRegisterID dest)
    543     {
    544         ASSERT(isSSE2Present());
    545         m_assembler.divsd_mr(src.offset, src.base, dest);
    546     }
    547 
    548     void subDouble(FPRegisterID src, FPRegisterID dest)
    549     {
    550         ASSERT(isSSE2Present());
    551         m_assembler.subsd_rr(src, dest);
    552     }
    553 
    554     void subDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
    555     {
    556         // B := A - B is invalid.
    557         ASSERT(op1 == dest || op2 != dest);
    558 
    559         moveDouble(op1, dest);
    560         subDouble(op2, dest);
    561     }
    562 
    563     void subDouble(Address src, FPRegisterID dest)
    564     {
    565         ASSERT(isSSE2Present());
    566         m_assembler.subsd_mr(src.offset, src.base, dest);
    567     }
    568 
    569     void mulDouble(FPRegisterID src, FPRegisterID dest)
    570     {
    571         ASSERT(isSSE2Present());
    572         m_assembler.mulsd_rr(src, dest);
    573     }
    574 
    575     void mulDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
    576     {
    577         ASSERT(isSSE2Present());
    578         if (op1 == dest)
    579             mulDouble(op2, dest);
    580         else {
    581             moveDouble(op2, dest);
    582             mulDouble(op1, dest);
    583         }
    584     }
    585 
    586     void mulDouble(Address src, FPRegisterID dest)
    587     {
    588         ASSERT(isSSE2Present());
    589         m_assembler.mulsd_mr(src.offset, src.base, dest);
    590     }
    591 
    592     void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
    593     {
    594         ASSERT(isSSE2Present());
    595         m_assembler.cvtsi2sd_rr(src, dest);
    596     }
    597 
    598     void convertInt32ToDouble(Address src, FPRegisterID dest)
    599     {
    600         ASSERT(isSSE2Present());
    601         m_assembler.cvtsi2sd_mr(src.offset, src.base, dest);
    602     }
    603 
    604     Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
    605     {
    606         ASSERT(isSSE2Present());
    607 
    608         if (cond & DoubleConditionBitInvert)
    609             m_assembler.ucomisd_rr(left, right);
    610         else
    611             m_assembler.ucomisd_rr(right, left);
    612 
    613         if (cond == DoubleEqual) {
    614             Jump isUnordered(m_assembler.jp());
    615             Jump result = Jump(m_assembler.je());
    616             isUnordered.link(this);
    617             return result;
    618         } else if (cond == DoubleNotEqualOrUnordered) {
    619             Jump isUnordered(m_assembler.jp());
    620             Jump isEqual(m_assembler.je());
    621             isUnordered.link(this);
    622             Jump result = jump();
    623             isEqual.link(this);
    624             return result;
    625         }
    626 
    627         ASSERT(!(cond & DoubleConditionBitSpecial));
    628         return Jump(m_assembler.jCC(static_cast<X86Assembler::Condition>(cond & ~DoubleConditionBits)));
    629     }
    630 
    631     // Truncates 'src' to an integer, and places the resulting 'dest'.
    632     // If the result is not representable as a 32 bit value, branch.
    633     // May also branch for some values that are representable in 32 bits
    634     // (specifically, in this case, INT_MIN).
    635     enum BranchTruncateType { BranchIfTruncateFailed, BranchIfTruncateSuccessful };
    636     Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed)
    637     {
    638         ASSERT(isSSE2Present());
    639         m_assembler.cvttsd2si_rr(src, dest);
    640         return branch32(branchType ? NotEqual : Equal, dest, TrustedImm32(0x80000000));
    641     }
    642 
    643     // Convert 'src' to an integer, and places the resulting 'dest'.
    644     // If the result is not representable as a 32 bit value, branch.
    645     // May also branch for some values that are representable in 32 bits
    646     // (specifically, in this case, 0).
    647     void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp)
    648     {
    649         ASSERT(isSSE2Present());
    650         m_assembler.cvttsd2si_rr(src, dest);
    651 
    652         // If the result is zero, it might have been -0.0, and the double comparison won't catch this!
    653         failureCases.append(branchTest32(Zero, dest));
    654 
    655         // Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump.
    656         convertInt32ToDouble(dest, fpTemp);
    657         m_assembler.ucomisd_rr(fpTemp, src);
    658         failureCases.append(m_assembler.jp());
    659         failureCases.append(m_assembler.jne());
    660     }
    661 
    662     Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID scratch)
    663     {
    664         ASSERT(isSSE2Present());
    665         m_assembler.xorpd_rr(scratch, scratch);
    666         return branchDouble(DoubleNotEqual, reg, scratch);
    667     }
    668 
    669     Jump branchDoubleZeroOrNaN(FPRegisterID reg, FPRegisterID scratch)
    670     {
    671         ASSERT(isSSE2Present());
    672         m_assembler.xorpd_rr(scratch, scratch);
    673         return branchDouble(DoubleEqualOrUnordered, reg, scratch);
    674     }
    675 
    676     // Stack manipulation operations:
    677     //
    678     // The ABI is assumed to provide a stack abstraction to memory,
    679     // containing machine word sized units of data.  Push and pop
    680     // operations add and remove a single register sized unit of data
    681     // to or from the stack.  Peek and poke operations read or write
    682     // values on the stack, without moving the current stack position.
    683 
    684     void pop(RegisterID dest)
    685     {
    686         m_assembler.pop_r(dest);
    687     }
    688 
    689     void push(RegisterID src)
    690     {
    691         m_assembler.push_r(src);
    692     }
    693 
    694     void push(Address address)
    695     {
    696         m_assembler.push_m(address.offset, address.base);
    697     }
    698 
    699     void push(TrustedImm32 imm)
    700     {
    701         m_assembler.push_i32(imm.m_value);
    702     }
    703 
    704 
    705     // Register move operations:
    706     //
    707     // Move values in registers.
    708 
    709     void move(TrustedImm32 imm, RegisterID dest)
    710     {
    711         // Note: on 64-bit the TrustedImm32 value is zero extended into the register, it
    712         // may be useful to have a separate version that sign extends the value?
    713         if (!imm.m_value)
    714             m_assembler.xorl_rr(dest, dest);
    715         else
    716             m_assembler.movl_i32r(imm.m_value, dest);
    717     }
    718 
    719 #if CPU(X86_64)
    720     void move(RegisterID src, RegisterID dest)
    721     {
    722         // Note: on 64-bit this is is a full register move; perhaps it would be
    723         // useful to have separate move32 & movePtr, with move32 zero extending?
    724         if (src != dest)
    725             m_assembler.movq_rr(src, dest);
    726     }
    727 
    728     void move(TrustedImmPtr imm, RegisterID dest)
    729     {
    730         m_assembler.movq_i64r(imm.asIntptr(), dest);
    731     }
    732 
    733     void swap(RegisterID reg1, RegisterID reg2)
    734     {
    735         if (reg1 != reg2)
    736             m_assembler.xchgq_rr(reg1, reg2);
    737     }
    738 
    739     void signExtend32ToPtr(RegisterID src, RegisterID dest)
    740     {
    741         m_assembler.movsxd_rr(src, dest);
    742     }
    743 
    744     void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
    745     {
    746         m_assembler.movl_rr(src, dest);
    747     }
    748 #else
    749     void move(RegisterID src, RegisterID dest)
    750     {
    751         if (src != dest)
    752             m_assembler.movl_rr(src, dest);
    753     }
    754 
    755     void move(TrustedImmPtr imm, RegisterID dest)
    756     {
    757         m_assembler.movl_i32r(imm.asIntptr(), dest);
    758     }
    759 
    760     void swap(RegisterID reg1, RegisterID reg2)
    761     {
    762         if (reg1 != reg2)
    763             m_assembler.xchgl_rr(reg1, reg2);
    764     }
    765 
    766     void signExtend32ToPtr(RegisterID src, RegisterID dest)
    767     {
    768         move(src, dest);
    769     }
    770 
    771     void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
    772     {
    773         move(src, dest);
    774     }
    775 #endif
    776 
    777 
    778     // Forwards / external control flow operations:
    779     //
    780     // This set of jump and conditional branch operations return a Jump
    781     // object which may linked at a later point, allow forwards jump,
    782     // or jumps that will require external linkage (after the code has been
    783     // relocated).
    784     //
    785     // For branches, signed <, >, <= and >= are denoted as l, g, le, and ge
    786     // respecitvely, for unsigned comparisons the names b, a, be, and ae are
    787     // used (representing the names 'below' and 'above').
    788     //
    789     // Operands to the comparision are provided in the expected order, e.g.
    790     // jle32(reg1, TrustedImm32(5)) will branch if the value held in reg1, when
    791     // treated as a signed 32bit value, is less than or equal to 5.
    792     //
    793     // jz and jnz test whether the first operand is equal to zero, and take
    794     // an optional second operand of a mask under which to perform the test.
    795 
    796 public:
    797     Jump branch8(Condition cond, Address left, TrustedImm32 right)
    798     {
    799         m_assembler.cmpb_im(right.m_value, left.offset, left.base);
    800         return Jump(m_assembler.jCC(x86Condition(cond)));
    801     }
    802 
    803     Jump branch32(Condition cond, RegisterID left, RegisterID right)
    804     {
    805         m_assembler.cmpl_rr(right, left);
    806         return Jump(m_assembler.jCC(x86Condition(cond)));
    807     }
    808 
    809     Jump branch32(Condition cond, RegisterID left, TrustedImm32 right)
    810     {
    811         if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
    812             m_assembler.testl_rr(left, left);
    813         else
    814             m_assembler.cmpl_ir(right.m_value, left);
    815         return Jump(m_assembler.jCC(x86Condition(cond)));
    816     }
    817 
    818     Jump branch32(Condition cond, RegisterID left, Address right)
    819     {
    820         m_assembler.cmpl_mr(right.offset, right.base, left);
    821         return Jump(m_assembler.jCC(x86Condition(cond)));
    822     }
    823 
    824     Jump branch32(Condition cond, Address left, RegisterID right)
    825     {
    826         m_assembler.cmpl_rm(right, left.offset, left.base);
    827         return Jump(m_assembler.jCC(x86Condition(cond)));
    828     }
    829 
    830     Jump branch32(Condition cond, Address left, TrustedImm32 right)
    831     {
    832         m_assembler.cmpl_im(right.m_value, left.offset, left.base);
    833         return Jump(m_assembler.jCC(x86Condition(cond)));
    834     }
    835 
    836     Jump branch32(Condition cond, BaseIndex left, TrustedImm32 right)
    837     {
    838         m_assembler.cmpl_im(right.m_value, left.offset, left.base, left.index, left.scale);
    839         return Jump(m_assembler.jCC(x86Condition(cond)));
    840     }
    841 
    842     Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, TrustedImm32 right)
    843     {
    844         return branch32(cond, left, right);
    845     }
    846 
    847     Jump branch16(Condition cond, BaseIndex left, RegisterID right)
    848     {
    849         m_assembler.cmpw_rm(right, left.offset, left.base, left.index, left.scale);
    850         return Jump(m_assembler.jCC(x86Condition(cond)));
    851     }
    852 
    853     Jump branch16(Condition cond, BaseIndex left, TrustedImm32 right)
    854     {
    855         ASSERT(!(right.m_value & 0xFFFF0000));
    856 
    857         m_assembler.cmpw_im(right.m_value, left.offset, left.base, left.index, left.scale);
    858         return Jump(m_assembler.jCC(x86Condition(cond)));
    859     }
    860 
    861     Jump branchTest32(Condition cond, RegisterID reg, RegisterID mask)
    862     {
    863         ASSERT((cond == Zero) || (cond == NonZero) || (cond == Signed));
    864         m_assembler.testl_rr(reg, mask);
    865         return Jump(m_assembler.jCC(x86Condition(cond)));
    866     }
    867 
    868     Jump branchTest32(Condition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
    869     {
    870         ASSERT((cond == Zero) || (cond == NonZero) || (cond == Signed));
    871         // if we are only interested in the low seven bits, this can be tested with a testb
    872         if (mask.m_value == -1)
    873             m_assembler.testl_rr(reg, reg);
    874         else if ((mask.m_value & ~0x7f) == 0)
    875             m_assembler.testb_i8r(mask.m_value, reg);
    876         else
    877             m_assembler.testl_i32r(mask.m_value, reg);
    878         return Jump(m_assembler.jCC(x86Condition(cond)));
    879     }
    880 
    881     Jump branchTest32(Condition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
    882     {
    883         ASSERT((cond == Zero) || (cond == NonZero) || (cond == Signed));
    884         if (mask.m_value == -1)
    885             m_assembler.cmpl_im(0, address.offset, address.base);
    886         else
    887             m_assembler.testl_i32m(mask.m_value, address.offset, address.base);
    888         return Jump(m_assembler.jCC(x86Condition(cond)));
    889     }
    890 
    891     Jump branchTest32(Condition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
    892     {
    893         ASSERT((cond == Zero) || (cond == NonZero) || (cond == Signed));
    894         if (mask.m_value == -1)
    895             m_assembler.cmpl_im(0, address.offset, address.base, address.index, address.scale);
    896         else
    897             m_assembler.testl_i32m(mask.m_value, address.offset, address.base, address.index, address.scale);
    898         return Jump(m_assembler.jCC(x86Condition(cond)));
    899     }
    900 
    901     Jump branchTest8(Condition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
    902     {
    903         // Byte in TrustedImm32 is not well defined, so be a little permisive here, but don't accept nonsense values.
    904         ASSERT(mask.m_value >= -128 && mask.m_value <= 255);
    905         ASSERT((cond == Zero) || (cond == NonZero) || (cond == Signed));
    906         if (mask.m_value == -1)
    907             m_assembler.testb_rr(reg, reg);
    908         else
    909             m_assembler.testb_i8r(mask.m_value, reg);
    910         return Jump(m_assembler.jCC(x86Condition(cond)));
    911     }
    912 
    913     Jump branchTest8(Condition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
    914     {
    915         // Byte in TrustedImm32 is not well defined, so be a little permisive here, but don't accept nonsense values.
    916         ASSERT(mask.m_value >= -128 && mask.m_value <= 255);
    917         ASSERT((cond == Zero) || (cond == NonZero) || (cond == Signed));
    918         if (mask.m_value == -1)
    919             m_assembler.cmpb_im(0, address.offset, address.base);
    920         else
    921             m_assembler.testb_im(mask.m_value, address.offset, address.base);
    922         return Jump(m_assembler.jCC(x86Condition(cond)));
    923     }
    924 
    925     Jump branchTest8(Condition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
    926     {
    927         // Byte in TrustedImm32 is not well defined, so be a little permisive here, but don't accept nonsense values.
    928         ASSERT(mask.m_value >= -128 && mask.m_value <= 255);
    929         ASSERT((cond == Zero) || (cond == NonZero) || (cond == Signed));
    930         if (mask.m_value == -1)
    931             m_assembler.cmpb_im(0, address.offset, address.base, address.index, address.scale);
    932         else
    933             m_assembler.testb_im(mask.m_value, address.offset, address.base, address.index, address.scale);
    934         return Jump(m_assembler.jCC(x86Condition(cond)));
    935     }
    936 
    937     Jump jump()
    938     {
    939         return Jump(m_assembler.jmp());
    940     }
    941 
    942     void jump(RegisterID target)
    943     {
    944         m_assembler.jmp_r(target);
    945     }
    946 
    947     // Address is a memory location containing the address to jump to
    948     void jump(Address address)
    949     {
    950         m_assembler.jmp_m(address.offset, address.base);
    951     }
    952 
    953 
    954     // Arithmetic control flow operations:
    955     //
    956     // This set of conditional branch operations branch based
    957     // on the result of an arithmetic operation.  The operation
    958     // is performed as normal, storing the result.
    959     //
    960     // * jz operations branch if the result is zero.
    961     // * jo operations branch if the (signed) arithmetic
    962     //   operation caused an overflow to occur.
    963 
    964     Jump branchAdd32(Condition cond, RegisterID src, RegisterID dest)
    965     {
    966         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
    967         add32(src, dest);
    968         return Jump(m_assembler.jCC(x86Condition(cond)));
    969     }
    970 
    971     Jump branchAdd32(Condition cond, TrustedImm32 imm, RegisterID dest)
    972     {
    973         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
    974         add32(imm, dest);
    975         return Jump(m_assembler.jCC(x86Condition(cond)));
    976     }
    977 
    978     Jump branchAdd32(Condition cond, TrustedImm32 src, Address dest)
    979     {
    980         ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
    981         add32(src, dest);
    982         return Jump(m_assembler.jCC(x86Condition(cond)));
    983     }
    984 
    985     Jump branchAdd32(Condition cond, RegisterID src, Address dest)
    986     {
    987         ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
    988         add32(src, dest);
    989         return Jump(m_assembler.jCC(x86Condition(cond)));
    990     }
    991 
    992     Jump branchAdd32(Condition cond, Address src, RegisterID dest)
    993     {
    994         ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
    995         add32(src, dest);
    996         return Jump(m_assembler.jCC(x86Condition(cond)));
    997     }
    998 
    999     Jump branchAdd32(Condition cond, RegisterID src1, RegisterID src2, RegisterID dest)
   1000     {
   1001         if (src1 == dest)
   1002             return branchAdd32(cond, src2, dest);
   1003         move(src2, dest);
   1004         return branchAdd32(cond, src1, dest);
   1005     }
   1006 
   1007     Jump branchAdd32(Condition cond, RegisterID src, TrustedImm32 imm, RegisterID dest)
   1008     {
   1009         move(src, dest);
   1010         return branchAdd32(cond, imm, dest);
   1011     }
   1012 
   1013     Jump branchMul32(Condition cond, RegisterID src, RegisterID dest)
   1014     {
   1015         ASSERT(cond == Overflow);
   1016         mul32(src, dest);
   1017         return Jump(m_assembler.jCC(x86Condition(cond)));
   1018     }
   1019 
   1020     Jump branchMul32(Condition cond, Address src, RegisterID dest)
   1021     {
   1022         ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
   1023         mul32(src, dest);
   1024         return Jump(m_assembler.jCC(x86Condition(cond)));
   1025     }
   1026 
   1027     Jump branchMul32(Condition cond, TrustedImm32 imm, RegisterID src, RegisterID dest)
   1028     {
   1029         ASSERT(cond == Overflow);
   1030         mul32(imm, src, dest);
   1031         return Jump(m_assembler.jCC(x86Condition(cond)));
   1032     }
   1033 
   1034     Jump branchMul32(Condition cond, RegisterID src1, RegisterID src2, RegisterID dest)
   1035     {
   1036         if (src1 == dest)
   1037             return branchMul32(cond, src2, dest);
   1038         move(src2, dest);
   1039         return branchMul32(cond, src1, dest);
   1040     }
   1041 
   1042     Jump branchSub32(Condition cond, RegisterID src, RegisterID dest)
   1043     {
   1044         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
   1045         sub32(src, dest);
   1046         return Jump(m_assembler.jCC(x86Condition(cond)));
   1047     }
   1048 
   1049     Jump branchSub32(Condition cond, TrustedImm32 imm, RegisterID dest)
   1050     {
   1051         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
   1052         sub32(imm, dest);
   1053         return Jump(m_assembler.jCC(x86Condition(cond)));
   1054     }
   1055 
   1056     Jump branchSub32(Condition cond, TrustedImm32 imm, Address dest)
   1057     {
   1058         ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
   1059         sub32(imm, dest);
   1060         return Jump(m_assembler.jCC(x86Condition(cond)));
   1061     }
   1062 
   1063     Jump branchSub32(Condition cond, RegisterID src, Address dest)
   1064     {
   1065         ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
   1066         sub32(src, dest);
   1067         return Jump(m_assembler.jCC(x86Condition(cond)));
   1068     }
   1069 
   1070     Jump branchSub32(Condition cond, Address src, RegisterID dest)
   1071     {
   1072         ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
   1073         sub32(src, dest);
   1074         return Jump(m_assembler.jCC(x86Condition(cond)));
   1075     }
   1076 
   1077     Jump branchSub32(Condition cond, RegisterID src1, RegisterID src2, RegisterID dest)
   1078     {
   1079         // B := A - B is invalid.
   1080         ASSERT(src1 == dest || src2 != dest);
   1081 
   1082         move(src1, dest);
   1083         return branchSub32(cond, src2, dest);
   1084     }
   1085 
   1086     Jump branchSub32(Condition cond, RegisterID src1, TrustedImm32 src2, RegisterID dest)
   1087     {
   1088         move(src1, dest);
   1089         return branchSub32(cond, src2, dest);
   1090     }
   1091 
   1092     Jump branchNeg32(Condition cond, RegisterID srcDest)
   1093     {
   1094         ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
   1095         neg32(srcDest);
   1096         return Jump(m_assembler.jCC(x86Condition(cond)));
   1097     }
   1098 
   1099     Jump branchOr32(Condition cond, RegisterID src, RegisterID dest)
   1100     {
   1101         ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero));
   1102         or32(src, dest);
   1103         return Jump(m_assembler.jCC(x86Condition(cond)));
   1104     }
   1105 
   1106 
   1107     // Miscellaneous operations:
   1108 
   1109     void breakpoint()
   1110     {
   1111         m_assembler.int3();
   1112     }
   1113 
   1114     Call nearCall()
   1115     {
   1116         return Call(m_assembler.call(), Call::LinkableNear);
   1117     }
   1118 
   1119     Call call(RegisterID target)
   1120     {
   1121         return Call(m_assembler.call(target), Call::None);
   1122     }
   1123 
   1124     void call(Address address)
   1125     {
   1126         m_assembler.call_m(address.offset, address.base);
   1127     }
   1128 
   1129     void ret()
   1130     {
   1131         m_assembler.ret();
   1132     }
   1133 
   1134     void set8Compare32(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
   1135     {
   1136         m_assembler.cmpl_rr(right, left);
   1137         m_assembler.setCC_r(x86Condition(cond), dest);
   1138     }
   1139 
   1140     void set8Compare32(Condition cond, Address left, RegisterID right, RegisterID dest)
   1141     {
   1142         m_assembler.cmpl_mr(left.offset, left.base, right);
   1143         m_assembler.setCC_r(x86Condition(cond), dest);
   1144     }
   1145 
   1146     void set8Compare32(Condition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
   1147     {
   1148         if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
   1149             m_assembler.testl_rr(left, left);
   1150         else
   1151             m_assembler.cmpl_ir(right.m_value, left);
   1152         m_assembler.setCC_r(x86Condition(cond), dest);
   1153     }
   1154 
   1155     void set32Compare32(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
   1156     {
   1157         m_assembler.cmpl_rr(right, left);
   1158         m_assembler.setCC_r(x86Condition(cond), dest);
   1159         m_assembler.movzbl_rr(dest, dest);
   1160     }
   1161 
   1162     void set32Compare32(Condition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
   1163     {
   1164         if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
   1165             m_assembler.testl_rr(left, left);
   1166         else
   1167             m_assembler.cmpl_ir(right.m_value, left);
   1168         m_assembler.setCC_r(x86Condition(cond), dest);
   1169         m_assembler.movzbl_rr(dest, dest);
   1170     }
   1171 
   1172     // FIXME:
   1173     // The mask should be optional... paerhaps the argument order should be
   1174     // dest-src, operations always have a dest? ... possibly not true, considering
   1175     // asm ops like test, or pseudo ops like pop().
   1176 
   1177     void set32Test8(Condition cond, Address address, TrustedImm32 mask, RegisterID dest)
   1178     {
   1179         if (mask.m_value == -1)
   1180             m_assembler.cmpb_im(0, address.offset, address.base);
   1181         else
   1182             m_assembler.testb_im(mask.m_value, address.offset, address.base);
   1183         m_assembler.setCC_r(x86Condition(cond), dest);
   1184         m_assembler.movzbl_rr(dest, dest);
   1185     }
   1186 
   1187     void set32Test32(Condition cond, Address address, TrustedImm32 mask, RegisterID dest)
   1188     {
   1189         if (mask.m_value == -1)
   1190             m_assembler.cmpl_im(0, address.offset, address.base);
   1191         else
   1192             m_assembler.testl_i32m(mask.m_value, address.offset, address.base);
   1193         m_assembler.setCC_r(x86Condition(cond), dest);
   1194         m_assembler.movzbl_rr(dest, dest);
   1195     }
   1196 
   1197 protected:
   1198     X86Assembler::Condition x86Condition(Condition cond)
   1199     {
   1200         return static_cast<X86Assembler::Condition>(cond);
   1201     }
   1202 
   1203 private:
   1204     // Only MacroAssemblerX86 should be using the following method; SSE2 is always available on
   1205     // x86_64, and clients & subclasses of MacroAssembler should be using 'supportsFloatingPoint()'.
   1206     friend class MacroAssemblerX86;
   1207 
   1208 #if CPU(X86)
   1209 #if OS(MAC_OS_X)
   1210 
   1211     // All X86 Macs are guaranteed to support at least SSE2,
   1212     static bool isSSE2Present()
   1213     {
   1214         return true;
   1215     }
   1216 
   1217 #else // OS(MAC_OS_X)
   1218 
   1219     enum SSE2CheckState {
   1220         NotCheckedSSE2,
   1221         HasSSE2,
   1222         NoSSE2
   1223     };
   1224 
   1225     static bool isSSE2Present()
   1226     {
   1227         if (s_sse2CheckState == NotCheckedSSE2) {
   1228             // Default the flags value to zero; if the compiler is
   1229             // not MSVC or GCC we will read this as SSE2 not present.
   1230             int flags = 0;
   1231 #if COMPILER(MSVC)
   1232             _asm {
   1233                 mov eax, 1 // cpuid function 1 gives us the standard feature set
   1234                 cpuid;
   1235                 mov flags, edx;
   1236             }
   1237 #elif COMPILER(GCC)
   1238             asm (
   1239                  "movl $0x1, %%eax;"
   1240                  "pushl %%ebx;"
   1241                  "cpuid;"
   1242                  "popl %%ebx;"
   1243                  "movl %%edx, %0;"
   1244                  : "=g" (flags)
   1245                  :
   1246                  : "%eax", "%ecx", "%edx"
   1247                  );
   1248 #endif
   1249             static const int SSE2FeatureBit = 1 << 26;
   1250             s_sse2CheckState = (flags & SSE2FeatureBit) ? HasSSE2 : NoSSE2;
   1251         }
   1252         // Only check once.
   1253         ASSERT(s_sse2CheckState != NotCheckedSSE2);
   1254 
   1255         return s_sse2CheckState == HasSSE2;
   1256     }
   1257 
   1258     static SSE2CheckState s_sse2CheckState;
   1259 
   1260 #endif // OS(MAC_OS_X)
   1261 #elif !defined(NDEBUG) // CPU(X86)
   1262 
   1263     // On x86-64 we should never be checking for SSE2 in a non-debug build,
   1264     // but non debug add this method to keep the asserts above happy.
   1265     static bool isSSE2Present()
   1266     {
   1267         return true;
   1268     }
   1269 
   1270 #endif
   1271 };
   1272 
   1273 } // namespace JSC
   1274 
   1275 #endif // ENABLE(ASSEMBLER)
   1276 
   1277 #endif // MacroAssemblerX86Common_h
   1278