2 * Copyright (C) 2009-2011 STMicroelectronics. All rights reserved.
3 * Copyright (C) 2008 Apple Inc. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #ifndef SH4Assembler_h
28 #define SH4Assembler_h
30 #if ENABLE(ASSEMBLER) && CPU(SH4)
32 #include "AssemblerBuffer.h"
33 #include "AssemblerBufferWithConstantPool.h"
34 #include "JITCompilationEffort.h"
38 #include <wtf/Assertions.h>
39 #include <wtf/DataLog.h>
40 #include <wtf/Vector.h>
43 #define SH4_ASSEMBLER_TRACING
47 typedef uint16_t SH4Word
;
50 INVALID_OPCODE
= 0xffff,
52 ADDIMM_OPCODE
= 0x7000,
56 ANDIMM_OPCODE
= 0xc900,
71 CMPEQ_OPCODE
= 0x3000,
72 CMPEQIMM_OPCODE
= 0x8800,
73 CMPGE_OPCODE
= 0x3003,
74 CMPGT_OPCODE
= 0x3007,
75 CMPHI_OPCODE
= 0x3006,
76 CMPHS_OPCODE
= 0x3002,
77 CMPPL_OPCODE
= 0x4015,
78 CMPPZ_OPCODE
= 0x4011,
79 CMPSTR_OPCODE
= 0x200c,
81 FCMPEQ_OPCODE
= 0xf004,
82 FCMPGT_OPCODE
= 0xf005,
91 LDSPR_OPCODE
= 0x402a,
92 LDSLPR_OPCODE
= 0x4026,
94 MOVIMM_OPCODE
= 0xe000,
95 MOVB_WRITE_RN_OPCODE
= 0x2000,
96 MOVB_WRITE_RNDEC_OPCODE
= 0x2004,
97 MOVB_WRITE_R0RN_OPCODE
= 0x0004,
98 MOVB_WRITE_OFFGBR_OPCODE
= 0xc000,
99 MOVB_WRITE_OFFRN_OPCODE
= 0x8000,
100 MOVB_READ_RM_OPCODE
= 0x6000,
101 MOVB_READ_RMINC_OPCODE
= 0x6004,
102 MOVB_READ_R0RM_OPCODE
= 0x000c,
103 MOVB_READ_OFFGBR_OPCODE
= 0xc400,
104 MOVB_READ_OFFRM_OPCODE
= 0x8400,
105 MOVL_WRITE_RN_OPCODE
= 0x2002,
106 MOVL_WRITE_RNDEC_OPCODE
= 0x2006,
107 MOVL_WRITE_R0RN_OPCODE
= 0x0006,
108 MOVL_WRITE_OFFGBR_OPCODE
= 0xc200,
109 MOVL_WRITE_OFFRN_OPCODE
= 0x1000,
110 MOVL_READ_RM_OPCODE
= 0x6002,
111 MOVL_READ_RMINC_OPCODE
= 0x6006,
112 MOVL_READ_R0RM_OPCODE
= 0x000e,
113 MOVL_READ_OFFGBR_OPCODE
= 0xc600,
114 MOVL_READ_OFFPC_OPCODE
= 0xd000,
115 MOVL_READ_OFFRM_OPCODE
= 0x5000,
116 MOVW_WRITE_RN_OPCODE
= 0x2001,
117 MOVW_READ_RM_OPCODE
= 0x6001,
118 MOVW_READ_R0RM_OPCODE
= 0x000d,
119 MOVW_READ_OFFRM_OPCODE
= 0x8500,
120 MOVW_READ_OFFPC_OPCODE
= 0x9000,
121 MOVA_READ_OFFPC_OPCODE
= 0xc700,
122 MOVT_OPCODE
= 0x0029,
123 MULL_OPCODE
= 0x0007,
124 DMULL_L_OPCODE
= 0x3005,
125 STSMACL_OPCODE
= 0x001a,
126 STSMACH_OPCODE
= 0x000a,
127 DMULSL_OPCODE
= 0x300d,
129 NEGC_OPCODE
= 0x600a,
132 ORIMM_OPCODE
= 0xcb00,
133 ORBIMM_OPCODE
= 0xcf00,
134 SETS_OPCODE
= 0x0058,
135 SETT_OPCODE
= 0x0018,
136 SHAD_OPCODE
= 0x400c,
137 SHAL_OPCODE
= 0x4020,
138 SHAR_OPCODE
= 0x4021,
139 SHLD_OPCODE
= 0x400d,
140 SHLL_OPCODE
= 0x4000,
141 SHLL2_OPCODE
= 0x4008,
142 SHLL8_OPCODE
= 0x4018,
143 SHLL16_OPCODE
= 0x4028,
144 SHLR_OPCODE
= 0x4001,
145 SHLR2_OPCODE
= 0x4009,
146 SHLR8_OPCODE
= 0x4019,
147 SHLR16_OPCODE
= 0x4029,
148 STSPR_OPCODE
= 0x002a,
149 STSLPR_OPCODE
= 0x4022,
150 FLOAT_OPCODE
= 0xf02d,
152 SUBC_OPCODE
= 0x300a,
153 SUBV_OPCODE
= 0x300b,
155 TSTIMM_OPCODE
= 0xc800,
156 TSTB_OPCODE
= 0xcc00,
157 EXTUB_OPCODE
= 0x600c,
158 EXTUW_OPCODE
= 0x600d,
160 XORIMM_OPCODE
= 0xca00,
161 XORB_OPCODE
= 0xce00,
162 FMOVS_READ_RM_INC_OPCODE
= 0xf009,
163 FMOVS_READ_RM_OPCODE
= 0xf008,
164 FMOVS_READ_R0RM_OPCODE
= 0xf006,
165 FMOVS_WRITE_RN_OPCODE
= 0xf00a,
166 FMOVS_WRITE_RN_DEC_OPCODE
= 0xf00b,
167 FMOVS_WRITE_R0RN_OPCODE
= 0xf007,
168 FCNVDS_DRM_FPUL_OPCODE
= 0xf0bd,
169 LDS_RM_FPUL_OPCODE
= 0x405a,
170 FLDS_FRM_FPUL_OPCODE
= 0xf01d,
171 STS_FPUL_RN_OPCODE
= 0x005a,
172 FSTS_FPUL_FRN_OPCODE
= 0xF00d,
173 LDSFPSCR_OPCODE
= 0x406a,
174 STSFPSCR_OPCODE
= 0x006a,
175 LDSRMFPUL_OPCODE
= 0x405a,
176 FSTSFPULFRN_OPCODE
= 0xf00d,
177 FSQRT_OPCODE
= 0xf06d,
178 FSCHG_OPCODE
= 0xf3fd,
182 namespace SH4Registers
{
224 inline uint16_t getOpcodeGroup1(uint16_t opc
, int rm
, int rn
)
226 return (opc
| ((rm
& 0xf) << 8) | ((rn
& 0xf) << 4));
229 inline uint16_t getOpcodeGroup2(uint16_t opc
, int rm
)
231 return (opc
| ((rm
& 0xf) << 8));
234 inline uint16_t getOpcodeGroup3(uint16_t opc
, int rm
, int rn
)
236 return (opc
| ((rm
& 0xf) << 8) | (rn
& 0xff));
239 inline uint16_t getOpcodeGroup4(uint16_t opc
, int rm
, int rn
, int offset
)
241 return (opc
| ((rm
& 0xf) << 8) | ((rn
& 0xf) << 4) | (offset
& 0xf));
244 inline uint16_t getOpcodeGroup5(uint16_t opc
, int rm
)
246 return (opc
| (rm
& 0xff));
249 inline uint16_t getOpcodeGroup6(uint16_t opc
, int rm
)
251 return (opc
| (rm
& 0xfff));
254 inline uint16_t getOpcodeGroup7(uint16_t opc
, int rm
)
256 return (opc
| ((rm
& 0x7) << 9));
259 inline uint16_t getOpcodeGroup8(uint16_t opc
, int rm
, int rn
)
261 return (opc
| ((rm
& 0x7) << 9) | ((rn
& 0x7) << 5));
264 inline uint16_t getOpcodeGroup9(uint16_t opc
, int rm
, int rn
)
266 return (opc
| ((rm
& 0xf) << 8) | ((rn
& 0x7) << 5));
269 inline uint16_t getOpcodeGroup10(uint16_t opc
, int rm
, int rn
)
271 return (opc
| ((rm
& 0x7) << 9) | ((rn
& 0xf) << 4));
274 inline uint16_t getOpcodeGroup11(uint16_t opc
, int rm
, int rn
)
276 return (opc
| ((rm
& 0xf) << 4) | (rn
& 0xf));
279 inline uint16_t getRn(uint16_t x
)
281 return ((x
& 0xf00) >> 8);
284 inline uint16_t getRm(uint16_t x
)
286 return ((x
& 0xf0) >> 4);
289 inline uint16_t getDisp(uint16_t x
)
294 inline uint16_t getImm8(uint16_t x
)
299 inline uint16_t getImm12(uint16_t x
)
304 inline uint16_t getDRn(uint16_t x
)
306 return ((x
& 0xe00) >> 9);
309 inline uint16_t getDRm(uint16_t x
)
311 return ((x
& 0xe0) >> 5);
316 typedef SH4Registers::RegisterID RegisterID
;
317 typedef SH4Registers::FPRegisterID FPRegisterID
;
318 typedef AssemblerBufferWithConstantPool
<512, 4, 2, SH4Assembler
> SH4Buffer
;
319 static const RegisterID scratchReg1
= SH4Registers::r3
;
320 static const RegisterID scratchReg2
= SH4Registers::r11
;
321 static const uint32_t maxInstructionSize
= 16;
325 padForAlign16
= 0x0009,
326 padForAlign32
= 0x00090009,
329 enum JumpType
{ JumpFar
,
335 m_claimscratchReg
= 0x0;
338 // SH4 condition codes
341 NE
= 0x1, // Not Equal
342 HS
= 0x2, // Unsigend Greater Than equal
343 HI
= 0x3, // Unsigend Greater Than
344 LS
= 0x4, // Unsigend Lower or Same
345 LI
= 0x5, // Unsigend Lower
346 GE
= 0x6, // Greater or Equal
347 LT
= 0x7, // Less Than
348 GT
= 0x8, // Greater Than
349 LE
= 0x9, // Less or Equal
350 OF
= 0xa, // OverFlow
352 EQU
= 0xc, // Equal or unordered(NaN)
360 // Opaque label types
362 bool isImmediate(int constant
)
364 return ((constant
<= 127) && (constant
>= -128));
367 RegisterID
claimScratch()
369 ASSERT((m_claimscratchReg
!= 0x3));
371 if (!(m_claimscratchReg
& 0x1)) {
372 m_claimscratchReg
= (m_claimscratchReg
| 0x1);
376 m_claimscratchReg
= (m_claimscratchReg
| 0x2);
380 void releaseScratch(RegisterID scratchR
)
382 if (scratchR
== scratchReg1
)
383 m_claimscratchReg
= (m_claimscratchReg
& 0x2);
385 m_claimscratchReg
= (m_claimscratchReg
& 0x1);
390 void pushReg(RegisterID reg
)
392 if (reg
== SH4Registers::pr
) {
393 oneShortOp(getOpcodeGroup2(STSLPR_OPCODE
, SH4Registers::sp
));
397 oneShortOp(getOpcodeGroup1(MOVL_WRITE_RNDEC_OPCODE
, SH4Registers::sp
, reg
));
400 void popReg(RegisterID reg
)
402 if (reg
== SH4Registers::pr
) {
403 oneShortOp(getOpcodeGroup2(LDSLPR_OPCODE
, SH4Registers::sp
));
407 oneShortOp(getOpcodeGroup1(MOVL_READ_RMINC_OPCODE
, reg
, SH4Registers::sp
));
410 void movt(RegisterID dst
)
412 uint16_t opc
= getOpcodeGroup2(MOVT_OPCODE
, dst
);
416 // Arithmetic operations
418 void addlRegReg(RegisterID src
, RegisterID dst
)
420 uint16_t opc
= getOpcodeGroup1(ADD_OPCODE
, dst
, src
);
424 void addclRegReg(RegisterID src
, RegisterID dst
)
426 uint16_t opc
= getOpcodeGroup1(ADDC_OPCODE
, dst
, src
);
430 void addvlRegReg(RegisterID src
, RegisterID dst
)
432 uint16_t opc
= getOpcodeGroup1(ADDV_OPCODE
, dst
, src
);
436 void addlImm8r(int imm8
, RegisterID dst
)
438 ASSERT((imm8
<= 127) && (imm8
>= -128));
440 uint16_t opc
= getOpcodeGroup3(ADDIMM_OPCODE
, dst
, imm8
);
444 void andlRegReg(RegisterID src
, RegisterID dst
)
446 uint16_t opc
= getOpcodeGroup1(AND_OPCODE
, dst
, src
);
450 void andlImm8r(int imm8
, RegisterID dst
)
452 ASSERT((imm8
<= 255) && (imm8
>= 0));
453 ASSERT(dst
== SH4Registers::r0
);
455 uint16_t opc
= getOpcodeGroup5(ANDIMM_OPCODE
, imm8
);
459 void div1lRegReg(RegisterID src
, RegisterID dst
)
461 uint16_t opc
= getOpcodeGroup1(DIV1_OPCODE
, dst
, src
);
465 void div0lRegReg(RegisterID src
, RegisterID dst
)
467 uint16_t opc
= getOpcodeGroup1(DIV0_OPCODE
, dst
, src
);
471 void notlReg(RegisterID src
, RegisterID dst
)
473 uint16_t opc
= getOpcodeGroup1(NOT_OPCODE
, dst
, src
);
477 void orlRegReg(RegisterID src
, RegisterID dst
)
479 uint16_t opc
= getOpcodeGroup1(OR_OPCODE
, dst
, src
);
483 void orlImm8r(int imm8
, RegisterID dst
)
485 ASSERT((imm8
<= 255) && (imm8
>= 0));
486 ASSERT(dst
== SH4Registers::r0
);
488 uint16_t opc
= getOpcodeGroup5(ORIMM_OPCODE
, imm8
);
492 void sublRegReg(RegisterID src
, RegisterID dst
)
494 uint16_t opc
= getOpcodeGroup1(SUB_OPCODE
, dst
, src
);
498 void subvlRegReg(RegisterID src
, RegisterID dst
)
500 uint16_t opc
= getOpcodeGroup1(SUBV_OPCODE
, dst
, src
);
504 void xorlRegReg(RegisterID src
, RegisterID dst
)
506 uint16_t opc
= getOpcodeGroup1(XOR_OPCODE
, dst
, src
);
510 void xorlImm8r(int imm8
, RegisterID dst
)
512 ASSERT((imm8
<= 255) && (imm8
>= 0));
513 ASSERT(dst
== SH4Registers::r0
);
515 uint16_t opc
= getOpcodeGroup5(XORIMM_OPCODE
, imm8
);
519 void shllImm8r(int imm
, RegisterID dst
)
523 oneShortOp(getOpcodeGroup2(SHLL_OPCODE
, dst
));
526 oneShortOp(getOpcodeGroup2(SHLL2_OPCODE
, dst
));
529 oneShortOp(getOpcodeGroup2(SHLL8_OPCODE
, dst
));
532 oneShortOp(getOpcodeGroup2(SHLL16_OPCODE
, dst
));
535 ASSERT_NOT_REACHED();
539 void neg(RegisterID dst
, RegisterID src
)
541 uint16_t opc
= getOpcodeGroup1(NEG_OPCODE
, dst
, src
);
545 void shllRegReg(RegisterID dst
, RegisterID rShift
)
547 uint16_t opc
= getOpcodeGroup1(SHLD_OPCODE
, dst
, rShift
);
551 void shlrRegReg(RegisterID dst
, RegisterID rShift
)
554 shllRegReg(dst
, rShift
);
557 void sharRegReg(RegisterID dst
, RegisterID rShift
)
560 shaRegReg(dst
, rShift
);
563 void shaRegReg(RegisterID dst
, RegisterID rShift
)
565 uint16_t opc
= getOpcodeGroup1(SHAD_OPCODE
, dst
, rShift
);
569 void shlrImm8r(int imm
, RegisterID dst
)
573 oneShortOp(getOpcodeGroup2(SHLR_OPCODE
, dst
));
576 oneShortOp(getOpcodeGroup2(SHLR2_OPCODE
, dst
));
579 oneShortOp(getOpcodeGroup2(SHLR8_OPCODE
, dst
));
582 oneShortOp(getOpcodeGroup2(SHLR16_OPCODE
, dst
));
585 ASSERT_NOT_REACHED();
589 void imullRegReg(RegisterID src
, RegisterID dst
)
591 uint16_t opc
= getOpcodeGroup1(MULL_OPCODE
, dst
, src
);
595 void dmullRegReg(RegisterID src
, RegisterID dst
)
597 uint16_t opc
= getOpcodeGroup1(DMULL_L_OPCODE
, dst
, src
);
601 void dmulslRegReg(RegisterID src
, RegisterID dst
)
603 uint16_t opc
= getOpcodeGroup1(DMULSL_OPCODE
, dst
, src
);
607 void stsmacl(RegisterID reg
)
609 uint16_t opc
= getOpcodeGroup2(STSMACL_OPCODE
, reg
);
613 void stsmach(RegisterID reg
)
615 uint16_t opc
= getOpcodeGroup2(STSMACH_OPCODE
, reg
);
621 void cmplRegReg(RegisterID left
, RegisterID right
, Condition cond
)
625 oneShortOp(getOpcodeGroup1(CMPEQ_OPCODE
, right
, left
));
628 oneShortOp(getOpcodeGroup1(CMPGT_OPCODE
, right
, left
));
631 oneShortOp(getOpcodeGroup1(CMPEQ_OPCODE
, right
, left
));
634 oneShortOp(getOpcodeGroup1(CMPGE_OPCODE
, right
, left
));
637 oneShortOp(getOpcodeGroup1(CMPHS_OPCODE
, right
, left
));
640 oneShortOp(getOpcodeGroup1(CMPHI_OPCODE
, right
, left
));
643 oneShortOp(getOpcodeGroup1(CMPHI_OPCODE
, left
, right
));
646 oneShortOp(getOpcodeGroup1(CMPHS_OPCODE
, left
, right
));
649 oneShortOp(getOpcodeGroup1(CMPGE_OPCODE
, left
, right
));
652 oneShortOp(getOpcodeGroup1(CMPGT_OPCODE
, left
, right
));
655 ASSERT_NOT_REACHED();
659 void cmppl(RegisterID reg
)
661 uint16_t opc
= getOpcodeGroup2(CMPPL_OPCODE
, reg
);
665 void cmppz(RegisterID reg
)
667 uint16_t opc
= getOpcodeGroup2(CMPPZ_OPCODE
, reg
);
671 void cmpEqImmR0(int imm
, RegisterID dst
)
673 uint16_t opc
= getOpcodeGroup5(CMPEQIMM_OPCODE
, imm
);
677 void testlRegReg(RegisterID src
, RegisterID dst
)
679 uint16_t opc
= getOpcodeGroup1(TST_OPCODE
, dst
, src
);
683 void testlImm8r(int imm
, RegisterID dst
)
685 ASSERT((dst
== SH4Registers::r0
) && (imm
<= 255) && (imm
>= 0));
687 uint16_t opc
= getOpcodeGroup5(TSTIMM_OPCODE
, imm
);
693 oneShortOp(NOP_OPCODE
, false);
698 oneShortOp(SETT_OPCODE
);
703 oneShortOp(CLRT_OPCODE
);
708 oneShortOp(FSCHG_OPCODE
);
713 oneShortOp(BRK_OPCODE
, false);
716 void branch(uint16_t opc
, int label
)
720 ASSERT((label
<= 127) && (label
>= -128));
721 oneShortOp(getOpcodeGroup5(BT_OPCODE
, label
));
724 ASSERT((label
<= 2047) && (label
>= -2048));
725 oneShortOp(getOpcodeGroup6(BRA_OPCODE
, label
));
728 ASSERT((label
<= 127) && (label
>= -128));
729 oneShortOp(getOpcodeGroup5(BF_OPCODE
, label
));
732 ASSERT_NOT_REACHED();
736 void branch(uint16_t opc
, RegisterID reg
)
740 oneShortOp(getOpcodeGroup2(BRAF_OPCODE
, reg
));
743 oneShortOp(getOpcodeGroup2(JMP_OPCODE
, reg
));
746 oneShortOp(getOpcodeGroup2(JSR_OPCODE
, reg
));
749 oneShortOp(getOpcodeGroup2(BSRF_OPCODE
, reg
));
752 ASSERT_NOT_REACHED();
756 void ldspr(RegisterID reg
)
758 uint16_t opc
= getOpcodeGroup2(LDSPR_OPCODE
, reg
);
762 void stspr(RegisterID reg
)
764 uint16_t opc
= getOpcodeGroup2(STSPR_OPCODE
, reg
);
768 void extub(RegisterID src
, RegisterID dst
)
770 uint16_t opc
= getOpcodeGroup1(EXTUB_OPCODE
, dst
, src
);
774 void extuw(RegisterID src
, RegisterID dst
)
776 uint16_t opc
= getOpcodeGroup1(EXTUW_OPCODE
, dst
, src
);
782 void ldsrmfpul(RegisterID src
)
784 uint16_t opc
= getOpcodeGroup2(LDS_RM_FPUL_OPCODE
, src
);
788 void fneg(FPRegisterID dst
)
790 uint16_t opc
= getOpcodeGroup2(FNEG_OPCODE
, dst
);
791 oneShortOp(opc
, true, false);
794 void fsqrt(FPRegisterID dst
)
796 uint16_t opc
= getOpcodeGroup2(FSQRT_OPCODE
, dst
);
797 oneShortOp(opc
, true, false);
800 void stsfpulReg(RegisterID src
)
802 uint16_t opc
= getOpcodeGroup2(STS_FPUL_RN_OPCODE
, src
);
806 void floatfpulfrn(RegisterID src
)
808 uint16_t opc
= getOpcodeGroup2(FLOAT_OPCODE
, src
);
809 oneShortOp(opc
, true, false);
812 void fmull(FPRegisterID src
, FPRegisterID dst
)
814 uint16_t opc
= getOpcodeGroup1(FMUL_OPCODE
, dst
, src
);
815 oneShortOp(opc
, true, false);
818 void fmovsReadrm(RegisterID src
, FPRegisterID dst
)
820 uint16_t opc
= getOpcodeGroup1(FMOVS_READ_RM_OPCODE
, dst
, src
);
821 oneShortOp(opc
, true, false);
824 void fmovsWriterm(FPRegisterID src
, RegisterID dst
)
826 uint16_t opc
= getOpcodeGroup1(FMOVS_WRITE_RN_OPCODE
, dst
, src
);
827 oneShortOp(opc
, true, false);
830 void fmovsWriter0r(FPRegisterID src
, RegisterID dst
)
832 uint16_t opc
= getOpcodeGroup1(FMOVS_WRITE_R0RN_OPCODE
, dst
, src
);
833 oneShortOp(opc
, true, false);
836 void fmovsReadr0r(RegisterID src
, FPRegisterID dst
)
838 uint16_t opc
= getOpcodeGroup1(FMOVS_READ_R0RM_OPCODE
, dst
, src
);
839 oneShortOp(opc
, true, false);
842 void fmovsReadrminc(RegisterID src
, FPRegisterID dst
)
844 uint16_t opc
= getOpcodeGroup1(FMOVS_READ_RM_INC_OPCODE
, dst
, src
);
845 oneShortOp(opc
, true, false);
848 void fmovsWriterndec(FPRegisterID src
, RegisterID dst
)
850 uint16_t opc
= getOpcodeGroup1(FMOVS_WRITE_RN_DEC_OPCODE
, dst
, src
);
851 oneShortOp(opc
, true, false);
854 void ftrcRegfpul(FPRegisterID src
)
856 uint16_t opc
= getOpcodeGroup2(FTRC_OPCODE
, src
);
857 oneShortOp(opc
, true, false);
860 void fldsfpul(RegisterID src
)
862 uint16_t opc
= getOpcodeGroup2(FLDS_FRM_FPUL_OPCODE
, src
);
866 void fstsfpul(RegisterID src
)
868 uint16_t opc
= getOpcodeGroup2(FSTS_FPUL_FRN_OPCODE
, src
);
872 void ldsfpscr(RegisterID reg
)
874 uint16_t opc
= getOpcodeGroup2(LDSFPSCR_OPCODE
, reg
);
878 void stsfpscr(RegisterID reg
)
880 uint16_t opc
= getOpcodeGroup2(STSFPSCR_OPCODE
, reg
);
886 void dcnvds(FPRegisterID src
)
888 uint16_t opc
= getOpcodeGroup7(FCNVDS_DRM_FPUL_OPCODE
, src
>> 1);
892 void dcmppeq(FPRegisterID src
, FPRegisterID dst
)
894 uint16_t opc
= getOpcodeGroup8(FCMPEQ_OPCODE
, dst
>> 1, src
>> 1);
898 void dcmppgt(FPRegisterID src
, FPRegisterID dst
)
900 uint16_t opc
= getOpcodeGroup8(FCMPGT_OPCODE
, dst
>> 1, src
>> 1);
904 void dmulRegReg(FPRegisterID src
, FPRegisterID dst
)
906 uint16_t opc
= getOpcodeGroup8(FMUL_OPCODE
, dst
>> 1, src
>> 1);
910 void dsubRegReg(FPRegisterID src
, FPRegisterID dst
)
912 uint16_t opc
= getOpcodeGroup8(FSUB_OPCODE
, dst
>> 1, src
>> 1);
916 void daddRegReg(FPRegisterID src
, FPRegisterID dst
)
918 uint16_t opc
= getOpcodeGroup8(FADD_OPCODE
, dst
>> 1, src
>> 1);
922 void dmovRegReg(FPRegisterID src
, FPRegisterID dst
)
924 uint16_t opc
= getOpcodeGroup8(FMOV_OPCODE
, dst
>> 1, src
>> 1);
928 void ddivRegReg(FPRegisterID src
, FPRegisterID dst
)
930 uint16_t opc
= getOpcodeGroup8(FDIV_OPCODE
, dst
>> 1, src
>> 1);
934 void dsqrt(FPRegisterID dst
)
936 uint16_t opc
= getOpcodeGroup7(FSQRT_OPCODE
, dst
>> 1);
940 void dneg(FPRegisterID dst
)
942 uint16_t opc
= getOpcodeGroup7(FNEG_OPCODE
, dst
>> 1);
946 void fmovReadrm(RegisterID src
, FPRegisterID dst
)
948 uint16_t opc
= getOpcodeGroup10(FMOVS_READ_RM_OPCODE
, dst
>> 1, src
);
952 void fmovWriterm(FPRegisterID src
, RegisterID dst
)
954 uint16_t opc
= getOpcodeGroup9(FMOVS_WRITE_RN_OPCODE
, dst
, src
>> 1);
958 void fmovWriter0r(FPRegisterID src
, RegisterID dst
)
960 uint16_t opc
= getOpcodeGroup9(FMOVS_WRITE_R0RN_OPCODE
, dst
, src
>> 1);
964 void fmovReadr0r(RegisterID src
, FPRegisterID dst
)
966 uint16_t opc
= getOpcodeGroup10(FMOVS_READ_R0RM_OPCODE
, dst
>> 1, src
);
970 void fmovReadrminc(RegisterID src
, FPRegisterID dst
)
972 uint16_t opc
= getOpcodeGroup10(FMOVS_READ_RM_INC_OPCODE
, dst
>> 1, src
);
976 void fmovWriterndec(FPRegisterID src
, RegisterID dst
)
978 uint16_t opc
= getOpcodeGroup9(FMOVS_WRITE_RN_DEC_OPCODE
, dst
, src
>> 1);
982 void floatfpulDreg(FPRegisterID src
)
984 uint16_t opc
= getOpcodeGroup7(FLOAT_OPCODE
, src
>> 1);
988 void ftrcdrmfpul(FPRegisterID src
)
990 uint16_t opc
= getOpcodeGroup7(FTRC_OPCODE
, src
>> 1);
996 void movImm8(int imm8
, RegisterID dst
)
998 ASSERT((imm8
<= 127) && (imm8
>= -128));
1000 uint16_t opc
= getOpcodeGroup3(MOVIMM_OPCODE
, dst
, imm8
);
1004 void movlRegReg(RegisterID src
, RegisterID dst
)
1006 uint16_t opc
= getOpcodeGroup1(MOV_OPCODE
, dst
, src
);
1010 void movwRegMem(RegisterID src
, RegisterID dst
)
1012 uint16_t opc
= getOpcodeGroup1(MOVW_WRITE_RN_OPCODE
, dst
, src
);
1016 void movwMemReg(RegisterID src
, RegisterID dst
)
1018 uint16_t opc
= getOpcodeGroup1(MOVW_READ_RM_OPCODE
, dst
, src
);
1022 void movwPCReg(int offset
, RegisterID base
, RegisterID dst
)
1024 ASSERT(base
== SH4Registers::pc
);
1025 ASSERT((offset
<= 255) && (offset
>= 0));
1027 uint16_t opc
= getOpcodeGroup3(MOVW_READ_OFFPC_OPCODE
, dst
, offset
);
1031 void movwMemReg(int offset
, RegisterID base
, RegisterID dst
)
1033 ASSERT(dst
== SH4Registers::r0
);
1035 uint16_t opc
= getOpcodeGroup11(MOVW_READ_OFFRM_OPCODE
, base
, offset
);
1039 void movwR0mr(RegisterID src
, RegisterID dst
)
1041 uint16_t opc
= getOpcodeGroup1(MOVW_READ_R0RM_OPCODE
, dst
, src
);
1045 void movlRegMem(RegisterID src
, int offset
, RegisterID base
)
1047 ASSERT((offset
<= 15) && (offset
>= 0));
1050 oneShortOp(getOpcodeGroup1(MOVL_WRITE_RN_OPCODE
, base
, src
));
1054 oneShortOp(getOpcodeGroup4(MOVL_WRITE_OFFRN_OPCODE
, base
, src
, offset
));
1057 void movlRegMem(RegisterID src
, RegisterID base
)
1059 uint16_t opc
= getOpcodeGroup1(MOVL_WRITE_RN_OPCODE
, base
, src
);
1063 void movlMemReg(int offset
, RegisterID base
, RegisterID dst
)
1065 if (base
== SH4Registers::pc
) {
1066 ASSERT((offset
<= 255) && (offset
>= 0));
1067 oneShortOp(getOpcodeGroup3(MOVL_READ_OFFPC_OPCODE
, dst
, offset
));
1071 ASSERT((offset
<= 15) && (offset
>= 0));
1073 oneShortOp(getOpcodeGroup1(MOVL_READ_RM_OPCODE
, dst
, base
));
1077 oneShortOp(getOpcodeGroup4(MOVL_READ_OFFRM_OPCODE
, dst
, base
, offset
));
1080 void movlMemRegCompact(int offset
, RegisterID base
, RegisterID dst
)
1082 oneShortOp(getOpcodeGroup4(MOVL_READ_OFFRM_OPCODE
, dst
, base
, offset
));
1085 void movbMemReg(int offset
, RegisterID base
, RegisterID dst
)
1087 ASSERT(dst
== SH4Registers::r0
);
1089 uint16_t opc
= getOpcodeGroup11(MOVB_READ_OFFRM_OPCODE
, base
, offset
);
1093 void movbR0mr(RegisterID src
, RegisterID dst
)
1095 uint16_t opc
= getOpcodeGroup1(MOVB_READ_R0RM_OPCODE
, dst
, src
);
1099 void movbMemReg(RegisterID src
, RegisterID dst
)
1101 uint16_t opc
= getOpcodeGroup1(MOVB_READ_RM_OPCODE
, dst
, src
);
1105 void movlMemReg(RegisterID base
, RegisterID dst
)
1107 uint16_t opc
= getOpcodeGroup1(MOVL_READ_RM_OPCODE
, dst
, base
);
1111 void movlMemRegIn(RegisterID base
, RegisterID dst
)
1113 uint16_t opc
= getOpcodeGroup1(MOVL_READ_RMINC_OPCODE
, dst
, base
);
1117 void movlR0mr(RegisterID src
, RegisterID dst
)
1119 uint16_t opc
= getOpcodeGroup1(MOVL_READ_R0RM_OPCODE
, dst
, src
);
1123 void movlRegMemr0(RegisterID src
, RegisterID dst
)
1125 uint16_t opc
= getOpcodeGroup1(MOVL_WRITE_R0RN_OPCODE
, dst
, src
);
1129 void movlImm8r(int imm8
, RegisterID dst
)
1131 ASSERT((imm8
<= 127) && (imm8
>= -128));
1133 uint16_t opc
= getOpcodeGroup3(MOVIMM_OPCODE
, dst
, imm8
);
1137 void loadConstant(uint32_t constant
, RegisterID dst
)
1139 if (((int)constant
<= 0x7f) && ((int)constant
>= -0x80)) {
1140 movImm8(constant
, dst
);
1144 uint16_t opc
= getOpcodeGroup3(MOVIMM_OPCODE
, dst
, 0);
1146 m_buffer
.ensureSpace(maxInstructionSize
, sizeof(uint32_t));
1147 printInstr(getOpcodeGroup3(MOVIMM_OPCODE
, dst
, constant
), m_buffer
.codeSize());
1148 m_buffer
.putShortWithConstantInt(opc
, constant
, true);
1151 void loadConstantUnReusable(uint32_t constant
, RegisterID dst
, bool ensureSpace
= false)
1153 uint16_t opc
= getOpcodeGroup3(MOVIMM_OPCODE
, dst
, 0);
1156 m_buffer
.ensureSpace(maxInstructionSize
, sizeof(uint32_t));
1158 printInstr(getOpcodeGroup3(MOVIMM_OPCODE
, dst
, constant
), m_buffer
.codeSize());
1159 m_buffer
.putShortWithConstantInt(opc
, constant
);
1164 AssemblerLabel
call()
1166 RegisterID scr
= claimScratch();
1167 m_buffer
.ensureSpace(maxInstructionSize
+ 4, sizeof(uint32_t));
1168 loadConstantUnReusable(0x0, scr
);
1169 branch(JSR_OPCODE
, scr
);
1171 releaseScratch(scr
);
1172 return m_buffer
.label();
1175 AssemblerLabel
call(RegisterID dst
)
1177 m_buffer
.ensureSpace(maxInstructionSize
+ 2);
1178 branch(JSR_OPCODE
, dst
);
1180 return m_buffer
.label();
1183 AssemblerLabel
jmp()
1185 RegisterID scr
= claimScratch();
1186 m_buffer
.ensureSpace(maxInstructionSize
+ 4, sizeof(uint32_t));
1187 AssemblerLabel label
= m_buffer
.label();
1188 loadConstantUnReusable(0x0, scr
);
1189 branch(BRAF_OPCODE
, scr
);
1191 releaseScratch(scr
);
1195 void extraInstrForBranch(RegisterID dst
)
1197 loadConstantUnReusable(0x0, dst
);
1202 AssemblerLabel
jmp(RegisterID dst
)
1205 return m_buffer
.label();
1208 void jmpReg(RegisterID dst
)
1210 m_buffer
.ensureSpace(maxInstructionSize
+ 2);
1211 branch(JMP_OPCODE
, dst
);
1215 AssemblerLabel
jne()
1217 AssemblerLabel label
= m_buffer
.label();
1218 branch(BF_OPCODE
, 0);
1224 AssemblerLabel label
= m_buffer
.label();
1225 branch(BT_OPCODE
, 0);
1229 AssemblerLabel
bra()
1231 AssemblerLabel label
= m_buffer
.label();
1232 branch(BRA_OPCODE
, 0);
1238 m_buffer
.ensureSpace(maxInstructionSize
+ 2);
1239 oneShortOp(RTS_OPCODE
, false);
1242 AssemblerLabel
label()
1244 m_buffer
.ensureSpaceForAnyOneInstruction();
1245 return m_buffer
.label();
1248 int sizeOfConstantPool()
1250 return m_buffer
.sizeOfConstantPool();
1253 AssemblerLabel
align(int alignment
)
1255 m_buffer
.ensureSpace(maxInstructionSize
+ 2);
1256 while (!m_buffer
.isAligned(alignment
)) {
1258 m_buffer
.ensureSpace(maxInstructionSize
+ 2);
1263 static void changePCrelativeAddress(int offset
, uint16_t* instructionPtr
, uint32_t newAddress
)
1265 uint32_t address
= (offset
<< 2) + ((reinterpret_cast<uint32_t>(instructionPtr
) + 4) &(~0x3));
1266 *reinterpret_cast<uint32_t*>(address
) = newAddress
;
1269 static uint32_t readPCrelativeAddress(int offset
, uint16_t* instructionPtr
)
1271 uint32_t address
= (offset
<< 2) + ((reinterpret_cast<uint32_t>(instructionPtr
) + 4) &(~0x3));
1272 return *reinterpret_cast<uint32_t*>(address
);
1275 static uint16_t* getInstructionPtr(void* code
, int offset
)
1277 return reinterpret_cast<uint16_t*> (reinterpret_cast<uint32_t>(code
) + offset
);
1280 static void linkJump(void* code
, AssemblerLabel from
, void* to
)
1282 ASSERT(from
.isSet());
1284 uint16_t* instructionPtr
= getInstructionPtr(code
, from
.m_offset
);
1285 uint16_t instruction
= *instructionPtr
;
1286 int offsetBits
= (reinterpret_cast<uint32_t>(to
) - reinterpret_cast<uint32_t>(code
)) - from
.m_offset
;
1288 if (((instruction
& 0xff00) == BT_OPCODE
) || ((instruction
& 0xff00) == BF_OPCODE
)) {
1289 /* BT label ==> BF 2
1295 instruction
^= 0x0202;
1296 *instructionPtr
++ = instruction
;
1297 changePCrelativeAddress((*instructionPtr
& 0xff), instructionPtr
, offsetBits
);
1298 instruction
= (BRAF_OPCODE
| (*instructionPtr
++ & 0xf00));
1299 *instructionPtr
= instruction
;
1300 printBlockInstr(instructionPtr
- 2, from
.m_offset
, 3);
1304 /* MOV #imm, reg => LDR reg
1308 ASSERT((*(instructionPtr
+ 1) & BRAF_OPCODE
) == BRAF_OPCODE
);
1311 if (offsetBits
>= -4096 && offsetBits
<= 4094) {
1312 *instructionPtr
= getOpcodeGroup6(BRA_OPCODE
, offsetBits
>> 1);
1313 *(++instructionPtr
) = NOP_OPCODE
;
1314 printBlockInstr(instructionPtr
- 1, from
.m_offset
, 2);
1318 changePCrelativeAddress((*instructionPtr
& 0xff), instructionPtr
, offsetBits
- 2);
1319 printInstr(*instructionPtr
, from
.m_offset
+ 2);
1322 static void linkCall(void* code
, AssemblerLabel from
, void* to
)
1324 uint16_t* instructionPtr
= getInstructionPtr(code
, from
.m_offset
);
1325 instructionPtr
-= 3;
1326 changePCrelativeAddress((*instructionPtr
& 0xff), instructionPtr
, reinterpret_cast<uint32_t>(to
));
1329 static void linkPointer(void* code
, AssemblerLabel where
, void* value
)
1331 uint16_t* instructionPtr
= getInstructionPtr(code
, where
.m_offset
);
1332 changePCrelativeAddress((*instructionPtr
& 0xff), instructionPtr
, reinterpret_cast<uint32_t>(value
));
1335 static unsigned getCallReturnOffset(AssemblerLabel call
)
1337 ASSERT(call
.isSet());
1338 return call
.m_offset
;
1341 static uint32_t* getLdrImmAddressOnPool(SH4Word
* insn
, uint32_t* constPool
)
1343 return (constPool
+ (*insn
& 0xff));
1346 static SH4Word
patchConstantPoolLoad(SH4Word load
, int value
)
1348 return ((load
& ~0xff) | value
);
1351 static SH4Buffer::TwoShorts
placeConstantPoolBarrier(int offset
)
1353 ASSERT(((offset
>> 1) <=2047) && ((offset
>> 1) >= -2048));
1355 SH4Buffer::TwoShorts m_barrier
;
1356 m_barrier
.high
= (BRA_OPCODE
| (offset
>> 1));
1357 m_barrier
.low
= NOP_OPCODE
;
1358 printInstr(((BRA_OPCODE
| (offset
>> 1))), 0);
1359 printInstr(NOP_OPCODE
, 0);
1363 static void patchConstantPoolLoad(void* loadAddr
, void* constPoolAddr
)
1365 SH4Word
* instructionPtr
= reinterpret_cast<SH4Word
*>(loadAddr
);
1366 SH4Word instruction
= *instructionPtr
;
1367 SH4Word index
= instruction
& 0xff;
1369 if ((instruction
& 0xf000) != MOVIMM_OPCODE
)
1372 ASSERT((((reinterpret_cast<uint32_t>(constPoolAddr
) - reinterpret_cast<uint32_t>(loadAddr
)) + index
* 4)) < 1024);
1374 int offset
= reinterpret_cast<uint32_t>(constPoolAddr
) + (index
* 4) - ((reinterpret_cast<uint32_t>(instructionPtr
) & ~0x03) + 4);
1375 instruction
&=0xf00;
1376 instruction
|= 0xd000;
1378 instruction
|= (offset
>> 2);
1379 *instructionPtr
= instruction
;
1380 printInstr(instruction
, reinterpret_cast<uint32_t>(loadAddr
));
1383 static void repatchPointer(void* where
, void* value
)
1385 patchPointer(where
, value
);
1388 static void* readPointer(void* code
)
1390 return reinterpret_cast<void*>(readInt32(code
));
1393 static void repatchInt32(void* where
, int32_t value
)
1395 uint16_t* instructionPtr
= reinterpret_cast<uint16_t*>(where
);
1396 changePCrelativeAddress((*instructionPtr
& 0xff), instructionPtr
, value
);
1399 static void repatchCompact(void* where
, int32_t value
)
1402 ASSERT(value
<= 60);
1403 *reinterpret_cast<uint16_t*>(where
) = ((*reinterpret_cast<uint16_t*>(where
) & 0xfff0) | (value
>> 2));
1404 cacheFlush(reinterpret_cast<uint16_t*>(where
), sizeof(uint16_t));
1407 static void relinkCall(void* from
, void* to
)
1409 uint16_t* instructionPtr
= reinterpret_cast<uint16_t*>(from
);
1410 instructionPtr
-= 3;
1411 changePCrelativeAddress((*instructionPtr
& 0xff), instructionPtr
, reinterpret_cast<uint32_t>(to
));
1414 static void relinkJump(void* from
, void* to
)
1416 uint16_t* instructionPtr
= reinterpret_cast<uint16_t*> (from
);
1417 uint16_t instruction
= *instructionPtr
;
1418 int32_t offsetBits
= (reinterpret_cast<uint32_t>(to
) - reinterpret_cast<uint32_t>(from
));
1420 if (((*instructionPtr
& 0xff00) == BT_OPCODE
) || ((*instructionPtr
& 0xff00) == BF_OPCODE
)) {
1423 changePCrelativeAddress((*instructionPtr
& 0xff), instructionPtr
, offsetBits
);
1424 instruction
= (BRAF_OPCODE
| (*instructionPtr
++ & 0xf00));
1425 *instructionPtr
= instruction
;
1426 printBlockInstr(instructionPtr
, reinterpret_cast<uint32_t>(from
) + 1, 3);
1430 ASSERT((*(instructionPtr
+ 1) & BRAF_OPCODE
) == BRAF_OPCODE
);
1432 if (offsetBits
>= -4096 && offsetBits
<= 4094) {
1433 *instructionPtr
= getOpcodeGroup6(BRA_OPCODE
, offsetBits
>> 1);
1434 *(++instructionPtr
) = NOP_OPCODE
;
1435 printBlockInstr(instructionPtr
- 2, reinterpret_cast<uint32_t>(from
), 2);
1439 changePCrelativeAddress((*instructionPtr
& 0xff), instructionPtr
, offsetBits
- 2);
1440 printInstr(*instructionPtr
, reinterpret_cast<uint32_t>(from
));
1443 // Linking & patching
1445 void linkJump(AssemblerLabel from
, AssemblerLabel to
, JumpType type
= JumpFar
)
1448 ASSERT(from
.isSet());
1450 uint16_t* instructionPtr
= getInstructionPtr(data(), from
.m_offset
);
1451 uint16_t instruction
= *instructionPtr
;
1454 if (type
== JumpNear
) {
1455 ASSERT((instruction
== BT_OPCODE
) || (instruction
== BF_OPCODE
) || (instruction
== BRA_OPCODE
));
1456 int offset
= (codeSize() - from
.m_offset
) - 4;
1457 *instructionPtr
++ = instruction
| (offset
>> 1);
1458 printInstr(*instructionPtr
, from
.m_offset
+ 2);
1462 if (((instruction
& 0xff00) == BT_OPCODE
) || ((instruction
& 0xff00) == BF_OPCODE
)) {
1468 offsetBits
= (to
.m_offset
- from
.m_offset
) - 8;
1469 instruction
^= 0x0202;
1470 *instructionPtr
++ = instruction
;
1471 if ((*instructionPtr
& 0xf000) == 0xe000) {
1472 uint32_t* addr
= getLdrImmAddressOnPool(instructionPtr
, m_buffer
.poolAddress());
1475 changePCrelativeAddress((*instructionPtr
& 0xff), instructionPtr
, offsetBits
);
1476 instruction
= (BRAF_OPCODE
| (*instructionPtr
++ & 0xf00));
1477 *instructionPtr
= instruction
;
1478 printBlockInstr(instructionPtr
- 2, from
.m_offset
, 3);
1482 /* MOV # imm, reg => LDR reg
1486 ASSERT((*(instructionPtr
+ 1) & BRAF_OPCODE
) == BRAF_OPCODE
);
1487 offsetBits
= (to
.m_offset
- from
.m_offset
) - 4;
1488 if (offsetBits
>= -4096 && offsetBits
<= 4094) {
1489 *instructionPtr
= getOpcodeGroup6(BRA_OPCODE
, offsetBits
>> 1);
1490 *(++instructionPtr
) = NOP_OPCODE
;
1491 printBlockInstr(instructionPtr
- 1, from
.m_offset
, 2);
1495 instruction
= *instructionPtr
;
1496 if ((instruction
& 0xf000) == 0xe000) {
1497 uint32_t* addr
= getLdrImmAddressOnPool(instructionPtr
, m_buffer
.poolAddress());
1498 *addr
= offsetBits
- 2;
1499 printInstr(*instructionPtr
, from
.m_offset
+ 2);
1503 changePCrelativeAddress((*instructionPtr
& 0xff), instructionPtr
, offsetBits
- 2);
1504 printInstr(*instructionPtr
, from
.m_offset
+ 2);
1507 static void* getRelocatedAddress(void* code
, AssemblerLabel label
)
1509 return reinterpret_cast<void*>(reinterpret_cast<char*>(code
) + label
.m_offset
);
1512 static int getDifferenceBetweenLabels(AssemblerLabel a
, AssemblerLabel b
)
1514 return b
.m_offset
- a
.m_offset
;
1517 static void patchPointer(void* code
, AssemblerLabel where
, void* value
)
1519 patchPointer(reinterpret_cast<uint32_t*>(code
) + where
.m_offset
, value
);
1522 static void patchPointer(void* code
, void* value
)
1524 patchInt32(code
, reinterpret_cast<uint32_t>(value
));
1527 static void patchInt32(void* code
, uint32_t value
)
1529 changePCrelativeAddress((*(reinterpret_cast<uint16_t*>(code
)) & 0xff), reinterpret_cast<uint16_t*>(code
), value
);
1532 static uint32_t readInt32(void* code
)
1534 return readPCrelativeAddress((*(reinterpret_cast<uint16_t*>(code
)) & 0xff), reinterpret_cast<uint16_t*>(code
));
1537 static void* readCallTarget(void* from
)
1539 uint16_t* instructionPtr
= static_cast<uint16_t*>(from
);
1540 instructionPtr
-= 3;
1541 return reinterpret_cast<void*>(readPCrelativeAddress((*instructionPtr
& 0xff), instructionPtr
));
1544 PassRefPtr
<ExecutableMemoryHandle
> executableCopy(JSGlobalData
& globalData
, void* ownerUID
, JITCompilationEffort effort
)
1546 return m_buffer
.executableCopy(globalData
, ownerUID
, effort
);
1549 static void cacheFlush(void* code
, size_t size
)
1552 #error "The cacheFlush support is missing on this platform."
1553 #elif defined CACHEFLUSH_D_L2
1554 syscall(__NR_cacheflush
, reinterpret_cast<unsigned>(code
), size
, CACHEFLUSH_D_WB
| CACHEFLUSH_I
| CACHEFLUSH_D_L2
);
1556 syscall(__NR_cacheflush
, reinterpret_cast<unsigned>(code
), size
, CACHEFLUSH_D_WB
| CACHEFLUSH_I
);
1560 void prefix(uint16_t pre
)
1562 m_buffer
.putByte(pre
);
1565 void oneShortOp(uint16_t opcode
, bool checksize
= true, bool isDouble
= true)
1567 printInstr(opcode
, m_buffer
.codeSize(), isDouble
);
1569 m_buffer
.ensureSpace(maxInstructionSize
);
1570 m_buffer
.putShortUnchecked(opcode
);
1573 void ensureSpace(int space
)
1575 m_buffer
.ensureSpace(space
);
1578 void ensureSpace(int insnSpace
, int constSpace
)
1580 m_buffer
.ensureSpace(insnSpace
, constSpace
);
1583 // Administrative methods
1585 void* data() const { return m_buffer
.data(); }
1586 size_t codeSize() const { return m_buffer
.codeSize(); }
1588 #ifdef SH4_ASSEMBLER_TRACING
1589 static void printInstr(uint16_t opc
, unsigned int size
, bool isdoubleInst
= true)
1591 if (!getenv("JavaScriptCoreDumpJIT"))
1594 const char *format
= 0;
1595 printfStdoutInstr("offset: 0x%8.8x\t", size
);
1616 format
= " FSCHG\n";
1620 printfStdoutInstr(format
);
1623 switch (opc
& 0xf0ff) {
1625 format
= " *BRAF R%d\n";
1628 format
= " DT R%d\n";
1631 format
= " CMP/PL R%d\n";
1634 format
= " CMP/PZ R%d\n";
1637 format
= " *JMP @R%d\n";
1640 format
= " *JSR @R%d\n";
1643 format
= " LDS R%d, PR\n";
1646 format
= " LDS.L @R%d+, PR\n";
1649 format
= " MOVT R%d\n";
1652 format
= " SHAL R%d\n";
1655 format
= " SHAR R%d\n";
1658 format
= " SHLL R%d\n";
1661 format
= " SHLL2 R%d\n";
1664 format
= " SHLL8 R%d\n";
1667 format
= " SHLL16 R%d\n";
1670 format
= " SHLR R%d\n";
1673 format
= " SHLR2 R%d\n";
1676 format
= " SHLR8 R%d\n";
1679 format
= " SHLR16 R%d\n";
1682 format
= " STS PR, R%d\n";
1685 format
= " STS.L PR, @-R%d\n";
1687 case LDS_RM_FPUL_OPCODE
:
1688 format
= " LDS R%d, FPUL\n";
1690 case STS_FPUL_RN_OPCODE
:
1691 format
= " STS FPUL, R%d \n";
1693 case FLDS_FRM_FPUL_OPCODE
:
1694 format
= " FLDS FR%d, FPUL\n";
1696 case FSTS_FPUL_FRN_OPCODE
:
1697 format
= " FSTS FPUL, R%d \n";
1699 case LDSFPSCR_OPCODE
:
1700 format
= " LDS R%d, FPSCR \n";
1702 case STSFPSCR_OPCODE
:
1703 format
= " STS FPSCR, R%d \n";
1705 case STSMACL_OPCODE
:
1706 format
= " STS MACL, R%d \n";
1708 case STSMACH_OPCODE
:
1709 format
= " STS MACH, R%d \n";
1712 format
= " *BSRF R%d";
1715 format
= " FTRC FR%d, FPUL\n";
1719 printfStdoutInstr(format
, getRn(opc
));
1722 switch (opc
& 0xf0ff) {
1724 format
= " FNEG DR%d\n";
1727 format
= " FLOAT DR%d\n";
1730 format
= " FTRC FR%d, FPUL\n";
1733 format
= " FSQRT FR%d\n";
1735 case FCNVDS_DRM_FPUL_OPCODE
:
1736 format
= " FCNVDS FR%d, FPUL\n";
1741 printfStdoutInstr(format
, getDRn(opc
) << 1);
1743 printfStdoutInstr(format
, getRn(opc
));
1746 switch (opc
& 0xf00f) {
1748 format
= " ADD R%d, R%d\n";
1751 format
= " ADDC R%d, R%d\n";
1754 format
= " ADDV R%d, R%d\n";
1757 format
= " AND R%d, R%d\n";
1760 format
= " DIV1 R%d, R%d\n";
1763 format
= " CMP/EQ R%d, R%d\n";
1766 format
= " CMP/GE R%d, R%d\n";
1769 format
= " CMP/GT R%d, R%d\n";
1772 format
= " CMP/HI R%d, R%d\n";
1775 format
= " CMP/HS R%d, R%d\n";
1778 format
= " MOV R%d, R%d\n";
1780 case MOVB_WRITE_RN_OPCODE
:
1781 format
= " MOV.B R%d, @R%d\n";
1783 case MOVB_WRITE_RNDEC_OPCODE
:
1784 format
= " MOV.B R%d, @-R%d\n";
1786 case MOVB_WRITE_R0RN_OPCODE
:
1787 format
= " MOV.B R%d, @(R0, R%d)\n";
1789 case MOVB_READ_RM_OPCODE
:
1790 format
= " MOV.B @R%d, R%d\n";
1792 case MOVB_READ_RMINC_OPCODE
:
1793 format
= " MOV.B @R%d+, R%d\n";
1795 case MOVB_READ_R0RM_OPCODE
:
1796 format
= " MOV.B @(R0, R%d), R%d\n";
1798 case MOVL_WRITE_RN_OPCODE
:
1799 format
= " MOV.L R%d, @R%d\n";
1801 case MOVL_WRITE_RNDEC_OPCODE
:
1802 format
= " MOV.L R%d, @-R%d\n";
1804 case MOVL_WRITE_R0RN_OPCODE
:
1805 format
= " MOV.L R%d, @(R0, R%d)\n";
1807 case MOVL_READ_RM_OPCODE
:
1808 format
= " MOV.L @R%d, R%d\n";
1810 case MOVL_READ_RMINC_OPCODE
:
1811 format
= " MOV.L @R%d+, R%d\n";
1813 case MOVL_READ_R0RM_OPCODE
:
1814 format
= " MOV.L @(R0, R%d), R%d\n";
1817 format
= " MUL.L R%d, R%d\n";
1819 case DMULL_L_OPCODE
:
1820 format
= " DMULU.L R%d, R%d\n";
1823 format
= " DMULS.L R%d, R%d\n";
1826 format
= " NEG R%d, R%d\n";
1829 format
= " NEGC R%d, R%d\n";
1832 format
= " NOT R%d, R%d\n";
1835 format
= " OR R%d, R%d\n";
1838 format
= " SHAD R%d, R%d\n";
1841 format
= " SHLD R%d, R%d\n";
1844 format
= " SUB R%d, R%d\n";
1847 format
= " SUBC R%d, R%d\n";
1850 format
= " SUBV R%d, R%d\n";
1853 format
= " TST R%d, R%d\n";
1856 format
= " XOR R%d, R%d\n";break;
1857 case MOVW_WRITE_RN_OPCODE
:
1858 format
= " MOV.W R%d, @R%d\n";
1860 case MOVW_READ_RM_OPCODE
:
1861 format
= " MOV.W @R%d, R%d\n";
1863 case MOVW_READ_R0RM_OPCODE
:
1864 format
= " MOV.W @(R0, R%d), R%d\n";
1867 format
= " EXTU.B R%d, R%d\n";
1870 format
= " EXTU.W R%d, R%d\n";
1874 printfStdoutInstr(format
, getRm(opc
), getRn(opc
));
1877 switch (opc
& 0xf00f) {
1879 format
= " FSUB FR%d, FR%d\n";
1882 format
= " FADD FR%d, FR%d\n";
1885 format
= " FDIV FR%d, FR%d\n";
1888 format
= " DMULL FR%d, FR%d\n";
1891 format
= " FMOV FR%d, FR%d\n";
1894 format
= " FCMP/EQ FR%d, FR%d\n";
1897 format
= " FCMP/GT FR%d, FR%d\n";
1902 printfStdoutInstr(format
, getDRm(opc
) << 1, getDRn(opc
) << 1);
1904 printfStdoutInstr(format
, getRm(opc
), getRn(opc
));
1907 switch (opc
& 0xf00f) {
1908 case FMOVS_WRITE_RN_DEC_OPCODE
:
1909 format
= " %s FR%d, @-R%d\n";
1911 case FMOVS_WRITE_RN_OPCODE
:
1912 format
= " %s FR%d, @R%d\n";
1914 case FMOVS_WRITE_R0RN_OPCODE
:
1915 format
= " %s FR%d, @(R0, R%d)\n";
1920 printfStdoutInstr(format
, "FMOV", getDRm(opc
) << 1, getDRn(opc
));
1922 printfStdoutInstr(format
, "FMOV.S", getRm(opc
), getRn(opc
));
1925 switch (opc
& 0xf00f) {
1926 case FMOVS_READ_RM_OPCODE
:
1927 format
= " %s @R%d, FR%d\n";
1929 case FMOVS_READ_RM_INC_OPCODE
:
1930 format
= " %s @R%d+, FR%d\n";
1932 case FMOVS_READ_R0RM_OPCODE
:
1933 format
= " %s @(R0, R%d), FR%d\n";
1938 printfStdoutInstr(format
, "FMOV", getDRm(opc
), getDRn(opc
) << 1);
1940 printfStdoutInstr(format
, "FMOV.S", getRm(opc
), getRn(opc
));
1943 switch (opc
& 0xff00) {
1945 format
= " BF %d\n";
1948 format
= " *BF/S %d\n";
1951 format
= " AND #%d, R0\n";
1954 format
= " BT %d\n";
1957 format
= " *BT/S %d\n";
1959 case CMPEQIMM_OPCODE
:
1960 format
= " CMP/EQ #%d, R0\n";
1962 case MOVB_WRITE_OFFGBR_OPCODE
:
1963 format
= " MOV.B R0, @(%d, GBR)\n";
1965 case MOVB_READ_OFFGBR_OPCODE
:
1966 format
= " MOV.B @(%d, GBR), R0\n";
1968 case MOVL_WRITE_OFFGBR_OPCODE
:
1969 format
= " MOV.L R0, @(%d, GBR)\n";
1971 case MOVL_READ_OFFGBR_OPCODE
:
1972 format
= " MOV.L @(%d, GBR), R0\n";
1974 case MOVA_READ_OFFPC_OPCODE
:
1975 format
= " MOVA @(%d, PC), R0\n";
1978 format
= " OR #%d, R0\n";
1981 format
= " OR.B #%d, @(R0, GBR)\n";
1984 format
= " TST #%d, R0\n";
1987 format
= " TST.B %d, @(R0, GBR)\n";
1990 format
= " XOR #%d, R0\n";
1993 format
= " XOR.B %d, @(R0, GBR)\n";
1997 printfStdoutInstr(format
, getImm8(opc
));
2000 switch (opc
& 0xff00) {
2001 case MOVB_WRITE_OFFRN_OPCODE
:
2002 format
= " MOV.B R0, @(%d, R%d)\n";
2004 case MOVB_READ_OFFRM_OPCODE
:
2005 format
= " MOV.B @(%d, R%d), R0\n";
2009 printfStdoutInstr(format
, getDisp(opc
), getRm(opc
));
2012 switch (opc
& 0xf000) {
2014 format
= " *BRA %d\n";
2017 format
= " *BSR %d\n";
2021 printfStdoutInstr(format
, getImm12(opc
));
2024 switch (opc
& 0xf000) {
2025 case MOVL_READ_OFFPC_OPCODE
:
2026 format
= " MOV.L @(%d, PC), R%d\n";
2029 format
= " ADD #%d, R%d\n";
2032 format
= " MOV #%d, R%d\n";
2034 case MOVW_READ_OFFPC_OPCODE
:
2035 format
= " MOV.W @(%d, PC), R%d\n";
2039 printfStdoutInstr(format
, getImm8(opc
), getRn(opc
));
2042 switch (opc
& 0xf000) {
2043 case MOVL_WRITE_OFFRN_OPCODE
:
2044 format
= " MOV.L R%d, @(%d, R%d)\n";
2045 printfStdoutInstr(format
, getRm(opc
), getDisp(opc
), getRn(opc
));
2047 case MOVL_READ_OFFRM_OPCODE
:
2048 format
= " MOV.L @(%d, R%d), R%d\n";
2049 printfStdoutInstr(format
, getDisp(opc
), getRm(opc
), getRn(opc
));
2054 static void printfStdoutInstr(const char* format
, ...)
2056 if (getenv("JavaScriptCoreDumpJIT")) {
2058 va_start(args
, format
);
2059 vprintfStdoutInstr(format
, args
);
2064 static void vprintfStdoutInstr(const char* format
, va_list args
)
2066 if (getenv("JavaScriptCoreDumpJIT"))
2067 WTF::dataLogV(format
, args
);
2070 static void printBlockInstr(uint16_t* first
, unsigned int offset
, int nbInstr
)
2072 printfStdoutInstr(">> repatch instructions after link\n");
2073 for (int i
= 0; i
<= nbInstr
; i
++)
2074 printInstr(*(first
+ i
), offset
+ i
);
2075 printfStdoutInstr(">> end repatch\n");
2078 static void printInstr(uint16_t opc
, unsigned int size
, bool isdoubleInst
= true) {};
2079 static void printBlockInstr(uint16_t* first
, unsigned int offset
, int nbInstr
) {};
2084 int m_claimscratchReg
;
2089 #endif // ENABLE(ASSEMBLER) && CPU(SH4)
2091 #endif // SH4Assembler_h