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