1 #include "l.h" 2 3 void 4 pagebug(Prog *p) 5 { 6 Prog *q; 7 8 switch(p->as) { 9 case ABGEZAL: 10 case ABLTZAL: 11 case AJAL: 12 case ABEQ: 13 case ABGEZ: 14 case ABGTZ: 15 case ABLEZ: 16 case ABLTZ: 17 case ABNE: 18 case ABFPT: 19 case ABFPF: 20 case AJMP: 21 q = prg(); 22 *q = *p; 23 p->link = q; 24 p->as = ANOR; 25 p->optab = 0; 26 p->from = zprg.from; 27 p->from.type = D_REG; 28 p->from.reg = REGZERO; 29 p->to = p->from; 30 } 31 } 32 33 void 34 span(void) 35 { 36 Prog *p, *q; 37 Sym *setext, *s; 38 Optab *o; 39 int m, bflag, i; 40 vlong c, otxt, v; 41 42 if(debug['v']) 43 Bprint(&bso, "%5.2f span\n", cputime()); 44 Bflush(&bso); 45 46 bflag = 0; 47 c = INITTEXT; 48 otxt = c; 49 for(p = firstp; p != P; p = p->link) { 50 /* bug in early 4000 chips delayslot on page boundary */ 51 if((c&(0x1000-1)) == 0xffc) 52 pagebug(p); 53 p->pc = c; 54 o = oplook(p); 55 m = o->size; 56 if(m == 0) { 57 if(p->as == ATEXT) { 58 curtext = p; 59 autosize = p->to.offset + 4; 60 if(p->from.sym != S) 61 p->from.sym->value = c; 62 /* need passes to resolve branches */ 63 if(c-otxt >= 1L<<17) 64 bflag = 1; 65 otxt = c; 66 continue; 67 } 68 diag("zero-width instruction\n%P", p); 69 continue; 70 } 71 c += m; 72 } 73 74 /* 75 * if any procedure is large enough to 76 * generate a large SBRA branch, then 77 * generate extra passes putting branches 78 * around jmps to fix. this is rare. 79 */ 80 while(bflag) { 81 if(debug['v']) 82 Bprint(&bso, "%5.2f span1\n", cputime()); 83 bflag = 0; 84 c = INITTEXT; 85 for(p = firstp; p != P; p = p->link) { 86 /* bug in early 4000 chips delayslot on page boundary */ 87 if((c&(0x1000-1)) == 0xffc) 88 pagebug(p); 89 p->pc = c; 90 o = oplook(p); 91 if(o->type == 6 && p->cond) { 92 otxt = p->cond->pc - c; 93 if(otxt < 0) 94 otxt = -otxt; 95 if(otxt >= (1L<<17) - 10) { 96 q = prg(); 97 q->link = p->link; 98 p->link = q; 99 q->as = AJMP; 100 q->to.type = D_BRANCH; 101 q->cond = p->cond; 102 p->cond = q; 103 q = prg(); 104 q->link = p->link; 105 p->link = q; 106 q->as = AJMP; 107 q->to.type = D_BRANCH; 108 q->cond = q->link->link; 109 addnop(p->link); 110 addnop(p); 111 bflag = 1; 112 } 113 } 114 m = o->size; 115 if(m == 0) { 116 if(p->as == ATEXT) { 117 curtext = p; 118 autosize = p->to.offset + 4; 119 if(p->from.sym != S) 120 p->from.sym->value = c; 121 continue; 122 } 123 diag("zero-width instruction\n%P", p); 124 continue; 125 } 126 c += m; 127 } 128 } 129 130 if(debug['t']) { 131 /* 132 * add strings to text segment 133 */ 134 c = rnd(c, 8); 135 for(i=0; i<NHASH; i++) 136 for(s = hash[i]; s != S; s = s->link) { 137 if(s->type != SSTRING) 138 continue; 139 v = s->value; 140 while(v & 3) 141 v++; 142 s->value = c; 143 c += v; 144 } 145 } 146 147 c = rnd(c, 8); 148 149 setext = lookup("etext", 0); 150 if(setext != S) { 151 setext->value = c; 152 textsize = c - INITTEXT; 153 } 154 if(INITRND) 155 INITDAT = rnd(c, INITRND); 156 if(debug['v']) 157 Bprint(&bso, "tsize = %llux\n", textsize); 158 Bflush(&bso); 159 } 160 161 void 162 xdefine(char *p, int t, long v) 163 { 164 Sym *s; 165 166 s = lookup(p, 0); 167 if(s->type == 0 || s->type == SXREF) { 168 s->type = t; 169 s->value = v; 170 } 171 } 172 173 long 174 regoff(Adr *a) 175 { 176 177 instoffset = 0; 178 aclass(a); 179 return instoffset; 180 } 181 182 aclass(Adr *a) 183 { 184 Sym *s; 185 int t; 186 187 switch(a->type) { 188 case D_NONE: 189 return C_NONE; 190 191 case D_REG: 192 return C_REG; 193 194 case D_FREG: 195 return C_FREG; 196 197 case D_FCREG: 198 return C_FCREG; 199 200 case D_MREG: 201 return C_MREG; 202 203 case D_OREG: 204 switch(a->name) { 205 case D_EXTERN: 206 case D_STATIC: 207 if(a->sym == 0 || a->sym->name == 0) { 208 print("null sym external\n"); 209 print("%D\n", a); 210 return C_GOK; 211 } 212 t = a->sym->type; 213 if(t == 0 || t == SXREF) { 214 diag("undefined external: %s in %s", 215 a->sym->name, TNAME); 216 a->sym->type = SDATA; 217 } 218 instoffset = a->sym->value + a->offset - BIG; 219 if(instoffset >= -BIG && instoffset < BIG) 220 return C_SEXT; 221 return C_LEXT; 222 case D_AUTO: 223 instoffset = autosize + a->offset; 224 if(instoffset >= -BIG && instoffset < BIG) 225 return C_SAUTO; 226 return C_LAUTO; 227 228 case D_PARAM: 229 instoffset = autosize + a->offset + 4L; 230 if(instoffset >= -BIG && instoffset < BIG) 231 return C_SAUTO; 232 return C_LAUTO; 233 case D_NONE: 234 instoffset = a->offset; 235 if(instoffset == 0) 236 return C_ZOREG; 237 if(instoffset >= -BIG && instoffset < BIG) 238 return C_SOREG; 239 return C_LOREG; 240 } 241 return C_GOK; 242 243 case D_HI: 244 return C_LO; 245 case D_LO: 246 return C_HI; 247 248 case D_OCONST: 249 switch(a->name) { 250 case D_EXTERN: 251 case D_STATIC: 252 s = a->sym; 253 t = s->type; 254 if(t == 0 || t == SXREF) { 255 diag("undefined external: %s in %s", 256 s->name, TNAME); 257 s->type = SDATA; 258 } 259 instoffset = s->value + a->offset + INITDAT; 260 if(s->type == STEXT || s->type == SLEAF) 261 instoffset = s->value + a->offset; 262 return C_LCON; 263 } 264 return C_GOK; 265 266 case D_CONST: 267 switch(a->name) { 268 269 case D_NONE: 270 instoffset = a->offset; 271 consize: 272 if(instoffset > 0) { 273 if(instoffset <= 0x7fff) 274 return C_SCON; 275 if(instoffset <= 0xffff) 276 return C_ANDCON; 277 if((instoffset & 0xffff) == 0) 278 return C_UCON; 279 return C_LCON; 280 } 281 if(instoffset == 0) 282 return C_ZCON; 283 if(instoffset >= -0x8000) 284 return C_ADDCON; 285 if((instoffset & 0xffff) == 0) 286 return C_UCON; 287 return C_LCON; 288 289 case D_EXTERN: 290 case D_STATIC: 291 s = a->sym; 292 if(s == S) 293 break; 294 t = s->type; 295 switch(t) { 296 case 0: 297 case SXREF: 298 diag("undefined external: %s in %s", 299 s->name, TNAME); 300 s->type = SDATA; 301 break; 302 case SCONST: 303 instoffset = s->value + a->offset; 304 goto consize; 305 case STEXT: 306 case SLEAF: 307 case SSTRING: 308 instoffset = s->value + a->offset; 309 return C_LCON; 310 } 311 instoffset = s->value + a->offset - BIG; 312 if(instoffset >= -BIG && instoffset < BIG && instoffset != 0L) 313 return C_SECON; 314 instoffset = s->value + a->offset + INITDAT; 315 return C_LCON; 316 317 case D_AUTO: 318 instoffset = autosize + a->offset; 319 if(instoffset >= -BIG && instoffset < BIG) 320 return C_SACON; 321 return C_LACON; 322 323 case D_PARAM: 324 instoffset = autosize + a->offset + 4L; 325 if(instoffset >= -BIG && instoffset < BIG) 326 return C_SACON; 327 return C_LACON; 328 } 329 return C_GOK; 330 331 case D_BRANCH: 332 return C_SBRA; 333 } 334 return C_GOK; 335 } 336 337 Optab* 338 oplook(Prog *p) 339 { 340 int a1, a2, a3, r; 341 char *c1, *c3; 342 Optab *o, *e; 343 344 a1 = p->optab; 345 if(a1) 346 return optab+(a1-1); 347 a1 = p->from.class; 348 if(a1 == 0) { 349 a1 = aclass(&p->from) + 1; 350 p->from.class = a1; 351 } 352 a1--; 353 a3 = p->to.class; 354 if(a3 == 0) { 355 a3 = aclass(&p->to) + 1; 356 p->to.class = a3; 357 } 358 a3--; 359 a2 = C_NONE; 360 if(p->reg != NREG) 361 a2 = C_REG; 362 r = p->as; 363 o = oprange[r].start; 364 if(o == 0) { 365 a1 = opcross[repop[r]][a1][a2][a3]; 366 if(a1) { 367 p->optab = a1+1; 368 return optab+a1; 369 } 370 o = oprange[r].stop; /* just generate an error */ 371 } 372 e = oprange[r].stop; 373 c1 = xcmp[a1]; 374 c3 = xcmp[a3]; 375 for(; o<e; o++) 376 if(o->a2 == a2) 377 if(c1[o->a1]) 378 if(c3[o->a3]) { 379 p->optab = (o-optab)+1; 380 return o; 381 } 382 diag("illegal combination %A %d %d %d", 383 p->as, a1, a2, a3); 384 if(!debug['a']) 385 prasm(p); 386 o = optab; 387 p->optab = (o-optab)+1; 388 return o; 389 } 390 391 int 392 cmp(int a, int b) 393 { 394 395 if(a == b) 396 return 1; 397 switch(a) { 398 case C_LCON: 399 if(b == C_ZCON || b == C_SCON || b == C_UCON || 400 b == C_ADDCON || b == C_ANDCON) 401 return 1; 402 break; 403 case C_ADD0CON: 404 if(b == C_ADDCON) 405 return 1; 406 case C_ADDCON: 407 if(b == C_ZCON || b == C_SCON) 408 return 1; 409 break; 410 case C_AND0CON: 411 if(b == C_ANDCON) 412 return 1; 413 case C_ANDCON: 414 if(b == C_ZCON || b == C_SCON) 415 return 1; 416 break; 417 case C_UCON: 418 if(b == C_ZCON) 419 return 1; 420 break; 421 case C_SCON: 422 if(b == C_ZCON) 423 return 1; 424 break; 425 case C_LACON: 426 if(b == C_SACON) 427 return 1; 428 break; 429 case C_LBRA: 430 if(b == C_SBRA) 431 return 1; 432 break; 433 case C_LEXT: 434 if(b == C_SEXT) 435 return 1; 436 break; 437 case C_LAUTO: 438 if(b == C_SAUTO) 439 return 1; 440 break; 441 case C_REG: 442 if(b == C_ZCON) 443 return 1; 444 break; 445 case C_LOREG: 446 if(b == C_ZOREG || b == C_SOREG) 447 return 1; 448 break; 449 case C_SOREG: 450 if(b == C_ZOREG) 451 return 1; 452 break; 453 } 454 return 0; 455 } 456 457 int 458 ocmp(const void *a1, const void *a2) 459 { 460 Optab *p1, *p2; 461 int n; 462 463 p1 = (Optab*)a1; 464 p2 = (Optab*)a2; 465 n = p1->as - p2->as; 466 if(n) 467 return n; 468 n = p1->a1 - p2->a1; 469 if(n) 470 return n; 471 n = p1->a2 - p2->a2; 472 if(n) 473 return n; 474 n = p1->a3 - p2->a3; 475 if(n) 476 return n; 477 return 0; 478 } 479 480 void 481 buildop(void) 482 { 483 int i, n, r; 484 485 for(i=0; i<32; i++) 486 for(n=0; n<32; n++) 487 xcmp[i][n] = cmp(n, i); 488 for(n=0; optab[n].as != AXXX; n++) 489 ; 490 qsort(optab, n, sizeof(optab[0]), ocmp); 491 for(i=0; i<n; i++) { 492 r = optab[i].as; 493 oprange[r].start = optab+i; 494 while(optab[i].as == r) 495 i++; 496 oprange[r].stop = optab+i; 497 i--; 498 499 switch(r) 500 { 501 default: 502 diag("unknown op in build: %A", r); 503 errorexit(); 504 case AABSF: 505 oprange[AMOVFD] = oprange[r]; 506 oprange[AMOVDF] = oprange[r]; 507 oprange[AMOVWF] = oprange[r]; 508 oprange[AMOVFW] = oprange[r]; 509 oprange[AMOVWD] = oprange[r]; 510 oprange[AMOVDW] = oprange[r]; 511 oprange[ANEGF] = oprange[r]; 512 oprange[ANEGD] = oprange[r]; 513 oprange[AABSD] = oprange[r]; 514 break; 515 case AADD: 516 buildrep(1, AADD); 517 oprange[ASGT] = oprange[r]; 518 repop[ASGT] = 1; 519 oprange[ASGTU] = oprange[r]; 520 repop[ASGTU] = 1; 521 oprange[AADDU] = oprange[r]; 522 repop[AADDU] = 1; 523 oprange[AADDVU] = oprange[r]; 524 repop[AADDVU] = 1; 525 break; 526 case AADDF: 527 oprange[ADIVF] = oprange[r]; 528 oprange[ADIVD] = oprange[r]; 529 oprange[AMULF] = oprange[r]; 530 oprange[AMULD] = oprange[r]; 531 oprange[ASUBF] = oprange[r]; 532 oprange[ASUBD] = oprange[r]; 533 oprange[AADDD] = oprange[r]; 534 break; 535 case AAND: 536 buildrep(2, AAND); 537 oprange[AXOR] = oprange[r]; 538 repop[AXOR] = 2; 539 oprange[AOR] = oprange[r]; 540 repop[AOR] = 2; 541 break; 542 case ABEQ: 543 oprange[ABNE] = oprange[r]; 544 break; 545 case ABLEZ: 546 oprange[ABGEZ] = oprange[r]; 547 oprange[ABGEZAL] = oprange[r]; 548 oprange[ABLTZ] = oprange[r]; 549 oprange[ABLTZAL] = oprange[r]; 550 oprange[ABGTZ] = oprange[r]; 551 break; 552 case AMOVB: 553 buildrep(3, AMOVB); 554 oprange[AMOVH] = oprange[r]; 555 repop[AMOVH] = 3; 556 break; 557 case AMOVBU: 558 buildrep(4, AMOVBU); 559 oprange[AMOVHU] = oprange[r]; 560 repop[AMOVHU] = 4; 561 break; 562 case AMUL: 563 oprange[AREM] = oprange[r]; 564 oprange[AREMU] = oprange[r]; 565 oprange[ADIVU] = oprange[r]; 566 oprange[AMULU] = oprange[r]; 567 oprange[ADIV] = oprange[r]; 568 oprange[ADIVVU] = oprange[r]; 569 oprange[ADIVV] = oprange[r]; 570 break; 571 case ASLL: 572 oprange[ASRL] = oprange[r]; 573 oprange[ASRA] = oprange[r]; 574 oprange[ASLLV] = oprange[r]; 575 oprange[ASRAV] = oprange[r]; 576 oprange[ASRLV] = oprange[r]; 577 break; 578 case ASUB: 579 oprange[ASUBU] = oprange[r]; 580 oprange[ANOR] = oprange[r]; 581 break; 582 case ASYSCALL: 583 oprange[ATLBP] = oprange[r]; 584 oprange[ATLBR] = oprange[r]; 585 oprange[ATLBWI] = oprange[r]; 586 oprange[ATLBWR] = oprange[r]; 587 break; 588 case ACMPEQF: 589 oprange[ACMPGTF] = oprange[r]; 590 oprange[ACMPGTD] = oprange[r]; 591 oprange[ACMPGEF] = oprange[r]; 592 oprange[ACMPGED] = oprange[r]; 593 oprange[ACMPEQD] = oprange[r]; 594 break; 595 case ABFPT: 596 oprange[ABFPF] = oprange[r]; 597 break; 598 case AMOVWL: 599 oprange[AMOVWR] = oprange[r]; 600 oprange[AMOVVR] = oprange[r]; 601 oprange[AMOVVL] = oprange[r]; 602 break; 603 case AMOVW: 604 buildrep(5, AMOVW); 605 break; 606 case AMOVD: 607 buildrep(6, AMOVD); 608 break; 609 case AMOVF: 610 buildrep(7, AMOVF); 611 break; 612 case AMOVV: 613 buildrep(8, AMOVV); 614 break; 615 case ABREAK: 616 case AWORD: 617 case ARFE: 618 case AJAL: 619 case AJMP: 620 case ATEXT: 621 case ACASE: 622 case ABCASE: 623 break; 624 } 625 } 626 } 627 628 void 629 buildrep(int x, int as) 630 { 631 Opcross *p; 632 Optab *e, *s, *o; 633 int a1, a2, a3, n; 634 635 if(C_NONE != 0 || C_REG != 1 || C_GOK >= 32 || x >= nelem(opcross)) { 636 diag("assumptions fail in buildrep"); 637 errorexit(); 638 } 639 repop[as] = x; 640 p = (opcross + x); 641 s = oprange[as].start; 642 e = oprange[as].stop; 643 for(o=e-1; o>=s; o--) { 644 n = o-optab; 645 for(a2=0; a2<2; a2++) { 646 if(a2) { 647 if(o->a2 == C_NONE) 648 continue; 649 } else 650 if(o->a2 != C_NONE) 651 continue; 652 for(a1=0; a1<32; a1++) { 653 if(!xcmp[a1][o->a1]) 654 continue; 655 for(a3=0; a3<32; a3++) 656 if(xcmp[a3][o->a3]) 657 (*p)[a1][a2][a3] = n; 658 } 659 } 660 } 661 oprange[as].start = 0; 662 } 663