xref: /aosp_15_r20/external/pcre/src/sljit/sljitNativeARM_32.c (revision 22dc650d8ae982c6770746019a6f94af92b0f024)
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 #ifdef __SOFTFP__
28*22dc650dSSadaf Ebrahimi #define ARM_ABI_INFO " ABI:softfp"
29*22dc650dSSadaf Ebrahimi #else
30*22dc650dSSadaf Ebrahimi #define ARM_ABI_INFO " ABI:hardfp"
31*22dc650dSSadaf Ebrahimi #endif
32*22dc650dSSadaf Ebrahimi 
sljit_get_platform_name(void)33*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
34*22dc650dSSadaf Ebrahimi {
35*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
36*22dc650dSSadaf Ebrahimi 	return "ARMv7" SLJIT_CPUINFO ARM_ABI_INFO;
37*22dc650dSSadaf Ebrahimi #elif (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
38*22dc650dSSadaf Ebrahimi 	return "ARMv6" SLJIT_CPUINFO ARM_ABI_INFO;
39*22dc650dSSadaf Ebrahimi #else
40*22dc650dSSadaf Ebrahimi #error "Internal error: Unknown ARM architecture"
41*22dc650dSSadaf Ebrahimi #endif
42*22dc650dSSadaf Ebrahimi }
43*22dc650dSSadaf Ebrahimi 
44*22dc650dSSadaf Ebrahimi /* Length of an instruction word. */
45*22dc650dSSadaf Ebrahimi typedef sljit_u32 sljit_ins;
46*22dc650dSSadaf Ebrahimi 
47*22dc650dSSadaf Ebrahimi /* Last register + 1. */
48*22dc650dSSadaf Ebrahimi #define TMP_REG1	(SLJIT_NUMBER_OF_REGISTERS + 2)
49*22dc650dSSadaf Ebrahimi #define TMP_REG2	(SLJIT_NUMBER_OF_REGISTERS + 3)
50*22dc650dSSadaf Ebrahimi #define TMP_PC		(SLJIT_NUMBER_OF_REGISTERS + 4)
51*22dc650dSSadaf Ebrahimi 
52*22dc650dSSadaf Ebrahimi #define TMP_FREG1	(SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
53*22dc650dSSadaf Ebrahimi #define TMP_FREG2	(SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)
54*22dc650dSSadaf Ebrahimi 
55*22dc650dSSadaf Ebrahimi /* In ARM instruction words.
56*22dc650dSSadaf Ebrahimi    Cache lines are usually 32 byte aligned. */
57*22dc650dSSadaf Ebrahimi #define CONST_POOL_ALIGNMENT	8
58*22dc650dSSadaf Ebrahimi #define CONST_POOL_EMPTY	0xffffffff
59*22dc650dSSadaf Ebrahimi 
60*22dc650dSSadaf Ebrahimi #define ALIGN_INSTRUCTION(ptr) \
61*22dc650dSSadaf Ebrahimi 	(sljit_ins*)(((sljit_ins)(ptr) + (CONST_POOL_ALIGNMENT * sizeof(sljit_ins)) - 1) & ~((CONST_POOL_ALIGNMENT * sizeof(sljit_ins)) - 1))
62*22dc650dSSadaf Ebrahimi #define MAX_DIFFERENCE(max_diff) \
63*22dc650dSSadaf Ebrahimi 	(((max_diff) / (sljit_s32)sizeof(sljit_ins)) - (CONST_POOL_ALIGNMENT - 1))
64*22dc650dSSadaf Ebrahimi 
65*22dc650dSSadaf Ebrahimi /* See sljit_emit_enter and sljit_emit_op0 if you want to change them. */
66*22dc650dSSadaf Ebrahimi static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
67*22dc650dSSadaf Ebrahimi 	0, 0, 1, 2, 3, 11, 10, 9, 8, 7, 6, 5, 4, 13, 12, 14, 15
68*22dc650dSSadaf Ebrahimi };
69*22dc650dSSadaf Ebrahimi 
70*22dc650dSSadaf Ebrahimi static const sljit_u8 freg_map[((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) << 1) + 1] = {
71*22dc650dSSadaf Ebrahimi 	0,
72*22dc650dSSadaf Ebrahimi 	0, 1, 2, 3, 4, 5, 15, 14, 13, 12, 11, 10, 9, 8,
73*22dc650dSSadaf Ebrahimi 	7, 6,
74*22dc650dSSadaf Ebrahimi 	0, 1, 2, 3, 4, 5, 15, 14, 13, 12, 11, 10, 9, 8,
75*22dc650dSSadaf Ebrahimi 	7, 6
76*22dc650dSSadaf Ebrahimi };
77*22dc650dSSadaf Ebrahimi 
78*22dc650dSSadaf Ebrahimi static const sljit_u8 freg_ebit_map[((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) << 1) + 1] = {
79*22dc650dSSadaf Ebrahimi 	0,
80*22dc650dSSadaf Ebrahimi 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
81*22dc650dSSadaf Ebrahimi 	0, 0,
82*22dc650dSSadaf Ebrahimi 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
83*22dc650dSSadaf Ebrahimi 	1, 1
84*22dc650dSSadaf Ebrahimi };
85*22dc650dSSadaf Ebrahimi 
86*22dc650dSSadaf Ebrahimi #define RM(rm) ((sljit_ins)reg_map[rm])
87*22dc650dSSadaf Ebrahimi #define RM8(rm) ((sljit_ins)reg_map[rm] << 8)
88*22dc650dSSadaf Ebrahimi #define RD(rd) ((sljit_ins)reg_map[rd] << 12)
89*22dc650dSSadaf Ebrahimi #define RN(rn) ((sljit_ins)reg_map[rn] << 16)
90*22dc650dSSadaf Ebrahimi 
91*22dc650dSSadaf Ebrahimi #define VM(vm) (((sljit_ins)freg_map[vm]) | ((sljit_ins)freg_ebit_map[vm] << 5))
92*22dc650dSSadaf Ebrahimi #define VD(vd) (((sljit_ins)freg_map[vd] << 12) | ((sljit_ins)freg_ebit_map[vd] << 22))
93*22dc650dSSadaf Ebrahimi #define VN(vn) (((sljit_ins)freg_map[vn] << 16) | ((sljit_ins)freg_ebit_map[vn] << 7))
94*22dc650dSSadaf Ebrahimi 
95*22dc650dSSadaf Ebrahimi /* --------------------------------------------------------------------- */
96*22dc650dSSadaf Ebrahimi /*  Instrucion forms                                                     */
97*22dc650dSSadaf Ebrahimi /* --------------------------------------------------------------------- */
98*22dc650dSSadaf Ebrahimi 
99*22dc650dSSadaf Ebrahimi /* The instruction includes the AL condition.
100*22dc650dSSadaf Ebrahimi    INST_NAME - CONDITIONAL remove this flag. */
101*22dc650dSSadaf Ebrahimi #define COND_MASK	0xf0000000
102*22dc650dSSadaf Ebrahimi #define CONDITIONAL	0xe0000000
103*22dc650dSSadaf Ebrahimi #define PUSH_POOL	0xff000000
104*22dc650dSSadaf Ebrahimi 
105*22dc650dSSadaf Ebrahimi #define ADC		0xe0a00000
106*22dc650dSSadaf Ebrahimi #define ADD		0xe0800000
107*22dc650dSSadaf Ebrahimi #define AND		0xe0000000
108*22dc650dSSadaf Ebrahimi #define B		0xea000000
109*22dc650dSSadaf Ebrahimi #define BIC		0xe1c00000
110*22dc650dSSadaf Ebrahimi #define BKPT		0xe1200070
111*22dc650dSSadaf Ebrahimi #define BL		0xeb000000
112*22dc650dSSadaf Ebrahimi #define BLX		0xe12fff30
113*22dc650dSSadaf Ebrahimi #define BX		0xe12fff10
114*22dc650dSSadaf Ebrahimi #define CLZ		0xe16f0f10
115*22dc650dSSadaf Ebrahimi #define CMN		0xe1600000
116*22dc650dSSadaf Ebrahimi #define CMP		0xe1400000
117*22dc650dSSadaf Ebrahimi #define EOR		0xe0200000
118*22dc650dSSadaf Ebrahimi #define LDR		0xe5100000
119*22dc650dSSadaf Ebrahimi #define LDR_POST	0xe4100000
120*22dc650dSSadaf Ebrahimi #define LDREX		0xe1900f9f
121*22dc650dSSadaf Ebrahimi #define LDREXB		0xe1d00f9f
122*22dc650dSSadaf Ebrahimi #define LDREXH		0xe1f00f9f
123*22dc650dSSadaf Ebrahimi #define MLA		0xe0200090
124*22dc650dSSadaf Ebrahimi #define MOV		0xe1a00000
125*22dc650dSSadaf Ebrahimi #define MUL		0xe0000090
126*22dc650dSSadaf Ebrahimi #define MVN		0xe1e00000
127*22dc650dSSadaf Ebrahimi #define NOP		0xe1a00000
128*22dc650dSSadaf Ebrahimi #define ORR		0xe1800000
129*22dc650dSSadaf Ebrahimi #define PUSH		0xe92d0000
130*22dc650dSSadaf Ebrahimi #define POP		0xe8bd0000
131*22dc650dSSadaf Ebrahimi #define REV		0xe6bf0f30
132*22dc650dSSadaf Ebrahimi #define REV16		0xe6bf0fb0
133*22dc650dSSadaf Ebrahimi #define RSB		0xe0600000
134*22dc650dSSadaf Ebrahimi #define RSC		0xe0e00000
135*22dc650dSSadaf Ebrahimi #define SBC		0xe0c00000
136*22dc650dSSadaf Ebrahimi #define SMULL		0xe0c00090
137*22dc650dSSadaf Ebrahimi #define STR		0xe5000000
138*22dc650dSSadaf Ebrahimi #define STREX		0xe1800f90
139*22dc650dSSadaf Ebrahimi #define STREXB		0xe1c00f90
140*22dc650dSSadaf Ebrahimi #define STREXH		0xe1e00f90
141*22dc650dSSadaf Ebrahimi #define SUB		0xe0400000
142*22dc650dSSadaf Ebrahimi #define SXTB		0xe6af0070
143*22dc650dSSadaf Ebrahimi #define SXTH		0xe6bf0070
144*22dc650dSSadaf Ebrahimi #define TST		0xe1000000
145*22dc650dSSadaf Ebrahimi #define UMULL		0xe0800090
146*22dc650dSSadaf Ebrahimi #define UXTB		0xe6ef0070
147*22dc650dSSadaf Ebrahimi #define UXTH		0xe6ff0070
148*22dc650dSSadaf Ebrahimi #define VABS_F32	0xeeb00ac0
149*22dc650dSSadaf Ebrahimi #define VADD_F32	0xee300a00
150*22dc650dSSadaf Ebrahimi #define VAND		0xf2000110
151*22dc650dSSadaf Ebrahimi #define VCMP_F32	0xeeb40a40
152*22dc650dSSadaf Ebrahimi #define VCVT_F32_S32	0xeeb80ac0
153*22dc650dSSadaf Ebrahimi #define VCVT_F32_U32	0xeeb80a40
154*22dc650dSSadaf Ebrahimi #define VCVT_F64_F32	0xeeb70ac0
155*22dc650dSSadaf Ebrahimi #define VCVT_S32_F32	0xeebd0ac0
156*22dc650dSSadaf Ebrahimi #define VDIV_F32	0xee800a00
157*22dc650dSSadaf Ebrahimi #define VDUP		0xee800b10
158*22dc650dSSadaf Ebrahimi #define VDUP_s		0xf3b00c00
159*22dc650dSSadaf Ebrahimi #define VEOR		0xf3000110
160*22dc650dSSadaf Ebrahimi #define VLD1		0xf4200000
161*22dc650dSSadaf Ebrahimi #define VLD1_r		0xf4a00c00
162*22dc650dSSadaf Ebrahimi #define VLD1_s		0xf4a00000
163*22dc650dSSadaf Ebrahimi #define VLDR_F32	0xed100a00
164*22dc650dSSadaf Ebrahimi #define VMOV_F32	0xeeb00a40
165*22dc650dSSadaf Ebrahimi #define VMOV		0xee000a10
166*22dc650dSSadaf Ebrahimi #define VMOV2		0xec400a10
167*22dc650dSSadaf Ebrahimi #define VMOV_i		0xf2800010
168*22dc650dSSadaf Ebrahimi #define VMOV_s		0xee000b10
169*22dc650dSSadaf Ebrahimi #define VMOVN		0xf3b20200
170*22dc650dSSadaf Ebrahimi #define VMRS		0xeef1fa10
171*22dc650dSSadaf Ebrahimi #define VMUL_F32	0xee200a00
172*22dc650dSSadaf Ebrahimi #define VNEG_F32	0xeeb10a40
173*22dc650dSSadaf Ebrahimi #define VORR		0xf2200110
174*22dc650dSSadaf Ebrahimi #define VPOP		0xecbd0b00
175*22dc650dSSadaf Ebrahimi #define VPUSH		0xed2d0b00
176*22dc650dSSadaf Ebrahimi #define VSHLL		0xf2800a10
177*22dc650dSSadaf Ebrahimi #define VSHR		0xf2800010
178*22dc650dSSadaf Ebrahimi #define VSRA		0xf2800110
179*22dc650dSSadaf Ebrahimi #define VST1		0xf4000000
180*22dc650dSSadaf Ebrahimi #define VST1_s		0xf4800000
181*22dc650dSSadaf Ebrahimi #define VSTR_F32	0xed000a00
182*22dc650dSSadaf Ebrahimi #define VSUB_F32	0xee300a40
183*22dc650dSSadaf Ebrahimi 
184*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
185*22dc650dSSadaf Ebrahimi /* Arm v7 specific instructions. */
186*22dc650dSSadaf Ebrahimi #define MOVT		0xe3400000
187*22dc650dSSadaf Ebrahimi #define MOVW		0xe3000000
188*22dc650dSSadaf Ebrahimi #define RBIT		0xe6ff0f30
189*22dc650dSSadaf Ebrahimi #endif
190*22dc650dSSadaf Ebrahimi 
191*22dc650dSSadaf Ebrahimi #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
192*22dc650dSSadaf Ebrahimi 
function_check_is_freg(struct sljit_compiler * compiler,sljit_s32 fr,sljit_s32 is_32)193*22dc650dSSadaf Ebrahimi static sljit_s32 function_check_is_freg(struct sljit_compiler *compiler, sljit_s32 fr, sljit_s32 is_32)
194*22dc650dSSadaf Ebrahimi {
195*22dc650dSSadaf Ebrahimi 	if (compiler->scratches == -1)
196*22dc650dSSadaf Ebrahimi 		return 0;
197*22dc650dSSadaf Ebrahimi 
198*22dc650dSSadaf Ebrahimi 	if (is_32 && fr >= SLJIT_F64_SECOND(SLJIT_FR0))
199*22dc650dSSadaf Ebrahimi 		fr -= SLJIT_F64_SECOND(0);
200*22dc650dSSadaf Ebrahimi 
201*22dc650dSSadaf Ebrahimi 	return (fr >= SLJIT_FR0 && fr < (SLJIT_FR0 + compiler->fscratches))
202*22dc650dSSadaf Ebrahimi 		|| (fr > (SLJIT_FS0 - compiler->fsaveds) && fr <= SLJIT_FS0)
203*22dc650dSSadaf Ebrahimi 		|| (fr >= SLJIT_TMP_FREGISTER_BASE && fr < (SLJIT_TMP_FREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS));
204*22dc650dSSadaf Ebrahimi }
205*22dc650dSSadaf Ebrahimi 
206*22dc650dSSadaf Ebrahimi #endif /* SLJIT_ARGUMENT_CHECKS */
207*22dc650dSSadaf Ebrahimi 
208*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
209*22dc650dSSadaf Ebrahimi 
push_cpool(struct sljit_compiler * compiler)210*22dc650dSSadaf Ebrahimi static sljit_s32 push_cpool(struct sljit_compiler *compiler)
211*22dc650dSSadaf Ebrahimi {
212*22dc650dSSadaf Ebrahimi 	/* Pushing the constant pool into the instruction stream. */
213*22dc650dSSadaf Ebrahimi 	sljit_ins* inst;
214*22dc650dSSadaf Ebrahimi 	sljit_uw* cpool_ptr;
215*22dc650dSSadaf Ebrahimi 	sljit_uw* cpool_end;
216*22dc650dSSadaf Ebrahimi 	sljit_s32 i;
217*22dc650dSSadaf Ebrahimi 
218*22dc650dSSadaf Ebrahimi 	/* The label could point the address after the constant pool. */
219*22dc650dSSadaf Ebrahimi 	if (compiler->last_label && compiler->last_label->size == compiler->size)
220*22dc650dSSadaf Ebrahimi 		compiler->last_label->size += compiler->cpool_fill + (CONST_POOL_ALIGNMENT - 1) + 1;
221*22dc650dSSadaf Ebrahimi 
222*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(compiler->cpool_fill > 0 && compiler->cpool_fill <= CPOOL_SIZE);
223*22dc650dSSadaf Ebrahimi 	inst = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
224*22dc650dSSadaf Ebrahimi 	FAIL_IF(!inst);
225*22dc650dSSadaf Ebrahimi 	compiler->size++;
226*22dc650dSSadaf Ebrahimi 	*inst = 0xff000000 | compiler->cpool_fill;
227*22dc650dSSadaf Ebrahimi 
228*22dc650dSSadaf Ebrahimi 	for (i = 0; i < CONST_POOL_ALIGNMENT - 1; i++) {
229*22dc650dSSadaf Ebrahimi 		inst = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
230*22dc650dSSadaf Ebrahimi 		FAIL_IF(!inst);
231*22dc650dSSadaf Ebrahimi 		compiler->size++;
232*22dc650dSSadaf Ebrahimi 		*inst = 0;
233*22dc650dSSadaf Ebrahimi 	}
234*22dc650dSSadaf Ebrahimi 
235*22dc650dSSadaf Ebrahimi 	cpool_ptr = compiler->cpool;
236*22dc650dSSadaf Ebrahimi 	cpool_end = cpool_ptr + compiler->cpool_fill;
237*22dc650dSSadaf Ebrahimi 	while (cpool_ptr < cpool_end) {
238*22dc650dSSadaf Ebrahimi 		inst = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
239*22dc650dSSadaf Ebrahimi 		FAIL_IF(!inst);
240*22dc650dSSadaf Ebrahimi 		compiler->size++;
241*22dc650dSSadaf Ebrahimi 		*inst = *cpool_ptr++;
242*22dc650dSSadaf Ebrahimi 	}
243*22dc650dSSadaf Ebrahimi 	compiler->cpool_diff = CONST_POOL_EMPTY;
244*22dc650dSSadaf Ebrahimi 	compiler->cpool_fill = 0;
245*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
246*22dc650dSSadaf Ebrahimi }
247*22dc650dSSadaf Ebrahimi 
push_inst(struct sljit_compiler * compiler,sljit_ins inst)248*22dc650dSSadaf Ebrahimi static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins inst)
249*22dc650dSSadaf Ebrahimi {
250*22dc650dSSadaf Ebrahimi 	sljit_ins* ptr;
251*22dc650dSSadaf Ebrahimi 
252*22dc650dSSadaf Ebrahimi 	if (SLJIT_UNLIKELY(compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4092)))
253*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_cpool(compiler));
254*22dc650dSSadaf Ebrahimi 
255*22dc650dSSadaf Ebrahimi 	ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
256*22dc650dSSadaf Ebrahimi 	FAIL_IF(!ptr);
257*22dc650dSSadaf Ebrahimi 	compiler->size++;
258*22dc650dSSadaf Ebrahimi 	*ptr = inst;
259*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
260*22dc650dSSadaf Ebrahimi }
261*22dc650dSSadaf Ebrahimi 
push_inst_with_literal(struct sljit_compiler * compiler,sljit_ins inst,sljit_uw literal)262*22dc650dSSadaf Ebrahimi static sljit_s32 push_inst_with_literal(struct sljit_compiler *compiler, sljit_ins inst, sljit_uw literal)
263*22dc650dSSadaf Ebrahimi {
264*22dc650dSSadaf Ebrahimi 	sljit_ins* ptr;
265*22dc650dSSadaf Ebrahimi 	sljit_uw cpool_index = CPOOL_SIZE;
266*22dc650dSSadaf Ebrahimi 	sljit_uw* cpool_ptr;
267*22dc650dSSadaf Ebrahimi 	sljit_uw* cpool_end;
268*22dc650dSSadaf Ebrahimi 	sljit_u8* cpool_unique_ptr;
269*22dc650dSSadaf Ebrahimi 
270*22dc650dSSadaf Ebrahimi 	if (SLJIT_UNLIKELY(compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4092)))
271*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_cpool(compiler));
272*22dc650dSSadaf Ebrahimi 	else if (compiler->cpool_fill > 0) {
273*22dc650dSSadaf Ebrahimi 		cpool_ptr = compiler->cpool;
274*22dc650dSSadaf Ebrahimi 		cpool_end = cpool_ptr + compiler->cpool_fill;
275*22dc650dSSadaf Ebrahimi 		cpool_unique_ptr = compiler->cpool_unique;
276*22dc650dSSadaf Ebrahimi 		do {
277*22dc650dSSadaf Ebrahimi 			if ((*cpool_ptr == literal) && !(*cpool_unique_ptr)) {
278*22dc650dSSadaf Ebrahimi 				cpool_index = (sljit_uw)(cpool_ptr - compiler->cpool);
279*22dc650dSSadaf Ebrahimi 				break;
280*22dc650dSSadaf Ebrahimi 			}
281*22dc650dSSadaf Ebrahimi 			cpool_ptr++;
282*22dc650dSSadaf Ebrahimi 			cpool_unique_ptr++;
283*22dc650dSSadaf Ebrahimi 		} while (cpool_ptr < cpool_end);
284*22dc650dSSadaf Ebrahimi 	}
285*22dc650dSSadaf Ebrahimi 
286*22dc650dSSadaf Ebrahimi 	if (cpool_index == CPOOL_SIZE) {
287*22dc650dSSadaf Ebrahimi 		/* Must allocate a new entry in the literal pool. */
288*22dc650dSSadaf Ebrahimi 		if (compiler->cpool_fill < CPOOL_SIZE) {
289*22dc650dSSadaf Ebrahimi 			cpool_index = compiler->cpool_fill;
290*22dc650dSSadaf Ebrahimi 			compiler->cpool_fill++;
291*22dc650dSSadaf Ebrahimi 		}
292*22dc650dSSadaf Ebrahimi 		else {
293*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_cpool(compiler));
294*22dc650dSSadaf Ebrahimi 			cpool_index = 0;
295*22dc650dSSadaf Ebrahimi 			compiler->cpool_fill = 1;
296*22dc650dSSadaf Ebrahimi 		}
297*22dc650dSSadaf Ebrahimi 	}
298*22dc650dSSadaf Ebrahimi 
299*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT((inst & 0xfff) == 0);
300*22dc650dSSadaf Ebrahimi 	ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
301*22dc650dSSadaf Ebrahimi 	FAIL_IF(!ptr);
302*22dc650dSSadaf Ebrahimi 	compiler->size++;
303*22dc650dSSadaf Ebrahimi 	*ptr = inst | cpool_index;
304*22dc650dSSadaf Ebrahimi 
305*22dc650dSSadaf Ebrahimi 	compiler->cpool[cpool_index] = literal;
306*22dc650dSSadaf Ebrahimi 	compiler->cpool_unique[cpool_index] = 0;
307*22dc650dSSadaf Ebrahimi 	if (compiler->cpool_diff == CONST_POOL_EMPTY)
308*22dc650dSSadaf Ebrahimi 		compiler->cpool_diff = compiler->size;
309*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
310*22dc650dSSadaf Ebrahimi }
311*22dc650dSSadaf Ebrahimi 
push_inst_with_unique_literal(struct sljit_compiler * compiler,sljit_ins inst,sljit_uw literal)312*22dc650dSSadaf Ebrahimi static sljit_s32 push_inst_with_unique_literal(struct sljit_compiler *compiler, sljit_ins inst, sljit_uw literal)
313*22dc650dSSadaf Ebrahimi {
314*22dc650dSSadaf Ebrahimi 	sljit_ins* ptr;
315*22dc650dSSadaf Ebrahimi 
316*22dc650dSSadaf Ebrahimi 	if (SLJIT_UNLIKELY((compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4092)) || compiler->cpool_fill >= CPOOL_SIZE))
317*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_cpool(compiler));
318*22dc650dSSadaf Ebrahimi 
319*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(compiler->cpool_fill < CPOOL_SIZE && (inst & 0xfff) == 0);
320*22dc650dSSadaf Ebrahimi 	ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
321*22dc650dSSadaf Ebrahimi 	FAIL_IF(!ptr);
322*22dc650dSSadaf Ebrahimi 	compiler->size++;
323*22dc650dSSadaf Ebrahimi 	*ptr = inst | compiler->cpool_fill;
324*22dc650dSSadaf Ebrahimi 
325*22dc650dSSadaf Ebrahimi 	compiler->cpool[compiler->cpool_fill] = literal;
326*22dc650dSSadaf Ebrahimi 	compiler->cpool_unique[compiler->cpool_fill] = 1;
327*22dc650dSSadaf Ebrahimi 	compiler->cpool_fill++;
328*22dc650dSSadaf Ebrahimi 	if (compiler->cpool_diff == CONST_POOL_EMPTY)
329*22dc650dSSadaf Ebrahimi 		compiler->cpool_diff = compiler->size;
330*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
331*22dc650dSSadaf Ebrahimi }
332*22dc650dSSadaf Ebrahimi 
prepare_blx(struct sljit_compiler * compiler)333*22dc650dSSadaf Ebrahimi static SLJIT_INLINE sljit_s32 prepare_blx(struct sljit_compiler *compiler)
334*22dc650dSSadaf Ebrahimi {
335*22dc650dSSadaf Ebrahimi 	/* Place for at least two instruction (doesn't matter whether the first has a literal). */
336*22dc650dSSadaf Ebrahimi 	if (SLJIT_UNLIKELY(compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4088)))
337*22dc650dSSadaf Ebrahimi 		return push_cpool(compiler);
338*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
339*22dc650dSSadaf Ebrahimi }
340*22dc650dSSadaf Ebrahimi 
emit_blx(struct sljit_compiler * compiler)341*22dc650dSSadaf Ebrahimi static SLJIT_INLINE sljit_s32 emit_blx(struct sljit_compiler *compiler)
342*22dc650dSSadaf Ebrahimi {
343*22dc650dSSadaf Ebrahimi 	/* Must follow tightly the previous instruction (to be able to convert it to bl instruction). */
344*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(compiler->cpool_diff == CONST_POOL_EMPTY || compiler->size - compiler->cpool_diff < MAX_DIFFERENCE(4092));
345*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(reg_map[TMP_REG1] != 14);
346*22dc650dSSadaf Ebrahimi 
347*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, BLX | RM(TMP_REG1));
348*22dc650dSSadaf Ebrahimi }
349*22dc650dSSadaf Ebrahimi 
patch_pc_relative_loads(sljit_uw * last_pc_patch,sljit_uw * code_ptr,sljit_uw * const_pool,sljit_uw cpool_size)350*22dc650dSSadaf Ebrahimi static sljit_uw patch_pc_relative_loads(sljit_uw *last_pc_patch, sljit_uw *code_ptr, sljit_uw* const_pool, sljit_uw cpool_size)
351*22dc650dSSadaf Ebrahimi {
352*22dc650dSSadaf Ebrahimi 	sljit_uw diff;
353*22dc650dSSadaf Ebrahimi 	sljit_uw ind;
354*22dc650dSSadaf Ebrahimi 	sljit_uw counter = 0;
355*22dc650dSSadaf Ebrahimi 	sljit_uw* clear_const_pool = const_pool;
356*22dc650dSSadaf Ebrahimi 	sljit_uw* clear_const_pool_end = const_pool + cpool_size;
357*22dc650dSSadaf Ebrahimi 
358*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(const_pool - code_ptr <= CONST_POOL_ALIGNMENT);
359*22dc650dSSadaf Ebrahimi 	/* Set unused flag for all literals in the constant pool.
360*22dc650dSSadaf Ebrahimi 	   I.e.: unused literals can belong to branches, which can be encoded as B or BL.
361*22dc650dSSadaf Ebrahimi 	   We can "compress" the constant pool by discarding these literals. */
362*22dc650dSSadaf Ebrahimi 	while (clear_const_pool < clear_const_pool_end)
363*22dc650dSSadaf Ebrahimi 		*clear_const_pool++ = (sljit_uw)(-1);
364*22dc650dSSadaf Ebrahimi 
365*22dc650dSSadaf Ebrahimi 	while (last_pc_patch < code_ptr) {
366*22dc650dSSadaf Ebrahimi 		/* Data transfer instruction with Rn == r15. */
367*22dc650dSSadaf Ebrahimi 		if ((*last_pc_patch & 0x0e0f0000) == 0x040f0000) {
368*22dc650dSSadaf Ebrahimi 			diff = (sljit_uw)(const_pool - last_pc_patch);
369*22dc650dSSadaf Ebrahimi 			ind = (*last_pc_patch) & 0xfff;
370*22dc650dSSadaf Ebrahimi 
371*22dc650dSSadaf Ebrahimi 			/* Must be a load instruction with immediate offset. */
372*22dc650dSSadaf Ebrahimi 			SLJIT_ASSERT(ind < cpool_size && !(*last_pc_patch & (1 << 25)) && (*last_pc_patch & (1 << 20)));
373*22dc650dSSadaf Ebrahimi 			if ((sljit_s32)const_pool[ind] < 0) {
374*22dc650dSSadaf Ebrahimi 				const_pool[ind] = counter;
375*22dc650dSSadaf Ebrahimi 				ind = counter;
376*22dc650dSSadaf Ebrahimi 				counter++;
377*22dc650dSSadaf Ebrahimi 			}
378*22dc650dSSadaf Ebrahimi 			else
379*22dc650dSSadaf Ebrahimi 				ind = const_pool[ind];
380*22dc650dSSadaf Ebrahimi 
381*22dc650dSSadaf Ebrahimi 			SLJIT_ASSERT(diff >= 1);
382*22dc650dSSadaf Ebrahimi 			if (diff >= 2 || ind > 0) {
383*22dc650dSSadaf Ebrahimi 				diff = (diff + (sljit_uw)ind - 2) << 2;
384*22dc650dSSadaf Ebrahimi 				SLJIT_ASSERT(diff <= 0xfff);
385*22dc650dSSadaf Ebrahimi 				*last_pc_patch = (*last_pc_patch & ~(sljit_uw)0xfff) | diff;
386*22dc650dSSadaf Ebrahimi 			}
387*22dc650dSSadaf Ebrahimi 			else
388*22dc650dSSadaf Ebrahimi 				*last_pc_patch = (*last_pc_patch & ~(sljit_uw)(0xfff | (1 << 23))) | 0x004;
389*22dc650dSSadaf Ebrahimi 		}
390*22dc650dSSadaf Ebrahimi 		last_pc_patch++;
391*22dc650dSSadaf Ebrahimi 	}
392*22dc650dSSadaf Ebrahimi 	return counter;
393*22dc650dSSadaf Ebrahimi }
394*22dc650dSSadaf Ebrahimi 
395*22dc650dSSadaf Ebrahimi /* In some rare ocasions we may need future patches. The probability is close to 0 in practice. */
396*22dc650dSSadaf Ebrahimi struct future_patch {
397*22dc650dSSadaf Ebrahimi 	struct future_patch* next;
398*22dc650dSSadaf Ebrahimi 	sljit_s32 index;
399*22dc650dSSadaf Ebrahimi 	sljit_s32 value;
400*22dc650dSSadaf Ebrahimi };
401*22dc650dSSadaf Ebrahimi 
resolve_const_pool_index(struct sljit_compiler * compiler,struct future_patch ** first_patch,sljit_uw cpool_current_index,sljit_uw * cpool_start_address,sljit_uw * buf_ptr)402*22dc650dSSadaf Ebrahimi static sljit_s32 resolve_const_pool_index(struct sljit_compiler *compiler, struct future_patch **first_patch, sljit_uw cpool_current_index, sljit_uw *cpool_start_address, sljit_uw *buf_ptr)
403*22dc650dSSadaf Ebrahimi {
404*22dc650dSSadaf Ebrahimi 	sljit_u32 value;
405*22dc650dSSadaf Ebrahimi 	struct future_patch *curr_patch, *prev_patch;
406*22dc650dSSadaf Ebrahimi 
407*22dc650dSSadaf Ebrahimi 	SLJIT_UNUSED_ARG(compiler);
408*22dc650dSSadaf Ebrahimi 
409*22dc650dSSadaf Ebrahimi 	/* Using the values generated by patch_pc_relative_loads. */
410*22dc650dSSadaf Ebrahimi 	if (!*first_patch)
411*22dc650dSSadaf Ebrahimi 		value = cpool_start_address[cpool_current_index];
412*22dc650dSSadaf Ebrahimi 	else {
413*22dc650dSSadaf Ebrahimi 		curr_patch = *first_patch;
414*22dc650dSSadaf Ebrahimi 		prev_patch = NULL;
415*22dc650dSSadaf Ebrahimi 		while (1) {
416*22dc650dSSadaf Ebrahimi 			if (!curr_patch) {
417*22dc650dSSadaf Ebrahimi 				value = cpool_start_address[cpool_current_index];
418*22dc650dSSadaf Ebrahimi 				break;
419*22dc650dSSadaf Ebrahimi 			}
420*22dc650dSSadaf Ebrahimi 			if ((sljit_uw)curr_patch->index == cpool_current_index) {
421*22dc650dSSadaf Ebrahimi 				value = (sljit_uw)curr_patch->value;
422*22dc650dSSadaf Ebrahimi 				if (prev_patch)
423*22dc650dSSadaf Ebrahimi 					prev_patch->next = curr_patch->next;
424*22dc650dSSadaf Ebrahimi 				else
425*22dc650dSSadaf Ebrahimi 					*first_patch = curr_patch->next;
426*22dc650dSSadaf Ebrahimi 				SLJIT_FREE(curr_patch, compiler->allocator_data);
427*22dc650dSSadaf Ebrahimi 				break;
428*22dc650dSSadaf Ebrahimi 			}
429*22dc650dSSadaf Ebrahimi 			prev_patch = curr_patch;
430*22dc650dSSadaf Ebrahimi 			curr_patch = curr_patch->next;
431*22dc650dSSadaf Ebrahimi 		}
432*22dc650dSSadaf Ebrahimi 	}
433*22dc650dSSadaf Ebrahimi 
434*22dc650dSSadaf Ebrahimi 	if ((sljit_sw)value >= 0) {
435*22dc650dSSadaf Ebrahimi 		if (value > cpool_current_index) {
436*22dc650dSSadaf Ebrahimi 			curr_patch = (struct future_patch*)SLJIT_MALLOC(sizeof(struct future_patch), compiler->allocator_data);
437*22dc650dSSadaf Ebrahimi 			if (!curr_patch) {
438*22dc650dSSadaf Ebrahimi 				while (*first_patch) {
439*22dc650dSSadaf Ebrahimi 					curr_patch = *first_patch;
440*22dc650dSSadaf Ebrahimi 					*first_patch = (*first_patch)->next;
441*22dc650dSSadaf Ebrahimi 					SLJIT_FREE(curr_patch, compiler->allocator_data);
442*22dc650dSSadaf Ebrahimi 				}
443*22dc650dSSadaf Ebrahimi 				return SLJIT_ERR_ALLOC_FAILED;
444*22dc650dSSadaf Ebrahimi 			}
445*22dc650dSSadaf Ebrahimi 			curr_patch->next = *first_patch;
446*22dc650dSSadaf Ebrahimi 			curr_patch->index = (sljit_sw)value;
447*22dc650dSSadaf Ebrahimi 			curr_patch->value = (sljit_sw)cpool_start_address[value];
448*22dc650dSSadaf Ebrahimi 			*first_patch = curr_patch;
449*22dc650dSSadaf Ebrahimi 		}
450*22dc650dSSadaf Ebrahimi 		cpool_start_address[value] = *buf_ptr;
451*22dc650dSSadaf Ebrahimi 	}
452*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
453*22dc650dSSadaf Ebrahimi }
454*22dc650dSSadaf Ebrahimi 
455*22dc650dSSadaf Ebrahimi #else
456*22dc650dSSadaf Ebrahimi 
push_inst(struct sljit_compiler * compiler,sljit_ins inst)457*22dc650dSSadaf Ebrahimi static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins inst)
458*22dc650dSSadaf Ebrahimi {
459*22dc650dSSadaf Ebrahimi 	sljit_ins* ptr;
460*22dc650dSSadaf Ebrahimi 
461*22dc650dSSadaf Ebrahimi 	ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
462*22dc650dSSadaf Ebrahimi 	FAIL_IF(!ptr);
463*22dc650dSSadaf Ebrahimi 	compiler->size++;
464*22dc650dSSadaf Ebrahimi 	*ptr = inst;
465*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
466*22dc650dSSadaf Ebrahimi }
467*22dc650dSSadaf Ebrahimi 
emit_imm(struct sljit_compiler * compiler,sljit_s32 reg,sljit_sw imm)468*22dc650dSSadaf Ebrahimi static SLJIT_INLINE sljit_s32 emit_imm(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm)
469*22dc650dSSadaf Ebrahimi {
470*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | ((sljit_u32)imm & 0xfff)));
471*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, MOVT | RD(reg) | ((imm >> 12) & 0xf0000) | (((sljit_u32)imm >> 16) & 0xfff));
472*22dc650dSSadaf Ebrahimi }
473*22dc650dSSadaf Ebrahimi 
474*22dc650dSSadaf Ebrahimi #endif
475*22dc650dSSadaf Ebrahimi 
detect_jump_type(struct sljit_jump * jump,sljit_uw * code_ptr,sljit_uw * code,sljit_sw executable_offset)476*22dc650dSSadaf Ebrahimi static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_uw *code_ptr, sljit_uw *code, sljit_sw executable_offset)
477*22dc650dSSadaf Ebrahimi {
478*22dc650dSSadaf Ebrahimi 	sljit_sw diff;
479*22dc650dSSadaf Ebrahimi 
480*22dc650dSSadaf Ebrahimi 	if (jump->flags & SLJIT_REWRITABLE_JUMP)
481*22dc650dSSadaf Ebrahimi 		return 0;
482*22dc650dSSadaf Ebrahimi 
483*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
484*22dc650dSSadaf Ebrahimi 	if (jump->flags & IS_BL)
485*22dc650dSSadaf Ebrahimi 		code_ptr--;
486*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_ARM_V6 */
487*22dc650dSSadaf Ebrahimi 
488*22dc650dSSadaf Ebrahimi 	if (jump->flags & JUMP_ADDR)
489*22dc650dSSadaf Ebrahimi 		diff = ((sljit_sw)jump->u.target - (sljit_sw)(code_ptr + 2) - executable_offset);
490*22dc650dSSadaf Ebrahimi 	else {
491*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(jump->u.label != NULL);
492*22dc650dSSadaf Ebrahimi 		diff = ((sljit_sw)(code + jump->u.label->size) - (sljit_sw)(code_ptr + 2));
493*22dc650dSSadaf Ebrahimi 	}
494*22dc650dSSadaf Ebrahimi 
495*22dc650dSSadaf Ebrahimi 	/* Branch to Thumb code has not been optimized yet. */
496*22dc650dSSadaf Ebrahimi 	if (diff & 0x3)
497*22dc650dSSadaf Ebrahimi 		return 0;
498*22dc650dSSadaf Ebrahimi 
499*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
500*22dc650dSSadaf Ebrahimi 	if (jump->flags & IS_BL) {
501*22dc650dSSadaf Ebrahimi 		if (diff <= 0x01ffffff && diff >= -0x02000000) {
502*22dc650dSSadaf Ebrahimi 			*code_ptr = (BL - CONDITIONAL) | (*(code_ptr + 1) & COND_MASK);
503*22dc650dSSadaf Ebrahimi 			jump->flags |= PATCH_B;
504*22dc650dSSadaf Ebrahimi 			return 1;
505*22dc650dSSadaf Ebrahimi 		}
506*22dc650dSSadaf Ebrahimi 	}
507*22dc650dSSadaf Ebrahimi 	else {
508*22dc650dSSadaf Ebrahimi 		if (diff <= 0x01ffffff && diff >= -0x02000000) {
509*22dc650dSSadaf Ebrahimi 			*code_ptr = (B - CONDITIONAL) | (*code_ptr & COND_MASK);
510*22dc650dSSadaf Ebrahimi 			jump->flags |= PATCH_B;
511*22dc650dSSadaf Ebrahimi 		}
512*22dc650dSSadaf Ebrahimi 	}
513*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_ARM_V6 */
514*22dc650dSSadaf Ebrahimi 	if (diff <= 0x01ffffff && diff >= -0x02000000) {
515*22dc650dSSadaf Ebrahimi 		*code_ptr = ((jump->flags & IS_BL) ? (BL - CONDITIONAL) : (B - CONDITIONAL)) | (*code_ptr & COND_MASK);
516*22dc650dSSadaf Ebrahimi 		jump->flags |= PATCH_B;
517*22dc650dSSadaf Ebrahimi 		return 1;
518*22dc650dSSadaf Ebrahimi 	}
519*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_ARM_V6 */
520*22dc650dSSadaf Ebrahimi 	return 0;
521*22dc650dSSadaf Ebrahimi }
522*22dc650dSSadaf Ebrahimi 
set_jump_addr(sljit_uw jump_ptr,sljit_sw executable_offset,sljit_uw new_addr,sljit_s32 flush_cache)523*22dc650dSSadaf Ebrahimi static void set_jump_addr(sljit_uw jump_ptr, sljit_sw executable_offset, sljit_uw new_addr, sljit_s32 flush_cache)
524*22dc650dSSadaf Ebrahimi {
525*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
526*22dc650dSSadaf Ebrahimi 	sljit_ins *ptr = (sljit_ins*)jump_ptr;
527*22dc650dSSadaf Ebrahimi 	sljit_ins *inst = (sljit_ins*)ptr[0];
528*22dc650dSSadaf Ebrahimi 	sljit_ins mov_pc = ptr[1];
529*22dc650dSSadaf Ebrahimi 	sljit_s32 bl = (mov_pc & 0x0000f000) != RD(TMP_PC);
530*22dc650dSSadaf Ebrahimi 	sljit_sw diff = (sljit_sw)(((sljit_sw)new_addr - (sljit_sw)(inst + 2) - executable_offset) >> 2);
531*22dc650dSSadaf Ebrahimi 
532*22dc650dSSadaf Ebrahimi 	SLJIT_UNUSED_ARG(executable_offset);
533*22dc650dSSadaf Ebrahimi 
534*22dc650dSSadaf Ebrahimi 	if (diff <= 0x7fffff && diff >= -0x800000) {
535*22dc650dSSadaf Ebrahimi 		/* Turn to branch. */
536*22dc650dSSadaf Ebrahimi 		if (!bl) {
537*22dc650dSSadaf Ebrahimi 			if (flush_cache) {
538*22dc650dSSadaf Ebrahimi 				SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);
539*22dc650dSSadaf Ebrahimi 			}
540*22dc650dSSadaf Ebrahimi 			inst[0] = (mov_pc & COND_MASK) | (B - CONDITIONAL) | (diff & 0xffffff);
541*22dc650dSSadaf Ebrahimi 			if (flush_cache) {
542*22dc650dSSadaf Ebrahimi 				SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);
543*22dc650dSSadaf Ebrahimi 				inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
544*22dc650dSSadaf Ebrahimi 				SLJIT_CACHE_FLUSH(inst, inst + 1);
545*22dc650dSSadaf Ebrahimi 			}
546*22dc650dSSadaf Ebrahimi 		} else {
547*22dc650dSSadaf Ebrahimi 			if (flush_cache) {
548*22dc650dSSadaf Ebrahimi 				SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);
549*22dc650dSSadaf Ebrahimi 			}
550*22dc650dSSadaf Ebrahimi 			inst[0] = (mov_pc & COND_MASK) | (BL - CONDITIONAL) | (diff & 0xffffff);
551*22dc650dSSadaf Ebrahimi 			inst[1] = NOP;
552*22dc650dSSadaf Ebrahimi 			if (flush_cache) {
553*22dc650dSSadaf Ebrahimi 				SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
554*22dc650dSSadaf Ebrahimi 				inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
555*22dc650dSSadaf Ebrahimi 				SLJIT_CACHE_FLUSH(inst, inst + 2);
556*22dc650dSSadaf Ebrahimi 			}
557*22dc650dSSadaf Ebrahimi 		}
558*22dc650dSSadaf Ebrahimi 	} else {
559*22dc650dSSadaf Ebrahimi 		/* Get the position of the constant. */
560*22dc650dSSadaf Ebrahimi 		if (mov_pc & (1 << 23))
561*22dc650dSSadaf Ebrahimi 			ptr = inst + ((mov_pc & 0xfff) >> 2) + 2;
562*22dc650dSSadaf Ebrahimi 		else
563*22dc650dSSadaf Ebrahimi 			ptr = inst + 1;
564*22dc650dSSadaf Ebrahimi 
565*22dc650dSSadaf Ebrahimi 		if (*inst != mov_pc) {
566*22dc650dSSadaf Ebrahimi 			if (flush_cache) {
567*22dc650dSSadaf Ebrahimi 				SLJIT_UPDATE_WX_FLAGS(inst, inst + (!bl ? 1 : 2), 0);
568*22dc650dSSadaf Ebrahimi 			}
569*22dc650dSSadaf Ebrahimi 			inst[0] = mov_pc;
570*22dc650dSSadaf Ebrahimi 			if (!bl) {
571*22dc650dSSadaf Ebrahimi 				if (flush_cache) {
572*22dc650dSSadaf Ebrahimi 					SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);
573*22dc650dSSadaf Ebrahimi 					inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
574*22dc650dSSadaf Ebrahimi 					SLJIT_CACHE_FLUSH(inst, inst + 1);
575*22dc650dSSadaf Ebrahimi 				}
576*22dc650dSSadaf Ebrahimi 			} else {
577*22dc650dSSadaf Ebrahimi 				inst[1] = BLX | RM(TMP_REG1);
578*22dc650dSSadaf Ebrahimi 				if (flush_cache) {
579*22dc650dSSadaf Ebrahimi 					SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
580*22dc650dSSadaf Ebrahimi 					inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
581*22dc650dSSadaf Ebrahimi 					SLJIT_CACHE_FLUSH(inst, inst + 2);
582*22dc650dSSadaf Ebrahimi 				}
583*22dc650dSSadaf Ebrahimi 			}
584*22dc650dSSadaf Ebrahimi 		}
585*22dc650dSSadaf Ebrahimi 
586*22dc650dSSadaf Ebrahimi 		if (flush_cache) {
587*22dc650dSSadaf Ebrahimi 			SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 0);
588*22dc650dSSadaf Ebrahimi 		}
589*22dc650dSSadaf Ebrahimi 
590*22dc650dSSadaf Ebrahimi 		*ptr = new_addr;
591*22dc650dSSadaf Ebrahimi 
592*22dc650dSSadaf Ebrahimi 		if (flush_cache) {
593*22dc650dSSadaf Ebrahimi 			SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 1);
594*22dc650dSSadaf Ebrahimi 		}
595*22dc650dSSadaf Ebrahimi 	}
596*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_ARM_V6 */
597*22dc650dSSadaf Ebrahimi 	sljit_ins *inst = (sljit_ins*)jump_ptr;
598*22dc650dSSadaf Ebrahimi 
599*22dc650dSSadaf Ebrahimi 	SLJIT_UNUSED_ARG(executable_offset);
600*22dc650dSSadaf Ebrahimi 
601*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT((inst[0] & 0xfff00000) == MOVW && (inst[1] & 0xfff00000) == MOVT);
602*22dc650dSSadaf Ebrahimi 
603*22dc650dSSadaf Ebrahimi 	if (flush_cache) {
604*22dc650dSSadaf Ebrahimi 		SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);
605*22dc650dSSadaf Ebrahimi 	}
606*22dc650dSSadaf Ebrahimi 
607*22dc650dSSadaf Ebrahimi 	inst[0] = MOVW | (inst[0] & 0xf000) | ((new_addr << 4) & 0xf0000) | (new_addr & 0xfff);
608*22dc650dSSadaf Ebrahimi 	inst[1] = MOVT | (inst[1] & 0xf000) | ((new_addr >> 12) & 0xf0000) | ((new_addr >> 16) & 0xfff);
609*22dc650dSSadaf Ebrahimi 
610*22dc650dSSadaf Ebrahimi 	if (flush_cache) {
611*22dc650dSSadaf Ebrahimi 		SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
612*22dc650dSSadaf Ebrahimi 		inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
613*22dc650dSSadaf Ebrahimi 		SLJIT_CACHE_FLUSH(inst, inst + 2);
614*22dc650dSSadaf Ebrahimi 	}
615*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_ARM_V6 */
616*22dc650dSSadaf Ebrahimi }
617*22dc650dSSadaf Ebrahimi 
618*22dc650dSSadaf Ebrahimi static sljit_uw get_imm(sljit_uw imm);
619*22dc650dSSadaf Ebrahimi static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_uw imm);
620*22dc650dSSadaf Ebrahimi static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg);
621*22dc650dSSadaf Ebrahimi 
set_const_value(sljit_uw addr,sljit_sw executable_offset,sljit_uw new_constant,sljit_s32 flush_cache)622*22dc650dSSadaf Ebrahimi static void set_const_value(sljit_uw addr, sljit_sw executable_offset, sljit_uw new_constant, sljit_s32 flush_cache)
623*22dc650dSSadaf Ebrahimi {
624*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
625*22dc650dSSadaf Ebrahimi 	sljit_ins *ptr = (sljit_ins*)addr;
626*22dc650dSSadaf Ebrahimi 	sljit_ins *inst = (sljit_ins*)ptr[0];
627*22dc650dSSadaf Ebrahimi 	sljit_uw ldr_literal = ptr[1];
628*22dc650dSSadaf Ebrahimi 	sljit_uw src2;
629*22dc650dSSadaf Ebrahimi 
630*22dc650dSSadaf Ebrahimi 	SLJIT_UNUSED_ARG(executable_offset);
631*22dc650dSSadaf Ebrahimi 
632*22dc650dSSadaf Ebrahimi 	src2 = get_imm(new_constant);
633*22dc650dSSadaf Ebrahimi 	if (src2) {
634*22dc650dSSadaf Ebrahimi 		if (flush_cache) {
635*22dc650dSSadaf Ebrahimi 			SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);
636*22dc650dSSadaf Ebrahimi 		}
637*22dc650dSSadaf Ebrahimi 
638*22dc650dSSadaf Ebrahimi 		*inst = 0xe3a00000 | (ldr_literal & 0xf000) | src2;
639*22dc650dSSadaf Ebrahimi 
640*22dc650dSSadaf Ebrahimi 		if (flush_cache) {
641*22dc650dSSadaf Ebrahimi 			SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);
642*22dc650dSSadaf Ebrahimi 			inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
643*22dc650dSSadaf Ebrahimi 			SLJIT_CACHE_FLUSH(inst, inst + 1);
644*22dc650dSSadaf Ebrahimi 		}
645*22dc650dSSadaf Ebrahimi 		return;
646*22dc650dSSadaf Ebrahimi 	}
647*22dc650dSSadaf Ebrahimi 
648*22dc650dSSadaf Ebrahimi 	src2 = get_imm(~new_constant);
649*22dc650dSSadaf Ebrahimi 	if (src2) {
650*22dc650dSSadaf Ebrahimi 		if (flush_cache) {
651*22dc650dSSadaf Ebrahimi 			SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);
652*22dc650dSSadaf Ebrahimi 		}
653*22dc650dSSadaf Ebrahimi 
654*22dc650dSSadaf Ebrahimi 		*inst = 0xe3e00000 | (ldr_literal & 0xf000) | src2;
655*22dc650dSSadaf Ebrahimi 
656*22dc650dSSadaf Ebrahimi 		if (flush_cache) {
657*22dc650dSSadaf Ebrahimi 			SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);
658*22dc650dSSadaf Ebrahimi 			inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
659*22dc650dSSadaf Ebrahimi 			SLJIT_CACHE_FLUSH(inst, inst + 1);
660*22dc650dSSadaf Ebrahimi 		}
661*22dc650dSSadaf Ebrahimi 		return;
662*22dc650dSSadaf Ebrahimi 	}
663*22dc650dSSadaf Ebrahimi 
664*22dc650dSSadaf Ebrahimi 	if (ldr_literal & (1 << 23))
665*22dc650dSSadaf Ebrahimi 		ptr = inst + ((ldr_literal & 0xfff) >> 2) + 2;
666*22dc650dSSadaf Ebrahimi 	else
667*22dc650dSSadaf Ebrahimi 		ptr = inst + 1;
668*22dc650dSSadaf Ebrahimi 
669*22dc650dSSadaf Ebrahimi 	if (*inst != ldr_literal) {
670*22dc650dSSadaf Ebrahimi 		if (flush_cache) {
671*22dc650dSSadaf Ebrahimi 			SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);
672*22dc650dSSadaf Ebrahimi 		}
673*22dc650dSSadaf Ebrahimi 
674*22dc650dSSadaf Ebrahimi 		*inst = ldr_literal;
675*22dc650dSSadaf Ebrahimi 
676*22dc650dSSadaf Ebrahimi 		if (flush_cache) {
677*22dc650dSSadaf Ebrahimi 			SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);
678*22dc650dSSadaf Ebrahimi 			inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
679*22dc650dSSadaf Ebrahimi 			SLJIT_CACHE_FLUSH(inst, inst + 1);
680*22dc650dSSadaf Ebrahimi 		}
681*22dc650dSSadaf Ebrahimi 	}
682*22dc650dSSadaf Ebrahimi 
683*22dc650dSSadaf Ebrahimi 	if (flush_cache) {
684*22dc650dSSadaf Ebrahimi 		SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 0);
685*22dc650dSSadaf Ebrahimi 	}
686*22dc650dSSadaf Ebrahimi 
687*22dc650dSSadaf Ebrahimi 	*ptr = new_constant;
688*22dc650dSSadaf Ebrahimi 
689*22dc650dSSadaf Ebrahimi 	if (flush_cache) {
690*22dc650dSSadaf Ebrahimi 		SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 1);
691*22dc650dSSadaf Ebrahimi 	}
692*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_ARM_V6 */
693*22dc650dSSadaf Ebrahimi 	sljit_ins *inst = (sljit_ins*)addr;
694*22dc650dSSadaf Ebrahimi 
695*22dc650dSSadaf Ebrahimi 	SLJIT_UNUSED_ARG(executable_offset);
696*22dc650dSSadaf Ebrahimi 
697*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT((inst[0] & 0xfff00000) == MOVW && (inst[1] & 0xfff00000) == MOVT);
698*22dc650dSSadaf Ebrahimi 
699*22dc650dSSadaf Ebrahimi 	if (flush_cache) {
700*22dc650dSSadaf Ebrahimi 		SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);
701*22dc650dSSadaf Ebrahimi 	}
702*22dc650dSSadaf Ebrahimi 
703*22dc650dSSadaf Ebrahimi 	inst[0] = MOVW | (inst[0] & 0xf000) | ((new_constant << 4) & 0xf0000) | (new_constant & 0xfff);
704*22dc650dSSadaf Ebrahimi 	inst[1] = MOVT | (inst[1] & 0xf000) | ((new_constant >> 12) & 0xf0000) | ((new_constant >> 16) & 0xfff);
705*22dc650dSSadaf Ebrahimi 
706*22dc650dSSadaf Ebrahimi 	if (flush_cache) {
707*22dc650dSSadaf Ebrahimi 		SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
708*22dc650dSSadaf Ebrahimi 		inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
709*22dc650dSSadaf Ebrahimi 		SLJIT_CACHE_FLUSH(inst, inst + 2);
710*22dc650dSSadaf Ebrahimi 	}
711*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_ARM_V6 */
712*22dc650dSSadaf Ebrahimi }
713*22dc650dSSadaf Ebrahimi 
mov_addr_get_length(struct sljit_jump * jump,sljit_ins * code_ptr,sljit_ins * code,sljit_sw executable_offset)714*22dc650dSSadaf Ebrahimi static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
715*22dc650dSSadaf Ebrahimi {
716*22dc650dSSadaf Ebrahimi 	sljit_uw addr;
717*22dc650dSSadaf Ebrahimi 	sljit_sw diff;
718*22dc650dSSadaf Ebrahimi 	SLJIT_UNUSED_ARG(executable_offset);
719*22dc650dSSadaf Ebrahimi 
720*22dc650dSSadaf Ebrahimi 	if (jump->flags & JUMP_ADDR)
721*22dc650dSSadaf Ebrahimi 		addr = jump->u.target;
722*22dc650dSSadaf Ebrahimi 	else
723*22dc650dSSadaf Ebrahimi 		addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);
724*22dc650dSSadaf Ebrahimi 
725*22dc650dSSadaf Ebrahimi 	/* The pc+8 offset is represented by the 2 * SSIZE_OF(ins) below. */
726*22dc650dSSadaf Ebrahimi 	diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
727*22dc650dSSadaf Ebrahimi 
728*22dc650dSSadaf Ebrahimi 	if ((diff & 0x3) == 0 && diff <= (0x3fc + 2 * SSIZE_OF(ins)) && diff >= (-0x3fc + 2 * SSIZE_OF(ins))) {
729*22dc650dSSadaf Ebrahimi 		jump->flags |= PATCH_B;
730*22dc650dSSadaf Ebrahimi 		return 0;
731*22dc650dSSadaf Ebrahimi 	}
732*22dc650dSSadaf Ebrahimi 
733*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
734*22dc650dSSadaf Ebrahimi 	return 0;
735*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_ARM_V6 */
736*22dc650dSSadaf Ebrahimi 	return 1;
737*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_ARM_V6 */
738*22dc650dSSadaf Ebrahimi }
739*22dc650dSSadaf Ebrahimi 
740*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
741*22dc650dSSadaf Ebrahimi 
reduce_code_size(struct sljit_compiler * compiler)742*22dc650dSSadaf Ebrahimi static void reduce_code_size(struct sljit_compiler *compiler)
743*22dc650dSSadaf Ebrahimi {
744*22dc650dSSadaf Ebrahimi 	struct sljit_label *label;
745*22dc650dSSadaf Ebrahimi 	struct sljit_jump *jump;
746*22dc650dSSadaf Ebrahimi 	struct sljit_const *const_;
747*22dc650dSSadaf Ebrahimi 	SLJIT_NEXT_DEFINE_TYPES;
748*22dc650dSSadaf Ebrahimi 	sljit_uw total_size;
749*22dc650dSSadaf Ebrahimi 	sljit_uw size_reduce = 0;
750*22dc650dSSadaf Ebrahimi 	sljit_sw diff;
751*22dc650dSSadaf Ebrahimi 
752*22dc650dSSadaf Ebrahimi 	label = compiler->labels;
753*22dc650dSSadaf Ebrahimi 	jump = compiler->jumps;
754*22dc650dSSadaf Ebrahimi 	const_ = compiler->consts;
755*22dc650dSSadaf Ebrahimi 	SLJIT_NEXT_INIT_TYPES();
756*22dc650dSSadaf Ebrahimi 
757*22dc650dSSadaf Ebrahimi 	while (1) {
758*22dc650dSSadaf Ebrahimi 		SLJIT_GET_NEXT_MIN();
759*22dc650dSSadaf Ebrahimi 
760*22dc650dSSadaf Ebrahimi 		if (next_min_addr == SLJIT_MAX_ADDRESS)
761*22dc650dSSadaf Ebrahimi 			break;
762*22dc650dSSadaf Ebrahimi 
763*22dc650dSSadaf Ebrahimi 		if (next_min_addr == next_label_size) {
764*22dc650dSSadaf Ebrahimi 			label->size -= size_reduce;
765*22dc650dSSadaf Ebrahimi 
766*22dc650dSSadaf Ebrahimi 			label = label->next;
767*22dc650dSSadaf Ebrahimi 			next_label_size = SLJIT_GET_NEXT_SIZE(label);
768*22dc650dSSadaf Ebrahimi 		}
769*22dc650dSSadaf Ebrahimi 
770*22dc650dSSadaf Ebrahimi 		if (next_min_addr == next_const_addr) {
771*22dc650dSSadaf Ebrahimi 			const_->addr -= size_reduce;
772*22dc650dSSadaf Ebrahimi 			const_ = const_->next;
773*22dc650dSSadaf Ebrahimi 			next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);
774*22dc650dSSadaf Ebrahimi 			continue;
775*22dc650dSSadaf Ebrahimi 		}
776*22dc650dSSadaf Ebrahimi 
777*22dc650dSSadaf Ebrahimi 		if (next_min_addr != next_jump_addr)
778*22dc650dSSadaf Ebrahimi 			continue;
779*22dc650dSSadaf Ebrahimi 
780*22dc650dSSadaf Ebrahimi 		jump->addr -= size_reduce;
781*22dc650dSSadaf Ebrahimi 		if (!(jump->flags & JUMP_MOV_ADDR)) {
782*22dc650dSSadaf Ebrahimi 			total_size = JUMP_MAX_SIZE - 1;
783*22dc650dSSadaf Ebrahimi 
784*22dc650dSSadaf Ebrahimi 			if (!(jump->flags & (SLJIT_REWRITABLE_JUMP | JUMP_ADDR))) {
785*22dc650dSSadaf Ebrahimi 				/* Unit size: instruction. */
786*22dc650dSSadaf Ebrahimi 				diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr - 2;
787*22dc650dSSadaf Ebrahimi 
788*22dc650dSSadaf Ebrahimi 				if (diff <= (0x01ffffff / SSIZE_OF(ins)) && diff >= (-0x02000000 / SSIZE_OF(ins)))
789*22dc650dSSadaf Ebrahimi 					total_size = 1 - 1;
790*22dc650dSSadaf Ebrahimi 			}
791*22dc650dSSadaf Ebrahimi 
792*22dc650dSSadaf Ebrahimi 			size_reduce += JUMP_MAX_SIZE - 1 - total_size;
793*22dc650dSSadaf Ebrahimi 		} else {
794*22dc650dSSadaf Ebrahimi 			/* Real size minus 1. Unit size: instruction. */
795*22dc650dSSadaf Ebrahimi 			total_size = 1;
796*22dc650dSSadaf Ebrahimi 
797*22dc650dSSadaf Ebrahimi 			if (!(jump->flags & JUMP_ADDR)) {
798*22dc650dSSadaf Ebrahimi 				diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;
799*22dc650dSSadaf Ebrahimi 				if (diff <= 0xff + 2 && diff >= -0xff + 2)
800*22dc650dSSadaf Ebrahimi 					total_size = 0;
801*22dc650dSSadaf Ebrahimi 			}
802*22dc650dSSadaf Ebrahimi 
803*22dc650dSSadaf Ebrahimi 			size_reduce += 1 - total_size;
804*22dc650dSSadaf Ebrahimi 		}
805*22dc650dSSadaf Ebrahimi 
806*22dc650dSSadaf Ebrahimi 		jump->flags |= total_size << JUMP_SIZE_SHIFT;
807*22dc650dSSadaf Ebrahimi 		jump = jump->next;
808*22dc650dSSadaf Ebrahimi 		next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);
809*22dc650dSSadaf Ebrahimi 	}
810*22dc650dSSadaf Ebrahimi 
811*22dc650dSSadaf Ebrahimi 	compiler->size -= size_reduce;
812*22dc650dSSadaf Ebrahimi }
813*22dc650dSSadaf Ebrahimi 
814*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_ARM_V7 */
815*22dc650dSSadaf Ebrahimi 
sljit_generate_code(struct sljit_compiler * compiler,sljit_s32 options,void * exec_allocator_data)816*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data)
817*22dc650dSSadaf Ebrahimi {
818*22dc650dSSadaf Ebrahimi 	struct sljit_memory_fragment *buf;
819*22dc650dSSadaf Ebrahimi 	sljit_ins *code;
820*22dc650dSSadaf Ebrahimi 	sljit_ins *code_ptr;
821*22dc650dSSadaf Ebrahimi 	sljit_ins *buf_ptr;
822*22dc650dSSadaf Ebrahimi 	sljit_ins *buf_end;
823*22dc650dSSadaf Ebrahimi 	sljit_uw word_count;
824*22dc650dSSadaf Ebrahimi 	SLJIT_NEXT_DEFINE_TYPES;
825*22dc650dSSadaf Ebrahimi 	sljit_sw executable_offset;
826*22dc650dSSadaf Ebrahimi 	sljit_uw addr;
827*22dc650dSSadaf Ebrahimi 	sljit_sw diff;
828*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
829*22dc650dSSadaf Ebrahimi 	sljit_uw cpool_size;
830*22dc650dSSadaf Ebrahimi 	sljit_uw cpool_skip_alignment;
831*22dc650dSSadaf Ebrahimi 	sljit_uw cpool_current_index;
832*22dc650dSSadaf Ebrahimi 	sljit_ins *cpool_start_address;
833*22dc650dSSadaf Ebrahimi 	sljit_ins *last_pc_patch;
834*22dc650dSSadaf Ebrahimi 	struct future_patch *first_patch;
835*22dc650dSSadaf Ebrahimi #endif
836*22dc650dSSadaf Ebrahimi 
837*22dc650dSSadaf Ebrahimi 	struct sljit_label *label;
838*22dc650dSSadaf Ebrahimi 	struct sljit_jump *jump;
839*22dc650dSSadaf Ebrahimi 	struct sljit_const *const_;
840*22dc650dSSadaf Ebrahimi 
841*22dc650dSSadaf Ebrahimi 	CHECK_ERROR_PTR();
842*22dc650dSSadaf Ebrahimi 	CHECK_PTR(check_sljit_generate_code(compiler));
843*22dc650dSSadaf Ebrahimi 
844*22dc650dSSadaf Ebrahimi 	/* Second code generation pass. */
845*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
846*22dc650dSSadaf Ebrahimi 	compiler->size += (compiler->patches << 1);
847*22dc650dSSadaf Ebrahimi 	if (compiler->cpool_fill > 0)
848*22dc650dSSadaf Ebrahimi 		compiler->size += compiler->cpool_fill + CONST_POOL_ALIGNMENT - 1;
849*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_ARM_V6 */
850*22dc650dSSadaf Ebrahimi 	reduce_code_size(compiler);
851*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_ARM_V6 */
852*22dc650dSSadaf Ebrahimi 	code = (sljit_ins*)allocate_executable_memory(compiler->size * sizeof(sljit_ins), options, exec_allocator_data, &executable_offset);
853*22dc650dSSadaf Ebrahimi 	PTR_FAIL_WITH_EXEC_IF(code);
854*22dc650dSSadaf Ebrahimi 
855*22dc650dSSadaf Ebrahimi 	reverse_buf(compiler);
856*22dc650dSSadaf Ebrahimi 	buf = compiler->buf;
857*22dc650dSSadaf Ebrahimi 
858*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
859*22dc650dSSadaf Ebrahimi 	cpool_size = 0;
860*22dc650dSSadaf Ebrahimi 	cpool_skip_alignment = 0;
861*22dc650dSSadaf Ebrahimi 	cpool_current_index = 0;
862*22dc650dSSadaf Ebrahimi 	cpool_start_address = NULL;
863*22dc650dSSadaf Ebrahimi 	first_patch = NULL;
864*22dc650dSSadaf Ebrahimi 	last_pc_patch = code;
865*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_ARM_V6 */
866*22dc650dSSadaf Ebrahimi 
867*22dc650dSSadaf Ebrahimi 	code_ptr = code;
868*22dc650dSSadaf Ebrahimi 	word_count = 0;
869*22dc650dSSadaf Ebrahimi 	label = compiler->labels;
870*22dc650dSSadaf Ebrahimi 	jump = compiler->jumps;
871*22dc650dSSadaf Ebrahimi 	const_ = compiler->consts;
872*22dc650dSSadaf Ebrahimi 	SLJIT_NEXT_INIT_TYPES();
873*22dc650dSSadaf Ebrahimi 	SLJIT_GET_NEXT_MIN();
874*22dc650dSSadaf Ebrahimi 
875*22dc650dSSadaf Ebrahimi 	do {
876*22dc650dSSadaf Ebrahimi 		buf_ptr = (sljit_ins*)buf->memory;
877*22dc650dSSadaf Ebrahimi 		buf_end = buf_ptr + (buf->used_size >> 2);
878*22dc650dSSadaf Ebrahimi 		do {
879*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
880*22dc650dSSadaf Ebrahimi 			if (cpool_size > 0) {
881*22dc650dSSadaf Ebrahimi 				if (cpool_skip_alignment > 0) {
882*22dc650dSSadaf Ebrahimi 					buf_ptr++;
883*22dc650dSSadaf Ebrahimi 					cpool_skip_alignment--;
884*22dc650dSSadaf Ebrahimi 				} else {
885*22dc650dSSadaf Ebrahimi 					if (SLJIT_UNLIKELY(resolve_const_pool_index(compiler, &first_patch, cpool_current_index, cpool_start_address, buf_ptr))) {
886*22dc650dSSadaf Ebrahimi 						SLJIT_FREE_EXEC(code, exec_allocator_data);
887*22dc650dSSadaf Ebrahimi 						compiler->error = SLJIT_ERR_ALLOC_FAILED;
888*22dc650dSSadaf Ebrahimi 						return NULL;
889*22dc650dSSadaf Ebrahimi 					}
890*22dc650dSSadaf Ebrahimi 					buf_ptr++;
891*22dc650dSSadaf Ebrahimi 					if (++cpool_current_index >= cpool_size) {
892*22dc650dSSadaf Ebrahimi 						SLJIT_ASSERT(!first_patch);
893*22dc650dSSadaf Ebrahimi 						cpool_size = 0;
894*22dc650dSSadaf Ebrahimi 					}
895*22dc650dSSadaf Ebrahimi 				}
896*22dc650dSSadaf Ebrahimi 			} else if ((*buf_ptr & 0xff000000) != PUSH_POOL) {
897*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_ARM_V6 */
898*22dc650dSSadaf Ebrahimi 				*code_ptr = *buf_ptr++;
899*22dc650dSSadaf Ebrahimi 				if (next_min_addr == word_count) {
900*22dc650dSSadaf Ebrahimi 					SLJIT_ASSERT(!label || label->size >= word_count);
901*22dc650dSSadaf Ebrahimi 					SLJIT_ASSERT(!jump || jump->addr >= word_count);
902*22dc650dSSadaf Ebrahimi 					SLJIT_ASSERT(!const_ || const_->addr >= word_count);
903*22dc650dSSadaf Ebrahimi 
904*22dc650dSSadaf Ebrahimi 					if (next_min_addr == next_label_size) {
905*22dc650dSSadaf Ebrahimi 						label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
906*22dc650dSSadaf Ebrahimi 						label->size = (sljit_uw)(code_ptr - code);
907*22dc650dSSadaf Ebrahimi 						label = label->next;
908*22dc650dSSadaf Ebrahimi 						next_label_size = SLJIT_GET_NEXT_SIZE(label);
909*22dc650dSSadaf Ebrahimi 					}
910*22dc650dSSadaf Ebrahimi 
911*22dc650dSSadaf Ebrahimi 					/* These structures are ordered by their address. */
912*22dc650dSSadaf Ebrahimi 					if (next_min_addr == next_jump_addr) {
913*22dc650dSSadaf Ebrahimi 						if (!(jump->flags & JUMP_MOV_ADDR)) {
914*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
915*22dc650dSSadaf Ebrahimi 							if (detect_jump_type(jump, code_ptr, code, executable_offset))
916*22dc650dSSadaf Ebrahimi 								code_ptr--;
917*22dc650dSSadaf Ebrahimi 							jump->addr = (sljit_uw)code_ptr;
918*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_ARM_V6 */
919*22dc650dSSadaf Ebrahimi 							word_count += jump->flags >> JUMP_SIZE_SHIFT;
920*22dc650dSSadaf Ebrahimi 							jump->addr = (sljit_uw)code_ptr;
921*22dc650dSSadaf Ebrahimi 							if (!detect_jump_type(jump, code_ptr, code, executable_offset)) {
922*22dc650dSSadaf Ebrahimi 								code_ptr[2] = code_ptr[0];
923*22dc650dSSadaf Ebrahimi 								addr = ((code_ptr[0] & 0xf) << 12);
924*22dc650dSSadaf Ebrahimi 								code_ptr[0] = MOVW | addr;
925*22dc650dSSadaf Ebrahimi 								code_ptr[1] = MOVT | addr;
926*22dc650dSSadaf Ebrahimi 								code_ptr += 2;
927*22dc650dSSadaf Ebrahimi 							}
928*22dc650dSSadaf Ebrahimi 							SLJIT_ASSERT((sljit_uw)code_ptr - jump->addr <= (jump->flags >> JUMP_SIZE_SHIFT) * sizeof(sljit_ins));
929*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_ARM_V6 */
930*22dc650dSSadaf Ebrahimi 						} else {
931*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
932*22dc650dSSadaf Ebrahimi 							word_count += jump->flags >> JUMP_SIZE_SHIFT;
933*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_ARM_V7 */
934*22dc650dSSadaf Ebrahimi 							addr = (sljit_uw)code_ptr;
935*22dc650dSSadaf Ebrahimi 							code_ptr += mov_addr_get_length(jump, code_ptr, code, executable_offset);
936*22dc650dSSadaf Ebrahimi 							jump->addr = addr;
937*22dc650dSSadaf Ebrahimi 						}
938*22dc650dSSadaf Ebrahimi 						jump = jump->next;
939*22dc650dSSadaf Ebrahimi 						next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);
940*22dc650dSSadaf Ebrahimi 					} else if (next_min_addr == next_const_addr) {
941*22dc650dSSadaf Ebrahimi 						const_->addr = (sljit_uw)code_ptr;
942*22dc650dSSadaf Ebrahimi 						const_ = const_->next;
943*22dc650dSSadaf Ebrahimi 						next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);
944*22dc650dSSadaf Ebrahimi 					}
945*22dc650dSSadaf Ebrahimi 
946*22dc650dSSadaf Ebrahimi 					SLJIT_GET_NEXT_MIN();
947*22dc650dSSadaf Ebrahimi 				}
948*22dc650dSSadaf Ebrahimi 				code_ptr++;
949*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
950*22dc650dSSadaf Ebrahimi 			} else {
951*22dc650dSSadaf Ebrahimi 				/* Fortunately, no need to shift. */
952*22dc650dSSadaf Ebrahimi 				cpool_size = *buf_ptr++ & ~PUSH_POOL;
953*22dc650dSSadaf Ebrahimi 				SLJIT_ASSERT(cpool_size > 0);
954*22dc650dSSadaf Ebrahimi 				cpool_start_address = ALIGN_INSTRUCTION(code_ptr + 1);
955*22dc650dSSadaf Ebrahimi 				cpool_current_index = patch_pc_relative_loads(last_pc_patch, code_ptr, cpool_start_address, cpool_size);
956*22dc650dSSadaf Ebrahimi 				if (cpool_current_index > 0) {
957*22dc650dSSadaf Ebrahimi 					/* Unconditional branch. */
958*22dc650dSSadaf Ebrahimi 					*code_ptr = B | (((sljit_ins)(cpool_start_address - code_ptr) + cpool_current_index - 2) & ~PUSH_POOL);
959*22dc650dSSadaf Ebrahimi 					code_ptr = (sljit_ins*)(cpool_start_address + cpool_current_index);
960*22dc650dSSadaf Ebrahimi 				}
961*22dc650dSSadaf Ebrahimi 				cpool_skip_alignment = CONST_POOL_ALIGNMENT - 1;
962*22dc650dSSadaf Ebrahimi 				cpool_current_index = 0;
963*22dc650dSSadaf Ebrahimi 				last_pc_patch = code_ptr;
964*22dc650dSSadaf Ebrahimi 			}
965*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_ARM_V6 */
966*22dc650dSSadaf Ebrahimi 			word_count++;
967*22dc650dSSadaf Ebrahimi 		} while (buf_ptr < buf_end);
968*22dc650dSSadaf Ebrahimi 		buf = buf->next;
969*22dc650dSSadaf Ebrahimi 	} while (buf);
970*22dc650dSSadaf Ebrahimi 
971*22dc650dSSadaf Ebrahimi 	if (label && label->size == word_count) {
972*22dc650dSSadaf Ebrahimi 		label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
973*22dc650dSSadaf Ebrahimi 		label->size = (sljit_uw)(code_ptr - code);
974*22dc650dSSadaf Ebrahimi 		label = label->next;
975*22dc650dSSadaf Ebrahimi 	}
976*22dc650dSSadaf Ebrahimi 
977*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(!label);
978*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(!jump);
979*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(!const_);
980*22dc650dSSadaf Ebrahimi 
981*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
982*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(cpool_size == 0);
983*22dc650dSSadaf Ebrahimi 	if (compiler->cpool_fill > 0) {
984*22dc650dSSadaf Ebrahimi 		cpool_start_address = ALIGN_INSTRUCTION(code_ptr);
985*22dc650dSSadaf Ebrahimi 		cpool_current_index = patch_pc_relative_loads(last_pc_patch, code_ptr, cpool_start_address, compiler->cpool_fill);
986*22dc650dSSadaf Ebrahimi 		if (cpool_current_index > 0)
987*22dc650dSSadaf Ebrahimi 			code_ptr = (sljit_ins*)(cpool_start_address + cpool_current_index);
988*22dc650dSSadaf Ebrahimi 
989*22dc650dSSadaf Ebrahimi 		buf_ptr = compiler->cpool;
990*22dc650dSSadaf Ebrahimi 		buf_end = buf_ptr + compiler->cpool_fill;
991*22dc650dSSadaf Ebrahimi 		cpool_current_index = 0;
992*22dc650dSSadaf Ebrahimi 		while (buf_ptr < buf_end) {
993*22dc650dSSadaf Ebrahimi 			if (SLJIT_UNLIKELY(resolve_const_pool_index(compiler, &first_patch, cpool_current_index, cpool_start_address, buf_ptr))) {
994*22dc650dSSadaf Ebrahimi 				SLJIT_FREE_EXEC(code, exec_allocator_data);
995*22dc650dSSadaf Ebrahimi 				compiler->error = SLJIT_ERR_ALLOC_FAILED;
996*22dc650dSSadaf Ebrahimi 				return NULL;
997*22dc650dSSadaf Ebrahimi 			}
998*22dc650dSSadaf Ebrahimi 			buf_ptr++;
999*22dc650dSSadaf Ebrahimi 			cpool_current_index++;
1000*22dc650dSSadaf Ebrahimi 		}
1001*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(!first_patch);
1002*22dc650dSSadaf Ebrahimi 	}
1003*22dc650dSSadaf Ebrahimi #endif
1004*22dc650dSSadaf Ebrahimi 
1005*22dc650dSSadaf Ebrahimi 	jump = compiler->jumps;
1006*22dc650dSSadaf Ebrahimi 	while (jump) {
1007*22dc650dSSadaf Ebrahimi 		addr = (jump->flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;
1008*22dc650dSSadaf Ebrahimi 		buf_ptr = (sljit_ins*)jump->addr;
1009*22dc650dSSadaf Ebrahimi 
1010*22dc650dSSadaf Ebrahimi 		if (jump->flags & JUMP_MOV_ADDR) {
1011*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
1012*22dc650dSSadaf Ebrahimi 			SLJIT_ASSERT((buf_ptr[0] & (sljit_ins)0xffff0000) == 0xe59f0000);
1013*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_ARM_V6 */
1014*22dc650dSSadaf Ebrahimi 			SLJIT_ASSERT((buf_ptr[0] & ~(sljit_ins)0xf000) == 0);
1015*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_ARM_V6 */
1016*22dc650dSSadaf Ebrahimi 
1017*22dc650dSSadaf Ebrahimi 			if (jump->flags & PATCH_B) {
1018*22dc650dSSadaf Ebrahimi 				SLJIT_ASSERT((((sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr + 2, executable_offset)) & 0x3) == 0);
1019*22dc650dSSadaf Ebrahimi 				diff = ((sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr + 2, executable_offset)) >> 2;
1020*22dc650dSSadaf Ebrahimi 
1021*22dc650dSSadaf Ebrahimi 				SLJIT_ASSERT(diff <= 0xff && diff >= -0xff);
1022*22dc650dSSadaf Ebrahimi 
1023*22dc650dSSadaf Ebrahimi 				addr = ADD;
1024*22dc650dSSadaf Ebrahimi 				if (diff < 0) {
1025*22dc650dSSadaf Ebrahimi 					diff = -diff;
1026*22dc650dSSadaf Ebrahimi 					addr = SUB;
1027*22dc650dSSadaf Ebrahimi 				}
1028*22dc650dSSadaf Ebrahimi 
1029*22dc650dSSadaf Ebrahimi 				buf_ptr[0] = addr | (buf_ptr[0] & 0xf000) | RN(TMP_PC) | (1 << 25) | (0xf << 8) | (sljit_ins)(diff & 0xff);
1030*22dc650dSSadaf Ebrahimi 			} else {
1031*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
1032*22dc650dSSadaf Ebrahimi 				buf_ptr[((buf_ptr[0] & 0xfff) >> 2) + 2] = addr;
1033*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_ARM_V6 */
1034*22dc650dSSadaf Ebrahimi 				buf_ptr[1] = MOVT | buf_ptr[0] | ((addr >> 12) & 0xf0000) | ((addr >> 16) & 0xfff);
1035*22dc650dSSadaf Ebrahimi 				buf_ptr[0] = MOVW | buf_ptr[0] | ((addr << 4) & 0xf0000) | (addr & 0xfff);
1036*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_ARM_V6 */
1037*22dc650dSSadaf Ebrahimi 			}
1038*22dc650dSSadaf Ebrahimi 		} else if (jump->flags & PATCH_B) {
1039*22dc650dSSadaf Ebrahimi 			diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr + 2, executable_offset);
1040*22dc650dSSadaf Ebrahimi 			SLJIT_ASSERT(diff <= 0x01ffffff && diff >= -0x02000000);
1041*22dc650dSSadaf Ebrahimi 			*buf_ptr |= (diff >> 2) & 0x00ffffff;
1042*22dc650dSSadaf Ebrahimi 		} else {
1043*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
1044*22dc650dSSadaf Ebrahimi 			if (jump->flags & IS_BL)
1045*22dc650dSSadaf Ebrahimi 				buf_ptr--;
1046*22dc650dSSadaf Ebrahimi 
1047*22dc650dSSadaf Ebrahimi 			if (jump->flags & SLJIT_REWRITABLE_JUMP) {
1048*22dc650dSSadaf Ebrahimi 				jump->addr = (sljit_uw)code_ptr;
1049*22dc650dSSadaf Ebrahimi 				code_ptr[0] = (sljit_ins)buf_ptr;
1050*22dc650dSSadaf Ebrahimi 				code_ptr[1] = *buf_ptr;
1051*22dc650dSSadaf Ebrahimi 				set_jump_addr((sljit_uw)code_ptr, executable_offset, addr, 0);
1052*22dc650dSSadaf Ebrahimi 				code_ptr += 2;
1053*22dc650dSSadaf Ebrahimi 			} else {
1054*22dc650dSSadaf Ebrahimi 				if (*buf_ptr & (1 << 23))
1055*22dc650dSSadaf Ebrahimi 					buf_ptr += ((*buf_ptr & 0xfff) >> 2) + 2;
1056*22dc650dSSadaf Ebrahimi 				else
1057*22dc650dSSadaf Ebrahimi 					buf_ptr += 1;
1058*22dc650dSSadaf Ebrahimi 				*buf_ptr = addr;
1059*22dc650dSSadaf Ebrahimi 			}
1060*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_ARM_V6 */
1061*22dc650dSSadaf Ebrahimi 			set_jump_addr((sljit_uw)buf_ptr, executable_offset, addr, 0);
1062*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_ARM_V6 */
1063*22dc650dSSadaf Ebrahimi 		}
1064*22dc650dSSadaf Ebrahimi 
1065*22dc650dSSadaf Ebrahimi 		jump = jump->next;
1066*22dc650dSSadaf Ebrahimi 	}
1067*22dc650dSSadaf Ebrahimi 
1068*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
1069*22dc650dSSadaf Ebrahimi 	const_ = compiler->consts;
1070*22dc650dSSadaf Ebrahimi 	while (const_) {
1071*22dc650dSSadaf Ebrahimi 		buf_ptr = (sljit_ins*)const_->addr;
1072*22dc650dSSadaf Ebrahimi 		const_->addr = (sljit_uw)code_ptr;
1073*22dc650dSSadaf Ebrahimi 
1074*22dc650dSSadaf Ebrahimi 		code_ptr[0] = (sljit_ins)buf_ptr;
1075*22dc650dSSadaf Ebrahimi 		code_ptr[1] = *buf_ptr;
1076*22dc650dSSadaf Ebrahimi 		if (*buf_ptr & (1 << 23))
1077*22dc650dSSadaf Ebrahimi 			buf_ptr += ((*buf_ptr & 0xfff) >> 2) + 2;
1078*22dc650dSSadaf Ebrahimi 		else
1079*22dc650dSSadaf Ebrahimi 			buf_ptr += 1;
1080*22dc650dSSadaf Ebrahimi 		/* Set the value again (can be a simple constant). */
1081*22dc650dSSadaf Ebrahimi 		set_const_value((sljit_uw)code_ptr, executable_offset, *buf_ptr, 0);
1082*22dc650dSSadaf Ebrahimi 		code_ptr += 2;
1083*22dc650dSSadaf Ebrahimi 
1084*22dc650dSSadaf Ebrahimi 		const_ = const_->next;
1085*22dc650dSSadaf Ebrahimi 	}
1086*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_ARM_V6 */
1087*22dc650dSSadaf Ebrahimi 
1088*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(code_ptr - code <= (sljit_s32)compiler->size);
1089*22dc650dSSadaf Ebrahimi 
1090*22dc650dSSadaf Ebrahimi 	compiler->error = SLJIT_ERR_COMPILED;
1091*22dc650dSSadaf Ebrahimi 	compiler->executable_offset = executable_offset;
1092*22dc650dSSadaf Ebrahimi 	compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_uw);
1093*22dc650dSSadaf Ebrahimi 
1094*22dc650dSSadaf Ebrahimi 	code = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
1095*22dc650dSSadaf Ebrahimi 	code_ptr = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
1096*22dc650dSSadaf Ebrahimi 
1097*22dc650dSSadaf Ebrahimi 	SLJIT_CACHE_FLUSH(code, code_ptr);
1098*22dc650dSSadaf Ebrahimi 	SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);
1099*22dc650dSSadaf Ebrahimi 	return code;
1100*22dc650dSSadaf Ebrahimi }
1101*22dc650dSSadaf Ebrahimi 
sljit_has_cpu_feature(sljit_s32 feature_type)1102*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
1103*22dc650dSSadaf Ebrahimi {
1104*22dc650dSSadaf Ebrahimi 	switch (feature_type) {
1105*22dc650dSSadaf Ebrahimi 	case SLJIT_HAS_FPU:
1106*22dc650dSSadaf Ebrahimi 	case SLJIT_HAS_F64_AS_F32_PAIR:
1107*22dc650dSSadaf Ebrahimi #ifdef SLJIT_IS_FPU_AVAILABLE
1108*22dc650dSSadaf Ebrahimi 		return (SLJIT_IS_FPU_AVAILABLE) != 0;
1109*22dc650dSSadaf Ebrahimi #else
1110*22dc650dSSadaf Ebrahimi 		/* Available by default. */
1111*22dc650dSSadaf Ebrahimi 		return 1;
1112*22dc650dSSadaf Ebrahimi #endif /* SLJIT_IS_FPU_AVAILABLE */
1113*22dc650dSSadaf Ebrahimi 	case SLJIT_HAS_SIMD:
1114*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
1115*22dc650dSSadaf Ebrahimi 		return 0;
1116*22dc650dSSadaf Ebrahimi #else
1117*22dc650dSSadaf Ebrahimi #ifdef SLJIT_IS_FPU_AVAILABLE
1118*22dc650dSSadaf Ebrahimi 		return (SLJIT_IS_FPU_AVAILABLE) != 0;
1119*22dc650dSSadaf Ebrahimi #else
1120*22dc650dSSadaf Ebrahimi 		/* Available by default. */
1121*22dc650dSSadaf Ebrahimi 		return 1;
1122*22dc650dSSadaf Ebrahimi #endif /* SLJIT_IS_FPU_AVAILABLE */
1123*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_ARM_V6 */
1124*22dc650dSSadaf Ebrahimi 
1125*22dc650dSSadaf Ebrahimi 	case SLJIT_SIMD_REGS_ARE_PAIRS:
1126*22dc650dSSadaf Ebrahimi 	case SLJIT_HAS_CLZ:
1127*22dc650dSSadaf Ebrahimi 	case SLJIT_HAS_ROT:
1128*22dc650dSSadaf Ebrahimi 	case SLJIT_HAS_CMOV:
1129*22dc650dSSadaf Ebrahimi 	case SLJIT_HAS_REV:
1130*22dc650dSSadaf Ebrahimi 	case SLJIT_HAS_PREFETCH:
1131*22dc650dSSadaf Ebrahimi 	case SLJIT_HAS_COPY_F32:
1132*22dc650dSSadaf Ebrahimi 	case SLJIT_HAS_COPY_F64:
1133*22dc650dSSadaf Ebrahimi 	case SLJIT_HAS_ATOMIC:
1134*22dc650dSSadaf Ebrahimi 		return 1;
1135*22dc650dSSadaf Ebrahimi 
1136*22dc650dSSadaf Ebrahimi 	case SLJIT_HAS_CTZ:
1137*22dc650dSSadaf Ebrahimi #if defined(SLJIT_CONFIG_ARM_V6) && SLJIT_CONFIG_ARM_V6
1138*22dc650dSSadaf Ebrahimi 		return 2;
1139*22dc650dSSadaf Ebrahimi #else
1140*22dc650dSSadaf Ebrahimi 		return 1;
1141*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_ARM_V6 */
1142*22dc650dSSadaf Ebrahimi 
1143*22dc650dSSadaf Ebrahimi 	default:
1144*22dc650dSSadaf Ebrahimi 		return 0;
1145*22dc650dSSadaf Ebrahimi 	}
1146*22dc650dSSadaf Ebrahimi }
1147*22dc650dSSadaf Ebrahimi 
1148*22dc650dSSadaf Ebrahimi /* --------------------------------------------------------------------- */
1149*22dc650dSSadaf Ebrahimi /*  Entry, exit                                                          */
1150*22dc650dSSadaf Ebrahimi /* --------------------------------------------------------------------- */
1151*22dc650dSSadaf Ebrahimi 
1152*22dc650dSSadaf Ebrahimi /* Creates an index in data_transfer_insts array. */
1153*22dc650dSSadaf Ebrahimi #define WORD_SIZE	0x00
1154*22dc650dSSadaf Ebrahimi #define BYTE_SIZE	0x01
1155*22dc650dSSadaf Ebrahimi #define HALF_SIZE	0x02
1156*22dc650dSSadaf Ebrahimi #define PRELOAD		0x03
1157*22dc650dSSadaf Ebrahimi #define SIGNED		0x04
1158*22dc650dSSadaf Ebrahimi #define LOAD_DATA	0x08
1159*22dc650dSSadaf Ebrahimi 
1160*22dc650dSSadaf Ebrahimi /* Flag bits for emit_op. */
1161*22dc650dSSadaf Ebrahimi #define ALLOW_IMM		0x10
1162*22dc650dSSadaf Ebrahimi #define ALLOW_INV_IMM		0x20
1163*22dc650dSSadaf Ebrahimi #define ALLOW_ANY_IMM		(ALLOW_IMM | ALLOW_INV_IMM)
1164*22dc650dSSadaf Ebrahimi #define ALLOW_NEG_IMM		0x40
1165*22dc650dSSadaf Ebrahimi #define ALLOW_DOUBLE_IMM	0x80
1166*22dc650dSSadaf Ebrahimi 
1167*22dc650dSSadaf Ebrahimi /* s/l - store/load (1 bit)
1168*22dc650dSSadaf Ebrahimi    u/s - signed/unsigned (1 bit)
1169*22dc650dSSadaf Ebrahimi    w/b/h/N - word/byte/half/NOT allowed (2 bit)
1170*22dc650dSSadaf Ebrahimi    Storing signed and unsigned values are the same operations. */
1171*22dc650dSSadaf Ebrahimi 
1172*22dc650dSSadaf Ebrahimi static const sljit_ins data_transfer_insts[16] = {
1173*22dc650dSSadaf Ebrahimi /* s u w */ 0xe5000000 /* str */,
1174*22dc650dSSadaf Ebrahimi /* s u b */ 0xe5400000 /* strb */,
1175*22dc650dSSadaf Ebrahimi /* s u h */ 0xe10000b0 /* strh */,
1176*22dc650dSSadaf Ebrahimi /* s u N */ 0x00000000 /* not allowed */,
1177*22dc650dSSadaf Ebrahimi /* s s w */ 0xe5000000 /* str */,
1178*22dc650dSSadaf Ebrahimi /* s s b */ 0xe5400000 /* strb */,
1179*22dc650dSSadaf Ebrahimi /* s s h */ 0xe10000b0 /* strh */,
1180*22dc650dSSadaf Ebrahimi /* s s N */ 0x00000000 /* not allowed */,
1181*22dc650dSSadaf Ebrahimi 
1182*22dc650dSSadaf Ebrahimi /* l u w */ 0xe5100000 /* ldr */,
1183*22dc650dSSadaf Ebrahimi /* l u b */ 0xe5500000 /* ldrb */,
1184*22dc650dSSadaf Ebrahimi /* l u h */ 0xe11000b0 /* ldrh */,
1185*22dc650dSSadaf Ebrahimi /* l u p */ 0xf5500000 /* preload */,
1186*22dc650dSSadaf Ebrahimi /* l s w */ 0xe5100000 /* ldr */,
1187*22dc650dSSadaf Ebrahimi /* l s b */ 0xe11000d0 /* ldrsb */,
1188*22dc650dSSadaf Ebrahimi /* l s h */ 0xe11000f0 /* ldrsh */,
1189*22dc650dSSadaf Ebrahimi /* l s N */ 0x00000000 /* not allowed */,
1190*22dc650dSSadaf Ebrahimi };
1191*22dc650dSSadaf Ebrahimi 
1192*22dc650dSSadaf Ebrahimi #define EMIT_DATA_TRANSFER(type, add, target_reg, base_reg, arg) \
1193*22dc650dSSadaf Ebrahimi 	(data_transfer_insts[(type) & 0xf] | ((add) << 23) | RD(target_reg) | RN(base_reg) | (sljit_ins)(arg))
1194*22dc650dSSadaf Ebrahimi 
1195*22dc650dSSadaf Ebrahimi /* Normal ldr/str instruction.
1196*22dc650dSSadaf Ebrahimi    Type2: ldrsb, ldrh, ldrsh */
1197*22dc650dSSadaf Ebrahimi #define IS_TYPE1_TRANSFER(type) \
1198*22dc650dSSadaf Ebrahimi 	(data_transfer_insts[(type) & 0xf] & 0x04000000)
1199*22dc650dSSadaf Ebrahimi #define TYPE2_TRANSFER_IMM(imm) \
1200*22dc650dSSadaf Ebrahimi 	(((imm) & 0xf) | (((imm) & 0xf0) << 4) | (1 << 22))
1201*22dc650dSSadaf Ebrahimi 
1202*22dc650dSSadaf Ebrahimi #define EMIT_FPU_OPERATION(opcode, mode, dst, src1, src2) \
1203*22dc650dSSadaf Ebrahimi 	((sljit_ins)(opcode) | (sljit_ins)(mode) | VD(dst) | VM(src1) | VN(src2))
1204*22dc650dSSadaf Ebrahimi 
1205*22dc650dSSadaf Ebrahimi /* Flags for emit_op: */
1206*22dc650dSSadaf Ebrahimi   /* Arguments are swapped. */
1207*22dc650dSSadaf Ebrahimi #define ARGS_SWAPPED	0x01
1208*22dc650dSSadaf Ebrahimi   /* Inverted immediate. */
1209*22dc650dSSadaf Ebrahimi #define INV_IMM		0x02
1210*22dc650dSSadaf Ebrahimi   /* Source and destination is register. */
1211*22dc650dSSadaf Ebrahimi #define REGISTER_OP	0x04
1212*22dc650dSSadaf Ebrahimi   /* Unused return value. */
1213*22dc650dSSadaf Ebrahimi #define UNUSED_RETURN	0x08
1214*22dc650dSSadaf Ebrahimi /* SET_FLAGS must be (1 << 20) as it is also the value of S bit (can be used for optimization). */
1215*22dc650dSSadaf Ebrahimi #define SET_FLAGS	(1 << 20)
1216*22dc650dSSadaf Ebrahimi /* dst: reg
1217*22dc650dSSadaf Ebrahimi    src1: reg
1218*22dc650dSSadaf Ebrahimi    src2: reg or imm (if allowed)
1219*22dc650dSSadaf Ebrahimi    SRC2_IMM must be (1 << 25) as it is also the value of I bit (can be used for optimization). */
1220*22dc650dSSadaf Ebrahimi #define SRC2_IMM	(1 << 25)
1221*22dc650dSSadaf Ebrahimi 
1222*22dc650dSSadaf Ebrahimi static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 inp_flags,
1223*22dc650dSSadaf Ebrahimi 	sljit_s32 dst, sljit_sw dstw,
1224*22dc650dSSadaf Ebrahimi 	sljit_s32 src1, sljit_sw src1w,
1225*22dc650dSSadaf Ebrahimi 	sljit_s32 src2, sljit_sw src2w);
1226*22dc650dSSadaf Ebrahimi 
sljit_emit_enter(struct sljit_compiler * compiler,sljit_s32 options,sljit_s32 arg_types,sljit_s32 scratches,sljit_s32 saveds,sljit_s32 fscratches,sljit_s32 fsaveds,sljit_s32 local_size)1227*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
1228*22dc650dSSadaf Ebrahimi 	sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
1229*22dc650dSSadaf Ebrahimi 	sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
1230*22dc650dSSadaf Ebrahimi {
1231*22dc650dSSadaf Ebrahimi 	sljit_uw imm, offset;
1232*22dc650dSSadaf Ebrahimi 	sljit_s32 i, tmp, size, word_arg_count;
1233*22dc650dSSadaf Ebrahimi 	sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options);
1234*22dc650dSSadaf Ebrahimi #ifdef __SOFTFP__
1235*22dc650dSSadaf Ebrahimi 	sljit_u32 float_arg_count;
1236*22dc650dSSadaf Ebrahimi #else
1237*22dc650dSSadaf Ebrahimi 	sljit_u32 old_offset, f32_offset;
1238*22dc650dSSadaf Ebrahimi 	sljit_u32 remap[3];
1239*22dc650dSSadaf Ebrahimi 	sljit_u32 *remap_ptr = remap;
1240*22dc650dSSadaf Ebrahimi #endif
1241*22dc650dSSadaf Ebrahimi 
1242*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
1243*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
1244*22dc650dSSadaf Ebrahimi 	set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
1245*22dc650dSSadaf Ebrahimi 
1246*22dc650dSSadaf Ebrahimi 	imm = 0;
1247*22dc650dSSadaf Ebrahimi 
1248*22dc650dSSadaf Ebrahimi 	tmp = SLJIT_S0 - saveds;
1249*22dc650dSSadaf Ebrahimi 	for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--)
1250*22dc650dSSadaf Ebrahimi 		imm |= (sljit_uw)1 << reg_map[i];
1251*22dc650dSSadaf Ebrahimi 
1252*22dc650dSSadaf Ebrahimi 	for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--)
1253*22dc650dSSadaf Ebrahimi 		imm |= (sljit_uw)1 << reg_map[i];
1254*22dc650dSSadaf Ebrahimi 
1255*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(reg_map[TMP_REG2] == 14);
1256*22dc650dSSadaf Ebrahimi 
1257*22dc650dSSadaf Ebrahimi 	/* Push saved and temporary registers
1258*22dc650dSSadaf Ebrahimi 	   multiple registers: stmdb sp!, {..., lr}
1259*22dc650dSSadaf Ebrahimi 	   single register: str reg, [sp, #-4]! */
1260*22dc650dSSadaf Ebrahimi 	if (imm != 0)
1261*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, PUSH | (1 << 14) | imm));
1262*22dc650dSSadaf Ebrahimi 	else
1263*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, 0xe52d0004 | RD(TMP_REG2)));
1264*22dc650dSSadaf Ebrahimi 
1265*22dc650dSSadaf Ebrahimi 	/* Stack must be aligned to 8 bytes: */
1266*22dc650dSSadaf Ebrahimi 	size = GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 1);
1267*22dc650dSSadaf Ebrahimi 
1268*22dc650dSSadaf Ebrahimi 	if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
1269*22dc650dSSadaf Ebrahimi 		if ((size & SSIZE_OF(sw)) != 0) {
1270*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, SUB | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | sizeof(sljit_sw)));
1271*22dc650dSSadaf Ebrahimi 			size += SSIZE_OF(sw);
1272*22dc650dSSadaf Ebrahimi 		}
1273*22dc650dSSadaf Ebrahimi 
1274*22dc650dSSadaf Ebrahimi 		if (fsaveds + fscratches >= SLJIT_NUMBER_OF_FLOAT_REGISTERS) {
1275*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, VPUSH | VD(SLJIT_FS0) | ((sljit_ins)SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS << 1)));
1276*22dc650dSSadaf Ebrahimi 		} else {
1277*22dc650dSSadaf Ebrahimi 			if (fsaveds > 0)
1278*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, VPUSH | VD(SLJIT_FS0) | ((sljit_ins)fsaveds << 1)));
1279*22dc650dSSadaf Ebrahimi 			if (fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG)
1280*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, VPUSH | VD(fscratches) | ((sljit_ins)(fscratches - (SLJIT_FIRST_SAVED_FLOAT_REG - 1)) << 1)));
1281*22dc650dSSadaf Ebrahimi 		}
1282*22dc650dSSadaf Ebrahimi 	}
1283*22dc650dSSadaf Ebrahimi 
1284*22dc650dSSadaf Ebrahimi 	local_size = ((size + local_size + 0x7) & ~0x7) - size;
1285*22dc650dSSadaf Ebrahimi 	compiler->local_size = local_size;
1286*22dc650dSSadaf Ebrahimi 
1287*22dc650dSSadaf Ebrahimi 	if (options & SLJIT_ENTER_REG_ARG)
1288*22dc650dSSadaf Ebrahimi 		arg_types = 0;
1289*22dc650dSSadaf Ebrahimi 
1290*22dc650dSSadaf Ebrahimi 	arg_types >>= SLJIT_ARG_SHIFT;
1291*22dc650dSSadaf Ebrahimi 	word_arg_count = 0;
1292*22dc650dSSadaf Ebrahimi 	saved_arg_count = 0;
1293*22dc650dSSadaf Ebrahimi #ifdef __SOFTFP__
1294*22dc650dSSadaf Ebrahimi 	SLJIT_COMPILE_ASSERT(SLJIT_FR0 == 1, float_register_index_start);
1295*22dc650dSSadaf Ebrahimi 
1296*22dc650dSSadaf Ebrahimi 	offset = 0;
1297*22dc650dSSadaf Ebrahimi 	float_arg_count = 0;
1298*22dc650dSSadaf Ebrahimi 
1299*22dc650dSSadaf Ebrahimi 	while (arg_types) {
1300*22dc650dSSadaf Ebrahimi 		switch (arg_types & SLJIT_ARG_MASK) {
1301*22dc650dSSadaf Ebrahimi 		case SLJIT_ARG_TYPE_F64:
1302*22dc650dSSadaf Ebrahimi 			if (offset & 0x7)
1303*22dc650dSSadaf Ebrahimi 				offset += sizeof(sljit_sw);
1304*22dc650dSSadaf Ebrahimi 
1305*22dc650dSSadaf Ebrahimi 			if (offset < 4 * sizeof(sljit_sw))
1306*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, VMOV2 | (offset << 10) | ((offset + sizeof(sljit_sw)) << 14) | float_arg_count));
1307*22dc650dSSadaf Ebrahimi 			else
1308*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, VLDR_F32 | 0x800100 | RN(SLJIT_SP)
1309*22dc650dSSadaf Ebrahimi 						| (float_arg_count << 12) | ((offset + (sljit_ins)size - 4 * sizeof(sljit_sw)) >> 2)));
1310*22dc650dSSadaf Ebrahimi 			float_arg_count++;
1311*22dc650dSSadaf Ebrahimi 			offset += sizeof(sljit_f64) - sizeof(sljit_sw);
1312*22dc650dSSadaf Ebrahimi 			break;
1313*22dc650dSSadaf Ebrahimi 		case SLJIT_ARG_TYPE_F32:
1314*22dc650dSSadaf Ebrahimi 			if (offset < 4 * sizeof(sljit_sw))
1315*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, VMOV | (float_arg_count << 16) | (offset << 10)));
1316*22dc650dSSadaf Ebrahimi 			else
1317*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, VLDR_F32 | 0x800000 | RN(SLJIT_SP)
1318*22dc650dSSadaf Ebrahimi 						| (float_arg_count << 12) | ((offset + (sljit_ins)size - 4 * sizeof(sljit_sw)) >> 2)));
1319*22dc650dSSadaf Ebrahimi 			float_arg_count++;
1320*22dc650dSSadaf Ebrahimi 			break;
1321*22dc650dSSadaf Ebrahimi 		default:
1322*22dc650dSSadaf Ebrahimi 			word_arg_count++;
1323*22dc650dSSadaf Ebrahimi 
1324*22dc650dSSadaf Ebrahimi 			if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
1325*22dc650dSSadaf Ebrahimi 				tmp = SLJIT_S0 - saved_arg_count;
1326*22dc650dSSadaf Ebrahimi 				saved_arg_count++;
1327*22dc650dSSadaf Ebrahimi 			} else if (word_arg_count - 1 != (sljit_s32)(offset >> 2))
1328*22dc650dSSadaf Ebrahimi 				tmp = word_arg_count;
1329*22dc650dSSadaf Ebrahimi 			else
1330*22dc650dSSadaf Ebrahimi 				break;
1331*22dc650dSSadaf Ebrahimi 
1332*22dc650dSSadaf Ebrahimi 			if (offset < 4 * sizeof(sljit_sw))
1333*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, MOV | RD(tmp) | (offset >> 2)));
1334*22dc650dSSadaf Ebrahimi 			else
1335*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, LDR | 0x800000 | RN(SLJIT_SP) | RD(tmp) | (offset + (sljit_ins)size - 4 * sizeof(sljit_sw))));
1336*22dc650dSSadaf Ebrahimi 			break;
1337*22dc650dSSadaf Ebrahimi 		}
1338*22dc650dSSadaf Ebrahimi 
1339*22dc650dSSadaf Ebrahimi 		offset += sizeof(sljit_sw);
1340*22dc650dSSadaf Ebrahimi 		arg_types >>= SLJIT_ARG_SHIFT;
1341*22dc650dSSadaf Ebrahimi 	}
1342*22dc650dSSadaf Ebrahimi 
1343*22dc650dSSadaf Ebrahimi 	compiler->args_size = offset;
1344*22dc650dSSadaf Ebrahimi #else
1345*22dc650dSSadaf Ebrahimi 	offset = SLJIT_FR0;
1346*22dc650dSSadaf Ebrahimi 	old_offset = SLJIT_FR0;
1347*22dc650dSSadaf Ebrahimi 	f32_offset = 0;
1348*22dc650dSSadaf Ebrahimi 
1349*22dc650dSSadaf Ebrahimi 	while (arg_types) {
1350*22dc650dSSadaf Ebrahimi 		switch (arg_types & SLJIT_ARG_MASK) {
1351*22dc650dSSadaf Ebrahimi 		case SLJIT_ARG_TYPE_F64:
1352*22dc650dSSadaf Ebrahimi 			if (offset != old_offset)
1353*22dc650dSSadaf Ebrahimi 				*remap_ptr++ = EMIT_FPU_OPERATION(VMOV_F32, SLJIT_32, offset, old_offset, 0);
1354*22dc650dSSadaf Ebrahimi 			old_offset++;
1355*22dc650dSSadaf Ebrahimi 			offset++;
1356*22dc650dSSadaf Ebrahimi 			break;
1357*22dc650dSSadaf Ebrahimi 		case SLJIT_ARG_TYPE_F32:
1358*22dc650dSSadaf Ebrahimi 			if (f32_offset != 0) {
1359*22dc650dSSadaf Ebrahimi 				*remap_ptr++ = EMIT_FPU_OPERATION(VMOV_F32, 0x20, offset, f32_offset, 0);
1360*22dc650dSSadaf Ebrahimi 				f32_offset = 0;
1361*22dc650dSSadaf Ebrahimi 			} else {
1362*22dc650dSSadaf Ebrahimi 				if (offset != old_offset)
1363*22dc650dSSadaf Ebrahimi 					*remap_ptr++ = EMIT_FPU_OPERATION(VMOV_F32, 0, offset, old_offset, 0);
1364*22dc650dSSadaf Ebrahimi 				f32_offset = old_offset;
1365*22dc650dSSadaf Ebrahimi 				old_offset++;
1366*22dc650dSSadaf Ebrahimi 			}
1367*22dc650dSSadaf Ebrahimi 			offset++;
1368*22dc650dSSadaf Ebrahimi 			break;
1369*22dc650dSSadaf Ebrahimi 		default:
1370*22dc650dSSadaf Ebrahimi 			if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
1371*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, MOV | RD(SLJIT_S0 - saved_arg_count) | RM(SLJIT_R0 + word_arg_count)));
1372*22dc650dSSadaf Ebrahimi 				saved_arg_count++;
1373*22dc650dSSadaf Ebrahimi 			}
1374*22dc650dSSadaf Ebrahimi 
1375*22dc650dSSadaf Ebrahimi 			word_arg_count++;
1376*22dc650dSSadaf Ebrahimi 			break;
1377*22dc650dSSadaf Ebrahimi 		}
1378*22dc650dSSadaf Ebrahimi 		arg_types >>= SLJIT_ARG_SHIFT;
1379*22dc650dSSadaf Ebrahimi 	}
1380*22dc650dSSadaf Ebrahimi 
1381*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT((sljit_uw)(remap_ptr - remap) <= sizeof(remap));
1382*22dc650dSSadaf Ebrahimi 
1383*22dc650dSSadaf Ebrahimi 	while (remap_ptr > remap)
1384*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, *(--remap_ptr)));
1385*22dc650dSSadaf Ebrahimi #endif
1386*22dc650dSSadaf Ebrahimi 
1387*22dc650dSSadaf Ebrahimi 	if (local_size > 0)
1388*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op(compiler, SLJIT_SUB, ALLOW_IMM | ALLOW_DOUBLE_IMM, SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, local_size));
1389*22dc650dSSadaf Ebrahimi 
1390*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
1391*22dc650dSSadaf Ebrahimi }
1392*22dc650dSSadaf Ebrahimi 
sljit_set_context(struct sljit_compiler * compiler,sljit_s32 options,sljit_s32 arg_types,sljit_s32 scratches,sljit_s32 saveds,sljit_s32 fscratches,sljit_s32 fsaveds,sljit_s32 local_size)1393*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
1394*22dc650dSSadaf Ebrahimi 	sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
1395*22dc650dSSadaf Ebrahimi 	sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
1396*22dc650dSSadaf Ebrahimi {
1397*22dc650dSSadaf Ebrahimi 	sljit_s32 size;
1398*22dc650dSSadaf Ebrahimi 
1399*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
1400*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
1401*22dc650dSSadaf Ebrahimi 	set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
1402*22dc650dSSadaf Ebrahimi 
1403*22dc650dSSadaf Ebrahimi 	size = GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1);
1404*22dc650dSSadaf Ebrahimi 
1405*22dc650dSSadaf Ebrahimi 	/* Doubles are saved, so alignment is unaffected. */
1406*22dc650dSSadaf Ebrahimi 	if ((size & SSIZE_OF(sw)) != 0 && (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG))
1407*22dc650dSSadaf Ebrahimi 		size += SSIZE_OF(sw);
1408*22dc650dSSadaf Ebrahimi 
1409*22dc650dSSadaf Ebrahimi 	compiler->local_size = ((size + local_size + 0x7) & ~0x7) - size;
1410*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
1411*22dc650dSSadaf Ebrahimi }
1412*22dc650dSSadaf Ebrahimi 
emit_add_sp(struct sljit_compiler * compiler,sljit_uw imm)1413*22dc650dSSadaf Ebrahimi static sljit_s32 emit_add_sp(struct sljit_compiler *compiler, sljit_uw imm)
1414*22dc650dSSadaf Ebrahimi {
1415*22dc650dSSadaf Ebrahimi 	sljit_uw imm2 = get_imm(imm);
1416*22dc650dSSadaf Ebrahimi 
1417*22dc650dSSadaf Ebrahimi 	if (imm2 == 0)
1418*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, SLJIT_ADD, ALLOW_IMM | ALLOW_DOUBLE_IMM, SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, (sljit_sw)imm);
1419*22dc650dSSadaf Ebrahimi 
1420*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | imm2);
1421*22dc650dSSadaf Ebrahimi }
1422*22dc650dSSadaf Ebrahimi 
emit_stack_frame_release(struct sljit_compiler * compiler,sljit_s32 frame_size)1423*22dc650dSSadaf Ebrahimi static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size)
1424*22dc650dSSadaf Ebrahimi {
1425*22dc650dSSadaf Ebrahimi 	sljit_s32 local_size, fscratches, fsaveds, i, tmp;
1426*22dc650dSSadaf Ebrahimi 	sljit_s32 restored_reg = 0;
1427*22dc650dSSadaf Ebrahimi 	sljit_s32 lr_dst = TMP_PC;
1428*22dc650dSSadaf Ebrahimi 	sljit_uw reg_list = 0;
1429*22dc650dSSadaf Ebrahimi 
1430*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(reg_map[TMP_REG2] == 14 && frame_size <= 128);
1431*22dc650dSSadaf Ebrahimi 
1432*22dc650dSSadaf Ebrahimi 	local_size = compiler->local_size;
1433*22dc650dSSadaf Ebrahimi 	fscratches = compiler->fscratches;
1434*22dc650dSSadaf Ebrahimi 	fsaveds = compiler->fsaveds;
1435*22dc650dSSadaf Ebrahimi 
1436*22dc650dSSadaf Ebrahimi 	if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
1437*22dc650dSSadaf Ebrahimi 		if (local_size > 0)
1438*22dc650dSSadaf Ebrahimi 			FAIL_IF(emit_add_sp(compiler, (sljit_uw)local_size));
1439*22dc650dSSadaf Ebrahimi 
1440*22dc650dSSadaf Ebrahimi 		if (fsaveds + fscratches >= SLJIT_NUMBER_OF_FLOAT_REGISTERS) {
1441*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, VPOP | VD(SLJIT_FS0) | ((sljit_ins)SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS << 1)));
1442*22dc650dSSadaf Ebrahimi 		} else {
1443*22dc650dSSadaf Ebrahimi 			if (fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG)
1444*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, VPOP | VD(fscratches) | ((sljit_ins)(fscratches - (SLJIT_FIRST_SAVED_FLOAT_REG - 1)) << 1)));
1445*22dc650dSSadaf Ebrahimi 			if (fsaveds > 0)
1446*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, VPOP | VD(SLJIT_FS0) | ((sljit_ins)fsaveds << 1)));
1447*22dc650dSSadaf Ebrahimi 		}
1448*22dc650dSSadaf Ebrahimi 
1449*22dc650dSSadaf Ebrahimi 		local_size = GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1) & 0x7;
1450*22dc650dSSadaf Ebrahimi 	}
1451*22dc650dSSadaf Ebrahimi 
1452*22dc650dSSadaf Ebrahimi 	if (frame_size < 0) {
1453*22dc650dSSadaf Ebrahimi 		lr_dst = TMP_REG2;
1454*22dc650dSSadaf Ebrahimi 		frame_size = 0;
1455*22dc650dSSadaf Ebrahimi 	} else if (frame_size > 0) {
1456*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(frame_size == 1 || (frame_size & 0x7) == 0);
1457*22dc650dSSadaf Ebrahimi 		lr_dst = 0;
1458*22dc650dSSadaf Ebrahimi 		frame_size &= ~0x7;
1459*22dc650dSSadaf Ebrahimi 	}
1460*22dc650dSSadaf Ebrahimi 
1461*22dc650dSSadaf Ebrahimi 	if (lr_dst != 0)
1462*22dc650dSSadaf Ebrahimi 		reg_list |= (sljit_uw)1 << reg_map[lr_dst];
1463*22dc650dSSadaf Ebrahimi 
1464*22dc650dSSadaf Ebrahimi 	tmp = SLJIT_S0 - compiler->saveds;
1465*22dc650dSSadaf Ebrahimi 	i = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options);
1466*22dc650dSSadaf Ebrahimi 	if (tmp < i) {
1467*22dc650dSSadaf Ebrahimi 		restored_reg = i;
1468*22dc650dSSadaf Ebrahimi 		do {
1469*22dc650dSSadaf Ebrahimi 			reg_list |= (sljit_uw)1 << reg_map[i];
1470*22dc650dSSadaf Ebrahimi 		} while (--i > tmp);
1471*22dc650dSSadaf Ebrahimi 	}
1472*22dc650dSSadaf Ebrahimi 
1473*22dc650dSSadaf Ebrahimi 	i = compiler->scratches;
1474*22dc650dSSadaf Ebrahimi 	if (i >= SLJIT_FIRST_SAVED_REG) {
1475*22dc650dSSadaf Ebrahimi 		restored_reg = i;
1476*22dc650dSSadaf Ebrahimi 		do {
1477*22dc650dSSadaf Ebrahimi 			reg_list |= (sljit_uw)1 << reg_map[i];
1478*22dc650dSSadaf Ebrahimi 		} while (--i >= SLJIT_FIRST_SAVED_REG);
1479*22dc650dSSadaf Ebrahimi 	}
1480*22dc650dSSadaf Ebrahimi 
1481*22dc650dSSadaf Ebrahimi 	if (lr_dst == TMP_REG2 && reg_list == 0) {
1482*22dc650dSSadaf Ebrahimi 		restored_reg = TMP_REG2;
1483*22dc650dSSadaf Ebrahimi 		lr_dst = 0;
1484*22dc650dSSadaf Ebrahimi 	}
1485*22dc650dSSadaf Ebrahimi 
1486*22dc650dSSadaf Ebrahimi 	if (lr_dst == 0 && (reg_list & (reg_list - 1)) == 0) {
1487*22dc650dSSadaf Ebrahimi 		/* The local_size does not include the saved registers. */
1488*22dc650dSSadaf Ebrahimi 		tmp = 0;
1489*22dc650dSSadaf Ebrahimi 		if (reg_list != 0) {
1490*22dc650dSSadaf Ebrahimi 			tmp = 2;
1491*22dc650dSSadaf Ebrahimi 			if (local_size <= 0xfff) {
1492*22dc650dSSadaf Ebrahimi 				if (local_size == 0) {
1493*22dc650dSSadaf Ebrahimi 					SLJIT_ASSERT(restored_reg != TMP_REG2);
1494*22dc650dSSadaf Ebrahimi 					if (frame_size == 0)
1495*22dc650dSSadaf Ebrahimi 						return push_inst(compiler, LDR_POST | RN(SLJIT_SP) | RD(restored_reg) | 0x800008);
1496*22dc650dSSadaf Ebrahimi 					if (frame_size > 2 * SSIZE_OF(sw))
1497*22dc650dSSadaf Ebrahimi 						return push_inst(compiler, LDR_POST | RN(SLJIT_SP) | RD(restored_reg) | (sljit_ins)(frame_size - (2 * SSIZE_OF(sw))));
1498*22dc650dSSadaf Ebrahimi 				}
1499*22dc650dSSadaf Ebrahimi 
1500*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, LDR | 0x800000 | RN(SLJIT_SP) | RD(restored_reg) | (sljit_ins)local_size));
1501*22dc650dSSadaf Ebrahimi 				tmp = 1;
1502*22dc650dSSadaf Ebrahimi 			} else if (frame_size == 0) {
1503*22dc650dSSadaf Ebrahimi 				frame_size = (restored_reg == TMP_REG2) ? SSIZE_OF(sw) : 2 * SSIZE_OF(sw);
1504*22dc650dSSadaf Ebrahimi 				tmp = 3;
1505*22dc650dSSadaf Ebrahimi 			}
1506*22dc650dSSadaf Ebrahimi 
1507*22dc650dSSadaf Ebrahimi 			/* Place for the saved register. */
1508*22dc650dSSadaf Ebrahimi 			if (restored_reg != TMP_REG2)
1509*22dc650dSSadaf Ebrahimi 				local_size += SSIZE_OF(sw);
1510*22dc650dSSadaf Ebrahimi 		}
1511*22dc650dSSadaf Ebrahimi 
1512*22dc650dSSadaf Ebrahimi 		/* Place for the lr register. */
1513*22dc650dSSadaf Ebrahimi 		local_size += SSIZE_OF(sw);
1514*22dc650dSSadaf Ebrahimi 
1515*22dc650dSSadaf Ebrahimi 		if (frame_size > local_size)
1516*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, SUB | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 25) | (sljit_ins)(frame_size - local_size)));
1517*22dc650dSSadaf Ebrahimi 		else if (frame_size < local_size)
1518*22dc650dSSadaf Ebrahimi 			FAIL_IF(emit_add_sp(compiler, (sljit_uw)(local_size - frame_size)));
1519*22dc650dSSadaf Ebrahimi 
1520*22dc650dSSadaf Ebrahimi 		if (tmp <= 1)
1521*22dc650dSSadaf Ebrahimi 			return SLJIT_SUCCESS;
1522*22dc650dSSadaf Ebrahimi 
1523*22dc650dSSadaf Ebrahimi 		if (tmp == 2) {
1524*22dc650dSSadaf Ebrahimi 			frame_size -= SSIZE_OF(sw);
1525*22dc650dSSadaf Ebrahimi 			if (restored_reg != TMP_REG2)
1526*22dc650dSSadaf Ebrahimi 				frame_size -= SSIZE_OF(sw);
1527*22dc650dSSadaf Ebrahimi 
1528*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, LDR | 0x800000 | RN(SLJIT_SP) | RD(restored_reg) | (sljit_ins)frame_size);
1529*22dc650dSSadaf Ebrahimi 		}
1530*22dc650dSSadaf Ebrahimi 
1531*22dc650dSSadaf Ebrahimi 		tmp = (restored_reg == TMP_REG2) ? 0x800004 : 0x800008;
1532*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, LDR_POST | RN(SLJIT_SP) | RD(restored_reg) | (sljit_ins)tmp);
1533*22dc650dSSadaf Ebrahimi 	}
1534*22dc650dSSadaf Ebrahimi 
1535*22dc650dSSadaf Ebrahimi 	if (local_size > 0)
1536*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_add_sp(compiler, (sljit_uw)local_size));
1537*22dc650dSSadaf Ebrahimi 
1538*22dc650dSSadaf Ebrahimi 	/* Pop saved and temporary registers
1539*22dc650dSSadaf Ebrahimi 	   multiple registers: ldmia sp!, {...}
1540*22dc650dSSadaf Ebrahimi 	   single register: ldr reg, [sp], #4 */
1541*22dc650dSSadaf Ebrahimi 	if ((reg_list & (reg_list - 1)) == 0) {
1542*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(lr_dst != 0);
1543*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(reg_list == (sljit_uw)1 << reg_map[lr_dst]);
1544*22dc650dSSadaf Ebrahimi 
1545*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, LDR_POST | RN(SLJIT_SP) | RD(lr_dst) | 0x800004);
1546*22dc650dSSadaf Ebrahimi 	}
1547*22dc650dSSadaf Ebrahimi 
1548*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, POP | reg_list));
1549*22dc650dSSadaf Ebrahimi 
1550*22dc650dSSadaf Ebrahimi 	if (frame_size > 0)
1551*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, SUB | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 25) | ((sljit_ins)frame_size - sizeof(sljit_sw)));
1552*22dc650dSSadaf Ebrahimi 
1553*22dc650dSSadaf Ebrahimi 	if (lr_dst != 0)
1554*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
1555*22dc650dSSadaf Ebrahimi 
1556*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 25) | sizeof(sljit_sw));
1557*22dc650dSSadaf Ebrahimi }
1558*22dc650dSSadaf Ebrahimi 
sljit_emit_return_void(struct sljit_compiler * compiler)1559*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
1560*22dc650dSSadaf Ebrahimi {
1561*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
1562*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_return_void(compiler));
1563*22dc650dSSadaf Ebrahimi 
1564*22dc650dSSadaf Ebrahimi 	return emit_stack_frame_release(compiler, 0);
1565*22dc650dSSadaf Ebrahimi }
1566*22dc650dSSadaf Ebrahimi 
sljit_emit_return_to(struct sljit_compiler * compiler,sljit_s32 src,sljit_sw srcw)1567*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler,
1568*22dc650dSSadaf Ebrahimi 	sljit_s32 src, sljit_sw srcw)
1569*22dc650dSSadaf Ebrahimi {
1570*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
1571*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_return_to(compiler, src, srcw));
1572*22dc650dSSadaf Ebrahimi 
1573*22dc650dSSadaf Ebrahimi 	if (src & SLJIT_MEM) {
1574*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
1575*22dc650dSSadaf Ebrahimi 		src = TMP_REG1;
1576*22dc650dSSadaf Ebrahimi 		srcw = 0;
1577*22dc650dSSadaf Ebrahimi 	} else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {
1578*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | RM(src)));
1579*22dc650dSSadaf Ebrahimi 		src = TMP_REG1;
1580*22dc650dSSadaf Ebrahimi 		srcw = 0;
1581*22dc650dSSadaf Ebrahimi 	}
1582*22dc650dSSadaf Ebrahimi 
1583*22dc650dSSadaf Ebrahimi 	FAIL_IF(emit_stack_frame_release(compiler, 1));
1584*22dc650dSSadaf Ebrahimi 
1585*22dc650dSSadaf Ebrahimi 	SLJIT_SKIP_CHECKS(compiler);
1586*22dc650dSSadaf Ebrahimi 	return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);
1587*22dc650dSSadaf Ebrahimi }
1588*22dc650dSSadaf Ebrahimi 
1589*22dc650dSSadaf Ebrahimi /* --------------------------------------------------------------------- */
1590*22dc650dSSadaf Ebrahimi /*  Operators                                                            */
1591*22dc650dSSadaf Ebrahimi /* --------------------------------------------------------------------- */
1592*22dc650dSSadaf Ebrahimi 
emit_single_op(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 flags,sljit_uw dst,sljit_uw src1,sljit_uw src2)1593*22dc650dSSadaf Ebrahimi static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
1594*22dc650dSSadaf Ebrahimi 	sljit_uw dst, sljit_uw src1, sljit_uw src2)
1595*22dc650dSSadaf Ebrahimi {
1596*22dc650dSSadaf Ebrahimi 	sljit_s32 reg, is_masked;
1597*22dc650dSSadaf Ebrahimi 	sljit_uw shift_type;
1598*22dc650dSSadaf Ebrahimi 
1599*22dc650dSSadaf Ebrahimi 	switch (op) {
1600*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV:
1601*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));
1602*22dc650dSSadaf Ebrahimi 		if (dst != src2) {
1603*22dc650dSSadaf Ebrahimi 			if (src2 & SRC2_IMM) {
1604*22dc650dSSadaf Ebrahimi 				return push_inst(compiler, ((flags & INV_IMM) ? MVN : MOV) | RD(dst) | src2);
1605*22dc650dSSadaf Ebrahimi 			}
1606*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, MOV | RD(dst) | RM(src2));
1607*22dc650dSSadaf Ebrahimi 		}
1608*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
1609*22dc650dSSadaf Ebrahimi 
1610*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_U8:
1611*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_S8:
1612*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));
1613*22dc650dSSadaf Ebrahimi 		if (flags & REGISTER_OP)
1614*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, (op == SLJIT_MOV_U8 ? UXTB : SXTB) | RD(dst) | RM(src2));
1615*22dc650dSSadaf Ebrahimi 
1616*22dc650dSSadaf Ebrahimi 		if (dst != src2) {
1617*22dc650dSSadaf Ebrahimi 			SLJIT_ASSERT(src2 & SRC2_IMM);
1618*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, ((flags & INV_IMM) ? MVN : MOV) | RD(dst) | src2);
1619*22dc650dSSadaf Ebrahimi 		}
1620*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
1621*22dc650dSSadaf Ebrahimi 
1622*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_U16:
1623*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_S16:
1624*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));
1625*22dc650dSSadaf Ebrahimi 		if (flags & REGISTER_OP)
1626*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, (op == SLJIT_MOV_U16 ? UXTH : SXTH) | RD(dst) | RM(src2));
1627*22dc650dSSadaf Ebrahimi 
1628*22dc650dSSadaf Ebrahimi 		if (dst != src2) {
1629*22dc650dSSadaf Ebrahimi 			SLJIT_ASSERT(src2 & SRC2_IMM);
1630*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, ((flags & INV_IMM) ? MVN : MOV) | RD(dst) | src2);
1631*22dc650dSSadaf Ebrahimi 		}
1632*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
1633*22dc650dSSadaf Ebrahimi 
1634*22dc650dSSadaf Ebrahimi 	case SLJIT_CLZ:
1635*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(!(flags & INV_IMM) && !(src2 & SRC2_IMM));
1636*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, CLZ | RD(dst) | RM(src2)));
1637*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
1638*22dc650dSSadaf Ebrahimi 
1639*22dc650dSSadaf Ebrahimi 	case SLJIT_CTZ:
1640*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(!(flags & INV_IMM) && !(src2 & SRC2_IMM));
1641*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(src1 == TMP_REG1 && src2 != TMP_REG2 && !(flags & ARGS_SWAPPED));
1642*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
1643*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, RSB | SRC2_IMM | RD(TMP_REG2) | RN(src2) | 0));
1644*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, AND | RD(TMP_REG1) | RN(src2) | RM(TMP_REG2)));
1645*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, CLZ | RD(dst) | RM(TMP_REG1)));
1646*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, CMP | SET_FLAGS | SRC2_IMM | RN(dst) | 32));
1647*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, (EOR ^ 0xf0000000) | SRC2_IMM | RD(dst) | RN(dst) | 0x1f);
1648*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_ARM_V6 */
1649*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, RBIT | RD(dst) | RM(src2)));
1650*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, CLZ | RD(dst) | RM(dst));
1651*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_ARM_V6 */
1652*22dc650dSSadaf Ebrahimi 
1653*22dc650dSSadaf Ebrahimi 	case SLJIT_REV:
1654*22dc650dSSadaf Ebrahimi 	case SLJIT_REV_U32:
1655*22dc650dSSadaf Ebrahimi 	case SLJIT_REV_S32:
1656*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));
1657*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, REV | RD(dst) | RM(src2));
1658*22dc650dSSadaf Ebrahimi 
1659*22dc650dSSadaf Ebrahimi 	case SLJIT_REV_U16:
1660*22dc650dSSadaf Ebrahimi 	case SLJIT_REV_S16:
1661*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));
1662*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, REV16 | RD(dst) | RM(src2)));
1663*22dc650dSSadaf Ebrahimi 		if (!(flags & REGISTER_OP))
1664*22dc650dSSadaf Ebrahimi 			return SLJIT_SUCCESS;
1665*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, (op == SLJIT_REV_U16 ? UXTH : SXTH) | RD(dst) | RM(dst));
1666*22dc650dSSadaf Ebrahimi 	case SLJIT_ADD:
1667*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(!(flags & INV_IMM));
1668*22dc650dSSadaf Ebrahimi 
1669*22dc650dSSadaf Ebrahimi 		if ((flags & (UNUSED_RETURN | ARGS_SWAPPED)) == UNUSED_RETURN)
1670*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, CMN | SET_FLAGS | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
1671*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, ADD | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
1672*22dc650dSSadaf Ebrahimi 
1673*22dc650dSSadaf Ebrahimi 	case SLJIT_ADDC:
1674*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(!(flags & INV_IMM));
1675*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, ADC | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
1676*22dc650dSSadaf Ebrahimi 
1677*22dc650dSSadaf Ebrahimi 	case SLJIT_SUB:
1678*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(!(flags & INV_IMM));
1679*22dc650dSSadaf Ebrahimi 
1680*22dc650dSSadaf Ebrahimi 		if ((flags & (UNUSED_RETURN | ARGS_SWAPPED)) == UNUSED_RETURN)
1681*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, CMP | SET_FLAGS | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
1682*22dc650dSSadaf Ebrahimi 
1683*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, (!(flags & ARGS_SWAPPED) ? SUB : RSB) | (flags & SET_FLAGS)
1684*22dc650dSSadaf Ebrahimi 			| RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
1685*22dc650dSSadaf Ebrahimi 
1686*22dc650dSSadaf Ebrahimi 	case SLJIT_SUBC:
1687*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(!(flags & INV_IMM));
1688*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, (!(flags & ARGS_SWAPPED) ? SBC : RSC) | (flags & SET_FLAGS)
1689*22dc650dSSadaf Ebrahimi 			| RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
1690*22dc650dSSadaf Ebrahimi 
1691*22dc650dSSadaf Ebrahimi 	case SLJIT_MUL:
1692*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(!(flags & INV_IMM));
1693*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(!(src2 & SRC2_IMM));
1694*22dc650dSSadaf Ebrahimi 		compiler->status_flags_state = 0;
1695*22dc650dSSadaf Ebrahimi 
1696*22dc650dSSadaf Ebrahimi 		if (!(flags & SET_FLAGS))
1697*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, MUL | RN(dst) | RM8(src2) | RM(src1));
1698*22dc650dSSadaf Ebrahimi 
1699*22dc650dSSadaf Ebrahimi 		reg = dst == TMP_REG1 ? TMP_REG2 : TMP_REG1;
1700*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SMULL | RN(reg) | RD(dst) | RM8(src2) | RM(src1)));
1701*22dc650dSSadaf Ebrahimi 
1702*22dc650dSSadaf Ebrahimi 		/* cmp TMP_REG1, dst asr #31. */
1703*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, CMP | SET_FLAGS | RN(reg) | RM(dst) | 0xfc0);
1704*22dc650dSSadaf Ebrahimi 
1705*22dc650dSSadaf Ebrahimi 	case SLJIT_AND:
1706*22dc650dSSadaf Ebrahimi 		if ((flags & (UNUSED_RETURN | INV_IMM)) == UNUSED_RETURN)
1707*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, TST | SET_FLAGS | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
1708*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, (!(flags & INV_IMM) ? AND : BIC) | (flags & SET_FLAGS)
1709*22dc650dSSadaf Ebrahimi 			| RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
1710*22dc650dSSadaf Ebrahimi 
1711*22dc650dSSadaf Ebrahimi 	case SLJIT_OR:
1712*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(!(flags & INV_IMM));
1713*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, ORR | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
1714*22dc650dSSadaf Ebrahimi 
1715*22dc650dSSadaf Ebrahimi 	case SLJIT_XOR:
1716*22dc650dSSadaf Ebrahimi 		if (flags & INV_IMM) {
1717*22dc650dSSadaf Ebrahimi 			SLJIT_ASSERT(src2 == SRC2_IMM);
1718*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, MVN | (flags & SET_FLAGS) | RD(dst) | RM(src1));
1719*22dc650dSSadaf Ebrahimi 		}
1720*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, EOR | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
1721*22dc650dSSadaf Ebrahimi 
1722*22dc650dSSadaf Ebrahimi 	case SLJIT_SHL:
1723*22dc650dSSadaf Ebrahimi 	case SLJIT_MSHL:
1724*22dc650dSSadaf Ebrahimi 		shift_type = 0;
1725*22dc650dSSadaf Ebrahimi 		is_masked = op == SLJIT_MSHL;
1726*22dc650dSSadaf Ebrahimi 		break;
1727*22dc650dSSadaf Ebrahimi 
1728*22dc650dSSadaf Ebrahimi 	case SLJIT_LSHR:
1729*22dc650dSSadaf Ebrahimi 	case SLJIT_MLSHR:
1730*22dc650dSSadaf Ebrahimi 		shift_type = 1;
1731*22dc650dSSadaf Ebrahimi 		is_masked = op == SLJIT_MLSHR;
1732*22dc650dSSadaf Ebrahimi 		break;
1733*22dc650dSSadaf Ebrahimi 
1734*22dc650dSSadaf Ebrahimi 	case SLJIT_ASHR:
1735*22dc650dSSadaf Ebrahimi 	case SLJIT_MASHR:
1736*22dc650dSSadaf Ebrahimi 		shift_type = 2;
1737*22dc650dSSadaf Ebrahimi 		is_masked = op == SLJIT_MASHR;
1738*22dc650dSSadaf Ebrahimi 		break;
1739*22dc650dSSadaf Ebrahimi 
1740*22dc650dSSadaf Ebrahimi 	case SLJIT_ROTL:
1741*22dc650dSSadaf Ebrahimi 		if (compiler->shift_imm == 0x20) {
1742*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, RSB | SRC2_IMM | RD(TMP_REG2) | RN(src2) | 0));
1743*22dc650dSSadaf Ebrahimi 			src2 = TMP_REG2;
1744*22dc650dSSadaf Ebrahimi 		} else
1745*22dc650dSSadaf Ebrahimi 			compiler->shift_imm = (sljit_uw)(-(sljit_sw)compiler->shift_imm) & 0x1f;
1746*22dc650dSSadaf Ebrahimi 		/* fallthrough */
1747*22dc650dSSadaf Ebrahimi 
1748*22dc650dSSadaf Ebrahimi 	case SLJIT_ROTR:
1749*22dc650dSSadaf Ebrahimi 		shift_type = 3;
1750*22dc650dSSadaf Ebrahimi 		is_masked = 0;
1751*22dc650dSSadaf Ebrahimi 		break;
1752*22dc650dSSadaf Ebrahimi 
1753*22dc650dSSadaf Ebrahimi 	case SLJIT_MULADD:
1754*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, MLA | RN(dst) | RD(dst) | RM8(src2) | RM(src1));
1755*22dc650dSSadaf Ebrahimi 
1756*22dc650dSSadaf Ebrahimi 	default:
1757*22dc650dSSadaf Ebrahimi 		SLJIT_UNREACHABLE();
1758*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
1759*22dc650dSSadaf Ebrahimi 	}
1760*22dc650dSSadaf Ebrahimi 
1761*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(!(flags & ARGS_SWAPPED) && !(flags & INV_IMM) && !(src2 & SRC2_IMM));
1762*22dc650dSSadaf Ebrahimi 
1763*22dc650dSSadaf Ebrahimi 	if (compiler->shift_imm != 0x20) {
1764*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(src1 == TMP_REG1);
1765*22dc650dSSadaf Ebrahimi 
1766*22dc650dSSadaf Ebrahimi 		if (compiler->shift_imm != 0)
1767*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, MOV | (flags & SET_FLAGS) |
1768*22dc650dSSadaf Ebrahimi 				RD(dst) | (compiler->shift_imm << 7) | (shift_type << 5) | RM(src2));
1769*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, MOV | (flags & SET_FLAGS) | RD(dst) | RM(src2));
1770*22dc650dSSadaf Ebrahimi 	}
1771*22dc650dSSadaf Ebrahimi 
1772*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(src1 != TMP_REG2);
1773*22dc650dSSadaf Ebrahimi 
1774*22dc650dSSadaf Ebrahimi 	if (is_masked) {
1775*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, AND | RD(TMP_REG2) | RN(src2) | SRC2_IMM | 0x1f));
1776*22dc650dSSadaf Ebrahimi 		src2 = TMP_REG2;
1777*22dc650dSSadaf Ebrahimi 	}
1778*22dc650dSSadaf Ebrahimi 
1779*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, MOV | (flags & SET_FLAGS) | RD(dst)
1780*22dc650dSSadaf Ebrahimi 		| RM8(src2) | (sljit_ins)(shift_type << 5) | 0x10 | RM(src1));
1781*22dc650dSSadaf Ebrahimi }
1782*22dc650dSSadaf Ebrahimi 
1783*22dc650dSSadaf Ebrahimi #undef EMIT_SHIFT_INS_AND_RETURN
1784*22dc650dSSadaf Ebrahimi 
1785*22dc650dSSadaf Ebrahimi /* Tests whether the immediate can be stored in the 12 bit imm field.
1786*22dc650dSSadaf Ebrahimi    Returns with 0 if not possible. */
get_imm(sljit_uw imm)1787*22dc650dSSadaf Ebrahimi static sljit_uw get_imm(sljit_uw imm)
1788*22dc650dSSadaf Ebrahimi {
1789*22dc650dSSadaf Ebrahimi 	sljit_u32 rol;
1790*22dc650dSSadaf Ebrahimi 
1791*22dc650dSSadaf Ebrahimi 	if (imm <= 0xff)
1792*22dc650dSSadaf Ebrahimi 		return SRC2_IMM | imm;
1793*22dc650dSSadaf Ebrahimi 
1794*22dc650dSSadaf Ebrahimi 	if (!(imm & 0xff000000)) {
1795*22dc650dSSadaf Ebrahimi 		imm <<= 8;
1796*22dc650dSSadaf Ebrahimi 		rol = 8;
1797*22dc650dSSadaf Ebrahimi 	} else {
1798*22dc650dSSadaf Ebrahimi 		imm = (imm << 24) | (imm >> 8);
1799*22dc650dSSadaf Ebrahimi 		rol = 0;
1800*22dc650dSSadaf Ebrahimi 	}
1801*22dc650dSSadaf Ebrahimi 
1802*22dc650dSSadaf Ebrahimi 	if (!(imm & 0xff000000)) {
1803*22dc650dSSadaf Ebrahimi 		imm <<= 8;
1804*22dc650dSSadaf Ebrahimi 		rol += 4;
1805*22dc650dSSadaf Ebrahimi 	}
1806*22dc650dSSadaf Ebrahimi 
1807*22dc650dSSadaf Ebrahimi 	if (!(imm & 0xf0000000)) {
1808*22dc650dSSadaf Ebrahimi 		imm <<= 4;
1809*22dc650dSSadaf Ebrahimi 		rol += 2;
1810*22dc650dSSadaf Ebrahimi 	}
1811*22dc650dSSadaf Ebrahimi 
1812*22dc650dSSadaf Ebrahimi 	if (!(imm & 0xc0000000)) {
1813*22dc650dSSadaf Ebrahimi 		imm <<= 2;
1814*22dc650dSSadaf Ebrahimi 		rol += 1;
1815*22dc650dSSadaf Ebrahimi 	}
1816*22dc650dSSadaf Ebrahimi 
1817*22dc650dSSadaf Ebrahimi 	if (!(imm & 0x00ffffff))
1818*22dc650dSSadaf Ebrahimi 		return SRC2_IMM | (imm >> 24) | (rol << 8);
1819*22dc650dSSadaf Ebrahimi 	return 0;
1820*22dc650dSSadaf Ebrahimi }
1821*22dc650dSSadaf Ebrahimi 
compute_imm(sljit_uw imm,sljit_uw * imm2)1822*22dc650dSSadaf Ebrahimi static sljit_uw compute_imm(sljit_uw imm, sljit_uw* imm2)
1823*22dc650dSSadaf Ebrahimi {
1824*22dc650dSSadaf Ebrahimi 	sljit_uw mask;
1825*22dc650dSSadaf Ebrahimi 	sljit_uw imm1;
1826*22dc650dSSadaf Ebrahimi 	sljit_uw rol;
1827*22dc650dSSadaf Ebrahimi 
1828*22dc650dSSadaf Ebrahimi 	/* Step1: Search a zero byte (8 continous zero bit). */
1829*22dc650dSSadaf Ebrahimi 	mask = 0xff000000;
1830*22dc650dSSadaf Ebrahimi 	rol = 8;
1831*22dc650dSSadaf Ebrahimi 	while (1) {
1832*22dc650dSSadaf Ebrahimi 		if (!(imm & mask)) {
1833*22dc650dSSadaf Ebrahimi 			/* Rol imm by rol. */
1834*22dc650dSSadaf Ebrahimi 			imm = (imm << rol) | (imm >> (32 - rol));
1835*22dc650dSSadaf Ebrahimi 			/* Calculate arm rol. */
1836*22dc650dSSadaf Ebrahimi 			rol = 4 + (rol >> 1);
1837*22dc650dSSadaf Ebrahimi 			break;
1838*22dc650dSSadaf Ebrahimi 		}
1839*22dc650dSSadaf Ebrahimi 
1840*22dc650dSSadaf Ebrahimi 		rol += 2;
1841*22dc650dSSadaf Ebrahimi 		mask >>= 2;
1842*22dc650dSSadaf Ebrahimi 		if (mask & 0x3) {
1843*22dc650dSSadaf Ebrahimi 			/* rol by 8. */
1844*22dc650dSSadaf Ebrahimi 			imm = (imm << 8) | (imm >> 24);
1845*22dc650dSSadaf Ebrahimi 			mask = 0xff00;
1846*22dc650dSSadaf Ebrahimi 			rol = 24;
1847*22dc650dSSadaf Ebrahimi 			while (1) {
1848*22dc650dSSadaf Ebrahimi 				if (!(imm & mask)) {
1849*22dc650dSSadaf Ebrahimi 					/* Rol imm by rol. */
1850*22dc650dSSadaf Ebrahimi 					imm = (imm << rol) | (imm >> (32 - rol));
1851*22dc650dSSadaf Ebrahimi 					/* Calculate arm rol. */
1852*22dc650dSSadaf Ebrahimi 					rol = (rol >> 1) - 8;
1853*22dc650dSSadaf Ebrahimi 					break;
1854*22dc650dSSadaf Ebrahimi 				}
1855*22dc650dSSadaf Ebrahimi 				rol += 2;
1856*22dc650dSSadaf Ebrahimi 				mask >>= 2;
1857*22dc650dSSadaf Ebrahimi 				if (mask & 0x3)
1858*22dc650dSSadaf Ebrahimi 					return 0;
1859*22dc650dSSadaf Ebrahimi 			}
1860*22dc650dSSadaf Ebrahimi 			break;
1861*22dc650dSSadaf Ebrahimi 		}
1862*22dc650dSSadaf Ebrahimi 	}
1863*22dc650dSSadaf Ebrahimi 
1864*22dc650dSSadaf Ebrahimi 	/* The low 8 bit must be zero. */
1865*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(!(imm & 0xff));
1866*22dc650dSSadaf Ebrahimi 
1867*22dc650dSSadaf Ebrahimi 	if (!(imm & 0xff000000)) {
1868*22dc650dSSadaf Ebrahimi 		imm1 = SRC2_IMM | ((imm >> 16) & 0xff) | (((rol + 4) & 0xf) << 8);
1869*22dc650dSSadaf Ebrahimi 		*imm2 = SRC2_IMM | ((imm >> 8) & 0xff) | (((rol + 8) & 0xf) << 8);
1870*22dc650dSSadaf Ebrahimi 	} else if (imm & 0xc0000000) {
1871*22dc650dSSadaf Ebrahimi 		imm1 = SRC2_IMM | ((imm >> 24) & 0xff) | ((rol & 0xf) << 8);
1872*22dc650dSSadaf Ebrahimi 		imm <<= 8;
1873*22dc650dSSadaf Ebrahimi 		rol += 4;
1874*22dc650dSSadaf Ebrahimi 
1875*22dc650dSSadaf Ebrahimi 		if (!(imm & 0xff000000)) {
1876*22dc650dSSadaf Ebrahimi 			imm <<= 8;
1877*22dc650dSSadaf Ebrahimi 			rol += 4;
1878*22dc650dSSadaf Ebrahimi 		}
1879*22dc650dSSadaf Ebrahimi 
1880*22dc650dSSadaf Ebrahimi 		if (!(imm & 0xf0000000)) {
1881*22dc650dSSadaf Ebrahimi 			imm <<= 4;
1882*22dc650dSSadaf Ebrahimi 			rol += 2;
1883*22dc650dSSadaf Ebrahimi 		}
1884*22dc650dSSadaf Ebrahimi 
1885*22dc650dSSadaf Ebrahimi 		if (!(imm & 0xc0000000)) {
1886*22dc650dSSadaf Ebrahimi 			imm <<= 2;
1887*22dc650dSSadaf Ebrahimi 			rol += 1;
1888*22dc650dSSadaf Ebrahimi 		}
1889*22dc650dSSadaf Ebrahimi 
1890*22dc650dSSadaf Ebrahimi 		if (!(imm & 0x00ffffff))
1891*22dc650dSSadaf Ebrahimi 			*imm2 = SRC2_IMM | (imm >> 24) | ((rol & 0xf) << 8);
1892*22dc650dSSadaf Ebrahimi 		else
1893*22dc650dSSadaf Ebrahimi 			return 0;
1894*22dc650dSSadaf Ebrahimi 	} else {
1895*22dc650dSSadaf Ebrahimi 		if (!(imm & 0xf0000000)) {
1896*22dc650dSSadaf Ebrahimi 			imm <<= 4;
1897*22dc650dSSadaf Ebrahimi 			rol += 2;
1898*22dc650dSSadaf Ebrahimi 		}
1899*22dc650dSSadaf Ebrahimi 
1900*22dc650dSSadaf Ebrahimi 		if (!(imm & 0xc0000000)) {
1901*22dc650dSSadaf Ebrahimi 			imm <<= 2;
1902*22dc650dSSadaf Ebrahimi 			rol += 1;
1903*22dc650dSSadaf Ebrahimi 		}
1904*22dc650dSSadaf Ebrahimi 
1905*22dc650dSSadaf Ebrahimi 		imm1 = SRC2_IMM | ((imm >> 24) & 0xff) | ((rol & 0xf) << 8);
1906*22dc650dSSadaf Ebrahimi 		imm <<= 8;
1907*22dc650dSSadaf Ebrahimi 		rol += 4;
1908*22dc650dSSadaf Ebrahimi 
1909*22dc650dSSadaf Ebrahimi 		if (!(imm & 0xf0000000)) {
1910*22dc650dSSadaf Ebrahimi 			imm <<= 4;
1911*22dc650dSSadaf Ebrahimi 			rol += 2;
1912*22dc650dSSadaf Ebrahimi 		}
1913*22dc650dSSadaf Ebrahimi 
1914*22dc650dSSadaf Ebrahimi 		if (!(imm & 0xc0000000)) {
1915*22dc650dSSadaf Ebrahimi 			imm <<= 2;
1916*22dc650dSSadaf Ebrahimi 			rol += 1;
1917*22dc650dSSadaf Ebrahimi 		}
1918*22dc650dSSadaf Ebrahimi 
1919*22dc650dSSadaf Ebrahimi 		if (!(imm & 0x00ffffff))
1920*22dc650dSSadaf Ebrahimi 			*imm2 = SRC2_IMM | (imm >> 24) | ((rol & 0xf) << 8);
1921*22dc650dSSadaf Ebrahimi 		else
1922*22dc650dSSadaf Ebrahimi 			return 0;
1923*22dc650dSSadaf Ebrahimi 	}
1924*22dc650dSSadaf Ebrahimi 
1925*22dc650dSSadaf Ebrahimi 	return imm1;
1926*22dc650dSSadaf Ebrahimi }
1927*22dc650dSSadaf Ebrahimi 
load_immediate(struct sljit_compiler * compiler,sljit_s32 reg,sljit_uw imm)1928*22dc650dSSadaf Ebrahimi static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_uw imm)
1929*22dc650dSSadaf Ebrahimi {
1930*22dc650dSSadaf Ebrahimi 	sljit_uw tmp;
1931*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
1932*22dc650dSSadaf Ebrahimi 	sljit_uw imm1, imm2;
1933*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_ARM_V6 */
1934*22dc650dSSadaf Ebrahimi 	if (!(imm & ~(sljit_uw)0xffff))
1935*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | (imm & 0xfff));
1936*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_ARM_V6 */
1937*22dc650dSSadaf Ebrahimi 
1938*22dc650dSSadaf Ebrahimi 	/* Create imm by 1 inst. */
1939*22dc650dSSadaf Ebrahimi 	tmp = get_imm(imm);
1940*22dc650dSSadaf Ebrahimi 	if (tmp)
1941*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, MOV | RD(reg) | tmp);
1942*22dc650dSSadaf Ebrahimi 
1943*22dc650dSSadaf Ebrahimi 	tmp = get_imm(~imm);
1944*22dc650dSSadaf Ebrahimi 	if (tmp)
1945*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, MVN | RD(reg) | tmp);
1946*22dc650dSSadaf Ebrahimi 
1947*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
1948*22dc650dSSadaf Ebrahimi 	/* Create imm by 2 inst. */
1949*22dc650dSSadaf Ebrahimi 	imm1 = compute_imm(imm, &imm2);
1950*22dc650dSSadaf Ebrahimi 	if (imm1 != 0) {
1951*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, MOV | RD(reg) | imm1));
1952*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, ORR | RD(reg) | RN(reg) | imm2);
1953*22dc650dSSadaf Ebrahimi 	}
1954*22dc650dSSadaf Ebrahimi 
1955*22dc650dSSadaf Ebrahimi 	imm1 = compute_imm(~imm, &imm2);
1956*22dc650dSSadaf Ebrahimi 	if (imm1 != 0) {
1957*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, MVN | RD(reg) | imm1));
1958*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, BIC | RD(reg) | RN(reg) | imm2);
1959*22dc650dSSadaf Ebrahimi 	}
1960*22dc650dSSadaf Ebrahimi 
1961*22dc650dSSadaf Ebrahimi 	/* Load integer. */
1962*22dc650dSSadaf Ebrahimi 	return push_inst_with_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, reg, TMP_PC, 0), imm);
1963*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_ARM_V6 */
1964*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | (imm & 0xfff)));
1965*22dc650dSSadaf Ebrahimi 	if (imm <= 0xffff)
1966*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
1967*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, MOVT | RD(reg) | ((imm >> 12) & 0xf0000) | ((imm >> 16) & 0xfff));
1968*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_ARM_V6 */
1969*22dc650dSSadaf Ebrahimi }
1970*22dc650dSSadaf Ebrahimi 
emit_op_mem(struct sljit_compiler * compiler,sljit_s32 flags,sljit_s32 reg,sljit_s32 arg,sljit_sw argw,sljit_s32 tmp_reg)1971*22dc650dSSadaf Ebrahimi static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg,
1972*22dc650dSSadaf Ebrahimi 	sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg)
1973*22dc650dSSadaf Ebrahimi {
1974*22dc650dSSadaf Ebrahimi 	sljit_uw imm, offset_reg, tmp;
1975*22dc650dSSadaf Ebrahimi 	sljit_sw mask = IS_TYPE1_TRANSFER(flags) ? 0xfff : 0xff;
1976*22dc650dSSadaf Ebrahimi 	sljit_sw sign = IS_TYPE1_TRANSFER(flags) ? 0x1000 : 0x100;
1977*22dc650dSSadaf Ebrahimi 
1978*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(arg & SLJIT_MEM);
1979*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT((arg & REG_MASK) != tmp_reg || (arg == SLJIT_MEM1(tmp_reg) && argw >= -mask && argw <= mask));
1980*22dc650dSSadaf Ebrahimi 
1981*22dc650dSSadaf Ebrahimi 	if (SLJIT_UNLIKELY(!(arg & REG_MASK))) {
1982*22dc650dSSadaf Ebrahimi 		tmp = (sljit_uw)(argw & (sign | mask));
1983*22dc650dSSadaf Ebrahimi 		tmp = (sljit_uw)((argw + (tmp <= (sljit_uw)sign ? 0 : sign)) & ~mask);
1984*22dc650dSSadaf Ebrahimi 
1985*22dc650dSSadaf Ebrahimi 		FAIL_IF(load_immediate(compiler, tmp_reg, tmp));
1986*22dc650dSSadaf Ebrahimi 
1987*22dc650dSSadaf Ebrahimi 		argw -= (sljit_sw)tmp;
1988*22dc650dSSadaf Ebrahimi 		tmp = 1;
1989*22dc650dSSadaf Ebrahimi 
1990*22dc650dSSadaf Ebrahimi 		if (argw < 0) {
1991*22dc650dSSadaf Ebrahimi 			argw = -argw;
1992*22dc650dSSadaf Ebrahimi 			tmp = 0;
1993*22dc650dSSadaf Ebrahimi 		}
1994*22dc650dSSadaf Ebrahimi 
1995*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, EMIT_DATA_TRANSFER(flags, tmp, reg, tmp_reg,
1996*22dc650dSSadaf Ebrahimi 			(mask == 0xff) ? TYPE2_TRANSFER_IMM(argw) : argw));
1997*22dc650dSSadaf Ebrahimi 	}
1998*22dc650dSSadaf Ebrahimi 
1999*22dc650dSSadaf Ebrahimi 	if (arg & OFFS_REG_MASK) {
2000*22dc650dSSadaf Ebrahimi 		offset_reg = OFFS_REG(arg);
2001*22dc650dSSadaf Ebrahimi 		arg &= REG_MASK;
2002*22dc650dSSadaf Ebrahimi 		argw &= 0x3;
2003*22dc650dSSadaf Ebrahimi 
2004*22dc650dSSadaf Ebrahimi 		if (argw != 0 && (mask == 0xff)) {
2005*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | RM(offset_reg) | ((sljit_ins)argw << 7)));
2006*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, tmp_reg, TYPE2_TRANSFER_IMM(0)));
2007*22dc650dSSadaf Ebrahimi 		}
2008*22dc650dSSadaf Ebrahimi 
2009*22dc650dSSadaf Ebrahimi 		/* Bit 25: RM is offset. */
2010*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg,
2011*22dc650dSSadaf Ebrahimi 			RM(offset_reg) | (mask == 0xff ? 0 : (1 << 25)) | ((sljit_ins)argw << 7)));
2012*22dc650dSSadaf Ebrahimi 	}
2013*22dc650dSSadaf Ebrahimi 
2014*22dc650dSSadaf Ebrahimi 	arg &= REG_MASK;
2015*22dc650dSSadaf Ebrahimi 
2016*22dc650dSSadaf Ebrahimi 	if (argw > mask) {
2017*22dc650dSSadaf Ebrahimi 		tmp = (sljit_uw)(argw & (sign | mask));
2018*22dc650dSSadaf Ebrahimi 		tmp = (sljit_uw)((argw + (tmp <= (sljit_uw)sign ? 0 : sign)) & ~mask);
2019*22dc650dSSadaf Ebrahimi 		imm = get_imm(tmp);
2020*22dc650dSSadaf Ebrahimi 
2021*22dc650dSSadaf Ebrahimi 		if (imm) {
2022*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | imm));
2023*22dc650dSSadaf Ebrahimi 			argw -= (sljit_sw)tmp;
2024*22dc650dSSadaf Ebrahimi 			arg = tmp_reg;
2025*22dc650dSSadaf Ebrahimi 
2026*22dc650dSSadaf Ebrahimi 			SLJIT_ASSERT(argw >= -mask && argw <= mask);
2027*22dc650dSSadaf Ebrahimi 		}
2028*22dc650dSSadaf Ebrahimi 	} else if (argw < -mask) {
2029*22dc650dSSadaf Ebrahimi 		tmp = (sljit_uw)(-argw & (sign | mask));
2030*22dc650dSSadaf Ebrahimi 		tmp = (sljit_uw)((-argw + (tmp <= (sljit_uw)sign ? 0 : sign)) & ~mask);
2031*22dc650dSSadaf Ebrahimi 		imm = get_imm(tmp);
2032*22dc650dSSadaf Ebrahimi 
2033*22dc650dSSadaf Ebrahimi 		if (imm) {
2034*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, SUB | RD(tmp_reg) | RN(arg) | imm));
2035*22dc650dSSadaf Ebrahimi 			argw += (sljit_sw)tmp;
2036*22dc650dSSadaf Ebrahimi 			arg = tmp_reg;
2037*22dc650dSSadaf Ebrahimi 
2038*22dc650dSSadaf Ebrahimi 			SLJIT_ASSERT(argw >= -mask && argw <= mask);
2039*22dc650dSSadaf Ebrahimi 		}
2040*22dc650dSSadaf Ebrahimi 	}
2041*22dc650dSSadaf Ebrahimi 
2042*22dc650dSSadaf Ebrahimi 	if (argw <= mask && argw >= -mask) {
2043*22dc650dSSadaf Ebrahimi 		if (argw >= 0) {
2044*22dc650dSSadaf Ebrahimi 			if (mask == 0xff)
2045*22dc650dSSadaf Ebrahimi 				argw = TYPE2_TRANSFER_IMM(argw);
2046*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg, argw));
2047*22dc650dSSadaf Ebrahimi 		}
2048*22dc650dSSadaf Ebrahimi 
2049*22dc650dSSadaf Ebrahimi 		argw = -argw;
2050*22dc650dSSadaf Ebrahimi 
2051*22dc650dSSadaf Ebrahimi 		if (mask == 0xff)
2052*22dc650dSSadaf Ebrahimi 			argw = TYPE2_TRANSFER_IMM(argw);
2053*22dc650dSSadaf Ebrahimi 
2054*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 0, reg, arg, argw));
2055*22dc650dSSadaf Ebrahimi 	}
2056*22dc650dSSadaf Ebrahimi 
2057*22dc650dSSadaf Ebrahimi 	FAIL_IF(load_immediate(compiler, tmp_reg, (sljit_uw)argw));
2058*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg,
2059*22dc650dSSadaf Ebrahimi 		RM(tmp_reg) | (mask == 0xff ? 0 : (1 << 25))));
2060*22dc650dSSadaf Ebrahimi }
2061*22dc650dSSadaf Ebrahimi 
emit_op(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 inp_flags,sljit_s32 dst,sljit_sw dstw,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2,sljit_sw src2w)2062*22dc650dSSadaf Ebrahimi static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 inp_flags,
2063*22dc650dSSadaf Ebrahimi 	sljit_s32 dst, sljit_sw dstw,
2064*22dc650dSSadaf Ebrahimi 	sljit_s32 src1, sljit_sw src1w,
2065*22dc650dSSadaf Ebrahimi 	sljit_s32 src2, sljit_sw src2w)
2066*22dc650dSSadaf Ebrahimi {
2067*22dc650dSSadaf Ebrahimi 	/* src1 is reg or TMP_REG1
2068*22dc650dSSadaf Ebrahimi 	   src2 is reg, TMP_REG2, or imm
2069*22dc650dSSadaf Ebrahimi 	   result goes to TMP_REG2, so put result can use TMP_REG1. */
2070*22dc650dSSadaf Ebrahimi 
2071*22dc650dSSadaf Ebrahimi 	/* We prefers register and simple consts. */
2072*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_reg;
2073*22dc650dSSadaf Ebrahimi 	sljit_s32 src1_reg = 0;
2074*22dc650dSSadaf Ebrahimi 	sljit_s32 src2_reg = 0;
2075*22dc650dSSadaf Ebrahimi 	sljit_s32 src2_tmp_reg = 0;
2076*22dc650dSSadaf Ebrahimi 	sljit_s32 flags = HAS_FLAGS(op) ? SET_FLAGS : 0;
2077*22dc650dSSadaf Ebrahimi 	sljit_s32 neg_op = 0;
2078*22dc650dSSadaf Ebrahimi 	sljit_u32 imm2;
2079*22dc650dSSadaf Ebrahimi 
2080*22dc650dSSadaf Ebrahimi 	op = GET_OPCODE(op);
2081*22dc650dSSadaf Ebrahimi 
2082*22dc650dSSadaf Ebrahimi 	if (flags & SET_FLAGS)
2083*22dc650dSSadaf Ebrahimi 		inp_flags &= ~ALLOW_DOUBLE_IMM;
2084*22dc650dSSadaf Ebrahimi 
2085*22dc650dSSadaf Ebrahimi 	if (dst == TMP_REG1)
2086*22dc650dSSadaf Ebrahimi 		flags |= UNUSED_RETURN;
2087*22dc650dSSadaf Ebrahimi 
2088*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(!(inp_flags & ALLOW_INV_IMM) || (inp_flags & ALLOW_IMM));
2089*22dc650dSSadaf Ebrahimi 
2090*22dc650dSSadaf Ebrahimi 	if (inp_flags & ALLOW_NEG_IMM) {
2091*22dc650dSSadaf Ebrahimi 		switch (op) {
2092*22dc650dSSadaf Ebrahimi 		case SLJIT_ADD:
2093*22dc650dSSadaf Ebrahimi 			compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
2094*22dc650dSSadaf Ebrahimi 			neg_op = SLJIT_SUB;
2095*22dc650dSSadaf Ebrahimi 			break;
2096*22dc650dSSadaf Ebrahimi 		case SLJIT_ADDC:
2097*22dc650dSSadaf Ebrahimi 			compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
2098*22dc650dSSadaf Ebrahimi 			neg_op = SLJIT_SUBC;
2099*22dc650dSSadaf Ebrahimi 			break;
2100*22dc650dSSadaf Ebrahimi 		case SLJIT_SUB:
2101*22dc650dSSadaf Ebrahimi 			compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
2102*22dc650dSSadaf Ebrahimi 			neg_op = SLJIT_ADD;
2103*22dc650dSSadaf Ebrahimi 			break;
2104*22dc650dSSadaf Ebrahimi 		case SLJIT_SUBC:
2105*22dc650dSSadaf Ebrahimi 			compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
2106*22dc650dSSadaf Ebrahimi 			neg_op = SLJIT_ADDC;
2107*22dc650dSSadaf Ebrahimi 			break;
2108*22dc650dSSadaf Ebrahimi 		}
2109*22dc650dSSadaf Ebrahimi 	}
2110*22dc650dSSadaf Ebrahimi 
2111*22dc650dSSadaf Ebrahimi 	do {
2112*22dc650dSSadaf Ebrahimi 		if (!(inp_flags & ALLOW_IMM))
2113*22dc650dSSadaf Ebrahimi 			break;
2114*22dc650dSSadaf Ebrahimi 
2115*22dc650dSSadaf Ebrahimi 		if (src2 == SLJIT_IMM) {
2116*22dc650dSSadaf Ebrahimi 			src2_reg = (sljit_s32)get_imm((sljit_uw)src2w);
2117*22dc650dSSadaf Ebrahimi 			if (src2_reg)
2118*22dc650dSSadaf Ebrahimi 				break;
2119*22dc650dSSadaf Ebrahimi 
2120*22dc650dSSadaf Ebrahimi 			if (inp_flags & ALLOW_INV_IMM) {
2121*22dc650dSSadaf Ebrahimi 				src2_reg = (sljit_s32)get_imm(~(sljit_uw)src2w);
2122*22dc650dSSadaf Ebrahimi 				if (src2_reg) {
2123*22dc650dSSadaf Ebrahimi 					flags |= INV_IMM;
2124*22dc650dSSadaf Ebrahimi 					break;
2125*22dc650dSSadaf Ebrahimi 				}
2126*22dc650dSSadaf Ebrahimi 			}
2127*22dc650dSSadaf Ebrahimi 
2128*22dc650dSSadaf Ebrahimi 			if (neg_op != 0) {
2129*22dc650dSSadaf Ebrahimi 				src2_reg = (sljit_s32)get_imm((neg_op == SLJIT_ADD || neg_op == SLJIT_SUB) ? (sljit_uw)-src2w : ~(sljit_uw)src2w);
2130*22dc650dSSadaf Ebrahimi 				if (src2_reg) {
2131*22dc650dSSadaf Ebrahimi 					op = neg_op | GET_ALL_FLAGS(op);
2132*22dc650dSSadaf Ebrahimi 					break;
2133*22dc650dSSadaf Ebrahimi 				}
2134*22dc650dSSadaf Ebrahimi 			}
2135*22dc650dSSadaf Ebrahimi 		}
2136*22dc650dSSadaf Ebrahimi 
2137*22dc650dSSadaf Ebrahimi 		if (src1 == SLJIT_IMM) {
2138*22dc650dSSadaf Ebrahimi 			src2_reg = (sljit_s32)get_imm((sljit_uw)src1w);
2139*22dc650dSSadaf Ebrahimi 			if (src2_reg) {
2140*22dc650dSSadaf Ebrahimi 				flags |= ARGS_SWAPPED;
2141*22dc650dSSadaf Ebrahimi 				src1 = src2;
2142*22dc650dSSadaf Ebrahimi 				src1w = src2w;
2143*22dc650dSSadaf Ebrahimi 				break;
2144*22dc650dSSadaf Ebrahimi 			}
2145*22dc650dSSadaf Ebrahimi 
2146*22dc650dSSadaf Ebrahimi 			if (inp_flags & ALLOW_INV_IMM) {
2147*22dc650dSSadaf Ebrahimi 				src2_reg = (sljit_s32)get_imm(~(sljit_uw)src1w);
2148*22dc650dSSadaf Ebrahimi 				if (src2_reg) {
2149*22dc650dSSadaf Ebrahimi 					flags |= ARGS_SWAPPED | INV_IMM;
2150*22dc650dSSadaf Ebrahimi 					src1 = src2;
2151*22dc650dSSadaf Ebrahimi 					src1w = src2w;
2152*22dc650dSSadaf Ebrahimi 					break;
2153*22dc650dSSadaf Ebrahimi 				}
2154*22dc650dSSadaf Ebrahimi 			}
2155*22dc650dSSadaf Ebrahimi 
2156*22dc650dSSadaf Ebrahimi 			if (neg_op >= SLJIT_SUB) {
2157*22dc650dSSadaf Ebrahimi 				/* Note: additive operation (commutative). */
2158*22dc650dSSadaf Ebrahimi 				SLJIT_ASSERT(op == SLJIT_ADD || op == SLJIT_ADDC);
2159*22dc650dSSadaf Ebrahimi 
2160*22dc650dSSadaf Ebrahimi 				src2_reg = (sljit_s32)get_imm((sljit_uw)-src1w);
2161*22dc650dSSadaf Ebrahimi 				if (src2_reg) {
2162*22dc650dSSadaf Ebrahimi 					src1 = src2;
2163*22dc650dSSadaf Ebrahimi 					src1w = src2w;
2164*22dc650dSSadaf Ebrahimi 					op = neg_op | GET_ALL_FLAGS(op);
2165*22dc650dSSadaf Ebrahimi 					break;
2166*22dc650dSSadaf Ebrahimi 				}
2167*22dc650dSSadaf Ebrahimi 			}
2168*22dc650dSSadaf Ebrahimi 		}
2169*22dc650dSSadaf Ebrahimi 	} while(0);
2170*22dc650dSSadaf Ebrahimi 
2171*22dc650dSSadaf Ebrahimi 	/* Destination. */
2172*22dc650dSSadaf Ebrahimi 	dst_reg = FAST_IS_REG(dst) ? dst : TMP_REG2;
2173*22dc650dSSadaf Ebrahimi 
2174*22dc650dSSadaf Ebrahimi 	if (op <= SLJIT_MOV_P) {
2175*22dc650dSSadaf Ebrahimi 		if (dst & SLJIT_MEM) {
2176*22dc650dSSadaf Ebrahimi 			if (inp_flags & BYTE_SIZE)
2177*22dc650dSSadaf Ebrahimi 				inp_flags &= ~SIGNED;
2178*22dc650dSSadaf Ebrahimi 
2179*22dc650dSSadaf Ebrahimi 			if (FAST_IS_REG(src2))
2180*22dc650dSSadaf Ebrahimi 				return emit_op_mem(compiler, inp_flags, src2, dst, dstw, TMP_REG1);
2181*22dc650dSSadaf Ebrahimi 		}
2182*22dc650dSSadaf Ebrahimi 
2183*22dc650dSSadaf Ebrahimi 		if (FAST_IS_REG(src2) && dst_reg != TMP_REG2)
2184*22dc650dSSadaf Ebrahimi 			flags |= REGISTER_OP;
2185*22dc650dSSadaf Ebrahimi 
2186*22dc650dSSadaf Ebrahimi 		src2_tmp_reg = dst_reg;
2187*22dc650dSSadaf Ebrahimi 	} else {
2188*22dc650dSSadaf Ebrahimi 		if (op == SLJIT_REV_U16 || op == SLJIT_REV_S16) {
2189*22dc650dSSadaf Ebrahimi 			if (!(dst & SLJIT_MEM) && (!(src2 & SLJIT_MEM) || op == SLJIT_REV_S16))
2190*22dc650dSSadaf Ebrahimi 				flags |= REGISTER_OP;
2191*22dc650dSSadaf Ebrahimi 		}
2192*22dc650dSSadaf Ebrahimi 
2193*22dc650dSSadaf Ebrahimi 		src2_tmp_reg = FAST_IS_REG(src1) ? TMP_REG1 : TMP_REG2;
2194*22dc650dSSadaf Ebrahimi 	}
2195*22dc650dSSadaf Ebrahimi 
2196*22dc650dSSadaf Ebrahimi 	if (src2_reg == 0 && (src2 & SLJIT_MEM)) {
2197*22dc650dSSadaf Ebrahimi 		src2_reg = src2_tmp_reg;
2198*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem(compiler, inp_flags | LOAD_DATA, src2_reg, src2, src2w, TMP_REG1));
2199*22dc650dSSadaf Ebrahimi 	}
2200*22dc650dSSadaf Ebrahimi 
2201*22dc650dSSadaf Ebrahimi 	/* Source 1. */
2202*22dc650dSSadaf Ebrahimi 	if (FAST_IS_REG(src1))
2203*22dc650dSSadaf Ebrahimi 		src1_reg = src1;
2204*22dc650dSSadaf Ebrahimi 	else if (src1 & SLJIT_MEM) {
2205*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, TMP_REG1));
2206*22dc650dSSadaf Ebrahimi 		src1_reg = TMP_REG1;
2207*22dc650dSSadaf Ebrahimi 	} else if (!(inp_flags & ALLOW_DOUBLE_IMM) || src2_reg != 0 || op == SLJIT_SUB || op == SLJIT_SUBC) {
2208*22dc650dSSadaf Ebrahimi 		FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)src1w));
2209*22dc650dSSadaf Ebrahimi 		src1_reg = TMP_REG1;
2210*22dc650dSSadaf Ebrahimi 	}
2211*22dc650dSSadaf Ebrahimi 
2212*22dc650dSSadaf Ebrahimi 	/* Source 2. */
2213*22dc650dSSadaf Ebrahimi 	if (src2_reg == 0) {
2214*22dc650dSSadaf Ebrahimi 		src2_reg = src2_tmp_reg;
2215*22dc650dSSadaf Ebrahimi 
2216*22dc650dSSadaf Ebrahimi 		if (FAST_IS_REG(src2))
2217*22dc650dSSadaf Ebrahimi 			src2_reg = src2;
2218*22dc650dSSadaf Ebrahimi 		else if (!(inp_flags & ALLOW_DOUBLE_IMM))
2219*22dc650dSSadaf Ebrahimi 			FAIL_IF(load_immediate(compiler, src2_reg, (sljit_uw)src2w));
2220*22dc650dSSadaf Ebrahimi 		else {
2221*22dc650dSSadaf Ebrahimi 			SLJIT_ASSERT(!(flags & SET_FLAGS));
2222*22dc650dSSadaf Ebrahimi 
2223*22dc650dSSadaf Ebrahimi 			if (src1_reg == 0) {
2224*22dc650dSSadaf Ebrahimi 				FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)src1w));
2225*22dc650dSSadaf Ebrahimi 				src1_reg = TMP_REG1;
2226*22dc650dSSadaf Ebrahimi 			}
2227*22dc650dSSadaf Ebrahimi 
2228*22dc650dSSadaf Ebrahimi 			src2_reg = (sljit_s32)compute_imm((sljit_uw)src2w, &imm2);
2229*22dc650dSSadaf Ebrahimi 
2230*22dc650dSSadaf Ebrahimi 			if (src2_reg == 0 && neg_op != 0) {
2231*22dc650dSSadaf Ebrahimi 				src2_reg = (sljit_s32)compute_imm((sljit_uw)-src2w, &imm2);
2232*22dc650dSSadaf Ebrahimi 				if (src2_reg != 0)
2233*22dc650dSSadaf Ebrahimi 					op = neg_op;
2234*22dc650dSSadaf Ebrahimi 			}
2235*22dc650dSSadaf Ebrahimi 
2236*22dc650dSSadaf Ebrahimi 			if (src2_reg == 0) {
2237*22dc650dSSadaf Ebrahimi 				FAIL_IF(load_immediate(compiler, src2_tmp_reg, (sljit_uw)src2w));
2238*22dc650dSSadaf Ebrahimi 				src2_reg = src2_tmp_reg;
2239*22dc650dSSadaf Ebrahimi 			} else {
2240*22dc650dSSadaf Ebrahimi 				FAIL_IF(emit_single_op(compiler, op, flags, (sljit_uw)dst_reg, (sljit_uw)src1_reg, (sljit_uw)src2_reg));
2241*22dc650dSSadaf Ebrahimi 				src1_reg = dst_reg;
2242*22dc650dSSadaf Ebrahimi 				src2_reg = (sljit_s32)imm2;
2243*22dc650dSSadaf Ebrahimi 
2244*22dc650dSSadaf Ebrahimi 				if (op == SLJIT_ADDC)
2245*22dc650dSSadaf Ebrahimi 					op = SLJIT_ADD;
2246*22dc650dSSadaf Ebrahimi 				else if (op == SLJIT_SUBC)
2247*22dc650dSSadaf Ebrahimi 					op = SLJIT_SUB;
2248*22dc650dSSadaf Ebrahimi 			}
2249*22dc650dSSadaf Ebrahimi 		}
2250*22dc650dSSadaf Ebrahimi 	}
2251*22dc650dSSadaf Ebrahimi 
2252*22dc650dSSadaf Ebrahimi 	if (src1_reg == 0) {
2253*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT((inp_flags & ALLOW_DOUBLE_IMM) && !(flags & SET_FLAGS));
2254*22dc650dSSadaf Ebrahimi 
2255*22dc650dSSadaf Ebrahimi 		src1_reg = (sljit_s32)compute_imm((sljit_uw)src1w, &imm2);
2256*22dc650dSSadaf Ebrahimi 
2257*22dc650dSSadaf Ebrahimi 		if (src1_reg == 0 && neg_op != 0) {
2258*22dc650dSSadaf Ebrahimi 			src1_reg = (sljit_s32)compute_imm((sljit_uw)-src1w, &imm2);
2259*22dc650dSSadaf Ebrahimi 			if (src1_reg != 0)
2260*22dc650dSSadaf Ebrahimi 				op = neg_op;
2261*22dc650dSSadaf Ebrahimi 		}
2262*22dc650dSSadaf Ebrahimi 
2263*22dc650dSSadaf Ebrahimi 		if (src1_reg == 0) {
2264*22dc650dSSadaf Ebrahimi 			FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)src1w));
2265*22dc650dSSadaf Ebrahimi 			src1_reg = TMP_REG1;
2266*22dc650dSSadaf Ebrahimi 		} else {
2267*22dc650dSSadaf Ebrahimi 			FAIL_IF(emit_single_op(compiler, op, flags, (sljit_uw)dst_reg, (sljit_uw)src2_reg, (sljit_uw)src1_reg));
2268*22dc650dSSadaf Ebrahimi 			src1_reg = dst_reg;
2269*22dc650dSSadaf Ebrahimi 			src2_reg = (sljit_s32)imm2;
2270*22dc650dSSadaf Ebrahimi 
2271*22dc650dSSadaf Ebrahimi 			if (op == SLJIT_ADDC)
2272*22dc650dSSadaf Ebrahimi 				op = SLJIT_ADD;
2273*22dc650dSSadaf Ebrahimi 		}
2274*22dc650dSSadaf Ebrahimi 	}
2275*22dc650dSSadaf Ebrahimi 
2276*22dc650dSSadaf Ebrahimi 	FAIL_IF(emit_single_op(compiler, op, flags, (sljit_uw)dst_reg, (sljit_uw)src1_reg, (sljit_uw)src2_reg));
2277*22dc650dSSadaf Ebrahimi 
2278*22dc650dSSadaf Ebrahimi 	if (!(dst & SLJIT_MEM))
2279*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
2280*22dc650dSSadaf Ebrahimi 
2281*22dc650dSSadaf Ebrahimi 	return emit_op_mem(compiler, inp_flags, dst_reg, dst, dstw, TMP_REG1);
2282*22dc650dSSadaf Ebrahimi }
2283*22dc650dSSadaf Ebrahimi 
2284*22dc650dSSadaf Ebrahimi #ifdef __cplusplus
2285*22dc650dSSadaf Ebrahimi extern "C" {
2286*22dc650dSSadaf Ebrahimi #endif
2287*22dc650dSSadaf Ebrahimi 
2288*22dc650dSSadaf Ebrahimi #if defined(__GNUC__)
2289*22dc650dSSadaf Ebrahimi extern unsigned int __aeabi_uidivmod(unsigned int numerator, unsigned int denominator);
2290*22dc650dSSadaf Ebrahimi extern int __aeabi_idivmod(int numerator, int denominator);
2291*22dc650dSSadaf Ebrahimi #else
2292*22dc650dSSadaf Ebrahimi #error "Software divmod functions are needed"
2293*22dc650dSSadaf Ebrahimi #endif
2294*22dc650dSSadaf Ebrahimi 
2295*22dc650dSSadaf Ebrahimi #ifdef __cplusplus
2296*22dc650dSSadaf Ebrahimi }
2297*22dc650dSSadaf Ebrahimi #endif
2298*22dc650dSSadaf Ebrahimi 
sljit_emit_op0(struct sljit_compiler * compiler,sljit_s32 op)2299*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
2300*22dc650dSSadaf Ebrahimi {
2301*22dc650dSSadaf Ebrahimi 	sljit_uw saved_reg_list[3];
2302*22dc650dSSadaf Ebrahimi 	sljit_sw saved_reg_count;
2303*22dc650dSSadaf Ebrahimi 
2304*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2305*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_op0(compiler, op));
2306*22dc650dSSadaf Ebrahimi 
2307*22dc650dSSadaf Ebrahimi 	op = GET_OPCODE(op);
2308*22dc650dSSadaf Ebrahimi 	switch (op) {
2309*22dc650dSSadaf Ebrahimi 	case SLJIT_BREAKPOINT:
2310*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, BKPT));
2311*22dc650dSSadaf Ebrahimi 		break;
2312*22dc650dSSadaf Ebrahimi 	case SLJIT_NOP:
2313*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, NOP));
2314*22dc650dSSadaf Ebrahimi 		break;
2315*22dc650dSSadaf Ebrahimi 	case SLJIT_LMUL_UW:
2316*22dc650dSSadaf Ebrahimi 	case SLJIT_LMUL_SW:
2317*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, (op == SLJIT_LMUL_UW ? UMULL : SMULL)
2318*22dc650dSSadaf Ebrahimi 			| RN(SLJIT_R1) | RD(SLJIT_R0) | RM8(SLJIT_R0) | RM(SLJIT_R1));
2319*22dc650dSSadaf Ebrahimi 	case SLJIT_DIVMOD_UW:
2320*22dc650dSSadaf Ebrahimi 	case SLJIT_DIVMOD_SW:
2321*22dc650dSSadaf Ebrahimi 	case SLJIT_DIV_UW:
2322*22dc650dSSadaf Ebrahimi 	case SLJIT_DIV_SW:
2323*22dc650dSSadaf Ebrahimi 		SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments);
2324*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(reg_map[2] == 1 && reg_map[3] == 2 && reg_map[4] == 3);
2325*22dc650dSSadaf Ebrahimi 
2326*22dc650dSSadaf Ebrahimi 		saved_reg_count = 0;
2327*22dc650dSSadaf Ebrahimi 		if (compiler->scratches >= 4)
2328*22dc650dSSadaf Ebrahimi 			saved_reg_list[saved_reg_count++] = 3;
2329*22dc650dSSadaf Ebrahimi 		if (compiler->scratches >= 3)
2330*22dc650dSSadaf Ebrahimi 			saved_reg_list[saved_reg_count++] = 2;
2331*22dc650dSSadaf Ebrahimi 		if (op >= SLJIT_DIV_UW)
2332*22dc650dSSadaf Ebrahimi 			saved_reg_list[saved_reg_count++] = 1;
2333*22dc650dSSadaf Ebrahimi 
2334*22dc650dSSadaf Ebrahimi 		if (saved_reg_count > 0) {
2335*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, STR | 0x2d0000 | (saved_reg_count >= 3 ? 16 : 8)
2336*22dc650dSSadaf Ebrahimi 						| (saved_reg_list[0] << 12) /* str rX, [sp, #-8/-16]! */));
2337*22dc650dSSadaf Ebrahimi 			if (saved_reg_count >= 2) {
2338*22dc650dSSadaf Ebrahimi 				SLJIT_ASSERT(saved_reg_list[1] < 8);
2339*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, STR | 0x8d0004 | (saved_reg_list[1] << 12) /* str rX, [sp, #4] */));
2340*22dc650dSSadaf Ebrahimi 			}
2341*22dc650dSSadaf Ebrahimi 			if (saved_reg_count >= 3) {
2342*22dc650dSSadaf Ebrahimi 				SLJIT_ASSERT(saved_reg_list[2] < 8);
2343*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, STR | 0x8d0008 | (saved_reg_list[2] << 12) /* str rX, [sp, #8] */));
2344*22dc650dSSadaf Ebrahimi 			}
2345*22dc650dSSadaf Ebrahimi 		}
2346*22dc650dSSadaf Ebrahimi 
2347*22dc650dSSadaf Ebrahimi #if defined(__GNUC__)
2348*22dc650dSSadaf Ebrahimi 		FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM,
2349*22dc650dSSadaf Ebrahimi 			((op | 0x2) == SLJIT_DIV_UW ? SLJIT_FUNC_ADDR(__aeabi_uidivmod) : SLJIT_FUNC_ADDR(__aeabi_idivmod))));
2350*22dc650dSSadaf Ebrahimi #else
2351*22dc650dSSadaf Ebrahimi #error "Software divmod functions are needed"
2352*22dc650dSSadaf Ebrahimi #endif
2353*22dc650dSSadaf Ebrahimi 
2354*22dc650dSSadaf Ebrahimi 		if (saved_reg_count > 0) {
2355*22dc650dSSadaf Ebrahimi 			if (saved_reg_count >= 3) {
2356*22dc650dSSadaf Ebrahimi 				SLJIT_ASSERT(saved_reg_list[2] < 8);
2357*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, LDR | 0x8d0008 | (saved_reg_list[2] << 12) /* ldr rX, [sp, #8] */));
2358*22dc650dSSadaf Ebrahimi 			}
2359*22dc650dSSadaf Ebrahimi 			if (saved_reg_count >= 2) {
2360*22dc650dSSadaf Ebrahimi 				SLJIT_ASSERT(saved_reg_list[1] < 8);
2361*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, LDR | 0x8d0004 | (saved_reg_list[1] << 12) /* ldr rX, [sp, #4] */));
2362*22dc650dSSadaf Ebrahimi 			}
2363*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, (LDR ^ (1 << 24)) | 0x8d0000 | (sljit_ins)(saved_reg_count >= 3 ? 16 : 8)
2364*22dc650dSSadaf Ebrahimi 						| (saved_reg_list[0] << 12) /* ldr rX, [sp], #8/16 */);
2365*22dc650dSSadaf Ebrahimi 		}
2366*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
2367*22dc650dSSadaf Ebrahimi 	case SLJIT_ENDBR:
2368*22dc650dSSadaf Ebrahimi 	case SLJIT_SKIP_FRAMES_BEFORE_RETURN:
2369*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
2370*22dc650dSSadaf Ebrahimi 	}
2371*22dc650dSSadaf Ebrahimi 
2372*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
2373*22dc650dSSadaf Ebrahimi }
2374*22dc650dSSadaf Ebrahimi 
sljit_emit_op1(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 src,sljit_sw srcw)2375*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
2376*22dc650dSSadaf Ebrahimi 	sljit_s32 dst, sljit_sw dstw,
2377*22dc650dSSadaf Ebrahimi 	sljit_s32 src, sljit_sw srcw)
2378*22dc650dSSadaf Ebrahimi {
2379*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2380*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
2381*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(dst, dstw);
2382*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(src, srcw);
2383*22dc650dSSadaf Ebrahimi 
2384*22dc650dSSadaf Ebrahimi 	switch (GET_OPCODE(op)) {
2385*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV:
2386*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_U32:
2387*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_S32:
2388*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV32:
2389*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_P:
2390*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, src, srcw);
2391*22dc650dSSadaf Ebrahimi 
2392*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_U8:
2393*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, SLJIT_MOV_U8, ALLOW_ANY_IMM | BYTE_SIZE, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_u8)srcw : srcw);
2394*22dc650dSSadaf Ebrahimi 
2395*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_S8:
2396*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, SLJIT_MOV_S8, ALLOW_ANY_IMM | SIGNED | BYTE_SIZE, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_s8)srcw : srcw);
2397*22dc650dSSadaf Ebrahimi 
2398*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_U16:
2399*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, SLJIT_MOV_U16, ALLOW_ANY_IMM | HALF_SIZE, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_u16)srcw : srcw);
2400*22dc650dSSadaf Ebrahimi 
2401*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_S16:
2402*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, SLJIT_MOV_S16, ALLOW_ANY_IMM | SIGNED | HALF_SIZE, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_s16)srcw : srcw);
2403*22dc650dSSadaf Ebrahimi 
2404*22dc650dSSadaf Ebrahimi 	case SLJIT_CLZ:
2405*22dc650dSSadaf Ebrahimi 	case SLJIT_CTZ:
2406*22dc650dSSadaf Ebrahimi 	case SLJIT_REV:
2407*22dc650dSSadaf Ebrahimi 	case SLJIT_REV_U32:
2408*22dc650dSSadaf Ebrahimi 	case SLJIT_REV_S32:
2409*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src, srcw);
2410*22dc650dSSadaf Ebrahimi 
2411*22dc650dSSadaf Ebrahimi 	case SLJIT_REV_U16:
2412*22dc650dSSadaf Ebrahimi 	case SLJIT_REV_S16:
2413*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, op, HALF_SIZE, dst, dstw, TMP_REG1, 0, src, srcw);
2414*22dc650dSSadaf Ebrahimi 	}
2415*22dc650dSSadaf Ebrahimi 
2416*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
2417*22dc650dSSadaf Ebrahimi }
2418*22dc650dSSadaf Ebrahimi 
sljit_emit_op2(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2,sljit_sw src2w)2419*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
2420*22dc650dSSadaf Ebrahimi 	sljit_s32 dst, sljit_sw dstw,
2421*22dc650dSSadaf Ebrahimi 	sljit_s32 src1, sljit_sw src1w,
2422*22dc650dSSadaf Ebrahimi 	sljit_s32 src2, sljit_sw src2w)
2423*22dc650dSSadaf Ebrahimi {
2424*22dc650dSSadaf Ebrahimi 	sljit_s32 inp_flags;
2425*22dc650dSSadaf Ebrahimi 
2426*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2427*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));
2428*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(dst, dstw);
2429*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(src1, src1w);
2430*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(src2, src2w);
2431*22dc650dSSadaf Ebrahimi 
2432*22dc650dSSadaf Ebrahimi 	switch (GET_OPCODE(op)) {
2433*22dc650dSSadaf Ebrahimi 	case SLJIT_ADD:
2434*22dc650dSSadaf Ebrahimi 	case SLJIT_ADDC:
2435*22dc650dSSadaf Ebrahimi 	case SLJIT_SUB:
2436*22dc650dSSadaf Ebrahimi 	case SLJIT_SUBC:
2437*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, op, ALLOW_IMM | ALLOW_NEG_IMM | ALLOW_DOUBLE_IMM, dst, dstw, src1, src1w, src2, src2w);
2438*22dc650dSSadaf Ebrahimi 
2439*22dc650dSSadaf Ebrahimi 	case SLJIT_OR:
2440*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, op, ALLOW_IMM | ALLOW_DOUBLE_IMM, dst, dstw, src1, src1w, src2, src2w);
2441*22dc650dSSadaf Ebrahimi 
2442*22dc650dSSadaf Ebrahimi 	case SLJIT_XOR:
2443*22dc650dSSadaf Ebrahimi 		inp_flags = ALLOW_IMM | ALLOW_DOUBLE_IMM;
2444*22dc650dSSadaf Ebrahimi 		if ((src1 == SLJIT_IMM && src1w == -1) || (src2 == SLJIT_IMM && src2w == -1)) {
2445*22dc650dSSadaf Ebrahimi 			inp_flags |= ALLOW_INV_IMM;
2446*22dc650dSSadaf Ebrahimi 		}
2447*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, op, inp_flags, dst, dstw, src1, src1w, src2, src2w);
2448*22dc650dSSadaf Ebrahimi 
2449*22dc650dSSadaf Ebrahimi 	case SLJIT_MUL:
2450*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w);
2451*22dc650dSSadaf Ebrahimi 
2452*22dc650dSSadaf Ebrahimi 	case SLJIT_AND:
2453*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, op, ALLOW_ANY_IMM, dst, dstw, src1, src1w, src2, src2w);
2454*22dc650dSSadaf Ebrahimi 
2455*22dc650dSSadaf Ebrahimi 	case SLJIT_SHL:
2456*22dc650dSSadaf Ebrahimi 	case SLJIT_MSHL:
2457*22dc650dSSadaf Ebrahimi 	case SLJIT_LSHR:
2458*22dc650dSSadaf Ebrahimi 	case SLJIT_MLSHR:
2459*22dc650dSSadaf Ebrahimi 	case SLJIT_ASHR:
2460*22dc650dSSadaf Ebrahimi 	case SLJIT_MASHR:
2461*22dc650dSSadaf Ebrahimi 	case SLJIT_ROTL:
2462*22dc650dSSadaf Ebrahimi 	case SLJIT_ROTR:
2463*22dc650dSSadaf Ebrahimi 		if (src2 == SLJIT_IMM) {
2464*22dc650dSSadaf Ebrahimi 			compiler->shift_imm = src2w & 0x1f;
2465*22dc650dSSadaf Ebrahimi 			return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src1, src1w);
2466*22dc650dSSadaf Ebrahimi 		} else {
2467*22dc650dSSadaf Ebrahimi 			compiler->shift_imm = 0x20;
2468*22dc650dSSadaf Ebrahimi 			return emit_op(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w);
2469*22dc650dSSadaf Ebrahimi 		}
2470*22dc650dSSadaf Ebrahimi 	}
2471*22dc650dSSadaf Ebrahimi 
2472*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
2473*22dc650dSSadaf Ebrahimi }
2474*22dc650dSSadaf Ebrahimi 
sljit_emit_op2u(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2,sljit_sw src2w)2475*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,
2476*22dc650dSSadaf Ebrahimi 	sljit_s32 src1, sljit_sw src1w,
2477*22dc650dSSadaf Ebrahimi 	sljit_s32 src2, sljit_sw src2w)
2478*22dc650dSSadaf Ebrahimi {
2479*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2480*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
2481*22dc650dSSadaf Ebrahimi 
2482*22dc650dSSadaf Ebrahimi 	SLJIT_SKIP_CHECKS(compiler);
2483*22dc650dSSadaf Ebrahimi 	return sljit_emit_op2(compiler, op, TMP_REG1, 0, src1, src1w, src2, src2w);
2484*22dc650dSSadaf Ebrahimi }
2485*22dc650dSSadaf Ebrahimi 
sljit_emit_op2r(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst_reg,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2,sljit_sw src2w)2486*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2r(struct sljit_compiler *compiler, sljit_s32 op,
2487*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_reg,
2488*22dc650dSSadaf Ebrahimi 	sljit_s32 src1, sljit_sw src1w,
2489*22dc650dSSadaf Ebrahimi 	sljit_s32 src2, sljit_sw src2w)
2490*22dc650dSSadaf Ebrahimi {
2491*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2492*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_op2r(compiler, op, dst_reg, src1, src1w, src2, src2w));
2493*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(src1, src1w);
2494*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(src2, src2w);
2495*22dc650dSSadaf Ebrahimi 
2496*22dc650dSSadaf Ebrahimi 	switch (GET_OPCODE(op)) {
2497*22dc650dSSadaf Ebrahimi 	case SLJIT_MULADD:
2498*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, op, 0, dst_reg, 0, src1, src1w, src2, src2w);
2499*22dc650dSSadaf Ebrahimi 	}
2500*22dc650dSSadaf Ebrahimi 
2501*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
2502*22dc650dSSadaf Ebrahimi }
2503*22dc650dSSadaf Ebrahimi 
sljit_emit_shift_into(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst_reg,sljit_s32 src1_reg,sljit_s32 src2_reg,sljit_s32 src3,sljit_sw src3w)2504*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op,
2505*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_reg,
2506*22dc650dSSadaf Ebrahimi 	sljit_s32 src1_reg,
2507*22dc650dSSadaf Ebrahimi 	sljit_s32 src2_reg,
2508*22dc650dSSadaf Ebrahimi 	sljit_s32 src3, sljit_sw src3w)
2509*22dc650dSSadaf Ebrahimi {
2510*22dc650dSSadaf Ebrahimi 	sljit_s32 is_left;
2511*22dc650dSSadaf Ebrahimi 
2512*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2513*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w));
2514*22dc650dSSadaf Ebrahimi 
2515*22dc650dSSadaf Ebrahimi 	op = GET_OPCODE(op);
2516*22dc650dSSadaf Ebrahimi 	is_left = (op == SLJIT_SHL || op == SLJIT_MSHL);
2517*22dc650dSSadaf Ebrahimi 
2518*22dc650dSSadaf Ebrahimi 	if (src1_reg == src2_reg) {
2519*22dc650dSSadaf Ebrahimi 		SLJIT_SKIP_CHECKS(compiler);
2520*22dc650dSSadaf Ebrahimi 		return sljit_emit_op2(compiler, is_left ? SLJIT_ROTL : SLJIT_ROTR, dst_reg, 0, src1_reg, 0, src3, src3w);
2521*22dc650dSSadaf Ebrahimi 	}
2522*22dc650dSSadaf Ebrahimi 
2523*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(src3, src3w);
2524*22dc650dSSadaf Ebrahimi 
2525*22dc650dSSadaf Ebrahimi 	/* Shift type of ROR is 3. */
2526*22dc650dSSadaf Ebrahimi 	if (src3 == SLJIT_IMM) {
2527*22dc650dSSadaf Ebrahimi 		src3w &= 0x1f;
2528*22dc650dSSadaf Ebrahimi 
2529*22dc650dSSadaf Ebrahimi 		if (src3w == 0)
2530*22dc650dSSadaf Ebrahimi 			return SLJIT_SUCCESS;
2531*22dc650dSSadaf Ebrahimi 
2532*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, MOV | RD(dst_reg) | RM(src1_reg) | ((sljit_ins)(is_left ? 0 : 1) << 5) | ((sljit_ins)src3w << 7)));
2533*22dc650dSSadaf Ebrahimi 		src3w = (src3w ^ 0x1f) + 1;
2534*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, ORR | RD(dst_reg) | RN(dst_reg) | RM(src2_reg) | ((sljit_ins)(is_left ? 1 : 0) << 5) | ((sljit_ins)src3w << 7));
2535*22dc650dSSadaf Ebrahimi 	}
2536*22dc650dSSadaf Ebrahimi 
2537*22dc650dSSadaf Ebrahimi 	if (src3 & SLJIT_MEM) {
2538*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, src3, src3w, TMP_REG2));
2539*22dc650dSSadaf Ebrahimi 		src3 = TMP_REG2;
2540*22dc650dSSadaf Ebrahimi 	}
2541*22dc650dSSadaf Ebrahimi 
2542*22dc650dSSadaf Ebrahimi 	if (op == SLJIT_MSHL || op == SLJIT_MLSHR || dst_reg == src3) {
2543*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, AND | SRC2_IMM | RD(TMP_REG2) | RN(src3) | 0x1f));
2544*22dc650dSSadaf Ebrahimi 		src3 = TMP_REG2;
2545*22dc650dSSadaf Ebrahimi 	}
2546*22dc650dSSadaf Ebrahimi 
2547*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, MOV | RD(dst_reg) | RM8(src3) | ((sljit_ins)(is_left ? 0 : 1) << 5) | 0x10 | RM(src1_reg)));
2548*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | RM(src2_reg) | ((sljit_ins)(is_left ? 1 : 0) << 5) | (1 << 7)));
2549*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, EOR | SRC2_IMM | RD(TMP_REG2) | RN(src3) | 0x1f));
2550*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, ORR | RD(dst_reg) | RN(dst_reg) | RM8(TMP_REG2) | ((sljit_ins)(is_left ? 1 : 0) << 5) | 0x10 | RM(TMP_REG1));
2551*22dc650dSSadaf Ebrahimi }
2552*22dc650dSSadaf Ebrahimi 
sljit_emit_op_src(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 src,sljit_sw srcw)2553*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
2554*22dc650dSSadaf Ebrahimi 	sljit_s32 src, sljit_sw srcw)
2555*22dc650dSSadaf Ebrahimi {
2556*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2557*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));
2558*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(src, srcw);
2559*22dc650dSSadaf Ebrahimi 
2560*22dc650dSSadaf Ebrahimi 	switch (op) {
2561*22dc650dSSadaf Ebrahimi 	case SLJIT_FAST_RETURN:
2562*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(reg_map[TMP_REG2] == 14);
2563*22dc650dSSadaf Ebrahimi 
2564*22dc650dSSadaf Ebrahimi 		if (FAST_IS_REG(src))
2565*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG2) | RM(src)));
2566*22dc650dSSadaf Ebrahimi 		else
2567*22dc650dSSadaf Ebrahimi 			FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, src, srcw, TMP_REG1));
2568*22dc650dSSadaf Ebrahimi 
2569*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, BX | RM(TMP_REG2));
2570*22dc650dSSadaf Ebrahimi 	case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:
2571*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
2572*22dc650dSSadaf Ebrahimi 	case SLJIT_PREFETCH_L1:
2573*22dc650dSSadaf Ebrahimi 	case SLJIT_PREFETCH_L2:
2574*22dc650dSSadaf Ebrahimi 	case SLJIT_PREFETCH_L3:
2575*22dc650dSSadaf Ebrahimi 	case SLJIT_PREFETCH_ONCE:
2576*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(src & SLJIT_MEM);
2577*22dc650dSSadaf Ebrahimi 		return emit_op_mem(compiler, PRELOAD | LOAD_DATA, TMP_PC, src, srcw, TMP_REG1);
2578*22dc650dSSadaf Ebrahimi 	}
2579*22dc650dSSadaf Ebrahimi 
2580*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
2581*22dc650dSSadaf Ebrahimi }
2582*22dc650dSSadaf Ebrahimi 
sljit_emit_op_dst(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw)2583*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op,
2584*22dc650dSSadaf Ebrahimi 	sljit_s32 dst, sljit_sw dstw)
2585*22dc650dSSadaf Ebrahimi {
2586*22dc650dSSadaf Ebrahimi 	sljit_s32 size, dst_r;
2587*22dc650dSSadaf Ebrahimi 
2588*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2589*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw));
2590*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(dst, dstw);
2591*22dc650dSSadaf Ebrahimi 
2592*22dc650dSSadaf Ebrahimi 	switch (op) {
2593*22dc650dSSadaf Ebrahimi 	case SLJIT_FAST_ENTER:
2594*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(reg_map[TMP_REG2] == 14);
2595*22dc650dSSadaf Ebrahimi 
2596*22dc650dSSadaf Ebrahimi 		if (FAST_IS_REG(dst))
2597*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, MOV | RD(dst) | RM(TMP_REG2));
2598*22dc650dSSadaf Ebrahimi 		break;
2599*22dc650dSSadaf Ebrahimi 	case SLJIT_GET_RETURN_ADDRESS:
2600*22dc650dSSadaf Ebrahimi 		size = GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds - SLJIT_KEPT_SAVEDS_COUNT(compiler->options), 0);
2601*22dc650dSSadaf Ebrahimi 
2602*22dc650dSSadaf Ebrahimi 		if (compiler->fsaveds > 0 || compiler->fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
2603*22dc650dSSadaf Ebrahimi 			/* The size of pc is not added above. */
2604*22dc650dSSadaf Ebrahimi 			if ((size & SSIZE_OF(sw)) == 0)
2605*22dc650dSSadaf Ebrahimi 				size += SSIZE_OF(sw);
2606*22dc650dSSadaf Ebrahimi 
2607*22dc650dSSadaf Ebrahimi 			size += GET_SAVED_FLOAT_REGISTERS_SIZE(compiler->fscratches, compiler->fsaveds, f64);
2608*22dc650dSSadaf Ebrahimi 		}
2609*22dc650dSSadaf Ebrahimi 
2610*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(((compiler->local_size + size + SSIZE_OF(sw)) & 0x7) == 0);
2611*22dc650dSSadaf Ebrahimi 
2612*22dc650dSSadaf Ebrahimi 		dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
2613*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, dst_r, SLJIT_MEM1(SLJIT_SP), compiler->local_size + size, TMP_REG1));
2614*22dc650dSSadaf Ebrahimi 		break;
2615*22dc650dSSadaf Ebrahimi 	}
2616*22dc650dSSadaf Ebrahimi 
2617*22dc650dSSadaf Ebrahimi 	if (dst & SLJIT_MEM)
2618*22dc650dSSadaf Ebrahimi 		return emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1);
2619*22dc650dSSadaf Ebrahimi 
2620*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
2621*22dc650dSSadaf Ebrahimi }
2622*22dc650dSSadaf Ebrahimi 
sljit_get_register_index(sljit_s32 type,sljit_s32 reg)2623*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg)
2624*22dc650dSSadaf Ebrahimi {
2625*22dc650dSSadaf Ebrahimi 	CHECK_REG_INDEX(check_sljit_get_register_index(type, reg));
2626*22dc650dSSadaf Ebrahimi 
2627*22dc650dSSadaf Ebrahimi 	if (type == SLJIT_GP_REGISTER)
2628*22dc650dSSadaf Ebrahimi 		return reg_map[reg];
2629*22dc650dSSadaf Ebrahimi 
2630*22dc650dSSadaf Ebrahimi 	if (type == SLJIT_FLOAT_REGISTER || type == SLJIT_SIMD_REG_64)
2631*22dc650dSSadaf Ebrahimi 		return freg_map[reg];
2632*22dc650dSSadaf Ebrahimi 
2633*22dc650dSSadaf Ebrahimi 	if (type != SLJIT_SIMD_REG_128)
2634*22dc650dSSadaf Ebrahimi 		return freg_map[reg] & ~0x1;
2635*22dc650dSSadaf Ebrahimi 
2636*22dc650dSSadaf Ebrahimi 	return -1;
2637*22dc650dSSadaf Ebrahimi }
2638*22dc650dSSadaf Ebrahimi 
sljit_emit_op_custom(struct sljit_compiler * compiler,void * instruction,sljit_u32 size)2639*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
2640*22dc650dSSadaf Ebrahimi 	void *instruction, sljit_u32 size)
2641*22dc650dSSadaf Ebrahimi {
2642*22dc650dSSadaf Ebrahimi 	SLJIT_UNUSED_ARG(size);
2643*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2644*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
2645*22dc650dSSadaf Ebrahimi 
2646*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, *(sljit_ins*)instruction);
2647*22dc650dSSadaf Ebrahimi }
2648*22dc650dSSadaf Ebrahimi 
2649*22dc650dSSadaf Ebrahimi /* --------------------------------------------------------------------- */
2650*22dc650dSSadaf Ebrahimi /*  Floating point operators                                             */
2651*22dc650dSSadaf Ebrahimi /* --------------------------------------------------------------------- */
2652*22dc650dSSadaf Ebrahimi 
2653*22dc650dSSadaf Ebrahimi #define FPU_LOAD (1 << 20)
2654*22dc650dSSadaf Ebrahimi #define EMIT_FPU_DATA_TRANSFER(inst, add, base, freg, offs) \
2655*22dc650dSSadaf Ebrahimi 	((inst) | (sljit_ins)((add) << 23) | RN(base) | VD(freg) | (sljit_ins)(offs))
2656*22dc650dSSadaf Ebrahimi 
emit_fop_mem(struct sljit_compiler * compiler,sljit_s32 flags,sljit_s32 reg,sljit_s32 arg,sljit_sw argw)2657*22dc650dSSadaf Ebrahimi static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
2658*22dc650dSSadaf Ebrahimi {
2659*22dc650dSSadaf Ebrahimi 	sljit_uw imm;
2660*22dc650dSSadaf Ebrahimi 	sljit_ins inst = VSTR_F32 | (flags & (SLJIT_32 | FPU_LOAD));
2661*22dc650dSSadaf Ebrahimi 
2662*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(arg & SLJIT_MEM);
2663*22dc650dSSadaf Ebrahimi 	arg &= ~SLJIT_MEM;
2664*22dc650dSSadaf Ebrahimi 
2665*22dc650dSSadaf Ebrahimi 	if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
2666*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | (((sljit_ins)argw & 0x3) << 7)));
2667*22dc650dSSadaf Ebrahimi 		arg = TMP_REG1;
2668*22dc650dSSadaf Ebrahimi 		argw = 0;
2669*22dc650dSSadaf Ebrahimi 	}
2670*22dc650dSSadaf Ebrahimi 
2671*22dc650dSSadaf Ebrahimi 	/* Fast loads and stores. */
2672*22dc650dSSadaf Ebrahimi 	if (arg) {
2673*22dc650dSSadaf Ebrahimi 		if (!(argw & ~0x3fc))
2674*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, arg & REG_MASK, reg, argw >> 2));
2675*22dc650dSSadaf Ebrahimi 		if (!(-argw & ~0x3fc))
2676*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, arg & REG_MASK, reg, (-argw) >> 2));
2677*22dc650dSSadaf Ebrahimi 
2678*22dc650dSSadaf Ebrahimi 		imm = get_imm((sljit_uw)argw & ~(sljit_uw)0x3fc);
2679*22dc650dSSadaf Ebrahimi 		if (imm) {
2680*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RN(arg & REG_MASK) | imm));
2681*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG1, reg, (argw & 0x3fc) >> 2));
2682*22dc650dSSadaf Ebrahimi 		}
2683*22dc650dSSadaf Ebrahimi 		imm = get_imm((sljit_uw)-argw & ~(sljit_uw)0x3fc);
2684*22dc650dSSadaf Ebrahimi 		if (imm) {
2685*22dc650dSSadaf Ebrahimi 			argw = -argw;
2686*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, SUB | RD(TMP_REG1) | RN(arg & REG_MASK) | imm));
2687*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, TMP_REG1, reg, (argw & 0x3fc) >> 2));
2688*22dc650dSSadaf Ebrahimi 		}
2689*22dc650dSSadaf Ebrahimi 	}
2690*22dc650dSSadaf Ebrahimi 
2691*22dc650dSSadaf Ebrahimi 	if (arg) {
2692*22dc650dSSadaf Ebrahimi 		FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)argw));
2693*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RN(arg & REG_MASK) | RM(TMP_REG1)));
2694*22dc650dSSadaf Ebrahimi 	}
2695*22dc650dSSadaf Ebrahimi 	else
2696*22dc650dSSadaf Ebrahimi 		FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)argw));
2697*22dc650dSSadaf Ebrahimi 
2698*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG1, reg, 0));
2699*22dc650dSSadaf Ebrahimi }
2700*22dc650dSSadaf Ebrahimi 
sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 src,sljit_sw srcw)2701*22dc650dSSadaf Ebrahimi static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
2702*22dc650dSSadaf Ebrahimi 	sljit_s32 dst, sljit_sw dstw,
2703*22dc650dSSadaf Ebrahimi 	sljit_s32 src, sljit_sw srcw)
2704*22dc650dSSadaf Ebrahimi {
2705*22dc650dSSadaf Ebrahimi 	op ^= SLJIT_32;
2706*22dc650dSSadaf Ebrahimi 
2707*22dc650dSSadaf Ebrahimi 	if (src & SLJIT_MEM) {
2708*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG1, src, srcw));
2709*22dc650dSSadaf Ebrahimi 		src = TMP_FREG1;
2710*22dc650dSSadaf Ebrahimi 	}
2711*22dc650dSSadaf Ebrahimi 
2712*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_S32_F32, op & SLJIT_32, TMP_FREG1, src, 0)));
2713*22dc650dSSadaf Ebrahimi 
2714*22dc650dSSadaf Ebrahimi 	if (FAST_IS_REG(dst))
2715*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, VMOV | (1 << 20) | RD(dst) | VN(TMP_FREG1));
2716*22dc650dSSadaf Ebrahimi 
2717*22dc650dSSadaf Ebrahimi 	/* Store the integer value from a VFP register. */
2718*22dc650dSSadaf Ebrahimi 	return emit_fop_mem(compiler, 0, TMP_FREG1, dst, dstw);
2719*22dc650dSSadaf Ebrahimi }
2720*22dc650dSSadaf Ebrahimi 
sljit_emit_fop1_conv_f64_from_w(struct sljit_compiler * compiler,sljit_ins ins,sljit_s32 dst,sljit_sw dstw,sljit_s32 src,sljit_sw srcw)2721*22dc650dSSadaf Ebrahimi static sljit_s32 sljit_emit_fop1_conv_f64_from_w(struct sljit_compiler *compiler, sljit_ins ins,
2722*22dc650dSSadaf Ebrahimi 	sljit_s32 dst, sljit_sw dstw,
2723*22dc650dSSadaf Ebrahimi 	sljit_s32 src, sljit_sw srcw)
2724*22dc650dSSadaf Ebrahimi {
2725*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
2726*22dc650dSSadaf Ebrahimi 
2727*22dc650dSSadaf Ebrahimi 	if (FAST_IS_REG(src))
2728*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, VMOV | RD(src) | VN(TMP_FREG1)));
2729*22dc650dSSadaf Ebrahimi 	else if (src & SLJIT_MEM) {
2730*22dc650dSSadaf Ebrahimi 		/* Load the integer value into a VFP register. */
2731*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_fop_mem(compiler, FPU_LOAD, TMP_FREG1, src, srcw));
2732*22dc650dSSadaf Ebrahimi 	}
2733*22dc650dSSadaf Ebrahimi 	else {
2734*22dc650dSSadaf Ebrahimi 		FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)srcw));
2735*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, VMOV | RD(TMP_REG1) | VN(TMP_FREG1)));
2736*22dc650dSSadaf Ebrahimi 	}
2737*22dc650dSSadaf Ebrahimi 
2738*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(ins, ins & SLJIT_32, dst_r, TMP_FREG1, 0)));
2739*22dc650dSSadaf Ebrahimi 
2740*22dc650dSSadaf Ebrahimi 	if (dst & SLJIT_MEM)
2741*22dc650dSSadaf Ebrahimi 		return emit_fop_mem(compiler, (ins & SLJIT_32), TMP_FREG1, dst, dstw);
2742*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
2743*22dc650dSSadaf Ebrahimi }
2744*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)2745*22dc650dSSadaf Ebrahimi static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
2746*22dc650dSSadaf Ebrahimi 	sljit_s32 dst, sljit_sw dstw,
2747*22dc650dSSadaf Ebrahimi 	sljit_s32 src, sljit_sw srcw)
2748*22dc650dSSadaf Ebrahimi {
2749*22dc650dSSadaf Ebrahimi 	return sljit_emit_fop1_conv_f64_from_w(compiler, VCVT_F32_S32 | (~op & SLJIT_32), dst, dstw, src, srcw);
2750*22dc650dSSadaf Ebrahimi }
2751*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)2752*22dc650dSSadaf Ebrahimi static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op,
2753*22dc650dSSadaf Ebrahimi 	sljit_s32 dst, sljit_sw dstw,
2754*22dc650dSSadaf Ebrahimi 	sljit_s32 src, sljit_sw srcw)
2755*22dc650dSSadaf Ebrahimi {
2756*22dc650dSSadaf Ebrahimi 	return sljit_emit_fop1_conv_f64_from_w(compiler, VCVT_F32_U32 | (~op & SLJIT_32), dst, dstw, src, srcw);
2757*22dc650dSSadaf Ebrahimi }
2758*22dc650dSSadaf Ebrahimi 
sljit_emit_fop1_cmp(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2,sljit_sw src2w)2759*22dc650dSSadaf Ebrahimi static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
2760*22dc650dSSadaf Ebrahimi 	sljit_s32 src1, sljit_sw src1w,
2761*22dc650dSSadaf Ebrahimi 	sljit_s32 src2, sljit_sw src2w)
2762*22dc650dSSadaf Ebrahimi {
2763*22dc650dSSadaf Ebrahimi 	op ^= SLJIT_32;
2764*22dc650dSSadaf Ebrahimi 
2765*22dc650dSSadaf Ebrahimi 	if (src1 & SLJIT_MEM) {
2766*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG1, src1, src1w));
2767*22dc650dSSadaf Ebrahimi 		src1 = TMP_FREG1;
2768*22dc650dSSadaf Ebrahimi 	}
2769*22dc650dSSadaf Ebrahimi 
2770*22dc650dSSadaf Ebrahimi 	if (src2 & SLJIT_MEM) {
2771*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG2, src2, src2w));
2772*22dc650dSSadaf Ebrahimi 		src2 = TMP_FREG2;
2773*22dc650dSSadaf Ebrahimi 	}
2774*22dc650dSSadaf Ebrahimi 
2775*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCMP_F32, op & SLJIT_32, src1, src2, 0)));
2776*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, VMRS));
2777*22dc650dSSadaf Ebrahimi 
2778*22dc650dSSadaf Ebrahimi 	if (GET_FLAG_TYPE(op) != SLJIT_UNORDERED_OR_EQUAL)
2779*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
2780*22dc650dSSadaf Ebrahimi 
2781*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, (CMP - CONDITIONAL) | (0x60000000 /* VS */) | SET_FLAGS | RN(TMP_REG1) | RM(TMP_REG1));
2782*22dc650dSSadaf Ebrahimi }
2783*22dc650dSSadaf Ebrahimi 
sljit_emit_fop1(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 src,sljit_sw srcw)2784*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
2785*22dc650dSSadaf Ebrahimi 	sljit_s32 dst, sljit_sw dstw,
2786*22dc650dSSadaf Ebrahimi 	sljit_s32 src, sljit_sw srcw)
2787*22dc650dSSadaf Ebrahimi {
2788*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_r;
2789*22dc650dSSadaf Ebrahimi 
2790*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2791*22dc650dSSadaf Ebrahimi 
2792*22dc650dSSadaf Ebrahimi 	SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100), float_transfer_bit_error);
2793*22dc650dSSadaf Ebrahimi 	SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
2794*22dc650dSSadaf Ebrahimi 
2795*22dc650dSSadaf Ebrahimi 	dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
2796*22dc650dSSadaf Ebrahimi 
2797*22dc650dSSadaf Ebrahimi 	if (GET_OPCODE(op) != SLJIT_CONV_F64_FROM_F32)
2798*22dc650dSSadaf Ebrahimi 		op ^= SLJIT_32;
2799*22dc650dSSadaf Ebrahimi 
2800*22dc650dSSadaf Ebrahimi 	if (src & SLJIT_MEM) {
2801*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, dst_r, src, srcw));
2802*22dc650dSSadaf Ebrahimi 		src = dst_r;
2803*22dc650dSSadaf Ebrahimi 	}
2804*22dc650dSSadaf Ebrahimi 
2805*22dc650dSSadaf Ebrahimi 	switch (GET_OPCODE(op)) {
2806*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_F64:
2807*22dc650dSSadaf Ebrahimi 		if (src != dst_r) {
2808*22dc650dSSadaf Ebrahimi 			if (!(dst & SLJIT_MEM))
2809*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32, op & SLJIT_32, dst_r, src, 0)));
2810*22dc650dSSadaf Ebrahimi 			else
2811*22dc650dSSadaf Ebrahimi 				dst_r = src;
2812*22dc650dSSadaf Ebrahimi 		}
2813*22dc650dSSadaf Ebrahimi 		break;
2814*22dc650dSSadaf Ebrahimi 	case SLJIT_NEG_F64:
2815*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VNEG_F32, op & SLJIT_32, dst_r, src, 0)));
2816*22dc650dSSadaf Ebrahimi 		break;
2817*22dc650dSSadaf Ebrahimi 	case SLJIT_ABS_F64:
2818*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VABS_F32, op & SLJIT_32, dst_r, src, 0)));
2819*22dc650dSSadaf Ebrahimi 		break;
2820*22dc650dSSadaf Ebrahimi 	case SLJIT_CONV_F64_FROM_F32:
2821*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_F64_F32, op & SLJIT_32, dst_r, src, 0)));
2822*22dc650dSSadaf Ebrahimi 		op ^= SLJIT_32;
2823*22dc650dSSadaf Ebrahimi 		break;
2824*22dc650dSSadaf Ebrahimi 	}
2825*22dc650dSSadaf Ebrahimi 
2826*22dc650dSSadaf Ebrahimi 	if (dst & SLJIT_MEM)
2827*22dc650dSSadaf Ebrahimi 		return emit_fop_mem(compiler, (op & SLJIT_32), dst_r, dst, dstw);
2828*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
2829*22dc650dSSadaf Ebrahimi }
2830*22dc650dSSadaf Ebrahimi 
sljit_emit_fop2(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2,sljit_sw src2w)2831*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
2832*22dc650dSSadaf Ebrahimi 	sljit_s32 dst, sljit_sw dstw,
2833*22dc650dSSadaf Ebrahimi 	sljit_s32 src1, sljit_sw src1w,
2834*22dc650dSSadaf Ebrahimi 	sljit_s32 src2, sljit_sw src2w)
2835*22dc650dSSadaf Ebrahimi {
2836*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_r;
2837*22dc650dSSadaf Ebrahimi 
2838*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2839*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
2840*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(dst, dstw);
2841*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(src1, src1w);
2842*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(src2, src2w);
2843*22dc650dSSadaf Ebrahimi 
2844*22dc650dSSadaf Ebrahimi 	op ^= SLJIT_32;
2845*22dc650dSSadaf Ebrahimi 
2846*22dc650dSSadaf Ebrahimi 	dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
2847*22dc650dSSadaf Ebrahimi 
2848*22dc650dSSadaf Ebrahimi 	if (src2 & SLJIT_MEM) {
2849*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG2, src2, src2w));
2850*22dc650dSSadaf Ebrahimi 		src2 = TMP_FREG2;
2851*22dc650dSSadaf Ebrahimi 	}
2852*22dc650dSSadaf Ebrahimi 
2853*22dc650dSSadaf Ebrahimi 	if (src1 & SLJIT_MEM) {
2854*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG1, src1, src1w));
2855*22dc650dSSadaf Ebrahimi 		src1 = TMP_FREG1;
2856*22dc650dSSadaf Ebrahimi 	}
2857*22dc650dSSadaf Ebrahimi 
2858*22dc650dSSadaf Ebrahimi 	switch (GET_OPCODE(op)) {
2859*22dc650dSSadaf Ebrahimi 	case SLJIT_ADD_F64:
2860*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VADD_F32, op & SLJIT_32, dst_r, src2, src1)));
2861*22dc650dSSadaf Ebrahimi 		break;
2862*22dc650dSSadaf Ebrahimi 	case SLJIT_SUB_F64:
2863*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VSUB_F32, op & SLJIT_32, dst_r, src2, src1)));
2864*22dc650dSSadaf Ebrahimi 		break;
2865*22dc650dSSadaf Ebrahimi 	case SLJIT_MUL_F64:
2866*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMUL_F32, op & SLJIT_32, dst_r, src2, src1)));
2867*22dc650dSSadaf Ebrahimi 		break;
2868*22dc650dSSadaf Ebrahimi 	case SLJIT_DIV_F64:
2869*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VDIV_F32, op & SLJIT_32, dst_r, src2, src1)));
2870*22dc650dSSadaf Ebrahimi 		break;
2871*22dc650dSSadaf Ebrahimi 	case SLJIT_COPYSIGN_F64:
2872*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, VMOV | (1 << 20) | VN(src2) | RD(TMP_REG1) | ((op & SLJIT_32) ? (1 << 7) : 0)));
2873*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VABS_F32, op & SLJIT_32, dst_r, src1, 0)));
2874*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, CMP | SET_FLAGS | RN(TMP_REG1) | SRC2_IMM | 0));
2875*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, EMIT_FPU_OPERATION((VNEG_F32 & ~COND_MASK) | 0xb0000000, op & SLJIT_32, dst_r, dst_r, 0));
2876*22dc650dSSadaf Ebrahimi 	}
2877*22dc650dSSadaf Ebrahimi 
2878*22dc650dSSadaf Ebrahimi 	if (dst_r != dst)
2879*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32), TMP_FREG1, dst, dstw));
2880*22dc650dSSadaf Ebrahimi 
2881*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
2882*22dc650dSSadaf Ebrahimi }
2883*22dc650dSSadaf Ebrahimi 
2884*22dc650dSSadaf Ebrahimi #undef EMIT_FPU_DATA_TRANSFER
2885*22dc650dSSadaf Ebrahimi 
sljit_emit_fset32(struct sljit_compiler * compiler,sljit_s32 freg,sljit_f32 value)2886*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler,
2887*22dc650dSSadaf Ebrahimi 	sljit_s32 freg, sljit_f32 value)
2888*22dc650dSSadaf Ebrahimi {
2889*22dc650dSSadaf Ebrahimi #if defined(__ARM_NEON) && __ARM_NEON
2890*22dc650dSSadaf Ebrahimi 	sljit_u32 exp;
2891*22dc650dSSadaf Ebrahimi 	sljit_ins ins;
2892*22dc650dSSadaf Ebrahimi #endif /* NEON */
2893*22dc650dSSadaf Ebrahimi 	union {
2894*22dc650dSSadaf Ebrahimi 		sljit_u32 imm;
2895*22dc650dSSadaf Ebrahimi 		sljit_f32 value;
2896*22dc650dSSadaf Ebrahimi 	} u;
2897*22dc650dSSadaf Ebrahimi 
2898*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2899*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_fset32(compiler, freg, value));
2900*22dc650dSSadaf Ebrahimi 
2901*22dc650dSSadaf Ebrahimi 	u.value = value;
2902*22dc650dSSadaf Ebrahimi 
2903*22dc650dSSadaf Ebrahimi #if defined(__ARM_NEON) && __ARM_NEON
2904*22dc650dSSadaf Ebrahimi 	if ((u.imm << (32 - 19)) == 0) {
2905*22dc650dSSadaf Ebrahimi 		exp = (u.imm >> (23 + 2)) & 0x3f;
2906*22dc650dSSadaf Ebrahimi 
2907*22dc650dSSadaf Ebrahimi 		if (exp == 0x20 || exp == 0x1f) {
2908*22dc650dSSadaf Ebrahimi 			ins = ((u.imm >> 24) & 0x80) | ((u.imm >> 19) & 0x7f);
2909*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, (VMOV_F32 ^ (1 << 6)) | ((ins & 0xf0) << 12) | VD(freg) | (ins & 0xf));
2910*22dc650dSSadaf Ebrahimi 		}
2911*22dc650dSSadaf Ebrahimi 	}
2912*22dc650dSSadaf Ebrahimi #endif /* NEON */
2913*22dc650dSSadaf Ebrahimi 
2914*22dc650dSSadaf Ebrahimi 	FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm));
2915*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, VMOV | VN(freg) | RD(TMP_REG1));
2916*22dc650dSSadaf Ebrahimi }
2917*22dc650dSSadaf Ebrahimi 
sljit_emit_fset64(struct sljit_compiler * compiler,sljit_s32 freg,sljit_f64 value)2918*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,
2919*22dc650dSSadaf Ebrahimi 	sljit_s32 freg, sljit_f64 value)
2920*22dc650dSSadaf Ebrahimi {
2921*22dc650dSSadaf Ebrahimi #if defined(__ARM_NEON) && __ARM_NEON
2922*22dc650dSSadaf Ebrahimi 	sljit_u32 exp;
2923*22dc650dSSadaf Ebrahimi 	sljit_ins ins;
2924*22dc650dSSadaf Ebrahimi #endif /* NEON */
2925*22dc650dSSadaf Ebrahimi 	union {
2926*22dc650dSSadaf Ebrahimi 		sljit_u32 imm[2];
2927*22dc650dSSadaf Ebrahimi 		sljit_f64 value;
2928*22dc650dSSadaf Ebrahimi 	} u;
2929*22dc650dSSadaf Ebrahimi 
2930*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2931*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_fset64(compiler, freg, value));
2932*22dc650dSSadaf Ebrahimi 
2933*22dc650dSSadaf Ebrahimi 	u.value = value;
2934*22dc650dSSadaf Ebrahimi 
2935*22dc650dSSadaf Ebrahimi #if defined(__ARM_NEON) && __ARM_NEON
2936*22dc650dSSadaf Ebrahimi 	if (u.imm[0] == 0 && (u.imm[1] << (64 - 48)) == 0) {
2937*22dc650dSSadaf Ebrahimi 		exp = (u.imm[1] >> ((52 - 32) + 2)) & 0x1ff;
2938*22dc650dSSadaf Ebrahimi 
2939*22dc650dSSadaf Ebrahimi 		if (exp == 0x100 || exp == 0xff) {
2940*22dc650dSSadaf Ebrahimi 			ins = ((u.imm[1] >> (56 - 32)) & 0x80) | ((u.imm[1] >> (48 - 32)) & 0x7f);
2941*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, (VMOV_F32 ^ (1 << 6)) | (1 << 8) | ((ins & 0xf0) << 12) | VD(freg) | (ins & 0xf));
2942*22dc650dSSadaf Ebrahimi 		}
2943*22dc650dSSadaf Ebrahimi 	}
2944*22dc650dSSadaf Ebrahimi #endif /* NEON */
2945*22dc650dSSadaf Ebrahimi 
2946*22dc650dSSadaf Ebrahimi 	FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm[0]));
2947*22dc650dSSadaf Ebrahimi 	if (u.imm[0] == u.imm[1])
2948*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, VMOV2 | RN(TMP_REG1) | RD(TMP_REG1) | VM(freg));
2949*22dc650dSSadaf Ebrahimi 
2950*22dc650dSSadaf Ebrahimi 	FAIL_IF(load_immediate(compiler, TMP_REG2, u.imm[1]));
2951*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, VMOV2 | RN(TMP_REG2) | RD(TMP_REG1) | VM(freg));
2952*22dc650dSSadaf Ebrahimi }
2953*22dc650dSSadaf Ebrahimi 
sljit_emit_fcopy(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 freg,sljit_s32 reg)2954*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,
2955*22dc650dSSadaf Ebrahimi 	sljit_s32 freg, sljit_s32 reg)
2956*22dc650dSSadaf Ebrahimi {
2957*22dc650dSSadaf Ebrahimi 	sljit_s32 reg2;
2958*22dc650dSSadaf Ebrahimi 	sljit_ins inst;
2959*22dc650dSSadaf Ebrahimi 
2960*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2961*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));
2962*22dc650dSSadaf Ebrahimi 
2963*22dc650dSSadaf Ebrahimi 	if (reg & REG_PAIR_MASK) {
2964*22dc650dSSadaf Ebrahimi 		reg2 = REG_PAIR_SECOND(reg);
2965*22dc650dSSadaf Ebrahimi 		reg = REG_PAIR_FIRST(reg);
2966*22dc650dSSadaf Ebrahimi 
2967*22dc650dSSadaf Ebrahimi 		inst = VMOV2 | RN(reg) | RD(reg2) | VM(freg);
2968*22dc650dSSadaf Ebrahimi 	} else {
2969*22dc650dSSadaf Ebrahimi 		inst = VMOV | VN(freg) | RD(reg);
2970*22dc650dSSadaf Ebrahimi 
2971*22dc650dSSadaf Ebrahimi 		if (!(op & SLJIT_32))
2972*22dc650dSSadaf Ebrahimi 			inst |= 1 << 7;
2973*22dc650dSSadaf Ebrahimi 	}
2974*22dc650dSSadaf Ebrahimi 
2975*22dc650dSSadaf Ebrahimi 	if (GET_OPCODE(op) == SLJIT_COPY_FROM_F64)
2976*22dc650dSSadaf Ebrahimi 		inst |= 1 << 20;
2977*22dc650dSSadaf Ebrahimi 
2978*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, inst);
2979*22dc650dSSadaf Ebrahimi }
2980*22dc650dSSadaf Ebrahimi 
2981*22dc650dSSadaf Ebrahimi /* --------------------------------------------------------------------- */
2982*22dc650dSSadaf Ebrahimi /*  Conditional instructions                                             */
2983*22dc650dSSadaf Ebrahimi /* --------------------------------------------------------------------- */
2984*22dc650dSSadaf Ebrahimi 
get_cc(struct sljit_compiler * compiler,sljit_s32 type)2985*22dc650dSSadaf Ebrahimi static sljit_ins get_cc(struct sljit_compiler *compiler, sljit_s32 type)
2986*22dc650dSSadaf Ebrahimi {
2987*22dc650dSSadaf Ebrahimi 	switch (type) {
2988*22dc650dSSadaf Ebrahimi 	case SLJIT_EQUAL:
2989*22dc650dSSadaf Ebrahimi 	case SLJIT_ATOMIC_STORED:
2990*22dc650dSSadaf Ebrahimi 	case SLJIT_F_EQUAL:
2991*22dc650dSSadaf Ebrahimi 	case SLJIT_ORDERED_EQUAL:
2992*22dc650dSSadaf Ebrahimi 	case SLJIT_UNORDERED_OR_EQUAL:
2993*22dc650dSSadaf Ebrahimi 		return 0x00000000;
2994*22dc650dSSadaf Ebrahimi 
2995*22dc650dSSadaf Ebrahimi 	case SLJIT_NOT_EQUAL:
2996*22dc650dSSadaf Ebrahimi 	case SLJIT_ATOMIC_NOT_STORED:
2997*22dc650dSSadaf Ebrahimi 	case SLJIT_F_NOT_EQUAL:
2998*22dc650dSSadaf Ebrahimi 	case SLJIT_UNORDERED_OR_NOT_EQUAL:
2999*22dc650dSSadaf Ebrahimi 	case SLJIT_ORDERED_NOT_EQUAL:
3000*22dc650dSSadaf Ebrahimi 		return 0x10000000;
3001*22dc650dSSadaf Ebrahimi 
3002*22dc650dSSadaf Ebrahimi 	case SLJIT_CARRY:
3003*22dc650dSSadaf Ebrahimi 		if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)
3004*22dc650dSSadaf Ebrahimi 			return 0x20000000;
3005*22dc650dSSadaf Ebrahimi 		/* fallthrough */
3006*22dc650dSSadaf Ebrahimi 
3007*22dc650dSSadaf Ebrahimi 	case SLJIT_LESS:
3008*22dc650dSSadaf Ebrahimi 		return 0x30000000;
3009*22dc650dSSadaf Ebrahimi 
3010*22dc650dSSadaf Ebrahimi 	case SLJIT_NOT_CARRY:
3011*22dc650dSSadaf Ebrahimi 		if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)
3012*22dc650dSSadaf Ebrahimi 			return 0x30000000;
3013*22dc650dSSadaf Ebrahimi 		/* fallthrough */
3014*22dc650dSSadaf Ebrahimi 
3015*22dc650dSSadaf Ebrahimi 	case SLJIT_GREATER_EQUAL:
3016*22dc650dSSadaf Ebrahimi 		return 0x20000000;
3017*22dc650dSSadaf Ebrahimi 
3018*22dc650dSSadaf Ebrahimi 	case SLJIT_GREATER:
3019*22dc650dSSadaf Ebrahimi 	case SLJIT_UNORDERED_OR_GREATER:
3020*22dc650dSSadaf Ebrahimi 		return 0x80000000;
3021*22dc650dSSadaf Ebrahimi 
3022*22dc650dSSadaf Ebrahimi 	case SLJIT_LESS_EQUAL:
3023*22dc650dSSadaf Ebrahimi 	case SLJIT_F_LESS_EQUAL:
3024*22dc650dSSadaf Ebrahimi 	case SLJIT_ORDERED_LESS_EQUAL:
3025*22dc650dSSadaf Ebrahimi 		return 0x90000000;
3026*22dc650dSSadaf Ebrahimi 
3027*22dc650dSSadaf Ebrahimi 	case SLJIT_SIG_LESS:
3028*22dc650dSSadaf Ebrahimi 	case SLJIT_UNORDERED_OR_LESS:
3029*22dc650dSSadaf Ebrahimi 		return 0xb0000000;
3030*22dc650dSSadaf Ebrahimi 
3031*22dc650dSSadaf Ebrahimi 	case SLJIT_SIG_GREATER_EQUAL:
3032*22dc650dSSadaf Ebrahimi 	case SLJIT_F_GREATER_EQUAL:
3033*22dc650dSSadaf Ebrahimi 	case SLJIT_ORDERED_GREATER_EQUAL:
3034*22dc650dSSadaf Ebrahimi 		return 0xa0000000;
3035*22dc650dSSadaf Ebrahimi 
3036*22dc650dSSadaf Ebrahimi 	case SLJIT_SIG_GREATER:
3037*22dc650dSSadaf Ebrahimi 	case SLJIT_F_GREATER:
3038*22dc650dSSadaf Ebrahimi 	case SLJIT_ORDERED_GREATER:
3039*22dc650dSSadaf Ebrahimi 		return 0xc0000000;
3040*22dc650dSSadaf Ebrahimi 
3041*22dc650dSSadaf Ebrahimi 	case SLJIT_SIG_LESS_EQUAL:
3042*22dc650dSSadaf Ebrahimi 	case SLJIT_UNORDERED_OR_LESS_EQUAL:
3043*22dc650dSSadaf Ebrahimi 		return 0xd0000000;
3044*22dc650dSSadaf Ebrahimi 
3045*22dc650dSSadaf Ebrahimi 	case SLJIT_OVERFLOW:
3046*22dc650dSSadaf Ebrahimi 		if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))
3047*22dc650dSSadaf Ebrahimi 			return 0x10000000;
3048*22dc650dSSadaf Ebrahimi 		/* fallthrough */
3049*22dc650dSSadaf Ebrahimi 
3050*22dc650dSSadaf Ebrahimi 	case SLJIT_UNORDERED:
3051*22dc650dSSadaf Ebrahimi 		return 0x60000000;
3052*22dc650dSSadaf Ebrahimi 
3053*22dc650dSSadaf Ebrahimi 	case SLJIT_NOT_OVERFLOW:
3054*22dc650dSSadaf Ebrahimi 		if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))
3055*22dc650dSSadaf Ebrahimi 			return 0x00000000;
3056*22dc650dSSadaf Ebrahimi 		/* fallthrough */
3057*22dc650dSSadaf Ebrahimi 
3058*22dc650dSSadaf Ebrahimi 	case SLJIT_ORDERED:
3059*22dc650dSSadaf Ebrahimi 		return 0x70000000;
3060*22dc650dSSadaf Ebrahimi 
3061*22dc650dSSadaf Ebrahimi 	case SLJIT_F_LESS:
3062*22dc650dSSadaf Ebrahimi 	case SLJIT_ORDERED_LESS:
3063*22dc650dSSadaf Ebrahimi 		return 0x40000000;
3064*22dc650dSSadaf Ebrahimi 
3065*22dc650dSSadaf Ebrahimi 	case SLJIT_UNORDERED_OR_GREATER_EQUAL:
3066*22dc650dSSadaf Ebrahimi 		return 0x50000000;
3067*22dc650dSSadaf Ebrahimi 
3068*22dc650dSSadaf Ebrahimi 	default:
3069*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_REG_ARG);
3070*22dc650dSSadaf Ebrahimi 		return 0xe0000000;
3071*22dc650dSSadaf Ebrahimi 	}
3072*22dc650dSSadaf Ebrahimi }
3073*22dc650dSSadaf Ebrahimi 
sljit_emit_label(struct sljit_compiler * compiler)3074*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
3075*22dc650dSSadaf Ebrahimi {
3076*22dc650dSSadaf Ebrahimi 	struct sljit_label *label;
3077*22dc650dSSadaf Ebrahimi 
3078*22dc650dSSadaf Ebrahimi 	CHECK_ERROR_PTR();
3079*22dc650dSSadaf Ebrahimi 	CHECK_PTR(check_sljit_emit_label(compiler));
3080*22dc650dSSadaf Ebrahimi 
3081*22dc650dSSadaf Ebrahimi 	if (compiler->last_label && compiler->last_label->size == compiler->size)
3082*22dc650dSSadaf Ebrahimi 		return compiler->last_label;
3083*22dc650dSSadaf Ebrahimi 
3084*22dc650dSSadaf Ebrahimi 	label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
3085*22dc650dSSadaf Ebrahimi 	PTR_FAIL_IF(!label);
3086*22dc650dSSadaf Ebrahimi 	set_label(label, compiler);
3087*22dc650dSSadaf Ebrahimi 	return label;
3088*22dc650dSSadaf Ebrahimi }
3089*22dc650dSSadaf Ebrahimi 
sljit_emit_jump(struct sljit_compiler * compiler,sljit_s32 type)3090*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
3091*22dc650dSSadaf Ebrahimi {
3092*22dc650dSSadaf Ebrahimi 	struct sljit_jump *jump;
3093*22dc650dSSadaf Ebrahimi 
3094*22dc650dSSadaf Ebrahimi 	CHECK_ERROR_PTR();
3095*22dc650dSSadaf Ebrahimi 	CHECK_PTR(check_sljit_emit_jump(compiler, type));
3096*22dc650dSSadaf Ebrahimi 
3097*22dc650dSSadaf Ebrahimi 	jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
3098*22dc650dSSadaf Ebrahimi 	PTR_FAIL_IF(!jump);
3099*22dc650dSSadaf Ebrahimi 	set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
3100*22dc650dSSadaf Ebrahimi 	type &= 0xff;
3101*22dc650dSSadaf Ebrahimi 
3102*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(reg_map[TMP_REG1] != 14);
3103*22dc650dSSadaf Ebrahimi 
3104*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
3105*22dc650dSSadaf Ebrahimi 	if (type >= SLJIT_FAST_CALL)
3106*22dc650dSSadaf Ebrahimi 		PTR_FAIL_IF(prepare_blx(compiler));
3107*22dc650dSSadaf Ebrahimi 
3108*22dc650dSSadaf Ebrahimi 	jump->addr = compiler->size;
3109*22dc650dSSadaf Ebrahimi 	PTR_FAIL_IF(push_inst_with_unique_literal(compiler, ((EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1,
3110*22dc650dSSadaf Ebrahimi 		type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0)) & ~COND_MASK) | get_cc(compiler, type), 0));
3111*22dc650dSSadaf Ebrahimi 
3112*22dc650dSSadaf Ebrahimi 	if (jump->flags & SLJIT_REWRITABLE_JUMP)
3113*22dc650dSSadaf Ebrahimi 		compiler->patches++;
3114*22dc650dSSadaf Ebrahimi 
3115*22dc650dSSadaf Ebrahimi 	if (type >= SLJIT_FAST_CALL) {
3116*22dc650dSSadaf Ebrahimi 		jump->flags |= IS_BL;
3117*22dc650dSSadaf Ebrahimi 		jump->addr = compiler->size;
3118*22dc650dSSadaf Ebrahimi 		PTR_FAIL_IF(emit_blx(compiler));
3119*22dc650dSSadaf Ebrahimi 	}
3120*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_ARM_V6 */
3121*22dc650dSSadaf Ebrahimi 	jump->addr = compiler->size;
3122*22dc650dSSadaf Ebrahimi 	if (type >= SLJIT_FAST_CALL)
3123*22dc650dSSadaf Ebrahimi 		jump->flags |= IS_BL;
3124*22dc650dSSadaf Ebrahimi 	PTR_FAIL_IF(push_inst(compiler, (((type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1)) & ~COND_MASK) | get_cc(compiler, type)));
3125*22dc650dSSadaf Ebrahimi 	compiler->size += JUMP_MAX_SIZE - 1;
3126*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_ARM_V6 */
3127*22dc650dSSadaf Ebrahimi 	return jump;
3128*22dc650dSSadaf Ebrahimi }
3129*22dc650dSSadaf Ebrahimi 
3130*22dc650dSSadaf Ebrahimi #ifdef __SOFTFP__
3131*22dc650dSSadaf Ebrahimi 
softfloat_call_with_args(struct sljit_compiler * compiler,sljit_s32 arg_types,sljit_s32 * src,sljit_u32 * extra_space)3132*22dc650dSSadaf Ebrahimi static sljit_s32 softfloat_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src, sljit_u32 *extra_space)
3133*22dc650dSSadaf Ebrahimi {
3134*22dc650dSSadaf Ebrahimi 	sljit_u32 is_tail_call = *extra_space & SLJIT_CALL_RETURN;
3135*22dc650dSSadaf Ebrahimi 	sljit_u32 offset = 0;
3136*22dc650dSSadaf Ebrahimi 	sljit_u32 word_arg_offset = 0;
3137*22dc650dSSadaf Ebrahimi 	sljit_u32 src_offset = 4 * sizeof(sljit_sw);
3138*22dc650dSSadaf Ebrahimi 	sljit_u32 float_arg_count = 0;
3139*22dc650dSSadaf Ebrahimi 	sljit_s32 types = 0;
3140*22dc650dSSadaf Ebrahimi 	sljit_u8 offsets[4];
3141*22dc650dSSadaf Ebrahimi 	sljit_u8 *offset_ptr = offsets;
3142*22dc650dSSadaf Ebrahimi 
3143*22dc650dSSadaf Ebrahimi 	if (src && FAST_IS_REG(*src))
3144*22dc650dSSadaf Ebrahimi 		src_offset = (sljit_u32)reg_map[*src] * sizeof(sljit_sw);
3145*22dc650dSSadaf Ebrahimi 
3146*22dc650dSSadaf Ebrahimi 	arg_types >>= SLJIT_ARG_SHIFT;
3147*22dc650dSSadaf Ebrahimi 
3148*22dc650dSSadaf Ebrahimi 	while (arg_types) {
3149*22dc650dSSadaf Ebrahimi 		types = (types << SLJIT_ARG_SHIFT) | (arg_types & SLJIT_ARG_MASK);
3150*22dc650dSSadaf Ebrahimi 
3151*22dc650dSSadaf Ebrahimi 		switch (arg_types & SLJIT_ARG_MASK) {
3152*22dc650dSSadaf Ebrahimi 		case SLJIT_ARG_TYPE_F64:
3153*22dc650dSSadaf Ebrahimi 			if (offset & 0x7)
3154*22dc650dSSadaf Ebrahimi 				offset += sizeof(sljit_sw);
3155*22dc650dSSadaf Ebrahimi 			*offset_ptr++ = (sljit_u8)offset;
3156*22dc650dSSadaf Ebrahimi 			offset += sizeof(sljit_f64);
3157*22dc650dSSadaf Ebrahimi 			float_arg_count++;
3158*22dc650dSSadaf Ebrahimi 			break;
3159*22dc650dSSadaf Ebrahimi 		case SLJIT_ARG_TYPE_F32:
3160*22dc650dSSadaf Ebrahimi 			*offset_ptr++ = (sljit_u8)offset;
3161*22dc650dSSadaf Ebrahimi 			offset += sizeof(sljit_f32);
3162*22dc650dSSadaf Ebrahimi 			float_arg_count++;
3163*22dc650dSSadaf Ebrahimi 			break;
3164*22dc650dSSadaf Ebrahimi 		default:
3165*22dc650dSSadaf Ebrahimi 			*offset_ptr++ = (sljit_u8)offset;
3166*22dc650dSSadaf Ebrahimi 			offset += sizeof(sljit_sw);
3167*22dc650dSSadaf Ebrahimi 			word_arg_offset += sizeof(sljit_sw);
3168*22dc650dSSadaf Ebrahimi 			break;
3169*22dc650dSSadaf Ebrahimi 		}
3170*22dc650dSSadaf Ebrahimi 
3171*22dc650dSSadaf Ebrahimi 		arg_types >>= SLJIT_ARG_SHIFT;
3172*22dc650dSSadaf Ebrahimi 	}
3173*22dc650dSSadaf Ebrahimi 
3174*22dc650dSSadaf Ebrahimi 	if (offset > 4 * sizeof(sljit_sw) && (!is_tail_call || offset > compiler->args_size)) {
3175*22dc650dSSadaf Ebrahimi 		/* Keep lr register on the stack. */
3176*22dc650dSSadaf Ebrahimi 		if (is_tail_call)
3177*22dc650dSSadaf Ebrahimi 			offset += sizeof(sljit_sw);
3178*22dc650dSSadaf Ebrahimi 
3179*22dc650dSSadaf Ebrahimi 		offset = ((offset - 4 * sizeof(sljit_sw)) + 0x7) & ~(sljit_u32)0x7;
3180*22dc650dSSadaf Ebrahimi 
3181*22dc650dSSadaf Ebrahimi 		*extra_space = offset;
3182*22dc650dSSadaf Ebrahimi 
3183*22dc650dSSadaf Ebrahimi 		if (is_tail_call)
3184*22dc650dSSadaf Ebrahimi 			FAIL_IF(emit_stack_frame_release(compiler, (sljit_s32)offset));
3185*22dc650dSSadaf Ebrahimi 		else
3186*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, SUB | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | offset));
3187*22dc650dSSadaf Ebrahimi 	} else {
3188*22dc650dSSadaf Ebrahimi 		if (is_tail_call)
3189*22dc650dSSadaf Ebrahimi 			FAIL_IF(emit_stack_frame_release(compiler, -1));
3190*22dc650dSSadaf Ebrahimi 		*extra_space = 0;
3191*22dc650dSSadaf Ebrahimi 	}
3192*22dc650dSSadaf Ebrahimi 
3193*22dc650dSSadaf Ebrahimi 	/* Process arguments in reversed direction. */
3194*22dc650dSSadaf Ebrahimi 	while (types) {
3195*22dc650dSSadaf Ebrahimi 		switch (types & SLJIT_ARG_MASK) {
3196*22dc650dSSadaf Ebrahimi 		case SLJIT_ARG_TYPE_F64:
3197*22dc650dSSadaf Ebrahimi 			float_arg_count--;
3198*22dc650dSSadaf Ebrahimi 			offset = *(--offset_ptr);
3199*22dc650dSSadaf Ebrahimi 
3200*22dc650dSSadaf Ebrahimi 			SLJIT_ASSERT((offset & 0x7) == 0);
3201*22dc650dSSadaf Ebrahimi 
3202*22dc650dSSadaf Ebrahimi 			if (offset < 4 * sizeof(sljit_sw)) {
3203*22dc650dSSadaf Ebrahimi 				if (src_offset == offset || src_offset == offset + sizeof(sljit_sw)) {
3204*22dc650dSSadaf Ebrahimi 					FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | (src_offset >> 2)));
3205*22dc650dSSadaf Ebrahimi 					*src = TMP_REG1;
3206*22dc650dSSadaf Ebrahimi 				}
3207*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, VMOV2 | 0x100000 | (offset << 10) | ((offset + sizeof(sljit_sw)) << 14) | float_arg_count));
3208*22dc650dSSadaf Ebrahimi 			} else
3209*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, VSTR_F32 | 0x800100 | RN(SLJIT_SP)
3210*22dc650dSSadaf Ebrahimi 						| (float_arg_count << 12) | ((offset - 4 * sizeof(sljit_sw)) >> 2)));
3211*22dc650dSSadaf Ebrahimi 			break;
3212*22dc650dSSadaf Ebrahimi 		case SLJIT_ARG_TYPE_F32:
3213*22dc650dSSadaf Ebrahimi 			float_arg_count--;
3214*22dc650dSSadaf Ebrahimi 			offset = *(--offset_ptr);
3215*22dc650dSSadaf Ebrahimi 
3216*22dc650dSSadaf Ebrahimi 			if (offset < 4 * sizeof(sljit_sw)) {
3217*22dc650dSSadaf Ebrahimi 				if (src_offset == offset) {
3218*22dc650dSSadaf Ebrahimi 					FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | (src_offset >> 2)));
3219*22dc650dSSadaf Ebrahimi 					*src = TMP_REG1;
3220*22dc650dSSadaf Ebrahimi 				}
3221*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, VMOV | 0x100000 | (float_arg_count << 16) | (offset << 10)));
3222*22dc650dSSadaf Ebrahimi 			} else
3223*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, VSTR_F32 | 0x800000 | RN(SLJIT_SP)
3224*22dc650dSSadaf Ebrahimi 						| (float_arg_count << 12) | ((offset - 4 * sizeof(sljit_sw)) >> 2)));
3225*22dc650dSSadaf Ebrahimi 			break;
3226*22dc650dSSadaf Ebrahimi 		default:
3227*22dc650dSSadaf Ebrahimi 			word_arg_offset -= sizeof(sljit_sw);
3228*22dc650dSSadaf Ebrahimi 			offset = *(--offset_ptr);
3229*22dc650dSSadaf Ebrahimi 
3230*22dc650dSSadaf Ebrahimi 			SLJIT_ASSERT(offset >= word_arg_offset);
3231*22dc650dSSadaf Ebrahimi 
3232*22dc650dSSadaf Ebrahimi 			if (offset != word_arg_offset) {
3233*22dc650dSSadaf Ebrahimi 				if (offset < 4 * sizeof(sljit_sw)) {
3234*22dc650dSSadaf Ebrahimi 					if (src_offset == offset) {
3235*22dc650dSSadaf Ebrahimi 						FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | (src_offset >> 2)));
3236*22dc650dSSadaf Ebrahimi 						*src = TMP_REG1;
3237*22dc650dSSadaf Ebrahimi 					}
3238*22dc650dSSadaf Ebrahimi 					else if (src_offset == word_arg_offset) {
3239*22dc650dSSadaf Ebrahimi 						*src = (sljit_s32)(SLJIT_R0 + (offset >> 2));
3240*22dc650dSSadaf Ebrahimi 						src_offset = offset;
3241*22dc650dSSadaf Ebrahimi 					}
3242*22dc650dSSadaf Ebrahimi 					FAIL_IF(push_inst(compiler, MOV | (offset << 10) | (word_arg_offset >> 2)));
3243*22dc650dSSadaf Ebrahimi 				} else
3244*22dc650dSSadaf Ebrahimi 					FAIL_IF(push_inst(compiler, STR | 0x800000 | RN(SLJIT_SP) | (word_arg_offset << 10) | (offset - 4 * sizeof(sljit_sw))));
3245*22dc650dSSadaf Ebrahimi 			}
3246*22dc650dSSadaf Ebrahimi 			break;
3247*22dc650dSSadaf Ebrahimi 		}
3248*22dc650dSSadaf Ebrahimi 
3249*22dc650dSSadaf Ebrahimi 		types >>= SLJIT_ARG_SHIFT;
3250*22dc650dSSadaf Ebrahimi 	}
3251*22dc650dSSadaf Ebrahimi 
3252*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
3253*22dc650dSSadaf Ebrahimi }
3254*22dc650dSSadaf Ebrahimi 
softfloat_post_call_with_args(struct sljit_compiler * compiler,sljit_s32 arg_types)3255*22dc650dSSadaf Ebrahimi static sljit_s32 softfloat_post_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types)
3256*22dc650dSSadaf Ebrahimi {
3257*22dc650dSSadaf Ebrahimi 	if ((arg_types & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F64)
3258*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, VMOV2 | (1 << 16) | (0 << 12) | 0));
3259*22dc650dSSadaf Ebrahimi 	if ((arg_types & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F32)
3260*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, VMOV | (0 << 16) | (0 << 12)));
3261*22dc650dSSadaf Ebrahimi 
3262*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
3263*22dc650dSSadaf Ebrahimi }
3264*22dc650dSSadaf Ebrahimi 
3265*22dc650dSSadaf Ebrahimi #else /* !__SOFTFP__ */
3266*22dc650dSSadaf Ebrahimi 
hardfloat_call_with_args(struct sljit_compiler * compiler,sljit_s32 arg_types)3267*22dc650dSSadaf Ebrahimi static sljit_s32 hardfloat_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types)
3268*22dc650dSSadaf Ebrahimi {
3269*22dc650dSSadaf Ebrahimi 	sljit_u32 offset = SLJIT_FR0;
3270*22dc650dSSadaf Ebrahimi 	sljit_u32 new_offset = SLJIT_FR0;
3271*22dc650dSSadaf Ebrahimi 	sljit_u32 f32_offset = 0;
3272*22dc650dSSadaf Ebrahimi 
3273*22dc650dSSadaf Ebrahimi 	/* Remove return value. */
3274*22dc650dSSadaf Ebrahimi 	arg_types >>= SLJIT_ARG_SHIFT;
3275*22dc650dSSadaf Ebrahimi 
3276*22dc650dSSadaf Ebrahimi 	while (arg_types) {
3277*22dc650dSSadaf Ebrahimi 		switch (arg_types & SLJIT_ARG_MASK) {
3278*22dc650dSSadaf Ebrahimi 		case SLJIT_ARG_TYPE_F64:
3279*22dc650dSSadaf Ebrahimi 			if (offset != new_offset)
3280*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32,
3281*22dc650dSSadaf Ebrahimi 					SLJIT_32, new_offset, offset, 0)));
3282*22dc650dSSadaf Ebrahimi 
3283*22dc650dSSadaf Ebrahimi 			new_offset++;
3284*22dc650dSSadaf Ebrahimi 			offset++;
3285*22dc650dSSadaf Ebrahimi 			break;
3286*22dc650dSSadaf Ebrahimi 		case SLJIT_ARG_TYPE_F32:
3287*22dc650dSSadaf Ebrahimi 			if (f32_offset != 0) {
3288*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32,
3289*22dc650dSSadaf Ebrahimi 					0x400000, f32_offset, offset, 0)));
3290*22dc650dSSadaf Ebrahimi 				f32_offset = 0;
3291*22dc650dSSadaf Ebrahimi 			} else {
3292*22dc650dSSadaf Ebrahimi 				if (offset != new_offset)
3293*22dc650dSSadaf Ebrahimi 					FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32,
3294*22dc650dSSadaf Ebrahimi 						0, new_offset, offset, 0)));
3295*22dc650dSSadaf Ebrahimi 				f32_offset = new_offset;
3296*22dc650dSSadaf Ebrahimi 				new_offset++;
3297*22dc650dSSadaf Ebrahimi 			}
3298*22dc650dSSadaf Ebrahimi 			offset++;
3299*22dc650dSSadaf Ebrahimi 			break;
3300*22dc650dSSadaf Ebrahimi 		}
3301*22dc650dSSadaf Ebrahimi 		arg_types >>= SLJIT_ARG_SHIFT;
3302*22dc650dSSadaf Ebrahimi 	}
3303*22dc650dSSadaf Ebrahimi 
3304*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
3305*22dc650dSSadaf Ebrahimi }
3306*22dc650dSSadaf Ebrahimi 
3307*22dc650dSSadaf Ebrahimi #endif /* __SOFTFP__ */
3308*22dc650dSSadaf Ebrahimi 
sljit_emit_call(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 arg_types)3309*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
3310*22dc650dSSadaf Ebrahimi 	sljit_s32 arg_types)
3311*22dc650dSSadaf Ebrahimi {
3312*22dc650dSSadaf Ebrahimi #ifdef __SOFTFP__
3313*22dc650dSSadaf Ebrahimi 	struct sljit_jump *jump;
3314*22dc650dSSadaf Ebrahimi 	sljit_u32 extra_space = (sljit_u32)type;
3315*22dc650dSSadaf Ebrahimi #endif
3316*22dc650dSSadaf Ebrahimi 
3317*22dc650dSSadaf Ebrahimi 	CHECK_ERROR_PTR();
3318*22dc650dSSadaf Ebrahimi 	CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
3319*22dc650dSSadaf Ebrahimi 
3320*22dc650dSSadaf Ebrahimi #ifdef __SOFTFP__
3321*22dc650dSSadaf Ebrahimi 	if ((type & 0xff) != SLJIT_CALL_REG_ARG) {
3322*22dc650dSSadaf Ebrahimi 		PTR_FAIL_IF(softfloat_call_with_args(compiler, arg_types, NULL, &extra_space));
3323*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT((extra_space & 0x7) == 0);
3324*22dc650dSSadaf Ebrahimi 
3325*22dc650dSSadaf Ebrahimi 		if ((type & SLJIT_CALL_RETURN) && extra_space == 0)
3326*22dc650dSSadaf Ebrahimi 			type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
3327*22dc650dSSadaf Ebrahimi 
3328*22dc650dSSadaf Ebrahimi 		SLJIT_SKIP_CHECKS(compiler);
3329*22dc650dSSadaf Ebrahimi 		jump = sljit_emit_jump(compiler, type);
3330*22dc650dSSadaf Ebrahimi 		PTR_FAIL_IF(jump == NULL);
3331*22dc650dSSadaf Ebrahimi 
3332*22dc650dSSadaf Ebrahimi 		if (extra_space > 0) {
3333*22dc650dSSadaf Ebrahimi 			if (type & SLJIT_CALL_RETURN)
3334*22dc650dSSadaf Ebrahimi 				PTR_FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1,
3335*22dc650dSSadaf Ebrahimi 					TMP_REG2, SLJIT_SP, extra_space - sizeof(sljit_sw))));
3336*22dc650dSSadaf Ebrahimi 
3337*22dc650dSSadaf Ebrahimi 			PTR_FAIL_IF(push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | extra_space));
3338*22dc650dSSadaf Ebrahimi 
3339*22dc650dSSadaf Ebrahimi 			if (type & SLJIT_CALL_RETURN) {
3340*22dc650dSSadaf Ebrahimi 				PTR_FAIL_IF(push_inst(compiler, BX | RM(TMP_REG2)));
3341*22dc650dSSadaf Ebrahimi 				return jump;
3342*22dc650dSSadaf Ebrahimi 			}
3343*22dc650dSSadaf Ebrahimi 		}
3344*22dc650dSSadaf Ebrahimi 
3345*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));
3346*22dc650dSSadaf Ebrahimi 		PTR_FAIL_IF(softfloat_post_call_with_args(compiler, arg_types));
3347*22dc650dSSadaf Ebrahimi 		return jump;
3348*22dc650dSSadaf Ebrahimi 	}
3349*22dc650dSSadaf Ebrahimi #endif /* __SOFTFP__ */
3350*22dc650dSSadaf Ebrahimi 
3351*22dc650dSSadaf Ebrahimi 	if (type & SLJIT_CALL_RETURN) {
3352*22dc650dSSadaf Ebrahimi 		PTR_FAIL_IF(emit_stack_frame_release(compiler, -1));
3353*22dc650dSSadaf Ebrahimi 		type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
3354*22dc650dSSadaf Ebrahimi 	}
3355*22dc650dSSadaf Ebrahimi 
3356*22dc650dSSadaf Ebrahimi #ifndef __SOFTFP__
3357*22dc650dSSadaf Ebrahimi 	if ((type & 0xff) != SLJIT_CALL_REG_ARG)
3358*22dc650dSSadaf Ebrahimi 		PTR_FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
3359*22dc650dSSadaf Ebrahimi #endif /* !__SOFTFP__ */
3360*22dc650dSSadaf Ebrahimi 
3361*22dc650dSSadaf Ebrahimi 	SLJIT_SKIP_CHECKS(compiler);
3362*22dc650dSSadaf Ebrahimi 	return sljit_emit_jump(compiler, type);
3363*22dc650dSSadaf Ebrahimi }
3364*22dc650dSSadaf Ebrahimi 
sljit_emit_ijump(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 src,sljit_sw srcw)3365*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
3366*22dc650dSSadaf Ebrahimi {
3367*22dc650dSSadaf Ebrahimi 	struct sljit_jump *jump;
3368*22dc650dSSadaf Ebrahimi 
3369*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
3370*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
3371*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(src, srcw);
3372*22dc650dSSadaf Ebrahimi 
3373*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(reg_map[TMP_REG1] != 14);
3374*22dc650dSSadaf Ebrahimi 
3375*22dc650dSSadaf Ebrahimi 	if (src != SLJIT_IMM) {
3376*22dc650dSSadaf Ebrahimi 		if (FAST_IS_REG(src)) {
3377*22dc650dSSadaf Ebrahimi 			SLJIT_ASSERT(reg_map[src] != 14);
3378*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(src));
3379*22dc650dSSadaf Ebrahimi 		}
3380*22dc650dSSadaf Ebrahimi 
3381*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(src & SLJIT_MEM);
3382*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
3383*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1));
3384*22dc650dSSadaf Ebrahimi 	}
3385*22dc650dSSadaf Ebrahimi 
3386*22dc650dSSadaf Ebrahimi 	/* These jumps are converted to jump/call instructions when possible. */
3387*22dc650dSSadaf Ebrahimi 	jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
3388*22dc650dSSadaf Ebrahimi 	FAIL_IF(!jump);
3389*22dc650dSSadaf Ebrahimi 	set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0));
3390*22dc650dSSadaf Ebrahimi 	jump->u.target = (sljit_uw)srcw;
3391*22dc650dSSadaf Ebrahimi 
3392*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
3393*22dc650dSSadaf Ebrahimi 	if (type >= SLJIT_FAST_CALL)
3394*22dc650dSSadaf Ebrahimi 		FAIL_IF(prepare_blx(compiler));
3395*22dc650dSSadaf Ebrahimi 	jump->addr = compiler->size;
3396*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0), 0));
3397*22dc650dSSadaf Ebrahimi 	if (type >= SLJIT_FAST_CALL) {
3398*22dc650dSSadaf Ebrahimi 		jump->addr = compiler->size;
3399*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_blx(compiler));
3400*22dc650dSSadaf Ebrahimi 	}
3401*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_ARM_V6 */
3402*22dc650dSSadaf Ebrahimi 	jump->addr = compiler->size;
3403*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1)));
3404*22dc650dSSadaf Ebrahimi 	compiler->size += JUMP_MAX_SIZE - 1;
3405*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_ARM_V6 */
3406*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
3407*22dc650dSSadaf Ebrahimi }
3408*22dc650dSSadaf Ebrahimi 
sljit_emit_icall(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 arg_types,sljit_s32 src,sljit_sw srcw)3409*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
3410*22dc650dSSadaf Ebrahimi 	sljit_s32 arg_types,
3411*22dc650dSSadaf Ebrahimi 	sljit_s32 src, sljit_sw srcw)
3412*22dc650dSSadaf Ebrahimi {
3413*22dc650dSSadaf Ebrahimi #ifdef __SOFTFP__
3414*22dc650dSSadaf Ebrahimi 	sljit_u32 extra_space = (sljit_u32)type;
3415*22dc650dSSadaf Ebrahimi #endif
3416*22dc650dSSadaf Ebrahimi 
3417*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
3418*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
3419*22dc650dSSadaf Ebrahimi 
3420*22dc650dSSadaf Ebrahimi 	if (src & SLJIT_MEM) {
3421*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
3422*22dc650dSSadaf Ebrahimi 		src = TMP_REG1;
3423*22dc650dSSadaf Ebrahimi 	}
3424*22dc650dSSadaf Ebrahimi 
3425*22dc650dSSadaf Ebrahimi 	if ((type & SLJIT_CALL_RETURN) && (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options)))) {
3426*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | RM(src)));
3427*22dc650dSSadaf Ebrahimi 		src = TMP_REG1;
3428*22dc650dSSadaf Ebrahimi 	}
3429*22dc650dSSadaf Ebrahimi 
3430*22dc650dSSadaf Ebrahimi #ifdef __SOFTFP__
3431*22dc650dSSadaf Ebrahimi 	if ((type & 0xff) != SLJIT_CALL_REG_ARG) {
3432*22dc650dSSadaf Ebrahimi 		FAIL_IF(softfloat_call_with_args(compiler, arg_types, &src, &extra_space));
3433*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT((extra_space & 0x7) == 0);
3434*22dc650dSSadaf Ebrahimi 
3435*22dc650dSSadaf Ebrahimi 		if ((type & SLJIT_CALL_RETURN) && extra_space == 0)
3436*22dc650dSSadaf Ebrahimi 			type = SLJIT_JUMP;
3437*22dc650dSSadaf Ebrahimi 
3438*22dc650dSSadaf Ebrahimi 		SLJIT_SKIP_CHECKS(compiler);
3439*22dc650dSSadaf Ebrahimi 		FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));
3440*22dc650dSSadaf Ebrahimi 
3441*22dc650dSSadaf Ebrahimi 		if (extra_space > 0) {
3442*22dc650dSSadaf Ebrahimi 			if (type & SLJIT_CALL_RETURN)
3443*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1,
3444*22dc650dSSadaf Ebrahimi 					TMP_REG2, SLJIT_SP, extra_space - sizeof(sljit_sw))));
3445*22dc650dSSadaf Ebrahimi 
3446*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | extra_space));
3447*22dc650dSSadaf Ebrahimi 
3448*22dc650dSSadaf Ebrahimi 			if (type & SLJIT_CALL_RETURN)
3449*22dc650dSSadaf Ebrahimi 				return push_inst(compiler, BX | RM(TMP_REG2));
3450*22dc650dSSadaf Ebrahimi 		}
3451*22dc650dSSadaf Ebrahimi 
3452*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));
3453*22dc650dSSadaf Ebrahimi 		return softfloat_post_call_with_args(compiler, arg_types);
3454*22dc650dSSadaf Ebrahimi 	}
3455*22dc650dSSadaf Ebrahimi #endif /* __SOFTFP__ */
3456*22dc650dSSadaf Ebrahimi 
3457*22dc650dSSadaf Ebrahimi 	if (type & SLJIT_CALL_RETURN) {
3458*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_stack_frame_release(compiler, -1));
3459*22dc650dSSadaf Ebrahimi 		type = SLJIT_JUMP;
3460*22dc650dSSadaf Ebrahimi 	}
3461*22dc650dSSadaf Ebrahimi 
3462*22dc650dSSadaf Ebrahimi #ifndef __SOFTFP__
3463*22dc650dSSadaf Ebrahimi 	if ((type & 0xff) != SLJIT_CALL_REG_ARG)
3464*22dc650dSSadaf Ebrahimi 		FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
3465*22dc650dSSadaf Ebrahimi #endif /* !__SOFTFP__ */
3466*22dc650dSSadaf Ebrahimi 
3467*22dc650dSSadaf Ebrahimi 	SLJIT_SKIP_CHECKS(compiler);
3468*22dc650dSSadaf Ebrahimi 	return sljit_emit_ijump(compiler, type, src, srcw);
3469*22dc650dSSadaf Ebrahimi }
3470*22dc650dSSadaf Ebrahimi 
3471*22dc650dSSadaf Ebrahimi #ifdef __SOFTFP__
3472*22dc650dSSadaf Ebrahimi 
emit_fmov_before_return(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 src,sljit_sw srcw)3473*22dc650dSSadaf Ebrahimi static SLJIT_INLINE sljit_s32 emit_fmov_before_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
3474*22dc650dSSadaf Ebrahimi {
3475*22dc650dSSadaf Ebrahimi 	if (compiler->options & SLJIT_ENTER_REG_ARG) {
3476*22dc650dSSadaf Ebrahimi 		if (src == SLJIT_FR0)
3477*22dc650dSSadaf Ebrahimi 			return SLJIT_SUCCESS;
3478*22dc650dSSadaf Ebrahimi 
3479*22dc650dSSadaf Ebrahimi 		SLJIT_SKIP_CHECKS(compiler);
3480*22dc650dSSadaf Ebrahimi 		return sljit_emit_fop1(compiler, op, SLJIT_RETURN_FREG, 0, src, srcw);
3481*22dc650dSSadaf Ebrahimi 	}
3482*22dc650dSSadaf Ebrahimi 
3483*22dc650dSSadaf Ebrahimi 	if (FAST_IS_REG(src)) {
3484*22dc650dSSadaf Ebrahimi 		if (op & SLJIT_32)
3485*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, VMOV | (1 << 20) | RD(SLJIT_R0) | VN(src));
3486*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, VMOV2 | (1 << 20) | RD(SLJIT_R0) | RN(SLJIT_R1) | VM(src));
3487*22dc650dSSadaf Ebrahimi 	}
3488*22dc650dSSadaf Ebrahimi 
3489*22dc650dSSadaf Ebrahimi 	SLJIT_SKIP_CHECKS(compiler);
3490*22dc650dSSadaf Ebrahimi 
3491*22dc650dSSadaf Ebrahimi 	if (op & SLJIT_32)
3492*22dc650dSSadaf Ebrahimi 		return sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, src, srcw);
3493*22dc650dSSadaf Ebrahimi 	return sljit_emit_mem(compiler, SLJIT_MOV, SLJIT_REG_PAIR(SLJIT_R0, SLJIT_R1), src, srcw);
3494*22dc650dSSadaf Ebrahimi }
3495*22dc650dSSadaf Ebrahimi 
3496*22dc650dSSadaf Ebrahimi #endif /* __SOFTFP__ */
3497*22dc650dSSadaf Ebrahimi 
sljit_emit_op_flags(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 type)3498*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
3499*22dc650dSSadaf Ebrahimi 	sljit_s32 dst, sljit_sw dstw,
3500*22dc650dSSadaf Ebrahimi 	sljit_s32 type)
3501*22dc650dSSadaf Ebrahimi {
3502*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_reg, flags = GET_ALL_FLAGS(op);
3503*22dc650dSSadaf Ebrahimi 	sljit_ins cc, ins;
3504*22dc650dSSadaf Ebrahimi 
3505*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
3506*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
3507*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(dst, dstw);
3508*22dc650dSSadaf Ebrahimi 
3509*22dc650dSSadaf Ebrahimi 	op = GET_OPCODE(op);
3510*22dc650dSSadaf Ebrahimi 	cc = get_cc(compiler, type);
3511*22dc650dSSadaf Ebrahimi 	dst_reg = FAST_IS_REG(dst) ? dst : TMP_REG1;
3512*22dc650dSSadaf Ebrahimi 
3513*22dc650dSSadaf Ebrahimi 	if (op < SLJIT_ADD) {
3514*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, MOV | RD(dst_reg) | SRC2_IMM | 0));
3515*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ((MOV | RD(dst_reg) | SRC2_IMM | 1) & ~COND_MASK) | cc));
3516*22dc650dSSadaf Ebrahimi 		if (dst & SLJIT_MEM)
3517*22dc650dSSadaf Ebrahimi 			return emit_op_mem(compiler, WORD_SIZE, TMP_REG1, dst, dstw, TMP_REG2);
3518*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
3519*22dc650dSSadaf Ebrahimi 	}
3520*22dc650dSSadaf Ebrahimi 
3521*22dc650dSSadaf Ebrahimi 	ins = (op == SLJIT_AND ? AND : (op == SLJIT_OR ? ORR : EOR));
3522*22dc650dSSadaf Ebrahimi 
3523*22dc650dSSadaf Ebrahimi 	if (dst & SLJIT_MEM)
3524*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, dst, dstw, TMP_REG2));
3525*22dc650dSSadaf Ebrahimi 
3526*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, ((ins | RD(dst_reg) | RN(dst_reg) | SRC2_IMM | 1) & ~COND_MASK) | cc));
3527*22dc650dSSadaf Ebrahimi 
3528*22dc650dSSadaf Ebrahimi 	if (op == SLJIT_AND)
3529*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ((ins | RD(dst_reg) | RN(dst_reg) | SRC2_IMM | 0) & ~COND_MASK) | (cc ^ 0x10000000)));
3530*22dc650dSSadaf Ebrahimi 
3531*22dc650dSSadaf Ebrahimi 	if (dst & SLJIT_MEM)
3532*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, dst, dstw, TMP_REG2));
3533*22dc650dSSadaf Ebrahimi 
3534*22dc650dSSadaf Ebrahimi 	if (flags & SLJIT_SET_Z)
3535*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, MOV | SET_FLAGS | RD(TMP_REG2) | RM(dst_reg));
3536*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
3537*22dc650dSSadaf Ebrahimi }
3538*22dc650dSSadaf Ebrahimi 
sljit_emit_select(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 dst_reg,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2_reg)3539*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,
3540*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_reg,
3541*22dc650dSSadaf Ebrahimi 	sljit_s32 src1, sljit_sw src1w,
3542*22dc650dSSadaf Ebrahimi 	sljit_s32 src2_reg)
3543*22dc650dSSadaf Ebrahimi {
3544*22dc650dSSadaf Ebrahimi 	sljit_ins cc, tmp;
3545*22dc650dSSadaf Ebrahimi 
3546*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
3547*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));
3548*22dc650dSSadaf Ebrahimi 
3549*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(src1, src1w);
3550*22dc650dSSadaf Ebrahimi 
3551*22dc650dSSadaf Ebrahimi 	if (src2_reg != dst_reg && src1 == dst_reg) {
3552*22dc650dSSadaf Ebrahimi 		src1 = src2_reg;
3553*22dc650dSSadaf Ebrahimi 		src1w = 0;
3554*22dc650dSSadaf Ebrahimi 		src2_reg = dst_reg;
3555*22dc650dSSadaf Ebrahimi 		type ^= 0x1;
3556*22dc650dSSadaf Ebrahimi 	}
3557*22dc650dSSadaf Ebrahimi 
3558*22dc650dSSadaf Ebrahimi 	if (src1 & SLJIT_MEM) {
3559*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, (src2_reg != dst_reg) ? dst_reg : TMP_REG1, src1, src1w, TMP_REG1));
3560*22dc650dSSadaf Ebrahimi 
3561*22dc650dSSadaf Ebrahimi 		if (src2_reg != dst_reg) {
3562*22dc650dSSadaf Ebrahimi 			src1 = src2_reg;
3563*22dc650dSSadaf Ebrahimi 			src1w = 0;
3564*22dc650dSSadaf Ebrahimi 			type ^= 0x1;
3565*22dc650dSSadaf Ebrahimi 		} else {
3566*22dc650dSSadaf Ebrahimi 			src1 = TMP_REG1;
3567*22dc650dSSadaf Ebrahimi 			src1w = 0;
3568*22dc650dSSadaf Ebrahimi 		}
3569*22dc650dSSadaf Ebrahimi 	} else if (dst_reg != src2_reg)
3570*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, MOV | RD(dst_reg) | RM(src2_reg)));
3571*22dc650dSSadaf Ebrahimi 
3572*22dc650dSSadaf Ebrahimi 	cc = get_cc(compiler, type & ~SLJIT_32);
3573*22dc650dSSadaf Ebrahimi 
3574*22dc650dSSadaf Ebrahimi 	if (SLJIT_UNLIKELY(src1 == SLJIT_IMM)) {
3575*22dc650dSSadaf Ebrahimi 		tmp = get_imm((sljit_uw)src1w);
3576*22dc650dSSadaf Ebrahimi 		if (tmp)
3577*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, ((MOV | RD(dst_reg) | tmp) & ~COND_MASK) | cc);
3578*22dc650dSSadaf Ebrahimi 
3579*22dc650dSSadaf Ebrahimi 		tmp = get_imm(~(sljit_uw)src1w);
3580*22dc650dSSadaf Ebrahimi 		if (tmp)
3581*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, ((MVN | RD(dst_reg) | tmp) & ~COND_MASK) | cc);
3582*22dc650dSSadaf Ebrahimi 
3583*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
3584*22dc650dSSadaf Ebrahimi 		tmp = (sljit_ins)src1w;
3585*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, (MOVW & ~COND_MASK) | cc | RD(dst_reg) | ((tmp << 4) & 0xf0000) | (tmp & 0xfff)));
3586*22dc650dSSadaf Ebrahimi 		if (tmp <= 0xffff)
3587*22dc650dSSadaf Ebrahimi 			return SLJIT_SUCCESS;
3588*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, (MOVT & ~COND_MASK) | cc | RD(dst_reg) | ((tmp >> 12) & 0xf0000) | ((tmp >> 16) & 0xfff));
3589*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_ARM_V7 */
3590*22dc650dSSadaf Ebrahimi 		FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)src1w));
3591*22dc650dSSadaf Ebrahimi 		src1 = TMP_REG1;
3592*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_ARM_V7 */
3593*22dc650dSSadaf Ebrahimi 	}
3594*22dc650dSSadaf Ebrahimi 
3595*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, ((MOV | RD(dst_reg) | RM(src1)) & ~COND_MASK) | cc);
3596*22dc650dSSadaf Ebrahimi }
3597*22dc650dSSadaf Ebrahimi 
sljit_emit_fselect(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 dst_freg,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2_freg)3598*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type,
3599*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_freg,
3600*22dc650dSSadaf Ebrahimi 	sljit_s32 src1, sljit_sw src1w,
3601*22dc650dSSadaf Ebrahimi 	sljit_s32 src2_freg)
3602*22dc650dSSadaf Ebrahimi {
3603*22dc650dSSadaf Ebrahimi 	sljit_ins cc;
3604*22dc650dSSadaf Ebrahimi 
3605*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
3606*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg));
3607*22dc650dSSadaf Ebrahimi 
3608*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(src1, src1w);
3609*22dc650dSSadaf Ebrahimi 
3610*22dc650dSSadaf Ebrahimi 	type ^= SLJIT_32;
3611*22dc650dSSadaf Ebrahimi 
3612*22dc650dSSadaf Ebrahimi 	if (dst_freg != src2_freg) {
3613*22dc650dSSadaf Ebrahimi 		if (dst_freg == src1) {
3614*22dc650dSSadaf Ebrahimi 			src1 = src2_freg;
3615*22dc650dSSadaf Ebrahimi 			src1w = 0;
3616*22dc650dSSadaf Ebrahimi 			type ^= 0x1;
3617*22dc650dSSadaf Ebrahimi 		} else
3618*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32, (type & SLJIT_32), dst_freg, src2_freg, 0)));
3619*22dc650dSSadaf Ebrahimi 	}
3620*22dc650dSSadaf Ebrahimi 
3621*22dc650dSSadaf Ebrahimi 	if (src1 & SLJIT_MEM) {
3622*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_fop_mem(compiler, (type & SLJIT_32) | FPU_LOAD, TMP_FREG2, src1, src1w));
3623*22dc650dSSadaf Ebrahimi 		src1 = TMP_FREG2;
3624*22dc650dSSadaf Ebrahimi 	}
3625*22dc650dSSadaf Ebrahimi 
3626*22dc650dSSadaf Ebrahimi 	cc = get_cc(compiler, type & ~SLJIT_32);
3627*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, EMIT_FPU_OPERATION((VMOV_F32 & ~COND_MASK) | cc, (type & SLJIT_32), dst_freg, src1, 0));
3628*22dc650dSSadaf Ebrahimi }
3629*22dc650dSSadaf Ebrahimi 
3630*22dc650dSSadaf Ebrahimi #undef EMIT_FPU_OPERATION
3631*22dc650dSSadaf Ebrahimi 
update_mem_addr(struct sljit_compiler * compiler,sljit_s32 * mem,sljit_sw * memw,sljit_s32 max_offset)3632*22dc650dSSadaf Ebrahimi static sljit_s32 update_mem_addr(struct sljit_compiler *compiler, sljit_s32 *mem, sljit_sw *memw, sljit_s32 max_offset)
3633*22dc650dSSadaf Ebrahimi {
3634*22dc650dSSadaf Ebrahimi 	sljit_s32 arg = *mem;
3635*22dc650dSSadaf Ebrahimi 	sljit_sw argw = *memw;
3636*22dc650dSSadaf Ebrahimi 	sljit_uw imm, tmp;
3637*22dc650dSSadaf Ebrahimi 	sljit_sw mask = 0xfff;
3638*22dc650dSSadaf Ebrahimi 	sljit_sw sign = 0x1000;
3639*22dc650dSSadaf Ebrahimi 
3640*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(max_offset >= 0xf00);
3641*22dc650dSSadaf Ebrahimi 
3642*22dc650dSSadaf Ebrahimi 	*mem = TMP_REG1;
3643*22dc650dSSadaf Ebrahimi 
3644*22dc650dSSadaf Ebrahimi 	if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
3645*22dc650dSSadaf Ebrahimi 		*memw = 0;
3646*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, ADD | RD(TMP_REG1) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | ((sljit_ins)(argw & 0x3) << 7));
3647*22dc650dSSadaf Ebrahimi 	}
3648*22dc650dSSadaf Ebrahimi 
3649*22dc650dSSadaf Ebrahimi 	arg &= REG_MASK;
3650*22dc650dSSadaf Ebrahimi 
3651*22dc650dSSadaf Ebrahimi 	if (arg) {
3652*22dc650dSSadaf Ebrahimi 		if (argw <= max_offset && argw >= -mask) {
3653*22dc650dSSadaf Ebrahimi 			*mem = arg;
3654*22dc650dSSadaf Ebrahimi 			return SLJIT_SUCCESS;
3655*22dc650dSSadaf Ebrahimi 		}
3656*22dc650dSSadaf Ebrahimi 
3657*22dc650dSSadaf Ebrahimi 		if (argw >= 0) {
3658*22dc650dSSadaf Ebrahimi 			tmp = (sljit_uw)(argw & (sign | mask));
3659*22dc650dSSadaf Ebrahimi 			tmp = (sljit_uw)((argw + ((tmp <= (sljit_uw)max_offset || tmp == (sljit_uw)sign) ? 0 : sign)) & ~mask);
3660*22dc650dSSadaf Ebrahimi 			imm = get_imm(tmp);
3661*22dc650dSSadaf Ebrahimi 
3662*22dc650dSSadaf Ebrahimi 			if (imm) {
3663*22dc650dSSadaf Ebrahimi 				*memw = argw - (sljit_sw)tmp;
3664*22dc650dSSadaf Ebrahimi 				SLJIT_ASSERT(*memw >= -mask && *memw <= max_offset);
3665*22dc650dSSadaf Ebrahimi 
3666*22dc650dSSadaf Ebrahimi 				return push_inst(compiler, ADD | RD(TMP_REG1) | RN(arg) | imm);
3667*22dc650dSSadaf Ebrahimi 			}
3668*22dc650dSSadaf Ebrahimi 		} else {
3669*22dc650dSSadaf Ebrahimi 			tmp = (sljit_uw)(-argw & (sign | mask));
3670*22dc650dSSadaf Ebrahimi 			tmp = (sljit_uw)((-argw + ((tmp <= (sljit_uw)((sign << 1) - max_offset - 1)) ? 0 : sign)) & ~mask);
3671*22dc650dSSadaf Ebrahimi 			imm = get_imm(tmp);
3672*22dc650dSSadaf Ebrahimi 
3673*22dc650dSSadaf Ebrahimi 			if (imm) {
3674*22dc650dSSadaf Ebrahimi 				*memw = argw + (sljit_sw)tmp;
3675*22dc650dSSadaf Ebrahimi 				SLJIT_ASSERT(*memw >= -mask && *memw <= max_offset);
3676*22dc650dSSadaf Ebrahimi 
3677*22dc650dSSadaf Ebrahimi 				return push_inst(compiler, SUB | RD(TMP_REG1) | RN(arg) | imm);
3678*22dc650dSSadaf Ebrahimi 			}
3679*22dc650dSSadaf Ebrahimi 		}
3680*22dc650dSSadaf Ebrahimi 	}
3681*22dc650dSSadaf Ebrahimi 
3682*22dc650dSSadaf Ebrahimi 	tmp = (sljit_uw)(argw & (sign | mask));
3683*22dc650dSSadaf Ebrahimi 	tmp = (sljit_uw)((argw + ((tmp <= (sljit_uw)max_offset || tmp == (sljit_uw)sign) ? 0 : sign)) & ~mask);
3684*22dc650dSSadaf Ebrahimi 	*memw = argw - (sljit_sw)tmp;
3685*22dc650dSSadaf Ebrahimi 
3686*22dc650dSSadaf Ebrahimi 	FAIL_IF(load_immediate(compiler, TMP_REG1, tmp));
3687*22dc650dSSadaf Ebrahimi 
3688*22dc650dSSadaf Ebrahimi 	if (arg == 0)
3689*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
3690*22dc650dSSadaf Ebrahimi 
3691*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, ADD | RD(TMP_REG1) | RN(TMP_REG1) | RM(arg));
3692*22dc650dSSadaf Ebrahimi }
3693*22dc650dSSadaf Ebrahimi 
sljit_emit_mem(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 reg,sljit_s32 mem,sljit_sw memw)3694*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
3695*22dc650dSSadaf Ebrahimi 	sljit_s32 reg,
3696*22dc650dSSadaf Ebrahimi 	sljit_s32 mem, sljit_sw memw)
3697*22dc650dSSadaf Ebrahimi {
3698*22dc650dSSadaf Ebrahimi 	sljit_s32 flags;
3699*22dc650dSSadaf Ebrahimi 
3700*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
3701*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
3702*22dc650dSSadaf Ebrahimi 
3703*22dc650dSSadaf Ebrahimi 	if (!(reg & REG_PAIR_MASK))
3704*22dc650dSSadaf Ebrahimi 		return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);
3705*22dc650dSSadaf Ebrahimi 
3706*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(mem, memw);
3707*22dc650dSSadaf Ebrahimi 
3708*22dc650dSSadaf Ebrahimi 	FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 4));
3709*22dc650dSSadaf Ebrahimi 
3710*22dc650dSSadaf Ebrahimi 	flags = WORD_SIZE;
3711*22dc650dSSadaf Ebrahimi 
3712*22dc650dSSadaf Ebrahimi 	if (!(type & SLJIT_MEM_STORE)) {
3713*22dc650dSSadaf Ebrahimi 		if (REG_PAIR_FIRST(reg) == (mem & REG_MASK)) {
3714*22dc650dSSadaf Ebrahimi 			FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, REG_PAIR_SECOND(reg), SLJIT_MEM1(mem), memw + SSIZE_OF(sw), TMP_REG1));
3715*22dc650dSSadaf Ebrahimi 			return emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, REG_PAIR_FIRST(reg), SLJIT_MEM1(mem), memw, TMP_REG1);
3716*22dc650dSSadaf Ebrahimi 		}
3717*22dc650dSSadaf Ebrahimi 
3718*22dc650dSSadaf Ebrahimi 		flags = WORD_SIZE | LOAD_DATA;
3719*22dc650dSSadaf Ebrahimi 	}
3720*22dc650dSSadaf Ebrahimi 
3721*22dc650dSSadaf Ebrahimi 	FAIL_IF(emit_op_mem(compiler, flags, REG_PAIR_FIRST(reg), SLJIT_MEM1(mem), memw, TMP_REG1));
3722*22dc650dSSadaf Ebrahimi 	return emit_op_mem(compiler, flags, REG_PAIR_SECOND(reg), SLJIT_MEM1(mem), memw + SSIZE_OF(sw), TMP_REG1);
3723*22dc650dSSadaf Ebrahimi }
3724*22dc650dSSadaf Ebrahimi 
sljit_emit_mem_update(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 reg,sljit_s32 mem,sljit_sw memw)3725*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type,
3726*22dc650dSSadaf Ebrahimi 	sljit_s32 reg,
3727*22dc650dSSadaf Ebrahimi 	sljit_s32 mem, sljit_sw memw)
3728*22dc650dSSadaf Ebrahimi {
3729*22dc650dSSadaf Ebrahimi 	sljit_s32 flags;
3730*22dc650dSSadaf Ebrahimi 	sljit_ins is_type1_transfer, inst;
3731*22dc650dSSadaf Ebrahimi 
3732*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
3733*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_mem_update(compiler, type, reg, mem, memw));
3734*22dc650dSSadaf Ebrahimi 
3735*22dc650dSSadaf Ebrahimi 	is_type1_transfer = 1;
3736*22dc650dSSadaf Ebrahimi 
3737*22dc650dSSadaf Ebrahimi 	switch (type & 0xff) {
3738*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV:
3739*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_U32:
3740*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_S32:
3741*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV32:
3742*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_P:
3743*22dc650dSSadaf Ebrahimi 		flags = WORD_SIZE;
3744*22dc650dSSadaf Ebrahimi 		break;
3745*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_U8:
3746*22dc650dSSadaf Ebrahimi 		flags = BYTE_SIZE;
3747*22dc650dSSadaf Ebrahimi 		break;
3748*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_S8:
3749*22dc650dSSadaf Ebrahimi 		if (!(type & SLJIT_MEM_STORE))
3750*22dc650dSSadaf Ebrahimi 			is_type1_transfer = 0;
3751*22dc650dSSadaf Ebrahimi 		flags = BYTE_SIZE | SIGNED;
3752*22dc650dSSadaf Ebrahimi 		break;
3753*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_U16:
3754*22dc650dSSadaf Ebrahimi 		is_type1_transfer = 0;
3755*22dc650dSSadaf Ebrahimi 		flags = HALF_SIZE;
3756*22dc650dSSadaf Ebrahimi 		break;
3757*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_S16:
3758*22dc650dSSadaf Ebrahimi 		is_type1_transfer = 0;
3759*22dc650dSSadaf Ebrahimi 		flags = HALF_SIZE | SIGNED;
3760*22dc650dSSadaf Ebrahimi 		break;
3761*22dc650dSSadaf Ebrahimi 	default:
3762*22dc650dSSadaf Ebrahimi 		SLJIT_UNREACHABLE();
3763*22dc650dSSadaf Ebrahimi 		flags = WORD_SIZE;
3764*22dc650dSSadaf Ebrahimi 		break;
3765*22dc650dSSadaf Ebrahimi 	}
3766*22dc650dSSadaf Ebrahimi 
3767*22dc650dSSadaf Ebrahimi 	if (!(type & SLJIT_MEM_STORE))
3768*22dc650dSSadaf Ebrahimi 		flags |= LOAD_DATA;
3769*22dc650dSSadaf Ebrahimi 
3770*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(is_type1_transfer == !!IS_TYPE1_TRANSFER(flags));
3771*22dc650dSSadaf Ebrahimi 
3772*22dc650dSSadaf Ebrahimi 	if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
3773*22dc650dSSadaf Ebrahimi 		if (!is_type1_transfer && memw != 0)
3774*22dc650dSSadaf Ebrahimi 			return SLJIT_ERR_UNSUPPORTED;
3775*22dc650dSSadaf Ebrahimi 	} else {
3776*22dc650dSSadaf Ebrahimi 		if (is_type1_transfer) {
3777*22dc650dSSadaf Ebrahimi 			if (memw > 4095 || memw < -4095)
3778*22dc650dSSadaf Ebrahimi 				return SLJIT_ERR_UNSUPPORTED;
3779*22dc650dSSadaf Ebrahimi 		} else if (memw > 255 || memw < -255)
3780*22dc650dSSadaf Ebrahimi 			return SLJIT_ERR_UNSUPPORTED;
3781*22dc650dSSadaf Ebrahimi 	}
3782*22dc650dSSadaf Ebrahimi 
3783*22dc650dSSadaf Ebrahimi 	if (type & SLJIT_MEM_SUPP)
3784*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
3785*22dc650dSSadaf Ebrahimi 
3786*22dc650dSSadaf Ebrahimi 	if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
3787*22dc650dSSadaf Ebrahimi 		memw &= 0x3;
3788*22dc650dSSadaf Ebrahimi 
3789*22dc650dSSadaf Ebrahimi 		inst = EMIT_DATA_TRANSFER(flags, 1, reg, mem & REG_MASK, RM(OFFS_REG(mem)) | ((sljit_ins)memw << 7));
3790*22dc650dSSadaf Ebrahimi 
3791*22dc650dSSadaf Ebrahimi 		if (is_type1_transfer)
3792*22dc650dSSadaf Ebrahimi 			inst |= (1 << 25);
3793*22dc650dSSadaf Ebrahimi 
3794*22dc650dSSadaf Ebrahimi 		if (type & SLJIT_MEM_POST)
3795*22dc650dSSadaf Ebrahimi 			inst ^= (1 << 24);
3796*22dc650dSSadaf Ebrahimi 		else
3797*22dc650dSSadaf Ebrahimi 			inst |= (1 << 21);
3798*22dc650dSSadaf Ebrahimi 
3799*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, inst);
3800*22dc650dSSadaf Ebrahimi 	}
3801*22dc650dSSadaf Ebrahimi 
3802*22dc650dSSadaf Ebrahimi 	inst = EMIT_DATA_TRANSFER(flags, 0, reg, mem & REG_MASK, 0);
3803*22dc650dSSadaf Ebrahimi 
3804*22dc650dSSadaf Ebrahimi 	if (type & SLJIT_MEM_POST)
3805*22dc650dSSadaf Ebrahimi 		inst ^= (1 << 24);
3806*22dc650dSSadaf Ebrahimi 	else
3807*22dc650dSSadaf Ebrahimi 		inst |= (1 << 21);
3808*22dc650dSSadaf Ebrahimi 
3809*22dc650dSSadaf Ebrahimi 	if (is_type1_transfer) {
3810*22dc650dSSadaf Ebrahimi 		if (memw >= 0)
3811*22dc650dSSadaf Ebrahimi 			inst |= (1 << 23);
3812*22dc650dSSadaf Ebrahimi 		else
3813*22dc650dSSadaf Ebrahimi 			memw = -memw;
3814*22dc650dSSadaf Ebrahimi 
3815*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, inst | (sljit_ins)memw);
3816*22dc650dSSadaf Ebrahimi 	}
3817*22dc650dSSadaf Ebrahimi 
3818*22dc650dSSadaf Ebrahimi 	if (memw >= 0)
3819*22dc650dSSadaf Ebrahimi 		inst |= (1 << 23);
3820*22dc650dSSadaf Ebrahimi 	else
3821*22dc650dSSadaf Ebrahimi 		memw = -memw;
3822*22dc650dSSadaf Ebrahimi 
3823*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, inst | TYPE2_TRANSFER_IMM((sljit_ins)memw));
3824*22dc650dSSadaf Ebrahimi }
3825*22dc650dSSadaf Ebrahimi 
sljit_emit_fmem(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 freg,sljit_s32 mem,sljit_sw memw)3826*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,
3827*22dc650dSSadaf Ebrahimi 	sljit_s32 freg,
3828*22dc650dSSadaf Ebrahimi 	sljit_s32 mem, sljit_sw memw)
3829*22dc650dSSadaf Ebrahimi {
3830*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
3831*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));
3832*22dc650dSSadaf Ebrahimi 
3833*22dc650dSSadaf Ebrahimi 	if (type & SLJIT_MEM_ALIGNED_32)
3834*22dc650dSSadaf Ebrahimi 		return emit_fop_mem(compiler, ((type ^ SLJIT_32) & SLJIT_32) | ((type & SLJIT_MEM_STORE) ? 0 : FPU_LOAD), freg, mem, memw);
3835*22dc650dSSadaf Ebrahimi 
3836*22dc650dSSadaf Ebrahimi 	if (type & SLJIT_MEM_STORE) {
3837*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, VMOV | (1 << 20) | VN(freg) | RD(TMP_REG2)));
3838*22dc650dSSadaf Ebrahimi 
3839*22dc650dSSadaf Ebrahimi 		if (type & SLJIT_32)
3840*22dc650dSSadaf Ebrahimi 			return emit_op_mem(compiler, WORD_SIZE, TMP_REG2, mem, memw, TMP_REG1);
3841*22dc650dSSadaf Ebrahimi 
3842*22dc650dSSadaf Ebrahimi 		FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 4));
3843*22dc650dSSadaf Ebrahimi 		mem |= SLJIT_MEM;
3844*22dc650dSSadaf Ebrahimi 
3845*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, mem, memw, TMP_REG1));
3846*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, VMOV | (1 << 20) | VN(freg) | 0x80 | RD(TMP_REG2)));
3847*22dc650dSSadaf Ebrahimi 		return emit_op_mem(compiler, WORD_SIZE, TMP_REG2, mem, memw + 4, TMP_REG1);
3848*22dc650dSSadaf Ebrahimi 	}
3849*22dc650dSSadaf Ebrahimi 
3850*22dc650dSSadaf Ebrahimi 	if (type & SLJIT_32) {
3851*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, mem, memw, TMP_REG1));
3852*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, VMOV | VN(freg) | RD(TMP_REG2));
3853*22dc650dSSadaf Ebrahimi 	}
3854*22dc650dSSadaf Ebrahimi 
3855*22dc650dSSadaf Ebrahimi 	FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 4));
3856*22dc650dSSadaf Ebrahimi 	mem |= SLJIT_MEM;
3857*22dc650dSSadaf Ebrahimi 
3858*22dc650dSSadaf Ebrahimi 	FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, mem, memw, TMP_REG1));
3859*22dc650dSSadaf Ebrahimi 	FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, mem, memw + 4, TMP_REG1));
3860*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, VMOV2 | VM(freg) | RD(TMP_REG2) | RN(TMP_REG1));
3861*22dc650dSSadaf Ebrahimi }
3862*22dc650dSSadaf Ebrahimi 
sljit_emit_simd_mem_offset(struct sljit_compiler * compiler,sljit_s32 * mem_ptr,sljit_sw memw)3863*22dc650dSSadaf Ebrahimi static sljit_s32 sljit_emit_simd_mem_offset(struct sljit_compiler *compiler, sljit_s32 *mem_ptr, sljit_sw memw)
3864*22dc650dSSadaf Ebrahimi {
3865*22dc650dSSadaf Ebrahimi 	sljit_s32 mem = *mem_ptr;
3866*22dc650dSSadaf Ebrahimi 	sljit_uw imm;
3867*22dc650dSSadaf Ebrahimi 
3868*22dc650dSSadaf Ebrahimi 	if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
3869*22dc650dSSadaf Ebrahimi 		*mem_ptr = TMP_REG1;
3870*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, ADD | RD(TMP_REG1) | RN(mem & REG_MASK) | RM(OFFS_REG(mem)) | ((sljit_ins)(memw & 0x3) << 7));
3871*22dc650dSSadaf Ebrahimi 	}
3872*22dc650dSSadaf Ebrahimi 
3873*22dc650dSSadaf Ebrahimi 	if (SLJIT_UNLIKELY(!(mem & REG_MASK))) {
3874*22dc650dSSadaf Ebrahimi 		*mem_ptr = TMP_REG1;
3875*22dc650dSSadaf Ebrahimi 		return load_immediate(compiler, TMP_REG1, (sljit_uw)memw);
3876*22dc650dSSadaf Ebrahimi 	}
3877*22dc650dSSadaf Ebrahimi 
3878*22dc650dSSadaf Ebrahimi 	mem &= REG_MASK;
3879*22dc650dSSadaf Ebrahimi 
3880*22dc650dSSadaf Ebrahimi 	if (memw == 0) {
3881*22dc650dSSadaf Ebrahimi 		*mem_ptr = mem;
3882*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
3883*22dc650dSSadaf Ebrahimi 	}
3884*22dc650dSSadaf Ebrahimi 
3885*22dc650dSSadaf Ebrahimi 	*mem_ptr = TMP_REG1;
3886*22dc650dSSadaf Ebrahimi 	imm = get_imm((sljit_uw)(memw < 0 ? -memw : memw));
3887*22dc650dSSadaf Ebrahimi 
3888*22dc650dSSadaf Ebrahimi 	if (imm != 0)
3889*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, ((memw < 0) ? SUB : ADD) | RD(TMP_REG1) | RN(mem) | imm);
3890*22dc650dSSadaf Ebrahimi 
3891*22dc650dSSadaf Ebrahimi 	FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)memw));
3892*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, ADD | RD(TMP_REG1) | RN(TMP_REG1) | RM(mem));
3893*22dc650dSSadaf Ebrahimi }
3894*22dc650dSSadaf Ebrahimi 
simd_get_quad_reg_index(sljit_s32 freg)3895*22dc650dSSadaf Ebrahimi static SLJIT_INLINE sljit_s32 simd_get_quad_reg_index(sljit_s32 freg)
3896*22dc650dSSadaf Ebrahimi {
3897*22dc650dSSadaf Ebrahimi 	freg += freg & 0x1;
3898*22dc650dSSadaf Ebrahimi 
3899*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT((freg_map[freg] & 0x1) == (freg <= SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS));
3900*22dc650dSSadaf Ebrahimi 
3901*22dc650dSSadaf Ebrahimi 	if (freg <= SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS)
3902*22dc650dSSadaf Ebrahimi 		freg--;
3903*22dc650dSSadaf Ebrahimi 
3904*22dc650dSSadaf Ebrahimi 	return freg;
3905*22dc650dSSadaf Ebrahimi }
3906*22dc650dSSadaf Ebrahimi 
3907*22dc650dSSadaf Ebrahimi #define SLJIT_QUAD_OTHER_HALF(freg) ((((freg) & 0x1) << 1) - 1)
3908*22dc650dSSadaf Ebrahimi 
sljit_emit_simd_mov(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 freg,sljit_s32 srcdst,sljit_sw srcdstw)3909*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type,
3910*22dc650dSSadaf Ebrahimi 	sljit_s32 freg,
3911*22dc650dSSadaf Ebrahimi 	sljit_s32 srcdst, sljit_sw srcdstw)
3912*22dc650dSSadaf Ebrahimi {
3913*22dc650dSSadaf Ebrahimi 	sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
3914*22dc650dSSadaf Ebrahimi 	sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
3915*22dc650dSSadaf Ebrahimi 	sljit_s32 alignment = SLJIT_SIMD_GET_ELEM2_SIZE(type);
3916*22dc650dSSadaf Ebrahimi 	sljit_ins ins;
3917*22dc650dSSadaf Ebrahimi 
3918*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
3919*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_simd_mov(compiler, type, freg, srcdst, srcdstw));
3920*22dc650dSSadaf Ebrahimi 
3921*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(srcdst, srcdstw);
3922*22dc650dSSadaf Ebrahimi 
3923*22dc650dSSadaf Ebrahimi 	if (reg_size != 3 && reg_size != 4)
3924*22dc650dSSadaf Ebrahimi 		return SLJIT_ERR_UNSUPPORTED;
3925*22dc650dSSadaf Ebrahimi 
3926*22dc650dSSadaf Ebrahimi 	if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))
3927*22dc650dSSadaf Ebrahimi 		return SLJIT_ERR_UNSUPPORTED;
3928*22dc650dSSadaf Ebrahimi 
3929*22dc650dSSadaf Ebrahimi 	if (type & SLJIT_SIMD_TEST)
3930*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
3931*22dc650dSSadaf Ebrahimi 
3932*22dc650dSSadaf Ebrahimi 	if (reg_size == 4)
3933*22dc650dSSadaf Ebrahimi 		freg = simd_get_quad_reg_index(freg);
3934*22dc650dSSadaf Ebrahimi 
3935*22dc650dSSadaf Ebrahimi 	if (!(srcdst & SLJIT_MEM)) {
3936*22dc650dSSadaf Ebrahimi 		if (reg_size == 4)
3937*22dc650dSSadaf Ebrahimi 			srcdst = simd_get_quad_reg_index(srcdst);
3938*22dc650dSSadaf Ebrahimi 
3939*22dc650dSSadaf Ebrahimi 		if (type & SLJIT_SIMD_STORE)
3940*22dc650dSSadaf Ebrahimi 			ins = VD(srcdst) | VN(freg) | VM(freg);
3941*22dc650dSSadaf Ebrahimi 		else
3942*22dc650dSSadaf Ebrahimi 			ins = VD(freg) | VN(srcdst) | VM(srcdst);
3943*22dc650dSSadaf Ebrahimi 
3944*22dc650dSSadaf Ebrahimi 		if (reg_size == 4)
3945*22dc650dSSadaf Ebrahimi 			ins |= (sljit_ins)1 << 6;
3946*22dc650dSSadaf Ebrahimi 
3947*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, VORR | ins);
3948*22dc650dSSadaf Ebrahimi 	}
3949*22dc650dSSadaf Ebrahimi 
3950*22dc650dSSadaf Ebrahimi 	FAIL_IF(sljit_emit_simd_mem_offset(compiler, &srcdst, srcdstw));
3951*22dc650dSSadaf Ebrahimi 
3952*22dc650dSSadaf Ebrahimi 	if (elem_size > 3)
3953*22dc650dSSadaf Ebrahimi 		elem_size = 3;
3954*22dc650dSSadaf Ebrahimi 
3955*22dc650dSSadaf Ebrahimi 	ins = ((type & SLJIT_SIMD_STORE) ? VST1 : VLD1) | VD(freg)
3956*22dc650dSSadaf Ebrahimi 		| (sljit_ins)((reg_size == 3) ? (0x7 << 8) : (0xa << 8));
3957*22dc650dSSadaf Ebrahimi 
3958*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(reg_size >= alignment);
3959*22dc650dSSadaf Ebrahimi 
3960*22dc650dSSadaf Ebrahimi 	if (alignment == 3)
3961*22dc650dSSadaf Ebrahimi 		ins |= 0x10;
3962*22dc650dSSadaf Ebrahimi 	else if (alignment >= 3)
3963*22dc650dSSadaf Ebrahimi 		ins |= 0x20;
3964*22dc650dSSadaf Ebrahimi 
3965*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, ins | RN(srcdst) | ((sljit_ins)elem_size) << 6 | 0xf);
3966*22dc650dSSadaf Ebrahimi }
3967*22dc650dSSadaf Ebrahimi 
simd_get_imm(sljit_s32 elem_size,sljit_uw value)3968*22dc650dSSadaf Ebrahimi static sljit_ins simd_get_imm(sljit_s32 elem_size, sljit_uw value)
3969*22dc650dSSadaf Ebrahimi {
3970*22dc650dSSadaf Ebrahimi 	sljit_ins result;
3971*22dc650dSSadaf Ebrahimi 
3972*22dc650dSSadaf Ebrahimi 	if (elem_size > 1 && (sljit_u16)value == (value >> 16)) {
3973*22dc650dSSadaf Ebrahimi 		elem_size = 1;
3974*22dc650dSSadaf Ebrahimi 		value = (sljit_u16)value;
3975*22dc650dSSadaf Ebrahimi 	}
3976*22dc650dSSadaf Ebrahimi 
3977*22dc650dSSadaf Ebrahimi 	if (elem_size == 1 && (sljit_u8)value == (value >> 8)) {
3978*22dc650dSSadaf Ebrahimi 		elem_size = 0;
3979*22dc650dSSadaf Ebrahimi 		value = (sljit_u8)value;
3980*22dc650dSSadaf Ebrahimi 	}
3981*22dc650dSSadaf Ebrahimi 
3982*22dc650dSSadaf Ebrahimi 	switch (elem_size) {
3983*22dc650dSSadaf Ebrahimi 	case 0:
3984*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(value <= 0xff);
3985*22dc650dSSadaf Ebrahimi 		result = 0xe00;
3986*22dc650dSSadaf Ebrahimi 		break;
3987*22dc650dSSadaf Ebrahimi 	case 1:
3988*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(value <= 0xffff);
3989*22dc650dSSadaf Ebrahimi 		result = 0;
3990*22dc650dSSadaf Ebrahimi 
3991*22dc650dSSadaf Ebrahimi 		while (1) {
3992*22dc650dSSadaf Ebrahimi 			if (value <= 0xff) {
3993*22dc650dSSadaf Ebrahimi 				result |= 0x800;
3994*22dc650dSSadaf Ebrahimi 				break;
3995*22dc650dSSadaf Ebrahimi 			}
3996*22dc650dSSadaf Ebrahimi 
3997*22dc650dSSadaf Ebrahimi 			if ((value & 0xff) == 0) {
3998*22dc650dSSadaf Ebrahimi 				value >>= 8;
3999*22dc650dSSadaf Ebrahimi 				result |= 0xa00;
4000*22dc650dSSadaf Ebrahimi 				break;
4001*22dc650dSSadaf Ebrahimi 			}
4002*22dc650dSSadaf Ebrahimi 
4003*22dc650dSSadaf Ebrahimi 			if (result != 0)
4004*22dc650dSSadaf Ebrahimi 				return ~(sljit_ins)0;
4005*22dc650dSSadaf Ebrahimi 
4006*22dc650dSSadaf Ebrahimi 			value ^= (sljit_uw)0xffff;
4007*22dc650dSSadaf Ebrahimi 			result = (1 << 5);
4008*22dc650dSSadaf Ebrahimi 		}
4009*22dc650dSSadaf Ebrahimi 		break;
4010*22dc650dSSadaf Ebrahimi 	default:
4011*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(value <= 0xffffffff);
4012*22dc650dSSadaf Ebrahimi 		result = 0;
4013*22dc650dSSadaf Ebrahimi 
4014*22dc650dSSadaf Ebrahimi 		while (1) {
4015*22dc650dSSadaf Ebrahimi 			if (value <= 0xff) {
4016*22dc650dSSadaf Ebrahimi 				result |= 0x000;
4017*22dc650dSSadaf Ebrahimi 				break;
4018*22dc650dSSadaf Ebrahimi 			}
4019*22dc650dSSadaf Ebrahimi 
4020*22dc650dSSadaf Ebrahimi 			if ((value & ~(sljit_uw)0xff00) == 0) {
4021*22dc650dSSadaf Ebrahimi 				value >>= 8;
4022*22dc650dSSadaf Ebrahimi 				result |= 0x200;
4023*22dc650dSSadaf Ebrahimi 				break;
4024*22dc650dSSadaf Ebrahimi 			}
4025*22dc650dSSadaf Ebrahimi 
4026*22dc650dSSadaf Ebrahimi 			if ((value & ~(sljit_uw)0xff0000) == 0) {
4027*22dc650dSSadaf Ebrahimi 				value >>= 16;
4028*22dc650dSSadaf Ebrahimi 				result |= 0x400;
4029*22dc650dSSadaf Ebrahimi 				break;
4030*22dc650dSSadaf Ebrahimi 			}
4031*22dc650dSSadaf Ebrahimi 
4032*22dc650dSSadaf Ebrahimi 			if ((value & ~(sljit_uw)0xff000000) == 0) {
4033*22dc650dSSadaf Ebrahimi 				value >>= 24;
4034*22dc650dSSadaf Ebrahimi 				result |= 0x600;
4035*22dc650dSSadaf Ebrahimi 				break;
4036*22dc650dSSadaf Ebrahimi 			}
4037*22dc650dSSadaf Ebrahimi 
4038*22dc650dSSadaf Ebrahimi 			if ((value & (sljit_uw)0xff) == 0xff && (value >> 16) == 0) {
4039*22dc650dSSadaf Ebrahimi 				value >>= 8;
4040*22dc650dSSadaf Ebrahimi 				result |= 0xc00;
4041*22dc650dSSadaf Ebrahimi 				break;
4042*22dc650dSSadaf Ebrahimi 			}
4043*22dc650dSSadaf Ebrahimi 
4044*22dc650dSSadaf Ebrahimi 			if ((value & (sljit_uw)0xffff) == 0xffff && (value >> 24) == 0) {
4045*22dc650dSSadaf Ebrahimi 				value >>= 16;
4046*22dc650dSSadaf Ebrahimi 				result |= 0xd00;
4047*22dc650dSSadaf Ebrahimi 				break;
4048*22dc650dSSadaf Ebrahimi 			}
4049*22dc650dSSadaf Ebrahimi 
4050*22dc650dSSadaf Ebrahimi 			if (result != 0)
4051*22dc650dSSadaf Ebrahimi 				return ~(sljit_ins)0;
4052*22dc650dSSadaf Ebrahimi 
4053*22dc650dSSadaf Ebrahimi 			value = ~value;
4054*22dc650dSSadaf Ebrahimi 			result = (1 << 5);
4055*22dc650dSSadaf Ebrahimi 		}
4056*22dc650dSSadaf Ebrahimi 		break;
4057*22dc650dSSadaf Ebrahimi 	}
4058*22dc650dSSadaf Ebrahimi 
4059*22dc650dSSadaf Ebrahimi 	return ((sljit_ins)value & 0xf) | (((sljit_ins)value & 0x70) << 12) | (((sljit_ins)value & 0x80) << 17) | result;
4060*22dc650dSSadaf Ebrahimi }
4061*22dc650dSSadaf Ebrahimi 
sljit_emit_simd_replicate(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 freg,sljit_s32 src,sljit_sw srcw)4062*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type,
4063*22dc650dSSadaf Ebrahimi 	sljit_s32 freg,
4064*22dc650dSSadaf Ebrahimi 	sljit_s32 src, sljit_sw srcw)
4065*22dc650dSSadaf Ebrahimi {
4066*22dc650dSSadaf Ebrahimi 	sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
4067*22dc650dSSadaf Ebrahimi 	sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
4068*22dc650dSSadaf Ebrahimi 	sljit_ins ins, imm;
4069*22dc650dSSadaf Ebrahimi 
4070*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
4071*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_simd_replicate(compiler, type, freg, src, srcw));
4072*22dc650dSSadaf Ebrahimi 
4073*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(src, srcw);
4074*22dc650dSSadaf Ebrahimi 
4075*22dc650dSSadaf Ebrahimi 	if (reg_size != 3 && reg_size != 4)
4076*22dc650dSSadaf Ebrahimi 		return SLJIT_ERR_UNSUPPORTED;
4077*22dc650dSSadaf Ebrahimi 
4078*22dc650dSSadaf Ebrahimi 	if ((type & SLJIT_SIMD_FLOAT) ? (elem_size < 2 || elem_size > 3) : (elem_size > 2))
4079*22dc650dSSadaf Ebrahimi 		return SLJIT_ERR_UNSUPPORTED;
4080*22dc650dSSadaf Ebrahimi 
4081*22dc650dSSadaf Ebrahimi 	if (type & SLJIT_SIMD_TEST)
4082*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
4083*22dc650dSSadaf Ebrahimi 
4084*22dc650dSSadaf Ebrahimi 	if (reg_size == 4)
4085*22dc650dSSadaf Ebrahimi 		freg = simd_get_quad_reg_index(freg);
4086*22dc650dSSadaf Ebrahimi 
4087*22dc650dSSadaf Ebrahimi 	if (src == SLJIT_IMM && srcw == 0)
4088*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, VMOV_i | ((reg_size == 4) ? (1 << 6) : 0) | VD(freg));
4089*22dc650dSSadaf Ebrahimi 
4090*22dc650dSSadaf Ebrahimi 	if (SLJIT_UNLIKELY(elem_size == 3)) {
4091*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(type & SLJIT_SIMD_FLOAT);
4092*22dc650dSSadaf Ebrahimi 
4093*22dc650dSSadaf Ebrahimi 		if (src & SLJIT_MEM) {
4094*22dc650dSSadaf Ebrahimi 			FAIL_IF(emit_fop_mem(compiler, FPU_LOAD | SLJIT_32, freg, src, srcw));
4095*22dc650dSSadaf Ebrahimi 			src = freg;
4096*22dc650dSSadaf Ebrahimi 		} else if (freg != src)
4097*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, VORR | VD(freg) | VN(src) | VM(src)));
4098*22dc650dSSadaf Ebrahimi 
4099*22dc650dSSadaf Ebrahimi 		freg += SLJIT_QUAD_OTHER_HALF(freg);
4100*22dc650dSSadaf Ebrahimi 
4101*22dc650dSSadaf Ebrahimi 		if (freg != src)
4102*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, VORR | VD(freg) | VN(src) | VM(src));
4103*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
4104*22dc650dSSadaf Ebrahimi 	}
4105*22dc650dSSadaf Ebrahimi 
4106*22dc650dSSadaf Ebrahimi 	if (src & SLJIT_MEM) {
4107*22dc650dSSadaf Ebrahimi 		FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src, srcw));
4108*22dc650dSSadaf Ebrahimi 
4109*22dc650dSSadaf Ebrahimi 		ins = (sljit_ins)(elem_size << 6);
4110*22dc650dSSadaf Ebrahimi 
4111*22dc650dSSadaf Ebrahimi 		if (reg_size == 4)
4112*22dc650dSSadaf Ebrahimi 			ins |= (sljit_ins)1 << 5;
4113*22dc650dSSadaf Ebrahimi 
4114*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, VLD1_r | ins | VD(freg) | RN(src) | 0xf);
4115*22dc650dSSadaf Ebrahimi 	}
4116*22dc650dSSadaf Ebrahimi 
4117*22dc650dSSadaf Ebrahimi 	if (type & SLJIT_SIMD_FLOAT) {
4118*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(elem_size == 2);
4119*22dc650dSSadaf Ebrahimi 		ins = ((sljit_ins)freg_ebit_map[src] << (16 + 2 + 1)) | ((sljit_ins)1 << (16 + 2));
4120*22dc650dSSadaf Ebrahimi 
4121*22dc650dSSadaf Ebrahimi 		if (reg_size == 4)
4122*22dc650dSSadaf Ebrahimi 			ins |= (sljit_ins)1 << 6;
4123*22dc650dSSadaf Ebrahimi 
4124*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, VDUP_s | ins | VD(freg) | (sljit_ins)freg_map[src]);
4125*22dc650dSSadaf Ebrahimi 	}
4126*22dc650dSSadaf Ebrahimi 
4127*22dc650dSSadaf Ebrahimi 	if (src == SLJIT_IMM) {
4128*22dc650dSSadaf Ebrahimi 		if (elem_size < 2)
4129*22dc650dSSadaf Ebrahimi 			srcw &= ((sljit_sw)1 << (((sljit_sw)1 << elem_size) << 3)) - 1;
4130*22dc650dSSadaf Ebrahimi 
4131*22dc650dSSadaf Ebrahimi 		imm = simd_get_imm(elem_size, (sljit_uw)srcw);
4132*22dc650dSSadaf Ebrahimi 
4133*22dc650dSSadaf Ebrahimi 		if (imm != ~(sljit_ins)0) {
4134*22dc650dSSadaf Ebrahimi 			if (reg_size == 4)
4135*22dc650dSSadaf Ebrahimi 				imm |= (sljit_ins)1 << 6;
4136*22dc650dSSadaf Ebrahimi 
4137*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, VMOV_i | imm | VD(freg));
4138*22dc650dSSadaf Ebrahimi 		}
4139*22dc650dSSadaf Ebrahimi 
4140*22dc650dSSadaf Ebrahimi 		FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)srcw));
4141*22dc650dSSadaf Ebrahimi 		src = TMP_REG1;
4142*22dc650dSSadaf Ebrahimi 	}
4143*22dc650dSSadaf Ebrahimi 
4144*22dc650dSSadaf Ebrahimi 	switch (elem_size) {
4145*22dc650dSSadaf Ebrahimi 	case 0:
4146*22dc650dSSadaf Ebrahimi 		ins = 1 << 22;
4147*22dc650dSSadaf Ebrahimi 		break;
4148*22dc650dSSadaf Ebrahimi 	case 1:
4149*22dc650dSSadaf Ebrahimi 		ins = 1 << 5;
4150*22dc650dSSadaf Ebrahimi 		break;
4151*22dc650dSSadaf Ebrahimi 	default:
4152*22dc650dSSadaf Ebrahimi 		ins = 0;
4153*22dc650dSSadaf Ebrahimi 		break;
4154*22dc650dSSadaf Ebrahimi 	}
4155*22dc650dSSadaf Ebrahimi 
4156*22dc650dSSadaf Ebrahimi 	if (reg_size == 4)
4157*22dc650dSSadaf Ebrahimi 		ins |= (sljit_ins)1 << 21;
4158*22dc650dSSadaf Ebrahimi 
4159*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, VDUP | ins | VN(freg) | RD(src));
4160*22dc650dSSadaf Ebrahimi }
4161*22dc650dSSadaf Ebrahimi 
sljit_emit_simd_lane_mov(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 freg,sljit_s32 lane_index,sljit_s32 srcdst,sljit_sw srcdstw)4162*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type,
4163*22dc650dSSadaf Ebrahimi 	sljit_s32 freg, sljit_s32 lane_index,
4164*22dc650dSSadaf Ebrahimi 	sljit_s32 srcdst, sljit_sw srcdstw)
4165*22dc650dSSadaf Ebrahimi {
4166*22dc650dSSadaf Ebrahimi 	sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
4167*22dc650dSSadaf Ebrahimi 	sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
4168*22dc650dSSadaf Ebrahimi 	sljit_ins ins;
4169*22dc650dSSadaf Ebrahimi 
4170*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
4171*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_simd_lane_mov(compiler, type, freg, lane_index, srcdst, srcdstw));
4172*22dc650dSSadaf Ebrahimi 
4173*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(srcdst, srcdstw);
4174*22dc650dSSadaf Ebrahimi 
4175*22dc650dSSadaf Ebrahimi 	if (reg_size != 3 && reg_size != 4)
4176*22dc650dSSadaf Ebrahimi 		return SLJIT_ERR_UNSUPPORTED;
4177*22dc650dSSadaf Ebrahimi 
4178*22dc650dSSadaf Ebrahimi 	if ((type & SLJIT_SIMD_FLOAT) ? (elem_size < 2 || elem_size > 3) : (elem_size > 2))
4179*22dc650dSSadaf Ebrahimi 		return SLJIT_ERR_UNSUPPORTED;
4180*22dc650dSSadaf Ebrahimi 
4181*22dc650dSSadaf Ebrahimi 	if (type & SLJIT_SIMD_TEST)
4182*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
4183*22dc650dSSadaf Ebrahimi 
4184*22dc650dSSadaf Ebrahimi 	if (reg_size == 4)
4185*22dc650dSSadaf Ebrahimi 		freg = simd_get_quad_reg_index(freg);
4186*22dc650dSSadaf Ebrahimi 
4187*22dc650dSSadaf Ebrahimi 	if (type & SLJIT_SIMD_LANE_ZERO) {
4188*22dc650dSSadaf Ebrahimi 		ins = (reg_size == 3) ? 0 : ((sljit_ins)1 << 6);
4189*22dc650dSSadaf Ebrahimi 
4190*22dc650dSSadaf Ebrahimi 		if (type & SLJIT_SIMD_FLOAT) {
4191*22dc650dSSadaf Ebrahimi 			if (elem_size == 3 && !(srcdst & SLJIT_MEM)) {
4192*22dc650dSSadaf Ebrahimi 				if (lane_index == 1)
4193*22dc650dSSadaf Ebrahimi 					freg += SLJIT_QUAD_OTHER_HALF(freg);
4194*22dc650dSSadaf Ebrahimi 
4195*22dc650dSSadaf Ebrahimi 				if (srcdst != freg)
4196*22dc650dSSadaf Ebrahimi 					FAIL_IF(push_inst(compiler, VORR | VD(freg) | VN(srcdst) | VM(srcdst)));
4197*22dc650dSSadaf Ebrahimi 
4198*22dc650dSSadaf Ebrahimi 				freg += SLJIT_QUAD_OTHER_HALF(freg);
4199*22dc650dSSadaf Ebrahimi 				return push_inst(compiler, VMOV_i | VD(freg));
4200*22dc650dSSadaf Ebrahimi 			}
4201*22dc650dSSadaf Ebrahimi 
4202*22dc650dSSadaf Ebrahimi 			if (srcdst == freg || (elem_size == 3 && srcdst == (freg + SLJIT_QUAD_OTHER_HALF(freg)))) {
4203*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, VORR | ins | VD(TMP_FREG2) | VN(freg) | VM(freg)));
4204*22dc650dSSadaf Ebrahimi 				srcdst = TMP_FREG2;
4205*22dc650dSSadaf Ebrahimi 				srcdstw = 0;
4206*22dc650dSSadaf Ebrahimi 			}
4207*22dc650dSSadaf Ebrahimi 		}
4208*22dc650dSSadaf Ebrahimi 
4209*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, VMOV_i | ins | VD(freg)));
4210*22dc650dSSadaf Ebrahimi 	}
4211*22dc650dSSadaf Ebrahimi 
4212*22dc650dSSadaf Ebrahimi 	if (reg_size == 4 && lane_index >= (0x8 >> elem_size)) {
4213*22dc650dSSadaf Ebrahimi 		lane_index -= (0x8 >> elem_size);
4214*22dc650dSSadaf Ebrahimi 		freg += SLJIT_QUAD_OTHER_HALF(freg);
4215*22dc650dSSadaf Ebrahimi 	}
4216*22dc650dSSadaf Ebrahimi 
4217*22dc650dSSadaf Ebrahimi 	if (srcdst & SLJIT_MEM) {
4218*22dc650dSSadaf Ebrahimi 		if (elem_size == 3)
4219*22dc650dSSadaf Ebrahimi 			return emit_fop_mem(compiler, ((type & SLJIT_SIMD_STORE) ? 0 : FPU_LOAD) | SLJIT_32, freg, srcdst, srcdstw);
4220*22dc650dSSadaf Ebrahimi 
4221*22dc650dSSadaf Ebrahimi 		FAIL_IF(sljit_emit_simd_mem_offset(compiler, &srcdst, srcdstw));
4222*22dc650dSSadaf Ebrahimi 
4223*22dc650dSSadaf Ebrahimi 		lane_index = lane_index << elem_size;
4224*22dc650dSSadaf Ebrahimi 		ins = (sljit_ins)((elem_size << 10) | (lane_index << 5));
4225*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, ((type & SLJIT_SIMD_STORE) ? VST1_s : VLD1_s) | ins | VD(freg) | RN(srcdst) | 0xf);
4226*22dc650dSSadaf Ebrahimi 	}
4227*22dc650dSSadaf Ebrahimi 
4228*22dc650dSSadaf Ebrahimi 	if (type & SLJIT_SIMD_FLOAT) {
4229*22dc650dSSadaf Ebrahimi 		if (elem_size == 3) {
4230*22dc650dSSadaf Ebrahimi 			if (type & SLJIT_SIMD_STORE)
4231*22dc650dSSadaf Ebrahimi 				return push_inst(compiler, VORR | VD(srcdst) | VN(freg) | VM(freg));
4232*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, VMOV_F32 | SLJIT_32 | VD(freg) | VM(srcdst));
4233*22dc650dSSadaf Ebrahimi 		}
4234*22dc650dSSadaf Ebrahimi 
4235*22dc650dSSadaf Ebrahimi 		if (type & SLJIT_SIMD_STORE) {
4236*22dc650dSSadaf Ebrahimi 			if (freg_ebit_map[freg] == 0) {
4237*22dc650dSSadaf Ebrahimi 				if (lane_index == 1)
4238*22dc650dSSadaf Ebrahimi 					freg = SLJIT_F64_SECOND(freg);
4239*22dc650dSSadaf Ebrahimi 
4240*22dc650dSSadaf Ebrahimi 				return push_inst(compiler, VMOV_F32 | VD(srcdst) | VM(freg));
4241*22dc650dSSadaf Ebrahimi 			}
4242*22dc650dSSadaf Ebrahimi 
4243*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, VMOV_s | (1 << 20) | ((sljit_ins)lane_index << 21) | VN(freg) | RD(TMP_REG1)));
4244*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, VMOV | VN(srcdst) | RD(TMP_REG1));
4245*22dc650dSSadaf Ebrahimi 		}
4246*22dc650dSSadaf Ebrahimi 
4247*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, VMOV | (1 << 20) | VN(srcdst) | RD(TMP_REG1)));
4248*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, VMOV_s | ((sljit_ins)lane_index << 21) | VN(freg) | RD(TMP_REG1));
4249*22dc650dSSadaf Ebrahimi 	}
4250*22dc650dSSadaf Ebrahimi 
4251*22dc650dSSadaf Ebrahimi 	if (srcdst == SLJIT_IMM) {
4252*22dc650dSSadaf Ebrahimi 		if (elem_size < 2)
4253*22dc650dSSadaf Ebrahimi 			srcdstw &= ((sljit_sw)1 << (((sljit_sw)1 << elem_size) << 3)) - 1;
4254*22dc650dSSadaf Ebrahimi 
4255*22dc650dSSadaf Ebrahimi 		FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)srcdstw));
4256*22dc650dSSadaf Ebrahimi 		srcdst = TMP_REG1;
4257*22dc650dSSadaf Ebrahimi 	}
4258*22dc650dSSadaf Ebrahimi 
4259*22dc650dSSadaf Ebrahimi 	if (elem_size == 0)
4260*22dc650dSSadaf Ebrahimi 		ins = 0x400000;
4261*22dc650dSSadaf Ebrahimi 	else if (elem_size == 1)
4262*22dc650dSSadaf Ebrahimi 		ins = 0x20;
4263*22dc650dSSadaf Ebrahimi 	else
4264*22dc650dSSadaf Ebrahimi 		ins = 0;
4265*22dc650dSSadaf Ebrahimi 
4266*22dc650dSSadaf Ebrahimi 	lane_index = lane_index << elem_size;
4267*22dc650dSSadaf Ebrahimi 	ins |= (sljit_ins)(((lane_index & 0x4) << 19) | ((lane_index & 0x3) << 5));
4268*22dc650dSSadaf Ebrahimi 
4269*22dc650dSSadaf Ebrahimi 	if (type & SLJIT_SIMD_STORE) {
4270*22dc650dSSadaf Ebrahimi 		ins |= (1 << 20);
4271*22dc650dSSadaf Ebrahimi 
4272*22dc650dSSadaf Ebrahimi 		if (elem_size < 2 && !(type & SLJIT_SIMD_LANE_SIGNED))
4273*22dc650dSSadaf Ebrahimi 			ins |= (1 << 23);
4274*22dc650dSSadaf Ebrahimi 	}
4275*22dc650dSSadaf Ebrahimi 
4276*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, VMOV_s | ins | VN(freg) | RD(srcdst));
4277*22dc650dSSadaf Ebrahimi }
4278*22dc650dSSadaf Ebrahimi 
sljit_emit_simd_lane_replicate(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 freg,sljit_s32 src,sljit_s32 src_lane_index)4279*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type,
4280*22dc650dSSadaf Ebrahimi 	sljit_s32 freg,
4281*22dc650dSSadaf Ebrahimi 	sljit_s32 src, sljit_s32 src_lane_index)
4282*22dc650dSSadaf Ebrahimi {
4283*22dc650dSSadaf Ebrahimi 	sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
4284*22dc650dSSadaf Ebrahimi 	sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
4285*22dc650dSSadaf Ebrahimi 	sljit_ins ins;
4286*22dc650dSSadaf Ebrahimi 
4287*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
4288*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, freg, src, src_lane_index));
4289*22dc650dSSadaf Ebrahimi 
4290*22dc650dSSadaf Ebrahimi 	if (reg_size != 3 && reg_size != 4)
4291*22dc650dSSadaf Ebrahimi 		return SLJIT_ERR_UNSUPPORTED;
4292*22dc650dSSadaf Ebrahimi 
4293*22dc650dSSadaf Ebrahimi 	if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))
4294*22dc650dSSadaf Ebrahimi 		return SLJIT_ERR_UNSUPPORTED;
4295*22dc650dSSadaf Ebrahimi 
4296*22dc650dSSadaf Ebrahimi 	if (type & SLJIT_SIMD_TEST)
4297*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
4298*22dc650dSSadaf Ebrahimi 
4299*22dc650dSSadaf Ebrahimi 	if (reg_size == 4) {
4300*22dc650dSSadaf Ebrahimi 		freg = simd_get_quad_reg_index(freg);
4301*22dc650dSSadaf Ebrahimi 		src = simd_get_quad_reg_index(src);
4302*22dc650dSSadaf Ebrahimi 
4303*22dc650dSSadaf Ebrahimi 		if (src_lane_index >= (0x8 >> elem_size)) {
4304*22dc650dSSadaf Ebrahimi 			src_lane_index -= (0x8 >> elem_size);
4305*22dc650dSSadaf Ebrahimi 			src += SLJIT_QUAD_OTHER_HALF(src);
4306*22dc650dSSadaf Ebrahimi 		}
4307*22dc650dSSadaf Ebrahimi 	}
4308*22dc650dSSadaf Ebrahimi 
4309*22dc650dSSadaf Ebrahimi 	if (elem_size == 3) {
4310*22dc650dSSadaf Ebrahimi 		if (freg != src)
4311*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, VORR | VD(freg) | VN(src) | VM(src)));
4312*22dc650dSSadaf Ebrahimi 
4313*22dc650dSSadaf Ebrahimi 		freg += SLJIT_QUAD_OTHER_HALF(freg);
4314*22dc650dSSadaf Ebrahimi 
4315*22dc650dSSadaf Ebrahimi 		if (freg != src)
4316*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, VORR | VD(freg) | VN(src) | VM(src));
4317*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
4318*22dc650dSSadaf Ebrahimi 	}
4319*22dc650dSSadaf Ebrahimi 
4320*22dc650dSSadaf Ebrahimi 	ins = ((((sljit_ins)src_lane_index << 1) | 1) << (16 + elem_size));
4321*22dc650dSSadaf Ebrahimi 
4322*22dc650dSSadaf Ebrahimi 	if (reg_size == 4)
4323*22dc650dSSadaf Ebrahimi 		ins |= (sljit_ins)1 << 6;
4324*22dc650dSSadaf Ebrahimi 
4325*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, VDUP_s | ins | VD(freg) | VM(src));
4326*22dc650dSSadaf Ebrahimi }
4327*22dc650dSSadaf Ebrahimi 
sljit_emit_simd_extend(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 freg,sljit_s32 src,sljit_sw srcw)4328*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type,
4329*22dc650dSSadaf Ebrahimi 	sljit_s32 freg,
4330*22dc650dSSadaf Ebrahimi 	sljit_s32 src, sljit_sw srcw)
4331*22dc650dSSadaf Ebrahimi {
4332*22dc650dSSadaf Ebrahimi 	sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
4333*22dc650dSSadaf Ebrahimi 	sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
4334*22dc650dSSadaf Ebrahimi 	sljit_s32 elem2_size = SLJIT_SIMD_GET_ELEM2_SIZE(type);
4335*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_reg;
4336*22dc650dSSadaf Ebrahimi 
4337*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
4338*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_simd_extend(compiler, type, freg, src, srcw));
4339*22dc650dSSadaf Ebrahimi 
4340*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(src, srcw);
4341*22dc650dSSadaf Ebrahimi 
4342*22dc650dSSadaf Ebrahimi 	if (reg_size != 3 && reg_size != 4)
4343*22dc650dSSadaf Ebrahimi 		return SLJIT_ERR_UNSUPPORTED;
4344*22dc650dSSadaf Ebrahimi 
4345*22dc650dSSadaf Ebrahimi 	if ((type & SLJIT_SIMD_FLOAT) && (elem_size != 2 || elem2_size != 3))
4346*22dc650dSSadaf Ebrahimi 		return SLJIT_ERR_UNSUPPORTED;
4347*22dc650dSSadaf Ebrahimi 
4348*22dc650dSSadaf Ebrahimi 	if (type & SLJIT_SIMD_TEST)
4349*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
4350*22dc650dSSadaf Ebrahimi 
4351*22dc650dSSadaf Ebrahimi 	if (reg_size == 4)
4352*22dc650dSSadaf Ebrahimi 		freg = simd_get_quad_reg_index(freg);
4353*22dc650dSSadaf Ebrahimi 
4354*22dc650dSSadaf Ebrahimi 	if (src & SLJIT_MEM) {
4355*22dc650dSSadaf Ebrahimi 		FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src, srcw));
4356*22dc650dSSadaf Ebrahimi 		if (reg_size == 4 && elem2_size - elem_size == 1)
4357*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, VLD1 | (0x7 << 8) | VD(freg) | RN(src) | 0xf));
4358*22dc650dSSadaf Ebrahimi 		else
4359*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, VLD1_s | (sljit_ins)((reg_size - elem2_size + elem_size) << 10) | VD(freg) | RN(src) | 0xf));
4360*22dc650dSSadaf Ebrahimi 		src = freg;
4361*22dc650dSSadaf Ebrahimi 	} else if (reg_size == 4)
4362*22dc650dSSadaf Ebrahimi 		src = simd_get_quad_reg_index(src);
4363*22dc650dSSadaf Ebrahimi 
4364*22dc650dSSadaf Ebrahimi 	if (!(type & SLJIT_SIMD_FLOAT)) {
4365*22dc650dSSadaf Ebrahimi 		dst_reg = (reg_size == 4) ? freg : TMP_FREG2;
4366*22dc650dSSadaf Ebrahimi 
4367*22dc650dSSadaf Ebrahimi 		do {
4368*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, VSHLL | ((type & SLJIT_SIMD_EXTEND_SIGNED) ? 0 : (1 << 24))
4369*22dc650dSSadaf Ebrahimi 				| ((sljit_ins)1 << (19 + elem_size)) | VD(dst_reg) | VM(src)));
4370*22dc650dSSadaf Ebrahimi 			src = dst_reg;
4371*22dc650dSSadaf Ebrahimi 		} while (++elem_size < elem2_size);
4372*22dc650dSSadaf Ebrahimi 
4373*22dc650dSSadaf Ebrahimi 		if (dst_reg == TMP_FREG2)
4374*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, VORR | VD(freg) | VN(TMP_FREG2) | VM(TMP_FREG2));
4375*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
4376*22dc650dSSadaf Ebrahimi 	}
4377*22dc650dSSadaf Ebrahimi 
4378*22dc650dSSadaf Ebrahimi 	/* No SIMD variant, must use VFP instead. */
4379*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(reg_size == 4);
4380*22dc650dSSadaf Ebrahimi 
4381*22dc650dSSadaf Ebrahimi 	if (freg == src) {
4382*22dc650dSSadaf Ebrahimi 		freg += SLJIT_QUAD_OTHER_HALF(freg);
4383*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, VCVT_F64_F32 | VD(freg) | VM(src) | 0x20));
4384*22dc650dSSadaf Ebrahimi 		freg += SLJIT_QUAD_OTHER_HALF(freg);
4385*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, VCVT_F64_F32 | VD(freg) | VM(src));
4386*22dc650dSSadaf Ebrahimi 	}
4387*22dc650dSSadaf Ebrahimi 
4388*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, VCVT_F64_F32 | VD(freg) | VM(src)));
4389*22dc650dSSadaf Ebrahimi 	freg += SLJIT_QUAD_OTHER_HALF(freg);
4390*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, VCVT_F64_F32 | VD(freg) | VM(src) | 0x20);
4391*22dc650dSSadaf Ebrahimi }
4392*22dc650dSSadaf Ebrahimi 
sljit_emit_simd_sign(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 freg,sljit_s32 dst,sljit_sw dstw)4393*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type,
4394*22dc650dSSadaf Ebrahimi 	sljit_s32 freg,
4395*22dc650dSSadaf Ebrahimi 	sljit_s32 dst, sljit_sw dstw)
4396*22dc650dSSadaf Ebrahimi {
4397*22dc650dSSadaf Ebrahimi 	sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
4398*22dc650dSSadaf Ebrahimi 	sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
4399*22dc650dSSadaf Ebrahimi 	sljit_ins ins, imms;
4400*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_r;
4401*22dc650dSSadaf Ebrahimi 
4402*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
4403*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_simd_sign(compiler, type, freg, dst, dstw));
4404*22dc650dSSadaf Ebrahimi 
4405*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(dst, dstw);
4406*22dc650dSSadaf Ebrahimi 
4407*22dc650dSSadaf Ebrahimi 	if (reg_size != 3 && reg_size != 4)
4408*22dc650dSSadaf Ebrahimi 		return SLJIT_ERR_UNSUPPORTED;
4409*22dc650dSSadaf Ebrahimi 
4410*22dc650dSSadaf Ebrahimi 	if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))
4411*22dc650dSSadaf Ebrahimi 		return SLJIT_ERR_UNSUPPORTED;
4412*22dc650dSSadaf Ebrahimi 
4413*22dc650dSSadaf Ebrahimi 	if (type & SLJIT_SIMD_TEST)
4414*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
4415*22dc650dSSadaf Ebrahimi 
4416*22dc650dSSadaf Ebrahimi 	switch (elem_size) {
4417*22dc650dSSadaf Ebrahimi 	case 0:
4418*22dc650dSSadaf Ebrahimi 		imms = 0x243219;
4419*22dc650dSSadaf Ebrahimi 		ins = VSHR | (1 << 24) | (0x9 << 16);
4420*22dc650dSSadaf Ebrahimi 		break;
4421*22dc650dSSadaf Ebrahimi 	case 1:
4422*22dc650dSSadaf Ebrahimi 		imms = (reg_size == 4) ? 0x243219 : 0x2231;
4423*22dc650dSSadaf Ebrahimi 		ins = VSHR | (1 << 24) | (0x11 << 16);
4424*22dc650dSSadaf Ebrahimi 		break;
4425*22dc650dSSadaf Ebrahimi 	case 2:
4426*22dc650dSSadaf Ebrahimi 		imms = (reg_size == 4) ? 0x2231 : 0x21;
4427*22dc650dSSadaf Ebrahimi 		ins = VSHR | (1 << 24) | (0x21 << 16);
4428*22dc650dSSadaf Ebrahimi 		break;
4429*22dc650dSSadaf Ebrahimi 	default:
4430*22dc650dSSadaf Ebrahimi 		imms = 0x21;
4431*22dc650dSSadaf Ebrahimi 		ins = VSHR | (1 << 24) | (0x1 << 16) | (1 << 7);
4432*22dc650dSSadaf Ebrahimi 		break;
4433*22dc650dSSadaf Ebrahimi 	}
4434*22dc650dSSadaf Ebrahimi 
4435*22dc650dSSadaf Ebrahimi 	if (reg_size == 4) {
4436*22dc650dSSadaf Ebrahimi 		freg = simd_get_quad_reg_index(freg);
4437*22dc650dSSadaf Ebrahimi 		ins |= (sljit_ins)1 << 6;
4438*22dc650dSSadaf Ebrahimi 	}
4439*22dc650dSSadaf Ebrahimi 
4440*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT((freg_map[TMP_FREG2] & 0x1) == 0);
4441*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, ins | VD(TMP_FREG2) | VM(freg)));
4442*22dc650dSSadaf Ebrahimi 
4443*22dc650dSSadaf Ebrahimi 	if (reg_size == 4 && elem_size > 0)
4444*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, VMOVN | ((sljit_ins)(elem_size - 1) << 18) | VD(TMP_FREG2) | VM(TMP_FREG2)));
4445*22dc650dSSadaf Ebrahimi 
4446*22dc650dSSadaf Ebrahimi 	ins = (reg_size == 4 && elem_size == 0) ? (1 << 6) : 0;
4447*22dc650dSSadaf Ebrahimi 
4448*22dc650dSSadaf Ebrahimi 	while (imms >= 0x100) {
4449*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, VSRA | (1 << 24) | ins | ((imms & 0xff) << 16) | VD(TMP_FREG2) | VM(TMP_FREG2)));
4450*22dc650dSSadaf Ebrahimi 		imms >>= 8;
4451*22dc650dSSadaf Ebrahimi 	}
4452*22dc650dSSadaf Ebrahimi 
4453*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, VSRA | (1 << 24) | ins | (1 << 7) | (imms << 16) | VD(TMP_FREG2) | VM(TMP_FREG2)));
4454*22dc650dSSadaf Ebrahimi 
4455*22dc650dSSadaf Ebrahimi 	dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
4456*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, VMOV_s | (1 << 20) | (1 << 23) | (0x2 << 21) | RD(dst_r) | VN(TMP_FREG2)));
4457*22dc650dSSadaf Ebrahimi 
4458*22dc650dSSadaf Ebrahimi 	if (reg_size == 4 && elem_size == 0) {
4459*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(freg_map[TMP_FREG2] + 1 == freg_map[TMP_FREG1]);
4460*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, VMOV_s | (1 << 20) | (1 << 23) | (0x2 << 21) | RD(TMP_REG2) | VN(TMP_FREG1)));
4461*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ORR | RD(dst_r) | RN(dst_r) | RM(TMP_REG2) | (0x8 << 7)));
4462*22dc650dSSadaf Ebrahimi 	}
4463*22dc650dSSadaf Ebrahimi 
4464*22dc650dSSadaf Ebrahimi 	if (dst_r == TMP_REG1)
4465*22dc650dSSadaf Ebrahimi 		return emit_op_mem(compiler, WORD_SIZE, TMP_REG1, dst, dstw, TMP_REG2);
4466*22dc650dSSadaf Ebrahimi 
4467*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
4468*22dc650dSSadaf Ebrahimi }
4469*22dc650dSSadaf Ebrahimi 
sljit_emit_simd_op2(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 dst_freg,sljit_s32 src1_freg,sljit_s32 src2_freg)4470*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type,
4471*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_freg, sljit_s32 src1_freg, sljit_s32 src2_freg)
4472*22dc650dSSadaf Ebrahimi {
4473*22dc650dSSadaf Ebrahimi 	sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
4474*22dc650dSSadaf Ebrahimi 	sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
4475*22dc650dSSadaf Ebrahimi 	sljit_ins ins = 0;
4476*22dc650dSSadaf Ebrahimi 
4477*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
4478*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_simd_op2(compiler, type, dst_freg, src1_freg, src2_freg));
4479*22dc650dSSadaf Ebrahimi 
4480*22dc650dSSadaf Ebrahimi 	if (reg_size != 3 && reg_size != 4)
4481*22dc650dSSadaf Ebrahimi 		return SLJIT_ERR_UNSUPPORTED;
4482*22dc650dSSadaf Ebrahimi 
4483*22dc650dSSadaf Ebrahimi 	if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))
4484*22dc650dSSadaf Ebrahimi 		return SLJIT_ERR_UNSUPPORTED;
4485*22dc650dSSadaf Ebrahimi 
4486*22dc650dSSadaf Ebrahimi 	switch (SLJIT_SIMD_GET_OPCODE(type)) {
4487*22dc650dSSadaf Ebrahimi 	case SLJIT_SIMD_OP2_AND:
4488*22dc650dSSadaf Ebrahimi 		ins = VAND;
4489*22dc650dSSadaf Ebrahimi 		break;
4490*22dc650dSSadaf Ebrahimi 	case SLJIT_SIMD_OP2_OR:
4491*22dc650dSSadaf Ebrahimi 		ins = VORR;
4492*22dc650dSSadaf Ebrahimi 		break;
4493*22dc650dSSadaf Ebrahimi 	case SLJIT_SIMD_OP2_XOR:
4494*22dc650dSSadaf Ebrahimi 		ins = VEOR;
4495*22dc650dSSadaf Ebrahimi 		break;
4496*22dc650dSSadaf Ebrahimi 	}
4497*22dc650dSSadaf Ebrahimi 
4498*22dc650dSSadaf Ebrahimi 	if (type & SLJIT_SIMD_TEST)
4499*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
4500*22dc650dSSadaf Ebrahimi 
4501*22dc650dSSadaf Ebrahimi 	if (reg_size == 4) {
4502*22dc650dSSadaf Ebrahimi 		dst_freg = simd_get_quad_reg_index(dst_freg);
4503*22dc650dSSadaf Ebrahimi 		src1_freg = simd_get_quad_reg_index(src1_freg);
4504*22dc650dSSadaf Ebrahimi 		src2_freg = simd_get_quad_reg_index(src2_freg);
4505*22dc650dSSadaf Ebrahimi 		ins |= (sljit_ins)1 << 6;
4506*22dc650dSSadaf Ebrahimi 	}
4507*22dc650dSSadaf Ebrahimi 
4508*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, ins | VD(dst_freg) | VN(src1_freg) | VM(src2_freg));
4509*22dc650dSSadaf Ebrahimi }
4510*22dc650dSSadaf Ebrahimi 
4511*22dc650dSSadaf Ebrahimi #undef FPU_LOAD
4512*22dc650dSSadaf Ebrahimi 
sljit_emit_atomic_load(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst_reg,sljit_s32 mem_reg)4513*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op,
4514*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_reg,
4515*22dc650dSSadaf Ebrahimi 	sljit_s32 mem_reg)
4516*22dc650dSSadaf Ebrahimi {
4517*22dc650dSSadaf Ebrahimi 	sljit_u32 ins;
4518*22dc650dSSadaf Ebrahimi 
4519*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
4520*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg));
4521*22dc650dSSadaf Ebrahimi 
4522*22dc650dSSadaf Ebrahimi 	switch (GET_OPCODE(op)) {
4523*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_U8:
4524*22dc650dSSadaf Ebrahimi 		ins = LDREXB;
4525*22dc650dSSadaf Ebrahimi 		break;
4526*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_U16:
4527*22dc650dSSadaf Ebrahimi 		ins = LDREXH;
4528*22dc650dSSadaf Ebrahimi 		break;
4529*22dc650dSSadaf Ebrahimi 	default:
4530*22dc650dSSadaf Ebrahimi 		ins = LDREX;
4531*22dc650dSSadaf Ebrahimi 		break;
4532*22dc650dSSadaf Ebrahimi 	}
4533*22dc650dSSadaf Ebrahimi 
4534*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, ins | RN(mem_reg) | RD(dst_reg));
4535*22dc650dSSadaf Ebrahimi }
4536*22dc650dSSadaf Ebrahimi 
sljit_emit_atomic_store(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 src_reg,sljit_s32 mem_reg,sljit_s32 temp_reg)4537*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op,
4538*22dc650dSSadaf Ebrahimi 	sljit_s32 src_reg,
4539*22dc650dSSadaf Ebrahimi 	sljit_s32 mem_reg,
4540*22dc650dSSadaf Ebrahimi 	sljit_s32 temp_reg)
4541*22dc650dSSadaf Ebrahimi {
4542*22dc650dSSadaf Ebrahimi 	sljit_u32 ins;
4543*22dc650dSSadaf Ebrahimi 
4544*22dc650dSSadaf Ebrahimi 	/* temp_reg == mem_reg is undefined so use another temp register */
4545*22dc650dSSadaf Ebrahimi 	SLJIT_UNUSED_ARG(temp_reg);
4546*22dc650dSSadaf Ebrahimi 
4547*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
4548*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg));
4549*22dc650dSSadaf Ebrahimi 
4550*22dc650dSSadaf Ebrahimi 	switch (GET_OPCODE(op)) {
4551*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_U8:
4552*22dc650dSSadaf Ebrahimi 		ins = STREXB;
4553*22dc650dSSadaf Ebrahimi 		break;
4554*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_U16:
4555*22dc650dSSadaf Ebrahimi 		ins = STREXH;
4556*22dc650dSSadaf Ebrahimi 		break;
4557*22dc650dSSadaf Ebrahimi 	default:
4558*22dc650dSSadaf Ebrahimi 		ins = STREX;
4559*22dc650dSSadaf Ebrahimi 		break;
4560*22dc650dSSadaf Ebrahimi 	}
4561*22dc650dSSadaf Ebrahimi 
4562*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, ins | RN(mem_reg) | RD(TMP_REG1) | RM(src_reg)));
4563*22dc650dSSadaf Ebrahimi 	if (op & SLJIT_SET_ATOMIC_STORED)
4564*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, CMP | SET_FLAGS | SRC2_IMM | RN(TMP_REG1));
4565*22dc650dSSadaf Ebrahimi 
4566*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
4567*22dc650dSSadaf Ebrahimi }
4568*22dc650dSSadaf Ebrahimi 
sljit_emit_const(struct sljit_compiler * compiler,sljit_s32 dst,sljit_sw dstw,sljit_sw init_value)4569*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
4570*22dc650dSSadaf Ebrahimi {
4571*22dc650dSSadaf Ebrahimi 	struct sljit_const *const_;
4572*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_r;
4573*22dc650dSSadaf Ebrahimi 
4574*22dc650dSSadaf Ebrahimi 	CHECK_ERROR_PTR();
4575*22dc650dSSadaf Ebrahimi 	CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
4576*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(dst, dstw);
4577*22dc650dSSadaf Ebrahimi 
4578*22dc650dSSadaf Ebrahimi 	const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
4579*22dc650dSSadaf Ebrahimi 	PTR_FAIL_IF(!const_);
4580*22dc650dSSadaf Ebrahimi 	set_const(const_, compiler);
4581*22dc650dSSadaf Ebrahimi 
4582*22dc650dSSadaf Ebrahimi 	dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
4583*22dc650dSSadaf Ebrahimi 
4584*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
4585*22dc650dSSadaf Ebrahimi 	PTR_FAIL_IF(push_inst_with_unique_literal(compiler,
4586*22dc650dSSadaf Ebrahimi 		EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, dst_r, TMP_PC, 0), (sljit_ins)init_value));
4587*22dc650dSSadaf Ebrahimi 	compiler->patches++;
4588*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_ARM_V6 */
4589*22dc650dSSadaf Ebrahimi 	PTR_FAIL_IF(emit_imm(compiler, dst_r, init_value));
4590*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_ARM_V6 */
4591*22dc650dSSadaf Ebrahimi 
4592*22dc650dSSadaf Ebrahimi 	if (dst & SLJIT_MEM)
4593*22dc650dSSadaf Ebrahimi 		PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1));
4594*22dc650dSSadaf Ebrahimi 	return const_;
4595*22dc650dSSadaf Ebrahimi }
4596*22dc650dSSadaf Ebrahimi 
sljit_emit_mov_addr(struct sljit_compiler * compiler,sljit_s32 dst,sljit_sw dstw)4597*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
4598*22dc650dSSadaf Ebrahimi {
4599*22dc650dSSadaf Ebrahimi 	struct sljit_jump *jump;
4600*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_r;
4601*22dc650dSSadaf Ebrahimi 
4602*22dc650dSSadaf Ebrahimi 	CHECK_ERROR_PTR();
4603*22dc650dSSadaf Ebrahimi 	CHECK_PTR(check_sljit_emit_mov_addr(compiler, dst, dstw));
4604*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(dst, dstw);
4605*22dc650dSSadaf Ebrahimi 
4606*22dc650dSSadaf Ebrahimi 	dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
4607*22dc650dSSadaf Ebrahimi 
4608*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
4609*22dc650dSSadaf Ebrahimi 	PTR_FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, dst_r, TMP_PC, 0), 0));
4610*22dc650dSSadaf Ebrahimi 	compiler->patches++;
4611*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_ARM_V6 */
4612*22dc650dSSadaf Ebrahimi 	PTR_FAIL_IF(push_inst(compiler, RD(dst_r)));
4613*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_ARM_V6 */
4614*22dc650dSSadaf Ebrahimi 
4615*22dc650dSSadaf Ebrahimi 	jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
4616*22dc650dSSadaf Ebrahimi 	PTR_FAIL_IF(!jump);
4617*22dc650dSSadaf Ebrahimi 	set_mov_addr(jump, compiler, 1);
4618*22dc650dSSadaf Ebrahimi 
4619*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
4620*22dc650dSSadaf Ebrahimi 	compiler->size += 1;
4621*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_ARM_V7 */
4622*22dc650dSSadaf Ebrahimi 
4623*22dc650dSSadaf Ebrahimi 	if (dst & SLJIT_MEM)
4624*22dc650dSSadaf Ebrahimi 		PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1));
4625*22dc650dSSadaf Ebrahimi 	return jump;
4626*22dc650dSSadaf Ebrahimi }
4627*22dc650dSSadaf Ebrahimi 
sljit_set_jump_addr(sljit_uw addr,sljit_uw new_target,sljit_sw executable_offset)4628*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
4629*22dc650dSSadaf Ebrahimi {
4630*22dc650dSSadaf Ebrahimi 	set_jump_addr(addr, executable_offset, new_target, 1);
4631*22dc650dSSadaf Ebrahimi }
4632*22dc650dSSadaf Ebrahimi 
sljit_set_const(sljit_uw addr,sljit_sw new_constant,sljit_sw executable_offset)4633*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
4634*22dc650dSSadaf Ebrahimi {
4635*22dc650dSSadaf Ebrahimi 	set_const_value(addr, executable_offset, (sljit_uw)new_constant, 1);
4636*22dc650dSSadaf Ebrahimi }
4637