1 #include "l.h" 2 3 void 4 dodata(void) 5 { 6 int i, t; 7 Sym *s; 8 Prog *p; 9 long orig, 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 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 R12) 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 67 /* 68 * pass 2 69 * assign large 'data' variables to data segment 70 */ 71 for(i=0; i<NHASH; i++) 72 for(s = hash[i]; s != S; s = s->link) { 73 t = s->type; 74 if(t != SDATA) { 75 if(t == SDATA1) 76 s->type = SDATA; 77 continue; 78 } 79 v = s->value; 80 s->value = orig; 81 orig += v; 82 } 83 84 while(orig & 7) 85 orig++; 86 datsize = orig; 87 88 /* 89 * pass 3 90 * everything else to bss segment 91 */ 92 for(i=0; i<NHASH; i++) 93 for(s = hash[i]; s != S; s = s->link) { 94 if(s->type != SBSS) 95 continue; 96 v = s->value; 97 s->value = orig; 98 orig += v; 99 } 100 while(orig & 7) 101 orig++; 102 bsssize = orig-datsize; 103 104 xdefine("setR12", SDATA, 0L+BIG); 105 xdefine("bdata", SDATA, 0L); 106 xdefine("edata", SDATA, datsize); 107 xdefine("end", SBSS, datsize+bsssize); 108 xdefine("etext", STEXT, 0L); 109 } 110 111 void 112 undef(void) 113 { 114 int i; 115 Sym *s; 116 117 for(i=0; i<NHASH; i++) 118 for(s = hash[i]; s != S; s = s->link) 119 if(s->type == SXREF) 120 diag("%s: not defined", s->name); 121 } 122 123 Prog* 124 brchain(Prog *p) 125 { 126 int i; 127 128 for(i=0; i<20; i++) { 129 if(p == P || p->as != AB) 130 return p; 131 p = p->cond; 132 } 133 return P; 134 } 135 136 int 137 relinv(int a) 138 { 139 switch(a) { 140 case ABEQ: return ABNE; 141 case ABNE: return ABEQ; 142 case ABCS: return ABCC; 143 case ABHS: return ABLO; 144 case ABCC: return ABCS; 145 case ABLO: return ABHS; 146 case ABMI: return ABPL; 147 case ABPL: return ABMI; 148 case ABVS: return ABVC; 149 case ABVC: return ABVS; 150 case ABHI: return ABLS; 151 case ABLS: return ABHI; 152 case ABGE: return ABLT; 153 case ABLT: return ABGE; 154 case ABGT: return ABLE; 155 case ABLE: return ABGT; 156 } 157 diag("unknown relation: %s", anames[a]); 158 return a; 159 } 160 161 void 162 follow(void) 163 { 164 if(debug['v']) 165 Bprint(&bso, "%5.2f follow\n", cputime()); 166 Bflush(&bso); 167 168 firstp = prg(); 169 lastp = firstp; 170 xfol(textp); 171 172 firstp = firstp->link; 173 lastp->link = P; 174 } 175 176 void 177 xfol(Prog *p) 178 { 179 Prog *q, *r; 180 int a, i; 181 182 loop: 183 if(p == P) 184 return; 185 a = p->as; 186 if(a == ATEXT) 187 curtext = p; 188 if(a == AB) { 189 q = p->cond; 190 if(q != P) { 191 p->mark |= FOLL; 192 p = q; 193 if(!(p->mark & FOLL)) 194 goto loop; 195 } 196 } 197 if(p->mark & FOLL) { 198 for(i=0,q=p; i<4; i++,q=q->link) { 199 if(q == lastp) 200 break; 201 a = q->as; 202 if(a == ANOP) { 203 i--; 204 continue; 205 } 206 if(a == AB || (a == ARET && q->scond == 14) || a == ARFE) 207 goto copy; 208 if(!q->cond || (q->cond->mark&FOLL)) 209 continue; 210 if(a != ABEQ && a != ABNE) 211 continue; 212 copy: 213 for(;;) { 214 r = prg(); 215 *r = *p; 216 if(!(r->mark&FOLL)) 217 print("cant happen 1\n"); 218 r->mark |= FOLL; 219 if(p != q) { 220 p = p->link; 221 lastp->link = r; 222 lastp = r; 223 continue; 224 } 225 lastp->link = r; 226 lastp = r; 227 if(a == AB || (a == ARET && q->scond == 14) || a == ARFE) 228 return; 229 r->as = ABNE; 230 if(a == ABNE) 231 r->as = ABEQ; 232 r->cond = p->link; 233 r->link = p->cond; 234 if(!(r->link->mark&FOLL)) 235 xfol(r->link); 236 if(!(r->cond->mark&FOLL)) 237 print("cant happen 2\n"); 238 return; 239 } 240 } 241 a = AB; 242 q = prg(); 243 q->as = a; 244 q->line = p->line; 245 q->to.type = D_BRANCH; 246 q->to.offset = p->pc; 247 q->cond = p; 248 p = q; 249 } 250 p->mark |= FOLL; 251 lastp->link = p; 252 lastp = p; 253 if(a == AB || (a == ARET && p->scond == 14) || a == ARFE){ 254 return; 255 } 256 if(p->cond != P) 257 if(a != ABL && p->link != P) { 258 q = brchain(p->link); 259 if(a != ATEXT && a != ABCASE) 260 if(q != P && (q->mark&FOLL)) { 261 p->as = relinv(a); 262 p->link = p->cond; 263 p->cond = q; 264 } 265 xfol(p->link); 266 q = brchain(p->cond); 267 if(q == P) 268 q = p->cond; 269 if(q->mark&FOLL) { 270 p->cond = q; 271 return; 272 } 273 p = q; 274 goto loop; 275 } 276 p = p->link; 277 goto loop; 278 } 279 280 void 281 patch(void) 282 { 283 long c, vexit; 284 Prog *p, *q; 285 Sym *s; 286 int a; 287 288 if(debug['v']) 289 Bprint(&bso, "%5.2f patch\n", cputime()); 290 Bflush(&bso); 291 mkfwd(); 292 s = lookup("exit", 0); 293 vexit = s->value; 294 for(p = firstp; p != P; p = p->link) { 295 a = p->as; 296 if(a == ATEXT) 297 curtext = p; 298 if((a == ABL || a == AB || a == ARET) && 299 p->to.type != D_BRANCH && p->to.sym != S) { 300 s = p->to.sym; 301 switch(s->type) { 302 default: 303 diag("undefined: %s\n%P", s->name, p); 304 s->type = STEXT; 305 s->value = vexit; 306 break; 307 case STEXT: 308 p->to.offset = s->value; 309 p->to.type = D_BRANCH; 310 break; 311 case SUNDEF: 312 if(p->as != ABL) 313 diag("help: SUNDEF in AB || ARET"); 314 p->to.offset = 0; 315 p->to.type = D_BRANCH; 316 p->cond = UP; 317 break; 318 } 319 } 320 if(p->to.type != D_BRANCH || p->cond == UP) 321 continue; 322 c = p->to.offset; 323 for(q = firstp; q != P;) { 324 if(q->forwd != P) 325 if(c >= q->forwd->pc) { 326 q = q->forwd; 327 continue; 328 } 329 if(c == q->pc) 330 break; 331 q = q->link; 332 } 333 if(q == P) { 334 diag("branch out of range %ld\n%P", c, p); 335 p->to.type = D_NONE; 336 } 337 p->cond = q; 338 } 339 340 for(p = firstp; p != P; p = p->link) { 341 if(p->as == ATEXT) 342 curtext = p; 343 if(p->cond != P && p->cond != UP) { 344 p->cond = brloop(p->cond); 345 if(p->cond != P) 346 if(p->to.type == D_BRANCH) 347 p->to.offset = p->cond->pc; 348 } 349 } 350 } 351 352 #define LOG 5 353 void 354 mkfwd(void) 355 { 356 Prog *p; 357 long dwn[LOG], cnt[LOG], i; 358 Prog *lst[LOG]; 359 360 for(i=0; i<LOG; i++) { 361 if(i == 0) 362 cnt[i] = 1; else 363 cnt[i] = LOG * cnt[i-1]; 364 dwn[i] = 1; 365 lst[i] = P; 366 } 367 i = 0; 368 for(p = firstp; p != P; p = p->link) { 369 if(p->as == ATEXT) 370 curtext = p; 371 i--; 372 if(i < 0) 373 i = LOG-1; 374 p->forwd = P; 375 dwn[i]--; 376 if(dwn[i] <= 0) { 377 dwn[i] = cnt[i]; 378 if(lst[i] != P) 379 lst[i]->forwd = p; 380 lst[i] = p; 381 } 382 } 383 } 384 385 Prog* 386 brloop(Prog *p) 387 { 388 Prog *q; 389 int c; 390 391 for(c=0; p!=P;) { 392 if(p->as != AB) 393 return p; 394 q = p->cond; 395 if(q <= p) { 396 c++; 397 if(q == p || c > 5000) 398 break; 399 } 400 p = q; 401 } 402 return P; 403 } 404 405 long 406 atolwhex(char *s) 407 { 408 long n; 409 int f; 410 411 n = 0; 412 f = 0; 413 while(*s == ' ' || *s == '\t') 414 s++; 415 if(*s == '-' || *s == '+') { 416 if(*s++ == '-') 417 f = 1; 418 while(*s == ' ' || *s == '\t') 419 s++; 420 } 421 if(s[0]=='0' && s[1]){ 422 if(s[1]=='x' || s[1]=='X'){ 423 s += 2; 424 for(;;){ 425 if(*s >= '0' && *s <= '9') 426 n = n*16 + *s++ - '0'; 427 else if(*s >= 'a' && *s <= 'f') 428 n = n*16 + *s++ - 'a' + 10; 429 else if(*s >= 'A' && *s <= 'F') 430 n = n*16 + *s++ - 'A' + 10; 431 else 432 break; 433 } 434 } else 435 while(*s >= '0' && *s <= '7') 436 n = n*8 + *s++ - '0'; 437 } else 438 while(*s >= '0' && *s <= '9') 439 n = n*10 + *s++ - '0'; 440 if(f) 441 n = -n; 442 return n; 443 } 444 445 long 446 rnd(long v, long r) 447 { 448 long c; 449 450 if(r <= 0) 451 return v; 452 v += r - 1; 453 c = v % r; 454 if(c < 0) 455 c += r; 456 v -= c; 457 return v; 458 } 459 460 void 461 import(void) 462 { 463 int i; 464 Sym *s; 465 466 for(i = 0; i < NHASH; i++) 467 for(s = hash[i]; s != S; s = s->link) 468 if(s->sig != 0 && s->type == SXREF && (nimports == 0 || s->subtype == SIMPORT)){ 469 undefsym(s); 470 Bprint(&bso, "IMPORT: %s sig=%lux v=%ld\n", s->name, s->sig, s->value); 471 } 472 } 473 474 void 475 ckoff(Sym *s, long v) 476 { 477 if(v < 0 || v >= 1<<Roffset) 478 diag("relocation offset %ld for %s out of range", v, s->name); 479 } 480 481 static Prog* 482 newdata(Sym *s, int o, int w, int t) 483 { 484 Prog *p; 485 486 p = prg(); 487 p->link = datap; 488 datap = p; 489 p->as = ADATA; 490 p->reg = w; 491 p->from.type = D_OREG; 492 p->from.name = t; 493 p->from.sym = s; 494 p->from.offset = o; 495 p->to.type = D_CONST; 496 p->to.name = D_NONE; 497 return p; 498 } 499 500 void 501 export(void) 502 { 503 int i, j, n, off, nb, sv, ne; 504 Sym *s, *et, *str, **esyms; 505 Prog *p; 506 char buf[NSNAME], *t; 507 508 n = 0; 509 for(i = 0; i < NHASH; i++) 510 for(s = hash[i]; s != S; s = s->link) 511 if(s->sig != 0 && s->type != SXREF && s->type != SUNDEF && (nexports == 0 || s->subtype == SEXPORT)) 512 n++; 513 esyms = malloc(n*sizeof(Sym*)); 514 ne = n; 515 n = 0; 516 for(i = 0; i < NHASH; i++) 517 for(s = hash[i]; s != S; s = s->link) 518 if(s->sig != 0 && s->type != SXREF && s->type != SUNDEF && (nexports == 0 || s->subtype == SEXPORT)) 519 esyms[n++] = s; 520 for(i = 0; i < ne-1; i++) 521 for(j = i+1; j < ne; j++) 522 if(strcmp(esyms[i]->name, esyms[j]->name) > 0){ 523 s = esyms[i]; 524 esyms[i] = esyms[j]; 525 esyms[j] = s; 526 } 527 528 nb = 0; 529 off = 0; 530 et = lookup(EXPTAB, 0); 531 if(et->type != 0 && et->type != SXREF) 532 diag("%s already defined", EXPTAB); 533 et->type = SDATA; 534 str = lookup(".string", 0); 535 if(str->type == 0) 536 str->type = SDATA; 537 sv = str->value; 538 for(i = 0; i < ne; i++){ 539 s = esyms[i]; 540 Bprint(&bso, "EXPORT: %s sig=%lux t=%d\n", s->name, s->sig, s->type); 541 542 /* signature */ 543 p = newdata(et, off, sizeof(long), D_EXTERN); 544 off += sizeof(long); 545 p->to.offset = s->sig; 546 547 /* address */ 548 p = newdata(et, off, sizeof(long), D_EXTERN); 549 off += sizeof(long); 550 p->to.name = D_EXTERN; 551 p->to.sym = s; 552 553 /* string */ 554 t = s->name; 555 n = strlen(t)+1; 556 for(;;){ 557 buf[nb++] = *t; 558 sv++; 559 if(nb >= NSNAME){ 560 p = newdata(str, sv-NSNAME, NSNAME, D_STATIC); 561 p->to.type = D_SCONST; 562 p->to.sval = malloc(NSNAME); 563 memmove(p->to.sval, buf, NSNAME); 564 nb = 0; 565 } 566 if(*t++ == 0) 567 break; 568 } 569 570 /* name */ 571 p = newdata(et, off, sizeof(long), D_EXTERN); 572 off += sizeof(long); 573 p->to.name = D_STATIC; 574 p->to.sym = str; 575 p->to.offset = sv-n; 576 } 577 578 if(nb > 0){ 579 p = newdata(str, sv-nb, nb, D_STATIC); 580 p->to.type = D_SCONST; 581 p->to.sval = malloc(NSNAME); 582 memmove(p->to.sval, buf, nb); 583 } 584 585 for(i = 0; i < 3; i++){ 586 newdata(et, off, sizeof(long), D_EXTERN); 587 off += sizeof(long); 588 } 589 et->value = off; 590 if(sv == 0) 591 sv = 1; 592 str->value = sv; 593 exports = ne; 594 free(esyms); 595 } 596