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 long 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 = %lux\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 int 183 aclass(Adr *a) 184 { 185 Sym *s; 186 int t; 187 188 switch(a->type) { 189 case D_NONE: 190 return C_NONE; 191 192 case D_REG: 193 return C_REG; 194 195 case D_FREG: 196 return C_FREG; 197 198 case D_FCREG: 199 return C_FCREG; 200 201 case D_MREG: 202 return C_MREG; 203 204 case D_OREG: 205 switch(a->name) { 206 case D_EXTERN: 207 case D_STATIC: 208 if(a->sym == 0 || a->sym->name == 0) { 209 print("null sym external\n"); 210 print("%D\n", a); 211 return C_GOK; 212 } 213 t = a->sym->type; 214 if(t == 0 || t == SXREF) { 215 diag("undefined external: %s in %s", 216 a->sym->name, TNAME); 217 a->sym->type = SDATA; 218 } 219 instoffset = a->sym->value + a->offset - BIG; 220 if(instoffset >= -BIG && instoffset < BIG) 221 return C_SEXT; 222 return C_LEXT; 223 case D_AUTO: 224 instoffset = autosize + a->offset; 225 if(instoffset >= -BIG && instoffset < BIG) 226 return C_SAUTO; 227 return C_LAUTO; 228 229 case D_PARAM: 230 instoffset = autosize + a->offset + 4L; 231 if(instoffset >= -BIG && instoffset < BIG) 232 return C_SAUTO; 233 return C_LAUTO; 234 case D_NONE: 235 instoffset = a->offset; 236 if(instoffset == 0) 237 return C_ZOREG; 238 if(instoffset >= -BIG && instoffset < BIG) 239 return C_SOREG; 240 return C_LOREG; 241 } 242 return C_GOK; 243 244 case D_HI: 245 return C_LO; 246 case D_LO: 247 return C_HI; 248 249 case D_OCONST: 250 switch(a->name) { 251 case D_EXTERN: 252 case D_STATIC: 253 s = a->sym; 254 t = s->type; 255 if(t == 0 || t == SXREF) { 256 diag("undefined external: %s in %s", 257 s->name, TNAME); 258 s->type = SDATA; 259 } 260 instoffset = s->value + a->offset + INITDAT; 261 if(s->type == STEXT || s->type == SLEAF) 262 instoffset = s->value + a->offset; 263 return C_LCON; 264 } 265 return C_GOK; 266 267 case D_CONST: 268 switch(a->name) { 269 270 case D_NONE: 271 instoffset = a->offset; 272 consize: 273 if(instoffset > 0) { 274 if(instoffset <= 0x7fff) 275 return C_SCON; 276 if(instoffset <= 0xffff) 277 return C_ANDCON; 278 if((instoffset & 0xffff) == 0) 279 return C_UCON; 280 return C_LCON; 281 } 282 if(instoffset == 0) 283 return C_ZCON; 284 if(instoffset >= -0x8000) 285 return C_ADDCON; 286 if((instoffset & 0xffff) == 0) 287 return C_UCON; 288 return C_LCON; 289 290 case D_EXTERN: 291 case D_STATIC: 292 s = a->sym; 293 if(s == S) 294 break; 295 t = s->type; 296 switch(t) { 297 case 0: 298 case SXREF: 299 diag("undefined external: %s in %s", 300 s->name, TNAME); 301 s->type = SDATA; 302 break; 303 case SCONST: 304 instoffset = s->value + a->offset; 305 goto consize; 306 case STEXT: 307 case SLEAF: 308 case SSTRING: 309 instoffset = s->value + a->offset; 310 return C_LCON; 311 } 312 instoffset = s->value + a->offset - BIG; 313 if(instoffset >= -BIG && instoffset < BIG && instoffset != 0L) 314 return C_SECON; 315 instoffset = s->value + a->offset + INITDAT; 316 return C_LCON; 317 318 case D_AUTO: 319 instoffset = autosize + a->offset; 320 if(instoffset >= -BIG && instoffset < BIG) 321 return C_SACON; 322 return C_LACON; 323 324 case D_PARAM: 325 instoffset = autosize + a->offset + 4L; 326 if(instoffset >= -BIG && instoffset < BIG) 327 return C_SACON; 328 return C_LACON; 329 } 330 return C_GOK; 331 332 case D_BRANCH: 333 return C_SBRA; 334 } 335 return C_GOK; 336 } 337 338 Optab* 339 oplook(Prog *p) 340 { 341 int a1, a2, a3, r; 342 char *c1, *c3; 343 Optab *o, *e; 344 345 a1 = p->optab; 346 if(a1) 347 return optab+(a1-1); 348 a1 = p->from.class; 349 if(a1 == 0) { 350 a1 = aclass(&p->from) + 1; 351 p->from.class = a1; 352 } 353 a1--; 354 a3 = p->to.class; 355 if(a3 == 0) { 356 a3 = aclass(&p->to) + 1; 357 p->to.class = a3; 358 } 359 a3--; 360 a2 = C_NONE; 361 if(p->reg != NREG) 362 a2 = C_REG; 363 r = p->as; 364 o = oprange[r].start; 365 if(o == 0) { 366 a1 = opcross[repop[r]][a1][a2][a3]; 367 if(a1) { 368 p->optab = a1+1; 369 return optab+a1; 370 } 371 o = oprange[r].stop; /* just generate an error */ 372 } 373 e = oprange[r].stop; 374 c1 = xcmp[a1]; 375 c3 = xcmp[a3]; 376 for(; o<e; o++) 377 if(o->a2 == a2) 378 if(c1[o->a1]) 379 if(c3[o->a3]) { 380 p->optab = (o-optab)+1; 381 return o; 382 } 383 diag("illegal combination %A %d %d %d", 384 p->as, a1, a2, a3); 385 if(!debug['a']) 386 prasm(p); 387 o = optab; 388 p->optab = (o-optab)+1; 389 return o; 390 } 391 392 int 393 cmp(int a, int b) 394 { 395 396 if(a == b) 397 return 1; 398 switch(a) { 399 case C_LCON: 400 if(b == C_ZCON || b == C_SCON || b == C_UCON || 401 b == C_ADDCON || b == C_ANDCON) 402 return 1; 403 break; 404 case C_ADD0CON: 405 if(b == C_ADDCON) 406 return 1; 407 case C_ADDCON: 408 if(b == C_ZCON || b == C_SCON) 409 return 1; 410 break; 411 case C_AND0CON: 412 if(b == C_ANDCON) 413 return 1; 414 case C_ANDCON: 415 if(b == C_ZCON || b == C_SCON) 416 return 1; 417 break; 418 case C_UCON: 419 if(b == C_ZCON) 420 return 1; 421 break; 422 case C_SCON: 423 if(b == C_ZCON) 424 return 1; 425 break; 426 case C_LACON: 427 if(b == C_SACON) 428 return 1; 429 break; 430 case C_LBRA: 431 if(b == C_SBRA) 432 return 1; 433 break; 434 case C_LEXT: 435 if(b == C_SEXT) 436 return 1; 437 break; 438 case C_LAUTO: 439 if(b == C_SAUTO) 440 return 1; 441 break; 442 case C_REG: 443 if(b == C_ZCON) 444 return 1; 445 break; 446 case C_LOREG: 447 if(b == C_ZOREG || b == C_SOREG) 448 return 1; 449 break; 450 case C_SOREG: 451 if(b == C_ZOREG) 452 return 1; 453 break; 454 } 455 return 0; 456 } 457 458 int 459 ocmp(void *a1, void *a2) 460 { 461 Optab *p1, *p2; 462 int n; 463 464 p1 = (Optab*)a1; 465 p2 = (Optab*)a2; 466 n = p1->as - p2->as; 467 if(n) 468 return n; 469 n = p1->a1 - p2->a1; 470 if(n) 471 return n; 472 n = p1->a2 - p2->a2; 473 if(n) 474 return n; 475 n = p1->a3 - p2->a3; 476 if(n) 477 return n; 478 return 0; 479 } 480 481 void 482 buildop(void) 483 { 484 int i, n, r; 485 486 for(i=0; i<32; i++) 487 for(n=0; n<32; n++) 488 xcmp[i][n] = cmp(n, i); 489 for(n=0; optab[n].as != AXXX; n++) 490 ; 491 qsort(optab, n, sizeof(optab[0]), ocmp); 492 for(i=0; i<n; i++) { 493 r = optab[i].as; 494 oprange[r].start = optab+i; 495 while(optab[i].as == r) 496 i++; 497 oprange[r].stop = optab+i; 498 i--; 499 500 switch(r) 501 { 502 default: 503 diag("unknown op in build: %A", r); 504 errorexit(); 505 case AABSF: 506 oprange[AMOVFD] = oprange[r]; 507 oprange[AMOVDF] = oprange[r]; 508 oprange[AMOVWF] = oprange[r]; 509 oprange[AMOVFW] = oprange[r]; 510 oprange[AMOVWD] = oprange[r]; 511 oprange[AMOVDW] = oprange[r]; 512 oprange[ANEGF] = oprange[r]; 513 oprange[ANEGD] = oprange[r]; 514 oprange[AABSD] = oprange[r]; 515 break; 516 case AADD: 517 buildrep(1, AADD); 518 oprange[ASGT] = oprange[r]; 519 repop[ASGT] = 1; 520 oprange[ASGTU] = oprange[r]; 521 repop[ASGTU] = 1; 522 oprange[AADDU] = oprange[r]; 523 repop[AADDU] = 1; 524 oprange[AADDVU] = oprange[r]; 525 repop[AADDVU] = 1; 526 break; 527 case AADDF: 528 oprange[ADIVF] = oprange[r]; 529 oprange[ADIVD] = oprange[r]; 530 oprange[AMULF] = oprange[r]; 531 oprange[AMULD] = oprange[r]; 532 oprange[ASUBF] = oprange[r]; 533 oprange[ASUBD] = oprange[r]; 534 oprange[AADDD] = oprange[r]; 535 break; 536 case AAND: 537 buildrep(2, AAND); 538 oprange[AXOR] = oprange[r]; 539 repop[AXOR] = 2; 540 oprange[AOR] = oprange[r]; 541 repop[AOR] = 2; 542 break; 543 case ABEQ: 544 oprange[ABNE] = oprange[r]; 545 break; 546 case ABLEZ: 547 oprange[ABGEZ] = oprange[r]; 548 oprange[ABGEZAL] = oprange[r]; 549 oprange[ABLTZ] = oprange[r]; 550 oprange[ABLTZAL] = oprange[r]; 551 oprange[ABGTZ] = oprange[r]; 552 break; 553 case AMOVB: 554 buildrep(3, AMOVB); 555 oprange[AMOVH] = oprange[r]; 556 repop[AMOVH] = 3; 557 break; 558 case AMOVBU: 559 buildrep(4, AMOVBU); 560 oprange[AMOVHU] = oprange[r]; 561 repop[AMOVHU] = 4; 562 break; 563 case AMUL: 564 oprange[AREM] = oprange[r]; 565 oprange[AREMU] = oprange[r]; 566 oprange[ADIVU] = oprange[r]; 567 oprange[AMULU] = oprange[r]; 568 oprange[ADIV] = oprange[r]; 569 oprange[ADIVVU] = oprange[r]; 570 oprange[ADIVV] = oprange[r]; 571 break; 572 case ASLL: 573 oprange[ASRL] = oprange[r]; 574 oprange[ASRA] = oprange[r]; 575 oprange[ASLLV] = oprange[r]; 576 oprange[ASRAV] = oprange[r]; 577 oprange[ASRLV] = oprange[r]; 578 break; 579 case ASUB: 580 oprange[ASUBU] = oprange[r]; 581 oprange[ANOR] = oprange[r]; 582 break; 583 case ASYSCALL: 584 oprange[ATLBP] = oprange[r]; 585 oprange[ATLBR] = oprange[r]; 586 oprange[ATLBWI] = oprange[r]; 587 oprange[ATLBWR] = oprange[r]; 588 break; 589 case ACMPEQF: 590 oprange[ACMPGTF] = oprange[r]; 591 oprange[ACMPGTD] = oprange[r]; 592 oprange[ACMPGEF] = oprange[r]; 593 oprange[ACMPGED] = oprange[r]; 594 oprange[ACMPEQD] = oprange[r]; 595 break; 596 case ABFPT: 597 oprange[ABFPF] = oprange[r]; 598 break; 599 case AMOVWL: 600 oprange[AMOVWR] = oprange[r]; 601 oprange[AMOVVR] = oprange[r]; 602 oprange[AMOVVL] = oprange[r]; 603 break; 604 case AMOVW: 605 buildrep(5, AMOVW); 606 break; 607 case AMOVD: 608 buildrep(6, AMOVD); 609 break; 610 case AMOVF: 611 buildrep(7, AMOVF); 612 break; 613 case AMOVV: 614 buildrep(8, AMOVV); 615 break; 616 case ABREAK: 617 case AWORD: 618 case ARFE: 619 case AJAL: 620 case AJMP: 621 case ATEXT: 622 case ACASE: 623 case ABCASE: 624 break; 625 } 626 } 627 } 628 629 void 630 buildrep(int x, int as) 631 { 632 Opcross *p; 633 Optab *e, *s, *o; 634 int a1, a2, a3, n; 635 636 if(C_NONE != 0 || C_REG != 1 || C_GOK >= 32 || x >= nelem(opcross)) { 637 diag("assumptions fail in buildrep"); 638 errorexit(); 639 } 640 repop[as] = x; 641 p = (opcross + x); 642 s = oprange[as].start; 643 e = oprange[as].stop; 644 for(o=e-1; o>=s; o--) { 645 n = o-optab; 646 for(a2=0; a2<2; a2++) { 647 if(a2) { 648 if(o->a2 == C_NONE) 649 continue; 650 } else 651 if(o->a2 != C_NONE) 652 continue; 653 for(a1=0; a1<32; a1++) { 654 if(!xcmp[a1][o->a1]) 655 continue; 656 for(a3=0; a3<32; a3++) 657 if(xcmp[a3][o->a3]) 658 (*p)[a1][a2][a3] = n; 659 } 660 } 661 } 662 oprange[as].start = 0; 663 } 664