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