LCOV - code coverage report
Current view: directory - js/src/assembler/assembler - MacroAssemblerX86Common.h (source / functions) Found Hit Coverage
Test: app.info Lines: 470 422 89.8 %
Date: 2012-06-02 Functions: 116 113 97.4 %

       1                 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2                 :  * vim: set ts=8 sw=4 et tw=79:
       3                 :  *
       4                 :  * ***** BEGIN LICENSE BLOCK *****
       5                 :  * Copyright (C) 2008 Apple Inc. All rights reserved.
       6                 :  *
       7                 :  * Redistribution and use in source and binary forms, with or without
       8                 :  * modification, are permitted provided that the following conditions
       9                 :  * are met:
      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.
      15                 :  *
      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. 
      27                 :  * 
      28                 :  * ***** END LICENSE BLOCK ***** */
      29                 : 
      30                 : #ifndef MacroAssemblerX86Common_h
      31                 : #define MacroAssemblerX86Common_h
      32                 : 
      33                 : #include "assembler/wtf/Platform.h"
      34                 : 
      35                 : #if ENABLE_ASSEMBLER
      36                 : 
      37                 : #include "X86Assembler.h"
      38                 : #include "AbstractMacroAssembler.h"
      39                 : 
      40                 : #if WTF_COMPILER_MSVC
      41                 : #if WTF_CPU_X86_64
      42                 : /* for __cpuid */
      43                 : #include <intrin.h>
      44                 : #endif
      45                 : #endif
      46                 : 
      47                 : namespace JSC {
      48                 : 
      49         1526632 : class MacroAssemblerX86Common : public AbstractMacroAssembler<X86Assembler> {
      50                 :     static const int DoubleConditionBitInvert = 0x10;
      51                 :     static const int DoubleConditionBitSpecial = 0x20;
      52                 :     static const int DoubleConditionBits = DoubleConditionBitInvert | DoubleConditionBitSpecial;
      53                 : 
      54                 : protected:
      55                 : #if WTF_CPU_X86_64
      56                 :     static const X86Registers::RegisterID scratchRegister = X86Registers::r11;
      57                 : #endif
      58                 : 
      59                 : public:
      60                 : 
      61                 :     enum Condition {
      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
      76                 :     };
      77                 : 
      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
      93                 :     };
      94                 :     static void staticAsserts() {
      95                 :         COMPILE_ASSERT(
      96                 :             !((X86Assembler::ConditionE | X86Assembler::ConditionNE | X86Assembler::ConditionA | X86Assembler::ConditionAE | X86Assembler::ConditionB | X86Assembler::ConditionBE) & DoubleConditionBits),
      97                 :             DoubleConditionBits_should_not_interfere_with_X86Assembler_Condition_codes);
      98                 :     }
      99                 : 
     100                 :     static const RegisterID stackPointerRegister = X86Registers::esp;
     101                 : 
     102           25760 :     static inline bool CanUse8Bit(RegisterID reg) {
     103                 :         return !!((1 << reg) & ~((1 << X86Registers::esp) |
     104                 :                                  (1 << X86Registers::edi) |
     105                 :                                  (1 << X86Registers::esi) |
     106           25760 :                                  (1 << X86Registers::ebp)));
     107                 :     }
     108                 : 
     109                 :     // Integer arithmetic operations:
     110                 :     //
     111                 :     // Operations are typically two operand - operation(source, srcDst)
     112                 :     // For many operations the source may be an Imm32, the srcDst operand
     113                 :     // may often be a memory location (explictly described using an Address
     114                 :     // object).
     115                 : 
     116          328883 :     void add32(RegisterID src, RegisterID dest)
     117                 :     {
     118          328883 :         m_assembler.addl_rr(src, dest);
     119          328883 :     }
     120                 : 
     121                 :     void add32(TrustedImm32 imm, Address address)
     122                 :     {
     123                 :         m_assembler.addl_im(imm.m_value, address.offset, address.base);
     124                 :     }
     125                 : 
     126         5647032 :     void add32(TrustedImm32 imm, RegisterID dest)
     127                 :     {
     128         5647032 :         m_assembler.addl_ir(imm.m_value, dest);
     129         5647032 :     }
     130                 :     
     131             276 :     void add32(Address src, RegisterID dest)
     132                 :     {
     133             276 :         m_assembler.addl_mr(src.offset, src.base, dest);
     134             276 :     }
     135                 : 
     136                 :     void add32(RegisterID src, Address dest)
     137                 :     {
     138                 :         m_assembler.addl_rm(src, dest.offset, dest.base);
     139                 :     }
     140                 :     
     141             914 :     void and32(RegisterID src, RegisterID dest)
     142                 :     {
     143             914 :         m_assembler.andl_rr(src, dest);
     144             914 :     }
     145                 : 
     146          154752 :     void and32(Imm32 imm, RegisterID dest)
     147                 :     {
     148          154752 :         m_assembler.andl_ir(imm.m_value, dest);
     149          154752 :     }
     150                 : 
     151                 :     void and32(RegisterID src, Address dest)
     152                 :     {
     153                 :         m_assembler.andl_rm(src, dest.offset, dest.base);
     154                 :     }
     155                 : 
     156              20 :     void and32(Address src, RegisterID dest)
     157                 :     {
     158              20 :         m_assembler.andl_mr(src.offset, src.base, dest);
     159              20 :     }
     160                 : 
     161                 :     void and32(Imm32 imm, Address address)
     162                 :     {
     163                 :         m_assembler.andl_im(imm.m_value, address.offset, address.base);
     164                 :     }
     165                 : 
     166            2593 :     void lshift32(Imm32 imm, RegisterID dest)
     167                 :     {
     168            2593 :         m_assembler.shll_i8r(imm.m_value, dest);
     169            2593 :     }
     170                 :     
     171            1153 :     void lshift32(RegisterID shift_amount, RegisterID dest)
     172                 :     {
     173                 :         // On x86 we can only shift by ecx; if asked to shift by another register we'll
     174                 :         // need rejig the shift amount into ecx first, and restore the registers afterwards.
     175            1153 :         if (shift_amount != X86Registers::ecx) {
     176               0 :             swap(shift_amount, X86Registers::ecx);
     177                 : 
     178                 :             // E.g. transform "shll %eax, %eax" -> "xchgl %eax, %ecx; shll %ecx, %ecx; xchgl %eax, %ecx"
     179               0 :             if (dest == shift_amount)
     180               0 :                 m_assembler.shll_CLr(X86Registers::ecx);
     181                 :             // E.g. transform "shll %eax, %ecx" -> "xchgl %eax, %ecx; shll %ecx, %eax; xchgl %eax, %ecx"
     182               0 :             else if (dest == X86Registers::ecx)
     183               0 :                 m_assembler.shll_CLr(shift_amount);
     184                 :             // E.g. transform "shll %eax, %ebx" -> "xchgl %eax, %ecx; shll %ecx, %ebx; xchgl %eax, %ecx"
     185                 :             else
     186               0 :                 m_assembler.shll_CLr(dest);
     187                 :         
     188               0 :             swap(shift_amount, X86Registers::ecx);
     189                 :         } else
     190            1153 :             m_assembler.shll_CLr(dest);
     191            1153 :     }
     192                 :     
     193            1939 :     void mul32(RegisterID src, RegisterID dest)
     194                 :     {
     195            1939 :         m_assembler.imull_rr(src, dest);
     196            1939 :     }
     197                 : 
     198                 :     void mul32(Address src, RegisterID dest)
     199                 :     {
     200                 :         m_assembler.imull_mr(src.offset, src.base, dest);
     201                 :     }
     202                 :     
     203            1881 :     void mul32(Imm32 imm, RegisterID src, RegisterID dest)
     204                 :     {
     205            1881 :         m_assembler.imull_i32r(src, imm.m_value, dest);
     206            1881 :     }
     207                 : 
     208                 :     void idiv(RegisterID reg)
     209                 :     {
     210                 :         m_assembler.cdq();
     211                 :         m_assembler.idivl_r(reg);
     212                 :     }
     213                 : 
     214           21265 :     void neg32(RegisterID srcDest)
     215                 :     {
     216           21265 :         m_assembler.negl_r(srcDest);
     217           21265 :     }
     218                 : 
     219                 :     void neg32(Address srcDest)
     220                 :     {
     221                 :         m_assembler.negl_m(srcDest.offset, srcDest.base);
     222                 :     }
     223                 : 
     224             167 :     void not32(RegisterID srcDest)
     225                 :     {
     226             167 :         m_assembler.notl_r(srcDest);
     227             167 :     }
     228                 : 
     229                 :     void not32(Address srcDest)
     230                 :     {
     231                 :         m_assembler.notl_m(srcDest.offset, srcDest.base);
     232                 :     }
     233                 :     
     234            2974 :     void or32(RegisterID src, RegisterID dest)
     235                 :     {
     236            2974 :         m_assembler.orl_rr(src, dest);
     237            2974 :     }
     238                 : 
     239           55295 :     void or32(TrustedImm32 imm, RegisterID dest)
     240                 :     {
     241           55295 :         m_assembler.orl_ir(imm.m_value, dest);
     242           55295 :     }
     243                 : 
     244                 :     void or32(RegisterID src, Address dest)
     245                 :     {
     246                 :         m_assembler.orl_rm(src, dest.offset, dest.base);
     247                 :     }
     248                 : 
     249               0 :     void or32(Address src, RegisterID dest)
     250                 :     {
     251               0 :         m_assembler.orl_mr(src.offset, src.base, dest);
     252               0 :     }
     253                 : 
     254                 :     void or32(TrustedImm32 imm, Address address)
     255                 :     {
     256                 :         m_assembler.orl_im(imm.m_value, address.offset, address.base);
     257                 :     }
     258                 : 
     259             884 :     void rshift32(RegisterID shift_amount, RegisterID dest)
     260                 :     {
     261                 :         // On x86 we can only shift by ecx; if asked to shift by another register we'll
     262                 :         // need rejig the shift amount into ecx first, and restore the registers afterwards.
     263             884 :         if (shift_amount != X86Registers::ecx) {
     264               0 :             swap(shift_amount, X86Registers::ecx);
     265                 : 
     266                 :             // E.g. transform "shll %eax, %eax" -> "xchgl %eax, %ecx; shll %ecx, %ecx; xchgl %eax, %ecx"
     267               0 :             if (dest == shift_amount)
     268               0 :                 m_assembler.sarl_CLr(X86Registers::ecx);
     269                 :             // E.g. transform "shll %eax, %ecx" -> "xchgl %eax, %ecx; shll %ecx, %eax; xchgl %eax, %ecx"
     270               0 :             else if (dest == X86Registers::ecx)
     271               0 :                 m_assembler.sarl_CLr(shift_amount);
     272                 :             // E.g. transform "shll %eax, %ebx" -> "xchgl %eax, %ecx; shll %ecx, %ebx; xchgl %eax, %ecx"
     273                 :             else
     274               0 :                 m_assembler.sarl_CLr(dest);
     275                 :         
     276               0 :             swap(shift_amount, X86Registers::ecx);
     277                 :         } else
     278             884 :             m_assembler.sarl_CLr(dest);
     279             884 :     }
     280                 : 
     281            3188 :     void rshift32(Imm32 imm, RegisterID dest)
     282                 :     {
     283            3188 :         m_assembler.sarl_i8r(imm.m_value, dest);
     284            3188 :     }
     285                 :     
     286             429 :     void urshift32(RegisterID shift_amount, RegisterID dest)
     287                 :     {
     288                 :         // On x86 we can only shift by ecx; if asked to shift by another register we'll
     289                 :         // need rejig the shift amount into ecx first, and restore the registers afterwards.
     290             429 :         if (shift_amount != X86Registers::ecx) {
     291               0 :             swap(shift_amount, X86Registers::ecx);
     292                 :             
     293                 :             // E.g. transform "shrl %eax, %eax" -> "xchgl %eax, %ecx; shrl %ecx, %ecx; xchgl %eax, %ecx"
     294               0 :             if (dest == shift_amount)
     295               0 :                 m_assembler.shrl_CLr(X86Registers::ecx);
     296                 :             // E.g. transform "shrl %eax, %ecx" -> "xchgl %eax, %ecx; shrl %ecx, %eax; xchgl %eax, %ecx"
     297               0 :             else if (dest == X86Registers::ecx)
     298               0 :                 m_assembler.shrl_CLr(shift_amount);
     299                 :             // E.g. transform "shrl %eax, %ebx" -> "xchgl %eax, %ecx; shrl %ecx, %ebx; xchgl %eax, %ecx"
     300                 :             else
     301               0 :                 m_assembler.shrl_CLr(dest);
     302                 :             
     303               0 :             swap(shift_amount, X86Registers::ecx);
     304                 :         } else
     305             429 :             m_assembler.shrl_CLr(dest);
     306             429 :     }
     307                 :     
     308            7373 :     void urshift32(Imm32 imm, RegisterID dest)
     309                 :     {
     310            7373 :         m_assembler.shrl_i8r(imm.m_value, dest);
     311            7373 :     }
     312                 : 
     313            4930 :     void sub32(RegisterID src, RegisterID dest)
     314                 :     {
     315            4930 :         m_assembler.subl_rr(src, dest);
     316            4930 :     }
     317                 :     
     318          262959 :     void sub32(TrustedImm32 imm, RegisterID dest)
     319                 :     {
     320          262959 :         m_assembler.subl_ir(imm.m_value, dest);
     321          262959 :     }
     322                 :     
     323                 :     void sub32(TrustedImm32 imm, Address address)
     324                 :     {
     325                 :         m_assembler.subl_im(imm.m_value, address.offset, address.base);
     326                 :     }
     327                 : 
     328                 :     void sub32(Address src, RegisterID dest)
     329                 :     {
     330                 :         m_assembler.subl_mr(src.offset, src.base, dest);
     331                 :     }
     332                 : 
     333                 :     void sub32(RegisterID src, Address dest)
     334                 :     {
     335                 :         m_assembler.subl_rm(src, dest.offset, dest.base);
     336                 :     }
     337                 : 
     338                 : 
     339            2805 :     void xor32(RegisterID src, RegisterID dest)
     340                 :     {
     341            2805 :         m_assembler.xorl_rr(src, dest);
     342            2805 :     }
     343                 : 
     344                 :     void xor32(TrustedImm32 imm, Address dest)
     345                 :     {
     346                 :         m_assembler.xorl_im(imm.m_value, dest.offset, dest.base);
     347                 :     }
     348                 : 
     349           33178 :     void xor32(TrustedImm32 imm, RegisterID dest)
     350                 :     {
     351           33178 :         m_assembler.xorl_ir(imm.m_value, dest);
     352           33178 :     }
     353                 : 
     354                 :     void xor32(RegisterID src, Address dest)
     355                 :     {
     356                 :         m_assembler.xorl_rm(src, dest.offset, dest.base);
     357                 :     }
     358                 : 
     359               0 :     void xor32(Address src, RegisterID dest)
     360                 :     {
     361               0 :         m_assembler.xorl_mr(src.offset, src.base, dest);
     362               0 :     }
     363                 :     
     364             188 :     void sqrtDouble(FPRegisterID src, FPRegisterID dst)
     365                 :     {
     366             188 :         m_assembler.sqrtsd_rr(src, dst);
     367             188 :     }
     368                 : 
     369                 :     // Memory access operations:
     370                 :     //
     371                 :     // Loads are of the form load(address, destination) and stores of the form
     372                 :     // store(source, address).  The source for a store may be an Imm32.  Address
     373                 :     // operand objects to loads and store will be implicitly constructed if a
     374                 :     // register is passed.
     375                 : 
     376        22263999 :     void load32(ImplicitAddress address, RegisterID dest)
     377                 :     {
     378        22263999 :         m_assembler.movl_mr(address.offset, address.base, dest);
     379        22263999 :     }
     380                 : 
     381           56465 :     void load32(BaseIndex address, RegisterID dest)
     382                 :     {
     383           56465 :         m_assembler.movl_mr(address.offset, address.base, address.index, address.scale, dest);
     384           56465 :     }
     385                 : 
     386            2702 :     void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
     387                 :     {
     388            2702 :         load32(address, dest);
     389            2702 :     }
     390                 : 
     391                 :     DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
     392                 :     {
     393                 :         m_assembler.movl_mr_disp32(address.offset, address.base, dest);
     394                 :         return DataLabel32(this);
     395                 :     }
     396                 : 
     397              27 :     void store8(RegisterID src, Address address)
     398                 :     {
     399              27 :         m_assembler.movb_rm(src, address.offset, address.base);
     400              27 :     }
     401                 : 
     402             147 :     void store8(RegisterID src, BaseIndex address)
     403                 :     {
     404             147 :         m_assembler.movb_rm(src, address.offset, address.base, address.index, address.scale);
     405             147 :     }
     406                 : 
     407              18 :     void store16(RegisterID src, Address address)
     408                 :     {
     409              18 :         m_assembler.movw_rm(src, address.offset, address.base);
     410              18 :     }
     411                 : 
     412              60 :     void store16(RegisterID src, BaseIndex address)
     413                 :     {
     414              60 :         m_assembler.movw_rm(src, address.offset, address.base, address.index, address.scale);
     415              60 :     }
     416                 : 
     417              63 :     void load8ZeroExtend(BaseIndex address, RegisterID dest)
     418                 :     {
     419              63 :         m_assembler.movzbl_mr(address.offset, address.base, address.index, address.scale, dest);
     420              63 :     }
     421                 :     
     422             306 :     void load8ZeroExtend(Address address, RegisterID dest)
     423                 :     {
     424             306 :         m_assembler.movzbl_mr(address.offset, address.base, dest);
     425             306 :     }
     426                 : 
     427              30 :     void load8SignExtend(BaseIndex address, RegisterID dest)
     428                 :     {
     429              30 :         m_assembler.movxbl_mr(address.offset, address.base, address.index, address.scale, dest);
     430              30 :     }
     431                 :     
     432             162 :     void load8SignExtend(Address address, RegisterID dest)
     433                 :     {
     434             162 :         m_assembler.movxbl_mr(address.offset, address.base, dest);
     435             162 :     }
     436                 : 
     437              32 :     void load16SignExtend(BaseIndex address, RegisterID dest)
     438                 :     {
     439              32 :         m_assembler.movxwl_mr(address.offset, address.base, address.index, address.scale, dest);
     440              32 :     }
     441                 :     
     442             153 :     void load16SignExtend(Address address, RegisterID dest)
     443                 :     {
     444             153 :         m_assembler.movxwl_mr(address.offset, address.base, dest);
     445             153 :     }
     446                 : 
     447           62978 :     void load16(BaseIndex address, RegisterID dest)
     448                 :     {
     449           62978 :         m_assembler.movzwl_mr(address.offset, address.base, address.index, address.scale, dest);
     450           62978 :     }
     451                 :     
     452          148055 :     void load16(Address address, RegisterID dest)
     453                 :     {
     454          148055 :         m_assembler.movzwl_mr(address.offset, address.base, dest);
     455          148055 :     }
     456                 : 
     457                 :     DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
     458                 :     {
     459                 :         m_assembler.movl_rm_disp32(src, address.offset, address.base);
     460                 :         return DataLabel32(this);
     461                 :     }
     462                 : 
     463        23398600 :     void store32(RegisterID src, ImplicitAddress address)
     464                 :     {
     465        23398600 :         m_assembler.movl_rm(src, address.offset, address.base);
     466        23398600 :     }
     467                 : 
     468           14444 :     void store32(RegisterID src, BaseIndex address)
     469                 :     {
     470           14444 :         m_assembler.movl_rm(src, address.offset, address.base, address.index, address.scale);
     471           14444 :     }
     472                 : 
     473            8153 :     void store32(TrustedImm32 imm, BaseIndex address)
     474                 :     {
     475            8153 :         m_assembler.movl_i32m(imm.m_value, address.offset, address.base, address.index, address.scale);
     476            8153 :     }
     477                 : 
     478             114 :     void store16(Imm32 imm, BaseIndex address)
     479                 :     {
     480             114 :         m_assembler.movw_i16m(imm.m_value, address.offset, address.base, address.index, address.scale);
     481             114 :     }
     482                 : 
     483             316 :     void store8(Imm32 imm, BaseIndex address)
     484                 :     {
     485             316 :         m_assembler.movb_i8m(imm.m_value, address.offset, address.base, address.index, address.scale);
     486             316 :     }
     487                 : 
     488        12485476 :     void store32(TrustedImm32 imm, ImplicitAddress address)
     489                 :     {
     490        12485476 :         m_assembler.movl_i32m(imm.m_value, address.offset, address.base);
     491        12485476 :     }
     492                 : 
     493              68 :     void store16(Imm32 imm, ImplicitAddress address)
     494                 :     {
     495              68 :         m_assembler.movw_i16m(imm.m_value, address.offset, address.base);
     496              68 :     }
     497                 : 
     498             108 :     void store8(Imm32 imm, ImplicitAddress address)
     499                 :     {
     500             108 :         m_assembler.movb_i8m(imm.m_value, address.offset, address.base);
     501             108 :     }
     502                 : 
     503                 : 
     504                 :     // Floating-point operation:
     505                 :     //
     506                 :     // Presently only supports SSE, not x87 floating point.
     507                 : 
     508            5200 :     void moveDouble(FPRegisterID src, FPRegisterID dest)
     509                 :     {
     510            5200 :         ASSERT(isSSE2Present());
     511            5200 :         m_assembler.movsd_rr(src, dest);
     512            5200 :     }
     513                 : 
     514             303 :     void loadFloat(ImplicitAddress address, FPRegisterID dest)
     515                 :     {
     516             303 :         ASSERT(isSSE2Present());
     517             303 :         m_assembler.movss_mr(address.offset, address.base, dest);
     518             303 :         m_assembler.cvtss2sd_rr(dest, dest);
     519             303 :     }
     520                 : 
     521              38 :     void loadFloat(BaseIndex address, FPRegisterID dest)
     522                 :     {
     523              38 :         ASSERT(isSSE2Present());
     524              38 :         m_assembler.movss_mr(address.offset, address.base, address.index, address.scale, dest);
     525              38 :         m_assembler.cvtss2sd_rr(dest, dest);
     526              38 :     }
     527                 : 
     528             104 :     void convertDoubleToFloat(FPRegisterID src, FPRegisterID dest)
     529                 :     {
     530             104 :         ASSERT(isSSE2Present());
     531             104 :         m_assembler.cvtsd2ss_rr(src, dest);
     532             104 :     }
     533                 : 
     534           52134 :     void loadDouble(ImplicitAddress address, FPRegisterID dest)
     535                 :     {
     536           52134 :         ASSERT(isSSE2Present());
     537           52134 :         m_assembler.movsd_mr(address.offset, address.base, dest);
     538           52134 :     }
     539                 : 
     540              50 :     void loadDouble(BaseIndex address, FPRegisterID dest)
     541                 :     {
     542              50 :         ASSERT(isSSE2Present());
     543              50 :         m_assembler.movsd_mr(address.offset, address.base, address.index, address.scale, dest);
     544              50 :     }
     545                 : 
     546              22 :     void storeFloat(ImmDouble imm, Address address)
     547                 :     {
     548                 :         union {
     549                 :             float f;
     550                 :             uint32_t u32;
     551                 :         } u;
     552              22 :         u.f = imm.u.d;
     553              22 :         store32(Imm32(u.u32), address);
     554              22 :     }
     555                 : 
     556              48 :     void storeFloat(ImmDouble imm, BaseIndex address)
     557                 :     {
     558                 :         union {
     559                 :             float f;
     560                 :             uint32_t u32;
     561                 :         } u;
     562              48 :         u.f = imm.u.d;
     563              48 :         store32(Imm32(u.u32), address);
     564              48 :     }
     565                 : 
     566          630156 :     void storeDouble(FPRegisterID src, ImplicitAddress address)
     567                 :     {
     568          630156 :         ASSERT(isSSE2Present());
     569          630156 :         m_assembler.movsd_rm(src, address.offset, address.base);
     570          630156 :     }
     571                 : 
     572              67 :     void storeFloat(FPRegisterID src, ImplicitAddress address)
     573                 :     {
     574              67 :         ASSERT(isSSE2Present());
     575              67 :         m_assembler.movss_rm(src, address.offset, address.base);
     576              67 :     }
     577                 : 
     578            1099 :     void storeDouble(FPRegisterID src, BaseIndex address)
     579                 :     {
     580            1099 :         ASSERT(isSSE2Present());
     581            1099 :         m_assembler.movsd_rm(src, address.offset, address.base, address.index, address.scale);
     582            1099 :     }
     583                 : 
     584              37 :     void storeFloat(FPRegisterID src, BaseIndex address)
     585                 :     {
     586              37 :         ASSERT(isSSE2Present());
     587              37 :         m_assembler.movss_rm(src, address.offset, address.base, address.index, address.scale);
     588              37 :     }
     589                 : 
     590          529223 :     void addDouble(FPRegisterID src, FPRegisterID dest)
     591                 :     {
     592          529223 :         ASSERT(isSSE2Present());
     593          529223 :         m_assembler.addsd_rr(src, dest);
     594          529223 :     }
     595                 : 
     596             195 :     void addDouble(Address src, FPRegisterID dest)
     597                 :     {
     598             195 :         ASSERT(isSSE2Present());
     599             195 :         m_assembler.addsd_mr(src.offset, src.base, dest);
     600             195 :     }
     601                 : 
     602            7983 :     void divDouble(FPRegisterID src, FPRegisterID dest)
     603                 :     {
     604            7983 :         ASSERT(isSSE2Present());
     605            7983 :         m_assembler.divsd_rr(src, dest);
     606            7983 :     }
     607                 : 
     608                 :     void divDouble(Address src, FPRegisterID dest)
     609                 :     {
     610                 :         ASSERT(isSSE2Present());
     611                 :         m_assembler.divsd_mr(src.offset, src.base, dest);
     612                 :     }
     613                 : 
     614           34525 :     void subDouble(FPRegisterID src, FPRegisterID dest)
     615                 :     {
     616           34525 :         ASSERT(isSSE2Present());
     617           34525 :         m_assembler.subsd_rr(src, dest);
     618           34525 :     }
     619                 : 
     620                 :     void subDouble(Address src, FPRegisterID dest)
     621                 :     {
     622                 :         ASSERT(isSSE2Present());
     623                 :         m_assembler.subsd_mr(src.offset, src.base, dest);
     624                 :     }
     625                 : 
     626            4933 :     void mulDouble(FPRegisterID src, FPRegisterID dest)
     627                 :     {
     628            4933 :         ASSERT(isSSE2Present());
     629            4933 :         m_assembler.mulsd_rr(src, dest);
     630            4933 :     }
     631                 : 
     632                 :     void mulDouble(Address src, FPRegisterID dest)
     633                 :     {
     634                 :         ASSERT(isSSE2Present());
     635                 :         m_assembler.mulsd_mr(src.offset, src.base, dest);
     636                 :     }
     637                 : 
     638            3250 :     void xorDouble(FPRegisterID src, FPRegisterID dest)
     639                 :     {
     640            3250 :         ASSERT(isSSE2Present());
     641            3250 :         m_assembler.xorpd_rr(src, dest);
     642            3250 :     }
     643                 : 
     644              85 :     void andDouble(FPRegisterID src, FPRegisterID dest)
     645                 :     {
     646              85 :         ASSERT(isSSE2Present());
     647              85 :         m_assembler.andpd_rr(src, dest);
     648              85 :     }
     649                 : 
     650              85 :     void absDouble(FPRegisterID src, FPRegisterID dest)
     651                 :     {
     652              85 :         ASSERT(isSSE2Present());
     653                 :         /* Compile abs(x) as x & -x. */
     654              85 :         zeroDouble(dest);
     655              85 :         subDouble(src, dest);
     656              85 :         andDouble(src, dest);
     657              85 :     }
     658                 : 
     659          717462 :     void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
     660                 :     {
     661          717462 :         ASSERT(isSSE2Present());
     662          717462 :         m_assembler.cvtsi2sd_rr(src, dest);
     663          717462 :     }
     664                 : 
     665           24669 :     void convertInt32ToDouble(Address src, FPRegisterID dest)
     666                 :     {
     667           24669 :         ASSERT(isSSE2Present());
     668           24669 :         m_assembler.cvtsi2sd_mr(src.offset, src.base, dest);
     669           24669 :     }
     670                 : 
     671           56199 :     Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
     672                 :     {
     673           56199 :         ASSERT(isSSE2Present());
     674                 : 
     675           56199 :         if (cond & DoubleConditionBitInvert)
     676           43297 :             m_assembler.ucomisd_rr(left, right);
     677                 :         else
     678           12902 :             m_assembler.ucomisd_rr(right, left);
     679                 : 
     680           56199 :         if (cond == DoubleEqual) {
     681             525 :             Jump isUnordered(m_assembler.jp());
     682             525 :             Jump result = Jump(m_assembler.je());
     683             525 :             isUnordered.link(this);
     684             525 :             return result;
     685           55674 :         } else if (cond == DoubleNotEqualOrUnordered) {
     686               0 :             Jump isUnordered(m_assembler.jp());
     687               0 :             Jump isEqual(m_assembler.je());
     688               0 :             isUnordered.link(this);
     689               0 :             Jump result = jump();
     690               0 :             isEqual.link(this);
     691               0 :             return result;
     692                 :         }
     693                 : 
     694           55674 :         ASSERT(!(cond & DoubleConditionBitSpecial));
     695           55674 :         return Jump(m_assembler.jCC(static_cast<X86Assembler::Condition>(cond & ~DoubleConditionBits)));
     696                 :     }
     697                 : 
     698                 :     // Truncates 'src' to an integer, and places the resulting 'dest'.
     699                 :     // If the result is not representable as a 32 bit value, branch.
     700                 :     // May also branch for some values that are representable in 32 bits
     701                 :     // (specifically, in this case, INT_MIN).
     702            6320 :     Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest)
     703                 :     {
     704            6320 :         ASSERT(isSSE2Present());
     705            6320 :         m_assembler.cvttsd2si_rr(src, dest);
     706            6320 :         return branch32(Equal, dest, Imm32(0x80000000));
     707                 :     }
     708                 : 
     709                 :     // Convert 'src' to an integer, and places the resulting 'dest'.
     710                 :     // If the result is not representable as a 32 bit value, branch.
     711                 :     // May also branch for some values that are representable in 32 bits
     712                 :     // (specifically, in this case, 0).
     713            7137 :     void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp)
     714                 :     {
     715            7137 :         ASSERT(isSSE2Present());
     716            7137 :         ASSERT(src != fpTemp); 
     717            7137 :         m_assembler.cvttsd2si_rr(src, dest);
     718                 : 
     719                 :         // If the result is zero, it might have been -0.0, and the double comparison won't catch this!
     720            7137 :         failureCases.append(branchTest32(Zero, dest));
     721                 : 
     722                 :         // Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump.
     723            7137 :         convertInt32ToDouble(dest, fpTemp);
     724            7137 :         m_assembler.ucomisd_rr(fpTemp, src);
     725            7137 :         failureCases.append(m_assembler.jp());
     726            7137 :         failureCases.append(m_assembler.jne());
     727            7137 :     }
     728                 : 
     729             949 :     void zeroDouble(FPRegisterID srcDest)
     730                 :     {
     731             949 :         ASSERT(isSSE2Present());
     732             949 :         m_assembler.xorpd_rr(srcDest, srcDest);
     733             949 :     }
     734                 : 
     735                 : 
     736                 :     // Stack manipulation operations:
     737                 :     //
     738                 :     // The ABI is assumed to provide a stack abstraction to memory,
     739                 :     // containing machine word sized units of data.  Push and pop
     740                 :     // operations add and remove a single register sized unit of data
     741                 :     // to or from the stack.  Peek and poke operations read or write
     742                 :     // values on the stack, without moving the current stack position.
     743                 :     
     744          449850 :     void pop(RegisterID dest)
     745                 :     {
     746          449850 :         m_assembler.pop_r(dest);
     747          449850 :     }
     748                 : 
     749          233906 :     void push(RegisterID src)
     750                 :     {
     751          233906 :         m_assembler.push_r(src);
     752          233906 :     }
     753                 : 
     754                 :     void push(Address address)
     755                 :     {
     756                 :         m_assembler.push_m(address.offset, address.base);
     757                 :     }
     758                 : 
     759                 :     void push(Imm32 imm)
     760                 :     {
     761                 :         m_assembler.push_i32(imm.m_value);
     762                 :     }
     763                 : 
     764                 : 
     765                 :     // Register move operations:
     766                 :     //
     767                 :     // Move values in registers.
     768                 : 
     769         1042429 :     void move(TrustedImm32 imm, RegisterID dest)
     770                 :     {
     771                 :         // Note: on 64-bit the Imm32 value is zero extended into the register, it
     772                 :         // may be useful to have a separate version that sign extends the value?
     773         1042429 :         if (!imm.m_value)
     774          357756 :             m_assembler.xorl_rr(dest, dest);
     775                 :         else
     776          684673 :             m_assembler.movl_i32r(imm.m_value, dest);
     777         1042429 :     }
     778                 : 
     779                 : #if WTF_CPU_X86_64
     780                 :     void move(RegisterID src, RegisterID dest)
     781                 :     {
     782                 :         // Note: on 64-bit this is is a full register move; perhaps it would be
     783                 :         // useful to have separate move32 & movePtr, with move32 zero extending?
     784                 :         if (src != dest)
     785                 :             m_assembler.movq_rr(src, dest);
     786                 :     }
     787                 : 
     788                 :     void move(TrustedImmPtr imm, RegisterID dest)
     789                 :     {
     790                 :         m_assembler.movq_i64r(imm.asIntptr(), dest);
     791                 :     }
     792                 : 
     793                 :     void swap(RegisterID reg1, RegisterID reg2)
     794                 :     {
     795                 :         // XCHG is extremely slow. Don't use XCHG.
     796                 :         if (reg1 != reg2) {
     797                 :             m_assembler.movq_rr(reg1, scratchRegister);
     798                 :             m_assembler.movq_rr(reg2, reg1);
     799                 :             m_assembler.movq_rr(scratchRegister, reg2);
     800                 :         }
     801                 :     }
     802                 : 
     803                 :     void signExtend32ToPtr(RegisterID src, RegisterID dest)
     804                 :     {
     805                 :         m_assembler.movsxd_rr(src, dest);
     806                 :     }
     807                 : 
     808                 :     void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
     809                 :     {
     810                 :         m_assembler.movl_rr(src, dest);
     811                 :     }
     812                 : #else
     813        11177949 :     void move(RegisterID src, RegisterID dest)
     814                 :     {
     815        11177949 :         if (src != dest)
     816        11177925 :             m_assembler.movl_rr(src, dest);
     817        11177949 :     }
     818                 : 
     819         1463284 :     void move(TrustedImmPtr imm, RegisterID dest)
     820                 :     {
     821         1463284 :         m_assembler.movl_i32r(imm.asIntptr(), dest);
     822         1463284 :     }
     823                 : 
     824               0 :     void swap(RegisterID reg1, RegisterID reg2)
     825                 :     {
     826               0 :         if (reg1 != reg2)
     827               0 :             m_assembler.xchgl_rr(reg1, reg2);
     828               0 :     }
     829                 : 
     830                 :     void signExtend32ToPtr(RegisterID src, RegisterID dest)
     831                 :     {
     832                 :         move(src, dest);
     833                 :     }
     834                 : 
     835                 :     void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
     836                 :     {
     837                 :         move(src, dest);
     838                 :     }
     839                 : #endif
     840                 : 
     841                 : 
     842                 :     // Forwards / external control flow operations:
     843                 :     //
     844                 :     // This set of jump and conditional branch operations return a Jump
     845                 :     // object which may linked at a later point, allow forwards jump,
     846                 :     // or jumps that will require external linkage (after the code has been
     847                 :     // relocated).
     848                 :     //
     849                 :     // For branches, signed <, >, <= and >= are denoted as l, g, le, and ge
     850                 :     // respecitvely, for unsigned comparisons the names b, a, be, and ae are
     851                 :     // used (representing the names 'below' and 'above').
     852                 :     //
     853                 :     // Operands to the comparision are provided in the expected order, e.g.
     854                 :     // jle32(reg1, Imm32(5)) will branch if the value held in reg1, when
     855                 :     // treated as a signed 32bit value, is less than or equal to 5.
     856                 :     //
     857                 :     // jz and jnz test whether the first operand is equal to zero, and take
     858                 :     // an optional second operand of a mask under which to perform the test.
     859                 : 
     860                 : public:
     861                 :     Jump branch8(Condition cond, Address left, Imm32 right)
     862                 :     {
     863                 :         m_assembler.cmpb_im(right.m_value, left.offset, left.base);
     864                 :         return Jump(m_assembler.jCC(x86Condition(cond)));
     865                 :     }
     866                 : 
     867          259138 :     Jump branch32(Condition cond, RegisterID left, RegisterID right)
     868                 :     {
     869          259138 :         m_assembler.cmpl_rr(right, left);
     870          259138 :         return Jump(m_assembler.jCC(x86Condition(cond)));
     871                 :     }
     872                 : 
     873         4501372 :     Jump branch32(Condition cond, RegisterID left, TrustedImm32 right)
     874                 :     {
     875         4501372 :         if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
     876           26960 :             m_assembler.testl_rr(left, left);
     877                 :         else
     878         4474412 :             m_assembler.cmpl_ir(right.m_value, left);
     879         4501372 :         return Jump(m_assembler.jCC(x86Condition(cond)));
     880                 :     }
     881                 :     
     882                 :     // Branch based on a 32-bit comparison, forcing the size of the
     883                 :     // immediate operand to 32 bits in the native code stream to ensure that
     884                 :     // the length of code emitted by this instruction is consistent.
     885                 :     Jump branch32FixedLength(Condition cond, RegisterID left, TrustedImm32 right)
     886                 :     {
     887                 :         m_assembler.cmpl_ir_force32(right.m_value, left);
     888                 :         return Jump(m_assembler.jCC(x86Condition(cond)));
     889                 :     }
     890                 : 
     891                 :     // Branch and record a label after the comparison.
     892                 :     Jump branch32WithPatch(Condition cond, RegisterID left, TrustedImm32 right, DataLabel32 &dataLabel)
     893                 :     {
     894                 :         // Always use cmpl, since the value is to be patched.
     895                 :         m_assembler.cmpl_ir_force32(right.m_value, left);
     896                 :         dataLabel = DataLabel32(this);
     897                 :         return Jump(m_assembler.jCC(x86Condition(cond)));
     898                 :     }
     899                 : 
     900                 :     Jump branch32WithPatch(Condition cond, Address left, TrustedImm32 right, DataLabel32 &dataLabel)
     901                 :     {
     902                 :         m_assembler.cmpl_im_force32(right.m_value, left.offset, left.base);
     903                 :         dataLabel = DataLabel32(this);
     904                 :         return Jump(m_assembler.jCC(x86Condition(cond)));
     905                 :     }
     906                 : 
     907           86999 :     Jump branch32(Condition cond, RegisterID left, Address right)
     908                 :     {
     909           86999 :         m_assembler.cmpl_mr(right.offset, right.base, left);
     910           86999 :         return Jump(m_assembler.jCC(x86Condition(cond)));
     911                 :     }
     912                 :     
     913           62448 :     Jump branch32(Condition cond, Address left, RegisterID right)
     914                 :     {
     915           62448 :         m_assembler.cmpl_rm(right, left.offset, left.base);
     916           62448 :         return Jump(m_assembler.jCC(x86Condition(cond)));
     917                 :     }
     918                 : 
     919          739976 :     Jump branch32(Condition cond, Address left, TrustedImm32 right)
     920                 :     {
     921          739976 :         m_assembler.cmpl_im(right.m_value, left.offset, left.base);
     922          739976 :         return Jump(m_assembler.jCC(x86Condition(cond)));
     923                 :     }
     924                 : 
     925           74169 :     Jump branch32(Condition cond, BaseIndex left, TrustedImm32 right)
     926                 :     {
     927           74169 :         m_assembler.cmpl_im(right.m_value, left.offset, left.base, left.index, left.scale);
     928           74169 :         return Jump(m_assembler.jCC(x86Condition(cond)));
     929                 :     }
     930                 : 
     931           69522 :     Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, TrustedImm32 right)
     932                 :     {
     933           69522 :         return branch32(cond, left, right);
     934                 :     }
     935                 : 
     936                 :     Jump branch16(Condition cond, BaseIndex left, RegisterID right)
     937                 :     {
     938                 :         m_assembler.cmpw_rm(right, left.offset, left.base, left.index, left.scale);
     939                 :         return Jump(m_assembler.jCC(x86Condition(cond)));
     940                 :     }
     941                 : 
     942           57430 :     Jump branch16(Condition cond, BaseIndex left, Imm32 right)
     943                 :     {
     944           57430 :         ASSERT(!(right.m_value & 0xFFFF0000));
     945                 : 
     946           57430 :         m_assembler.cmpw_im(right.m_value, left.offset, left.base, left.index, left.scale);
     947           57430 :         return Jump(m_assembler.jCC(x86Condition(cond)));
     948                 :     }
     949                 : 
     950          606310 :     Jump branchTest32(Condition cond, RegisterID reg, RegisterID mask)
     951                 :     {
     952          606310 :         ASSERT((cond == Zero) || (cond == NonZero));
     953          606310 :         m_assembler.testl_rr(reg, mask);
     954          606310 :         return Jump(m_assembler.jCC(x86Condition(cond)));
     955                 :     }
     956                 : 
     957          248716 :     Jump branchTest32(Condition cond, RegisterID reg, Imm32 mask = Imm32(-1))
     958                 :     {
     959          248716 :         ASSERT((cond == Zero) || (cond == NonZero));
     960                 :         // if we are only interested in the low seven bits, this can be tested with a testb
     961          248716 :         if (mask.m_value == -1)
     962          222956 :             m_assembler.testl_rr(reg, reg);
     963           25760 :         else if (CanUse8Bit(reg) && (mask.m_value & ~0x7f) == 0)
     964           14215 :             m_assembler.testb_i8r(mask.m_value, reg);
     965                 :         else
     966           11545 :             m_assembler.testl_i32r(mask.m_value, reg);
     967          248716 :         return Jump(m_assembler.jCC(x86Condition(cond)));
     968                 :     }
     969                 : 
     970          297748 :     Jump branchTest32(Condition cond, Address address, Imm32 mask = Imm32(-1))
     971                 :     {
     972          297748 :         ASSERT((cond == Zero) || (cond == NonZero));
     973          297748 :         if (mask.m_value == -1)
     974               0 :             m_assembler.cmpl_im(0, address.offset, address.base);
     975                 :         else
     976          297748 :             m_assembler.testl_i32m(mask.m_value, address.offset, address.base);
     977          297748 :         return Jump(m_assembler.jCC(x86Condition(cond)));
     978                 :     }
     979                 : 
     980                 :     Jump branchTest32(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1))
     981                 :     {
     982                 :         ASSERT((cond == Zero) || (cond == NonZero));
     983                 :         if (mask.m_value == -1)
     984                 :             m_assembler.cmpl_im(0, address.offset, address.base, address.index, address.scale);
     985                 :         else
     986                 :             m_assembler.testl_i32m(mask.m_value, address.offset, address.base, address.index, address.scale);
     987                 :         return Jump(m_assembler.jCC(x86Condition(cond)));
     988                 :     }
     989                 :     
     990            3435 :     Jump branchTest8(Condition cond, Address address, Imm32 mask = Imm32(-1))
     991                 :     {
     992            3435 :         ASSERT((cond == Zero) || (cond == NonZero));
     993            3435 :         if (mask.m_value == -1)
     994            3435 :             m_assembler.cmpb_im(0, address.offset, address.base);
     995                 :         else
     996               0 :             m_assembler.testb_im(mask.m_value, address.offset, address.base);
     997            3435 :         return Jump(m_assembler.jCC(x86Condition(cond)));
     998                 :     }
     999                 :     
    1000                 :     Jump branchTest8(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1))
    1001                 :     {
    1002                 :         ASSERT((cond == Zero) || (cond == NonZero));
    1003                 :         if (mask.m_value == -1)
    1004                 :             m_assembler.cmpb_im(0, address.offset, address.base, address.index, address.scale);
    1005                 :         else
    1006                 :             m_assembler.testb_im(mask.m_value, address.offset, address.base, address.index, address.scale);
    1007                 :         return Jump(m_assembler.jCC(x86Condition(cond)));
    1008                 :     }
    1009                 : 
    1010         8690929 :     Jump jump()
    1011                 :     {
    1012         8690929 :         return Jump(m_assembler.jmp());
    1013                 :     }
    1014                 : 
    1015          579341 :     void jump(RegisterID target)
    1016                 :     {
    1017          579341 :         m_assembler.jmp_r(target);
    1018          579341 :     }
    1019                 : 
    1020                 :     // Address is a memory location containing the address to jump to
    1021            2921 :     void jump(Address address)
    1022                 :     {
    1023            2921 :         m_assembler.jmp_m(address.offset, address.base);
    1024            2921 :     }
    1025                 : 
    1026             274 :     void jump(BaseIndex address)
    1027                 :     {
    1028             274 :         m_assembler.jmp_m(address.offset, address.base, address.index, address.scale);
    1029             274 :     }
    1030                 : 
    1031                 :     // Arithmetic control flow operations:
    1032                 :     //
    1033                 :     // This set of conditional branch operations branch based
    1034                 :     // on the result of an arithmetic operation.  The operation
    1035                 :     // is performed as normal, storing the result.
    1036                 :     //
    1037                 :     // * jz operations branch if the result is zero.
    1038                 :     // * jo operations branch if the (signed) arithmetic
    1039                 :     //   operation caused an overflow to occur.
    1040                 :     
    1041          319053 :     Jump branchAdd32(Condition cond, RegisterID src, RegisterID dest)
    1042                 :     {
    1043          319053 :         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
    1044          319053 :         add32(src, dest);
    1045          319053 :         return Jump(m_assembler.jCC(x86Condition(cond)));
    1046                 :     }
    1047                 : 
    1048          221891 :     Jump branchAdd32(Condition cond, Imm32 imm, RegisterID dest)
    1049                 :     {
    1050          221891 :         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
    1051          221891 :         add32(imm, dest);
    1052          221891 :         return Jump(m_assembler.jCC(x86Condition(cond)));
    1053                 :     }
    1054                 :     
    1055                 :     Jump branchAdd32(Condition cond, Imm32 src, Address dest)
    1056                 :     {
    1057                 :         ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
    1058                 :         add32(src, dest);
    1059                 :         return Jump(m_assembler.jCC(x86Condition(cond)));
    1060                 :     }
    1061                 : 
    1062                 :     Jump branchAdd32(Condition cond, RegisterID src, Address dest)
    1063                 :     {
    1064                 :         ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
    1065                 :         add32(src, dest);
    1066                 :         return Jump(m_assembler.jCC(x86Condition(cond)));
    1067                 :     }
    1068                 : 
    1069             276 :     Jump branchAdd32(Condition cond, Address src, RegisterID dest)
    1070                 :     {
    1071             276 :         ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
    1072             276 :         add32(src, dest);
    1073             276 :         return Jump(m_assembler.jCC(x86Condition(cond)));
    1074                 :     }
    1075                 : 
    1076            1927 :     Jump branchMul32(Condition cond, RegisterID src, RegisterID dest)
    1077                 :     {
    1078            1927 :         ASSERT(cond == Overflow);
    1079            1927 :         mul32(src, dest);
    1080            1927 :         return Jump(m_assembler.jCC(x86Condition(cond)));
    1081                 :     }
    1082                 : 
    1083                 :     Jump branchMul32(Condition cond, Address src, RegisterID dest)
    1084                 :     {
    1085                 :         ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
    1086                 :         mul32(src, dest);
    1087                 :         return Jump(m_assembler.jCC(x86Condition(cond)));
    1088                 :     }
    1089                 :     
    1090            1881 :     Jump branchMul32(Condition cond, Imm32 imm, RegisterID src, RegisterID dest)
    1091                 :     {
    1092            1881 :         ASSERT(cond == Overflow);
    1093            1881 :         mul32(imm, src, dest);
    1094            1881 :         return Jump(m_assembler.jCC(x86Condition(cond)));
    1095                 :     }
    1096                 :     
    1097            3979 :     Jump branchSub32(Condition cond, RegisterID src, RegisterID dest)
    1098                 :     {
    1099            3979 :         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
    1100            3979 :         sub32(src, dest);
    1101            3979 :         return Jump(m_assembler.jCC(x86Condition(cond)));
    1102                 :     }
    1103                 :     
    1104           42117 :     Jump branchSub32(Condition cond, Imm32 imm, RegisterID dest)
    1105                 :     {
    1106           42117 :         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
    1107           42117 :         sub32(imm, dest);
    1108           42117 :         return Jump(m_assembler.jCC(x86Condition(cond)));
    1109                 :     }
    1110                 : 
    1111                 :     Jump branchSub32(Condition cond, Imm32 imm, Address dest)
    1112                 :     {
    1113                 :         ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
    1114                 :         sub32(imm, dest);
    1115                 :         return Jump(m_assembler.jCC(x86Condition(cond)));
    1116                 :     }
    1117                 : 
    1118                 :     Jump branchSub32(Condition cond, RegisterID src, Address dest)
    1119                 :     {
    1120                 :         ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
    1121                 :         sub32(src, dest);
    1122                 :         return Jump(m_assembler.jCC(x86Condition(cond)));
    1123                 :     }
    1124                 : 
    1125                 :     Jump branchSub32(Condition cond, Address src, RegisterID dest)
    1126                 :     {
    1127                 :         ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
    1128                 :         sub32(src, dest);
    1129                 :         return Jump(m_assembler.jCC(x86Condition(cond)));
    1130                 :     }
    1131                 : 
    1132                 :     Jump branchNeg32(Condition cond, RegisterID srcDest)
    1133                 :     {
    1134                 :         ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
    1135                 :         neg32(srcDest);
    1136                 :         return Jump(m_assembler.jCC(x86Condition(cond)));
    1137                 :     }
    1138                 : 
    1139            1877 :     Jump branchOr32(Condition cond, RegisterID src, RegisterID dest)
    1140                 :     {
    1141            1877 :         ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero));
    1142            1877 :         or32(src, dest);
    1143            1877 :         return Jump(m_assembler.jCC(x86Condition(cond)));
    1144                 :     }
    1145                 : 
    1146                 : 
    1147                 :     // Miscellaneous operations:
    1148                 : 
    1149                 :     void breakpoint()
    1150                 :     {
    1151                 :         m_assembler.int3();
    1152                 :     }
    1153                 : 
    1154                 :     Call nearCall()
    1155                 :     {
    1156                 :         return Call(m_assembler.call(), Call::LinkableNear);
    1157                 :     }
    1158                 : 
    1159                 :     Call call(RegisterID target)
    1160                 :     {
    1161                 :         return Call(m_assembler.call(target), Call::None);
    1162                 :     }
    1163                 : 
    1164                 :     void call(Address address)
    1165                 :     {
    1166                 :         m_assembler.call_m(address.offset, address.base);
    1167                 :     }
    1168                 : 
    1169          112212 :     void ret()
    1170                 :     {
    1171          112212 :         m_assembler.ret();
    1172          112212 :     }
    1173                 : 
    1174                 :     void set8(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
    1175                 :     {
    1176                 :         m_assembler.cmpl_rr(right, left);
    1177                 :         m_assembler.setCC_r(x86Condition(cond), dest);
    1178                 :     }
    1179                 : 
    1180                 :     void set8(Condition cond, Address left, RegisterID right, RegisterID dest)
    1181                 :     {
    1182                 :         m_assembler.cmpl_mr(left.offset, left.base, right);
    1183                 :         m_assembler.setCC_r(x86Condition(cond), dest);
    1184                 :     }
    1185                 : 
    1186                 :     void set8(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
    1187                 :     {
    1188                 :         if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
    1189                 :             m_assembler.testl_rr(left, left);
    1190                 :         else
    1191                 :             m_assembler.cmpl_ir(right.m_value, left);
    1192                 :         m_assembler.setCC_r(x86Condition(cond), dest);
    1193                 :     }
    1194                 : 
    1195                 :     void set32(Condition cond, Address left, RegisterID right, RegisterID dest)
    1196                 :     {
    1197                 :         m_assembler.cmpl_rm(right, left.offset, left.base);
    1198                 :         m_assembler.setCC_r(x86Condition(cond), dest);
    1199                 :         m_assembler.movzbl_rr(dest, dest);
    1200                 :     }
    1201                 : 
    1202            1104 :     void set32(Condition cond, RegisterID left, Address right, RegisterID dest)
    1203                 :     {
    1204            1104 :         m_assembler.cmpl_mr(right.offset, right.base, left);
    1205            1104 :         m_assembler.setCC_r(x86Condition(cond), dest);
    1206            1104 :         m_assembler.movzbl_rr(dest, dest);
    1207            1104 :     }
    1208                 : 
    1209            7583 :     void set32(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
    1210                 :     {
    1211            7583 :         m_assembler.cmpl_rr(right, left);
    1212            7583 :         m_assembler.setCC_r(x86Condition(cond), dest);
    1213            7583 :         m_assembler.movzbl_rr(dest, dest);
    1214            7583 :     }
    1215                 : 
    1216               7 :     void set32(Condition cond, Address left, Imm32 right, RegisterID dest)
    1217                 :     {
    1218               7 :         m_assembler.cmpl_im(right.m_value, left.offset, left.base);
    1219               7 :         m_assembler.setCC_r(x86Condition(cond), dest);
    1220               7 :         m_assembler.movzbl_rr(dest, dest);
    1221               7 :     }
    1222                 : 
    1223           34997 :     void set32(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
    1224                 :     {
    1225           34997 :         if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
    1226           20726 :             m_assembler.testl_rr(left, left);
    1227                 :         else
    1228           14271 :             m_assembler.cmpl_ir(right.m_value, left);
    1229           34997 :         m_assembler.setCC_r(x86Condition(cond), dest);
    1230           34997 :         m_assembler.movzbl_rr(dest, dest);
    1231           34997 :     }
    1232                 : 
    1233                 :     // FIXME:
    1234                 :     // The mask should be optional... paerhaps the argument order should be
    1235                 :     // dest-src, operations always have a dest? ... possibly not true, considering
    1236                 :     // asm ops like test, or pseudo ops like pop().
    1237                 : 
    1238                 :     void setTest8(Condition cond, Address address, Imm32 mask, RegisterID dest)
    1239                 :     {
    1240                 :         if (mask.m_value == -1)
    1241                 :             m_assembler.cmpb_im(0, address.offset, address.base);
    1242                 :         else
    1243                 :             m_assembler.testb_im(mask.m_value, address.offset, address.base);
    1244                 :         m_assembler.setCC_r(x86Condition(cond), dest);
    1245                 :         m_assembler.movzbl_rr(dest, dest);
    1246                 :     }
    1247                 : 
    1248                 :     void setTest32(Condition cond, Address address, Imm32 mask, RegisterID dest)
    1249                 :     {
    1250                 :         if (mask.m_value == -1)
    1251                 :             m_assembler.cmpl_im(0, address.offset, address.base);
    1252                 :         else
    1253                 :             m_assembler.testl_i32m(mask.m_value, address.offset, address.base);
    1254                 :         m_assembler.setCC_r(x86Condition(cond), dest);
    1255                 :         m_assembler.movzbl_rr(dest, dest);
    1256                 :     }
    1257                 : 
    1258                 :     // As the SSE's were introduced in order, the presence of a later SSE implies
    1259                 :     // the presence of an earlier SSE. For example, SSE4_2 support implies SSE2 support.
    1260                 :     enum SSECheckState {
    1261                 :         NotCheckedSSE = 0,
    1262                 :         NoSSE = 1,
    1263                 :         HasSSE = 2,
    1264                 :         HasSSE2 = 3,
    1265                 :         HasSSE3 = 4,
    1266                 :         HasSSSE3 = 5,
    1267                 :         HasSSE4_1 = 6,
    1268                 :         HasSSE4_2 = 7
    1269                 :     };
    1270                 : 
    1271         1322273 :     static SSECheckState getSSEState()
    1272                 :     {
    1273         1322273 :         if (s_sseCheckState == NotCheckedSSE) {
    1274               0 :             MacroAssemblerX86Common::setSSECheckState();
    1275                 :         }
    1276                 :         // Only check once.
    1277         1322273 :         ASSERT(s_sseCheckState != NotCheckedSSE);
    1278                 : 
    1279         1322273 :         return s_sseCheckState;
    1280                 :     }
    1281                 : 
    1282                 : protected:
    1283         8988801 :     X86Assembler::Condition x86Condition(Condition cond)
    1284                 :     {
    1285         8988801 :         return static_cast<X86Assembler::Condition>(cond);
    1286                 :     }
    1287                 : 
    1288                 : private:
    1289                 :     friend class MacroAssemblerX86;
    1290                 : 
    1291                 :     static SSECheckState s_sseCheckState;
    1292                 : 
    1293           16462 :     static void setSSECheckState()
    1294                 :     {
    1295                 :         // Default the flags value to zero; if the compiler is
    1296                 :         // not MSVC or GCC we will read this as SSE2 not present.
    1297           16462 :         volatile int flags_edx = 0;
    1298           16462 :         volatile int flags_ecx = 0;
    1299                 : #if WTF_COMPILER_MSVC
    1300                 : #if WTF_CPU_X86_64
    1301                 :         int cpuinfo[4];
    1302                 : 
    1303                 :         __cpuid(cpuinfo, 1);
    1304                 :         flags_ecx = cpuinfo[2];
    1305                 :         flags_edx = cpuinfo[3];
    1306                 : #else
    1307                 :         _asm {
    1308                 :             mov eax, 1 // cpuid function 1 gives us the standard feature set
    1309                 :             cpuid;
    1310                 :             mov flags_ecx, ecx;
    1311                 :             mov flags_edx, edx;
    1312                 :         }
    1313                 : #endif
    1314                 : #elif WTF_COMPILER_GCC
    1315                 : #if WTF_CPU_X86_64
    1316                 :         asm (
    1317                 :              "movl $0x1, %%eax;"
    1318                 :              "pushq %%rbx;"
    1319                 :              "cpuid;"
    1320                 :              "popq %%rbx;"
    1321                 :              "movl %%ecx, %0;"
    1322                 :              "movl %%edx, %1;"
    1323                 :              : "=g" (flags_ecx), "=g" (flags_edx)
    1324                 :              :
    1325                 :              : "%eax", "%ecx", "%edx"
    1326                 :              );
    1327                 : #else
    1328                 :         asm (
    1329                 :              "movl $0x1, %%eax;"
    1330                 :              "pushl %%ebx;"
    1331                 :              "cpuid;"
    1332                 :              "popl %%ebx;"
    1333                 :              "movl %%ecx, %0;"
    1334                 :              "movl %%edx, %1;"
    1335                 :              : "=g" (flags_ecx), "=g" (flags_edx)
    1336                 :              :
    1337                 :              : "%eax", "%ecx", "%edx"
    1338           16462 :              );
    1339                 : #endif
    1340                 : #elif WTF_COMPILER_SUNCC
    1341                 : #if WTF_CPU_X86_64
    1342                 :         asm (
    1343                 :              "movl $0x1, %%eax;"
    1344                 :              "pushq %%rbx;"
    1345                 :              "cpuid;"
    1346                 :              "popq %%rbx;"
    1347                 :              "movl %%ecx, (%rsi);"
    1348                 :              "movl %%edx, (%rdi);"
    1349                 :              :
    1350                 :              : "S" (&flags_ecx), "D" (&flags_edx)
    1351                 :              : "%eax", "%ecx", "%edx"
    1352                 :              );
    1353                 : #else
    1354                 :         asm (
    1355                 :              "movl $0x1, %eax;"
    1356                 :              "pushl %ebx;"
    1357                 :              "cpuid;"
    1358                 :              "popl %ebx;"
    1359                 :              "movl %ecx, (%esi);"
    1360                 :              "movl %edx, (%edi);"
    1361                 :              :
    1362                 :              : "S" (&flags_ecx), "D" (&flags_edx)
    1363                 :              : "%eax", "%ecx", "%edx"
    1364                 :              );
    1365                 : #endif
    1366                 : #endif
    1367                 :         static const int SSEFeatureBit = 1 << 25;
    1368                 :         static const int SSE2FeatureBit = 1 << 26;
    1369                 :         static const int SSE3FeatureBit = 1 << 0;
    1370                 :         static const int SSSE3FeatureBit = 1 << 9;
    1371                 :         static const int SSE41FeatureBit = 1 << 19;
    1372                 :         static const int SSE42FeatureBit = 1 << 20;
    1373           16462 :         if (flags_ecx & SSE42FeatureBit)
    1374           16445 :             s_sseCheckState = HasSSE4_2;
    1375              17 :         else if (flags_ecx & SSE41FeatureBit)
    1376               0 :             s_sseCheckState = HasSSE4_1;
    1377              17 :         else if (flags_ecx & SSSE3FeatureBit)
    1378              17 :             s_sseCheckState = HasSSSE3;
    1379               0 :         else if (flags_ecx & SSE3FeatureBit)
    1380               0 :             s_sseCheckState = HasSSE3;
    1381               0 :         else if (flags_edx & SSE2FeatureBit)
    1382               0 :             s_sseCheckState = HasSSE2;
    1383               0 :         else if (flags_edx & SSEFeatureBit)
    1384               0 :             s_sseCheckState = HasSSE;
    1385                 :         else
    1386               0 :             s_sseCheckState = NoSSE;
    1387           16462 :     }
    1388                 : 
    1389                 : #if WTF_CPU_X86
    1390                 : #if WTF_OS_MAC_OS_X
    1391                 : 
    1392                 :     // All X86 Macs are guaranteed to support at least SSE2
    1393                 :     static bool isSSEPresent()
    1394                 :     {
    1395                 :         return true;
    1396                 :     }
    1397                 : 
    1398                 :     static bool isSSE2Present()
    1399                 :     {
    1400                 :         return true;
    1401                 :     }
    1402                 : 
    1403                 : #else // OS(MAC_OS_X)
    1404                 : 
    1405                 :     static bool isSSEPresent()
    1406                 :     {
    1407                 :         if (s_sseCheckState == NotCheckedSSE) {
    1408                 :             setSSECheckState();
    1409                 :         }
    1410                 :         // Only check once.
    1411                 :         ASSERT(s_sseCheckState != NotCheckedSSE);
    1412                 : 
    1413                 :         return s_sseCheckState >= HasSSE;
    1414                 :     }
    1415                 : 
    1416         3126088 :     static bool isSSE2Present()
    1417                 :     {
    1418         3126088 :         if (s_sseCheckState == NotCheckedSSE) {
    1419           16462 :             setSSECheckState();
    1420                 :         }
    1421                 :         // Only check once.
    1422         3126088 :         ASSERT(s_sseCheckState != NotCheckedSSE);
    1423                 : 
    1424         3126088 :         return s_sseCheckState >= HasSSE2;
    1425                 :     }
    1426                 :     
    1427                 : 
    1428                 : #endif // PLATFORM(MAC)
    1429                 : #elif !defined(NDEBUG) // CPU(X86)
    1430                 : 
    1431                 :     // On x86-64 we should never be checking for SSE2 in a non-debug build,
    1432                 :     // but non debug add this method to keep the asserts above happy.
    1433                 :     static bool isSSE2Present()
    1434                 :     {
    1435                 :         return true;
    1436                 :     }
    1437                 : 
    1438                 : #endif
    1439                 :     static bool isSSE3Present()
    1440                 :     {
    1441                 :         if (s_sseCheckState == NotCheckedSSE) {
    1442                 :             setSSECheckState();
    1443                 :         }
    1444                 :         // Only check once.
    1445                 :         ASSERT(s_sseCheckState != NotCheckedSSE);
    1446                 : 
    1447                 :         return s_sseCheckState >= HasSSE3;
    1448                 :     }
    1449                 : 
    1450                 :     static bool isSSSE3Present()
    1451                 :     {
    1452                 :         if (s_sseCheckState == NotCheckedSSE) {
    1453                 :             setSSECheckState();
    1454                 :         }
    1455                 :         // Only check once.
    1456                 :         ASSERT(s_sseCheckState != NotCheckedSSE);
    1457                 : 
    1458                 :         return s_sseCheckState >= HasSSSE3;
    1459                 :     }
    1460                 : 
    1461                 :     static bool isSSE41Present()
    1462                 :     {
    1463                 :         if (s_sseCheckState == NotCheckedSSE) {
    1464                 :             setSSECheckState();
    1465                 :         }
    1466                 :         // Only check once.
    1467                 :         ASSERT(s_sseCheckState != NotCheckedSSE);
    1468                 : 
    1469                 :         return s_sseCheckState >= HasSSE4_1;
    1470                 :     }
    1471                 : 
    1472                 :     static bool isSSE42Present()
    1473                 :     {
    1474                 :         if (s_sseCheckState == NotCheckedSSE) {
    1475                 :             setSSECheckState();
    1476                 :         }
    1477                 :         // Only check once.
    1478                 :         ASSERT(s_sseCheckState != NotCheckedSSE);
    1479                 : 
    1480                 :         return s_sseCheckState >= HasSSE4_2;
    1481                 :     }
    1482                 : };
    1483                 : 
    1484                 : } // namespace JSC
    1485                 : 
    1486                 : #endif // ENABLE(ASSEMBLER)
    1487                 : 
    1488                 : #endif // MacroAssemblerX86Common_h

Generated by: LCOV version 1.7