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