version 1.1.1.2, 2012/02/21 23:50:25
|
version 1.1.1.3, 2012/10/09 09:19:18
|
Line 104 static SLJIT_CONST sljit_ub reg_lmap[SLJIT_NO_REGISTER
|
Line 104 static SLJIT_CONST sljit_ub reg_lmap[SLJIT_NO_REGISTER
|
#else |
#else |
/* 1st passed in rcx, 2nd argument passed in rdx, 3rd in r8. */ |
/* 1st passed in rcx, 2nd argument passed in rdx, 3rd in r8. */ |
static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 4] = { |
static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 4] = { |
0, 0, 2, 1, 11, 13, 3, 6, 7, 14, 12, 15, 10, 8, 9 | 0, 0, 2, 1, 11, 13, 3, 6, 7, 14, 15, 4, 10, 8, 9 |
}; |
}; |
/* low-map. reg_map & 0x7. */ |
/* low-map. reg_map & 0x7. */ |
static SLJIT_CONST sljit_ub reg_lmap[SLJIT_NO_REGISTERS + 4] = { |
static SLJIT_CONST sljit_ub reg_lmap[SLJIT_NO_REGISTERS + 4] = { |
0, 0, 2, 1, 3, 5, 3, 6, 7, 6, 4, 7, 2, 0, 1 | 0, 0, 2, 1, 3, 5, 3, 6, 7, 6, 7, 4, 2, 0, 1 |
}; |
}; |
#endif |
#endif |
|
|
Line 415 static SLJIT_INLINE int emit_save_flags(struct sljit_c
|
Line 415 static SLJIT_INLINE int emit_save_flags(struct sljit_c
|
buf = (sljit_ub*)ensure_buf(compiler, 1 + 5); |
buf = (sljit_ub*)ensure_buf(compiler, 1 + 5); |
FAIL_IF(!buf); |
FAIL_IF(!buf); |
INC_SIZE(5); |
INC_SIZE(5); |
*buf++ = 0x9c; /* pushfd */ |
|
#else |
#else |
buf = (sljit_ub*)ensure_buf(compiler, 1 + 6); |
buf = (sljit_ub*)ensure_buf(compiler, 1 + 6); |
FAIL_IF(!buf); |
FAIL_IF(!buf); |
INC_SIZE(6); |
INC_SIZE(6); |
*buf++ = 0x9c; /* pushfq */ | *buf++ = REX_W; |
*buf++ = 0x48; | |
#endif |
#endif |
*buf++ = 0x8d; /* lea esp/rsp, [esp/rsp + sizeof(sljit_w)] */ |
*buf++ = 0x8d; /* lea esp/rsp, [esp/rsp + sizeof(sljit_w)] */ |
*buf++ = 0x64; |
*buf++ = 0x64; |
*buf++ = 0x24; |
*buf++ = 0x24; |
*buf++ = sizeof(sljit_w); | *buf++ = (sljit_ub)sizeof(sljit_w); |
| *buf++ = 0x9c; /* pushfd / pushfq */ |
compiler->flags_saved = 1; |
compiler->flags_saved = 1; |
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
} |
} |
Line 439 static SLJIT_INLINE int emit_restore_flags(struct slji
|
Line 438 static SLJIT_INLINE int emit_restore_flags(struct slji
|
buf = (sljit_ub*)ensure_buf(compiler, 1 + 5); |
buf = (sljit_ub*)ensure_buf(compiler, 1 + 5); |
FAIL_IF(!buf); |
FAIL_IF(!buf); |
INC_SIZE(5); |
INC_SIZE(5); |
|
*buf++ = 0x9d; /* popfd */ |
#else |
#else |
buf = (sljit_ub*)ensure_buf(compiler, 1 + 6); |
buf = (sljit_ub*)ensure_buf(compiler, 1 + 6); |
FAIL_IF(!buf); |
FAIL_IF(!buf); |
INC_SIZE(6); |
INC_SIZE(6); |
*buf++ = 0x48; | *buf++ = 0x9d; /* popfq */ |
| *buf++ = REX_W; |
#endif |
#endif |
*buf++ = 0x8d; /* lea esp/rsp, [esp/rsp - sizeof(sljit_w)] */ |
*buf++ = 0x8d; /* lea esp/rsp, [esp/rsp - sizeof(sljit_w)] */ |
*buf++ = 0x64; |
*buf++ = 0x64; |
*buf++ = 0x24; |
*buf++ = 0x24; |
*buf++ = (sljit_ub)-(int)sizeof(sljit_w); |
*buf++ = (sljit_ub)-(int)sizeof(sljit_w); |
*buf++ = 0x9d; /* popfd / popfq */ |
|
compiler->flags_saved = keep_flags; |
compiler->flags_saved = keep_flags; |
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
} |
} |
Line 457 static SLJIT_INLINE int emit_restore_flags(struct slji
|
Line 457 static SLJIT_INLINE int emit_restore_flags(struct slji
|
#ifdef _WIN32 |
#ifdef _WIN32 |
#include <malloc.h> |
#include <malloc.h> |
|
|
static void SLJIT_CALL sljit_touch_stack(sljit_w local_size) | static void SLJIT_CALL sljit_grow_stack(sljit_w local_size) |
{ |
{ |
/* Workaround for calling _chkstk. */ | /* Workaround for calling the internal _chkstk() function on Windows. |
| This function touches all 4k pages belongs to the requested stack space, |
| which size is passed in local_size. This is necessary on Windows where |
| the stack can only grow in 4k steps. However, this function just burn |
| CPU cycles if the stack is large enough, but you don't know it in advance. |
| I think this is a bad design even if it has some reasons. */ |
alloca(local_size); |
alloca(local_size); |
} |
} |
|
|
#endif |
#endif |
|
|
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) |
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) |
Line 1050 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct slj
|
Line 1056 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct slj
|
|
|
CHECK_ERROR(); |
CHECK_ERROR(); |
check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw); |
check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw); |
|
ADJUST_LOCAL_OFFSET(dst, dstw); |
|
ADJUST_LOCAL_OFFSET(src, srcw); |
|
|
|
CHECK_EXTRA_REGS(dst, dstw, dst_is_ereg = 1); |
|
CHECK_EXTRA_REGS(src, srcw, src_is_ereg = 1); |
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) |
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) |
compiler->mode32 = op & SLJIT_INT_OP; |
compiler->mode32 = op & SLJIT_INT_OP; |
#endif |
#endif |
CHECK_EXTRA_REGS(dst, dstw, dst_is_ereg = 1); |
|
CHECK_EXTRA_REGS(src, srcw, src_is_ereg = 1); |
|
|
|
if (GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_MOVU_SI) { |
if (GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_MOVU_SI) { |
op = GET_OPCODE(op); |
op = GET_OPCODE(op); |
Line 1558 static int emit_lea_binary(struct sljit_compiler *comp
|
Line 1566 static int emit_lea_binary(struct sljit_compiler *comp
|
dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REGISTER; |
dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REGISTER; |
|
|
if (src1 >= SLJIT_TEMPORARY_REG1 && src1 <= SLJIT_NO_REGISTERS) { |
if (src1 >= SLJIT_TEMPORARY_REG1 && src1 <= SLJIT_NO_REGISTERS) { |
if (src2 >= SLJIT_TEMPORARY_REG1 && src2 <= SLJIT_NO_REGISTERS) { | if ((src2 >= SLJIT_TEMPORARY_REG1 && src2 <= SLJIT_NO_REGISTERS) || src2 == TMP_REGISTER) { |
/* It is not possible to be both SLJIT_LOCALS_REG. */ | code = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM2(src1, src2), 0); |
if (src1 != SLJIT_LOCALS_REG || src2 != SLJIT_LOCALS_REG) { | FAIL_IF(!code); |
code = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM2(src1, src2), 0); | *code = 0x8d; |
FAIL_IF(!code); | done = 1; |
*code = 0x8d; | |
done = 1; | |
} | |
} |
} |
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) |
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) |
if ((src2 & SLJIT_IMM) && (compiler->mode32 || IS_HALFWORD(src2w))) { |
if ((src2 & SLJIT_IMM) && (compiler->mode32 || IS_HALFWORD(src2w))) { |
Line 1831 static int emit_shift(struct sljit_compiler *compiler,
|
Line 1836 static int emit_shift(struct sljit_compiler *compiler,
|
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) |
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) |
EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_PREF_SHIFT_REG, 0); |
EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_PREF_SHIFT_REG, 0); |
#else |
#else |
/* [esp - 4] is reserved for eflags. */ | /* [esp+0] contains the flags. */ |
EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), -(int)(2 * sizeof(sljit_w)), SLJIT_PREF_SHIFT_REG, 0); | EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), sizeof(sljit_w), SLJIT_PREF_SHIFT_REG, 0); |
#endif |
#endif |
EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w); |
EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w); |
code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0); |
code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0); |
Line 1841 static int emit_shift(struct sljit_compiler *compiler,
|
Line 1846 static int emit_shift(struct sljit_compiler *compiler,
|
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) |
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) |
EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG2, 0); |
EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG2, 0); |
#else |
#else |
/* [esp - 4] is reserved for eflags. */ | EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), sizeof(sljit_w)); |
EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), -(int)(2 * sizeof(sljit_w))); | |
#endif |
#endif |
EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0); |
EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0); |
} |
} |
Line 1892 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct slj
|
Line 1896 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct slj
|
{ |
{ |
CHECK_ERROR(); |
CHECK_ERROR(); |
check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w); |
check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w); |
|
ADJUST_LOCAL_OFFSET(dst, dstw); |
|
ADJUST_LOCAL_OFFSET(src1, src1w); |
|
ADJUST_LOCAL_OFFSET(src2, src2w); |
|
|
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) |
|
compiler->mode32 = op & SLJIT_INT_OP; |
|
#endif |
|
CHECK_EXTRA_REGS(dst, dstw, (void)0); |
CHECK_EXTRA_REGS(dst, dstw, (void)0); |
CHECK_EXTRA_REGS(src1, src1w, (void)0); |
CHECK_EXTRA_REGS(src1, src1w, (void)0); |
CHECK_EXTRA_REGS(src2, src2w, (void)0); |
CHECK_EXTRA_REGS(src2, src2w, (void)0); |
|
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) |
|
compiler->mode32 = op & SLJIT_INT_OP; |
|
#endif |
|
|
if (GET_OPCODE(op) >= SLJIT_MUL) { |
if (GET_OPCODE(op) >= SLJIT_MUL) { |
if (SLJIT_UNLIKELY(GET_FLAGS(op))) |
if (SLJIT_UNLIKELY(GET_FLAGS(op))) |
Line 1912 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct slj
|
Line 1919 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct slj
|
if (!GET_FLAGS(op)) { |
if (!GET_FLAGS(op)) { |
if (emit_lea_binary(compiler, dst, dstw, src1, src1w, src2, src2w) != SLJIT_ERR_UNSUPPORTED) |
if (emit_lea_binary(compiler, dst, dstw, src1, src1w, src2, src2w) != SLJIT_ERR_UNSUPPORTED) |
return compiler->error; |
return compiler->error; |
} | } |
else |
else |
compiler->flags_saved = 0; |
compiler->flags_saved = 0; |
if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS) && !compiler->flags_saved) |
if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS) && !compiler->flags_saved) |
Line 2008 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(stru
|
Line 2015 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(stru
|
/* Floating point operators */ |
/* Floating point operators */ |
/* --------------------------------------------------------------------- */ |
/* --------------------------------------------------------------------- */ |
|
|
#if (defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO) |
|
static int sse2_available = 0; |
|
#endif |
|
|
|
#if (defined SLJIT_SSE2 && SLJIT_SSE2) |
#if (defined SLJIT_SSE2 && SLJIT_SSE2) |
|
|
/* Alignment + 2 * 16 bytes. */ |
/* Alignment + 2 * 16 bytes. */ |
Line 2020 static sljit_i *sse2_buffer;
|
Line 2023 static sljit_i *sse2_buffer;
|
|
|
static void init_compiler() |
static void init_compiler() |
{ |
{ |
#if (defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO) |
|
int features = 0; |
|
#endif |
|
|
|
sse2_buffer = (sljit_i*)(((sljit_uw)sse2_data + 15) & ~0xf); |
sse2_buffer = (sljit_i*)(((sljit_uw)sse2_data + 15) & ~0xf); |
sse2_buffer[0] = 0; |
sse2_buffer[0] = 0; |
sse2_buffer[1] = 0x80000000; |
sse2_buffer[1] = 0x80000000; |
sse2_buffer[4] = 0xffffffff; |
sse2_buffer[4] = 0xffffffff; |
sse2_buffer[5] = 0x7fffffff; |
sse2_buffer[5] = 0x7fffffff; |
|
} |
|
|
#if (defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO) | #endif |
| |
| SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void) |
| { |
| #if (defined SLJIT_SSE2 && SLJIT_SSE2) |
| #if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2) |
| static int sse2_available = -1; |
| int features; |
| |
| if (sse2_available != -1) |
| return sse2_available; |
| |
#ifdef __GNUC__ |
#ifdef __GNUC__ |
/* AT&T syntax. */ |
/* AT&T syntax. */ |
asm ( |
asm ( |
Line 2053 static void init_compiler()
|
Line 2064 static void init_compiler()
|
mov features, edx |
mov features, edx |
} |
} |
#else |
#else |
#error "SLJIT_SSE2_AUTO is not implemented for this C compiler" | #error "SLJIT_DETECT_SSE2 is not implemented for this C compiler" |
#endif |
#endif |
sse2_available = (features >> 26) & 0x1; |
sse2_available = (features >> 26) & 0x1; |
|
return sse2_available; |
|
#else |
|
return 1; |
#endif |
#endif |
} | #else |
| return 0; |
#endif |
#endif |
|
|
SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void) |
|
{ |
|
/* Always available. */ |
|
return 1; |
|
} |
} |
|
|
#if (defined SLJIT_SSE2 && SLJIT_SSE2) |
#if (defined SLJIT_SSE2 && SLJIT_SSE2) |
Line 2105 static SLJIT_INLINE int emit_sse2_store(struct sljit_c
|
Line 2114 static SLJIT_INLINE int emit_sse2_store(struct sljit_c
|
return emit_sse2(compiler, 0x11, src, dst, dstw); |
return emit_sse2(compiler, 0x11, src, dst, dstw); |
} |
} |
|
|
#if !(defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO) |
|
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, int op, |
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, int op, |
#else |
|
static int sljit_emit_sse2_fop1(struct sljit_compiler *compiler, int op, |
|
#endif |
|
int dst, sljit_w dstw, |
int dst, sljit_w dstw, |
int src, sljit_w srcw) |
int src, sljit_w srcw) |
{ |
{ |
Line 2167 static int sljit_emit_sse2_fop1(struct sljit_compiler
|
Line 2172 static int sljit_emit_sse2_fop1(struct sljit_compiler
|
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
} |
} |
|
|
#if !(defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO) |
|
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, int op, |
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, int op, |
#else |
|
static int sljit_emit_sse2_fop2(struct sljit_compiler *compiler, int op, |
|
#endif |
|
int dst, sljit_w dstw, |
int dst, sljit_w dstw, |
int src1, sljit_w src1w, |
int src1, sljit_w src1w, |
int src2, sljit_w src2w) |
int src2, sljit_w src2w) |
Line 2229 static int sljit_emit_sse2_fop2(struct sljit_compiler
|
Line 2230 static int sljit_emit_sse2_fop2(struct sljit_compiler
|
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
} |
} |
|
|
#endif | #else |
|
|
#if (defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO) || !(defined SLJIT_SSE2 && SLJIT_SSE2) |
|
|
|
static int emit_fld(struct sljit_compiler *compiler, |
|
int src, sljit_w srcw) |
|
{ |
|
sljit_ub *buf; |
|
|
|
if (src >= SLJIT_FLOAT_REG1 && src <= SLJIT_FLOAT_REG4) { |
|
buf = (sljit_ub*)ensure_buf(compiler, 1 + 2); |
|
FAIL_IF(!buf); |
|
INC_SIZE(2); |
|
*buf++ = 0xd9; |
|
*buf = 0xc0 + src - 1; |
|
return SLJIT_SUCCESS; |
|
} |
|
|
|
buf = emit_x86_instruction(compiler, 1, 0, 0, src, srcw); |
|
FAIL_IF(!buf); |
|
*buf = 0xdd; |
|
return SLJIT_SUCCESS; |
|
} |
|
|
|
static int emit_fop(struct sljit_compiler *compiler, |
|
sljit_ub st_arg, sljit_ub st_arg2, |
|
sljit_ub m64fp_arg, sljit_ub m64fp_arg2, |
|
int src, sljit_w srcw) |
|
{ |
|
sljit_ub *buf; |
|
|
|
if (src >= SLJIT_FLOAT_REG1 && src <= SLJIT_FLOAT_REG4) { |
|
buf = (sljit_ub*)ensure_buf(compiler, 1 + 2); |
|
FAIL_IF(!buf); |
|
INC_SIZE(2); |
|
*buf++ = st_arg; |
|
*buf = st_arg2 + src; |
|
return SLJIT_SUCCESS; |
|
} |
|
|
|
buf = emit_x86_instruction(compiler, 1, 0, 0, src, srcw); |
|
FAIL_IF(!buf); |
|
*buf++ = m64fp_arg; |
|
*buf |= m64fp_arg2; |
|
return SLJIT_SUCCESS; |
|
} |
|
|
|
static int emit_fop_regs(struct sljit_compiler *compiler, |
|
sljit_ub st_arg, sljit_ub st_arg2, |
|
int src) |
|
{ |
|
sljit_ub *buf; |
|
|
|
buf = (sljit_ub*)ensure_buf(compiler, 1 + 2); |
|
FAIL_IF(!buf); |
|
INC_SIZE(2); |
|
*buf++ = st_arg; |
|
*buf = st_arg2 + src; |
|
return SLJIT_SUCCESS; |
|
} |
|
|
|
#if !(defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO) |
|
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, int op, |
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, int op, |
#else |
|
static int sljit_emit_fpu_fop1(struct sljit_compiler *compiler, int op, |
|
#endif |
|
int dst, sljit_w dstw, |
int dst, sljit_w dstw, |
int src, sljit_w srcw) |
int src, sljit_w srcw) |
{ |
{ |
#if !(defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) |
|
sljit_ub *buf; |
|
#endif |
|
|
|
CHECK_ERROR(); |
CHECK_ERROR(); |
|
/* Should cause an assertion fail. */ |
check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw); |
check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw); |
| compiler->error = SLJIT_ERR_UNSUPPORTED; |
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) | return SLJIT_ERR_UNSUPPORTED; |
compiler->mode32 = 1; | |
#endif | |
| |
if (GET_OPCODE(op) == SLJIT_FCMP) { | |
compiler->flags_saved = 0; | |
#if !(defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) | |
FAIL_IF(emit_fld(compiler, dst, dstw)); | |
FAIL_IF(emit_fop(compiler, 0xd8, 0xd8, 0xdc, 0x3 << 3, src, srcw)); | |
| |
/* Copy flags. */ | |
EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_TEMPORARY_REG1, 0); | |
buf = (sljit_ub*)ensure_buf(compiler, 1 + 3); | |
FAIL_IF(!buf); | |
INC_SIZE(3); | |
*buf++ = 0xdf; | |
*buf++ = 0xe0; | |
/* Note: lahf is not supported on all x86-64 architectures. */ | |
*buf++ = 0x9e; | |
EMIT_MOV(compiler, SLJIT_TEMPORARY_REG1, 0, TMP_REGISTER, 0); | |
#else | |
if (src >= SLJIT_FLOAT_REG1 && src <= SLJIT_FLOAT_REG4) { | |
FAIL_IF(emit_fld(compiler, dst, dstw)); | |
FAIL_IF(emit_fop_regs(compiler, 0xdf, 0xe8, src)); | |
} else { | |
FAIL_IF(emit_fld(compiler, src, srcw)); | |
FAIL_IF(emit_fld(compiler, dst + ((dst >= SLJIT_FLOAT_REG1 && dst <= SLJIT_FLOAT_REG4) ? 1 : 0), dstw)); | |
FAIL_IF(emit_fop_regs(compiler, 0xdf, 0xe8, src)); | |
FAIL_IF(emit_fop_regs(compiler, 0xdd, 0xd8, 0)); | |
} | |
#endif | |
return SLJIT_SUCCESS; | |
} | |
| |
FAIL_IF(emit_fld(compiler, src, srcw)); | |
| |
switch (op) { | |
case SLJIT_FNEG: | |
FAIL_IF(emit_fop_regs(compiler, 0xd9, 0xe0, 0)); | |
break; | |
case SLJIT_FABS: | |
FAIL_IF(emit_fop_regs(compiler, 0xd9, 0xe1, 0)); | |
break; | |
} | |
| |
FAIL_IF(emit_fop(compiler, 0xdd, 0xd8, 0xdd, 0x3 << 3, dst, dstw)); | |
| |
return SLJIT_SUCCESS; | |
} |
} |
|
|
#if !(defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO) |
|
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, int op, |
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, int op, |
#else |
|
static int sljit_emit_fpu_fop2(struct sljit_compiler *compiler, int op, |
|
#endif |
|
int dst, sljit_w dstw, |
int dst, sljit_w dstw, |
int src1, sljit_w src1w, |
int src1, sljit_w src1w, |
int src2, sljit_w src2w) |
int src2, sljit_w src2w) |
{ |
{ |
CHECK_ERROR(); |
CHECK_ERROR(); |
|
/* Should cause an assertion fail. */ |
check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w); |
check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w); |
| compiler->error = SLJIT_ERR_UNSUPPORTED; |
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) | return SLJIT_ERR_UNSUPPORTED; |
compiler->mode32 = 1; | |
#endif | |
| |
if (src1 >= SLJIT_FLOAT_REG1 && src1 <= SLJIT_FLOAT_REG4 && dst == src1) { | |
FAIL_IF(emit_fld(compiler, src2, src2w)); | |
| |
switch (op) { | |
case SLJIT_FADD: | |
FAIL_IF(emit_fop_regs(compiler, 0xde, 0xc0, src1)); | |
break; | |
case SLJIT_FSUB: | |
FAIL_IF(emit_fop_regs(compiler, 0xde, 0xe8, src1)); | |
break; | |
case SLJIT_FMUL: | |
FAIL_IF(emit_fop_regs(compiler, 0xde, 0xc8, src1)); | |
break; | |
case SLJIT_FDIV: | |
FAIL_IF(emit_fop_regs(compiler, 0xde, 0xf8, src1)); | |
break; | |
} | |
return SLJIT_SUCCESS; | |
} | |
| |
FAIL_IF(emit_fld(compiler, src1, src1w)); | |
| |
if (src2 >= SLJIT_FLOAT_REG1 && src2 <= SLJIT_FLOAT_REG4 && dst == src2) { | |
switch (op) { | |
case SLJIT_FADD: | |
FAIL_IF(emit_fop_regs(compiler, 0xde, 0xc0, src2)); | |
break; | |
case SLJIT_FSUB: | |
FAIL_IF(emit_fop_regs(compiler, 0xde, 0xe0, src2)); | |
break; | |
case SLJIT_FMUL: | |
FAIL_IF(emit_fop_regs(compiler, 0xde, 0xc8, src2)); | |
break; | |
case SLJIT_FDIV: | |
FAIL_IF(emit_fop_regs(compiler, 0xde, 0xf0, src2)); | |
break; | |
} | |
return SLJIT_SUCCESS; | |
} | |
| |
switch (op) { | |
case SLJIT_FADD: | |
FAIL_IF(emit_fop(compiler, 0xd8, 0xc0, 0xdc, 0x0 << 3, src2, src2w)); | |
break; | |
case SLJIT_FSUB: | |
FAIL_IF(emit_fop(compiler, 0xd8, 0xe0, 0xdc, 0x4 << 3, src2, src2w)); | |
break; | |
case SLJIT_FMUL: | |
FAIL_IF(emit_fop(compiler, 0xd8, 0xc8, 0xdc, 0x1 << 3, src2, src2w)); | |
break; | |
case SLJIT_FDIV: | |
FAIL_IF(emit_fop(compiler, 0xd8, 0xf0, 0xdc, 0x6 << 3, src2, src2w)); | |
break; | |
} | |
| |
FAIL_IF(emit_fop(compiler, 0xdd, 0xd8, 0xdd, 0x3 << 3, dst, dstw)); | |
| |
return SLJIT_SUCCESS; | |
} |
} |
#endif |
|
|
|
#if (defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO) |
|
|
|
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, int op, |
|
int dst, sljit_w dstw, |
|
int src, sljit_w srcw) |
|
{ |
|
if (sse2_available) |
|
return sljit_emit_sse2_fop1(compiler, op, dst, dstw, src, srcw); |
|
else |
|
return sljit_emit_fpu_fop1(compiler, op, dst, dstw, src, srcw); |
|
} |
|
|
|
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, int op, |
|
int dst, sljit_w dstw, |
|
int src1, sljit_w src1w, |
|
int src2, sljit_w src2w) |
|
{ |
|
if (sse2_available) |
|
return sljit_emit_sse2_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w); |
|
else |
|
return sljit_emit_fpu_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w); |
|
} |
|
|
|
#endif |
#endif |
|
|
/* --------------------------------------------------------------------- */ |
/* --------------------------------------------------------------------- */ |
Line 2534 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct s
|
Line 2334 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct s
|
|
|
CHECK_ERROR(); |
CHECK_ERROR(); |
check_sljit_emit_ijump(compiler, type, src, srcw); |
check_sljit_emit_ijump(compiler, type, src, srcw); |
|
ADJUST_LOCAL_OFFSET(src, srcw); |
|
|
CHECK_EXTRA_REGS(src, srcw, (void)0); |
CHECK_EXTRA_REGS(src, srcw, (void)0); |
|
|
if (SLJIT_UNLIKELY(compiler->flags_saved)) { |
if (SLJIT_UNLIKELY(compiler->flags_saved)) { |
if (type <= SLJIT_JUMP) |
if (type <= SLJIT_JUMP) |
FAIL_IF(emit_restore_flags(compiler, 0)); |
FAIL_IF(emit_restore_flags(compiler, 0)); |
Line 2549 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct s
|
Line 2351 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct s
|
EMIT_MOV(compiler, TMP_REGISTER, 0, src, 0); |
EMIT_MOV(compiler, TMP_REGISTER, 0, src, 0); |
src = TMP_REGISTER; |
src = TMP_REGISTER; |
} |
} |
if ((src & SLJIT_MEM) && (src & 0xf) == SLJIT_LOCALS_REG && type >= SLJIT_CALL3) { | if (src == SLJIT_MEM1(SLJIT_LOCALS_REG) && type >= SLJIT_CALL3) |
if (src & 0xf0) { | srcw += sizeof(sljit_w); |
EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw); | |
src = TMP_REGISTER; | |
} | |
else | |
srcw += sizeof(sljit_w); | |
} | |
#else |
#else |
if ((src & SLJIT_MEM) && (src & 0xf) == SLJIT_LOCALS_REG) { | if (src == SLJIT_MEM1(SLJIT_LOCALS_REG)) |
if (src & 0xf0) { | srcw += sizeof(sljit_w) * (type - SLJIT_CALL0); |
EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw); | |
src = TMP_REGISTER; | |
} | |
else | |
srcw += sizeof(sljit_w) * (type - SLJIT_CALL0); | |
} | |
#endif |
#endif |
#endif |
#endif |
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && defined(_WIN64) |
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && defined(_WIN64) |
Line 2613 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(str
|
Line 2403 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(str
|
{ |
{ |
sljit_ub *buf; |
sljit_ub *buf; |
sljit_ub cond_set = 0; |
sljit_ub cond_set = 0; |
|
int dst_save = dst; |
|
sljit_w dstw_save = dstw; |
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) |
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) |
int reg; |
int reg; |
#endif |
#endif |
Line 2623 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(str
|
Line 2415 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(str
|
if (dst == SLJIT_UNUSED) |
if (dst == SLJIT_UNUSED) |
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
|
|
|
ADJUST_LOCAL_OFFSET(dst, dstw); |
CHECK_EXTRA_REGS(dst, dstw, (void)0); |
CHECK_EXTRA_REGS(dst, dstw, (void)0); |
if (SLJIT_UNLIKELY(compiler->flags_saved)) |
if (SLJIT_UNLIKELY(compiler->flags_saved)) |
FAIL_IF(emit_restore_flags(compiler, 0)); | FAIL_IF(emit_restore_flags(compiler, op & SLJIT_KEEP_FLAGS)); |
|
|
switch (type) { |
switch (type) { |
case SLJIT_C_EQUAL: |
case SLJIT_C_EQUAL: |
Line 2718 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(str
|
Line 2511 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(str
|
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) |
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) |
compiler->skip_checks = 1; |
compiler->skip_checks = 1; |
#endif |
#endif |
return sljit_emit_op2(compiler, op, dst, dstw, dst, dstw, TMP_REGISTER, 0); | return sljit_emit_op2(compiler, op, dst_save, dstw_save, dst_save, dstw_save, TMP_REGISTER, 0); |
} |
} |
} |
} |
#else |
#else |
Line 2790 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(str
|
Line 2583 SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(str
|
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) |
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) |
compiler->skip_checks = 1; |
compiler->skip_checks = 1; |
#endif |
#endif |
return sljit_emit_op2(compiler, op, dst, dstw, dst, dstw, TMP_REGISTER, 0); | return sljit_emit_op2(compiler, op, dst_save, dstw_save, dst_save, dstw_save, TMP_REGISTER, 0); |
} |
} |
#endif |
#endif |
|
|
return SLJIT_SUCCESS; |
return SLJIT_SUCCESS; |
} |
} |
|
|
|
SLJIT_API_FUNC_ATTRIBUTE int sljit_get_local_base(struct sljit_compiler *compiler, int dst, sljit_w dstw, sljit_w offset) |
|
{ |
|
CHECK_ERROR(); |
|
check_sljit_get_local_base(compiler, dst, dstw, offset); |
|
ADJUST_LOCAL_OFFSET(dst, dstw); |
|
|
|
CHECK_EXTRA_REGS(dst, dstw, (void)0); |
|
|
|
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) |
|
compiler->mode32 = 0; |
|
#endif |
|
|
|
ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_LOCALS_REG), offset); |
|
|
|
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) |
|
if (NOT_HALFWORD(offset)) { |
|
FAIL_IF(emit_load_imm64(compiler, TMP_REGISTER, offset)); |
|
#if (defined SLJIT_DEBUG && SLJIT_DEBUG) |
|
SLJIT_ASSERT(emit_lea_binary(compiler, dst, dstw, SLJIT_LOCALS_REG, 0, TMP_REGISTER, 0) != SLJIT_ERR_UNSUPPORTED); |
|
return compiler->error; |
|
#else |
|
return emit_lea_binary(compiler, dst, dstw, SLJIT_LOCALS_REG, 0, TMP_REGISTER, 0); |
|
#endif |
|
} |
|
#endif |
|
|
|
if (offset != 0) |
|
return emit_lea_binary(compiler, dst, dstw, SLJIT_LOCALS_REG, 0, SLJIT_IMM, offset); |
|
return emit_mov(compiler, dst, dstw, SLJIT_LOCALS_REG, 0); |
|
} |
|
|
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, int dst, sljit_w dstw, sljit_w init_value) |
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, int dst, sljit_w dstw, sljit_w init_value) |
{ |
{ |
sljit_ub *buf; |
sljit_ub *buf; |
Line 2807 SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emi
|
Line 2631 SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emi
|
|
|
CHECK_ERROR_PTR(); |
CHECK_ERROR_PTR(); |
check_sljit_emit_const(compiler, dst, dstw, init_value); |
check_sljit_emit_const(compiler, dst, dstw, init_value); |
|
ADJUST_LOCAL_OFFSET(dst, dstw); |
|
|
CHECK_EXTRA_REGS(dst, dstw, (void)0); |
CHECK_EXTRA_REGS(dst, dstw, (void)0); |
|
|