in pcre/sljit/sljitNativeARM_32.c [986:1132]
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_s32 src2)
{
sljit_sw mul_inst;
switch (GET_OPCODE(op)) {
case SLJIT_MOV:
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));
if (dst != src2) {
if (src2 & SRC2_IMM) {
if (flags & INV_IMM)
EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2);
EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2);
}
EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, reg_map[src2]);
}
return SLJIT_SUCCESS;
case SLJIT_MOV_U8:
case SLJIT_MOV_S8:
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));
if ((flags & (REG_DEST | REG_SOURCE)) == (REG_DEST | REG_SOURCE)) {
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
if (op == SLJIT_MOV_U8)
return push_inst(compiler, EMIT_DATA_PROCESS_INS(AND_DP, 0, dst, src2, SRC2_IMM | 0xff));
FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (24 << 7) | reg_map[src2])));
return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (24 << 7) | (op == SLJIT_MOV_U8 ? 0x20 : 0x40) | reg_map[dst]));
#else
return push_inst(compiler, (op == SLJIT_MOV_U8 ? UXTB : SXTB) | RD(dst) | RM(src2));
#endif
}
else if (dst != src2) {
SLJIT_ASSERT(src2 & SRC2_IMM);
if (flags & INV_IMM)
EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2);
EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2);
}
return SLJIT_SUCCESS;
case SLJIT_MOV_U16:
case SLJIT_MOV_S16:
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));
if ((flags & (REG_DEST | REG_SOURCE)) == (REG_DEST | REG_SOURCE)) {
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (16 << 7) | reg_map[src2])));
return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (16 << 7) | (op == SLJIT_MOV_U16 ? 0x20 : 0x40) | reg_map[dst]));
#else
return push_inst(compiler, (op == SLJIT_MOV_U16 ? UXTH : SXTH) | RD(dst) | RM(src2));
#endif
}
else if (dst != src2) {
SLJIT_ASSERT(src2 & SRC2_IMM);
if (flags & INV_IMM)
EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2);
EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2);
}
return SLJIT_SUCCESS;
case SLJIT_NOT:
if (src2 & SRC2_IMM) {
if (flags & INV_IMM)
EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2);
EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2);
}
EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, RM(src2));
case SLJIT_CLZ:
SLJIT_ASSERT(!(flags & INV_IMM));
SLJIT_ASSERT(!(src2 & SRC2_IMM));
FAIL_IF(push_inst(compiler, CLZ | RD(dst) | RM(src2)));
if (flags & SET_FLAGS)
EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(CMP_DP, SLJIT_UNUSED, dst, SRC2_IMM);
return SLJIT_SUCCESS;
case SLJIT_ADD:
SLJIT_ASSERT(!(flags & INV_IMM));
EMIT_DATA_PROCESS_INS_AND_RETURN(ADD_DP);
case SLJIT_ADDC:
SLJIT_ASSERT(!(flags & INV_IMM));
EMIT_DATA_PROCESS_INS_AND_RETURN(ADC_DP);
case SLJIT_SUB:
SLJIT_ASSERT(!(flags & INV_IMM));
if (!(flags & ARGS_SWAPPED))
EMIT_DATA_PROCESS_INS_AND_RETURN(SUB_DP);
EMIT_DATA_PROCESS_INS_AND_RETURN(RSB_DP);
case SLJIT_SUBC:
SLJIT_ASSERT(!(flags & INV_IMM));
if (!(flags & ARGS_SWAPPED))
EMIT_DATA_PROCESS_INS_AND_RETURN(SBC_DP);
EMIT_DATA_PROCESS_INS_AND_RETURN(RSC_DP);
case SLJIT_MUL:
SLJIT_ASSERT(!(flags & INV_IMM));
SLJIT_ASSERT(!(src2 & SRC2_IMM));
if (SLJIT_UNLIKELY(op & SLJIT_SET_O))
mul_inst = SMULL | (reg_map[TMP_REG3] << 16) | (reg_map[dst] << 12);
else
mul_inst = MUL | (reg_map[dst] << 16);
if (dst != src2)
FAIL_IF(push_inst(compiler, mul_inst | (reg_map[src1] << 8) | reg_map[src2]));
else if (dst != src1)
FAIL_IF(push_inst(compiler, mul_inst | (reg_map[src2] << 8) | reg_map[src1]));
else {
/* Rm and Rd must not be the same register. */
SLJIT_ASSERT(dst != TMP_REG1);
FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG1, SLJIT_UNUSED, reg_map[src2])));
FAIL_IF(push_inst(compiler, mul_inst | (reg_map[src2] << 8) | reg_map[TMP_REG1]));
}
if (!(op & SLJIT_SET_O))
return SLJIT_SUCCESS;
/* We need to use TMP_REG3. */
compiler->cache_arg = 0;
compiler->cache_argw = 0;
/* cmp TMP_REG2, dst asr #31. */
return push_inst(compiler, EMIT_DATA_PROCESS_INS(CMP_DP, SET_FLAGS, SLJIT_UNUSED, TMP_REG3, RM(dst) | 0xfc0));
case SLJIT_AND:
if (!(flags & INV_IMM))
EMIT_DATA_PROCESS_INS_AND_RETURN(AND_DP);
EMIT_DATA_PROCESS_INS_AND_RETURN(BIC_DP);
case SLJIT_OR:
SLJIT_ASSERT(!(flags & INV_IMM));
EMIT_DATA_PROCESS_INS_AND_RETURN(ORR_DP);
case SLJIT_XOR:
SLJIT_ASSERT(!(flags & INV_IMM));
EMIT_DATA_PROCESS_INS_AND_RETURN(EOR_DP);
case SLJIT_SHL:
EMIT_SHIFT_INS_AND_RETURN(0);
case SLJIT_LSHR:
EMIT_SHIFT_INS_AND_RETURN(1);
case SLJIT_ASHR:
EMIT_SHIFT_INS_AND_RETURN(2);
}
SLJIT_ASSERT_STOP();
return SLJIT_SUCCESS;
}