xref: /plan9-contrib/sys/src/cmd/6l/obj.c (revision 40d015479ed36701ae6dcfd8814f849fc6285e8d)
1e887ea33SDavid du Colombier #define	EXTERN
2e887ea33SDavid du Colombier #include	"l.h"
3e887ea33SDavid du Colombier #include	<ar.h>
4e887ea33SDavid du Colombier 
5e887ea33SDavid du Colombier #ifndef	DEFAULT
6e887ea33SDavid du Colombier #define	DEFAULT	'9'
7e887ea33SDavid du Colombier #endif
8e887ea33SDavid du Colombier 
9e887ea33SDavid du Colombier char	*noname		= "<none>";
10e887ea33SDavid du Colombier char	symname[]	= SYMDEF;
11e887ea33SDavid du Colombier char	thechar		= '6';
12e887ea33SDavid du Colombier char	*thestring 	= "amd64";
13e887ea33SDavid du Colombier char	*paramspace	= "FP";
14e887ea33SDavid du Colombier 
15b87cd620SDavid du Colombier char**	libdir;
16b87cd620SDavid du Colombier int	nlibdir	= 0;
17b87cd620SDavid du Colombier static	int	maxlibdir = 0;
18b87cd620SDavid du Colombier 
19e887ea33SDavid du Colombier /*
20e887ea33SDavid du Colombier  *	-H2 -T0x200028 -R0x200000	is plan9 format (was -T4136 -R4096)
21e887ea33SDavid du Colombier  *	-H5 -T0x80110000 -R4096		is ELF32
22b87cd620SDavid du Colombier  *	-H6 -T0x2000e8 -R0x200000	is ELF64
23e887ea33SDavid du Colombier  *
24b87cd620SDavid du Colombier  *	options used: 189BLPQSVWabcjlnpsvz
25e887ea33SDavid du Colombier  */
26e887ea33SDavid du Colombier 
27b87cd620SDavid du Colombier void
usage(void)28b87cd620SDavid du Colombier usage(void)
29b87cd620SDavid du Colombier {
306af32fc1SDavid du Colombier 	diag("usage: %s [-options] objects", argv0);
31b87cd620SDavid du Colombier 	errorexit();
32b87cd620SDavid du Colombier }
33b87cd620SDavid du Colombier 
34e887ea33SDavid du Colombier static int
isobjfile(char * f)35e887ea33SDavid du Colombier isobjfile(char *f)
36e887ea33SDavid du Colombier {
37e887ea33SDavid du Colombier 	int n, v;
38e887ea33SDavid du Colombier 	Biobuf *b;
39e887ea33SDavid du Colombier 	char buf1[5], buf2[SARMAG];
40e887ea33SDavid du Colombier 
41e887ea33SDavid du Colombier 	b = Bopen(f, OREAD);
42e887ea33SDavid du Colombier 	if(b == nil)
43e887ea33SDavid du Colombier 		return 0;
44e887ea33SDavid du Colombier 	n = Bread(b, buf1, 5);
45e887ea33SDavid du Colombier 	if(n == 5 && (buf1[2] == 1 && buf1[3] == '<' || buf1[3] == 1 && buf1[4] == '<'))
46e887ea33SDavid du Colombier 		v = 1;	/* good enough for our purposes */
47e887ea33SDavid du Colombier 	else{
48e887ea33SDavid du Colombier 		Bseek(b, 0, 0);
49e887ea33SDavid du Colombier 		n = Bread(b, buf2, SARMAG);
50e887ea33SDavid du Colombier 		v = n == SARMAG && strncmp(buf2, ARMAG, SARMAG) == 0;
51e887ea33SDavid du Colombier 	}
52e887ea33SDavid du Colombier 	Bterm(b);
53e887ea33SDavid du Colombier 	return v;
54e887ea33SDavid du Colombier }
55e887ea33SDavid du Colombier 
56e887ea33SDavid du Colombier void
main(int argc,char * argv[])57e887ea33SDavid du Colombier main(int argc, char *argv[])
58e887ea33SDavid du Colombier {
59e887ea33SDavid du Colombier 	int i, c;
60e887ea33SDavid du Colombier 	char *a;
61b87cd620SDavid du Colombier 	char name[LIBNAMELEN];
62e887ea33SDavid du Colombier 
63e887ea33SDavid du Colombier 	Binit(&bso, 1, OWRITE);
64e887ea33SDavid du Colombier 	cout = -1;
65e887ea33SDavid du Colombier 	listinit();
66e887ea33SDavid du Colombier 	memset(debug, 0, sizeof(debug));
67e887ea33SDavid du Colombier 	nerrors = 0;
68e887ea33SDavid du Colombier 	outfile = "6.out";
69e887ea33SDavid du Colombier 	HEADTYPE = -1;
70e887ea33SDavid du Colombier 	INITTEXT = -1;
718153b942SDavid du Colombier 	INITTEXTP = -1;
72e887ea33SDavid du Colombier 	INITDAT = -1;
73e887ea33SDavid du Colombier 	INITRND = -1;
74e887ea33SDavid du Colombier 	INITENTRY = 0;
75e887ea33SDavid du Colombier 	ARGBEGIN {
76e887ea33SDavid du Colombier 	default:
77e887ea33SDavid du Colombier 		c = ARGC();
78e887ea33SDavid du Colombier 		if(c >= 0 && c < sizeof(debug))
79e887ea33SDavid du Colombier 			debug[c]++;
80e887ea33SDavid du Colombier 		break;
81e887ea33SDavid du Colombier 	case 'o': /* output to (next arg) */
82e887ea33SDavid du Colombier 		outfile = ARGF();
83e887ea33SDavid du Colombier 		break;
84e887ea33SDavid du Colombier 	case 'E':
85e887ea33SDavid du Colombier 		a = ARGF();
86e887ea33SDavid du Colombier 		if(a)
87e887ea33SDavid du Colombier 			INITENTRY = a;
88e887ea33SDavid du Colombier 		break;
89e887ea33SDavid du Colombier 	case 'H':
90e887ea33SDavid du Colombier 		a = ARGF();
91e887ea33SDavid du Colombier 		if(a)
92e887ea33SDavid du Colombier 			HEADTYPE = atolwhex(a);
93e887ea33SDavid du Colombier 		break;
94b87cd620SDavid du Colombier 	case 'L':
95b87cd620SDavid du Colombier 		addlibpath(EARGF(usage()));
96b87cd620SDavid du Colombier 		break;
97e887ea33SDavid du Colombier 	case 'T':
98e887ea33SDavid du Colombier 		a = ARGF();
99e887ea33SDavid du Colombier 		if(a)
100e887ea33SDavid du Colombier 			INITTEXT = atolwhex(a);
101e887ea33SDavid du Colombier 		break;
1028153b942SDavid du Colombier 	case 'P':
1038153b942SDavid du Colombier 		a = ARGF();
1048153b942SDavid du Colombier 		if(a)
1058153b942SDavid du Colombier 			INITTEXTP = atolwhex(a);
1068153b942SDavid du Colombier 		break;
107e887ea33SDavid du Colombier 	case 'D':
108e887ea33SDavid du Colombier 		a = ARGF();
109e887ea33SDavid du Colombier 		if(a)
110e887ea33SDavid du Colombier 			INITDAT = atolwhex(a);
111e887ea33SDavid du Colombier 		break;
112e887ea33SDavid du Colombier 	case 'R':
113e887ea33SDavid du Colombier 		a = ARGF();
114e887ea33SDavid du Colombier 		if(a)
115e887ea33SDavid du Colombier 			INITRND = atolwhex(a);
116e887ea33SDavid du Colombier 		break;
117e887ea33SDavid du Colombier 	case 'x':	/* produce export table */
118e887ea33SDavid du Colombier 		doexp = 1;
119e887ea33SDavid du Colombier 		if(argv[1] != nil && argv[1][0] != '-' && !isobjfile(argv[1]))
120e887ea33SDavid du Colombier 			readundefs(ARGF(), SEXPORT);
121e887ea33SDavid du Colombier 		break;
122e887ea33SDavid du Colombier 	case 'u':	/* produce dynamically loadable module */
123e887ea33SDavid du Colombier 		dlm = 1;
124e887ea33SDavid du Colombier 		debug['l']++;
125e887ea33SDavid du Colombier 		if(argv[1] != nil && argv[1][0] != '-' && !isobjfile(argv[1]))
126e887ea33SDavid du Colombier 			readundefs(ARGF(), SIMPORT);
127e887ea33SDavid du Colombier 		break;
128e887ea33SDavid du Colombier 	} ARGEND
129e887ea33SDavid du Colombier 	USED(argc);
130*40d01547SDavid du Colombier 	if(*argv == nil)
131b87cd620SDavid du Colombier 		usage();
132e887ea33SDavid du Colombier 	if(!debug['9'] && !debug['U'] && !debug['B'])
133e887ea33SDavid du Colombier 		debug[DEFAULT] = 1;
134b87cd620SDavid du Colombier 	a = getenv("ccroot");
135b87cd620SDavid du Colombier 	if(a != nil && *a != '\0') {
136b87cd620SDavid du Colombier 		if(!fileexists(a)) {
137b87cd620SDavid du Colombier 			diag("nonexistent $ccroot: %s", a);
138b87cd620SDavid du Colombier 			errorexit();
139b87cd620SDavid du Colombier 		}
140b87cd620SDavid du Colombier 	}else
141b87cd620SDavid du Colombier 		a = "";
142b87cd620SDavid du Colombier 	snprint(name, sizeof(name), "%s/%s/lib", a, thestring);
143b87cd620SDavid du Colombier 	addlibpath(name);
144e887ea33SDavid du Colombier 	if(HEADTYPE == -1) {
145e887ea33SDavid du Colombier 		if(debug['B'])
146e887ea33SDavid du Colombier 			HEADTYPE = 2;
147e887ea33SDavid du Colombier 		if(debug['9'])
148e887ea33SDavid du Colombier 			HEADTYPE = 2;
149e887ea33SDavid du Colombier 	}
150e887ea33SDavid du Colombier 	switch(HEADTYPE) {
151e887ea33SDavid du Colombier 	default:
152e887ea33SDavid du Colombier 		diag("unknown -H option");
153e887ea33SDavid du Colombier 		errorexit();
154e887ea33SDavid du Colombier 	case 2:	/* plan 9 */
155e887ea33SDavid du Colombier 		HEADR = 32L+8L;
156e887ea33SDavid du Colombier 		if(INITTEXT == -1)
157e887ea33SDavid du Colombier 			INITTEXT = 0x200000+HEADR;
158e887ea33SDavid du Colombier 		if(INITDAT == -1)
159e887ea33SDavid du Colombier 			INITDAT = 0;
160e887ea33SDavid du Colombier 		if(INITRND == -1)
161e887ea33SDavid du Colombier 			INITRND = 0x200000;
162e887ea33SDavid du Colombier 		break;
163e887ea33SDavid du Colombier 	case 5:	/* elf32 executable */
1648153b942SDavid du Colombier 		HEADR = rnd(Ehdr32sz+3*Phdr32sz, 16);
165e887ea33SDavid du Colombier 		if(INITTEXT == -1)
166e887ea33SDavid du Colombier 			INITTEXT = 0xf0110000L;
167e887ea33SDavid du Colombier 		if(INITDAT == -1)
168e887ea33SDavid du Colombier 			INITDAT = 0;
169e887ea33SDavid du Colombier 		if(INITRND == -1)
170e887ea33SDavid du Colombier 			INITRND = 4096;
171e887ea33SDavid du Colombier 		break;
172b87cd620SDavid du Colombier 	case 6:	/* ELF64 executable */
1738153b942SDavid du Colombier 		HEADR = rnd(Ehdr64sz+3*Phdr64sz, 16);
174b87cd620SDavid du Colombier 		if(INITTEXT == -1)
175b87cd620SDavid du Colombier 			INITTEXT = 0x200000+HEADR;
176b87cd620SDavid du Colombier 		if(INITDAT == -1)
177b87cd620SDavid du Colombier 			INITDAT = 0;
178b87cd620SDavid du Colombier 		if(INITRND == -1)
179b87cd620SDavid du Colombier 			INITRND = 0x200000;
180b87cd620SDavid du Colombier 		break;
181e887ea33SDavid du Colombier 	}
1828153b942SDavid du Colombier 	if (INITTEXTP == -1)
1838153b942SDavid du Colombier 		INITTEXTP = INITTEXT;
184e887ea33SDavid du Colombier 	if(INITDAT != 0 && INITRND != 0)
185e887ea33SDavid du Colombier 		print("warning: -D0x%llux is ignored because of -R0x%lux\n",
186e887ea33SDavid du Colombier 			INITDAT, INITRND);
187e887ea33SDavid du Colombier 	if(debug['v'])
188e887ea33SDavid du Colombier 		Bprint(&bso, "HEADER = -H%ld -T0x%llux -D0x%llux -R0x%lux\n",
189e887ea33SDavid du Colombier 			HEADTYPE, INITTEXT, INITDAT, INITRND);
190e887ea33SDavid du Colombier 	Bflush(&bso);
191e887ea33SDavid du Colombier 	for(i=1; optab[i].as; i++) {
192e887ea33SDavid du Colombier 		c = optab[i].as;
193e887ea33SDavid du Colombier 		if(opindex[c] != nil) {
194e887ea33SDavid du Colombier 			diag("phase error in optab: %d (%A)", i, c);
195e887ea33SDavid du Colombier 			errorexit();
196e887ea33SDavid du Colombier 		}
197e887ea33SDavid du Colombier 		opindex[c] = &optab[i];
198e887ea33SDavid du Colombier 	}
199e887ea33SDavid du Colombier 
200e887ea33SDavid du Colombier 	for(i=0; i<Ymax; i++)
201e887ea33SDavid du Colombier 		ycover[i*Ymax + i] = 1;
202e887ea33SDavid du Colombier 
203e887ea33SDavid du Colombier 	ycover[Yi0*Ymax + Yi8] = 1;
204e887ea33SDavid du Colombier 	ycover[Yi1*Ymax + Yi8] = 1;
205e887ea33SDavid du Colombier 
206e887ea33SDavid du Colombier 	ycover[Yi0*Ymax + Ys32] = 1;
207e887ea33SDavid du Colombier 	ycover[Yi1*Ymax + Ys32] = 1;
208e887ea33SDavid du Colombier 	ycover[Yi8*Ymax + Ys32] = 1;
209e887ea33SDavid du Colombier 
210e887ea33SDavid du Colombier 	ycover[Yi0*Ymax + Yi32] = 1;
211e887ea33SDavid du Colombier 	ycover[Yi1*Ymax + Yi32] = 1;
212e887ea33SDavid du Colombier 	ycover[Yi8*Ymax + Yi32] = 1;
213e887ea33SDavid du Colombier 	ycover[Ys32*Ymax + Yi32] = 1;
214e887ea33SDavid du Colombier 
215e887ea33SDavid du Colombier 	ycover[Yi0*Ymax + Yi64] = 1;
216e887ea33SDavid du Colombier 	ycover[Yi1*Ymax + Yi64] = 1;
217e887ea33SDavid du Colombier 	ycover[Yi8*Ymax + Yi64] = 1;
218e887ea33SDavid du Colombier 	ycover[Ys32*Ymax + Yi64] = 1;
219e887ea33SDavid du Colombier 	ycover[Yi32*Ymax + Yi64] = 1;
220e887ea33SDavid du Colombier 
221e887ea33SDavid du Colombier 	ycover[Yal*Ymax + Yrb] = 1;
222e887ea33SDavid du Colombier 	ycover[Ycl*Ymax + Yrb] = 1;
223e887ea33SDavid du Colombier 	ycover[Yax*Ymax + Yrb] = 1;
224e887ea33SDavid du Colombier 	ycover[Ycx*Ymax + Yrb] = 1;
225e887ea33SDavid du Colombier 	ycover[Yrx*Ymax + Yrb] = 1;
226*40d01547SDavid du Colombier 	ycover[Yrl*Ymax + Yrb] = 1;	// 8l disables this
227*40d01547SDavid du Colombier 	ycover[Ycl*Ymax + Ycx] = 1;	// 8l disables this
228e887ea33SDavid du Colombier 
229e887ea33SDavid du Colombier 	ycover[Yax*Ymax + Yrx] = 1;
230e887ea33SDavid du Colombier 	ycover[Ycx*Ymax + Yrx] = 1;
231e887ea33SDavid du Colombier 
232e887ea33SDavid du Colombier 	ycover[Yax*Ymax + Yrl] = 1;
233e887ea33SDavid du Colombier 	ycover[Ycx*Ymax + Yrl] = 1;
234e887ea33SDavid du Colombier 	ycover[Yrx*Ymax + Yrl] = 1;
235e887ea33SDavid du Colombier 
236e887ea33SDavid du Colombier 	ycover[Yf0*Ymax + Yrf] = 1;
237e887ea33SDavid du Colombier 
238e887ea33SDavid du Colombier 	ycover[Yal*Ymax + Ymb] = 1;
239e887ea33SDavid du Colombier 	ycover[Ycl*Ymax + Ymb] = 1;
240e887ea33SDavid du Colombier 	ycover[Yax*Ymax + Ymb] = 1;
241e887ea33SDavid du Colombier 	ycover[Ycx*Ymax + Ymb] = 1;
242e887ea33SDavid du Colombier 	ycover[Yrx*Ymax + Ymb] = 1;
243e887ea33SDavid du Colombier 	ycover[Yrb*Ymax + Ymb] = 1;
244*40d01547SDavid du Colombier 	ycover[Yrl*Ymax + Ymb] = 1;	// 8l disables this
245e887ea33SDavid du Colombier 	ycover[Ym*Ymax + Ymb] = 1;
246e887ea33SDavid du Colombier 
247e887ea33SDavid du Colombier 	ycover[Yax*Ymax + Yml] = 1;
248e887ea33SDavid du Colombier 	ycover[Ycx*Ymax + Yml] = 1;
249e887ea33SDavid du Colombier 	ycover[Yrx*Ymax + Yml] = 1;
250e887ea33SDavid du Colombier 	ycover[Yrl*Ymax + Yml] = 1;
251e887ea33SDavid du Colombier 	ycover[Ym*Ymax + Yml] = 1;
252e887ea33SDavid du Colombier 
253e887ea33SDavid du Colombier 	ycover[Yax*Ymax + Ymm] = 1;
254e887ea33SDavid du Colombier 	ycover[Ycx*Ymax + Ymm] = 1;
255e887ea33SDavid du Colombier 	ycover[Yrx*Ymax + Ymm] = 1;
256e887ea33SDavid du Colombier 	ycover[Yrl*Ymax + Ymm] = 1;
257e887ea33SDavid du Colombier 	ycover[Ym*Ymax + Ymm] = 1;
258e887ea33SDavid du Colombier 	ycover[Ymr*Ymax + Ymm] = 1;
259e887ea33SDavid du Colombier 
260e887ea33SDavid du Colombier 	ycover[Yax*Ymax + Yxm] = 1;
261e887ea33SDavid du Colombier 	ycover[Ycx*Ymax + Yxm] = 1;
262e887ea33SDavid du Colombier 	ycover[Yrx*Ymax + Yxm] = 1;
263e887ea33SDavid du Colombier 	ycover[Yrl*Ymax + Yxm] = 1;
264e887ea33SDavid du Colombier 	ycover[Ym*Ymax + Yxm] = 1;
265e887ea33SDavid du Colombier 	ycover[Yxr*Ymax + Yxm] = 1;
266*40d01547SDavid du Colombier 	ycover[Yxr*Ymax + Yxyr] = 1;
267*40d01547SDavid du Colombier 
268*40d01547SDavid du Colombier 	ycover[Yyr*Ymax + Yxm] = 1;
269*40d01547SDavid du Colombier 	ycover[Yyr*Ymax + Yxyr] = 1;
270e887ea33SDavid du Colombier 
271e887ea33SDavid du Colombier 	for(i=0; i<D_NONE; i++) {
272e887ea33SDavid du Colombier 		reg[i] = -1;
273e887ea33SDavid du Colombier 		if(i >= D_AL && i <= D_R15B) {
274e887ea33SDavid du Colombier 			reg[i] = (i-D_AL) & 7;
275e887ea33SDavid du Colombier 			if(i >= D_SPB && i <= D_DIB)
276e887ea33SDavid du Colombier 				regrex[i] = 0x40;
277e887ea33SDavid du Colombier 			if(i >= D_R8B && i <= D_R15B)
278e887ea33SDavid du Colombier 				regrex[i] = Rxr | Rxx | Rxb;
279e887ea33SDavid du Colombier 		}
280e887ea33SDavid du Colombier 		if(i >= D_AH && i<= D_BH)
281e887ea33SDavid du Colombier 			reg[i] = 4 + ((i-D_AH) & 7);
282e887ea33SDavid du Colombier 		if(i >= D_AX && i <= D_R15) {
283e887ea33SDavid du Colombier 			reg[i] = (i-D_AX) & 7;
284e887ea33SDavid du Colombier 			if(i >= D_R8)
285e887ea33SDavid du Colombier 				regrex[i] = Rxr | Rxx | Rxb;
286e887ea33SDavid du Colombier 		}
287*40d01547SDavid du Colombier /*
288e887ea33SDavid du Colombier 		if(i >= D_F0 && i <= D_F0+7)
289e887ea33SDavid du Colombier 			reg[i] = (i-D_F0) & 7;
290*40d01547SDavid du Colombier */
291e887ea33SDavid du Colombier 		if(i >= D_M0 && i <= D_M0+7)
292e887ea33SDavid du Colombier 			reg[i] = (i-D_M0) & 7;
293e887ea33SDavid du Colombier 		if(i >= D_X0 && i <= D_X0+15) {
294e887ea33SDavid du Colombier 			reg[i] = (i-D_X0) & 7;
295e887ea33SDavid du Colombier 			if(i >= D_X0+8)
296e887ea33SDavid du Colombier 				regrex[i] = Rxr | Rxx | Rxb;
297e887ea33SDavid du Colombier 		}
298*40d01547SDavid du Colombier 		if(i >= D_Y0 && i <= D_Y0+15) {
299*40d01547SDavid du Colombier 			reg[i] = (i-D_Y0) & 7;
300*40d01547SDavid du Colombier 			if(i >= D_Y0+8)
301*40d01547SDavid du Colombier 				regrex[i] = Rxr | Rxx | Rxb;
302*40d01547SDavid du Colombier 		}
303e887ea33SDavid du Colombier 		if(i >= D_CR+8 && i <= D_CR+15)
304e887ea33SDavid du Colombier 			regrex[i] = Rxr;
305e887ea33SDavid du Colombier 	}
306e887ea33SDavid du Colombier 
307e887ea33SDavid du Colombier 	zprg.link = P;
308e887ea33SDavid du Colombier 	zprg.pcond = P;
309e887ea33SDavid du Colombier 	zprg.back = 2;
310e887ea33SDavid du Colombier 	zprg.as = AGOK;
311e887ea33SDavid du Colombier 	zprg.from.type = D_NONE;
312e887ea33SDavid du Colombier 	zprg.from.index = D_NONE;
313e887ea33SDavid du Colombier 	zprg.from.scale = 1;
314e887ea33SDavid du Colombier 	zprg.to = zprg.from;
315e887ea33SDavid du Colombier 	zprg.mode = 64;
316e887ea33SDavid du Colombier 
317e887ea33SDavid du Colombier 	pcstr = "%.6llux ";
318e887ea33SDavid du Colombier 	nuxiinit();
319e887ea33SDavid du Colombier 	histgen = 0;
320e887ea33SDavid du Colombier 	textp = P;
321e887ea33SDavid du Colombier 	datap = P;
322e887ea33SDavid du Colombier 	edatap = P;
323e887ea33SDavid du Colombier 	pc = 0;
324e887ea33SDavid du Colombier 	dtype = 4;
325e887ea33SDavid du Colombier 	cout = create(outfile, 1, 0775);
326e887ea33SDavid du Colombier 	if(cout < 0) {
327b87cd620SDavid du Colombier 		diag("cannot create %s: %r", outfile);
328e887ea33SDavid du Colombier 		errorexit();
329e887ea33SDavid du Colombier 	}
330e887ea33SDavid du Colombier 	version = 0;
331e887ea33SDavid du Colombier 	cbp = buf.cbuf;
332e887ea33SDavid du Colombier 	cbc = sizeof(buf.cbuf);
333e887ea33SDavid du Colombier 	firstp = prg();
334e887ea33SDavid du Colombier 	lastp = firstp;
335e887ea33SDavid du Colombier 
336e887ea33SDavid du Colombier 	if(INITENTRY == 0) {
337e887ea33SDavid du Colombier 		INITENTRY = "_main";
338e887ea33SDavid du Colombier 		if(debug['p'])
339e887ea33SDavid du Colombier 			INITENTRY = "_mainp";
340e887ea33SDavid du Colombier 		if(!debug['l'])
341e887ea33SDavid du Colombier 			lookup(INITENTRY, 0)->type = SXREF;
342e887ea33SDavid du Colombier 	} else if(!(*INITENTRY >= '0' && *INITENTRY <= '9'))
343e887ea33SDavid du Colombier 		lookup(INITENTRY, 0)->type = SXREF;
344e887ea33SDavid du Colombier 
345e887ea33SDavid du Colombier 	while(*argv)
346e887ea33SDavid du Colombier 		objfile(*argv++);
347e887ea33SDavid du Colombier 	if(!debug['l'])
348e887ea33SDavid du Colombier 		loadlib();
349e887ea33SDavid du Colombier 	firstp = firstp->link;
350e887ea33SDavid du Colombier 	if(firstp == P)
351e887ea33SDavid du Colombier 		errorexit();
352e887ea33SDavid du Colombier 	if(doexp || dlm){
353e887ea33SDavid du Colombier 		EXPTAB = "_exporttab";
354e887ea33SDavid du Colombier 		zerosig(EXPTAB);
355e887ea33SDavid du Colombier 		zerosig("etext");
356e887ea33SDavid du Colombier 		zerosig("edata");
357e887ea33SDavid du Colombier 		zerosig("end");
358e887ea33SDavid du Colombier 		if(dlm){
359e887ea33SDavid du Colombier 			import();
360e887ea33SDavid du Colombier 			HEADTYPE = 2;
361e887ea33SDavid du Colombier 			INITTEXT = 0;
362e887ea33SDavid du Colombier 			INITDAT = 0;
363e887ea33SDavid du Colombier 			INITRND = 8;
364e887ea33SDavid du Colombier 			INITENTRY = EXPTAB;
365e887ea33SDavid du Colombier 		}
366e887ea33SDavid du Colombier 		export();
367e887ea33SDavid du Colombier 	}
368e887ea33SDavid du Colombier 	patch();
369e887ea33SDavid du Colombier 	follow();
370e887ea33SDavid du Colombier 	dodata();
371e887ea33SDavid du Colombier 	dostkoff();
372e887ea33SDavid du Colombier 	paramspace = "SP";	/* (FP) now (SP) on output */
373e887ea33SDavid du Colombier 	if(debug['p'])
374e887ea33SDavid du Colombier 		if(debug['1'])
375e887ea33SDavid du Colombier 			doprof1();
376e887ea33SDavid du Colombier 		else
377e887ea33SDavid du Colombier 			doprof2();
378e887ea33SDavid du Colombier 	span();
379e887ea33SDavid du Colombier 	doinit();
380e887ea33SDavid du Colombier 	asmb();
381e887ea33SDavid du Colombier 	undef();
382e887ea33SDavid du Colombier 	if(debug['v']) {
383e887ea33SDavid du Colombier 		Bprint(&bso, "%5.2f cpu time\n", cputime());
384e887ea33SDavid du Colombier 		Bprint(&bso, "%ld symbols\n", nsymbol);
385e887ea33SDavid du Colombier 		Bprint(&bso, "%ld memory used\n", thunk);
386e887ea33SDavid du Colombier 		Bprint(&bso, "%d sizeof adr\n", sizeof(Adr));
387e887ea33SDavid du Colombier 		Bprint(&bso, "%d sizeof prog\n", sizeof(Prog));
388e887ea33SDavid du Colombier 	}
389e887ea33SDavid du Colombier 	Bflush(&bso);
390e887ea33SDavid du Colombier 
391e887ea33SDavid du Colombier 	errorexit();
392e887ea33SDavid du Colombier }
393e887ea33SDavid du Colombier 
394e887ea33SDavid du Colombier void
addlibpath(char * arg)395b87cd620SDavid du Colombier addlibpath(char *arg)
396b87cd620SDavid du Colombier {
397b87cd620SDavid du Colombier 	char **p;
398b87cd620SDavid du Colombier 
399b87cd620SDavid du Colombier 	if(nlibdir >= maxlibdir) {
400b87cd620SDavid du Colombier 		if(maxlibdir == 0)
401b87cd620SDavid du Colombier 			maxlibdir = 8;
402b87cd620SDavid du Colombier 		else
403b87cd620SDavid du Colombier 			maxlibdir *= 2;
404b87cd620SDavid du Colombier 		p = malloc(maxlibdir*sizeof(*p));
405b87cd620SDavid du Colombier 		if(p == nil) {
406b87cd620SDavid du Colombier 			diag("out of memory");
407b87cd620SDavid du Colombier 			errorexit();
408b87cd620SDavid du Colombier 		}
409b87cd620SDavid du Colombier 		memmove(p, libdir, nlibdir*sizeof(*p));
410b87cd620SDavid du Colombier 		free(libdir);
411b87cd620SDavid du Colombier 		libdir = p;
412b87cd620SDavid du Colombier 	}
413b87cd620SDavid du Colombier 	libdir[nlibdir++] = strdup(arg);
414b87cd620SDavid du Colombier }
415b87cd620SDavid du Colombier 
416b87cd620SDavid du Colombier char*
findlib(char * file)417b87cd620SDavid du Colombier findlib(char *file)
418b87cd620SDavid du Colombier {
419b87cd620SDavid du Colombier 	int i;
420b87cd620SDavid du Colombier 	char name[LIBNAMELEN];
421b87cd620SDavid du Colombier 
422b87cd620SDavid du Colombier 	for(i = 0; i < nlibdir; i++) {
423b87cd620SDavid du Colombier 		snprint(name, sizeof(name), "%s/%s", libdir[i], file);
424b87cd620SDavid du Colombier 		if(fileexists(name))
425b87cd620SDavid du Colombier 			return libdir[i];
426b87cd620SDavid du Colombier 	}
427b87cd620SDavid du Colombier 	return nil;
428b87cd620SDavid du Colombier }
429b87cd620SDavid du Colombier 
430b87cd620SDavid du Colombier void
loadlib(void)431e887ea33SDavid du Colombier loadlib(void)
432e887ea33SDavid du Colombier {
433e887ea33SDavid du Colombier 	int i;
434e887ea33SDavid du Colombier 	long h;
435e887ea33SDavid du Colombier 	Sym *s;
436e887ea33SDavid du Colombier 
437e887ea33SDavid du Colombier loop:
438e887ea33SDavid du Colombier 	xrefresolv = 0;
439e887ea33SDavid du Colombier 	for(i=0; i<libraryp; i++) {
440e887ea33SDavid du Colombier 		if(debug['v'])
441e887ea33SDavid du Colombier 			Bprint(&bso, "%5.2f autolib: %s (from %s)\n", cputime(), library[i], libraryobj[i]);
442e887ea33SDavid du Colombier 		objfile(library[i]);
443e887ea33SDavid du Colombier 	}
444e887ea33SDavid du Colombier 	if(xrefresolv)
445e887ea33SDavid du Colombier 	for(h=0; h<nelem(hash); h++)
446e887ea33SDavid du Colombier 	for(s = hash[h]; s != S; s = s->link)
447e887ea33SDavid du Colombier 		if(s->type == SXREF)
448e887ea33SDavid du Colombier 			goto loop;
449e887ea33SDavid du Colombier }
450e887ea33SDavid du Colombier 
451e887ea33SDavid du Colombier void
errorexit(void)452e887ea33SDavid du Colombier errorexit(void)
453e887ea33SDavid du Colombier {
454e887ea33SDavid du Colombier 
455e887ea33SDavid du Colombier 	if(nerrors) {
456e887ea33SDavid du Colombier 		if(cout >= 0)
457e887ea33SDavid du Colombier 			remove(outfile);
458e887ea33SDavid du Colombier 		exits("error");
459e887ea33SDavid du Colombier 	}
460e887ea33SDavid du Colombier 	exits(0);
461e887ea33SDavid du Colombier }
462e887ea33SDavid du Colombier 
463e887ea33SDavid du Colombier void
objfile(char * file)464e887ea33SDavid du Colombier objfile(char *file)
465e887ea33SDavid du Colombier {
466e887ea33SDavid du Colombier 	long off, esym, cnt, l;
467e887ea33SDavid du Colombier 	int f, work;
468e887ea33SDavid du Colombier 	Sym *s;
469e887ea33SDavid du Colombier 	char magbuf[SARMAG];
470b87cd620SDavid du Colombier 	char name[LIBNAMELEN], pname[LIBNAMELEN];
471e887ea33SDavid du Colombier 	struct ar_hdr arhdr;
472e887ea33SDavid du Colombier 	char *e, *start, *stop;
473e887ea33SDavid du Colombier 
474e887ea33SDavid du Colombier 	if(debug['v'])
475e887ea33SDavid du Colombier 		Bprint(&bso, "%5.2f ldobj: %s\n", cputime(), file);
476e887ea33SDavid du Colombier 	Bflush(&bso);
477b87cd620SDavid du Colombier 	if(file[0] == '-' && file[1] == 'l') {
478b87cd620SDavid du Colombier 		snprint(pname, sizeof(pname), "lib%s.a", file+2);
479b87cd620SDavid du Colombier 		e = findlib(pname);
480b87cd620SDavid du Colombier 		if(e == nil) {
481b87cd620SDavid du Colombier 			diag("cannot find library: %s", file);
482b87cd620SDavid du Colombier 			errorexit();
483b87cd620SDavid du Colombier 		}
484b87cd620SDavid du Colombier 		snprint(name, sizeof(name), "%s/%s", e, pname);
485b87cd620SDavid du Colombier 		file = name;
486b87cd620SDavid du Colombier 	}
487e887ea33SDavid du Colombier 	f = open(file, 0);
488e887ea33SDavid du Colombier 	if(f < 0) {
489b87cd620SDavid du Colombier 		diag("cannot open %s: %r", file);
490e887ea33SDavid du Colombier 		errorexit();
491e887ea33SDavid du Colombier 	}
492e887ea33SDavid du Colombier 	l = read(f, magbuf, SARMAG);
493e887ea33SDavid du Colombier 	if(l != SARMAG || strncmp(magbuf, ARMAG, SARMAG)){
494e887ea33SDavid du Colombier 		/* load it as a regular file */
495e887ea33SDavid du Colombier 		l = seek(f, 0L, 2);
496e887ea33SDavid du Colombier 		seek(f, 0L, 0);
497e887ea33SDavid du Colombier 		ldobj(f, l, file);
498e887ea33SDavid du Colombier 		close(f);
499e887ea33SDavid du Colombier 		return;
500e887ea33SDavid du Colombier 	}
501e887ea33SDavid du Colombier 
502e887ea33SDavid du Colombier 	l = read(f, &arhdr, SAR_HDR);
503e887ea33SDavid du Colombier 	if(l != SAR_HDR) {
504e887ea33SDavid du Colombier 		diag("%s: short read on archive file symbol header", file);
505e887ea33SDavid du Colombier 		goto out;
506e887ea33SDavid du Colombier 	}
507e887ea33SDavid du Colombier 	if(strncmp(arhdr.name, symname, strlen(symname))) {
508e887ea33SDavid du Colombier 		diag("%s: first entry not symbol header", file);
509e887ea33SDavid du Colombier 		goto out;
510e887ea33SDavid du Colombier 	}
511e887ea33SDavid du Colombier 
512e887ea33SDavid du Colombier 	esym = SARMAG + SAR_HDR + atolwhex(arhdr.size);
513e887ea33SDavid du Colombier 	off = SARMAG + SAR_HDR;
514e887ea33SDavid du Colombier 
515e887ea33SDavid du Colombier 	/*
516e887ea33SDavid du Colombier 	 * just bang the whole symbol file into memory
517e887ea33SDavid du Colombier 	 */
518e887ea33SDavid du Colombier 	seek(f, off, 0);
519e887ea33SDavid du Colombier 	cnt = esym - off;
520e887ea33SDavid du Colombier 	start = malloc(cnt + 10);
521e887ea33SDavid du Colombier 	cnt = read(f, start, cnt);
522e887ea33SDavid du Colombier 	if(cnt <= 0){
523e887ea33SDavid du Colombier 		close(f);
524e887ea33SDavid du Colombier 		return;
525e887ea33SDavid du Colombier 	}
526e887ea33SDavid du Colombier 	stop = &start[cnt];
527e887ea33SDavid du Colombier 	memset(stop, 0, 10);
528e887ea33SDavid du Colombier 
529e887ea33SDavid du Colombier 	work = 1;
530e887ea33SDavid du Colombier 	while(work) {
531e887ea33SDavid du Colombier 		if(debug['v'])
532e887ea33SDavid du Colombier 			Bprint(&bso, "%5.2f library pass: %s\n", cputime(), file);
533e887ea33SDavid du Colombier 		Bflush(&bso);
534e887ea33SDavid du Colombier 		work = 0;
535e887ea33SDavid du Colombier 		for(e = start; e < stop; e = strchr(e+5, 0) + 1) {
536e887ea33SDavid du Colombier 			s = lookup(e+5, 0);
537e887ea33SDavid du Colombier 			if(s->type != SXREF)
538e887ea33SDavid du Colombier 				continue;
539e887ea33SDavid du Colombier 			sprint(pname, "%s(%s)", file, s->name);
540e887ea33SDavid du Colombier 			if(debug['v'])
541e887ea33SDavid du Colombier 				Bprint(&bso, "%5.2f library: %s\n", cputime(), pname);
542e887ea33SDavid du Colombier 			Bflush(&bso);
543e887ea33SDavid du Colombier 			l = e[1] & 0xff;
544e887ea33SDavid du Colombier 			l |= (e[2] & 0xff) << 8;
545e887ea33SDavid du Colombier 			l |= (e[3] & 0xff) << 16;
546e887ea33SDavid du Colombier 			l |= (e[4] & 0xff) << 24;
547e887ea33SDavid du Colombier 			seek(f, l, 0);
548*40d01547SDavid du Colombier 			l = read(f, &arhdr, SAR_HDR);
549e887ea33SDavid du Colombier 			if(l != SAR_HDR)
550e887ea33SDavid du Colombier 				goto bad;
551e887ea33SDavid du Colombier 			if(strncmp(arhdr.fmag, ARFMAG, sizeof(arhdr.fmag)))
552e887ea33SDavid du Colombier 				goto bad;
553e887ea33SDavid du Colombier 			l = atolwhex(arhdr.size);
554e887ea33SDavid du Colombier 			ldobj(f, l, pname);
555e887ea33SDavid du Colombier 			if(s->type == SXREF) {
556e887ea33SDavid du Colombier 				diag("%s: failed to load: %s", file, s->name);
557e887ea33SDavid du Colombier 				errorexit();
558e887ea33SDavid du Colombier 			}
559e887ea33SDavid du Colombier 			work = 1;
560e887ea33SDavid du Colombier 			xrefresolv = 1;
561e887ea33SDavid du Colombier 		}
562e887ea33SDavid du Colombier 	}
563e887ea33SDavid du Colombier 	return;
564e887ea33SDavid du Colombier 
565e887ea33SDavid du Colombier bad:
566e887ea33SDavid du Colombier 	diag("%s: bad or out of date archive", file);
567e887ea33SDavid du Colombier out:
568e887ea33SDavid du Colombier 	close(f);
569e887ea33SDavid du Colombier }
570e887ea33SDavid du Colombier 
571e887ea33SDavid du Colombier int
zaddr(uchar * p,Adr * a,Sym * h[])572e887ea33SDavid du Colombier zaddr(uchar *p, Adr *a, Sym *h[])
573e887ea33SDavid du Colombier {
574e887ea33SDavid du Colombier 	int c, t, i;
575b87cd620SDavid du Colombier 	int l;
576e887ea33SDavid du Colombier 	Sym *s;
577e887ea33SDavid du Colombier 	Auto *u;
578e887ea33SDavid du Colombier 
579e887ea33SDavid du Colombier 	t = p[0];
580e887ea33SDavid du Colombier 	c = 1;
581e887ea33SDavid du Colombier 	if(t & T_INDEX) {
582e887ea33SDavid du Colombier 		a->index = p[c];
583e887ea33SDavid du Colombier 		a->scale = p[c+1];
584e887ea33SDavid du Colombier 		c += 2;
585e887ea33SDavid du Colombier 	} else {
586e887ea33SDavid du Colombier 		a->index = D_NONE;
587e887ea33SDavid du Colombier 		a->scale = 0;
588e887ea33SDavid du Colombier 	}
589e887ea33SDavid du Colombier 	a->offset = 0;
590e887ea33SDavid du Colombier 	if(t & T_OFFSET) {
591e887ea33SDavid du Colombier 		l = p[c] | (p[c+1]<<8) | (p[c+2]<<16) | (p[c+3]<<24);
592e887ea33SDavid du Colombier 		a->offset = l;
593e887ea33SDavid du Colombier 		c += 4;
594e887ea33SDavid du Colombier 		if(t & T_64) {
595e887ea33SDavid du Colombier 			l = p[c] | (p[c+1]<<8) | (p[c+2]<<16) | (p[c+3]<<24);
596e887ea33SDavid du Colombier 			a->offset = ((vlong)l<<32) | (a->offset & 0xFFFFFFFFUL);
597e887ea33SDavid du Colombier 			c += 4;
598e887ea33SDavid du Colombier 		}
599e887ea33SDavid du Colombier 	}
600e887ea33SDavid du Colombier 	a->sym = S;
601e887ea33SDavid du Colombier 	if(t & T_SYM) {
602e887ea33SDavid du Colombier 		a->sym = h[p[c]];
603e887ea33SDavid du Colombier 		c++;
604e887ea33SDavid du Colombier 	}
605e887ea33SDavid du Colombier 	a->type = D_NONE;
606e887ea33SDavid du Colombier 	if(t & T_FCONST) {
607e887ea33SDavid du Colombier 		a->ieee.l = p[c] | (p[c+1]<<8) | (p[c+2]<<16) | (p[c+3]<<24);
608e887ea33SDavid du Colombier 		a->ieee.h = p[c+4] | (p[c+5]<<8) | (p[c+6]<<16) | (p[c+7]<<24);
609e887ea33SDavid du Colombier 		c += 8;
610e887ea33SDavid du Colombier 		a->type = D_FCONST;
611e887ea33SDavid du Colombier 	} else
612e887ea33SDavid du Colombier 	if(t & T_SCONST) {
613e887ea33SDavid du Colombier 		for(i=0; i<NSNAME; i++)
614e887ea33SDavid du Colombier 			a->scon[i] = p[c+i];
615e887ea33SDavid du Colombier 		c += NSNAME;
616e887ea33SDavid du Colombier 		a->type = D_SCONST;
617e887ea33SDavid du Colombier 	}
618e887ea33SDavid du Colombier 	if(t & T_TYPE) {
619e887ea33SDavid du Colombier 		a->type = p[c];
620e887ea33SDavid du Colombier 		c++;
621e887ea33SDavid du Colombier 	}
622e887ea33SDavid du Colombier 	s = a->sym;
623e887ea33SDavid du Colombier 	if(s == S)
624e887ea33SDavid du Colombier 		return c;
625e887ea33SDavid du Colombier 
626e887ea33SDavid du Colombier 	t = a->type;
627e887ea33SDavid du Colombier 	if(t != D_AUTO && t != D_PARAM)
628e887ea33SDavid du Colombier 		return c;
629e887ea33SDavid du Colombier 	l = a->offset;
630e887ea33SDavid du Colombier 	for(u=curauto; u; u=u->link) {
631e887ea33SDavid du Colombier 		if(u->asym == s)
632e887ea33SDavid du Colombier 		if(u->type == t) {
633e887ea33SDavid du Colombier 			if(u->aoffset > l)
634e887ea33SDavid du Colombier 				u->aoffset = l;
635e887ea33SDavid du Colombier 			return c;
636e887ea33SDavid du Colombier 		}
637e887ea33SDavid du Colombier 	}
638e887ea33SDavid du Colombier 
639e887ea33SDavid du Colombier 	while(nhunk < sizeof(Auto))
640e887ea33SDavid du Colombier 		gethunk();
641e887ea33SDavid du Colombier 	u = (Auto*)hunk;
642e887ea33SDavid du Colombier 	nhunk -= sizeof(Auto);
643e887ea33SDavid du Colombier 	hunk += sizeof(Auto);
644e887ea33SDavid du Colombier 
645e887ea33SDavid du Colombier 	u->link = curauto;
646e887ea33SDavid du Colombier 	curauto = u;
647e887ea33SDavid du Colombier 	u->asym = s;
648e887ea33SDavid du Colombier 	u->aoffset = l;
649e887ea33SDavid du Colombier 	u->type = t;
650e887ea33SDavid du Colombier 	return c;
651e887ea33SDavid du Colombier }
652e887ea33SDavid du Colombier 
653e887ea33SDavid du Colombier void
addlib(char * obj)654e887ea33SDavid du Colombier addlib(char *obj)
655e887ea33SDavid du Colombier {
656b87cd620SDavid du Colombier 	char fn1[LIBNAMELEN], fn2[LIBNAMELEN], comp[LIBNAMELEN], *p, *name;
657b87cd620SDavid du Colombier 	int i, search;
658e887ea33SDavid du Colombier 
659e887ea33SDavid du Colombier 	if(histfrogp <= 0)
660e887ea33SDavid du Colombier 		return;
661e887ea33SDavid du Colombier 
662b87cd620SDavid du Colombier 	name = fn1;
663b87cd620SDavid du Colombier 	search = 0;
664e887ea33SDavid du Colombier 	if(histfrog[0]->name[1] == '/') {
665e887ea33SDavid du Colombier 		sprint(name, "");
666e887ea33SDavid du Colombier 		i = 1;
667b87cd620SDavid du Colombier 	} else if(histfrog[0]->name[1] == '.') {
668e887ea33SDavid du Colombier 		sprint(name, ".");
669e887ea33SDavid du Colombier 		i = 0;
670e887ea33SDavid du Colombier 	} else {
671b87cd620SDavid du Colombier 		sprint(name, "");
672e887ea33SDavid du Colombier 		i = 0;
673b87cd620SDavid du Colombier 		search = 1;
674e887ea33SDavid du Colombier 	}
675e887ea33SDavid du Colombier 
676e887ea33SDavid du Colombier 	for(; i<histfrogp; i++) {
677e887ea33SDavid du Colombier 		snprint(comp, sizeof comp, histfrog[i]->name+1);
678e887ea33SDavid du Colombier 		for(;;) {
679e887ea33SDavid du Colombier 			p = strstr(comp, "$O");
680e887ea33SDavid du Colombier 			if(p == 0)
681e887ea33SDavid du Colombier 				break;
682e887ea33SDavid du Colombier 			memmove(p+1, p+2, strlen(p+2)+1);
683e887ea33SDavid du Colombier 			p[0] = thechar;
684e887ea33SDavid du Colombier 		}
685e887ea33SDavid du Colombier 		for(;;) {
686e887ea33SDavid du Colombier 			p = strstr(comp, "$M");
687e887ea33SDavid du Colombier 			if(p == 0)
688e887ea33SDavid du Colombier 				break;
689e887ea33SDavid du Colombier 			if(strlen(comp)+strlen(thestring)-2+1 >= sizeof comp) {
690e887ea33SDavid du Colombier 				diag("library component too long");
691e887ea33SDavid du Colombier 				return;
692e887ea33SDavid du Colombier 			}
693e887ea33SDavid du Colombier 			memmove(p+strlen(thestring), p+2, strlen(p+2)+1);
694e887ea33SDavid du Colombier 			memmove(p, thestring, strlen(thestring));
695e887ea33SDavid du Colombier 		}
696b87cd620SDavid du Colombier 		if(strlen(fn1) + strlen(comp) + 3 >= sizeof(fn1)) {
697e887ea33SDavid du Colombier 			diag("library component too long");
698e887ea33SDavid du Colombier 			return;
699e887ea33SDavid du Colombier 		}
700b87cd620SDavid du Colombier 		if(i > 0 || !search)
701b87cd620SDavid du Colombier 			strcat(fn1, "/");
702b87cd620SDavid du Colombier 		strcat(fn1, comp);
703e887ea33SDavid du Colombier 	}
704b87cd620SDavid du Colombier 
705b87cd620SDavid du Colombier 	cleanname(name);
706b87cd620SDavid du Colombier 
707b87cd620SDavid du Colombier 	if(search){
708b87cd620SDavid du Colombier 		p = findlib(name);
709b87cd620SDavid du Colombier 		if(p != nil){
710b87cd620SDavid du Colombier 			snprint(fn2, sizeof(fn2), "%s/%s", p, name);
711b87cd620SDavid du Colombier 			name = fn2;
712b87cd620SDavid du Colombier 		}
713b87cd620SDavid du Colombier 	}
714b87cd620SDavid du Colombier 
715e887ea33SDavid du Colombier 	for(i=0; i<libraryp; i++)
716e887ea33SDavid du Colombier 		if(strcmp(name, library[i]) == 0)
717e887ea33SDavid du Colombier 			return;
718e887ea33SDavid du Colombier 	if(libraryp == nelem(library)){
719e887ea33SDavid du Colombier 		diag("too many autolibs; skipping %s", name);
720e887ea33SDavid du Colombier 		return;
721e887ea33SDavid du Colombier 	}
722e887ea33SDavid du Colombier 
723e887ea33SDavid du Colombier 	p = malloc(strlen(name) + 1);
724e887ea33SDavid du Colombier 	strcpy(p, name);
725e887ea33SDavid du Colombier 	library[libraryp] = p;
726e887ea33SDavid du Colombier 	p = malloc(strlen(obj) + 1);
727e887ea33SDavid du Colombier 	strcpy(p, obj);
728e887ea33SDavid du Colombier 	libraryobj[libraryp] = p;
729e887ea33SDavid du Colombier 	libraryp++;
730e887ea33SDavid du Colombier }
731e887ea33SDavid du Colombier 
732e887ea33SDavid du Colombier void
addhist(long line,int type)733e887ea33SDavid du Colombier addhist(long line, int type)
734e887ea33SDavid du Colombier {
735e887ea33SDavid du Colombier 	Auto *u;
736e887ea33SDavid du Colombier 	Sym *s;
737e887ea33SDavid du Colombier 	int i, j, k;
738e887ea33SDavid du Colombier 
739e887ea33SDavid du Colombier 	u = malloc(sizeof(Auto));
740e887ea33SDavid du Colombier 	s = malloc(sizeof(Sym));
741e887ea33SDavid du Colombier 	s->name = malloc(2*(histfrogp+1) + 1);
742e887ea33SDavid du Colombier 
743e887ea33SDavid du Colombier 	u->asym = s;
744e887ea33SDavid du Colombier 	u->type = type;
745e887ea33SDavid du Colombier 	u->aoffset = line;
746e887ea33SDavid du Colombier 	u->link = curhist;
747e887ea33SDavid du Colombier 	curhist = u;
748e887ea33SDavid du Colombier 
749e887ea33SDavid du Colombier 	j = 1;
750e887ea33SDavid du Colombier 	for(i=0; i<histfrogp; i++) {
751e887ea33SDavid du Colombier 		k = histfrog[i]->value;
752e887ea33SDavid du Colombier 		s->name[j+0] = k>>8;
753e887ea33SDavid du Colombier 		s->name[j+1] = k;
754e887ea33SDavid du Colombier 		j += 2;
755e887ea33SDavid du Colombier 	}
756e887ea33SDavid du Colombier }
757e887ea33SDavid du Colombier 
758e887ea33SDavid du Colombier void
histtoauto(void)759e887ea33SDavid du Colombier histtoauto(void)
760e887ea33SDavid du Colombier {
761e887ea33SDavid du Colombier 	Auto *l;
762e887ea33SDavid du Colombier 
763e887ea33SDavid du Colombier 	while(l = curhist) {
764e887ea33SDavid du Colombier 		curhist = l->link;
765e887ea33SDavid du Colombier 		l->link = curauto;
766e887ea33SDavid du Colombier 		curauto = l;
767e887ea33SDavid du Colombier 	}
768e887ea33SDavid du Colombier }
769e887ea33SDavid du Colombier 
770e887ea33SDavid du Colombier void
collapsefrog(Sym * s)771e887ea33SDavid du Colombier collapsefrog(Sym *s)
772e887ea33SDavid du Colombier {
773e887ea33SDavid du Colombier 	int i;
774e887ea33SDavid du Colombier 
775e887ea33SDavid du Colombier 	/*
776e887ea33SDavid du Colombier 	 * bad encoding of path components only allows
777e887ea33SDavid du Colombier 	 * MAXHIST components. if there is an overflow,
778e887ea33SDavid du Colombier 	 * first try to collapse xxx/..
779e887ea33SDavid du Colombier 	 */
780e887ea33SDavid du Colombier 	for(i=1; i<histfrogp; i++)
781e887ea33SDavid du Colombier 		if(strcmp(histfrog[i]->name+1, "..") == 0) {
782e887ea33SDavid du Colombier 			memmove(histfrog+i-1, histfrog+i+1,
783e887ea33SDavid du Colombier 				(histfrogp-i-1)*sizeof(histfrog[0]));
784e887ea33SDavid du Colombier 			histfrogp--;
785e887ea33SDavid du Colombier 			goto out;
786e887ea33SDavid du Colombier 		}
787e887ea33SDavid du Colombier 
788e887ea33SDavid du Colombier 	/*
789e887ea33SDavid du Colombier 	 * next try to collapse .
790e887ea33SDavid du Colombier 	 */
791e887ea33SDavid du Colombier 	for(i=0; i<histfrogp; i++)
792e887ea33SDavid du Colombier 		if(strcmp(histfrog[i]->name+1, ".") == 0) {
793e887ea33SDavid du Colombier 			memmove(histfrog+i, histfrog+i+1,
794e887ea33SDavid du Colombier 				(histfrogp-i-1)*sizeof(histfrog[0]));
795e887ea33SDavid du Colombier 			goto out;
796e887ea33SDavid du Colombier 		}
797e887ea33SDavid du Colombier 
798e887ea33SDavid du Colombier 	/*
799e887ea33SDavid du Colombier 	 * last chance, just truncate from front
800e887ea33SDavid du Colombier 	 */
801e887ea33SDavid du Colombier 	memmove(histfrog+0, histfrog+1,
802e887ea33SDavid du Colombier 		(histfrogp-1)*sizeof(histfrog[0]));
803e887ea33SDavid du Colombier 
804e887ea33SDavid du Colombier out:
805e887ea33SDavid du Colombier 	histfrog[histfrogp-1] = s;
806e887ea33SDavid du Colombier }
807e887ea33SDavid du Colombier 
808e887ea33SDavid du Colombier void
nopout(Prog * p)809e887ea33SDavid du Colombier nopout(Prog *p)
810e887ea33SDavid du Colombier {
811e887ea33SDavid du Colombier 	p->as = ANOP;
812e887ea33SDavid du Colombier 	p->from.type = D_NONE;
813e887ea33SDavid du Colombier 	p->to.type = D_NONE;
814e887ea33SDavid du Colombier }
815e887ea33SDavid du Colombier 
816e887ea33SDavid du Colombier uchar*
readsome(int f,uchar * buf,uchar * good,uchar * stop,int max)817e887ea33SDavid du Colombier readsome(int f, uchar *buf, uchar *good, uchar *stop, int max)
818e887ea33SDavid du Colombier {
819e887ea33SDavid du Colombier 	int n;
820e887ea33SDavid du Colombier 
821e887ea33SDavid du Colombier 	n = stop - good;
822e887ea33SDavid du Colombier 	memmove(buf, good, stop - good);
823e887ea33SDavid du Colombier 	stop = buf + n;
824e887ea33SDavid du Colombier 	n = MAXIO - n;
825e887ea33SDavid du Colombier 	if(n > max)
826e887ea33SDavid du Colombier 		n = max;
827e887ea33SDavid du Colombier 	n = read(f, stop, n);
828e887ea33SDavid du Colombier 	if(n <= 0)
829e887ea33SDavid du Colombier 		return 0;
830e887ea33SDavid du Colombier 	return stop + n;
831e887ea33SDavid du Colombier }
832e887ea33SDavid du Colombier 
833e887ea33SDavid du Colombier void
ldobj(int f,long c,char * pn)834e887ea33SDavid du Colombier ldobj(int f, long c, char *pn)
835e887ea33SDavid du Colombier {
836e887ea33SDavid du Colombier 	vlong ipc;
837e887ea33SDavid du Colombier 	Prog *p, *t;
838e887ea33SDavid du Colombier 	uchar *bloc, *bsize, *stop;
839e887ea33SDavid du Colombier 	int v, o, r, skip, mode;
840e887ea33SDavid du Colombier 	Sym *h[NSYM], *s, *di;
841e887ea33SDavid du Colombier 	ulong sig;
842e887ea33SDavid du Colombier 	static int files;
843e887ea33SDavid du Colombier 	static char **filen;
844e887ea33SDavid du Colombier 	char **nfilen;
845e887ea33SDavid du Colombier 
846e887ea33SDavid du Colombier 	if((files&15) == 0){
847e887ea33SDavid du Colombier 		nfilen = malloc((files+16)*sizeof(char*));
848e887ea33SDavid du Colombier 		memmove(nfilen, filen, files*sizeof(char*));
849e887ea33SDavid du Colombier 		free(filen);
850e887ea33SDavid du Colombier 		filen = nfilen;
851e887ea33SDavid du Colombier 	}
852e887ea33SDavid du Colombier 	filen[files++] = strdup(pn);
853e887ea33SDavid du Colombier 
854e887ea33SDavid du Colombier 	bsize = buf.xbuf;
855e887ea33SDavid du Colombier 	bloc = buf.xbuf;
856e887ea33SDavid du Colombier 	di = S;
857e887ea33SDavid du Colombier 
858e887ea33SDavid du Colombier newloop:
859e887ea33SDavid du Colombier 	memset(h, 0, sizeof(h));
860e887ea33SDavid du Colombier 	version++;
861e887ea33SDavid du Colombier 	histfrogp = 0;
862e887ea33SDavid du Colombier 	ipc = pc;
863e887ea33SDavid du Colombier 	skip = 0;
864e887ea33SDavid du Colombier 	mode = 64;
865e887ea33SDavid du Colombier 
866e887ea33SDavid du Colombier loop:
867e887ea33SDavid du Colombier 	if(c <= 0)
868e887ea33SDavid du Colombier 		goto eof;
869e887ea33SDavid du Colombier 	r = bsize - bloc;
870e887ea33SDavid du Colombier 	if(r < 100 && r < c) {		/* enough for largest prog */
871e887ea33SDavid du Colombier 		bsize = readsome(f, buf.xbuf, bloc, bsize, c);
872e887ea33SDavid du Colombier 		if(bsize == 0)
873e887ea33SDavid du Colombier 			goto eof;
874e887ea33SDavid du Colombier 		bloc = buf.xbuf;
875e887ea33SDavid du Colombier 		goto loop;
876e887ea33SDavid du Colombier 	}
877e887ea33SDavid du Colombier 	o = bloc[0] | (bloc[1] << 8);
878e887ea33SDavid du Colombier 	if(o <= AXXX || o >= ALAST) {
879e887ea33SDavid du Colombier 		if(o < 0)
880e887ea33SDavid du Colombier 			goto eof;
881e887ea33SDavid du Colombier 		diag("%s: opcode out of range %d", pn, o);
882e887ea33SDavid du Colombier 		print("	probably not a .6 file\n");
883e887ea33SDavid du Colombier 		errorexit();
884e887ea33SDavid du Colombier 	}
885e887ea33SDavid du Colombier 
886e887ea33SDavid du Colombier 	if(o == ANAME || o == ASIGNAME) {
887e887ea33SDavid du Colombier 		sig = 0;
888e887ea33SDavid du Colombier 		if(o == ASIGNAME) {
889e887ea33SDavid du Colombier 			sig = bloc[2] | (bloc[3]<<8) | (bloc[4]<<16) | (bloc[5]<<24);
890e887ea33SDavid du Colombier 			bloc += 4;
891e887ea33SDavid du Colombier 			c -= 4;
892e887ea33SDavid du Colombier 		}
893e887ea33SDavid du Colombier 		stop = memchr(&bloc[4], 0, bsize-&bloc[4]);
894e887ea33SDavid du Colombier 		if(stop == 0){
895e887ea33SDavid du Colombier 			bsize = readsome(f, buf.xbuf, bloc, bsize, c);
896e887ea33SDavid du Colombier 			if(bsize == 0)
897e887ea33SDavid du Colombier 				goto eof;
898e887ea33SDavid du Colombier 			bloc = buf.xbuf;
899e887ea33SDavid du Colombier 			stop = memchr(&bloc[4], 0, bsize-&bloc[4]);
900e887ea33SDavid du Colombier 			if(stop == 0){
901e887ea33SDavid du Colombier 				fprint(2, "%s: name too long\n", pn);
902e887ea33SDavid du Colombier 				errorexit();
903e887ea33SDavid du Colombier 			}
904e887ea33SDavid du Colombier 		}
905e887ea33SDavid du Colombier 		v = bloc[2];	/* type */
906e887ea33SDavid du Colombier 		o = bloc[3];	/* sym */
907e887ea33SDavid du Colombier 		bloc += 4;
908e887ea33SDavid du Colombier 		c -= 4;
909e887ea33SDavid du Colombier 
910e887ea33SDavid du Colombier 		r = 0;
911e887ea33SDavid du Colombier 		if(v == D_STATIC)
912e887ea33SDavid du Colombier 			r = version;
913e887ea33SDavid du Colombier 		s = lookup((char*)bloc, r);
914e887ea33SDavid du Colombier 		c -= &stop[1] - bloc;
915e887ea33SDavid du Colombier 		bloc = stop + 1;
916e887ea33SDavid du Colombier 
917e887ea33SDavid du Colombier 		if(debug['S'] && r == 0)
918e887ea33SDavid du Colombier 			sig = 1729;
919e887ea33SDavid du Colombier 		if(sig != 0){
920e887ea33SDavid du Colombier 			if(s->sig != 0 && s->sig != sig)
921e887ea33SDavid du Colombier 				diag("incompatible type signatures %lux(%s) and %lux(%s) for %s", s->sig, filen[s->file], sig, pn, s->name);
922e887ea33SDavid du Colombier 			s->sig = sig;
923e887ea33SDavid du Colombier 			s->file = files-1;
924e887ea33SDavid du Colombier 		}
925e887ea33SDavid du Colombier 
926e887ea33SDavid du Colombier 		if(debug['W'])
927e887ea33SDavid du Colombier 			print("	ANAME	%s\n", s->name);
928e887ea33SDavid du Colombier 		h[o] = s;
929e887ea33SDavid du Colombier 		if((v == D_EXTERN || v == D_STATIC) && s->type == 0)
930e887ea33SDavid du Colombier 			s->type = SXREF;
931e887ea33SDavid du Colombier 		if(v == D_FILE) {
932e887ea33SDavid du Colombier 			if(s->type != SFILE) {
933e887ea33SDavid du Colombier 				histgen++;
934e887ea33SDavid du Colombier 				s->type = SFILE;
935e887ea33SDavid du Colombier 				s->value = histgen;
936e887ea33SDavid du Colombier 			}
937e887ea33SDavid du Colombier 			if(histfrogp < MAXHIST) {
938e887ea33SDavid du Colombier 				histfrog[histfrogp] = s;
939e887ea33SDavid du Colombier 				histfrogp++;
940e887ea33SDavid du Colombier 			} else
941e887ea33SDavid du Colombier 				collapsefrog(s);
942e887ea33SDavid du Colombier 		}
943e887ea33SDavid du Colombier 		goto loop;
944e887ea33SDavid du Colombier 	}
945e887ea33SDavid du Colombier 
946e887ea33SDavid du Colombier 	while(nhunk < sizeof(Prog))
947e887ea33SDavid du Colombier 		gethunk();
948e887ea33SDavid du Colombier 	p = (Prog*)hunk;
949e887ea33SDavid du Colombier 	nhunk -= sizeof(Prog);
950e887ea33SDavid du Colombier 	hunk += sizeof(Prog);
951e887ea33SDavid du Colombier 
952e887ea33SDavid du Colombier 	p->as = o;
953e887ea33SDavid du Colombier 	p->line = bloc[2] | (bloc[3] << 8) | (bloc[4] << 16) | (bloc[5] << 24);
954e887ea33SDavid du Colombier 	p->back = 2;
955e887ea33SDavid du Colombier 	p->mode = mode;
956e887ea33SDavid du Colombier 	r = zaddr(bloc+6, &p->from, h) + 6;
957e887ea33SDavid du Colombier 	r += zaddr(bloc+r, &p->to, h);
958e887ea33SDavid du Colombier 	bloc += r;
959e887ea33SDavid du Colombier 	c -= r;
960e887ea33SDavid du Colombier 
961e887ea33SDavid du Colombier 	if(debug['W'])
962e887ea33SDavid du Colombier 		print("%P\n", p);
963e887ea33SDavid du Colombier 
964e887ea33SDavid du Colombier 	switch(p->as) {
965e887ea33SDavid du Colombier 	case AHISTORY:
966e887ea33SDavid du Colombier 		if(p->to.offset == -1) {
967e887ea33SDavid du Colombier 			addlib(pn);
968e887ea33SDavid du Colombier 			histfrogp = 0;
969e887ea33SDavid du Colombier 			goto loop;
970e887ea33SDavid du Colombier 		}
971e887ea33SDavid du Colombier 		addhist(p->line, D_FILE);		/* 'z' */
972e887ea33SDavid du Colombier 		if(p->to.offset)
973e887ea33SDavid du Colombier 			addhist(p->to.offset, D_FILE1);	/* 'Z' */
974e887ea33SDavid du Colombier 		histfrogp = 0;
975e887ea33SDavid du Colombier 		goto loop;
976e887ea33SDavid du Colombier 
977e887ea33SDavid du Colombier 	case AEND:
978e887ea33SDavid du Colombier 		histtoauto();
979e887ea33SDavid du Colombier 		if(curtext != P)
980e887ea33SDavid du Colombier 			curtext->to.autom = curauto;
981e887ea33SDavid du Colombier 		curauto = 0;
982e887ea33SDavid du Colombier 		curtext = P;
983e887ea33SDavid du Colombier 		if(c)
984e887ea33SDavid du Colombier 			goto newloop;
985e887ea33SDavid du Colombier 		return;
986e887ea33SDavid du Colombier 
987e887ea33SDavid du Colombier 	case AGLOBL:
988e887ea33SDavid du Colombier 		s = p->from.sym;
989e887ea33SDavid du Colombier 		if(s->type == 0 || s->type == SXREF) {
990e887ea33SDavid du Colombier 			s->type = SBSS;
991e887ea33SDavid du Colombier 			s->value = 0;
992e887ea33SDavid du Colombier 		}
993e887ea33SDavid du Colombier 		if(s->type != SBSS) {
994e887ea33SDavid du Colombier 			diag("%s: redefinition: %s in %s",
995e887ea33SDavid du Colombier 				pn, s->name, TNAME);
996e887ea33SDavid du Colombier 			s->type = SBSS;
997e887ea33SDavid du Colombier 			s->value = 0;
998e887ea33SDavid du Colombier 		}
999e887ea33SDavid du Colombier 		if(p->to.offset > s->value)
1000e887ea33SDavid du Colombier 			s->value = p->to.offset;
1001e887ea33SDavid du Colombier 		goto loop;
1002e887ea33SDavid du Colombier 
1003e887ea33SDavid du Colombier 	case ADYNT:
1004e887ea33SDavid du Colombier 		if(p->to.sym == S) {
1005e887ea33SDavid du Colombier 			diag("DYNT without a sym\n%P", p);
1006e887ea33SDavid du Colombier 			break;
1007e887ea33SDavid du Colombier 		}
1008e887ea33SDavid du Colombier 		di = p->to.sym;
1009e887ea33SDavid du Colombier 		p->from.scale = 4;
1010e887ea33SDavid du Colombier 		if(di->type == SXREF) {
1011e887ea33SDavid du Colombier 			if(debug['z'])
1012e887ea33SDavid du Colombier 				Bprint(&bso, "%P set to %d\n", p, dtype);
1013e887ea33SDavid du Colombier 			di->type = SCONST;
1014e887ea33SDavid du Colombier 			di->value = dtype;
1015e887ea33SDavid du Colombier 			dtype += 4;
1016e887ea33SDavid du Colombier 		}
1017e887ea33SDavid du Colombier 		if(p->from.sym == S)
1018e887ea33SDavid du Colombier 			break;
1019e887ea33SDavid du Colombier 
1020e887ea33SDavid du Colombier 		p->from.offset = di->value;
1021e887ea33SDavid du Colombier 		p->from.sym->type = SDATA;
1022e887ea33SDavid du Colombier 		if(curtext == P) {
1023e887ea33SDavid du Colombier 			diag("DYNT not in text: %P", p);
1024e887ea33SDavid du Colombier 			break;
1025e887ea33SDavid du Colombier 		}
1026e887ea33SDavid du Colombier 		p->to.sym = curtext->from.sym;
1027e887ea33SDavid du Colombier 		p->to.type = D_ADDR;
1028e887ea33SDavid du Colombier 		p->to.index = D_EXTERN;
1029e887ea33SDavid du Colombier 		goto data;
1030e887ea33SDavid du Colombier 
1031e887ea33SDavid du Colombier 	case AINIT:
1032e887ea33SDavid du Colombier 		if(p->from.sym == S) {
1033e887ea33SDavid du Colombier 			diag("INIT without a sym\n%P", p);
1034e887ea33SDavid du Colombier 			break;
1035e887ea33SDavid du Colombier 		}
1036e887ea33SDavid du Colombier 		if(di == S) {
1037e887ea33SDavid du Colombier 			diag("INIT without previous DYNT\n%P", p);
1038e887ea33SDavid du Colombier 			break;
1039e887ea33SDavid du Colombier 		}
1040e887ea33SDavid du Colombier 		p->from.offset = di->value;
1041e887ea33SDavid du Colombier 		p->from.sym->type = SDATA;
1042e887ea33SDavid du Colombier 		goto data;
1043e887ea33SDavid du Colombier 
1044e887ea33SDavid du Colombier 	case ADATA:
1045e887ea33SDavid du Colombier 	data:
1046e887ea33SDavid du Colombier 		if(edatap == P)
1047e887ea33SDavid du Colombier 			datap = p;
1048e887ea33SDavid du Colombier 		else
1049e887ea33SDavid du Colombier 			edatap->link = p;
1050e887ea33SDavid du Colombier 		edatap = p;
1051e887ea33SDavid du Colombier 		p->link = P;
1052e887ea33SDavid du Colombier 		goto loop;
1053e887ea33SDavid du Colombier 
1054e887ea33SDavid du Colombier 	case AGOK:
1055e887ea33SDavid du Colombier 		diag("%s: GOK opcode in %s", pn, TNAME);
1056e887ea33SDavid du Colombier 		pc++;
1057e887ea33SDavid du Colombier 		goto loop;
1058e887ea33SDavid du Colombier 
1059e887ea33SDavid du Colombier 	case ATEXT:
1060e887ea33SDavid du Colombier 		if(curtext != P) {
1061e887ea33SDavid du Colombier 			histtoauto();
1062e887ea33SDavid du Colombier 			curtext->to.autom = curauto;
1063e887ea33SDavid du Colombier 			curauto = 0;
1064e887ea33SDavid du Colombier 		}
1065e887ea33SDavid du Colombier 		skip = 0;
1066e887ea33SDavid du Colombier 		curtext = p;
1067e887ea33SDavid du Colombier 		s = p->from.sym;
1068e887ea33SDavid du Colombier 		if(s == S) {
1069e887ea33SDavid du Colombier 			diag("%s: no TEXT symbol: %P", pn, p);
1070e887ea33SDavid du Colombier 			errorexit();
1071e887ea33SDavid du Colombier 		}
1072e887ea33SDavid du Colombier 		if(s->type != 0 && s->type != SXREF) {
1073e887ea33SDavid du Colombier 			if(p->from.scale & DUPOK) {
1074e887ea33SDavid du Colombier 				skip = 1;
1075e887ea33SDavid du Colombier 				goto casdef;
1076e887ea33SDavid du Colombier 			}
1077e887ea33SDavid du Colombier 			diag("%s: redefinition: %s\n%P", pn, s->name, p);
1078e887ea33SDavid du Colombier 		}
1079e887ea33SDavid du Colombier 		s->type = STEXT;
1080e887ea33SDavid du Colombier 		s->value = pc;
1081e887ea33SDavid du Colombier 		lastp->link = p;
1082e887ea33SDavid du Colombier 		lastp = p;
1083e887ea33SDavid du Colombier 		p->pc = pc;
1084e887ea33SDavid du Colombier 		pc++;
1085e887ea33SDavid du Colombier 		if(textp == P) {
1086e887ea33SDavid du Colombier 			textp = p;
1087e887ea33SDavid du Colombier 			etextp = p;
1088e887ea33SDavid du Colombier 			goto loop;
1089e887ea33SDavid du Colombier 		}
1090e887ea33SDavid du Colombier 		etextp->pcond = p;
1091e887ea33SDavid du Colombier 		etextp = p;
1092e887ea33SDavid du Colombier 		goto loop;
1093e887ea33SDavid du Colombier 
1094e887ea33SDavid du Colombier 	case AMODE:
1095e887ea33SDavid du Colombier 		if(p->from.type == D_CONST || p->from.type == D_INDIR+D_NONE){
1096e887ea33SDavid du Colombier 			switch((int)p->from.offset){
1097e887ea33SDavid du Colombier 			case 16: case 32: case 64:
1098e887ea33SDavid du Colombier 				mode = p->from.offset;
1099e887ea33SDavid du Colombier 				break;
1100e887ea33SDavid du Colombier 			}
1101e887ea33SDavid du Colombier 		}
1102e887ea33SDavid du Colombier 		goto loop;
1103e887ea33SDavid du Colombier 
1104e887ea33SDavid du Colombier 	case AFMOVF:
1105e887ea33SDavid du Colombier 	case AFADDF:
1106e887ea33SDavid du Colombier 	case AFSUBF:
1107e887ea33SDavid du Colombier 	case AFSUBRF:
1108e887ea33SDavid du Colombier 	case AFMULF:
1109e887ea33SDavid du Colombier 	case AFDIVF:
1110e887ea33SDavid du Colombier 	case AFDIVRF:
1111e887ea33SDavid du Colombier 	case AFCOMF:
1112e887ea33SDavid du Colombier 	case AFCOMFP:
1113e887ea33SDavid du Colombier 	case AMOVSS:
1114e887ea33SDavid du Colombier 	case AADDSS:
1115e887ea33SDavid du Colombier 	case ASUBSS:
1116e887ea33SDavid du Colombier 	case AMULSS:
1117e887ea33SDavid du Colombier 	case ADIVSS:
1118e887ea33SDavid du Colombier 	case ACOMISS:
1119e887ea33SDavid du Colombier 	case AUCOMISS:
1120e887ea33SDavid du Colombier 		if(skip)
1121e887ea33SDavid du Colombier 			goto casdef;
1122e887ea33SDavid du Colombier 		if(p->from.type == D_FCONST) {
1123e887ea33SDavid du Colombier 			/* size sb 9 max */
1124e887ea33SDavid du Colombier 			sprint(literal, "$%lux", ieeedtof(&p->from.ieee));
1125e887ea33SDavid du Colombier 			s = lookup(literal, 0);
1126e887ea33SDavid du Colombier 			if(s->type == 0) {
1127e887ea33SDavid du Colombier 				s->type = SBSS;
1128e887ea33SDavid du Colombier 				s->value = 4;
1129e887ea33SDavid du Colombier 				t = prg();
1130e887ea33SDavid du Colombier 				t->as = ADATA;
1131e887ea33SDavid du Colombier 				t->line = p->line;
1132e887ea33SDavid du Colombier 				t->from.type = D_EXTERN;
1133e887ea33SDavid du Colombier 				t->from.sym = s;
1134e887ea33SDavid du Colombier 				t->from.scale = 4;
1135e887ea33SDavid du Colombier 				t->to = p->from;
1136e887ea33SDavid du Colombier 				if(edatap == P)
1137e887ea33SDavid du Colombier 					datap = t;
1138e887ea33SDavid du Colombier 				else
1139e887ea33SDavid du Colombier 					edatap->link = t;
1140e887ea33SDavid du Colombier 				edatap = t;
1141e887ea33SDavid du Colombier 				t->link = P;
1142e887ea33SDavid du Colombier 			}
1143e887ea33SDavid du Colombier 			p->from.type = D_EXTERN;
1144e887ea33SDavid du Colombier 			p->from.sym = s;
1145e887ea33SDavid du Colombier 			p->from.offset = 0;
1146e887ea33SDavid du Colombier 		}
1147e887ea33SDavid du Colombier 		goto casdef;
1148e887ea33SDavid du Colombier 
1149e887ea33SDavid du Colombier 	case AFMOVD:
1150e887ea33SDavid du Colombier 	case AFADDD:
1151e887ea33SDavid du Colombier 	case AFSUBD:
1152e887ea33SDavid du Colombier 	case AFSUBRD:
1153e887ea33SDavid du Colombier 	case AFMULD:
1154e887ea33SDavid du Colombier 	case AFDIVD:
1155e887ea33SDavid du Colombier 	case AFDIVRD:
1156e887ea33SDavid du Colombier 	case AFCOMD:
1157e887ea33SDavid du Colombier 	case AFCOMDP:
1158e887ea33SDavid du Colombier 	case AMOVSD:
1159e887ea33SDavid du Colombier 	case AADDSD:
1160e887ea33SDavid du Colombier 	case ASUBSD:
1161e887ea33SDavid du Colombier 	case AMULSD:
1162e887ea33SDavid du Colombier 	case ADIVSD:
1163e887ea33SDavid du Colombier 	case ACOMISD:
1164e887ea33SDavid du Colombier 	case AUCOMISD:
1165e887ea33SDavid du Colombier 		if(skip)
1166e887ea33SDavid du Colombier 			goto casdef;
1167e887ea33SDavid du Colombier 		if(p->from.type == D_FCONST) {
1168e887ea33SDavid du Colombier 			/* size sb 18 max */
1169e887ea33SDavid du Colombier 			sprint(literal, "$%lux.%lux",
1170e887ea33SDavid du Colombier 				p->from.ieee.l, p->from.ieee.h);
1171e887ea33SDavid du Colombier 			s = lookup(literal, 0);
1172e887ea33SDavid du Colombier 			if(s->type == 0) {
1173e887ea33SDavid du Colombier 				s->type = SBSS;
1174e887ea33SDavid du Colombier 				s->value = 8;
1175e887ea33SDavid du Colombier 				t = prg();
1176e887ea33SDavid du Colombier 				t->as = ADATA;
1177e887ea33SDavid du Colombier 				t->line = p->line;
1178e887ea33SDavid du Colombier 				t->from.type = D_EXTERN;
1179e887ea33SDavid du Colombier 				t->from.sym = s;
1180e887ea33SDavid du Colombier 				t->from.scale = 8;
1181e887ea33SDavid du Colombier 				t->to = p->from;
1182e887ea33SDavid du Colombier 				if(edatap == P)
1183e887ea33SDavid du Colombier 					datap = t;
1184e887ea33SDavid du Colombier 				else
1185e887ea33SDavid du Colombier 					edatap->link = t;
1186e887ea33SDavid du Colombier 				edatap = t;
1187e887ea33SDavid du Colombier 				t->link = P;
1188e887ea33SDavid du Colombier 			}
1189e887ea33SDavid du Colombier 			p->from.type = D_EXTERN;
1190e887ea33SDavid du Colombier 			p->from.sym = s;
1191e887ea33SDavid du Colombier 			p->from.offset = 0;
1192e887ea33SDavid du Colombier 		}
1193e887ea33SDavid du Colombier 		goto casdef;
1194e887ea33SDavid du Colombier 
1195e887ea33SDavid du Colombier 	casdef:
1196e887ea33SDavid du Colombier 	default:
1197e887ea33SDavid du Colombier 		if(skip)
1198e887ea33SDavid du Colombier 			nopout(p);
1199e887ea33SDavid du Colombier 
1200e887ea33SDavid du Colombier 		if(p->to.type == D_BRANCH)
1201e887ea33SDavid du Colombier 			p->to.offset += ipc;
1202e887ea33SDavid du Colombier 		lastp->link = p;
1203e887ea33SDavid du Colombier 		lastp = p;
1204e887ea33SDavid du Colombier 		p->pc = pc;
1205e887ea33SDavid du Colombier 		pc++;
1206e887ea33SDavid du Colombier 		goto loop;
1207e887ea33SDavid du Colombier 	}
1208e887ea33SDavid du Colombier 	goto loop;
1209e887ea33SDavid du Colombier 
1210e887ea33SDavid du Colombier eof:
1211e887ea33SDavid du Colombier 	diag("truncated object file: %s", pn);
1212e887ea33SDavid du Colombier }
1213e887ea33SDavid du Colombier 
1214e887ea33SDavid du Colombier Sym*
lookup(char * symb,int v)1215e887ea33SDavid du Colombier lookup(char *symb, int v)
1216e887ea33SDavid du Colombier {
1217e887ea33SDavid du Colombier 	Sym *s;
1218e887ea33SDavid du Colombier 	char *p;
1219e887ea33SDavid du Colombier 	long h;
1220e887ea33SDavid du Colombier 	int l, c;
1221e887ea33SDavid du Colombier 
1222e887ea33SDavid du Colombier 	h = v;
1223e887ea33SDavid du Colombier 	for(p=symb; c = *p; p++)
1224e887ea33SDavid du Colombier 		h = h+h+h + c;
1225e887ea33SDavid du Colombier 	l = (p - symb) + 1;
1226b87cd620SDavid du Colombier 	h &= 0xffffff;
1227e887ea33SDavid du Colombier 	h %= NHASH;
1228e887ea33SDavid du Colombier 	for(s = hash[h]; s != S; s = s->link)
1229e887ea33SDavid du Colombier 		if(s->version == v)
1230e887ea33SDavid du Colombier 		if(memcmp(s->name, symb, l) == 0)
1231e887ea33SDavid du Colombier 			return s;
1232e887ea33SDavid du Colombier 
1233e887ea33SDavid du Colombier 	while(nhunk < sizeof(Sym))
1234e887ea33SDavid du Colombier 		gethunk();
1235e887ea33SDavid du Colombier 	s = (Sym*)hunk;
1236e887ea33SDavid du Colombier 	nhunk -= sizeof(Sym);
1237e887ea33SDavid du Colombier 	hunk += sizeof(Sym);
1238e887ea33SDavid du Colombier 
1239e887ea33SDavid du Colombier 	s->name = malloc(l + 1);
1240e887ea33SDavid du Colombier 	memmove(s->name, symb, l);
1241e887ea33SDavid du Colombier 
1242e887ea33SDavid du Colombier 	s->link = hash[h];
1243e887ea33SDavid du Colombier 	s->type = 0;
1244e887ea33SDavid du Colombier 	s->version = v;
1245e887ea33SDavid du Colombier 	s->value = 0;
1246e887ea33SDavid du Colombier 	s->sig = 0;
1247e887ea33SDavid du Colombier 	hash[h] = s;
1248e887ea33SDavid du Colombier 	nsymbol++;
1249e887ea33SDavid du Colombier 	return s;
1250e887ea33SDavid du Colombier }
1251e887ea33SDavid du Colombier 
1252e887ea33SDavid du Colombier Prog*
prg(void)1253e887ea33SDavid du Colombier prg(void)
1254e887ea33SDavid du Colombier {
1255e887ea33SDavid du Colombier 	Prog *p;
1256e887ea33SDavid du Colombier 
1257e887ea33SDavid du Colombier 	while(nhunk < sizeof(Prog))
1258e887ea33SDavid du Colombier 		gethunk();
1259e887ea33SDavid du Colombier 	p = (Prog*)hunk;
1260e887ea33SDavid du Colombier 	nhunk -= sizeof(Prog);
1261e887ea33SDavid du Colombier 	hunk += sizeof(Prog);
1262e887ea33SDavid du Colombier 
1263e887ea33SDavid du Colombier 	*p = zprg;
1264e887ea33SDavid du Colombier 	return p;
1265e887ea33SDavid du Colombier }
1266e887ea33SDavid du Colombier 
1267e887ea33SDavid du Colombier Prog*
copyp(Prog * q)1268e887ea33SDavid du Colombier copyp(Prog *q)
1269e887ea33SDavid du Colombier {
1270e887ea33SDavid du Colombier 	Prog *p;
1271e887ea33SDavid du Colombier 
1272e887ea33SDavid du Colombier 	p = prg();
1273e887ea33SDavid du Colombier 	*p = *q;
1274e887ea33SDavid du Colombier 	return p;
1275e887ea33SDavid du Colombier }
1276e887ea33SDavid du Colombier 
1277e887ea33SDavid du Colombier Prog*
appendp(Prog * q)1278e887ea33SDavid du Colombier appendp(Prog *q)
1279e887ea33SDavid du Colombier {
1280e887ea33SDavid du Colombier 	Prog *p;
1281e887ea33SDavid du Colombier 
1282e887ea33SDavid du Colombier 	p = prg();
1283e887ea33SDavid du Colombier 	p->link = q->link;
1284e887ea33SDavid du Colombier 	q->link = p;
1285e887ea33SDavid du Colombier 	p->line = q->line;
1286e887ea33SDavid du Colombier 	p->mode = q->mode;
1287e887ea33SDavid du Colombier 	return p;
1288e887ea33SDavid du Colombier }
1289e887ea33SDavid du Colombier 
1290e887ea33SDavid du Colombier void
gethunk(void)1291e887ea33SDavid du Colombier gethunk(void)
1292e887ea33SDavid du Colombier {
1293e887ea33SDavid du Colombier 	char *h;
1294e887ea33SDavid du Colombier 	long nh;
1295e887ea33SDavid du Colombier 
1296e887ea33SDavid du Colombier 	nh = NHUNK;
1297e887ea33SDavid du Colombier 	if(thunk >= 5L*NHUNK) {
1298e887ea33SDavid du Colombier 		nh = 5L*NHUNK;
1299e887ea33SDavid du Colombier 		if(thunk >= 25L*NHUNK)
1300e887ea33SDavid du Colombier 			nh = 25L*NHUNK;
1301e887ea33SDavid du Colombier 	}
1302e887ea33SDavid du Colombier 	h = mysbrk(nh);
1303e887ea33SDavid du Colombier 	if(h == (char*)-1) {
1304e887ea33SDavid du Colombier 		diag("out of memory");
1305e887ea33SDavid du Colombier 		errorexit();
1306e887ea33SDavid du Colombier 	}
1307e887ea33SDavid du Colombier 	hunk = h;
1308e887ea33SDavid du Colombier 	nhunk = nh;
1309e887ea33SDavid du Colombier 	thunk += nh;
1310e887ea33SDavid du Colombier }
1311e887ea33SDavid du Colombier 
1312e887ea33SDavid du Colombier void
doprof1(void)1313e887ea33SDavid du Colombier doprof1(void)
1314e887ea33SDavid du Colombier {
1315e887ea33SDavid du Colombier 	Sym *s;
1316e887ea33SDavid du Colombier 	long n;
1317e887ea33SDavid du Colombier 	Prog *p, *q;
1318e887ea33SDavid du Colombier 
1319e887ea33SDavid du Colombier 	if(debug['v'])
1320e887ea33SDavid du Colombier 		Bprint(&bso, "%5.2f profile 1\n", cputime());
1321e887ea33SDavid du Colombier 	Bflush(&bso);
1322e887ea33SDavid du Colombier 	s = lookup("__mcount", 0);
1323e887ea33SDavid du Colombier 	n = 1;
1324e887ea33SDavid du Colombier 	for(p = firstp->link; p != P; p = p->link) {
1325e887ea33SDavid du Colombier 		if(p->as == ATEXT) {
1326e887ea33SDavid du Colombier 			q = prg();
1327e887ea33SDavid du Colombier 			q->line = p->line;
1328e887ea33SDavid du Colombier 			q->link = datap;
1329e887ea33SDavid du Colombier 			datap = q;
1330e887ea33SDavid du Colombier 			q->as = ADATA;
1331e887ea33SDavid du Colombier 			q->from.type = D_EXTERN;
1332e887ea33SDavid du Colombier 			q->from.offset = n*4;
1333e887ea33SDavid du Colombier 			q->from.sym = s;
1334e887ea33SDavid du Colombier 			q->from.scale = 4;
1335e887ea33SDavid du Colombier 			q->to = p->from;
1336e887ea33SDavid du Colombier 			q->to.type = D_CONST;
1337e887ea33SDavid du Colombier 
1338e887ea33SDavid du Colombier 			q = prg();
1339e887ea33SDavid du Colombier 			q->line = p->line;
1340e887ea33SDavid du Colombier 			q->pc = p->pc;
1341e887ea33SDavid du Colombier 			q->link = p->link;
1342e887ea33SDavid du Colombier 			p->link = q;
1343e887ea33SDavid du Colombier 			p = q;
1344e887ea33SDavid du Colombier 			p->as = AADDL;
1345e887ea33SDavid du Colombier 			p->from.type = D_CONST;
1346e887ea33SDavid du Colombier 			p->from.offset = 1;
1347e887ea33SDavid du Colombier 			p->to.type = D_EXTERN;
1348e887ea33SDavid du Colombier 			p->to.sym = s;
1349e887ea33SDavid du Colombier 			p->to.offset = n*4 + 4;
1350e887ea33SDavid du Colombier 
1351e887ea33SDavid du Colombier 			n += 2;
1352e887ea33SDavid du Colombier 			continue;
1353e887ea33SDavid du Colombier 		}
1354e887ea33SDavid du Colombier 	}
1355e887ea33SDavid du Colombier 	q = prg();
1356e887ea33SDavid du Colombier 	q->line = 0;
1357e887ea33SDavid du Colombier 	q->link = datap;
1358e887ea33SDavid du Colombier 	datap = q;
1359e887ea33SDavid du Colombier 
1360e887ea33SDavid du Colombier 	q->as = ADATA;
1361e887ea33SDavid du Colombier 	q->from.type = D_EXTERN;
1362e887ea33SDavid du Colombier 	q->from.sym = s;
1363e887ea33SDavid du Colombier 	q->from.scale = 4;
1364e887ea33SDavid du Colombier 	q->to.type = D_CONST;
1365e887ea33SDavid du Colombier 	q->to.offset = n;
1366e887ea33SDavid du Colombier 
1367e887ea33SDavid du Colombier 	s->type = SBSS;
1368e887ea33SDavid du Colombier 	s->value = n*4;
1369e887ea33SDavid du Colombier }
1370e887ea33SDavid du Colombier 
1371e887ea33SDavid du Colombier void
doprof2(void)1372e887ea33SDavid du Colombier doprof2(void)
1373e887ea33SDavid du Colombier {
1374e887ea33SDavid du Colombier 	Sym *s2, *s4;
1375e887ea33SDavid du Colombier 	Prog *p, *q, *q2, *ps2, *ps4;
1376e887ea33SDavid du Colombier 
1377e887ea33SDavid du Colombier 	if(debug['v'])
1378e887ea33SDavid du Colombier 		Bprint(&bso, "%5.2f profile 2\n", cputime());
1379e887ea33SDavid du Colombier 	Bflush(&bso);
1380e887ea33SDavid du Colombier 
1381e887ea33SDavid du Colombier 	if(debug['e']){
1382e887ea33SDavid du Colombier 		s2 = lookup("_tracein", 0);
1383e887ea33SDavid du Colombier 		s4 = lookup("_traceout", 0);
1384e887ea33SDavid du Colombier 	}else{
1385e887ea33SDavid du Colombier 		s2 = lookup("_profin", 0);
1386e887ea33SDavid du Colombier 		s4 = lookup("_profout", 0);
1387e887ea33SDavid du Colombier 	}
1388e887ea33SDavid du Colombier 	if(s2->type != STEXT || s4->type != STEXT) {
1389e887ea33SDavid du Colombier 		if(debug['e'])
1390e887ea33SDavid du Colombier 			diag("_tracein/_traceout not defined %d %d", s2->type, s4->type);
1391e887ea33SDavid du Colombier 		else
1392e887ea33SDavid du Colombier 			diag("_profin/_profout not defined");
1393e887ea33SDavid du Colombier 		return;
1394e887ea33SDavid du Colombier 	}
1395e887ea33SDavid du Colombier 
1396e887ea33SDavid du Colombier 	ps2 = P;
1397e887ea33SDavid du Colombier 	ps4 = P;
1398e887ea33SDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
1399e887ea33SDavid du Colombier 		if(p->as == ATEXT) {
1400e887ea33SDavid du Colombier 			if(p->from.sym == s2) {
1401e887ea33SDavid du Colombier 				p->from.scale = 1;
1402e887ea33SDavid du Colombier 				ps2 = p;
1403e887ea33SDavid du Colombier 			}
1404e887ea33SDavid du Colombier 			if(p->from.sym == s4) {
1405e887ea33SDavid du Colombier 				p->from.scale = 1;
1406e887ea33SDavid du Colombier 				ps4 = p;
1407e887ea33SDavid du Colombier 			}
1408e887ea33SDavid du Colombier 		}
1409e887ea33SDavid du Colombier 	}
1410e887ea33SDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
1411e887ea33SDavid du Colombier 		if(p->as == ATEXT) {
1412e887ea33SDavid du Colombier 			curtext = p;
1413e887ea33SDavid du Colombier 
1414e887ea33SDavid du Colombier 			if(p->from.scale & NOPROF) {	/* dont profile */
1415e887ea33SDavid du Colombier 				for(;;) {
1416e887ea33SDavid du Colombier 					q = p->link;
1417e887ea33SDavid du Colombier 					if(q == P)
1418e887ea33SDavid du Colombier 						break;
1419e887ea33SDavid du Colombier 					if(q->as == ATEXT)
1420e887ea33SDavid du Colombier 						break;
1421e887ea33SDavid du Colombier 					p = q;
1422e887ea33SDavid du Colombier 				}
1423e887ea33SDavid du Colombier 				continue;
1424e887ea33SDavid du Colombier 			}
1425e887ea33SDavid du Colombier 
1426e887ea33SDavid du Colombier 			/*
1427e887ea33SDavid du Colombier 			 * JMPL	profin
1428e887ea33SDavid du Colombier 			 */
1429e887ea33SDavid du Colombier 			q = prg();
1430e887ea33SDavid du Colombier 			q->line = p->line;
1431e887ea33SDavid du Colombier 			q->pc = p->pc;
1432e887ea33SDavid du Colombier 			q->link = p->link;
1433e887ea33SDavid du Colombier 			if(debug['e']){		/* embedded tracing */
1434e887ea33SDavid du Colombier 				q2 = prg();
1435e887ea33SDavid du Colombier 				p->link = q2;
1436e887ea33SDavid du Colombier 				q2->link = q;
1437e887ea33SDavid du Colombier 
1438e887ea33SDavid du Colombier 				q2->line = p->line;
1439e887ea33SDavid du Colombier 				q2->pc = p->pc;
1440e887ea33SDavid du Colombier 
1441e887ea33SDavid du Colombier 				q2->as = AJMP;
1442e887ea33SDavid du Colombier 				q2->to.type = D_BRANCH;
1443e887ea33SDavid du Colombier 				q2->to.sym = p->to.sym;
1444e887ea33SDavid du Colombier 				q2->pcond = q->link;
1445e887ea33SDavid du Colombier 			}else
1446e887ea33SDavid du Colombier 				p->link = q;
1447e887ea33SDavid du Colombier 			p = q;
1448e887ea33SDavid du Colombier 			p->as = ACALL;
1449e887ea33SDavid du Colombier 			p->to.type = D_BRANCH;
1450e887ea33SDavid du Colombier 			p->pcond = ps2;
1451e887ea33SDavid du Colombier 			p->to.sym = s2;
1452e887ea33SDavid du Colombier 
1453e887ea33SDavid du Colombier 			continue;
1454e887ea33SDavid du Colombier 		}
1455e887ea33SDavid du Colombier 		if(p->as == ARET) {
1456e887ea33SDavid du Colombier 			/*
1457e887ea33SDavid du Colombier 			 * RET (default)
1458e887ea33SDavid du Colombier 			 */
1459e887ea33SDavid du Colombier 			if(debug['e']){		/* embedded tracing */
1460e887ea33SDavid du Colombier 				q = prg();
1461e887ea33SDavid du Colombier 				q->line = p->line;
1462e887ea33SDavid du Colombier 				q->pc = p->pc;
1463e887ea33SDavid du Colombier 				q->link = p->link;
1464e887ea33SDavid du Colombier 				p->link = q;
1465e887ea33SDavid du Colombier 				p = q;
1466e887ea33SDavid du Colombier 			}
1467e887ea33SDavid du Colombier 			/*
1468e887ea33SDavid du Colombier 			 * RET
1469e887ea33SDavid du Colombier 			 */
1470e887ea33SDavid du Colombier 			q = prg();
1471e887ea33SDavid du Colombier 			q->as = ARET;
1472e887ea33SDavid du Colombier 			q->from = p->from;
1473e887ea33SDavid du Colombier 			q->to = p->to;
1474e887ea33SDavid du Colombier 			q->link = p->link;
1475e887ea33SDavid du Colombier 			p->link = q;
1476e887ea33SDavid du Colombier 
1477e887ea33SDavid du Colombier 			/*
1478e887ea33SDavid du Colombier 			 * JAL	profout
1479e887ea33SDavid du Colombier 			 */
1480e887ea33SDavid du Colombier 			p->as = ACALL;
1481e887ea33SDavid du Colombier 			p->from = zprg.from;
1482e887ea33SDavid du Colombier 			p->to = zprg.to;
1483e887ea33SDavid du Colombier 			p->to.type = D_BRANCH;
1484e887ea33SDavid du Colombier 			p->pcond = ps4;
1485e887ea33SDavid du Colombier 			p->to.sym = s4;
1486e887ea33SDavid du Colombier 
1487e887ea33SDavid du Colombier 			p = q;
1488e887ea33SDavid du Colombier 
1489e887ea33SDavid du Colombier 			continue;
1490e887ea33SDavid du Colombier 		}
1491e887ea33SDavid du Colombier 	}
1492e887ea33SDavid du Colombier }
1493e887ea33SDavid du Colombier 
1494e887ea33SDavid du Colombier void
nuxiinit(void)1495e887ea33SDavid du Colombier nuxiinit(void)
1496e887ea33SDavid du Colombier {
1497e887ea33SDavid du Colombier 	int i, c;
1498e887ea33SDavid du Colombier 
1499e887ea33SDavid du Colombier 	for(i=0; i<4; i++) {
1500e887ea33SDavid du Colombier 		c = find1(0x04030201L, i+1);
1501e887ea33SDavid du Colombier 		if(i < 2)
1502e887ea33SDavid du Colombier 			inuxi2[i] = c;
1503e887ea33SDavid du Colombier 		if(i < 1)
1504e887ea33SDavid du Colombier 			inuxi1[i] = c;
1505e887ea33SDavid du Colombier 		inuxi4[i] = c;
1506e887ea33SDavid du Colombier 		inuxi8[i] = c;
1507e887ea33SDavid du Colombier 		inuxi8[i+4] = c+4;
1508e887ea33SDavid du Colombier 		fnuxi4[i] = c;
1509e887ea33SDavid du Colombier 		fnuxi8[i] = c;
1510e887ea33SDavid du Colombier 		fnuxi8[i+4] = c+4;
1511e887ea33SDavid du Colombier 	}
1512e887ea33SDavid du Colombier 	if(debug['v']) {
1513e887ea33SDavid du Colombier 		Bprint(&bso, "inuxi = ");
1514e887ea33SDavid du Colombier 		for(i=0; i<1; i++)
1515e887ea33SDavid du Colombier 			Bprint(&bso, "%d", inuxi1[i]);
1516e887ea33SDavid du Colombier 		Bprint(&bso, " ");
1517e887ea33SDavid du Colombier 		for(i=0; i<2; i++)
1518e887ea33SDavid du Colombier 			Bprint(&bso, "%d", inuxi2[i]);
1519e887ea33SDavid du Colombier 		Bprint(&bso, " ");
1520e887ea33SDavid du Colombier 		for(i=0; i<4; i++)
1521e887ea33SDavid du Colombier 			Bprint(&bso, "%d", inuxi4[i]);
1522e887ea33SDavid du Colombier 		Bprint(&bso, " ");
1523e887ea33SDavid du Colombier 		for(i=0; i<8; i++)
1524e887ea33SDavid du Colombier 			Bprint(&bso, "%d", inuxi8[i]);
1525e887ea33SDavid du Colombier 		Bprint(&bso, "\nfnuxi = ");
1526e887ea33SDavid du Colombier 		for(i=0; i<4; i++)
1527e887ea33SDavid du Colombier 			Bprint(&bso, "%d", fnuxi4[i]);
1528e887ea33SDavid du Colombier 		Bprint(&bso, " ");
1529e887ea33SDavid du Colombier 		for(i=0; i<8; i++)
1530e887ea33SDavid du Colombier 			Bprint(&bso, "%d", fnuxi8[i]);
1531e887ea33SDavid du Colombier 		Bprint(&bso, "\n");
1532e887ea33SDavid du Colombier 	}
1533e887ea33SDavid du Colombier 	Bflush(&bso);
1534e887ea33SDavid du Colombier }
1535e887ea33SDavid du Colombier 
1536e887ea33SDavid du Colombier int
find1(long l,int c)1537e887ea33SDavid du Colombier find1(long l, int c)
1538e887ea33SDavid du Colombier {
1539e887ea33SDavid du Colombier 	char *p;
1540e887ea33SDavid du Colombier 	int i;
1541e887ea33SDavid du Colombier 
1542e887ea33SDavid du Colombier 	p = (char*)&l;
1543e887ea33SDavid du Colombier 	for(i=0; i<4; i++)
1544e887ea33SDavid du Colombier 		if(*p++ == c)
1545e887ea33SDavid du Colombier 			return i;
1546e887ea33SDavid du Colombier 	return 0;
1547e887ea33SDavid du Colombier }
1548e887ea33SDavid du Colombier 
1549e887ea33SDavid du Colombier int
find2(long l,int c)1550e887ea33SDavid du Colombier find2(long l, int c)
1551e887ea33SDavid du Colombier {
1552e887ea33SDavid du Colombier 	short *p;
1553e887ea33SDavid du Colombier 	int i;
1554e887ea33SDavid du Colombier 
1555e887ea33SDavid du Colombier 	p = (short*)&l;
1556e887ea33SDavid du Colombier 	for(i=0; i<4; i+=2) {
1557e887ea33SDavid du Colombier 		if(((*p >> 8) & 0xff) == c)
1558e887ea33SDavid du Colombier 			return i;
1559e887ea33SDavid du Colombier 		if((*p++ & 0xff) == c)
1560e887ea33SDavid du Colombier 			return i+1;
1561e887ea33SDavid du Colombier 	}
1562e887ea33SDavid du Colombier 	return 0;
1563e887ea33SDavid du Colombier }
1564e887ea33SDavid du Colombier 
1565e887ea33SDavid du Colombier long
ieeedtof(Ieee * e)1566e887ea33SDavid du Colombier ieeedtof(Ieee *e)
1567e887ea33SDavid du Colombier {
1568e887ea33SDavid du Colombier 	int exp;
1569e887ea33SDavid du Colombier 	long v;
1570e887ea33SDavid du Colombier 
1571e887ea33SDavid du Colombier 	if(e->h == 0)
1572e887ea33SDavid du Colombier 		return 0;
1573e887ea33SDavid du Colombier 	exp = (e->h>>20) & ((1L<<11)-1L);
1574e887ea33SDavid du Colombier 	exp -= (1L<<10) - 2L;
1575e887ea33SDavid du Colombier 	v = (e->h & 0xfffffL) << 3;
1576e887ea33SDavid du Colombier 	v |= (e->l >> 29) & 0x7L;
1577e887ea33SDavid du Colombier 	if((e->l >> 28) & 1) {
1578e887ea33SDavid du Colombier 		v++;
1579e887ea33SDavid du Colombier 		if(v & 0x800000L) {
1580e887ea33SDavid du Colombier 			v = (v & 0x7fffffL) >> 1;
1581e887ea33SDavid du Colombier 			exp++;
1582e887ea33SDavid du Colombier 		}
1583e887ea33SDavid du Colombier 	}
1584e887ea33SDavid du Colombier 	if(exp <= -126 || exp >= 130)
1585e887ea33SDavid du Colombier 		diag("double fp to single fp overflow");
1586e887ea33SDavid du Colombier 	v |= ((exp + 126) & 0xffL) << 23;
1587e887ea33SDavid du Colombier 	v |= e->h & 0x80000000L;
1588e887ea33SDavid du Colombier 	return v;
1589e887ea33SDavid du Colombier }
1590e887ea33SDavid du Colombier 
1591e887ea33SDavid du Colombier double
ieeedtod(Ieee * ieeep)1592e887ea33SDavid du Colombier ieeedtod(Ieee *ieeep)
1593e887ea33SDavid du Colombier {
1594e887ea33SDavid du Colombier 	Ieee e;
1595e887ea33SDavid du Colombier 	double fr;
1596e887ea33SDavid du Colombier 	int exp;
1597e887ea33SDavid du Colombier 
1598e887ea33SDavid du Colombier 	if(ieeep->h & (1L<<31)) {
1599e887ea33SDavid du Colombier 		e.h = ieeep->h & ~(1L<<31);
1600e887ea33SDavid du Colombier 		e.l = ieeep->l;
1601e887ea33SDavid du Colombier 		return -ieeedtod(&e);
1602e887ea33SDavid du Colombier 	}
1603e887ea33SDavid du Colombier 	if(ieeep->l == 0 && ieeep->h == 0)
1604e887ea33SDavid du Colombier 		return 0;
1605e887ea33SDavid du Colombier 	fr = ieeep->l & ((1L<<16)-1L);
1606e887ea33SDavid du Colombier 	fr /= 1L<<16;
1607e887ea33SDavid du Colombier 	fr += (ieeep->l>>16) & ((1L<<16)-1L);
1608e887ea33SDavid du Colombier 	fr /= 1L<<16;
1609e887ea33SDavid du Colombier 	fr += (ieeep->h & (1L<<20)-1L) | (1L<<20);
1610e887ea33SDavid du Colombier 	fr /= 1L<<21;
1611e887ea33SDavid du Colombier 	exp = (ieeep->h>>20) & ((1L<<11)-1L);
1612e887ea33SDavid du Colombier 	exp -= (1L<<10) - 2L;
1613e887ea33SDavid du Colombier 	return ldexp(fr, exp);
1614e887ea33SDavid du Colombier }
1615e887ea33SDavid du Colombier 
1616e887ea33SDavid du Colombier void
undefsym(Sym * s)1617e887ea33SDavid du Colombier undefsym(Sym *s)
1618e887ea33SDavid du Colombier {
1619e887ea33SDavid du Colombier 	int n;
1620e887ea33SDavid du Colombier 
1621e887ea33SDavid du Colombier 	n = imports;
1622e887ea33SDavid du Colombier 	if(s->value != 0)
1623e887ea33SDavid du Colombier 		diag("value != 0 on SXREF");
1624e887ea33SDavid du Colombier 	if(n >= 1<<Rindex)
1625e887ea33SDavid du Colombier 		diag("import index %d out of range", n);
1626e887ea33SDavid du Colombier 	s->value = n<<Roffset;
1627e887ea33SDavid du Colombier 	s->type = SUNDEF;
1628e887ea33SDavid du Colombier 	imports++;
1629e887ea33SDavid du Colombier }
1630e887ea33SDavid du Colombier 
1631e887ea33SDavid du Colombier void
zerosig(char * sp)1632e887ea33SDavid du Colombier zerosig(char *sp)
1633e887ea33SDavid du Colombier {
1634e887ea33SDavid du Colombier 	Sym *s;
1635e887ea33SDavid du Colombier 
1636e887ea33SDavid du Colombier 	s = lookup(sp, 0);
1637e887ea33SDavid du Colombier 	s->sig = 0;
1638e887ea33SDavid du Colombier }
1639e887ea33SDavid du Colombier 
1640e887ea33SDavid du Colombier void
readundefs(char * f,int t)1641e887ea33SDavid du Colombier readundefs(char *f, int t)
1642e887ea33SDavid du Colombier {
1643e887ea33SDavid du Colombier 	int i, n;
1644e887ea33SDavid du Colombier 	Sym *s;
1645e887ea33SDavid du Colombier 	Biobuf *b;
1646e887ea33SDavid du Colombier 	char *l, buf[256], *fields[64];
1647e887ea33SDavid du Colombier 
1648e887ea33SDavid du Colombier 	if(f == nil)
1649e887ea33SDavid du Colombier 		return;
1650e887ea33SDavid du Colombier 	b = Bopen(f, OREAD);
1651e887ea33SDavid du Colombier 	if(b == nil){
1652e887ea33SDavid du Colombier 		diag("could not open %s: %r", f);
1653e887ea33SDavid du Colombier 		errorexit();
1654e887ea33SDavid du Colombier 	}
1655e887ea33SDavid du Colombier 	while((l = Brdline(b, '\n')) != nil){
1656e887ea33SDavid du Colombier 		n = Blinelen(b);
1657e887ea33SDavid du Colombier 		if(n >= sizeof(buf)){
1658e887ea33SDavid du Colombier 			diag("%s: line too long", f);
1659e887ea33SDavid du Colombier 			errorexit();
1660e887ea33SDavid du Colombier 		}
1661e887ea33SDavid du Colombier 		memmove(buf, l, n);
1662e887ea33SDavid du Colombier 		buf[n-1] = '\0';
1663e887ea33SDavid du Colombier 		n = getfields(buf, fields, nelem(fields), 1, " \t\r\n");
1664e887ea33SDavid du Colombier 		if(n == nelem(fields)){
1665e887ea33SDavid du Colombier 			diag("%s: bad format", f);
1666e887ea33SDavid du Colombier 			errorexit();
1667e887ea33SDavid du Colombier 		}
1668e887ea33SDavid du Colombier 		for(i = 0; i < n; i++){
1669e887ea33SDavid du Colombier 			s = lookup(fields[i], 0);
1670e887ea33SDavid du Colombier 			s->type = SXREF;
1671e887ea33SDavid du Colombier 			s->subtype = t;
1672e887ea33SDavid du Colombier 			if(t == SIMPORT)
1673e887ea33SDavid du Colombier 				nimports++;
1674e887ea33SDavid du Colombier 			else
1675e887ea33SDavid du Colombier 				nexports++;
1676e887ea33SDavid du Colombier 		}
1677e887ea33SDavid du Colombier 	}
1678e887ea33SDavid du Colombier 	Bterm(b);
1679e887ea33SDavid du Colombier }
1680