1 #include "l.h"
2
3 static struct {
4 ulong start;
5 ulong size;
6 } pool;
7
8 void checkpool(Prog*);
9 void flushpool(Prog*, int);
10
11 void
span(void)12 span(void)
13 {
14 Prog *p;
15 Sym *setext, *s;
16 Optab *o;
17 int m, bflag, i;
18 long c, otxt, v;
19
20 if(debug['v'])
21 Bprint(&bso, "%5.2f span\n", cputime());
22 Bflush(&bso);
23
24 bflag = 0;
25 c = INITTEXT;
26 otxt = c;
27 for(p = firstp; p != P; p = p->link) {
28 p->pc = c;
29 o = oplook(p);
30 m = o->size;
31 if(m == 0) {
32 if(p->as == ATEXT) {
33 curtext = p;
34 autosize = p->to.offset + 4;
35 if(p->from.sym != S)
36 p->from.sym->value = c;
37 /* need passes to resolve branches */
38 if(c-otxt >= 1L<<17)
39 bflag = 1;
40 otxt = c;
41 continue;
42 }
43 diag("zero-width instruction\n%P", p);
44 continue;
45 }
46 switch(o->flag & (LFROM|LTO|LPOOL)) {
47 case LFROM:
48 addpool(p, &p->from);
49 break;
50 case LTO:
51 addpool(p, &p->to);
52 break;
53 case LPOOL:
54 if ((p->scond&C_SCOND) == 14)
55 flushpool(p, 0);
56 break;
57 }
58 if(p->as==AMOVW && p->to.type==D_REG && p->to.reg==REGPC && (p->scond&C_SCOND) == 14)
59 flushpool(p, 0);
60 c += m;
61 if(blitrl)
62 checkpool(p);
63 }
64
65 /*
66 * if any procedure is large enough to
67 * generate a large SBRA branch, then
68 * generate extra passes putting branches
69 * around jmps to fix. this is rare.
70 */
71 while(bflag) {
72 if(debug['v'])
73 Bprint(&bso, "%5.2f span1\n", cputime());
74 bflag = 0;
75 c = INITTEXT;
76 for(p = firstp; p != P; p = p->link) {
77 p->pc = c;
78 o = oplook(p);
79 /* very larg branches
80 if(o->type == 6 && p->cond) {
81 otxt = p->cond->pc - c;
82 if(otxt < 0)
83 otxt = -otxt;
84 if(otxt >= (1L<<17) - 10) {
85 q = prg();
86 q->link = p->link;
87 p->link = q;
88 q->as = AB;
89 q->to.type = D_BRANCH;
90 q->cond = p->cond;
91 p->cond = q;
92 q = prg();
93 q->link = p->link;
94 p->link = q;
95 q->as = AB;
96 q->to.type = D_BRANCH;
97 q->cond = q->link->link;
98 bflag = 1;
99 }
100 }
101 */
102 m = o->size;
103 if(m == 0) {
104 if(p->as == ATEXT) {
105 curtext = p;
106 autosize = p->to.offset + 4;
107 if(p->from.sym != S)
108 p->from.sym->value = c;
109 continue;
110 }
111 diag("zero-width instruction\n%P", p);
112 continue;
113 }
114 c += m;
115 }
116 }
117
118 if(debug['t']) {
119 /*
120 * add strings to text segment
121 */
122 c = rnd(c, 8);
123 for(i=0; i<NHASH; i++)
124 for(s = hash[i]; s != S; s = s->link) {
125 if(s->type != SSTRING)
126 continue;
127 v = s->value;
128 while(v & 3)
129 v++;
130 s->value = c;
131 c += v;
132 }
133 }
134
135 c = rnd(c, 8);
136
137 setext = lookup("etext", 0);
138 if(setext != S) {
139 setext->value = c;
140 textsize = c - INITTEXT;
141 }
142 if(INITRND)
143 INITDAT = rnd(c, INITRND);
144 if(debug['v'])
145 Bprint(&bso, "tsize = %lux\n", textsize);
146 Bflush(&bso);
147 }
148
149 /*
150 * when the first reference to the literal pool threatens
151 * to go out of range of a 12-bit PC-relative offset,
152 * drop the pool now, and branch round it.
153 * this happens only in extended basic blocks that exceed 4k.
154 */
155 void
checkpool(Prog * p)156 checkpool(Prog *p)
157 {
158 if(pool.size >= 0xffc || immaddr((p->pc+4)+4+pool.size - pool.start+8) == 0)
159 flushpool(p, 1);
160 else if(p->link == P)
161 flushpool(p, 2);
162 }
163
164 void
flushpool(Prog * p,int skip)165 flushpool(Prog *p, int skip)
166 {
167 Prog *q;
168
169 if(blitrl) {
170 if(skip){
171 if(debug['v'] && skip == 1)
172 print("note: flush literal pool at %lux: len=%lud ref=%lux\n", p->pc+4, pool.size, pool.start);
173 q = prg();
174 q->as = AB;
175 q->to.type = D_BRANCH;
176 q->cond = p->link;
177 q->link = blitrl;
178 blitrl = q;
179 }
180 else if(p->pc+pool.size-pool.start < 2048)
181 return;
182 elitrl->link = p->link;
183 p->link = blitrl;
184 blitrl = 0; /* BUG: should refer back to values until out-of-range */
185 elitrl = 0;
186 pool.size = 0;
187 pool.start = 0;
188 }
189 }
190
191 void
addpool(Prog * p,Adr * a)192 addpool(Prog *p, Adr *a)
193 {
194 Prog *q, t;
195 int c;
196
197 c = aclass(a);
198
199 t = zprg;
200 t.as = AWORD;
201
202 switch(c) {
203 default:
204 t.to = *a;
205 break;
206
207 case C_SROREG:
208 case C_LOREG:
209 case C_ROREG:
210 case C_FOREG:
211 case C_SOREG:
212 case C_FAUTO:
213 case C_SAUTO:
214 case C_LAUTO:
215 case C_LACON:
216 t.to.type = D_CONST;
217 t.to.offset = instoffset;
218 break;
219 }
220
221 for(q = blitrl; q != P; q = q->link) /* could hash on t.t0.offset */
222 if(memcmp(&q->to, &t.to, sizeof(t.to)) == 0) {
223 p->cond = q;
224 return;
225 }
226
227 q = prg();
228 *q = t;
229 q->pc = pool.size;
230
231 if(blitrl == P) {
232 blitrl = q;
233 pool.start = p->pc;
234 } else
235 elitrl->link = q;
236 elitrl = q;
237 pool.size += 4;
238
239 p->cond = q;
240 }
241
242 void
xdefine(char * p,int t,long v)243 xdefine(char *p, int t, long v)
244 {
245 Sym *s;
246
247 s = lookup(p, 0);
248 if(s->type == 0 || s->type == SXREF) {
249 s->type = t;
250 s->value = v;
251 }
252 }
253
254 long
regoff(Adr * a)255 regoff(Adr *a)
256 {
257
258 instoffset = 0;
259 aclass(a);
260 return instoffset;
261 }
262
263 long
immrot(ulong v)264 immrot(ulong v)
265 {
266 int i;
267
268 for(i=0; i<16; i++) {
269 if((v & ~0xff) == 0)
270 return (i<<8) | v | (1<<25);
271 v = (v<<2) | (v>>30);
272 }
273 return 0;
274 }
275
276 long
immaddr(long v)277 immaddr(long v)
278 {
279 if(v >= 0 && v <= 0xfff)
280 return (v & 0xfff) |
281 (1<<24) | /* pre indexing */
282 (1<<23); /* pre indexing, up */
283 if(v >= -0xfff && v < 0)
284 return (-v & 0xfff) |
285 (1<<24); /* pre indexing */
286 return 0;
287 }
288
289 int
immfloat(long v)290 immfloat(long v)
291 {
292 return (v & 0xC03) == 0; /* offset will fit in floating-point load/store */
293 }
294
295 int
immhalf(long v)296 immhalf(long v)
297 {
298 if(v >= 0 && v <= 0xff)
299 return v|
300 (1<<24)| /* pre indexing */
301 (1<<23); /* pre indexing, up */
302 if(v >= -0xff && v < 0)
303 return (-v & 0xff)|
304 (1<<24); /* pre indexing */
305 return 0;
306 }
307
308 int
aclass(Adr * a)309 aclass(Adr *a)
310 {
311 Sym *s;
312 int t;
313
314 switch(a->type) {
315 case D_NONE:
316 return C_NONE;
317
318 case D_REG:
319 return C_REG;
320
321 case D_REGREG:
322 return C_REGREG;
323
324 case D_SHIFT:
325 return C_SHIFT;
326
327 case D_FREG:
328 return C_FREG;
329
330 case D_FPCR:
331 return C_FCR;
332
333 case D_OREG:
334 switch(a->name) {
335 case D_EXTERN:
336 case D_STATIC:
337 if(a->sym == 0 || a->sym->name == 0) {
338 print("null sym external\n");
339 print("%D\n", a);
340 return C_GOK;
341 }
342 s = a->sym;
343 t = s->type;
344 if(t == 0 || t == SXREF) {
345 diag("undefined external: %s in %s",
346 s->name, TNAME);
347 s->type = SDATA;
348 }
349 if(dlm) {
350 switch(t) {
351 default:
352 instoffset = s->value + a->offset + INITDAT;
353 break;
354 case SUNDEF:
355 case STEXT:
356 case SCONST:
357 case SLEAF:
358 case SSTRING:
359 instoffset = s->value + a->offset;
360 break;
361 }
362 return C_ADDR;
363 }
364 instoffset = s->value + a->offset - BIG;
365 t = immaddr(instoffset);
366 if(t) {
367 if(immhalf(instoffset))
368 return immfloat(t) ? C_HFEXT : C_HEXT;
369 if(immfloat(t))
370 return C_FEXT;
371 return C_SEXT;
372 }
373 return C_LEXT;
374 case D_AUTO:
375 instoffset = autosize + a->offset;
376 t = immaddr(instoffset);
377 if(t){
378 if(immhalf(instoffset))
379 return immfloat(t) ? C_HFAUTO : C_HAUTO;
380 if(immfloat(t))
381 return C_FAUTO;
382 return C_SAUTO;
383 }
384 return C_LAUTO;
385
386 case D_PARAM:
387 instoffset = autosize + a->offset + 4L;
388 t = immaddr(instoffset);
389 if(t){
390 if(immhalf(instoffset))
391 return immfloat(t) ? C_HFAUTO : C_HAUTO;
392 if(immfloat(t))
393 return C_FAUTO;
394 return C_SAUTO;
395 }
396 return C_LAUTO;
397 case D_NONE:
398 instoffset = a->offset;
399 t = immaddr(instoffset);
400 if(t) {
401 if(immhalf(instoffset)) /* n.b. that it will also satisfy immrot */
402 return immfloat(t) ? C_HFOREG : C_HOREG;
403 if(immfloat(t))
404 return C_FOREG; /* n.b. that it will also satisfy immrot */
405 t = immrot(instoffset);
406 if(t)
407 return C_SROREG;
408 if(immhalf(instoffset))
409 return C_HOREG;
410 return C_SOREG;
411 }
412 t = immrot(instoffset);
413 if(t)
414 return C_ROREG;
415 return C_LOREG;
416 }
417 return C_GOK;
418
419 case D_PSR:
420 return C_PSR;
421
422 case D_OCONST:
423 switch(a->name) {
424 case D_EXTERN:
425 case D_STATIC:
426 s = a->sym;
427 t = s->type;
428 if(t == 0 || t == SXREF) {
429 diag("undefined external: %s in %s",
430 s->name, TNAME);
431 s->type = SDATA;
432 }
433 instoffset = s->value + a->offset + INITDAT;
434 if(s->type == STEXT || s->type == SLEAF || s->type == SUNDEF)
435 instoffset = s->value + a->offset;
436 return C_LCON;
437 }
438 return C_GOK;
439
440 case D_FCONST:
441 return C_FCON;
442
443 case D_CONST:
444 switch(a->name) {
445
446 case D_NONE:
447 instoffset = a->offset;
448 if(a->reg != NREG)
449 goto aconsize;
450
451 t = immrot(instoffset);
452 if(t)
453 return C_RCON;
454 t = immrot(~instoffset);
455 if(t)
456 return C_NCON;
457 return C_LCON;
458
459 case D_EXTERN:
460 case D_STATIC:
461 s = a->sym;
462 if(s == S)
463 break;
464 t = s->type;
465 switch(t) {
466 case 0:
467 case SXREF:
468 diag("undefined external: %s in %s",
469 s->name, TNAME);
470 s->type = SDATA;
471 break;
472 case SUNDEF:
473 case STEXT:
474 case SSTRING:
475 case SCONST:
476 case SLEAF:
477 instoffset = s->value + a->offset;
478 return C_LCON;
479 }
480 if(!dlm) {
481 instoffset = s->value + a->offset - BIG;
482 t = immrot(instoffset);
483 if(t && instoffset != 0)
484 return C_RECON;
485 }
486 instoffset = s->value + a->offset + INITDAT;
487 return C_LCON;
488
489 case D_AUTO:
490 instoffset = autosize + a->offset;
491 goto aconsize;
492
493 case D_PARAM:
494 instoffset = autosize + a->offset + 4L;
495 aconsize:
496 t = immrot(instoffset);
497 if(t)
498 return C_RACON;
499 return C_LACON;
500 }
501 return C_GOK;
502
503 case D_BRANCH:
504 return C_SBRA;
505 }
506 return C_GOK;
507 }
508
509 Optab*
oplook(Prog * p)510 oplook(Prog *p)
511 {
512 int a1, a2, a3, r;
513 char *c1, *c3;
514 Optab *o, *e;
515
516 a1 = p->optab;
517 if(a1)
518 return optab+(a1-1);
519 a1 = p->from.class;
520 if(a1 == 0) {
521 a1 = aclass(&p->from) + 1;
522 p->from.class = a1;
523 }
524 a1--;
525 a3 = p->to.class;
526 if(a3 == 0) {
527 a3 = aclass(&p->to) + 1;
528 p->to.class = a3;
529 }
530 a3--;
531 a2 = C_NONE;
532 if(p->reg != NREG)
533 a2 = C_REG;
534 r = p->as;
535 o = oprange[r].start;
536 if(o == 0) {
537 a1 = opcross[repop[r]][a1][a2][a3];
538 if(a1) {
539 p->optab = a1+1;
540 return optab+a1;
541 }
542 o = oprange[r].stop; /* just generate an error */
543 }
544 if(0) {
545 print("oplook %A %d %d %d\n",
546 (int)p->as, a1, a2, a3);
547 print(" %d %d\n", p->from.type, p->to.type);
548 }
549 e = oprange[r].stop;
550 c1 = xcmp[a1];
551 c3 = xcmp[a3];
552 for(; o<e; o++)
553 if(o->a2 == a2)
554 if(c1[o->a1])
555 if(c3[o->a3]) {
556 p->optab = (o-optab)+1;
557 return o;
558 }
559 diag("illegal combination %A %d %d %d",
560 p->as, a1, a2, a3);
561 prasm(p);
562 if(o == 0)
563 o = optab;
564 return o;
565 }
566
567 int
cmp(int a,int b)568 cmp(int a, int b)
569 {
570
571 if(a == b)
572 return 1;
573 switch(a) {
574 case C_LCON:
575 if(b == C_RCON || b == C_NCON)
576 return 1;
577 break;
578 case C_LACON:
579 if(b == C_RACON)
580 return 1;
581 break;
582 case C_LECON:
583 if(b == C_RECON)
584 return 1;
585 break;
586
587 case C_HFEXT:
588 return b == C_HEXT || b == C_FEXT;
589 case C_FEXT:
590 case C_HEXT:
591 return b == C_HFEXT;
592 case C_SEXT:
593 return cmp(C_HFEXT, b);
594 case C_LEXT:
595 return cmp(C_SEXT, b);
596
597 case C_HFAUTO:
598 return b == C_HAUTO || b == C_FAUTO;
599 case C_FAUTO:
600 case C_HAUTO:
601 return b == C_HFAUTO;
602 case C_SAUTO:
603 return cmp(C_HFAUTO, b);
604 case C_LAUTO:
605 return cmp(C_SAUTO, b);
606
607 case C_HFOREG:
608 return b == C_HOREG || b == C_FOREG;
609 case C_FOREG:
610 case C_HOREG:
611 return b == C_HFOREG;
612 case C_SROREG:
613 return cmp(C_SOREG, b) || cmp(C_ROREG, b);
614 case C_SOREG:
615 case C_ROREG:
616 return b == C_SROREG || cmp(C_HFOREG, b);
617 case C_LOREG:
618 return cmp(C_SROREG, b);
619
620 case C_LBRA:
621 if(b == C_SBRA)
622 return 1;
623 break;
624 }
625 return 0;
626 }
627
628 int
ocmp(const void * a1,const void * a2)629 ocmp(const void *a1, const void *a2)
630 {
631 Optab *p1, *p2;
632 int n;
633
634 p1 = (Optab*)a1;
635 p2 = (Optab*)a2;
636 n = p1->as - p2->as;
637 if(n)
638 return n;
639 n = (p2->flag&V4) - (p1->flag&V4); /* architecture version */
640 if(n)
641 return n;
642 n = (p2->flag&VFP) - (p1->flag&VFP); /* floating point arch */
643 if(n)
644 return n;
645 n = p1->a1 - p2->a1;
646 if(n)
647 return n;
648 n = p1->a2 - p2->a2;
649 if(n)
650 return n;
651 n = p1->a3 - p2->a3;
652 if(n)
653 return n;
654 return 0;
655 }
656
657 void
buildop(void)658 buildop(void)
659 {
660 int i, n, r;
661
662 armv4 = !debug['h'];
663 vfp = debug['f'];
664 for(i=0; i<C_GOK; i++)
665 for(n=0; n<C_GOK; n++)
666 xcmp[i][n] = cmp(n, i);
667 for(n=0; optab[n].as != AXXX; n++) {
668 if((optab[n].flag & VFP) && !vfp)
669 optab[n].as = AXXX;
670 if((optab[n].flag & V4) && !armv4) {
671 optab[n].as = AXXX;
672 break;
673 }
674 }
675 qsort(optab, n, sizeof(optab[0]), ocmp);
676 for(i=0; i<n; i++) {
677 r = optab[i].as;
678 oprange[r].start = optab+i;
679 while(optab[i].as == r)
680 i++;
681 oprange[r].stop = optab+i;
682 i--;
683
684 switch(r)
685 {
686 default:
687 diag("unknown op in build: %A", r);
688 errorexit();
689 case AXXX:
690 break;
691 case AADD:
692 oprange[AAND] = oprange[r];
693 oprange[AEOR] = oprange[r];
694 oprange[ASUB] = oprange[r];
695 oprange[ARSB] = oprange[r];
696 oprange[AADC] = oprange[r];
697 oprange[ASBC] = oprange[r];
698 oprange[ARSC] = oprange[r];
699 oprange[AORR] = oprange[r];
700 oprange[ABIC] = oprange[r];
701 break;
702 case ACMP:
703 oprange[ATST] = oprange[r];
704 oprange[ATEQ] = oprange[r];
705 oprange[ACMN] = oprange[r];
706 break;
707 case AMVN:
708 break;
709 case ABEQ:
710 oprange[ABNE] = oprange[r];
711 oprange[ABCS] = oprange[r];
712 oprange[ABHS] = oprange[r];
713 oprange[ABCC] = oprange[r];
714 oprange[ABLO] = oprange[r];
715 oprange[ABMI] = oprange[r];
716 oprange[ABPL] = oprange[r];
717 oprange[ABVS] = oprange[r];
718 oprange[ABVC] = oprange[r];
719 oprange[ABHI] = oprange[r];
720 oprange[ABLS] = oprange[r];
721 oprange[ABGE] = oprange[r];
722 oprange[ABLT] = oprange[r];
723 oprange[ABGT] = oprange[r];
724 oprange[ABLE] = oprange[r];
725 break;
726 case ASLL:
727 oprange[ASRL] = oprange[r];
728 oprange[ASRA] = oprange[r];
729 break;
730 case AMUL:
731 oprange[AMULU] = oprange[r];
732 break;
733 case ADIV:
734 oprange[AMOD] = oprange[r];
735 oprange[AMODU] = oprange[r];
736 oprange[ADIVU] = oprange[r];
737 break;
738 case AMOVW:
739 case AMOVB:
740 case AMOVBU:
741 case AMOVH:
742 case AMOVHU:
743 break;
744 case ASWPW:
745 oprange[ASWPBU] = oprange[r];
746 break;
747 case AB:
748 case ABL:
749 case ABX:
750 case ABXRET:
751 case ASWI:
752 case AWORD:
753 case AMOVM:
754 case ARFE:
755 case ATEXT:
756 case ACASE:
757 case ABCASE:
758 break;
759 case AADDF:
760 oprange[AADDD] = oprange[r];
761 oprange[ASUBF] = oprange[r];
762 oprange[ASUBD] = oprange[r];
763 oprange[AMULF] = oprange[r];
764 oprange[AMULD] = oprange[r];
765 oprange[ADIVF] = oprange[r];
766 oprange[ADIVD] = oprange[r];
767 oprange[AMOVFD] = oprange[r];
768 oprange[AMOVDF] = oprange[r];
769 break;
770
771 case ACMPF:
772 oprange[ACMPD] = oprange[r];
773 break;
774
775 case AMOVF:
776 oprange[AMOVD] = oprange[r];
777 break;
778
779 case AMOVFW:
780 oprange[AMOVWF] = oprange[r];
781 oprange[AMOVWD] = oprange[r];
782 oprange[AMOVDW] = oprange[r];
783 break;
784
785 case AMULL:
786 oprange[AMULA] = oprange[r];
787 oprange[AMULAL] = oprange[r];
788 oprange[AMULLU] = oprange[r];
789 oprange[AMULALU] = oprange[r];
790 break;
791 }
792 }
793 }
794
795 /*
796 void
797 buildrep(int x, int as)
798 {
799 Opcross *p;
800 Optab *e, *s, *o;
801 int a1, a2, a3, n;
802
803 if(C_NONE != 0 || C_REG != 1 || C_GOK >= 32 || x >= nelem(opcross)) {
804 diag("assumptions fail in buildrep");
805 errorexit();
806 }
807 repop[as] = x;
808 p = (opcross + x);
809 s = oprange[as].start;
810 e = oprange[as].stop;
811 for(o=e-1; o>=s; o--) {
812 n = o-optab;
813 for(a2=0; a2<2; a2++) {
814 if(a2) {
815 if(o->a2 == C_NONE)
816 continue;
817 } else
818 if(o->a2 != C_NONE)
819 continue;
820 for(a1=0; a1<32; a1++) {
821 if(!xcmp[a1][o->a1])
822 continue;
823 for(a3=0; a3<32; a3++)
824 if(xcmp[a3][o->a3])
825 (*p)[a1][a2][a3] = n;
826 }
827 }
828 }
829 oprange[as].start = 0;
830 }
831 */
832
833 enum{
834 ABSD = 0,
835 ABSU = 1,
836 RELD = 2,
837 RELU = 3,
838 };
839
840 int modemap[4] = { 0, 1, -1, 2, };
841
842 typedef struct Reloc Reloc;
843
844 struct Reloc
845 {
846 int n;
847 int t;
848 uchar *m;
849 ulong *a;
850 };
851
852 Reloc rels;
853
854 static void
grow(Reloc * r)855 grow(Reloc *r)
856 {
857 int t;
858 uchar *m, *nm;
859 ulong *a, *na;
860
861 t = r->t;
862 r->t += 64;
863 m = r->m;
864 a = r->a;
865 r->m = nm = malloc(r->t*sizeof(uchar));
866 r->a = na = malloc(r->t*sizeof(ulong));
867 memmove(nm, m, t*sizeof(uchar));
868 memmove(na, a, t*sizeof(ulong));
869 free(m);
870 free(a);
871 }
872
873 void
dynreloc(Sym * s,long v,int abs)874 dynreloc(Sym *s, long v, int abs)
875 {
876 int i, k, n;
877 uchar *m;
878 ulong *a;
879 Reloc *r;
880
881 if(v&3)
882 diag("bad relocation address");
883 v >>= 2;
884 if(s != S && s->type == SUNDEF)
885 k = abs ? ABSU : RELU;
886 else
887 k = abs ? ABSD : RELD;
888 /* Bprint(&bso, "R %s a=%ld(%lx) %d\n", s->name, a, a, k); */
889 k = modemap[k];
890 r = &rels;
891 n = r->n;
892 if(n >= r->t)
893 grow(r);
894 m = r->m;
895 a = r->a;
896 for(i = n; i > 0; i--){
897 if(v < a[i-1]){ /* happens occasionally for data */
898 m[i] = m[i-1];
899 a[i] = a[i-1];
900 }
901 else
902 break;
903 }
904 m[i] = k;
905 a[i] = v;
906 r->n++;
907 }
908
909 static int
sput(char * s)910 sput(char *s)
911 {
912 char *p;
913
914 p = s;
915 while(*s)
916 cput(*s++);
917 cput(0);
918 return s-p+1;
919 }
920
921 void
asmdyn()922 asmdyn()
923 {
924 int i, n, t, c;
925 Sym *s;
926 ulong la, ra, *a;
927 vlong off;
928 uchar *m;
929 Reloc *r;
930
931 cflush();
932 off = seek(cout, 0, 1);
933 lput(0);
934 t = 0;
935 lput(imports);
936 t += 4;
937 for(i = 0; i < NHASH; i++)
938 for(s = hash[i]; s != S; s = s->link)
939 if(s->type == SUNDEF){
940 lput(s->sig);
941 t += 4;
942 t += sput(s->name);
943 }
944
945 la = 0;
946 r = &rels;
947 n = r->n;
948 m = r->m;
949 a = r->a;
950 lput(n);
951 t += 4;
952 for(i = 0; i < n; i++){
953 ra = *a-la;
954 if(*a < la)
955 diag("bad relocation order");
956 if(ra < 256)
957 c = 0;
958 else if(ra < 65536)
959 c = 1;
960 else
961 c = 2;
962 cput((c<<6)|*m++);
963 t++;
964 if(c == 0){
965 cput(ra);
966 t++;
967 }
968 else if(c == 1){
969 wput(ra);
970 t += 2;
971 }
972 else{
973 lput(ra);
974 t += 4;
975 }
976 la = *a++;
977 }
978
979 cflush();
980 seek(cout, off, 0);
981 lput(t);
982
983 if(debug['v']){
984 Bprint(&bso, "import table entries = %d\n", imports);
985 Bprint(&bso, "export table entries = %d\n", exports);
986 }
987 }
988