2 * Stack-less Just-In-Time compiler
4 * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
6 * Redistribution and use in source and binary forms, with or without modification, are
7 * permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright notice, this list of
10 * conditions and the following disclaimer.
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.
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.
27 SLJIT_API_FUNC_ATTRIBUTE
const char* sljit_get_platform_name(void)
30 return "ARM-Thumb2" SLJIT_CPUINFO
" ABI:softfp";
32 return "ARM-Thumb2" SLJIT_CPUINFO
" ABI:hardfp";
36 /* Length of an instruction word. */
37 typedef sljit_u32 sljit_ins
;
39 /* Last register + 1. */
40 #define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
41 #define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
42 #define TMP_PC (SLJIT_NUMBER_OF_REGISTERS + 4)
44 #define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
45 #define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)
47 /* See sljit_emit_enter and sljit_emit_op0 if you want to change them. */
48 static const sljit_u8 reg_map
[SLJIT_NUMBER_OF_REGISTERS
+ 5] = {
49 0, 0, 1, 2, 3, 11, 10, 9, 8, 7, 6, 5, 4, 13, 12, 14, 15
52 static const sljit_u8 freg_map
[SLJIT_NUMBER_OF_FLOAT_REGISTERS
+ 3] = {
53 0, 0, 1, 2, 3, 4, 5, 6, 7
56 #define COPY_BITS(src, from, to, bits) \
57 ((from >= to ? (src >> (from - to)) : (src << (to - from))) & (((1 << bits) - 1) << to))
59 /* Thumb16 encodings. */
60 #define RD3(rd) (reg_map[rd])
61 #define RN3(rn) (reg_map[rn] << 3)
62 #define RM3(rm) (reg_map[rm] << 6)
63 #define RDN3(rdn) (reg_map[rdn] << 8)
64 #define IMM3(imm) (imm << 6)
65 #define IMM8(imm) (imm)
67 /* Thumb16 helpers. */
68 #define SET_REGS44(rd, rn) \
69 ((reg_map[rn] << 3) | (reg_map[rd] & 0x7) | ((reg_map[rd] & 0x8) << 4))
70 #define IS_2_LO_REGS(reg1, reg2) \
71 (reg_map[reg1] <= 7 && reg_map[reg2] <= 7)
72 #define IS_3_LO_REGS(reg1, reg2, reg3) \
73 (reg_map[reg1] <= 7 && reg_map[reg2] <= 7 && reg_map[reg3] <= 7)
75 /* Thumb32 encodings. */
76 #define RD4(rd) (reg_map[rd] << 8)
77 #define RN4(rn) (reg_map[rn] << 16)
78 #define RM4(rm) (reg_map[rm])
79 #define RT4(rt) (reg_map[rt] << 12)
80 #define DD4(dd) (freg_map[dd] << 12)
81 #define DN4(dn) (freg_map[dn] << 16)
82 #define DM4(dm) (freg_map[dm])
84 (COPY_BITS(imm, 2, 12, 3) | ((imm & 0x3) << 6))
86 (COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | (imm & 0xff))
88 /* --------------------------------------------------------------------- */
89 /* Instrucion forms */
90 /* --------------------------------------------------------------------- */
92 /* dot '.' changed to _
93 I immediate form (possibly followed by number of immediate bits). */
94 #define ADCI 0xf1400000
96 #define ADC_W 0xeb400000
100 #define ADDSI8 0x3000
101 #define ADD_W 0xeb000000
102 #define ADDWI 0xf2000000
103 #define ADD_SP 0xb000
104 #define ADD_W 0xeb000000
105 #define ADD_WI 0xf1000000
106 #define ANDI 0xf0000000
108 #define AND_W 0xea000000
111 #define ASR_W 0xfa40f000
112 #define ASR_WI 0xea4f0020
114 #define BICI 0xf0200000
118 #define CLZ 0xfab0f080
119 #define CMNI_W 0xf1100f00
122 #define CMPI_W 0xf1b00f00
124 #define CMP_W 0xebb00f00
125 #define EORI 0xf0800000
127 #define EOR_W 0xea800000
129 #define LDRI 0xf8500800
132 #define LSL_W 0xfa00f000
133 #define LSL_WI 0xea4f0000
136 #define LSR_W 0xfa20f000
137 #define LSR_WI 0xea4f0010
141 #define MOVT 0xf2c00000
142 #define MOVW 0xf2400000
143 #define MOV_W 0xea4f0000
144 #define MOV_WI 0xf04f0000
145 #define MUL 0xfb00f000
147 #define MVN_W 0xea6f0000
148 #define MVN_WI 0xf06f0000
150 #define ORNI 0xf0600000
151 #define ORRI 0xf0400000
153 #define ORR_W 0xea400000
155 #define POP_W 0xe8bd0000
157 #define PUSH_W 0xe92d0000
158 #define RSB_WI 0xf1c00000
160 #define SBCI 0xf1600000
162 #define SBC_W 0xeb600000
163 #define SDIV 0xfb90f0f0
164 #define SMULL 0xfb800000
165 #define STR_SP 0x9000
167 #define SUBSI3 0x1e00
168 #define SUBSI8 0x3800
169 #define SUB_W 0xeba00000
170 #define SUBWI 0xf2a00000
171 #define SUB_SP 0xb080
172 #define SUB_WI 0xf1a00000
174 #define SXTB_W 0xfa4ff080
176 #define SXTH_W 0xfa0ff080
178 #define UDIV 0xfbb0f0f0
179 #define UMULL 0xfba00000
181 #define UXTB_W 0xfa5ff080
183 #define UXTH_W 0xfa1ff080
184 #define VABS_F32 0xeeb00ac0
185 #define VADD_F32 0xee300a00
186 #define VCMP_F32 0xeeb40a40
187 #define VCVT_F32_S32 0xeeb80ac0
188 #define VCVT_F64_F32 0xeeb70ac0
189 #define VCVT_S32_F32 0xeebd0ac0
190 #define VDIV_F32 0xee800a00
191 #define VMOV_F32 0xeeb00a40
192 #define VMOV 0xee000a10
193 #define VMOV2 0xec400a10
194 #define VMRS 0xeef1fa10
195 #define VMUL_F32 0xee200a00
196 #define VNEG_F32 0xeeb10a40
197 #define VSTR_F32 0xed000a00
198 #define VSUB_F32 0xee300a40
200 static sljit_s32
push_inst16(struct sljit_compiler
*compiler
, sljit_ins inst
)
203 SLJIT_ASSERT(!(inst
& 0xffff0000));
205 ptr
= (sljit_u16
*)ensure_buf(compiler
, sizeof(sljit_u16
));
209 return SLJIT_SUCCESS
;
212 static sljit_s32
push_inst32(struct sljit_compiler
*compiler
, sljit_ins inst
)
214 sljit_u16
*ptr
= (sljit_u16
*)ensure_buf(compiler
, sizeof(sljit_ins
));
219 return SLJIT_SUCCESS
;
222 static SLJIT_INLINE sljit_s32
emit_imm32_const(struct sljit_compiler
*compiler
, sljit_s32 dst
, sljit_uw imm
)
224 FAIL_IF(push_inst32(compiler
, MOVW
| RD4(dst
)
225 | COPY_BITS(imm
, 12, 16, 4) | COPY_BITS(imm
, 11, 26, 1) | COPY_BITS(imm
, 8, 12, 3) | (imm
& 0xff)));
226 return push_inst32(compiler
, MOVT
| RD4(dst
)
227 | COPY_BITS(imm
, 12 + 16, 16, 4) | COPY_BITS(imm
, 11 + 16, 26, 1) | COPY_BITS(imm
, 8 + 16, 12, 3) | ((imm
& 0xff0000) >> 16));
230 static SLJIT_INLINE
void modify_imm32_const(sljit_u16
*inst
, sljit_uw new_imm
)
232 sljit_s32 dst
= inst
[1] & 0x0f00;
233 SLJIT_ASSERT(((inst
[0] & 0xfbf0) == (MOVW
>> 16)) && ((inst
[2] & 0xfbf0) == (MOVT
>> 16)) && dst
== (inst
[3] & 0x0f00));
234 inst
[0] = (MOVW
>> 16) | COPY_BITS(new_imm
, 12, 0, 4) | COPY_BITS(new_imm
, 11, 10, 1);
235 inst
[1] = dst
| COPY_BITS(new_imm
, 8, 12, 3) | (new_imm
& 0xff);
236 inst
[2] = (MOVT
>> 16) | COPY_BITS(new_imm
, 12 + 16, 0, 4) | COPY_BITS(new_imm
, 11 + 16, 10, 1);
237 inst
[3] = dst
| COPY_BITS(new_imm
, 8 + 16, 12, 3) | ((new_imm
& 0xff0000) >> 16);
240 static SLJIT_INLINE sljit_s32
detect_jump_type(struct sljit_jump
*jump
, sljit_u16
*code_ptr
, sljit_u16
*code
, sljit_sw executable_offset
)
244 if (jump
->flags
& SLJIT_REWRITABLE_JUMP
)
247 if (jump
->flags
& JUMP_ADDR
) {
248 /* Branch to ARM code is not optimized yet. */
249 if (!(jump
->u
.target
& 0x1))
251 diff
= ((sljit_sw
)jump
->u
.target
- (sljit_sw
)(code_ptr
+ 2) - executable_offset
) >> 1;
254 SLJIT_ASSERT(jump
->flags
& JUMP_LABEL
);
255 diff
= ((sljit_sw
)(code
+ jump
->u
.label
->size
) - (sljit_sw
)(code_ptr
+ 2)) >> 1;
258 if (jump
->flags
& IS_COND
) {
259 SLJIT_ASSERT(!(jump
->flags
& IS_BL
));
260 if (diff
<= 127 && diff
>= -128) {
261 jump
->flags
|= PATCH_TYPE1
;
264 if (diff
<= 524287 && diff
>= -524288) {
265 jump
->flags
|= PATCH_TYPE2
;
268 /* +1 comes from the prefix IT instruction. */
270 if (diff
<= 8388607 && diff
>= -8388608) {
271 jump
->flags
|= PATCH_TYPE3
;
275 else if (jump
->flags
& IS_BL
) {
276 if (diff
<= 8388607 && diff
>= -8388608) {
277 jump
->flags
|= PATCH_BL
;
282 if (diff
<= 1023 && diff
>= -1024) {
283 jump
->flags
|= PATCH_TYPE4
;
286 if (diff
<= 8388607 && diff
>= -8388608) {
287 jump
->flags
|= PATCH_TYPE5
;
295 static SLJIT_INLINE
void set_jump_instruction(struct sljit_jump
*jump
, sljit_sw executable_offset
)
297 sljit_s32 type
= (jump
->flags
>> 4) & 0xf;
299 sljit_u16
*jump_inst
;
302 if (SLJIT_UNLIKELY(type
== 0)) {
303 modify_imm32_const((sljit_u16
*)jump
->addr
, (jump
->flags
& JUMP_LABEL
) ? jump
->u
.label
->addr
: jump
->u
.target
);
307 if (jump
->flags
& JUMP_ADDR
) {
308 SLJIT_ASSERT(jump
->u
.target
& 0x1);
309 diff
= ((sljit_sw
)jump
->u
.target
- (sljit_sw
)(jump
->addr
+ sizeof(sljit_u32
)) - executable_offset
) >> 1;
312 SLJIT_ASSERT(jump
->u
.label
->addr
& 0x1);
313 diff
= ((sljit_sw
)(jump
->u
.label
->addr
) - (sljit_sw
)(jump
->addr
+ sizeof(sljit_u32
)) - executable_offset
) >> 1;
315 jump_inst
= (sljit_u16
*)jump
->addr
;
319 /* Encoding T1 of 'B' instruction */
320 SLJIT_ASSERT(diff
<= 127 && diff
>= -128 && (jump
->flags
& IS_COND
));
321 jump_inst
[0] = 0xd000 | (jump
->flags
& 0xf00) | (diff
& 0xff);
324 /* Encoding T3 of 'B' instruction */
325 SLJIT_ASSERT(diff
<= 524287 && diff
>= -524288 && (jump
->flags
& IS_COND
));
326 jump_inst
[0] = 0xf000 | COPY_BITS(jump
->flags
, 8, 6, 4) | COPY_BITS(diff
, 11, 0, 6) | COPY_BITS(diff
, 19, 10, 1);
327 jump_inst
[1] = 0x8000 | COPY_BITS(diff
, 17, 13, 1) | COPY_BITS(diff
, 18, 11, 1) | (diff
& 0x7ff);
330 SLJIT_ASSERT(jump
->flags
& IS_COND
);
331 *jump_inst
++ = IT
| ((jump
->flags
>> 4) & 0xf0) | 0x8;
336 /* Encoding T2 of 'B' instruction */
337 SLJIT_ASSERT(diff
<= 1023 && diff
>= -1024 && !(jump
->flags
& IS_COND
));
338 jump_inst
[0] = 0xe000 | (diff
& 0x7ff);
342 SLJIT_ASSERT(diff
<= 8388607 && diff
>= -8388608);
344 /* Really complex instruction form for branches. */
345 s
= (diff
>> 23) & 0x1;
346 j1
= (~(diff
>> 22) ^ s
) & 0x1;
347 j2
= (~(diff
>> 21) ^ s
) & 0x1;
348 jump_inst
[0] = 0xf000 | (s
<< 10) | COPY_BITS(diff
, 11, 0, 10);
349 jump_inst
[1] = (j1
<< 13) | (j2
<< 11) | (diff
& 0x7ff);
351 /* The others have a common form. */
352 if (type
== 5) /* Encoding T4 of 'B' instruction */
353 jump_inst
[1] |= 0x9000;
354 else if (type
== 6) /* Encoding T1 of 'BL' instruction */
355 jump_inst
[1] |= 0xd000;
360 SLJIT_API_FUNC_ATTRIBUTE
void* sljit_generate_code(struct sljit_compiler
*compiler
)
362 struct sljit_memory_fragment
*buf
;
369 sljit_sw executable_offset
;
371 struct sljit_label
*label
;
372 struct sljit_jump
*jump
;
373 struct sljit_const
*const_
;
374 struct sljit_put_label
*put_label
;
377 CHECK_PTR(check_sljit_generate_code(compiler
));
378 reverse_buf(compiler
);
380 code
= (sljit_u16
*)SLJIT_MALLOC_EXEC(compiler
->size
* sizeof(sljit_u16
), compiler
->exec_allocator_data
);
381 PTR_FAIL_WITH_EXEC_IF(code
);
387 executable_offset
= SLJIT_EXEC_OFFSET(code
);
389 label
= compiler
->labels
;
390 jump
= compiler
->jumps
;
391 const_
= compiler
->consts
;
392 put_label
= compiler
->put_labels
;
395 buf_ptr
= (sljit_u16
*)buf
->memory
;
396 buf_end
= buf_ptr
+ (buf
->used_size
>> 1);
398 *code_ptr
= *buf_ptr
++;
399 if (next_addr
== half_count
) {
400 SLJIT_ASSERT(!label
|| label
->size
>= half_count
);
401 SLJIT_ASSERT(!jump
|| jump
->addr
>= half_count
);
402 SLJIT_ASSERT(!const_
|| const_
->addr
>= half_count
);
403 SLJIT_ASSERT(!put_label
|| put_label
->addr
>= half_count
);
405 /* These structures are ordered by their address. */
406 if (label
&& label
->size
== half_count
) {
407 label
->addr
= ((sljit_uw
)SLJIT_ADD_EXEC_OFFSET(code_ptr
, executable_offset
)) | 0x1;
408 label
->size
= code_ptr
- code
;
411 if (jump
&& jump
->addr
== half_count
) {
412 jump
->addr
= (sljit_uw
)code_ptr
- ((jump
->flags
& IS_COND
) ? 10 : 8);
413 code_ptr
-= detect_jump_type(jump
, code_ptr
, code
, executable_offset
);
416 if (const_
&& const_
->addr
== half_count
) {
417 const_
->addr
= (sljit_uw
)code_ptr
;
418 const_
= const_
->next
;
420 if (put_label
&& put_label
->addr
== half_count
) {
421 SLJIT_ASSERT(put_label
->label
);
422 put_label
->addr
= (sljit_uw
)code_ptr
;
423 put_label
= put_label
->next
;
425 next_addr
= compute_next_addr(label
, jump
, const_
, put_label
);
429 } while (buf_ptr
< buf_end
);
434 if (label
&& label
->size
== half_count
) {
435 label
->addr
= ((sljit_uw
)SLJIT_ADD_EXEC_OFFSET(code_ptr
, executable_offset
)) | 0x1;
436 label
->size
= code_ptr
- code
;
440 SLJIT_ASSERT(!label
);
442 SLJIT_ASSERT(!const_
);
443 SLJIT_ASSERT(!put_label
);
444 SLJIT_ASSERT(code_ptr
- code
<= (sljit_sw
)compiler
->size
);
446 jump
= compiler
->jumps
;
448 set_jump_instruction(jump
, executable_offset
);
452 put_label
= compiler
->put_labels
;
454 modify_imm32_const((sljit_u16
*)put_label
->addr
, put_label
->label
->addr
);
455 put_label
= put_label
->next
;
458 compiler
->error
= SLJIT_ERR_COMPILED
;
459 compiler
->executable_offset
= executable_offset
;
460 compiler
->executable_size
= (code_ptr
- code
) * sizeof(sljit_u16
);
462 code
= (sljit_u16
*)SLJIT_ADD_EXEC_OFFSET(code
, executable_offset
);
463 code_ptr
= (sljit_u16
*)SLJIT_ADD_EXEC_OFFSET(code_ptr
, executable_offset
);
465 SLJIT_CACHE_FLUSH(code
, code_ptr
);
466 SLJIT_UPDATE_WX_FLAGS(code
, code_ptr
, 1);
468 /* Set thumb mode flag. */
469 return (void*)((sljit_uw
)code
| 0x1);
472 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_has_cpu_feature(sljit_s32 feature_type
)
474 switch (feature_type
) {
476 #ifdef SLJIT_IS_FPU_AVAILABLE
477 return SLJIT_IS_FPU_AVAILABLE
;
479 /* Available by default. */
485 case SLJIT_HAS_PREFETCH
:
493 /* --------------------------------------------------------------------- */
494 /* Core code generator functions. */
495 /* --------------------------------------------------------------------- */
497 #define INVALID_IMM 0x80000000
498 static sljit_uw
get_imm(sljit_uw imm
)
500 /* Thumb immediate form. */
506 if ((imm
& 0xffff) == (imm
>> 16)) {
507 /* Some special cases. */
509 return (1 << 12) | (imm
& 0xff);
511 return (2 << 12) | ((imm
>> 8) & 0xff);
512 if ((imm
& 0xff00) == ((imm
& 0xff) << 8))
513 return (3 << 12) | (imm
& 0xff);
516 /* Assembly optimization: count leading zeroes? */
518 if (!(imm
& 0xffff0000)) {
522 if (!(imm
& 0xff000000)) {
526 if (!(imm
& 0xf0000000)) {
530 if (!(imm
& 0xc0000000)) {
534 if (!(imm
& 0x80000000)) {
538 /* Since imm >= 128, this must be true. */
539 SLJIT_ASSERT(counter
<= 31);
541 if (imm
& 0x00ffffff)
542 return INVALID_IMM
; /* Cannot be encoded. */
544 return ((imm
>> 24) & 0x7f) | COPY_BITS(counter
, 4, 26, 1) | COPY_BITS(counter
, 1, 12, 3) | COPY_BITS(counter
, 0, 7, 1);
547 static sljit_s32
load_immediate(struct sljit_compiler
*compiler
, sljit_s32 dst
, sljit_uw imm
)
551 /* MOVS cannot be used since it destroy flags. */
553 if (imm
>= 0x10000) {
555 if (tmp
!= INVALID_IMM
)
556 return push_inst32(compiler
, MOV_WI
| RD4(dst
) | tmp
);
558 if (tmp
!= INVALID_IMM
)
559 return push_inst32(compiler
, MVN_WI
| RD4(dst
) | tmp
);
562 /* set low 16 bits, set hi 16 bits to 0. */
563 FAIL_IF(push_inst32(compiler
, MOVW
| RD4(dst
)
564 | COPY_BITS(imm
, 12, 16, 4) | COPY_BITS(imm
, 11, 26, 1) | COPY_BITS(imm
, 8, 12, 3) | (imm
& 0xff)));
566 /* set hi 16 bit if needed. */
568 return push_inst32(compiler
, MOVT
| RD4(dst
)
569 | COPY_BITS(imm
, 12 + 16, 16, 4) | COPY_BITS(imm
, 11 + 16, 26, 1) | COPY_BITS(imm
, 8 + 16, 12, 3) | ((imm
& 0xff0000) >> 16));
570 return SLJIT_SUCCESS
;
573 #define ARG1_IMM 0x0010000
574 #define ARG2_IMM 0x0020000
575 /* SET_FLAGS must be 0x100000 as it is also the value of S bit (can be used for optimization). */
576 #define SET_FLAGS 0x0100000
577 #define UNUSED_RETURN 0x0200000
579 static sljit_s32
emit_op_imm(struct sljit_compiler
*compiler
, sljit_s32 flags
, sljit_s32 dst
, sljit_uw arg1
, sljit_uw arg2
)
581 /* dst must be register, TMP_REG1
582 arg1 must be register, imm
583 arg2 must be register, imm */
587 if (SLJIT_UNLIKELY((flags
& (ARG1_IMM
| ARG2_IMM
)) == (ARG1_IMM
| ARG2_IMM
))) {
588 /* Both are immediates, no temporaries are used. */
590 FAIL_IF(load_immediate(compiler
, TMP_REG1
, arg1
));
594 if (flags
& (ARG1_IMM
| ARG2_IMM
)) {
595 reg
= (flags
& ARG2_IMM
) ? arg1
: arg2
;
596 imm
= (flags
& ARG2_IMM
) ? arg2
: arg1
;
598 switch (flags
& 0xffff) {
601 /* No form with immediate operand. */
604 SLJIT_ASSERT(!(flags
& SET_FLAGS
) && (flags
& ARG2_IMM
) && arg1
== TMP_REG2
);
605 return load_immediate(compiler
, dst
, imm
);
607 if (!(flags
& SET_FLAGS
))
608 return load_immediate(compiler
, dst
, ~imm
);
609 /* Since the flags should be set, we just fallback to the register mode.
610 Although some clever things could be done here, "NOT IMM" does not worth the efforts. */
613 compiler
->status_flags_state
= SLJIT_CURRENT_FLAGS_ADD_SUB
;
614 nimm
= -(sljit_sw
)imm
;
615 if (IS_2_LO_REGS(reg
, dst
)) {
617 return push_inst16(compiler
, ADDSI3
| IMM3(imm
) | RD3(dst
) | RN3(reg
));
619 return push_inst16(compiler
, SUBSI3
| IMM3(nimm
) | RD3(dst
) | RN3(reg
));
622 return push_inst16(compiler
, ADDSI8
| IMM8(imm
) | RDN3(dst
));
624 return push_inst16(compiler
, SUBSI8
| IMM8(nimm
) | RDN3(dst
));
627 if (!(flags
& SET_FLAGS
)) {
629 return push_inst32(compiler
, ADDWI
| RD4(dst
) | RN4(reg
) | IMM12(imm
));
631 return push_inst32(compiler
, SUBWI
| RD4(dst
) | RN4(reg
) | IMM12(nimm
));
634 if (nimm
!= INVALID_IMM
)
635 return push_inst32(compiler
, ADD_WI
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(reg
) | nimm
);
636 nimm
= get_imm(-(sljit_sw
)imm
);
637 if (nimm
!= INVALID_IMM
)
638 return push_inst32(compiler
, SUB_WI
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(reg
) | nimm
);
642 if (imm
!= INVALID_IMM
)
643 return push_inst32(compiler
, ADCI
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(reg
) | imm
);
646 /* SUB operation can be replaced by ADD because of the negative carry flag. */
647 compiler
->status_flags_state
= SLJIT_CURRENT_FLAGS_ADD_SUB
;
648 if (flags
& ARG1_IMM
) {
649 if (imm
== 0 && IS_2_LO_REGS(reg
, dst
))
650 return push_inst16(compiler
, RSBSI
| RD3(dst
) | RN3(reg
));
652 if (imm
!= INVALID_IMM
)
653 return push_inst32(compiler
, RSB_WI
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(reg
) | imm
);
656 if (flags
& UNUSED_RETURN
) {
657 if (imm
<= 0xff && reg_map
[reg
] <= 7)
658 return push_inst16(compiler
, CMPI
| IMM8(imm
) | RDN3(reg
));
660 if (nimm
!= INVALID_IMM
)
661 return push_inst32(compiler
, CMPI_W
| RN4(reg
) | nimm
);
662 nimm
= get_imm(-(sljit_sw
)imm
);
663 if (nimm
!= INVALID_IMM
)
664 return push_inst32(compiler
, CMNI_W
| RN4(reg
) | nimm
);
666 nimm
= -(sljit_sw
)imm
;
667 if (IS_2_LO_REGS(reg
, dst
)) {
669 return push_inst16(compiler
, SUBSI3
| IMM3(imm
) | RD3(dst
) | RN3(reg
));
671 return push_inst16(compiler
, ADDSI3
| IMM3(nimm
) | RD3(dst
) | RN3(reg
));
674 return push_inst16(compiler
, SUBSI8
| IMM8(imm
) | RDN3(dst
));
676 return push_inst16(compiler
, ADDSI8
| IMM8(nimm
) | RDN3(dst
));
679 if (!(flags
& SET_FLAGS
)) {
681 return push_inst32(compiler
, SUBWI
| RD4(dst
) | RN4(reg
) | IMM12(imm
));
683 return push_inst32(compiler
, ADDWI
| RD4(dst
) | RN4(reg
) | IMM12(nimm
));
686 if (nimm
!= INVALID_IMM
)
687 return push_inst32(compiler
, SUB_WI
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(reg
) | nimm
);
688 nimm
= get_imm(-(sljit_sw
)imm
);
689 if (nimm
!= INVALID_IMM
)
690 return push_inst32(compiler
, ADD_WI
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(reg
) | nimm
);
693 if (flags
& ARG1_IMM
)
696 if (imm
!= INVALID_IMM
)
697 return push_inst32(compiler
, SBCI
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(reg
) | imm
);
701 if (nimm
!= INVALID_IMM
)
702 return push_inst32(compiler
, ANDI
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(reg
) | nimm
);
704 if (imm
!= INVALID_IMM
)
705 return push_inst32(compiler
, BICI
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(reg
) | imm
);
709 if (nimm
!= INVALID_IMM
)
710 return push_inst32(compiler
, ORRI
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(reg
) | nimm
);
712 if (imm
!= INVALID_IMM
)
713 return push_inst32(compiler
, ORNI
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(reg
) | imm
);
717 if (imm
!= INVALID_IMM
)
718 return push_inst32(compiler
, EORI
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(reg
) | imm
);
723 if (flags
& ARG1_IMM
)
727 if (!(flags
& SET_FLAGS
))
728 return push_inst16(compiler
, MOV
| SET_REGS44(dst
, reg
));
729 if (IS_2_LO_REGS(dst
, reg
))
730 return push_inst16(compiler
, MOVS
| RD3(dst
) | RN3(reg
));
731 return push_inst32(compiler
, MOV_W
| SET_FLAGS
| RD4(dst
) | RM4(reg
));
733 switch (flags
& 0xffff) {
735 if (IS_2_LO_REGS(dst
, reg
))
736 return push_inst16(compiler
, LSLSI
| RD3(dst
) | RN3(reg
) | (imm
<< 6));
737 return push_inst32(compiler
, LSL_WI
| (flags
& SET_FLAGS
) | RD4(dst
) | RM4(reg
) | IMM5(imm
));
739 if (IS_2_LO_REGS(dst
, reg
))
740 return push_inst16(compiler
, LSRSI
| RD3(dst
) | RN3(reg
) | (imm
<< 6));
741 return push_inst32(compiler
, LSR_WI
| (flags
& SET_FLAGS
) | RD4(dst
) | RM4(reg
) | IMM5(imm
));
742 default: /* SLJIT_ASHR */
743 if (IS_2_LO_REGS(dst
, reg
))
744 return push_inst16(compiler
, ASRSI
| RD3(dst
) | RN3(reg
) | (imm
<< 6));
745 return push_inst32(compiler
, ASR_WI
| (flags
& SET_FLAGS
) | RD4(dst
) | RM4(reg
) | IMM5(imm
));
752 if (flags
& ARG2_IMM
) {
754 arg2
= (arg1
== TMP_REG1
) ? TMP_REG2
: TMP_REG1
;
755 FAIL_IF(load_immediate(compiler
, arg2
, imm
));
759 arg1
= (arg2
== TMP_REG1
) ? TMP_REG2
: TMP_REG1
;
760 FAIL_IF(load_immediate(compiler
, arg1
, imm
));
763 SLJIT_ASSERT(arg1
!= arg2
);
766 /* Both arguments are registers. */
767 switch (flags
& 0xffff) {
772 SLJIT_ASSERT(!(flags
& SET_FLAGS
) && arg1
== TMP_REG2
);
774 return SLJIT_SUCCESS
;
775 return push_inst16(compiler
, MOV
| SET_REGS44(dst
, arg2
));
777 SLJIT_ASSERT(!(flags
& SET_FLAGS
) && arg1
== TMP_REG2
);
778 if (IS_2_LO_REGS(dst
, arg2
))
779 return push_inst16(compiler
, UXTB
| RD3(dst
) | RN3(arg2
));
780 return push_inst32(compiler
, UXTB_W
| RD4(dst
) | RM4(arg2
));
782 SLJIT_ASSERT(!(flags
& SET_FLAGS
) && arg1
== TMP_REG2
);
783 if (IS_2_LO_REGS(dst
, arg2
))
784 return push_inst16(compiler
, SXTB
| RD3(dst
) | RN3(arg2
));
785 return push_inst32(compiler
, SXTB_W
| RD4(dst
) | RM4(arg2
));
787 SLJIT_ASSERT(!(flags
& SET_FLAGS
) && arg1
== TMP_REG2
);
788 if (IS_2_LO_REGS(dst
, arg2
))
789 return push_inst16(compiler
, UXTH
| RD3(dst
) | RN3(arg2
));
790 return push_inst32(compiler
, UXTH_W
| RD4(dst
) | RM4(arg2
));
792 SLJIT_ASSERT(!(flags
& SET_FLAGS
) && arg1
== TMP_REG2
);
793 if (IS_2_LO_REGS(dst
, arg2
))
794 return push_inst16(compiler
, SXTH
| RD3(dst
) | RN3(arg2
));
795 return push_inst32(compiler
, SXTH_W
| RD4(dst
) | RM4(arg2
));
797 SLJIT_ASSERT(arg1
== TMP_REG2
);
798 if (IS_2_LO_REGS(dst
, arg2
))
799 return push_inst16(compiler
, MVNS
| RD3(dst
) | RN3(arg2
));
800 return push_inst32(compiler
, MVN_W
| (flags
& SET_FLAGS
) | RD4(dst
) | RM4(arg2
));
802 SLJIT_ASSERT(arg1
== TMP_REG2
);
803 FAIL_IF(push_inst32(compiler
, CLZ
| RN4(arg2
) | RD4(dst
) | RM4(arg2
)));
804 return SLJIT_SUCCESS
;
806 compiler
->status_flags_state
= SLJIT_CURRENT_FLAGS_ADD_SUB
;
807 if (IS_3_LO_REGS(dst
, arg1
, arg2
))
808 return push_inst16(compiler
, ADDS
| RD3(dst
) | RN3(arg1
) | RM3(arg2
));
809 if (dst
== arg1
&& !(flags
& SET_FLAGS
))
810 return push_inst16(compiler
, ADD
| SET_REGS44(dst
, arg2
));
811 return push_inst32(compiler
, ADD_W
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(arg1
) | RM4(arg2
));
813 if (dst
== arg1
&& IS_2_LO_REGS(dst
, arg2
))
814 return push_inst16(compiler
, ADCS
| RD3(dst
) | RN3(arg2
));
815 return push_inst32(compiler
, ADC_W
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(arg1
) | RM4(arg2
));
817 compiler
->status_flags_state
= SLJIT_CURRENT_FLAGS_ADD_SUB
;
818 if (flags
& UNUSED_RETURN
) {
819 if (IS_2_LO_REGS(arg1
, arg2
))
820 return push_inst16(compiler
, CMP
| RD3(arg1
) | RN3(arg2
));
821 return push_inst16(compiler
, CMP_X
| SET_REGS44(arg1
, arg2
));
823 if (IS_3_LO_REGS(dst
, arg1
, arg2
))
824 return push_inst16(compiler
, SUBS
| RD3(dst
) | RN3(arg1
) | RM3(arg2
));
825 return push_inst32(compiler
, SUB_W
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(arg1
) | RM4(arg2
));
827 if (dst
== arg1
&& IS_2_LO_REGS(dst
, arg2
))
828 return push_inst16(compiler
, SBCS
| RD3(dst
) | RN3(arg2
));
829 return push_inst32(compiler
, SBC_W
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(arg1
) | RM4(arg2
));
831 compiler
->status_flags_state
= 0;
832 if (!(flags
& SET_FLAGS
))
833 return push_inst32(compiler
, MUL
| RD4(dst
) | RN4(arg1
) | RM4(arg2
));
834 SLJIT_ASSERT(dst
!= TMP_REG2
);
835 FAIL_IF(push_inst32(compiler
, SMULL
| RT4(dst
) | RD4(TMP_REG2
) | RN4(arg1
) | RM4(arg2
)));
836 /* cmp TMP_REG2, dst asr #31. */
837 return push_inst32(compiler
, CMP_W
| RN4(TMP_REG2
) | 0x70e0 | RM4(dst
));
839 if (dst
== arg1
&& IS_2_LO_REGS(dst
, arg2
))
840 return push_inst16(compiler
, ANDS
| RD3(dst
) | RN3(arg2
));
841 if ((flags
& UNUSED_RETURN
) && IS_2_LO_REGS(arg1
, arg2
))
842 return push_inst16(compiler
, TST
| RD3(arg1
) | RN3(arg2
));
843 return push_inst32(compiler
, AND_W
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(arg1
) | RM4(arg2
));
845 if (dst
== arg1
&& IS_2_LO_REGS(dst
, arg2
))
846 return push_inst16(compiler
, ORRS
| RD3(dst
) | RN3(arg2
));
847 return push_inst32(compiler
, ORR_W
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(arg1
) | RM4(arg2
));
849 if (dst
== arg1
&& IS_2_LO_REGS(dst
, arg2
))
850 return push_inst16(compiler
, EORS
| RD3(dst
) | RN3(arg2
));
851 return push_inst32(compiler
, EOR_W
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(arg1
) | RM4(arg2
));
853 if (dst
== arg1
&& IS_2_LO_REGS(dst
, arg2
))
854 return push_inst16(compiler
, LSLS
| RD3(dst
) | RN3(arg2
));
855 return push_inst32(compiler
, LSL_W
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(arg1
) | RM4(arg2
));
857 if (dst
== arg1
&& IS_2_LO_REGS(dst
, arg2
))
858 return push_inst16(compiler
, LSRS
| RD3(dst
) | RN3(arg2
));
859 return push_inst32(compiler
, LSR_W
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(arg1
) | RM4(arg2
));
861 if (dst
== arg1
&& IS_2_LO_REGS(dst
, arg2
))
862 return push_inst16(compiler
, ASRS
| RD3(dst
) | RN3(arg2
));
863 return push_inst32(compiler
, ASR_W
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(arg1
) | RM4(arg2
));
867 return SLJIT_SUCCESS
;
873 #define WORD_SIZE 0x00
874 #define BYTE_SIZE 0x04
875 #define HALF_SIZE 0x08
878 #define IS_WORD_SIZE(flags) (!(flags & (BYTE_SIZE | HALF_SIZE)))
879 #define OFFSET_CHECK(imm, shift) (!(argw & ~(imm << shift)))
896 static const sljit_ins sljit_mem16
[12] = {
897 /* w u l */ 0x5800 /* ldr */,
898 /* w u s */ 0x5000 /* str */,
899 /* w s l */ 0x5800 /* ldr */,
900 /* w s s */ 0x5000 /* str */,
902 /* b u l */ 0x5c00 /* ldrb */,
903 /* b u s */ 0x5400 /* strb */,
904 /* b s l */ 0x5600 /* ldrsb */,
905 /* b s s */ 0x5400 /* strb */,
907 /* h u l */ 0x5a00 /* ldrh */,
908 /* h u s */ 0x5200 /* strh */,
909 /* h s l */ 0x5e00 /* ldrsh */,
910 /* h s s */ 0x5200 /* strh */,
913 static const sljit_ins sljit_mem16_imm5
[12] = {
914 /* w u l */ 0x6800 /* ldr imm5 */,
915 /* w u s */ 0x6000 /* str imm5 */,
916 /* w s l */ 0x6800 /* ldr imm5 */,
917 /* w s s */ 0x6000 /* str imm5 */,
919 /* b u l */ 0x7800 /* ldrb imm5 */,
920 /* b u s */ 0x7000 /* strb imm5 */,
921 /* b s l */ 0x0000 /* not allowed */,
922 /* b s s */ 0x7000 /* strb imm5 */,
924 /* h u l */ 0x8800 /* ldrh imm5 */,
925 /* h u s */ 0x8000 /* strh imm5 */,
926 /* h s l */ 0x0000 /* not allowed */,
927 /* h s s */ 0x8000 /* strh imm5 */,
930 #define MEM_IMM8 0xc00
931 #define MEM_IMM12 0x800000
932 static const sljit_ins sljit_mem32
[13] = {
933 /* w u l */ 0xf8500000 /* ldr.w */,
934 /* w u s */ 0xf8400000 /* str.w */,
935 /* w s l */ 0xf8500000 /* ldr.w */,
936 /* w s s */ 0xf8400000 /* str.w */,
938 /* b u l */ 0xf8100000 /* ldrb.w */,
939 /* b u s */ 0xf8000000 /* strb.w */,
940 /* b s l */ 0xf9100000 /* ldrsb.w */,
941 /* b s s */ 0xf8000000 /* strb.w */,
943 /* h u l */ 0xf8300000 /* ldrh.w */,
944 /* h u s */ 0xf8200000 /* strsh.w */,
945 /* h s l */ 0xf9300000 /* ldrsh.w */,
946 /* h s s */ 0xf8200000 /* strsh.w */,
948 /* p u l */ 0xf8100000 /* pld */,
951 /* Helper function. Dst should be reg + value, using at most 1 instruction, flags does not set. */
952 static sljit_s32
emit_set_delta(struct sljit_compiler
*compiler
, sljit_s32 dst
, sljit_s32 reg
, sljit_sw value
)
956 return push_inst32(compiler
, ADDWI
| RD4(dst
) | RN4(reg
) | IMM12(value
));
957 value
= get_imm(value
);
958 if (value
!= INVALID_IMM
)
959 return push_inst32(compiler
, ADD_WI
| RD4(dst
) | RN4(reg
) | value
);
964 return push_inst32(compiler
, SUBWI
| RD4(dst
) | RN4(reg
) | IMM12(value
));
965 value
= get_imm(value
);
966 if (value
!= INVALID_IMM
)
967 return push_inst32(compiler
, SUB_WI
| RD4(dst
) | RN4(reg
) | value
);
969 return SLJIT_ERR_UNSUPPORTED
;
972 static SLJIT_INLINE sljit_s32
emit_op_mem(struct sljit_compiler
*compiler
, sljit_s32 flags
, sljit_s32 reg
,
973 sljit_s32 arg
, sljit_sw argw
, sljit_s32 tmp_reg
)
978 SLJIT_ASSERT(arg
& SLJIT_MEM
);
979 SLJIT_ASSERT((arg
& REG_MASK
) != tmp_reg
);
982 if (SLJIT_UNLIKELY(!(arg
& REG_MASK
))) {
983 tmp
= get_imm(argw
& ~0xfff);
984 if (tmp
!= INVALID_IMM
) {
985 FAIL_IF(push_inst32(compiler
, MOV_WI
| RD4(tmp_reg
) | tmp
));
986 return push_inst32(compiler
, sljit_mem32
[flags
] | MEM_IMM12
| RT4(reg
) | RN4(tmp_reg
) | (argw
& 0xfff));
989 FAIL_IF(load_immediate(compiler
, tmp_reg
, argw
));
990 if (IS_2_LO_REGS(reg
, tmp_reg
) && sljit_mem16_imm5
[flags
])
991 return push_inst16(compiler
, sljit_mem16_imm5
[flags
] | RD3(reg
) | RN3(tmp_reg
));
992 return push_inst32(compiler
, sljit_mem32
[flags
] | MEM_IMM12
| RT4(reg
) | RN4(tmp_reg
));
995 if (SLJIT_UNLIKELY(arg
& OFFS_REG_MASK
)) {
997 other_r
= OFFS_REG(arg
);
1000 if (!argw
&& IS_3_LO_REGS(reg
, arg
, other_r
))
1001 return push_inst16(compiler
, sljit_mem16
[flags
] | RD3(reg
) | RN3(arg
) | RM3(other_r
));
1002 return push_inst32(compiler
, sljit_mem32
[flags
] | RT4(reg
) | RN4(arg
) | RM4(other_r
) | (argw
<< 4));
1006 tmp
= get_imm(argw
& ~0xfff);
1007 if (tmp
!= INVALID_IMM
) {
1008 push_inst32(compiler
, ADD_WI
| RD4(tmp_reg
) | RN4(arg
) | tmp
);
1010 argw
= argw
& 0xfff;
1013 else if (argw
< -0xff) {
1014 tmp
= get_imm(-argw
& ~0xff);
1015 if (tmp
!= INVALID_IMM
) {
1016 push_inst32(compiler
, SUB_WI
| RD4(tmp_reg
) | RN4(arg
) | tmp
);
1018 argw
= -(-argw
& 0xff);
1022 if (IS_2_LO_REGS(reg
, arg
) && sljit_mem16_imm5
[flags
]) {
1024 if (IS_WORD_SIZE(flags
)) {
1025 if (OFFSET_CHECK(0x1f, 2))
1028 else if (flags
& BYTE_SIZE
)
1030 if (OFFSET_CHECK(0x1f, 0))
1034 SLJIT_ASSERT(flags
& HALF_SIZE
);
1035 if (OFFSET_CHECK(0x1f, 1))
1040 return push_inst16(compiler
, sljit_mem16_imm5
[flags
] | RD3(reg
) | RN3(arg
) | (argw
<< (6 - tmp
)));
1042 else if (SLJIT_UNLIKELY(arg
== SLJIT_SP
) && IS_WORD_SIZE(flags
) && OFFSET_CHECK(0xff, 2) && reg_map
[reg
] <= 7) {
1043 /* SP based immediate. */
1044 return push_inst16(compiler
, STR_SP
| ((flags
& STORE
) ? 0 : 0x800) | RDN3(reg
) | (argw
>> 2));
1047 if (argw
>= 0 && argw
<= 0xfff)
1048 return push_inst32(compiler
, sljit_mem32
[flags
] | MEM_IMM12
| RT4(reg
) | RN4(arg
) | argw
);
1049 else if (argw
< 0 && argw
>= -0xff)
1050 return push_inst32(compiler
, sljit_mem32
[flags
] | MEM_IMM8
| RT4(reg
) | RN4(arg
) | -argw
);
1052 SLJIT_ASSERT(arg
!= tmp_reg
);
1054 FAIL_IF(load_immediate(compiler
, tmp_reg
, argw
));
1055 if (IS_3_LO_REGS(reg
, arg
, tmp_reg
))
1056 return push_inst16(compiler
, sljit_mem16
[flags
] | RD3(reg
) | RN3(arg
) | RM3(tmp_reg
));
1057 return push_inst32(compiler
, sljit_mem32
[flags
] | RT4(reg
) | RN4(arg
) | RM4(tmp_reg
));
1060 /* --------------------------------------------------------------------- */
1062 /* --------------------------------------------------------------------- */
1064 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_enter(struct sljit_compiler
*compiler
,
1065 sljit_s32 options
, sljit_s32 arg_types
, sljit_s32 scratches
, sljit_s32 saveds
,
1066 sljit_s32 fscratches
, sljit_s32 fsaveds
, sljit_s32 local_size
)
1068 sljit_s32 args
, size
, i
, tmp
;
1075 CHECK(check_sljit_emit_enter(compiler
, options
, arg_types
, scratches
, saveds
, fscratches
, fsaveds
, local_size
));
1076 set_emit_enter(compiler
, options
, arg_types
, scratches
, saveds
, fscratches
, fsaveds
, local_size
);
1078 tmp
= saveds
< SLJIT_NUMBER_OF_SAVED_REGISTERS
? (SLJIT_S0
+ 1 - saveds
) : SLJIT_FIRST_SAVED_REG
;
1079 for (i
= SLJIT_S0
; i
>= tmp
; i
--)
1080 push
|= 1 << reg_map
[i
];
1082 for (i
= scratches
; i
>= SLJIT_FIRST_SAVED_REG
; i
--)
1083 push
|= 1 << reg_map
[i
];
1085 FAIL_IF((push
& 0xff00)
1086 ? push_inst32(compiler
, PUSH_W
| (1 << 14) | push
)
1087 : push_inst16(compiler
, PUSH
| (1 << 8) | push
));
1089 /* Stack must be aligned to 8 bytes: (LR, R4) */
1090 size
= GET_SAVED_REGISTERS_SIZE(scratches
, saveds
, 1);
1091 local_size
= ((size
+ local_size
+ 7) & ~7) - size
;
1092 compiler
->local_size
= local_size
;
1095 if (local_size
>= 256) {
1096 if (local_size
> 4096)
1097 imm
= get_imm(4096);
1099 imm
= get_imm(local_size
& ~0xff);
1101 SLJIT_ASSERT(imm
!= INVALID_IMM
);
1102 FAIL_IF(push_inst32(compiler
, SUB_WI
| RD4(TMP_REG1
) | RN4(SLJIT_SP
) | imm
));
1105 if (local_size
> 0) {
1106 if (local_size
<= (127 << 2))
1107 FAIL_IF(push_inst16(compiler
, SUB_SP
| (local_size
>> 2)));
1109 FAIL_IF(emit_op_imm(compiler
, SLJIT_SUB
| ARG2_IMM
, SLJIT_SP
, SLJIT_SP
, local_size
));
1113 args
= get_arg_count(arg_types
);
1116 FAIL_IF(push_inst16(compiler
, MOV
| SET_REGS44(SLJIT_S0
, SLJIT_R0
)));
1118 FAIL_IF(push_inst16(compiler
, MOV
| SET_REGS44(SLJIT_S1
, SLJIT_R1
)));
1120 FAIL_IF(push_inst16(compiler
, MOV
| SET_REGS44(SLJIT_S2
, SLJIT_R2
)));
1123 if (local_size
>= 256) {
1124 if (local_size
> 4096) {
1125 imm
= get_imm(4096);
1126 SLJIT_ASSERT(imm
!= INVALID_IMM
);
1128 if (local_size
< 4 * 4096) {
1129 if (local_size
> 2 * 4096) {
1130 FAIL_IF(push_inst32(compiler
, LDRI
| 0x400 | RT4(TMP_REG2
) | RN4(TMP_REG1
)));
1131 FAIL_IF(push_inst32(compiler
, SUB_WI
| RD4(TMP_REG1
) | RN4(TMP_REG1
) | imm
));
1135 if (local_size
> 2 * 4096) {
1136 FAIL_IF(push_inst32(compiler
, LDRI
| 0x400 | RT4(TMP_REG2
) | RN4(TMP_REG1
)));
1137 FAIL_IF(push_inst32(compiler
, SUB_WI
| RD4(TMP_REG1
) | RN4(TMP_REG1
) | imm
));
1141 FAIL_IF(push_inst32(compiler
, LDRI
| 0x400 | RT4(TMP_REG2
) | RN4(TMP_REG1
)));
1144 SLJIT_ASSERT(local_size
> 0);
1147 FAIL_IF(load_immediate(compiler
, SLJIT_R3
, (local_size
>> 12) - 1));
1148 FAIL_IF(push_inst32(compiler
, LDRI
| 0x400 | RT4(TMP_REG2
) | RN4(TMP_REG1
)));
1149 FAIL_IF(push_inst32(compiler
, SUB_WI
| RD4(TMP_REG1
) | RN4(TMP_REG1
) | imm
));
1150 SLJIT_ASSERT(reg_map
[SLJIT_R3
] < 7);
1151 FAIL_IF(push_inst16(compiler
, SUBSI8
| RDN3(SLJIT_R3
) | 1));
1152 FAIL_IF(push_inst16(compiler
, BCC
| (0x1 << 8) /* not-equal */ | (-7 & 0xff)));
1154 local_size
&= 0xfff;
1156 if (local_size
!= 0)
1157 FAIL_IF(push_inst32(compiler
, LDRI
| 0x400 | RT4(TMP_REG2
) | RN4(TMP_REG1
)));
1160 if (local_size
>= 256) {
1161 imm
= get_imm(local_size
& ~0xff);
1162 SLJIT_ASSERT(imm
!= INVALID_IMM
);
1164 FAIL_IF(push_inst32(compiler
, SUB_WI
| RD4(TMP_REG1
) | RN4(TMP_REG1
) | imm
));
1169 FAIL_IF(push_inst32(compiler
, LDRI
| 0x400 | (local_size
> 0 ? 0x100 : 0) | RT4(TMP_REG2
) | RN4(TMP_REG1
) | local_size
));
1171 FAIL_IF(push_inst16(compiler
, MOV
| SET_REGS44(SLJIT_SP
, TMP_REG1
)));
1173 else if (local_size
> 0)
1174 FAIL_IF(push_inst32(compiler
, LDRI
| 0x500 | RT4(TMP_REG1
) | RN4(SLJIT_SP
) | local_size
));
1177 return SLJIT_SUCCESS
;
1180 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_set_context(struct sljit_compiler
*compiler
,
1181 sljit_s32 options
, sljit_s32 arg_types
, sljit_s32 scratches
, sljit_s32 saveds
,
1182 sljit_s32 fscratches
, sljit_s32 fsaveds
, sljit_s32 local_size
)
1187 CHECK(check_sljit_set_context(compiler
, options
, arg_types
, scratches
, saveds
, fscratches
, fsaveds
, local_size
));
1188 set_set_context(compiler
, options
, arg_types
, scratches
, saveds
, fscratches
, fsaveds
, local_size
);
1190 size
= GET_SAVED_REGISTERS_SIZE(scratches
, saveds
, 1);
1191 compiler
->local_size
= ((size
+ local_size
+ 7) & ~7) - size
;
1192 return SLJIT_SUCCESS
;
1195 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_return(struct sljit_compiler
*compiler
, sljit_s32 op
, sljit_s32 src
, sljit_sw srcw
)
1201 CHECK(check_sljit_emit_return(compiler
, op
, src
, srcw
));
1203 FAIL_IF(emit_mov_before_return(compiler
, op
, src
, srcw
));
1205 if (compiler
->local_size
> 0) {
1206 if (compiler
->local_size
<= (127 << 2))
1207 FAIL_IF(push_inst16(compiler
, ADD_SP
| (compiler
->local_size
>> 2)));
1209 FAIL_IF(emit_op_imm(compiler
, SLJIT_ADD
| ARG2_IMM
, SLJIT_SP
, SLJIT_SP
, compiler
->local_size
));
1212 tmp
= compiler
->saveds
< SLJIT_NUMBER_OF_SAVED_REGISTERS
? (SLJIT_S0
+ 1 - compiler
->saveds
) : SLJIT_FIRST_SAVED_REG
;
1213 for (i
= SLJIT_S0
; i
>= tmp
; i
--)
1214 pop
|= 1 << reg_map
[i
];
1216 for (i
= compiler
->scratches
; i
>= SLJIT_FIRST_SAVED_REG
; i
--)
1217 pop
|= 1 << reg_map
[i
];
1219 return (pop
& 0xff00)
1220 ? push_inst32(compiler
, POP_W
| (1 << 15) | pop
)
1221 : push_inst16(compiler
, POP
| (1 << 8) | pop
);
1224 /* --------------------------------------------------------------------- */
1226 /* --------------------------------------------------------------------- */
1228 #if !(defined __ARM_FEATURE_IDIV) && !(defined __ARM_ARCH_EXT_IDIV__)
1235 extern unsigned long long __rt_udiv(unsigned int denominator
, unsigned int numerator
);
1236 extern long long __rt_sdiv(int denominator
, int numerator
);
1237 #elif defined(__GNUC__)
1238 extern unsigned int __aeabi_uidivmod(unsigned int numerator
, int unsigned denominator
);
1239 extern int __aeabi_idivmod(int numerator
, int denominator
);
1241 #error "Software divmod functions are needed"
1248 #endif /* !__ARM_FEATURE_IDIV && !__ARM_ARCH_EXT_IDIV__ */
1250 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_op0(struct sljit_compiler
*compiler
, sljit_s32 op
)
1252 #if !(defined __ARM_FEATURE_IDIV) && !(defined __ARM_ARCH_EXT_IDIV__)
1253 sljit_sw saved_reg_list
[3];
1254 sljit_sw saved_reg_count
;
1258 CHECK(check_sljit_emit_op0(compiler
, op
));
1260 op
= GET_OPCODE(op
);
1262 case SLJIT_BREAKPOINT
:
1263 return push_inst16(compiler
, BKPT
);
1265 return push_inst16(compiler
, NOP
);
1268 return push_inst32(compiler
, (op
== SLJIT_LMUL_UW
? UMULL
: SMULL
)
1269 | (reg_map
[SLJIT_R1
] << 8)
1270 | (reg_map
[SLJIT_R0
] << 12)
1271 | (reg_map
[SLJIT_R0
] << 16)
1272 | reg_map
[SLJIT_R1
]);
1273 #if (defined __ARM_FEATURE_IDIV) || (defined __ARM_ARCH_EXT_IDIV__)
1274 case SLJIT_DIVMOD_UW
:
1275 case SLJIT_DIVMOD_SW
:
1276 FAIL_IF(push_inst16(compiler
, MOV
| SET_REGS44(TMP_REG1
, SLJIT_R0
)));
1277 FAIL_IF(push_inst32(compiler
, (op
== SLJIT_DIVMOD_UW
? UDIV
: SDIV
) | RD4(SLJIT_R0
) | RN4(SLJIT_R0
) | RM4(SLJIT_R1
)));
1278 FAIL_IF(push_inst32(compiler
, MUL
| RD4(SLJIT_R1
) | RN4(SLJIT_R0
) | RM4(SLJIT_R1
)));
1279 return push_inst32(compiler
, SUB_W
| RD4(SLJIT_R1
) | RN4(TMP_REG1
) | RM4(SLJIT_R1
));
1282 return push_inst32(compiler
, (op
== SLJIT_DIV_UW
? UDIV
: SDIV
) | RD4(SLJIT_R0
) | RN4(SLJIT_R0
) | RM4(SLJIT_R1
));
1283 #else /* !__ARM_FEATURE_IDIV && !__ARM_ARCH_EXT_IDIV__ */
1284 case SLJIT_DIVMOD_UW
:
1285 case SLJIT_DIVMOD_SW
:
1288 SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW
& 0x2) == 0 && SLJIT_DIV_UW
- 0x2 == SLJIT_DIVMOD_UW
, bad_div_opcode_assignments
);
1289 SLJIT_ASSERT(reg_map
[2] == 1 && reg_map
[3] == 2 && reg_map
[4] == 3);
1291 saved_reg_count
= 0;
1292 if (compiler
->scratches
>= 4)
1293 saved_reg_list
[saved_reg_count
++] = 3;
1294 if (compiler
->scratches
>= 3)
1295 saved_reg_list
[saved_reg_count
++] = 2;
1296 if (op
>= SLJIT_DIV_UW
)
1297 saved_reg_list
[saved_reg_count
++] = 1;
1299 if (saved_reg_count
> 0) {
1300 FAIL_IF(push_inst32(compiler
, 0xf84d0d00 | (saved_reg_count
>= 3 ? 16 : 8)
1301 | (saved_reg_list
[0] << 12) /* str rX, [sp, #-8/-16]! */));
1302 if (saved_reg_count
>= 2) {
1303 SLJIT_ASSERT(saved_reg_list
[1] < 8);
1304 FAIL_IF(push_inst16(compiler
, 0x9001 | (saved_reg_list
[1] << 8) /* str rX, [sp, #4] */));
1306 if (saved_reg_count
>= 3) {
1307 SLJIT_ASSERT(saved_reg_list
[2] < 8);
1308 FAIL_IF(push_inst16(compiler
, 0x9002 | (saved_reg_list
[2] << 8) /* str rX, [sp, #8] */));
1313 FAIL_IF(push_inst16(compiler
, MOV
| SET_REGS44(TMP_REG1
, SLJIT_R0
)));
1314 FAIL_IF(push_inst16(compiler
, MOV
| SET_REGS44(SLJIT_R0
, SLJIT_R1
)));
1315 FAIL_IF(push_inst16(compiler
, MOV
| SET_REGS44(SLJIT_R1
, TMP_REG1
)));
1316 FAIL_IF(sljit_emit_ijump(compiler
, SLJIT_FAST_CALL
, SLJIT_IMM
,
1317 ((op
| 0x2) == SLJIT_DIV_UW
? SLJIT_FUNC_OFFSET(__rt_udiv
) : SLJIT_FUNC_OFFSET(__rt_sdiv
))));
1318 #elif defined(__GNUC__)
1319 FAIL_IF(sljit_emit_ijump(compiler
, SLJIT_FAST_CALL
, SLJIT_IMM
,
1320 ((op
| 0x2) == SLJIT_DIV_UW
? SLJIT_FUNC_OFFSET(__aeabi_uidivmod
) : SLJIT_FUNC_OFFSET(__aeabi_idivmod
))));
1322 #error "Software divmod functions are needed"
1325 if (saved_reg_count
> 0) {
1326 if (saved_reg_count
>= 3) {
1327 SLJIT_ASSERT(saved_reg_list
[2] < 8);
1328 FAIL_IF(push_inst16(compiler
, 0x9802 | (saved_reg_list
[2] << 8) /* ldr rX, [sp, #8] */));
1330 if (saved_reg_count
>= 2) {
1331 SLJIT_ASSERT(saved_reg_list
[1] < 8);
1332 FAIL_IF(push_inst16(compiler
, 0x9801 | (saved_reg_list
[1] << 8) /* ldr rX, [sp, #4] */));
1334 return push_inst32(compiler
, 0xf85d0b00 | (saved_reg_count
>= 3 ? 16 : 8)
1335 | (saved_reg_list
[0] << 12) /* ldr rX, [sp], #8/16 */);
1337 return SLJIT_SUCCESS
;
1338 #endif /* __ARM_FEATURE_IDIV || __ARM_ARCH_EXT_IDIV__ */
1340 case SLJIT_SKIP_FRAMES_BEFORE_RETURN
:
1341 return SLJIT_SUCCESS
;
1344 return SLJIT_SUCCESS
;
1347 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_op1(struct sljit_compiler
*compiler
, sljit_s32 op
,
1348 sljit_s32 dst
, sljit_sw dstw
,
1349 sljit_s32 src
, sljit_sw srcw
)
1351 sljit_s32 dst_r
, flags
;
1352 sljit_s32 op_flags
= GET_ALL_FLAGS(op
);
1355 CHECK(check_sljit_emit_op1(compiler
, op
, dst
, dstw
, src
, srcw
));
1356 ADJUST_LOCAL_OFFSET(dst
, dstw
);
1357 ADJUST_LOCAL_OFFSET(src
, srcw
);
1359 dst_r
= SLOW_IS_REG(dst
) ? dst
: TMP_REG1
;
1361 op
= GET_OPCODE(op
);
1362 if (op
>= SLJIT_MOV
&& op
<= SLJIT_MOV_P
) {
1372 if (src
& SLJIT_IMM
)
1373 srcw
= (sljit_u8
)srcw
;
1376 flags
= BYTE_SIZE
| SIGNED
;
1377 if (src
& SLJIT_IMM
)
1378 srcw
= (sljit_s8
)srcw
;
1382 if (src
& SLJIT_IMM
)
1383 srcw
= (sljit_u16
)srcw
;
1386 flags
= HALF_SIZE
| SIGNED
;
1387 if (src
& SLJIT_IMM
)
1388 srcw
= (sljit_s16
)srcw
;
1391 SLJIT_UNREACHABLE();
1396 if (src
& SLJIT_IMM
)
1397 FAIL_IF(emit_op_imm(compiler
, SLJIT_MOV
| ARG2_IMM
, dst_r
, TMP_REG2
, srcw
));
1398 else if (src
& SLJIT_MEM
) {
1399 FAIL_IF(emit_op_mem(compiler
, flags
, dst_r
, src
, srcw
, TMP_REG1
));
1401 if (dst_r
!= TMP_REG1
)
1402 return emit_op_imm(compiler
, op
, dst_r
, TMP_REG2
, src
);
1406 if (!(dst
& SLJIT_MEM
))
1407 return SLJIT_SUCCESS
;
1409 return emit_op_mem(compiler
, flags
| STORE
, dst_r
, dst
, dstw
, TMP_REG2
);
1412 if (op
== SLJIT_NEG
) {
1413 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
1414 || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
1415 compiler
->skip_checks
= 1;
1417 return sljit_emit_op2(compiler
, SLJIT_SUB
| op_flags
, dst
, dstw
, SLJIT_IMM
, 0, src
, srcw
);
1420 flags
= HAS_FLAGS(op_flags
) ? SET_FLAGS
: 0;
1422 if (src
& SLJIT_MEM
) {
1423 FAIL_IF(emit_op_mem(compiler
, WORD_SIZE
, TMP_REG1
, src
, srcw
, TMP_REG1
));
1427 emit_op_imm(compiler
, flags
| op
, dst_r
, TMP_REG2
, src
);
1429 if (SLJIT_UNLIKELY(dst
& SLJIT_MEM
))
1430 return emit_op_mem(compiler
, flags
| STORE
, dst_r
, dst
, dstw
, TMP_REG2
);
1431 return SLJIT_SUCCESS
;
1434 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_op2(struct sljit_compiler
*compiler
, sljit_s32 op
,
1435 sljit_s32 dst
, sljit_sw dstw
,
1436 sljit_s32 src1
, sljit_sw src1w
,
1437 sljit_s32 src2
, sljit_sw src2w
)
1439 sljit_s32 dst_reg
, flags
, src2_reg
;
1442 CHECK(check_sljit_emit_op2(compiler
, op
, dst
, dstw
, src1
, src1w
, src2
, src2w
));
1443 ADJUST_LOCAL_OFFSET(dst
, dstw
);
1444 ADJUST_LOCAL_OFFSET(src1
, src1w
);
1445 ADJUST_LOCAL_OFFSET(src2
, src2w
);
1447 if (dst
== SLJIT_UNUSED
&& !HAS_FLAGS(op
))
1448 return SLJIT_SUCCESS
;
1450 dst_reg
= SLOW_IS_REG(dst
) ? dst
: TMP_REG1
;
1451 flags
= HAS_FLAGS(op
) ? SET_FLAGS
: 0;
1453 if (src1
& SLJIT_IMM
)
1455 else if (src1
& SLJIT_MEM
) {
1456 emit_op_mem(compiler
, WORD_SIZE
, TMP_REG1
, src1
, src1w
, TMP_REG1
);
1462 if (src2
& SLJIT_IMM
)
1464 else if (src2
& SLJIT_MEM
) {
1465 src2_reg
= (!(flags
& ARG1_IMM
) && (src1w
== TMP_REG1
)) ? TMP_REG2
: TMP_REG1
;
1466 emit_op_mem(compiler
, WORD_SIZE
, src2_reg
, src2
, src2w
, src2_reg
);
1472 if (dst
== SLJIT_UNUSED
)
1473 flags
|= UNUSED_RETURN
;
1475 emit_op_imm(compiler
, flags
| GET_OPCODE(op
), dst_reg
, src1w
, src2w
);
1477 if (!(dst
& SLJIT_MEM
))
1478 return SLJIT_SUCCESS
;
1479 return emit_op_mem(compiler
, WORD_SIZE
| STORE
, dst_reg
, dst
, dstw
, TMP_REG2
);
1482 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_op_src(struct sljit_compiler
*compiler
, sljit_s32 op
,
1483 sljit_s32 src
, sljit_sw srcw
)
1486 CHECK(check_sljit_emit_op_src(compiler
, op
, src
, srcw
));
1487 ADJUST_LOCAL_OFFSET(src
, srcw
);
1490 case SLJIT_FAST_RETURN
:
1491 SLJIT_ASSERT(reg_map
[TMP_REG2
] == 14);
1493 if (FAST_IS_REG(src
))
1494 FAIL_IF(push_inst16(compiler
, MOV
| SET_REGS44(TMP_REG2
, src
)));
1496 FAIL_IF(emit_op_mem(compiler
, WORD_SIZE
, TMP_REG2
, src
, srcw
, TMP_REG2
));
1498 return push_inst16(compiler
, BX
| RN3(TMP_REG2
));
1499 case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN
:
1500 return SLJIT_SUCCESS
;
1501 case SLJIT_PREFETCH_L1
:
1502 case SLJIT_PREFETCH_L2
:
1503 case SLJIT_PREFETCH_L3
:
1504 case SLJIT_PREFETCH_ONCE
:
1505 return emit_op_mem(compiler
, PRELOAD
, TMP_PC
, src
, srcw
, TMP_REG1
);
1508 return SLJIT_SUCCESS
;
1511 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_get_register_index(sljit_s32 reg
)
1513 CHECK_REG_INDEX(check_sljit_get_register_index(reg
));
1514 return reg_map
[reg
];
1517 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_get_float_register_index(sljit_s32 reg
)
1519 CHECK_REG_INDEX(check_sljit_get_float_register_index(reg
));
1520 return (freg_map
[reg
] << 1);
1523 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_op_custom(struct sljit_compiler
*compiler
,
1524 void *instruction
, sljit_s32 size
)
1527 CHECK(check_sljit_emit_op_custom(compiler
, instruction
, size
));
1530 return push_inst16(compiler
, *(sljit_u16
*)instruction
);
1531 return push_inst32(compiler
, *(sljit_ins
*)instruction
);
1534 /* --------------------------------------------------------------------- */
1535 /* Floating point operators */
1536 /* --------------------------------------------------------------------- */
1538 #define FPU_LOAD (1 << 20)
1540 static sljit_s32
emit_fop_mem(struct sljit_compiler
*compiler
, sljit_s32 flags
, sljit_s32 reg
, sljit_s32 arg
, sljit_sw argw
)
1543 sljit_sw inst
= VSTR_F32
| (flags
& (SLJIT_F32_OP
| FPU_LOAD
));
1545 SLJIT_ASSERT(arg
& SLJIT_MEM
);
1547 /* Fast loads and stores. */
1548 if (SLJIT_UNLIKELY(arg
& OFFS_REG_MASK
)) {
1549 FAIL_IF(push_inst32(compiler
, ADD_W
| RD4(TMP_REG1
) | RN4(arg
& REG_MASK
) | RM4(OFFS_REG(arg
)) | ((argw
& 0x3) << 6)));
1550 arg
= SLJIT_MEM
| TMP_REG1
;
1554 if ((arg
& REG_MASK
) && (argw
& 0x3) == 0) {
1555 if (!(argw
& ~0x3fc))
1556 return push_inst32(compiler
, inst
| 0x800000 | RN4(arg
& REG_MASK
) | DD4(reg
) | (argw
>> 2));
1557 if (!(-argw
& ~0x3fc))
1558 return push_inst32(compiler
, inst
| RN4(arg
& REG_MASK
) | DD4(reg
) | (-argw
>> 2));
1561 if (arg
& REG_MASK
) {
1562 if (emit_set_delta(compiler
, TMP_REG1
, arg
& REG_MASK
, argw
) != SLJIT_ERR_UNSUPPORTED
) {
1563 FAIL_IF(compiler
->error
);
1564 return push_inst32(compiler
, inst
| 0x800000 | RN4(TMP_REG1
) | DD4(reg
));
1566 imm
= get_imm(argw
& ~0x3fc);
1567 if (imm
!= INVALID_IMM
) {
1568 FAIL_IF(push_inst32(compiler
, ADD_WI
| RD4(TMP_REG1
) | RN4(arg
& REG_MASK
) | imm
));
1569 return push_inst32(compiler
, inst
| 0x800000 | RN4(TMP_REG1
) | DD4(reg
) | ((argw
& 0x3fc) >> 2));
1571 imm
= get_imm(-argw
& ~0x3fc);
1572 if (imm
!= INVALID_IMM
) {
1574 FAIL_IF(push_inst32(compiler
, SUB_WI
| RD4(TMP_REG1
) | RN4(arg
& REG_MASK
) | imm
));
1575 return push_inst32(compiler
, inst
| RN4(TMP_REG1
) | DD4(reg
) | ((argw
& 0x3fc) >> 2));
1579 FAIL_IF(load_immediate(compiler
, TMP_REG1
, argw
));
1581 FAIL_IF(push_inst16(compiler
, ADD
| SET_REGS44(TMP_REG1
, (arg
& REG_MASK
))));
1582 return push_inst32(compiler
, inst
| 0x800000 | RN4(TMP_REG1
) | DD4(reg
));
1585 static SLJIT_INLINE sljit_s32
sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler
*compiler
, sljit_s32 op
,
1586 sljit_s32 dst
, sljit_sw dstw
,
1587 sljit_s32 src
, sljit_sw srcw
)
1591 if (src
& SLJIT_MEM
) {
1592 FAIL_IF(emit_fop_mem(compiler
, (op
& SLJIT_F32_OP
) | FPU_LOAD
, TMP_FREG1
, src
, srcw
));
1596 FAIL_IF(push_inst32(compiler
, VCVT_S32_F32
| (op
& SLJIT_F32_OP
) | DD4(TMP_FREG1
) | DM4(src
)));
1598 if (FAST_IS_REG(dst
))
1599 return push_inst32(compiler
, VMOV
| (1 << 20) | RT4(dst
) | DN4(TMP_FREG1
));
1601 /* Store the integer value from a VFP register. */
1602 return emit_fop_mem(compiler
, 0, TMP_FREG1
, dst
, dstw
);
1605 static SLJIT_INLINE sljit_s32
sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler
*compiler
, sljit_s32 op
,
1606 sljit_s32 dst
, sljit_sw dstw
,
1607 sljit_s32 src
, sljit_sw srcw
)
1609 sljit_s32 dst_r
= FAST_IS_REG(dst
) ? dst
: TMP_FREG1
;
1613 if (FAST_IS_REG(src
))
1614 FAIL_IF(push_inst32(compiler
, VMOV
| RT4(src
) | DN4(TMP_FREG1
)));
1615 else if (src
& SLJIT_MEM
) {
1616 /* Load the integer value into a VFP register. */
1617 FAIL_IF(emit_fop_mem(compiler
, FPU_LOAD
, TMP_FREG1
, src
, srcw
));
1620 FAIL_IF(load_immediate(compiler
, TMP_REG1
, srcw
));
1621 FAIL_IF(push_inst32(compiler
, VMOV
| RT4(TMP_REG1
) | DN4(TMP_FREG1
)));
1624 FAIL_IF(push_inst32(compiler
, VCVT_F32_S32
| (op
& SLJIT_F32_OP
) | DD4(dst_r
) | DM4(TMP_FREG1
)));
1626 if (dst
& SLJIT_MEM
)
1627 return emit_fop_mem(compiler
, (op
& SLJIT_F32_OP
), TMP_FREG1
, dst
, dstw
);
1628 return SLJIT_SUCCESS
;
1631 static SLJIT_INLINE sljit_s32
sljit_emit_fop1_cmp(struct sljit_compiler
*compiler
, sljit_s32 op
,
1632 sljit_s32 src1
, sljit_sw src1w
,
1633 sljit_s32 src2
, sljit_sw src2w
)
1637 if (src1
& SLJIT_MEM
) {
1638 emit_fop_mem(compiler
, (op
& SLJIT_F32_OP
) | FPU_LOAD
, TMP_FREG1
, src1
, src1w
);
1642 if (src2
& SLJIT_MEM
) {
1643 emit_fop_mem(compiler
, (op
& SLJIT_F32_OP
) | FPU_LOAD
, TMP_FREG2
, src2
, src2w
);
1647 FAIL_IF(push_inst32(compiler
, VCMP_F32
| (op
& SLJIT_F32_OP
) | DD4(src1
) | DM4(src2
)));
1648 return push_inst32(compiler
, VMRS
);
1651 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_fop1(struct sljit_compiler
*compiler
, sljit_s32 op
,
1652 sljit_s32 dst
, sljit_sw dstw
,
1653 sljit_s32 src
, sljit_sw srcw
)
1659 SLJIT_COMPILE_ASSERT((SLJIT_F32_OP
== 0x100), float_transfer_bit_error
);
1660 SELECT_FOP1_OPERATION_WITH_CHECKS(compiler
, op
, dst
, dstw
, src
, srcw
);
1662 dst_r
= FAST_IS_REG(dst
) ? dst
: TMP_FREG1
;
1664 if (GET_OPCODE(op
) != SLJIT_CONV_F64_FROM_F32
)
1667 if (src
& SLJIT_MEM
) {
1668 emit_fop_mem(compiler
, (op
& SLJIT_F32_OP
) | FPU_LOAD
, dst_r
, src
, srcw
);
1672 switch (GET_OPCODE(op
)) {
1675 if (dst_r
!= TMP_FREG1
)
1676 FAIL_IF(push_inst32(compiler
, VMOV_F32
| (op
& SLJIT_F32_OP
) | DD4(dst_r
) | DM4(src
)));
1682 FAIL_IF(push_inst32(compiler
, VNEG_F32
| (op
& SLJIT_F32_OP
) | DD4(dst_r
) | DM4(src
)));
1685 FAIL_IF(push_inst32(compiler
, VABS_F32
| (op
& SLJIT_F32_OP
) | DD4(dst_r
) | DM4(src
)));
1687 case SLJIT_CONV_F64_FROM_F32
:
1688 FAIL_IF(push_inst32(compiler
, VCVT_F64_F32
| (op
& SLJIT_F32_OP
) | DD4(dst_r
) | DM4(src
)));
1693 if (dst
& SLJIT_MEM
)
1694 return emit_fop_mem(compiler
, (op
& SLJIT_F32_OP
), dst_r
, dst
, dstw
);
1695 return SLJIT_SUCCESS
;
1698 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_fop2(struct sljit_compiler
*compiler
, sljit_s32 op
,
1699 sljit_s32 dst
, sljit_sw dstw
,
1700 sljit_s32 src1
, sljit_sw src1w
,
1701 sljit_s32 src2
, sljit_sw src2w
)
1706 CHECK(check_sljit_emit_fop2(compiler
, op
, dst
, dstw
, src1
, src1w
, src2
, src2w
));
1707 ADJUST_LOCAL_OFFSET(dst
, dstw
);
1708 ADJUST_LOCAL_OFFSET(src1
, src1w
);
1709 ADJUST_LOCAL_OFFSET(src2
, src2w
);
1713 dst_r
= FAST_IS_REG(dst
) ? dst
: TMP_FREG1
;
1714 if (src1
& SLJIT_MEM
) {
1715 emit_fop_mem(compiler
, (op
& SLJIT_F32_OP
) | FPU_LOAD
, TMP_FREG1
, src1
, src1w
);
1718 if (src2
& SLJIT_MEM
) {
1719 emit_fop_mem(compiler
, (op
& SLJIT_F32_OP
) | FPU_LOAD
, TMP_FREG2
, src2
, src2w
);
1723 switch (GET_OPCODE(op
)) {
1725 FAIL_IF(push_inst32(compiler
, VADD_F32
| (op
& SLJIT_F32_OP
) | DD4(dst_r
) | DN4(src1
) | DM4(src2
)));
1728 FAIL_IF(push_inst32(compiler
, VSUB_F32
| (op
& SLJIT_F32_OP
) | DD4(dst_r
) | DN4(src1
) | DM4(src2
)));
1731 FAIL_IF(push_inst32(compiler
, VMUL_F32
| (op
& SLJIT_F32_OP
) | DD4(dst_r
) | DN4(src1
) | DM4(src2
)));
1734 FAIL_IF(push_inst32(compiler
, VDIV_F32
| (op
& SLJIT_F32_OP
) | DD4(dst_r
) | DN4(src1
) | DM4(src2
)));
1738 if (!(dst
& SLJIT_MEM
))
1739 return SLJIT_SUCCESS
;
1740 return emit_fop_mem(compiler
, (op
& SLJIT_F32_OP
), TMP_FREG1
, dst
, dstw
);
1745 /* --------------------------------------------------------------------- */
1746 /* Other instructions */
1747 /* --------------------------------------------------------------------- */
1749 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_fast_enter(struct sljit_compiler
*compiler
, sljit_s32 dst
, sljit_sw dstw
)
1752 CHECK(check_sljit_emit_fast_enter(compiler
, dst
, dstw
));
1753 ADJUST_LOCAL_OFFSET(dst
, dstw
);
1755 SLJIT_ASSERT(reg_map
[TMP_REG2
] == 14);
1757 if (FAST_IS_REG(dst
))
1758 return push_inst16(compiler
, MOV
| SET_REGS44(dst
, TMP_REG2
));
1761 return emit_op_mem(compiler
, WORD_SIZE
| STORE
, TMP_REG2
, dst
, dstw
, TMP_REG1
);
1764 /* --------------------------------------------------------------------- */
1765 /* Conditional instructions */
1766 /* --------------------------------------------------------------------- */
1768 static sljit_uw
get_cc(struct sljit_compiler
*compiler
, sljit_s32 type
)
1772 case SLJIT_EQUAL_F64
:
1775 case SLJIT_NOT_EQUAL
:
1776 case SLJIT_NOT_EQUAL_F64
:
1780 case SLJIT_LESS_F64
:
1783 case SLJIT_GREATER_EQUAL
:
1784 case SLJIT_GREATER_EQUAL_F64
:
1788 case SLJIT_GREATER_F64
:
1791 case SLJIT_LESS_EQUAL
:
1792 case SLJIT_LESS_EQUAL_F64
:
1795 case SLJIT_SIG_LESS
:
1798 case SLJIT_SIG_GREATER_EQUAL
:
1801 case SLJIT_SIG_GREATER
:
1804 case SLJIT_SIG_LESS_EQUAL
:
1807 case SLJIT_OVERFLOW
:
1808 if (!(compiler
->status_flags_state
& SLJIT_CURRENT_FLAGS_ADD_SUB
))
1811 case SLJIT_UNORDERED_F64
:
1814 case SLJIT_NOT_OVERFLOW
:
1815 if (!(compiler
->status_flags_state
& SLJIT_CURRENT_FLAGS_ADD_SUB
))
1818 case SLJIT_ORDERED_F64
:
1821 default: /* SLJIT_JUMP */
1822 SLJIT_UNREACHABLE();
1827 SLJIT_API_FUNC_ATTRIBUTE
struct sljit_label
* sljit_emit_label(struct sljit_compiler
*compiler
)
1829 struct sljit_label
*label
;
1832 CHECK_PTR(check_sljit_emit_label(compiler
));
1834 if (compiler
->last_label
&& compiler
->last_label
->size
== compiler
->size
)
1835 return compiler
->last_label
;
1837 label
= (struct sljit_label
*)ensure_abuf(compiler
, sizeof(struct sljit_label
));
1838 PTR_FAIL_IF(!label
);
1839 set_label(label
, compiler
);
1843 SLJIT_API_FUNC_ATTRIBUTE
struct sljit_jump
* sljit_emit_jump(struct sljit_compiler
*compiler
, sljit_s32 type
)
1845 struct sljit_jump
*jump
;
1849 CHECK_PTR(check_sljit_emit_jump(compiler
, type
));
1851 jump
= (struct sljit_jump
*)ensure_abuf(compiler
, sizeof(struct sljit_jump
));
1853 set_jump(jump
, compiler
, type
& SLJIT_REWRITABLE_JUMP
);
1856 PTR_FAIL_IF(emit_imm32_const(compiler
, TMP_REG1
, 0));
1857 if (type
< SLJIT_JUMP
) {
1858 jump
->flags
|= IS_COND
;
1859 cc
= get_cc(compiler
, type
);
1860 jump
->flags
|= cc
<< 8;
1861 PTR_FAIL_IF(push_inst16(compiler
, IT
| (cc
<< 4) | 0x8));
1864 jump
->addr
= compiler
->size
;
1865 if (type
<= SLJIT_JUMP
)
1866 PTR_FAIL_IF(push_inst16(compiler
, BX
| RN3(TMP_REG1
)));
1868 jump
->flags
|= IS_BL
;
1869 PTR_FAIL_IF(push_inst16(compiler
, BLX
| RN3(TMP_REG1
)));
1877 static sljit_s32
softfloat_call_with_args(struct sljit_compiler
*compiler
, sljit_s32 arg_types
, sljit_s32
*src
)
1879 sljit_s32 stack_offset
= 0;
1880 sljit_s32 arg_count
= 0;
1881 sljit_s32 word_arg_offset
= 0;
1882 sljit_s32 float_arg_count
= 0;
1883 sljit_s32 types
= 0;
1884 sljit_s32 src_offset
= 4 * sizeof(sljit_sw
);
1885 sljit_u8 offsets
[4];
1887 if (src
&& FAST_IS_REG(*src
))
1888 src_offset
= reg_map
[*src
] * sizeof(sljit_sw
);
1890 arg_types
>>= SLJIT_DEF_SHIFT
;
1893 types
= (types
<< SLJIT_DEF_SHIFT
) | (arg_types
& SLJIT_DEF_MASK
);
1895 switch (arg_types
& SLJIT_DEF_MASK
) {
1896 case SLJIT_ARG_TYPE_F32
:
1897 offsets
[arg_count
] = (sljit_u8
)stack_offset
;
1898 stack_offset
+= sizeof(sljit_f32
);
1902 case SLJIT_ARG_TYPE_F64
:
1903 if (stack_offset
& 0x7)
1904 stack_offset
+= sizeof(sljit_sw
);
1905 offsets
[arg_count
] = (sljit_u8
)stack_offset
;
1906 stack_offset
+= sizeof(sljit_f64
);
1911 offsets
[arg_count
] = (sljit_u8
)stack_offset
;
1912 stack_offset
+= sizeof(sljit_sw
);
1914 word_arg_offset
+= sizeof(sljit_sw
);
1918 arg_types
>>= SLJIT_DEF_SHIFT
;
1921 if (stack_offset
> 16)
1922 FAIL_IF(push_inst16(compiler
, SUB_SP
| (((stack_offset
- 16) + 0x7) & ~0x7) >> 2));
1924 SLJIT_ASSERT(reg_map
[TMP_REG1
] == 12);
1926 /* Process arguments in reversed direction. */
1928 switch (types
& SLJIT_DEF_MASK
) {
1929 case SLJIT_ARG_TYPE_F32
:
1932 stack_offset
= offsets
[arg_count
];
1934 if (stack_offset
< 16) {
1935 if (src_offset
== stack_offset
) {
1936 FAIL_IF(push_inst16(compiler
, MOV
| (src_offset
<< 1) | 4 | (1 << 7)));
1939 FAIL_IF(push_inst32(compiler
, VMOV
| 0x100000 | (float_arg_count
<< 16) | (stack_offset
<< 10)));
1941 FAIL_IF(push_inst32(compiler
, VSTR_F32
| 0x800000 | RN4(SLJIT_SP
) | (float_arg_count
<< 12) | ((stack_offset
- 16) >> 2)));
1943 case SLJIT_ARG_TYPE_F64
:
1946 stack_offset
= offsets
[arg_count
];
1948 SLJIT_ASSERT((stack_offset
& 0x7) == 0);
1950 if (stack_offset
< 16) {
1951 if (src_offset
== stack_offset
|| src_offset
== stack_offset
+ sizeof(sljit_sw
)) {
1952 FAIL_IF(push_inst16(compiler
, MOV
| (src_offset
<< 1) | 4 | (1 << 7)));
1955 FAIL_IF(push_inst32(compiler
, VMOV2
| 0x100000 | (stack_offset
<< 10) | ((stack_offset
+ sizeof(sljit_sw
)) << 14) | float_arg_count
));
1957 FAIL_IF(push_inst32(compiler
, VSTR_F32
| 0x800100 | RN4(SLJIT_SP
) | (float_arg_count
<< 12) | ((stack_offset
- 16) >> 2)));
1961 word_arg_offset
-= sizeof(sljit_sw
);
1962 stack_offset
= offsets
[arg_count
];
1964 SLJIT_ASSERT(stack_offset
>= word_arg_offset
);
1966 if (stack_offset
!= word_arg_offset
) {
1967 if (stack_offset
< 16) {
1968 if (src_offset
== stack_offset
) {
1969 FAIL_IF(push_inst16(compiler
, MOV
| (src_offset
<< 1) | 4 | (1 << 7)));
1972 else if (src_offset
== word_arg_offset
) {
1973 *src
= 1 + (stack_offset
>> 2);
1974 src_offset
= stack_offset
;
1976 FAIL_IF(push_inst16(compiler
, MOV
| (stack_offset
>> 2) | (word_arg_offset
<< 1)));
1978 FAIL_IF(push_inst16(compiler
, STR_SP
| (word_arg_offset
<< 6) | ((stack_offset
- 16) >> 2)));
1983 types
>>= SLJIT_DEF_SHIFT
;
1986 return SLJIT_SUCCESS
;
1989 static sljit_s32
softfloat_post_call_with_args(struct sljit_compiler
*compiler
, sljit_s32 arg_types
)
1991 sljit_s32 stack_size
= 0;
1993 if ((arg_types
& SLJIT_DEF_MASK
) == SLJIT_ARG_TYPE_F32
)
1994 FAIL_IF(push_inst32(compiler
, VMOV
| (0 << 16) | (0 << 12)));
1995 if ((arg_types
& SLJIT_DEF_MASK
) == SLJIT_ARG_TYPE_F64
)
1996 FAIL_IF(push_inst32(compiler
, VMOV2
| (1 << 16) | (0 << 12) | 0));
1998 arg_types
>>= SLJIT_DEF_SHIFT
;
2001 switch (arg_types
& SLJIT_DEF_MASK
) {
2002 case SLJIT_ARG_TYPE_F32
:
2003 stack_size
+= sizeof(sljit_f32
);
2005 case SLJIT_ARG_TYPE_F64
:
2006 if (stack_size
& 0x7)
2007 stack_size
+= sizeof(sljit_sw
);
2008 stack_size
+= sizeof(sljit_f64
);
2011 stack_size
+= sizeof(sljit_sw
);
2015 arg_types
>>= SLJIT_DEF_SHIFT
;
2018 if (stack_size
<= 16)
2019 return SLJIT_SUCCESS
;
2021 return push_inst16(compiler
, ADD_SP
| ((((stack_size
- 16) + 0x7) & ~0x7) >> 2));
2026 static sljit_s32
hardfloat_call_with_args(struct sljit_compiler
*compiler
, sljit_s32 arg_types
)
2028 sljit_u32 remap
= 0;
2029 sljit_u32 offset
= 0;
2030 sljit_u32 new_offset
, mask
;
2032 /* Remove return value. */
2033 arg_types
>>= SLJIT_DEF_SHIFT
;
2036 if ((arg_types
& SLJIT_DEF_MASK
) == SLJIT_ARG_TYPE_F32
) {
2040 while (remap
& mask
) {
2046 if (offset
!= new_offset
)
2047 FAIL_IF(push_inst32(compiler
, VMOV_F32
| DD4((new_offset
>> 1) + 1)
2048 | ((new_offset
& 0x1) ? 0x400000 : 0) | DM4((offset
>> 1) + 1)));
2052 else if ((arg_types
& SLJIT_DEF_MASK
) == SLJIT_ARG_TYPE_F64
) {
2056 while (remap
& mask
) {
2062 if (offset
!= new_offset
)
2063 FAIL_IF(push_inst32(compiler
, VMOV_F32
| SLJIT_F32_OP
| DD4((new_offset
>> 1) + 1) | DM4((offset
>> 1) + 1)));
2067 arg_types
>>= SLJIT_DEF_SHIFT
;
2070 return SLJIT_SUCCESS
;
2075 SLJIT_API_FUNC_ATTRIBUTE
struct sljit_jump
* sljit_emit_call(struct sljit_compiler
*compiler
, sljit_s32 type
,
2076 sljit_s32 arg_types
)
2079 struct sljit_jump
*jump
;
2083 CHECK_PTR(check_sljit_emit_call(compiler
, type
, arg_types
));
2086 PTR_FAIL_IF(softfloat_call_with_args(compiler
, arg_types
, NULL
));
2088 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
2089 || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
2090 compiler
->skip_checks
= 1;
2093 jump
= sljit_emit_jump(compiler
, type
);
2094 PTR_FAIL_IF(jump
== NULL
);
2096 PTR_FAIL_IF(softfloat_post_call_with_args(compiler
, arg_types
));
2099 PTR_FAIL_IF(hardfloat_call_with_args(compiler
, arg_types
));
2101 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
2102 || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
2103 compiler
->skip_checks
= 1;
2106 return sljit_emit_jump(compiler
, type
);
2110 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_ijump(struct sljit_compiler
*compiler
, sljit_s32 type
, sljit_s32 src
, sljit_sw srcw
)
2112 struct sljit_jump
*jump
;
2115 CHECK(check_sljit_emit_ijump(compiler
, type
, src
, srcw
));
2116 ADJUST_LOCAL_OFFSET(src
, srcw
);
2118 SLJIT_ASSERT(reg_map
[TMP_REG1
] != 14);
2120 if (!(src
& SLJIT_IMM
)) {
2121 if (FAST_IS_REG(src
)) {
2122 SLJIT_ASSERT(reg_map
[src
] != 14);
2123 return push_inst16(compiler
, (type
<= SLJIT_JUMP
? BX
: BLX
) | RN3(src
));
2126 FAIL_IF(emit_op_mem(compiler
, WORD_SIZE
, type
<= SLJIT_JUMP
? TMP_PC
: TMP_REG1
, src
, srcw
, TMP_REG1
));
2127 if (type
>= SLJIT_FAST_CALL
)
2128 return push_inst16(compiler
, BLX
| RN3(TMP_REG1
));
2131 /* These jumps are converted to jump/call instructions when possible. */
2132 jump
= (struct sljit_jump
*)ensure_abuf(compiler
, sizeof(struct sljit_jump
));
2134 set_jump(jump
, compiler
, JUMP_ADDR
| ((type
>= SLJIT_FAST_CALL
) ? IS_BL
: 0));
2135 jump
->u
.target
= srcw
;
2137 FAIL_IF(emit_imm32_const(compiler
, TMP_REG1
, 0));
2138 jump
->addr
= compiler
->size
;
2139 return push_inst16(compiler
, (type
<= SLJIT_JUMP
? BX
: BLX
) | RN3(TMP_REG1
));
2142 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_icall(struct sljit_compiler
*compiler
, sljit_s32 type
,
2143 sljit_s32 arg_types
,
2144 sljit_s32 src
, sljit_sw srcw
)
2147 CHECK(check_sljit_emit_icall(compiler
, type
, arg_types
, src
, srcw
));
2150 if (src
& SLJIT_MEM
) {
2151 FAIL_IF(emit_op_mem(compiler
, WORD_SIZE
, TMP_REG1
, src
, srcw
, TMP_REG1
));
2155 FAIL_IF(softfloat_call_with_args(compiler
, arg_types
, &src
));
2157 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
2158 || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
2159 compiler
->skip_checks
= 1;
2162 FAIL_IF(sljit_emit_ijump(compiler
, type
, src
, srcw
));
2164 return softfloat_post_call_with_args(compiler
, arg_types
);
2165 #else /* !__SOFTFP__ */
2166 FAIL_IF(hardfloat_call_with_args(compiler
, arg_types
));
2168 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
2169 || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
2170 compiler
->skip_checks
= 1;
2173 return sljit_emit_ijump(compiler
, type
, src
, srcw
);
2174 #endif /* __SOFTFP__ */
2177 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_op_flags(struct sljit_compiler
*compiler
, sljit_s32 op
,
2178 sljit_s32 dst
, sljit_sw dstw
,
2181 sljit_s32 dst_r
, flags
= GET_ALL_FLAGS(op
);
2185 CHECK(check_sljit_emit_op_flags(compiler
, op
, dst
, dstw
, type
));
2186 ADJUST_LOCAL_OFFSET(dst
, dstw
);
2188 op
= GET_OPCODE(op
);
2189 cc
= get_cc(compiler
, type
& 0xff);
2190 dst_r
= FAST_IS_REG(dst
) ? dst
: TMP_REG1
;
2192 if (op
< SLJIT_ADD
) {
2193 FAIL_IF(push_inst16(compiler
, IT
| (cc
<< 4) | (((cc
& 0x1) ^ 0x1) << 3) | 0x4));
2194 if (reg_map
[dst_r
] > 7) {
2195 FAIL_IF(push_inst32(compiler
, MOV_WI
| RD4(dst_r
) | 1));
2196 FAIL_IF(push_inst32(compiler
, MOV_WI
| RD4(dst_r
) | 0));
2198 /* The movsi (immediate) instruction does not set flags in IT block. */
2199 FAIL_IF(push_inst16(compiler
, MOVSI
| RDN3(dst_r
) | 1));
2200 FAIL_IF(push_inst16(compiler
, MOVSI
| RDN3(dst_r
) | 0));
2202 if (!(dst
& SLJIT_MEM
))
2203 return SLJIT_SUCCESS
;
2204 return emit_op_mem(compiler
, WORD_SIZE
| STORE
, TMP_REG1
, dst
, dstw
, TMP_REG2
);
2207 if (dst
& SLJIT_MEM
)
2208 FAIL_IF(emit_op_mem(compiler
, WORD_SIZE
, TMP_REG1
, dst
, dstw
, TMP_REG2
));
2210 if (op
== SLJIT_AND
) {
2211 FAIL_IF(push_inst16(compiler
, IT
| (cc
<< 4) | (((cc
& 0x1) ^ 0x1) << 3) | 0x4));
2212 FAIL_IF(push_inst32(compiler
, ANDI
| RN4(dst_r
) | RD4(dst_r
) | 1));
2213 FAIL_IF(push_inst32(compiler
, ANDI
| RN4(dst_r
) | RD4(dst_r
) | 0));
2216 FAIL_IF(push_inst16(compiler
, IT
| (cc
<< 4) | 0x8));
2217 FAIL_IF(push_inst32(compiler
, ((op
== SLJIT_OR
) ? ORRI
: EORI
) | RN4(dst_r
) | RD4(dst_r
) | 1));
2220 if (dst
& SLJIT_MEM
)
2221 FAIL_IF(emit_op_mem(compiler
, WORD_SIZE
| STORE
, TMP_REG1
, dst
, dstw
, TMP_REG2
));
2223 if (!(flags
& SLJIT_SET_Z
))
2224 return SLJIT_SUCCESS
;
2226 /* The condition must always be set, even if the ORR/EORI is not executed above. */
2227 return push_inst32(compiler
, MOV_W
| SET_FLAGS
| RD4(TMP_REG1
) | RM4(dst_r
));
2230 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_cmov(struct sljit_compiler
*compiler
, sljit_s32 type
,
2232 sljit_s32 src
, sljit_sw srcw
)
2237 CHECK(check_sljit_emit_cmov(compiler
, type
, dst_reg
, src
, srcw
));
2239 dst_reg
&= ~SLJIT_I32_OP
;
2241 cc
= get_cc(compiler
, type
& 0xff);
2243 if (!(src
& SLJIT_IMM
)) {
2244 FAIL_IF(push_inst16(compiler
, IT
| (cc
<< 4) | 0x8));
2245 return push_inst16(compiler
, MOV
| SET_REGS44(dst_reg
, src
));
2248 tmp
= (sljit_uw
) srcw
;
2250 if (tmp
< 0x10000) {
2251 /* set low 16 bits, set hi 16 bits to 0. */
2252 FAIL_IF(push_inst16(compiler
, IT
| (cc
<< 4) | 0x8));
2253 return push_inst32(compiler
, MOVW
| RD4(dst_reg
)
2254 | COPY_BITS(tmp
, 12, 16, 4) | COPY_BITS(tmp
, 11, 26, 1) | COPY_BITS(tmp
, 8, 12, 3) | (tmp
& 0xff));
2257 tmp
= get_imm(srcw
);
2258 if (tmp
!= INVALID_IMM
) {
2259 FAIL_IF(push_inst16(compiler
, IT
| (cc
<< 4) | 0x8));
2260 return push_inst32(compiler
, MOV_WI
| RD4(dst_reg
) | tmp
);
2263 tmp
= get_imm(~srcw
);
2264 if (tmp
!= INVALID_IMM
) {
2265 FAIL_IF(push_inst16(compiler
, IT
| (cc
<< 4) | 0x8));
2266 return push_inst32(compiler
, MVN_WI
| RD4(dst_reg
) | tmp
);
2269 FAIL_IF(push_inst16(compiler
, IT
| (cc
<< 4) | ((cc
& 0x1) << 3) | 0x4));
2271 tmp
= (sljit_uw
) srcw
;
2272 FAIL_IF(push_inst32(compiler
, MOVW
| RD4(dst_reg
)
2273 | COPY_BITS(tmp
, 12, 16, 4) | COPY_BITS(tmp
, 11, 26, 1) | COPY_BITS(tmp
, 8, 12, 3) | (tmp
& 0xff)));
2274 return push_inst32(compiler
, MOVT
| RD4(dst_reg
)
2275 | COPY_BITS(tmp
, 12 + 16, 16, 4) | COPY_BITS(tmp
, 11 + 16, 26, 1) | COPY_BITS(tmp
, 8 + 16, 12, 3) | ((tmp
& 0xff0000) >> 16));
2278 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_mem(struct sljit_compiler
*compiler
, sljit_s32 type
,
2280 sljit_s32 mem
, sljit_sw memw
)
2286 CHECK(check_sljit_emit_mem(compiler
, type
, reg
, mem
, memw
));
2288 if ((mem
& OFFS_REG_MASK
) || (memw
> 255 || memw
< -255))
2289 return SLJIT_ERR_UNSUPPORTED
;
2291 if (type
& SLJIT_MEM_SUPP
)
2292 return SLJIT_SUCCESS
;
2294 switch (type
& 0xff) {
2305 flags
= BYTE_SIZE
| SIGNED
;
2311 flags
= HALF_SIZE
| SIGNED
;
2314 SLJIT_UNREACHABLE();
2319 if (type
& SLJIT_MEM_STORE
)
2322 inst
= sljit_mem32
[flags
] | 0x900;
2324 if (type
& SLJIT_MEM_PRE
)
2332 return push_inst32(compiler
, inst
| RT4(reg
) | RN4(mem
& REG_MASK
) | memw
);
2335 SLJIT_API_FUNC_ATTRIBUTE
struct sljit_const
* sljit_emit_const(struct sljit_compiler
*compiler
, sljit_s32 dst
, sljit_sw dstw
, sljit_sw init_value
)
2337 struct sljit_const
*const_
;
2341 CHECK_PTR(check_sljit_emit_const(compiler
, dst
, dstw
, init_value
));
2342 ADJUST_LOCAL_OFFSET(dst
, dstw
);
2344 const_
= (struct sljit_const
*)ensure_abuf(compiler
, sizeof(struct sljit_const
));
2345 PTR_FAIL_IF(!const_
);
2346 set_const(const_
, compiler
);
2348 dst_r
= FAST_IS_REG(dst
) ? dst
: TMP_REG1
;
2349 PTR_FAIL_IF(emit_imm32_const(compiler
, dst_r
, init_value
));
2351 if (dst
& SLJIT_MEM
)
2352 PTR_FAIL_IF(emit_op_mem(compiler
, WORD_SIZE
| STORE
, dst_r
, dst
, dstw
, TMP_REG2
));
2356 SLJIT_API_FUNC_ATTRIBUTE
struct sljit_put_label
* sljit_emit_put_label(struct sljit_compiler
*compiler
, sljit_s32 dst
, sljit_sw dstw
)
2358 struct sljit_put_label
*put_label
;
2362 CHECK_PTR(check_sljit_emit_put_label(compiler
, dst
, dstw
));
2363 ADJUST_LOCAL_OFFSET(dst
, dstw
);
2365 put_label
= (struct sljit_put_label
*)ensure_abuf(compiler
, sizeof(struct sljit_put_label
));
2366 PTR_FAIL_IF(!put_label
);
2367 set_put_label(put_label
, compiler
, 0);
2369 dst_r
= FAST_IS_REG(dst
) ? dst
: TMP_REG1
;
2370 PTR_FAIL_IF(emit_imm32_const(compiler
, dst_r
, 0));
2372 if (dst
& SLJIT_MEM
)
2373 PTR_FAIL_IF(emit_op_mem(compiler
, WORD_SIZE
| STORE
, dst_r
, dst
, dstw
, TMP_REG2
));
2377 SLJIT_API_FUNC_ATTRIBUTE
void sljit_set_jump_addr(sljit_uw addr
, sljit_uw new_target
, sljit_sw executable_offset
)
2379 sljit_u16
*inst
= (sljit_u16
*)addr
;
2380 SLJIT_UNUSED_ARG(executable_offset
);
2382 SLJIT_UPDATE_WX_FLAGS(inst
, inst
+ 4, 0);
2383 modify_imm32_const(inst
, new_target
);
2384 SLJIT_UPDATE_WX_FLAGS(inst
, inst
+ 4, 1);
2385 inst
= (sljit_u16
*)SLJIT_ADD_EXEC_OFFSET(inst
, executable_offset
);
2386 SLJIT_CACHE_FLUSH(inst
, inst
+ 4);
2389 SLJIT_API_FUNC_ATTRIBUTE
void sljit_set_const(sljit_uw addr
, sljit_sw new_constant
, sljit_sw executable_offset
)
2391 sljit_set_jump_addr(addr
, new_constant
, executable_offset
);