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