2 * Stack-less Just-In-Time compiler
4 * Copyright 2009-2012 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 SLJIT_CONST
char* sljit_get_platform_name(void)
29 return "ARM-64" SLJIT_CPUINFO
;
32 /* Length of an instruction word */
33 typedef sljit_ui sljit_ins
;
37 #define TMP_REG1 (SLJIT_NO_REGISTERS + 1)
38 #define TMP_REG2 (SLJIT_NO_REGISTERS + 2)
39 #define TMP_REG3 (SLJIT_NO_REGISTERS + 3)
40 #define TMP_REG4 (SLJIT_NO_REGISTERS + 4)
41 #define TMP_LR (SLJIT_NO_REGISTERS + 5)
44 #define TMP_FREG2 (SLJIT_FLOAT_REG6 + 1)
46 static SLJIT_CONST sljit_ub reg_map
[SLJIT_NO_REGISTERS
+ 6] = {
47 31, 0, 1, 2, 3, 4, 19, 20, 21, 22, 23, 31, 9, 10, 11, 12, 30
50 #define W_OP (1 << 31)
51 #define RD(rd) (reg_map[rd])
52 #define RT(rt) (reg_map[rt])
53 #define RN(rn) (reg_map[rn] << 5)
54 #define RT2(rt2) (reg_map[rt2] << 10)
55 #define RM(rm) (reg_map[rm] << 16)
58 #define VN(vn) ((vn) << 5)
59 #define VM(vm) ((vm) << 16)
61 /* --------------------------------------------------------------------- */
62 /* Instrucion forms */
63 /* --------------------------------------------------------------------- */
65 #define ADC 0x9a000000
66 #define ADD 0x8b000000
67 #define ADDI 0x91000000
68 #define AND 0x8a000000
69 #define ANDI 0x92000000
70 #define ASRV 0x9ac02800
71 #define BRK 0xd4200000
72 #define CLZ 0xdac01000
73 #define CSINC 0x9a800400
74 #define EOR 0xca000000
75 #define EORI 0xd2000000
76 #define LDRI 0xf9400000
77 #define LDP 0xa9400000
78 #define LDP_PST 0xa8c00000
79 #define LSLV 0x9ac02000
80 #define LSRV 0x9ac02400
81 #define MADD 0x9b000000
82 #define MOVK 0xf2800000
83 #define MOVN 0x92800000
84 #define MOVZ 0xd2800000
85 #define NOP 0xd503201f
86 #define ORN 0xaa200000
87 #define ORR 0xaa000000
88 #define ORRI 0xb2000000
89 #define RET 0xd65f0000
90 #define SBC 0xda000000
91 #define SBFM 0x93000000
92 #define SMADDL 0x9b200000
93 #define SMULH 0x9b400000
94 #define STP 0xa9000000
95 #define STRI 0xf9000000
96 #define STR_F 0x3d000000
97 #define STR_FR 0x3c206800
98 #define STP_PRE 0xa9800000
99 #define STUR_F 0x3c000000
100 #define SUB 0xcb000000
101 #define SUBI 0xd1000000
102 #define SUBS 0xeb000000
103 #define UBFM 0xd3000000
105 /* dest_reg is the absolute name of the register
106 Useful for reordering instructions in the delay slot. */
107 static sljit_si
push_inst(struct sljit_compiler
*compiler
, sljit_ins ins
)
109 sljit_ins
*ptr
= (sljit_ins
*)ensure_buf(compiler
, sizeof(sljit_ins
));
113 return SLJIT_SUCCESS
;
116 SLJIT_API_FUNC_ATTRIBUTE
void* sljit_generate_code(struct sljit_compiler
*compiler
)
118 struct sljit_memory_fragment
*buf
;
125 struct sljit_label
*label
;
126 struct sljit_jump
*jump
;
127 struct sljit_const
*const_
;
130 check_sljit_generate_code(compiler
);
131 reverse_buf(compiler
);
133 code
= (sljit_ins
*)SLJIT_MALLOC_EXEC(compiler
->size
* sizeof(sljit_ins
));
134 PTR_FAIL_WITH_EXEC_IF(code
);
139 label
= compiler
->labels
;
140 jump
= compiler
->jumps
;
141 const_
= compiler
->consts
;
144 buf_ptr
= (sljit_ins
*)buf
->memory
;
145 buf_end
= buf_ptr
+ (buf
->used_size
>> 2);
147 *code_ptr
= *buf_ptr
++;
148 /* These structures are ordered by their address. */
149 SLJIT_ASSERT(!label
|| label
->size
>= word_count
);
150 SLJIT_ASSERT(!jump
|| jump
->addr
>= word_count
);
151 SLJIT_ASSERT(!const_
|| const_
->addr
>= word_count
);
152 if (label
&& label
->size
== word_count
) {
153 label
->addr
= (sljit_uw
)code_ptr
;
154 label
->size
= code_ptr
- code
;
157 if (jump
&& jump
->addr
== word_count
) {
158 // jump->addr = (sljit_uw)code_ptr - ((jump->flags & IS_COND) ? 10 : 8);
159 // code_ptr -= detect_jump_type(jump, code_ptr, code);
162 if (const_
&& const_
->addr
== word_count
) {
163 const_
->addr
= (sljit_uw
)code_ptr
;
164 const_
= const_
->next
;
168 } while (buf_ptr
< buf_end
);
173 if (label
&& label
->size
== word_count
) {
174 label
->addr
= (sljit_uw
)code_ptr
;
175 label
->size
= code_ptr
- code
;
179 SLJIT_ASSERT(!label
);
181 SLJIT_ASSERT(!const_
);
182 SLJIT_ASSERT(code_ptr
- code
<= (sljit_sw
)compiler
->size
);
184 jump
= compiler
->jumps
;
190 compiler
->error
= SLJIT_ERR_COMPILED
;
191 compiler
->executable_size
= (code_ptr
- code
) * sizeof(sljit_ins
);
192 /* SLJIT_CACHE_FLUSH(code, code_ptr); */
196 /* --------------------------------------------------------------------- */
197 /* Core code generator functions. */
198 /* --------------------------------------------------------------------- */
200 #define COUNT_TRAILING_ZERO(value, result) \
202 if (!(value & 0xffffffff)) { \
206 if (!(value & 0xffff)) { \
210 if (!(value & 0xff)) { \
214 if (!(value & 0xf)) { \
218 if (!(value & 0x3)) { \
222 if (!(value & 0x1)) { \
227 #define LOGICAL_IMM_CHECK 0x100
229 static sljit_ins
logical_imm(sljit_sw imm
, sljit_si len
)
231 sljit_si negated
, ones
, right
;
235 if (len
& LOGICAL_IMM_CHECK
) {
236 len
&= ~LOGICAL_IMM_CHECK
;
237 if (len
== 32 && (imm
== 0 || imm
== -1))
239 if (len
== 16 && ((sljit_si
)imm
== 0 || (sljit_si
)imm
== -1))
243 SLJIT_ASSERT((len
== 32 && imm
!= 0 && imm
!= -1)
244 || (len
== 16 && (sljit_si
)imm
!= 0 && (sljit_si
)imm
!= -1));
245 uimm
= (sljit_uw
)imm
;
251 mask
= ((sljit_uw
)1 << len
) - 1;
252 if ((uimm
& mask
) != ((uimm
>> len
) & mask
))
266 uimm
&= ((sljit_uw
)1 << len
) - 1;
268 /* Unsigned right shift. */
269 COUNT_TRAILING_ZERO(uimm
, right
);
271 /* Signed shift. We also know that the highest bit is set. */
272 imm
= (sljit_sw
)~uimm
;
273 SLJIT_ASSERT(imm
< 0);
275 COUNT_TRAILING_ZERO(imm
, ones
);
283 ins
= (0x3f - ((len
<< 1) - 1)) << 10;
286 return ins
| ((len
- ones
- 1) << 10) | ((len
- ones
- right
) << 16);
288 return ins
| ((ones
- 1) << 10) | ((len
- right
) << 16);
291 #undef COUNT_TRAILING_ZERO
293 static sljit_si
load_immediate(struct sljit_compiler
*compiler
, sljit_si dst
, sljit_sw simm
)
295 sljit_uw imm
= (sljit_uw
)simm
;
296 sljit_si i
, zeros
, ones
, first
;
300 return push_inst(compiler
, MOVZ
| (imm
<< 5) | RD(dst
));
302 if (simm
>= -0x10000 && simm
< 0)
303 return push_inst(compiler
, MOVN
| ((~imm
& 0xffff) << 5) | RD(dst
));
305 if (imm
<= 0xffffffffl
) {
306 if ((imm
& 0xffff0000l
) == 0xffff0000)
307 return push_inst(compiler
, (MOVN
^ W_OP
) | ((~imm
& 0xffff) << 5) | RD(dst
));
308 if ((imm
& 0xffff) == 0xffff)
309 return push_inst(compiler
, (MOVN
^ W_OP
) | (1 << 21) | ((~imm
& 0xffff0000l
) >> (16 - 5)) | RD(dst
));
310 bitmask
= logical_imm(simm
, 16);
312 return push_inst(compiler
, (ORRI
^ W_OP
) | bitmask
| RN(TMP_ZERO
) | RD(dst
));
315 bitmask
= logical_imm(simm
, 32);
317 return push_inst(compiler
, ORRI
| bitmask
| RN(TMP_ZERO
) | RD(dst
));
320 if (imm
<= 0xffffffffl
) {
321 FAIL_IF(push_inst(compiler
, MOVZ
| ((imm
& 0xffff) << 5) | RD(dst
)));
322 return push_inst(compiler
, MOVK
| (1 << 21) | ((imm
& 0xffff0000l
) >> (16 - 5)) | RD(dst
));
325 if (simm
>= -0x100000000l
&& simm
< 0) {
326 FAIL_IF(push_inst(compiler
, MOVN
| ((~imm
& 0xffff) << 5) | RD(dst
)));
327 return push_inst(compiler
, MOVK
| (1 << 21) | ((imm
& 0xffff0000l
) >> (16 - 5)) | RD(dst
));
330 /* A large amount of number can be constructed from ORR and MOVx,
331 but computing them is costly. We don't */
335 for (i
= 4; i
> 0; i
--) {
336 if ((simm
& 0xffff) == 0)
338 if ((simm
& 0xffff) == 0xffff)
343 simm
= (sljit_sw
)imm
;
347 for (i
= 0; i
< 4; i
++) {
348 if (!(simm
& 0xffff)) {
354 FAIL_IF(push_inst(compiler
, MOVN
| (i
<< 21) | ((simm
& 0xffff) << 5) | RD(dst
)));
357 FAIL_IF(push_inst(compiler
, MOVK
| (i
<< 21) | ((~simm
& 0xffff) << 5) | RD(dst
)));
360 return SLJIT_SUCCESS
;
363 for (i
= 0; i
< 4; i
++) {
364 if (!(simm
& 0xffff)) {
370 FAIL_IF(push_inst(compiler
, MOVZ
| (i
<< 21) | ((simm
& 0xffff) << 5) | RD(dst
)));
373 FAIL_IF(push_inst(compiler
, MOVK
| (i
<< 21) | ((simm
& 0xffff) << 5) | RD(dst
)));
376 return SLJIT_SUCCESS
;
379 #define ARG1_IMM 0x0010000
380 #define ARG2_IMM 0x0020000
381 #define INT_OP 0x0040000
382 #define SET_FLAGS 0x0080000
383 #define UNUSED_RETURN 0x0100000
384 #define SLOW_DEST 0x0200000
385 #define SLOW_SRC1 0x0400000
386 #define SLOW_SRC2 0x0800000
388 #define CHECK_FLAGS(flag_bits) \
389 if (flags & SET_FLAGS) { \
390 inv_bits |= flag_bits; \
391 if (flags & UNUSED_RETURN) \
395 static sljit_si
emit_op_imm(struct sljit_compiler
*compiler
, sljit_si flags
, sljit_si dst
, sljit_sw arg1
, sljit_sw arg2
)
397 /* dst must be register, TMP_REG1
398 arg1 must be register, TMP_REG1, imm
399 arg2 must be register, TMP_REG2, imm */
400 sljit_ins inv_bits
= (flags
& INT_OP
) ? (1 << 31) : 0;
402 sljit_si op
= (flags
& 0xffff);
406 if (SLJIT_UNLIKELY((flags
& (ARG1_IMM
| ARG2_IMM
)) == (ARG1_IMM
| ARG2_IMM
))) {
407 /* Both are immediates. */
409 if (arg1
== 0 && op
!= SLJIT_ADD
&& op
!= SLJIT_SUB
)
412 FAIL_IF(load_immediate(compiler
, TMP_REG1
, arg1
));
417 if (flags
& (ARG1_IMM
| ARG2_IMM
)) {
418 reg
= (flags
& ARG2_IMM
) ? arg1
: arg2
;
419 imm
= (flags
& ARG2_IMM
) ? arg2
: arg1
;
427 /* No form with immediate operand (except imm 0, which
428 is represented by a ZERO register). */
431 SLJIT_ASSERT(!(flags
& SET_FLAGS
) && (flags
& ARG2_IMM
) && arg1
== TMP_REG1
);
432 return load_immediate(compiler
, dst
, imm
);
434 SLJIT_ASSERT(flags
& ARG2_IMM
);
435 FAIL_IF(load_immediate(compiler
, dst
, (flags
& INT_OP
) ? (~imm
& 0xffffffff) : ~imm
));
438 if (flags
& ARG1_IMM
)
444 CHECK_FLAGS(1 << 29);
445 return push_inst(compiler
, ((op
== SLJIT_ADD
? ADDI
: SUBI
) ^ inv_bits
) | RD(dst
) | RN(reg
));
447 if (imm
> 0 && imm
<= 0xfff) {
448 CHECK_FLAGS(1 << 29);
449 return push_inst(compiler
, (ADDI
^ inv_bits
) | RD(dst
) | RN(reg
) | (imm
<< 10));
452 if (nimm
> 0 && nimm
<= 0xfff) {
453 CHECK_FLAGS(1 << 29);
454 return push_inst(compiler
, (SUBI
^ inv_bits
) | RD(dst
) | RN(reg
) | (nimm
<< 10));
456 if (imm
> 0 && imm
<= 0xffffff && !(imm
& 0xfff)) {
457 CHECK_FLAGS(1 << 29);
458 return push_inst(compiler
, (ADDI
^ inv_bits
) | RD(dst
) | RN(reg
) | (1 << 22) | ((imm
>> 12) << 10));
460 if (nimm
> 0 && nimm
<= 0xffffff && !(nimm
& 0xfff)) {
461 CHECK_FLAGS(1 << 29);
462 return push_inst(compiler
, (SUBI
^ inv_bits
) | RD(dst
) | RN(reg
) | (1 << 22) | ((nimm
>> 12) << 10));
464 if (imm
> 0 && imm
<= 0xffffff && !(flags
& SET_FLAGS
)) {
465 FAIL_IF(push_inst(compiler
, (ADDI
^ inv_bits
) | RD(dst
) | RN(reg
) | (1 << 22) | ((imm
>> 12) << 10)));
466 return push_inst(compiler
, (ADDI
^ inv_bits
) | RD(dst
) | RN(dst
) | ((imm
& 0xfff) << 10));
468 if (nimm
> 0 && nimm
<= 0xffffff && !(flags
& SET_FLAGS
)) {
469 FAIL_IF(push_inst(compiler
, (SUBI
^ inv_bits
) | RD(dst
) | RN(reg
) | ((nimm
>> 12) << 10)));
470 return push_inst(compiler
, (SUBI
^ inv_bits
) | RD(dst
) | RN(dst
) | ((nimm
& 0xfff) << 10));
474 inst_bits
= logical_imm(imm
, LOGICAL_IMM_CHECK
| ((flags
& INT_OP
) ? 16 : 32));
477 CHECK_FLAGS(3 << 29);
478 return push_inst(compiler
, (ANDI
^ inv_bits
) | RD(dst
) | RN(reg
) | inst_bits
);
481 inst_bits
= logical_imm(imm
, LOGICAL_IMM_CHECK
| ((flags
& INT_OP
) ? 16 : 32));
488 FAIL_IF(push_inst(compiler
, (inst_bits
^ inv_bits
) | RD(dst
) | RN(reg
)));
491 if (flags
& ARG1_IMM
)
493 if (flags
& INT_OP
) {
495 FAIL_IF(push_inst(compiler
, (UBFM
^ inv_bits
) | RD(dst
) | RN(arg1
) | ((-imm
& 0x1f) << 16) | ((31 - imm
) << 10)));
499 FAIL_IF(push_inst(compiler
, (UBFM
^ inv_bits
) | RD(dst
) | RN(arg1
) | (1 << 22) | ((-imm
& 0x3f) << 16) | ((63 - imm
) << 10)));
504 if (flags
& ARG1_IMM
)
506 if (op
== SLJIT_ASHR
)
508 if (flags
& INT_OP
) {
510 FAIL_IF(push_inst(compiler
, (UBFM
^ inv_bits
) | RD(dst
) | RN(arg1
) | (imm
<< 16) | (31 << 10)));
514 FAIL_IF(push_inst(compiler
, (UBFM
^ inv_bits
) | RD(dst
) | RN(arg1
) | (1 << 22) | (imm
<< 16) | (63 << 10)));
522 if (flags
& ARG2_IMM
) {
526 FAIL_IF(load_immediate(compiler
, TMP_REG2
, arg2
));
534 FAIL_IF(load_immediate(compiler
, TMP_REG1
, arg1
));
540 /* Both arguments are registers. */
546 SLJIT_ASSERT(!(flags
& SET_FLAGS
) && arg1
== TMP_REG1
);
548 return SLJIT_SUCCESS
;
549 return push_inst(compiler
, ORR
| RD(dst
) | RN(TMP_ZERO
) | RM(arg2
));
552 SLJIT_ASSERT(!(flags
& SET_FLAGS
) && arg1
== TMP_REG1
);
553 return push_inst(compiler
, (UBFM
^ (1 << 31)) | RD(dst
) | RN(arg2
) | (7 << 10));
556 SLJIT_ASSERT(!(flags
& SET_FLAGS
) && arg1
== TMP_REG1
);
557 if (!(flags
& INT_OP
))
559 return push_inst(compiler
, (SBFM
^ inv_bits
) | RD(dst
) | RN(arg2
) | (7 << 10));
562 SLJIT_ASSERT(!(flags
& SET_FLAGS
) && arg1
== TMP_REG1
);
563 return push_inst(compiler
, (UBFM
^ (1 << 31)) | RD(dst
) | RN(arg2
) | (15 << 10));
566 SLJIT_ASSERT(!(flags
& SET_FLAGS
) && arg1
== TMP_REG1
);
567 if (!(flags
& INT_OP
))
569 return push_inst(compiler
, (SBFM
^ inv_bits
) | RD(dst
) | RN(arg2
) | (15 << 10));
572 SLJIT_ASSERT(!(flags
& SET_FLAGS
) && arg1
== TMP_REG1
);
573 if ((flags
& INT_OP
) && dst
== arg2
)
574 return SLJIT_SUCCESS
;
575 return push_inst(compiler
, (ORR
^ (1 << 31)) | RD(dst
) | RN(TMP_ZERO
) | RM(arg2
));
578 SLJIT_ASSERT(!(flags
& SET_FLAGS
) && arg1
== TMP_REG1
);
579 if ((flags
& INT_OP
) && dst
== arg2
)
580 return SLJIT_SUCCESS
;
581 return push_inst(compiler
, SBFM
| (1 << 22) | RD(dst
) | RN(arg2
) | (31 << 10));
583 SLJIT_ASSERT(arg1
== TMP_REG1
);
584 FAIL_IF(push_inst(compiler
, (ORN
^ inv_bits
) | RD(dst
) | RN(TMP_ZERO
) | RM(arg2
)));
587 SLJIT_ASSERT(arg1
== TMP_REG1
);
588 if (flags
& SET_FLAGS
)
590 return push_inst(compiler
, (SUB
^ inv_bits
) | RD(dst
) | RN(TMP_ZERO
) | RM(arg2
));
592 SLJIT_ASSERT(arg1
== TMP_REG1
);
593 FAIL_IF(push_inst(compiler
, (CLZ
^ inv_bits
) | RD(dst
) | RN(arg2
)));
596 CHECK_FLAGS(1 << 29);
597 return push_inst(compiler
, (ADD
^ inv_bits
) | RD(dst
) | RN(arg1
) | RM(arg2
));
599 CHECK_FLAGS(1 << 29);
600 return push_inst(compiler
, (ADC
^ inv_bits
) | RD(dst
) | RN(arg1
) | RM(arg2
));
602 CHECK_FLAGS(1 << 29);
603 return push_inst(compiler
, (SUB
^ inv_bits
) | RD(dst
) | RN(arg1
) | RM(arg2
));
605 CHECK_FLAGS(1 << 29);
606 return push_inst(compiler
, (SBC
^ inv_bits
) | RD(dst
) | RN(arg1
) | RM(arg2
));
608 if (!(flags
& SET_FLAGS
))
609 return push_inst(compiler
, (MADD
^ inv_bits
) | RD(dst
) | RN(arg1
) | RM(arg2
) | (31 << 10));
610 if (flags
& INT_OP
) {
611 FAIL_IF(push_inst(compiler
, SMADDL
| RD(dst
) | RN(arg1
) | RM(arg2
) | (31 << 10)));
612 FAIL_IF(push_inst(compiler
, SUBS
| RD(TMP_REG4
) | RN(TMP_ZERO
) | RM(dst
) | (2 << 22) | (31 << 10)));
613 return push_inst(compiler
, SUBS
| RD(TMP_ZERO
) | RN(TMP_REG4
) | RM(dst
) | (2 << 22) | (63 << 10));
615 FAIL_IF(push_inst(compiler
, SMULH
| RD(TMP_REG4
) | RN(arg1
) | RM(arg2
) | (31 << 10)));
616 FAIL_IF(push_inst(compiler
, MADD
| RD(dst
) | RN(arg1
) | RM(arg2
) | (31 << 10)));
617 return push_inst(compiler
, SUBS
| RD(TMP_ZERO
) | RN(TMP_REG4
) | RM(dst
) | (2 << 22) | (63 << 10));
619 CHECK_FLAGS(3 << 29);
620 return push_inst(compiler
, (AND
^ inv_bits
) | RD(dst
) | RN(arg1
) | RM(arg2
));
622 FAIL_IF(push_inst(compiler
, (ORR
^ inv_bits
) | RD(dst
) | RN(arg1
) | RM(arg2
)));
625 FAIL_IF(push_inst(compiler
, (EOR
^ inv_bits
) | RD(dst
) | RN(arg1
) | RM(arg2
)));
628 FAIL_IF(push_inst(compiler
, (LSLV
^ inv_bits
) | RD(dst
) | RN(arg1
) | RM(arg2
)));
631 FAIL_IF(push_inst(compiler
, (LSRV
^ inv_bits
) | RD(dst
) | RN(arg1
) | RM(arg2
)));
634 FAIL_IF(push_inst(compiler
, (ASRV
^ inv_bits
) | RD(dst
) | RN(arg1
) | RM(arg2
)));
639 return SLJIT_SUCCESS
;
642 if (flags
& SET_FLAGS
)
643 return push_inst(compiler
, (SUBS
^ inv_bits
) | RD(TMP_ZERO
) | RN(dst
) | RM(TMP_ZERO
));
644 return SLJIT_SUCCESS
;
651 #define ARG_TEST 0x08
653 #define BYTE_SIZE 0x000
654 #define HALF_SIZE 0x100
655 #define INT_SIZE 0x200
656 #define WORD_SIZE 0x300
658 #define MEM_SIZE_SHIFT(flags) ((flags) >> 8)
660 static SLJIT_CONST sljit_ins sljit_mem_imm
[4] = {
661 /* u l */ 0x39400000 /* ldrb [reg,imm] */,
662 /* u s */ 0x39000000 /* strb [reg,imm] */,
663 /* s l */ 0x39800000 /* ldrsb [reg,imm] */,
664 /* s s */ 0x39000000 /* strb [reg,imm] */,
667 static SLJIT_CONST sljit_ins sljit_mem_simm
[4] = {
668 /* u l */ 0x38400000 /* ldurb [reg,imm] */,
669 /* u s */ 0x38000000 /* sturb [reg,imm] */,
670 /* s l */ 0x38800000 /* ldursb [reg,imm] */,
671 /* s s */ 0x38000000 /* sturb [reg,imm] */,
674 static SLJIT_CONST sljit_ins sljit_mem_pre_simm
[4] = {
675 /* u l */ 0x38400c00 /* ldrb [reg,imm]! */,
676 /* u s */ 0x38000c00 /* strb [reg,imm]! */,
677 /* s l */ 0x38c00c00 /* ldrsb [reg,imm]! */,
678 /* s s */ 0x38000c00 /* strb [reg,imm]! */,
681 static SLJIT_CONST sljit_ins sljit_mem_reg
[4] = {
682 /* u l */ 0x38606800 /* ldrb [reg,reg] */,
683 /* u s */ 0x38206800 /* strb [reg,reg] */,
684 /* s l */ 0x38a06800 /* ldrsb [reg,reg] */,
685 /* s s */ 0x38206800 /* strb [reg,reg] */,
688 /* Helper function. Dst should be reg + value, using at most 1 instruction, flags does not set. */
689 static sljit_si
emit_set_delta(struct sljit_compiler
*compiler
, sljit_si dst
, sljit_si reg
, sljit_sw value
)
693 return push_inst(compiler
, ADDI
| RD(dst
) | RN(reg
) | (value
<< 10));
694 if (value
<= 0xffffff && !(value
& 0xfff))
695 return push_inst(compiler
, ADDI
| (1 << 22) | RD(dst
) | RN(reg
) | (value
>> 2));
700 return push_inst(compiler
, SUBI
| RD(dst
) | RN(reg
) | (value
<< 10));
701 if (value
<= 0xffffff && !(value
& 0xfff))
702 return push_inst(compiler
, SUBI
| (1 << 22) | RD(dst
) | RN(reg
) | (value
>> 2));
704 return SLJIT_ERR_UNSUPPORTED
;
707 /* Can perform an operation using at most 1 instruction. */
708 static sljit_si
getput_arg_fast(struct sljit_compiler
*compiler
, sljit_si flags
, sljit_si reg
, sljit_si arg
, sljit_sw argw
)
710 sljit_ui shift
= MEM_SIZE_SHIFT(flags
);
712 SLJIT_ASSERT(arg
& SLJIT_MEM
);
714 if (SLJIT_UNLIKELY(flags
& UPDATE
)) {
715 if ((arg
& REG_MASK
) && !(arg
& OFFS_REG_MASK
) && argw
<= 255 && argw
>= -256) {
716 if (SLJIT_UNLIKELY(flags
& ARG_TEST
))
721 FAIL_IF(push_inst(compiler
, sljit_mem_pre_simm
[flags
& 0x3]
722 | (shift
<< 30) | RT(reg
) | RN(arg
) | (argw
<< 12)));
728 if (SLJIT_UNLIKELY(arg
& OFFS_REG_MASK
)) {
730 if (argw
&& argw
!= shift
)
733 if (SLJIT_UNLIKELY(flags
& ARG_TEST
))
736 FAIL_IF(push_inst(compiler
, sljit_mem_reg
[flags
& 0x3] | (shift
<< 30) | RT(reg
)
737 | RN(arg
& REG_MASK
) | RM(OFFS_REG(arg
)) | (argw
? (1 << 12) : 0)));
742 if (argw
>= 0 && ((argw
>> shift
) <= 0xfff) && (argw
& ((1 << shift
) - 1)) == 0) {
743 if (SLJIT_UNLIKELY(flags
& ARG_TEST
))
746 FAIL_IF(push_inst(compiler
, sljit_mem_imm
[flags
& 0x3] | (shift
<< 30)
747 | RT(reg
) | RN(arg
) | (argw
<< (10 - shift
))));
751 if (argw
> 255 || argw
< -256)
754 FAIL_IF(push_inst(compiler
, sljit_mem_simm
[flags
& 0x3] | (shift
<< 30)
755 | RT(reg
) | RN(arg
) | ((argw
& 0x1ff) << 12)));
759 /* see getput_arg below.
760 Note: can_cache is called only for binary operators. Those
761 operators always uses word arguments without write back. */
762 static sljit_si
can_cache(sljit_si arg
, sljit_sw argw
, sljit_si next_arg
, sljit_sw next_argw
)
765 if ((arg
& OFFS_REG_MASK
) || !(next_arg
& SLJIT_MEM
))
768 if (!(arg
& REG_MASK
)) {
769 diff
= argw
- next_argw
;
770 if (diff
<= 0xfff && diff
>= -0xfff)
775 if (argw
== next_argw
)
778 diff
= argw
- next_argw
;
779 if (arg
== next_arg
&& diff
<= 0xfff && diff
>= -0xfff)
785 /* Emit the necessary instructions. See can_cache above. */
786 static sljit_si
getput_arg(struct sljit_compiler
*compiler
, sljit_si flags
, sljit_si reg
, sljit_si arg
, sljit_sw argw
, sljit_si next_arg
, sljit_sw next_argw
)
788 sljit_ui shift
= MEM_SIZE_SHIFT(flags
);
789 sljit_si tmp_r
, other_r
;
792 SLJIT_ASSERT(arg
& SLJIT_MEM
);
793 if (!(next_arg
& SLJIT_MEM
)) {
798 tmp_r
= (flags
& STORE
) ? TMP_REG3
: reg
;
800 if (SLJIT_UNLIKELY((flags
& UPDATE
) && (arg
& REG_MASK
))) {
801 /* Update only applies if a base register exists. */
802 other_r
= OFFS_REG(arg
);
804 if (argw
>= 0 && argw
<= 0xffffff) {
806 if ((argw
& 0xfff) != 0)
807 FAIL_IF(push_inst(compiler
, ADDI
| RD(arg
) | RN(arg
) | ((argw
& 0xfff) << 10)));
809 FAIL_IF(push_inst(compiler
, ADDI
| (1 << 22) | RD(arg
) | RN(arg
) | ((argw
>> 12) << 10)));
810 return push_inst(compiler
, sljit_mem_imm
[flags
& 0x3] | (shift
<< 30) | RT(reg
) | RN(arg
));
812 else if (argw
< 0 && argw
>= -0xffffff) {
815 if ((argw
& 0xfff) != 0)
816 FAIL_IF(push_inst(compiler
, SUBI
| RD(arg
) | RN(arg
) | ((argw
& 0xfff) << 10)));
818 FAIL_IF(push_inst(compiler
, SUBI
| (1 << 22) | RD(arg
) | RN(arg
) | ((argw
>> 12) << 10)));
819 return push_inst(compiler
, sljit_mem_imm
[flags
& 0x3] | (shift
<< 30) | RT(reg
) | RN(arg
));
822 if (compiler
->cache_arg
== SLJIT_MEM
) {
823 if (argw
== compiler
->cache_argw
) {
827 else if (emit_set_delta(compiler
, TMP_REG3
, TMP_REG3
, argw
- compiler
->cache_argw
) != SLJIT_ERR_UNSUPPORTED
) {
828 FAIL_IF(compiler
->error
);
829 compiler
->cache_argw
= argw
;
836 FAIL_IF(load_immediate(compiler
, TMP_REG3
, argw
));
837 compiler
->cache_arg
= SLJIT_MEM
;
838 compiler
->cache_argw
= argw
;
844 /* No caching here. */
846 FAIL_IF(push_inst(compiler
, ADD
| RD(arg
) | RN(arg
) | RM(other_r
) | ((argw
& 0x3) << 10)));
847 return push_inst(compiler
, sljit_mem_imm
[flags
& 0x3] | (shift
<< 30) | RT(reg
) | RN(arg
));
850 if (arg
& OFFS_REG_MASK
) {
851 other_r
= OFFS_REG(arg
);
853 FAIL_IF(push_inst(compiler
, ADD
| RD(tmp_r
) | RN(arg
) | RM(other_r
) | ((argw
& 0x3) << 10)));
854 return push_inst(compiler
, sljit_mem_imm
[flags
& 0x3] | (shift
<< 30) | RT(reg
) | RN(tmp_r
));
857 if (compiler
->cache_arg
== arg
) {
858 diff
= argw
- compiler
->cache_argw
;
859 if (diff
<= 255 && diff
>= -256)
860 return push_inst(compiler
, sljit_mem_simm
[flags
& 0x3] | (shift
<< 30)
861 | RT(reg
) | RN(TMP_REG3
) | ((diff
& 0x1ff) << 12));
862 if (emit_set_delta(compiler
, TMP_REG3
, TMP_REG3
, diff
) != SLJIT_ERR_UNSUPPORTED
) {
863 FAIL_IF(compiler
->error
);
864 return push_inst(compiler
, sljit_mem_imm
[flags
& 0x3] | (shift
<< 30) | RT(reg
) | RN(arg
));
868 diff
= argw
- next_argw
;
869 next_arg
= (arg
& REG_MASK
) && (arg
== next_arg
) && diff
<= 0xfff && diff
>= -0xfff && diff
!= 0;
871 if (arg
&& compiler
->cache_arg
== SLJIT_MEM
) {
872 if (compiler
->cache_argw
== argw
)
873 return push_inst(compiler
, sljit_mem_reg
[flags
& 0x3] | (shift
<< 30) | RT(reg
) | RN(arg
) | RM(TMP_REG3
));
874 if (emit_set_delta(compiler
, TMP_REG3
, TMP_REG3
, argw
- compiler
->cache_argw
) != SLJIT_ERR_UNSUPPORTED
) {
875 FAIL_IF(compiler
->error
);
876 compiler
->cache_argw
= argw
;
877 return push_inst(compiler
, sljit_mem_reg
[flags
& 0x3] | (shift
<< 30) | RT(reg
) | RN(arg
) | RM(TMP_REG3
));
881 compiler
->cache_argw
= argw
;
882 if (next_arg
&& emit_set_delta(compiler
, TMP_REG3
, arg
, argw
) != SLJIT_ERR_UNSUPPORTED
) {
883 FAIL_IF(compiler
->error
);
884 compiler
->cache_arg
= SLJIT_MEM
| arg
;
888 FAIL_IF(load_immediate(compiler
, TMP_REG3
, argw
));
889 compiler
->cache_arg
= SLJIT_MEM
;
892 FAIL_IF(push_inst(compiler
, ADD
| RD(TMP_REG3
) | RN(TMP_REG3
) | RM(arg
)));
893 compiler
->cache_arg
= SLJIT_MEM
| arg
;
899 return push_inst(compiler
, sljit_mem_reg
[flags
& 0x3] | (shift
<< 30) | RT(reg
) | RN(arg
) | RM(TMP_REG3
));
900 return push_inst(compiler
, sljit_mem_imm
[flags
& 0x3] | (shift
<< 30) | RT(reg
) | RN(TMP_REG3
));
903 static SLJIT_INLINE sljit_si
emit_op_mem(struct sljit_compiler
*compiler
, sljit_si flags
, sljit_si reg
, sljit_si arg
, sljit_sw argw
)
905 if (getput_arg_fast(compiler
, flags
, reg
, arg
, argw
))
906 return compiler
->error
;
907 compiler
->cache_arg
= 0;
908 compiler
->cache_argw
= 0;
909 return getput_arg(compiler
, flags
, reg
, arg
, argw
, 0, 0);
912 static SLJIT_INLINE sljit_si
emit_op_mem2(struct sljit_compiler
*compiler
, sljit_si flags
, sljit_si reg
, sljit_si arg1
, sljit_sw arg1w
, sljit_si arg2
, sljit_sw arg2w
)
914 if (getput_arg_fast(compiler
, flags
, reg
, arg1
, arg1w
))
915 return compiler
->error
;
916 return getput_arg(compiler
, flags
, reg
, arg1
, arg1w
, arg2
, arg2w
);
919 /* --------------------------------------------------------------------- */
921 /* --------------------------------------------------------------------- */
923 SLJIT_API_FUNC_ATTRIBUTE sljit_si
sljit_emit_enter(struct sljit_compiler
*compiler
, sljit_si args
, sljit_si scratches
, sljit_si saveds
, sljit_si local_size
)
926 check_sljit_emit_enter(compiler
, args
, scratches
, saveds
, local_size
);
928 compiler
->scratches
= scratches
;
929 compiler
->saveds
= saveds
;
930 #if (defined SLJIT_DEBUG && SLJIT_DEBUG)
931 compiler
->logical_local_size
= local_size
;
933 compiler
->locals_offset
= (2 + saveds
) * sizeof(sljit_sw
);
934 local_size
= (compiler
->locals_offset
+ local_size
+ 15) & ~15;
935 compiler
->local_size
= local_size
;
937 if (local_size
<= (64 << 3))
938 FAIL_IF(push_inst(compiler
, STP_PRE
| 29 | RT2(TMP_LR
)
939 | RN(SLJIT_LOCALS_REG
) | ((-(local_size
>> 3) & 0x7f) << 15)));
941 local_size
-= (64 << 3);
942 if (local_size
> 0xfff) {
943 FAIL_IF(push_inst(compiler
, SUBI
| RD(SLJIT_LOCALS_REG
) | RN(SLJIT_LOCALS_REG
) | ((local_size
>> 12) << 10) | (1 << 22)));
947 FAIL_IF(push_inst(compiler
, SUBI
| RD(SLJIT_LOCALS_REG
) | RN(SLJIT_LOCALS_REG
) | (local_size
<< 10)));
948 FAIL_IF(push_inst(compiler
, STP_PRE
| 29 | RT2(TMP_LR
) | RN(SLJIT_LOCALS_REG
) | (0x40 << 15)));
952 FAIL_IF(push_inst(compiler
, STP
| RT(SLJIT_SAVED_REG1
) | RT2(SLJIT_SAVED_REG2
) | RN(SLJIT_LOCALS_REG
) | (2 << 15)));
954 FAIL_IF(push_inst(compiler
, STP
| RT(SLJIT_SAVED_REG3
) | RT2(SLJIT_SAVED_EREG1
) | RN(SLJIT_LOCALS_REG
) | (4 << 15)));
956 FAIL_IF(push_inst(compiler
, STRI
| RT(SLJIT_SAVED_REG1
) | RN(SLJIT_LOCALS_REG
) | (2 << 10)));
958 FAIL_IF(push_inst(compiler
, STRI
| RT(SLJIT_SAVED_REG3
) | RN(SLJIT_LOCALS_REG
) | (4 << 10)));
960 FAIL_IF(push_inst(compiler
, STRI
| RT(SLJIT_SAVED_EREG2
) | RN(SLJIT_LOCALS_REG
) | (6 << 10)));
963 FAIL_IF(push_inst(compiler
, ORR
| RD(SLJIT_SAVED_REG1
) | RN(TMP_ZERO
) | RM(SLJIT_SCRATCH_REG1
)));
965 FAIL_IF(push_inst(compiler
, ORR
| RD(SLJIT_SAVED_REG2
) | RN(TMP_ZERO
) | RM(SLJIT_SCRATCH_REG2
)));
967 FAIL_IF(push_inst(compiler
, ORR
| RD(SLJIT_SAVED_REG3
) | RN(TMP_ZERO
) | RM(SLJIT_SCRATCH_REG3
)));
969 return SLJIT_SUCCESS
;
972 SLJIT_API_FUNC_ATTRIBUTE
void sljit_set_context(struct sljit_compiler
*compiler
, sljit_si args
, sljit_si scratches
, sljit_si saveds
, sljit_si local_size
)
975 check_sljit_set_context(compiler
, args
, scratches
, saveds
, local_size
);
977 compiler
->scratches
= scratches
;
978 compiler
->saveds
= saveds
;
979 #if (defined SLJIT_DEBUG && SLJIT_DEBUG)
980 compiler
->logical_local_size
= local_size
;
982 compiler
->locals_offset
= (2 + saveds
) * sizeof(sljit_sw
);
983 compiler
->local_size
= (compiler
->locals_offset
+ local_size
+ 15) & ~15;
986 SLJIT_API_FUNC_ATTRIBUTE sljit_si
sljit_emit_return(struct sljit_compiler
*compiler
, sljit_si op
, sljit_si src
, sljit_sw srcw
)
988 sljit_si saveds
, local_size
;
991 check_sljit_emit_return(compiler
, op
, src
, srcw
);
992 ADJUST_LOCAL_OFFSET(src
, srcw
);
994 FAIL_IF(emit_mov_before_return(compiler
, op
, src
, srcw
));
996 saveds
= compiler
->saveds
;
999 FAIL_IF(push_inst(compiler
, LDP
| RT(SLJIT_SAVED_REG1
) | RT2(SLJIT_SAVED_REG2
) | RN(SLJIT_LOCALS_REG
) | (2 << 15)));
1001 FAIL_IF(push_inst(compiler
, LDP
| RT(SLJIT_SAVED_REG3
) | RT2(SLJIT_SAVED_EREG1
) | RN(SLJIT_LOCALS_REG
) | (4 << 15)));
1003 FAIL_IF(push_inst(compiler
, LDRI
| RT(SLJIT_SAVED_REG1
) | RN(SLJIT_LOCALS_REG
) | (2 << 10)));
1005 FAIL_IF(push_inst(compiler
, LDRI
| RT(SLJIT_SAVED_REG3
) | RN(SLJIT_LOCALS_REG
) | (4 << 10)));
1007 FAIL_IF(push_inst(compiler
, LDRI
| RT(SLJIT_SAVED_EREG2
) | RN(SLJIT_LOCALS_REG
) | (6 << 10)));
1009 local_size
= compiler
->local_size
;
1011 if (local_size
<= (62 << 3))
1012 FAIL_IF(push_inst(compiler
, LDP_PST
| 29 | RT2(TMP_LR
)
1013 | RN(SLJIT_LOCALS_REG
) | (((local_size
>> 3) & 0x7f) << 15)));
1015 FAIL_IF(push_inst(compiler
, LDP_PST
| 29 | RT2(TMP_LR
) | RN(SLJIT_LOCALS_REG
) | (0x3e << 15)));
1016 local_size
-= (62 << 3);
1017 if (local_size
> 0xfff) {
1018 FAIL_IF(push_inst(compiler
, ADDI
| RD(SLJIT_LOCALS_REG
) | RN(SLJIT_LOCALS_REG
) | ((local_size
>> 12) << 10) | (1 << 22)));
1019 local_size
&= 0xfff;
1022 FAIL_IF(push_inst(compiler
, ADDI
| RD(SLJIT_LOCALS_REG
) | RN(SLJIT_LOCALS_REG
) | (local_size
<< 10)));
1025 FAIL_IF(push_inst(compiler
, RET
| RN(TMP_LR
)));
1026 return SLJIT_SUCCESS
;
1029 /* --------------------------------------------------------------------- */
1031 /* --------------------------------------------------------------------- */
1033 SLJIT_API_FUNC_ATTRIBUTE sljit_si
sljit_emit_op0(struct sljit_compiler
*compiler
, sljit_si op
)
1036 check_sljit_emit_op0(compiler
, op
);
1038 op
= GET_OPCODE(op
);
1040 case SLJIT_BREAKPOINT
:
1041 push_inst(compiler
, BRK
);
1044 push_inst(compiler
, NOP
);
1048 return SLJIT_SUCCESS
;
1051 SLJIT_API_FUNC_ATTRIBUTE sljit_si
sljit_emit_op1(struct sljit_compiler
*compiler
, sljit_si op
,
1052 sljit_si dst
, sljit_sw dstw
,
1053 sljit_si src
, sljit_sw srcw
)
1055 sljit_si dst_r
, flags
, mem_flags
;
1056 sljit_si op_flags
= GET_ALL_FLAGS(op
);
1059 check_sljit_emit_op1(compiler
, op
, dst
, dstw
, src
, srcw
);
1060 ADJUST_LOCAL_OFFSET(dst
, dstw
);
1061 ADJUST_LOCAL_OFFSET(src
, srcw
);
1063 compiler
->cache_arg
= 0;
1064 compiler
->cache_argw
= 0;
1066 dst_r
= (dst
>= SLJIT_SCRATCH_REG1
&& dst
<= REG_MASK
) ? dst
: TMP_REG1
;
1068 op
= GET_OPCODE(op
);
1069 if (op
>= SLJIT_MOV
&& op
<= SLJIT_MOVU_P
) {
1077 if (src
& SLJIT_IMM
)
1078 srcw
= (sljit_ub
)srcw
;
1081 flags
= BYTE_SIZE
| SIGNED
;
1082 if (src
& SLJIT_IMM
)
1083 srcw
= (sljit_sb
)srcw
;
1087 if (src
& SLJIT_IMM
)
1088 srcw
= (sljit_uh
)srcw
;
1091 flags
= HALF_SIZE
| SIGNED
;
1092 if (src
& SLJIT_IMM
)
1093 srcw
= (sljit_sh
)srcw
;
1097 if (src
& SLJIT_IMM
)
1098 srcw
= (sljit_ui
)srcw
;
1101 flags
= INT_SIZE
| SIGNED
;
1102 if (src
& SLJIT_IMM
)
1103 srcw
= (sljit_si
)srcw
;
1107 flags
= WORD_SIZE
| UPDATE
;
1110 flags
= BYTE_SIZE
| UPDATE
;
1111 if (src
& SLJIT_IMM
)
1112 srcw
= (sljit_ub
)srcw
;
1115 flags
= BYTE_SIZE
| SIGNED
| UPDATE
;
1116 if (src
& SLJIT_IMM
)
1117 srcw
= (sljit_sb
)srcw
;
1120 flags
= HALF_SIZE
| UPDATE
;
1121 if (src
& SLJIT_IMM
)
1122 srcw
= (sljit_uh
)srcw
;
1125 flags
= HALF_SIZE
| SIGNED
| UPDATE
;
1126 if (src
& SLJIT_IMM
)
1127 srcw
= (sljit_sh
)srcw
;
1130 flags
= INT_SIZE
| UPDATE
;
1131 if (src
& SLJIT_IMM
)
1132 srcw
= (sljit_ui
)srcw
;
1135 flags
= INT_SIZE
| SIGNED
| UPDATE
;
1136 if (src
& SLJIT_IMM
)
1137 srcw
= (sljit_si
)srcw
;
1140 SLJIT_ASSERT_STOP();
1145 if (src
& SLJIT_IMM
)
1146 FAIL_IF(emit_op_imm(compiler
, SLJIT_MOV
| ARG2_IMM
, dst_r
, TMP_REG1
, srcw
));
1147 else if (src
& SLJIT_MEM
) {
1148 if (getput_arg_fast(compiler
, flags
, dst_r
, src
, srcw
))
1149 FAIL_IF(compiler
->error
);
1151 FAIL_IF(getput_arg(compiler
, flags
, dst_r
, src
, srcw
, dst
, dstw
));
1153 if (dst_r
!= TMP_REG1
)
1154 return emit_op_imm(compiler
, op
| ((op_flags
& SLJIT_INT_OP
) ? INT_OP
: 0), dst_r
, TMP_REG1
, src
);
1158 if (dst
& SLJIT_MEM
) {
1159 if (getput_arg_fast(compiler
, flags
| STORE
, dst_r
, dst
, dstw
))
1160 return compiler
->error
;
1162 return getput_arg(compiler
, flags
| STORE
, dst_r
, dst
, dstw
, 0, 0);
1164 return SLJIT_SUCCESS
;
1167 flags
= GET_FLAGS(op_flags
) ? SET_FLAGS
: 0;
1168 mem_flags
= WORD_SIZE
;
1169 if (op
& SLJIT_INT_OP
) {
1171 mem_flags
= INT_SIZE
;
1174 if (dst
== SLJIT_UNUSED
)
1175 flags
|= UNUSED_RETURN
;
1177 if (src
& SLJIT_MEM
) {
1178 if (getput_arg_fast(compiler
, mem_flags
, TMP_REG2
, src
, srcw
))
1179 FAIL_IF(compiler
->error
);
1181 FAIL_IF(getput_arg(compiler
, mem_flags
, TMP_REG2
, src
, srcw
, dst
, dstw
));
1185 if (src
& SLJIT_IMM
) {
1187 if (op_flags
& SLJIT_INT_OP
)
1188 srcw
= (sljit_si
)srcw
;
1192 emit_op_imm(compiler
, flags
| op
, dst_r
, TMP_REG1
, srcw
);
1194 if (dst
& SLJIT_MEM
) {
1195 if (getput_arg_fast(compiler
, mem_flags
| STORE
, dst_r
, dst
, dstw
))
1196 return compiler
->error
;
1198 return getput_arg(compiler
, mem_flags
| STORE
, dst_r
, dst
, dstw
, 0, 0);
1200 return SLJIT_SUCCESS
;
1203 SLJIT_API_FUNC_ATTRIBUTE sljit_si
sljit_emit_op2(struct sljit_compiler
*compiler
, sljit_si op
,
1204 sljit_si dst
, sljit_sw dstw
,
1205 sljit_si src1
, sljit_sw src1w
,
1206 sljit_si src2
, sljit_sw src2w
)
1208 sljit_si dst_r
, flags
, mem_flags
;
1211 check_sljit_emit_op2(compiler
, op
, dst
, dstw
, src1
, src1w
, src2
, src2w
);
1212 ADJUST_LOCAL_OFFSET(dst
, dstw
);
1213 ADJUST_LOCAL_OFFSET(src1
, src1w
);
1214 ADJUST_LOCAL_OFFSET(src2
, src2w
);
1216 compiler
->cache_arg
= 0;
1217 compiler
->cache_argw
= 0;
1219 dst_r
= (dst
>= SLJIT_SCRATCH_REG1
&& dst
<= REG_MASK
) ? dst
: TMP_REG1
;
1220 flags
= GET_FLAGS(op
) ? SET_FLAGS
: 0;
1221 mem_flags
= WORD_SIZE
;
1222 if (op
& SLJIT_INT_OP
) {
1224 mem_flags
= INT_SIZE
;
1227 if (dst
== SLJIT_UNUSED
)
1228 flags
|= UNUSED_RETURN
;
1230 if ((dst
& SLJIT_MEM
) && !getput_arg_fast(compiler
, mem_flags
| STORE
| ARG_TEST
, TMP_REG1
, dst
, dstw
))
1233 if (src1
& SLJIT_MEM
) {
1234 if (getput_arg_fast(compiler
, mem_flags
, TMP_REG1
, src1
, src1w
))
1235 FAIL_IF(compiler
->error
);
1239 if (src2
& SLJIT_MEM
) {
1240 if (getput_arg_fast(compiler
, mem_flags
, TMP_REG2
, src2
, src2w
))
1241 FAIL_IF(compiler
->error
);
1246 if ((flags
& (SLOW_SRC1
| SLOW_SRC2
)) == (SLOW_SRC1
| SLOW_SRC2
)) {
1247 if (!can_cache(src1
, src1w
, src2
, src2w
) && can_cache(src1
, src1w
, dst
, dstw
)) {
1248 FAIL_IF(getput_arg(compiler
, mem_flags
, TMP_REG2
, src2
, src2w
, src1
, src1w
));
1249 FAIL_IF(getput_arg(compiler
, mem_flags
, TMP_REG1
, src1
, src1w
, dst
, dstw
));
1252 FAIL_IF(getput_arg(compiler
, mem_flags
, TMP_REG1
, src1
, src1w
, src2
, src2w
));
1253 FAIL_IF(getput_arg(compiler
, mem_flags
, TMP_REG2
, src2
, src2w
, dst
, dstw
));
1256 else if (flags
& SLOW_SRC1
)
1257 FAIL_IF(getput_arg(compiler
, mem_flags
, TMP_REG1
, src1
, src1w
, dst
, dstw
));
1258 else if (flags
& SLOW_SRC2
)
1259 FAIL_IF(getput_arg(compiler
, mem_flags
, TMP_REG2
, src2
, src2w
, dst
, dstw
));
1261 if (src1
& SLJIT_MEM
)
1263 if (src2
& SLJIT_MEM
)
1266 if (src1
& SLJIT_IMM
)
1270 if (src2
& SLJIT_IMM
)
1275 emit_op_imm(compiler
, flags
| GET_OPCODE(op
), dst_r
, src1w
, src2w
);
1277 if (dst
& SLJIT_MEM
) {
1278 if (!(flags
& SLOW_DEST
)) {
1279 getput_arg_fast(compiler
, mem_flags
| STORE
, dst_r
, dst
, dstw
);
1280 return compiler
->error
;
1282 return getput_arg(compiler
, mem_flags
| STORE
, TMP_REG1
, dst
, dstw
, 0, 0);
1285 return SLJIT_SUCCESS
;
1288 SLJIT_API_FUNC_ATTRIBUTE sljit_si
sljit_get_register_index(sljit_si reg
)
1290 check_sljit_get_register_index(reg
);
1291 return reg_map
[reg
];
1294 SLJIT_API_FUNC_ATTRIBUTE sljit_si
sljit_get_float_register_index(sljit_si reg
)
1296 check_sljit_get_float_register_index(reg
);
1300 SLJIT_API_FUNC_ATTRIBUTE sljit_si
sljit_emit_op_custom(struct sljit_compiler
*compiler
,
1301 void *instruction
, sljit_si size
)
1304 check_sljit_emit_op_custom(compiler
, instruction
, size
);
1305 SLJIT_ASSERT(size
== 4);
1307 return push_inst(compiler
, *(sljit_ins
*)instruction
);
1310 /* --------------------------------------------------------------------- */
1311 /* Floating point operators */
1312 /* --------------------------------------------------------------------- */
1314 SLJIT_API_FUNC_ATTRIBUTE sljit_si
sljit_is_fpu_available(void)
1319 static sljit_si
emit_fop_mem(struct sljit_compiler
*compiler
, sljit_si flags
, sljit_si reg
, sljit_si arg
, sljit_sw argw
)
1321 sljit_ui shift
= MEM_SIZE_SHIFT(flags
);
1322 sljit_ins ins_bits
= (shift
<< 30);
1326 SLJIT_ASSERT(arg
& SLJIT_MEM
);
1328 if (!(flags
& STORE
))
1329 ins_bits
|= 1 << 22;
1331 if (arg
& OFFS_REG_MASK
) {
1333 if (!argw
|| argw
== shift
)
1334 return push_inst(compiler
, STR_FR
| ins_bits
| VT(reg
)
1335 | RN(arg
& REG_MASK
) | RM(OFFS_REG(arg
)) | (argw
? (1 << 12) : 0));
1336 other_r
= OFFS_REG(arg
);
1338 FAIL_IF(push_inst(compiler
, ADD
| RD(TMP_REG1
) | RN(arg
) | RM(other_r
) | (argw
<< 10)));
1344 if (arg
&& argw
>= 0 && ((argw
>> shift
) <= 0xfff) && (argw
& ((1 << shift
) - 1)) == 0)
1345 return push_inst(compiler
, STR_F
| ins_bits
| VT(reg
) | RN(arg
) | (argw
<< (10 - shift
)));
1347 if (arg
&& argw
<= 255 && argw
>= -256)
1348 return push_inst(compiler
, STUR_F
| ins_bits
| VT(reg
) | RN(arg
) | ((argw
& 0x1ff) << 12));
1351 if (compiler
->cache_arg
== SLJIT_MEM
&& argw
!= compiler
->cache_argw
) {
1352 diff
= argw
- compiler
->cache_argw
;
1353 if (!arg
&& diff
<= 255 && diff
>= -256)
1354 return push_inst(compiler
, STUR_F
| ins_bits
| VT(reg
) | RN(TMP_REG3
) | ((diff
& 0x1ff) << 12));
1355 if (emit_set_delta(compiler
, TMP_REG3
, TMP_REG3
, argw
- compiler
->cache_argw
) != SLJIT_ERR_UNSUPPORTED
) {
1356 FAIL_IF(compiler
->error
);
1357 compiler
->cache_argw
= argw
;
1361 if (compiler
->cache_arg
!= SLJIT_MEM
|| argw
!= compiler
->cache_argw
) {
1362 compiler
->cache_arg
= SLJIT_MEM
;
1363 compiler
->cache_argw
= argw
;
1364 FAIL_IF(load_immediate(compiler
, TMP_REG3
, argw
));
1368 return push_inst(compiler
, STR_FR
| ins_bits
| VT(reg
) | RN(arg
) | RM(TMP_REG3
));
1369 return push_inst(compiler
, STR_F
| ins_bits
| VT(reg
) | RN(TMP_REG3
));
1372 SLJIT_API_FUNC_ATTRIBUTE sljit_si
sljit_emit_fop1(struct sljit_compiler
*compiler
, sljit_si op
,
1373 sljit_si dst
, sljit_sw dstw
,
1374 sljit_si src
, sljit_sw srcw
)
1376 sljit_si dst_r
, mem_flags
;
1379 check_sljit_emit_fop1(compiler
, op
, dst
, dstw
, src
, srcw
);
1381 compiler
->cache_arg
= 0;
1382 compiler
->cache_argw
= 0;
1383 mem_flags
= (op
& SLJIT_SINGLE_OP
) ? INT_SIZE
: WORD_SIZE
;
1385 dst_r
= (dst
<= REG_MASK
) ? dst
: TMP_FREG1
;
1386 if (src
& SLJIT_MEM
) {
1387 emit_fop_mem(compiler
, mem_flags
, dst_r
, src
, srcw
);
1391 if (dst
& SLJIT_MEM
)
1392 return emit_fop_mem(compiler
, mem_flags
| STORE
, TMP_FREG1
, dst
, dstw
);
1393 return SLJIT_SUCCESS
;
1396 SLJIT_API_FUNC_ATTRIBUTE sljit_si
sljit_emit_fop2(struct sljit_compiler
*compiler
, sljit_si op
,
1397 sljit_si dst
, sljit_sw dstw
,
1398 sljit_si src1
, sljit_sw src1w
,
1399 sljit_si src2
, sljit_sw src2w
)
1402 check_sljit_emit_fop2(compiler
, op
, dst
, dstw
, src1
, src1w
, src2
, src2w
);
1404 compiler
->cache_arg
= 0;
1405 compiler
->cache_argw
= 0;
1407 return SLJIT_SUCCESS
;
1410 /* --------------------------------------------------------------------- */
1411 /* Other instructions */
1412 /* --------------------------------------------------------------------- */
1414 SLJIT_API_FUNC_ATTRIBUTE sljit_si
sljit_emit_fast_enter(struct sljit_compiler
*compiler
, sljit_si dst
, sljit_sw dstw
)
1417 check_sljit_emit_fast_enter(compiler
, dst
, dstw
);
1418 ADJUST_LOCAL_OFFSET(dst
, dstw
);
1420 return SLJIT_SUCCESS
;
1423 SLJIT_API_FUNC_ATTRIBUTE sljit_si
sljit_emit_fast_return(struct sljit_compiler
*compiler
, sljit_si src
, sljit_sw srcw
)
1426 check_sljit_emit_fast_return(compiler
, src
, srcw
);
1427 ADJUST_LOCAL_OFFSET(src
, srcw
);
1429 return SLJIT_SUCCESS
;
1432 /* --------------------------------------------------------------------- */
1433 /* Conditional instructions */
1434 /* --------------------------------------------------------------------- */
1436 static sljit_uw
get_cc(sljit_si type
)
1440 case SLJIT_C_MUL_NOT_OVERFLOW
:
1441 case SLJIT_C_FLOAT_EQUAL
:
1444 case SLJIT_C_NOT_EQUAL
:
1445 case SLJIT_C_MUL_OVERFLOW
:
1446 case SLJIT_C_FLOAT_NOT_EQUAL
:
1450 case SLJIT_C_FLOAT_LESS
:
1453 case SLJIT_C_GREATER_EQUAL
:
1454 case SLJIT_C_FLOAT_GREATER_EQUAL
:
1457 case SLJIT_C_GREATER
:
1458 case SLJIT_C_FLOAT_GREATER
:
1461 case SLJIT_C_LESS_EQUAL
:
1462 case SLJIT_C_FLOAT_LESS_EQUAL
:
1465 case SLJIT_C_SIG_LESS
:
1468 case SLJIT_C_SIG_GREATER_EQUAL
:
1471 case SLJIT_C_SIG_GREATER
:
1474 case SLJIT_C_SIG_LESS_EQUAL
:
1477 case SLJIT_C_OVERFLOW
:
1478 case SLJIT_C_FLOAT_UNORDERED
:
1481 case SLJIT_C_NOT_OVERFLOW
:
1482 case SLJIT_C_FLOAT_ORDERED
:
1485 default: /* SLJIT_JUMP */
1490 SLJIT_API_FUNC_ATTRIBUTE
struct sljit_label
* sljit_emit_label(struct sljit_compiler
*compiler
)
1492 struct sljit_label
*label
;
1495 check_sljit_emit_label(compiler
);
1497 if (compiler
->last_label
&& compiler
->last_label
->size
== compiler
->size
)
1498 return compiler
->last_label
;
1500 label
= (struct sljit_label
*)ensure_abuf(compiler
, sizeof(struct sljit_label
));
1501 PTR_FAIL_IF(!label
);
1502 set_label(label
, compiler
);
1506 SLJIT_API_FUNC_ATTRIBUTE
struct sljit_jump
* sljit_emit_jump(struct sljit_compiler
*compiler
, sljit_si type
)
1508 struct sljit_jump
*jump
;
1511 check_sljit_emit_jump(compiler
, type
);
1513 jump
= (struct sljit_jump
*)ensure_abuf(compiler
, sizeof(struct sljit_jump
));
1515 set_jump(jump
, compiler
, type
& SLJIT_REWRITABLE_JUMP
);
1521 SLJIT_API_FUNC_ATTRIBUTE sljit_si
sljit_emit_ijump(struct sljit_compiler
*compiler
, sljit_si type
, sljit_si src
, sljit_sw srcw
)
1524 check_sljit_emit_ijump(compiler
, type
, src
, srcw
);
1525 ADJUST_LOCAL_OFFSET(src
, srcw
);
1527 return SLJIT_SUCCESS
;
1530 SLJIT_API_FUNC_ATTRIBUTE sljit_si
sljit_emit_op_flags(struct sljit_compiler
*compiler
, sljit_si op
,
1531 sljit_si dst
, sljit_sw dstw
,
1532 sljit_si src
, sljit_sw srcw
,
1535 sljit_si dst_r
, flags
, mem_flags
;
1539 check_sljit_emit_op_flags(compiler
, op
, dst
, dstw
, src
, srcw
, type
);
1540 ADJUST_LOCAL_OFFSET(dst
, dstw
);
1541 ADJUST_LOCAL_OFFSET(src
, srcw
);
1543 if (dst
== SLJIT_UNUSED
)
1544 return SLJIT_SUCCESS
;
1546 cc
= get_cc(type
) ^ 0x1;
1547 dst_r
= (dst
<= REG_MASK
) ? dst
: TMP_REG1
;
1549 if (GET_OPCODE(op
) < SLJIT_ADD
) {
1550 FAIL_IF(push_inst(compiler
, CSINC
| (cc
<< 12) | RD(dst_r
) | RN(TMP_ZERO
) | RM(TMP_ZERO
)));
1551 if (dst_r
!= TMP_REG1
)
1552 return SLJIT_SUCCESS
;
1553 return emit_op_mem(compiler
, (GET_OPCODE(op
) == SLJIT_MOV
? WORD_SIZE
: INT_SIZE
) | STORE
, TMP_REG1
, dst
, dstw
);
1556 compiler
->cache_arg
= 0;
1557 compiler
->cache_argw
= 0;
1558 flags
= GET_FLAGS(op
) ? SET_FLAGS
: 0;
1559 mem_flags
= WORD_SIZE
;
1560 if (op
& SLJIT_INT_OP
) {
1562 mem_flags
= INT_SIZE
;
1565 if (src
& SLJIT_MEM
) {
1566 FAIL_IF(emit_op_mem2(compiler
, mem_flags
, TMP_REG1
, src
, srcw
, dst
, dstw
));
1569 } else if (src
& SLJIT_IMM
)
1572 FAIL_IF(push_inst(compiler
, CSINC
| (cc
<< 12) | RD(TMP_REG2
) | RN(TMP_ZERO
) | RM(TMP_ZERO
)));
1573 emit_op_imm(compiler
, flags
| GET_OPCODE(op
), dst_r
, src
, TMP_REG2
);
1575 if (dst_r
!= TMP_REG1
)
1576 return SLJIT_SUCCESS
;
1577 return emit_op_mem2(compiler
, mem_flags
| STORE
, TMP_REG2
, dst
, dstw
, 0, 0);
1580 SLJIT_API_FUNC_ATTRIBUTE
struct sljit_const
* sljit_emit_const(struct sljit_compiler
*compiler
, sljit_si dst
, sljit_sw dstw
, sljit_sw init_value
)
1582 struct sljit_const
*const_
;
1585 check_sljit_emit_const(compiler
, dst
, dstw
, init_value
);
1586 ADJUST_LOCAL_OFFSET(dst
, dstw
);
1588 const_
= (struct sljit_const
*)ensure_abuf(compiler
, sizeof(struct sljit_const
));
1589 PTR_FAIL_IF(!const_
);
1590 set_const(const_
, compiler
);
1595 SLJIT_API_FUNC_ATTRIBUTE
void sljit_set_jump_addr(sljit_uw addr
, sljit_uw new_addr
)
1599 SLJIT_API_FUNC_ATTRIBUTE
void sljit_set_const(sljit_uw addr
, sljit_sw new_constant
)