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