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 "x86" SLJIT_CPUINFO
;
54 8 - R8 - From now on REX prefix is required
64 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
66 /* Last register + 1. */
67 #define TMP_REGISTER (SLJIT_NO_REGISTERS + 1)
69 static SLJIT_CONST sljit_ub reg_map
[SLJIT_NO_REGISTERS
+ 2] = {
70 0, 0, 2, 1, 0, 0, 3, 6, 7, 0, 0, 4, 5
73 #define CHECK_EXTRA_REGS(p, w, do) \
74 if (p >= SLJIT_TEMPORARY_EREG1 && p <= SLJIT_TEMPORARY_EREG2) { \
75 w = compiler->temporaries_start + (p - SLJIT_TEMPORARY_EREG1) * sizeof(sljit_sw); \
76 p = SLJIT_MEM1(SLJIT_LOCALS_REG); \
79 else if (p >= SLJIT_SAVED_EREG1 && p <= SLJIT_SAVED_EREG2) { \
80 w = compiler->saveds_start + (p - SLJIT_SAVED_EREG1) * sizeof(sljit_sw); \
81 p = SLJIT_MEM1(SLJIT_LOCALS_REG); \
85 #else /* SLJIT_CONFIG_X86_32 */
87 /* Last register + 1. */
88 #define TMP_REGISTER (SLJIT_NO_REGISTERS + 1)
89 #define TMP_REG2 (SLJIT_NO_REGISTERS + 2)
90 #define TMP_REG3 (SLJIT_NO_REGISTERS + 3)
92 /* Note: r12 & 0x7 == 0b100, which decoded as SIB byte present
93 Note: avoid to use r12 and r13 for memory addessing
94 therefore r12 is better for SAVED_EREG than SAVED_REG. */
96 /* 1st passed in rdi, 2nd argument passed in rsi, 3rd in rdx. */
97 static SLJIT_CONST sljit_ub reg_map
[SLJIT_NO_REGISTERS
+ 4] = {
98 0, 0, 6, 1, 8, 11, 3, 15, 14, 13, 12, 4, 2, 7, 9
100 /* low-map. reg_map & 0x7. */
101 static SLJIT_CONST sljit_ub reg_lmap
[SLJIT_NO_REGISTERS
+ 4] = {
102 0, 0, 6, 1, 0, 3, 3, 7, 6, 5, 4, 4, 2, 7, 1
105 /* 1st passed in rcx, 2nd argument passed in rdx, 3rd in r8. */
106 static SLJIT_CONST sljit_ub reg_map
[SLJIT_NO_REGISTERS
+ 4] = {
107 0, 0, 2, 1, 11, 13, 3, 6, 7, 14, 15, 4, 10, 8, 9
109 /* low-map. reg_map & 0x7. */
110 static SLJIT_CONST sljit_ub reg_lmap
[SLJIT_NO_REGISTERS
+ 4] = {
111 0, 0, 2, 1, 3, 5, 3, 6, 7, 6, 7, 4, 2, 0, 1
121 #define IS_HALFWORD(x) ((x) <= 0x7fffffffll && (x) >= -0x80000000ll)
122 #define NOT_HALFWORD(x) ((x) > 0x7fffffffll || (x) < -0x80000000ll)
124 #define CHECK_EXTRA_REGS(p, w, do)
126 #endif /* SLJIT_CONFIG_X86_32 */
128 #if (defined SLJIT_SSE2 && SLJIT_SSE2)
132 /* Size flags for emit_x86_instruction: */
133 #define EX86_BIN_INS 0x0010
134 #define EX86_SHIFT_INS 0x0020
135 #define EX86_REX 0x0040
136 #define EX86_NO_REXW 0x0080
137 #define EX86_BYTE_ARG 0x0100
138 #define EX86_HALF_ARG 0x0200
139 #define EX86_PREF_66 0x0400
141 #if (defined SLJIT_SSE2 && SLJIT_SSE2)
142 #define EX86_SSE2 0x0800
143 #define EX86_PREF_F2 0x1000
144 #define EX86_PREF_F3 0x2000
147 /* --------------------------------------------------------------------- */
148 /* Instrucion forms */
149 /* --------------------------------------------------------------------- */
151 #define ADD (/* BINARY */ 0 << 3)
152 #define ADD_EAX_i32 0x05
153 #define ADD_r_rm 0x03
154 #define ADD_rm_r 0x01
155 #define ADDSD_x_xm 0x58
156 #define ADC (/* BINARY */ 2 << 3)
157 #define ADC_EAX_i32 0x15
158 #define ADC_r_rm 0x13
159 #define ADC_rm_r 0x11
160 #define AND (/* BINARY */ 4 << 3)
161 #define AND_EAX_i32 0x25
162 #define AND_r_rm 0x23
163 #define AND_rm_r 0x21
164 #define ANDPD_x_xm 0x54
165 #define BSR_r_rm (/* GROUP_0F */ 0xbd)
166 #define CALL_i32 0xe8
167 #define CALL_rm (/* GROUP_FF */ 2 << 3)
169 #define CMOVNE_r_rm (/* GROUP_0F */ 0x45)
170 #define CMP (/* BINARY */ 7 << 3)
171 #define CMP_EAX_i32 0x3d
172 #define CMP_r_rm 0x3b
173 #define CMP_rm_r 0x39
174 #define DIV (/* GROUP_F7 */ 6 << 3)
175 #define DIVSD_x_xm 0x5e
177 #define IDIV (/* GROUP_F7 */ 7 << 3)
178 #define IMUL (/* GROUP_F7 */ 5 << 3)
179 #define IMUL_r_rm (/* GROUP_0F */ 0xaf)
180 #define IMUL_r_rm_i8 0x6b
181 #define IMUL_r_rm_i32 0x69
184 #define JMP_rm (/* GROUP_FF */ 4 << 3)
186 #define MOV_r_rm 0x8b
187 #define MOV_r_i32 0xb8
188 #define MOV_rm_r 0x89
189 #define MOV_rm_i32 0xc7
190 #define MOV_rm8_i8 0xc6
191 #define MOV_rm8_r8 0x88
192 #define MOVSD_x_xm 0x10
193 #define MOVSD_xm_x 0x11
194 #define MOVSXD_r_rm 0x63
195 #define MOVSX_r_rm8 (/* GROUP_0F */ 0xbe)
196 #define MOVSX_r_rm16 (/* GROUP_0F */ 0xbf)
197 #define MOVZX_r_rm8 (/* GROUP_0F */ 0xb6)
198 #define MOVZX_r_rm16 (/* GROUP_0F */ 0xb7)
199 #define MUL (/* GROUP_F7 */ 4 << 3)
200 #define MULSD_x_xm 0x59
201 #define NEG_rm (/* GROUP_F7 */ 3 << 3)
203 #define NOT_rm (/* GROUP_F7 */ 2 << 3)
204 #define OR (/* BINARY */ 1 << 3)
206 #define OR_EAX_i32 0x0d
211 #define PUSH_i32 0x68
213 #define PUSH_rm (/* GROUP_FF */ 6 << 3)
215 #define RET_near 0xc3
217 #define SBB (/* BINARY */ 3 << 3)
218 #define SBB_EAX_i32 0x1d
219 #define SBB_r_rm 0x1b
220 #define SBB_rm_r 0x19
221 #define SAR (/* SHIFT */ 7 << 3)
222 #define SHL (/* SHIFT */ 4 << 3)
223 #define SHR (/* SHIFT */ 5 << 3)
224 #define SUB (/* BINARY */ 5 << 3)
225 #define SUB_EAX_i32 0x2d
226 #define SUB_r_rm 0x2b
227 #define SUB_rm_r 0x29
228 #define SUBSD_x_xm 0x5c
229 #define TEST_EAX_i32 0xa9
230 #define TEST_rm_r 0x85
231 #define UCOMISD_x_xm 0x2e
232 #define XCHG_EAX_r 0x90
233 #define XCHG_r_rm 0x87
234 #define XOR (/* BINARY */ 6 << 3)
235 #define XOR_EAX_i32 0x35
236 #define XOR_r_rm 0x33
237 #define XOR_rm_r 0x31
238 #define XORPD_x_xm 0x57
240 #define GROUP_0F 0x0f
241 #define GROUP_F7 0xf7
242 #define GROUP_FF 0xff
243 #define GROUP_BIN_81 0x81
244 #define GROUP_BIN_83 0x83
248 #define INC_SIZE(s) (*buf++ = (s), compiler->size += (s))
249 #define INC_CSIZE(s) (*code++ = (s), compiler->size += (s))
251 #define PUSH_REG(r) (*buf++ = (PUSH_r + (r)))
252 #define POP_REG(r) (*buf++ = (POP_r + (r)))
253 #define RET() (*buf++ = (RET_near))
254 #define RET_I16(n) (*buf++ = (RET_i16), *buf++ = n, *buf++ = 0)
256 #define MOV_RM(mod, reg, rm) (*buf++ = (MOV_r_rm), *buf++ = (mod) << 6 | (reg) << 3 | (rm))
258 static sljit_ub
get_jump_code(sljit_si type
)
262 case SLJIT_C_FLOAT_EQUAL
:
263 return 0x84 /* je */;
265 case SLJIT_C_NOT_EQUAL
:
266 case SLJIT_C_FLOAT_NOT_EQUAL
:
267 return 0x85 /* jne */;
270 case SLJIT_C_FLOAT_LESS
:
271 return 0x82 /* jc */;
273 case SLJIT_C_GREATER_EQUAL
:
274 case SLJIT_C_FLOAT_GREATER_EQUAL
:
275 return 0x83 /* jae */;
277 case SLJIT_C_GREATER
:
278 case SLJIT_C_FLOAT_GREATER
:
279 return 0x87 /* jnbe */;
281 case SLJIT_C_LESS_EQUAL
:
282 case SLJIT_C_FLOAT_LESS_EQUAL
:
283 return 0x86 /* jbe */;
285 case SLJIT_C_SIG_LESS
:
286 return 0x8c /* jl */;
288 case SLJIT_C_SIG_GREATER_EQUAL
:
289 return 0x8d /* jnl */;
291 case SLJIT_C_SIG_GREATER
:
292 return 0x8f /* jnle */;
294 case SLJIT_C_SIG_LESS_EQUAL
:
295 return 0x8e /* jle */;
297 case SLJIT_C_OVERFLOW
:
298 case SLJIT_C_MUL_OVERFLOW
:
299 return 0x80 /* jo */;
301 case SLJIT_C_NOT_OVERFLOW
:
302 case SLJIT_C_MUL_NOT_OVERFLOW
:
303 return 0x81 /* jno */;
305 case SLJIT_C_FLOAT_UNORDERED
:
306 return 0x8a /* jp */;
308 case SLJIT_C_FLOAT_ORDERED
:
309 return 0x8b /* jpo */;
314 static sljit_ub
* generate_far_jump_code(struct sljit_jump
*jump
, sljit_ub
*code_ptr
, sljit_si type
);
316 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
317 static sljit_ub
* generate_fixed_jump(sljit_ub
*code_ptr
, sljit_sw addr
, sljit_si type
);
320 static sljit_ub
* generate_near_jump_code(struct sljit_jump
*jump
, sljit_ub
*code_ptr
, sljit_ub
*code
, sljit_si type
)
325 if (jump
->flags
& JUMP_LABEL
)
326 label_addr
= (sljit_uw
)(code
+ jump
->u
.label
->size
);
328 label_addr
= jump
->u
.target
;
329 short_jump
= (sljit_sw
)(label_addr
- (jump
->addr
+ 2)) >= -128 && (sljit_sw
)(label_addr
- (jump
->addr
+ 2)) <= 127;
331 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
332 if ((sljit_sw
)(label_addr
- (jump
->addr
+ 1)) > 0x7fffffffll
|| (sljit_sw
)(label_addr
- (jump
->addr
+ 1)) < -0x80000000ll
)
333 return generate_far_jump_code(jump
, code_ptr
, type
);
336 if (type
== SLJIT_JUMP
) {
338 *code_ptr
++ = JMP_i8
;
340 *code_ptr
++ = JMP_i32
;
343 else if (type
>= SLJIT_FAST_CALL
) {
345 *code_ptr
++ = CALL_i32
;
348 else if (short_jump
) {
349 *code_ptr
++ = get_jump_code(type
) - 0x10;
353 *code_ptr
++ = GROUP_0F
;
354 *code_ptr
++ = get_jump_code(type
);
359 jump
->flags
|= PATCH_MB
;
360 code_ptr
+= sizeof(sljit_sb
);
362 jump
->flags
|= PATCH_MW
;
363 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
364 code_ptr
+= sizeof(sljit_sw
);
366 code_ptr
+= sizeof(sljit_si
);
373 SLJIT_API_FUNC_ATTRIBUTE
void* sljit_generate_code(struct sljit_compiler
*compiler
)
375 struct sljit_memory_fragment
*buf
;
382 struct sljit_label
*label
;
383 struct sljit_jump
*jump
;
384 struct sljit_const
*const_
;
387 check_sljit_generate_code(compiler
);
388 reverse_buf(compiler
);
390 /* Second code generation pass. */
391 code
= (sljit_ub
*)SLJIT_MALLOC_EXEC(compiler
->size
);
392 PTR_FAIL_WITH_EXEC_IF(code
);
396 label
= compiler
->labels
;
397 jump
= compiler
->jumps
;
398 const_
= compiler
->consts
;
400 buf_ptr
= buf
->memory
;
401 buf_end
= buf_ptr
+ buf
->used_size
;
405 /* The code is already generated. */
406 SLJIT_MEMMOVE(code_ptr
, buf_ptr
, len
);
412 jump
->addr
= (sljit_uw
)code_ptr
;
413 if (!(jump
->flags
& SLJIT_REWRITABLE_JUMP
))
414 code_ptr
= generate_near_jump_code(jump
, code_ptr
, code
, *buf_ptr
- 4);
416 code_ptr
= generate_far_jump_code(jump
, code_ptr
, *buf_ptr
- 4);
419 else if (*buf_ptr
== 0) {
420 label
->addr
= (sljit_uw
)code_ptr
;
421 label
->size
= code_ptr
- code
;
424 else if (*buf_ptr
== 1) {
425 const_
->addr
= ((sljit_uw
)code_ptr
) - sizeof(sljit_sw
);
426 const_
= const_
->next
;
429 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
430 *code_ptr
++ = (*buf_ptr
== 2) ? CALL_i32
: JMP_i32
;
432 *(sljit_sw
*)code_ptr
= *(sljit_sw
*)buf_ptr
- ((sljit_sw
)code_ptr
+ sizeof(sljit_sw
));
433 code_ptr
+= sizeof(sljit_sw
);
434 buf_ptr
+= sizeof(sljit_sw
) - 1;
436 code_ptr
= generate_fixed_jump(code_ptr
, *(sljit_sw
*)(buf_ptr
+ 1), *buf_ptr
);
437 buf_ptr
+= sizeof(sljit_sw
);
442 } while (buf_ptr
< buf_end
);
443 SLJIT_ASSERT(buf_ptr
== buf_end
);
447 SLJIT_ASSERT(!label
);
449 SLJIT_ASSERT(!const_
);
451 jump
= compiler
->jumps
;
453 if (jump
->flags
& PATCH_MB
) {
454 SLJIT_ASSERT((sljit_sw
)(jump
->u
.label
->addr
- (jump
->addr
+ sizeof(sljit_sb
))) >= -128 && (sljit_sw
)(jump
->u
.label
->addr
- (jump
->addr
+ sizeof(sljit_sb
))) <= 127);
455 *(sljit_ub
*)jump
->addr
= (sljit_ub
)(jump
->u
.label
->addr
- (jump
->addr
+ sizeof(sljit_sb
)));
456 } else if (jump
->flags
& PATCH_MW
) {
457 if (jump
->flags
& JUMP_LABEL
) {
458 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
459 *(sljit_sw
*)jump
->addr
= (sljit_sw
)(jump
->u
.label
->addr
- (jump
->addr
+ sizeof(sljit_sw
)));
461 SLJIT_ASSERT((sljit_sw
)(jump
->u
.label
->addr
- (jump
->addr
+ sizeof(sljit_si
))) >= -0x80000000ll
&& (sljit_sw
)(jump
->u
.label
->addr
- (jump
->addr
+ sizeof(sljit_si
))) <= 0x7fffffffll
);
462 *(sljit_si
*)jump
->addr
= (sljit_si
)(jump
->u
.label
->addr
- (jump
->addr
+ sizeof(sljit_si
)));
466 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
467 *(sljit_sw
*)jump
->addr
= (sljit_sw
)(jump
->u
.target
- (jump
->addr
+ sizeof(sljit_sw
)));
469 SLJIT_ASSERT((sljit_sw
)(jump
->u
.target
- (jump
->addr
+ sizeof(sljit_si
))) >= -0x80000000ll
&& (sljit_sw
)(jump
->u
.target
- (jump
->addr
+ sizeof(sljit_si
))) <= 0x7fffffffll
);
470 *(sljit_si
*)jump
->addr
= (sljit_si
)(jump
->u
.target
- (jump
->addr
+ sizeof(sljit_si
)));
474 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
475 else if (jump
->flags
& PATCH_MD
)
476 *(sljit_sw
*)jump
->addr
= jump
->u
.label
->addr
;
482 /* Maybe we waste some space because of short jumps. */
483 SLJIT_ASSERT(code_ptr
<= code
+ compiler
->size
);
484 compiler
->error
= SLJIT_ERR_COMPILED
;
485 compiler
->executable_size
= compiler
->size
;
489 /* --------------------------------------------------------------------- */
491 /* --------------------------------------------------------------------- */
493 static sljit_si
emit_cum_binary(struct sljit_compiler
*compiler
,
494 sljit_ub op_rm
, sljit_ub op_mr
, sljit_ub op_imm
, sljit_ub op_eax_imm
,
495 sljit_si dst
, sljit_sw dstw
,
496 sljit_si src1
, sljit_sw src1w
,
497 sljit_si src2
, sljit_sw src2w
);
499 static sljit_si
emit_non_cum_binary(struct sljit_compiler
*compiler
,
500 sljit_ub op_rm
, sljit_ub op_mr
, sljit_ub op_imm
, sljit_ub op_eax_imm
,
501 sljit_si dst
, sljit_sw dstw
,
502 sljit_si src1
, sljit_sw src1w
,
503 sljit_si src2
, sljit_sw src2w
);
505 static sljit_si
emit_mov(struct sljit_compiler
*compiler
,
506 sljit_si dst
, sljit_sw dstw
,
507 sljit_si src
, sljit_sw srcw
);
509 static SLJIT_INLINE sljit_si
emit_save_flags(struct sljit_compiler
*compiler
)
513 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
514 buf
= (sljit_ub
*)ensure_buf(compiler
, 1 + 5);
518 buf
= (sljit_ub
*)ensure_buf(compiler
, 1 + 6);
523 *buf
++ = LEA_r_m
; /* lea esp/rsp, [esp/rsp + sizeof(sljit_sw)] */
526 *buf
++ = (sljit_ub
)sizeof(sljit_sw
);
528 compiler
->flags_saved
= 1;
529 return SLJIT_SUCCESS
;
532 static SLJIT_INLINE sljit_si
emit_restore_flags(struct sljit_compiler
*compiler
, sljit_si keep_flags
)
536 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
537 buf
= (sljit_ub
*)ensure_buf(compiler
, 1 + 5);
542 buf
= (sljit_ub
*)ensure_buf(compiler
, 1 + 6);
548 *buf
++ = LEA_r_m
; /* lea esp/rsp, [esp/rsp - sizeof(sljit_sw)] */
551 *buf
++ = (sljit_ub
)-(sljit_sb
)sizeof(sljit_sw
);
552 compiler
->flags_saved
= keep_flags
;
553 return SLJIT_SUCCESS
;
559 static void SLJIT_CALL
sljit_grow_stack(sljit_sw local_size
)
561 /* Workaround for calling the internal _chkstk() function on Windows.
562 This function touches all 4k pages belongs to the requested stack space,
563 which size is passed in local_size. This is necessary on Windows where
564 the stack can only grow in 4k steps. However, this function just burn
565 CPU cycles if the stack is large enough, but you don't know it in advance.
566 I think this is a bad design even if it has some reasons. */
572 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
573 #include "sljitNativeX86_32.c"
575 #include "sljitNativeX86_64.c"
578 static sljit_si
emit_mov(struct sljit_compiler
*compiler
,
579 sljit_si dst
, sljit_sw dstw
,
580 sljit_si src
, sljit_sw srcw
)
584 if (dst
== SLJIT_UNUSED
) {
585 /* No destination, doesn't need to setup flags. */
586 if (src
& SLJIT_MEM
) {
587 code
= emit_x86_instruction(compiler
, 1, TMP_REGISTER
, 0, src
, srcw
);
591 return SLJIT_SUCCESS
;
593 if (src
>= SLJIT_TEMPORARY_REG1
&& src
<= TMP_REGISTER
) {
594 code
= emit_x86_instruction(compiler
, 1, src
, 0, dst
, dstw
);
597 return SLJIT_SUCCESS
;
599 if (src
& SLJIT_IMM
) {
600 if (dst
>= SLJIT_TEMPORARY_REG1
&& dst
<= TMP_REGISTER
) {
601 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
602 return emit_do_imm(compiler
, MOV_r_i32
+ reg_map
[dst
], srcw
);
604 if (!compiler
->mode32
) {
605 if (NOT_HALFWORD(srcw
))
606 return emit_load_imm64(compiler
, dst
, srcw
);
609 return emit_do_imm32(compiler
, (reg_map
[dst
] >= 8) ? REX_B
: 0, MOV_r_i32
+ reg_lmap
[dst
], srcw
);
612 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
613 if (!compiler
->mode32
&& NOT_HALFWORD(srcw
)) {
614 FAIL_IF(emit_load_imm64(compiler
, TMP_REG2
, srcw
));
615 code
= emit_x86_instruction(compiler
, 1, TMP_REG2
, 0, dst
, dstw
);
618 return SLJIT_SUCCESS
;
621 code
= emit_x86_instruction(compiler
, 1, SLJIT_IMM
, srcw
, dst
, dstw
);
624 return SLJIT_SUCCESS
;
626 if (dst
>= SLJIT_TEMPORARY_REG1
&& dst
<= TMP_REGISTER
) {
627 code
= emit_x86_instruction(compiler
, 1, dst
, 0, src
, srcw
);
630 return SLJIT_SUCCESS
;
633 /* Memory to memory move. Requires two instruction. */
634 code
= emit_x86_instruction(compiler
, 1, TMP_REGISTER
, 0, src
, srcw
);
637 code
= emit_x86_instruction(compiler
, 1, TMP_REGISTER
, 0, dst
, dstw
);
640 return SLJIT_SUCCESS
;
643 #define EMIT_MOV(compiler, dst, dstw, src, srcw) \
644 FAIL_IF(emit_mov(compiler, dst, dstw, src, srcw));
646 SLJIT_API_FUNC_ATTRIBUTE sljit_si
sljit_emit_op0(struct sljit_compiler
*compiler
, sljit_si op
)
649 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
654 check_sljit_emit_op0(compiler
, op
);
656 switch (GET_OPCODE(op
)) {
657 case SLJIT_BREAKPOINT
:
658 buf
= (sljit_ub
*)ensure_buf(compiler
, 1 + 1);
664 buf
= (sljit_ub
*)ensure_buf(compiler
, 1 + 1);
673 compiler
->flags_saved
= 0;
674 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
676 SLJIT_COMPILE_ASSERT(
677 reg_map
[SLJIT_TEMPORARY_REG1
] == 0
678 && reg_map
[SLJIT_TEMPORARY_REG2
] == 2
679 && reg_map
[TMP_REGISTER
] > 7,
680 invalid_register_assignment_for_div_mul
);
682 SLJIT_COMPILE_ASSERT(
683 reg_map
[SLJIT_TEMPORARY_REG1
] == 0
684 && reg_map
[SLJIT_TEMPORARY_REG2
] < 7
685 && reg_map
[TMP_REGISTER
] == 2,
686 invalid_register_assignment_for_div_mul
);
688 compiler
->mode32
= op
& SLJIT_INT_OP
;
692 if (op
== SLJIT_UDIV
) {
693 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64)
694 EMIT_MOV(compiler
, TMP_REGISTER
, 0, SLJIT_TEMPORARY_REG2
, 0);
695 buf
= emit_x86_instruction(compiler
, 1, SLJIT_TEMPORARY_REG2
, 0, SLJIT_TEMPORARY_REG2
, 0);
697 buf
= emit_x86_instruction(compiler
, 1, TMP_REGISTER
, 0, TMP_REGISTER
, 0);
703 if (op
== SLJIT_SDIV
) {
704 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64)
705 EMIT_MOV(compiler
, TMP_REGISTER
, 0, SLJIT_TEMPORARY_REG2
, 0);
708 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
709 buf
= (sljit_ub
*)ensure_buf(compiler
, 1 + 1);
714 if (compiler
->mode32
) {
715 buf
= (sljit_ub
*)ensure_buf(compiler
, 1 + 1);
720 buf
= (sljit_ub
*)ensure_buf(compiler
, 1 + 2);
729 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
730 buf
= (sljit_ub
*)ensure_buf(compiler
, 1 + 2);
734 *buf
= MOD_REG
| ((op
>= SLJIT_UDIV
) ? reg_map
[TMP_REGISTER
] : reg_map
[SLJIT_TEMPORARY_REG2
]);
737 size
= (!compiler
->mode32
|| op
>= SLJIT_UDIV
) ? 3 : 2;
739 size
= (!compiler
->mode32
) ? 3 : 2;
741 buf
= (sljit_ub
*)ensure_buf(compiler
, 1 + size
);
745 if (!compiler
->mode32
)
746 *buf
++ = REX_W
| ((op
>= SLJIT_UDIV
) ? REX_B
: 0);
747 else if (op
>= SLJIT_UDIV
)
750 *buf
= MOD_REG
| ((op
>= SLJIT_UDIV
) ? reg_lmap
[TMP_REGISTER
] : reg_lmap
[SLJIT_TEMPORARY_REG2
]);
752 if (!compiler
->mode32
)
755 *buf
= MOD_REG
| reg_map
[SLJIT_TEMPORARY_REG2
];
772 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && !defined(_WIN64)
773 EMIT_MOV(compiler
, SLJIT_TEMPORARY_REG2
, 0, TMP_REGISTER
, 0);
778 return SLJIT_SUCCESS
;
781 #define ENCODE_PREFIX(prefix) \
783 code = (sljit_ub*)ensure_buf(compiler, 1 + 1); \
789 static sljit_si
emit_mov_byte(struct sljit_compiler
*compiler
, sljit_si sign
,
790 sljit_si dst
, sljit_sw dstw
,
791 sljit_si src
, sljit_sw srcw
)
795 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
799 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
800 compiler
->mode32
= 0;
803 if (dst
== SLJIT_UNUSED
&& !(src
& SLJIT_MEM
))
804 return SLJIT_SUCCESS
; /* Empty instruction. */
806 if (src
& SLJIT_IMM
) {
807 if (dst
>= SLJIT_TEMPORARY_REG1
&& dst
<= TMP_REGISTER
) {
808 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
809 return emit_do_imm(compiler
, MOV_r_i32
+ reg_map
[dst
], srcw
);
811 return emit_load_imm64(compiler
, dst
, srcw
);
814 code
= emit_x86_instruction(compiler
, 1 | EX86_BYTE_ARG
| EX86_NO_REXW
, SLJIT_IMM
, srcw
, dst
, dstw
);
817 return SLJIT_SUCCESS
;
820 dst_r
= (dst
>= SLJIT_TEMPORARY_REG1
&& dst
<= TMP_REGISTER
) ? dst
: TMP_REGISTER
;
822 if ((dst
& SLJIT_MEM
) && src
>= SLJIT_TEMPORARY_REG1
&& src
<= SLJIT_NO_REGISTERS
) {
823 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
824 if (reg_map
[src
] >= 4) {
825 SLJIT_ASSERT(dst_r
== TMP_REGISTER
);
826 EMIT_MOV(compiler
, TMP_REGISTER
, 0, src
, 0);
833 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
834 else if (src
>= SLJIT_TEMPORARY_REG1
&& src
<= SLJIT_NO_REGISTERS
&& reg_map
[src
] >= 4) {
835 /* src, dst are registers. */
836 SLJIT_ASSERT(dst
>= SLJIT_TEMPORARY_REG1
&& dst
<= TMP_REGISTER
);
837 if (reg_map
[dst
] < 4) {
839 EMIT_MOV(compiler
, dst
, 0, src
, 0);
840 code
= emit_x86_instruction(compiler
, 2, dst
, 0, dst
, 0);
843 *code
= sign
? MOVSX_r_rm8
: MOVZX_r_rm8
;
847 EMIT_MOV(compiler
, dst
, 0, src
, 0);
850 code
= emit_x86_instruction(compiler
, 1 | EX86_SHIFT_INS
, SLJIT_IMM
, 24, dst
, 0);
854 code
= emit_x86_instruction(compiler
, 1 | EX86_SHIFT_INS
, SLJIT_IMM
, 24, dst
, 0);
859 code
= emit_x86_instruction(compiler
, 1 | EX86_BIN_INS
, SLJIT_IMM
, 0xff, dst
, 0);
864 return SLJIT_SUCCESS
;
868 /* src can be memory addr or reg_map[src] < 4 on x86_32 architectures. */
869 code
= emit_x86_instruction(compiler
, 2, dst_r
, 0, src
, srcw
);
872 *code
= sign
? MOVSX_r_rm8
: MOVZX_r_rm8
;
875 if (dst
& SLJIT_MEM
) {
876 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
877 if (dst_r
== TMP_REGISTER
) {
878 /* Find a non-used register, whose reg_map[src] < 4. */
879 if ((dst
& 0xf) == SLJIT_TEMPORARY_REG1
) {
880 if ((dst
& 0xf0) == (SLJIT_TEMPORARY_REG2
<< 4))
881 work_r
= SLJIT_TEMPORARY_REG3
;
883 work_r
= SLJIT_TEMPORARY_REG2
;
886 if ((dst
& 0xf0) != (SLJIT_TEMPORARY_REG1
<< 4))
887 work_r
= SLJIT_TEMPORARY_REG1
;
888 else if ((dst
& 0xf) == SLJIT_TEMPORARY_REG2
)
889 work_r
= SLJIT_TEMPORARY_REG3
;
891 work_r
= SLJIT_TEMPORARY_REG2
;
894 if (work_r
== SLJIT_TEMPORARY_REG1
) {
895 ENCODE_PREFIX(XCHG_EAX_r
+ reg_map
[TMP_REGISTER
]);
898 code
= emit_x86_instruction(compiler
, 1, work_r
, 0, dst_r
, 0);
903 code
= emit_x86_instruction(compiler
, 1, work_r
, 0, dst
, dstw
);
907 if (work_r
== SLJIT_TEMPORARY_REG1
) {
908 ENCODE_PREFIX(XCHG_EAX_r
+ reg_map
[TMP_REGISTER
]);
911 code
= emit_x86_instruction(compiler
, 1, work_r
, 0, dst_r
, 0);
917 code
= emit_x86_instruction(compiler
, 1, dst_r
, 0, dst
, dstw
);
922 code
= emit_x86_instruction(compiler
, 1 | EX86_REX
| EX86_NO_REXW
, dst_r
, 0, dst
, dstw
);
928 return SLJIT_SUCCESS
;
931 static sljit_si
emit_mov_half(struct sljit_compiler
*compiler
, sljit_si sign
,
932 sljit_si dst
, sljit_sw dstw
,
933 sljit_si src
, sljit_sw srcw
)
938 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
939 compiler
->mode32
= 0;
942 if (dst
== SLJIT_UNUSED
&& !(src
& SLJIT_MEM
))
943 return SLJIT_SUCCESS
; /* Empty instruction. */
945 if (src
& SLJIT_IMM
) {
946 if (dst
>= SLJIT_TEMPORARY_REG1
&& dst
<= TMP_REGISTER
) {
947 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
948 return emit_do_imm(compiler
, MOV_r_i32
+ reg_map
[dst
], srcw
);
950 return emit_load_imm64(compiler
, dst
, srcw
);
953 code
= emit_x86_instruction(compiler
, 1 | EX86_HALF_ARG
| EX86_NO_REXW
| EX86_PREF_66
, SLJIT_IMM
, srcw
, dst
, dstw
);
956 return SLJIT_SUCCESS
;
959 dst_r
= (dst
>= SLJIT_TEMPORARY_REG1
&& dst
<= TMP_REGISTER
) ? dst
: TMP_REGISTER
;
961 if ((dst
& SLJIT_MEM
) && (src
>= SLJIT_TEMPORARY_REG1
&& src
<= SLJIT_NO_REGISTERS
))
964 code
= emit_x86_instruction(compiler
, 2, dst_r
, 0, src
, srcw
);
967 *code
= sign
? MOVSX_r_rm16
: MOVZX_r_rm16
;
970 if (dst
& SLJIT_MEM
) {
971 code
= emit_x86_instruction(compiler
, 1 | EX86_NO_REXW
| EX86_PREF_66
, dst_r
, 0, dst
, dstw
);
976 return SLJIT_SUCCESS
;
979 static sljit_si
emit_unary(struct sljit_compiler
*compiler
, sljit_ub opcode
,
980 sljit_si dst
, sljit_sw dstw
,
981 sljit_si src
, sljit_sw srcw
)
985 if (dst
== SLJIT_UNUSED
) {
986 EMIT_MOV(compiler
, TMP_REGISTER
, 0, src
, srcw
);
987 code
= emit_x86_instruction(compiler
, 1, 0, 0, TMP_REGISTER
, 0);
991 return SLJIT_SUCCESS
;
993 if (dst
== src
&& dstw
== srcw
) {
994 /* Same input and output */
995 code
= emit_x86_instruction(compiler
, 1, 0, 0, dst
, dstw
);
999 return SLJIT_SUCCESS
;
1001 if (dst
>= SLJIT_TEMPORARY_REG1
&& dst
<= SLJIT_NO_REGISTERS
) {
1002 EMIT_MOV(compiler
, dst
, 0, src
, srcw
);
1003 code
= emit_x86_instruction(compiler
, 1, 0, 0, dst
, dstw
);
1007 return SLJIT_SUCCESS
;
1009 EMIT_MOV(compiler
, TMP_REGISTER
, 0, src
, srcw
);
1010 code
= emit_x86_instruction(compiler
, 1, 0, 0, TMP_REGISTER
, 0);
1014 EMIT_MOV(compiler
, dst
, dstw
, TMP_REGISTER
, 0);
1015 return SLJIT_SUCCESS
;
1018 static sljit_si
emit_not_with_flags(struct sljit_compiler
*compiler
,
1019 sljit_si dst
, sljit_sw dstw
,
1020 sljit_si src
, sljit_sw srcw
)
1024 if (dst
== SLJIT_UNUSED
) {
1025 EMIT_MOV(compiler
, TMP_REGISTER
, 0, src
, srcw
);
1026 code
= emit_x86_instruction(compiler
, 1, 0, 0, TMP_REGISTER
, 0);
1030 code
= emit_x86_instruction(compiler
, 1, TMP_REGISTER
, 0, TMP_REGISTER
, 0);
1033 return SLJIT_SUCCESS
;
1035 if (dst
>= SLJIT_TEMPORARY_REG1
&& dst
<= SLJIT_NO_REGISTERS
) {
1036 EMIT_MOV(compiler
, dst
, 0, src
, srcw
);
1037 code
= emit_x86_instruction(compiler
, 1, 0, 0, dst
, dstw
);
1041 code
= emit_x86_instruction(compiler
, 1, dst
, 0, dst
, 0);
1044 return SLJIT_SUCCESS
;
1046 EMIT_MOV(compiler
, TMP_REGISTER
, 0, src
, srcw
);
1047 code
= emit_x86_instruction(compiler
, 1, 0, 0, TMP_REGISTER
, 0);
1051 code
= emit_x86_instruction(compiler
, 1, TMP_REGISTER
, 0, TMP_REGISTER
, 0);
1054 EMIT_MOV(compiler
, dst
, dstw
, TMP_REGISTER
, 0);
1055 return SLJIT_SUCCESS
;
1058 static sljit_si
emit_clz(struct sljit_compiler
*compiler
, sljit_si op_flags
,
1059 sljit_si dst
, sljit_sw dstw
,
1060 sljit_si src
, sljit_sw srcw
)
1065 SLJIT_UNUSED_ARG(op_flags
);
1066 if (SLJIT_UNLIKELY(dst
== SLJIT_UNUSED
)) {
1067 /* Just set the zero flag. */
1068 EMIT_MOV(compiler
, TMP_REGISTER
, 0, src
, srcw
);
1069 code
= emit_x86_instruction(compiler
, 1, 0, 0, TMP_REGISTER
, 0);
1073 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1074 code
= emit_x86_instruction(compiler
, 1 | EX86_SHIFT_INS
, SLJIT_IMM
, 31, TMP_REGISTER
, 0);
1076 code
= emit_x86_instruction(compiler
, 1 | EX86_SHIFT_INS
, SLJIT_IMM
, !(op_flags
& SLJIT_INT_OP
) ? 63 : 31, TMP_REGISTER
, 0);
1080 return SLJIT_SUCCESS
;
1083 if (SLJIT_UNLIKELY(src
& SLJIT_IMM
)) {
1084 EMIT_MOV(compiler
, TMP_REGISTER
, 0, src
, srcw
);
1089 code
= emit_x86_instruction(compiler
, 2, TMP_REGISTER
, 0, src
, srcw
);
1094 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1095 if (dst
>= SLJIT_TEMPORARY_REG1
&& dst
<= TMP_REGISTER
)
1098 /* Find an unused temporary register. */
1099 if ((dst
& 0xf) != SLJIT_TEMPORARY_REG1
&& (dst
& 0xf0) != (SLJIT_TEMPORARY_REG1
<< 4))
1100 dst_r
= SLJIT_TEMPORARY_REG1
;
1101 else if ((dst
& 0xf) != SLJIT_TEMPORARY_REG2
&& (dst
& 0xf0) != (SLJIT_TEMPORARY_REG2
<< 4))
1102 dst_r
= SLJIT_TEMPORARY_REG2
;
1104 dst_r
= SLJIT_TEMPORARY_REG3
;
1105 EMIT_MOV(compiler
, dst
, dstw
, dst_r
, 0);
1107 EMIT_MOV(compiler
, dst_r
, 0, SLJIT_IMM
, 32 + 31);
1109 dst_r
= (dst
>= SLJIT_TEMPORARY_REG1
&& dst
<= TMP_REGISTER
) ? dst
: TMP_REG2
;
1110 compiler
->mode32
= 0;
1111 EMIT_MOV(compiler
, dst_r
, 0, SLJIT_IMM
, !(op_flags
& SLJIT_INT_OP
) ? 64 + 63 : 32 + 31);
1112 compiler
->mode32
= op_flags
& SLJIT_INT_OP
;
1115 code
= emit_x86_instruction(compiler
, 2, dst_r
, 0, TMP_REGISTER
, 0);
1118 *code
= CMOVNE_r_rm
;
1120 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1121 code
= emit_x86_instruction(compiler
, 1 | EX86_BIN_INS
, SLJIT_IMM
, 31, dst_r
, 0);
1123 code
= emit_x86_instruction(compiler
, 1 | EX86_BIN_INS
, SLJIT_IMM
, !(op_flags
& SLJIT_INT_OP
) ? 63 : 31, dst_r
, 0);
1128 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1129 if (dst
& SLJIT_MEM
) {
1130 code
= emit_x86_instruction(compiler
, 1, dst_r
, 0, dst
, dstw
);
1135 if (dst
& SLJIT_MEM
)
1136 EMIT_MOV(compiler
, dst
, dstw
, TMP_REG2
, 0);
1138 return SLJIT_SUCCESS
;
1141 SLJIT_API_FUNC_ATTRIBUTE sljit_si
sljit_emit_op1(struct sljit_compiler
*compiler
, sljit_si op
,
1142 sljit_si dst
, sljit_sw dstw
,
1143 sljit_si src
, sljit_sw srcw
)
1146 sljit_si update
= 0;
1147 sljit_si op_flags
= GET_ALL_FLAGS(op
);
1148 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1149 sljit_si dst_is_ereg
= 0;
1150 sljit_si src_is_ereg
= 0;
1152 #define src_is_ereg 0
1156 check_sljit_emit_op1(compiler
, op
, dst
, dstw
, src
, srcw
);
1157 ADJUST_LOCAL_OFFSET(dst
, dstw
);
1158 ADJUST_LOCAL_OFFSET(src
, srcw
);
1160 CHECK_EXTRA_REGS(dst
, dstw
, dst_is_ereg
= 1);
1161 CHECK_EXTRA_REGS(src
, srcw
, src_is_ereg
= 1);
1162 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1163 compiler
->mode32
= op_flags
& SLJIT_INT_OP
;
1166 op
= GET_OPCODE(op
);
1167 if (op
>= SLJIT_MOV
&& op
<= SLJIT_MOVU_P
) {
1168 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1169 compiler
->mode32
= 0;
1172 if (op_flags
& SLJIT_INT_OP
) {
1173 if (src
<= SLJIT_NO_REGISTERS
&& src
== dst
) {
1174 if (!TYPE_CAST_NEEDED(op
))
1175 return SLJIT_SUCCESS
;
1177 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1178 if (op
== SLJIT_MOV_SI
&& (src
& SLJIT_MEM
))
1180 if (op
== SLJIT_MOVU_SI
&& (src
& SLJIT_MEM
))
1182 if (op
== SLJIT_MOV_UI
&& (src
& SLJIT_IMM
))
1184 if (op
== SLJIT_MOVU_UI
&& (src
& SLJIT_IMM
))
1189 SLJIT_COMPILE_ASSERT(SLJIT_MOV
+ 8 == SLJIT_MOVU
, movu_offset
);
1190 if (op
>= SLJIT_MOVU
) {
1195 if (src
& SLJIT_IMM
) {
1198 srcw
= (sljit_ub
)srcw
;
1201 srcw
= (sljit_sb
)srcw
;
1204 srcw
= (sljit_uh
)srcw
;
1207 srcw
= (sljit_sh
)srcw
;
1209 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1211 srcw
= (sljit_ui
)srcw
;
1214 srcw
= (sljit_si
)srcw
;
1218 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1219 if (SLJIT_UNLIKELY(dst_is_ereg
))
1220 return emit_mov(compiler
, dst
, dstw
, src
, srcw
);
1224 if (SLJIT_UNLIKELY(update
) && (src
& SLJIT_MEM
) && !src_is_ereg
&& (src
& 0xf) && (srcw
!= 0 || (src
& 0xf0) != 0)) {
1225 code
= emit_x86_instruction(compiler
, 1, src
& 0xf, 0, src
, srcw
);
1228 src
&= SLJIT_MEM
| 0xf;
1232 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1233 if (SLJIT_UNLIKELY(dst_is_ereg
) && (!(op
== SLJIT_MOV
|| op
== SLJIT_MOV_UI
|| op
== SLJIT_MOV_SI
|| op
== SLJIT_MOV_P
) || (src
& SLJIT_MEM
))) {
1234 SLJIT_ASSERT(dst
== SLJIT_MEM1(SLJIT_LOCALS_REG
));
1242 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1246 FAIL_IF(emit_mov(compiler
, dst
, dstw
, src
, srcw
));
1249 FAIL_IF(emit_mov_byte(compiler
, 0, dst
, dstw
, src
, srcw
));
1252 FAIL_IF(emit_mov_byte(compiler
, 1, dst
, dstw
, src
, srcw
));
1255 FAIL_IF(emit_mov_half(compiler
, 0, dst
, dstw
, src
, srcw
));
1258 FAIL_IF(emit_mov_half(compiler
, 1, dst
, dstw
, src
, srcw
));
1260 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1262 FAIL_IF(emit_mov_int(compiler
, 0, dst
, dstw
, src
, srcw
));
1265 FAIL_IF(emit_mov_int(compiler
, 1, dst
, dstw
, src
, srcw
));
1270 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1271 if (SLJIT_UNLIKELY(dst_is_ereg
) && dst
== TMP_REGISTER
)
1272 return emit_mov(compiler
, SLJIT_MEM1(SLJIT_LOCALS_REG
), dstw
, TMP_REGISTER
, 0);
1275 if (SLJIT_UNLIKELY(update
) && (dst
& SLJIT_MEM
) && (dst
& 0xf) && (dstw
!= 0 || (dst
& 0xf0) != 0)) {
1276 code
= emit_x86_instruction(compiler
, 1, dst
& 0xf, 0, dst
, dstw
);
1280 return SLJIT_SUCCESS
;
1283 if (SLJIT_UNLIKELY(GET_FLAGS(op_flags
)))
1284 compiler
->flags_saved
= 0;
1288 if (SLJIT_UNLIKELY(op_flags
& SLJIT_SET_E
))
1289 return emit_not_with_flags(compiler
, dst
, dstw
, src
, srcw
);
1290 return emit_unary(compiler
, NOT_rm
, dst
, dstw
, src
, srcw
);
1293 if (SLJIT_UNLIKELY(op_flags
& SLJIT_KEEP_FLAGS
) && !compiler
->flags_saved
)
1294 FAIL_IF(emit_save_flags(compiler
));
1295 return emit_unary(compiler
, NEG_rm
, dst
, dstw
, src
, srcw
);
1298 if (SLJIT_UNLIKELY(op_flags
& SLJIT_KEEP_FLAGS
) && !compiler
->flags_saved
)
1299 FAIL_IF(emit_save_flags(compiler
));
1300 return emit_clz(compiler
, op_flags
, dst
, dstw
, src
, srcw
);
1303 return SLJIT_SUCCESS
;
1305 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1310 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1312 #define BINARY_IMM(_op_imm_, _op_mr_, immw, arg, argw) \
1313 if (IS_HALFWORD(immw) || compiler->mode32) { \
1314 code = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, immw, arg, argw); \
1316 *(code + 1) |= (_op_imm_); \
1319 FAIL_IF(emit_load_imm64(compiler, TMP_REG2, immw)); \
1320 code = emit_x86_instruction(compiler, 1, TMP_REG2, 0, arg, argw); \
1322 *code = (_op_mr_); \
1325 #define BINARY_EAX_IMM(_op_eax_imm_, immw) \
1326 FAIL_IF(emit_do_imm32(compiler, (!compiler->mode32) ? REX_W : 0, (_op_eax_imm_), immw))
1330 #define BINARY_IMM(_op_imm_, _op_mr_, immw, arg, argw) \
1331 code = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, immw, arg, argw); \
1333 *(code + 1) |= (_op_imm_);
1335 #define BINARY_EAX_IMM(_op_eax_imm_, immw) \
1336 FAIL_IF(emit_do_imm(compiler, (_op_eax_imm_), immw))
1340 static sljit_si
emit_cum_binary(struct sljit_compiler
*compiler
,
1341 sljit_ub op_rm
, sljit_ub op_mr
, sljit_ub op_imm
, sljit_ub op_eax_imm
,
1342 sljit_si dst
, sljit_sw dstw
,
1343 sljit_si src1
, sljit_sw src1w
,
1344 sljit_si src2
, sljit_sw src2w
)
1348 if (dst
== SLJIT_UNUSED
) {
1349 EMIT_MOV(compiler
, TMP_REGISTER
, 0, src1
, src1w
);
1350 if (src2
& SLJIT_IMM
) {
1351 BINARY_IMM(op_imm
, op_mr
, src2w
, TMP_REGISTER
, 0);
1354 code
= emit_x86_instruction(compiler
, 1, TMP_REGISTER
, 0, src2
, src2w
);
1358 return SLJIT_SUCCESS
;
1361 if (dst
== src1
&& dstw
== src1w
) {
1362 if (src2
& SLJIT_IMM
) {
1363 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1364 if ((dst
== SLJIT_TEMPORARY_REG1
) && (src2w
> 127 || src2w
< -128) && (compiler
->mode32
|| IS_HALFWORD(src2w
))) {
1366 if ((dst
== SLJIT_TEMPORARY_REG1
) && (src2w
> 127 || src2w
< -128)) {
1368 BINARY_EAX_IMM(op_eax_imm
, src2w
);
1371 BINARY_IMM(op_imm
, op_mr
, src2w
, dst
, dstw
);
1374 else if (dst
>= SLJIT_TEMPORARY_REG1
&& dst
<= SLJIT_NO_REGISTERS
) {
1375 code
= emit_x86_instruction(compiler
, 1, dst
, dstw
, src2
, src2w
);
1379 else if (src2
>= SLJIT_TEMPORARY_REG1
&& src2
<= TMP_REGISTER
) {
1380 /* Special exception for sljit_emit_cond_value. */
1381 code
= emit_x86_instruction(compiler
, 1, src2
, src2w
, dst
, dstw
);
1386 EMIT_MOV(compiler
, TMP_REGISTER
, 0, src2
, src2w
);
1387 code
= emit_x86_instruction(compiler
, 1, TMP_REGISTER
, 0, dst
, dstw
);
1391 return SLJIT_SUCCESS
;
1394 /* Only for cumulative operations. */
1395 if (dst
== src2
&& dstw
== src2w
) {
1396 if (src1
& SLJIT_IMM
) {
1397 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1398 if ((dst
== SLJIT_TEMPORARY_REG1
) && (src1w
> 127 || src1w
< -128) && (compiler
->mode32
|| IS_HALFWORD(src1w
))) {
1400 if ((dst
== SLJIT_TEMPORARY_REG1
) && (src1w
> 127 || src1w
< -128)) {
1402 BINARY_EAX_IMM(op_eax_imm
, src1w
);
1405 BINARY_IMM(op_imm
, op_mr
, src1w
, dst
, dstw
);
1408 else if (dst
>= SLJIT_TEMPORARY_REG1
&& dst
<= SLJIT_NO_REGISTERS
) {
1409 code
= emit_x86_instruction(compiler
, 1, dst
, dstw
, src1
, src1w
);
1413 else if (src1
>= SLJIT_TEMPORARY_REG1
&& src1
<= SLJIT_NO_REGISTERS
) {
1414 code
= emit_x86_instruction(compiler
, 1, src1
, src1w
, dst
, dstw
);
1419 EMIT_MOV(compiler
, TMP_REGISTER
, 0, src1
, src1w
);
1420 code
= emit_x86_instruction(compiler
, 1, TMP_REGISTER
, 0, dst
, dstw
);
1424 return SLJIT_SUCCESS
;
1427 /* General version. */
1428 if (dst
>= SLJIT_TEMPORARY_REG1
&& dst
<= SLJIT_NO_REGISTERS
) {
1429 EMIT_MOV(compiler
, dst
, 0, src1
, src1w
);
1430 if (src2
& SLJIT_IMM
) {
1431 BINARY_IMM(op_imm
, op_mr
, src2w
, dst
, 0);
1434 code
= emit_x86_instruction(compiler
, 1, dst
, 0, src2
, src2w
);
1440 /* This version requires less memory writing. */
1441 EMIT_MOV(compiler
, TMP_REGISTER
, 0, src1
, src1w
);
1442 if (src2
& SLJIT_IMM
) {
1443 BINARY_IMM(op_imm
, op_mr
, src2w
, TMP_REGISTER
, 0);
1446 code
= emit_x86_instruction(compiler
, 1, TMP_REGISTER
, 0, src2
, src2w
);
1450 EMIT_MOV(compiler
, dst
, dstw
, TMP_REGISTER
, 0);
1453 return SLJIT_SUCCESS
;
1456 static sljit_si
emit_non_cum_binary(struct sljit_compiler
*compiler
,
1457 sljit_ub op_rm
, sljit_ub op_mr
, sljit_ub op_imm
, sljit_ub op_eax_imm
,
1458 sljit_si dst
, sljit_sw dstw
,
1459 sljit_si src1
, sljit_sw src1w
,
1460 sljit_si src2
, sljit_sw src2w
)
1464 if (dst
== SLJIT_UNUSED
) {
1465 EMIT_MOV(compiler
, TMP_REGISTER
, 0, src1
, src1w
);
1466 if (src2
& SLJIT_IMM
) {
1467 BINARY_IMM(op_imm
, op_mr
, src2w
, TMP_REGISTER
, 0);
1470 code
= emit_x86_instruction(compiler
, 1, TMP_REGISTER
, 0, src2
, src2w
);
1474 return SLJIT_SUCCESS
;
1477 if (dst
== src1
&& dstw
== src1w
) {
1478 if (src2
& SLJIT_IMM
) {
1479 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1480 if ((dst
== SLJIT_TEMPORARY_REG1
) && (src2w
> 127 || src2w
< -128) && (compiler
->mode32
|| IS_HALFWORD(src2w
))) {
1482 if ((dst
== SLJIT_TEMPORARY_REG1
) && (src2w
> 127 || src2w
< -128)) {
1484 BINARY_EAX_IMM(op_eax_imm
, src2w
);
1487 BINARY_IMM(op_imm
, op_mr
, src2w
, dst
, dstw
);
1490 else if (dst
>= SLJIT_TEMPORARY_REG1
&& dst
<= SLJIT_NO_REGISTERS
) {
1491 code
= emit_x86_instruction(compiler
, 1, dst
, dstw
, src2
, src2w
);
1495 else if (src2
>= SLJIT_TEMPORARY_REG1
&& src2
<= SLJIT_NO_REGISTERS
) {
1496 code
= emit_x86_instruction(compiler
, 1, src2
, src2w
, dst
, dstw
);
1501 EMIT_MOV(compiler
, TMP_REGISTER
, 0, src2
, src2w
);
1502 code
= emit_x86_instruction(compiler
, 1, TMP_REGISTER
, 0, dst
, dstw
);
1506 return SLJIT_SUCCESS
;
1509 /* General version. */
1510 if ((dst
>= SLJIT_TEMPORARY_REG1
&& dst
<= SLJIT_NO_REGISTERS
) && dst
!= src2
) {
1511 EMIT_MOV(compiler
, dst
, 0, src1
, src1w
);
1512 if (src2
& SLJIT_IMM
) {
1513 BINARY_IMM(op_imm
, op_mr
, src2w
, dst
, 0);
1516 code
= emit_x86_instruction(compiler
, 1, dst
, 0, src2
, src2w
);
1522 /* This version requires less memory writing. */
1523 EMIT_MOV(compiler
, TMP_REGISTER
, 0, src1
, src1w
);
1524 if (src2
& SLJIT_IMM
) {
1525 BINARY_IMM(op_imm
, op_mr
, src2w
, TMP_REGISTER
, 0);
1528 code
= emit_x86_instruction(compiler
, 1, TMP_REGISTER
, 0, src2
, src2w
);
1532 EMIT_MOV(compiler
, dst
, dstw
, TMP_REGISTER
, 0);
1535 return SLJIT_SUCCESS
;
1538 static sljit_si
emit_mul(struct sljit_compiler
*compiler
,
1539 sljit_si dst
, sljit_sw dstw
,
1540 sljit_si src1
, sljit_sw src1w
,
1541 sljit_si src2
, sljit_sw src2w
)
1546 dst_r
= (dst
>= SLJIT_TEMPORARY_REG1
&& dst
<= SLJIT_NO_REGISTERS
) ? dst
: TMP_REGISTER
;
1548 /* Register destination. */
1549 if (dst_r
== src1
&& !(src2
& SLJIT_IMM
)) {
1550 code
= emit_x86_instruction(compiler
, 2, dst_r
, 0, src2
, src2w
);
1555 else if (dst_r
== src2
&& !(src1
& SLJIT_IMM
)) {
1556 code
= emit_x86_instruction(compiler
, 2, dst_r
, 0, src1
, src1w
);
1561 else if (src1
& SLJIT_IMM
) {
1562 if (src2
& SLJIT_IMM
) {
1563 EMIT_MOV(compiler
, dst_r
, 0, SLJIT_IMM
, src2w
);
1568 if (src1w
<= 127 && src1w
>= -128) {
1569 code
= emit_x86_instruction(compiler
, 1, dst_r
, 0, src2
, src2w
);
1571 *code
= IMUL_r_rm_i8
;
1572 code
= (sljit_ub
*)ensure_buf(compiler
, 1 + 1);
1575 *code
= (sljit_sb
)src1w
;
1577 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1579 code
= emit_x86_instruction(compiler
, 1, dst_r
, 0, src2
, src2w
);
1581 *code
= IMUL_r_rm_i32
;
1582 code
= (sljit_ub
*)ensure_buf(compiler
, 1 + 4);
1585 *(sljit_sw
*)code
= src1w
;
1588 else if (IS_HALFWORD(src1w
)) {
1589 code
= emit_x86_instruction(compiler
, 1, dst_r
, 0, src2
, src2w
);
1591 *code
= IMUL_r_rm_i32
;
1592 code
= (sljit_ub
*)ensure_buf(compiler
, 1 + 4);
1595 *(sljit_si
*)code
= (sljit_si
)src1w
;
1598 EMIT_MOV(compiler
, TMP_REG2
, 0, SLJIT_IMM
, src1w
);
1600 EMIT_MOV(compiler
, dst_r
, 0, src2
, src2w
);
1601 code
= emit_x86_instruction(compiler
, 2, dst_r
, 0, TMP_REG2
, 0);
1608 else if (src2
& SLJIT_IMM
) {
1609 /* Note: src1 is NOT immediate. */
1611 if (src2w
<= 127 && src2w
>= -128) {
1612 code
= emit_x86_instruction(compiler
, 1, dst_r
, 0, src1
, src1w
);
1614 *code
= IMUL_r_rm_i8
;
1615 code
= (sljit_ub
*)ensure_buf(compiler
, 1 + 1);
1618 *code
= (sljit_sb
)src2w
;
1620 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
1622 code
= emit_x86_instruction(compiler
, 1, dst_r
, 0, src1
, src1w
);
1624 *code
= IMUL_r_rm_i32
;
1625 code
= (sljit_ub
*)ensure_buf(compiler
, 1 + 4);
1628 *(sljit_sw
*)code
= src2w
;
1631 else if (IS_HALFWORD(src2w
)) {
1632 code
= emit_x86_instruction(compiler
, 1, dst_r
, 0, src1
, src1w
);
1634 *code
= IMUL_r_rm_i32
;
1635 code
= (sljit_ub
*)ensure_buf(compiler
, 1 + 4);
1638 *(sljit_si
*)code
= (sljit_si
)src2w
;
1641 EMIT_MOV(compiler
, TMP_REG2
, 0, SLJIT_IMM
, src1w
);
1643 EMIT_MOV(compiler
, dst_r
, 0, src1
, src1w
);
1644 code
= emit_x86_instruction(compiler
, 2, dst_r
, 0, TMP_REG2
, 0);
1652 /* Neither argument is immediate. */
1653 if (ADDRESSING_DEPENDS_ON(src2
, dst_r
))
1654 dst_r
= TMP_REGISTER
;
1655 EMIT_MOV(compiler
, dst_r
, 0, src1
, src1w
);
1656 code
= emit_x86_instruction(compiler
, 2, dst_r
, 0, src2
, src2w
);
1662 if (dst_r
== TMP_REGISTER
)
1663 EMIT_MOV(compiler
, dst
, dstw
, TMP_REGISTER
, 0);
1665 return SLJIT_SUCCESS
;
1668 static sljit_si
emit_lea_binary(struct sljit_compiler
*compiler
,
1669 sljit_si dst
, sljit_sw dstw
,
1670 sljit_si src1
, sljit_sw src1w
,
1671 sljit_si src2
, sljit_sw src2w
)
1674 sljit_si dst_r
, done
= 0;
1676 /* These cases better be left to handled by normal way. */
1677 if (dst
== src1
&& dstw
== src1w
)
1678 return SLJIT_ERR_UNSUPPORTED
;
1679 if (dst
== src2
&& dstw
== src2w
)
1680 return SLJIT_ERR_UNSUPPORTED
;
1682 dst_r
= (dst
>= SLJIT_TEMPORARY_REG1
&& dst
<= SLJIT_NO_REGISTERS
) ? dst
: TMP_REGISTER
;
1684 if (src1
>= SLJIT_TEMPORARY_REG1
&& src1
<= SLJIT_NO_REGISTERS
) {
1685 if ((src2
>= SLJIT_TEMPORARY_REG1
&& src2
<= SLJIT_NO_REGISTERS
) || src2
== TMP_REGISTER
) {
1686 code
= emit_x86_instruction(compiler
, 1, dst_r
, 0, SLJIT_MEM2(src1
, src2
), 0);
1691 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1692 if ((src2
& SLJIT_IMM
) && (compiler
->mode32
|| IS_HALFWORD(src2w
))) {
1693 code
= emit_x86_instruction(compiler
, 1, dst_r
, 0, SLJIT_MEM1(src1
), (sljit_si
)src2w
);
1695 if (src2
& SLJIT_IMM
) {
1696 code
= emit_x86_instruction(compiler
, 1, dst_r
, 0, SLJIT_MEM1(src1
), src2w
);
1703 else if (src2
>= SLJIT_TEMPORARY_REG1
&& src2
<= SLJIT_NO_REGISTERS
) {
1704 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1705 if ((src1
& SLJIT_IMM
) && (compiler
->mode32
|| IS_HALFWORD(src1w
))) {
1706 code
= emit_x86_instruction(compiler
, 1, dst_r
, 0, SLJIT_MEM1(src2
), (sljit_si
)src1w
);
1708 if (src1
& SLJIT_IMM
) {
1709 code
= emit_x86_instruction(compiler
, 1, dst_r
, 0, SLJIT_MEM1(src2
), src1w
);
1718 if (dst_r
== TMP_REGISTER
)
1719 return emit_mov(compiler
, dst
, dstw
, TMP_REGISTER
, 0);
1720 return SLJIT_SUCCESS
;
1722 return SLJIT_ERR_UNSUPPORTED
;
1725 static sljit_si
emit_cmp_binary(struct sljit_compiler
*compiler
,
1726 sljit_si src1
, sljit_sw src1w
,
1727 sljit_si src2
, sljit_sw src2w
)
1731 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1732 if (src1
== SLJIT_TEMPORARY_REG1
&& (src2
& SLJIT_IMM
) && (src2w
> 127 || src2w
< -128) && (compiler
->mode32
|| IS_HALFWORD(src2w
))) {
1734 if (src1
== SLJIT_TEMPORARY_REG1
&& (src2
& SLJIT_IMM
) && (src2w
> 127 || src2w
< -128)) {
1736 BINARY_EAX_IMM(CMP_EAX_i32
, src2w
);
1737 return SLJIT_SUCCESS
;
1740 if (src1
>= SLJIT_TEMPORARY_REG1
&& src1
<= SLJIT_NO_REGISTERS
) {
1741 if (src2
& SLJIT_IMM
) {
1742 BINARY_IMM(CMP
, CMP_rm_r
, src2w
, src1
, 0);
1745 code
= emit_x86_instruction(compiler
, 1, src1
, 0, src2
, src2w
);
1749 return SLJIT_SUCCESS
;
1752 if (src2
>= SLJIT_TEMPORARY_REG1
&& src2
<= SLJIT_NO_REGISTERS
&& !(src1
& SLJIT_IMM
)) {
1753 code
= emit_x86_instruction(compiler
, 1, src2
, 0, src1
, src1w
);
1756 return SLJIT_SUCCESS
;
1759 if (src2
& SLJIT_IMM
) {
1760 if (src1
& SLJIT_IMM
) {
1761 EMIT_MOV(compiler
, TMP_REGISTER
, 0, src1
, src1w
);
1762 src1
= TMP_REGISTER
;
1765 BINARY_IMM(CMP
, CMP_rm_r
, src2w
, src1
, src1w
);
1768 EMIT_MOV(compiler
, TMP_REGISTER
, 0, src1
, src1w
);
1769 code
= emit_x86_instruction(compiler
, 1, TMP_REGISTER
, 0, src2
, src2w
);
1773 return SLJIT_SUCCESS
;
1776 static sljit_si
emit_test_binary(struct sljit_compiler
*compiler
,
1777 sljit_si src1
, sljit_sw src1w
,
1778 sljit_si src2
, sljit_sw src2w
)
1782 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1783 if (src1
== SLJIT_TEMPORARY_REG1
&& (src2
& SLJIT_IMM
) && (src2w
> 127 || src2w
< -128) && (compiler
->mode32
|| IS_HALFWORD(src2w
))) {
1785 if (src1
== SLJIT_TEMPORARY_REG1
&& (src2
& SLJIT_IMM
) && (src2w
> 127 || src2w
< -128)) {
1787 BINARY_EAX_IMM(TEST_EAX_i32
, src2w
);
1788 return SLJIT_SUCCESS
;
1791 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1792 if (src2
== SLJIT_TEMPORARY_REG1
&& (src2
& SLJIT_IMM
) && (src1w
> 127 || src1w
< -128) && (compiler
->mode32
|| IS_HALFWORD(src1w
))) {
1794 if (src2
== SLJIT_TEMPORARY_REG1
&& (src1
& SLJIT_IMM
) && (src1w
> 127 || src1w
< -128)) {
1796 BINARY_EAX_IMM(TEST_EAX_i32
, src1w
);
1797 return SLJIT_SUCCESS
;
1800 if (src1
>= SLJIT_TEMPORARY_REG1
&& src1
<= SLJIT_NO_REGISTERS
) {
1801 if (src2
& SLJIT_IMM
) {
1802 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1803 if (IS_HALFWORD(src2w
) || compiler
->mode32
) {
1804 code
= emit_x86_instruction(compiler
, 1, SLJIT_IMM
, src2w
, src1
, 0);
1809 FAIL_IF(emit_load_imm64(compiler
, TMP_REG2
, src2w
));
1810 code
= emit_x86_instruction(compiler
, 1, TMP_REG2
, 0, src1
, 0);
1815 code
= emit_x86_instruction(compiler
, 1, SLJIT_IMM
, src2w
, src1
, 0);
1821 code
= emit_x86_instruction(compiler
, 1, src1
, 0, src2
, src2w
);
1825 return SLJIT_SUCCESS
;
1828 if (src2
>= SLJIT_TEMPORARY_REG1
&& src2
<= SLJIT_NO_REGISTERS
) {
1829 if (src1
& SLJIT_IMM
) {
1830 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1831 if (IS_HALFWORD(src1w
) || compiler
->mode32
) {
1832 code
= emit_x86_instruction(compiler
, 1, SLJIT_IMM
, src1w
, src2
, 0);
1837 FAIL_IF(emit_load_imm64(compiler
, TMP_REG2
, src1w
));
1838 code
= emit_x86_instruction(compiler
, 1, TMP_REG2
, 0, src2
, 0);
1843 code
= emit_x86_instruction(compiler
, 1, src1
, src1w
, src2
, 0);
1849 code
= emit_x86_instruction(compiler
, 1, src2
, 0, src1
, src1w
);
1853 return SLJIT_SUCCESS
;
1856 EMIT_MOV(compiler
, TMP_REGISTER
, 0, src1
, src1w
);
1857 if (src2
& SLJIT_IMM
) {
1858 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1859 if (IS_HALFWORD(src2w
) || compiler
->mode32
) {
1860 code
= emit_x86_instruction(compiler
, 1, SLJIT_IMM
, src2w
, TMP_REGISTER
, 0);
1865 FAIL_IF(emit_load_imm64(compiler
, TMP_REG2
, src2w
));
1866 code
= emit_x86_instruction(compiler
, 1, TMP_REG2
, 0, TMP_REGISTER
, 0);
1871 code
= emit_x86_instruction(compiler
, 1, SLJIT_IMM
, src2w
, TMP_REGISTER
, 0);
1877 code
= emit_x86_instruction(compiler
, 1, TMP_REGISTER
, 0, src2
, src2w
);
1881 return SLJIT_SUCCESS
;
1884 static sljit_si
emit_shift(struct sljit_compiler
*compiler
,
1886 sljit_si dst
, sljit_sw dstw
,
1887 sljit_si src1
, sljit_sw src1w
,
1888 sljit_si src2
, sljit_sw src2w
)
1892 if ((src2
& SLJIT_IMM
) || (src2
== SLJIT_PREF_SHIFT_REG
)) {
1893 if (dst
== src1
&& dstw
== src1w
) {
1894 code
= emit_x86_instruction(compiler
, 1 | EX86_SHIFT_INS
, src2
, src2w
, dst
, dstw
);
1897 return SLJIT_SUCCESS
;
1899 if (dst
== SLJIT_UNUSED
) {
1900 EMIT_MOV(compiler
, TMP_REGISTER
, 0, src1
, src1w
);
1901 code
= emit_x86_instruction(compiler
, 1 | EX86_SHIFT_INS
, src2
, src2w
, TMP_REGISTER
, 0);
1904 return SLJIT_SUCCESS
;
1906 if (dst
== SLJIT_PREF_SHIFT_REG
&& src2
== SLJIT_PREF_SHIFT_REG
) {
1907 EMIT_MOV(compiler
, TMP_REGISTER
, 0, src1
, src1w
);
1908 code
= emit_x86_instruction(compiler
, 1 | EX86_SHIFT_INS
, SLJIT_PREF_SHIFT_REG
, 0, TMP_REGISTER
, 0);
1911 EMIT_MOV(compiler
, SLJIT_PREF_SHIFT_REG
, 0, TMP_REGISTER
, 0);
1912 return SLJIT_SUCCESS
;
1914 if (dst
>= SLJIT_TEMPORARY_REG1
&& dst
<= SLJIT_NO_REGISTERS
) {
1915 EMIT_MOV(compiler
, dst
, 0, src1
, src1w
);
1916 code
= emit_x86_instruction(compiler
, 1 | EX86_SHIFT_INS
, src2
, src2w
, dst
, 0);
1919 return SLJIT_SUCCESS
;
1922 EMIT_MOV(compiler
, TMP_REGISTER
, 0, src1
, src1w
);
1923 code
= emit_x86_instruction(compiler
, 1 | EX86_SHIFT_INS
, src2
, src2w
, TMP_REGISTER
, 0);
1926 EMIT_MOV(compiler
, dst
, dstw
, TMP_REGISTER
, 0);
1927 return SLJIT_SUCCESS
;
1930 if (dst
== SLJIT_PREF_SHIFT_REG
) {
1931 EMIT_MOV(compiler
, TMP_REGISTER
, 0, src1
, src1w
);
1932 EMIT_MOV(compiler
, SLJIT_PREF_SHIFT_REG
, 0, src2
, src2w
);
1933 code
= emit_x86_instruction(compiler
, 1 | EX86_SHIFT_INS
, SLJIT_PREF_SHIFT_REG
, 0, TMP_REGISTER
, 0);
1936 EMIT_MOV(compiler
, SLJIT_PREF_SHIFT_REG
, 0, TMP_REGISTER
, 0);
1938 else if (dst
>= SLJIT_TEMPORARY_REG1
&& dst
<= SLJIT_NO_REGISTERS
&& dst
!= src2
&& !ADDRESSING_DEPENDS_ON(src2
, dst
)) {
1940 EMIT_MOV(compiler
, dst
, 0, src1
, src1w
);
1941 EMIT_MOV(compiler
, TMP_REGISTER
, 0, SLJIT_PREF_SHIFT_REG
, 0);
1942 EMIT_MOV(compiler
, SLJIT_PREF_SHIFT_REG
, 0, src2
, src2w
);
1943 code
= emit_x86_instruction(compiler
, 1 | EX86_SHIFT_INS
, SLJIT_PREF_SHIFT_REG
, 0, dst
, 0);
1946 EMIT_MOV(compiler
, SLJIT_PREF_SHIFT_REG
, 0, TMP_REGISTER
, 0);
1949 /* This case is really difficult, since ecx itself may used for
1950 addressing, and we must ensure to work even in that case. */
1951 EMIT_MOV(compiler
, TMP_REGISTER
, 0, src1
, src1w
);
1952 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1953 EMIT_MOV(compiler
, TMP_REG2
, 0, SLJIT_PREF_SHIFT_REG
, 0);
1955 /* [esp+0] contains the flags. */
1956 EMIT_MOV(compiler
, SLJIT_MEM1(SLJIT_LOCALS_REG
), sizeof(sljit_sw
), SLJIT_PREF_SHIFT_REG
, 0);
1958 EMIT_MOV(compiler
, SLJIT_PREF_SHIFT_REG
, 0, src2
, src2w
);
1959 code
= emit_x86_instruction(compiler
, 1 | EX86_SHIFT_INS
, SLJIT_PREF_SHIFT_REG
, 0, TMP_REGISTER
, 0);
1962 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1963 EMIT_MOV(compiler
, SLJIT_PREF_SHIFT_REG
, 0, TMP_REG2
, 0);
1965 EMIT_MOV(compiler
, SLJIT_PREF_SHIFT_REG
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), sizeof(sljit_sw
));
1967 EMIT_MOV(compiler
, dst
, dstw
, TMP_REGISTER
, 0);
1970 return SLJIT_SUCCESS
;
1973 static sljit_si
emit_shift_with_flags(struct sljit_compiler
*compiler
,
1974 sljit_ub mode
, sljit_si set_flags
,
1975 sljit_si dst
, sljit_sw dstw
,
1976 sljit_si src1
, sljit_sw src1w
,
1977 sljit_si src2
, sljit_sw src2w
)
1979 /* The CPU does not set flags if the shift count is 0. */
1980 if (src2
& SLJIT_IMM
) {
1981 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1982 if ((src2w
& 0x3f) != 0 || (compiler
->mode32
&& (src2w
& 0x1f) != 0))
1983 return emit_shift(compiler
, mode
, dst
, dstw
, src1
, src1w
, src2
, src2w
);
1985 if ((src2w
& 0x1f) != 0)
1986 return emit_shift(compiler
, mode
, dst
, dstw
, src1
, src1w
, src2
, src2w
);
1989 return emit_mov(compiler
, dst
, dstw
, src1
, src1w
);
1990 /* OR dst, src, 0 */
1991 return emit_cum_binary(compiler
, OR_r_rm
, OR_rm_r
, OR
, OR_EAX_i32
,
1992 dst
, dstw
, src1
, src1w
, SLJIT_IMM
, 0);
1996 return emit_shift(compiler
, mode
, dst
, dstw
, src1
, src1w
, src2
, src2w
);
1998 if (!(dst
>= SLJIT_TEMPORARY_REG1
&& dst
<= SLJIT_NO_REGISTERS
))
1999 FAIL_IF(emit_cmp_binary(compiler
, src1
, src1w
, SLJIT_IMM
, 0));
2001 FAIL_IF(emit_shift(compiler
,mode
, dst
, dstw
, src1
, src1w
, src2
, src2w
));
2003 if (dst
>= SLJIT_TEMPORARY_REG1
&& dst
<= SLJIT_NO_REGISTERS
)
2004 return emit_cmp_binary(compiler
, dst
, dstw
, SLJIT_IMM
, 0);
2005 return SLJIT_SUCCESS
;
2008 SLJIT_API_FUNC_ATTRIBUTE sljit_si
sljit_emit_op2(struct sljit_compiler
*compiler
, sljit_si op
,
2009 sljit_si dst
, sljit_sw dstw
,
2010 sljit_si src1
, sljit_sw src1w
,
2011 sljit_si src2
, sljit_sw src2w
)
2014 check_sljit_emit_op2(compiler
, op
, dst
, dstw
, src1
, src1w
, src2
, src2w
);
2015 ADJUST_LOCAL_OFFSET(dst
, dstw
);
2016 ADJUST_LOCAL_OFFSET(src1
, src1w
);
2017 ADJUST_LOCAL_OFFSET(src2
, src2w
);
2019 CHECK_EXTRA_REGS(dst
, dstw
, (void)0);
2020 CHECK_EXTRA_REGS(src1
, src1w
, (void)0);
2021 CHECK_EXTRA_REGS(src2
, src2w
, (void)0);
2022 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
2023 compiler
->mode32
= op
& SLJIT_INT_OP
;
2026 if (GET_OPCODE(op
) >= SLJIT_MUL
) {
2027 if (SLJIT_UNLIKELY(GET_FLAGS(op
)))
2028 compiler
->flags_saved
= 0;
2029 else if (SLJIT_UNLIKELY(op
& SLJIT_KEEP_FLAGS
) && !compiler
->flags_saved
)
2030 FAIL_IF(emit_save_flags(compiler
));
2033 switch (GET_OPCODE(op
)) {
2035 if (!GET_FLAGS(op
)) {
2036 if (emit_lea_binary(compiler
, dst
, dstw
, src1
, src1w
, src2
, src2w
) != SLJIT_ERR_UNSUPPORTED
)
2037 return compiler
->error
;
2040 compiler
->flags_saved
= 0;
2041 if (SLJIT_UNLIKELY(op
& SLJIT_KEEP_FLAGS
) && !compiler
->flags_saved
)
2042 FAIL_IF(emit_save_flags(compiler
));
2043 return emit_cum_binary(compiler
, ADD_r_rm
, ADD_rm_r
, ADD
, ADD_EAX_i32
,
2044 dst
, dstw
, src1
, src1w
, src2
, src2w
);
2046 if (SLJIT_UNLIKELY(compiler
->flags_saved
)) /* C flag must be restored. */
2047 FAIL_IF(emit_restore_flags(compiler
, 1));
2048 else if (SLJIT_UNLIKELY(op
& SLJIT_KEEP_FLAGS
))
2049 FAIL_IF(emit_save_flags(compiler
));
2050 if (SLJIT_UNLIKELY(GET_FLAGS(op
)))
2051 compiler
->flags_saved
= 0;
2052 return emit_cum_binary(compiler
, ADC_r_rm
, ADC_rm_r
, ADC
, ADC_EAX_i32
,
2053 dst
, dstw
, src1
, src1w
, src2
, src2w
);
2055 if (!GET_FLAGS(op
)) {
2056 if ((src2
& SLJIT_IMM
) && emit_lea_binary(compiler
, dst
, dstw
, src1
, src1w
, SLJIT_IMM
, -src2w
) != SLJIT_ERR_UNSUPPORTED
)
2057 return compiler
->error
;
2060 compiler
->flags_saved
= 0;
2061 if (SLJIT_UNLIKELY(op
& SLJIT_KEEP_FLAGS
) && !compiler
->flags_saved
)
2062 FAIL_IF(emit_save_flags(compiler
));
2063 if (dst
== SLJIT_UNUSED
)
2064 return emit_cmp_binary(compiler
, src1
, src1w
, src2
, src2w
);
2065 return emit_non_cum_binary(compiler
, SUB_r_rm
, SUB_rm_r
, SUB
, SUB_EAX_i32
,
2066 dst
, dstw
, src1
, src1w
, src2
, src2w
);
2068 if (SLJIT_UNLIKELY(compiler
->flags_saved
)) /* C flag must be restored. */
2069 FAIL_IF(emit_restore_flags(compiler
, 1));
2070 else if (SLJIT_UNLIKELY(op
& SLJIT_KEEP_FLAGS
))
2071 FAIL_IF(emit_save_flags(compiler
));
2072 if (SLJIT_UNLIKELY(GET_FLAGS(op
)))
2073 compiler
->flags_saved
= 0;
2074 return emit_non_cum_binary(compiler
, SBB_r_rm
, SBB_rm_r
, SBB
, SBB_EAX_i32
,
2075 dst
, dstw
, src1
, src1w
, src2
, src2w
);
2077 return emit_mul(compiler
, dst
, dstw
, src1
, src1w
, src2
, src2w
);
2079 if (dst
== SLJIT_UNUSED
)
2080 return emit_test_binary(compiler
, src1
, src1w
, src2
, src2w
);
2081 return emit_cum_binary(compiler
, AND_r_rm
, AND_rm_r
, AND
, AND_EAX_i32
,
2082 dst
, dstw
, src1
, src1w
, src2
, src2w
);
2084 return emit_cum_binary(compiler
, OR_r_rm
, OR_rm_r
, OR
, OR_EAX_i32
,
2085 dst
, dstw
, src1
, src1w
, src2
, src2w
);
2087 return emit_cum_binary(compiler
, XOR_r_rm
, XOR_rm_r
, XOR
, XOR_EAX_i32
,
2088 dst
, dstw
, src1
, src1w
, src2
, src2w
);
2090 return emit_shift_with_flags(compiler
, SHL
, GET_FLAGS(op
),
2091 dst
, dstw
, src1
, src1w
, src2
, src2w
);
2093 return emit_shift_with_flags(compiler
, SHR
, GET_FLAGS(op
),
2094 dst
, dstw
, src1
, src1w
, src2
, src2w
);
2096 return emit_shift_with_flags(compiler
, SAR
, GET_FLAGS(op
),
2097 dst
, dstw
, src1
, src1w
, src2
, src2w
);
2100 return SLJIT_SUCCESS
;
2103 SLJIT_API_FUNC_ATTRIBUTE sljit_si
sljit_get_register_index(sljit_si reg
)
2105 check_sljit_get_register_index(reg
);
2106 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
2107 if (reg
== SLJIT_TEMPORARY_EREG1
|| reg
== SLJIT_TEMPORARY_EREG2
2108 || reg
== SLJIT_SAVED_EREG1
|| reg
== SLJIT_SAVED_EREG2
)
2111 return reg_map
[reg
];
2114 SLJIT_API_FUNC_ATTRIBUTE sljit_si
sljit_emit_op_custom(struct sljit_compiler
*compiler
,
2115 void *instruction
, sljit_si size
)
2120 check_sljit_emit_op_custom(compiler
, instruction
, size
);
2121 SLJIT_ASSERT(size
> 0 && size
< 16);
2123 buf
= (sljit_ub
*)ensure_buf(compiler
, 1 + size
);
2126 SLJIT_MEMMOVE(buf
, instruction
, size
);
2127 return SLJIT_SUCCESS
;
2130 /* --------------------------------------------------------------------- */
2131 /* Floating point operators */
2132 /* --------------------------------------------------------------------- */
2134 #if (defined SLJIT_SSE2 && SLJIT_SSE2)
2136 /* Alignment + 2 * 16 bytes. */
2137 static sljit_si sse2_data
[3 + (4 + 4) * 2];
2138 static sljit_si
*sse2_buffer
;
2140 static void init_compiler(void)
2142 sse2_buffer
= (sljit_si
*)(((sljit_uw
)sse2_data
+ 15) & ~0xf);
2143 /* Single precision constants. */
2144 sse2_buffer
[0] = 0x80000000;
2145 sse2_buffer
[4] = 0x7fffffff;
2146 /* Double precision constants. */
2148 sse2_buffer
[9] = 0x80000000;
2149 sse2_buffer
[12] = 0xffffffff;
2150 sse2_buffer
[13] = 0x7fffffff;
2155 SLJIT_API_FUNC_ATTRIBUTE sljit_si
sljit_is_fpu_available(void)
2157 #if (defined SLJIT_SSE2 && SLJIT_SSE2)
2158 #if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
2159 static sljit_si sse2_available
= -1;
2162 if (sse2_available
!= -1)
2163 return sse2_available
;
2169 "movl $0x1, %%eax\n"
2175 : "%eax", "%ecx", "%edx"
2177 #elif defined(_MSC_VER) || defined(__BORLANDC__)
2187 #error "SLJIT_DETECT_SSE2 is not implemented for this C compiler"
2189 sse2_available
= (features
>> 26) & 0x1;
2190 return sse2_available
;
2199 #if (defined SLJIT_SSE2 && SLJIT_SSE2)
2201 static sljit_si
emit_sse2(struct sljit_compiler
*compiler
, sljit_ub opcode
,
2202 sljit_si single
, sljit_si xmm1
, sljit_si xmm2
, sljit_sw xmm2w
)
2206 buf
= emit_x86_instruction(compiler
, 2 | (single
? EX86_PREF_F3
: EX86_PREF_F2
) | EX86_SSE2
, xmm1
, 0, xmm2
, xmm2w
);
2210 return SLJIT_SUCCESS
;
2213 static sljit_si
emit_sse2_logic(struct sljit_compiler
*compiler
, sljit_ub opcode
,
2214 sljit_si pref66
, sljit_si xmm1
, sljit_si xmm2
, sljit_sw xmm2w
)
2218 buf
= emit_x86_instruction(compiler
, 2 | (pref66
? EX86_PREF_66
: 0) | EX86_SSE2
, xmm1
, 0, xmm2
, xmm2w
);
2222 return SLJIT_SUCCESS
;
2225 static SLJIT_INLINE sljit_si
emit_sse2_load(struct sljit_compiler
*compiler
,
2226 sljit_si single
, sljit_si dst
, sljit_si src
, sljit_sw srcw
)
2228 return emit_sse2(compiler
, MOVSD_x_xm
, single
, dst
, src
, srcw
);
2231 static SLJIT_INLINE sljit_si
emit_sse2_store(struct sljit_compiler
*compiler
,
2232 sljit_si single
, sljit_si dst
, sljit_sw dstw
, sljit_si src
)
2234 return emit_sse2(compiler
, MOVSD_xm_x
, single
, src
, dst
, dstw
);
2237 SLJIT_API_FUNC_ATTRIBUTE sljit_si
sljit_emit_fop1(struct sljit_compiler
*compiler
, sljit_si op
,
2238 sljit_si dst
, sljit_sw dstw
,
2239 sljit_si src
, sljit_sw srcw
)
2244 check_sljit_emit_fop1(compiler
, op
, dst
, dstw
, src
, srcw
);
2246 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
2247 compiler
->mode32
= 1;
2250 if (GET_OPCODE(op
) == SLJIT_CMPD
) {
2251 compiler
->flags_saved
= 0;
2252 if (dst
<= SLJIT_FLOAT_REG6
)
2256 FAIL_IF(emit_sse2_load(compiler
, op
& SLJIT_SINGLE_OP
, dst_r
, dst
, dstw
));
2258 return emit_sse2_logic(compiler
, UCOMISD_x_xm
, !(op
& SLJIT_SINGLE_OP
), dst_r
, src
, srcw
);
2261 if (op
== SLJIT_MOVD
) {
2262 if (dst
<= SLJIT_FLOAT_REG6
)
2263 return emit_sse2_load(compiler
, op
& SLJIT_SINGLE_OP
, dst
, src
, srcw
);
2264 if (src
<= SLJIT_FLOAT_REG6
)
2265 return emit_sse2_store(compiler
, op
& SLJIT_SINGLE_OP
, dst
, dstw
, src
);
2266 FAIL_IF(emit_sse2_load(compiler
, op
& SLJIT_SINGLE_OP
, TMP_FREG
, src
, srcw
));
2267 return emit_sse2_store(compiler
, op
& SLJIT_SINGLE_OP
, dst
, dstw
, TMP_FREG
);
2270 if (dst
>= SLJIT_FLOAT_REG1
&& dst
<= SLJIT_FLOAT_REG6
) {
2273 FAIL_IF(emit_sse2_load(compiler
, op
& SLJIT_SINGLE_OP
, dst_r
, src
, srcw
));
2277 FAIL_IF(emit_sse2_load(compiler
, op
& SLJIT_SINGLE_OP
, dst_r
, src
, srcw
));
2280 switch (GET_OPCODE(op
)) {
2282 FAIL_IF(emit_sse2_logic(compiler
, XORPD_x_xm
, 1, dst_r
, SLJIT_MEM0(), (sljit_sw
)(op
& SLJIT_SINGLE_OP
? sse2_buffer
: sse2_buffer
+ 8)));
2286 FAIL_IF(emit_sse2_logic(compiler
, ANDPD_x_xm
, 1, dst_r
, SLJIT_MEM0(), (sljit_sw
)(op
& SLJIT_SINGLE_OP
? sse2_buffer
+ 4 : sse2_buffer
+ 12)));
2290 if (dst_r
== TMP_FREG
)
2291 return emit_sse2_store(compiler
, op
& SLJIT_SINGLE_OP
, dst
, dstw
, TMP_FREG
);
2292 return SLJIT_SUCCESS
;
2295 SLJIT_API_FUNC_ATTRIBUTE sljit_si
sljit_emit_fop2(struct sljit_compiler
*compiler
, sljit_si op
,
2296 sljit_si dst
, sljit_sw dstw
,
2297 sljit_si src1
, sljit_sw src1w
,
2298 sljit_si src2
, sljit_sw src2w
)
2303 check_sljit_emit_fop2(compiler
, op
, dst
, dstw
, src1
, src1w
, src2
, src2w
);
2305 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
2306 compiler
->mode32
= 1;
2309 if (dst
<= SLJIT_FLOAT_REG6
) {
2312 ; /* Do nothing here. */
2313 else if (dst
== src2
&& (op
== SLJIT_ADDD
|| op
== SLJIT_MULD
)) {
2314 /* Swap arguments. */
2318 else if (dst
!= src2
)
2319 FAIL_IF(emit_sse2_load(compiler
, op
& SLJIT_SINGLE_OP
, dst_r
, src1
, src1w
));
2322 FAIL_IF(emit_sse2_load(compiler
, op
& SLJIT_SINGLE_OP
, TMP_FREG
, src1
, src1w
));
2327 FAIL_IF(emit_sse2_load(compiler
, op
& SLJIT_SINGLE_OP
, TMP_FREG
, src1
, src1w
));
2330 switch (GET_OPCODE(op
)) {
2332 FAIL_IF(emit_sse2(compiler
, ADDSD_x_xm
, op
& SLJIT_SINGLE_OP
, dst_r
, src2
, src2w
));
2336 FAIL_IF(emit_sse2(compiler
, SUBSD_x_xm
, op
& SLJIT_SINGLE_OP
, dst_r
, src2
, src2w
));
2340 FAIL_IF(emit_sse2(compiler
, MULSD_x_xm
, op
& SLJIT_SINGLE_OP
, dst_r
, src2
, src2w
));
2344 FAIL_IF(emit_sse2(compiler
, DIVSD_x_xm
, op
& SLJIT_SINGLE_OP
, dst_r
, src2
, src2w
));
2348 if (dst_r
== TMP_FREG
)
2349 return emit_sse2_store(compiler
, op
& SLJIT_SINGLE_OP
, dst
, dstw
, TMP_FREG
);
2350 return SLJIT_SUCCESS
;
2355 SLJIT_API_FUNC_ATTRIBUTE sljit_si
sljit_emit_fop1(struct sljit_compiler
*compiler
, sljit_si op
,
2356 sljit_si dst
, sljit_sw dstw
,
2357 sljit_si src
, sljit_sw srcw
)
2360 /* Should cause an assertion fail. */
2361 check_sljit_emit_fop1(compiler
, op
, dst
, dstw
, src
, srcw
);
2362 compiler
->error
= SLJIT_ERR_UNSUPPORTED
;
2363 return SLJIT_ERR_UNSUPPORTED
;
2366 SLJIT_API_FUNC_ATTRIBUTE sljit_si
sljit_emit_fop2(struct sljit_compiler
*compiler
, sljit_si op
,
2367 sljit_si dst
, sljit_sw dstw
,
2368 sljit_si src1
, sljit_sw src1w
,
2369 sljit_si src2
, sljit_sw src2w
)
2372 /* Should cause an assertion fail. */
2373 check_sljit_emit_fop2(compiler
, op
, dst
, dstw
, src1
, src1w
, src2
, src2w
);
2374 compiler
->error
= SLJIT_ERR_UNSUPPORTED
;
2375 return SLJIT_ERR_UNSUPPORTED
;
2380 /* --------------------------------------------------------------------- */
2381 /* Conditional instructions */
2382 /* --------------------------------------------------------------------- */
2384 SLJIT_API_FUNC_ATTRIBUTE
struct sljit_label
* sljit_emit_label(struct sljit_compiler
*compiler
)
2387 struct sljit_label
*label
;
2390 check_sljit_emit_label(compiler
);
2392 /* We should restore the flags before the label,
2393 since other taken jumps has their own flags as well. */
2394 if (SLJIT_UNLIKELY(compiler
->flags_saved
))
2395 PTR_FAIL_IF(emit_restore_flags(compiler
, 0));
2397 if (compiler
->last_label
&& compiler
->last_label
->size
== compiler
->size
)
2398 return compiler
->last_label
;
2400 label
= (struct sljit_label
*)ensure_abuf(compiler
, sizeof(struct sljit_label
));
2401 PTR_FAIL_IF(!label
);
2402 set_label(label
, compiler
);
2404 buf
= (sljit_ub
*)ensure_buf(compiler
, 2);
2413 SLJIT_API_FUNC_ATTRIBUTE
struct sljit_jump
* sljit_emit_jump(struct sljit_compiler
*compiler
, sljit_si type
)
2416 struct sljit_jump
*jump
;
2419 check_sljit_emit_jump(compiler
, type
);
2421 if (SLJIT_UNLIKELY(compiler
->flags_saved
)) {
2422 if ((type
& 0xff) <= SLJIT_JUMP
)
2423 PTR_FAIL_IF(emit_restore_flags(compiler
, 0));
2424 compiler
->flags_saved
= 0;
2427 jump
= (struct sljit_jump
*)ensure_abuf(compiler
, sizeof(struct sljit_jump
));
2428 PTR_FAIL_IF_NULL(jump
);
2429 set_jump(jump
, compiler
, type
& SLJIT_REWRITABLE_JUMP
);
2432 if (type
>= SLJIT_CALL1
)
2433 PTR_FAIL_IF(call_with_args(compiler
, type
));
2435 /* Worst case size. */
2436 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
2437 compiler
->size
+= (type
>= SLJIT_JUMP
) ? 5 : 6;
2439 compiler
->size
+= (type
>= SLJIT_JUMP
) ? (10 + 3) : (2 + 10 + 3);
2442 buf
= (sljit_ub
*)ensure_buf(compiler
, 2);
2443 PTR_FAIL_IF_NULL(buf
);
2450 SLJIT_API_FUNC_ATTRIBUTE sljit_si
sljit_emit_ijump(struct sljit_compiler
*compiler
, sljit_si type
, sljit_si src
, sljit_sw srcw
)
2453 struct sljit_jump
*jump
;
2456 check_sljit_emit_ijump(compiler
, type
, src
, srcw
);
2457 ADJUST_LOCAL_OFFSET(src
, srcw
);
2459 CHECK_EXTRA_REGS(src
, srcw
, (void)0);
2461 if (SLJIT_UNLIKELY(compiler
->flags_saved
)) {
2462 if (type
<= SLJIT_JUMP
)
2463 FAIL_IF(emit_restore_flags(compiler
, 0));
2464 compiler
->flags_saved
= 0;
2467 if (type
>= SLJIT_CALL1
) {
2468 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
2469 #if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
2470 if (src
== SLJIT_TEMPORARY_REG3
) {
2471 EMIT_MOV(compiler
, TMP_REGISTER
, 0, src
, 0);
2474 if (src
== SLJIT_MEM1(SLJIT_LOCALS_REG
) && type
>= SLJIT_CALL3
)
2475 srcw
+= sizeof(sljit_sw
);
2477 if (src
== SLJIT_MEM1(SLJIT_LOCALS_REG
))
2478 srcw
+= sizeof(sljit_sw
) * (type
- SLJIT_CALL0
);
2481 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && defined(_WIN64)
2482 if (src
== SLJIT_TEMPORARY_REG3
) {
2483 EMIT_MOV(compiler
, TMP_REGISTER
, 0, src
, 0);
2487 FAIL_IF(call_with_args(compiler
, type
));
2490 if (src
== SLJIT_IMM
) {
2491 jump
= (struct sljit_jump
*)ensure_abuf(compiler
, sizeof(struct sljit_jump
));
2493 set_jump(jump
, compiler
, JUMP_ADDR
);
2494 jump
->u
.target
= srcw
;
2496 /* Worst case size. */
2497 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
2498 compiler
->size
+= 5;
2500 compiler
->size
+= 10 + 3;
2503 code
= (sljit_ub
*)ensure_buf(compiler
, 2);
2510 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
2511 /* REX_W is not necessary (src is not immediate). */
2512 compiler
->mode32
= 1;
2514 code
= emit_x86_instruction(compiler
, 1, 0, 0, src
, srcw
);
2517 *code
|= (type
>= SLJIT_FAST_CALL
) ? CALL_rm
: JMP_rm
;
2519 return SLJIT_SUCCESS
;
2522 SLJIT_API_FUNC_ATTRIBUTE sljit_si
sljit_emit_cond_value(struct sljit_compiler
*compiler
, sljit_si op
, sljit_si dst
, sljit_sw dstw
, sljit_si type
)
2525 sljit_ub cond_set
= 0;
2526 sljit_si dst_save
= dst
;
2527 sljit_sw dstw_save
= dstw
;
2528 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
2533 check_sljit_emit_cond_value(compiler
, op
, dst
, dstw
, type
);
2535 if (dst
== SLJIT_UNUSED
)
2536 return SLJIT_SUCCESS
;
2538 ADJUST_LOCAL_OFFSET(dst
, dstw
);
2539 CHECK_EXTRA_REGS(dst
, dstw
, (void)0);
2540 if (SLJIT_UNLIKELY(compiler
->flags_saved
))
2541 FAIL_IF(emit_restore_flags(compiler
, op
& SLJIT_KEEP_FLAGS
));
2545 case SLJIT_C_FLOAT_EQUAL
:
2546 cond_set
= 0x94 /* sete */;
2549 case SLJIT_C_NOT_EQUAL
:
2550 case SLJIT_C_FLOAT_NOT_EQUAL
:
2551 cond_set
= 0x95 /* setne */;
2555 case SLJIT_C_FLOAT_LESS
:
2556 cond_set
= 0x92 /* setnae */;
2559 case SLJIT_C_GREATER_EQUAL
:
2560 case SLJIT_C_FLOAT_GREATER_EQUAL
:
2561 cond_set
= 0x93 /* setnb */;
2564 case SLJIT_C_GREATER
:
2565 case SLJIT_C_FLOAT_GREATER
:
2566 cond_set
= 0x97 /* seta */;
2569 case SLJIT_C_LESS_EQUAL
:
2570 case SLJIT_C_FLOAT_LESS_EQUAL
:
2571 cond_set
= 0x96 /* setbe */;
2574 case SLJIT_C_SIG_LESS
:
2575 cond_set
= 0x9c /* setnge */;
2578 case SLJIT_C_SIG_GREATER_EQUAL
:
2579 cond_set
= 0x9d /* setnl */;
2582 case SLJIT_C_SIG_GREATER
:
2583 cond_set
= 0x9f /* setg */;
2586 case SLJIT_C_SIG_LESS_EQUAL
:
2587 cond_set
= 0x9e /* setle */;
2590 case SLJIT_C_OVERFLOW
:
2591 case SLJIT_C_MUL_OVERFLOW
:
2592 cond_set
= 0x90 /* seto */;
2595 case SLJIT_C_NOT_OVERFLOW
:
2596 case SLJIT_C_MUL_NOT_OVERFLOW
:
2597 cond_set
= 0x91 /* setno */;
2600 case SLJIT_C_FLOAT_UNORDERED
:
2601 cond_set
= 0x9a /* setp */;
2604 case SLJIT_C_FLOAT_ORDERED
:
2605 cond_set
= 0x9b /* setpo */;
2609 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
2610 reg
= (op
== SLJIT_MOV
&& dst
>= SLJIT_TEMPORARY_REG1
&& dst
<= SLJIT_NO_REGISTERS
) ? dst
: TMP_REGISTER
;
2612 buf
= (sljit_ub
*)ensure_buf(compiler
, 1 + 4 + 4);
2615 /* Set low register to conditional flag. */
2616 *buf
++ = (reg_map
[reg
] <= 7) ? REX
: REX_B
;
2619 *buf
++ = MOD_REG
| reg_lmap
[reg
];
2620 *buf
++ = REX_W
| (reg_map
[reg
] <= 7 ? 0 : (REX_B
| REX_R
));
2622 *buf
++ = MOVZX_r_rm8
;
2623 *buf
= MOD_REG
| (reg_lmap
[reg
] << 3) | reg_lmap
[reg
];
2625 if (reg
== TMP_REGISTER
) {
2626 if (op
== SLJIT_MOV
) {
2627 compiler
->mode32
= 0;
2628 EMIT_MOV(compiler
, dst
, dstw
, TMP_REGISTER
, 0);
2631 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
2632 compiler
->skip_checks
= 1;
2634 return sljit_emit_op2(compiler
, op
, dst_save
, dstw_save
, dst_save
, dstw_save
, TMP_REGISTER
, 0);
2638 if (op
== SLJIT_MOV
) {
2639 if (dst
>= SLJIT_TEMPORARY_REG1
&& dst
<= SLJIT_TEMPORARY_REG3
) {
2640 buf
= (sljit_ub
*)ensure_buf(compiler
, 1 + 3 + 3);
2643 /* Set low byte to conditional flag. */
2646 *buf
++ = MOD_REG
| reg_map
[dst
];
2649 *buf
++ = MOVZX_r_rm8
;
2650 *buf
= MOD_REG
| (reg_map
[dst
] << 3) | reg_map
[dst
];
2653 EMIT_MOV(compiler
, TMP_REGISTER
, 0, SLJIT_TEMPORARY_REG1
, 0);
2655 buf
= (sljit_ub
*)ensure_buf(compiler
, 1 + 3 + 3);
2658 /* Set al to conditional flag. */
2664 *buf
++ = MOVZX_r_rm8
;
2665 if (dst
>= SLJIT_SAVED_REG1
&& dst
<= SLJIT_NO_REGISTERS
)
2666 *buf
= MOD_REG
| (reg_map
[dst
] << 3);
2669 EMIT_MOV(compiler
, dst
, dstw
, SLJIT_TEMPORARY_REG1
, 0);
2672 EMIT_MOV(compiler
, SLJIT_TEMPORARY_REG1
, 0, TMP_REGISTER
, 0);
2676 if (dst
>= SLJIT_TEMPORARY_REG1
&& dst
<= SLJIT_TEMPORARY_REG3
) {
2677 EMIT_MOV(compiler
, TMP_REGISTER
, 0, dst
, 0);
2678 buf
= (sljit_ub
*)ensure_buf(compiler
, 1 + 3);
2684 *buf
++ = MOD_REG
| reg_map
[dst
];
2687 EMIT_MOV(compiler
, TMP_REGISTER
, 0, SLJIT_TEMPORARY_REG1
, 0);
2689 buf
= (sljit_ub
*)ensure_buf(compiler
, 1 + 3 + 3 + 1);
2691 INC_SIZE(3 + 3 + 1);
2692 /* Set al to conditional flag. */
2698 *buf
++ = MOVZX_r_rm8
;
2701 *buf
++ = XCHG_EAX_r
+ reg_map
[TMP_REGISTER
];
2703 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
2704 compiler
->skip_checks
= 1;
2706 return sljit_emit_op2(compiler
, op
, dst_save
, dstw_save
, dst_save
, dstw_save
, TMP_REGISTER
, 0);
2710 return SLJIT_SUCCESS
;
2713 SLJIT_API_FUNC_ATTRIBUTE sljit_si
sljit_get_local_base(struct sljit_compiler
*compiler
, sljit_si dst
, sljit_sw dstw
, sljit_sw offset
)
2716 check_sljit_get_local_base(compiler
, dst
, dstw
, offset
);
2717 ADJUST_LOCAL_OFFSET(dst
, dstw
);
2719 CHECK_EXTRA_REGS(dst
, dstw
, (void)0);
2721 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
2722 compiler
->mode32
= 0;
2725 ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_LOCALS_REG
), offset
);
2727 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
2728 if (NOT_HALFWORD(offset
)) {
2729 FAIL_IF(emit_load_imm64(compiler
, TMP_REGISTER
, offset
));
2730 #if (defined SLJIT_DEBUG && SLJIT_DEBUG)
2731 SLJIT_ASSERT(emit_lea_binary(compiler
, dst
, dstw
, SLJIT_LOCALS_REG
, 0, TMP_REGISTER
, 0) != SLJIT_ERR_UNSUPPORTED
);
2732 return compiler
->error
;
2734 return emit_lea_binary(compiler
, dst
, dstw
, SLJIT_LOCALS_REG
, 0, TMP_REGISTER
, 0);
2740 return emit_lea_binary(compiler
, dst
, dstw
, SLJIT_LOCALS_REG
, 0, SLJIT_IMM
, offset
);
2741 return emit_mov(compiler
, dst
, dstw
, SLJIT_LOCALS_REG
, 0);
2744 SLJIT_API_FUNC_ATTRIBUTE
struct sljit_const
* sljit_emit_const(struct sljit_compiler
*compiler
, sljit_si dst
, sljit_sw dstw
, sljit_sw init_value
)
2747 struct sljit_const
*const_
;
2748 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
2753 check_sljit_emit_const(compiler
, dst
, dstw
, init_value
);
2754 ADJUST_LOCAL_OFFSET(dst
, dstw
);
2756 CHECK_EXTRA_REGS(dst
, dstw
, (void)0);
2758 const_
= (struct sljit_const
*)ensure_abuf(compiler
, sizeof(struct sljit_const
));
2759 PTR_FAIL_IF(!const_
);
2760 set_const(const_
, compiler
);
2762 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
2763 compiler
->mode32
= 0;
2764 reg
= (dst
>= SLJIT_TEMPORARY_REG1
&& dst
<= SLJIT_NO_REGISTERS
) ? dst
: TMP_REGISTER
;
2766 if (emit_load_imm64(compiler
, reg
, init_value
))
2769 if (dst
== SLJIT_UNUSED
)
2772 if (emit_mov(compiler
, dst
, dstw
, SLJIT_IMM
, init_value
))
2776 buf
= (sljit_ub
*)ensure_buf(compiler
, 2);
2782 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
2783 if (reg
== TMP_REGISTER
&& dst
!= SLJIT_UNUSED
)
2784 if (emit_mov(compiler
, dst
, dstw
, TMP_REGISTER
, 0))
2791 SLJIT_API_FUNC_ATTRIBUTE
void sljit_set_jump_addr(sljit_uw addr
, sljit_uw new_addr
)
2793 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
2794 *(sljit_sw
*)addr
= new_addr
- (addr
+ 4);
2796 *(sljit_uw
*)addr
= new_addr
;
2800 SLJIT_API_FUNC_ATTRIBUTE
void sljit_set_const(sljit_uw addr
, sljit_sw new_constant
)
2802 *(sljit_sw
*)addr
= new_constant
;