1*22dc650dSSadaf Ebrahimi /*
2*22dc650dSSadaf Ebrahimi * Stack-less Just-In-Time compiler
3*22dc650dSSadaf Ebrahimi *
4*22dc650dSSadaf Ebrahimi * Copyright Zoltan Herczeg ([email protected]). All rights reserved.
5*22dc650dSSadaf Ebrahimi *
6*22dc650dSSadaf Ebrahimi * Redistribution and use in source and binary forms, with or without modification, are
7*22dc650dSSadaf Ebrahimi * permitted provided that the following conditions are met:
8*22dc650dSSadaf Ebrahimi *
9*22dc650dSSadaf Ebrahimi * 1. Redistributions of source code must retain the above copyright notice, this list of
10*22dc650dSSadaf Ebrahimi * conditions and the following disclaimer.
11*22dc650dSSadaf Ebrahimi *
12*22dc650dSSadaf Ebrahimi * 2. Redistributions in binary form must reproduce the above copyright notice, this list
13*22dc650dSSadaf Ebrahimi * of conditions and the following disclaimer in the documentation and/or other materials
14*22dc650dSSadaf Ebrahimi * provided with the distribution.
15*22dc650dSSadaf Ebrahimi *
16*22dc650dSSadaf Ebrahimi * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
17*22dc650dSSadaf Ebrahimi * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18*22dc650dSSadaf Ebrahimi * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19*22dc650dSSadaf Ebrahimi * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20*22dc650dSSadaf Ebrahimi * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21*22dc650dSSadaf Ebrahimi * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
22*22dc650dSSadaf Ebrahimi * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23*22dc650dSSadaf Ebrahimi * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24*22dc650dSSadaf Ebrahimi * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*22dc650dSSadaf Ebrahimi */
26*22dc650dSSadaf Ebrahimi
27*22dc650dSSadaf Ebrahimi /* ppc 32-bit arch dependent functions. */
28*22dc650dSSadaf Ebrahimi
load_immediate(struct sljit_compiler * compiler,sljit_s32 reg,sljit_sw imm)29*22dc650dSSadaf Ebrahimi static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm)
30*22dc650dSSadaf Ebrahimi {
31*22dc650dSSadaf Ebrahimi if (imm <= SIMM_MAX && imm >= SIMM_MIN)
32*22dc650dSSadaf Ebrahimi return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm));
33*22dc650dSSadaf Ebrahimi
34*22dc650dSSadaf Ebrahimi if (!(imm & ~0xffff))
35*22dc650dSSadaf Ebrahimi return push_inst(compiler, ORI | S(TMP_ZERO) | A(reg) | IMM(imm));
36*22dc650dSSadaf Ebrahimi
37*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 16)));
38*22dc650dSSadaf Ebrahimi return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS;
39*22dc650dSSadaf Ebrahimi }
40*22dc650dSSadaf Ebrahimi
41*22dc650dSSadaf Ebrahimi /* Simplified mnemonics: clrlwi. */
42*22dc650dSSadaf Ebrahimi #define INS_CLEAR_LEFT(dst, src, from) \
43*22dc650dSSadaf Ebrahimi (RLWINM | S(src) | A(dst) | RLWI_MBE(from, 31))
44*22dc650dSSadaf Ebrahimi
emit_single_op(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 flags,sljit_s32 dst,sljit_s32 src1,sljit_s32 src2)45*22dc650dSSadaf Ebrahimi static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
46*22dc650dSSadaf Ebrahimi sljit_s32 dst, sljit_s32 src1, sljit_s32 src2)
47*22dc650dSSadaf Ebrahimi {
48*22dc650dSSadaf Ebrahimi sljit_u32 imm;
49*22dc650dSSadaf Ebrahimi
50*22dc650dSSadaf Ebrahimi switch (op) {
51*22dc650dSSadaf Ebrahimi case SLJIT_MOV:
52*22dc650dSSadaf Ebrahimi case SLJIT_MOV_U32:
53*22dc650dSSadaf Ebrahimi case SLJIT_MOV_S32:
54*22dc650dSSadaf Ebrahimi case SLJIT_MOV_P:
55*22dc650dSSadaf Ebrahimi SLJIT_ASSERT(src1 == TMP_REG1);
56*22dc650dSSadaf Ebrahimi if (dst != src2)
57*22dc650dSSadaf Ebrahimi return push_inst(compiler, OR | S(src2) | A(dst) | B(src2));
58*22dc650dSSadaf Ebrahimi return SLJIT_SUCCESS;
59*22dc650dSSadaf Ebrahimi
60*22dc650dSSadaf Ebrahimi case SLJIT_MOV_U8:
61*22dc650dSSadaf Ebrahimi case SLJIT_MOV_S8:
62*22dc650dSSadaf Ebrahimi SLJIT_ASSERT(src1 == TMP_REG1);
63*22dc650dSSadaf Ebrahimi if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
64*22dc650dSSadaf Ebrahimi if (op == SLJIT_MOV_S8)
65*22dc650dSSadaf Ebrahimi return push_inst(compiler, EXTSB | S(src2) | A(dst));
66*22dc650dSSadaf Ebrahimi return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 24));
67*22dc650dSSadaf Ebrahimi }
68*22dc650dSSadaf Ebrahimi else if ((flags & REG_DEST) && op == SLJIT_MOV_S8)
69*22dc650dSSadaf Ebrahimi return push_inst(compiler, EXTSB | S(src2) | A(dst));
70*22dc650dSSadaf Ebrahimi else {
71*22dc650dSSadaf Ebrahimi SLJIT_ASSERT(dst == src2);
72*22dc650dSSadaf Ebrahimi }
73*22dc650dSSadaf Ebrahimi return SLJIT_SUCCESS;
74*22dc650dSSadaf Ebrahimi
75*22dc650dSSadaf Ebrahimi case SLJIT_MOV_U16:
76*22dc650dSSadaf Ebrahimi case SLJIT_MOV_S16:
77*22dc650dSSadaf Ebrahimi SLJIT_ASSERT(src1 == TMP_REG1);
78*22dc650dSSadaf Ebrahimi if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
79*22dc650dSSadaf Ebrahimi if (op == SLJIT_MOV_S16)
80*22dc650dSSadaf Ebrahimi return push_inst(compiler, EXTSH | S(src2) | A(dst));
81*22dc650dSSadaf Ebrahimi return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 16));
82*22dc650dSSadaf Ebrahimi }
83*22dc650dSSadaf Ebrahimi else {
84*22dc650dSSadaf Ebrahimi SLJIT_ASSERT(dst == src2);
85*22dc650dSSadaf Ebrahimi }
86*22dc650dSSadaf Ebrahimi return SLJIT_SUCCESS;
87*22dc650dSSadaf Ebrahimi
88*22dc650dSSadaf Ebrahimi case SLJIT_CLZ:
89*22dc650dSSadaf Ebrahimi SLJIT_ASSERT(src1 == TMP_REG1);
90*22dc650dSSadaf Ebrahimi return push_inst(compiler, CNTLZW | S(src2) | A(dst));
91*22dc650dSSadaf Ebrahimi
92*22dc650dSSadaf Ebrahimi case SLJIT_CTZ:
93*22dc650dSSadaf Ebrahimi SLJIT_ASSERT(src1 == TMP_REG1);
94*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, NEG | D(TMP_REG1) | A(src2)));
95*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, AND | S(src2) | A(dst) | B(TMP_REG1)));
96*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, CNTLZW | S(dst) | A(dst)));
97*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG1) | A(dst) | IMM(-32)));
98*22dc650dSSadaf Ebrahimi /* The highest bits are set, if dst < 32, zero otherwise. */
99*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, SRWI(27) | S(TMP_REG1) | A(TMP_REG1)));
100*22dc650dSSadaf Ebrahimi return push_inst(compiler, XOR | S(dst) | A(dst) | B(TMP_REG1));
101*22dc650dSSadaf Ebrahimi
102*22dc650dSSadaf Ebrahimi case SLJIT_ADD:
103*22dc650dSSadaf Ebrahimi if (flags & ALT_FORM1) {
104*22dc650dSSadaf Ebrahimi /* Setting XER SO is not enough, CR SO is also needed. */
105*22dc650dSSadaf Ebrahimi return push_inst(compiler, ADD | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
106*22dc650dSSadaf Ebrahimi }
107*22dc650dSSadaf Ebrahimi
108*22dc650dSSadaf Ebrahimi if (flags & ALT_FORM2) {
109*22dc650dSSadaf Ebrahimi /* Flags does not set: BIN_IMM_EXTS unnecessary. */
110*22dc650dSSadaf Ebrahimi SLJIT_ASSERT(src2 == TMP_REG2);
111*22dc650dSSadaf Ebrahimi
112*22dc650dSSadaf Ebrahimi if (flags & ALT_FORM3)
113*22dc650dSSadaf Ebrahimi return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm);
114*22dc650dSSadaf Ebrahimi
115*22dc650dSSadaf Ebrahimi imm = compiler->imm;
116*22dc650dSSadaf Ebrahimi
117*22dc650dSSadaf Ebrahimi if (flags & ALT_FORM4) {
118*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, ADDIS | D(dst) | A(src1) | (((imm >> 16) & 0xffff) + ((imm >> 15) & 0x1))));
119*22dc650dSSadaf Ebrahimi src1 = dst;
120*22dc650dSSadaf Ebrahimi }
121*22dc650dSSadaf Ebrahimi
122*22dc650dSSadaf Ebrahimi return push_inst(compiler, ADDI | D(dst) | A(src1) | (imm & 0xffff));
123*22dc650dSSadaf Ebrahimi }
124*22dc650dSSadaf Ebrahimi if (flags & ALT_FORM3) {
125*22dc650dSSadaf Ebrahimi SLJIT_ASSERT(src2 == TMP_REG2);
126*22dc650dSSadaf Ebrahimi return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm);
127*22dc650dSSadaf Ebrahimi }
128*22dc650dSSadaf Ebrahimi SLJIT_ASSERT(!(flags & ALT_FORM4));
129*22dc650dSSadaf Ebrahimi if (!(flags & ALT_SET_FLAGS))
130*22dc650dSSadaf Ebrahimi return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2));
131*22dc650dSSadaf Ebrahimi if (flags & ALT_FORM5)
132*22dc650dSSadaf Ebrahimi return push_inst(compiler, ADDC | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
133*22dc650dSSadaf Ebrahimi return push_inst(compiler, ADD | RC(flags) | D(dst) | A(src1) | B(src2));
134*22dc650dSSadaf Ebrahimi
135*22dc650dSSadaf Ebrahimi case SLJIT_ADDC:
136*22dc650dSSadaf Ebrahimi return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2));
137*22dc650dSSadaf Ebrahimi
138*22dc650dSSadaf Ebrahimi case SLJIT_SUB:
139*22dc650dSSadaf Ebrahimi if (flags & ALT_FORM1) {
140*22dc650dSSadaf Ebrahimi if (flags & ALT_FORM2) {
141*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, CMPLI | CRD(0) | A(src1) | compiler->imm));
142*22dc650dSSadaf Ebrahimi if (!(flags & ALT_FORM3))
143*22dc650dSSadaf Ebrahimi return SLJIT_SUCCESS;
144*22dc650dSSadaf Ebrahimi return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));
145*22dc650dSSadaf Ebrahimi }
146*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, CMPL | CRD(0) | A(src1) | B(src2)));
147*22dc650dSSadaf Ebrahimi if (!(flags & ALT_FORM3))
148*22dc650dSSadaf Ebrahimi return SLJIT_SUCCESS;
149*22dc650dSSadaf Ebrahimi return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
150*22dc650dSSadaf Ebrahimi }
151*22dc650dSSadaf Ebrahimi
152*22dc650dSSadaf Ebrahimi if (flags & ALT_FORM2) {
153*22dc650dSSadaf Ebrahimi if (flags & ALT_FORM3) {
154*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, CMPI | CRD(0) | A(src1) | compiler->imm));
155*22dc650dSSadaf Ebrahimi if (!(flags & ALT_FORM4))
156*22dc650dSSadaf Ebrahimi return SLJIT_SUCCESS;
157*22dc650dSSadaf Ebrahimi return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));
158*22dc650dSSadaf Ebrahimi }
159*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, CMP | CRD(0) | A(src1) | B(src2)));
160*22dc650dSSadaf Ebrahimi if (!(flags & ALT_FORM4))
161*22dc650dSSadaf Ebrahimi return SLJIT_SUCCESS;
162*22dc650dSSadaf Ebrahimi return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
163*22dc650dSSadaf Ebrahimi }
164*22dc650dSSadaf Ebrahimi
165*22dc650dSSadaf Ebrahimi if (flags & ALT_FORM3) {
166*22dc650dSSadaf Ebrahimi /* Setting XER SO is not enough, CR SO is also needed. */
167*22dc650dSSadaf Ebrahimi if (src1 != TMP_ZERO)
168*22dc650dSSadaf Ebrahimi return push_inst(compiler, SUBF | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
169*22dc650dSSadaf Ebrahimi return push_inst(compiler, NEG | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2));
170*22dc650dSSadaf Ebrahimi }
171*22dc650dSSadaf Ebrahimi
172*22dc650dSSadaf Ebrahimi if (flags & ALT_FORM4) {
173*22dc650dSSadaf Ebrahimi /* Flags does not set: BIN_IMM_EXTS unnecessary. */
174*22dc650dSSadaf Ebrahimi SLJIT_ASSERT(src2 == TMP_REG2);
175*22dc650dSSadaf Ebrahimi return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);
176*22dc650dSSadaf Ebrahimi }
177*22dc650dSSadaf Ebrahimi
178*22dc650dSSadaf Ebrahimi if (!(flags & ALT_SET_FLAGS)) {
179*22dc650dSSadaf Ebrahimi SLJIT_ASSERT(src1 != TMP_ZERO);
180*22dc650dSSadaf Ebrahimi return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
181*22dc650dSSadaf Ebrahimi }
182*22dc650dSSadaf Ebrahimi
183*22dc650dSSadaf Ebrahimi if (flags & ALT_FORM5)
184*22dc650dSSadaf Ebrahimi return push_inst(compiler, SUBFC | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
185*22dc650dSSadaf Ebrahimi
186*22dc650dSSadaf Ebrahimi if (src1 != TMP_ZERO)
187*22dc650dSSadaf Ebrahimi return push_inst(compiler, SUBF | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
188*22dc650dSSadaf Ebrahimi return push_inst(compiler, NEG | RC(ALT_SET_FLAGS) | D(dst) | A(src2));
189*22dc650dSSadaf Ebrahimi
190*22dc650dSSadaf Ebrahimi case SLJIT_SUBC:
191*22dc650dSSadaf Ebrahimi return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1));
192*22dc650dSSadaf Ebrahimi
193*22dc650dSSadaf Ebrahimi case SLJIT_MUL:
194*22dc650dSSadaf Ebrahimi if (flags & ALT_FORM1) {
195*22dc650dSSadaf Ebrahimi SLJIT_ASSERT(src2 == TMP_REG2);
196*22dc650dSSadaf Ebrahimi return push_inst(compiler, MULLI | D(dst) | A(src1) | compiler->imm);
197*22dc650dSSadaf Ebrahimi }
198*22dc650dSSadaf Ebrahimi return push_inst(compiler, MULLW | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1));
199*22dc650dSSadaf Ebrahimi
200*22dc650dSSadaf Ebrahimi case SLJIT_AND:
201*22dc650dSSadaf Ebrahimi if (flags & ALT_FORM1) {
202*22dc650dSSadaf Ebrahimi SLJIT_ASSERT(src2 == TMP_REG2);
203*22dc650dSSadaf Ebrahimi return push_inst(compiler, ANDI | S(src1) | A(dst) | compiler->imm);
204*22dc650dSSadaf Ebrahimi }
205*22dc650dSSadaf Ebrahimi if (flags & ALT_FORM2) {
206*22dc650dSSadaf Ebrahimi SLJIT_ASSERT(src2 == TMP_REG2);
207*22dc650dSSadaf Ebrahimi return push_inst(compiler, ANDIS | S(src1) | A(dst) | compiler->imm);
208*22dc650dSSadaf Ebrahimi }
209*22dc650dSSadaf Ebrahimi return push_inst(compiler, AND | RC(flags) | S(src1) | A(dst) | B(src2));
210*22dc650dSSadaf Ebrahimi
211*22dc650dSSadaf Ebrahimi case SLJIT_OR:
212*22dc650dSSadaf Ebrahimi if (flags & ALT_FORM1) {
213*22dc650dSSadaf Ebrahimi SLJIT_ASSERT(src2 == TMP_REG2);
214*22dc650dSSadaf Ebrahimi return push_inst(compiler, ORI | S(src1) | A(dst) | compiler->imm);
215*22dc650dSSadaf Ebrahimi }
216*22dc650dSSadaf Ebrahimi if (flags & ALT_FORM2) {
217*22dc650dSSadaf Ebrahimi SLJIT_ASSERT(src2 == TMP_REG2);
218*22dc650dSSadaf Ebrahimi return push_inst(compiler, ORIS | S(src1) | A(dst) | compiler->imm);
219*22dc650dSSadaf Ebrahimi }
220*22dc650dSSadaf Ebrahimi if (flags & ALT_FORM3) {
221*22dc650dSSadaf Ebrahimi SLJIT_ASSERT(src2 == TMP_REG2);
222*22dc650dSSadaf Ebrahimi imm = compiler->imm;
223*22dc650dSSadaf Ebrahimi
224*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(imm)));
225*22dc650dSSadaf Ebrahimi return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(imm >> 16));
226*22dc650dSSadaf Ebrahimi }
227*22dc650dSSadaf Ebrahimi return push_inst(compiler, OR | RC(flags) | S(src1) | A(dst) | B(src2));
228*22dc650dSSadaf Ebrahimi
229*22dc650dSSadaf Ebrahimi case SLJIT_XOR:
230*22dc650dSSadaf Ebrahimi if (flags & ALT_FORM1) {
231*22dc650dSSadaf Ebrahimi SLJIT_ASSERT(src2 == TMP_REG2);
232*22dc650dSSadaf Ebrahimi return push_inst(compiler, XORI | S(src1) | A(dst) | compiler->imm);
233*22dc650dSSadaf Ebrahimi }
234*22dc650dSSadaf Ebrahimi if (flags & ALT_FORM2) {
235*22dc650dSSadaf Ebrahimi SLJIT_ASSERT(src2 == TMP_REG2);
236*22dc650dSSadaf Ebrahimi return push_inst(compiler, XORIS | S(src1) | A(dst) | compiler->imm);
237*22dc650dSSadaf Ebrahimi }
238*22dc650dSSadaf Ebrahimi if (flags & ALT_FORM3) {
239*22dc650dSSadaf Ebrahimi SLJIT_ASSERT(src2 == TMP_REG2);
240*22dc650dSSadaf Ebrahimi imm = compiler->imm;
241*22dc650dSSadaf Ebrahimi
242*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(imm)));
243*22dc650dSSadaf Ebrahimi return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(imm >> 16));
244*22dc650dSSadaf Ebrahimi }
245*22dc650dSSadaf Ebrahimi if (flags & ALT_FORM4) {
246*22dc650dSSadaf Ebrahimi SLJIT_ASSERT(src1 == TMP_REG1);
247*22dc650dSSadaf Ebrahimi return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2));
248*22dc650dSSadaf Ebrahimi }
249*22dc650dSSadaf Ebrahimi return push_inst(compiler, XOR | RC(flags) | S(src1) | A(dst) | B(src2));
250*22dc650dSSadaf Ebrahimi
251*22dc650dSSadaf Ebrahimi case SLJIT_SHL:
252*22dc650dSSadaf Ebrahimi case SLJIT_MSHL:
253*22dc650dSSadaf Ebrahimi if (flags & ALT_FORM1) {
254*22dc650dSSadaf Ebrahimi SLJIT_ASSERT(src2 == TMP_REG2);
255*22dc650dSSadaf Ebrahimi imm = compiler->imm & 0x1f;
256*22dc650dSSadaf Ebrahimi return push_inst(compiler, SLWI(imm) | RC(flags) | S(src1) | A(dst));
257*22dc650dSSadaf Ebrahimi }
258*22dc650dSSadaf Ebrahimi
259*22dc650dSSadaf Ebrahimi if (op == SLJIT_MSHL) {
260*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | 0x1f));
261*22dc650dSSadaf Ebrahimi src2 = TMP_REG2;
262*22dc650dSSadaf Ebrahimi }
263*22dc650dSSadaf Ebrahimi
264*22dc650dSSadaf Ebrahimi return push_inst(compiler, SLW | RC(flags) | S(src1) | A(dst) | B(src2));
265*22dc650dSSadaf Ebrahimi
266*22dc650dSSadaf Ebrahimi case SLJIT_LSHR:
267*22dc650dSSadaf Ebrahimi case SLJIT_MLSHR:
268*22dc650dSSadaf Ebrahimi if (flags & ALT_FORM1) {
269*22dc650dSSadaf Ebrahimi SLJIT_ASSERT(src2 == TMP_REG2);
270*22dc650dSSadaf Ebrahimi imm = compiler->imm & 0x1f;
271*22dc650dSSadaf Ebrahimi /* Since imm can be 0, SRWI() cannot be used. */
272*22dc650dSSadaf Ebrahimi return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | RLWI_SH((32 - imm) & 0x1f) | RLWI_MBE(imm, 31));
273*22dc650dSSadaf Ebrahimi }
274*22dc650dSSadaf Ebrahimi
275*22dc650dSSadaf Ebrahimi if (op == SLJIT_MLSHR) {
276*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | 0x1f));
277*22dc650dSSadaf Ebrahimi src2 = TMP_REG2;
278*22dc650dSSadaf Ebrahimi }
279*22dc650dSSadaf Ebrahimi
280*22dc650dSSadaf Ebrahimi return push_inst(compiler, SRW | RC(flags) | S(src1) | A(dst) | B(src2));
281*22dc650dSSadaf Ebrahimi
282*22dc650dSSadaf Ebrahimi case SLJIT_ASHR:
283*22dc650dSSadaf Ebrahimi case SLJIT_MASHR:
284*22dc650dSSadaf Ebrahimi if (flags & ALT_FORM1) {
285*22dc650dSSadaf Ebrahimi SLJIT_ASSERT(src2 == TMP_REG2);
286*22dc650dSSadaf Ebrahimi imm = compiler->imm & 0x1f;
287*22dc650dSSadaf Ebrahimi return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (imm << 11));
288*22dc650dSSadaf Ebrahimi }
289*22dc650dSSadaf Ebrahimi
290*22dc650dSSadaf Ebrahimi if (op == SLJIT_MASHR) {
291*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | 0x1f));
292*22dc650dSSadaf Ebrahimi src2 = TMP_REG2;
293*22dc650dSSadaf Ebrahimi }
294*22dc650dSSadaf Ebrahimi
295*22dc650dSSadaf Ebrahimi return push_inst(compiler, SRAW | RC(flags) | S(src1) | A(dst) | B(src2));
296*22dc650dSSadaf Ebrahimi
297*22dc650dSSadaf Ebrahimi case SLJIT_ROTL:
298*22dc650dSSadaf Ebrahimi case SLJIT_ROTR:
299*22dc650dSSadaf Ebrahimi if (flags & ALT_FORM1) {
300*22dc650dSSadaf Ebrahimi SLJIT_ASSERT(src2 == TMP_REG2);
301*22dc650dSSadaf Ebrahimi imm = compiler->imm;
302*22dc650dSSadaf Ebrahimi
303*22dc650dSSadaf Ebrahimi if (op == SLJIT_ROTR)
304*22dc650dSSadaf Ebrahimi imm = (sljit_u32)(-(sljit_s32)imm);
305*22dc650dSSadaf Ebrahimi
306*22dc650dSSadaf Ebrahimi imm &= 0x1f;
307*22dc650dSSadaf Ebrahimi return push_inst(compiler, RLWINM | S(src1) | A(dst) | RLWI_SH(imm) | RLWI_MBE(0, 31));
308*22dc650dSSadaf Ebrahimi }
309*22dc650dSSadaf Ebrahimi
310*22dc650dSSadaf Ebrahimi if (op == SLJIT_ROTR) {
311*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, SUBFIC | D(TMP_REG2) | A(src2) | 0));
312*22dc650dSSadaf Ebrahimi src2 = TMP_REG2;
313*22dc650dSSadaf Ebrahimi }
314*22dc650dSSadaf Ebrahimi
315*22dc650dSSadaf Ebrahimi return push_inst(compiler, RLWNM | S(src1) | A(dst) | B(src2) | RLWI_MBE(0, 31));
316*22dc650dSSadaf Ebrahimi }
317*22dc650dSSadaf Ebrahimi
318*22dc650dSSadaf Ebrahimi SLJIT_UNREACHABLE();
319*22dc650dSSadaf Ebrahimi return SLJIT_SUCCESS;
320*22dc650dSSadaf Ebrahimi }
321*22dc650dSSadaf Ebrahimi
emit_const(struct sljit_compiler * compiler,sljit_s32 reg,sljit_sw init_value)322*22dc650dSSadaf Ebrahimi static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw init_value)
323*22dc650dSSadaf Ebrahimi {
324*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 16)));
325*22dc650dSSadaf Ebrahimi return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value));
326*22dc650dSSadaf Ebrahimi }
327*22dc650dSSadaf Ebrahimi
sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 src,sljit_sw srcw)328*22dc650dSSadaf Ebrahimi static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
329*22dc650dSSadaf Ebrahimi sljit_s32 dst, sljit_sw dstw,
330*22dc650dSSadaf Ebrahimi sljit_s32 src, sljit_sw srcw)
331*22dc650dSSadaf Ebrahimi {
332*22dc650dSSadaf Ebrahimi sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
333*22dc650dSSadaf Ebrahimi sljit_s32 invert_sign = 1;
334*22dc650dSSadaf Ebrahimi
335*22dc650dSSadaf Ebrahimi if (src == SLJIT_IMM) {
336*22dc650dSSadaf Ebrahimi FAIL_IF(load_immediate(compiler, TMP_REG1, srcw ^ (sljit_sw)0x80000000));
337*22dc650dSSadaf Ebrahimi src = TMP_REG1;
338*22dc650dSSadaf Ebrahimi invert_sign = 0;
339*22dc650dSSadaf Ebrahimi } else if (!FAST_IS_REG(src)) {
340*22dc650dSSadaf Ebrahimi FAIL_IF(emit_op_mem(compiler, WORD_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
341*22dc650dSSadaf Ebrahimi src = TMP_REG1;
342*22dc650dSSadaf Ebrahimi }
343*22dc650dSSadaf Ebrahimi
344*22dc650dSSadaf Ebrahimi /* First, a special double precision floating point value is constructed:
345*22dc650dSSadaf Ebrahimi (2^53 + (src xor (2^31)))
346*22dc650dSSadaf Ebrahimi The upper 32 bits of this number is a constant, and the lower 32 bits
347*22dc650dSSadaf Ebrahimi is simply the value of the source argument. The xor 2^31 operation adds
348*22dc650dSSadaf Ebrahimi 0x80000000 to the source argument, which moves it into the 0 - 0xffffffff
349*22dc650dSSadaf Ebrahimi range. Finally we substract 2^53 + 2^31 to get the converted value. */
350*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG2) | A(0) | 0x4330));
351*22dc650dSSadaf Ebrahimi if (invert_sign)
352*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, XORIS | S(src) | A(TMP_REG1) | 0x8000));
353*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, STW | S(TMP_REG2) | A(SLJIT_SP) | TMP_MEM_OFFSET_HI));
354*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, STW | S(TMP_REG1) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));
355*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG1) | A(0) | 0x8000));
356*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));
357*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, STW | S(TMP_REG1) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));
358*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG2) | A(SLJIT_SP) | TMP_MEM_OFFSET));
359*22dc650dSSadaf Ebrahimi
360*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, FSUB | FD(dst_r) | FA(TMP_FREG1) | FB(TMP_FREG2)));
361*22dc650dSSadaf Ebrahimi
362*22dc650dSSadaf Ebrahimi if (op & SLJIT_32)
363*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r)));
364*22dc650dSSadaf Ebrahimi
365*22dc650dSSadaf Ebrahimi if (dst & SLJIT_MEM)
366*22dc650dSSadaf Ebrahimi return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1);
367*22dc650dSSadaf Ebrahimi return SLJIT_SUCCESS;
368*22dc650dSSadaf Ebrahimi }
369*22dc650dSSadaf Ebrahimi
sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 src,sljit_sw srcw)370*22dc650dSSadaf Ebrahimi static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op,
371*22dc650dSSadaf Ebrahimi sljit_s32 dst, sljit_sw dstw,
372*22dc650dSSadaf Ebrahimi sljit_s32 src, sljit_sw srcw)
373*22dc650dSSadaf Ebrahimi {
374*22dc650dSSadaf Ebrahimi sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
375*22dc650dSSadaf Ebrahimi
376*22dc650dSSadaf Ebrahimi if (src == SLJIT_IMM) {
377*22dc650dSSadaf Ebrahimi FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
378*22dc650dSSadaf Ebrahimi src = TMP_REG1;
379*22dc650dSSadaf Ebrahimi } else if (!FAST_IS_REG(src)) {
380*22dc650dSSadaf Ebrahimi FAIL_IF(emit_op_mem(compiler, WORD_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
381*22dc650dSSadaf Ebrahimi src = TMP_REG1;
382*22dc650dSSadaf Ebrahimi }
383*22dc650dSSadaf Ebrahimi
384*22dc650dSSadaf Ebrahimi /* First, a special double precision floating point value is constructed:
385*22dc650dSSadaf Ebrahimi (2^53 + src)
386*22dc650dSSadaf Ebrahimi The upper 32 bits of this number is a constant, and the lower 32 bits
387*22dc650dSSadaf Ebrahimi is simply the value of the source argument. Finally we substract 2^53
388*22dc650dSSadaf Ebrahimi to get the converted value. */
389*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG2) | A(0) | 0x4330));
390*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, STW | S(src) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));
391*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, STW | S(TMP_REG2) | A(SLJIT_SP) | TMP_MEM_OFFSET_HI));
392*22dc650dSSadaf Ebrahimi
393*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));
394*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, STW | S(TMP_ZERO) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));
395*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG2) | A(SLJIT_SP) | TMP_MEM_OFFSET));
396*22dc650dSSadaf Ebrahimi
397*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, FSUB | FD(dst_r) | FA(TMP_FREG1) | FB(TMP_FREG2)));
398*22dc650dSSadaf Ebrahimi
399*22dc650dSSadaf Ebrahimi if (op & SLJIT_32)
400*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r)));
401*22dc650dSSadaf Ebrahimi
402*22dc650dSSadaf Ebrahimi if (dst & SLJIT_MEM)
403*22dc650dSSadaf Ebrahimi return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1);
404*22dc650dSSadaf Ebrahimi return SLJIT_SUCCESS;
405*22dc650dSSadaf Ebrahimi }
406*22dc650dSSadaf Ebrahimi
sljit_emit_fset64(struct sljit_compiler * compiler,sljit_s32 freg,sljit_f64 value)407*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,
408*22dc650dSSadaf Ebrahimi sljit_s32 freg, sljit_f64 value)
409*22dc650dSSadaf Ebrahimi {
410*22dc650dSSadaf Ebrahimi union {
411*22dc650dSSadaf Ebrahimi sljit_s32 imm[2];
412*22dc650dSSadaf Ebrahimi sljit_f64 value;
413*22dc650dSSadaf Ebrahimi } u;
414*22dc650dSSadaf Ebrahimi
415*22dc650dSSadaf Ebrahimi CHECK_ERROR();
416*22dc650dSSadaf Ebrahimi CHECK(check_sljit_emit_fset64(compiler, freg, value));
417*22dc650dSSadaf Ebrahimi
418*22dc650dSSadaf Ebrahimi u.value = value;
419*22dc650dSSadaf Ebrahimi
420*22dc650dSSadaf Ebrahimi if (u.imm[0] != 0)
421*22dc650dSSadaf Ebrahimi FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm[0]));
422*22dc650dSSadaf Ebrahimi if (u.imm[1] != 0)
423*22dc650dSSadaf Ebrahimi FAIL_IF(load_immediate(compiler, TMP_REG2, u.imm[1]));
424*22dc650dSSadaf Ebrahimi
425*22dc650dSSadaf Ebrahimi /* Saved in the same endianness. */
426*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, STW | S(u.imm[0] != 0 ? TMP_REG1 : TMP_ZERO) | A(SLJIT_SP) | TMP_MEM_OFFSET));
427*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, STW | S(u.imm[1] != 0 ? TMP_REG2 : TMP_ZERO) | A(SLJIT_SP) | (TMP_MEM_OFFSET + sizeof(sljit_s32))));
428*22dc650dSSadaf Ebrahimi return push_inst(compiler, LFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET);
429*22dc650dSSadaf Ebrahimi }
430*22dc650dSSadaf Ebrahimi
sljit_emit_fcopy(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 freg,sljit_s32 reg)431*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,
432*22dc650dSSadaf Ebrahimi sljit_s32 freg, sljit_s32 reg)
433*22dc650dSSadaf Ebrahimi {
434*22dc650dSSadaf Ebrahimi sljit_s32 reg2 = 0;
435*22dc650dSSadaf Ebrahimi
436*22dc650dSSadaf Ebrahimi CHECK_ERROR();
437*22dc650dSSadaf Ebrahimi CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));
438*22dc650dSSadaf Ebrahimi
439*22dc650dSSadaf Ebrahimi if (op & SLJIT_32) {
440*22dc650dSSadaf Ebrahimi if (op == SLJIT_COPY32_TO_F32) {
441*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, STW | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET));
442*22dc650dSSadaf Ebrahimi return push_inst(compiler, LFS | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET);
443*22dc650dSSadaf Ebrahimi }
444*22dc650dSSadaf Ebrahimi
445*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, STFS | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET));
446*22dc650dSSadaf Ebrahimi return push_inst(compiler, LWZ | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET);
447*22dc650dSSadaf Ebrahimi }
448*22dc650dSSadaf Ebrahimi
449*22dc650dSSadaf Ebrahimi if (reg & REG_PAIR_MASK) {
450*22dc650dSSadaf Ebrahimi reg2 = REG_PAIR_SECOND(reg);
451*22dc650dSSadaf Ebrahimi reg = REG_PAIR_FIRST(reg);
452*22dc650dSSadaf Ebrahimi }
453*22dc650dSSadaf Ebrahimi
454*22dc650dSSadaf Ebrahimi if (op == SLJIT_COPY_TO_F64) {
455*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, STW | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET_HI));
456*22dc650dSSadaf Ebrahimi
457*22dc650dSSadaf Ebrahimi if (reg2 != 0)
458*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, STW | S(reg2) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));
459*22dc650dSSadaf Ebrahimi else
460*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, STFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));
461*22dc650dSSadaf Ebrahimi
462*22dc650dSSadaf Ebrahimi return push_inst(compiler, LFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET);
463*22dc650dSSadaf Ebrahimi }
464*22dc650dSSadaf Ebrahimi
465*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, STFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET));
466*22dc650dSSadaf Ebrahimi
467*22dc650dSSadaf Ebrahimi if (reg2 != 0)
468*22dc650dSSadaf Ebrahimi FAIL_IF(push_inst(compiler, LWZ | S(reg2) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));
469*22dc650dSSadaf Ebrahimi
470*22dc650dSSadaf Ebrahimi return push_inst(compiler, LWZ | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET_HI);
471*22dc650dSSadaf Ebrahimi }
472*22dc650dSSadaf Ebrahimi
sljit_set_jump_addr(sljit_uw addr,sljit_uw new_target,sljit_sw executable_offset)473*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
474*22dc650dSSadaf Ebrahimi {
475*22dc650dSSadaf Ebrahimi sljit_ins *inst = (sljit_ins *)addr;
476*22dc650dSSadaf Ebrahimi SLJIT_UNUSED_ARG(executable_offset);
477*22dc650dSSadaf Ebrahimi
478*22dc650dSSadaf Ebrahimi SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);
479*22dc650dSSadaf Ebrahimi SLJIT_ASSERT((inst[0] & 0xfc1f0000) == ADDIS && (inst[1] & 0xfc000000) == ORI);
480*22dc650dSSadaf Ebrahimi inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 16) & 0xffff);
481*22dc650dSSadaf Ebrahimi inst[1] = (inst[1] & 0xffff0000) | (new_target & 0xffff);
482*22dc650dSSadaf Ebrahimi SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
483*22dc650dSSadaf Ebrahimi inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
484*22dc650dSSadaf Ebrahimi SLJIT_CACHE_FLUSH(inst, inst + 2);
485*22dc650dSSadaf Ebrahimi }
486