1 /* $OpenBSD: db_disasm.c,v 1.21 2024/09/20 02:00:46 jsg Exp $ */ 2 3 /* 4 * Copyright (c) 2010 Miodrag Vallat. 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 /*- 19 * Copyright (c) 1991, 1993 20 * The Regents of the University of California. All rights reserved. 21 * 22 * This code is derived from software contributed to Berkeley by 23 * Ralph Campbell. 24 * 25 * Redistribution and use in source and binary forms, with or without 26 * modification, are permitted provided that the following conditions 27 * are met: 28 * 1. Redistributions of source code must retain the above copyright 29 * notice, this list of conditions and the following disclaimer. 30 * 2. Redistributions in binary form must reproduce the above copyright 31 * notice, this list of conditions and the following disclaimer in the 32 * documentation and/or other materials provided with the distribution. 33 * 3. All advertising materials mentioning features or use of this software 34 * must display the following acknowledgement: 35 * This product includes software developed by the University of 36 * California, Berkeley and its contributors. 37 * 4. Neither the name of the University nor the names of its contributors 38 * may be used to endorse or promote products derived from this software 39 * without specific prior written permission. 40 * 41 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51 * SUCH DAMAGE. 52 * 53 * from: @(#)kadb.c 8.1 (Berkeley) 6/10/93 54 * $Id: db_disasm.c,v 1.21 2024/09/20 02:00:46 jsg Exp $ 55 */ 56 57 #ifdef _KERNEL 58 #include <sys/param.h> 59 #include <sys/systm.h> 60 #else 61 #include <unistd.h> 62 #include <stdio.h> 63 #endif 64 65 #ifdef _KERNEL 66 #include <machine/db_machdep.h> 67 #endif 68 #include <machine/mips_opcode.h> 69 #include <machine/regnum.h> 70 71 #ifdef _KERNEL 72 #include <ddb/db_interface.h> 73 #include <ddb/db_output.h> 74 #include <ddb/db_sym.h> 75 #else 76 #define db_printsym(addr,flags,fn) (fn)("%p",addr) 77 #endif 78 79 static const char *op_name[64] = { 80 NULL, /* OP_SPECIAL */ 81 NULL, /* OP_BCOND */ 82 "j", 83 "jal", 84 "beq", 85 "bne", 86 "blez", 87 "bgtz", 88 89 "addi", 90 "addiu", 91 "slti", 92 "sltiu", 93 "andi", 94 "ori", 95 "xori", 96 "lui", 97 98 "cop0", 99 "cop1", 100 "cop2", 101 "cop1x", 102 "beql", 103 "bnel", 104 "blezl", 105 "bgtzl", 106 107 "daddi", 108 "daddiu", 109 "ldl", 110 "ldr", 111 NULL, 112 NULL, 113 NULL, 114 NULL, 115 116 "lb", 117 "lh", 118 "lwl", 119 "lw", 120 "lbu", 121 "lhu", 122 "lwr", 123 "lwu", 124 125 "sb", 126 "sh", 127 "swl", 128 "sw", 129 "sdl", 130 "sdr", 131 "swr", 132 "cache", 133 134 "ll", 135 "lwc1", 136 "lwc2", 137 "pref", 138 "lld", 139 "ldc1", 140 "ldc2", 141 "ld", 142 143 "sc", 144 "swc1", 145 "swc2", 146 "swc3", 147 "scd", 148 "sdc1", 149 "sdc2", 150 "sd" 151 }; 152 153 static const char *special_name[64] = { 154 "sll", 155 NULL, 156 "srl", 157 "sra", 158 "sllv", 159 NULL, 160 "srlv", 161 "srav", 162 163 "jr", 164 "jalr", 165 "movz", 166 "movn", 167 "syscall", 168 "break", 169 NULL, 170 "sync", 171 172 "mfhi", 173 "mthi", 174 "mflo", 175 "mtlo", 176 "dsllv", 177 NULL, 178 "dsrlv", 179 "dsrav", 180 181 "mult", 182 "multu", 183 "div", 184 "divu", 185 "dmult", 186 "dmultu", 187 "ddiv", 188 "ddivu", 189 190 "add", 191 "addu", 192 "sub", 193 "subu", 194 "and", 195 "or", 196 "xor", 197 "nor", 198 199 NULL, 200 NULL, 201 "slt", 202 "sltu", 203 "dadd", 204 "daddu", 205 "dsub", 206 "dsubu", 207 208 "tge", 209 "tgeu", 210 "tlt", 211 "tltu", 212 "teq", 213 NULL, 214 "tne", 215 NULL, 216 217 "dsll", 218 NULL, 219 "dsrl", 220 "dsra", 221 "dsll32", 222 NULL, 223 "dsrl32", 224 "dsra32" 225 }; 226 227 static const char *bcond_name[32] = { 228 "bltz", 229 "bgez", 230 "bltzl", 231 "bgezl", 232 NULL, 233 NULL, 234 NULL, 235 NULL, 236 237 "tgei", 238 "tgeiu", 239 "tlti", 240 "tltiu", 241 "teqi", 242 NULL, 243 "tnei", 244 NULL, 245 246 "bltzal", 247 "bgezal", 248 "bltzall", 249 "bgezall", 250 NULL, 251 NULL, 252 NULL, 253 NULL, 254 255 NULL, 256 NULL, 257 NULL, 258 NULL, 259 NULL, 260 NULL, 261 NULL, 262 "synci" 263 }; 264 265 static const char *cop_std[OP_MTH + 1] = { 266 "mfc", 267 "dmfc", 268 "cfc", 269 "mfhc", 270 "mtc", 271 "dmtc", 272 "ctc", 273 "mthc" 274 }; 275 276 static const char *cop1_name[64] = { 277 "add", 278 "sub", 279 "mul", 280 "div", 281 "sqrt", 282 "abs", 283 "mov", 284 "neg", 285 286 "round.l", 287 "trunc.l", 288 "ceil.l", 289 "floor.l", 290 "round.w", 291 "trunc.w", 292 "ceil.w", 293 "floor.w", 294 295 NULL, 296 NULL, /* movf/movt */ 297 "movz", 298 "movn", 299 NULL, 300 "recip", 301 "rsqrt", 302 NULL, 303 304 NULL, 305 NULL, 306 NULL, 307 NULL, 308 NULL, 309 NULL, 310 NULL, 311 NULL, 312 313 "cvt.s", 314 "cvt.d", 315 NULL, 316 NULL, 317 "cvt.w", 318 "cvt.l", 319 NULL, 320 NULL, 321 322 NULL, 323 NULL, 324 NULL, 325 NULL, 326 NULL, 327 NULL, 328 NULL, 329 NULL, 330 331 "c.f", 332 "c.un", 333 "c.eq", 334 "c.ueq", 335 "c.olt", 336 "c.ult", 337 "c.ole", 338 "c.ule", 339 340 "c.sf", 341 "c.ngle", 342 "c.seq", 343 "c.ngl", 344 "c.lt", 345 "c.nge", 346 "c.le", 347 "c.ngt" 348 }; 349 350 static const char *fmt_name[16] = { 351 "s", 352 "d", 353 NULL, 354 NULL, 355 "w", 356 "l", 357 NULL, 358 NULL, 359 NULL, 360 NULL, 361 NULL, 362 NULL, 363 NULL, 364 NULL, 365 NULL, 366 NULL 367 }; 368 369 static const char *cop1x_op4[8] = { 370 NULL, 371 NULL, 372 NULL, 373 NULL, 374 "madd", 375 "msub", 376 "nmadd", 377 "nmsub" 378 }; 379 380 static const char *cop1x_std[32] = { 381 "lwxc1", 382 "ldxc1", 383 NULL, 384 NULL, 385 NULL, 386 NULL, 387 NULL, 388 NULL, 389 390 "swxc1", 391 "sdxc1", 392 NULL, 393 NULL, 394 NULL, 395 NULL, 396 NULL, 397 "prefx", 398 399 NULL, 400 NULL, 401 NULL, 402 NULL, 403 NULL, 404 NULL, 405 NULL, 406 NULL, 407 408 NULL, 409 NULL, 410 NULL, 411 NULL, 412 NULL, 413 NULL, 414 NULL, 415 NULL 416 }; 417 418 static const char *reg_name[32] = { 419 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", 420 "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3", 421 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", 422 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra" 423 }; 424 425 static const char *cop0_miscname[64] = { 426 NULL, 427 "tlbr", 428 "tlbwi", 429 NULL, 430 NULL, 431 NULL, 432 "tlbwr", 433 NULL, 434 435 "tlbp", 436 NULL, 437 NULL, 438 NULL, 439 NULL, 440 NULL, 441 NULL, 442 NULL, 443 444 NULL, /* rfe */ 445 NULL, 446 NULL, 447 NULL, 448 NULL, 449 NULL, 450 NULL, 451 NULL, 452 453 "eret", 454 NULL, 455 NULL, 456 NULL, 457 NULL, 458 NULL, 459 NULL, 460 NULL, 461 462 "wait" /* RM5200 */ 463 }; 464 465 static const char *cop0_tfp_miscname[64] = { 466 NULL, 467 "tlbr", 468 "tlbw", 469 NULL, 470 NULL, 471 NULL, 472 "tlbwr", 473 NULL, 474 475 "tlbp", 476 "dctr", 477 "dctw" 478 }; 479 480 static const char *cop0_reg0[32] = { 481 "Index", 482 "Random", 483 "EntryLo0", 484 "EntryLo1", 485 "Context", 486 "PageMask", 487 "Wired", 488 "Info", /* RM7000 */ 489 490 "BadVAddr", 491 "Count", 492 "EntryHi", 493 "Compare", 494 "Status", 495 "Cause", 496 "EPC", 497 "PRId", 498 499 "Config", 500 "LLAddr", 501 "WatchLo", /* RM7000 Watch1 */ 502 "WatchHi", /* RM7000 Watch2 */ 503 "XContext", 504 NULL, 505 "PerfControl", /* RM7000 */ 506 NULL, 507 508 "WatchMask", /* RM7000 */ 509 "PerfCount", /* RM7000 */ 510 "ECC", 511 "CacheErr", 512 "TagLo", 513 "TagHi", 514 "ErrorEPC", 515 NULL 516 }; 517 518 static const char *cop0_reg1[32] = { 519 NULL, 520 NULL, 521 NULL, 522 NULL, 523 NULL, 524 NULL, 525 NULL, 526 NULL, 527 528 NULL, 529 NULL, 530 NULL, 531 NULL, 532 NULL, 533 NULL, 534 NULL, 535 NULL, 536 537 NULL, 538 NULL, 539 "IPLLo", 540 "IPLHi", 541 "IntCtl", 542 NULL, 543 NULL, 544 NULL, 545 546 NULL, 547 NULL, 548 "DErrAddr0", 549 "DErrAddr1", 550 NULL, 551 NULL, 552 NULL, 553 NULL, 554 }; 555 556 int 557 dbmd_print_insn(uint32_t ins, vaddr_t mdbdot, int (*pr)(const char *, ...)) 558 { 559 InstFmt i; 560 int delay = 0; 561 const char *insn, *descr; 562 563 i.word = ins; 564 insn = op_name[i.JType.op]; 565 566 switch (i.JType.op) { 567 case OP_SPECIAL: 568 /* recognize nop/ssnop variants of sll early */ 569 if (i.word == 0) { 570 (*pr)("nop"); 571 break; 572 } else if (i.word == 1 << 6) { 573 (*pr)("ssnop"); 574 break; 575 } 576 577 /* display `daddu' involving zero as `move' */ 578 if (i.RType.func == OP_DADDU && i.RType.rt == 0) { 579 (*pr)("move\t%s,%s", 580 reg_name[i.RType.rd], reg_name[i.RType.rs]); 581 break; 582 } 583 584 if (i.RType.func == OP_MOVCI) { 585 (*pr)("mov%c\t%s,%s,%d", 586 i.RType.rt & 1 ? 't' : 'f', 587 reg_name[i.RType.rd], reg_name[i.RType.rs], 588 i.RType.rt >> 2); 589 break; 590 } 591 592 /* fix ambiguous opcode memonics */ 593 insn = special_name[i.RType.func]; 594 switch (i.RType.func) { 595 case OP_SRL: 596 if (i.RType.rs != 0) 597 insn = "rotr"; 598 break; 599 case OP_SRLV: 600 if (i.RType.shamt != 0) 601 insn = "rotrv"; 602 break; 603 case OP_JR: 604 if (i.RType.shamt != 0) 605 insn = "jr.hb"; 606 break; 607 case OP_JALR: 608 if (i.RType.shamt != 0) 609 insn = "jalr.hb"; 610 break; 611 case OP_DSRL: 612 if (i.RType.rs != 0) 613 insn = "drotr"; 614 break; 615 case OP_DSRLV: 616 if (i.RType.shamt != 0) 617 insn = "drotrv"; 618 break; 619 } 620 621 if (insn == NULL) 622 goto unknown; 623 (*pr)("%s", insn); 624 625 switch (i.RType.func) { 626 case OP_SLL: 627 case OP_SRL: 628 case OP_SRA: 629 case OP_DSLL: 630 case OP_DSRL: 631 case OP_DSRA: 632 case OP_DSLL32: 633 case OP_DSRL32: 634 case OP_DSRA32: 635 (*pr)("\t%s,%s,%d", 636 reg_name[i.RType.rd], reg_name[i.RType.rt], 637 i.RType.shamt); 638 break; 639 case OP_SLLV: 640 case OP_SRLV: 641 case OP_SRAV: 642 case OP_DSLLV: 643 case OP_DSRLV: 644 case OP_DSRAV: 645 (*pr)("\t%s,%s,%s", 646 reg_name[i.RType.rd], reg_name[i.RType.rt], 647 reg_name[i.RType.rs]); 648 break; 649 case OP_MFHI: 650 case OP_MFLO: 651 (*pr)("\t%s", reg_name[i.RType.rd]); 652 break; 653 case OP_JALR: 654 delay = 1; 655 if (i.RType.rd != RA) 656 (*pr)("\t%s,%s", 657 reg_name[i.RType.rd], reg_name[i.RType.rs]); 658 else 659 (*pr)("\t%s", reg_name[i.RType.rs]); 660 break; 661 case OP_JR: 662 delay = 1; 663 /* FALLTHROUGH */ 664 case OP_MTLO: 665 case OP_MTHI: 666 (*pr)("\t%s", reg_name[i.RType.rs]); 667 break; 668 case OP_MULT: 669 case OP_MULTU: 670 case OP_DIV: 671 case OP_DIVU: 672 case OP_DMULT: 673 case OP_DMULTU: 674 case OP_DDIV: 675 case OP_DDIVU: 676 case OP_TGE: 677 case OP_TGEU: 678 case OP_TLT: 679 case OP_TLTU: 680 case OP_TEQ: 681 case OP_TNE: 682 (*pr)("\t%s,%s", 683 reg_name[i.RType.rs], reg_name[i.RType.rt]); 684 break; 685 case OP_SYSCALL: 686 if ((ins >> 6) != 0) 687 (*pr)("\t%d", ins >> 6); 688 break; 689 case OP_SYNC: 690 break; 691 case OP_BREAK: 692 (*pr)("\t%d", ins >> 16); 693 break; 694 case OP_MOVZ: 695 case OP_MOVN: 696 default: 697 (*pr)("\t%s,%s,%s", 698 reg_name[i.RType.rd], reg_name[i.RType.rs], 699 reg_name[i.RType.rt]); 700 } 701 break; 702 703 case OP_BCOND: 704 insn = bcond_name[i.IType.rt]; 705 if (insn == NULL) 706 goto unknown; 707 if (i.IType.rt == 31) { /* synci */ 708 (*pr)("%s\t", insn); 709 goto loadstore; 710 } 711 (*pr)("%s\t%s,", insn, reg_name[i.IType.rs]); 712 if ((i.IType.rt & 0x18) == 0x08) /* trap, not branch */ 713 (*pr)("%d", i.IType.imm); 714 else 715 goto pr_displ; 716 717 case OP_J: 718 case OP_JAL: 719 delay = 1; 720 (*pr)("%s\t", insn); 721 db_printsym((mdbdot & ~0x0fffffffUL) | 722 (vaddr_t)(i.JType.target << 2), DB_STGY_PROC, pr); 723 break; 724 725 case OP_BEQ: 726 case OP_BEQL: 727 if (i.IType.rs == ZERO && i.IType.rt == ZERO) { 728 (*pr)("b\t"); 729 goto pr_displ; 730 } 731 /* FALLTHROUGH */ 732 case OP_BNE: 733 case OP_BNEL: 734 if (i.IType.rt == ZERO) { 735 if (i.IType.op == OP_BEQL || i.IType.op == OP_BNEL) { 736 /* get the non-l opcode name */ 737 insn = op_name[i.IType.op & 0x07]; 738 (*pr)("%szl\t%s,", insn, reg_name[i.IType.rs]); 739 } else 740 (*pr)("%sz\t%s,", insn, reg_name[i.IType.rs]); 741 } else 742 (*pr)("%s\t%s,%s,", insn, 743 reg_name[i.IType.rs], reg_name[i.IType.rt]); 744 pr_displ: 745 delay = 1; 746 db_printsym(mdbdot + 4 + ((int16_t)i.IType.imm << 2), 747 DB_STGY_PROC, pr); 748 break; 749 750 case OP_BLEZ: 751 case OP_BGTZ: 752 case OP_BLEZL: 753 case OP_BGTZL: 754 (*pr)("%s\t%s,", insn, reg_name[i.IType.rs]); 755 goto pr_displ; 756 757 case OP_ADDI: 758 case OP_ADDIU: 759 case OP_DADDI: 760 case OP_DADDIU: 761 if (i.IType.rs == 0) { 762 (*pr)("li\t%s,%d", 763 reg_name[i.IType.rt], (int16_t)i.IType.imm); 764 break; 765 } 766 /* FALLTHROUGH */ 767 case OP_SLTI: 768 case OP_SLTIU: 769 default: 770 if (insn != NULL) 771 (*pr)("%s\t%s,%s,%d", insn, 772 reg_name[i.IType.rt], reg_name[i.IType.rs], 773 (int16_t)i.IType.imm); 774 else { 775 unknown: 776 (*pr)(".word\t%08x", ins); 777 } 778 break; 779 780 case OP_ORI: 781 case OP_XORI: 782 if (i.IType.rs == 0) { 783 (*pr)("li\t%s,0x%x", reg_name[i.IType.rt], i.IType.imm); 784 break; 785 } 786 /* FALLTHROUGH */ 787 case OP_ANDI: 788 (*pr)("%s\t%s,%s,0x%x", insn, 789 reg_name[i.IType.rt], reg_name[i.IType.rs], i.IType.imm); 790 break; 791 792 case OP_LUI: 793 (*pr)("%s\t%s,0x%x", insn, reg_name[i.IType.rt], i.IType.imm); 794 break; 795 796 case OP_COP0: 797 switch (i.RType.rs) { 798 case OP_MF: 799 case OP_DMF: 800 case OP_MT: 801 case OP_DMT: 802 if ((i.RType.func & 0x07) != 0) { 803 insn = cop_std[i.RType.rs]; 804 descr = cop0_reg0[i.RType.rd]; 805 if (descr != NULL) 806 (*pr)("%s0\t%s,%d,%d # %s.%d", insn, 807 reg_name[i.RType.rt], i.RType.rd, 808 i.RType.func & 0x07, descr, 809 i.RType.func & 0x07); 810 else 811 (*pr)("%s0\t%s,%d,%d", insn, 812 reg_name[i.RType.rt], i.RType.rd, 813 i.RType.func & 0x07); 814 break; 815 } 816 /* FALLTHROUGH */ 817 case OP_CF: 818 case OP_CT: 819 insn = cop_std[i.RType.rs]; 820 if (i.RType.rs == OP_CF || i.RType.rs == OP_CT) 821 descr = cop0_reg1[i.RType.rd]; 822 else 823 descr = cop0_reg0[i.RType.rd]; 824 if (descr != NULL) 825 (*pr)("%s0\t%s,%d # %s", insn, 826 reg_name[i.RType.rt], i.RType.rd, descr); 827 else 828 (*pr)("%s0\t%s,%d", insn, 829 reg_name[i.RType.rt], i.RType.rd); 830 break; 831 case OP_BC: 832 (*pr)("bc0%c%c\t", 833 i.RType.rt & COPz_BC_TF_MASK ? 't' : 'f', 834 i.RType.rt & COPz_BCL_TF_MASK ? 'l' : ' '); 835 goto pr_displ; 836 case OP_C0MISC: 837 if (i.FRType.func < nitems(cop0_miscname)) 838 insn = cop0_miscname[i.FRType.func]; 839 else 840 insn = NULL; 841 if (insn == NULL) 842 goto unknown; 843 else 844 (*pr)("%s", insn); 845 break; 846 case OP_TFP_C0MISC: 847 if (i.FRType.func < nitems(cop0_tfp_miscname)) 848 insn = cop0_tfp_miscname[i.FRType.func]; 849 else 850 insn = NULL; 851 if (insn == NULL) 852 goto unknown; 853 else 854 (*pr)("%s", insn); 855 break; 856 default: 857 goto unknown; 858 } 859 break; 860 861 case OP_COP1: 862 switch (i.RType.rs) { 863 case OP_MF: 864 case OP_DMF: 865 case OP_CF: 866 case OP_MFH: 867 case OP_MT: 868 case OP_DMT: 869 case OP_CT: 870 case OP_MTH: 871 insn = cop_std[i.RType.rs]; 872 (*pr)("%s1\t%s,f%d", insn, 873 reg_name[i.RType.rt], i.RType.rd); 874 break; 875 case OP_BC: 876 (*pr)("bc1%c%c\t", 877 i.RType.rt & COPz_BC_TF_MASK ? 't' : 'f', 878 i.RType.rt & COPz_BCL_TF_MASK ? 'l' : ' '); 879 goto pr_displ; 880 default: 881 if (fmt_name[i.FRType.fmt] == NULL) 882 goto unknown; 883 if (i.FRType.func == 0x11) { /* movcf */ 884 insn = i.FRType.ft & 1 ? "movt" : "movf"; 885 (*pr)("%s.%s\tf%d,f%d,%d", 886 insn, fmt_name[i.FRType.fmt], 887 i.FRType.fd, i.FRType.fs, i.FRType.ft >> 2); 888 break; 889 } 890 insn = cop1_name[i.FRType.func]; 891 if (insn == NULL) 892 goto unknown; 893 (*pr)("%s.%s\tf%d,f%d,f%d", 894 insn, fmt_name[i.FRType.fmt], 895 i.FRType.fd, i.FRType.fs, i.FRType.ft); 896 } 897 break; 898 899 case OP_COP2: 900 switch (i.RType.rs) { 901 case OP_MF: 902 case OP_DMF: 903 case OP_CF: 904 case OP_MFH: 905 case OP_MT: 906 case OP_DMT: 907 case OP_CT: 908 case OP_MTH: 909 insn = cop_std[i.RType.rs]; 910 (*pr)("%s2\t%s,f%d", insn, 911 reg_name[i.RType.rt], i.RType.rd); 912 break; 913 case OP_BC: 914 (*pr)("bc2%c%c\t", 915 i.RType.rt & COPz_BC_TF_MASK ? 't' : 'f', 916 i.RType.rt & COPz_BCL_TF_MASK ? 'l' : ' '); 917 goto pr_displ; 918 default: 919 goto unknown; 920 } 921 break; 922 923 case OP_COP1X: 924 switch (i.FQType.op4) { 925 case OP_MADD: 926 case OP_MSUB: 927 case OP_NMADD: 928 case OP_NMSUB: 929 if (fmt_name[i.FQType.fmt3] == NULL) 930 goto unknown; 931 insn = cop1x_op4[i.FQType.op4]; 932 (*pr)("%s.%s\tf%d,f%d,f%d,f%d", 933 insn, fmt_name[i.FQType.fmt3], 934 i.FQType.fd, i.FQType.fr, 935 i.FQType.fs, i.FQType.ft); 936 break; 937 default: 938 insn = cop1x_std[i.FRType.func]; 939 switch (i.FRType.func) { 940 case OP_LWXC1: 941 case OP_LDXC1: 942 (*pr)("%s\tf%d,%s(%s)", insn, 943 i.FQType.fd, reg_name[i.FQType.ft], 944 reg_name[i.FQType.fr]); 945 break; 946 case OP_SWXC1: 947 case OP_SDXC1: 948 (*pr)("%s\tf%d,%s(%s)", insn, 949 i.FQType.fs, reg_name[i.FQType.ft], 950 reg_name[i.FQType.fr]); 951 break; 952 case OP_PREFX: 953 (*pr)("%s\t%d,%s(%s)", insn, 954 i.FQType.fs, reg_name[i.FQType.ft], 955 reg_name[i.FQType.fr]); 956 break; 957 } 958 break; 959 } 960 break; 961 962 case OP_LDL: 963 case OP_LDR: 964 case OP_LB: 965 case OP_LH: 966 case OP_LWL: 967 case OP_LW: 968 case OP_LBU: 969 case OP_LHU: 970 case OP_LWR: 971 case OP_LWU: 972 case OP_SB: 973 case OP_SH: 974 case OP_SWL: 975 case OP_SW: 976 case OP_SDL: 977 case OP_SDR: 978 case OP_SWR: 979 case OP_LL: 980 case OP_LLD: 981 case OP_LD: 982 case OP_SC: 983 case OP_SCD: 984 case OP_SD: 985 (*pr)("%s\t%s,", insn, reg_name[i.IType.rt]); 986 loadstore: 987 (*pr)("%d(%s)", (int16_t)i.IType.imm, reg_name[i.IType.rs]); 988 break; 989 990 case OP_CACHE: 991 (*pr)("%s\t0x%x,", insn, i.IType.rt); 992 goto loadstore; 993 break; 994 995 case OP_LWC1: 996 case OP_LWC2: 997 /* case OP_LWC3: superseded with OP_PREF */ 998 case OP_LDC1: 999 case OP_LDC2: 1000 case OP_SWC1: 1001 case OP_SWC2: 1002 case OP_SWC3: 1003 case OP_SDC1: 1004 case OP_SDC2: 1005 (*pr)("%s\tf%d,", insn, i.IType.rt); 1006 goto loadstore; 1007 1008 case OP_PREF: 1009 (*pr)("%s\t%d,", insn, i.IType.rt); 1010 goto loadstore; 1011 } 1012 (*pr)("\n"); 1013 return delay; 1014 } 1015 1016 #ifdef _KERNEL 1017 vaddr_t 1018 db_disasm(vaddr_t loc, int altfmt) 1019 { 1020 extern uint32_t kdbpeek(vaddr_t); 1021 1022 if (dbmd_print_insn(kdbpeek(loc), loc, db_printf)) { 1023 loc += 4; 1024 db_printsym(loc, DB_STGY_ANY, db_printf); 1025 db_printf(":\t "); 1026 dbmd_print_insn(kdbpeek(loc), loc, db_printf); 1027 } 1028 loc += 4; 1029 return loc; 1030 } 1031 #else 1032 /* 1033 * Simple userspace test program (to confirm the logic never tries to print 1034 * NULL, to begin with...) 1035 */ 1036 int 1037 main() 1038 { 1039 uint32_t insn = 0; 1040 1041 do { 1042 printf("%08x\t", insn); 1043 dbmd_print_insn(insn, 0, printf); 1044 insn++; 1045 if ((insn & 0x00ffffff) == 0) 1046 fprintf(stderr, "%08x\n", insn); 1047 } while (insn != 0); 1048 1049 return 0; 1050 } 1051 #endif 1052