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