JIT compiler update.
This commit is contained in:
parent
556b0abe99
commit
11ed257eaa
|
@ -573,16 +573,13 @@ the start pointers when the end of the capturing group has not yet reached. */
|
|||
|
||||
#if PCRE2_CODE_UNIT_WIDTH == 8
|
||||
#define MOV_UCHAR SLJIT_MOV_U8
|
||||
#define MOVU_UCHAR SLJIT_MOVU_U8
|
||||
#define IN_UCHARS(x) (x)
|
||||
#elif PCRE2_CODE_UNIT_WIDTH == 16
|
||||
#define MOV_UCHAR SLJIT_MOV_U16
|
||||
#define MOVU_UCHAR SLJIT_MOVU_U16
|
||||
#define UCHAR_SHIFT (1)
|
||||
#define IN_UCHARS(x) ((x) * 2)
|
||||
#elif PCRE2_CODE_UNIT_WIDTH == 32
|
||||
#define MOV_UCHAR SLJIT_MOV_U32
|
||||
#define MOVU_UCHAR SLJIT_MOVU_U32
|
||||
#define UCHAR_SHIFT (2)
|
||||
#define IN_UCHARS(x) ((x) * 4)
|
||||
#else
|
||||
|
@ -2712,12 +2709,25 @@ if (length < 8)
|
|||
}
|
||||
else
|
||||
{
|
||||
GET_LOCAL_BASE(SLJIT_R1, 0, OVECTOR_START);
|
||||
OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, length - 1);
|
||||
loop = LABEL();
|
||||
OP1(SLJIT_MOVU, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw), SLJIT_R0, 0);
|
||||
OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, 1);
|
||||
JUMPTO(SLJIT_NOT_ZERO, loop);
|
||||
if (sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_PRE, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw)) == SLJIT_SUCCESS)
|
||||
{
|
||||
GET_LOCAL_BASE(SLJIT_R1, 0, OVECTOR_START);
|
||||
OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, length - 1);
|
||||
loop = LABEL();
|
||||
sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_PRE, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw));
|
||||
OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, 1);
|
||||
JUMPTO(SLJIT_NOT_ZERO, loop);
|
||||
}
|
||||
else
|
||||
{
|
||||
GET_LOCAL_BASE(SLJIT_R1, 0, OVECTOR_START + sizeof(sljit_sw));
|
||||
OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, length - 1);
|
||||
loop = LABEL();
|
||||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R0, 0);
|
||||
OP2(SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, sizeof(sljit_sw));
|
||||
OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, 1);
|
||||
JUMPTO(SLJIT_NOT_ZERO, loop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2750,12 +2760,25 @@ if (length < 8)
|
|||
}
|
||||
else
|
||||
{
|
||||
GET_LOCAL_BASE(TMP2, 0, OVECTOR_START + sizeof(sljit_sw));
|
||||
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, length - 2);
|
||||
loop = LABEL();
|
||||
OP1(SLJIT_MOVU, SLJIT_MEM1(TMP2), sizeof(sljit_sw), TMP1, 0);
|
||||
OP2(SLJIT_SUB | SLJIT_SET_Z, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 1);
|
||||
JUMPTO(SLJIT_NOT_ZERO, loop);
|
||||
if (sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_PRE, TMP1, SLJIT_MEM1(TMP2), sizeof(sljit_sw)) == SLJIT_SUCCESS)
|
||||
{
|
||||
GET_LOCAL_BASE(TMP2, 0, OVECTOR_START + sizeof(sljit_sw));
|
||||
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, length - 2);
|
||||
loop = LABEL();
|
||||
sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_PRE, TMP1, SLJIT_MEM1(TMP2), sizeof(sljit_sw));
|
||||
OP2(SLJIT_SUB | SLJIT_SET_Z, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 1);
|
||||
JUMPTO(SLJIT_NOT_ZERO, loop);
|
||||
}
|
||||
else
|
||||
{
|
||||
GET_LOCAL_BASE(TMP2, 0, OVECTOR_START + 2 * sizeof(sljit_sw));
|
||||
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, length - 2);
|
||||
loop = LABEL();
|
||||
OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, TMP1, 0);
|
||||
OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, sizeof(sljit_sw));
|
||||
OP2(SLJIT_SUB | SLJIT_SET_Z, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 1);
|
||||
JUMPTO(SLJIT_NOT_ZERO, loop);
|
||||
}
|
||||
}
|
||||
|
||||
OP1(SLJIT_MOV, STACK_TOP, 0, ARGUMENTS, 0);
|
||||
|
@ -2796,6 +2819,7 @@ static SLJIT_INLINE void copy_ovector(compiler_common *common, int topbracket)
|
|||
{
|
||||
DEFINE_COMPILER;
|
||||
struct sljit_label *loop;
|
||||
BOOL has_pre;
|
||||
|
||||
/* At this point we can freely use all registers. */
|
||||
OP1(SLJIT_MOV, SLJIT_S2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1));
|
||||
|
@ -2812,36 +2836,62 @@ if (common->mark_ptr != 0)
|
|||
OP2(SLJIT_ADD, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, match_data),
|
||||
SLJIT_IMM, SLJIT_OFFSETOF(pcre2_match_data, ovector) - sizeof(PCRE2_SIZE));
|
||||
|
||||
GET_LOCAL_BASE(SLJIT_S0, 0, OVECTOR_START);
|
||||
has_pre = sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, SLJIT_S1, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw)) == SLJIT_SUCCESS;
|
||||
|
||||
GET_LOCAL_BASE(SLJIT_S0, 0, OVECTOR_START - (has_pre ? sizeof(sljit_sw) : 0));
|
||||
OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, begin));
|
||||
|
||||
loop = LABEL();
|
||||
OP2(SLJIT_SUB, SLJIT_S1, 0, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0);
|
||||
OP2(SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, sizeof(sljit_sw));
|
||||
|
||||
if (has_pre)
|
||||
sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_PRE, SLJIT_S1, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw));
|
||||
else
|
||||
{
|
||||
OP1(SLJIT_MOV, SLJIT_S1, 0, SLJIT_MEM1(SLJIT_S0), 0);
|
||||
OP2(SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, sizeof(sljit_sw));
|
||||
}
|
||||
|
||||
OP2(SLJIT_ADD, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, sizeof(PCRE2_SIZE));
|
||||
OP2(SLJIT_SUB, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_R0, 0);
|
||||
/* Copy the integer value to the output buffer */
|
||||
#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32
|
||||
OP2(SLJIT_ASHR, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_IMM, UCHAR_SHIFT);
|
||||
#endif
|
||||
|
||||
SLJIT_ASSERT(sizeof(PCRE2_SIZE) == 4 || sizeof(PCRE2_SIZE) == 8);
|
||||
if (sizeof(PCRE2_SIZE) == 4)
|
||||
OP1(SLJIT_MOVU_U32, SLJIT_MEM1(SLJIT_R2), sizeof(PCRE2_SIZE), SLJIT_S1, 0);
|
||||
else
|
||||
OP1(SLJIT_MOVU, SLJIT_MEM1(SLJIT_R2), sizeof(PCRE2_SIZE), SLJIT_S1, 0);
|
||||
OP1(((sizeof(PCRE2_SIZE) == 4) ? SLJIT_MOV_U32 : SLJIT_MOV), SLJIT_MEM1(SLJIT_R2), 0, SLJIT_S1, 0);
|
||||
|
||||
OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);
|
||||
JUMPTO(SLJIT_NOT_ZERO, loop);
|
||||
|
||||
/* Calculate the return value, which is the maximum ovector value. */
|
||||
if (topbracket > 1)
|
||||
{
|
||||
GET_LOCAL_BASE(SLJIT_R0, 0, OVECTOR_START + topbracket * 2 * sizeof(sljit_sw));
|
||||
OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, topbracket + 1);
|
||||
if (sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, SLJIT_R2, SLJIT_MEM1(SLJIT_R0), -(2 * (sljit_sw)sizeof(sljit_sw))) == SLJIT_SUCCESS)
|
||||
{
|
||||
GET_LOCAL_BASE(SLJIT_R0, 0, OVECTOR_START + topbracket * 2 * sizeof(sljit_sw));
|
||||
OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, topbracket + 1);
|
||||
|
||||
/* OVECTOR(0) is never equal to SLJIT_S2. */
|
||||
loop = LABEL();
|
||||
OP1(SLJIT_MOVU, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R0), -(2 * (sljit_sw)sizeof(sljit_sw)));
|
||||
OP2(SLJIT_SUB, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);
|
||||
CMPTO(SLJIT_EQUAL, SLJIT_R2, 0, SLJIT_S2, 0, loop);
|
||||
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_R1, 0);
|
||||
/* OVECTOR(0) is never equal to SLJIT_S2. */
|
||||
loop = LABEL();
|
||||
sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_PRE, SLJIT_R2, SLJIT_MEM1(SLJIT_R0), -(2 * (sljit_sw)sizeof(sljit_sw)));
|
||||
OP2(SLJIT_SUB, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);
|
||||
CMPTO(SLJIT_EQUAL, SLJIT_R2, 0, SLJIT_S2, 0, loop);
|
||||
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_R1, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
GET_LOCAL_BASE(SLJIT_R0, 0, OVECTOR_START + (topbracket - 1) * 2 * sizeof(sljit_sw));
|
||||
OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, topbracket + 1);
|
||||
|
||||
/* OVECTOR(0) is never equal to SLJIT_S2. */
|
||||
loop = LABEL();
|
||||
OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R0), 0);
|
||||
OP2(SLJIT_SUB, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 2 * (sljit_sw)sizeof(sljit_sw));
|
||||
OP2(SLJIT_SUB, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);
|
||||
CMPTO(SLJIT_EQUAL, SLJIT_R2, 0, SLJIT_S2, 0, loop);
|
||||
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_R1, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1);
|
||||
|
@ -5988,84 +6038,183 @@ OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL);
|
|||
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
|
||||
}
|
||||
|
||||
#define CHAR1 STR_END
|
||||
#define CHAR2 STACK_TOP
|
||||
|
||||
static void do_casefulcmp(compiler_common *common)
|
||||
{
|
||||
DEFINE_COMPILER;
|
||||
struct sljit_jump *jump;
|
||||
struct sljit_label *label;
|
||||
int char1_reg;
|
||||
int char2_reg;
|
||||
|
||||
sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
|
||||
if (sljit_get_register_index(TMP3) < 0)
|
||||
{
|
||||
char1_reg = STR_END;
|
||||
char2_reg = STACK_TOP;
|
||||
}
|
||||
else
|
||||
{
|
||||
char1_reg = TMP3;
|
||||
char2_reg = RETURN_ADDR;
|
||||
}
|
||||
|
||||
sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0);
|
||||
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
|
||||
OP1(SLJIT_MOV, TMP3, 0, CHAR1, 0);
|
||||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, CHAR2, 0);
|
||||
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
|
||||
label = LABEL();
|
||||
OP1(MOVU_UCHAR, CHAR1, 0, SLJIT_MEM1(TMP1), IN_UCHARS(1));
|
||||
OP1(MOVU_UCHAR, CHAR2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
|
||||
jump = CMP(SLJIT_NOT_EQUAL, CHAR1, 0, CHAR2, 0);
|
||||
OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
JUMPTO(SLJIT_NOT_ZERO, label);
|
||||
if (char1_reg == STR_END)
|
||||
{
|
||||
OP1(SLJIT_MOV, TMP3, 0, char1_reg, 0);
|
||||
OP1(SLJIT_MOV, RETURN_ADDR, 0, char2_reg, 0);
|
||||
}
|
||||
|
||||
JUMPHERE(jump);
|
||||
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
OP1(SLJIT_MOV, CHAR1, 0, TMP3, 0);
|
||||
OP1(SLJIT_MOV, CHAR2, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
|
||||
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
|
||||
if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS)
|
||||
{
|
||||
label = LABEL();
|
||||
sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1));
|
||||
sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
|
||||
jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0);
|
||||
OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
JUMPTO(SLJIT_NOT_ZERO, label);
|
||||
|
||||
JUMPHERE(jump);
|
||||
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
|
||||
}
|
||||
else if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS)
|
||||
{
|
||||
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
|
||||
label = LABEL();
|
||||
sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1));
|
||||
sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
|
||||
jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0);
|
||||
OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
JUMPTO(SLJIT_NOT_ZERO, label);
|
||||
|
||||
JUMPHERE(jump);
|
||||
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
|
||||
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
}
|
||||
else
|
||||
{
|
||||
label = LABEL();
|
||||
OP1(MOV_UCHAR, char1_reg, 0, SLJIT_MEM1(TMP1), 0);
|
||||
OP1(MOV_UCHAR, char2_reg, 0, SLJIT_MEM1(STR_PTR), 0);
|
||||
OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0);
|
||||
OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
JUMPTO(SLJIT_NOT_ZERO, label);
|
||||
|
||||
JUMPHERE(jump);
|
||||
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
|
||||
}
|
||||
|
||||
if (char1_reg == STR_END)
|
||||
{
|
||||
OP1(SLJIT_MOV, char1_reg, 0, TMP3, 0);
|
||||
OP1(SLJIT_MOV, char2_reg, 0, RETURN_ADDR, 0);
|
||||
}
|
||||
|
||||
sljit_emit_fast_return(compiler, TMP1, 0);
|
||||
}
|
||||
|
||||
#define LCC_TABLE STACK_LIMIT
|
||||
|
||||
static void do_caselesscmp(compiler_common *common)
|
||||
{
|
||||
DEFINE_COMPILER;
|
||||
struct sljit_jump *jump;
|
||||
struct sljit_label *label;
|
||||
int char1_reg = STR_END;
|
||||
int char2_reg;
|
||||
int lcc_table;
|
||||
int opt_type = 0;
|
||||
|
||||
sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
|
||||
if (sljit_get_register_index(TMP3) < 0)
|
||||
{
|
||||
char2_reg = STACK_TOP;
|
||||
lcc_table = STACK_LIMIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
char2_reg = RETURN_ADDR;
|
||||
lcc_table = TMP3;
|
||||
}
|
||||
|
||||
if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS)
|
||||
opt_type = 1;
|
||||
else if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS)
|
||||
opt_type = 2;
|
||||
|
||||
sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0);
|
||||
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
|
||||
|
||||
OP1(SLJIT_MOV, TMP3, 0, LCC_TABLE, 0);
|
||||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, CHAR1, 0);
|
||||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, CHAR2, 0);
|
||||
OP1(SLJIT_MOV, LCC_TABLE, 0, SLJIT_IMM, common->lcc);
|
||||
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, char1_reg, 0);
|
||||
|
||||
if (char2_reg == STACK_TOP)
|
||||
{
|
||||
OP1(SLJIT_MOV, TMP3, 0, char2_reg, 0);
|
||||
OP1(SLJIT_MOV, RETURN_ADDR, 0, lcc_table, 0);
|
||||
}
|
||||
|
||||
OP1(SLJIT_MOV, lcc_table, 0, SLJIT_IMM, common->lcc);
|
||||
|
||||
if (opt_type == 1)
|
||||
{
|
||||
label = LABEL();
|
||||
sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1));
|
||||
sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
|
||||
}
|
||||
else if (opt_type == 2)
|
||||
{
|
||||
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
|
||||
label = LABEL();
|
||||
sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1));
|
||||
sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
|
||||
}
|
||||
else
|
||||
{
|
||||
label = LABEL();
|
||||
OP1(MOV_UCHAR, char1_reg, 0, SLJIT_MEM1(TMP1), 0);
|
||||
OP1(MOV_UCHAR, char2_reg, 0, SLJIT_MEM1(STR_PTR), 0);
|
||||
OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
}
|
||||
|
||||
label = LABEL();
|
||||
OP1(MOVU_UCHAR, CHAR1, 0, SLJIT_MEM1(TMP1), IN_UCHARS(1));
|
||||
OP1(MOVU_UCHAR, CHAR2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1));
|
||||
#if PCRE2_CODE_UNIT_WIDTH != 8
|
||||
jump = CMP(SLJIT_GREATER, CHAR1, 0, SLJIT_IMM, 255);
|
||||
jump = CMP(SLJIT_GREATER, char1_reg, 0, SLJIT_IMM, 255);
|
||||
#endif
|
||||
OP1(SLJIT_MOV_U8, CHAR1, 0, SLJIT_MEM2(LCC_TABLE, CHAR1), 0);
|
||||
OP1(SLJIT_MOV_U8, char1_reg, 0, SLJIT_MEM2(lcc_table, char1_reg), 0);
|
||||
#if PCRE2_CODE_UNIT_WIDTH != 8
|
||||
JUMPHERE(jump);
|
||||
jump = CMP(SLJIT_GREATER, CHAR2, 0, SLJIT_IMM, 255);
|
||||
jump = CMP(SLJIT_GREATER, char2_reg, 0, SLJIT_IMM, 255);
|
||||
#endif
|
||||
OP1(SLJIT_MOV_U8, CHAR2, 0, SLJIT_MEM2(LCC_TABLE, CHAR2), 0);
|
||||
OP1(SLJIT_MOV_U8, char2_reg, 0, SLJIT_MEM2(lcc_table, char2_reg), 0);
|
||||
#if PCRE2_CODE_UNIT_WIDTH != 8
|
||||
JUMPHERE(jump);
|
||||
#endif
|
||||
jump = CMP(SLJIT_NOT_EQUAL, CHAR1, 0, CHAR2, 0);
|
||||
|
||||
if (opt_type == 0)
|
||||
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
|
||||
jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0);
|
||||
OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
JUMPTO(SLJIT_NOT_ZERO, label);
|
||||
|
||||
JUMPHERE(jump);
|
||||
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
OP1(SLJIT_MOV, LCC_TABLE, 0, TMP3, 0);
|
||||
OP1(SLJIT_MOV, CHAR1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
|
||||
OP1(SLJIT_MOV, CHAR2, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1);
|
||||
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
|
||||
}
|
||||
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
|
||||
|
||||
#undef LCC_TABLE
|
||||
#undef CHAR1
|
||||
#undef CHAR2
|
||||
if (opt_type == 2)
|
||||
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
|
||||
|
||||
if (char2_reg == STACK_TOP)
|
||||
{
|
||||
OP1(SLJIT_MOV, char2_reg, 0, TMP3, 0);
|
||||
OP1(SLJIT_MOV, lcc_table, 0, RETURN_ADDR, 0);
|
||||
}
|
||||
|
||||
OP1(SLJIT_MOV, char1_reg, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1);
|
||||
sljit_emit_fast_return(compiler, TMP1, 0);
|
||||
}
|
||||
|
||||
#if defined SUPPORT_UNICODE
|
||||
|
||||
|
|
|
@ -588,13 +588,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr);
|
|||
|
||||
#elif (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
|
||||
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 25
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 26
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 10
|
||||
#define SLJIT_LOCALS_OFFSET_BASE (2 * sizeof(sljit_sw))
|
||||
|
||||
#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
|
||||
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 22
|
||||
#define SLJIT_NUMBER_OF_REGISTERS 23
|
||||
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 17
|
||||
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) || (defined _AIX)
|
||||
#define SLJIT_LOCALS_OFFSET_BASE ((6 + 8) * sizeof(sljit_sw))
|
||||
|
|
|
@ -99,10 +99,10 @@
|
|||
|
||||
#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
|
||||
#define TYPE_CAST_NEEDED(op) \
|
||||
(((op) >= SLJIT_MOV_U8 && (op) <= SLJIT_MOV_S32) || ((op) >= SLJIT_MOVU_U8 && (op) <= SLJIT_MOVU_S32))
|
||||
((op) >= SLJIT_MOV_U8 && (op) <= SLJIT_MOV_S32)
|
||||
#else
|
||||
#define TYPE_CAST_NEEDED(op) \
|
||||
(((op) >= SLJIT_MOV_U8 && (op) <= SLJIT_MOV_S16) || ((op) >= SLJIT_MOVU_U8 && (op) <= SLJIT_MOVU_S16))
|
||||
((op) >= SLJIT_MOV_U8 && (op) <= SLJIT_MOV_S16)
|
||||
#endif
|
||||
|
||||
#define BUF_SIZE 4096
|
||||
|
@ -685,80 +685,106 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp
|
|||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
|
||||
#define FUNCTION_CHECK_IS_REG(r) \
|
||||
(((r) >= SLJIT_R0 && (r) < (SLJIT_R0 + compiler->scratches)) || \
|
||||
((r) > (SLJIT_S0 - compiler->saveds) && (r) <= SLJIT_S0))
|
||||
(((r) >= SLJIT_R0 && (r) < (SLJIT_R0 + compiler->scratches)) \
|
||||
|| ((r) > (SLJIT_S0 - compiler->saveds) && (r) <= SLJIT_S0))
|
||||
|
||||
#define FUNCTION_CHECK_IS_REG_OR_UNUSED(r) \
|
||||
((r) == SLJIT_UNUSED || \
|
||||
((r) >= SLJIT_R0 && (r) < (SLJIT_R0 + compiler->scratches)) || \
|
||||
((r) > (SLJIT_S0 - compiler->saveds) && (r) <= SLJIT_S0))
|
||||
#define FUNCTION_CHECK_IS_FREG(fr) \
|
||||
(((fr) >= SLJIT_FR0 && (fr) < (SLJIT_FR0 + compiler->fscratches)) \
|
||||
|| ((fr) > (SLJIT_FS0 - compiler->fsaveds) && (fr) <= SLJIT_FS0))
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
#define CHECK_NOT_VIRTUAL_REGISTER(p) \
|
||||
CHECK_ARGUMENT((p) < SLJIT_R3 || (p) > SLJIT_R6);
|
||||
#define CHECK_IF_VIRTUAL_REGISTER(p) ((p) <= SLJIT_S3 && (p) >= SLJIT_S8)
|
||||
#else
|
||||
#define CHECK_NOT_VIRTUAL_REGISTER(p)
|
||||
#define CHECK_IF_VIRTUAL_REGISTER(p) 0
|
||||
#endif
|
||||
|
||||
#define FUNCTION_CHECK_SRC(p, i) \
|
||||
CHECK_ARGUMENT(compiler->scratches != -1 && compiler->saveds != -1); \
|
||||
if (FUNCTION_CHECK_IS_REG(p)) \
|
||||
CHECK_ARGUMENT((i) == 0); \
|
||||
else if ((p) == SLJIT_IMM) \
|
||||
; \
|
||||
else if ((p) == (SLJIT_MEM1(SLJIT_SP))) \
|
||||
CHECK_ARGUMENT((i) >= 0 && (i) < compiler->logical_local_size); \
|
||||
else { \
|
||||
CHECK_ARGUMENT((p) & SLJIT_MEM); \
|
||||
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG_OR_UNUSED((p) & REG_MASK)); \
|
||||
CHECK_NOT_VIRTUAL_REGISTER((p) & REG_MASK); \
|
||||
if ((p) & OFFS_REG_MASK) { \
|
||||
CHECK_ARGUMENT(((p) & REG_MASK) != SLJIT_UNUSED); \
|
||||
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(OFFS_REG(p))); \
|
||||
CHECK_NOT_VIRTUAL_REGISTER(OFFS_REG(p)); \
|
||||
CHECK_ARGUMENT(!((i) & ~0x3)); \
|
||||
} \
|
||||
CHECK_ARGUMENT(!((p) & ~(SLJIT_MEM | REG_MASK | OFFS_REG_MASK))); \
|
||||
static sljit_s32 function_check_src_mem(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)
|
||||
{
|
||||
if (compiler->scratches == -1 || compiler->saveds == -1)
|
||||
return 0;
|
||||
|
||||
if (!(p & SLJIT_MEM))
|
||||
return 0;
|
||||
|
||||
if (!((p & REG_MASK) == SLJIT_UNUSED || FUNCTION_CHECK_IS_REG(p & REG_MASK)))
|
||||
return 0;
|
||||
|
||||
if (CHECK_IF_VIRTUAL_REGISTER(p & REG_MASK))
|
||||
return 0;
|
||||
|
||||
if (p & OFFS_REG_MASK) {
|
||||
if ((p & REG_MASK) == SLJIT_UNUSED)
|
||||
return 0;
|
||||
|
||||
if (!(FUNCTION_CHECK_IS_REG(OFFS_REG(p))))
|
||||
return 0;
|
||||
|
||||
if (CHECK_IF_VIRTUAL_REGISTER(OFFS_REG(p)))
|
||||
return 0;
|
||||
|
||||
if ((i & ~0x3) != 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (p & ~(SLJIT_MEM | REG_MASK | OFFS_REG_MASK)) == 0;
|
||||
}
|
||||
|
||||
#define FUNCTION_CHECK_SRC_MEM(p, i) \
|
||||
CHECK_ARGUMENT(function_check_src_mem(compiler, p, i));
|
||||
|
||||
static sljit_s32 function_check_src(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)
|
||||
{
|
||||
if (compiler->scratches == -1 || compiler->saveds == -1)
|
||||
return 0;
|
||||
|
||||
if (FUNCTION_CHECK_IS_REG(p))
|
||||
return (i == 0);
|
||||
|
||||
if (p == SLJIT_IMM)
|
||||
return 1;
|
||||
|
||||
if (p == SLJIT_MEM1(SLJIT_SP))
|
||||
return (i >= 0 && i < compiler->logical_local_size);
|
||||
|
||||
return function_check_src_mem(compiler, p, i);
|
||||
}
|
||||
|
||||
#define FUNCTION_CHECK_SRC(p, i) \
|
||||
CHECK_ARGUMENT(function_check_src(compiler, p, i));
|
||||
|
||||
static sljit_s32 function_check_dst(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i, sljit_s32 unused)
|
||||
{
|
||||
if (compiler->scratches == -1 || compiler->saveds == -1)
|
||||
return 0;
|
||||
|
||||
if (FUNCTION_CHECK_IS_REG(p) || ((unused) && (p) == SLJIT_UNUSED))
|
||||
return (i == 0);
|
||||
|
||||
if (p == SLJIT_MEM1(SLJIT_SP))
|
||||
return (i >= 0 && i < compiler->logical_local_size);
|
||||
|
||||
return function_check_src_mem(compiler, p, i);
|
||||
}
|
||||
|
||||
#define FUNCTION_CHECK_DST(p, i, unused) \
|
||||
CHECK_ARGUMENT(compiler->scratches != -1 && compiler->saveds != -1); \
|
||||
if (FUNCTION_CHECK_IS_REG(p) || ((unused) && (p) == SLJIT_UNUSED)) \
|
||||
CHECK_ARGUMENT((i) == 0); \
|
||||
else if ((p) == (SLJIT_MEM1(SLJIT_SP))) \
|
||||
CHECK_ARGUMENT((i) >= 0 && (i) < compiler->logical_local_size); \
|
||||
else { \
|
||||
CHECK_ARGUMENT((p) & SLJIT_MEM); \
|
||||
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG_OR_UNUSED((p) & REG_MASK)); \
|
||||
CHECK_NOT_VIRTUAL_REGISTER((p) & REG_MASK); \
|
||||
if ((p) & OFFS_REG_MASK) { \
|
||||
CHECK_ARGUMENT(((p) & REG_MASK) != SLJIT_UNUSED); \
|
||||
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(OFFS_REG(p))); \
|
||||
CHECK_NOT_VIRTUAL_REGISTER(OFFS_REG(p)); \
|
||||
CHECK_ARGUMENT(!((i) & ~0x3)); \
|
||||
} \
|
||||
CHECK_ARGUMENT(!((p) & ~(SLJIT_MEM | REG_MASK | OFFS_REG_MASK))); \
|
||||
}
|
||||
CHECK_ARGUMENT(function_check_dst(compiler, p, i, unused));
|
||||
|
||||
static sljit_s32 function_fcheck(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)
|
||||
{
|
||||
if (compiler->scratches == -1 || compiler->saveds == -1)
|
||||
return 0;
|
||||
|
||||
if (FUNCTION_CHECK_IS_FREG(p))
|
||||
return (i == 0);
|
||||
|
||||
if (p == SLJIT_MEM1(SLJIT_SP))
|
||||
return (i >= 0 && i < compiler->logical_local_size);
|
||||
|
||||
return function_check_src_mem(compiler, p, i);
|
||||
}
|
||||
|
||||
#define FUNCTION_FCHECK(p, i) \
|
||||
CHECK_ARGUMENT(compiler->fscratches != -1 && compiler->fsaveds != -1); \
|
||||
if (((p) >= SLJIT_FR0 && (p) < (SLJIT_FR0 + compiler->fscratches)) || \
|
||||
((p) > (SLJIT_FS0 - compiler->fsaveds) && (p) <= SLJIT_FS0)) \
|
||||
CHECK_ARGUMENT(i == 0); \
|
||||
else if ((p) == (SLJIT_MEM1(SLJIT_SP))) \
|
||||
CHECK_ARGUMENT((i) >= 0 && (i) < compiler->logical_local_size); \
|
||||
else { \
|
||||
CHECK_ARGUMENT((p) & SLJIT_MEM); \
|
||||
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG_OR_UNUSED((p) & REG_MASK)); \
|
||||
CHECK_NOT_VIRTUAL_REGISTER((p) & REG_MASK); \
|
||||
if ((p) & OFFS_REG_MASK) { \
|
||||
CHECK_ARGUMENT(((p) & REG_MASK) != SLJIT_UNUSED); \
|
||||
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(OFFS_REG(p))); \
|
||||
CHECK_NOT_VIRTUAL_REGISTER(OFFS_REG(p)); \
|
||||
CHECK_ARGUMENT(((p) & OFFS_REG_MASK) != TO_OFFS_REG(SLJIT_SP) && !(i & ~0x3)); \
|
||||
} \
|
||||
CHECK_ARGUMENT(!((p) & ~(SLJIT_MEM | REG_MASK | OFFS_REG_MASK))); \
|
||||
}
|
||||
CHECK_ARGUMENT(function_fcheck(compiler, p, i));
|
||||
|
||||
#endif /* SLJIT_ARGUMENT_CHECKS */
|
||||
|
||||
|
@ -779,64 +805,72 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *comp
|
|||
# define SLJIT_PRINT_D ""
|
||||
#endif
|
||||
|
||||
#define sljit_verbose_reg(compiler, r) \
|
||||
do { \
|
||||
if ((r) < (SLJIT_R0 + compiler->scratches)) \
|
||||
fprintf(compiler->verbose, "r%d", (r) - SLJIT_R0); \
|
||||
else if ((r) != SLJIT_SP) \
|
||||
fprintf(compiler->verbose, "s%d", SLJIT_NUMBER_OF_REGISTERS - (r)); \
|
||||
else \
|
||||
fprintf(compiler->verbose, "sp"); \
|
||||
} while (0)
|
||||
static void sljit_verbose_reg(struct sljit_compiler *compiler, sljit_s32 r)
|
||||
{
|
||||
if (r < (SLJIT_R0 + compiler->scratches))
|
||||
fprintf(compiler->verbose, "r%d", r - SLJIT_R0);
|
||||
else if (r != SLJIT_SP)
|
||||
fprintf(compiler->verbose, "s%d", SLJIT_NUMBER_OF_REGISTERS - r);
|
||||
else
|
||||
fprintf(compiler->verbose, "sp");
|
||||
}
|
||||
|
||||
#define sljit_verbose_param(compiler, p, i) \
|
||||
if ((p) & SLJIT_IMM) \
|
||||
fprintf(compiler->verbose, "#%" SLJIT_PRINT_D "d", (i)); \
|
||||
else if ((p) & SLJIT_MEM) { \
|
||||
if ((p) & REG_MASK) { \
|
||||
fputc('[', compiler->verbose); \
|
||||
sljit_verbose_reg(compiler, (p) & REG_MASK); \
|
||||
if ((p) & OFFS_REG_MASK) { \
|
||||
fprintf(compiler->verbose, " + "); \
|
||||
sljit_verbose_reg(compiler, OFFS_REG(p)); \
|
||||
if (i) \
|
||||
fprintf(compiler->verbose, " * %d", 1 << (i)); \
|
||||
} \
|
||||
else if (i) \
|
||||
fprintf(compiler->verbose, " + %" SLJIT_PRINT_D "d", (i)); \
|
||||
fputc(']', compiler->verbose); \
|
||||
} \
|
||||
else \
|
||||
fprintf(compiler->verbose, "[#%" SLJIT_PRINT_D "d]", (i)); \
|
||||
} else if (p) \
|
||||
sljit_verbose_reg(compiler, p); \
|
||||
else \
|
||||
static void sljit_verbose_freg(struct sljit_compiler *compiler, sljit_s32 r)
|
||||
{
|
||||
if (r < (SLJIT_FR0 + compiler->fscratches))
|
||||
fprintf(compiler->verbose, "fr%d", r - SLJIT_FR0);
|
||||
else
|
||||
fprintf(compiler->verbose, "fs%d", SLJIT_NUMBER_OF_FLOAT_REGISTERS - r);
|
||||
}
|
||||
|
||||
static void sljit_verbose_param(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)
|
||||
{
|
||||
if ((p) & SLJIT_IMM)
|
||||
fprintf(compiler->verbose, "#%" SLJIT_PRINT_D "d", (i));
|
||||
else if ((p) & SLJIT_MEM) {
|
||||
if ((p) & REG_MASK) {
|
||||
fputc('[', compiler->verbose);
|
||||
sljit_verbose_reg(compiler, (p) & REG_MASK);
|
||||
if ((p) & OFFS_REG_MASK) {
|
||||
fprintf(compiler->verbose, " + ");
|
||||
sljit_verbose_reg(compiler, OFFS_REG(p));
|
||||
if (i)
|
||||
fprintf(compiler->verbose, " * %d", 1 << (i));
|
||||
}
|
||||
else if (i)
|
||||
fprintf(compiler->verbose, " + %" SLJIT_PRINT_D "d", (i));
|
||||
fputc(']', compiler->verbose);
|
||||
}
|
||||
else
|
||||
fprintf(compiler->verbose, "[#%" SLJIT_PRINT_D "d]", (i));
|
||||
} else if (p)
|
||||
sljit_verbose_reg(compiler, p);
|
||||
else
|
||||
fprintf(compiler->verbose, "unused");
|
||||
}
|
||||
|
||||
#define sljit_verbose_fparam(compiler, p, i) \
|
||||
if ((p) & SLJIT_MEM) { \
|
||||
if ((p) & REG_MASK) { \
|
||||
fputc('[', compiler->verbose); \
|
||||
sljit_verbose_reg(compiler, (p) & REG_MASK); \
|
||||
if ((p) & OFFS_REG_MASK) { \
|
||||
fprintf(compiler->verbose, " + "); \
|
||||
sljit_verbose_reg(compiler, OFFS_REG(p)); \
|
||||
if (i) \
|
||||
fprintf(compiler->verbose, "%d", 1 << (i)); \
|
||||
} \
|
||||
else if (i) \
|
||||
fprintf(compiler->verbose, "%" SLJIT_PRINT_D "d", (i)); \
|
||||
fputc(']', compiler->verbose); \
|
||||
} \
|
||||
else \
|
||||
fprintf(compiler->verbose, "[#%" SLJIT_PRINT_D "d]", (i)); \
|
||||
} \
|
||||
else { \
|
||||
if ((p) < (SLJIT_FR0 + compiler->fscratches)) \
|
||||
fprintf(compiler->verbose, "fr%d", (p) - SLJIT_FR0); \
|
||||
else \
|
||||
fprintf(compiler->verbose, "fs%d", SLJIT_NUMBER_OF_FLOAT_REGISTERS - (p)); \
|
||||
static void sljit_verbose_fparam(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)
|
||||
{
|
||||
if ((p) & SLJIT_MEM) {
|
||||
if ((p) & REG_MASK) {
|
||||
fputc('[', compiler->verbose);
|
||||
sljit_verbose_reg(compiler, (p) & REG_MASK);
|
||||
if ((p) & OFFS_REG_MASK) {
|
||||
fprintf(compiler->verbose, " + ");
|
||||
sljit_verbose_reg(compiler, OFFS_REG(p));
|
||||
if (i)
|
||||
fprintf(compiler->verbose, "%d", 1 << (i));
|
||||
}
|
||||
else if (i)
|
||||
fprintf(compiler->verbose, " + %" SLJIT_PRINT_D "d", (i));
|
||||
fputc(']', compiler->verbose);
|
||||
}
|
||||
else
|
||||
fprintf(compiler->verbose, "[#%" SLJIT_PRINT_D "d]", (i));
|
||||
}
|
||||
else
|
||||
sljit_verbose_freg(compiler, p);
|
||||
}
|
||||
|
||||
static const char* op0_names[] = {
|
||||
(char*)"breakpoint", (char*)"nop", (char*)"lmul.uw", (char*)"lmul.sw",
|
||||
|
@ -1070,6 +1104,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fast_return(struct sljit_
|
|||
{
|
||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
FUNCTION_CHECK_SRC(src, srcw);
|
||||
CHECK_ARGUMENT(src != SLJIT_IMM);
|
||||
compiler->last_flags = 0;
|
||||
#endif
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
|
@ -1128,9 +1163,6 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op1(struct sljit_compiler
|
|||
case SLJIT_MOV:
|
||||
case SLJIT_MOV_U32:
|
||||
case SLJIT_MOV_P:
|
||||
case SLJIT_MOVU:
|
||||
case SLJIT_MOVU_U32:
|
||||
case SLJIT_MOVU_P:
|
||||
/* Nothing allowed */
|
||||
CHECK_ARGUMENT(!(op & (SLJIT_I32_OP | SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
|
||||
break;
|
||||
|
@ -1143,28 +1175,17 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op1(struct sljit_compiler
|
|||
FUNCTION_CHECK_DST(dst, dstw, 1);
|
||||
FUNCTION_CHECK_SRC(src, srcw);
|
||||
|
||||
if (GET_OPCODE(op) >= SLJIT_NOT)
|
||||
if (GET_OPCODE(op) >= SLJIT_NOT) {
|
||||
CHECK_ARGUMENT(src != SLJIT_IMM);
|
||||
compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_I32_OP | SLJIT_SET_Z));
|
||||
else if (GET_OPCODE(op) >= SLJIT_MOVU) {
|
||||
CHECK_ARGUMENT(!(src & SLJIT_MEM) || (src & REG_MASK) != SLJIT_SP);
|
||||
CHECK_ARGUMENT(!(dst & SLJIT_MEM) || (dst & REG_MASK) != SLJIT_SP);
|
||||
if ((src & REG_MASK) != SLJIT_UNUSED) {
|
||||
CHECK_ARGUMENT((src & REG_MASK) != (dst & REG_MASK) && (src & REG_MASK) != OFFS_REG(dst));
|
||||
CHECK_ARGUMENT((src & OFFS_REG_MASK) == SLJIT_UNUSED || srcw == 0);
|
||||
}
|
||||
if ((dst & REG_MASK) != SLJIT_UNUSED) {
|
||||
CHECK_ARGUMENT((dst & REG_MASK) != OFFS_REG(src));
|
||||
CHECK_ARGUMENT((dst & OFFS_REG_MASK) == SLJIT_UNUSED || dstw == 0);
|
||||
}
|
||||
compiler->last_flags = 0;
|
||||
}
|
||||
#endif
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
if (GET_OPCODE(op) <= SLJIT_MOVU_P)
|
||||
if (GET_OPCODE(op) <= SLJIT_MOV_P)
|
||||
{
|
||||
fprintf(compiler->verbose, " mov%s%s%s ", (GET_OPCODE(op) >= SLJIT_MOVU) ? "u" : "",
|
||||
!(op & SLJIT_I32_OP) ? "" : "32", (op != SLJIT_MOV32 && op != SLJIT_MOVU32) ? op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE] : "");
|
||||
fprintf(compiler->verbose, " mov%s%s ", !(op & SLJIT_I32_OP) ? "" : "32",
|
||||
(op != SLJIT_MOV32) ? op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE] : "");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1746,6 +1767,8 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmov(struct sljit_compile
|
|||
#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(compiler->scratches != -1 && compiler->saveds != -1);
|
||||
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg & ~SLJIT_I32_OP));
|
||||
if (src != SLJIT_IMM) {
|
||||
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src));
|
||||
|
@ -1762,7 +1785,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmov(struct sljit_compile
|
|||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
fprintf(compiler->verbose, " cmov%s %s%s, ",
|
||||
!(dst_reg & SLJIT_I32_OP) ? "" : ".i",
|
||||
!(dst_reg & SLJIT_I32_OP) ? "" : "32",
|
||||
jump_names[type & 0xff], JUMP_POSTFIX(type));
|
||||
sljit_verbose_reg(compiler, dst_reg & ~SLJIT_I32_OP);
|
||||
fprintf(compiler->verbose, ", ");
|
||||
|
@ -1773,6 +1796,72 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmov(struct sljit_compile
|
|||
CHECK_RETURN_OK;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 reg,
|
||||
sljit_s32 mem, sljit_sw memw)
|
||||
{
|
||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
CHECK_ARGUMENT((type & 0xff) >= SLJIT_MOV && (type & 0xff) <= SLJIT_MOV_P);
|
||||
CHECK_ARGUMENT(!(type & SLJIT_I32_OP) || ((type & 0xff) != SLJIT_MOV && (type & 0xff) != SLJIT_MOV_U32 && (type & 0xff) != SLJIT_MOV_P));
|
||||
CHECK_ARGUMENT((type & SLJIT_MEM_PRE) || (type & SLJIT_MEM_POST));
|
||||
CHECK_ARGUMENT((type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) != (SLJIT_MEM_PRE | SLJIT_MEM_POST));
|
||||
CHECK_ARGUMENT((type & ~(0xff | SLJIT_I32_OP | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_PRE | SLJIT_MEM_POST)) == 0);
|
||||
|
||||
FUNCTION_CHECK_SRC_MEM(mem, memw);
|
||||
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(reg));
|
||||
|
||||
CHECK_ARGUMENT((mem & REG_MASK) != SLJIT_UNUSED && (mem & REG_MASK) != reg);
|
||||
#endif
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (!(type & SLJIT_MEM_SUPP) && SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
if (sljit_emit_mem(compiler, type | SLJIT_MEM_SUPP, reg, mem, memw) == SLJIT_ERR_UNSUPPORTED)
|
||||
fprintf(compiler->verbose, " //");
|
||||
|
||||
fprintf(compiler->verbose, " mem%s.%s%s%s ",
|
||||
!(type & SLJIT_I32_OP) ? "" : "32",
|
||||
(type & SLJIT_MEM_STORE) ? "st" : "ld",
|
||||
op1_names[(type & 0xff) - SLJIT_OP1_BASE],
|
||||
(type & SLJIT_MEM_PRE) ? ".pre" : ".post");
|
||||
sljit_verbose_reg(compiler, reg);
|
||||
fprintf(compiler->verbose, ", ");
|
||||
sljit_verbose_param(compiler, mem, memw);
|
||||
fprintf(compiler->verbose, "\n");
|
||||
}
|
||||
#endif
|
||||
CHECK_RETURN_OK;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 freg,
|
||||
sljit_s32 mem, sljit_sw memw)
|
||||
{
|
||||
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
|
||||
CHECK_ARGUMENT((type & 0xff) == SLJIT_MOV_F64);
|
||||
CHECK_ARGUMENT((type & SLJIT_MEM_PRE) || (type & SLJIT_MEM_POST));
|
||||
CHECK_ARGUMENT((type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) != (SLJIT_MEM_PRE | SLJIT_MEM_POST));
|
||||
CHECK_ARGUMENT((type & ~(0xff | SLJIT_I32_OP | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_PRE | SLJIT_MEM_POST)) == 0);
|
||||
|
||||
FUNCTION_CHECK_SRC_MEM(mem, memw);
|
||||
CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg));
|
||||
#endif
|
||||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (!(type & SLJIT_MEM_SUPP) && SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
if (sljit_emit_fmem(compiler, type | SLJIT_MEM_SUPP, freg, mem, memw) == SLJIT_ERR_UNSUPPORTED)
|
||||
fprintf(compiler->verbose, " //");
|
||||
|
||||
fprintf(compiler->verbose, " fmem.%s%s%s ",
|
||||
(type & SLJIT_MEM_STORE) ? "st" : "ld",
|
||||
!(type & SLJIT_I32_OP) ? ".f64" : ".f32",
|
||||
(type & SLJIT_MEM_PRE) ? ".pre" : ".post");
|
||||
sljit_verbose_freg(compiler, freg);
|
||||
fprintf(compiler->verbose, ", ");
|
||||
sljit_verbose_param(compiler, mem, memw);
|
||||
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)
|
||||
{
|
||||
/* Any offset is allowed. */
|
||||
|
@ -2046,6 +2135,49 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compile
|
|||
return sljit_emit_jump(compiler, type);
|
||||
}
|
||||
|
||||
#if !(defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) \
|
||||
&& !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
|
||||
&& !(defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 reg,
|
||||
sljit_s32 mem, sljit_sw memw)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
SLJIT_UNUSED_ARG(type);
|
||||
SLJIT_UNUSED_ARG(reg);
|
||||
SLJIT_UNUSED_ARG(mem);
|
||||
SLJIT_UNUSED_ARG(memw);
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
|
||||
|
||||
return SLJIT_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
|
||||
&& !(defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 freg,
|
||||
sljit_s32 mem, sljit_sw memw)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
SLJIT_UNUSED_ARG(type);
|
||||
SLJIT_UNUSED_ARG(freg);
|
||||
SLJIT_UNUSED_ARG(mem);
|
||||
SLJIT_UNUSED_ARG(memw);
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));
|
||||
|
||||
return SLJIT_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)
|
||||
|
@ -2398,6 +2530,28 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
|
|||
return SLJIT_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 reg, sljit_s32 mem, sljit_sw memw)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
SLJIT_UNUSED_ARG(type);
|
||||
SLJIT_UNUSED_ARG(reg);
|
||||
SLJIT_UNUSED_ARG(mem);
|
||||
SLJIT_UNUSED_ARG(memw);
|
||||
SLJIT_UNREACHABLE();
|
||||
return SLJIT_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 freg, sljit_s32 mem, sljit_sw memw)
|
||||
{
|
||||
SLJIT_UNUSED_ARG(compiler);
|
||||
SLJIT_UNUSED_ARG(type);
|
||||
SLJIT_UNUSED_ARG(freg);
|
||||
SLJIT_UNUSED_ARG(mem);
|
||||
SLJIT_UNUSED_ARG(memw);
|
||||
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_UNUSED_ARG(compiler);
|
||||
|
|
|
@ -153,8 +153,8 @@ of sljitConfigInternal.h */
|
|||
is not available at all.
|
||||
*/
|
||||
|
||||
/* When SLJIT_UNUSED is specified as the destination of sljit_emit_op1 and
|
||||
and sljit_emit_op2 operations the result is discarded. If no status
|
||||
/* When SLJIT_UNUSED is specified as the destination of sljit_emit_op1
|
||||
or sljit_emit_op2 operations the result is discarded. If no status
|
||||
flags are set, no instructions are emitted for these operations. Data
|
||||
prefetch is a special exception, see SLJIT_MOV operation. Other SLJIT
|
||||
operations do not support SLJIT_UNUSED as a destination operand. */
|
||||
|
@ -422,15 +422,8 @@ struct sljit_compiler {
|
|||
sljit_uw shift_imm;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
|
||||
sljit_s32 cache_arg;
|
||||
sljit_sw cache_argw;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
|
||||
sljit_sw imm;
|
||||
sljit_s32 cache_arg;
|
||||
sljit_sw cache_argw;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
|
||||
|
@ -565,12 +558,10 @@ static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler
|
|||
#define SLJIT_HAS_FPU 0
|
||||
/* [Limitation] Some registers are virtual registers. */
|
||||
#define SLJIT_HAS_VIRTUAL_REGISTERS 1
|
||||
/* [Emulated] Some forms of move with pre update is supported. */
|
||||
#define SLJIT_HAS_PRE_UPDATE 2
|
||||
/* [Emulated] Count leading zero is supported. */
|
||||
#define SLJIT_HAS_CLZ 3
|
||||
#define SLJIT_HAS_CLZ 2
|
||||
/* [Emulated] Conditional move is supported. */
|
||||
#define SLJIT_HAS_CMOV 4
|
||||
#define SLJIT_HAS_CMOV 3
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
|
||||
/* [Not emulated] SSE2 support is available on x86. */
|
||||
|
@ -657,26 +648,31 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp
|
|||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op,
|
||||
sljit_s32 src, sljit_sw srcw);
|
||||
|
||||
/* Fast calling mechanism for utility functions (see SLJIT_FAST_CALL). All registers and
|
||||
even the stack frame is passed to the callee. The return address is preserved in
|
||||
dst/dstw by sljit_emit_fast_enter (the type of the value stored by this function
|
||||
is sljit_p), and sljit_emit_fast_return can use this as a return value later. */
|
||||
/* Generating entry and exit points for fast call functions (see SLJIT_FAST_CALL).
|
||||
Both sljit_emit_fast_enter and sljit_emit_fast_return functions preserve the
|
||||
values of all registers and stack frame. The return address is stored in the
|
||||
dst argument of sljit_emit_fast_enter, and this return address can be passed
|
||||
to sljit_emit_fast_return to continue the execution after the fast call.
|
||||
|
||||
/* Note: only for sljit specific, non ABI compilant calls. Fast, since only a few machine
|
||||
instructions are needed. Excellent for small uility functions, where saving registers
|
||||
and setting up a new stack frame would cost too much performance. However, it is still
|
||||
possible to return to the address of the caller (or anywhere else). */
|
||||
Fast calls are cheap operations (usually only a single call instruction is
|
||||
emitted) but they do not preserve any registers. However the callee function
|
||||
can freely use / update any registers and stack values which can be
|
||||
efficiently exploited by various optimizations. Registers can be saved
|
||||
manually by the callee function if needed.
|
||||
|
||||
/* Note: may destroy flags. */
|
||||
Although returning to different address by sljit_emit_fast_return is possible,
|
||||
this address usually cannot be predicted by the return address predictor of
|
||||
modern CPUs which may reduce performance. Furthermore using sljit_emit_ijump
|
||||
to return is also inefficient since return address prediction is usually
|
||||
triggered by a specific form of ijump.
|
||||
|
||||
/* Note: although sljit_emit_fast_return could be replaced by an ijump, it is not suggested,
|
||||
since many architectures do clever branch prediction on call / return instruction pairs. */
|
||||
Flags: - (does not modify flags). */
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw);
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw);
|
||||
|
||||
/*
|
||||
Source and destination values for arithmetical instructions
|
||||
Source and destination operands for arithmetical instructions
|
||||
imm - a simple immediate value (cannot be used as a destination)
|
||||
reg - any of the registers (immediate argument must be 0)
|
||||
[imm] - absolute immediate memory address
|
||||
|
@ -717,6 +713,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler
|
|||
arm-t2: [reg+imm], -255 <= imm <= 4095
|
||||
[reg+(reg<<imm)] is supported
|
||||
Write back is supported only for [reg+imm], where -255 <= imm <= 255
|
||||
arm64: [reg+imm], -256 <= imm <= 255, 0 <= aligned imm <= 4095 * alignment
|
||||
[reg+(reg<<imm)] is supported
|
||||
Write back is supported only for [reg+imm], where -256 <= imm <= 255
|
||||
ppc: [reg+imm], -65536 <= imm <= 65535. 64 bit loads/stores and 32 bit
|
||||
signed load on 64 bit requires immediates divisible by 4.
|
||||
[reg+imm] is not supported for signed 8 bit values.
|
||||
|
@ -728,8 +727,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler
|
|||
[reg+reg] is supported
|
||||
*/
|
||||
|
||||
/* Register output: simply the name of the register.
|
||||
For destination, you can use SLJIT_UNUSED as well. */
|
||||
/* Macros for specifying operand types. */
|
||||
#define SLJIT_MEM 0x80
|
||||
#define SLJIT_MEM0() (SLJIT_MEM)
|
||||
#define SLJIT_MEM1(r1) (SLJIT_MEM | (r1))
|
||||
|
@ -898,43 +896,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
|
|||
S32 - signed int (32 bit) data transfer
|
||||
P - pointer (sljit_p) data transfer
|
||||
|
||||
U = move with update (pre form). If source or destination defined as
|
||||
SLJIT_MEM1(r1) or SLJIT_MEM2(r1, r2), r1 is increased by the
|
||||
offset part of the address.
|
||||
|
||||
Register arguments and base registers can only be used once for move
|
||||
with update instructions. The shift value of SLJIT_MEM2 addressing
|
||||
mode must also be 0. Reason: SLJIT_MOVU instructions are expected to
|
||||
be in high-performance loops where complex instruction emulation
|
||||
would be too costly.
|
||||
|
||||
Examples for invalid move with update instructions:
|
||||
|
||||
sljit_emit_op1(..., SLJIT_MOVU_U8,
|
||||
SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), 8);
|
||||
sljit_emit_op1(..., SLJIT_MOVU_U8,
|
||||
SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 0, SLJIT_R0, 0);
|
||||
sljit_emit_op1(..., SLJIT_MOVU_U8,
|
||||
SLJIT_MEM2(SLJIT_R0, SLJIT_R1), 0, SLJIT_MEM1(SLJIT_R0), 8);
|
||||
sljit_emit_op1(..., SLJIT_MOVU_U8,
|
||||
SLJIT_MEM2(SLJIT_R0, SLJIT_R1), 0, SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 0);
|
||||
sljit_emit_op1(..., SLJIT_MOVU_U8,
|
||||
SLJIT_R2, 0, SLJIT_MEM2(SLJIT_R0, SLJIT_R1), 1);
|
||||
|
||||
The following example is valid, since only the offset register is
|
||||
used multiple times:
|
||||
|
||||
sljit_emit_op1(..., SLJIT_MOVU_U8,
|
||||
SLJIT_MEM2(SLJIT_R0, SLJIT_R2), 0, SLJIT_MEM2(SLJIT_R1, SLJIT_R2), 0);
|
||||
|
||||
If the destination of a MOV without update instruction is SLJIT_UNUSED
|
||||
and the source operand is a memory address the compiler emits a prefetch
|
||||
instruction if this instruction is supported by the current CPU.
|
||||
Higher data sizes bring the data closer to the core: a MOV with word
|
||||
size loads the data into a higher level cache than a byte size. Otherwise
|
||||
the type does not affect the prefetch instruction. Furthermore a prefetch
|
||||
instruction never fails, so it can be used to prefetch a data from an
|
||||
address and check whether that address is NULL afterwards.
|
||||
If the destination of a MOV instruction is SLJIT_UNUSED and the source
|
||||
operand is a memory address the compiler emits a prefetch instruction
|
||||
if this instruction is supported by the current CPU. Higher data sizes
|
||||
bring the data closer to the core: a MOV with word size loads the data
|
||||
into a higher level cache than a byte size. Otherwise the type does not
|
||||
affect the prefetch instruction. Furthermore a prefetch instruction
|
||||
never fails, so it can be used to prefetch a data from an address and
|
||||
check whether that address is NULL afterwards.
|
||||
*/
|
||||
|
||||
/* Flags: - (does not modify flags) */
|
||||
|
@ -959,41 +928,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
|
|||
#define SLJIT_MOV_S32 (SLJIT_OP1_BASE + 6)
|
||||
/* Flags: - (does not modify flags) */
|
||||
#define SLJIT_MOV32 (SLJIT_MOV_S32 | SLJIT_I32_OP)
|
||||
/* Flags: - (does not modify flags) */
|
||||
/* Flags: - (does not modify flags)
|
||||
Note: load a pointer sized data, useful on x32 (a 32 bit mode on x86-64
|
||||
where all x64 features are available, e.g. 16 register) or similar
|
||||
compiling modes */
|
||||
#define SLJIT_MOV_P (SLJIT_OP1_BASE + 7)
|
||||
/* Flags: - (may destroy flags) */
|
||||
#define SLJIT_MOVU (SLJIT_OP1_BASE + 8)
|
||||
/* Flags: - (may destroy flags) */
|
||||
#define SLJIT_MOVU_U8 (SLJIT_OP1_BASE + 9)
|
||||
#define SLJIT_MOVU32_U8 (SLJIT_MOVU_U8 | SLJIT_I32_OP)
|
||||
/* Flags: - (may destroy flags) */
|
||||
#define SLJIT_MOVU_S8 (SLJIT_OP1_BASE + 10)
|
||||
#define SLJIT_MOVU32_S8 (SLJIT_MOVU_S8 | SLJIT_I32_OP)
|
||||
/* Flags: - (may destroy flags) */
|
||||
#define SLJIT_MOVU_U16 (SLJIT_OP1_BASE + 11)
|
||||
#define SLJIT_MOVU32_U16 (SLJIT_MOVU_U16 | SLJIT_I32_OP)
|
||||
/* Flags: - (may destroy flags) */
|
||||
#define SLJIT_MOVU_S16 (SLJIT_OP1_BASE + 12)
|
||||
#define SLJIT_MOVU32_S16 (SLJIT_MOVU_S16 | SLJIT_I32_OP)
|
||||
/* Flags: - (may destroy flags)
|
||||
Note: no SLJIT_MOVU32_U32 form, since it is the same as SLJIT_MOVU32 */
|
||||
#define SLJIT_MOVU_U32 (SLJIT_OP1_BASE + 13)
|
||||
/* Flags: - (may destroy flags)
|
||||
Note: no SLJIT_MOVU32_S32 form, since it is the same as SLJIT_MOVU32 */
|
||||
#define SLJIT_MOVU_S32 (SLJIT_OP1_BASE + 14)
|
||||
/* Flags: - (may destroy flags) */
|
||||
#define SLJIT_MOVU32 (SLJIT_MOVU_S32 | SLJIT_I32_OP)
|
||||
/* Flags: - (may destroy flags) */
|
||||
#define SLJIT_MOVU_P (SLJIT_OP1_BASE + 15)
|
||||
/* Flags: Z */
|
||||
#define SLJIT_NOT (SLJIT_OP1_BASE + 16)
|
||||
/* Flags: Z
|
||||
Note: immediate source argument is not supported */
|
||||
#define SLJIT_NOT (SLJIT_OP1_BASE + 8)
|
||||
#define SLJIT_NOT32 (SLJIT_NOT | SLJIT_I32_OP)
|
||||
/* Flags: Z | OVERFLOW */
|
||||
#define SLJIT_NEG (SLJIT_OP1_BASE + 17)
|
||||
/* Flags: Z | OVERFLOW
|
||||
Note: immediate source argument is not supported */
|
||||
#define SLJIT_NEG (SLJIT_OP1_BASE + 9)
|
||||
#define SLJIT_NEG32 (SLJIT_NEG | SLJIT_I32_OP)
|
||||
/* Count leading zeroes
|
||||
Flags: - (may destroy flags) */
|
||||
#define SLJIT_CLZ (SLJIT_OP1_BASE + 18)
|
||||
Flags: - (may destroy flags)
|
||||
Note: immediate source argument is not supported */
|
||||
#define SLJIT_CLZ (SLJIT_OP1_BASE + 10)
|
||||
#define SLJIT_CLZ32 (SLJIT_CLZ | SLJIT_I32_OP)
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
|
||||
|
@ -1294,7 +1245,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
|
|||
|
||||
/* 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.
|
||||
instruction does not support memory access.
|
||||
|
||||
type must be between SLJIT_EQUAL and SLJIT_ORDERED_F64
|
||||
dst_reg must be a valid register and it can be combined
|
||||
|
@ -1306,6 +1257,51 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
|
|||
sljit_s32 dst_reg,
|
||||
sljit_s32 src, sljit_sw srcw);
|
||||
|
||||
/* The following flags are used by sljit_emit_mem() and sljit_emit_fmem(). */
|
||||
|
||||
/* When SLJIT_MEM_SUPP is passed, no instructions are emitted.
|
||||
Instead the function returns with SLJIT_SUCCESS if the instruction
|
||||
form is supported and SLJIT_ERR_UNSUPPORTED otherwise. This flag
|
||||
allows runtime checking of available instruction forms. */
|
||||
#define SLJIT_MEM_SUPP 0x0200
|
||||
/* Memory load operation. This is the default. */
|
||||
#define SLJIT_MEM_LOAD 0x0000
|
||||
/* Memory store operation. */
|
||||
#define SLJIT_MEM_STORE 0x0400
|
||||
/* Base register is updated before the memory access. */
|
||||
#define SLJIT_MEM_PRE 0x0800
|
||||
/* Base register is updated after the memory access. */
|
||||
#define SLJIT_MEM_POST 0x1000
|
||||
|
||||
/* Emit a single memory load or store with update instruction. When the
|
||||
requested instruction from is not supported by the CPU, it returns
|
||||
with SLJIT_ERR_UNSUPPORTED instead of emulating the instruction. This
|
||||
allows specializing tight loops based on the supported instruction
|
||||
forms (see SLJIT_MEM_SUPP flag).
|
||||
|
||||
type must be between SLJIT_MOV and SLJIT_MOV_P and can be
|
||||
combined with SLJIT_MEM_* flags. Either SLJIT_MEM_PRE
|
||||
or SLJIT_MEM_POST must be specified.
|
||||
reg is the source or destination register, and must be
|
||||
different from the base register of the mem operand
|
||||
mem must be a SLJIT_MEM1() or SLJIT_MEM2() operand
|
||||
|
||||
Flags: - (does not modify flags) */
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 reg,
|
||||
sljit_s32 mem, sljit_sw memw);
|
||||
|
||||
/* Same as sljit_emit_mem except the followings:
|
||||
|
||||
type must be SLJIT_MOV_F64 or SLJIT_MOV_F32 and can be
|
||||
combined with SLJIT_MEM_* flags. Either SLJIT_MEM_PRE
|
||||
or SLJIT_MEM_POST must be specified.
|
||||
freg is the source or destination floating point register */
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 freg,
|
||||
sljit_s32 mem, sljit_sw memw);
|
||||
|
||||
/* Copies the base address of SLJIT_SP + offset to dst. The offset can be
|
||||
anything to negate the effect of relative addressing. For example if an
|
||||
array of sljit_sw values is stored on the stack from offset 0x40, and R0
|
||||
|
@ -1358,9 +1354,9 @@ SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_release_lock(void);
|
|||
#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK)
|
||||
|
||||
/* The sljit_stack is a utility extension of sljit, which provides
|
||||
a top-down stack. The stack starts at base and goes down to
|
||||
max_limit, so the memory region for this stack is between
|
||||
max_limit (inclusive) and base (exclusive). However the
|
||||
a top-down stack. The stack top is stored in base and the stack
|
||||
goes down to max_limit, so the memory region for this stack is
|
||||
between max_limit (inclusive) and base (exclusive). However the
|
||||
application can only use the region between limit (inclusive)
|
||||
and base (exclusive). The sljit_stack_resize can be used to
|
||||
extend this region up to max_limit.
|
||||
|
@ -1368,8 +1364,8 @@ SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_release_lock(void);
|
|||
This feature uses the "address space reserve" feature of modern
|
||||
operating systems, so instead of allocating a huge memory block
|
||||
applications can allocate a small region and extend it later
|
||||
without moving the memory area. Hence pointers can be stored
|
||||
in this area. */
|
||||
without moving the memory area. Hence the region is never moved
|
||||
so pointers are valid after resize. */
|
||||
|
||||
/* Note: base and max_limit fields are aligned to PAGE_SIZE bytes
|
||||
(usually 4 Kbyte or more).
|
||||
|
@ -1389,9 +1385,13 @@ struct sljit_stack {
|
|||
};
|
||||
|
||||
/* Returns NULL if unsuccessful.
|
||||
Note: max_limit contains the maximum stack size in bytes.
|
||||
Note: limit contains the starting stack size in bytes.
|
||||
Note: the top field is initialized to base.
|
||||
|
||||
Note:
|
||||
max_limit field contains the lower bound adress of the stack.
|
||||
limit field contains the current starting address of the stack.
|
||||
base field contains the end address of the stack.
|
||||
top field is initialized to base.
|
||||
|
||||
Note: see sljit_create_compiler for the explanation of allocator_data. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(sljit_uw limit, sljit_uw max_limit, void *allocator_data);
|
||||
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data);
|
||||
|
|
|
@ -837,7 +837,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
|
|||
return 1;
|
||||
#endif
|
||||
|
||||
case SLJIT_HAS_PRE_UPDATE:
|
||||
case SLJIT_HAS_CLZ:
|
||||
case SLJIT_HAS_CMOV:
|
||||
return 1;
|
||||
|
@ -852,18 +851,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
|
|||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* Creates an index in data_transfer_insts array. */
|
||||
#define WORD_DATA 0x00
|
||||
#define BYTE_DATA 0x01
|
||||
#define HALF_DATA 0x02
|
||||
#define PRELOAD_DATA 0x03
|
||||
#define SIGNED_DATA 0x04
|
||||
#define WORD_SIZE 0x00
|
||||
#define BYTE_SIZE 0x01
|
||||
#define HALF_SIZE 0x02
|
||||
#define PRELOAD 0x03
|
||||
#define SIGNED 0x04
|
||||
#define LOAD_DATA 0x08
|
||||
|
||||
/* emit_op inp_flags.
|
||||
WRITE_BACK must be the first, since it is a flag. */
|
||||
#define WRITE_BACK 0x10
|
||||
#define ALLOW_IMM 0x20
|
||||
#define ALLOW_INV_IMM 0x40
|
||||
/* Flag bits for emit_op. */
|
||||
#define ALLOW_IMM 0x10
|
||||
#define ALLOW_INV_IMM 0x20
|
||||
#define ALLOW_ANY_IMM (ALLOW_IMM | ALLOW_INV_IMM)
|
||||
|
||||
/* s/l - store/load (1 bit)
|
||||
|
@ -884,15 +881,15 @@ static const sljit_uw data_transfer_insts[16] = {
|
|||
/* l u w */ 0xe5100000 /* ldr */,
|
||||
/* l u b */ 0xe5500000 /* ldrb */,
|
||||
/* l u h */ 0xe11000b0 /* ldrh */,
|
||||
/* l u p */ 0xf5500000 /* preload data */,
|
||||
/* l u p */ 0xf5500000 /* preload */,
|
||||
/* l s w */ 0xe5100000 /* ldr */,
|
||||
/* l s b */ 0xe11000d0 /* ldrsb */,
|
||||
/* l s h */ 0xe11000f0 /* ldrsh */,
|
||||
/* l s N */ 0x00000000 /* not allowed */,
|
||||
};
|
||||
|
||||
#define EMIT_DATA_TRANSFER(type, add, wb, target_reg, base_reg, arg) \
|
||||
(data_transfer_insts[(type) & 0xf] | ((add) << 23) | ((wb) << (21 - 4)) | RD(target_reg) | RN(base_reg) | (arg))
|
||||
#define EMIT_DATA_TRANSFER(type, add, target_reg, base_reg, arg) \
|
||||
(data_transfer_insts[(type) & 0xf] | ((add) << 23) | RD(target_reg) | RN(base_reg) | (arg))
|
||||
|
||||
/* Normal ldr/str instruction.
|
||||
Type2: ldrsb, ldrh, ldrsh */
|
||||
|
@ -1325,7 +1322,7 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg,
|
|||
FAIL_IF(generate_int(compiler, reg, ~imm, 0));
|
||||
|
||||
/* 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_SIZE | LOAD_DATA, 1, reg, TMP_PC, 0), imm);
|
||||
#else
|
||||
FAIL_IF(push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | (imm & 0xfff)));
|
||||
if (imm <= 0xffff)
|
||||
|
@ -1337,16 +1334,13 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg,
|
|||
static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg,
|
||||
sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg)
|
||||
{
|
||||
sljit_uw offset_reg, imm;
|
||||
sljit_uw imm, offset_reg;
|
||||
sljit_uw is_type1_transfer = IS_TYPE1_TRANSFER(flags);
|
||||
|
||||
SLJIT_ASSERT (arg & SLJIT_MEM);
|
||||
SLJIT_ASSERT((arg & REG_MASK) != tmp_reg);
|
||||
|
||||
SLJIT_COMPILE_ASSERT(WRITE_BACK == 0x10, optimized_for_emit_data_transfer);
|
||||
|
||||
if ((arg & REG_MASK) == SLJIT_UNUSED) {
|
||||
/* Write back is not used. */
|
||||
if (is_type1_transfer) {
|
||||
FAIL_IF(load_immediate(compiler, tmp_reg, argw & ~0xfff));
|
||||
argw &= 0xfff;
|
||||
|
@ -1356,7 +1350,8 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit
|
|||
argw &= 0xff;
|
||||
}
|
||||
|
||||
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, 0, reg, tmp_reg, is_type1_transfer ? argw : TYPE2_TRANSFER_IMM(argw)));
|
||||
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, tmp_reg,
|
||||
is_type1_transfer ? argw : TYPE2_TRANSFER_IMM(argw)));
|
||||
}
|
||||
|
||||
if (arg & OFFS_REG_MASK) {
|
||||
|
@ -1365,14 +1360,12 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit
|
|||
argw &= 0x3;
|
||||
|
||||
if (argw != 0 && !is_type1_transfer) {
|
||||
SLJIT_ASSERT(!(flags & WRITE_BACK));
|
||||
|
||||
FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | RM(offset_reg) | (argw << 7)));
|
||||
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, 0, reg, tmp_reg, TYPE2_TRANSFER_IMM(0)));
|
||||
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, tmp_reg, TYPE2_TRANSFER_IMM(0)));
|
||||
}
|
||||
|
||||
/* Bit 25: RM is offset. */
|
||||
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, flags & WRITE_BACK, reg, arg,
|
||||
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg,
|
||||
RM(offset_reg) | (is_type1_transfer ? (1 << 25) : 0) | (argw << 7)));
|
||||
}
|
||||
|
||||
|
@ -1382,60 +1375,55 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit
|
|||
if (argw > 0xfff) {
|
||||
imm = get_imm(argw & ~0xfff);
|
||||
if (imm) {
|
||||
offset_reg = (flags & WRITE_BACK) ? arg : tmp_reg;
|
||||
FAIL_IF(push_inst(compiler, ADD | RD(offset_reg) | RN(arg) | imm));
|
||||
FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | imm));
|
||||
argw = argw & 0xfff;
|
||||
arg = offset_reg;
|
||||
arg = tmp_reg;
|
||||
}
|
||||
}
|
||||
else if (argw < -0xfff) {
|
||||
imm = get_imm(-argw & ~0xfff);
|
||||
if (imm) {
|
||||
offset_reg = (flags & WRITE_BACK) ? arg : tmp_reg;
|
||||
FAIL_IF(push_inst(compiler, SUB | RD(offset_reg) | RN(arg) | imm));
|
||||
FAIL_IF(push_inst(compiler, SUB | RD(tmp_reg) | RN(arg) | imm));
|
||||
argw = -(-argw & 0xfff);
|
||||
arg = offset_reg;
|
||||
arg = tmp_reg;
|
||||
}
|
||||
}
|
||||
|
||||
if (argw >= 0 && argw <= 0xfff) {
|
||||
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, flags & WRITE_BACK, reg, arg & REG_MASK, argw));
|
||||
}
|
||||
if (argw < 0 && argw >= -0xfff) {
|
||||
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 0, flags & WRITE_BACK, reg, arg & REG_MASK, -argw));
|
||||
}
|
||||
if (argw >= 0 && argw <= 0xfff)
|
||||
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg, argw));
|
||||
|
||||
if (argw < 0 && argw >= -0xfff)
|
||||
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 0, reg, arg, -argw));
|
||||
}
|
||||
else {
|
||||
if (argw > 0xff) {
|
||||
imm = get_imm(argw & ~0xff);
|
||||
if (imm) {
|
||||
offset_reg = (flags & WRITE_BACK) ? arg : tmp_reg;
|
||||
FAIL_IF(push_inst(compiler, ADD | RD(offset_reg) | RN(arg) | imm));
|
||||
FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | imm));
|
||||
argw = argw & 0xff;
|
||||
arg = offset_reg;
|
||||
arg = tmp_reg;
|
||||
}
|
||||
}
|
||||
else if (argw < -0xff) {
|
||||
imm = get_imm(-argw & ~0xff);
|
||||
if (imm) {
|
||||
offset_reg = (flags & WRITE_BACK) ? arg : tmp_reg;
|
||||
FAIL_IF(push_inst(compiler, SUB | RD(offset_reg) | RN(arg) | imm));
|
||||
FAIL_IF(push_inst(compiler, SUB | RD(tmp_reg) | RN(arg) | imm));
|
||||
argw = -(-argw & 0xff);
|
||||
arg = offset_reg;
|
||||
arg = tmp_reg;
|
||||
}
|
||||
}
|
||||
|
||||
if (argw >= 0 && argw <= 0xff) {
|
||||
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, flags & WRITE_BACK, reg, arg, TYPE2_TRANSFER_IMM(argw)));
|
||||
}
|
||||
if (argw >= 0 && argw <= 0xff)
|
||||
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg, TYPE2_TRANSFER_IMM(argw)));
|
||||
|
||||
if (argw < 0 && argw >= -0xff) {
|
||||
argw = -argw;
|
||||
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 0, flags & WRITE_BACK, reg, arg, TYPE2_TRANSFER_IMM(argw)));
|
||||
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 0, reg, arg, TYPE2_TRANSFER_IMM(argw)));
|
||||
}
|
||||
}
|
||||
|
||||
FAIL_IF(load_immediate(compiler, tmp_reg, argw));
|
||||
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, flags & WRITE_BACK, reg, arg,
|
||||
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg,
|
||||
RM(tmp_reg) | (is_type1_transfer ? (1 << 25) : 0)));
|
||||
}
|
||||
|
||||
|
@ -1538,10 +1526,10 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
|
|||
/* Destination. */
|
||||
dst_reg = SLOW_IS_REG(dst) ? dst : TMP_REG2;
|
||||
|
||||
if (op <= SLJIT_MOVU_P) {
|
||||
if (op <= SLJIT_MOV_P) {
|
||||
if (dst & SLJIT_MEM) {
|
||||
if (inp_flags & BYTE_DATA)
|
||||
inp_flags &= ~SIGNED_DATA;
|
||||
if (inp_flags & BYTE_SIZE)
|
||||
inp_flags &= ~SIGNED;
|
||||
|
||||
if (FAST_IS_REG(src2))
|
||||
return emit_op_mem(compiler, inp_flags, src2, dst, dstw, TMP_REG2);
|
||||
|
@ -1553,7 +1541,7 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
|
|||
|
||||
/* Source 2. */
|
||||
if (src2_reg == 0) {
|
||||
src2_reg = (op <= SLJIT_MOVU_P) ? dst_reg : TMP_REG2;
|
||||
src2_reg = (op <= SLJIT_MOV_P) ? dst_reg : TMP_REG2;
|
||||
|
||||
if (FAST_IS_REG(src2))
|
||||
src2_reg = src2;
|
||||
|
@ -1674,7 +1662,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
|||
if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) {
|
||||
#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
|
||||
if (op <= SLJIT_MOV_P && (src & SLJIT_MEM))
|
||||
return emit_op_mem(compiler, PRELOAD_DATA | LOAD_DATA, TMP_PC, src, srcw, TMP_REG1);
|
||||
return emit_op_mem(compiler, PRELOAD | LOAD_DATA, TMP_PC, src, srcw, TMP_REG1);
|
||||
#endif
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
@ -1687,34 +1675,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
|||
return emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
|
||||
case SLJIT_MOV_U8:
|
||||
return emit_op(compiler, SLJIT_MOV_U8, ALLOW_ANY_IMM | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw);
|
||||
return emit_op(compiler, SLJIT_MOV_U8, ALLOW_ANY_IMM | BYTE_SIZE, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw);
|
||||
|
||||
case SLJIT_MOV_S8:
|
||||
return emit_op(compiler, SLJIT_MOV_S8, ALLOW_ANY_IMM | SIGNED_DATA | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw);
|
||||
return emit_op(compiler, SLJIT_MOV_S8, ALLOW_ANY_IMM | SIGNED | BYTE_SIZE, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw);
|
||||
|
||||
case SLJIT_MOV_U16:
|
||||
return emit_op(compiler, SLJIT_MOV_U16, ALLOW_ANY_IMM | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw);
|
||||
return emit_op(compiler, SLJIT_MOV_U16, ALLOW_ANY_IMM | HALF_SIZE, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw);
|
||||
|
||||
case SLJIT_MOV_S16:
|
||||
return emit_op(compiler, SLJIT_MOV_S16, ALLOW_ANY_IMM | SIGNED_DATA | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw);
|
||||
|
||||
case SLJIT_MOVU:
|
||||
case SLJIT_MOVU_U32:
|
||||
case SLJIT_MOVU_S32:
|
||||
case SLJIT_MOVU_P:
|
||||
return emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
|
||||
case SLJIT_MOVU_U8:
|
||||
return emit_op(compiler, SLJIT_MOV_U8, ALLOW_ANY_IMM | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw);
|
||||
|
||||
case SLJIT_MOVU_S8:
|
||||
return emit_op(compiler, SLJIT_MOV_S8, ALLOW_ANY_IMM | SIGNED_DATA | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw);
|
||||
|
||||
case SLJIT_MOVU_U16:
|
||||
return emit_op(compiler, SLJIT_MOV_U16, ALLOW_ANY_IMM | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw);
|
||||
|
||||
case SLJIT_MOVU_S16:
|
||||
return emit_op(compiler, SLJIT_MOV_S16, ALLOW_ANY_IMM | SIGNED_DATA | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw);
|
||||
return emit_op(compiler, SLJIT_MOV_S16, ALLOW_ANY_IMM | SIGNED | HALF_SIZE, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw);
|
||||
|
||||
case SLJIT_NOT:
|
||||
return emit_op(compiler, op, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
|
@ -2037,7 +2007,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *
|
|||
return push_inst(compiler, MOV | RD(dst) | RM(TMP_REG2));
|
||||
|
||||
/* Memory. */
|
||||
return emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw, TMP_REG1);
|
||||
return emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
|
||||
|
@ -2050,10 +2020,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler
|
|||
|
||||
if (FAST_IS_REG(src))
|
||||
FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG2) | RM(src)));
|
||||
else if (src & SLJIT_MEM)
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, src, srcw, TMP_REG1));
|
||||
else if (src & SLJIT_IMM)
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG2, srcw));
|
||||
else
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, src, srcw, TMP_REG1));
|
||||
|
||||
return push_inst(compiler, BX | RM(TMP_REG2));
|
||||
}
|
||||
|
@ -2150,7 +2118,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
|
|||
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
|
||||
if (type >= SLJIT_FAST_CALL)
|
||||
PTR_FAIL_IF(prepare_blx(compiler));
|
||||
PTR_FAIL_IF(push_inst_with_unique_literal(compiler, ((EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0,
|
||||
PTR_FAIL_IF(push_inst_with_unique_literal(compiler, ((EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1,
|
||||
type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0)) & ~COND_MASK) | get_cc(type), 0));
|
||||
|
||||
if (jump->flags & SLJIT_REWRITABLE_JUMP) {
|
||||
|
@ -2276,7 +2244,7 @@ static sljit_s32 softfloat_call_with_args(struct sljit_compiler *compiler, sljit
|
|||
}
|
||||
FAIL_IF(push_inst(compiler, MOV | (stack_offset << 10) | (word_arg_offset >> 2)));
|
||||
} else
|
||||
FAIL_IF(push_inst(compiler, data_transfer_insts[WORD_DATA] | 0x800000 | RN(SLJIT_SP) | (word_arg_offset << 10) | (stack_offset - 16)));
|
||||
FAIL_IF(push_inst(compiler, data_transfer_insts[WORD_SIZE] | 0x800000 | RN(SLJIT_SP) | (word_arg_offset << 10) | (stack_offset - 16)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -2427,7 +2395,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
|
|||
}
|
||||
|
||||
SLJIT_ASSERT(src & SLJIT_MEM);
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
|
||||
return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1));
|
||||
}
|
||||
|
||||
|
@ -2440,7 +2408,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
|
|||
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
|
||||
if (type >= SLJIT_FAST_CALL)
|
||||
FAIL_IF(prepare_blx(compiler));
|
||||
FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0), 0));
|
||||
FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0), 0));
|
||||
if (type >= SLJIT_FAST_CALL)
|
||||
FAIL_IF(emit_blx(compiler));
|
||||
#else
|
||||
|
@ -2460,7 +2428,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
|
|||
|
||||
#ifdef __SOFTFP__
|
||||
if (src & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
|
||||
src = TMP_REG1;
|
||||
}
|
||||
|
||||
|
@ -2505,14 +2473,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
|
|||
FAIL_IF(push_inst(compiler, MOV | RD(dst_reg) | SRC2_IMM | 0));
|
||||
FAIL_IF(push_inst(compiler, ((MOV | RD(dst_reg) | SRC2_IMM | 1) & ~COND_MASK) | cc));
|
||||
if (dst & SLJIT_MEM)
|
||||
return emit_op_mem(compiler, WORD_DATA, TMP_REG1, dst, dstw, TMP_REG2);
|
||||
return emit_op_mem(compiler, WORD_SIZE, TMP_REG1, dst, dstw, TMP_REG2);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
ins = (op == SLJIT_AND ? AND : (op == SLJIT_OR ? ORR : EOR));
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, dst, dstw, TMP_REG2));
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, dst, dstw, TMP_REG2));
|
||||
|
||||
FAIL_IF(push_inst(compiler, ((ins | RD(dst_reg) | RN(dst_reg) | SRC2_IMM | 1) & ~COND_MASK) | cc));
|
||||
|
||||
|
@ -2520,7 +2488,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
|
|||
FAIL_IF(push_inst(compiler, ((ins | RD(dst_reg) | RN(dst_reg) | SRC2_IMM | 0) & ~COND_MASK) | (cc ^ 0x10000000)));
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG1, dst, dstw, TMP_REG2));
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, dst, dstw, TMP_REG2));
|
||||
|
||||
if (flags & SLJIT_SET_Z)
|
||||
return push_inst(compiler, MOV | SET_FLAGS | RD(TMP_REG2) | RM(dst_reg));
|
||||
|
@ -2564,6 +2532,110 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
|
|||
return push_inst(compiler, ((MOV | RD(dst_reg) | RM(src)) & ~COND_MASK) | cc);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 reg,
|
||||
sljit_s32 mem, sljit_sw memw)
|
||||
{
|
||||
sljit_s32 flags;
|
||||
sljit_uw is_type1_transfer, inst;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
|
||||
|
||||
is_type1_transfer = 1;
|
||||
|
||||
switch (type & 0xff) {
|
||||
case SLJIT_MOV:
|
||||
case SLJIT_MOV_U32:
|
||||
case SLJIT_MOV_S32:
|
||||
case SLJIT_MOV_P:
|
||||
flags = WORD_SIZE;
|
||||
break;
|
||||
case SLJIT_MOV_U8:
|
||||
flags = BYTE_SIZE;
|
||||
break;
|
||||
case SLJIT_MOV_S8:
|
||||
if (!(type & SLJIT_MEM_STORE))
|
||||
is_type1_transfer = 0;
|
||||
flags = BYTE_SIZE | SIGNED;
|
||||
break;
|
||||
case SLJIT_MOV_U16:
|
||||
is_type1_transfer = 0;
|
||||
flags = HALF_SIZE;
|
||||
break;
|
||||
case SLJIT_MOV_S16:
|
||||
is_type1_transfer = 0;
|
||||
flags = HALF_SIZE | SIGNED;
|
||||
break;
|
||||
default:
|
||||
SLJIT_UNREACHABLE();
|
||||
flags = WORD_SIZE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(type & SLJIT_MEM_STORE))
|
||||
flags |= LOAD_DATA;
|
||||
|
||||
SLJIT_ASSERT(is_type1_transfer == !!IS_TYPE1_TRANSFER(flags));
|
||||
|
||||
if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
|
||||
if (!is_type1_transfer && memw != 0)
|
||||
return SLJIT_ERR_UNSUPPORTED;
|
||||
}
|
||||
else {
|
||||
if (is_type1_transfer) {
|
||||
if (memw > 4095 && memw < -4095)
|
||||
return SLJIT_ERR_UNSUPPORTED;
|
||||
}
|
||||
else {
|
||||
if (memw > 255 && memw < -255)
|
||||
return SLJIT_ERR_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
if (type & SLJIT_MEM_SUPP)
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
|
||||
memw &= 0x3;
|
||||
|
||||
inst = EMIT_DATA_TRANSFER(flags, 1, reg, mem & REG_MASK, RM(OFFS_REG(mem)) | (memw << 7));
|
||||
|
||||
if (is_type1_transfer)
|
||||
inst |= (1 << 25);
|
||||
|
||||
if (type & SLJIT_MEM_PRE)
|
||||
inst |= (1 << 21);
|
||||
else
|
||||
inst ^= (1 << 24);
|
||||
|
||||
return push_inst(compiler, inst);
|
||||
}
|
||||
|
||||
inst = EMIT_DATA_TRANSFER(flags, 0, reg, mem & REG_MASK, 0);
|
||||
|
||||
if (type & SLJIT_MEM_PRE)
|
||||
inst |= (1 << 21);
|
||||
else
|
||||
inst ^= (1 << 24);
|
||||
|
||||
if (is_type1_transfer) {
|
||||
if (memw >= 0)
|
||||
inst |= (1 << 23);
|
||||
else
|
||||
memw = -memw;
|
||||
|
||||
return push_inst(compiler, inst | memw);
|
||||
}
|
||||
|
||||
if (memw >= 0)
|
||||
inst |= (1 << 23);
|
||||
else
|
||||
memw = -memw;
|
||||
|
||||
return push_inst(compiler, inst | TYPE2_TRANSFER_IMM(memw));
|
||||
}
|
||||
|
||||
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_;
|
||||
|
@ -2579,7 +2651,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
|
|||
reg = SLOW_IS_REG(dst) ? dst : TMP_REG2;
|
||||
|
||||
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
|
||||
PTR_FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0, reg, TMP_PC, 0), init_value));
|
||||
PTR_FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, reg, TMP_PC, 0), init_value));
|
||||
compiler->patches++;
|
||||
#else
|
||||
PTR_FAIL_IF(emit_imm(compiler, reg, init_value));
|
||||
|
@ -2587,7 +2659,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
|
|||
set_const(const_, compiler);
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw, TMP_REG1));
|
||||
PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1));
|
||||
return const_;
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -453,7 +453,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
|
|||
return 1;
|
||||
#endif
|
||||
|
||||
case SLJIT_HAS_PRE_UPDATE:
|
||||
case SLJIT_HAS_CLZ:
|
||||
case SLJIT_HAS_CMOV:
|
||||
return 1;
|
||||
|
@ -738,34 +737,26 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
|
|||
case SLJIT_MOV_U32:
|
||||
case SLJIT_MOV_S32:
|
||||
case SLJIT_MOV_P:
|
||||
case SLJIT_MOVU:
|
||||
case SLJIT_MOVU_U32:
|
||||
case SLJIT_MOVU_S32:
|
||||
case SLJIT_MOVU_P:
|
||||
SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2);
|
||||
if (dst == arg2)
|
||||
return SLJIT_SUCCESS;
|
||||
return push_inst16(compiler, MOV | SET_REGS44(dst, arg2));
|
||||
case SLJIT_MOV_U8:
|
||||
case SLJIT_MOVU_U8:
|
||||
SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2);
|
||||
if (IS_2_LO_REGS(dst, arg2))
|
||||
return push_inst16(compiler, UXTB | RD3(dst) | RN3(arg2));
|
||||
return push_inst32(compiler, UXTB_W | RD4(dst) | RM4(arg2));
|
||||
case SLJIT_MOV_S8:
|
||||
case SLJIT_MOVU_S8:
|
||||
SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2);
|
||||
if (IS_2_LO_REGS(dst, arg2))
|
||||
return push_inst16(compiler, SXTB | RD3(dst) | RN3(arg2));
|
||||
return push_inst32(compiler, SXTB_W | RD4(dst) | RM4(arg2));
|
||||
case SLJIT_MOV_U16:
|
||||
case SLJIT_MOVU_U16:
|
||||
SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2);
|
||||
if (IS_2_LO_REGS(dst, arg2))
|
||||
return push_inst16(compiler, UXTH | RD3(dst) | RN3(arg2));
|
||||
return push_inst32(compiler, UXTH_W | RD4(dst) | RM4(arg2));
|
||||
case SLJIT_MOV_S16:
|
||||
case SLJIT_MOVU_S16:
|
||||
SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2);
|
||||
if (IS_2_LO_REGS(dst, arg2))
|
||||
return push_inst16(compiler, SXTH | RD3(dst) | RN3(arg2));
|
||||
|
@ -849,8 +840,6 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
|
|||
#define HALF_SIZE 0x08
|
||||
#define PRELOAD 0x0c
|
||||
|
||||
#define UPDATE 0x10
|
||||
|
||||
#define IS_WORD_SIZE(flags) (!(flags & (BYTE_SIZE | HALF_SIZE)))
|
||||
#define OFFSET_CHECK(imm, shift) (!(argw & ~(imm << shift)))
|
||||
|
||||
|
@ -949,12 +938,10 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit
|
|||
sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg)
|
||||
{
|
||||
sljit_s32 other_r;
|
||||
sljit_s32 update = flags & UPDATE;
|
||||
sljit_uw tmp;
|
||||
|
||||
SLJIT_ASSERT(arg & SLJIT_MEM);
|
||||
SLJIT_ASSERT((arg & REG_MASK) != tmp_reg);
|
||||
flags &= ~UPDATE;
|
||||
arg &= ~SLJIT_MEM;
|
||||
|
||||
if (SLJIT_UNLIKELY(!(arg & REG_MASK))) {
|
||||
|
@ -970,63 +957,6 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit
|
|||
return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(tmp_reg));
|
||||
}
|
||||
|
||||
if (SLJIT_UNLIKELY(update)) {
|
||||
SLJIT_ASSERT(reg != arg);
|
||||
|
||||
if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
|
||||
other_r = OFFS_REG(arg);
|
||||
arg &= 0xf;
|
||||
|
||||
if (IS_3_LO_REGS(reg, arg, other_r))
|
||||
FAIL_IF(push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(other_r)));
|
||||
else
|
||||
FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(other_r)));
|
||||
return push_inst16(compiler, ADD | SET_REGS44(arg, other_r));
|
||||
}
|
||||
|
||||
if (argw > 0xff) {
|
||||
tmp = get_imm(argw & ~0xff);
|
||||
if (tmp != INVALID_IMM) {
|
||||
push_inst32(compiler, ADD_WI | RD4(arg) | RN4(arg) | tmp);
|
||||
argw = argw & 0xff;
|
||||
}
|
||||
}
|
||||
else if (argw < -0xff) {
|
||||
tmp = get_imm(-argw & ~0xff);
|
||||
if (tmp != INVALID_IMM) {
|
||||
push_inst32(compiler, SUB_WI | RD4(arg) | RN4(arg) | tmp);
|
||||
argw = -(-argw & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
if (argw == 0) {
|
||||
if (IS_2_LO_REGS(reg, arg) && sljit_mem16_imm5[flags])
|
||||
return push_inst16(compiler, sljit_mem16_imm5[flags] | RD3(reg) | RN3(arg));
|
||||
return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(arg));
|
||||
}
|
||||
|
||||
if (argw <= 0xff && argw >= -0xff) {
|
||||
if (argw >= 0)
|
||||
argw |= 0x200;
|
||||
else {
|
||||
argw = -argw;
|
||||
}
|
||||
|
||||
SLJIT_ASSERT(argw >= 0 && (argw & 0xff) <= 0xff);
|
||||
return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM8 | RT4(reg) | RN4(arg) | 0x100 | argw);
|
||||
}
|
||||
|
||||
FAIL_IF(load_immediate(compiler, tmp_reg, argw));
|
||||
|
||||
SLJIT_ASSERT(reg != tmp_reg);
|
||||
|
||||
if (IS_3_LO_REGS(reg, arg, tmp_reg))
|
||||
FAIL_IF(push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(tmp_reg)));
|
||||
else
|
||||
FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(tmp_reg)));
|
||||
return push_inst16(compiler, ADD | SET_REGS44(arg, tmp_reg));
|
||||
}
|
||||
|
||||
if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
|
||||
argw &= 0x3;
|
||||
other_r = OFFS_REG(arg);
|
||||
|
@ -1300,7 +1230,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
|||
dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
|
||||
|
||||
op = GET_OPCODE(op);
|
||||
if (op >= SLJIT_MOV && op <= SLJIT_MOVU_P) {
|
||||
if (op >= SLJIT_MOV && op <= SLJIT_MOV_P) {
|
||||
switch (op) {
|
||||
case SLJIT_MOV:
|
||||
case SLJIT_MOV_U32:
|
||||
|
@ -1328,32 +1258,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
|||
if (src & SLJIT_IMM)
|
||||
srcw = (sljit_s16)srcw;
|
||||
break;
|
||||
case SLJIT_MOVU:
|
||||
case SLJIT_MOVU_U32:
|
||||
case SLJIT_MOVU_S32:
|
||||
case SLJIT_MOVU_P:
|
||||
flags = WORD_SIZE | UPDATE;
|
||||
break;
|
||||
case SLJIT_MOVU_U8:
|
||||
flags = BYTE_SIZE | UPDATE;
|
||||
if (src & SLJIT_IMM)
|
||||
srcw = (sljit_u8)srcw;
|
||||
break;
|
||||
case SLJIT_MOVU_S8:
|
||||
flags = BYTE_SIZE | SIGNED | UPDATE;
|
||||
if (src & SLJIT_IMM)
|
||||
srcw = (sljit_s8)srcw;
|
||||
break;
|
||||
case SLJIT_MOVU_U16:
|
||||
flags = HALF_SIZE | UPDATE;
|
||||
if (src & SLJIT_IMM)
|
||||
srcw = (sljit_u16)srcw;
|
||||
break;
|
||||
case SLJIT_MOVU_S16:
|
||||
flags = HALF_SIZE | SIGNED | UPDATE;
|
||||
if (src & SLJIT_IMM)
|
||||
srcw = (sljit_s16)srcw;
|
||||
break;
|
||||
default:
|
||||
SLJIT_UNREACHABLE();
|
||||
flags = 0;
|
||||
|
@ -1363,7 +1267,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
|||
if (src & SLJIT_IMM)
|
||||
FAIL_IF(emit_op_imm(compiler, SLJIT_MOV | ARG2_IMM, dst_r, TMP_REG2, srcw));
|
||||
else if (src & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem(compiler, flags, dst_r, src, srcw, ((flags & UPDATE) && dst_r == TMP_REG1) ? TMP_REG2 : TMP_REG1));
|
||||
FAIL_IF(emit_op_mem(compiler, flags, dst_r, src, srcw, TMP_REG1));
|
||||
} else {
|
||||
if (dst_r != TMP_REG1)
|
||||
return emit_op_imm(compiler, op, dst_r, TMP_REG2, src);
|
||||
|
@ -1373,7 +1277,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
|||
if (!(dst & SLJIT_MEM))
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
return emit_op_mem(compiler, flags | STORE, dst_r, dst, dstw, (dst_r == TMP_REG1) ? TMP_REG2 : TMP_REG1);
|
||||
return emit_op_mem(compiler, flags | STORE, dst_r, dst, dstw, TMP_REG2);
|
||||
}
|
||||
|
||||
if (op == SLJIT_NEG) {
|
||||
|
@ -1386,20 +1290,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
|||
|
||||
flags = HAS_FLAGS(op_flags) ? SET_FLAGS : 0;
|
||||
|
||||
if (src & SLJIT_IMM)
|
||||
flags |= ARG2_IMM;
|
||||
else if (src & SLJIT_MEM) {
|
||||
if (src & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1));
|
||||
srcw = TMP_REG1;
|
||||
src = TMP_REG1;
|
||||
}
|
||||
else
|
||||
srcw = src;
|
||||
|
||||
emit_op_imm(compiler, flags | op, dst_r, TMP_REG2, srcw);
|
||||
emit_op_imm(compiler, flags | op, dst_r, TMP_REG2, src);
|
||||
|
||||
if (!(dst & SLJIT_MEM))
|
||||
return SLJIT_SUCCESS;
|
||||
return emit_op_mem(compiler, flags | STORE, dst_r, dst, dstw, TMP_REG2);
|
||||
if (SLJIT_UNLIKELY(dst & SLJIT_MEM))
|
||||
return emit_op_mem(compiler, flags | STORE, dst_r, dst, dstw, TMP_REG2);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
|
||||
|
@ -1713,11 +1613,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler
|
|||
|
||||
if (FAST_IS_REG(src))
|
||||
FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG2, src)));
|
||||
else if (src & SLJIT_MEM) {
|
||||
else
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, src, srcw, TMP_REG2));
|
||||
}
|
||||
else if (src & SLJIT_IMM)
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG2, srcw));
|
||||
|
||||
return push_inst16(compiler, BX | RN3(TMP_REG2));
|
||||
}
|
||||
|
||||
|
@ -2231,6 +2129,63 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
|
|||
| 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 sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
|
||||
sljit_s32 reg,
|
||||
sljit_s32 mem, sljit_sw memw)
|
||||
{
|
||||
sljit_s32 flags;
|
||||
sljit_ins inst;
|
||||
|
||||
CHECK_ERROR();
|
||||
CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
|
||||
|
||||
if ((mem & OFFS_REG_MASK) || (memw > 255 && memw < -255))
|
||||
return SLJIT_ERR_UNSUPPORTED;
|
||||
|
||||
if (type & SLJIT_MEM_SUPP)
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
switch (type & 0xff) {
|
||||
case SLJIT_MOV:
|
||||
case SLJIT_MOV_U32:
|
||||
case SLJIT_MOV_S32:
|
||||
case SLJIT_MOV_P:
|
||||
flags = WORD_SIZE;
|
||||
break;
|
||||
case SLJIT_MOV_U8:
|
||||
flags = BYTE_SIZE;
|
||||
break;
|
||||
case SLJIT_MOV_S8:
|
||||
flags = BYTE_SIZE | SIGNED;
|
||||
break;
|
||||
case SLJIT_MOV_U16:
|
||||
flags = HALF_SIZE;
|
||||
break;
|
||||
case SLJIT_MOV_S16:
|
||||
flags = HALF_SIZE | SIGNED;
|
||||
break;
|
||||
default:
|
||||
SLJIT_UNREACHABLE();
|
||||
flags = WORD_SIZE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (type & SLJIT_MEM_STORE)
|
||||
flags |= STORE;
|
||||
|
||||
inst = sljit_mem32[flags] | 0x900;
|
||||
|
||||
if (type & SLJIT_MEM_PRE)
|
||||
inst |= 0x400;
|
||||
|
||||
if (memw >= 0)
|
||||
inst |= 0x200;
|
||||
else
|
||||
memw = -memw;
|
||||
|
||||
return push_inst32(compiler, inst | RT4(reg) | RN4(mem & REG_MASK) | memw);
|
||||
}
|
||||
|
||||
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_;
|
||||
|
|
|
@ -558,21 +558,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
|
|||
|
||||
#define MEM_MASK 0x1f
|
||||
|
||||
#define WRITE_BACK 0x00020
|
||||
#define ARG_TEST 0x00040
|
||||
#define ALT_KEEP_CACHE 0x00080
|
||||
#define CUMULATIVE_OP 0x00100
|
||||
#define LOGICAL_OP 0x00200
|
||||
#define IMM_OP 0x00400
|
||||
#define SRC2_IMM 0x00800
|
||||
#define ARG_TEST 0x00020
|
||||
#define ALT_KEEP_CACHE 0x00040
|
||||
#define CUMULATIVE_OP 0x00080
|
||||
#define LOGICAL_OP 0x00100
|
||||
#define IMM_OP 0x00200
|
||||
#define SRC2_IMM 0x00400
|
||||
|
||||
#define UNUSED_DEST 0x01000
|
||||
#define REG_DEST 0x02000
|
||||
#define REG1_SOURCE 0x04000
|
||||
#define REG2_SOURCE 0x08000
|
||||
#define SLOW_SRC1 0x10000
|
||||
#define SLOW_SRC2 0x20000
|
||||
#define SLOW_DEST 0x40000
|
||||
#define UNUSED_DEST 0x00800
|
||||
#define REG_DEST 0x01000
|
||||
#define REG1_SOURCE 0x02000
|
||||
#define REG2_SOURCE 0x04000
|
||||
#define SLOW_SRC1 0x08000
|
||||
#define SLOW_SRC2 0x10000
|
||||
#define SLOW_DEST 0x20000
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
#define STACK_STORE SW
|
||||
|
@ -756,7 +755,7 @@ static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flag
|
|||
{
|
||||
SLJIT_ASSERT(arg & SLJIT_MEM);
|
||||
|
||||
if ((!(flags & WRITE_BACK) || !(arg & REG_MASK)) && !(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN) {
|
||||
if (!(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN) {
|
||||
/* Works for both absoulte and relative addresses. */
|
||||
if (SLJIT_UNLIKELY(flags & ARG_TEST))
|
||||
return 1;
|
||||
|
@ -813,12 +812,6 @@ static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sl
|
|||
base = arg & REG_MASK;
|
||||
|
||||
if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
|
||||
if (SLJIT_UNLIKELY(flags & WRITE_BACK)) {
|
||||
SLJIT_ASSERT(argw == 0);
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(OFFS_REG(arg)) | D(base), DR(base)));
|
||||
return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(base) | TA(reg_ar), delay_slot);
|
||||
}
|
||||
|
||||
argw &= 0x3;
|
||||
|
||||
/* Using the cache. */
|
||||
|
@ -855,29 +848,6 @@ static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sl
|
|||
return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
|
||||
}
|
||||
|
||||
if (SLJIT_UNLIKELY(flags & WRITE_BACK) && base) {
|
||||
if (argw <= SIMM_MAX && argw >= SIMM_MIN) {
|
||||
if (argw)
|
||||
FAIL_IF(push_inst(compiler, ADDIU_W | S(base) | T(base) | IMM(argw), DR(base)));
|
||||
}
|
||||
else {
|
||||
if (compiler->cache_arg == SLJIT_MEM && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN) {
|
||||
if (argw != compiler->cache_argw) {
|
||||
FAIL_IF(push_inst(compiler, ADDIU_W | S(TMP_REG3) | T(TMP_REG3) | IMM(argw - compiler->cache_argw), DR(TMP_REG3)));
|
||||
compiler->cache_argw = argw;
|
||||
}
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(base), DR(base)));
|
||||
}
|
||||
else {
|
||||
compiler->cache_arg = SLJIT_MEM;
|
||||
compiler->cache_argw = argw;
|
||||
FAIL_IF(load_immediate(compiler, DR(TMP_REG3), argw));
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(base), DR(base)));
|
||||
}
|
||||
}
|
||||
return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(base) | TA(reg_ar), delay_slot);
|
||||
}
|
||||
|
||||
if (compiler->cache_arg == arg && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN) {
|
||||
if (argw != compiler->cache_argw) {
|
||||
FAIL_IF(push_inst(compiler, ADDIU_W | S(TMP_REG3) | T(TMP_REG3) | IMM(argw - compiler->cache_argw), DR(TMP_REG3)));
|
||||
|
@ -951,7 +921,7 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
|
|||
else if (FAST_IS_REG(dst)) {
|
||||
dst_r = dst;
|
||||
flags |= REG_DEST;
|
||||
if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32)
|
||||
if (op >= SLJIT_MOV && op <= SLJIT_MOV_P)
|
||||
sugg_src2_r = dst_r;
|
||||
}
|
||||
else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, DR(TMP_REG1), dst, dstw))
|
||||
|
@ -1005,7 +975,7 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
|
|||
if (FAST_IS_REG(src2)) {
|
||||
src2_r = src2;
|
||||
flags |= REG2_SOURCE;
|
||||
if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_S32)
|
||||
if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOV_P)
|
||||
dst_r = src2_r;
|
||||
}
|
||||
else if (src2 & SLJIT_IMM) {
|
||||
|
@ -1016,7 +986,7 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
|
|||
}
|
||||
else {
|
||||
src2_r = 0;
|
||||
if ((op >= SLJIT_MOV && op <= SLJIT_MOVU_S32) && (dst & SLJIT_MEM))
|
||||
if ((op >= SLJIT_MOV && op <= SLJIT_MOV_P) && (dst & SLJIT_MEM))
|
||||
dst_r = 0;
|
||||
}
|
||||
}
|
||||
|
@ -1155,11 +1125,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
|||
}
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
||||
if ((op & SLJIT_I32_OP) && GET_OPCODE(op) >= SLJIT_NOT) {
|
||||
if ((op & SLJIT_I32_OP) && GET_OPCODE(op) >= SLJIT_NOT)
|
||||
flags |= INT_DATA | SIGNED_DATA;
|
||||
if (src & SLJIT_IMM)
|
||||
srcw = (sljit_s32)srcw;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (GET_OPCODE(op)) {
|
||||
|
@ -1193,36 +1160,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
|||
case SLJIT_MOV_S16:
|
||||
return emit_op(compiler, SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw);
|
||||
|
||||
case SLJIT_MOVU:
|
||||
case SLJIT_MOVU_P:
|
||||
return emit_op(compiler, SLJIT_MOV, WORD_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
|
||||
case SLJIT_MOVU_U32:
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
#else
|
||||
return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u32)srcw : srcw);
|
||||
#endif
|
||||
|
||||
case SLJIT_MOVU_S32:
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
#else
|
||||
return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s32)srcw : srcw);
|
||||
#endif
|
||||
|
||||
case SLJIT_MOVU_U8:
|
||||
return emit_op(compiler, SLJIT_MOV_U8, BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw);
|
||||
|
||||
case SLJIT_MOVU_S8:
|
||||
return emit_op(compiler, SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw);
|
||||
|
||||
case SLJIT_MOVU_U16:
|
||||
return emit_op(compiler, SLJIT_MOV_U16, HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw);
|
||||
|
||||
case SLJIT_MOVU_S16:
|
||||
return emit_op(compiler, SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw);
|
||||
|
||||
case SLJIT_NOT:
|
||||
return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
|
||||
|
@ -1233,6 +1170,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
|||
return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
}
|
||||
|
||||
SLJIT_UNREACHABLE();
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
|
@ -1304,6 +1242,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
|
|||
return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
|
||||
}
|
||||
|
||||
SLJIT_UNREACHABLE();
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
|
@ -1595,10 +1534,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler
|
|||
|
||||
if (FAST_IS_REG(src))
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | DA(RETURN_ADDR_REG), RETURN_ADDR_REG));
|
||||
else if (src & SLJIT_MEM)
|
||||
else
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw));
|
||||
else if (src & SLJIT_IMM)
|
||||
FAIL_IF(load_immediate(compiler, RETURN_ADDR_REG, srcw));
|
||||
|
||||
FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));
|
||||
return push_inst(compiler, NOP, UNMOVABLE_INS);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -449,18 +449,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
|
|||
|
||||
#define MEM_MASK 0x1f
|
||||
|
||||
#define WRITE_BACK 0x00020
|
||||
#define ARG_TEST 0x00040
|
||||
#define ALT_KEEP_CACHE 0x00080
|
||||
#define CUMULATIVE_OP 0x00100
|
||||
#define IMM_OP 0x00200
|
||||
#define SRC2_IMM 0x00400
|
||||
#define ARG_TEST 0x00020
|
||||
#define ALT_KEEP_CACHE 0x00040
|
||||
#define CUMULATIVE_OP 0x00080
|
||||
#define IMM_OP 0x00100
|
||||
#define SRC2_IMM 0x00200
|
||||
|
||||
#define REG_DEST 0x00800
|
||||
#define REG2_SOURCE 0x01000
|
||||
#define SLOW_SRC1 0x02000
|
||||
#define SLOW_SRC2 0x04000
|
||||
#define SLOW_DEST 0x08000
|
||||
#define REG_DEST 0x00400
|
||||
#define REG2_SOURCE 0x00800
|
||||
#define SLOW_SRC1 0x01000
|
||||
#define SLOW_SRC2 0x02000
|
||||
#define SLOW_DEST 0x04000
|
||||
|
||||
/* SET_FLAGS (0x10 << 19) also belong here! */
|
||||
|
||||
|
@ -562,18 +561,16 @@ static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flag
|
|||
{
|
||||
SLJIT_ASSERT(arg & SLJIT_MEM);
|
||||
|
||||
if (!(flags & WRITE_BACK) || !(arg & REG_MASK)) {
|
||||
if ((!(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN)
|
||||
|| ((arg & OFFS_REG_MASK) && (argw & 0x3) == 0)) {
|
||||
/* Works for both absoulte and relative addresses (immediate case). */
|
||||
if (SLJIT_UNLIKELY(flags & ARG_TEST))
|
||||
return 1;
|
||||
FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK]
|
||||
| ((flags & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg))
|
||||
| S1(arg & REG_MASK) | ((arg & OFFS_REG_MASK) ? S2(OFFS_REG(arg)) : IMM(argw)),
|
||||
((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? DR(reg) : MOVABLE_INS));
|
||||
return -1;
|
||||
}
|
||||
if ((!(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN)
|
||||
|| ((arg & OFFS_REG_MASK) && (argw & 0x3) == 0)) {
|
||||
/* Works for both absoulte and relative addresses (immediate case). */
|
||||
if (SLJIT_UNLIKELY(flags & ARG_TEST))
|
||||
return 1;
|
||||
FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK]
|
||||
| ((flags & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg))
|
||||
| S1(arg & REG_MASK) | ((arg & OFFS_REG_MASK) ? S2(OFFS_REG(arg)) : IMM(argw)),
|
||||
((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? DR(reg) : MOVABLE_INS));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -658,10 +655,7 @@ static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sl
|
|||
delay_slot = ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? DR(reg) : MOVABLE_INS;
|
||||
if (!base)
|
||||
return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | dest | S1(arg2) | IMM(0), delay_slot);
|
||||
if (!(flags & WRITE_BACK))
|
||||
return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | dest | S1(base) | S2(arg2), delay_slot);
|
||||
FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | dest | S1(base) | S2(arg2), delay_slot));
|
||||
return push_inst(compiler, ADD | D(base) | S1(base) | S2(arg2), DR(base));
|
||||
return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | dest | S1(base) | S2(arg2), delay_slot);
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
|
||||
|
@ -703,7 +697,7 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
|
|||
if (FAST_IS_REG(dst)) {
|
||||
dst_r = dst;
|
||||
flags |= REG_DEST;
|
||||
if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32)
|
||||
if (op >= SLJIT_MOV && op <= SLJIT_MOV_P)
|
||||
sugg_src2_r = dst_r;
|
||||
}
|
||||
else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, TMP_REG1, dst, dstw))
|
||||
|
@ -754,7 +748,7 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
|
|||
if (FAST_IS_REG(src2)) {
|
||||
src2_r = src2;
|
||||
flags |= REG2_SOURCE;
|
||||
if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_S32)
|
||||
if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOV_P)
|
||||
dst_r = src2_r;
|
||||
}
|
||||
else if (src2 & SLJIT_IMM) {
|
||||
|
@ -765,7 +759,7 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
|
|||
}
|
||||
else {
|
||||
src2_r = 0;
|
||||
if ((op >= SLJIT_MOV && op <= SLJIT_MOVU_S32) && (dst & SLJIT_MEM))
|
||||
if ((op >= SLJIT_MOV && op <= SLJIT_MOV_P) && (dst & SLJIT_MEM))
|
||||
dst_r = 0;
|
||||
}
|
||||
}
|
||||
|
@ -891,28 +885,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
|||
case SLJIT_MOV_S16:
|
||||
return emit_op(compiler, SLJIT_MOV_S16, flags | HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw);
|
||||
|
||||
case SLJIT_MOVU:
|
||||
case SLJIT_MOVU_P:
|
||||
return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
|
||||
case SLJIT_MOVU_U32:
|
||||
return emit_op(compiler, SLJIT_MOV_U32, flags | INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
|
||||
case SLJIT_MOVU_S32:
|
||||
return emit_op(compiler, SLJIT_MOV_S32, flags | INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
|
||||
case SLJIT_MOVU_U8:
|
||||
return emit_op(compiler, SLJIT_MOV_U8, flags | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw);
|
||||
|
||||
case SLJIT_MOVU_S8:
|
||||
return emit_op(compiler, SLJIT_MOV_S8, flags | BYTE_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw);
|
||||
|
||||
case SLJIT_MOVU_U16:
|
||||
return emit_op(compiler, SLJIT_MOV_U16, flags | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw);
|
||||
|
||||
case SLJIT_MOVU_S16:
|
||||
return emit_op(compiler, SLJIT_MOV_S16, flags | HALF_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw);
|
||||
|
||||
case SLJIT_NOT:
|
||||
case SLJIT_CLZ:
|
||||
return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
|
@ -1227,10 +1199,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler
|
|||
|
||||
if (FAST_IS_REG(src))
|
||||
FAIL_IF(push_inst(compiler, OR | D(TMP_LINK) | S1(0) | S2(src), DR(TMP_LINK)));
|
||||
else if (src & SLJIT_MEM)
|
||||
else
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_LINK, src, srcw));
|
||||
else if (src & SLJIT_IMM)
|
||||
FAIL_IF(load_immediate(compiler, TMP_LINK, srcw));
|
||||
|
||||
FAIL_IF(push_inst(compiler, JMPL | D(0) | S1(TMP_LINK) | IMM(8), UNMOVABLE_INS));
|
||||
return push_inst(compiler, NOP, UNMOVABLE_INS);
|
||||
|
|
|
@ -855,7 +855,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler
|
|||
INC_SIZE(1 + 1);
|
||||
PUSH_REG(reg_map[src]);
|
||||
}
|
||||
else if (src & SLJIT_MEM) {
|
||||
else {
|
||||
inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);
|
||||
FAIL_IF(!inst);
|
||||
*inst++ = GROUP_FF;
|
||||
|
@ -865,16 +865,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler
|
|||
FAIL_IF(!inst);
|
||||
INC_SIZE(1);
|
||||
}
|
||||
else {
|
||||
/* SLJIT_IMM. */
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + 5 + 1);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(5 + 1);
|
||||
*inst++ = PUSH_i32;
|
||||
sljit_unaligned_store_sw(inst, srcw);
|
||||
inst += sizeof(sljit_sw);
|
||||
}
|
||||
|
||||
RET();
|
||||
return SLJIT_SUCCESS;
|
||||
|
|
|
@ -41,24 +41,31 @@ static sljit_s32 emit_load_imm64(struct sljit_compiler *compiler, sljit_s32 reg,
|
|||
|
||||
static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_s32 type)
|
||||
{
|
||||
/* The relative jump below specialized for this case. */
|
||||
SLJIT_ASSERT(reg_map[TMP_REG2] >= 8);
|
||||
|
||||
int short_addr = !(jump->flags & SLJIT_REWRITABLE_JUMP) && !(jump->flags & JUMP_LABEL) && (jump->u.target <= 0xffffffff);
|
||||
|
||||
if (type < SLJIT_JUMP) {
|
||||
/* Invert type. */
|
||||
*code_ptr++ = get_jump_code(type ^ 0x1) - 0x10;
|
||||
*code_ptr++ = 10 + 3;
|
||||
*code_ptr++ = short_addr ? (6 + 3) : (10 + 3);
|
||||
}
|
||||
|
||||
*code_ptr++ = REX_W | ((reg_map[TMP_REG2] <= 7) ? 0 : REX_B);
|
||||
*code_ptr++ = short_addr ? REX_B : (REX_W | REX_B);
|
||||
*code_ptr++ = MOV_r_i32 | reg_lmap[TMP_REG2];
|
||||
jump->addr = (sljit_uw)code_ptr;
|
||||
|
||||
if (jump->flags & JUMP_LABEL)
|
||||
jump->flags |= PATCH_MD;
|
||||
else if (short_addr)
|
||||
sljit_unaligned_store_s32(code_ptr, (sljit_s32)jump->u.target);
|
||||
else
|
||||
sljit_unaligned_store_sw(code_ptr, jump->u.target);
|
||||
|
||||
code_ptr += sizeof(sljit_sw);
|
||||
if (reg_map[TMP_REG2] >= 8)
|
||||
*code_ptr++ = REX_B;
|
||||
code_ptr += short_addr ? sizeof(sljit_s32) : sizeof(sljit_sw);
|
||||
|
||||
*code_ptr++ = REX_B;
|
||||
*code_ptr++ = GROUP_FF;
|
||||
*code_ptr++ = MOD_REG | (type >= SLJIT_FAST_CALL ? CALL_rm : JMP_rm) | reg_lmap[TMP_REG2];
|
||||
|
||||
|
@ -755,11 +762,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler
|
|||
CHECK(check_sljit_emit_fast_return(compiler, src, srcw));
|
||||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
|
||||
if ((src & SLJIT_IMM) && NOT_HALFWORD(srcw)) {
|
||||
FAIL_IF(emit_load_imm64(compiler, TMP_REG1, srcw));
|
||||
src = TMP_REG1;
|
||||
}
|
||||
|
||||
if (FAST_IS_REG(src)) {
|
||||
if (reg_map[src] < 8) {
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 1);
|
||||
|
@ -777,7 +779,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler
|
|||
PUSH_REG(reg_lmap[src]);
|
||||
}
|
||||
}
|
||||
else if (src & SLJIT_MEM) {
|
||||
else {
|
||||
/* REX_W is not necessary (src is not immediate). */
|
||||
compiler->mode32 = 1;
|
||||
inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);
|
||||
|
@ -789,17 +791,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler
|
|||
FAIL_IF(!inst);
|
||||
INC_SIZE(1);
|
||||
}
|
||||
else {
|
||||
SLJIT_ASSERT(IS_HALFWORD(srcw));
|
||||
/* SLJIT_IMM. */
|
||||
inst = (sljit_u8*)ensure_buf(compiler, 1 + 5 + 1);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(5 + 1);
|
||||
*inst++ = PUSH_i32;
|
||||
sljit_unaligned_store_s32(inst, srcw);
|
||||
inst += sizeof(sljit_s32);
|
||||
}
|
||||
|
||||
RET();
|
||||
return SLJIT_SUCCESS;
|
||||
|
|
|
@ -39,7 +39,7 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
|
|||
1 - ECX
|
||||
2 - EDX
|
||||
3 - EBX
|
||||
4 - none
|
||||
4 - ESP
|
||||
5 - EBP
|
||||
6 - ESI
|
||||
7 - EDI
|
||||
|
@ -51,7 +51,7 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
|
|||
1 - RCX
|
||||
2 - RDX
|
||||
3 - RBX
|
||||
4 - none
|
||||
4 - RSP
|
||||
5 - RBP
|
||||
6 - RSI
|
||||
7 - RDI
|
||||
|
@ -477,11 +477,7 @@ static sljit_u8* generate_near_jump_code(struct sljit_jump *jump, sljit_u8 *code
|
|||
code_ptr += sizeof(sljit_s8);
|
||||
} else {
|
||||
jump->flags |= PATCH_MW;
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
code_ptr += sizeof(sljit_sw);
|
||||
#else
|
||||
code_ptr += sizeof(sljit_s32);
|
||||
#endif
|
||||
}
|
||||
|
||||
return code_ptr;
|
||||
|
@ -1135,7 +1131,7 @@ static sljit_s32 emit_unary(struct sljit_compiler *compiler, sljit_u8 opcode,
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (dst == SLJIT_UNUSED)
|
||||
if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED))
|
||||
dst = TMP_REG1;
|
||||
|
||||
if (FAST_IS_REG(dst)) {
|
||||
|
@ -1202,12 +1198,6 @@ static sljit_s32 emit_clz(struct sljit_compiler *compiler, sljit_s32 op_flags,
|
|||
|
||||
SLJIT_UNUSED_ARG(op_flags);
|
||||
|
||||
if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {
|
||||
EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, srcw);
|
||||
src = TMP_REG1;
|
||||
srcw = 0;
|
||||
}
|
||||
|
||||
if (cpu_has_cmov == -1)
|
||||
get_cpu_features();
|
||||
|
||||
|
@ -1262,13 +1252,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
|||
sljit_s32 dst, sljit_sw dstw,
|
||||
sljit_s32 src, sljit_sw srcw)
|
||||
{
|
||||
sljit_s32 update = 0;
|
||||
sljit_s32 op_flags = GET_ALL_FLAGS(op);
|
||||
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
|
||||
sljit_s32 dst_is_ereg = 0;
|
||||
sljit_s32 src_is_ereg = 0;
|
||||
#else
|
||||
# define src_is_ereg 0
|
||||
#endif
|
||||
|
||||
CHECK_ERROR();
|
||||
|
@ -1277,7 +1263,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
|||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
|
||||
CHECK_EXTRA_REGS(dst, dstw, dst_is_ereg = 1);
|
||||
CHECK_EXTRA_REGS(src, srcw, src_is_ereg = 1);
|
||||
CHECK_EXTRA_REGS(src, srcw, (void)0);
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
compiler->mode32 = op_flags & SLJIT_I32_OP;
|
||||
#endif
|
||||
|
@ -1290,7 +1276,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
|||
|
||||
op = GET_OPCODE(op);
|
||||
|
||||
if (op >= SLJIT_MOV && op <= SLJIT_MOVU_P) {
|
||||
if (op >= SLJIT_MOV && op <= SLJIT_MOV_P) {
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
compiler->mode32 = 0;
|
||||
#endif
|
||||
|
@ -1305,24 +1291,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
|||
if (src & SLJIT_MEM) {
|
||||
if (op == SLJIT_MOV_S32)
|
||||
op = SLJIT_MOV_U32;
|
||||
if (op == SLJIT_MOVU_S32)
|
||||
op = SLJIT_MOVU_U32;
|
||||
}
|
||||
else if (src & SLJIT_IMM) {
|
||||
if (op == SLJIT_MOV_U32)
|
||||
op = SLJIT_MOV_S32;
|
||||
if (op == SLJIT_MOVU_U32)
|
||||
op = SLJIT_MOVU_S32;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
SLJIT_COMPILE_ASSERT(SLJIT_MOV + 8 == SLJIT_MOVU, movu_offset);
|
||||
if (op >= SLJIT_MOVU) {
|
||||
update = 1;
|
||||
op -= 8;
|
||||
}
|
||||
|
||||
if (src & SLJIT_IMM) {
|
||||
switch (op) {
|
||||
case SLJIT_MOV_U8:
|
||||
|
@ -1394,28 +1370,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
|||
if (SLJIT_UNLIKELY(dst_is_ereg) && dst == TMP_REG1)
|
||||
return emit_mov(compiler, SLJIT_MEM1(SLJIT_SP), dstw, TMP_REG1, 0);
|
||||
#endif
|
||||
|
||||
if (SLJIT_UNLIKELY(update) && (src & SLJIT_MEM) && !src_is_ereg && (src & REG_MASK)) {
|
||||
if ((src & OFFS_REG_MASK) != 0) {
|
||||
FAIL_IF(emit_cum_binary(compiler, BINARY_OPCODE(ADD),
|
||||
(src & REG_MASK), 0, (src & REG_MASK), 0, OFFS_REG(dst), 0));
|
||||
}
|
||||
else if (srcw != 0) {
|
||||
FAIL_IF(emit_cum_binary(compiler, BINARY_OPCODE(ADD),
|
||||
(src & REG_MASK), 0, (src & REG_MASK), 0, SLJIT_IMM, srcw));
|
||||
}
|
||||
}
|
||||
|
||||
if (SLJIT_UNLIKELY(update) && (dst & SLJIT_MEM) && (dst & REG_MASK)) {
|
||||
if ((dst & OFFS_REG_MASK) != 0) {
|
||||
FAIL_IF(emit_cum_binary(compiler, BINARY_OPCODE(ADD),
|
||||
(dst & REG_MASK), 0, (dst & REG_MASK), 0, OFFS_REG(dst), 0));
|
||||
}
|
||||
else if (dstw != 0) {
|
||||
FAIL_IF(emit_cum_binary(compiler, BINARY_OPCODE(ADD),
|
||||
(dst & REG_MASK), 0, (dst & REG_MASK), 0, SLJIT_IMM, dstw));
|
||||
}
|
||||
}
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1433,10 +1387,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
|
|||
}
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
# undef src_is_ereg
|
||||
#endif
|
||||
}
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
|
|
Loading…
Reference in New Issue