1 #include "l.h" 2 3 long OFFSET; 4 /* 5 long BADOFFSET = -1; 6 7 if(OFFSET <= BADOFFSET && OFFSET+4 > BADOFFSET)\ 8 abort();\ 9 OFFSET += 4;\ 10 11 if(OFFSET == BADOFFSET)\ 12 abort();\ 13 OFFSET++;\ 14 */ 15 16 #define LPUT(c)\ 17 {\ 18 cbp[0] = (c)>>24;\ 19 cbp[1] = (c)>>16;\ 20 cbp[2] = (c)>>8;\ 21 cbp[3] = (c);\ 22 cbp += 4;\ 23 cbc -= 4;\ 24 if(cbc <= 0)\ 25 cflush();\ 26 } 27 28 #define CPUT(c)\ 29 {\ 30 cbp[0] = (c);\ 31 cbp++;\ 32 cbc--;\ 33 if(cbc <= 0)\ 34 cflush();\ 35 } 36 37 long 38 entryvalue(void) 39 { 40 char *a; 41 Sym *s; 42 43 a = INITENTRY; 44 if(*a >= '0' && *a <= '9') 45 return atolwhex(a); 46 s = lookup(a, 0); 47 if(s->type == 0) 48 return INITTEXT; 49 if(s->type != STEXT && s->type != SLEAF) 50 diag("entry not text: %s", s->name); 51 return s->value; 52 } 53 54 void 55 asmb(void) 56 { 57 Prog *p; 58 long t; 59 Optab *o; 60 61 if(debug['v']) 62 Bprint(&bso, "%5.2f asm\n", cputime()); 63 Bflush(&bso); 64 OFFSET = HEADR; 65 seek(cout, OFFSET, 0); 66 pc = INITTEXT; 67 for(p = firstp; p != P; p = p->link) { 68 if(p->as == ATEXT) { 69 curtext = p; 70 autosize = p->to.offset + 4; 71 } 72 if(p->pc != pc) { 73 diag("phase error %lux sb %lux\n", 74 p->pc, pc); 75 if(!debug['a']) 76 prasm(curp); 77 pc = p->pc; 78 } 79 curp = p; 80 o = oplook(p); /* could probably avoid this call */ 81 if(asmout(p, o, 0)) { 82 p = p->link; 83 pc += 4; 84 } 85 pc += o->size; 86 } 87 if(debug['a']) 88 Bprint(&bso, "\n"); 89 Bflush(&bso); 90 cflush(); 91 92 curtext = P; 93 switch(HEADTYPE) { 94 case 0: 95 case 4: 96 OFFSET = rnd(HEADR+textsize, 4096); 97 seek(cout, OFFSET, 0); 98 break; 99 case 1: 100 case 2: 101 case 3: 102 case 5: 103 OFFSET = HEADR+textsize; 104 seek(cout, OFFSET, 0); 105 break; 106 } 107 for(t = 0; t < datsize; t += sizeof(buf)-100) { 108 if(datsize-t > sizeof(buf)-100) 109 datblk(t, sizeof(buf)-100); 110 else 111 datblk(t, datsize-t); 112 } 113 114 symsize = 0; 115 lcsize = 0; 116 if(!debug['s']) { 117 if(debug['v']) 118 Bprint(&bso, "%5.2f sym\n", cputime()); 119 Bflush(&bso); 120 switch(HEADTYPE) { 121 case 0: 122 case 4: 123 OFFSET = rnd(HEADR+textsize, 4096)+datsize; 124 seek(cout, OFFSET, 0); 125 break; 126 case 3: 127 case 2: 128 case 1: 129 case 5: 130 OFFSET = HEADR+textsize+datsize; 131 seek(cout, OFFSET, 0); 132 break; 133 } 134 if(!debug['s']) 135 asmsym(); 136 if(debug['v']) 137 Bprint(&bso, "%5.2f pc\n", cputime()); 138 Bflush(&bso); 139 if(!debug['s']) 140 asmlc(); 141 cflush(); 142 } 143 144 if(debug['v']) 145 Bprint(&bso, "%5.2f header\n", cputime()); 146 Bflush(&bso); 147 OFFSET = 0; 148 seek(cout, OFFSET, 0); 149 switch(HEADTYPE) { 150 case 0: 151 lput(0x160L<<16); /* magic and sections */ 152 lput(0L); /* time and date */ 153 lput(rnd(HEADR+textsize, 4096)+datsize); 154 lput(symsize); /* nsyms */ 155 lput((0x38L<<16)|7L); /* size of optional hdr and flags */ 156 lput((0413<<16)|0437L); /* magic and version */ 157 lput(rnd(HEADR+textsize, 4096)); /* sizes */ 158 lput(datsize); 159 lput(bsssize); 160 lput(entryvalue()); /* va of entry */ 161 lput(INITTEXT-HEADR); /* va of base of text */ 162 lput(INITDAT); /* va of base of data */ 163 lput(INITDAT+datsize); /* va of base of bss */ 164 lput(~0L); /* gp reg mask */ 165 lput(0L); 166 lput(0L); 167 lput(0L); 168 lput(0L); 169 lput(~0L); /* gp value ?? */ 170 break; 171 case 1: 172 lput(0x160L<<16); /* magic and sections */ 173 lput(0L); /* time and date */ 174 lput(HEADR+textsize+datsize); 175 lput(symsize); /* nsyms */ 176 lput((0x38L<<16)|7L); /* size of optional hdr and flags */ 177 178 lput((0407<<16)|0437L); /* magic and version */ 179 lput(textsize); /* sizes */ 180 lput(datsize); 181 lput(bsssize); 182 lput(entryvalue()); /* va of entry */ 183 lput(INITTEXT); /* va of base of text */ 184 lput(INITDAT); /* va of base of data */ 185 lput(INITDAT+datsize); /* va of base of bss */ 186 lput(~0L); /* gp reg mask */ 187 lput(lcsize); 188 lput(0L); 189 lput(0L); 190 lput(0L); 191 lput(~0L); /* gp value ?? */ 192 lput(0L); /* complete mystery */ 193 break; 194 case 2: 195 lput(0x407); /* magic */ 196 lput(textsize); /* sizes */ 197 lput(datsize); 198 lput(bsssize); 199 lput(symsize); /* nsyms */ 200 lput(entryvalue()); /* va of entry */ 201 lput(0L); 202 lput(lcsize); 203 break; 204 case 3: 205 lput((0x160L<<16)|3L); /* magic and sections */ 206 lput(time(0)); /* time and date */ 207 lput(HEADR+textsize+datsize); 208 lput(symsize); /* nsyms */ 209 lput((0x38L<<16)|7L); /* size of optional hdr and flags */ 210 211 lput((0407<<16)|0437L); /* magic and version */ 212 lput(textsize); /* sizes */ 213 lput(datsize); 214 lput(bsssize); 215 lput(entryvalue()); /* va of entry */ 216 lput(INITTEXT); /* va of base of text */ 217 lput(INITDAT); /* va of base of data */ 218 lput(INITDAT+datsize); /* va of base of bss */ 219 lput(~0L); /* gp reg mask */ 220 lput(lcsize); 221 lput(0L); 222 lput(0L); 223 lput(0L); 224 lput(~0L); /* gp value ?? */ 225 226 strnput(".text", 8); /* text segment */ 227 lput(INITTEXT); /* address */ 228 lput(INITTEXT); 229 lput(textsize); 230 lput(HEADR); 231 lput(0L); 232 lput(HEADR+textsize+datsize+symsize); 233 lput(lcsize); /* line number size */ 234 lput(0x20L); /* flags */ 235 236 strnput(".data", 8); /* data segment */ 237 lput(INITDAT); /* address */ 238 lput(INITDAT); 239 lput(datsize); 240 lput(HEADR+textsize); 241 lput(0L); 242 lput(0L); 243 lput(0L); 244 lput(0x40L); /* flags */ 245 246 strnput(".bss", 8); /* bss segment */ 247 lput(INITDAT+datsize); /* address */ 248 lput(INITDAT+datsize); 249 lput(bsssize); 250 lput(0L); 251 lput(0L); 252 lput(0L); 253 lput(0L); 254 lput(0x80L); /* flags */ 255 break; 256 case 4: 257 258 lput((0x160L<<16)|3L); /* magic and sections */ 259 lput(time(0)); /* time and date */ 260 lput(rnd(HEADR+textsize, 4096)+datsize); 261 lput(symsize); /* nsyms */ 262 lput((0x38L<<16)|7L); /* size of optional hdr and flags */ 263 264 lput((0413<<16)|01012L); /* magic and version */ 265 lput(textsize); /* sizes */ 266 lput(datsize); 267 lput(bsssize); 268 lput(entryvalue()); /* va of entry */ 269 lput(INITTEXT); /* va of base of text */ 270 lput(INITDAT); /* va of base of data */ 271 lput(INITDAT+datsize); /* va of base of bss */ 272 lput(~0L); /* gp reg mask */ 273 lput(lcsize); 274 lput(0L); 275 lput(0L); 276 lput(0L); 277 lput(~0L); /* gp value ?? */ 278 279 strnput(".text", 8); /* text segment */ 280 lput(INITTEXT); /* address */ 281 lput(INITTEXT); 282 lput(textsize); 283 lput(HEADR); 284 lput(0L); 285 lput(HEADR+textsize+datsize+symsize); 286 lput(lcsize); /* line number size */ 287 lput(0x20L); /* flags */ 288 289 strnput(".data", 8); /* data segment */ 290 lput(INITDAT); /* address */ 291 lput(INITDAT); 292 lput(datsize); 293 lput(rnd(HEADR+textsize, 4096)); /* sizes */ 294 lput(0L); 295 lput(0L); 296 lput(0L); 297 lput(0x40L); /* flags */ 298 299 strnput(".bss", 8); /* bss segment */ 300 lput(INITDAT+datsize); /* address */ 301 lput(INITDAT+datsize); 302 lput(bsssize); 303 lput(0L); 304 lput(0L); 305 lput(0L); 306 lput(0L); 307 lput(0x80L); /* flags */ 308 break; 309 case 5: 310 strnput("\177ELF", 4); /* e_ident */ 311 CPUT(1); /* class = 32 bit */ 312 CPUT(2); /* data = MSB */ 313 CPUT(1); /* version = CURRENT */ 314 strnput("", 9); 315 lput((2L<<16)|8L); /* type = EXEC; machine = MIPS */ 316 lput(1L); /* version = CURRENT */ 317 lput(entryvalue()); /* entry vaddr */ 318 lput(52L); /* offset to first phdr */ 319 lput(0L); /* offset to first shdr */ 320 lput(0L); /* flags = MIPS */ 321 lput((52L<<16)|32L); /* Ehdr & Phdr sizes*/ 322 lput((3L<<16)|0L); /* # Phdrs & Shdr size */ 323 lput((0L<<16)|0L); /* # Shdrs & shdr string size */ 324 325 lput(1L); /* text - type = PT_LOAD */ 326 lput(0L); /* file offset */ 327 lput(INITTEXT-HEADR); /* vaddr */ 328 lput(INITTEXT-HEADR); /* paddr */ 329 lput(HEADR+textsize); /* file size */ 330 lput(HEADR+textsize); /* memory size */ 331 lput(0x05L); /* protections = RWX */ 332 lput(0x10000L); /* alignment code?? */ 333 334 lput(1L); /* data - type = PT_LOAD */ 335 lput(HEADR+textsize); /* file offset */ 336 lput(INITDAT); /* vaddr */ 337 lput(INITDAT); /* paddr */ 338 lput(datsize); /* file size */ 339 lput(datsize+bsssize); /* memory size */ 340 lput(0x06L); /* protections = RW */ 341 lput(0x10000L); /* alignment code?? */ 342 343 lput(0L); /* data - type = PT_NULL */ 344 lput(HEADR+textsize+datsize); /* file offset */ 345 lput(0L); 346 lput(0L); 347 lput(symsize); /* symbol table size */ 348 lput(lcsize); /* line number size */ 349 lput(0x04L); /* protections = R */ 350 lput(0x04L); /* alignment code?? */ 351 } 352 cflush(); 353 } 354 355 void 356 strnput(char *s, int n) 357 { 358 for(; *s; s++){ 359 CPUT(*s); 360 n--; 361 } 362 for(; n > 0; n--) 363 CPUT(0); 364 } 365 366 void 367 lput(long l) 368 { 369 370 LPUT(l); 371 } 372 373 void 374 cflush(void) 375 { 376 int n; 377 378 n = sizeof(buf.cbuf) - cbc; 379 if(n) 380 write(cout, buf.cbuf, n); 381 cbp = buf.cbuf; 382 cbc = sizeof(buf.cbuf); 383 } 384 385 void 386 nopstat(char *f, Count *c) 387 { 388 if(c->outof) 389 Bprint(&bso, "%s delay %ld/%ld (%.2f)\n", f, 390 c->outof - c->count, c->outof, 391 (double)(c->outof - c->count)/c->outof); 392 } 393 394 void 395 asmsym(void) 396 { 397 Prog *p; 398 Auto *a; 399 Sym *s; 400 int h; 401 402 s = lookup("etext", 0); 403 if(s->type == STEXT) 404 putsymb(s->name, 'T', s->value, s->version); 405 406 for(h=0; h<NHASH; h++) 407 for(s=hash[h]; s!=S; s=s->link) 408 switch(s->type) { 409 case SCONST: 410 putsymb(s->name, 'D', s->value, s->version); 411 continue; 412 413 case SDATA: 414 putsymb(s->name, 'D', s->value+INITDAT, s->version); 415 continue; 416 417 case SBSS: 418 putsymb(s->name, 'B', s->value+INITDAT, s->version); 419 continue; 420 421 case SFILE: 422 putsymb(s->name, 'f', s->value, s->version); 423 continue; 424 } 425 426 for(p=textp; p!=P; p=p->cond) { 427 s = p->from.sym; 428 if(s->type != STEXT && s->type != SLEAF) 429 continue; 430 431 /* filenames first */ 432 for(a=p->to.autom; a; a=a->link) 433 if(a->type == D_FILE) 434 putsymb(a->sym->name, 'z', a->offset, 0); 435 else 436 if(a->type == D_FILE1) 437 putsymb(a->sym->name, 'Z', a->offset, 0); 438 439 if(s->type == STEXT) 440 putsymb(s->name, 'T', s->value, s->version); 441 else 442 putsymb(s->name, 'L', s->value, s->version); 443 444 /* frame, auto and param after */ 445 putsymb(".frame", 'm', p->to.offset+4, 0); 446 for(a=p->to.autom; a; a=a->link) 447 if(a->type == D_AUTO) 448 putsymb(a->sym->name, 'a', -a->offset, 0); 449 else 450 if(a->type == D_PARAM) 451 putsymb(a->sym->name, 'p', a->offset, 0); 452 } 453 if(debug['v'] || debug['n']) 454 Bprint(&bso, "symsize = %lud\n", symsize); 455 Bflush(&bso); 456 } 457 458 void 459 putsymb(char *s, int t, long v, int ver) 460 { 461 int i, f; 462 463 if(t == 'f') 464 s++; 465 LPUT(v); 466 if(ver) 467 t += 'a' - 'A'; 468 CPUT(t+0x80); /* 0x80 is variable length */ 469 470 if(t == 'Z' || t == 'z') { 471 CPUT(s[0]); 472 for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) { 473 CPUT(s[i]); 474 CPUT(s[i+1]); 475 } 476 CPUT(0); 477 CPUT(0); 478 i++; 479 } 480 else { 481 for(i=0; s[i]; i++) 482 CPUT(s[i]); 483 CPUT(0); 484 } 485 symsize += 4 + 1 + i + 1; 486 487 if(debug['n']) { 488 if(t == 'z' || t == 'Z') { 489 Bprint(&bso, "%c %.8lux ", t, v); 490 for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) { 491 f = ((s[i]&0xff) << 8) | (s[i+1]&0xff); 492 Bprint(&bso, "/%x", f); 493 } 494 Bprint(&bso, "\n"); 495 return; 496 } 497 if(ver) 498 Bprint(&bso, "%c %.8lux %s<%d>\n", t, v, s, ver); 499 else 500 Bprint(&bso, "%c %.8lux %s\n", t, v, s); 501 } 502 } 503 504 #define MINLC 4 505 void 506 asmlc(void) 507 { 508 long oldpc, oldlc; 509 Prog *p; 510 long v, s; 511 512 oldpc = INITTEXT; 513 oldlc = 0; 514 for(p = firstp; p != P; p = p->link) { 515 if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) { 516 if(p->as == ATEXT) 517 curtext = p; 518 if(debug['L']) 519 Bprint(&bso, "%6lux %P\n", 520 p->pc, p); 521 continue; 522 } 523 if(debug['L']) 524 Bprint(&bso, "\t\t%6ld", lcsize); 525 v = (p->pc - oldpc) / MINLC; 526 while(v) { 527 s = 127; 528 if(v < 127) 529 s = v; 530 CPUT(s+128); /* 129-255 +pc */ 531 if(debug['L']) 532 Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128); 533 v -= s; 534 lcsize++; 535 } 536 s = p->line - oldlc; 537 oldlc = p->line; 538 oldpc = p->pc + MINLC; 539 if(s > 64 || s < -64) { 540 CPUT(0); /* 0 vv +lc */ 541 CPUT(s>>24); 542 CPUT(s>>16); 543 CPUT(s>>8); 544 CPUT(s); 545 if(debug['L']) { 546 if(s > 0) 547 Bprint(&bso, " lc+%ld(%d,%ld)\n", 548 s, 0, s); 549 else 550 Bprint(&bso, " lc%ld(%d,%ld)\n", 551 s, 0, s); 552 Bprint(&bso, "%6lux %P\n", 553 p->pc, p); 554 } 555 lcsize += 5; 556 continue; 557 } 558 if(s > 0) { 559 CPUT(0+s); /* 1-64 +lc */ 560 if(debug['L']) { 561 Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s); 562 Bprint(&bso, "%6lux %P\n", 563 p->pc, p); 564 } 565 } else { 566 CPUT(64-s); /* 65-128 -lc */ 567 if(debug['L']) { 568 Bprint(&bso, " lc%ld(%ld)\n", s, 64-s); 569 Bprint(&bso, "%6lux %P\n", 570 p->pc, p); 571 } 572 } 573 lcsize++; 574 } 575 while(lcsize & 1) { 576 s = 129; 577 CPUT(s); 578 lcsize++; 579 } 580 if(debug['v'] || debug['L']) 581 Bprint(&bso, "lcsize = %ld\n", lcsize); 582 Bflush(&bso); 583 } 584 585 void 586 datblk(long s, long n) 587 { 588 Prog *p; 589 char *cast; 590 long l, fl, j, d; 591 int i, c; 592 593 memset(buf.dbuf, 0, n+100); 594 for(p = datap; p != P; p = p->link) { 595 curp = p; 596 l = p->from.sym->value + p->from.offset - s; 597 c = p->reg; 598 i = 0; 599 if(l < 0) { 600 if(l+c <= 0) 601 continue; 602 while(l < 0) { 603 l++; 604 i++; 605 } 606 } 607 if(l >= n) 608 continue; 609 if(p->as != AINIT && p->as != ADYNT) { 610 for(j=l+(c-i)-1; j>=l; j--) 611 if(buf.dbuf[j]) { 612 print("%P\n", p); 613 diag("multiple initialization\n"); 614 break; 615 } 616 } 617 switch(p->to.type) { 618 default: 619 diag("unknown mode in initialization\n%P\n", p); 620 break; 621 622 case D_FCONST: 623 switch(c) { 624 default: 625 case 4: 626 fl = ieeedtof(p->to.ieee); 627 cast = (char*)&fl; 628 for(; i<c; i++) { 629 buf.dbuf[l] = cast[fnuxi8[i+4]]; 630 l++; 631 } 632 break; 633 case 8: 634 cast = (char*)p->to.ieee; 635 for(; i<c; i++) { 636 buf.dbuf[l] = cast[fnuxi8[i]]; 637 l++; 638 } 639 break; 640 } 641 break; 642 643 case D_SCONST: 644 for(; i<c; i++) { 645 buf.dbuf[l] = p->to.sval[i]; 646 l++; 647 } 648 break; 649 650 case D_CONST: 651 d = p->to.offset; 652 if(p->to.sym) { 653 if(p->to.sym->type == STEXT || 654 p->to.sym->type == SLEAF) 655 d += p->to.sym->value; 656 if(p->to.sym->type == SDATA) 657 d += p->to.sym->value + INITDAT; 658 if(p->to.sym->type == SBSS) 659 d += p->to.sym->value + INITDAT; 660 } 661 cast = (char*)&d; 662 switch(c) { 663 default: 664 diag("bad nuxi %d %d\n%P\n", c, i, curp); 665 break; 666 case 1: 667 for(; i<c; i++) { 668 buf.dbuf[l] = cast[inuxi1[i]]; 669 l++; 670 } 671 break; 672 case 2: 673 for(; i<c; i++) { 674 buf.dbuf[l] = cast[inuxi2[i]]; 675 l++; 676 } 677 break; 678 case 4: 679 for(; i<c; i++) { 680 buf.dbuf[l] = cast[inuxi4[i]]; 681 l++; 682 } 683 break; 684 } 685 break; 686 } 687 } 688 write(cout, buf.dbuf, n); 689 } 690 691 #define OP_RRR(op,r1,r2,r3)\ 692 (op|(((r1)&31L)<<16)|(((r2)&31L)<<21)|(((r3)&31L)<<11)) 693 #define OP_IRR(op,i,r2,r3)\ 694 (op|((i)&0xffffL)|(((r2)&31L)<<21)|(((r3)&31L)<<16)) 695 #define OP_SRR(op,s,r2,r3)\ 696 (op|(((s)&31L)<<6)|(((r2)&31L)<<16)|(((r3)&31L)<<11)) 697 #define OP_FRRR(op,r1,r2,r3)\ 698 (op|(((r1)&31L)<<16)|(((r2)&31L)<<11)|(((r3)&31L)<<6)) 699 #define OP_JMP(op,i)\ 700 ((op)|((i)&0x3ffffffL)) 701 702 #define OP(x,y)\ 703 (((x)<<3)|((y)<<0)) 704 #define SP(x,y)\ 705 (((x)<<29)|((y)<<26)) 706 #define BCOND(x,y)\ 707 (((x)<<19)|((y)<<16)) 708 #define MMU(x,y)\ 709 (SP(2,0)|(16<<21)|((x)<<3)|((y)<<0)) 710 #define FPF(x,y)\ 711 (SP(2,1)|(16<<21)|((x)<<3)|((y)<<0)) 712 #define FPD(x,y)\ 713 (SP(2,1)|(17<<21)|((x)<<3)|((y)<<0)) 714 #define FPW(x,y)\ 715 (SP(2,1)|(20<<21)|((x)<<3)|((y)<<0)) 716 717 int 718 asmout(Prog *p, Optab *o, int aflag) 719 { 720 long o1, o2, o3, o4, o5, v; 721 Prog *ct; 722 int r, a; 723 724 o1 = 0; 725 o2 = 0; 726 o3 = 0; 727 o4 = 0; 728 o5 = 0; 729 switch(o->type) { 730 default: 731 diag("unknown type %d\n", o->type); 732 if(!debug['a']) 733 prasm(p); 734 break; 735 736 case 0: /* pseudo ops */ 737 if(aflag) { 738 if(p->link) { 739 if(p->as == ATEXT) { 740 ct = curtext; 741 o2 = autosize; 742 curtext = p; 743 autosize = p->to.offset + 4; 744 o1 = asmout(p->link, oplook(p->link), aflag); 745 curtext = ct; 746 autosize = o2; 747 } else 748 o1 = asmout(p->link, oplook(p->link), aflag); 749 } 750 return o1; 751 } 752 break; 753 754 case 1: /* mov[v] r1,r2 ==> OR r1,r0,r2 */ 755 o1 = OP_RRR(oprrr(AOR), p->from.reg, REGZERO, p->to.reg); 756 break; 757 758 case 2: /* add/sub r1,[r2],r3 */ 759 r = p->reg; 760 if(r == NREG) 761 r = p->to.reg; 762 o1 = OP_RRR(oprrr(p->as), p->from.reg, r, p->to.reg); 763 break; 764 765 case 3: /* mov $soreg, r ==> or/add $i,o,r */ 766 v = regoff(&p->from); 767 r = p->from.reg; 768 if(r == NREG) 769 r = o->param; 770 a = AADDU; 771 if(o->a1 == C_ANDCON) 772 a = AOR; 773 o1 = OP_IRR(opirr(a), v, r, p->to.reg); 774 break; 775 776 case 4: /* add $scon,[r1],r2 */ 777 v = regoff(&p->from); 778 r = p->reg; 779 if(r == NREG) 780 r = p->to.reg; 781 o1 = OP_IRR(opirr(p->as), v, r, p->to.reg); 782 break; 783 784 case 5: /* syscall */ 785 if(aflag) 786 return 0; 787 o1 = oprrr(p->as); 788 break; 789 790 case 6: /* beq r1,[r2],sbra */ 791 if(aflag) 792 return 0; 793 if(p->cond == P) 794 v = -4 >> 2; 795 else 796 v = (p->cond->pc - pc-4) >> 2; 797 o1 = OP_IRR(opirr(p->as), v, p->from.reg, p->reg); 798 break; 799 800 case 7: /* mov r, soreg ==> sw o(r) */ 801 r = p->to.reg; 802 if(r == NREG) 803 r = o->param; 804 v = regoff(&p->to); 805 o1 = OP_IRR(opirr(p->as), v, r, p->from.reg); 806 break; 807 808 case 8: /* mov soreg, r ==> lw o(r) */ 809 r = p->from.reg; 810 if(r == NREG) 811 r = o->param; 812 v = regoff(&p->from); 813 o1 = OP_IRR(opirr(p->as+ALAST), v, r, p->to.reg); 814 break; 815 816 case 9: /* asl r1,[r2],r3 */ 817 r = p->reg; 818 if(r == NREG) 819 r = p->to.reg; 820 o1 = OP_RRR(oprrr(p->as), r, p->from.reg, p->to.reg); 821 break; 822 823 case 10: /* add $con,[r1],r2 ==> mov $con,t; add t,[r1],r2 */ 824 v = regoff(&p->from); 825 r = AOR; 826 if(v < 0) 827 r = AADDU; 828 o1 = OP_IRR(opirr(r), v, 0, REGTMP); 829 r = p->reg; 830 if(r == NREG) 831 r = p->to.reg; 832 o2 = OP_RRR(oprrr(p->as), REGTMP, r, p->to.reg); 833 break; 834 835 case 11: /* jmp lbra */ 836 if(aflag) 837 return 0; 838 if(p->cond == P) 839 v = p->pc >> 2; 840 else 841 v = p->cond->pc >> 2; 842 o1 = OP_JMP(opirr(p->as), v); 843 if(!debug['Y'] && p->link && p->cond && isnop(p->link)) { 844 nop.branch.count--; 845 nop.branch.outof--; 846 nop.jump.outof++; 847 o2 = asmout(p->cond, oplook(p->cond), 1); 848 if(o2) { 849 o1 += 1; 850 if(debug['a']) 851 Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", 852 p->pc, o1, o2, p); 853 LPUT(o1); 854 LPUT(o2); 855 return 1; 856 } 857 } 858 break; 859 860 case 12: /* movbs r,r */ 861 v = 16; 862 if(p->as == AMOVB) 863 v = 24; 864 o1 = OP_SRR(opirr(ASLL), v, p->from.reg, p->to.reg); 865 o2 = OP_SRR(opirr(ASRA), v, p->to.reg, p->to.reg); 866 break; 867 868 case 13: /* movbu r,r */ 869 if(p->as == AMOVBU) 870 o1 = OP_IRR(opirr(AAND), 0xffL, p->from.reg, p->to.reg); 871 else 872 o1 = OP_IRR(opirr(AAND), 0xffffL, p->from.reg, p->to.reg); 873 break; 874 875 case 16: /* sll $c,[r1],r2 */ 876 v = regoff(&p->from); 877 r = p->reg; 878 if(r == NREG) 879 r = p->to.reg; 880 if(v >= 32) 881 o1 = OP_SRR(opirr(p->as+ALAST), v-32, r, p->to.reg); 882 else 883 o1 = OP_SRR(opirr(p->as), v, r, p->to.reg); 884 break; 885 886 case 18: /* jmp [r1],0(r2) */ 887 if(aflag) 888 return 0; 889 r = p->reg; 890 if(r == NREG) 891 r = o->param; 892 o1 = OP_RRR(oprrr(p->as), 0, p->to.reg, r); 893 break; 894 895 case 19: /* mov $lcon,r ==> lu+or */ 896 v = regoff(&p->from); 897 o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, p->to.reg); 898 o2 = OP_IRR(opirr(AOR), v, p->to.reg, p->to.reg); 899 break; 900 901 case 20: /* mov lohi,r */ 902 r = OP(2,0); /* mfhi */ 903 if(p->from.type == D_LO) 904 r = OP(2,2); /* mflo */ 905 o1 = OP_RRR(r, REGZERO, REGZERO, p->to.reg); 906 break; 907 908 case 21: /* mov r,lohi */ 909 r = OP(2,1); /* mthi */ 910 if(p->to.type == D_LO) 911 r = OP(2,3); /* mtlo */ 912 o1 = OP_RRR(r, REGZERO, p->from.reg, REGZERO); 913 break; 914 915 case 22: /* mul r1,r2 */ 916 o1 = OP_RRR(oprrr(p->as), p->from.reg, p->reg, REGZERO); 917 break; 918 919 case 23: /* add $lcon,r1,r2 ==> lu+or+add */ 920 v = regoff(&p->from); 921 if(p->to.reg == REGTMP || p->reg == REGTMP) 922 diag("cant synthesize large constant\n%P\n", p); 923 o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP); 924 o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP); 925 r = p->reg; 926 if(r == NREG) 927 r = p->to.reg; 928 o3 = OP_RRR(oprrr(p->as), REGTMP, r, p->to.reg); 929 break; 930 931 case 24: /* mov $ucon,,r ==> lu r */ 932 v = regoff(&p->from); 933 o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, p->to.reg); 934 break; 935 936 case 25: /* add/and $ucon,[r1],r2 ==> lu $con,t; add t,[r1],r2 */ 937 v = regoff(&p->from); 938 o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP); 939 r = p->reg; 940 if(r == NREG) 941 r = p->to.reg; 942 o2 = OP_RRR(oprrr(p->as), REGTMP, r, p->to.reg); 943 break; 944 945 case 26: /* mov $lsext/auto/oreg,,r2 ==> lu+or+add */ 946 v = regoff(&p->from); 947 if(p->to.reg == REGTMP) 948 diag("cant synthesize large constant\n%P\n", p); 949 o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP); 950 o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP); 951 r = p->from.reg; 952 if(r == NREG) 953 r = o->param; 954 o3 = OP_RRR(oprrr(AADDU), REGTMP, r, p->to.reg); 955 break; 956 957 case 27: /* mov [sl]ext/auto/oreg,fr ==> lwc1 o(r) */ 958 r = p->from.reg; 959 if(r == NREG) 960 r = o->param; 961 v = regoff(&p->from); 962 switch(o->size) { 963 case 20: 964 o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP); 965 o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP); 966 o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP); 967 o4 = OP_IRR(opirr(AMOVF+ALAST), 0, REGTMP, p->to.reg+1); 968 o5 = OP_IRR(opirr(AMOVF+ALAST), 4, REGTMP, p->to.reg); 969 break; 970 case 16: 971 o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP); 972 o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP); 973 o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP); 974 o4 = OP_IRR(opirr(AMOVF+ALAST), 0, REGTMP, p->to.reg); 975 break; 976 case 8: 977 o1 = OP_IRR(opirr(AMOVF+ALAST), v, r, p->to.reg+1); 978 o2 = OP_IRR(opirr(AMOVF+ALAST), v+4, r, p->to.reg); 979 break; 980 case 4: 981 o1 = OP_IRR(opirr(AMOVF+ALAST), v, r, p->to.reg); 982 break; 983 } 984 break; 985 986 case 28: /* mov fr,[sl]ext/auto/oreg ==> swc1 o(r) */ 987 r = p->to.reg; 988 if(r == NREG) 989 r = o->param; 990 v = regoff(&p->to); 991 switch(o->size) { 992 case 20: 993 if(r == REGTMP) 994 diag("cant synthesize large constant\n%P\n", p); 995 o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP); 996 o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP); 997 o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP); 998 o4 = OP_IRR(opirr(AMOVF), 0, REGTMP, p->from.reg+1); 999 o5 = OP_IRR(opirr(AMOVF), 4, REGTMP, p->from.reg); 1000 break; 1001 case 16: 1002 if(r == REGTMP) 1003 diag("cant synthesize large constant\n%P\n", p); 1004 o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP); 1005 o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP); 1006 o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP); 1007 o4 = OP_IRR(opirr(AMOVF), 0, REGTMP, p->from.reg); 1008 break; 1009 case 8: 1010 o1 = OP_IRR(opirr(AMOVF), v, r, p->from.reg+1); 1011 o2 = OP_IRR(opirr(AMOVF), v+4, r, p->from.reg); 1012 break; 1013 case 4: 1014 o1 = OP_IRR(opirr(AMOVF), v, r, p->from.reg); 1015 break; 1016 } 1017 break; 1018 1019 case 30: /* movw r,fr */ 1020 r = SP(2,1)|(4<<21); /* mtc1 */ 1021 o1 = OP_RRR(r, p->from.reg, 0, p->to.reg); 1022 break; 1023 1024 case 31: /* movw fr,r */ 1025 r = SP(2,1)|(0<<21); /* mfc1 */ 1026 o1 = OP_RRR(r, p->to.reg, 0, p->from.reg); 1027 break; 1028 1029 case 32: /* fadd fr1,[fr2],fr3 */ 1030 r = p->reg; 1031 if(r == NREG) 1032 o1 = OP_FRRR(oprrr(p->as), p->from.reg, p->to.reg, p->to.reg); 1033 else 1034 o1 = OP_FRRR(oprrr(p->as), p->from.reg, r, p->to.reg); 1035 break; 1036 1037 case 33: /* fabs fr1,fr3 */ 1038 o1 = OP_FRRR(oprrr(p->as), 0, p->from.reg, p->to.reg); 1039 break; 1040 1041 case 34: /* mov $con,fr ==> or/add $i,r,r2 */ 1042 v = regoff(&p->from); 1043 r = AADDU; 1044 if(o->a1 == C_ANDCON) 1045 r = AOR; 1046 o1 = OP_IRR(opirr(r), v, 0, REGTMP); 1047 o2 = OP_RRR(SP(2,1)|(4<<21), REGTMP, 0, p->to.reg); /* mtc1 */ 1048 break; 1049 1050 case 35: /* mov r,lext/luto/oreg ==> sw o(r) */ 1051 /* 1052 * the lowbits of the constant cannot 1053 * be moved into the offset of the load 1054 * because the mips 4000 in 64-bit mode 1055 * does a 64-bit add and it will screw up. 1056 */ 1057 v = regoff(&p->to); 1058 r = p->to.reg; 1059 if(r == NREG) 1060 r = o->param; 1061 if(r == REGTMP) 1062 diag("cant synthesize large constant\n%P\n", p); 1063 o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP); 1064 o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP); 1065 o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP); 1066 o4 = OP_IRR(opirr(p->as), 0, REGTMP, p->from.reg); 1067 break; 1068 1069 case 36: /* mov lext/lauto/lreg,r ==> lw o(r30) */ 1070 v = regoff(&p->from); 1071 r = p->from.reg; 1072 if(r == NREG) 1073 r = o->param; 1074 if(r == REGTMP) 1075 diag("cant synthesize large constant\n%P\n", p); 1076 o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP); 1077 o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP); 1078 o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP); 1079 o4 = OP_IRR(opirr(p->as+ALAST), 0, REGTMP, p->to.reg); 1080 break; 1081 1082 case 37: /* movw r,mr */ 1083 r = SP(2,0)|(4<<21); /* mtc0 */ 1084 if(p->as == AMOVV) 1085 r = SP(2,0)|(5<<21); /* dmtc0 */ 1086 o1 = OP_RRR(r, p->from.reg, 0, p->to.reg); 1087 break; 1088 1089 case 38: /* movw mr,r */ 1090 r = SP(2,0)|(0<<21); /* mfc0 */ 1091 if(p->as == AMOVV) 1092 r = SP(2,0)|(1<<21); /* dmfc0 */ 1093 o1 = OP_RRR(r, p->to.reg, 0, p->from.reg); 1094 break; 1095 1096 case 39: /* rfe ==> jmp+rfe */ 1097 if(aflag) 1098 return 0; 1099 o1 = OP_RRR(oprrr(AJMP), 0, p->to.reg, REGZERO); 1100 o2 = oprrr(p->as); 1101 break; 1102 1103 case 40: /* word */ 1104 if(aflag) 1105 return 0; 1106 o1 = regoff(&p->to); 1107 break; 1108 1109 case 41: /* movw r,fcr */ 1110 o1 = OP_RRR(SP(2,1)|(2<<21), REGZERO, 0, p->to.reg); /* mfcc1 */ 1111 o2 = OP_RRR(SP(2,1)|(6<<21), p->from.reg, 0, p->to.reg);/* mtcc1 */ 1112 break; 1113 1114 case 42: /* movw fcr,r */ 1115 o1 = OP_RRR(SP(2,1)|(2<<21), p->to.reg, 0, p->from.reg);/* mfcc1 */ 1116 break; 1117 } 1118 if(aflag) 1119 return o1; 1120 v = p->pc; 1121 switch(o->size) { 1122 default: 1123 if(debug['a']) 1124 Bprint(&bso, " %.8lux:\t\t%P\n", v, p); 1125 break; 1126 case 4: 1127 if(debug['a']) 1128 Bprint(&bso, " %.8lux: %.8lux\t%P\n", v, o1, p); 1129 LPUT(o1); 1130 break; 1131 case 8: 1132 if(debug['a']) 1133 Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", v, o1, o2, p); 1134 LPUT(o1); 1135 LPUT(o2); 1136 break; 1137 case 12: 1138 if(debug['a']) 1139 Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux%P\n", v, o1, o2, o3, p); 1140 LPUT(o1); 1141 LPUT(o2); 1142 LPUT(o3); 1143 break; 1144 case 16: 1145 if(debug['a']) 1146 Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux%P\n", 1147 v, o1, o2, o3, o4, p); 1148 LPUT(o1); 1149 LPUT(o2); 1150 LPUT(o3); 1151 LPUT(o4); 1152 break; 1153 case 20: 1154 if(debug['a']) 1155 Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux%P\n", 1156 v, o1, o2, o3, o4, o5, p); 1157 LPUT(o1); 1158 LPUT(o2); 1159 LPUT(o3); 1160 LPUT(o4); 1161 LPUT(o5); 1162 break; 1163 } 1164 return 0; 1165 } 1166 1167 int 1168 isnop(Prog *p) 1169 { 1170 if(p->as != ANOR) 1171 return 0; 1172 if(p->reg != REGZERO && p->reg != NREG) 1173 return 0; 1174 if(p->from.type != D_REG || p->from.reg != REGZERO) 1175 return 0; 1176 if(p->to.type != D_REG || p->to.reg != REGZERO) 1177 return 0; 1178 return 1; 1179 } 1180 1181 long 1182 oprrr(int a) 1183 { 1184 switch(a) { 1185 case AADD: return OP(4,0); 1186 case AADDU: return OP(4,1); 1187 case ASGT: return OP(5,2); 1188 case ASGTU: return OP(5,3); 1189 case AAND: return OP(4,4); 1190 case AOR: return OP(4,5); 1191 case AXOR: return OP(4,6); 1192 case ASUB: return OP(4,2); 1193 case ASUBU: return OP(4,3); 1194 case ANOR: return OP(4,7); 1195 case ASLL: return OP(0,4); 1196 case ASRL: return OP(0,6); 1197 case ASRA: return OP(0,7); 1198 1199 case AREM: 1200 case ADIV: return OP(3,2); 1201 case AREMU: 1202 case ADIVU: return OP(3,3); 1203 case AMUL: return OP(3,0); 1204 case AMULU: return OP(3,1); 1205 1206 case AJMP: return OP(1,0); 1207 case AJAL: return OP(1,1); 1208 1209 case ABREAK: return OP(1,5); 1210 case ASYSCALL: return OP(1,4); 1211 case ATLBP: return MMU(1,0); 1212 case ATLBR: return MMU(0,1); 1213 case ATLBWI: return MMU(0,2); 1214 case ATLBWR: return MMU(0,6); 1215 case ARFE: return MMU(2,0); 1216 1217 case ADIVF: return FPF(0,3); 1218 case ADIVD: return FPD(0,3); 1219 case AMULF: return FPF(0,2); 1220 case AMULD: return FPD(0,2); 1221 case ASUBF: return FPF(0,1); 1222 case ASUBD: return FPD(0,1); 1223 case AADDF: return FPF(0,0); 1224 case AADDD: return FPD(0,0); 1225 1226 case AMOVFW: return FPF(4,4); 1227 case AMOVDW: return FPD(4,4); 1228 case AMOVWF: return FPW(4,0); 1229 case AMOVDF: return FPD(4,0); 1230 case AMOVWD: return FPW(4,1); 1231 case AMOVFD: return FPF(4,1); 1232 case AABSF: return FPF(0,5); 1233 case AABSD: return FPD(0,5); 1234 case AMOVF: return FPF(0,6); 1235 case AMOVD: return FPD(0,6); 1236 case ANEGF: return FPF(0,7); 1237 case ANEGD: return FPD(0,7); 1238 1239 case ACMPEQF: return FPF(6,2); 1240 case ACMPEQD: return FPD(6,2); 1241 case ACMPGTF: return FPF(7,4); 1242 case ACMPGTD: return FPD(7,4); 1243 case ACMPGEF: return FPF(7,6); 1244 case ACMPGED: return FPD(7,6); 1245 } 1246 diag("bad rrr %d\n", a); 1247 return 0; 1248 } 1249 1250 long 1251 opirr(int a) 1252 { 1253 switch(a) { 1254 case AADD: return SP(1,0); 1255 case AADDU: return SP(1,1); 1256 case ASGT: return SP(1,2); 1257 case ASGTU: return SP(1,3); 1258 case AAND: return SP(1,4); 1259 case AOR: return SP(1,5); 1260 case AXOR: return SP(1,6); 1261 case ALAST: return SP(1,7); 1262 case ASLL: return OP(0,0); 1263 case ASRL: return OP(0,2); 1264 case ASRA: return OP(0,3); 1265 1266 case AJMP: return SP(0,2); 1267 case AJAL: return SP(0,3); 1268 case ABEQ: return SP(0,4); 1269 case ABNE: return SP(0,5); 1270 1271 case ABGEZ: return SP(0,1)|BCOND(0,1); 1272 case ABGEZAL: return SP(0,1)|BCOND(2,1); 1273 case ABGTZ: return SP(0,7); 1274 case ABLEZ: return SP(0,6); 1275 case ABLTZ: return SP(0,1)|BCOND(0,0); 1276 case ABLTZAL: return SP(0,1)|BCOND(2,0); 1277 1278 case ABFPT: return SP(2,1)|(257<<16); 1279 case ABFPF: return SP(2,1)|(256<<16); 1280 1281 case AMOVB: 1282 case AMOVBU: return SP(5,0); 1283 case AMOVH: 1284 case AMOVHU: return SP(5,1); 1285 case AMOVW: return SP(5,3); 1286 case AMOVV: return SP(7,7); 1287 case AMOVF: return SP(7,1); 1288 case AMOVWL: return SP(5,2); 1289 case AMOVWR: return SP(5,6); 1290 case AMOVVL: return SP(5,4); 1291 case AMOVVR: return SP(5,5); 1292 1293 case ABREAK: return SP(5,7); 1294 1295 case AMOVWL+ALAST: return SP(4,2); 1296 case AMOVWR+ALAST: return SP(4,6); 1297 case AMOVVL+ALAST: return SP(3,2); 1298 case AMOVVR+ALAST: return SP(3,3); 1299 case AMOVB+ALAST: return SP(4,0); 1300 case AMOVBU+ALAST: return SP(4,4); 1301 case AMOVH+ALAST: return SP(4,1); 1302 case AMOVHU+ALAST: return SP(4,5); 1303 case AMOVW+ALAST: return SP(4,3); 1304 case AMOVV+ALAST: return SP(6,7); 1305 case AMOVF+ALAST: return SP(6,1); 1306 1307 case ASLLV: return OP(7,0); 1308 case ASRLV: return OP(7,2); 1309 case ASRAV: return OP(7,3); 1310 case ASLLV+ALAST: return OP(7,4); 1311 case ASRLV+ALAST: return OP(7,6); 1312 case ASRAV+ALAST: return OP(7,7); 1313 } 1314 diag("bad irr %d\n", a); 1315 return 0; 1316 } 1317