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 SH4Assembler_h
     28 #define SH4Assembler_h
     29 
     30 #if ENABLE(ASSEMBLER) && CPU(SH4)
     31 
     32 #include "AssemblerBuffer.h"
     33 #include "AssemblerBufferWithConstantPool.h"
     34 #include <stdarg.h>
     35 #include <stdint.h>
     36 #include <wtf/Assertions.h>
     37 #include <wtf/Vector.h>
     38 
     39 #ifndef NDEBUG
     40 #define SH4_ASSEMBLER_TRACING
     41 #endif
     42 
     43 namespace JSC {
     44 typedef uint16_t SH4Word;
     45 
     46 enum {
     47     INVALID_OPCODE = 0xffff,
     48     ADD_OPCODE = 0x300c,
     49     ADDIMM_OPCODE = 0x7000,
     50     ADDC_OPCODE = 0x300e,
     51     ADDV_OPCODE = 0x300f,
     52     AND_OPCODE = 0x2009,
     53     ANDIMM_OPCODE = 0xc900,
     54     DIV0_OPCODE = 0x2007,
     55     DIV1_OPCODE = 0x3004,
     56     BF_OPCODE = 0x8b00,
     57     BFS_OPCODE = 0x8f00,
     58     BRA_OPCODE = 0xa000,
     59     BRAF_OPCODE = 0x0023,
     60     NOP_OPCODE = 0x0009,
     61     BSR_OPCODE = 0xb000,
     62     RTS_OPCODE = 0x000b,
     63     BT_OPCODE = 0x8900,
     64     BTS_OPCODE = 0x8d00,
     65     BSRF_OPCODE = 0x0003,
     66     BRK_OPCODE = 0x003b,
     67     FTRC_OPCODE = 0xf03d,
     68     CMPEQ_OPCODE = 0x3000,
     69     CMPEQIMM_OPCODE = 0x8800,
     70     CMPGE_OPCODE = 0x3003,
     71     CMPGT_OPCODE = 0x3007,
     72     CMPHI_OPCODE = 0x3006,
     73     CMPHS_OPCODE = 0x3002,
     74     CMPPL_OPCODE = 0x4015,
     75     CMPPZ_OPCODE = 0x4011,
     76     CMPSTR_OPCODE = 0x200c,
     77     DT_OPCODE = 0x4010,
     78     FCMPEQ_OPCODE = 0xf004,
     79     FCMPGT_OPCODE = 0xf005,
     80     FMOV_OPCODE = 0xf00c,
     81     FADD_OPCODE = 0xf000,
     82     FMUL_OPCODE = 0xf002,
     83     FSUB_OPCODE = 0xf001,
     84     FDIV_OPCODE = 0xf003,
     85     FNEG_OPCODE = 0xf04d,
     86     JMP_OPCODE = 0x402b,
     87     JSR_OPCODE = 0x400b,
     88     LDSPR_OPCODE = 0x402a,
     89     LDSLPR_OPCODE = 0x4026,
     90     MOV_OPCODE = 0x6003,
     91     MOVIMM_OPCODE = 0xe000,
     92     MOVB_WRITE_RN_OPCODE = 0x2000,
     93     MOVB_WRITE_RNDEC_OPCODE = 0x2004,
     94     MOVB_WRITE_R0RN_OPCODE = 0x0004,
     95     MOVB_WRITE_OFFGBR_OPCODE = 0xc000,
     96     MOVB_WRITE_OFFRN_OPCODE = 0x8000,
     97     MOVB_READ_RM_OPCODE = 0x6000,
     98     MOVB_READ_RMINC_OPCODE = 0x6004,
     99     MOVB_READ_R0RM_OPCODE = 0x000c,
    100     MOVB_READ_OFFGBR_OPCODE = 0xc400,
    101     MOVB_READ_OFFRM_OPCODE = 0x8400,
    102     MOVL_WRITE_RN_OPCODE = 0x2002,
    103     MOVL_WRITE_RNDEC_OPCODE = 0x2006,
    104     MOVL_WRITE_R0RN_OPCODE = 0x0006,
    105     MOVL_WRITE_OFFGBR_OPCODE = 0xc200,
    106     MOVL_WRITE_OFFRN_OPCODE = 0x1000,
    107     MOVL_READ_RM_OPCODE = 0x6002,
    108     MOVL_READ_RMINC_OPCODE = 0x6006,
    109     MOVL_READ_R0RM_OPCODE = 0x000e,
    110     MOVL_READ_OFFGBR_OPCODE = 0xc600,
    111     MOVL_READ_OFFPC_OPCODE = 0xd000,
    112     MOVL_READ_OFFRM_OPCODE = 0x5000,
    113     MOVW_WRITE_RN_OPCODE = 0x2001,
    114     MOVW_READ_RM_OPCODE = 0x6001,
    115     MOVW_READ_R0RM_OPCODE = 0x000d,
    116     MOVW_READ_OFFRM_OPCODE = 0x8500,
    117     MOVW_READ_OFFPC_OPCODE = 0x9000,
    118     MOVA_READ_OFFPC_OPCODE = 0xc700,
    119     MOVT_OPCODE = 0x0029,
    120     MULL_OPCODE = 0x0007,
    121     DMULL_L_OPCODE = 0x3005,
    122     STSMACL_OPCODE = 0x001a,
    123     STSMACH_OPCODE = 0x000a,
    124     DMULSL_OPCODE = 0x300d,
    125     NEG_OPCODE = 0x600b,
    126     NEGC_OPCODE = 0x600a,
    127     NOT_OPCODE = 0x6007,
    128     OR_OPCODE = 0x200b,
    129     ORIMM_OPCODE = 0xcb00,
    130     ORBIMM_OPCODE = 0xcf00,
    131     SETS_OPCODE = 0x0058,
    132     SETT_OPCODE = 0x0018,
    133     SHAD_OPCODE = 0x400c,
    134     SHAL_OPCODE = 0x4020,
    135     SHAR_OPCODE = 0x4021,
    136     SHLD_OPCODE = 0x400d,
    137     SHLL_OPCODE = 0x4000,
    138     SHLL2_OPCODE = 0x4008,
    139     SHLL8_OPCODE = 0x4018,
    140     SHLL16_OPCODE = 0x4028,
    141     SHLR_OPCODE = 0x4001,
    142     SHLR2_OPCODE = 0x4009,
    143     SHLR8_OPCODE = 0x4019,
    144     SHLR16_OPCODE = 0x4029,
    145     STSPR_OPCODE = 0x002a,
    146     STSLPR_OPCODE = 0x4022,
    147     FLOAT_OPCODE = 0xf02d,
    148     SUB_OPCODE = 0x3008,
    149     SUBC_OPCODE = 0x300a,
    150     SUBV_OPCODE = 0x300b,
    151     TST_OPCODE = 0x2008,
    152     TSTIMM_OPCODE = 0xc800,
    153     TSTB_OPCODE = 0xcc00,
    154     EXTUW_OPCODE = 0x600d,
    155     XOR_OPCODE = 0x200a,
    156     XORIMM_OPCODE = 0xca00,
    157     XORB_OPCODE = 0xce00,
    158     FMOVS_READ_RM_INC_OPCODE = 0xf009,
    159     FMOVS_READ_RM_OPCODE = 0xf008,
    160     FMOVS_READ_R0RM_OPCODE = 0xf006,
    161     FMOVS_WRITE_RN_OPCODE = 0xf00a,
    162     FMOVS_WRITE_RN_DEC_OPCODE = 0xf00b,
    163     FMOVS_WRITE_R0RN_OPCODE = 0xf007,
    164     FCNVDS_DRM_FPUL_OPCODE = 0xf0bd,
    165     LDS_RM_FPUL_OPCODE = 0x405a,
    166     FLDS_FRM_FPUL_OPCODE = 0xf01d,
    167     STS_FPUL_RN_OPCODE = 0x005a,
    168     FSTS_FPUL_FRN_OPCODE = 0xF00d,
    169     LDSFPSCR_OPCODE = 0x406a,
    170     STSFPSCR_OPCODE = 0x006a,
    171     LDSRMFPUL_OPCODE = 0x405a,
    172     FSTSFPULFRN_OPCODE = 0xf00d,
    173     FSQRT_OPCODE = 0xf06d,
    174     FSCHG_OPCODE = 0xf3fd,
    175     CLRT_OPCODE = 8,
    176 };
    177 
    178 namespace SH4Registers {
    179 typedef enum {
    180     r0,
    181     r1,
    182     r2,
    183     r3,
    184     r4,
    185     r5,
    186     r6,
    187     r7,
    188     r8,
    189     r9,
    190     r10,
    191     r11,
    192     r12,
    193     r13,
    194     r14, fp = r14,
    195     r15, sp = r15,
    196     pc,
    197     pr,
    198 } RegisterID;
    199 
    200 typedef enum {
    201     fr0, dr0 = fr0,
    202     fr1,
    203     fr2, dr2 = fr2,
    204     fr3,
    205     fr4, dr4 = fr4,
    206     fr5,
    207     fr6, dr6 = fr6,
    208     fr7,
    209     fr8, dr8 = fr8,
    210     fr9,
    211     fr10, dr10 = fr10,
    212     fr11,
    213     fr12, dr12 = fr12,
    214     fr13,
    215     fr14, dr14 = fr14,
    216     fr15,
    217 } FPRegisterID;
    218 }
    219 
    220 inline uint16_t getOpcodeGroup1(uint16_t opc, int rm, int rn)
    221 {
    222     return (opc | ((rm & 0xf) << 8) | ((rn & 0xf) << 4));
    223 }
    224 
    225 inline uint16_t getOpcodeGroup2(uint16_t opc, int rm)
    226 {
    227     return (opc | ((rm & 0xf) << 8));
    228 }
    229 
    230 inline uint16_t getOpcodeGroup3(uint16_t opc, int rm, int rn)
    231 {
    232     return (opc | ((rm & 0xf) << 8) | (rn & 0xff));
    233 }
    234 
    235 inline uint16_t getOpcodeGroup4(uint16_t opc, int rm, int rn, int offset)
    236 {
    237     return (opc | ((rm & 0xf) << 8) | ((rn & 0xf) << 4) | (offset & 0xf));
    238 }
    239 
    240 inline uint16_t getOpcodeGroup5(uint16_t opc, int rm)
    241 {
    242     return (opc | (rm & 0xff));
    243 }
    244 
    245 inline uint16_t getOpcodeGroup6(uint16_t opc, int rm)
    246 {
    247     return (opc | (rm & 0xfff));
    248 }
    249 
    250 inline uint16_t getOpcodeGroup7(uint16_t opc, int rm)
    251 {
    252     return (opc | ((rm & 0x7) << 9));
    253 }
    254 
    255 inline uint16_t getOpcodeGroup8(uint16_t opc, int rm, int rn)
    256 {
    257     return (opc | ((rm & 0x7) << 9) | ((rn & 0x7) << 5));
    258 }
    259 
    260 inline uint16_t getOpcodeGroup9(uint16_t opc, int rm, int rn)
    261 {
    262     return (opc | ((rm & 0xf) << 8) | ((rn & 0x7) << 5));
    263 }
    264 
    265 inline uint16_t getOpcodeGroup10(uint16_t opc, int rm, int rn)
    266 {
    267     return (opc | ((rm & 0x7) << 9) | ((rn & 0xf) << 4));
    268 }
    269 
    270 inline uint16_t getOpcodeGroup11(uint16_t opc, int rm, int rn)
    271 {
    272     return (opc | ((rm & 0xf) << 4) | (rn & 0xf));
    273 }
    274 
    275 inline uint16_t getRn(uint16_t x)
    276 {
    277     return ((x & 0xf00) >> 8);
    278 }
    279 
    280 inline uint16_t getRm(uint16_t x)
    281 {
    282     return ((x & 0xf0) >> 4);
    283 }
    284 
    285 inline uint16_t getDisp(uint16_t x)
    286 {
    287     return (x & 0xf);
    288 }
    289 
    290 inline uint16_t getImm8(uint16_t x)
    291 {
    292     return (x & 0xff);
    293 }
    294 
    295 inline uint16_t getImm12(uint16_t x)
    296 {
    297     return (x & 0xfff);
    298 }
    299 
    300 inline uint16_t getDRn(uint16_t x)
    301 {
    302     return ((x & 0xe00) >> 9);
    303 }
    304 
    305 inline uint16_t getDRm(uint16_t x)
    306 {
    307     return ((x & 0xe0) >> 5);
    308 }
    309 
    310 class SH4Assembler {
    311 public:
    312     typedef SH4Registers::RegisterID RegisterID;
    313     typedef SH4Registers::FPRegisterID FPRegisterID;
    314     typedef AssemblerBufferWithConstantPool<512, 4, 2, SH4Assembler> SH4Buffer;
    315     static const RegisterID scratchReg1 = SH4Registers::r3;
    316     static const RegisterID scratchReg2 = SH4Registers::r11;
    317     static const uint32_t maxInstructionSize = 16;
    318 
    319     enum {
    320         padForAlign8 = 0x00,
    321         padForAlign16 = 0x0009,
    322         padForAlign32 = 0x00090009,
    323     };
    324 
    325     SH4Assembler()
    326     {
    327         m_claimscratchReg = 0x0;
    328     }
    329 
    330     // SH4 condition codes
    331     typedef enum {
    332         EQ = 0x0, // Equal
    333         NE = 0x1, // Not Equal
    334         HS = 0x2, // Unsigend Greater Than equal
    335         HI = 0x3, // Unsigend Greater Than
    336         LS = 0x4, // Unsigend Lower or Same
    337         LI = 0x5, // Unsigend Lower
    338         GE = 0x6, // Greater or Equal
    339         LT = 0x7, // Less Than
    340         GT = 0x8, // Greater Than
    341         LE = 0x9, // Less or Equal
    342         OF = 0xa, // OverFlow
    343         SI = 0xb, // Signed
    344         EQU= 0xc, // Equal or unordered(NaN)
    345         NEU= 0xd,
    346         GTU= 0xe,
    347         GEU= 0xf,
    348         LTU= 0x10,
    349         LEU= 0x11,
    350     } Condition;
    351 
    352     // Opaque label types
    353 public:
    354     class JmpSrc {
    355         friend class SH4Assembler;
    356     public:
    357         JmpSrc()
    358             : m_offset(-1)
    359         {
    360         }
    361 
    362     private:
    363         JmpSrc(int offset)
    364             : m_offset(offset)
    365         {
    366         }
    367 
    368         int m_offset;
    369     };
    370 
    371     class JmpDst {
    372         friend class SH4Assembler;
    373     public:
    374         JmpDst()
    375             : m_offset(-1)
    376             , m_used(false)
    377         {
    378         }
    379 
    380         bool isUsed() const { return m_used; }
    381         bool isSet() const { return (m_offset != -1); }
    382         void used() { m_used = true; }
    383 
    384     private:
    385         JmpDst(int offset)
    386             : m_offset(offset)
    387             , m_used(false)
    388         {
    389             ASSERT(m_offset == offset);
    390         }
    391 
    392         int m_offset : 31;
    393         int m_used : 1;
    394     };
    395 
    396     bool isImmediate(int constant)
    397     {
    398         return ((constant <= 127) && (constant >= -128));
    399     }
    400 
    401     RegisterID claimScratch()
    402     {
    403         ASSERT((m_claimscratchReg != 0x3));
    404 
    405         if (!(m_claimscratchReg & 0x1)) {
    406             m_claimscratchReg = (m_claimscratchReg | 0x1);
    407             return scratchReg1;
    408         }
    409 
    410         m_claimscratchReg = (m_claimscratchReg | 0x2);
    411         return scratchReg2;
    412     }
    413 
    414     void releaseScratch(RegisterID scratchR)
    415     {
    416         if (scratchR == scratchReg1)
    417             m_claimscratchReg = (m_claimscratchReg & 0x2);
    418         else
    419             m_claimscratchReg = (m_claimscratchReg & 0x1);
    420     }
    421 
    422     // Stack operations
    423 
    424     void pushReg(RegisterID reg)
    425     {
    426         if (reg == SH4Registers::pr) {
    427             oneShortOp(getOpcodeGroup2(STSLPR_OPCODE, SH4Registers::sp));
    428             return;
    429         }
    430 
    431         oneShortOp(getOpcodeGroup1(MOVL_WRITE_RNDEC_OPCODE, SH4Registers::sp, reg));
    432     }
    433 
    434     void popReg(RegisterID reg)
    435     {
    436         if (reg == SH4Registers::pr) {
    437             oneShortOp(getOpcodeGroup2(LDSLPR_OPCODE, SH4Registers::sp));
    438             return;
    439         }
    440 
    441         oneShortOp(getOpcodeGroup1(MOVL_READ_RMINC_OPCODE, reg, SH4Registers::sp));
    442     }
    443 
    444     void movt(RegisterID dst)
    445     {
    446         uint16_t opc = getOpcodeGroup2(MOVT_OPCODE, dst);
    447         oneShortOp(opc);
    448     }
    449 
    450     // Arithmetic operations
    451 
    452     void addlRegReg(RegisterID src, RegisterID dst)
    453     {
    454         uint16_t opc = getOpcodeGroup1(ADD_OPCODE, dst, src);
    455         oneShortOp(opc);
    456     }
    457 
    458     void addclRegReg(RegisterID src, RegisterID dst)
    459     {
    460         uint16_t opc = getOpcodeGroup1(ADDC_OPCODE, dst, src);
    461         oneShortOp(opc);
    462     }
    463 
    464     void addvlRegReg(RegisterID src, RegisterID dst)
    465     {
    466         uint16_t opc = getOpcodeGroup1(ADDV_OPCODE, dst, src);
    467         oneShortOp(opc);
    468     }
    469 
    470     void addlImm8r(int imm8, RegisterID dst)
    471     {
    472         ASSERT((imm8 <= 127) && (imm8 >= -128));
    473 
    474         uint16_t opc = getOpcodeGroup3(ADDIMM_OPCODE, dst, imm8);
    475         oneShortOp(opc);
    476     }
    477 
    478     void andlRegReg(RegisterID src, RegisterID dst)
    479     {
    480         uint16_t opc = getOpcodeGroup1(AND_OPCODE, dst, src);
    481         oneShortOp(opc);
    482     }
    483 
    484     void andlImm8r(int imm8, RegisterID dst)
    485     {
    486         ASSERT((imm8 <= 255) && (imm8 >= 0));
    487         ASSERT(dst == SH4Registers::r0);
    488 
    489         uint16_t opc = getOpcodeGroup5(ANDIMM_OPCODE, imm8);
    490         oneShortOp(opc);
    491     }
    492 
    493     void div1lRegReg(RegisterID src, RegisterID dst)
    494     {
    495         uint16_t opc = getOpcodeGroup1(DIV1_OPCODE, dst, src);
    496         oneShortOp(opc);
    497     }
    498 
    499     void div0lRegReg(RegisterID src, RegisterID dst)
    500     {
    501         uint16_t opc = getOpcodeGroup1(DIV0_OPCODE, dst, src);
    502         oneShortOp(opc);
    503     }
    504 
    505     void notlReg(RegisterID src, RegisterID dst)
    506     {
    507         uint16_t opc = getOpcodeGroup1(NOT_OPCODE, dst, src);
    508         oneShortOp(opc);
    509     }
    510 
    511     void orlRegReg(RegisterID src, RegisterID dst)
    512     {
    513         uint16_t opc = getOpcodeGroup1(OR_OPCODE, dst, src);
    514         oneShortOp(opc);
    515     }
    516 
    517     void orlImm8r(int imm8, RegisterID dst)
    518     {
    519         ASSERT((imm8 <= 255) && (imm8 >= 0));
    520         ASSERT(dst == SH4Registers::r0);
    521 
    522         uint16_t opc = getOpcodeGroup5(ORIMM_OPCODE, imm8);
    523         oneShortOp(opc);
    524     }
    525 
    526     void sublRegReg(RegisterID src, RegisterID dst)
    527     {
    528          uint16_t opc = getOpcodeGroup1(SUB_OPCODE, dst, src);
    529          oneShortOp(opc);
    530     }
    531 
    532     void subvlRegReg(RegisterID src, RegisterID dst)
    533     {
    534          uint16_t opc = getOpcodeGroup1(SUBV_OPCODE, dst, src);
    535          oneShortOp(opc);
    536     }
    537 
    538     void xorlRegReg(RegisterID src, RegisterID dst)
    539     {
    540         uint16_t opc = getOpcodeGroup1(XOR_OPCODE, dst, src);
    541         oneShortOp(opc);
    542     }
    543 
    544     void xorlImm8r(int imm8, RegisterID dst)
    545     {
    546         ASSERT((imm8 <= 255) && (imm8 >= 0));
    547         ASSERT(dst == SH4Registers::r0);
    548 
    549         uint16_t opc = getOpcodeGroup5(XORIMM_OPCODE, imm8);
    550         oneShortOp(opc);
    551     }
    552 
    553     void shllImm8r(int imm, RegisterID dst)
    554     {
    555         switch (imm) {
    556         case 1:
    557             oneShortOp(getOpcodeGroup2(SHLL_OPCODE, dst));
    558             break;
    559         case 2:
    560             oneShortOp(getOpcodeGroup2(SHLL2_OPCODE, dst));
    561             break;
    562         case 8:
    563             oneShortOp(getOpcodeGroup2(SHLL8_OPCODE, dst));
    564             break;
    565         case 16:
    566             oneShortOp(getOpcodeGroup2(SHLL16_OPCODE, dst));
    567             break;
    568         default:
    569             ASSERT_NOT_REACHED();
    570         }
    571     }
    572 
    573     void neg(RegisterID dst, RegisterID src)
    574     {
    575         uint16_t opc = getOpcodeGroup1(NEG_OPCODE, dst, src);
    576         oneShortOp(opc);
    577     }
    578 
    579     void shllRegReg(RegisterID dst, RegisterID rShift)
    580     {
    581         uint16_t opc = getOpcodeGroup1(SHLD_OPCODE, dst, rShift);
    582         oneShortOp(opc);
    583     }
    584 
    585     void shlrRegReg(RegisterID dst, RegisterID rShift)
    586     {
    587         neg(rShift, rShift);
    588         shllRegReg(dst, rShift);
    589     }
    590 
    591     void sharRegReg(RegisterID dst, RegisterID rShift)
    592     {
    593         neg(rShift, rShift);
    594         shaRegReg(dst, rShift);
    595     }
    596 
    597     void shaRegReg(RegisterID dst, RegisterID rShift)
    598     {
    599         uint16_t opc = getOpcodeGroup1(SHAD_OPCODE, dst, rShift);
    600         oneShortOp(opc);
    601     }
    602 
    603     void shlrImm8r(int imm, RegisterID dst)
    604     {
    605         switch (imm) {
    606         case 1:
    607             oneShortOp(getOpcodeGroup2(SHLR_OPCODE, dst));
    608             break;
    609         case 2:
    610             oneShortOp(getOpcodeGroup2(SHLR2_OPCODE, dst));
    611             break;
    612         case 8:
    613             oneShortOp(getOpcodeGroup2(SHLR8_OPCODE, dst));
    614             break;
    615         case 16:
    616             oneShortOp(getOpcodeGroup2(SHLR16_OPCODE, dst));
    617             break;
    618         default:
    619             ASSERT_NOT_REACHED();
    620         }
    621     }
    622 
    623     void imullRegReg(RegisterID src, RegisterID dst)
    624     {
    625         uint16_t opc = getOpcodeGroup1(MULL_OPCODE, dst, src);
    626         oneShortOp(opc);
    627     }
    628 
    629     void dmullRegReg(RegisterID src, RegisterID dst)
    630     {
    631         uint16_t opc = getOpcodeGroup1(DMULL_L_OPCODE, dst, src);
    632         oneShortOp(opc);
    633     }
    634 
    635     void dmulslRegReg(RegisterID src, RegisterID dst)
    636     {
    637         uint16_t opc = getOpcodeGroup1(DMULSL_OPCODE, dst, src);
    638         oneShortOp(opc);
    639     }
    640 
    641     void stsmacl(RegisterID reg)
    642     {
    643         uint16_t opc = getOpcodeGroup2(STSMACL_OPCODE, reg);
    644         oneShortOp(opc);
    645     }
    646 
    647     void stsmach(RegisterID reg)
    648     {
    649         uint16_t opc = getOpcodeGroup2(STSMACH_OPCODE, reg);
    650         oneShortOp(opc);
    651     }
    652 
    653     // Comparisons
    654 
    655     void cmplRegReg(RegisterID left, RegisterID right, Condition cond)
    656     {
    657         switch (cond) {
    658         case NE:
    659             oneShortOp(getOpcodeGroup1(CMPEQ_OPCODE, right, left));
    660             break;
    661         case GT:
    662             oneShortOp(getOpcodeGroup1(CMPGT_OPCODE, right, left));
    663             break;
    664         case EQ:
    665             oneShortOp(getOpcodeGroup1(CMPEQ_OPCODE, right, left));
    666             break;
    667         case GE:
    668             oneShortOp(getOpcodeGroup1(CMPGE_OPCODE, right, left));
    669             break;
    670         case HS:
    671             oneShortOp(getOpcodeGroup1(CMPHS_OPCODE, right, left));
    672             break;
    673         case HI:
    674             oneShortOp(getOpcodeGroup1(CMPHI_OPCODE, right, left));
    675             break;
    676         case LI:
    677             oneShortOp(getOpcodeGroup1(CMPHI_OPCODE, left, right));
    678             break;
    679         case LS:
    680             oneShortOp(getOpcodeGroup1(CMPHS_OPCODE, left, right));
    681             break;
    682         case LE:
    683             oneShortOp(getOpcodeGroup1(CMPGE_OPCODE, left, right));
    684             break;
    685         case LT:
    686             oneShortOp(getOpcodeGroup1(CMPGT_OPCODE, left, right));
    687             break;
    688         default:
    689             ASSERT_NOT_REACHED();
    690         }
    691     }
    692 
    693     void cmppl(RegisterID reg)
    694     {
    695         uint16_t opc = getOpcodeGroup2(CMPPL_OPCODE, reg);
    696         oneShortOp(opc);
    697     }
    698 
    699     void cmppz(RegisterID reg)
    700     {
    701         uint16_t opc = getOpcodeGroup2(CMPPZ_OPCODE, reg);
    702         oneShortOp(opc);
    703     }
    704 
    705     void cmpEqImmR0(int imm, RegisterID dst, Condition cond)
    706     {
    707         uint16_t opc = getOpcodeGroup5(CMPEQIMM_OPCODE, imm);
    708         oneShortOp(opc);
    709     }
    710 
    711     void testlRegReg(RegisterID src, RegisterID dst)
    712     {
    713         uint16_t opc = getOpcodeGroup1(TST_OPCODE, dst, src);
    714         oneShortOp(opc);
    715     }
    716 
    717     void testlImm8r(int imm, RegisterID dst)
    718     {
    719         ASSERT((dst == SH4Registers::r0) && (imm <= 255) && (imm >= 0));
    720 
    721         uint16_t opc = getOpcodeGroup5(TSTIMM_OPCODE, imm);
    722         oneShortOp(opc);
    723     }
    724 
    725     void nop()
    726     {
    727         oneShortOp(NOP_OPCODE, false);
    728     }
    729 
    730     void sett()
    731     {
    732         oneShortOp(SETT_OPCODE);
    733     }
    734 
    735     void clrt()
    736     {
    737         oneShortOp(CLRT_OPCODE);
    738     }
    739 
    740     void fschg()
    741     {
    742         oneShortOp(FSCHG_OPCODE);
    743     }
    744 
    745     void bkpt()
    746     {
    747         oneShortOp(BRK_OPCODE, false);
    748     }
    749 
    750     void branch(uint16_t opc, int label)
    751     {
    752         switch (opc) {
    753         case BT_OPCODE:
    754             ASSERT((label <= 127) && (label >= -128));
    755             oneShortOp(getOpcodeGroup5(BT_OPCODE, label));
    756             break;
    757         case BRA_OPCODE:
    758             ASSERT((label <= 2047) && (label >= -2048));
    759             oneShortOp(getOpcodeGroup6(BRA_OPCODE, label));
    760             break;
    761         case BF_OPCODE:
    762             ASSERT((label <= 127) && (label >= -128));
    763             oneShortOp(getOpcodeGroup5(BF_OPCODE, label));
    764             break;
    765         default:
    766             ASSERT_NOT_REACHED();
    767         }
    768     }
    769 
    770     void branch(uint16_t opc, RegisterID reg)
    771     {
    772         switch (opc) {
    773         case BRAF_OPCODE:
    774             oneShortOp(getOpcodeGroup2(BRAF_OPCODE, reg));
    775             break;
    776         case JMP_OPCODE:
    777             oneShortOp(getOpcodeGroup2(JMP_OPCODE, reg));
    778             break;
    779         case JSR_OPCODE:
    780             oneShortOp(getOpcodeGroup2(JSR_OPCODE, reg));
    781             break;
    782         case BSRF_OPCODE:
    783             oneShortOp(getOpcodeGroup2(BSRF_OPCODE, reg));
    784             break;
    785         default:
    786             ASSERT_NOT_REACHED();
    787         }
    788     }
    789 
    790     void ldspr(RegisterID reg)
    791     {
    792         uint16_t opc = getOpcodeGroup2(LDSPR_OPCODE, reg);
    793         oneShortOp(opc);
    794     }
    795 
    796     void stspr(RegisterID reg)
    797     {
    798         uint16_t opc = getOpcodeGroup2(STSPR_OPCODE, reg);
    799         oneShortOp(opc);
    800     }
    801 
    802     void extuw(RegisterID src, RegisterID dst)
    803     {
    804         uint16_t opc = getOpcodeGroup1(EXTUW_OPCODE, dst, src);
    805         oneShortOp(opc);
    806     }
    807 
    808     // float operations
    809 
    810     void ldsrmfpul(RegisterID src)
    811     {
    812         uint16_t opc = getOpcodeGroup2(LDS_RM_FPUL_OPCODE, src);
    813         oneShortOp(opc);
    814     }
    815 
    816     void fneg(FPRegisterID dst)
    817     {
    818         uint16_t opc = getOpcodeGroup2(FNEG_OPCODE, dst);
    819         oneShortOp(opc, true, false);
    820     }
    821 
    822     void fsqrt(FPRegisterID dst)
    823     {
    824         uint16_t opc = getOpcodeGroup2(FSQRT_OPCODE, dst);
    825         oneShortOp(opc, true, false);
    826     }
    827 
    828     void stsfpulReg(RegisterID src)
    829     {
    830         uint16_t opc = getOpcodeGroup2(STS_FPUL_RN_OPCODE, src);
    831         oneShortOp(opc);
    832     }
    833 
    834     void floatfpulfrn(RegisterID src)
    835     {
    836         uint16_t opc = getOpcodeGroup2(FLOAT_OPCODE, src);
    837         oneShortOp(opc, true, false);
    838     }
    839 
    840     void fmull(FPRegisterID src, FPRegisterID dst)
    841     {
    842         uint16_t opc = getOpcodeGroup1(FMUL_OPCODE, dst, src);
    843         oneShortOp(opc, true, false);
    844     }
    845 
    846     void fmovsReadrm(RegisterID src, FPRegisterID dst)
    847     {
    848         uint16_t opc = getOpcodeGroup1(FMOVS_READ_RM_OPCODE, dst, src);
    849         oneShortOp(opc, true, false);
    850     }
    851 
    852     void fmovsWriterm(FPRegisterID src, RegisterID dst)
    853     {
    854         uint16_t opc = getOpcodeGroup1(FMOVS_WRITE_RN_OPCODE, dst, src);
    855         oneShortOp(opc, true, false);
    856     }
    857 
    858     void fmovsWriter0r(FPRegisterID src, RegisterID dst)
    859     {
    860         uint16_t opc = getOpcodeGroup1(FMOVS_WRITE_R0RN_OPCODE, dst, src);
    861         oneShortOp(opc, true, false);
    862     }
    863 
    864     void fmovsReadr0r(RegisterID src, FPRegisterID dst)
    865     {
    866         uint16_t opc = getOpcodeGroup1(FMOVS_READ_R0RM_OPCODE, dst, src);
    867         oneShortOp(opc, true, false);
    868     }
    869 
    870     void fmovsReadrminc(RegisterID src, FPRegisterID dst)
    871     {
    872         uint16_t opc = getOpcodeGroup1(FMOVS_READ_RM_INC_OPCODE, dst, src);
    873         oneShortOp(opc, true, false);
    874     }
    875 
    876     void fmovsWriterndec(FPRegisterID src, RegisterID dst)
    877     {
    878         uint16_t opc = getOpcodeGroup1(FMOVS_WRITE_RN_DEC_OPCODE, dst, src);
    879         oneShortOp(opc, true, false);
    880     }
    881 
    882     void ftrcRegfpul(FPRegisterID src)
    883     {
    884         uint16_t opc = getOpcodeGroup2(FTRC_OPCODE, src);
    885         oneShortOp(opc, true, false);
    886     }
    887 
    888     void fldsfpul(RegisterID src)
    889     {
    890         uint16_t opc = getOpcodeGroup2(FLDS_FRM_FPUL_OPCODE, src);
    891         oneShortOp(opc);
    892     }
    893 
    894     void fstsfpul(RegisterID src)
    895     {
    896         uint16_t opc = getOpcodeGroup2(FSTS_FPUL_FRN_OPCODE, src);
    897         oneShortOp(opc);
    898     }
    899 
    900     void ldsfpscr(RegisterID reg)
    901     {
    902         uint16_t opc = getOpcodeGroup2(LDSFPSCR_OPCODE, reg);
    903         oneShortOp(opc);
    904     }
    905 
    906     void stsfpscr(RegisterID reg)
    907     {
    908         uint16_t opc = getOpcodeGroup2(STSFPSCR_OPCODE, reg);
    909         oneShortOp(opc);
    910     }
    911 
    912     // double operations
    913 
    914     void dcnvds(FPRegisterID src)
    915     {
    916         uint16_t opc = getOpcodeGroup7(FCNVDS_DRM_FPUL_OPCODE, src >> 1);
    917         oneShortOp(opc);
    918     }
    919 
    920     void dcmppeq(FPRegisterID src, FPRegisterID dst)
    921     {
    922         uint16_t opc = getOpcodeGroup8(FCMPEQ_OPCODE, dst >> 1, src >> 1);
    923         oneShortOp(opc);
    924     }
    925 
    926     void dcmppgt(FPRegisterID src, FPRegisterID dst)
    927     {
    928         uint16_t opc = getOpcodeGroup8(FCMPGT_OPCODE, dst >> 1, src >> 1);
    929         oneShortOp(opc);
    930     }
    931 
    932     void dmulRegReg(FPRegisterID src, FPRegisterID dst)
    933     {
    934         uint16_t opc = getOpcodeGroup8(FMUL_OPCODE, dst >> 1, src >> 1);
    935         oneShortOp(opc);
    936     }
    937 
    938     void dsubRegReg(FPRegisterID src, FPRegisterID dst)
    939     {
    940         uint16_t opc = getOpcodeGroup8(FSUB_OPCODE, dst >> 1, src >> 1);
    941         oneShortOp(opc);
    942     }
    943 
    944     void daddRegReg(FPRegisterID src, FPRegisterID dst)
    945     {
    946         uint16_t opc = getOpcodeGroup8(FADD_OPCODE, dst >> 1, src >> 1);
    947         oneShortOp(opc);
    948     }
    949 
    950     void dmovRegReg(FPRegisterID src, FPRegisterID dst)
    951     {
    952         uint16_t opc = getOpcodeGroup8(FMOV_OPCODE, dst >> 1, src >> 1);
    953         oneShortOp(opc);
    954     }
    955 
    956     void ddivRegReg(FPRegisterID src, FPRegisterID dst)
    957     {
    958         uint16_t opc = getOpcodeGroup8(FDIV_OPCODE, dst >> 1, src >> 1);
    959         oneShortOp(opc);
    960     }
    961 
    962     void dsqrt(FPRegisterID dst)
    963     {
    964         uint16_t opc = getOpcodeGroup7(FSQRT_OPCODE, dst >> 1);
    965         oneShortOp(opc);
    966     }
    967 
    968     void dneg(FPRegisterID dst)
    969     {
    970         uint16_t opc = getOpcodeGroup7(FNEG_OPCODE, dst >> 1);
    971         oneShortOp(opc);
    972     }
    973 
    974     void fmovReadrm(RegisterID src, FPRegisterID dst)
    975     {
    976         uint16_t opc = getOpcodeGroup10(FMOVS_READ_RM_OPCODE, dst >> 1, src);
    977         oneShortOp(opc);
    978     }
    979 
    980     void fmovWriterm(FPRegisterID src, RegisterID dst)
    981     {
    982         uint16_t opc = getOpcodeGroup9(FMOVS_WRITE_RN_OPCODE, dst, src >> 1);
    983         oneShortOp(opc);
    984     }
    985 
    986     void fmovWriter0r(FPRegisterID src, RegisterID dst)
    987     {
    988         uint16_t opc = getOpcodeGroup9(FMOVS_WRITE_R0RN_OPCODE, dst, src >> 1);
    989         oneShortOp(opc);
    990     }
    991 
    992     void fmovReadr0r(RegisterID src, FPRegisterID dst)
    993     {
    994         uint16_t opc = getOpcodeGroup10(FMOVS_READ_R0RM_OPCODE, dst >> 1, src);
    995         oneShortOp(opc);
    996     }
    997 
    998     void fmovReadrminc(RegisterID src, FPRegisterID dst)
    999     {
   1000         uint16_t opc = getOpcodeGroup10(FMOVS_READ_RM_INC_OPCODE, dst >> 1, src);
   1001         oneShortOp(opc);
   1002     }
   1003 
   1004     void fmovWriterndec(FPRegisterID src, RegisterID dst)
   1005     {
   1006         uint16_t opc = getOpcodeGroup9(FMOVS_WRITE_RN_DEC_OPCODE, dst, src >> 1);
   1007         oneShortOp(opc);
   1008     }
   1009 
   1010     void floatfpulDreg(FPRegisterID src)
   1011     {
   1012         uint16_t opc = getOpcodeGroup7(FLOAT_OPCODE, src >> 1);
   1013         oneShortOp(opc);
   1014     }
   1015 
   1016     void ftrcdrmfpul(FPRegisterID src)
   1017     {
   1018         uint16_t opc = getOpcodeGroup7(FTRC_OPCODE, src >> 1);
   1019         oneShortOp(opc);
   1020     }
   1021 
   1022     // Various move ops
   1023 
   1024     void movImm8(int imm8, RegisterID dst)
   1025     {
   1026         ASSERT((imm8 <= 127) && (imm8 >= -128));
   1027 
   1028         uint16_t opc = getOpcodeGroup3(MOVIMM_OPCODE, dst, imm8);
   1029         oneShortOp(opc);
   1030     }
   1031 
   1032     void movlRegReg(RegisterID src, RegisterID dst)
   1033     {
   1034         uint16_t opc = getOpcodeGroup1(MOV_OPCODE, dst, src);
   1035         oneShortOp(opc);
   1036     }
   1037 
   1038     void movwRegMem(RegisterID src, RegisterID dst)
   1039     {
   1040         uint16_t opc = getOpcodeGroup1(MOVW_WRITE_RN_OPCODE, dst, src);
   1041         oneShortOp(opc);
   1042     }
   1043 
   1044     void movwMemReg(RegisterID src, RegisterID dst)
   1045     {
   1046         uint16_t opc = getOpcodeGroup1(MOVW_READ_RM_OPCODE, dst, src);
   1047         oneShortOp(opc);
   1048     }
   1049 
   1050     void movwPCReg(int offset, RegisterID base, RegisterID dst)
   1051     {
   1052         ASSERT(base == SH4Registers::pc);
   1053         ASSERT((offset <= 255) && (offset >= 0));
   1054 
   1055         uint16_t opc = getOpcodeGroup3(MOVW_READ_OFFPC_OPCODE, dst, offset);
   1056         oneShortOp(opc);
   1057     }
   1058 
   1059     void movwMemReg(int offset, RegisterID base, RegisterID dst)
   1060     {
   1061         ASSERT(dst == SH4Registers::r0);
   1062 
   1063         uint16_t opc = getOpcodeGroup11(MOVW_READ_OFFRM_OPCODE, base, offset);
   1064         oneShortOp(opc);
   1065     }
   1066 
   1067     void movwR0mr(RegisterID src, RegisterID dst)
   1068     {
   1069         uint16_t opc = getOpcodeGroup1(MOVW_READ_R0RM_OPCODE, dst, src);
   1070         oneShortOp(opc);
   1071     }
   1072 
   1073     void movlRegMem(RegisterID src, int offset, RegisterID base)
   1074     {
   1075         ASSERT((offset <= 15) && (offset >= 0));
   1076 
   1077         if (!offset) {
   1078             oneShortOp(getOpcodeGroup1(MOVL_WRITE_RN_OPCODE, base, src));
   1079             return;
   1080         }
   1081 
   1082         oneShortOp(getOpcodeGroup4(MOVL_WRITE_OFFRN_OPCODE, base, src, offset));
   1083     }
   1084 
   1085     void movlRegMem(RegisterID src, RegisterID base)
   1086     {
   1087         uint16_t opc = getOpcodeGroup1(MOVL_WRITE_RN_OPCODE, base, src);
   1088         oneShortOp(opc);
   1089     }
   1090 
   1091     void movlMemReg(int offset, RegisterID base, RegisterID dst)
   1092     {
   1093         if (base == SH4Registers::pc) {
   1094             ASSERT((offset <= 255) && (offset >= 0));
   1095             oneShortOp(getOpcodeGroup3(MOVL_READ_OFFPC_OPCODE, dst, offset));
   1096             return;
   1097         }
   1098 
   1099         ASSERT((offset <= 15) && (offset >= 0));
   1100         if (!offset) {
   1101             oneShortOp(getOpcodeGroup1(MOVL_READ_RM_OPCODE, dst, base));
   1102             return;
   1103         }
   1104 
   1105         oneShortOp(getOpcodeGroup4(MOVL_READ_OFFRM_OPCODE, dst, base, offset));
   1106     }
   1107 
   1108     void movbMemReg(int offset, RegisterID base, RegisterID dst)
   1109     {
   1110         ASSERT(dst == SH4Registers::r0);
   1111 
   1112         uint16_t opc = getOpcodeGroup11(MOVB_READ_OFFRM_OPCODE, base, offset);
   1113         oneShortOp(opc);
   1114     }
   1115 
   1116     void movbR0mr(RegisterID src, RegisterID dst)
   1117     {
   1118         uint16_t opc = getOpcodeGroup1(MOVB_READ_R0RM_OPCODE, dst, src);
   1119         oneShortOp(opc);
   1120     }
   1121 
   1122     void movbMemReg(RegisterID src, RegisterID dst)
   1123     {
   1124         uint16_t opc = getOpcodeGroup1(MOVB_READ_RM_OPCODE, dst, src);
   1125         oneShortOp(opc);
   1126     }
   1127 
   1128     void movlMemReg(RegisterID base, RegisterID dst)
   1129     {
   1130         uint16_t opc = getOpcodeGroup1(MOVL_READ_RM_OPCODE, dst, base);
   1131         oneShortOp(opc);
   1132     }
   1133 
   1134     void movlMemRegIn(RegisterID base, RegisterID dst)
   1135     {
   1136         uint16_t opc = getOpcodeGroup1(MOVL_READ_RMINC_OPCODE, dst, base);
   1137         oneShortOp(opc);
   1138     }
   1139 
   1140     void movlR0mr(RegisterID src, RegisterID dst)
   1141     {
   1142         uint16_t opc = getOpcodeGroup1(MOVL_READ_R0RM_OPCODE, dst, src);
   1143         oneShortOp(opc);
   1144     }
   1145 
   1146     void movlRegMemr0(RegisterID src, RegisterID dst)
   1147     {
   1148         uint16_t opc = getOpcodeGroup1(MOVL_WRITE_R0RN_OPCODE, dst, src);
   1149         oneShortOp(opc);
   1150     }
   1151 
   1152     void movlImm8r(int imm8, RegisterID dst)
   1153     {
   1154         ASSERT((imm8 <= 127) && (imm8 >= -128));
   1155 
   1156         uint16_t opc = getOpcodeGroup3(MOVIMM_OPCODE, dst, imm8);
   1157         oneShortOp(opc);
   1158     }
   1159 
   1160     void loadConstant(uint32_t constant, RegisterID dst)
   1161     {
   1162         if (((int)constant <= 0x7f) && ((int)constant >= -0x80)) {
   1163             movImm8(constant, dst);
   1164             return;
   1165         }
   1166 
   1167         uint16_t opc = getOpcodeGroup3(MOVIMM_OPCODE, dst, 0);
   1168 
   1169         m_buffer.ensureSpace(maxInstructionSize, sizeof(uint32_t));
   1170         printInstr(getOpcodeGroup3(MOVIMM_OPCODE, dst, constant), m_buffer.uncheckedSize());
   1171         m_buffer.putShortWithConstantInt(opc, constant, true);
   1172     }
   1173 
   1174     void loadConstantUnReusable(uint32_t constant, RegisterID dst, bool ensureSpace = false)
   1175     {
   1176         uint16_t opc = getOpcodeGroup3(MOVIMM_OPCODE, dst, 0);
   1177 
   1178         if (ensureSpace)
   1179             m_buffer.ensureSpace(maxInstructionSize, sizeof(uint32_t));
   1180 
   1181         printInstr(getOpcodeGroup3(MOVIMM_OPCODE, dst, constant), m_buffer.uncheckedSize());
   1182         m_buffer.putShortWithConstantInt(opc, constant);
   1183     }
   1184 
   1185     // Flow control
   1186 
   1187     JmpSrc call()
   1188     {
   1189         RegisterID scr = claimScratch();
   1190         m_buffer.ensureSpace(maxInstructionSize + 4, sizeof(uint32_t));
   1191         loadConstantUnReusable(0x0, scr);
   1192         branch(JSR_OPCODE, scr);
   1193         nop();
   1194         releaseScratch(scr);
   1195         return JmpSrc(m_buffer.uncheckedSize());
   1196     }
   1197 
   1198     JmpSrc call(RegisterID dst)
   1199     {
   1200         m_buffer.ensureSpace(maxInstructionSize + 2);
   1201         branch(JSR_OPCODE, dst);
   1202         nop();
   1203         return JmpSrc(m_buffer.uncheckedSize());
   1204     }
   1205 
   1206     JmpSrc jmp()
   1207     {
   1208         RegisterID scr = claimScratch();
   1209         m_buffer.ensureSpace(maxInstructionSize + 4, sizeof(uint32_t));
   1210         int m_size = m_buffer.uncheckedSize();
   1211         loadConstantUnReusable(0x0, scr);
   1212         branch(BRAF_OPCODE, scr);
   1213         nop();
   1214         releaseScratch(scr);
   1215         return JmpSrc(m_size);
   1216     }
   1217 
   1218     JmpSrc jmp(RegisterID dst)
   1219     {
   1220         jmpReg(dst);
   1221         return JmpSrc(m_buffer.uncheckedSize());
   1222     }
   1223 
   1224     void jmpReg(RegisterID dst)
   1225     {
   1226         m_buffer.ensureSpace(maxInstructionSize + 2);
   1227         branch(JMP_OPCODE, dst);
   1228         nop();
   1229     }
   1230 
   1231     JmpSrc jne()
   1232     {
   1233         int m_size = m_buffer.uncheckedSize();
   1234         branch(BF_OPCODE, 0);
   1235         return JmpSrc(m_size);
   1236     }
   1237 
   1238     JmpSrc je()
   1239     {
   1240         int m_size = m_buffer.uncheckedSize();
   1241         branch(BT_OPCODE, 0);
   1242         return JmpSrc(m_size);
   1243     }
   1244 
   1245     void ret()
   1246     {
   1247         m_buffer.ensureSpace(maxInstructionSize + 2);
   1248         oneShortOp(RTS_OPCODE, false);
   1249     }
   1250 
   1251     JmpDst label()
   1252     {
   1253         return JmpDst(m_buffer.size());
   1254     }
   1255 
   1256     int sizeOfConstantPool()
   1257     {
   1258          return m_buffer.sizeOfConstantPool();
   1259     }
   1260 
   1261     JmpDst align(int alignment)
   1262     {
   1263         m_buffer.ensureSpace(maxInstructionSize + 2);
   1264         while (!m_buffer.isAligned(alignment)) {
   1265             nop();
   1266             m_buffer.ensureSpace(maxInstructionSize + 2);
   1267         }
   1268         return label();
   1269     }
   1270 
   1271     static void changePCrelativeAddress(int offset, uint16_t* instructionPtr, uint32_t newAddress)
   1272     {
   1273         uint32_t address = (offset << 2) + ((reinterpret_cast<uint32_t>(instructionPtr) + 4) &(~0x3));
   1274         *reinterpret_cast<uint32_t*>(address) = newAddress;
   1275     }
   1276 
   1277     static uint16_t* getInstructionPtr(void* code, int offset)
   1278     {
   1279         return reinterpret_cast<uint16_t*> (reinterpret_cast<uint32_t>(code) + offset);
   1280     }
   1281 
   1282     static void linkJump(void* code, JmpSrc from, void* to)
   1283     {
   1284         ASSERT(from.m_offset != -1);
   1285 
   1286         uint16_t* instructionPtr = getInstructionPtr(code, from.m_offset);
   1287         uint16_t instruction = *instructionPtr;
   1288         int offsetBits = (reinterpret_cast<uint32_t>(to) - reinterpret_cast<uint32_t>(code)) - from.m_offset;
   1289 
   1290         if (((instruction & 0xff00) == BT_OPCODE) || ((instruction & 0xff00) == BF_OPCODE)) {
   1291             /* BT label ==> BF 2
   1292                nop          LDR reg
   1293                nop          braf @reg
   1294                nop          nop
   1295             */
   1296             offsetBits -= 8;
   1297             instruction ^= 0x0202;
   1298             *instructionPtr++ = instruction;
   1299             changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits);
   1300             instruction = (BRAF_OPCODE | (*instructionPtr++ & 0xf00));
   1301             *instructionPtr = instruction;
   1302             printBlockInstr(instructionPtr - 2, from.m_offset, 3);
   1303             return;
   1304          }
   1305 
   1306          /* MOV #imm, reg => LDR reg
   1307             braf @reg        braf @reg
   1308             nop              nop
   1309          */
   1310         ASSERT((*(instructionPtr + 1) & BRAF_OPCODE) == BRAF_OPCODE);
   1311 
   1312         offsetBits -= 4;
   1313         if (offsetBits >= -4096 && offsetBits <= 4094) {
   1314             *instructionPtr = getOpcodeGroup6(BRA_OPCODE, offsetBits >> 1);
   1315             *(++instructionPtr) = NOP_OPCODE;
   1316             printBlockInstr(instructionPtr - 1, from.m_offset, 2);
   1317             return;
   1318         }
   1319 
   1320         changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits - 2);
   1321         printInstr(*instructionPtr, from.m_offset + 2);
   1322     }
   1323 
   1324     static void linkCall(void* code, JmpSrc from, void* to)
   1325     {
   1326         uint16_t* instructionPtr = getInstructionPtr(code, from.m_offset);
   1327         instructionPtr -= 3;
   1328         changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, reinterpret_cast<uint32_t>(to));
   1329     }
   1330 
   1331     static void linkPointer(void* code, JmpDst where, void* value)
   1332     {
   1333         uint16_t* instructionPtr = getInstructionPtr(code, where.m_offset);
   1334         changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, reinterpret_cast<uint32_t>(value));
   1335     }
   1336 
   1337     static unsigned getCallReturnOffset(JmpSrc call)
   1338     {
   1339         ASSERT(call.m_offset >= 0);
   1340         return call.m_offset;
   1341     }
   1342 
   1343     static uint32_t* getLdrImmAddressOnPool(SH4Word* insn, uint32_t* constPool)
   1344     {
   1345         return (constPool + (*insn & 0xff));
   1346     }
   1347 
   1348     static SH4Word patchConstantPoolLoad(SH4Word load, int value)
   1349     {
   1350         return ((load & ~0xff) | value);
   1351     }
   1352 
   1353     static SH4Buffer::TwoShorts placeConstantPoolBarrier(int offset)
   1354     {
   1355         ASSERT(((offset >> 1) <=2047) && ((offset >> 1) >= -2048));
   1356 
   1357         SH4Buffer::TwoShorts m_barrier;
   1358         m_barrier.high = (BRA_OPCODE | (offset >> 1));
   1359         m_barrier.low = NOP_OPCODE;
   1360         printInstr(((BRA_OPCODE | (offset >> 1))), 0);
   1361         printInstr(NOP_OPCODE, 0);
   1362         return m_barrier;
   1363     }
   1364 
   1365     static void patchConstantPoolLoad(void* loadAddr, void* constPoolAddr)
   1366     {
   1367         SH4Word* instructionPtr = reinterpret_cast<SH4Word*>(loadAddr);
   1368         SH4Word instruction = *instructionPtr;
   1369         SH4Word index = instruction & 0xff;
   1370 
   1371         if ((instruction & 0xf000) != MOVIMM_OPCODE)
   1372             return;
   1373 
   1374         ASSERT((((reinterpret_cast<uint32_t>(constPoolAddr) - reinterpret_cast<uint32_t>(loadAddr)) + index * 4)) < 1024);
   1375 
   1376         int offset = reinterpret_cast<uint32_t>(constPoolAddr) + (index * 4) - ((reinterpret_cast<uint32_t>(instructionPtr) & ~0x03) + 4);
   1377         instruction &=0xf00;
   1378         instruction |= 0xd000;
   1379         offset &= 0x03ff;
   1380         instruction |= (offset >> 2);
   1381         *instructionPtr = instruction;
   1382         printInstr(instruction, reinterpret_cast<uint32_t>(loadAddr));
   1383     }
   1384 
   1385     static void repatchPointer(void* where, void* value)
   1386     {
   1387         patchPointer(where, value);
   1388     }
   1389 
   1390     static void repatchInt32(void* where, int32_t value)
   1391     {
   1392         uint16_t* instructionPtr = reinterpret_cast<uint16_t*>(where);
   1393         changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, value);
   1394     }
   1395 
   1396     static void relinkCall(void* from, void* to)
   1397     {
   1398         uint16_t* instructionPtr = reinterpret_cast<uint16_t*>(from);
   1399         instructionPtr -= 3;
   1400         changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, reinterpret_cast<uint32_t>(to));
   1401     }
   1402 
   1403     static void relinkJump(void* from, void* to)
   1404     {
   1405         uint16_t* instructionPtr = reinterpret_cast<uint16_t*> (from);
   1406         uint16_t instruction = *instructionPtr;
   1407         int32_t offsetBits = (reinterpret_cast<uint32_t>(to) - reinterpret_cast<uint32_t>(from));
   1408 
   1409         if (((*instructionPtr & 0xff00) == BT_OPCODE) || ((*instructionPtr & 0xff00) == BF_OPCODE)) {
   1410             offsetBits -= 8;
   1411             instructionPtr++;
   1412             changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits);
   1413             instruction = (BRAF_OPCODE | (*instructionPtr++ & 0xf00));
   1414             *instructionPtr = instruction;
   1415             printBlockInstr(instructionPtr, reinterpret_cast<uint32_t>(from) + 1, 3);
   1416             return;
   1417         }
   1418 
   1419         ASSERT((*(instructionPtr + 1) & BRAF_OPCODE) == BRAF_OPCODE);
   1420         offsetBits -= 4;
   1421         if (offsetBits >= -4096 && offsetBits <= 4094) {
   1422             *instructionPtr = getOpcodeGroup6(BRA_OPCODE, offsetBits >> 1);
   1423             *(++instructionPtr) = NOP_OPCODE;
   1424             printBlockInstr(instructionPtr - 2, reinterpret_cast<uint32_t>(from), 2);
   1425             return;
   1426         }
   1427 
   1428         changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits - 2);
   1429         printInstr(*instructionPtr, reinterpret_cast<uint32_t>(from));
   1430     }
   1431 
   1432     // Linking & patching
   1433 
   1434     void linkJump(JmpSrc from, JmpDst to)
   1435     {
   1436         ASSERT(to.m_offset != -1);
   1437         ASSERT(from.m_offset != -1);
   1438 
   1439         uint16_t* instructionPtr = getInstructionPtr(data(), from.m_offset);
   1440         uint16_t instruction = *instructionPtr;
   1441         int offsetBits;
   1442 
   1443         if (((instruction & 0xff00) == BT_OPCODE) || ((instruction & 0xff00) == BF_OPCODE)) {
   1444             /* BT label => BF 2
   1445                nop        LDR reg
   1446                nop        braf @reg
   1447                nop        nop
   1448             */
   1449             offsetBits = (to.m_offset - from.m_offset) - 8;
   1450             instruction ^= 0x0202;
   1451             *instructionPtr++ = instruction;
   1452             if ((*instructionPtr & 0xf000) == 0xe000) {
   1453                 uint32_t* addr = getLdrImmAddressOnPool(instructionPtr, m_buffer.poolAddress());
   1454                 *addr = offsetBits;
   1455             } else
   1456                 changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits);
   1457             instruction = (BRAF_OPCODE | (*instructionPtr++ & 0xf00));
   1458             *instructionPtr = instruction;
   1459             printBlockInstr(instructionPtr - 2, from.m_offset, 3);
   1460             return;
   1461         }
   1462 
   1463         /* MOV # imm, reg => LDR reg
   1464            braf @reg         braf @reg
   1465            nop               nop
   1466         */
   1467         ASSERT((*(instructionPtr + 1) & BRAF_OPCODE) == BRAF_OPCODE);
   1468         offsetBits = (to.m_offset - from.m_offset) - 4;
   1469         if (offsetBits >= -4096 && offsetBits <= 4094) {
   1470             *instructionPtr = getOpcodeGroup6(BRA_OPCODE, offsetBits >> 1);
   1471             *(++instructionPtr) = NOP_OPCODE;
   1472             printBlockInstr(instructionPtr - 1, from.m_offset, 2);
   1473             return;
   1474         }
   1475 
   1476         instruction = *instructionPtr;
   1477         if ((instruction  & 0xf000) == 0xe000) {
   1478             uint32_t* addr = getLdrImmAddressOnPool(instructionPtr, m_buffer.poolAddress());
   1479             *addr = offsetBits - 2;
   1480             printInstr(*instructionPtr, from.m_offset + 2);
   1481             return;
   1482         }
   1483 
   1484         changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits - 2);
   1485         printInstr(*instructionPtr, from.m_offset + 2);
   1486     }
   1487 
   1488     static void* getRelocatedAddress(void* code, JmpSrc jump)
   1489     {
   1490         return reinterpret_cast<void*>(reinterpret_cast<uint32_t>(code) + jump.m_offset);
   1491     }
   1492 
   1493     static void* getRelocatedAddress(void* code, JmpDst destination)
   1494     {
   1495         ASSERT(destination.m_offset != -1);
   1496         return reinterpret_cast<void*>(reinterpret_cast<uint32_t>(code) + destination.m_offset);
   1497     }
   1498 
   1499     static int getDifferenceBetweenLabels(JmpDst src, JmpDst dst)
   1500     {
   1501         return dst.m_offset - src.m_offset;
   1502     }
   1503 
   1504     static int getDifferenceBetweenLabels(JmpDst src, JmpSrc dst)
   1505     {
   1506         return dst.m_offset - src.m_offset;
   1507     }
   1508 
   1509     static int getDifferenceBetweenLabels(JmpSrc src, JmpDst dst)
   1510     {
   1511         return dst.m_offset - src.m_offset;
   1512     }
   1513 
   1514     static void patchPointer(void* code, JmpDst where, void* value)
   1515     {
   1516         patchPointer(reinterpret_cast<uint32_t*>(code) + where.m_offset, value);
   1517     }
   1518 
   1519     static void patchPointer(void* code, void* value)
   1520     {
   1521         patchInt32(code, reinterpret_cast<uint32_t>(value));
   1522     }
   1523 
   1524     static void patchInt32(void* code, uint32_t value)
   1525     {
   1526         changePCrelativeAddress((*(reinterpret_cast<uint16_t*>(code)) & 0xff), reinterpret_cast<uint16_t*>(code), value);
   1527     }
   1528 
   1529     void* executableCopy(ExecutablePool* allocator)
   1530     {
   1531         void* copy = m_buffer.executableCopy(allocator);
   1532         ASSERT(copy);
   1533         return copy;
   1534     }
   1535 
   1536     void prefix(uint16_t pre)
   1537     {
   1538         m_buffer.putByte(pre);
   1539     }
   1540 
   1541     void oneShortOp(uint16_t opcode, bool checksize = true, bool isDouble = true)
   1542     {
   1543         printInstr(opcode, m_buffer.uncheckedSize(), isDouble);
   1544         if (checksize)
   1545             m_buffer.ensureSpace(maxInstructionSize);
   1546         m_buffer.putShortUnchecked(opcode);
   1547     }
   1548 
   1549     void ensureSpace(int space)
   1550     {
   1551         m_buffer.ensureSpace(space);
   1552     }
   1553 
   1554     void ensureSpace(int insnSpace, int constSpace)
   1555     {
   1556         m_buffer.ensureSpace(insnSpace, constSpace);
   1557     }
   1558 
   1559     // Administrative methods
   1560 
   1561     void* data() const { return m_buffer.data(); }
   1562     int size()
   1563     {
   1564         return m_buffer.size();
   1565     }
   1566 
   1567 #ifdef SH4_ASSEMBLER_TRACING
   1568     static void printInstr(uint16_t opc, unsigned int size, bool isdoubleInst = true)
   1569     {
   1570         if (!getenv("JavaScriptCoreDumpJIT"))
   1571             return;
   1572 
   1573         const char *format = 0;
   1574         printfStdoutInstr("offset: 0x%8.8x\t", size);
   1575         switch (opc) {
   1576         case BRK_OPCODE:
   1577             format = "    BRK\n";
   1578             break;
   1579         case NOP_OPCODE:
   1580             format = "    NOP\n";
   1581             break;
   1582         case RTS_OPCODE:
   1583             format ="    *RTS\n";
   1584             break;
   1585         case SETS_OPCODE:
   1586             format = "    SETS\n";
   1587             break;
   1588         case SETT_OPCODE:
   1589             format = "    SETT\n";
   1590             break;
   1591         case CLRT_OPCODE:
   1592             format = "    CLRT\n";
   1593             break;
   1594         case FSCHG_OPCODE:
   1595             format = "    FSCHG\n";
   1596             break;
   1597         }
   1598         if (format) {
   1599             printfStdoutInstr(format);
   1600             return;
   1601         }
   1602         switch (opc & 0xf0ff) {
   1603         case BRAF_OPCODE:
   1604             format = "    *BRAF R%d\n";
   1605             break;
   1606         case DT_OPCODE:
   1607             format = "    DT R%d\n";
   1608             break;
   1609         case CMPPL_OPCODE:
   1610             format = "    CMP/PL R%d\n";
   1611             break;
   1612         case CMPPZ_OPCODE:
   1613             format = "    CMP/PZ R%d\n";
   1614             break;
   1615         case JMP_OPCODE:
   1616             format = "    *JMP @R%d\n";
   1617             break;
   1618         case JSR_OPCODE:
   1619             format = "    *JSR @R%d\n";
   1620             break;
   1621         case LDSPR_OPCODE:
   1622             format = "    LDS R%d, PR\n";
   1623             break;
   1624         case LDSLPR_OPCODE:
   1625             format = "    LDS.L @R%d+, PR\n";
   1626             break;
   1627         case MOVT_OPCODE:
   1628             format = "    MOVT R%d\n";
   1629             break;
   1630         case SHAL_OPCODE:
   1631             format = "    SHAL R%d\n";
   1632             break;
   1633         case SHAR_OPCODE:
   1634             format = "    SHAR R%d\n";
   1635             break;
   1636         case SHLL_OPCODE:
   1637             format = "    SHLL R%d\n";
   1638             break;
   1639         case SHLL2_OPCODE:
   1640             format = "    SHLL2 R%d\n";
   1641             break;
   1642         case SHLL8_OPCODE:
   1643             format = "    SHLL8 R%d\n";
   1644             break;
   1645         case SHLL16_OPCODE:
   1646             format = "    SHLL16 R%d\n";
   1647             break;
   1648         case SHLR_OPCODE:
   1649             format = "    SHLR R%d\n";
   1650             break;
   1651         case SHLR2_OPCODE:
   1652             format = "    SHLR2 R%d\n";
   1653             break;
   1654         case SHLR8_OPCODE:
   1655             format = "    SHLR8 R%d\n";
   1656             break;
   1657         case SHLR16_OPCODE:
   1658             format = "    SHLR16 R%d\n";
   1659             break;
   1660         case STSPR_OPCODE:
   1661             format = "    STS PR, R%d\n";
   1662             break;
   1663         case STSLPR_OPCODE:
   1664             format = "    STS.L PR, @-R%d\n";
   1665             break;
   1666         case LDS_RM_FPUL_OPCODE:
   1667             format = "    LDS R%d, FPUL\n";
   1668             break;
   1669         case STS_FPUL_RN_OPCODE:
   1670             format = "    STS FPUL, R%d \n";
   1671             break;
   1672         case FLDS_FRM_FPUL_OPCODE:
   1673             format = "    FLDS FR%d, FPUL\n";
   1674             break;
   1675         case FSTS_FPUL_FRN_OPCODE:
   1676             format = "    FSTS FPUL, R%d \n";
   1677             break;
   1678         case LDSFPSCR_OPCODE:
   1679             format = "    LDS R%d, FPSCR \n";
   1680             break;
   1681         case STSFPSCR_OPCODE:
   1682             format = "    STS FPSCR, R%d \n";
   1683             break;
   1684         case STSMACL_OPCODE:
   1685             format = "    STS MACL, R%d \n";
   1686             break;
   1687         case STSMACH_OPCODE:
   1688             format = "    STS MACH, R%d \n";
   1689             break;
   1690         case BSRF_OPCODE:
   1691             format = "    *BSRF R%d";
   1692             break;
   1693         case FTRC_OPCODE:
   1694             format = "    FTRC FR%d, FPUL\n";
   1695             break;
   1696         }
   1697         if (format) {
   1698             printfStdoutInstr(format, getRn(opc));
   1699             return;
   1700         }
   1701         switch (opc & 0xf0ff) {
   1702         case FNEG_OPCODE:
   1703             format = "    FNEG DR%d\n";
   1704             break;
   1705         case FLOAT_OPCODE:
   1706             format = "    FLOAT DR%d\n";
   1707             break;
   1708         case FTRC_OPCODE:
   1709             format = "    FTRC FR%d, FPUL\n";
   1710             break;
   1711         case FSQRT_OPCODE:
   1712             format = "    FSQRT FR%d\n";
   1713             break;
   1714         case FCNVDS_DRM_FPUL_OPCODE:
   1715             format = "    FCNVDS FR%d, FPUL\n";
   1716             break;
   1717         }
   1718         if (format) {
   1719             if (isdoubleInst)
   1720                 printfStdoutInstr(format, getDRn(opc) << 1);
   1721             else
   1722                 printfStdoutInstr(format, getRn(opc));
   1723             return;
   1724         }
   1725         switch (opc & 0xf00f) {
   1726         case ADD_OPCODE:
   1727             format = "    ADD R%d, R%d\n";
   1728             break;
   1729         case ADDC_OPCODE:
   1730             format = "    ADDC R%d, R%d\n";
   1731             break;
   1732         case ADDV_OPCODE:
   1733             format = "    ADDV R%d, R%d\n";
   1734             break;
   1735         case AND_OPCODE:
   1736             format = "    AND R%d, R%d\n";
   1737             break;
   1738         case DIV1_OPCODE:
   1739             format = "    DIV1 R%d, R%d\n";
   1740             break;
   1741         case CMPEQ_OPCODE:
   1742             format = "    CMP/EQ R%d, R%d\n";
   1743             break;
   1744         case CMPGE_OPCODE:
   1745             format = "    CMP/GE R%d, R%d\n";
   1746             break;
   1747         case CMPGT_OPCODE:
   1748             format = "    CMP/GT R%d, R%d\n";
   1749             break;
   1750         case CMPHI_OPCODE:
   1751             format = "    CMP/HI R%d, R%d\n";
   1752             break;
   1753         case CMPHS_OPCODE:
   1754             format = "    CMP/HS R%d, R%d\n";
   1755             break;
   1756         case MOV_OPCODE:
   1757             format = "    MOV R%d, R%d\n";
   1758             break;
   1759         case MOVB_WRITE_RN_OPCODE:
   1760             format = "    MOV.B R%d, @R%d\n";
   1761             break;
   1762         case MOVB_WRITE_RNDEC_OPCODE:
   1763             format = "    MOV.B R%d, @-R%d\n";
   1764             break;
   1765         case MOVB_WRITE_R0RN_OPCODE:
   1766             format = "    MOV.B R%d, @(R0, R%d)\n";
   1767             break;
   1768         case MOVB_READ_RM_OPCODE:
   1769             format = "    MOV.B @R%d, R%d\n";
   1770             break;
   1771         case MOVB_READ_RMINC_OPCODE:
   1772             format = "    MOV.B @R%d+, R%d\n";
   1773             break;
   1774         case MOVB_READ_R0RM_OPCODE:
   1775             format = "    MOV.B @(R0, R%d), R%d\n";
   1776             break;
   1777         case MOVL_WRITE_RN_OPCODE:
   1778             format = "    MOV.L R%d, @R%d\n";
   1779             break;
   1780         case MOVL_WRITE_RNDEC_OPCODE:
   1781             format = "    MOV.L R%d, @-R%d\n";
   1782             break;
   1783         case MOVL_WRITE_R0RN_OPCODE:
   1784             format = "    MOV.L R%d, @(R0, R%d)\n";
   1785             break;
   1786         case MOVL_READ_RM_OPCODE:
   1787             format = "    MOV.L @R%d, R%d\n";
   1788             break;
   1789         case MOVL_READ_RMINC_OPCODE:
   1790             format = "    MOV.L @R%d+, R%d\n";
   1791             break;
   1792         case MOVL_READ_R0RM_OPCODE:
   1793             format = "    MOV.L @(R0, R%d), R%d\n";
   1794             break;
   1795         case MULL_OPCODE:
   1796             format = "    MUL.L R%d, R%d\n";
   1797             break;
   1798         case DMULL_L_OPCODE:
   1799             format = "    DMULU.L R%d, R%d\n";
   1800             break;
   1801         case DMULSL_OPCODE:
   1802             format = "    DMULS.L R%d, R%d\n";
   1803             break;
   1804         case NEG_OPCODE:
   1805             format = "    NEG R%d, R%d\n";
   1806             break;
   1807         case NEGC_OPCODE:
   1808             format = "    NEGC R%d, R%d\n";
   1809             break;
   1810         case NOT_OPCODE:
   1811             format = "    NOT R%d, R%d\n";
   1812             break;
   1813         case OR_OPCODE:
   1814             format = "    OR R%d, R%d\n";
   1815             break;
   1816         case SHAD_OPCODE:
   1817             format = "    SHAD R%d, R%d\n";
   1818             break;
   1819         case SHLD_OPCODE:
   1820             format = "    SHLD R%d, R%d\n";
   1821             break;
   1822         case SUB_OPCODE:
   1823             format = "    SUB R%d, R%d\n";
   1824             break;
   1825         case SUBC_OPCODE:
   1826             format = "    SUBC R%d, R%d\n";
   1827             break;
   1828         case SUBV_OPCODE:
   1829             format = "    SUBV R%d, R%d\n";
   1830             break;
   1831         case TST_OPCODE:
   1832             format = "    TST R%d, R%d\n";
   1833             break;
   1834         case XOR_OPCODE:
   1835             format = "    XOR R%d, R%d\n";break;
   1836         case MOVW_WRITE_RN_OPCODE:
   1837             format = "    MOV.W R%d, @R%d\n";
   1838             break;
   1839         case MOVW_READ_RM_OPCODE:
   1840             format = "    MOV.W @R%d, R%d\n";
   1841             break;
   1842         case MOVW_READ_R0RM_OPCODE:
   1843             format = "    MOV.W @(R0, R%d), R%d\n";
   1844             break;
   1845         case EXTUW_OPCODE:
   1846             format = "    EXTU.W R%d, R%d\n";
   1847             break;
   1848         }
   1849         if (format) {
   1850             printfStdoutInstr(format, getRm(opc), getRn(opc));
   1851             return;
   1852         }
   1853         switch (opc & 0xf00f) {
   1854         case FSUB_OPCODE:
   1855             format = "    FSUB FR%d, FR%d\n";
   1856             break;
   1857         case FADD_OPCODE:
   1858             format = "    FADD FR%d, FR%d\n";
   1859             break;
   1860         case FDIV_OPCODE:
   1861             format = "    FDIV FR%d, FR%d\n";
   1862             break;
   1863         case FMUL_OPCODE:
   1864             format = "    DMULL FR%d, FR%d\n";
   1865             break;
   1866         case FMOV_OPCODE:
   1867             format = "    FMOV FR%d, FR%d\n";
   1868             break;
   1869         case FCMPEQ_OPCODE:
   1870             format = "    FCMP/EQ FR%d, FR%d\n";
   1871             break;
   1872         case FCMPGT_OPCODE:
   1873             format = "    FCMP/GT FR%d, FR%d\n";
   1874             break;
   1875         }
   1876         if (format) {
   1877             if (isdoubleInst)
   1878                 printfStdoutInstr(format, getDRm(opc) << 1, getDRn(opc) << 1);
   1879             else
   1880                 printfStdoutInstr(format, getRm(opc), getRn(opc));
   1881             return;
   1882         }
   1883         switch (opc & 0xf00f) {
   1884         case FMOVS_WRITE_RN_DEC_OPCODE:
   1885             format = "    %s FR%d, @-R%d\n";
   1886             break;
   1887         case FMOVS_WRITE_RN_OPCODE:
   1888             format = "    %s FR%d, @R%d\n";
   1889             break;
   1890         case FMOVS_WRITE_R0RN_OPCODE:
   1891             format = "    %s FR%d, @(R0, R%d)\n";
   1892             break;
   1893         }
   1894         if (format) {
   1895             if (isdoubleInst)
   1896                 printfStdoutInstr(format, "FMOV", getDRm(opc) << 1, getDRn(opc));
   1897             else
   1898                 printfStdoutInstr(format, "FMOV.S", getRm(opc), getRn(opc));
   1899             return;
   1900         }
   1901         switch (opc & 0xf00f) {
   1902         case FMOVS_READ_RM_OPCODE:
   1903             format = "    %s @R%d, FR%d\n";
   1904             break;
   1905         case FMOVS_READ_RM_INC_OPCODE:
   1906             format = "    %s @R%d+, FR%d\n";
   1907             break;
   1908         case FMOVS_READ_R0RM_OPCODE:
   1909             format = "    %s @(R0, R%d), FR%d\n";
   1910             break;
   1911         }
   1912         if (format) {
   1913             if (isdoubleInst)
   1914                 printfStdoutInstr(format, "FMOV", getDRm(opc), getDRn(opc) << 1);
   1915             else
   1916                 printfStdoutInstr(format, "FMOV.S", getRm(opc), getRn(opc));
   1917             return;
   1918         }
   1919         switch (opc & 0xff00) {
   1920         case BF_OPCODE:
   1921             format = "    BF %d\n";
   1922             break;
   1923         case BFS_OPCODE:
   1924             format = "    *BF/S %d\n";
   1925             break;
   1926         case ANDIMM_OPCODE:
   1927             format = "    AND #%d, R0\n";
   1928             break;
   1929         case BT_OPCODE:
   1930             format = "    BT %d\n";
   1931             break;
   1932         case BTS_OPCODE:
   1933             format = "    *BT/S %d\n";
   1934             break;
   1935         case CMPEQIMM_OPCODE:
   1936             format = "    CMP/EQ #%d, R0\n";
   1937             break;
   1938         case MOVB_WRITE_OFFGBR_OPCODE:
   1939             format = "    MOV.B R0, @(%d, GBR)\n";
   1940             break;
   1941         case MOVB_READ_OFFGBR_OPCODE:
   1942             format = "    MOV.B @(%d, GBR), R0\n";
   1943             break;
   1944         case MOVL_WRITE_OFFGBR_OPCODE:
   1945             format = "    MOV.L R0, @(%d, GBR)\n";
   1946             break;
   1947         case MOVL_READ_OFFGBR_OPCODE:
   1948             format = "    MOV.L @(%d, GBR), R0\n";
   1949             break;
   1950         case MOVA_READ_OFFPC_OPCODE:
   1951             format = "    MOVA @(%d, PC), R0\n";
   1952             break;
   1953         case ORIMM_OPCODE:
   1954             format = "    OR #%d, R0\n";
   1955             break;
   1956         case ORBIMM_OPCODE:
   1957             format = "    OR.B #%d, @(R0, GBR)\n";
   1958             break;
   1959         case TSTIMM_OPCODE:
   1960             format = "    TST #%d, R0\n";
   1961             break;
   1962         case TSTB_OPCODE:
   1963             format = "    TST.B %d, @(R0, GBR)\n";
   1964             break;
   1965         case XORIMM_OPCODE:
   1966             format = "    XOR #%d, R0\n";
   1967             break;
   1968         case XORB_OPCODE:
   1969             format = "    XOR.B %d, @(R0, GBR)\n";
   1970             break;
   1971         }
   1972         if (format) {
   1973             printfStdoutInstr(format, getImm8(opc));
   1974             return;
   1975         }
   1976         switch (opc & 0xff00) {
   1977         case MOVB_WRITE_OFFRN_OPCODE:
   1978             format = "    MOV.B R0, @(%d, R%d)\n";
   1979             break;
   1980         case MOVB_READ_OFFRM_OPCODE:
   1981             format = "    MOV.B @(%d, R%d), R0\n";
   1982             break;
   1983         }
   1984         if (format) {
   1985             printfStdoutInstr(format, getDisp(opc), getRm(opc));
   1986             return;
   1987         }
   1988         switch (opc & 0xf000) {
   1989         case BRA_OPCODE:
   1990             format = "    *BRA %d\n";
   1991             break;
   1992         case BSR_OPCODE:
   1993             format = "    *BSR %d\n";
   1994             break;
   1995         }
   1996         if (format) {
   1997             printfStdoutInstr(format, getImm12(opc));
   1998             return;
   1999         }
   2000         switch (opc & 0xf000) {
   2001         case MOVL_READ_OFFPC_OPCODE:
   2002             format = "    MOV.L @(%d, PC), R%d\n";
   2003             break;
   2004         case ADDIMM_OPCODE:
   2005             format = "    ADD #%d, R%d\n";
   2006             break;
   2007         case MOVIMM_OPCODE:
   2008             format = "    MOV #%d, R%d\n";
   2009             break;
   2010         case MOVW_READ_OFFPC_OPCODE:
   2011             format = "    MOV.W @(%d, PC), R%d\n";
   2012             break;
   2013         }
   2014         if (format) {
   2015             printfStdoutInstr(format, getImm8(opc), getRn(opc));
   2016             return;
   2017         }
   2018         switch (opc & 0xf000) {
   2019         case MOVL_WRITE_OFFRN_OPCODE:
   2020             format = "    MOV.L R%d, @(%d, R%d)\n";
   2021             printfStdoutInstr(format, getRm(opc), getDisp(opc), getRn(opc));
   2022             break;
   2023         case MOVL_READ_OFFRM_OPCODE:
   2024             format = "    MOV.L @(%d, R%d), R%d\n";
   2025             printfStdoutInstr(format, getDisp(opc), getRm(opc), getRn(opc));
   2026             break;
   2027         }
   2028     }
   2029 
   2030     static void printfStdoutInstr(const char* format, ...)
   2031     {
   2032         if (getenv("JavaScriptCoreDumpJIT")) {
   2033             va_list args;
   2034             va_start(args, format);
   2035             vprintfStdoutInstr(format, args);
   2036             va_end(args);
   2037         }
   2038     }
   2039 
   2040     static void vprintfStdoutInstr(const char* format, va_list args)
   2041     {
   2042         if (getenv("JavaScriptCoreDumpJIT"))
   2043             vfprintf(stdout, format, args);
   2044     }
   2045 
   2046     static void printBlockInstr(uint16_t* first, unsigned int offset, int nbInstr)
   2047     {
   2048         printfStdoutInstr(">> repatch instructions after link\n");
   2049         for (int i = 0; i <= nbInstr; i++)
   2050            printInstr(*(first + i), offset + i);
   2051         printfStdoutInstr(">> end repatch\n");
   2052     }
   2053 #else
   2054     static void printInstr(uint16_t opc, unsigned int size, bool isdoubleInst = true) {};
   2055     static void printBlockInstr(uint16_t* first, unsigned int offset, int nbInstr) {};
   2056 #endif
   2057 
   2058 private:
   2059     SH4Buffer m_buffer;
   2060     int m_claimscratchReg;
   2061 };
   2062 
   2063 } // namespace JSC
   2064 
   2065 #endif // ENABLE(ASSEMBLER) && CPU(SH4)
   2066 
   2067 #endif // SH4Assembler_h
   2068