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