xref: /plan9-contrib/sys/src/cmd/4l/obj.c (revision f8bc6aaf8056e137bcdfb6117a990ac3eff62cc9)
17edc7532SDavid du Colombier #define	EXTERN
27edc7532SDavid du Colombier #include	"l.h"
37edc7532SDavid du Colombier #include	<ar.h>
47edc7532SDavid du Colombier 
57edc7532SDavid du Colombier #ifndef	DEFAULT
67edc7532SDavid du Colombier #define	DEFAULT	'9'
77edc7532SDavid du Colombier #endif
87edc7532SDavid du Colombier 
97edc7532SDavid du Colombier char	*noname		= "<none>";
107edc7532SDavid du Colombier char	symname[]	= SYMDEF;
117edc7532SDavid du Colombier char	thechar		= '4';
127edc7532SDavid du Colombier char	*thestring 	= "mips64";
13*f8bc6aafSDavid du Colombier int little;
14*f8bc6aafSDavid du Colombier 
15*f8bc6aafSDavid du Colombier char**	libdir;
16*f8bc6aafSDavid du Colombier int	nlibdir	= 0;
17*f8bc6aafSDavid du Colombier static	int	maxlibdir = 0;
187edc7532SDavid du Colombier 
197edc7532SDavid du Colombier /*
207edc7532SDavid du Colombier  *	-H0 -T0x40004C -D0x10000000	is abbrev unix
217edc7532SDavid du Colombier  *	-H1 -T0x80020000 -R4		is bootp() format for 3k
22*f8bc6aafSDavid du Colombier  *	-H2 -T16416 -R16384		is plan9 mips64 format
237edc7532SDavid du Colombier  *	-H3 -T0x80020000 -R8		is bootp() format for 4k
247edc7532SDavid du Colombier  *	-H4 -T0x400000 -R4		is sgi unix coff executable
257edc7532SDavid du Colombier  *	-H5 -T0x4000A0 -R4		is sgi unix elf executable
26*f8bc6aafSDavid du Colombier  *	-H6 -T16416 -R16384		is plan9 mips format
27*f8bc6aafSDavid du Colombier  *	-H7				is 64-bit elf executable
287edc7532SDavid du Colombier  */
297edc7532SDavid du Colombier 
307edc7532SDavid du Colombier void
usage(void)31*f8bc6aafSDavid du Colombier usage(void)
32*f8bc6aafSDavid du Colombier {
33*f8bc6aafSDavid du Colombier 	diag("usage: %s [-options] objects", argv0);
34*f8bc6aafSDavid du Colombier 	errorexit();
35*f8bc6aafSDavid du Colombier }
36*f8bc6aafSDavid du Colombier 
37*f8bc6aafSDavid du Colombier void
main(int argc,char * argv[])387edc7532SDavid du Colombier main(int argc, char *argv[])
397edc7532SDavid du Colombier {
407edc7532SDavid du Colombier 	int c;
417edc7532SDavid du Colombier 	char *a;
42*f8bc6aafSDavid du Colombier 	char name[LIBNAMELEN];
437edc7532SDavid du Colombier 
447edc7532SDavid du Colombier 	Binit(&bso, 1, OWRITE);
457edc7532SDavid du Colombier 	cout = -1;
467edc7532SDavid du Colombier 	listinit();
477edc7532SDavid du Colombier 	outfile = 0;
487edc7532SDavid du Colombier 	nerrors = 0;
497edc7532SDavid du Colombier 	curtext = P;
507edc7532SDavid du Colombier 	HEADTYPE = -1;
517edc7532SDavid du Colombier 	INITTEXT = -1;
52*f8bc6aafSDavid du Colombier 	INITTEXTP = -1;
537edc7532SDavid du Colombier 	INITDAT = -1;
547edc7532SDavid du Colombier 	INITRND = -1;
557edc7532SDavid du Colombier 	INITENTRY = 0;
567edc7532SDavid du Colombier 	M64 = 1;
577edc7532SDavid du Colombier 
587edc7532SDavid du Colombier 	ARGBEGIN {
597edc7532SDavid du Colombier 	default:
607edc7532SDavid du Colombier 		c = ARGC();
617edc7532SDavid du Colombier 		if(c >= 0 && c < sizeof(debug))
627edc7532SDavid du Colombier 			debug[c]++;
637edc7532SDavid du Colombier 		break;
647edc7532SDavid du Colombier 	case 'o':
657edc7532SDavid du Colombier 		outfile = ARGF();
667edc7532SDavid du Colombier 		break;
677edc7532SDavid du Colombier 	case 'E':
687edc7532SDavid du Colombier 		a = ARGF();
697edc7532SDavid du Colombier 		if(a)
707edc7532SDavid du Colombier 			INITENTRY = a;
717edc7532SDavid du Colombier 		break;
72*f8bc6aafSDavid du Colombier 	case  'm':			/* for little-endian mips */
73*f8bc6aafSDavid du Colombier 		thechar = 'x';	/* XXX the char unknown */
74*f8bc6aafSDavid du Colombier 		thestring = "spim64";
75*f8bc6aafSDavid du Colombier 		little = 1;
76*f8bc6aafSDavid du Colombier 		break;
777edc7532SDavid du Colombier 	case 'T':
787edc7532SDavid du Colombier 		a = ARGF();
797edc7532SDavid du Colombier 		if(a)
807edc7532SDavid du Colombier 			INITTEXT = atolwhex(a);
817edc7532SDavid du Colombier 		break;
82*f8bc6aafSDavid du Colombier 	case 'P':
83*f8bc6aafSDavid du Colombier 		a = ARGF();
84*f8bc6aafSDavid du Colombier 		if(a)
85*f8bc6aafSDavid du Colombier 			INITTEXTP = atolwhex(a);
86*f8bc6aafSDavid du Colombier 		break;
877edc7532SDavid du Colombier 	case 'D':
887edc7532SDavid du Colombier 		a = ARGF();
897edc7532SDavid du Colombier 		if(a)
907edc7532SDavid du Colombier 			INITDAT = atolwhex(a);
917edc7532SDavid du Colombier 		break;
927edc7532SDavid du Colombier 	case 'R':
937edc7532SDavid du Colombier 		a = ARGF();
947edc7532SDavid du Colombier 		if(a)
957edc7532SDavid du Colombier 			INITRND = atolwhex(a);
967edc7532SDavid du Colombier 		break;
977edc7532SDavid du Colombier 	case 'H':
987edc7532SDavid du Colombier 		a = ARGF();
997edc7532SDavid du Colombier 		if(a)
1007edc7532SDavid du Colombier 			HEADTYPE = atolwhex(a);
1017edc7532SDavid du Colombier 		/* do something about setting INITTEXT */
1027edc7532SDavid du Colombier 		break;
103*f8bc6aafSDavid du Colombier 	case 'L':
104*f8bc6aafSDavid du Colombier 		addlibpath(EARGF(usage()));
105*f8bc6aafSDavid du Colombier 		break;
1067edc7532SDavid du Colombier 	} ARGEND
1077edc7532SDavid du Colombier 
1087edc7532SDavid du Colombier 	USED(argc);
1097edc7532SDavid du Colombier 
110*f8bc6aafSDavid du Colombier 	if(*argv == 0)
111*f8bc6aafSDavid du Colombier 		usage();
1127edc7532SDavid du Colombier 	if(!debug['9'] && !debug['U'] && !debug['B'])
1137edc7532SDavid du Colombier 		debug[DEFAULT] = 1;
114*f8bc6aafSDavid du Colombier 	a = getenv("ccroot");
115*f8bc6aafSDavid du Colombier 	if(a != nil && *a != '\0') {
116*f8bc6aafSDavid du Colombier 		if(!fileexists(a)) {
117*f8bc6aafSDavid du Colombier 			diag("nonexistent $ccroot: %s", a);
118*f8bc6aafSDavid du Colombier 			errorexit();
119*f8bc6aafSDavid du Colombier 		}
120*f8bc6aafSDavid du Colombier 	}else
121*f8bc6aafSDavid du Colombier 		a = "";
122*f8bc6aafSDavid du Colombier 	snprint(name, sizeof(name), "%s/%s/lib", a, thestring);
123*f8bc6aafSDavid du Colombier 	addlibpath(name);
1247edc7532SDavid du Colombier 	if(HEADTYPE == -1) {
1257edc7532SDavid du Colombier 		if(debug['U'])
1267edc7532SDavid du Colombier 			HEADTYPE = 0;
1277edc7532SDavid du Colombier 		if(debug['B'])
1287edc7532SDavid du Colombier 			HEADTYPE = 1;
1297edc7532SDavid du Colombier 		if(debug['9'])
1307edc7532SDavid du Colombier 			HEADTYPE = 2;
1317edc7532SDavid du Colombier 	}
1327edc7532SDavid du Colombier 	switch(HEADTYPE) {
1337edc7532SDavid du Colombier 	default:
1347edc7532SDavid du Colombier 		diag("unknown -H option");
1357edc7532SDavid du Colombier 		errorexit();
1367edc7532SDavid du Colombier 
1377edc7532SDavid du Colombier 	case 0:	/* unix simple */
1387edc7532SDavid du Colombier 		HEADR = 20L+56L;
1397edc7532SDavid du Colombier 		if(INITTEXT == -1)
1407edc7532SDavid du Colombier 			INITTEXT = 0x40004CL;
1417edc7532SDavid du Colombier 		if(INITDAT == -1)
1427edc7532SDavid du Colombier 			INITDAT = 0x10000000L;
1437edc7532SDavid du Colombier 		if(INITRND == -1)
1447edc7532SDavid du Colombier 			INITRND = 0;
1457edc7532SDavid du Colombier 		break;
1467edc7532SDavid du Colombier 	case 1:	/* boot for 3k */
1477edc7532SDavid du Colombier 		HEADR = 20L+60L;
1487edc7532SDavid du Colombier 		if(INITTEXT == -1)
1497edc7532SDavid du Colombier 			INITTEXT = 0x80020000L;
1507edc7532SDavid du Colombier 		if(INITDAT == -1)
1517edc7532SDavid du Colombier 			INITDAT = 0;
1527edc7532SDavid du Colombier 		if(INITRND == -1)
1537edc7532SDavid du Colombier 			INITRND = 4;
1547edc7532SDavid du Colombier 		break;
155*f8bc6aafSDavid du Colombier 	case 2:	/* plan 9 mips64 */
1567edc7532SDavid du Colombier 		HEADR = 32L;
1577edc7532SDavid du Colombier 		if(INITDAT == -1)
1587edc7532SDavid du Colombier 			INITDAT = 0;
1597edc7532SDavid du Colombier 		if(INITRND == -1)
160*f8bc6aafSDavid du Colombier 			INITRND = 16*1024;
161*f8bc6aafSDavid du Colombier 		if(INITTEXT == -1)
162*f8bc6aafSDavid du Colombier 			INITTEXT = INITRND + HEADR;
1637edc7532SDavid du Colombier 		break;
1647edc7532SDavid du Colombier 	case 3:	/* boot for 4k */
1657edc7532SDavid du Colombier 		HEADR = 20L+56L+3*40L;
1667edc7532SDavid du Colombier 		if(INITTEXT == -1)
1677edc7532SDavid du Colombier 			INITTEXT = 0x80020000L;
1687edc7532SDavid du Colombier 		if(INITDAT == -1)
1697edc7532SDavid du Colombier 			INITDAT = 0;
1707edc7532SDavid du Colombier 		if(INITRND == -1)
1717edc7532SDavid du Colombier 			INITRND = 8;
1727edc7532SDavid du Colombier 		break;
1737edc7532SDavid du Colombier 	case 4:	/* sgi unix coff executable */
1747edc7532SDavid du Colombier 		HEADR = 20L+56L+3*40L;
1757edc7532SDavid du Colombier 		if(INITTEXT == -1)
1767edc7532SDavid du Colombier 			INITTEXT = 0x00400000L+HEADR;
1777edc7532SDavid du Colombier 		if(INITDAT == -1)
1787edc7532SDavid du Colombier 			INITDAT = 0x10000000;
1797edc7532SDavid du Colombier 		if(INITRND == -1)
1807edc7532SDavid du Colombier 			INITRND = 0;
1817edc7532SDavid du Colombier 		break;
1827edc7532SDavid du Colombier 	case 5:	/* sgi unix elf executable */
183*f8bc6aafSDavid du Colombier 		HEADR = rnd(Ehdr32sz+3*Phdr32sz, 16);
1847edc7532SDavid du Colombier 		if(INITTEXT == -1)
1857edc7532SDavid du Colombier 			INITTEXT = 0x00400000L+HEADR;
1867edc7532SDavid du Colombier 		if(INITDAT == -1)
1877edc7532SDavid du Colombier 			INITDAT = 0x10000000;
1887edc7532SDavid du Colombier 		if(INITRND == -1)
1897edc7532SDavid du Colombier 			INITRND = 0;
1907edc7532SDavid du Colombier 		break;
1917edc7532SDavid du Colombier 	case 6:	/* plan 9 mips */
1927edc7532SDavid du Colombier 		HEADR = 32L;
1937edc7532SDavid du Colombier 		if(INITDAT == -1)
1947edc7532SDavid du Colombier 			INITDAT = 0;
1957edc7532SDavid du Colombier 		if(INITRND == -1)
196*f8bc6aafSDavid du Colombier 			INITRND = 16*1024;
197*f8bc6aafSDavid du Colombier 		if(INITTEXT == -1)
198*f8bc6aafSDavid du Colombier 			INITTEXT = INITRND + HEADR;
1997edc7532SDavid du Colombier 		break;
200*f8bc6aafSDavid du Colombier 	case 7:	/* 64-bit elf executable  */
2017edc7532SDavid du Colombier 		HEADR = rnd(64L+3*56L, 16);
2027edc7532SDavid du Colombier 		if(INITTEXT == -1)
2037edc7532SDavid du Colombier 			INITTEXT = 0xa800000020040000ULL;
2047edc7532SDavid du Colombier 		if(INITDAT == -1)
2057edc7532SDavid du Colombier 			INITDAT = 0;
2067edc7532SDavid du Colombier 		if(INITRND == -1)
2077edc7532SDavid du Colombier 			INITRND = 8;
2087edc7532SDavid du Colombier 		break;
2097edc7532SDavid du Colombier 	}
210*f8bc6aafSDavid du Colombier 	if (INITTEXTP == -1)
211*f8bc6aafSDavid du Colombier 		INITTEXTP = INITTEXT;
2127edc7532SDavid du Colombier 	if(INITDAT != 0 && INITRND != 0)
213*f8bc6aafSDavid du Colombier 		print("warning: -D%#llux is ignored because of -R%#llux\n",
2147edc7532SDavid du Colombier 			INITDAT, INITRND);
2157edc7532SDavid du Colombier 	if(debug['v'])
216*f8bc6aafSDavid du Colombier 		Bprint(&bso, "HEADER = -H%d -T%#llux -D%#llux -R%#llux\n",
2177edc7532SDavid du Colombier 			HEADTYPE, INITTEXT, INITDAT, INITRND);
2187edc7532SDavid du Colombier 	Bflush(&bso);
2197edc7532SDavid du Colombier 	zprg.as = AGOK;
2207edc7532SDavid du Colombier 	zprg.reg = NREG;
2217edc7532SDavid du Colombier 	zprg.from.name = D_NONE;
2227edc7532SDavid du Colombier 	zprg.from.type = D_NONE;
2237edc7532SDavid du Colombier 	zprg.from.reg = NREG;
2247edc7532SDavid du Colombier 	zprg.to = zprg.from;
2257edc7532SDavid du Colombier 	buildop();
2267edc7532SDavid du Colombier 	histgen = 0;
2277edc7532SDavid du Colombier 	textp = P;
2287edc7532SDavid du Colombier 	datap = P;
2297edc7532SDavid du Colombier 	pc = 0;
2307edc7532SDavid du Colombier 	dtype = 4;
231*f8bc6aafSDavid du Colombier 	if(outfile == 0) {
232*f8bc6aafSDavid du Colombier 		static char name[20];
233*f8bc6aafSDavid du Colombier 
234*f8bc6aafSDavid du Colombier 		snprint(name, sizeof name, "%c.out", thechar);
235*f8bc6aafSDavid du Colombier 		outfile = name;
236*f8bc6aafSDavid du Colombier 	}
2377edc7532SDavid du Colombier 	cout = create(outfile, 1, 0775);
2387edc7532SDavid du Colombier 	if(cout < 0) {
239*f8bc6aafSDavid du Colombier 		diag("cannot create %s: %r", outfile);
2407edc7532SDavid du Colombier 		errorexit();
2417edc7532SDavid du Colombier 	}
2427edc7532SDavid du Colombier 	nuxiinit();
2437edc7532SDavid du Colombier 
2447edc7532SDavid du Colombier 	version = 0;
2457edc7532SDavid du Colombier 	cbp = buf.cbuf;
2467edc7532SDavid du Colombier 	cbc = sizeof(buf.cbuf);
2477edc7532SDavid du Colombier 	firstp = prg();
2487edc7532SDavid du Colombier 	lastp = firstp;
2497edc7532SDavid du Colombier 
2507edc7532SDavid du Colombier 	if(INITENTRY == 0) {
2517edc7532SDavid du Colombier 		INITENTRY = "_main";
2527edc7532SDavid du Colombier 		if(debug['p'])
2537edc7532SDavid du Colombier 			INITENTRY = "_mainp";
2547edc7532SDavid du Colombier 		if(!debug['l'])
2557edc7532SDavid du Colombier 			lookup(INITENTRY, 0)->type = SXREF;
256*f8bc6aafSDavid du Colombier 	} else if(!(*INITENTRY >= '0' && *INITENTRY <= '9'))
2577edc7532SDavid du Colombier 		lookup(INITENTRY, 0)->type = SXREF;
2587edc7532SDavid du Colombier 
2597edc7532SDavid du Colombier 	while(*argv)
2607edc7532SDavid du Colombier 		objfile(*argv++);
2617edc7532SDavid du Colombier 	if(!debug['l'])
262*f8bc6aafSDavid du Colombier 		loadlib();
2637edc7532SDavid du Colombier 	firstp = firstp->link;
2647edc7532SDavid du Colombier 	if(firstp == P)
2657edc7532SDavid du Colombier 		goto out;
2667edc7532SDavid du Colombier 	patch();
2677edc7532SDavid du Colombier 	if(debug['p'])
2687edc7532SDavid du Colombier 		if(debug['1'])
2697edc7532SDavid du Colombier 			doprof1();
2707edc7532SDavid du Colombier 		else
2717edc7532SDavid du Colombier 			doprof2();
2727edc7532SDavid du Colombier 	dodata();
2737edc7532SDavid du Colombier 	follow();
2747edc7532SDavid du Colombier 	if(firstp == P)
2757edc7532SDavid du Colombier 		goto out;
2767edc7532SDavid du Colombier 	noops();
2777edc7532SDavid du Colombier 	span();
2787edc7532SDavid du Colombier 	asmb();
2797edc7532SDavid du Colombier 	undef();
2807edc7532SDavid du Colombier 
2817edc7532SDavid du Colombier out:
2827edc7532SDavid du Colombier 	if(debug['v']) {
2837edc7532SDavid du Colombier 		Bprint(&bso, "%5.2f cpu time\n", cputime());
2847edc7532SDavid du Colombier 		Bprint(&bso, "%ld memory used\n", thunk);
2857edc7532SDavid du Colombier 		Bprint(&bso, "%d sizeof adr\n", sizeof(Adr));
2867edc7532SDavid du Colombier 		Bprint(&bso, "%d sizeof prog\n", sizeof(Prog));
2877edc7532SDavid du Colombier 	}
2887edc7532SDavid du Colombier 	Bflush(&bso);
2897edc7532SDavid du Colombier 	errorexit();
2907edc7532SDavid du Colombier }
2917edc7532SDavid du Colombier 
2927edc7532SDavid du Colombier void
addlibpath(char * arg)293*f8bc6aafSDavid du Colombier addlibpath(char *arg)
2947edc7532SDavid du Colombier {
295*f8bc6aafSDavid du Colombier 	char **p;
2967edc7532SDavid du Colombier 
297*f8bc6aafSDavid du Colombier 	if(nlibdir >= maxlibdir) {
298*f8bc6aafSDavid du Colombier 		if(maxlibdir == 0)
299*f8bc6aafSDavid du Colombier 			maxlibdir = 8;
300*f8bc6aafSDavid du Colombier 		else
301*f8bc6aafSDavid du Colombier 			maxlibdir *= 2;
302*f8bc6aafSDavid du Colombier 		p = malloc(maxlibdir*sizeof(*p));
303*f8bc6aafSDavid du Colombier 		if(p == nil) {
304*f8bc6aafSDavid du Colombier 			diag("out of memory");
305*f8bc6aafSDavid du Colombier 			errorexit();
3067edc7532SDavid du Colombier 		}
307*f8bc6aafSDavid du Colombier 		memmove(p, libdir, nlibdir*sizeof(*p));
308*f8bc6aafSDavid du Colombier 		free(libdir);
309*f8bc6aafSDavid du Colombier 		libdir = p;
310*f8bc6aafSDavid du Colombier 	}
311*f8bc6aafSDavid du Colombier 	libdir[nlibdir++] = strdup(arg);
312*f8bc6aafSDavid du Colombier }
313*f8bc6aafSDavid du Colombier 
314*f8bc6aafSDavid du Colombier char*
findlib(char * file)315*f8bc6aafSDavid du Colombier findlib(char *file)
316*f8bc6aafSDavid du Colombier {
317*f8bc6aafSDavid du Colombier 	int i;
318*f8bc6aafSDavid du Colombier 	char name[LIBNAMELEN];
319*f8bc6aafSDavid du Colombier 
320*f8bc6aafSDavid du Colombier 	for(i = 0; i < nlibdir; i++) {
321*f8bc6aafSDavid du Colombier 		snprint(name, sizeof(name), "%s/%s", libdir[i], file);
322*f8bc6aafSDavid du Colombier 		if(fileexists(name))
323*f8bc6aafSDavid du Colombier 			return libdir[i];
324*f8bc6aafSDavid du Colombier 	}
325*f8bc6aafSDavid du Colombier 	return nil;
326*f8bc6aafSDavid du Colombier }
327*f8bc6aafSDavid du Colombier 
328*f8bc6aafSDavid du Colombier void
loadlib(void)329*f8bc6aafSDavid du Colombier loadlib(void)
330*f8bc6aafSDavid du Colombier {
331*f8bc6aafSDavid du Colombier 	int i;
332*f8bc6aafSDavid du Colombier 	long h;
333*f8bc6aafSDavid du Colombier 	Sym *s;
334*f8bc6aafSDavid du Colombier 
335*f8bc6aafSDavid du Colombier loop:
336*f8bc6aafSDavid du Colombier 	xrefresolv = 0;
337*f8bc6aafSDavid du Colombier 	for(i=0; i<libraryp; i++) {
338*f8bc6aafSDavid du Colombier 		if(debug['v'])
339*f8bc6aafSDavid du Colombier 			Bprint(&bso, "%5.2f autolib: %s (from %s)\n", cputime(), library[i], libraryobj[i]);
340*f8bc6aafSDavid du Colombier 		objfile(library[i]);
341*f8bc6aafSDavid du Colombier 	}
342*f8bc6aafSDavid du Colombier 	if(xrefresolv)
343*f8bc6aafSDavid du Colombier 	for(h=0; h<nelem(hash); h++)
344*f8bc6aafSDavid du Colombier 	for(s = hash[h]; s != S; s = s->link)
345*f8bc6aafSDavid du Colombier 		if(s->type == SXREF)
346*f8bc6aafSDavid du Colombier 			goto loop;
3477edc7532SDavid du Colombier }
3487edc7532SDavid du Colombier 
3497edc7532SDavid du Colombier void
errorexit(void)3507edc7532SDavid du Colombier errorexit(void)
3517edc7532SDavid du Colombier {
3527edc7532SDavid du Colombier 
3537edc7532SDavid du Colombier 	if(nerrors) {
3547edc7532SDavid du Colombier 		if(cout >= 0)
3557edc7532SDavid du Colombier 			remove(outfile);
3567edc7532SDavid du Colombier 		exits("error");
3577edc7532SDavid du Colombier 	}
3587edc7532SDavid du Colombier 	exits(0);
3597edc7532SDavid du Colombier }
3607edc7532SDavid du Colombier 
3617edc7532SDavid du Colombier void
objfile(char * file)3627edc7532SDavid du Colombier objfile(char *file)
3637edc7532SDavid du Colombier {
3647edc7532SDavid du Colombier 	vlong off, esym, cnt, l;
3657edc7532SDavid du Colombier 	int f, work;
3667edc7532SDavid du Colombier 	Sym *s;
3677edc7532SDavid du Colombier 	char magbuf[SARMAG];
3687edc7532SDavid du Colombier 	char name[100], pname[150];
3697edc7532SDavid du Colombier 	struct ar_hdr arhdr;
3707edc7532SDavid du Colombier 	char *e, *start, *stop;
3717edc7532SDavid du Colombier 
3727edc7532SDavid du Colombier 	if(file[0] == '-' && file[1] == 'l') {
3737edc7532SDavid du Colombier 		if(debug['9'])
3747edc7532SDavid du Colombier 			sprint(name, "/%s/lib/lib", thestring);
3757edc7532SDavid du Colombier 		else
3767edc7532SDavid du Colombier 			sprint(name, "/usr/%clib/lib", thechar);
3777edc7532SDavid du Colombier 		strcat(name, file+2);
3787edc7532SDavid du Colombier 		strcat(name, ".a");
3797edc7532SDavid du Colombier 		file = name;
3807edc7532SDavid du Colombier 	}
3817edc7532SDavid du Colombier 	if(debug['v'])
3827edc7532SDavid du Colombier 		Bprint(&bso, "%5.2f ldobj: %s\n", cputime(), file);
3837edc7532SDavid du Colombier 	Bflush(&bso);
3847edc7532SDavid du Colombier 	f = open(file, 0);
3857edc7532SDavid du Colombier 	if(f < 0) {
3867edc7532SDavid du Colombier 		diag("cannot open file: %s", file);
3877edc7532SDavid du Colombier 		errorexit();
3887edc7532SDavid du Colombier 	}
3897edc7532SDavid du Colombier 	l = read(f, magbuf, SARMAG);
3907edc7532SDavid du Colombier 	if(l != SARMAG || strncmp(magbuf, ARMAG, SARMAG)){
3917edc7532SDavid du Colombier 		/* load it as a regular file */
3927edc7532SDavid du Colombier 		l = seek(f, 0L, 2);
3937edc7532SDavid du Colombier 		seek(f, 0L, 0);
3947edc7532SDavid du Colombier 		ldobj(f, l, file);
3957edc7532SDavid du Colombier 		close(f);
3967edc7532SDavid du Colombier 		return;
3977edc7532SDavid du Colombier 	}
3987edc7532SDavid du Colombier 
3997edc7532SDavid du Colombier 	if(debug['v'])
4007edc7532SDavid du Colombier 		Bprint(&bso, "%5.2f ldlib: %s\n", cputime(), file);
4017edc7532SDavid du Colombier 	l = read(f, &arhdr, SAR_HDR);
4027edc7532SDavid du Colombier 	if(l != SAR_HDR) {
4037edc7532SDavid du Colombier 		diag("%s: short read on archive file symbol header", file);
4047edc7532SDavid du Colombier 		goto out;
4057edc7532SDavid du Colombier 	}
4067edc7532SDavid du Colombier 	if(strncmp(arhdr.name, symname, strlen(symname))) {
4077edc7532SDavid du Colombier 		diag("%s: first entry not symbol header", file);
4087edc7532SDavid du Colombier 		goto out;
4097edc7532SDavid du Colombier 	}
4107edc7532SDavid du Colombier 
4117edc7532SDavid du Colombier 	esym = SARMAG + SAR_HDR + atolwhex(arhdr.size);
4127edc7532SDavid du Colombier 	off = SARMAG + SAR_HDR;
4137edc7532SDavid du Colombier 
4147edc7532SDavid du Colombier 	/*
4157edc7532SDavid du Colombier 	 * just bang the whole symbol file into memory
4167edc7532SDavid du Colombier 	 */
4177edc7532SDavid du Colombier 	seek(f, off, 0);
4187edc7532SDavid du Colombier 	cnt = esym - off;
4197edc7532SDavid du Colombier 	start = malloc(cnt + 10);
4207edc7532SDavid du Colombier 	cnt = read(f, start, cnt);
4217edc7532SDavid du Colombier 	if(cnt <= 0){
4227edc7532SDavid du Colombier 		close(f);
4237edc7532SDavid du Colombier 		return;
4247edc7532SDavid du Colombier 	}
4257edc7532SDavid du Colombier 	stop = &start[cnt];
4267edc7532SDavid du Colombier 	memset(stop, 0, 10);
4277edc7532SDavid du Colombier 
4287edc7532SDavid du Colombier 	work = 1;
4297edc7532SDavid du Colombier 	while(work){
4307edc7532SDavid du Colombier 		if(debug['v'])
4317edc7532SDavid du Colombier 			Bprint(&bso, "%5.2f library pass: %s\n", cputime(), file);
4327edc7532SDavid du Colombier 		Bflush(&bso);
4337edc7532SDavid du Colombier 		work = 0;
4347edc7532SDavid du Colombier 		for(e = start; e < stop; e = strchr(e+5, 0) + 1) {
4357edc7532SDavid du Colombier 			s = lookup(e+5, 0);
4367edc7532SDavid du Colombier 			if(s->type != SXREF)
4377edc7532SDavid du Colombier 				continue;
4387edc7532SDavid du Colombier 			sprint(pname, "%s(%s)", file, s->name);
4397edc7532SDavid du Colombier 			if(debug['v'])
4407edc7532SDavid du Colombier 				Bprint(&bso, "%5.2f library: %s\n", cputime(), pname);
4417edc7532SDavid du Colombier 			Bflush(&bso);
4427edc7532SDavid du Colombier 			l = e[1] & 0xff;
4437edc7532SDavid du Colombier 			l |= (e[2] & 0xff) << 8;
4447edc7532SDavid du Colombier 			l |= (e[3] & 0xff) << 16;
4457edc7532SDavid du Colombier 			l |= (e[4] & 0xff) << 24;
4467edc7532SDavid du Colombier 			seek(f, l, 0);
447*f8bc6aafSDavid du Colombier 			/* need readn to read the dumps (at least) */
448*f8bc6aafSDavid du Colombier 			l = readn(f, &arhdr, SAR_HDR);
4497edc7532SDavid du Colombier 			if(l != SAR_HDR)
4507edc7532SDavid du Colombier 				goto bad;
4517edc7532SDavid du Colombier 			if(strncmp(arhdr.fmag, ARFMAG, sizeof(arhdr.fmag)))
4527edc7532SDavid du Colombier 				goto bad;
4537edc7532SDavid du Colombier 			l = atolwhex(arhdr.size);
4547edc7532SDavid du Colombier 			ldobj(f, l, pname);
4557edc7532SDavid du Colombier 			if(s->type == SXREF) {
4567edc7532SDavid du Colombier 				diag("%s: failed to load: %s", file, s->name);
4577edc7532SDavid du Colombier 				errorexit();
4587edc7532SDavid du Colombier 			}
4597edc7532SDavid du Colombier 			work = 1;
460*f8bc6aafSDavid du Colombier 			xrefresolv = 1;
4617edc7532SDavid du Colombier 		}
4627edc7532SDavid du Colombier 	}
4637edc7532SDavid du Colombier 	return;
4647edc7532SDavid du Colombier 
4657edc7532SDavid du Colombier bad:
4667edc7532SDavid du Colombier 	diag("%s: bad or out of date archive", file);
4677edc7532SDavid du Colombier out:
4687edc7532SDavid du Colombier 	close(f);
4697edc7532SDavid du Colombier }
4707edc7532SDavid du Colombier 
4717edc7532SDavid du Colombier int
zaddr(uchar * p,Adr * a,Sym * h[])4727edc7532SDavid du Colombier zaddr(uchar *p, Adr *a, Sym *h[])
4737edc7532SDavid du Colombier {
4747edc7532SDavid du Colombier 	int i, c;
4757edc7532SDavid du Colombier 	long l;
4767edc7532SDavid du Colombier 	Sym *s;
4777edc7532SDavid du Colombier 	Auto *u;
4787edc7532SDavid du Colombier 
4797edc7532SDavid du Colombier 	c = p[2];
4807edc7532SDavid du Colombier 	if(c < 0 || c > NSYM){
4817edc7532SDavid du Colombier 		print("sym out of range: %d\n", c);
4827edc7532SDavid du Colombier 		p[0] = ALAST+1;
4837edc7532SDavid du Colombier 		return 0;
4847edc7532SDavid du Colombier 	}
4857edc7532SDavid du Colombier 	a->type = p[0];
4867edc7532SDavid du Colombier 	a->reg = p[1];
4877edc7532SDavid du Colombier 	a->sym = h[c];
4887edc7532SDavid du Colombier 	a->name = p[3];
4897edc7532SDavid du Colombier 	c = 4;
4907edc7532SDavid du Colombier 
4917edc7532SDavid du Colombier 	if(a->reg < 0 || a->reg > NREG) {
4927edc7532SDavid du Colombier 		print("register out of range %d\n", a->reg);
4937edc7532SDavid du Colombier 		p[0] = ALAST+1;
4947edc7532SDavid du Colombier 		return 0;	/*  force real diagnostic */
4957edc7532SDavid du Colombier 	}
4967edc7532SDavid du Colombier 
4977edc7532SDavid du Colombier 	switch(a->type) {
4987edc7532SDavid du Colombier 	default:
4997edc7532SDavid du Colombier 		print("unknown type %d\n", a->type);
5007edc7532SDavid du Colombier 		p[0] = ALAST+1;
5017edc7532SDavid du Colombier 		return 0;	/*  force real diagnostic */
5027edc7532SDavid du Colombier 
5037edc7532SDavid du Colombier 	case D_NONE:
5047edc7532SDavid du Colombier 	case D_REG:
5057edc7532SDavid du Colombier 	case D_FREG:
5067edc7532SDavid du Colombier 	case D_MREG:
5077edc7532SDavid du Colombier 	case D_FCREG:
5087edc7532SDavid du Colombier 	case D_LO:
5097edc7532SDavid du Colombier 	case D_HI:
5107edc7532SDavid du Colombier 		break;
5117edc7532SDavid du Colombier 
5127edc7532SDavid du Colombier 	case D_BRANCH:
5137edc7532SDavid du Colombier 	case D_OREG:
5147edc7532SDavid du Colombier 	case D_CONST:
5157edc7532SDavid du Colombier 	case D_OCONST:
516*f8bc6aafSDavid du Colombier 		l = p[4] | (p[5]<<8) | (p[6]<<16) | (p[7]<<24);
517*f8bc6aafSDavid du Colombier 		a->offset = l;
5187edc7532SDavid du Colombier 		c += 4;
5197edc7532SDavid du Colombier 		break;
5207edc7532SDavid du Colombier 
5217edc7532SDavid du Colombier 	case D_SCONST:
522*f8bc6aafSDavid du Colombier 		while(nhunk < NSNAME)
523*f8bc6aafSDavid du Colombier 			gethunk();
524*f8bc6aafSDavid du Colombier 		a->sval = (char*)hunk;
525*f8bc6aafSDavid du Colombier 		nhunk -= NSNAME;
526*f8bc6aafSDavid du Colombier 		hunk += NSNAME;
527*f8bc6aafSDavid du Colombier 
5287edc7532SDavid du Colombier 		memmove(a->sval, p+4, NSNAME);
5297edc7532SDavid du Colombier 		c += NSNAME;
5307edc7532SDavid du Colombier 		break;
5317edc7532SDavid du Colombier 
5327edc7532SDavid du Colombier 	case D_FCONST:
533*f8bc6aafSDavid du Colombier 		while(nhunk < sizeof(Ieee))
534*f8bc6aafSDavid du Colombier 			gethunk();
535*f8bc6aafSDavid du Colombier 		a->ieee = (Ieee*)hunk;
536*f8bc6aafSDavid du Colombier 		nhunk -= sizeof(Ieee);
537*f8bc6aafSDavid du Colombier 		hunk += sizeof(Ieee);
538*f8bc6aafSDavid du Colombier 
5397edc7532SDavid du Colombier 		a->ieee->l = p[4] | (p[5]<<8) |
5407edc7532SDavid du Colombier 			(p[6]<<16) | (p[7]<<24);
5417edc7532SDavid du Colombier 		a->ieee->h = p[8] | (p[9]<<8) |
5427edc7532SDavid du Colombier 			(p[10]<<16) | (p[11]<<24);
5437edc7532SDavid du Colombier 		c += 8;
5447edc7532SDavid du Colombier 		break;
5457edc7532SDavid du Colombier 
5467edc7532SDavid du Colombier 	case D_VCONST:
547*f8bc6aafSDavid du Colombier 		l = p[4] | (p[5]<<8) | (p[6]<<16) | (p[7]<<24);
548*f8bc6aafSDavid du Colombier 		a->offset = (uvlong)l & 0xfffffffful;
549*f8bc6aafSDavid du Colombier 		l = p[8] | (p[9]<<8) | (p[10]<<16) | (p[11]<<24);
550*f8bc6aafSDavid du Colombier 		a->offset |= (vlong)l << 32;
5517edc7532SDavid du Colombier 		c += 8;
552*f8bc6aafSDavid du Colombier 		a->type = D_CONST;
5537edc7532SDavid du Colombier 		break;
5547edc7532SDavid du Colombier 	}
5557edc7532SDavid du Colombier 	s = a->sym;
5567edc7532SDavid du Colombier 	if(s == S)
5577edc7532SDavid du Colombier 		return c;
5587edc7532SDavid du Colombier 	i = a->name;
5597edc7532SDavid du Colombier 	if(i != D_AUTO && i != D_PARAM)
5607edc7532SDavid du Colombier 		return c;
5617edc7532SDavid du Colombier 
5627edc7532SDavid du Colombier 	l = a->offset;
5637edc7532SDavid du Colombier 	for(u=curauto; u; u=u->link)
5647edc7532SDavid du Colombier 		if(u->asym == s)
5657edc7532SDavid du Colombier 		if(u->type == i) {
5667edc7532SDavid du Colombier 			if(u->aoffset > l)
5677edc7532SDavid du Colombier 				u->aoffset = l;
5687edc7532SDavid du Colombier 			return c;
5697edc7532SDavid du Colombier 		}
5707edc7532SDavid du Colombier 
5717edc7532SDavid du Colombier 	while(nhunk < sizeof(Auto))
5727edc7532SDavid du Colombier 		gethunk();
5737edc7532SDavid du Colombier 	u = (Auto*)hunk;
5747edc7532SDavid du Colombier 	nhunk -= sizeof(Auto);
5757edc7532SDavid du Colombier 	hunk += sizeof(Auto);
5767edc7532SDavid du Colombier 
5777edc7532SDavid du Colombier 	u->link = curauto;
5787edc7532SDavid du Colombier 	curauto = u;
5797edc7532SDavid du Colombier 	u->asym = s;
5807edc7532SDavid du Colombier 	u->aoffset = l;
5817edc7532SDavid du Colombier 	u->type = i;
5827edc7532SDavid du Colombier 	return c;
5837edc7532SDavid du Colombier }
5847edc7532SDavid du Colombier 
5857edc7532SDavid du Colombier void
addlib(char * obj)5867edc7532SDavid du Colombier addlib(char *obj)
5877edc7532SDavid du Colombier {
588*f8bc6aafSDavid du Colombier 	char fn1[LIBNAMELEN], fn2[LIBNAMELEN], comp[LIBNAMELEN], *p, *name;
589*f8bc6aafSDavid du Colombier 	int i, search;
5907edc7532SDavid du Colombier 
5917edc7532SDavid du Colombier 	if(histfrogp <= 0)
5927edc7532SDavid du Colombier 		return;
5937edc7532SDavid du Colombier 
594*f8bc6aafSDavid du Colombier 	name = fn1;
595*f8bc6aafSDavid du Colombier 	search = 0;
5967edc7532SDavid du Colombier 	if(histfrog[0]->name[1] == '/') {
5977edc7532SDavid du Colombier 		sprint(name, "");
5987edc7532SDavid du Colombier 		i = 1;
599*f8bc6aafSDavid du Colombier 	} else if(histfrog[0]->name[1] == '.') {
6007edc7532SDavid du Colombier 		sprint(name, ".");
6017edc7532SDavid du Colombier 		i = 0;
6027edc7532SDavid du Colombier 	} else {
603*f8bc6aafSDavid du Colombier 		sprint(name, "");
6047edc7532SDavid du Colombier 		i = 0;
605*f8bc6aafSDavid du Colombier 		search = 1;
6067edc7532SDavid du Colombier 	}
6077edc7532SDavid du Colombier 
6087edc7532SDavid du Colombier 	for(; i<histfrogp; i++) {
6097edc7532SDavid du Colombier 		snprint(comp, sizeof comp, histfrog[i]->name+1);
6107edc7532SDavid du Colombier 		for(;;) {
6117edc7532SDavid du Colombier 			p = strstr(comp, "$O");
6127edc7532SDavid du Colombier 			if(p == 0)
6137edc7532SDavid du Colombier 				break;
6147edc7532SDavid du Colombier 			memmove(p+1, p+2, strlen(p+2)+1);
6157edc7532SDavid du Colombier 			p[0] = thechar;
6167edc7532SDavid du Colombier 		}
6177edc7532SDavid du Colombier 		for(;;) {
6187edc7532SDavid du Colombier 			p = strstr(comp, "$M");
6197edc7532SDavid du Colombier 			if(p == 0)
6207edc7532SDavid du Colombier 				break;
6217edc7532SDavid du Colombier 			if(strlen(comp)+strlen(thestring)-2+1 >= sizeof comp) {
6227edc7532SDavid du Colombier 				diag("library component too long");
6237edc7532SDavid du Colombier 				return;
6247edc7532SDavid du Colombier 			}
6257edc7532SDavid du Colombier 			memmove(p+strlen(thestring), p+2, strlen(p+2)+1);
6267edc7532SDavid du Colombier 			memmove(p, thestring, strlen(thestring));
6277edc7532SDavid du Colombier 		}
628*f8bc6aafSDavid du Colombier 		if(strlen(fn1) + strlen(comp) + 3 >= sizeof(fn1)) {
6297edc7532SDavid du Colombier 			diag("library component too long");
6307edc7532SDavid du Colombier 			return;
6317edc7532SDavid du Colombier 		}
632*f8bc6aafSDavid du Colombier 		if(i > 0 || !search)
633*f8bc6aafSDavid du Colombier 			strcat(fn1, "/");
634*f8bc6aafSDavid du Colombier 		strcat(fn1, comp);
6357edc7532SDavid du Colombier 	}
636*f8bc6aafSDavid du Colombier 
637*f8bc6aafSDavid du Colombier 	cleanname(name);
638*f8bc6aafSDavid du Colombier 
639*f8bc6aafSDavid du Colombier 	if(search){
640*f8bc6aafSDavid du Colombier 		p = findlib(name);
641*f8bc6aafSDavid du Colombier 		if(p != nil){
642*f8bc6aafSDavid du Colombier 			snprint(fn2, sizeof(fn2), "%s/%s", p, name);
643*f8bc6aafSDavid du Colombier 			name = fn2;
644*f8bc6aafSDavid du Colombier 		}
645*f8bc6aafSDavid du Colombier 	}
646*f8bc6aafSDavid du Colombier 
6477edc7532SDavid du Colombier 	for(i=0; i<libraryp; i++)
6487edc7532SDavid du Colombier 		if(strcmp(name, library[i]) == 0)
6497edc7532SDavid du Colombier 			return;
6507edc7532SDavid du Colombier 	if(libraryp == nelem(library)){
6517edc7532SDavid du Colombier 		diag("too many autolibs; skipping %s", name);
6527edc7532SDavid du Colombier 		return;
6537edc7532SDavid du Colombier 	}
6547edc7532SDavid du Colombier 
6557edc7532SDavid du Colombier 	p = malloc(strlen(name) + 1);
6567edc7532SDavid du Colombier 	strcpy(p, name);
6577edc7532SDavid du Colombier 	library[libraryp] = p;
6587edc7532SDavid du Colombier 	p = malloc(strlen(obj) + 1);
6597edc7532SDavid du Colombier 	strcpy(p, obj);
6607edc7532SDavid du Colombier 	libraryobj[libraryp] = p;
6617edc7532SDavid du Colombier 	libraryp++;
6627edc7532SDavid du Colombier }
6637edc7532SDavid du Colombier 
6647edc7532SDavid du Colombier void
addhist(long line,int type)6657edc7532SDavid du Colombier addhist(long line, int type)
6667edc7532SDavid du Colombier {
6677edc7532SDavid du Colombier 	Auto *u;
6687edc7532SDavid du Colombier 	Sym *s;
6697edc7532SDavid du Colombier 	int i, j, k;
6707edc7532SDavid du Colombier 
6717edc7532SDavid du Colombier 	u = malloc(sizeof(Auto));
6727edc7532SDavid du Colombier 	s = malloc(sizeof(Sym));
6737edc7532SDavid du Colombier 	s->name = malloc(2*(histfrogp+1) + 1);
6747edc7532SDavid du Colombier 
6757edc7532SDavid du Colombier 	u->asym = s;
6767edc7532SDavid du Colombier 	u->type = type;
6777edc7532SDavid du Colombier 	u->aoffset = line;
6787edc7532SDavid du Colombier 	u->link = curhist;
6797edc7532SDavid du Colombier 	curhist = u;
6807edc7532SDavid du Colombier 
6817edc7532SDavid du Colombier 	j = 1;
6827edc7532SDavid du Colombier 	for(i=0; i<histfrogp; i++) {
6837edc7532SDavid du Colombier 		k = histfrog[i]->value;
6847edc7532SDavid du Colombier 		s->name[j+0] = k>>8;
6857edc7532SDavid du Colombier 		s->name[j+1] = k;
6867edc7532SDavid du Colombier 		j += 2;
6877edc7532SDavid du Colombier 	}
6887edc7532SDavid du Colombier }
6897edc7532SDavid du Colombier 
6907edc7532SDavid du Colombier void
histtoauto(void)6917edc7532SDavid du Colombier histtoauto(void)
6927edc7532SDavid du Colombier {
6937edc7532SDavid du Colombier 	Auto *l;
6947edc7532SDavid du Colombier 
6957edc7532SDavid du Colombier 	while(l = curhist) {
6967edc7532SDavid du Colombier 		curhist = l->link;
6977edc7532SDavid du Colombier 		l->link = curauto;
6987edc7532SDavid du Colombier 		curauto = l;
6997edc7532SDavid du Colombier 	}
7007edc7532SDavid du Colombier }
7017edc7532SDavid du Colombier 
7027edc7532SDavid du Colombier void
collapsefrog(Sym * s)7037edc7532SDavid du Colombier collapsefrog(Sym *s)
7047edc7532SDavid du Colombier {
7057edc7532SDavid du Colombier 	int i;
7067edc7532SDavid du Colombier 
7077edc7532SDavid du Colombier 	/*
7087edc7532SDavid du Colombier 	 * bad encoding of path components only allows
7097edc7532SDavid du Colombier 	 * MAXHIST components. if there is an overflow,
7107edc7532SDavid du Colombier 	 * first try to collapse xxx/..
7117edc7532SDavid du Colombier 	 */
7127edc7532SDavid du Colombier 	for(i=1; i<histfrogp; i++)
7137edc7532SDavid du Colombier 		if(strcmp(histfrog[i]->name+1, "..") == 0) {
7147edc7532SDavid du Colombier 			memmove(histfrog+i-1, histfrog+i+1,
7157edc7532SDavid du Colombier 				(histfrogp-i-1)*sizeof(histfrog[0]));
7167edc7532SDavid du Colombier 			histfrogp--;
7177edc7532SDavid du Colombier 			goto out;
7187edc7532SDavid du Colombier 		}
7197edc7532SDavid du Colombier 
7207edc7532SDavid du Colombier 	/*
7217edc7532SDavid du Colombier 	 * next try to collapse .
7227edc7532SDavid du Colombier 	 */
7237edc7532SDavid du Colombier 	for(i=0; i<histfrogp; i++)
7247edc7532SDavid du Colombier 		if(strcmp(histfrog[i]->name+1, ".") == 0) {
7257edc7532SDavid du Colombier 			memmove(histfrog+i, histfrog+i+1,
7267edc7532SDavid du Colombier 				(histfrogp-i-1)*sizeof(histfrog[0]));
7277edc7532SDavid du Colombier 			goto out;
7287edc7532SDavid du Colombier 		}
7297edc7532SDavid du Colombier 
7307edc7532SDavid du Colombier 	/*
7317edc7532SDavid du Colombier 	 * last chance, just truncate from front
7327edc7532SDavid du Colombier 	 */
7337edc7532SDavid du Colombier 	memmove(histfrog+0, histfrog+1,
7347edc7532SDavid du Colombier 		(histfrogp-1)*sizeof(histfrog[0]));
7357edc7532SDavid du Colombier 
7367edc7532SDavid du Colombier out:
7377edc7532SDavid du Colombier 	histfrog[histfrogp-1] = s;
7387edc7532SDavid du Colombier }
7397edc7532SDavid du Colombier 
7407edc7532SDavid du Colombier void
nopout(Prog * p)7417edc7532SDavid du Colombier nopout(Prog *p)
7427edc7532SDavid du Colombier {
7437edc7532SDavid du Colombier 	p->as = ANOP;
7447edc7532SDavid du Colombier 	p->from.type = D_NONE;
7457edc7532SDavid du Colombier 	p->to.type = D_NONE;
7467edc7532SDavid du Colombier }
7477edc7532SDavid du Colombier 
7487edc7532SDavid du Colombier uchar*
readsome(int f,uchar * buf,uchar * good,uchar * stop,int max)7497edc7532SDavid du Colombier readsome(int f, uchar *buf, uchar *good, uchar *stop, int max)
7507edc7532SDavid du Colombier {
7517edc7532SDavid du Colombier 	int n;
7527edc7532SDavid du Colombier 
7537edc7532SDavid du Colombier 	n = stop - good;
7547edc7532SDavid du Colombier 	memmove(buf, good, stop - good);
7557edc7532SDavid du Colombier 	stop = buf + n;
7567edc7532SDavid du Colombier 	n = MAXIO - n;
7577edc7532SDavid du Colombier 	if(n > max)
7587edc7532SDavid du Colombier 		n = max;
7597edc7532SDavid du Colombier 	n = read(f, stop, n);
7607edc7532SDavid du Colombier 	if(n <= 0)
7617edc7532SDavid du Colombier 		return 0;
7627edc7532SDavid du Colombier 	return stop + n;
7637edc7532SDavid du Colombier }
7647edc7532SDavid du Colombier 
7657edc7532SDavid du Colombier void
ldobj(int f,long c,char * pn)7667edc7532SDavid du Colombier ldobj(int f, long c, char *pn)
7677edc7532SDavid du Colombier {
7687edc7532SDavid du Colombier 	vlong ipc;
7697edc7532SDavid du Colombier 	Prog *p, *t;
7707edc7532SDavid du Colombier 	uchar *bloc, *bsize, *stop;
7717edc7532SDavid du Colombier 	Sym *h[NSYM], *s, *di;
7727edc7532SDavid du Colombier 	int v, o, r, skip;
7737edc7532SDavid du Colombier 
7747edc7532SDavid du Colombier 	bsize = buf.xbuf;
7757edc7532SDavid du Colombier 	bloc = buf.xbuf;
7767edc7532SDavid du Colombier 	di = S;
7777edc7532SDavid du Colombier 
7787edc7532SDavid du Colombier newloop:
7797edc7532SDavid du Colombier 	memset(h, 0, sizeof(h));
7807edc7532SDavid du Colombier 	version++;
7817edc7532SDavid du Colombier 	histfrogp = 0;
7827edc7532SDavid du Colombier 	ipc = pc;
7837edc7532SDavid du Colombier 	skip = 0;
7847edc7532SDavid du Colombier 
7857edc7532SDavid du Colombier loop:
7867edc7532SDavid du Colombier 	if(c <= 0)
7877edc7532SDavid du Colombier 		goto eof;
7887edc7532SDavid du Colombier 	r = bsize - bloc;
7897edc7532SDavid du Colombier 	if(r < 100 && r < c) {		/* enough for largest prog */
7907edc7532SDavid du Colombier 		bsize = readsome(f, buf.xbuf, bloc, bsize, c);
7917edc7532SDavid du Colombier 		if(bsize == 0)
7927edc7532SDavid du Colombier 			goto eof;
7937edc7532SDavid du Colombier 		bloc = buf.xbuf;
7947edc7532SDavid du Colombier 		goto loop;
7957edc7532SDavid du Colombier 	}
7967edc7532SDavid du Colombier 	o = bloc[0];		/* as */
7977edc7532SDavid du Colombier 	if(o <= AXXX || o >= ALAST) {
798*f8bc6aafSDavid du Colombier 		diag("%s: line %lld: opcode out of range %d", pn, pc-ipc, o);
799*f8bc6aafSDavid du Colombier 		print("	probably not a .%c file\n", thechar);
8007edc7532SDavid du Colombier 		errorexit();
8017edc7532SDavid du Colombier 	}
802*f8bc6aafSDavid du Colombier 	if(o == ANAME || o == ASIGNAME) {
803*f8bc6aafSDavid du Colombier 		if(o == ASIGNAME) {
804*f8bc6aafSDavid du Colombier 			bloc += 4;
805*f8bc6aafSDavid du Colombier 			c -= 4;
806*f8bc6aafSDavid du Colombier 		}
8077edc7532SDavid du Colombier 		stop = memchr(&bloc[3], 0, bsize-&bloc[3]);
8087edc7532SDavid du Colombier 		if(stop == 0){
8097edc7532SDavid du Colombier 			bsize = readsome(f, buf.xbuf, bloc, bsize, c);
8107edc7532SDavid du Colombier 			if(bsize == 0)
8117edc7532SDavid du Colombier 				goto eof;
8127edc7532SDavid du Colombier 			bloc = buf.xbuf;
8137edc7532SDavid du Colombier 			stop = memchr(&bloc[3], 0, bsize-&bloc[3]);
8147edc7532SDavid du Colombier 			if(stop == 0){
8157edc7532SDavid du Colombier 				fprint(2, "%s: name too long\n", pn);
8167edc7532SDavid du Colombier 				errorexit();
8177edc7532SDavid du Colombier 			}
8187edc7532SDavid du Colombier 		}
8197edc7532SDavid du Colombier 		v = bloc[1];	/* type */
8207edc7532SDavid du Colombier 		o = bloc[2];	/* sym */
8217edc7532SDavid du Colombier 		bloc += 3;
8227edc7532SDavid du Colombier 		c -= 3;
8237edc7532SDavid du Colombier 
8247edc7532SDavid du Colombier 		r = 0;
8257edc7532SDavid du Colombier 		if(v == D_STATIC)
8267edc7532SDavid du Colombier 			r = version;
8277edc7532SDavid du Colombier 		s = lookup((char*)bloc, r);
8287edc7532SDavid du Colombier 		c -= &stop[1] - bloc;
8297edc7532SDavid du Colombier 		bloc = stop + 1;
8307edc7532SDavid du Colombier 
8317edc7532SDavid du Colombier 		if(debug['W'])
8327edc7532SDavid du Colombier 			print("	ANAME	%s\n", s->name);
8337edc7532SDavid du Colombier 		h[o] = s;
8347edc7532SDavid du Colombier 		if((v == D_EXTERN || v == D_STATIC) && s->type == 0)
8357edc7532SDavid du Colombier 			s->type = SXREF;
8367edc7532SDavid du Colombier 		if(v == D_FILE) {
8377edc7532SDavid du Colombier 			if(s->type != SFILE) {
8387edc7532SDavid du Colombier 				histgen++;
8397edc7532SDavid du Colombier 				s->type = SFILE;
8407edc7532SDavid du Colombier 				s->value = histgen;
8417edc7532SDavid du Colombier 			}
8427edc7532SDavid du Colombier 			if(histfrogp < MAXHIST) {
8437edc7532SDavid du Colombier 				histfrog[histfrogp] = s;
8447edc7532SDavid du Colombier 				histfrogp++;
8457edc7532SDavid du Colombier 			} else
8467edc7532SDavid du Colombier 				collapsefrog(s);
8477edc7532SDavid du Colombier 		}
8487edc7532SDavid du Colombier 		goto loop;
8497edc7532SDavid du Colombier 	}
8507edc7532SDavid du Colombier 
8517edc7532SDavid du Colombier 	if(nhunk < sizeof(Prog))
8527edc7532SDavid du Colombier 		gethunk();
8537edc7532SDavid du Colombier 	p = (Prog*)hunk;
8547edc7532SDavid du Colombier 	nhunk -= sizeof(Prog);
8557edc7532SDavid du Colombier 	hunk += sizeof(Prog);
8567edc7532SDavid du Colombier 
8577edc7532SDavid du Colombier 	p->as = o;
8587edc7532SDavid du Colombier 	p->reg = bloc[1] & 0x7f;
8597edc7532SDavid du Colombier 	if(bloc[1] & 0x80)
8607edc7532SDavid du Colombier 		p->mark = NOSCHED;
8617edc7532SDavid du Colombier 	p->line = bloc[2] | (bloc[3]<<8) | (bloc[4]<<16) | (bloc[5]<<24);
8627edc7532SDavid du Colombier 
8637edc7532SDavid du Colombier 	r = zaddr(bloc+6, &p->from, h) + 6;
8647edc7532SDavid du Colombier 	r += zaddr(bloc+r, &p->to, h);
8657edc7532SDavid du Colombier 	bloc += r;
8667edc7532SDavid du Colombier 	c -= r;
8677edc7532SDavid du Colombier 
8687edc7532SDavid du Colombier 	if(p->reg < 0 || p->reg > NREG)
8697edc7532SDavid du Colombier 		diag("register out of range %d", p->reg);
8707edc7532SDavid du Colombier 
8717edc7532SDavid du Colombier 	p->link = P;
8727edc7532SDavid du Colombier 	p->cond = P;
8737edc7532SDavid du Colombier 
8747edc7532SDavid du Colombier 	if(debug['W'])
8757edc7532SDavid du Colombier 		print("%P\n", p);
8767edc7532SDavid du Colombier 
8777edc7532SDavid du Colombier 	switch(o) {
8787edc7532SDavid du Colombier 	case AHISTORY:
8797edc7532SDavid du Colombier 		if(p->to.offset == -1) {
8807edc7532SDavid du Colombier 			addlib(pn);
8817edc7532SDavid du Colombier 			histfrogp = 0;
8827edc7532SDavid du Colombier 			goto loop;
8837edc7532SDavid du Colombier 		}
8847edc7532SDavid du Colombier 		addhist(p->line, D_FILE);		/* 'z' */
8857edc7532SDavid du Colombier 		if(p->to.offset)
8867edc7532SDavid du Colombier 			addhist(p->to.offset, D_FILE1);	/* 'Z' */
8877edc7532SDavid du Colombier 		histfrogp = 0;
8887edc7532SDavid du Colombier 		goto loop;
8897edc7532SDavid du Colombier 
8907edc7532SDavid du Colombier 	case AEND:
8917edc7532SDavid du Colombier 		histtoauto();
8927edc7532SDavid du Colombier 		if(curtext != P)
8937edc7532SDavid du Colombier 			curtext->to.autom = curauto;
8947edc7532SDavid du Colombier 		curauto = 0;
8957edc7532SDavid du Colombier 		curtext = P;
8967edc7532SDavid du Colombier 		if(c)
8977edc7532SDavid du Colombier 			goto newloop;
8987edc7532SDavid du Colombier 		return;
8997edc7532SDavid du Colombier 
9007edc7532SDavid du Colombier 	case AGLOBL:
9017edc7532SDavid du Colombier 		s = p->from.sym;
9027edc7532SDavid du Colombier 		if(s == S) {
9037edc7532SDavid du Colombier 			diag("GLOBL must have a name\n%P", p);
9047edc7532SDavid du Colombier 			errorexit();
9057edc7532SDavid du Colombier 		}
9067edc7532SDavid du Colombier 		if(s->type == 0 || s->type == SXREF) {
9077edc7532SDavid du Colombier 			s->type = SBSS;
9087edc7532SDavid du Colombier 			s->value = 0;
9097edc7532SDavid du Colombier 		}
9107edc7532SDavid du Colombier 		if(s->type != SBSS) {
9117edc7532SDavid du Colombier 			diag("redefinition: %s\n%P", s->name, p);
9127edc7532SDavid du Colombier 			s->type = SBSS;
9137edc7532SDavid du Colombier 			s->value = 0;
9147edc7532SDavid du Colombier 		}
9157edc7532SDavid du Colombier 		if(p->to.offset > s->value)
9167edc7532SDavid du Colombier 			s->value = p->to.offset;
9177edc7532SDavid du Colombier 		break;
9187edc7532SDavid du Colombier 
9197edc7532SDavid du Colombier 	case ADYNT:
9207edc7532SDavid du Colombier 		if(p->to.sym == S) {
9217edc7532SDavid du Colombier 			diag("DYNT without a sym\n%P", p);
9227edc7532SDavid du Colombier 			break;
9237edc7532SDavid du Colombier 		}
9247edc7532SDavid du Colombier 		di = p->to.sym;
9257edc7532SDavid du Colombier 		p->reg = 4;
9267edc7532SDavid du Colombier 		if(di->type == SXREF) {
9277edc7532SDavid du Colombier 			if(debug['z'])
9287edc7532SDavid du Colombier 				Bprint(&bso, "%P set to %d\n", p, dtype);
9297edc7532SDavid du Colombier 			di->type = SCONST;
9307edc7532SDavid du Colombier 			di->value = dtype;
9317edc7532SDavid du Colombier 			dtype += 4;
9327edc7532SDavid du Colombier 		}
9337edc7532SDavid du Colombier 		if(p->from.sym == S)
9347edc7532SDavid du Colombier 			break;
9357edc7532SDavid du Colombier 
9367edc7532SDavid du Colombier 		p->from.offset = di->value;
9377edc7532SDavid du Colombier 		p->from.sym->type = SDATA;
9387edc7532SDavid du Colombier 		if(curtext == P) {
9397edc7532SDavid du Colombier 			diag("DYNT not in text: %P", p);
9407edc7532SDavid du Colombier 			break;
9417edc7532SDavid du Colombier 		}
9427edc7532SDavid du Colombier 		p->to.sym = curtext->from.sym;
9437edc7532SDavid du Colombier 		p->to.type = D_CONST;
9447edc7532SDavid du Colombier 		p->link = datap;
9457edc7532SDavid du Colombier 		datap = p;
9467edc7532SDavid du Colombier 		break;
9477edc7532SDavid du Colombier 
9487edc7532SDavid du Colombier 	case AINIT:
9497edc7532SDavid du Colombier 		if(p->from.sym == S) {
9507edc7532SDavid du Colombier 			diag("INIT without a sym\n%P", p);
9517edc7532SDavid du Colombier 			break;
9527edc7532SDavid du Colombier 		}
9537edc7532SDavid du Colombier 		if(di == S) {
9547edc7532SDavid du Colombier 			diag("INIT without previous DYNT\n%P", p);
9557edc7532SDavid du Colombier 			break;
9567edc7532SDavid du Colombier 		}
9577edc7532SDavid du Colombier 		p->from.offset = di->value;
9587edc7532SDavid du Colombier 		p->from.sym->type = SDATA;
9597edc7532SDavid du Colombier 		p->link = datap;
9607edc7532SDavid du Colombier 		datap = p;
9617edc7532SDavid du Colombier 		break;
9627edc7532SDavid du Colombier 
9637edc7532SDavid du Colombier 	case ADATA:
9647edc7532SDavid du Colombier 		if(p->from.sym == S) {
9657edc7532SDavid du Colombier 			diag("DATA without a sym\n%P", p);
9667edc7532SDavid du Colombier 			break;
9677edc7532SDavid du Colombier 		}
9687edc7532SDavid du Colombier 		p->link = datap;
9697edc7532SDavid du Colombier 		datap = p;
9707edc7532SDavid du Colombier 		break;
9717edc7532SDavid du Colombier 
9727edc7532SDavid du Colombier 	case AGOK:
9737edc7532SDavid du Colombier 		diag("unknown opcode\n%P", p);
9747edc7532SDavid du Colombier 		p->pc = pc;
9757edc7532SDavid du Colombier 		pc++;
9767edc7532SDavid du Colombier 		break;
9777edc7532SDavid du Colombier 
9787edc7532SDavid du Colombier 	case ATEXT:
9797edc7532SDavid du Colombier 		if(curtext != P) {
9807edc7532SDavid du Colombier 			histtoauto();
9817edc7532SDavid du Colombier 			curtext->to.autom = curauto;
9827edc7532SDavid du Colombier 			curauto = 0;
9837edc7532SDavid du Colombier 		}
9847edc7532SDavid du Colombier 		skip = 0;
9857edc7532SDavid du Colombier 		curtext = p;
9867edc7532SDavid du Colombier 		s = p->from.sym;
9877edc7532SDavid du Colombier 		if(s == S) {
9887edc7532SDavid du Colombier 			diag("TEXT must have a name\n%P", p);
9897edc7532SDavid du Colombier 			errorexit();
9907edc7532SDavid du Colombier 		}
9917edc7532SDavid du Colombier 		autosize = p->to.offset;
9927edc7532SDavid du Colombier 		if(autosize & 7) {
9937edc7532SDavid du Colombier 			diag("stack frame not 8 multiple: %s\n%P", s->name, p);
9947edc7532SDavid du Colombier 			autosize = autosize + 7 & ~7;
9957edc7532SDavid du Colombier 			p->to.offset = autosize;
9967edc7532SDavid du Colombier 		}
9977edc7532SDavid du Colombier 		autosize += 8;
9987edc7532SDavid du Colombier 		if(s->type != 0 && s->type != SXREF) {
9997edc7532SDavid du Colombier 			if(p->reg & DUPOK) {
10007edc7532SDavid du Colombier 				skip = 1;
10017edc7532SDavid du Colombier 				goto casedef;
10027edc7532SDavid du Colombier 			}
10037edc7532SDavid du Colombier 			diag("redefinition: %s\n%P", s->name, p);
10047edc7532SDavid du Colombier 		}
10057edc7532SDavid du Colombier 		s->type = STEXT;
10067edc7532SDavid du Colombier 		s->value = pc;
10077edc7532SDavid du Colombier 		lastp->link = p;
10087edc7532SDavid du Colombier 		lastp = p;
10097edc7532SDavid du Colombier 		p->pc = pc;
10107edc7532SDavid du Colombier 		pc++;
10117edc7532SDavid du Colombier 		if(textp == P) {
10127edc7532SDavid du Colombier 			textp = p;
10137edc7532SDavid du Colombier 			etextp = p;
10147edc7532SDavid du Colombier 			goto loop;
10157edc7532SDavid du Colombier 		}
10167edc7532SDavid du Colombier 		etextp->cond = p;
10177edc7532SDavid du Colombier 		etextp = p;
10187edc7532SDavid du Colombier 		break;
10197edc7532SDavid du Colombier 
10207edc7532SDavid du Colombier 	case ASUB:
10217edc7532SDavid du Colombier 	case ASUBU:
10227edc7532SDavid du Colombier 		if(p->from.type == D_CONST)
10237edc7532SDavid du Colombier 		if(p->from.name == D_NONE) {
10247edc7532SDavid du Colombier 			p->from.offset = -p->from.offset;
10257edc7532SDavid du Colombier 			if(p->as == ASUB)
10267edc7532SDavid du Colombier 				p->as = AADD;
10277edc7532SDavid du Colombier 			else
10287edc7532SDavid du Colombier 				p->as = AADDU;
10297edc7532SDavid du Colombier 		}
10307edc7532SDavid du Colombier 		goto casedef;
10317edc7532SDavid du Colombier 
1032*f8bc6aafSDavid du Colombier 	case ASUBV:
1033*f8bc6aafSDavid du Colombier 	case ASUBVU:
1034*f8bc6aafSDavid du Colombier 		if(p->from.type == D_CONST)
1035*f8bc6aafSDavid du Colombier 		if(p->from.name == D_NONE) {
1036*f8bc6aafSDavid du Colombier 			p->from.offset = -p->from.offset;
1037*f8bc6aafSDavid du Colombier 			if(p->as == ASUBV)
1038*f8bc6aafSDavid du Colombier 				p->as = AADDV;
1039*f8bc6aafSDavid du Colombier 			else
1040*f8bc6aafSDavid du Colombier 				p->as = AADDVU;
1041*f8bc6aafSDavid du Colombier 		}
1042*f8bc6aafSDavid du Colombier 		goto casedef;
1043*f8bc6aafSDavid du Colombier 
10447edc7532SDavid du Colombier 	case AMOVF:
10457edc7532SDavid du Colombier 		if(skip)
10467edc7532SDavid du Colombier 			goto casedef;
10477edc7532SDavid du Colombier 
10487edc7532SDavid du Colombier 		if(p->from.type == D_FCONST) {
10497edc7532SDavid du Colombier 			/* size sb 9 max */
10507edc7532SDavid du Colombier 			sprint(literal, "$%lux", ieeedtof(p->from.ieee));
10517edc7532SDavid du Colombier 			s = lookup(literal, 0);
10527edc7532SDavid du Colombier 			if(s->type == 0) {
10537edc7532SDavid du Colombier 				s->type = SBSS;
10547edc7532SDavid du Colombier 				s->value = 4;
10557edc7532SDavid du Colombier 				t = prg();
10567edc7532SDavid du Colombier 				t->as = ADATA;
10577edc7532SDavid du Colombier 				t->line = p->line;
10587edc7532SDavid du Colombier 				t->from.type = D_OREG;
10597edc7532SDavid du Colombier 				t->from.sym = s;
10607edc7532SDavid du Colombier 				t->from.name = D_EXTERN;
10617edc7532SDavid du Colombier 				t->reg = 4;
10627edc7532SDavid du Colombier 				t->to = p->from;
10637edc7532SDavid du Colombier 				t->link = datap;
10647edc7532SDavid du Colombier 				datap = t;
10657edc7532SDavid du Colombier 			}
10667edc7532SDavid du Colombier 			p->from.type = D_OREG;
10677edc7532SDavid du Colombier 			p->from.sym = s;
10687edc7532SDavid du Colombier 			p->from.name = D_EXTERN;
10697edc7532SDavid du Colombier 			p->from.offset = 0;
10707edc7532SDavid du Colombier 		}
10717edc7532SDavid du Colombier 		goto casedef;
10727edc7532SDavid du Colombier 
10737edc7532SDavid du Colombier 	case AMOVD:
10747edc7532SDavid du Colombier 		if(skip)
10757edc7532SDavid du Colombier 			goto casedef;
10767edc7532SDavid du Colombier 
10777edc7532SDavid du Colombier 		if(p->from.type == D_FCONST) {
10787edc7532SDavid du Colombier 			/* size sb 18 max */
10797edc7532SDavid du Colombier 			sprint(literal, "$%lux.%lux",
1080*f8bc6aafSDavid du Colombier 				p->from.ieee->l, p->from.ieee->h);
10817edc7532SDavid du Colombier 			s = lookup(literal, 0);
10827edc7532SDavid du Colombier 			if(s->type == 0) {
10837edc7532SDavid du Colombier 				s->type = SBSS;
10847edc7532SDavid du Colombier 				s->value = 8;
10857edc7532SDavid du Colombier 				t = prg();
10867edc7532SDavid du Colombier 				t->as = ADATA;
10877edc7532SDavid du Colombier 				t->line = p->line;
10887edc7532SDavid du Colombier 				t->from.type = D_OREG;
10897edc7532SDavid du Colombier 				t->from.sym = s;
10907edc7532SDavid du Colombier 				t->from.name = D_EXTERN;
10917edc7532SDavid du Colombier 				t->reg = 8;
10927edc7532SDavid du Colombier 				t->to = p->from;
10937edc7532SDavid du Colombier 				t->link = datap;
10947edc7532SDavid du Colombier 				datap = t;
10957edc7532SDavid du Colombier 			}
10967edc7532SDavid du Colombier 			p->from.type = D_OREG;
10977edc7532SDavid du Colombier 			p->from.sym = s;
10987edc7532SDavid du Colombier 			p->from.name = D_EXTERN;
10997edc7532SDavid du Colombier 			p->from.offset = 0;
11007edc7532SDavid du Colombier 		}
11017edc7532SDavid du Colombier 		goto casedef;
11027edc7532SDavid du Colombier 
11037edc7532SDavid du Colombier 	case AMOVV:
11047edc7532SDavid du Colombier 		if(skip)
11057edc7532SDavid du Colombier 			goto casedef;
11067edc7532SDavid du Colombier 
1107*f8bc6aafSDavid du Colombier 		if(p->from.type == D_CONST)
1108*f8bc6aafSDavid du Colombier 		if(!isint32(p->from.offset)) {
11097edc7532SDavid du Colombier 			/* size sb 18 max */
1110*f8bc6aafSDavid du Colombier 			sprint(literal, "$%llux", p->from.offset);
11117edc7532SDavid du Colombier 			s = lookup(literal, 0);
11127edc7532SDavid du Colombier 			if(s->type == 0) {
11137edc7532SDavid du Colombier 				s->type = SBSS;
11147edc7532SDavid du Colombier 				s->value = 8;
11157edc7532SDavid du Colombier 				t = prg();
11167edc7532SDavid du Colombier 				t->as = ADATA;
11177edc7532SDavid du Colombier 				t->line = p->line;
11187edc7532SDavid du Colombier 				t->from.type = D_OREG;
11197edc7532SDavid du Colombier 				t->from.sym = s;
11207edc7532SDavid du Colombier 				t->from.name = D_EXTERN;
11217edc7532SDavid du Colombier 				t->reg = 8;
11227edc7532SDavid du Colombier 				t->to = p->from;
11237edc7532SDavid du Colombier 				t->link = datap;
11247edc7532SDavid du Colombier 				datap = t;
11257edc7532SDavid du Colombier 			}
11267edc7532SDavid du Colombier 			p->from.type = D_OREG;
11277edc7532SDavid du Colombier 			p->from.sym = s;
11287edc7532SDavid du Colombier 			p->from.name = D_EXTERN;
11297edc7532SDavid du Colombier 			p->from.offset = 0;
11307edc7532SDavid du Colombier 		}
11317edc7532SDavid du Colombier 		goto casedef;
11327edc7532SDavid du Colombier 
11337edc7532SDavid du Colombier 	default:
11347edc7532SDavid du Colombier 	casedef:
11357edc7532SDavid du Colombier 		if(skip)
11367edc7532SDavid du Colombier 			nopout(p);
11377edc7532SDavid du Colombier 
11387edc7532SDavid du Colombier 		if(p->to.type == D_BRANCH)
11397edc7532SDavid du Colombier 			p->to.offset += ipc;
11407edc7532SDavid du Colombier 		lastp->link = p;
11417edc7532SDavid du Colombier 		lastp = p;
11427edc7532SDavid du Colombier 		p->pc = pc;
11437edc7532SDavid du Colombier 		pc++;
11447edc7532SDavid du Colombier 		break;
11457edc7532SDavid du Colombier 	}
11467edc7532SDavid du Colombier 	goto loop;
11477edc7532SDavid du Colombier 
11487edc7532SDavid du Colombier eof:
11497edc7532SDavid du Colombier 	diag("truncated object file: %s", pn);
11507edc7532SDavid du Colombier }
11517edc7532SDavid du Colombier 
11527edc7532SDavid du Colombier Sym*
lookup(char * symb,int v)11537edc7532SDavid du Colombier lookup(char *symb, int v)
11547edc7532SDavid du Colombier {
11557edc7532SDavid du Colombier 	Sym *s;
11567edc7532SDavid du Colombier 	char *p;
11577edc7532SDavid du Colombier 	long h;
11587edc7532SDavid du Colombier 	int c, l;
11597edc7532SDavid du Colombier 
11607edc7532SDavid du Colombier 	h = v;
11617edc7532SDavid du Colombier 	for(p=symb; c = *p; p++)
11627edc7532SDavid du Colombier 		h = h+h+h + c;
11637edc7532SDavid du Colombier 	l = (p - symb) + 1;
11647edc7532SDavid du Colombier 	if(h < 0)
11657edc7532SDavid du Colombier 		h = ~h;
1166*f8bc6aafSDavid du Colombier 	h &= 0xffffff;		// XXX
11677edc7532SDavid du Colombier 	h %= NHASH;
11687edc7532SDavid du Colombier 	for(s = hash[h]; s != S; s = s->link)
11697edc7532SDavid du Colombier 		if(s->version == v)
11707edc7532SDavid du Colombier 		if(memcmp(s->name, symb, l) == 0)
11717edc7532SDavid du Colombier 			return s;
11727edc7532SDavid du Colombier 
11737edc7532SDavid du Colombier 	while(nhunk < sizeof(Sym))
11747edc7532SDavid du Colombier 		gethunk();
11757edc7532SDavid du Colombier 	s = (Sym*)hunk;
11767edc7532SDavid du Colombier 	nhunk -= sizeof(Sym);
11777edc7532SDavid du Colombier 	hunk += sizeof(Sym);
11787edc7532SDavid du Colombier 
11797edc7532SDavid du Colombier 	s->name = malloc(l);
11807edc7532SDavid du Colombier 	memmove(s->name, symb, l);
11817edc7532SDavid du Colombier 
11827edc7532SDavid du Colombier 	s->link = hash[h];
11837edc7532SDavid du Colombier 	s->type = 0;
11847edc7532SDavid du Colombier 	s->version = v;
11857edc7532SDavid du Colombier 	s->value = 0;
11867edc7532SDavid du Colombier 	hash[h] = s;
11877edc7532SDavid du Colombier 	return s;
11887edc7532SDavid du Colombier }
11897edc7532SDavid du Colombier 
11907edc7532SDavid du Colombier Prog*
prg(void)11917edc7532SDavid du Colombier prg(void)
11927edc7532SDavid du Colombier {
11937edc7532SDavid du Colombier 	Prog *p;
11947edc7532SDavid du Colombier 
11957edc7532SDavid du Colombier 	while(nhunk < sizeof(Prog))
11967edc7532SDavid du Colombier 		gethunk();
11977edc7532SDavid du Colombier 	p = (Prog*)hunk;
11987edc7532SDavid du Colombier 	nhunk -= sizeof(Prog);
11997edc7532SDavid du Colombier 	hunk += sizeof(Prog);
12007edc7532SDavid du Colombier 
12017edc7532SDavid du Colombier 	*p = zprg;
12027edc7532SDavid du Colombier 	return p;
12037edc7532SDavid du Colombier }
12047edc7532SDavid du Colombier 
12057edc7532SDavid du Colombier void
gethunk(void)12067edc7532SDavid du Colombier gethunk(void)
12077edc7532SDavid du Colombier {
12087edc7532SDavid du Colombier 	char *h;
12097edc7532SDavid du Colombier 	long nh;
12107edc7532SDavid du Colombier 
12117edc7532SDavid du Colombier 	nh = NHUNK;
12127edc7532SDavid du Colombier 	if(thunk >= 5L*NHUNK) {
12137edc7532SDavid du Colombier 		nh = 5L*NHUNK;
12147edc7532SDavid du Colombier 		if(thunk >= 25L*NHUNK)
12157edc7532SDavid du Colombier 			nh = 25L*NHUNK;
12167edc7532SDavid du Colombier 	}
12177edc7532SDavid du Colombier 	h = mysbrk(nh);
12187edc7532SDavid du Colombier 	if(h == (char*)-1) {
12197edc7532SDavid du Colombier 		diag("out of memory");
12207edc7532SDavid du Colombier 		errorexit();
12217edc7532SDavid du Colombier 	}
12227edc7532SDavid du Colombier 	hunk = h;
12237edc7532SDavid du Colombier 	nhunk = nh;
12247edc7532SDavid du Colombier 	thunk += nh;
12257edc7532SDavid du Colombier }
12267edc7532SDavid du Colombier 
12277edc7532SDavid du Colombier void
doprof1(void)12287edc7532SDavid du Colombier doprof1(void)
12297edc7532SDavid du Colombier {
12307edc7532SDavid du Colombier 	Sym *s;
12317edc7532SDavid du Colombier 	long n;
12327edc7532SDavid du Colombier 	Prog *p, *q;
12337edc7532SDavid du Colombier 
12347edc7532SDavid du Colombier 	if(debug['v'])
12357edc7532SDavid du Colombier 		Bprint(&bso, "%5.2f profile 1\n", cputime());
12367edc7532SDavid du Colombier 	Bflush(&bso);
12377edc7532SDavid du Colombier 	s = lookup("__mcount", 0);
12387edc7532SDavid du Colombier 	n = 1;
12397edc7532SDavid du Colombier 	for(p = firstp->link; p != P; p = p->link) {
12407edc7532SDavid du Colombier 		if(p->as == ATEXT) {
12417edc7532SDavid du Colombier 			q = prg();
12427edc7532SDavid du Colombier 			q->line = p->line;
12437edc7532SDavid du Colombier 			q->link = datap;
12447edc7532SDavid du Colombier 			datap = q;
12457edc7532SDavid du Colombier 			q->as = ADATA;
12467edc7532SDavid du Colombier 			q->from.type = D_OREG;
12477edc7532SDavid du Colombier 			q->from.name = D_EXTERN;
12487edc7532SDavid du Colombier 			q->from.offset = n*4;
12497edc7532SDavid du Colombier 			q->from.sym = s;
12507edc7532SDavid du Colombier 			q->reg = 4;
12517edc7532SDavid du Colombier 			q->to = p->from;
12527edc7532SDavid du Colombier 			q->to.type = D_CONST;
12537edc7532SDavid du Colombier 
12547edc7532SDavid du Colombier 			q = prg();
12557edc7532SDavid du Colombier 			q->line = p->line;
12567edc7532SDavid du Colombier 			q->pc = p->pc;
12577edc7532SDavid du Colombier 			q->link = p->link;
12587edc7532SDavid du Colombier 			p->link = q;
12597edc7532SDavid du Colombier 			p = q;
12607edc7532SDavid du Colombier 			p->as = AMOVW;
12617edc7532SDavid du Colombier 			p->from.type = D_OREG;
12627edc7532SDavid du Colombier 			p->from.name = D_EXTERN;
12637edc7532SDavid du Colombier 			p->from.sym = s;
12647edc7532SDavid du Colombier 			p->from.offset = n*4 + 4;
12657edc7532SDavid du Colombier 			p->to.type = D_REG;
12667edc7532SDavid du Colombier 			p->to.reg = REGTMP;
12677edc7532SDavid du Colombier 
12687edc7532SDavid du Colombier 			q = prg();
12697edc7532SDavid du Colombier 			q->line = p->line;
12707edc7532SDavid du Colombier 			q->pc = p->pc;
12717edc7532SDavid du Colombier 			q->link = p->link;
12727edc7532SDavid du Colombier 			p->link = q;
12737edc7532SDavid du Colombier 			p = q;
12747edc7532SDavid du Colombier 			p->as = AADDU;
12757edc7532SDavid du Colombier 			p->from.type = D_CONST;
12767edc7532SDavid du Colombier 			p->from.offset = 1;
12777edc7532SDavid du Colombier 			p->to.type = D_REG;
12787edc7532SDavid du Colombier 			p->to.reg = REGTMP;
12797edc7532SDavid du Colombier 
12807edc7532SDavid du Colombier 			q = prg();
12817edc7532SDavid du Colombier 			q->line = p->line;
12827edc7532SDavid du Colombier 			q->pc = p->pc;
12837edc7532SDavid du Colombier 			q->link = p->link;
12847edc7532SDavid du Colombier 			p->link = q;
12857edc7532SDavid du Colombier 			p = q;
12867edc7532SDavid du Colombier 			p->as = AMOVW;
12877edc7532SDavid du Colombier 			p->from.type = D_REG;
12887edc7532SDavid du Colombier 			p->from.reg = REGTMP;
12897edc7532SDavid du Colombier 			p->to.type = D_OREG;
12907edc7532SDavid du Colombier 			p->to.name = D_EXTERN;
12917edc7532SDavid du Colombier 			p->to.sym = s;
12927edc7532SDavid du Colombier 			p->to.offset = n*4 + 4;
12937edc7532SDavid du Colombier 
12947edc7532SDavid du Colombier 			n += 2;
12957edc7532SDavid du Colombier 			continue;
12967edc7532SDavid du Colombier 		}
12977edc7532SDavid du Colombier 	}
12987edc7532SDavid du Colombier 	q = prg();
12997edc7532SDavid du Colombier 	q->line = 0;
13007edc7532SDavid du Colombier 	q->link = datap;
13017edc7532SDavid du Colombier 	datap = q;
13027edc7532SDavid du Colombier 
13037edc7532SDavid du Colombier 	q->as = ADATA;
13047edc7532SDavid du Colombier 	q->from.type = D_OREG;
13057edc7532SDavid du Colombier 	q->from.name = D_EXTERN;
13067edc7532SDavid du Colombier 	q->from.sym = s;
13077edc7532SDavid du Colombier 	q->reg = 4;
13087edc7532SDavid du Colombier 	q->to.type = D_CONST;
13097edc7532SDavid du Colombier 	q->to.offset = n;
13107edc7532SDavid du Colombier 
13117edc7532SDavid du Colombier 	s->type = SBSS;
13127edc7532SDavid du Colombier 	s->value = n*4;
13137edc7532SDavid du Colombier }
13147edc7532SDavid du Colombier 
13157edc7532SDavid du Colombier void
doprof2(void)13167edc7532SDavid du Colombier doprof2(void)
13177edc7532SDavid du Colombier {
13187edc7532SDavid du Colombier 	Sym *s2, *s4;
1319*f8bc6aafSDavid du Colombier 	Prog *p, *q, *q2, *ps2, *ps4;
13207edc7532SDavid du Colombier 
13217edc7532SDavid du Colombier 	if(debug['v'])
13227edc7532SDavid du Colombier 		Bprint(&bso, "%5.2f profile 2\n", cputime());
13237edc7532SDavid du Colombier 	Bflush(&bso);
1324*f8bc6aafSDavid du Colombier 
1325*f8bc6aafSDavid du Colombier 	if(debug['e']){
1326*f8bc6aafSDavid du Colombier 		s2 = lookup("_tracein", 0);
1327*f8bc6aafSDavid du Colombier 		s4 = lookup("_traceout", 0);
1328*f8bc6aafSDavid du Colombier 	}else{
13297edc7532SDavid du Colombier 		s2 = lookup("_profin", 0);
13307edc7532SDavid du Colombier 		s4 = lookup("_profout", 0);
1331*f8bc6aafSDavid du Colombier 	}
13327edc7532SDavid du Colombier 	if(s2->type != STEXT || s4->type != STEXT) {
1333*f8bc6aafSDavid du Colombier 		if(debug['e'])
1334*f8bc6aafSDavid du Colombier 			diag("_tracein/_traceout not defined %d %d", s2->type, s4->type);
1335*f8bc6aafSDavid du Colombier 		else
13367edc7532SDavid du Colombier 			diag("_profin/_profout not defined");
13377edc7532SDavid du Colombier 		return;
13387edc7532SDavid du Colombier 	}
13397edc7532SDavid du Colombier 
13407edc7532SDavid du Colombier 	ps2 = P;
13417edc7532SDavid du Colombier 	ps4 = P;
13427edc7532SDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
13437edc7532SDavid du Colombier 		if(p->as == ATEXT) {
13447edc7532SDavid du Colombier 			if(p->from.sym == s2) {
13457edc7532SDavid du Colombier 				ps2 = p;
13467edc7532SDavid du Colombier 				p->reg = 1;
13477edc7532SDavid du Colombier 			}
13487edc7532SDavid du Colombier 			if(p->from.sym == s4) {
13497edc7532SDavid du Colombier 				ps4 = p;
13507edc7532SDavid du Colombier 				p->reg = 1;
13517edc7532SDavid du Colombier 			}
13527edc7532SDavid du Colombier 		}
13537edc7532SDavid du Colombier 	}
13547edc7532SDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
13557edc7532SDavid du Colombier 		if(p->as == ATEXT) {
13567edc7532SDavid du Colombier 			if(p->reg & NOPROF) {
13577edc7532SDavid du Colombier 				for(;;) {
13587edc7532SDavid du Colombier 					q = p->link;
13597edc7532SDavid du Colombier 					if(q == P)
13607edc7532SDavid du Colombier 						break;
13617edc7532SDavid du Colombier 					if(q->as == ATEXT)
13627edc7532SDavid du Colombier 						break;
13637edc7532SDavid du Colombier 					p = q;
13647edc7532SDavid du Colombier 				}
13657edc7532SDavid du Colombier 				continue;
13667edc7532SDavid du Colombier 			}
13677edc7532SDavid du Colombier 
13687edc7532SDavid du Colombier 			/*
13697edc7532SDavid du Colombier 			 * JAL	profin, R2
13707edc7532SDavid du Colombier 			 */
13717edc7532SDavid du Colombier 			q = prg();
13727edc7532SDavid du Colombier 			q->line = p->line;
13737edc7532SDavid du Colombier 			q->pc = p->pc;
13747edc7532SDavid du Colombier 			q->link = p->link;
1375*f8bc6aafSDavid du Colombier 			if(debug['e']){		/* embedded tracing */
1376*f8bc6aafSDavid du Colombier 				q2 = prg();
1377*f8bc6aafSDavid du Colombier 				p->link = q2;
1378*f8bc6aafSDavid du Colombier 				q2->link = q;
1379*f8bc6aafSDavid du Colombier 
1380*f8bc6aafSDavid du Colombier 				q2->line = p->line;
1381*f8bc6aafSDavid du Colombier 				q2->pc = p->pc;
1382*f8bc6aafSDavid du Colombier 
1383*f8bc6aafSDavid du Colombier 				q2->as = AJMP;
1384*f8bc6aafSDavid du Colombier 				q2->to.type = D_BRANCH;
1385*f8bc6aafSDavid du Colombier 				q2->to.sym = p->to.sym;
1386*f8bc6aafSDavid du Colombier 				q2->cond = q->link;
1387*f8bc6aafSDavid du Colombier 			}else
13887edc7532SDavid du Colombier 				p->link = q;
13897edc7532SDavid du Colombier 			p = q;
13907edc7532SDavid du Colombier 			p->as = AJAL;
13917edc7532SDavid du Colombier 			p->to.type = D_BRANCH;
13927edc7532SDavid du Colombier 			p->cond = ps2;
13937edc7532SDavid du Colombier 			p->to.sym = s2;
13947edc7532SDavid du Colombier 
13957edc7532SDavid du Colombier 			continue;
13967edc7532SDavid du Colombier 		}
13977edc7532SDavid du Colombier 		if(p->as == ARET) {
13987edc7532SDavid du Colombier 			/*
1399*f8bc6aafSDavid du Colombier 			 * RET (default)
1400*f8bc6aafSDavid du Colombier 			 */
1401*f8bc6aafSDavid du Colombier 			if(debug['e']){		/* embedded tracing */
1402*f8bc6aafSDavid du Colombier 				q = prg();
1403*f8bc6aafSDavid du Colombier 				q->line = p->line;
1404*f8bc6aafSDavid du Colombier 				q->pc = p->pc;
1405*f8bc6aafSDavid du Colombier 				q->link = p->link;
1406*f8bc6aafSDavid du Colombier 				p->link = q;
1407*f8bc6aafSDavid du Colombier 				p = q;
1408*f8bc6aafSDavid du Colombier 			}
1409*f8bc6aafSDavid du Colombier 			/*
14107edc7532SDavid du Colombier 			 * RET
14117edc7532SDavid du Colombier 			 */
14127edc7532SDavid du Colombier 			q = prg();
14137edc7532SDavid du Colombier 			q->as = ARET;
14147edc7532SDavid du Colombier 			q->from = p->from;
14157edc7532SDavid du Colombier 			q->to = p->to;
14167edc7532SDavid du Colombier 			q->link = p->link;
14177edc7532SDavid du Colombier 			p->link = q;
14187edc7532SDavid du Colombier 
14197edc7532SDavid du Colombier 			/*
14207edc7532SDavid du Colombier 			 * JAL	profout
14217edc7532SDavid du Colombier 			 */
14227edc7532SDavid du Colombier 			p->as = AJAL;
14237edc7532SDavid du Colombier 			p->from = zprg.from;
14247edc7532SDavid du Colombier 			p->to = zprg.to;
14257edc7532SDavid du Colombier 			p->to.type = D_BRANCH;
14267edc7532SDavid du Colombier 			p->cond = ps4;
14277edc7532SDavid du Colombier 			p->to.sym = s4;
14287edc7532SDavid du Colombier 
14297edc7532SDavid du Colombier 			p = q;
14307edc7532SDavid du Colombier 
14317edc7532SDavid du Colombier 			continue;
14327edc7532SDavid du Colombier 		}
14337edc7532SDavid du Colombier 	}
14347edc7532SDavid du Colombier }
14357edc7532SDavid du Colombier 
14367edc7532SDavid du Colombier void
nuxiinit(void)14377edc7532SDavid du Colombier nuxiinit(void)
14387edc7532SDavid du Colombier {
14397edc7532SDavid du Colombier 	int i, c;
14407edc7532SDavid du Colombier 
1441*f8bc6aafSDavid du Colombier 	for(i=0; i<4; i++)
1442*f8bc6aafSDavid du Colombier 		if (!little) {			/* normal big-endian case */
14437edc7532SDavid du Colombier 			c = find1(0x01020304L, i+1);
14447edc7532SDavid du Colombier 			if(i >= 2)
14457edc7532SDavid du Colombier 				inuxi2[i-2] = c;
14467edc7532SDavid du Colombier 			if(i >= 3)
14477edc7532SDavid du Colombier 				inuxi1[i-3] = c;
14487edc7532SDavid du Colombier 			inuxi4[i] = c;
1449*f8bc6aafSDavid du Colombier 			inuxi8[i] = c+4;
1450*f8bc6aafSDavid du Colombier 			inuxi8[i+4] = c;
1451*f8bc6aafSDavid du Colombier 			fnuxi4[i] = c;
14527edc7532SDavid du Colombier 			fnuxi8[i] = c+4;
14537edc7532SDavid du Colombier 			fnuxi8[i+4] = c;
1454*f8bc6aafSDavid du Colombier 		} else {			/* oddball little-endian case */
1455*f8bc6aafSDavid du Colombier 			c = find1(0x04030201L, i+1);
1456*f8bc6aafSDavid du Colombier 			if(i < 2)
1457*f8bc6aafSDavid du Colombier 				inuxi2[i] = c;
1458*f8bc6aafSDavid du Colombier 			if(i < 1)
1459*f8bc6aafSDavid du Colombier 				inuxi1[i] = c;
1460*f8bc6aafSDavid du Colombier 			inuxi4[i] = c;
1461*f8bc6aafSDavid du Colombier 			inuxi8[i] = c;
1462*f8bc6aafSDavid du Colombier 			inuxi8[i+4] = c+4;
1463*f8bc6aafSDavid du Colombier 			fnuxi4[i] = c;
1464*f8bc6aafSDavid du Colombier 			fnuxi8[i] = c;
1465*f8bc6aafSDavid du Colombier 			fnuxi8[i+4] = c+4;
14667edc7532SDavid du Colombier 		}
14677edc7532SDavid du Colombier 	if(debug['v']) {
14687edc7532SDavid du Colombier 		Bprint(&bso, "inuxi = ");
14697edc7532SDavid du Colombier 		for(i=0; i<1; i++)
14707edc7532SDavid du Colombier 			Bprint(&bso, "%d", inuxi1[i]);
14717edc7532SDavid du Colombier 		Bprint(&bso, " ");
14727edc7532SDavid du Colombier 		for(i=0; i<2; i++)
14737edc7532SDavid du Colombier 			Bprint(&bso, "%d", inuxi2[i]);
14747edc7532SDavid du Colombier 		Bprint(&bso, " ");
14757edc7532SDavid du Colombier 		for(i=0; i<4; i++)
14767edc7532SDavid du Colombier 			Bprint(&bso, "%d", inuxi4[i]);
14777edc7532SDavid du Colombier 		Bprint(&bso, "\nfnuxi = ");
14787edc7532SDavid du Colombier 		for(i=0; i<8; i++)
1479*f8bc6aafSDavid du Colombier 			Bprint(&bso, "%d", inuxi8[i]);
1480*f8bc6aafSDavid du Colombier 		Bprint(&bso, "\n");
1481*f8bc6aafSDavid du Colombier 		for(i=0; i<4; i++)
1482*f8bc6aafSDavid du Colombier 			Bprint(&bso, "%d", fnuxi4[i]);
1483*f8bc6aafSDavid du Colombier 		Bprint(&bso, "\nfnuxi = ");
1484*f8bc6aafSDavid du Colombier 		for(i=0; i<8; i++)
14857edc7532SDavid du Colombier 			Bprint(&bso, "%d", fnuxi8[i]);
14867edc7532SDavid du Colombier 		Bprint(&bso, "\n");
14877edc7532SDavid du Colombier 	}
14887edc7532SDavid du Colombier 	Bflush(&bso);
14897edc7532SDavid du Colombier }
14907edc7532SDavid du Colombier 
14917edc7532SDavid du Colombier int
find1(long l,int c)14927edc7532SDavid du Colombier find1(long l, int c)
14937edc7532SDavid du Colombier {
14947edc7532SDavid du Colombier 	char *p;
14957edc7532SDavid du Colombier 	int i;
14967edc7532SDavid du Colombier 
14977edc7532SDavid du Colombier 	p = (char*)&l;
14987edc7532SDavid du Colombier 	for(i=0; i<4; i++)
14997edc7532SDavid du Colombier 		if(*p++ == c)
15007edc7532SDavid du Colombier 			return i;
15017edc7532SDavid du Colombier 	return 0;
15027edc7532SDavid du Colombier }
15037edc7532SDavid du Colombier 
15047edc7532SDavid du Colombier vlong
ieeedtov(Ieee * ieeep)15057edc7532SDavid du Colombier ieeedtov(Ieee *ieeep)
15067edc7532SDavid du Colombier {
15077edc7532SDavid du Colombier 	vlong v;
15087edc7532SDavid du Colombier 
15097edc7532SDavid du Colombier 	v = (vlong)ieeep->l & 0xffffffffLL;
15107edc7532SDavid du Colombier 	v |= (vlong)ieeep->h << 32;
15117edc7532SDavid du Colombier 	return v;
15127edc7532SDavid du Colombier }
15137edc7532SDavid du Colombier 
15147edc7532SDavid du Colombier long
ieeedtof(Ieee * ieeep)15157edc7532SDavid du Colombier ieeedtof(Ieee *ieeep)
15167edc7532SDavid du Colombier {
15177edc7532SDavid du Colombier 	int exp;
15187edc7532SDavid du Colombier 	long v;
15197edc7532SDavid du Colombier 
15207edc7532SDavid du Colombier 	if(ieeep->h == 0)
15217edc7532SDavid du Colombier 		return 0;
15227edc7532SDavid du Colombier 	exp = (ieeep->h>>20) & ((1L<<11)-1L);
15237edc7532SDavid du Colombier 	exp -= (1L<<10) - 2L;
15247edc7532SDavid du Colombier 	v = (ieeep->h & 0xfffffL) << 3;
15257edc7532SDavid du Colombier 	v |= (ieeep->l >> 29) & 0x7L;
15267edc7532SDavid du Colombier 	if((ieeep->l >> 28) & 1) {
15277edc7532SDavid du Colombier 		v++;
15287edc7532SDavid du Colombier 		if(v & 0x800000L) {
15297edc7532SDavid du Colombier 			v = (v & 0x7fffffL) >> 1;
15307edc7532SDavid du Colombier 			exp++;
15317edc7532SDavid du Colombier 		}
15327edc7532SDavid du Colombier 	}
15337edc7532SDavid du Colombier 	if(exp <= -126 || exp >= 130)
15347edc7532SDavid du Colombier 		diag("double fp to single fp overflow");
15357edc7532SDavid du Colombier 	v |= ((exp + 126) & 0xffL) << 23;
15367edc7532SDavid du Colombier 	v |= ieeep->h & 0x80000000L;
15377edc7532SDavid du Colombier 	return v;
15387edc7532SDavid du Colombier }
15397edc7532SDavid du Colombier 
15407edc7532SDavid du Colombier double
ieeedtod(Ieee * ieeep)15417edc7532SDavid du Colombier ieeedtod(Ieee *ieeep)
15427edc7532SDavid du Colombier {
15437edc7532SDavid du Colombier 	Ieee e;
15447edc7532SDavid du Colombier 	double fr;
15457edc7532SDavid du Colombier 	int exp;
15467edc7532SDavid du Colombier 
15477edc7532SDavid du Colombier 	if(ieeep->h & (1L<<31)) {
15487edc7532SDavid du Colombier 		e.h = ieeep->h & ~(1L<<31);
15497edc7532SDavid du Colombier 		e.l = ieeep->l;
15507edc7532SDavid du Colombier 		return -ieeedtod(&e);
15517edc7532SDavid du Colombier 	}
15527edc7532SDavid du Colombier 	if(ieeep->l == 0 && ieeep->h == 0)
15537edc7532SDavid du Colombier 		return 0;
15547edc7532SDavid du Colombier 	fr = ieeep->l & ((1L<<16)-1L);
15557edc7532SDavid du Colombier 	fr /= 1L<<16;
15567edc7532SDavid du Colombier 	fr += (ieeep->l>>16) & ((1L<<16)-1L);
15577edc7532SDavid du Colombier 	fr /= 1L<<16;
15587edc7532SDavid du Colombier 	fr += (ieeep->h & (1L<<20)-1L) | (1L<<20);
15597edc7532SDavid du Colombier 	fr /= 1L<<21;
15607edc7532SDavid du Colombier 	exp = (ieeep->h>>20) & ((1L<<11)-1L);
15617edc7532SDavid du Colombier 	exp -= (1L<<10) - 2L;
15627edc7532SDavid du Colombier 	return ldexp(fr, exp);
15637edc7532SDavid du Colombier }
1564