LCOV - app.info - js/src/assembler/assembler/MacroAssemblerX86Common.h

LCOV - code coverage report
| Current view: | directory - js/src/assembler/assembler - MacroAssemblerX86Common.h (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 470 | 421 | 89.6 %
| Date: | 2012-04-21 | 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         1530100 : 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           25838 :     static inline bool CanUse8Bit(RegisterID reg) {
         103                 :         return !!((1 << reg) & ~((1 << X86Registers::esp) |
         104                 :                                  (1 << X86Registers::edi) |
         105                 :                                  (1 << X86Registers::esi) |
         106           25838 :                                  (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          328908 :     void add32(RegisterID src, RegisterID dest)
         117                 :     {
         118          328908 :         m_assembler.addl_rr(src, dest);
         119          328908 :     }
         120                 :
         121                 :     void add32(TrustedImm32 imm, Address address)
         122                 :     {
         123                 :         m_assembler.addl_im(imm.m_value, address.offset, address.base);
         124                 :     }
         125                 :
         126         5661438 :     void add32(TrustedImm32 imm, RegisterID dest)
         127                 :     {
         128         5661438 :         m_assembler.addl_ir(imm.m_value, dest);
         129         5661438 :     }
         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          155115 :     void and32(Imm32 imm, RegisterID dest)
         147                 :     {
         148          155115 :         m_assembler.andl_ir(imm.m_value, dest);
         149          155115 :     }
         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            2591 :     void lshift32(Imm32 imm, RegisterID dest)
         167                 :     {
         168            2591 :         m_assembler.shll_i8r(imm.m_value, dest);
         169            2591 :     }
         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            1875 :     void mul32(Imm32 imm, RegisterID src, RegisterID dest)
         204                 :     {
         205            1875 :         m_assembler.imull_i32r(src, imm.m_value, dest);
         206            1875 :     }
         207                 :
         208                 :     void idiv(RegisterID reg)
         209                 :     {
         210                 :         m_assembler.cdq();
         211                 :         m_assembler.idivl_r(reg);
         212                 :     }
         213                 :
         214           21241 :     void neg32(RegisterID srcDest)
         215                 :     {
         216           21241 :         m_assembler.negl_r(srcDest);
         217           21241 :     }
         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           55474 :     void or32(TrustedImm32 imm, RegisterID dest)
         240                 :     {
         241           55474 :         m_assembler.orl_ir(imm.m_value, dest);
         242           55474 :     }
         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            3189 :     void rshift32(Imm32 imm, RegisterID dest)
         282                 :     {
         283            3189 :         m_assembler.sarl_i8r(imm.m_value, dest);
         284            3189 :     }
         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            7387 :     void urshift32(Imm32 imm, RegisterID dest)
         309                 :     {
         310            7387 :         m_assembler.shrl_i8r(imm.m_value, dest);
         311            7387 :     }
         312                 :
         313            4939 :     void sub32(RegisterID src, RegisterID dest)
         314                 :     {
         315            4939 :         m_assembler.subl_rr(src, dest);
         316            4939 :     }
         317                 :
         318          263521 :     void sub32(TrustedImm32 imm, RegisterID dest)
         319                 :     {
         320          263521 :         m_assembler.subl_ir(imm.m_value, dest);
         321          263521 :     }
         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            2802 :     void xor32(RegisterID src, RegisterID dest)
         340                 :     {
         341            2802 :         m_assembler.xorl_rr(src, dest);
         342            2802 :     }
         343                 :
         344                 :     void xor32(TrustedImm32 imm, Address dest)
         345                 :     {
         346                 :         m_assembler.xorl_im(imm.m_value, dest.offset, dest.base);
         347                 :     }
         348                 :
         349           33292 :     void xor32(TrustedImm32 imm, RegisterID dest)
         350                 :     {
         351           33292 :         m_assembler.xorl_ir(imm.m_value, dest);
         352           33292 :     }
         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             187 :     void sqrtDouble(FPRegisterID src, FPRegisterID dst)
         365                 :     {
         366             187 :         m_assembler.sqrtsd_rr(src, dst);
         367             187 :     }
         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        22315598 :     void load32(ImplicitAddress address, RegisterID dest)
         377                 :     {
         378        22315598 :         m_assembler.movl_mr(address.offset, address.base, dest);
         379        22315598 :     }
         380                 :
         381           56527 :     void load32(BaseIndex address, RegisterID dest)
         382                 :     {
         383           56527 :         m_assembler.movl_mr(address.offset, address.base, address.index, address.scale, dest);
         384           56527 :     }
         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           63198 :     void load16(BaseIndex address, RegisterID dest)
         448                 :     {
         449           63198 :         m_assembler.movzwl_mr(address.offset, address.base, address.index, address.scale, dest);
         450           63198 :     }
         451                 :
         452          148406 :     void load16(Address address, RegisterID dest)
         453                 :     {
         454          148406 :         m_assembler.movzwl_mr(address.offset, address.base, dest);
         455          148406 :     }
         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        23457719 :     void store32(RegisterID src, ImplicitAddress address)
         464                 :     {
         465        23457719 :         m_assembler.movl_rm(src, address.offset, address.base);
         466        23457719 :     }
         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            8183 :     void store32(TrustedImm32 imm, BaseIndex address)
         474                 :     {
         475            8183 :         m_assembler.movl_i32m(imm.m_value, address.offset, address.base, address.index, address.scale);
         476            8183 :     }
         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        12503874 :     void store32(TrustedImm32 imm, ImplicitAddress address)
         489                 :     {
         490        12503874 :         m_assembler.movl_i32m(imm.m_value, address.offset, address.base);
         491        12503874 :     }
         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            4816 :     void moveDouble(FPRegisterID src, FPRegisterID dest)
         509                 :     {
         510            4816 :         ASSERT(isSSE2Present());
         511            4816 :         m_assembler.movsd_rr(src, dest);
         512            4816 :     }
         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           50206 :     void loadDouble(ImplicitAddress address, FPRegisterID dest)
         535                 :     {
         536           50206 :         ASSERT(isSSE2Present());
         537           50206 :         m_assembler.movsd_mr(address.offset, address.base, dest);
         538           50206 :     }
         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          629432 :     void storeDouble(FPRegisterID src, ImplicitAddress address)
         567                 :     {
         568          629432 :         ASSERT(isSSE2Present());
         569          629432 :         m_assembler.movsd_rm(src, address.offset, address.base);
         570          629432 :     }
         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          530032 :     void addDouble(FPRegisterID src, FPRegisterID dest)
         591                 :     {
         592          530032 :         ASSERT(isSSE2Present());
         593          530032 :         m_assembler.addsd_rr(src, dest);
         594          530032 :     }
         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            7994 :     void divDouble(FPRegisterID src, FPRegisterID dest)
         603                 :     {
         604            7994 :         ASSERT(isSSE2Present());
         605            7994 :         m_assembler.divsd_rr(src, dest);
         606            7994 :     }
         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           34555 :     void subDouble(FPRegisterID src, FPRegisterID dest)
         615                 :     {
         616           34555 :         ASSERT(isSSE2Present());
         617           34555 :         m_assembler.subsd_rr(src, dest);
         618           34555 :     }
         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            4702 :     void mulDouble(FPRegisterID src, FPRegisterID dest)
         627                 :     {
         628            4702 :         ASSERT(isSSE2Present());
         629            4702 :         m_assembler.mulsd_rr(src, dest);
         630            4702 :     }
         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            3232 :     void xorDouble(FPRegisterID src, FPRegisterID dest)
         639                 :     {
         640            3232 :         ASSERT(isSSE2Present());
         641            3232 :         m_assembler.xorpd_rr(src, dest);
         642            3232 :     }
         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          717365 :     void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
         660                 :     {
         661          717365 :         ASSERT(isSSE2Present());
         662          717365 :         m_assembler.cvtsi2sd_rr(src, dest);
         663          717365 :     }
         664                 :
         665           24081 :     void convertInt32ToDouble(Address src, FPRegisterID dest)
         666                 :     {
         667           24081 :         ASSERT(isSSE2Present());
         668           24081 :         m_assembler.cvtsi2sd_mr(src.offset, src.base, dest);
         669           24081 :     }
         670                 :
         671           56298 :     Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
         672                 :     {
         673           56298 :         ASSERT(isSSE2Present());
         674                 :
         675           56298 :         if (cond & DoubleConditionBitInvert)
         676           43385 :             m_assembler.ucomisd_rr(left, right);
         677                 :         else
         678           12913 :             m_assembler.ucomisd_rr(right, left);
         679                 :
         680           56298 :         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           55773 :         } 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           55773 :         ASSERT(!(cond & DoubleConditionBitSpecial));
         695           55773 :         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            6321 :     Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest)
         703                 :     {
         704            6321 :         ASSERT(isSSE2Present());
         705            6321 :         m_assembler.cvttsd2si_rr(src, dest);
         706            6321 :         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            7149 :     void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp)
         714                 :     {
         715            7149 :         ASSERT(isSSE2Present());
         716            7149 :         ASSERT(src != fpTemp);
         717            7149 :         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            7149 :         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            7149 :         convertInt32ToDouble(dest, fpTemp);
         724            7149 :         m_assembler.ucomisd_rr(fpTemp, src);
         725            7149 :         failureCases.append(m_assembler.jp());
         726            7149 :         failureCases.append(m_assembler.jne());
         727            7149 :     }
         728                 :
         729             945 :     void zeroDouble(FPRegisterID srcDest)
         730                 :     {
         731             945 :         ASSERT(isSSE2Present());
         732             945 :         m_assembler.xorpd_rr(srcDest, srcDest);
         733             945 :     }
         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          450635 :     void pop(RegisterID dest)
         745                 :     {
         746          450635 :         m_assembler.pop_r(dest);
         747          450635 :     }
         748                 :
         749          234339 :     void push(RegisterID src)
         750                 :     {
         751          234339 :         m_assembler.push_r(src);
         752          234339 :     }
         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         1044382 :     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         1044382 :         if (!imm.m_value)
         774          358540 :             m_assembler.xorl_rr(dest, dest);
         775                 :         else
         776          685842 :             m_assembler.movl_i32r(imm.m_value, dest);
         777         1044382 :     }
         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        11207512 :     void move(RegisterID src, RegisterID dest)
         814                 :     {
         815        11207512 :         if (src != dest)
         816        11207488 :             m_assembler.movl_rr(src, dest);
         817        11207512 :     }
         818                 :
         819         1467468 :     void move(TrustedImmPtr imm, RegisterID dest)
         820                 :     {
         821         1467468 :         m_assembler.movl_i32r(imm.asIntptr(), dest);
         822         1467468 :     }
         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          259717 :     Jump branch32(Condition cond, RegisterID left, RegisterID right)
         868                 :     {
         869          259717 :         m_assembler.cmpl_rr(right, left);
         870          259717 :         return Jump(m_assembler.jCC(x86Condition(cond)));
         871                 :     }
         872                 :
         873         4508712 :     Jump branch32(Condition cond, RegisterID left, TrustedImm32 right)
         874                 :     {
         875         4508712 :         if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
         876           27039 :             m_assembler.testl_rr(left, left);
         877                 :         else
         878         4481673 :             m_assembler.cmpl_ir(right.m_value, left);
         879         4508712 :         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           87182 :     Jump branch32(Condition cond, RegisterID left, Address right)
         908                 :     {
         909           87182 :         m_assembler.cmpl_mr(right.offset, right.base, left);
         910           87182 :         return Jump(m_assembler.jCC(x86Condition(cond)));
         911                 :     }
         912                 :
         913           62494 :     Jump branch32(Condition cond, Address left, RegisterID right)
         914                 :     {
         915           62494 :         m_assembler.cmpl_rm(right, left.offset, left.base);
         916           62494 :         return Jump(m_assembler.jCC(x86Condition(cond)));
         917                 :     }
         918                 :
         919          741866 :     Jump branch32(Condition cond, Address left, TrustedImm32 right)
         920                 :     {
         921          741866 :         m_assembler.cmpl_im(right.m_value, left.offset, left.base);
         922          741866 :         return Jump(m_assembler.jCC(x86Condition(cond)));
         923                 :     }
         924                 :
         925           74246 :     Jump branch32(Condition cond, BaseIndex left, TrustedImm32 right)
         926                 :     {
         927           74246 :         m_assembler.cmpl_im(right.m_value, left.offset, left.base, left.index, left.scale);
         928           74246 :         return Jump(m_assembler.jCC(x86Condition(cond)));
         929                 :     }
         930                 :
         931           69584 :     Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, TrustedImm32 right)
         932                 :     {
         933           69584 :         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           57551 :     Jump branch16(Condition cond, BaseIndex left, Imm32 right)
         943                 :     {
         944           57551 :         ASSERT(!(right.m_value & 0xFFFF0000));
         945                 :
         946           57551 :         m_assembler.cmpw_im(right.m_value, left.offset, left.base, left.index, left.scale);
         947           57551 :         return Jump(m_assembler.jCC(x86Condition(cond)));
         948                 :     }
         949                 :
         950          607695 :     Jump branchTest32(Condition cond, RegisterID reg, RegisterID mask)
         951                 :     {
         952          607695 :         ASSERT((cond == Zero) || (cond == NonZero));
         953          607695 :         m_assembler.testl_rr(reg, mask);
         954          607695 :         return Jump(m_assembler.jCC(x86Condition(cond)));
         955                 :     }
         956                 :
         957          249429 :     Jump branchTest32(Condition cond, RegisterID reg, Imm32 mask = Imm32(-1))
         958                 :     {
         959          249429 :         ASSERT((cond == Zero) || (cond == NonZero));
         960                 :         // if we are only interested in the low seven bits, this can be tested with a testb
         961          249429 :         if (mask.m_value == -1)
         962          223591 :             m_assembler.testl_rr(reg, reg);
         963           25838 :         else if (CanUse8Bit(reg) && (mask.m_value & ~0x7f) == 0)
         964           14260 :             m_assembler.testb_i8r(mask.m_value, reg);
         965                 :         else
         966           11578 :             m_assembler.testl_i32r(mask.m_value, reg);
         967          249429 :         return Jump(m_assembler.jCC(x86Condition(cond)));
         968                 :     }
         969                 :
         970          298338 :     Jump branchTest32(Condition cond, Address address, Imm32 mask = Imm32(-1))
         971                 :     {
         972          298338 :         ASSERT((cond == Zero) || (cond == NonZero));
         973          298338 :         if (mask.m_value == -1)
         974               0 :             m_assembler.cmpl_im(0, address.offset, address.base);
         975                 :         else
         976          298338 :             m_assembler.testl_i32m(mask.m_value, address.offset, address.base);
         977          298338 :         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            3431 :     Jump branchTest8(Condition cond, Address address, Imm32 mask = Imm32(-1))
         991                 :     {
         992            3431 :         ASSERT((cond == Zero) || (cond == NonZero));
         993            3431 :         if (mask.m_value == -1)
         994            3431 :             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            3431 :         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         8709420 :     Jump jump()
        1011                 :     {
        1012         8709420 :         return Jump(m_assembler.jmp());
        1013                 :     }
        1014                 :
        1015          580405 :     void jump(RegisterID target)
        1016                 :     {
        1017          580405 :         m_assembler.jmp_r(target);
        1018          580405 :     }
        1019                 :
        1020                 :     // Address is a memory location containing the address to jump to
        1021            2927 :     void jump(Address address)
        1022                 :     {
        1023            2927 :         m_assembler.jmp_m(address.offset, address.base);
        1024            2927 :     }
        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          319089 :     Jump branchAdd32(Condition cond, RegisterID src, RegisterID dest)
        1042                 :     {
        1043          319089 :         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
        1044          319089 :         add32(src, dest);
        1045          319089 :         return Jump(m_assembler.jCC(x86Condition(cond)));
        1046                 :     }
        1047                 :
        1048          222719 :     Jump branchAdd32(Condition cond, Imm32 imm, RegisterID dest)
        1049                 :     {
        1050          222719 :         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
        1051          222719 :         add32(imm, dest);
        1052          222719 :         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            1875 :     Jump branchMul32(Condition cond, Imm32 imm, RegisterID src, RegisterID dest)
        1091                 :     {
        1092            1875 :         ASSERT(cond == Overflow);
        1093            1875 :         mul32(imm, src, dest);
        1094            1875 :         return Jump(m_assembler.jCC(x86Condition(cond)));
        1095                 :     }
        1096                 :
        1097            3987 :     Jump branchSub32(Condition cond, RegisterID src, RegisterID dest)
        1098                 :     {
        1099            3987 :         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
        1100            3987 :         sub32(src, dest);
        1101            3987 :         return Jump(m_assembler.jCC(x86Condition(cond)));
        1102                 :     }
        1103                 :
        1104           42142 :     Jump branchSub32(Condition cond, Imm32 imm, RegisterID dest)
        1105                 :     {
        1106           42142 :         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
        1107           42142 :         sub32(imm, dest);
        1108           42142 :         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          112408 :     void ret()
        1170                 :     {
        1171          112408 :         m_assembler.ret();
        1172          112408 :     }
        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            1102 :     void set32(Condition cond, RegisterID left, Address right, RegisterID dest)
        1203                 :     {
        1204            1102 :         m_assembler.cmpl_mr(right.offset, right.base, left);
        1205            1102 :         m_assembler.setCC_r(x86Condition(cond), dest);
        1206            1102 :         m_assembler.movzbl_rr(dest, dest);
        1207            1102 :     }
        1208                 :
        1209            7614 :     void set32(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
        1210                 :     {
        1211            7614 :         m_assembler.cmpl_rr(right, left);
        1212            7614 :         m_assembler.setCC_r(x86Condition(cond), dest);
        1213            7614 :         m_assembler.movzbl_rr(dest, dest);
        1214            7614 :     }
        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           35149 :     void set32(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
        1224                 :     {
        1225           35149 :         if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
        1226           20845 :             m_assembler.testl_rr(left, left);
        1227                 :         else
        1228           14304 :             m_assembler.cmpl_ir(right.m_value, left);
        1229           35149 :         m_assembler.setCC_r(x86Condition(cond), dest);
        1230           35149 :         m_assembler.movzbl_rr(dest, dest);
        1231           35149 :     }
        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         1323192 :     static SSECheckState getSSEState()
        1272                 :     {
        1273         1323192 :         if (s_sseCheckState == NotCheckedSSE) {
        1274               0 :             MacroAssemblerX86Common::setSSECheckState();
        1275                 :         }
        1276                 :         // Only check once.
        1277         1323192 :         ASSERT(s_sseCheckState != NotCheckedSSE);
        1278                 :
        1279         1323192 :         return s_sseCheckState;
        1280                 :     }
        1281                 :
        1282                 : protected:
        1283         9005811 :     X86Assembler::Condition x86Condition(Condition cond)
        1284                 :     {
        1285         9005811 :         return static_cast<X86Assembler::Condition>(cond);
        1286                 :     }
        1287                 :
        1288                 : private:
        1289                 :     friend class MacroAssemblerX86;
        1290                 :
        1291                 :     static SSECheckState s_sseCheckState;
        1292                 :
        1293           16442 :     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           16442 :         volatile int flags_edx = 0;
        1298           16442 :         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           16442 :              );
        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           16442 :         if (flags_ecx & SSE42FeatureBit)
        1374               0 :             s_sseCheckState = HasSSE4_2;
        1375           16442 :         else if (flags_ecx & SSE41FeatureBit)
        1376               0 :             s_sseCheckState = HasSSE4_1;
        1377           16442 :         else if (flags_ecx & SSSE3FeatureBit)
        1378           16442 :             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           16442 :     }
        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         3125692 :     static bool isSSE2Present()
        1417                 :     {
        1418         3125692 :         if (s_sseCheckState == NotCheckedSSE) {
        1419           16442 :             setSSECheckState();
        1420                 :         }
        1421                 :         // Only check once.
        1422         3125692 :         ASSERT(s_sseCheckState != NotCheckedSSE);
        1423                 :
        1424         3125692 :         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