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