forsyth20121205-174063a80cc13 years agoHistory
628 lines · 11.4 KB · C
RawDownload
#include	"l.h" voidspan(void){	Prog *p, *q;	Sym *setext;	Optab *o;	int m, bflag;	long c, otxt; 	if(debug['v'])		Bprint(&bso, "%5.2f span\n", cputime());	Bflush(&bso); 	bflag = 0;	c = INITTEXT;	otxt = c;	for(p = firstp; p != P; p = p->link) {		p->pc = c;		o = oplook(p);		m = o->size;		if(m == 0) {			if(p->as == ATEXT) {				curtext = p;				autosize = p->to.offset + 8;				if(p->from.sym != S)					p->from.sym->value = c;				/* need passes to resolve branches */				if(c-otxt >= 1L<<17)					bflag = 1;				otxt = c;				continue;			}			diag("zero-width instruction\n%P\n", p);			continue;		}		c += m;	} 	/*	 * if any procedure is large enough to	 * generate a large SBRA branch, then	 * generate extra passes putting branches	 * around jmps to fix. this is rare.	 */	while(bflag) {		if(debug['v'])			Bprint(&bso, "%5.2f span1\n", cputime());		bflag = 0;		c = INITTEXT;		for(p = firstp; p != P; p = p->link) {			p->pc = c;			o = oplook(p);			if(o->type == 6 && p->cond) {				otxt = p->cond->pc - c;				if(otxt < 0)					otxt = -otxt;				if(otxt >= (1L<<17) - 10) {					q = prg();					q->link = p->link;					p->link = q;					q->as = AJMP;					q->to.type = D_BRANCH;					q->cond = p->cond;					p->cond = q;					q = prg();					q->link = p->link;					p->link = q;					q->as = AJMP;					q->to.type = D_BRANCH;					q->cond = q->link->link;					addnop(p->link);					addnop(p);					bflag = 1;				}			}			m = o->size;			if(m == 0) {				if(p->as == ATEXT) {					curtext = p;					autosize = p->to.offset + 8;					if(p->from.sym != S)						p->from.sym->value = c;					continue;				}				diag("zero-width instruction\n%P\n", p);				continue;			}			c += m;		}	}	c = rnd(c, 8); 	setext = lookup("etext", 0);	if(setext != S) {		setext->value = c;		textsize = c - INITTEXT;	}	if(INITRND)		INITDAT = rnd(c, INITRND);	if(debug['v'])		Bprint(&bso, "tsize = %lux\n", textsize);	Bflush(&bso);}		voidxdefine(char *p, int t, long v){	Sym *s; 	s = lookup(p, 0);	if(s->type == 0 || s->type == SXREF) {		s->type = t;		s->value = v;	}} longregoff(Adr *a){ 	instoffset = 0;	aclass(a);	return instoffset;} intaclass(Adr *a){	Sym *s;	int t; 	switch(a->type) {	case D_NONE:		return C_NONE; 	case D_REG:		return C_REG; 	case D_FREG:		return C_FREG; 	case D_FCREG:		return C_FCREG; 	case D_MREG:		return C_MREG; 	case D_OREG:		switch(a->name) {		case D_EXTERN:		case D_STATIC:			if(a->sym == 0 || a->sym->name == 0) {				print("null sym external\n");				print("%D\n", a);				return C_GOK;			}			t = a->sym->type;			if(t == 0 || t == SXREF) {				diag("undefined external: %s in %s\n",					a->sym->name, TNAME);				a->sym->type = SDATA;			}			instoffset = a->sym->value + a->offset - BIG;			if(instoffset >= -BIG && instoffset < BIG)				return C_SEXT;			return C_LEXT;		case D_AUTO:			instoffset = autosize + a->offset;			if(instoffset >= -BIG && instoffset < BIG)				return C_SAUTO;			return C_LAUTO; 		case D_PARAM:			instoffset = autosize + a->offset + 8L;			if(instoffset >= -BIG && instoffset < BIG)				return C_SAUTO;			return C_LAUTO;		case D_NONE:			instoffset = a->offset;			if(instoffset == 0)				return C_ZOREG;			if(instoffset >= -BIG && instoffset < BIG)				return C_SOREG;			return C_LOREG;		}		return C_GOK; 	case D_HI:		return C_LO;	case D_LO:		return C_HI; 	case D_OCONST:		switch(a->name) {		case D_EXTERN:		case D_STATIC:			s = a->sym;			t = s->type;			if(t == 0 || t == SXREF) {				diag("undefined external: %s in %s\n",					s->name, TNAME);				s->type = SDATA;			}			instoffset = s->value + a->offset + INITDAT;			if(s->type == STEXT || s->type == SLEAF)				instoffset = s->value + a->offset;			return C_LCON;		}		return C_GOK; 	case D_CONST:		switch(a->name) { 		case D_NONE:			instoffset = a->offset;		consize:			if(instoffset > 0) {				if(instoffset <= 0x7fff)					return C_SCON;				if(instoffset <= 0xffff)					return C_ANDCON;				if((instoffset & 0xffff) == 0)					return C_UCON;				return C_LCON;			}			if(instoffset == 0)				return C_ZCON;			if(instoffset >= -0x8000)				return C_ADDCON;			if((instoffset & 0xffff) == 0)				return C_UCON;			return C_LCON; 		case D_EXTERN:		case D_STATIC:			s = a->sym;			if(s == S)				break;			t = s->type;			switch(t) {			case 0:			case SXREF:				diag("undefined external: %s in %s\n",					s->name, TNAME);				s->type = SDATA;				break;			case SCONST:				instoffset = s->value + a->offset;				goto consize;			case STEXT:			case SLEAF:				instoffset = s->value + a->offset;				return C_LCON;			}			instoffset = s->value + a->offset - BIG;			if(instoffset >= -BIG && instoffset < BIG && instoffset != 0L)				return C_SECON;			instoffset = s->value + a->offset + INITDAT;			return C_LCON; 		case D_AUTO:			instoffset = autosize + a->offset;			if(instoffset >= -BIG && instoffset < BIG)				return C_SACON;			return C_LACON; 		case D_PARAM:			instoffset = autosize + a->offset + 8L;			if(instoffset >= -BIG && instoffset < BIG)				return C_SACON;			return C_LACON;		}		return C_GOK; 	case D_BRANCH:		return C_SBRA;	}	return C_GOK;} Optab*oplook(Prog *p){	int a1, a2, a3, r, t;	char *c1, *c3;	Optab *o, *e; 	a1 = p->optab;	if(a1)		return optab+(a1-1);	a1 = p->from.class;	if(a1 == 0) {		a1 = aclass(&p->from) + 1;		p->from.class = a1;	}	a1--;	a3 = p->to.class;	if(a3 == 0) {		a3 = aclass(&p->to) + 1;		p->to.class = a3;	}	a3--;	a2 = C_NONE;	if(p->reg != NREG)		a2 = C_REG;	r = p->as;	o = oprange[r].start;	if(o == 0) {		t = opcross[repop[r]][a1][a2][a3];		if(t) {			p->optab = t+1;			return optab+t;		}		o = oprange[r].stop; /* just generate an error */	}	e = oprange[r].stop;	c1 = xcmp[a1];	c3 = xcmp[a3];	for(; o<e; o++)		if(o->a2 == a2)		if(c1[o->a1])		if(c3[o->a3]) {			p->optab = (o-optab)+1;			return o;		}	diag("illegal combination %A %d %d %d",		p->as, a1, a2, a3);	if(!debug['a'])		prasm(p);	o = optab;	p->optab = (o-optab)+1;	return o;} intcmp(int a, int b){ 	if(a == b)		return 1;	switch(a) {	case C_LCON:		if(b == C_ZCON || b == C_SCON || b == C_UCON ||		   b == C_ADDCON || b == C_ANDCON)			return 1;		break;	case C_ADD0CON:		if(b == C_ADDCON)			return 1;	case C_ADDCON:		if(b == C_ZCON || b == C_SCON)			return 1;		break;	case C_AND0CON:		if(b == C_ANDCON)			return 1;	case C_ANDCON:		if(b == C_ZCON || b == C_SCON)			return 1;		break;	case C_UCON:		if(b == C_ZCON)			return 1;		break;	case C_SCON:		if(b == C_ZCON)			return 1;		break;	case C_LACON:		if(b == C_SACON)			return 1;		break;	case C_LBRA:		if(b == C_SBRA)			return 1;		break;	case C_LEXT:		if(b == C_SEXT)			return 1;		break;	case C_LAUTO:		if(b == C_SAUTO)			return 1;		break;	case C_REG:		if(b == C_ZCON)			return 1;		break;	case C_LOREG:		if(b == C_ZOREG || b == C_SOREG)			return 1;		break;	case C_SOREG:		if(b == C_ZOREG)			return 1;		break;	}	return 0;} intocmp(const void *a1, const void *a2){	Optab *p1, *p2;	int n; 	p1 = (Optab*)a1;	p2 = (Optab*)a2;	n = p1->as - p2->as;	if(n)		return n;	n = p1->a1 - p2->a1;	if(n)		return n;	n = p1->a2 - p2->a2;	if(n)		return n;	n = p1->a3 - p2->a3;	if(n)		return n;	return 0;} voidbuildop(void){	int i, n, r; 	for(i=0; i<32; i++)		for(n=0; n<32; n++)			xcmp[i][n] = cmp(n, i);	for(n=0; optab[n].as != AXXX; n++)		;	qsort(optab, n, sizeof(optab[0]), ocmp);	for(i=0; i<n; i++) {		r = optab[i].as;		oprange[r].start = optab+i;		while(optab[i].as == r)			i++;		oprange[r].stop = optab+i;		i--;				switch(r)		{		default:			diag("unknown op in build: %A\n", r);			errorexit();		case AABSF:			oprange[AMOVFD] = oprange[r];			oprange[AMOVDF] = oprange[r];			oprange[AMOVWF] = oprange[r];			oprange[AMOVFW] = oprange[r];			oprange[AMOVWD] = oprange[r];			oprange[AMOVDW] = oprange[r];			oprange[ANEGF] = oprange[r];			oprange[ANEGD] = oprange[r];			oprange[AABSD] = oprange[r];			oprange[ATRUNCDW] = oprange[r];			oprange[ATRUNCFW] = oprange[r];			oprange[ATRUNCDV] = oprange[r];			oprange[ATRUNCFV] = oprange[r];			oprange[AMOVDV] = oprange[r];			oprange[AMOVFV] = oprange[r];			oprange[AMOVVD] = oprange[r];			oprange[AMOVVF] = oprange[r];			break;		case AADD:			buildrep(1, AADD);			oprange[ASGT] = oprange[r];			repop[ASGT] = 1;			oprange[ASGTU] = oprange[r];			repop[ASGTU] = 1;			oprange[AADDU] = oprange[r];			repop[AADDU] = 1;			oprange[AADDVU] = oprange[r];			repop[AADDVU] = 1;			oprange[AADDV] = oprange[r];			repop[AADDV] = 1;			break;		case AADDF:			oprange[ADIVF] = oprange[r];			oprange[ADIVD] = oprange[r];			oprange[AMULF] = oprange[r];			oprange[AMULD] = oprange[r];			oprange[ASUBF] = oprange[r];			oprange[ASUBD] = oprange[r];			oprange[AADDD] = oprange[r];			break;		case AAND:			buildrep(2, AAND);			oprange[AXOR] = oprange[r];			repop[AXOR] = 2;			oprange[AOR] = oprange[r];			repop[AOR] = 2;			break;		case ABEQ:			oprange[ABNE] = oprange[r];			break;

Lines 1–500 of 628.