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, "$%p.%lux", 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 || a == ARFCI) 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 || a == ARFCI) 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 || a == ARFCI){ 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 && s->type != SUNDEF) { 381 diag("undefined: %s\n%P", s->name, p); 382 s->type = STEXT; 383 s->value = vexit; 384 } 385 if(s->type == SUNDEF){ 386 p->to.offset = 0; 387 p->cond = UP; 388 } 389 else 390 p->to.offset = s->value; 391 p->to.type = D_BRANCH; 392 } 393 if(p->to.type != D_BRANCH || p->cond == UP) 394 continue; 395 c = p->to.offset; 396 for(q = firstp; q != P;) { 397 if(q->forwd != P) 398 if(c >= q->forwd->pc) { 399 q = q->forwd; 400 continue; 401 } 402 if(c == q->pc) 403 break; 404 q = q->link; 405 } 406 if(q == P) { 407 diag("branch out of range %ld\n%P", c, p); 408 p->to.type = D_NONE; 409 } 410 p->cond = q; 411 } 412 413 for(p = firstp; p != P; p = p->link) { 414 if(p->as == ATEXT) 415 curtext = p; 416 p->mark = 0; /* initialization for follow */ 417 if(p->cond != P && p->cond != UP) { 418 p->cond = brloop(p->cond); 419 if(p->cond != P) 420 if(p->to.type == D_BRANCH) 421 p->to.offset = p->cond->pc; 422 } 423 } 424 } 425 426 #define LOG 5 427 void 428 mkfwd(void) 429 { 430 Prog *p; 431 long dwn[LOG], cnt[LOG], i; 432 Prog *lst[LOG]; 433 434 for(i=0; i<LOG; i++) { 435 if(i == 0) 436 cnt[i] = 1; else 437 cnt[i] = LOG * cnt[i-1]; 438 dwn[i] = 1; 439 lst[i] = P; 440 } 441 i = 0; 442 for(p = firstp; p != P; p = p->link) { 443 if(p->as == ATEXT) 444 curtext = p; 445 i--; 446 if(i < 0) 447 i = LOG-1; 448 p->forwd = P; 449 dwn[i]--; 450 if(dwn[i] <= 0) { 451 dwn[i] = cnt[i]; 452 if(lst[i] != P) 453 lst[i]->forwd = p; 454 lst[i] = p; 455 } 456 } 457 } 458 459 Prog* 460 brloop(Prog *p) 461 { 462 Prog *q; 463 int c; 464 465 for(c=0; p!=P;) { 466 if(p->as != ABR || (p->mark&NOSCHED)) 467 return p; 468 q = p->cond; 469 if(q <= p) { 470 c++; 471 if(q == p || c > 5000) 472 break; 473 } 474 p = q; 475 } 476 return P; 477 } 478 479 long 480 atolwhex(char *s) 481 { 482 long n; 483 int f; 484 485 n = 0; 486 f = 0; 487 while(*s == ' ' || *s == '\t') 488 s++; 489 if(*s == '-' || *s == '+') { 490 if(*s++ == '-') 491 f = 1; 492 while(*s == ' ' || *s == '\t') 493 s++; 494 } 495 if(s[0]=='0' && s[1]){ 496 if(s[1]=='x' || s[1]=='X'){ 497 s += 2; 498 for(;;){ 499 if(*s >= '0' && *s <= '9') 500 n = n*16 + *s++ - '0'; 501 else if(*s >= 'a' && *s <= 'f') 502 n = n*16 + *s++ - 'a' + 10; 503 else if(*s >= 'A' && *s <= 'F') 504 n = n*16 + *s++ - 'A' + 10; 505 else 506 break; 507 } 508 } else 509 while(*s >= '0' && *s <= '7') 510 n = n*8 + *s++ - '0'; 511 } else 512 while(*s >= '0' && *s <= '9') 513 n = n*10 + *s++ - '0'; 514 if(f) 515 n = -n; 516 return n; 517 } 518 519 long 520 rnd(long v, long r) 521 { 522 long c; 523 524 if(r <= 0) 525 return v; 526 v += r - 1; 527 c = v % r; 528 if(c < 0) 529 c += r; 530 v -= c; 531 return v; 532 } 533 534 void 535 import(void) 536 { 537 int i; 538 Sym *s; 539 540 for(i = 0; i < NHASH; i++) 541 for(s = hash[i]; s != S; s = s->link) 542 if(s->sig != 0 && s->type == SXREF && (nimports == 0 || s->subtype == SIMPORT)){ 543 undefsym(s); 544 Bprint(&bso, "IMPORT: %s sig=%lux v=%ld\n", s->name, s->sig, s->value); 545 } 546 } 547 548 void 549 ckoff(Sym *s, long v) 550 { 551 if(v < 0 || v >= 1<<Roffset) 552 diag("relocation offset %ld for %s out of range", v, s->name); 553 } 554 555 static Prog* 556 newdata(Sym *s, int o, int w, int t) 557 { 558 Prog *p; 559 560 p = prg(); 561 p->link = datap; 562 datap = p; 563 p->as = ADATA; 564 p->reg = w; 565 p->from.type = D_OREG; 566 p->from.name = t; 567 p->from.sym = s; 568 p->from.offset = o; 569 p->to.type = D_CONST; 570 p->to.name = D_NONE; 571 return p; 572 } 573 574 void 575 export(void) 576 { 577 int i, j, n, off, nb, sv, ne; 578 Sym *s, *et, *str, **esyms; 579 Prog *p; 580 char buf[NSNAME], *t; 581 582 n = 0; 583 for(i = 0; i < NHASH; i++) 584 for(s = hash[i]; s != S; s = s->link) 585 if(s->sig != 0 && s->type != SXREF && s->type != SUNDEF && (nexports == 0 || s->subtype == SEXPORT)) 586 n++; 587 esyms = malloc(n*sizeof(Sym*)); 588 ne = n; 589 n = 0; 590 for(i = 0; i < NHASH; i++) 591 for(s = hash[i]; s != S; s = s->link) 592 if(s->sig != 0 && s->type != SXREF && s->type != SUNDEF && (nexports == 0 || s->subtype == SEXPORT)) 593 esyms[n++] = s; 594 for(i = 0; i < ne-1; i++) 595 for(j = i+1; j < ne; j++) 596 if(strcmp(esyms[i]->name, esyms[j]->name) > 0){ 597 s = esyms[i]; 598 esyms[i] = esyms[j]; 599 esyms[j] = s; 600 } 601 602 nb = 0; 603 off = 0; 604 et = lookup(EXPTAB, 0); 605 if(et->type != 0 && et->type != SXREF) 606 diag("%s already defined", EXPTAB); 607 et->type = SDATA; 608 str = lookup(".string", 0); 609 if(str->type == 0) 610 str->type = SDATA; 611 sv = str->value; 612 for(i = 0; i < ne; i++){ 613 s = esyms[i]; 614 Bprint(&bso, "EXPORT: %s sig=%lux t=%d\n", s->name, s->sig, s->type); 615 616 /* signature */ 617 p = newdata(et, off, sizeof(long), D_EXTERN); 618 off += sizeof(long); 619 p->to.offset = s->sig; 620 621 /* address */ 622 p = newdata(et, off, sizeof(long), D_EXTERN); 623 off += sizeof(long); 624 p->to.name = D_EXTERN; 625 p->to.sym = s; 626 627 /* string */ 628 t = s->name; 629 n = strlen(t)+1; 630 for(;;){ 631 buf[nb++] = *t; 632 sv++; 633 if(nb >= NSNAME){ 634 p = newdata(str, sv-NSNAME, NSNAME, D_STATIC); 635 p->to.type = D_SCONST; 636 memmove(p->to.sval, buf, NSNAME); 637 nb = 0; 638 } 639 if(*t++ == 0) 640 break; 641 } 642 643 /* name */ 644 p = newdata(et, off, sizeof(long), D_EXTERN); 645 off += sizeof(long); 646 p->to.name = D_STATIC; 647 p->to.sym = str; 648 p->to.offset = sv-n; 649 } 650 651 if(nb > 0){ 652 p = newdata(str, sv-nb, nb, D_STATIC); 653 p->to.type = D_SCONST; 654 memmove(p->to.sval, buf, nb); 655 } 656 657 for(i = 0; i < 3; i++){ 658 newdata(et, off, sizeof(long), D_EXTERN); 659 off += sizeof(long); 660 } 661 et->value = off; 662 if(sv == 0) 663 sv = 1; 664 str->value = sv; 665 exports = ne; 666 free(esyms); 667 } 668