Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

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