in pcre/sljit/sljitNativeARM_32.c [1459:1584]
static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 inp_flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
{
sljit_s32 tmp_r;
sljit_sw max_delta;
sljit_sw sign;
sljit_uw imm;
if (arg & SLJIT_IMM) {
SLJIT_ASSERT(inp_flags & LOAD_DATA);
return load_immediate(compiler, reg, argw);
}
SLJIT_ASSERT(arg & SLJIT_MEM);
tmp_r = (inp_flags & LOAD_DATA) ? reg : TMP_REG3;
max_delta = IS_TYPE1_TRANSFER(inp_flags) ? 0xfff : 0xff;
if ((arg & REG_MASK) == SLJIT_UNUSED) {
/* Write back is not used. */
imm = (sljit_uw)(argw - compiler->cache_argw);
if ((compiler->cache_arg & SLJIT_IMM) && (imm <= (sljit_uw)max_delta || imm >= (sljit_uw)-max_delta)) {
if (imm <= (sljit_uw)max_delta) {
sign = 1;
argw = argw - compiler->cache_argw;
}
else {
sign = 0;
argw = compiler->cache_argw - argw;
}
GETPUT_ARG_DATA_TRANSFER(sign, 0, reg, TMP_REG3, argw);
return SLJIT_SUCCESS;
}
/* With write back, we can create some sophisticated loads, but
it is hard to decide whether we should convert downward (0s) or upward (1s). */
imm = (sljit_uw)(argw - next_argw);
if ((next_arg & SLJIT_MEM) && (imm <= (sljit_uw)max_delta || imm >= (sljit_uw)-max_delta)) {
SLJIT_ASSERT(inp_flags & LOAD_DATA);
compiler->cache_arg = SLJIT_IMM;
compiler->cache_argw = argw;
tmp_r = TMP_REG3;
}
FAIL_IF(load_immediate(compiler, tmp_r, argw));
GETPUT_ARG_DATA_TRANSFER(1, 0, reg, tmp_r, 0);
return SLJIT_SUCCESS;
}
if (arg & OFFS_REG_MASK) {
SLJIT_ASSERT((argw & 0x3) && !(max_delta & 0xf00));
if (inp_flags & WRITE_BACK)
tmp_r = arg & REG_MASK;
FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, tmp_r, arg & REG_MASK, RM(OFFS_REG(arg)) | ((argw & 0x3) << 7))));
return push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 1, 0, reg, tmp_r, TYPE2_TRANSFER_IMM(0)));
}
imm = (sljit_uw)(argw - compiler->cache_argw);
if (compiler->cache_arg == arg && imm <= (sljit_uw)max_delta) {
SLJIT_ASSERT(!(inp_flags & WRITE_BACK));
GETPUT_ARG_DATA_TRANSFER(1, 0, reg, TMP_REG3, imm);
return SLJIT_SUCCESS;
}
if (compiler->cache_arg == arg && imm >= (sljit_uw)-max_delta) {
SLJIT_ASSERT(!(inp_flags & WRITE_BACK));
imm = (sljit_uw)-(sljit_sw)imm;
GETPUT_ARG_DATA_TRANSFER(0, 0, reg, TMP_REG3, imm);
return SLJIT_SUCCESS;
}
imm = get_imm(argw & ~max_delta);
if (imm) {
TEST_WRITE_BACK();
FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, tmp_r, arg & REG_MASK, imm)));
GETPUT_ARG_DATA_TRANSFER(1, inp_flags & WRITE_BACK, reg, tmp_r, argw & max_delta);
return SLJIT_SUCCESS;
}
imm = get_imm(-argw & ~max_delta);
if (imm) {
argw = -argw;
TEST_WRITE_BACK();
FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(SUB_DP, 0, tmp_r, arg & REG_MASK, imm)));
GETPUT_ARG_DATA_TRANSFER(0, inp_flags & WRITE_BACK, reg, tmp_r, argw & max_delta);
return SLJIT_SUCCESS;
}
if ((compiler->cache_arg & SLJIT_IMM) && compiler->cache_argw == argw) {
TEST_WRITE_BACK();
return push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, RM(TMP_REG3) | (max_delta & 0xf00 ? SRC2_IMM : 0)));
}
if (argw == next_argw && (next_arg & SLJIT_MEM)) {
SLJIT_ASSERT(inp_flags & LOAD_DATA);
FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
compiler->cache_arg = SLJIT_IMM;
compiler->cache_argw = argw;
TEST_WRITE_BACK();
return push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, RM(TMP_REG3) | (max_delta & 0xf00 ? SRC2_IMM : 0)));
}
imm = (sljit_uw)(argw - next_argw);
if (arg == next_arg && !(inp_flags & WRITE_BACK) && (imm <= (sljit_uw)max_delta || imm >= (sljit_uw)-max_delta)) {
SLJIT_ASSERT(inp_flags & LOAD_DATA);
FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG3, TMP_REG3, reg_map[arg & REG_MASK])));
compiler->cache_arg = arg;
compiler->cache_argw = argw;
GETPUT_ARG_DATA_TRANSFER(1, 0, reg, TMP_REG3, 0);
return SLJIT_SUCCESS;
}
if ((arg & REG_MASK) == tmp_r) {
compiler->cache_arg = SLJIT_IMM;
compiler->cache_argw = argw;
tmp_r = TMP_REG3;
}
FAIL_IF(load_immediate(compiler, tmp_r, argw));
return push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, reg_map[tmp_r] | (max_delta & 0xf00 ? SRC2_IMM : 0)));
}