12159047fSniklas /* Print mips instructions for GDB, the GNU debugger, or for objdump. 22159047fSniklas Copyright 1989, 1991, 1992 Free Software Foundation, Inc. 32159047fSniklas Contributed by Nobuyuki Hikichi(hikichi@sra.co.jp). 42159047fSniklas 52159047fSniklas This file is part of GDB. 62159047fSniklas 72159047fSniklas This program is free software; you can redistribute it and/or modify 82159047fSniklas it under the terms of the GNU General Public License as published by 92159047fSniklas the Free Software Foundation; either version 2 of the License, or 102159047fSniklas (at your option) any later version. 112159047fSniklas 122159047fSniklas This program is distributed in the hope that it will be useful, 132159047fSniklas but WITHOUT ANY WARRANTY; without even the implied warranty of 142159047fSniklas MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 152159047fSniklas GNU General Public License for more details. 162159047fSniklas 172159047fSniklas You should have received a copy of the GNU General Public License 182159047fSniklas along with this program; if not, write to the Free Software 192159047fSniklas Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 202159047fSniklas 212159047fSniklas #include <ansidecl.h> 222159047fSniklas #include "sysdep.h" 232159047fSniklas #include "dis-asm.h" 242159047fSniklas #include "opcode/mips.h" 252159047fSniklas 262159047fSniklas /* Mips instructions are never longer than this many bytes. */ 272159047fSniklas #define MAXLEN 4 282159047fSniklas 292159047fSniklas /* FIXME: This should be shared with gdb somehow. */ 302159047fSniklas #define REGISTER_NAMES \ 312159047fSniklas { "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", \ 322159047fSniklas "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", \ 332159047fSniklas "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", \ 342159047fSniklas "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", \ 352159047fSniklas "sr", "lo", "hi", "bad", "cause","pc", \ 362159047fSniklas "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \ 372159047fSniklas "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \ 382159047fSniklas "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",\ 392159047fSniklas "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",\ 402159047fSniklas "fsr", "fir", "fp", "inx", "rand", "tlblo","ctxt", "tlbhi",\ 412159047fSniklas "epc", "prid"\ 422159047fSniklas } 432159047fSniklas 442159047fSniklas static CONST char * CONST reg_names[] = REGISTER_NAMES; 452159047fSniklas 462159047fSniklas /* subroutine */ 472159047fSniklas static void 482159047fSniklas print_insn_arg (d, l, pc, info) 492159047fSniklas const char *d; 502159047fSniklas register unsigned long int l; 512159047fSniklas bfd_vma pc; 522159047fSniklas struct disassemble_info *info; 532159047fSniklas { 542159047fSniklas int delta; 552159047fSniklas 562159047fSniklas switch (*d) 572159047fSniklas { 582159047fSniklas case ',': 592159047fSniklas case '(': 602159047fSniklas case ')': 612159047fSniklas (*info->fprintf_func) (info->stream, "%c", *d); 622159047fSniklas break; 632159047fSniklas 642159047fSniklas case 's': 652159047fSniklas case 'b': 662159047fSniklas case 'r': 672159047fSniklas case 'v': 682159047fSniklas (*info->fprintf_func) (info->stream, "$%s", 692159047fSniklas reg_names[(l >> OP_SH_RS) & OP_MASK_RS]); 702159047fSniklas break; 712159047fSniklas 722159047fSniklas case 't': 732159047fSniklas case 'w': 742159047fSniklas (*info->fprintf_func) (info->stream, "$%s", 752159047fSniklas reg_names[(l >> OP_SH_RT) & OP_MASK_RT]); 762159047fSniklas break; 772159047fSniklas 782159047fSniklas case 'i': 792159047fSniklas case 'u': 80*c88b1d6cSniklas (*info->fprintf_func) (info->stream, "0x%x", 812159047fSniklas (l >> OP_SH_IMMEDIATE) & OP_MASK_IMMEDIATE); 822159047fSniklas break; 832159047fSniklas 842159047fSniklas case 'j': /* same as i, but sign-extended */ 852159047fSniklas case 'o': 862159047fSniklas delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA; 872159047fSniklas if (delta & 0x8000) 882159047fSniklas delta |= ~0xffff; 892159047fSniklas (*info->fprintf_func) (info->stream, "%d", 902159047fSniklas delta); 912159047fSniklas break; 922159047fSniklas 932159047fSniklas case 'h': 942159047fSniklas (*info->fprintf_func) (info->stream, "0x%x", 952159047fSniklas (unsigned int) ((l >> OP_SH_PREFX) 962159047fSniklas & OP_MASK_PREFX)); 972159047fSniklas break; 982159047fSniklas 992159047fSniklas case 'k': 1002159047fSniklas (*info->fprintf_func) (info->stream, "0x%x", 1012159047fSniklas (unsigned int) ((l >> OP_SH_CACHE) 1022159047fSniklas & OP_MASK_CACHE)); 1032159047fSniklas break; 1042159047fSniklas 1052159047fSniklas case 'a': 1062159047fSniklas (*info->print_address_func) 1072159047fSniklas (((pc & 0xF0000000) | (((l >> OP_SH_TARGET) & OP_MASK_TARGET) << 2)), 1082159047fSniklas info); 1092159047fSniklas break; 1102159047fSniklas 1112159047fSniklas case 'p': 1122159047fSniklas /* sign extend the displacement */ 1132159047fSniklas delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA; 1142159047fSniklas if (delta & 0x8000) 1152159047fSniklas delta |= ~0xffff; 1162159047fSniklas (*info->print_address_func) 1172159047fSniklas ((delta << 2) + pc + 4, 1182159047fSniklas info); 1192159047fSniklas break; 1202159047fSniklas 1212159047fSniklas case 'd': 1222159047fSniklas (*info->fprintf_func) (info->stream, "$%s", 1232159047fSniklas reg_names[(l >> OP_SH_RD) & OP_MASK_RD]); 1242159047fSniklas break; 1252159047fSniklas 1262159047fSniklas case 'z': 1272159047fSniklas (*info->fprintf_func) (info->stream, "$%s", reg_names[0]); 1282159047fSniklas break; 1292159047fSniklas 1302159047fSniklas case '<': 1312159047fSniklas (*info->fprintf_func) (info->stream, "0x%x", 1322159047fSniklas (l >> OP_SH_SHAMT) & OP_MASK_SHAMT); 1332159047fSniklas break; 1342159047fSniklas 1352159047fSniklas case 'c': 1362159047fSniklas (*info->fprintf_func) (info->stream, "0x%x", 1372159047fSniklas (l >> OP_SH_CODE) & OP_MASK_CODE); 1382159047fSniklas break; 1392159047fSniklas 1402159047fSniklas case 'C': 1412159047fSniklas (*info->fprintf_func) (info->stream, "0x%x", 1422159047fSniklas (l >> OP_SH_COPZ) & OP_MASK_COPZ); 1432159047fSniklas break; 1442159047fSniklas 1452159047fSniklas case 'B': 1462159047fSniklas (*info->fprintf_func) (info->stream, "0x%x", 1472159047fSniklas (l >> OP_SH_SYSCALL) & OP_MASK_SYSCALL); 1482159047fSniklas break; 1492159047fSniklas 1502159047fSniklas case 'S': 1512159047fSniklas case 'V': 1522159047fSniklas (*info->fprintf_func) (info->stream, "$f%d", 1532159047fSniklas (l >> OP_SH_FS) & OP_MASK_FS); 1542159047fSniklas break; 1552159047fSniklas 1562159047fSniklas case 'T': 1572159047fSniklas case 'W': 1582159047fSniklas (*info->fprintf_func) (info->stream, "$f%d", 1592159047fSniklas (l >> OP_SH_FT) & OP_MASK_FT); 1602159047fSniklas break; 1612159047fSniklas 1622159047fSniklas case 'D': 1632159047fSniklas (*info->fprintf_func) (info->stream, "$f%d", 1642159047fSniklas (l >> OP_SH_FD) & OP_MASK_FD); 1652159047fSniklas break; 1662159047fSniklas 1672159047fSniklas case 'R': 1682159047fSniklas (*info->fprintf_func) (info->stream, "$f%d", 1692159047fSniklas (l >> OP_SH_FR) & OP_MASK_FR); 1702159047fSniklas break; 1712159047fSniklas 1722159047fSniklas case 'E': 1732159047fSniklas (*info->fprintf_func) (info->stream, "$%d", 1742159047fSniklas (l >> OP_SH_RT) & OP_MASK_RT); 1752159047fSniklas break; 1762159047fSniklas 1772159047fSniklas case 'G': 1782159047fSniklas (*info->fprintf_func) (info->stream, "$%d", 1792159047fSniklas (l >> OP_SH_RD) & OP_MASK_RD); 1802159047fSniklas break; 1812159047fSniklas 1822159047fSniklas case 'N': 1832159047fSniklas (*info->fprintf_func) (info->stream, "%d", 1842159047fSniklas (l >> OP_SH_BCC) & OP_MASK_BCC); 1852159047fSniklas break; 1862159047fSniklas 1872159047fSniklas case 'M': 1882159047fSniklas (*info->fprintf_func) (info->stream, "%d", 1892159047fSniklas (l >> OP_SH_CCC) & OP_MASK_CCC); 1902159047fSniklas break; 1912159047fSniklas 1922159047fSniklas default: 1932159047fSniklas (*info->fprintf_func) (info->stream, 1942159047fSniklas "# internal error, undefined modifier(%c)", *d); 1952159047fSniklas break; 1962159047fSniklas } 1972159047fSniklas } 1982159047fSniklas 1992159047fSniklas /* Print the mips instruction at address MEMADDR in debugged memory, 2002159047fSniklas on using INFO. Returns length of the instruction, in bytes, which is 2012159047fSniklas always 4. BIGENDIAN must be 1 if this is big-endian code, 0 if 2022159047fSniklas this is little-endian code. */ 2032159047fSniklas 2042159047fSniklas static int 2052159047fSniklas _print_insn_mips (memaddr, word, info) 2062159047fSniklas bfd_vma memaddr; 2072159047fSniklas struct disassemble_info *info; 2082159047fSniklas unsigned long int word; 2092159047fSniklas { 2102159047fSniklas register const struct mips_opcode *op; 2112159047fSniklas static boolean init = 0; 2122159047fSniklas static const struct mips_opcode *mips_hash[OP_MASK_OP + 1]; 2132159047fSniklas 2142159047fSniklas /* Build a hash table to shorten the search time. */ 2152159047fSniklas if (! init) 2162159047fSniklas { 217*c88b1d6cSniklas unsigned int i; 2182159047fSniklas 2192159047fSniklas for (i = 0; i <= OP_MASK_OP; i++) 2202159047fSniklas { 2212159047fSniklas for (op = mips_opcodes; op < &mips_opcodes[NUMOPCODES]; op++) 2222159047fSniklas { 2232159047fSniklas if (op->pinfo == INSN_MACRO) 2242159047fSniklas continue; 2252159047fSniklas if (i == ((op->match >> OP_SH_OP) & OP_MASK_OP)) 2262159047fSniklas { 2272159047fSniklas mips_hash[i] = op; 2282159047fSniklas break; 2292159047fSniklas } 2302159047fSniklas } 2312159047fSniklas } 2322159047fSniklas 2332159047fSniklas init = 1; 2342159047fSniklas } 2352159047fSniklas 2362159047fSniklas op = mips_hash[(word >> OP_SH_OP) & OP_MASK_OP]; 2372159047fSniklas if (op != NULL) 2382159047fSniklas { 2392159047fSniklas for (; op < &mips_opcodes[NUMOPCODES]; op++) 2402159047fSniklas { 2412159047fSniklas if (op->pinfo != INSN_MACRO && (word & op->mask) == op->match) 2422159047fSniklas { 2432159047fSniklas register const char *d; 2442159047fSniklas 2452159047fSniklas (*info->fprintf_func) (info->stream, "%s", op->name); 2462159047fSniklas 2472159047fSniklas d = op->args; 2482159047fSniklas if (d != NULL) 2492159047fSniklas { 2502159047fSniklas (*info->fprintf_func) (info->stream, " "); 2512159047fSniklas for (; *d != '\0'; d++) 2522159047fSniklas print_insn_arg (d, word, memaddr, info); 2532159047fSniklas } 2542159047fSniklas 2552159047fSniklas return 4; 2562159047fSniklas } 2572159047fSniklas } 2582159047fSniklas } 2592159047fSniklas 2602159047fSniklas /* Handle undefined instructions. */ 2612159047fSniklas (*info->fprintf_func) (info->stream, "0x%x", word); 2622159047fSniklas return 4; 2632159047fSniklas } 2642159047fSniklas 2652159047fSniklas int 2662159047fSniklas print_insn_big_mips (memaddr, info) 2672159047fSniklas bfd_vma memaddr; 2682159047fSniklas struct disassemble_info *info; 2692159047fSniklas { 2702159047fSniklas bfd_byte buffer[4]; 2712159047fSniklas int status = (*info->read_memory_func) (memaddr, buffer, 4, info); 2722159047fSniklas if (status == 0) 2732159047fSniklas return _print_insn_mips (memaddr, (unsigned long) bfd_getb32 (buffer), info); 2742159047fSniklas else 2752159047fSniklas { 2762159047fSniklas (*info->memory_error_func) (status, memaddr, info); 2772159047fSniklas return -1; 2782159047fSniklas } 2792159047fSniklas } 2802159047fSniklas 2812159047fSniklas int 2822159047fSniklas print_insn_little_mips (memaddr, info) 2832159047fSniklas bfd_vma memaddr; 2842159047fSniklas struct disassemble_info *info; 2852159047fSniklas { 2862159047fSniklas bfd_byte buffer[4]; 2872159047fSniklas int status = (*info->read_memory_func) (memaddr, buffer, 4, info); 2882159047fSniklas if (status == 0) 2892159047fSniklas return _print_insn_mips (memaddr, (unsigned long) bfd_getl32 (buffer), info); 2902159047fSniklas else 2912159047fSniklas { 2922159047fSniklas (*info->memory_error_func) (status, memaddr, info); 2932159047fSniklas return -1; 2942159047fSniklas } 2952159047fSniklas } 296