changelog shortlog tags branches changeset file revisions annotate raw help

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

revision 0: eaccc3e8d226
child 4275: d1102fefd6c1
     1.1new file mode 100755
     1.2--- /dev/null
     1.3+++ b/sys/src/cmd/7l/obj.c
     1.4@@ -0,0 +1,1352 @@
     1.5+#include	"l.h"
     1.6+#include	<ar.h>
     1.7+
     1.8+#ifndef	DEFAULT
     1.9+#define	DEFAULT	'9'
    1.10+#endif
    1.11+
    1.12+char	*noname		= "<none>";
    1.13+char	symname[]	= SYMDEF;
    1.14+char	thechar		= '7';
    1.15+char	*thestring 	= "alpha";
    1.16+
    1.17+/*
    1.18+ *	-H0 -T0x12000004C -D0x140000000	is abbrev unix
    1.19+ *	-H1 -T0x20000000 -R4		is bootp() format
    1.20+ *	-H2 -T8224 -R8192		is plan9 format
    1.21+ */
    1.22+
    1.23+void
    1.24+main(int argc, char *argv[])
    1.25+{
    1.26+	int c;
    1.27+	char *a;
    1.28+
    1.29+	Binit(&bso, 1, OWRITE);
    1.30+	cout = -1;
    1.31+	listinit();
    1.32+	outfile = 0;
    1.33+	nerrors = 0;
    1.34+	curtext = P;
    1.35+	HEADTYPE = -1;
    1.36+	INITTEXT = -1;
    1.37+	INITDAT = -1;
    1.38+	INITRND = -1;
    1.39+	INITENTRY = 0;
    1.40+
    1.41+	ARGBEGIN {
    1.42+	default:
    1.43+		c = ARGC();
    1.44+		if(c >= 0 && c < sizeof(debug))
    1.45+			debug[c]++;
    1.46+		break;
    1.47+	case 'o':
    1.48+		outfile = ARGF();
    1.49+		break;
    1.50+	case 'E':
    1.51+		a = ARGF();
    1.52+		if(a)
    1.53+			INITENTRY = a;
    1.54+		break;
    1.55+	case 'T':
    1.56+		a = ARGF();
    1.57+		if(a)
    1.58+			INITTEXT = atolwhex(a);
    1.59+		break;
    1.60+	case 'D':
    1.61+		a = ARGF();
    1.62+		if(a)
    1.63+			INITDAT = atolwhex(a);
    1.64+		break;
    1.65+	case 'R':
    1.66+		a = ARGF();
    1.67+		if(a)
    1.68+			INITRND = atolwhex(a);
    1.69+		break;
    1.70+	case 'H':
    1.71+		a = ARGF();
    1.72+		if(a)
    1.73+			HEADTYPE = atolwhex(a);
    1.74+		/* do something about setting INITTEXT */
    1.75+		break;
    1.76+	} ARGEND
    1.77+
    1.78+	USED(argc);
    1.79+
    1.80+	if(*argv == 0) {
    1.81+		diag("usage: 7l [-options] objects");
    1.82+		errorexit();
    1.83+	}
    1.84+	if(!debug['9'] && !debug['B'] && !debug['U'])
    1.85+		debug[DEFAULT] = 1;
    1.86+	if(HEADTYPE == -1) {
    1.87+		if(debug['U'])
    1.88+			HEADTYPE = 0;
    1.89+		if(debug['B'])
    1.90+			HEADTYPE = 1;
    1.91+		if(debug['9'])
    1.92+			HEADTYPE = 2;
    1.93+	}
    1.94+	switch(HEADTYPE) {
    1.95+	default:
    1.96+		diag("unknown -H option");
    1.97+		errorexit();
    1.98+
    1.99+	case 0:	/* unix simple */
   1.100+		HEADR = 32L+80L;
   1.101+		if(INITTEXT == -1)
   1.102+			INITTEXT = 0x120000070LL;		/* BUG */
   1.103+		if(INITDAT == -1)
   1.104+			INITDAT = 0x140000000LL;		/* BUG */
   1.105+		if(INITRND == -1)
   1.106+			INITRND = 0;
   1.107+		break;
   1.108+
   1.109+	case 1:	/* boot */
   1.110+		HEADR = 32L+84L;
   1.111+		if(INITTEXT == -1)
   1.112+			INITTEXT = 0x20000074L;
   1.113+		if(INITDAT == -1)
   1.114+			INITDAT = 0;
   1.115+		if(INITRND == -1)
   1.116+			INITRND = 8;
   1.117+		break;
   1.118+	case 2:	/* plan 9 */
   1.119+		HEADR = 32L;
   1.120+		if(INITTEXT == -1)
   1.121+			INITTEXT = 8224;
   1.122+		if(INITDAT == -1)
   1.123+			INITDAT = 0;
   1.124+		if(INITRND == -1)
   1.125+			INITRND = 8192;
   1.126+		break;
   1.127+	case 3:	/* ``headerless'' tftp boot -- uses branch as magic */
   1.128+		HEADR = 32L;
   1.129+		if(INITTEXT == -1)
   1.130+			INITTEXT = 0x20000020L;
   1.131+		if(INITDAT == -1)
   1.132+			INITDAT = 0;
   1.133+		if(INITRND == -1)
   1.134+			INITRND = 8;
   1.135+		break;
   1.136+	}
   1.137+	if(INITDAT != 0 && INITRND != 0)
   1.138+		print("warning: -D0x%lux is ignored because of -R0x%lux\n",
   1.139+			INITDAT, INITRND);
   1.140+	if(debug['v'])
   1.141+		Bprint(&bso, "HEADER = -H0x%d -T0x%lux -D0x%lux -R0x%lux\n",
   1.142+			HEADTYPE, INITTEXT, INITDAT, INITRND);
   1.143+	Bflush(&bso);
   1.144+	zprg.as = AGOK;
   1.145+	zprg.reg = NREG;
   1.146+	zprg.from.name = D_NONE;
   1.147+	zprg.from.type = D_NONE;
   1.148+	zprg.from.reg = NREG;
   1.149+	zprg.to = zprg.from;
   1.150+	buildop();
   1.151+	histgen = 0;
   1.152+	textp = P;
   1.153+	datap = P;
   1.154+	pc = 0;
   1.155+	dtype = 4;
   1.156+	if(outfile == 0)
   1.157+		outfile = "7.out";
   1.158+	cout = create(outfile, 1, 0775);
   1.159+	if(cout < 0) {
   1.160+		diag("%s: cannot create", outfile);
   1.161+		errorexit();
   1.162+	}
   1.163+	nuxiinit();
   1.164+
   1.165+	version = 0;
   1.166+	cbp = buf.cbuf;
   1.167+	cbc = sizeof(buf.cbuf);
   1.168+	firstp = prg();
   1.169+	lastp = firstp;
   1.170+
   1.171+	if(INITENTRY == 0) {
   1.172+		INITENTRY = "_main";
   1.173+		if(debug['p'])
   1.174+			INITENTRY = "_mainp";
   1.175+		if(!debug['l'])
   1.176+			lookup(INITENTRY, 0)->type = SXREF;
   1.177+	} else
   1.178+		lookup(INITENTRY, 0)->type = SXREF;
   1.179+
   1.180+	while(*argv)
   1.181+		objfile(*argv++);
   1.182+	if(!debug['l'])
   1.183+		loadlib();
   1.184+	firstp = firstp->link;
   1.185+	if(firstp == P)
   1.186+		goto out;
   1.187+	patch();
   1.188+	if(debug['p'])
   1.189+		if(debug['1'])
   1.190+			doprof1();
   1.191+		else
   1.192+			doprof2();
   1.193+	follow();
   1.194+	if(firstp == P)
   1.195+		goto out;
   1.196+	noops();
   1.197+	dodata();		/* is before follow() on other arch */
   1.198+	span();
   1.199+	asmb();
   1.200+	undef();
   1.201+
   1.202+out:
   1.203+	if(debug['v']) {
   1.204+		Bprint(&bso, "%5.2f cpu time\n", cputime());
   1.205+		Bprint(&bso, "%ld memory used\n", thunk);
   1.206+		Bprint(&bso, "%d sizeof adr\n", sizeof(Adr));
   1.207+		Bprint(&bso, "%d sizeof prog\n", sizeof(Prog));
   1.208+	}
   1.209+	Bflush(&bso);
   1.210+	errorexit();
   1.211+}
   1.212+
   1.213+void
   1.214+loadlib(void)
   1.215+{
   1.216+	int i;
   1.217+	long h;
   1.218+	Sym *s;
   1.219+
   1.220+loop:
   1.221+	xrefresolv = 0;
   1.222+	for(i=0; i<libraryp; i++) {
   1.223+		if(debug['v'])
   1.224+			Bprint(&bso, "%5.2f autolib: %s\n", cputime(), library[i]);
   1.225+		objfile(library[i]);
   1.226+	}
   1.227+	if(xrefresolv)
   1.228+	for(h=0; h<nelem(hash); h++)
   1.229+	for(s = hash[h]; s != S; s = s->link)
   1.230+		if(s->type == SXREF)
   1.231+			goto loop;
   1.232+}
   1.233+
   1.234+void
   1.235+errorexit(void)
   1.236+{
   1.237+
   1.238+	Bflush(&bso);
   1.239+	if(nerrors) {
   1.240+		if(cout >= 0)
   1.241+			remove(outfile);
   1.242+		exits("error");
   1.243+	}
   1.244+	exits(0);
   1.245+}
   1.246+
   1.247+void
   1.248+objfile(char *file)
   1.249+{
   1.250+	long off, esym, cnt, l;
   1.251+	int f, work;
   1.252+	Sym *s;
   1.253+	char magbuf[SARMAG];
   1.254+	char name[100], pname[150];
   1.255+	struct ar_hdr arhdr;
   1.256+	char *e, *start, *stop;
   1.257+
   1.258+	if(file[0] == '-' && file[1] == 'l') {
   1.259+		if(debug['9'])
   1.260+			sprint(name, "/%s/lib/lib", thestring);
   1.261+		else
   1.262+			sprint(name, "/usr/%clib/lib", thechar);
   1.263+		strcat(name, file+2);
   1.264+		strcat(name, ".a");
   1.265+		file = name;
   1.266+	}
   1.267+	if(debug['v'])
   1.268+		Bprint(&bso, "%5.2f ldobj: %s\n", cputime(), file);
   1.269+	Bflush(&bso);
   1.270+	f = open(file, 0);
   1.271+	if(f < 0) {
   1.272+		diag("cannot open file: %s", file);
   1.273+		errorexit();
   1.274+	}
   1.275+	l = read(f, magbuf, SARMAG);
   1.276+	if(l != SARMAG || strncmp(magbuf, ARMAG, SARMAG)){
   1.277+		/* load it as a regular file */
   1.278+		l = seek(f, 0L, 2);
   1.279+		seek(f, 0L, 0);
   1.280+		ldobj(f, l, file);
   1.281+		close(f);
   1.282+		return;
   1.283+	}
   1.284+
   1.285+	if(debug['v'])
   1.286+		Bprint(&bso, "%5.2f ldlib: %s\n", cputime(), file);
   1.287+	l = read(f, &arhdr, SAR_HDR);
   1.288+	if(l != SAR_HDR) {
   1.289+		diag("%s: short read on archive file symbol header", file);
   1.290+		goto out;
   1.291+	}
   1.292+	if(strncmp(arhdr.name, symname, strlen(symname))) {
   1.293+		diag("%s: first entry not symbol header", file);
   1.294+		goto out;
   1.295+	}
   1.296+
   1.297+	esym = SARMAG + SAR_HDR + atolwhex(arhdr.size);
   1.298+	off = SARMAG + SAR_HDR;
   1.299+
   1.300+	/*
   1.301+	 * just bang the whole symbol file into memory
   1.302+	 */
   1.303+	seek(f, off, 0);
   1.304+	cnt = esym - off;
   1.305+	start = malloc(cnt + 10);
   1.306+	cnt = read(f, start, cnt);
   1.307+	if(cnt <= 0){
   1.308+		close(f);
   1.309+		return;
   1.310+	}
   1.311+	stop = &start[cnt];
   1.312+	memset(stop, 0, 10);
   1.313+
   1.314+	work = 1;
   1.315+	while(work){
   1.316+		if(debug['v'])
   1.317+			Bprint(&bso, "%5.2f library pass: %s\n", cputime(), file);
   1.318+		Bflush(&bso);
   1.319+		work = 0;
   1.320+		for(e = start; e < stop; e = strchr(e+5, 0) + 1) {
   1.321+			s = lookup(e+5, 0);
   1.322+			if(s->type != SXREF)
   1.323+				continue;
   1.324+			sprint(pname, "%s(%s)", file, s->name);
   1.325+			if(debug['v'])
   1.326+				Bprint(&bso, "%5.2f library: %s\n", cputime(), pname);
   1.327+			Bflush(&bso);
   1.328+			l = e[1] & 0xff;
   1.329+			l |= (e[2] & 0xff) << 8;
   1.330+			l |= (e[3] & 0xff) << 16;
   1.331+			l |= (e[4] & 0xff) << 24;
   1.332+			seek(f, l, 0);
   1.333+			l = read(f, &arhdr, SAR_HDR);
   1.334+			if(l != SAR_HDR)
   1.335+				goto bad;
   1.336+			if(strncmp(arhdr.fmag, ARFMAG, sizeof(arhdr.fmag)))
   1.337+				goto bad;
   1.338+			l = atolwhex(arhdr.size);
   1.339+			ldobj(f, l, pname);
   1.340+			if(s->type == SXREF) {
   1.341+				diag("%s: failed to load: %s", file, s->name);
   1.342+				errorexit();
   1.343+			}
   1.344+			work = 1;
   1.345+			xrefresolv = 1;
   1.346+		}
   1.347+	}
   1.348+	return;
   1.349+
   1.350+bad:
   1.351+	diag("%s: bad or out of date archive", file);
   1.352+out:
   1.353+	close(f);
   1.354+}
   1.355+
   1.356+int
   1.357+zaddr(uchar *p, Adr *a, Sym *h[])
   1.358+{
   1.359+	int i, c;
   1.360+	vlong l;
   1.361+	Sym *s;
   1.362+	Auto *u;
   1.363+
   1.364+	c = p[2];
   1.365+	if(c < 0 || c > NSYM){
   1.366+		print("sym out of range: %d\n", c);
   1.367+		p[0] = ALAST+1;
   1.368+		return 0;
   1.369+	}
   1.370+	a->type = p[0];
   1.371+	a->reg = p[1];
   1.372+	a->sym = h[p[2]];
   1.373+	a->name = p[3];
   1.374+	c = 4;
   1.375+
   1.376+	if(a->reg < 0 || a->reg > NREG) {
   1.377+		print("register out of range %d\n", a->reg);
   1.378+		p[0] = ALAST+1;
   1.379+		return 0;	/*  force real diagnostic */
   1.380+	}
   1.381+
   1.382+	switch(a->type) {
   1.383+	default:
   1.384+		print("unknown type %d\n", a->type);
   1.385+		p[0] = ALAST+1;
   1.386+		return 0;	/*  force real diagnostic */
   1.387+
   1.388+	case D_NONE:
   1.389+	case D_REG:
   1.390+	case D_FREG:
   1.391+	case D_PREG:
   1.392+	case D_FCREG:
   1.393+	case D_PCC:
   1.394+		break;
   1.395+
   1.396+	case D_BRANCH:
   1.397+	case D_OREG:
   1.398+	case D_CONST:
   1.399+		a->offset = (uvlong)p[4] | ((uvlong)p[5]<<8L) |
   1.400+			((uvlong) p[6]<<16L) | ((uvlong) p[7]<<24L) |
   1.401+			((uvlong) p[8]<<32L) | ((uvlong) p[9]<<40L) |
   1.402+			((uvlong) p[10]<<48L) | ((uvlong) p[11]<<56L);
   1.403+		c += 8;
   1.404+		break;
   1.405+
   1.406+	case D_SCONST:
   1.407+		while(nhunk < NSNAME)
   1.408+			gethunk();
   1.409+		a->sval = (char*)hunk;
   1.410+		nhunk -= NSNAME;
   1.411+		hunk += NSNAME;
   1.412+
   1.413+		memmove(a->sval, p+4, NSNAME);
   1.414+		c += NSNAME;
   1.415+		break;
   1.416+
   1.417+	case D_FCONST:
   1.418+		while(nhunk < sizeof(Ieee))
   1.419+			gethunk();
   1.420+		a->ieee = (Ieee*)hunk;
   1.421+		nhunk -= sizeof(Ieee);
   1.422+		hunk += sizeof(Ieee);
   1.423+
   1.424+		a->ieee->l = p[4] | (p[5]<<8) |
   1.425+			(p[6]<<16) | (p[7]<<24);
   1.426+		a->ieee->h = p[8] | (p[9]<<8) |
   1.427+			(p[10]<<16) | (p[11]<<24);
   1.428+		c += 8;
   1.429+		break;
   1.430+	}
   1.431+	s = a->sym;
   1.432+	if(s == S)
   1.433+		return c;
   1.434+	i = a->name;
   1.435+	if(i != D_AUTO && i != D_PARAM)
   1.436+		return c;
   1.437+
   1.438+	l = a->offset;
   1.439+	for(u=curauto; u; u=u->link)
   1.440+		if(u->sym == s)
   1.441+		if(u->type == i) {
   1.442+			if(u->offset > l)
   1.443+				u->offset = l;
   1.444+			return c;
   1.445+		}
   1.446+
   1.447+	while(nhunk < sizeof(Auto))
   1.448+		gethunk();
   1.449+	u = (Auto*)hunk;
   1.450+	nhunk -= sizeof(Auto);
   1.451+	hunk += sizeof(Auto);
   1.452+
   1.453+	u->link = curauto;
   1.454+	curauto = u;
   1.455+	u->sym = s;
   1.456+	u->offset = l;
   1.457+	u->type = i;
   1.458+	return c;
   1.459+}
   1.460+
   1.461+void
   1.462+addlib(char *obj)
   1.463+{
   1.464+	char name[1024], comp[256], *p;
   1.465+	int i;
   1.466+
   1.467+	if(histfrogp <= 0)
   1.468+		return;
   1.469+
   1.470+	if(histfrog[0]->name[1] == '/') {
   1.471+		sprint(name, "");
   1.472+		i = 1;
   1.473+	} else
   1.474+	if(histfrog[0]->name[1] == '.') {
   1.475+		sprint(name, ".");
   1.476+		i = 0;
   1.477+	} else {
   1.478+		if(debug['9'])
   1.479+			sprint(name, "/%s/lib", thestring);
   1.480+		else
   1.481+			sprint(name, "/usr/%clib", thechar);
   1.482+		i = 0;
   1.483+	}
   1.484+
   1.485+	for(; i<histfrogp; i++) {
   1.486+		snprint(comp, sizeof comp, histfrog[i]->name+1);
   1.487+		for(;;) {
   1.488+			p = strstr(comp, "$O");
   1.489+			if(p == 0)
   1.490+				break;
   1.491+			memmove(p+1, p+2, strlen(p+2)+1);
   1.492+			p[0] = thechar;
   1.493+		}
   1.494+		for(;;) {
   1.495+			p = strstr(comp, "$M");
   1.496+			if(p == 0)
   1.497+				break;
   1.498+			if(strlen(comp)+strlen(thestring)-2+1 >= sizeof comp) {
   1.499+				diag("library component too long");
   1.500+				return;
   1.501+			}
   1.502+			memmove(p+strlen(thestring), p+2, strlen(p+2)+1);
   1.503+			memmove(p, thestring, strlen(thestring));
   1.504+		}
   1.505+		if(strlen(name) + strlen(comp) + 3 >= sizeof(name)) {
   1.506+			diag("library component too long");
   1.507+			return;
   1.508+		}
   1.509+		strcat(name, "/");
   1.510+		strcat(name, comp);
   1.511+	}
   1.512+	for(i=0; i<libraryp; i++)
   1.513+		if(strcmp(name, library[i]) == 0)
   1.514+			return;
   1.515+	if(libraryp == nelem(library)){
   1.516+		diag("too many autolibs; skipping %s", name);
   1.517+		return;
   1.518+	}
   1.519+
   1.520+	p = malloc(strlen(name) + 1);
   1.521+	strcpy(p, name);
   1.522+	library[libraryp] = p;
   1.523+	p = malloc(strlen(obj) + 1);
   1.524+	strcpy(p, obj);
   1.525+	libraryobj[libraryp] = p;
   1.526+	libraryp++;
   1.527+}
   1.528+
   1.529+void
   1.530+addhist(long line, int type)
   1.531+{
   1.532+	Auto *u;
   1.533+	Sym *s;
   1.534+	int i, j, k;
   1.535+
   1.536+	u = malloc(sizeof(Auto));
   1.537+	s = malloc(sizeof(Sym));
   1.538+	s->name = malloc(2*(histfrogp+1) + 1);
   1.539+
   1.540+	u->sym = s;
   1.541+	u->type = type;
   1.542+	u->offset = line;
   1.543+	u->link = curhist;
   1.544+	curhist = u;
   1.545+
   1.546+	j = 1;
   1.547+	for(i=0; i<histfrogp; i++) {
   1.548+		k = histfrog[i]->value;
   1.549+		s->name[j+0] = k>>8;
   1.550+		s->name[j+1] = k;
   1.551+		j += 2;
   1.552+	}
   1.553+}
   1.554+
   1.555+void
   1.556+histtoauto(void)
   1.557+{
   1.558+	Auto *l;
   1.559+
   1.560+	while(l = curhist) {
   1.561+		curhist = l->link;
   1.562+		l->link = curauto;
   1.563+		curauto = l;
   1.564+	}
   1.565+}
   1.566+
   1.567+void
   1.568+collapsefrog(Sym *s)
   1.569+{
   1.570+	int i;
   1.571+
   1.572+	/*
   1.573+	 * bad encoding of path components only allows
   1.574+	 * MAXHIST components. if there is an overflow,
   1.575+	 * first try to collapse xxx/..
   1.576+	 */
   1.577+	for(i=1; i<histfrogp; i++)
   1.578+		if(strcmp(histfrog[i]->name+1, "..") == 0) {
   1.579+			memmove(histfrog+i-1, histfrog+i+1,
   1.580+				(histfrogp-i-1)*sizeof(histfrog[0]));
   1.581+			histfrogp--;
   1.582+			goto out;
   1.583+		}
   1.584+
   1.585+	/*
   1.586+	 * next try to collapse .
   1.587+	 */
   1.588+	for(i=0; i<histfrogp; i++)
   1.589+		if(strcmp(histfrog[i]->name+1, ".") == 0) {
   1.590+			memmove(histfrog+i, histfrog+i+1,
   1.591+				(histfrogp-i-1)*sizeof(histfrog[0]));
   1.592+			goto out;
   1.593+		}
   1.594+
   1.595+	/*
   1.596+	 * last chance, just truncate from front
   1.597+	 */
   1.598+	memmove(histfrog+0, histfrog+1,
   1.599+		(histfrogp-1)*sizeof(histfrog[0]));
   1.600+
   1.601+out:
   1.602+	histfrog[histfrogp-1] = s;
   1.603+}
   1.604+
   1.605+void
   1.606+nopout(Prog *p)
   1.607+{
   1.608+	p->as = ANOP;
   1.609+	p->from.type = D_NONE;
   1.610+	p->to.type = D_NONE;
   1.611+}
   1.612+
   1.613+uchar*
   1.614+readsome(int f, uchar *buf, uchar *good, uchar *stop, int max)
   1.615+{
   1.616+	int n;
   1.617+
   1.618+	n = stop - good;
   1.619+	memmove(buf, good, stop - good);
   1.620+	stop = buf + n;
   1.621+	n = MAXIO - n;
   1.622+	if(n > max)
   1.623+		n = max;
   1.624+	n = read(f, stop, n);
   1.625+	if(n <= 0)
   1.626+		return 0;
   1.627+	return stop + n;
   1.628+}
   1.629+
   1.630+void
   1.631+ldobj(int f, long c, char *pn)
   1.632+{
   1.633+	long ipc;
   1.634+	Prog *p, *t;
   1.635+	uchar *bloc, *bsize, *stop;
   1.636+	Sym *h[NSYM], *s, *di;
   1.637+	int v, o, r, skip;
   1.638+
   1.639+	bsize = buf.xbuf;
   1.640+	bloc = buf.xbuf;
   1.641+	di = S;
   1.642+
   1.643+newloop:
   1.644+	memset(h, 0, sizeof(h));
   1.645+	version++;
   1.646+	histfrogp = 0;
   1.647+	ipc = pc;
   1.648+	skip = 0;
   1.649+
   1.650+loop:
   1.651+	if(c <= 0)
   1.652+		goto eof;
   1.653+	r = bsize - bloc;
   1.654+	if(r < 100 && r < c) {		/* enough for largest prog */
   1.655+		bsize = readsome(f, buf.xbuf, bloc, bsize, c);
   1.656+		if(bsize == 0)
   1.657+			goto eof;
   1.658+		bloc = buf.xbuf;
   1.659+		goto loop;
   1.660+	}
   1.661+	o = bloc[0];		/* as */
   1.662+	if(o <= AXXX || o >= ALAST) {
   1.663+		diag("%s: line %ld: opcode out of range %d", pn, pc-ipc, o);
   1.664+		print("	probably not a .7 file\n");
   1.665+		errorexit();
   1.666+	}
   1.667+	if(o == ANAME) {
   1.668+		stop = memchr(&bloc[3], 0, bsize-&bloc[3]);
   1.669+		if(stop == 0){
   1.670+			bsize = readsome(f, buf.xbuf, bloc, bsize, c);
   1.671+			if(bsize == 0)
   1.672+				goto eof;
   1.673+			bloc = buf.xbuf;
   1.674+			stop = memchr(&bloc[3], 0, bsize-&bloc[3]);
   1.675+			if(stop == 0){
   1.676+				fprint(2, "%s: name too long\n", pn);
   1.677+				errorexit();
   1.678+			}
   1.679+		}
   1.680+		v = bloc[1];	/* type */
   1.681+		o = bloc[2];	/* sym */
   1.682+		bloc += 3;
   1.683+		c -= 3;
   1.684+
   1.685+		r = 0;
   1.686+		if(v == D_STATIC)
   1.687+			r = version;
   1.688+		s = lookup((char*)bloc, r);
   1.689+		c -= &stop[1] - bloc;
   1.690+		bloc = stop + 1;
   1.691+
   1.692+		if(debug['W'])
   1.693+			print("	ANAME	%s\n", s->name);
   1.694+		h[o] = s;
   1.695+		if((v == D_EXTERN || v == D_STATIC) && s->type == 0)
   1.696+			s->type = SXREF;
   1.697+		if(v == D_FILE) {
   1.698+			if(s->type != SFILE) {
   1.699+				histgen++;
   1.700+				s->type = SFILE;
   1.701+				s->value = histgen;
   1.702+			}
   1.703+			if(histfrogp < MAXHIST) {
   1.704+				histfrog[histfrogp] = s;
   1.705+				histfrogp++;
   1.706+			} else
   1.707+				collapsefrog(s);
   1.708+		}
   1.709+		goto loop;
   1.710+	}
   1.711+
   1.712+	if(nhunk < sizeof(Prog))
   1.713+		gethunk();
   1.714+	p = (Prog*)hunk;
   1.715+	nhunk -= sizeof(Prog);
   1.716+	hunk += sizeof(Prog);
   1.717+
   1.718+	p->as = o;
   1.719+	p->reg = bloc[1] & 0x7f;
   1.720+	if(bloc[1] & 0x80)
   1.721+		p->mark = NOSCHED;
   1.722+	p->line = bloc[2] | (bloc[3]<<8) | (bloc[4]<<16) | (bloc[5]<<24);
   1.723+
   1.724+	r = zaddr(bloc+6, &p->from, h) + 6;
   1.725+	r += zaddr(bloc+r, &p->to, h);
   1.726+	bloc += r;
   1.727+	c -= r;
   1.728+
   1.729+	if(p->reg < 0 || p->reg > NREG)
   1.730+		diag("register out of range %d", p->reg);
   1.731+
   1.732+	p->link = P;
   1.733+	p->cond = P;
   1.734+
   1.735+	if(debug['W'])
   1.736+		print("%P\n", p);
   1.737+
   1.738+	switch(o) {
   1.739+	case AHISTORY:
   1.740+		if(p->to.offset == -1) {
   1.741+			addlib(pn);
   1.742+			histfrogp = 0;
   1.743+			goto loop;
   1.744+		}
   1.745+		addhist(p->line, D_FILE);		/* 'z' */
   1.746+		if(p->to.offset)
   1.747+			addhist(p->to.offset, D_PREG);	/* 'Z' */
   1.748+		histfrogp = 0;
   1.749+		goto loop;
   1.750+
   1.751+	case AEND:
   1.752+		histtoauto();
   1.753+		if(curtext != P)
   1.754+			curtext->to.autom = curauto;
   1.755+		curauto = 0;
   1.756+		curtext = P;
   1.757+		if(c)
   1.758+			goto newloop;
   1.759+		return;
   1.760+
   1.761+	case AGLOBL:
   1.762+		s = p->from.sym;
   1.763+		if(s == S) {
   1.764+			diag("GLOBL must have a name\n%P", p);
   1.765+			errorexit();
   1.766+		}
   1.767+		if(s->type == 0 || s->type == SXREF) {
   1.768+			s->type = SBSS;
   1.769+			s->value = 0;
   1.770+		}
   1.771+		if(s->type != SBSS) {
   1.772+			diag("redefinition: %s\n%P", s->name, p);
   1.773+			s->type = SBSS;
   1.774+			s->value = 0;
   1.775+		}
   1.776+		if(p->to.offset > s->value)
   1.777+			s->value = p->to.offset;
   1.778+		break;
   1.779+
   1.780+	case ADYNT:
   1.781+		if(p->to.sym == S) {
   1.782+			diag("DYNT without a sym\n%P", p);
   1.783+			break;
   1.784+		}
   1.785+		di = p->to.sym;
   1.786+		p->reg = 4;
   1.787+		if(di->type == SXREF) {
   1.788+			if(debug['z'])
   1.789+				Bprint(&bso, "%P set to %d\n", p, dtype);
   1.790+			di->type = SCONST;
   1.791+			di->value = dtype;
   1.792+			dtype += 4;
   1.793+		}
   1.794+		if(p->from.sym == S)
   1.795+			break;
   1.796+
   1.797+		p->from.offset = di->value;
   1.798+		p->from.sym->type = SDATA;
   1.799+		if(curtext == P) {
   1.800+			diag("DYNT not in text: %P", p);
   1.801+			break;
   1.802+		}
   1.803+		p->to.sym = curtext->from.sym;
   1.804+		p->to.type = D_CONST;
   1.805+		p->link = datap;
   1.806+		datap = p;
   1.807+		break;
   1.808+
   1.809+	case AINIT:
   1.810+		if(p->from.sym == S) {
   1.811+			diag("INIT without a sym\n%P", p);
   1.812+			break;
   1.813+		}
   1.814+		if(di == S) {
   1.815+			diag("INIT without previous DYNT\n%P", p);
   1.816+			break;
   1.817+		}
   1.818+		p->from.offset = di->value;
   1.819+		p->from.sym->type = SDATA;
   1.820+		p->link = datap;
   1.821+		datap = p;
   1.822+		break;
   1.823+	
   1.824+	case ADATA:
   1.825+		if(p->from.sym == S) {
   1.826+			diag("DATA without a sym\n%P", p);
   1.827+			break;
   1.828+		}
   1.829+		p->link = datap;
   1.830+		datap = p;
   1.831+		break;
   1.832+
   1.833+	case AGOK:
   1.834+		diag("unknown opcode\n%P", p);
   1.835+		p->pc = pc;
   1.836+		pc++;
   1.837+		break;
   1.838+
   1.839+	case ATEXT:
   1.840+		if(curtext != P) {
   1.841+			histtoauto();
   1.842+			curtext->to.autom = curauto;
   1.843+			curauto = 0;
   1.844+		}
   1.845+		skip = 0;
   1.846+		curtext = p;
   1.847+		autosize = (p->to.offset+3L) & ~3L;
   1.848+		if (autosize & 4)
   1.849+			autosize += 4;
   1.850+		p->to.offset = autosize;
   1.851+		autosize += 8;
   1.852+		s = p->from.sym;
   1.853+		if(s == S) {
   1.854+			diag("TEXT must have a name\n%P", p);
   1.855+			errorexit();
   1.856+		}
   1.857+		if(s->type != 0 && s->type != SXREF) {
   1.858+			if(p->reg & DUPOK) {
   1.859+				skip = 1;
   1.860+				goto casedef;
   1.861+			}
   1.862+			diag("redefinition: %s\n%P", s->name, p);
   1.863+		}
   1.864+		s->type = STEXT;
   1.865+		s->value = pc;
   1.866+		lastp->link = p;
   1.867+		lastp = p;
   1.868+		p->pc = pc;
   1.869+		pc++;
   1.870+		if(textp == P) {
   1.871+			textp = p;
   1.872+			etextp = p;
   1.873+			goto loop;
   1.874+		}
   1.875+		etextp->cond = p;
   1.876+		etextp = p;
   1.877+		break;
   1.878+
   1.879+	case AMOVS:
   1.880+		if(skip)
   1.881+			goto casedef;
   1.882+
   1.883+		if(p->from.type == D_FCONST) {
   1.884+			/* size sb 9 max */
   1.885+			sprint(literal, "$%lux", ieeedtof(p->from.ieee));
   1.886+			s = lookup(literal, 0);
   1.887+			if(s->type == 0) {
   1.888+				s->type = SBSS;
   1.889+				s->value = 4;
   1.890+				t = prg();
   1.891+				t->as = ADATA;
   1.892+				t->line = p->line;
   1.893+				t->from.type = D_OREG;
   1.894+				t->from.sym = s;
   1.895+				t->from.name = D_EXTERN;
   1.896+				t->reg = 4;
   1.897+				t->to = p->from;
   1.898+				t->link = datap;
   1.899+				datap = t;
   1.900+			}
   1.901+			p->from.type = D_OREG;
   1.902+			p->from.sym = s;
   1.903+			p->from.name = D_EXTERN;
   1.904+			p->from.offset = 0;
   1.905+		}
   1.906+		goto casedef;
   1.907+
   1.908+	case AMOVT:
   1.909+		if(skip)
   1.910+			goto casedef;
   1.911+
   1.912+		if(p->from.type == D_FCONST) {
   1.913+			/* size sb 18 max */
   1.914+			sprint(literal, "$%lux.%lux",
   1.915+				p->from.ieee->l, p->from.ieee->h);
   1.916+			s = lookup(literal, 0);
   1.917+			if(s->type == 0) {
   1.918+				s->type = SBSS;
   1.919+				s->value = 8;
   1.920+				t = prg();
   1.921+				t->as = ADATA;
   1.922+				t->line = p->line;
   1.923+				t->from.type = D_OREG;
   1.924+				t->from.sym = s;
   1.925+				t->from.name = D_EXTERN;
   1.926+				t->reg = 8;
   1.927+				t->to = p->from;
   1.928+				t->link = datap;
   1.929+				datap = t;
   1.930+			}
   1.931+			p->from.type = D_OREG;
   1.932+			p->from.sym = s;
   1.933+			p->from.name = D_EXTERN;
   1.934+			p->from.offset = 0;
   1.935+		}
   1.936+		goto casedef;
   1.937+
   1.938+	case AMOVQ:
   1.939+		if(skip)
   1.940+			goto casedef;
   1.941+
   1.942+		if (p->from.type == D_FREG || p->to.type == D_FREG)
   1.943+			p->as = AMOVT;		/* stupid compiler optimiser kkludge */
   1.944+
   1.945+	case AMOVL:
   1.946+	case AMOVW:
   1.947+	case AMOVB:
   1.948+		/* BOTCH */
   1.949+		if (p->from.type == D_CONST)
   1.950+		if (p->from.offset == 0LL && p->from.name == D_NONE) {
   1.951+			p->from.type = D_REG;
   1.952+			p->from.reg = REGZERO;
   1.953+		}
   1.954+		goto casedef;
   1.955+
   1.956+	default:
   1.957+	casedef:
   1.958+		if(skip)
   1.959+			nopout(p);
   1.960+
   1.961+		if(p->to.type == D_BRANCH)
   1.962+			p->to.offset += ipc;
   1.963+		lastp->link = p;
   1.964+		lastp = p;
   1.965+		p->pc = pc;
   1.966+		pc++;
   1.967+		break;
   1.968+	}
   1.969+	goto loop;
   1.970+
   1.971+eof:
   1.972+	diag("truncated object file: %s", pn);
   1.973+}
   1.974+
   1.975+Sym*
   1.976+lookup(char *symb, int v)
   1.977+{
   1.978+	Sym *s;
   1.979+	char *p;
   1.980+	long h;
   1.981+	int c0, l;
   1.982+
   1.983+	h = v;
   1.984+	for(p=symb; c0 = *p; p++)
   1.985+		h = h+h+h + c0;
   1.986+	l = (p - symb) + 1;
   1.987+	if(h < 0)
   1.988+		h = ~h;
   1.989+	h %= NHASH;
   1.990+	for(s = hash[h]; s != S; s = s->link)
   1.991+		if(s->version == v)
   1.992+		if(memcmp(s->name, symb, l) == 0)
   1.993+			return s;
   1.994+
   1.995+	while(nhunk < sizeof(Sym))
   1.996+		gethunk();
   1.997+	s = (Sym*)hunk;
   1.998+	nhunk -= sizeof(Sym);
   1.999+	hunk += sizeof(Sym);
  1.1000+
  1.1001+	s->name = malloc(l);
  1.1002+	memmove(s->name, symb, l);
  1.1003+
  1.1004+	s->link = hash[h];
  1.1005+	s->type = 0;
  1.1006+	s->version = v;
  1.1007+	s->value = 0;
  1.1008+	hash[h] = s;
  1.1009+	return s;
  1.1010+}
  1.1011+
  1.1012+Prog*
  1.1013+prg(void)
  1.1014+{
  1.1015+	Prog *p;
  1.1016+
  1.1017+	while(nhunk < sizeof(Prog))
  1.1018+		gethunk();
  1.1019+	p = (Prog*)hunk;
  1.1020+	nhunk -= sizeof(Prog);
  1.1021+	hunk += sizeof(Prog);
  1.1022+
  1.1023+	*p = zprg;
  1.1024+	return p;
  1.1025+}
  1.1026+
  1.1027+void
  1.1028+gethunk(void)
  1.1029+{
  1.1030+	char *h;
  1.1031+	long nh;
  1.1032+
  1.1033+	nh = NHUNK;
  1.1034+	if(thunk >= 5L*NHUNK) {
  1.1035+		nh = 5L*NHUNK;
  1.1036+		if(thunk >= 25L*NHUNK)
  1.1037+			nh = 25L*NHUNK;
  1.1038+	}
  1.1039+	h = mysbrk(nh);
  1.1040+	if(h == (char*)-1) {
  1.1041+		diag("out of memory");
  1.1042+		errorexit();
  1.1043+	}
  1.1044+	hunk = h;
  1.1045+	nhunk = nh;
  1.1046+	thunk += nh;
  1.1047+}
  1.1048+
  1.1049+void
  1.1050+doprof1(void)
  1.1051+{
  1.1052+	Sym *s;
  1.1053+	long n;
  1.1054+	Prog *p, *q;
  1.1055+
  1.1056+	if(debug['v'])
  1.1057+		Bprint(&bso, "%5.2f profile 1\n", cputime());
  1.1058+	Bflush(&bso);
  1.1059+	s = lookup("__mcount", 0);
  1.1060+	n = 1;
  1.1061+	for(p = firstp->link; p != P; p = p->link) {
  1.1062+		if(p->as == ATEXT) {
  1.1063+			q = prg();
  1.1064+			q->line = p->line;
  1.1065+			q->link = datap;
  1.1066+			datap = q;
  1.1067+			q->as = ADATA;
  1.1068+			q->from.type = D_OREG;
  1.1069+			q->from.name = D_EXTERN;
  1.1070+			q->from.offset = n*4;
  1.1071+			q->from.sym = s;
  1.1072+			q->reg = 4;
  1.1073+			q->to = p->from;
  1.1074+			q->to.type = D_CONST;
  1.1075+
  1.1076+			q = prg();
  1.1077+			q->line = p->line;
  1.1078+			q->pc = p->pc;
  1.1079+			q->link = p->link;
  1.1080+			p->link = q;
  1.1081+			p = q;
  1.1082+			p->as = AMOVL;
  1.1083+			p->from.type = D_OREG;
  1.1084+			p->from.name = D_EXTERN;
  1.1085+			p->from.sym = s;
  1.1086+			p->from.offset = n*4 + 4;
  1.1087+			p->to.type = D_REG;
  1.1088+			p->to.reg = REGTMP;
  1.1089+
  1.1090+			q = prg();
  1.1091+			q->line = p->line;
  1.1092+			q->pc = p->pc;
  1.1093+			q->link = p->link;
  1.1094+			p->link = q;
  1.1095+			p = q;
  1.1096+			p->as = AADDQ;
  1.1097+			p->from.type = D_CONST;
  1.1098+			p->from.offset = 1;
  1.1099+			p->to.type = D_REG;
  1.1100+			p->to.reg = REGTMP;
  1.1101+
  1.1102+			q = prg();
  1.1103+			q->line = p->line;
  1.1104+			q->pc = p->pc;
  1.1105+			q->link = p->link;
  1.1106+			p->link = q;
  1.1107+			p = q;
  1.1108+			p->as = AMOVL;
  1.1109+			p->from.type = D_REG;
  1.1110+			p->from.reg = REGTMP;
  1.1111+			p->to.type = D_OREG;
  1.1112+			p->to.name = D_EXTERN;
  1.1113+			p->to.sym = s;
  1.1114+			p->to.offset = n*4 + 4;
  1.1115+
  1.1116+			n += 2;
  1.1117+			continue;
  1.1118+		}
  1.1119+	}
  1.1120+	q = prg();
  1.1121+	q->line = 0;
  1.1122+	q->link = datap;
  1.1123+	datap = q;
  1.1124+
  1.1125+	q->as = ADATA;
  1.1126+	q->from.type = D_OREG;
  1.1127+	q->from.name = D_EXTERN;
  1.1128+	q->from.sym = s;
  1.1129+	q->reg = 4;
  1.1130+	q->to.type = D_CONST;
  1.1131+	q->to.offset = n;
  1.1132+
  1.1133+	s->type = SBSS;
  1.1134+	s->value = n*4;
  1.1135+}
  1.1136+
  1.1137+void
  1.1138+doprof2(void)
  1.1139+{
  1.1140+	Sym *s2, *s4;
  1.1141+	Prog *p, *q, *q2, *ps2, *ps4;
  1.1142+
  1.1143+	if(debug['v'])
  1.1144+		Bprint(&bso, "%5.2f profile 2\n", cputime());
  1.1145+	Bflush(&bso);
  1.1146+
  1.1147+	if(debug['e']){
  1.1148+		s2 = lookup("_tracein", 0);
  1.1149+		s4 = lookup("_traceout", 0);
  1.1150+	}else{
  1.1151+		s2 = lookup("_profin", 0);
  1.1152+		s4 = lookup("_profout", 0);
  1.1153+	}
  1.1154+	if(s2->type != STEXT || s4->type != STEXT) {
  1.1155+		if(debug['e'])
  1.1156+			diag("_tracein/_traceout not defined %d %d", s2->type, s4->type);
  1.1157+		else
  1.1158+			diag("_profin/_profout not defined");
  1.1159+		return;
  1.1160+	}
  1.1161+
  1.1162+	ps2 = P;
  1.1163+	ps4 = P;
  1.1164+	for(p = firstp; p != P; p = p->link) {
  1.1165+		if(p->as == ATEXT) {
  1.1166+			if(p->from.sym == s2) {
  1.1167+				ps2 = p;
  1.1168+				p->reg = 1;
  1.1169+			}
  1.1170+			if(p->from.sym == s4) {
  1.1171+				ps4 = p;
  1.1172+				p->reg = 1;
  1.1173+			}
  1.1174+		}
  1.1175+	}
  1.1176+	for(p = firstp; p != P; p = p->link) {
  1.1177+		if(p->as == ATEXT) {
  1.1178+			if(p->reg != NREG) {
  1.1179+				for(;;) {
  1.1180+					q = p->link;
  1.1181+					if(q == P)
  1.1182+						break;
  1.1183+					if(q->as == ATEXT)
  1.1184+						break;
  1.1185+					p = q;
  1.1186+				}
  1.1187+				continue;
  1.1188+			}
  1.1189+
  1.1190+			/*
  1.1191+			 * JSR	profin, R2
  1.1192+			 */
  1.1193+			q = prg();
  1.1194+			q->line = p->line;
  1.1195+			q->pc = p->pc;
  1.1196+			q->link = p->link;
  1.1197+			if(debug['e']){		/* embedded tracing */
  1.1198+				q2 = prg();
  1.1199+				p->link = q2;
  1.1200+				q2->link = q;
  1.1201+
  1.1202+				q2->line = p->line;
  1.1203+				q2->pc = p->pc;
  1.1204+
  1.1205+				q2->as = AJMP;
  1.1206+				q2->to.type = D_BRANCH;
  1.1207+				q2->to.sym = p->to.sym;
  1.1208+				q2->cond = q->link;
  1.1209+			}else
  1.1210+				p->link = q;
  1.1211+			p = q;
  1.1212+			p->as = AJSR;
  1.1213+			p->to.type = D_BRANCH;
  1.1214+			p->cond = ps2;
  1.1215+			p->to.sym = s2;
  1.1216+
  1.1217+			continue;
  1.1218+		}
  1.1219+		if(p->as == ARET) {
  1.1220+			/*
  1.1221+			 * JSR (default)
  1.1222+			 */
  1.1223+			if(debug['e']){		/* embedded tracing */
  1.1224+				q = prg();
  1.1225+				q->line = p->line;
  1.1226+				q->pc = p->pc;
  1.1227+				q->link = p->link;
  1.1228+				p->link = q;
  1.1229+				p = q;
  1.1230+			}
  1.1231+			/*
  1.1232+			 * JSR	profout
  1.1233+			 */
  1.1234+			p->as = AJSR;
  1.1235+			p->to.type = D_BRANCH;
  1.1236+			p->cond = ps4;
  1.1237+			p->to.sym = s4;
  1.1238+
  1.1239+			
  1.1240+			/*
  1.1241+			 * RET
  1.1242+			 */
  1.1243+			q = prg();
  1.1244+			q->line = p->line;
  1.1245+			q->pc = p->pc;
  1.1246+			q->link = p->link;
  1.1247+			p->link = q;
  1.1248+			p = q;
  1.1249+			p->as = ARET;
  1.1250+
  1.1251+			continue;
  1.1252+		}
  1.1253+	}
  1.1254+}
  1.1255+
  1.1256+void
  1.1257+nuxiinit(void)
  1.1258+{
  1.1259+	int i, c;
  1.1260+
  1.1261+	for(i=0; i<4; i++) {
  1.1262+		c = find1(0x04030201L, i+1);
  1.1263+		if(i <= 4)
  1.1264+			inuxi4[i] = c;
  1.1265+		if(i <= 2)
  1.1266+			inuxi2[i] = c;
  1.1267+		if(i <= 1)
  1.1268+			inuxi1[i] = c;
  1.1269+	}
  1.1270+	for (i = 0; i < 4; i++) {
  1.1271+		c = find1(0x04030201L, i+1);
  1.1272+		fnuxi8[i] = c;
  1.1273+		fnuxi8[i+4] = c + sizeof(long);
  1.1274+	}
  1.1275+
  1.1276+	if(debug['v']) {
  1.1277+		Bprint(&bso, "inuxi = ");
  1.1278+		for(i=0; i<1; i++)
  1.1279+			Bprint(&bso, "%d", inuxi1[i]);
  1.1280+		Bprint(&bso, " ");
  1.1281+		for(i=0; i<2; i++)
  1.1282+			Bprint(&bso, "%d", inuxi2[i]);
  1.1283+		Bprint(&bso, " ");
  1.1284+		for(i=0; i<4; i++)
  1.1285+			Bprint(&bso, "%d", inuxi4[i]);
  1.1286+		Bprint(&bso, " ");
  1.1287+		Bprint(&bso, "\nfnuxi = ");
  1.1288+		for(i=0; i<8; i++)
  1.1289+			Bprint(&bso, "%d", fnuxi8[i]);
  1.1290+		Bprint(&bso, "\n");
  1.1291+	}
  1.1292+	Bflush(&bso);
  1.1293+}
  1.1294+
  1.1295+find1(long l, int c)
  1.1296+{
  1.1297+	char *p;
  1.1298+	int i;
  1.1299+
  1.1300+	p = (char*)&l;
  1.1301+	for(i=0; i<4; i++)
  1.1302+		if(*p++ == c)
  1.1303+			return i;
  1.1304+	return 0;
  1.1305+}
  1.1306+
  1.1307+long
  1.1308+ieeedtof(Ieee *ieee)
  1.1309+{
  1.1310+	int exp;
  1.1311+	long v;
  1.1312+
  1.1313+	if(ieee->h == 0)
  1.1314+		return 0;
  1.1315+	exp = (ieee->h>>20) & ((1L<<11)-1L);
  1.1316+	exp -= (1L<<10) - 2L;
  1.1317+	v = (ieee->h & 0xfffffL) << 3;
  1.1318+	v |= (ieee->l >> 29) & 0x7L;
  1.1319+	if((ieee->l >> 28) & 1) {
  1.1320+		v++;
  1.1321+		if(v & 0x800000L) {
  1.1322+			v = (v & 0x7fffffL) >> 1;
  1.1323+			exp++;
  1.1324+		}
  1.1325+	}
  1.1326+	if(exp <= -126 || exp >= 130)
  1.1327+		diag("double fp to single fp overflow");
  1.1328+	v |= ((exp + 126) & 0xffL) << 23;
  1.1329+	v |= ieee->h & 0x80000000L;
  1.1330+	return v;
  1.1331+}
  1.1332+
  1.1333+double
  1.1334+ieeedtod(Ieee *ieee)
  1.1335+{
  1.1336+	Ieee e;
  1.1337+	double fr;
  1.1338+	int exp;
  1.1339+
  1.1340+	if(ieee->h & (1L<<31)) {
  1.1341+		e.h = ieee->h & ~(1L<<31);
  1.1342+		e.l = ieee->l;
  1.1343+		return -ieeedtod(&e);
  1.1344+	}
  1.1345+	if(ieee->l == 0 && ieee->h == 0)
  1.1346+		return 0;
  1.1347+	fr = ieee->l & ((1L<<16)-1L);
  1.1348+	fr /= 1L<<16;
  1.1349+	fr += (ieee->l>>16) & ((1L<<16)-1L);
  1.1350+	fr /= 1L<<16;
  1.1351+	fr += (ieee->h & (1L<<20)-1L) | (1L<<20);
  1.1352+	fr /= 1L<<21;
  1.1353+	exp = (ieee->h>>20) & ((1L<<11)-1L);
  1.1354+	exp -= (1L<<10) - 2L;
  1.1355+	return ldexp(fr, exp);
  1.1356+}