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, 15, 14, 13, 12, 11, 10, 9, 8, 6, 7
56 #define COPY_BITS(src, from, to, bits) \
57 ((from >= to ? ((sljit_ins)(src) >> (from - to)) : ((sljit_ins)(src) << (to - from))) & (((1 << bits) - 1) << to))
59 #define NEGATE(uimm) ((sljit_uw)-(sljit_sw)(uimm))
61 /* Thumb16 encodings. */
62 #define RD3(rd) ((sljit_ins)reg_map[rd])
63 #define RN3(rn) ((sljit_ins)reg_map[rn] << 3)
64 #define RM3(rm) ((sljit_ins)reg_map[rm] << 6)
65 #define RDN3(rdn) ((sljit_ins)reg_map[rdn] << 8)
66 #define IMM3(imm) ((sljit_ins)imm << 6)
67 #define IMM8(imm) ((sljit_ins)imm)
69 /* Thumb16 helpers. */
70 #define SET_REGS44(rd, rn) \
71 (((sljit_ins)reg_map[rn] << 3) | ((sljit_ins)reg_map[rd] & 0x7) | (((sljit_ins)reg_map[rd] & 0x8) << 4))
72 #define IS_2_LO_REGS(reg1, reg2) \
73 (reg_map[reg1] <= 7 && reg_map[reg2] <= 7)
74 #define IS_3_LO_REGS(reg1, reg2, reg3) \
75 (reg_map[reg1] <= 7 && reg_map[reg2] <= 7 && reg_map[reg3] <= 7)
77 /* Thumb32 encodings. */
78 #define RD4(rd) ((sljit_ins)reg_map[rd] << 8)
79 #define RN4(rn) ((sljit_ins)reg_map[rn] << 16)
80 #define RM4(rm) ((sljit_ins)reg_map[rm])
81 #define RT4(rt) ((sljit_ins)reg_map[rt] << 12)
82 #define DD4(dd) ((sljit_ins)freg_map[dd] << 12)
83 #define DN4(dn) ((sljit_ins)freg_map[dn] << 16)
84 #define DM4(dm) ((sljit_ins)freg_map[dm])
86 (COPY_BITS(imm, 2, 12, 3) | (((sljit_ins)imm & 0x3) << 6))
88 (COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | ((sljit_ins)imm & 0xff))
90 /* --------------------------------------------------------------------- */
91 /* Instrucion forms */
92 /* --------------------------------------------------------------------- */
94 /* dot '.' changed to _
95 I immediate form (possibly followed by number of immediate bits). */
96 #define ADCI 0xf1400000
98 #define ADC_W 0xeb400000
101 #define ADDSI3 0x1c00
102 #define ADDSI8 0x3000
103 #define ADD_W 0xeb000000
104 #define ADDWI 0xf2000000
105 #define ADD_SP 0x4485
106 #define ADD_SP_I 0xb000
107 #define ADD_W 0xeb000000
108 #define ADD_WI 0xf1000000
109 #define ANDI 0xf0000000
111 #define AND_W 0xea000000
114 #define ASR_W 0xfa40f000
115 #define ASR_WI 0xea4f0020
117 #define BICI 0xf0200000
121 #define CLZ 0xfab0f080
122 #define CMNI_W 0xf1100f00
125 #define CMPI_W 0xf1b00f00
127 #define CMP_W 0xebb00f00
128 #define EORI 0xf0800000
130 #define EOR_W 0xea800000
132 #define LDR_SP 0x9800
133 #define LDR 0xf8d00000
134 #define LDRI 0xf8500800
137 #define LSL_W 0xfa00f000
138 #define LSL_WI 0xea4f0000
141 #define LSR_W 0xfa20f000
142 #define LSR_WI 0xea4f0010
146 #define MOVT 0xf2c00000
147 #define MOVW 0xf2400000
148 #define MOV_W 0xea4f0000
149 #define MOV_WI 0xf04f0000
150 #define MUL 0xfb00f000
152 #define MVN_W 0xea6f0000
153 #define MVN_WI 0xf06f0000
155 #define ORNI 0xf0600000
156 #define ORRI 0xf0400000
158 #define ORR_W 0xea400000
160 #define POP_W 0xe8bd0000
162 #define PUSH_W 0xe92d0000
163 #define RSB_WI 0xf1c00000
165 #define SBCI 0xf1600000
167 #define SBC_W 0xeb600000
168 #define SDIV 0xfb90f0f0
169 #define SMULL 0xfb800000
170 #define STR_SP 0x9000
172 #define SUBSI3 0x1e00
173 #define SUBSI8 0x3800
174 #define SUB_W 0xeba00000
175 #define SUBWI 0xf2a00000
176 #define SUB_SP_I 0xb080
177 #define SUB_WI 0xf1a00000
179 #define SXTB_W 0xfa4ff080
181 #define SXTH_W 0xfa0ff080
183 #define TSTI 0xf0000f00
184 #define TST_W 0xea000f00
185 #define UDIV 0xfbb0f0f0
186 #define UMULL 0xfba00000
188 #define UXTB_W 0xfa5ff080
190 #define UXTH_W 0xfa1ff080
191 #define VABS_F32 0xeeb00ac0
192 #define VADD_F32 0xee300a00
193 #define VCMP_F32 0xeeb40a40
194 #define VCVT_F32_S32 0xeeb80ac0
195 #define VCVT_F64_F32 0xeeb70ac0
196 #define VCVT_S32_F32 0xeebd0ac0
197 #define VDIV_F32 0xee800a00
198 #define VLDR_F32 0xed100a00
199 #define VMOV_F32 0xeeb00a40
200 #define VMOV 0xee000a10
201 #define VMOV2 0xec400a10
202 #define VMRS 0xeef1fa10
203 #define VMUL_F32 0xee200a00
204 #define VNEG_F32 0xeeb10a40
205 #define VPOP 0xecbd0b00
206 #define VPUSH 0xed2d0b00
207 #define VSTR_F32 0xed000a00
208 #define VSUB_F32 0xee300a40
210 static sljit_s32
push_inst16(struct sljit_compiler
*compiler
, sljit_ins inst
)
213 SLJIT_ASSERT(!(inst
& 0xffff0000));
215 ptr
= (sljit_u16
*)ensure_buf(compiler
, sizeof(sljit_u16
));
217 *ptr
= (sljit_u16
)(inst
);
219 return SLJIT_SUCCESS
;
222 static sljit_s32
push_inst32(struct sljit_compiler
*compiler
, sljit_ins inst
)
224 sljit_u16
*ptr
= (sljit_u16
*)ensure_buf(compiler
, sizeof(sljit_ins
));
226 *ptr
++ = (sljit_u16
)(inst
>> 16);
227 *ptr
= (sljit_u16
)(inst
);
229 return SLJIT_SUCCESS
;
232 static SLJIT_INLINE sljit_s32
emit_imm32_const(struct sljit_compiler
*compiler
, sljit_s32 dst
, sljit_uw imm
)
234 FAIL_IF(push_inst32(compiler
, MOVW
| RD4(dst
)
235 | COPY_BITS(imm
, 12, 16, 4) | COPY_BITS(imm
, 11, 26, 1) | COPY_BITS(imm
, 8, 12, 3) | (imm
& 0xff)));
236 return push_inst32(compiler
, MOVT
| RD4(dst
)
237 | COPY_BITS(imm
, 12 + 16, 16, 4) | COPY_BITS(imm
, 11 + 16, 26, 1) | COPY_BITS(imm
, 8 + 16, 12, 3) | ((imm
& 0xff0000) >> 16));
240 static SLJIT_INLINE
void modify_imm32_const(sljit_u16
*inst
, sljit_uw new_imm
)
242 sljit_ins dst
= inst
[1] & 0x0f00;
243 SLJIT_ASSERT(((inst
[0] & 0xfbf0) == (MOVW
>> 16)) && ((inst
[2] & 0xfbf0) == (MOVT
>> 16)) && dst
== (inst
[3] & 0x0f00));
244 inst
[0] = (sljit_u16
)((MOVW
>> 16) | COPY_BITS(new_imm
, 12, 0, 4) | COPY_BITS(new_imm
, 11, 10, 1));
245 inst
[1] = (sljit_u16
)(dst
| COPY_BITS(new_imm
, 8, 12, 3) | (new_imm
& 0xff));
246 inst
[2] = (sljit_u16
)((MOVT
>> 16) | COPY_BITS(new_imm
, 12 + 16, 0, 4) | COPY_BITS(new_imm
, 11 + 16, 10, 1));
247 inst
[3] = (sljit_u16
)(dst
| COPY_BITS(new_imm
, 8 + 16, 12, 3) | ((new_imm
& 0xff0000) >> 16));
250 static SLJIT_INLINE sljit_s32
detect_jump_type(struct sljit_jump
*jump
, sljit_u16
*code_ptr
, sljit_u16
*code
, sljit_sw executable_offset
)
254 if (jump
->flags
& SLJIT_REWRITABLE_JUMP
)
257 if (jump
->flags
& JUMP_ADDR
) {
258 /* Branch to ARM code is not optimized yet. */
259 if (!(jump
->u
.target
& 0x1))
261 diff
= ((sljit_sw
)jump
->u
.target
- (sljit_sw
)(code_ptr
+ 2) - executable_offset
) >> 1;
264 SLJIT_ASSERT(jump
->flags
& JUMP_LABEL
);
265 diff
= ((sljit_sw
)(code
+ jump
->u
.label
->size
) - (sljit_sw
)(code_ptr
+ 2)) >> 1;
268 if (jump
->flags
& IS_COND
) {
269 SLJIT_ASSERT(!(jump
->flags
& IS_BL
));
270 if (diff
<= 127 && diff
>= -128) {
271 jump
->flags
|= PATCH_TYPE1
;
274 if (diff
<= 524287 && diff
>= -524288) {
275 jump
->flags
|= PATCH_TYPE2
;
278 /* +1 comes from the prefix IT instruction. */
280 if (diff
<= 8388607 && diff
>= -8388608) {
281 jump
->flags
|= PATCH_TYPE3
;
285 else if (jump
->flags
& IS_BL
) {
286 if (diff
<= 8388607 && diff
>= -8388608) {
287 jump
->flags
|= PATCH_BL
;
292 if (diff
<= 1023 && diff
>= -1024) {
293 jump
->flags
|= PATCH_TYPE4
;
296 if (diff
<= 8388607 && diff
>= -8388608) {
297 jump
->flags
|= PATCH_TYPE5
;
305 static SLJIT_INLINE
void set_jump_instruction(struct sljit_jump
*jump
, sljit_sw executable_offset
)
307 sljit_s32 type
= (jump
->flags
>> 4) & 0xf;
309 sljit_u16
*jump_inst
;
312 if (SLJIT_UNLIKELY(type
== 0)) {
313 modify_imm32_const((sljit_u16
*)jump
->addr
, (jump
->flags
& JUMP_LABEL
) ? jump
->u
.label
->addr
: jump
->u
.target
);
317 if (jump
->flags
& JUMP_ADDR
) {
318 SLJIT_ASSERT(jump
->u
.target
& 0x1);
319 diff
= ((sljit_sw
)jump
->u
.target
- (sljit_sw
)(jump
->addr
+ sizeof(sljit_u32
)) - executable_offset
) >> 1;
322 SLJIT_ASSERT(jump
->u
.label
->addr
& 0x1);
323 diff
= ((sljit_sw
)(jump
->u
.label
->addr
) - (sljit_sw
)(jump
->addr
+ sizeof(sljit_u32
)) - executable_offset
) >> 1;
325 jump_inst
= (sljit_u16
*)jump
->addr
;
329 /* Encoding T1 of 'B' instruction */
330 SLJIT_ASSERT(diff
<= 127 && diff
>= -128 && (jump
->flags
& IS_COND
));
331 jump_inst
[0] = (sljit_u16
)(0xd000 | (jump
->flags
& 0xf00) | ((sljit_ins
)diff
& 0xff));
334 /* Encoding T3 of 'B' instruction */
335 SLJIT_ASSERT(diff
<= 524287 && diff
>= -524288 && (jump
->flags
& IS_COND
));
336 jump_inst
[0] = (sljit_u16
)(0xf000 | COPY_BITS(jump
->flags
, 8, 6, 4) | COPY_BITS(diff
, 11, 0, 6) | COPY_BITS(diff
, 19, 10, 1));
337 jump_inst
[1] = (sljit_u16
)(0x8000 | COPY_BITS(diff
, 17, 13, 1) | COPY_BITS(diff
, 18, 11, 1) | ((sljit_ins
)diff
& 0x7ff));
340 SLJIT_ASSERT(jump
->flags
& IS_COND
);
341 *jump_inst
++ = (sljit_u16
)(IT
| ((jump
->flags
>> 4) & 0xf0) | 0x8);
346 /* Encoding T2 of 'B' instruction */
347 SLJIT_ASSERT(diff
<= 1023 && diff
>= -1024 && !(jump
->flags
& IS_COND
));
348 jump_inst
[0] = (sljit_u16
)(0xe000 | (diff
& 0x7ff));
352 SLJIT_ASSERT(diff
<= 8388607 && diff
>= -8388608);
354 /* Really complex instruction form for branches. */
355 s
= (diff
>> 23) & 0x1;
356 j1
= (~(diff
>> 22) ^ s
) & 0x1;
357 j2
= (~(diff
>> 21) ^ s
) & 0x1;
358 jump_inst
[0] = (sljit_u16
)(0xf000 | ((sljit_ins
)s
<< 10) | COPY_BITS(diff
, 11, 0, 10));
359 jump_inst
[1] = (sljit_u16
)((j1
<< 13) | (j2
<< 11) | (diff
& 0x7ff));
361 /* The others have a common form. */
362 if (type
== 5) /* Encoding T4 of 'B' instruction */
363 jump_inst
[1] |= 0x9000;
364 else if (type
== 6) /* Encoding T1 of 'BL' instruction */
365 jump_inst
[1] |= 0xd000;
370 SLJIT_API_FUNC_ATTRIBUTE
void* sljit_generate_code(struct sljit_compiler
*compiler
)
372 struct sljit_memory_fragment
*buf
;
379 sljit_sw executable_offset
;
381 struct sljit_label
*label
;
382 struct sljit_jump
*jump
;
383 struct sljit_const
*const_
;
384 struct sljit_put_label
*put_label
;
387 CHECK_PTR(check_sljit_generate_code(compiler
));
388 reverse_buf(compiler
);
390 code
= (sljit_u16
*)SLJIT_MALLOC_EXEC(compiler
->size
* sizeof(sljit_u16
), compiler
->exec_allocator_data
);
391 PTR_FAIL_WITH_EXEC_IF(code
);
397 executable_offset
= SLJIT_EXEC_OFFSET(code
);
399 label
= compiler
->labels
;
400 jump
= compiler
->jumps
;
401 const_
= compiler
->consts
;
402 put_label
= compiler
->put_labels
;
405 buf_ptr
= (sljit_u16
*)buf
->memory
;
406 buf_end
= buf_ptr
+ (buf
->used_size
>> 1);
408 *code_ptr
= *buf_ptr
++;
409 if (next_addr
== half_count
) {
410 SLJIT_ASSERT(!label
|| label
->size
>= half_count
);
411 SLJIT_ASSERT(!jump
|| jump
->addr
>= half_count
);
412 SLJIT_ASSERT(!const_
|| const_
->addr
>= half_count
);
413 SLJIT_ASSERT(!put_label
|| put_label
->addr
>= half_count
);
415 /* These structures are ordered by their address. */
416 if (label
&& label
->size
== half_count
) {
417 label
->addr
= ((sljit_uw
)SLJIT_ADD_EXEC_OFFSET(code_ptr
, executable_offset
)) | 0x1;
418 label
->size
= (sljit_uw
)(code_ptr
- code
);
421 if (jump
&& jump
->addr
== half_count
) {
422 jump
->addr
= (sljit_uw
)code_ptr
- ((jump
->flags
& IS_COND
) ? 10 : 8);
423 code_ptr
-= detect_jump_type(jump
, code_ptr
, code
, executable_offset
);
426 if (const_
&& const_
->addr
== half_count
) {
427 const_
->addr
= (sljit_uw
)code_ptr
;
428 const_
= const_
->next
;
430 if (put_label
&& put_label
->addr
== half_count
) {
431 SLJIT_ASSERT(put_label
->label
);
432 put_label
->addr
= (sljit_uw
)code_ptr
;
433 put_label
= put_label
->next
;
435 next_addr
= compute_next_addr(label
, jump
, const_
, put_label
);
439 } while (buf_ptr
< buf_end
);
444 if (label
&& label
->size
== half_count
) {
445 label
->addr
= ((sljit_uw
)SLJIT_ADD_EXEC_OFFSET(code_ptr
, executable_offset
)) | 0x1;
446 label
->size
= (sljit_uw
)(code_ptr
- code
);
450 SLJIT_ASSERT(!label
);
452 SLJIT_ASSERT(!const_
);
453 SLJIT_ASSERT(!put_label
);
454 SLJIT_ASSERT(code_ptr
- code
<= (sljit_sw
)compiler
->size
);
456 jump
= compiler
->jumps
;
458 set_jump_instruction(jump
, executable_offset
);
462 put_label
= compiler
->put_labels
;
464 modify_imm32_const((sljit_u16
*)put_label
->addr
, put_label
->label
->addr
);
465 put_label
= put_label
->next
;
468 compiler
->error
= SLJIT_ERR_COMPILED
;
469 compiler
->executable_offset
= executable_offset
;
470 compiler
->executable_size
= (sljit_uw
)(code_ptr
- code
) * sizeof(sljit_u16
);
472 code
= (sljit_u16
*)SLJIT_ADD_EXEC_OFFSET(code
, executable_offset
);
473 code_ptr
= (sljit_u16
*)SLJIT_ADD_EXEC_OFFSET(code_ptr
, executable_offset
);
475 SLJIT_CACHE_FLUSH(code
, code_ptr
);
476 SLJIT_UPDATE_WX_FLAGS(code
, code_ptr
, 1);
478 /* Set thumb mode flag. */
479 return (void*)((sljit_uw
)code
| 0x1);
482 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_has_cpu_feature(sljit_s32 feature_type
)
484 switch (feature_type
) {
486 #ifdef SLJIT_IS_FPU_AVAILABLE
487 return SLJIT_IS_FPU_AVAILABLE
;
489 /* Available by default. */
495 case SLJIT_HAS_PREFETCH
:
503 /* --------------------------------------------------------------------- */
504 /* Core code generator functions. */
505 /* --------------------------------------------------------------------- */
507 #define INVALID_IMM 0x80000000
508 static sljit_uw
get_imm(sljit_uw imm
)
510 /* Thumb immediate form. */
516 if ((imm
& 0xffff) == (imm
>> 16)) {
517 /* Some special cases. */
519 return (1 << 12) | (imm
& 0xff);
521 return (2 << 12) | ((imm
>> 8) & 0xff);
522 if ((imm
& 0xff00) == ((imm
& 0xff) << 8))
523 return (3 << 12) | (imm
& 0xff);
526 /* Assembly optimization: count leading zeroes? */
528 if (!(imm
& 0xffff0000)) {
532 if (!(imm
& 0xff000000)) {
536 if (!(imm
& 0xf0000000)) {
540 if (!(imm
& 0xc0000000)) {
544 if (!(imm
& 0x80000000)) {
548 /* Since imm >= 128, this must be true. */
549 SLJIT_ASSERT(counter
<= 31);
551 if (imm
& 0x00ffffff)
552 return INVALID_IMM
; /* Cannot be encoded. */
554 return ((imm
>> 24) & 0x7f) | COPY_BITS(counter
, 4, 26, 1) | COPY_BITS(counter
, 1, 12, 3) | COPY_BITS(counter
, 0, 7, 1);
557 static sljit_s32
load_immediate(struct sljit_compiler
*compiler
, sljit_s32 dst
, sljit_uw imm
)
561 /* MOVS cannot be used since it destroy flags. */
563 if (imm
>= 0x10000) {
565 if (tmp
!= INVALID_IMM
)
566 return push_inst32(compiler
, MOV_WI
| RD4(dst
) | tmp
);
568 if (tmp
!= INVALID_IMM
)
569 return push_inst32(compiler
, MVN_WI
| RD4(dst
) | tmp
);
572 /* set low 16 bits, set hi 16 bits to 0. */
573 FAIL_IF(push_inst32(compiler
, MOVW
| RD4(dst
)
574 | COPY_BITS(imm
, 12, 16, 4) | COPY_BITS(imm
, 11, 26, 1) | COPY_BITS(imm
, 8, 12, 3) | (imm
& 0xff)));
576 /* set hi 16 bit if needed. */
578 return push_inst32(compiler
, MOVT
| RD4(dst
)
579 | COPY_BITS(imm
, 12 + 16, 16, 4) | COPY_BITS(imm
, 11 + 16, 26, 1) | COPY_BITS(imm
, 8 + 16, 12, 3) | ((imm
& 0xff0000) >> 16));
580 return SLJIT_SUCCESS
;
583 #define ARG1_IMM 0x0010000
584 #define ARG2_IMM 0x0020000
585 /* SET_FLAGS must be 0x100000 as it is also the value of S bit (can be used for optimization). */
586 #define SET_FLAGS 0x0100000
587 #define UNUSED_RETURN 0x0200000
589 static sljit_s32
emit_op_imm(struct sljit_compiler
*compiler
, sljit_s32 flags
, sljit_s32 dst
, sljit_uw arg1
, sljit_uw arg2
)
591 /* dst must be register, TMP_REG1
592 arg1 must be register, imm
593 arg2 must be register, imm */
597 if (SLJIT_UNLIKELY((flags
& (ARG1_IMM
| ARG2_IMM
)) == (ARG1_IMM
| ARG2_IMM
))) {
598 /* Both are immediates, no temporaries are used. */
600 FAIL_IF(load_immediate(compiler
, TMP_REG1
, arg1
));
604 if (flags
& (ARG1_IMM
| ARG2_IMM
)) {
605 reg
= (sljit_s32
)((flags
& ARG2_IMM
) ? arg1
: arg2
);
606 imm
= (flags
& ARG2_IMM
) ? arg2
: arg1
;
608 switch (flags
& 0xffff) {
611 /* No form with immediate operand. */
614 SLJIT_ASSERT(!(flags
& SET_FLAGS
) && (flags
& ARG2_IMM
) && arg1
== TMP_REG2
);
615 return load_immediate(compiler
, dst
, imm
);
617 if (!(flags
& SET_FLAGS
))
618 return load_immediate(compiler
, dst
, ~imm
);
619 /* Since the flags should be set, we just fallback to the register mode.
620 Although some clever things could be done here, "NOT IMM" does not worth the efforts. */
623 compiler
->status_flags_state
= SLJIT_CURRENT_FLAGS_ADD
;
625 if (IS_2_LO_REGS(reg
, dst
)) {
627 return push_inst16(compiler
, ADDSI3
| IMM3(imm
) | RD3(dst
) | RN3(reg
));
629 return push_inst16(compiler
, SUBSI3
| IMM3(nimm
) | RD3(dst
) | RN3(reg
));
632 return push_inst16(compiler
, ADDSI8
| IMM8(imm
) | RDN3(dst
));
634 return push_inst16(compiler
, SUBSI8
| IMM8(nimm
) | RDN3(dst
));
637 if (!(flags
& SET_FLAGS
)) {
639 return push_inst32(compiler
, ADDWI
| RD4(dst
) | RN4(reg
) | IMM12(imm
));
641 return push_inst32(compiler
, SUBWI
| RD4(dst
) | RN4(reg
) | IMM12(nimm
));
644 if (nimm
!= INVALID_IMM
)
645 return push_inst32(compiler
, ADD_WI
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(reg
) | nimm
);
646 nimm
= get_imm(NEGATE(imm
));
647 if (nimm
!= INVALID_IMM
)
648 return push_inst32(compiler
, SUB_WI
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(reg
) | nimm
);
651 compiler
->status_flags_state
= SLJIT_CURRENT_FLAGS_ADD
;
653 if (imm
!= INVALID_IMM
)
654 return push_inst32(compiler
, ADCI
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(reg
) | imm
);
657 compiler
->status_flags_state
= SLJIT_CURRENT_FLAGS_SUB
;
658 if (flags
& ARG1_IMM
) {
659 if (imm
== 0 && IS_2_LO_REGS(reg
, dst
))
660 return push_inst16(compiler
, RSBSI
| RD3(dst
) | RN3(reg
));
662 if (imm
!= INVALID_IMM
)
663 return push_inst32(compiler
, RSB_WI
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(reg
) | imm
);
666 if (flags
& UNUSED_RETURN
) {
667 if (imm
<= 0xff && reg_map
[reg
] <= 7)
668 return push_inst16(compiler
, CMPI
| IMM8(imm
) | RDN3(reg
));
670 if (nimm
!= INVALID_IMM
)
671 return push_inst32(compiler
, CMPI_W
| RN4(reg
) | nimm
);
672 nimm
= get_imm(NEGATE(imm
));
673 if (nimm
!= INVALID_IMM
)
674 return push_inst32(compiler
, CMNI_W
| RN4(reg
) | nimm
);
678 if (IS_2_LO_REGS(reg
, dst
)) {
680 return push_inst16(compiler
, SUBSI3
| IMM3(imm
) | RD3(dst
) | RN3(reg
));
682 return push_inst16(compiler
, ADDSI3
| IMM3(nimm
) | RD3(dst
) | RN3(reg
));
685 return push_inst16(compiler
, SUBSI8
| IMM8(imm
) | RDN3(dst
));
687 return push_inst16(compiler
, ADDSI8
| IMM8(nimm
) | RDN3(dst
));
690 if (!(flags
& SET_FLAGS
)) {
692 return push_inst32(compiler
, SUBWI
| RD4(dst
) | RN4(reg
) | IMM12(imm
));
694 return push_inst32(compiler
, ADDWI
| RD4(dst
) | RN4(reg
) | IMM12(nimm
));
697 if (nimm
!= INVALID_IMM
)
698 return push_inst32(compiler
, SUB_WI
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(reg
) | nimm
);
699 nimm
= get_imm(NEGATE(imm
));
700 if (nimm
!= INVALID_IMM
)
701 return push_inst32(compiler
, ADD_WI
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(reg
) | nimm
);
704 compiler
->status_flags_state
= SLJIT_CURRENT_FLAGS_SUB
;
705 if (flags
& ARG1_IMM
)
708 if (imm
!= INVALID_IMM
)
709 return push_inst32(compiler
, SBCI
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(reg
) | imm
);
713 if (nimm
!= INVALID_IMM
)
714 return push_inst32(compiler
, ((flags
& UNUSED_RETURN
) ? TSTI
: ANDI
) | (flags
& SET_FLAGS
) | RD4(dst
) | RN4(reg
) | nimm
);
716 if (imm
!= INVALID_IMM
)
717 return push_inst32(compiler
, BICI
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(reg
) | imm
);
721 if (nimm
!= INVALID_IMM
)
722 return push_inst32(compiler
, ORRI
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(reg
) | nimm
);
724 if (imm
!= INVALID_IMM
)
725 return push_inst32(compiler
, ORNI
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(reg
) | imm
);
729 if (imm
!= INVALID_IMM
)
730 return push_inst32(compiler
, EORI
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(reg
) | imm
);
735 if (flags
& ARG1_IMM
)
739 if (!(flags
& SET_FLAGS
))
740 return push_inst16(compiler
, MOV
| SET_REGS44(dst
, reg
));
741 if (IS_2_LO_REGS(dst
, reg
))
742 return push_inst16(compiler
, MOVS
| RD3(dst
) | RN3(reg
));
743 return push_inst32(compiler
, MOV_W
| SET_FLAGS
| RD4(dst
) | RM4(reg
));
745 switch (flags
& 0xffff) {
747 if (IS_2_LO_REGS(dst
, reg
))
748 return push_inst16(compiler
, LSLSI
| RD3(dst
) | RN3(reg
) | (imm
<< 6));
749 return push_inst32(compiler
, LSL_WI
| (flags
& SET_FLAGS
) | RD4(dst
) | RM4(reg
) | IMM5(imm
));
751 if (IS_2_LO_REGS(dst
, reg
))
752 return push_inst16(compiler
, LSRSI
| RD3(dst
) | RN3(reg
) | (imm
<< 6));
753 return push_inst32(compiler
, LSR_WI
| (flags
& SET_FLAGS
) | RD4(dst
) | RM4(reg
) | IMM5(imm
));
754 default: /* SLJIT_ASHR */
755 if (IS_2_LO_REGS(dst
, reg
))
756 return push_inst16(compiler
, ASRSI
| RD3(dst
) | RN3(reg
) | (imm
<< 6));
757 return push_inst32(compiler
, ASR_WI
| (flags
& SET_FLAGS
) | RD4(dst
) | RM4(reg
) | IMM5(imm
));
764 if (flags
& ARG2_IMM
) {
766 arg2
= (arg1
== TMP_REG1
) ? TMP_REG2
: TMP_REG1
;
767 FAIL_IF(load_immediate(compiler
, (sljit_s32
)arg2
, imm
));
771 arg1
= (arg2
== TMP_REG1
) ? TMP_REG2
: TMP_REG1
;
772 FAIL_IF(load_immediate(compiler
, (sljit_s32
)arg1
, imm
));
775 SLJIT_ASSERT(arg1
!= arg2
);
778 /* Both arguments are registers. */
779 switch (flags
& 0xffff) {
785 SLJIT_ASSERT(!(flags
& SET_FLAGS
) && arg1
== TMP_REG2
);
786 if (dst
== (sljit_s32
)arg2
)
787 return SLJIT_SUCCESS
;
788 return push_inst16(compiler
, MOV
| SET_REGS44(dst
, arg2
));
790 SLJIT_ASSERT(!(flags
& SET_FLAGS
) && arg1
== TMP_REG2
);
791 if (IS_2_LO_REGS(dst
, arg2
))
792 return push_inst16(compiler
, UXTB
| RD3(dst
) | RN3(arg2
));
793 return push_inst32(compiler
, UXTB_W
| RD4(dst
) | RM4(arg2
));
795 SLJIT_ASSERT(!(flags
& SET_FLAGS
) && arg1
== TMP_REG2
);
796 if (IS_2_LO_REGS(dst
, arg2
))
797 return push_inst16(compiler
, SXTB
| RD3(dst
) | RN3(arg2
));
798 return push_inst32(compiler
, SXTB_W
| RD4(dst
) | RM4(arg2
));
800 SLJIT_ASSERT(!(flags
& SET_FLAGS
) && arg1
== TMP_REG2
);
801 if (IS_2_LO_REGS(dst
, arg2
))
802 return push_inst16(compiler
, UXTH
| RD3(dst
) | RN3(arg2
));
803 return push_inst32(compiler
, UXTH_W
| RD4(dst
) | RM4(arg2
));
805 SLJIT_ASSERT(!(flags
& SET_FLAGS
) && arg1
== TMP_REG2
);
806 if (IS_2_LO_REGS(dst
, arg2
))
807 return push_inst16(compiler
, SXTH
| RD3(dst
) | RN3(arg2
));
808 return push_inst32(compiler
, SXTH_W
| RD4(dst
) | RM4(arg2
));
810 SLJIT_ASSERT(arg1
== TMP_REG2
);
811 if (IS_2_LO_REGS(dst
, arg2
))
812 return push_inst16(compiler
, MVNS
| RD3(dst
) | RN3(arg2
));
813 return push_inst32(compiler
, MVN_W
| (flags
& SET_FLAGS
) | RD4(dst
) | RM4(arg2
));
815 SLJIT_ASSERT(arg1
== TMP_REG2
);
816 FAIL_IF(push_inst32(compiler
, CLZ
| RN4(arg2
) | RD4(dst
) | RM4(arg2
)));
817 return SLJIT_SUCCESS
;
819 compiler
->status_flags_state
= SLJIT_CURRENT_FLAGS_ADD
;
820 if (IS_3_LO_REGS(dst
, arg1
, arg2
))
821 return push_inst16(compiler
, ADDS
| RD3(dst
) | RN3(arg1
) | RM3(arg2
));
822 if (dst
== (sljit_s32
)arg1
&& !(flags
& SET_FLAGS
))
823 return push_inst16(compiler
, ADD
| SET_REGS44(dst
, arg2
));
824 return push_inst32(compiler
, ADD_W
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(arg1
) | RM4(arg2
));
826 compiler
->status_flags_state
= SLJIT_CURRENT_FLAGS_ADD
;
827 if (dst
== (sljit_s32
)arg1
&& IS_2_LO_REGS(dst
, arg2
))
828 return push_inst16(compiler
, ADCS
| RD3(dst
) | RN3(arg2
));
829 return push_inst32(compiler
, ADC_W
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(arg1
) | RM4(arg2
));
831 compiler
->status_flags_state
= SLJIT_CURRENT_FLAGS_SUB
;
832 if (flags
& UNUSED_RETURN
) {
833 if (IS_2_LO_REGS(arg1
, arg2
))
834 return push_inst16(compiler
, CMP
| RD3(arg1
) | RN3(arg2
));
835 return push_inst16(compiler
, CMP_X
| SET_REGS44(arg1
, arg2
));
837 if (IS_3_LO_REGS(dst
, arg1
, arg2
))
838 return push_inst16(compiler
, SUBS
| RD3(dst
) | RN3(arg1
) | RM3(arg2
));
839 return push_inst32(compiler
, SUB_W
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(arg1
) | RM4(arg2
));
841 compiler
->status_flags_state
= SLJIT_CURRENT_FLAGS_SUB
;
842 if (dst
== (sljit_s32
)arg1
&& IS_2_LO_REGS(dst
, arg2
))
843 return push_inst16(compiler
, SBCS
| RD3(dst
) | RN3(arg2
));
844 return push_inst32(compiler
, SBC_W
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(arg1
) | RM4(arg2
));
846 compiler
->status_flags_state
= 0;
847 if (!(flags
& SET_FLAGS
))
848 return push_inst32(compiler
, MUL
| RD4(dst
) | RN4(arg1
) | RM4(arg2
));
849 SLJIT_ASSERT(dst
!= TMP_REG2
);
850 FAIL_IF(push_inst32(compiler
, SMULL
| RT4(dst
) | RD4(TMP_REG2
) | RN4(arg1
) | RM4(arg2
)));
851 /* cmp TMP_REG2, dst asr #31. */
852 return push_inst32(compiler
, CMP_W
| RN4(TMP_REG2
) | 0x70e0 | RM4(dst
));
854 if (dst
== (sljit_s32
)arg1
&& IS_2_LO_REGS(dst
, arg2
))
855 return push_inst16(compiler
, ANDS
| RD3(dst
) | RN3(arg2
));
856 if ((flags
& UNUSED_RETURN
) && IS_2_LO_REGS(arg1
, arg2
))
857 return push_inst16(compiler
, TST
| RD3(arg1
) | RN3(arg2
));
858 return push_inst32(compiler
, ((flags
& UNUSED_RETURN
) ? TST_W
: AND_W
) | (flags
& SET_FLAGS
) | RD4(dst
) | RN4(arg1
) | RM4(arg2
));
860 if (dst
== (sljit_s32
)arg1
&& IS_2_LO_REGS(dst
, arg2
))
861 return push_inst16(compiler
, ORRS
| RD3(dst
) | RN3(arg2
));
862 return push_inst32(compiler
, ORR_W
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(arg1
) | RM4(arg2
));
864 if (dst
== (sljit_s32
)arg1
&& IS_2_LO_REGS(dst
, arg2
))
865 return push_inst16(compiler
, EORS
| RD3(dst
) | RN3(arg2
));
866 return push_inst32(compiler
, EOR_W
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(arg1
) | RM4(arg2
));
868 if (dst
== (sljit_s32
)arg1
&& IS_2_LO_REGS(dst
, arg2
))
869 return push_inst16(compiler
, LSLS
| RD3(dst
) | RN3(arg2
));
870 return push_inst32(compiler
, LSL_W
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(arg1
) | RM4(arg2
));
872 if (dst
== (sljit_s32
)arg1
&& IS_2_LO_REGS(dst
, arg2
))
873 return push_inst16(compiler
, LSRS
| RD3(dst
) | RN3(arg2
));
874 return push_inst32(compiler
, LSR_W
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(arg1
) | RM4(arg2
));
876 if (dst
== (sljit_s32
)arg1
&& IS_2_LO_REGS(dst
, arg2
))
877 return push_inst16(compiler
, ASRS
| RD3(dst
) | RN3(arg2
));
878 return push_inst32(compiler
, ASR_W
| (flags
& SET_FLAGS
) | RD4(dst
) | RN4(arg1
) | RM4(arg2
));
882 return SLJIT_SUCCESS
;
888 #define WORD_SIZE 0x00
889 #define BYTE_SIZE 0x04
890 #define HALF_SIZE 0x08
893 #define IS_WORD_SIZE(flags) (!((flags) & (BYTE_SIZE | HALF_SIZE)))
894 #define ALIGN_CHECK(argw, imm, shift) (!((argw) & ~((imm) << (shift))))
911 static const sljit_ins sljit_mem16
[12] = {
912 /* w u l */ 0x5800 /* ldr */,
913 /* w u s */ 0x5000 /* str */,
914 /* w s l */ 0x5800 /* ldr */,
915 /* w s s */ 0x5000 /* str */,
917 /* b u l */ 0x5c00 /* ldrb */,
918 /* b u s */ 0x5400 /* strb */,
919 /* b s l */ 0x5600 /* ldrsb */,
920 /* b s s */ 0x5400 /* strb */,
922 /* h u l */ 0x5a00 /* ldrh */,
923 /* h u s */ 0x5200 /* strh */,
924 /* h s l */ 0x5e00 /* ldrsh */,
925 /* h s s */ 0x5200 /* strh */,
928 static const sljit_ins sljit_mem16_imm5
[12] = {
929 /* w u l */ 0x6800 /* ldr imm5 */,
930 /* w u s */ 0x6000 /* str imm5 */,
931 /* w s l */ 0x6800 /* ldr imm5 */,
932 /* w s s */ 0x6000 /* str imm5 */,
934 /* b u l */ 0x7800 /* ldrb imm5 */,
935 /* b u s */ 0x7000 /* strb imm5 */,
936 /* b s l */ 0x0000 /* not allowed */,
937 /* b s s */ 0x7000 /* strb imm5 */,
939 /* h u l */ 0x8800 /* ldrh imm5 */,
940 /* h u s */ 0x8000 /* strh imm5 */,
941 /* h s l */ 0x0000 /* not allowed */,
942 /* h s s */ 0x8000 /* strh imm5 */,
945 #define MEM_IMM8 0xc00
946 #define MEM_IMM12 0x800000
947 static const sljit_ins sljit_mem32
[13] = {
948 /* w u l */ 0xf8500000 /* ldr.w */,
949 /* w u s */ 0xf8400000 /* str.w */,
950 /* w s l */ 0xf8500000 /* ldr.w */,
951 /* w s s */ 0xf8400000 /* str.w */,
953 /* b u l */ 0xf8100000 /* ldrb.w */,
954 /* b u s */ 0xf8000000 /* strb.w */,
955 /* b s l */ 0xf9100000 /* ldrsb.w */,
956 /* b s s */ 0xf8000000 /* strb.w */,
958 /* h u l */ 0xf8300000 /* ldrh.w */,
959 /* h u s */ 0xf8200000 /* strsh.w */,
960 /* h s l */ 0xf9300000 /* ldrsh.w */,
961 /* h s s */ 0xf8200000 /* strsh.w */,
963 /* p u l */ 0xf8100000 /* pld */,
966 /* Helper function. Dst should be reg + value, using at most 1 instruction, flags does not set. */
967 static sljit_s32
emit_set_delta(struct sljit_compiler
*compiler
, sljit_s32 dst
, sljit_s32 reg
, sljit_sw value
)
973 return push_inst32(compiler
, ADDWI
| RD4(dst
) | RN4(reg
) | IMM12(value
));
974 imm
= get_imm((sljit_uw
)value
);
975 if (imm
!= INVALID_IMM
)
976 return push_inst32(compiler
, ADD_WI
| RD4(dst
) | RN4(reg
) | imm
);
981 return push_inst32(compiler
, SUBWI
| RD4(dst
) | RN4(reg
) | IMM12(value
));
982 imm
= get_imm((sljit_uw
)value
);
983 if (imm
!= INVALID_IMM
)
984 return push_inst32(compiler
, SUB_WI
| RD4(dst
) | RN4(reg
) | imm
);
986 return SLJIT_ERR_UNSUPPORTED
;
989 static SLJIT_INLINE sljit_s32
emit_op_mem(struct sljit_compiler
*compiler
, sljit_s32 flags
, sljit_s32 reg
,
990 sljit_s32 arg
, sljit_sw argw
, sljit_s32 tmp_reg
)
995 SLJIT_ASSERT(arg
& SLJIT_MEM
);
996 SLJIT_ASSERT((arg
& REG_MASK
) != tmp_reg
|| (arg
== SLJIT_MEM1(tmp_reg
) && argw
>= -0xff && argw
<= 0xfff));
998 if (SLJIT_UNLIKELY(!(arg
& REG_MASK
))) {
999 tmp
= get_imm((sljit_uw
)argw
& ~(sljit_uw
)0xfff);
1000 if (tmp
!= INVALID_IMM
) {
1001 FAIL_IF(push_inst32(compiler
, MOV_WI
| RD4(tmp_reg
) | tmp
));
1002 return push_inst32(compiler
, sljit_mem32
[flags
] | MEM_IMM12
| RT4(reg
) | RN4(tmp_reg
) | (argw
& 0xfff));
1005 FAIL_IF(load_immediate(compiler
, tmp_reg
, (sljit_uw
)argw
));
1006 if (IS_2_LO_REGS(reg
, tmp_reg
) && sljit_mem16_imm5
[flags
])
1007 return push_inst16(compiler
, sljit_mem16_imm5
[flags
] | RD3(reg
) | RN3(tmp_reg
));
1008 return push_inst32(compiler
, sljit_mem32
[flags
] | MEM_IMM12
| RT4(reg
) | RN4(tmp_reg
));
1011 if (SLJIT_UNLIKELY(arg
& OFFS_REG_MASK
)) {
1013 other_r
= OFFS_REG(arg
);
1016 if (!argw
&& IS_3_LO_REGS(reg
, arg
, other_r
))
1017 return push_inst16(compiler
, sljit_mem16
[flags
] | RD3(reg
) | RN3(arg
) | RM3(other_r
));
1018 return push_inst32(compiler
, sljit_mem32
[flags
] | RT4(reg
) | RN4(arg
) | RM4(other_r
) | ((sljit_ins
)argw
<< 4));
1024 tmp
= get_imm((sljit_uw
)(argw
& ~0xfff));
1025 if (tmp
!= INVALID_IMM
) {
1026 push_inst32(compiler
, ADD_WI
| RD4(tmp_reg
) | RN4(arg
) | tmp
);
1028 argw
= argw
& 0xfff;
1031 else if (argw
< -0xff) {
1032 tmp
= get_imm((sljit_uw
)(-argw
& ~0xff));
1033 if (tmp
!= INVALID_IMM
) {
1034 push_inst32(compiler
, SUB_WI
| RD4(tmp_reg
) | RN4(arg
) | tmp
);
1036 argw
= -(-argw
& 0xff);
1040 /* 16 bit instruction forms. */
1041 if (IS_2_LO_REGS(reg
, arg
) && sljit_mem16_imm5
[flags
]) {
1043 if (IS_WORD_SIZE(flags
)) {
1044 if (ALIGN_CHECK(argw
, 0x1f, 2))
1047 else if (flags
& BYTE_SIZE
)
1049 if (ALIGN_CHECK(argw
, 0x1f, 0))
1053 SLJIT_ASSERT(flags
& HALF_SIZE
);
1054 if (ALIGN_CHECK(argw
, 0x1f, 1))
1059 return push_inst16(compiler
, sljit_mem16_imm5
[flags
] | RD3(reg
) | RN3(arg
) | ((sljit_ins
)argw
<< (6 - tmp
)));
1061 else if (SLJIT_UNLIKELY(arg
== SLJIT_SP
) && IS_WORD_SIZE(flags
) && ALIGN_CHECK(argw
, 0xff, 2) && reg_map
[reg
] <= 7) {
1062 /* SP based immediate. */
1063 return push_inst16(compiler
, STR_SP
| (sljit_ins
)((flags
& STORE
) ? 0 : 0x800) | RDN3(reg
) | ((sljit_ins
)argw
>> 2));
1066 if (argw
>= 0 && argw
<= 0xfff)
1067 return push_inst32(compiler
, sljit_mem32
[flags
] | MEM_IMM12
| RT4(reg
) | RN4(arg
) | (sljit_ins
)argw
);
1068 else if (argw
< 0 && argw
>= -0xff)
1069 return push_inst32(compiler
, sljit_mem32
[flags
] | MEM_IMM8
| RT4(reg
) | RN4(arg
) | (sljit_ins
)-argw
);
1071 SLJIT_ASSERT(arg
!= tmp_reg
);
1073 FAIL_IF(load_immediate(compiler
, tmp_reg
, (sljit_uw
)argw
));
1074 if (IS_3_LO_REGS(reg
, arg
, tmp_reg
))
1075 return push_inst16(compiler
, sljit_mem16
[flags
] | RD3(reg
) | RN3(arg
) | RM3(tmp_reg
));
1076 return push_inst32(compiler
, sljit_mem32
[flags
] | RT4(reg
) | RN4(arg
) | RM4(tmp_reg
));
1082 /* --------------------------------------------------------------------- */
1084 /* --------------------------------------------------------------------- */
1086 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_enter(struct sljit_compiler
*compiler
,
1087 sljit_s32 options
, sljit_s32 arg_types
, sljit_s32 scratches
, sljit_s32 saveds
,
1088 sljit_s32 fscratches
, sljit_s32 fsaveds
, sljit_s32 local_size
)
1090 sljit_s32 size
, i
, tmp
, word_arg_count
;
1091 sljit_s32 saved_arg_count
= SLJIT_KEPT_SAVEDS_COUNT(options
);
1095 sljit_u32 float_arg_count
;
1097 sljit_u32 old_offset
, f32_offset
;
1099 sljit_u32
*remap_ptr
= remap
;
1103 CHECK(check_sljit_emit_enter(compiler
, options
, arg_types
, scratches
, saveds
, fscratches
, fsaveds
, local_size
));
1104 set_emit_enter(compiler
, options
, arg_types
, scratches
, saveds
, fscratches
, fsaveds
, local_size
);
1106 tmp
= SLJIT_S0
- saveds
;
1107 for (i
= SLJIT_S0
- saved_arg_count
; i
> tmp
; i
--)
1108 imm
|= (sljit_uw
)1 << reg_map
[i
];
1110 for (i
= scratches
; i
>= SLJIT_FIRST_SAVED_REG
; i
--)
1111 imm
|= (sljit_uw
)1 << reg_map
[i
];
1113 /* At least two registers must be set for PUSH_W and one for PUSH instruction. */
1114 FAIL_IF((imm
& 0xff00)
1115 ? push_inst32(compiler
, PUSH_W
| (1 << 14) | imm
)
1116 : push_inst16(compiler
, PUSH
| (1 << 8) | imm
));
1118 /* Stack must be aligned to 8 bytes: (LR, R4) */
1119 size
= GET_SAVED_REGISTERS_SIZE(scratches
, saveds
- saved_arg_count
, 1);
1121 if (fsaveds
> 0 || fscratches
>= SLJIT_FIRST_SAVED_FLOAT_REG
) {
1122 if ((size
& SSIZE_OF(sw
)) != 0) {
1123 FAIL_IF(push_inst16(compiler
, SUB_SP_I
| (sizeof(sljit_sw
) >> 2)));
1124 size
+= SSIZE_OF(sw
);
1127 if (fsaveds
+ fscratches
>= SLJIT_NUMBER_OF_FLOAT_REGISTERS
) {
1128 FAIL_IF(push_inst32(compiler
, VPUSH
| DD4(SLJIT_FS0
) | ((sljit_uw
)SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS
<< 1)));
1131 FAIL_IF(push_inst32(compiler
, VPUSH
| DD4(SLJIT_FS0
) | ((sljit_uw
)fsaveds
<< 1)));
1132 if (fscratches
>= SLJIT_FIRST_SAVED_FLOAT_REG
)
1133 FAIL_IF(push_inst32(compiler
, VPUSH
| DD4(fscratches
) | ((sljit_uw
)(fscratches
- (SLJIT_FIRST_SAVED_FLOAT_REG
- 1)) << 1)));
1137 local_size
= ((size
+ local_size
+ 0x7) & ~0x7) - size
;
1138 compiler
->local_size
= local_size
;
1140 arg_types
>>= SLJIT_ARG_SHIFT
;
1143 SLJIT_COMPILE_ASSERT(SLJIT_FR0
== 1, float_register_index_start
);
1146 float_arg_count
= 0;
1149 switch (arg_types
& SLJIT_ARG_MASK
) {
1150 case SLJIT_ARG_TYPE_F64
:
1152 offset
+= sizeof(sljit_sw
);
1154 if (offset
< 4 * sizeof(sljit_sw
))
1155 FAIL_IF(push_inst32(compiler
, VMOV2
| (offset
<< 10) | ((offset
+ sizeof(sljit_sw
)) << 14) | float_arg_count
));
1157 FAIL_IF(push_inst32(compiler
, VLDR_F32
| 0x800100 | RN4(SLJIT_SP
)
1158 | (float_arg_count
<< 12) | ((offset
+ (sljit_uw
)size
- 4 * sizeof(sljit_sw
)) >> 2)));
1160 offset
+= sizeof(sljit_f64
) - sizeof(sljit_sw
);
1162 case SLJIT_ARG_TYPE_F32
:
1163 if (offset
< 4 * sizeof(sljit_sw
))
1164 FAIL_IF(push_inst32(compiler
, VMOV
| (float_arg_count
<< 16) | (offset
<< 10)));
1166 FAIL_IF(push_inst32(compiler
, VLDR_F32
| 0x800000 | RN4(SLJIT_SP
)
1167 | (float_arg_count
<< 12) | ((offset
+ (sljit_uw
)size
- 4 * sizeof(sljit_sw
)) >> 2)));
1173 if (!(arg_types
& SLJIT_ARG_TYPE_SCRATCH_REG
)) {
1174 tmp
= SLJIT_S0
- saved_arg_count
;
1176 } else if (word_arg_count
- 1 != (sljit_s32
)(offset
>> 2))
1177 tmp
= word_arg_count
;
1181 if (offset
< 4 * sizeof(sljit_sw
))
1182 FAIL_IF(push_inst16(compiler
, MOV
| ((sljit_ins
)reg_map
[tmp
] & 0x7) | (((sljit_ins
)reg_map
[tmp
] & 0x8) << 4) | (offset
<< 1)));
1183 else if (reg_map
[tmp
] <= 7)
1184 FAIL_IF(push_inst16(compiler
, LDR_SP
| RDN3(tmp
)
1185 | ((offset
+ (sljit_uw
)size
- 4 * sizeof(sljit_sw
)) >> 2)));
1187 FAIL_IF(push_inst32(compiler
, LDR
| RT4(tmp
) | RN4(SLJIT_SP
)
1188 | ((offset
+ (sljit_uw
)size
- 4 * sizeof(sljit_sw
)))));
1192 offset
+= sizeof(sljit_sw
);
1193 arg_types
>>= SLJIT_ARG_SHIFT
;
1196 compiler
->args_size
= offset
;
1199 old_offset
= SLJIT_FR0
;
1203 switch (arg_types
& SLJIT_ARG_MASK
) {
1204 case SLJIT_ARG_TYPE_F64
:
1205 if (offset
!= old_offset
)
1206 *remap_ptr
++ = VMOV_F32
| SLJIT_32
| DD4(offset
) | DM4(old_offset
);
1210 case SLJIT_ARG_TYPE_F32
:
1211 if (f32_offset
!= 0) {
1212 *remap_ptr
++ = VMOV_F32
| 0x20 | DD4(offset
) | DM4(f32_offset
);
1215 if (offset
!= old_offset
)
1216 *remap_ptr
++ = VMOV_F32
| DD4(offset
) | DM4(old_offset
);
1217 f32_offset
= old_offset
;
1223 if (!(arg_types
& SLJIT_ARG_TYPE_SCRATCH_REG
)) {
1224 FAIL_IF(push_inst16(compiler
, MOV
| SET_REGS44(SLJIT_S0
- saved_arg_count
, SLJIT_R0
+ word_arg_count
)));
1231 arg_types
>>= SLJIT_ARG_SHIFT
;
1234 SLJIT_ASSERT((sljit_uw
)(remap_ptr
- remap
) <= sizeof(remap
));
1236 while (remap_ptr
> remap
)
1237 FAIL_IF(push_inst32(compiler
, *(--remap_ptr
)));
1241 if (local_size
>= 4096) {
1242 imm
= get_imm(4096);
1243 SLJIT_ASSERT(imm
!= INVALID_IMM
);
1245 FAIL_IF(push_inst32(compiler
, SUB_WI
| RD4(SLJIT_SP
) | RN4(SLJIT_SP
) | imm
));
1247 if (local_size
< 4 * 4096) {
1248 if (local_size
> 2 * 4096) {
1249 if (local_size
> 3 * 4096) {
1250 FAIL_IF(push_inst32(compiler
, LDRI
| 0x400 | RT4(TMP_REG1
) | RN4(SLJIT_SP
)));
1251 FAIL_IF(push_inst32(compiler
, SUB_WI
| RD4(SLJIT_SP
) | RN4(SLJIT_SP
) | imm
));
1254 FAIL_IF(push_inst32(compiler
, LDRI
| 0x400 | RT4(TMP_REG1
) | RN4(SLJIT_SP
)));
1255 FAIL_IF(push_inst32(compiler
, SUB_WI
| RD4(SLJIT_SP
) | RN4(SLJIT_SP
) | imm
));
1258 FAIL_IF(load_immediate(compiler
, TMP_REG2
, ((sljit_uw
)local_size
>> 12) - 1));
1259 FAIL_IF(push_inst32(compiler
, LDRI
| 0x400 | RT4(TMP_REG1
) | RN4(SLJIT_SP
)));
1260 FAIL_IF(push_inst32(compiler
, SUB_WI
| RD4(SLJIT_SP
) | RN4(SLJIT_SP
) | imm
));
1261 FAIL_IF(push_inst32(compiler
, SUB_WI
| SET_FLAGS
| RD4(TMP_REG2
) | RN4(TMP_REG2
) | 1));
1262 FAIL_IF(push_inst16(compiler
, BCC
| (0x1 << 8) /* not-equal */ | (-8 & 0xff)));
1265 FAIL_IF(push_inst32(compiler
, LDRI
| 0x400 | RT4(TMP_REG1
) | RN4(SLJIT_SP
)));
1266 local_size
&= 0xfff;
1269 if (local_size
>= 256) {
1270 SLJIT_ASSERT(local_size
< 4096);
1272 if (local_size
<= (127 << 2))
1273 FAIL_IF(push_inst16(compiler
, SUB_SP_I
| ((sljit_uw
)local_size
>> 2)));
1275 FAIL_IF(emit_op_imm(compiler
, SLJIT_SUB
| ARG2_IMM
, SLJIT_SP
, SLJIT_SP
, (sljit_uw
)local_size
));
1277 FAIL_IF(push_inst32(compiler
, LDRI
| 0x400 | RT4(TMP_REG1
) | RN4(SLJIT_SP
)));
1278 } else if (local_size
> 0)
1279 FAIL_IF(push_inst32(compiler
, LDRI
| 0x500 | RT4(TMP_REG1
) | RN4(SLJIT_SP
) | (sljit_uw
)local_size
));
1281 if (local_size
> 0) {
1282 if (local_size
<= (127 << 2))
1283 FAIL_IF(push_inst16(compiler
, SUB_SP_I
| ((sljit_uw
)local_size
>> 2)));
1285 FAIL_IF(emit_op_imm(compiler
, SLJIT_SUB
| ARG2_IMM
, SLJIT_SP
, SLJIT_SP
, (sljit_uw
)local_size
));
1289 return SLJIT_SUCCESS
;
1292 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_set_context(struct sljit_compiler
*compiler
,
1293 sljit_s32 options
, sljit_s32 arg_types
, sljit_s32 scratches
, sljit_s32 saveds
,
1294 sljit_s32 fscratches
, sljit_s32 fsaveds
, sljit_s32 local_size
)
1299 CHECK(check_sljit_set_context(compiler
, options
, arg_types
, scratches
, saveds
, fscratches
, fsaveds
, local_size
));
1300 set_set_context(compiler
, options
, arg_types
, scratches
, saveds
, fscratches
, fsaveds
, local_size
);
1302 size
= GET_SAVED_REGISTERS_SIZE(scratches
, saveds
- SLJIT_KEPT_SAVEDS_COUNT(options
), 1);
1304 if ((size
& SSIZE_OF(sw
)) != 0 && (fsaveds
> 0 || fscratches
>= SLJIT_FIRST_SAVED_FLOAT_REG
))
1305 size
+= SSIZE_OF(sw
);
1307 compiler
->local_size
= ((size
+ local_size
+ 0x7) & ~0x7) - size
;
1308 return SLJIT_SUCCESS
;
1311 static sljit_s32
emit_add_sp(struct sljit_compiler
*compiler
, sljit_uw imm
)
1315 /* The TMP_REG1 register must keep its value. */
1316 if (imm
<= (127u << 2))
1317 return push_inst16(compiler
, ADD_SP_I
| (imm
>> 2));
1320 return push_inst32(compiler
, ADDWI
| RD4(SLJIT_SP
) | RN4(SLJIT_SP
) | IMM12(imm
));
1322 imm2
= get_imm(imm
);
1324 if (imm2
!= INVALID_IMM
)
1325 return push_inst32(compiler
, ADD_WI
| RD4(SLJIT_SP
) | RN4(SLJIT_SP
) | imm2
);
1327 FAIL_IF(load_immediate(compiler
, TMP_REG2
, imm
));
1328 return push_inst16(compiler
, ADD_SP
| RN3(TMP_REG2
));
1331 static sljit_s32
emit_stack_frame_release(struct sljit_compiler
*compiler
, sljit_s32 frame_size
)
1333 sljit_s32 local_size
, fscratches
, fsaveds
, i
, tmp
;
1334 sljit_s32 saveds_restore_start
= SLJIT_S0
- SLJIT_KEPT_SAVEDS_COUNT(compiler
->options
);
1335 sljit_s32 lr_dst
= TMP_PC
;
1338 SLJIT_ASSERT(reg_map
[TMP_REG2
] == 14 && frame_size
<= 128);
1340 local_size
= compiler
->local_size
;
1341 fscratches
= compiler
->fscratches
;
1342 fsaveds
= compiler
->fsaveds
;
1344 if (fsaveds
> 0 || fscratches
>= SLJIT_FIRST_SAVED_FLOAT_REG
) {
1346 FAIL_IF(emit_add_sp(compiler
, (sljit_uw
)local_size
));
1348 if (fsaveds
+ fscratches
>= SLJIT_NUMBER_OF_FLOAT_REGISTERS
) {
1349 FAIL_IF(push_inst32(compiler
, VPOP
| DD4(SLJIT_FS0
) | ((sljit_uw
)SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS
<< 1)));
1351 if (fscratches
>= SLJIT_FIRST_SAVED_FLOAT_REG
)
1352 FAIL_IF(push_inst32(compiler
, VPOP
| DD4(fscratches
) | ((sljit_uw
)(fscratches
- (SLJIT_FIRST_SAVED_FLOAT_REG
- 1)) << 1)));
1354 FAIL_IF(push_inst32(compiler
, VPOP
| DD4(SLJIT_FS0
) | ((sljit_uw
)fsaveds
<< 1)));
1357 local_size
= GET_SAVED_REGISTERS_SIZE(compiler
->scratches
, compiler
->saveds
, 1) & 0x7;
1360 if (frame_size
< 0) {
1363 } else if (frame_size
> 0)
1367 tmp
= SLJIT_S0
- compiler
->saveds
;
1368 if (saveds_restore_start
!= tmp
) {
1369 for (i
= saveds_restore_start
; i
> tmp
; i
--)
1370 reg_list
|= (sljit_uw
)1 << reg_map
[i
];
1372 saveds_restore_start
= 0;
1374 for (i
= compiler
->scratches
; i
>= SLJIT_FIRST_SAVED_REG
; i
--)
1375 reg_list
|= (sljit_uw
)1 << reg_map
[i
];
1377 if (lr_dst
== 0 && (reg_list
& (reg_list
- 1)) == 0) {
1378 /* The local_size does not include the saved registers. */
1379 local_size
+= SSIZE_OF(sw
);
1382 local_size
+= SSIZE_OF(sw
);
1384 if (frame_size
> local_size
)
1385 FAIL_IF(push_inst16(compiler
, SUB_SP_I
| ((sljit_uw
)(frame_size
- local_size
) >> 2)));
1386 else if (frame_size
< local_size
)
1387 FAIL_IF(emit_add_sp(compiler
, (sljit_uw
)(local_size
- frame_size
)));
1390 return SLJIT_SUCCESS
;
1392 if (saveds_restore_start
!= 0) {
1393 SLJIT_ASSERT(reg_list
== ((sljit_uw
)1 << reg_map
[saveds_restore_start
]));
1394 lr_dst
= saveds_restore_start
;
1396 SLJIT_ASSERT(reg_list
== ((sljit_uw
)1 << reg_map
[SLJIT_FIRST_SAVED_REG
]));
1397 lr_dst
= SLJIT_FIRST_SAVED_REG
;
1400 frame_size
-= 2 * SSIZE_OF(sw
);
1402 if (reg_map
[lr_dst
] <= 7)
1403 return push_inst16(compiler
, STR_SP
| 0x800 | RDN3(lr_dst
) | (sljit_uw
)(frame_size
>> 2));
1405 return push_inst32(compiler
, LDR
| RT4(lr_dst
) | RN4(SLJIT_SP
) | (sljit_uw
)frame_size
);
1409 FAIL_IF(emit_add_sp(compiler
, (sljit_uw
)local_size
));
1411 if (!(reg_list
& 0xff00) && lr_dst
!= TMP_REG2
) {
1412 if (lr_dst
== TMP_PC
)
1413 reg_list
|= 1u << 8;
1415 /* At least one register must be set for POP instruction. */
1416 SLJIT_ASSERT(reg_list
!= 0);
1418 FAIL_IF(push_inst16(compiler
, POP
| reg_list
));
1422 return push_inst32(compiler
, 0xf85d0b04 | RT4(lr_dst
));
1424 reg_list
|= (sljit_uw
)1 << reg_map
[lr_dst
];
1427 /* At least two registers must be set for POP_W instruction. */
1428 SLJIT_ASSERT((reg_list
& (reg_list
- 1)) != 0);
1430 FAIL_IF(push_inst32(compiler
, POP_W
| reg_list
));
1434 return push_inst16(compiler
, SUB_SP_I
| (((sljit_uw
)frame_size
- sizeof(sljit_sw
)) >> 2));
1435 return SLJIT_SUCCESS
;
1438 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_return_void(struct sljit_compiler
*compiler
)
1441 CHECK(check_sljit_emit_return_void(compiler
));
1443 return emit_stack_frame_release(compiler
, 0);
1446 /* --------------------------------------------------------------------- */
1448 /* --------------------------------------------------------------------- */
1450 #if !(defined __ARM_FEATURE_IDIV) && !(defined __ARM_ARCH_EXT_IDIV__)
1457 extern unsigned long long __rt_udiv(unsigned int denominator
, unsigned int numerator
);
1458 extern long long __rt_sdiv(int denominator
, int numerator
);
1459 #elif defined(__GNUC__)
1460 extern unsigned int __aeabi_uidivmod(unsigned int numerator
, int unsigned denominator
);
1461 extern int __aeabi_idivmod(int numerator
, int denominator
);
1463 #error "Software divmod functions are needed"
1470 #endif /* !__ARM_FEATURE_IDIV && !__ARM_ARCH_EXT_IDIV__ */
1472 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_op0(struct sljit_compiler
*compiler
, sljit_s32 op
)
1474 #if !(defined __ARM_FEATURE_IDIV) && !(defined __ARM_ARCH_EXT_IDIV__)
1475 sljit_uw saved_reg_list
[3];
1476 sljit_uw saved_reg_count
;
1480 CHECK(check_sljit_emit_op0(compiler
, op
));
1482 op
= GET_OPCODE(op
);
1484 case SLJIT_BREAKPOINT
:
1485 return push_inst16(compiler
, BKPT
);
1487 return push_inst16(compiler
, NOP
);
1490 return push_inst32(compiler
, (op
== SLJIT_LMUL_UW
? UMULL
: SMULL
)
1491 | RD4(SLJIT_R1
) | RT4(SLJIT_R0
) | RN4(SLJIT_R0
) | RM4(SLJIT_R1
));
1492 #if (defined __ARM_FEATURE_IDIV) || (defined __ARM_ARCH_EXT_IDIV__)
1493 case SLJIT_DIVMOD_UW
:
1494 case SLJIT_DIVMOD_SW
:
1495 FAIL_IF(push_inst16(compiler
, MOV
| SET_REGS44(TMP_REG1
, SLJIT_R0
)));
1496 FAIL_IF(push_inst32(compiler
, (op
== SLJIT_DIVMOD_UW
? UDIV
: SDIV
) | RD4(SLJIT_R0
) | RN4(SLJIT_R0
) | RM4(SLJIT_R1
)));
1497 FAIL_IF(push_inst32(compiler
, MUL
| RD4(SLJIT_R1
) | RN4(SLJIT_R0
) | RM4(SLJIT_R1
)));
1498 return push_inst32(compiler
, SUB_W
| RD4(SLJIT_R1
) | RN4(TMP_REG1
) | RM4(SLJIT_R1
));
1501 return push_inst32(compiler
, (op
== SLJIT_DIV_UW
? UDIV
: SDIV
) | RD4(SLJIT_R0
) | RN4(SLJIT_R0
) | RM4(SLJIT_R1
));
1502 #else /* !__ARM_FEATURE_IDIV && !__ARM_ARCH_EXT_IDIV__ */
1503 case SLJIT_DIVMOD_UW
:
1504 case SLJIT_DIVMOD_SW
:
1507 SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW
& 0x2) == 0 && SLJIT_DIV_UW
- 0x2 == SLJIT_DIVMOD_UW
, bad_div_opcode_assignments
);
1508 SLJIT_ASSERT(reg_map
[2] == 1 && reg_map
[3] == 2 && reg_map
[4] == 3);
1510 saved_reg_count
= 0;
1511 if (compiler
->scratches
>= 4)
1512 saved_reg_list
[saved_reg_count
++] = 3;
1513 if (compiler
->scratches
>= 3)
1514 saved_reg_list
[saved_reg_count
++] = 2;
1515 if (op
>= SLJIT_DIV_UW
)
1516 saved_reg_list
[saved_reg_count
++] = 1;
1518 if (saved_reg_count
> 0) {
1519 FAIL_IF(push_inst32(compiler
, 0xf84d0d00 | (saved_reg_count
>= 3 ? 16 : 8)
1520 | (saved_reg_list
[0] << 12) /* str rX, [sp, #-8/-16]! */));
1521 if (saved_reg_count
>= 2) {
1522 SLJIT_ASSERT(saved_reg_list
[1] < 8);
1523 FAIL_IF(push_inst16(compiler
, 0x9001 | (saved_reg_list
[1] << 8) /* str rX, [sp, #4] */));
1525 if (saved_reg_count
>= 3) {
1526 SLJIT_ASSERT(saved_reg_list
[2] < 8);
1527 FAIL_IF(push_inst16(compiler
, 0x9002 | (saved_reg_list
[2] << 8) /* str rX, [sp, #8] */));
1532 FAIL_IF(push_inst16(compiler
, MOV
| SET_REGS44(TMP_REG1
, SLJIT_R0
)));
1533 FAIL_IF(push_inst16(compiler
, MOV
| SET_REGS44(SLJIT_R0
, SLJIT_R1
)));
1534 FAIL_IF(push_inst16(compiler
, MOV
| SET_REGS44(SLJIT_R1
, TMP_REG1
)));
1535 FAIL_IF(sljit_emit_ijump(compiler
, SLJIT_FAST_CALL
, SLJIT_IMM
,
1536 ((op
| 0x2) == SLJIT_DIV_UW
? SLJIT_FUNC_ADDR(__rt_udiv
) : SLJIT_FUNC_ADDR(__rt_sdiv
))));
1537 #elif defined(__GNUC__)
1538 FAIL_IF(sljit_emit_ijump(compiler
, SLJIT_FAST_CALL
, SLJIT_IMM
,
1539 ((op
| 0x2) == SLJIT_DIV_UW
? SLJIT_FUNC_ADDR(__aeabi_uidivmod
) : SLJIT_FUNC_ADDR(__aeabi_idivmod
))));
1541 #error "Software divmod functions are needed"
1544 if (saved_reg_count
> 0) {
1545 if (saved_reg_count
>= 3) {
1546 SLJIT_ASSERT(saved_reg_list
[2] < 8);
1547 FAIL_IF(push_inst16(compiler
, 0x9802 | (saved_reg_list
[2] << 8) /* ldr rX, [sp, #8] */));
1549 if (saved_reg_count
>= 2) {
1550 SLJIT_ASSERT(saved_reg_list
[1] < 8);
1551 FAIL_IF(push_inst16(compiler
, 0x9801 | (saved_reg_list
[1] << 8) /* ldr rX, [sp, #4] */));
1553 return push_inst32(compiler
, 0xf85d0b00 | (saved_reg_count
>= 3 ? 16 : 8)
1554 | (saved_reg_list
[0] << 12) /* ldr rX, [sp], #8/16 */);
1556 return SLJIT_SUCCESS
;
1557 #endif /* __ARM_FEATURE_IDIV || __ARM_ARCH_EXT_IDIV__ */
1559 case SLJIT_SKIP_FRAMES_BEFORE_RETURN
:
1560 return SLJIT_SUCCESS
;
1563 return SLJIT_SUCCESS
;
1566 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_op1(struct sljit_compiler
*compiler
, sljit_s32 op
,
1567 sljit_s32 dst
, sljit_sw dstw
,
1568 sljit_s32 src
, sljit_sw srcw
)
1570 sljit_s32 dst_r
, flags
;
1571 sljit_s32 op_flags
= GET_ALL_FLAGS(op
);
1574 CHECK(check_sljit_emit_op1(compiler
, op
, dst
, dstw
, src
, srcw
));
1575 ADJUST_LOCAL_OFFSET(dst
, dstw
);
1576 ADJUST_LOCAL_OFFSET(src
, srcw
);
1578 dst_r
= FAST_IS_REG(dst
) ? dst
: TMP_REG1
;
1580 op
= GET_OPCODE(op
);
1581 if (op
>= SLJIT_MOV
&& op
<= SLJIT_MOV_P
) {
1592 if (src
& SLJIT_IMM
)
1593 srcw
= (sljit_u8
)srcw
;
1596 flags
= BYTE_SIZE
| SIGNED
;
1597 if (src
& SLJIT_IMM
)
1598 srcw
= (sljit_s8
)srcw
;
1602 if (src
& SLJIT_IMM
)
1603 srcw
= (sljit_u16
)srcw
;
1606 flags
= HALF_SIZE
| SIGNED
;
1607 if (src
& SLJIT_IMM
)
1608 srcw
= (sljit_s16
)srcw
;
1611 SLJIT_UNREACHABLE();
1616 if (src
& SLJIT_IMM
)
1617 FAIL_IF(emit_op_imm(compiler
, SLJIT_MOV
| ARG2_IMM
, dst_r
, TMP_REG2
, (sljit_uw
)srcw
));
1618 else if (src
& SLJIT_MEM
) {
1619 FAIL_IF(emit_op_mem(compiler
, flags
, dst_r
, src
, srcw
, TMP_REG1
));
1621 if (dst_r
!= TMP_REG1
)
1622 return emit_op_imm(compiler
, op
, dst_r
, TMP_REG2
, (sljit_uw
)src
);
1626 if (!(dst
& SLJIT_MEM
))
1627 return SLJIT_SUCCESS
;
1629 return emit_op_mem(compiler
, flags
| STORE
, dst_r
, dst
, dstw
, TMP_REG2
);
1632 flags
= HAS_FLAGS(op_flags
) ? SET_FLAGS
: 0;
1634 if (src
& SLJIT_MEM
) {
1635 FAIL_IF(emit_op_mem(compiler
, WORD_SIZE
, TMP_REG1
, src
, srcw
, TMP_REG1
));
1639 emit_op_imm(compiler
, flags
| op
, dst_r
, TMP_REG2
, (sljit_uw
)src
);
1641 if (SLJIT_UNLIKELY(dst
& SLJIT_MEM
))
1642 return emit_op_mem(compiler
, flags
| STORE
, dst_r
, dst
, dstw
, TMP_REG2
);
1643 return SLJIT_SUCCESS
;
1646 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_op2(struct sljit_compiler
*compiler
, sljit_s32 op
,
1647 sljit_s32 dst
, sljit_sw dstw
,
1648 sljit_s32 src1
, sljit_sw src1w
,
1649 sljit_s32 src2
, sljit_sw src2w
)
1651 sljit_s32 dst_reg
, flags
, src2_reg
;
1654 CHECK(check_sljit_emit_op2(compiler
, op
, 0, dst
, dstw
, src1
, src1w
, src2
, src2w
));
1655 ADJUST_LOCAL_OFFSET(dst
, dstw
);
1656 ADJUST_LOCAL_OFFSET(src1
, src1w
);
1657 ADJUST_LOCAL_OFFSET(src2
, src2w
);
1659 dst_reg
= FAST_IS_REG(dst
) ? dst
: TMP_REG1
;
1660 flags
= HAS_FLAGS(op
) ? SET_FLAGS
: 0;
1662 if (dst
== TMP_REG1
)
1663 flags
|= UNUSED_RETURN
;
1665 if (src1
& SLJIT_IMM
)
1667 else if (src1
& SLJIT_MEM
) {
1668 emit_op_mem(compiler
, WORD_SIZE
, TMP_REG1
, src1
, src1w
, TMP_REG1
);
1674 if (src2
& SLJIT_IMM
)
1676 else if (src2
& SLJIT_MEM
) {
1677 src2_reg
= (!(flags
& ARG1_IMM
) && (src1w
== TMP_REG1
)) ? TMP_REG2
: TMP_REG1
;
1678 emit_op_mem(compiler
, WORD_SIZE
, src2_reg
, src2
, src2w
, src2_reg
);
1684 emit_op_imm(compiler
, flags
| GET_OPCODE(op
), dst_reg
, (sljit_uw
)src1w
, (sljit_uw
)src2w
);
1686 if (!(dst
& SLJIT_MEM
))
1687 return SLJIT_SUCCESS
;
1688 return emit_op_mem(compiler
, WORD_SIZE
| STORE
, dst_reg
, dst
, dstw
, TMP_REG2
);
1691 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_op2u(struct sljit_compiler
*compiler
, sljit_s32 op
,
1692 sljit_s32 src1
, sljit_sw src1w
,
1693 sljit_s32 src2
, sljit_sw src2w
)
1696 CHECK(check_sljit_emit_op2(compiler
, op
, 1, 0, 0, src1
, src1w
, src2
, src2w
));
1698 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
1699 || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
1700 compiler
->skip_checks
= 1;
1702 return sljit_emit_op2(compiler
, op
, TMP_REG1
, 0, src1
, src1w
, src2
, src2w
);
1705 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_op_src(struct sljit_compiler
*compiler
, sljit_s32 op
,
1706 sljit_s32 src
, sljit_sw srcw
)
1709 CHECK(check_sljit_emit_op_src(compiler
, op
, src
, srcw
));
1710 ADJUST_LOCAL_OFFSET(src
, srcw
);
1713 case SLJIT_FAST_RETURN
:
1714 SLJIT_ASSERT(reg_map
[TMP_REG2
] == 14);
1716 if (FAST_IS_REG(src
))
1717 FAIL_IF(push_inst16(compiler
, MOV
| SET_REGS44(TMP_REG2
, src
)));
1719 FAIL_IF(emit_op_mem(compiler
, WORD_SIZE
, TMP_REG2
, src
, srcw
, TMP_REG2
));
1721 return push_inst16(compiler
, BX
| RN3(TMP_REG2
));
1722 case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN
:
1723 return SLJIT_SUCCESS
;
1724 case SLJIT_PREFETCH_L1
:
1725 case SLJIT_PREFETCH_L2
:
1726 case SLJIT_PREFETCH_L3
:
1727 case SLJIT_PREFETCH_ONCE
:
1728 return emit_op_mem(compiler
, PRELOAD
, TMP_PC
, src
, srcw
, TMP_REG1
);
1731 return SLJIT_SUCCESS
;
1734 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_get_register_index(sljit_s32 reg
)
1736 CHECK_REG_INDEX(check_sljit_get_register_index(reg
));
1737 return reg_map
[reg
];
1740 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_get_float_register_index(sljit_s32 reg
)
1742 CHECK_REG_INDEX(check_sljit_get_float_register_index(reg
));
1743 return (freg_map
[reg
] << 1);
1746 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_op_custom(struct sljit_compiler
*compiler
,
1747 void *instruction
, sljit_u32 size
)
1750 CHECK(check_sljit_emit_op_custom(compiler
, instruction
, size
));
1753 return push_inst16(compiler
, *(sljit_u16
*)instruction
);
1754 return push_inst32(compiler
, *(sljit_ins
*)instruction
);
1757 /* --------------------------------------------------------------------- */
1758 /* Floating point operators */
1759 /* --------------------------------------------------------------------- */
1761 #define FPU_LOAD (1 << 20)
1763 static sljit_s32
emit_fop_mem(struct sljit_compiler
*compiler
, sljit_s32 flags
, sljit_s32 reg
, sljit_s32 arg
, sljit_sw argw
)
1766 sljit_ins inst
= VSTR_F32
| (flags
& (SLJIT_32
| FPU_LOAD
));
1768 SLJIT_ASSERT(arg
& SLJIT_MEM
);
1770 /* Fast loads and stores. */
1771 if (SLJIT_UNLIKELY(arg
& OFFS_REG_MASK
)) {
1772 FAIL_IF(push_inst32(compiler
, ADD_W
| RD4(TMP_REG1
) | RN4(arg
& REG_MASK
) | RM4(OFFS_REG(arg
)) | (((sljit_uw
)argw
& 0x3) << 6)));
1773 arg
= SLJIT_MEM
| TMP_REG1
;
1777 if ((arg
& REG_MASK
) && (argw
& 0x3) == 0) {
1778 if (!(argw
& ~0x3fc))
1779 return push_inst32(compiler
, inst
| 0x800000 | RN4(arg
& REG_MASK
) | DD4(reg
) | ((sljit_uw
)argw
>> 2));
1780 if (!(-argw
& ~0x3fc))
1781 return push_inst32(compiler
, inst
| RN4(arg
& REG_MASK
) | DD4(reg
) | ((sljit_uw
)-argw
>> 2));
1784 if (arg
& REG_MASK
) {
1785 if (emit_set_delta(compiler
, TMP_REG1
, arg
& REG_MASK
, argw
) != SLJIT_ERR_UNSUPPORTED
) {
1786 FAIL_IF(compiler
->error
);
1787 return push_inst32(compiler
, inst
| 0x800000 | RN4(TMP_REG1
) | DD4(reg
));
1790 imm
= get_imm((sljit_uw
)argw
& ~(sljit_uw
)0x3fc);
1791 if (imm
!= INVALID_IMM
) {
1792 FAIL_IF(push_inst32(compiler
, ADD_WI
| RD4(TMP_REG1
) | RN4(arg
& REG_MASK
) | imm
));
1793 return push_inst32(compiler
, inst
| 0x800000 | RN4(TMP_REG1
) | DD4(reg
) | (((sljit_uw
)argw
& 0x3fc) >> 2));
1796 imm
= get_imm((sljit_uw
)-argw
& ~(sljit_uw
)0x3fc);
1797 if (imm
!= INVALID_IMM
) {
1799 FAIL_IF(push_inst32(compiler
, SUB_WI
| RD4(TMP_REG1
) | RN4(arg
& REG_MASK
) | imm
));
1800 return push_inst32(compiler
, inst
| RN4(TMP_REG1
) | DD4(reg
) | (((sljit_uw
)argw
& 0x3fc) >> 2));
1804 FAIL_IF(load_immediate(compiler
, TMP_REG1
, (sljit_uw
)argw
));
1806 FAIL_IF(push_inst16(compiler
, ADD
| SET_REGS44(TMP_REG1
, (arg
& REG_MASK
))));
1807 return push_inst32(compiler
, inst
| 0x800000 | RN4(TMP_REG1
) | DD4(reg
));
1810 static SLJIT_INLINE sljit_s32
sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler
*compiler
, sljit_s32 op
,
1811 sljit_s32 dst
, sljit_sw dstw
,
1812 sljit_s32 src
, sljit_sw srcw
)
1816 if (src
& SLJIT_MEM
) {
1817 FAIL_IF(emit_fop_mem(compiler
, (op
& SLJIT_32
) | FPU_LOAD
, TMP_FREG1
, src
, srcw
));
1821 FAIL_IF(push_inst32(compiler
, VCVT_S32_F32
| (op
& SLJIT_32
) | DD4(TMP_FREG1
) | DM4(src
)));
1823 if (FAST_IS_REG(dst
))
1824 return push_inst32(compiler
, VMOV
| (1 << 20) | RT4(dst
) | DN4(TMP_FREG1
));
1826 /* Store the integer value from a VFP register. */
1827 return emit_fop_mem(compiler
, 0, TMP_FREG1
, dst
, dstw
);
1830 static SLJIT_INLINE sljit_s32
sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler
*compiler
, sljit_s32 op
,
1831 sljit_s32 dst
, sljit_sw dstw
,
1832 sljit_s32 src
, sljit_sw srcw
)
1834 sljit_s32 dst_r
= FAST_IS_REG(dst
) ? dst
: TMP_FREG1
;
1838 if (FAST_IS_REG(src
))
1839 FAIL_IF(push_inst32(compiler
, VMOV
| RT4(src
) | DN4(TMP_FREG1
)));
1840 else if (src
& SLJIT_MEM
) {
1841 /* Load the integer value into a VFP register. */
1842 FAIL_IF(emit_fop_mem(compiler
, FPU_LOAD
, TMP_FREG1
, src
, srcw
));
1845 FAIL_IF(load_immediate(compiler
, TMP_REG1
, (sljit_uw
)srcw
));
1846 FAIL_IF(push_inst32(compiler
, VMOV
| RT4(TMP_REG1
) | DN4(TMP_FREG1
)));
1849 FAIL_IF(push_inst32(compiler
, VCVT_F32_S32
| (op
& SLJIT_32
) | DD4(dst_r
) | DM4(TMP_FREG1
)));
1851 if (dst
& SLJIT_MEM
)
1852 return emit_fop_mem(compiler
, (op
& SLJIT_32
), TMP_FREG1
, dst
, dstw
);
1853 return SLJIT_SUCCESS
;
1856 static SLJIT_INLINE sljit_s32
sljit_emit_fop1_cmp(struct sljit_compiler
*compiler
, sljit_s32 op
,
1857 sljit_s32 src1
, sljit_sw src1w
,
1858 sljit_s32 src2
, sljit_sw src2w
)
1862 if (src1
& SLJIT_MEM
) {
1863 emit_fop_mem(compiler
, (op
& SLJIT_32
) | FPU_LOAD
, TMP_FREG1
, src1
, src1w
);
1867 if (src2
& SLJIT_MEM
) {
1868 emit_fop_mem(compiler
, (op
& SLJIT_32
) | FPU_LOAD
, TMP_FREG2
, src2
, src2w
);
1872 FAIL_IF(push_inst32(compiler
, VCMP_F32
| (op
& SLJIT_32
) | DD4(src1
) | DM4(src2
)));
1873 return push_inst32(compiler
, VMRS
);
1876 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_fop1(struct sljit_compiler
*compiler
, sljit_s32 op
,
1877 sljit_s32 dst
, sljit_sw dstw
,
1878 sljit_s32 src
, sljit_sw srcw
)
1884 SLJIT_COMPILE_ASSERT((SLJIT_32
== 0x100), float_transfer_bit_error
);
1885 SELECT_FOP1_OPERATION_WITH_CHECKS(compiler
, op
, dst
, dstw
, src
, srcw
);
1887 dst_r
= FAST_IS_REG(dst
) ? dst
: TMP_FREG1
;
1889 if (GET_OPCODE(op
) != SLJIT_CONV_F64_FROM_F32
)
1892 if (src
& SLJIT_MEM
) {
1893 emit_fop_mem(compiler
, (op
& SLJIT_32
) | FPU_LOAD
, dst_r
, src
, srcw
);
1897 switch (GET_OPCODE(op
)) {
1900 if (dst_r
!= TMP_FREG1
)
1901 FAIL_IF(push_inst32(compiler
, VMOV_F32
| (op
& SLJIT_32
) | DD4(dst_r
) | DM4(src
)));
1907 FAIL_IF(push_inst32(compiler
, VNEG_F32
| (op
& SLJIT_32
) | DD4(dst_r
) | DM4(src
)));
1910 FAIL_IF(push_inst32(compiler
, VABS_F32
| (op
& SLJIT_32
) | DD4(dst_r
) | DM4(src
)));
1912 case SLJIT_CONV_F64_FROM_F32
:
1913 FAIL_IF(push_inst32(compiler
, VCVT_F64_F32
| (op
& SLJIT_32
) | DD4(dst_r
) | DM4(src
)));
1918 if (dst
& SLJIT_MEM
)
1919 return emit_fop_mem(compiler
, (op
& SLJIT_32
), dst_r
, dst
, dstw
);
1920 return SLJIT_SUCCESS
;
1923 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_fop2(struct sljit_compiler
*compiler
, sljit_s32 op
,
1924 sljit_s32 dst
, sljit_sw dstw
,
1925 sljit_s32 src1
, sljit_sw src1w
,
1926 sljit_s32 src2
, sljit_sw src2w
)
1931 CHECK(check_sljit_emit_fop2(compiler
, op
, dst
, dstw
, src1
, src1w
, src2
, src2w
));
1932 ADJUST_LOCAL_OFFSET(dst
, dstw
);
1933 ADJUST_LOCAL_OFFSET(src1
, src1w
);
1934 ADJUST_LOCAL_OFFSET(src2
, src2w
);
1938 dst_r
= FAST_IS_REG(dst
) ? dst
: TMP_FREG1
;
1939 if (src1
& SLJIT_MEM
) {
1940 emit_fop_mem(compiler
, (op
& SLJIT_32
) | FPU_LOAD
, TMP_FREG1
, src1
, src1w
);
1943 if (src2
& SLJIT_MEM
) {
1944 emit_fop_mem(compiler
, (op
& SLJIT_32
) | FPU_LOAD
, TMP_FREG2
, src2
, src2w
);
1948 switch (GET_OPCODE(op
)) {
1950 FAIL_IF(push_inst32(compiler
, VADD_F32
| (op
& SLJIT_32
) | DD4(dst_r
) | DN4(src1
) | DM4(src2
)));
1953 FAIL_IF(push_inst32(compiler
, VSUB_F32
| (op
& SLJIT_32
) | DD4(dst_r
) | DN4(src1
) | DM4(src2
)));
1956 FAIL_IF(push_inst32(compiler
, VMUL_F32
| (op
& SLJIT_32
) | DD4(dst_r
) | DN4(src1
) | DM4(src2
)));
1959 FAIL_IF(push_inst32(compiler
, VDIV_F32
| (op
& SLJIT_32
) | DD4(dst_r
) | DN4(src1
) | DM4(src2
)));
1963 if (!(dst
& SLJIT_MEM
))
1964 return SLJIT_SUCCESS
;
1965 return emit_fop_mem(compiler
, (op
& SLJIT_32
), TMP_FREG1
, dst
, dstw
);
1968 /* --------------------------------------------------------------------- */
1969 /* Other instructions */
1970 /* --------------------------------------------------------------------- */
1972 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_fast_enter(struct sljit_compiler
*compiler
, sljit_s32 dst
, sljit_sw dstw
)
1975 CHECK(check_sljit_emit_fast_enter(compiler
, dst
, dstw
));
1976 ADJUST_LOCAL_OFFSET(dst
, dstw
);
1978 SLJIT_ASSERT(reg_map
[TMP_REG2
] == 14);
1980 if (FAST_IS_REG(dst
))
1981 return push_inst16(compiler
, MOV
| SET_REGS44(dst
, TMP_REG2
));
1984 return emit_op_mem(compiler
, WORD_SIZE
| STORE
, TMP_REG2
, dst
, dstw
, TMP_REG1
);
1987 /* --------------------------------------------------------------------- */
1988 /* Conditional instructions */
1989 /* --------------------------------------------------------------------- */
1991 static sljit_uw
get_cc(struct sljit_compiler
*compiler
, sljit_s32 type
)
1996 case SLJIT_ORDERED_EQUAL
:
1997 case SLJIT_UNORDERED_OR_EQUAL
: /* Not supported. */
2000 case SLJIT_NOT_EQUAL
:
2001 case SLJIT_F_NOT_EQUAL
:
2002 case SLJIT_UNORDERED_OR_NOT_EQUAL
:
2003 case SLJIT_ORDERED_NOT_EQUAL
: /* Not supported. */
2007 if (compiler
->status_flags_state
& SLJIT_CURRENT_FLAGS_ADD
)
2014 case SLJIT_NOT_CARRY
:
2015 if (compiler
->status_flags_state
& SLJIT_CURRENT_FLAGS_ADD
)
2019 case SLJIT_GREATER_EQUAL
:
2023 case SLJIT_UNORDERED_OR_GREATER
:
2026 case SLJIT_LESS_EQUAL
:
2027 case SLJIT_F_LESS_EQUAL
:
2028 case SLJIT_ORDERED_LESS_EQUAL
:
2031 case SLJIT_SIG_LESS
:
2032 case SLJIT_UNORDERED_OR_LESS
:
2035 case SLJIT_SIG_GREATER_EQUAL
:
2036 case SLJIT_F_GREATER_EQUAL
:
2037 case SLJIT_ORDERED_GREATER_EQUAL
:
2040 case SLJIT_SIG_GREATER
:
2041 case SLJIT_F_GREATER
:
2042 case SLJIT_ORDERED_GREATER
:
2045 case SLJIT_SIG_LESS_EQUAL
:
2046 case SLJIT_UNORDERED_OR_LESS_EQUAL
:
2049 case SLJIT_OVERFLOW
:
2050 if (!(compiler
->status_flags_state
& (SLJIT_CURRENT_FLAGS_ADD
| SLJIT_CURRENT_FLAGS_SUB
)))
2054 case SLJIT_UNORDERED
:
2057 case SLJIT_NOT_OVERFLOW
:
2058 if (!(compiler
->status_flags_state
& (SLJIT_CURRENT_FLAGS_ADD
| SLJIT_CURRENT_FLAGS_SUB
)))
2066 case SLJIT_ORDERED_LESS
:
2069 case SLJIT_UNORDERED_OR_GREATER_EQUAL
:
2072 default: /* SLJIT_JUMP */
2073 SLJIT_UNREACHABLE();
2078 SLJIT_API_FUNC_ATTRIBUTE
struct sljit_label
* sljit_emit_label(struct sljit_compiler
*compiler
)
2080 struct sljit_label
*label
;
2083 CHECK_PTR(check_sljit_emit_label(compiler
));
2085 if (compiler
->last_label
&& compiler
->last_label
->size
== compiler
->size
)
2086 return compiler
->last_label
;
2088 label
= (struct sljit_label
*)ensure_abuf(compiler
, sizeof(struct sljit_label
));
2089 PTR_FAIL_IF(!label
);
2090 set_label(label
, compiler
);
2094 SLJIT_API_FUNC_ATTRIBUTE
struct sljit_jump
* sljit_emit_jump(struct sljit_compiler
*compiler
, sljit_s32 type
)
2096 struct sljit_jump
*jump
;
2100 CHECK_PTR(check_sljit_emit_jump(compiler
, type
));
2102 jump
= (struct sljit_jump
*)ensure_abuf(compiler
, sizeof(struct sljit_jump
));
2104 set_jump(jump
, compiler
, type
& SLJIT_REWRITABLE_JUMP
);
2107 PTR_FAIL_IF(emit_imm32_const(compiler
, TMP_REG1
, 0));
2108 if (type
< SLJIT_JUMP
) {
2109 jump
->flags
|= IS_COND
;
2110 cc
= get_cc(compiler
, type
);
2111 jump
->flags
|= cc
<< 8;
2112 PTR_FAIL_IF(push_inst16(compiler
, IT
| (cc
<< 4) | 0x8));
2115 jump
->addr
= compiler
->size
;
2116 if (type
<= SLJIT_JUMP
)
2117 PTR_FAIL_IF(push_inst16(compiler
, BX
| RN3(TMP_REG1
)));
2119 jump
->flags
|= IS_BL
;
2120 PTR_FAIL_IF(push_inst16(compiler
, BLX
| RN3(TMP_REG1
)));
2128 static sljit_s32
softfloat_call_with_args(struct sljit_compiler
*compiler
, sljit_s32 arg_types
, sljit_s32
*src
, sljit_u32
*extra_space
)
2130 sljit_u32 is_tail_call
= *extra_space
& SLJIT_CALL_RETURN
;
2131 sljit_u32 offset
= 0;
2132 sljit_u32 word_arg_offset
= 0;
2133 sljit_u32 float_arg_count
= 0;
2134 sljit_s32 types
= 0;
2135 sljit_u32 src_offset
= 4 * sizeof(sljit_sw
);
2136 sljit_u8 offsets
[4];
2137 sljit_u8
*offset_ptr
= offsets
;
2139 if (src
&& FAST_IS_REG(*src
))
2140 src_offset
= (sljit_u32
)reg_map
[*src
] * sizeof(sljit_sw
);
2142 arg_types
>>= SLJIT_ARG_SHIFT
;
2145 types
= (types
<< SLJIT_ARG_SHIFT
) | (arg_types
& SLJIT_ARG_MASK
);
2147 switch (arg_types
& SLJIT_ARG_MASK
) {
2148 case SLJIT_ARG_TYPE_F64
:
2150 offset
+= sizeof(sljit_sw
);
2151 *offset_ptr
++ = (sljit_u8
)offset
;
2152 offset
+= sizeof(sljit_f64
);
2155 case SLJIT_ARG_TYPE_F32
:
2156 *offset_ptr
++ = (sljit_u8
)offset
;
2157 offset
+= sizeof(sljit_f32
);
2161 *offset_ptr
++ = (sljit_u8
)offset
;
2162 offset
+= sizeof(sljit_sw
);
2163 word_arg_offset
+= sizeof(sljit_sw
);
2167 arg_types
>>= SLJIT_ARG_SHIFT
;
2170 if (offset
> 4 * sizeof(sljit_sw
) && (!is_tail_call
|| offset
> compiler
->args_size
)) {
2171 /* Keep lr register on the stack. */
2173 offset
+= sizeof(sljit_sw
);
2175 offset
= ((offset
- 4 * sizeof(sljit_sw
)) + 0x7) & ~(sljit_uw
)0x7;
2177 *extra_space
= offset
;
2180 FAIL_IF(emit_stack_frame_release(compiler
, (sljit_s32
)offset
));
2182 FAIL_IF(push_inst16(compiler
, SUB_SP_I
| (offset
>> 2)));
2185 FAIL_IF(emit_stack_frame_release(compiler
, -1));
2189 SLJIT_ASSERT(reg_map
[TMP_REG1
] == 12);
2191 /* Process arguments in reversed direction. */
2193 switch (types
& SLJIT_ARG_MASK
) {
2194 case SLJIT_ARG_TYPE_F64
:
2196 offset
= *(--offset_ptr
);
2198 SLJIT_ASSERT((offset
& 0x7) == 0);
2200 if (offset
< 4 * sizeof(sljit_sw
)) {
2201 if (src_offset
== offset
|| src_offset
== offset
+ sizeof(sljit_sw
)) {
2202 FAIL_IF(push_inst16(compiler
, MOV
| (src_offset
<< 1) | 4 | (1 << 7)));
2205 FAIL_IF(push_inst32(compiler
, VMOV2
| 0x100000 | (offset
<< 10) | ((offset
+ sizeof(sljit_sw
)) << 14) | float_arg_count
));
2207 FAIL_IF(push_inst32(compiler
, VSTR_F32
| 0x800100 | RN4(SLJIT_SP
)
2208 | (float_arg_count
<< 12) | ((offset
- 4 * sizeof(sljit_sw
)) >> 2)));
2210 case SLJIT_ARG_TYPE_F32
:
2212 offset
= *(--offset_ptr
);
2214 if (offset
< 4 * sizeof(sljit_sw
)) {
2215 if (src_offset
== offset
) {
2216 FAIL_IF(push_inst16(compiler
, MOV
| (src_offset
<< 1) | 4 | (1 << 7)));
2219 FAIL_IF(push_inst32(compiler
, VMOV
| 0x100000 | (float_arg_count
<< 16) | (offset
<< 10)));
2221 FAIL_IF(push_inst32(compiler
, VSTR_F32
| 0x800000 | RN4(SLJIT_SP
)
2222 | (float_arg_count
<< 12) | ((offset
- 4 * sizeof(sljit_sw
)) >> 2)));
2225 word_arg_offset
-= sizeof(sljit_sw
);
2226 offset
= *(--offset_ptr
);
2228 SLJIT_ASSERT(offset
>= word_arg_offset
);
2230 if (offset
!= word_arg_offset
) {
2231 if (offset
< 4 * sizeof(sljit_sw
)) {
2232 if (src_offset
== offset
) {
2233 FAIL_IF(push_inst16(compiler
, MOV
| (src_offset
<< 1) | 4 | (1 << 7)));
2236 else if (src_offset
== word_arg_offset
) {
2237 *src
= (sljit_s32
)(1 + (offset
>> 2));
2238 src_offset
= offset
;
2240 FAIL_IF(push_inst16(compiler
, MOV
| (offset
>> 2) | (word_arg_offset
<< 1)));
2242 FAIL_IF(push_inst16(compiler
, STR_SP
| (word_arg_offset
<< 6) | ((offset
- 4 * sizeof(sljit_sw
)) >> 2)));
2247 types
>>= SLJIT_ARG_SHIFT
;
2250 return SLJIT_SUCCESS
;
2253 static sljit_s32
softfloat_post_call_with_args(struct sljit_compiler
*compiler
, sljit_s32 arg_types
)
2255 if ((arg_types
& SLJIT_ARG_MASK
) == SLJIT_ARG_TYPE_F64
)
2256 FAIL_IF(push_inst32(compiler
, VMOV2
| (1 << 16) | (0 << 12) | 0));
2257 if ((arg_types
& SLJIT_ARG_MASK
) == SLJIT_ARG_TYPE_F32
)
2258 FAIL_IF(push_inst32(compiler
, VMOV
| (0 << 16) | (0 << 12)));
2260 return SLJIT_SUCCESS
;
2265 static sljit_s32
hardfloat_call_with_args(struct sljit_compiler
*compiler
, sljit_s32 arg_types
)
2267 sljit_u32 offset
= SLJIT_FR0
;
2268 sljit_u32 new_offset
= SLJIT_FR0
;
2269 sljit_u32 f32_offset
= 0;
2271 /* Remove return value. */
2272 arg_types
>>= SLJIT_ARG_SHIFT
;
2275 switch (arg_types
& SLJIT_ARG_MASK
) {
2276 case SLJIT_ARG_TYPE_F64
:
2277 if (offset
!= new_offset
)
2278 FAIL_IF(push_inst32(compiler
, VMOV_F32
| SLJIT_32
| DD4(new_offset
) | DM4(offset
)));
2283 case SLJIT_ARG_TYPE_F32
:
2284 if (f32_offset
!= 0) {
2285 FAIL_IF(push_inst32(compiler
, VMOV_F32
| 0x400000 | DD4(f32_offset
) | DM4(offset
)));
2288 if (offset
!= new_offset
)
2289 FAIL_IF(push_inst32(compiler
, VMOV_F32
| 0x400000 | DD4(new_offset
) | DM4(offset
)));
2290 f32_offset
= new_offset
;
2296 arg_types
>>= SLJIT_ARG_SHIFT
;
2299 return SLJIT_SUCCESS
;
2304 SLJIT_API_FUNC_ATTRIBUTE
struct sljit_jump
* sljit_emit_call(struct sljit_compiler
*compiler
, sljit_s32 type
,
2305 sljit_s32 arg_types
)
2308 struct sljit_jump
*jump
;
2309 sljit_u32 extra_space
= (sljit_u32
)type
;
2313 CHECK_PTR(check_sljit_emit_call(compiler
, type
, arg_types
));
2316 PTR_FAIL_IF(softfloat_call_with_args(compiler
, arg_types
, NULL
, &extra_space
));
2317 SLJIT_ASSERT((extra_space
& 0x7) == 0);
2319 if ((type
& SLJIT_CALL_RETURN
) && extra_space
== 0)
2320 type
= SLJIT_JUMP
| (type
& SLJIT_REWRITABLE_JUMP
);
2322 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
2323 || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
2324 compiler
->skip_checks
= 1;
2327 jump
= sljit_emit_jump(compiler
, type
);
2328 PTR_FAIL_IF(jump
== NULL
);
2330 if (extra_space
> 0) {
2331 if (type
& SLJIT_CALL_RETURN
)
2332 PTR_FAIL_IF(push_inst32(compiler
, LDR
| RT4(TMP_REG2
)
2333 | RN4(SLJIT_SP
) | (extra_space
- sizeof(sljit_sw
))));
2335 PTR_FAIL_IF(push_inst16(compiler
, ADD_SP_I
| (extra_space
>> 2)));
2337 if (type
& SLJIT_CALL_RETURN
) {
2338 PTR_FAIL_IF(push_inst16(compiler
, BX
| RN3(TMP_REG2
)));
2343 SLJIT_ASSERT(!(type
& SLJIT_CALL_RETURN
));
2344 PTR_FAIL_IF(softfloat_post_call_with_args(compiler
, arg_types
));
2347 if (type
& SLJIT_CALL_RETURN
) {
2348 /* ldmia sp!, {..., lr} */
2349 PTR_FAIL_IF(emit_stack_frame_release(compiler
, -1));
2350 type
= SLJIT_JUMP
| (type
& SLJIT_REWRITABLE_JUMP
);
2353 PTR_FAIL_IF(hardfloat_call_with_args(compiler
, arg_types
));
2355 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
2356 || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
2357 compiler
->skip_checks
= 1;
2360 return sljit_emit_jump(compiler
, type
);
2364 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_ijump(struct sljit_compiler
*compiler
, sljit_s32 type
, sljit_s32 src
, sljit_sw srcw
)
2366 struct sljit_jump
*jump
;
2369 CHECK(check_sljit_emit_ijump(compiler
, type
, src
, srcw
));
2370 ADJUST_LOCAL_OFFSET(src
, srcw
);
2372 SLJIT_ASSERT(reg_map
[TMP_REG1
] != 14);
2374 if (!(src
& SLJIT_IMM
)) {
2375 if (FAST_IS_REG(src
)) {
2376 SLJIT_ASSERT(reg_map
[src
] != 14);
2377 return push_inst16(compiler
, (type
<= SLJIT_JUMP
? BX
: BLX
) | RN3(src
));
2380 FAIL_IF(emit_op_mem(compiler
, WORD_SIZE
, type
<= SLJIT_JUMP
? TMP_PC
: TMP_REG1
, src
, srcw
, TMP_REG1
));
2381 if (type
>= SLJIT_FAST_CALL
)
2382 return push_inst16(compiler
, BLX
| RN3(TMP_REG1
));
2385 /* These jumps are converted to jump/call instructions when possible. */
2386 jump
= (struct sljit_jump
*)ensure_abuf(compiler
, sizeof(struct sljit_jump
));
2388 set_jump(jump
, compiler
, JUMP_ADDR
| ((type
>= SLJIT_FAST_CALL
) ? IS_BL
: 0));
2389 jump
->u
.target
= (sljit_uw
)srcw
;
2391 FAIL_IF(emit_imm32_const(compiler
, TMP_REG1
, 0));
2392 jump
->addr
= compiler
->size
;
2393 return push_inst16(compiler
, (type
<= SLJIT_JUMP
? BX
: BLX
) | RN3(TMP_REG1
));
2396 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_icall(struct sljit_compiler
*compiler
, sljit_s32 type
,
2397 sljit_s32 arg_types
,
2398 sljit_s32 src
, sljit_sw srcw
)
2401 sljit_u32 extra_space
= (sljit_u32
)type
;
2405 CHECK(check_sljit_emit_icall(compiler
, type
, arg_types
, src
, srcw
));
2407 if (src
& SLJIT_MEM
) {
2408 FAIL_IF(emit_op_mem(compiler
, WORD_SIZE
, TMP_REG1
, src
, srcw
, TMP_REG1
));
2412 if ((type
& SLJIT_CALL_RETURN
) && (src
>= SLJIT_FIRST_SAVED_REG
&& src
<= SLJIT_S0
)) {
2413 FAIL_IF(push_inst16(compiler
, MOV
| SET_REGS44(TMP_REG1
, src
)));
2418 FAIL_IF(softfloat_call_with_args(compiler
, arg_types
, &src
, &extra_space
));
2419 SLJIT_ASSERT((extra_space
& 0x7) == 0);
2421 if ((type
& SLJIT_CALL_RETURN
) && extra_space
== 0)
2424 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
2425 || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
2426 compiler
->skip_checks
= 1;
2429 FAIL_IF(sljit_emit_ijump(compiler
, type
, src
, srcw
));
2431 if (extra_space
> 0) {
2432 if (type
& SLJIT_CALL_RETURN
)
2433 FAIL_IF(push_inst32(compiler
, LDR
| RT4(TMP_REG2
)
2434 | RN4(SLJIT_SP
) | (extra_space
- sizeof(sljit_sw
))));
2436 FAIL_IF(push_inst16(compiler
, ADD_SP_I
| (extra_space
>> 2)));
2438 if (type
& SLJIT_CALL_RETURN
)
2439 return push_inst16(compiler
, BX
| RN3(TMP_REG2
));
2442 SLJIT_ASSERT(!(type
& SLJIT_CALL_RETURN
));
2443 return softfloat_post_call_with_args(compiler
, arg_types
);
2444 #else /* !__SOFTFP__ */
2445 if (type
& SLJIT_CALL_RETURN
) {
2446 /* ldmia sp!, {..., lr} */
2447 FAIL_IF(emit_stack_frame_release(compiler
, -1));
2451 FAIL_IF(hardfloat_call_with_args(compiler
, arg_types
));
2453 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
2454 || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
2455 compiler
->skip_checks
= 1;
2458 return sljit_emit_ijump(compiler
, type
, src
, srcw
);
2459 #endif /* __SOFTFP__ */
2462 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_op_flags(struct sljit_compiler
*compiler
, sljit_s32 op
,
2463 sljit_s32 dst
, sljit_sw dstw
,
2466 sljit_s32 dst_r
, flags
= GET_ALL_FLAGS(op
);
2470 CHECK(check_sljit_emit_op_flags(compiler
, op
, dst
, dstw
, type
));
2471 ADJUST_LOCAL_OFFSET(dst
, dstw
);
2473 op
= GET_OPCODE(op
);
2474 cc
= get_cc(compiler
, type
);
2475 dst_r
= FAST_IS_REG(dst
) ? dst
: TMP_REG1
;
2477 if (op
< SLJIT_ADD
) {
2478 FAIL_IF(push_inst16(compiler
, IT
| (cc
<< 4) | (((cc
& 0x1) ^ 0x1) << 3) | 0x4));
2479 if (reg_map
[dst_r
] > 7) {
2480 FAIL_IF(push_inst32(compiler
, MOV_WI
| RD4(dst_r
) | 1));
2481 FAIL_IF(push_inst32(compiler
, MOV_WI
| RD4(dst_r
) | 0));
2483 /* The movsi (immediate) instruction does not set flags in IT block. */
2484 FAIL_IF(push_inst16(compiler
, MOVSI
| RDN3(dst_r
) | 1));
2485 FAIL_IF(push_inst16(compiler
, MOVSI
| RDN3(dst_r
) | 0));
2487 if (!(dst
& SLJIT_MEM
))
2488 return SLJIT_SUCCESS
;
2489 return emit_op_mem(compiler
, WORD_SIZE
| STORE
, TMP_REG1
, dst
, dstw
, TMP_REG2
);
2492 if (dst
& SLJIT_MEM
)
2493 FAIL_IF(emit_op_mem(compiler
, WORD_SIZE
, TMP_REG1
, dst
, dstw
, TMP_REG2
));
2495 if (op
== SLJIT_AND
) {
2496 FAIL_IF(push_inst16(compiler
, IT
| (cc
<< 4) | (((cc
& 0x1) ^ 0x1) << 3) | 0x4));
2497 FAIL_IF(push_inst32(compiler
, ANDI
| RN4(dst_r
) | RD4(dst_r
) | 1));
2498 FAIL_IF(push_inst32(compiler
, ANDI
| RN4(dst_r
) | RD4(dst_r
) | 0));
2501 FAIL_IF(push_inst16(compiler
, IT
| (cc
<< 4) | 0x8));
2502 FAIL_IF(push_inst32(compiler
, ((op
== SLJIT_OR
) ? ORRI
: EORI
) | RN4(dst_r
) | RD4(dst_r
) | 1));
2505 if (dst
& SLJIT_MEM
)
2506 FAIL_IF(emit_op_mem(compiler
, WORD_SIZE
| STORE
, TMP_REG1
, dst
, dstw
, TMP_REG2
));
2508 if (!(flags
& SLJIT_SET_Z
))
2509 return SLJIT_SUCCESS
;
2511 /* The condition must always be set, even if the ORR/EORI is not executed above. */
2512 return push_inst32(compiler
, MOV_W
| SET_FLAGS
| RD4(TMP_REG1
) | RM4(dst_r
));
2515 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_cmov(struct sljit_compiler
*compiler
, sljit_s32 type
,
2517 sljit_s32 src
, sljit_sw srcw
)
2522 CHECK(check_sljit_emit_cmov(compiler
, type
, dst_reg
, src
, srcw
));
2524 dst_reg
&= ~SLJIT_32
;
2526 cc
= get_cc(compiler
, type
);
2528 if (!(src
& SLJIT_IMM
)) {
2529 FAIL_IF(push_inst16(compiler
, IT
| (cc
<< 4) | 0x8));
2530 return push_inst16(compiler
, MOV
| SET_REGS44(dst_reg
, src
));
2533 tmp
= (sljit_uw
) srcw
;
2535 if (tmp
< 0x10000) {
2536 /* set low 16 bits, set hi 16 bits to 0. */
2537 FAIL_IF(push_inst16(compiler
, IT
| (cc
<< 4) | 0x8));
2538 return push_inst32(compiler
, MOVW
| RD4(dst_reg
)
2539 | COPY_BITS(tmp
, 12, 16, 4) | COPY_BITS(tmp
, 11, 26, 1) | COPY_BITS(tmp
, 8, 12, 3) | (tmp
& 0xff));
2542 tmp
= get_imm((sljit_uw
)srcw
);
2543 if (tmp
!= INVALID_IMM
) {
2544 FAIL_IF(push_inst16(compiler
, IT
| (cc
<< 4) | 0x8));
2545 return push_inst32(compiler
, MOV_WI
| RD4(dst_reg
) | tmp
);
2548 tmp
= get_imm(~(sljit_uw
)srcw
);
2549 if (tmp
!= INVALID_IMM
) {
2550 FAIL_IF(push_inst16(compiler
, IT
| (cc
<< 4) | 0x8));
2551 return push_inst32(compiler
, MVN_WI
| RD4(dst_reg
) | tmp
);
2554 FAIL_IF(push_inst16(compiler
, IT
| (cc
<< 4) | ((cc
& 0x1) << 3) | 0x4));
2556 tmp
= (sljit_uw
) srcw
;
2557 FAIL_IF(push_inst32(compiler
, MOVW
| RD4(dst_reg
)
2558 | COPY_BITS(tmp
, 12, 16, 4) | COPY_BITS(tmp
, 11, 26, 1) | COPY_BITS(tmp
, 8, 12, 3) | (tmp
& 0xff)));
2559 return push_inst32(compiler
, MOVT
| RD4(dst_reg
)
2560 | COPY_BITS(tmp
, 12 + 16, 16, 4) | COPY_BITS(tmp
, 11 + 16, 26, 1) | COPY_BITS(tmp
, 8 + 16, 12, 3) | ((tmp
& 0xff0000) >> 16));
2563 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_mem(struct sljit_compiler
*compiler
, sljit_s32 type
,
2565 sljit_s32 mem
, sljit_sw memw
)
2571 CHECK(check_sljit_emit_mem(compiler
, type
, reg
, mem
, memw
));
2573 if (type
& SLJIT_MEM_UNALIGNED
)
2574 return sljit_emit_mem_unaligned(compiler
, type
, reg
, mem
, memw
);
2576 if ((mem
& OFFS_REG_MASK
) || (memw
> 255 || memw
< -255))
2577 return SLJIT_ERR_UNSUPPORTED
;
2579 if (type
& SLJIT_MEM_SUPP
)
2580 return SLJIT_SUCCESS
;
2582 switch (type
& 0xff) {
2594 flags
= BYTE_SIZE
| SIGNED
;
2600 flags
= HALF_SIZE
| SIGNED
;
2603 SLJIT_UNREACHABLE();
2608 if (type
& SLJIT_MEM_STORE
)
2611 inst
= sljit_mem32
[flags
] | 0x900;
2613 if (type
& SLJIT_MEM_PRE
)
2621 return push_inst32(compiler
, inst
| RT4(reg
) | RN4(mem
& REG_MASK
) | (sljit_ins
)memw
);
2624 static sljit_s32
update_mem_addr(struct sljit_compiler
*compiler
, sljit_s32
*mem
, sljit_sw
*memw
, sljit_s32 max_offset
)
2626 sljit_s32 arg
= *mem
;
2627 sljit_sw argw
= *memw
;
2632 if (SLJIT_UNLIKELY(arg
& OFFS_REG_MASK
)) {
2634 return push_inst32(compiler
, ADD_W
| RD4(TMP_REG1
) | RN4(arg
& REG_MASK
) | RM4(OFFS_REG(arg
)) | ((sljit_uw
)(argw
& 0x3) << 6));
2640 if (argw
<= max_offset
&& argw
>= -0xff) {
2642 return SLJIT_SUCCESS
;
2646 imm
= get_imm((sljit_uw
)(-argw
& ~0xff));
2649 *memw
= -(-argw
& 0xff);
2650 return push_inst32(compiler
, SUB_WI
| RD4(TMP_REG1
) | RN4(arg
) | imm
);
2652 } else if ((argw
& 0xfff) <= max_offset
) {
2653 imm
= get_imm((sljit_uw
)(argw
& ~0xfff));
2656 *memw
= argw
& 0xfff;
2657 return push_inst32(compiler
, ADD_WI
| RD4(TMP_REG1
) | RN4(arg
) | imm
);
2660 imm
= get_imm((sljit_uw
)((argw
| 0xfff) + 1));
2663 *memw
= (argw
& 0xfff) - 0x1000;
2664 return push_inst32(compiler
, ADD_WI
| RD4(TMP_REG1
) | RN4(arg
) | imm
);
2669 imm
= (sljit_uw
)(argw
& ~0xfff);
2671 if ((argw
& 0xfff) > max_offset
) {
2673 *memw
= (argw
& 0xfff) - 0x1000;
2675 *memw
= argw
& 0xfff;
2677 FAIL_IF(load_immediate(compiler
, TMP_REG1
, imm
));
2680 return SLJIT_SUCCESS
;
2682 return push_inst16(compiler
, ADD
| SET_REGS44(TMP_REG1
, arg
));
2685 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_fmem(struct sljit_compiler
*compiler
, sljit_s32 type
,
2687 sljit_s32 mem
, sljit_sw memw
)
2690 CHECK(check_sljit_emit_fmem(compiler
, type
, freg
, mem
, memw
));
2692 if (type
& (SLJIT_MEM_PRE
| SLJIT_MEM_POST
))
2693 return SLJIT_ERR_UNSUPPORTED
;
2695 if (type
& SLJIT_MEM_ALIGNED_32
)
2696 return emit_fop_mem(compiler
, ((type
^ SLJIT_32
) & SLJIT_32
) | ((type
& SLJIT_MEM_STORE
) ? 0 : FPU_LOAD
), freg
, mem
, memw
);
2698 if (type
& SLJIT_MEM_STORE
) {
2699 FAIL_IF(push_inst32(compiler
, VMOV
| (1 << 20) | DN4(freg
) | RT4(TMP_REG2
)));
2701 if (type
& SLJIT_32
)
2702 return emit_op_mem(compiler
, WORD_SIZE
| STORE
, TMP_REG2
, mem
, memw
, TMP_REG1
);
2704 FAIL_IF(update_mem_addr(compiler
, &mem
, &memw
, 0xfff - 4));
2707 FAIL_IF(emit_op_mem(compiler
, WORD_SIZE
| STORE
, TMP_REG2
, mem
, memw
, TMP_REG1
));
2708 FAIL_IF(push_inst32(compiler
, VMOV
| (1 << 20) | DN4(freg
) | 0x80 | RT4(TMP_REG2
)));
2709 return emit_op_mem(compiler
, WORD_SIZE
| STORE
, TMP_REG2
, mem
, memw
+ 4, TMP_REG1
);
2712 if (type
& SLJIT_32
) {
2713 FAIL_IF(emit_op_mem(compiler
, WORD_SIZE
, TMP_REG2
, mem
, memw
, TMP_REG1
));
2714 return push_inst32(compiler
, VMOV
| DN4(freg
) | RT4(TMP_REG2
));
2717 FAIL_IF(update_mem_addr(compiler
, &mem
, &memw
, 0xfff - 4));
2720 FAIL_IF(emit_op_mem(compiler
, WORD_SIZE
, TMP_REG2
, mem
, memw
, TMP_REG1
));
2721 FAIL_IF(emit_op_mem(compiler
, WORD_SIZE
, TMP_REG1
, mem
, memw
+ 4, TMP_REG1
));
2722 return push_inst32(compiler
, VMOV2
| DM4(freg
) | RT4(TMP_REG2
) | RN4(TMP_REG1
));
2727 SLJIT_API_FUNC_ATTRIBUTE
struct sljit_const
* sljit_emit_const(struct sljit_compiler
*compiler
, sljit_s32 dst
, sljit_sw dstw
, sljit_sw init_value
)
2729 struct sljit_const
*const_
;
2733 CHECK_PTR(check_sljit_emit_const(compiler
, dst
, dstw
, init_value
));
2734 ADJUST_LOCAL_OFFSET(dst
, dstw
);
2736 const_
= (struct sljit_const
*)ensure_abuf(compiler
, sizeof(struct sljit_const
));
2737 PTR_FAIL_IF(!const_
);
2738 set_const(const_
, compiler
);
2740 dst_r
= FAST_IS_REG(dst
) ? dst
: TMP_REG1
;
2741 PTR_FAIL_IF(emit_imm32_const(compiler
, dst_r
, (sljit_uw
)init_value
));
2743 if (dst
& SLJIT_MEM
)
2744 PTR_FAIL_IF(emit_op_mem(compiler
, WORD_SIZE
| STORE
, dst_r
, dst
, dstw
, TMP_REG2
));
2748 SLJIT_API_FUNC_ATTRIBUTE
struct sljit_put_label
* sljit_emit_put_label(struct sljit_compiler
*compiler
, sljit_s32 dst
, sljit_sw dstw
)
2750 struct sljit_put_label
*put_label
;
2754 CHECK_PTR(check_sljit_emit_put_label(compiler
, dst
, dstw
));
2755 ADJUST_LOCAL_OFFSET(dst
, dstw
);
2757 put_label
= (struct sljit_put_label
*)ensure_abuf(compiler
, sizeof(struct sljit_put_label
));
2758 PTR_FAIL_IF(!put_label
);
2759 set_put_label(put_label
, compiler
, 0);
2761 dst_r
= FAST_IS_REG(dst
) ? dst
: TMP_REG1
;
2762 PTR_FAIL_IF(emit_imm32_const(compiler
, dst_r
, 0));
2764 if (dst
& SLJIT_MEM
)
2765 PTR_FAIL_IF(emit_op_mem(compiler
, WORD_SIZE
| STORE
, dst_r
, dst
, dstw
, TMP_REG2
));
2769 SLJIT_API_FUNC_ATTRIBUTE
void sljit_set_jump_addr(sljit_uw addr
, sljit_uw new_target
, sljit_sw executable_offset
)
2771 sljit_u16
*inst
= (sljit_u16
*)addr
;
2772 SLJIT_UNUSED_ARG(executable_offset
);
2774 SLJIT_UPDATE_WX_FLAGS(inst
, inst
+ 4, 0);
2775 modify_imm32_const(inst
, new_target
);
2776 SLJIT_UPDATE_WX_FLAGS(inst
, inst
+ 4, 1);
2777 inst
= (sljit_u16
*)SLJIT_ADD_EXEC_OFFSET(inst
, executable_offset
);
2778 SLJIT_CACHE_FLUSH(inst
, inst
+ 4);
2781 SLJIT_API_FUNC_ATTRIBUTE
void sljit_set_const(sljit_uw addr
, sljit_sw new_constant
, sljit_sw executable_offset
)
2783 sljit_set_jump_addr(addr
, (sljit_uw
)new_constant
, executable_offset
);