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