]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - assembler/SH4Assembler.h
JavaScriptCore-903.tar.gz
[apple/javascriptcore.git] / assembler / SH4Assembler.h
diff --git a/assembler/SH4Assembler.h b/assembler/SH4Assembler.h
new file mode 100644 (file)
index 0000000..1d089e5
--- /dev/null
@@ -0,0 +1,2026 @@
+/*
+ * Copyright (C) 2009-2011 STMicroelectronics. All rights reserved.
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SH4Assembler_h
+#define SH4Assembler_h
+
+#if ENABLE(ASSEMBLER) && CPU(SH4)
+
+#include "AssemblerBuffer.h"
+#include "AssemblerBufferWithConstantPool.h"
+#include <stdarg.h>
+#include <stdint.h>
+#include <wtf/Assertions.h>
+#include <wtf/Vector.h>
+
+#ifndef NDEBUG
+#define SH4_ASSEMBLER_TRACING
+#endif
+
+namespace JSC {
+typedef uint16_t SH4Word;
+
+enum {
+    INVALID_OPCODE = 0xffff,
+    ADD_OPCODE = 0x300c,
+    ADDIMM_OPCODE = 0x7000,
+    ADDC_OPCODE = 0x300e,
+    ADDV_OPCODE = 0x300f,
+    AND_OPCODE = 0x2009,
+    ANDIMM_OPCODE = 0xc900,
+    DIV0_OPCODE = 0x2007,
+    DIV1_OPCODE = 0x3004,
+    BF_OPCODE = 0x8b00,
+    BFS_OPCODE = 0x8f00,
+    BRA_OPCODE = 0xa000,
+    BRAF_OPCODE = 0x0023,
+    NOP_OPCODE = 0x0009,
+    BSR_OPCODE = 0xb000,
+    RTS_OPCODE = 0x000b,
+    BT_OPCODE = 0x8900,
+    BTS_OPCODE = 0x8d00,
+    BSRF_OPCODE = 0x0003,
+    BRK_OPCODE = 0x003b,
+    FTRC_OPCODE = 0xf03d,
+    CMPEQ_OPCODE = 0x3000,
+    CMPEQIMM_OPCODE = 0x8800,
+    CMPGE_OPCODE = 0x3003,
+    CMPGT_OPCODE = 0x3007,
+    CMPHI_OPCODE = 0x3006,
+    CMPHS_OPCODE = 0x3002,
+    CMPPL_OPCODE = 0x4015,
+    CMPPZ_OPCODE = 0x4011,
+    CMPSTR_OPCODE = 0x200c,
+    DT_OPCODE = 0x4010,
+    FCMPEQ_OPCODE = 0xf004,
+    FCMPGT_OPCODE = 0xf005,
+    FMOV_OPCODE = 0xf00c,
+    FADD_OPCODE = 0xf000,
+    FMUL_OPCODE = 0xf002,
+    FSUB_OPCODE = 0xf001,
+    FDIV_OPCODE = 0xf003,
+    FNEG_OPCODE = 0xf04d,
+    JMP_OPCODE = 0x402b,
+    JSR_OPCODE = 0x400b,
+    LDSPR_OPCODE = 0x402a,
+    LDSLPR_OPCODE = 0x4026,
+    MOV_OPCODE = 0x6003,
+    MOVIMM_OPCODE = 0xe000,
+    MOVB_WRITE_RN_OPCODE = 0x2000,
+    MOVB_WRITE_RNDEC_OPCODE = 0x2004,
+    MOVB_WRITE_R0RN_OPCODE = 0x0004,
+    MOVB_WRITE_OFFGBR_OPCODE = 0xc000,
+    MOVB_WRITE_OFFRN_OPCODE = 0x8000,
+    MOVB_READ_RM_OPCODE = 0x6000,
+    MOVB_READ_RMINC_OPCODE = 0x6004,
+    MOVB_READ_R0RM_OPCODE = 0x000c,
+    MOVB_READ_OFFGBR_OPCODE = 0xc400,
+    MOVB_READ_OFFRM_OPCODE = 0x8400,
+    MOVL_WRITE_RN_OPCODE = 0x2002,
+    MOVL_WRITE_RNDEC_OPCODE = 0x2006,
+    MOVL_WRITE_R0RN_OPCODE = 0x0006,
+    MOVL_WRITE_OFFGBR_OPCODE = 0xc200,
+    MOVL_WRITE_OFFRN_OPCODE = 0x1000,
+    MOVL_READ_RM_OPCODE = 0x6002,
+    MOVL_READ_RMINC_OPCODE = 0x6006,
+    MOVL_READ_R0RM_OPCODE = 0x000e,
+    MOVL_READ_OFFGBR_OPCODE = 0xc600,
+    MOVL_READ_OFFPC_OPCODE = 0xd000,
+    MOVL_READ_OFFRM_OPCODE = 0x5000,
+    MOVW_WRITE_RN_OPCODE = 0x2001,
+    MOVW_READ_RM_OPCODE = 0x6001,
+    MOVW_READ_R0RM_OPCODE = 0x000d,
+    MOVW_READ_OFFRM_OPCODE = 0x8500,
+    MOVW_READ_OFFPC_OPCODE = 0x9000,
+    MOVA_READ_OFFPC_OPCODE = 0xc700,
+    MOVT_OPCODE = 0x0029,
+    MULL_OPCODE = 0x0007,
+    DMULL_L_OPCODE = 0x3005,
+    STSMACL_OPCODE = 0x001a,
+    STSMACH_OPCODE = 0x000a,
+    DMULSL_OPCODE = 0x300d,
+    NEG_OPCODE = 0x600b,
+    NEGC_OPCODE = 0x600a,
+    NOT_OPCODE = 0x6007,
+    OR_OPCODE = 0x200b,
+    ORIMM_OPCODE = 0xcb00,
+    ORBIMM_OPCODE = 0xcf00,
+    SETS_OPCODE = 0x0058,
+    SETT_OPCODE = 0x0018,
+    SHAD_OPCODE = 0x400c,
+    SHAL_OPCODE = 0x4020,
+    SHAR_OPCODE = 0x4021,
+    SHLD_OPCODE = 0x400d,
+    SHLL_OPCODE = 0x4000,
+    SHLL2_OPCODE = 0x4008,
+    SHLL8_OPCODE = 0x4018,
+    SHLL16_OPCODE = 0x4028,
+    SHLR_OPCODE = 0x4001,
+    SHLR2_OPCODE = 0x4009,
+    SHLR8_OPCODE = 0x4019,
+    SHLR16_OPCODE = 0x4029,
+    STSPR_OPCODE = 0x002a,
+    STSLPR_OPCODE = 0x4022,
+    FLOAT_OPCODE = 0xf02d,
+    SUB_OPCODE = 0x3008,
+    SUBC_OPCODE = 0x300a,
+    SUBV_OPCODE = 0x300b,
+    TST_OPCODE = 0x2008,
+    TSTIMM_OPCODE = 0xc800,
+    TSTB_OPCODE = 0xcc00,
+    EXTUW_OPCODE = 0x600d,
+    XOR_OPCODE = 0x200a,
+    XORIMM_OPCODE = 0xca00,
+    XORB_OPCODE = 0xce00,
+    FMOVS_READ_RM_INC_OPCODE = 0xf009,
+    FMOVS_READ_RM_OPCODE = 0xf008,
+    FMOVS_READ_R0RM_OPCODE = 0xf006,
+    FMOVS_WRITE_RN_OPCODE = 0xf00a,
+    FMOVS_WRITE_RN_DEC_OPCODE = 0xf00b,
+    FMOVS_WRITE_R0RN_OPCODE = 0xf007,
+    FCNVDS_DRM_FPUL_OPCODE = 0xf0bd,
+    LDS_RM_FPUL_OPCODE = 0x405a,
+    FLDS_FRM_FPUL_OPCODE = 0xf01d,
+    STS_FPUL_RN_OPCODE = 0x005a,
+    FSTS_FPUL_FRN_OPCODE = 0xF00d,
+    LDSFPSCR_OPCODE = 0x406a,
+    STSFPSCR_OPCODE = 0x006a,
+    LDSRMFPUL_OPCODE = 0x405a,
+    FSTSFPULFRN_OPCODE = 0xf00d,
+    FSQRT_OPCODE = 0xf06d,
+    FSCHG_OPCODE = 0xf3fd,
+    CLRT_OPCODE = 8,
+};
+
+namespace SH4Registers {
+typedef enum {
+    r0,
+    r1,
+    r2,
+    r3,
+    r4,
+    r5,
+    r6,
+    r7,
+    r8,
+    r9,
+    r10,
+    r11,
+    r12,
+    r13,
+    r14, fp = r14,
+    r15, sp = r15,
+    pc,
+    pr,
+} RegisterID;
+
+typedef enum {
+    fr0, dr0 = fr0,
+    fr1,
+    fr2, dr2 = fr2,
+    fr3,
+    fr4, dr4 = fr4,
+    fr5,
+    fr6, dr6 = fr6,
+    fr7,
+    fr8, dr8 = fr8,
+    fr9,
+    fr10, dr10 = fr10,
+    fr11,
+    fr12, dr12 = fr12,
+    fr13,
+    fr14, dr14 = fr14,
+    fr15,
+} FPRegisterID;
+}
+
+inline uint16_t getOpcodeGroup1(uint16_t opc, int rm, int rn)
+{
+    return (opc | ((rm & 0xf) << 8) | ((rn & 0xf) << 4));
+}
+
+inline uint16_t getOpcodeGroup2(uint16_t opc, int rm)
+{
+    return (opc | ((rm & 0xf) << 8));
+}
+
+inline uint16_t getOpcodeGroup3(uint16_t opc, int rm, int rn)
+{
+    return (opc | ((rm & 0xf) << 8) | (rn & 0xff));
+}
+
+inline uint16_t getOpcodeGroup4(uint16_t opc, int rm, int rn, int offset)
+{
+    return (opc | ((rm & 0xf) << 8) | ((rn & 0xf) << 4) | (offset & 0xf));
+}
+
+inline uint16_t getOpcodeGroup5(uint16_t opc, int rm)
+{
+    return (opc | (rm & 0xff));
+}
+
+inline uint16_t getOpcodeGroup6(uint16_t opc, int rm)
+{
+    return (opc | (rm & 0xfff));
+}
+
+inline uint16_t getOpcodeGroup7(uint16_t opc, int rm)
+{
+    return (opc | ((rm & 0x7) << 9));
+}
+
+inline uint16_t getOpcodeGroup8(uint16_t opc, int rm, int rn)
+{
+    return (opc | ((rm & 0x7) << 9) | ((rn & 0x7) << 5));
+}
+
+inline uint16_t getOpcodeGroup9(uint16_t opc, int rm, int rn)
+{
+    return (opc | ((rm & 0xf) << 8) | ((rn & 0x7) << 5));
+}
+
+inline uint16_t getOpcodeGroup10(uint16_t opc, int rm, int rn)
+{
+    return (opc | ((rm & 0x7) << 9) | ((rn & 0xf) << 4));
+}
+
+inline uint16_t getOpcodeGroup11(uint16_t opc, int rm, int rn)
+{
+    return (opc | ((rm & 0xf) << 4) | (rn & 0xf));
+}
+
+inline uint16_t getRn(uint16_t x)
+{
+    return ((x & 0xf00) >> 8);
+}
+
+inline uint16_t getRm(uint16_t x)
+{
+    return ((x & 0xf0) >> 4);
+}
+
+inline uint16_t getDisp(uint16_t x)
+{
+    return (x & 0xf);
+}
+
+inline uint16_t getImm8(uint16_t x)
+{
+    return (x & 0xff);
+}
+
+inline uint16_t getImm12(uint16_t x)
+{
+    return (x & 0xfff);
+}
+
+inline uint16_t getDRn(uint16_t x)
+{
+    return ((x & 0xe00) >> 9);
+}
+
+inline uint16_t getDRm(uint16_t x)
+{
+    return ((x & 0xe0) >> 5);
+}
+
+class SH4Assembler {
+public:
+    typedef SH4Registers::RegisterID RegisterID;
+    typedef SH4Registers::FPRegisterID FPRegisterID;
+    typedef AssemblerBufferWithConstantPool<512, 4, 2, SH4Assembler> SH4Buffer;
+    static const RegisterID scratchReg1 = SH4Registers::r3;
+    static const RegisterID scratchReg2 = SH4Registers::r11;
+    static const uint32_t maxInstructionSize = 16;
+
+    enum {
+        padForAlign8 = 0x00,
+        padForAlign16 = 0x0009,
+        padForAlign32 = 0x00090009,
+    };
+
+    SH4Assembler()
+    {
+        m_claimscratchReg = 0x0;
+    }
+
+    // SH4 condition codes
+    typedef enum {
+        EQ = 0x0, // Equal
+        NE = 0x1, // Not Equal
+        HS = 0x2, // Unsigend Greater Than equal
+        HI = 0x3, // Unsigend Greater Than
+        LS = 0x4, // Unsigend Lower or Same
+        LI = 0x5, // Unsigend Lower
+        GE = 0x6, // Greater or Equal
+        LT = 0x7, // Less Than
+        GT = 0x8, // Greater Than
+        LE = 0x9, // Less or Equal
+        OF = 0xa, // OverFlow
+        SI = 0xb, // Signed
+        EQU= 0xc, // Equal or unordered(NaN)
+        NEU= 0xd,
+        GTU= 0xe,
+        GEU= 0xf,
+        LTU= 0x10,
+        LEU= 0x11,
+    } Condition;
+
+    // Opaque label types
+public:
+    bool isImmediate(int constant)
+    {
+        return ((constant <= 127) && (constant >= -128));
+    }
+
+    RegisterID claimScratch()
+    {
+        ASSERT((m_claimscratchReg != 0x3));
+
+        if (!(m_claimscratchReg & 0x1)) {
+            m_claimscratchReg = (m_claimscratchReg | 0x1);
+            return scratchReg1;
+        }
+
+        m_claimscratchReg = (m_claimscratchReg | 0x2);
+        return scratchReg2;
+    }
+
+    void releaseScratch(RegisterID scratchR)
+    {
+        if (scratchR == scratchReg1)
+            m_claimscratchReg = (m_claimscratchReg & 0x2);
+        else
+            m_claimscratchReg = (m_claimscratchReg & 0x1);
+    }
+
+    // Stack operations
+
+    void pushReg(RegisterID reg)
+    {
+        if (reg == SH4Registers::pr) {
+            oneShortOp(getOpcodeGroup2(STSLPR_OPCODE, SH4Registers::sp));
+            return;
+        }
+
+        oneShortOp(getOpcodeGroup1(MOVL_WRITE_RNDEC_OPCODE, SH4Registers::sp, reg));
+    }
+
+    void popReg(RegisterID reg)
+    {
+        if (reg == SH4Registers::pr) {
+            oneShortOp(getOpcodeGroup2(LDSLPR_OPCODE, SH4Registers::sp));
+            return;
+        }
+
+        oneShortOp(getOpcodeGroup1(MOVL_READ_RMINC_OPCODE, reg, SH4Registers::sp));
+    }
+
+    void movt(RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup2(MOVT_OPCODE, dst);
+        oneShortOp(opc);
+    }
+
+    // Arithmetic operations
+
+    void addlRegReg(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(ADD_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void addclRegReg(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(ADDC_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void addvlRegReg(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(ADDV_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void addlImm8r(int imm8, RegisterID dst)
+    {
+        ASSERT((imm8 <= 127) && (imm8 >= -128));
+
+        uint16_t opc = getOpcodeGroup3(ADDIMM_OPCODE, dst, imm8);
+        oneShortOp(opc);
+    }
+
+    void andlRegReg(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(AND_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void andlImm8r(int imm8, RegisterID dst)
+    {
+        ASSERT((imm8 <= 255) && (imm8 >= 0));
+        ASSERT(dst == SH4Registers::r0);
+
+        uint16_t opc = getOpcodeGroup5(ANDIMM_OPCODE, imm8);
+        oneShortOp(opc);
+    }
+
+    void div1lRegReg(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(DIV1_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void div0lRegReg(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(DIV0_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void notlReg(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(NOT_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void orlRegReg(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(OR_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void orlImm8r(int imm8, RegisterID dst)
+    {
+        ASSERT((imm8 <= 255) && (imm8 >= 0));
+        ASSERT(dst == SH4Registers::r0);
+
+        uint16_t opc = getOpcodeGroup5(ORIMM_OPCODE, imm8);
+        oneShortOp(opc);
+    }
+
+    void sublRegReg(RegisterID src, RegisterID dst)
+    {
+         uint16_t opc = getOpcodeGroup1(SUB_OPCODE, dst, src);
+         oneShortOp(opc);
+    }
+
+    void subvlRegReg(RegisterID src, RegisterID dst)
+    {
+         uint16_t opc = getOpcodeGroup1(SUBV_OPCODE, dst, src);
+         oneShortOp(opc);
+    }
+
+    void xorlRegReg(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(XOR_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void xorlImm8r(int imm8, RegisterID dst)
+    {
+        ASSERT((imm8 <= 255) && (imm8 >= 0));
+        ASSERT(dst == SH4Registers::r0);
+
+        uint16_t opc = getOpcodeGroup5(XORIMM_OPCODE, imm8);
+        oneShortOp(opc);
+    }
+
+    void shllImm8r(int imm, RegisterID dst)
+    {
+        switch (imm) {
+        case 1:
+            oneShortOp(getOpcodeGroup2(SHLL_OPCODE, dst));
+            break;
+        case 2:
+            oneShortOp(getOpcodeGroup2(SHLL2_OPCODE, dst));
+            break;
+        case 8:
+            oneShortOp(getOpcodeGroup2(SHLL8_OPCODE, dst));
+            break;
+        case 16:
+            oneShortOp(getOpcodeGroup2(SHLL16_OPCODE, dst));
+            break;
+        default:
+            ASSERT_NOT_REACHED();
+        }
+    }
+
+    void neg(RegisterID dst, RegisterID src)
+    {
+        uint16_t opc = getOpcodeGroup1(NEG_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void shllRegReg(RegisterID dst, RegisterID rShift)
+    {
+        uint16_t opc = getOpcodeGroup1(SHLD_OPCODE, dst, rShift);
+        oneShortOp(opc);
+    }
+
+    void shlrRegReg(RegisterID dst, RegisterID rShift)
+    {
+        neg(rShift, rShift);
+        shllRegReg(dst, rShift);
+    }
+
+    void sharRegReg(RegisterID dst, RegisterID rShift)
+    {
+        neg(rShift, rShift);
+        shaRegReg(dst, rShift);
+    }
+
+    void shaRegReg(RegisterID dst, RegisterID rShift)
+    {
+        uint16_t opc = getOpcodeGroup1(SHAD_OPCODE, dst, rShift);
+        oneShortOp(opc);
+    }
+
+    void shlrImm8r(int imm, RegisterID dst)
+    {
+        switch (imm) {
+        case 1:
+            oneShortOp(getOpcodeGroup2(SHLR_OPCODE, dst));
+            break;
+        case 2:
+            oneShortOp(getOpcodeGroup2(SHLR2_OPCODE, dst));
+            break;
+        case 8:
+            oneShortOp(getOpcodeGroup2(SHLR8_OPCODE, dst));
+            break;
+        case 16:
+            oneShortOp(getOpcodeGroup2(SHLR16_OPCODE, dst));
+            break;
+        default:
+            ASSERT_NOT_REACHED();
+        }
+    }
+
+    void imullRegReg(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(MULL_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void dmullRegReg(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(DMULL_L_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void dmulslRegReg(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(DMULSL_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void stsmacl(RegisterID reg)
+    {
+        uint16_t opc = getOpcodeGroup2(STSMACL_OPCODE, reg);
+        oneShortOp(opc);
+    }
+
+    void stsmach(RegisterID reg)
+    {
+        uint16_t opc = getOpcodeGroup2(STSMACH_OPCODE, reg);
+        oneShortOp(opc);
+    }
+
+    // Comparisons
+
+    void cmplRegReg(RegisterID left, RegisterID right, Condition cond)
+    {
+        switch (cond) {
+        case NE:
+            oneShortOp(getOpcodeGroup1(CMPEQ_OPCODE, right, left));
+            break;
+        case GT:
+            oneShortOp(getOpcodeGroup1(CMPGT_OPCODE, right, left));
+            break;
+        case EQ:
+            oneShortOp(getOpcodeGroup1(CMPEQ_OPCODE, right, left));
+            break;
+        case GE:
+            oneShortOp(getOpcodeGroup1(CMPGE_OPCODE, right, left));
+            break;
+        case HS:
+            oneShortOp(getOpcodeGroup1(CMPHS_OPCODE, right, left));
+            break;
+        case HI:
+            oneShortOp(getOpcodeGroup1(CMPHI_OPCODE, right, left));
+            break;
+        case LI:
+            oneShortOp(getOpcodeGroup1(CMPHI_OPCODE, left, right));
+            break;
+        case LS:
+            oneShortOp(getOpcodeGroup1(CMPHS_OPCODE, left, right));
+            break;
+        case LE:
+            oneShortOp(getOpcodeGroup1(CMPGE_OPCODE, left, right));
+            break;
+        case LT:
+            oneShortOp(getOpcodeGroup1(CMPGT_OPCODE, left, right));
+            break;
+        default:
+            ASSERT_NOT_REACHED();
+        }
+    }
+
+    void cmppl(RegisterID reg)
+    {
+        uint16_t opc = getOpcodeGroup2(CMPPL_OPCODE, reg);
+        oneShortOp(opc);
+    }
+
+    void cmppz(RegisterID reg)
+    {
+        uint16_t opc = getOpcodeGroup2(CMPPZ_OPCODE, reg);
+        oneShortOp(opc);
+    }
+
+    void cmpEqImmR0(int imm, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup5(CMPEQIMM_OPCODE, imm);
+        oneShortOp(opc);
+    }
+
+    void testlRegReg(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(TST_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void testlImm8r(int imm, RegisterID dst)
+    {
+        ASSERT((dst == SH4Registers::r0) && (imm <= 255) && (imm >= 0));
+
+        uint16_t opc = getOpcodeGroup5(TSTIMM_OPCODE, imm);
+        oneShortOp(opc);
+    }
+
+    void nop()
+    {
+        oneShortOp(NOP_OPCODE, false);
+    }
+
+    void sett()
+    {
+        oneShortOp(SETT_OPCODE);
+    }
+
+    void clrt()
+    {
+        oneShortOp(CLRT_OPCODE);
+    }
+
+    void fschg()
+    {
+        oneShortOp(FSCHG_OPCODE);
+    }
+
+    void bkpt()
+    {
+        oneShortOp(BRK_OPCODE, false);
+    }
+
+    void branch(uint16_t opc, int label)
+    {
+        switch (opc) {
+        case BT_OPCODE:
+            ASSERT((label <= 127) && (label >= -128));
+            oneShortOp(getOpcodeGroup5(BT_OPCODE, label));
+            break;
+        case BRA_OPCODE:
+            ASSERT((label <= 2047) && (label >= -2048));
+            oneShortOp(getOpcodeGroup6(BRA_OPCODE, label));
+            break;
+        case BF_OPCODE:
+            ASSERT((label <= 127) && (label >= -128));
+            oneShortOp(getOpcodeGroup5(BF_OPCODE, label));
+            break;
+        default:
+            ASSERT_NOT_REACHED();
+        }
+    }
+
+    void branch(uint16_t opc, RegisterID reg)
+    {
+        switch (opc) {
+        case BRAF_OPCODE:
+            oneShortOp(getOpcodeGroup2(BRAF_OPCODE, reg));
+            break;
+        case JMP_OPCODE:
+            oneShortOp(getOpcodeGroup2(JMP_OPCODE, reg));
+            break;
+        case JSR_OPCODE:
+            oneShortOp(getOpcodeGroup2(JSR_OPCODE, reg));
+            break;
+        case BSRF_OPCODE:
+            oneShortOp(getOpcodeGroup2(BSRF_OPCODE, reg));
+            break;
+        default:
+            ASSERT_NOT_REACHED();
+        }
+    }
+
+    void ldspr(RegisterID reg)
+    {
+        uint16_t opc = getOpcodeGroup2(LDSPR_OPCODE, reg);
+        oneShortOp(opc);
+    }
+
+    void stspr(RegisterID reg)
+    {
+        uint16_t opc = getOpcodeGroup2(STSPR_OPCODE, reg);
+        oneShortOp(opc);
+    }
+
+    void extuw(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(EXTUW_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    // float operations
+
+    void ldsrmfpul(RegisterID src)
+    {
+        uint16_t opc = getOpcodeGroup2(LDS_RM_FPUL_OPCODE, src);
+        oneShortOp(opc);
+    }
+
+    void fneg(FPRegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup2(FNEG_OPCODE, dst);
+        oneShortOp(opc, true, false);
+    }
+
+    void fsqrt(FPRegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup2(FSQRT_OPCODE, dst);
+        oneShortOp(opc, true, false);
+    }
+
+    void stsfpulReg(RegisterID src)
+    {
+        uint16_t opc = getOpcodeGroup2(STS_FPUL_RN_OPCODE, src);
+        oneShortOp(opc);
+    }
+
+    void floatfpulfrn(RegisterID src)
+    {
+        uint16_t opc = getOpcodeGroup2(FLOAT_OPCODE, src);
+        oneShortOp(opc, true, false);
+    }
+
+    void fmull(FPRegisterID src, FPRegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(FMUL_OPCODE, dst, src);
+        oneShortOp(opc, true, false);
+    }
+
+    void fmovsReadrm(RegisterID src, FPRegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(FMOVS_READ_RM_OPCODE, dst, src);
+        oneShortOp(opc, true, false);
+    }
+
+    void fmovsWriterm(FPRegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(FMOVS_WRITE_RN_OPCODE, dst, src);
+        oneShortOp(opc, true, false);
+    }
+
+    void fmovsWriter0r(FPRegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(FMOVS_WRITE_R0RN_OPCODE, dst, src);
+        oneShortOp(opc, true, false);
+    }
+
+    void fmovsReadr0r(RegisterID src, FPRegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(FMOVS_READ_R0RM_OPCODE, dst, src);
+        oneShortOp(opc, true, false);
+    }
+
+    void fmovsReadrminc(RegisterID src, FPRegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(FMOVS_READ_RM_INC_OPCODE, dst, src);
+        oneShortOp(opc, true, false);
+    }
+
+    void fmovsWriterndec(FPRegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(FMOVS_WRITE_RN_DEC_OPCODE, dst, src);
+        oneShortOp(opc, true, false);
+    }
+
+    void ftrcRegfpul(FPRegisterID src)
+    {
+        uint16_t opc = getOpcodeGroup2(FTRC_OPCODE, src);
+        oneShortOp(opc, true, false);
+    }
+
+    void fldsfpul(RegisterID src)
+    {
+        uint16_t opc = getOpcodeGroup2(FLDS_FRM_FPUL_OPCODE, src);
+        oneShortOp(opc);
+    }
+
+    void fstsfpul(RegisterID src)
+    {
+        uint16_t opc = getOpcodeGroup2(FSTS_FPUL_FRN_OPCODE, src);
+        oneShortOp(opc);
+    }
+
+    void ldsfpscr(RegisterID reg)
+    {
+        uint16_t opc = getOpcodeGroup2(LDSFPSCR_OPCODE, reg);
+        oneShortOp(opc);
+    }
+
+    void stsfpscr(RegisterID reg)
+    {
+        uint16_t opc = getOpcodeGroup2(STSFPSCR_OPCODE, reg);
+        oneShortOp(opc);
+    }
+
+    // double operations
+
+    void dcnvds(FPRegisterID src)
+    {
+        uint16_t opc = getOpcodeGroup7(FCNVDS_DRM_FPUL_OPCODE, src >> 1);
+        oneShortOp(opc);
+    }
+
+    void dcmppeq(FPRegisterID src, FPRegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup8(FCMPEQ_OPCODE, dst >> 1, src >> 1);
+        oneShortOp(opc);
+    }
+
+    void dcmppgt(FPRegisterID src, FPRegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup8(FCMPGT_OPCODE, dst >> 1, src >> 1);
+        oneShortOp(opc);
+    }
+
+    void dmulRegReg(FPRegisterID src, FPRegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup8(FMUL_OPCODE, dst >> 1, src >> 1);
+        oneShortOp(opc);
+    }
+
+    void dsubRegReg(FPRegisterID src, FPRegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup8(FSUB_OPCODE, dst >> 1, src >> 1);
+        oneShortOp(opc);
+    }
+
+    void daddRegReg(FPRegisterID src, FPRegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup8(FADD_OPCODE, dst >> 1, src >> 1);
+        oneShortOp(opc);
+    }
+
+    void dmovRegReg(FPRegisterID src, FPRegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup8(FMOV_OPCODE, dst >> 1, src >> 1);
+        oneShortOp(opc);
+    }
+
+    void ddivRegReg(FPRegisterID src, FPRegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup8(FDIV_OPCODE, dst >> 1, src >> 1);
+        oneShortOp(opc);
+    }
+
+    void dsqrt(FPRegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup7(FSQRT_OPCODE, dst >> 1);
+        oneShortOp(opc);
+    }
+
+    void dneg(FPRegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup7(FNEG_OPCODE, dst >> 1);
+        oneShortOp(opc);
+    }
+
+    void fmovReadrm(RegisterID src, FPRegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup10(FMOVS_READ_RM_OPCODE, dst >> 1, src);
+        oneShortOp(opc);
+    }
+
+    void fmovWriterm(FPRegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup9(FMOVS_WRITE_RN_OPCODE, dst, src >> 1);
+        oneShortOp(opc);
+    }
+
+    void fmovWriter0r(FPRegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup9(FMOVS_WRITE_R0RN_OPCODE, dst, src >> 1);
+        oneShortOp(opc);
+    }
+
+    void fmovReadr0r(RegisterID src, FPRegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup10(FMOVS_READ_R0RM_OPCODE, dst >> 1, src);
+        oneShortOp(opc);
+    }
+
+    void fmovReadrminc(RegisterID src, FPRegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup10(FMOVS_READ_RM_INC_OPCODE, dst >> 1, src);
+        oneShortOp(opc);
+    }
+
+    void fmovWriterndec(FPRegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup9(FMOVS_WRITE_RN_DEC_OPCODE, dst, src >> 1);
+        oneShortOp(opc);
+    }
+
+    void floatfpulDreg(FPRegisterID src)
+    {
+        uint16_t opc = getOpcodeGroup7(FLOAT_OPCODE, src >> 1);
+        oneShortOp(opc);
+    }
+
+    void ftrcdrmfpul(FPRegisterID src)
+    {
+        uint16_t opc = getOpcodeGroup7(FTRC_OPCODE, src >> 1);
+        oneShortOp(opc);
+    }
+
+    // Various move ops
+
+    void movImm8(int imm8, RegisterID dst)
+    {
+        ASSERT((imm8 <= 127) && (imm8 >= -128));
+
+        uint16_t opc = getOpcodeGroup3(MOVIMM_OPCODE, dst, imm8);
+        oneShortOp(opc);
+    }
+
+    void movlRegReg(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(MOV_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void movwRegMem(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(MOVW_WRITE_RN_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void movwMemReg(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(MOVW_READ_RM_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void movwPCReg(int offset, RegisterID base, RegisterID dst)
+    {
+        ASSERT(base == SH4Registers::pc);
+        ASSERT((offset <= 255) && (offset >= 0));
+
+        uint16_t opc = getOpcodeGroup3(MOVW_READ_OFFPC_OPCODE, dst, offset);
+        oneShortOp(opc);
+    }
+
+    void movwMemReg(int offset, RegisterID base, RegisterID dst)
+    {
+        ASSERT(dst == SH4Registers::r0);
+
+        uint16_t opc = getOpcodeGroup11(MOVW_READ_OFFRM_OPCODE, base, offset);
+        oneShortOp(opc);
+    }
+
+    void movwR0mr(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(MOVW_READ_R0RM_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void movlRegMem(RegisterID src, int offset, RegisterID base)
+    {
+        ASSERT((offset <= 15) && (offset >= 0));
+
+        if (!offset) {
+            oneShortOp(getOpcodeGroup1(MOVL_WRITE_RN_OPCODE, base, src));
+            return;
+        }
+
+        oneShortOp(getOpcodeGroup4(MOVL_WRITE_OFFRN_OPCODE, base, src, offset));
+    }
+
+    void movlRegMem(RegisterID src, RegisterID base)
+    {
+        uint16_t opc = getOpcodeGroup1(MOVL_WRITE_RN_OPCODE, base, src);
+        oneShortOp(opc);
+    }
+
+    void movlMemReg(int offset, RegisterID base, RegisterID dst)
+    {
+        if (base == SH4Registers::pc) {
+            ASSERT((offset <= 255) && (offset >= 0));
+            oneShortOp(getOpcodeGroup3(MOVL_READ_OFFPC_OPCODE, dst, offset));
+            return;
+        }
+
+        ASSERT((offset <= 15) && (offset >= 0));
+        if (!offset) {
+            oneShortOp(getOpcodeGroup1(MOVL_READ_RM_OPCODE, dst, base));
+            return;
+        }
+
+        oneShortOp(getOpcodeGroup4(MOVL_READ_OFFRM_OPCODE, dst, base, offset));
+    }
+
+    void movbMemReg(int offset, RegisterID base, RegisterID dst)
+    {
+        ASSERT(dst == SH4Registers::r0);
+
+        uint16_t opc = getOpcodeGroup11(MOVB_READ_OFFRM_OPCODE, base, offset);
+        oneShortOp(opc);
+    }
+
+    void movbR0mr(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(MOVB_READ_R0RM_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void movbMemReg(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(MOVB_READ_RM_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void movlMemReg(RegisterID base, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(MOVL_READ_RM_OPCODE, dst, base);
+        oneShortOp(opc);
+    }
+
+    void movlMemRegIn(RegisterID base, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(MOVL_READ_RMINC_OPCODE, dst, base);
+        oneShortOp(opc);
+    }
+
+    void movlR0mr(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(MOVL_READ_R0RM_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void movlRegMemr0(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(MOVL_WRITE_R0RN_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void movlImm8r(int imm8, RegisterID dst)
+    {
+        ASSERT((imm8 <= 127) && (imm8 >= -128));
+
+        uint16_t opc = getOpcodeGroup3(MOVIMM_OPCODE, dst, imm8);
+        oneShortOp(opc);
+    }
+
+    void loadConstant(uint32_t constant, RegisterID dst)
+    {
+        if (((int)constant <= 0x7f) && ((int)constant >= -0x80)) {
+            movImm8(constant, dst);
+            return;
+        }
+
+        uint16_t opc = getOpcodeGroup3(MOVIMM_OPCODE, dst, 0);
+
+        m_buffer.ensureSpace(maxInstructionSize, sizeof(uint32_t));
+        printInstr(getOpcodeGroup3(MOVIMM_OPCODE, dst, constant), m_buffer.codeSize());
+        m_buffer.putShortWithConstantInt(opc, constant, true);
+    }
+
+    void loadConstantUnReusable(uint32_t constant, RegisterID dst, bool ensureSpace = false)
+    {
+        uint16_t opc = getOpcodeGroup3(MOVIMM_OPCODE, dst, 0);
+
+        if (ensureSpace)
+            m_buffer.ensureSpace(maxInstructionSize, sizeof(uint32_t));
+
+        printInstr(getOpcodeGroup3(MOVIMM_OPCODE, dst, constant), m_buffer.codeSize());
+        m_buffer.putShortWithConstantInt(opc, constant);
+    }
+
+    // Flow control
+
+    AssemblerLabel call()
+    {
+        RegisterID scr = claimScratch();
+        m_buffer.ensureSpace(maxInstructionSize + 4, sizeof(uint32_t));
+        loadConstantUnReusable(0x0, scr);
+        branch(JSR_OPCODE, scr);
+        nop();
+        releaseScratch(scr);
+        return m_buffer.label();
+    }
+
+    AssemblerLabel call(RegisterID dst)
+    {
+        m_buffer.ensureSpace(maxInstructionSize + 2);
+        branch(JSR_OPCODE, dst);
+        nop();
+        return m_buffer.label();
+    }
+
+    AssemblerLabel jmp()
+    {
+        RegisterID scr = claimScratch();
+        m_buffer.ensureSpace(maxInstructionSize + 4, sizeof(uint32_t));
+        AssemblerLabel label = m_buffer.label();
+        loadConstantUnReusable(0x0, scr);
+        branch(BRAF_OPCODE, scr);
+        nop();
+        releaseScratch(scr);
+        return label;
+    }
+
+    AssemblerLabel jmp(RegisterID dst)
+    {
+        jmpReg(dst);
+        return m_buffer.label();
+    }
+
+    void jmpReg(RegisterID dst)
+    {
+        m_buffer.ensureSpace(maxInstructionSize + 2);
+        branch(JMP_OPCODE, dst);
+        nop();
+    }
+
+    AssemblerLabel jne()
+    {
+        AssemblerLabel label = m_buffer.label();
+        branch(BF_OPCODE, 0);
+        return label;
+    }
+
+    AssemblerLabel je()
+    {
+        AssemblerLabel label = m_buffer.label();
+        branch(BT_OPCODE, 0);
+        return label;
+    }
+
+    void ret()
+    {
+        m_buffer.ensureSpace(maxInstructionSize + 2);
+        oneShortOp(RTS_OPCODE, false);
+    }
+
+    AssemblerLabel label()
+    {
+        m_buffer.ensureSpaceForAnyOneInstruction();
+        return m_buffer.label();
+    }
+
+    int sizeOfConstantPool()
+    {
+         return m_buffer.sizeOfConstantPool();
+    }
+
+    AssemblerLabel align(int alignment)
+    {
+        m_buffer.ensureSpace(maxInstructionSize + 2);
+        while (!m_buffer.isAligned(alignment)) {
+            nop();
+            m_buffer.ensureSpace(maxInstructionSize + 2);
+        }
+        return label();
+    }
+
+    static void changePCrelativeAddress(int offset, uint16_t* instructionPtr, uint32_t newAddress)
+    {
+        uint32_t address = (offset << 2) + ((reinterpret_cast<uint32_t>(instructionPtr) + 4) &(~0x3));
+        *reinterpret_cast<uint32_t*>(address) = newAddress;
+    }
+    
+    static uint32_t readPCrelativeAddress(int offset, uint16_t* instructionPtr)
+    {
+        uint32_t address = (offset << 2) + ((reinterpret_cast<uint32_t>(instructionPtr) + 4) &(~0x3));
+        return *reinterpret_cast<uint32_t*>(address);
+    }
+
+    static uint16_t* getInstructionPtr(void* code, int offset)
+    {
+        return reinterpret_cast<uint16_t*> (reinterpret_cast<uint32_t>(code) + offset);
+    }
+
+    static void linkJump(void* code, AssemblerLabel from, void* to)
+    {
+        ASSERT(from.isSet());
+
+        uint16_t* instructionPtr = getInstructionPtr(code, from.m_offset);
+        uint16_t instruction = *instructionPtr;
+        int offsetBits = (reinterpret_cast<uint32_t>(to) - reinterpret_cast<uint32_t>(code)) - from.m_offset;
+
+        if (((instruction & 0xff00) == BT_OPCODE) || ((instruction & 0xff00) == BF_OPCODE)) {
+            /* BT label ==> BF 2
+               nop          LDR reg
+               nop          braf @reg
+               nop          nop
+            */
+            offsetBits -= 8;
+            instruction ^= 0x0202;
+            *instructionPtr++ = instruction;
+            changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits);
+            instruction = (BRAF_OPCODE | (*instructionPtr++ & 0xf00));
+            *instructionPtr = instruction;
+            printBlockInstr(instructionPtr - 2, from.m_offset, 3);
+            return;
+         }
+
+         /* MOV #imm, reg => LDR reg
+            braf @reg        braf @reg
+            nop              nop
+         */
+        ASSERT((*(instructionPtr + 1) & BRAF_OPCODE) == BRAF_OPCODE);
+
+        offsetBits -= 4;
+        if (offsetBits >= -4096 && offsetBits <= 4094) {
+            *instructionPtr = getOpcodeGroup6(BRA_OPCODE, offsetBits >> 1);
+            *(++instructionPtr) = NOP_OPCODE;
+            printBlockInstr(instructionPtr - 1, from.m_offset, 2);
+            return;
+        }
+
+        changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits - 2);
+        printInstr(*instructionPtr, from.m_offset + 2);
+    }
+
+    static void linkCall(void* code, AssemblerLabel from, void* to)
+    {
+        uint16_t* instructionPtr = getInstructionPtr(code, from.m_offset);
+        instructionPtr -= 3;
+        changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, reinterpret_cast<uint32_t>(to));
+    }
+
+    static void linkPointer(void* code, AssemblerLabel where, void* value)
+    {
+        uint16_t* instructionPtr = getInstructionPtr(code, where.m_offset);
+        changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, reinterpret_cast<uint32_t>(value));
+    }
+
+    static unsigned getCallReturnOffset(AssemblerLabel call)
+    {
+        ASSERT(call.isSet());
+        return call.m_offset;
+    }
+
+    static uint32_t* getLdrImmAddressOnPool(SH4Word* insn, uint32_t* constPool)
+    {
+        return (constPool + (*insn & 0xff));
+    }
+
+    static SH4Word patchConstantPoolLoad(SH4Word load, int value)
+    {
+        return ((load & ~0xff) | value);
+    }
+
+    static SH4Buffer::TwoShorts placeConstantPoolBarrier(int offset)
+    {
+        ASSERT(((offset >> 1) <=2047) && ((offset >> 1) >= -2048));
+
+        SH4Buffer::TwoShorts m_barrier;
+        m_barrier.high = (BRA_OPCODE | (offset >> 1));
+        m_barrier.low = NOP_OPCODE;
+        printInstr(((BRA_OPCODE | (offset >> 1))), 0);
+        printInstr(NOP_OPCODE, 0);
+        return m_barrier;
+    }
+
+    static void patchConstantPoolLoad(void* loadAddr, void* constPoolAddr)
+    {
+        SH4Word* instructionPtr = reinterpret_cast<SH4Word*>(loadAddr);
+        SH4Word instruction = *instructionPtr;
+        SH4Word index = instruction & 0xff;
+
+        if ((instruction & 0xf000) != MOVIMM_OPCODE)
+            return;
+
+        ASSERT((((reinterpret_cast<uint32_t>(constPoolAddr) - reinterpret_cast<uint32_t>(loadAddr)) + index * 4)) < 1024);
+
+        int offset = reinterpret_cast<uint32_t>(constPoolAddr) + (index * 4) - ((reinterpret_cast<uint32_t>(instructionPtr) & ~0x03) + 4);
+        instruction &=0xf00;
+        instruction |= 0xd000;
+        offset &= 0x03ff;
+        instruction |= (offset >> 2);
+        *instructionPtr = instruction;
+        printInstr(instruction, reinterpret_cast<uint32_t>(loadAddr));
+    }
+
+    static void repatchPointer(void* where, void* value)
+    {
+        patchPointer(where, value);
+    }
+
+    static void* readPointer(void* code)
+    {
+        return static_cast<void*>(readInt32(code));
+    }
+
+    static void repatchInt32(void* where, int32_t value)
+    {
+        uint16_t* instructionPtr = reinterpret_cast<uint16_t*>(where);
+        changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, value);
+    }
+
+    static void repatchCompact(void* where, int32_t value)
+    {
+        repatchInt32(where, value);
+    }
+
+    static void relinkCall(void* from, void* to)
+    {
+        uint16_t* instructionPtr = reinterpret_cast<uint16_t*>(from);
+        instructionPtr -= 3;
+        changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, reinterpret_cast<uint32_t>(to));
+    }
+
+    static void relinkJump(void* from, void* to)
+    {
+        uint16_t* instructionPtr = reinterpret_cast<uint16_t*> (from);
+        uint16_t instruction = *instructionPtr;
+        int32_t offsetBits = (reinterpret_cast<uint32_t>(to) - reinterpret_cast<uint32_t>(from));
+
+        if (((*instructionPtr & 0xff00) == BT_OPCODE) || ((*instructionPtr & 0xff00) == BF_OPCODE)) {
+            offsetBits -= 8;
+            instructionPtr++;
+            changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits);
+            instruction = (BRAF_OPCODE | (*instructionPtr++ & 0xf00));
+            *instructionPtr = instruction;
+            printBlockInstr(instructionPtr, reinterpret_cast<uint32_t>(from) + 1, 3);
+            return;
+        }
+
+        ASSERT((*(instructionPtr + 1) & BRAF_OPCODE) == BRAF_OPCODE);
+        offsetBits -= 4;
+        if (offsetBits >= -4096 && offsetBits <= 4094) {
+            *instructionPtr = getOpcodeGroup6(BRA_OPCODE, offsetBits >> 1);
+            *(++instructionPtr) = NOP_OPCODE;
+            printBlockInstr(instructionPtr - 2, reinterpret_cast<uint32_t>(from), 2);
+            return;
+        }
+
+        changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits - 2);
+        printInstr(*instructionPtr, reinterpret_cast<uint32_t>(from));
+    }
+
+    // Linking & patching
+
+    void linkJump(AssemblerLabel from, AssemblerLabel to)
+    {
+        ASSERT(to.isSet());
+        ASSERT(from.isSet());
+
+        uint16_t* instructionPtr = getInstructionPtr(data(), from.m_offset);
+        uint16_t instruction = *instructionPtr;
+        int offsetBits;
+
+        if (((instruction & 0xff00) == BT_OPCODE) || ((instruction & 0xff00) == BF_OPCODE)) {
+            /* BT label => BF 2
+               nop        LDR reg
+               nop        braf @reg
+               nop        nop
+            */
+            offsetBits = (to.m_offset - from.m_offset) - 8;
+            instruction ^= 0x0202;
+            *instructionPtr++ = instruction;
+            if ((*instructionPtr & 0xf000) == 0xe000) {
+                uint32_t* addr = getLdrImmAddressOnPool(instructionPtr, m_buffer.poolAddress());
+                *addr = offsetBits;
+            } else
+                changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits);
+            instruction = (BRAF_OPCODE | (*instructionPtr++ & 0xf00));
+            *instructionPtr = instruction;
+            printBlockInstr(instructionPtr - 2, from.m_offset, 3);
+            return;
+        }
+
+        /* MOV # imm, reg => LDR reg
+           braf @reg         braf @reg
+           nop               nop
+        */
+        ASSERT((*(instructionPtr + 1) & BRAF_OPCODE) == BRAF_OPCODE);
+        offsetBits = (to.m_offset - from.m_offset) - 4;
+        if (offsetBits >= -4096 && offsetBits <= 4094) {
+            *instructionPtr = getOpcodeGroup6(BRA_OPCODE, offsetBits >> 1);
+            *(++instructionPtr) = NOP_OPCODE;
+            printBlockInstr(instructionPtr - 1, from.m_offset, 2);
+            return;
+        }
+
+        instruction = *instructionPtr;
+        if ((instruction  & 0xf000) == 0xe000) {
+            uint32_t* addr = getLdrImmAddressOnPool(instructionPtr, m_buffer.poolAddress());
+            *addr = offsetBits - 2;
+            printInstr(*instructionPtr, from.m_offset + 2);
+            return;
+        }
+
+        changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits - 2);
+        printInstr(*instructionPtr, from.m_offset + 2);
+    }
+
+    static void* getRelocatedAddress(void* code, AssemblerLabel label)
+    {
+        return reinterpret_cast<void*>(reinterpret_cast<char*>(code) + label.m_offset);
+    }
+
+    static int getDifferenceBetweenLabels(AssemblerLabel a, AssemblerLabel b)
+    {
+        return b.m_offset - a.m_offset;
+    }
+
+    static void patchPointer(void* code, AssemblerLabel where, void* value)
+    {
+        patchPointer(reinterpret_cast<uint32_t*>(code) + where.m_offset, value);
+    }
+
+    static void patchPointer(void* code, void* value)
+    {
+        patchInt32(code, reinterpret_cast<uint32_t>(value));
+    }
+
+    static void patchInt32(void* code, uint32_t value)
+    {
+        changePCrelativeAddress((*(reinterpret_cast<uint16_t*>(code)) & 0xff), reinterpret_cast<uint16_t*>(code), value);
+    }
+
+    static uint32_t readInt32(void* code)
+    {
+        return readPCrelativeAddress((*(reinterpret_cast<uint16_t*>(code)) & 0xff), reinterpret_cast<uint16_t*>(code));
+    }
+
+    void* executableCopy(JSGlobalData& globalData, ExecutablePool* allocator)
+    {
+        return m_buffer.executableCopy(globalData, allocator);
+    }
+
+    void prefix(uint16_t pre)
+    {
+        m_buffer.putByte(pre);
+    }
+
+    void oneShortOp(uint16_t opcode, bool checksize = true, bool isDouble = true)
+    {
+        printInstr(opcode, m_buffer.codeSize(), isDouble);
+        if (checksize)
+            m_buffer.ensureSpace(maxInstructionSize);
+        m_buffer.putShortUnchecked(opcode);
+    }
+
+    void ensureSpace(int space)
+    {
+        m_buffer.ensureSpace(space);
+    }
+
+    void ensureSpace(int insnSpace, int constSpace)
+    {
+        m_buffer.ensureSpace(insnSpace, constSpace);
+    }
+
+    // Administrative methods
+
+    void* data() const { return m_buffer.data(); }
+    size_t codeSize() const { return m_buffer.codeSize(); }
+
+#ifdef SH4_ASSEMBLER_TRACING
+    static void printInstr(uint16_t opc, unsigned int size, bool isdoubleInst = true)
+    {
+        if (!getenv("JavaScriptCoreDumpJIT"))
+            return;
+
+        const char *format = 0;
+        printfStdoutInstr("offset: 0x%8.8x\t", size);
+        switch (opc) {
+        case BRK_OPCODE:
+            format = "    BRK\n";
+            break;
+        case NOP_OPCODE:
+            format = "    NOP\n";
+            break;
+        case RTS_OPCODE:
+            format ="    *RTS\n";
+            break;
+        case SETS_OPCODE:
+            format = "    SETS\n";
+            break;
+        case SETT_OPCODE:
+            format = "    SETT\n";
+            break;
+        case CLRT_OPCODE:
+            format = "    CLRT\n";
+            break;
+        case FSCHG_OPCODE:
+            format = "    FSCHG\n";
+            break;
+        }
+        if (format) {
+            printfStdoutInstr(format);
+            return;
+        }
+        switch (opc & 0xf0ff) {
+        case BRAF_OPCODE:
+            format = "    *BRAF R%d\n";
+            break;
+        case DT_OPCODE:
+            format = "    DT R%d\n";
+            break;
+        case CMPPL_OPCODE:
+            format = "    CMP/PL R%d\n";
+            break;
+        case CMPPZ_OPCODE:
+            format = "    CMP/PZ R%d\n";
+            break;
+        case JMP_OPCODE:
+            format = "    *JMP @R%d\n";
+            break;
+        case JSR_OPCODE:
+            format = "    *JSR @R%d\n";
+            break;
+        case LDSPR_OPCODE:
+            format = "    LDS R%d, PR\n";
+            break;
+        case LDSLPR_OPCODE:
+            format = "    LDS.L @R%d+, PR\n";
+            break;
+        case MOVT_OPCODE:
+            format = "    MOVT R%d\n";
+            break;
+        case SHAL_OPCODE:
+            format = "    SHAL R%d\n";
+            break;
+        case SHAR_OPCODE:
+            format = "    SHAR R%d\n";
+            break;
+        case SHLL_OPCODE:
+            format = "    SHLL R%d\n";
+            break;
+        case SHLL2_OPCODE:
+            format = "    SHLL2 R%d\n";
+            break;
+        case SHLL8_OPCODE:
+            format = "    SHLL8 R%d\n";
+            break;
+        case SHLL16_OPCODE:
+            format = "    SHLL16 R%d\n";
+            break;
+        case SHLR_OPCODE:
+            format = "    SHLR R%d\n";
+            break;
+        case SHLR2_OPCODE:
+            format = "    SHLR2 R%d\n";
+            break;
+        case SHLR8_OPCODE:
+            format = "    SHLR8 R%d\n";
+            break;
+        case SHLR16_OPCODE:
+            format = "    SHLR16 R%d\n";
+            break;
+        case STSPR_OPCODE:
+            format = "    STS PR, R%d\n";
+            break;
+        case STSLPR_OPCODE:
+            format = "    STS.L PR, @-R%d\n";
+            break;
+        case LDS_RM_FPUL_OPCODE:
+            format = "    LDS R%d, FPUL\n";
+            break;
+        case STS_FPUL_RN_OPCODE:
+            format = "    STS FPUL, R%d \n";
+            break;
+        case FLDS_FRM_FPUL_OPCODE:
+            format = "    FLDS FR%d, FPUL\n";
+            break;
+        case FSTS_FPUL_FRN_OPCODE:
+            format = "    FSTS FPUL, R%d \n";
+            break;
+        case LDSFPSCR_OPCODE:
+            format = "    LDS R%d, FPSCR \n";
+            break;
+        case STSFPSCR_OPCODE:
+            format = "    STS FPSCR, R%d \n";
+            break;
+        case STSMACL_OPCODE:
+            format = "    STS MACL, R%d \n";
+            break;
+        case STSMACH_OPCODE:
+            format = "    STS MACH, R%d \n";
+            break;
+        case BSRF_OPCODE:
+            format = "    *BSRF R%d";
+            break;
+        case FTRC_OPCODE:
+            format = "    FTRC FR%d, FPUL\n";
+            break;
+        }
+        if (format) {
+            printfStdoutInstr(format, getRn(opc));
+            return;
+        }
+        switch (opc & 0xf0ff) {
+        case FNEG_OPCODE:
+            format = "    FNEG DR%d\n";
+            break;
+        case FLOAT_OPCODE:
+            format = "    FLOAT DR%d\n";
+            break;
+        case FTRC_OPCODE:
+            format = "    FTRC FR%d, FPUL\n";
+            break;
+        case FSQRT_OPCODE:
+            format = "    FSQRT FR%d\n";
+            break;
+        case FCNVDS_DRM_FPUL_OPCODE:
+            format = "    FCNVDS FR%d, FPUL\n";
+            break;
+        }
+        if (format) {
+            if (isdoubleInst)
+                printfStdoutInstr(format, getDRn(opc) << 1);
+            else
+                printfStdoutInstr(format, getRn(opc));
+            return;
+        }
+        switch (opc & 0xf00f) {
+        case ADD_OPCODE:
+            format = "    ADD R%d, R%d\n";
+            break;
+        case ADDC_OPCODE:
+            format = "    ADDC R%d, R%d\n";
+            break;
+        case ADDV_OPCODE:
+            format = "    ADDV R%d, R%d\n";
+            break;
+        case AND_OPCODE:
+            format = "    AND R%d, R%d\n";
+            break;
+        case DIV1_OPCODE:
+            format = "    DIV1 R%d, R%d\n";
+            break;
+        case CMPEQ_OPCODE:
+            format = "    CMP/EQ R%d, R%d\n";
+            break;
+        case CMPGE_OPCODE:
+            format = "    CMP/GE R%d, R%d\n";
+            break;
+        case CMPGT_OPCODE:
+            format = "    CMP/GT R%d, R%d\n";
+            break;
+        case CMPHI_OPCODE:
+            format = "    CMP/HI R%d, R%d\n";
+            break;
+        case CMPHS_OPCODE:
+            format = "    CMP/HS R%d, R%d\n";
+            break;
+        case MOV_OPCODE:
+            format = "    MOV R%d, R%d\n";
+            break;
+        case MOVB_WRITE_RN_OPCODE:
+            format = "    MOV.B R%d, @R%d\n";
+            break;
+        case MOVB_WRITE_RNDEC_OPCODE:
+            format = "    MOV.B R%d, @-R%d\n";
+            break;
+        case MOVB_WRITE_R0RN_OPCODE:
+            format = "    MOV.B R%d, @(R0, R%d)\n";
+            break;
+        case MOVB_READ_RM_OPCODE:
+            format = "    MOV.B @R%d, R%d\n";
+            break;
+        case MOVB_READ_RMINC_OPCODE:
+            format = "    MOV.B @R%d+, R%d\n";
+            break;
+        case MOVB_READ_R0RM_OPCODE:
+            format = "    MOV.B @(R0, R%d), R%d\n";
+            break;
+        case MOVL_WRITE_RN_OPCODE:
+            format = "    MOV.L R%d, @R%d\n";
+            break;
+        case MOVL_WRITE_RNDEC_OPCODE:
+            format = "    MOV.L R%d, @-R%d\n";
+            break;
+        case MOVL_WRITE_R0RN_OPCODE:
+            format = "    MOV.L R%d, @(R0, R%d)\n";
+            break;
+        case MOVL_READ_RM_OPCODE:
+            format = "    MOV.L @R%d, R%d\n";
+            break;
+        case MOVL_READ_RMINC_OPCODE:
+            format = "    MOV.L @R%d+, R%d\n";
+            break;
+        case MOVL_READ_R0RM_OPCODE:
+            format = "    MOV.L @(R0, R%d), R%d\n";
+            break;
+        case MULL_OPCODE:
+            format = "    MUL.L R%d, R%d\n";
+            break;
+        case DMULL_L_OPCODE:
+            format = "    DMULU.L R%d, R%d\n";
+            break;
+        case DMULSL_OPCODE:
+            format = "    DMULS.L R%d, R%d\n";
+            break;
+        case NEG_OPCODE:
+            format = "    NEG R%d, R%d\n";
+            break;
+        case NEGC_OPCODE:
+            format = "    NEGC R%d, R%d\n";
+            break;
+        case NOT_OPCODE:
+            format = "    NOT R%d, R%d\n";
+            break;
+        case OR_OPCODE:
+            format = "    OR R%d, R%d\n";
+            break;
+        case SHAD_OPCODE:
+            format = "    SHAD R%d, R%d\n";
+            break;
+        case SHLD_OPCODE:
+            format = "    SHLD R%d, R%d\n";
+            break;
+        case SUB_OPCODE:
+            format = "    SUB R%d, R%d\n";
+            break;
+        case SUBC_OPCODE:
+            format = "    SUBC R%d, R%d\n";
+            break;
+        case SUBV_OPCODE:
+            format = "    SUBV R%d, R%d\n";
+            break;
+        case TST_OPCODE:
+            format = "    TST R%d, R%d\n";
+            break;
+        case XOR_OPCODE:
+            format = "    XOR R%d, R%d\n";break;
+        case MOVW_WRITE_RN_OPCODE:
+            format = "    MOV.W R%d, @R%d\n";
+            break;
+        case MOVW_READ_RM_OPCODE:
+            format = "    MOV.W @R%d, R%d\n";
+            break;
+        case MOVW_READ_R0RM_OPCODE:
+            format = "    MOV.W @(R0, R%d), R%d\n";
+            break;
+        case EXTUW_OPCODE:
+            format = "    EXTU.W R%d, R%d\n";
+            break;
+        }
+        if (format) {
+            printfStdoutInstr(format, getRm(opc), getRn(opc));
+            return;
+        }
+        switch (opc & 0xf00f) {
+        case FSUB_OPCODE:
+            format = "    FSUB FR%d, FR%d\n";
+            break;
+        case FADD_OPCODE:
+            format = "    FADD FR%d, FR%d\n";
+            break;
+        case FDIV_OPCODE:
+            format = "    FDIV FR%d, FR%d\n";
+            break;
+        case FMUL_OPCODE:
+            format = "    DMULL FR%d, FR%d\n";
+            break;
+        case FMOV_OPCODE:
+            format = "    FMOV FR%d, FR%d\n";
+            break;
+        case FCMPEQ_OPCODE:
+            format = "    FCMP/EQ FR%d, FR%d\n";
+            break;
+        case FCMPGT_OPCODE:
+            format = "    FCMP/GT FR%d, FR%d\n";
+            break;
+        }
+        if (format) {
+            if (isdoubleInst)
+                printfStdoutInstr(format, getDRm(opc) << 1, getDRn(opc) << 1);
+            else
+                printfStdoutInstr(format, getRm(opc), getRn(opc));
+            return;
+        }
+        switch (opc & 0xf00f) {
+        case FMOVS_WRITE_RN_DEC_OPCODE:
+            format = "    %s FR%d, @-R%d\n";
+            break;
+        case FMOVS_WRITE_RN_OPCODE:
+            format = "    %s FR%d, @R%d\n";
+            break;
+        case FMOVS_WRITE_R0RN_OPCODE:
+            format = "    %s FR%d, @(R0, R%d)\n";
+            break;
+        }
+        if (format) {
+            if (isdoubleInst)
+                printfStdoutInstr(format, "FMOV", getDRm(opc) << 1, getDRn(opc));
+            else
+                printfStdoutInstr(format, "FMOV.S", getRm(opc), getRn(opc));
+            return;
+        }
+        switch (opc & 0xf00f) {
+        case FMOVS_READ_RM_OPCODE:
+            format = "    %s @R%d, FR%d\n";
+            break;
+        case FMOVS_READ_RM_INC_OPCODE:
+            format = "    %s @R%d+, FR%d\n";
+            break;
+        case FMOVS_READ_R0RM_OPCODE:
+            format = "    %s @(R0, R%d), FR%d\n";
+            break;
+        }
+        if (format) {
+            if (isdoubleInst)
+                printfStdoutInstr(format, "FMOV", getDRm(opc), getDRn(opc) << 1);
+            else
+                printfStdoutInstr(format, "FMOV.S", getRm(opc), getRn(opc));
+            return;
+        }
+        switch (opc & 0xff00) {
+        case BF_OPCODE:
+            format = "    BF %d\n";
+            break;
+        case BFS_OPCODE:
+            format = "    *BF/S %d\n";
+            break;
+        case ANDIMM_OPCODE:
+            format = "    AND #%d, R0\n";
+            break;
+        case BT_OPCODE:
+            format = "    BT %d\n";
+            break;
+        case BTS_OPCODE:
+            format = "    *BT/S %d\n";
+            break;
+        case CMPEQIMM_OPCODE:
+            format = "    CMP/EQ #%d, R0\n";
+            break;
+        case MOVB_WRITE_OFFGBR_OPCODE:
+            format = "    MOV.B R0, @(%d, GBR)\n";
+            break;
+        case MOVB_READ_OFFGBR_OPCODE:
+            format = "    MOV.B @(%d, GBR), R0\n";
+            break;
+        case MOVL_WRITE_OFFGBR_OPCODE:
+            format = "    MOV.L R0, @(%d, GBR)\n";
+            break;
+        case MOVL_READ_OFFGBR_OPCODE:
+            format = "    MOV.L @(%d, GBR), R0\n";
+            break;
+        case MOVA_READ_OFFPC_OPCODE:
+            format = "    MOVA @(%d, PC), R0\n";
+            break;
+        case ORIMM_OPCODE:
+            format = "    OR #%d, R0\n";
+            break;
+        case ORBIMM_OPCODE:
+            format = "    OR.B #%d, @(R0, GBR)\n";
+            break;
+        case TSTIMM_OPCODE:
+            format = "    TST #%d, R0\n";
+            break;
+        case TSTB_OPCODE:
+            format = "    TST.B %d, @(R0, GBR)\n";
+            break;
+        case XORIMM_OPCODE:
+            format = "    XOR #%d, R0\n";
+            break;
+        case XORB_OPCODE:
+            format = "    XOR.B %d, @(R0, GBR)\n";
+            break;
+        }
+        if (format) {
+            printfStdoutInstr(format, getImm8(opc));
+            return;
+        }
+        switch (opc & 0xff00) {
+        case MOVB_WRITE_OFFRN_OPCODE:
+            format = "    MOV.B R0, @(%d, R%d)\n";
+            break;
+        case MOVB_READ_OFFRM_OPCODE:
+            format = "    MOV.B @(%d, R%d), R0\n";
+            break;
+        }
+        if (format) {
+            printfStdoutInstr(format, getDisp(opc), getRm(opc));
+            return;
+        }
+        switch (opc & 0xf000) {
+        case BRA_OPCODE:
+            format = "    *BRA %d\n";
+            break;
+        case BSR_OPCODE:
+            format = "    *BSR %d\n";
+            break;
+        }
+        if (format) {
+            printfStdoutInstr(format, getImm12(opc));
+            return;
+        }
+        switch (opc & 0xf000) {
+        case MOVL_READ_OFFPC_OPCODE:
+            format = "    MOV.L @(%d, PC), R%d\n";
+            break;
+        case ADDIMM_OPCODE:
+            format = "    ADD #%d, R%d\n";
+            break;
+        case MOVIMM_OPCODE:
+            format = "    MOV #%d, R%d\n";
+            break;
+        case MOVW_READ_OFFPC_OPCODE:
+            format = "    MOV.W @(%d, PC), R%d\n";
+            break;
+        }
+        if (format) {
+            printfStdoutInstr(format, getImm8(opc), getRn(opc));
+            return;
+        }
+        switch (opc & 0xf000) {
+        case MOVL_WRITE_OFFRN_OPCODE:
+            format = "    MOV.L R%d, @(%d, R%d)\n";
+            printfStdoutInstr(format, getRm(opc), getDisp(opc), getRn(opc));
+            break;
+        case MOVL_READ_OFFRM_OPCODE:
+            format = "    MOV.L @(%d, R%d), R%d\n";
+            printfStdoutInstr(format, getDisp(opc), getRm(opc), getRn(opc));
+            break;
+        }
+    }
+
+    static void printfStdoutInstr(const char* format, ...)
+    {
+        if (getenv("JavaScriptCoreDumpJIT")) {
+            va_list args;
+            va_start(args, format);
+            vprintfStdoutInstr(format, args);
+            va_end(args);
+        }
+    }
+
+    static void vprintfStdoutInstr(const char* format, va_list args)
+    {
+        if (getenv("JavaScriptCoreDumpJIT"))
+            vfprintf(stdout, format, args);
+    }
+
+    static void printBlockInstr(uint16_t* first, unsigned int offset, int nbInstr)
+    {
+        printfStdoutInstr(">> repatch instructions after link\n");
+        for (int i = 0; i <= nbInstr; i++)
+           printInstr(*(first + i), offset + i);
+        printfStdoutInstr(">> end repatch\n");
+    }
+#else
+    static void printInstr(uint16_t opc, unsigned int size, bool isdoubleInst = true) {};
+    static void printBlockInstr(uint16_t* first, unsigned int offset, int nbInstr) {};
+#endif
+
+private:
+    SH4Buffer m_buffer;
+    int m_claimscratchReg;
+};
+
+} // namespace JSC
+
+#endif // ENABLE(ASSEMBLER) && CPU(SH4)
+
+#endif // SH4Assembler_h