Home | History | Annotate | Download | only in assembler
      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 TrustedImm32, 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(TrustedImm32 imm, RegisterID dest)
    108     {
    109         add32(imm, dest, dest);
    110     }
    111 
    112     void add32(TrustedImm32 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(TrustedImm32 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(TrustedImm32 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(TrustedImmPtr(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(TrustedImm32 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(TrustedImm32 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(TrustedImm32 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 neg32(RegisterID srcDest)
    285     {
    286         m_assembler.subu(srcDest, MIPSRegisters::zero, srcDest);
    287     }
    288 
    289     void not32(RegisterID srcDest)
    290     {
    291         m_assembler.nor(srcDest, srcDest, MIPSRegisters::zero);
    292     }
    293 
    294     void or32(RegisterID src, RegisterID dest)
    295     {
    296         m_assembler.orInsn(dest, dest, src);
    297     }
    298 
    299     void or32(TrustedImm32 imm, RegisterID dest)
    300     {
    301         if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth)
    302             return;
    303 
    304         if (!imm.m_isPointer && imm.m_value > 0 && imm.m_value < 65535
    305             && !m_fixedWidth) {
    306             m_assembler.ori(dest, dest, imm.m_value);
    307             return;
    308         }
    309 
    310         /*
    311             li      dataTemp, imm
    312             or      dest, dest, dataTemp
    313         */
    314         move(imm, dataTempRegister);
    315         m_assembler.orInsn(dest, dest, dataTempRegister);
    316     }
    317 
    318     void rshift32(RegisterID shiftAmount, RegisterID dest)
    319     {
    320         m_assembler.srav(dest, dest, shiftAmount);
    321     }
    322 
    323     void rshift32(TrustedImm32 imm, RegisterID dest)
    324     {
    325         m_assembler.sra(dest, dest, imm.m_value);
    326     }
    327 
    328     void urshift32(RegisterID shiftAmount, RegisterID dest)
    329     {
    330         m_assembler.srlv(dest, dest, shiftAmount);
    331     }
    332 
    333     void urshift32(TrustedImm32 imm, RegisterID dest)
    334     {
    335         m_assembler.srl(dest, dest, imm.m_value);
    336     }
    337 
    338     void sub32(RegisterID src, RegisterID dest)
    339     {
    340         m_assembler.subu(dest, dest, src);
    341     }
    342 
    343     void sub32(TrustedImm32 imm, RegisterID dest)
    344     {
    345         if (!imm.m_isPointer && imm.m_value >= -32767 && imm.m_value <= 32768
    346             && !m_fixedWidth) {
    347             /*
    348               addiu     dest, src, imm
    349             */
    350             m_assembler.addiu(dest, dest, -imm.m_value);
    351         } else {
    352             /*
    353               li        immTemp, imm
    354               subu      dest, src, immTemp
    355             */
    356             move(imm, immTempRegister);
    357             m_assembler.subu(dest, dest, immTempRegister);
    358         }
    359     }
    360 
    361     void sub32(TrustedImm32 imm, Address address)
    362     {
    363         if (address.offset >= -32768 && address.offset <= 32767
    364             && !m_fixedWidth) {
    365             /*
    366               lw        dataTemp, offset(base)
    367               li        immTemp, imm
    368               subu      dataTemp, dataTemp, immTemp
    369               sw        dataTemp, offset(base)
    370             */
    371             m_assembler.lw(dataTempRegister, address.base, address.offset);
    372             if (!imm.m_isPointer
    373                 && imm.m_value >= -32767 && imm.m_value <= 32768
    374                 && !m_fixedWidth)
    375                 m_assembler.addiu(dataTempRegister, dataTempRegister,
    376                                   -imm.m_value);
    377             else {
    378                 move(imm, immTempRegister);
    379                 m_assembler.subu(dataTempRegister, dataTempRegister,
    380                                  immTempRegister);
    381             }
    382             m_assembler.sw(dataTempRegister, address.base, address.offset);
    383         } else {
    384             /*
    385               lui       addrTemp, (offset + 0x8000) >> 16
    386               addu      addrTemp, addrTemp, base
    387               lw        dataTemp, (offset & 0xffff)(addrTemp)
    388               li        immtemp, imm
    389               subu      dataTemp, dataTemp, immTemp
    390               sw        dataTemp, (offset & 0xffff)(addrTemp)
    391             */
    392             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
    393             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
    394             m_assembler.lw(dataTempRegister, addrTempRegister, address.offset);
    395 
    396             if (!imm.m_isPointer
    397                 && imm.m_value >= -32767 && imm.m_value <= 32768
    398                 && !m_fixedWidth)
    399                 m_assembler.addiu(dataTempRegister, dataTempRegister,
    400                                   -imm.m_value);
    401             else {
    402                 move(imm, immTempRegister);
    403                 m_assembler.subu(dataTempRegister, dataTempRegister,
    404                                  immTempRegister);
    405             }
    406             m_assembler.sw(dataTempRegister, addrTempRegister, address.offset);
    407         }
    408     }
    409 
    410     void sub32(Address src, RegisterID dest)
    411     {
    412         load32(src, dataTempRegister);
    413         sub32(dataTempRegister, dest);
    414     }
    415 
    416     void sub32(TrustedImm32 imm, AbsoluteAddress address)
    417     {
    418         /*
    419            li   addrTemp, address
    420            li   immTemp, imm
    421            lw   dataTemp, 0(addrTemp)
    422            subu dataTemp, dataTemp, immTemp
    423            sw   dataTemp, 0(addrTemp)
    424         */
    425         move(TrustedImmPtr(address.m_ptr), addrTempRegister);
    426         m_assembler.lw(dataTempRegister, addrTempRegister, 0);
    427 
    428         if (!imm.m_isPointer && imm.m_value >= -32767 && imm.m_value <= 32768
    429             && !m_fixedWidth) {
    430             m_assembler.addiu(dataTempRegister, dataTempRegister,
    431                               -imm.m_value);
    432         } else {
    433             move(imm, immTempRegister);
    434             m_assembler.subu(dataTempRegister, dataTempRegister, immTempRegister);
    435         }
    436         m_assembler.sw(dataTempRegister, addrTempRegister, 0);
    437     }
    438 
    439     void xor32(RegisterID src, RegisterID dest)
    440     {
    441         m_assembler.xorInsn(dest, dest, src);
    442     }
    443 
    444     void xor32(TrustedImm32 imm, RegisterID dest)
    445     {
    446         /*
    447             li  immTemp, imm
    448             xor dest, dest, immTemp
    449         */
    450         move(imm, immTempRegister);
    451         m_assembler.xorInsn(dest, dest, immTempRegister);
    452     }
    453 
    454     void sqrtDouble(FPRegisterID src, FPRegisterID dst)
    455     {
    456         m_assembler.sqrtd(dst, src);
    457     }
    458 
    459     // Memory access operations:
    460     //
    461     // Loads are of the form load(address, destination) and stores of the form
    462     // store(source, address).  The source for a store may be an TrustedImm32.  Address
    463     // operand objects to loads and store will be implicitly constructed if a
    464     // register is passed.
    465 
    466     /* Need to use zero-extened load byte for load8.  */
    467     void load8(ImplicitAddress address, RegisterID dest)
    468     {
    469         if (address.offset >= -32768 && address.offset <= 32767
    470             && !m_fixedWidth)
    471             m_assembler.lbu(dest, address.base, address.offset);
    472         else {
    473             /*
    474                 lui     addrTemp, (offset + 0x8000) >> 16
    475                 addu    addrTemp, addrTemp, base
    476                 lbu     dest, (offset & 0xffff)(addrTemp)
    477               */
    478             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
    479             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
    480             m_assembler.lbu(dest, addrTempRegister, address.offset);
    481         }
    482     }
    483 
    484     void load32(ImplicitAddress address, RegisterID dest)
    485     {
    486         if (address.offset >= -32768 && address.offset <= 32767
    487             && !m_fixedWidth)
    488             m_assembler.lw(dest, address.base, address.offset);
    489         else {
    490             /*
    491                 lui     addrTemp, (offset + 0x8000) >> 16
    492                 addu    addrTemp, addrTemp, base
    493                 lw      dest, (offset & 0xffff)(addrTemp)
    494               */
    495             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
    496             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
    497             m_assembler.lw(dest, addrTempRegister, address.offset);
    498         }
    499     }
    500 
    501     void load32(BaseIndex address, RegisterID dest)
    502     {
    503         if (address.offset >= -32768 && address.offset <= 32767
    504             && !m_fixedWidth) {
    505             /*
    506                 sll     addrTemp, address.index, address.scale
    507                 addu    addrTemp, addrTemp, address.base
    508                 lw      dest, address.offset(addrTemp)
    509             */
    510             m_assembler.sll(addrTempRegister, address.index, address.scale);
    511             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
    512             m_assembler.lw(dest, addrTempRegister, address.offset);
    513         } else {
    514             /*
    515                 sll     addrTemp, address.index, address.scale
    516                 addu    addrTemp, addrTemp, address.base
    517                 lui     immTemp, (address.offset + 0x8000) >> 16
    518                 addu    addrTemp, addrTemp, immTemp
    519                 lw      dest, (address.offset & 0xffff)(at)
    520             */
    521             m_assembler.sll(addrTempRegister, address.index, address.scale);
    522             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
    523             m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
    524             m_assembler.addu(addrTempRegister, addrTempRegister,
    525                              immTempRegister);
    526             m_assembler.lw(dest, addrTempRegister, address.offset);
    527         }
    528     }
    529 
    530     void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
    531     {
    532         if (address.offset >= -32768 && address.offset <= 32764
    533             && !m_fixedWidth) {
    534             /*
    535                 sll     addrTemp, address.index, address.scale
    536                 addu    addrTemp, addrTemp, address.base
    537                 (Big-Endian)
    538                 lwl     dest, address.offset(addrTemp)
    539                 lwr     dest, address.offset+3(addrTemp)
    540                 (Little-Endian)
    541                 lwl     dest, address.offset+3(addrTemp)
    542                 lwr     dest, address.offset(addrTemp)
    543             */
    544             m_assembler.sll(addrTempRegister, address.index, address.scale);
    545             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
    546 #if CPU(BIG_ENDIAN)
    547             m_assembler.lwl(dest, addrTempRegister, address.offset);
    548             m_assembler.lwr(dest, addrTempRegister, address.offset + 3);
    549 #else
    550             m_assembler.lwl(dest, addrTempRegister, address.offset + 3);
    551             m_assembler.lwr(dest, addrTempRegister, address.offset);
    552 
    553 #endif
    554         } else {
    555             /*
    556                 sll     addrTemp, address.index, address.scale
    557                 addu    addrTemp, addrTemp, address.base
    558                 lui     immTemp, address.offset >> 16
    559                 ori     immTemp, immTemp, address.offset & 0xffff
    560                 addu    addrTemp, addrTemp, immTemp
    561                 (Big-Endian)
    562                 lw      dest, 0(at)
    563                 lw      dest, 3(at)
    564                 (Little-Endian)
    565                 lw      dest, 3(at)
    566                 lw      dest, 0(at)
    567             */
    568             m_assembler.sll(addrTempRegister, address.index, address.scale);
    569             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
    570             m_assembler.lui(immTempRegister, address.offset >> 16);
    571             m_assembler.ori(immTempRegister, immTempRegister, address.offset);
    572             m_assembler.addu(addrTempRegister, addrTempRegister,
    573                              immTempRegister);
    574 #if CPU(BIG_ENDIAN)
    575             m_assembler.lwl(dest, addrTempRegister, 0);
    576             m_assembler.lwr(dest, addrTempRegister, 3);
    577 #else
    578             m_assembler.lwl(dest, addrTempRegister, 3);
    579             m_assembler.lwr(dest, addrTempRegister, 0);
    580 #endif
    581         }
    582     }
    583 
    584     void load32(const void* address, RegisterID dest)
    585     {
    586         /*
    587             li  addrTemp, address
    588             lw  dest, 0(addrTemp)
    589         */
    590         move(TrustedImmPtr(address), addrTempRegister);
    591         m_assembler.lw(dest, addrTempRegister, 0);
    592     }
    593 
    594     DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
    595     {
    596         m_fixedWidth = true;
    597         /*
    598             lui addrTemp, address.offset >> 16
    599             ori addrTemp, addrTemp, address.offset & 0xffff
    600             addu        addrTemp, addrTemp, address.base
    601             lw  dest, 0(addrTemp)
    602         */
    603         DataLabel32 dataLabel(this);
    604         move(TrustedImm32(address.offset), addrTempRegister);
    605         m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
    606         m_assembler.lw(dest, addrTempRegister, 0);
    607         m_fixedWidth = false;
    608         return dataLabel;
    609     }
    610 
    611     /* Need to use zero-extened load half-word for load16.  */
    612     void load16(ImplicitAddress address, RegisterID dest)
    613     {
    614         if (address.offset >= -32768 && address.offset <= 32767
    615             && !m_fixedWidth)
    616             m_assembler.lhu(dest, address.base, address.offset);
    617         else {
    618             /*
    619                 lui     addrTemp, (offset + 0x8000) >> 16
    620                 addu    addrTemp, addrTemp, base
    621                 lhu     dest, (offset & 0xffff)(addrTemp)
    622               */
    623             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
    624             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
    625             m_assembler.lhu(dest, addrTempRegister, address.offset);
    626         }
    627     }
    628 
    629     /* Need to use zero-extened load half-word for load16.  */
    630     void load16(BaseIndex address, RegisterID dest)
    631     {
    632         if (address.offset >= -32768 && address.offset <= 32767
    633             && !m_fixedWidth) {
    634             /*
    635                 sll     addrTemp, address.index, address.scale
    636                 addu    addrTemp, addrTemp, address.base
    637                 lhu     dest, address.offset(addrTemp)
    638             */
    639             m_assembler.sll(addrTempRegister, address.index, address.scale);
    640             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
    641             m_assembler.lhu(dest, addrTempRegister, address.offset);
    642         } else {
    643             /*
    644                 sll     addrTemp, address.index, address.scale
    645                 addu    addrTemp, addrTemp, address.base
    646                 lui     immTemp, (address.offset + 0x8000) >> 16
    647                 addu    addrTemp, addrTemp, immTemp
    648                 lhu     dest, (address.offset & 0xffff)(addrTemp)
    649             */
    650             m_assembler.sll(addrTempRegister, address.index, address.scale);
    651             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
    652             m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
    653             m_assembler.addu(addrTempRegister, addrTempRegister,
    654                              immTempRegister);
    655             m_assembler.lhu(dest, addrTempRegister, address.offset);
    656         }
    657     }
    658 
    659     DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
    660     {
    661         m_fixedWidth = true;
    662         /*
    663             lui addrTemp, address.offset >> 16
    664             ori addrTemp, addrTemp, address.offset & 0xffff
    665             addu        addrTemp, addrTemp, address.base
    666             sw  src, 0(addrTemp)
    667         */
    668         DataLabel32 dataLabel(this);
    669         move(TrustedImm32(address.offset), addrTempRegister);
    670         m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
    671         m_assembler.sw(src, addrTempRegister, 0);
    672         m_fixedWidth = false;
    673         return dataLabel;
    674     }
    675 
    676     void store32(RegisterID src, ImplicitAddress address)
    677     {
    678         if (address.offset >= -32768 && address.offset <= 32767
    679             && !m_fixedWidth)
    680             m_assembler.sw(src, address.base, address.offset);
    681         else {
    682             /*
    683                 lui     addrTemp, (offset + 0x8000) >> 16
    684                 addu    addrTemp, addrTemp, base
    685                 sw      src, (offset & 0xffff)(addrTemp)
    686               */
    687             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
    688             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
    689             m_assembler.sw(src, addrTempRegister, address.offset);
    690         }
    691     }
    692 
    693     void store32(RegisterID src, BaseIndex address)
    694     {
    695         if (address.offset >= -32768 && address.offset <= 32767
    696             && !m_fixedWidth) {
    697             /*
    698                 sll     addrTemp, address.index, address.scale
    699                 addu    addrTemp, addrTemp, address.base
    700                 sw      src, address.offset(addrTemp)
    701             */
    702             m_assembler.sll(addrTempRegister, address.index, address.scale);
    703             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
    704             m_assembler.sw(src, addrTempRegister, address.offset);
    705         } else {
    706             /*
    707                 sll     addrTemp, address.index, address.scale
    708                 addu    addrTemp, addrTemp, address.base
    709                 lui     immTemp, (address.offset + 0x8000) >> 16
    710                 addu    addrTemp, addrTemp, immTemp
    711                 sw      src, (address.offset & 0xffff)(at)
    712             */
    713             m_assembler.sll(addrTempRegister, address.index, address.scale);
    714             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
    715             m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
    716             m_assembler.addu(addrTempRegister, addrTempRegister,
    717                              immTempRegister);
    718             m_assembler.sw(src, addrTempRegister, address.offset);
    719         }
    720     }
    721 
    722     void store32(TrustedImm32 imm, ImplicitAddress address)
    723     {
    724         if (address.offset >= -32768 && address.offset <= 32767
    725             && !m_fixedWidth) {
    726             if (!imm.m_isPointer && !imm.m_value)
    727                 m_assembler.sw(MIPSRegisters::zero, address.base,
    728                                address.offset);
    729             else {
    730                 move(imm, immTempRegister);
    731                 m_assembler.sw(immTempRegister, address.base, address.offset);
    732             }
    733         } else {
    734             /*
    735                 lui     addrTemp, (offset + 0x8000) >> 16
    736                 addu    addrTemp, addrTemp, base
    737                 sw      immTemp, (offset & 0xffff)(addrTemp)
    738               */
    739             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
    740             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
    741             if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth)
    742                 m_assembler.sw(MIPSRegisters::zero, addrTempRegister,
    743                                address.offset);
    744             else {
    745                 move(imm, immTempRegister);
    746                 m_assembler.sw(immTempRegister, addrTempRegister,
    747                                address.offset);
    748             }
    749         }
    750     }
    751 
    752     void store32(RegisterID src, const void* address)
    753     {
    754         /*
    755             li  addrTemp, address
    756             sw  src, 0(addrTemp)
    757         */
    758         move(TrustedImmPtr(address), addrTempRegister);
    759         m_assembler.sw(src, addrTempRegister, 0);
    760     }
    761 
    762     void store32(TrustedImm32 imm, const void* address)
    763     {
    764         /*
    765             li  immTemp, imm
    766             li  addrTemp, address
    767             sw  src, 0(addrTemp)
    768         */
    769         if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) {
    770             move(TrustedImmPtr(address), addrTempRegister);
    771             m_assembler.sw(MIPSRegisters::zero, addrTempRegister, 0);
    772         } else {
    773             move(imm, immTempRegister);
    774             move(TrustedImmPtr(address), addrTempRegister);
    775             m_assembler.sw(immTempRegister, addrTempRegister, 0);
    776         }
    777     }
    778 
    779     // Floating-point operations:
    780 
    781     bool supportsFloatingPoint() const
    782     {
    783 #if WTF_MIPS_DOUBLE_FLOAT
    784         return true;
    785 #else
    786         return false;
    787 #endif
    788     }
    789 
    790     bool supportsFloatingPointTruncate() const
    791     {
    792 #if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2)
    793         return true;
    794 #else
    795         return false;
    796 #endif
    797     }
    798 
    799     bool supportsFloatingPointSqrt() const
    800     {
    801 #if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2)
    802         return true;
    803 #else
    804         return false;
    805 #endif
    806     }
    807 
    808     // Stack manipulation operations:
    809     //
    810     // The ABI is assumed to provide a stack abstraction to memory,
    811     // containing machine word sized units of data.  Push and pop
    812     // operations add and remove a single register sized unit of data
    813     // to or from the stack.  Peek and poke operations read or write
    814     // values on the stack, without moving the current stack position.
    815 
    816     void pop(RegisterID dest)
    817     {
    818         m_assembler.lw(dest, MIPSRegisters::sp, 0);
    819         m_assembler.addiu(MIPSRegisters::sp, MIPSRegisters::sp, 4);
    820     }
    821 
    822     void push(RegisterID src)
    823     {
    824         m_assembler.addiu(MIPSRegisters::sp, MIPSRegisters::sp, -4);
    825         m_assembler.sw(src, MIPSRegisters::sp, 0);
    826     }
    827 
    828     void push(Address address)
    829     {
    830         load32(address, dataTempRegister);
    831         push(dataTempRegister);
    832     }
    833 
    834     void push(TrustedImm32 imm)
    835     {
    836         move(imm, immTempRegister);
    837         push(immTempRegister);
    838     }
    839 
    840     // Register move operations:
    841     //
    842     // Move values in registers.
    843 
    844     void move(TrustedImm32 imm, RegisterID dest)
    845     {
    846         if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth)
    847             move(MIPSRegisters::zero, dest);
    848         else if (imm.m_isPointer || m_fixedWidth) {
    849             m_assembler.lui(dest, imm.m_value >> 16);
    850             m_assembler.ori(dest, dest, imm.m_value);
    851         } else
    852             m_assembler.li(dest, imm.m_value);
    853     }
    854 
    855     void move(RegisterID src, RegisterID dest)
    856     {
    857         if (src != dest || m_fixedWidth)
    858             m_assembler.move(dest, src);
    859     }
    860 
    861     void move(TrustedImmPtr imm, RegisterID dest)
    862     {
    863         move(TrustedImm32(imm), dest);
    864     }
    865 
    866     void swap(RegisterID reg1, RegisterID reg2)
    867     {
    868         move(reg1, immTempRegister);
    869         move(reg2, reg1);
    870         move(immTempRegister, reg2);
    871     }
    872 
    873     void signExtend32ToPtr(RegisterID src, RegisterID dest)
    874     {
    875         if (src != dest || m_fixedWidth)
    876             move(src, dest);
    877     }
    878 
    879     void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
    880     {
    881         if (src != dest || m_fixedWidth)
    882             move(src, dest);
    883     }
    884 
    885     // Forwards / external control flow operations:
    886     //
    887     // This set of jump and conditional branch operations return a Jump
    888     // object which may linked at a later point, allow forwards jump,
    889     // or jumps that will require external linkage (after the code has been
    890     // relocated).
    891     //
    892     // For branches, signed <, >, <= and >= are denoted as l, g, le, and ge
    893     // respecitvely, for unsigned comparisons the names b, a, be, and ae are
    894     // used (representing the names 'below' and 'above').
    895     //
    896     // Operands to the comparision are provided in the expected order, e.g.
    897     // jle32(reg1, TrustedImm32(5)) will branch if the value held in reg1, when
    898     // treated as a signed 32bit value, is less than or equal to 5.
    899     //
    900     // jz and jnz test whether the first operand is equal to zero, and take
    901     // an optional second operand of a mask under which to perform the test.
    902 
    903     Jump branch8(Condition cond, Address left, TrustedImm32 right)
    904     {
    905         // Make sure the immediate value is unsigned 8 bits.
    906         ASSERT(!(right.m_value & 0xFFFFFF00));
    907         load8(left, dataTempRegister);
    908         move(right, immTempRegister);
    909         return branch32(cond, dataTempRegister, immTempRegister);
    910     }
    911 
    912     Jump branch32(Condition cond, RegisterID left, RegisterID right)
    913     {
    914         if (cond == Equal || cond == Zero)
    915             return branchEqual(left, right);
    916         if (cond == NotEqual || cond == NonZero)
    917             return branchNotEqual(left, right);
    918         if (cond == Above) {
    919             m_assembler.sltu(cmpTempRegister, right, left);
    920             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
    921         }
    922         if (cond == AboveOrEqual) {
    923             m_assembler.sltu(cmpTempRegister, left, right);
    924             return branchEqual(cmpTempRegister, MIPSRegisters::zero);
    925         }
    926         if (cond == Below) {
    927             m_assembler.sltu(cmpTempRegister, left, right);
    928             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
    929         }
    930         if (cond == BelowOrEqual) {
    931             m_assembler.sltu(cmpTempRegister, right, left);
    932             return branchEqual(cmpTempRegister, MIPSRegisters::zero);
    933         }
    934         if (cond == GreaterThan) {
    935             m_assembler.slt(cmpTempRegister, right, left);
    936             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
    937         }
    938         if (cond == GreaterThanOrEqual) {
    939             m_assembler.slt(cmpTempRegister, left, right);
    940             return branchEqual(cmpTempRegister, MIPSRegisters::zero);
    941         }
    942         if (cond == LessThan) {
    943             m_assembler.slt(cmpTempRegister, left, right);
    944             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
    945         }
    946         if (cond == LessThanOrEqual) {
    947             m_assembler.slt(cmpTempRegister, right, left);
    948             return branchEqual(cmpTempRegister, MIPSRegisters::zero);
    949         }
    950         if (cond == Overflow) {
    951             /*
    952                 xor     cmpTemp, left, right
    953                 bgez    No_overflow, cmpTemp    # same sign bit -> no overflow
    954                 nop
    955                 subu    cmpTemp, left, right
    956                 xor     cmpTemp, cmpTemp, left
    957                 bgez    No_overflow, cmpTemp    # same sign bit -> no overflow
    958                 nop
    959                 b       Overflow
    960                 nop
    961                 nop
    962                 nop
    963                 nop
    964                 nop
    965               No_overflow:
    966             */
    967             m_assembler.xorInsn(cmpTempRegister, left, right);
    968             m_assembler.bgez(cmpTempRegister, 11);
    969             m_assembler.nop();
    970             m_assembler.subu(cmpTempRegister, left, right);
    971             m_assembler.xorInsn(cmpTempRegister, cmpTempRegister, left);
    972             m_assembler.bgez(cmpTempRegister, 7);
    973             m_assembler.nop();
    974             return jump();
    975         }
    976         if (cond == Signed) {
    977             m_assembler.subu(cmpTempRegister, left, right);
    978             // Check if the result is negative.
    979             m_assembler.slt(cmpTempRegister, cmpTempRegister,
    980                             MIPSRegisters::zero);
    981             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
    982         }
    983         ASSERT(0);
    984 
    985         return Jump();
    986     }
    987 
    988     Jump branch32(Condition cond, RegisterID left, TrustedImm32 right)
    989     {
    990         move(right, immTempRegister);
    991         return branch32(cond, left, immTempRegister);
    992     }
    993 
    994     Jump branch32(Condition cond, RegisterID left, Address right)
    995     {
    996         load32(right, dataTempRegister);
    997         return branch32(cond, left, dataTempRegister);
    998     }
    999 
   1000     Jump branch32(Condition cond, Address left, RegisterID right)
   1001     {
   1002         load32(left, dataTempRegister);
   1003         return branch32(cond, dataTempRegister, right);
   1004     }
   1005 
   1006     Jump branch32(Condition cond, Address left, TrustedImm32 right)
   1007     {
   1008         load32(left, dataTempRegister);
   1009         move(right, immTempRegister);
   1010         return branch32(cond, dataTempRegister, immTempRegister);
   1011     }
   1012 
   1013     Jump branch32(Condition cond, BaseIndex left, TrustedImm32 right)
   1014     {
   1015         load32(left, dataTempRegister);
   1016         // Be careful that the previous load32() uses immTempRegister.
   1017         // So, we need to put move() after load32().
   1018         move(right, immTempRegister);
   1019         return branch32(cond, dataTempRegister, immTempRegister);
   1020     }
   1021 
   1022     Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, TrustedImm32 right)
   1023     {
   1024         load32WithUnalignedHalfWords(left, dataTempRegister);
   1025         // Be careful that the previous load32WithUnalignedHalfWords()
   1026         // uses immTempRegister.
   1027         // So, we need to put move() after load32WithUnalignedHalfWords().
   1028         move(right, immTempRegister);
   1029         return branch32(cond, dataTempRegister, immTempRegister);
   1030     }
   1031 
   1032     Jump branch32(Condition cond, AbsoluteAddress left, RegisterID right)
   1033     {
   1034         load32(left.m_ptr, dataTempRegister);
   1035         return branch32(cond, dataTempRegister, right);
   1036     }
   1037 
   1038     Jump branch32(Condition cond, AbsoluteAddress left, TrustedImm32 right)
   1039     {
   1040         load32(left.m_ptr, dataTempRegister);
   1041         move(right, immTempRegister);
   1042         return branch32(cond, dataTempRegister, immTempRegister);
   1043     }
   1044 
   1045     Jump branch16(Condition cond, BaseIndex left, RegisterID right)
   1046     {
   1047         load16(left, dataTempRegister);
   1048         return branch32(cond, dataTempRegister, right);
   1049     }
   1050 
   1051     Jump branch16(Condition cond, BaseIndex left, TrustedImm32 right)
   1052     {
   1053         ASSERT(!(right.m_value & 0xFFFF0000));
   1054         load16(left, dataTempRegister);
   1055         // Be careful that the previous load16() uses immTempRegister.
   1056         // So, we need to put move() after load16().
   1057         move(right, immTempRegister);
   1058         return branch32(cond, dataTempRegister, immTempRegister);
   1059     }
   1060 
   1061     Jump branchTest32(Condition cond, RegisterID reg, RegisterID mask)
   1062     {
   1063         ASSERT((cond == Zero) || (cond == NonZero));
   1064         m_assembler.andInsn(cmpTempRegister, reg, mask);
   1065         if (cond == Zero)
   1066             return branchEqual(cmpTempRegister, MIPSRegisters::zero);
   1067         return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
   1068     }
   1069 
   1070     Jump branchTest32(Condition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
   1071     {
   1072         ASSERT((cond == Zero) || (cond == NonZero));
   1073         if (mask.m_value == -1 && !m_fixedWidth) {
   1074             if (cond == Zero)
   1075                 return branchEqual(reg, MIPSRegisters::zero);
   1076             return branchNotEqual(reg, MIPSRegisters::zero);
   1077         }
   1078         move(mask, immTempRegister);
   1079         return branchTest32(cond, reg, immTempRegister);
   1080     }
   1081 
   1082     Jump branchTest32(Condition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
   1083     {
   1084         load32(address, dataTempRegister);
   1085         return branchTest32(cond, dataTempRegister, mask);
   1086     }
   1087 
   1088     Jump branchTest32(Condition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
   1089     {
   1090         load32(address, dataTempRegister);
   1091         return branchTest32(cond, dataTempRegister, mask);
   1092     }
   1093 
   1094     Jump branchTest8(Condition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
   1095     {
   1096         load8(address, dataTempRegister);
   1097         return branchTest32(cond, dataTempRegister, mask);
   1098     }
   1099 
   1100     Jump jump()
   1101     {
   1102         return branchEqual(MIPSRegisters::zero, MIPSRegisters::zero);
   1103     }
   1104 
   1105     void jump(RegisterID target)
   1106     {
   1107         m_assembler.jr(target);
   1108         m_assembler.nop();
   1109     }
   1110 
   1111     void jump(Address address)
   1112     {
   1113         m_fixedWidth = true;
   1114         load32(address, MIPSRegisters::t9);
   1115         m_assembler.jr(MIPSRegisters::t9);
   1116         m_assembler.nop();
   1117         m_fixedWidth = false;
   1118     }
   1119 
   1120     // Arithmetic control flow operations:
   1121     //
   1122     // This set of conditional branch operations branch based
   1123     // on the result of an arithmetic operation.  The operation
   1124     // is performed as normal, storing the result.
   1125     //
   1126     // * jz operations branch if the result is zero.
   1127     // * jo operations branch if the (signed) arithmetic
   1128     //   operation caused an overflow to occur.
   1129 
   1130     Jump branchAdd32(Condition cond, RegisterID src, RegisterID dest)
   1131     {
   1132         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
   1133         if (cond == Overflow) {
   1134             /*
   1135                 move    dest, dataTemp
   1136                 xor     cmpTemp, dataTemp, src
   1137                 bltz    cmpTemp, No_overflow    # diff sign bit -> no overflow
   1138                 addu    dest, dataTemp, src
   1139                 xor     cmpTemp, dest, dataTemp
   1140                 bgez    cmpTemp, No_overflow    # same sign big -> no overflow
   1141                 nop
   1142                 b       Overflow
   1143                 nop
   1144                 nop
   1145                 nop
   1146                 nop
   1147                 nop
   1148             No_overflow:
   1149             */
   1150             move(dest, dataTempRegister);
   1151             m_assembler.xorInsn(cmpTempRegister, dataTempRegister, src);
   1152             m_assembler.bltz(cmpTempRegister, 10);
   1153             m_assembler.addu(dest, dataTempRegister, src);
   1154             m_assembler.xorInsn(cmpTempRegister, dest, dataTempRegister);
   1155             m_assembler.bgez(cmpTempRegister, 7);
   1156             m_assembler.nop();
   1157             return jump();
   1158         }
   1159         if (cond == Signed) {
   1160             add32(src, dest);
   1161             // Check if dest is negative.
   1162             m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
   1163             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
   1164         }
   1165         if (cond == Zero) {
   1166             add32(src, dest);
   1167             return branchEqual(dest, MIPSRegisters::zero);
   1168         }
   1169         if (cond == NonZero) {
   1170             add32(src, dest);
   1171             return branchNotEqual(dest, MIPSRegisters::zero);
   1172         }
   1173         ASSERT(0);
   1174         return Jump();
   1175     }
   1176 
   1177     Jump branchAdd32(Condition cond, TrustedImm32 imm, RegisterID dest)
   1178     {
   1179         move(imm, immTempRegister);
   1180         return branchAdd32(cond, immTempRegister, dest);
   1181     }
   1182 
   1183     Jump branchMul32(Condition cond, RegisterID src, RegisterID dest)
   1184     {
   1185         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
   1186         if (cond == Overflow) {
   1187             /*
   1188                 mult    src, dest
   1189                 mfhi    dataTemp
   1190                 mflo    dest
   1191                 sra     addrTemp, dest, 31
   1192                 beq     dataTemp, addrTemp, No_overflow # all sign bits (bit 63 to bit 31) are the same -> no overflow
   1193                 nop
   1194                 b       Overflow
   1195                 nop
   1196                 nop
   1197                 nop
   1198                 nop
   1199                 nop
   1200             No_overflow:
   1201             */
   1202             m_assembler.mult(src, dest);
   1203             m_assembler.mfhi(dataTempRegister);
   1204             m_assembler.mflo(dest);
   1205             m_assembler.sra(addrTempRegister, dest, 31);
   1206             m_assembler.beq(dataTempRegister, addrTempRegister, 7);
   1207             m_assembler.nop();
   1208             return jump();
   1209         }
   1210         if (cond == Signed) {
   1211             mul32(src, dest);
   1212             // Check if dest is negative.
   1213             m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
   1214             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
   1215         }
   1216         if (cond == Zero) {
   1217             mul32(src, dest);
   1218             return branchEqual(dest, MIPSRegisters::zero);
   1219         }
   1220         if (cond == NonZero) {
   1221             mul32(src, dest);
   1222             return branchNotEqual(dest, MIPSRegisters::zero);
   1223         }
   1224         ASSERT(0);
   1225         return Jump();
   1226     }
   1227 
   1228     Jump branchMul32(Condition cond, TrustedImm32 imm, RegisterID src, RegisterID dest)
   1229     {
   1230         move(imm, immTempRegister);
   1231         move(src, dest);
   1232         return branchMul32(cond, immTempRegister, dest);
   1233     }
   1234 
   1235     Jump branchSub32(Condition cond, RegisterID src, RegisterID dest)
   1236     {
   1237         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
   1238         if (cond == Overflow) {
   1239             /*
   1240                 move    dest, dataTemp
   1241                 xor     cmpTemp, dataTemp, src
   1242                 bgez    cmpTemp, No_overflow    # same sign bit -> no overflow
   1243                 subu    dest, dataTemp, src
   1244                 xor     cmpTemp, dest, dataTemp
   1245                 bgez    cmpTemp, No_overflow    # same sign bit -> no overflow
   1246                 nop
   1247                 b       Overflow
   1248                 nop
   1249                 nop
   1250                 nop
   1251                 nop
   1252                 nop
   1253             No_overflow:
   1254             */
   1255             move(dest, dataTempRegister);
   1256             m_assembler.xorInsn(cmpTempRegister, dataTempRegister, src);
   1257             m_assembler.bgez(cmpTempRegister, 10);
   1258             m_assembler.subu(dest, dataTempRegister, src);
   1259             m_assembler.xorInsn(cmpTempRegister, dest, dataTempRegister);
   1260             m_assembler.bgez(cmpTempRegister, 7);
   1261             m_assembler.nop();
   1262             return jump();
   1263         }
   1264         if (cond == Signed) {
   1265             sub32(src, dest);
   1266             // Check if dest is negative.
   1267             m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
   1268             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
   1269         }
   1270         if (cond == Zero) {
   1271             sub32(src, dest);
   1272             return branchEqual(dest, MIPSRegisters::zero);
   1273         }
   1274         if (cond == NonZero) {
   1275             sub32(src, dest);
   1276             return branchNotEqual(dest, MIPSRegisters::zero);
   1277         }
   1278         ASSERT(0);
   1279         return Jump();
   1280     }
   1281 
   1282     Jump branchSub32(Condition cond, TrustedImm32 imm, RegisterID dest)
   1283     {
   1284         move(imm, immTempRegister);
   1285         return branchSub32(cond, immTempRegister, dest);
   1286     }
   1287 
   1288     Jump branchOr32(Condition cond, RegisterID src, RegisterID dest)
   1289     {
   1290         ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero));
   1291         if (cond == Signed) {
   1292             or32(src, dest);
   1293             // Check if dest is negative.
   1294             m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
   1295             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
   1296         }
   1297         if (cond == Zero) {
   1298             or32(src, dest);
   1299             return branchEqual(dest, MIPSRegisters::zero);
   1300         }
   1301         if (cond == NonZero) {
   1302             or32(src, dest);
   1303             return branchNotEqual(dest, MIPSRegisters::zero);
   1304         }
   1305         ASSERT(0);
   1306         return Jump();
   1307     }
   1308 
   1309     // Miscellaneous operations:
   1310 
   1311     void breakpoint()
   1312     {
   1313         m_assembler.bkpt();
   1314     }
   1315 
   1316     Call nearCall()
   1317     {
   1318         /* We need two words for relaxation.  */
   1319         m_assembler.nop();
   1320         m_assembler.nop();
   1321         m_assembler.jal();
   1322         m_assembler.nop();
   1323         return Call(m_assembler.newJmpSrc(), Call::LinkableNear);
   1324     }
   1325 
   1326     Call call()
   1327     {
   1328         m_assembler.lui(MIPSRegisters::t9, 0);
   1329         m_assembler.ori(MIPSRegisters::t9, MIPSRegisters::t9, 0);
   1330         m_assembler.jalr(MIPSRegisters::t9);
   1331         m_assembler.nop();
   1332         return Call(m_assembler.newJmpSrc(), Call::Linkable);
   1333     }
   1334 
   1335     Call call(RegisterID target)
   1336     {
   1337         m_assembler.jalr(target);
   1338         m_assembler.nop();
   1339         return Call(m_assembler.newJmpSrc(), Call::None);
   1340     }
   1341 
   1342     Call call(Address address)
   1343     {
   1344         m_fixedWidth = true;
   1345         load32(address, MIPSRegisters::t9);
   1346         m_assembler.jalr(MIPSRegisters::t9);
   1347         m_assembler.nop();
   1348         m_fixedWidth = false;
   1349         return Call(m_assembler.newJmpSrc(), Call::None);
   1350     }
   1351 
   1352     void ret()
   1353     {
   1354         m_assembler.jr(MIPSRegisters::ra);
   1355         m_assembler.nop();
   1356     }
   1357 
   1358     void set8Compare32(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
   1359     {
   1360         set32Compare32(cond, left, right, dest);
   1361     }
   1362 
   1363     void set8Compare32(Condition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
   1364     {
   1365         move(right, immTempRegister);
   1366         set32Compare32(cond, left, immTempRegister, dest);
   1367     }
   1368 
   1369     void set32Compare32(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
   1370     {
   1371         if (cond == Equal || cond == Zero) {
   1372             m_assembler.xorInsn(dest, left, right);
   1373             m_assembler.sltiu(dest, dest, 1);
   1374         } else if (cond == NotEqual || cond == NonZero) {
   1375             m_assembler.xorInsn(dest, left, right);
   1376             m_assembler.sltu(dest, MIPSRegisters::zero, dest);
   1377         } else if (cond == Above)
   1378             m_assembler.sltu(dest, right, left);
   1379         else if (cond == AboveOrEqual) {
   1380             m_assembler.sltu(dest, left, right);
   1381             m_assembler.xori(dest, dest, 1);
   1382         } else if (cond == Below)
   1383             m_assembler.sltu(dest, left, right);
   1384         else if (cond == BelowOrEqual) {
   1385             m_assembler.sltu(dest, right, left);
   1386             m_assembler.xori(dest, dest, 1);
   1387         } else if (cond == GreaterThan)
   1388             m_assembler.slt(dest, right, left);
   1389         else if (cond == GreaterThanOrEqual) {
   1390             m_assembler.slt(dest, left, right);
   1391             m_assembler.xori(dest, dest, 1);
   1392         } else if (cond == LessThan)
   1393             m_assembler.slt(dest, left, right);
   1394         else if (cond == LessThanOrEqual) {
   1395             m_assembler.slt(dest, right, left);
   1396             m_assembler.xori(dest, dest, 1);
   1397         } else if (cond == Overflow) {
   1398             /*
   1399                 xor     cmpTemp, left, right
   1400                 bgez    Done, cmpTemp   # same sign bit -> no overflow
   1401                 move    dest, 0
   1402                 subu    cmpTemp, left, right
   1403                 xor     cmpTemp, cmpTemp, left # diff sign bit -> overflow
   1404                 slt     dest, cmpTemp, 0
   1405               Done:
   1406             */
   1407             m_assembler.xorInsn(cmpTempRegister, left, right);
   1408             m_assembler.bgez(cmpTempRegister, 4);
   1409             m_assembler.move(dest, MIPSRegisters::zero);
   1410             m_assembler.subu(cmpTempRegister, left, right);
   1411             m_assembler.xorInsn(cmpTempRegister, cmpTempRegister, left);
   1412             m_assembler.slt(dest, cmpTempRegister, MIPSRegisters::zero);
   1413         } else if (cond == Signed) {
   1414             m_assembler.subu(dest, left, right);
   1415             // Check if the result is negative.
   1416             m_assembler.slt(dest, dest, MIPSRegisters::zero);
   1417         }
   1418     }
   1419 
   1420     void set32Compare32(Condition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
   1421     {
   1422         move(right, immTempRegister);
   1423         set32Compare32(cond, left, immTempRegister, dest);
   1424     }
   1425 
   1426     void set32Test8(Condition cond, Address address, TrustedImm32 mask, RegisterID dest)
   1427     {
   1428         ASSERT((cond == Zero) || (cond == NonZero));
   1429         load8(address, dataTempRegister);
   1430         if (mask.m_value == -1 && !m_fixedWidth) {
   1431             if (cond == Zero)
   1432                 m_assembler.sltiu(dest, dataTempRegister, 1);
   1433             else
   1434                 m_assembler.sltu(dest, MIPSRegisters::zero, dataTempRegister);
   1435         } else {
   1436             move(mask, immTempRegister);
   1437             m_assembler.andInsn(cmpTempRegister, dataTempRegister,
   1438                                 immTempRegister);
   1439             if (cond == Zero)
   1440                 m_assembler.sltiu(dest, cmpTempRegister, 1);
   1441             else
   1442                 m_assembler.sltu(dest, MIPSRegisters::zero, cmpTempRegister);
   1443         }
   1444     }
   1445 
   1446     void set32Test32(Condition cond, Address address, TrustedImm32 mask, RegisterID dest)
   1447     {
   1448         ASSERT((cond == Zero) || (cond == NonZero));
   1449         load32(address, dataTempRegister);
   1450         if (mask.m_value == -1 && !m_fixedWidth) {
   1451             if (cond == Zero)
   1452                 m_assembler.sltiu(dest, dataTempRegister, 1);
   1453             else
   1454                 m_assembler.sltu(dest, MIPSRegisters::zero, dataTempRegister);
   1455         } else {
   1456             move(mask, immTempRegister);
   1457             m_assembler.andInsn(cmpTempRegister, dataTempRegister,
   1458                                 immTempRegister);
   1459             if (cond == Zero)
   1460                 m_assembler.sltiu(dest, cmpTempRegister, 1);
   1461             else
   1462                 m_assembler.sltu(dest, MIPSRegisters::zero, cmpTempRegister);
   1463         }
   1464     }
   1465 
   1466     DataLabel32 moveWithPatch(TrustedImm32 imm, RegisterID dest)
   1467     {
   1468         m_fixedWidth = true;
   1469         DataLabel32 label(this);
   1470         move(imm, dest);
   1471         m_fixedWidth = false;
   1472         return label;
   1473     }
   1474 
   1475     DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest)
   1476     {
   1477         m_fixedWidth = true;
   1478         DataLabelPtr label(this);
   1479         move(initialValue, dest);
   1480         m_fixedWidth = false;
   1481         return label;
   1482     }
   1483 
   1484     Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
   1485     {
   1486         m_fixedWidth = true;
   1487         dataLabel = moveWithPatch(initialRightValue, immTempRegister);
   1488         Jump temp = branch32(cond, left, immTempRegister);
   1489         m_fixedWidth = false;
   1490         return temp;
   1491     }
   1492 
   1493     Jump branchPtrWithPatch(Condition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
   1494     {
   1495         m_fixedWidth = true;
   1496         load32(left, dataTempRegister);
   1497         dataLabel = moveWithPatch(initialRightValue, immTempRegister);
   1498         Jump temp = branch32(cond, dataTempRegister, immTempRegister);
   1499         m_fixedWidth = false;
   1500         return temp;
   1501     }
   1502 
   1503     DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address)
   1504     {
   1505         m_fixedWidth = true;
   1506         DataLabelPtr dataLabel = moveWithPatch(initialValue, dataTempRegister);
   1507         store32(dataTempRegister, address);
   1508         m_fixedWidth = false;
   1509         return dataLabel;
   1510     }
   1511 
   1512     DataLabelPtr storePtrWithPatch(ImplicitAddress address)
   1513     {
   1514         return storePtrWithPatch(TrustedImmPtr(0), address);
   1515     }
   1516 
   1517     Call tailRecursiveCall()
   1518     {
   1519         // Like a normal call, but don't update the returned address register
   1520         m_fixedWidth = true;
   1521         move(TrustedImm32(0), MIPSRegisters::t9);
   1522         m_assembler.jr(MIPSRegisters::t9);
   1523         m_assembler.nop();
   1524         m_fixedWidth = false;
   1525         return Call(m_assembler.newJmpSrc(), Call::Linkable);
   1526     }
   1527 
   1528     Call makeTailRecursiveCall(Jump oldJump)
   1529     {
   1530         oldJump.link(this);
   1531         return tailRecursiveCall();
   1532     }
   1533 
   1534     void loadDouble(ImplicitAddress address, FPRegisterID dest)
   1535     {
   1536 #if WTF_MIPS_ISA(1)
   1537         /*
   1538             li          addrTemp, address.offset
   1539             addu        addrTemp, addrTemp, base
   1540             lwc1        dest, 0(addrTemp)
   1541             lwc1        dest+1, 4(addrTemp)
   1542          */
   1543         move(TrustedImm32(address.offset), addrTempRegister);
   1544         m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
   1545         m_assembler.lwc1(dest, addrTempRegister, 0);
   1546         m_assembler.lwc1(FPRegisterID(dest + 1), addrTempRegister, 4);
   1547 #else
   1548         if (address.offset >= -32768 && address.offset <= 32767
   1549             && !m_fixedWidth) {
   1550             m_assembler.ldc1(dest, address.base, address.offset);
   1551         } else {
   1552             /*
   1553                 lui     addrTemp, (offset + 0x8000) >> 16
   1554                 addu    addrTemp, addrTemp, base
   1555                 ldc1    dest, (offset & 0xffff)(addrTemp)
   1556               */
   1557             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
   1558             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
   1559             m_assembler.ldc1(dest, addrTempRegister, address.offset);
   1560         }
   1561 #endif
   1562     }
   1563 
   1564     void loadDouble(const void* address, FPRegisterID dest)
   1565     {
   1566 #if WTF_MIPS_ISA(1)
   1567         /*
   1568             li          addrTemp, address
   1569             lwc1        dest, 0(addrTemp)
   1570             lwc1        dest+1, 4(addrTemp)
   1571          */
   1572         move(TrustedImmPtr(address), addrTempRegister);
   1573         m_assembler.lwc1(dest, addrTempRegister, 0);
   1574         m_assembler.lwc1(FPRegisterID(dest + 1), addrTempRegister, 4);
   1575 #else
   1576         /*
   1577             li          addrTemp, address
   1578             ldc1        dest, 0(addrTemp)
   1579         */
   1580         move(TrustedImmPtr(address), addrTempRegister);
   1581         m_assembler.ldc1(dest, addrTempRegister, 0);
   1582 #endif
   1583     }
   1584 
   1585 
   1586     void storeDouble(FPRegisterID src, ImplicitAddress address)
   1587     {
   1588 #if WTF_MIPS_ISA(1)
   1589         /*
   1590             li          addrTemp, address.offset
   1591             addu        addrTemp, addrTemp, base
   1592             swc1        dest, 0(addrTemp)
   1593             swc1        dest+1, 4(addrTemp)
   1594          */
   1595         move(TrustedImm32(address.offset), addrTempRegister);
   1596         m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
   1597         m_assembler.swc1(src, addrTempRegister, 0);
   1598         m_assembler.swc1(FPRegisterID(src + 1), addrTempRegister, 4);
   1599 #else
   1600         if (address.offset >= -32768 && address.offset <= 32767
   1601             && !m_fixedWidth)
   1602             m_assembler.sdc1(src, address.base, address.offset);
   1603         else {
   1604             /*
   1605                 lui     addrTemp, (offset + 0x8000) >> 16
   1606                 addu    addrTemp, addrTemp, base
   1607                 sdc1    src, (offset & 0xffff)(addrTemp)
   1608               */
   1609             m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
   1610             m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
   1611             m_assembler.sdc1(src, addrTempRegister, address.offset);
   1612         }
   1613 #endif
   1614     }
   1615 
   1616     void addDouble(FPRegisterID src, FPRegisterID dest)
   1617     {
   1618         m_assembler.addd(dest, dest, src);
   1619     }
   1620 
   1621     void addDouble(Address src, FPRegisterID dest)
   1622     {
   1623         loadDouble(src, fpTempRegister);
   1624         m_assembler.addd(dest, dest, fpTempRegister);
   1625     }
   1626 
   1627     void subDouble(FPRegisterID src, FPRegisterID dest)
   1628     {
   1629         m_assembler.subd(dest, dest, src);
   1630     }
   1631 
   1632     void subDouble(Address src, FPRegisterID dest)
   1633     {
   1634         loadDouble(src, fpTempRegister);
   1635         m_assembler.subd(dest, dest, fpTempRegister);
   1636     }
   1637 
   1638     void mulDouble(FPRegisterID src, FPRegisterID dest)
   1639     {
   1640         m_assembler.muld(dest, dest, src);
   1641     }
   1642 
   1643     void mulDouble(Address src, FPRegisterID dest)
   1644     {
   1645         loadDouble(src, fpTempRegister);
   1646         m_assembler.muld(dest, dest, fpTempRegister);
   1647     }
   1648 
   1649     void divDouble(FPRegisterID src, FPRegisterID dest)
   1650     {
   1651         m_assembler.divd(dest, dest, src);
   1652     }
   1653 
   1654     void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
   1655     {
   1656         m_assembler.mtc1(src, fpTempRegister);
   1657         m_assembler.cvtdw(dest, fpTempRegister);
   1658     }
   1659 
   1660     void convertInt32ToDouble(Address src, FPRegisterID dest)
   1661     {
   1662         load32(src, dataTempRegister);
   1663         m_assembler.mtc1(dataTempRegister, fpTempRegister);
   1664         m_assembler.cvtdw(dest, fpTempRegister);
   1665     }
   1666 
   1667     void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest)
   1668     {
   1669         load32(src.m_ptr, dataTempRegister);
   1670         m_assembler.mtc1(dataTempRegister, fpTempRegister);
   1671         m_assembler.cvtdw(dest, fpTempRegister);
   1672     }
   1673 
   1674     void insertRelaxationWords()
   1675     {
   1676         /* We need four words for relaxation. */
   1677         m_assembler.beq(MIPSRegisters::zero, MIPSRegisters::zero, 3); // Jump over nops;
   1678         m_assembler.nop();
   1679         m_assembler.nop();
   1680         m_assembler.nop();
   1681     }
   1682 
   1683     Jump branchTrue()
   1684     {
   1685         m_assembler.appendJump();
   1686         m_assembler.bc1t();
   1687         m_assembler.nop();
   1688         insertRelaxationWords();
   1689         return Jump(m_assembler.newJmpSrc());
   1690     }
   1691 
   1692     Jump branchFalse()
   1693     {
   1694         m_assembler.appendJump();
   1695         m_assembler.bc1f();
   1696         m_assembler.nop();
   1697         insertRelaxationWords();
   1698         return Jump(m_assembler.newJmpSrc());
   1699     }
   1700 
   1701     Jump branchEqual(RegisterID rs, RegisterID rt)
   1702     {
   1703         m_assembler.appendJump();
   1704         m_assembler.beq(rs, rt, 0);
   1705         m_assembler.nop();
   1706         insertRelaxationWords();
   1707         return Jump(m_assembler.newJmpSrc());
   1708     }
   1709 
   1710     Jump branchNotEqual(RegisterID rs, RegisterID rt)
   1711     {
   1712         m_assembler.appendJump();
   1713         m_assembler.bne(rs, rt, 0);
   1714         m_assembler.nop();
   1715         insertRelaxationWords();
   1716         return Jump(m_assembler.newJmpSrc());
   1717     }
   1718 
   1719     Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
   1720     {
   1721         if (cond == DoubleEqual) {
   1722             m_assembler.ceqd(left, right);
   1723             return branchTrue();
   1724         }
   1725         if (cond == DoubleNotEqual) {
   1726             m_assembler.cueqd(left, right);
   1727             return branchFalse(); // false
   1728         }
   1729         if (cond == DoubleGreaterThan) {
   1730             m_assembler.cngtd(left, right);
   1731             return branchFalse(); // false
   1732         }
   1733         if (cond == DoubleGreaterThanOrEqual) {
   1734             m_assembler.cnged(left, right);
   1735             return branchFalse(); // false
   1736         }
   1737         if (cond == DoubleLessThan) {
   1738             m_assembler.cltd(left, right);
   1739             return branchTrue();
   1740         }
   1741         if (cond == DoubleLessThanOrEqual) {
   1742             m_assembler.cled(left, right);
   1743             return branchTrue();
   1744         }
   1745         if (cond == DoubleEqualOrUnordered) {
   1746             m_assembler.cueqd(left, right);
   1747             return branchTrue();
   1748         }
   1749         if (cond == DoubleNotEqualOrUnordered) {
   1750             m_assembler.ceqd(left, right);
   1751             return branchFalse(); // false
   1752         }
   1753         if (cond == DoubleGreaterThanOrUnordered) {
   1754             m_assembler.coled(left, right);
   1755             return branchFalse(); // false
   1756         }
   1757         if (cond == DoubleGreaterThanOrEqualOrUnordered) {
   1758             m_assembler.coltd(left, right);
   1759             return branchFalse(); // false
   1760         }
   1761         if (cond == DoubleLessThanOrUnordered) {
   1762             m_assembler.cultd(left, right);
   1763             return branchTrue();
   1764         }
   1765         if (cond == DoubleLessThanOrEqualOrUnordered) {
   1766             m_assembler.culed(left, right);
   1767             return branchTrue();
   1768         }
   1769         ASSERT(0);
   1770 
   1771         return Jump();
   1772     }
   1773 
   1774     // Truncates 'src' to an integer, and places the resulting 'dest'.
   1775     // If the result is not representable as a 32 bit value, branch.
   1776     // May also branch for some values that are representable in 32 bits
   1777     // (specifically, in this case, INT_MAX 0x7fffffff).
   1778     Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest)
   1779     {
   1780         m_assembler.truncwd(fpTempRegister, src);
   1781         m_assembler.mfc1(dest, fpTempRegister);
   1782         return branch32(Equal, dest, TrustedImm32(0x7fffffff));
   1783     }
   1784 
   1785     // Convert 'src' to an integer, and places the resulting 'dest'.
   1786     // If the result is not representable as a 32 bit value, branch.
   1787     // May also branch for some values that are representable in 32 bits
   1788     // (specifically, in this case, 0).
   1789     void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp)
   1790     {
   1791         m_assembler.cvtwd(fpTempRegister, src);
   1792         m_assembler.mfc1(dest, fpTempRegister);
   1793 
   1794         // If the result is zero, it might have been -0.0, and the double comparison won't catch this!
   1795         failureCases.append(branch32(Equal, dest, MIPSRegisters::zero));
   1796 
   1797         // Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump.
   1798         convertInt32ToDouble(dest, fpTemp);
   1799         failureCases.append(branchDouble(DoubleNotEqualOrUnordered, fpTemp, src));
   1800     }
   1801 
   1802     Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID scratch)
   1803     {
   1804 #if WTF_MIPS_ISA_REV(2) && WTF_MIPS_FP64
   1805         m_assembler.mtc1(MIPSRegisters::zero, scratch);
   1806         m_assembler.mthc1(MIPSRegisters::zero, scratch);
   1807 #else
   1808         m_assembler.mtc1(MIPSRegisters::zero, scratch);
   1809         m_assembler.mtc1(MIPSRegisters::zero, FPRegisterID(scratch + 1));
   1810 #endif
   1811         return branchDouble(DoubleNotEqual, reg, scratch);
   1812     }
   1813 
   1814     Jump branchDoubleZeroOrNaN(FPRegisterID reg, FPRegisterID scratch)
   1815     {
   1816 #if WTF_MIPS_ISA_REV(2) && WTF_MIPS_FP64
   1817         m_assembler.mtc1(MIPSRegisters::zero, scratch);
   1818         m_assembler.mthc1(MIPSRegisters::zero, scratch);
   1819 #else
   1820         m_assembler.mtc1(MIPSRegisters::zero, scratch);
   1821         m_assembler.mtc1(MIPSRegisters::zero, FPRegisterID(scratch + 1));
   1822 #endif
   1823         return branchDouble(DoubleEqualOrUnordered, reg, scratch);
   1824     }
   1825 
   1826 
   1827 private:
   1828     // If m_fixedWidth is true, we will generate a fixed number of instructions.
   1829     // Otherwise, we can emit any number of instructions.
   1830     bool m_fixedWidth;
   1831 
   1832     friend class LinkBuffer;
   1833     friend class RepatchBuffer;
   1834 
   1835     static void linkCall(void* code, Call call, FunctionPtr function)
   1836     {
   1837         MIPSAssembler::linkCall(code, call.m_jmp, function.value());
   1838     }
   1839 
   1840     static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)
   1841     {
   1842         MIPSAssembler::relinkCall(call.dataLocation(), destination.executableAddress());
   1843     }
   1844 
   1845     static void repatchCall(CodeLocationCall call, FunctionPtr destination)
   1846     {
   1847         MIPSAssembler::relinkCall(call.dataLocation(), destination.executableAddress());
   1848     }
   1849 
   1850 };
   1851 
   1852 }
   1853 
   1854 #endif // ENABLE(ASSEMBLER) && CPU(MIPS)
   1855 
   1856 #endif // MacroAssemblerMIPS_h
   1857