1 #include "l.h" 2 3 long OFFSET; 4 5 static Prog *PP; 6 7 long 8 entryvalue(void) 9 { 10 char *a; 11 Sym *s; 12 13 a = INITENTRY; 14 if(*a >= '0' && *a <= '9') 15 return atolwhex(a); 16 s = lookup(a, 0); 17 if(s->type == 0) 18 return INITTEXT; 19 switch(s->type) { 20 case STEXT: 21 case SLEAF: 22 break; 23 case SDATA: 24 if(dlm) 25 return s->value+INITDAT; 26 default: 27 diag("entry not text: %s", s->name); 28 } 29 return s->value; 30 } 31 32 void 33 asmb(void) 34 { 35 Prog *p; 36 long t, etext; 37 Optab *o; 38 39 if(debug['v']) 40 Bprint(&bso, "%5.2f asm\n", cputime()); 41 Bflush(&bso); 42 OFFSET = HEADR; 43 seek(cout, OFFSET, 0); 44 pc = INITTEXT; 45 for(p = firstp; p != P; p = p->link) { 46 if(p->as == ATEXT) { 47 curtext = p; 48 autosize = p->to.offset + 4; 49 } 50 if(p->pc != pc) { 51 diag("phase error %lux sb %lux", 52 p->pc, pc); 53 if(!debug['a']) 54 prasm(curp); 55 pc = p->pc; 56 } 57 curp = p; 58 o = oplook(p); /* could probably avoid this call */ 59 asmout(p, o); 60 pc += o->size; 61 } 62 63 if(debug['a']) 64 Bprint(&bso, "\n"); 65 Bflush(&bso); 66 cflush(); 67 68 /* output strings in text segment */ 69 etext = INITTEXT + textsize; 70 for(t = pc; t < etext; t += sizeof(buf)-100) { 71 if(etext-t > sizeof(buf)-100) 72 datblk(t, sizeof(buf)-100, 1); 73 else 74 datblk(t, etext-t, 1); 75 } 76 77 curtext = P; 78 switch(HEADTYPE) { 79 case 0: 80 case 1: 81 case 2: 82 case 5: 83 OFFSET = HEADR+textsize; 84 seek(cout, OFFSET, 0); 85 break; 86 case 3: 87 OFFSET = rnd(HEADR+textsize, 4096); 88 seek(cout, OFFSET, 0); 89 break; 90 } 91 if(dlm){ 92 char buf[8]; 93 94 write(cout, buf, INITDAT-textsize); 95 textsize = INITDAT; 96 } 97 for(t = 0; t < datsize; t += sizeof(buf)-100) { 98 if(datsize-t > sizeof(buf)-100) 99 datblk(t, sizeof(buf)-100, 0); 100 else 101 datblk(t, datsize-t, 0); 102 } 103 104 symsize = 0; 105 lcsize = 0; 106 if(!debug['s']) { 107 if(debug['v']) 108 Bprint(&bso, "%5.2f sym\n", cputime()); 109 Bflush(&bso); 110 switch(HEADTYPE) { 111 case 0: 112 case 1: 113 case 4: 114 case 5: 115 debug['s'] = 1; 116 break; 117 case 2: 118 OFFSET = HEADR+textsize+datsize; 119 seek(cout, OFFSET, 0); 120 break; 121 case 3: 122 OFFSET += rnd(datsize, 4096); 123 seek(cout, OFFSET, 0); 124 break; 125 } 126 if(!debug['s']) 127 asmsym(); 128 if(debug['v']) 129 Bprint(&bso, "%5.2f pc\n", cputime()); 130 Bflush(&bso); 131 if(!debug['s']) 132 asmlc(); 133 if(dlm) 134 asmdyn(); 135 cflush(); 136 } 137 else if(dlm){ 138 seek(cout, HEADR+textsize+datsize, 0); 139 asmdyn(); 140 cflush(); 141 } 142 143 if(debug['v']) 144 Bprint(&bso, "%5.2f header\n", cputime()); 145 Bflush(&bso); 146 OFFSET = 0; 147 seek(cout, OFFSET, 0); 148 switch(HEADTYPE) { 149 case 0: /* no header */ 150 break; 151 case 1: /* aif for risc os */ 152 lputl(0xe1a00000); /* NOP - decompress code */ 153 lputl(0xe1a00000); /* NOP - relocation code */ 154 lputl(0xeb000000 + 12); /* BL - zero init code */ 155 lputl(0xeb000000 + 156 (entryvalue() 157 - INITTEXT 158 + HEADR 159 - 12 160 - 8) / 4); /* BL - entry code */ 161 162 lputl(0xef000011); /* SWI - exit code */ 163 lputl(textsize+HEADR); /* text size */ 164 lputl(datsize); /* data size */ 165 lputl(0); /* sym size */ 166 167 lputl(bsssize); /* bss size */ 168 lputl(0); /* sym type */ 169 lputl(INITTEXT-HEADR); /* text addr */ 170 lputl(0); /* workspace - ignored */ 171 172 lputl(32); /* addr mode / data addr flag */ 173 lputl(0); /* data addr */ 174 for(t=0; t<2; t++) 175 lputl(0); /* reserved */ 176 177 for(t=0; t<15; t++) 178 lputl(0xe1a00000); /* NOP - zero init code */ 179 lputl(0xe1a0f00e); /* B (R14) - zero init return */ 180 break; 181 case 2: /* plan 9 */ 182 if(dlm) 183 lput(0x80000000|0x647); /* magic */ 184 else 185 lput(0x647); /* magic */ 186 lput(textsize); /* sizes */ 187 lput(datsize); 188 lput(bsssize); 189 lput(symsize); /* nsyms */ 190 lput(entryvalue()); /* va of entry */ 191 lput(0L); 192 lput(lcsize); 193 break; 194 case 3: /* boot for NetBSD */ 195 lput((143<<16)|0413); /* magic */ 196 lputl(rnd(HEADR+textsize, 4096)); 197 lputl(rnd(datsize, 4096)); 198 lputl(bsssize); 199 lputl(symsize); /* nsyms */ 200 lputl(entryvalue()); /* va of entry */ 201 lputl(0L); 202 lputl(0L); 203 break; 204 case 4: /* boot for IXP1200 */ 205 break; 206 case 5: /* boot for ipaq */ 207 lputl(0xe3300000); /* nop */ 208 lputl(0xe3300000); /* nop */ 209 lputl(0xe3300000); /* nop */ 210 lputl(0xe3300000); /* nop */ 211 break; 212 } 213 cflush(); 214 } 215 216 void 217 strnput(char *s, int n) 218 { 219 for(; *s; s++){ 220 cput(*s); 221 n--; 222 } 223 for(; n > 0; n--) 224 cput(0); 225 } 226 227 void 228 cput(int c) 229 { 230 cbp[0] = c; 231 cbp++; 232 cbc--; 233 if(cbc <= 0) 234 cflush(); 235 } 236 237 void 238 wput(long l) 239 { 240 241 cbp[0] = l>>8; 242 cbp[1] = l; 243 cbp += 2; 244 cbc -= 2; 245 if(cbc <= 0) 246 cflush(); 247 } 248 249 void 250 lput(long l) 251 { 252 253 cbp[0] = l>>24; 254 cbp[1] = l>>16; 255 cbp[2] = l>>8; 256 cbp[3] = l; 257 cbp += 4; 258 cbc -= 4; 259 if(cbc <= 0) 260 cflush(); 261 } 262 263 void 264 lputl(long l) 265 { 266 267 cbp[3] = l>>24; 268 cbp[2] = l>>16; 269 cbp[1] = l>>8; 270 cbp[0] = l; 271 cbp += 4; 272 cbc -= 4; 273 if(cbc <= 0) 274 cflush(); 275 } 276 277 void 278 cflush(void) 279 { 280 int n; 281 282 n = sizeof(buf.cbuf) - cbc; 283 if(n) 284 write(cout, buf.cbuf, n); 285 cbp = buf.cbuf; 286 cbc = sizeof(buf.cbuf); 287 } 288 289 void 290 nopstat(char *f, Count *c) 291 { 292 if(c->outof) 293 Bprint(&bso, "%s delay %ld/%ld (%.2f)\n", f, 294 c->outof - c->count, c->outof, 295 (double)(c->outof - c->count)/c->outof); 296 } 297 298 void 299 asmsym(void) 300 { 301 Prog *p; 302 Auto *a; 303 Sym *s; 304 int h; 305 306 s = lookup("etext", 0); 307 if(s->type == STEXT) 308 putsymb(s->name, 'T', s->value, s->version); 309 310 for(h=0; h<NHASH; h++) 311 for(s=hash[h]; s!=S; s=s->link) 312 switch(s->type) { 313 case SCONST: 314 putsymb(s->name, 'D', s->value, s->version); 315 continue; 316 317 case SDATA: 318 putsymb(s->name, 'D', s->value+INITDAT, s->version); 319 continue; 320 321 case SBSS: 322 putsymb(s->name, 'B', s->value+INITDAT, s->version); 323 continue; 324 325 case SSTRING: 326 putsymb(s->name, 'T', s->value, s->version); 327 continue; 328 329 case SFILE: 330 putsymb(s->name, 'f', s->value, s->version); 331 continue; 332 } 333 334 for(p=textp; p!=P; p=p->cond) { 335 s = p->from.sym; 336 if(s->type != STEXT && s->type != SLEAF) 337 continue; 338 339 /* filenames first */ 340 for(a=p->to.autom; a; a=a->link) 341 if(a->type == D_FILE) 342 putsymb(a->asym->name, 'z', a->aoffset, 0); 343 else 344 if(a->type == D_FILE1) 345 putsymb(a->asym->name, 'Z', a->aoffset, 0); 346 347 if(s->type == STEXT) 348 putsymb(s->name, 'T', s->value, s->version); 349 else 350 putsymb(s->name, 'L', s->value, s->version); 351 352 /* frame, auto and param after */ 353 putsymb(".frame", 'm', p->to.offset+4, 0); 354 for(a=p->to.autom; a; a=a->link) 355 if(a->type == D_AUTO) 356 putsymb(a->asym->name, 'a', -a->aoffset, 0); 357 else 358 if(a->type == D_PARAM) 359 putsymb(a->asym->name, 'p', a->aoffset, 0); 360 } 361 if(debug['v'] || debug['n']) 362 Bprint(&bso, "symsize = %lud\n", symsize); 363 Bflush(&bso); 364 } 365 366 void 367 putsymb(char *s, int t, long v, int ver) 368 { 369 int i, f; 370 371 if(t == 'f') 372 s++; 373 lput(v); 374 if(ver) 375 t += 'a' - 'A'; 376 cput(t+0x80); /* 0x80 is variable length */ 377 378 if(t == 'Z' || t == 'z') { 379 cput(s[0]); 380 for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) { 381 cput(s[i]); 382 cput(s[i+1]); 383 } 384 cput(0); 385 cput(0); 386 i++; 387 } 388 else { 389 for(i=0; s[i]; i++) 390 cput(s[i]); 391 cput(0); 392 } 393 symsize += 4 + 1 + i + 1; 394 395 if(debug['n']) { 396 if(t == 'z' || t == 'Z') { 397 Bprint(&bso, "%c %.8lux ", t, v); 398 for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) { 399 f = ((s[i]&0xff) << 8) | (s[i+1]&0xff); 400 Bprint(&bso, "/%x", f); 401 } 402 Bprint(&bso, "\n"); 403 return; 404 } 405 if(ver) 406 Bprint(&bso, "%c %.8lux %s<%d>\n", t, v, s, ver); 407 else 408 Bprint(&bso, "%c %.8lux %s\n", t, v, s); 409 } 410 } 411 412 #define MINLC 4 413 void 414 asmlc(void) 415 { 416 long oldpc, oldlc; 417 Prog *p; 418 long v, s; 419 420 oldpc = INITTEXT; 421 oldlc = 0; 422 for(p = firstp; p != P; p = p->link) { 423 if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) { 424 if(p->as == ATEXT) 425 curtext = p; 426 if(debug['L']) 427 Bprint(&bso, "%6lux %P\n", 428 p->pc, p); 429 continue; 430 } 431 if(debug['L']) 432 Bprint(&bso, "\t\t%6ld", lcsize); 433 v = (p->pc - oldpc) / MINLC; 434 while(v) { 435 s = 127; 436 if(v < 127) 437 s = v; 438 cput(s+128); /* 129-255 +pc */ 439 if(debug['L']) 440 Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128); 441 v -= s; 442 lcsize++; 443 } 444 s = p->line - oldlc; 445 oldlc = p->line; 446 oldpc = p->pc + MINLC; 447 if(s > 64 || s < -64) { 448 cput(0); /* 0 vv +lc */ 449 cput(s>>24); 450 cput(s>>16); 451 cput(s>>8); 452 cput(s); 453 if(debug['L']) { 454 if(s > 0) 455 Bprint(&bso, " lc+%ld(%d,%ld)\n", 456 s, 0, s); 457 else 458 Bprint(&bso, " lc%ld(%d,%ld)\n", 459 s, 0, s); 460 Bprint(&bso, "%6lux %P\n", 461 p->pc, p); 462 } 463 lcsize += 5; 464 continue; 465 } 466 if(s > 0) { 467 cput(0+s); /* 1-64 +lc */ 468 if(debug['L']) { 469 Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s); 470 Bprint(&bso, "%6lux %P\n", 471 p->pc, p); 472 } 473 } else { 474 cput(64-s); /* 65-128 -lc */ 475 if(debug['L']) { 476 Bprint(&bso, " lc%ld(%ld)\n", s, 64-s); 477 Bprint(&bso, "%6lux %P\n", 478 p->pc, p); 479 } 480 } 481 lcsize++; 482 } 483 while(lcsize & 1) { 484 s = 129; 485 cput(s); 486 lcsize++; 487 } 488 if(debug['v'] || debug['L']) 489 Bprint(&bso, "lcsize = %ld\n", lcsize); 490 Bflush(&bso); 491 } 492 493 void 494 datblk(long s, long n, int str) 495 { 496 Sym *v; 497 Prog *p; 498 char *cast; 499 long a, l, fl, j, d; 500 int i, c; 501 502 memset(buf.dbuf, 0, n+100); 503 for(p = datap; p != P; p = p->link) { 504 if(str != (p->from.sym->type == SSTRING)) 505 continue; 506 curp = p; 507 a = p->from.sym->value + p->from.offset; 508 l = a - s; 509 c = p->reg; 510 i = 0; 511 if(l < 0) { 512 if(l+c <= 0) 513 continue; 514 while(l < 0) { 515 l++; 516 i++; 517 } 518 } 519 if(l >= n) 520 continue; 521 if(p->as != AINIT && p->as != ADYNT) { 522 for(j=l+(c-i)-1; j>=l; j--) 523 if(buf.dbuf[j]) { 524 print("%P\n", p); 525 diag("multiple initialization"); 526 break; 527 } 528 } 529 switch(p->to.type) { 530 default: 531 diag("unknown mode in initialization%P", p); 532 break; 533 534 case D_FCONST: 535 switch(c) { 536 default: 537 case 4: 538 fl = ieeedtof(p->to.ieee); 539 cast = (char*)&fl; 540 for(; i<c; i++) { 541 buf.dbuf[l] = cast[fnuxi4[i]]; 542 l++; 543 } 544 break; 545 case 8: 546 cast = (char*)p->to.ieee; 547 for(; i<c; i++) { 548 buf.dbuf[l] = cast[fnuxi8[i]]; 549 l++; 550 } 551 break; 552 } 553 break; 554 555 case D_SCONST: 556 for(; i<c; i++) { 557 buf.dbuf[l] = p->to.sval[i]; 558 l++; 559 } 560 break; 561 562 case D_CONST: 563 d = p->to.offset; 564 v = p->to.sym; 565 if(v) { 566 switch(v->type) { 567 case SUNDEF: 568 ckoff(v, d); 569 case STEXT: 570 case SLEAF: 571 case SSTRING: 572 d += p->to.sym->value; 573 break; 574 case SDATA: 575 case SBSS: 576 d += p->to.sym->value + INITDAT; 577 } 578 if(dlm) 579 dynreloc(v, a+INITDAT, 1); 580 } 581 cast = (char*)&d; 582 switch(c) { 583 default: 584 diag("bad nuxi %d %d%P", c, i, curp); 585 break; 586 case 1: 587 for(; i<c; i++) { 588 buf.dbuf[l] = cast[inuxi1[i]]; 589 l++; 590 } 591 break; 592 case 2: 593 for(; i<c; i++) { 594 buf.dbuf[l] = cast[inuxi2[i]]; 595 l++; 596 } 597 break; 598 case 4: 599 for(; i<c; i++) { 600 buf.dbuf[l] = cast[inuxi4[i]]; 601 l++; 602 } 603 break; 604 } 605 break; 606 } 607 } 608 write(cout, buf.dbuf, n); 609 } 610 611 void 612 asmout(Prog *p, Optab *o) 613 { 614 long o1, o2, o3, o4, o5, o6, v; 615 int r, rf, rt, rt2; 616 Sym *s; 617 618 PP = p; 619 o1 = 0; 620 o2 = 0; 621 o3 = 0; 622 o4 = 0; 623 o5 = 0; 624 o6 = 0; 625 switch(o->type) { 626 default: 627 diag("unknown asm %d", o->type); 628 prasm(p); 629 break; 630 631 case 0: /* pseudo ops */ 632 break; 633 634 case 1: /* op R,[R],R */ 635 o1 = oprrr(p->as, p->scond); 636 rf = p->from.reg; 637 rt = p->to.reg; 638 r = p->reg; 639 if(p->to.type == D_NONE) 640 rt = 0; 641 if(p->as == AMOVW || p->as == AMVN) 642 r = 0; 643 else if(r == NREG) 644 r = rt; 645 o1 |= rf | (r<<16) | (rt<<12); 646 break; 647 648 case 2: /* movbu $I,[R],R */ 649 aclass(&p->from); 650 o1 = oprrr(p->as, p->scond); 651 o1 |= immrot(instoffset); 652 rt = p->to.reg; 653 r = p->reg; 654 if(p->to.type == D_NONE) 655 rt = 0; 656 if(p->as == AMOVW || p->as == AMVN) 657 r = 0; 658 else if(r == NREG) 659 r = rt; 660 o1 |= (r<<16) | (rt<<12); 661 break; 662 663 case 3: /* add R<<[IR],[R],R */ 664 mov: 665 aclass(&p->from); 666 o1 = oprrr(p->as, p->scond); 667 o1 |= p->from.offset; 668 rt = p->to.reg; 669 r = p->reg; 670 if(p->to.type == D_NONE) 671 rt = 0; 672 if(p->as == AMOVW || p->as == AMVN) 673 r = 0; 674 else if(r == NREG) 675 r = rt; 676 o1 |= (r<<16) | (rt<<12); 677 break; 678 679 case 4: /* add $I,[R],R */ 680 aclass(&p->from); 681 o1 = oprrr(AADD, p->scond); 682 o1 |= immrot(instoffset); 683 r = p->from.reg; 684 if(r == NREG) 685 r = o->param; 686 o1 |= r << 16; 687 o1 |= p->to.reg << 12; 688 break; 689 690 case 5: /* bra s */ 691 v = -8; 692 if(p->cond == UP) { 693 s = p->to.sym; 694 if(s->type != SUNDEF) 695 diag("bad branch sym type"); 696 v = (ulong)s->value >> (Roffset-2); 697 dynreloc(s, p->pc, 0); 698 } 699 else if(p->cond != P) 700 v = (p->cond->pc - pc) - 8; 701 o1 = opbra(p->as, p->scond); 702 o1 |= (v >> 2) & 0xffffff; 703 break; 704 705 case 6: /* b ,O(R) -> add $O,R,PC */ 706 aclass(&p->to); 707 o1 = oprrr(AADD, p->scond); 708 o1 |= immrot(instoffset); 709 o1 |= p->to.reg << 16; 710 o1 |= REGPC << 12; 711 break; 712 713 case 7: /* bl ,O(R) -> mov PC,link; add $O,R,PC */ 714 aclass(&p->to); 715 o1 = oprrr(AADD, p->scond); 716 o1 |= immrot(0); 717 o1 |= REGPC << 16; 718 o1 |= REGLINK << 12; 719 720 o2 = oprrr(AADD, p->scond); 721 o2 |= immrot(instoffset); 722 o2 |= p->to.reg << 16; 723 o2 |= REGPC << 12; 724 break; 725 726 case 8: /* sll $c,[R],R -> mov (R<<$c),R */ 727 aclass(&p->from); 728 o1 = oprrr(p->as, p->scond); 729 r = p->reg; 730 if(r == NREG) 731 r = p->to.reg; 732 o1 |= r; 733 o1 |= (instoffset&31) << 7; 734 o1 |= p->to.reg << 12; 735 break; 736 737 case 9: /* sll R,[R],R -> mov (R<<R),R */ 738 o1 = oprrr(p->as, p->scond); 739 r = p->reg; 740 if(r == NREG) 741 r = p->to.reg; 742 o1 |= r; 743 o1 |= (p->from.reg << 8) | (1<<4); 744 o1 |= p->to.reg << 12; 745 break; 746 747 case 10: /* swi [$con] */ 748 o1 = oprrr(p->as, p->scond); 749 if(p->to.type != D_NONE) { 750 aclass(&p->to); 751 o1 |= instoffset & 0xffffff; 752 } 753 break; 754 755 case 11: /* word */ 756 switch(aclass(&p->to)) { 757 case C_LCON: 758 if(!dlm) 759 break; 760 if(p->to.name != D_EXTERN && p->to.name != D_STATIC) 761 break; 762 case C_ADDR: 763 if(p->to.sym->type == SUNDEF) 764 ckoff(p->to.sym, p->to.offset); 765 dynreloc(p->to.sym, p->pc, 1); 766 } 767 o1 = instoffset; 768 break; 769 770 case 12: /* movw $lcon, reg */ 771 o1 = omvl(p, &p->from, p->to.reg); 772 break; 773 774 case 13: /* op $lcon, [R], R */ 775 o1 = omvl(p, &p->from, REGTMP); 776 if(!o1) 777 break; 778 o2 = oprrr(p->as, p->scond); 779 o2 |= REGTMP; 780 r = p->reg; 781 if(p->as == AMOVW || p->as == AMVN) 782 r = 0; 783 else if(r == NREG) 784 r = p->to.reg; 785 o2 |= r << 16; 786 if(p->to.type != D_NONE) 787 o2 |= p->to.reg << 12; 788 break; 789 790 case 14: /* movb/movbu/movh/movhu R,R */ 791 o1 = oprrr(ASLL, p->scond); 792 793 if(p->as == AMOVBU || p->as == AMOVHU) 794 o2 = oprrr(ASRL, p->scond); 795 else 796 o2 = oprrr(ASRA, p->scond); 797 798 r = p->to.reg; 799 o1 |= (p->from.reg)|(r<<12); 800 o2 |= (r)|(r<<12); 801 if(p->as == AMOVB || p->as == AMOVBU) { 802 o1 |= (24<<7); 803 o2 |= (24<<7); 804 } else { 805 o1 |= (16<<7); 806 o2 |= (16<<7); 807 } 808 break; 809 810 case 15: /* mul r,[r,]r */ 811 o1 = oprrr(p->as, p->scond); 812 rf = p->from.reg; 813 rt = p->to.reg; 814 r = p->reg; 815 if(r == NREG) 816 r = rt; 817 if(rt == r) { 818 r = rf; 819 rf = rt; 820 } 821 if(0) 822 if(rt == r || rf == REGPC || r == REGPC || rt == REGPC) { 823 diag("bad registers in MUL"); 824 prasm(p); 825 } 826 o1 |= (rf<<8) | r | (rt<<16); 827 break; 828 829 830 case 16: /* div r,[r,]r */ 831 o1 = 0xf << 28; 832 o2 = 0; 833 break; 834 835 case 17: 836 o1 = oprrr(p->as, p->scond); 837 rf = p->from.reg; 838 rt = p->to.reg; 839 rt2 = p->to.offset; 840 r = p->reg; 841 o1 |= (rf<<8) | r | (rt<<16) | (rt2<<12); 842 break; 843 844 case 20: /* mov/movb/movbu R,O(R) */ 845 aclass(&p->to); 846 r = p->to.reg; 847 if(r == NREG) 848 r = o->param; 849 o1 = osr(p->as, p->from.reg, instoffset, r, p->scond); 850 break; 851 852 case 21: /* mov/movbu O(R),R -> lr */ 853 aclass(&p->from); 854 r = p->from.reg; 855 if(r == NREG) 856 r = o->param; 857 o1 = olr(instoffset, r, p->to.reg, p->scond); 858 if(p->as != AMOVW) 859 o1 |= 1<<22; 860 break; 861 862 case 22: /* movb/movh/movhu O(R),R -> lr,shl,shr */ 863 aclass(&p->from); 864 r = p->from.reg; 865 if(r == NREG) 866 r = o->param; 867 o1 = olr(instoffset, r, p->to.reg, p->scond); 868 869 o2 = oprrr(ASLL, p->scond); 870 o3 = oprrr(ASRA, p->scond); 871 r = p->to.reg; 872 if(p->as == AMOVB) { 873 o2 |= (24<<7)|(r)|(r<<12); 874 o3 |= (24<<7)|(r)|(r<<12); 875 } else { 876 o2 |= (16<<7)|(r)|(r<<12); 877 if(p->as == AMOVHU) 878 o3 = oprrr(ASRL, p->scond); 879 o3 |= (16<<7)|(r)|(r<<12); 880 } 881 break; 882 883 case 23: /* movh/movhu R,O(R) -> sb,sb */ 884 aclass(&p->to); 885 r = p->to.reg; 886 if(r == NREG) 887 r = o->param; 888 o1 = osr(AMOVH, p->from.reg, instoffset, r, p->scond); 889 890 o2 = oprrr(ASRL, p->scond); 891 o2 |= (8<<7)|(p->from.reg)|(REGTMP<<12); 892 893 o3 = osr(AMOVH, REGTMP, instoffset+1, r, p->scond); 894 break; 895 896 case 30: /* mov/movb/movbu R,L(R) */ 897 o1 = omvl(p, &p->to, REGTMP); 898 if(!o1) 899 break; 900 r = p->to.reg; 901 if(r == NREG) 902 r = o->param; 903 o2 = osrr(p->from.reg, REGTMP,r, p->scond); 904 if(p->as != AMOVW) 905 o2 |= 1<<22; 906 break; 907 908 case 31: /* mov/movbu L(R),R -> lr[b] */ 909 case 32: /* movh/movb L(R),R -> lr[b] */ 910 o1 = omvl(p, &p->from, REGTMP); 911 if(!o1) 912 break; 913 r = p->from.reg; 914 if(r == NREG) 915 r = o->param; 916 o2 = olrr(REGTMP,r, p->to.reg, p->scond); 917 if(p->as == AMOVBU || p->as == AMOVB) 918 o2 |= 1<<22; 919 if(o->type == 31) 920 break; 921 922 o3 = oprrr(ASLL, p->scond); 923 924 if(p->as == AMOVBU || p->as == AMOVHU) 925 o4 = oprrr(ASRL, p->scond); 926 else 927 o4 = oprrr(ASRA, p->scond); 928 929 r = p->to.reg; 930 o3 |= (r)|(r<<12); 931 o4 |= (r)|(r<<12); 932 if(p->as == AMOVB || p->as == AMOVBU) { 933 o3 |= (24<<7); 934 o4 |= (24<<7); 935 } else { 936 o3 |= (16<<7); 937 o4 |= (16<<7); 938 } 939 break; 940 941 case 33: /* movh/movhu R,L(R) -> sb, sb */ 942 o1 = omvl(p, &p->to, REGTMP); 943 if(!o1) 944 break; 945 r = p->to.reg; 946 if(r == NREG) 947 r = o->param; 948 o2 = osrr(p->from.reg, REGTMP, r, p->scond); 949 o2 |= (1<<22) ; 950 951 o3 = oprrr(ASRL, p->scond); 952 o3 |= (8<<7)|(p->from.reg)|(p->from.reg<<12); 953 o3 |= (1<<6); /* ROR 8 */ 954 955 o4 = oprrr(AADD, p->scond); 956 o4 |= (REGTMP << 12) | (REGTMP << 16); 957 o4 |= immrot(1); 958 959 o5 = osrr(p->from.reg, REGTMP,r,p->scond); 960 o5 |= (1<<22); 961 962 o6 = oprrr(ASRL, p->scond); 963 o6 |= (24<<7)|(p->from.reg)|(p->from.reg<<12); 964 o6 |= (1<<6); /* ROL 8 */ 965 966 break; 967 968 case 34: /* mov $lacon,R */ 969 o1 = omvl(p, &p->from, REGTMP); 970 if(!o1) 971 break; 972 973 o2 = oprrr(AADD, p->scond); 974 o2 |= REGTMP; 975 r = p->from.reg; 976 if(r == NREG) 977 r = o->param; 978 o2 |= r << 16; 979 if(p->to.type != D_NONE) 980 o2 |= p->to.reg << 12; 981 break; 982 983 case 35: /* mov PSR,R */ 984 o1 = (2<<23) | (0xf<<16) | (0<<0); 985 o1 |= (p->scond & C_SCOND) << 28; 986 o1 |= (p->from.reg & 1) << 22; 987 o1 |= p->to.reg << 12; 988 break; 989 990 case 36: /* mov R,PSR */ 991 o1 = (2<<23) | (0x29f<<12) | (0<<4); 992 if(p->scond & C_FBIT) 993 o1 ^= 0x010 << 12; 994 o1 |= (p->scond & C_SCOND) << 28; 995 o1 |= (p->to.reg & 1) << 22; 996 o1 |= p->from.reg << 0; 997 break; 998 999 case 37: /* mov $con,PSR */ 1000 aclass(&p->from); 1001 o1 = (2<<23) | (0x29f<<12) | (0<<4); 1002 if(p->scond & C_FBIT) 1003 o1 ^= 0x010 << 12; 1004 o1 |= (p->scond & C_SCOND) << 28; 1005 o1 |= immrot(instoffset); 1006 o1 |= (p->to.reg & 1) << 22; 1007 o1 |= p->from.reg << 0; 1008 break; 1009 1010 case 38: /* movm $con,oreg -> stm */ 1011 o1 = (0x4 << 25); 1012 o1 |= p->from.offset & 0xffff; 1013 o1 |= p->to.reg << 16; 1014 aclass(&p->to); 1015 goto movm; 1016 1017 case 39: /* movm oreg,$con -> ldm */ 1018 o1 = (0x4 << 25) | (1 << 20); 1019 o1 |= p->to.offset & 0xffff; 1020 o1 |= p->from.reg << 16; 1021 aclass(&p->from); 1022 movm: 1023 if(instoffset != 0) 1024 diag("offset must be zero in MOVM"); 1025 o1 |= (p->scond & C_SCOND) << 28; 1026 if(p->scond & C_PBIT) 1027 o1 |= 1 << 24; 1028 if(p->scond & C_UBIT) 1029 o1 |= 1 << 23; 1030 if(p->scond & C_SBIT) 1031 o1 |= 1 << 22; 1032 if(p->scond & C_WBIT) 1033 o1 |= 1 << 21; 1034 break; 1035 1036 case 40: /* swp oreg,reg,reg */ 1037 aclass(&p->from); 1038 if(instoffset != 0) 1039 diag("offset must be zero in SWP"); 1040 o1 = (0x2<<23) | (0x9<<4); 1041 if(p->as != ASWPW) 1042 o1 |= 1 << 22; 1043 o1 |= p->from.reg << 16; 1044 o1 |= p->reg << 0; 1045 o1 |= p->to.reg << 12; 1046 o1 |= (p->scond & C_SCOND) << 28; 1047 break; 1048 1049 case 41: /* rfe -> movm.s.w.u 0(r13),[r15] */ 1050 o1 = 0xe8fd8000; 1051 break; 1052 1053 case 50: /* floating point store */ 1054 v = regoff(&p->to); 1055 r = p->to.reg; 1056 if(r == NREG) 1057 r = o->param; 1058 o1 = ofsr(p->as, p->from.reg, v, r, p->scond, p); 1059 break; 1060 1061 case 51: /* floating point load */ 1062 v = regoff(&p->from); 1063 r = p->from.reg; 1064 if(r == NREG) 1065 r = o->param; 1066 o1 = ofsr(p->as, p->to.reg, v, r, p->scond, p) | (1<<20); 1067 break; 1068 1069 case 52: /* floating point store, long offset UGLY */ 1070 o1 = omvl(p, &p->to, REGTMP); 1071 if(!o1) 1072 break; 1073 r = p->to.reg; 1074 if(r == NREG) 1075 r = o->param; 1076 o2 = oprrr(AADD, p->scond) | (REGTMP << 12) | (REGTMP << 16) | r; 1077 o3 = ofsr(p->as, p->from.reg, 0, REGTMP, p->scond, p); 1078 break; 1079 1080 case 53: /* floating point load, long offset UGLY */ 1081 o1 = omvl(p, &p->from, REGTMP); 1082 if(!o1) 1083 break; 1084 r = p->from.reg; 1085 if(r == NREG) 1086 r = o->param; 1087 o2 = oprrr(AADD, p->scond) | (REGTMP << 12) | (REGTMP << 16) | r; 1088 o3 = ofsr(p->as, p->to.reg, 0, REGTMP, p->scond, p) | (1<<20); 1089 break; 1090 1091 case 54: /* floating point arith */ 1092 o1 = oprrr(p->as, p->scond); 1093 if(p->from.type == D_FCONST) { 1094 rf = chipfloat(p->from.ieee); 1095 if(rf < 0){ 1096 diag("invalid floating-point immediate\n%P", p); 1097 rf = 0; 1098 } 1099 rf |= (1<<3); 1100 } else 1101 rf = p->from.reg; 1102 rt = p->to.reg; 1103 r = p->reg; 1104 if(p->to.type == D_NONE) 1105 rt = 0; /* CMP[FD] */ 1106 else if(o1 & (1<<15)) 1107 r = 0; /* monadic */ 1108 else if(r == NREG) 1109 r = rt; 1110 o1 |= rf | (r<<16) | (rt<<12); 1111 break; 1112 1113 case 55: /* floating point fix and float */ 1114 o1 = oprrr(p->as, p->scond); 1115 rf = p->from.reg; 1116 rt = p->to.reg; 1117 if(p->to.type == D_NONE){ 1118 rt = 0; 1119 diag("to.type==D_NONE (asm/fp)"); 1120 } 1121 if(p->from.type == D_REG) 1122 o1 |= (rf<<12) | (rt<<16); 1123 else 1124 o1 |= rf | (rt<<12); 1125 break; 1126 1127 case 56: /* move to FP[CS]R */ 1128 o1 = ((p->scond & C_SCOND) << 28) | (0xe << 24) | (1<<8) | (1<<4); 1129 o1 |= ((p->to.reg+1)<<21) | (p->from.reg << 12); 1130 break; 1131 1132 case 57: /* move from FP[CS]R */ 1133 o1 = ((p->scond & C_SCOND) << 28) | (0xe << 24) | (1<<8) | (1<<4); 1134 o1 |= ((p->from.reg+1)<<21) | (p->to.reg<<12) | (1<<20); 1135 break; 1136 case 58: /* movbu R,R */ 1137 o1 = oprrr(AAND, p->scond); 1138 o1 |= immrot(0xff); 1139 rt = p->to.reg; 1140 r = p->from.reg; 1141 if(p->to.type == D_NONE) 1142 rt = 0; 1143 if(r == NREG) 1144 r = rt; 1145 o1 |= (r<<16) | (rt<<12); 1146 break; 1147 1148 case 59: /* movw/bu R<<I(R),R -> ldr indexed */ 1149 if(p->from.reg == NREG) { 1150 if(p->as != AMOVW) 1151 diag("byte MOV from shifter operand"); 1152 goto mov; 1153 } 1154 if(p->from.offset&(1<<4)) 1155 diag("bad shift in LDR"); 1156 o1 = olrr(p->from.offset, p->from.reg, p->to.reg, p->scond); 1157 if(p->as == AMOVBU) 1158 o1 |= 1<<22; 1159 break; 1160 1161 case 60: /* movb R(R),R -> ldrsb indexed */ 1162 if(p->from.reg == NREG) { 1163 diag("byte MOV from shifter operand"); 1164 goto mov; 1165 } 1166 if(p->from.offset&(~0xf)) 1167 diag("bad shift in LDRSB"); 1168 o1 = olhrr(p->from.offset, p->from.reg, p->to.reg, p->scond); 1169 o1 ^= (1<<5)|(1<<6); 1170 break; 1171 1172 case 61: /* movw/b/bu R,R<<[IR](R) -> str indexed */ 1173 if(p->to.reg == NREG) 1174 diag("MOV to shifter operand"); 1175 o1 = osrr(p->from.reg, p->to.offset, p->to.reg, p->scond); 1176 if(p->as == AMOVB || p->as == AMOVBU) 1177 o1 |= 1<<22; 1178 break; 1179 1180 case 62: /* case R -> movw R<<2(PC),PC */ 1181 o1 = olrr(p->from.reg, REGPC, REGPC, p->scond); 1182 o1 |= 2<<7; 1183 break; 1184 1185 case 63: /* bcase */ 1186 if(p->cond != P) { 1187 o1 = p->cond->pc; 1188 if(dlm) 1189 dynreloc(S, p->pc, 1); 1190 } 1191 break; 1192 1193 /* reloc ops */ 1194 case 64: /* mov/movb/movbu R,addr */ 1195 o1 = omvl(p, &p->to, REGTMP); 1196 if(!o1) 1197 break; 1198 o2 = osr(p->as, p->from.reg, 0, REGTMP, p->scond); 1199 break; 1200 1201 case 65: /* mov/movbu addr,R */ 1202 case 66: /* movh/movhu/movb addr,R */ 1203 o1 = omvl(p, &p->from, REGTMP); 1204 if(!o1) 1205 break; 1206 o2 = olr(0, REGTMP, p->to.reg, p->scond); 1207 if(p->as == AMOVBU || p->as == AMOVB) 1208 o2 |= 1<<22; 1209 if(o->type == 65) 1210 break; 1211 1212 o3 = oprrr(ASLL, p->scond); 1213 1214 if(p->as == AMOVBU || p->as == AMOVHU) 1215 o4 = oprrr(ASRL, p->scond); 1216 else 1217 o4 = oprrr(ASRA, p->scond); 1218 1219 r = p->to.reg; 1220 o3 |= (r)|(r<<12); 1221 o4 |= (r)|(r<<12); 1222 if(p->as == AMOVB || p->as == AMOVBU) { 1223 o3 |= (24<<7); 1224 o4 |= (24<<7); 1225 } else { 1226 o3 |= (16<<7); 1227 o4 |= (16<<7); 1228 } 1229 break; 1230 1231 case 67: /* movh/movhu R,addr -> sb, sb */ 1232 o1 = omvl(p, &p->to, REGTMP); 1233 if(!o1) 1234 break; 1235 o2 = osr(p->as, p->from.reg, 0, REGTMP, p->scond); 1236 1237 o3 = oprrr(ASRL, p->scond); 1238 o3 |= (8<<7)|(p->from.reg)|(p->from.reg<<12); 1239 o3 |= (1<<6); /* ROR 8 */ 1240 1241 o4 = oprrr(AADD, p->scond); 1242 o4 |= (REGTMP << 12) | (REGTMP << 16); 1243 o4 |= immrot(1); 1244 1245 o5 = osr(p->as, p->from.reg, 0, REGTMP, p->scond); 1246 1247 o6 = oprrr(ASRL, p->scond); 1248 o6 |= (24<<7)|(p->from.reg)|(p->from.reg<<12); 1249 o6 |= (1<<6); /* ROL 8 */ 1250 break; 1251 1252 case 68: /* floating point store -> ADDR */ 1253 o1 = omvl(p, &p->to, REGTMP); 1254 if(!o1) 1255 break; 1256 o2 = ofsr(p->as, p->from.reg, 0, REGTMP, p->scond, p); 1257 break; 1258 1259 case 69: /* floating point load <- ADDR */ 1260 o1 = omvl(p, &p->from, REGTMP); 1261 if(!o1) 1262 break; 1263 o2 = ofsr(p->as, p->to.reg, 0, REGTMP, p->scond, p) | (1<<20); 1264 break; 1265 1266 /* ArmV4 ops: */ 1267 case 70: /* movh/movhu R,O(R) -> strh */ 1268 aclass(&p->to); 1269 r = p->to.reg; 1270 if(r == NREG) 1271 r = o->param; 1272 o1 = oshr(p->from.reg, instoffset, r, p->scond); 1273 break; 1274 case 71: /* movb/movh/movhu O(R),R -> ldrsb/ldrsh/ldrh */ 1275 aclass(&p->from); 1276 r = p->from.reg; 1277 if(r == NREG) 1278 r = o->param; 1279 o1 = olhr(instoffset, r, p->to.reg, p->scond); 1280 if(p->as == AMOVB) 1281 o1 ^= (1<<5)|(1<<6); 1282 else if(p->as == AMOVH) 1283 o1 ^= (1<<6); 1284 break; 1285 case 72: /* movh/movhu R,L(R) -> strh */ 1286 o1 = omvl(p, &p->to, REGTMP); 1287 if(!o1) 1288 break; 1289 r = p->to.reg; 1290 if(r == NREG) 1291 r = o->param; 1292 o2 = oshrr(p->from.reg, REGTMP,r, p->scond); 1293 break; 1294 case 73: /* movb/movh/movhu L(R),R -> ldrsb/ldrsh/ldrh */ 1295 o1 = omvl(p, &p->from, REGTMP); 1296 if(!o1) 1297 break; 1298 r = p->from.reg; 1299 if(r == NREG) 1300 r = o->param; 1301 o2 = olhrr(REGTMP, r, p->to.reg, p->scond); 1302 if(p->as == AMOVB) 1303 o2 ^= (1<<5)|(1<<6); 1304 else if(p->as == AMOVH) 1305 o2 ^= (1<<6); 1306 break; 1307 } 1308 1309 if(debug['a'] > 1) 1310 Bprint(&bso, "%2d ", o->type); 1311 1312 v = p->pc; 1313 switch(o->size) { 1314 default: 1315 if(debug['a']) 1316 Bprint(&bso, " %.8lux:\t\t%P\n", v, p); 1317 break; 1318 case 4: 1319 if(debug['a']) 1320 Bprint(&bso, " %.8lux: %.8lux\t%P\n", v, o1, p); 1321 lputl(o1); 1322 break; 1323 case 8: 1324 if(debug['a']) 1325 Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", v, o1, o2, p); 1326 lputl(o1); 1327 lputl(o2); 1328 break; 1329 case 12: 1330 if(debug['a']) 1331 Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux%P\n", v, o1, o2, o3, p); 1332 lputl(o1); 1333 lputl(o2); 1334 lputl(o3); 1335 break; 1336 case 16: 1337 if(debug['a']) 1338 Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux%P\n", 1339 v, o1, o2, o3, o4, p); 1340 lputl(o1); 1341 lputl(o2); 1342 lputl(o3); 1343 lputl(o4); 1344 break; 1345 case 20: 1346 if(debug['a']) 1347 Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux%P\n", 1348 v, o1, o2, o3, o4, o5, p); 1349 lputl(o1); 1350 lputl(o2); 1351 lputl(o3); 1352 lputl(o4); 1353 lputl(o5); 1354 break; 1355 case 24: 1356 if(debug['a']) 1357 Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux %.8lux%P\n", 1358 v, o1, o2, o3, o4, o5, o6, p); 1359 lputl(o1); 1360 lputl(o2); 1361 lputl(o3); 1362 lputl(o4); 1363 lputl(o5); 1364 lputl(o6); 1365 break; 1366 } 1367 } 1368 1369 long 1370 oprrr(int a, int sc) 1371 { 1372 long o; 1373 1374 o = (sc & C_SCOND) << 28; 1375 if(sc & C_SBIT) 1376 o |= 1 << 20; 1377 if(sc & (C_PBIT|C_WBIT)) 1378 diag(".P/.W on dp instruction"); 1379 switch(a) { 1380 case AMULU: 1381 case AMUL: return o | (0x0<<21) | (0x9<<4); 1382 case AMULA: return o | (0x1<<21) | (0x9<<4); 1383 case AMULLU: return o | (0x4<<21) | (0x9<<4); 1384 case AMULL: return o | (0x6<<21) | (0x9<<4); 1385 case AMULALU: return o | (0x5<<21) | (0x9<<4); 1386 case AMULAL: return o | (0x7<<21) | (0x9<<4); 1387 case AAND: return o | (0x0<<21); 1388 case AEOR: return o | (0x1<<21); 1389 case ASUB: return o | (0x2<<21); 1390 case ARSB: return o | (0x3<<21); 1391 case AADD: return o | (0x4<<21); 1392 case AADC: return o | (0x5<<21); 1393 case ASBC: return o | (0x6<<21); 1394 case ARSC: return o | (0x7<<21); 1395 case ATST: return o | (0x8<<21) | (1<<20); 1396 case ATEQ: return o | (0x9<<21) | (1<<20); 1397 case ACMP: return o | (0xa<<21) | (1<<20); 1398 case ACMN: return o | (0xb<<21) | (1<<20); 1399 case AORR: return o | (0xc<<21); 1400 case AMOVW: return o | (0xd<<21); 1401 case ABIC: return o | (0xe<<21); 1402 case AMVN: return o | (0xf<<21); 1403 case ASLL: return o | (0xd<<21) | (0<<5); 1404 case ASRL: return o | (0xd<<21) | (1<<5); 1405 case ASRA: return o | (0xd<<21) | (2<<5); 1406 case ASWI: return o | (0xf<<24); 1407 1408 case AADDD: return o | (0xe<<24) | (0x0<<20) | (1<<8) | (1<<7); 1409 case AADDF: return o | (0xe<<24) | (0x0<<20) | (1<<8); 1410 case AMULD: return o | (0xe<<24) | (0x1<<20) | (1<<8) | (1<<7); 1411 case AMULF: return o | (0xe<<24) | (0x1<<20) | (1<<8); 1412 case ASUBD: return o | (0xe<<24) | (0x2<<20) | (1<<8) | (1<<7); 1413 case ASUBF: return o | (0xe<<24) | (0x2<<20) | (1<<8); 1414 case ADIVD: return o | (0xe<<24) | (0x4<<20) | (1<<8) | (1<<7); 1415 case ADIVF: return o | (0xe<<24) | (0x4<<20) | (1<<8); 1416 case ACMPD: 1417 case ACMPF: return o | (0xe<<24) | (0x9<<20) | (0xF<<12) | (1<<8) | (1<<4); /* arguably, ACMPF should expand to RNDF, CMPD */ 1418 1419 case AMOVF: 1420 case AMOVDF: return o | (0xe<<24) | (0x0<<20) | (1<<15) | (1<<8); 1421 case AMOVD: 1422 case AMOVFD: return o | (0xe<<24) | (0x0<<20) | (1<<15) | (1<<8) | (1<<7); 1423 1424 case AMOVWF: return o | (0xe<<24) | (0<<20) | (1<<8) | (1<<4); 1425 case AMOVWD: return o | (0xe<<24) | (0<<20) | (1<<8) | (1<<4) | (1<<7); 1426 case AMOVFW: return o | (0xe<<24) | (1<<20) | (1<<8) | (1<<4); 1427 case AMOVDW: return o | (0xe<<24) | (1<<20) | (1<<8) | (1<<4) | (1<<7); 1428 } 1429 diag("bad rrr %d", a); 1430 prasm(curp); 1431 return 0; 1432 } 1433 1434 long 1435 opbra(int a, int sc) 1436 { 1437 1438 if(sc & (C_SBIT|C_PBIT|C_WBIT)) 1439 diag(".S/.P/.W on bra instruction"); 1440 sc &= C_SCOND; 1441 if(a == ABL) 1442 return (sc<<28)|(0x5<<25)|(0x1<<24); 1443 if(sc != 0xe) 1444 diag(".COND on bcond instruction"); 1445 switch(a) { 1446 case ABEQ: return (0x0<<28)|(0x5<<25); 1447 case ABNE: return (0x1<<28)|(0x5<<25); 1448 case ABCS: return (0x2<<28)|(0x5<<25); 1449 case ABHS: return (0x2<<28)|(0x5<<25); 1450 case ABCC: return (0x3<<28)|(0x5<<25); 1451 case ABLO: return (0x3<<28)|(0x5<<25); 1452 case ABMI: return (0x4<<28)|(0x5<<25); 1453 case ABPL: return (0x5<<28)|(0x5<<25); 1454 case ABVS: return (0x6<<28)|(0x5<<25); 1455 case ABVC: return (0x7<<28)|(0x5<<25); 1456 case ABHI: return (0x8<<28)|(0x5<<25); 1457 case ABLS: return (0x9<<28)|(0x5<<25); 1458 case ABGE: return (0xa<<28)|(0x5<<25); 1459 case ABLT: return (0xb<<28)|(0x5<<25); 1460 case ABGT: return (0xc<<28)|(0x5<<25); 1461 case ABLE: return (0xd<<28)|(0x5<<25); 1462 case AB: return (0xe<<28)|(0x5<<25); 1463 } 1464 diag("bad bra %A", a); 1465 prasm(curp); 1466 return 0; 1467 } 1468 1469 long 1470 olr(long v, int b, int r, int sc) 1471 { 1472 long o; 1473 1474 if(sc & C_SBIT) 1475 diag(".S on LDR/STR instruction"); 1476 o = (sc & C_SCOND) << 28; 1477 if(!(sc & C_PBIT)) 1478 o |= 1 << 24; 1479 if(!(sc & C_UBIT)) 1480 o |= 1 << 23; 1481 if(sc & C_WBIT) 1482 o |= 1 << 21; 1483 o |= (0x1<<26) | (1<<20); 1484 if(v < 0) { 1485 v = -v; 1486 o ^= 1 << 23; 1487 } 1488 if(v >= (1<<12)) 1489 diag("literal span too large: %ld (R%d)\n%P", v, b, PP); 1490 o |= v; 1491 o |= b << 16; 1492 o |= r << 12; 1493 return o; 1494 } 1495 1496 long 1497 olhr(long v, int b, int r, int sc) 1498 { 1499 long o; 1500 1501 if(sc & C_SBIT) 1502 diag(".S on LDRH/STRH instruction"); 1503 o = (sc & C_SCOND) << 28; 1504 if(!(sc & C_PBIT)) 1505 o |= 1 << 24; 1506 if(sc & C_WBIT) 1507 o |= 1 << 21; 1508 o |= (1<<23) | (1<<20)|(0xb<<4); 1509 if(v < 0) { 1510 v = -v; 1511 o ^= 1 << 23; 1512 } 1513 if(v >= (1<<8)) 1514 diag("literal span too large: %ld (R%d)\n%P", v, b, PP); 1515 o |= (v&0xf)|((v>>4)<<8)|(1<<22); 1516 o |= b << 16; 1517 o |= r << 12; 1518 return o; 1519 } 1520 1521 long 1522 osr(int a, int r, long v, int b, int sc) 1523 { 1524 long o; 1525 1526 o = olr(v, b, r, sc) ^ (1<<20); 1527 if(a != AMOVW) 1528 o |= 1<<22; 1529 return o; 1530 } 1531 1532 long 1533 oshr(int r, long v, int b, int sc) 1534 { 1535 long o; 1536 1537 o = olhr(v, b, r, sc) ^ (1<<20); 1538 return o; 1539 } 1540 1541 1542 long 1543 osrr(int r, int i, int b, int sc) 1544 { 1545 1546 return olr(i, b, r, sc) ^ ((1<<25) | (1<<20)); 1547 } 1548 1549 long 1550 oshrr(int r, int i, int b, int sc) 1551 { 1552 return olhr(i, b, r, sc) ^ ((1<<22) | (1<<20)); 1553 } 1554 1555 long 1556 olrr(int i, int b, int r, int sc) 1557 { 1558 1559 return olr(i, b, r, sc) ^ (1<<25); 1560 } 1561 1562 long 1563 olhrr(int i, int b, int r, int sc) 1564 { 1565 return olhr(i, b, r, sc) ^ (1<<22); 1566 } 1567 1568 long 1569 ofsr(int a, int r, long v, int b, int sc, Prog *p) 1570 { 1571 long o; 1572 1573 if(sc & C_SBIT) 1574 diag(".S on FLDR/FSTR instruction"); 1575 o = (sc & C_SCOND) << 28; 1576 if(!(sc & C_PBIT)) 1577 o |= 1 << 24; 1578 if(sc & C_WBIT) 1579 o |= 1 << 21; 1580 o |= (6<<25) | (1<<24) | (1<<23); 1581 if(v < 0) { 1582 v = -v; 1583 o ^= 1 << 23; 1584 } 1585 if(v & 3) 1586 diag("odd offset for floating point op: %ld\n%P", v, p); 1587 else if(v >= (1<<10)) 1588 diag("literal span too large: %ld\n%P", v, p); 1589 o |= (v>>2) & 0xFF; 1590 o |= b << 16; 1591 o |= r << 12; 1592 o |= 1 << 8; 1593 1594 switch(a) { 1595 default: 1596 diag("bad fst %A", a); 1597 case AMOVD: 1598 o |= 1<<15; 1599 case AMOVF: 1600 break; 1601 } 1602 return o; 1603 } 1604 1605 long 1606 omvl(Prog *p, Adr *a, int dr) 1607 { 1608 long v, o1; 1609 if(!p->cond) { 1610 aclass(a); 1611 v = immrot(~instoffset); 1612 if(v == 0) { 1613 diag("missing literal"); 1614 prasm(p); 1615 return 0; 1616 } 1617 o1 = oprrr(AMVN, p->scond&C_SCOND); 1618 o1 |= v; 1619 o1 |= dr << 12; 1620 } else { 1621 v = p->cond->pc - p->pc - 8; 1622 o1 = olr(v, REGPC, dr, p->scond&C_SCOND); 1623 } 1624 return o1; 1625 } 1626 1627 static Ieee chipfloats[] = { 1628 {0x00000000, 0x00000000}, /* 0 */ 1629 {0x00000000, 0x3ff00000}, /* 1 */ 1630 {0x00000000, 0x40000000}, /* 2 */ 1631 {0x00000000, 0x40080000}, /* 3 */ 1632 {0x00000000, 0x40100000}, /* 4 */ 1633 {0x00000000, 0x40140000}, /* 5 */ 1634 {0x00000000, 0x3fe00000}, /* .5 */ 1635 {0x00000000, 0x40240000}, /* 10 */ 1636 }; 1637 1638 int 1639 chipfloat(Ieee *e) 1640 { 1641 Ieee *p; 1642 int n; 1643 1644 for(n = sizeof(chipfloats)/sizeof(chipfloats[0]); --n >= 0;){ 1645 p = &chipfloats[n]; 1646 if(p->l == e->l && p->h == e->h) 1647 return n; 1648 } 1649 return -1; 1650 } 1651