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