home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / gnu / djgpp / src / binutils.2 / opcodes / mips-dis.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-30  |  6.0 KB  |  229 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 'C':
  130.       (*info->fprintf_func) (info->stream, "0x%x",
  131.                  (l >> OP_SH_COPZ) & OP_MASK_COPZ);
  132.       break;
  133.  
  134.     case 'S':
  135.       (*info->fprintf_func) (info->stream, "$f%d",
  136.                  (l >> OP_SH_FS) & OP_MASK_FS);
  137.       break;
  138.  
  139.     case 'T':
  140.       (*info->fprintf_func) (info->stream, "$f%d",
  141.                  (l >> OP_SH_FT) & OP_MASK_FT);
  142.       break;
  143.  
  144.     case 'D':
  145.       (*info->fprintf_func) (info->stream, "$f%d",
  146.                  (l >> OP_SH_FD) & OP_MASK_FD);
  147.       break;
  148.  
  149.     default:
  150.       (*info->fprintf_func) (info->stream,
  151.                  "# internal error, undefined modifier(%c)", *d);
  152.       break;
  153.     }
  154. }
  155.  
  156. /* Print the mips instruction at address MEMADDR in debugged memory,
  157.    on using INFO.  Returns length of the instruction, in bytes, which is
  158.    always 4.  BIGENDIAN must be 1 if this is big-endian code, 0 if
  159.    this is little-endian code.  */
  160.  
  161. int
  162. _print_insn_mips (memaddr, word, info)
  163.      bfd_vma memaddr;
  164.      struct disassemble_info *info;
  165.      unsigned long int word;
  166. {
  167.   register int i;
  168.   register char *d;
  169.  
  170.   for (i = 0; i < NOPCODES; i++)
  171.     {
  172.       register unsigned int opcode = mips_opcodes[i].opcode;
  173.       register unsigned int match = mips_opcodes[i].match;
  174.       if ((word & match) == opcode)
  175.     break;
  176.     }
  177.  
  178.   /* Handle undefined instructions.  */
  179.   if (i == NOPCODES)
  180.     {
  181.       (*info->fprintf_func) (info->stream, "0x%x", word);
  182.       return 4;
  183.     }
  184.  
  185.   (*info->fprintf_func) (info->stream, "%s", mips_opcodes[i].name);
  186.  
  187.   if (!(d = mips_opcodes[i].args))
  188.     return 4;
  189.  
  190.   (*info->fprintf_func) (info->stream, " ");
  191.  
  192.   while (*d)
  193.     print_insn_arg (d++, word, memaddr, info);
  194.  
  195.   return 4;
  196. }
  197.  
  198. int
  199. print_insn_big_mips (memaddr, info)
  200.      bfd_vma memaddr;
  201.      struct disassemble_info *info;
  202. {
  203.   bfd_byte buffer[4];
  204.   int status = (*info->read_memory_func) (memaddr, buffer, 4, info);
  205.   if (status == 0)
  206.     return _print_insn_mips (memaddr, _do_getb32 (buffer), info);
  207.   else
  208.     {
  209.       (*info->memory_error_func) (status, memaddr, info);
  210.       return -1;
  211.     }
  212. }
  213.  
  214. int
  215. print_insn_little_mips (memaddr, info)
  216.      bfd_vma memaddr;
  217.      struct disassemble_info *info;
  218. {
  219.   bfd_byte buffer[4];
  220.   int status = (*info->read_memory_func) (memaddr, buffer, 4, info);
  221.   if (status == 0)
  222.     return _print_insn_mips (memaddr, _do_getl32 (buffer), info);
  223.   else
  224.     {
  225.       (*info->memory_error_func) (status, memaddr, info);
  226.       return -1;
  227.     }
  228. }
  229.