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)
29 #if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
30 return "x86" SLJIT_CPUINFO
" ABI:fastcall";
32 return "x86" SLJIT_CPUINFO
;
58 8 - R8 - From now on REX prefix is required
68 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
70 /* Last register + 1. */
71 #define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
73 static const sljit_u8 reg_map
[SLJIT_NUMBER_OF_REGISTERS
+ 3] = {
74 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 7, 6, 3, 4, 5
77 #define CHECK_EXTRA_REGS(p, w, do) \
78 if (p >= SLJIT_R3 && p <= SLJIT_S3) { \
79 if (p <= compiler->scratches) \
80 w = compiler->saveds_offset - ((p) - SLJIT_R2) * (sljit_sw)sizeof(sljit_sw); \
82 w = compiler->locals_offset + ((p) - SLJIT_S2) * (sljit_sw)sizeof(sljit_sw); \
83 p = SLJIT_MEM1(SLJIT_SP); \
87 #else /* SLJIT_CONFIG_X86_32 */
89 /* Last register + 1. */
90 #define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
91 #define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
93 /* Note: r12 & 0x7 == 0b100, which decoded as SIB byte present
94 Note: avoid to use r12 and r13 for memory addessing
95 therefore r12 is better to be a higher saved register. */
97 /* Args: rdi(=7), rsi(=6), rdx(=2), rcx(=1), r8, r9. Scratches: rax(=0), r10, r11 */
98 static const sljit_u8 reg_map
[SLJIT_NUMBER_OF_REGISTERS
+ 4] = {
99 0, 0, 6, 7, 1, 8, 11, 10, 12, 5, 13, 14, 15, 3, 4, 2, 9
101 /* low-map. reg_map & 0x7. */
102 static const sljit_u8 reg_lmap
[SLJIT_NUMBER_OF_REGISTERS
+ 4] = {
103 0, 0, 6, 7, 1, 0, 3, 2, 4, 5, 5, 6, 7, 3, 4, 2, 1
106 /* Args: rcx(=1), rdx(=2), r8, r9. Scratches: rax(=0), r10, r11 */
107 static const sljit_u8 reg_map
[SLJIT_NUMBER_OF_REGISTERS
+ 4] = {
108 0, 0, 2, 8, 1, 11, 12, 5, 13, 14, 15, 7, 6, 3, 4, 9, 10
110 /* low-map. reg_map & 0x7. */
111 static const sljit_u8 reg_lmap
[SLJIT_NUMBER_OF_REGISTERS
+ 4] = {
112 0, 0, 2, 0, 1, 3, 4, 5, 5, 6, 7, 7, 6, 3, 4, 1, 2
116 /* Args: xmm0-xmm3 */
117 static const sljit_u8 freg_map
[SLJIT_NUMBER_OF_FLOAT_REGISTERS
+ 1] = {
120 /* low-map. freg_map & 0x7. */
121 static const sljit_u8 freg_lmap
[SLJIT_NUMBER_OF_FLOAT_REGISTERS
+ 1] = {
132 #define HALFWORD_MAX 0x7fffffffl
133 #define HALFWORD_MIN -0x80000000l
135 #define HALFWORD_MAX 0x7fffffffll
136 #define HALFWORD_MIN -0x80000000ll
139 #define IS_HALFWORD(x) ((x) <= HALFWORD_MAX && (x) >= HALFWORD_MIN)
140 #define NOT_HALFWORD(x) ((x) > HALFWORD_MAX || (x) < HALFWORD_MIN)
142 #define CHECK_EXTRA_REGS(p, w, do)
144 #endif /* SLJIT_CONFIG_X86_32 */
148 /* Size flags for emit_x86_instruction: */
149 #define EX86_BIN_INS 0x0010
150 #define EX86_SHIFT_INS 0x0020
151 #define EX86_REX 0x0040
152 #define EX86_NO_REXW 0x0080
153 #define EX86_BYTE_ARG 0x0100
154 #define EX86_HALF_ARG 0x0200
155 #define EX86_PREF_66 0x0400
156 #define EX86_PREF_F2 0x0800
157 #define EX86_PREF_F3 0x1000
158 #define EX86_SSE2_OP1 0x2000
159 #define EX86_SSE2_OP2 0x4000
160 #define EX86_SSE2 (EX86_SSE2_OP1 | EX86_SSE2_OP2)
162 /* --------------------------------------------------------------------- */
163 /* Instrucion forms */
164 /* --------------------------------------------------------------------- */
166 #define ADD (/* BINARY */ 0 << 3)
167 #define ADD_EAX_i32 0x05
168 #define ADD_r_rm 0x03
169 #define ADD_rm_r 0x01
170 #define ADDSD_x_xm 0x58
171 #define ADC (/* BINARY */ 2 << 3)
172 #define ADC_EAX_i32 0x15
173 #define ADC_r_rm 0x13
174 #define ADC_rm_r 0x11
175 #define AND (/* BINARY */ 4 << 3)
176 #define AND_EAX_i32 0x25
177 #define AND_r_rm 0x23
178 #define AND_rm_r 0x21
179 #define ANDPD_x_xm 0x54
180 #define BSR_r_rm (/* GROUP_0F */ 0xbd)
181 #define CALL_i32 0xe8
182 #define CALL_rm (/* GROUP_FF */ 2 << 3)
184 #define CMOVE_r_rm (/* GROUP_0F */ 0x44)
185 #define CMP (/* BINARY */ 7 << 3)
186 #define CMP_EAX_i32 0x3d
187 #define CMP_r_rm 0x3b
188 #define CMP_rm_r 0x39
189 #define CVTPD2PS_x_xm 0x5a
190 #define CVTSI2SD_x_rm 0x2a
191 #define CVTTSD2SI_r_xm 0x2c
192 #define DIV (/* GROUP_F7 */ 6 << 3)
193 #define DIVSD_x_xm 0x5e
197 #define IDIV (/* GROUP_F7 */ 7 << 3)
198 #define IMUL (/* GROUP_F7 */ 5 << 3)
199 #define IMUL_r_rm (/* GROUP_0F */ 0xaf)
200 #define IMUL_r_rm_i8 0x6b
201 #define IMUL_r_rm_i32 0x69
206 #define JMP_rm (/* GROUP_FF */ 4 << 3)
208 #define MOV_r_rm 0x8b
209 #define MOV_r_i32 0xb8
210 #define MOV_rm_r 0x89
211 #define MOV_rm_i32 0xc7
212 #define MOV_rm8_i8 0xc6
213 #define MOV_rm8_r8 0x88
214 #define MOVSD_x_xm 0x10
215 #define MOVSD_xm_x 0x11
216 #define MOVSXD_r_rm 0x63
217 #define MOVSX_r_rm8 (/* GROUP_0F */ 0xbe)
218 #define MOVSX_r_rm16 (/* GROUP_0F */ 0xbf)
219 #define MOVZX_r_rm8 (/* GROUP_0F */ 0xb6)
220 #define MOVZX_r_rm16 (/* GROUP_0F */ 0xb7)
221 #define MUL (/* GROUP_F7 */ 4 << 3)
222 #define MULSD_x_xm 0x59
223 #define NEG_rm (/* GROUP_F7 */ 3 << 3)
225 #define NOT_rm (/* GROUP_F7 */ 2 << 3)
226 #define OR (/* BINARY */ 1 << 3)
228 #define OR_EAX_i32 0x0d
230 #define OR_rm8_r8 0x08
234 #define PREFETCH 0x18
235 #define PUSH_i32 0x68
237 #define PUSH_rm (/* GROUP_FF */ 6 << 3)
239 #define RET_near 0xc3
241 #define SBB (/* BINARY */ 3 << 3)
242 #define SBB_EAX_i32 0x1d
243 #define SBB_r_rm 0x1b
244 #define SBB_rm_r 0x19
245 #define SAR (/* SHIFT */ 7 << 3)
246 #define SHL (/* SHIFT */ 4 << 3)
247 #define SHR (/* SHIFT */ 5 << 3)
248 #define SUB (/* BINARY */ 5 << 3)
249 #define SUB_EAX_i32 0x2d
250 #define SUB_r_rm 0x2b
251 #define SUB_rm_r 0x29
252 #define SUBSD_x_xm 0x5c
253 #define TEST_EAX_i32 0xa9
254 #define TEST_rm_r 0x85
255 #define UCOMISD_x_xm 0x2e
256 #define UNPCKLPD_x_xm 0x14
257 #define XCHG_EAX_r 0x90
258 #define XCHG_r_rm 0x87
259 #define XOR (/* BINARY */ 6 << 3)
260 #define XOR_EAX_i32 0x35
261 #define XOR_r_rm 0x33
262 #define XOR_rm_r 0x31
263 #define XORPD_x_xm 0x57
265 #define GROUP_0F 0x0f
266 #define GROUP_F7 0xf7
267 #define GROUP_FF 0xff
268 #define GROUP_BINARY_81 0x81
269 #define GROUP_BINARY_83 0x83
270 #define GROUP_SHIFT_1 0xd1
271 #define GROUP_SHIFT_N 0xc1
272 #define GROUP_SHIFT_CL 0xd3
275 #define MOD_DISP8 0x40
277 #define INC_SIZE(s) (*inst++ = (s), compiler->size += (s))
279 #define PUSH_REG(r) (*inst++ = (PUSH_r + (r)))
280 #define POP_REG(r) (*inst++ = (POP_r + (r)))
281 #define RET() (*inst++ = (RET_near))
282 #define RET_I16(n) (*inst++ = (RET_i16), *inst++ = n, *inst++ = 0)
284 #define MOV_RM(mod, reg, rm) (*inst++ = (MOV_r_rm), *inst++ = (mod) << 6 | (reg) << 3 | (rm))
286 /* Multithreading does not affect these static variables, since they store
287 built-in CPU features. Therefore they can be overwritten by different threads
288 if they detect the CPU features in the same time. */
289 #if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
290 static sljit_s32 cpu_has_sse2
= -1;
292 static sljit_s32 cpu_has_cmov
= -1;
295 #include <cmnintrin.h>
296 #elif defined(_MSC_VER) && _MSC_VER >= 1400
300 /******************************************************/
301 /* Unaligned-store functions */
302 /******************************************************/
304 static SLJIT_INLINE
void sljit_unaligned_store_s16(void *addr
, sljit_s16 value
)
306 SLJIT_MEMCPY(addr
, &value
, sizeof(value
));
309 static SLJIT_INLINE
void sljit_unaligned_store_s32(void *addr
, sljit_s32 value
)
311 SLJIT_MEMCPY(addr
, &value
, sizeof(value
));
314 static SLJIT_INLINE
void sljit_unaligned_store_sw(void *addr
, sljit_sw value
)
316 SLJIT_MEMCPY(addr
, &value
, sizeof(value
));
319 /******************************************************/
320 /* Utility functions */
321 /******************************************************/
323 static void get_cpu_features(void)
327 #if defined(_MSC_VER) && _MSC_VER >= 1400
331 features
= (sljit_u32
)CPUInfo
[3];
333 #elif defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_C)
338 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
339 /* On x86-32, there is no red zone, so this
340 should work (no need for a local variable). */
344 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
350 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
351 : "%eax", "%ecx", "%edx"
353 : "%rax", "%rbx", "%rcx", "%rdx"
357 #else /* _MSC_VER && _MSC_VER >= 1400 */
366 #endif /* _MSC_VER && _MSC_VER >= 1400 */
368 #if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
369 cpu_has_sse2
= (features
>> 26) & 0x1;
371 cpu_has_cmov
= (features
>> 15) & 0x1;
374 static sljit_u8
get_jump_code(sljit_s32 type
)
378 case SLJIT_EQUAL_F64
:
379 return 0x84 /* je */;
381 case SLJIT_NOT_EQUAL
:
382 case SLJIT_NOT_EQUAL_F64
:
383 return 0x85 /* jne */;
387 return 0x82 /* jc */;
389 case SLJIT_GREATER_EQUAL
:
390 case SLJIT_GREATER_EQUAL_F64
:
391 return 0x83 /* jae */;
394 case SLJIT_GREATER_F64
:
395 return 0x87 /* jnbe */;
397 case SLJIT_LESS_EQUAL
:
398 case SLJIT_LESS_EQUAL_F64
:
399 return 0x86 /* jbe */;
402 return 0x8c /* jl */;
404 case SLJIT_SIG_GREATER_EQUAL
:
405 return 0x8d /* jnl */;
407 case SLJIT_SIG_GREATER
:
408 return 0x8f /* jnle */;
410 case SLJIT_SIG_LESS_EQUAL
:
411 return 0x8e /* jle */;
414 return 0x80 /* jo */;
416 case SLJIT_NOT_OVERFLOW
:
417 return 0x81 /* jno */;
419 case SLJIT_UNORDERED_F64
:
420 return 0x8a /* jp */;
422 case SLJIT_ORDERED_F64
:
423 return 0x8b /* jpo */;
428 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
429 static sljit_u8
* generate_far_jump_code(struct sljit_jump
*jump
, sljit_u8
*code_ptr
, sljit_sw executable_offset
);
431 static sljit_u8
* generate_far_jump_code(struct sljit_jump
*jump
, sljit_u8
*code_ptr
);
432 static sljit_u8
* generate_put_label_code(struct sljit_put_label
*put_label
, sljit_u8
*code_ptr
, sljit_uw max_label
);
435 static sljit_u8
* generate_near_jump_code(struct sljit_jump
*jump
, sljit_u8
*code_ptr
, sljit_u8
*code
, sljit_sw executable_offset
)
437 sljit_s32 type
= jump
->flags
>> TYPE_SHIFT
;
438 sljit_s32 short_jump
;
441 if (jump
->flags
& JUMP_LABEL
)
442 label_addr
= (sljit_uw
)(code
+ jump
->u
.label
->size
);
444 label_addr
= jump
->u
.target
- executable_offset
;
446 short_jump
= (sljit_sw
)(label_addr
- (jump
->addr
+ 2)) >= -128 && (sljit_sw
)(label_addr
- (jump
->addr
+ 2)) <= 127;
448 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
449 if ((sljit_sw
)(label_addr
- (jump
->addr
+ 1)) > HALFWORD_MAX
|| (sljit_sw
)(label_addr
- (jump
->addr
+ 1)) < HALFWORD_MIN
)
450 return generate_far_jump_code(jump
, code_ptr
);
453 if (type
== SLJIT_JUMP
) {
455 *code_ptr
++ = JMP_i8
;
457 *code_ptr
++ = JMP_i32
;
460 else if (type
>= SLJIT_FAST_CALL
) {
462 *code_ptr
++ = CALL_i32
;
465 else if (short_jump
) {
466 *code_ptr
++ = get_jump_code(type
) - 0x10;
470 *code_ptr
++ = GROUP_0F
;
471 *code_ptr
++ = get_jump_code(type
);
476 jump
->flags
|= PATCH_MB
;
477 code_ptr
+= sizeof(sljit_s8
);
479 jump
->flags
|= PATCH_MW
;
480 code_ptr
+= sizeof(sljit_s32
);
486 SLJIT_API_FUNC_ATTRIBUTE
void* sljit_generate_code(struct sljit_compiler
*compiler
)
488 struct sljit_memory_fragment
*buf
;
494 sljit_sw executable_offset
;
497 struct sljit_label
*label
;
498 struct sljit_jump
*jump
;
499 struct sljit_const
*const_
;
500 struct sljit_put_label
*put_label
;
503 CHECK_PTR(check_sljit_generate_code(compiler
));
504 reverse_buf(compiler
);
506 /* Second code generation pass. */
507 code
= (sljit_u8
*)SLJIT_MALLOC_EXEC(compiler
->size
, compiler
->exec_allocator_data
);
508 PTR_FAIL_WITH_EXEC_IF(code
);
512 label
= compiler
->labels
;
513 jump
= compiler
->jumps
;
514 const_
= compiler
->consts
;
515 put_label
= compiler
->put_labels
;
516 executable_offset
= SLJIT_EXEC_OFFSET(code
);
519 buf_ptr
= buf
->memory
;
520 buf_end
= buf_ptr
+ buf
->used_size
;
524 /* The code is already generated. */
525 SLJIT_MEMCPY(code_ptr
, buf_ptr
, len
);
532 label
->addr
= (sljit_uw
)SLJIT_ADD_EXEC_OFFSET(code_ptr
, executable_offset
);
533 label
->size
= code_ptr
- code
;
537 jump
->addr
= (sljit_uw
)code_ptr
;
538 if (!(jump
->flags
& SLJIT_REWRITABLE_JUMP
))
539 code_ptr
= generate_near_jump_code(jump
, code_ptr
, code
, executable_offset
);
541 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
542 code_ptr
= generate_far_jump_code(jump
, code_ptr
, executable_offset
);
544 code_ptr
= generate_far_jump_code(jump
, code_ptr
);
550 const_
->addr
= ((sljit_uw
)code_ptr
) - sizeof(sljit_sw
);
551 const_
= const_
->next
;
554 SLJIT_ASSERT(*buf_ptr
== 3);
555 SLJIT_ASSERT(put_label
->label
);
556 put_label
->addr
= (sljit_uw
)code_ptr
;
557 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
558 code_ptr
= generate_put_label_code(put_label
, code_ptr
, (sljit_uw
)SLJIT_ADD_EXEC_OFFSET(code
, executable_offset
) + put_label
->label
->size
);
560 put_label
= put_label
->next
;
565 } while (buf_ptr
< buf_end
);
566 SLJIT_ASSERT(buf_ptr
== buf_end
);
570 SLJIT_ASSERT(!label
);
572 SLJIT_ASSERT(!const_
);
573 SLJIT_ASSERT(!put_label
);
574 SLJIT_ASSERT(code_ptr
<= code
+ compiler
->size
);
576 jump
= compiler
->jumps
;
578 jump_addr
= jump
->addr
+ executable_offset
;
580 if (jump
->flags
& PATCH_MB
) {
581 SLJIT_ASSERT((sljit_sw
)(jump
->u
.label
->addr
- (jump_addr
+ sizeof(sljit_s8
))) >= -128 && (sljit_sw
)(jump
->u
.label
->addr
- (jump_addr
+ sizeof(sljit_s8
))) <= 127);
582 *(sljit_u8
*)jump
->addr
= (sljit_u8
)(jump
->u
.label
->addr
- (jump_addr
+ sizeof(sljit_s8
)));
583 } else if (jump
->flags
& PATCH_MW
) {
584 if (jump
->flags
& JUMP_LABEL
) {
585 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
586 sljit_unaligned_store_sw((void*)jump
->addr
, (sljit_sw
)(jump
->u
.label
->addr
- (jump_addr
+ sizeof(sljit_sw
))));
588 SLJIT_ASSERT((sljit_sw
)(jump
->u
.label
->addr
- (jump_addr
+ sizeof(sljit_s32
))) >= HALFWORD_MIN
&& (sljit_sw
)(jump
->u
.label
->addr
- (jump_addr
+ sizeof(sljit_s32
))) <= HALFWORD_MAX
);
589 sljit_unaligned_store_s32((void*)jump
->addr
, (sljit_s32
)(jump
->u
.label
->addr
- (jump_addr
+ sizeof(sljit_s32
))));
593 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
594 sljit_unaligned_store_sw((void*)jump
->addr
, (sljit_sw
)(jump
->u
.target
- (jump_addr
+ sizeof(sljit_sw
))));
596 SLJIT_ASSERT((sljit_sw
)(jump
->u
.target
- (jump_addr
+ sizeof(sljit_s32
))) >= HALFWORD_MIN
&& (sljit_sw
)(jump
->u
.target
- (jump_addr
+ sizeof(sljit_s32
))) <= HALFWORD_MAX
);
597 sljit_unaligned_store_s32((void*)jump
->addr
, (sljit_s32
)(jump
->u
.target
- (jump_addr
+ sizeof(sljit_s32
))));
601 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
602 else if (jump
->flags
& PATCH_MD
)
603 sljit_unaligned_store_sw((void*)jump
->addr
, jump
->u
.label
->addr
);
609 put_label
= compiler
->put_labels
;
611 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
612 sljit_unaligned_store_sw((void*)(put_label
->addr
- sizeof(sljit_sw
)), (sljit_sw
)put_label
->label
->addr
);
614 if (put_label
->flags
& PATCH_MD
) {
615 SLJIT_ASSERT(put_label
->label
->addr
> HALFWORD_MAX
);
616 sljit_unaligned_store_sw((void*)(put_label
->addr
- sizeof(sljit_sw
)), (sljit_sw
)put_label
->label
->addr
);
619 SLJIT_ASSERT(put_label
->label
->addr
<= HALFWORD_MAX
);
620 sljit_unaligned_store_s32((void*)(put_label
->addr
- sizeof(sljit_s32
)), (sljit_s32
)put_label
->label
->addr
);
624 put_label
= put_label
->next
;
627 compiler
->error
= SLJIT_ERR_COMPILED
;
628 compiler
->executable_offset
= executable_offset
;
629 compiler
->executable_size
= code_ptr
- code
;
631 code
= (sljit_u8
*)SLJIT_ADD_EXEC_OFFSET(code
, executable_offset
);
633 SLJIT_UPDATE_WX_FLAGS(code
, (sljit_u8
*)SLJIT_ADD_EXEC_OFFSET(code_ptr
, executable_offset
), 1);
637 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_has_cpu_feature(sljit_s32 feature_type
)
639 switch (feature_type
) {
641 #ifdef SLJIT_IS_FPU_AVAILABLE
642 return SLJIT_IS_FPU_AVAILABLE
;
643 #elif (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
644 if (cpu_has_sse2
== -1)
647 #else /* SLJIT_DETECT_SSE2 */
649 #endif /* SLJIT_DETECT_SSE2 */
651 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
652 case SLJIT_HAS_VIRTUAL_REGISTERS
:
658 if (cpu_has_cmov
== -1)
662 case SLJIT_HAS_PREFETCH
:
666 #if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
667 if (cpu_has_sse2
== -1)
679 /* --------------------------------------------------------------------- */
681 /* --------------------------------------------------------------------- */
683 #define BINARY_OPCODE(opcode) (((opcode ## _EAX_i32) << 24) | ((opcode ## _r_rm) << 16) | ((opcode ## _rm_r) << 8) | (opcode))
685 static sljit_s32
emit_cum_binary(struct sljit_compiler
*compiler
,
687 sljit_s32 dst
, sljit_sw dstw
,
688 sljit_s32 src1
, sljit_sw src1w
,
689 sljit_s32 src2
, sljit_sw src2w
);
691 static sljit_s32
emit_non_cum_binary(struct sljit_compiler
*compiler
,
693 sljit_s32 dst
, sljit_sw dstw
,
694 sljit_s32 src1
, sljit_sw src1w
,
695 sljit_s32 src2
, sljit_sw src2w
);
697 static sljit_s32
emit_mov(struct sljit_compiler
*compiler
,
698 sljit_s32 dst
, sljit_sw dstw
,
699 sljit_s32 src
, sljit_sw srcw
);
701 #define EMIT_MOV(compiler, dst, dstw, src, srcw) \
702 FAIL_IF(emit_mov(compiler, dst, dstw, src, srcw));
704 static SLJIT_INLINE sljit_s32
emit_sse2_store(struct sljit_compiler
*compiler
,
705 sljit_s32 single
, sljit_s32 dst
, sljit_sw dstw
, sljit_s32 src
);
707 static SLJIT_INLINE sljit_s32
emit_sse2_load(struct sljit_compiler
*compiler
,
708 sljit_s32 single
, sljit_s32 dst
, sljit_s32 src
, sljit_sw srcw
);
710 static sljit_s32
emit_cmp_binary(struct sljit_compiler
*compiler
,
711 sljit_s32 src1
, sljit_sw src1w
,
712 sljit_s32 src2
, sljit_sw src2w
);
714 static SLJIT_INLINE sljit_s32
emit_endbranch(struct sljit_compiler
*compiler
)
716 #if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET)
717 /* Emit endbr32/endbr64 when CET is enabled. */
719 inst
= (sljit_u8
*)ensure_buf(compiler
, 1 + 4);
725 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
730 #else /* !SLJIT_CONFIG_X86_CET */
731 SLJIT_UNUSED_ARG(compiler
);
732 #endif /* SLJIT_CONFIG_X86_CET */
733 return SLJIT_SUCCESS
;
736 #if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET) && defined (__SHSTK__)
738 static SLJIT_INLINE sljit_s32
emit_rdssp(struct sljit_compiler
*compiler
, sljit_s32 reg
)
743 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
749 inst
= (sljit_u8
*)ensure_buf(compiler
, 1 + size
);
753 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
754 *inst
++ = REX_W
| (reg_map
[reg
] <= 7 ? 0 : REX_B
);
758 *inst
= (0x3 << 6) | (0x1 << 3) | (reg_map
[reg
] & 0x7);
759 return SLJIT_SUCCESS
;
762 static SLJIT_INLINE sljit_s32
emit_incssp(struct sljit_compiler
*compiler
, sljit_s32 reg
)
767 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
773 inst
= (sljit_u8
*)ensure_buf(compiler
, 1 + size
);
777 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
778 *inst
++ = REX_W
| (reg_map
[reg
] <= 7 ? 0 : REX_B
);
782 *inst
= (0x3 << 6) | (0x5 << 3) | (reg_map
[reg
] & 0x7);
783 return SLJIT_SUCCESS
;
786 #endif /* SLJIT_CONFIG_X86_CET && __SHSTK__ */
788 static SLJIT_INLINE sljit_s32
cpu_has_shadow_stack(void)
790 #if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET) && defined (__SHSTK__)
791 return _get_ssp() != 0;
792 #else /* !SLJIT_CONFIG_X86_CET || !__SHSTK__ */
794 #endif /* SLJIT_CONFIG_X86_CET && __SHSTK__ */
797 static SLJIT_INLINE sljit_s32
adjust_shadow_stack(struct sljit_compiler
*compiler
,
798 sljit_s32 src
, sljit_sw srcw
, sljit_s32 base
, sljit_sw disp
)
800 #if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET) && defined (__SHSTK__)
801 sljit_u8
*inst
, *jz_after_cmp_inst
;
802 sljit_uw size_jz_after_cmp_inst
;
804 sljit_uw size_before_rdssp_inst
= compiler
->size
;
806 /* Generate "RDSSP TMP_REG1". */
807 FAIL_IF(emit_rdssp(compiler
, TMP_REG1
));
809 /* Load return address on shadow stack into TMP_REG1. */
810 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
811 SLJIT_ASSERT(reg_map
[TMP_REG1
] == 5);
813 /* Hand code unsupported "mov 0x0(%ebp),%ebp". */
814 inst
= (sljit_u8
*)ensure_buf(compiler
, 1 + 3);
820 #else /* !SLJIT_CONFIG_X86_32 */
821 EMIT_MOV(compiler
, TMP_REG1
, 0, SLJIT_MEM1(TMP_REG1
), 0);
822 #endif /* SLJIT_CONFIG_X86_32 */
824 if (src
== SLJIT_UNUSED
) {
825 /* Return address is on stack. */
826 src
= SLJIT_MEM1(base
);
830 /* Compare return address against TMP_REG1. */
831 FAIL_IF(emit_cmp_binary (compiler
, TMP_REG1
, 0, src
, srcw
));
833 /* Generate JZ to skip shadow stack ajdustment when shadow
834 stack matches normal stack. */
835 inst
= (sljit_u8
*)ensure_buf(compiler
, 1 + 2);
838 *inst
++ = get_jump_code(SLJIT_EQUAL
) - 0x10;
839 size_jz_after_cmp_inst
= compiler
->size
;
840 jz_after_cmp_inst
= inst
;
842 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
843 /* REX_W is not necessary. */
844 compiler
->mode32
= 1;
846 /* Load 1 into TMP_REG1. */
847 EMIT_MOV(compiler
, TMP_REG1
, 0, SLJIT_IMM
, 1);
849 /* Generate "INCSSP TMP_REG1". */
850 FAIL_IF(emit_incssp(compiler
, TMP_REG1
));
852 /* Jump back to "RDSSP TMP_REG1" to check shadow stack again. */
853 inst
= (sljit_u8
*)ensure_buf(compiler
, 1 + 2);
857 *inst
= size_before_rdssp_inst
- compiler
->size
;
859 *jz_after_cmp_inst
= compiler
->size
- size_jz_after_cmp_inst
;
860 #else /* !SLJIT_CONFIG_X86_CET || !__SHSTK__ */
861 SLJIT_UNUSED_ARG(compiler
);
862 SLJIT_UNUSED_ARG(src
);
863 SLJIT_UNUSED_ARG(srcw
);
864 SLJIT_UNUSED_ARG(base
);
865 SLJIT_UNUSED_ARG(disp
);
866 #endif /* SLJIT_CONFIG_X86_CET && __SHSTK__ */
867 return SLJIT_SUCCESS
;
870 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
871 #include "sljitNativeX86_32.c"
873 #include "sljitNativeX86_64.c"
876 static sljit_s32
emit_mov(struct sljit_compiler
*compiler
,
877 sljit_s32 dst
, sljit_sw dstw
,
878 sljit_s32 src
, sljit_sw srcw
)
882 SLJIT_ASSERT(dst
!= SLJIT_UNUSED
);
884 if (FAST_IS_REG(src
)) {
885 inst
= emit_x86_instruction(compiler
, 1, src
, 0, dst
, dstw
);
888 return SLJIT_SUCCESS
;
890 if (src
& SLJIT_IMM
) {
891 if (FAST_IS_REG(dst
)) {
892 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
893 return emit_do_imm(compiler
, MOV_r_i32
+ reg_map
[dst
], srcw
);
895 if (!compiler
->mode32
) {
896 if (NOT_HALFWORD(srcw
))
897 return emit_load_imm64(compiler
, dst
, srcw
);
900 return emit_do_imm32(compiler
, (reg_map
[dst
] >= 8) ? REX_B
: 0, MOV_r_i32
+ reg_lmap
[dst
], srcw
);
903 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
904 if (!compiler
->mode32
&& NOT_HALFWORD(srcw
)) {
905 /* Immediate to memory move. Only SLJIT_MOV operation copies
906 an immediate directly into memory so TMP_REG1 can be used. */
907 FAIL_IF(emit_load_imm64(compiler
, TMP_REG1
, srcw
));
908 inst
= emit_x86_instruction(compiler
, 1, TMP_REG1
, 0, dst
, dstw
);
911 return SLJIT_SUCCESS
;
914 inst
= emit_x86_instruction(compiler
, 1, SLJIT_IMM
, srcw
, dst
, dstw
);
917 return SLJIT_SUCCESS
;
919 if (FAST_IS_REG(dst
)) {
920 inst
= emit_x86_instruction(compiler
, 1, dst
, 0, src
, srcw
);
923 return SLJIT_SUCCESS
;
926 /* Memory to memory move. Only SLJIT_MOV operation copies
927 data from memory to memory so TMP_REG1 can be used. */
928 inst
= emit_x86_instruction(compiler
, 1, TMP_REG1
, 0, src
, srcw
);
931 inst
= emit_x86_instruction(compiler
, 1, TMP_REG1
, 0, dst
, dstw
);
934 return SLJIT_SUCCESS
;
937 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_op0(struct sljit_compiler
*compiler
, sljit_s32 op
)
940 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
945 CHECK(check_sljit_emit_op0(compiler
, op
));
947 switch (GET_OPCODE(op
)) {
948 case SLJIT_BREAKPOINT
:
949 inst
= (sljit_u8
*)ensure_buf(compiler
, 1 + 1);
955 inst
= (sljit_u8
*)ensure_buf(compiler
, 1 + 1);
962 case SLJIT_DIVMOD_UW
:
963 case SLJIT_DIVMOD_SW
:
966 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
969 reg_map
[SLJIT_R0
] == 0
970 && reg_map
[SLJIT_R1
] == 2
971 && reg_map
[TMP_REG1
] > 7);
974 reg_map
[SLJIT_R0
] == 0
975 && reg_map
[SLJIT_R1
] < 7
976 && reg_map
[TMP_REG1
] == 2);
978 compiler
->mode32
= op
& SLJIT_I32_OP
;
980 SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW
& 0x2) == 0 && SLJIT_DIV_UW
- 0x2 == SLJIT_DIVMOD_UW
, bad_div_opcode_assignments
);
983 if ((op
| 0x2) == SLJIT_DIV_UW
) {
984 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64)
985 EMIT_MOV(compiler
, TMP_REG1
, 0, SLJIT_R1
, 0);
986 inst
= emit_x86_instruction(compiler
, 1, SLJIT_R1
, 0, SLJIT_R1
, 0);
988 inst
= emit_x86_instruction(compiler
, 1, TMP_REG1
, 0, TMP_REG1
, 0);
994 if ((op
| 0x2) == SLJIT_DIV_SW
) {
995 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64)
996 EMIT_MOV(compiler
, TMP_REG1
, 0, SLJIT_R1
, 0);
999 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1000 inst
= (sljit_u8
*)ensure_buf(compiler
, 1 + 1);
1005 if (compiler
->mode32
) {
1006 inst
= (sljit_u8
*)ensure_buf(compiler
, 1 + 1);
1011 inst
= (sljit_u8
*)ensure_buf(compiler
, 1 + 2);
1020 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1021 inst
= (sljit_u8
*)ensure_buf(compiler
, 1 + 2);
1025 *inst
= MOD_REG
| ((op
>= SLJIT_DIVMOD_UW
) ? reg_map
[TMP_REG1
] : reg_map
[SLJIT_R1
]);
1028 size
= (!compiler
->mode32
|| op
>= SLJIT_DIVMOD_UW
) ? 3 : 2;
1030 size
= (!compiler
->mode32
) ? 3 : 2;
1032 inst
= (sljit_u8
*)ensure_buf(compiler
, 1 + size
);
1036 if (!compiler
->mode32
)
1037 *inst
++ = REX_W
| ((op
>= SLJIT_DIVMOD_UW
) ? REX_B
: 0);
1038 else if (op
>= SLJIT_DIVMOD_UW
)
1041 *inst
= MOD_REG
| ((op
>= SLJIT_DIVMOD_UW
) ? reg_lmap
[TMP_REG1
] : reg_lmap
[SLJIT_R1
]);
1043 if (!compiler
->mode32
)
1046 *inst
= MOD_REG
| reg_map
[SLJIT_R1
];
1056 case SLJIT_DIVMOD_UW
:
1060 case SLJIT_DIVMOD_SW
:
1065 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && !defined(_WIN64)
1066 if (op
<= SLJIT_DIVMOD_SW
)
1067 EMIT_MOV(compiler
, SLJIT_R1
, 0, TMP_REG1
, 0);
1069 if (op
>= SLJIT_DIV_UW
)
1070 EMIT_MOV(compiler
, SLJIT_R1
, 0, TMP_REG1
, 0);
1074 return emit_endbranch(compiler
);
1075 case SLJIT_SKIP_FRAMES_BEFORE_RETURN
:
1076 return skip_frames_before_return(compiler
);
1079 return SLJIT_SUCCESS
;
1082 #define ENCODE_PREFIX(prefix) \
1084 inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); \
1090 static sljit_s32
emit_mov_byte(struct sljit_compiler
*compiler
, sljit_s32 sign
,
1091 sljit_s32 dst
, sljit_sw dstw
,
1092 sljit_s32 src
, sljit_sw srcw
)
1096 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1100 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1101 compiler
->mode32
= 0;
1104 if (src
& SLJIT_IMM
) {
1105 if (FAST_IS_REG(dst
)) {
1106 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1107 return emit_do_imm(compiler
, MOV_r_i32
+ reg_map
[dst
], srcw
);
1109 inst
= emit_x86_instruction(compiler
, 1, SLJIT_IMM
, srcw
, dst
, 0);
1112 return SLJIT_SUCCESS
;
1115 inst
= emit_x86_instruction(compiler
, 1 | EX86_BYTE_ARG
| EX86_NO_REXW
, SLJIT_IMM
, srcw
, dst
, dstw
);
1118 return SLJIT_SUCCESS
;
1121 dst_r
= FAST_IS_REG(dst
) ? dst
: TMP_REG1
;
1123 if ((dst
& SLJIT_MEM
) && FAST_IS_REG(src
)) {
1124 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1125 if (reg_map
[src
] >= 4) {
1126 SLJIT_ASSERT(dst_r
== TMP_REG1
);
1127 EMIT_MOV(compiler
, TMP_REG1
, 0, src
, 0);
1134 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1135 else if (FAST_IS_REG(src
) && reg_map
[src
] >= 4) {
1136 /* src, dst are registers. */
1137 SLJIT_ASSERT(SLOW_IS_REG(dst
));
1138 if (reg_map
[dst
] < 4) {
1140 EMIT_MOV(compiler
, dst
, 0, src
, 0);
1141 inst
= emit_x86_instruction(compiler
, 2, dst
, 0, dst
, 0);
1144 *inst
= sign
? MOVSX_r_rm8
: MOVZX_r_rm8
;
1148 EMIT_MOV(compiler
, dst
, 0, src
, 0);
1151 inst
= emit_x86_instruction(compiler
, 1 | EX86_SHIFT_INS
, SLJIT_IMM
, 24, dst
, 0);
1155 inst
= emit_x86_instruction(compiler
, 1 | EX86_SHIFT_INS
, SLJIT_IMM
, 24, dst
, 0);
1160 inst
= emit_x86_instruction(compiler
, 1 | EX86_BIN_INS
, SLJIT_IMM
, 0xff, dst
, 0);
1165 return SLJIT_SUCCESS
;
1169 /* src can be memory addr or reg_map[src] < 4 on x86_32 architectures. */
1170 inst
= emit_x86_instruction(compiler
, 2, dst_r
, 0, src
, srcw
);
1173 *inst
= sign
? MOVSX_r_rm8
: MOVZX_r_rm8
;
1176 if (dst
& SLJIT_MEM
) {
1177 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1178 if (dst_r
== TMP_REG1
) {
1179 /* Find a non-used register, whose reg_map[src] < 4. */
1180 if ((dst
& REG_MASK
) == SLJIT_R0
) {
1181 if ((dst
& OFFS_REG_MASK
) == TO_OFFS_REG(SLJIT_R1
))
1187 if ((dst
& OFFS_REG_MASK
) != TO_OFFS_REG(SLJIT_R0
))
1189 else if ((dst
& REG_MASK
) == SLJIT_R1
)
1195 if (work_r
== SLJIT_R0
) {
1196 ENCODE_PREFIX(XCHG_EAX_r
+ reg_map
[TMP_REG1
]);
1199 inst
= emit_x86_instruction(compiler
, 1, work_r
, 0, dst_r
, 0);
1204 inst
= emit_x86_instruction(compiler
, 1, work_r
, 0, dst
, dstw
);
1208 if (work_r
== SLJIT_R0
) {
1209 ENCODE_PREFIX(XCHG_EAX_r
+ reg_map
[TMP_REG1
]);
1212 inst
= emit_x86_instruction(compiler
, 1, work_r
, 0, dst_r
, 0);
1218 inst
= emit_x86_instruction(compiler
, 1, dst_r
, 0, dst
, dstw
);
1223 inst
= emit_x86_instruction(compiler
, 1 | EX86_REX
| EX86_NO_REXW
, dst_r
, 0, dst
, dstw
);
1229 return SLJIT_SUCCESS
;
1232 static sljit_s32
emit_prefetch(struct sljit_compiler
*compiler
, sljit_s32 op
,
1233 sljit_s32 src
, sljit_sw srcw
)
1237 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1238 compiler
->mode32
= 1;
1241 inst
= emit_x86_instruction(compiler
, 2, 0, 0, src
, srcw
);
1246 if (op
== SLJIT_PREFETCH_L1
)
1248 else if (op
== SLJIT_PREFETCH_L2
)
1250 else if (op
== SLJIT_PREFETCH_L3
)
1253 return SLJIT_SUCCESS
;
1256 static sljit_s32
emit_mov_half(struct sljit_compiler
*compiler
, sljit_s32 sign
,
1257 sljit_s32 dst
, sljit_sw dstw
,
1258 sljit_s32 src
, sljit_sw srcw
)
1263 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1264 compiler
->mode32
= 0;
1267 if (src
& SLJIT_IMM
) {
1268 if (FAST_IS_REG(dst
)) {
1269 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1270 return emit_do_imm(compiler
, MOV_r_i32
+ reg_map
[dst
], srcw
);
1272 inst
= emit_x86_instruction(compiler
, 1, SLJIT_IMM
, srcw
, dst
, 0);
1275 return SLJIT_SUCCESS
;
1278 inst
= emit_x86_instruction(compiler
, 1 | EX86_HALF_ARG
| EX86_NO_REXW
| EX86_PREF_66
, SLJIT_IMM
, srcw
, dst
, dstw
);
1281 return SLJIT_SUCCESS
;
1284 dst_r
= FAST_IS_REG(dst
) ? dst
: TMP_REG1
;
1286 if ((dst
& SLJIT_MEM
) && FAST_IS_REG(src
))
1289 inst
= emit_x86_instruction(compiler
, 2, dst_r
, 0, src
, srcw
);
1292 *inst
= sign
? MOVSX_r_rm16
: MOVZX_r_rm16
;
1295 if (dst
& SLJIT_MEM
) {
1296 inst
= emit_x86_instruction(compiler
, 1 | EX86_NO_REXW
| EX86_PREF_66
, dst_r
, 0, dst
, dstw
);
1301 return SLJIT_SUCCESS
;
1304 static sljit_s32
emit_unary(struct sljit_compiler
*compiler
, sljit_u8 opcode
,
1305 sljit_s32 dst
, sljit_sw dstw
,
1306 sljit_s32 src
, sljit_sw srcw
)
1310 if (dst
== src
&& dstw
== srcw
) {
1311 /* Same input and output */
1312 inst
= emit_x86_instruction(compiler
, 1, 0, 0, dst
, dstw
);
1316 return SLJIT_SUCCESS
;
1319 if (SLJIT_UNLIKELY(dst
== SLJIT_UNUSED
))
1322 if (FAST_IS_REG(dst
)) {
1323 EMIT_MOV(compiler
, dst
, 0, src
, srcw
);
1324 inst
= emit_x86_instruction(compiler
, 1, 0, 0, dst
, 0);
1328 return SLJIT_SUCCESS
;
1331 EMIT_MOV(compiler
, TMP_REG1
, 0, src
, srcw
);
1332 inst
= emit_x86_instruction(compiler
, 1, 0, 0, TMP_REG1
, 0);
1336 EMIT_MOV(compiler
, dst
, dstw
, TMP_REG1
, 0);
1337 return SLJIT_SUCCESS
;
1340 static sljit_s32
emit_not_with_flags(struct sljit_compiler
*compiler
,
1341 sljit_s32 dst
, sljit_sw dstw
,
1342 sljit_s32 src
, sljit_sw srcw
)
1346 if (dst
== SLJIT_UNUSED
)
1349 if (FAST_IS_REG(dst
)) {
1350 EMIT_MOV(compiler
, dst
, 0, src
, srcw
);
1351 inst
= emit_x86_instruction(compiler
, 1, 0, 0, dst
, 0);
1355 inst
= emit_x86_instruction(compiler
, 1, dst
, 0, dst
, 0);
1358 return SLJIT_SUCCESS
;
1361 EMIT_MOV(compiler
, TMP_REG1
, 0, src
, srcw
);
1362 inst
= emit_x86_instruction(compiler
, 1, 0, 0, TMP_REG1
, 0);
1366 inst
= emit_x86_instruction(compiler
, 1, TMP_REG1
, 0, TMP_REG1
, 0);
1369 EMIT_MOV(compiler
, dst
, dstw
, TMP_REG1
, 0);
1370 return SLJIT_SUCCESS
;
1373 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1374 static const sljit_sw emit_clz_arg
= 32 + 31;
1377 static sljit_s32
emit_clz(struct sljit_compiler
*compiler
, sljit_s32 op_flags
,
1378 sljit_s32 dst
, sljit_sw dstw
,
1379 sljit_s32 src
, sljit_sw srcw
)
1384 SLJIT_UNUSED_ARG(op_flags
);
1386 if (cpu_has_cmov
== -1)
1389 dst_r
= FAST_IS_REG(dst
) ? dst
: TMP_REG1
;
1391 inst
= emit_x86_instruction(compiler
, 2, dst_r
, 0, src
, srcw
);
1396 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1398 if (dst_r
!= TMP_REG1
) {
1399 EMIT_MOV(compiler
, TMP_REG1
, 0, SLJIT_IMM
, 32 + 31);
1400 inst
= emit_x86_instruction(compiler
, 2, dst_r
, 0, TMP_REG1
, 0);
1403 inst
= emit_x86_instruction(compiler
, 2, dst_r
, 0, SLJIT_MEM0(), (sljit_sw
)&emit_clz_arg
);
1410 FAIL_IF(sljit_emit_cmov_generic(compiler
, SLJIT_EQUAL
, dst_r
, SLJIT_IMM
, 32 + 31));
1412 inst
= emit_x86_instruction(compiler
, 1 | EX86_BIN_INS
, SLJIT_IMM
, 31, dst_r
, 0);
1415 EMIT_MOV(compiler
, TMP_REG2
, 0, SLJIT_IMM
, !(op_flags
& SLJIT_I32_OP
) ? (64 + 63) : (32 + 31));
1417 inst
= emit_x86_instruction(compiler
, 2, dst_r
, 0, TMP_REG2
, 0);
1423 FAIL_IF(sljit_emit_cmov_generic(compiler
, SLJIT_EQUAL
, dst_r
, SLJIT_IMM
, !(op_flags
& SLJIT_I32_OP
) ? (64 + 63) : (32 + 31)));
1425 inst
= emit_x86_instruction(compiler
, 1 | EX86_BIN_INS
, SLJIT_IMM
, !(op_flags
& SLJIT_I32_OP
) ? 63 : 31, dst_r
, 0);
1431 if (dst
& SLJIT_MEM
)
1432 EMIT_MOV(compiler
, dst
, dstw
, TMP_REG1
, 0);
1433 return SLJIT_SUCCESS
;
1436 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_op1(struct sljit_compiler
*compiler
, sljit_s32 op
,
1437 sljit_s32 dst
, sljit_sw dstw
,
1438 sljit_s32 src
, sljit_sw srcw
)
1440 sljit_s32 op_flags
= GET_ALL_FLAGS(op
);
1441 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1442 sljit_s32 dst_is_ereg
= 0;
1446 CHECK(check_sljit_emit_op1(compiler
, op
, dst
, dstw
, src
, srcw
));
1447 ADJUST_LOCAL_OFFSET(dst
, dstw
);
1448 ADJUST_LOCAL_OFFSET(src
, srcw
);
1450 CHECK_EXTRA_REGS(dst
, dstw
, dst_is_ereg
= 1);
1451 CHECK_EXTRA_REGS(src
, srcw
, (void)0);
1452 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1453 compiler
->mode32
= op_flags
& SLJIT_I32_OP
;
1456 op
= GET_OPCODE(op
);
1458 if (op
>= SLJIT_MOV
&& op
<= SLJIT_MOV_P
) {
1459 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1460 compiler
->mode32
= 0;
1463 if (FAST_IS_REG(src
) && src
== dst
) {
1464 if (!TYPE_CAST_NEEDED(op
))
1465 return SLJIT_SUCCESS
;
1468 if (op_flags
& SLJIT_I32_OP
) {
1469 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1470 if (src
& SLJIT_MEM
) {
1471 if (op
== SLJIT_MOV_S32
)
1474 else if (src
& SLJIT_IMM
) {
1475 if (op
== SLJIT_MOV_U32
)
1481 if (src
& SLJIT_IMM
) {
1484 srcw
= (sljit_u8
)srcw
;
1487 srcw
= (sljit_s8
)srcw
;
1490 srcw
= (sljit_u16
)srcw
;
1493 srcw
= (sljit_s16
)srcw
;
1495 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1497 srcw
= (sljit_u32
)srcw
;
1500 srcw
= (sljit_s32
)srcw
;
1504 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1505 if (SLJIT_UNLIKELY(dst_is_ereg
))
1506 return emit_mov(compiler
, dst
, dstw
, src
, srcw
);
1510 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1511 if (SLJIT_UNLIKELY(dst_is_ereg
) && (!(op
== SLJIT_MOV
|| op
== SLJIT_MOV_U32
|| op
== SLJIT_MOV_S32
|| op
== SLJIT_MOV_P
) || (src
& SLJIT_MEM
))) {
1512 SLJIT_ASSERT(dst
== SLJIT_MEM1(SLJIT_SP
));
1520 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1524 FAIL_IF(emit_mov(compiler
, dst
, dstw
, src
, srcw
));
1527 FAIL_IF(emit_mov_byte(compiler
, 0, dst
, dstw
, src
, srcw
));
1530 FAIL_IF(emit_mov_byte(compiler
, 1, dst
, dstw
, src
, srcw
));
1533 FAIL_IF(emit_mov_half(compiler
, 0, dst
, dstw
, src
, srcw
));
1536 FAIL_IF(emit_mov_half(compiler
, 1, dst
, dstw
, src
, srcw
));
1538 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1540 FAIL_IF(emit_mov_int(compiler
, 0, dst
, dstw
, src
, srcw
));
1543 FAIL_IF(emit_mov_int(compiler
, 1, dst
, dstw
, src
, srcw
));
1548 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1549 if (SLJIT_UNLIKELY(dst_is_ereg
) && dst
== TMP_REG1
)
1550 return emit_mov(compiler
, SLJIT_MEM1(SLJIT_SP
), dstw
, TMP_REG1
, 0);
1552 return SLJIT_SUCCESS
;
1557 if (SLJIT_UNLIKELY(op_flags
& SLJIT_SET_Z
))
1558 return emit_not_with_flags(compiler
, dst
, dstw
, src
, srcw
);
1559 return emit_unary(compiler
, NOT_rm
, dst
, dstw
, src
, srcw
);
1562 return emit_unary(compiler
, NEG_rm
, dst
, dstw
, src
, srcw
);
1565 return emit_clz(compiler
, op_flags
, dst
, dstw
, src
, srcw
);
1568 return SLJIT_SUCCESS
;
1571 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1573 #define BINARY_IMM(op_imm, op_mr, immw, arg, argw) \
1574 if (IS_HALFWORD(immw) || compiler->mode32) { \
1575 inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, immw, arg, argw); \
1577 *(inst + 1) |= (op_imm); \
1580 FAIL_IF(emit_load_imm64(compiler, (arg == TMP_REG1) ? TMP_REG2 : TMP_REG1, immw)); \
1581 inst = emit_x86_instruction(compiler, 1, (arg == TMP_REG1) ? TMP_REG2 : TMP_REG1, 0, arg, argw); \
1586 #define BINARY_EAX_IMM(op_eax_imm, immw) \
1587 FAIL_IF(emit_do_imm32(compiler, (!compiler->mode32) ? REX_W : 0, (op_eax_imm), immw))
1591 #define BINARY_IMM(op_imm, op_mr, immw, arg, argw) \
1592 inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, immw, arg, argw); \
1594 *(inst + 1) |= (op_imm);
1596 #define BINARY_EAX_IMM(op_eax_imm, immw) \
1597 FAIL_IF(emit_do_imm(compiler, (op_eax_imm), immw))
1601 static sljit_s32
emit_cum_binary(struct sljit_compiler
*compiler
,
1603 sljit_s32 dst
, sljit_sw dstw
,
1604 sljit_s32 src1
, sljit_sw src1w
,
1605 sljit_s32 src2
, sljit_sw src2w
)
1608 sljit_u8 op_eax_imm
= (op_types
>> 24);
1609 sljit_u8 op_rm
= (op_types
>> 16) & 0xff;
1610 sljit_u8 op_mr
= (op_types
>> 8) & 0xff;
1611 sljit_u8 op_imm
= op_types
& 0xff;
1613 if (dst
== SLJIT_UNUSED
) {
1614 EMIT_MOV(compiler
, TMP_REG1
, 0, src1
, src1w
);
1615 if (src2
& SLJIT_IMM
) {
1616 BINARY_IMM(op_imm
, op_mr
, src2w
, TMP_REG1
, 0);
1619 inst
= emit_x86_instruction(compiler
, 1, TMP_REG1
, 0, src2
, src2w
);
1623 return SLJIT_SUCCESS
;
1626 if (dst
== src1
&& dstw
== src1w
) {
1627 if (src2
& SLJIT_IMM
) {
1628 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1629 if ((dst
== SLJIT_R0
) && (src2w
> 127 || src2w
< -128) && (compiler
->mode32
|| IS_HALFWORD(src2w
))) {
1631 if ((dst
== SLJIT_R0
) && (src2w
> 127 || src2w
< -128)) {
1633 BINARY_EAX_IMM(op_eax_imm
, src2w
);
1636 BINARY_IMM(op_imm
, op_mr
, src2w
, dst
, dstw
);
1639 else if (FAST_IS_REG(dst
)) {
1640 inst
= emit_x86_instruction(compiler
, 1, dst
, dstw
, src2
, src2w
);
1644 else if (FAST_IS_REG(src2
)) {
1645 /* Special exception for sljit_emit_op_flags. */
1646 inst
= emit_x86_instruction(compiler
, 1, src2
, src2w
, dst
, dstw
);
1651 EMIT_MOV(compiler
, TMP_REG1
, 0, src2
, src2w
);
1652 inst
= emit_x86_instruction(compiler
, 1, TMP_REG1
, 0, dst
, dstw
);
1656 return SLJIT_SUCCESS
;
1659 /* Only for cumulative operations. */
1660 if (dst
== src2
&& dstw
== src2w
) {
1661 if (src1
& SLJIT_IMM
) {
1662 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1663 if ((dst
== SLJIT_R0
) && (src1w
> 127 || src1w
< -128) && (compiler
->mode32
|| IS_HALFWORD(src1w
))) {
1665 if ((dst
== SLJIT_R0
) && (src1w
> 127 || src1w
< -128)) {
1667 BINARY_EAX_IMM(op_eax_imm
, src1w
);
1670 BINARY_IMM(op_imm
, op_mr
, src1w
, dst
, dstw
);
1673 else if (FAST_IS_REG(dst
)) {
1674 inst
= emit_x86_instruction(compiler
, 1, dst
, dstw
, src1
, src1w
);
1678 else if (FAST_IS_REG(src1
)) {
1679 inst
= emit_x86_instruction(compiler
, 1, src1
, src1w
, dst
, dstw
);
1684 EMIT_MOV(compiler
, TMP_REG1
, 0, src1
, src1w
);
1685 inst
= emit_x86_instruction(compiler
, 1, TMP_REG1
, 0, dst
, dstw
);
1689 return SLJIT_SUCCESS
;
1692 /* General version. */
1693 if (FAST_IS_REG(dst
)) {
1694 EMIT_MOV(compiler
, dst
, 0, src1
, src1w
);
1695 if (src2
& SLJIT_IMM
) {
1696 BINARY_IMM(op_imm
, op_mr
, src2w
, dst
, 0);
1699 inst
= emit_x86_instruction(compiler
, 1, dst
, 0, src2
, src2w
);
1705 /* This version requires less memory writing. */
1706 EMIT_MOV(compiler
, TMP_REG1
, 0, src1
, src1w
);
1707 if (src2
& SLJIT_IMM
) {
1708 BINARY_IMM(op_imm
, op_mr
, src2w
, TMP_REG1
, 0);
1711 inst
= emit_x86_instruction(compiler
, 1, TMP_REG1
, 0, src2
, src2w
);
1715 EMIT_MOV(compiler
, dst
, dstw
, TMP_REG1
, 0);
1718 return SLJIT_SUCCESS
;
1721 static sljit_s32
emit_non_cum_binary(struct sljit_compiler
*compiler
,
1723 sljit_s32 dst
, sljit_sw dstw
,
1724 sljit_s32 src1
, sljit_sw src1w
,
1725 sljit_s32 src2
, sljit_sw src2w
)
1728 sljit_u8 op_eax_imm
= (op_types
>> 24);
1729 sljit_u8 op_rm
= (op_types
>> 16) & 0xff;
1730 sljit_u8 op_mr
= (op_types
>> 8) & 0xff;
1731 sljit_u8 op_imm
= op_types
& 0xff;
1733 if (dst
== SLJIT_UNUSED
) {
1734 EMIT_MOV(compiler
, TMP_REG1
, 0, src1
, src1w
);
1735 if (src2
& SLJIT_IMM
) {
1736 BINARY_IMM(op_imm
, op_mr
, src2w
, TMP_REG1
, 0);
1739 inst
= emit_x86_instruction(compiler
, 1, TMP_REG1
, 0, src2
, src2w
);
1743 return SLJIT_SUCCESS
;
1746 if (dst
== src1
&& dstw
== src1w
) {
1747 if (src2
& SLJIT_IMM
) {
1748 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1749 if ((dst
== SLJIT_R0
) && (src2w
> 127 || src2w
< -128) && (compiler
->mode32
|| IS_HALFWORD(src2w
))) {
1751 if ((dst
== SLJIT_R0
) && (src2w
> 127 || src2w
< -128)) {
1753 BINARY_EAX_IMM(op_eax_imm
, src2w
);
1756 BINARY_IMM(op_imm
, op_mr
, src2w
, dst
, dstw
);
1759 else if (FAST_IS_REG(dst
)) {
1760 inst
= emit_x86_instruction(compiler
, 1, dst
, dstw
, src2
, src2w
);
1764 else if (FAST_IS_REG(src2
)) {
1765 inst
= emit_x86_instruction(compiler
, 1, src2
, src2w
, dst
, dstw
);
1770 EMIT_MOV(compiler
, TMP_REG1
, 0, src2
, src2w
);
1771 inst
= emit_x86_instruction(compiler
, 1, TMP_REG1
, 0, dst
, dstw
);
1775 return SLJIT_SUCCESS
;
1778 /* General version. */
1779 if (FAST_IS_REG(dst
) && dst
!= src2
) {
1780 EMIT_MOV(compiler
, dst
, 0, src1
, src1w
);
1781 if (src2
& SLJIT_IMM
) {
1782 BINARY_IMM(op_imm
, op_mr
, src2w
, dst
, 0);
1785 inst
= emit_x86_instruction(compiler
, 1, dst
, 0, src2
, src2w
);
1791 /* This version requires less memory writing. */
1792 EMIT_MOV(compiler
, TMP_REG1
, 0, src1
, src1w
);
1793 if (src2
& SLJIT_IMM
) {
1794 BINARY_IMM(op_imm
, op_mr
, src2w
, TMP_REG1
, 0);
1797 inst
= emit_x86_instruction(compiler
, 1, TMP_REG1
, 0, src2
, src2w
);
1801 EMIT_MOV(compiler
, dst
, dstw
, TMP_REG1
, 0);
1804 return SLJIT_SUCCESS
;
1807 static sljit_s32
emit_mul(struct sljit_compiler
*compiler
,
1808 sljit_s32 dst
, sljit_sw dstw
,
1809 sljit_s32 src1
, sljit_sw src1w
,
1810 sljit_s32 src2
, sljit_sw src2w
)
1815 dst_r
= SLOW_IS_REG(dst
) ? dst
: TMP_REG1
;
1817 /* Register destination. */
1818 if (dst_r
== src1
&& !(src2
& SLJIT_IMM
)) {
1819 inst
= emit_x86_instruction(compiler
, 2, dst_r
, 0, src2
, src2w
);
1824 else if (dst_r
== src2
&& !(src1
& SLJIT_IMM
)) {
1825 inst
= emit_x86_instruction(compiler
, 2, dst_r
, 0, src1
, src1w
);
1830 else if (src1
& SLJIT_IMM
) {
1831 if (src2
& SLJIT_IMM
) {
1832 EMIT_MOV(compiler
, dst_r
, 0, SLJIT_IMM
, src2w
);
1837 if (src1w
<= 127 && src1w
>= -128) {
1838 inst
= emit_x86_instruction(compiler
, 1, dst_r
, 0, src2
, src2w
);
1840 *inst
= IMUL_r_rm_i8
;
1841 inst
= (sljit_u8
*)ensure_buf(compiler
, 1 + 1);
1844 *inst
= (sljit_s8
)src1w
;
1846 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1848 inst
= emit_x86_instruction(compiler
, 1, dst_r
, 0, src2
, src2w
);
1850 *inst
= IMUL_r_rm_i32
;
1851 inst
= (sljit_u8
*)ensure_buf(compiler
, 1 + 4);
1854 sljit_unaligned_store_sw(inst
, src1w
);
1857 else if (IS_HALFWORD(src1w
)) {
1858 inst
= emit_x86_instruction(compiler
, 1, dst_r
, 0, src2
, src2w
);
1860 *inst
= IMUL_r_rm_i32
;
1861 inst
= (sljit_u8
*)ensure_buf(compiler
, 1 + 4);
1864 sljit_unaligned_store_s32(inst
, (sljit_s32
)src1w
);
1868 EMIT_MOV(compiler
, dst_r
, 0, src2
, src2w
);
1869 FAIL_IF(emit_load_imm64(compiler
, TMP_REG2
, src1w
));
1870 inst
= emit_x86_instruction(compiler
, 2, dst_r
, 0, TMP_REG2
, 0);
1877 else if (src2
& SLJIT_IMM
) {
1878 /* Note: src1 is NOT immediate. */
1880 if (src2w
<= 127 && src2w
>= -128) {
1881 inst
= emit_x86_instruction(compiler
, 1, dst_r
, 0, src1
, src1w
);
1883 *inst
= IMUL_r_rm_i8
;
1884 inst
= (sljit_u8
*)ensure_buf(compiler
, 1 + 1);
1887 *inst
= (sljit_s8
)src2w
;
1889 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1891 inst
= emit_x86_instruction(compiler
, 1, dst_r
, 0, src1
, src1w
);
1893 *inst
= IMUL_r_rm_i32
;
1894 inst
= (sljit_u8
*)ensure_buf(compiler
, 1 + 4);
1897 sljit_unaligned_store_sw(inst
, src2w
);
1900 else if (IS_HALFWORD(src2w
)) {
1901 inst
= emit_x86_instruction(compiler
, 1, dst_r
, 0, src1
, src1w
);
1903 *inst
= IMUL_r_rm_i32
;
1904 inst
= (sljit_u8
*)ensure_buf(compiler
, 1 + 4);
1907 sljit_unaligned_store_s32(inst
, (sljit_s32
)src2w
);
1911 EMIT_MOV(compiler
, dst_r
, 0, src1
, src1w
);
1912 FAIL_IF(emit_load_imm64(compiler
, TMP_REG2
, src2w
));
1913 inst
= emit_x86_instruction(compiler
, 2, dst_r
, 0, TMP_REG2
, 0);
1921 /* Neither argument is immediate. */
1922 if (ADDRESSING_DEPENDS_ON(src2
, dst_r
))
1924 EMIT_MOV(compiler
, dst_r
, 0, src1
, src1w
);
1925 inst
= emit_x86_instruction(compiler
, 2, dst_r
, 0, src2
, src2w
);
1931 if (dst
& SLJIT_MEM
)
1932 EMIT_MOV(compiler
, dst
, dstw
, TMP_REG1
, 0);
1934 return SLJIT_SUCCESS
;
1937 static sljit_s32
emit_lea_binary(struct sljit_compiler
*compiler
,
1938 sljit_s32 dst
, sljit_sw dstw
,
1939 sljit_s32 src1
, sljit_sw src1w
,
1940 sljit_s32 src2
, sljit_sw src2w
)
1943 sljit_s32 dst_r
, done
= 0;
1945 /* These cases better be left to handled by normal way. */
1946 if (dst
== src1
&& dstw
== src1w
)
1947 return SLJIT_ERR_UNSUPPORTED
;
1948 if (dst
== src2
&& dstw
== src2w
)
1949 return SLJIT_ERR_UNSUPPORTED
;
1951 dst_r
= FAST_IS_REG(dst
) ? dst
: TMP_REG1
;
1953 if (FAST_IS_REG(src1
)) {
1954 if (FAST_IS_REG(src2
)) {
1955 inst
= emit_x86_instruction(compiler
, 1, dst_r
, 0, SLJIT_MEM2(src1
, src2
), 0);
1960 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1961 if ((src2
& SLJIT_IMM
) && (compiler
->mode32
|| IS_HALFWORD(src2w
))) {
1962 inst
= emit_x86_instruction(compiler
, 1, dst_r
, 0, SLJIT_MEM1(src1
), (sljit_s32
)src2w
);
1964 if (src2
& SLJIT_IMM
) {
1965 inst
= emit_x86_instruction(compiler
, 1, dst_r
, 0, SLJIT_MEM1(src1
), src2w
);
1972 else if (FAST_IS_REG(src2
)) {
1973 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1974 if ((src1
& SLJIT_IMM
) && (compiler
->mode32
|| IS_HALFWORD(src1w
))) {
1975 inst
= emit_x86_instruction(compiler
, 1, dst_r
, 0, SLJIT_MEM1(src2
), (sljit_s32
)src1w
);
1977 if (src1
& SLJIT_IMM
) {
1978 inst
= emit_x86_instruction(compiler
, 1, dst_r
, 0, SLJIT_MEM1(src2
), src1w
);
1987 if (dst_r
== TMP_REG1
)
1988 return emit_mov(compiler
, dst
, dstw
, TMP_REG1
, 0);
1989 return SLJIT_SUCCESS
;
1991 return SLJIT_ERR_UNSUPPORTED
;
1994 static sljit_s32
emit_cmp_binary(struct sljit_compiler
*compiler
,
1995 sljit_s32 src1
, sljit_sw src1w
,
1996 sljit_s32 src2
, sljit_sw src2w
)
2000 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
2001 if (src1
== SLJIT_R0
&& (src2
& SLJIT_IMM
) && (src2w
> 127 || src2w
< -128) && (compiler
->mode32
|| IS_HALFWORD(src2w
))) {
2003 if (src1
== SLJIT_R0
&& (src2
& SLJIT_IMM
) && (src2w
> 127 || src2w
< -128)) {
2005 BINARY_EAX_IMM(CMP_EAX_i32
, src2w
);
2006 return SLJIT_SUCCESS
;
2009 if (FAST_IS_REG(src1
)) {
2010 if (src2
& SLJIT_IMM
) {
2011 BINARY_IMM(CMP
, CMP_rm_r
, src2w
, src1
, 0);
2014 inst
= emit_x86_instruction(compiler
, 1, src1
, 0, src2
, src2w
);
2018 return SLJIT_SUCCESS
;
2021 if (FAST_IS_REG(src2
) && !(src1
& SLJIT_IMM
)) {
2022 inst
= emit_x86_instruction(compiler
, 1, src2
, 0, src1
, src1w
);
2025 return SLJIT_SUCCESS
;
2028 if (src2
& SLJIT_IMM
) {
2029 if (src1
& SLJIT_IMM
) {
2030 EMIT_MOV(compiler
, TMP_REG1
, 0, src1
, src1w
);
2034 BINARY_IMM(CMP
, CMP_rm_r
, src2w
, src1
, src1w
);
2037 EMIT_MOV(compiler
, TMP_REG1
, 0, src1
, src1w
);
2038 inst
= emit_x86_instruction(compiler
, 1, TMP_REG1
, 0, src2
, src2w
);
2042 return SLJIT_SUCCESS
;
2045 static sljit_s32
emit_test_binary(struct sljit_compiler
*compiler
,
2046 sljit_s32 src1
, sljit_sw src1w
,
2047 sljit_s32 src2
, sljit_sw src2w
)
2051 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
2052 if (src1
== SLJIT_R0
&& (src2
& SLJIT_IMM
) && (src2w
> 127 || src2w
< -128) && (compiler
->mode32
|| IS_HALFWORD(src2w
))) {
2054 if (src1
== SLJIT_R0
&& (src2
& SLJIT_IMM
) && (src2w
> 127 || src2w
< -128)) {
2056 BINARY_EAX_IMM(TEST_EAX_i32
, src2w
);
2057 return SLJIT_SUCCESS
;
2060 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
2061 if (src2
== SLJIT_R0
&& (src1
& SLJIT_IMM
) && (src1w
> 127 || src1w
< -128) && (compiler
->mode32
|| IS_HALFWORD(src1w
))) {
2063 if (src2
== SLJIT_R0
&& (src1
& SLJIT_IMM
) && (src1w
> 127 || src1w
< -128)) {
2065 BINARY_EAX_IMM(TEST_EAX_i32
, src1w
);
2066 return SLJIT_SUCCESS
;
2069 if (!(src1
& SLJIT_IMM
)) {
2070 if (src2
& SLJIT_IMM
) {
2071 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
2072 if (IS_HALFWORD(src2w
) || compiler
->mode32
) {
2073 inst
= emit_x86_instruction(compiler
, 1, SLJIT_IMM
, src2w
, src1
, src1w
);
2078 FAIL_IF(emit_load_imm64(compiler
, TMP_REG1
, src2w
));
2079 inst
= emit_x86_instruction(compiler
, 1, TMP_REG1
, 0, src1
, src1w
);
2084 inst
= emit_x86_instruction(compiler
, 1, SLJIT_IMM
, src2w
, src1
, src1w
);
2088 return SLJIT_SUCCESS
;
2090 else if (FAST_IS_REG(src1
)) {
2091 inst
= emit_x86_instruction(compiler
, 1, src1
, 0, src2
, src2w
);
2094 return SLJIT_SUCCESS
;
2098 if (!(src2
& SLJIT_IMM
)) {
2099 if (src1
& SLJIT_IMM
) {
2100 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
2101 if (IS_HALFWORD(src1w
) || compiler
->mode32
) {
2102 inst
= emit_x86_instruction(compiler
, 1, SLJIT_IMM
, src1w
, src2
, src2w
);
2107 FAIL_IF(emit_load_imm64(compiler
, TMP_REG1
, src1w
));
2108 inst
= emit_x86_instruction(compiler
, 1, TMP_REG1
, 0, src2
, src2w
);
2113 inst
= emit_x86_instruction(compiler
, 1, src1
, src1w
, src2
, src2w
);
2117 return SLJIT_SUCCESS
;
2119 else if (FAST_IS_REG(src2
)) {
2120 inst
= emit_x86_instruction(compiler
, 1, src2
, 0, src1
, src1w
);
2123 return SLJIT_SUCCESS
;
2127 EMIT_MOV(compiler
, TMP_REG1
, 0, src1
, src1w
);
2128 if (src2
& SLJIT_IMM
) {
2129 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
2130 if (IS_HALFWORD(src2w
) || compiler
->mode32
) {
2131 inst
= emit_x86_instruction(compiler
, 1, SLJIT_IMM
, src2w
, TMP_REG1
, 0);
2136 FAIL_IF(emit_load_imm64(compiler
, TMP_REG2
, src2w
));
2137 inst
= emit_x86_instruction(compiler
, 1, TMP_REG2
, 0, TMP_REG1
, 0);
2142 inst
= emit_x86_instruction(compiler
, 1, SLJIT_IMM
, src2w
, TMP_REG1
, 0);
2148 inst
= emit_x86_instruction(compiler
, 1, TMP_REG1
, 0, src2
, src2w
);
2152 return SLJIT_SUCCESS
;
2155 static sljit_s32
emit_shift(struct sljit_compiler
*compiler
,
2157 sljit_s32 dst
, sljit_sw dstw
,
2158 sljit_s32 src1
, sljit_sw src1w
,
2159 sljit_s32 src2
, sljit_sw src2w
)
2163 if ((src2
& SLJIT_IMM
) || (src2
== SLJIT_PREF_SHIFT_REG
)) {
2164 if (dst
== src1
&& dstw
== src1w
) {
2165 inst
= emit_x86_instruction(compiler
, 1 | EX86_SHIFT_INS
, src2
, src2w
, dst
, dstw
);
2168 return SLJIT_SUCCESS
;
2170 if (dst
== SLJIT_UNUSED
) {
2171 EMIT_MOV(compiler
, TMP_REG1
, 0, src1
, src1w
);
2172 inst
= emit_x86_instruction(compiler
, 1 | EX86_SHIFT_INS
, src2
, src2w
, TMP_REG1
, 0);
2175 return SLJIT_SUCCESS
;
2177 if (dst
== SLJIT_PREF_SHIFT_REG
&& src2
== SLJIT_PREF_SHIFT_REG
) {
2178 EMIT_MOV(compiler
, TMP_REG1
, 0, src1
, src1w
);
2179 inst
= emit_x86_instruction(compiler
, 1 | EX86_SHIFT_INS
, SLJIT_PREF_SHIFT_REG
, 0, TMP_REG1
, 0);
2182 EMIT_MOV(compiler
, SLJIT_PREF_SHIFT_REG
, 0, TMP_REG1
, 0);
2183 return SLJIT_SUCCESS
;
2185 if (FAST_IS_REG(dst
)) {
2186 EMIT_MOV(compiler
, dst
, 0, src1
, src1w
);
2187 inst
= emit_x86_instruction(compiler
, 1 | EX86_SHIFT_INS
, src2
, src2w
, dst
, 0);
2190 return SLJIT_SUCCESS
;
2193 EMIT_MOV(compiler
, TMP_REG1
, 0, src1
, src1w
);
2194 inst
= emit_x86_instruction(compiler
, 1 | EX86_SHIFT_INS
, src2
, src2w
, TMP_REG1
, 0);
2197 EMIT_MOV(compiler
, dst
, dstw
, TMP_REG1
, 0);
2198 return SLJIT_SUCCESS
;
2201 if (dst
== SLJIT_PREF_SHIFT_REG
) {
2202 EMIT_MOV(compiler
, TMP_REG1
, 0, src1
, src1w
);
2203 EMIT_MOV(compiler
, SLJIT_PREF_SHIFT_REG
, 0, src2
, src2w
);
2204 inst
= emit_x86_instruction(compiler
, 1 | EX86_SHIFT_INS
, SLJIT_PREF_SHIFT_REG
, 0, TMP_REG1
, 0);
2207 EMIT_MOV(compiler
, SLJIT_PREF_SHIFT_REG
, 0, TMP_REG1
, 0);
2209 else if (SLOW_IS_REG(dst
) && dst
!= src2
&& !ADDRESSING_DEPENDS_ON(src2
, dst
)) {
2211 EMIT_MOV(compiler
, dst
, 0, src1
, src1w
);
2212 EMIT_MOV(compiler
, TMP_REG1
, 0, SLJIT_PREF_SHIFT_REG
, 0);
2213 EMIT_MOV(compiler
, SLJIT_PREF_SHIFT_REG
, 0, src2
, src2w
);
2214 inst
= emit_x86_instruction(compiler
, 1 | EX86_SHIFT_INS
, SLJIT_PREF_SHIFT_REG
, 0, dst
, 0);
2217 EMIT_MOV(compiler
, SLJIT_PREF_SHIFT_REG
, 0, TMP_REG1
, 0);
2220 /* This case is complex since ecx itself may be used for
2221 addressing, and this case must be supported as well. */
2222 EMIT_MOV(compiler
, TMP_REG1
, 0, src1
, src1w
);
2223 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
2224 EMIT_MOV(compiler
, SLJIT_MEM1(SLJIT_SP
), 0, SLJIT_PREF_SHIFT_REG
, 0);
2225 EMIT_MOV(compiler
, SLJIT_PREF_SHIFT_REG
, 0, src2
, src2w
);
2226 inst
= emit_x86_instruction(compiler
, 1 | EX86_SHIFT_INS
, SLJIT_PREF_SHIFT_REG
, 0, TMP_REG1
, 0);
2229 EMIT_MOV(compiler
, SLJIT_PREF_SHIFT_REG
, 0, SLJIT_MEM1(SLJIT_SP
), 0);
2231 EMIT_MOV(compiler
, TMP_REG2
, 0, SLJIT_PREF_SHIFT_REG
, 0);
2232 EMIT_MOV(compiler
, SLJIT_PREF_SHIFT_REG
, 0, src2
, src2w
);
2233 inst
= emit_x86_instruction(compiler
, 1 | EX86_SHIFT_INS
, SLJIT_PREF_SHIFT_REG
, 0, TMP_REG1
, 0);
2236 EMIT_MOV(compiler
, SLJIT_PREF_SHIFT_REG
, 0, TMP_REG2
, 0);
2238 if (dst
!= SLJIT_UNUSED
)
2239 return emit_mov(compiler
, dst
, dstw
, TMP_REG1
, 0);
2242 return SLJIT_SUCCESS
;
2245 static sljit_s32
emit_shift_with_flags(struct sljit_compiler
*compiler
,
2246 sljit_u8 mode
, sljit_s32 set_flags
,
2247 sljit_s32 dst
, sljit_sw dstw
,
2248 sljit_s32 src1
, sljit_sw src1w
,
2249 sljit_s32 src2
, sljit_sw src2w
)
2251 /* The CPU does not set flags if the shift count is 0. */
2252 if (src2
& SLJIT_IMM
) {
2253 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
2254 if ((src2w
& 0x3f) != 0 || (compiler
->mode32
&& (src2w
& 0x1f) != 0))
2255 return emit_shift(compiler
, mode
, dst
, dstw
, src1
, src1w
, src2
, src2w
);
2257 if ((src2w
& 0x1f) != 0)
2258 return emit_shift(compiler
, mode
, dst
, dstw
, src1
, src1w
, src2
, src2w
);
2261 return emit_mov(compiler
, dst
, dstw
, src1
, src1w
);
2262 /* OR dst, src, 0 */
2263 return emit_cum_binary(compiler
, BINARY_OPCODE(OR
),
2264 dst
, dstw
, src1
, src1w
, SLJIT_IMM
, 0);
2268 return emit_shift(compiler
, mode
, dst
, dstw
, src1
, src1w
, src2
, src2w
);
2270 if (!FAST_IS_REG(dst
))
2271 FAIL_IF(emit_cmp_binary(compiler
, src1
, src1w
, SLJIT_IMM
, 0));
2273 FAIL_IF(emit_shift(compiler
, mode
, dst
, dstw
, src1
, src1w
, src2
, src2w
));
2275 if (FAST_IS_REG(dst
))
2276 return emit_cmp_binary(compiler
, (dst
== SLJIT_UNUSED
) ? TMP_REG1
: dst
, dstw
, SLJIT_IMM
, 0);
2277 return SLJIT_SUCCESS
;
2280 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_op2(struct sljit_compiler
*compiler
, sljit_s32 op
,
2281 sljit_s32 dst
, sljit_sw dstw
,
2282 sljit_s32 src1
, sljit_sw src1w
,
2283 sljit_s32 src2
, sljit_sw src2w
)
2286 CHECK(check_sljit_emit_op2(compiler
, op
, dst
, dstw
, src1
, src1w
, src2
, src2w
));
2287 ADJUST_LOCAL_OFFSET(dst
, dstw
);
2288 ADJUST_LOCAL_OFFSET(src1
, src1w
);
2289 ADJUST_LOCAL_OFFSET(src2
, src2w
);
2291 CHECK_EXTRA_REGS(dst
, dstw
, (void)0);
2292 CHECK_EXTRA_REGS(src1
, src1w
, (void)0);
2293 CHECK_EXTRA_REGS(src2
, src2w
, (void)0);
2294 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
2295 compiler
->mode32
= op
& SLJIT_I32_OP
;
2298 if (dst
== SLJIT_UNUSED
&& !HAS_FLAGS(op
))
2299 return SLJIT_SUCCESS
;
2301 switch (GET_OPCODE(op
)) {
2303 if (!HAS_FLAGS(op
)) {
2304 if (emit_lea_binary(compiler
, dst
, dstw
, src1
, src1w
, src2
, src2w
) != SLJIT_ERR_UNSUPPORTED
)
2305 return compiler
->error
;
2307 return emit_cum_binary(compiler
, BINARY_OPCODE(ADD
),
2308 dst
, dstw
, src1
, src1w
, src2
, src2w
);
2310 return emit_cum_binary(compiler
, BINARY_OPCODE(ADC
),
2311 dst
, dstw
, src1
, src1w
, src2
, src2w
);
2313 if (!HAS_FLAGS(op
)) {
2314 if ((src2
& SLJIT_IMM
) && emit_lea_binary(compiler
, dst
, dstw
, src1
, src1w
, SLJIT_IMM
, -src2w
) != SLJIT_ERR_UNSUPPORTED
)
2315 return compiler
->error
;
2316 if (SLOW_IS_REG(dst
) && src2
== dst
) {
2317 FAIL_IF(emit_non_cum_binary(compiler
, BINARY_OPCODE(SUB
), dst
, 0, dst
, 0, src1
, src1w
));
2318 return emit_unary(compiler
, NEG_rm
, dst
, 0, dst
, 0);
2322 if (dst
== SLJIT_UNUSED
)
2323 return emit_cmp_binary(compiler
, src1
, src1w
, src2
, src2w
);
2324 return emit_non_cum_binary(compiler
, BINARY_OPCODE(SUB
),
2325 dst
, dstw
, src1
, src1w
, src2
, src2w
);
2327 return emit_non_cum_binary(compiler
, BINARY_OPCODE(SBB
),
2328 dst
, dstw
, src1
, src1w
, src2
, src2w
);
2330 return emit_mul(compiler
, dst
, dstw
, src1
, src1w
, src2
, src2w
);
2332 if (dst
== SLJIT_UNUSED
)
2333 return emit_test_binary(compiler
, src1
, src1w
, src2
, src2w
);
2334 return emit_cum_binary(compiler
, BINARY_OPCODE(AND
),
2335 dst
, dstw
, src1
, src1w
, src2
, src2w
);
2337 return emit_cum_binary(compiler
, BINARY_OPCODE(OR
),
2338 dst
, dstw
, src1
, src1w
, src2
, src2w
);
2340 return emit_cum_binary(compiler
, BINARY_OPCODE(XOR
),
2341 dst
, dstw
, src1
, src1w
, src2
, src2w
);
2343 return emit_shift_with_flags(compiler
, SHL
, HAS_FLAGS(op
),
2344 dst
, dstw
, src1
, src1w
, src2
, src2w
);
2346 return emit_shift_with_flags(compiler
, SHR
, HAS_FLAGS(op
),
2347 dst
, dstw
, src1
, src1w
, src2
, src2w
);
2349 return emit_shift_with_flags(compiler
, SAR
, HAS_FLAGS(op
),
2350 dst
, dstw
, src1
, src1w
, src2
, src2w
);
2353 return SLJIT_SUCCESS
;
2356 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_op_src(struct sljit_compiler
*compiler
, sljit_s32 op
,
2357 sljit_s32 src
, sljit_sw srcw
)
2360 CHECK(check_sljit_emit_op_src(compiler
, op
, src
, srcw
));
2361 ADJUST_LOCAL_OFFSET(src
, srcw
);
2363 CHECK_EXTRA_REGS(src
, srcw
, (void)0);
2366 case SLJIT_FAST_RETURN
:
2367 return emit_fast_return(compiler
, src
, srcw
);
2368 case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN
:
2369 /* Don't adjust shadow stack if it isn't enabled. */
2370 if (!cpu_has_shadow_stack ())
2371 return SLJIT_SUCCESS
;
2372 return adjust_shadow_stack(compiler
, src
, srcw
, SLJIT_UNUSED
, 0);
2373 case SLJIT_PREFETCH_L1
:
2374 case SLJIT_PREFETCH_L2
:
2375 case SLJIT_PREFETCH_L3
:
2376 case SLJIT_PREFETCH_ONCE
:
2377 return emit_prefetch(compiler
, op
, src
, srcw
);
2380 return SLJIT_SUCCESS
;
2383 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_get_register_index(sljit_s32 reg
)
2385 CHECK_REG_INDEX(check_sljit_get_register_index(reg
));
2386 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
2387 if (reg
>= SLJIT_R3
&& reg
<= SLJIT_R8
)
2390 return reg_map
[reg
];
2393 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_get_float_register_index(sljit_s32 reg
)
2395 CHECK_REG_INDEX(check_sljit_get_float_register_index(reg
));
2396 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
2399 return freg_map
[reg
];
2403 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_op_custom(struct sljit_compiler
*compiler
,
2404 void *instruction
, sljit_s32 size
)
2409 CHECK(check_sljit_emit_op_custom(compiler
, instruction
, size
));
2411 inst
= (sljit_u8
*)ensure_buf(compiler
, 1 + size
);
2414 SLJIT_MEMCPY(inst
, instruction
, size
);
2415 return SLJIT_SUCCESS
;
2418 /* --------------------------------------------------------------------- */
2419 /* Floating point operators */
2420 /* --------------------------------------------------------------------- */
2422 /* Alignment(3) + 4 * 16 bytes. */
2423 static sljit_s32 sse2_data
[3 + (4 * 4)];
2424 static sljit_s32
*sse2_buffer
;
2426 static void init_compiler(void)
2428 /* Align to 16 bytes. */
2429 sse2_buffer
= (sljit_s32
*)(((sljit_uw
)sse2_data
+ 15) & ~0xf);
2431 /* Single precision constants (each constant is 16 byte long). */
2432 sse2_buffer
[0] = 0x80000000;
2433 sse2_buffer
[4] = 0x7fffffff;
2434 /* Double precision constants (each constant is 16 byte long). */
2436 sse2_buffer
[9] = 0x80000000;
2437 sse2_buffer
[12] = 0xffffffff;
2438 sse2_buffer
[13] = 0x7fffffff;
2441 static sljit_s32
emit_sse2(struct sljit_compiler
*compiler
, sljit_u8 opcode
,
2442 sljit_s32 single
, sljit_s32 xmm1
, sljit_s32 xmm2
, sljit_sw xmm2w
)
2446 inst
= emit_x86_instruction(compiler
, 2 | (single
? EX86_PREF_F3
: EX86_PREF_F2
) | EX86_SSE2
, xmm1
, 0, xmm2
, xmm2w
);
2450 return SLJIT_SUCCESS
;
2453 static sljit_s32
emit_sse2_logic(struct sljit_compiler
*compiler
, sljit_u8 opcode
,
2454 sljit_s32 pref66
, sljit_s32 xmm1
, sljit_s32 xmm2
, sljit_sw xmm2w
)
2458 inst
= emit_x86_instruction(compiler
, 2 | (pref66
? EX86_PREF_66
: 0) | EX86_SSE2
, xmm1
, 0, xmm2
, xmm2w
);
2462 return SLJIT_SUCCESS
;
2465 static SLJIT_INLINE sljit_s32
emit_sse2_load(struct sljit_compiler
*compiler
,
2466 sljit_s32 single
, sljit_s32 dst
, sljit_s32 src
, sljit_sw srcw
)
2468 return emit_sse2(compiler
, MOVSD_x_xm
, single
, dst
, src
, srcw
);
2471 static SLJIT_INLINE sljit_s32
emit_sse2_store(struct sljit_compiler
*compiler
,
2472 sljit_s32 single
, sljit_s32 dst
, sljit_sw dstw
, sljit_s32 src
)
2474 return emit_sse2(compiler
, MOVSD_xm_x
, single
, src
, dst
, dstw
);
2477 static SLJIT_INLINE sljit_s32
sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler
*compiler
, sljit_s32 op
,
2478 sljit_s32 dst
, sljit_sw dstw
,
2479 sljit_s32 src
, sljit_sw srcw
)
2481 sljit_s32 dst_r
= FAST_IS_REG(dst
) ? dst
: TMP_REG1
;
2484 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
2485 if (GET_OPCODE(op
) == SLJIT_CONV_SW_FROM_F64
)
2486 compiler
->mode32
= 0;
2489 inst
= emit_x86_instruction(compiler
, 2 | ((op
& SLJIT_F32_OP
) ? EX86_PREF_F3
: EX86_PREF_F2
) | EX86_SSE2_OP2
, dst_r
, 0, src
, srcw
);
2492 *inst
= CVTTSD2SI_r_xm
;
2494 if (dst
& SLJIT_MEM
)
2495 return emit_mov(compiler
, dst
, dstw
, TMP_REG1
, 0);
2496 return SLJIT_SUCCESS
;
2499 static SLJIT_INLINE sljit_s32
sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler
*compiler
, sljit_s32 op
,
2500 sljit_s32 dst
, sljit_sw dstw
,
2501 sljit_s32 src
, sljit_sw srcw
)
2503 sljit_s32 dst_r
= FAST_IS_REG(dst
) ? dst
: TMP_FREG
;
2506 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
2507 if (GET_OPCODE(op
) == SLJIT_CONV_F64_FROM_SW
)
2508 compiler
->mode32
= 0;
2511 if (src
& SLJIT_IMM
) {
2512 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
2513 if (GET_OPCODE(op
) == SLJIT_CONV_F64_FROM_S32
)
2514 srcw
= (sljit_s32
)srcw
;
2516 EMIT_MOV(compiler
, TMP_REG1
, 0, src
, srcw
);
2521 inst
= emit_x86_instruction(compiler
, 2 | ((op
& SLJIT_F32_OP
) ? EX86_PREF_F3
: EX86_PREF_F2
) | EX86_SSE2_OP1
, dst_r
, 0, src
, srcw
);
2524 *inst
= CVTSI2SD_x_rm
;
2526 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
2527 compiler
->mode32
= 1;
2529 if (dst_r
== TMP_FREG
)
2530 return emit_sse2_store(compiler
, op
& SLJIT_F32_OP
, dst
, dstw
, TMP_FREG
);
2531 return SLJIT_SUCCESS
;
2534 static SLJIT_INLINE sljit_s32
sljit_emit_fop1_cmp(struct sljit_compiler
*compiler
, sljit_s32 op
,
2535 sljit_s32 src1
, sljit_sw src1w
,
2536 sljit_s32 src2
, sljit_sw src2w
)
2538 if (!FAST_IS_REG(src1
)) {
2539 FAIL_IF(emit_sse2_load(compiler
, op
& SLJIT_F32_OP
, TMP_FREG
, src1
, src1w
));
2543 return emit_sse2_logic(compiler
, UCOMISD_x_xm
, !(op
& SLJIT_F32_OP
), src1
, src2
, src2w
);
2546 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_fop1(struct sljit_compiler
*compiler
, sljit_s32 op
,
2547 sljit_s32 dst
, sljit_sw dstw
,
2548 sljit_s32 src
, sljit_sw srcw
)
2552 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
2553 compiler
->mode32
= 1;
2557 SELECT_FOP1_OPERATION_WITH_CHECKS(compiler
, op
, dst
, dstw
, src
, srcw
);
2559 if (GET_OPCODE(op
) == SLJIT_MOV_F64
) {
2560 if (FAST_IS_REG(dst
))
2561 return emit_sse2_load(compiler
, op
& SLJIT_F32_OP
, dst
, src
, srcw
);
2562 if (FAST_IS_REG(src
))
2563 return emit_sse2_store(compiler
, op
& SLJIT_F32_OP
, dst
, dstw
, src
);
2564 FAIL_IF(emit_sse2_load(compiler
, op
& SLJIT_F32_OP
, TMP_FREG
, src
, srcw
));
2565 return emit_sse2_store(compiler
, op
& SLJIT_F32_OP
, dst
, dstw
, TMP_FREG
);
2568 if (GET_OPCODE(op
) == SLJIT_CONV_F64_FROM_F32
) {
2569 dst_r
= FAST_IS_REG(dst
) ? dst
: TMP_FREG
;
2570 if (FAST_IS_REG(src
)) {
2571 /* We overwrite the high bits of source. From SLJIT point of view,
2572 this is not an issue.
2573 Note: In SSE3, we could also use MOVDDUP and MOVSLDUP. */
2574 FAIL_IF(emit_sse2_logic(compiler
, UNPCKLPD_x_xm
, op
& SLJIT_F32_OP
, src
, src
, 0));
2577 FAIL_IF(emit_sse2_load(compiler
, !(op
& SLJIT_F32_OP
), TMP_FREG
, src
, srcw
));
2581 FAIL_IF(emit_sse2_logic(compiler
, CVTPD2PS_x_xm
, op
& SLJIT_F32_OP
, dst_r
, src
, 0));
2582 if (dst_r
== TMP_FREG
)
2583 return emit_sse2_store(compiler
, op
& SLJIT_F32_OP
, dst
, dstw
, TMP_FREG
);
2584 return SLJIT_SUCCESS
;
2587 if (FAST_IS_REG(dst
)) {
2590 FAIL_IF(emit_sse2_load(compiler
, op
& SLJIT_F32_OP
, dst_r
, src
, srcw
));
2594 FAIL_IF(emit_sse2_load(compiler
, op
& SLJIT_F32_OP
, dst_r
, src
, srcw
));
2597 switch (GET_OPCODE(op
)) {
2599 FAIL_IF(emit_sse2_logic(compiler
, XORPD_x_xm
, 1, dst_r
, SLJIT_MEM0(), (sljit_sw
)(op
& SLJIT_F32_OP
? sse2_buffer
: sse2_buffer
+ 8)));
2603 FAIL_IF(emit_sse2_logic(compiler
, ANDPD_x_xm
, 1, dst_r
, SLJIT_MEM0(), (sljit_sw
)(op
& SLJIT_F32_OP
? sse2_buffer
+ 4 : sse2_buffer
+ 12)));
2607 if (dst_r
== TMP_FREG
)
2608 return emit_sse2_store(compiler
, op
& SLJIT_F32_OP
, dst
, dstw
, TMP_FREG
);
2609 return SLJIT_SUCCESS
;
2612 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_fop2(struct sljit_compiler
*compiler
, sljit_s32 op
,
2613 sljit_s32 dst
, sljit_sw dstw
,
2614 sljit_s32 src1
, sljit_sw src1w
,
2615 sljit_s32 src2
, sljit_sw src2w
)
2620 CHECK(check_sljit_emit_fop2(compiler
, op
, dst
, dstw
, src1
, src1w
, src2
, src2w
));
2621 ADJUST_LOCAL_OFFSET(dst
, dstw
);
2622 ADJUST_LOCAL_OFFSET(src1
, src1w
);
2623 ADJUST_LOCAL_OFFSET(src2
, src2w
);
2625 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
2626 compiler
->mode32
= 1;
2629 if (FAST_IS_REG(dst
)) {
2632 ; /* Do nothing here. */
2633 else if (dst
== src2
&& (op
== SLJIT_ADD_F64
|| op
== SLJIT_MUL_F64
)) {
2634 /* Swap arguments. */
2638 else if (dst
!= src2
)
2639 FAIL_IF(emit_sse2_load(compiler
, op
& SLJIT_F32_OP
, dst_r
, src1
, src1w
));
2642 FAIL_IF(emit_sse2_load(compiler
, op
& SLJIT_F32_OP
, TMP_FREG
, src1
, src1w
));
2647 FAIL_IF(emit_sse2_load(compiler
, op
& SLJIT_F32_OP
, TMP_FREG
, src1
, src1w
));
2650 switch (GET_OPCODE(op
)) {
2652 FAIL_IF(emit_sse2(compiler
, ADDSD_x_xm
, op
& SLJIT_F32_OP
, dst_r
, src2
, src2w
));
2656 FAIL_IF(emit_sse2(compiler
, SUBSD_x_xm
, op
& SLJIT_F32_OP
, dst_r
, src2
, src2w
));
2660 FAIL_IF(emit_sse2(compiler
, MULSD_x_xm
, op
& SLJIT_F32_OP
, dst_r
, src2
, src2w
));
2664 FAIL_IF(emit_sse2(compiler
, DIVSD_x_xm
, op
& SLJIT_F32_OP
, dst_r
, src2
, src2w
));
2668 if (dst_r
== TMP_FREG
)
2669 return emit_sse2_store(compiler
, op
& SLJIT_F32_OP
, dst
, dstw
, TMP_FREG
);
2670 return SLJIT_SUCCESS
;
2673 /* --------------------------------------------------------------------- */
2674 /* Conditional instructions */
2675 /* --------------------------------------------------------------------- */
2677 SLJIT_API_FUNC_ATTRIBUTE
struct sljit_label
* sljit_emit_label(struct sljit_compiler
*compiler
)
2680 struct sljit_label
*label
;
2683 CHECK_PTR(check_sljit_emit_label(compiler
));
2685 if (compiler
->last_label
&& compiler
->last_label
->size
== compiler
->size
)
2686 return compiler
->last_label
;
2688 label
= (struct sljit_label
*)ensure_abuf(compiler
, sizeof(struct sljit_label
));
2689 PTR_FAIL_IF(!label
);
2690 set_label(label
, compiler
);
2692 inst
= (sljit_u8
*)ensure_buf(compiler
, 2);
2701 SLJIT_API_FUNC_ATTRIBUTE
struct sljit_jump
* sljit_emit_jump(struct sljit_compiler
*compiler
, sljit_s32 type
)
2704 struct sljit_jump
*jump
;
2707 CHECK_PTR(check_sljit_emit_jump(compiler
, type
));
2709 jump
= (struct sljit_jump
*)ensure_abuf(compiler
, sizeof(struct sljit_jump
));
2710 PTR_FAIL_IF_NULL(jump
);
2711 set_jump(jump
, compiler
, (type
& SLJIT_REWRITABLE_JUMP
) | ((type
& 0xff) << TYPE_SHIFT
));
2714 /* Worst case size. */
2715 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
2716 compiler
->size
+= (type
>= SLJIT_JUMP
) ? 5 : 6;
2718 compiler
->size
+= (type
>= SLJIT_JUMP
) ? (10 + 3) : (2 + 10 + 3);
2721 inst
= (sljit_u8
*)ensure_buf(compiler
, 2);
2722 PTR_FAIL_IF_NULL(inst
);
2729 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_ijump(struct sljit_compiler
*compiler
, sljit_s32 type
, sljit_s32 src
, sljit_sw srcw
)
2732 struct sljit_jump
*jump
;
2735 CHECK(check_sljit_emit_ijump(compiler
, type
, src
, srcw
));
2736 ADJUST_LOCAL_OFFSET(src
, srcw
);
2738 CHECK_EXTRA_REGS(src
, srcw
, (void)0);
2740 if (src
== SLJIT_IMM
) {
2741 jump
= (struct sljit_jump
*)ensure_abuf(compiler
, sizeof(struct sljit_jump
));
2743 set_jump(jump
, compiler
, JUMP_ADDR
| (type
<< TYPE_SHIFT
));
2744 jump
->u
.target
= srcw
;
2746 /* Worst case size. */
2747 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
2748 compiler
->size
+= 5;
2750 compiler
->size
+= 10 + 3;
2753 inst
= (sljit_u8
*)ensure_buf(compiler
, 2);
2760 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
2761 /* REX_W is not necessary (src is not immediate). */
2762 compiler
->mode32
= 1;
2764 inst
= emit_x86_instruction(compiler
, 1, 0, 0, src
, srcw
);
2767 *inst
|= (type
>= SLJIT_FAST_CALL
) ? CALL_rm
: JMP_rm
;
2769 return SLJIT_SUCCESS
;
2772 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_op_flags(struct sljit_compiler
*compiler
, sljit_s32 op
,
2773 sljit_s32 dst
, sljit_sw dstw
,
2777 sljit_u8 cond_set
= 0;
2778 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
2781 /* ADJUST_LOCAL_OFFSET and CHECK_EXTRA_REGS might overwrite these values. */
2782 sljit_s32 dst_save
= dst
;
2783 sljit_sw dstw_save
= dstw
;
2786 CHECK(check_sljit_emit_op_flags(compiler
, op
, dst
, dstw
, type
));
2788 ADJUST_LOCAL_OFFSET(dst
, dstw
);
2789 CHECK_EXTRA_REGS(dst
, dstw
, (void)0);
2792 /* setcc = jcc + 0x10. */
2793 cond_set
= get_jump_code(type
) + 0x10;
2795 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
2796 if (GET_OPCODE(op
) == SLJIT_OR
&& !GET_ALL_FLAGS(op
) && FAST_IS_REG(dst
)) {
2797 inst
= (sljit_u8
*)ensure_buf(compiler
, 1 + 4 + 3);
2800 /* Set low register to conditional flag. */
2801 *inst
++ = (reg_map
[TMP_REG1
] <= 7) ? REX
: REX_B
;
2804 *inst
++ = MOD_REG
| reg_lmap
[TMP_REG1
];
2805 *inst
++ = REX
| (reg_map
[TMP_REG1
] <= 7 ? 0 : REX_R
) | (reg_map
[dst
] <= 7 ? 0 : REX_B
);
2806 *inst
++ = OR_rm8_r8
;
2807 *inst
++ = MOD_REG
| (reg_lmap
[TMP_REG1
] << 3) | reg_lmap
[dst
];
2808 return SLJIT_SUCCESS
;
2811 reg
= (GET_OPCODE(op
) < SLJIT_ADD
&& FAST_IS_REG(dst
)) ? dst
: TMP_REG1
;
2813 inst
= (sljit_u8
*)ensure_buf(compiler
, 1 + 4 + 4);
2816 /* Set low register to conditional flag. */
2817 *inst
++ = (reg_map
[reg
] <= 7) ? REX
: REX_B
;
2820 *inst
++ = MOD_REG
| reg_lmap
[reg
];
2821 *inst
++ = REX_W
| (reg_map
[reg
] <= 7 ? 0 : (REX_B
| REX_R
));
2822 /* The movzx instruction does not affect flags. */
2824 *inst
++ = MOVZX_r_rm8
;
2825 *inst
= MOD_REG
| (reg_lmap
[reg
] << 3) | reg_lmap
[reg
];
2827 if (reg
!= TMP_REG1
)
2828 return SLJIT_SUCCESS
;
2830 if (GET_OPCODE(op
) < SLJIT_ADD
) {
2831 compiler
->mode32
= GET_OPCODE(op
) != SLJIT_MOV
;
2832 return emit_mov(compiler
, dst
, dstw
, TMP_REG1
, 0);
2835 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
2836 || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
2837 compiler
->skip_checks
= 1;
2839 return sljit_emit_op2(compiler
, op
, dst_save
, dstw_save
, dst_save
, dstw_save
, TMP_REG1
, 0);
2842 /* The SLJIT_CONFIG_X86_32 code path starts here. */
2843 if (GET_OPCODE(op
) < SLJIT_ADD
&& FAST_IS_REG(dst
)) {
2844 if (reg_map
[dst
] <= 4) {
2845 /* Low byte is accessible. */
2846 inst
= (sljit_u8
*)ensure_buf(compiler
, 1 + 3 + 3);
2849 /* Set low byte to conditional flag. */
2852 *inst
++ = MOD_REG
| reg_map
[dst
];
2855 *inst
++ = MOVZX_r_rm8
;
2856 *inst
= MOD_REG
| (reg_map
[dst
] << 3) | reg_map
[dst
];
2857 return SLJIT_SUCCESS
;
2860 /* Low byte is not accessible. */
2861 if (cpu_has_cmov
== -1)
2865 EMIT_MOV(compiler
, TMP_REG1
, 0, SLJIT_IMM
, 1);
2866 /* a xor reg, reg operation would overwrite the flags. */
2867 EMIT_MOV(compiler
, dst
, 0, SLJIT_IMM
, 0);
2869 inst
= (sljit_u8
*)ensure_buf(compiler
, 1 + 3);
2874 /* cmovcc = setcc - 0x50. */
2875 *inst
++ = cond_set
- 0x50;
2876 *inst
++ = MOD_REG
| (reg_map
[dst
] << 3) | reg_map
[TMP_REG1
];
2877 return SLJIT_SUCCESS
;
2880 inst
= (sljit_u8
*)ensure_buf(compiler
, 1 + 1 + 3 + 3 + 1);
2882 INC_SIZE(1 + 3 + 3 + 1);
2883 *inst
++ = XCHG_EAX_r
+ reg_map
[TMP_REG1
];
2884 /* Set al to conditional flag. */
2887 *inst
++ = MOD_REG
| 0 /* eax */;
2890 *inst
++ = MOVZX_r_rm8
;
2891 *inst
++ = MOD_REG
| (reg_map
[dst
] << 3) | 0 /* eax */;
2892 *inst
++ = XCHG_EAX_r
+ reg_map
[TMP_REG1
];
2893 return SLJIT_SUCCESS
;
2896 if (GET_OPCODE(op
) == SLJIT_OR
&& !GET_ALL_FLAGS(op
) && FAST_IS_REG(dst
) && reg_map
[dst
] <= 4) {
2897 SLJIT_ASSERT(reg_map
[SLJIT_R0
] == 0);
2899 if (dst
!= SLJIT_R0
) {
2900 inst
= (sljit_u8
*)ensure_buf(compiler
, 1 + 1 + 3 + 2 + 1);
2902 INC_SIZE(1 + 3 + 2 + 1);
2903 /* Set low register to conditional flag. */
2904 *inst
++ = XCHG_EAX_r
+ reg_map
[TMP_REG1
];
2907 *inst
++ = MOD_REG
| 0 /* eax */;
2908 *inst
++ = OR_rm8_r8
;
2909 *inst
++ = MOD_REG
| (0 /* eax */ << 3) | reg_map
[dst
];
2910 *inst
++ = XCHG_EAX_r
+ reg_map
[TMP_REG1
];
2913 inst
= (sljit_u8
*)ensure_buf(compiler
, 1 + 2 + 3 + 2 + 2);
2915 INC_SIZE(2 + 3 + 2 + 2);
2916 /* Set low register to conditional flag. */
2917 *inst
++ = XCHG_r_rm
;
2918 *inst
++ = MOD_REG
| (1 /* ecx */ << 3) | reg_map
[TMP_REG1
];
2921 *inst
++ = MOD_REG
| 1 /* ecx */;
2922 *inst
++ = OR_rm8_r8
;
2923 *inst
++ = MOD_REG
| (1 /* ecx */ << 3) | 0 /* eax */;
2924 *inst
++ = XCHG_r_rm
;
2925 *inst
++ = MOD_REG
| (1 /* ecx */ << 3) | reg_map
[TMP_REG1
];
2927 return SLJIT_SUCCESS
;
2930 /* Set TMP_REG1 to the bit. */
2931 inst
= (sljit_u8
*)ensure_buf(compiler
, 1 + 1 + 3 + 3 + 1);
2933 INC_SIZE(1 + 3 + 3 + 1);
2934 *inst
++ = XCHG_EAX_r
+ reg_map
[TMP_REG1
];
2935 /* Set al to conditional flag. */
2938 *inst
++ = MOD_REG
| 0 /* eax */;
2941 *inst
++ = MOVZX_r_rm8
;
2942 *inst
++ = MOD_REG
| (0 << 3) /* eax */ | 0 /* eax */;
2944 *inst
++ = XCHG_EAX_r
+ reg_map
[TMP_REG1
];
2946 if (GET_OPCODE(op
) < SLJIT_ADD
)
2947 return emit_mov(compiler
, dst
, dstw
, TMP_REG1
, 0);
2949 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
2950 || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
2951 compiler
->skip_checks
= 1;
2953 return sljit_emit_op2(compiler
, op
, dst_save
, dstw_save
, dst_save
, dstw_save
, TMP_REG1
, 0);
2954 #endif /* SLJIT_CONFIG_X86_64 */
2957 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_cmov(struct sljit_compiler
*compiler
, sljit_s32 type
,
2959 sljit_s32 src
, sljit_sw srcw
)
2964 CHECK(check_sljit_emit_cmov(compiler
, type
, dst_reg
, src
, srcw
));
2966 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
2967 dst_reg
&= ~SLJIT_I32_OP
;
2969 if (!sljit_has_cpu_feature(SLJIT_HAS_CMOV
) || (dst_reg
>= SLJIT_R3
&& dst_reg
<= SLJIT_S3
))
2970 return sljit_emit_cmov_generic(compiler
, type
, dst_reg
, src
, srcw
);
2972 if (!sljit_has_cpu_feature(SLJIT_HAS_CMOV
))
2973 return sljit_emit_cmov_generic(compiler
, type
, dst_reg
, src
, srcw
);
2976 /* ADJUST_LOCAL_OFFSET is not needed. */
2977 CHECK_EXTRA_REGS(src
, srcw
, (void)0);
2979 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
2980 compiler
->mode32
= dst_reg
& SLJIT_I32_OP
;
2981 dst_reg
&= ~SLJIT_I32_OP
;
2984 if (SLJIT_UNLIKELY(src
& SLJIT_IMM
)) {
2985 EMIT_MOV(compiler
, TMP_REG1
, 0, SLJIT_IMM
, srcw
);
2990 inst
= emit_x86_instruction(compiler
, 2, dst_reg
, 0, src
, srcw
);
2993 *inst
= get_jump_code(type
& 0xff) - 0x40;
2994 return SLJIT_SUCCESS
;
2997 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_get_local_base(struct sljit_compiler
*compiler
, sljit_s32 dst
, sljit_sw dstw
, sljit_sw offset
)
3000 CHECK(check_sljit_get_local_base(compiler
, dst
, dstw
, offset
));
3001 ADJUST_LOCAL_OFFSET(dst
, dstw
);
3003 CHECK_EXTRA_REGS(dst
, dstw
, (void)0);
3005 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
3006 compiler
->mode32
= 0;
3009 ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_SP
), offset
);
3011 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
3012 if (NOT_HALFWORD(offset
)) {
3013 FAIL_IF(emit_load_imm64(compiler
, TMP_REG1
, offset
));
3014 #if (defined SLJIT_DEBUG && SLJIT_DEBUG)
3015 SLJIT_ASSERT(emit_lea_binary(compiler
, dst
, dstw
, SLJIT_SP
, 0, TMP_REG1
, 0) != SLJIT_ERR_UNSUPPORTED
);
3016 return compiler
->error
;
3018 return emit_lea_binary(compiler
, dst
, dstw
, SLJIT_SP
, 0, TMP_REG1
, 0);
3024 return emit_lea_binary(compiler
, dst
, dstw
, SLJIT_SP
, 0, SLJIT_IMM
, offset
);
3025 return emit_mov(compiler
, dst
, dstw
, SLJIT_SP
, 0);
3028 SLJIT_API_FUNC_ATTRIBUTE
struct sljit_const
* sljit_emit_const(struct sljit_compiler
*compiler
, sljit_s32 dst
, sljit_sw dstw
, sljit_sw init_value
)
3031 struct sljit_const
*const_
;
3032 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
3037 CHECK_PTR(check_sljit_emit_const(compiler
, dst
, dstw
, init_value
));
3038 ADJUST_LOCAL_OFFSET(dst
, dstw
);
3040 CHECK_EXTRA_REGS(dst
, dstw
, (void)0);
3042 const_
= (struct sljit_const
*)ensure_abuf(compiler
, sizeof(struct sljit_const
));
3043 PTR_FAIL_IF(!const_
);
3044 set_const(const_
, compiler
);
3046 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
3047 compiler
->mode32
= 0;
3048 reg
= FAST_IS_REG(dst
) ? dst
: TMP_REG1
;
3050 if (emit_load_imm64(compiler
, reg
, init_value
))
3053 if (emit_mov(compiler
, dst
, dstw
, SLJIT_IMM
, init_value
))
3057 inst
= (sljit_u8
*)ensure_buf(compiler
, 2);
3063 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
3064 if (dst
& SLJIT_MEM
)
3065 if (emit_mov(compiler
, dst
, dstw
, TMP_REG1
, 0))
3072 SLJIT_API_FUNC_ATTRIBUTE
struct sljit_put_label
* sljit_emit_put_label(struct sljit_compiler
*compiler
, sljit_s32 dst
, sljit_sw dstw
)
3074 struct sljit_put_label
*put_label
;
3076 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
3078 sljit_uw start_size
;
3082 CHECK_PTR(check_sljit_emit_put_label(compiler
, dst
, dstw
));
3083 ADJUST_LOCAL_OFFSET(dst
, dstw
);
3085 CHECK_EXTRA_REGS(dst
, dstw
, (void)0);
3087 put_label
= (struct sljit_put_label
*)ensure_abuf(compiler
, sizeof(struct sljit_put_label
));
3088 PTR_FAIL_IF(!put_label
);
3089 set_put_label(put_label
, compiler
, 0);
3091 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
3092 compiler
->mode32
= 0;
3093 reg
= FAST_IS_REG(dst
) ? dst
: TMP_REG1
;
3095 if (emit_load_imm64(compiler
, reg
, 0))
3098 if (emit_mov(compiler
, dst
, dstw
, SLJIT_IMM
, 0))
3102 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
3103 if (dst
& SLJIT_MEM
) {
3104 start_size
= compiler
->size
;
3105 if (emit_mov(compiler
, dst
, dstw
, TMP_REG1
, 0))
3107 put_label
->flags
= compiler
->size
- start_size
;
3111 inst
= (sljit_u8
*)ensure_buf(compiler
, 2);
3120 SLJIT_API_FUNC_ATTRIBUTE
void sljit_set_jump_addr(sljit_uw addr
, sljit_uw new_target
, sljit_sw executable_offset
)
3122 SLJIT_UNUSED_ARG(executable_offset
);
3124 SLJIT_UPDATE_WX_FLAGS((void*)addr
, (void*)(addr
+ sizeof(sljit_uw
)), 0);
3125 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
3126 sljit_unaligned_store_sw((void*)addr
, new_target
- (addr
+ 4) - (sljit_uw
)executable_offset
);
3128 sljit_unaligned_store_sw((void*)addr
, (sljit_sw
) new_target
);
3130 SLJIT_UPDATE_WX_FLAGS((void*)addr
, (void*)(addr
+ sizeof(sljit_uw
)), 1);
3133 SLJIT_API_FUNC_ATTRIBUTE
void sljit_set_const(sljit_uw addr
, sljit_sw new_constant
, sljit_sw executable_offset
)
3135 SLJIT_UNUSED_ARG(executable_offset
);
3137 SLJIT_UPDATE_WX_FLAGS((void*)addr
, (void*)(addr
+ sizeof(sljit_sw
)), 0);
3138 sljit_unaligned_store_sw((void*)addr
, new_constant
);
3139 SLJIT_UPDATE_WX_FLAGS((void*)addr
, (void*)(addr
+ sizeof(sljit_sw
)), 1);