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