changelog shortlog tags branches changeset file revisions annotate raw help

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

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