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 && v <= 0xffff)
144 continue;
145 if(!(v & 0xffff))
146 continue;
147 /* size should be 9 max */
148 sprint(literal, "$%lux", v);
149 }
150 s = lookup(literal, 0);
151 if(s->type == 0) {
152 s->type = SDATA;
153 s->value = orig1+orig;
154 orig += 4;
155 p1 = prg();
156 p1->as = ADATA;
157 p1->line = p->line;
158 p1->from.type = D_OREG;
159 p1->from.sym = s;
160 p1->from.name = D_EXTERN;
161 p1->reg = 4;
162 p1->to = p->from;
163 p1->link = datap;
164 datap = p1;
165 }
166 if(s->type != SDATA)
167 diag("literal not data: %s", s->name);
168 p->from.type = D_OREG;
169 p->from.sym = s;
170 p->from.name = D_EXTERN;
171 p->from.offset = 0;
172 continue;
173 }
174 while(orig & 7)
175 orig++;
176 /*
177 * pass 5
178 * re-adjust offsets
179 */
180 for(i=0; i<NHASH; i++)
181 for(s = hash[i]; s != S; s = s->link) {
182 t = s->type;
183 if(t == SBSS) {
184 s->value += orig;
185 continue;
186 }
187 if(t == SDATA1) {
188 s->type = SDATA;
189 s->value += orig;
190 continue;
191 }
192 }
193 datsize += orig;
194 xdefine("setSB", SDATA, 0L+BIG);
195 xdefine("bdata", SDATA, 0L);
196 xdefine("edata", SDATA, datsize);
197 xdefine("end", SBSS, datsize+bsssize);
198 xdefine("etext", STEXT, 0L);
199 }
200
201 void
undef(void)202 undef(void)
203 {
204 int i;
205 Sym *s;
206
207 for(i=0; i<NHASH; i++)
208 for(s = hash[i]; s != S; s = s->link)
209 if(s->type == SXREF)
210 diag("%s: not defined", s->name);
211 }
212
213 int
relinv(int a)214 relinv(int a)
215 {
216
217 switch(a) {
218 case ABA: return ABN;
219 case ABN: return ABA;
220
221 case ABE: return ABNE;
222 case ABNE: return ABE;
223
224 case ABLE: return ABG;
225 case ABG: return ABLE;
226
227 case ABL: return ABGE;
228 case ABGE: return ABL;
229
230 case ABLEU: return ABGU;
231 case ABGU: return ABLEU;
232
233 case ABCS: return ABCC;
234 case ABCC: return ABCS;
235
236 case ABNEG: return ABPOS;
237 case ABPOS: return ABNEG;
238
239 case ABVC: return ABVS;
240 case ABVS: return ABVC;
241
242 case AFBN: return AFBA;
243 case AFBA: return AFBN;
244
245 case AFBE: return AFBLG;
246 case AFBLG: return AFBE;
247
248 case AFBG: return AFBLE;
249 case AFBLE: return AFBG;
250
251 case AFBGE: return AFBL;
252 case AFBL: return AFBGE;
253
254 /* unordered fp compares have no inverse
255 that traps in the same way */
256 }
257 return 0;
258 }
259
260 void
follow(void)261 follow(void)
262 {
263
264 if(debug['v'])
265 Bprint(&bso, "%5.2f follow\n", cputime());
266 Bflush(&bso);
267
268 firstp = prg();
269 lastp = firstp;
270
271 xfol(textp);
272
273 firstp = firstp->link;
274 lastp->link = P;
275 }
276
277 void
xfol(Prog * p)278 xfol(Prog *p)
279 {
280 Prog *q, *r;
281 int a, b, i;
282
283 loop:
284 if(p == P)
285 return;
286 a = p->as;
287 if(a == ATEXT)
288 curtext = p;
289 if(a == AJMP) {
290 q = p->cond;
291 if((p->mark&NOSCHED) || q && (q->mark&NOSCHED)){
292 p->mark |= FOLL;
293 lastp->link = p;
294 lastp = p;
295 p = p->link;
296 xfol(p);
297 p = q;
298 if(p && !(p->mark & FOLL))
299 goto loop;
300 return;
301 }
302 if(q != P) {
303 p->mark |= FOLL;
304 p = q;
305 if(!(p->mark & FOLL))
306 goto loop;
307 }
308 }
309 if(p->mark & FOLL) {
310 for(i=0,q=p; i<4; i++,q=q->link) {
311 if(q == lastp || (q->mark&NOSCHED))
312 break;
313 b = 0; /* set */
314 a = q->as;
315 if(a == ANOP) {
316 i--;
317 continue;
318 }
319 if(a == AJMP || a == ARETURN || a == ARETT)
320 goto copy;
321 if(!q->cond || (q->cond->mark&FOLL))
322 continue;
323 b = relinv(a);
324 if(!b)
325 continue;
326 copy:
327 for(;;) {
328 r = prg();
329 *r = *p;
330 if(!(r->mark&FOLL))
331 print("cant happen 1\n");
332 r->mark |= FOLL;
333 if(p != q) {
334 p = p->link;
335 lastp->link = r;
336 lastp = r;
337 continue;
338 }
339 lastp->link = r;
340 lastp = r;
341 if(a == AJMP || a == ARETURN || a == ARETT)
342 return;
343 r->as = b;
344 r->cond = p->link;
345 r->link = p->cond;
346 if(!(r->link->mark&FOLL))
347 xfol(r->link);
348 if(!(r->cond->mark&FOLL))
349 print("cant happen 2\n");
350 return;
351 }
352 }
353
354 a = AJMP;
355 q = prg();
356 q->as = a;
357 q->line = p->line;
358 q->to.type = D_BRANCH;
359 q->to.offset = p->pc;
360 q->cond = p;
361 p = q;
362 }
363 p->mark |= FOLL;
364 lastp->link = p;
365 lastp = p;
366 if(a == AJMP || a == ARETURN || a == ARETT){
367 if(p->mark & NOSCHED){
368 p = p->link;
369 goto loop;
370 }
371 return;
372 }
373 if(p->cond != P)
374 if(a != AJMPL && p->link != P) {
375 xfol(p->link);
376 p = p->cond;
377 if(p == P || (p->mark&FOLL))
378 return;
379 goto loop;
380 }
381 p = p->link;
382 goto loop;
383 }
384
385 void
patch(void)386 patch(void)
387 {
388 long c, vexit;
389 Prog *p, *q;
390 Sym *s;
391 int a;
392
393 if(debug['v'])
394 Bprint(&bso, "%5.2f patch\n", cputime());
395 Bflush(&bso);
396 mkfwd();
397 s = lookup("exit", 0);
398 vexit = s->value;
399 for(p = firstp; p != P; p = p->link) {
400 a = p->as;
401 if(a == ATEXT)
402 curtext = p;
403 if((a == AJMPL || a == ARETURN) && p->to.sym != S) {
404 s = p->to.sym;
405 if(s->type != STEXT) {
406 diag("undefined: %s\n%P", s->name, p);
407 s->type = STEXT;
408 s->value = vexit;
409 }
410 p->to.offset = s->value;
411 p->to.type = D_BRANCH;
412 }
413 if(p->to.type != D_BRANCH)
414 continue;
415 c = p->to.offset;
416 for(q = firstp; q != P;) {
417 if(q->forwd != P)
418 if(c >= q->forwd->pc) {
419 q = q->forwd;
420 continue;
421 }
422 if(c == q->pc)
423 break;
424 q = q->link;
425 }
426 if(q == P) {
427 diag("branch out of range %ld\n%P", c, p);
428 p->to.type = D_NONE;
429 }
430 p->cond = q;
431 }
432
433 for(p = firstp; p != P; p = p->link) {
434 if(p->as == ATEXT)
435 curtext = p;
436 if(p->cond != P) {
437 p->cond = brloop(p->cond);
438 if(p->cond != P)
439 if(p->to.type == D_BRANCH)
440 p->to.offset = p->cond->pc;
441 }
442 }
443 }
444
445 #define LOG 5
446 void
mkfwd(void)447 mkfwd(void)
448 {
449 Prog *p;
450 long dwn[LOG], cnt[LOG], i;
451 Prog *lst[LOG];
452
453 for(i=0; i<LOG; i++) {
454 if(i == 0)
455 cnt[i] = 1; else
456 cnt[i] = LOG * cnt[i-1];
457 dwn[i] = 1;
458 lst[i] = P;
459 }
460 i = 0;
461 for(p = firstp; p != P; p = p->link) {
462 if(p->as == ATEXT)
463 curtext = p;
464 i--;
465 if(i < 0)
466 i = LOG-1;
467 p->forwd = P;
468 dwn[i]--;
469 if(dwn[i] <= 0) {
470 dwn[i] = cnt[i];
471 if(lst[i] != P)
472 lst[i]->forwd = p;
473 lst[i] = p;
474 }
475 }
476 }
477
478 Prog*
brloop(Prog * p)479 brloop(Prog *p)
480 {
481 Prog *q;
482 int c;
483
484 for(c=0; p!=P;) {
485 if(p->as != AJMP || (p->mark&NOSCHED))
486 return p;
487 q = p->cond;
488 if(q <= p) {
489 c++;
490 if(q == p || c > 5000)
491 break;
492 }
493 p = q;
494 }
495 return P;
496 }
497
498 long
atolwhex(char * s)499 atolwhex(char *s)
500 {
501 long n;
502 int f;
503
504 n = 0;
505 f = 0;
506 while(*s == ' ' || *s == '\t')
507 s++;
508 if(*s == '-' || *s == '+') {
509 if(*s++ == '-')
510 f = 1;
511 while(*s == ' ' || *s == '\t')
512 s++;
513 }
514 if(s[0]=='0' && s[1]){
515 if(s[1]=='x' || s[1]=='X'){
516 s += 2;
517 for(;;){
518 if(*s >= '0' && *s <= '9')
519 n = n*16 + *s++ - '0';
520 else if(*s >= 'a' && *s <= 'f')
521 n = n*16 + *s++ - 'a' + 10;
522 else if(*s >= 'A' && *s <= 'F')
523 n = n*16 + *s++ - 'A' + 10;
524 else
525 break;
526 }
527 } else
528 while(*s >= '0' && *s <= '7')
529 n = n*8 + *s++ - '0';
530 } else
531 while(*s >= '0' && *s <= '9')
532 n = n*10 + *s++ - '0';
533 if(f)
534 n = -n;
535 return n;
536 }
537
538 long
rnd(long v,long r)539 rnd(long v, long r)
540 {
541 long c;
542
543 if(r <= 0)
544 return v;
545 v += r - 1;
546 c = v % r;
547 if(c < 0)
548 c += r;
549 v -= c;
550 return v;
551 }
552