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