1 #include "l.h"
2
3 void
dodata(void)4 dodata(void)
5 {
6 int i, t;
7 Sym *s;
8 Prog *p, *p1;
9 long orig, orig1, v;
10
11 if(debug['v'])
12 Bprint(&bso, "%5.2f dodata\n", cputime());
13 Bflush(&bso);
14 for(p = datap; p != P; p = p->link) {
15 s = p->from.sym;
16 if(p->as == ADYNT || p->as == AINIT)
17 s->value = dtype;
18 if(s->type == SBSS)
19 s->type = SDATA;
20 if(s->type != SDATA)
21 diag("initialize non-data (%d): %s\n%P",
22 s->type, s->name, p);
23 v = p->from.offset + p->reg;
24 if(v > s->value)
25 diag("initialize bounds (%ld): %s\n%P",
26 s->value, s->name, p);
27 }
28
29 /*
30 * pass 1
31 * assign 'small' variables to data segment
32 * (rational is that data segment is more easily
33 * addressed through offset on REGSB)
34 */
35 orig = 0;
36 for(i=0; i<NHASH; i++)
37 for(s = hash[i]; s != S; s = s->link) {
38 t = s->type;
39 if(t != SDATA && t != SBSS)
40 continue;
41 v = s->value;
42 if(v == 0) {
43 diag("%s: no size", s->name);
44 v = 1;
45 }
46 while(v & 3)
47 v++;
48 s->value = v;
49 if(v > MINSIZ)
50 continue;
51 if(v >= 8)
52 while(orig & 7)
53 orig++;
54 s->value = orig;
55 orig += v;
56 s->type = SDATA1;
57 }
58 orig1 = orig;
59
60 /*
61 * pass 2
62 * assign 'data' variables to data segment
63 */
64 for(i=0; i<NHASH; i++)
65 for(s = hash[i]; s != S; s = s->link) {
66 t = s->type;
67 if(t != SDATA) {
68 if(t == SDATA1)
69 s->type = SDATA;
70 continue;
71 }
72 v = s->value;
73 if(v >= 8)
74 while(orig & 7)
75 orig++;
76 s->value = orig;
77 orig += v;
78 s->type = SDATA1;
79 }
80
81 while(orig & 7)
82 orig++;
83 datsize = orig;
84
85 /*
86 * pass 3
87 * everything else to bss segment
88 */
89 for(i=0; i<NHASH; i++)
90 for(s = hash[i]; s != S; s = s->link) {
91 if(s->type != SBSS)
92 continue;
93 v = s->value;
94 if(v >= 8)
95 while(orig & 7)
96 orig++;
97 s->value = orig;
98 orig += v;
99 }
100 while(orig & 7)
101 orig++;
102 bsssize = orig-datsize;
103
104 /*
105 * pass 4
106 * add literals to all large values.
107 * at this time:
108 * small data is allocated DATA
109 * large data is allocated DATA1
110 * large bss is allocated BSS
111 * the new literals are loaded between
112 * small data and large data.
113 */
114 orig = 0;
115 for(p = firstp; p != P; p = p->link) {
116 if(p->as != AMOVW)
117 continue;
118 if(p->from.type != D_CONST)
119 continue;
120 if(s = p->from.sym) {
121 t = s->type;
122 if(t != SDATA && t != SDATA1 && t != SBSS)
123 continue;
124 t = p->from.name;
125 if(t != D_EXTERN && t != D_STATIC)
126 continue;
127 v = s->value + p->from.offset;
128 if(v >= 0 && v <= 0xffff)
129 continue;
130 if(!strcmp(s->name, "setSB"))
131 continue;
132 /* size should be 19 max */
133 if(strlen(s->name) >= 10) /* has loader address */
134 sprint(literal, "$%p.%lux", s, p->from.offset);
135 else
136 sprint(literal, "$%s.%d.%lux", s->name, s->version, p->from.offset);
137 } else {
138 if(p->from.name != D_NONE)
139 continue;
140 if(p->from.reg != NREG)
141 continue;
142 v = p->from.offset;
143 if(v >= -0x7fff-1 && v <= 0x7fff)
144 continue;
145 if(!(v & 0xffff))
146 continue;
147 if(v)
148 continue; /* quicker to build it than load it */
149 /* size should be 9 max */
150 sprint(literal, "$%lux", v);
151 }
152 s = lookup(literal, 0);
153 if(s->type == 0) {
154 s->type = SDATA;
155 s->value = orig1+orig;
156 orig += 4;
157 p1 = prg();
158 p1->as = ADATA;
159 p1->line = p->line;
160 p1->from.type = D_OREG;
161 p1->from.sym = s;
162 p1->from.name = D_EXTERN;
163 p1->reg = 4;
164 p1->to = p->from;
165 p1->link = datap;
166 datap = p1;
167 }
168 if(s->type != SDATA)
169 diag("literal not data: %s", s->name);
170 p->from.type = D_OREG;
171 p->from.sym = s;
172 p->from.name = D_EXTERN;
173 p->from.offset = 0;
174 continue;
175 }
176 while(orig & 7)
177 orig++;
178 /*
179 * pass 5
180 * re-adjust offsets
181 */
182 for(i=0; i<NHASH; i++)
183 for(s = hash[i]; s != S; s = s->link) {
184 t = s->type;
185 if(t == SBSS) {
186 s->value += orig;
187 continue;
188 }
189 if(t == SDATA1) {
190 s->type = SDATA;
191 s->value += orig;
192 continue;
193 }
194 }
195 datsize += orig;
196 xdefine("setSB", SDATA, 0L+BIG);
197 xdefine("bdata", SDATA, 0L);
198 xdefine("edata", SDATA, datsize);
199 xdefine("end", SBSS, datsize+bsssize);
200 xdefine("etext", STEXT, 0L);
201 }
202
203 void
undef(void)204 undef(void)
205 {
206 int i;
207 Sym *s;
208
209 for(i=0; i<NHASH; i++)
210 for(s = hash[i]; s != S; s = s->link)
211 if(s->type == SXREF)
212 diag("%s: not defined", s->name);
213 }
214
215 int
relinv(int a)216 relinv(int a)
217 {
218
219 switch(a) {
220 case ABEQ: return ABNE;
221 case ABNE: return ABEQ;
222
223 case ABGE: return ABLT;
224 case ABLT: return ABGE;
225
226 case ABGT: return ABLE;
227 case ABLE: return ABGT;
228
229 case ABVC: return ABVS;
230 case ABVS: return ABVC;
231 }
232 return 0;
233 }
234
235 void
follow(void)236 follow(void)
237 {
238
239 if(debug['v'])
240 Bprint(&bso, "%5.2f follow\n", cputime());
241 Bflush(&bso);
242
243 firstp = prg();
244 lastp = firstp;
245
246 xfol(textp);
247
248 firstp = firstp->link;
249 lastp->link = P;
250 }
251
252 void
xfol(Prog * p)253 xfol(Prog *p)
254 {
255 Prog *q, *r;
256 int a, b, i;
257
258 loop:
259 if(p == P)
260 return;
261 a = p->as;
262 if(a == ATEXT)
263 curtext = p;
264 if(a == ABR) {
265 q = p->cond;
266 if((p->mark&NOSCHED) || q && (q->mark&NOSCHED)){
267 p->mark |= FOLL;
268 lastp->link = p;
269 lastp = p;
270 p = p->link;
271 xfol(p);
272 p = q;
273 if(p && !(p->mark & FOLL))
274 goto loop;
275 return;
276 }
277 if(q != P) {
278 p->mark |= FOLL;
279 p = q;
280 if(!(p->mark & FOLL))
281 goto loop;
282 }
283 }
284 if(p->mark & FOLL) {
285 for(i=0,q=p; i<4; i++,q=q->link) {
286 if(q == lastp || (q->mark&NOSCHED))
287 break;
288 b = 0; /* set */
289 a = q->as;
290 if(a == ANOP) {
291 i--;
292 continue;
293 }
294 if(a == ABR || a == ARETURN || a == ARFI || a == ARFCI)
295 goto copy;
296 if(!q->cond || (q->cond->mark&FOLL))
297 continue;
298 b = relinv(a);
299 if(!b)
300 continue;
301 copy:
302 for(;;) {
303 r = prg();
304 *r = *p;
305 if(!(r->mark&FOLL))
306 print("cant happen 1\n");
307 r->mark |= FOLL;
308 if(p != q) {
309 p = p->link;
310 lastp->link = r;
311 lastp = r;
312 continue;
313 }
314 lastp->link = r;
315 lastp = r;
316 if(a == ABR || a == ARETURN || a == ARFI || a == ARFCI)
317 return;
318 r->as = b;
319 r->cond = p->link;
320 r->link = p->cond;
321 if(!(r->link->mark&FOLL))
322 xfol(r->link);
323 if(!(r->cond->mark&FOLL))
324 print("cant happen 2\n");
325 return;
326 }
327 }
328
329 a = ABR;
330 q = prg();
331 q->as = a;
332 q->line = p->line;
333 q->to.type = D_BRANCH;
334 q->to.offset = p->pc;
335 q->cond = p;
336 p = q;
337 }
338 p->mark |= FOLL;
339 lastp->link = p;
340 lastp = p;
341 if(a == ABR || a == ARETURN || a == ARFI || a == ARFCI){
342 if(p->mark & NOSCHED){
343 p = p->link;
344 goto loop;
345 }
346 return;
347 }
348 if(p->cond != P)
349 if(a != ABL && p->link != P) {
350 xfol(p->link);
351 p = p->cond;
352 if(p == P || (p->mark&FOLL))
353 return;
354 goto loop;
355 }
356 p = p->link;
357 goto loop;
358 }
359
360 void
patch(void)361 patch(void)
362 {
363 long c, vexit;
364 Prog *p, *q;
365 Sym *s;
366 int a;
367
368 if(debug['v'])
369 Bprint(&bso, "%5.2f patch\n", cputime());
370 Bflush(&bso);
371 mkfwd();
372 s = lookup("exit", 0);
373 vexit = s->value;
374 for(p = firstp; p != P; p = p->link) {
375 a = p->as;
376 if(a == ATEXT)
377 curtext = p;
378 if((a == ABL || a == ARETURN) && p->to.sym != S) {
379 s = p->to.sym;
380 if(s->type != STEXT && s->type != SUNDEF) {
381 diag("undefined: %s\n%P", s->name, p);
382 s->type = STEXT;
383 s->value = vexit;
384 }
385 if(s->type == SUNDEF){
386 p->to.offset = 0;
387 p->cond = UP;
388 }
389 else
390 p->to.offset = s->value;
391 p->to.type = D_BRANCH;
392 }
393 if(p->to.type != D_BRANCH || p->cond == UP)
394 continue;
395 c = p->to.offset;
396 for(q = firstp; q != P;) {
397 if(q->forwd != P)
398 if(c >= q->forwd->pc) {
399 q = q->forwd;
400 continue;
401 }
402 if(c == q->pc)
403 break;
404 q = q->link;
405 }
406 if(q == P) {
407 diag("branch out of range %ld\n%P", c, p);
408 p->to.type = D_NONE;
409 }
410 p->cond = q;
411 }
412
413 for(p = firstp; p != P; p = p->link) {
414 if(p->as == ATEXT)
415 curtext = p;
416 p->mark = 0; /* initialization for follow */
417 if(p->cond != P && p->cond != UP) {
418 p->cond = brloop(p->cond);
419 if(p->cond != P)
420 if(p->to.type == D_BRANCH)
421 p->to.offset = p->cond->pc;
422 }
423 }
424 }
425
426 #define LOG 5
427 void
mkfwd(void)428 mkfwd(void)
429 {
430 Prog *p;
431 long dwn[LOG], cnt[LOG], i;
432 Prog *lst[LOG];
433
434 for(i=0; i<LOG; i++) {
435 if(i == 0)
436 cnt[i] = 1; else
437 cnt[i] = LOG * cnt[i-1];
438 dwn[i] = 1;
439 lst[i] = P;
440 }
441 i = 0;
442 for(p = firstp; p != P; p = p->link) {
443 if(p->as == ATEXT)
444 curtext = p;
445 i--;
446 if(i < 0)
447 i = LOG-1;
448 p->forwd = P;
449 dwn[i]--;
450 if(dwn[i] <= 0) {
451 dwn[i] = cnt[i];
452 if(lst[i] != P)
453 lst[i]->forwd = p;
454 lst[i] = p;
455 }
456 }
457 }
458
459 Prog*
brloop(Prog * p)460 brloop(Prog *p)
461 {
462 Prog *q;
463 int c;
464
465 for(c=0; p!=P;) {
466 if(p->as != ABR || (p->mark&NOSCHED))
467 return p;
468 q = p->cond;
469 if(q <= p) {
470 c++;
471 if(q == p || c > 5000)
472 break;
473 }
474 p = q;
475 }
476 return P;
477 }
478
479 long
atolwhex(char * s)480 atolwhex(char *s)
481 {
482 long n;
483 int f;
484
485 n = 0;
486 f = 0;
487 while(*s == ' ' || *s == '\t')
488 s++;
489 if(*s == '-' || *s == '+') {
490 if(*s++ == '-')
491 f = 1;
492 while(*s == ' ' || *s == '\t')
493 s++;
494 }
495 if(s[0]=='0' && s[1]){
496 if(s[1]=='x' || s[1]=='X'){
497 s += 2;
498 for(;;){
499 if(*s >= '0' && *s <= '9')
500 n = n*16 + *s++ - '0';
501 else if(*s >= 'a' && *s <= 'f')
502 n = n*16 + *s++ - 'a' + 10;
503 else if(*s >= 'A' && *s <= 'F')
504 n = n*16 + *s++ - 'A' + 10;
505 else
506 break;
507 }
508 } else
509 while(*s >= '0' && *s <= '7')
510 n = n*8 + *s++ - '0';
511 } else
512 while(*s >= '0' && *s <= '9')
513 n = n*10 + *s++ - '0';
514 if(f)
515 n = -n;
516 return n;
517 }
518
519 long
rnd(long v,long r)520 rnd(long v, long r)
521 {
522 long c;
523
524 if(r <= 0)
525 return v;
526 v += r - 1;
527 c = v % r;
528 if(c < 0)
529 c += r;
530 v -= c;
531 return v;
532 }
533
534 void
import(void)535 import(void)
536 {
537 int i;
538 Sym *s;
539
540 for(i = 0; i < NHASH; i++)
541 for(s = hash[i]; s != S; s = s->link)
542 if(s->sig != 0 && s->type == SXREF && (nimports == 0 || s->subtype == SIMPORT)){
543 undefsym(s);
544 Bprint(&bso, "IMPORT: %s sig=%lux v=%ld\n", s->name, s->sig, s->value);
545 }
546 }
547
548 void
ckoff(Sym * s,long v)549 ckoff(Sym *s, long v)
550 {
551 if(v < 0 || v >= 1<<Roffset)
552 diag("relocation offset %ld for %s out of range", v, s->name);
553 }
554
555 static Prog*
newdata(Sym * s,int o,int w,int t)556 newdata(Sym *s, int o, int w, int t)
557 {
558 Prog *p;
559
560 p = prg();
561 p->link = datap;
562 datap = p;
563 p->as = ADATA;
564 p->reg = w;
565 p->from.type = D_OREG;
566 p->from.name = t;
567 p->from.sym = s;
568 p->from.offset = o;
569 p->to.type = D_CONST;
570 p->to.name = D_NONE;
571 return p;
572 }
573
574 void
export(void)575 export(void)
576 {
577 int i, j, n, off, nb, sv, ne;
578 Sym *s, *et, *str, **esyms;
579 Prog *p;
580 char buf[NSNAME], *t;
581
582 n = 0;
583 for(i = 0; i < NHASH; i++)
584 for(s = hash[i]; s != S; s = s->link)
585 if(s->sig != 0 && s->type != SXREF && s->type != SUNDEF && (nexports == 0 || s->subtype == SEXPORT))
586 n++;
587 esyms = malloc(n*sizeof(Sym*));
588 ne = n;
589 n = 0;
590 for(i = 0; i < NHASH; i++)
591 for(s = hash[i]; s != S; s = s->link)
592 if(s->sig != 0 && s->type != SXREF && s->type != SUNDEF && (nexports == 0 || s->subtype == SEXPORT))
593 esyms[n++] = s;
594 for(i = 0; i < ne-1; i++)
595 for(j = i+1; j < ne; j++)
596 if(strcmp(esyms[i]->name, esyms[j]->name) > 0){
597 s = esyms[i];
598 esyms[i] = esyms[j];
599 esyms[j] = s;
600 }
601
602 nb = 0;
603 off = 0;
604 et = lookup(EXPTAB, 0);
605 if(et->type != 0 && et->type != SXREF)
606 diag("%s already defined", EXPTAB);
607 et->type = SDATA;
608 str = lookup(".string", 0);
609 if(str->type == 0)
610 str->type = SDATA;
611 sv = str->value;
612 for(i = 0; i < ne; i++){
613 s = esyms[i];
614 Bprint(&bso, "EXPORT: %s sig=%lux t=%d\n", s->name, s->sig, s->type);
615
616 /* signature */
617 p = newdata(et, off, sizeof(long), D_EXTERN);
618 off += sizeof(long);
619 p->to.offset = s->sig;
620
621 /* address */
622 p = newdata(et, off, sizeof(long), D_EXTERN);
623 off += sizeof(long);
624 p->to.name = D_EXTERN;
625 p->to.sym = s;
626
627 /* string */
628 t = s->name;
629 n = strlen(t)+1;
630 for(;;){
631 buf[nb++] = *t;
632 sv++;
633 if(nb >= NSNAME){
634 p = newdata(str, sv-NSNAME, NSNAME, D_STATIC);
635 p->to.type = D_SCONST;
636 memmove(p->to.sval, buf, NSNAME);
637 nb = 0;
638 }
639 if(*t++ == 0)
640 break;
641 }
642
643 /* name */
644 p = newdata(et, off, sizeof(long), D_EXTERN);
645 off += sizeof(long);
646 p->to.name = D_STATIC;
647 p->to.sym = str;
648 p->to.offset = sv-n;
649 }
650
651 if(nb > 0){
652 p = newdata(str, sv-nb, nb, D_STATIC);
653 p->to.type = D_SCONST;
654 memmove(p->to.sval, buf, nb);
655 }
656
657 for(i = 0; i < 3; i++){
658 newdata(et, off, sizeof(long), D_EXTERN);
659 off += sizeof(long);
660 }
661 et->value = off;
662 if(sv == 0)
663 sv = 1;
664 str->value = sv;
665 exports = ne;
666 free(esyms);
667 }
668