in pcre/sljit/sljitNativePPC_common.c [1121:1248]
static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 input_flags,
sljit_s32 dst, sljit_sw dstw,
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
{
/* arg1 goes to TMP_REG1 or src reg
arg2 goes to TMP_REG2, imm or src reg
TMP_REG3 can be used for caching
result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */
sljit_s32 dst_r;
sljit_s32 src1_r;
sljit_s32 src2_r;
sljit_s32 sugg_src2_r = TMP_REG2;
sljit_s32 flags = input_flags & (ALT_FORM1 | ALT_FORM2 | ALT_FORM3 | ALT_FORM4 | ALT_FORM5 | ALT_FORM6 | ALT_SIGN_EXT | ALT_SET_FLAGS);
if (!(input_flags & ALT_KEEP_CACHE)) {
compiler->cache_arg = 0;
compiler->cache_argw = 0;
}
/* Destination check. */
if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) {
if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32 && !(src2 & SLJIT_MEM))
return SLJIT_SUCCESS;
dst_r = TMP_REG2;
}
else if (FAST_IS_REG(dst)) {
dst_r = dst;
flags |= REG_DEST;
if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32)
sugg_src2_r = dst_r;
}
else {
SLJIT_ASSERT(dst & SLJIT_MEM);
if (getput_arg_fast(compiler, input_flags | ARG_TEST, TMP_REG2, dst, dstw)) {
flags |= FAST_DEST;
dst_r = TMP_REG2;
}
else {
flags |= SLOW_DEST;
dst_r = 0;
}
}
/* Source 1. */
if (FAST_IS_REG(src1)) {
src1_r = src1;
flags |= REG1_SOURCE;
}
else if (src1 & SLJIT_IMM) {
FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));
src1_r = TMP_REG1;
}
else if (getput_arg_fast(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w)) {
FAIL_IF(compiler->error);
src1_r = TMP_REG1;
}
else
src1_r = 0;
/* Source 2. */
if (FAST_IS_REG(src2)) {
src2_r = src2;
flags |= REG2_SOURCE;
if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_S32)
dst_r = src2_r;
}
else if (src2 & SLJIT_IMM) {
FAIL_IF(load_immediate(compiler, sugg_src2_r, src2w));
src2_r = sugg_src2_r;
}
else if (getput_arg_fast(compiler, input_flags | LOAD_DATA, sugg_src2_r, src2, src2w)) {
FAIL_IF(compiler->error);
src2_r = sugg_src2_r;
}
else
src2_r = 0;
/* src1_r, src2_r and dst_r can be zero (=unprocessed).
All arguments are complex addressing modes, and it is a binary operator. */
if (src1_r == 0 && src2_r == 0 && dst_r == 0) {
if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, TMP_REG2, src2, src2w, src1, src1w));
FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));
}
else {
FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w));
FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, TMP_REG2, src2, src2w, dst, dstw));
}
src1_r = TMP_REG1;
src2_r = TMP_REG2;
}
else if (src1_r == 0 && src2_r == 0) {
FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w));
src1_r = TMP_REG1;
}
else if (src1_r == 0 && dst_r == 0) {
FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));
src1_r = TMP_REG1;
}
else if (src2_r == 0 && dst_r == 0) {
FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, sugg_src2_r, src2, src2w, dst, dstw));
src2_r = sugg_src2_r;
}
if (dst_r == 0)
dst_r = TMP_REG2;
if (src1_r == 0) {
FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, 0, 0));
src1_r = TMP_REG1;
}
if (src2_r == 0) {
FAIL_IF(getput_arg(compiler, input_flags | LOAD_DATA, sugg_src2_r, src2, src2w, 0, 0));
src2_r = sugg_src2_r;
}
FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));
if (flags & (FAST_DEST | SLOW_DEST)) {
if (flags & FAST_DEST)
FAIL_IF(getput_arg_fast(compiler, input_flags, dst_r, dst, dstw));
else
FAIL_IF(getput_arg(compiler, input_flags, dst_r, dst, dstw, 0, 0));
}
return SLJIT_SUCCESS;
}