1 #include "l.h" 2 3 #define LPUT(c)\ 4 {\ 5 cbp[0] = (c)>>24;\ 6 cbp[1] = (c)>>16;\ 7 cbp[2] = (c)>>8;\ 8 cbp[3] = (c);\ 9 cbp += 4;\ 10 cbc -= 4;\ 11 if(cbc <= 0)\ 12 cflush();\ 13 } 14 15 #define CPUT(c)\ 16 {\ 17 cbp[0] = (c);\ 18 cbp++;\ 19 cbc--;\ 20 if(cbc <= 0)\ 21 cflush();\ 22 } 23 24 long 25 entryvalue(void) 26 { 27 char *a; 28 Sym *s; 29 30 a = INITENTRY; 31 if(*a >= '0' && *a <= '9') 32 return atolwhex(a); 33 s = lookup(a, 0); 34 if(s->type == 0) 35 return INITTEXT; 36 if(s->type != STEXT && s->type != SLEAF) 37 diag("entry not text: %s", s->name); 38 return s->value; 39 } 40 41 void 42 asmb(void) 43 { 44 Prog *p; 45 long t; 46 Optab *o; 47 48 if(debug['v']) 49 Bprint(&bso, "%5.2f asm\n", cputime()); 50 Bflush(&bso); 51 seek(cout, HEADR, 0); 52 pc = INITTEXT; 53 for(p = firstp; p != P; p = p->link) { 54 if(p->as == ATEXT) { 55 curtext = p; 56 autosize = p->to.offset + 4; 57 } 58 if(p->pc != pc) { 59 diag("phase error %lux sb %lux", 60 p->pc, pc); 61 if(!debug['a']) 62 prasm(curp); 63 pc = p->pc; 64 } 65 curp = p; 66 o = oplook(p); /* could probably avoid this call */ 67 if(asmout(p, o, 0)) { 68 p = p->link; 69 pc += 4; 70 } 71 pc += o->size; 72 } 73 if(debug['a']) 74 Bprint(&bso, "\n"); 75 Bflush(&bso); 76 cflush(); 77 78 curtext = P; 79 switch(HEADTYPE) { 80 case 0: 81 case 3: 82 seek(cout, HEADR+textsize, 0); 83 break; 84 case 1: 85 case 2: 86 seek(cout, HEADR+textsize, 0); 87 break; 88 } 89 for(t = 0; t < datsize; t += sizeof(buf)-100) { 90 if(datsize-t > sizeof(buf)-100) 91 datblk(t, sizeof(buf)-100); 92 else 93 datblk(t, datsize-t); 94 } 95 96 symsize = 0; 97 lcsize = 0; 98 if(!debug['s']) { 99 if(debug['v']) 100 Bprint(&bso, "%5.2f sym\n", cputime()); 101 Bflush(&bso); 102 switch(HEADTYPE) { 103 case 0: 104 case 3: 105 seek(cout, HEADR+textsize+datsize, 0); 106 break; 107 case 2: 108 case 1: 109 seek(cout, HEADR+textsize+datsize, 0); 110 break; 111 } 112 if(!debug['s']) 113 asmsym(); 114 if(debug['v']) 115 Bprint(&bso, "%5.2f sp\n", cputime()); 116 Bflush(&bso); 117 if(!debug['s']) 118 asmlc(); 119 /* round up file length for boot image */ 120 if(HEADTYPE == 0 || HEADTYPE == 3) 121 if((symsize+lcsize) & 1) 122 CPUT(0); 123 cflush(); 124 } 125 126 seek(cout, 0L, 0); 127 switch(HEADTYPE) { 128 case 0: 129 lput(0x1030107); /* magic and sections */ 130 lput(textsize); /* sizes */ 131 lput(datsize); 132 lput(bsssize); 133 lput(symsize); /* nsyms */ 134 lput(entryvalue()); /* va of entry */ 135 lput(0L); 136 lput(lcsize); 137 break; 138 case 1: 139 break; 140 case 2: 141 lput(4*13*13+7); /* magic */ 142 lput(textsize); /* sizes */ 143 lput(datsize); 144 lput(bsssize); 145 lput(symsize); /* nsyms */ 146 lput(entryvalue()); /* va of entry */ 147 lput(0L); 148 lput(lcsize); 149 break; 150 case 3: 151 lput(0x1030107); /* magic and sections */ 152 lput(0x90100000); 153 #define SPARC_NOOP 0x01000000 154 lput(SPARC_NOOP); 155 lput(SPARC_NOOP); 156 lput(SPARC_NOOP); 157 lput(SPARC_NOOP); 158 lput(SPARC_NOOP); 159 lput(SPARC_NOOP); 160 break; 161 } 162 cflush(); 163 } 164 165 void 166 lput(long l) 167 { 168 169 LPUT(l); 170 } 171 172 void 173 cflush(void) 174 { 175 int n; 176 177 n = sizeof(buf.cbuf) - cbc; 178 if(n) 179 write(cout, buf.cbuf, n); 180 cbp = buf.cbuf; 181 cbc = sizeof(buf.cbuf); 182 } 183 184 void 185 asmsym(void) 186 { 187 Prog *p; 188 Auto *a; 189 Sym *s; 190 int h; 191 192 s = lookup("etext", 0); 193 if(s->type == STEXT) 194 putsymb(s->name, 'T', s->value, s->version); 195 196 for(h=0; h<NHASH; h++) 197 for(s=hash[h]; s!=S; s=s->link) 198 switch(s->type) { 199 case SCONST: 200 putsymb(s->name, 'D', s->value, s->version); 201 continue; 202 203 case SDATA: 204 putsymb(s->name, 'D', s->value+INITDAT, s->version); 205 continue; 206 207 case SBSS: 208 putsymb(s->name, 'B', s->value+INITDAT, s->version); 209 continue; 210 211 case SFILE: 212 putsymb(s->name, 'f', s->value, s->version); 213 continue; 214 } 215 216 for(p=textp; p!=P; p=p->cond) { 217 s = p->from.sym; 218 if(s->type != STEXT && s->type != SLEAF) 219 continue; 220 221 /* filenames first */ 222 for(a=p->to.autom; a; a=a->link) 223 if(a->type == D_FILE) 224 putsymb(a->asym->name, 'z', a->aoffset, 0); 225 else 226 if(a->type == D_FILE1) 227 putsymb(a->asym->name, 'Z', a->aoffset, 0); 228 229 if(s->type == STEXT) 230 putsymb(s->name, 'T', s->value, s->version); 231 else 232 putsymb(s->name, 'L', s->value, s->version); 233 234 /* frame, auto and param after */ 235 putsymb(".frame", 'm', p->to.offset+4, 0); 236 for(a=p->to.autom; a; a=a->link) 237 if(a->type == D_AUTO) 238 putsymb(a->asym->name, 'a', -a->aoffset, 0); 239 else 240 if(a->type == D_PARAM) 241 putsymb(a->asym->name, 'p', a->aoffset, 0); 242 } 243 if(debug['v'] || debug['n']) 244 Bprint(&bso, "symsize = %lud\n", symsize); 245 Bflush(&bso); 246 } 247 248 void 249 putsymb(char *s, int t, long v, int ver) 250 { 251 int i, f; 252 253 if(t == 'f') 254 s++; 255 LPUT(v); 256 if(ver) 257 t += 'a' - 'A'; 258 CPUT(t+0x80); /* 0x80 is variable length */ 259 260 if(t == 'Z' || t == 'z') { 261 CPUT(s[0]); 262 for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) { 263 CPUT(s[i]); 264 CPUT(s[i+1]); 265 } 266 CPUT(0); 267 CPUT(0); 268 i++; 269 } 270 else { 271 for(i=0; s[i]; i++) 272 CPUT(s[i]); 273 CPUT(0); 274 } 275 symsize += 4 + 1 + i + 1; 276 277 if(debug['n']) { 278 if(t == 'z' || t == 'Z') { 279 Bprint(&bso, "%c %.8lux ", t, v); 280 for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) { 281 f = ((s[i]&0xff) << 8) | (s[i+1]&0xff); 282 Bprint(&bso, "/%x", f); 283 } 284 Bprint(&bso, "\n"); 285 return; 286 } 287 if(ver) 288 Bprint(&bso, "%c %.8lux %s<%d>\n", t, v, s, ver); 289 else 290 Bprint(&bso, "%c %.8lux %s\n", t, v, s); 291 } 292 } 293 294 #define MINLC 4 295 void 296 asmlc(void) 297 { 298 long oldpc, oldlc; 299 Prog *p; 300 long v, s; 301 302 oldpc = INITTEXT; 303 oldlc = 0; 304 for(p = firstp; p != P; p = p->link) { 305 if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) { 306 if(p->as == ATEXT) 307 curtext = p; 308 if(debug['L']) 309 Bprint(&bso, "%6lux %P\n", 310 p->pc, p); 311 continue; 312 } 313 if(debug['L']) 314 Bprint(&bso, "\t\t%6ld", lcsize); 315 v = (p->pc - oldpc) / MINLC; 316 while(v) { 317 s = 127; 318 if(v < 127) 319 s = v; 320 CPUT(s+128); /* 129-255 +pc */ 321 if(debug['L']) 322 Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128); 323 v -= s; 324 lcsize++; 325 } 326 s = p->line - oldlc; 327 oldlc = p->line; 328 oldpc = p->pc + MINLC; 329 if(s > 64 || s < -64) { 330 CPUT(0); /* 0 vv +lc */ 331 CPUT(s>>24); 332 CPUT(s>>16); 333 CPUT(s>>8); 334 CPUT(s); 335 if(debug['L']) { 336 if(s > 0) 337 Bprint(&bso, " lc+%ld(%d,%ld)\n", 338 s, 0, s); 339 else 340 Bprint(&bso, " lc%ld(%d,%ld)\n", 341 s, 0, s); 342 Bprint(&bso, "%6lux %P\n", 343 p->pc, p); 344 } 345 lcsize += 5; 346 continue; 347 } 348 if(s > 0) { 349 CPUT(0+s); /* 1-64 +lc */ 350 if(debug['L']) { 351 Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s); 352 Bprint(&bso, "%6lux %P\n", 353 p->pc, p); 354 } 355 } else { 356 CPUT(64-s); /* 65-128 -lc */ 357 if(debug['L']) { 358 Bprint(&bso, " lc%ld(%ld)\n", s, 64-s); 359 Bprint(&bso, "%6lux %P\n", 360 p->pc, p); 361 } 362 } 363 lcsize++; 364 } 365 while(lcsize & 1) { 366 s = 129; 367 CPUT(s); 368 lcsize++; 369 } 370 if(debug['v'] || debug['L']) 371 Bprint(&bso, "lcsize = %ld\n", lcsize); 372 Bflush(&bso); 373 } 374 375 void 376 datblk(long s, long n) 377 { 378 Prog *p; 379 char *cast; 380 long l, fl, j, d; 381 int i, c; 382 383 memset(buf.dbuf, 0, n+100); 384 for(p = datap; p != P; p = p->link) { 385 curp = p; 386 l = p->from.sym->value + p->from.offset - s; 387 c = p->reg; 388 i = 0; 389 if(l < 0) { 390 if(l+c <= 0) 391 continue; 392 while(l < 0) { 393 l++; 394 i++; 395 } 396 } 397 if(l >= n) 398 continue; 399 if(p->as != AINIT && p->as != ADYNT) { 400 for(j=l+(c-i)-1; j>=l; j--) 401 if(buf.dbuf[j]) { 402 print("%P\n", p); 403 diag("multiple initialization"); 404 break; 405 } 406 } 407 switch(p->to.type) { 408 default: 409 diag("unknown mode in initialization\n%P", p); 410 break; 411 412 case D_FCONST: 413 switch(c) { 414 default: 415 case 4: 416 fl = ieeedtof(&p->to.ieee); 417 cast = (char*)&fl; 418 for(; i<c; i++) { 419 buf.dbuf[l] = cast[fnuxi8[i+4]]; 420 l++; 421 } 422 break; 423 case 8: 424 cast = (char*)&p->to.ieee; 425 for(; i<c; i++) { 426 buf.dbuf[l] = cast[fnuxi8[i]]; 427 l++; 428 } 429 break; 430 } 431 break; 432 433 case D_SCONST: 434 for(; i<c; i++) { 435 buf.dbuf[l] = p->to.sval[i]; 436 l++; 437 } 438 break; 439 440 case D_CONST: 441 d = p->to.offset; 442 if(p->to.sym) { 443 if(p->to.sym->type == STEXT || 444 p->to.sym->type == SLEAF) 445 d += p->to.sym->value; 446 if(p->to.sym->type == SDATA) 447 d += p->to.sym->value + INITDAT; 448 if(p->to.sym->type == SBSS) 449 d += p->to.sym->value + INITDAT; 450 } 451 cast = (char*)&d; 452 switch(c) { 453 default: 454 diag("bad nuxi %d %d\n%P", c, i, curp); 455 break; 456 case 1: 457 for(; i<c; i++) { 458 buf.dbuf[l] = cast[inuxi1[i]]; 459 l++; 460 } 461 break; 462 case 2: 463 for(; i<c; i++) { 464 buf.dbuf[l] = cast[inuxi2[i]]; 465 l++; 466 } 467 break; 468 case 4: 469 for(; i<c; i++) { 470 buf.dbuf[l] = cast[inuxi4[i]]; 471 l++; 472 } 473 break; 474 } 475 break; 476 } 477 } 478 write(cout, buf.dbuf, n); 479 } 480 481 #define OP2(x) (0x80000000|((x)<<19)) 482 #define OP3(x) (0xc0000000|((x)<<19)) 483 #define OPB(x) (0x00800000|((x)<<25)) 484 #define OPT(x) (0x81d02000|((x)<<25)) 485 #define OPF1(x) (0x81a00000|((x)<<5)) 486 #define OPF2(x) (0x81a80000|((x)<<5)) 487 #define OPFB(x) (0x01800000|((x)<<25)) 488 489 #define OP_RRR(op,r1,r2,r3)\ 490 (0x00000000 | op |\ 491 (((r1)&31L)<<0) |\ 492 (((r2)&31L)<<14) |\ 493 (((r3)&31L)<<25)) 494 #define OP_IRR(op,i,r2,r3)\ 495 (0x00002000L | (op) |\ 496 (((i)&0x1fffL)<<0) |\ 497 (((r2)&31L)<<14) |\ 498 (((r3)&31L)<<25)) 499 #define OP_BRA(op,pc)\ 500 ((op) |\ 501 (((pc)&0x3fffff)<<0)) 502 503 int 504 asmout(Prog *p, Optab *o, int aflag) 505 { 506 long o1, o2, o3, o4, o5, v; 507 Prog *ct; 508 int r; 509 510 o1 = 0; 511 o2 = 0; 512 o3 = 0; 513 o4 = 0; 514 o5 = 0; 515 516 switch(o->type) { 517 default: 518 if(aflag) 519 return 0; 520 diag("unknown type %d", o->type); 521 if(!debug['a']) 522 prasm(p); 523 break; 524 525 case 0: /* pseudo ops */ 526 if(aflag) { 527 if(p->link) { 528 if(p->as == ATEXT) { 529 ct = curtext; 530 o2 = autosize; 531 curtext = p; 532 autosize = p->to.offset + 4; 533 o1 = asmout(p->link, oplook(p->link), aflag); 534 curtext = ct; 535 autosize = o2; 536 } else 537 o1 = asmout(p->link, oplook(p->link), aflag); 538 } 539 return o1; 540 } 541 break; 542 543 case 1: /* mov r1,r2 ==> OR r1,r0,r2 */ 544 o1 = OP_RRR(opcode(AOR), p->from.reg, REGZERO, p->to.reg); 545 break; 546 547 case 2: /* mov $c,r ==> add r1,r0,r2 */ 548 r = p->from.reg; 549 if(r == NREG) 550 r = o->param; 551 v = regoff(&p->from); 552 o1 = OP_IRR(opcode(AADD), v, r, p->to.reg); 553 break; 554 555 case 3: /* mov soreg, r */ 556 r = p->from.reg; 557 if(r == NREG) 558 r = o->param; 559 v = regoff(&p->from); 560 if(v == 0 && p->reg != NREG) 561 o1 = OP_RRR(opcode(p->as), p->reg, r, p->to.reg); 562 else 563 o1 = OP_IRR(opcode(p->as), v, r, p->to.reg); 564 break; 565 566 case 4: /* mov r, soreg */ 567 r = p->to.reg; 568 if(r == NREG) 569 r = o->param; 570 v = regoff(&p->to); 571 if(v == 0 && p->reg != NREG) 572 o1 = OP_RRR(opcode(p->as+AEND), p->reg, r, p->from.reg); 573 else 574 o1 = OP_IRR(opcode(p->as+AEND), v, r, p->from.reg); 575 break; 576 577 case 5: /* mov $lcon, reg => sethi, add */ 578 v = regoff(&p->from); 579 o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff); /* sethi */ 580 o2 = OP_IRR(opcode(AADD), (v&0x3ff), REGTMP, p->to.reg); 581 break; 582 583 case 6: /* mov asi, r[+r] */ 584 o1 = OP_RRR(opcode(p->as), p->reg, p->from.reg, p->to.reg); 585 o1 |= (1<<23) | ((p->from.offset&0xff)<<5); 586 break; 587 588 case 7: /* mov [+r]r, asi */ 589 o1 = OP_RRR(opcode(p->as+AEND), p->reg, p->to.reg, p->from.reg); 590 o1 |= (1<<23) | ((p->to.offset&0xff)<<5); 591 break; 592 593 case 8: /* mov r, preg and mov preg, r */ 594 if(p->to.type == D_PREG) { 595 r = p->from.reg; 596 switch(p->to.reg) 597 { 598 default: 599 diag("unknown register P%d", p->to.reg); 600 case D_Y: 601 o1 = OP2(48); /* wry */ 602 break; 603 case D_PSR: 604 o1 = OP2(49); /* wrpsr */ 605 break; 606 case D_WIM: 607 o1 = OP2(50); /* wrwim */ 608 break; 609 case D_TBR: 610 o1 = OP2(51); /* wrtbr */ 611 break; 612 } 613 o1 = OP_IRR(o1, 0, r, 0); 614 break; 615 } 616 if(p->from.type == D_PREG) { 617 r = p->to.reg; 618 switch(p->from.reg) 619 { 620 default: 621 diag("unknown register P%d", p->to.reg); 622 case D_Y: 623 o1 = OP2(40); /* rdy */ 624 break; 625 case D_PSR: 626 o1 = OP2(41); /* rdpsr */ 627 break; 628 case D_WIM: 629 o1 = OP2(42); /* rdwim */ 630 break; 631 case D_TBR: 632 o1 = OP2(43); /* rdtbr */ 633 break; 634 } 635 o1 = OP_RRR(o1, 0, 0, r); 636 break; 637 } 638 break; 639 640 case 9: /* movb r,r */ 641 v = 24; 642 if(p->as == AMOVH || p->as == AMOVHU) 643 v = 16; 644 r = ASRA; 645 if(p->as == AMOVBU || p->as == AMOVHU) 646 r = ASRL; 647 o1 = OP_IRR(opcode(ASLL), v, p->from.reg, p->to.reg); 648 o2 = OP_IRR(opcode(r), v, p->to.reg, p->to.reg); 649 break; 650 651 case 10: /* mov $loreg, reg */ 652 r = p->from.reg; 653 if(r == NREG) 654 r = o->param; 655 v = regoff(&p->from); 656 o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff); /* sethi */ 657 o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP); 658 o3 = OP_IRR(opcode(AADD), (v&0x3ff), REGTMP, p->to.reg); 659 break; 660 661 case 11: /* mov loreg, r */ 662 r = p->from.reg; 663 if(r == NREG) 664 r = o->param; 665 v = regoff(&p->from); 666 o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff); /* sethi */ 667 o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP); 668 o3 = OP_IRR(opcode(p->as), (v&0x3ff), REGTMP, p->to.reg); 669 break; 670 671 case 12: /* mov r, loreg */ 672 r = p->to.reg; 673 if(r == NREG) 674 r = o->param; 675 v = regoff(&p->to); 676 o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff); /* sethi */ 677 o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP); 678 o3 = OP_IRR(opcode(p->as+AEND), (v&0x3ff), REGTMP, p->from.reg); 679 break; 680 681 case 13: /* mov $ucon, r */ 682 v = regoff(&p->from); 683 o1 = 0x1000000 | (p->to.reg<<25) | ((v>>10) & 0x3fffff); /* sethi */ 684 break; 685 686 case 20: /* op $scon,r */ 687 v = regoff(&p->from); 688 r = p->reg; 689 if(r == NREG) 690 r = p->to.reg; 691 o1 = OP_IRR(opcode(p->as), v, r, p->to.reg); 692 break; 693 694 case 21: /* op r1,r2 */ 695 r = p->reg; 696 if(r == NREG) 697 r = p->to.reg; 698 o1 = OP_RRR(opcode(p->as), p->from.reg, r, p->to.reg); 699 break; 700 701 case 22: /* op $lcon,r */ 702 v = regoff(&p->from); 703 r = p->reg; 704 if(r == NREG) 705 r = p->to.reg; 706 o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff); /* sethi */ 707 o2 = OP_IRR(opcode(AADD), (v&0x3ff), REGTMP, REGTMP); 708 o3 = OP_RRR(opcode(p->as), REGTMP, r, p->to.reg); 709 break; 710 711 case 23: /* cmp r,r */ 712 o1 = OP_RRR(opcode(ASUBCC), p->to.reg, p->from.reg, REGZERO); 713 break; 714 715 case 24: /* cmp r,$c */ 716 v = regoff(&p->to); 717 o1 = OP_IRR(opcode(ASUBCC), v, p->from.reg, REGZERO); 718 break; 719 720 case 25: /* cmp $c,r BOTCH, fix compiler */ 721 v = regoff(&p->from); 722 o1 = OP_IRR(opcode(AADD), v, NREG, REGTMP); 723 o2 = OP_RRR(opcode(ASUBCC), p->to.reg, REGTMP, REGZERO); 724 break; 725 726 case 26: /* op $ucon,r */ 727 v = regoff(&p->from); 728 r = p->reg; 729 if(r == NREG) 730 r = p->to.reg; 731 o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff); /* sethi */ 732 o2 = OP_RRR(opcode(p->as), REGTMP, r, p->to.reg); 733 break; 734 735 case 30: /* jmp/jmpl soreg */ 736 if(aflag) 737 return 0; 738 v = regoff(&p->to); 739 r = p->reg; 740 if(r == NREG && p->as == AJMPL) 741 r = 15; 742 o1 = OP_IRR(opcode(AJMPL), v, p->to.reg, r); 743 break; 744 745 case 31: /* ba jmp */ 746 if(aflag) 747 return 0; 748 r = p->as; 749 if(r == AJMP) 750 r = ABA; 751 v = 0; 752 if(p->cond) 753 v = p->cond->pc - p->pc; 754 o1 = OP_BRA(opcode(r), v/4); 755 if(r == ABA && p->link && p->cond && isnop(p->link)) { 756 o2 = asmout(p->cond, oplook(p->cond), 1); 757 if(o2) { 758 o1 += 1; 759 if(debug['a']) 760 Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", p->pc, o1, o2, p); 761 LPUT(o1); 762 LPUT(o2); 763 return 1; 764 } 765 /* cant set annul here because pc has already been counted */ 766 } 767 break; 768 769 case 32: /* jmpl lbra */ 770 if(aflag) 771 return 0; 772 v = 0; 773 if(p->cond) 774 v = p->cond->pc - p->pc; 775 r = p->reg; 776 if(r != NREG && r != 15) 777 diag("cant jmpl other than R15"); 778 o1 = 0x40000000 | ((v/4) & 0x3fffffffL); /* call */ 779 if(p->link && p->cond && isnop(p->link)) { 780 o2 = asmout(p->cond, oplook(p->cond), 1); 781 if(o2) { 782 o1 += 1; 783 if(debug['a']) 784 Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", p->pc, o1, o2, p); 785 LPUT(o1); 786 LPUT(o2); 787 return 1; 788 } 789 } 790 break; 791 792 case 33: /* trap r */ 793 if(aflag) 794 return 0; 795 o1 = opcode(p->as) | (p->from.reg<<14); 796 break; 797 798 case 34: /* rett r1,r2 -> jmpl (r1); rett (r2) */ 799 if(aflag) 800 return 0; 801 o1 = OP_IRR(opcode(AJMPL), 0, p->from.reg, REGZERO); 802 o2 = OP_IRR(opcode(ARETT), 0, p->to.reg, REGZERO); 803 break; 804 805 case 40: /* ldfsr, stfsr, stdq */ 806 if(p->to.type == D_PREG) { 807 r = p->from.reg; 808 if(r == NREG) 809 r = o->param; 810 v = regoff(&p->from); 811 if(p->to.reg == D_FSR) { 812 o1 = OP_IRR(OP3(33), v, r, 0); 813 break; 814 } 815 diag("unknown reg load %d", p->to.reg); 816 } else { 817 r = p->to.reg; 818 if(r == NREG) 819 r = o->param; 820 v = regoff(&p->to); 821 if(p->from.reg == D_FSR) { 822 o1 = OP_IRR(OP3(37), v, r, 0); 823 break; 824 } 825 if(p->as == AMOVD && p->from.reg == D_FPQ) { 826 o1 = OP_IRR(OP3(38), v, r, 0); 827 break; 828 } 829 diag("unknown reg store %d", p->from.reg); 830 } 831 break; 832 833 case 41: /* ldf,ldd */ 834 r = p->from.reg; 835 if(r == NREG) 836 r = o->param; 837 v = regoff(&p->from); 838 if(p->as == AFMOVF || p->as == AMOVW) { 839 o1 = OP_IRR(OP3(32), v, r, p->to.reg); 840 break; 841 } 842 if(p->as == AMOVD || p->as == AFMOVD) { 843 o1 = OP_IRR(OP3(35), v, r, p->to.reg); 844 break; 845 } 846 diag("only MOVD and MOVW to FREG"); 847 break; 848 849 case 42: /* ldd -> ldf,ldf */ 850 /* note should be ldd with proper allignment */ 851 r = p->from.reg; 852 if(r == NREG) 853 r = o->param; 854 v = regoff(&p->from); 855 o1 = OP_IRR(OP3(32), v, r, p->to.reg); 856 o2 = OP_IRR(OP3(32), v+4, r, p->to.reg+1); 857 break; 858 859 case 43: /* stf */ 860 r = p->to.reg; 861 if(r == NREG) 862 r = o->param; 863 v = regoff(&p->to); 864 if(p->as == AFMOVF || p->as == AMOVW) { 865 o1 = OP_IRR(OP3(36), v, r, p->from.reg); 866 break; 867 } 868 if(p->as == AMOVD || p->as == AFMOVD) { 869 o1 = OP_IRR(OP3(39), v, r, p->from.reg); 870 break; 871 } 872 diag("only MOVD and MOVW from FREG"); 873 break; 874 875 case 44: /* std -> stf,stf */ 876 /* note should be std with proper allignment */ 877 r = p->to.reg; 878 if(r == NREG) 879 r = o->param; 880 v = regoff(&p->to); 881 o1 = OP_IRR(OP3(36), v, r, p->from.reg); 882 o2 = OP_IRR(OP3(36), v+4, r, p->from.reg+1); 883 break; 884 885 case 45: /* ldf lorg */ 886 r = p->from.reg; 887 if(r == NREG) 888 r = o->param; 889 v = regoff(&p->from); 890 o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff); /* sethi */ 891 o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP); 892 o3 = OP_IRR(OP3(32), v&0x3ff, REGTMP, p->to.reg); 893 break; 894 895 case 46: /* ldd lorg -> ldf,ldf */ 896 /* note should be ldd with proper allignment */ 897 r = p->from.reg; 898 if(r == NREG) 899 r = o->param; 900 v = regoff(&p->from); 901 o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff); /* sethi */ 902 o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP); 903 o3 = OP_IRR(OP3(32), (v&0x3ff), REGTMP, p->to.reg); 904 o4 = OP_IRR(OP3(32), (v&0x3ff)+4, REGTMP, p->to.reg+1); 905 break; 906 907 case 47: /* stf lorg */ 908 r = p->to.reg; 909 if(r == NREG) 910 r = o->param; 911 v = regoff(&p->to); 912 o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff); /* sethi */ 913 o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP); 914 o3 = OP_IRR(OP3(36), v&0x3ff, REGTMP, p->from.reg); 915 break; 916 917 case 48: /* std lorg -> stf,stf */ 918 /* note should be std with proper allignment */ 919 r = p->to.reg; 920 if(r == NREG) 921 r = o->param; 922 v = regoff(&p->to); 923 o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff); /* sethi */ 924 o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP); 925 o3 = OP_IRR(OP3(36), (v&0x3ff), REGTMP, p->from.reg); 926 o4 = OP_IRR(OP3(36), (v&0x3ff)+4, REGTMP, p->from.reg+1); 927 break; 928 929 case 49: /* fmovd -> fmovf,fmovf */ 930 o1 = OP_RRR(opcode(AFMOVF), p->from.reg, 0, p->to.reg); 931 o2 = OP_RRR(opcode(AFMOVF), p->from.reg+1, 0, p->to.reg+1); 932 break; 933 934 case 50: /* fcmp */ 935 o1 = OP_RRR(opcode(p->as), p->to.reg, p->from.reg, 0); 936 break; 937 938 case 51: /* word */ 939 if(aflag) 940 return 0; 941 o1 = regoff(&p->from); 942 break; 943 944 case 52: /* div */ 945 r = p->reg; 946 if(r == NREG) 947 r = p->to.reg; 948 o1 = OP_IRR(opcode(ASRA), 31, r, REGTMP); 949 o2 = OP_IRR(OP2(48), 0, REGTMP, 0); 950 o3 = OP_RRR(opcode(ADIV), p->from.reg, r, p->to.reg); 951 break; 952 953 case 53: /* divl */ 954 r = p->reg; 955 if(r == NREG) 956 r = p->to.reg; 957 o1 = OP_IRR(OP2(48), 0, REGZERO, 0); 958 o2 = OP_RRR(opcode(ADIVL), p->from.reg, r, p->to.reg); 959 break; 960 961 case 54: /* mod */ 962 r = p->reg; 963 if(r == NREG) 964 r = p->to.reg; 965 o1 = OP_IRR(opcode(ASRA), 31, r, REGTMP); 966 o2 = OP_IRR(OP2(48), 0, REGTMP, 0); 967 o3 = OP_RRR(opcode(ADIV), p->from.reg, r, REGTMP); 968 o4 = OP_RRR(opcode(AMUL), p->from.reg, REGTMP, REGTMP); 969 o5 = OP_RRR(opcode(ASUB), REGTMP, r, p->to.reg); 970 break; 971 972 case 55: /* modl */ 973 r = p->reg; 974 if(r == NREG) 975 r = p->to.reg; 976 o1 = OP_IRR(OP2(48), 0, REGZERO, 0); 977 o2 = OP_RRR(opcode(ADIVL), p->from.reg, r, REGTMP); 978 o3 = OP_RRR(opcode(AMUL), p->from.reg, REGTMP, REGTMP); 979 o4 = OP_RRR(opcode(ASUB), REGTMP, r, p->to.reg); 980 break; 981 982 case 56: /* b(cc) -- annullable */ 983 if(aflag) 984 return 0; 985 r = p->as; 986 v = 0; 987 if(p->cond) 988 v = p->cond->pc - p->pc; 989 o1 = OP_BRA(opcode(r), v/4); 990 if(p->link && p->cond && isnop(p->link)) 991 if(!debug['A']) { 992 o2 = asmout(p->cond, oplook(p->cond), 2); 993 if(o2) { 994 o1 |= 1<<29; /* annul */ 995 o1 += 1; 996 if(debug['a']) 997 Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", p->pc, o1, o2, p); 998 LPUT(o1); 999 LPUT(o2); 1000 return 1; 1001 } 1002 } 1003 break; 1004 } 1005 if(aflag) 1006 return o1; 1007 v = p->pc; 1008 switch(o->size) { 1009 default: 1010 if(debug['a']) 1011 Bprint(&bso, " %.8lux:\t\t%P\n", v, p); 1012 break; 1013 case 4: 1014 if(debug['a']) 1015 Bprint(&bso, " %.8lux: %.8lux\t%P\n", v, o1, p); 1016 LPUT(o1); 1017 break; 1018 case 8: 1019 if(debug['a']) 1020 Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", v, o1, o2, p); 1021 LPUT(o1); 1022 LPUT(o2); 1023 break; 1024 case 12: 1025 if(debug['a']) 1026 Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux%P\n", v, o1, o2, o3, p); 1027 LPUT(o1); 1028 LPUT(o2); 1029 LPUT(o3); 1030 break; 1031 case 16: 1032 if(debug['a']) 1033 Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux%P\n", 1034 v, o1, o2, o3, o4, p); 1035 LPUT(o1); 1036 LPUT(o2); 1037 LPUT(o3); 1038 LPUT(o4); 1039 break; 1040 case 20: 1041 if(debug['a']) 1042 Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux%P\n", 1043 v, o1, o2, o3, o4, o5, p); 1044 LPUT(o1); 1045 LPUT(o2); 1046 LPUT(o3); 1047 LPUT(o4); 1048 LPUT(o5); 1049 break; 1050 } 1051 return 0; 1052 } 1053 1054 int 1055 isnop(Prog *p) 1056 { 1057 if(p->as != AORN) 1058 return 0; 1059 if(p->reg != REGZERO && p->reg != NREG) 1060 return 0; 1061 if(p->from.type != D_REG || p->from.reg != REGZERO) 1062 return 0; 1063 if(p->to.type != D_REG || p->to.reg != REGZERO) 1064 return 0; 1065 return 1; 1066 } 1067 1068 long 1069 opcode(int a) 1070 { 1071 switch(a) { 1072 case AADD: return OP2(0); 1073 case AADDCC: return OP2(16); 1074 case AADDX: return OP2(8); 1075 case AADDXCC: return OP2(24); 1076 1077 case AMUL: return OP2(10); 1078 case ADIV: return OP2(15); 1079 case ADIVL: return OP2(14); 1080 1081 case ATADDCC: return OP2(32); 1082 case ATADDCCTV: return OP2(34); 1083 1084 case ASUB: return OP2(4); 1085 case ASUBCC: return OP2(20); 1086 case ASUBX: return OP2(12); 1087 case ASUBXCC: return OP2(28); 1088 1089 case ATSUBCC: return OP2(33); 1090 case ATSUBCCTV: return OP2(35); 1091 1092 case AMULSCC: return OP2(36); 1093 case ASAVE: return OP2(60); 1094 case ARESTORE: return OP2(61); 1095 1096 case AAND: return OP2(1); 1097 case AANDCC: return OP2(17); 1098 case AANDN: return OP2(5); 1099 case AANDNCC: return OP2(21); 1100 1101 case AOR: return OP2(2); 1102 case AORCC: return OP2(18); 1103 case AORN: return OP2(6); 1104 case AORNCC: return OP2(22); 1105 1106 case AXOR: return OP2(3); 1107 case AXORCC: return OP2(19); 1108 case AXNOR: return OP2(7); 1109 case AXNORCC: return OP2(23); 1110 1111 case ASLL: return OP2(37); 1112 case ASRL: return OP2(38); 1113 case ASRA: return OP2(39); 1114 1115 case AJMPL: 1116 case AJMP: return OP2(56); 1117 case ARETT: return OP2(57); 1118 1119 case AMOVBU: return OP3(1); /* ldub */ 1120 case AMOVB: return OP3(9); /* ldsb */ 1121 case AMOVHU: return OP3(2); /* lduh */ 1122 case AMOVH: return OP3(10); /* ldsh */ 1123 case AMOVW: return OP3(0); /* ld */ 1124 case AMOVD: return OP3(3); /* ldd */ 1125 1126 case AMOVBU+AEND: 1127 case AMOVB+AEND:return OP3(5); /* stb */ 1128 1129 case AMOVHU+AEND: 1130 case AMOVH+AEND:return OP3(6); /* sth */ 1131 1132 case AMOVW+AEND:return OP3(4); /* st */ 1133 1134 case AMOVD+AEND:return OP3(7); /* std */ 1135 1136 case ASWAP: /* swap is symmetric */ 1137 case ASWAP+AEND:return OP3(15); 1138 1139 case ATAS: return OP3(13); /* tas is really ldstub */ 1140 1141 case ABN: return OPB(0); 1142 case ABE: return OPB(1); 1143 case ABLE: return OPB(2); 1144 case ABL: return OPB(3); 1145 case ABLEU: return OPB(4); 1146 case ABCS: return OPB(5); 1147 case ABNEG: return OPB(6); 1148 case ABVS: return OPB(7); 1149 case ABA: return OPB(8); 1150 case ABNE: return OPB(9); 1151 case ABG: return OPB(10); 1152 case ABGE: return OPB(11); 1153 case ABGU: return OPB(12); 1154 case ABCC: return OPB(13); 1155 case ABPOS: return OPB(14); 1156 case ABVC: return OPB(15); 1157 1158 case AFBA: return OPFB(8); 1159 case AFBE: return OPFB(9); 1160 case AFBG: return OPFB(6); 1161 case AFBGE: return OPFB(11); 1162 case AFBL: return OPFB(4); 1163 case AFBLE: return OPFB(13); 1164 case AFBLG: return OPFB(2); 1165 case AFBN: return OPFB(0); 1166 case AFBNE: return OPFB(1); 1167 case AFBO: return OPFB(15); 1168 case AFBU: return OPFB(7); 1169 case AFBUE: return OPFB(10); 1170 case AFBUG: return OPFB(5); 1171 case AFBUGE: return OPFB(12); 1172 case AFBUL: return OPFB(3); 1173 case AFBULE: return OPFB(14); 1174 1175 case ATN: return OPT(0); 1176 case ATE: return OPT(1); 1177 case ATLE: return OPT(2); 1178 case ATL: return OPT(3); 1179 case ATLEU: return OPT(4); 1180 case ATCS: return OPT(5); 1181 case ATNEG: return OPT(6); 1182 case ATVS: return OPT(7); 1183 case ATA: return OPT(8); 1184 case ATNE: return OPT(9); 1185 case ATG: return OPT(10); 1186 case ATGE: return OPT(11); 1187 case ATGU: return OPT(12); 1188 case ATCC: return OPT(13); 1189 case ATPOS: return OPT(14); 1190 case ATVC: return OPT(15); 1191 1192 case AFADDF: return OPF1(65); 1193 case AFADDD: return OPF1(66); 1194 case AFADDX: return OPF1(67); 1195 case AFSUBF: return OPF1(69); 1196 case AFSUBD: return OPF1(70); 1197 case AFSUBX: return OPF1(71); 1198 case AFMULF: return OPF1(73); 1199 case AFMULD: return OPF1(74); 1200 case AFMULX: return OPF1(75); 1201 case AFDIVF: return OPF1(77); 1202 case AFDIVD: return OPF1(78); 1203 case AFDIVX: return OPF1(79); 1204 1205 case AFMOVF: return OPF1(1); 1206 case AFNEGF: return OPF1(5); 1207 case AFABSF: return OPF1(9); 1208 1209 case AFSQRTF: return OPF1(41); 1210 case AFSQRTD: return OPF1(42); 1211 case AFSQRTX: return OPF1(43); 1212 1213 case AFMOVWF: return OPF1(196); 1214 case AFMOVWD: return OPF1(200); 1215 case AFMOVWX: return OPF1(204); 1216 case AFMOVFW: return OPF1(209); 1217 case AFMOVDW: return OPF1(210); 1218 case AFMOVXW: return OPF1(211); 1219 case AFMOVFD: return OPF1(201); 1220 case AFMOVFX: return OPF1(205); 1221 case AFMOVDF: return OPF1(198); 1222 case AFMOVDX: return OPF1(206); 1223 case AFMOVXF: return OPF1(199); 1224 case AFMOVXD: return OPF1(203); 1225 1226 case AFCMPF: return OPF2(81); 1227 case AFCMPD: return OPF2(82); 1228 case AFCMPX: return OPF2(83); 1229 case AFCMPEF: return OPF2(85); 1230 case AFCMPED: return OPF2(86); 1231 case AFCMPEX: return OPF2(87); 1232 1233 case AUNIMP: return 0; 1234 } 1235 diag("bad opcode %A", a); 1236 return 0; 1237 } 1238