gas/
[deliverable/binutils-gdb.git] / opcodes / mips-dis.c
index 59e1824f220a58730c1322063879a1660988624b..01e446c56aa507f0bb3cf0f73f4d8fbb4f2a1155 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, 2006, 2007, 2008, 2009
    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",
@@ -295,6 +319,56 @@ static const struct mips_cp0sel_name mips_cp0sel_names_sb1[] =
   { 29, 3, "c0_datahi_d"       },
 };
 
+/* Xlr cop0 register names.  */
+static const char * const mips_cp0_names_xlr[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_status",    "c0_cause",     "c0_epc",       "c0_prid",
+  "c0_config",    "c0_lladdr",    "c0_watchlo",   "c0_watchhi",
+  "c0_xcontext",  "$21",          "$22",          "c0_debug",
+  "c0_depc",      "c0_perfcnt",   "c0_errctl",    "c0_cacheerr_i",
+  "c0_taglo_i",   "c0_taghi_i",   "c0_errorepc",  "c0_desave",
+};
+
+/* XLR's CP0 Select Registers.  */
+
+static const struct mips_cp0sel_name mips_cp0sel_names_xlr[] = {
+  {  9, 6, "c0_extintreq"       },
+  {  9, 7, "c0_extintmask"      },
+  { 15, 1, "c0_ebase"           },
+  { 16, 1, "c0_config1"         },
+  { 16, 2, "c0_config2"         },
+  { 16, 3, "c0_config3"         },
+  { 16, 7, "c0_procid2"         },
+  { 18, 1, "c0_watchlo,1"       },
+  { 18, 2, "c0_watchlo,2"       },
+  { 18, 3, "c0_watchlo,3"       },
+  { 18, 4, "c0_watchlo,4"       },
+  { 18, 5, "c0_watchlo,5"       },
+  { 18, 6, "c0_watchlo,6"       },
+  { 18, 7, "c0_watchlo,7"       },
+  { 19, 1, "c0_watchhi,1"       },
+  { 19, 2, "c0_watchhi,2"       },
+  { 19, 3, "c0_watchhi,3"       },
+  { 19, 4, "c0_watchhi,4"       },
+  { 19, 5, "c0_watchhi,5"       },
+  { 19, 6, "c0_watchhi,6"       },
+  { 19, 7, "c0_watchhi,7"       },
+  { 25, 1, "c0_perfcnt,1"       },
+  { 25, 2, "c0_perfcnt,2"       },
+  { 25, 3, "c0_perfcnt,3"       },
+  { 25, 4, "c0_perfcnt,4"       },
+  { 25, 5, "c0_perfcnt,5"       },
+  { 25, 6, "c0_perfcnt,6"       },
+  { 25, 7, "c0_perfcnt,7"       },
+  { 27, 1, "c0_cacheerr,1"      },
+  { 27, 2, "c0_cacheerr,2"      },
+  { 27, 3, "c0_cacheerr,3"      },
+  { 28, 1, "c0_datalo"          },
+  { 29, 1, "c0_datahi"          }
+};
+
 static const char * const mips_hwr_names_numeric[32] =
 {
   "$0",   "$1",   "$2",   "$3",   "$4",   "$5",   "$6",   "$7",
@@ -346,11 +420,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 +436,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,
@@ -385,6 +459,10 @@ const struct mips_arch_choice mips_arch_choices[] =
     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
   { "r12000",  1, bfd_mach_mips12000, CPU_R12000, ISA_MIPS4,
     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
+  { "r14000",  1, bfd_mach_mips14000, CPU_R14000, ISA_MIPS4,
+    mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
+  { "r16000",  1, bfd_mach_mips16000, CPU_R16000, ISA_MIPS4,
+    mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
   { "mips5",   1, bfd_mach_mips5, CPU_MIPS5, ISA_MIPS5,
     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
 
@@ -394,26 +472,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_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_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_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_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,9 +504,27 @@ 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 },
+
+  { "xlr", 1, bfd_mach_mips_xlr, CPU_XLR,
+    ISA_MIPS64 | INSN_XLR,
+    mips_cp0_names_xlr,
+    mips_cp0sel_names_xlr, ARRAY_SIZE (mips_cp0sel_names_xlr),
+    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,
+  { "",                1, bfd_mach_mips16, CPU_MIPS16, ISA_MIPS3,
     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
 };
 
@@ -573,7 +671,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 +942,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 +978,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);
@@ -1034,6 +1164,7 @@ print_insn_args (const char *d,
          break;
 
        case '<':
+       case '1':
          (*info->fprintf_func) (info->stream, "0x%lx",
                                 (l >> OP_SH_SHAMT) & OP_MASK_SHAMT);
          break;
@@ -1201,7 +1332,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;
        }
@@ -1529,7 +1660,6 @@ print_mips16_insn_arg (char type,
            signedp = 1;
            pcrel = 1;
            branch = 1;
-           info->insn_type = dis_condbranch;
            break;
          case 'q':
            nbits = 11;
@@ -1537,7 +1667,6 @@ print_mips16_insn_arg (char type,
            signedp = 1;
            pcrel = 1;
            branch = 1;
-           info->insn_type = dis_branch;
            break;
          case 'A':
            nbits = 8;
@@ -1658,8 +1787,6 @@ print_mips16_insn_arg (char type,
       }
       info->target = ((memaddr + 4) & ~(bfd_vma) 0x0fffffff) | l;
       (*info->print_address_func) (info->target, info);
-      info->insn_type = dis_jsr;
-      info->branch_delay_insns = 1;
       break;
 
     case 'l':
@@ -1951,12 +2078,19 @@ print_insn_mips16 (bfd_vma memaddr, struct disassemble_info *info)
                                     info);
            }
 
+         /* Figure out branch instruction type and delay slot information.  */
          if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
+           info->branch_delay_insns = 1;
+         if ((op->pinfo & (INSN_UNCOND_BRANCH_DELAY
+                           | MIPS16_INSN_UNCOND_BRANCH)) != 0)
            {
-             info->branch_delay_insns = 1;
-             if (info->insn_type != dis_jsr)
+             if ((op->pinfo & INSN_WRITE_GPR_31) != 0)
+               info->insn_type = dis_jsr;
+             else
                info->insn_type = dis_branch;
            }
+         else if ((op->pinfo & MIPS16_INSN_COND_BRANCH) != 0)
+           info->insn_type = dis_condbranch;
 
          return length;
        }
@@ -1996,10 +2130,10 @@ _print_insn_mips (bfd_vma memaddr,
 
 #if SYMTAB_AVAILABLE
   if (info->mach == bfd_mach_mips16
-      || (info->flavour == bfd_target_elf_flavour
-         && info->symbols != NULL
-         && ((*(elf_symbol_type **) info->symbols)->internal_elf_sym.st_other
-             == STO_MIPS16)))
+      || (info->symbols != NULL
+         && bfd_asymbol_flavour (*info->symbols) == bfd_target_elf_flavour
+         && ELF_ST_IS_MIPS16 ((*(elf_symbol_type **) info->symbols)
+                              ->internal_elf_sym.st_other)))
     return print_insn_mips16 (memaddr, info);
 #endif
 
This page took 0.028789 seconds and 4 git commands to generate.