in pcre/sljit/sljitNativeARM_64.c [909:1041]
static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg,
sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
{
sljit_u32 shift = MEM_SIZE_SHIFT(flags);
sljit_s32 tmp_r, other_r;
sljit_sw diff;
SLJIT_ASSERT(arg & SLJIT_MEM);
if (!(next_arg & SLJIT_MEM)) {
next_arg = 0;
next_argw = 0;
}
tmp_r = (flags & STORE) ? TMP_REG3 : reg;
if (SLJIT_UNLIKELY((flags & UPDATE) && (arg & REG_MASK))) {
/* Update only applies if a base register exists. */
other_r = OFFS_REG(arg);
if (!other_r) {
other_r = arg & REG_MASK;
if (other_r != reg && argw >= 0 && argw <= 0xffffff) {
if ((argw & 0xfff) != 0)
FAIL_IF(push_inst(compiler, ADDI | RD(other_r) | RN(other_r) | ((argw & 0xfff) << 10)));
if (argw >> 12)
FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(other_r) | RN(other_r) | ((argw >> 12) << 10)));
return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) | RT(reg) | RN(other_r));
}
else if (other_r != reg && argw < 0 && argw >= -0xffffff) {
argw = -argw;
if ((argw & 0xfff) != 0)
FAIL_IF(push_inst(compiler, SUBI | RD(other_r) | RN(other_r) | ((argw & 0xfff) << 10)));
if (argw >> 12)
FAIL_IF(push_inst(compiler, SUBI | (1 << 22) | RD(other_r) | RN(other_r) | ((argw >> 12) << 10)));
return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) | RT(reg) | RN(other_r));
}
if (compiler->cache_arg == SLJIT_MEM) {
if (argw == compiler->cache_argw) {
other_r = TMP_REG3;
argw = 0;
}
else if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, argw - compiler->cache_argw) != SLJIT_ERR_UNSUPPORTED) {
FAIL_IF(compiler->error);
compiler->cache_argw = argw;
other_r = TMP_REG3;
argw = 0;
}
}
if (argw) {
FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
compiler->cache_arg = SLJIT_MEM;
compiler->cache_argw = argw;
other_r = TMP_REG3;
argw = 0;
}
}
/* No caching here. */
arg &= REG_MASK;
argw &= 0x3;
if (!argw || argw == shift) {
FAIL_IF(push_inst(compiler, sljit_mem_reg[flags & 0x3] | (shift << 30) | RT(reg) | RN(arg) | RM(other_r) | (argw ? (1 << 12) : 0)));
return push_inst(compiler, ADD | RD(arg) | RN(arg) | RM(other_r) | (argw << 10));
}
if (arg != reg) {
FAIL_IF(push_inst(compiler, ADD | RD(arg) | RN(arg) | RM(other_r) | (argw << 10)));
return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) | RT(reg) | RN(arg));
}
FAIL_IF(push_inst(compiler, ADD | RD(TMP_LR) | RN(arg) | RM(other_r) | (argw << 10)));
FAIL_IF(push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) | RT(reg) | RN(TMP_LR)));
return push_inst(compiler, ORR | RD(arg) | RN(TMP_ZERO) | RM(TMP_LR));
}
if (arg & OFFS_REG_MASK) {
other_r = OFFS_REG(arg);
arg &= REG_MASK;
FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RN(arg) | RM(other_r) | ((argw & 0x3) << 10)));
return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) | RT(reg) | RN(tmp_r));
}
if (compiler->cache_arg == arg) {
diff = argw - compiler->cache_argw;
if (diff <= 255 && diff >= -256)
return push_inst(compiler, sljit_mem_simm[flags & 0x3] | (shift << 30)
| RT(reg) | RN(TMP_REG3) | ((diff & 0x1ff) << 12));
if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, diff) != SLJIT_ERR_UNSUPPORTED) {
FAIL_IF(compiler->error);
return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) | RT(reg) | RN(arg));
}
}
if (argw >= 0 && argw <= 0xffffff && (argw & ((1 << shift) - 1)) == 0) {
FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(tmp_r) | RN(arg & REG_MASK) | ((argw >> 12) << 10)));
return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30)
| RT(reg) | RN(tmp_r) | ((argw & 0xfff) << (10 - shift)));
}
diff = argw - next_argw;
next_arg = (arg & REG_MASK) && (arg == next_arg) && diff <= 0xfff && diff >= -0xfff && diff != 0;
arg &= REG_MASK;
if (arg && compiler->cache_arg == SLJIT_MEM) {
if (compiler->cache_argw == argw)
return push_inst(compiler, sljit_mem_reg[flags & 0x3] | (shift << 30) | RT(reg) | RN(arg) | RM(TMP_REG3));
if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, argw - compiler->cache_argw) != SLJIT_ERR_UNSUPPORTED) {
FAIL_IF(compiler->error);
compiler->cache_argw = argw;
return push_inst(compiler, sljit_mem_reg[flags & 0x3] | (shift << 30) | RT(reg) | RN(arg) | RM(TMP_REG3));
}
}
compiler->cache_argw = argw;
if (next_arg && emit_set_delta(compiler, TMP_REG3, arg, argw) != SLJIT_ERR_UNSUPPORTED) {
FAIL_IF(compiler->error);
compiler->cache_arg = SLJIT_MEM | arg;
arg = 0;
}
else {
FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
compiler->cache_arg = SLJIT_MEM;
if (next_arg) {
FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG3) | RN(TMP_REG3) | RM(arg)));
compiler->cache_arg = SLJIT_MEM | arg;
arg = 0;
}
}
if (arg)
return push_inst(compiler, sljit_mem_reg[flags & 0x3] | (shift << 30) | RT(reg) | RN(arg) | RM(TMP_REG3));
return push_inst(compiler, sljit_mem_imm[flags & 0x3] | (shift << 30) | RT(reg) | RN(TMP_REG3));
}