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