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