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