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