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