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