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