Home | History | Annotate | Download | only in assembler
      1 /*
      2  * Copyright (C) 2009-2011 STMicroelectronics. All rights reserved.
      3  * Copyright (C) 2008 Apple 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 APPLE 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 APPLE 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 MacroAssemblerSH4_h
     28 #define MacroAssemblerSH4_h
     29 
     30 #if ENABLE(ASSEMBLER) && CPU(SH4)
     31 
     32 #include "AbstractMacroAssembler.h"
     33 #include "SH4Assembler.h"
     34 #include <wtf/Assertions.h>
     35 
     36 namespace JSC {
     37 typedef SH4Assembler::Condition Condition;
     38 
     39 class MacroAssemblerSH4 : public AbstractMacroAssembler<SH4Assembler> {
     40 public:
     41     typedef SH4Assembler::FPRegisterID FPRegisterID;
     42 
     43     static const Condition Equal;
     44     static const Condition NotEqual;
     45     static const Condition GreaterThan;
     46     static const Condition GreaterThanOrEqual;
     47     static const Condition LessThan;
     48     static const Condition LessThanOrEqual;
     49     static const Condition UGreaterThan;
     50     static const Condition UGreaterThanOrEqual;
     51     static const Condition ULessThan;
     52     static const Condition ULessThanOrEqual;
     53     static const Condition Zero;
     54     static const Condition NonZero;
     55     static const Condition Overflow;
     56     static const Condition Above;
     57     static const Condition AboveOrEqual;
     58     static const Condition Below;
     59     static const Condition BelowOrEqual;
     60     static const Condition DoubleEqual;
     61     static const Condition DoubleNotEqual;
     62     static const Condition DoubleGreaterThan;
     63     static const Condition DoubleGreaterThanOrEqual;
     64     static const Condition DoubleLessThan;
     65     static const Condition DoubleLessThanOrEqual;
     66     static const Condition DoubleEqualOrUnordered;
     67     static const Condition DoubleNotEqualOrUnordered;
     68     static const Condition DoubleGreaterThanOrUnordered;
     69     static const Condition DoubleGreaterThanOrEqualOrUnordered;
     70     static const Condition DoubleLessThanOrUnordered;
     71     static const Condition DoubleLessThanOrEqualOrUnordered;
     72     static const Condition Signed;
     73     static const Scale ScalePtr = TimesFour;
     74     static const FPRegisterID fscratch = SH4Registers::fr10;
     75     static const RegisterID stackPointerRegister = SH4Registers::sp;
     76     static const RegisterID linkRegister = SH4Registers::pr;
     77     static const RegisterID scratchReg3 = SH4Registers::r13;
     78 
     79     RegisterID claimScratch()
     80     {
     81         return m_assembler.claimScratch();
     82     }
     83 
     84     void releaseScratch(RegisterID reg)
     85     {
     86         m_assembler.releaseScratch(reg);
     87     }
     88 
     89     // Integer arithmetic operations
     90 
     91     void add32(RegisterID src, RegisterID dest)
     92     {
     93         m_assembler.addlRegReg(src, dest);
     94     }
     95 
     96     void add32(TrustedImm32 imm, RegisterID dest)
     97     {
     98         if (m_assembler.isImmediate(imm.m_value)) {
     99             m_assembler.addlImm8r(imm.m_value, dest);
    100             return;
    101         }
    102 
    103         RegisterID scr = claimScratch();
    104         m_assembler.loadConstant(imm.m_value, scr);
    105         m_assembler.addlRegReg(scr, dest);
    106         releaseScratch(scr);
    107     }
    108 
    109     void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
    110     {
    111         if (src != dest)
    112             m_assembler.movlRegReg(src, dest);
    113         add32(imm, dest);
    114     }
    115 
    116     void add32(TrustedImm32 imm, Address address)
    117     {
    118         RegisterID scr = claimScratch();
    119         load32(address, scr);
    120         add32(imm, scr);
    121         store32(scr, address);
    122         releaseScratch(scr);
    123     }
    124 
    125     void add32(Address src, RegisterID dest)
    126     {
    127         RegisterID scr = claimScratch();
    128         load32(src, scr);
    129         m_assembler.addlRegReg(scr, dest);
    130         releaseScratch(scr);
    131     }
    132 
    133     void and32(RegisterID src, RegisterID dest)
    134     {
    135         m_assembler.andlRegReg(src, dest);
    136     }
    137 
    138     void and32(TrustedImm32 imm, RegisterID dest)
    139     {
    140         if ((imm.m_value <= 255) && (imm.m_value >= 0) && (dest == SH4Registers::r0)) {
    141             m_assembler.andlImm8r(imm.m_value, dest);
    142             return;
    143         }
    144 
    145         RegisterID scr = claimScratch();
    146         m_assembler.loadConstant((imm.m_value), scr);
    147         m_assembler.andlRegReg(scr, dest);
    148         releaseScratch(scr);
    149     }
    150 
    151     void lshift32(RegisterID shiftamount, RegisterID dest)
    152     {
    153         m_assembler.shllRegReg(dest, shiftamount);
    154     }
    155 
    156     void rshift32(int imm, RegisterID dest)
    157     {
    158         RegisterID scr = claimScratch();
    159         m_assembler.loadConstant(-imm, scr);
    160         m_assembler.shaRegReg(dest, scr);
    161         releaseScratch(scr);
    162     }
    163 
    164     void lshift32(TrustedImm32 imm, RegisterID dest)
    165     {
    166         if ((imm.m_value == 1) || (imm.m_value == 2) || (imm.m_value == 8) || (imm.m_value == 16)) {
    167             m_assembler.shllImm8r(imm.m_value, dest);
    168             return;
    169         }
    170 
    171         RegisterID scr = claimScratch();
    172         m_assembler.loadConstant(imm.m_value, scr);
    173         m_assembler.shllRegReg(dest, scr);
    174         releaseScratch(scr);
    175     }
    176 
    177     void mul32(RegisterID src, RegisterID dest)
    178     {
    179         m_assembler.imullRegReg(src, dest);
    180         m_assembler.stsmacl(dest);
    181     }
    182 
    183     void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest)
    184     {
    185         RegisterID scr = claimScratch();
    186         move(imm, scr);
    187         if  (src != dest)
    188             move(src, dest);
    189         mul32(scr,  dest);
    190         releaseScratch(scr);
    191     }
    192 
    193     void not32(RegisterID src, RegisterID dest)
    194     {
    195         m_assembler.notlReg(src, dest);
    196     }
    197 
    198     void or32(RegisterID src, RegisterID dest)
    199     {
    200         m_assembler.orlRegReg(src, dest);
    201     }
    202 
    203     void or32(TrustedImm32 imm, RegisterID dest)
    204     {
    205         if ((imm.m_value <= 255) && (imm.m_value >= 0) && (dest == SH4Registers::r0)) {
    206             m_assembler.orlImm8r(imm.m_value, dest);
    207             return;
    208         }
    209 
    210         RegisterID scr = claimScratch();
    211         m_assembler.loadConstant(imm.m_value, scr);
    212         m_assembler.orlRegReg(scr, dest);
    213         releaseScratch(scr);
    214     }
    215 
    216     void rshift32(RegisterID shiftamount, RegisterID dest)
    217     {
    218         compare32(32, shiftamount, Equal);
    219         m_assembler.ensureSpace(m_assembler.maxInstructionSize + 4);
    220         m_assembler.branch(BT_OPCODE, 1);
    221         m_assembler.neg(shiftamount, shiftamount);
    222         m_assembler.shaRegReg(dest, shiftamount);
    223     }
    224 
    225     void rshift32(TrustedImm32 imm, RegisterID dest)
    226     {
    227         if (imm.m_value & 0x1f)
    228             rshift32(imm.m_value & 0x1f, dest);
    229     }
    230 
    231     void sub32(RegisterID src, RegisterID dest)
    232     {
    233         m_assembler.sublRegReg(src, dest);
    234     }
    235 
    236     void sub32(TrustedImm32 imm, AbsoluteAddress address, RegisterID scratchReg)
    237     {
    238         RegisterID result = claimScratch();
    239 
    240         m_assembler.loadConstant(reinterpret_cast<uint32_t>(address.m_ptr), scratchReg);
    241         m_assembler.movlMemReg(scratchReg, result);
    242 
    243         if (m_assembler.isImmediate(-imm.m_value))
    244             m_assembler.addlImm8r(-imm.m_value, result);
    245         else {
    246             m_assembler.loadConstant(imm.m_value, scratchReg3);
    247             m_assembler.sublRegReg(scratchReg3, result);
    248         }
    249 
    250         store32(result, scratchReg);
    251         releaseScratch(result);
    252     }
    253 
    254     void sub32(TrustedImm32 imm, AbsoluteAddress address)
    255     {
    256         RegisterID result = claimScratch();
    257         RegisterID scratchReg = claimScratch();
    258 
    259         m_assembler.loadConstant(reinterpret_cast<uint32_t>(address.m_ptr), scratchReg);
    260         m_assembler.movlMemReg(scratchReg, result);
    261 
    262         if (m_assembler.isImmediate(-imm.m_value))
    263             m_assembler.addlImm8r(-imm.m_value, result);
    264         else {
    265             m_assembler.loadConstant(imm.m_value, scratchReg3);
    266             m_assembler.sublRegReg(scratchReg3, result);
    267         }
    268 
    269         store32(result, scratchReg);
    270         releaseScratch(result);
    271         releaseScratch(scratchReg);
    272     }
    273 
    274     void add32(TrustedImm32 imm, AbsoluteAddress address, RegisterID scratchReg)
    275     {
    276         RegisterID result = claimScratch();
    277 
    278         m_assembler.loadConstant(reinterpret_cast<uint32_t>(address.m_ptr), scratchReg);
    279         m_assembler.movlMemReg(scratchReg, result);
    280 
    281         if (m_assembler.isImmediate(imm.m_value))
    282             m_assembler.addlImm8r(imm.m_value, result);
    283         else {
    284             m_assembler.loadConstant(imm.m_value, scratchReg3);
    285             m_assembler.addlRegReg(scratchReg3, result);
    286         }
    287 
    288         store32(result, scratchReg);
    289         releaseScratch(result);
    290     }
    291 
    292     void add32(TrustedImm32 imm, AbsoluteAddress address)
    293     {
    294         RegisterID result = claimScratch();
    295         RegisterID scratchReg = claimScratch();
    296 
    297         m_assembler.loadConstant(reinterpret_cast<uint32_t>(address.m_ptr), scratchReg);
    298         m_assembler.movlMemReg(scratchReg, result);
    299 
    300         if (m_assembler.isImmediate(imm.m_value))
    301             m_assembler.addlImm8r(imm.m_value, result);
    302         else {
    303             m_assembler.loadConstant(imm.m_value, scratchReg3);
    304             m_assembler.addlRegReg(scratchReg3, result);
    305         }
    306 
    307         store32(result, scratchReg);
    308         releaseScratch(result);
    309         releaseScratch(scratchReg);
    310     }
    311 
    312     void sub32(TrustedImm32 imm, RegisterID dest)
    313     {
    314         if (m_assembler.isImmediate(-imm.m_value)) {
    315             m_assembler.addlImm8r(-imm.m_value, dest);
    316             return;
    317         }
    318 
    319         RegisterID scr = claimScratch();
    320         m_assembler.loadConstant(imm.m_value, scr);
    321         m_assembler.sublRegReg(scr, dest);
    322         releaseScratch(scr);
    323     }
    324 
    325     void sub32(Address src, RegisterID dest)
    326     {
    327         RegisterID scr = claimScratch();
    328         load32(src, scr);
    329         m_assembler.sublRegReg(scr, dest);
    330         releaseScratch(scr);
    331     }
    332 
    333     void xor32(RegisterID src, RegisterID dest)
    334     {
    335         m_assembler.xorlRegReg(src, dest);
    336     }
    337 
    338     void xor32(TrustedImm32 imm, RegisterID srcDest)
    339     {
    340         if ((srcDest != SH4Registers::r0) || (imm.m_value > 255) || (imm.m_value < 0)) {
    341             RegisterID scr = claimScratch();
    342             m_assembler.loadConstant((imm.m_value), scr);
    343             m_assembler.xorlRegReg(scr, srcDest);
    344             releaseScratch(scr);
    345             return;
    346         }
    347 
    348         m_assembler.xorlImm8r(imm.m_value, srcDest);
    349     }
    350 
    351     void compare32(int imm, RegisterID dst, Condition cond)
    352     {
    353         if (((cond == Equal) || (cond == NotEqual)) && (dst == SH4Registers::r0) && m_assembler.isImmediate(imm)) {
    354             m_assembler.cmpEqImmR0(imm, dst, cond);
    355             return;
    356         }
    357 
    358         RegisterID scr = claimScratch();
    359         m_assembler.loadConstant(imm, scr);
    360         m_assembler.cmplRegReg(scr, dst, cond);
    361         releaseScratch(scr);
    362     }
    363 
    364     void compare32(int offset, RegisterID base, RegisterID left, Condition cond)
    365     {
    366         RegisterID scr = claimScratch();
    367         if (!offset) {
    368             m_assembler.movlMemReg(base, scr);
    369             m_assembler.cmplRegReg(scr, left, cond);
    370             releaseScratch(scr);
    371             return;
    372         }
    373 
    374         if ((offset < 0) || (offset >= 64)) {
    375             m_assembler.loadConstant(offset, scr);
    376             m_assembler.addlRegReg(base, scr);
    377             m_assembler.movlMemReg(scr, scr);
    378             m_assembler.cmplRegReg(scr, left, cond);
    379             releaseScratch(scr);
    380             return;
    381         }
    382 
    383         m_assembler.movlMemReg(offset >> 2, base, scr);
    384         m_assembler.cmplRegReg(scr, left, cond);
    385         releaseScratch(scr);
    386     }
    387 
    388     void testImm(int imm, int offset, RegisterID base)
    389     {
    390         RegisterID scr = claimScratch();
    391         RegisterID scr1 = claimScratch();
    392 
    393         if ((offset < 0) || (offset >= 64)) {
    394             m_assembler.loadConstant(offset, scr);
    395             m_assembler.addlRegReg(base, scr);
    396             m_assembler.movlMemReg(scr, scr);
    397         } else if (offset)
    398             m_assembler.movlMemReg(offset >> 2, base, scr);
    399         else
    400             m_assembler.movlMemReg(base, scr);
    401         if (m_assembler.isImmediate(imm))
    402             m_assembler.movImm8(imm, scr1);
    403         else
    404             m_assembler.loadConstant(imm, scr1);
    405 
    406         m_assembler.testlRegReg(scr, scr1);
    407         releaseScratch(scr);
    408         releaseScratch(scr1);
    409     }
    410 
    411     void testlImm(int imm, RegisterID dst)
    412     {
    413         if ((dst == SH4Registers::r0) && (imm <= 255) && (imm >= 0)) {
    414             m_assembler.testlImm8r(imm, dst);
    415             return;
    416         }
    417 
    418         RegisterID scr = claimScratch();
    419         m_assembler.loadConstant(imm, scr);
    420         m_assembler.testlRegReg(scr, dst);
    421         releaseScratch(scr);
    422     }
    423 
    424     void compare32(RegisterID right, int offset, RegisterID base, Condition cond)
    425     {
    426         if (!offset) {
    427             RegisterID scr = claimScratch();
    428             m_assembler.movlMemReg(base, scr);
    429             m_assembler.cmplRegReg(right, scr, cond);
    430             releaseScratch(scr);
    431             return;
    432         }
    433 
    434         if ((offset < 0) || (offset >= 64)) {
    435             RegisterID scr = claimScratch();
    436             m_assembler.loadConstant(offset, scr);
    437             m_assembler.addlRegReg(base, scr);
    438             m_assembler.movlMemReg(scr, scr);
    439             m_assembler.cmplRegReg(right, scr, cond);
    440             releaseScratch(scr);
    441             return;
    442         }
    443 
    444         RegisterID scr = claimScratch();
    445         m_assembler.movlMemReg(offset >> 2, base, scr);
    446         m_assembler.cmplRegReg(right, scr, cond);
    447         releaseScratch(scr);
    448     }
    449 
    450     void compare32(int imm, int offset, RegisterID base, Condition cond)
    451     {
    452         if (!offset) {
    453             RegisterID scr = claimScratch();
    454             RegisterID scr1 = claimScratch();
    455             m_assembler.movlMemReg(base, scr);
    456             m_assembler.loadConstant(imm, scr1);
    457             m_assembler.cmplRegReg(scr1, scr, cond);
    458             releaseScratch(scr1);
    459             releaseScratch(scr);
    460             return;
    461         }
    462 
    463         if ((offset < 0) || (offset >= 64)) {
    464             RegisterID scr = claimScratch();
    465             RegisterID scr1 = claimScratch();
    466             m_assembler.loadConstant(offset, scr);
    467             m_assembler.addlRegReg(base, scr);
    468             m_assembler.movlMemReg(scr, scr);
    469             m_assembler.loadConstant(imm, scr1);
    470             m_assembler.cmplRegReg(scr1, scr, cond);
    471             releaseScratch(scr1);
    472             releaseScratch(scr);
    473             return;
    474         }
    475 
    476         RegisterID scr = claimScratch();
    477         RegisterID scr1 = claimScratch();
    478         m_assembler.movlMemReg(offset >> 2, base, scr);
    479         m_assembler.loadConstant(imm, scr1);
    480         m_assembler.cmplRegReg(scr1, scr, cond);
    481         releaseScratch(scr1);
    482         releaseScratch(scr);
    483     }
    484 
    485     // Memory access operation
    486 
    487     void load32(ImplicitAddress address, RegisterID dest)
    488     {
    489         load32(address.base, address.offset, dest);
    490     }
    491 
    492     void load8(ImplicitAddress address, RegisterID dest)
    493     {
    494         load8(address.base, address.offset, dest);
    495     }
    496 
    497     void load32(BaseIndex address, RegisterID dest)
    498     {
    499         RegisterID scr = claimScratch();
    500         move(address.index, scr);
    501         lshift32(TrustedImm32(address.scale), scr);
    502         add32(address.base, scr);
    503         load32(scr, address.offset, dest);
    504         releaseScratch(scr);
    505     }
    506 
    507     void load32(void* address, RegisterID dest)
    508     {
    509         m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), dest);
    510         m_assembler.movlMemReg(dest, dest);
    511     }
    512 
    513     void load32(RegisterID base, int offset, RegisterID dest)
    514     {
    515         if (!offset) {
    516             m_assembler.movlMemReg(base, dest);
    517             return;
    518         }
    519 
    520         if ((offset >= 0) && (offset < 64)) {
    521             m_assembler.movlMemReg(offset >> 2, base, dest);
    522             return;
    523         }
    524 
    525         if ((dest == SH4Registers::r0) && (dest != base)) {
    526             m_assembler.loadConstant((offset), dest);
    527             m_assembler.movlR0mr(base, dest);
    528             return;
    529         }
    530 
    531         RegisterID scr;
    532         if (dest == base)
    533             scr = claimScratch();
    534         else
    535             scr = dest;
    536         m_assembler.loadConstant((offset), scr);
    537         m_assembler.addlRegReg(base, scr);
    538         m_assembler.movlMemReg(scr, dest);
    539 
    540         if (dest == base)
    541             releaseScratch(scr);
    542     }
    543 
    544     void load8(RegisterID base, int offset, RegisterID dest)
    545     {
    546         if (!offset) {
    547             m_assembler.movbMemReg(base, dest);
    548             return;
    549         }
    550 
    551         if ((offset > 0) && (offset < 64) && (dest == SH4Registers::r0)) {
    552             m_assembler.movbMemReg(offset, base, dest);
    553             return;
    554         }
    555 
    556         if (base != dest) {
    557             m_assembler.loadConstant((offset), dest);
    558             m_assembler.addlRegReg(base, dest);
    559             m_assembler.movbMemReg(dest, dest);
    560             return;
    561         }
    562 
    563         RegisterID scr = claimScratch();
    564         m_assembler.loadConstant((offset), scr);
    565         m_assembler.addlRegReg(base, scr);
    566         m_assembler.movbMemReg(scr, dest);
    567         releaseScratch(scr);
    568     }
    569 
    570     void load32(RegisterID r0, RegisterID src, RegisterID dst)
    571     {
    572         ASSERT(r0 == SH4Registers::r0);
    573         m_assembler.movlR0mr(src, dst);
    574     }
    575 
    576     void load32(RegisterID src, RegisterID dst)
    577     {
    578         m_assembler.movlMemReg(src, dst);
    579     }
    580 
    581     void load16(ImplicitAddress address, RegisterID dest)
    582     {
    583         if (!address.offset) {
    584             m_assembler.movwMemReg(address.base, dest);
    585             return;
    586         }
    587 
    588         if ((address.offset > 0) && (address.offset < 64) && (dest == SH4Registers::r0)) {
    589             m_assembler.movwMemReg(address.offset, address.base, dest);
    590             return;
    591         }
    592 
    593         if (address.base != dest) {
    594             m_assembler.loadConstant((address.offset), dest);
    595             m_assembler.addlRegReg(address.base, dest);
    596             m_assembler.movwMemReg(dest, dest);
    597             return;
    598         }
    599 
    600         RegisterID scr = claimScratch();
    601         m_assembler.loadConstant((address.offset), scr);
    602         m_assembler.addlRegReg(address.base, scr);
    603         m_assembler.movwMemReg(scr, dest);
    604         releaseScratch(scr);
    605     }
    606 
    607     void load16(RegisterID src, RegisterID dest)
    608     {
    609         m_assembler.movwMemReg(src, dest);
    610     }
    611 
    612     void load16(RegisterID r0, RegisterID src, RegisterID dest)
    613     {
    614         ASSERT(r0 == SH4Registers::r0);
    615         m_assembler.movwR0mr(src, dest);
    616     }
    617 
    618     void load16(BaseIndex address, RegisterID dest)
    619     {
    620         RegisterID scr = claimScratch();
    621 
    622         move(address.index, scr);
    623         lshift32(TrustedImm32(address.scale), scr);
    624 
    625         if (address.offset)
    626             add32(TrustedImm32(address.offset), scr);
    627         if (scr == SH4Registers::r0)
    628             m_assembler.movwR0mr(address.base, scr);
    629         else {
    630             add32(address.base, scr);
    631             load16(scr, scr);
    632         }
    633 
    634         extuw(scr, dest);
    635         releaseScratch(scr);
    636     }
    637 
    638     void store32(RegisterID src, ImplicitAddress address)
    639     {
    640         RegisterID scr = claimScratch();
    641         store32(src, address.offset, address.base, scr);
    642         releaseScratch(scr);
    643     }
    644 
    645     void store32(RegisterID src, int offset, RegisterID base, RegisterID scr)
    646     {
    647         if (!offset) {
    648             m_assembler.movlRegMem(src, base);
    649             return;
    650         }
    651 
    652         if ((offset >=0) && (offset < 64)) {
    653             m_assembler.movlRegMem(src, offset >> 2, base);
    654             return;
    655         }
    656 
    657         m_assembler.loadConstant((offset), scr);
    658         if (scr == SH4Registers::r0) {
    659             m_assembler.movlRegMemr0(src, base);
    660             return;
    661         }
    662 
    663         m_assembler.addlRegReg(base, scr);
    664         m_assembler.movlRegMem(src, scr);
    665     }
    666 
    667     void store32(RegisterID src, RegisterID offset, RegisterID base)
    668     {
    669         ASSERT(offset == SH4Registers::r0);
    670         m_assembler.movlRegMemr0(src, base);
    671     }
    672 
    673     void store32(RegisterID src, RegisterID dst)
    674     {
    675         m_assembler.movlRegMem(src, dst);
    676     }
    677 
    678     void store32(TrustedImm32 imm, ImplicitAddress address)
    679     {
    680         RegisterID scr = claimScratch();
    681         RegisterID scr1 = claimScratch();
    682         m_assembler.loadConstant((imm.m_value), scr);
    683         store32(scr, address.offset, address.base, scr1);
    684         releaseScratch(scr);
    685         releaseScratch(scr1);
    686     }
    687 
    688     void store32(RegisterID src, BaseIndex address)
    689     {
    690         RegisterID scr = claimScratch();
    691 
    692         move(address.index, scr);
    693         lshift32(TrustedImm32(address.scale), scr);
    694         add32(address.base, scr);
    695         store32(src, Address(scr, address.offset));
    696 
    697         releaseScratch(scr);
    698     }
    699 
    700     void store32(TrustedImm32 imm, void* address)
    701     {
    702         RegisterID scr = claimScratch();
    703         RegisterID scr1 = claimScratch();
    704         m_assembler.loadConstant((imm.m_value), scr);
    705         m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), scr1);
    706         m_assembler.movlMemReg(scr, scr1);
    707         releaseScratch(scr);
    708         releaseScratch(scr1);
    709     }
    710 
    711     void store32(RegisterID src, void* address)
    712     {
    713         RegisterID scr = claimScratch();
    714         m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), scr);
    715         m_assembler.movlMemReg(src, scr);
    716         releaseScratch(scr);
    717     }
    718 
    719     DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
    720     {
    721         RegisterID scr = claimScratch();
    722         DataLabel32 label(this);
    723         m_assembler.loadConstantUnReusable(address.offset, scr);
    724         m_assembler.addlRegReg(address.base, scr);
    725         m_assembler.movlMemReg(scr, dest);
    726         releaseScratch(scr);
    727         return label;
    728     }
    729 
    730     DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
    731     {
    732         RegisterID scr = claimScratch();
    733         DataLabel32 label(this);
    734         m_assembler.loadConstantUnReusable(address.offset, scr);
    735         m_assembler.addlRegReg(address.base, scr);
    736         m_assembler.movlRegMem(src, scr);
    737         releaseScratch(scr);
    738         return label;
    739     }
    740 
    741      // Floating-point operations
    742 
    743     bool supportsFloatingPoint() const { return true; }
    744     bool supportsFloatingPointTruncate() const { return true; }
    745     bool supportsFloatingPointSqrt() const { return true; }
    746 
    747     void loadDouble(ImplicitAddress address, FPRegisterID dest)
    748     {
    749         RegisterID scr = claimScratch();
    750 
    751         m_assembler.loadConstant(address.offset, scr);
    752         if (address.base == SH4Registers::r0) {
    753             m_assembler.fmovsReadr0r(scr, (FPRegisterID)(dest + 1));
    754             m_assembler.addlImm8r(4, scr);
    755             m_assembler.fmovsReadr0r(scr, dest);
    756             releaseScratch(scr);
    757             return;
    758         }
    759 
    760         m_assembler.addlRegReg(address.base, scr);
    761         m_assembler.fmovsReadrminc(scr, (FPRegisterID)(dest + 1));
    762         m_assembler.fmovsReadrm(scr, dest);
    763         releaseScratch(scr);
    764     }
    765 
    766     void loadDouble(const void* address, FPRegisterID dest)
    767     {
    768         RegisterID scr = claimScratch();
    769         m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), scr);
    770         m_assembler.fmovsReadrminc(scr, (FPRegisterID)(dest + 1));
    771         m_assembler.fmovsReadrm(scr, dest);
    772         releaseScratch(scr);
    773     }
    774 
    775     void storeDouble(FPRegisterID src, ImplicitAddress address)
    776     {
    777         RegisterID scr = claimScratch();
    778         m_assembler.loadConstant(address.offset, scr);
    779         m_assembler.addlRegReg(address.base, scr);
    780         m_assembler.fmovsWriterm((FPRegisterID)(src + 1), scr);
    781         m_assembler.addlImm8r(4, scr);
    782         m_assembler.fmovsWriterm(src, scr);
    783         releaseScratch(scr);
    784     }
    785 
    786     void addDouble(FPRegisterID src, FPRegisterID dest)
    787     {
    788         m_assembler.daddRegReg(src, dest);
    789     }
    790 
    791     void addDouble(Address address, FPRegisterID dest)
    792     {
    793         loadDouble(address, fscratch);
    794         addDouble(fscratch, dest);
    795     }
    796 
    797     void subDouble(FPRegisterID src, FPRegisterID dest)
    798     {
    799         m_assembler.dsubRegReg(src, dest);
    800     }
    801 
    802     void subDouble(Address address, FPRegisterID dest)
    803     {
    804         loadDouble(address, fscratch);
    805         subDouble(fscratch, dest);
    806     }
    807 
    808     void mulDouble(FPRegisterID src, FPRegisterID dest)
    809     {
    810         m_assembler.dmulRegReg(src, dest);
    811     }
    812 
    813     void mulDouble(Address address, FPRegisterID dest)
    814     {
    815         loadDouble(address, fscratch);
    816         mulDouble(fscratch, dest);
    817     }
    818 
    819     void divDouble(FPRegisterID src, FPRegisterID dest)
    820     {
    821         m_assembler.ddivRegReg(src, dest);
    822     }
    823 
    824     void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
    825     {
    826         m_assembler.ldsrmfpul(src);
    827         m_assembler.floatfpulDreg(dest);
    828     }
    829 
    830     void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest)
    831     {
    832         RegisterID scr = claimScratch();
    833         m_assembler.loadConstant(reinterpret_cast<uint32_t>(src.m_ptr), scr);
    834         convertInt32ToDouble(scr, dest);
    835         releaseScratch(scr);
    836     }
    837 
    838     void convertInt32ToDouble(Address src, FPRegisterID dest)
    839     {
    840         RegisterID scr = claimScratch();
    841         load32(src, scr);
    842         convertInt32ToDouble(scr, dest);
    843         releaseScratch(scr);
    844     }
    845 
    846     void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
    847     {
    848         RegisterID scr = claimScratch();
    849 
    850         move(address.index, scr);
    851         lshift32(TrustedImm32(address.scale), scr);
    852         add32(address.base, scr);
    853 
    854         if (address.offset)
    855             add32(TrustedImm32(address.offset), scr);
    856 
    857         RegisterID scr1 = claimScratch();
    858         load16(scr, scr1);
    859         add32(TrustedImm32(2), scr);
    860         load16(scr, dest);
    861         move(TrustedImm32(16), scr);
    862         m_assembler.shllRegReg(dest, scr);
    863         or32(scr1, dest);
    864 
    865         releaseScratch(scr);
    866         releaseScratch(scr1);
    867     }
    868 
    869     Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, TrustedImm32 right)
    870     {
    871         RegisterID scr = scratchReg3;
    872         load32WithUnalignedHalfWords(left, scr);
    873         if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
    874             m_assembler.testlRegReg(scr, scr);
    875         else
    876             compare32(right.m_value, scr, cond);
    877 
    878         if (cond == NotEqual)
    879             return branchFalse();
    880         return branchTrue();
    881     }
    882 
    883     Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID scratch)
    884     {
    885         m_assembler.movImm8(0, scratchReg3);
    886         convertInt32ToDouble(scratchReg3, scratch);
    887         return branchDouble(DoubleNotEqual, reg, scratch);
    888     }
    889 
    890     Jump branchDoubleZeroOrNaN(FPRegisterID reg, FPRegisterID scratch)
    891     {
    892         m_assembler.movImm8(0, scratchReg3);
    893         convertInt32ToDouble(scratchReg3, scratch);
    894         return branchDouble(DoubleEqualOrUnordered, reg, scratch);
    895     }
    896 
    897     Jump branchDouble(Condition cond, FPRegisterID left, FPRegisterID right)
    898     {
    899         if (cond == DoubleEqual) {
    900             m_assembler.dcmppeq(right, left);
    901             return branchTrue();
    902         }
    903 
    904         if (cond == DoubleNotEqual) {
    905             RegisterID scr = claimScratch();
    906             m_assembler.loadConstant(0x7fbfffff, scratchReg3);
    907             m_assembler.dcnvds(right);
    908             m_assembler.stsfpulReg(scr);
    909             m_assembler.cmplRegReg(scratchReg3, scr, Equal);
    910             m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
    911             m_assembler.branch(BT_OPCODE, 8);
    912             m_assembler.dcnvds(left);
    913             m_assembler.stsfpulReg(scr);
    914             m_assembler.cmplRegReg(scratchReg3, scr, Equal);
    915             m_assembler.branch(BT_OPCODE, 4);
    916             m_assembler.dcmppeq(right, left);
    917             releaseScratch(scr);
    918             return branchFalse();
    919         }
    920 
    921         if (cond == DoubleGreaterThan) {
    922             m_assembler.dcmppgt(right, left);
    923             return branchTrue();
    924         }
    925 
    926         if (cond == DoubleGreaterThanOrEqual) {
    927             m_assembler.dcmppgt(left, right);
    928             return branchFalse();
    929         }
    930 
    931         if (cond == DoubleLessThan) {
    932             m_assembler.dcmppgt(left, right);
    933             return branchTrue();
    934         }
    935 
    936         if (cond == DoubleLessThanOrEqual) {
    937             m_assembler.dcmppgt(right, left);
    938             return branchFalse();
    939         }
    940 
    941         if (cond == DoubleEqualOrUnordered) {
    942             RegisterID scr = claimScratch();
    943             m_assembler.loadConstant(0x7fbfffff, scratchReg3);
    944             m_assembler.dcnvds(right);
    945             m_assembler.stsfpulReg(scr);
    946             m_assembler.cmplRegReg(scratchReg3, scr, Equal);
    947             m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
    948             m_assembler.branch(BT_OPCODE, 5);
    949             m_assembler.dcnvds(left);
    950             m_assembler.stsfpulReg(scr);
    951             m_assembler.cmplRegReg(scratchReg3, scr, Equal);
    952             m_assembler.branch(BT_OPCODE, 1);
    953             m_assembler.dcmppeq(left, right);
    954             releaseScratch(scr);
    955             return branchTrue();
    956         }
    957 
    958         if (cond == DoubleGreaterThanOrUnordered) {
    959             RegisterID scr = claimScratch();
    960             m_assembler.loadConstant(0x7fbfffff, scratchReg3);
    961             m_assembler.dcnvds(right);
    962             m_assembler.stsfpulReg(scr);
    963             m_assembler.cmplRegReg(scratchReg3, scr, Equal);
    964             m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
    965             m_assembler.branch(BT_OPCODE, 5);
    966             m_assembler.dcnvds(left);
    967             m_assembler.stsfpulReg(scr);
    968             m_assembler.cmplRegReg(scratchReg3, scr, Equal);
    969             m_assembler.branch(BT_OPCODE, 1);
    970             m_assembler.dcmppgt(right, left);
    971             releaseScratch(scr);
    972             return branchTrue();
    973         }
    974 
    975         if (cond == DoubleGreaterThanOrEqualOrUnordered) {
    976             RegisterID scr = claimScratch();
    977             m_assembler.loadConstant(0x7fbfffff, scratchReg3);
    978             m_assembler.dcnvds(right);
    979             m_assembler.stsfpulReg(scr);
    980             m_assembler.cmplRegReg(scratchReg3, scr, Equal);
    981             m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
    982             m_assembler.branch(BT_OPCODE, 5);
    983             m_assembler.dcnvds(left);
    984             m_assembler.stsfpulReg(scr);
    985             m_assembler.cmplRegReg(scratchReg3, scr, Equal);
    986             m_assembler.branch(BT_OPCODE, 1);
    987             m_assembler.dcmppgt(left, right);
    988             releaseScratch(scr);
    989             return branchFalse();
    990         }
    991 
    992         if (cond == DoubleLessThanOrUnordered) {
    993             RegisterID scr = claimScratch();
    994             m_assembler.loadConstant(0x7fbfffff, scratchReg3);
    995             m_assembler.dcnvds(right);
    996             m_assembler.stsfpulReg(scr);
    997             m_assembler.cmplRegReg(scratchReg3, scr, Equal);
    998             m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
    999             m_assembler.branch(BT_OPCODE, 5);
   1000             m_assembler.dcnvds(left);
   1001             m_assembler.stsfpulReg(scr);
   1002             m_assembler.cmplRegReg(scratchReg3, scr, Equal);
   1003             m_assembler.branch(BT_OPCODE, 1);
   1004             m_assembler.dcmppgt(left, right);
   1005             releaseScratch(scr);
   1006             return branchTrue();
   1007         }
   1008 
   1009         if (cond == DoubleLessThanOrEqualOrUnordered) {
   1010             RegisterID scr = claimScratch();
   1011             m_assembler.loadConstant(0x7fbfffff, scratchReg3);
   1012             m_assembler.dcnvds(right);
   1013             m_assembler.stsfpulReg(scr);
   1014             m_assembler.cmplRegReg(scratchReg3, scr, Equal);
   1015             m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
   1016             m_assembler.branch(BT_OPCODE, 5);
   1017             m_assembler.dcnvds(left);
   1018             m_assembler.stsfpulReg(scr);
   1019             m_assembler.cmplRegReg(scratchReg3, scr, Equal);
   1020             m_assembler.branch(BT_OPCODE, 1);
   1021             m_assembler.dcmppgt(right, left);
   1022             releaseScratch(scr);
   1023             return branchFalse();
   1024         }
   1025 
   1026         ASSERT(cond == DoubleNotEqualOrUnordered);
   1027         RegisterID scr = claimScratch();
   1028         m_assembler.loadConstant(0x7fbfffff, scratchReg3);
   1029         m_assembler.dcnvds(right);
   1030         m_assembler.stsfpulReg(scr);
   1031         m_assembler.cmplRegReg(scratchReg3, scr, Equal);
   1032         m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
   1033         m_assembler.branch(BT_OPCODE, 5);
   1034         m_assembler.dcnvds(left);
   1035         m_assembler.stsfpulReg(scr);
   1036         m_assembler.cmplRegReg(scratchReg3, scr, Equal);
   1037         m_assembler.branch(BT_OPCODE, 1);
   1038         m_assembler.dcmppeq(right, left);
   1039         releaseScratch(scr);
   1040         return branchFalse();
   1041     }
   1042 
   1043     Jump branchTrue()
   1044     {
   1045         m_assembler.ensureSpace(m_assembler.maxInstructionSize + 6, sizeof(uint32_t));
   1046         Jump m_jump = Jump(m_assembler.je());
   1047         m_assembler.loadConstantUnReusable(0x0, scratchReg3);
   1048         m_assembler.nop();
   1049         m_assembler.nop();
   1050         return m_jump;
   1051     }
   1052 
   1053     Jump branchFalse()
   1054     {
   1055         m_assembler.ensureSpace(m_assembler.maxInstructionSize + 6, sizeof(uint32_t));
   1056         Jump m_jump = Jump(m_assembler.jne());
   1057         m_assembler.loadConstantUnReusable(0x0, scratchReg3);
   1058         m_assembler.nop();
   1059         m_assembler.nop();
   1060         return m_jump;
   1061     }
   1062 
   1063     void set8Compare32(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
   1064     {
   1065         set32Compare32(cond, left, right, dest);
   1066     }
   1067 
   1068     void set8Compare32(Condition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
   1069     {
   1070         if (left != dest) {
   1071             m_assembler.loadConstant(right.m_value, dest);
   1072             set32Compare32(cond, left, dest, dest);
   1073             return;
   1074         }
   1075 
   1076         RegisterID scr = claimScratch();
   1077         m_assembler.loadConstant(right.m_value, scr);
   1078         set32Compare32(cond, left, scr, dest);
   1079         releaseScratch(scr);
   1080     }
   1081 
   1082     Jump branch32(Condition cond, BaseIndex left, TrustedImm32 right)
   1083     {
   1084         RegisterID scr = claimScratch();
   1085         move(left.index, scr);
   1086         lshift32(TrustedImm32(left.scale), scr);
   1087         add32(left.base, scr);
   1088         load32(scr, left.offset, scr);
   1089         compare32(right.m_value, scr, cond);
   1090         releaseScratch(scr);
   1091 
   1092         if (cond == NotEqual)
   1093             return branchFalse();
   1094         return branchTrue();
   1095     }
   1096 
   1097     void sqrtDouble(FPRegisterID src, FPRegisterID dest)
   1098     {
   1099         if (dest != src)
   1100             m_assembler.dmovRegReg(src, dest);
   1101         m_assembler.dsqrt(dest);
   1102     }
   1103 
   1104     Jump branchTest8(Condition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
   1105     {
   1106         RegisterID addressTempRegister = claimScratch();
   1107         load8(address, addressTempRegister);
   1108         Jump jmp = branchTest32(cond, addressTempRegister, mask);
   1109         releaseScratch(addressTempRegister);
   1110         return jmp;
   1111     }
   1112 
   1113     void signExtend32ToPtr(RegisterID src, RegisterID dest)
   1114     {
   1115         if (src != dest)
   1116             move(src, dest);
   1117     }
   1118 
   1119     Jump branch8(Condition cond, Address left, TrustedImm32 right)
   1120     {
   1121         RegisterID addressTempRegister = claimScratch();
   1122         load8(left, addressTempRegister);
   1123         Jump jmp = branch32(cond, addressTempRegister, right);
   1124         releaseScratch(addressTempRegister);
   1125         return jmp;
   1126     }
   1127 
   1128     Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest)
   1129     {
   1130         m_assembler.ftrcdrmfpul(src);
   1131         m_assembler.stsfpulReg(dest);
   1132         m_assembler.loadConstant(0x7fffffff, scratchReg3);
   1133         m_assembler.cmplRegReg(dest, scratchReg3, Equal);
   1134         m_assembler.ensureSpace(m_assembler.maxInstructionSize + 14, sizeof(uint32_t));
   1135         m_assembler.branch(BT_OPCODE, 2);
   1136         m_assembler.addlImm8r(1, scratchReg3);
   1137         m_assembler.cmplRegReg(dest, scratchReg3, Equal);
   1138         return branchTrue();
   1139     }
   1140 
   1141     // Stack manipulation operations
   1142 
   1143     void pop(RegisterID dest)
   1144     {
   1145         m_assembler.popReg(dest);
   1146     }
   1147 
   1148     void push(RegisterID src)
   1149     {
   1150         m_assembler.pushReg(src);
   1151     }
   1152 
   1153     void push(Address address)
   1154     {
   1155         if (!address.offset) {
   1156             push(address.base);
   1157             return;
   1158         }
   1159 
   1160         if ((address.offset < 0) || (address.offset >= 64)) {
   1161             RegisterID scr = claimScratch();
   1162             m_assembler.loadConstant(address.offset, scr);
   1163             m_assembler.addlRegReg(address.base, scr);
   1164             m_assembler.movlMemReg(scr, SH4Registers::sp);
   1165             m_assembler.addlImm8r(-4, SH4Registers::sp);
   1166             releaseScratch(scr);
   1167             return;
   1168         }
   1169 
   1170         m_assembler.movlMemReg(address.offset >> 2, address.base, SH4Registers::sp);
   1171         m_assembler.addlImm8r(-4, SH4Registers::sp);
   1172     }
   1173 
   1174     void push(TrustedImm32 imm)
   1175     {
   1176         RegisterID scr = claimScratch();
   1177         m_assembler.loadConstant(imm.m_value, scr);
   1178         push(scr);
   1179         releaseScratch(scr);
   1180     }
   1181 
   1182     // Register move operations
   1183 
   1184     void move(TrustedImm32 imm, RegisterID dest)
   1185     {
   1186         m_assembler.loadConstant(imm.m_value, dest);
   1187     }
   1188 
   1189     DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest)
   1190     {
   1191         DataLabelPtr dataLabel(this);
   1192         m_assembler.loadConstantUnReusable(reinterpret_cast<uint32_t>(initialValue.m_value), dest, true);
   1193         return dataLabel;
   1194     }
   1195 
   1196     void move(RegisterID src, RegisterID dest)
   1197     {
   1198         m_assembler.movlRegReg(src, dest);
   1199     }
   1200 
   1201     void move(TrustedImmPtr imm, RegisterID dest)
   1202     {
   1203         m_assembler.loadConstant(imm.asIntptr(), dest);
   1204     }
   1205 
   1206     void extuw(RegisterID src, RegisterID dst)
   1207     {
   1208         m_assembler.extuw(src, dst);
   1209     }
   1210 
   1211     void set32Compare32(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
   1212     {
   1213         m_assembler.cmplRegReg(right, left, cond);
   1214         if (cond != NotEqual) {
   1215             m_assembler.movt(dest);
   1216             return;
   1217         }
   1218 
   1219         m_assembler.ensureSpace(m_assembler.maxInstructionSize + 4);
   1220         m_assembler.movImm8(0, dest);
   1221         m_assembler.branch(BT_OPCODE, 0);
   1222         m_assembler.movImm8(1, dest);
   1223     }
   1224 
   1225     void set32Compare32(Condition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
   1226     {
   1227         if (left != dest) {
   1228             move(right, dest);
   1229             set32Compare32(cond, left, dest, dest);
   1230             return;
   1231         }
   1232 
   1233         RegisterID scr = claimScratch();
   1234         move(right, scr);
   1235         set32Compare32(cond, left, scr, dest);
   1236         releaseScratch(scr);
   1237     }
   1238 
   1239     void set32Test8(Condition cond, Address address, TrustedImm32 mask, RegisterID dest)
   1240     {
   1241         ASSERT((cond == Zero) || (cond == NonZero));
   1242 
   1243         load8(address, dest);
   1244         if (mask.m_value == -1)
   1245             compare32(0, dest, cond);
   1246         else
   1247             testlImm(mask.m_value, dest);
   1248         if (cond != NonZero) {
   1249             m_assembler.movt(dest);
   1250             return;
   1251         }
   1252 
   1253         m_assembler.ensureSpace(m_assembler.maxInstructionSize + 4);
   1254         m_assembler.movImm8(0, dest);
   1255         m_assembler.branch(BT_OPCODE, 0);
   1256         m_assembler.movImm8(1, dest);
   1257     }
   1258 
   1259     void loadPtrLinkReg(ImplicitAddress address)
   1260     {
   1261         RegisterID scr = claimScratch();
   1262         load32(address, scr);
   1263         m_assembler.ldspr(scr);
   1264         releaseScratch(scr);
   1265     }
   1266 
   1267     Jump branch32(Condition cond, RegisterID left, RegisterID right)
   1268     {
   1269         m_assembler.cmplRegReg(right, left, cond);
   1270         /* BT label => BF off
   1271            nop         LDR reg
   1272            nop         braf @reg
   1273            nop         nop
   1274          */
   1275         if (cond == NotEqual)
   1276             return branchFalse();
   1277         return branchTrue();
   1278     }
   1279 
   1280     Jump branch32(Condition cond, RegisterID left, TrustedImm32 right)
   1281     {
   1282         if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
   1283             m_assembler.testlRegReg(left, left);
   1284         else
   1285             compare32(right.m_value, left, cond);
   1286 
   1287         if (cond == NotEqual)
   1288             return branchFalse();
   1289         return branchTrue();
   1290     }
   1291 
   1292     Jump branch32(Condition cond, RegisterID left, Address right)
   1293     {
   1294         compare32(right.offset, right.base, left, cond);
   1295         if (cond == NotEqual)
   1296             return branchFalse();
   1297         return branchTrue();
   1298     }
   1299 
   1300     Jump branch32(Condition cond, Address left, RegisterID right)
   1301     {
   1302         compare32(right, left.offset, left.base, cond);
   1303         if (cond == NotEqual)
   1304             return branchFalse();
   1305         return branchTrue();
   1306     }
   1307 
   1308     Jump branch32(Condition cond, Address left, TrustedImm32 right)
   1309     {
   1310         compare32(right.m_value, left.offset, left.base, cond);
   1311         if (cond == NotEqual)
   1312             return branchFalse();
   1313         return branchTrue();
   1314     }
   1315 
   1316     Jump branch32(Condition cond, AbsoluteAddress left, RegisterID right)
   1317     {
   1318         RegisterID scr = claimScratch();
   1319 
   1320         move(TrustedImm32(reinterpret_cast<uint32_t>(left.m_ptr)), scr);
   1321         m_assembler.cmplRegReg(right, scr, cond);
   1322         releaseScratch(scr);
   1323 
   1324         if (cond == NotEqual)
   1325             return branchFalse();
   1326         return branchTrue();
   1327     }
   1328 
   1329     Jump branch32(Condition cond, AbsoluteAddress left, TrustedImm32 right)
   1330     {
   1331         RegisterID addressTempRegister = claimScratch();
   1332 
   1333         m_assembler.loadConstant(reinterpret_cast<uint32_t>(left.m_ptr), addressTempRegister);
   1334         m_assembler.movlMemReg(addressTempRegister, addressTempRegister);
   1335         compare32(right.m_value, addressTempRegister, cond);
   1336         releaseScratch(addressTempRegister);
   1337 
   1338         if (cond == NotEqual)
   1339             return branchFalse();
   1340         return branchTrue();
   1341     }
   1342 
   1343     Jump branch16(Condition cond,  BaseIndex left, RegisterID right)
   1344     {
   1345         RegisterID scr = claimScratch();
   1346 
   1347         move(left.index, scr);
   1348         lshift32(TrustedImm32(left.scale), scr);
   1349 
   1350         if (left.offset)
   1351             add32(TrustedImm32(left.offset), scr);
   1352         add32(left.base, scr);
   1353         load16(scr, scr);
   1354         extuw(scr, scr);
   1355         releaseScratch(scr);
   1356 
   1357         return branch32(cond, scr, right);
   1358     }
   1359 
   1360     Jump branch16(Condition cond, BaseIndex left, TrustedImm32 right)
   1361     {
   1362         RegisterID scr = claimScratch();
   1363 
   1364         move(left.index, scr);
   1365         lshift32(TrustedImm32(left.scale), scr);
   1366 
   1367         if (left.offset)
   1368             add32(TrustedImm32(left.offset), scr);
   1369         add32(left.base, scr);
   1370         load16(scr, scr);
   1371         extuw(scr, scr);
   1372         RegisterID scr1 = claimScratch();
   1373         m_assembler.loadConstant(right.m_value, scr1);
   1374         releaseScratch(scr);
   1375         releaseScratch(scr1);
   1376 
   1377         return branch32(cond, scr, scr1);
   1378     }
   1379 
   1380     Jump branchTest32(Condition cond, RegisterID reg, RegisterID mask)
   1381     {
   1382         ASSERT((cond == Zero) || (cond == NonZero));
   1383 
   1384         m_assembler.testlRegReg(reg, mask);
   1385 
   1386         if (cond == NotEqual)
   1387             return branchFalse();
   1388         return branchTrue();
   1389     }
   1390 
   1391     Jump branchTest32(Condition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
   1392     {
   1393         ASSERT((cond == Zero) || (cond == NonZero));
   1394 
   1395         if (mask.m_value == -1)
   1396             m_assembler.testlRegReg(reg, reg);
   1397         else
   1398             testlImm(mask.m_value, reg);
   1399 
   1400         if (cond == NotEqual)
   1401             return branchFalse();
   1402         return branchTrue();
   1403     }
   1404 
   1405     Jump branchTest32(Condition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
   1406     {
   1407         ASSERT((cond == Zero) || (cond == NonZero));
   1408 
   1409         if (mask.m_value == -1)
   1410             compare32(0, address.offset, address.base, cond);
   1411         else
   1412             testImm(mask.m_value, address.offset, address.base);
   1413 
   1414         if (cond == NotEqual)
   1415             return branchFalse();
   1416         return branchTrue();
   1417     }
   1418 
   1419     Jump branchTest32(Condition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
   1420     {
   1421         RegisterID scr = claimScratch();
   1422 
   1423         move(address.index, scr);
   1424         lshift32(TrustedImm32(address.scale), scr);
   1425         add32(address.base, scr);
   1426         load32(scr, address.offset, scr);
   1427 
   1428         if (mask.m_value == -1)
   1429             m_assembler.testlRegReg(scr, scr);
   1430         else
   1431             testlImm(mask.m_value, scr);
   1432 
   1433         releaseScratch(scr);
   1434 
   1435         if (cond == NotEqual)
   1436             return branchFalse();
   1437         return branchTrue();
   1438     }
   1439 
   1440     Jump jump()
   1441     {
   1442         return Jump(m_assembler.jmp());
   1443     }
   1444 
   1445     void jump(RegisterID target)
   1446     {
   1447         m_assembler.jmpReg(target);
   1448     }
   1449 
   1450     void jump(Address address)
   1451     {
   1452         RegisterID scr = claimScratch();
   1453 
   1454         if ((address.offset < 0) || (address.offset >= 64)) {
   1455             m_assembler.loadConstant(address.offset, scr);
   1456             m_assembler.addlRegReg(address.base, scr);
   1457             m_assembler.movlMemReg(scr, scr);
   1458         } else if (address.offset)
   1459             m_assembler.movlMemReg(address.offset >> 2, address.base, scr);
   1460         else
   1461             m_assembler.movlMemReg(address.base, scr);
   1462         m_assembler.jmpReg(scr);
   1463 
   1464         releaseScratch(scr);
   1465     }
   1466 
   1467     // Arithmetic control flow operations
   1468 
   1469     Jump branchAdd32(Condition cond, RegisterID src, RegisterID dest)
   1470     {
   1471         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
   1472 
   1473         if (cond == Overflow) {
   1474             m_assembler.addvlRegReg(src, dest);
   1475             return branchTrue();
   1476         }
   1477 
   1478         if (cond == Signed) {
   1479             m_assembler.addlRegReg(src, dest);
   1480             // Check if dest is negative
   1481             m_assembler.cmppz(dest);
   1482             return branchFalse();
   1483         }
   1484 
   1485         m_assembler.addlRegReg(src, dest);
   1486         compare32(0, dest, Equal);
   1487 
   1488         if (cond == NotEqual)
   1489             return branchFalse();
   1490         return branchTrue();
   1491     }
   1492 
   1493     Jump branchAdd32(Condition cond, TrustedImm32 imm, RegisterID dest)
   1494     {
   1495         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
   1496 
   1497         move(imm, scratchReg3);
   1498         return branchAdd32(cond, scratchReg3, dest);
   1499     }
   1500 
   1501     Jump branchMul32(Condition cond, RegisterID src, RegisterID dest)
   1502     {
   1503         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
   1504 
   1505         if (cond == Overflow) {
   1506             RegisterID scr1 = claimScratch();
   1507             RegisterID scr = claimScratch();
   1508             m_assembler.dmullRegReg(src, dest);
   1509             m_assembler.stsmacl(dest);
   1510             m_assembler.movImm8(-31, scr);
   1511             m_assembler.movlRegReg(dest, scr1);
   1512             m_assembler.shaRegReg(scr1, scr);
   1513             m_assembler.stsmach(scr);
   1514             m_assembler.cmplRegReg(scr, scr1, Zero);
   1515             releaseScratch(scr1);
   1516             releaseScratch(scr);
   1517             return branchFalse();
   1518         }
   1519 
   1520         m_assembler.imullRegReg(src, dest);
   1521         m_assembler.stsmacl(dest);
   1522         if (cond == Signed) {
   1523             // Check if dest is negative
   1524             m_assembler.cmppz(dest);
   1525             return branchFalse();
   1526         }
   1527 
   1528         compare32(0, dest, cond);
   1529 
   1530         if (cond == NotEqual)
   1531             return branchFalse();
   1532         return branchTrue();
   1533     }
   1534 
   1535     Jump branchMul32(Condition cond, TrustedImm32 imm, RegisterID src, RegisterID dest)
   1536     {
   1537         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
   1538 
   1539         move(imm, scratchReg3);
   1540         if (src != dest)
   1541             move(src, dest);
   1542 
   1543         return branchMul32(cond, scratchReg3, dest);
   1544     }
   1545 
   1546     Jump branchSub32(Condition cond, RegisterID src, RegisterID dest)
   1547     {
   1548         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
   1549 
   1550         if (cond == Overflow) {
   1551             m_assembler.subvlRegReg(src, dest);
   1552             return branchTrue();
   1553         }
   1554 
   1555         if (cond == Signed) {
   1556             // Check if dest is negative
   1557             m_assembler.sublRegReg(src, dest);
   1558             compare32(0, dest, LessThan);
   1559             return branchTrue();
   1560         }
   1561 
   1562         sub32(src, dest);
   1563         compare32(0, dest, cond);
   1564 
   1565         if (cond == NotEqual)
   1566             return branchFalse();
   1567         return branchTrue();
   1568     }
   1569 
   1570     Jump branchSub32(Condition cond, TrustedImm32 imm, RegisterID dest)
   1571     {
   1572         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
   1573 
   1574         move(imm, scratchReg3);
   1575         return branchSub32(cond, scratchReg3, dest);
   1576     }
   1577 
   1578     Jump branchOr32(Condition cond, RegisterID src, RegisterID dest)
   1579     {
   1580         ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero));
   1581 
   1582         if (cond == Signed) {
   1583             or32(src, dest);
   1584             compare32(0, dest, LessThan);
   1585             return branchTrue();
   1586         }
   1587 
   1588         or32(src, dest);
   1589         compare32(0, dest, cond);
   1590 
   1591         if (cond == NotEqual)
   1592             return branchFalse();
   1593         return branchTrue();
   1594     }
   1595 
   1596     void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp)
   1597     {
   1598         m_assembler.ftrcdrmfpul(src);
   1599         m_assembler.stsfpulReg(dest);
   1600         convertInt32ToDouble(dest, fscratch);
   1601         failureCases.append(branchDouble(DoubleNotEqualOrUnordered, fscratch, src));
   1602 
   1603         if (dest == SH4Registers::r0)
   1604             m_assembler.cmpEqImmR0(0, dest, Equal);
   1605         else {
   1606             m_assembler.movImm8(0, scratchReg3);
   1607             m_assembler.cmplRegReg(scratchReg3, dest, Equal);
   1608         }
   1609         failureCases.append(branchTrue());
   1610     }
   1611 
   1612     void neg32(RegisterID dst)
   1613     {
   1614         m_assembler.neg(dst, dst);
   1615     }
   1616 
   1617     void not32(RegisterID dst)
   1618     {
   1619         m_assembler.notlReg(dst, dst);
   1620     }
   1621 
   1622     void urshift32(RegisterID shiftamount, RegisterID dest)
   1623     {
   1624         compare32(32, shiftamount, Equal);
   1625         m_assembler.ensureSpace(m_assembler.maxInstructionSize + 4);
   1626         m_assembler.branch(BT_OPCODE, 1);
   1627         m_assembler.neg(shiftamount, shiftamount);
   1628         m_assembler.shllRegReg(dest, shiftamount);
   1629     }
   1630 
   1631     void urshift32(TrustedImm32 imm, RegisterID dest)
   1632     {
   1633         RegisterID scr = claimScratch();
   1634         m_assembler.loadConstant(-(imm.m_value), scr);
   1635         m_assembler.shaRegReg(dest, scr);
   1636         releaseScratch(scr);
   1637     }
   1638 
   1639     Call call()
   1640     {
   1641         return Call(m_assembler.call(), Call::Linkable);
   1642     }
   1643 
   1644     Call nearCall()
   1645     {
   1646         return Call(m_assembler.call(), Call::LinkableNear);
   1647     }
   1648 
   1649     Call call(RegisterID target)
   1650     {
   1651         return Call(m_assembler.call(target), Call::None);
   1652     }
   1653 
   1654     void call(Address address, RegisterID target)
   1655     {
   1656         load32(address.base, address.offset, target);
   1657         m_assembler.ensureSpace(m_assembler.maxInstructionSize + 2);
   1658         m_assembler.branch(JSR_OPCODE, target);
   1659         m_assembler.nop();
   1660     }
   1661 
   1662     void breakpoint()
   1663     {
   1664         m_assembler.bkpt();
   1665         m_assembler.nop();
   1666     }
   1667 
   1668     Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
   1669     {
   1670         RegisterID dataTempRegister = claimScratch();
   1671 
   1672         dataLabel = moveWithPatch(initialRightValue, dataTempRegister);
   1673         m_assembler.cmplRegReg(dataTempRegister, left, cond);
   1674         releaseScratch(dataTempRegister);
   1675 
   1676         if (cond == NotEqual)
   1677             return branchFalse();
   1678         return branchTrue();
   1679     }
   1680 
   1681     Jump branchPtrWithPatch(Condition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
   1682     {
   1683         RegisterID scr = claimScratch();
   1684 
   1685         m_assembler.loadConstant(left.offset, scr);
   1686         m_assembler.addlRegReg(left.base, scr);
   1687         m_assembler.movlMemReg(scr, scr);
   1688         RegisterID scr1 = claimScratch();
   1689         dataLabel = moveWithPatch(initialRightValue, scr1);
   1690         m_assembler.cmplRegReg(scr1, scr, cond);
   1691         releaseScratch(scr);
   1692         releaseScratch(scr1);
   1693 
   1694         if (cond == NotEqual)
   1695             return branchFalse();
   1696         return branchTrue();
   1697     }
   1698 
   1699     void ret()
   1700     {
   1701         m_assembler.ret();
   1702         m_assembler.nop();
   1703     }
   1704 
   1705     DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address)
   1706     {
   1707         RegisterID scr = claimScratch();
   1708         DataLabelPtr label = moveWithPatch(initialValue, scr);
   1709         store32(scr, address);
   1710         releaseScratch(scr);
   1711         return label;
   1712     }
   1713 
   1714     DataLabelPtr storePtrWithPatch(ImplicitAddress address) { return storePtrWithPatch(TrustedImmPtr(0), address); }
   1715 
   1716     int sizeOfConstantPool()
   1717     {
   1718         return m_assembler.sizeOfConstantPool();
   1719     }
   1720 
   1721     Call tailRecursiveCall()
   1722     {
   1723         RegisterID scr = claimScratch();
   1724 
   1725         m_assembler.loadConstantUnReusable(0x0, scr, true);
   1726         Jump m_jump = Jump(m_assembler.jmp(scr));
   1727         releaseScratch(scr);
   1728 
   1729         return Call::fromTailJump(m_jump);
   1730     }
   1731 
   1732     Call makeTailRecursiveCall(Jump oldJump)
   1733     {
   1734         oldJump.link(this);
   1735         return tailRecursiveCall();
   1736     }
   1737 
   1738 private:
   1739     friend class LinkBuffer;
   1740     friend class RepatchBuffer;
   1741 
   1742     static void linkCall(void*, Call, FunctionPtr);
   1743     static void repatchCall(CodeLocationCall, CodeLocationLabel);
   1744     static void repatchCall(CodeLocationCall, FunctionPtr);
   1745 };
   1746 
   1747 } // namespace JSC
   1748 
   1749 #endif // ENABLE(ASSEMBLER)
   1750 
   1751 #endif // MacroAssemblerSH4_h
   1752