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