Ejemplo n.º 1
0
static NODE *
moveargs(NODE *p, int *regp)
{
	NODE *r, **rp;
	int reg;

	if (p->n_op == CM) {
		p->n_left = moveargs(p->n_left, regp);
		r = p->n_right;
		rp = &p->n_right;
	} else {
		r = p;
		rp = &p;
	}

	reg = *regp;

	if (reg > R3 && r->n_op != STARG) {
		*rp = pusharg(r, regp);
	} else if (r->n_op == STARG) {
		*rp = movearg_struct(r, regp);
	} else if (DEUNSIGN(r->n_type) == LONGLONG) {
		*rp = movearg_64bit(r, regp);
	} else if (r->n_type == DOUBLE || r->n_type == LDOUBLE) {
		*rp = movearg_double(r, regp);
	} else if (r->n_type == FLOAT) {
		*rp = movearg_float(r, regp);
	} else {
		*rp = movearg_32bit(r, regp);
	}

	return straighten(p);
}
Ejemplo n.º 2
0
/*
 * Called with a function call with arguments as argument.
 * This is done early in buildtree() and only done once.
 */
NODE *
funcode(NODE *p)
{
	int regnum = A0;
	NODE *l, *r, *t, *q;
	int ty;

	l = p->n_left;
	r = p->n_right;

	/*
	 * if returning a structure, make the first argument
	 * a hidden pointer to return structure.
	 */
	ty = DECREF(l->n_type);
	if (ty == STRTY+FTN || ty == UNIONTY+FTN) {
		ty = DECREF(l->n_type) - FTN;
		q = tempnode(0, ty, l->n_df, l->n_ap);
		q = buildtree(ADDROF, q, NIL);
		if (r->n_op != CM) {
			p->n_right = block(CM, q, r, INCREF(ty),
			    l->n_df, l->n_ap);
		} else {
			for (t = r; t->n_left->n_op == CM; t = t->n_left)
				;
			t->n_left = block(CM, q, t->n_left, INCREF(ty),
			    l->n_df, l->n_ap);
		}
	}

	p->n_right = moveargs(p->n_right, &regnum);

	return p;
}
Ejemplo n.º 3
0
static NODE *
moveargs(NODE *p, int *regp)
{
        NODE *r, **rp;
	int lastreg;
	int reg;

        if (p->n_op == CM) {
                p->n_left = moveargs(p->n_left, regp);
                r = p->n_right;
		rp = &p->n_right;
        } else {
		r = p;
		rp = &p;
	}

 	lastreg = A0 + nargregs - 1;
        reg = *regp;

	if (reg > lastreg && r->n_op != STARG)
		*rp = block(FUNARG, r, NIL, r->n_type, r->n_df, r->n_ap);
	else if (r->n_op == STARG) {
		*rp = movearg_struct(r, p, regp);
	} else if (DEUNSIGN(r->n_type) == LONGLONG) {
		*rp = movearg_64bit(r, regp);
	} else if (r->n_type == DOUBLE || r->n_type == LDOUBLE) {
		/* XXX bounce in and out of temporary to change to longlong */
		NODE *t1 = tempnode(0, LONGLONG, 0, 0);
		int tmpnr = regno(t1);
		NODE *t2 = tempnode(tmpnr, r->n_type, r->n_df, r->n_ap);
		t1 =  movearg_64bit(t1, regp);
		r = block(ASSIGN, t2, r, r->n_type, r->n_df, r->n_ap);
		if (p->n_op == CM) {
			p->n_left = buildtree(CM, p->n_left, t1);
			p->n_right = r;
		} else {
			p = buildtree(CM, t1, r);
		}
	} else if (r->n_type == FLOAT) {
		/* XXX bounce in and out of temporary to change to int */
		NODE *t1 = tempnode(0, INT, 0, 0);
		int tmpnr = regno(t1);
		NODE *t2 = tempnode(tmpnr, r->n_type, r->n_df, r->n_ap);
		t1 =  movearg_32bit(t1, regp);
		r = block(ASSIGN, t2, r, r->n_type, r->n_df, r->n_ap);
		if (p->n_op == CM) {
			p->n_left = buildtree(CM, p->n_left, t1);
			p->n_right = r;
		} else {
			p = buildtree(CM, t1, r);
		}
	} else {
		*rp = movearg_32bit(r, regp);
	}

	return p;
}
Ejemplo n.º 4
0
/*
 * The first six 64-bit arguments are saved in the registers O0 to O5,
 * which become I0 to I5 after the "save" instruction moves the register
 * window. Arguments 7 and up must be saved on the stack to %sp+BIAS+176.
 *
 * For a pretty picture, see Figure 3-16 in the SPARC Compliance Def 2.4.
 */
static NODE *
moveargs(NODE *p, int *regp, int *stacksize)
{
	NODE *r, *q;

	if (p->n_op == CM) {
		p->n_left = moveargs(p->n_left, regp, stacksize);
		r = p->n_right;
	} else {
		r = p;
	}

	/* XXX more than six FP args can and should be passed in registers. */
	if (*regp > 5 && r->n_op != STARG) {
		/* We are storing the stack offset in n_rval. */
		r = block(FUNARG, r, NIL, r->n_type, r->n_df, r->n_ap);
		/* Make sure we are appropriately aligned. */
		*stacksize = ALIGN(*stacksize, (tlen(r) - 1));
		r->n_rval = *stacksize;
		*stacksize += tlen(r);
	} else if (r->n_op == STARG)
		cerror("op STARG in moveargs");
	else {
		q = block(REG, NIL, NIL, r->n_type, r->n_df, r->n_ap);

		/*
		 * The first six non-FP arguments go in the registers O0 - O5.
		 * Float arguments are stored in %fp1, %fp3, ..., %fp29, %fp31.
		 * Double arguments are stored in %fp0, %fp2, ..., %fp28, %fp30.
		 * A non-fp argument still increments register, eg.
		 *     test(int a, int b, float b)
		 * takes %o0, %o1, %fp5.
		 */
		if (q->n_type == FLOAT)
			q->n_rval = F0 + (*regp++ * 2) + 1;
		else if (q->n_type == DOUBLE)
			q->n_rval = D0 + *regp++;
		else if (q->n_type == LDOUBLE)
			cerror("long double support incomplete");
		else
			q->n_rval = O0 + (*regp)++;

		r = buildtree(ASSIGN, q, r);
	}

	if (p->n_op == CM) {
		p->n_right = r;
		return p;
	}

	return r;
}
Ejemplo n.º 5
0
NODE *
funcode(NODE *p)
{
	NODE *r, *l;
	int reg = 0, stacksize = 0;

	r = l = 0;

	p->n_right = moveargs(p->n_right, &reg, &stacksize);

	/*
	 * This is a particularly gross and inefficient way to handle
	 * argument overflows. First, we calculate how much stack space
	 * we need in moveargs(). Then we assign it by moving %sp, make
	 * the function call, and then move %sp back.
	 *
	 * What we should be doing is getting the maximum of all the needed
	 * stacksize values to the prologue and doing it all in the "save"
	 * instruction.
	 */
	if (stacksize != 0) {
		stacksize = V9STEP(stacksize); /* 16-bit alignment. */

		r = block(REG, NIL, NIL, INT, 0, 0);
		r->n_lval = 0;
		r->n_rval = SP;
		r = block(MINUS, r, bcon(stacksize), INT, 0, 0);

		l = block(REG, NIL, NIL, INT, 0, 0);
		l->n_lval = 0;
		l->n_rval = SP;
		r = buildtree(ASSIGN, l, r);

		p = buildtree(COMOP, r, p);

		r = block(REG, NIL, NIL, INT, 0, 0);
		r->n_lval = 0;
		r->n_rval = SP;
		r = block(PLUS, r, bcon(stacksize), INT, 0, 0);

		l = block(REG, NIL, NIL, INT, 0, 0);
		l->n_lval = 0;
		l->n_rval = SP;
		r = buildtree(ASSIGN, l, r);

		p = buildtree(COMOP, p, r);

	}
	return p;
}
Ejemplo n.º 6
0
/*
 * Called with a function call with arguments as argument.
 * This is done early in buildtree() and only done once.
 */
NODE *
funcode(NODE *p)
{
	int reg = R0;

	if (p->n_type == STRTY+FTN || p->n_type == UNIONTY+FTN) {
		p = retstruct(p);
		reg = R1;
	}

	p->n_right = moveargs(p->n_right, &reg);

	if (p->n_right == NULL)
		p->n_op += (UCALL - CALL);

	return p;
}