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