bfd/
[deliverable/binutils-gdb.git] / opcodes / mips-dis.c
index ee1e9af0c9ad0b1da37740d3ea3d360821123abe..35a51191525903913eef8c9b7b1212d16ac79106 100644 (file)
@@ -1,20 +1,20 @@
 /* Print mips instructions for GDB, the GNU debugger, or for objdump.
    Copyright 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003, 2005
+   2000, 2001, 2002, 2003, 2005, 2007, 2008
    Free Software Foundation, Inc.
    Contributed by Nobuyuki Hikichi(hikichi@sra.co.jp).
 
-   This file is part of GDB, GAS, and the GNU binutils.
+   This file is part of the GNU opcodes library.
 
-   This program is free software; you can redistribute it and/or modify
+   This library is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
 
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
+   It is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
@@ -124,6 +124,30 @@ static const char * const mips_cp0_names_numeric[32] =
   "$24",  "$25",  "$26",  "$27",  "$28",  "$29",  "$30",  "$31"
 };
 
+static const char * const mips_cp0_names_r3000[32] =
+{
+  "c0_index",     "c0_random",    "c0_entrylo",   "$3",
+  "c0_context",   "$5",           "$6",           "$7",
+  "c0_badvaddr",  "$9",           "c0_entryhi",   "$11",
+  "c0_sr",        "c0_cause",     "c0_epc",       "c0_prid",
+  "$16",          "$17",          "$18",          "$19",
+  "$20",          "$21",          "$22",          "$23",
+  "$24",          "$25",          "$26",          "$27",
+  "$28",          "$29",          "$30",          "$31",
+};
+
+static const char * const mips_cp0_names_r4000[32] =
+{
+  "c0_index",     "c0_random",    "c0_entrylo0",  "c0_entrylo1",
+  "c0_context",   "c0_pagemask",  "c0_wired",     "$7",
+  "c0_badvaddr",  "c0_count",     "c0_entryhi",   "c0_compare",
+  "c0_sr",        "c0_cause",     "c0_epc",       "c0_prid",
+  "c0_config",    "c0_lladdr",    "c0_watchlo",   "c0_watchhi",
+  "c0_xcontext",  "$21",          "$22",          "$23",
+  "$24",          "$25",          "c0_ecc",       "c0_cacheerr",
+  "c0_taglo",     "c0_taghi",     "c0_errorepc",  "$31",
+};
+
 static const char * const mips_cp0_names_mips3264[32] =
 {
   "c0_index",     "c0_random",    "c0_entrylo0",  "c0_entrylo1",
@@ -346,11 +370,11 @@ const struct mips_arch_choice mips_arch_choices[] =
     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
 
   { "r3000",   1, bfd_mach_mips3000, CPU_R3000, ISA_MIPS1,
-    mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
+    mips_cp0_names_r3000, NULL, 0, mips_hwr_names_numeric },
   { "r3900",   1, bfd_mach_mips3900, CPU_R3900, ISA_MIPS1,
     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
   { "r4000",   1, bfd_mach_mips4000, CPU_R4000, ISA_MIPS3,
-    mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
+    mips_cp0_names_r4000, NULL, 0, mips_hwr_names_numeric },
   { "r4010",   1, bfd_mach_mips4010, CPU_R4010, ISA_MIPS2,
     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
   { "vr4100",  1, bfd_mach_mips4100, CPU_VR4100, ISA_MIPS3,
@@ -362,7 +386,7 @@ const struct mips_arch_choice mips_arch_choices[] =
   { "r4300",   1, bfd_mach_mips4300, CPU_R4300, ISA_MIPS3,
     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
   { "r4400",   1, bfd_mach_mips4400, CPU_R4400, ISA_MIPS3,
-    mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
+    mips_cp0_names_r4000, NULL, 0, mips_hwr_names_numeric },
   { "r4600",   1, bfd_mach_mips4600, CPU_R4600, ISA_MIPS3,
     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
   { "r4650",   1, bfd_mach_mips4650, CPU_R4650, ISA_MIPS3,
@@ -394,26 +418,28 @@ const struct mips_arch_choice mips_arch_choices[] =
      MIPS32 Architecture_ (MIPS Document Number MD00082, Revision 0.95),
      page 1.  */
   { "mips32",  1, bfd_mach_mipsisa32, CPU_MIPS32,
-    ISA_MIPS32 | INSN_MIPS16 | INSN_DSP,
+    ISA_MIPS32 | INSN_MIPS16 | INSN_SMARTMIPS,
     mips_cp0_names_mips3264,
     mips_cp0sel_names_mips3264, ARRAY_SIZE (mips_cp0sel_names_mips3264),
     mips_hwr_names_numeric },
 
   { "mips32r2",        1, bfd_mach_mipsisa32r2, CPU_MIPS32R2,
-    ISA_MIPS32R2 | INSN_MIPS16 | INSN_DSP | INSN_MT,
+    (ISA_MIPS32R2 | INSN_MIPS16 | INSN_SMARTMIPS | INSN_DSP | INSN_DSPR2
+     | INSN_MIPS3D | INSN_MT),
     mips_cp0_names_mips3264r2,
     mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
     mips_hwr_names_mips3264r2 },
 
   /* For stock MIPS64, disassemble all applicable MIPS-specified ASEs.  */
   { "mips64",  1, bfd_mach_mipsisa64, CPU_MIPS64,
-    ISA_MIPS64 | INSN_MIPS16 | INSN_MIPS3D | INSN_MDMX | INSN_DSP,
+    ISA_MIPS64 | INSN_MIPS16 | INSN_MIPS3D | INSN_MDMX,
     mips_cp0_names_mips3264,
     mips_cp0sel_names_mips3264, ARRAY_SIZE (mips_cp0sel_names_mips3264),
     mips_hwr_names_numeric },
 
   { "mips64r2",        1, bfd_mach_mipsisa64r2, CPU_MIPS64R2,
-    ISA_MIPS64R2 | INSN_MIPS16 | INSN_MIPS3D | INSN_MDMX | INSN_DSP,
+    (ISA_MIPS64R2 | INSN_MIPS16 | INSN_MIPS3D | INSN_DSP | INSN_DSPR2
+     | INSN_DSP64 | INSN_MT | INSN_MDMX),
     mips_cp0_names_mips3264r2,
     mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
     mips_hwr_names_mips3264r2 },
@@ -424,6 +450,18 @@ const struct mips_arch_choice mips_arch_choices[] =
     mips_cp0sel_names_sb1, ARRAY_SIZE (mips_cp0sel_names_sb1),
     mips_hwr_names_numeric },
 
+  { "loongson2e",   1, bfd_mach_mips_loongson_2e, CPU_LOONGSON_2E,
+    ISA_MIPS3 | INSN_LOONGSON_2E, mips_cp0_names_numeric, 
+    NULL, 0, mips_hwr_names_numeric },
+
+  { "loongson2f",   1, bfd_mach_mips_loongson_2f, CPU_LOONGSON_2F,
+    ISA_MIPS3 | INSN_LOONGSON_2F, mips_cp0_names_numeric, 
+    NULL, 0, mips_hwr_names_numeric },
+
+  { "octeon",   1, bfd_mach_mips_octeon, CPU_OCTEON,
+    ISA_MIPS64R2 | INSN_OCTEON, mips_cp0_names_numeric, NULL, 0,
+    mips_hwr_names_numeric },
+
   /* This entry, mips16, is here only for ISA/processor selection; do
      not print its name.  */
   { "",                1, bfd_mach_mips16, CPU_MIPS16, ISA_MIPS3 | INSN_MIPS16,
@@ -573,7 +611,7 @@ parse_mips_dis_option (const char *option, unsigned int len)
   const struct mips_arch_choice *chosen_arch;
 
   /* Try to match options that are simple flags */
-  if (strncmp (option, "no-aliases", 10) == 0)
+  if (CONST_STRNEQ (option, "no-aliases"))
     {
       no_aliases = 1;
       return;
@@ -844,6 +882,33 @@ print_insn_args (const char *d,
                break;
              }
 
+           case 'x':           /* bbit bit index */
+             (*info->fprintf_func) (info->stream, "0x%lx",
+                                    (l >> OP_SH_BBITIND) & OP_MASK_BBITIND);
+             break;
+
+           case 'p':           /* cins, cins32, exts and exts32 position */
+             (*info->fprintf_func) (info->stream, "0x%lx",
+                                    (l >> OP_SH_CINSPOS) & OP_MASK_CINSPOS);
+             break;
+
+           case 's':           /* cins and exts length-minus-one */
+             (*info->fprintf_func) (info->stream, "0x%lx",
+                                    (l >> OP_SH_CINSLM1) & OP_MASK_CINSLM1);
+             break;
+
+           case 'S':           /* cins32 and exts32 length-minus-one field */
+             (*info->fprintf_func) (info->stream, "0x%lx",
+                                    (l >> OP_SH_CINSLM1) & OP_MASK_CINSLM1);
+             break;
+
+           case 'Q':           /* seqi/snei immediate field */
+             op = (l >> OP_SH_SEQI) & OP_MASK_SEQI;
+             /* Sign-extend it.  */
+             op = (op ^ 512) - 512;
+             (*info->fprintf_func) (info->stream, "%d", op);
+             break;
+
            default:
              /* xgettext:c-format */
              (*info->fprintf_func) (info->stream,
@@ -853,6 +918,11 @@ print_insn_args (const char *d,
            }
          break;
 
+       case '2':
+         (*info->fprintf_func) (info->stream, "0x%lx",
+                                (l >> OP_SH_BP) & OP_MASK_BP);
+         break;
+
        case '3':
          (*info->fprintf_func) (info->stream, "0x%lx",
                                 (l >> OP_SH_SA3) & OP_MASK_SA3);
@@ -984,6 +1054,10 @@ print_insn_args (const char *d,
        case 'a':
          info->target = (((pc + 4) & ~(bfd_vma) 0x0fffffff)
                          | (((l >> OP_SH_TARGET) & OP_MASK_TARGET) << 2));
+         /* For gdb disassembler, force odd address on jalx.  */
+         if (info->flavour == bfd_target_unknown_flavour
+             && strcmp (opp->name, "jalx") == 0)
+           info->target |= 1;
          (*info->print_address_func) (info->target, info);
          break;
 
@@ -1197,7 +1271,7 @@ print_insn_args (const char *d,
        default:
          /* xgettext:c-format */
          (*info->fprintf_func) (info->stream,
-                                _("# internal error, undefined modifier(%c)"),
+                                _("# internal error, undefined modifier (%c)"),
                                 *d);
          return;
        }
@@ -1632,15 +1706,26 @@ print_mips16_insn_arg (char type,
                  }
              }
            info->target = (baseaddr & ~((1 << shift) - 1)) + immed;
+           if (pcrel && branch
+               && info->flavour == bfd_target_unknown_flavour)
+             /* For gdb disassembler, maintain odd address.  */
+             info->target |= 1;
            (*info->print_address_func) (info->target, info);
          }
       }
       break;
 
     case 'a':
-      if (! use_extend)
-       extend = 0;
-      l = ((l & 0x1f) << 23) | ((l & 0x3e0) << 13) | (extend << 2);
+      {
+       int jalx = l & 0x400;
+
+       if (! use_extend)
+         extend = 0;
+       l = ((l & 0x1f) << 23) | ((l & 0x3e0) << 13) | (extend << 2);
+       if (!jalx && info->flavour == bfd_target_unknown_flavour)
+         /* For gdb disassembler, maintain odd address.  */
+         l |= 1;
+      }
       info->target = ((memaddr + 4) & ~(bfd_vma) 0x0fffffff) | l;
       (*info->print_address_func) (info->target, info);
       info->insn_type = dis_jsr;
@@ -1981,8 +2066,8 @@ _print_insn_mips (bfd_vma memaddr,
 
 #if SYMTAB_AVAILABLE
   if (info->mach == bfd_mach_mips16
-      || (info->flavour == bfd_target_elf_flavour
-         && info->symbols != NULL
+      || (info->symbols != NULL
+         && bfd_asymbol_flavour (*info->symbols) == bfd_target_elf_flavour
          && ((*(elf_symbol_type **) info->symbols)->internal_elf_sym.st_other
              == STO_MIPS16)))
     return print_insn_mips16 (memaddr, info);
This page took 0.027594 seconds and 4 git commands to generate.