• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *    Stack-less Just-In-Time compiler
3  *
4  *    Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without modification, are
7  * permitted provided that the following conditions are met:
8  *
9  *   1. Redistributions of source code must retain the above copyright notice, this list of
10  *      conditions and the following disclaimer.
11  *
12  *   2. Redistributions in binary form must reproduce the above copyright notice, this list
13  *      of conditions and the following disclaimer in the documentation and/or other materials
14  *      provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19  * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
22  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #ifdef __SOFTFP__
28 #define ARM_ABI_INFO " ABI:softfp"
29 #else
30 #define ARM_ABI_INFO " ABI:hardfp"
31 #endif
32 
sljit_get_platform_name(void)33 SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
34 {
35 #if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
36 	return "ARMv7" SLJIT_CPUINFO ARM_ABI_INFO;
37 #elif (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
38 	return "ARMv5" SLJIT_CPUINFO ARM_ABI_INFO;
39 #else
40 #error "Internal error: Unknown ARM architecture"
41 #endif
42 }
43 
44 /* Last register + 1. */
45 #define TMP_REG1	(SLJIT_NUMBER_OF_REGISTERS + 2)
46 #define TMP_REG2	(SLJIT_NUMBER_OF_REGISTERS + 3)
47 #define TMP_PC		(SLJIT_NUMBER_OF_REGISTERS + 4)
48 
49 #define TMP_FREG1	(SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
50 #define TMP_FREG2	(SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)
51 
52 /* In ARM instruction words.
53    Cache lines are usually 32 byte aligned. */
54 #define CONST_POOL_ALIGNMENT	8
55 #define CONST_POOL_EMPTY	0xffffffff
56 
57 #define ALIGN_INSTRUCTION(ptr) \
58 	(sljit_uw*)(((sljit_uw)(ptr) + (CONST_POOL_ALIGNMENT * sizeof(sljit_uw)) - 1) & ~((CONST_POOL_ALIGNMENT * sizeof(sljit_uw)) - 1))
59 #define MAX_DIFFERENCE(max_diff) \
60 	(((max_diff) / (sljit_s32)sizeof(sljit_uw)) - (CONST_POOL_ALIGNMENT - 1))
61 
62 /* See sljit_emit_enter and sljit_emit_op0 if you want to change them. */
63 static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
64 	0, 0, 1, 2, 3, 11, 10, 9, 8, 7, 6, 5, 4, 13, 12, 14, 15
65 };
66 
67 static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
68 	0, 0, 1, 2, 3, 4, 5, 15, 14, 13, 12, 11, 10, 9, 8, 6, 7
69 };
70 
71 #define RM(rm) ((sljit_uw)reg_map[rm])
72 #define RM8(rm) ((sljit_uw)reg_map[rm] << 8)
73 #define RD(rd) ((sljit_uw)reg_map[rd] << 12)
74 #define RN(rn) ((sljit_uw)reg_map[rn] << 16)
75 
76 #define VM(rm) ((sljit_uw)freg_map[rm])
77 #define VD(rd) ((sljit_uw)freg_map[rd] << 12)
78 #define VN(rn) ((sljit_uw)freg_map[rn] << 16)
79 
80 /* --------------------------------------------------------------------- */
81 /*  Instrucion forms                                                     */
82 /* --------------------------------------------------------------------- */
83 
84 /* The instruction includes the AL condition.
85    INST_NAME - CONDITIONAL remove this flag. */
86 #define COND_MASK	0xf0000000
87 #define CONDITIONAL	0xe0000000
88 #define PUSH_POOL	0xff000000
89 
90 #define ADC		0xe0a00000
91 #define ADD		0xe0800000
92 #define AND		0xe0000000
93 #define B		0xea000000
94 #define BIC		0xe1c00000
95 #define BL		0xeb000000
96 #define BLX		0xe12fff30
97 #define BX		0xe12fff10
98 #define CLZ		0xe16f0f10
99 #define CMN		0xe1600000
100 #define CMP		0xe1400000
101 #define BKPT		0xe1200070
102 #define EOR		0xe0200000
103 #define MOV		0xe1a00000
104 #define MUL		0xe0000090
105 #define MVN		0xe1e00000
106 #define NOP		0xe1a00000
107 #define ORR		0xe1800000
108 #define PUSH		0xe92d0000
109 #define POP		0xe8bd0000
110 #define RSB		0xe0600000
111 #define RSC		0xe0e00000
112 #define SBC		0xe0c00000
113 #define SMULL		0xe0c00090
114 #define SUB		0xe0400000
115 #define TST		0xe1000000
116 #define UMULL		0xe0800090
117 #define VABS_F32	0xeeb00ac0
118 #define VADD_F32	0xee300a00
119 #define VCMP_F32	0xeeb40a40
120 #define VCVT_F32_S32	0xeeb80ac0
121 #define VCVT_F64_F32	0xeeb70ac0
122 #define VCVT_S32_F32	0xeebd0ac0
123 #define VDIV_F32	0xee800a00
124 #define VLDR_F32	0xed100a00
125 #define VMOV_F32	0xeeb00a40
126 #define VMOV		0xee000a10
127 #define VMOV2		0xec400a10
128 #define VMRS		0xeef1fa10
129 #define VMUL_F32	0xee200a00
130 #define VNEG_F32	0xeeb10a40
131 #define VPOP		0xecbd0b00
132 #define VPUSH		0xed2d0b00
133 #define VSTR_F32	0xed000a00
134 #define VSUB_F32	0xee300a40
135 
136 #if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
137 /* Arm v7 specific instructions. */
138 #define MOVW		0xe3000000
139 #define MOVT		0xe3400000
140 #define SXTB		0xe6af0070
141 #define SXTH		0xe6bf0070
142 #define UXTB		0xe6ef0070
143 #define UXTH		0xe6ff0070
144 #endif
145 
146 #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
147 
push_cpool(struct sljit_compiler * compiler)148 static sljit_s32 push_cpool(struct sljit_compiler *compiler)
149 {
150 	/* Pushing the constant pool into the instruction stream. */
151 	sljit_uw* inst;
152 	sljit_uw* cpool_ptr;
153 	sljit_uw* cpool_end;
154 	sljit_s32 i;
155 
156 	/* The label could point the address after the constant pool. */
157 	if (compiler->last_label && compiler->last_label->size == compiler->size)
158 		compiler->last_label->size += compiler->cpool_fill + (CONST_POOL_ALIGNMENT - 1) + 1;
159 
160 	SLJIT_ASSERT(compiler->cpool_fill > 0 && compiler->cpool_fill <= CPOOL_SIZE);
161 	inst = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw));
162 	FAIL_IF(!inst);
163 	compiler->size++;
164 	*inst = 0xff000000 | compiler->cpool_fill;
165 
166 	for (i = 0; i < CONST_POOL_ALIGNMENT - 1; i++) {
167 		inst = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw));
168 		FAIL_IF(!inst);
169 		compiler->size++;
170 		*inst = 0;
171 	}
172 
173 	cpool_ptr = compiler->cpool;
174 	cpool_end = cpool_ptr + compiler->cpool_fill;
175 	while (cpool_ptr < cpool_end) {
176 		inst = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw));
177 		FAIL_IF(!inst);
178 		compiler->size++;
179 		*inst = *cpool_ptr++;
180 	}
181 	compiler->cpool_diff = CONST_POOL_EMPTY;
182 	compiler->cpool_fill = 0;
183 	return SLJIT_SUCCESS;
184 }
185 
push_inst(struct sljit_compiler * compiler,sljit_uw inst)186 static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_uw inst)
187 {
188 	sljit_uw* ptr;
189 
190 	if (SLJIT_UNLIKELY(compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4092)))
191 		FAIL_IF(push_cpool(compiler));
192 
193 	ptr = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw));
194 	FAIL_IF(!ptr);
195 	compiler->size++;
196 	*ptr = inst;
197 	return SLJIT_SUCCESS;
198 }
199 
push_inst_with_literal(struct sljit_compiler * compiler,sljit_uw inst,sljit_uw literal)200 static sljit_s32 push_inst_with_literal(struct sljit_compiler *compiler, sljit_uw inst, sljit_uw literal)
201 {
202 	sljit_uw* ptr;
203 	sljit_uw cpool_index = CPOOL_SIZE;
204 	sljit_uw* cpool_ptr;
205 	sljit_uw* cpool_end;
206 	sljit_u8* cpool_unique_ptr;
207 
208 	if (SLJIT_UNLIKELY(compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4092)))
209 		FAIL_IF(push_cpool(compiler));
210 	else if (compiler->cpool_fill > 0) {
211 		cpool_ptr = compiler->cpool;
212 		cpool_end = cpool_ptr + compiler->cpool_fill;
213 		cpool_unique_ptr = compiler->cpool_unique;
214 		do {
215 			if ((*cpool_ptr == literal) && !(*cpool_unique_ptr)) {
216 				cpool_index = (sljit_uw)(cpool_ptr - compiler->cpool);
217 				break;
218 			}
219 			cpool_ptr++;
220 			cpool_unique_ptr++;
221 		} while (cpool_ptr < cpool_end);
222 	}
223 
224 	if (cpool_index == CPOOL_SIZE) {
225 		/* Must allocate a new entry in the literal pool. */
226 		if (compiler->cpool_fill < CPOOL_SIZE) {
227 			cpool_index = compiler->cpool_fill;
228 			compiler->cpool_fill++;
229 		}
230 		else {
231 			FAIL_IF(push_cpool(compiler));
232 			cpool_index = 0;
233 			compiler->cpool_fill = 1;
234 		}
235 	}
236 
237 	SLJIT_ASSERT((inst & 0xfff) == 0);
238 	ptr = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw));
239 	FAIL_IF(!ptr);
240 	compiler->size++;
241 	*ptr = inst | cpool_index;
242 
243 	compiler->cpool[cpool_index] = literal;
244 	compiler->cpool_unique[cpool_index] = 0;
245 	if (compiler->cpool_diff == CONST_POOL_EMPTY)
246 		compiler->cpool_diff = compiler->size;
247 	return SLJIT_SUCCESS;
248 }
249 
push_inst_with_unique_literal(struct sljit_compiler * compiler,sljit_uw inst,sljit_uw literal)250 static sljit_s32 push_inst_with_unique_literal(struct sljit_compiler *compiler, sljit_uw inst, sljit_uw literal)
251 {
252 	sljit_uw* ptr;
253 	if (SLJIT_UNLIKELY((compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4092)) || compiler->cpool_fill >= CPOOL_SIZE))
254 		FAIL_IF(push_cpool(compiler));
255 
256 	SLJIT_ASSERT(compiler->cpool_fill < CPOOL_SIZE && (inst & 0xfff) == 0);
257 	ptr = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw));
258 	FAIL_IF(!ptr);
259 	compiler->size++;
260 	*ptr = inst | compiler->cpool_fill;
261 
262 	compiler->cpool[compiler->cpool_fill] = literal;
263 	compiler->cpool_unique[compiler->cpool_fill] = 1;
264 	compiler->cpool_fill++;
265 	if (compiler->cpool_diff == CONST_POOL_EMPTY)
266 		compiler->cpool_diff = compiler->size;
267 	return SLJIT_SUCCESS;
268 }
269 
prepare_blx(struct sljit_compiler * compiler)270 static SLJIT_INLINE sljit_s32 prepare_blx(struct sljit_compiler *compiler)
271 {
272 	/* Place for at least two instruction (doesn't matter whether the first has a literal). */
273 	if (SLJIT_UNLIKELY(compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4088)))
274 		return push_cpool(compiler);
275 	return SLJIT_SUCCESS;
276 }
277 
emit_blx(struct sljit_compiler * compiler)278 static SLJIT_INLINE sljit_s32 emit_blx(struct sljit_compiler *compiler)
279 {
280 	/* Must follow tightly the previous instruction (to be able to convert it to bl instruction). */
281 	SLJIT_ASSERT(compiler->cpool_diff == CONST_POOL_EMPTY || compiler->size - compiler->cpool_diff < MAX_DIFFERENCE(4092));
282 	SLJIT_ASSERT(reg_map[TMP_REG1] != 14);
283 
284 	return push_inst(compiler, BLX | RM(TMP_REG1));
285 }
286 
patch_pc_relative_loads(sljit_uw * last_pc_patch,sljit_uw * code_ptr,sljit_uw * const_pool,sljit_uw cpool_size)287 static sljit_uw patch_pc_relative_loads(sljit_uw *last_pc_patch, sljit_uw *code_ptr, sljit_uw* const_pool, sljit_uw cpool_size)
288 {
289 	sljit_uw diff;
290 	sljit_uw ind;
291 	sljit_uw counter = 0;
292 	sljit_uw* clear_const_pool = const_pool;
293 	sljit_uw* clear_const_pool_end = const_pool + cpool_size;
294 
295 	SLJIT_ASSERT(const_pool - code_ptr <= CONST_POOL_ALIGNMENT);
296 	/* Set unused flag for all literals in the constant pool.
297 	   I.e.: unused literals can belong to branches, which can be encoded as B or BL.
298 	   We can "compress" the constant pool by discarding these literals. */
299 	while (clear_const_pool < clear_const_pool_end)
300 		*clear_const_pool++ = (sljit_uw)(-1);
301 
302 	while (last_pc_patch < code_ptr) {
303 		/* Data transfer instruction with Rn == r15. */
304 		if ((*last_pc_patch & 0x0c0f0000) == 0x040f0000) {
305 			diff = (sljit_uw)(const_pool - last_pc_patch);
306 			ind = (*last_pc_patch) & 0xfff;
307 
308 			/* Must be a load instruction with immediate offset. */
309 			SLJIT_ASSERT(ind < cpool_size && !(*last_pc_patch & (1 << 25)) && (*last_pc_patch & (1 << 20)));
310 			if ((sljit_s32)const_pool[ind] < 0) {
311 				const_pool[ind] = counter;
312 				ind = counter;
313 				counter++;
314 			}
315 			else
316 				ind = const_pool[ind];
317 
318 			SLJIT_ASSERT(diff >= 1);
319 			if (diff >= 2 || ind > 0) {
320 				diff = (diff + (sljit_uw)ind - 2) << 2;
321 				SLJIT_ASSERT(diff <= 0xfff);
322 				*last_pc_patch = (*last_pc_patch & ~(sljit_uw)0xfff) | diff;
323 			}
324 			else
325 				*last_pc_patch = (*last_pc_patch & ~(sljit_uw)(0xfff | (1 << 23))) | 0x004;
326 		}
327 		last_pc_patch++;
328 	}
329 	return counter;
330 }
331 
332 /* In some rare ocasions we may need future patches. The probability is close to 0 in practice. */
333 struct future_patch {
334 	struct future_patch* next;
335 	sljit_s32 index;
336 	sljit_s32 value;
337 };
338 
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)339 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)
340 {
341 	sljit_u32 value;
342 	struct future_patch *curr_patch, *prev_patch;
343 
344 	SLJIT_UNUSED_ARG(compiler);
345 
346 	/* Using the values generated by patch_pc_relative_loads. */
347 	if (!*first_patch)
348 		value = cpool_start_address[cpool_current_index];
349 	else {
350 		curr_patch = *first_patch;
351 		prev_patch = NULL;
352 		while (1) {
353 			if (!curr_patch) {
354 				value = cpool_start_address[cpool_current_index];
355 				break;
356 			}
357 			if ((sljit_uw)curr_patch->index == cpool_current_index) {
358 				value = (sljit_uw)curr_patch->value;
359 				if (prev_patch)
360 					prev_patch->next = curr_patch->next;
361 				else
362 					*first_patch = curr_patch->next;
363 				SLJIT_FREE(curr_patch, compiler->allocator_data);
364 				break;
365 			}
366 			prev_patch = curr_patch;
367 			curr_patch = curr_patch->next;
368 		}
369 	}
370 
371 	if ((sljit_sw)value >= 0) {
372 		if (value > cpool_current_index) {
373 			curr_patch = (struct future_patch*)SLJIT_MALLOC(sizeof(struct future_patch), compiler->allocator_data);
374 			if (!curr_patch) {
375 				while (*first_patch) {
376 					curr_patch = *first_patch;
377 					*first_patch = (*first_patch)->next;
378 					SLJIT_FREE(curr_patch, compiler->allocator_data);
379 				}
380 				return SLJIT_ERR_ALLOC_FAILED;
381 			}
382 			curr_patch->next = *first_patch;
383 			curr_patch->index = (sljit_sw)value;
384 			curr_patch->value = (sljit_sw)cpool_start_address[value];
385 			*first_patch = curr_patch;
386 		}
387 		cpool_start_address[value] = *buf_ptr;
388 	}
389 	return SLJIT_SUCCESS;
390 }
391 
392 #else
393 
push_inst(struct sljit_compiler * compiler,sljit_uw inst)394 static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_uw inst)
395 {
396 	sljit_uw* ptr;
397 
398 	ptr = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw));
399 	FAIL_IF(!ptr);
400 	compiler->size++;
401 	*ptr = inst;
402 	return SLJIT_SUCCESS;
403 }
404 
emit_imm(struct sljit_compiler * compiler,sljit_s32 reg,sljit_sw imm)405 static SLJIT_INLINE sljit_s32 emit_imm(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm)
406 {
407 	FAIL_IF(push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | ((sljit_u32)imm & 0xfff)));
408 	return push_inst(compiler, MOVT | RD(reg) | ((imm >> 12) & 0xf0000) | (((sljit_u32)imm >> 16) & 0xfff));
409 }
410 
411 #endif
412 
detect_jump_type(struct sljit_jump * jump,sljit_uw * code_ptr,sljit_uw * code,sljit_sw executable_offset)413 static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_uw *code_ptr, sljit_uw *code, sljit_sw executable_offset)
414 {
415 	sljit_sw diff;
416 
417 	if (jump->flags & SLJIT_REWRITABLE_JUMP)
418 		return 0;
419 
420 #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
421 	if (jump->flags & IS_BL)
422 		code_ptr--;
423 
424 	if (jump->flags & JUMP_ADDR)
425 		diff = ((sljit_sw)jump->u.target - (sljit_sw)(code_ptr + 2) - executable_offset);
426 	else {
427 		SLJIT_ASSERT(jump->flags & JUMP_LABEL);
428 		diff = ((sljit_sw)(code + jump->u.label->size) - (sljit_sw)(code_ptr + 2));
429 	}
430 
431 	/* Branch to Thumb code has not been optimized yet. */
432 	if (diff & 0x3)
433 		return 0;
434 
435 	if (jump->flags & IS_BL) {
436 		if (diff <= 0x01ffffff && diff >= -0x02000000) {
437 			*code_ptr = (BL - CONDITIONAL) | (*(code_ptr + 1) & COND_MASK);
438 			jump->flags |= PATCH_B;
439 			return 1;
440 		}
441 	}
442 	else {
443 		if (diff <= 0x01ffffff && diff >= -0x02000000) {
444 			*code_ptr = (B - CONDITIONAL) | (*code_ptr & COND_MASK);
445 			jump->flags |= PATCH_B;
446 		}
447 	}
448 #else
449 	if (jump->flags & JUMP_ADDR)
450 		diff = ((sljit_sw)jump->u.target - (sljit_sw)code_ptr - executable_offset);
451 	else {
452 		SLJIT_ASSERT(jump->flags & JUMP_LABEL);
453 		diff = ((sljit_sw)(code + jump->u.label->size) - (sljit_sw)code_ptr);
454 	}
455 
456 	/* Branch to Thumb code has not been optimized yet. */
457 	if (diff & 0x3)
458 		return 0;
459 
460 	if (diff <= 0x01ffffff && diff >= -0x02000000) {
461 		code_ptr -= 2;
462 		*code_ptr = ((jump->flags & IS_BL) ? (BL - CONDITIONAL) : (B - CONDITIONAL)) | (code_ptr[2] & COND_MASK);
463 		jump->flags |= PATCH_B;
464 		return 1;
465 	}
466 #endif
467 	return 0;
468 }
469 
inline_set_jump_addr(sljit_uw jump_ptr,sljit_sw executable_offset,sljit_uw new_addr,sljit_s32 flush_cache)470 static SLJIT_INLINE void inline_set_jump_addr(sljit_uw jump_ptr, sljit_sw executable_offset, sljit_uw new_addr, sljit_s32 flush_cache)
471 {
472 #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
473 	sljit_uw *ptr = (sljit_uw *)jump_ptr;
474 	sljit_uw *inst = (sljit_uw *)ptr[0];
475 	sljit_uw mov_pc = ptr[1];
476 	sljit_s32 bl = (mov_pc & 0x0000f000) != RD(TMP_PC);
477 	sljit_sw diff = (sljit_sw)(((sljit_sw)new_addr - (sljit_sw)(inst + 2) - executable_offset) >> 2);
478 
479 	SLJIT_UNUSED_ARG(executable_offset);
480 
481 	if (diff <= 0x7fffff && diff >= -0x800000) {
482 		/* Turn to branch. */
483 		if (!bl) {
484 			if (flush_cache) {
485 				SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);
486 			}
487 			inst[0] = (mov_pc & COND_MASK) | (B - CONDITIONAL) | (diff & 0xffffff);
488 			if (flush_cache) {
489 				SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);
490 				inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
491 				SLJIT_CACHE_FLUSH(inst, inst + 1);
492 			}
493 		} else {
494 			if (flush_cache) {
495 				SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);
496 			}
497 			inst[0] = (mov_pc & COND_MASK) | (BL - CONDITIONAL) | (diff & 0xffffff);
498 			inst[1] = NOP;
499 			if (flush_cache) {
500 				SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
501 				inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
502 				SLJIT_CACHE_FLUSH(inst, inst + 2);
503 			}
504 		}
505 	} else {
506 		/* Get the position of the constant. */
507 		if (mov_pc & (1 << 23))
508 			ptr = inst + ((mov_pc & 0xfff) >> 2) + 2;
509 		else
510 			ptr = inst + 1;
511 
512 		if (*inst != mov_pc) {
513 			if (flush_cache) {
514 				SLJIT_UPDATE_WX_FLAGS(inst, inst + (!bl ? 1 : 2), 0);
515 			}
516 			inst[0] = mov_pc;
517 			if (!bl) {
518 				if (flush_cache) {
519 					SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);
520 					inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
521 					SLJIT_CACHE_FLUSH(inst, inst + 1);
522 				}
523 			} else {
524 				inst[1] = BLX | RM(TMP_REG1);
525 				if (flush_cache) {
526 					SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
527 					inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
528 					SLJIT_CACHE_FLUSH(inst, inst + 2);
529 				}
530 			}
531 		}
532 
533 		if (flush_cache) {
534 			SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 0);
535 		}
536 
537 		*ptr = new_addr;
538 
539 		if (flush_cache) {
540 			SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 1);
541 		}
542 	}
543 #else
544 	sljit_uw *inst = (sljit_uw*)jump_ptr;
545 
546 	SLJIT_UNUSED_ARG(executable_offset);
547 
548 	SLJIT_ASSERT((inst[0] & 0xfff00000) == MOVW && (inst[1] & 0xfff00000) == MOVT);
549 
550 	if (flush_cache) {
551 		SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);
552 	}
553 
554 	inst[0] = MOVW | (inst[0] & 0xf000) | ((new_addr << 4) & 0xf0000) | (new_addr & 0xfff);
555 	inst[1] = MOVT | (inst[1] & 0xf000) | ((new_addr >> 12) & 0xf0000) | ((new_addr >> 16) & 0xfff);
556 
557 	if (flush_cache) {
558 		SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
559 		inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
560 		SLJIT_CACHE_FLUSH(inst, inst + 2);
561 	}
562 #endif
563 }
564 
565 static sljit_uw get_imm(sljit_uw imm);
566 static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_uw imm);
567 
inline_set_const(sljit_uw addr,sljit_sw executable_offset,sljit_uw new_constant,sljit_s32 flush_cache)568 static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_sw executable_offset, sljit_uw new_constant, sljit_s32 flush_cache)
569 {
570 #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
571 	sljit_uw *ptr = (sljit_uw*)addr;
572 	sljit_uw *inst = (sljit_uw*)ptr[0];
573 	sljit_uw ldr_literal = ptr[1];
574 	sljit_uw src2;
575 
576 	SLJIT_UNUSED_ARG(executable_offset);
577 
578 	src2 = get_imm(new_constant);
579 	if (src2) {
580 		if (flush_cache) {
581 			SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);
582 		}
583 
584 		*inst = 0xe3a00000 | (ldr_literal & 0xf000) | src2;
585 
586 		if (flush_cache) {
587 			SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);
588 			inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
589 			SLJIT_CACHE_FLUSH(inst, inst + 1);
590 		}
591 		return;
592 	}
593 
594 	src2 = get_imm(~new_constant);
595 	if (src2) {
596 		if (flush_cache) {
597 			SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);
598 		}
599 
600 		*inst = 0xe3e00000 | (ldr_literal & 0xf000) | src2;
601 
602 		if (flush_cache) {
603 			SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);
604 			inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
605 			SLJIT_CACHE_FLUSH(inst, inst + 1);
606 		}
607 		return;
608 	}
609 
610 	if (ldr_literal & (1 << 23))
611 		ptr = inst + ((ldr_literal & 0xfff) >> 2) + 2;
612 	else
613 		ptr = inst + 1;
614 
615 	if (*inst != ldr_literal) {
616 		if (flush_cache) {
617 			SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);
618 		}
619 
620 		*inst = ldr_literal;
621 
622 		if (flush_cache) {
623 			SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);
624 			inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
625 			SLJIT_CACHE_FLUSH(inst, inst + 1);
626 		}
627 	}
628 
629 	if (flush_cache) {
630 		SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 0);
631 	}
632 
633 	*ptr = new_constant;
634 
635 	if (flush_cache) {
636 		SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 1);
637 	}
638 #else
639 	sljit_uw *inst = (sljit_uw*)addr;
640 
641 	SLJIT_UNUSED_ARG(executable_offset);
642 
643 	SLJIT_ASSERT((inst[0] & 0xfff00000) == MOVW && (inst[1] & 0xfff00000) == MOVT);
644 
645 	if (flush_cache) {
646 		SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);
647 	}
648 
649 	inst[0] = MOVW | (inst[0] & 0xf000) | ((new_constant << 4) & 0xf0000) | (new_constant & 0xfff);
650 	inst[1] = MOVT | (inst[1] & 0xf000) | ((new_constant >> 12) & 0xf0000) | ((new_constant >> 16) & 0xfff);
651 
652 	if (flush_cache) {
653 		SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
654 		inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
655 		SLJIT_CACHE_FLUSH(inst, inst + 2);
656 	}
657 #endif
658 }
659 
sljit_generate_code(struct sljit_compiler * compiler)660 SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)
661 {
662 	struct sljit_memory_fragment *buf;
663 	sljit_uw *code;
664 	sljit_uw *code_ptr;
665 	sljit_uw *buf_ptr;
666 	sljit_uw *buf_end;
667 	sljit_uw size;
668 	sljit_uw word_count;
669 	sljit_uw next_addr;
670 	sljit_sw executable_offset;
671 	sljit_uw addr;
672 #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
673 	sljit_uw cpool_size;
674 	sljit_uw cpool_skip_alignment;
675 	sljit_uw cpool_current_index;
676 	sljit_uw *cpool_start_address;
677 	sljit_uw *last_pc_patch;
678 	struct future_patch *first_patch;
679 #endif
680 
681 	struct sljit_label *label;
682 	struct sljit_jump *jump;
683 	struct sljit_const *const_;
684 	struct sljit_put_label *put_label;
685 
686 	CHECK_ERROR_PTR();
687 	CHECK_PTR(check_sljit_generate_code(compiler));
688 	reverse_buf(compiler);
689 
690 	/* Second code generation pass. */
691 #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
692 	size = compiler->size + (compiler->patches << 1);
693 	if (compiler->cpool_fill > 0)
694 		size += compiler->cpool_fill + CONST_POOL_ALIGNMENT - 1;
695 #else
696 	size = compiler->size;
697 #endif
698 	code = (sljit_uw*)SLJIT_MALLOC_EXEC(size * sizeof(sljit_uw), compiler->exec_allocator_data);
699 	PTR_FAIL_WITH_EXEC_IF(code);
700 	buf = compiler->buf;
701 
702 #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
703 	cpool_size = 0;
704 	cpool_skip_alignment = 0;
705 	cpool_current_index = 0;
706 	cpool_start_address = NULL;
707 	first_patch = NULL;
708 	last_pc_patch = code;
709 #endif
710 
711 	code_ptr = code;
712 	word_count = 0;
713 	next_addr = 1;
714 	executable_offset = SLJIT_EXEC_OFFSET(code);
715 
716 	label = compiler->labels;
717 	jump = compiler->jumps;
718 	const_ = compiler->consts;
719 	put_label = compiler->put_labels;
720 
721 	if (label && label->size == 0) {
722 		label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
723 		label = label->next;
724 	}
725 
726 	do {
727 		buf_ptr = (sljit_uw*)buf->memory;
728 		buf_end = buf_ptr + (buf->used_size >> 2);
729 		do {
730 			word_count++;
731 #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
732 			if (cpool_size > 0) {
733 				if (cpool_skip_alignment > 0) {
734 					buf_ptr++;
735 					cpool_skip_alignment--;
736 				}
737 				else {
738 					if (SLJIT_UNLIKELY(resolve_const_pool_index(compiler, &first_patch, cpool_current_index, cpool_start_address, buf_ptr))) {
739 						SLJIT_FREE_EXEC(code, compiler->exec_allocator_data);
740 						compiler->error = SLJIT_ERR_ALLOC_FAILED;
741 						return NULL;
742 					}
743 					buf_ptr++;
744 					if (++cpool_current_index >= cpool_size) {
745 						SLJIT_ASSERT(!first_patch);
746 						cpool_size = 0;
747 						if (label && label->size == word_count) {
748 							/* Points after the current instruction. */
749 							label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
750 							label->size = (sljit_uw)(code_ptr - code);
751 							label = label->next;
752 
753 							next_addr = compute_next_addr(label, jump, const_, put_label);
754 						}
755 					}
756 				}
757 			}
758 			else if ((*buf_ptr & 0xff000000) != PUSH_POOL) {
759 #endif
760 				*code_ptr = *buf_ptr++;
761 				if (next_addr == word_count) {
762 					SLJIT_ASSERT(!label || label->size >= word_count);
763 					SLJIT_ASSERT(!jump || jump->addr >= word_count);
764 					SLJIT_ASSERT(!const_ || const_->addr >= word_count);
765 					SLJIT_ASSERT(!put_label || put_label->addr >= word_count);
766 
767 				/* These structures are ordered by their address. */
768 					if (jump && jump->addr == word_count) {
769 #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
770 						if (detect_jump_type(jump, code_ptr, code, executable_offset))
771 							code_ptr--;
772 						jump->addr = (sljit_uw)code_ptr;
773 #else
774 						jump->addr = (sljit_uw)(code_ptr - 2);
775 						if (detect_jump_type(jump, code_ptr, code, executable_offset))
776 							code_ptr -= 2;
777 #endif
778 						jump = jump->next;
779 					}
780 					if (label && label->size == word_count) {
781 						/* code_ptr can be affected above. */
782 						label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr + 1, executable_offset);
783 						label->size = (sljit_uw)((code_ptr + 1) - code);
784 						label = label->next;
785 					}
786 					if (const_ && const_->addr == word_count) {
787 #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
788 						const_->addr = (sljit_uw)code_ptr;
789 #else
790 						const_->addr = (sljit_uw)(code_ptr - 1);
791 #endif
792 						const_ = const_->next;
793 					}
794 					if (put_label && put_label->addr == word_count) {
795 						SLJIT_ASSERT(put_label->label);
796 						put_label->addr = (sljit_uw)code_ptr;
797 						put_label = put_label->next;
798 					}
799 					next_addr = compute_next_addr(label, jump, const_, put_label);
800 				}
801 				code_ptr++;
802 #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
803 			}
804 			else {
805 				/* Fortunately, no need to shift. */
806 				cpool_size = *buf_ptr++ & ~PUSH_POOL;
807 				SLJIT_ASSERT(cpool_size > 0);
808 				cpool_start_address = ALIGN_INSTRUCTION(code_ptr + 1);
809 				cpool_current_index = patch_pc_relative_loads(last_pc_patch, code_ptr, cpool_start_address, cpool_size);
810 				if (cpool_current_index > 0) {
811 					/* Unconditional branch. */
812 					*code_ptr = B | (((sljit_uw)(cpool_start_address - code_ptr) + cpool_current_index - 2) & ~PUSH_POOL);
813 					code_ptr = (sljit_uw*)(cpool_start_address + cpool_current_index);
814 				}
815 				cpool_skip_alignment = CONST_POOL_ALIGNMENT - 1;
816 				cpool_current_index = 0;
817 				last_pc_patch = code_ptr;
818 			}
819 #endif
820 		} while (buf_ptr < buf_end);
821 		buf = buf->next;
822 	} while (buf);
823 
824 	SLJIT_ASSERT(!label);
825 	SLJIT_ASSERT(!jump);
826 	SLJIT_ASSERT(!const_);
827 	SLJIT_ASSERT(!put_label);
828 
829 #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
830 	SLJIT_ASSERT(cpool_size == 0);
831 	if (compiler->cpool_fill > 0) {
832 		cpool_start_address = ALIGN_INSTRUCTION(code_ptr);
833 		cpool_current_index = patch_pc_relative_loads(last_pc_patch, code_ptr, cpool_start_address, compiler->cpool_fill);
834 		if (cpool_current_index > 0)
835 			code_ptr = (sljit_uw*)(cpool_start_address + cpool_current_index);
836 
837 		buf_ptr = compiler->cpool;
838 		buf_end = buf_ptr + compiler->cpool_fill;
839 		cpool_current_index = 0;
840 		while (buf_ptr < buf_end) {
841 			if (SLJIT_UNLIKELY(resolve_const_pool_index(compiler, &first_patch, cpool_current_index, cpool_start_address, buf_ptr))) {
842 				SLJIT_FREE_EXEC(code, compiler->exec_allocator_data);
843 				compiler->error = SLJIT_ERR_ALLOC_FAILED;
844 				return NULL;
845 			}
846 			buf_ptr++;
847 			cpool_current_index++;
848 		}
849 		SLJIT_ASSERT(!first_patch);
850 	}
851 #endif
852 
853 	jump = compiler->jumps;
854 	while (jump) {
855 		buf_ptr = (sljit_uw *)jump->addr;
856 
857 		if (jump->flags & PATCH_B) {
858 			addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr + 2, executable_offset);
859 			if (!(jump->flags & JUMP_ADDR)) {
860 				SLJIT_ASSERT(jump->flags & JUMP_LABEL);
861 				SLJIT_ASSERT((sljit_sw)(jump->u.label->addr - addr) <= 0x01ffffff && (sljit_sw)(jump->u.label->addr - addr) >= -0x02000000);
862 				*buf_ptr |= ((jump->u.label->addr - addr) >> 2) & 0x00ffffff;
863 			}
864 			else {
865 				SLJIT_ASSERT((sljit_sw)(jump->u.target - addr) <= 0x01ffffff && (sljit_sw)(jump->u.target - addr) >= -0x02000000);
866 				*buf_ptr |= ((jump->u.target - addr) >> 2) & 0x00ffffff;
867 			}
868 		}
869 		else if (jump->flags & SLJIT_REWRITABLE_JUMP) {
870 #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
871 			jump->addr = (sljit_uw)code_ptr;
872 			code_ptr[0] = (sljit_uw)buf_ptr;
873 			code_ptr[1] = *buf_ptr;
874 			inline_set_jump_addr((sljit_uw)code_ptr, executable_offset, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0);
875 			code_ptr += 2;
876 #else
877 			inline_set_jump_addr((sljit_uw)buf_ptr, executable_offset, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0);
878 #endif
879 		}
880 		else {
881 #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
882 			if (jump->flags & IS_BL)
883 				buf_ptr--;
884 			if (*buf_ptr & (1 << 23))
885 				buf_ptr += ((*buf_ptr & 0xfff) >> 2) + 2;
886 			else
887 				buf_ptr += 1;
888 			*buf_ptr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;
889 #else
890 			inline_set_jump_addr((sljit_uw)buf_ptr, executable_offset, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0);
891 #endif
892 		}
893 		jump = jump->next;
894 	}
895 
896 #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
897 	const_ = compiler->consts;
898 	while (const_) {
899 		buf_ptr = (sljit_uw*)const_->addr;
900 		const_->addr = (sljit_uw)code_ptr;
901 
902 		code_ptr[0] = (sljit_uw)buf_ptr;
903 		code_ptr[1] = *buf_ptr;
904 		if (*buf_ptr & (1 << 23))
905 			buf_ptr += ((*buf_ptr & 0xfff) >> 2) + 2;
906 		else
907 			buf_ptr += 1;
908 		/* Set the value again (can be a simple constant). */
909 		inline_set_const((sljit_uw)code_ptr, executable_offset, *buf_ptr, 0);
910 		code_ptr += 2;
911 
912 		const_ = const_->next;
913 	}
914 #endif
915 
916 	put_label = compiler->put_labels;
917 	while (put_label) {
918 		addr = put_label->label->addr;
919 		buf_ptr = (sljit_uw*)put_label->addr;
920 
921 #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
922 		SLJIT_ASSERT((buf_ptr[0] & 0xffff0000) == 0xe59f0000);
923 		buf_ptr[((buf_ptr[0] & 0xfff) >> 2) + 2] = addr;
924 #else
925 		SLJIT_ASSERT((buf_ptr[-1] & 0xfff00000) == MOVW && (buf_ptr[0] & 0xfff00000) == MOVT);
926 		buf_ptr[-1] |= ((addr << 4) & 0xf0000) | (addr & 0xfff);
927 		buf_ptr[0] |= ((addr >> 12) & 0xf0000) | ((addr >> 16) & 0xfff);
928 #endif
929 		put_label = put_label->next;
930 	}
931 
932 	SLJIT_ASSERT(code_ptr - code <= (sljit_s32)size);
933 
934 	compiler->error = SLJIT_ERR_COMPILED;
935 	compiler->executable_offset = executable_offset;
936 	compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_uw);
937 
938 	code = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
939 	code_ptr = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
940 
941 	SLJIT_CACHE_FLUSH(code, code_ptr);
942 	SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);
943 	return code;
944 }
945 
sljit_has_cpu_feature(sljit_s32 feature_type)946 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
947 {
948 	switch (feature_type) {
949 	case SLJIT_HAS_FPU:
950 #ifdef SLJIT_IS_FPU_AVAILABLE
951 		return SLJIT_IS_FPU_AVAILABLE;
952 #else
953 		/* Available by default. */
954 		return 1;
955 #endif
956 
957 	case SLJIT_HAS_CLZ:
958 	case SLJIT_HAS_CMOV:
959 #if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
960 	case SLJIT_HAS_PREFETCH:
961 #endif
962 		return 1;
963 
964 	default:
965 		return 0;
966 	}
967 }
968 
969 /* --------------------------------------------------------------------- */
970 /*  Entry, exit                                                          */
971 /* --------------------------------------------------------------------- */
972 
973 /* Creates an index in data_transfer_insts array. */
974 #define WORD_SIZE	0x00
975 #define BYTE_SIZE	0x01
976 #define HALF_SIZE	0x02
977 #define PRELOAD		0x03
978 #define SIGNED		0x04
979 #define LOAD_DATA	0x08
980 
981 /* Flag bits for emit_op. */
982 #define ALLOW_IMM	0x10
983 #define ALLOW_INV_IMM	0x20
984 #define ALLOW_ANY_IMM	(ALLOW_IMM | ALLOW_INV_IMM)
985 #define ALLOW_NEG_IMM	0x40
986 
987 /* s/l - store/load (1 bit)
988    u/s - signed/unsigned (1 bit)
989    w/b/h/N - word/byte/half/NOT allowed (2 bit)
990    Storing signed and unsigned values are the same operations. */
991 
992 static const sljit_uw data_transfer_insts[16] = {
993 /* s u w */ 0xe5000000 /* str */,
994 /* s u b */ 0xe5400000 /* strb */,
995 /* s u h */ 0xe10000b0 /* strh */,
996 /* s u N */ 0x00000000 /* not allowed */,
997 /* s s w */ 0xe5000000 /* str */,
998 /* s s b */ 0xe5400000 /* strb */,
999 /* s s h */ 0xe10000b0 /* strh */,
1000 /* s s N */ 0x00000000 /* not allowed */,
1001 
1002 /* l u w */ 0xe5100000 /* ldr */,
1003 /* l u b */ 0xe5500000 /* ldrb */,
1004 /* l u h */ 0xe11000b0 /* ldrh */,
1005 /* l u p */ 0xf5500000 /* preload */,
1006 /* l s w */ 0xe5100000 /* ldr */,
1007 /* l s b */ 0xe11000d0 /* ldrsb */,
1008 /* l s h */ 0xe11000f0 /* ldrsh */,
1009 /* l s N */ 0x00000000 /* not allowed */,
1010 };
1011 
1012 #define EMIT_DATA_TRANSFER(type, add, target_reg, base_reg, arg) \
1013 	(data_transfer_insts[(type) & 0xf] | ((add) << 23) | RD(target_reg) | RN(base_reg) | (sljit_uw)(arg))
1014 
1015 /* Normal ldr/str instruction.
1016    Type2: ldrsb, ldrh, ldrsh */
1017 #define IS_TYPE1_TRANSFER(type) \
1018 	(data_transfer_insts[(type) & 0xf] & 0x04000000)
1019 #define TYPE2_TRANSFER_IMM(imm) \
1020 	(((imm) & 0xf) | (((imm) & 0xf0) << 4) | (1 << 22))
1021 
1022 #define EMIT_FPU_OPERATION(opcode, mode, dst, src1, src2) \
1023 	((sljit_uw)(opcode) | (sljit_uw)(mode) | VD(dst) | VM(src1) | VN(src2))
1024 
1025 /* Flags for emit_op: */
1026   /* Arguments are swapped. */
1027 #define ARGS_SWAPPED	0x01
1028   /* Inverted immediate. */
1029 #define INV_IMM		0x02
1030   /* Source and destination is register. */
1031 #define MOVE_REG_CONV	0x04
1032   /* Unused return value. */
1033 #define UNUSED_RETURN	0x08
1034 /* SET_FLAGS must be (1 << 20) as it is also the value of S bit (can be used for optimization). */
1035 #define SET_FLAGS	(1 << 20)
1036 /* dst: reg
1037    src1: reg
1038    src2: reg or imm (if allowed)
1039    SRC2_IMM must be (1 << 25) as it is also the value of I bit (can be used for optimization). */
1040 #define SRC2_IMM	(1 << 25)
1041 
1042 static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 inp_flags,
1043 	sljit_s32 dst, sljit_sw dstw,
1044 	sljit_s32 src1, sljit_sw src1w,
1045 	sljit_s32 src2, sljit_sw src2w);
1046 
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)1047 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
1048 	sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
1049 	sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
1050 {
1051 	sljit_uw imm, offset;
1052 	sljit_s32 i, tmp, size, word_arg_count, saved_arg_count;
1053 #ifdef __SOFTFP__
1054 	sljit_u32 float_arg_count;
1055 #else
1056 	sljit_u32 old_offset, f32_offset;
1057 	sljit_u32 remap[3];
1058 	sljit_u32 *remap_ptr = remap;
1059 #endif
1060 
1061 	CHECK_ERROR();
1062 	CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
1063 	set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
1064 
1065 	imm = 0;
1066 
1067 	tmp = SLJIT_S0 - saveds;
1068 	for (i = SLJIT_S0; i > tmp; i--)
1069 		imm |= (sljit_uw)1 << reg_map[i];
1070 
1071 	for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--)
1072 		imm |= (sljit_uw)1 << reg_map[i];
1073 
1074 	SLJIT_ASSERT(reg_map[TMP_REG2] == 14);
1075 
1076 	/* Push saved and temporary registers
1077 	   multiple registers: stmdb sp!, {..., lr}
1078 	   single register: str reg, [sp, #-4]! */
1079 	if (imm != 0)
1080 		FAIL_IF(push_inst(compiler, PUSH | (1 << 14) | imm));
1081 	else
1082 		FAIL_IF(push_inst(compiler, 0xe52d0004 | RD(TMP_REG2)));
1083 
1084 	/* Stack must be aligned to 8 bytes: */
1085 	size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
1086 
1087 	if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
1088 		if ((size & SSIZE_OF(sw)) != 0) {
1089 			FAIL_IF(push_inst(compiler, SUB | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | sizeof(sljit_sw)));
1090 			size += SSIZE_OF(sw);
1091 		}
1092 
1093 		if (fsaveds + fscratches >= SLJIT_NUMBER_OF_FLOAT_REGISTERS) {
1094 			FAIL_IF(push_inst(compiler, VPUSH | VD(SLJIT_FS0) | ((sljit_uw)SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS << 1)));
1095 		} else {
1096 			if (fsaveds > 0)
1097 				FAIL_IF(push_inst(compiler, VPUSH | VD(SLJIT_FS0) | ((sljit_uw)fsaveds << 1)));
1098 			if (fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG)
1099 				FAIL_IF(push_inst(compiler, VPUSH | VD(fscratches) | ((sljit_uw)(fscratches - (SLJIT_FIRST_SAVED_FLOAT_REG - 1)) << 1)));
1100 		}
1101 	}
1102 
1103 	local_size = ((size + local_size + 0x7) & ~0x7) - size;
1104 	compiler->local_size = local_size;
1105 
1106 	arg_types >>= SLJIT_ARG_SHIFT;
1107 	word_arg_count = 0;
1108 	saved_arg_count = 0;
1109 #ifdef __SOFTFP__
1110 	SLJIT_COMPILE_ASSERT(SLJIT_FR0 == 1, float_register_index_start);
1111 
1112 	offset = 0;
1113 	float_arg_count = 0;
1114 
1115 	while (arg_types) {
1116 		switch (arg_types & SLJIT_ARG_MASK) {
1117 		case SLJIT_ARG_TYPE_F64:
1118 			if (offset & 0x7)
1119 				offset += sizeof(sljit_sw);
1120 
1121 			if (offset < 4 * sizeof(sljit_sw))
1122 				FAIL_IF(push_inst(compiler, VMOV2 | (offset << 10) | ((offset + sizeof(sljit_sw)) << 14) | float_arg_count));
1123 			else
1124 				FAIL_IF(push_inst(compiler, VLDR_F32 | 0x800100 | RN(SLJIT_SP)
1125 						| (float_arg_count << 12) | ((offset + (sljit_uw)size - 4 * sizeof(sljit_sw)) >> 2)));
1126 			float_arg_count++;
1127 			offset += sizeof(sljit_f64) - sizeof(sljit_sw);
1128 			break;
1129 		case SLJIT_ARG_TYPE_F32:
1130 			if (offset < 4 * sizeof(sljit_sw))
1131 				FAIL_IF(push_inst(compiler, VMOV | (float_arg_count << 16) | (offset << 10)));
1132 			else
1133 				FAIL_IF(push_inst(compiler, VLDR_F32 | 0x800000 | RN(SLJIT_SP)
1134 						| (float_arg_count << 12) | ((offset + (sljit_uw)size - 4 * sizeof(sljit_sw)) >> 2)));
1135 			float_arg_count++;
1136 			break;
1137 		default:
1138 			word_arg_count++;
1139 
1140 			if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
1141 				tmp = SLJIT_S0 - saved_arg_count;
1142 				saved_arg_count++;
1143 			} else if (word_arg_count - 1 != (sljit_s32)(offset >> 2))
1144 				tmp = word_arg_count;
1145 			else
1146 				break;
1147 
1148 			if (offset < 4 * sizeof(sljit_sw))
1149 				FAIL_IF(push_inst(compiler, MOV | RD(tmp) | (offset >> 2)));
1150 			else
1151 				FAIL_IF(push_inst(compiler, data_transfer_insts[WORD_SIZE | LOAD_DATA] | 0x800000
1152 						| RN(SLJIT_SP) | RD(tmp) | (offset + (sljit_uw)size - 4 * sizeof(sljit_sw))));
1153 			break;
1154 		}
1155 
1156 		offset += sizeof(sljit_sw);
1157 		arg_types >>= SLJIT_ARG_SHIFT;
1158 	}
1159 
1160 	compiler->args_size = offset;
1161 #else
1162 	offset = SLJIT_FR0;
1163 	old_offset = SLJIT_FR0;
1164 	f32_offset = 0;
1165 
1166 	while (arg_types) {
1167 		switch (arg_types & SLJIT_ARG_MASK) {
1168 		case SLJIT_ARG_TYPE_F64:
1169 			if (offset != old_offset)
1170 				*remap_ptr++ = EMIT_FPU_OPERATION(VMOV_F32, SLJIT_32, offset, old_offset, 0);
1171 			old_offset++;
1172 			offset++;
1173 			break;
1174 		case SLJIT_ARG_TYPE_F32:
1175 			if (f32_offset != 0) {
1176 				*remap_ptr++ = EMIT_FPU_OPERATION(VMOV_F32, 0x20, offset, f32_offset, 0);
1177 				f32_offset = 0;
1178 			} else {
1179 				if (offset != old_offset)
1180 					*remap_ptr++ = EMIT_FPU_OPERATION(VMOV_F32, 0, offset, old_offset, 0);
1181 				f32_offset = old_offset;
1182 				old_offset++;
1183 			}
1184 			offset++;
1185 			break;
1186 		default:
1187 			if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
1188 				FAIL_IF(push_inst(compiler, MOV | RD(SLJIT_S0 - saved_arg_count) | RM(SLJIT_R0 + word_arg_count)));
1189 				saved_arg_count++;
1190 			}
1191 
1192 			word_arg_count++;
1193 			break;
1194 		}
1195 		arg_types >>= SLJIT_ARG_SHIFT;
1196 	}
1197 
1198 	SLJIT_ASSERT((sljit_uw)(remap_ptr - remap) <= sizeof(remap));
1199 
1200 	while (remap_ptr > remap)
1201 		FAIL_IF(push_inst(compiler, *(--remap_ptr)));
1202 #endif
1203 
1204 	if (local_size > 0)
1205 		FAIL_IF(emit_op(compiler, SLJIT_SUB, ALLOW_IMM, SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, local_size));
1206 
1207 	return SLJIT_SUCCESS;
1208 }
1209 
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)1210 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
1211 	sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
1212 	sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
1213 {
1214 	sljit_s32 size;
1215 
1216 	CHECK_ERROR();
1217 	CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
1218 	set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
1219 
1220 	size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
1221 
1222 	if ((size & SSIZE_OF(sw)) != 0 && (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG))
1223 		size += SSIZE_OF(sw);
1224 
1225 	compiler->local_size = ((size + local_size + 0x7) & ~0x7) - size;
1226 	return SLJIT_SUCCESS;
1227 }
1228 
emit_add_sp(struct sljit_compiler * compiler,sljit_uw imm)1229 static sljit_s32 emit_add_sp(struct sljit_compiler *compiler, sljit_uw imm)
1230 {
1231 	sljit_uw imm2 = get_imm(imm);
1232 
1233 	if (imm2 == 0) {
1234 		FAIL_IF(load_immediate(compiler, TMP_REG2, imm));
1235 		imm2 = RM(TMP_REG2);
1236 	}
1237 
1238 	return push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | imm2);
1239 }
1240 
emit_stack_frame_release(struct sljit_compiler * compiler,sljit_s32 frame_size)1241 static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size)
1242 {
1243 	sljit_s32 local_size, fscratches, fsaveds, i, tmp;
1244 	sljit_s32 lr_dst = TMP_PC;
1245 	sljit_uw reg_list;
1246 
1247 	SLJIT_ASSERT(reg_map[TMP_REG2] == 14);
1248 
1249 	local_size = compiler->local_size;
1250 	fscratches = compiler->fscratches;
1251 	fsaveds = compiler->fsaveds;
1252 
1253 	if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
1254 		if (local_size > 0)
1255 			FAIL_IF(emit_add_sp(compiler, (sljit_uw)local_size));
1256 
1257 		if (fsaveds + fscratches >= SLJIT_NUMBER_OF_FLOAT_REGISTERS) {
1258 			FAIL_IF(push_inst(compiler, VPOP | VD(SLJIT_FS0) | ((sljit_uw)SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS << 1)));
1259 		} else {
1260 			if (fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG)
1261 				FAIL_IF(push_inst(compiler, VPOP | VD(fscratches) | ((sljit_uw)(fscratches - (SLJIT_FIRST_SAVED_FLOAT_REG - 1)) << 1)));
1262 			if (fsaveds > 0)
1263 				FAIL_IF(push_inst(compiler, VPOP | VD(SLJIT_FS0) | ((sljit_uw)fsaveds << 1)));
1264 		}
1265 
1266 		local_size = GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1) & 0x7;
1267 	}
1268 
1269 	if (frame_size < 0) {
1270 		lr_dst = TMP_REG2;
1271 		frame_size = 0;
1272 	} else if (frame_size > 0)
1273 		lr_dst = 0;
1274 
1275 	reg_list = 0;
1276 	if (lr_dst != 0)
1277 		reg_list |= (sljit_uw)1 << reg_map[lr_dst];
1278 
1279 	tmp = SLJIT_S0 - compiler->saveds;
1280 	for (i = SLJIT_S0; i > tmp; i--)
1281 		reg_list |= (sljit_uw)1 << reg_map[i];
1282 
1283 	for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--)
1284 		reg_list |= (sljit_uw)1 << reg_map[i];
1285 
1286 	if (lr_dst == 0 && (reg_list & (reg_list - 1)) == 0) {
1287 		/* The local_size does not include the saved registers. */
1288 		local_size += SSIZE_OF(sw);
1289 
1290 		if (reg_list != 0)
1291 			local_size += SSIZE_OF(sw);
1292 
1293 		if (frame_size > local_size)
1294 			FAIL_IF(push_inst(compiler, SUB | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 25) | (sljit_uw)(frame_size - local_size)));
1295 		else if (frame_size < local_size)
1296 			FAIL_IF(emit_add_sp(compiler, (sljit_uw)(local_size - frame_size)));
1297 
1298 		if (reg_list == 0)
1299 			return SLJIT_SUCCESS;
1300 
1301 		if (compiler->saveds > 0) {
1302 			SLJIT_ASSERT(reg_list == ((sljit_uw)1 << reg_map[SLJIT_S0]));
1303 			lr_dst = SLJIT_S0;
1304 		} else {
1305 			SLJIT_ASSERT(reg_list == ((sljit_uw)1 << reg_map[SLJIT_FIRST_SAVED_REG]));
1306 			lr_dst = SLJIT_FIRST_SAVED_REG;
1307 		}
1308 
1309 		return push_inst(compiler, data_transfer_insts[WORD_SIZE | LOAD_DATA] | 0x800000
1310 			| RN(SLJIT_SP) | RD(lr_dst) | (sljit_uw)(frame_size - 2 * SSIZE_OF(sw)));
1311 	}
1312 
1313 	if (local_size > 0)
1314 		FAIL_IF(emit_add_sp(compiler, (sljit_uw)local_size));
1315 
1316 	/* Pop saved and temporary registers
1317 	   multiple registers: ldmia sp!, {...}
1318 	   single register: ldr reg, [sp], #4 */
1319 	if ((reg_list & (reg_list - 1)) == 0) {
1320 		SLJIT_ASSERT(lr_dst != 0);
1321 		SLJIT_ASSERT(reg_list == (sljit_uw)1 << reg_map[lr_dst]);
1322 
1323 		return push_inst(compiler, 0xe49d0004 | RD(lr_dst));
1324 	}
1325 
1326 	FAIL_IF(push_inst(compiler, POP | reg_list));
1327 	if (frame_size > 0)
1328 		return push_inst(compiler, SUB | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 25) | ((sljit_uw)frame_size - sizeof(sljit_sw)));
1329 	return SLJIT_SUCCESS;
1330 }
1331 
sljit_emit_return_void(struct sljit_compiler * compiler)1332 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
1333 {
1334 	CHECK_ERROR();
1335 	CHECK(check_sljit_emit_return_void(compiler));
1336 
1337 	return emit_stack_frame_release(compiler, 0);
1338 }
1339 
1340 /* --------------------------------------------------------------------- */
1341 /*  Operators                                                            */
1342 /* --------------------------------------------------------------------- */
1343 
1344 #define EMIT_SHIFT_INS_AND_RETURN(opcode) \
1345 	SLJIT_ASSERT(!(flags & INV_IMM) && !(src2 & SRC2_IMM)); \
1346 	if (compiler->shift_imm != 0x20) { \
1347 		SLJIT_ASSERT(src1 == TMP_REG1); \
1348 		SLJIT_ASSERT(!(flags & ARGS_SWAPPED)); \
1349 		\
1350 		if (compiler->shift_imm != 0) \
1351 			return push_inst(compiler, MOV | (flags & SET_FLAGS) | \
1352 				RD(dst) | (compiler->shift_imm << 7) | (opcode << 5) | RM(src2)); \
1353 		return push_inst(compiler, MOV | (flags & SET_FLAGS) | RD(dst) | RM(src2)); \
1354 	} \
1355 	return push_inst(compiler, MOV | (flags & SET_FLAGS) | RD(dst) \
1356 		| RM8((flags & ARGS_SWAPPED) ? src1 : src2) | (sljit_uw)(opcode << 5) \
1357 		| 0x10 | RM((flags & ARGS_SWAPPED) ? src2 : src1));
1358 
emit_single_op(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 flags,sljit_uw dst,sljit_uw src1,sljit_uw src2)1359 static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
1360 	sljit_uw dst, sljit_uw src1, sljit_uw src2)
1361 {
1362 	switch (GET_OPCODE(op)) {
1363 	case SLJIT_MOV:
1364 		SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));
1365 		if (dst != src2) {
1366 			if (src2 & SRC2_IMM) {
1367 				return push_inst(compiler, ((flags & INV_IMM) ? MVN : MOV) | RD(dst) | src2);
1368 			}
1369 			return push_inst(compiler, MOV | RD(dst) | RM(src2));
1370 		}
1371 		return SLJIT_SUCCESS;
1372 
1373 	case SLJIT_MOV_U8:
1374 	case SLJIT_MOV_S8:
1375 		SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));
1376 		if (flags & MOVE_REG_CONV) {
1377 #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
1378 			if (op == SLJIT_MOV_U8)
1379 				return push_inst(compiler, AND | RD(dst) | RN(src2) | SRC2_IMM | 0xff);
1380 			FAIL_IF(push_inst(compiler, MOV | RD(dst) | (24 << 7) | RM(src2)));
1381 			return push_inst(compiler, MOV | RD(dst) | (24 << 7) | (op == SLJIT_MOV_U8 ? 0x20 : 0x40) | RM(dst));
1382 #else
1383 			return push_inst(compiler, (op == SLJIT_MOV_U8 ? UXTB : SXTB) | RD(dst) | RM(src2));
1384 #endif
1385 		}
1386 		else if (dst != src2) {
1387 			SLJIT_ASSERT(src2 & SRC2_IMM);
1388 			return push_inst(compiler, ((flags & INV_IMM) ? MVN : MOV) | RD(dst) | src2);
1389 		}
1390 		return SLJIT_SUCCESS;
1391 
1392 	case SLJIT_MOV_U16:
1393 	case SLJIT_MOV_S16:
1394 		SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));
1395 		if (flags & MOVE_REG_CONV) {
1396 #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
1397 			FAIL_IF(push_inst(compiler, MOV | RD(dst) | (16 << 7) | RM(src2)));
1398 			return push_inst(compiler, MOV | RD(dst) | (16 << 7) | (op == SLJIT_MOV_U16 ? 0x20 : 0x40) | RM(dst));
1399 #else
1400 			return push_inst(compiler, (op == SLJIT_MOV_U16 ? UXTH : SXTH) | RD(dst) | RM(src2));
1401 #endif
1402 		}
1403 		else if (dst != src2) {
1404 			SLJIT_ASSERT(src2 & SRC2_IMM);
1405 			return push_inst(compiler, ((flags & INV_IMM) ? MVN : MOV) | RD(dst) | src2);
1406 		}
1407 		return SLJIT_SUCCESS;
1408 
1409 	case SLJIT_NOT:
1410 		if (src2 & SRC2_IMM)
1411 			return push_inst(compiler, ((flags & INV_IMM) ? MOV : MVN) | (flags & SET_FLAGS) | RD(dst) | src2);
1412 
1413 		return push_inst(compiler, MVN | (flags & SET_FLAGS) | RD(dst) | RM(src2));
1414 
1415 	case SLJIT_CLZ:
1416 		SLJIT_ASSERT(!(flags & INV_IMM));
1417 		SLJIT_ASSERT(!(src2 & SRC2_IMM));
1418 		FAIL_IF(push_inst(compiler, CLZ | RD(dst) | RM(src2)));
1419 		return SLJIT_SUCCESS;
1420 
1421 	case SLJIT_ADD:
1422 		SLJIT_ASSERT(!(flags & INV_IMM));
1423 
1424 		if ((flags & (UNUSED_RETURN | ARGS_SWAPPED)) == UNUSED_RETURN)
1425 			return push_inst(compiler, CMN | SET_FLAGS | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
1426 		return push_inst(compiler, ADD | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
1427 
1428 	case SLJIT_ADDC:
1429 		SLJIT_ASSERT(!(flags & INV_IMM));
1430 		return push_inst(compiler, ADC | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
1431 
1432 	case SLJIT_SUB:
1433 		SLJIT_ASSERT(!(flags & INV_IMM));
1434 
1435 		if ((flags & (UNUSED_RETURN | ARGS_SWAPPED)) == UNUSED_RETURN)
1436 			return push_inst(compiler, CMP | SET_FLAGS | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
1437 
1438 		return push_inst(compiler, (!(flags & ARGS_SWAPPED) ? SUB : RSB) | (flags & SET_FLAGS)
1439 			| RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
1440 
1441 	case SLJIT_SUBC:
1442 		SLJIT_ASSERT(!(flags & INV_IMM));
1443 		return push_inst(compiler, (!(flags & ARGS_SWAPPED) ? SBC : RSC) | (flags & SET_FLAGS)
1444 			| RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
1445 
1446 	case SLJIT_MUL:
1447 		SLJIT_ASSERT(!(flags & INV_IMM));
1448 		SLJIT_ASSERT(!(src2 & SRC2_IMM));
1449 		compiler->status_flags_state = 0;
1450 
1451 		if (!HAS_FLAGS(op))
1452 			return push_inst(compiler, MUL | RN(dst) | RM8(src2) | RM(src1));
1453 
1454 		FAIL_IF(push_inst(compiler, SMULL | RN(TMP_REG1) | RD(dst) | RM8(src2) | RM(src1)));
1455 
1456 		/* cmp TMP_REG1, dst asr #31. */
1457 		return push_inst(compiler, CMP | SET_FLAGS | RN(TMP_REG1) | RM(dst) | 0xfc0);
1458 
1459 	case SLJIT_AND:
1460 		if ((flags & (UNUSED_RETURN | INV_IMM)) == UNUSED_RETURN)
1461 			return push_inst(compiler, TST | SET_FLAGS | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
1462 		return push_inst(compiler, (!(flags & INV_IMM) ? AND : BIC) | (flags & SET_FLAGS)
1463 			| RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
1464 
1465 	case SLJIT_OR:
1466 		SLJIT_ASSERT(!(flags & INV_IMM));
1467 		return push_inst(compiler, ORR | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
1468 
1469 	case SLJIT_XOR:
1470 		SLJIT_ASSERT(!(flags & INV_IMM));
1471 		return push_inst(compiler, EOR | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
1472 
1473 	case SLJIT_SHL:
1474 		EMIT_SHIFT_INS_AND_RETURN(0);
1475 
1476 	case SLJIT_LSHR:
1477 		EMIT_SHIFT_INS_AND_RETURN(1);
1478 
1479 	case SLJIT_ASHR:
1480 		EMIT_SHIFT_INS_AND_RETURN(2);
1481 	}
1482 
1483 	SLJIT_UNREACHABLE();
1484 	return SLJIT_SUCCESS;
1485 }
1486 
1487 #undef EMIT_SHIFT_INS_AND_RETURN
1488 
1489 /* Tests whether the immediate can be stored in the 12 bit imm field.
1490    Returns with 0 if not possible. */
get_imm(sljit_uw imm)1491 static sljit_uw get_imm(sljit_uw imm)
1492 {
1493 	sljit_u32 rol;
1494 
1495 	if (imm <= 0xff)
1496 		return SRC2_IMM | imm;
1497 
1498 	if (!(imm & 0xff000000)) {
1499 		imm <<= 8;
1500 		rol = 8;
1501 	}
1502 	else {
1503 		imm = (imm << 24) | (imm >> 8);
1504 		rol = 0;
1505 	}
1506 
1507 	if (!(imm & 0xff000000)) {
1508 		imm <<= 8;
1509 		rol += 4;
1510 	}
1511 
1512 	if (!(imm & 0xf0000000)) {
1513 		imm <<= 4;
1514 		rol += 2;
1515 	}
1516 
1517 	if (!(imm & 0xc0000000)) {
1518 		imm <<= 2;
1519 		rol += 1;
1520 	}
1521 
1522 	if (!(imm & 0x00ffffff))
1523 		return SRC2_IMM | (imm >> 24) | (rol << 8);
1524 	else
1525 		return 0;
1526 }
1527 
1528 #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
generate_int(struct sljit_compiler * compiler,sljit_s32 reg,sljit_uw imm,sljit_s32 positive)1529 static sljit_s32 generate_int(struct sljit_compiler *compiler, sljit_s32 reg, sljit_uw imm, sljit_s32 positive)
1530 {
1531 	sljit_uw mask;
1532 	sljit_uw imm1;
1533 	sljit_uw imm2;
1534 	sljit_uw rol;
1535 
1536 	/* Step1: Search a zero byte (8 continous zero bit). */
1537 	mask = 0xff000000;
1538 	rol = 8;
1539 	while(1) {
1540 		if (!(imm & mask)) {
1541 			/* Rol imm by rol. */
1542 			imm = (imm << rol) | (imm >> (32 - rol));
1543 			/* Calculate arm rol. */
1544 			rol = 4 + (rol >> 1);
1545 			break;
1546 		}
1547 		rol += 2;
1548 		mask >>= 2;
1549 		if (mask & 0x3) {
1550 			/* rol by 8. */
1551 			imm = (imm << 8) | (imm >> 24);
1552 			mask = 0xff00;
1553 			rol = 24;
1554 			while (1) {
1555 				if (!(imm & mask)) {
1556 					/* Rol imm by rol. */
1557 					imm = (imm << rol) | (imm >> (32 - rol));
1558 					/* Calculate arm rol. */
1559 					rol = (rol >> 1) - 8;
1560 					break;
1561 				}
1562 				rol += 2;
1563 				mask >>= 2;
1564 				if (mask & 0x3)
1565 					return 0;
1566 			}
1567 			break;
1568 		}
1569 	}
1570 
1571 	/* The low 8 bit must be zero. */
1572 	SLJIT_ASSERT(!(imm & 0xff));
1573 
1574 	if (!(imm & 0xff000000)) {
1575 		imm1 = SRC2_IMM | ((imm >> 16) & 0xff) | (((rol + 4) & 0xf) << 8);
1576 		imm2 = SRC2_IMM | ((imm >> 8) & 0xff) | (((rol + 8) & 0xf) << 8);
1577 	}
1578 	else if (imm & 0xc0000000) {
1579 		imm1 = SRC2_IMM | ((imm >> 24) & 0xff) | ((rol & 0xf) << 8);
1580 		imm <<= 8;
1581 		rol += 4;
1582 
1583 		if (!(imm & 0xff000000)) {
1584 			imm <<= 8;
1585 			rol += 4;
1586 		}
1587 
1588 		if (!(imm & 0xf0000000)) {
1589 			imm <<= 4;
1590 			rol += 2;
1591 		}
1592 
1593 		if (!(imm & 0xc0000000)) {
1594 			imm <<= 2;
1595 			rol += 1;
1596 		}
1597 
1598 		if (!(imm & 0x00ffffff))
1599 			imm2 = SRC2_IMM | (imm >> 24) | ((rol & 0xf) << 8);
1600 		else
1601 			return 0;
1602 	}
1603 	else {
1604 		if (!(imm & 0xf0000000)) {
1605 			imm <<= 4;
1606 			rol += 2;
1607 		}
1608 
1609 		if (!(imm & 0xc0000000)) {
1610 			imm <<= 2;
1611 			rol += 1;
1612 		}
1613 
1614 		imm1 = SRC2_IMM | ((imm >> 24) & 0xff) | ((rol & 0xf) << 8);
1615 		imm <<= 8;
1616 		rol += 4;
1617 
1618 		if (!(imm & 0xf0000000)) {
1619 			imm <<= 4;
1620 			rol += 2;
1621 		}
1622 
1623 		if (!(imm & 0xc0000000)) {
1624 			imm <<= 2;
1625 			rol += 1;
1626 		}
1627 
1628 		if (!(imm & 0x00ffffff))
1629 			imm2 = SRC2_IMM | (imm >> 24) | ((rol & 0xf) << 8);
1630 		else
1631 			return 0;
1632 	}
1633 
1634 	FAIL_IF(push_inst(compiler, (positive ? MOV : MVN) | RD(reg) | imm1));
1635 	FAIL_IF(push_inst(compiler, (positive ? ORR : BIC) | RD(reg) | RN(reg) | imm2));
1636 	return 1;
1637 }
1638 #endif
1639 
load_immediate(struct sljit_compiler * compiler,sljit_s32 reg,sljit_uw imm)1640 static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_uw imm)
1641 {
1642 	sljit_uw tmp;
1643 
1644 #if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
1645 	if (!(imm & ~(sljit_uw)0xffff))
1646 		return push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | (imm & 0xfff));
1647 #endif
1648 
1649 	/* Create imm by 1 inst. */
1650 	tmp = get_imm(imm);
1651 	if (tmp)
1652 		return push_inst(compiler, MOV | RD(reg) | tmp);
1653 
1654 	tmp = get_imm(~imm);
1655 	if (tmp)
1656 		return push_inst(compiler, MVN | RD(reg) | tmp);
1657 
1658 #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
1659 	/* Create imm by 2 inst. */
1660 	FAIL_IF(generate_int(compiler, reg, imm, 1));
1661 	FAIL_IF(generate_int(compiler, reg, ~imm, 0));
1662 
1663 	/* Load integer. */
1664 	return push_inst_with_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, reg, TMP_PC, 0), imm);
1665 #else
1666 	FAIL_IF(push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | (imm & 0xfff)));
1667 	if (imm <= 0xffff)
1668 		return SLJIT_SUCCESS;
1669 	return push_inst(compiler, MOVT | RD(reg) | ((imm >> 12) & 0xf0000) | ((imm >> 16) & 0xfff));
1670 #endif
1671 }
1672 
emit_op_mem(struct sljit_compiler * compiler,sljit_s32 flags,sljit_s32 reg,sljit_s32 arg,sljit_sw argw,sljit_s32 tmp_reg)1673 static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg,
1674 	sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg)
1675 {
1676 	sljit_uw imm, offset_reg;
1677 	sljit_uw is_type1_transfer = IS_TYPE1_TRANSFER(flags);
1678 
1679 	SLJIT_ASSERT (arg & SLJIT_MEM);
1680 	SLJIT_ASSERT((arg & REG_MASK) != tmp_reg);
1681 
1682 	if (!(arg & REG_MASK)) {
1683 		if (is_type1_transfer) {
1684 			FAIL_IF(load_immediate(compiler, tmp_reg, (sljit_uw)argw & ~(sljit_uw)0xfff));
1685 			argw &= 0xfff;
1686 		}
1687 		else {
1688 			FAIL_IF(load_immediate(compiler, tmp_reg, (sljit_uw)argw & ~(sljit_uw)0xff));
1689 			argw &= 0xff;
1690 		}
1691 
1692 		return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, tmp_reg,
1693 			is_type1_transfer ? argw : TYPE2_TRANSFER_IMM(argw)));
1694 	}
1695 
1696 	if (arg & OFFS_REG_MASK) {
1697 		offset_reg = OFFS_REG(arg);
1698 		arg &= REG_MASK;
1699 		argw &= 0x3;
1700 
1701 		if (argw != 0 && !is_type1_transfer) {
1702 			FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | RM(offset_reg) | ((sljit_uw)argw << 7)));
1703 			return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, tmp_reg, TYPE2_TRANSFER_IMM(0)));
1704 		}
1705 
1706 		/* Bit 25: RM is offset. */
1707 		return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg,
1708 			RM(offset_reg) | (is_type1_transfer ? (1 << 25) : 0) | ((sljit_uw)argw << 7)));
1709 	}
1710 
1711 	arg &= REG_MASK;
1712 
1713 	if (is_type1_transfer) {
1714 		if (argw > 0xfff) {
1715 			imm = get_imm((sljit_uw)argw & ~(sljit_uw)0xfff);
1716 			if (imm) {
1717 				FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | imm));
1718 				argw = argw & 0xfff;
1719 				arg = tmp_reg;
1720 			}
1721 		}
1722 		else if (argw < -0xfff) {
1723 			imm = get_imm((sljit_uw)-argw & ~(sljit_uw)0xfff);
1724 			if (imm) {
1725 				FAIL_IF(push_inst(compiler, SUB | RD(tmp_reg) | RN(arg) | imm));
1726 				argw = -(-argw & 0xfff);
1727 				arg = tmp_reg;
1728 			}
1729 		}
1730 
1731 		if (argw >= 0 && argw <= 0xfff)
1732 			return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg, argw));
1733 
1734 		if (argw < 0 && argw >= -0xfff)
1735 			return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 0, reg, arg, -argw));
1736 	}
1737 	else {
1738 		if (argw > 0xff) {
1739 			imm = get_imm((sljit_uw)argw & ~(sljit_uw)0xff);
1740 			if (imm) {
1741 				FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | imm));
1742 				argw = argw & 0xff;
1743 				arg = tmp_reg;
1744 			}
1745 		}
1746 		else if (argw < -0xff) {
1747 			imm = get_imm((sljit_uw)-argw & ~(sljit_uw)0xff);
1748 			if (imm) {
1749 				FAIL_IF(push_inst(compiler, SUB | RD(tmp_reg) | RN(arg) | imm));
1750 				argw = -(-argw & 0xff);
1751 				arg = tmp_reg;
1752 			}
1753 		}
1754 
1755 		if (argw >= 0 && argw <= 0xff)
1756 			return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg, TYPE2_TRANSFER_IMM(argw)));
1757 
1758 		if (argw < 0 && argw >= -0xff) {
1759 			argw = -argw;
1760 			return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 0, reg, arg, TYPE2_TRANSFER_IMM(argw)));
1761 		}
1762 	}
1763 
1764 	FAIL_IF(load_immediate(compiler, tmp_reg, (sljit_uw)argw));
1765 	return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg,
1766 		RM(tmp_reg) | (is_type1_transfer ? (1 << 25) : 0)));
1767 }
1768 
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)1769 static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 inp_flags,
1770 	sljit_s32 dst, sljit_sw dstw,
1771 	sljit_s32 src1, sljit_sw src1w,
1772 	sljit_s32 src2, sljit_sw src2w)
1773 {
1774 	/* src1 is reg or TMP_REG1
1775 	   src2 is reg, TMP_REG2, or imm
1776 	   result goes to TMP_REG2, so put result can use TMP_REG1. */
1777 
1778 	/* We prefers register and simple consts. */
1779 	sljit_s32 dst_reg;
1780 	sljit_s32 src1_reg;
1781 	sljit_s32 src2_reg = 0;
1782 	sljit_s32 flags = HAS_FLAGS(op) ? SET_FLAGS : 0;
1783 	sljit_s32 neg_op = 0;
1784 
1785 	if (dst == TMP_REG2)
1786 		flags |= UNUSED_RETURN;
1787 
1788 	SLJIT_ASSERT(!(inp_flags & ALLOW_INV_IMM) || (inp_flags & ALLOW_IMM));
1789 
1790 	if (inp_flags & ALLOW_NEG_IMM) {
1791 		switch (GET_OPCODE(op)) {
1792 		case SLJIT_ADD:
1793 			compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
1794 			neg_op = SLJIT_SUB;
1795 			break;
1796 		case SLJIT_ADDC:
1797 			compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
1798 			neg_op = SLJIT_SUBC;
1799 			break;
1800 		case SLJIT_SUB:
1801 			compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
1802 			neg_op = SLJIT_ADD;
1803 			break;
1804 		case SLJIT_SUBC:
1805 			compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
1806 			neg_op = SLJIT_ADDC;
1807 			break;
1808 		}
1809 	}
1810 
1811 	do {
1812 		if (!(inp_flags & ALLOW_IMM))
1813 			break;
1814 
1815 		if (src2 & SLJIT_IMM) {
1816 			src2_reg = (sljit_s32)get_imm((sljit_uw)src2w);
1817 			if (src2_reg)
1818 				break;
1819 			if (inp_flags & ALLOW_INV_IMM) {
1820 				src2_reg = (sljit_s32)get_imm(~(sljit_uw)src2w);
1821 				if (src2_reg) {
1822 					flags |= INV_IMM;
1823 					break;
1824 				}
1825 			}
1826 			if (neg_op != 0) {
1827 				src2_reg = (sljit_s32)get_imm((sljit_uw)-src2w);
1828 				if (src2_reg) {
1829 					op = neg_op | GET_ALL_FLAGS(op);
1830 					break;
1831 				}
1832 			}
1833 		}
1834 
1835 		if (src1 & SLJIT_IMM) {
1836 			src2_reg = (sljit_s32)get_imm((sljit_uw)src1w);
1837 			if (src2_reg) {
1838 				flags |= ARGS_SWAPPED;
1839 				src1 = src2;
1840 				src1w = src2w;
1841 				break;
1842 			}
1843 			if (inp_flags & ALLOW_INV_IMM) {
1844 				src2_reg = (sljit_s32)get_imm(~(sljit_uw)src1w);
1845 				if (src2_reg) {
1846 					flags |= ARGS_SWAPPED | INV_IMM;
1847 					src1 = src2;
1848 					src1w = src2w;
1849 					break;
1850 				}
1851 			}
1852 			if (neg_op >= SLJIT_SUB) {
1853 				/* Note: additive operation (commutative). */
1854 				src2_reg = (sljit_s32)get_imm((sljit_uw)-src1w);
1855 				if (src2_reg) {
1856 					src1 = src2;
1857 					src1w = src2w;
1858 					op = neg_op | GET_ALL_FLAGS(op);
1859 					break;
1860 				}
1861 			}
1862 		}
1863 	} while(0);
1864 
1865 	/* Source 1. */
1866 	if (FAST_IS_REG(src1))
1867 		src1_reg = src1;
1868 	else if (src1 & SLJIT_MEM) {
1869 		FAIL_IF(emit_op_mem(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, TMP_REG1));
1870 		src1_reg = TMP_REG1;
1871 	}
1872 	else {
1873 		FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)src1w));
1874 		src1_reg = TMP_REG1;
1875 	}
1876 
1877 	/* Destination. */
1878 	dst_reg = FAST_IS_REG(dst) ? dst : TMP_REG2;
1879 
1880 	if (op <= SLJIT_MOV_P) {
1881 		if (dst & SLJIT_MEM) {
1882 			if (inp_flags & BYTE_SIZE)
1883 				inp_flags &= ~SIGNED;
1884 
1885 			if (FAST_IS_REG(src2))
1886 				return emit_op_mem(compiler, inp_flags, src2, dst, dstw, TMP_REG2);
1887 		}
1888 
1889 		if (FAST_IS_REG(src2) && dst_reg != TMP_REG2)
1890 			flags |= MOVE_REG_CONV;
1891 	}
1892 
1893 	/* Source 2. */
1894 	if (src2_reg == 0) {
1895 		src2_reg = (op <= SLJIT_MOV_P) ? dst_reg : TMP_REG2;
1896 
1897 		if (FAST_IS_REG(src2))
1898 			src2_reg = src2;
1899 		else if (src2 & SLJIT_MEM)
1900 			FAIL_IF(emit_op_mem(compiler, inp_flags | LOAD_DATA, src2_reg, src2, src2w, TMP_REG2));
1901 		else
1902 			FAIL_IF(load_immediate(compiler, src2_reg, (sljit_uw)src2w));
1903 	}
1904 
1905 	FAIL_IF(emit_single_op(compiler, op, flags, (sljit_uw)dst_reg, (sljit_uw)src1_reg, (sljit_uw)src2_reg));
1906 
1907 	if (!(dst & SLJIT_MEM))
1908 		return SLJIT_SUCCESS;
1909 
1910 	return emit_op_mem(compiler, inp_flags, dst_reg, dst, dstw, TMP_REG1);
1911 }
1912 
1913 #ifdef __cplusplus
1914 extern "C" {
1915 #endif
1916 
1917 #if defined(__GNUC__)
1918 extern unsigned int __aeabi_uidivmod(unsigned int numerator, unsigned int denominator);
1919 extern int __aeabi_idivmod(int numerator, int denominator);
1920 #else
1921 #error "Software divmod functions are needed"
1922 #endif
1923 
1924 #ifdef __cplusplus
1925 }
1926 #endif
1927 
sljit_emit_op0(struct sljit_compiler * compiler,sljit_s32 op)1928 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
1929 {
1930 	sljit_uw saved_reg_list[3];
1931 	sljit_sw saved_reg_count;
1932 
1933 	CHECK_ERROR();
1934 	CHECK(check_sljit_emit_op0(compiler, op));
1935 
1936 	op = GET_OPCODE(op);
1937 	switch (op) {
1938 	case SLJIT_BREAKPOINT:
1939 		FAIL_IF(push_inst(compiler, BKPT));
1940 		break;
1941 	case SLJIT_NOP:
1942 		FAIL_IF(push_inst(compiler, NOP));
1943 		break;
1944 	case SLJIT_LMUL_UW:
1945 	case SLJIT_LMUL_SW:
1946 		return push_inst(compiler, (op == SLJIT_LMUL_UW ? UMULL : SMULL)
1947 			| RN(SLJIT_R1) | RD(SLJIT_R0) | RM8(SLJIT_R0) | RM(SLJIT_R1));
1948 	case SLJIT_DIVMOD_UW:
1949 	case SLJIT_DIVMOD_SW:
1950 	case SLJIT_DIV_UW:
1951 	case SLJIT_DIV_SW:
1952 		SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments);
1953 		SLJIT_ASSERT(reg_map[2] == 1 && reg_map[3] == 2 && reg_map[4] == 3);
1954 
1955 		saved_reg_count = 0;
1956 		if (compiler->scratches >= 4)
1957 			saved_reg_list[saved_reg_count++] = 3;
1958 		if (compiler->scratches >= 3)
1959 			saved_reg_list[saved_reg_count++] = 2;
1960 		if (op >= SLJIT_DIV_UW)
1961 			saved_reg_list[saved_reg_count++] = 1;
1962 
1963 		if (saved_reg_count > 0) {
1964 			FAIL_IF(push_inst(compiler, 0xe52d0000 | (saved_reg_count >= 3 ? 16 : 8)
1965 						| (saved_reg_list[0] << 12) /* str rX, [sp, #-8/-16]! */));
1966 			if (saved_reg_count >= 2) {
1967 				SLJIT_ASSERT(saved_reg_list[1] < 8);
1968 				FAIL_IF(push_inst(compiler, 0xe58d0004 | (saved_reg_list[1] << 12) /* str rX, [sp, #4] */));
1969 			}
1970 			if (saved_reg_count >= 3) {
1971 				SLJIT_ASSERT(saved_reg_list[2] < 8);
1972 				FAIL_IF(push_inst(compiler, 0xe58d0008 | (saved_reg_list[2] << 12) /* str rX, [sp, #8] */));
1973 			}
1974 		}
1975 
1976 #if defined(__GNUC__)
1977 		FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM,
1978 			((op | 0x2) == SLJIT_DIV_UW ? SLJIT_FUNC_ADDR(__aeabi_uidivmod) : SLJIT_FUNC_ADDR(__aeabi_idivmod))));
1979 #else
1980 #error "Software divmod functions are needed"
1981 #endif
1982 
1983 		if (saved_reg_count > 0) {
1984 			if (saved_reg_count >= 3) {
1985 				SLJIT_ASSERT(saved_reg_list[2] < 8);
1986 				FAIL_IF(push_inst(compiler, 0xe59d0008 | (saved_reg_list[2] << 12) /* ldr rX, [sp, #8] */));
1987 			}
1988 			if (saved_reg_count >= 2) {
1989 				SLJIT_ASSERT(saved_reg_list[1] < 8);
1990 				FAIL_IF(push_inst(compiler, 0xe59d0004 | (saved_reg_list[1] << 12) /* ldr rX, [sp, #4] */));
1991 			}
1992 			return push_inst(compiler, 0xe49d0000 | (sljit_uw)(saved_reg_count >= 3 ? 16 : 8)
1993 						| (saved_reg_list[0] << 12) /* ldr rX, [sp], #8/16 */);
1994 		}
1995 		return SLJIT_SUCCESS;
1996 	case SLJIT_ENDBR:
1997 	case SLJIT_SKIP_FRAMES_BEFORE_RETURN:
1998 		return SLJIT_SUCCESS;
1999 	}
2000 
2001 	return SLJIT_SUCCESS;
2002 }
2003 
sljit_emit_op1(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 src,sljit_sw srcw)2004 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
2005 	sljit_s32 dst, sljit_sw dstw,
2006 	sljit_s32 src, sljit_sw srcw)
2007 {
2008 	CHECK_ERROR();
2009 	CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
2010 	ADJUST_LOCAL_OFFSET(dst, dstw);
2011 	ADJUST_LOCAL_OFFSET(src, srcw);
2012 
2013 	switch (GET_OPCODE(op)) {
2014 	case SLJIT_MOV:
2015 	case SLJIT_MOV_U32:
2016 	case SLJIT_MOV_S32:
2017 	case SLJIT_MOV32:
2018 	case SLJIT_MOV_P:
2019 		return emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, src, srcw);
2020 
2021 	case SLJIT_MOV_U8:
2022 		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);
2023 
2024 	case SLJIT_MOV_S8:
2025 		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);
2026 
2027 	case SLJIT_MOV_U16:
2028 		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);
2029 
2030 	case SLJIT_MOV_S16:
2031 		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);
2032 
2033 	case SLJIT_NOT:
2034 		return emit_op(compiler, op, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, src, srcw);
2035 
2036 	case SLJIT_CLZ:
2037 		return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src, srcw);
2038 	}
2039 
2040 	return SLJIT_SUCCESS;
2041 }
2042 
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)2043 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
2044 	sljit_s32 dst, sljit_sw dstw,
2045 	sljit_s32 src1, sljit_sw src1w,
2046 	sljit_s32 src2, sljit_sw src2w)
2047 {
2048 	CHECK_ERROR();
2049 	CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));
2050 	ADJUST_LOCAL_OFFSET(dst, dstw);
2051 	ADJUST_LOCAL_OFFSET(src1, src1w);
2052 	ADJUST_LOCAL_OFFSET(src2, src2w);
2053 
2054 	switch (GET_OPCODE(op)) {
2055 	case SLJIT_ADD:
2056 	case SLJIT_ADDC:
2057 	case SLJIT_SUB:
2058 	case SLJIT_SUBC:
2059 		return emit_op(compiler, op, ALLOW_IMM | ALLOW_NEG_IMM, dst, dstw, src1, src1w, src2, src2w);
2060 
2061 	case SLJIT_OR:
2062 	case SLJIT_XOR:
2063 		return emit_op(compiler, op, ALLOW_IMM, dst, dstw, src1, src1w, src2, src2w);
2064 
2065 	case SLJIT_MUL:
2066 		return emit_op(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w);
2067 
2068 	case SLJIT_AND:
2069 		return emit_op(compiler, op, ALLOW_ANY_IMM, dst, dstw, src1, src1w, src2, src2w);
2070 
2071 	case SLJIT_SHL:
2072 	case SLJIT_LSHR:
2073 	case SLJIT_ASHR:
2074 		if (src2 & SLJIT_IMM) {
2075 			compiler->shift_imm = src2w & 0x1f;
2076 			return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src1, src1w);
2077 		}
2078 		else {
2079 			compiler->shift_imm = 0x20;
2080 			return emit_op(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w);
2081 		}
2082 	}
2083 
2084 	return SLJIT_SUCCESS;
2085 }
2086 
sljit_emit_op2u(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2,sljit_sw src2w)2087 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,
2088 	sljit_s32 src1, sljit_sw src1w,
2089 	sljit_s32 src2, sljit_sw src2w)
2090 {
2091 	CHECK_ERROR();
2092 	CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
2093 
2094 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
2095 		|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
2096 	compiler->skip_checks = 1;
2097 #endif
2098 	return sljit_emit_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w);
2099 }
2100 
sljit_emit_op_src(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 src,sljit_sw srcw)2101 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
2102 	sljit_s32 src, sljit_sw srcw)
2103 {
2104 	CHECK_ERROR();
2105 	CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));
2106 	ADJUST_LOCAL_OFFSET(src, srcw);
2107 
2108 	switch (op) {
2109 	case SLJIT_FAST_RETURN:
2110 		SLJIT_ASSERT(reg_map[TMP_REG2] == 14);
2111 
2112 		if (FAST_IS_REG(src))
2113 			FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG2) | RM(src)));
2114 		else
2115 			FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, src, srcw, TMP_REG1));
2116 
2117 		return push_inst(compiler, BX | RM(TMP_REG2));
2118 	case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:
2119 		return SLJIT_SUCCESS;
2120 	case SLJIT_PREFETCH_L1:
2121 	case SLJIT_PREFETCH_L2:
2122 	case SLJIT_PREFETCH_L3:
2123 	case SLJIT_PREFETCH_ONCE:
2124 #if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
2125 		SLJIT_ASSERT(src & SLJIT_MEM);
2126 		return emit_op_mem(compiler, PRELOAD | LOAD_DATA, TMP_PC, src, srcw, TMP_REG1);
2127 #else /* !SLJIT_CONFIG_ARM_V7 */
2128 		return SLJIT_SUCCESS;
2129 #endif /* SLJIT_CONFIG_ARM_V7 */
2130 	}
2131 
2132 	return SLJIT_SUCCESS;
2133 }
2134 
sljit_get_register_index(sljit_s32 reg)2135 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
2136 {
2137 	CHECK_REG_INDEX(check_sljit_get_register_index(reg));
2138 	return reg_map[reg];
2139 }
2140 
sljit_get_float_register_index(sljit_s32 reg)2141 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)
2142 {
2143 	CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));
2144 	return (freg_map[reg] << 1);
2145 }
2146 
sljit_emit_op_custom(struct sljit_compiler * compiler,void * instruction,sljit_u32 size)2147 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
2148 	void *instruction, sljit_u32 size)
2149 {
2150 	SLJIT_UNUSED_ARG(size);
2151 	CHECK_ERROR();
2152 	CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
2153 
2154 	return push_inst(compiler, *(sljit_uw*)instruction);
2155 }
2156 
2157 /* --------------------------------------------------------------------- */
2158 /*  Floating point operators                                             */
2159 /* --------------------------------------------------------------------- */
2160 
2161 #define FPU_LOAD (1 << 20)
2162 #define EMIT_FPU_DATA_TRANSFER(inst, add, base, freg, offs) \
2163 	((inst) | (sljit_uw)((add) << 23) | RN(base) | VD(freg) | (sljit_uw)(offs))
2164 
emit_fop_mem(struct sljit_compiler * compiler,sljit_s32 flags,sljit_s32 reg,sljit_s32 arg,sljit_sw argw)2165 static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
2166 {
2167 	sljit_uw imm;
2168 	sljit_uw inst = VSTR_F32 | (flags & (SLJIT_32 | FPU_LOAD));
2169 
2170 	SLJIT_ASSERT(arg & SLJIT_MEM);
2171 	arg &= ~SLJIT_MEM;
2172 
2173 	if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
2174 		FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG2) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | (((sljit_uw)argw & 0x3) << 7)));
2175 		arg = TMP_REG2;
2176 		argw = 0;
2177 	}
2178 
2179 	/* Fast loads and stores. */
2180 	if (arg) {
2181 		if (!(argw & ~0x3fc))
2182 			return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, arg & REG_MASK, reg, argw >> 2));
2183 		if (!(-argw & ~0x3fc))
2184 			return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, arg & REG_MASK, reg, (-argw) >> 2));
2185 
2186 		imm = get_imm((sljit_uw)argw & ~(sljit_uw)0x3fc);
2187 		if (imm) {
2188 			FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG2) | RN(arg & REG_MASK) | imm));
2189 			return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG2, reg, (argw & 0x3fc) >> 2));
2190 		}
2191 		imm = get_imm((sljit_uw)-argw & ~(sljit_uw)0x3fc);
2192 		if (imm) {
2193 			argw = -argw;
2194 			FAIL_IF(push_inst(compiler, SUB | RD(TMP_REG2) | RN(arg & REG_MASK) | imm));
2195 			return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, TMP_REG2, reg, (argw & 0x3fc) >> 2));
2196 		}
2197 	}
2198 
2199 	if (arg) {
2200 		FAIL_IF(load_immediate(compiler, TMP_REG2, (sljit_uw)argw));
2201 		FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG2) | RN(arg & REG_MASK) | RM(TMP_REG2)));
2202 	}
2203 	else
2204 		FAIL_IF(load_immediate(compiler, TMP_REG2, (sljit_uw)argw));
2205 
2206 	return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG2, reg, 0));
2207 }
2208 
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)2209 static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
2210 	sljit_s32 dst, sljit_sw dstw,
2211 	sljit_s32 src, sljit_sw srcw)
2212 {
2213 	op ^= SLJIT_32;
2214 
2215 	if (src & SLJIT_MEM) {
2216 		FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG1, src, srcw));
2217 		src = TMP_FREG1;
2218 	}
2219 
2220 	FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_S32_F32, op & SLJIT_32, TMP_FREG1, src, 0)));
2221 
2222 	if (FAST_IS_REG(dst))
2223 		return push_inst(compiler, VMOV | (1 << 20) | RD(dst) | VN(TMP_FREG1));
2224 
2225 	/* Store the integer value from a VFP register. */
2226 	return emit_fop_mem(compiler, 0, TMP_FREG1, dst, dstw);
2227 }
2228 
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)2229 static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
2230 	sljit_s32 dst, sljit_sw dstw,
2231 	sljit_s32 src, sljit_sw srcw)
2232 {
2233 	sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
2234 
2235 	op ^= SLJIT_32;
2236 
2237 	if (FAST_IS_REG(src))
2238 		FAIL_IF(push_inst(compiler, VMOV | RD(src) | VN(TMP_FREG1)));
2239 	else if (src & SLJIT_MEM) {
2240 		/* Load the integer value into a VFP register. */
2241 		FAIL_IF(emit_fop_mem(compiler, FPU_LOAD, TMP_FREG1, src, srcw));
2242 	}
2243 	else {
2244 		FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)srcw));
2245 		FAIL_IF(push_inst(compiler, VMOV | RD(TMP_REG1) | VN(TMP_FREG1)));
2246 	}
2247 
2248 	FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_F32_S32, op & SLJIT_32, dst_r, TMP_FREG1, 0)));
2249 
2250 	if (dst & SLJIT_MEM)
2251 		return emit_fop_mem(compiler, (op & SLJIT_32), TMP_FREG1, dst, dstw);
2252 	return SLJIT_SUCCESS;
2253 }
2254 
sljit_emit_fop1_cmp(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2,sljit_sw src2w)2255 static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
2256 	sljit_s32 src1, sljit_sw src1w,
2257 	sljit_s32 src2, sljit_sw src2w)
2258 {
2259 	op ^= SLJIT_32;
2260 
2261 	if (src1 & SLJIT_MEM) {
2262 		FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG1, src1, src1w));
2263 		src1 = TMP_FREG1;
2264 	}
2265 
2266 	if (src2 & SLJIT_MEM) {
2267 		FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG2, src2, src2w));
2268 		src2 = TMP_FREG2;
2269 	}
2270 
2271 	FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCMP_F32, op & SLJIT_32, src1, src2, 0)));
2272 	return push_inst(compiler, VMRS);
2273 }
2274 
sljit_emit_fop1(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 src,sljit_sw srcw)2275 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
2276 	sljit_s32 dst, sljit_sw dstw,
2277 	sljit_s32 src, sljit_sw srcw)
2278 {
2279 	sljit_s32 dst_r;
2280 
2281 	CHECK_ERROR();
2282 
2283 	SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100), float_transfer_bit_error);
2284 	SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
2285 
2286 	dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
2287 
2288 	if (GET_OPCODE(op) != SLJIT_CONV_F64_FROM_F32)
2289 		op ^= SLJIT_32;
2290 
2291 	if (src & SLJIT_MEM) {
2292 		FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, dst_r, src, srcw));
2293 		src = dst_r;
2294 	}
2295 
2296 	switch (GET_OPCODE(op)) {
2297 	case SLJIT_MOV_F64:
2298 		if (src != dst_r) {
2299 			if (dst_r != TMP_FREG1)
2300 				FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32, op & SLJIT_32, dst_r, src, 0)));
2301 			else
2302 				dst_r = src;
2303 		}
2304 		break;
2305 	case SLJIT_NEG_F64:
2306 		FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VNEG_F32, op & SLJIT_32, dst_r, src, 0)));
2307 		break;
2308 	case SLJIT_ABS_F64:
2309 		FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VABS_F32, op & SLJIT_32, dst_r, src, 0)));
2310 		break;
2311 	case SLJIT_CONV_F64_FROM_F32:
2312 		FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_F64_F32, op & SLJIT_32, dst_r, src, 0)));
2313 		op ^= SLJIT_32;
2314 		break;
2315 	}
2316 
2317 	if (dst & SLJIT_MEM)
2318 		return emit_fop_mem(compiler, (op & SLJIT_32), dst_r, dst, dstw);
2319 	return SLJIT_SUCCESS;
2320 }
2321 
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)2322 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
2323 	sljit_s32 dst, sljit_sw dstw,
2324 	sljit_s32 src1, sljit_sw src1w,
2325 	sljit_s32 src2, sljit_sw src2w)
2326 {
2327 	sljit_s32 dst_r;
2328 
2329 	CHECK_ERROR();
2330 	CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
2331 	ADJUST_LOCAL_OFFSET(dst, dstw);
2332 	ADJUST_LOCAL_OFFSET(src1, src1w);
2333 	ADJUST_LOCAL_OFFSET(src2, src2w);
2334 
2335 	op ^= SLJIT_32;
2336 
2337 	dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
2338 
2339 	if (src2 & SLJIT_MEM) {
2340 		FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG2, src2, src2w));
2341 		src2 = TMP_FREG2;
2342 	}
2343 
2344 	if (src1 & SLJIT_MEM) {
2345 		FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG1, src1, src1w));
2346 		src1 = TMP_FREG1;
2347 	}
2348 
2349 	switch (GET_OPCODE(op)) {
2350 	case SLJIT_ADD_F64:
2351 		FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VADD_F32, op & SLJIT_32, dst_r, src2, src1)));
2352 		break;
2353 
2354 	case SLJIT_SUB_F64:
2355 		FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VSUB_F32, op & SLJIT_32, dst_r, src2, src1)));
2356 		break;
2357 
2358 	case SLJIT_MUL_F64:
2359 		FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMUL_F32, op & SLJIT_32, dst_r, src2, src1)));
2360 		break;
2361 
2362 	case SLJIT_DIV_F64:
2363 		FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VDIV_F32, op & SLJIT_32, dst_r, src2, src1)));
2364 		break;
2365 	}
2366 
2367 	if (dst_r == TMP_FREG1)
2368 		FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32), TMP_FREG1, dst, dstw));
2369 
2370 	return SLJIT_SUCCESS;
2371 }
2372 
2373 #undef FPU_LOAD
2374 #undef EMIT_FPU_DATA_TRANSFER
2375 
2376 /* --------------------------------------------------------------------- */
2377 /*  Other instructions                                                   */
2378 /* --------------------------------------------------------------------- */
2379 
sljit_emit_fast_enter(struct sljit_compiler * compiler,sljit_s32 dst,sljit_sw dstw)2380 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
2381 {
2382 	CHECK_ERROR();
2383 	CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
2384 	ADJUST_LOCAL_OFFSET(dst, dstw);
2385 
2386 	SLJIT_ASSERT(reg_map[TMP_REG2] == 14);
2387 
2388 	if (FAST_IS_REG(dst))
2389 		return push_inst(compiler, MOV | RD(dst) | RM(TMP_REG2));
2390 
2391 	/* Memory. */
2392 	return emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1);
2393 }
2394 
2395 /* --------------------------------------------------------------------- */
2396 /*  Conditional instructions                                             */
2397 /* --------------------------------------------------------------------- */
2398 
get_cc(struct sljit_compiler * compiler,sljit_s32 type)2399 static sljit_uw get_cc(struct sljit_compiler *compiler, sljit_s32 type)
2400 {
2401 	switch (type) {
2402 	case SLJIT_EQUAL:
2403 	case SLJIT_EQUAL_F64:
2404 		return 0x00000000;
2405 
2406 	case SLJIT_NOT_EQUAL:
2407 	case SLJIT_NOT_EQUAL_F64:
2408 		return 0x10000000;
2409 
2410 	case SLJIT_CARRY:
2411 		if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)
2412 			return 0x20000000;
2413 		/* fallthrough */
2414 
2415 	case SLJIT_LESS:
2416 	case SLJIT_LESS_F64:
2417 		return 0x30000000;
2418 
2419 	case SLJIT_NOT_CARRY:
2420 		if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)
2421 			return 0x30000000;
2422 		/* fallthrough */
2423 
2424 	case SLJIT_GREATER_EQUAL:
2425 	case SLJIT_GREATER_EQUAL_F64:
2426 		return 0x20000000;
2427 
2428 	case SLJIT_GREATER:
2429 	case SLJIT_GREATER_F64:
2430 		return 0x80000000;
2431 
2432 	case SLJIT_LESS_EQUAL:
2433 	case SLJIT_LESS_EQUAL_F64:
2434 		return 0x90000000;
2435 
2436 	case SLJIT_SIG_LESS:
2437 		return 0xb0000000;
2438 
2439 	case SLJIT_SIG_GREATER_EQUAL:
2440 		return 0xa0000000;
2441 
2442 	case SLJIT_SIG_GREATER:
2443 		return 0xc0000000;
2444 
2445 	case SLJIT_SIG_LESS_EQUAL:
2446 		return 0xd0000000;
2447 
2448 	case SLJIT_OVERFLOW:
2449 		if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))
2450 			return 0x10000000;
2451 		/* fallthrough */
2452 
2453 	case SLJIT_UNORDERED_F64:
2454 		return 0x60000000;
2455 
2456 	case SLJIT_NOT_OVERFLOW:
2457 		if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))
2458 			return 0x00000000;
2459 		/* fallthrough */
2460 
2461 	case SLJIT_ORDERED_F64:
2462 		return 0x70000000;
2463 
2464 	default:
2465 		SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_CDECL);
2466 		return 0xe0000000;
2467 	}
2468 }
2469 
sljit_emit_label(struct sljit_compiler * compiler)2470 SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
2471 {
2472 	struct sljit_label *label;
2473 
2474 	CHECK_ERROR_PTR();
2475 	CHECK_PTR(check_sljit_emit_label(compiler));
2476 
2477 	if (compiler->last_label && compiler->last_label->size == compiler->size)
2478 		return compiler->last_label;
2479 
2480 	label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
2481 	PTR_FAIL_IF(!label);
2482 	set_label(label, compiler);
2483 	return label;
2484 }
2485 
sljit_emit_jump(struct sljit_compiler * compiler,sljit_s32 type)2486 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
2487 {
2488 	struct sljit_jump *jump;
2489 
2490 	CHECK_ERROR_PTR();
2491 	CHECK_PTR(check_sljit_emit_jump(compiler, type));
2492 
2493 	jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
2494 	PTR_FAIL_IF(!jump);
2495 	set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
2496 	type &= 0xff;
2497 
2498 	SLJIT_ASSERT(reg_map[TMP_REG1] != 14);
2499 
2500 #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
2501 	if (type >= SLJIT_FAST_CALL)
2502 		PTR_FAIL_IF(prepare_blx(compiler));
2503 	PTR_FAIL_IF(push_inst_with_unique_literal(compiler, ((EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1,
2504 		type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0)) & ~COND_MASK) | get_cc(compiler, type), 0));
2505 
2506 	if (jump->flags & SLJIT_REWRITABLE_JUMP) {
2507 		jump->addr = compiler->size;
2508 		compiler->patches++;
2509 	}
2510 
2511 	if (type >= SLJIT_FAST_CALL) {
2512 		jump->flags |= IS_BL;
2513 		PTR_FAIL_IF(emit_blx(compiler));
2514 	}
2515 
2516 	if (!(jump->flags & SLJIT_REWRITABLE_JUMP))
2517 		jump->addr = compiler->size;
2518 #else
2519 	if (type >= SLJIT_FAST_CALL)
2520 		jump->flags |= IS_BL;
2521 	PTR_FAIL_IF(emit_imm(compiler, TMP_REG1, 0));
2522 	PTR_FAIL_IF(push_inst(compiler, (((type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1)) & ~COND_MASK) | get_cc(compiler, type)));
2523 	jump->addr = compiler->size;
2524 #endif
2525 	return jump;
2526 }
2527 
2528 #ifdef __SOFTFP__
2529 
softfloat_call_with_args(struct sljit_compiler * compiler,sljit_s32 arg_types,sljit_s32 * src,sljit_u32 * extra_space)2530 static sljit_s32 softfloat_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src, sljit_u32 *extra_space)
2531 {
2532 	sljit_u32 is_tail_call = *extra_space & SLJIT_CALL_RETURN;
2533 	sljit_u32 offset = 0;
2534 	sljit_u32 word_arg_offset = 0;
2535 	sljit_u32 src_offset = 4 * sizeof(sljit_sw);
2536 	sljit_u32 float_arg_count = 0;
2537 	sljit_s32 types = 0;
2538 	sljit_u8 offsets[4];
2539 	sljit_u8 *offset_ptr = offsets;
2540 
2541 	if (src && FAST_IS_REG(*src))
2542 		src_offset = (sljit_uw)reg_map[*src] * sizeof(sljit_sw);
2543 
2544 	arg_types >>= SLJIT_ARG_SHIFT;
2545 
2546 	while (arg_types) {
2547 		types = (types << SLJIT_ARG_SHIFT) | (arg_types & SLJIT_ARG_MASK);
2548 
2549 		switch (arg_types & SLJIT_ARG_MASK) {
2550 		case SLJIT_ARG_TYPE_F64:
2551 			if (offset & 0x7)
2552 				offset += sizeof(sljit_sw);
2553 			*offset_ptr++ = (sljit_u8)offset;
2554 			offset += sizeof(sljit_f64);
2555 			float_arg_count++;
2556 			break;
2557 		case SLJIT_ARG_TYPE_F32:
2558 			*offset_ptr++ = (sljit_u8)offset;
2559 			offset += sizeof(sljit_f32);
2560 			float_arg_count++;
2561 			break;
2562 		default:
2563 			*offset_ptr++ = (sljit_u8)offset;
2564 			offset += sizeof(sljit_sw);
2565 			word_arg_offset += sizeof(sljit_sw);
2566 			break;
2567 		}
2568 
2569 		arg_types >>= SLJIT_ARG_SHIFT;
2570 	}
2571 
2572 	if (offset > 4 * sizeof(sljit_sw) && (!is_tail_call || offset > compiler->args_size)) {
2573 		/* Keep lr register on the stack. */
2574 		if (is_tail_call)
2575 			offset += sizeof(sljit_sw);
2576 
2577 		offset = ((offset - 4 * sizeof(sljit_sw)) + 0x7) & ~(sljit_uw)0x7;
2578 
2579 		*extra_space = offset;
2580 
2581 		if (is_tail_call)
2582 			FAIL_IF(emit_stack_frame_release(compiler, (sljit_s32)offset));
2583 		else
2584 			FAIL_IF(push_inst(compiler, SUB | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | offset));
2585 	} else {
2586 		if (is_tail_call)
2587 			FAIL_IF(emit_stack_frame_release(compiler, -1));
2588 		*extra_space = 0;
2589 	}
2590 
2591 	/* Process arguments in reversed direction. */
2592 	while (types) {
2593 		switch (types & SLJIT_ARG_MASK) {
2594 		case SLJIT_ARG_TYPE_F64:
2595 			float_arg_count--;
2596 			offset = *(--offset_ptr);
2597 
2598 			SLJIT_ASSERT((offset & 0x7) == 0);
2599 
2600 			if (offset < 4 * sizeof(sljit_sw)) {
2601 				if (src_offset == offset || src_offset == offset + sizeof(sljit_sw)) {
2602 					FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | (src_offset >> 2)));
2603 					*src = TMP_REG1;
2604 				}
2605 				FAIL_IF(push_inst(compiler, VMOV2 | 0x100000 | (offset << 10) | ((offset + sizeof(sljit_sw)) << 14) | float_arg_count));
2606 			} else
2607 				FAIL_IF(push_inst(compiler, VSTR_F32 | 0x800100 | RN(SLJIT_SP)
2608 						| (float_arg_count << 12) | ((offset - 4 * sizeof(sljit_sw)) >> 2)));
2609 			break;
2610 		case SLJIT_ARG_TYPE_F32:
2611 			float_arg_count--;
2612 			offset = *(--offset_ptr);
2613 
2614 			if (offset < 4 * sizeof(sljit_sw)) {
2615 				if (src_offset == offset) {
2616 					FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | (src_offset >> 2)));
2617 					*src = TMP_REG1;
2618 				}
2619 				FAIL_IF(push_inst(compiler, VMOV | 0x100000 | (float_arg_count << 16) | (offset << 10)));
2620 			} else
2621 				FAIL_IF(push_inst(compiler, VSTR_F32 | 0x800000 | RN(SLJIT_SP)
2622 						| (float_arg_count << 12) | ((offset - 4 * sizeof(sljit_sw)) >> 2)));
2623 			break;
2624 		default:
2625 			word_arg_offset -= sizeof(sljit_sw);
2626 			offset = *(--offset_ptr);
2627 
2628 			SLJIT_ASSERT(offset >= word_arg_offset);
2629 
2630 			if (offset != word_arg_offset) {
2631 				if (offset < 4 * sizeof(sljit_sw)) {
2632 					if (src_offset == offset) {
2633 						FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | (src_offset >> 2)));
2634 						*src = TMP_REG1;
2635 					}
2636 					else if (src_offset == word_arg_offset) {
2637 						*src = (sljit_s32)(SLJIT_R0 + (offset >> 2));
2638 						src_offset = offset;
2639 					}
2640 					FAIL_IF(push_inst(compiler, MOV | (offset << 10) | (word_arg_offset >> 2)));
2641 				} else
2642 					FAIL_IF(push_inst(compiler, data_transfer_insts[WORD_SIZE] | 0x800000 | RN(SLJIT_SP) | (word_arg_offset << 10) | (offset - 4 * sizeof(sljit_sw))));
2643 			}
2644 			break;
2645 		}
2646 
2647 		types >>= SLJIT_ARG_SHIFT;
2648 	}
2649 
2650 	return SLJIT_SUCCESS;
2651 }
2652 
softfloat_post_call_with_args(struct sljit_compiler * compiler,sljit_s32 arg_types)2653 static sljit_s32 softfloat_post_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types)
2654 {
2655 	if ((arg_types & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F64)
2656 		FAIL_IF(push_inst(compiler, VMOV2 | (1 << 16) | (0 << 12) | 0));
2657 	if ((arg_types & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F32)
2658 		FAIL_IF(push_inst(compiler, VMOV | (0 << 16) | (0 << 12)));
2659 
2660 	return SLJIT_SUCCESS;
2661 }
2662 
2663 #else /* !__SOFTFP__ */
2664 
hardfloat_call_with_args(struct sljit_compiler * compiler,sljit_s32 arg_types)2665 static sljit_s32 hardfloat_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types)
2666 {
2667 	sljit_u32 offset = SLJIT_FR0;
2668 	sljit_u32 new_offset = SLJIT_FR0;
2669 	sljit_u32 f32_offset = 0;
2670 
2671 	/* Remove return value. */
2672 	arg_types >>= SLJIT_ARG_SHIFT;
2673 
2674 	while (arg_types) {
2675 		switch (arg_types & SLJIT_ARG_MASK) {
2676 		case SLJIT_ARG_TYPE_F64:
2677 			if (offset != new_offset)
2678 				FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32,
2679 					SLJIT_32, new_offset, offset, 0)));
2680 
2681 			new_offset++;
2682 			offset++;
2683 			break;
2684 		case SLJIT_ARG_TYPE_F32:
2685 			if (f32_offset != 0) {
2686 				FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32,
2687 					0x400000, f32_offset, offset, 0)));
2688 				f32_offset = 0;
2689 			} else {
2690 				if (offset != new_offset)
2691 					FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32,
2692 						0, new_offset, offset, 0)));
2693 				f32_offset = new_offset;
2694 				new_offset++;
2695 			}
2696 			offset++;
2697 			break;
2698 		}
2699 		arg_types >>= SLJIT_ARG_SHIFT;
2700 	}
2701 
2702 	return SLJIT_SUCCESS;
2703 }
2704 
2705 #endif /* __SOFTFP__ */
2706 
2707 #undef EMIT_FPU_OPERATION
2708 
sljit_emit_call(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 arg_types)2709 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
2710 	sljit_s32 arg_types)
2711 {
2712 #ifdef __SOFTFP__
2713 	struct sljit_jump *jump;
2714 	sljit_u32 extra_space = (sljit_u32)type;
2715 #endif
2716 
2717 	CHECK_ERROR_PTR();
2718 	CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
2719 
2720 #ifdef __SOFTFP__
2721 	PTR_FAIL_IF(softfloat_call_with_args(compiler, arg_types, NULL, &extra_space));
2722 	SLJIT_ASSERT((extra_space & 0x7) == 0);
2723 
2724 	if ((type & SLJIT_CALL_RETURN) && extra_space == 0)
2725 		type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
2726 
2727 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
2728 		|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
2729 	compiler->skip_checks = 1;
2730 #endif
2731 
2732 	jump = sljit_emit_jump(compiler, type);
2733 	PTR_FAIL_IF(jump == NULL);
2734 
2735 	if (extra_space > 0) {
2736 		if (type & SLJIT_CALL_RETURN)
2737 			PTR_FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1,
2738 				TMP_REG2, SLJIT_SP, extra_space - sizeof(sljit_sw))));
2739 
2740 		PTR_FAIL_IF(push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | extra_space));
2741 
2742 		if (type & SLJIT_CALL_RETURN) {
2743 			PTR_FAIL_IF(push_inst(compiler, BX | RM(TMP_REG2)));
2744 			return jump;
2745 		}
2746 	}
2747 
2748 	SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));
2749 	PTR_FAIL_IF(softfloat_post_call_with_args(compiler, arg_types));
2750 	return jump;
2751 #else /* !__SOFTFP__ */
2752 	if (type & SLJIT_CALL_RETURN) {
2753 		PTR_FAIL_IF(emit_stack_frame_release(compiler, -1));
2754 		type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
2755 	}
2756 
2757 	PTR_FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
2758 
2759 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
2760 		|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
2761 	compiler->skip_checks = 1;
2762 #endif
2763 
2764 	return sljit_emit_jump(compiler, type);
2765 #endif /* __SOFTFP__ */
2766 }
2767 
sljit_emit_ijump(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 src,sljit_sw srcw)2768 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
2769 {
2770 	struct sljit_jump *jump;
2771 
2772 	CHECK_ERROR();
2773 	CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
2774 	ADJUST_LOCAL_OFFSET(src, srcw);
2775 
2776 	SLJIT_ASSERT(reg_map[TMP_REG1] != 14);
2777 
2778 	if (!(src & SLJIT_IMM)) {
2779 		if (FAST_IS_REG(src)) {
2780 			SLJIT_ASSERT(reg_map[src] != 14);
2781 			return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(src));
2782 		}
2783 
2784 		SLJIT_ASSERT(src & SLJIT_MEM);
2785 		FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
2786 		return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1));
2787 	}
2788 
2789 	/* These jumps are converted to jump/call instructions when possible. */
2790 	jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
2791 	FAIL_IF(!jump);
2792 	set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0));
2793 	jump->u.target = (sljit_uw)srcw;
2794 
2795 #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
2796 	if (type >= SLJIT_FAST_CALL)
2797 		FAIL_IF(prepare_blx(compiler));
2798 	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));
2799 	if (type >= SLJIT_FAST_CALL)
2800 		FAIL_IF(emit_blx(compiler));
2801 #else
2802 	FAIL_IF(emit_imm(compiler, TMP_REG1, 0));
2803 	FAIL_IF(push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1)));
2804 #endif
2805 	jump->addr = compiler->size;
2806 	return SLJIT_SUCCESS;
2807 }
2808 
sljit_emit_icall(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 arg_types,sljit_s32 src,sljit_sw srcw)2809 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
2810 	sljit_s32 arg_types,
2811 	sljit_s32 src, sljit_sw srcw)
2812 {
2813 #ifdef __SOFTFP__
2814 	sljit_u32 extra_space = (sljit_u32)type;
2815 #endif
2816 
2817 	CHECK_ERROR();
2818 	CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
2819 
2820 	if (src & SLJIT_MEM) {
2821 		FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
2822 		src = TMP_REG1;
2823 	}
2824 
2825 	if ((type & SLJIT_CALL_RETURN) && (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0)) {
2826 		FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | RM(src)));
2827 		src = TMP_REG1;
2828 	}
2829 
2830 #ifdef __SOFTFP__
2831 	FAIL_IF(softfloat_call_with_args(compiler, arg_types, &src, &extra_space));
2832 	SLJIT_ASSERT((extra_space & 0x7) == 0);
2833 
2834 	if ((type & SLJIT_CALL_RETURN) && extra_space == 0)
2835 		type = SLJIT_JUMP;
2836 
2837 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
2838 		|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
2839 	compiler->skip_checks = 1;
2840 #endif
2841 
2842 	FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));
2843 
2844 	if (extra_space > 0) {
2845 		if (type & SLJIT_CALL_RETURN)
2846 			FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1,
2847 				TMP_REG2, SLJIT_SP, extra_space - sizeof(sljit_sw))));
2848 
2849 		FAIL_IF(push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | extra_space));
2850 
2851 		if (type & SLJIT_CALL_RETURN)
2852 			return push_inst(compiler, BX | RM(TMP_REG2));
2853 	}
2854 
2855 	SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));
2856 	return softfloat_post_call_with_args(compiler, arg_types);
2857 #else /* !__SOFTFP__ */
2858 	if (type & SLJIT_CALL_RETURN) {
2859 		FAIL_IF(emit_stack_frame_release(compiler, -1));
2860 		type = SLJIT_JUMP;
2861 	}
2862 
2863 	FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
2864 
2865 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
2866 		|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
2867 	compiler->skip_checks = 1;
2868 #endif
2869 
2870 	return sljit_emit_ijump(compiler, type, src, srcw);
2871 #endif /* __SOFTFP__ */
2872 }
2873 
sljit_emit_op_flags(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 type)2874 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
2875 	sljit_s32 dst, sljit_sw dstw,
2876 	sljit_s32 type)
2877 {
2878 	sljit_s32 dst_reg, flags = GET_ALL_FLAGS(op);
2879 	sljit_uw cc, ins;
2880 
2881 	CHECK_ERROR();
2882 	CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
2883 	ADJUST_LOCAL_OFFSET(dst, dstw);
2884 
2885 	op = GET_OPCODE(op);
2886 	cc = get_cc(compiler, type & 0xff);
2887 	dst_reg = FAST_IS_REG(dst) ? dst : TMP_REG1;
2888 
2889 	if (op < SLJIT_ADD) {
2890 		FAIL_IF(push_inst(compiler, MOV | RD(dst_reg) | SRC2_IMM | 0));
2891 		FAIL_IF(push_inst(compiler, ((MOV | RD(dst_reg) | SRC2_IMM | 1) & ~COND_MASK) | cc));
2892 		if (dst & SLJIT_MEM)
2893 			return emit_op_mem(compiler, WORD_SIZE, TMP_REG1, dst, dstw, TMP_REG2);
2894 		return SLJIT_SUCCESS;
2895 	}
2896 
2897 	ins = (op == SLJIT_AND ? AND : (op == SLJIT_OR ? ORR : EOR));
2898 
2899 	if (dst & SLJIT_MEM)
2900 		FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, dst, dstw, TMP_REG2));
2901 
2902 	FAIL_IF(push_inst(compiler, ((ins | RD(dst_reg) | RN(dst_reg) | SRC2_IMM | 1) & ~COND_MASK) | cc));
2903 
2904 	if (op == SLJIT_AND)
2905 		FAIL_IF(push_inst(compiler, ((ins | RD(dst_reg) | RN(dst_reg) | SRC2_IMM | 0) & ~COND_MASK) | (cc ^ 0x10000000)));
2906 
2907 	if (dst & SLJIT_MEM)
2908 		FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, dst, dstw, TMP_REG2));
2909 
2910 	if (flags & SLJIT_SET_Z)
2911 		return push_inst(compiler, MOV | SET_FLAGS | RD(TMP_REG2) | RM(dst_reg));
2912 	return SLJIT_SUCCESS;
2913 }
2914 
sljit_emit_cmov(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 dst_reg,sljit_s32 src,sljit_sw srcw)2915 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
2916 	sljit_s32 dst_reg,
2917 	sljit_s32 src, sljit_sw srcw)
2918 {
2919 	sljit_uw cc, tmp;
2920 
2921 	CHECK_ERROR();
2922 	CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
2923 
2924 	dst_reg &= ~SLJIT_32;
2925 
2926 	cc = get_cc(compiler, type & 0xff);
2927 
2928 	if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {
2929 		tmp = get_imm((sljit_uw)srcw);
2930 		if (tmp)
2931 			return push_inst(compiler, ((MOV | RD(dst_reg) | tmp) & ~COND_MASK) | cc);
2932 
2933 		tmp = get_imm(~(sljit_uw)srcw);
2934 		if (tmp)
2935 			return push_inst(compiler, ((MVN | RD(dst_reg) | tmp) & ~COND_MASK) | cc);
2936 
2937 #if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
2938 		tmp = (sljit_uw)srcw;
2939 		FAIL_IF(push_inst(compiler, (MOVW & ~COND_MASK) | cc | RD(dst_reg) | ((tmp << 4) & 0xf0000) | (tmp & 0xfff)));
2940 		if (tmp <= 0xffff)
2941 			return SLJIT_SUCCESS;
2942 		return push_inst(compiler, (MOVT & ~COND_MASK) | cc | RD(dst_reg) | ((tmp >> 12) & 0xf0000) | ((tmp >> 16) & 0xfff));
2943 #else
2944 		FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)srcw));
2945 		src = TMP_REG1;
2946 #endif
2947 	}
2948 
2949 	return push_inst(compiler, ((MOV | RD(dst_reg) | RM(src)) & ~COND_MASK) | cc);
2950 }
2951 
sljit_emit_mem(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 reg,sljit_s32 mem,sljit_sw memw)2952 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
2953 	sljit_s32 reg,
2954 	sljit_s32 mem, sljit_sw memw)
2955 {
2956 	sljit_s32 flags;
2957 	sljit_uw is_type1_transfer, inst;
2958 
2959 	CHECK_ERROR();
2960 	CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
2961 
2962 	is_type1_transfer = 1;
2963 
2964 	switch (type & 0xff) {
2965 	case SLJIT_MOV:
2966 	case SLJIT_MOV_U32:
2967 	case SLJIT_MOV_S32:
2968 	case SLJIT_MOV32:
2969 	case SLJIT_MOV_P:
2970 		flags = WORD_SIZE;
2971 		break;
2972 	case SLJIT_MOV_U8:
2973 		flags = BYTE_SIZE;
2974 		break;
2975 	case SLJIT_MOV_S8:
2976 		if (!(type & SLJIT_MEM_STORE))
2977 			is_type1_transfer = 0;
2978 		flags = BYTE_SIZE | SIGNED;
2979 		break;
2980 	case SLJIT_MOV_U16:
2981 		is_type1_transfer = 0;
2982 		flags = HALF_SIZE;
2983 		break;
2984 	case SLJIT_MOV_S16:
2985 		is_type1_transfer = 0;
2986 		flags = HALF_SIZE | SIGNED;
2987 		break;
2988 	default:
2989 		SLJIT_UNREACHABLE();
2990 		flags = WORD_SIZE;
2991 		break;
2992 	}
2993 
2994 	if (!(type & SLJIT_MEM_STORE))
2995 		flags |= LOAD_DATA;
2996 
2997 	SLJIT_ASSERT(is_type1_transfer == !!IS_TYPE1_TRANSFER(flags));
2998 
2999 	if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
3000 		if (!is_type1_transfer && memw != 0)
3001 			return SLJIT_ERR_UNSUPPORTED;
3002 	}
3003 	else {
3004 		if (is_type1_transfer) {
3005 			if (memw > 4095 || memw < -4095)
3006 				return SLJIT_ERR_UNSUPPORTED;
3007 		}
3008 		else {
3009 			if (memw > 255 || memw < -255)
3010 				return SLJIT_ERR_UNSUPPORTED;
3011 		}
3012 	}
3013 
3014 	if (type & SLJIT_MEM_SUPP)
3015 		return SLJIT_SUCCESS;
3016 
3017 	if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
3018 		memw &= 0x3;
3019 
3020 		inst = EMIT_DATA_TRANSFER(flags, 1, reg, mem & REG_MASK, RM(OFFS_REG(mem)) | ((sljit_uw)memw << 7));
3021 
3022 		if (is_type1_transfer)
3023 			inst |= (1 << 25);
3024 
3025 		if (type & SLJIT_MEM_PRE)
3026 			inst |= (1 << 21);
3027 		else
3028 			inst ^= (1 << 24);
3029 
3030 		return push_inst(compiler, inst);
3031 	}
3032 
3033 	inst = EMIT_DATA_TRANSFER(flags, 0, reg, mem & REG_MASK, 0);
3034 
3035 	if (type & SLJIT_MEM_PRE)
3036 		inst |= (1 << 21);
3037 	else
3038 		inst ^= (1 << 24);
3039 
3040 	if (is_type1_transfer) {
3041 		if (memw >= 0)
3042 			inst |= (1 << 23);
3043 		else
3044 			memw = -memw;
3045 
3046 		return push_inst(compiler, inst | (sljit_uw)memw);
3047 	}
3048 
3049 	if (memw >= 0)
3050 		inst |= (1 << 23);
3051 	else
3052 		memw = -memw;
3053 
3054 	return push_inst(compiler, inst | TYPE2_TRANSFER_IMM((sljit_uw)memw));
3055 }
3056 
sljit_emit_const(struct sljit_compiler * compiler,sljit_s32 dst,sljit_sw dstw,sljit_sw init_value)3057 SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
3058 {
3059 	struct sljit_const *const_;
3060 	sljit_s32 dst_r;
3061 
3062 	CHECK_ERROR_PTR();
3063 	CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
3064 	ADJUST_LOCAL_OFFSET(dst, dstw);
3065 
3066 	dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
3067 
3068 #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
3069 	PTR_FAIL_IF(push_inst_with_unique_literal(compiler,
3070 		EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, dst_r, TMP_PC, 0), (sljit_uw)init_value));
3071 	compiler->patches++;
3072 #else
3073 	PTR_FAIL_IF(emit_imm(compiler, dst_r, init_value));
3074 #endif
3075 
3076 	const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
3077 	PTR_FAIL_IF(!const_);
3078 	set_const(const_, compiler);
3079 
3080 	if (dst & SLJIT_MEM)
3081 		PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1));
3082 	return const_;
3083 }
3084 
sljit_emit_put_label(struct sljit_compiler * compiler,sljit_s32 dst,sljit_sw dstw)3085 SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
3086 {
3087 	struct sljit_put_label *put_label;
3088 	sljit_s32 dst_r;
3089 
3090 	CHECK_ERROR_PTR();
3091 	CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));
3092 	ADJUST_LOCAL_OFFSET(dst, dstw);
3093 
3094 	dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
3095 
3096 #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
3097 	PTR_FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, dst_r, TMP_PC, 0), 0));
3098 	compiler->patches++;
3099 #else
3100 	PTR_FAIL_IF(emit_imm(compiler, dst_r, 0));
3101 #endif
3102 
3103 	put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));
3104 	PTR_FAIL_IF(!put_label);
3105 	set_put_label(put_label, compiler, 0);
3106 
3107 	if (dst & SLJIT_MEM)
3108 		PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1));
3109 	return put_label;
3110 }
3111 
sljit_set_jump_addr(sljit_uw addr,sljit_uw new_target,sljit_sw executable_offset)3112 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
3113 {
3114 	inline_set_jump_addr(addr, executable_offset, new_target, 1);
3115 }
3116 
sljit_set_const(sljit_uw addr,sljit_sw new_constant,sljit_sw executable_offset)3117 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
3118 {
3119 	inline_set_const(addr, executable_offset, (sljit_uw)new_constant, 1);
3120 }
3121