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.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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.
28 #ifndef SH4Assembler_h
29 #define SH4Assembler_h
31 #if ENABLE(ASSEMBLER) && CPU(SH4)
33 #include "AssemblerBuffer.h"
34 #include "AssemblerBufferWithConstantPool.h"
35 #include "JITCompilationEffort.h"
39 #include <wtf/Assertions.h>
40 #include <wtf/DataLog.h>
41 #include <wtf/Vector.h>
44 #define SH4_ASSEMBLER_TRACING
48 typedef uint16_t SH4Word
;
51 INVALID_OPCODE
= 0xffff,
53 ADDIMM_OPCODE
= 0x7000,
57 ANDIMM_OPCODE
= 0xc900,
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,
82 FCMPEQ_OPCODE
= 0xf004,
83 FCMPGT_OPCODE
= 0xf005,
92 LDSPR_OPCODE
= 0x402a,
93 LDSLPR_OPCODE
= 0x4026,
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,
132 NEGC_OPCODE
= 0x600a,
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,
155 SUBC_OPCODE
= 0x300a,
156 SUBV_OPCODE
= 0x300b,
158 TSTIMM_OPCODE
= 0xc800,
159 TSTB_OPCODE
= 0xcc00,
160 EXTUB_OPCODE
= 0x600c,
161 EXTUW_OPCODE
= 0x600d,
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,
187 namespace SH4Registers
{
229 inline uint16_t getOpcodeGroup1(uint16_t opc
, int rm
, int rn
)
231 return (opc
| ((rm
& 0xf) << 8) | ((rn
& 0xf) << 4));
234 inline uint16_t getOpcodeGroup2(uint16_t opc
, int rm
)
236 return (opc
| ((rm
& 0xf) << 8));
239 inline uint16_t getOpcodeGroup3(uint16_t opc
, int rm
, int rn
)
241 return (opc
| ((rm
& 0xf) << 8) | (rn
& 0xff));
244 inline uint16_t getOpcodeGroup4(uint16_t opc
, int rm
, int rn
, int offset
)
246 return (opc
| ((rm
& 0xf) << 8) | ((rn
& 0xf) << 4) | (offset
& 0xf));
249 inline uint16_t getOpcodeGroup5(uint16_t opc
, int rm
)
251 return (opc
| (rm
& 0xff));
254 inline uint16_t getOpcodeGroup6(uint16_t opc
, int rm
)
256 return (opc
| (rm
& 0xfff));
259 inline uint16_t getOpcodeGroup7(uint16_t opc
, int rm
)
261 return (opc
| ((rm
& 0x7) << 9));
264 inline uint16_t getOpcodeGroup8(uint16_t opc
, int rm
, int rn
)
266 return (opc
| ((rm
& 0x7) << 9) | ((rn
& 0x7) << 5));
269 inline uint16_t getOpcodeGroup9(uint16_t opc
, int rm
, int rn
)
271 return (opc
| ((rm
& 0xf) << 8) | ((rn
& 0x7) << 5));
274 inline uint16_t getOpcodeGroup10(uint16_t opc
, int rm
, int rn
)
276 return (opc
| ((rm
& 0x7) << 9) | ((rn
& 0xf) << 4));
279 inline uint16_t getOpcodeGroup11(uint16_t opc
, int rm
, int rn
)
281 return (opc
| ((rm
& 0xf) << 4) | (rn
& 0xf));
284 inline uint16_t getRn(uint16_t x
)
286 return ((x
& 0xf00) >> 8);
289 inline uint16_t getRm(uint16_t x
)
291 return ((x
& 0xf0) >> 4);
294 inline uint16_t getDisp(uint16_t x
)
299 inline uint16_t getImm8(uint16_t x
)
304 inline uint16_t getImm12(uint16_t x
)
309 inline uint16_t getDRn(uint16_t x
)
311 return ((x
& 0xe00) >> 9);
314 inline uint16_t getDRm(uint16_t x
)
316 return ((x
& 0xe0) >> 5);
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;
330 padForAlign16
= 0x0009,
331 padForAlign32
= 0x00090009,
341 m_claimscratchReg
= 0x0;
344 // SH4 condition codes
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
358 NS
= 0xc, // Not Signed
359 EQU
= 0xd, // Equal or unordered(NaN)
367 // Opaque label types
369 bool isImmediate(int constant
)
371 return ((constant
<= 127) && (constant
>= -128));
374 RegisterID
claimScratch()
376 ASSERT((m_claimscratchReg
!= 0x3));
378 if (!(m_claimscratchReg
& 0x1)) {
379 m_claimscratchReg
= (m_claimscratchReg
| 0x1);
383 m_claimscratchReg
= (m_claimscratchReg
| 0x2);
387 void releaseScratch(RegisterID scratchR
)
389 if (scratchR
== scratchReg1
)
390 m_claimscratchReg
= (m_claimscratchReg
& 0x2);
392 m_claimscratchReg
= (m_claimscratchReg
& 0x1);
397 void pushReg(RegisterID reg
)
399 if (reg
== SH4Registers::pr
) {
400 oneShortOp(getOpcodeGroup2(STSLPR_OPCODE
, SH4Registers::sp
));
404 oneShortOp(getOpcodeGroup1(MOVL_WRITE_RNDEC_OPCODE
, SH4Registers::sp
, reg
));
407 void popReg(RegisterID reg
)
409 if (reg
== SH4Registers::pr
) {
410 oneShortOp(getOpcodeGroup2(LDSLPR_OPCODE
, SH4Registers::sp
));
414 oneShortOp(getOpcodeGroup1(MOVL_READ_RMINC_OPCODE
, reg
, SH4Registers::sp
));
417 void movt(RegisterID dst
)
419 uint16_t opc
= getOpcodeGroup2(MOVT_OPCODE
, dst
);
423 // Arithmetic operations
425 void addlRegReg(RegisterID src
, RegisterID dst
)
427 uint16_t opc
= getOpcodeGroup1(ADD_OPCODE
, dst
, src
);
431 void addclRegReg(RegisterID src
, RegisterID dst
)
433 uint16_t opc
= getOpcodeGroup1(ADDC_OPCODE
, dst
, src
);
437 void addvlRegReg(RegisterID src
, RegisterID dst
)
439 uint16_t opc
= getOpcodeGroup1(ADDV_OPCODE
, dst
, src
);
443 void addlImm8r(int imm8
, RegisterID dst
)
445 ASSERT((imm8
<= 127) && (imm8
>= -128));
447 uint16_t opc
= getOpcodeGroup3(ADDIMM_OPCODE
, dst
, imm8
);
451 void andlRegReg(RegisterID src
, RegisterID dst
)
453 uint16_t opc
= getOpcodeGroup1(AND_OPCODE
, dst
, src
);
457 void andlImm8r(int imm8
, RegisterID dst
)
459 ASSERT((imm8
<= 255) && (imm8
>= 0));
460 ASSERT(dst
== SH4Registers::r0
);
462 uint16_t opc
= getOpcodeGroup5(ANDIMM_OPCODE
, imm8
);
466 void div1lRegReg(RegisterID src
, RegisterID dst
)
468 uint16_t opc
= getOpcodeGroup1(DIV1_OPCODE
, dst
, src
);
472 void div0lRegReg(RegisterID src
, RegisterID dst
)
474 uint16_t opc
= getOpcodeGroup1(DIV0_OPCODE
, dst
, src
);
478 void notlReg(RegisterID src
, RegisterID dst
)
480 uint16_t opc
= getOpcodeGroup1(NOT_OPCODE
, dst
, src
);
484 void orlRegReg(RegisterID src
, RegisterID dst
)
486 uint16_t opc
= getOpcodeGroup1(OR_OPCODE
, dst
, src
);
490 void orlImm8r(int imm8
, RegisterID dst
)
492 ASSERT((imm8
<= 255) && (imm8
>= 0));
493 ASSERT(dst
== SH4Registers::r0
);
495 uint16_t opc
= getOpcodeGroup5(ORIMM_OPCODE
, imm8
);
499 void sublRegReg(RegisterID src
, RegisterID dst
)
501 uint16_t opc
= getOpcodeGroup1(SUB_OPCODE
, dst
, src
);
505 void subvlRegReg(RegisterID src
, RegisterID dst
)
507 uint16_t opc
= getOpcodeGroup1(SUBV_OPCODE
, dst
, src
);
511 void xorlRegReg(RegisterID src
, RegisterID dst
)
513 uint16_t opc
= getOpcodeGroup1(XOR_OPCODE
, dst
, src
);
517 void xorlImm8r(int imm8
, RegisterID dst
)
519 ASSERT((imm8
<= 255) && (imm8
>= 0));
520 ASSERT(dst
== SH4Registers::r0
);
522 uint16_t opc
= getOpcodeGroup5(XORIMM_OPCODE
, imm8
);
526 void shllImm8r(int imm
, RegisterID dst
)
530 oneShortOp(getOpcodeGroup2(SHLL_OPCODE
, dst
));
533 oneShortOp(getOpcodeGroup2(SHLL2_OPCODE
, dst
));
536 oneShortOp(getOpcodeGroup2(SHLL8_OPCODE
, dst
));
539 oneShortOp(getOpcodeGroup2(SHLL16_OPCODE
, dst
));
542 RELEASE_ASSERT_NOT_REACHED();
546 void neg(RegisterID dst
, RegisterID src
)
548 uint16_t opc
= getOpcodeGroup1(NEG_OPCODE
, dst
, src
);
552 void shldRegReg(RegisterID dst
, RegisterID rShift
)
554 oneShortOp(getOpcodeGroup1(SHLD_OPCODE
, dst
, rShift
));
557 void shadRegReg(RegisterID dst
, RegisterID rShift
)
559 oneShortOp(getOpcodeGroup1(SHAD_OPCODE
, dst
, rShift
));
562 void shlrImm8r(int imm
, RegisterID dst
)
566 oneShortOp(getOpcodeGroup2(SHLR_OPCODE
, dst
));
569 oneShortOp(getOpcodeGroup2(SHLR2_OPCODE
, dst
));
572 oneShortOp(getOpcodeGroup2(SHLR8_OPCODE
, dst
));
575 oneShortOp(getOpcodeGroup2(SHLR16_OPCODE
, dst
));
578 RELEASE_ASSERT_NOT_REACHED();
582 void shalImm8r(int imm
, RegisterID dst
)
586 oneShortOp(getOpcodeGroup2(SHAL_OPCODE
, dst
));
589 RELEASE_ASSERT_NOT_REACHED();
593 void sharImm8r(int imm
, RegisterID dst
)
597 oneShortOp(getOpcodeGroup2(SHAR_OPCODE
, dst
));
600 RELEASE_ASSERT_NOT_REACHED();
604 void imullRegReg(RegisterID src
, RegisterID dst
)
606 uint16_t opc
= getOpcodeGroup1(MULL_OPCODE
, dst
, src
);
610 void dmullRegReg(RegisterID src
, RegisterID dst
)
612 uint16_t opc
= getOpcodeGroup1(DMULL_L_OPCODE
, dst
, src
);
616 void dmulslRegReg(RegisterID src
, RegisterID dst
)
618 uint16_t opc
= getOpcodeGroup1(DMULSL_OPCODE
, dst
, src
);
622 void stsmacl(RegisterID reg
)
624 uint16_t opc
= getOpcodeGroup2(STSMACL_OPCODE
, reg
);
628 void stsmach(RegisterID reg
)
630 uint16_t opc
= getOpcodeGroup2(STSMACH_OPCODE
, reg
);
636 void cmplRegReg(RegisterID left
, RegisterID right
, Condition cond
)
640 oneShortOp(getOpcodeGroup1(CMPEQ_OPCODE
, right
, left
));
643 oneShortOp(getOpcodeGroup1(CMPGT_OPCODE
, right
, left
));
646 oneShortOp(getOpcodeGroup1(CMPEQ_OPCODE
, right
, left
));
649 oneShortOp(getOpcodeGroup1(CMPGE_OPCODE
, right
, left
));
652 oneShortOp(getOpcodeGroup1(CMPHS_OPCODE
, right
, left
));
655 oneShortOp(getOpcodeGroup1(CMPHI_OPCODE
, right
, left
));
658 oneShortOp(getOpcodeGroup1(CMPHI_OPCODE
, left
, right
));
661 oneShortOp(getOpcodeGroup1(CMPHS_OPCODE
, left
, right
));
664 oneShortOp(getOpcodeGroup1(CMPGE_OPCODE
, left
, right
));
667 oneShortOp(getOpcodeGroup1(CMPGT_OPCODE
, left
, right
));
670 RELEASE_ASSERT_NOT_REACHED();
674 void cmppl(RegisterID reg
)
676 uint16_t opc
= getOpcodeGroup2(CMPPL_OPCODE
, reg
);
680 void cmppz(RegisterID reg
)
682 uint16_t opc
= getOpcodeGroup2(CMPPZ_OPCODE
, reg
);
686 void cmpEqImmR0(int imm
, RegisterID dst
)
688 uint16_t opc
= getOpcodeGroup5(CMPEQIMM_OPCODE
, imm
);
692 void testlRegReg(RegisterID src
, RegisterID dst
)
694 uint16_t opc
= getOpcodeGroup1(TST_OPCODE
, dst
, src
);
698 void testlImm8r(int imm
, RegisterID dst
)
700 ASSERT((dst
== SH4Registers::r0
) && (imm
<= 255) && (imm
>= 0));
702 uint16_t opc
= getOpcodeGroup5(TSTIMM_OPCODE
, imm
);
708 oneShortOp(NOP_OPCODE
, false);
713 oneShortOp(SETT_OPCODE
);
718 oneShortOp(CLRT_OPCODE
);
723 oneShortOp(FSCHG_OPCODE
);
728 oneShortOp(BRK_OPCODE
, false);
731 void branch(uint16_t opc
, int label
)
735 ASSERT((label
<= 127) && (label
>= -128));
736 oneShortOp(getOpcodeGroup5(BT_OPCODE
, label
));
739 ASSERT((label
<= 2047) && (label
>= -2048));
740 oneShortOp(getOpcodeGroup6(BRA_OPCODE
, label
));
743 ASSERT((label
<= 127) && (label
>= -128));
744 oneShortOp(getOpcodeGroup5(BF_OPCODE
, label
));
747 RELEASE_ASSERT_NOT_REACHED();
751 void branch(uint16_t opc
, RegisterID reg
)
755 oneShortOp(getOpcodeGroup2(BRAF_OPCODE
, reg
));
758 oneShortOp(getOpcodeGroup2(JMP_OPCODE
, reg
));
761 oneShortOp(getOpcodeGroup2(JSR_OPCODE
, reg
));
764 oneShortOp(getOpcodeGroup2(BSRF_OPCODE
, reg
));
767 RELEASE_ASSERT_NOT_REACHED();
771 void ldspr(RegisterID reg
)
773 uint16_t opc
= getOpcodeGroup2(LDSPR_OPCODE
, reg
);
777 void stspr(RegisterID reg
)
779 uint16_t opc
= getOpcodeGroup2(STSPR_OPCODE
, reg
);
783 void extub(RegisterID src
, RegisterID dst
)
785 uint16_t opc
= getOpcodeGroup1(EXTUB_OPCODE
, dst
, src
);
789 void extuw(RegisterID src
, RegisterID dst
)
791 uint16_t opc
= getOpcodeGroup1(EXTUW_OPCODE
, dst
, src
);
797 void ldsrmfpul(RegisterID src
)
799 uint16_t opc
= getOpcodeGroup2(LDS_RM_FPUL_OPCODE
, src
);
803 void fneg(FPRegisterID dst
)
805 uint16_t opc
= getOpcodeGroup2(FNEG_OPCODE
, dst
);
806 oneShortOp(opc
, true, false);
809 void fsqrt(FPRegisterID dst
)
811 uint16_t opc
= getOpcodeGroup2(FSQRT_OPCODE
, dst
);
812 oneShortOp(opc
, true, false);
815 void stsfpulReg(RegisterID src
)
817 uint16_t opc
= getOpcodeGroup2(STS_FPUL_RN_OPCODE
, src
);
821 void floatfpulfrn(FPRegisterID src
)
823 uint16_t opc
= getOpcodeGroup2(FLOAT_OPCODE
, src
);
824 oneShortOp(opc
, true, false);
827 void fmull(FPRegisterID src
, FPRegisterID dst
)
829 uint16_t opc
= getOpcodeGroup1(FMUL_OPCODE
, dst
, src
);
830 oneShortOp(opc
, true, false);
833 void fmovsRegReg(FPRegisterID src
, FPRegisterID dst
)
835 uint16_t opc
= getOpcodeGroup1(FMOV_OPCODE
, dst
, src
);
836 oneShortOp(opc
, true, false);
839 void fmovsReadrm(RegisterID src
, FPRegisterID dst
)
841 uint16_t opc
= getOpcodeGroup1(FMOVS_READ_RM_OPCODE
, dst
, src
);
842 oneShortOp(opc
, true, false);
845 void fmovsWriterm(FPRegisterID src
, RegisterID dst
)
847 uint16_t opc
= getOpcodeGroup1(FMOVS_WRITE_RN_OPCODE
, dst
, src
);
848 oneShortOp(opc
, true, false);
851 void fmovsWriter0r(FPRegisterID src
, RegisterID dst
)
853 uint16_t opc
= getOpcodeGroup1(FMOVS_WRITE_R0RN_OPCODE
, dst
, src
);
854 oneShortOp(opc
, true, false);
857 void fmovsReadr0r(RegisterID src
, FPRegisterID dst
)
859 uint16_t opc
= getOpcodeGroup1(FMOVS_READ_R0RM_OPCODE
, dst
, src
);
860 oneShortOp(opc
, true, false);
863 void fmovsReadrminc(RegisterID src
, FPRegisterID dst
)
865 uint16_t opc
= getOpcodeGroup1(FMOVS_READ_RM_INC_OPCODE
, dst
, src
);
866 oneShortOp(opc
, true, false);
869 void fmovsWriterndec(FPRegisterID src
, RegisterID dst
)
871 uint16_t opc
= getOpcodeGroup1(FMOVS_WRITE_RN_DEC_OPCODE
, dst
, src
);
872 oneShortOp(opc
, true, false);
875 void ftrcRegfpul(FPRegisterID src
)
877 uint16_t opc
= getOpcodeGroup2(FTRC_OPCODE
, src
);
878 oneShortOp(opc
, true, false);
881 void fldsfpul(FPRegisterID src
)
883 uint16_t opc
= getOpcodeGroup2(FLDS_FRM_FPUL_OPCODE
, src
);
887 void fstsfpul(FPRegisterID src
)
889 uint16_t opc
= getOpcodeGroup2(FSTS_FPUL_FRN_OPCODE
, src
);
893 void ldsfpscr(RegisterID reg
)
895 uint16_t opc
= getOpcodeGroup2(LDSFPSCR_OPCODE
, reg
);
899 void stsfpscr(RegisterID reg
)
901 uint16_t opc
= getOpcodeGroup2(STSFPSCR_OPCODE
, reg
);
907 void dcnvds(FPRegisterID src
)
909 uint16_t opc
= getOpcodeGroup7(FCNVDS_DRM_FPUL_OPCODE
, src
>> 1);
913 void dcnvsd(FPRegisterID dst
)
915 uint16_t opc
= getOpcodeGroup7(FCNVSD_FPUL_DRN_OPCODE
, dst
>> 1);
919 void dcmppeq(FPRegisterID src
, FPRegisterID dst
)
921 uint16_t opc
= getOpcodeGroup8(FCMPEQ_OPCODE
, dst
>> 1, src
>> 1);
925 void dcmppgt(FPRegisterID src
, FPRegisterID dst
)
927 uint16_t opc
= getOpcodeGroup8(FCMPGT_OPCODE
, dst
>> 1, src
>> 1);
931 void dmulRegReg(FPRegisterID src
, FPRegisterID dst
)
933 uint16_t opc
= getOpcodeGroup8(FMUL_OPCODE
, dst
>> 1, src
>> 1);
937 void dsubRegReg(FPRegisterID src
, FPRegisterID dst
)
939 uint16_t opc
= getOpcodeGroup8(FSUB_OPCODE
, dst
>> 1, src
>> 1);
943 void daddRegReg(FPRegisterID src
, FPRegisterID dst
)
945 uint16_t opc
= getOpcodeGroup8(FADD_OPCODE
, dst
>> 1, src
>> 1);
949 void dmovRegReg(FPRegisterID src
, FPRegisterID dst
)
951 uint16_t opc
= getOpcodeGroup8(FMOV_OPCODE
, dst
>> 1, src
>> 1);
955 void ddivRegReg(FPRegisterID src
, FPRegisterID dst
)
957 uint16_t opc
= getOpcodeGroup8(FDIV_OPCODE
, dst
>> 1, src
>> 1);
961 void dabs(FPRegisterID dst
)
963 uint16_t opc
= getOpcodeGroup7(FABS_OPCODE
, dst
>> 1);
967 void dsqrt(FPRegisterID dst
)
969 uint16_t opc
= getOpcodeGroup7(FSQRT_OPCODE
, dst
>> 1);
973 void dneg(FPRegisterID dst
)
975 uint16_t opc
= getOpcodeGroup7(FNEG_OPCODE
, dst
>> 1);
979 void fmovReadrm(RegisterID src
, FPRegisterID dst
)
981 uint16_t opc
= getOpcodeGroup10(FMOVS_READ_RM_OPCODE
, dst
>> 1, src
);
985 void fmovWriterm(FPRegisterID src
, RegisterID dst
)
987 uint16_t opc
= getOpcodeGroup9(FMOVS_WRITE_RN_OPCODE
, dst
, src
>> 1);
991 void fmovWriter0r(FPRegisterID src
, RegisterID dst
)
993 uint16_t opc
= getOpcodeGroup9(FMOVS_WRITE_R0RN_OPCODE
, dst
, src
>> 1);
997 void fmovReadr0r(RegisterID src
, FPRegisterID dst
)
999 uint16_t opc
= getOpcodeGroup10(FMOVS_READ_R0RM_OPCODE
, dst
>> 1, src
);
1003 void fmovReadrminc(RegisterID src
, FPRegisterID dst
)
1005 uint16_t opc
= getOpcodeGroup10(FMOVS_READ_RM_INC_OPCODE
, dst
>> 1, src
);
1009 void fmovWriterndec(FPRegisterID src
, RegisterID dst
)
1011 uint16_t opc
= getOpcodeGroup9(FMOVS_WRITE_RN_DEC_OPCODE
, dst
, src
>> 1);
1015 void floatfpulDreg(FPRegisterID src
)
1017 uint16_t opc
= getOpcodeGroup7(FLOAT_OPCODE
, src
>> 1);
1021 void ftrcdrmfpul(FPRegisterID src
)
1023 uint16_t opc
= getOpcodeGroup7(FTRC_OPCODE
, src
>> 1);
1029 void movImm8(int imm8
, RegisterID dst
)
1031 ASSERT((imm8
<= 127) && (imm8
>= -128));
1033 uint16_t opc
= getOpcodeGroup3(MOVIMM_OPCODE
, dst
, imm8
);
1037 void movlRegReg(RegisterID src
, RegisterID dst
)
1039 uint16_t opc
= getOpcodeGroup1(MOV_OPCODE
, dst
, src
);
1043 void movwRegMem(RegisterID src
, RegisterID dst
)
1045 uint16_t opc
= getOpcodeGroup1(MOVW_WRITE_RN_OPCODE
, dst
, src
);
1049 void movwMemReg(RegisterID src
, RegisterID dst
)
1051 uint16_t opc
= getOpcodeGroup1(MOVW_READ_RM_OPCODE
, dst
, src
);
1055 void movwMemRegIn(RegisterID base
, RegisterID dst
)
1057 uint16_t opc
= getOpcodeGroup1(MOVW_READ_RMINC_OPCODE
, dst
, base
);
1061 void movwPCReg(int offset
, RegisterID base
, RegisterID dst
)
1063 ASSERT(base
== SH4Registers::pc
);
1064 ASSERT((offset
<= 255) && (offset
>= 0));
1066 uint16_t opc
= getOpcodeGroup3(MOVW_READ_OFFPC_OPCODE
, dst
, offset
);
1070 void movwMemReg(int offset
, RegisterID base
, RegisterID dst
)
1072 ASSERT(dst
== SH4Registers::r0
);
1074 uint16_t opc
= getOpcodeGroup11(MOVW_READ_OFFRM_OPCODE
, base
, offset
);
1078 void movwR0mr(RegisterID src
, RegisterID dst
)
1080 uint16_t opc
= getOpcodeGroup1(MOVW_READ_R0RM_OPCODE
, dst
, src
);
1084 void movwRegMemr0(RegisterID src
, RegisterID dst
)
1086 uint16_t opc
= getOpcodeGroup1(MOVW_WRITE_R0RN_OPCODE
, dst
, src
);
1090 void movlRegMem(RegisterID src
, int offset
, RegisterID base
)
1092 ASSERT((offset
<= 15) && (offset
>= 0));
1095 oneShortOp(getOpcodeGroup1(MOVL_WRITE_RN_OPCODE
, base
, src
));
1099 oneShortOp(getOpcodeGroup4(MOVL_WRITE_OFFRN_OPCODE
, base
, src
, offset
));
1102 void movlRegMem(RegisterID src
, RegisterID base
)
1104 uint16_t opc
= getOpcodeGroup1(MOVL_WRITE_RN_OPCODE
, base
, src
);
1108 void movlMemReg(int offset
, RegisterID base
, RegisterID dst
)
1110 if (base
== SH4Registers::pc
) {
1111 ASSERT((offset
<= 255) && (offset
>= 0));
1112 oneShortOp(getOpcodeGroup3(MOVL_READ_OFFPC_OPCODE
, dst
, offset
));
1116 ASSERT((offset
<= 15) && (offset
>= 0));
1118 oneShortOp(getOpcodeGroup1(MOVL_READ_RM_OPCODE
, dst
, base
));
1122 oneShortOp(getOpcodeGroup4(MOVL_READ_OFFRM_OPCODE
, dst
, base
, offset
));
1125 void movlMemRegCompact(int offset
, RegisterID base
, RegisterID dst
)
1127 oneShortOp(getOpcodeGroup4(MOVL_READ_OFFRM_OPCODE
, dst
, base
, offset
));
1130 void movbRegMem(RegisterID src
, RegisterID base
)
1132 uint16_t opc
= getOpcodeGroup1(MOVB_WRITE_RN_OPCODE
, base
, src
);
1136 void movbMemReg(int offset
, RegisterID base
, RegisterID dst
)
1138 ASSERT(dst
== SH4Registers::r0
);
1140 uint16_t opc
= getOpcodeGroup11(MOVB_READ_OFFRM_OPCODE
, base
, offset
);
1144 void movbR0mr(RegisterID src
, RegisterID dst
)
1146 uint16_t opc
= getOpcodeGroup1(MOVB_READ_R0RM_OPCODE
, dst
, src
);
1150 void movbMemReg(RegisterID src
, RegisterID dst
)
1152 uint16_t opc
= getOpcodeGroup1(MOVB_READ_RM_OPCODE
, dst
, src
);
1156 void movbMemRegIn(RegisterID base
, RegisterID dst
)
1158 uint16_t opc
= getOpcodeGroup1(MOVB_READ_RMINC_OPCODE
, dst
, base
);
1162 void movbRegMemr0(RegisterID src
, RegisterID dst
)
1164 uint16_t opc
= getOpcodeGroup1(MOVB_WRITE_R0RN_OPCODE
, dst
, src
);
1168 void movlMemReg(RegisterID base
, RegisterID dst
)
1170 uint16_t opc
= getOpcodeGroup1(MOVL_READ_RM_OPCODE
, dst
, base
);
1174 void movlMemRegIn(RegisterID base
, RegisterID dst
)
1176 uint16_t opc
= getOpcodeGroup1(MOVL_READ_RMINC_OPCODE
, dst
, base
);
1180 void movlR0mr(RegisterID src
, RegisterID dst
)
1182 uint16_t opc
= getOpcodeGroup1(MOVL_READ_R0RM_OPCODE
, dst
, src
);
1186 void movlRegMemr0(RegisterID src
, RegisterID dst
)
1188 uint16_t opc
= getOpcodeGroup1(MOVL_WRITE_R0RN_OPCODE
, dst
, src
);
1192 void movlImm8r(int imm8
, RegisterID dst
)
1194 ASSERT((imm8
<= 127) && (imm8
>= -128));
1196 uint16_t opc
= getOpcodeGroup3(MOVIMM_OPCODE
, dst
, imm8
);
1200 void loadConstant(uint32_t constant
, RegisterID dst
)
1202 if (((int)constant
<= 0x7f) && ((int)constant
>= -0x80)) {
1203 movImm8(constant
, dst
);
1207 uint16_t opc
= getOpcodeGroup3(MOVIMM_OPCODE
, dst
, 0);
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);
1214 void loadConstantUnReusable(uint32_t constant
, RegisterID dst
, bool ensureSpace
= false)
1216 uint16_t opc
= getOpcodeGroup3(MOVIMM_OPCODE
, dst
, 0);
1219 m_buffer
.ensureSpace(maxInstructionSize
, sizeof(uint32_t));
1221 printInstr(getOpcodeGroup3(MOVIMM_OPCODE
, dst
, constant
), m_buffer
.codeSize());
1222 m_buffer
.putShortWithConstantInt(opc
, constant
);
1227 AssemblerLabel
call()
1229 RegisterID scr
= claimScratch();
1230 m_buffer
.ensureSpace(maxInstructionSize
+ 4, sizeof(uint32_t));
1231 loadConstantUnReusable(0x0, scr
);
1232 branch(JSR_OPCODE
, scr
);
1234 releaseScratch(scr
);
1235 return m_buffer
.label();
1238 AssemblerLabel
call(RegisterID dst
)
1240 m_buffer
.ensureSpace(maxInstructionSize
+ 2);
1241 branch(JSR_OPCODE
, dst
);
1243 return m_buffer
.label();
1246 AssemblerLabel
jmp()
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
);
1254 releaseScratch(scr
);
1258 void extraInstrForBranch(RegisterID dst
)
1260 loadConstantUnReusable(0x0, dst
);
1265 AssemblerLabel
jmp(RegisterID dst
)
1268 return m_buffer
.label();
1271 void jmpReg(RegisterID dst
)
1273 m_buffer
.ensureSpace(maxInstructionSize
+ 2);
1274 branch(JMP_OPCODE
, dst
);
1278 AssemblerLabel
jne()
1280 AssemblerLabel label
= m_buffer
.label();
1281 branch(BF_OPCODE
, 0);
1287 AssemblerLabel label
= m_buffer
.label();
1288 branch(BT_OPCODE
, 0);
1292 AssemblerLabel
bra()
1294 AssemblerLabel label
= m_buffer
.label();
1295 branch(BRA_OPCODE
, 0);
1301 m_buffer
.ensureSpace(maxInstructionSize
+ 2);
1302 oneShortOp(RTS_OPCODE
, false);
1305 AssemblerLabel
labelIgnoringWatchpoints()
1307 m_buffer
.ensureSpaceForAnyInstruction();
1308 return m_buffer
.label();
1311 AssemblerLabel
label()
1313 m_buffer
.ensureSpaceForAnyInstruction();
1314 return m_buffer
.label();
1317 int sizeOfConstantPool()
1319 return m_buffer
.sizeOfConstantPool();
1322 AssemblerLabel
align(int alignment
)
1324 m_buffer
.ensureSpace(maxInstructionSize
+ 2);
1325 while (!m_buffer
.isAligned(alignment
)) {
1327 m_buffer
.ensureSpace(maxInstructionSize
+ 2);
1332 static void changePCrelativeAddress(int offset
, uint16_t* instructionPtr
, uint32_t newAddress
)
1334 uint32_t address
= (offset
<< 2) + ((reinterpret_cast<uint32_t>(instructionPtr
) + 4) &(~0x3));
1335 *reinterpret_cast<uint32_t*>(address
) = newAddress
;
1338 static uint32_t readPCrelativeAddress(int offset
, uint16_t* instructionPtr
)
1340 uint32_t address
= (offset
<< 2) + ((reinterpret_cast<uint32_t>(instructionPtr
) + 4) &(~0x3));
1341 return *reinterpret_cast<uint32_t*>(address
);
1344 static uint16_t* getInstructionPtr(void* code
, int offset
)
1346 return reinterpret_cast<uint16_t*> (reinterpret_cast<uint32_t>(code
) + offset
);
1349 static void linkJump(void* code
, AssemblerLabel from
, void* to
)
1351 ASSERT(from
.isSet());
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
;
1357 if (((instruction
& 0xff00) == BT_OPCODE
) || ((instruction
& 0xff00) == BF_OPCODE
)) {
1358 /* BT label ==> BF 2
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);
1373 /* MOV #imm, reg => LDR reg
1377 ASSERT((*(instructionPtr
+ 1) & BRAF_OPCODE
) == BRAF_OPCODE
);
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);
1387 changePCrelativeAddress((*instructionPtr
& 0xff), instructionPtr
, offsetBits
- 2);
1388 printInstr(*instructionPtr
, from
.m_offset
+ 2);
1391 static void linkCall(void* code
, AssemblerLabel from
, void* to
)
1393 uint16_t* instructionPtr
= getInstructionPtr(code
, from
.m_offset
);
1394 instructionPtr
-= 3;
1395 changePCrelativeAddress((*instructionPtr
& 0xff), instructionPtr
, reinterpret_cast<uint32_t>(to
));
1398 static void linkPointer(void* code
, AssemblerLabel where
, void* value
)
1400 uint16_t* instructionPtr
= getInstructionPtr(code
, where
.m_offset
);
1401 changePCrelativeAddress((*instructionPtr
& 0xff), instructionPtr
, reinterpret_cast<uint32_t>(value
));
1404 static unsigned getCallReturnOffset(AssemblerLabel call
)
1406 ASSERT(call
.isSet());
1407 return call
.m_offset
;
1410 static uint32_t* getLdrImmAddressOnPool(SH4Word
* insn
, uint32_t* constPool
)
1412 return (constPool
+ (*insn
& 0xff));
1415 static SH4Word
patchConstantPoolLoad(SH4Word load
, int value
)
1417 return ((load
& ~0xff) | value
);
1420 static SH4Buffer::TwoShorts
placeConstantPoolBarrier(int offset
)
1422 ASSERT(((offset
>> 1) <= 2047) && ((offset
>> 1) >= -2048));
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);
1432 static void patchConstantPoolLoad(void* loadAddr
, void* constPoolAddr
)
1434 SH4Word
* instructionPtr
= reinterpret_cast<SH4Word
*>(loadAddr
);
1435 SH4Word instruction
= *instructionPtr
;
1436 SH4Word index
= instruction
& 0xff;
1438 if ((instruction
& 0xf000) != MOVIMM_OPCODE
)
1441 ASSERT((((reinterpret_cast<uint32_t>(constPoolAddr
) - reinterpret_cast<uint32_t>(loadAddr
)) + index
* 4)) < 1024);
1443 int offset
= reinterpret_cast<uint32_t>(constPoolAddr
) + (index
* 4) - ((reinterpret_cast<uint32_t>(instructionPtr
) & ~0x03) + 4);
1444 instruction
&=0xf00;
1445 instruction
|= 0xd000;
1447 instruction
|= (offset
>> 2);
1448 *instructionPtr
= instruction
;
1449 printInstr(instruction
, reinterpret_cast<uint32_t>(loadAddr
));
1452 static void repatchPointer(void* where
, void* value
)
1454 patchPointer(where
, value
);
1457 static void* readPointer(void* code
)
1459 return reinterpret_cast<void*>(readInt32(code
));
1462 static void repatchInt32(void* where
, int32_t value
)
1464 uint16_t* instructionPtr
= reinterpret_cast<uint16_t*>(where
);
1465 changePCrelativeAddress((*instructionPtr
& 0xff), instructionPtr
, value
);
1468 static void repatchCompact(void* where
, int32_t value
)
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));
1476 static void relinkCall(void* from
, void* to
)
1478 uint16_t* instructionPtr
= reinterpret_cast<uint16_t*>(from
);
1479 instructionPtr
-= 3;
1480 changePCrelativeAddress((*instructionPtr
& 0xff), instructionPtr
, reinterpret_cast<uint32_t>(to
));
1483 static void relinkJump(void* from
, void* to
)
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
));
1489 if (((*instructionPtr
& 0xff00) == BT_OPCODE
) || ((*instructionPtr
& 0xff00) == BF_OPCODE
)) {
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);
1499 ASSERT((*(instructionPtr
+ 1) & BRAF_OPCODE
) == BRAF_OPCODE
);
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);
1508 changePCrelativeAddress((*instructionPtr
& 0xff), instructionPtr
, offsetBits
- 2);
1509 printInstr(*instructionPtr
, reinterpret_cast<uint32_t>(from
));
1512 // Linking & patching
1514 static ptrdiff_t maxJumpReplacementSize()
1516 return sizeof(SH4Word
) * 6;
1519 static void replaceWithJump(void *instructionStart
, void *to
)
1521 SH4Word
* instruction
= reinterpret_cast<SH4Word
*>(instructionStart
);
1522 intptr_t difference
= reinterpret_cast<intptr_t>(to
) - (reinterpret_cast<intptr_t>(instruction
) + 2 * sizeof(SH4Word
));
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);
1532 instruction
[nbinst
++] = getOpcodeGroup3(MOVL_READ_OFFPC_OPCODE
, scratchReg2
, 1);
1533 instruction
[nbinst
++] = getOpcodeGroup2(JMP_OPCODE
, scratchReg2
);
1534 instruction
[nbinst
++] = NOP_OPCODE
;
1536 if (!(reinterpret_cast<unsigned>(instruction
) & 3))
1537 instruction
[nbinst
++] = NOP_OPCODE
;
1539 instruction
[nbinst
++] = reinterpret_cast<unsigned>(to
) & 0xffff;
1540 instruction
[nbinst
++] = reinterpret_cast<unsigned>(to
) >> 16;
1541 cacheFlush(instruction
, sizeof(SH4Word
) * nbinst
);
1544 static void revertJump(void* instructionStart
, void *immptr
)
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
));
1551 void linkJump(AssemblerLabel from
, AssemblerLabel to
, JumpType type
= JumpFar
)
1554 ASSERT(from
.isSet());
1556 uint16_t* instructionPtr
= getInstructionPtr(data(), from
.m_offset
);
1557 uint16_t instruction
= *instructionPtr
;
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);
1568 if (((instruction
& 0xff00) == BT_OPCODE
) || ((instruction
& 0xff00) == BF_OPCODE
)) {
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());
1581 changePCrelativeAddress((*instructionPtr
& 0xff), instructionPtr
, offsetBits
);
1582 instruction
= (BRAF_OPCODE
| (*instructionPtr
++ & 0xf00));
1583 *instructionPtr
= instruction
;
1584 printBlockInstr(instructionPtr
- 2, from
.m_offset
, 3);
1588 /* MOV # imm, reg => LDR reg
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);
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);
1609 changePCrelativeAddress((*instructionPtr
& 0xff), instructionPtr
, offsetBits
- 2);
1610 printInstr(*instructionPtr
, from
.m_offset
+ 2);
1613 static void* getRelocatedAddress(void* code
, AssemblerLabel label
)
1615 return reinterpret_cast<void*>(reinterpret_cast<char*>(code
) + label
.m_offset
);
1618 static int getDifferenceBetweenLabels(AssemblerLabel a
, AssemblerLabel b
)
1620 return b
.m_offset
- a
.m_offset
;
1623 static void patchPointer(void* code
, AssemblerLabel where
, void* value
)
1625 patchPointer(reinterpret_cast<uint32_t*>(code
) + where
.m_offset
, value
);
1628 static void patchPointer(void* code
, void* value
)
1630 patchInt32(code
, reinterpret_cast<uint32_t>(value
));
1633 static void patchInt32(void* code
, uint32_t value
)
1635 changePCrelativeAddress((*(reinterpret_cast<uint16_t*>(code
)) & 0xff), reinterpret_cast<uint16_t*>(code
), value
);
1638 static uint32_t readInt32(void* code
)
1640 return readPCrelativeAddress((*(reinterpret_cast<uint16_t*>(code
)) & 0xff), reinterpret_cast<uint16_t*>(code
));
1643 static void* readCallTarget(void* from
)
1645 uint16_t* instructionPtr
= static_cast<uint16_t*>(from
);
1646 instructionPtr
-= 3;
1647 return reinterpret_cast<void*>(readPCrelativeAddress((*instructionPtr
& 0xff), instructionPtr
));
1650 PassRefPtr
<ExecutableMemoryHandle
> executableCopy(VM
& vm
, void* ownerUID
, JITCompilationEffort effort
)
1652 return m_buffer
.executableCopy(vm
, ownerUID
, effort
);
1655 static void cacheFlush(void* code
, size_t size
)
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);
1662 #if defined CACHEFLUSH_D_L2
1663 syscall(__NR_cacheflush
, currentPage
, pageSize(), CACHEFLUSH_D_WB
| CACHEFLUSH_I
| CACHEFLUSH_D_L2
);
1665 syscall(__NR_cacheflush
, currentPage
, pageSize(), CACHEFLUSH_D_WB
| CACHEFLUSH_I
);
1667 currentPage
+= pageSize();
1668 } while (lastPage
>= currentPage
);
1670 #error "The cacheFlush support is missing on this platform."
1674 void prefix(uint16_t pre
)
1676 m_buffer
.putByte(pre
);
1679 void oneShortOp(uint16_t opcode
, bool checksize
= true, bool isDouble
= true)
1681 printInstr(opcode
, m_buffer
.codeSize(), isDouble
);
1683 m_buffer
.ensureSpace(maxInstructionSize
);
1684 m_buffer
.putShortUnchecked(opcode
);
1687 void ensureSpace(int space
)
1689 m_buffer
.ensureSpace(space
);
1692 void ensureSpace(int insnSpace
, int constSpace
)
1694 m_buffer
.ensureSpace(insnSpace
, constSpace
);
1697 // Administrative methods
1699 void* data() const { return m_buffer
.data(); }
1700 size_t codeSize() const { return m_buffer
.codeSize(); }
1702 #ifdef SH4_ASSEMBLER_TRACING
1703 static void printInstr(uint16_t opc
, unsigned size
, bool isdoubleInst
= true)
1705 if (!getenv("JavaScriptCoreDumpJIT"))
1708 const char *format
= 0;
1709 printfStdoutInstr("offset: 0x%8.8x\t", size
);
1730 format
= " FSCHG\n";
1734 printfStdoutInstr(format
);
1737 switch (opc
& 0xf0ff) {
1739 format
= " *BRAF R%d\n";
1742 format
= " DT R%d\n";
1745 format
= " CMP/PL R%d\n";
1748 format
= " CMP/PZ R%d\n";
1751 format
= " *JMP @R%d\n";
1754 format
= " *JSR @R%d\n";
1757 format
= " LDS R%d, PR\n";
1760 format
= " LDS.L @R%d+, PR\n";
1763 format
= " MOVT R%d\n";
1766 format
= " SHAL R%d\n";
1769 format
= " SHAR R%d\n";
1772 format
= " SHLL R%d\n";
1775 format
= " SHLL2 R%d\n";
1778 format
= " SHLL8 R%d\n";
1781 format
= " SHLL16 R%d\n";
1784 format
= " SHLR R%d\n";
1787 format
= " SHLR2 R%d\n";
1790 format
= " SHLR8 R%d\n";
1793 format
= " SHLR16 R%d\n";
1796 format
= " STS PR, R%d\n";
1799 format
= " STS.L PR, @-R%d\n";
1801 case LDS_RM_FPUL_OPCODE
:
1802 format
= " LDS R%d, FPUL\n";
1804 case STS_FPUL_RN_OPCODE
:
1805 format
= " STS FPUL, R%d \n";
1807 case FLDS_FRM_FPUL_OPCODE
:
1808 format
= " FLDS FR%d, FPUL\n";
1810 case FSTS_FPUL_FRN_OPCODE
:
1811 format
= " FSTS FPUL, R%d \n";
1813 case LDSFPSCR_OPCODE
:
1814 format
= " LDS R%d, FPSCR \n";
1816 case STSFPSCR_OPCODE
:
1817 format
= " STS FPSCR, R%d \n";
1819 case STSMACL_OPCODE
:
1820 format
= " STS MACL, R%d \n";
1822 case STSMACH_OPCODE
:
1823 format
= " STS MACH, R%d \n";
1826 format
= " *BSRF R%d";
1829 format
= " FTRC FR%d, FPUL\n";
1833 printfStdoutInstr(format
, getRn(opc
));
1836 switch (opc
& 0xf0ff) {
1838 format
= " FNEG DR%d\n";
1841 format
= " FLOAT DR%d\n";
1844 format
= " FTRC FR%d, FPUL\n";
1847 format
= " FABS FR%d\n";
1850 format
= " FSQRT FR%d\n";
1852 case FCNVDS_DRM_FPUL_OPCODE
:
1853 format
= " FCNVDS FR%d, FPUL\n";
1855 case FCNVSD_FPUL_DRN_OPCODE
:
1856 format
= " FCNVSD FPUL, FR%d\n";
1861 printfStdoutInstr(format
, getDRn(opc
) << 1);
1863 printfStdoutInstr(format
, getRn(opc
));
1866 switch (opc
& 0xf00f) {
1868 format
= " ADD R%d, R%d\n";
1871 format
= " ADDC R%d, R%d\n";
1874 format
= " ADDV R%d, R%d\n";
1877 format
= " AND R%d, R%d\n";
1880 format
= " DIV1 R%d, R%d\n";
1883 format
= " CMP/EQ R%d, R%d\n";
1886 format
= " CMP/GE R%d, R%d\n";
1889 format
= " CMP/GT R%d, R%d\n";
1892 format
= " CMP/HI R%d, R%d\n";
1895 format
= " CMP/HS R%d, R%d\n";
1898 format
= " MOV R%d, R%d\n";
1900 case MOVB_WRITE_RN_OPCODE
:
1901 format
= " MOV.B R%d, @R%d\n";
1903 case MOVB_WRITE_RNDEC_OPCODE
:
1904 format
= " MOV.B R%d, @-R%d\n";
1906 case MOVB_WRITE_R0RN_OPCODE
:
1907 format
= " MOV.B R%d, @(R0, R%d)\n";
1909 case MOVB_READ_RM_OPCODE
:
1910 format
= " MOV.B @R%d, R%d\n";
1912 case MOVB_READ_RMINC_OPCODE
:
1913 format
= " MOV.B @R%d+, R%d\n";
1915 case MOVB_READ_R0RM_OPCODE
:
1916 format
= " MOV.B @(R0, R%d), R%d\n";
1918 case MOVL_WRITE_RN_OPCODE
:
1919 format
= " MOV.L R%d, @R%d\n";
1921 case MOVL_WRITE_RNDEC_OPCODE
:
1922 format
= " MOV.L R%d, @-R%d\n";
1924 case MOVL_WRITE_R0RN_OPCODE
:
1925 format
= " MOV.L R%d, @(R0, R%d)\n";
1927 case MOVL_READ_RM_OPCODE
:
1928 format
= " MOV.L @R%d, R%d\n";
1930 case MOVL_READ_RMINC_OPCODE
:
1931 format
= " MOV.L @R%d+, R%d\n";
1933 case MOVL_READ_R0RM_OPCODE
:
1934 format
= " MOV.L @(R0, R%d), R%d\n";
1937 format
= " MUL.L R%d, R%d\n";
1939 case DMULL_L_OPCODE
:
1940 format
= " DMULU.L R%d, R%d\n";
1943 format
= " DMULS.L R%d, R%d\n";
1946 format
= " NEG R%d, R%d\n";
1949 format
= " NEGC R%d, R%d\n";
1952 format
= " NOT R%d, R%d\n";
1955 format
= " OR R%d, R%d\n";
1958 format
= " SHAD R%d, R%d\n";
1961 format
= " SHLD R%d, R%d\n";
1964 format
= " SUB R%d, R%d\n";
1967 format
= " SUBC R%d, R%d\n";
1970 format
= " SUBV R%d, R%d\n";
1973 format
= " TST R%d, R%d\n";
1976 format
= " XOR R%d, R%d\n";break;
1977 case MOVW_WRITE_RN_OPCODE
:
1978 format
= " MOV.W R%d, @R%d\n";
1980 case MOVW_READ_RM_OPCODE
:
1981 format
= " MOV.W @R%d, R%d\n";
1983 case MOVW_READ_RMINC_OPCODE
:
1984 format
= " MOV.W @R%d+, R%d\n";
1986 case MOVW_READ_R0RM_OPCODE
:
1987 format
= " MOV.W @(R0, R%d), R%d\n";
1989 case MOVW_WRITE_R0RN_OPCODE
:
1990 format
= " MOV.W R%d, @(R0, R%d)\n";
1993 format
= " EXTU.B R%d, R%d\n";
1996 format
= " EXTU.W R%d, R%d\n";
2000 printfStdoutInstr(format
, getRm(opc
), getRn(opc
));
2003 switch (opc
& 0xf00f) {
2005 format
= " FSUB FR%d, FR%d\n";
2008 format
= " FADD FR%d, FR%d\n";
2011 format
= " FDIV FR%d, FR%d\n";
2014 format
= " DMULL FR%d, FR%d\n";
2017 format
= " FMOV FR%d, FR%d\n";
2020 format
= " FCMP/EQ FR%d, FR%d\n";
2023 format
= " FCMP/GT FR%d, FR%d\n";
2028 printfStdoutInstr(format
, getDRm(opc
) << 1, getDRn(opc
) << 1);
2030 printfStdoutInstr(format
, getRm(opc
), getRn(opc
));
2033 switch (opc
& 0xf00f) {
2034 case FMOVS_WRITE_RN_DEC_OPCODE
:
2035 format
= " %s FR%d, @-R%d\n";
2037 case FMOVS_WRITE_RN_OPCODE
:
2038 format
= " %s FR%d, @R%d\n";
2040 case FMOVS_WRITE_R0RN_OPCODE
:
2041 format
= " %s FR%d, @(R0, R%d)\n";
2046 printfStdoutInstr(format
, "FMOV", getDRm(opc
) << 1, getDRn(opc
));
2048 printfStdoutInstr(format
, "FMOV.S", getRm(opc
), getRn(opc
));
2051 switch (opc
& 0xf00f) {
2052 case FMOVS_READ_RM_OPCODE
:
2053 format
= " %s @R%d, FR%d\n";
2055 case FMOVS_READ_RM_INC_OPCODE
:
2056 format
= " %s @R%d+, FR%d\n";
2058 case FMOVS_READ_R0RM_OPCODE
:
2059 format
= " %s @(R0, R%d), FR%d\n";
2064 printfStdoutInstr(format
, "FMOV", getDRm(opc
), getDRn(opc
) << 1);
2066 printfStdoutInstr(format
, "FMOV.S", getRm(opc
), getRn(opc
));
2069 switch (opc
& 0xff00) {
2071 format
= " BF %d\n";
2074 format
= " *BF/S %d\n";
2077 format
= " AND #%d, R0\n";
2080 format
= " BT %d\n";
2083 format
= " *BT/S %d\n";
2085 case CMPEQIMM_OPCODE
:
2086 format
= " CMP/EQ #%d, R0\n";
2088 case MOVB_WRITE_OFFGBR_OPCODE
:
2089 format
= " MOV.B R0, @(%d, GBR)\n";
2091 case MOVB_READ_OFFGBR_OPCODE
:
2092 format
= " MOV.B @(%d, GBR), R0\n";
2094 case MOVL_WRITE_OFFGBR_OPCODE
:
2095 format
= " MOV.L R0, @(%d, GBR)\n";
2097 case MOVL_READ_OFFGBR_OPCODE
:
2098 format
= " MOV.L @(%d, GBR), R0\n";
2100 case MOVA_READ_OFFPC_OPCODE
:
2101 format
= " MOVA @(%d, PC), R0\n";
2104 format
= " OR #%d, R0\n";
2107 format
= " OR.B #%d, @(R0, GBR)\n";
2110 format
= " TST #%d, R0\n";
2113 format
= " TST.B %d, @(R0, GBR)\n";
2116 format
= " XOR #%d, R0\n";
2119 format
= " XOR.B %d, @(R0, GBR)\n";
2123 printfStdoutInstr(format
, getImm8(opc
));
2126 switch (opc
& 0xff00) {
2127 case MOVB_WRITE_OFFRN_OPCODE
:
2128 format
= " MOV.B R0, @(%d, R%d)\n";
2130 case MOVB_READ_OFFRM_OPCODE
:
2131 format
= " MOV.B @(%d, R%d), R0\n";
2135 printfStdoutInstr(format
, getDisp(opc
), getRm(opc
));
2138 switch (opc
& 0xf000) {
2140 format
= " *BRA %d\n";
2143 format
= " *BSR %d\n";
2147 printfStdoutInstr(format
, getImm12(opc
));
2150 switch (opc
& 0xf000) {
2151 case MOVL_READ_OFFPC_OPCODE
:
2152 format
= " MOV.L @(%d, PC), R%d\n";
2155 format
= " ADD #%d, R%d\n";
2158 format
= " MOV #%d, R%d\n";
2160 case MOVW_READ_OFFPC_OPCODE
:
2161 format
= " MOV.W @(%d, PC), R%d\n";
2165 printfStdoutInstr(format
, getImm8(opc
), getRn(opc
));
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
));
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
));
2180 static void printfStdoutInstr(const char* format
, ...)
2182 if (getenv("JavaScriptCoreDumpJIT")) {
2184 va_start(args
, format
);
2185 vprintfStdoutInstr(format
, args
);
2190 static void vprintfStdoutInstr(const char* format
, va_list args
)
2192 if (getenv("JavaScriptCoreDumpJIT"))
2193 WTF::dataLogFV(format
, args
);
2196 static void printBlockInstr(uint16_t* first
, unsigned offset
, int nbInstr
)
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");
2204 static void printInstr(uint16_t opc
, unsigned size
, bool isdoubleInst
= true) { };
2205 static void printBlockInstr(uint16_t* first
, unsigned offset
, int nbInstr
) { };
2208 static void replaceWithLoad(void* instructionStart
)
2210 SH4Word
* insPtr
= reinterpret_cast<SH4Word
*>(instructionStart
);
2212 insPtr
+= 2; // skip MOV and ADD opcodes
2214 if (((*insPtr
) & 0xf00f) != MOVL_READ_RM_OPCODE
) {
2215 *insPtr
= MOVL_READ_RM_OPCODE
| (*insPtr
& 0x0ff0);
2216 cacheFlush(insPtr
, sizeof(SH4Word
));
2220 static void replaceWithAddressComputation(void* instructionStart
)
2222 SH4Word
* insPtr
= reinterpret_cast<SH4Word
*>(instructionStart
);
2224 insPtr
+= 2; // skip MOV and ADD opcodes
2226 if (((*insPtr
) & 0xf00f) != MOV_OPCODE
) {
2227 *insPtr
= MOV_OPCODE
| (*insPtr
& 0x0ff0);
2228 cacheFlush(insPtr
, sizeof(SH4Word
));
2234 int m_claimscratchReg
;
2239 #endif // ENABLE(ASSEMBLER) && CPU(SH4)
2241 #endif // SH4Assembler_h