home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / gdb-4.9 / opcodes / mips-dis.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-12  |  5.9 KB  |  224 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. /* FIXME: we need direct access to the swapping functions.  */
  27. #include "libbfd.h"
  28.  
  29. /* We use bfd_vma in a couple of places where gdb expects CORE_ADDR.  */
  30. #ifdef HOST_64_BIT
  31.  #error FIXME: bfd_vma will not match gdb expectations
  32. #endif
  33.  
  34. /* Mips instructions are never longer than this many bytes.  */
  35. #define MAXLEN 4
  36.  
  37. /* Number of elements in the opcode table.  */
  38. #define NOPCODES (sizeof mips_opcodes / sizeof mips_opcodes[0])
  39.  
  40. /* FIXME: This should be shared with gdb somehow.  */
  41. #define REGISTER_NAMES     \
  42.     {    "zero",    "at",    "v0",    "v1",    "a0",    "a1",    "a2",    "a3", \
  43.     "t0",    "t1",    "t2",    "t3",    "t4",    "t5",    "t6",    "t7", \
  44.     "s0",    "s1",    "s2",    "s3",    "s4",    "s5",    "s6",    "s7", \
  45.     "t8",    "t9",    "k0",    "k1",    "gp",    "sp",    "s8",    "ra", \
  46.     "sr",    "lo",    "hi",    "bad",    "cause","pc",    \
  47.     "f0",   "f1",   "f2",   "f3",   "f4",   "f5",   "f6",   "f7", \
  48.     "f8",   "f9",   "f10",  "f11",  "f12",  "f13",  "f14",  "f15", \
  49.     "f16",  "f17",  "f18",  "f19",  "f20",  "f21",  "f22",  "f23",\
  50.     "f24",  "f25",  "f26",  "f27",  "f28",  "f29",  "f30",  "f31",\
  51.     "fsr",  "fir",  "fp",   "inx",  "rand", "tlblo","ctxt", "tlbhi",\
  52.     "epc",  "prid"\
  53.     }
  54.  
  55. static CONST char * CONST reg_names[] = REGISTER_NAMES;
  56.  
  57. /* subroutine */
  58. static void
  59. print_insn_arg (d, l, pc, info)
  60.      char *d;
  61.      register unsigned long int l;
  62.      bfd_vma pc;
  63.      struct disassemble_info *info;
  64. {
  65.   int delta;
  66.  
  67.   switch (*d)
  68.     {
  69.     case ',':
  70.     case '(':
  71.     case ')':
  72.       (*info->fprintf_func) (info->stream, "%c", *d);
  73.       break;
  74.  
  75.     case 's':
  76.       (*info->fprintf_func) (info->stream, "$%s",
  77.                  reg_names[(l >> OP_SH_RS) & OP_MASK_RS]);
  78.       break;
  79.  
  80.     case 't':
  81.       (*info->fprintf_func) (info->stream, "$%s",
  82.                  reg_names[(l >> OP_SH_RT) & OP_MASK_RT]);
  83.       break;
  84.  
  85.     case 'i':
  86.       (*info->fprintf_func) (info->stream, "%d",
  87.             (l >> OP_SH_IMMEDIATE) & OP_MASK_IMMEDIATE);
  88.       break;
  89.  
  90.     case 'j': /* same as i, but sign-extended */
  91.       delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
  92.       if (delta & 0x8000)
  93.     delta |= ~0xffff;
  94.       (*info->fprintf_func) (info->stream, "%d",
  95.                  delta);
  96.       break;
  97.  
  98.     case 'a':
  99.       (*info->print_address_func)
  100.     (((pc & 0xF0000000) | (((l >> OP_SH_TARGET) & OP_MASK_TARGET) << 2)),
  101.      info);
  102.       break;
  103.  
  104.     case 'b':
  105.       /* sign extend the displacement */
  106.       delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
  107.       if (delta & 0x8000)
  108.     delta |= ~0xffff;
  109.       (*info->print_address_func)
  110.     ((delta << 2) + pc + 4,
  111.      info);
  112.       break;
  113.  
  114.     case 'd':
  115.       (*info->fprintf_func) (info->stream, "$%s",
  116.                  reg_names[(l >> OP_SH_RD) & OP_MASK_RD]);
  117.       break;
  118.  
  119.     case 'h':
  120.       (*info->fprintf_func) (info->stream, "0x%x",
  121.                  (l >> OP_SH_SHAMT) & OP_MASK_SHAMT);
  122.       break;
  123.  
  124.     case 'B':
  125.       (*info->fprintf_func) (info->stream, "0x%x",
  126.                  (l >> OP_SH_CODE) & OP_MASK_CODE);
  127.       break;
  128.  
  129.     case 'S':
  130.       (*info->fprintf_func) (info->stream, "$f%d",
  131.                  (l >> OP_SH_FS) & OP_MASK_FS);
  132.       break;
  133.  
  134.     case 'T':
  135.       (*info->fprintf_func) (info->stream, "$f%d",
  136.                  (l >> OP_SH_FT) & OP_MASK_FT);
  137.       break;
  138.  
  139.     case 'D':
  140.       (*info->fprintf_func) (info->stream, "$f%d",
  141.                  (l >> OP_SH_FD) & OP_MASK_FD);
  142.       break;
  143.  
  144.     default:
  145.       (*info->fprintf_func) (info->stream,
  146.                  "# internal error, undefined modifier(%c)", *d);
  147.       break;
  148.     }
  149. }
  150.  
  151. /* Print the mips instruction at address MEMADDR in debugged memory,
  152.    on using INFO.  Returns length of the instruction, in bytes, which is
  153.    always 4.  BIGENDIAN must be 1 if this is big-endian code, 0 if
  154.    this is little-endian code.  */
  155.  
  156. int
  157. _print_insn_mips (memaddr, word, info)
  158.      bfd_vma memaddr;
  159.      struct disassemble_info *info;
  160.      unsigned long int word;
  161. {
  162.   register int i;
  163.   register char *d;
  164.  
  165.   for (i = 0; i < NOPCODES; i++)
  166.     {
  167.       register unsigned int opcode = mips_opcodes[i].opcode;
  168.       register unsigned int match = mips_opcodes[i].match;
  169.       if ((word & match) == opcode)
  170.     break;
  171.     }
  172.  
  173.   /* Handle undefined instructions.  */
  174.   if (i == NOPCODES)
  175.     {
  176.       (*info->fprintf_func) (info->stream, "0x%x", word);
  177.       return 4;
  178.     }
  179.  
  180.   (*info->fprintf_func) (info->stream, "%s", mips_opcodes[i].name);
  181.  
  182.   if (!(d = mips_opcodes[i].args))
  183.     return 4;
  184.  
  185.   (*info->fprintf_func) (info->stream, " ");
  186.  
  187.   while (*d)
  188.     print_insn_arg (d++, word, memaddr, info);
  189.  
  190.   return 4;
  191. }
  192.  
  193. int
  194. print_insn_big_mips (memaddr, info)
  195.      bfd_vma memaddr;
  196.      struct disassemble_info *info;
  197. {
  198.   bfd_byte buffer[4];
  199.   int status = (*info->read_memory_func) (memaddr, buffer, 4, info);
  200.   if (status == 0)
  201.     return _print_insn_mips (memaddr, _do_getb32 (buffer), info);
  202.   else
  203.     {
  204.       (*info->memory_error_func) (status, memaddr, info);
  205.       return -1;
  206.     }
  207. }
  208.  
  209. int
  210. print_insn_little_mips (memaddr, info)
  211.      bfd_vma memaddr;
  212.      struct disassemble_info *info;
  213. {
  214.   bfd_byte buffer[4];
  215.   int status = (*info->read_memory_func) (memaddr, buffer, 4, info);
  216.   if (status == 0)
  217.     return _print_insn_mips (memaddr, _do_getl32 (buffer), info);
  218.   else
  219.     {
  220.       (*info->memory_error_func) (status, memaddr, info);
  221.       return -1;
  222.     }
  223. }
  224.