JavaScriptCore/assembler/MacroAssemblerMIPS.h
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 2008 Apple Inc. All rights reserved.
       
     3  * Copyright (C) 2010 MIPS Technologies, Inc. All rights reserved.
       
     4  *
       
     5  * Redistribution and use in source and binary forms, with or without
       
     6  * modification, are permitted provided that the following conditions
       
     7  * are met:
       
     8  * 1. Redistributions of source code must retain the above copyright
       
     9  *    notice, this list of conditions and the following disclaimer.
       
    10  * 2. Redistributions in binary form must reproduce the above copyright
       
    11  *    notice, this list of conditions and the following disclaimer in the
       
    12  *    documentation and/or other materials provided with the distribution.
       
    13  *
       
    14  * THIS SOFTWARE IS PROVIDED BY MIPS TECHNOLOGIES, INC. ``AS IS'' AND ANY
       
    15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
       
    16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
       
    17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL MIPS TECHNOLOGIES, INC. OR
       
    18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
       
    19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
       
    20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
       
    21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
       
    22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
       
    24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    25  */
       
    26 
       
    27 #ifndef MacroAssemblerMIPS_h
       
    28 #define MacroAssemblerMIPS_h
       
    29 
       
    30 #if ENABLE(ASSEMBLER) && CPU(MIPS)
       
    31 
       
    32 #include "AbstractMacroAssembler.h"
       
    33 #include "MIPSAssembler.h"
       
    34 
       
    35 namespace JSC {
       
    36 
       
    37 class MacroAssemblerMIPS : public AbstractMacroAssembler<MIPSAssembler> {
       
    38 public:
       
    39     typedef MIPSRegisters::FPRegisterID FPRegisterID;
       
    40 
       
    41     MacroAssemblerMIPS()
       
    42         : m_fixedWidth(false)
       
    43     {
       
    44     }
       
    45 
       
    46     static const Scale ScalePtr = TimesFour;
       
    47 
       
    48     // For storing immediate number
       
    49     static const RegisterID immTempRegister = MIPSRegisters::t0;
       
    50     // For storing data loaded from the memory
       
    51     static const RegisterID dataTempRegister = MIPSRegisters::t1;
       
    52     // For storing address base
       
    53     static const RegisterID addrTempRegister = MIPSRegisters::t2;
       
    54     // For storing compare result
       
    55     static const RegisterID cmpTempRegister = MIPSRegisters::t3;
       
    56 
       
    57     // FP temp register
       
    58     static const FPRegisterID fpTempRegister = MIPSRegisters::f16;
       
    59 
       
    60     enum Condition {
       
    61         Equal,
       
    62         NotEqual,
       
    63         Above,
       
    64         AboveOrEqual,
       
    65         Below,
       
    66         BelowOrEqual,
       
    67         GreaterThan,
       
    68         GreaterThanOrEqual,
       
    69         LessThan,
       
    70         LessThanOrEqual,
       
    71         Overflow,
       
    72         Signed,
       
    73         Zero,
       
    74         NonZero
       
    75     };
       
    76 
       
    77     enum DoubleCondition {
       
    78         DoubleEqual,
       
    79         DoubleNotEqual,
       
    80         DoubleGreaterThan,
       
    81         DoubleGreaterThanOrEqual,
       
    82         DoubleLessThan,
       
    83         DoubleLessThanOrEqual,
       
    84         DoubleEqualOrUnordered,
       
    85         DoubleNotEqualOrUnordered,
       
    86         DoubleGreaterThanOrUnordered,
       
    87         DoubleGreaterThanOrEqualOrUnordered,
       
    88         DoubleLessThanOrUnordered,
       
    89         DoubleLessThanOrEqualOrUnordered
       
    90     };
       
    91 
       
    92     static const RegisterID stackPointerRegister = MIPSRegisters::sp;
       
    93     static const RegisterID returnAddressRegister = MIPSRegisters::ra;
       
    94 
       
    95     // Integer arithmetic operations:
       
    96     //
       
    97     // Operations are typically two operand - operation(source, srcDst)
       
    98     // For many operations the source may be an Imm32, the srcDst operand
       
    99     // may often be a memory location (explictly described using an Address
       
   100     // object).
       
   101 
       
   102     void add32(RegisterID src, RegisterID dest)
       
   103     {
       
   104         m_assembler.addu(dest, dest, src);
       
   105     }
       
   106 
       
   107     void add32(Imm32 imm, RegisterID dest)
       
   108     {
       
   109         add32(imm, dest, dest);
       
   110     }
       
   111 
       
   112     void add32(Imm32 imm, RegisterID src, RegisterID dest)
       
   113     {
       
   114         if (!imm.m_isPointer && imm.m_value >= -32768 && imm.m_value <= 32767
       
   115             && !m_fixedWidth) {
       
   116             /*
       
   117               addiu     dest, src, imm
       
   118             */
       
   119             m_assembler.addiu(dest, src, imm.m_value);
       
   120         } else {
       
   121             /*
       
   122               li        immTemp, imm
       
   123               addu      dest, src, immTemp
       
   124             */
       
   125             move(imm, immTempRegister);
       
   126             m_assembler.addu(dest, src, immTempRegister);
       
   127         }
       
   128     }
       
   129 
       
   130     void add32(Imm32 imm, Address address)
       
   131     {
       
   132         if (address.offset >= -32768 && address.offset <= 32767
       
   133             && !m_fixedWidth) {
       
   134             /*
       
   135               lw        dataTemp, offset(base)
       
   136               li        immTemp, imm
       
   137               addu      dataTemp, dataTemp, immTemp
       
   138               sw        dataTemp, offset(base)
       
   139             */
       
   140             m_assembler.lw(dataTempRegister, address.base, address.offset);
       
   141             if (!imm.m_isPointer
       
   142                 && imm.m_value >= -32768 && imm.m_value <= 32767
       
   143                 && !m_fixedWidth)
       
   144                 m_assembler.addiu(dataTempRegister, dataTempRegister,
       
   145                                   imm.m_value);
       
   146             else {
       
   147                 move(imm, immTempRegister);
       
   148                 m_assembler.addu(dataTempRegister, dataTempRegister,
       
   149                                  immTempRegister);
       
   150             }
       
   151             m_assembler.sw(dataTempRegister, address.base, address.offset);
       
   152         } else {
       
   153             /*
       
   154               lui       addrTemp, (offset + 0x8000) >> 16
       
   155               addu      addrTemp, addrTemp, base
       
   156               lw        dataTemp, (offset & 0xffff)(addrTemp)
       
   157               li        immtemp, imm
       
   158               addu      dataTemp, dataTemp, immTemp
       
   159               sw        dataTemp, (offset & 0xffff)(addrTemp)
       
   160             */
       
   161             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
       
   162             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
       
   163             m_assembler.lw(dataTempRegister, addrTempRegister, address.offset);
       
   164 
       
   165             if (imm.m_value >= -32768 && imm.m_value <= 32767 && !m_fixedWidth)
       
   166                 m_assembler.addiu(dataTempRegister, dataTempRegister,
       
   167                                   imm.m_value);
       
   168             else {
       
   169                 move(imm, immTempRegister);
       
   170                 m_assembler.addu(dataTempRegister, dataTempRegister,
       
   171                                  immTempRegister);
       
   172             }
       
   173             m_assembler.sw(dataTempRegister, addrTempRegister, address.offset);
       
   174         }
       
   175     }
       
   176 
       
   177     void add32(Address src, RegisterID dest)
       
   178     {
       
   179         load32(src, dataTempRegister);
       
   180         add32(dataTempRegister, dest);
       
   181     }
       
   182 
       
   183     void add32(RegisterID src, Address dest)
       
   184     {
       
   185         if (dest.offset >= -32768 && dest.offset <= 32767 && !m_fixedWidth) {
       
   186             /*
       
   187               lw        dataTemp, offset(base)
       
   188               addu      dataTemp, dataTemp, src
       
   189               sw        dataTemp, offset(base)
       
   190             */
       
   191             m_assembler.lw(dataTempRegister, dest.base, dest.offset);
       
   192             m_assembler.addu(dataTempRegister, dataTempRegister, src);
       
   193             m_assembler.sw(dataTempRegister, dest.base, dest.offset);
       
   194         } else {
       
   195             /*
       
   196               lui       addrTemp, (offset + 0x8000) >> 16
       
   197               addu      addrTemp, addrTemp, base
       
   198               lw        dataTemp, (offset & 0xffff)(addrTemp)
       
   199               addu      dataTemp, dataTemp, src
       
   200               sw        dataTemp, (offset & 0xffff)(addrTemp)
       
   201             */
       
   202             m_assembler.lui(addrTempRegister, (dest.offset + 0x8000) >> 16);
       
   203             m_assembler.addu(addrTempRegister, addrTempRegister, dest.base);
       
   204             m_assembler.lw(dataTempRegister, addrTempRegister, dest.offset);
       
   205             m_assembler.addu(dataTempRegister, dataTempRegister, src);
       
   206             m_assembler.sw(dataTempRegister, addrTempRegister, dest.offset);
       
   207         }
       
   208     }
       
   209 
       
   210     void add32(Imm32 imm, AbsoluteAddress address)
       
   211     {
       
   212         /*
       
   213            li   addrTemp, address
       
   214            li   immTemp, imm
       
   215            lw   dataTemp, 0(addrTemp)
       
   216            addu dataTemp, dataTemp, immTemp
       
   217            sw   dataTemp, 0(addrTemp)
       
   218         */
       
   219         move(ImmPtr(address.m_ptr), addrTempRegister);
       
   220         m_assembler.lw(dataTempRegister, addrTempRegister, 0);
       
   221         if (!imm.m_isPointer && imm.m_value >= -32768 && imm.m_value <= 32767
       
   222             && !m_fixedWidth)
       
   223             m_assembler.addiu(dataTempRegister, dataTempRegister, imm.m_value);
       
   224         else {
       
   225             move(imm, immTempRegister);
       
   226             m_assembler.addu(dataTempRegister, dataTempRegister, immTempRegister);
       
   227         }
       
   228         m_assembler.sw(dataTempRegister, addrTempRegister, 0);
       
   229     }
       
   230 
       
   231     void and32(RegisterID src, RegisterID dest)
       
   232     {
       
   233         m_assembler.andInsn(dest, dest, src);
       
   234     }
       
   235 
       
   236     void and32(Imm32 imm, RegisterID dest)
       
   237     {
       
   238         if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth)
       
   239             move(MIPSRegisters::zero, dest);
       
   240         else if (!imm.m_isPointer && imm.m_value > 0 && imm.m_value < 65535
       
   241                  && !m_fixedWidth)
       
   242             m_assembler.andi(dest, dest, imm.m_value);
       
   243         else {
       
   244             /*
       
   245               li        immTemp, imm
       
   246               and       dest, dest, immTemp
       
   247             */
       
   248             move(imm, immTempRegister);
       
   249             m_assembler.andInsn(dest, dest, immTempRegister);
       
   250         }
       
   251     }
       
   252 
       
   253     void lshift32(Imm32 imm, RegisterID dest)
       
   254     {
       
   255         m_assembler.sll(dest, dest, imm.m_value);
       
   256     }
       
   257 
       
   258     void lshift32(RegisterID shiftAmount, RegisterID dest)
       
   259     {
       
   260         m_assembler.sllv(dest, dest, shiftAmount);
       
   261     }
       
   262 
       
   263     void mul32(RegisterID src, RegisterID dest)
       
   264     {
       
   265         m_assembler.mul(dest, dest, src);
       
   266     }
       
   267 
       
   268     void mul32(Imm32 imm, RegisterID src, RegisterID dest)
       
   269     {
       
   270         if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth)
       
   271             move(MIPSRegisters::zero, dest);
       
   272         else if (!imm.m_isPointer && imm.m_value == 1 && !m_fixedWidth)
       
   273             move(src, dest);
       
   274         else {
       
   275             /*
       
   276                 li      dataTemp, imm
       
   277                 mul     dest, src, dataTemp
       
   278             */
       
   279             move(imm, dataTempRegister);
       
   280             m_assembler.mul(dest, src, dataTempRegister);
       
   281         }
       
   282     }
       
   283 
       
   284     void not32(RegisterID srcDest)
       
   285     {
       
   286         m_assembler.nor(srcDest, srcDest, MIPSRegisters::zero);
       
   287     }
       
   288 
       
   289     void or32(RegisterID src, RegisterID dest)
       
   290     {
       
   291         m_assembler.orInsn(dest, dest, src);
       
   292     }
       
   293 
       
   294     void or32(Imm32 imm, RegisterID dest)
       
   295     {
       
   296         if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth)
       
   297             return;
       
   298 
       
   299         if (!imm.m_isPointer && imm.m_value > 0 && imm.m_value < 65535
       
   300             && !m_fixedWidth) {
       
   301             m_assembler.ori(dest, dest, imm.m_value);
       
   302             return;
       
   303         }
       
   304 
       
   305         /*
       
   306             li      dataTemp, imm
       
   307             or      dest, dest, dataTemp
       
   308         */
       
   309         move(imm, dataTempRegister);
       
   310         m_assembler.orInsn(dest, dest, dataTempRegister);
       
   311     }
       
   312 
       
   313     void rshift32(RegisterID shiftAmount, RegisterID dest)
       
   314     {
       
   315         m_assembler.srav(dest, dest, shiftAmount);
       
   316     }
       
   317 
       
   318     void rshift32(Imm32 imm, RegisterID dest)
       
   319     {
       
   320         m_assembler.sra(dest, dest, imm.m_value);
       
   321     }
       
   322 
       
   323     void urshift32(RegisterID shiftAmount, RegisterID dest)
       
   324     {
       
   325         m_assembler.srlv(dest, dest, shiftAmount);
       
   326     }
       
   327 
       
   328     void urshift32(Imm32 imm, RegisterID dest)
       
   329     {
       
   330         m_assembler.srl(dest, dest, imm.m_value);
       
   331     }
       
   332 
       
   333     void sub32(RegisterID src, RegisterID dest)
       
   334     {
       
   335         m_assembler.subu(dest, dest, src);
       
   336     }
       
   337 
       
   338     void sub32(Imm32 imm, RegisterID dest)
       
   339     {
       
   340         if (!imm.m_isPointer && imm.m_value >= -32767 && imm.m_value <= 32768
       
   341             && !m_fixedWidth) {
       
   342             /*
       
   343               addiu     dest, src, imm
       
   344             */
       
   345             m_assembler.addiu(dest, dest, -imm.m_value);
       
   346         } else {
       
   347             /*
       
   348               li        immTemp, imm
       
   349               subu      dest, src, immTemp
       
   350             */
       
   351             move(imm, immTempRegister);
       
   352             m_assembler.subu(dest, dest, immTempRegister);
       
   353         }
       
   354     }
       
   355 
       
   356     void sub32(Imm32 imm, Address address)
       
   357     {
       
   358         if (address.offset >= -32768 && address.offset <= 32767
       
   359             && !m_fixedWidth) {
       
   360             /*
       
   361               lw        dataTemp, offset(base)
       
   362               li        immTemp, imm
       
   363               subu      dataTemp, dataTemp, immTemp
       
   364               sw        dataTemp, offset(base)
       
   365             */
       
   366             m_assembler.lw(dataTempRegister, address.base, address.offset);
       
   367             if (!imm.m_isPointer
       
   368                 && imm.m_value >= -32767 && imm.m_value <= 32768
       
   369                 && !m_fixedWidth)
       
   370                 m_assembler.addiu(dataTempRegister, dataTempRegister,
       
   371                                   -imm.m_value);
       
   372             else {
       
   373                 move(imm, immTempRegister);
       
   374                 m_assembler.subu(dataTempRegister, dataTempRegister,
       
   375                                  immTempRegister);
       
   376             }
       
   377             m_assembler.sw(dataTempRegister, address.base, address.offset);
       
   378         } else {
       
   379             /*
       
   380               lui       addrTemp, (offset + 0x8000) >> 16
       
   381               addu      addrTemp, addrTemp, base
       
   382               lw        dataTemp, (offset & 0xffff)(addrTemp)
       
   383               li        immtemp, imm
       
   384               subu      dataTemp, dataTemp, immTemp
       
   385               sw        dataTemp, (offset & 0xffff)(addrTemp)
       
   386             */
       
   387             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
       
   388             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
       
   389             m_assembler.lw(dataTempRegister, addrTempRegister, address.offset);
       
   390 
       
   391             if (!imm.m_isPointer
       
   392                 && imm.m_value >= -32767 && imm.m_value <= 32768
       
   393                 && !m_fixedWidth)
       
   394                 m_assembler.addiu(dataTempRegister, dataTempRegister,
       
   395                                   -imm.m_value);
       
   396             else {
       
   397                 move(imm, immTempRegister);
       
   398                 m_assembler.subu(dataTempRegister, dataTempRegister,
       
   399                                  immTempRegister);
       
   400             }
       
   401             m_assembler.sw(dataTempRegister, addrTempRegister, address.offset);
       
   402         }
       
   403     }
       
   404 
       
   405     void sub32(Address src, RegisterID dest)
       
   406     {
       
   407         load32(src, dataTempRegister);
       
   408         sub32(dataTempRegister, dest);
       
   409     }
       
   410 
       
   411     void sub32(Imm32 imm, AbsoluteAddress address)
       
   412     {
       
   413         /*
       
   414            li   addrTemp, address
       
   415            li   immTemp, imm
       
   416            lw   dataTemp, 0(addrTemp)
       
   417            subu dataTemp, dataTemp, immTemp
       
   418            sw   dataTemp, 0(addrTemp)
       
   419         */
       
   420         move(ImmPtr(address.m_ptr), addrTempRegister);
       
   421         m_assembler.lw(dataTempRegister, addrTempRegister, 0);
       
   422 
       
   423         if (!imm.m_isPointer && imm.m_value >= -32767 && imm.m_value <= 32768
       
   424             && !m_fixedWidth) {
       
   425             m_assembler.addiu(dataTempRegister, dataTempRegister,
       
   426                               -imm.m_value);
       
   427         } else {
       
   428             move(imm, immTempRegister);
       
   429             m_assembler.subu(dataTempRegister, dataTempRegister, immTempRegister);
       
   430         }
       
   431         m_assembler.sw(dataTempRegister, addrTempRegister, 0);
       
   432     }
       
   433 
       
   434     void xor32(RegisterID src, RegisterID dest)
       
   435     {
       
   436         m_assembler.xorInsn(dest, dest, src);
       
   437     }
       
   438 
       
   439     void xor32(Imm32 imm, RegisterID dest)
       
   440     {
       
   441         /*
       
   442             li  immTemp, imm
       
   443             xor dest, dest, immTemp
       
   444         */
       
   445         move(imm, immTempRegister);
       
   446         m_assembler.xorInsn(dest, dest, immTempRegister);
       
   447     }
       
   448 
       
   449     void sqrtDouble(FPRegisterID src, FPRegisterID dst)
       
   450     {
       
   451         m_assembler.sqrtd(dst, src);
       
   452     }
       
   453 
       
   454     // Memory access operations:
       
   455     //
       
   456     // Loads are of the form load(address, destination) and stores of the form
       
   457     // store(source, address).  The source for a store may be an Imm32.  Address
       
   458     // operand objects to loads and store will be implicitly constructed if a
       
   459     // register is passed.
       
   460 
       
   461     /* Need to use zero-extened load byte for load8.  */
       
   462     void load8(ImplicitAddress address, RegisterID dest)
       
   463     {
       
   464         if (address.offset >= -32768 && address.offset <= 32767
       
   465             && !m_fixedWidth)
       
   466             m_assembler.lbu(dest, address.base, address.offset);
       
   467         else {
       
   468             /*
       
   469                 lui     addrTemp, (offset + 0x8000) >> 16
       
   470                 addu    addrTemp, addrTemp, base
       
   471                 lbu     dest, (offset & 0xffff)(addrTemp)
       
   472               */
       
   473             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
       
   474             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
       
   475             m_assembler.lbu(dest, addrTempRegister, address.offset);
       
   476         }
       
   477     }
       
   478 
       
   479     void load32(ImplicitAddress address, RegisterID dest)
       
   480     {
       
   481         if (address.offset >= -32768 && address.offset <= 32767
       
   482             && !m_fixedWidth)
       
   483             m_assembler.lw(dest, address.base, address.offset);
       
   484         else {
       
   485             /*
       
   486                 lui     addrTemp, (offset + 0x8000) >> 16
       
   487                 addu    addrTemp, addrTemp, base
       
   488                 lw      dest, (offset & 0xffff)(addrTemp)
       
   489               */
       
   490             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
       
   491             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
       
   492             m_assembler.lw(dest, addrTempRegister, address.offset);
       
   493         }
       
   494     }
       
   495 
       
   496     void load32(BaseIndex address, RegisterID dest)
       
   497     {
       
   498         if (address.offset >= -32768 && address.offset <= 32767
       
   499             && !m_fixedWidth) {
       
   500             /*
       
   501                 sll     addrTemp, address.index, address.scale
       
   502                 addu    addrTemp, addrTemp, address.base
       
   503                 lw      dest, address.offset(addrTemp)
       
   504             */
       
   505             m_assembler.sll(addrTempRegister, address.index, address.scale);
       
   506             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
       
   507             m_assembler.lw(dest, addrTempRegister, address.offset);
       
   508         } else {
       
   509             /*
       
   510                 sll     addrTemp, address.index, address.scale
       
   511                 addu    addrTemp, addrTemp, address.base
       
   512                 lui     immTemp, (address.offset + 0x8000) >> 16
       
   513                 addu    addrTemp, addrTemp, immTemp
       
   514                 lw      dest, (address.offset & 0xffff)(at)
       
   515             */
       
   516             m_assembler.sll(addrTempRegister, address.index, address.scale);
       
   517             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
       
   518             m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
       
   519             m_assembler.addu(addrTempRegister, addrTempRegister,
       
   520                              immTempRegister);
       
   521             m_assembler.lw(dest, addrTempRegister, address.offset);
       
   522         }
       
   523     }
       
   524 
       
   525     void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
       
   526     {
       
   527         if (address.offset >= -32768 && address.offset <= 32764
       
   528             && !m_fixedWidth) {
       
   529             /*
       
   530                 sll     addrTemp, address.index, address.scale
       
   531                 addu    addrTemp, addrTemp, address.base
       
   532                 (Big-Endian)
       
   533                 lwl     dest, address.offset(addrTemp)
       
   534                 lwr     dest, address.offset+3(addrTemp)
       
   535                 (Little-Endian)
       
   536                 lwl     dest, address.offset+3(addrTemp)
       
   537                 lwr     dest, address.offset(addrTemp)
       
   538             */
       
   539             m_assembler.sll(addrTempRegister, address.index, address.scale);
       
   540             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
       
   541 #if CPU(BIG_ENDIAN)
       
   542             m_assembler.lwl(dest, addrTempRegister, address.offset);
       
   543             m_assembler.lwr(dest, addrTempRegister, address.offset + 3);
       
   544 #else
       
   545             m_assembler.lwl(dest, addrTempRegister, address.offset + 3);
       
   546             m_assembler.lwr(dest, addrTempRegister, address.offset);
       
   547 
       
   548 #endif
       
   549         } else {
       
   550             /*
       
   551                 sll     addrTemp, address.index, address.scale
       
   552                 addu    addrTemp, addrTemp, address.base
       
   553                 lui     immTemp, address.offset >> 16
       
   554                 ori     immTemp, immTemp, address.offset & 0xffff
       
   555                 addu    addrTemp, addrTemp, immTemp
       
   556                 (Big-Endian)
       
   557                 lw      dest, 0(at)
       
   558                 lw      dest, 3(at)
       
   559                 (Little-Endian)
       
   560                 lw      dest, 3(at)
       
   561                 lw      dest, 0(at)
       
   562             */
       
   563             m_assembler.sll(addrTempRegister, address.index, address.scale);
       
   564             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
       
   565             m_assembler.lui(immTempRegister, address.offset >> 16);
       
   566             m_assembler.ori(immTempRegister, immTempRegister, address.offset);
       
   567             m_assembler.addu(addrTempRegister, addrTempRegister,
       
   568                              immTempRegister);
       
   569 #if CPU(BIG_ENDIAN)
       
   570             m_assembler.lwl(dest, addrTempRegister, 0);
       
   571             m_assembler.lwr(dest, addrTempRegister, 3);
       
   572 #else
       
   573             m_assembler.lwl(dest, addrTempRegister, 3);
       
   574             m_assembler.lwr(dest, addrTempRegister, 0);
       
   575 #endif
       
   576         }
       
   577     }
       
   578 
       
   579     void load32(void* address, RegisterID dest)
       
   580     {
       
   581         /*
       
   582             li  addrTemp, address
       
   583             lw  dest, 0(addrTemp)
       
   584         */
       
   585         move(ImmPtr(address), addrTempRegister);
       
   586         m_assembler.lw(dest, addrTempRegister, 0);
       
   587     }
       
   588 
       
   589     DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
       
   590     {
       
   591         m_fixedWidth = true;
       
   592         /*
       
   593             lui addrTemp, address.offset >> 16
       
   594             ori addrTemp, addrTemp, address.offset & 0xffff
       
   595             addu        addrTemp, addrTemp, address.base
       
   596             lw  dest, 0(addrTemp)
       
   597         */
       
   598         DataLabel32 dataLabel(this);
       
   599         move(Imm32(address.offset), addrTempRegister);
       
   600         m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
       
   601         m_assembler.lw(dest, addrTempRegister, 0);
       
   602         m_fixedWidth = false;
       
   603         return dataLabel;
       
   604     }
       
   605 
       
   606     Label loadPtrWithPatchToLEA(Address address, RegisterID dest)
       
   607     {
       
   608         m_fixedWidth = true;
       
   609         /*
       
   610             lui         addrTemp, address.offset >> 16
       
   611             ori         addrTemp, addrTemp, address.offset & 0xffff
       
   612             addu        addrTemp, addrTemp, address.base
       
   613             lw          dest, 0(addrTemp)
       
   614         */
       
   615         Label label(this);
       
   616         move(Imm32(address.offset), addrTempRegister);
       
   617         m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
       
   618         m_assembler.lw(dest, addrTempRegister, 0);
       
   619         m_fixedWidth = false;
       
   620         return label;
       
   621     }
       
   622 
       
   623     Label loadPtrWithAddressOffsetPatch(Address address, RegisterID dest)
       
   624     {
       
   625         return loadPtrWithPatchToLEA(address, dest);
       
   626     }
       
   627 
       
   628     /* Need to use zero-extened load half-word for load16.  */
       
   629     void load16(ImplicitAddress address, RegisterID dest)
       
   630     {
       
   631         if (address.offset >= -32768 && address.offset <= 32767
       
   632             && !m_fixedWidth)
       
   633             m_assembler.lhu(dest, address.base, address.offset);
       
   634         else {
       
   635             /*
       
   636                 lui     addrTemp, (offset + 0x8000) >> 16
       
   637                 addu    addrTemp, addrTemp, base
       
   638                 lhu     dest, (offset & 0xffff)(addrTemp)
       
   639               */
       
   640             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
       
   641             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
       
   642             m_assembler.lhu(dest, addrTempRegister, address.offset);
       
   643         }
       
   644     }
       
   645 
       
   646     /* Need to use zero-extened load half-word for load16.  */
       
   647     void load16(BaseIndex address, RegisterID dest)
       
   648     {
       
   649         if (address.offset >= -32768 && address.offset <= 32767
       
   650             && !m_fixedWidth) {
       
   651             /*
       
   652                 sll     addrTemp, address.index, address.scale
       
   653                 addu    addrTemp, addrTemp, address.base
       
   654                 lhu     dest, address.offset(addrTemp)
       
   655             */
       
   656             m_assembler.sll(addrTempRegister, address.index, address.scale);
       
   657             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
       
   658             m_assembler.lhu(dest, addrTempRegister, address.offset);
       
   659         } else {
       
   660             /*
       
   661                 sll     addrTemp, address.index, address.scale
       
   662                 addu    addrTemp, addrTemp, address.base
       
   663                 lui     immTemp, (address.offset + 0x8000) >> 16
       
   664                 addu    addrTemp, addrTemp, immTemp
       
   665                 lhu     dest, (address.offset & 0xffff)(addrTemp)
       
   666             */
       
   667             m_assembler.sll(addrTempRegister, address.index, address.scale);
       
   668             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
       
   669             m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
       
   670             m_assembler.addu(addrTempRegister, addrTempRegister,
       
   671                              immTempRegister);
       
   672             m_assembler.lhu(dest, addrTempRegister, address.offset);
       
   673         }
       
   674     }
       
   675 
       
   676     DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
       
   677     {
       
   678         m_fixedWidth = true;
       
   679         /*
       
   680             lui addrTemp, address.offset >> 16
       
   681             ori addrTemp, addrTemp, address.offset & 0xffff
       
   682             addu        addrTemp, addrTemp, address.base
       
   683             sw  src, 0(addrTemp)
       
   684         */
       
   685         DataLabel32 dataLabel(this);
       
   686         move(Imm32(address.offset), addrTempRegister);
       
   687         m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
       
   688         m_assembler.sw(src, addrTempRegister, 0);
       
   689         m_fixedWidth = false;
       
   690         return dataLabel;
       
   691     }
       
   692 
       
   693     void store32(RegisterID src, ImplicitAddress address)
       
   694     {
       
   695         if (address.offset >= -32768 && address.offset <= 32767
       
   696             && !m_fixedWidth)
       
   697             m_assembler.sw(src, address.base, address.offset);
       
   698         else {
       
   699             /*
       
   700                 lui     addrTemp, (offset + 0x8000) >> 16
       
   701                 addu    addrTemp, addrTemp, base
       
   702                 sw      src, (offset & 0xffff)(addrTemp)
       
   703               */
       
   704             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
       
   705             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
       
   706             m_assembler.sw(src, addrTempRegister, address.offset);
       
   707         }
       
   708     }
       
   709 
       
   710     void store32(RegisterID src, BaseIndex address)
       
   711     {
       
   712         if (address.offset >= -32768 && address.offset <= 32767
       
   713             && !m_fixedWidth) {
       
   714             /*
       
   715                 sll     addrTemp, address.index, address.scale
       
   716                 addu    addrTemp, addrTemp, address.base
       
   717                 sw      src, address.offset(addrTemp)
       
   718             */
       
   719             m_assembler.sll(addrTempRegister, address.index, address.scale);
       
   720             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
       
   721             m_assembler.sw(src, addrTempRegister, address.offset);
       
   722         } else {
       
   723             /*
       
   724                 sll     addrTemp, address.index, address.scale
       
   725                 addu    addrTemp, addrTemp, address.base
       
   726                 lui     immTemp, (address.offset + 0x8000) >> 16
       
   727                 addu    addrTemp, addrTemp, immTemp
       
   728                 sw      src, (address.offset & 0xffff)(at)
       
   729             */
       
   730             m_assembler.sll(addrTempRegister, address.index, address.scale);
       
   731             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
       
   732             m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
       
   733             m_assembler.addu(addrTempRegister, addrTempRegister,
       
   734                              immTempRegister);
       
   735             m_assembler.sw(src, addrTempRegister, address.offset);
       
   736         }
       
   737     }
       
   738 
       
   739     void store32(Imm32 imm, ImplicitAddress address)
       
   740     {
       
   741         if (address.offset >= -32768 && address.offset <= 32767
       
   742             && !m_fixedWidth) {
       
   743             if (!imm.m_isPointer && !imm.m_value)
       
   744                 m_assembler.sw(MIPSRegisters::zero, address.base,
       
   745                                address.offset);
       
   746             else {
       
   747                 move(imm, immTempRegister);
       
   748                 m_assembler.sw(immTempRegister, address.base, address.offset);
       
   749             }
       
   750         } else {
       
   751             /*
       
   752                 lui     addrTemp, (offset + 0x8000) >> 16
       
   753                 addu    addrTemp, addrTemp, base
       
   754                 sw      immTemp, (offset & 0xffff)(addrTemp)
       
   755               */
       
   756             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
       
   757             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
       
   758             if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth)
       
   759                 m_assembler.sw(MIPSRegisters::zero, addrTempRegister,
       
   760                                address.offset);
       
   761             else {
       
   762                 move(imm, immTempRegister);
       
   763                 m_assembler.sw(immTempRegister, addrTempRegister,
       
   764                                address.offset);
       
   765             }
       
   766         }
       
   767     }
       
   768 
       
   769     void store32(RegisterID src, void* address)
       
   770     {
       
   771         /*
       
   772             li  addrTemp, address
       
   773             sw  src, 0(addrTemp)
       
   774         */
       
   775         move(ImmPtr(address), addrTempRegister);
       
   776         m_assembler.sw(src, addrTempRegister, 0);
       
   777     }
       
   778 
       
   779     void store32(Imm32 imm, void* address)
       
   780     {
       
   781         /*
       
   782             li  immTemp, imm
       
   783             li  addrTemp, address
       
   784             sw  src, 0(addrTemp)
       
   785         */
       
   786         if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) {
       
   787             move(ImmPtr(address), addrTempRegister);
       
   788             m_assembler.sw(MIPSRegisters::zero, addrTempRegister, 0);
       
   789         } else {
       
   790             move(imm, immTempRegister);
       
   791             move(ImmPtr(address), addrTempRegister);
       
   792             m_assembler.sw(immTempRegister, addrTempRegister, 0);
       
   793         }
       
   794     }
       
   795 
       
   796     // Floating-point operations:
       
   797 
       
   798     bool supportsFloatingPoint() const
       
   799     {
       
   800 #if WTF_MIPS_DOUBLE_FLOAT
       
   801         return true;
       
   802 #else
       
   803         return false;
       
   804 #endif
       
   805     }
       
   806 
       
   807     bool supportsFloatingPointTruncate() const
       
   808     {
       
   809 #if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2)
       
   810         return true;
       
   811 #else
       
   812         return false;
       
   813 #endif
       
   814     }
       
   815 
       
   816     bool supportsFloatingPointSqrt() const
       
   817     {
       
   818 #if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2)
       
   819         return true;
       
   820 #else
       
   821         return false;
       
   822 #endif
       
   823     }
       
   824 
       
   825     // Stack manipulation operations:
       
   826     //
       
   827     // The ABI is assumed to provide a stack abstraction to memory,
       
   828     // containing machine word sized units of data.  Push and pop
       
   829     // operations add and remove a single register sized unit of data
       
   830     // to or from the stack.  Peek and poke operations read or write
       
   831     // values on the stack, without moving the current stack position.
       
   832 
       
   833     void pop(RegisterID dest)
       
   834     {
       
   835         m_assembler.lw(dest, MIPSRegisters::sp, 0);
       
   836         m_assembler.addiu(MIPSRegisters::sp, MIPSRegisters::sp, 4);
       
   837     }
       
   838 
       
   839     void push(RegisterID src)
       
   840     {
       
   841         m_assembler.addiu(MIPSRegisters::sp, MIPSRegisters::sp, -4);
       
   842         m_assembler.sw(src, MIPSRegisters::sp, 0);
       
   843     }
       
   844 
       
   845     void push(Address address)
       
   846     {
       
   847         load32(address, dataTempRegister);
       
   848         push(dataTempRegister);
       
   849     }
       
   850 
       
   851     void push(Imm32 imm)
       
   852     {
       
   853         move(imm, immTempRegister);
       
   854         push(immTempRegister);
       
   855     }
       
   856 
       
   857     // Register move operations:
       
   858     //
       
   859     // Move values in registers.
       
   860 
       
   861     void move(Imm32 imm, RegisterID dest)
       
   862     {
       
   863         if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth)
       
   864             move(MIPSRegisters::zero, dest);
       
   865         else if (imm.m_isPointer || m_fixedWidth) {
       
   866             m_assembler.lui(dest, imm.m_value >> 16);
       
   867             m_assembler.ori(dest, dest, imm.m_value);
       
   868         } else
       
   869             m_assembler.li(dest, imm.m_value);
       
   870     }
       
   871 
       
   872     void move(RegisterID src, RegisterID dest)
       
   873     {
       
   874         if (src != dest || m_fixedWidth)
       
   875             m_assembler.move(dest, src);
       
   876     }
       
   877 
       
   878     void move(ImmPtr imm, RegisterID dest)
       
   879     {
       
   880         move(Imm32(imm), dest);
       
   881     }
       
   882 
       
   883     void swap(RegisterID reg1, RegisterID reg2)
       
   884     {
       
   885         move(reg1, immTempRegister);
       
   886         move(reg2, reg1);
       
   887         move(immTempRegister, reg2);
       
   888     }
       
   889 
       
   890     void signExtend32ToPtr(RegisterID src, RegisterID dest)
       
   891     {
       
   892         if (src != dest || m_fixedWidth)
       
   893             move(src, dest);
       
   894     }
       
   895 
       
   896     void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
       
   897     {
       
   898         if (src != dest || m_fixedWidth)
       
   899             move(src, dest);
       
   900     }
       
   901 
       
   902     // Forwards / external control flow operations:
       
   903     //
       
   904     // This set of jump and conditional branch operations return a Jump
       
   905     // object which may linked at a later point, allow forwards jump,
       
   906     // or jumps that will require external linkage (after the code has been
       
   907     // relocated).
       
   908     //
       
   909     // For branches, signed <, >, <= and >= are denoted as l, g, le, and ge
       
   910     // respecitvely, for unsigned comparisons the names b, a, be, and ae are
       
   911     // used (representing the names 'below' and 'above').
       
   912     //
       
   913     // Operands to the comparision are provided in the expected order, e.g.
       
   914     // jle32(reg1, Imm32(5)) will branch if the value held in reg1, when
       
   915     // treated as a signed 32bit value, is less than or equal to 5.
       
   916     //
       
   917     // jz and jnz test whether the first operand is equal to zero, and take
       
   918     // an optional second operand of a mask under which to perform the test.
       
   919 
       
   920     Jump branch8(Condition cond, Address left, Imm32 right)
       
   921     {
       
   922         // Make sure the immediate value is unsigned 8 bits.
       
   923         ASSERT(!(right.m_value & 0xFFFFFF00));
       
   924         load8(left, dataTempRegister);
       
   925         move(right, immTempRegister);
       
   926         return branch32(cond, dataTempRegister, immTempRegister);
       
   927     }
       
   928 
       
   929     Jump branch32(Condition cond, RegisterID left, RegisterID right)
       
   930     {
       
   931         if (cond == Equal || cond == Zero)
       
   932             return branchEqual(left, right);
       
   933         if (cond == NotEqual || cond == NonZero)
       
   934             return branchNotEqual(left, right);
       
   935         if (cond == Above) {
       
   936             m_assembler.sltu(cmpTempRegister, right, left);
       
   937             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
       
   938         }
       
   939         if (cond == AboveOrEqual) {
       
   940             m_assembler.sltu(cmpTempRegister, left, right);
       
   941             return branchEqual(cmpTempRegister, MIPSRegisters::zero);
       
   942         }
       
   943         if (cond == Below) {
       
   944             m_assembler.sltu(cmpTempRegister, left, right);
       
   945             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
       
   946         }
       
   947         if (cond == BelowOrEqual) {
       
   948             m_assembler.sltu(cmpTempRegister, right, left);
       
   949             return branchEqual(cmpTempRegister, MIPSRegisters::zero);
       
   950         }
       
   951         if (cond == GreaterThan) {
       
   952             m_assembler.slt(cmpTempRegister, right, left);
       
   953             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
       
   954         }
       
   955         if (cond == GreaterThanOrEqual) {
       
   956             m_assembler.slt(cmpTempRegister, left, right);
       
   957             return branchEqual(cmpTempRegister, MIPSRegisters::zero);
       
   958         }
       
   959         if (cond == LessThan) {
       
   960             m_assembler.slt(cmpTempRegister, left, right);
       
   961             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
       
   962         }
       
   963         if (cond == LessThanOrEqual) {
       
   964             m_assembler.slt(cmpTempRegister, right, left);
       
   965             return branchEqual(cmpTempRegister, MIPSRegisters::zero);
       
   966         }
       
   967         if (cond == Overflow) {
       
   968             /*
       
   969                 xor     cmpTemp, left, right
       
   970                 bgez    No_overflow, cmpTemp    # same sign bit -> no overflow
       
   971                 nop
       
   972                 subu    cmpTemp, left, right
       
   973                 xor     cmpTemp, cmpTemp, left
       
   974                 bgez    No_overflow, cmpTemp    # same sign bit -> no overflow
       
   975                 nop
       
   976                 b       Overflow
       
   977                 nop
       
   978                 nop
       
   979                 nop
       
   980                 nop
       
   981                 nop
       
   982               No_overflow:
       
   983             */
       
   984             m_assembler.xorInsn(cmpTempRegister, left, right);
       
   985             m_assembler.bgez(cmpTempRegister, 11);
       
   986             m_assembler.nop();
       
   987             m_assembler.subu(cmpTempRegister, left, right);
       
   988             m_assembler.xorInsn(cmpTempRegister, cmpTempRegister, left);
       
   989             m_assembler.bgez(cmpTempRegister, 7);
       
   990             m_assembler.nop();
       
   991             return jump();
       
   992         }
       
   993         if (cond == Signed) {
       
   994             m_assembler.subu(cmpTempRegister, left, right);
       
   995             // Check if the result is negative.
       
   996             m_assembler.slt(cmpTempRegister, cmpTempRegister,
       
   997                             MIPSRegisters::zero);
       
   998             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
       
   999         }
       
  1000         ASSERT(0);
       
  1001 
       
  1002         return Jump();
       
  1003     }
       
  1004 
       
  1005     Jump branch32(Condition cond, RegisterID left, Imm32 right)
       
  1006     {
       
  1007         move(right, immTempRegister);
       
  1008         return branch32(cond, left, immTempRegister);
       
  1009     }
       
  1010 
       
  1011     Jump branch32(Condition cond, RegisterID left, Address right)
       
  1012     {
       
  1013         load32(right, dataTempRegister);
       
  1014         return branch32(cond, left, dataTempRegister);
       
  1015     }
       
  1016 
       
  1017     Jump branch32(Condition cond, Address left, RegisterID right)
       
  1018     {
       
  1019         load32(left, dataTempRegister);
       
  1020         return branch32(cond, dataTempRegister, right);
       
  1021     }
       
  1022 
       
  1023     Jump branch32(Condition cond, Address left, Imm32 right)
       
  1024     {
       
  1025         load32(left, dataTempRegister);
       
  1026         move(right, immTempRegister);
       
  1027         return branch32(cond, dataTempRegister, immTempRegister);
       
  1028     }
       
  1029 
       
  1030     Jump branch32(Condition cond, BaseIndex left, Imm32 right)
       
  1031     {
       
  1032         load32(left, dataTempRegister);
       
  1033         // Be careful that the previous load32() uses immTempRegister.
       
  1034         // So, we need to put move() after load32().
       
  1035         move(right, immTempRegister);
       
  1036         return branch32(cond, dataTempRegister, immTempRegister);
       
  1037     }
       
  1038 
       
  1039     Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, Imm32 right)
       
  1040     {
       
  1041         load32WithUnalignedHalfWords(left, dataTempRegister);
       
  1042         // Be careful that the previous load32WithUnalignedHalfWords()
       
  1043         // uses immTempRegister.
       
  1044         // So, we need to put move() after load32WithUnalignedHalfWords().
       
  1045         move(right, immTempRegister);
       
  1046         return branch32(cond, dataTempRegister, immTempRegister);
       
  1047     }
       
  1048 
       
  1049     Jump branch32(Condition cond, AbsoluteAddress left, RegisterID right)
       
  1050     {
       
  1051         load32(left.m_ptr, dataTempRegister);
       
  1052         return branch32(cond, dataTempRegister, right);
       
  1053     }
       
  1054 
       
  1055     Jump branch32(Condition cond, AbsoluteAddress left, Imm32 right)
       
  1056     {
       
  1057         load32(left.m_ptr, dataTempRegister);
       
  1058         move(right, immTempRegister);
       
  1059         return branch32(cond, dataTempRegister, immTempRegister);
       
  1060     }
       
  1061 
       
  1062     Jump branch16(Condition cond, BaseIndex left, RegisterID right)
       
  1063     {
       
  1064         load16(left, dataTempRegister);
       
  1065         return branch32(cond, dataTempRegister, right);
       
  1066     }
       
  1067 
       
  1068     Jump branch16(Condition cond, BaseIndex left, Imm32 right)
       
  1069     {
       
  1070         ASSERT(!(right.m_value & 0xFFFF0000));
       
  1071         load16(left, dataTempRegister);
       
  1072         // Be careful that the previous load16() uses immTempRegister.
       
  1073         // So, we need to put move() after load16().
       
  1074         move(right, immTempRegister);
       
  1075         return branch32(cond, dataTempRegister, immTempRegister);
       
  1076     }
       
  1077 
       
  1078     Jump branchTest32(Condition cond, RegisterID reg, RegisterID mask)
       
  1079     {
       
  1080         ASSERT((cond == Zero) || (cond == NonZero));
       
  1081         m_assembler.andInsn(cmpTempRegister, reg, mask);
       
  1082         if (cond == Zero)
       
  1083             return branchEqual(cmpTempRegister, MIPSRegisters::zero);
       
  1084         return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
       
  1085     }
       
  1086 
       
  1087     Jump branchTest32(Condition cond, RegisterID reg, Imm32 mask = Imm32(-1))
       
  1088     {
       
  1089         ASSERT((cond == Zero) || (cond == NonZero));
       
  1090         if (mask.m_value == -1 && !m_fixedWidth) {
       
  1091             if (cond == Zero)
       
  1092                 return branchEqual(reg, MIPSRegisters::zero);
       
  1093             return branchNotEqual(reg, MIPSRegisters::zero);
       
  1094         }
       
  1095         move(mask, immTempRegister);
       
  1096         return branchTest32(cond, reg, immTempRegister);
       
  1097     }
       
  1098 
       
  1099     Jump branchTest32(Condition cond, Address address, Imm32 mask = Imm32(-1))
       
  1100     {
       
  1101         load32(address, dataTempRegister);
       
  1102         return branchTest32(cond, dataTempRegister, mask);
       
  1103     }
       
  1104 
       
  1105     Jump branchTest32(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1))
       
  1106     {
       
  1107         load32(address, dataTempRegister);
       
  1108         return branchTest32(cond, dataTempRegister, mask);
       
  1109     }
       
  1110 
       
  1111     Jump branchTest8(Condition cond, Address address, Imm32 mask = Imm32(-1))
       
  1112     {
       
  1113         load8(address, dataTempRegister);
       
  1114         return branchTest32(cond, dataTempRegister, mask);
       
  1115     }
       
  1116 
       
  1117     Jump jump()
       
  1118     {
       
  1119         return branchEqual(MIPSRegisters::zero, MIPSRegisters::zero);
       
  1120     }
       
  1121 
       
  1122     void jump(RegisterID target)
       
  1123     {
       
  1124         m_assembler.jr(target);
       
  1125         m_assembler.nop();
       
  1126     }
       
  1127 
       
  1128     void jump(Address address)
       
  1129     {
       
  1130         m_fixedWidth = true;
       
  1131         load32(address, MIPSRegisters::t9);
       
  1132         m_assembler.jr(MIPSRegisters::t9);
       
  1133         m_assembler.nop();
       
  1134         m_fixedWidth = false;
       
  1135     }
       
  1136 
       
  1137     // Arithmetic control flow operations:
       
  1138     //
       
  1139     // This set of conditional branch operations branch based
       
  1140     // on the result of an arithmetic operation.  The operation
       
  1141     // is performed as normal, storing the result.
       
  1142     //
       
  1143     // * jz operations branch if the result is zero.
       
  1144     // * jo operations branch if the (signed) arithmetic
       
  1145     //   operation caused an overflow to occur.
       
  1146 
       
  1147     Jump branchAdd32(Condition cond, RegisterID src, RegisterID dest)
       
  1148     {
       
  1149         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
       
  1150         if (cond == Overflow) {
       
  1151             /*
       
  1152                 move    dest, dataTemp
       
  1153                 xor     cmpTemp, dataTemp, src
       
  1154                 bltz    cmpTemp, No_overflow    # diff sign bit -> no overflow
       
  1155                 addu    dest, dataTemp, src
       
  1156                 xor     cmpTemp, dest, dataTemp
       
  1157                 bgez    cmpTemp, No_overflow    # same sign big -> no overflow
       
  1158                 nop
       
  1159                 b       Overflow
       
  1160                 nop
       
  1161                 nop
       
  1162                 nop
       
  1163                 nop
       
  1164                 nop
       
  1165             No_overflow:
       
  1166             */
       
  1167             move(dest, dataTempRegister);
       
  1168             m_assembler.xorInsn(cmpTempRegister, dataTempRegister, src);
       
  1169             m_assembler.bltz(cmpTempRegister, 10);
       
  1170             m_assembler.addu(dest, dataTempRegister, src);
       
  1171             m_assembler.xorInsn(cmpTempRegister, dest, dataTempRegister);
       
  1172             m_assembler.bgez(cmpTempRegister, 7);
       
  1173             m_assembler.nop();
       
  1174             return jump();
       
  1175         }
       
  1176         if (cond == Signed) {
       
  1177             add32(src, dest);
       
  1178             // Check if dest is negative.
       
  1179             m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
       
  1180             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
       
  1181         }
       
  1182         if (cond == Zero) {
       
  1183             add32(src, dest);
       
  1184             return branchEqual(dest, MIPSRegisters::zero);
       
  1185         }
       
  1186         if (cond == NonZero) {
       
  1187             add32(src, dest);
       
  1188             return branchNotEqual(dest, MIPSRegisters::zero);
       
  1189         }
       
  1190         ASSERT(0);
       
  1191         return Jump();
       
  1192     }
       
  1193 
       
  1194     Jump branchAdd32(Condition cond, Imm32 imm, RegisterID dest)
       
  1195     {
       
  1196         move(imm, immTempRegister);
       
  1197         return branchAdd32(cond, immTempRegister, dest);
       
  1198     }
       
  1199 
       
  1200     Jump branchMul32(Condition cond, RegisterID src, RegisterID dest)
       
  1201     {
       
  1202         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
       
  1203         if (cond == Overflow) {
       
  1204             /*
       
  1205                 mult    src, dest
       
  1206                 mfhi    dataTemp
       
  1207                 mflo    dest
       
  1208                 sra     addrTemp, dest, 31
       
  1209                 beq     dataTemp, addrTemp, No_overflow # all sign bits (bit 63 to bit 31) are the same -> no overflow
       
  1210                 nop
       
  1211                 b       Overflow
       
  1212                 nop
       
  1213                 nop
       
  1214                 nop
       
  1215                 nop
       
  1216                 nop
       
  1217             No_overflow:
       
  1218             */
       
  1219             m_assembler.mult(src, dest);
       
  1220             m_assembler.mfhi(dataTempRegister);
       
  1221             m_assembler.mflo(dest);
       
  1222             m_assembler.sra(addrTempRegister, dest, 31);
       
  1223             m_assembler.beq(dataTempRegister, addrTempRegister, 7);
       
  1224             m_assembler.nop();
       
  1225             return jump();
       
  1226         }
       
  1227         if (cond == Signed) {
       
  1228             mul32(src, dest);
       
  1229             // Check if dest is negative.
       
  1230             m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
       
  1231             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
       
  1232         }
       
  1233         if (cond == Zero) {
       
  1234             mul32(src, dest);
       
  1235             return branchEqual(dest, MIPSRegisters::zero);
       
  1236         }
       
  1237         if (cond == NonZero) {
       
  1238             mul32(src, dest);
       
  1239             return branchNotEqual(dest, MIPSRegisters::zero);
       
  1240         }
       
  1241         ASSERT(0);
       
  1242         return Jump();
       
  1243     }
       
  1244 
       
  1245     Jump branchMul32(Condition cond, Imm32 imm, RegisterID src, RegisterID dest)
       
  1246     {
       
  1247         move(imm, immTempRegister);
       
  1248         move(src, dest);
       
  1249         return branchMul32(cond, immTempRegister, dest);
       
  1250     }
       
  1251 
       
  1252     Jump branchSub32(Condition cond, RegisterID src, RegisterID dest)
       
  1253     {
       
  1254         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
       
  1255         if (cond == Overflow) {
       
  1256             /*
       
  1257                 move    dest, dataTemp
       
  1258                 xor     cmpTemp, dataTemp, src
       
  1259                 bgez    cmpTemp, No_overflow    # same sign bit -> no overflow
       
  1260                 subu    dest, dataTemp, src
       
  1261                 xor     cmpTemp, dest, dataTemp
       
  1262                 bgez    cmpTemp, No_overflow    # same sign bit -> no overflow
       
  1263                 nop
       
  1264                 b       Overflow
       
  1265                 nop
       
  1266                 nop
       
  1267                 nop
       
  1268                 nop
       
  1269                 nop
       
  1270             No_overflow:
       
  1271             */
       
  1272             move(dest, dataTempRegister);
       
  1273             m_assembler.xorInsn(cmpTempRegister, dataTempRegister, src);
       
  1274             m_assembler.bgez(cmpTempRegister, 10);
       
  1275             m_assembler.subu(dest, dataTempRegister, src);
       
  1276             m_assembler.xorInsn(cmpTempRegister, dest, dataTempRegister);
       
  1277             m_assembler.bgez(cmpTempRegister, 7);
       
  1278             m_assembler.nop();
       
  1279             return jump();
       
  1280         }
       
  1281         if (cond == Signed) {
       
  1282             sub32(src, dest);
       
  1283             // Check if dest is negative.
       
  1284             m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
       
  1285             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
       
  1286         }
       
  1287         if (cond == Zero) {
       
  1288             sub32(src, dest);
       
  1289             return branchEqual(dest, MIPSRegisters::zero);
       
  1290         }
       
  1291         if (cond == NonZero) {
       
  1292             sub32(src, dest);
       
  1293             return branchNotEqual(dest, MIPSRegisters::zero);
       
  1294         }
       
  1295         ASSERT(0);
       
  1296         return Jump();
       
  1297     }
       
  1298 
       
  1299     Jump branchSub32(Condition cond, Imm32 imm, RegisterID dest)
       
  1300     {
       
  1301         move(imm, immTempRegister);
       
  1302         return branchSub32(cond, immTempRegister, dest);
       
  1303     }
       
  1304 
       
  1305     // Miscellaneous operations:
       
  1306 
       
  1307     void breakpoint()
       
  1308     {
       
  1309         m_assembler.bkpt();
       
  1310     }
       
  1311 
       
  1312     Call nearCall()
       
  1313     {
       
  1314         /* We need two words for relaxation.  */
       
  1315         m_assembler.nop();
       
  1316         m_assembler.nop();
       
  1317         m_assembler.jal();
       
  1318         m_assembler.nop();
       
  1319         return Call(m_assembler.newJmpSrc(), Call::LinkableNear);
       
  1320     }
       
  1321 
       
  1322     Call call()
       
  1323     {
       
  1324         m_assembler.lui(MIPSRegisters::t9, 0);
       
  1325         m_assembler.ori(MIPSRegisters::t9, MIPSRegisters::t9, 0);
       
  1326         m_assembler.jalr(MIPSRegisters::t9);
       
  1327         m_assembler.nop();
       
  1328         return Call(m_assembler.newJmpSrc(), Call::Linkable);
       
  1329     }
       
  1330 
       
  1331     Call call(RegisterID target)
       
  1332     {
       
  1333         m_assembler.jalr(target);
       
  1334         m_assembler.nop();
       
  1335         return Call(m_assembler.newJmpSrc(), Call::None);
       
  1336     }
       
  1337 
       
  1338     Call call(Address address)
       
  1339     {
       
  1340         m_fixedWidth = true;
       
  1341         load32(address, MIPSRegisters::t9);
       
  1342         m_assembler.jalr(MIPSRegisters::t9);
       
  1343         m_assembler.nop();
       
  1344         m_fixedWidth = false;
       
  1345         return Call(m_assembler.newJmpSrc(), Call::None);
       
  1346     }
       
  1347 
       
  1348     void ret()
       
  1349     {
       
  1350         m_assembler.jr(MIPSRegisters::ra);
       
  1351         m_assembler.nop();
       
  1352     }
       
  1353 
       
  1354     void set32(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
       
  1355     {
       
  1356         if (cond == Equal || cond == Zero) {
       
  1357             m_assembler.xorInsn(dest, left, right);
       
  1358             m_assembler.sltiu(dest, dest, 1);
       
  1359         } else if (cond == NotEqual || cond == NonZero) {
       
  1360             m_assembler.xorInsn(dest, left, right);
       
  1361             m_assembler.sltu(dest, MIPSRegisters::zero, dest);
       
  1362         } else if (cond == Above)
       
  1363             m_assembler.sltu(dest, right, left);
       
  1364         else if (cond == AboveOrEqual) {
       
  1365             m_assembler.sltu(dest, left, right);
       
  1366             m_assembler.xori(dest, dest, 1);
       
  1367         } else if (cond == Below)
       
  1368             m_assembler.sltu(dest, left, right);
       
  1369         else if (cond == BelowOrEqual) {
       
  1370             m_assembler.sltu(dest, right, left);
       
  1371             m_assembler.xori(dest, dest, 1);
       
  1372         } else if (cond == GreaterThan)
       
  1373             m_assembler.slt(dest, right, left);
       
  1374         else if (cond == GreaterThanOrEqual) {
       
  1375             m_assembler.slt(dest, left, right);
       
  1376             m_assembler.xori(dest, dest, 1);
       
  1377         } else if (cond == LessThan)
       
  1378             m_assembler.slt(dest, left, right);
       
  1379         else if (cond == LessThanOrEqual) {
       
  1380             m_assembler.slt(dest, right, left);
       
  1381             m_assembler.xori(dest, dest, 1);
       
  1382         } else if (cond == Overflow) {
       
  1383             /*
       
  1384                 xor     cmpTemp, left, right
       
  1385                 bgez    Done, cmpTemp   # same sign bit -> no overflow
       
  1386                 move    dest, 0
       
  1387                 subu    cmpTemp, left, right
       
  1388                 xor     cmpTemp, cmpTemp, left # diff sign bit -> overflow
       
  1389                 slt     dest, cmpTemp, 0
       
  1390               Done:
       
  1391             */
       
  1392             m_assembler.xorInsn(cmpTempRegister, left, right);
       
  1393             m_assembler.bgez(cmpTempRegister, 4);
       
  1394             m_assembler.move(dest, MIPSRegisters::zero);
       
  1395             m_assembler.subu(cmpTempRegister, left, right);
       
  1396             m_assembler.xorInsn(cmpTempRegister, cmpTempRegister, left);
       
  1397             m_assembler.slt(dest, cmpTempRegister, MIPSRegisters::zero);
       
  1398         } else if (cond == Signed) {
       
  1399             m_assembler.subu(dest, left, right);
       
  1400             // Check if the result is negative.
       
  1401             m_assembler.slt(dest, dest, MIPSRegisters::zero);
       
  1402         }
       
  1403     }
       
  1404 
       
  1405     void set32(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
       
  1406     {
       
  1407         move(right, immTempRegister);
       
  1408         set32(cond, left, immTempRegister, dest);
       
  1409     }
       
  1410 
       
  1411     void setTest8(Condition cond, Address address, Imm32 mask, RegisterID dest)
       
  1412     {
       
  1413         ASSERT((cond == Zero) || (cond == NonZero));
       
  1414         load8(address, dataTempRegister);
       
  1415         if (mask.m_value == -1 && !m_fixedWidth) {
       
  1416             if (cond == Zero)
       
  1417                 m_assembler.sltiu(dest, dataTempRegister, 1);
       
  1418             else
       
  1419                 m_assembler.sltu(dest, MIPSRegisters::zero, dataTempRegister);
       
  1420         } else {
       
  1421             move(mask, immTempRegister);
       
  1422             m_assembler.andInsn(cmpTempRegister, dataTempRegister,
       
  1423                                 immTempRegister);
       
  1424             if (cond == Zero)
       
  1425                 m_assembler.sltiu(dest, cmpTempRegister, 1);
       
  1426             else
       
  1427                 m_assembler.sltu(dest, MIPSRegisters::zero, cmpTempRegister);
       
  1428         }
       
  1429     }
       
  1430 
       
  1431     void setTest32(Condition cond, Address address, Imm32 mask, RegisterID dest)
       
  1432     {
       
  1433         ASSERT((cond == Zero) || (cond == NonZero));
       
  1434         load32(address, dataTempRegister);
       
  1435         if (mask.m_value == -1 && !m_fixedWidth) {
       
  1436             if (cond == Zero)
       
  1437                 m_assembler.sltiu(dest, dataTempRegister, 1);
       
  1438             else
       
  1439                 m_assembler.sltu(dest, MIPSRegisters::zero, dataTempRegister);
       
  1440         } else {
       
  1441             move(mask, immTempRegister);
       
  1442             m_assembler.andInsn(cmpTempRegister, dataTempRegister,
       
  1443                                 immTempRegister);
       
  1444             if (cond == Zero)
       
  1445                 m_assembler.sltiu(dest, cmpTempRegister, 1);
       
  1446             else
       
  1447                 m_assembler.sltu(dest, MIPSRegisters::zero, cmpTempRegister);
       
  1448         }
       
  1449     }
       
  1450 
       
  1451     DataLabel32 moveWithPatch(Imm32 imm, RegisterID dest)
       
  1452     {
       
  1453         m_fixedWidth = true;
       
  1454         DataLabel32 label(this);
       
  1455         move(imm, dest);
       
  1456         m_fixedWidth = false;
       
  1457         return label;
       
  1458     }
       
  1459 
       
  1460     DataLabelPtr moveWithPatch(ImmPtr initialValue, RegisterID dest)
       
  1461     {
       
  1462         m_fixedWidth = true;
       
  1463         DataLabelPtr label(this);
       
  1464         move(initialValue, dest);
       
  1465         m_fixedWidth = false;
       
  1466         return label;
       
  1467     }
       
  1468 
       
  1469     Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
       
  1470     {
       
  1471         m_fixedWidth = true;
       
  1472         dataLabel = moveWithPatch(initialRightValue, immTempRegister);
       
  1473         Jump temp = branch32(cond, left, immTempRegister);
       
  1474         m_fixedWidth = false;
       
  1475         return temp;
       
  1476     }
       
  1477 
       
  1478     Jump branchPtrWithPatch(Condition cond, Address left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
       
  1479     {
       
  1480         m_fixedWidth = true;
       
  1481         load32(left, dataTempRegister);
       
  1482         dataLabel = moveWithPatch(initialRightValue, immTempRegister);
       
  1483         Jump temp = branch32(cond, dataTempRegister, immTempRegister);
       
  1484         m_fixedWidth = false;
       
  1485         return temp;
       
  1486     }
       
  1487 
       
  1488     DataLabelPtr storePtrWithPatch(ImmPtr initialValue, ImplicitAddress address)
       
  1489     {
       
  1490         m_fixedWidth = true;
       
  1491         DataLabelPtr dataLabel = moveWithPatch(initialValue, dataTempRegister);
       
  1492         store32(dataTempRegister, address);
       
  1493         m_fixedWidth = false;
       
  1494         return dataLabel;
       
  1495     }
       
  1496 
       
  1497     DataLabelPtr storePtrWithPatch(ImplicitAddress address)
       
  1498     {
       
  1499         return storePtrWithPatch(ImmPtr(0), address);
       
  1500     }
       
  1501 
       
  1502     Call tailRecursiveCall()
       
  1503     {
       
  1504         // Like a normal call, but don't update the returned address register
       
  1505         m_fixedWidth = true;
       
  1506         move(Imm32(0), MIPSRegisters::t9);
       
  1507         m_assembler.jr(MIPSRegisters::t9);
       
  1508         m_assembler.nop();
       
  1509         m_fixedWidth = false;
       
  1510         return Call(m_assembler.newJmpSrc(), Call::Linkable);
       
  1511     }
       
  1512 
       
  1513     Call makeTailRecursiveCall(Jump oldJump)
       
  1514     {
       
  1515         oldJump.link(this);
       
  1516         return tailRecursiveCall();
       
  1517     }
       
  1518 
       
  1519     void loadDouble(ImplicitAddress address, FPRegisterID dest)
       
  1520     {
       
  1521 #if WTF_MIPS_ISA(1)
       
  1522         /*
       
  1523             li          addrTemp, address.offset
       
  1524             addu        addrTemp, addrTemp, base
       
  1525             lwc1        dest, 0(addrTemp)
       
  1526             lwc1        dest+1, 4(addrTemp)
       
  1527          */
       
  1528         move(Imm32(address.offset), addrTempRegister);
       
  1529         m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
       
  1530         m_assembler.lwc1(dest, addrTempRegister, 0);
       
  1531         m_assembler.lwc1(FPRegisterID(dest + 1), addrTempRegister, 4);
       
  1532 #else
       
  1533         if (address.offset >= -32768 && address.offset <= 32767
       
  1534             && !m_fixedWidth) {
       
  1535             m_assembler.ldc1(dest, address.base, address.offset);
       
  1536         } else {
       
  1537             /*
       
  1538                 lui     addrTemp, (offset + 0x8000) >> 16
       
  1539                 addu    addrTemp, addrTemp, base
       
  1540                 ldc1    dest, (offset & 0xffff)(addrTemp)
       
  1541               */
       
  1542             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
       
  1543             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
       
  1544             m_assembler.ldc1(dest, addrTempRegister, address.offset);
       
  1545         }
       
  1546 #endif
       
  1547     }
       
  1548 
       
  1549     void storeDouble(FPRegisterID src, ImplicitAddress address)
       
  1550     {
       
  1551 #if WTF_MIPS_ISA(1)
       
  1552         /*
       
  1553             li          addrTemp, address.offset
       
  1554             addu        addrTemp, addrTemp, base
       
  1555             swc1        dest, 0(addrTemp)
       
  1556             swc1        dest+1, 4(addrTemp)
       
  1557          */
       
  1558         move(Imm32(address.offset), addrTempRegister);
       
  1559         m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
       
  1560         m_assembler.swc1(src, addrTempRegister, 0);
       
  1561         m_assembler.swc1(FPRegisterID(src + 1), addrTempRegister, 4);
       
  1562 #else
       
  1563         if (address.offset >= -32768 && address.offset <= 32767
       
  1564             && !m_fixedWidth)
       
  1565             m_assembler.sdc1(src, address.base, address.offset);
       
  1566         else {
       
  1567             /*
       
  1568                 lui     addrTemp, (offset + 0x8000) >> 16
       
  1569                 addu    addrTemp, addrTemp, base
       
  1570                 sdc1    src, (offset & 0xffff)(addrTemp)
       
  1571               */
       
  1572             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
       
  1573             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
       
  1574             m_assembler.sdc1(src, addrTempRegister, address.offset);
       
  1575         }
       
  1576 #endif
       
  1577     }
       
  1578 
       
  1579     void addDouble(FPRegisterID src, FPRegisterID dest)
       
  1580     {
       
  1581         m_assembler.addd(dest, dest, src);
       
  1582     }
       
  1583 
       
  1584     void addDouble(Address src, FPRegisterID dest)
       
  1585     {
       
  1586         loadDouble(src, fpTempRegister);
       
  1587         m_assembler.addd(dest, dest, fpTempRegister);
       
  1588     }
       
  1589 
       
  1590     void subDouble(FPRegisterID src, FPRegisterID dest)
       
  1591     {
       
  1592         m_assembler.subd(dest, dest, src);
       
  1593     }
       
  1594 
       
  1595     void subDouble(Address src, FPRegisterID dest)
       
  1596     {
       
  1597         loadDouble(src, fpTempRegister);
       
  1598         m_assembler.subd(dest, dest, fpTempRegister);
       
  1599     }
       
  1600 
       
  1601     void mulDouble(FPRegisterID src, FPRegisterID dest)
       
  1602     {
       
  1603         m_assembler.muld(dest, dest, src);
       
  1604     }
       
  1605 
       
  1606     void mulDouble(Address src, FPRegisterID dest)
       
  1607     {
       
  1608         loadDouble(src, fpTempRegister);
       
  1609         m_assembler.muld(dest, dest, fpTempRegister);
       
  1610     }
       
  1611 
       
  1612     void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
       
  1613     {
       
  1614         m_assembler.mtc1(src, fpTempRegister);
       
  1615         m_assembler.cvtdw(dest, fpTempRegister);
       
  1616     }
       
  1617 
       
  1618     void insertRelaxationWords()
       
  1619     {
       
  1620         /* We need four words for relaxation. */
       
  1621         m_assembler.beq(MIPSRegisters::zero, MIPSRegisters::zero, 3); // Jump over nops;
       
  1622         m_assembler.nop();
       
  1623         m_assembler.nop();
       
  1624         m_assembler.nop();
       
  1625     }
       
  1626 
       
  1627     Jump branchTrue()
       
  1628     {
       
  1629         m_assembler.appendJump();
       
  1630         m_assembler.bc1t();
       
  1631         m_assembler.nop();
       
  1632         insertRelaxationWords();
       
  1633         return Jump(m_assembler.newJmpSrc());
       
  1634     }
       
  1635 
       
  1636     Jump branchFalse()
       
  1637     {
       
  1638         m_assembler.appendJump();
       
  1639         m_assembler.bc1f();
       
  1640         m_assembler.nop();
       
  1641         insertRelaxationWords();
       
  1642         return Jump(m_assembler.newJmpSrc());
       
  1643     }
       
  1644 
       
  1645     Jump branchEqual(RegisterID rs, RegisterID rt)
       
  1646     {
       
  1647         m_assembler.appendJump();
       
  1648         m_assembler.beq(rs, rt, 0);
       
  1649         m_assembler.nop();
       
  1650         insertRelaxationWords();
       
  1651         return Jump(m_assembler.newJmpSrc());
       
  1652     }
       
  1653 
       
  1654     Jump branchNotEqual(RegisterID rs, RegisterID rt)
       
  1655     {
       
  1656         m_assembler.appendJump();
       
  1657         m_assembler.bne(rs, rt, 0);
       
  1658         m_assembler.nop();
       
  1659         insertRelaxationWords();
       
  1660         return Jump(m_assembler.newJmpSrc());
       
  1661     }
       
  1662 
       
  1663     Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
       
  1664     {
       
  1665         if (cond == DoubleEqual) {
       
  1666             m_assembler.ceqd(left, right);
       
  1667             return branchTrue();
       
  1668         }
       
  1669         if (cond == DoubleNotEqual) {
       
  1670             m_assembler.ceqd(left, right);
       
  1671             return branchFalse(); // false
       
  1672         }
       
  1673         if (cond == DoubleGreaterThan) {
       
  1674             m_assembler.cngtd(left, right);
       
  1675             return branchFalse(); // false
       
  1676         }
       
  1677         if (cond == DoubleGreaterThanOrEqual) {
       
  1678             m_assembler.cnged(left, right);
       
  1679             return branchFalse(); // false
       
  1680         }
       
  1681         if (cond == DoubleLessThan) {
       
  1682             m_assembler.cltd(left, right);
       
  1683             return branchTrue();
       
  1684         }
       
  1685         if (cond == DoubleLessThanOrEqual) {
       
  1686             m_assembler.cled(left, right);
       
  1687             return branchTrue();
       
  1688         }
       
  1689         if (cond == DoubleEqualOrUnordered) {
       
  1690             m_assembler.cueqd(left, right);
       
  1691             return branchTrue();
       
  1692         }
       
  1693         if (cond == DoubleGreaterThanOrUnordered) {
       
  1694             m_assembler.coled(left, right);
       
  1695             return branchFalse(); // false
       
  1696         }
       
  1697         if (cond == DoubleGreaterThanOrEqualOrUnordered) {
       
  1698             m_assembler.coltd(left, right);
       
  1699             return branchFalse(); // false
       
  1700         }
       
  1701         if (cond == DoubleLessThanOrUnordered) {
       
  1702             m_assembler.cultd(left, right);
       
  1703             return branchTrue();
       
  1704         }
       
  1705         if (cond == DoubleLessThanOrEqualOrUnordered) {
       
  1706             m_assembler.culed(left, right);
       
  1707             return branchTrue();
       
  1708         }
       
  1709         ASSERT(0);
       
  1710 
       
  1711         return Jump();
       
  1712     }
       
  1713 
       
  1714     // Truncates 'src' to an integer, and places the resulting 'dest'.
       
  1715     // If the result is not representable as a 32 bit value, branch.
       
  1716     // May also branch for some values that are representable in 32 bits
       
  1717     // (specifically, in this case, INT_MAX 0x7fffffff).
       
  1718     Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest)
       
  1719     {
       
  1720         m_assembler.truncwd(fpTempRegister, src);
       
  1721         m_assembler.mfc1(dest, fpTempRegister);
       
  1722         return branch32(Equal, dest, Imm32(0x7fffffff));
       
  1723     }
       
  1724 
       
  1725 private:
       
  1726     // If m_fixedWidth is true, we will generate a fixed number of instructions.
       
  1727     // Otherwise, we can emit any number of instructions.
       
  1728     bool m_fixedWidth;
       
  1729 
       
  1730     friend class LinkBuffer;
       
  1731     friend class RepatchBuffer;
       
  1732 
       
  1733     static void linkCall(void* code, Call call, FunctionPtr function)
       
  1734     {
       
  1735         MIPSAssembler::linkCall(code, call.m_jmp, function.value());
       
  1736     }
       
  1737 
       
  1738     static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)
       
  1739     {
       
  1740         MIPSAssembler::relinkCall(call.dataLocation(), destination.executableAddress());
       
  1741     }
       
  1742 
       
  1743     static void repatchCall(CodeLocationCall call, FunctionPtr destination)
       
  1744     {
       
  1745         MIPSAssembler::relinkCall(call.dataLocation(), destination.executableAddress());
       
  1746     }
       
  1747 
       
  1748 };
       
  1749 
       
  1750 }
       
  1751 
       
  1752 #endif // ENABLE(ASSEMBLER) && CPU(MIPS)
       
  1753 
       
  1754 #endif // MacroAssemblerMIPS_h