home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / gnu / gdb-4.12.tar.gz / gdb-4.12.tar / gdb-4.12 / opcodes / mips-dis.c < prev    next >
C/C++ Source or Header  |  1994-02-03  |  7KB  |  254 lines

  1. /* Print mips instructions for GDB, the GNU debugger, or for objdump.
  2.    Copyright 1989, 1991, 1992 Free Software Foundation, Inc.
  3.    Contributed by Nobuyuki Hikichi(hikichi@sra.co.jp).
  4.  
  5. This file is part of GDB.
  6.  
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or
  10. (at your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.  
  21. #include <ansidecl.h>
  22. #include "sysdep.h"
  23. #include "dis-asm.h"
  24. #include "opcode/mips.h"
  25.  
  26. /* Mips instructions are never longer than this many bytes.  */
  27. #define MAXLEN 4
  28.  
  29. /* FIXME: This should be shared with gdb somehow.  */
  30. #define REGISTER_NAMES     \
  31.     {    "zero",    "at",    "v0",    "v1",    "a0",    "a1",    "a2",    "a3", \
  32.     "t0",    "t1",    "t2",    "t3",    "t4",    "t5",    "t6",    "t7", \
  33.     "s0",    "s1",    "s2",    "s3",    "s4",    "s5",    "s6",    "s7", \
  34.     "t8",    "t9",    "k0",    "k1",    "gp",    "sp",    "s8",    "ra", \
  35.     "sr",    "lo",    "hi",    "bad",    "cause","pc",    \
  36.     "f0",   "f1",   "f2",   "f3",   "f4",   "f5",   "f6",   "f7", \
  37.     "f8",   "f9",   "f10",  "f11",  "f12",  "f13",  "f14",  "f15", \
  38.     "f16",  "f17",  "f18",  "f19",  "f20",  "f21",  "f22",  "f23",\
  39.     "f24",  "f25",  "f26",  "f27",  "f28",  "f29",  "f30",  "f31",\
  40.     "fsr",  "fir",  "fp",   "inx",  "rand", "tlblo","ctxt", "tlbhi",\
  41.     "epc",  "prid"\
  42.     }
  43.  
  44. static CONST char * CONST reg_names[] = REGISTER_NAMES;
  45.  
  46. /* subroutine */
  47. static void
  48. print_insn_arg (d, l, pc, info)
  49.      const char *d;
  50.      register unsigned long int l;
  51.      bfd_vma pc;
  52.      struct disassemble_info *info;
  53. {
  54.   int delta;
  55.  
  56.   switch (*d)
  57.     {
  58.     case ',':
  59.     case '(':
  60.     case ')':
  61.       (*info->fprintf_func) (info->stream, "%c", *d);
  62.       break;
  63.  
  64.     case 's':
  65.     case 'b':
  66.     case 'r':
  67.     case 'v':
  68.       (*info->fprintf_func) (info->stream, "$%s",
  69.                  reg_names[(l >> OP_SH_RS) & OP_MASK_RS]);
  70.       break;
  71.  
  72.     case 't':
  73.     case 'w':
  74.       (*info->fprintf_func) (info->stream, "$%s",
  75.                  reg_names[(l >> OP_SH_RT) & OP_MASK_RT]);
  76.       break;
  77.  
  78.     case 'i':
  79.     case 'u':
  80.       (*info->fprintf_func) (info->stream, "%d",
  81.             (l >> OP_SH_IMMEDIATE) & OP_MASK_IMMEDIATE);
  82.       break;
  83.  
  84.     case 'j': /* same as i, but sign-extended */
  85.     case 'o':
  86.       delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
  87.       if (delta & 0x8000)
  88.     delta |= ~0xffff;
  89.       (*info->fprintf_func) (info->stream, "%d",
  90.                  delta);
  91.       break;
  92.  
  93.     case 'k':
  94.       (*info->fprintf_func) (info->stream, "0x%x",
  95.                  (unsigned int) ((l >> OP_SH_CACHE)
  96.                          & OP_MASK_CACHE));
  97.       break;
  98.  
  99.     case 'a':
  100.       (*info->print_address_func)
  101.     (((pc & 0xF0000000) | (((l >> OP_SH_TARGET) & OP_MASK_TARGET) << 2)),
  102.      info);
  103.       break;
  104.  
  105.     case 'p':
  106.       /* sign extend the displacement */
  107.       delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
  108.       if (delta & 0x8000)
  109.     delta |= ~0xffff;
  110.       (*info->print_address_func)
  111.     ((delta << 2) + pc + 4,
  112.      info);
  113.       break;
  114.  
  115.     case 'd':
  116.       (*info->fprintf_func) (info->stream, "$%s",
  117.                  reg_names[(l >> OP_SH_RD) & OP_MASK_RD]);
  118.       break;
  119.  
  120.     case 'z':
  121.       (*info->fprintf_func) (info->stream, "$%s", reg_names[0]);
  122.       break;
  123.  
  124.     case '<':
  125.       (*info->fprintf_func) (info->stream, "0x%x",
  126.                  (l >> OP_SH_SHAMT) & OP_MASK_SHAMT);
  127.       break;
  128.  
  129.     case 'c':
  130.       (*info->fprintf_func) (info->stream, "0x%x",
  131.                  (l >> OP_SH_CODE) & OP_MASK_CODE);
  132.       break;
  133.  
  134.     case 'C':
  135.       (*info->fprintf_func) (info->stream, "0x%x",
  136.                  (l >> OP_SH_COPZ) & OP_MASK_COPZ);
  137.       break;
  138.  
  139.     case 'B':
  140.       (*info->fprintf_func) (info->stream, "0x%x",
  141.                  (l >> OP_SH_SYSCALL) & OP_MASK_SYSCALL);
  142.       break;
  143.  
  144.     case 'S':
  145.     case 'V':
  146.       (*info->fprintf_func) (info->stream, "$f%d",
  147.                  (l >> OP_SH_FS) & OP_MASK_FS);
  148.       break;
  149.  
  150.     case 'T':
  151.     case 'W':
  152.       (*info->fprintf_func) (info->stream, "$f%d",
  153.                  (l >> OP_SH_FT) & OP_MASK_FT);
  154.       break;
  155.  
  156.     case 'D':
  157.       (*info->fprintf_func) (info->stream, "$f%d",
  158.                  (l >> OP_SH_FD) & OP_MASK_FD);
  159.       break;
  160.  
  161.     case 'E':
  162.       (*info->fprintf_func) (info->stream, "$%d",
  163.                  (l >> OP_SH_RT) & OP_MASK_RT);
  164.       break;
  165.  
  166.     case 'G':
  167.       (*info->fprintf_func) (info->stream, "$%d",
  168.                  (l >> OP_SH_RD) & OP_MASK_RD);
  169.       break;
  170.  
  171.     default:
  172.       (*info->fprintf_func) (info->stream,
  173.                  "# internal error, undefined modifier(%c)", *d);
  174.       break;
  175.     }
  176. }
  177.  
  178. /* Print the mips instruction at address MEMADDR in debugged memory,
  179.    on using INFO.  Returns length of the instruction, in bytes, which is
  180.    always 4.  BIGENDIAN must be 1 if this is big-endian code, 0 if
  181.    this is little-endian code.  */
  182.  
  183. int
  184. _print_insn_mips (memaddr, word, info)
  185.      bfd_vma memaddr;
  186.      struct disassemble_info *info;
  187.      unsigned long int word;
  188. {
  189.   register int i;
  190.   register const char *d;
  191.  
  192.   for (i = 0; i < NUMOPCODES; i++)
  193.     {
  194.       if (mips_opcodes[i].pinfo != INSN_MACRO)
  195.     {
  196.       register unsigned int match = mips_opcodes[i].match;
  197.       register unsigned int mask = mips_opcodes[i].mask;
  198.       if ((word & mask) == match)
  199.         break;
  200.     }
  201.     }
  202.  
  203.   /* Handle undefined instructions.  */
  204.   if (i == NUMOPCODES)
  205.     {
  206.       (*info->fprintf_func) (info->stream, "0x%x", word);
  207.       return 4;
  208.     }
  209.  
  210.   (*info->fprintf_func) (info->stream, "%s", mips_opcodes[i].name);
  211.  
  212.   if (!(d = mips_opcodes[i].args))
  213.     return 4;
  214.  
  215.   (*info->fprintf_func) (info->stream, " ");
  216.  
  217.   while (*d)
  218.     print_insn_arg (d++, word, memaddr, info);
  219.  
  220.   return 4;
  221. }
  222.  
  223. int
  224. print_insn_big_mips (memaddr, info)
  225.      bfd_vma memaddr;
  226.      struct disassemble_info *info;
  227. {
  228.   bfd_byte buffer[4];
  229.   int status = (*info->read_memory_func) (memaddr, buffer, 4, info);
  230.   if (status == 0)
  231.     return _print_insn_mips (memaddr, bfd_getb32 (buffer), info);
  232.   else
  233.     {
  234.       (*info->memory_error_func) (status, memaddr, info);
  235.       return -1;
  236.     }
  237. }
  238.  
  239. int
  240. print_insn_little_mips (memaddr, info)
  241.      bfd_vma memaddr;
  242.      struct disassemble_info *info;
  243. {
  244.   bfd_byte buffer[4];
  245.   int status = (*info->read_memory_func) (memaddr, buffer, 4, info);
  246.   if (status == 0)
  247.     return _print_insn_mips (memaddr, bfd_getl32 (buffer), info);
  248.   else
  249.     {
  250.       (*info->memory_error_func) (status, memaddr, info);
  251.       return -1;
  252.     }
  253. }
  254.