xref: /plan9/sys/src/cmd/ql/obj.c (revision 3f193c012918ec0feb8f0a7f2a03985f6e7ecfab)
1375daca8SDavid du Colombier #define	EXTERN
27dd7cddfSDavid du Colombier #include	"l.h"
37dd7cddfSDavid du Colombier #include	<ar.h>
47dd7cddfSDavid du Colombier 
57dd7cddfSDavid du Colombier #ifndef	DEFAULT
67dd7cddfSDavid du Colombier #define	DEFAULT	'9'
77dd7cddfSDavid du Colombier #endif
87dd7cddfSDavid du Colombier 
97dd7cddfSDavid du Colombier char	*noname		= "<none>";
107dd7cddfSDavid du Colombier char	symname[]	= SYMDEF;
117dd7cddfSDavid du Colombier char	thechar		= 'q';
127dd7cddfSDavid du Colombier char	*thestring 	= "power";
137dd7cddfSDavid du Colombier 
147dd7cddfSDavid du Colombier /*
157dd7cddfSDavid du Colombier  *	-H0 -T0x200000 -R0		is boot
167dd7cddfSDavid du Colombier  *	-H1 -T0x100000 -R4		is Be boot
177dd7cddfSDavid du Colombier  *	-H2 -T4128 -R4096		is plan9 format
187dd7cddfSDavid du Colombier  *	-H3 -T0x02010000 -D0x00001000	is raw
197dd7cddfSDavid du Colombier  *	-H4 -T0x1000200 -D0x20000e00 -R4	is aix xcoff executable
20dc5a79c1SDavid du Colombier  *	-H5 -T0x80010000 -t0x10000	ELF, phys = 10000, vaddr = 0x8001...
217dd7cddfSDavid du Colombier  */
227dd7cddfSDavid du Colombier 
23375daca8SDavid du Colombier static int
24375daca8SDavid du Colombier isobjfile(char *f)
25375daca8SDavid du Colombier {
26375daca8SDavid du Colombier 	int n, v;
27375daca8SDavid du Colombier 	Biobuf *b;
28375daca8SDavid du Colombier 	char buf1[5], buf2[SARMAG];
29375daca8SDavid du Colombier 
30375daca8SDavid du Colombier 	b = Bopen(f, OREAD);
31375daca8SDavid du Colombier 	if(b == nil)
32375daca8SDavid du Colombier 		return 0;
33375daca8SDavid du Colombier 	n = Bread(b, buf1, 5);
34375daca8SDavid du Colombier 	if(n == 5 && (buf1[2] == 1 && buf1[3] == '<' || buf1[3] == 1 && buf1[4] == '<'))
35375daca8SDavid du Colombier 		v = 1;	/* good enough for our purposes */
36375daca8SDavid du Colombier 	else{
37375daca8SDavid du Colombier 		Bseek(b, 0, 0);
38375daca8SDavid du Colombier 		n = Bread(b, buf2, SARMAG);
39375daca8SDavid du Colombier 		v = n == SARMAG && strncmp(buf2, ARMAG, SARMAG) == 0;
40375daca8SDavid du Colombier 	}
41375daca8SDavid du Colombier 	Bterm(b);
42375daca8SDavid du Colombier 	return v;
43375daca8SDavid du Colombier }
44375daca8SDavid du Colombier 
457dd7cddfSDavid du Colombier void
467dd7cddfSDavid du Colombier main(int argc, char *argv[])
477dd7cddfSDavid du Colombier {
487dd7cddfSDavid du Colombier 	int c;
497dd7cddfSDavid du Colombier 	char *a;
507dd7cddfSDavid du Colombier 
517dd7cddfSDavid du Colombier 	Binit(&bso, 1, OWRITE);
527dd7cddfSDavid du Colombier 	cout = -1;
537dd7cddfSDavid du Colombier 	listinit();
547dd7cddfSDavid du Colombier 	outfile = 0;
557dd7cddfSDavid du Colombier 	nerrors = 0;
567dd7cddfSDavid du Colombier 	curtext = P;
577dd7cddfSDavid du Colombier 	HEADTYPE = -1;
587dd7cddfSDavid du Colombier 	INITTEXT = -1;
597dd7cddfSDavid du Colombier 	INITDAT = -1;
607dd7cddfSDavid du Colombier 	INITRND = -1;
617dd7cddfSDavid du Colombier 	INITENTRY = 0;
627dd7cddfSDavid du Colombier 
637dd7cddfSDavid du Colombier 	ARGBEGIN {
647dd7cddfSDavid du Colombier 	default:
657dd7cddfSDavid du Colombier 		c = ARGC();
667dd7cddfSDavid du Colombier 		if(c >= 0 && c < sizeof(debug))
677dd7cddfSDavid du Colombier 			debug[c]++;
687dd7cddfSDavid du Colombier 		break;
697dd7cddfSDavid du Colombier 	case 'o':
707dd7cddfSDavid du Colombier 		outfile = ARGF();
717dd7cddfSDavid du Colombier 		break;
727dd7cddfSDavid du Colombier 	case 'E':
737dd7cddfSDavid du Colombier 		a = ARGF();
747dd7cddfSDavid du Colombier 		if(a)
757dd7cddfSDavid du Colombier 			INITENTRY = a;
767dd7cddfSDavid du Colombier 		break;
777dd7cddfSDavid du Colombier 	case 'T':
787dd7cddfSDavid du Colombier 		a = ARGF();
797dd7cddfSDavid du Colombier 		if(a)
807dd7cddfSDavid du Colombier 			INITTEXT = atolwhex(a);
817dd7cddfSDavid du Colombier 		break;
827dd7cddfSDavid du Colombier 	case 'D':
837dd7cddfSDavid du Colombier 		a = ARGF();
847dd7cddfSDavid du Colombier 		if(a)
857dd7cddfSDavid du Colombier 			INITDAT = atolwhex(a);
867dd7cddfSDavid du Colombier 		break;
877dd7cddfSDavid du Colombier 	case 'R':
887dd7cddfSDavid du Colombier 		a = ARGF();
897dd7cddfSDavid du Colombier 		if(a)
907dd7cddfSDavid du Colombier 			INITRND = atolwhex(a);
917dd7cddfSDavid du Colombier 		break;
927dd7cddfSDavid du Colombier 	case 'H':
937dd7cddfSDavid du Colombier 		a = ARGF();
947dd7cddfSDavid du Colombier 		if(a)
957dd7cddfSDavid du Colombier 			HEADTYPE = atolwhex(a);
967dd7cddfSDavid du Colombier 		break;
97375daca8SDavid du Colombier 	case 'x':	/* produce export table */
98375daca8SDavid du Colombier 		doexp = 1;
99375daca8SDavid du Colombier 		if(argv[1] != nil && argv[1][0] != '-' && !isobjfile(argv[1]))
100375daca8SDavid du Colombier 			readundefs(ARGF(), SEXPORT);
101375daca8SDavid du Colombier 		break;
102375daca8SDavid du Colombier 	case 'u':	/* produce dynamically loadable module */
103375daca8SDavid du Colombier 		dlm = 1;
104375daca8SDavid du Colombier 		if(argv[1] != nil && argv[1][0] != '-' && !isobjfile(argv[1]))
105375daca8SDavid du Colombier 			readundefs(ARGF(), SIMPORT);
106375daca8SDavid du Colombier 		break;
1077dd7cddfSDavid du Colombier 	} ARGEND
1087dd7cddfSDavid du Colombier 	USED(argc);
1097dd7cddfSDavid du Colombier 	if(*argv == 0) {
110375daca8SDavid du Colombier 		diag("usage: ql [-options] objects");
1117dd7cddfSDavid du Colombier 		errorexit();
1127dd7cddfSDavid du Colombier 	}
1137dd7cddfSDavid du Colombier 	if(!debug['9'] && !debug['U'] && !debug['B'])
1147dd7cddfSDavid du Colombier 		debug[DEFAULT] = 1;
115375daca8SDavid du Colombier 	r0iszero = debug['0'] == 0;
1167dd7cddfSDavid du Colombier 	if(HEADTYPE == -1) {
1177dd7cddfSDavid du Colombier 		if(debug['U'])
1187dd7cddfSDavid du Colombier 			HEADTYPE = 0;
1197dd7cddfSDavid du Colombier 		if(debug['B'])
1207dd7cddfSDavid du Colombier 			HEADTYPE = 1;
1217dd7cddfSDavid du Colombier 		if(debug['9'])
1227dd7cddfSDavid du Colombier 			HEADTYPE = 2;
1237dd7cddfSDavid du Colombier 	}
1247dd7cddfSDavid du Colombier 	switch(HEADTYPE) {
1257dd7cddfSDavid du Colombier 	default:
1267dd7cddfSDavid du Colombier 		diag("unknown -H option");
1277dd7cddfSDavid du Colombier 		errorexit();
1287dd7cddfSDavid du Colombier 
1297dd7cddfSDavid du Colombier 	case 0:	/* boot */
1307dd7cddfSDavid du Colombier 		HEADR = 32L;
1317dd7cddfSDavid du Colombier 		if(INITTEXT == -1)
1327dd7cddfSDavid du Colombier 			INITTEXT = 0x200000L;
1337dd7cddfSDavid du Colombier 		if(INITDAT == -1)
1347dd7cddfSDavid du Colombier 			INITDAT = 0;
1357dd7cddfSDavid du Colombier 		if(INITRND == -1)
1367dd7cddfSDavid du Colombier 			INITRND = 4096L;
1377dd7cddfSDavid du Colombier 		break;
1387dd7cddfSDavid du Colombier 	case 1:	/* Be boot format (PEF) */
1397dd7cddfSDavid du Colombier 		HEADR = 208L;
1407dd7cddfSDavid du Colombier 		if(INITTEXT == -1)
1417dd7cddfSDavid du Colombier 			INITTEXT = 0x100000;
1427dd7cddfSDavid du Colombier 		if(INITDAT == -1)
1437dd7cddfSDavid du Colombier 			INITDAT = 0;
1447dd7cddfSDavid du Colombier 		if(INITRND == -1)
1457dd7cddfSDavid du Colombier 			INITRND = 4;
1467dd7cddfSDavid du Colombier 		break;
1477dd7cddfSDavid du Colombier 	case 2:	/* plan 9 */
1487dd7cddfSDavid du Colombier 		HEADR = 32L;
1497dd7cddfSDavid du Colombier 		if(INITTEXT == -1)
1507dd7cddfSDavid du Colombier 			INITTEXT = 4128;
1517dd7cddfSDavid du Colombier 		if(INITDAT == -1)
1527dd7cddfSDavid du Colombier 			INITDAT = 0;
1537dd7cddfSDavid du Colombier 		if(INITRND == -1)
1547dd7cddfSDavid du Colombier 			INITRND = 4096;
1557dd7cddfSDavid du Colombier 		break;
1567dd7cddfSDavid du Colombier 	case 3:	/* raw */
1577dd7cddfSDavid du Colombier 		HEADR = 0;
1587dd7cddfSDavid du Colombier 		if(INITTEXT == -1)
1597dd7cddfSDavid du Colombier 			INITTEXT = 4128;
1607dd7cddfSDavid du Colombier 		if(INITDAT == -1) {
1617dd7cddfSDavid du Colombier 			INITDAT = 0;
1627dd7cddfSDavid du Colombier 			INITRND = 4;
1637dd7cddfSDavid du Colombier 		}
1647dd7cddfSDavid du Colombier 		if(INITRND == -1)
1657dd7cddfSDavid du Colombier 			INITRND = 0;
1667dd7cddfSDavid du Colombier 		break;
1677dd7cddfSDavid du Colombier 	case 4:	/* aix unix xcoff executable */
1687dd7cddfSDavid du Colombier 		HEADR = 20L+72L+3*40L;
1697dd7cddfSDavid du Colombier 		if(INITTEXT == -1)
1707dd7cddfSDavid du Colombier 			INITTEXT = 0x1000000L+HEADR;
1717dd7cddfSDavid du Colombier 		if(INITDAT == -1)
1727dd7cddfSDavid du Colombier 			INITDAT = 0x20000000;
1737dd7cddfSDavid du Colombier 		if(INITRND == -1)
1747dd7cddfSDavid du Colombier 			INITRND = 0;
1757dd7cddfSDavid du Colombier 		break;
176dc5a79c1SDavid du Colombier 	case 5:	/* elf executable */
177dc5a79c1SDavid du Colombier 		HEADR = rnd(52L+3*32L, 16);
178dc5a79c1SDavid du Colombier 		if(INITTEXT == -1)
179dc5a79c1SDavid du Colombier 			INITTEXT = 0x00400000L+HEADR;
180dc5a79c1SDavid du Colombier 		if(INITDAT == -1)
181dc5a79c1SDavid du Colombier 			INITDAT = 0x10000000;
182dc5a79c1SDavid du Colombier 		if(INITRND == -1)
183dc5a79c1SDavid du Colombier 			INITRND = 0;
184dc5a79c1SDavid du Colombier 		break;
1857dd7cddfSDavid du Colombier 	}
1867dd7cddfSDavid du Colombier 	if(INITDAT != 0 && INITRND != 0)
1877dd7cddfSDavid du Colombier 		print("warning: -D0x%lux is ignored because of -R0x%lux\n",
1887dd7cddfSDavid du Colombier 			INITDAT, INITRND);
1897dd7cddfSDavid du Colombier 	if(debug['v'])
190375daca8SDavid du Colombier 		Bprint(&bso, "HEADER = -H0x%x -T0x%lux -D0x%lux -R0x%lux\n",
1917dd7cddfSDavid du Colombier 			HEADTYPE, INITTEXT, INITDAT, INITRND);
1927dd7cddfSDavid du Colombier 	Bflush(&bso);
1937dd7cddfSDavid du Colombier 	zprg.as = AGOK;
1947dd7cddfSDavid du Colombier 	zprg.reg = NREG;
1957dd7cddfSDavid du Colombier 	zprg.from.name = D_NONE;
1967dd7cddfSDavid du Colombier 	zprg.from.type = D_NONE;
1977dd7cddfSDavid du Colombier 	zprg.from.reg = NREG;
1987dd7cddfSDavid du Colombier 	zprg.from3 = zprg.from;
1997dd7cddfSDavid du Colombier 	zprg.to = zprg.from;
2007dd7cddfSDavid du Colombier 	buildop();
2017dd7cddfSDavid du Colombier 	histgen = 0;
2027dd7cddfSDavid du Colombier 	textp = P;
2037dd7cddfSDavid du Colombier 	datap = P;
2047dd7cddfSDavid du Colombier 	pc = 0;
2057dd7cddfSDavid du Colombier 	dtype = 4;
2067dd7cddfSDavid du Colombier 	if(outfile == 0)
2077dd7cddfSDavid du Colombier 		outfile = "q.out";
2087dd7cddfSDavid du Colombier 	cout = create(outfile, 1, 0775);
2097dd7cddfSDavid du Colombier 	if(cout < 0) {
2106b6b9ac8SDavid du Colombier 		diag("%s: cannot create", outfile);
2117dd7cddfSDavid du Colombier 		errorexit();
2127dd7cddfSDavid du Colombier 	}
2137dd7cddfSDavid du Colombier 	nuxiinit();
2147dd7cddfSDavid du Colombier 	version = 0;
2157dd7cddfSDavid du Colombier 	cbp = buf.cbuf;
2167dd7cddfSDavid du Colombier 	cbc = sizeof(buf.cbuf);
2177dd7cddfSDavid du Colombier 	firstp = prg();
2187dd7cddfSDavid du Colombier 	lastp = firstp;
2197dd7cddfSDavid du Colombier 
2207dd7cddfSDavid du Colombier 	if(INITENTRY == 0) {
2217dd7cddfSDavid du Colombier 		INITENTRY = "_main";
2227dd7cddfSDavid du Colombier 		if(debug['p'])
2237dd7cddfSDavid du Colombier 			INITENTRY = "_mainp";
2247dd7cddfSDavid du Colombier 		if(!debug['l'])
2257dd7cddfSDavid du Colombier 			lookup(INITENTRY, 0)->type = SXREF;
2267dd7cddfSDavid du Colombier 	} else
2277dd7cddfSDavid du Colombier 		lookup(INITENTRY, 0)->type = SXREF;
2287dd7cddfSDavid du Colombier 
2297dd7cddfSDavid du Colombier 	while(*argv)
2307dd7cddfSDavid du Colombier 		objfile(*argv++);
2317dd7cddfSDavid du Colombier 	if(!debug['l'])
2327dd7cddfSDavid du Colombier 		loadlib();
2337dd7cddfSDavid du Colombier 	firstp = firstp->link;
2347dd7cddfSDavid du Colombier 	if(firstp == P)
2357dd7cddfSDavid du Colombier 		goto out;
236375daca8SDavid du Colombier 	if(doexp || dlm){
237375daca8SDavid du Colombier 		EXPTAB = "_exporttab";
238375daca8SDavid du Colombier 		zerosig(EXPTAB);
239375daca8SDavid du Colombier 		zerosig("etext");
240375daca8SDavid du Colombier 		zerosig("edata");
241375daca8SDavid du Colombier 		zerosig("end");
242375daca8SDavid du Colombier 		if(dlm){
243375daca8SDavid du Colombier 			import();
244375daca8SDavid du Colombier 			HEADTYPE = 2;
245375daca8SDavid du Colombier 			INITTEXT = INITDAT = 0;
246375daca8SDavid du Colombier 			INITRND = 8;
247375daca8SDavid du Colombier 			INITENTRY = EXPTAB;
248375daca8SDavid du Colombier 		}
249375daca8SDavid du Colombier 		export();
250375daca8SDavid du Colombier 	}
2517dd7cddfSDavid du Colombier 	patch();
2527dd7cddfSDavid du Colombier 	if(debug['p'])
2537dd7cddfSDavid du Colombier 		if(debug['1'])
2547dd7cddfSDavid du Colombier 			doprof1();
2557dd7cddfSDavid du Colombier 		else
2567dd7cddfSDavid du Colombier 			doprof2();
2577dd7cddfSDavid du Colombier 	dodata();
2587dd7cddfSDavid du Colombier 	follow();
2597dd7cddfSDavid du Colombier 	if(firstp == P)
2607dd7cddfSDavid du Colombier 		goto out;
2617dd7cddfSDavid du Colombier 	noops();
2627dd7cddfSDavid du Colombier 	span();
2637dd7cddfSDavid du Colombier 	asmb();
2647dd7cddfSDavid du Colombier 	undef();
2657dd7cddfSDavid du Colombier 
2667dd7cddfSDavid du Colombier out:
2677dd7cddfSDavid du Colombier 	if(debug['v']) {
2687dd7cddfSDavid du Colombier 		Bprint(&bso, "%5.2f cpu time\n", cputime());
2697dd7cddfSDavid du Colombier 		Bprint(&bso, "%ld memory used\n", tothunk);
2707dd7cddfSDavid du Colombier 		Bprint(&bso, "%d sizeof adr\n", sizeof(Adr));
2717dd7cddfSDavid du Colombier 		Bprint(&bso, "%d sizeof prog\n", sizeof(Prog));
2727dd7cddfSDavid du Colombier 	}
2737dd7cddfSDavid du Colombier 	errorexit();
2747dd7cddfSDavid du Colombier }
2757dd7cddfSDavid du Colombier 
2767dd7cddfSDavid du Colombier void
2777dd7cddfSDavid du Colombier loadlib(void)
2787dd7cddfSDavid du Colombier {
2797dd7cddfSDavid du Colombier 	int i;
2807dd7cddfSDavid du Colombier 	long h;
2817dd7cddfSDavid du Colombier 	Sym *s;
2827dd7cddfSDavid du Colombier 
2837dd7cddfSDavid du Colombier loop:
2847dd7cddfSDavid du Colombier 	xrefresolv = 0;
2857dd7cddfSDavid du Colombier 	for(i=0; i<libraryp; i++) {
2867dd7cddfSDavid du Colombier 		if(debug['v'])
287375daca8SDavid du Colombier 			Bprint(&bso, "%5.2f autolib: %s (from %s)\n", cputime(), library[i], libraryobj[i]);
2887dd7cddfSDavid du Colombier 		objfile(library[i]);
2897dd7cddfSDavid du Colombier 	}
2907dd7cddfSDavid du Colombier 	if(xrefresolv)
2917dd7cddfSDavid du Colombier 	for(h=0; h<nelem(hash); h++)
2927dd7cddfSDavid du Colombier 	for(s = hash[h]; s != S; s = s->link)
2937dd7cddfSDavid du Colombier 		if(s->type == SXREF)
2947dd7cddfSDavid du Colombier 			goto loop;
2957dd7cddfSDavid du Colombier }
2967dd7cddfSDavid du Colombier 
2977dd7cddfSDavid du Colombier void
2987dd7cddfSDavid du Colombier errorexit(void)
2997dd7cddfSDavid du Colombier {
3007dd7cddfSDavid du Colombier 
3017dd7cddfSDavid du Colombier 	Bflush(&bso);
3027dd7cddfSDavid du Colombier 	if(nerrors) {
3037dd7cddfSDavid du Colombier 		if(cout >= 0)
3047dd7cddfSDavid du Colombier 			remove(outfile);
3057dd7cddfSDavid du Colombier 		exits("error");
3067dd7cddfSDavid du Colombier 	}
3077dd7cddfSDavid du Colombier 	exits(0);
3087dd7cddfSDavid du Colombier }
3097dd7cddfSDavid du Colombier 
3107dd7cddfSDavid du Colombier void
3117dd7cddfSDavid du Colombier objfile(char *file)
3127dd7cddfSDavid du Colombier {
3137dd7cddfSDavid du Colombier 	long off, esym, cnt, l;
3147dd7cddfSDavid du Colombier 	int f, work;
3157dd7cddfSDavid du Colombier 	Sym *s;
3167dd7cddfSDavid du Colombier 	char magbuf[SARMAG];
3177dd7cddfSDavid du Colombier 	char name[100], pname[150];
3187dd7cddfSDavid du Colombier 	struct ar_hdr arhdr;
3197dd7cddfSDavid du Colombier 	char *e, *start, *stop;
3207dd7cddfSDavid du Colombier 
3217dd7cddfSDavid du Colombier 	if(file[0] == '-' && file[1] == 'l') {
3227dd7cddfSDavid du Colombier 		if(debug['9'])
3237dd7cddfSDavid du Colombier 			sprint(name, "/%s/lib/lib", thestring);
3247dd7cddfSDavid du Colombier 		else
3257dd7cddfSDavid du Colombier 			sprint(name, "/usr/%clib/lib", thechar);
3267dd7cddfSDavid du Colombier 		strcat(name, file+2);
3277dd7cddfSDavid du Colombier 		strcat(name, ".a");
3287dd7cddfSDavid du Colombier 		file = name;
3297dd7cddfSDavid du Colombier 	}
3307dd7cddfSDavid du Colombier 	if(debug['v'])
3317dd7cddfSDavid du Colombier 		Bprint(&bso, "%5.2f ldobj: %s\n", cputime(), file);
3327dd7cddfSDavid du Colombier 	Bflush(&bso);
3337dd7cddfSDavid du Colombier 	f = open(file, 0);
3347dd7cddfSDavid du Colombier 	if(f < 0) {
3356b6b9ac8SDavid du Colombier 		diag("cannot open file: %s", file);
3367dd7cddfSDavid du Colombier 		errorexit();
3377dd7cddfSDavid du Colombier 	}
3387dd7cddfSDavid du Colombier 	l = read(f, magbuf, SARMAG);
3397dd7cddfSDavid du Colombier 	if(l != SARMAG || strncmp(magbuf, ARMAG, SARMAG)){
3407dd7cddfSDavid du Colombier 		/* load it as a regular file */
3417dd7cddfSDavid du Colombier 		l = seek(f, 0L, 2);
3427dd7cddfSDavid du Colombier 		seek(f, 0L, 0);
3437dd7cddfSDavid du Colombier 		ldobj(f, l, file);
3447dd7cddfSDavid du Colombier 		close(f);
3457dd7cddfSDavid du Colombier 		return;
3467dd7cddfSDavid du Colombier 	}
3477dd7cddfSDavid du Colombier 
3487dd7cddfSDavid du Colombier 	l = read(f, &arhdr, SAR_HDR);
3497dd7cddfSDavid du Colombier 	if(l != SAR_HDR) {
3506b6b9ac8SDavid du Colombier 		diag("%s: short read on archive file symbol header", file);
3517dd7cddfSDavid du Colombier 		goto out;
3527dd7cddfSDavid du Colombier 	}
3537dd7cddfSDavid du Colombier 	if(strncmp(arhdr.name, symname, strlen(symname))) {
3546b6b9ac8SDavid du Colombier 		diag("%s: first entry not symbol header", file);
3557dd7cddfSDavid du Colombier 		goto out;
3567dd7cddfSDavid du Colombier 	}
3577dd7cddfSDavid du Colombier 
3587dd7cddfSDavid du Colombier 	esym = SARMAG + SAR_HDR + atolwhex(arhdr.size);
3597dd7cddfSDavid du Colombier 	off = SARMAG + SAR_HDR;
3607dd7cddfSDavid du Colombier 
3617dd7cddfSDavid du Colombier 	/*
3627dd7cddfSDavid du Colombier 	 * just bang the whole symbol file into memory
3637dd7cddfSDavid du Colombier 	 */
3647dd7cddfSDavid du Colombier 	seek(f, off, 0);
3657dd7cddfSDavid du Colombier 	cnt = esym - off;
3667dd7cddfSDavid du Colombier 	start = malloc(cnt + 10);
3677dd7cddfSDavid du Colombier 	cnt = read(f, start, cnt);
3687dd7cddfSDavid du Colombier 	if(cnt <= 0){
3697dd7cddfSDavid du Colombier 		close(f);
3707dd7cddfSDavid du Colombier 		return;
3717dd7cddfSDavid du Colombier 	}
3727dd7cddfSDavid du Colombier 	stop = &start[cnt];
3737dd7cddfSDavid du Colombier 	memset(stop, 0, 10);
3747dd7cddfSDavid du Colombier 
3757dd7cddfSDavid du Colombier 	work = 1;
3767dd7cddfSDavid du Colombier 	while(work){
3777dd7cddfSDavid du Colombier 		if(debug['v'])
3787dd7cddfSDavid du Colombier 			Bprint(&bso, "%5.2f library pass: %s\n", cputime(), file);
3797dd7cddfSDavid du Colombier 		Bflush(&bso);
3807dd7cddfSDavid du Colombier 		work = 0;
3817dd7cddfSDavid du Colombier 		for(e = start; e < stop; e = strchr(e+5, 0) + 1) {
3827dd7cddfSDavid du Colombier 			s = lookup(e+5, 0);
3837dd7cddfSDavid du Colombier 			if(s->type != SXREF)
3847dd7cddfSDavid du Colombier 				continue;
3857dd7cddfSDavid du Colombier 			sprint(pname, "%s(%s)", file, s->name);
3867dd7cddfSDavid du Colombier 			if(debug['v'])
3877dd7cddfSDavid du Colombier 				Bprint(&bso, "%5.2f library: %s\n", cputime(), pname);
3887dd7cddfSDavid du Colombier 			Bflush(&bso);
3897dd7cddfSDavid du Colombier 			l = e[1] & 0xff;
3907dd7cddfSDavid du Colombier 			l |= (e[2] & 0xff) << 8;
3917dd7cddfSDavid du Colombier 			l |= (e[3] & 0xff) << 16;
3927dd7cddfSDavid du Colombier 			l |= (e[4] & 0xff) << 24;
3937dd7cddfSDavid du Colombier 			seek(f, l, 0);
3947dd7cddfSDavid du Colombier 			l = read(f, &arhdr, SAR_HDR);
3957dd7cddfSDavid du Colombier 			if(l != SAR_HDR)
3967dd7cddfSDavid du Colombier 				goto bad;
3977dd7cddfSDavid du Colombier 			if(strncmp(arhdr.fmag, ARFMAG, sizeof(arhdr.fmag)))
3987dd7cddfSDavid du Colombier 				goto bad;
3997dd7cddfSDavid du Colombier 			l = atolwhex(arhdr.size);
4007dd7cddfSDavid du Colombier 			ldobj(f, l, pname);
4017dd7cddfSDavid du Colombier 			if(s->type == SXREF) {
4026b6b9ac8SDavid du Colombier 				diag("%s: failed to load: %s", file, s->name);
4037dd7cddfSDavid du Colombier 				errorexit();
4047dd7cddfSDavid du Colombier 			}
4057dd7cddfSDavid du Colombier 			work = 1;
4067dd7cddfSDavid du Colombier 			xrefresolv = 1;
4077dd7cddfSDavid du Colombier 		}
4087dd7cddfSDavid du Colombier 	}
4097dd7cddfSDavid du Colombier 	return;
4107dd7cddfSDavid du Colombier 
4117dd7cddfSDavid du Colombier bad:
4126b6b9ac8SDavid du Colombier 	diag("%s: bad or out of date archive", file);
4137dd7cddfSDavid du Colombier out:
4147dd7cddfSDavid du Colombier 	close(f);
4157dd7cddfSDavid du Colombier }
4167dd7cddfSDavid du Colombier 
4177dd7cddfSDavid du Colombier int
4187dd7cddfSDavid du Colombier zaddr(uchar *p, Adr *a, Sym *h[])
4197dd7cddfSDavid du Colombier {
4207dd7cddfSDavid du Colombier 	int i, c;
4217dd7cddfSDavid du Colombier 	long l;
4227dd7cddfSDavid du Colombier 	Sym *s;
4237dd7cddfSDavid du Colombier 	Auto *u;
4247dd7cddfSDavid du Colombier 
4257dd7cddfSDavid du Colombier 	c = p[2];
4267dd7cddfSDavid du Colombier 	if(c < 0 || c > NSYM){
4277dd7cddfSDavid du Colombier 		print("sym out of range: %d\n", c);
4287dd7cddfSDavid du Colombier 		p[0] = AEND+1;
4297dd7cddfSDavid du Colombier 		return 0;
4307dd7cddfSDavid du Colombier 	}
4317dd7cddfSDavid du Colombier 	a->type = p[0];
4327dd7cddfSDavid du Colombier 	a->reg = p[1];
4337dd7cddfSDavid du Colombier 	a->sym = h[c];
4347dd7cddfSDavid du Colombier 	a->name = p[3];
4357dd7cddfSDavid du Colombier 	c = 4;
4367dd7cddfSDavid du Colombier 
43722a127bbSDavid du Colombier 	if(a->reg > NREG) {
4387dd7cddfSDavid du Colombier 		print("register out of range %d\n", a->reg);
4397dd7cddfSDavid du Colombier 		p[0] = AEND+1;
4407dd7cddfSDavid du Colombier 		return 0;	/*  force real diagnostic */
4417dd7cddfSDavid du Colombier 	}
4427dd7cddfSDavid du Colombier 
4437dd7cddfSDavid du Colombier 	switch(a->type) {
4447dd7cddfSDavid du Colombier 	default:
4457dd7cddfSDavid du Colombier 		print("unknown type %d\n", a->type);
4467dd7cddfSDavid du Colombier 		p[0] = AEND+1;
4477dd7cddfSDavid du Colombier 		return 0;	/* force real diagnostic */
4487dd7cddfSDavid du Colombier 
4497dd7cddfSDavid du Colombier 	case D_NONE:
4507dd7cddfSDavid du Colombier 	case D_REG:
4517dd7cddfSDavid du Colombier 	case D_FREG:
4527dd7cddfSDavid du Colombier 	case D_CREG:
4537dd7cddfSDavid du Colombier 	case D_FPSCR:
4547dd7cddfSDavid du Colombier 	case D_MSR:
4557dd7cddfSDavid du Colombier 	case D_SREG:
4567dd7cddfSDavid du Colombier 	case D_OPT:
4577dd7cddfSDavid du Colombier 		break;
4587dd7cddfSDavid du Colombier 
4597dd7cddfSDavid du Colombier 	case D_SPR:
460375daca8SDavid du Colombier 	case D_DCR:
4617dd7cddfSDavid du Colombier 	case D_BRANCH:
4627dd7cddfSDavid du Colombier 	case D_OREG:
4637dd7cddfSDavid du Colombier 	case D_CONST:
4647dd7cddfSDavid du Colombier 		a->offset = p[4] | (p[5]<<8) |
4657dd7cddfSDavid du Colombier 			(p[6]<<16) | (p[7]<<24);
4667dd7cddfSDavid du Colombier 		c += 4;
4677dd7cddfSDavid du Colombier 		break;
4687dd7cddfSDavid du Colombier 
4697dd7cddfSDavid du Colombier 	case D_SCONST:
4707dd7cddfSDavid du Colombier 		memmove(a->sval, p+4, NSNAME);
4717dd7cddfSDavid du Colombier 		c += NSNAME;
4727dd7cddfSDavid du Colombier 		break;
4737dd7cddfSDavid du Colombier 
4747dd7cddfSDavid du Colombier 	case D_FCONST:
4757dd7cddfSDavid du Colombier 		a->ieee.l = p[4] | (p[5]<<8) |
4767dd7cddfSDavid du Colombier 			(p[6]<<16) | (p[7]<<24);
4777dd7cddfSDavid du Colombier 		a->ieee.h = p[8] | (p[9]<<8) |
4787dd7cddfSDavid du Colombier 			(p[10]<<16) | (p[11]<<24);
4797dd7cddfSDavid du Colombier 		c += 8;
4807dd7cddfSDavid du Colombier 		break;
4817dd7cddfSDavid du Colombier 	}
4827dd7cddfSDavid du Colombier 	s = a->sym;
4837dd7cddfSDavid du Colombier 	if(s == S)
4847dd7cddfSDavid du Colombier 		goto out;
4857dd7cddfSDavid du Colombier 	i = a->name;
4867dd7cddfSDavid du Colombier 	if(i != D_AUTO && i != D_PARAM)
4877dd7cddfSDavid du Colombier 		goto out;
4887dd7cddfSDavid du Colombier 
4897dd7cddfSDavid du Colombier 	l = a->offset;
4907dd7cddfSDavid du Colombier 	for(u=curauto; u; u=u->link)
4917dd7cddfSDavid du Colombier 		if(u->sym == s)
4927dd7cddfSDavid du Colombier 		if(u->type == i) {
493375daca8SDavid du Colombier 			if(u->aoffset > l)
494375daca8SDavid du Colombier 				u->aoffset = l;
4957dd7cddfSDavid du Colombier 			goto out;
4967dd7cddfSDavid du Colombier 		}
4977dd7cddfSDavid du Colombier 
4987dd7cddfSDavid du Colombier 	u = malloc(sizeof(Auto));
4997dd7cddfSDavid du Colombier 
5007dd7cddfSDavid du Colombier 	u->link = curauto;
5017dd7cddfSDavid du Colombier 	curauto = u;
5027dd7cddfSDavid du Colombier 	u->sym = s;
503375daca8SDavid du Colombier 	u->aoffset = l;
5047dd7cddfSDavid du Colombier 	u->type = i;
5057dd7cddfSDavid du Colombier out:
5067dd7cddfSDavid du Colombier 	return c;
5077dd7cddfSDavid du Colombier }
5087dd7cddfSDavid du Colombier 
5097dd7cddfSDavid du Colombier void
51080ee5cbfSDavid du Colombier addlib(char *obj)
5117dd7cddfSDavid du Colombier {
5129a747e4fSDavid du Colombier 	char name[1024], comp[256], *p;
5137dd7cddfSDavid du Colombier 	int i;
5147dd7cddfSDavid du Colombier 
5157dd7cddfSDavid du Colombier 	if(histfrogp <= 0)
5167dd7cddfSDavid du Colombier 		return;
5177dd7cddfSDavid du Colombier 
5187dd7cddfSDavid du Colombier 	if(histfrog[0]->name[1] == '/') {
5197dd7cddfSDavid du Colombier 		sprint(name, "");
5207dd7cddfSDavid du Colombier 		i = 1;
5217dd7cddfSDavid du Colombier 	} else
5227dd7cddfSDavid du Colombier 	if(histfrog[0]->name[1] == '.') {
5237dd7cddfSDavid du Colombier 		sprint(name, ".");
5247dd7cddfSDavid du Colombier 		i = 0;
5257dd7cddfSDavid du Colombier 	} else {
5267dd7cddfSDavid du Colombier 		if(debug['9'])
5277dd7cddfSDavid du Colombier 			sprint(name, "/%s/lib", thestring);
5287dd7cddfSDavid du Colombier 		else
5297dd7cddfSDavid du Colombier 			sprint(name, "/usr/%clib", thechar);
5307dd7cddfSDavid du Colombier 		i = 0;
5317dd7cddfSDavid du Colombier 	}
5327dd7cddfSDavid du Colombier 
5337dd7cddfSDavid du Colombier 	for(; i<histfrogp; i++) {
5349a747e4fSDavid du Colombier 		snprint(comp, sizeof comp, histfrog[i]->name+1);
5357dd7cddfSDavid du Colombier 		for(;;) {
5367dd7cddfSDavid du Colombier 			p = strstr(comp, "$O");
5377dd7cddfSDavid du Colombier 			if(p == 0)
5387dd7cddfSDavid du Colombier 				break;
5397dd7cddfSDavid du Colombier 			memmove(p+1, p+2, strlen(p+2)+1);
5407dd7cddfSDavid du Colombier 			p[0] = thechar;
5417dd7cddfSDavid du Colombier 		}
5427dd7cddfSDavid du Colombier 		for(;;) {
5437dd7cddfSDavid du Colombier 			p = strstr(comp, "$M");
5447dd7cddfSDavid du Colombier 			if(p == 0)
5457dd7cddfSDavid du Colombier 				break;
5469a747e4fSDavid du Colombier 			if(strlen(comp)+strlen(thestring)-2+1 >= sizeof comp) {
5477dd7cddfSDavid du Colombier 				diag("library component too long");
5487dd7cddfSDavid du Colombier 				return;
5497dd7cddfSDavid du Colombier 			}
5509a747e4fSDavid du Colombier 			memmove(p+strlen(thestring), p+2, strlen(p+2)+1);
5519a747e4fSDavid du Colombier 			memmove(p, thestring, strlen(thestring));
5527dd7cddfSDavid du Colombier 		}
5539a747e4fSDavid du Colombier 		if(strlen(name) + strlen(comp) + 3 >= sizeof(name)) {
5547dd7cddfSDavid du Colombier 			diag("library component too long");
5557dd7cddfSDavid du Colombier 			return;
5567dd7cddfSDavid du Colombier 		}
5577dd7cddfSDavid du Colombier 		strcat(name, "/");
5587dd7cddfSDavid du Colombier 		strcat(name, comp);
5597dd7cddfSDavid du Colombier 	}
5607dd7cddfSDavid du Colombier 	for(i=0; i<libraryp; i++)
5617dd7cddfSDavid du Colombier 		if(strcmp(name, library[i]) == 0)
5627dd7cddfSDavid du Colombier 			return;
56380ee5cbfSDavid du Colombier 	if(libraryp == nelem(library)){
56480ee5cbfSDavid du Colombier 		diag("too many autolibs; skipping %s", name);
56580ee5cbfSDavid du Colombier 		return;
56680ee5cbfSDavid du Colombier 	}
5677dd7cddfSDavid du Colombier 
5687dd7cddfSDavid du Colombier 	p = malloc(strlen(name) + 1);
5697dd7cddfSDavid du Colombier 	strcpy(p, name);
5707dd7cddfSDavid du Colombier 	library[libraryp] = p;
57180ee5cbfSDavid du Colombier 	p = malloc(strlen(obj) + 1);
57280ee5cbfSDavid du Colombier 	strcpy(p, obj);
57380ee5cbfSDavid du Colombier 	libraryobj[libraryp] = p;
5747dd7cddfSDavid du Colombier 	libraryp++;
5757dd7cddfSDavid du Colombier }
5767dd7cddfSDavid du Colombier 
5777dd7cddfSDavid du Colombier void
5787dd7cddfSDavid du Colombier addhist(long line, int type)
5797dd7cddfSDavid du Colombier {
5807dd7cddfSDavid du Colombier 	Auto *u;
5817dd7cddfSDavid du Colombier 	Sym *s;
5827dd7cddfSDavid du Colombier 	int i, j, k;
5837dd7cddfSDavid du Colombier 
5847dd7cddfSDavid du Colombier 	u = malloc(sizeof(Auto));
5857dd7cddfSDavid du Colombier 	s = malloc(sizeof(Sym));
5867dd7cddfSDavid du Colombier 	s->name = malloc(2*(histfrogp+1) + 1);
5877dd7cddfSDavid du Colombier 
5887dd7cddfSDavid du Colombier 	u->sym = s;
5897dd7cddfSDavid du Colombier 	u->type = type;
590375daca8SDavid du Colombier 	u->aoffset = line;
5917dd7cddfSDavid du Colombier 	u->link = curhist;
5927dd7cddfSDavid du Colombier 	curhist = u;
5937dd7cddfSDavid du Colombier 
5947dd7cddfSDavid du Colombier 	j = 1;
5957dd7cddfSDavid du Colombier 	for(i=0; i<histfrogp; i++) {
5967dd7cddfSDavid du Colombier 		k = histfrog[i]->value;
5977dd7cddfSDavid du Colombier 		s->name[j+0] = k>>8;
5987dd7cddfSDavid du Colombier 		s->name[j+1] = k;
5997dd7cddfSDavid du Colombier 		j += 2;
6007dd7cddfSDavid du Colombier 	}
6017dd7cddfSDavid du Colombier }
6027dd7cddfSDavid du Colombier 
6037dd7cddfSDavid du Colombier void
6047dd7cddfSDavid du Colombier histtoauto(void)
6057dd7cddfSDavid du Colombier {
6067dd7cddfSDavid du Colombier 	Auto *l;
6077dd7cddfSDavid du Colombier 
6087dd7cddfSDavid du Colombier 	while(l = curhist) {
6097dd7cddfSDavid du Colombier 		curhist = l->link;
6107dd7cddfSDavid du Colombier 		l->link = curauto;
6117dd7cddfSDavid du Colombier 		curauto = l;
6127dd7cddfSDavid du Colombier 	}
6137dd7cddfSDavid du Colombier }
6147dd7cddfSDavid du Colombier 
6157dd7cddfSDavid du Colombier void
6167dd7cddfSDavid du Colombier collapsefrog(Sym *s)
6177dd7cddfSDavid du Colombier {
6187dd7cddfSDavid du Colombier 	int i;
6197dd7cddfSDavid du Colombier 
6207dd7cddfSDavid du Colombier 	/*
6217dd7cddfSDavid du Colombier 	 * bad encoding of path components only allows
6227dd7cddfSDavid du Colombier 	 * MAXHIST components. if there is an overflow,
6237dd7cddfSDavid du Colombier 	 * first try to collapse xxx/..
6247dd7cddfSDavid du Colombier 	 */
6257dd7cddfSDavid du Colombier 	for(i=1; i<histfrogp; i++)
6267dd7cddfSDavid du Colombier 		if(strcmp(histfrog[i]->name+1, "..") == 0) {
6277dd7cddfSDavid du Colombier 			memmove(histfrog+i-1, histfrog+i+1,
6287dd7cddfSDavid du Colombier 				(histfrogp-i-1)*sizeof(histfrog[0]));
6297dd7cddfSDavid du Colombier 			histfrogp--;
6307dd7cddfSDavid du Colombier 			goto out;
6317dd7cddfSDavid du Colombier 		}
6327dd7cddfSDavid du Colombier 
6337dd7cddfSDavid du Colombier 	/*
6347dd7cddfSDavid du Colombier 	 * next try to collapse .
6357dd7cddfSDavid du Colombier 	 */
6367dd7cddfSDavid du Colombier 	for(i=0; i<histfrogp; i++)
6377dd7cddfSDavid du Colombier 		if(strcmp(histfrog[i]->name+1, ".") == 0) {
6387dd7cddfSDavid du Colombier 			memmove(histfrog+i, histfrog+i+1,
6397dd7cddfSDavid du Colombier 				(histfrogp-i-1)*sizeof(histfrog[0]));
6407dd7cddfSDavid du Colombier 			goto out;
6417dd7cddfSDavid du Colombier 		}
6427dd7cddfSDavid du Colombier 
6437dd7cddfSDavid du Colombier 	/*
6447dd7cddfSDavid du Colombier 	 * last chance, just truncate from front
6457dd7cddfSDavid du Colombier 	 */
6467dd7cddfSDavid du Colombier 	memmove(histfrog+0, histfrog+1,
6477dd7cddfSDavid du Colombier 		(histfrogp-1)*sizeof(histfrog[0]));
6487dd7cddfSDavid du Colombier 
6497dd7cddfSDavid du Colombier out:
6507dd7cddfSDavid du Colombier 	histfrog[histfrogp-1] = s;
6517dd7cddfSDavid du Colombier }
6527dd7cddfSDavid du Colombier 
6537dd7cddfSDavid du Colombier void
6547dd7cddfSDavid du Colombier nopout(Prog *p)
6557dd7cddfSDavid du Colombier {
6567dd7cddfSDavid du Colombier 	p->as = ANOP;
6577dd7cddfSDavid du Colombier 	p->from.type = D_NONE;
6587dd7cddfSDavid du Colombier 	p->to.type = D_NONE;
6597dd7cddfSDavid du Colombier }
6607dd7cddfSDavid du Colombier 
6617dd7cddfSDavid du Colombier uchar*
6627dd7cddfSDavid du Colombier readsome(int f, uchar *buf, uchar *good, uchar *stop, int max)
6637dd7cddfSDavid du Colombier {
6647dd7cddfSDavid du Colombier 	int n;
6657dd7cddfSDavid du Colombier 
6667dd7cddfSDavid du Colombier 	n = stop - good;
6677dd7cddfSDavid du Colombier 	memmove(buf, good, stop - good);
6687dd7cddfSDavid du Colombier 	stop = buf + n;
6697dd7cddfSDavid du Colombier 	n = MAXIO - n;
6707dd7cddfSDavid du Colombier 	if(n > max)
6717dd7cddfSDavid du Colombier 		n = max;
6727dd7cddfSDavid du Colombier 	n = read(f, stop, n);
6737dd7cddfSDavid du Colombier 	if(n <= 0)
6747dd7cddfSDavid du Colombier 		return 0;
6757dd7cddfSDavid du Colombier 	return stop + n;
6767dd7cddfSDavid du Colombier }
6777dd7cddfSDavid du Colombier 
6787dd7cddfSDavid du Colombier void
6797dd7cddfSDavid du Colombier ldobj(int f, long c, char *pn)
6807dd7cddfSDavid du Colombier {
6817dd7cddfSDavid du Colombier 	Prog *p, *t;
6827dd7cddfSDavid du Colombier 	Sym *h[NSYM], *s, *di;
6837dd7cddfSDavid du Colombier 	int v, o, r, skip;
6847dd7cddfSDavid du Colombier 	long ipc;
6857dd7cddfSDavid du Colombier 	uchar *bloc, *bsize, *stop;
686375daca8SDavid du Colombier 	ulong sig;
687375daca8SDavid du Colombier 	static int files;
688375daca8SDavid du Colombier 	static char **filen;
689375daca8SDavid du Colombier 	char **nfilen;
690375daca8SDavid du Colombier 
691375daca8SDavid du Colombier 	if((files&15) == 0){
692375daca8SDavid du Colombier 		nfilen = malloc((files+16)*sizeof(char*));
693375daca8SDavid du Colombier 		memmove(nfilen, filen, files*sizeof(char*));
694375daca8SDavid du Colombier 		free(filen);
695375daca8SDavid du Colombier 		filen = nfilen;
696375daca8SDavid du Colombier 	}
697375daca8SDavid du Colombier 	filen[files++] = strdup(pn);
6987dd7cddfSDavid du Colombier 
6997dd7cddfSDavid du Colombier 	bsize = buf.xbuf;
7007dd7cddfSDavid du Colombier 	bloc = buf.xbuf;
7017dd7cddfSDavid du Colombier 	di = S;
7027dd7cddfSDavid du Colombier 
7037dd7cddfSDavid du Colombier newloop:
7047dd7cddfSDavid du Colombier 	memset(h, 0, sizeof(h));
7057dd7cddfSDavid du Colombier 	histfrogp = 0;
7067dd7cddfSDavid du Colombier 	version++;
7077dd7cddfSDavid du Colombier 	ipc = pc;
7087dd7cddfSDavid du Colombier 	skip = 0;
7097dd7cddfSDavid du Colombier 
7107dd7cddfSDavid du Colombier loop:
7117dd7cddfSDavid du Colombier 	if(c <= 0)
7127dd7cddfSDavid du Colombier 		goto eof;
7137dd7cddfSDavid du Colombier 	r = bsize - bloc;
7147dd7cddfSDavid du Colombier 	if(r < 100 && r < c) {		/* enough for largest prog */
7157dd7cddfSDavid du Colombier 		bsize = readsome(f, buf.xbuf, bloc, bsize, c);
7167dd7cddfSDavid du Colombier 		if(bsize == 0)
7177dd7cddfSDavid du Colombier 			goto eof;
7187dd7cddfSDavid du Colombier 		bloc = buf.xbuf;
7197dd7cddfSDavid du Colombier 		goto loop;
7207dd7cddfSDavid du Colombier 	}
7217dd7cddfSDavid du Colombier 	o = bloc[0];		/* as */
7227dd7cddfSDavid du Colombier 	if(o <= 0 || o >= ALAST) {
7236b6b9ac8SDavid du Colombier 		diag("%s: opcode out of range %d", pn, o);
7247dd7cddfSDavid du Colombier 		print("	probably not a .q file\n");
7257dd7cddfSDavid du Colombier 		errorexit();
7267dd7cddfSDavid du Colombier 	}
727375daca8SDavid du Colombier 	if(o == ANAME || o == ASIGNAME) {
728375daca8SDavid du Colombier 		sig = 0;
729375daca8SDavid du Colombier 		if(o == ASIGNAME) {
730375daca8SDavid du Colombier 			sig = bloc[1] | (bloc[2]<<8) | (bloc[3]<<16) | (bloc[4]<<24);
731375daca8SDavid du Colombier 			bloc += 4;
732375daca8SDavid du Colombier 			c -= 4;
733375daca8SDavid du Colombier 		}
7347dd7cddfSDavid du Colombier 		stop = memchr(&bloc[3], 0, bsize-&bloc[3]);
7357dd7cddfSDavid du Colombier 		if(stop == 0){
7367dd7cddfSDavid du Colombier 			bsize = readsome(f, buf.xbuf, bloc, bsize, c);
7377dd7cddfSDavid du Colombier 			if(bsize == 0)
7387dd7cddfSDavid du Colombier 				goto eof;
7397dd7cddfSDavid du Colombier 			bloc = buf.xbuf;
7407dd7cddfSDavid du Colombier 			stop = memchr(&bloc[3], 0, bsize-&bloc[3]);
7417dd7cddfSDavid du Colombier 			if(stop == 0){
7427dd7cddfSDavid du Colombier 				fprint(2, "%s: name too long\n", pn);
7437dd7cddfSDavid du Colombier 				errorexit();
7447dd7cddfSDavid du Colombier 			}
7457dd7cddfSDavid du Colombier 		}
7467dd7cddfSDavid du Colombier 		v = bloc[1];	/* type */
7477dd7cddfSDavid du Colombier 		o = bloc[2];	/* sym */
7487dd7cddfSDavid du Colombier 		bloc += 3;
7497dd7cddfSDavid du Colombier 		c -= 3;
7507dd7cddfSDavid du Colombier 
7517dd7cddfSDavid du Colombier 		r = 0;
7527dd7cddfSDavid du Colombier 		if(v == D_STATIC)
7537dd7cddfSDavid du Colombier 			r = version;
7547dd7cddfSDavid du Colombier 		s = lookup((char*)bloc, r);
7557dd7cddfSDavid du Colombier 		c -= &stop[1] - bloc;
7567dd7cddfSDavid du Colombier 		bloc = stop + 1;
757375daca8SDavid du Colombier 		if(sig != 0){
758375daca8SDavid du Colombier 			if(s->sig != 0 && s->sig != sig)
759375daca8SDavid du Colombier 				diag("incompatible type signatures %lux(%s) and %lux(%s) for %s", s->sig, filen[s->file], sig, pn, s->name);
760375daca8SDavid du Colombier 			s->sig = sig;
761375daca8SDavid du Colombier 			s->file = files-1;
762375daca8SDavid du Colombier 		}
763375daca8SDavid du Colombier 
7647dd7cddfSDavid du Colombier 
7657dd7cddfSDavid du Colombier 		if(debug['W'])
7667dd7cddfSDavid du Colombier 			print("	ANAME	%s\n", s->name);
7677dd7cddfSDavid du Colombier 		h[o] = s;
7687dd7cddfSDavid du Colombier 		if((v == D_EXTERN || v == D_STATIC) && s->type == 0)
7697dd7cddfSDavid du Colombier 			s->type = SXREF;
7707dd7cddfSDavid du Colombier 		if(v == D_FILE) {
7717dd7cddfSDavid du Colombier 			if(s->type != SFILE) {
7727dd7cddfSDavid du Colombier 				histgen++;
7737dd7cddfSDavid du Colombier 				s->type = SFILE;
7747dd7cddfSDavid du Colombier 				s->value = histgen;
7757dd7cddfSDavid du Colombier 			}
7767dd7cddfSDavid du Colombier 			if(histfrogp < MAXHIST) {
7777dd7cddfSDavid du Colombier 				histfrog[histfrogp] = s;
7787dd7cddfSDavid du Colombier 				histfrogp++;
7797dd7cddfSDavid du Colombier 			} else
7807dd7cddfSDavid du Colombier 				collapsefrog(s);
7817dd7cddfSDavid du Colombier 		}
7827dd7cddfSDavid du Colombier 		goto loop;
7837dd7cddfSDavid du Colombier 	}
7847dd7cddfSDavid du Colombier 
7857dd7cddfSDavid du Colombier 	if(nhunk < sizeof(Prog))
7867dd7cddfSDavid du Colombier 		gethunk();
7877dd7cddfSDavid du Colombier 	p = (Prog*)hunk;
7887dd7cddfSDavid du Colombier 	nhunk -= sizeof(Prog);
7897dd7cddfSDavid du Colombier 	hunk += sizeof(Prog);
7907dd7cddfSDavid du Colombier 
7917dd7cddfSDavid du Colombier 	p->as = o;
7927dd7cddfSDavid du Colombier 	p->reg = bloc[1] & 0x3f;
7937dd7cddfSDavid du Colombier 	if(bloc[1] & 0x80)
7947dd7cddfSDavid du Colombier 		p->mark = NOSCHED;
7957dd7cddfSDavid du Colombier 	p->line = bloc[2] | (bloc[3]<<8) | (bloc[4]<<16) | (bloc[5]<<24);
7967dd7cddfSDavid du Colombier 	r = zaddr(bloc+6, &p->from, h) + 6;
7977dd7cddfSDavid du Colombier 	if(bloc[1] & 0x40)
7987dd7cddfSDavid du Colombier 		r += zaddr(bloc+r, &p->from3, h);
7997dd7cddfSDavid du Colombier 	else
8007dd7cddfSDavid du Colombier 		p->from3 = zprg.from3;
8017dd7cddfSDavid du Colombier 	r += zaddr(bloc+r, &p->to, h);
8027dd7cddfSDavid du Colombier 	bloc += r;
8037dd7cddfSDavid du Colombier 	c -= r;
8047dd7cddfSDavid du Colombier 
8057dd7cddfSDavid du Colombier 	if(p->reg < 0 || p->reg > NREG)
8066b6b9ac8SDavid du Colombier 		diag("register out of range %d", p->reg);
8077dd7cddfSDavid du Colombier 
8087dd7cddfSDavid du Colombier 	p->link = P;
8097dd7cddfSDavid du Colombier 	p->cond = P;
8107dd7cddfSDavid du Colombier 
8117dd7cddfSDavid du Colombier 	if(debug['W'])
8127dd7cddfSDavid du Colombier 		print("%P\n", p);
8137dd7cddfSDavid du Colombier 
8147dd7cddfSDavid du Colombier 	switch(o) {
8157dd7cddfSDavid du Colombier 	case AHISTORY:
8167dd7cddfSDavid du Colombier 		if(p->to.offset == -1) {
81780ee5cbfSDavid du Colombier 			addlib(pn);
8187dd7cddfSDavid du Colombier 			histfrogp = 0;
8197dd7cddfSDavid du Colombier 			goto loop;
8207dd7cddfSDavid du Colombier 		}
8217dd7cddfSDavid du Colombier 		addhist(p->line, D_FILE);		/* 'z' */
8227dd7cddfSDavid du Colombier 		if(p->to.offset)
8237dd7cddfSDavid du Colombier 			addhist(p->to.offset, D_FILE1);	/* 'Z' */
8247dd7cddfSDavid du Colombier 		histfrogp = 0;
8257dd7cddfSDavid du Colombier 		goto loop;
8267dd7cddfSDavid du Colombier 
8277dd7cddfSDavid du Colombier 	case AEND:
8287dd7cddfSDavid du Colombier 		histtoauto();
8297dd7cddfSDavid du Colombier 		if(curtext != P)
8307dd7cddfSDavid du Colombier 			curtext->to.autom = curauto;
8317dd7cddfSDavid du Colombier 		curauto = 0;
8327dd7cddfSDavid du Colombier 		curtext = P;
8337dd7cddfSDavid du Colombier 		if(c)
8347dd7cddfSDavid du Colombier 			goto newloop;
8357dd7cddfSDavid du Colombier 		return;
8367dd7cddfSDavid du Colombier 
8377dd7cddfSDavid du Colombier 	case AGLOBL:
8387dd7cddfSDavid du Colombier 		s = p->from.sym;
8397dd7cddfSDavid du Colombier 		if(s == S) {
8406b6b9ac8SDavid du Colombier 			diag("GLOBL must have a name\n%P", p);
8417dd7cddfSDavid du Colombier 			errorexit();
8427dd7cddfSDavid du Colombier 		}
8437dd7cddfSDavid du Colombier 		if(s->type == 0 || s->type == SXREF) {
8447dd7cddfSDavid du Colombier 			s->type = SBSS;
8457dd7cddfSDavid du Colombier 			s->value = 0;
8467dd7cddfSDavid du Colombier 		}
8477dd7cddfSDavid du Colombier 		if(s->type != SBSS) {
8486b6b9ac8SDavid du Colombier 			diag("redefinition: %s\n%P", s->name, p);
8497dd7cddfSDavid du Colombier 			s->type = SBSS;
8507dd7cddfSDavid du Colombier 			s->value = 0;
8517dd7cddfSDavid du Colombier 		}
8527dd7cddfSDavid du Colombier 		if(p->to.offset > s->value)
8537dd7cddfSDavid du Colombier 			s->value = p->to.offset;
8547dd7cddfSDavid du Colombier 		break;
8557dd7cddfSDavid du Colombier 
8567dd7cddfSDavid du Colombier 	case ADYNT:
8577dd7cddfSDavid du Colombier 		if(p->to.sym == S) {
8586b6b9ac8SDavid du Colombier 			diag("DYNT without a sym\n%P", p);
8597dd7cddfSDavid du Colombier 			break;
8607dd7cddfSDavid du Colombier 		}
8617dd7cddfSDavid du Colombier 		di = p->to.sym;
8627dd7cddfSDavid du Colombier 		p->reg = 4;
8637dd7cddfSDavid du Colombier 		if(di->type == SXREF) {
8647dd7cddfSDavid du Colombier 			if(debug['z'])
8657dd7cddfSDavid du Colombier 				Bprint(&bso, "%P set to %d\n", p, dtype);
8667dd7cddfSDavid du Colombier 			di->type = SCONST;
8677dd7cddfSDavid du Colombier 			di->value = dtype;
8687dd7cddfSDavid du Colombier 			dtype += 4;
8697dd7cddfSDavid du Colombier 		}
8707dd7cddfSDavid du Colombier 		if(p->from.sym == S)
8717dd7cddfSDavid du Colombier 			break;
8727dd7cddfSDavid du Colombier 
8737dd7cddfSDavid du Colombier 		p->from.offset = di->value;
8747dd7cddfSDavid du Colombier 		p->from.sym->type = SDATA;
8757dd7cddfSDavid du Colombier 		if(curtext == P) {
8766b6b9ac8SDavid du Colombier 			diag("DYNT not in text: %P", p);
8777dd7cddfSDavid du Colombier 			break;
8787dd7cddfSDavid du Colombier 		}
8797dd7cddfSDavid du Colombier 		p->to.sym = curtext->from.sym;
8807dd7cddfSDavid du Colombier 		p->to.type = D_CONST;
8817dd7cddfSDavid du Colombier 		p->link = datap;
8827dd7cddfSDavid du Colombier 		datap = p;
8837dd7cddfSDavid du Colombier 		break;
8847dd7cddfSDavid du Colombier 
8857dd7cddfSDavid du Colombier 	case AINIT:
8867dd7cddfSDavid du Colombier 		if(p->from.sym == S) {
8876b6b9ac8SDavid du Colombier 			diag("INIT without a sym\n%P", p);
8887dd7cddfSDavid du Colombier 			break;
8897dd7cddfSDavid du Colombier 		}
8907dd7cddfSDavid du Colombier 		if(di == S) {
8916b6b9ac8SDavid du Colombier 			diag("INIT without previous DYNT\n%P", p);
8927dd7cddfSDavid du Colombier 			break;
8937dd7cddfSDavid du Colombier 		}
8947dd7cddfSDavid du Colombier 		p->from.offset = di->value;
8957dd7cddfSDavid du Colombier 		p->from.sym->type = SDATA;
8967dd7cddfSDavid du Colombier 		p->link = datap;
8977dd7cddfSDavid du Colombier 		datap = p;
8987dd7cddfSDavid du Colombier 		break;
8997dd7cddfSDavid du Colombier 
9007dd7cddfSDavid du Colombier 	case ADATA:
9017dd7cddfSDavid du Colombier 		p->link = datap;
9027dd7cddfSDavid du Colombier 		datap = p;
9037dd7cddfSDavid du Colombier 		break;
9047dd7cddfSDavid du Colombier 
9057dd7cddfSDavid du Colombier 	case AGOK:
9066b6b9ac8SDavid du Colombier 		diag("unknown opcode\n%P", p);
9077dd7cddfSDavid du Colombier 		p->pc = pc;
9087dd7cddfSDavid du Colombier 		pc++;
9097dd7cddfSDavid du Colombier 		break;
9107dd7cddfSDavid du Colombier 
9117dd7cddfSDavid du Colombier 	case ATEXT:
9127dd7cddfSDavid du Colombier 		if(curtext != P) {
9137dd7cddfSDavid du Colombier 			histtoauto();
9147dd7cddfSDavid du Colombier 			curtext->to.autom = curauto;
9157dd7cddfSDavid du Colombier 			curauto = 0;
9167dd7cddfSDavid du Colombier 		}
9177dd7cddfSDavid du Colombier 		curtext = p;
9187dd7cddfSDavid du Colombier 		autosize = (p->to.offset+3L) & ~3L;
9197dd7cddfSDavid du Colombier 		p->to.offset = autosize;
9207dd7cddfSDavid du Colombier 		autosize += 4;
9217dd7cddfSDavid du Colombier 		s = p->from.sym;
9227dd7cddfSDavid du Colombier 		if(s == S) {
9236b6b9ac8SDavid du Colombier 			diag("TEXT must have a name\n%P", p);
9247dd7cddfSDavid du Colombier 			errorexit();
9257dd7cddfSDavid du Colombier 		}
9267dd7cddfSDavid du Colombier 		if(s->type != 0 && s->type != SXREF) {
9277dd7cddfSDavid du Colombier 			if(p->reg & DUPOK) {
9287dd7cddfSDavid du Colombier 				skip = 1;
9297dd7cddfSDavid du Colombier 				goto casedef;
9307dd7cddfSDavid du Colombier 			}
9316b6b9ac8SDavid du Colombier 			diag("redefinition: %s\n%P", s->name, p);
9327dd7cddfSDavid du Colombier 		}
9337dd7cddfSDavid du Colombier 		s->type = STEXT;
9347dd7cddfSDavid du Colombier 		s->value = pc;
9357dd7cddfSDavid du Colombier 		if(textp != P) {
9367dd7cddfSDavid du Colombier 			for(t = textp; t->cond != P; t = t->cond)
9377dd7cddfSDavid du Colombier 				;
9387dd7cddfSDavid du Colombier 			t->cond = p;
9397dd7cddfSDavid du Colombier 		} else
9407dd7cddfSDavid du Colombier 			textp = p;
9417dd7cddfSDavid du Colombier 		lastp->link = p;
9427dd7cddfSDavid du Colombier 		lastp = p;
9437dd7cddfSDavid du Colombier 		p->pc = pc;
9447dd7cddfSDavid du Colombier 		pc++;
9457dd7cddfSDavid du Colombier 		break;
9467dd7cddfSDavid du Colombier 
9477dd7cddfSDavid du Colombier 	case AFMOVS:
9487dd7cddfSDavid du Colombier 		if(skip)
9497dd7cddfSDavid du Colombier 			goto casedef;
9507dd7cddfSDavid du Colombier 
9517dd7cddfSDavid du Colombier 		if(p->from.type == D_FCONST) {
9527dd7cddfSDavid du Colombier 			/* size sb 9 max */
9537dd7cddfSDavid du Colombier 			sprint(literal, "$%lux", ieeedtof(&p->from.ieee));
9547dd7cddfSDavid du Colombier 			s = lookup(literal, 0);
9557dd7cddfSDavid du Colombier 			if(s->type == 0) {
9567dd7cddfSDavid du Colombier 				s->type = SBSS;
9577dd7cddfSDavid du Colombier 				s->value = 4;
9587dd7cddfSDavid du Colombier 				t = prg();
9597dd7cddfSDavid du Colombier 				t->as = ADATA;
9607dd7cddfSDavid du Colombier 				t->line = p->line;
9617dd7cddfSDavid du Colombier 				t->from.type = D_OREG;
9627dd7cddfSDavid du Colombier 				t->from.sym = s;
9637dd7cddfSDavid du Colombier 				t->from.name = D_EXTERN;
9647dd7cddfSDavid du Colombier 				t->reg = 4;
9657dd7cddfSDavid du Colombier 				t->to = p->from;
9667dd7cddfSDavid du Colombier 				t->link = datap;
9677dd7cddfSDavid du Colombier 				datap = t;
9687dd7cddfSDavid du Colombier 			}
9697dd7cddfSDavid du Colombier 			p->from.type = D_OREG;
9707dd7cddfSDavid du Colombier 			p->from.sym = s;
9717dd7cddfSDavid du Colombier 			p->from.name = D_EXTERN;
9727dd7cddfSDavid du Colombier 			p->from.offset = 0;
9737dd7cddfSDavid du Colombier 		}
9747dd7cddfSDavid du Colombier 		goto casedef;
9757dd7cddfSDavid du Colombier 
9767dd7cddfSDavid du Colombier 	case AFMOVD:
9777dd7cddfSDavid du Colombier 		if(skip)
9787dd7cddfSDavid du Colombier 			goto casedef;
9797dd7cddfSDavid du Colombier 		if(p->from.type == D_FCONST) {
9807dd7cddfSDavid du Colombier 			/* size sb 18 max */
9817dd7cddfSDavid du Colombier 			sprint(literal, "$%lux.%lux",
9827dd7cddfSDavid du Colombier 				p->from.ieee.l, p->from.ieee.h);
9837dd7cddfSDavid du Colombier 			s = lookup(literal, 0);
9847dd7cddfSDavid du Colombier 			if(s->type == 0) {
9857dd7cddfSDavid du Colombier 				s->type = SBSS;
9867dd7cddfSDavid du Colombier 				s->value = 8;
9877dd7cddfSDavid du Colombier 				t = prg();
9887dd7cddfSDavid du Colombier 				t->as = ADATA;
9897dd7cddfSDavid du Colombier 				t->line = p->line;
9907dd7cddfSDavid du Colombier 				t->from.type = D_OREG;
9917dd7cddfSDavid du Colombier 				t->from.sym = s;
9927dd7cddfSDavid du Colombier 				t->from.name = D_EXTERN;
9937dd7cddfSDavid du Colombier 				t->reg = 8;
9947dd7cddfSDavid du Colombier 				t->to = p->from;
9957dd7cddfSDavid du Colombier 				t->link = datap;
9967dd7cddfSDavid du Colombier 				datap = t;
9977dd7cddfSDavid du Colombier 			}
9987dd7cddfSDavid du Colombier 			p->from.type = D_OREG;
9997dd7cddfSDavid du Colombier 			p->from.sym = s;
10007dd7cddfSDavid du Colombier 			p->from.name = D_EXTERN;
10017dd7cddfSDavid du Colombier 			p->from.offset = 0;
10027dd7cddfSDavid du Colombier 		}
10037dd7cddfSDavid du Colombier 		goto casedef;
10047dd7cddfSDavid du Colombier 
10057dd7cddfSDavid du Colombier 	case ASUBC:
10067dd7cddfSDavid du Colombier 		if(p->from.type == D_CONST) {
10077dd7cddfSDavid du Colombier 			p->from.offset = -p->from.offset;
10087dd7cddfSDavid du Colombier 			p->as = AADDC;
10097dd7cddfSDavid du Colombier 		}
10107dd7cddfSDavid du Colombier 		goto casedef;
10117dd7cddfSDavid du Colombier 
10127dd7cddfSDavid du Colombier 	case ASUBCCC:
10137dd7cddfSDavid du Colombier 		if(p->from.type == D_CONST) {
10147dd7cddfSDavid du Colombier 			p->from.offset = -p->from.offset;
10157dd7cddfSDavid du Colombier 			p->as = AADDCCC;
10167dd7cddfSDavid du Colombier 		}
10177dd7cddfSDavid du Colombier 		goto casedef;
10187dd7cddfSDavid du Colombier 
10197dd7cddfSDavid du Colombier 	case ASUB:
10207dd7cddfSDavid du Colombier 		if(p->from.type == D_CONST) {
10217dd7cddfSDavid du Colombier 			p->from.offset = -p->from.offset;
10227dd7cddfSDavid du Colombier 			p->as = AADD;
10237dd7cddfSDavid du Colombier 		}
10247dd7cddfSDavid du Colombier 		goto casedef;
10257dd7cddfSDavid du Colombier 
10267dd7cddfSDavid du Colombier 	default:
10277dd7cddfSDavid du Colombier 	casedef:
10287dd7cddfSDavid du Colombier 		if(skip)
10297dd7cddfSDavid du Colombier 			nopout(p);
10307dd7cddfSDavid du Colombier 
10317dd7cddfSDavid du Colombier 		if(p->to.type == D_BRANCH)
10327dd7cddfSDavid du Colombier 			p->to.offset += ipc;
10337dd7cddfSDavid du Colombier 		lastp->link = p;
10347dd7cddfSDavid du Colombier 		lastp = p;
10357dd7cddfSDavid du Colombier 		p->pc = pc;
10367dd7cddfSDavid du Colombier 		pc++;
10377dd7cddfSDavid du Colombier 		break;
10387dd7cddfSDavid du Colombier 	}
10397dd7cddfSDavid du Colombier 	goto loop;
10407dd7cddfSDavid du Colombier 
10417dd7cddfSDavid du Colombier eof:
10426b6b9ac8SDavid du Colombier 	diag("truncated object file: %s", pn);
10437dd7cddfSDavid du Colombier }
10447dd7cddfSDavid du Colombier 
10457dd7cddfSDavid du Colombier Sym*
10467dd7cddfSDavid du Colombier lookup(char *symb, int v)
10477dd7cddfSDavid du Colombier {
10487dd7cddfSDavid du Colombier 	Sym *s;
10497dd7cddfSDavid du Colombier 	char *p;
10507dd7cddfSDavid du Colombier 	long h;
10517dd7cddfSDavid du Colombier 	int c, l;
10527dd7cddfSDavid du Colombier 
10537dd7cddfSDavid du Colombier 	h = v;
10547dd7cddfSDavid du Colombier 	for(p=symb; c = *p; p++)
10557dd7cddfSDavid du Colombier 		h = h+h+h + c;
10567dd7cddfSDavid du Colombier 	l = (p - symb) + 1;
10577dd7cddfSDavid du Colombier 	if(h < 0)
10587dd7cddfSDavid du Colombier 		h = ~h;
10597dd7cddfSDavid du Colombier 	h %= NHASH;
10607dd7cddfSDavid du Colombier 	for(s = hash[h]; s != S; s = s->link)
10617dd7cddfSDavid du Colombier 		if(s->version == v)
10627dd7cddfSDavid du Colombier 		if(memcmp(s->name, symb, l) == 0)
10637dd7cddfSDavid du Colombier 			return s;
10647dd7cddfSDavid du Colombier 
10657dd7cddfSDavid du Colombier 	while(nhunk < sizeof(Sym))
10667dd7cddfSDavid du Colombier 		gethunk();
10677dd7cddfSDavid du Colombier 	s = (Sym*)hunk;
10687dd7cddfSDavid du Colombier 	nhunk -= sizeof(Sym);
10697dd7cddfSDavid du Colombier 	hunk += sizeof(Sym);
10707dd7cddfSDavid du Colombier 
10717dd7cddfSDavid du Colombier 	s->name = malloc(l + 1);
10727dd7cddfSDavid du Colombier 	memmove(s->name, symb, l);
10737dd7cddfSDavid du Colombier 
10747dd7cddfSDavid du Colombier 	s->link = hash[h];
10757dd7cddfSDavid du Colombier 	s->type = 0;
10767dd7cddfSDavid du Colombier 	s->version = v;
10777dd7cddfSDavid du Colombier 	s->value = 0;
1078375daca8SDavid du Colombier 	s->sig = 0;
10797dd7cddfSDavid du Colombier 	hash[h] = s;
10807dd7cddfSDavid du Colombier 	return s;
10817dd7cddfSDavid du Colombier }
10827dd7cddfSDavid du Colombier 
10837dd7cddfSDavid du Colombier Prog*
10847dd7cddfSDavid du Colombier prg(void)
10857dd7cddfSDavid du Colombier {
10867dd7cddfSDavid du Colombier 	Prog *p;
10877dd7cddfSDavid du Colombier 	int n;
10887dd7cddfSDavid du Colombier 
10897dd7cddfSDavid du Colombier 	n = (sizeof(Prog) + 3) & ~3;
10907dd7cddfSDavid du Colombier 	while(nhunk < n)
10917dd7cddfSDavid du Colombier 		gethunk();
10927dd7cddfSDavid du Colombier 
10937dd7cddfSDavid du Colombier 	p = (Prog*)hunk;
10947dd7cddfSDavid du Colombier 	nhunk -= n;
10957dd7cddfSDavid du Colombier 	hunk += n;
10967dd7cddfSDavid du Colombier 
10977dd7cddfSDavid du Colombier 	*p = zprg;
10987dd7cddfSDavid du Colombier 	return p;
10997dd7cddfSDavid du Colombier }
11007dd7cddfSDavid du Colombier 
11017dd7cddfSDavid du Colombier void
11027dd7cddfSDavid du Colombier gethunk(void)
11037dd7cddfSDavid du Colombier {
11047dd7cddfSDavid du Colombier 	char *h;
1105*3f193c01SDavid du Colombier 	long nh;
11067dd7cddfSDavid du Colombier 
1107*3f193c01SDavid du Colombier 	nh = NHUNK;
1108*3f193c01SDavid du Colombier 	if(tothunk >= 5L*NHUNK) {
1109*3f193c01SDavid du Colombier 		nh = 5L*NHUNK;
1110*3f193c01SDavid du Colombier 		if(tothunk >= 25L*NHUNK)
1111*3f193c01SDavid du Colombier 			nh = 25L*NHUNK;
1112*3f193c01SDavid du Colombier 	}
1113*3f193c01SDavid du Colombier 	h = mysbrk(nh);
11147dd7cddfSDavid du Colombier 	if(h == (char *)-1) {
11156b6b9ac8SDavid du Colombier 		diag("out of memory");
11167dd7cddfSDavid du Colombier 		errorexit();
11177dd7cddfSDavid du Colombier 	}
11187dd7cddfSDavid du Colombier 
11197dd7cddfSDavid du Colombier 	hunk = h;
1120*3f193c01SDavid du Colombier 	nhunk = nh;
1121*3f193c01SDavid du Colombier 	tothunk += nh;
11227dd7cddfSDavid du Colombier }
11237dd7cddfSDavid du Colombier 
11247dd7cddfSDavid du Colombier void
11257dd7cddfSDavid du Colombier doprof1(void)
11267dd7cddfSDavid du Colombier {
11277dd7cddfSDavid du Colombier 	Sym *s;
11287dd7cddfSDavid du Colombier 	long n;
11297dd7cddfSDavid du Colombier 	Prog *p, *q;
11307dd7cddfSDavid du Colombier 
11317dd7cddfSDavid du Colombier 	if(debug['v'])
11327dd7cddfSDavid du Colombier 		Bprint(&bso, "%5.2f profile 1\n", cputime());
11337dd7cddfSDavid du Colombier 	Bflush(&bso);
11347dd7cddfSDavid du Colombier 	s = lookup("__mcount", 0);
11357dd7cddfSDavid du Colombier 	n = 1;
11367dd7cddfSDavid du Colombier 	for(p = firstp->link; p != P; p = p->link) {
11377dd7cddfSDavid du Colombier 		if(p->as == ATEXT) {
11387dd7cddfSDavid du Colombier 			q = prg();
11397dd7cddfSDavid du Colombier 			q->line = p->line;
11407dd7cddfSDavid du Colombier 			q->link = datap;
11417dd7cddfSDavid du Colombier 			datap = q;
11427dd7cddfSDavid du Colombier 			q->as = ADATA;
11437dd7cddfSDavid du Colombier 			q->from.type = D_OREG;
11447dd7cddfSDavid du Colombier 			q->from.name = D_EXTERN;
11457dd7cddfSDavid du Colombier 			q->from.offset = n*4;
11467dd7cddfSDavid du Colombier 			q->from.sym = s;
11477dd7cddfSDavid du Colombier 			q->reg = 4;
11487dd7cddfSDavid du Colombier 			q->to = p->from;
11497dd7cddfSDavid du Colombier 			q->to.type = D_CONST;
11507dd7cddfSDavid du Colombier 
11517dd7cddfSDavid du Colombier 			q = prg();
11527dd7cddfSDavid du Colombier 			q->line = p->line;
11537dd7cddfSDavid du Colombier 			q->pc = p->pc;
11547dd7cddfSDavid du Colombier 			q->link = p->link;
11557dd7cddfSDavid du Colombier 			p->link = q;
11567dd7cddfSDavid du Colombier 			p = q;
11577dd7cddfSDavid du Colombier 			p->as = AMOVW;
11587dd7cddfSDavid du Colombier 			p->from.type = D_OREG;
11597dd7cddfSDavid du Colombier 			p->from.name = D_EXTERN;
11607dd7cddfSDavid du Colombier 			p->from.sym = s;
11617dd7cddfSDavid du Colombier 			p->from.offset = n*4 + 4;
11627dd7cddfSDavid du Colombier 			p->to.type = D_REG;
11637dd7cddfSDavid du Colombier 			p->to.reg = REGTMP;
11647dd7cddfSDavid du Colombier 
11657dd7cddfSDavid du Colombier 			q = prg();
11667dd7cddfSDavid du Colombier 			q->line = p->line;
11677dd7cddfSDavid du Colombier 			q->pc = p->pc;
11687dd7cddfSDavid du Colombier 			q->link = p->link;
11697dd7cddfSDavid du Colombier 			p->link = q;
11707dd7cddfSDavid du Colombier 			p = q;
11717dd7cddfSDavid du Colombier 			p->as = AADD;
11727dd7cddfSDavid du Colombier 			p->from.type = D_CONST;
11737dd7cddfSDavid du Colombier 			p->from.offset = 1;
11747dd7cddfSDavid du Colombier 			p->to.type = D_REG;
11757dd7cddfSDavid du Colombier 			p->to.reg = REGTMP;
11767dd7cddfSDavid du Colombier 
11777dd7cddfSDavid du Colombier 			q = prg();
11787dd7cddfSDavid du Colombier 			q->line = p->line;
11797dd7cddfSDavid du Colombier 			q->pc = p->pc;
11807dd7cddfSDavid du Colombier 			q->link = p->link;
11817dd7cddfSDavid du Colombier 			p->link = q;
11827dd7cddfSDavid du Colombier 			p = q;
11837dd7cddfSDavid du Colombier 			p->as = AMOVW;
11847dd7cddfSDavid du Colombier 			p->from.type = D_REG;
11857dd7cddfSDavid du Colombier 			p->from.reg = REGTMP;
11867dd7cddfSDavid du Colombier 			p->to.type = D_OREG;
11877dd7cddfSDavid du Colombier 			p->to.name = D_EXTERN;
11887dd7cddfSDavid du Colombier 			p->to.sym = s;
11897dd7cddfSDavid du Colombier 			p->to.offset = n*4 + 4;
11907dd7cddfSDavid du Colombier 
11917dd7cddfSDavid du Colombier 			n += 2;
11927dd7cddfSDavid du Colombier 			continue;
11937dd7cddfSDavid du Colombier 		}
11947dd7cddfSDavid du Colombier 	}
11957dd7cddfSDavid du Colombier 	q = prg();
11967dd7cddfSDavid du Colombier 	q->line = 0;
11977dd7cddfSDavid du Colombier 	q->link = datap;
11987dd7cddfSDavid du Colombier 	datap = q;
11997dd7cddfSDavid du Colombier 
12007dd7cddfSDavid du Colombier 	q->as = ADATA;
12017dd7cddfSDavid du Colombier 	q->from.type = D_OREG;
12027dd7cddfSDavid du Colombier 	q->from.name = D_EXTERN;
12037dd7cddfSDavid du Colombier 	q->from.sym = s;
12047dd7cddfSDavid du Colombier 	q->reg = 4;
12057dd7cddfSDavid du Colombier 	q->to.type = D_CONST;
12067dd7cddfSDavid du Colombier 	q->to.offset = n;
12077dd7cddfSDavid du Colombier 
12087dd7cddfSDavid du Colombier 	s->type = SBSS;
12097dd7cddfSDavid du Colombier 	s->value = n*4;
12107dd7cddfSDavid du Colombier }
12117dd7cddfSDavid du Colombier 
12127dd7cddfSDavid du Colombier void
12137dd7cddfSDavid du Colombier doprof2(void)
12147dd7cddfSDavid du Colombier {
12157dd7cddfSDavid du Colombier 	Sym *s2, *s4;
12167dd7cddfSDavid du Colombier 	Prog *p, *q, *ps2, *ps4;
12177dd7cddfSDavid du Colombier 
12187dd7cddfSDavid du Colombier 	if(debug['v'])
12197dd7cddfSDavid du Colombier 		Bprint(&bso, "%5.2f profile 2\n", cputime());
12207dd7cddfSDavid du Colombier 	Bflush(&bso);
12217dd7cddfSDavid du Colombier 
12227dd7cddfSDavid du Colombier 	s2 = lookup("_profin", 0);
12237dd7cddfSDavid du Colombier 	s4 = lookup("_profout", 0);
122459cc4ca5SDavid du Colombier 	if(s2->type != STEXT || s4->type != STEXT) {
12256b6b9ac8SDavid du Colombier 		diag("_profin/_profout not defined");
122659cc4ca5SDavid du Colombier 		return;
122759cc4ca5SDavid du Colombier 	}
12287dd7cddfSDavid du Colombier 
12297dd7cddfSDavid du Colombier 	ps2 = P;
12307dd7cddfSDavid du Colombier 	ps4 = P;
12317dd7cddfSDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
12327dd7cddfSDavid du Colombier 		if(p->as == ATEXT) {
12337dd7cddfSDavid du Colombier 			if(p->from.sym == s2) {
12347dd7cddfSDavid du Colombier 				p->reg = 1;
12357dd7cddfSDavid du Colombier 				ps2 = p;
12367dd7cddfSDavid du Colombier 			}
12377dd7cddfSDavid du Colombier 			if(p->from.sym == s4) {
12387dd7cddfSDavid du Colombier 				p->reg = 1;
12397dd7cddfSDavid du Colombier 				ps4 = p;
12407dd7cddfSDavid du Colombier 			}
12417dd7cddfSDavid du Colombier 		}
12427dd7cddfSDavid du Colombier 	}
12437dd7cddfSDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
12447dd7cddfSDavid du Colombier 		if(p->as == ATEXT) {
12457dd7cddfSDavid du Colombier 			curtext = p;
12467dd7cddfSDavid du Colombier 
12477dd7cddfSDavid du Colombier 			if(p->reg & NOPROF) {	/* dont profile */
12487dd7cddfSDavid du Colombier 				for(;;) {
12497dd7cddfSDavid du Colombier 					q = p->link;
12507dd7cddfSDavid du Colombier 					if(q == P)
12517dd7cddfSDavid du Colombier 						break;
12527dd7cddfSDavid du Colombier 					if(q->as == ATEXT)
12537dd7cddfSDavid du Colombier 						break;
12547dd7cddfSDavid du Colombier 					p = q;
12557dd7cddfSDavid du Colombier 				}
12567dd7cddfSDavid du Colombier 				continue;
12577dd7cddfSDavid du Colombier 			}
12587dd7cddfSDavid du Colombier 
12597dd7cddfSDavid du Colombier 			/*
12607dd7cddfSDavid du Colombier 			 * BL	profin
12617dd7cddfSDavid du Colombier 			 */
12627dd7cddfSDavid du Colombier 			q = prg();
12637dd7cddfSDavid du Colombier 			q->line = p->line;
12647dd7cddfSDavid du Colombier 			q->pc = p->pc;
12657dd7cddfSDavid du Colombier 			q->link = p->link;
12667dd7cddfSDavid du Colombier 			p->link = q;
12677dd7cddfSDavid du Colombier 			p = q;
12687dd7cddfSDavid du Colombier 			p->as = ABL;
12697dd7cddfSDavid du Colombier 			p->to.type = D_BRANCH;
12707dd7cddfSDavid du Colombier 			p->cond = ps2;
12717dd7cddfSDavid du Colombier 			p->to.sym = s2;
12727dd7cddfSDavid du Colombier 
12737dd7cddfSDavid du Colombier 			continue;
12747dd7cddfSDavid du Colombier 		}
12757dd7cddfSDavid du Colombier 		if(p->as == ARETURN) {
12767dd7cddfSDavid du Colombier 
12777dd7cddfSDavid du Colombier 			/*
12787dd7cddfSDavid du Colombier 			 * RETURN
12797dd7cddfSDavid du Colombier 			 */
12807dd7cddfSDavid du Colombier 			q = prg();
12817dd7cddfSDavid du Colombier 			q->as = ARETURN;
12827dd7cddfSDavid du Colombier 			q->from = p->from;
12837dd7cddfSDavid du Colombier 			q->to = p->to;
12847dd7cddfSDavid du Colombier 			q->link = p->link;
12857dd7cddfSDavid du Colombier 			p->link = q;
12867dd7cddfSDavid du Colombier 
12877dd7cddfSDavid du Colombier 			/*
12887dd7cddfSDavid du Colombier 			 * BL profout
12897dd7cddfSDavid du Colombier 			 */
12907dd7cddfSDavid du Colombier 			p->as = ABL;
12917dd7cddfSDavid du Colombier 			p->from = zprg.from;
12927dd7cddfSDavid du Colombier 			p->to = zprg.to;
12937dd7cddfSDavid du Colombier 			p->to.type = D_BRANCH;
12947dd7cddfSDavid du Colombier 			p->cond = ps4;
12957dd7cddfSDavid du Colombier 			p->to.sym = s4;
12967dd7cddfSDavid du Colombier 
12977dd7cddfSDavid du Colombier 			p = q;
12987dd7cddfSDavid du Colombier 
12997dd7cddfSDavid du Colombier 			continue;
13007dd7cddfSDavid du Colombier 		}
13017dd7cddfSDavid du Colombier 	}
13027dd7cddfSDavid du Colombier }
13037dd7cddfSDavid du Colombier 
13047dd7cddfSDavid du Colombier void
13057dd7cddfSDavid du Colombier nuxiinit(void)
13067dd7cddfSDavid du Colombier {
13077dd7cddfSDavid du Colombier 	int i, c;
13087dd7cddfSDavid du Colombier 
13097dd7cddfSDavid du Colombier 	for(i=0; i<4; i++) {
13107dd7cddfSDavid du Colombier 		c = find1(0x01020304L, i+1);
13117dd7cddfSDavid du Colombier 		if(i >= 2)
13127dd7cddfSDavid du Colombier 			inuxi2[i-2] = c;
13137dd7cddfSDavid du Colombier 		if(i >= 3)
13147dd7cddfSDavid du Colombier 			inuxi1[i-3] = c;
13157dd7cddfSDavid du Colombier 		inuxi4[i] = c;
13167dd7cddfSDavid du Colombier 
13177dd7cddfSDavid du Colombier 		fnuxi8[i] = c+4;
13187dd7cddfSDavid du Colombier 		fnuxi8[i+4] = c;
13197dd7cddfSDavid du Colombier 	}
13207dd7cddfSDavid du Colombier 	if(debug['v']) {
13217dd7cddfSDavid du Colombier 		Bprint(&bso, "inuxi = ");
13227dd7cddfSDavid du Colombier 		for(i=0; i<1; i++)
13237dd7cddfSDavid du Colombier 			Bprint(&bso, "%d", inuxi1[i]);
13247dd7cddfSDavid du Colombier 		Bprint(&bso, " ");
13257dd7cddfSDavid du Colombier 		for(i=0; i<2; i++)
13267dd7cddfSDavid du Colombier 			Bprint(&bso, "%d", inuxi2[i]);
13277dd7cddfSDavid du Colombier 		Bprint(&bso, " ");
13287dd7cddfSDavid du Colombier 		for(i=0; i<4; i++)
13297dd7cddfSDavid du Colombier 			Bprint(&bso, "%d", inuxi4[i]);
13307dd7cddfSDavid du Colombier 		Bprint(&bso, "\nfnuxi = ");
13317dd7cddfSDavid du Colombier 		for(i=0; i<8; i++)
13327dd7cddfSDavid du Colombier 			Bprint(&bso, "%d", fnuxi8[i]);
13337dd7cddfSDavid du Colombier 		Bprint(&bso, "\n");
13347dd7cddfSDavid du Colombier 	}
13357dd7cddfSDavid du Colombier 	Bflush(&bso);
13367dd7cddfSDavid du Colombier }
13377dd7cddfSDavid du Colombier 
13387dd7cddfSDavid du Colombier int
13397dd7cddfSDavid du Colombier find1(long l, int c)
13407dd7cddfSDavid du Colombier {
13417dd7cddfSDavid du Colombier 	char *p;
13427dd7cddfSDavid du Colombier 	int i;
13437dd7cddfSDavid du Colombier 
13447dd7cddfSDavid du Colombier 	p = (char*)&l;
13457dd7cddfSDavid du Colombier 	for(i=0; i<4; i++)
13467dd7cddfSDavid du Colombier 		if(*p++ == c)
13477dd7cddfSDavid du Colombier 			return i;
13487dd7cddfSDavid du Colombier 	return 0;
13497dd7cddfSDavid du Colombier }
13507dd7cddfSDavid du Colombier 
13517dd7cddfSDavid du Colombier long
1352375daca8SDavid du Colombier ieeedtof(Ieee *ieeep)
13537dd7cddfSDavid du Colombier {
13547dd7cddfSDavid du Colombier 	int exp;
13557dd7cddfSDavid du Colombier 	long v;
13567dd7cddfSDavid du Colombier 
1357375daca8SDavid du Colombier 	if(ieeep->h == 0)
13587dd7cddfSDavid du Colombier 		return 0;
1359375daca8SDavid du Colombier 	exp = (ieeep->h>>20) & ((1L<<11)-1L);
13607dd7cddfSDavid du Colombier 	exp -= (1L<<10) - 2L;
1361375daca8SDavid du Colombier 	v = (ieeep->h & 0xfffffL) << 3;
1362375daca8SDavid du Colombier 	v |= (ieeep->l >> 29) & 0x7L;
1363375daca8SDavid du Colombier 	if((ieeep->l >> 28) & 1) {
13647dd7cddfSDavid du Colombier 		v++;
13657dd7cddfSDavid du Colombier 		if(v & 0x800000L) {
13667dd7cddfSDavid du Colombier 			v = (v & 0x7fffffL) >> 1;
13677dd7cddfSDavid du Colombier 			exp++;
13687dd7cddfSDavid du Colombier 		}
13697dd7cddfSDavid du Colombier 	}
13707dd7cddfSDavid du Colombier 	if(exp <= -126 || exp >= 130)
13716b6b9ac8SDavid du Colombier 		diag("double fp to single fp overflow");
13727dd7cddfSDavid du Colombier 	v |= ((exp + 126) & 0xffL) << 23;
1373375daca8SDavid du Colombier 	v |= ieeep->h & 0x80000000L;
13747dd7cddfSDavid du Colombier 	return v;
13757dd7cddfSDavid du Colombier }
13767dd7cddfSDavid du Colombier 
13777dd7cddfSDavid du Colombier double
1378375daca8SDavid du Colombier ieeedtod(Ieee *ieeep)
13797dd7cddfSDavid du Colombier {
13807dd7cddfSDavid du Colombier 	Ieee e;
13817dd7cddfSDavid du Colombier 	double fr;
13827dd7cddfSDavid du Colombier 	int exp;
13837dd7cddfSDavid du Colombier 
1384375daca8SDavid du Colombier 	if(ieeep->h & (1L<<31)) {
1385375daca8SDavid du Colombier 		e.h = ieeep->h & ~(1L<<31);
1386375daca8SDavid du Colombier 		e.l = ieeep->l;
13877dd7cddfSDavid du Colombier 		return -ieeedtod(&e);
13887dd7cddfSDavid du Colombier 	}
1389375daca8SDavid du Colombier 	if(ieeep->l == 0 && ieeep->h == 0)
13907dd7cddfSDavid du Colombier 		return 0;
1391375daca8SDavid du Colombier 	fr = ieeep->l & ((1L<<16)-1L);
13927dd7cddfSDavid du Colombier 	fr /= 1L<<16;
1393375daca8SDavid du Colombier 	fr += (ieeep->l>>16) & ((1L<<16)-1L);
13947dd7cddfSDavid du Colombier 	fr /= 1L<<16;
1395375daca8SDavid du Colombier 	fr += (ieeep->h & (1L<<20)-1L) | (1L<<20);
13967dd7cddfSDavid du Colombier 	fr /= 1L<<21;
1397375daca8SDavid du Colombier 	exp = (ieeep->h>>20) & ((1L<<11)-1L);
13987dd7cddfSDavid du Colombier 	exp -= (1L<<10) - 2L;
13997dd7cddfSDavid du Colombier 	return ldexp(fr, exp);
14007dd7cddfSDavid du Colombier }
14017dd7cddfSDavid du Colombier 
1402375daca8SDavid du Colombier void
1403375daca8SDavid du Colombier undefsym(Sym *s)
14047dd7cddfSDavid du Colombier {
1405375daca8SDavid du Colombier 	int n;
14067dd7cddfSDavid du Colombier 
1407375daca8SDavid du Colombier 	n = imports;
1408375daca8SDavid du Colombier 	if(s->value != 0)
1409375daca8SDavid du Colombier 		diag("value != 0 on SXREF");
1410375daca8SDavid du Colombier 	if(n >= 1<<Rindex)
1411375daca8SDavid du Colombier 		diag("import index %d out of range", n);
1412375daca8SDavid du Colombier 	s->value = n<<Roffset;
1413375daca8SDavid du Colombier 	s->type = SUNDEF;
1414375daca8SDavid du Colombier 	imports++;
14157dd7cddfSDavid du Colombier }
14167dd7cddfSDavid du Colombier 
14177dd7cddfSDavid du Colombier void
1418375daca8SDavid du Colombier zerosig(char *sp)
14197dd7cddfSDavid du Colombier {
1420375daca8SDavid du Colombier 	Sym *s;
1421375daca8SDavid du Colombier 
1422375daca8SDavid du Colombier 	s = lookup(sp, 0);
1423375daca8SDavid du Colombier 	s->sig = 0;
14247dd7cddfSDavid du Colombier }
14257dd7cddfSDavid du Colombier 
1426375daca8SDavid du Colombier void
1427375daca8SDavid du Colombier readundefs(char *f, int t)
14287dd7cddfSDavid du Colombier {
1429375daca8SDavid du Colombier 	int i, n;
1430375daca8SDavid du Colombier 	Sym *s;
1431375daca8SDavid du Colombier 	Biobuf *b;
1432375daca8SDavid du Colombier 	char *l, buf[256], *fields[64];
14337dd7cddfSDavid du Colombier 
1434375daca8SDavid du Colombier 	if(f == nil)
1435375daca8SDavid du Colombier 		return;
1436375daca8SDavid du Colombier 	b = Bopen(f, OREAD);
1437375daca8SDavid du Colombier 	if(b == nil){
1438375daca8SDavid du Colombier 		diag("could not open %s: %r", f);
1439375daca8SDavid du Colombier 		errorexit();
14407dd7cddfSDavid du Colombier 	}
1441375daca8SDavid du Colombier 	while((l = Brdline(b, '\n')) != nil){
1442375daca8SDavid du Colombier 		n = Blinelen(b);
1443375daca8SDavid du Colombier 		if(n >= sizeof(buf)){
1444375daca8SDavid du Colombier 			diag("%s: line too long", f);
1445375daca8SDavid du Colombier 			errorexit();
1446375daca8SDavid du Colombier 		}
1447375daca8SDavid du Colombier 		memmove(buf, l, n);
1448375daca8SDavid du Colombier 		buf[n-1] = '\0';
1449375daca8SDavid du Colombier 		n = getfields(buf, fields, nelem(fields), 1, " \t\r\n");
1450375daca8SDavid du Colombier 		if(n == nelem(fields)){
1451375daca8SDavid du Colombier 			diag("%s: bad format", f);
1452375daca8SDavid du Colombier 			errorexit();
1453375daca8SDavid du Colombier 		}
1454375daca8SDavid du Colombier 		for(i = 0; i < n; i++){
1455375daca8SDavid du Colombier 			s = lookup(fields[i], 0);
1456375daca8SDavid du Colombier 			s->type = SXREF;
1457375daca8SDavid du Colombier 			s->subtype = t;
1458375daca8SDavid du Colombier 			if(t == SIMPORT)
1459375daca8SDavid du Colombier 				nimports++;
1460375daca8SDavid du Colombier 			else
1461375daca8SDavid du Colombier 				nexports++;
1462375daca8SDavid du Colombier 		}
1463375daca8SDavid du Colombier 	}
1464375daca8SDavid du Colombier 	Bterm(b);
14657dd7cddfSDavid du Colombier }
1466