static sljit_s32 getput_arg()

in pcre/sljit/sljitNativeTILEGX_64.c [1340:1531]


static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
{
	sljit_s32 tmp_ar, base;

	SLJIT_ASSERT(arg & SLJIT_MEM);
	if (!(next_arg & SLJIT_MEM)) {
		next_arg = 0;
		next_argw = 0;
	}

	if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA))
		tmp_ar = reg_ar;
	else
		tmp_ar = TMP_REG1_mapped;

	base = arg & REG_MASK;

	if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
		argw &= 0x3;

		if ((flags & WRITE_BACK) && reg_ar == reg_map[base]) {
			SLJIT_ASSERT(!(flags & LOAD_DATA) && reg_map[TMP_REG1] != reg_ar);
			FAIL_IF(ADD(TMP_REG1_mapped, reg_ar, ZERO));
			reg_ar = TMP_REG1_mapped;
		}

		/* Using the cache. */
		if (argw == compiler->cache_argw) {
			if (!(flags & WRITE_BACK)) {
				if (arg == compiler->cache_arg) {
					if (flags & LOAD_DATA)
						return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, TMP_REG3_mapped);
					else
						return PB2(data_transfer_insts[flags & MEM_MASK], TMP_REG3_mapped, reg_ar);
				}

				if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) {
					if (arg == next_arg && argw == (next_argw & 0x3)) {
						compiler->cache_arg = arg;
						compiler->cache_argw = argw;
						FAIL_IF(ADD(TMP_REG3_mapped, reg_map[base], TMP_REG3_mapped));
						if (flags & LOAD_DATA)
							return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, TMP_REG3_mapped);
						else
							return PB2(data_transfer_insts[flags & MEM_MASK], TMP_REG3_mapped, reg_ar);
					}

					FAIL_IF(ADD(tmp_ar, reg_map[base], TMP_REG3_mapped));
					if (flags & LOAD_DATA)
						return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, tmp_ar);
					else
						return PB2(data_transfer_insts[flags & MEM_MASK], tmp_ar, reg_ar);
				}
			} else {
				if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) {
					FAIL_IF(ADD(reg_map[base], reg_map[base], TMP_REG3_mapped));
					if (flags & LOAD_DATA)
						return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, reg_map[base]);
					else
						return PB2(data_transfer_insts[flags & MEM_MASK], reg_map[base], reg_ar);
				}
			}
		}

		if (SLJIT_UNLIKELY(argw)) {
			compiler->cache_arg = SLJIT_MEM | (arg & OFFS_REG_MASK);
			compiler->cache_argw = argw;
			FAIL_IF(SHLI(TMP_REG3_mapped, reg_map[OFFS_REG(arg)], argw));
		}

		if (!(flags & WRITE_BACK)) {
			if (arg == next_arg && argw == (next_argw & 0x3)) {
				compiler->cache_arg = arg;
				compiler->cache_argw = argw;
				FAIL_IF(ADD(TMP_REG3_mapped, reg_map[base], reg_map[!argw ? OFFS_REG(arg) : TMP_REG3]));
				tmp_ar = TMP_REG3_mapped;
			} else
				FAIL_IF(ADD(tmp_ar, reg_map[base], reg_map[!argw ? OFFS_REG(arg) : TMP_REG3]));

			if (flags & LOAD_DATA)
				return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, tmp_ar);
			else
				return PB2(data_transfer_insts[flags & MEM_MASK], tmp_ar, reg_ar);
		}

		FAIL_IF(ADD(reg_map[base], reg_map[base], reg_map[!argw ? OFFS_REG(arg) : TMP_REG3]));

		if (flags & LOAD_DATA)
			return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, reg_map[base]);
		else
			return PB2(data_transfer_insts[flags & MEM_MASK], reg_map[base], reg_ar);
	}

	if (SLJIT_UNLIKELY(flags & WRITE_BACK) && base) {
		/* Update only applies if a base register exists. */
		if (reg_ar == reg_map[base]) {
			SLJIT_ASSERT(!(flags & LOAD_DATA) && TMP_REG1_mapped != reg_ar);
			if (argw <= SIMM_16BIT_MAX && argw >= SIMM_16BIT_MIN) {
				FAIL_IF(ADDLI(ADDR_TMP_mapped, reg_map[base], argw));
				if (flags & LOAD_DATA)
					FAIL_IF(PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, ADDR_TMP_mapped));
				else
					FAIL_IF(PB2(data_transfer_insts[flags & MEM_MASK], ADDR_TMP_mapped, reg_ar));

				if (argw)
					return ADDLI(reg_map[base], reg_map[base], argw);

				return SLJIT_SUCCESS;
			}

			FAIL_IF(ADD(TMP_REG1_mapped, reg_ar, ZERO));
			reg_ar = TMP_REG1_mapped;
		}

		if (argw <= SIMM_16BIT_MAX && argw >= SIMM_16BIT_MIN) {
			if (argw)
				FAIL_IF(ADDLI(reg_map[base], reg_map[base], argw));
		} else {
			if (compiler->cache_arg == SLJIT_MEM
					&& argw - compiler->cache_argw <= SIMM_16BIT_MAX
					&& argw - compiler->cache_argw >= SIMM_16BIT_MIN) {
				if (argw != compiler->cache_argw) {
					FAIL_IF(ADD(TMP_REG3_mapped, TMP_REG3_mapped, argw - compiler->cache_argw));
					compiler->cache_argw = argw;
				}

				FAIL_IF(ADD(reg_map[base], reg_map[base], TMP_REG3_mapped));
			} else {
				compiler->cache_arg = SLJIT_MEM;
				compiler->cache_argw = argw;
				FAIL_IF(load_immediate(compiler, TMP_REG3_mapped, argw));
				FAIL_IF(ADD(reg_map[base], reg_map[base], TMP_REG3_mapped));
			}
		}

		if (flags & LOAD_DATA)
			return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, reg_map[base]);
		else
			return PB2(data_transfer_insts[flags & MEM_MASK], reg_map[base], reg_ar);
	}

	if (compiler->cache_arg == arg
			&& argw - compiler->cache_argw <= SIMM_16BIT_MAX
			&& argw - compiler->cache_argw >= SIMM_16BIT_MIN) {
		if (argw != compiler->cache_argw) {
			FAIL_IF(ADDLI(TMP_REG3_mapped, TMP_REG3_mapped, argw - compiler->cache_argw));
			compiler->cache_argw = argw;
		}

		if (flags & LOAD_DATA)
			return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, TMP_REG3_mapped);
		else
			return PB2(data_transfer_insts[flags & MEM_MASK], TMP_REG3_mapped, reg_ar);
	}

	if (compiler->cache_arg == SLJIT_MEM
			&& argw - compiler->cache_argw <= SIMM_16BIT_MAX
			&& argw - compiler->cache_argw >= SIMM_16BIT_MIN) {
		if (argw != compiler->cache_argw)
			FAIL_IF(ADDLI(TMP_REG3_mapped, TMP_REG3_mapped, argw - compiler->cache_argw));
	} else {
		compiler->cache_arg = SLJIT_MEM;
		FAIL_IF(load_immediate(compiler, TMP_REG3_mapped, argw));
	}

	compiler->cache_argw = argw;

	if (!base) {
		if (flags & LOAD_DATA)
			return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, TMP_REG3_mapped);
		else
			return PB2(data_transfer_insts[flags & MEM_MASK], TMP_REG3_mapped, reg_ar);
	}

	if (arg == next_arg
			&& next_argw - argw <= SIMM_16BIT_MAX
			&& next_argw - argw >= SIMM_16BIT_MIN) {
		compiler->cache_arg = arg;
		FAIL_IF(ADD(TMP_REG3_mapped, TMP_REG3_mapped, reg_map[base]));
		if (flags & LOAD_DATA)
			return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, TMP_REG3_mapped);
		else
			return PB2(data_transfer_insts[flags & MEM_MASK], TMP_REG3_mapped, reg_ar);
	}

	FAIL_IF(ADD(tmp_ar, TMP_REG3_mapped, reg_map[base]));

	if (flags & LOAD_DATA)
		return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, tmp_ar);
	else
		return PB2(data_transfer_insts[flags & MEM_MASK], tmp_ar, reg_ar);
}