1 #include <u.h> 2 #include <libc.h> 3 #include <bio.h> 4 #include <mach.h> 5 6 /* 7 * Sparc-specific debugger interface 8 */ 9 10 static char *sparcexcep(Map*, Rgetter); 11 static int sparcfoll(Map*, ulong, Rgetter, ulong*); 12 static int sparcinst(Map*, ulong, char, char*, int); 13 static int sparcdas(Map*, ulong, char*, int); 14 static int sparcinstlen(Map*, ulong); 15 16 Machdata sparcmach = 17 { 18 {0x91, 0xd0, 0x20, 0x01}, /* breakpoint: TA $1 */ 19 4, /* break point size */ 20 21 beswab, /* convert short to local byte order */ 22 beswal, /* convert long to local byte order */ 23 risctrace, /* C traceback */ 24 riscframe, /* frame finder */ 25 0, /* ublock fixup */ 26 sparcexcep, /* print exception */ 27 0, /* breakpoint fixup */ 28 beieeesftos, /* single precision float printer */ 29 beieeedftos, /* double precision float printer */ 30 sparcfoll, /* following addresses */ 31 sparcinst, /* print instruction */ 32 sparcdas, /* dissembler */ 33 sparcinstlen, /* instruction size */ 34 }; 35 36 static char *trapname[] = 37 { 38 "reset", 39 "instruction access exception", 40 "illegal instruction", 41 "privileged instruction", 42 "fp disabled", 43 "window overflow", 44 "window underflow", 45 "unaligned address", 46 "fp exception", 47 "data access exception", 48 "tag overflow", 49 }; 50 51 static char* 52 excname(ulong tbr) 53 { 54 static char buf[32]; 55 56 if(tbr < sizeof trapname/sizeof(char*)) 57 return trapname[tbr]; 58 if(tbr >= 130) 59 sprint(buf, "trap instruction %d", tbr-128); 60 else if(17<=tbr && tbr<=31) 61 sprint(buf, "interrupt level %d", tbr-16); 62 else switch(tbr){ 63 case 36: 64 return "cp disabled"; 65 case 40: 66 return "cp exception"; 67 case 128: 68 return "syscall"; 69 case 129: 70 return "breakpoint"; 71 default: 72 sprint(buf, "unknown trap %d", tbr); 73 } 74 Return: 75 return buf; 76 } 77 78 static char* 79 sparcexcep(Map *map, Rgetter rget) 80 { 81 long tbr; 82 83 tbr = (*rget)(map, "TBR"); 84 tbr = (tbr&0xFFF)>>4; 85 return excname(tbr); 86 } 87 88 /* Sparc disassembler and related functions */ 89 90 struct opcode { 91 char *mnemonic; 92 void (*f)(struct instr*, char*); 93 int flag; 94 }; 95 96 static char FRAMENAME[] = ".frame"; 97 98 typedef struct instr Instr; 99 100 struct instr { 101 uchar op; /* bits 31-30 */ 102 uchar rd; /* bits 29-25 */ 103 uchar op2; /* bits 24-22 */ 104 uchar a; /* bit 29 */ 105 uchar cond; /* bits 28-25 */ 106 uchar op3; /* bits 24-19 */ 107 uchar rs1; /* bits 18-14 */ 108 uchar i; /* bit 13 */ 109 uchar asi; /* bits 12-05 */ 110 uchar rs2; /* bits 04-00 */ 111 short simm13; /* bits 12-00, signed */ 112 ushort opf; /* bits 13-05 */ 113 ulong immdisp22; /* bits 21-00 */ 114 ulong simmdisp22; /* bits 21-00, signed */ 115 ulong disp30; /* bits 30-00 */ 116 ulong imm32; /* SETHI+ADD constant */ 117 int target; /* SETHI+ADD dest reg */ 118 long w0; 119 long w1; 120 ulong addr; /* pc of instruction */ 121 char *curr; /* current fill level in output buffer */ 122 char *end; /* end of buffer */ 123 int size; /* number of longs in instr */ 124 char *err; /* errmsg */ 125 }; 126 127 static Map *mymap; /* disassembler context */ 128 static int dascase; 129 130 static int mkinstr(ulong, Instr*); 131 static void bra1(Instr*, char*, char*[]); 132 static void bra(Instr*, char*); 133 static void fbra(Instr*, char*); 134 static void cbra(Instr*, char*); 135 static void unimp(Instr*, char*); 136 static void fpop(Instr*, char*); 137 static void shift(Instr*, char*); 138 static void sethi(Instr*, char*); 139 static void load(Instr*, char*); 140 static void loada(Instr*, char*); 141 static void store(Instr*, char*); 142 static void storea(Instr*, char*); 143 static void add(Instr*, char*); 144 static void cmp(Instr*, char*); 145 static void wr(Instr*, char*); 146 static void jmpl(Instr*, char*); 147 static void rd(Instr*, char*); 148 static void loadf(Instr*, char*); 149 static void storef(Instr*, char*); 150 static void loadc(Instr*, char*); 151 static void loadcsr(Instr*, char*); 152 static void trap(Instr*, char*); 153 154 static struct opcode sparcop0[8] = { 155 [0] "UNIMP", unimp, 0, /* page 137 */ 156 [2] "B", bra, 0, /* page 119 */ 157 [4] "SETHI", sethi, 0, /* page 104 */ 158 [6] "FB", fbra, 0, /* page 121 */ 159 [7] "CB", cbra, 0, /* page 123 */ 160 }; 161 162 static struct opcode sparcop2[64] = { 163 [0x00] "ADD", add, 0, /* page 108 */ 164 [0x10] "ADDCC", add, 0, 165 [0x08] "ADDX", add, 0, 166 [0x18] "ADDXCC", add, 0, 167 168 [0x20] "TADD", add, 0, /* page 109 */ 169 [0x22] "TADDCCTV", add, 0, 170 171 [0x04] "SUB", add, 0, /* page 110 */ 172 [0x14] "SUBCC", cmp, 0, 173 [0x0C] "SUBX", add, 0, 174 [0x1C] "SUBXCC", add, 0, 175 176 [0x21] "TSUB", add, 0, /* page 111 */ 177 [0x23] "TSUBCCTV", add, 0, 178 179 [0x24] "MULSCC", add, 0, /* page 112 */ 180 181 [0x0A] "UMUL", add, 0, /* page 113 */ 182 [0x0B] "SMUL", add, 0, 183 [0x1A] "UMULCC", add, 0, 184 [0x1B] "SMULCC", add, 0, 185 186 [0x0E] "UDIV", add, 0, /* page 115 */ 187 [0x0F] "SDIV", add, 0, 188 [0x1E] "UDIVCC", add, 0, 189 [0x1F] "SDIVCC", add, 0, 190 191 [0x01] "AND", add, 0, /* page 106 */ 192 [0x11] "ANDCC", add, 0, 193 [0x05] "ANDN", add, 0, 194 [0x15] "ANDNCC", add, 0, 195 [0x02] "OR", add, 0, 196 [0x12] "ORCC", add, 0, 197 [0x06] "ORN", add, 0, 198 [0x16] "ORNCC", add, 0, 199 [0x03] "XOR", add, 0, 200 [0x13] "XORCC", add, 0, 201 [0x07] "XORN", add, 0, 202 [0x17] "XORNCC", add, 0, 203 204 [0x25] "SLL", shift, 0, /* page 107 */ 205 [0x26] "SRL", shift, 0, 206 [0x27] "SRA", shift, 0, 207 208 [0x3C] "SAVE", add, 0, /* page 117 */ 209 [0x3D] "RESTORE", add, 0, 210 211 [0x38] "JMPL", jmpl, 0, /* page 126 */ 212 213 [0x39] "RETT", add, 0, /* page 127 */ 214 215 [0x3A] "T", trap, 0, /* page 129 */ 216 217 [0x28] "rdy", rd, 0, /* page 131 */ 218 [0x29] "rdpsr", rd, 0, 219 [0x2A] "rdwim", rd, 0, 220 [0x2B] "rdtbr", rd, 0, 221 222 [0x30] "wry", wr, 0, /* page 133 */ 223 [0x31] "wrpsr", wr, 0, 224 [0x32] "wrwim", wr, 0, 225 [0x33] "wrtbr", wr, 0, 226 227 [0x3B] "flush", add, 0, /* page 138 */ 228 229 [0x34] "FPOP", fpop, 0, /* page 140 */ 230 [0x35] "FPOP", fpop, 0, 231 }; 232 233 static struct opcode sparcop3[64]={ 234 [0x09] "ldsb", load, 0, /* page 90 */ 235 [0x19] "ldsba", loada, 0, 236 [0x0A] "ldsh", load, 0, 237 [0x1A] "ldsha", loada, 0, 238 [0x01] "ldub", load, 0, 239 [0x11] "lduba", loada, 0, 240 [0x02] "lduh", load, 0, 241 [0x12] "lduha", loada, 0, 242 [0x00] "ld", load, 0, 243 [0x10] "lda", loada, 0, 244 [0x03] "ldd", load, 0, 245 [0x13] "ldda", loada, 0, 246 247 [0x20] "ldf", loadf, 0, /* page 92 */ 248 [0x23] "lddf", loadf, 0, 249 [0x21] "ldfsr", loadf,0, 250 251 [0x30] "ldc", loadc, 0, /* page 94 */ 252 [0x33] "lddc", loadc, 0, 253 [0x31] "ldcsr", loadcsr,0, 254 255 [0x05] "stb", store, 0, /* page 95 */ 256 [0x15] "stba", storea, 0, 257 [0x06] "sth", store, 0, 258 [0x16] "stha", storea, 0, 259 [0x04] "st", store, 0, 260 [0x14] "sta", storea, 0, 261 [0x07] "std", store, 0, 262 [0x17] "stda", storea, 0, 263 264 [0x24] "stf", storef, 0, /* page 97 */ 265 [0x27] "stdf", storef, 0, 266 [0x25] "stfsr", storef,0, 267 [0x26] "stdfq", storef,0, 268 269 [0x34] "stc", loadc, 0, /* page 99 */ 270 [0x37] "stdc", loadc, 0, 271 [0x35] "stcsr", loadcsr,0, 272 [0x36] "stdcq", loadcsr,0, 273 274 [0x0D] "ldstub", store, 0, /* page 101 */ 275 [0x1D] "ldstuba", storea, 0, 276 277 [0x0F] "swap", load, 0, /* page 102 */ 278 [0x1F] "swapa", loada, 0, 279 }; 280 281 static void 282 bprint(Instr *i, char *fmt, ...) 283 { 284 i->curr = doprint(i->curr, i->end, fmt, (&fmt+1)); 285 } 286 287 static int 288 decode(ulong pc, Instr *i) 289 { 290 long w; 291 292 if (get4(mymap, pc, &w) < 0) { 293 werrstr("can't read instruction: %r"); 294 return -1; 295 } 296 i->op = (w >> 30) & 0x03; 297 i->rd = (w >> 25) & 0x1F; 298 i->op2 = (w >> 22) & 0x07; 299 i->a = (w >> 29) & 0x01; 300 i->cond = (w >> 25) & 0x0F; 301 i->op3 = (w >> 19) & 0x3F; 302 i->rs1 = (w >> 14) & 0x1F; 303 i->i = (w >> 13) & 0x01; 304 i->asi = (w >> 5) & 0xFF; 305 i->rs2 = (w >> 0) & 0x1F; 306 i->simm13 = (w >> 0) & 0x1FFF; 307 if(i->simm13 & (1<<12)) 308 i->simm13 |= ~((1<<13)-1); 309 i->opf = (w >> 5) & 0x1FF; 310 i->immdisp22 = (w >> 0) & 0x3FFFFF; 311 i->simmdisp22 = i->immdisp22; 312 if(i->simmdisp22 & (1<<21)) 313 i->simmdisp22 |= ~((1<<22)-1); 314 i->disp30 = (w >> 0) & 0x3FFFFFFF; 315 i->w0 = w; 316 i->target = -1; 317 i->addr = pc; 318 i->size = 1; 319 return 1; 320 } 321 322 static int 323 mkinstr(ulong pc, Instr *i) 324 { 325 Instr xi; 326 327 if (decode(pc, i) < 0) 328 return -1; 329 if(i->op==0 && i->op2==4 && !dascase){ /* SETHI */ 330 if (decode(pc+4, &xi) < 0) 331 return -1; 332 if(xi.op==2 && xi.op3==0) /* ADD */ 333 if(xi.i == 1 && xi.rs1 == i->rd){ /* immediate to same reg */ 334 i->imm32 = xi.simm13 + (i->immdisp22<<10); 335 i->target = xi.rd; 336 i->w1 = xi.w0; 337 i->size++; 338 return 1; 339 } 340 } 341 if(i->op==2 && i->opf==1 && !dascase){ /* FMOVS */ 342 if (decode(pc+4, &xi) < 0) 343 return -1; 344 if(i->op==2 && i->opf==1) /* FMOVS */ 345 if(xi.rd==i->rd+1 && xi.rs2==i->rs2+1){ /* next pair */ 346 i->w1 = xi.w0; 347 i->size++; 348 } 349 } 350 return 1; 351 } 352 353 static int 354 printins(Map *map, ulong pc, char *buf, int n) 355 { 356 Instr instr; 357 void (*f)(Instr*, char*); 358 359 mymap = map; 360 memset(&instr, 0, sizeof(instr)); 361 instr.curr = buf; 362 instr.end = buf+n-1; 363 if (mkinstr(pc, &instr) < 0) 364 return -1; 365 switch(instr.op){ 366 case 0: 367 f = sparcop0[instr.op2].f; 368 if(f) 369 (*f)(&instr, sparcop0[instr.op2].mnemonic); 370 else 371 bprint(&instr, "unknown %lux", instr.w0); 372 break; 373 374 case 1: 375 bprint(&instr, "%X", "CALL\t"); 376 instr.curr += symoff(instr.curr, instr.end-instr.curr, 377 pc+instr.disp30*4, CTEXT); 378 if (!dascase) 379 bprint(&instr, "(SB)"); 380 break; 381 382 case 2: 383 f = sparcop2[instr.op3].f; 384 if(f) 385 (*f)(&instr, sparcop2[instr.op3].mnemonic); 386 else 387 bprint(&instr, "unknown %lux", instr.w0); 388 break; 389 390 case 3: 391 f = sparcop3[instr.op3].f; 392 if(f) 393 (*f)(&instr, sparcop3[instr.op3].mnemonic); 394 else 395 bprint(&instr, "unknown %lux", instr.w0); 396 break; 397 } 398 if (instr.err) { 399 if (instr.curr != buf) 400 bprint(&instr, "\t\t;"); 401 bprint(&instr, instr.err); 402 } 403 return instr.size*4; 404 } 405 406 /* convert to lower case from upper, according to dascase */ 407 static int 408 Xconv(void *oa, Fconv *f) 409 { 410 char buf[128]; 411 char *s, *t; 412 413 if(dascase){ 414 for(s=*(char**)oa,t=buf; *t = *s; s++,t++) 415 if('A'<=*t && *t<='Z') 416 *t += 'a'-'A'; 417 strconv(buf, f); 418 }else 419 strconv(*(char**)oa, f); 420 return sizeof(char*); 421 } 422 423 static int 424 sparcinst(Map *map, ulong pc, char modifier, char *buf, int n) 425 { 426 static int fmtinstalled = 0; 427 428 /* a modifier of 'I' toggles the dissassembler type */ 429 if (!fmtinstalled) { 430 fmtinstalled = 1; 431 fmtinstall('X', Xconv); 432 } 433 if ((asstype == ASUNSPARC && modifier == 'i') 434 || (asstype == ASPARC && modifier == 'I')) 435 dascase = 'a'-'A'; 436 else 437 dascase = 0; 438 return printins(map, pc, buf, n); 439 } 440 441 static int 442 sparcdas(Map *map, ulong pc, char *buf, int n) 443 { 444 Instr instr; 445 446 mymap = map; 447 memset(&instr, 0, sizeof(instr)); 448 instr.curr = buf; 449 instr.end = buf+n-1; 450 if (mkinstr(pc, &instr) < 0) 451 return -1; 452 if (instr.end-instr.curr > 8) 453 instr.curr = _hexify(instr.curr, instr.w0, 7); 454 if (instr.end-instr.curr > 9 && instr.size == 2) { 455 *instr.curr++ = ' '; 456 instr.curr = _hexify(instr.curr, instr.w1, 7); 457 } 458 *instr.curr = 0; 459 return instr.size*4; 460 } 461 462 static int 463 sparcinstlen(Map *map, ulong pc) 464 { 465 Instr i; 466 467 mymap = map; 468 if (mkinstr(pc, &i) < 0) 469 return -1; 470 return i.size*4; 471 } 472 473 static int 474 plocal(Instr *i) 475 { 476 int offset; 477 Symbol s; 478 479 if (!findsym(i->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s)) 480 return -1; 481 if (s.value > i->simm13) { 482 if(getauto(&s, s.value-i->simm13, CAUTO, &s)) { 483 bprint(i, "%s+%d(SP)", s.name, s.value); 484 return 1; 485 } 486 } else { 487 offset = i->simm13-s.value; 488 if (getauto(&s, offset-4, CPARAM, &s)) { 489 bprint(i, "%s+%d(FP)", s.name, offset); 490 return 1; 491 } 492 } 493 return -1; 494 } 495 496 static void 497 address(Instr *i) 498 { 499 Symbol s, s2; 500 long off, off1; 501 502 if (i->rs1 == 1 && plocal(i) >= 0) 503 return; 504 off = mach->sb+i->simm13; 505 if(i->rs1 == 2 && findsym(off, CANY, &s) 506 && s.value-off < 4096 507 && (s.class == CDATA || s.class == CTEXT)) { 508 if(off==s.value && s.name[0]=='$'){ 509 off1 = 0; 510 get4(mymap, s.value, &off1); 511 if(off1 && findsym(off1, CANY, &s2) && s2.value == off1){ 512 bprint(i, "$%s(SB)", s2.name); 513 return; 514 } 515 } 516 bprint(i, "%s", s.name); 517 if (s.value != off) 518 bprint(i, "+%lux", s.value-off); 519 bprint(i, "(SB)"); 520 return; 521 } 522 bprint(i, "%lux(R%d)", i->simm13, i->rs1); 523 } 524 525 static void 526 unimp(Instr *i, char *m) 527 { 528 bprint(i, "%X", m); 529 } 530 531 static char *bratab[16] = { /* page 91 */ 532 [0X8] "A", 533 [0X0] "N", 534 [0X9] "NE", 535 [0X1] "E", 536 [0XA] "G", 537 [0X2] "LE", 538 [0XB] "GE", 539 [0X3] "L", 540 [0XC] "GU", 541 [0X4] "LEU", 542 [0XD] "CC", 543 [0X5] "CS", 544 [0XE] "POS", 545 [0X6] "NEG", 546 [0XF] "VC", 547 [0X7] "VS", 548 }; 549 550 static char *fbratab[16] = { /* page 91 */ 551 [0X8] "A", 552 [0X0] "N", 553 [0X7] "U", 554 [0X6] "G", 555 [0X5] "UG", 556 [0X4] "L", 557 [0X3] "UL", 558 [0X2] "LG", 559 [0X1] "NE", 560 [0X9] "E", 561 [0XA] "UE", 562 [0XB] "GE", 563 [0XC] "UGE", 564 [0XD] "LE", 565 [0XE] "ULE", 566 [0XF] "O", 567 }; 568 569 static char *cbratab[16] = { /* page 91 */ 570 [0X8] "A", 571 [0X0] "N", 572 [0X7] "3", 573 [0X6] "2", 574 [0X5] "23", 575 [0X4] "1", 576 [0X3] "13", 577 [0X2] "12", 578 [0X1] "123", 579 [0X9] "0", 580 [0XA] "03", 581 [0XB] "02", 582 [0XC] "023", 583 [0XD] "01", 584 [0XE] "013", 585 [0XF] "012", 586 }; 587 588 static void 589 bra1(Instr *i, char *m, char *tab[]) 590 { 591 long imm; 592 593 imm = i->simmdisp22; 594 if(i->a) 595 bprint(i, "%X%X.%c\t", m, tab[i->cond], 'A'+dascase); 596 else 597 bprint(i, "%X%X\t", m, tab[i->cond]); 598 i->curr += symoff(i->curr, i->end-i->curr, i->addr+4*imm, CTEXT); 599 if (!dascase) 600 bprint(i, "(SB)"); 601 } 602 603 static void 604 bra(Instr *i, char *m) /* page 91 */ 605 { 606 bra1(i, m, bratab); 607 } 608 609 static void 610 fbra(Instr *i, char *m) /* page 93 */ 611 { 612 bra1(i, m, fbratab); 613 } 614 615 static void 616 cbra(Instr *i, char *m) /* page 95 */ 617 { 618 bra1(i, m, cbratab); 619 } 620 621 static void 622 trap(Instr *i, char *m) /* page 101 */ 623 { 624 if(i->i == 0) 625 bprint(i, "%X%X\tR%d+R%d", m, bratab[i->cond], i->rs2, i->rs1); 626 else 627 bprint(i, "%X%X\t$%lux+R%d", m, bratab[i->cond], i->simm13, i->rs1); 628 } 629 630 static void 631 sethi(Instr *i, char *m) /* page 89 */ 632 { 633 ulong imm; 634 635 imm = i->immdisp22<<10; 636 if(dascase){ 637 bprint(i, "%X\t%lux, R%d", m, imm, i->rd); 638 return; 639 } 640 if(imm==0 && i->rd==0){ 641 bprint(i, "NOP"); 642 return; 643 } 644 if(i->target < 0){ 645 bprint(i, "MOVW\t$%lux, R%d", imm, i->rd); 646 return; 647 } 648 bprint(i, "MOVW\t$%lux, R%d", i->imm32, i->target); 649 } 650 651 static char ldtab[] = { 652 'W', 653 'B', 654 'H', 655 'D', 656 }; 657 658 static char* 659 moveinstr(int op3, char *m) 660 { 661 char *s; 662 int c; 663 static char buf[8]; 664 665 if(!dascase){ 666 /* batshit cases */ 667 if(op3 == 0xF || op3 == 0x1F) 668 return "SWAP"; 669 if(op3 == 0xD || op3 == 0x1D) 670 return "TAS"; /* really LDSTUB */ 671 c = ldtab[op3&3]; 672 s = ""; 673 if((op3&11)==1 || (op3&11)==2) 674 s="U"; 675 sprint(buf, "MOV%c%s", c, s); 676 return buf; 677 } 678 return m; 679 } 680 681 static void 682 load(Instr *i, char *m) /* page 68 */ 683 { 684 m = moveinstr(i->op3, m); 685 if(i->i == 0) 686 bprint(i, "%s\t(R%d+R%d), R%d", m, i->rs1, i->rs2, i->rd); 687 else{ 688 bprint(i, "%s\t", m); 689 address(i); 690 bprint(i, ", R%d", i->rd); 691 } 692 } 693 694 static void 695 loada(Instr *i, char *m) /* page 68 */ 696 { 697 m = moveinstr(i->op3, m); 698 if(i->i == 0) 699 bprint(i, "%s\t(R%d+R%d, %d), R%d", m, i->rs1, i->rs2, i->asi, i->rd); 700 else 701 bprint(i, "unknown ld asi %lux", i->w0); 702 } 703 704 static void 705 store(Instr *i, char *m) /* page 74 */ 706 { 707 m = moveinstr(i->op3, m); 708 if(i->i == 0) 709 bprint(i, "%s\tR%d, (R%d+R%d)", 710 m, i->rd, i->rs1, i->rs2); 711 else{ 712 bprint(i, "%s\tR%d, ", m, i->rd); 713 address(i); 714 } 715 } 716 717 static void 718 storea(Instr *i, char *m) /* page 74 */ 719 { 720 m = moveinstr(i->op3, m); 721 if(i->i == 0) 722 bprint(i, "%s\tR%d, (R%d+R%d, %d)", m, i->rd, i->rs1, i->rs2, i->asi); 723 else 724 bprint(i, "%s\tR%d, %d(R%d, %d), ???", m, i->rd, i->simm13, i->rs1, i->asi); 725 } 726 727 void 728 shift(Instr *i, char *m) /* page 88 */ 729 { 730 if(i->i == 0){ 731 if(i->rs1 == i->rd) 732 if(dascase) 733 bprint(i, "%X\tR%d, R%d", m, i->rs1, i->rs2); 734 else 735 bprint(i, "%X\tR%d, R%d", m, i->rs2, i->rs1); 736 else 737 if(dascase) 738 bprint(i, "%X\tR%d, R%d, R%d", m, i->rs1, i->rs2, i->rd); 739 else 740 bprint(i, "%X\tR%d, R%d, R%d", m, i->rs2, i->rs1, i->rd); 741 }else{ 742 if(i->rs1 == i->rd) 743 if(dascase) 744 bprint(i, "%X\t$%d,R%d", m, i->simm13&0x1F, i->rs1); 745 else 746 bprint(i, "%X\tR%d, $%d", m, i->rs1, i->simm13&0x1F); 747 else 748 if(dascase) 749 bprint(i, "%X\tR%d, $%d, R%d",m,i->rs1,i->simm13&0x1F,i->rd); 750 else 751 bprint(i, "%X\t$%d, R%d, R%d",m,i->simm13&0x1F,i->rs1,i->rd); 752 } 753 } 754 755 static void 756 add(Instr *i, char *m) /* page 82 */ 757 { 758 if(i->i == 0){ 759 if(dascase) 760 bprint(i, "%X\tR%d, R%d", m, i->rs1, i->rs2); 761 else 762 if(i->op3==2 && i->rs1==0 && i->rd) /* OR R2, R0, R1 */ 763 bprint(i, "MOVW\tR%d", i->rs2); 764 else 765 bprint(i, "%X\tR%d, R%d", m, i->rs2, i->rs1); 766 }else{ 767 if(dascase) 768 bprint(i, "%X\tR%d, $%lux", m, i->rs1, i->simm13); 769 else 770 if(i->op3==0 && i->rd && i->rs1==0) /* ADD $x, R0, R1 */ 771 bprint(i, "MOVW\t$%lux", i->simm13); 772 else if(i->op3==0 && i->rd && i->rs1==2){ 773 /* ADD $x, R2, R1 -> MOVW $x(SB), R1 */ 774 bprint(i, "MOVW\t$"); 775 address(i); 776 } else 777 bprint(i, "%X\t$%lux, R%d", m, i->simm13, i->rs1); 778 } 779 if(i->rs1 != i->rd) 780 bprint(i, ", R%d", i->rd); 781 } 782 783 static void 784 cmp(Instr *i, char *m) 785 { 786 if(dascase || i->rd){ 787 add(i, m); 788 return; 789 } 790 if(i->i == 0) 791 bprint(i, "CMP\tR%d, R%d", i->rs1, i->rs2); 792 else 793 bprint(i, "CMP\tR%d, $%lux", i->rs1, i->simm13); 794 } 795 796 static char *regtab[4] = { 797 "Y", 798 "PSR", 799 "WIM", 800 "TBR", 801 }; 802 803 static void 804 wr(Instr *i, char *m) /* page 82 */ 805 { 806 if(dascase){ 807 if(i->i == 0) 808 bprint(i, "%s\tR%d, R%d", m, i->rs1, i->rs2); 809 else 810 bprint(i, "%s\tR%d, $%lux", m, i->rs1, i->simm13); 811 }else{ 812 if(i->i && i->simm13==0) 813 bprint(i, "MOVW\tR%d", i->rs1); 814 else if(i->i == 0) 815 bprint(i, "wr\tR%d, R%d", i->rs2, i->rs1); 816 else 817 bprint(i, "wr\t$%lux, R%d", i->simm13, i->rs1); 818 } 819 bprint(i, ", %s", regtab[i->op3&3]); 820 } 821 822 static void 823 rd(Instr *i, char *m) /* page 103 */ 824 { 825 if(i->rs1==15 && i->rd==0){ 826 m = "stbar"; 827 if(!dascase) 828 m = "STBAR"; 829 bprint(i, "%s", m); 830 }else{ 831 if(!dascase) 832 m = "MOVW"; 833 bprint(i, "%s\t%s, R%d", m, regtab[i->op3&3], i->rd); 834 } 835 } 836 837 static void 838 jmpl(Instr *i, char *m) /* page 82 */ 839 { 840 if(i->i == 0){ 841 if(i->rd == 15) 842 bprint(i, "%X\t(R%d+R%d)", "CALL", i->rs2, i->rs1); 843 else 844 bprint(i, "%X\t(R%d+R%d), R%d", m, i->rs2, i->rs1, i->rd); 845 }else{ 846 if(!dascase && i->simm13==8 && i->rs1==15 && i->rd==0) 847 bprint(i, "RETURN"); 848 else{ 849 bprint(i, "%X\t", m); 850 address(i); 851 bprint(i, ", R%d", i->rd); 852 } 853 } 854 } 855 856 static void 857 loadf(Instr *i, char *m) /* page 70 */ 858 { 859 if(!dascase){ 860 m = "FMOVD"; 861 if(i->op3 == 0x20) 862 m = "FMOVF"; 863 else if(i->op3 == 0x21) 864 m = "MOVW"; 865 } 866 if(i->i == 0) 867 bprint(i, "%s\t(R%d+R%d)", m, i->rs1, i->rs2); 868 else{ 869 bprint(i, "%s\t", m); 870 address(i); 871 } 872 if(i->op3 == 0x21) 873 bprint(i, ", FSR"); 874 else 875 bprint(i, ", R%d", i->rd); 876 } 877 878 static 879 void storef(Instr *i, char *m) /* page 70 */ 880 { 881 if(!dascase){ 882 m = "FMOVD"; 883 if(i->op3 == 0x25 || i->op3 == 0x26) 884 m = "MOVW"; 885 else if(i->op3 == 0x20) 886 m = "FMOVF"; 887 } 888 bprint(i, "%s\t", m); 889 if(i->op3 == 0x25) 890 bprint(i, "FSR, "); 891 else if(i->op3 == 0x26) 892 bprint(i, "FQ, "); 893 else 894 bprint(i, "R%d, ", i->rd); 895 if(i->i == 0) 896 bprint(i, "(R%d+R%d)", i->rs1, i->rs2); 897 else 898 address(i); 899 } 900 901 static 902 void loadc(Instr *i, char *m) /* page 72 */ 903 { 904 if(i->i == 0) 905 bprint(i, "%s\t(R%d+R%d), C%d", m, i->rs1, i->rs2, i->rd); 906 else{ 907 bprint(i, "%s\t", m); 908 address(i); 909 bprint(i, ", C%d", i->rd); 910 } 911 } 912 913 static 914 void loadcsr(Instr *i, char *m) /* page 72 */ 915 { 916 if(i->i == 0) 917 bprint(i, "%s\t(R%d+R%d), CSR", m, i->rs1, i->rs2); 918 else{ 919 bprint(i, "%s\t", m); 920 address(i); 921 bprint(i, ", CSR"); 922 } 923 } 924 925 static struct{ 926 int opf; 927 char *name; 928 } fptab1[] = { /* ignores rs1 */ 929 0xC4, "FITOS", /* page 109 */ 930 0xC8, "FITOD", 931 0xCC, "FITOX", 932 933 0xD1, "FSTOI", /* page 110 */ 934 0xD2, "FDTOI", 935 0xD3, "FXTOI", 936 937 0xC9, "FSTOD", /* page 111 */ 938 0xCD, "FSTOX", 939 0xC6, "FDTOS", 940 0xCE, "FDTOX", 941 0xC7, "FXTOS", 942 0xCB, "FXTOD", 943 944 0x01, "FMOVS", /* page 112 */ 945 0x05, "FNEGS", 946 0x09, "FABSS", 947 948 0x29, "FSQRTS", /* page 113 */ 949 0x2A, "FSQRTD", 950 0x2B, "FSQRTX", 951 952 0, 0, 953 }; 954 955 static struct{ 956 int opf; 957 char *name; 958 } fptab2[] = { /* uses rs1 */ 959 960 0x41, "FADDS", /* page 114 */ 961 0x42, "FADDD", 962 0x43, "FADDX", 963 0x45, "FSUBS", 964 0x46, "FSUBD", 965 0x47, "FSUBX", 966 967 0x49, "FMULS", /* page 115 */ 968 0x4A, "FMULD", 969 0x4B, "FMULX", 970 0x4D, "FDIVS", 971 0x4E, "FDIVD", 972 0x4F, "FDIVX", 973 974 0x51, "FCMPS", /* page 116 */ 975 0x52, "FCMPD", 976 0x53, "FCMPX", 977 0x55, "FCMPES", 978 0x56, "FCMPED", 979 0x57, "FCMPEX", 980 981 0, 0 982 }; 983 984 static void 985 fpop(Instr *i, char *m) /* page 108-116 */ 986 { 987 int j; 988 989 if(dascase==0 && i->size==2){ 990 bprint(i, "FMOVD\tF%d, F%d", i->rs2, i->rd); 991 return; 992 } 993 for(j=0; fptab1[j].name; j++) 994 if(fptab1[j].opf == i->opf){ 995 bprint(i, "%X\tF%d, F%d", fptab1[j].name, i->rs2, i->rd); 996 return; 997 } 998 for(j=0; fptab2[j].name; j++) 999 if(fptab2[j].opf == i->opf){ 1000 bprint(i, "%X\tF%d, F%d, F%d", fptab2[j].name, i->rs1, i->rs2, i->rd); 1001 return; 1002 } 1003 bprint(i, "%X%ux\tF%d, F%d, F%d", m, i->opf, i->rs1, i->rs2, i->rd); 1004 } 1005 1006 static int 1007 sparcfoll(Map *map, ulong pc, Rgetter rget, ulong *foll) 1008 { 1009 ulong w, r1, r2; 1010 char buf[8]; 1011 Instr i; 1012 1013 mymap = map; 1014 if (mkinstr(pc, &i) < 0) 1015 return -1; 1016 w = i.w0; 1017 switch(w & 0xC1C00000){ 1018 case 0x00800000: /* branch on int cond */ 1019 case 0x01800000: /* branch on fp cond */ 1020 case 0x01C00000: /* branch on copr cond */ 1021 foll[0] = pc+8; 1022 foll[1] = pc + (i.simmdisp22<<2); 1023 return 2; 1024 } 1025 1026 if((w&0xC0000000) == 0x40000000){ /* CALL */ 1027 foll[0] = pc + (i.disp30<<2); 1028 return 1; 1029 } 1030 1031 if((w&0xC1F80000) == 0x81C00000){ /* JMPL */ 1032 sprint(buf, "R%d", (w>>14)&0xF); 1033 r1 = (*rget)(map, buf); 1034 if(w & 0x2000) /* JMPL R1+simm13 */ 1035 r2 = i.simm13; 1036 else{ /* JMPL R1+R2 */ 1037 sprint(buf, "R%d", w&0xF); 1038 r2 = (*rget)(map, buf); 1039 } 1040 foll[0] = r1 + r2; 1041 return 1; 1042 } 1043 foll[0] = pc+i.size*4; 1044 return 1; 1045 } 1046