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		= 'k';
12
char	*thestring 	= "sparc";
13
 
14
char**	libdir;
15
int	nlibdir	= 0;
16
static	int	maxlibdir = 0;
17
 
18
/*
19
 *	-H0 -T0x200000 -R0		is boot
20
 *	-H2 -T4128 -R4096		is plan9 format
21
 *	-H3 -T0xE0004000 -R4		is javastation boot format
22
 */
23
 
24
void
25
usage(void)
26
{
27
	diag("usage: %s [-options] objects", argv0);
28
	errorexit();
29
}
30
 
31
void
32
main(int argc, char *argv[])
33
{
34
	int c;
35
	char *a;
36
	char name[LIBNAMELEN];
37
 
38
	Binit(&bso, 1, OWRITE);
39
	cout = -1;
40
	listinit();
41
	outfile = 0;
42
	nerrors = 0;
43
	curtext = P;
44
	HEADTYPE = -1;
45
	INITTEXT = -1;
46
	INITDAT = -1;
47
	INITRND = -1;
48
	INITENTRY = 0;
49
 
50
	ARGBEGIN {
51
	default:
52
		c = ARGC();
53
		if(c >= 0 && c < sizeof(debug))
54
			debug[c]++;
55
		break;
56
	case 'o':
57
		outfile = ARGF();
58
		break;
59
	case 'E':
60
		a = ARGF();
61
		if(a)
62
			INITENTRY = a;
63
		break;
64
	case 'T':
65
		a = ARGF();
66
		if(a)
67
			INITTEXT = atolwhex(a);
68
		break;
69
	case 'D':
70
		a = ARGF();
71
		if(a)
72
			INITDAT = atolwhex(a);
73
		break;
74
	case 'R':
75
		a = ARGF();
76
		if(a)
77
			INITRND = atolwhex(a);
78
		break;
79
	case 'H':
80
		a = ARGF();
81
		if(a)
82
			HEADTYPE = atolwhex(a);
83
		break;
84
	case 'L':
85
		addlibpath(EARGF(usage()));
86
		break;
87
	} ARGEND
88
	USED(argc);
89
	if(*argv == 0)
90
		usage();
91
	if(!debug['9'] && !debug['U'] && !debug['B'])
92
		debug[DEFAULT] = 1;
93
	a = getenv("ccroot");
94
	if(a != nil && *a != '\0') {
95
		if(!fileexists(a)) {
96
			diag("nonexistent $ccroot: %s", a);
97
			errorexit();
98
		}
99
	}else
100
		a = "";
101
	snprint(name, sizeof(name), "%s/%s/lib", a, thestring);
102
	addlibpath(name);
103
	if(HEADTYPE == -1) {
104
		if(debug['U'])
105
			HEADTYPE = 0;
106
		if(debug['B'])
107
			HEADTYPE = 1;
108
		if(debug['9'])
109
			HEADTYPE = 2;
110
	}
111
	switch(HEADTYPE) {
112
	default:
113
		diag("unknown -H option");
114
		errorexit();
115
 
116
	case 0:	/* boot */
117
		HEADR = 32L;
118
		if(INITTEXT == -1)
119
			INITTEXT = 0x200000L;
120
		if(INITDAT == -1)
121
			INITDAT = 0;
122
		if(INITRND == -1)
123
			INITRND = 4096L;
124
		break;
125
	case 1:	/* garbage */
126
		HEADR = 20L+60L;
127
		if(INITTEXT == -1)
128
			INITTEXT = 0x80020000L;
129
		if(INITDAT == -1)
130
			INITDAT = 0;
131
		if(INITRND == -1)
132
			INITRND = 4;
133
		break;
134
	case 2:	/* plan 9 */
135
		HEADR = 32L;
136
		if(INITTEXT == -1)
137
			INITTEXT = 4128;
138
		if(INITDAT == -1)
139
			INITDAT = 0;
140
		if(INITRND == -1)
141
			INITRND = 4096;
142
		break;
143
	case 3:	/* javastation boot */
144
		HEADR = 32L;
145
		if(INITTEXT == -1)
146
			INITTEXT = 0xE0004020L;
147
		if(INITDAT == -1)
148
			INITDAT = 0;
149
		if(INITRND == -1)
150
			INITRND = 4;
151
		break;
152
	}
153
	if(INITDAT != 0 && INITRND != 0)
154
		print("warning: -D0x%lux is ignored because of -R0x%lux\n",
155
			INITDAT, INITRND);
156
	if(debug['v'])
157
		Bprint(&bso, "HEADER = -H0x%d -T0x%lux -D0x%lux -R0x%lux\n",
158
			HEADTYPE, INITTEXT, INITDAT, INITRND);
159
	Bflush(&bso);
160
	zprg.as = AGOK;
161
	zprg.reg = NREG;
162
	zprg.from.name = D_NONE;
163
	zprg.from.type = D_NONE;
164
	zprg.from.reg = NREG;
165
	zprg.to = zprg.from;
166
	buildop();
167
	histgen = 0;
168
	textp = P;
169
	datap = P;
170
	pc = 0;
171
	dtype = 4;
172
	if(outfile == 0)
173
		outfile = "k.out";
174
	cout = create(outfile, 1, 0775);
175
	if(cout < 0) {
176
		diag("cannot create %s: %r", outfile);
177
		errorexit();
178
	}
179
	nuxiinit();
180
	version = 0;
181
	cbp = buf.cbuf;
182
	cbc = sizeof(buf.cbuf);
183
	firstp = prg();
184
	lastp = firstp;
185
 
186
	if(INITENTRY == 0) {
187
		INITENTRY = "_main";
188
		if(debug['p'])
189
			INITENTRY = "_mainp";
190
		if(!debug['l'])
191
			lookup(INITENTRY, 0)->type = SXREF;
192
	} else if(!(*INITENTRY >= '0' && *INITENTRY <= '9'))
193
		lookup(INITENTRY, 0)->type = SXREF;
194
 
195
	while(*argv)
196
		objfile(*argv++);
197
	if(!debug['l'])
198
		loadlib();
199
	firstp = firstp->link;
200
	if(firstp == P)
201
		goto out;
202
	patch();
203
	if(debug['p'])
204
		if(debug['1'])
205
			doprof1();
206
		else
207
			doprof2();
208
	dodata();
209
	follow();
210
	if(firstp == P)
211
		goto out;
212
	noops();
213
	span();
214
	asmb();
215
	undef();
216
 
217
out:
218
	if(debug['v']) {
219
		Bprint(&bso, "%5.2f cpu time\n", cputime());
220
		Bprint(&bso, "%ld memory used\n", tothunk);
221
		Bprint(&bso, "%d sizeof adr\n", sizeof(Adr));
222
		Bprint(&bso, "%d sizeof prog\n", sizeof(Prog));
223
	}
224
	errorexit();
225
}
226
 
227
void
228
addlibpath(char *arg)
229
{
230
	char **p;
231
 
232
	if(nlibdir >= maxlibdir) {
233
		if(maxlibdir == 0)
234
			maxlibdir = 8;
235
		else
236
			maxlibdir *= 2;
237
		p = malloc(maxlibdir*sizeof(*p));
238
		if(p == nil) {
239
			diag("out of memory");
240
			errorexit();
241
		}
242
		memmove(p, libdir, nlibdir*sizeof(*p));
243
		free(libdir);
244
		libdir = p;
245
	}
246
	libdir[nlibdir++] = strdup(arg);
247
}
248
 
249
char*
250
findlib(char *file)
251
{
252
	int i;
253
	char name[LIBNAMELEN];
254
 
255
	for(i = 0; i < nlibdir; i++) {
256
		snprint(name, sizeof(name), "%s/%s", libdir[i], file);
257
		if(fileexists(name))
258
			return libdir[i];
259
	}
260
	return nil;
261
}
262
 
263
void
264
loadlib(void)
265
{
266
	int i;
267
	long h;
268
	Sym *s;
269
 
270
loop:
271
	xrefresolv = 0;
272
	for(i=0; i<libraryp; i++) {
273
		if(debug['v'])
274
			Bprint(&bso, "%5.2f autolib: %s (from %s)\n", cputime(), library[i], libraryobj[i]);
275
		objfile(library[i]);
276
	}
277
	if(xrefresolv)
278
	for(h=0; h<nelem(hash); h++)
279
	for(s = hash[h]; s != S; s = s->link)
280
		if(s->type == SXREF)
281
			goto loop;
282
}
283
 
284
void
285
errorexit(void)
286
{
287
 
288
	Bflush(&bso);
289
	if(nerrors) {
290
		if(cout >= 0)
291
			remove(outfile);
292
		exits("error");
293
	}
294
	exits(0);
295
}
296
 
297
void
298
objfile(char *file)
299
{
300
	long off, esym, cnt, l;
301
	int f, work;
302
	Sym *s;
303
	char magbuf[SARMAG];
304
	char name[LIBNAMELEN], pname[LIBNAMELEN];
305
	struct ar_hdr arhdr;
306
	char *e, *start, *stop;
307
 
308
	if(debug['v'])
309
		Bprint(&bso, "%5.2f ldobj: %s\n", cputime(), file);
310
	Bflush(&bso);
311
	if(file[0] == '-' && file[1] == 'l') {
312
		snprint(pname, sizeof(pname), "lib%s.a", file+2);
313
		e = findlib(pname);
314
		if(e == nil) {
315
			diag("cannot find library: %s", file);
316
			errorexit();
317
		}
318
		snprint(name, sizeof(name), "%s/%s", e, pname);
319
		file = name;
320
	}
321
	f = open(file, 0);
322
	if(f < 0) {
323
		diag("cannot open %s: %r", file);
324
		errorexit();
325
	}
326
	l = read(f, magbuf, SARMAG);
327
	if(l != SARMAG || strncmp(magbuf, ARMAG, SARMAG)){
328
		/* load it as a regular file */
329
		l = seek(f, 0L, 2);
330
		seek(f, 0L, 0);
331
		ldobj(f, l, file);
332
		close(f);
333
		return;
334
	}
335
 
336
	l = read(f, &arhdr, SAR_HDR);
337
	if(l != SAR_HDR) {
338
		diag("%s: short read on archive file symbol header", file);
339
		goto out;
340
	}
341
	if(strncmp(arhdr.name, symname, strlen(symname))) {
342
		diag("%s: first entry not symbol header", file);
343
		goto out;
344
	}
345
 
346
	esym = SARMAG + SAR_HDR + atolwhex(arhdr.size);
347
	off = SARMAG + SAR_HDR;
348
 
349
	/*
350
	 * just bang the whole symbol file into memory
351
	 */
352
	seek(f, off, 0);
353
	cnt = esym - off;
354
	start = malloc(cnt + 10);
355
	cnt = read(f, start, cnt);
356
	if(cnt <= 0){
357
		close(f);
358
		return;
359
	}
360
	stop = &start[cnt];
361
	memset(stop, 0, 10);
362
 
363
	work = 1;
364
	while(work){
365
		if(debug['v'])
366
			Bprint(&bso, "%5.2f library pass: %s\n", cputime(), file);
367
		Bflush(&bso);
368
		work = 0;
369
		for(e = start; e < stop; e = strchr(e+5, 0) + 1) {
370
			s = lookup(e+5, 0);
371
			if(s->type != SXREF)
372
				continue;
373
			sprint(pname, "%s(%s)", file, s->name);
374
			if(debug['v'])
375
				Bprint(&bso, "%5.2f library: %s\n", cputime(), pname);
376
			Bflush(&bso);
377
			l = e[1] & 0xff;
378
			l |= (e[2] & 0xff) << 8;
379
			l |= (e[3] & 0xff) << 16;
380
			l |= (e[4] & 0xff) << 24;
381
			seek(f, l, 0);
382
			/* need readn to read the dumps (at least) */
383
			l = readn(f, &arhdr, SAR_HDR);
384
			if(l != SAR_HDR)
385
				goto bad;
386
			if(strncmp(arhdr.fmag, ARFMAG, sizeof(arhdr.fmag)))
387
				goto bad;
388
			l = atolwhex(arhdr.size);
389
			ldobj(f, l, pname);
390
			if(s->type == SXREF) {
391
				diag("%s: failed to load: %s", file, s->name);
392
				errorexit();
393
			}
394
			work = 1;
395
			xrefresolv = 1;
396
		}
397
	}
398
	return;
399
 
400
bad:
401
	diag("%s: bad or out of date archive", file);
402
out:
403
	close(f);
404
}
405
 
406
int
407
zaddr(uchar *p, Adr *a, Sym *h[])
408
{
409
	int i, c;
410
	int l;
411
	Sym *s;
412
	Auto *u;
413
 
414
	c = p[2];
415
	if(c < 0 || c > NSYM){
416
		print("sym out of range: %d\n", c);
417
		p[0] = AEND+1;
418
		return 0;
419
	}
420
	a->type = p[0];
421
	a->reg = p[1];
422
	a->sym = h[c];
423
	a->name = p[3];
424
	c = 4;
425
 
426
	if(a->reg < 0 || a->reg > NREG) {
427
		print("register out of range %d\n", a->reg);
428
		p[0] = AEND+1;
429
		return 0;	/*  force real diagnostic */
430
	}
431
 
432
	switch(a->type) {
433
	default:
434
		print("unknown type %d\n", a->type);
435
		p[0] = AEND+1;
436
		return 0;	/* force real diagnostic */
437
 
438
	case D_NONE:
439
	case D_REG:
440
	case D_FREG:
441
	case D_CREG:
442
	case D_PREG:
443
		break;
444
 
445
	case D_BRANCH:
446
	case D_OREG:
447
	case D_ASI:
448
	case D_CONST:
449
		a->offset = p[4] | (p[5]<<8) |
450
			(p[6]<<16) | (p[7]<<24);
451
		c += 4;
452
		break;
453
 
454
	case D_SCONST:
455
		memmove(a->sval, p+4, NSNAME);
456
		c += NSNAME;
457
		break;
458
 
459
	case D_FCONST:
460
		a->ieee.l = p[4] | (p[5]<<8) |
461
			(p[6]<<16) | (p[7]<<24);
462
		a->ieee.h = p[8] | (p[9]<<8) |
463
			(p[10]<<16) | (p[11]<<24);
464
		c += 8;
465
		break;
466
	}
467
	s = a->sym;
468
	if(s == S)
469
		goto out;
470
	i = a->name;
471
	if(i != D_AUTO && i != D_PARAM)
472
		goto out;
473
 
474
	l = a->offset;
475
	for(u=curauto; u; u=u->link)
476
		if(u->asym == s)
477
		if(u->type == i) {
478
			if(u->aoffset > l)
479
				u->aoffset = l;
480
			goto out;
481
		}
482
 
483
	u = malloc(sizeof(Auto));
484
 
485
	u->link = curauto;
486
	curauto = u;
487
	u->asym = s;
488
	u->aoffset = l;
489
	u->type = i;
490
out:
491
	return c;
492
}
493
 
494
void
495
addlib(char *obj)
496
{
497
	char fn1[LIBNAMELEN], fn2[LIBNAMELEN], comp[LIBNAMELEN], *p, *name;
498
	int i, search;
499
 
500
	if(histfrogp <= 0)
501
		return;
502
 
503
	name = fn1;
504
	search = 0;
505
	if(histfrog[0]->name[1] == '/') {
506
		sprint(name, "");
507
		i = 1;
508
	} else if(histfrog[0]->name[1] == '.') {
509
		sprint(name, ".");
510
		i = 0;
511
	} else {
512
		sprint(name, "");
513
		i = 0;
514
		search = 1;
515
	}
516
 
517
	for(; i<histfrogp; i++) {
518
		snprint(comp, sizeof comp, histfrog[i]->name+1);
519
		for(;;) {
520
			p = strstr(comp, "$O");
521
			if(p == 0)
522
				break;
523
			memmove(p+1, p+2, strlen(p+2)+1);
524
			p[0] = thechar;
525
		}
526
		for(;;) {
527
			p = strstr(comp, "$M");
528
			if(p == 0)
529
				break;
530
			if(strlen(comp)+strlen(thestring)-2+1 >= sizeof comp) {
531
				diag("library component too long");
532
				return;
533
			}
534
			memmove(p+strlen(thestring), p+2, strlen(p+2)+1);
535
			memmove(p, thestring, strlen(thestring));
536
		}
537
		if(strlen(fn1) + strlen(comp) + 3 >= sizeof(fn1)) {
538
			diag("library component too long");
539
			return;
540
		}
541
		if(i > 0 || !search)
542
			strcat(fn1, "/");
543
		strcat(fn1, comp);
544
	}
545
 
546
	cleanname(name);
547
 
548
	if(search){
549
		p = findlib(name);
550
		if(p != nil){
551
			snprint(fn2, sizeof(fn2), "%s/%s", p, name);
552
			name = fn2;
553
		}
554
	}
555
 
556
	for(i=0; i<libraryp; i++)
557
		if(strcmp(name, library[i]) == 0)
558
			return;
559
	if(libraryp == nelem(library)){
560
		diag("too many autolibs; skipping %s", name);
561
		return;
562
	}
563
 
564
	p = malloc(strlen(name) + 1);
565
	strcpy(p, name);
566
	library[libraryp] = p;
567
	p = malloc(strlen(obj) + 1);
568
	strcpy(p, obj);
569
	libraryobj[libraryp] = p;
570
	libraryp++;
571
}
572
 
573
void
574
addhist(long line, int type)
575
{
576
	Auto *u;
577
	Sym *s;
578
	int i, j, k;
579
 
580
	u = malloc(sizeof(Auto));
581
	s = malloc(sizeof(Sym));
582
	s->name = malloc(2*(histfrogp+1) + 1);
583
 
584
	u->asym = s;
585
	u->type = type;
586
	u->aoffset = line;
587
	u->link = curhist;
588
	curhist = u;
589
 
590
	j = 1;
591
	for(i=0; i<histfrogp; i++) {
592
		k = histfrog[i]->value;
593
		s->name[j+0] = k>>8;
594
		s->name[j+1] = k;
595
		j += 2;
596
	}
597
}
598
 
599
void
600
histtoauto(void)
601
{
602
	Auto *l;
603
 
604
	while(l = curhist) {
605
		curhist = l->link;
606
		l->link = curauto;
607
		curauto = l;
608
	}
609
}
610
 
611
void
612
collapsefrog(Sym *s)
613
{
614
	int i;
615
 
616
	/*
617
	 * bad encoding of path components only allows
618
	 * MAXHIST components. if there is an overflow,
619
	 * first try to collapse xxx/..
620
	 */
621
	for(i=1; i<histfrogp; i++)
622
		if(strcmp(histfrog[i]->name+1, "..") == 0) {
623
			memmove(histfrog+i-1, histfrog+i+1,
624
				(histfrogp-i-1)*sizeof(histfrog[0]));
625
			histfrogp--;
626
			goto out;
627
		}
628
 
629
	/*
630
	 * next try to collapse .
631
	 */
632
	for(i=0; i<histfrogp; i++)
633
		if(strcmp(histfrog[i]->name+1, ".") == 0) {
634
			memmove(histfrog+i, histfrog+i+1,
635
				(histfrogp-i-1)*sizeof(histfrog[0]));
636
			goto out;
637
		}
638
 
639
	/*
640
	 * last chance, just truncate from front
641
	 */
642
	memmove(histfrog+0, histfrog+1,
643
		(histfrogp-1)*sizeof(histfrog[0]));
644
 
645
out:
646
	histfrog[histfrogp-1] = s;
647
}
648
 
649
void
650
nopout(Prog *p)
651
{
652
	p->as = ANOP;
653
	p->from.type = D_NONE;
654
	p->to.type = D_NONE;
655
}
656
 
657
uchar*
658
readsome(int f, uchar *buf, uchar *good, uchar *stop, int max)
659
{
660
	int n;
661
 
662
	n = stop - good;
663
	memmove(buf, good, stop - good);
664
	stop = buf + n;
665
	n = MAXIO - n;
666
	if(n > max)
667
		n = max;
668
	n = read(f, stop, n);
669
	if(n <= 0)
670
		return 0;
671
	return stop + n;
672
}
673
 
674
void
675
ldobj(int f, long c, char *pn)
676
{
677
	Prog *p, *t;
678
	Sym *h[NSYM], *s, *di;
679
	int v, o, r, skip;
680
	long ipc;
681
	uchar *bloc, *bsize, *stop;
682
 
683
	bsize = buf.xbuf;
684
	bloc = buf.xbuf;
685
	di = S;
686
 
687
newloop:
688
	memset(h, 0, sizeof(h));
689
	histfrogp = 0;
690
	version++;
691
	ipc = pc;
692
	skip = 0;
693
 
694
loop:
695
	if(c <= 0)
696
		goto eof;
697
	r = bsize - bloc;
698
	if(r < 100 && r < c) {		/* enough for largest prog */
699
		bsize = readsome(f, buf.xbuf, bloc, bsize, c);
700
		if(bsize == 0)
701
			goto eof;
702
		bloc = buf.xbuf;
703
		goto loop;
704
	}
705
	o = bloc[0];		/* as */
706
	if(o <= 0 || o >= ALAST) {
707
		diag("%s: opcode out of range %d", pn, o);
708
		print("	probably not a .k file\n");
709
		errorexit();
710
	}
711
	if(o == ANAME || o == ASIGNAME) {
712
		if(o == ASIGNAME) {
713
			bloc += 4;
714
			c -= 4;
715
		}
716
		stop = memchr(&bloc[3], 0, bsize-&bloc[3]);
717
		if(stop == 0){
718
			bsize = readsome(f, buf.xbuf, bloc, bsize, c);
719
			if(bsize == 0)
720
				goto eof;
721
			bloc = buf.xbuf;
722
			stop = memchr(&bloc[3], 0, bsize-&bloc[3]);
723
			if(stop == 0){
724
				fprint(2, "%s: name too long\n", pn);
725
				errorexit();
726
			}
727
		}
728
		v = bloc[1];	/* type */
729
		o = bloc[2];	/* sym */
730
		bloc += 3;
731
		c -= 3;
732
 
733
		r = 0;
734
		if(v == D_STATIC)
735
			r = version;
736
		s = lookup((char*)bloc, r);
737
		c -= &stop[1] - bloc;
738
		bloc = stop + 1;
739
 
740
		if(debug['W'])
741
			print("	ANAME	%s\n", s->name);
742
		h[o] = s;
743
		if((v == D_EXTERN || v == D_STATIC) && s->type == 0)
744
			s->type = SXREF;
745
		if(v == D_FILE) {
746
			if(s->type != SFILE) {
747
				histgen++;
748
				s->type = SFILE;
749
				s->value = histgen;
750
			}
751
			if(histfrogp < MAXHIST) {
752
				histfrog[histfrogp] = s;
753
				histfrogp++;
754
			} else
755
				collapsefrog(s);
756
		}
757
		goto loop;
758
	}
759
 
760
	if(nhunk < sizeof(Prog))
761
		gethunk();
762
	p = (Prog*)hunk;
763
	nhunk -= sizeof(Prog);
764
	hunk += sizeof(Prog);
765
 
766
	p->as = o;
767
	p->reg = bloc[1] & 0x7f;
768
	if(bloc[1] & 0x80)
769
		p->mark = NOSCHED;
770
	p->line = bloc[2] | (bloc[3]<<8) | (bloc[4]<<16) | (bloc[5]<<24);
771
	r = zaddr(bloc+6, &p->from, h) + 6;
772
	r += zaddr(bloc+r, &p->to, h);
773
	bloc += r;
774
	c -= r;
775
 
776
	if(p->reg < 0 || p->reg > NREG)
777
		diag("register out of range %d", p->reg);
778
 
779
	p->link = P;
780
	p->cond = P;
781
 
782
	if(debug['W'])
783
		print("%P\n", p);
784
 
785
	switch(o) {
786
	case AHISTORY:
787
		if(p->to.offset == -1) {
788
			addlib(pn);
789
			histfrogp = 0;
790
			goto loop;
791
		}
792
		addhist(p->line, D_FILE);		/* 'z' */
793
		if(p->to.offset)
794
			addhist(p->to.offset, D_FILE1);	/* 'Z' */
795
		histfrogp = 0;
796
		goto loop;
797
 
798
	case AEND:
799
		histtoauto();
800
		if(curtext != P)
801
			curtext->to.autom = curauto;
802
		curauto = 0;
803
		curtext = P;
804
		if(c)
805
			goto newloop;
806
		return;
807
 
808
	case AGLOBL:
809
		s = p->from.sym;
810
		if(s == S) {
811
			diag("GLOBL must have a name\n%P", p);
812
			errorexit();
813
		}
814
		if(s->type == 0 || s->type == SXREF) {
815
			s->type = SBSS;
816
			s->value = 0;
817
		}
818
		if(s->type != SBSS) {
819
			diag("redefinition: %s\n%P", s->name, p);
820
			s->type = SBSS;
821
			s->value = 0;
822
		}
823
		if(p->to.offset > s->value)
824
			s->value = p->to.offset;
825
		break;
826
 
827
	case ADYNT:
828
		if(p->to.sym == S) {
829
			diag("DYNT without a sym\n%P", p);
830
			break;
831
		}
832
		di = p->to.sym;
833
		p->reg = 4;
834
		if(di->type == SXREF) {
835
			if(debug['z'])
836
				Bprint(&bso, "%P set to %d\n", p, dtype);
837
			di->type = SCONST;
838
			di->value = dtype;
839
			dtype += 4;
840
		}
841
		if(p->from.sym == S)
842
			break;
843
 
844
		p->from.offset = di->value;
845
		p->from.sym->type = SDATA;
846
		if(curtext == P) {
847
			diag("DYNT not in text: %P", p);
848
			break;
849
		}
850
		p->to.sym = curtext->from.sym;
851
		p->to.type = D_CONST;
852
		p->link = datap;
853
		datap = p;
854
		break;
855
 
856
	case AINIT:
857
		if(p->from.sym == S) {
858
			diag("INIT without a sym\n%P", p);
859
			break;
860
		}
861
		if(di == S) {
862
			diag("INIT without previous DYNT\n%P", p);
863
			break;
864
		}
865
		p->from.offset = di->value;
866
		p->from.sym->type = SDATA;
867
		p->link = datap;
868
		datap = p;
869
		break;
870
 
871
	case ADATA:
872
		p->link = datap;
873
		datap = p;
874
		break;
875
 
876
	case AGOK:
877
		diag("unknown opcode\n%P", p);
878
		p->pc = pc;
879
		pc++;
880
		break;
881
 
882
	case ATEXT:
883
		if(curtext != P) {
884
			histtoauto();
885
			curtext->to.autom = curauto;
886
			curauto = 0;
887
		}
888
		curtext = p;
889
		autosize = (p->to.offset+3L) & ~3L;
890
		p->to.offset = autosize;
891
		autosize += 4;
892
		s = p->from.sym;
893
		if(s == S) {
894
			diag("TEXT must have a name\n%P", p);
895
			errorexit();
896
		}
897
		if(s->type != 0 && s->type != SXREF) {
898
			if(p->reg & DUPOK) {
899
				skip = 1;
900
				goto casedef;
901
			}
902
			diag("redefinition: %s\n%P", s->name, p);
903
		}
904
		s->type = STEXT;
905
		s->value = pc;
906
		if(textp != P) {
907
			for(t = textp; t->cond != P; t = t->cond)
908
				;
909
			t->cond = p;
910
		} else
911
			textp = p;
912
		lastp->link = p;
913
		lastp = p;
914
		p->pc = pc;
915
		pc++;
916
		break;
917
 
918
	case AFMOVF:
919
		if(skip)
920
			goto casedef;
921
 
922
		if(p->from.type == D_FCONST) {
923
			/* size sb 9 max */
924
			sprint(literal, "$%lux", ieeedtof(&p->from.ieee));
925
			s = lookup(literal, 0);
926
			if(s->type == 0) {
927
				s->type = SBSS;
928
				s->value = 4;
929
				t = prg();
930
				t->as = ADATA;
931
				t->line = p->line;
932
				t->from.type = D_OREG;
933
				t->from.sym = s;
934
				t->from.name = D_EXTERN;
935
				t->reg = 4;
936
				t->to = p->from;
937
				t->link = datap;
938
				datap = t;
939
			}
940
			p->from.type = D_OREG;
941
			p->from.sym = s;
942
			p->from.name = D_EXTERN;
943
			p->from.offset = 0;
944
		}
945
		goto casedef;
946
 
947
	case AFMOVD:
948
		if(skip)
949
			goto casedef;
950
		if(p->from.type == D_FCONST) {
951
			/* size sb 18 max */
952
			sprint(literal, "$%lux.%lux",
953
				p->from.ieee.l, p->from.ieee.h);
954
			s = lookup(literal, 0);
955
			if(s->type == 0) {
956
				s->type = SBSS;
957
				s->value = 8;
958
				t = prg();
959
				t->as = ADATA;
960
				t->line = p->line;
961
				t->from.type = D_OREG;
962
				t->from.sym = s;
963
				t->from.name = D_EXTERN;
964
				t->reg = 8;
965
				t->to = p->from;
966
				t->link = datap;
967
				datap = t;
968
			}
969
			p->from.type = D_OREG;
970
			p->from.sym = s;
971
			p->from.name = D_EXTERN;
972
			p->from.offset = 0;
973
		}
974
		goto casedef;
975
 
976
	default:
977
	casedef:
978
		if(skip)
979
			nopout(p);
980
 
981
		if(p->to.type == D_BRANCH)
982
			p->to.offset += ipc;
983
		lastp->link = p;
984
		lastp = p;
985
		p->pc = pc;
986
		pc++;
987
		break;
988
	}
989
	goto loop;
990
 
991
eof:
992
	diag("truncated object file: %s", pn);
993
}
994
 
995
Sym*
996
lookup(char *symb, int v)
997
{
998
	Sym *s;
999
	char *p;
1000
	long h;
1001
	int c, l;
1002
 
1003
	h = v;
1004
	for(p=symb; c = *p; p++)
1005
		h = h+h+h + c;
1006
	l = (p - symb) + 1;
1007
	h &= 0xffffff;
1008
	h %= NHASH;
1009
	for(s = hash[h]; s != S; s = s->link)
1010
		if(s->version == v)
1011
		if(memcmp(s->name, symb, l) == 0)
1012
			return s;
1013
 
1014
	while(nhunk < sizeof(Sym))
1015
		gethunk();
1016
	s = (Sym*)hunk;
1017
	nhunk -= sizeof(Sym);
1018
	hunk += sizeof(Sym);
1019
 
1020
	s->name = malloc(l + 1);
1021
	memmove(s->name, symb, l);
1022
 
1023
	s->link = hash[h];
1024
	s->type = 0;
1025
	s->version = v;
1026
	s->value = 0;
1027
	hash[h] = s;
1028
	return s;
1029
}
1030
 
1031
Prog*
1032
prg(void)
1033
{
1034
	Prog *p;
1035
	int n;
1036
 
1037
	n = (sizeof(Prog) + 3) & ~3;
1038
	while(nhunk < n)
1039
		gethunk();
1040
 
1041
	p = (Prog*)hunk;
1042
	nhunk -= n;
1043
	hunk += n;
1044
 
1045
	*p = zprg;
1046
	return p;
1047
}
1048
 
1049
void
1050
gethunk(void)
1051
{
1052
	char *h;
1053
	long nh;
1054
 
1055
	nh = NHUNK;
1056
	if(tothunk >= 5L*NHUNK) {
1057
		nh = 5L*NHUNK;
1058
		if(tothunk >= 25L*NHUNK)
1059
			nh = 25L*NHUNK;
1060
	}
1061
	h = mysbrk(nh);
1062
	if(h == (char *)-1) {
1063
		diag("out of memory");
1064
		errorexit();
1065
	}
1066
 
1067
	hunk = h;
1068
	nhunk = nh;
1069
	tothunk += nh;
1070
}
1071
 
1072
void
1073
doprof1(void)
1074
{
1075
	Sym *s;
1076
	long n;
1077
	Prog *p, *q;
1078
 
1079
	if(debug['v'])
1080
		Bprint(&bso, "%5.2f profile 1\n", cputime());
1081
	Bflush(&bso);
1082
	s = lookup("__mcount", 0);
1083
	n = 1;
1084
	for(p = firstp->link; p != P; p = p->link) {
1085
		if(p->as == ATEXT) {
1086
			q = prg();
1087
			q->line = p->line;
1088
			q->link = datap;
1089
			datap = q;
1090
			q->as = ADATA;
1091
			q->from.type = D_OREG;
1092
			q->from.name = D_EXTERN;
1093
			q->from.offset = n*4;
1094
			q->from.sym = s;
1095
			q->reg = 4;
1096
			q->to = p->from;
1097
			q->to.type = D_CONST;
1098
 
1099
			q = prg();
1100
			q->line = p->line;
1101
			q->pc = p->pc;
1102
			q->link = p->link;
1103
			p->link = q;
1104
			p = q;
1105
			p->as = AMOVW;
1106
			p->from.type = D_OREG;
1107
			p->from.name = D_EXTERN;
1108
			p->from.sym = s;
1109
			p->from.offset = n*4 + 4;
1110
			p->to.type = D_REG;
1111
			p->to.reg = REGTMP;
1112
 
1113
			q = prg();
1114
			q->line = p->line;
1115
			q->pc = p->pc;
1116
			q->link = p->link;
1117
			p->link = q;
1118
			p = q;
1119
			p->as = AADD;
1120
			p->from.type = D_CONST;
1121
			p->from.offset = 1;
1122
			p->to.type = D_REG;
1123
			p->to.reg = REGTMP;
1124
 
1125
			q = prg();
1126
			q->line = p->line;
1127
			q->pc = p->pc;
1128
			q->link = p->link;
1129
			p->link = q;
1130
			p = q;
1131
			p->as = AMOVW;
1132
			p->from.type = D_REG;
1133
			p->from.reg = REGTMP;
1134
			p->to.type = D_OREG;
1135
			p->to.name = D_EXTERN;
1136
			p->to.sym = s;
1137
			p->to.offset = n*4 + 4;
1138
 
1139
			n += 2;
1140
			continue;
1141
		}
1142
	}
1143
	q = prg();
1144
	q->line = 0;
1145
	q->link = datap;
1146
	datap = q;
1147
 
1148
	q->as = ADATA;
1149
	q->from.type = D_OREG;
1150
	q->from.name = D_EXTERN;
1151
	q->from.sym = s;
1152
	q->reg = 4;
1153
	q->to.type = D_CONST;
1154
	q->to.offset = n;
1155
 
1156
	s->type = SBSS;
1157
	s->value = n*4;
1158
}
1159
 
1160
void
1161
doprof2(void)
1162
{
1163
	Sym *s2, *s4;
1164
	Prog *p, *q, *q2, *ps2, *ps4;
1165
 
1166
	if(debug['v'])
1167
		Bprint(&bso, "%5.2f profile 2\n", cputime());
1168
	Bflush(&bso);
1169
 
1170
	if(debug['e']){
1171
		s2 = lookup("_tracein", 0);
1172
		s4 = lookup("_traceout", 0);
1173
	}else{
1174
		s2 = lookup("_profin", 0);
1175
		s4 = lookup("_profout", 0);
1176
	}
1177
	if(s2->type != STEXT || s4->type != STEXT) {
1178
		if(debug['e'])
1179
			diag("_tracein/_traceout not defined %d %d", s2->type, s4->type);
1180
		else
1181
			diag("_profin/_profout not defined");
1182
		return;
1183
	}
1184
 
1185
	ps2 = P;
1186
	ps4 = P;
1187
	for(p = firstp; p != P; p = p->link) {
1188
		if(p->as == ATEXT) {
1189
			if(p->from.sym == s2) {
1190
				p->reg = 1;
1191
				ps2 = p;
1192
			}
1193
			if(p->from.sym == s4) {
1194
				p->reg = 1;
1195
				ps4 = p;
1196
			}
1197
		}
1198
	}
1199
	for(p = firstp; p != P; p = p->link) {
1200
		if(p->as == ATEXT) {
1201
			curtext = p;
1202
 
1203
			if(p->reg & NOPROF) {	/* dont profile */
1204
				for(;;) {
1205
					q = p->link;
1206
					if(q == P)
1207
						break;
1208
					if(q->as == ATEXT)
1209
						break;
1210
					p = q;
1211
				}
1212
				continue;
1213
			}
1214
 
1215
			/*
1216
			 * JMPL	profin
1217
			 */
1218
			q = prg();
1219
			q->line = p->line;
1220
			q->pc = p->pc;
1221
			q->link = p->link;
1222
			if(debug['e']){		/* embedded tracing */
1223
				q2 = prg();
1224
				p->link = q2;
1225
				q2->link = q;
1226
 
1227
				q2->line = p->line;
1228
				q2->pc = p->pc;
1229
 
1230
				q2->as = AJMP;
1231
				q2->to.type = D_BRANCH;
1232
				q2->to.sym = p->to.sym;
1233
				q2->cond = q->link;
1234
			}else
1235
				p->link = q;
1236
			p = q;
1237
			p->as = AJMPL;
1238
			p->to.type = D_BRANCH;
1239
			p->cond = ps2;
1240
			p->to.sym = s2;
1241
 
1242
			continue;
1243
		}
1244
		if(p->as == ARETURN) {
1245
			/*
1246
			 * RETURN (default)
1247
			 */
1248
			if(debug['e']){		/* embedded tracing */
1249
				q = prg();
1250
				q->line = p->line;
1251
				q->pc = p->pc;
1252
				q->link = p->link;
1253
				p->link = q;
1254
				p = q;
1255
			}
1256
			/*
1257
			 * RETURN
1258
			 */
1259
			q = prg();
1260
			q->as = ARETURN;
1261
			q->from = p->from;
1262
			q->to = p->to;
1263
			q->link = p->link;
1264
			p->link = q;
1265
 
1266
			/*
1267
			 * JMPL profout
1268
			 */
1269
			p->as = AJMPL;
1270
			p->from = zprg.from;
1271
			p->to = zprg.to;
1272
			p->to.type = D_BRANCH;
1273
			p->cond = ps4;
1274
			p->to.sym = s4;
1275
 
1276
			p = q;
1277
 
1278
			continue;
1279
		}
1280
	}
1281
}
1282
 
1283
void
1284
nuxiinit(void)
1285
{
1286
	int i, c;
1287
 
1288
	for(i=0; i<4; i++) {
1289
		c = find1(0x01020304L, i+1);
1290
		if(i >= 2)
1291
			inuxi2[i-2] = c;
1292
		if(i >= 3)
1293
			inuxi1[i-3] = c;
1294
		inuxi4[i] = c;
1295
 
1296
		fnuxi8[i] = c+4;
1297
		fnuxi8[i+4] = c;
1298
	}
1299
	if(debug['v']) {
1300
		Bprint(&bso, "inuxi = ");
1301
		for(i=0; i<1; i++)
1302
			Bprint(&bso, "%d", inuxi1[i]);
1303
		Bprint(&bso, " ");
1304
		for(i=0; i<2; i++)
1305
			Bprint(&bso, "%d", inuxi2[i]);
1306
		Bprint(&bso, " ");
1307
		for(i=0; i<4; i++)
1308
			Bprint(&bso, "%d", inuxi4[i]);
1309
		Bprint(&bso, "\nfnuxi = ");
1310
		for(i=0; i<8; i++)
1311
			Bprint(&bso, "%d", fnuxi8[i]);
1312
		Bprint(&bso, "\n");
1313
	}
1314
	Bflush(&bso);
1315
}
1316
 
1317
int
1318
find1(long l, int c)
1319
{
1320
	char *p;
1321
	int i;
1322
 
1323
	p = (char*)&l;
1324
	for(i=0; i<4; i++)
1325
		if(*p++ == c)
1326
			return i;
1327
	return 0;
1328
}
1329
 
1330
long
1331
ieeedtof(Ieee *ieeep)
1332
{
1333
	int exp;
1334
	long v;
1335
 
1336
	if(ieeep->h == 0)
1337
		return 0;
1338
	exp = (ieeep->h>>20) & ((1L<<11)-1L);
1339
	exp -= (1L<<10) - 2L;
1340
	v = (ieeep->h & 0xfffffL) << 3;
1341
	v |= (ieeep->l >> 29) & 0x7L;
1342
	if((ieeep->l >> 28) & 1) {
1343
		v++;
1344
		if(v & 0x800000L) {
1345
			v = (v & 0x7fffffL) >> 1;
1346
			exp++;
1347
		}
1348
	}
1349
	if(exp <= -126 || exp >= 130)
1350
		diag("double fp to single fp overflow");
1351
	v |= ((exp + 126) & 0xffL) << 23;
1352
	v |= ieeep->h & 0x80000000L;
1353
	return v;
1354
}
1355
 
1356
double
1357
ieeedtod(Ieee *ieeep)
1358
{
1359
	Ieee e;
1360
	double fr;
1361
	int exp;
1362
 
1363
	if(ieeep->h & (1L<<31)) {
1364
		e.h = ieeep->h & ~(1L<<31);
1365
		e.l = ieeep->l;
1366
		return -ieeedtod(&e);
1367
	}
1368
	if(ieeep->l == 0 && ieeep->h == 0)
1369
		return 0;
1370
	fr = ieeep->l & ((1L<<16)-1L);
1371
	fr /= 1L<<16;
1372
	fr += (ieeep->l>>16) & ((1L<<16)-1L);
1373
	fr /= 1L<<16;
1374
	fr += (ieeep->h & (1L<<20)-1L) | (1L<<20);
1375
	fr /= 1L<<21;
1376
	exp = (ieeep->h>>20) & ((1L<<11)-1L);
1377
	exp -= (1L<<10) - 2L;
1378
	return ldexp(fr, exp);
1379
}