⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 span.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include	"l.h"static struct {	ulong	start;	ulong	size;} pool;void	checkpool(Prog*);void 	flushpool(Prog*, int);voidspan(void){	Prog *p;	Sym *setext, *s;	Optab *o;	int m, bflag, i;	long c, otxt, v;	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 + 4;				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", p);			continue;		}		switch(o->flag & (LFROM|LTO|LPOOL)) {		case LFROM:			addpool(p, &p->from);			break;		case LTO:			addpool(p, &p->to);			break;		case LPOOL:			if ((p->scond&C_SCOND) == 14)				flushpool(p, 0);			break;		}		if(p->as==AMOVW && p->to.type==D_REG && p->to.reg==REGPC && (p->scond&C_SCOND) == 14)			flushpool(p, 0);		c += m;		if(blitrl)			checkpool(p);	}	/*	 * 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);/* very larg branches			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 = AB;					q->to.type = D_BRANCH;					q->cond = p->cond;					p->cond = q;					q = prg();					q->link = p->link;					p->link = q;					q->as = AB;					q->to.type = D_BRANCH;					q->cond = q->link->link;					bflag = 1;				}			} */			m = o->size;			if(m == 0) {				if(p->as == ATEXT) {					curtext = p;					autosize = p->to.offset + 4;					if(p->from.sym != S)						p->from.sym->value = c;					continue;				}				diag("zero-width instruction\n%P", p);				continue;			}			c += m;		}	}	if(debug['t']) {		/* 		 * add strings to text segment		 */		c = rnd(c, 8);		for(i=0; i<NHASH; i++)		for(s = hash[i]; s != S; s = s->link) {			if(s->type != SSTRING)				continue;			v = s->value;			while(v & 3)				v++;			s->value = c;			c += v;		}	}	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);}/* * when the first reference to the literal pool threatens * to go out of range of a 12-bit PC-relative offset, * drop the pool now, and branch round it. * this happens only in extended basic blocks that exceed 4k. */voidcheckpool(Prog *p){	if(pool.size >= 0xffc || immaddr((p->pc+4)+4+pool.size - pool.start+8) == 0)		flushpool(p, 1);	else if(p->link == P)		flushpool(p, 2);}voidflushpool(Prog *p, int skip){	Prog *q;	if(blitrl) {		if(skip){			if(debug['v'] && skip == 1)				print("note: flush literal pool at %lux: len=%lud ref=%lux\n", p->pc+4, pool.size, pool.start);			q = prg();			q->as = AB;			q->to.type = D_BRANCH;			q->cond = p->link;			q->link = blitrl;			blitrl = q;		}		else if(p->pc+pool.size-pool.start < 2048)			return;		elitrl->link = p->link;		p->link = blitrl;		blitrl = 0;	/* BUG: should refer back to values until out-of-range */		elitrl = 0;		pool.size = 0;		pool.start = 0;	}}voidaddpool(Prog *p, Adr *a){	Prog *q, t;	int c;	c = aclass(a);	t = zprg;	t.as = AWORD;	switch(c) {	default:		t.to = *a;		break;	case C_SROREG:	case C_LOREG:	case C_ROREG:	case C_FOREG:	case C_SOREG:	case C_FAUTO:	case C_SAUTO:	case C_LAUTO:	case C_LACON:		t.to.type = D_CONST;		t.to.offset = instoffset;		break;	}	for(q = blitrl; q != P; q = q->link)	/* could hash on t.t0.offset */		if(memcmp(&q->to, &t.to, sizeof(t.to)) == 0) {			p->cond = q;			return;		}	q = prg();	*q = t;	q->pc = pool.size;	if(blitrl == P) {		blitrl = q;		pool.start = p->pc;	} else		elitrl->link = q;	elitrl = q;	pool.size += 4;	p->cond = q;}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;}longimmrot(ulong v){	int i;	for(i=0; i<16; i++) {		if((v & ~0xff) == 0)			return (i<<8) | v | (1<<25);		v = (v<<2) | (v>>30);	}	return 0;}longimmaddr(long v){	if(v >= 0 && v <= 0xfff)		return (v & 0xfff) |			(1<<24) |	/* pre indexing */			(1<<23);	/* pre indexing, up */	if(v >= -0xfff && v < 0)		return (-v & 0xfff) |			(1<<24);	/* pre indexing */	return 0;}intimmfloat(long v){	return (v & 0xC03) == 0;	/* offset will fit in floating-point load/store */}intimmhalf(long v){	if(v >= 0 && v <= 0xff)		return v|			(1<<24)|	/* pre indexing */			(1<<23);	/* pre indexing, up */	if(v >= -0xff && v < 0)		return (-v & 0xff)|			(1<<24);	/* pre indexing */	return 0;}intaclass(Adr *a){	Sym *s;	int t;	switch(a->type) {	case D_NONE:		return C_NONE;	case D_REG:		return C_REG;	case D_REGREG:		return C_REGREG;	case D_SHIFT:		return C_SHIFT;	case D_FREG:		return C_FREG;	case D_FPCR:		return C_FCR;	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;			}			s = a->sym;			t = s->type;			if(t == 0 || t == SXREF) {				diag("undefined external: %s in %s",					s->name, TNAME);				s->type = SDATA;			}			if(dlm) {				switch(t) {				default:					instoffset = s->value + a->offset + INITDAT;					break;				case SUNDEF:				case STEXT:				case SCONST:				case SLEAF:				case SSTRING:					instoffset = s->value + a->offset;					break;				}				return C_ADDR;			}			instoffset = s->value + a->offset - BIG;			t = immaddr(instoffset);			if(t) {				if(immhalf(instoffset))					return immfloat(t) ? C_HFEXT : C_HEXT;				if(immfloat(t))					return C_FEXT;				return C_SEXT;			}			return C_LEXT;		case D_AUTO:			instoffset = autosize + a->offset;			t = immaddr(instoffset);			if(t){				if(immhalf(instoffset))					return immfloat(t) ? C_HFAUTO : C_HAUTO;				if(immfloat(t))					return C_FAUTO;				return C_SAUTO;			}			return C_LAUTO;		case D_PARAM:			instoffset = autosize + a->offset + 4L;			t = immaddr(instoffset);			if(t){				if(immhalf(instoffset))					return immfloat(t) ? C_HFAUTO : C_HAUTO;				if(immfloat(t))					return C_FAUTO;				return C_SAUTO;			}			return C_LAUTO;		case D_NONE:			instoffset = a->offset;			t = immaddr(instoffset);			if(t) {				if(immhalf(instoffset))		 /* n.b. that it will also satisfy immrot */					return immfloat(t) ? C_HFOREG : C_HOREG;				if(immfloat(t))					return C_FOREG; /* n.b. that it will also satisfy immrot */				t = immrot(instoffset);				if(t)					return C_SROREG;				if(immhalf(instoffset))					return C_HOREG;				return C_SOREG;			}			t = immrot(instoffset);			if(t)				return C_ROREG;			return C_LOREG;		}		return C_GOK;	case D_PSR:		return C_PSR;	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",					s->name, TNAME);				s->type = SDATA;			}			instoffset = s->value + a->offset + INITDAT;			if(s->type == STEXT || s->type == SLEAF || s->type == SUNDEF)				instoffset = s->value + a->offset;			return C_LCON;		}		return C_GOK;	case D_FCONST:		return C_FCON;	case D_CONST:		switch(a->name) {		case D_NONE:			instoffset = a->offset;			if(a->reg != NREG)				goto aconsize;			t = immrot(instoffset);			if(t)				return C_RCON;			t = immrot(~instoffset);			if(t)				return C_NCON;			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",					s->name, TNAME);				s->type = SDATA;				break;			case SUNDEF:			case STEXT:			case SSTRING:			case SCONST:			case SLEAF:				instoffset = s->value + a->offset;				return C_LCON;			}			if(!dlm) {				instoffset = s->value + a->offset - BIG;				t = immrot(instoffset);				if(t && instoffset != 0)					return C_RECON;			}			instoffset = s->value + a->offset + INITDAT;			return C_LCON;		case D_AUTO:			instoffset = autosize + a->offset;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -