in pcre/sljit/sljitNativeTILEGX_64.c [1585:1957]
static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, sljit_s32 dst, sljit_s32 src1, sljit_sw src2)
{
sljit_s32 overflow_ra = 0;
switch (GET_OPCODE(op)) {
case SLJIT_MOV:
case SLJIT_MOV_P:
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
if (dst != src2)
return ADD(reg_map[dst], reg_map[src2], ZERO);
return SLJIT_SUCCESS;
case SLJIT_MOV_U32:
case SLJIT_MOV_S32:
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
if (op == SLJIT_MOV_S32)
return BFEXTS(reg_map[dst], reg_map[src2], 0, 31);
return BFEXTU(reg_map[dst], reg_map[src2], 0, 31);
} else if (dst != src2) {
SLJIT_ASSERT(src2 == 0);
return ADD(reg_map[dst], reg_map[src2], ZERO);
}
return SLJIT_SUCCESS;
case SLJIT_MOV_U8:
case SLJIT_MOV_S8:
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
if (op == SLJIT_MOV_S8)
return BFEXTS(reg_map[dst], reg_map[src2], 0, 7);
return BFEXTU(reg_map[dst], reg_map[src2], 0, 7);
} else if (dst != src2) {
SLJIT_ASSERT(src2 == 0);
return ADD(reg_map[dst], reg_map[src2], ZERO);
}
return SLJIT_SUCCESS;
case SLJIT_MOV_U16:
case SLJIT_MOV_S16:
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
if (op == SLJIT_MOV_S16)
return BFEXTS(reg_map[dst], reg_map[src2], 0, 15);
return BFEXTU(reg_map[dst], reg_map[src2], 0, 15);
} else if (dst != src2) {
SLJIT_ASSERT(src2 == 0);
return ADD(reg_map[dst], reg_map[src2], ZERO);
}
return SLJIT_SUCCESS;
case SLJIT_NOT:
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
if (op & SLJIT_SET_E)
FAIL_IF(NOR(EQUAL_FLAG, reg_map[src2], reg_map[src2]));
if (CHECK_FLAGS(SLJIT_SET_E))
FAIL_IF(NOR(reg_map[dst], reg_map[src2], reg_map[src2]));
return SLJIT_SUCCESS;
case SLJIT_CLZ:
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
if (op & SLJIT_SET_E)
FAIL_IF(CLZ(EQUAL_FLAG, reg_map[src2]));
if (CHECK_FLAGS(SLJIT_SET_E))
FAIL_IF(CLZ(reg_map[dst], reg_map[src2]));
return SLJIT_SUCCESS;
case SLJIT_ADD:
if (flags & SRC2_IMM) {
if (op & SLJIT_SET_O) {
FAIL_IF(SHRUI(TMP_EREG1, reg_map[src1], 63));
if (src2 < 0)
FAIL_IF(XORI(TMP_EREG1, TMP_EREG1, 1));
}
if (op & SLJIT_SET_E)
FAIL_IF(ADDLI(EQUAL_FLAG, reg_map[src1], src2));
if (op & SLJIT_SET_C) {
if (src2 >= 0)
FAIL_IF(ORI(ULESS_FLAG ,reg_map[src1], src2));
else {
FAIL_IF(ADDLI(ULESS_FLAG ,ZERO, src2));
FAIL_IF(OR(ULESS_FLAG,reg_map[src1],ULESS_FLAG));
}
}
/* dst may be the same as src1 or src2. */
if (CHECK_FLAGS(SLJIT_SET_E))
FAIL_IF(ADDLI(reg_map[dst], reg_map[src1], src2));
if (op & SLJIT_SET_O) {
FAIL_IF(SHRUI(OVERFLOW_FLAG, reg_map[dst], 63));
if (src2 < 0)
FAIL_IF(XORI(OVERFLOW_FLAG, OVERFLOW_FLAG, 1));
}
} else {
if (op & SLJIT_SET_O) {
FAIL_IF(XOR(TMP_EREG1, reg_map[src1], reg_map[src2]));
FAIL_IF(SHRUI(TMP_EREG1, TMP_EREG1, 63));
if (src1 != dst)
overflow_ra = reg_map[src1];
else if (src2 != dst)
overflow_ra = reg_map[src2];
else {
/* Rare ocasion. */
FAIL_IF(ADD(TMP_EREG2, reg_map[src1], ZERO));
overflow_ra = TMP_EREG2;
}
}
if (op & SLJIT_SET_E)
FAIL_IF(ADD(EQUAL_FLAG ,reg_map[src1], reg_map[src2]));
if (op & SLJIT_SET_C)
FAIL_IF(OR(ULESS_FLAG,reg_map[src1], reg_map[src2]));
/* dst may be the same as src1 or src2. */
if (CHECK_FLAGS(SLJIT_SET_E))
FAIL_IF(ADD(reg_map[dst],reg_map[src1], reg_map[src2]));
if (op & SLJIT_SET_O) {
FAIL_IF(XOR(OVERFLOW_FLAG,reg_map[dst], overflow_ra));
FAIL_IF(SHRUI(OVERFLOW_FLAG, OVERFLOW_FLAG, 63));
}
}
/* a + b >= a | b (otherwise, the carry should be set to 1). */
if (op & SLJIT_SET_C)
FAIL_IF(CMPLTU(ULESS_FLAG ,reg_map[dst] ,ULESS_FLAG));
if (op & SLJIT_SET_O)
return CMOVNEZ(OVERFLOW_FLAG, TMP_EREG1, ZERO);
return SLJIT_SUCCESS;
case SLJIT_ADDC:
if (flags & SRC2_IMM) {
if (op & SLJIT_SET_C) {
if (src2 >= 0)
FAIL_IF(ORI(TMP_EREG1, reg_map[src1], src2));
else {
FAIL_IF(ADDLI(TMP_EREG1, ZERO, src2));
FAIL_IF(OR(TMP_EREG1, reg_map[src1], TMP_EREG1));
}
}
FAIL_IF(ADDLI(reg_map[dst], reg_map[src1], src2));
} else {
if (op & SLJIT_SET_C)
FAIL_IF(OR(TMP_EREG1, reg_map[src1], reg_map[src2]));
/* dst may be the same as src1 or src2. */
FAIL_IF(ADD(reg_map[dst], reg_map[src1], reg_map[src2]));
}
if (op & SLJIT_SET_C)
FAIL_IF(CMPLTU(TMP_EREG1, reg_map[dst], TMP_EREG1));
FAIL_IF(ADD(reg_map[dst], reg_map[dst], ULESS_FLAG));
if (!(op & SLJIT_SET_C))
return SLJIT_SUCCESS;
/* Set TMP_EREG2 (dst == 0) && (ULESS_FLAG == 1). */
FAIL_IF(CMPLTUI(TMP_EREG2, reg_map[dst], 1));
FAIL_IF(AND(TMP_EREG2, TMP_EREG2, ULESS_FLAG));
/* Set carry flag. */
return OR(ULESS_FLAG, TMP_EREG2, TMP_EREG1);
case SLJIT_SUB:
if ((flags & SRC2_IMM) && ((op & (SLJIT_SET_U | SLJIT_SET_S)) || src2 == SIMM_16BIT_MIN)) {
FAIL_IF(ADDLI(TMP_REG2_mapped, ZERO, src2));
src2 = TMP_REG2;
flags &= ~SRC2_IMM;
}
if (flags & SRC2_IMM) {
if (op & SLJIT_SET_O) {
FAIL_IF(SHRUI(TMP_EREG1,reg_map[src1], 63));
if (src2 < 0)
FAIL_IF(XORI(TMP_EREG1, TMP_EREG1, 1));
if (src1 != dst)
overflow_ra = reg_map[src1];
else {
/* Rare ocasion. */
FAIL_IF(ADD(TMP_EREG2, reg_map[src1], ZERO));
overflow_ra = TMP_EREG2;
}
}
if (op & SLJIT_SET_E)
FAIL_IF(ADDLI(EQUAL_FLAG, reg_map[src1], -src2));
if (op & SLJIT_SET_C) {
FAIL_IF(load_immediate(compiler, ADDR_TMP_mapped, src2));
FAIL_IF(CMPLTU(ULESS_FLAG, reg_map[src1], ADDR_TMP_mapped));
}
/* dst may be the same as src1 or src2. */
if (CHECK_FLAGS(SLJIT_SET_E))
FAIL_IF(ADDLI(reg_map[dst], reg_map[src1], -src2));
} else {
if (op & SLJIT_SET_O) {
FAIL_IF(XOR(TMP_EREG1, reg_map[src1], reg_map[src2]));
FAIL_IF(SHRUI(TMP_EREG1, TMP_EREG1, 63));
if (src1 != dst)
overflow_ra = reg_map[src1];
else {
/* Rare ocasion. */
FAIL_IF(ADD(TMP_EREG2, reg_map[src1], ZERO));
overflow_ra = TMP_EREG2;
}
}
if (op & SLJIT_SET_E)
FAIL_IF(SUB(EQUAL_FLAG, reg_map[src1], reg_map[src2]));
if (op & (SLJIT_SET_U | SLJIT_SET_C))
FAIL_IF(CMPLTU(ULESS_FLAG, reg_map[src1], reg_map[src2]));
if (op & SLJIT_SET_U)
FAIL_IF(CMPLTU(UGREATER_FLAG, reg_map[src2], reg_map[src1]));
if (op & SLJIT_SET_S) {
FAIL_IF(CMPLTS(LESS_FLAG ,reg_map[src1] ,reg_map[src2]));
FAIL_IF(CMPLTS(GREATER_FLAG ,reg_map[src2] ,reg_map[src1]));
}
/* dst may be the same as src1 or src2. */
if (CHECK_FLAGS(SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_C))
FAIL_IF(SUB(reg_map[dst], reg_map[src1], reg_map[src2]));
}
if (op & SLJIT_SET_O) {
FAIL_IF(XOR(OVERFLOW_FLAG, reg_map[dst], overflow_ra));
FAIL_IF(SHRUI(OVERFLOW_FLAG, OVERFLOW_FLAG, 63));
return CMOVEQZ(OVERFLOW_FLAG, TMP_EREG1, ZERO);
}
return SLJIT_SUCCESS;
case SLJIT_SUBC:
if ((flags & SRC2_IMM) && src2 == SIMM_16BIT_MIN) {
FAIL_IF(ADDLI(TMP_REG2_mapped, ZERO, src2));
src2 = TMP_REG2;
flags &= ~SRC2_IMM;
}
if (flags & SRC2_IMM) {
if (op & SLJIT_SET_C) {
FAIL_IF(load_immediate(compiler, ADDR_TMP_mapped, -src2));
FAIL_IF(CMPLTU(TMP_EREG1, reg_map[src1], ADDR_TMP_mapped));
}
/* dst may be the same as src1 or src2. */
FAIL_IF(ADDLI(reg_map[dst], reg_map[src1], -src2));
} else {
if (op & SLJIT_SET_C)
FAIL_IF(CMPLTU(TMP_EREG1, reg_map[src1], reg_map[src2]));
/* dst may be the same as src1 or src2. */
FAIL_IF(SUB(reg_map[dst], reg_map[src1], reg_map[src2]));
}
if (op & SLJIT_SET_C)
FAIL_IF(CMOVEQZ(TMP_EREG1, reg_map[dst], ULESS_FLAG));
FAIL_IF(SUB(reg_map[dst], reg_map[dst], ULESS_FLAG));
if (op & SLJIT_SET_C)
FAIL_IF(ADD(ULESS_FLAG, TMP_EREG1, ZERO));
return SLJIT_SUCCESS;
case SLJIT_MUL:
if (flags & SRC2_IMM) {
FAIL_IF(load_immediate(compiler, TMP_REG2_mapped, src2));
src2 = TMP_REG2;
flags &= ~SRC2_IMM;
}
FAIL_IF(MUL(reg_map[dst], reg_map[src1], reg_map[src2]));
return SLJIT_SUCCESS;
#define EMIT_LOGICAL(op_imm, op_norm) \
if (flags & SRC2_IMM) { \
FAIL_IF(load_immediate(compiler, ADDR_TMP_mapped, src2)); \
if (op & SLJIT_SET_E) \
FAIL_IF(push_3_buffer( \
compiler, op_norm, EQUAL_FLAG, reg_map[src1], \
ADDR_TMP_mapped, __LINE__)); \
if (CHECK_FLAGS(SLJIT_SET_E)) \
FAIL_IF(push_3_buffer( \
compiler, op_norm, reg_map[dst], reg_map[src1], \
ADDR_TMP_mapped, __LINE__)); \
} else { \
if (op & SLJIT_SET_E) \
FAIL_IF(push_3_buffer( \
compiler, op_norm, EQUAL_FLAG, reg_map[src1], \
reg_map[src2], __LINE__)); \
if (CHECK_FLAGS(SLJIT_SET_E)) \
FAIL_IF(push_3_buffer( \
compiler, op_norm, reg_map[dst], reg_map[src1], \
reg_map[src2], __LINE__)); \
}
case SLJIT_AND:
EMIT_LOGICAL(TILEGX_OPC_ANDI, TILEGX_OPC_AND);
return SLJIT_SUCCESS;
case SLJIT_OR:
EMIT_LOGICAL(TILEGX_OPC_ORI, TILEGX_OPC_OR);
return SLJIT_SUCCESS;
case SLJIT_XOR:
EMIT_LOGICAL(TILEGX_OPC_XORI, TILEGX_OPC_XOR);
return SLJIT_SUCCESS;
#define EMIT_SHIFT(op_imm, op_norm) \
if (flags & SRC2_IMM) { \
if (op & SLJIT_SET_E) \
FAIL_IF(push_3_buffer( \
compiler, op_imm, EQUAL_FLAG, reg_map[src1], \
src2 & 0x3F, __LINE__)); \
if (CHECK_FLAGS(SLJIT_SET_E)) \
FAIL_IF(push_3_buffer( \
compiler, op_imm, reg_map[dst], reg_map[src1], \
src2 & 0x3F, __LINE__)); \
} else { \
if (op & SLJIT_SET_E) \
FAIL_IF(push_3_buffer( \
compiler, op_norm, EQUAL_FLAG, reg_map[src1], \
reg_map[src2], __LINE__)); \
if (CHECK_FLAGS(SLJIT_SET_E)) \
FAIL_IF(push_3_buffer( \
compiler, op_norm, reg_map[dst], reg_map[src1], \
reg_map[src2], __LINE__)); \
}
case SLJIT_SHL:
EMIT_SHIFT(TILEGX_OPC_SHLI, TILEGX_OPC_SHL);
return SLJIT_SUCCESS;
case SLJIT_LSHR:
EMIT_SHIFT(TILEGX_OPC_SHRUI, TILEGX_OPC_SHRU);
return SLJIT_SUCCESS;
case SLJIT_ASHR:
EMIT_SHIFT(TILEGX_OPC_SHRSI, TILEGX_OPC_SHRS);
return SLJIT_SUCCESS;
}
SLJIT_ASSERT_STOP();
return SLJIT_SUCCESS;
}