Esempio n. 1
0
static NODE *
builtin_stdarg_start(const struct bitable *bt, NODE *a)
{
    NODE *p, *q;
    int sz;

    /* must first deal with argument size; use int size */
    p = a->n_right;
    if (p->n_type < INT) {
        sz = (int)(SZINT/tsize(p->n_type, p->n_df, p->n_ap));
    } else
        sz = 1;

    /* do the real job */
    p = buildtree(ADDROF, p, NIL); /* address of last arg */
#ifdef BACKAUTO
    p = optim(buildtree(PLUS, p, bcon(sz))); /* add one to it (next arg) */
#else
    p = optim(buildtree(MINUS, p, bcon(sz))); /* add one to it (next arg) */
#endif
    q = block(NAME, NIL, NIL, PTR+VOID, 0, 0); /* create cast node */
    q = buildtree(CAST, q, p); /* cast to void * (for assignment) */
    p = q->n_right;
    nfree(q->n_left);
    nfree(q);
    p = buildtree(ASSIGN, a->n_left, p); /* assign to ap */
    nfree(a);
    return p;
}
Esempio n. 2
0
File: code.c Progetto: paploo/pcc
/*
 * code for the end of a function
 * deals with struct return here
 */
void
efcode(void)
{
	NODE *p, *q;
	int sz;

	if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN)
		return;
	/* address of return struct is in %ret0 */
	/* create a call to memcpy() */
	/* will get the result in %ret0 */
	p = block(REG, NIL, NIL, CHAR+PTR, 0, 0);
	p->n_rval = RET0;
	q = block(OREG, NIL, NIL, CHAR+PTR, 0, 0);
	q->n_rval = FP;
	q->n_lval = 8; /* return buffer offset */
	p = block(CM, q, p, INT, 0, 0);
	sz = (tsize(STRTY, cftnsp->sdf, cftnsp->ssue)+SZCHAR-1)/SZCHAR;
	p = block(CM, p, bcon(sz), INT, 0, 0);
	p->n_right->n_name = "";
	p = block(CALL, bcon(0), p, CHAR+PTR, 0, 0);
	p->n_left->n_name = "memcpy";
	p = clocal(p);
	send_passt(IP_NODE, p);
}
Esempio n. 3
0
NODE *	
builtin_return_address(const struct bitable *bt, NODE *a)
{	
	int nframes;
	NODE *f; 
	
	if (a->n_op != ICON)
		goto bad;

	nframes = (int)a->n_lval;
  
	tfree(a);	
			
	f = block(REG, NIL, NIL, PTR+VOID, 0, 0);
	regno(f) = FPREG;
 
	while (nframes--)
		f = block(UMUL, f, NIL, PTR+VOID, 0, 0);
				    
	f = block(PLUS, f, bcon(2), INCREF(PTR+VOID), 0, 0);
	f = buildtree(UMUL, f, NIL);	
   
	return f;
bad:						
	uerror("bad argument to __builtin_return_address");
	return bcon(0);
}
Esempio n. 4
0
/*
 * va_start(ap, last) implementation.
 *
 * f is the NAME node for this builtin function.
 * a is the argument list containing:
 *	   CM
 *	ap   last
 *
 * It turns out that this is easy on MIPS.  Just write the
 * argument registers to the stack in va_arg_start() and
 * use the traditional method of walking the stackframe.
 */
NODE *
mips_builtin_stdarg_start(NODE *f, NODE *a, TWORD t)
{
	NODE *p, *q;
	int sz = 1;

	/* check num args and type */
	if (a == NULL || a->n_op != CM || a->n_left->n_op == CM ||
	    !ISPTR(a->n_left->n_type))
		goto bad;

	/* must first deal with argument size; use int size */
	p = a->n_right;
	if (p->n_type < INT) {
		/* round up to word */
		sz = SZINT / tsize(p->n_type, p->n_df, p->n_ap);
	}

	p = buildtree(ADDROF, p, NIL);	/* address of last arg */
	p = optim(buildtree(PLUS, p, bcon(sz)));
	q = block(NAME, NIL, NIL, PTR+VOID, 0, 0);
	q = buildtree(CAST, q, p);
	p = q->n_right;
	nfree(q->n_left);
	nfree(q);
	p = buildtree(ASSIGN, a->n_left, p);
	tfree(f);
	nfree(a);

	return p;

bad:
	uerror("bad argument to __builtin_stdarg_start");
	return bcon(0);
}
Esempio n. 5
0
File: code.c Progetto: Sciumo/pcc
NODE *
builtin_return_address(const struct bitable *bt, NODE *a)
{
	NODE *f;

	if (a->n_op != ICON)
		goto bad;

	if (a->n_lval != 0)
		werror("unsupported argument");

	tfree(a);

	f = block(REG, NIL, NIL, INCREF(PTR+CHAR), 0, 0);
	regno(f) = FPREG;
	f = block(UMUL,
		block(PLUS, f,
		    bcon(16), INCREF(PTR+CHAR), 0, 0), NIL, PTR+CHAR, 0, 0);
	f = makety(f, PTR+VOID, 0, 0, 0);

	return f;
bad:
	uerror("bad argument to __builtin_return_address");
	return bcon(0);
}
Esempio n. 6
0
File: code.c Progetto: Sciumo/pcc
NODE *
builtin_frame_address(const struct bitable *bt, NODE *a)
{
	int nframes;
	NODE *f;

	if (a->n_op != ICON)
		goto bad;

	nframes = a->n_lval;

	tfree(a);

	f = block(REG, NIL, NIL, PTR+CHAR, 0, 0);
	regno(f) = FPREG;

	while (nframes--) {
		f = block(UMUL,
			block(PLUS, f,
			    bcon(12), INCREF(PTR+CHAR), 0, 0),
				NIL, PTR+CHAR, 0, 0);
		f = makety(f, PTR+CHAR, 0, 0, 0);
	}

	return f;
bad:
	uerror("bad argument to __builtin_frame_address");
	return bcon(0);
}
Esempio n. 7
0
/* called by moveargs() */
static NODE *
pusharg(NODE *p, int *regp)
{
	NODE *q;
	int sz;

	/* convert to register size, if smaller */
	sz = tsize(p->n_type, p->n_df, p->n_ap);
	if (sz < SZINT)
		p = block(SCONV, p, NIL, INT, 0, 0);

	q = block(REG, NIL, NIL, INT, 0, 0);
	regno(q) = SP;

	if (szty(p->n_type) == 1) {
		++(*regp);
		q = block(MINUSEQ, q, bcon(4), INT, 0, 0);
	} else {
		(*regp) += 2;
		q = block(MINUSEQ, q, bcon(8), INT, 0, 0);
	}

	q = block(UMUL, q, NIL, p->n_type, p->n_df, p->n_ap);

	return buildtree(ASSIGN, q, p);
}
Esempio n. 8
0
/*
 * Allocate off bits on the stack.  p is a tree that when evaluated
 * is the multiply count for off, t is a storeable node where to write
 * the allocated address.
 */
void
spalloc(NODE *t, NODE *p, OFFSZ off)
{
	NODE *sp;

	p = buildtree(MUL, p, bcon(off/SZCHAR));
	p = buildtree(PLUS, p, bcon(30));
	p = buildtree(AND, p, xbcon(-16, NULL, UNSIGNED));
	p = cast(p, UNSIGNED, 0);

	/* sub the size from sp */
	sp = block(REG, NIL, NIL, UNSIGNED+PTR, 0, 0);
	slval(sp, 0);
	sp->n_rval = STKREG;
	p = (buildtree(MINUSEQ, sp, p));
	ecomp(p);

	/* save the address of sp */
	sp = block(REG, NIL, NIL, PTR+UNSIGNED, t->n_df, t->n_ap);
	slval(sp, 0);
	sp->n_rval = STKREG;
	t->n_type = sp->n_type;
	p = (buildtree(ASSIGN, t, sp)); /* Emit! */
	ecomp(p);

}
Esempio n. 9
0
static NODE *
builtin_va_arg(const struct bitable *bt, NODE *a)
{
    NODE *p, *q, *r, *rv;
    int sz, nodnum;

    /* create a copy to a temp node of current ap */
    p = ccopy(a->n_left);
    q = tempnode(0, p->n_type, p->n_df, p->n_ap);
    nodnum = regno(q);
    rv = buildtree(ASSIGN, q, p);

    r = a->n_right;
    sz = (int)tsize(r->n_type, r->n_df, r->n_ap)/SZCHAR;
    /* add one to ap */
#ifdef BACKAUTO
    rv = buildtree(COMOP, rv , buildtree(PLUSEQ, a->n_left, bcon(sz)));
#else
#error fix wrong eval order in builtin_va_arg
    ecomp(buildtree(MINUSEQ, a->n_left, bcon(sz)));
#endif

    nfree(a->n_right);
    nfree(a);
    r = tempnode(nodnum, INCREF(r->n_type), r->n_df, r->n_ap);
    return buildtree(COMOP, rv, buildtree(UMUL, r, NIL));

}
Esempio n. 10
0
static NODE *
builtin_bswap16(const struct bitable *bt, NODE *a)
{
    NODE *f, *t1, *t2;

    t1 = buildtree(LS, buildtree(AND, ccopy(a), bcon(255)), bcon(8));
    t2 = buildtree(AND, buildtree(RS, a, bcon(8)), bcon(255));
    f = buildtree(OR, t1, t2);
    return f;
}
Esempio n. 11
0
NODE *
mips_builtin_va_arg(NODE *f, NODE *a, TWORD t)
{
	NODE *p, *q, *r;
	int sz, tmpnr;

	/* check num args and type */
	if (a == NULL || a->n_op != CM || a->n_left->n_op == CM ||
	    !ISPTR(a->n_left->n_type) || a->n_right->n_op != TYPE)
		goto bad;

	r = a->n_right;

	/* get type size */
	sz = tsize(r->n_type, r->n_df, r->n_ap) / SZCHAR;
	if (sz < SZINT/SZCHAR) {
		werror("%s%s promoted to int when passed through ...",
			r->n_type & 1 ? "unsigned " : "",
			DEUNSIGN(r->n_type) == SHORT ? "short" : "char");
		sz = SZINT/SZCHAR;
	}

	/* alignment */
	p = tcopy(a->n_left);
	if (sz > SZINT/SZCHAR && r->n_type != UNIONTY && r->n_type != STRTY) {
		p = buildtree(PLUS, p, bcon(7));
		p = block(AND, p, bcon(-8), p->n_type, p->n_df, p->n_ap);
	}

	/* create a copy to a temp node */
	q = tempnode(0, p->n_type, p->n_df, p->n_ap);
	tmpnr = regno(q);
	p = buildtree(ASSIGN, q, p);

	q = tempnode(tmpnr, p->n_type, p->n_df,p->n_ap);
	q = buildtree(PLUS, q, bcon(sz));
	q = buildtree(ASSIGN, a->n_left, q);

	q = buildtree(COMOP, p, q);

	nfree(a->n_right);
	nfree(a);
	nfree(f); 

	p = tempnode(tmpnr, INCREF(r->n_type), r->n_df, r->n_ap);
	p = buildtree(UMUL, p, NIL);
	p = buildtree(COMOP, q, p);

	return p;

bad:
	uerror("bad argument to __builtin_va_arg");
	return bcon(0);
}
Esempio n. 12
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;
}
Esempio n. 13
0
static NODE *
builtin_va_end(NODE *f, NODE *a, TWORD rt)
{
	tfree(f);
	tfree(a);
	return bcon(0); /* nothing */
}
Esempio n. 14
0
/* setup struct parameter
 * push the registers out to memory
 * used by bfcode() */
static void
param_struct(struct symtab *sym, int *regp)
{
	int reg = *regp;
	NODE *p, *q;
	int navail;
	int sz;
	int off;
	int num;
	int i;

	navail = nargregs - (reg - A0);
	sz = tsize(sym->stype, sym->sdf, sym->sap) / SZINT;
	off = ARGINIT/SZINT + (reg - A0);
	num = sz > navail ? navail : sz;
	for (i = 0; i < num; i++) {
		q = block(REG, NIL, NIL, INT, 0, 0);
		q->n_rval = reg++;
		p = block(REG, NIL, NIL, INT, 0, 0);
		p->n_rval = FP;
		p = block(PLUS, p, bcon(4*off++), INT, 0, 0);
		p = block(UMUL, p, NIL, INT, 0, 0);
		p = buildtree(ASSIGN, p, q);
		ecomp(p);
	}

	*regp = reg;
}
Esempio n. 15
0
static NODE *
builtin_prefetch(NODE *f, NODE *a, TWORD rt)
{
	tfree(f);
	tfree(a);
	return bcon(0);
}
Esempio n. 16
0
/* setup struct parameter
 * push the registers out to memory
 * used by bfcode() */
static void
param_struct(struct symtab *sym, int *argofsp)
{
	int argofs = *argofsp;
	NODE *p, *q;
	int navail;
	int sz;
	int off;
	int num;
	int i;

	navail = NARGREGS - argofs;
	sz = tsize(sym->stype, sym->sdf, sym->sap) / SZINT;
	off = ARGINIT/SZINT + argofs;
	num = sz > navail ? navail : sz;
	for (i = 0; i < num; i++) {
		q = block(REG, NIL, NIL, INT, 0, 0);
		regno(q) = R0 + argofs++;
		p = block(REG, NIL, NIL, INT, 0, 0);
		regno(p) = SP;
		p = block(PLUS, p, bcon(4*off++), INT, 0, 0);
		p = block(UMUL, p, NIL, INT, 0, 0);
		p = buildtree(ASSIGN, p, q);
		ecomp(p);
	}

	*argofsp = argofs;
}
Esempio n. 17
0
/*
 * code for the end of a function
 * deals with struct return here
 */
void
efcode(void)
{
	NODE *p, *q;
//	int sz;

#if 0
	/* restore ac3 */
	p = block(REG, 0, 0, INT, 0, 0);
	regno(p) = 3;
	q = tempnode(ac3temp, INT, 0, 0);
	ecomp(buildtree(ASSIGN, p, q));
#endif


	if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN)
		return;
cerror("efcode");
	/* address of return struct is in eax */
	/* create a call to memcpy() */
	/* will get the result in eax */
	p = block(REG, NIL, NIL, CHAR+PTR, 0, 0);
//	p->n_rval = EAX;
	q = block(OREG, NIL, NIL, CHAR+PTR, 0, 0);
//	q->n_rval = EBP;
	q->n_lval = 8; /* return buffer offset */
	p = block(CM, q, p, INT, 0, 0);
//	sz = (tsize(STRTY, cftnsp->sdf, cftnsp->ssue)+SZCHAR-1)/SZCHAR;
//	p = block(CM, p, bcon(sz), INT, 0, 0);
	p->n_right->n_name = "";
	p = block(CALL, bcon(0), p, CHAR+PTR, 0, 0);
	p->n_left->n_name = "memcpy";
	p = clocal(p);
	send_passt(IP_NODE, p);
}
Esempio n. 18
0
NODE *
amd64_builtin_va_end(NODE *f, NODE *a, TWORD t)
{
	tfree(f);
	tfree(a);
	return bcon(0); /* nothing */
}
Esempio n. 19
0
/*
 * The "initial exec" tls model.
 */
static NODE *
tlsinitialexec(NODE *p)
{
	NODE *q, *r, *s;
	char *s1, *s2;

	/*
	 * movq %fs:0,%rax
	 * addq x@GOTTPOFF(%rip),%rax
	 */

	q = bcon(0);
	q->n_type = STRTY;

	s = ccopy(r = tempnode(0, INCREF(p->n_type), p->n_df, p->n_ap));
	r = mkx("=r", r);
	r = block(XASM, r, q, INT, 0, 0);

	s1 = "movq %%fs:0,%0\n\taddq ";
	s2 = "@GOTTPOFF(%%rip),%0";
	if (p->n_sp->soname == NULL)
		p->n_sp->soname = p->n_sp->sname;
	r->n_name = mk3str(s1, p->n_sp->soname, s2);

	r = block(COMOP, r, s, INCREF(p->n_type), p->n_df, p->n_ap);
	r = buildtree(UMUL, r, NIL);
	tfree(p);
	return r;
}
Esempio n. 20
0
NODE *
mips_builtin_va_end(NODE *f, NODE *a, TWORD t)
{
	tfree(f);
	tfree(a);
	return bcon(0);
}
Esempio n. 21
0
/*
 * The "initial exec" tls model.
 */
static NODE *
tlsinitialexec(NODE *p)
{
	NODE *q, *r, *s;
	char *s1, *s2;

	/*
	 * movq %fs:0,%rax
	 * addq x@GOTTPOFF(%rip),%rax
	 */

	q = bcon(0);
	q->n_type = STRTY;

	s = ccopy(r = tempnode(0, INCREF(p->n_type), p->n_df, p->n_ap));
	r = mkx("=r", r);
	r = block(XASM, r, q, INT, 0, 0);

	s1 = "movq %%fs:0,%0\n\taddq ";
	s2 = "@GOTTPOFF(%%rip),%0";
	if (attr_find(p->n_sp->sap, ATTR_SONAME) == NULL) {
		p->n_sp->sap = attr_add(p->n_sp->sap, attr_new(ATTR_SONAME, 1));
		p->n_sp->sap->sarg(0) = p->n_sp->sname;
	}
	r->n_name = mk3str(s1,
	    attr_find(p->n_sp->sap, ATTR_SONAME)->sarg(0), s2);

	r = block(COMOP, r, s, INCREF(p->n_type), p->n_df, p->n_ap);
	r = buildtree(UMUL, r, NIL);
	tfree(p);
	return r;
}
Esempio n. 22
0
/* called from moveargs() */
static NODE *
movearg_float(NODE *p, int *regp)
{
	NODE *q, *r;
	TWORD ty = INCREF(p->n_type);
	int tmpnr;

	/*
	 * Floats are passed in the general registers for
	 * compatibily with libraries compiled to handle soft-float.
	 */

	if (xtemps) {
		/* bounce on TOS */
		r = block(REG, NIL, NIL, ty, p->n_df, p->n_ap);
		regno(r) = SP;
		r = block(PLUS, r, bcon(-4), ty, p->n_df, p->n_ap);
		r = block(UMUL, r, NIL, p->n_type, p->n_df, p->n_ap);
		r = buildtree(ASSIGN, r, p);
		ecomp(r);

		/* bounce into temp */
		r = block(REG, NIL, NIL, PTR+INT, 0, 0);
		regno(r) = SP;
		r = block(PLUS, r, bcon(-8), PTR+INT, 0, 0);
		r = block(UMUL, r, NIL, INT, 0, 0);
		q = tempnode(0, INT, 0, 0);
		tmpnr = regno(q);
		r = buildtree(ASSIGN, q, r);
		ecomp(r);
	} else {
		/* copy directly into temp */
		q = tempnode(0, p->n_type, p->n_df, p->n_ap);
		tmpnr = regno(q);
		r = buildtree(ASSIGN, q, p);
		ecomp(r);
	}

	/* copy from temp to register parameter */
	r = tempnode(tmpnr, INT, 0, 0);
	q = block(REG, NIL, NIL, INT, 0, 0);
	regno(q) = (*regp)++;
	p = buildtree(ASSIGN, q, r);

	return p;
}
Esempio n. 23
0
/*
 * Allocate off bits on the stack.  p is a tree that when evaluated
 * is the multiply count for off, t is a NAME node where to write
 * the allocated address.
 */
void
spalloc(NODE *t, NODE *p, OFFSZ off)
{
	NODE *sp;

	if ((off % SZINT) == 0)
		p =  buildtree(MUL, p, bcon(off/SZINT));
	else if ((off % SZSHORT) == 0) {
		p = buildtree(MUL, p, bcon(off/SZSHORT));
		p = buildtree(PLUS, p, bcon(1));
		p = buildtree(RS, p, bcon(1));
	} else if ((off % SZCHAR) == 0) {
		p = buildtree(MUL, p, bcon(off/SZCHAR));
		p = buildtree(PLUS, p, bcon(3));
		p = buildtree(RS, p, bcon(2));
	} else
		cerror("roundsp");

	/* save the address of sp */
	sp = block(REG, NIL, NIL, PTR+INT, t->n_df, t->n_sue);
	sp->n_lval = 0;
	sp->n_rval = STKREG;
	t->n_type = sp->n_type;
	ecomp(buildtree(ASSIGN, t, sp)); /* Emit! */

	/* add the size to sp */
	sp = block(REG, NIL, NIL, p->n_type, 0, 0);
	sp->n_lval = 0;
	sp->n_rval = STKREG;
	ecomp(buildtree(PLUSEQ, sp, p));
}
Esempio n. 24
0
static NODE *
mkstkref(int off, TWORD typ)
{
	NODE *p;

	p = block(REG, NIL, NIL, PTR|typ, 0, MKAP(LONG));
	regno(p) = FPREG;
	return buildtree(PLUS, p, bcon(off/SZCHAR));
}
Esempio n. 25
0
File: code.c Progetto: rheoli/pcc
/*
 * code for the end of a function
 * deals with struct return here
 * The return value is in (or pointed to by) RETREG.
 */
void
efcode(void)
{
	struct symtab *sp;
	extern int gotnr;
	TWORD t;
	NODE *p, *r, *l;
	int typ, ssz, rno;

	gotnr = 0;	/* new number for next fun */
	sp = cftnsp;
	t = DECREF(sp->stype);
	if (t != STRTY && t != UNIONTY)
		return;

	/* XXX should have one routine for this */
	ngpr = nsse = 0;
	if ((typ = argtyp(t, sp->sdf, sp->sap)) == STRREG || typ == STRCPX) {
		/* Cast to long pointer and move to the registers */
		/* XXX can overrun struct size */
		/* XXX check carefully for SSE members */

		if ((ssz = tsize(t, sp->sdf, sp->sap)) > SZLONG*2)
			cerror("efcode1");

		if (typ == STRCPX) {
			t = DOUBLE;
			rno = XMM0;
		} else {
			t = LONG;
			rno = RAX;
		}
		if (ssz > SZLONG) {
			p = block(REG, NIL, NIL, INCREF(t), 0, 0);
			regno(p) = RAX;
			p = buildtree(UMUL, buildtree(PLUS, p, bcon(1)), NIL);
			ecomp(movtoreg(p, rno+1));
		}
		p = block(REG, NIL, NIL, INCREF(t), 0, 0);
		regno(p) = RAX;
		p = buildtree(UMUL, p, NIL);
		ecomp(movtoreg(p, rno));
	} else if (typ == STRMEM) {
		r = block(REG, NIL, NIL, INCREF(t), sp->sdf, sp->sap);
		regno(r) = RAX;
		r = buildtree(UMUL, r, NIL);
		l = tempnode(stroffset, INCREF(t), sp->sdf, sp->sap);
		l = buildtree(UMUL, l, NIL);
		ecomp(buildtree(ASSIGN, l, r));
		l = block(REG, NIL, NIL, LONG, 0, 0);
		regno(l) = RAX;
		r = tempnode(stroffset, LONG, 0, 0);
		ecomp(buildtree(ASSIGN, l, r));
	} else
		cerror("efcode");
}
Esempio n. 26
0
static NODE *
builtin_bswap32(const struct bitable *bt, NODE *a)
{
    NODE *f, *t1, *t2, *t3, *t4;

    t1 = buildtree(LS, buildtree(AND, ccopy(a), bcon(255)), bcon(24));
    t2 = buildtree(LS, buildtree(AND, ccopy(a), bcon(255 << 8)), bcon(8));
    t3 = buildtree(AND, buildtree(RS, ccopy(a), bcon(8)), bcon(255 << 8));
    t4 = buildtree(AND, buildtree(RS, a, bcon(24)), bcon(255));
    f = buildtree(OR, buildtree(OR, t1, t2), buildtree(OR, t3, t4));
    return f;
}
Esempio n. 27
0
/* called from moveargs() */
static NODE *
movearg_double(NODE *p, int *regp)
{
	NODE *q, *r;
	TWORD ty = INCREF(p->n_type);
	int tmpnr;

	if (xtemps) {
		/* bounce on TOS */
		r = block(REG, NIL, NIL, ty, p->n_df, p->n_ap);
		regno(r) = SP;
		r = block(PLUS, r, bcon(-8), ty, p->n_df, p->n_ap);
		r = block(UMUL, r, NIL, p->n_type, p->n_df, p->n_ap);
		r = buildtree(ASSIGN, r, p);
		ecomp(r);

		/* bounce into temp */
		r = block(REG, NIL, NIL, PTR+LONGLONG, 0, 0);
		regno(r) = SP;
		r = block(PLUS, r, bcon(-8), PTR+LONGLONG, 0, 0);
		r = block(UMUL, r, NIL, LONGLONG, 0, 0);
		q = tempnode(0, LONGLONG, 0, 0);
		tmpnr = regno(q);
		r = buildtree(ASSIGN, q, r);
		ecomp(r);
	} else {
		/* copy directly into temp */
		q = tempnode(0, p->n_type, p->n_df, p->n_ap);
		tmpnr = regno(q);
		r = buildtree(ASSIGN, q, p);
		ecomp(r);
	}

	/* copy from temp to register parameter */
	r = tempnode(tmpnr, LONGLONG, 0, 0);
	q = block(REG, NIL, NIL, LONGLONG, 0, 0);
	regno(q) = R0R1 - R0 + (*regp);
	p = buildtree(ASSIGN, q, r);

	(*regp) += 2;

	return p;
}
Esempio n. 28
0
File: code.c Progetto: rheoli/pcc
/*
 * Called with a function call with arguments as argument.
 * This is done early in buildtree() and only done once.
 * Returns p.
 */
NODE *
funcode(NODE *p)
{
	NODE *l, *r;
	TWORD t;
	int i;

	nsse = ngpr = nrsp = 0;
	/* Check if hidden arg needed */
	/* If so, add it in pass2 */
	if ((l = p->n_left)->n_type == INCREF(FTN)+STRTY ||
	    l->n_type == INCREF(FTN)+UNIONTY) {
		int ssz = tsize(BTYPE(l->n_type), l->n_df, l->n_ap);
		if (ssz > 2*SZLONG)
			ngpr++;
	}

	/* Convert just regs to assign insn's */
	p->n_right = argput(p->n_right);

	/* Must sort arglist so that STASG ends up first */
	/* This avoids registers being clobbered */
	while (argsort(p->n_right))
		;
	/* Check if there are varargs */
	if (nsse || l->n_df == NULL || l->n_df->dfun == NULL) {
		; /* Need RAX */
	} else {
		union arglist *al = l->n_df->dfun;

		for (; al->type != TELLIPSIS; al++) {
			if ((t = al->type) == TNULL)
				return p; /* No need */
			if (ISSOU(BTYPE(t)))
				al++;
			for (i = 0; t > BTMASK; t = DECREF(t))
				if (ISARY(t) || ISFTN(t))
					i++;
			if (i)
				al++;
		}
	}

	/* Always emit number of SSE regs used */
	l = movtoreg(bcon(nsse), RAX);
	if (p->n_right->n_op != CM) {
		p->n_right = block(CM, l, p->n_right, INT, 0, 0);
	} else {
		for (r = p->n_right; r->n_left->n_op == CM; r = r->n_left)
			;
		r->n_left = block(CM, l, r->n_left, INT, 0, 0);
	}
	return p;
}
Esempio n. 29
0
/*
 * Sanitycheck "new" keyword.
 */
NODE *
cxx_new(NODE *p)
{
	NODE *q = p;
	NODE *t1 = bcon(1);
	int nw = NM_NEW;

	while (p->n_op == LB) {
		nw = NM_NWA;
		t1 = buildtree(MUL, t1, eve(p->n_right));
		p->n_right = bcon(0);
		p = p->n_left;
	}
	if (p->n_op != TYPE)
		uerror("new used illegally");
	t1 = buildtree(MUL, t1, 
	    xbcon(tsize(p->n_type, p->n_df, p->n_ap)/SZCHAR, NULL, INTPTR));
	tfree(q);
	return callftn(decoratename(NULL, nw), t1, NULL);
}
Esempio n. 30
0
/* called from moveargs() */
static NODE *
movearg_64bit(NODE *p, int *regp)
{
	int reg = *regp;
	NODE *q, *r;

#if ALLONGLONG == 64
	/* alignment */
	++reg;
	reg &= ~1;
	*regp = reg;
#endif

	if (reg > R3) {
		q = pusharg(p, regp);
	} else if (reg == R3) {
		/* half in and half out of the registers */
		r = tcopy(p);
		if (!features(FEATURE_BIGENDIAN)) {
			q = block(SCONV, p, NIL, INT, 0, 0);
			q = movearg_32bit(q, regp);     /* little-endian */
			r = buildtree(RS, r, bcon(32));
			r = block(SCONV, r, NIL, INT, 0, 0);
			r = pusharg(r, regp); /* little-endian */
		} else {
			q = buildtree(RS, p, bcon(32));
			q = block(SCONV, q, NIL, INT, 0, 0);
			q = movearg_32bit(q, regp);     /* big-endian */
			r = block(SCONV, r, NIL, INT, 0, 0);
			r = pusharg(r, regp); /* big-endian */
		}
		q = straighten(block(CM, q, r, p->n_type, p->n_df, p->n_ap));
	} else {
		q = block(REG, NIL, NIL, p->n_type, p->n_df, p->n_ap);
		regno(q) = R0R1 + (reg - R0);
		q = buildtree(ASSIGN, q, p);
		*regp = reg + 2;
	}

	return q;
}