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