changelog shortlog tags branches changeset file revisions annotate raw help

Mercurial > hg > plan9front / sys/src/cmd/7l/asm.c

revision 7144: d0b9ab522e8b
child 7243: 34f64dcbbc25
     1.1new file mode 100644
     1.2--- /dev/null
     1.3+++ b/sys/src/cmd/7l/asm.c
     1.4@@ -0,0 +1,615 @@
     1.5+#include	"l.h"
     1.6+
     1.7+long	OFFSET;
     1.8+
     1.9+#define PADDR(a)	((a) & ~0xfffffffff0000000ull)
    1.10+
    1.11+vlong
    1.12+entryvalue(void)
    1.13+{
    1.14+	char *a;
    1.15+	Sym *s;
    1.16+
    1.17+	a = INITENTRY;
    1.18+	if(*a >= '0' && *a <= '9')
    1.19+		return atolwhex(a);
    1.20+	s = lookup(a, 0);
    1.21+	if(s->type == 0)
    1.22+		return INITTEXT;
    1.23+	switch(s->type) {
    1.24+	case STEXT:
    1.25+	case SLEAF:
    1.26+		break;
    1.27+	case SDATA:
    1.28+		if(dlm)
    1.29+			return s->value+INITDAT;
    1.30+	default:
    1.31+		diag("entry not text: %s", s->name);
    1.32+	}
    1.33+	return s->value;
    1.34+}
    1.35+
    1.36+void
    1.37+cflush(void)
    1.38+{
    1.39+	int n;
    1.40+
    1.41+	n = sizeof(buf.cbuf) - cbc;
    1.42+	if(n)
    1.43+		write(cout, buf.cbuf, n);
    1.44+	cbp = buf.cbuf;
    1.45+	cbc = sizeof(buf.cbuf);
    1.46+}
    1.47+
    1.48+void
    1.49+asmb(void)
    1.50+{
    1.51+	Prog *p;
    1.52+	long magic, t, etext;
    1.53+	vlong vl;
    1.54+	Optab *o;
    1.55+
    1.56+	if(debug['v'])
    1.57+		Bprint(&bso, "%5.2f asm\n", cputime());
    1.58+	Bflush(&bso);
    1.59+	OFFSET = HEADR;
    1.60+	seek(cout, OFFSET, 0);
    1.61+	pc = INITTEXT;
    1.62+	for(p = firstp; p != P; p = p->link) {
    1.63+		if(p->as == ATEXT) {
    1.64+			curtext = p;
    1.65+			autosize = p->to.offset + PCSZ;
    1.66+		}
    1.67+		if(p->as == ADWORD && (pc & 7) != 0) {
    1.68+			lputl(0);
    1.69+			pc += 4;
    1.70+		}
    1.71+		if(p->pc != pc) {
    1.72+			diag("phase error %llux sb %llux",
    1.73+				p->pc, pc);
    1.74+			if(!debug['a'])
    1.75+				prasm(curp);
    1.76+			pc = p->pc;
    1.77+		}
    1.78+		curp = p;
    1.79+		o = oplook(p);	/* could probably avoid this call */
    1.80+		asmout(p, o);
    1.81+		pc += o->size;
    1.82+	}
    1.83+
    1.84+	if(debug['a'])
    1.85+		Bprint(&bso, "\n");
    1.86+	Bflush(&bso);
    1.87+	cflush();
    1.88+
    1.89+	/* output strings in text segment */
    1.90+	etext = INITTEXT + textsize;
    1.91+	for(t = pc; t < etext; t += sizeof(buf)-100) {
    1.92+		if(etext-t > sizeof(buf)-100)
    1.93+			datblk(t, sizeof(buf)-100, 1);
    1.94+		else
    1.95+			datblk(t, etext-t, 1);
    1.96+	}
    1.97+
    1.98+	curtext = P;
    1.99+	switch(HEADTYPE) {
   1.100+	case 0:
   1.101+	case 2:
   1.102+	case 7:
   1.103+		OFFSET = HEADR+textsize;
   1.104+		seek(cout, OFFSET, 0);
   1.105+		break;
   1.106+	case 6:	/* no header, padded segments */
   1.107+		OFFSET = rnd(HEADR+textsize, 4096);
   1.108+		seek(cout, OFFSET, 0);
   1.109+		break;
   1.110+	}
   1.111+	if(dlm){
   1.112+		char buf[8];
   1.113+
   1.114+		write(cout, buf, INITDAT-textsize);
   1.115+		textsize = INITDAT;
   1.116+	}
   1.117+	for(t = 0; t < datsize; t += sizeof(buf)-100) {
   1.118+		if(datsize-t > sizeof(buf)-100)
   1.119+			datblk(t, sizeof(buf)-100, 0);
   1.120+		else
   1.121+			datblk(t, datsize-t, 0);
   1.122+	}
   1.123+
   1.124+	symsize = 0;
   1.125+	lcsize = 0;
   1.126+	if(!debug['s']) {
   1.127+		if(debug['v'])
   1.128+			Bprint(&bso, "%5.2f sym\n", cputime());
   1.129+		Bflush(&bso);
   1.130+		switch(HEADTYPE) {
   1.131+		case 0:
   1.132+			debug['s'] = 1;
   1.133+			break;
   1.134+		case 2:
   1.135+			OFFSET = HEADR+textsize+datsize;
   1.136+			seek(cout, OFFSET, 0);
   1.137+			break;
   1.138+		case 6:	/* no header, padded segments */
   1.139+			OFFSET += rnd(datsize, 4096);
   1.140+			seek(cout, OFFSET, 0);
   1.141+			break;
   1.142+		case 7:
   1.143+			break;
   1.144+		}
   1.145+		if(!debug['s'])
   1.146+			asmsym();
   1.147+		if(debug['v'])
   1.148+			Bprint(&bso, "%5.2f pc\n", cputime());
   1.149+		Bflush(&bso);
   1.150+		if(!debug['s'])
   1.151+			asmlc();
   1.152+		if(dlm)
   1.153+			asmdyn();
   1.154+		cflush();
   1.155+	}
   1.156+	else if(dlm){
   1.157+		seek(cout, HEADR+textsize+datsize, 0);
   1.158+		asmdyn();
   1.159+		cflush();
   1.160+	}
   1.161+
   1.162+	if(debug['v'])
   1.163+		Bprint(&bso, "%5.2f header\n", cputime());
   1.164+	Bflush(&bso);
   1.165+	OFFSET = 0;
   1.166+	seek(cout, OFFSET, 0);
   1.167+	switch(HEADTYPE) {
   1.168+	case 0:	/* no header */
   1.169+	case 6:	/* no header, padded segments */
   1.170+		break;
   1.171+	case 2:	/* plan 9 */
   1.172+		magic = 4*28*28+7;
   1.173+		magic |= 0x00008000;		/* fat header */
   1.174+		if(dlm)
   1.175+			magic |= 0x80000000;	/* dlm */
   1.176+		lput(magic);			/* magic */
   1.177+		lput(textsize);			/* sizes */
   1.178+		lput(datsize);
   1.179+		lput(bsssize);
   1.180+		lput(symsize);			/* nsyms */
   1.181+		vl = entryvalue();
   1.182+		lput(PADDR(vl));		/* va of entry */
   1.183+		lput(0L);
   1.184+		lput(lcsize);
   1.185+		llput(vl);			/* va of entry */
   1.186+		break;
   1.187+	}
   1.188+	cflush();
   1.189+}
   1.190+
   1.191+void
   1.192+cput(int c)
   1.193+{
   1.194+	cbp[0] = c;
   1.195+	cbp++;
   1.196+	cbc--;
   1.197+	if(cbc <= 0)
   1.198+		cflush();
   1.199+}
   1.200+
   1.201+void
   1.202+wput(long l)
   1.203+{
   1.204+
   1.205+	cbp[0] = l>>8;
   1.206+	cbp[1] = l;
   1.207+	cbp += 2;
   1.208+	cbc -= 2;
   1.209+	if(cbc <= 0)
   1.210+		cflush();
   1.211+}
   1.212+
   1.213+void
   1.214+wputl(long l)
   1.215+{
   1.216+
   1.217+	cbp[0] = l;
   1.218+	cbp[1] = l>>8;
   1.219+	cbp += 2;
   1.220+	cbc -= 2;
   1.221+	if(cbc <= 0)
   1.222+		cflush();
   1.223+}
   1.224+
   1.225+void
   1.226+lput(long l)
   1.227+{
   1.228+
   1.229+	cbp[0] = l>>24;
   1.230+	cbp[1] = l>>16;
   1.231+	cbp[2] = l>>8;
   1.232+	cbp[3] = l;
   1.233+	cbp += 4;
   1.234+	cbc -= 4;
   1.235+	if(cbc <= 0)
   1.236+		cflush();
   1.237+}
   1.238+
   1.239+void
   1.240+lputl(long l)
   1.241+{
   1.242+
   1.243+	cbp[3] = l>>24;
   1.244+	cbp[2] = l>>16;
   1.245+	cbp[1] = l>>8;
   1.246+	cbp[0] = l;
   1.247+	cbp += 4;
   1.248+	cbc -= 4;
   1.249+	if(cbc <= 0)
   1.250+		cflush();
   1.251+}
   1.252+
   1.253+void
   1.254+llput(vlong v)
   1.255+{
   1.256+	lput(v>>32);
   1.257+	lput(v);
   1.258+}
   1.259+
   1.260+void
   1.261+llputl(vlong v)
   1.262+{
   1.263+	lputl(v);
   1.264+	lputl(v>>32);
   1.265+}
   1.266+
   1.267+void
   1.268+asmsym(void)
   1.269+{
   1.270+	Prog *p;
   1.271+	Auto *a;
   1.272+	Sym *s;
   1.273+	int h;
   1.274+
   1.275+	s = lookup("etext", 0);
   1.276+	if(s->type == STEXT)
   1.277+		putsymb(s->name, 'T', s->value, s->version);
   1.278+
   1.279+	for(h=0; h<NHASH; h++)
   1.280+		for(s=hash[h]; s!=S; s=s->link)
   1.281+			switch(s->type) {
   1.282+			case SCONST:
   1.283+				putsymb(s->name, 'D', s->value, s->version);
   1.284+				continue;
   1.285+
   1.286+			case SDATA:
   1.287+				putsymb(s->name, 'D', s->value+INITDAT, s->version);
   1.288+				continue;
   1.289+
   1.290+			case SBSS:
   1.291+				putsymb(s->name, 'B', s->value+INITDAT, s->version);
   1.292+				continue;
   1.293+
   1.294+			case SSTRING:
   1.295+				putsymb(s->name, 'T', s->value, s->version);
   1.296+				continue;
   1.297+
   1.298+			case SFILE:
   1.299+				putsymb(s->name, 'f', s->value, s->version);
   1.300+				continue;
   1.301+			}
   1.302+
   1.303+	for(p=textp; p!=P; p=p->cond) {
   1.304+		s = p->from.sym;
   1.305+		if(s->type != STEXT && s->type != SLEAF)
   1.306+			continue;
   1.307+
   1.308+		/* filenames first */
   1.309+		for(a=p->to.autom; a; a=a->link)
   1.310+			if(a->type == D_FILE)
   1.311+				putsymb(a->asym->name, 'z', a->aoffset, 0);
   1.312+			else
   1.313+			if(a->type == D_FILE1)
   1.314+				putsymb(a->asym->name, 'Z', a->aoffset, 0);
   1.315+
   1.316+		if(s->type == STEXT)
   1.317+			putsymb(s->name, 'T', s->value, s->version);
   1.318+		else
   1.319+			putsymb(s->name, 'L', s->value, s->version);
   1.320+
   1.321+		/* frame, auto and param after */
   1.322+		putsymb(".frame", 'm', p->to.offset+PCSZ, 0);
   1.323+		for(a=p->to.autom; a; a=a->link)
   1.324+			if(a->type == D_AUTO)
   1.325+				putsymb(a->asym->name, 'a', -a->aoffset, 0);
   1.326+			else
   1.327+			if(a->type == D_PARAM)
   1.328+				putsymb(a->asym->name, 'p', a->aoffset, 0);
   1.329+	}
   1.330+	if(debug['v'] || debug['n'])
   1.331+		Bprint(&bso, "symsize = %lud\n", symsize);
   1.332+	Bflush(&bso);
   1.333+}
   1.334+
   1.335+void
   1.336+putsymb(char *s, int t, vlong v, int ver)
   1.337+{
   1.338+	int i, f, l;
   1.339+
   1.340+	if(t == 'f')
   1.341+		s++;
   1.342+	l = 4;
   1.343+	switch(HEADTYPE){
   1.344+	default:
   1.345+		break;
   1.346+	case 2:
   1.347+		lput(v>>32);
   1.348+		l = 8;
   1.349+		break;
   1.350+	}
   1.351+	lput(v);
   1.352+	if(ver)
   1.353+		t += 'a' - 'A';
   1.354+	cput(t+0x80);			/* 0x80 is variable length */
   1.355+
   1.356+	if(t == 'Z' || t == 'z') {
   1.357+		cput(s[0]);
   1.358+		for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
   1.359+			cput(s[i]);
   1.360+			cput(s[i+1]);
   1.361+		}
   1.362+		cput(0);
   1.363+		cput(0);
   1.364+		i++;
   1.365+	}
   1.366+	else {
   1.367+		for(i=0; s[i]; i++)
   1.368+			cput(s[i]);
   1.369+		cput(0);
   1.370+	}
   1.371+	symsize += l + 1 + i + 1;
   1.372+
   1.373+	if(debug['n']) {
   1.374+		if(t == 'z' || t == 'Z') {
   1.375+			Bprint(&bso, "%c %.8llux ", t, v);
   1.376+			for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) {
   1.377+				f = ((s[i]&0xff) << 8) | (s[i+1]&0xff);
   1.378+				Bprint(&bso, "/%x", f);
   1.379+			}
   1.380+			Bprint(&bso, "\n");
   1.381+			return;
   1.382+		}
   1.383+		if(ver)
   1.384+			Bprint(&bso, "%c %.8llux %s<%d>\n", t, v, s, ver);
   1.385+		else
   1.386+			Bprint(&bso, "%c %.8llux %s\n", t, v, s);
   1.387+	}
   1.388+}
   1.389+
   1.390+#define	MINLC	4
   1.391+void
   1.392+asmlc(void)
   1.393+{
   1.394+	long oldpc, oldlc;
   1.395+	Prog *p;
   1.396+	long v, s;
   1.397+
   1.398+	oldpc = INITTEXT;
   1.399+	oldlc = 0;
   1.400+	for(p = firstp; p != P; p = p->link) {
   1.401+		if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {
   1.402+			if(p->as == ATEXT)
   1.403+				curtext = p;
   1.404+			if(debug['V'])
   1.405+				Bprint(&bso, "%6llux %P\n",
   1.406+					p->pc, p);
   1.407+			continue;
   1.408+		}
   1.409+		if(debug['V'])
   1.410+			Bprint(&bso, "\t\t%6ld", lcsize);
   1.411+		v = (p->pc - oldpc) / MINLC;
   1.412+		while(v) {
   1.413+			s = 127;
   1.414+			if(v < 127)
   1.415+				s = v;
   1.416+			cput(s+128);	/* 129-255 +pc */
   1.417+			if(debug['V'])
   1.418+				Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128);
   1.419+			v -= s;
   1.420+			lcsize++;
   1.421+		}
   1.422+		s = p->line - oldlc;
   1.423+		oldlc = p->line;
   1.424+		oldpc = p->pc + MINLC;
   1.425+		if(s > 64 || s < -64) {
   1.426+			cput(0);	/* 0 vv +lc */
   1.427+			cput(s>>24);
   1.428+			cput(s>>16);
   1.429+			cput(s>>8);
   1.430+			cput(s);
   1.431+			if(debug['V']) {
   1.432+				if(s > 0)
   1.433+					Bprint(&bso, " lc+%ld(%d,%ld)\n",
   1.434+						s, 0, s);
   1.435+				else
   1.436+					Bprint(&bso, " lc%ld(%d,%ld)\n",
   1.437+						s, 0, s);
   1.438+				Bprint(&bso, "%6llux %P\n",
   1.439+					p->pc, p);
   1.440+			}
   1.441+			lcsize += 5;
   1.442+			continue;
   1.443+		}
   1.444+		if(s > 0) {
   1.445+			cput(0+s);	/* 1-64 +lc */
   1.446+			if(debug['V']) {
   1.447+				Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s);
   1.448+				Bprint(&bso, "%6llux %P\n",
   1.449+					p->pc, p);
   1.450+			}
   1.451+		} else {
   1.452+			cput(64-s);	/* 65-128 -lc */
   1.453+			if(debug['V']) {
   1.454+				Bprint(&bso, " lc%ld(%ld)\n", s, 64-s);
   1.455+				Bprint(&bso, "%6llux %P\n",
   1.456+					p->pc, p);
   1.457+			}
   1.458+		}
   1.459+		lcsize++;
   1.460+	}
   1.461+	while(lcsize & 1) {
   1.462+		s = 129;
   1.463+		cput(s);
   1.464+		lcsize++;
   1.465+	}
   1.466+	if(debug['v'] || debug['V'])
   1.467+		Bprint(&bso, "lcsize = %ld\n", lcsize);
   1.468+	Bflush(&bso);
   1.469+}
   1.470+
   1.471+void
   1.472+datblk(long s, long n, int str)
   1.473+{
   1.474+	Sym *v;
   1.475+	Prog *p;
   1.476+	char *cast;
   1.477+	long a, l, fl, j;
   1.478+	vlong d;
   1.479+	int i, c;
   1.480+
   1.481+	memset(buf.dbuf, 0, n+100);
   1.482+	for(p = datap; p != P; p = p->link) {
   1.483+		if(str != (p->from.sym->type == SSTRING))
   1.484+			continue;
   1.485+		curp = p;
   1.486+		a = p->from.sym->value + p->from.offset;
   1.487+		l = a - s;
   1.488+		c = p->reg;
   1.489+		i = 0;
   1.490+		if(l < 0) {
   1.491+			if(l+c <= 0)
   1.492+				continue;
   1.493+			while(l < 0) {
   1.494+				l++;
   1.495+				i++;
   1.496+			}
   1.497+		}
   1.498+		if(l >= n)
   1.499+			continue;
   1.500+		if(p->as != AINIT && p->as != ADYNT) {
   1.501+			for(j=l+(c-i)-1; j>=l; j--)
   1.502+				if(buf.dbuf[j]) {
   1.503+					print("%P\n", p);
   1.504+					diag("multiple initialization");
   1.505+					break;
   1.506+				}
   1.507+		}
   1.508+		switch(p->to.type) {
   1.509+		default:
   1.510+			diag("unknown mode in initialization%P", p);
   1.511+			break;
   1.512+
   1.513+		case D_FCONST:
   1.514+			switch(c) {
   1.515+			default:
   1.516+			case 4:
   1.517+				fl = ieeedtof(p->to.ieee);
   1.518+				cast = (char*)&fl;
   1.519+				for(; i<c; i++) {
   1.520+					buf.dbuf[l] = cast[fnuxi4[i]];
   1.521+					l++;
   1.522+				}
   1.523+				break;
   1.524+			case 8:
   1.525+				cast = (char*)p->to.ieee;
   1.526+				for(; i<c; i++) {
   1.527+					buf.dbuf[l] = cast[fnuxi8[i]];
   1.528+					l++;
   1.529+				}
   1.530+				break;
   1.531+			}
   1.532+			break;
   1.533+
   1.534+		case D_SCONST:
   1.535+			for(; i<c; i++) {
   1.536+				buf.dbuf[l] = p->to.sval[i];
   1.537+				l++;
   1.538+			}
   1.539+			break;
   1.540+
   1.541+		case D_CONST:
   1.542+			d = p->to.offset;
   1.543+			v = p->to.sym;
   1.544+			if(v) {
   1.545+				switch(v->type) {
   1.546+				case SUNDEF:
   1.547+					ckoff(v, d);
   1.548+				case STEXT:
   1.549+				case SLEAF:
   1.550+				case SSTRING:
   1.551+					d += p->to.sym->value;
   1.552+					break;
   1.553+				case SDATA:
   1.554+				case SBSS:
   1.555+					d += p->to.sym->value + INITDAT;
   1.556+				}
   1.557+				if(dlm)
   1.558+					dynreloc(v, a+INITDAT, 1);
   1.559+			}
   1.560+			cast = (char*)&d;
   1.561+			switch(c) {
   1.562+			default:
   1.563+				diag("bad nuxi %d %d%P", c, i, curp);
   1.564+				break;
   1.565+			case 1:
   1.566+				for(; i<c; i++) {
   1.567+					buf.dbuf[l] = cast[inuxi1[i]];
   1.568+					l++;
   1.569+				}
   1.570+				break;
   1.571+			case 2:
   1.572+				for(; i<c; i++) {
   1.573+					buf.dbuf[l] = cast[inuxi2[i]];
   1.574+					l++;
   1.575+				}
   1.576+				break;
   1.577+			case 4:
   1.578+				for(; i<c; i++) {
   1.579+					buf.dbuf[l] = cast[inuxi4[i]];
   1.580+					l++;
   1.581+				}
   1.582+				break;
   1.583+			case 8:
   1.584+				for(; i<c; i++) {
   1.585+					buf.dbuf[l] = cast[inuxi8[i]];
   1.586+					l++;
   1.587+				}
   1.588+				break;
   1.589+			}
   1.590+			break;
   1.591+		}
   1.592+	}
   1.593+	write(cout, buf.dbuf, n);
   1.594+}
   1.595+
   1.596+static Ieee chipfloats[] = {
   1.597+	{0x00000000, 0x00000000}, /* 0 */
   1.598+	{0x00000000, 0x3ff00000}, /* 1 */
   1.599+	{0x00000000, 0x40000000}, /* 2 */
   1.600+	{0x00000000, 0x40080000}, /* 3 */
   1.601+	{0x00000000, 0x40100000}, /* 4 */
   1.602+	{0x00000000, 0x40140000}, /* 5 */
   1.603+	{0x00000000, 0x3fe00000}, /* .5 */
   1.604+	{0x00000000, 0x40240000}, /* 10 */
   1.605+};
   1.606+
   1.607+int
   1.608+chipfloat(Ieee *e)
   1.609+{
   1.610+	Ieee *p;
   1.611+	int n;
   1.612+
   1.613+	for(n = sizeof(chipfloats)/sizeof(chipfloats[0]); --n >= 0;){
   1.614+		p = &chipfloats[n];
   1.615+		if(p->l == e->l && p->h == e->h && 0)
   1.616+			return n;		/* TO DO: return imm8 encoding */
   1.617+	}
   1.618+	return -1;
   1.619+}