Esempio n. 1
0
int
arch_fetch_retval(struct fetch_context *ctx, enum tof type,
		  struct process *proc, struct arg_type_info *info,
		  struct value *valuep)
{
	if (fetch_register_banks(proc, ctx) < 0)
		return -1;

	if (ctx->hardfp && !ctx->in_varargs) {
		int rc;
		if ((rc = consider_vfp(ctx, proc, info, valuep)) != 1)
			return rc;
	}

	size_t sz = type_sizeof(proc, info);
	assert(sz != (size_t)-1);

	switch (info->type) {
		unsigned char *data;

	case ARGTYPE_VOID:
		return 0;

	case ARGTYPE_FLOAT:
	case ARGTYPE_DOUBLE:
		if (ctx->hardfp && !ctx->in_varargs) {
			unsigned char *data = value_reserve(valuep, sz);
			if (data == NULL)
				return -1;
			memmove(data, &ctx->fpregs, sz);
			return 0;
		}
		goto pass_in_registers;

	case ARGTYPE_ARRAY:
	case ARGTYPE_STRUCT:
		if (sz > 4) {
			value_in_inferior(valuep, ctx->ret_struct);
			return 0;
		}
		/* Fall through.  */

	case ARGTYPE_CHAR:
	case ARGTYPE_SHORT:
	case ARGTYPE_USHORT:
	case ARGTYPE_INT:
	case ARGTYPE_UINT:
	case ARGTYPE_LONG:
	case ARGTYPE_ULONG:
	case ARGTYPE_POINTER:
	pass_in_registers:
		if ((data = value_reserve(valuep, sz)) == NULL)
			return -1;
		memmove(data, ctx->regs.uregs, sz);
		return 0;
	}
	assert(info->type != info->type);
	abort();
}
Esempio n. 2
0
static int
allocate_gpr_pair(struct fetch_context *ctx, struct Process *proc,
		  struct arg_type_info *info, struct value *valuep,
		  size_t sz)
{
	assert(!s390x(ctx));
	assert(sz <= 8);

	if (ctx->greg > 5) {
		ctx->greg = 7;
		return allocate_stack_slot(ctx, proc, info, valuep, sz);
	}

	if (value_reserve(valuep, sz) == NULL)
		return -1;

	unsigned char *ptr = value_get_raw_data(valuep);
	union {
		struct {
			uint32_t a;
			uint32_t b;
		};
		unsigned char buf[8];
	} u;
	u.a = ctx->regs.gprs[ctx->greg++];
	u.b = ctx->regs.gprs[ctx->greg++];
	memcpy(ptr, u.buf, sz);

	return 0;
}
Esempio n. 3
0
static int
allocate_fpr(struct fetch_context *ctx, struct Process *proc,
	     struct arg_type_info *info, struct value *valuep,
	     size_t sz)
{
	int pool = s390x(ctx) ? 6 : 2;

	if (ctx->freg > pool)
		return allocate_stack_slot(ctx, proc, info, valuep, sz);

	if (value_reserve(valuep, sz) == NULL)
		return -1;

	memcpy(value_get_raw_data(valuep),
	       &ctx->regs.fp_regs.fprs[ctx->freg], sz);
	ctx->freg += 2;

	return 0;
}
Esempio n. 4
0
/* 0 is success, 1 is failure, negative value is an error.  */
static int
pass_in_vfp(struct fetch_context *ctx, struct process *proc,
	    enum arg_type type, size_t count, struct value *valuep)
{
	assert(type == ARGTYPE_FLOAT || type == ARGTYPE_DOUBLE);
	unsigned max = type == ARGTYPE_DOUBLE ? NUM_VFP_REGS : 2 * NUM_VFP_REGS;
	if (count > max)
		return 1;

	size_t i;
	size_t j;
	for (i = 0; i < max; ++i) {
		for (j = i; j < i + count; ++j)
			if ((type == ARGTYPE_DOUBLE && ctx->alloc.d[j] != 0)
			    || (type == ARGTYPE_FLOAT && ctx->alloc.s[j] != 0))
				goto next;

		/* Found COUNT consecutive unallocated registers at I.  */
		const size_t sz = (type == ARGTYPE_FLOAT ? 4 : 8) * count;
		unsigned char *data = value_reserve(valuep, sz);
		if (data == NULL)
			return -1;

		for (j = i; j < i + count; ++j)
			if (type == ARGTYPE_DOUBLE)
				ctx->alloc.d[j] = -1;
			else
				ctx->alloc.s[j] = -1;

		if (type == ARGTYPE_DOUBLE)
			memcpy(data, ctx->fpregs.d + i, sz);
		else
			memcpy(data, ctx->fpregs.s + i, sz);

		return 0;

	next:
		continue;
	}
	return 1;
}
Esempio n. 5
0
int
arch_fetch_arg_next(struct fetch_context *ctx, enum tof type,
		    struct process *proc,
		    struct arg_type_info *info, struct value *valuep)
{
	const size_t sz = type_sizeof(proc, info);
	assert(sz != (size_t)-1);

	if (ctx->hardfp && !ctx->in_varargs) {
		int rc;
		if ((rc = consider_vfp(ctx, proc, info, valuep)) != 1)
			return rc;
	}

	/* IHI0042E_aapcs: If the argument requires double-word
	 * alignment (8-byte), the NCRN is rounded up to the next even
	 * register number.  */
	const size_t al = type_alignof(proc, info);
	assert(al != (size_t)-1);
	if (al == 8)
		ctx->ncrn = ((ctx->ncrn + 1) / 2) * 2;

	/* If the size in words of the argument is not more than r4
	 * minus NCRN, the argument is copied into core registers,
	 * starting at the NCRN.  */
	/* If the NCRN is less than r4 and the NSAA is equal to the
	 * SP, the argument is split between core registers and the
	 * stack.  */

	const size_t words = (sz + 3) / 4;
	if (ctx->ncrn < 4 && ctx->nsaa == ctx->sp) {
		unsigned char *data = value_reserve(valuep, words * 4);
		if (data == NULL)
			return -1;
		size_t i;
		for (i = 0; i < words && ctx->ncrn < 4; ++i) {
			memcpy(data, &ctx->regs.uregs[ctx->ncrn++], 4);
			data += 4;
		}
		const size_t rest = (words - i) * 4;
		if (rest > 0) {
			umovebytes(proc, ctx->nsaa, data, rest);
			ctx->nsaa += rest;
		}
		return 0;
	}

	assert(ctx->ncrn == 4);

	/* If the argument required double-word alignment (8-byte),
	 * then the NSAA is rounded up to the next double-word
	 * address.  */
	if (al == 8)
		/* XXX double cast.  */
		ctx->nsaa = (arch_addr_t)((((uintptr_t)ctx->nsaa + 7) / 8) * 8);
	else
		ctx->nsaa = (arch_addr_t)((((uintptr_t)ctx->nsaa + 3) / 4) * 4);

	value_in_inferior(valuep, ctx->nsaa);
	ctx->nsaa += sz;

	return 0;
}