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