changelog shortlog tags branches changeset files revisions annotate raw help

Mercurial > hg > plan9front / sys/src/cmd/7l/obj.c

changeset 0: eaccc3e8d226
child: d1102fefd6c1
author: Taru Karttunen <taruti@taruti.net>
date: Wed, 30 Mar 2011 15:46:40 +0300
permissions: -rwxr-xr-x
description: Import sources from 2011-03-30 iso image
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 }