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