Charles.Forsyth20060303644188019 years agoHistory
2711 lines · 44.8 KB · C
RawDownload
#include "gc.h" voidzeroregm(Node *n){	gins(AMOVL, nodconst(0), n);} /* do we need to load the address of a vlong? */intvaddr(Node *n, int a){	switch(n->op) {	case ONAME:		if(a)			return 1;		return !(n->class == CEXTERN || n->class == CGLOBL || n->class == CSTATIC); 	case OCONST:	case OREGISTER:	case OINDREG:		return 1;	}	return 0;} longhi64v(Node *n){	if(align(0, types[TCHAR], Aarg1))	/* isbigendian */		return (long)(n->vconst) & ~0L;	else		return (long)((uvlong)n->vconst>>32) & ~0L;} longlo64v(Node *n){	if(align(0, types[TCHAR], Aarg1))	/* isbigendian */		return (long)((uvlong)n->vconst>>32) & ~0L;	else		return (long)(n->vconst) & ~0L;} Node *hi64(Node *n){	return nodconst(hi64v(n));} Node *lo64(Node *n){	return nodconst(lo64v(n));} static Node *anonreg(void){	Node *n; 	n = new(OREGISTER, Z, Z);	n->reg = D_NONE;	n->type = types[TLONG];	return n;} static Node *regpair(Node *n, Node *t){	Node *r; 	if(n != Z && n->op == OREGPAIR)		return n;	r = new(OREGPAIR, anonreg(), anonreg());	if(n != Z)		r->type = n->type;	else		r->type = t->type;	return r;} static voidevacaxdx(Node *r){	Node nod1, nod2; 	if(r->reg == D_AX || r->reg == D_DX) {		reg[D_AX]++;		reg[D_DX]++;		/*		 * this is just an optim that should		 * check for spill		 */		r->type = types[TULONG];		regalloc(&nod1, r, Z);		nodreg(&nod2, Z, r->reg);		gins(AMOVL, &nod2, &nod1);		regfree(r);		r->reg = nod1.reg;		reg[D_AX]--;		reg[D_DX]--;	}} /* lazy instantiation of register pair */static intinstpair(Node *n, Node *l){	int r; 	r = 0;	if(n->left->reg == D_NONE) {		if(l != Z) {			n->left->reg = l->reg;			r = 1;		}		else			regalloc(n->left, n->left, Z);	}	if(n->right->reg == D_NONE)		regalloc(n->right, n->right, Z);	return r;} static voidzapreg(Node *n){	if(n->reg != D_NONE) {		regfree(n);		n->reg = D_NONE;	}} static voidfreepair(Node *n){	regfree(n->left);	regfree(n->right);} /* n is not OREGPAIR, nn is */voidloadpair(Node *n, Node *nn){	Node nod; 	instpair(nn, Z);	if(n->op == OCONST) {		gins(AMOVL, lo64(n), nn->left);		n->xoffset += SZ_LONG;		gins(AMOVL, hi64(n), nn->right);		n->xoffset -= SZ_LONG;		return;	}	if(!vaddr(n, 0)) {		/* steal the right register for the laddr */		nod = regnode;		nod.reg = nn->right->reg;		lcgen(n, &nod);		n = &nod;		regind(n, n);		n->xoffset = 0;	}	gins(AMOVL, n, nn->left);	n->xoffset += SZ_LONG;	gins(AMOVL, n, nn->right);	n->xoffset -= SZ_LONG;} /* n is OREGPAIR, nn is not */static voidstorepair(Node *n, Node *nn, int f){	Node nod; 	if(!vaddr(nn, 0)) {		reglcgen(&nod, nn, Z);		nn = &nod;	}	gins(AMOVL, n->left, nn);	nn->xoffset += SZ_LONG;	gins(AMOVL, n->right, nn);	nn->xoffset -= SZ_LONG;	if(nn == &nod)		regfree(&nod);	if(f)		freepair(n);} /* generate a cast t from n to tt */static voidcast(Node *n, Type *t, Node *nn){	Node *r; 	r = new(OCAST, n, Z);	r->type = t;	sugen(r, nn, 8);} static voidswapregs(Node *a, Node *b){	int t; 	t = a->reg;	a->reg = b->reg;	b->reg = t;} static voidswappairs(Node *a, Node *b){	swapregs(a->left, b->left);	swapregs(a->right, b->right);} static intsaveme(Node *n){	int r; 	r = n->reg;	return r >= D_AX && r <= D_DI;} static voidsaveit(Node *n, Node *t, Node *r){	Node nod; 	if(saveme(n)) {		t->reg = n->reg;		gins(AMOVL, t, r);		r->xoffset += SZ_LONG;		if(n->reg == D_AX) {			regalloc(&nod, n, Z);			regfree(n);			n->reg = nod.reg;		}	}} static voidrestoreit(Node *n, Node *t, Node *r){	if(saveme(n)) {		t->reg = n->reg;		gins(AMOVL, r, t);		r->xoffset += SZ_LONG;	}} enum{/* 4 only, see WW */	WNONE	= 0,	WCONST,	WADDR,	WHARD,}; static intwhatof(Node *n, int a){	if(n->op == OCONST)		return WCONST;	return !vaddr(n, a) ? WHARD : WADDR;} /* can upgrade an extern to addr for AND */static intreduxv(Node *n){	return lo64v(n) == 0 || hi64v(n) == 0;} intcond(int op){	switch(op) {	case OANDAND:	case OOROR:	case ONOT:		return 1; 	case OEQ:	case ONE:	case OLE:	case OLT:	case OGE:	case OGT:	case OHI:	case OHS:	case OLO:	case OLS:		return 1;	}	return 0;} /* * for a func operand call it and then return * the safe node */static Node *vfunc(Node *n, Node *nn){	Node *t; 	if(n->op != OFUNC)		return n;	t = new(0, Z, Z);	if(nn == Z || nn == nodret)		nn = n;	regsalloc(t, nn);	sugen(n, t, 8);	return t;} static intforcereg(Node *d, int r, int o, Node *t){	int a; 	if(d->reg != D_NONE)		diag(Z, "force alloc");	d->reg = r;	a = 0;	if(reg[r]) {		reg[o]++;		regalloc(t, d, Z);		a = 1;		gins(AMOVL, d, t);		reg[o]--;	}	reg[r]++;	return a;} /* try to steal a reg */static intgetreg(Node **np, Node *t, int r){	Node *n, *p; 	n = *np;	if(n->reg == r) {		p = new(0, Z, Z);		regalloc(p, n, Z);		gins(AMOVL, n, p);		*t = *n;		*np = p;		return 1;	}	return 0;} static Node *snarfreg(Node *n, Node *t, int r, Node *d, Node *c){	if(n == Z || n->op != OREGPAIR || (!getreg(&n->left, t, r) && !getreg(&n->right, t, r))) {		if(nodreg(t, Z, r)) {			regalloc(c, d, Z);			gins(AMOVL, t, c);			reg[r]++;			return c;		}		reg[r]++;	}	return Z;} enum{	Vstart	= OEND, 	Vgo,	Vamv,	Vmv,	Vzero,	Vop,	Vopx,	Vins,	Vins0,	Vinsl,	Vinsr,	Vinsla,	Vinsra,	Vinsx,	Vmul,	Vshll,	VT,	VF,	V_l_lo_f,	V_l_hi_f,	V_l_lo_t,	V_l_hi_t,	V_l_lo_u,	V_l_hi_u,	V_r_lo_f,	V_r_hi_f,	V_r_lo_t,	V_r_hi_t,	V_r_lo_u,	V_r_hi_u,	Vspazz,	Vend, 	V_T0,	V_T1,	V_F0,	V_F1, 	V_a0,	V_a1,	V_f0,	V_f1, 	V_p0,	V_p1,	V_p2,	V_p3,	V_p4, 	V_s0,	V_s1,	V_s2,	V_s3,	V_s4, 	C00,	C01,	C31,	C32, 	O_l_lo,	O_l_hi,	O_r_lo,	O_r_hi,	O_t_lo,	O_t_hi,	O_l,	O_r,	O_l_rp,	O_r_rp,	O_t_rp,	O_r0,	O_r1,	O_Zop, 	O_a0,	O_a1, 	V_C0,	V_C1, 	V_S0,	V_S1, 	VOPS	= 5,	VLEN	= 5,	VARGS	= 2, 	S00	= 0,	Sc0,	Sc1,	Sc2,	Sac3,	Sac4,	S10, 	SAgen	= 0,	SAclo,	SAc32,	SAchi,	SAdgen,	SAdclo,	SAdc32,	SAdchi, 	B0c	= 0,	Bca,	Bac, 	T0i	= 0,	Tii, 	Bop0	= 0,	Bop1,}; /* * _testv: * 	CMPL	lo,$0 * 	JNE	true * 	CMPL	hi,$0 * 	JNE	true * 	GOTO	false

Lines 1–500 of 2711.