JIT compielr update.
This commit is contained in:
parent
05a8186117
commit
aa224e4ac9
|
@ -4458,7 +4458,7 @@ sljit_s32 cmp1b_ind = 4;
|
||||||
sljit_s32 cmp2a_ind = 5;
|
sljit_s32 cmp2a_ind = 5;
|
||||||
sljit_s32 cmp2b_ind = 6;
|
sljit_s32 cmp2b_ind = 6;
|
||||||
struct sljit_label *start;
|
struct sljit_label *start;
|
||||||
struct sljit_jump *jump[4];
|
struct sljit_jump *jump[3];
|
||||||
|
|
||||||
sljit_u8 instruction[8];
|
sljit_u8 instruction[8];
|
||||||
|
|
||||||
|
@ -4473,17 +4473,8 @@ if (common->match_end_ptr != 0)
|
||||||
OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);
|
OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);
|
||||||
OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(offs1 + 1));
|
OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(offs1 + 1));
|
||||||
|
|
||||||
if (sljit_x86_is_cmov_available())
|
|
||||||
{
|
|
||||||
OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP1, 0, STR_END, 0);
|
OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP1, 0, STR_END, 0);
|
||||||
sljit_x86_emit_cmov(compiler, SLJIT_LESS, STR_END, TMP1, 0);
|
sljit_emit_cmov(compiler, SLJIT_LESS, STR_END, TMP1, 0);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
jump[1] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_END, 0);
|
|
||||||
OP1(SLJIT_MOV, STR_END, 0, TMP1, 0);
|
|
||||||
JUMPHERE(jump[1]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* MOVD xmm, r/m32 */
|
/* MOVD xmm, r/m32 */
|
||||||
|
@ -4574,7 +4565,7 @@ if (char2a != char2b)
|
||||||
|
|
||||||
if (offs2 > 0)
|
if (offs2 > 0)
|
||||||
OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(offs2));
|
OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(offs2));
|
||||||
jump[1] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
|
jump[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
|
||||||
|
|
||||||
OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);
|
OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);
|
||||||
OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, ~0xf);
|
OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, ~0xf);
|
||||||
|
@ -4582,7 +4573,7 @@ OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, ~0xf);
|
||||||
|
|
||||||
load_from_mem_sse2(compiler, data1_ind, str_ptr_ind);
|
load_from_mem_sse2(compiler, data1_ind, str_ptr_ind);
|
||||||
|
|
||||||
jump[2] = CMP(SLJIT_EQUAL, STR_PTR, 0, TMP1, 0);
|
jump[1] = CMP(SLJIT_EQUAL, STR_PTR, 0, TMP1, 0);
|
||||||
|
|
||||||
load_from_mem_sse2(compiler, data2_ind, tmp1_ind);
|
load_from_mem_sse2(compiler, data2_ind, tmp1_ind);
|
||||||
|
|
||||||
|
@ -4616,9 +4607,9 @@ instruction[2] = 0xeb;
|
||||||
instruction[3] = 0xc0 | (data2_ind << 3) | tmp_ind;
|
instruction[3] = 0xc0 | (data2_ind << 3) | tmp_ind;
|
||||||
sljit_emit_op_custom(compiler, instruction, 4);
|
sljit_emit_op_custom(compiler, instruction, 4);
|
||||||
|
|
||||||
jump[3] = JUMP(SLJIT_JUMP);
|
jump[2] = JUMP(SLJIT_JUMP);
|
||||||
|
|
||||||
JUMPHERE(jump[2]);
|
JUMPHERE(jump[1]);
|
||||||
|
|
||||||
/* MOVDQA xmm1, xmm2/m128 */
|
/* MOVDQA xmm1, xmm2/m128 */
|
||||||
/* instruction[0] = 0x66; */
|
/* instruction[0] = 0x66; */
|
||||||
|
@ -4635,7 +4626,7 @@ instruction[3] = 0xc0 | (7 << 3) | data2_ind;
|
||||||
instruction[4] = diff;
|
instruction[4] = diff;
|
||||||
sljit_emit_op_custom(compiler, instruction, 5);
|
sljit_emit_op_custom(compiler, instruction, 5);
|
||||||
|
|
||||||
JUMPHERE(jump[3]);
|
JUMPHERE(jump[2]);
|
||||||
|
|
||||||
OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xf);
|
OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xf);
|
||||||
|
|
||||||
|
@ -4667,7 +4658,7 @@ instruction[2] = 0xc0 | (tmp1_ind << 3) | tmp1_ind;
|
||||||
sljit_emit_op_custom(compiler, instruction, 3);
|
sljit_emit_op_custom(compiler, instruction, 3);
|
||||||
sljit_set_current_flags(compiler, SLJIT_SET_Z);
|
sljit_set_current_flags(compiler, SLJIT_SET_Z);
|
||||||
|
|
||||||
jump[2] = JUMP(SLJIT_NOT_ZERO);
|
jump[1] = JUMP(SLJIT_NOT_ZERO);
|
||||||
|
|
||||||
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
|
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
|
||||||
|
|
||||||
|
@ -4680,7 +4671,7 @@ start = LABEL();
|
||||||
load_from_mem_sse2(compiler, data2_ind, str_ptr_ind);
|
load_from_mem_sse2(compiler, data2_ind, str_ptr_ind);
|
||||||
|
|
||||||
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 16);
|
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 16);
|
||||||
jump[3] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
|
jump[2] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
|
||||||
|
|
||||||
load_from_mem_sse2(compiler, data1_ind, str_ptr_ind);
|
load_from_mem_sse2(compiler, data1_ind, str_ptr_ind);
|
||||||
|
|
||||||
|
@ -4740,28 +4731,19 @@ sljit_set_current_flags(compiler, SLJIT_SET_Z);
|
||||||
|
|
||||||
JUMPTO(SLJIT_ZERO, start);
|
JUMPTO(SLJIT_ZERO, start);
|
||||||
|
|
||||||
JUMPHERE(jump[2]);
|
JUMPHERE(jump[1]);
|
||||||
|
|
||||||
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
|
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
|
||||||
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offs1));
|
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offs1));
|
||||||
|
|
||||||
JUMPHERE(jump[1]);
|
JUMPHERE(jump[0]);
|
||||||
JUMPHERE(jump[3]);
|
JUMPHERE(jump[2]);
|
||||||
|
|
||||||
if (common->match_end_ptr != 0)
|
if (common->match_end_ptr != 0)
|
||||||
OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);
|
OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);
|
||||||
|
|
||||||
if (sljit_x86_is_cmov_available())
|
|
||||||
{
|
|
||||||
OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_PTR, 0, STR_END, 0);
|
OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_PTR, 0, STR_END, 0);
|
||||||
sljit_x86_emit_cmov(compiler, SLJIT_GREATER, STR_PTR, STR_END, 0);
|
sljit_emit_cmov(compiler, SLJIT_GREATER, STR_PTR, STR_END, 0);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
jump[1] = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, STR_END, 0);
|
|
||||||
OP1(SLJIT_MOV, STR_PTR, 0, STR_END, 0);
|
|
||||||
JUMPHERE(jump[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (common->match_end_ptr != 0)
|
if (common->match_end_ptr != 0)
|
||||||
OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);
|
OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);
|
||||||
|
@ -4847,19 +4829,8 @@ if (has_match_end)
|
||||||
OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);
|
OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);
|
||||||
|
|
||||||
OP2(SLJIT_ADD, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, SLJIT_IMM, IN_UCHARS(offset + 1));
|
OP2(SLJIT_ADD, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, SLJIT_IMM, IN_UCHARS(offset + 1));
|
||||||
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
|
|
||||||
if (sljit_x86_is_cmov_available())
|
|
||||||
{
|
|
||||||
OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_END, 0, TMP3, 0);
|
OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_END, 0, TMP3, 0);
|
||||||
sljit_x86_emit_cmov(compiler, SLJIT_GREATER, STR_END, TMP3, 0);
|
sljit_emit_cmov(compiler, SLJIT_GREATER, STR_END, TMP3, 0);
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
quit = CMP(SLJIT_LESS_EQUAL, STR_END, 0, TMP3, 0);
|
|
||||||
OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);
|
|
||||||
JUMPHERE(quit);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
|
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
|
||||||
|
@ -4871,7 +4842,7 @@ if (common->utf && offset > 0)
|
||||||
|
|
||||||
/* SSE2 accelerated first character search. */
|
/* SSE2 accelerated first character search. */
|
||||||
|
|
||||||
if (sljit_x86_is_sse2_available())
|
if (sljit_has_cpu_feature(SLJIT_HAS_SSE2))
|
||||||
{
|
{
|
||||||
fast_forward_first_char2_sse2(common, char1, char2);
|
fast_forward_first_char2_sse2(common, char1, char2);
|
||||||
|
|
||||||
|
@ -4906,16 +4877,16 @@ if (sljit_x86_is_sse2_available())
|
||||||
if (offset > 0)
|
if (offset > 0)
|
||||||
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset));
|
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset));
|
||||||
}
|
}
|
||||||
else if (sljit_x86_is_cmov_available())
|
|
||||||
{
|
|
||||||
OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, STR_PTR, 0, STR_END, 0);
|
|
||||||
sljit_x86_emit_cmov(compiler, SLJIT_GREATER_EQUAL, STR_PTR, has_match_end ? SLJIT_MEM1(SLJIT_SP) : STR_END, has_match_end ? common->match_end_ptr : 0);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
quit = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0);
|
OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, STR_PTR, 0, STR_END, 0);
|
||||||
OP1(SLJIT_MOV, STR_PTR, 0, has_match_end ? SLJIT_MEM1(SLJIT_SP) : STR_END, has_match_end ? common->match_end_ptr : 0);
|
if (has_match_end)
|
||||||
JUMPHERE(quit);
|
{
|
||||||
|
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);
|
||||||
|
sljit_emit_cmov(compiler, SLJIT_GREATER_EQUAL, STR_PTR, TMP1, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sljit_emit_cmov(compiler, SLJIT_GREATER_EQUAL, STR_PTR, STR_END, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_match_end)
|
if (has_match_end)
|
||||||
|
|
|
@ -393,7 +393,9 @@ typedef double sljit_f64;
|
||||||
#ifndef SLJIT_W
|
#ifndef SLJIT_W
|
||||||
|
|
||||||
/* Defining long constants. */
|
/* Defining long constants. */
|
||||||
#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
|
#if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
|
||||||
|
#define SLJIT_W(w) (w##l)
|
||||||
|
#elif (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
|
||||||
#define SLJIT_W(w) (w##ll)
|
#define SLJIT_W(w) (w##ll)
|
||||||
#else
|
#else
|
||||||
#define SLJIT_W(w) (w)
|
#define SLJIT_W(w) (w)
|
||||||
|
|
|
@ -342,7 +342,7 @@
|
||||||
/* Public functions */
|
/* Public functions */
|
||||||
/* --------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------- */
|
||||||
|
|
||||||
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
|
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
|
||||||
#define SLJIT_NEEDS_COMPILER_INIT 1
|
#define SLJIT_NEEDS_COMPILER_INIT 1
|
||||||
static sljit_s32 compiler_initialized = 0;
|
static sljit_s32 compiler_initialized = 0;
|
||||||
/* A thread safe initialization. */
|
/* A thread safe initialization. */
|
||||||
|
@ -1042,7 +1042,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op1(struct sljit_compiler
|
||||||
|
|
||||||
switch (GET_OPCODE(op)) {
|
switch (GET_OPCODE(op)) {
|
||||||
case SLJIT_NOT:
|
case SLJIT_NOT:
|
||||||
case SLJIT_CLZ:
|
/* Only SLJIT_I32_OP and SLJIT_SET_Z are allowed. */
|
||||||
CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK));
|
CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK));
|
||||||
break;
|
break;
|
||||||
case SLJIT_NEG:
|
case SLJIT_NEG:
|
||||||
|
@ -1060,7 +1060,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op1(struct sljit_compiler
|
||||||
CHECK_ARGUMENT(!(op & (SLJIT_I32_OP | SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
|
CHECK_ARGUMENT(!(op & (SLJIT_I32_OP | SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* Only SLJIT_I32_OP or SLJIT_F32_OP is allowed. */
|
/* Only SLJIT_I32_OP is allowed. */
|
||||||
CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
|
CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1241,7 +1241,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1(struct sljit_compile
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||||
CHECK_ARGUMENT(sljit_is_fpu_available());
|
CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
|
||||||
CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_MOV_F64 && GET_OPCODE(op) <= SLJIT_ABS_F64);
|
CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_MOV_F64 && GET_OPCODE(op) <= SLJIT_ABS_F64);
|
||||||
CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
|
CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
|
||||||
FUNCTION_FCHECK(src, srcw);
|
FUNCTION_FCHECK(src, srcw);
|
||||||
|
@ -1279,7 +1279,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_cmp(struct sljit_com
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||||
CHECK_ARGUMENT(sljit_is_fpu_available());
|
CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
|
||||||
CHECK_ARGUMENT(GET_OPCODE(op) == SLJIT_CMP_F64);
|
CHECK_ARGUMENT(GET_OPCODE(op) == SLJIT_CMP_F64);
|
||||||
CHECK_ARGUMENT(!(op & SLJIT_SET_Z));
|
CHECK_ARGUMENT(!(op & SLJIT_SET_Z));
|
||||||
CHECK_ARGUMENT((op & VARIABLE_FLAG_MASK)
|
CHECK_ARGUMENT((op & VARIABLE_FLAG_MASK)
|
||||||
|
@ -1313,7 +1313,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_conv_sw_from_f64(str
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||||
CHECK_ARGUMENT(sljit_is_fpu_available());
|
CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
|
||||||
CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_CONV_SW_FROM_F64 && GET_OPCODE(op) <= SLJIT_CONV_S32_FROM_F64);
|
CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_CONV_SW_FROM_F64 && GET_OPCODE(op) <= SLJIT_CONV_S32_FROM_F64);
|
||||||
CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
|
CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
|
||||||
FUNCTION_FCHECK(src, srcw);
|
FUNCTION_FCHECK(src, srcw);
|
||||||
|
@ -1343,7 +1343,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_conv_f64_from_sw(str
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||||
CHECK_ARGUMENT(sljit_is_fpu_available());
|
CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
|
||||||
CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_CONV_F64_FROM_SW && GET_OPCODE(op) <= SLJIT_CONV_F64_FROM_S32);
|
CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_CONV_F64_FROM_SW && GET_OPCODE(op) <= SLJIT_CONV_F64_FROM_S32);
|
||||||
CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
|
CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
|
||||||
FUNCTION_CHECK_SRC(src, srcw);
|
FUNCTION_CHECK_SRC(src, srcw);
|
||||||
|
@ -1369,7 +1369,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop2(struct sljit_compile
|
||||||
sljit_s32 src2, sljit_sw src2w)
|
sljit_s32 src2, sljit_sw src2w)
|
||||||
{
|
{
|
||||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||||
CHECK_ARGUMENT(sljit_is_fpu_available());
|
CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
|
||||||
CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_ADD_F64 && GET_OPCODE(op) <= SLJIT_DIV_F64);
|
CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_ADD_F64 && GET_OPCODE(op) <= SLJIT_DIV_F64);
|
||||||
CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
|
CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
|
||||||
FUNCTION_FCHECK(src1, src1w);
|
FUNCTION_FCHECK(src1, src1w);
|
||||||
|
@ -1394,6 +1394,11 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_label(struct sljit_compil
|
||||||
{
|
{
|
||||||
SLJIT_UNUSED_ARG(compiler);
|
SLJIT_UNUSED_ARG(compiler);
|
||||||
|
|
||||||
|
if (SLJIT_UNLIKELY(compiler->skip_checks)) {
|
||||||
|
compiler->skip_checks = 0;
|
||||||
|
CHECK_RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||||
compiler->last_flags = 0;
|
compiler->last_flags = 0;
|
||||||
#endif
|
#endif
|
||||||
|
@ -1464,7 +1469,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fcmp(struct sljit_compile
|
||||||
sljit_s32 src2, sljit_sw src2w)
|
sljit_s32 src2, sljit_sw src2w)
|
||||||
{
|
{
|
||||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||||
CHECK_ARGUMENT(sljit_is_fpu_available());
|
CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
|
||||||
CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_F32_OP)));
|
CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_F32_OP)));
|
||||||
CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL_F64 && (type & 0xff) <= SLJIT_ORDERED_F64);
|
CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL_F64 && (type & 0xff) <= SLJIT_ORDERED_F64);
|
||||||
FUNCTION_FCHECK(src1, src1w);
|
FUNCTION_FCHECK(src1, src1w);
|
||||||
|
@ -1553,6 +1558,37 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_flags(struct sljit_com
|
||||||
CHECK_RETURN_OK;
|
CHECK_RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
|
||||||
|
sljit_s32 dst_reg,
|
||||||
|
sljit_s32 src, sljit_sw srcw)
|
||||||
|
{
|
||||||
|
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||||
|
CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_I32_OP)));
|
||||||
|
CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_ORDERED_F64);
|
||||||
|
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg & ~SLJIT_I32_OP));
|
||||||
|
if (src != SLJIT_IMM) {
|
||||||
|
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((type & 0xff) <= SLJIT_NOT_ZERO)
|
||||||
|
CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z);
|
||||||
|
else
|
||||||
|
CHECK_ARGUMENT((type & 0xff) == (compiler->last_flags & 0xff));
|
||||||
|
#endif
|
||||||
|
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||||
|
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||||
|
fprintf(compiler->verbose, " cmov%s %s%s, ",
|
||||||
|
!(dst_reg & SLJIT_I32_OP) ? "" : ".i",
|
||||||
|
jump_names[type & 0xff], JUMP_POSTFIX(type));
|
||||||
|
sljit_verbose_reg(compiler, dst_reg & ~SLJIT_I32_OP);
|
||||||
|
fprintf(compiler->verbose, ", ");
|
||||||
|
sljit_verbose_param(compiler, src, srcw);
|
||||||
|
fprintf(compiler->verbose, "\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
CHECK_RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)
|
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)
|
||||||
{
|
{
|
||||||
SLJIT_UNUSED_ARG(offset);
|
SLJIT_UNUSED_ARG(offset);
|
||||||
|
@ -1636,6 +1672,44 @@ static SLJIT_INLINE sljit_s32 emit_mov_before_return(struct sljit_compiler *comp
|
||||||
return sljit_emit_op1(compiler, op, SLJIT_RETURN_REG, 0, src, srcw);
|
return sljit_emit_op1(compiler, op, SLJIT_RETURN_REG, 0, src, srcw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \
|
||||||
|
|| (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \
|
||||||
|
|| (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \
|
||||||
|
|| ((defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) && !(defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1))
|
||||||
|
|
||||||
|
static SLJIT_INLINE sljit_s32 sljit_emit_cmov_generic(struct sljit_compiler *compiler, sljit_s32 type,
|
||||||
|
sljit_s32 dst_reg,
|
||||||
|
sljit_s32 src, sljit_sw srcw)
|
||||||
|
{
|
||||||
|
struct sljit_label *label;
|
||||||
|
struct sljit_jump *jump;
|
||||||
|
sljit_s32 op = (dst_reg & SLJIT_I32_OP) ? SLJIT_MOV32 : SLJIT_MOV;
|
||||||
|
|
||||||
|
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||||
|
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||||
|
compiler->skip_checks = 1;
|
||||||
|
#endif
|
||||||
|
jump = sljit_emit_jump(compiler, type ^ 0x1);
|
||||||
|
FAIL_IF(!jump);
|
||||||
|
|
||||||
|
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||||
|
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||||
|
compiler->skip_checks = 1;
|
||||||
|
#endif
|
||||||
|
FAIL_IF(sljit_emit_op1(compiler, op, dst_reg & ~SLJIT_I32_OP, 0, src, srcw));
|
||||||
|
|
||||||
|
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|
||||||
|
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||||
|
compiler->skip_checks = 1;
|
||||||
|
#endif
|
||||||
|
label = sljit_emit_label(compiler);
|
||||||
|
FAIL_IF(!label);
|
||||||
|
sljit_set_label(jump, label);
|
||||||
|
return SLJIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/* CPU description section */
|
/* CPU description section */
|
||||||
|
|
||||||
#if (defined SLJIT_32BIT_ARCHITECTURE && SLJIT_32BIT_ARCHITECTURE)
|
#if (defined SLJIT_32BIT_ARCHITECTURE && SLJIT_32BIT_ARCHITECTURE)
|
||||||
|
@ -1858,6 +1932,13 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
|
||||||
|
{
|
||||||
|
SLJIT_UNUSED_ARG(feature_type);
|
||||||
|
SLJIT_UNREACHABLE();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code)
|
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code)
|
||||||
{
|
{
|
||||||
SLJIT_UNUSED_ARG(code);
|
SLJIT_UNUSED_ARG(code);
|
||||||
|
@ -1985,12 +2066,6 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *com
|
||||||
SLJIT_UNUSED_ARG(current_flags);
|
SLJIT_UNUSED_ARG(current_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_fpu_available(void)
|
|
||||||
{
|
|
||||||
SLJIT_UNREACHABLE();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
|
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
|
||||||
sljit_s32 dst, sljit_sw dstw,
|
sljit_s32 dst, sljit_sw dstw,
|
||||||
sljit_s32 src, sljit_sw srcw)
|
sljit_s32 src, sljit_sw srcw)
|
||||||
|
@ -2105,6 +2180,19 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
|
||||||
return SLJIT_ERR_UNSUPPORTED;
|
return SLJIT_ERR_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
|
||||||
|
sljit_s32 dst_reg,
|
||||||
|
sljit_s32 src, sljit_sw srcw)
|
||||||
|
{
|
||||||
|
SLJIT_UNUSED_ARG(compiler);
|
||||||
|
SLJIT_UNUSED_ARG(type);
|
||||||
|
SLJIT_UNUSED_ARG(dst_reg);
|
||||||
|
SLJIT_UNUSED_ARG(src);
|
||||||
|
SLJIT_UNUSED_ARG(srcw);
|
||||||
|
SLJIT_UNREACHABLE();
|
||||||
|
return SLJIT_ERR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)
|
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)
|
||||||
{
|
{
|
||||||
SLJIT_UNUSED_ARG(compiler);
|
SLJIT_UNUSED_ARG(compiler);
|
||||||
|
|
|
@ -489,6 +489,29 @@ static SLJIT_INLINE sljit_sw sljit_get_executable_offset(struct sljit_compiler *
|
||||||
*/
|
*/
|
||||||
static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler *compiler) { return compiler->executable_size; }
|
static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler *compiler) { return compiler->executable_size; }
|
||||||
|
|
||||||
|
/* Returns with non-zero if the passed SLJIT_HAS_* feature is available.
|
||||||
|
|
||||||
|
Some features (e.g. floating point operations) require CPU support
|
||||||
|
while other (e.g. move with update) is emulated if not available.
|
||||||
|
However it might be worth to generate a special code path even in
|
||||||
|
the latter case in certain cases. */
|
||||||
|
|
||||||
|
/* [Not emulated] Floating-point support is available. */
|
||||||
|
#define SLJIT_HAS_FPU 0
|
||||||
|
/* [Emulated] Some forms of move with pre update is supported. */
|
||||||
|
#define SLJIT_HAS_PRE_UPDATE 1
|
||||||
|
/* [Emulated] Count leading zero is supported. */
|
||||||
|
#define SLJIT_HAS_CLZ 2
|
||||||
|
/* [Emulated] Conditional move is supported. */
|
||||||
|
#define SLJIT_HAS_CMOV 3
|
||||||
|
|
||||||
|
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
|
||||||
|
/* [Not emulated] SSE2 support is available on x86. */
|
||||||
|
#define SLJIT_HAS_SSE2 100
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type);
|
||||||
|
|
||||||
/* Instruction generation. Returns with any error code. If there is no
|
/* Instruction generation. Returns with any error code. If there is no
|
||||||
error, they return with SLJIT_SUCCESS. */
|
error, they return with SLJIT_SUCCESS. */
|
||||||
|
|
||||||
|
@ -896,7 +919,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
|
||||||
#define SLJIT_NEG (SLJIT_OP1_BASE + 17)
|
#define SLJIT_NEG (SLJIT_OP1_BASE + 17)
|
||||||
#define SLJIT_NEG32 (SLJIT_NEG | SLJIT_I32_OP)
|
#define SLJIT_NEG32 (SLJIT_NEG | SLJIT_I32_OP)
|
||||||
/* Count leading zeroes
|
/* Count leading zeroes
|
||||||
Flags: Z */
|
Flags: - (may destroy flags) */
|
||||||
#define SLJIT_CLZ (SLJIT_OP1_BASE + 18)
|
#define SLJIT_CLZ (SLJIT_OP1_BASE + 18)
|
||||||
#define SLJIT_CLZ32 (SLJIT_CLZ | SLJIT_I32_OP)
|
#define SLJIT_CLZ32 (SLJIT_CLZ | SLJIT_I32_OP)
|
||||||
|
|
||||||
|
@ -961,10 +984,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
|
||||||
sljit_s32 src1, sljit_sw src1w,
|
sljit_s32 src1, sljit_sw src1w,
|
||||||
sljit_s32 src2, sljit_sw src2w);
|
sljit_s32 src2, sljit_sw src2w);
|
||||||
|
|
||||||
/* Returns with non-zero if fpu is available. */
|
|
||||||
|
|
||||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_fpu_available(void);
|
|
||||||
|
|
||||||
/* Starting index of opcodes for sljit_emit_fop1. */
|
/* Starting index of opcodes for sljit_emit_fop1. */
|
||||||
#define SLJIT_FOP1_BASE 128
|
#define SLJIT_FOP1_BASE 128
|
||||||
|
|
||||||
|
@ -1058,7 +1077,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
|
||||||
#define SLJIT_SET_SIG_LESS SLJIT_SET(SLJIT_SIG_LESS)
|
#define SLJIT_SET_SIG_LESS SLJIT_SET(SLJIT_SIG_LESS)
|
||||||
#define SLJIT_SIG_GREATER_EQUAL 7
|
#define SLJIT_SIG_GREATER_EQUAL 7
|
||||||
#define SLJIT_SIG_GREATER_EQUAL32 (SLJIT_SIG_GREATER_EQUAL | SLJIT_I32_OP)
|
#define SLJIT_SIG_GREATER_EQUAL32 (SLJIT_SIG_GREATER_EQUAL | SLJIT_I32_OP)
|
||||||
#define SLJIT_SET_SIG_GREATER_EQUAL SLJIT_SET(SLJIT_SET_SIG_GREATER_EQUAL)
|
#define SLJIT_SET_SIG_GREATER_EQUAL SLJIT_SET(SLJIT_SIG_GREATER_EQUAL)
|
||||||
#define SLJIT_SIG_GREATER 8
|
#define SLJIT_SIG_GREATER 8
|
||||||
#define SLJIT_SIG_GREATER32 (SLJIT_SIG_GREATER | SLJIT_I32_OP)
|
#define SLJIT_SIG_GREATER32 (SLJIT_SIG_GREATER | SLJIT_I32_OP)
|
||||||
#define SLJIT_SET_SIG_GREATER SLJIT_SET(SLJIT_SIG_GREATER)
|
#define SLJIT_SET_SIG_GREATER SLJIT_SET(SLJIT_SIG_GREATER)
|
||||||
|
@ -1171,7 +1190,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw
|
||||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw);
|
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw);
|
||||||
|
|
||||||
/* Perform the operation using the conditional flags as the second argument.
|
/* Perform the operation using the conditional flags as the second argument.
|
||||||
Type must always be between SLJIT_EQUAL and SLJIT_S_ORDERED. The value
|
Type must always be between SLJIT_EQUAL and SLJIT_ORDERED_F64. The value
|
||||||
represented by the type is 1, if the condition represented by the type
|
represented by the type is 1, if the condition represented by the type
|
||||||
is fulfilled, and 0 otherwise.
|
is fulfilled, and 0 otherwise.
|
||||||
|
|
||||||
|
@ -1190,6 +1209,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
|
||||||
sljit_s32 src, sljit_sw srcw,
|
sljit_s32 src, sljit_sw srcw,
|
||||||
sljit_s32 type);
|
sljit_s32 type);
|
||||||
|
|
||||||
|
/* Emit a conditional mov instruction which moves source to destination,
|
||||||
|
if the condition is satisfied. Unlike other arithmetic operations this
|
||||||
|
instruction does not support memory accesses.
|
||||||
|
|
||||||
|
type must be between SLJIT_EQUAL and SLJIT_ORDERED_F64
|
||||||
|
dst_reg must be a valid register and it can be combined
|
||||||
|
with SLJIT_I32_OP to perform a 32 bit arithmetic operation
|
||||||
|
src must be register or immediate (SLJIT_IMM)
|
||||||
|
|
||||||
|
Flags: - (does not modify flags) */
|
||||||
|
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
|
||||||
|
sljit_s32 dst_reg,
|
||||||
|
sljit_s32 src, sljit_sw srcw);
|
||||||
|
|
||||||
/* Copies the base address of SLJIT_SP + offset to dst.
|
/* Copies the base address of SLJIT_SP + offset to dst.
|
||||||
Flags: - (may destroy flags) */
|
Flags: - (may destroy flags) */
|
||||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset);
|
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset);
|
||||||
|
@ -1215,7 +1248,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta
|
||||||
/* --------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------- */
|
||||||
|
|
||||||
#define SLJIT_MAJOR_VERSION 0
|
#define SLJIT_MAJOR_VERSION 0
|
||||||
#define SLJIT_MINOR_VERSION 93
|
#define SLJIT_MINOR_VERSION 94
|
||||||
|
|
||||||
/* Get the human readable name of the platform. Can be useful on platforms
|
/* Get the human readable name of the platform. Can be useful on platforms
|
||||||
like ARM, where ARM and Thumb2 functions can be mixed, and
|
like ARM, where ARM and Thumb2 functions can be mixed, and
|
||||||
|
@ -1354,32 +1387,4 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c
|
||||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler,
|
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler,
|
||||||
sljit_s32 current_flags);
|
sljit_s32 current_flags);
|
||||||
|
|
||||||
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
|
|
||||||
|
|
||||||
/* Returns with non-zero if sse2 is available. */
|
|
||||||
|
|
||||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_x86_is_sse2_available(void);
|
|
||||||
|
|
||||||
/* Returns with non-zero if cmov instruction is available. */
|
|
||||||
|
|
||||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_x86_is_cmov_available(void);
|
|
||||||
|
|
||||||
/* Emit a conditional mov instruction on x86 CPUs. This instruction
|
|
||||||
moves src to destination, if the condition is satisfied. Unlike
|
|
||||||
other arithmetic instructions, destination must be a register.
|
|
||||||
Before such instructions are emitted, cmov support should be
|
|
||||||
checked by sljit_x86_is_cmov_available function.
|
|
||||||
type must be between SLJIT_EQUAL and SLJIT_S_ORDERED
|
|
||||||
dst_reg must be a valid register and it can be combined
|
|
||||||
with SLJIT_I32_OP to perform 32 bit arithmetic
|
|
||||||
Flags: - (does not modify flags)
|
|
||||||
*/
|
|
||||||
|
|
||||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_x86_emit_cmov(struct sljit_compiler *compiler,
|
|
||||||
sljit_s32 type,
|
|
||||||
sljit_s32 dst_reg,
|
|
||||||
sljit_s32 src, sljit_sw srcw);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* _SLJIT_LIR_H_ */
|
#endif /* _SLJIT_LIR_H_ */
|
||||||
|
|
|
@ -82,6 +82,7 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
|
||||||
#define BLX 0xe12fff30
|
#define BLX 0xe12fff30
|
||||||
#define BX 0xe12fff10
|
#define BX 0xe12fff10
|
||||||
#define CLZ 0xe16f0f10
|
#define CLZ 0xe16f0f10
|
||||||
|
#define CMN_DP 0xb
|
||||||
#define CMP_DP 0xa
|
#define CMP_DP 0xa
|
||||||
#define BKPT 0xe1200070
|
#define BKPT 0xe1200070
|
||||||
#define EOR_DP 0x1
|
#define EOR_DP 0x1
|
||||||
|
@ -813,6 +814,27 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
|
||||||
|
{
|
||||||
|
switch (feature_type) {
|
||||||
|
case SLJIT_HAS_FPU:
|
||||||
|
#ifdef SLJIT_IS_FPU_AVAILABLE
|
||||||
|
return SLJIT_IS_FPU_AVAILABLE;
|
||||||
|
#else
|
||||||
|
/* Available by default. */
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case SLJIT_HAS_PRE_UPDATE:
|
||||||
|
case SLJIT_HAS_CLZ:
|
||||||
|
case SLJIT_HAS_CMOV:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------- */
|
||||||
/* Entry, exit */
|
/* Entry, exit */
|
||||||
/* --------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------- */
|
||||||
|
@ -969,6 +991,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp
|
||||||
#define INV_IMM 0x02
|
#define INV_IMM 0x02
|
||||||
/* Source and destination is register. */
|
/* Source and destination is register. */
|
||||||
#define MOVE_REG_CONV 0x04
|
#define MOVE_REG_CONV 0x04
|
||||||
|
/* Unused return value. */
|
||||||
|
#define UNUSED_RETURN 0x08
|
||||||
/* SET_FLAGS must be (1 << 20) as it is also the value of S bit (can be used for optimization). */
|
/* SET_FLAGS must be (1 << 20) as it is also the value of S bit (can be used for optimization). */
|
||||||
#define SET_FLAGS (1 << 20)
|
#define SET_FLAGS (1 << 20)
|
||||||
/* dst: reg
|
/* dst: reg
|
||||||
|
@ -1055,12 +1079,13 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
|
||||||
SLJIT_ASSERT(!(flags & INV_IMM));
|
SLJIT_ASSERT(!(flags & INV_IMM));
|
||||||
SLJIT_ASSERT(!(src2 & SRC2_IMM));
|
SLJIT_ASSERT(!(src2 & SRC2_IMM));
|
||||||
FAIL_IF(push_inst(compiler, CLZ | RD(dst) | RM(src2)));
|
FAIL_IF(push_inst(compiler, CLZ | RD(dst) | RM(src2)));
|
||||||
if (flags & SET_FLAGS)
|
|
||||||
return push_inst(compiler, EMIT_DATA_PROCESS_INS(CMP_DP, flags & SET_FLAGS, SLJIT_UNUSED, dst, SRC2_IMM));
|
|
||||||
return SLJIT_SUCCESS;
|
return SLJIT_SUCCESS;
|
||||||
|
|
||||||
case SLJIT_ADD:
|
case SLJIT_ADD:
|
||||||
SLJIT_ASSERT(!(flags & INV_IMM));
|
SLJIT_ASSERT(!(flags & INV_IMM));
|
||||||
|
if ((flags & (UNUSED_RETURN | SET_FLAGS)) == (UNUSED_RETURN | SET_FLAGS) && !(flags & ARGS_SWAPPED))
|
||||||
|
return push_inst(compiler, EMIT_DATA_PROCESS_INS(CMN_DP, SET_FLAGS,
|
||||||
|
SLJIT_UNUSED, src1, (src2 & SRC2_IMM) ? src2 : RM(src2)));
|
||||||
return push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, flags & SET_FLAGS,
|
return push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, flags & SET_FLAGS,
|
||||||
dst, src1, (src2 & SRC2_IMM) ? src2 : RM(src2)));
|
dst, src1, (src2 & SRC2_IMM) ? src2 : RM(src2)));
|
||||||
|
|
||||||
|
@ -1071,6 +1096,9 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
|
||||||
|
|
||||||
case SLJIT_SUB:
|
case SLJIT_SUB:
|
||||||
SLJIT_ASSERT(!(flags & INV_IMM));
|
SLJIT_ASSERT(!(flags & INV_IMM));
|
||||||
|
if ((flags & (UNUSED_RETURN | SET_FLAGS)) == (UNUSED_RETURN | SET_FLAGS) && !(flags & ARGS_SWAPPED))
|
||||||
|
return push_inst(compiler, EMIT_DATA_PROCESS_INS(CMP_DP, SET_FLAGS,
|
||||||
|
SLJIT_UNUSED, src1, (src2 & SRC2_IMM) ? src2 : RM(src2)));
|
||||||
return push_inst(compiler, EMIT_DATA_PROCESS_INS(!(flags & ARGS_SWAPPED) ? SUB_DP : RSB_DP, flags & SET_FLAGS,
|
return push_inst(compiler, EMIT_DATA_PROCESS_INS(!(flags & ARGS_SWAPPED) ? SUB_DP : RSB_DP, flags & SET_FLAGS,
|
||||||
dst, src1, (src2 & SRC2_IMM) ? src2 : RM(src2)));
|
dst, src1, (src2 & SRC2_IMM) ? src2 : RM(src2)));
|
||||||
|
|
||||||
|
@ -1296,7 +1324,10 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg,
|
||||||
/* Load integer. */
|
/* Load integer. */
|
||||||
return push_inst_with_literal(compiler, EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0, reg, TMP_PC, 0), imm);
|
return push_inst_with_literal(compiler, EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0, reg, TMP_PC, 0), imm);
|
||||||
#else
|
#else
|
||||||
return emit_imm(compiler, reg, imm);
|
FAIL_IF(push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | (imm & 0xfff)));
|
||||||
|
if (imm <= 0xffff)
|
||||||
|
return SLJIT_SUCCESS;
|
||||||
|
return push_inst(compiler, MOVT | RD(reg) | ((imm >> 12) & 0xf0000) | ((imm >> 16) & 0xfff));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1413,10 +1444,8 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
|
||||||
sljit_s32 flags = HAS_FLAGS(op) ? SET_FLAGS : 0;
|
sljit_s32 flags = HAS_FLAGS(op) ? SET_FLAGS : 0;
|
||||||
|
|
||||||
/* Destination check. */
|
/* Destination check. */
|
||||||
if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) {
|
if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED))
|
||||||
if (op <= SLJIT_MOVU_P && !(src2 & SLJIT_MEM))
|
flags |= UNUSED_RETURN;
|
||||||
return SLJIT_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
SLJIT_ASSERT(!(inp_flags & ALLOW_INV_IMM) || (inp_flags & ALLOW_IMM));
|
SLJIT_ASSERT(!(inp_flags & ALLOW_INV_IMM) || (inp_flags & ALLOW_IMM));
|
||||||
|
|
||||||
|
@ -1752,43 +1781,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c
|
||||||
/* Floating point operators */
|
/* Floating point operators */
|
||||||
/* --------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------- */
|
||||||
|
|
||||||
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
|
|
||||||
|
|
||||||
/* 0 - no fpu
|
|
||||||
1 - vfp */
|
|
||||||
static sljit_s32 arm_fpu_type = -1;
|
|
||||||
|
|
||||||
static void init_compiler(void)
|
|
||||||
{
|
|
||||||
if (arm_fpu_type != -1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* TODO: Only the OS can help to determine the correct fpu type. */
|
|
||||||
arm_fpu_type = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_fpu_available(void)
|
|
||||||
{
|
|
||||||
#ifdef SLJIT_IS_FPU_AVAILABLE
|
|
||||||
return SLJIT_IS_FPU_AVAILABLE;
|
|
||||||
#else
|
|
||||||
if (arm_fpu_type == -1)
|
|
||||||
init_compiler();
|
|
||||||
return arm_fpu_type;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#define arm_fpu_type 1
|
|
||||||
|
|
||||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_fpu_available(void)
|
|
||||||
{
|
|
||||||
/* Always available. */
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define FPU_LOAD (1 << 20)
|
#define FPU_LOAD (1 << 20)
|
||||||
#define EMIT_FPU_DATA_TRANSFER(inst, add, base, freg, offs) \
|
#define EMIT_FPU_DATA_TRANSFER(inst, add, base, freg, offs) \
|
||||||
|
@ -2254,6 +2246,43 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
|
||||||
return (flags & SLJIT_SET_Z) ? push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, SET_FLAGS, TMP_REG2, SLJIT_UNUSED, RM(dst_reg))) : SLJIT_SUCCESS;
|
return (flags & SLJIT_SET_Z) ? push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, SET_FLAGS, TMP_REG2, SLJIT_UNUSED, RM(dst_reg))) : SLJIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
|
||||||
|
sljit_s32 dst_reg,
|
||||||
|
sljit_s32 src, sljit_sw srcw)
|
||||||
|
{
|
||||||
|
sljit_uw cc, tmp;
|
||||||
|
|
||||||
|
CHECK_ERROR();
|
||||||
|
CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
|
||||||
|
|
||||||
|
dst_reg &= ~SLJIT_I32_OP;
|
||||||
|
|
||||||
|
cc = get_cc(type & 0xff);
|
||||||
|
|
||||||
|
if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {
|
||||||
|
tmp = get_imm(srcw);
|
||||||
|
if (tmp)
|
||||||
|
return push_inst(compiler, (EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst_reg, SLJIT_UNUSED, tmp) & ~COND_MASK) | cc);
|
||||||
|
|
||||||
|
tmp = get_imm(~srcw);
|
||||||
|
if (tmp)
|
||||||
|
return push_inst(compiler, (EMIT_DATA_PROCESS_INS(MVN_DP, 0, dst_reg, SLJIT_UNUSED, tmp) & ~COND_MASK) | cc);
|
||||||
|
|
||||||
|
#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
|
||||||
|
tmp = (sljit_uw) srcw;
|
||||||
|
FAIL_IF(push_inst(compiler, (MOVW & ~COND_MASK) | cc | RD(dst_reg) | ((tmp << 4) & 0xf0000) | (tmp & 0xfff)));
|
||||||
|
if (tmp <= 0xffff)
|
||||||
|
return SLJIT_SUCCESS;
|
||||||
|
return push_inst(compiler, (MOVT & ~COND_MASK) | cc | RD(dst_reg) | ((tmp >> 12) & 0xf0000) | ((tmp >> 16) & 0xfff));
|
||||||
|
#else
|
||||||
|
FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
|
||||||
|
src = TMP_REG1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return push_inst(compiler, (EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst_reg, SLJIT_UNUSED, src) & ~COND_MASK) | cc);
|
||||||
|
}
|
||||||
|
|
||||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
|
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
|
||||||
{
|
{
|
||||||
struct sljit_const *const_;
|
struct sljit_const *const_;
|
||||||
|
|
|
@ -76,6 +76,7 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 8] = {
|
||||||
#define BRK 0xd4200000
|
#define BRK 0xd4200000
|
||||||
#define CBZ 0xb4000000
|
#define CBZ 0xb4000000
|
||||||
#define CLZ 0xdac01000
|
#define CLZ 0xdac01000
|
||||||
|
#define CSEL 0x9a800000
|
||||||
#define CSINC 0x9a800400
|
#define CSINC 0x9a800400
|
||||||
#define EOR 0xca000000
|
#define EOR 0xca000000
|
||||||
#define EORI 0xd2000000
|
#define EORI 0xd2000000
|
||||||
|
@ -323,6 +324,27 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
|
||||||
|
{
|
||||||
|
switch (feature_type) {
|
||||||
|
case SLJIT_HAS_FPU:
|
||||||
|
#ifdef SLJIT_IS_FPU_AVAILABLE
|
||||||
|
return SLJIT_IS_FPU_AVAILABLE;
|
||||||
|
#else
|
||||||
|
/* Available by default. */
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case SLJIT_HAS_PRE_UPDATE:
|
||||||
|
case SLJIT_HAS_CLZ:
|
||||||
|
case SLJIT_HAS_CMOV:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------- */
|
||||||
/* Core code generator functions. */
|
/* Core code generator functions. */
|
||||||
/* --------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------- */
|
||||||
|
@ -712,7 +734,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
|
||||||
case SLJIT_NOT:
|
case SLJIT_NOT:
|
||||||
SLJIT_ASSERT(arg1 == TMP_REG1);
|
SLJIT_ASSERT(arg1 == TMP_REG1);
|
||||||
FAIL_IF(push_inst(compiler, (ORN ^ inv_bits) | RD(dst) | RN(TMP_ZERO) | RM(arg2)));
|
FAIL_IF(push_inst(compiler, (ORN ^ inv_bits) | RD(dst) | RN(TMP_ZERO) | RM(arg2)));
|
||||||
goto set_flags;
|
break; /* Set flags. */
|
||||||
case SLJIT_NEG:
|
case SLJIT_NEG:
|
||||||
SLJIT_ASSERT(arg1 == TMP_REG1);
|
SLJIT_ASSERT(arg1 == TMP_REG1);
|
||||||
if (flags & SET_FLAGS)
|
if (flags & SET_FLAGS)
|
||||||
|
@ -720,8 +742,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
|
||||||
return push_inst(compiler, (SUB ^ inv_bits) | RD(dst) | RN(TMP_ZERO) | RM(arg2));
|
return push_inst(compiler, (SUB ^ inv_bits) | RD(dst) | RN(TMP_ZERO) | RM(arg2));
|
||||||
case SLJIT_CLZ:
|
case SLJIT_CLZ:
|
||||||
SLJIT_ASSERT(arg1 == TMP_REG1);
|
SLJIT_ASSERT(arg1 == TMP_REG1);
|
||||||
FAIL_IF(push_inst(compiler, (CLZ ^ inv_bits) | RD(dst) | RN(arg2)));
|
return push_inst(compiler, (CLZ ^ inv_bits) | RD(dst) | RN(arg2));
|
||||||
goto set_flags;
|
|
||||||
case SLJIT_ADD:
|
case SLJIT_ADD:
|
||||||
CHECK_FLAGS(1 << 29);
|
CHECK_FLAGS(1 << 29);
|
||||||
return push_inst(compiler, (ADD ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));
|
return push_inst(compiler, (ADD ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));
|
||||||
|
@ -750,23 +771,23 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
|
||||||
return push_inst(compiler, (AND ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));
|
return push_inst(compiler, (AND ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));
|
||||||
case SLJIT_OR:
|
case SLJIT_OR:
|
||||||
FAIL_IF(push_inst(compiler, (ORR ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));
|
FAIL_IF(push_inst(compiler, (ORR ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));
|
||||||
goto set_flags;
|
break; /* Set flags. */
|
||||||
case SLJIT_XOR:
|
case SLJIT_XOR:
|
||||||
FAIL_IF(push_inst(compiler, (EOR ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));
|
FAIL_IF(push_inst(compiler, (EOR ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));
|
||||||
goto set_flags;
|
break; /* Set flags. */
|
||||||
case SLJIT_SHL:
|
case SLJIT_SHL:
|
||||||
FAIL_IF(push_inst(compiler, (LSLV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));
|
FAIL_IF(push_inst(compiler, (LSLV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));
|
||||||
goto set_flags;
|
break; /* Set flags. */
|
||||||
case SLJIT_LSHR:
|
case SLJIT_LSHR:
|
||||||
FAIL_IF(push_inst(compiler, (LSRV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));
|
FAIL_IF(push_inst(compiler, (LSRV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));
|
||||||
goto set_flags;
|
break; /* Set flags. */
|
||||||
case SLJIT_ASHR:
|
case SLJIT_ASHR:
|
||||||
FAIL_IF(push_inst(compiler, (ASRV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));
|
FAIL_IF(push_inst(compiler, (ASRV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));
|
||||||
goto set_flags;
|
break; /* Set flags. */
|
||||||
}
|
default:
|
||||||
|
|
||||||
SLJIT_UNREACHABLE();
|
SLJIT_UNREACHABLE();
|
||||||
return SLJIT_SUCCESS;
|
return SLJIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
set_flags:
|
set_flags:
|
||||||
if (flags & SET_FLAGS)
|
if (flags & SET_FLAGS)
|
||||||
|
@ -1539,16 +1560,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c
|
||||||
/* Floating point operators */
|
/* Floating point operators */
|
||||||
/* --------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------- */
|
||||||
|
|
||||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_fpu_available(void)
|
|
||||||
{
|
|
||||||
#ifdef SLJIT_IS_FPU_AVAILABLE
|
|
||||||
return SLJIT_IS_FPU_AVAILABLE;
|
|
||||||
#else
|
|
||||||
/* Available by default. */
|
|
||||||
return 1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
|
static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
|
||||||
{
|
{
|
||||||
sljit_u32 shift = MEM_SIZE_SHIFT(flags);
|
sljit_u32 shift = MEM_SIZE_SHIFT(flags);
|
||||||
|
@ -2016,6 +2027,30 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
|
||||||
return emit_op_mem2(compiler, mem_flags | STORE, TMP_REG1, dst, dstw, 0, 0);
|
return emit_op_mem2(compiler, mem_flags | STORE, TMP_REG1, dst, dstw, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
|
||||||
|
sljit_s32 dst_reg,
|
||||||
|
sljit_s32 src, sljit_sw srcw)
|
||||||
|
{
|
||||||
|
sljit_ins inv_bits = (dst_reg & SLJIT_I32_OP) ? (1 << 31) : 0;
|
||||||
|
sljit_ins cc;
|
||||||
|
|
||||||
|
CHECK_ERROR();
|
||||||
|
CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
|
||||||
|
|
||||||
|
if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {
|
||||||
|
if (dst_reg & SLJIT_I32_OP)
|
||||||
|
srcw = (sljit_s32)srcw;
|
||||||
|
FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
|
||||||
|
src = TMP_REG1;
|
||||||
|
srcw = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cc = get_cc(type & 0xff);
|
||||||
|
dst_reg &= ~SLJIT_I32_OP;
|
||||||
|
|
||||||
|
return push_inst(compiler, (CSEL ^ inv_bits) | (cc << 12) | RD(dst_reg) | RN(src) | RM(dst_reg));
|
||||||
|
}
|
||||||
|
|
||||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
|
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
|
||||||
{
|
{
|
||||||
struct sljit_const *const_;
|
struct sljit_const *const_;
|
||||||
|
|
|
@ -107,7 +107,11 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
|
||||||
#define BLX 0x4780
|
#define BLX 0x4780
|
||||||
#define BX 0x4700
|
#define BX 0x4700
|
||||||
#define CLZ 0xfab0f080
|
#define CLZ 0xfab0f080
|
||||||
|
#define CMNI_W 0xf1100f00
|
||||||
|
#define CMP 0x4280
|
||||||
#define CMPI 0x2800
|
#define CMPI 0x2800
|
||||||
|
#define CMPI_W 0xf1b00f00
|
||||||
|
#define CMP_X 0x4500
|
||||||
#define CMP_W 0xebb00f00
|
#define CMP_W 0xebb00f00
|
||||||
#define EORI 0xf0800000
|
#define EORI 0xf0800000
|
||||||
#define EORS 0x4040
|
#define EORS 0x4040
|
||||||
|
@ -429,6 +433,27 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
||||||
return (void*)((sljit_uw)code | 0x1);
|
return (void*)((sljit_uw)code | 0x1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
|
||||||
|
{
|
||||||
|
switch (feature_type) {
|
||||||
|
case SLJIT_HAS_FPU:
|
||||||
|
#ifdef SLJIT_IS_FPU_AVAILABLE
|
||||||
|
return SLJIT_IS_FPU_AVAILABLE;
|
||||||
|
#else
|
||||||
|
/* Available by default. */
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case SLJIT_HAS_PRE_UPDATE:
|
||||||
|
case SLJIT_HAS_CLZ:
|
||||||
|
case SLJIT_HAS_CMOV:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------- */
|
||||||
/* Core code generator functions. */
|
/* Core code generator functions. */
|
||||||
/* --------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------- */
|
||||||
|
@ -566,9 +591,12 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
|
||||||
if (nimm <= 0xfff)
|
if (nimm <= 0xfff)
|
||||||
return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(nimm));
|
return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(nimm));
|
||||||
}
|
}
|
||||||
imm = get_imm(imm);
|
nimm = get_imm(imm);
|
||||||
if (imm != INVALID_IMM)
|
if (nimm != INVALID_IMM)
|
||||||
return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
|
return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm);
|
||||||
|
nimm = get_imm(-imm);
|
||||||
|
if (nimm != INVALID_IMM)
|
||||||
|
return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm);
|
||||||
break;
|
break;
|
||||||
case SLJIT_ADDC:
|
case SLJIT_ADDC:
|
||||||
imm = get_imm(imm);
|
imm = get_imm(imm);
|
||||||
|
@ -576,6 +604,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
|
||||||
return push_inst32(compiler, ADCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
|
return push_inst32(compiler, ADCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
|
||||||
break;
|
break;
|
||||||
case SLJIT_SUB:
|
case SLJIT_SUB:
|
||||||
|
/* SUB operation can be replaced by ADD because of the negative carry flag. */
|
||||||
if (flags & ARG1_IMM) {
|
if (flags & ARG1_IMM) {
|
||||||
if (imm == 0 && IS_2_LO_REGS(reg, dst))
|
if (imm == 0 && IS_2_LO_REGS(reg, dst))
|
||||||
return push_inst16(compiler, RSBSI | RD3(dst) | RN3(reg));
|
return push_inst16(compiler, RSBSI | RD3(dst) | RN3(reg));
|
||||||
|
@ -584,6 +613,16 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
|
||||||
return push_inst32(compiler, RSB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
|
return push_inst32(compiler, RSB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (flags & UNUSED_RETURN) {
|
||||||
|
if (imm <= 0xff && reg_map[reg] <= 7)
|
||||||
|
return push_inst16(compiler, CMPI | IMM8(imm) | RDN3(reg));
|
||||||
|
nimm = get_imm(imm);
|
||||||
|
if (nimm != INVALID_IMM)
|
||||||
|
return push_inst32(compiler, CMPI_W | RN4(reg) | nimm);
|
||||||
|
nimm = get_imm(-imm);
|
||||||
|
if (nimm != INVALID_IMM)
|
||||||
|
return push_inst32(compiler, CMNI_W | RN4(reg) | nimm);
|
||||||
|
}
|
||||||
nimm = -imm;
|
nimm = -imm;
|
||||||
if (IS_2_LO_REGS(reg, dst)) {
|
if (IS_2_LO_REGS(reg, dst)) {
|
||||||
if (imm <= 0x7)
|
if (imm <= 0x7)
|
||||||
|
@ -596,8 +635,6 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
|
||||||
if (nimm <= 0xff)
|
if (nimm <= 0xff)
|
||||||
return push_inst16(compiler, ADDSI8 | IMM8(nimm) | RDN3(dst));
|
return push_inst16(compiler, ADDSI8 | IMM8(nimm) | RDN3(dst));
|
||||||
}
|
}
|
||||||
if (imm <= 0xff && (flags & UNUSED_RETURN))
|
|
||||||
return push_inst16(compiler, CMPI | IMM8(imm) | RDN3(reg));
|
|
||||||
}
|
}
|
||||||
if (!(flags & SET_FLAGS)) {
|
if (!(flags & SET_FLAGS)) {
|
||||||
if (imm <= 0xfff)
|
if (imm <= 0xfff)
|
||||||
|
@ -605,9 +642,12 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
|
||||||
if (nimm <= 0xfff)
|
if (nimm <= 0xfff)
|
||||||
return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(nimm));
|
return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(nimm));
|
||||||
}
|
}
|
||||||
imm = get_imm(imm);
|
nimm = get_imm(imm);
|
||||||
if (imm != INVALID_IMM)
|
if (nimm != INVALID_IMM)
|
||||||
return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
|
return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm);
|
||||||
|
nimm = get_imm(-imm);
|
||||||
|
if (nimm != INVALID_IMM)
|
||||||
|
return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm);
|
||||||
break;
|
break;
|
||||||
case SLJIT_SUBC:
|
case SLJIT_SUBC:
|
||||||
if (flags & ARG1_IMM)
|
if (flags & ARG1_IMM)
|
||||||
|
@ -729,11 +769,6 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
|
||||||
case SLJIT_CLZ:
|
case SLJIT_CLZ:
|
||||||
SLJIT_ASSERT(arg1 == TMP_REG2);
|
SLJIT_ASSERT(arg1 == TMP_REG2);
|
||||||
FAIL_IF(push_inst32(compiler, CLZ | RN4(arg2) | RD4(dst) | RM4(arg2)));
|
FAIL_IF(push_inst32(compiler, CLZ | RN4(arg2) | RD4(dst) | RM4(arg2)));
|
||||||
if (flags & SET_FLAGS) {
|
|
||||||
if (reg_map[dst] <= 7)
|
|
||||||
return push_inst16(compiler, CMPI | RDN3(dst));
|
|
||||||
return push_inst32(compiler, ADD_WI | SET_FLAGS | RN4(dst) | RD4(dst));
|
|
||||||
}
|
|
||||||
return SLJIT_SUCCESS;
|
return SLJIT_SUCCESS;
|
||||||
case SLJIT_ADD:
|
case SLJIT_ADD:
|
||||||
if (IS_3_LO_REGS(dst, arg1, arg2))
|
if (IS_3_LO_REGS(dst, arg1, arg2))
|
||||||
|
@ -746,6 +781,11 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
|
||||||
return push_inst16(compiler, ADCS | RD3(dst) | RN3(arg2));
|
return push_inst16(compiler, ADCS | RD3(dst) | RN3(arg2));
|
||||||
return push_inst32(compiler, ADC_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
|
return push_inst32(compiler, ADC_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
|
||||||
case SLJIT_SUB:
|
case SLJIT_SUB:
|
||||||
|
if (flags & UNUSED_RETURN) {
|
||||||
|
if (IS_2_LO_REGS(arg1, arg2))
|
||||||
|
return push_inst16(compiler, CMP | RD3(arg1) | RN3(arg2));
|
||||||
|
return push_inst16(compiler, CMP_X | SET_REGS44(arg1, arg2));
|
||||||
|
}
|
||||||
if (IS_3_LO_REGS(dst, arg1, arg2))
|
if (IS_3_LO_REGS(dst, arg1, arg2))
|
||||||
return push_inst16(compiler, SUBS | RD3(dst) | RN3(arg1) | RM3(arg2));
|
return push_inst16(compiler, SUBS | RD3(dst) | RN3(arg1) | RM3(arg2));
|
||||||
return push_inst32(compiler, SUB_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
|
return push_inst32(compiler, SUB_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
|
||||||
|
@ -1407,16 +1447,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c
|
||||||
/* Floating point operators */
|
/* Floating point operators */
|
||||||
/* --------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------- */
|
||||||
|
|
||||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_fpu_available(void)
|
|
||||||
{
|
|
||||||
#ifdef SLJIT_IS_FPU_AVAILABLE
|
|
||||||
return SLJIT_IS_FPU_AVAILABLE;
|
|
||||||
#else
|
|
||||||
/* Available by default. */
|
|
||||||
return 1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#define FPU_LOAD (1 << 20)
|
#define FPU_LOAD (1 << 20)
|
||||||
|
|
||||||
static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
|
static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
|
||||||
|
@ -1830,6 +1860,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
|
||||||
FAIL_IF(push_inst32(compiler, MOV_WI | RD4(dst_r) | 1));
|
FAIL_IF(push_inst32(compiler, MOV_WI | RD4(dst_r) | 1));
|
||||||
FAIL_IF(push_inst32(compiler, MOV_WI | RD4(dst_r) | 0));
|
FAIL_IF(push_inst32(compiler, MOV_WI | RD4(dst_r) | 0));
|
||||||
} else {
|
} else {
|
||||||
|
/* The movsi (immediate) instruction does not set flags in IT block. */
|
||||||
FAIL_IF(push_inst16(compiler, MOVSI | RDN3(dst_r) | 1));
|
FAIL_IF(push_inst16(compiler, MOVSI | RDN3(dst_r) | 1));
|
||||||
FAIL_IF(push_inst16(compiler, MOVSI | RDN3(dst_r) | 0));
|
FAIL_IF(push_inst16(compiler, MOVSI | RDN3(dst_r) | 0));
|
||||||
}
|
}
|
||||||
|
@ -1885,6 +1916,54 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
|
||||||
return SLJIT_SUCCESS;
|
return SLJIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
|
||||||
|
sljit_s32 dst_reg,
|
||||||
|
sljit_s32 src, sljit_sw srcw)
|
||||||
|
{
|
||||||
|
sljit_uw cc, tmp;
|
||||||
|
|
||||||
|
CHECK_ERROR();
|
||||||
|
CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
|
||||||
|
|
||||||
|
dst_reg &= ~SLJIT_I32_OP;
|
||||||
|
|
||||||
|
cc = get_cc(type & 0xff);
|
||||||
|
|
||||||
|
if (!(src & SLJIT_IMM)) {
|
||||||
|
FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
|
||||||
|
return push_inst16(compiler, MOV | SET_REGS44(dst_reg, src));
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp = (sljit_uw) srcw;
|
||||||
|
|
||||||
|
if (tmp < 0x10000) {
|
||||||
|
/* set low 16 bits, set hi 16 bits to 0. */
|
||||||
|
FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
|
||||||
|
return push_inst32(compiler, MOVW | RD4(dst_reg) |
|
||||||
|
COPY_BITS(tmp, 12, 16, 4) | COPY_BITS(tmp, 11, 26, 1) | COPY_BITS(tmp, 8, 12, 3) | (tmp & 0xff));
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp = get_imm(srcw);
|
||||||
|
if (tmp != INVALID_IMM) {
|
||||||
|
FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
|
||||||
|
return push_inst32(compiler, MOV_WI | RD4(dst_reg) | tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp = get_imm(~srcw);
|
||||||
|
if (tmp != INVALID_IMM) {
|
||||||
|
FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
|
||||||
|
return push_inst32(compiler, MVN_WI | RD4(dst_reg) | tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
FAIL_IF(push_inst16(compiler, IT | (cc << 4) | ((cc & 0x1) << 3) | 0x4));
|
||||||
|
|
||||||
|
tmp = (sljit_uw) srcw;
|
||||||
|
FAIL_IF(push_inst32(compiler, MOVW | RD4(dst_reg) |
|
||||||
|
COPY_BITS(tmp, 12, 16, 4) | COPY_BITS(tmp, 11, 26, 1) | COPY_BITS(tmp, 8, 12, 3) | (tmp & 0xff)));
|
||||||
|
return push_inst32(compiler, MOVT | RD4(dst_reg) |
|
||||||
|
COPY_BITS(tmp, 12 + 16, 16, 4) | COPY_BITS(tmp, 11 + 16, 26, 1) | COPY_BITS(tmp, 8 + 16, 12, 3) | ((tmp & 0xff0000) >> 16));
|
||||||
|
}
|
||||||
|
|
||||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
|
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
|
||||||
{
|
{
|
||||||
struct sljit_const *const_;
|
struct sljit_const *const_;
|
||||||
|
|
|
@ -149,8 +149,6 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
|
||||||
FAIL_IF(push_inst(compiler, ADDIU | S(dst) | T(dst) | IMM(1), DR(dst)));
|
FAIL_IF(push_inst(compiler, ADDIU | S(dst) | T(dst) | IMM(1), DR(dst)));
|
||||||
FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS));
|
FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS));
|
||||||
FAIL_IF(push_inst(compiler, SLL | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS));
|
FAIL_IF(push_inst(compiler, SLL | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS));
|
||||||
if (op & SLJIT_SET_Z)
|
|
||||||
return push_inst(compiler, ADDU | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG);
|
|
||||||
#endif
|
#endif
|
||||||
return SLJIT_SUCCESS;
|
return SLJIT_SUCCESS;
|
||||||
|
|
||||||
|
|
|
@ -240,8 +240,6 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
|
||||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(dst) | T(dst) | IMM(1), DR(dst)));
|
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(dst) | T(dst) | IMM(1), DR(dst)));
|
||||||
FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS));
|
FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS));
|
||||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSLL, SLL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS));
|
FAIL_IF(push_inst(compiler, SELECT_OP(DSLL, SLL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS));
|
||||||
if (op & SLJIT_SET_Z)
|
|
||||||
return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG);
|
|
||||||
#endif
|
#endif
|
||||||
return SLJIT_SUCCESS;
|
return SLJIT_SUCCESS;
|
||||||
|
|
||||||
|
|
|
@ -173,6 +173,10 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
|
||||||
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
|
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
|
||||||
#define CLZ (HI(28) | LO(32))
|
#define CLZ (HI(28) | LO(32))
|
||||||
#define DCLZ (HI(28) | LO(36))
|
#define DCLZ (HI(28) | LO(36))
|
||||||
|
#define MOVF (HI(0) | (0 << 16) | LO(1))
|
||||||
|
#define MOVN (HI(0) | LO(11))
|
||||||
|
#define MOVT (HI(0) | (1 << 16) | LO(1))
|
||||||
|
#define MOVZ (HI(0) | LO(10))
|
||||||
#define MUL (HI(28) | LO(2))
|
#define MUL (HI(28) | LO(2))
|
||||||
#define SEB (HI(31) | (16 << 6) | LO(32))
|
#define SEB (HI(31) | (16 << 6) | LO(32))
|
||||||
#define SEH (HI(31) | (24 << 6) | LO(32))
|
#define SEH (HI(31) | (24 << 6) | LO(32))
|
||||||
|
@ -490,6 +494,31 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
|
||||||
|
{
|
||||||
|
switch (feature_type) {
|
||||||
|
case SLJIT_HAS_FPU:
|
||||||
|
#ifdef SLJIT_IS_FPU_AVAILABLE
|
||||||
|
return SLJIT_IS_FPU_AVAILABLE;
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
sljit_sw fir;
|
||||||
|
asm ("cfc1 %0, $0" : "=r"(fir));
|
||||||
|
return (fir >> 22) & 0x1;
|
||||||
|
#else
|
||||||
|
#error "FIR check is not implemented for this architecture"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
|
||||||
|
case SLJIT_HAS_CLZ:
|
||||||
|
case SLJIT_HAS_CMOV:
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------- */
|
||||||
/* Entry, exit */
|
/* Entry, exit */
|
||||||
/* --------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------- */
|
||||||
|
@ -1250,19 +1279,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c
|
||||||
/* Floating point operators */
|
/* Floating point operators */
|
||||||
/* --------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------- */
|
||||||
|
|
||||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_fpu_available(void)
|
|
||||||
{
|
|
||||||
#ifdef SLJIT_IS_FPU_AVAILABLE
|
|
||||||
return SLJIT_IS_FPU_AVAILABLE;
|
|
||||||
#elif defined(__GNUC__)
|
|
||||||
sljit_sw fir;
|
|
||||||
asm ("cfc1 %0, $0" : "=r"(fir));
|
|
||||||
return (fir >> 22) & 0x1;
|
|
||||||
#else
|
|
||||||
#error "FIR check is not implemented for this architecture"
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_F32_OP) >> 7))
|
#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_F32_OP) >> 7))
|
||||||
#define FMT(op) (((op & SLJIT_F32_OP) ^ SLJIT_F32_OP) << (21 - 8))
|
#define FMT(op) (((op & SLJIT_F32_OP) ^ SLJIT_F32_OP) << (21 - 8))
|
||||||
|
|
||||||
|
@ -1976,6 +1992,79 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
|
||||||
|
sljit_s32 dst_reg,
|
||||||
|
sljit_s32 src, sljit_sw srcw)
|
||||||
|
{
|
||||||
|
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
|
||||||
|
sljit_ins ins;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CHECK_ERROR();
|
||||||
|
CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
|
||||||
|
|
||||||
|
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
|
||||||
|
|
||||||
|
if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {
|
||||||
|
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
||||||
|
if (dst_reg & SLJIT_I32_OP)
|
||||||
|
srcw = (sljit_s32)srcw;
|
||||||
|
#endif
|
||||||
|
FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));
|
||||||
|
src = TMP_REG1;
|
||||||
|
srcw = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dst_reg &= ~SLJIT_I32_OP;
|
||||||
|
|
||||||
|
switch (type & 0xff) {
|
||||||
|
case SLJIT_EQUAL:
|
||||||
|
ins = MOVZ | TA(EQUAL_FLAG);
|
||||||
|
break;
|
||||||
|
case SLJIT_NOT_EQUAL:
|
||||||
|
ins = MOVN | TA(EQUAL_FLAG);
|
||||||
|
break;
|
||||||
|
case SLJIT_LESS:
|
||||||
|
case SLJIT_GREATER:
|
||||||
|
case SLJIT_SIG_LESS:
|
||||||
|
case SLJIT_SIG_GREATER:
|
||||||
|
case SLJIT_OVERFLOW:
|
||||||
|
case SLJIT_MUL_OVERFLOW:
|
||||||
|
ins = MOVN | TA(OTHER_FLAG);
|
||||||
|
break;
|
||||||
|
case SLJIT_GREATER_EQUAL:
|
||||||
|
case SLJIT_LESS_EQUAL:
|
||||||
|
case SLJIT_SIG_GREATER_EQUAL:
|
||||||
|
case SLJIT_SIG_LESS_EQUAL:
|
||||||
|
case SLJIT_NOT_OVERFLOW:
|
||||||
|
case SLJIT_MUL_NOT_OVERFLOW:
|
||||||
|
ins = MOVZ | TA(OTHER_FLAG);
|
||||||
|
break;
|
||||||
|
case SLJIT_EQUAL_F64:
|
||||||
|
case SLJIT_LESS_F64:
|
||||||
|
case SLJIT_LESS_EQUAL_F64:
|
||||||
|
case SLJIT_UNORDERED_F64:
|
||||||
|
ins = MOVT;
|
||||||
|
break;
|
||||||
|
case SLJIT_NOT_EQUAL_F64:
|
||||||
|
case SLJIT_GREATER_EQUAL_F64:
|
||||||
|
case SLJIT_GREATER_F64:
|
||||||
|
case SLJIT_ORDERED_F64:
|
||||||
|
ins = MOVF;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ins = MOVZ | TA(OTHER_FLAG);
|
||||||
|
SLJIT_UNREACHABLE();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return push_inst(compiler, ins | S(src) | D(dst_reg), DR(dst_reg));
|
||||||
|
|
||||||
|
#else
|
||||||
|
return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
|
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
|
||||||
{
|
{
|
||||||
struct sljit_const *const_;
|
struct sljit_const *const_;
|
||||||
|
|
|
@ -88,63 +88,84 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
|
||||||
|
|
||||||
case SLJIT_NEG:
|
case SLJIT_NEG:
|
||||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||||
return push_inst(compiler, NEG | OERC(flags) | D(dst) | A(src2));
|
/* Setting XER SO is not enough, CR SO is also needed. */
|
||||||
|
return push_inst(compiler, NEG | OE((flags & ALT_FORM1) ? ALT_SET_FLAGS : 0) | RC(flags) | D(dst) | A(src2));
|
||||||
|
|
||||||
case SLJIT_CLZ:
|
case SLJIT_CLZ:
|
||||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||||
return push_inst(compiler, CNTLZW | RC(flags) | S(src2) | A(dst));
|
return push_inst(compiler, CNTLZW | S(src2) | A(dst));
|
||||||
|
|
||||||
case SLJIT_ADD:
|
case SLJIT_ADD:
|
||||||
if (flags & ALT_FORM1) {
|
if (flags & ALT_FORM1) {
|
||||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
/* Setting XER SO is not enough, CR SO is also needed. */
|
||||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
return push_inst(compiler, ADD | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
|
||||||
return push_inst(compiler, ADDI | D(dst) | A(src1) | compiler->imm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & ALT_FORM2) {
|
if (flags & ALT_FORM2) {
|
||||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
||||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||||
|
|
||||||
|
if (flags & ALT_FORM3)
|
||||||
return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm);
|
return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm);
|
||||||
|
|
||||||
|
if (flags & ALT_FORM4) {
|
||||||
|
FAIL_IF(push_inst(compiler, ADDIS | D(dst) | A(src1) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1))));
|
||||||
|
src1 = dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
return push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff));
|
||||||
}
|
}
|
||||||
if (flags & ALT_FORM3) {
|
if (flags & ALT_FORM3) {
|
||||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||||
return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm);
|
return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm);
|
||||||
}
|
}
|
||||||
if (flags & ALT_FORM4) {
|
|
||||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
|
||||||
FAIL_IF(push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff)));
|
|
||||||
return push_inst(compiler, ADDIS | D(dst) | A(dst) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1)));
|
|
||||||
}
|
|
||||||
if (!(flags & ALT_SET_FLAGS))
|
if (!(flags & ALT_SET_FLAGS))
|
||||||
return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2));
|
return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2));
|
||||||
return push_inst(compiler, ADDC | OERC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
|
if (flags & ALT_FORM4)
|
||||||
|
return push_inst(compiler, ADDC | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
|
||||||
|
return push_inst(compiler, ADD | RC(flags) | D(dst) | A(src1) | B(src2));
|
||||||
|
|
||||||
case SLJIT_ADDC:
|
case SLJIT_ADDC:
|
||||||
return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2));
|
return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2));
|
||||||
|
|
||||||
case SLJIT_SUB:
|
case SLJIT_SUB:
|
||||||
if (flags & ALT_FORM1) {
|
if (flags & ALT_FORM1) {
|
||||||
|
if (flags & ALT_FORM2) {
|
||||||
|
FAIL_IF(push_inst(compiler, CMPLI | CRD(0) | A(src1) | compiler->imm));
|
||||||
|
if (!(flags & ALT_FORM3))
|
||||||
|
return SLJIT_SUCCESS;
|
||||||
|
return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));
|
||||||
|
}
|
||||||
|
FAIL_IF(push_inst(compiler, CMPL | CRD(0) | A(src1) | B(src2)));
|
||||||
|
if (!(flags & ALT_FORM3))
|
||||||
|
return SLJIT_SUCCESS;
|
||||||
|
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & ALT_FORM2) {
|
||||||
|
/* Setting XER SO is not enough, CR SO is also needed. */
|
||||||
|
return push_inst(compiler, SUBF | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & ALT_FORM3) {
|
||||||
|
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
||||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||||
return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);
|
return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);
|
||||||
}
|
}
|
||||||
if (flags & (ALT_FORM2 | ALT_FORM3)) {
|
|
||||||
|
if (flags & ALT_FORM4) {
|
||||||
|
if (flags & ALT_FORM5) {
|
||||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||||
return push_inst(compiler, ((flags & ALT_FORM2) ? CMPI : CMPLI) | CRD(0) | A(src1) | compiler->imm);
|
return push_inst(compiler, CMPI | CRD(0) | A(src1) | compiler->imm);
|
||||||
}
|
}
|
||||||
if (flags & (ALT_FORM4 | ALT_FORM5)) {
|
return push_inst(compiler, CMP | CRD(0) | A(src1) | B(src2));
|
||||||
return push_inst(compiler, ((flags & ALT_FORM4) ? CMP : CMPL) | CRD(0) | A(src1) | B(src2));
|
|
||||||
}
|
|
||||||
if (flags & ALT_FORM6) {
|
|
||||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
|
||||||
FAIL_IF(push_inst(compiler, CMPLI | CRD(0) | A(src1) | compiler->imm));
|
|
||||||
return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));
|
|
||||||
}
|
|
||||||
if (flags & ALT_FORM7) {
|
|
||||||
FAIL_IF(push_inst(compiler, CMPL | CRD(0) | A(src1) | B(src2)));
|
|
||||||
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(flags & ALT_SET_FLAGS))
|
if (!(flags & ALT_SET_FLAGS))
|
||||||
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
|
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
|
||||||
return push_inst(compiler, SUBFC | OERC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
|
if (flags & ALT_FORM5)
|
||||||
|
return push_inst(compiler, SUBFC | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
|
||||||
|
return push_inst(compiler, SUBF | RC(flags) | D(dst) | A(src2) | B(src1));
|
||||||
|
|
||||||
case SLJIT_SUBC:
|
case SLJIT_SUBC:
|
||||||
return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1));
|
return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1));
|
||||||
|
@ -154,7 +175,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
|
||||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||||
return push_inst(compiler, MULLI | D(dst) | A(src1) | compiler->imm);
|
return push_inst(compiler, MULLI | D(dst) | A(src1) | compiler->imm);
|
||||||
}
|
}
|
||||||
return push_inst(compiler, MULLW | OERC(flags) | D(dst) | A(src2) | B(src1));
|
return push_inst(compiler, MULLW | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1));
|
||||||
|
|
||||||
case SLJIT_AND:
|
case SLJIT_AND:
|
||||||
if (flags & ALT_FORM1) {
|
if (flags & ALT_FORM1) {
|
||||||
|
|
|
@ -204,40 +204,63 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
|
||||||
|
|
||||||
case SLJIT_NEG:
|
case SLJIT_NEG:
|
||||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||||
|
|
||||||
|
if ((flags & (ALT_FORM1 | ALT_SIGN_EXT)) == (ALT_FORM1 | ALT_SIGN_EXT)) {
|
||||||
|
FAIL_IF(push_inst(compiler, RLDI(TMP_REG2, src2, 32, 31, 1)));
|
||||||
|
FAIL_IF(push_inst(compiler, NEG | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(TMP_REG2)));
|
||||||
|
return push_inst(compiler, RLDI(dst, dst, 32, 32, 0));
|
||||||
|
}
|
||||||
|
|
||||||
UN_EXTS();
|
UN_EXTS();
|
||||||
return push_inst(compiler, NEG | OERC(flags) | D(dst) | A(src2));
|
/* Setting XER SO is not enough, CR SO is also needed. */
|
||||||
|
return push_inst(compiler, NEG | OE((flags & ALT_FORM1) ? ALT_SET_FLAGS : 0) | RC(flags) | D(dst) | A(src2));
|
||||||
|
|
||||||
case SLJIT_CLZ:
|
case SLJIT_CLZ:
|
||||||
SLJIT_ASSERT(src1 == TMP_REG1);
|
SLJIT_ASSERT(src1 == TMP_REG1);
|
||||||
if (flags & ALT_FORM1)
|
if (flags & ALT_FORM1)
|
||||||
return push_inst(compiler, CNTLZW | RC(flags) | S(src2) | A(dst));
|
return push_inst(compiler, CNTLZW | S(src2) | A(dst));
|
||||||
return push_inst(compiler, CNTLZD | RC(flags) | S(src2) | A(dst));
|
return push_inst(compiler, CNTLZD | S(src2) | A(dst));
|
||||||
|
|
||||||
case SLJIT_ADD:
|
case SLJIT_ADD:
|
||||||
if (flags & ALT_FORM1) {
|
if (flags & ALT_FORM1) {
|
||||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
if (flags & ALT_SIGN_EXT) {
|
||||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, src1, 32, 31, 1)));
|
||||||
return push_inst(compiler, ADDI | D(dst) | A(src1) | compiler->imm);
|
src1 = TMP_REG1;
|
||||||
|
FAIL_IF(push_inst(compiler, RLDI(TMP_REG2, src2, 32, 31, 1)));
|
||||||
|
src2 = TMP_REG2;
|
||||||
}
|
}
|
||||||
|
/* Setting XER SO is not enough, CR SO is also needed. */
|
||||||
|
FAIL_IF(push_inst(compiler, ADD | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2)));
|
||||||
|
if (flags & ALT_SIGN_EXT)
|
||||||
|
return push_inst(compiler, RLDI(dst, dst, 32, 32, 0));
|
||||||
|
return SLJIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
if (flags & ALT_FORM2) {
|
if (flags & ALT_FORM2) {
|
||||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
||||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||||
|
|
||||||
|
if (flags & ALT_FORM3)
|
||||||
return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm);
|
return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm);
|
||||||
|
|
||||||
|
if (flags & ALT_FORM4) {
|
||||||
|
FAIL_IF(push_inst(compiler, ADDIS | D(dst) | A(src1) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1))));
|
||||||
|
src1 = dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
return push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff));
|
||||||
}
|
}
|
||||||
if (flags & ALT_FORM3) {
|
if (flags & ALT_FORM3) {
|
||||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||||
BIN_IMM_EXTS();
|
BIN_IMM_EXTS();
|
||||||
return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm);
|
return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm);
|
||||||
}
|
}
|
||||||
if (flags & ALT_FORM4) {
|
|
||||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
|
||||||
FAIL_IF(push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff)));
|
|
||||||
return push_inst(compiler, ADDIS | D(dst) | A(dst) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1)));
|
|
||||||
}
|
|
||||||
if (!(flags & ALT_SET_FLAGS))
|
if (!(flags & ALT_SET_FLAGS))
|
||||||
return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2));
|
return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2));
|
||||||
BIN_EXTS();
|
BIN_EXTS();
|
||||||
return push_inst(compiler, ADDC | OERC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
|
if (flags & ALT_FORM4)
|
||||||
|
return push_inst(compiler, ADDC | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
|
||||||
|
return push_inst(compiler, ADD | RC(flags) | D(dst) | A(src1) | B(src2));
|
||||||
|
|
||||||
case SLJIT_ADDC:
|
case SLJIT_ADDC:
|
||||||
BIN_EXTS();
|
BIN_EXTS();
|
||||||
|
@ -245,30 +268,52 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
|
||||||
|
|
||||||
case SLJIT_SUB:
|
case SLJIT_SUB:
|
||||||
if (flags & ALT_FORM1) {
|
if (flags & ALT_FORM1) {
|
||||||
|
if (flags & ALT_FORM2) {
|
||||||
|
FAIL_IF(push_inst(compiler, CMPLI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm));
|
||||||
|
if (!(flags & ALT_FORM3))
|
||||||
|
return SLJIT_SUCCESS;
|
||||||
|
return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));
|
||||||
|
}
|
||||||
|
FAIL_IF(push_inst(compiler, CMPL | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)));
|
||||||
|
if (!(flags & ALT_FORM3))
|
||||||
|
return SLJIT_SUCCESS;
|
||||||
|
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & ALT_FORM2) {
|
||||||
|
if (flags & ALT_SIGN_EXT) {
|
||||||
|
FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, src1, 32, 31, 1)));
|
||||||
|
src1 = TMP_REG1;
|
||||||
|
FAIL_IF(push_inst(compiler, RLDI(TMP_REG2, src2, 32, 31, 1)));
|
||||||
|
src2 = TMP_REG2;
|
||||||
|
}
|
||||||
|
/* Setting XER SO is not enough, CR SO is also needed. */
|
||||||
|
FAIL_IF(push_inst(compiler, SUBF | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1)));
|
||||||
|
if (flags & ALT_SIGN_EXT)
|
||||||
|
return push_inst(compiler, RLDI(dst, dst, 32, 32, 0));
|
||||||
|
return SLJIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & ALT_FORM3) {
|
||||||
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
|
||||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||||
return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);
|
return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);
|
||||||
}
|
}
|
||||||
if (flags & (ALT_FORM2 | ALT_FORM3)) {
|
|
||||||
|
if (flags & ALT_FORM4) {
|
||||||
|
if (flags & ALT_FORM5) {
|
||||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
SLJIT_ASSERT(src2 == TMP_REG2);
|
||||||
return push_inst(compiler, ((flags & ALT_FORM2) ? CMPI : CMPLI) | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm);
|
return push_inst(compiler, CMPI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm);
|
||||||
}
|
}
|
||||||
if (flags & (ALT_FORM4 | ALT_FORM5)) {
|
return push_inst(compiler, CMP | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2));
|
||||||
return push_inst(compiler, ((flags & ALT_FORM4) ? CMP : CMPL) | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2));
|
|
||||||
}
|
|
||||||
if (flags & ALT_FORM6) {
|
|
||||||
SLJIT_ASSERT(src2 == TMP_REG2);
|
|
||||||
FAIL_IF(push_inst(compiler, CMPLI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm));
|
|
||||||
return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));
|
|
||||||
}
|
|
||||||
if (flags & ALT_FORM7) {
|
|
||||||
FAIL_IF(push_inst(compiler, CMPL | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)));
|
|
||||||
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(flags & ALT_SET_FLAGS))
|
if (!(flags & ALT_SET_FLAGS))
|
||||||
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
|
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
|
||||||
BIN_EXTS();
|
BIN_EXTS();
|
||||||
return push_inst(compiler, SUBFC | OERC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
|
if (flags & ALT_FORM5)
|
||||||
|
return push_inst(compiler, SUBFC | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
|
||||||
|
return push_inst(compiler, SUBF | RC(flags) | D(dst) | A(src2) | B(src1));
|
||||||
|
|
||||||
case SLJIT_SUBC:
|
case SLJIT_SUBC:
|
||||||
BIN_EXTS();
|
BIN_EXTS();
|
||||||
|
@ -281,8 +326,8 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
|
||||||
}
|
}
|
||||||
BIN_EXTS();
|
BIN_EXTS();
|
||||||
if (flags & ALT_FORM2)
|
if (flags & ALT_FORM2)
|
||||||
return push_inst(compiler, MULLW | OERC(flags) | D(dst) | A(src2) | B(src1));
|
return push_inst(compiler, MULLW | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1));
|
||||||
return push_inst(compiler, MULLD | OERC(flags) | D(dst) | A(src2) | B(src1));
|
return push_inst(compiler, MULLD | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1));
|
||||||
|
|
||||||
case SLJIT_AND:
|
case SLJIT_AND:
|
||||||
if (flags & ALT_FORM1) {
|
if (flags & ALT_FORM1) {
|
||||||
|
|
|
@ -127,9 +127,9 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = {
|
||||||
|
|
||||||
/* Instruction bit sections.
|
/* Instruction bit sections.
|
||||||
OE and Rc flag (see ALT_SET_FLAGS). */
|
OE and Rc flag (see ALT_SET_FLAGS). */
|
||||||
#define OERC(flags) (((flags & ALT_SET_FLAGS) >> 10) | (flags & ALT_SET_FLAGS))
|
#define OE(flags) ((flags) & ALT_SET_FLAGS)
|
||||||
/* Rc flag (see ALT_SET_FLAGS). */
|
/* Rc flag (see ALT_SET_FLAGS). */
|
||||||
#define RC(flags) ((flags & ALT_SET_FLAGS) >> 10)
|
#define RC(flags) (((flags) & ALT_SET_FLAGS) >> 10)
|
||||||
#define HI(opcode) ((opcode) << 26)
|
#define HI(opcode) ((opcode) << 26)
|
||||||
#define LO(opcode) ((opcode) << 1)
|
#define LO(opcode) ((opcode) << 1)
|
||||||
|
|
||||||
|
@ -524,6 +524,26 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
|
||||||
|
{
|
||||||
|
switch (feature_type) {
|
||||||
|
case SLJIT_HAS_FPU:
|
||||||
|
#ifdef SLJIT_IS_FPU_AVAILABLE
|
||||||
|
return SLJIT_IS_FPU_AVAILABLE;
|
||||||
|
#else
|
||||||
|
/* Available by default. */
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case SLJIT_HAS_PRE_UPDATE:
|
||||||
|
case SLJIT_HAS_CLZ:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------- */
|
||||||
/* Entry, exit */
|
/* Entry, exit */
|
||||||
/* --------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------- */
|
||||||
|
@ -558,8 +578,6 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
||||||
#define ALT_FORM3 0x040000
|
#define ALT_FORM3 0x040000
|
||||||
#define ALT_FORM4 0x080000
|
#define ALT_FORM4 0x080000
|
||||||
#define ALT_FORM5 0x100000
|
#define ALT_FORM5 0x100000
|
||||||
#define ALT_FORM6 0x200000
|
|
||||||
#define ALT_FORM7 0x400000
|
|
||||||
|
|
||||||
/* Source and destination is register. */
|
/* Source and destination is register. */
|
||||||
#define REG_DEST 0x000001
|
#define REG_DEST 0x000001
|
||||||
|
@ -574,7 +592,7 @@ ALT_SIGN_EXT 0x000200
|
||||||
ALT_SET_FLAGS 0x000400
|
ALT_SET_FLAGS 0x000400
|
||||||
ALT_FORM1 0x010000
|
ALT_FORM1 0x010000
|
||||||
...
|
...
|
||||||
ALT_FORM7 0x400000 */
|
ALT_FORM5 0x100000 */
|
||||||
|
|
||||||
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
|
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
|
||||||
#include "sljitNativePPC_32.c"
|
#include "sljitNativePPC_32.c"
|
||||||
|
@ -1142,7 +1160,7 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
|
||||||
sljit_s32 src1_r;
|
sljit_s32 src1_r;
|
||||||
sljit_s32 src2_r;
|
sljit_s32 src2_r;
|
||||||
sljit_s32 sugg_src2_r = TMP_REG2;
|
sljit_s32 sugg_src2_r = TMP_REG2;
|
||||||
sljit_s32 flags = input_flags & (ALT_FORM1 | ALT_FORM2 | ALT_FORM3 | ALT_FORM4 | ALT_FORM5 | ALT_FORM6 | ALT_FORM7 | ALT_SIGN_EXT | ALT_SET_FLAGS);
|
sljit_s32 flags = input_flags & (ALT_FORM1 | ALT_FORM2 | ALT_FORM3 | ALT_FORM4 | ALT_FORM5 | ALT_SIGN_EXT | ALT_SET_FLAGS);
|
||||||
|
|
||||||
if (!(input_flags & ALT_KEEP_CACHE)) {
|
if (!(input_flags & ALT_KEEP_CACHE)) {
|
||||||
compiler->cache_arg = 0;
|
compiler->cache_arg = 0;
|
||||||
|
@ -1350,6 +1368,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
||||||
flags |= INT_DATA | SIGNED_DATA;
|
flags |= INT_DATA | SIGNED_DATA;
|
||||||
if (src & SLJIT_IMM)
|
if (src & SLJIT_IMM)
|
||||||
srcw = (sljit_s32)srcw;
|
srcw = (sljit_s32)srcw;
|
||||||
|
if (HAS_FLAGS(op_flags))
|
||||||
|
flags |= ALT_SIGN_EXT;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -1415,7 +1435,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
||||||
return emit_op(compiler, SLJIT_NOT, flags, dst, dstw, TMP_REG1, 0, src, srcw);
|
return emit_op(compiler, SLJIT_NOT, flags, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||||
|
|
||||||
case SLJIT_NEG:
|
case SLJIT_NEG:
|
||||||
return emit_op(compiler, SLJIT_NEG, flags, dst, dstw, TMP_REG1, 0, src, srcw);
|
return emit_op(compiler, SLJIT_NEG, flags | (GET_FLAG_TYPE(op_flags) ? ALT_FORM1 : 0), dst, dstw, TMP_REG1, 0, src, srcw);
|
||||||
|
|
||||||
case SLJIT_CLZ:
|
case SLJIT_CLZ:
|
||||||
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||||
|
@ -1500,31 +1520,34 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
|
||||||
|
|
||||||
switch (GET_OPCODE(op)) {
|
switch (GET_OPCODE(op)) {
|
||||||
case SLJIT_ADD:
|
case SLJIT_ADD:
|
||||||
|
if (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW || GET_FLAG_TYPE(op) == SLJIT_NOT_OVERFLOW)
|
||||||
|
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w);
|
||||||
|
|
||||||
if (!HAS_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) {
|
if (!HAS_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) {
|
||||||
if (TEST_SL_IMM(src2, src2w)) {
|
if (TEST_SL_IMM(src2, src2w)) {
|
||||||
compiler->imm = src2w & 0xffff;
|
compiler->imm = src2w & 0xffff;
|
||||||
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
|
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
|
||||||
}
|
}
|
||||||
if (TEST_SL_IMM(src1, src1w)) {
|
if (TEST_SL_IMM(src1, src1w)) {
|
||||||
compiler->imm = src1w & 0xffff;
|
compiler->imm = src1w & 0xffff;
|
||||||
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
|
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
|
||||||
}
|
}
|
||||||
if (TEST_SH_IMM(src2, src2w)) {
|
if (TEST_SH_IMM(src2, src2w)) {
|
||||||
compiler->imm = (src2w >> 16) & 0xffff;
|
compiler->imm = (src2w >> 16) & 0xffff;
|
||||||
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
|
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
|
||||||
}
|
}
|
||||||
if (TEST_SH_IMM(src1, src1w)) {
|
if (TEST_SH_IMM(src1, src1w)) {
|
||||||
compiler->imm = (src1w >> 16) & 0xffff;
|
compiler->imm = (src1w >> 16) & 0xffff;
|
||||||
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
|
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
|
||||||
}
|
}
|
||||||
/* Range between -1 and -32768 is covered above. */
|
/* Range between -1 and -32768 is covered above. */
|
||||||
if (TEST_ADD_IMM(src2, src2w)) {
|
if (TEST_ADD_IMM(src2, src2w)) {
|
||||||
compiler->imm = src2w & 0xffffffff;
|
compiler->imm = src2w & 0xffffffff;
|
||||||
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
|
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
|
||||||
}
|
}
|
||||||
if (TEST_ADD_IMM(src1, src1w)) {
|
if (TEST_ADD_IMM(src1, src1w)) {
|
||||||
compiler->imm = src1w & 0xffffffff;
|
compiler->imm = src1w & 0xffffffff;
|
||||||
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0);
|
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (HAS_FLAGS(op)) {
|
if (HAS_FLAGS(op)) {
|
||||||
|
@ -1537,56 +1560,55 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
|
||||||
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
|
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return emit_op(compiler, SLJIT_ADD, flags, dst, dstw, src1, src1w, src2, src2w);
|
return emit_op(compiler, SLJIT_ADD, flags | ((GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)) ? ALT_FORM4 : 0), dst, dstw, src1, src1w, src2, src2w);
|
||||||
|
|
||||||
case SLJIT_ADDC:
|
case SLJIT_ADDC:
|
||||||
return emit_op(compiler, SLJIT_ADDC, flags, dst, dstw, src1, src1w, src2, src2w);
|
return emit_op(compiler, SLJIT_ADDC, flags, dst, dstw, src1, src1w, src2, src2w);
|
||||||
|
|
||||||
case SLJIT_SUB:
|
case SLJIT_SUB:
|
||||||
if (GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_LESS_EQUAL)
|
if (GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_LESS_EQUAL) {
|
||||||
{
|
if (dst == SLJIT_UNUSED) {
|
||||||
if (dst == SLJIT_UNUSED)
|
|
||||||
{
|
|
||||||
if (TEST_UL_IMM(src2, src2w)) {
|
if (TEST_UL_IMM(src2, src2w)) {
|
||||||
compiler->imm = src2w & 0xffff;
|
compiler->imm = src2w & 0xffff;
|
||||||
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
|
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
|
||||||
}
|
}
|
||||||
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM5, dst, dstw, src1, src1w, src2, src2w);
|
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((src2 & SLJIT_IMM) && src2w >= 0 && src2w <= (SIMM_MAX + 1))
|
if ((src2 & SLJIT_IMM) && src2w >= 0 && src2w <= (SIMM_MAX + 1)) {
|
||||||
{
|
|
||||||
compiler->imm = src2w;
|
compiler->imm = src2w;
|
||||||
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM6, dst, dstw, src1, src1w, TMP_REG2, 0);
|
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
|
||||||
}
|
}
|
||||||
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM7, dst, dstw, src1, src1w, src2, src2w);
|
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM3, dst, dstw, src1, src1w, src2, src2w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW || GET_FLAG_TYPE(op) == SLJIT_NOT_OVERFLOW)
|
||||||
|
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2, dst, dstw, src1, src1w, src2, src2w);
|
||||||
|
|
||||||
if (!HAS_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) {
|
if (!HAS_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) {
|
||||||
if (TEST_SL_IMM(src2, -src2w)) {
|
if (TEST_SL_IMM(src2, -src2w)) {
|
||||||
compiler->imm = (-src2w) & 0xffff;
|
compiler->imm = (-src2w) & 0xffff;
|
||||||
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
|
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
|
||||||
}
|
}
|
||||||
if (TEST_SL_IMM(src1, src1w)) {
|
if (TEST_SL_IMM(src1, src1w)) {
|
||||||
compiler->imm = src1w & 0xffff;
|
compiler->imm = src1w & 0xffff;
|
||||||
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
|
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
|
||||||
}
|
}
|
||||||
if (TEST_SH_IMM(src2, -src2w)) {
|
if (TEST_SH_IMM(src2, -src2w)) {
|
||||||
compiler->imm = ((-src2w) >> 16) & 0xffff;
|
compiler->imm = ((-src2w) >> 16) & 0xffff;
|
||||||
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
|
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
|
||||||
}
|
}
|
||||||
/* Range between -1 and -32768 is covered above. */
|
/* Range between -1 and -32768 is covered above. */
|
||||||
if (TEST_ADD_IMM(src2, -src2w)) {
|
if (TEST_ADD_IMM(src2, -src2w)) {
|
||||||
compiler->imm = -src2w & 0xffffffff;
|
compiler->imm = -src2w & 0xffffffff;
|
||||||
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
|
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dst == SLJIT_UNUSED && GET_FLAG_TYPE(op) != GET_FLAG_TYPE(SLJIT_SET_CARRY)
|
if (dst == SLJIT_UNUSED && GET_FLAG_TYPE(op) != GET_FLAG_TYPE(SLJIT_SET_CARRY)) {
|
||||||
&& GET_FLAG_TYPE(op) == SLJIT_OVERFLOW && GET_FLAG_TYPE(op) == SLJIT_NOT_OVERFLOW) {
|
|
||||||
if (TEST_SL_IMM(src2, src2w)) {
|
if (TEST_SL_IMM(src2, src2w)) {
|
||||||
compiler->imm = src2w & 0xffff;
|
compiler->imm = src2w & 0xffff;
|
||||||
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
|
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM4 | ALT_FORM5, dst, dstw, src1, src1w, TMP_REG2, 0);
|
||||||
}
|
}
|
||||||
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);
|
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);
|
||||||
}
|
}
|
||||||
|
@ -1596,7 +1618,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
|
||||||
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
|
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
|
||||||
}
|
}
|
||||||
/* We know ALT_SIGN_EXT is set if it is an SLJIT_I32_OP on 64 bit systems. */
|
/* We know ALT_SIGN_EXT is set if it is an SLJIT_I32_OP on 64 bit systems. */
|
||||||
return emit_op(compiler, SLJIT_SUB, flags, dst, dstw, src1, src1w, src2, src2w);
|
return emit_op(compiler, SLJIT_SUB, flags | ((GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w);
|
||||||
|
|
||||||
case SLJIT_SUBC:
|
case SLJIT_SUBC:
|
||||||
return emit_op(compiler, SLJIT_SUBC, flags, dst, dstw, src1, src1w, src2, src2w);
|
return emit_op(compiler, SLJIT_SUBC, flags, dst, dstw, src1, src1w, src2, src2w);
|
||||||
|
@ -1697,16 +1719,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c
|
||||||
/* Floating point operators */
|
/* Floating point operators */
|
||||||
/* --------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------- */
|
||||||
|
|
||||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_fpu_available(void)
|
|
||||||
{
|
|
||||||
#ifdef SLJIT_IS_FPU_AVAILABLE
|
|
||||||
return SLJIT_IS_FPU_AVAILABLE;
|
|
||||||
#else
|
|
||||||
/* Available by default. */
|
|
||||||
return 1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_F32_OP) >> 6))
|
#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_F32_OP) >> 6))
|
||||||
#define SELECT_FOP(op, single, double) ((op & SLJIT_F32_OP) ? single : double)
|
#define SELECT_FOP(op, single, double) ((op & SLJIT_F32_OP) ? single : double)
|
||||||
|
|
||||||
|
@ -2369,6 +2381,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
|
||||||
return sljit_emit_op2(compiler, op | flags, dst, original_dstw, src, srcw, TMP_REG2, 0);
|
return sljit_emit_op2(compiler, op | flags, dst, original_dstw, src, srcw, TMP_REG2, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
|
||||||
|
sljit_s32 dst_reg,
|
||||||
|
sljit_s32 src, sljit_sw srcw)
|
||||||
|
{
|
||||||
|
CHECK_ERROR();
|
||||||
|
CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
|
||||||
|
|
||||||
|
return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);;
|
||||||
|
}
|
||||||
|
|
||||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
|
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
|
||||||
{
|
{
|
||||||
struct sljit_const *const_;
|
struct sljit_const *const_;
|
||||||
|
|
|
@ -80,18 +80,17 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
|
||||||
|
|
||||||
case SLJIT_CLZ:
|
case SLJIT_CLZ:
|
||||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||||
/* sparc 32 does not support SLJIT_KEEP_FLAGS. Not sure I can fix this. */
|
|
||||||
FAIL_IF(push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(src2) | S2(0), SET_FLAGS));
|
FAIL_IF(push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(src2) | S2(0), SET_FLAGS));
|
||||||
FAIL_IF(push_inst(compiler, OR | D(TMP_REG1) | S1(0) | S2(src2), DR(TMP_REG1)));
|
FAIL_IF(push_inst(compiler, OR | D(TMP_REG1) | S1(0) | S2(src2), DR(TMP_REG1)));
|
||||||
FAIL_IF(push_inst(compiler, BICC | DA(0x1) | (7 & DISP_MASK), UNMOVABLE_INS));
|
FAIL_IF(push_inst(compiler, BICC | DA(0x1) | (7 & DISP_MASK), UNMOVABLE_INS));
|
||||||
FAIL_IF(push_inst(compiler, OR | (flags & SET_FLAGS) | D(dst) | S1(0) | IMM(32), UNMOVABLE_INS | (flags & SET_FLAGS)));
|
FAIL_IF(push_inst(compiler, OR | D(dst) | S1(0) | IMM(32), UNMOVABLE_INS));
|
||||||
FAIL_IF(push_inst(compiler, OR | D(dst) | S1(0) | IMM(-1), DR(dst)));
|
FAIL_IF(push_inst(compiler, OR | D(dst) | S1(0) | IMM(-1), DR(dst)));
|
||||||
|
|
||||||
/* Loop. */
|
/* Loop. */
|
||||||
FAIL_IF(push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(TMP_REG1) | S2(0), SET_FLAGS));
|
FAIL_IF(push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(TMP_REG1) | S2(0), SET_FLAGS));
|
||||||
FAIL_IF(push_inst(compiler, SLL | D(TMP_REG1) | S1(TMP_REG1) | IMM(1), DR(TMP_REG1)));
|
FAIL_IF(push_inst(compiler, SLL | D(TMP_REG1) | S1(TMP_REG1) | IMM(1), DR(TMP_REG1)));
|
||||||
FAIL_IF(push_inst(compiler, BICC | DA(0xe) | (-2 & DISP_MASK), UNMOVABLE_INS));
|
FAIL_IF(push_inst(compiler, BICC | DA(0xe) | (-2 & DISP_MASK), UNMOVABLE_INS));
|
||||||
return push_inst(compiler, ADD | (flags & SET_FLAGS) | D(dst) | S1(dst) | IMM(1), UNMOVABLE_INS | (flags & SET_FLAGS));
|
return push_inst(compiler, ADD | D(dst) | S1(dst) | IMM(1), UNMOVABLE_INS);
|
||||||
|
|
||||||
case SLJIT_ADD:
|
case SLJIT_ADD:
|
||||||
return push_inst(compiler, ADD | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
|
return push_inst(compiler, ADD | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
|
||||||
|
|
|
@ -394,6 +394,27 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
|
||||||
|
{
|
||||||
|
switch (feature_type) {
|
||||||
|
case SLJIT_HAS_FPU:
|
||||||
|
#ifdef SLJIT_IS_FPU_AVAILABLE
|
||||||
|
return SLJIT_IS_FPU_AVAILABLE;
|
||||||
|
#else
|
||||||
|
/* Available by default. */
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (defined SLJIT_CONFIG_SPARC_64 && SLJIT_CONFIG_SPARC_64)
|
||||||
|
case SLJIT_HAS_CMOV:
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------- */
|
||||||
/* Entry, exit */
|
/* Entry, exit */
|
||||||
/* --------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------- */
|
||||||
|
@ -953,16 +974,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c
|
||||||
/* Floating point operators */
|
/* Floating point operators */
|
||||||
/* --------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------- */
|
||||||
|
|
||||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_fpu_available(void)
|
|
||||||
{
|
|
||||||
#ifdef SLJIT_IS_FPU_AVAILABLE
|
|
||||||
return SLJIT_IS_FPU_AVAILABLE;
|
|
||||||
#else
|
|
||||||
/* Available by default. */
|
|
||||||
return 1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_F32_OP) >> 7))
|
#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_F32_OP) >> 7))
|
||||||
#define SELECT_FOP(op, single, double) ((op & SLJIT_F32_OP) ? single : double)
|
#define SELECT_FOP(op, single, double) ((op & SLJIT_F32_OP) ? single : double)
|
||||||
#define FLOAT_TMP_MEM_OFFSET (22 * sizeof(sljit_sw))
|
#define FLOAT_TMP_MEM_OFFSET (22 * sizeof(sljit_sw))
|
||||||
|
@ -1426,6 +1437,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
|
||||||
|
sljit_s32 dst_reg,
|
||||||
|
sljit_s32 src, sljit_sw srcw)
|
||||||
|
{
|
||||||
|
CHECK_ERROR();
|
||||||
|
CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
|
||||||
|
|
||||||
|
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
|
||||||
|
return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);;
|
||||||
|
#else
|
||||||
|
#error "Implementation required"
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
|
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
|
||||||
{
|
{
|
||||||
sljit_s32 reg;
|
sljit_s32 reg;
|
||||||
|
|
|
@ -2487,11 +2487,6 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump * sljit_emit_jump(struct sljit_compil
|
||||||
return jump;
|
return jump;
|
||||||
}
|
}
|
||||||
|
|
||||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_fpu_available(void)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw)
|
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw)
|
||||||
{
|
{
|
||||||
SLJIT_UNREACHABLE();
|
SLJIT_UNREACHABLE();
|
||||||
|
|
|
@ -588,6 +588,42 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
||||||
return (void*)(code + executable_offset);
|
return (void*)(code + executable_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
|
||||||
|
{
|
||||||
|
switch (feature_type) {
|
||||||
|
case SLJIT_HAS_FPU:
|
||||||
|
#ifdef SLJIT_IS_FPU_AVAILABLE
|
||||||
|
return SLJIT_IS_FPU_AVAILABLE;
|
||||||
|
#elif (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
|
||||||
|
if (cpu_has_sse2 == -1)
|
||||||
|
get_cpu_features();
|
||||||
|
return cpu_has_sse2;
|
||||||
|
#else /* SLJIT_DETECT_SSE2 */
|
||||||
|
return 1;
|
||||||
|
#endif /* SLJIT_DETECT_SSE2 */
|
||||||
|
|
||||||
|
case SLJIT_HAS_CLZ:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case SLJIT_HAS_CMOV:
|
||||||
|
if (cpu_has_cmov == -1)
|
||||||
|
get_cpu_features();
|
||||||
|
return cpu_has_cmov;
|
||||||
|
|
||||||
|
case SLJIT_HAS_SSE2:
|
||||||
|
#if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
|
||||||
|
if (cpu_has_sse2 == -1)
|
||||||
|
get_cpu_features();
|
||||||
|
return cpu_has_sse2;
|
||||||
|
#else
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------- */
|
||||||
/* Operators */
|
/* Operators */
|
||||||
/* --------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------- */
|
||||||
|
@ -1131,22 +1167,8 @@ static sljit_s32 emit_clz(struct sljit_compiler *compiler, sljit_s32 op_flags,
|
||||||
sljit_s32 dst_r;
|
sljit_s32 dst_r;
|
||||||
|
|
||||||
SLJIT_UNUSED_ARG(op_flags);
|
SLJIT_UNUSED_ARG(op_flags);
|
||||||
if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) {
|
if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED))
|
||||||
/* Just set the zero flag. */
|
|
||||||
EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);
|
|
||||||
inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REG1, 0);
|
|
||||||
FAIL_IF(!inst);
|
|
||||||
*inst++ = GROUP_F7;
|
|
||||||
*inst |= NOT_rm;
|
|
||||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
|
||||||
inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 31, TMP_REG1, 0);
|
|
||||||
#else
|
|
||||||
inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, !(op_flags & SLJIT_I32_OP) ? 63 : 31, TMP_REG1, 0);
|
|
||||||
#endif
|
|
||||||
FAIL_IF(!inst);
|
|
||||||
*inst |= SHR;
|
|
||||||
return SLJIT_SUCCESS;
|
return SLJIT_SUCCESS;
|
||||||
}
|
|
||||||
|
|
||||||
if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {
|
if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {
|
||||||
EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, srcw);
|
EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, srcw);
|
||||||
|
@ -2221,19 +2243,6 @@ static void init_compiler(void)
|
||||||
sse2_buffer[13] = 0x7fffffff;
|
sse2_buffer[13] = 0x7fffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_fpu_available(void)
|
|
||||||
{
|
|
||||||
#ifdef SLJIT_IS_FPU_AVAILABLE
|
|
||||||
return SLJIT_IS_FPU_AVAILABLE;
|
|
||||||
#elif (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
|
|
||||||
if (cpu_has_sse2 == -1)
|
|
||||||
get_cpu_features();
|
|
||||||
return cpu_has_sse2;
|
|
||||||
#else /* SLJIT_DETECT_SSE2 */
|
|
||||||
return 1;
|
|
||||||
#endif /* SLJIT_DETECT_SSE2 */
|
|
||||||
}
|
|
||||||
|
|
||||||
static sljit_s32 emit_sse2(struct sljit_compiler *compiler, sljit_u8 opcode,
|
static sljit_s32 emit_sse2(struct sljit_compiler *compiler, sljit_u8 opcode,
|
||||||
sljit_s32 single, sljit_s32 xmm1, sljit_s32 xmm2, sljit_sw xmm2w)
|
sljit_s32 single, sljit_s32 xmm1, sljit_s32 xmm2, sljit_sw xmm2w)
|
||||||
{
|
{
|
||||||
|
@ -2776,6 +2785,46 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
|
||||||
#endif /* SLJIT_CONFIG_X86_64 */
|
#endif /* SLJIT_CONFIG_X86_64 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
|
||||||
|
sljit_s32 dst_reg,
|
||||||
|
sljit_s32 src, sljit_sw srcw)
|
||||||
|
{
|
||||||
|
sljit_u8* inst;
|
||||||
|
|
||||||
|
CHECK_ERROR();
|
||||||
|
CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
|
||||||
|
|
||||||
|
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||||
|
dst_reg &= ~SLJIT_I32_OP;
|
||||||
|
|
||||||
|
if (!sljit_has_cpu_feature(SLJIT_HAS_CMOV) || (dst_reg >= SLJIT_R3 && dst_reg <= SLJIT_S3))
|
||||||
|
return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);
|
||||||
|
#else
|
||||||
|
if (!sljit_has_cpu_feature(SLJIT_HAS_CMOV))
|
||||||
|
return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ADJUST_LOCAL_OFFSET is not needed. */
|
||||||
|
CHECK_EXTRA_REGS(src, srcw, (void)0);
|
||||||
|
|
||||||
|
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||||
|
compiler->mode32 = dst_reg & SLJIT_I32_OP;
|
||||||
|
dst_reg &= ~SLJIT_I32_OP;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {
|
||||||
|
EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, srcw);
|
||||||
|
src = TMP_REG1;
|
||||||
|
srcw = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inst = emit_x86_instruction(compiler, 2, dst_reg, 0, src, srcw);
|
||||||
|
FAIL_IF(!inst);
|
||||||
|
*inst++ = GROUP_0F;
|
||||||
|
*inst = get_jump_code(type & 0xff) - 0x40;
|
||||||
|
return SLJIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)
|
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)
|
||||||
{
|
{
|
||||||
CHECK_ERROR();
|
CHECK_ERROR();
|
||||||
|
@ -2869,74 +2918,3 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta
|
||||||
SLJIT_UNUSED_ARG(executable_offset);
|
SLJIT_UNUSED_ARG(executable_offset);
|
||||||
sljit_unaligned_store_sw((void*)addr, new_constant);
|
sljit_unaligned_store_sw((void*)addr, new_constant);
|
||||||
}
|
}
|
||||||
|
|
||||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_x86_is_sse2_available(void)
|
|
||||||
{
|
|
||||||
#if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
|
|
||||||
if (cpu_has_sse2 == -1)
|
|
||||||
get_cpu_features();
|
|
||||||
return cpu_has_sse2;
|
|
||||||
#else
|
|
||||||
return 1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_x86_is_cmov_available(void)
|
|
||||||
{
|
|
||||||
if (cpu_has_cmov == -1)
|
|
||||||
get_cpu_features();
|
|
||||||
return cpu_has_cmov;
|
|
||||||
}
|
|
||||||
|
|
||||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_x86_emit_cmov(struct sljit_compiler *compiler,
|
|
||||||
sljit_s32 type,
|
|
||||||
sljit_s32 dst_reg,
|
|
||||||
sljit_s32 src, sljit_sw srcw)
|
|
||||||
{
|
|
||||||
sljit_u8* inst;
|
|
||||||
|
|
||||||
CHECK_ERROR();
|
|
||||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
|
||||||
CHECK_ARGUMENT(sljit_x86_is_cmov_available());
|
|
||||||
CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_I32_OP)));
|
|
||||||
CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_ORDERED_F64);
|
|
||||||
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg & ~SLJIT_I32_OP));
|
|
||||||
FUNCTION_CHECK_SRC(src, srcw);
|
|
||||||
|
|
||||||
if ((type & 0xff) <= SLJIT_NOT_ZERO)
|
|
||||||
CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z);
|
|
||||||
else
|
|
||||||
CHECK_ARGUMENT((type & 0xff) == (compiler->last_flags & 0xff));
|
|
||||||
#endif
|
|
||||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
|
||||||
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
|
|
||||||
fprintf(compiler->verbose, " x86_cmov%s %s%s, ",
|
|
||||||
!(dst_reg & SLJIT_I32_OP) ? "" : ".i",
|
|
||||||
jump_names[type & 0xff], JUMP_POSTFIX(type));
|
|
||||||
sljit_verbose_reg(compiler, dst_reg & ~SLJIT_I32_OP);
|
|
||||||
fprintf(compiler->verbose, ", ");
|
|
||||||
sljit_verbose_param(compiler, src, srcw);
|
|
||||||
fprintf(compiler->verbose, "\n");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ADJUST_LOCAL_OFFSET(src, srcw);
|
|
||||||
CHECK_EXTRA_REGS(src, srcw, (void)0);
|
|
||||||
|
|
||||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
|
||||||
compiler->mode32 = dst_reg & SLJIT_I32_OP;
|
|
||||||
#endif
|
|
||||||
dst_reg &= ~SLJIT_I32_OP;
|
|
||||||
|
|
||||||
if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {
|
|
||||||
EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, srcw);
|
|
||||||
src = TMP_REG1;
|
|
||||||
srcw = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inst = emit_x86_instruction(compiler, 2, dst_reg, 0, src, srcw);
|
|
||||||
FAIL_IF(!inst);
|
|
||||||
*inst++ = GROUP_0F;
|
|
||||||
*inst = get_jump_code(type & 0xff) - 0x40;
|
|
||||||
return SLJIT_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue