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.ensureSpaceForAnyInstruction();
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