Constify main.c:get_init_files.
[deliverable/binutils-gdb.git] / opcodes / mips-dis.c
index 9c9112b3f59110b3e0064913701307a2743bb88c..ee5827cada6405b9ec93b4200207bd3493c23dcd 100644 (file)
@@ -517,6 +517,7 @@ struct mips_arch_choice
   unsigned long bfd_mach;
   int processor;
   int isa;
+  int ase;
   const char * const *cp0_names;
   const struct mips_cp0sel_name *cp0sel_names;
   unsigned int cp0sel_names_len;
@@ -525,56 +526,56 @@ struct mips_arch_choice
 
 const struct mips_arch_choice mips_arch_choices[] =
 {
-  { "numeric", 0, 0, 0, 0,
+  { "numeric", 0, 0, 0, 0, 0,
     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
 
-  { "r3000",   1, bfd_mach_mips3000, CPU_R3000, ISA_MIPS1,
+  { "r3000",   1, bfd_mach_mips3000, CPU_R3000, ISA_MIPS1, 0,
     mips_cp0_names_r3000, NULL, 0, mips_hwr_names_numeric },
-  { "r3900",   1, bfd_mach_mips3900, CPU_R3900, ISA_MIPS1,
+  { "r3900",   1, bfd_mach_mips3900, CPU_R3900, ISA_MIPS1, 0,
     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
-  { "r4000",   1, bfd_mach_mips4000, CPU_R4000, ISA_MIPS3,
+  { "r4000",   1, bfd_mach_mips4000, CPU_R4000, ISA_MIPS3, 0,
     mips_cp0_names_r4000, NULL, 0, mips_hwr_names_numeric },
-  { "r4010",   1, bfd_mach_mips4010, CPU_R4010, ISA_MIPS2,
+  { "r4010",   1, bfd_mach_mips4010, CPU_R4010, ISA_MIPS2, 0,
     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
-  { "vr4100",  1, bfd_mach_mips4100, CPU_VR4100, ISA_MIPS3,
+  { "vr4100",  1, bfd_mach_mips4100, CPU_VR4100, ISA_MIPS3, 0,
     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
-  { "vr4111",  1, bfd_mach_mips4111, CPU_R4111, ISA_MIPS3,
+  { "vr4111",  1, bfd_mach_mips4111, CPU_R4111, ISA_MIPS3, 0,
     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
-  { "vr4120",  1, bfd_mach_mips4120, CPU_VR4120, ISA_MIPS3,
+  { "vr4120",  1, bfd_mach_mips4120, CPU_VR4120, ISA_MIPS3, 0,
     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
-  { "r4300",   1, bfd_mach_mips4300, CPU_R4300, ISA_MIPS3,
+  { "r4300",   1, bfd_mach_mips4300, CPU_R4300, ISA_MIPS3, 0,
     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
-  { "r4400",   1, bfd_mach_mips4400, CPU_R4400, ISA_MIPS3,
+  { "r4400",   1, bfd_mach_mips4400, CPU_R4400, ISA_MIPS3, 0,
     mips_cp0_names_r4000, NULL, 0, mips_hwr_names_numeric },
-  { "r4600",   1, bfd_mach_mips4600, CPU_R4600, ISA_MIPS3,
+  { "r4600",   1, bfd_mach_mips4600, CPU_R4600, ISA_MIPS3, 0,
     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
-  { "r4650",   1, bfd_mach_mips4650, CPU_R4650, ISA_MIPS3,
+  { "r4650",   1, bfd_mach_mips4650, CPU_R4650, ISA_MIPS3, 0,
     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
-  { "r5000",   1, bfd_mach_mips5000, CPU_R5000, ISA_MIPS4,
+  { "r5000",   1, bfd_mach_mips5000, CPU_R5000, ISA_MIPS4, 0,
     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
-  { "vr5400",  1, bfd_mach_mips5400, CPU_VR5400, ISA_MIPS4,
+  { "vr5400",  1, bfd_mach_mips5400, CPU_VR5400, ISA_MIPS4, 0,
     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
-  { "vr5500",  1, bfd_mach_mips5500, CPU_VR5500, ISA_MIPS4,
+  { "vr5500",  1, bfd_mach_mips5500, CPU_VR5500, ISA_MIPS4, 0,
     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
-  { "r5900",   1, bfd_mach_mips5900, CPU_R5900, ISA_MIPS3,
+  { "r5900",   1, bfd_mach_mips5900, CPU_R5900, ISA_MIPS3, 0,
     mips_cp0_names_r5900, NULL, 0, mips_hwr_names_numeric },
-  { "r6000",   1, bfd_mach_mips6000, CPU_R6000, ISA_MIPS2,
+  { "r6000",   1, bfd_mach_mips6000, CPU_R6000, ISA_MIPS2, 0,
     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
-  { "rm7000",  1, bfd_mach_mips7000, CPU_RM7000, ISA_MIPS4,
+  { "rm7000",  1, bfd_mach_mips7000, CPU_RM7000, ISA_MIPS4, 0,
     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
-  { "rm9000",  1, bfd_mach_mips7000, CPU_RM7000, ISA_MIPS4,
+  { "rm9000",  1, bfd_mach_mips7000, CPU_RM7000, ISA_MIPS4, 0,
     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
-  { "r8000",   1, bfd_mach_mips8000, CPU_R8000, ISA_MIPS4,
+  { "r8000",   1, bfd_mach_mips8000, CPU_R8000, ISA_MIPS4, 0,
     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
-  { "r10000",  1, bfd_mach_mips10000, CPU_R10000, ISA_MIPS4,
+  { "r10000",  1, bfd_mach_mips10000, CPU_R10000, ISA_MIPS4, 0,
     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
-  { "r12000",  1, bfd_mach_mips12000, CPU_R12000, ISA_MIPS4,
+  { "r12000",  1, bfd_mach_mips12000, CPU_R12000, ISA_MIPS4, 0,
     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
-  { "r14000",  1, bfd_mach_mips14000, CPU_R14000, ISA_MIPS4,
+  { "r14000",  1, bfd_mach_mips14000, CPU_R14000, ISA_MIPS4, 0,
     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
-  { "r16000",  1, bfd_mach_mips16000, CPU_R16000, ISA_MIPS4,
+  { "r16000",  1, bfd_mach_mips16000, CPU_R16000, ISA_MIPS4, 0,
     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
-  { "mips5",   1, bfd_mach_mips5, CPU_MIPS5, ISA_MIPS5,
+  { "mips5",   1, bfd_mach_mips5, CPU_MIPS5, ISA_MIPS5, 0,
     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
 
   /* For stock MIPS32, disassemble all applicable MIPS-specified ASEs.
@@ -583,64 +584,66 @@ 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_SMARTMIPS,
+    ISA_MIPS32,  ASE_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_SMARTMIPS | INSN_DSP | INSN_DSPR2
-     | INSN_MIPS3D | INSN_MT | INSN_MCU),
+    ISA_MIPS32R2,
+    (ASE_SMARTMIPS | ASE_DSP | ASE_DSPR2 | ASE_EVA | ASE_MIPS3D
+     | ASE_MT | ASE_MCU | ASE_VIRT),
     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_MIPS3D | INSN_MDMX,
+    ISA_MIPS64,  ASE_MIPS3D | ASE_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_MIPS3D | INSN_DSP | INSN_DSPR2
-     | INSN_DSP64 | INSN_MT | INSN_MDMX | INSN_MCU),
+    ISA_MIPS64R2,
+    (ASE_MIPS3D | ASE_DSP | ASE_DSPR2 | ASE_DSP64 | ASE_EVA | ASE_MT
+     | ASE_MDMX | ASE_MCU | ASE_VIRT | ASE_VIRT64),
     mips_cp0_names_mips3264r2,
     mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
     mips_hwr_names_mips3264r2 },
 
   { "sb1",     1, bfd_mach_mips_sb1, CPU_SB1,
-    ISA_MIPS64 | INSN_MIPS3D | INSN_SB1,
+    ISA_MIPS64 | INSN_SB1,  ASE_MIPS3D,
     mips_cp0_names_sb1,
     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, 
+    ISA_MIPS3 | INSN_LOONGSON_2E, 0, 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, 
+    ISA_MIPS3 | INSN_LOONGSON_2F, 0, mips_cp0_names_numeric,
     NULL, 0, mips_hwr_names_numeric },
 
   { "loongson3a",   1, bfd_mach_mips_loongson_3a, CPU_LOONGSON_3A,
-    ISA_MIPS64 | INSN_LOONGSON_3A, mips_cp0_names_numeric, 
+    ISA_MIPS64 | INSN_LOONGSON_3A, 0, 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,
+    ISA_MIPS64R2 | INSN_OCTEON, 0, mips_cp0_names_numeric, NULL, 0,
     mips_hwr_names_numeric },
 
   { "octeon+",   1, bfd_mach_mips_octeonp, CPU_OCTEONP,
-    ISA_MIPS64R2 | INSN_OCTEONP, mips_cp0_names_numeric,
+    ISA_MIPS64R2 | INSN_OCTEONP, 0, mips_cp0_names_numeric,
     NULL, 0, mips_hwr_names_numeric },
 
   { "octeon2",   1, bfd_mach_mips_octeon2, CPU_OCTEON2,
-    ISA_MIPS64R2 | INSN_OCTEON2, mips_cp0_names_numeric,
+    ISA_MIPS64R2 | INSN_OCTEON2, 0, mips_cp0_names_numeric,
     NULL, 0, mips_hwr_names_numeric },
 
   { "xlr", 1, bfd_mach_mips_xlr, CPU_XLR,
-    ISA_MIPS64 | INSN_XLR,
+    ISA_MIPS64 | INSN_XLR, 0,
     mips_cp0_names_xlr,
     mips_cp0sel_names_xlr, ARRAY_SIZE (mips_cp0sel_names_xlr),
     mips_hwr_names_numeric },
@@ -648,14 +651,14 @@ const struct mips_arch_choice mips_arch_choices[] =
   /* XLP is mostly like XLR, with the prominent exception it is being
      MIPS64R2.  */
   { "xlp", 1, bfd_mach_mips_xlr, CPU_XLR,
-    ISA_MIPS64R2 | INSN_XLR,
+    ISA_MIPS64R2 | INSN_XLR, 0,
     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,
+  { "",                1, bfd_mach_mips16, CPU_MIPS16, ISA_MIPS3, 0,
     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
 };
 
@@ -664,6 +667,7 @@ const struct mips_arch_choice mips_arch_choices[] =
    values.  */
 static int mips_processor;
 static int mips_isa;
+static int mips_ase;
 static int micromips_ase;
 static const char * const *mips_gpr_names;
 static const char * const *mips_fpr_names;
@@ -769,6 +773,7 @@ set_default_mips_dis_options (struct disassemble_info *info)
   mips_isa = ISA_MIPS3;
   mips_processor = CPU_R3000;
   micromips_ase = 0;
+  mips_ase = 0;
   mips_gpr_names = mips_gpr_names_oldabi;
   mips_fpr_names = mips_fpr_names_numeric;
   mips_cp0_names = mips_cp0_names_numeric;
@@ -796,12 +801,14 @@ set_default_mips_dis_options (struct disassemble_info *info)
      FIXME: Where does mips_target_info come from?  */
   target_processor = mips_target_info.processor;
   mips_isa = mips_target_info.isa;
+  mips_ase = mips_target_info.ase;
 #else
   chosen_arch = choose_arch_by_number (info->mach);
   if (chosen_arch != NULL)
     {
       mips_processor = chosen_arch->processor;
       mips_isa = chosen_arch->isa;
+      mips_ase = chosen_arch->ase;
       mips_cp0_names = chosen_arch->cp0_names;
       mips_cp0sel_names = chosen_arch->cp0sel_names;
       mips_cp0sel_names_len = chosen_arch->cp0sel_names_len;
@@ -824,6 +831,14 @@ parse_mips_dis_option (const char *option, unsigned int len)
       no_aliases = 1;
       return;
     }
+
+  if (CONST_STRNEQ (option, "virt"))
+    {
+      mips_ase |= ASE_VIRT;
+      if (mips_isa & ISA_MIPS64R2)
+       mips_ase |= ASE_VIRT64;
+      return;
+    }
   
   /* Look for the = that delimits the end of the option name.  */
   for (i = 0; i < len; i++)
@@ -1066,6 +1081,10 @@ print_insn_args (const char *d,
              infprintf (is, "0x%x", msbd + 1);
              break;
 
+           case 'J':           /* hypcall operand */
+             infprintf (is, "0x%x", GET_OP (l, CODE10));
+             break;
+
            case 't': /* Coprocessor 0 reg name */
              infprintf (is, "%s", mips_cp0_names[GET_OP (l, RT)]);
              break;
@@ -1133,6 +1152,10 @@ print_insn_args (const char *d,
              infprintf (is, "%s", mips_fpr_names[GET_OP (l, FZ)]);
              break;
 
+           case 'j':   /* 9-bit signed offset in bit 7.  */
+             infprintf (is, "%d", GET_OP_S (l, EVAOFFSET));
+             break;
+
            default:
              /* xgettext:c-format */
              infprintf (is,
@@ -1273,7 +1296,9 @@ print_insn_args (const char *d,
        case 'U':
          {
            /* First check for both rd and rt being equal.  */
-           unsigned int reg = GET_OP (l, RD);
+           unsigned int reg;
+
+           reg = GET_OP (l, RD);
            if (reg == GET_OP (l, RT))
              infprintf (is, "%s", mips_gpr_names[reg]);
            else
@@ -1500,7 +1525,7 @@ print_insn_mips (bfd_vma memaddr,
              const char *d;
 
              /* We always allow to disassemble the jalx instruction.  */
-             if (!opcode_is_member (op, mips_isa, mips_processor)
+             if (!opcode_is_member (op, mips_isa, mips_ase, mips_processor)
                  && strcmp (op->name, "jalx"))
                continue;
 
@@ -2031,6 +2056,23 @@ print_mips16_insn_arg (char type,
     }
 }
 
+
+/* Check if the given address is the last word of a MIPS16 PLT entry.
+   This word is data and depending on the value it may interfere with
+   disassembly of further PLT entries.  We make use of the fact PLT
+   symbols are marked BSF_SYNTHETIC.  */
+static bfd_boolean
+is_mips16_plt_tail (struct disassemble_info *info, bfd_vma addr)
+{
+  if (info->symbols
+      && info->symbols[0]
+      && (info->symbols[0]->flags & BSF_SYNTHETIC)
+      && addr == bfd_asymbol_value (info->symbols[0]) + 12)
+    return TRUE;
+
+  return FALSE;
+}
+
 /* Disassemble mips16 instructions.  */
 
 static int
@@ -2038,7 +2080,7 @@ print_insn_mips16 (bfd_vma memaddr, struct disassemble_info *info)
 {
   const fprintf_ftype infprintf = info->fprintf_func;
   int status;
-  bfd_byte buffer[2];
+  bfd_byte buffer[4];
   int length;
   int insn;
   bfd_boolean use_extend;
@@ -2051,11 +2093,32 @@ print_insn_mips16 (bfd_vma memaddr, struct disassemble_info *info)
   info->insn_info_valid = 1;
   info->branch_delay_insns = 0;
   info->data_size = 0;
-  info->insn_type = dis_nonbranch;
   info->target = 0;
   info->target2 = 0;
 
-  status = (*info->read_memory_func) (memaddr, buffer, 2, info);
+  /* Decode PLT entry's GOT slot address word.  */
+  if (is_mips16_plt_tail (info, memaddr))
+    {
+      info->insn_type = dis_noninsn;
+      status = (*info->read_memory_func) (memaddr, buffer, 4, info);
+      if (status == 0)
+       {
+         unsigned int gotslot;
+
+         if (info->endian == BFD_ENDIAN_BIG)
+           gotslot = bfd_getb32 (buffer);
+         else
+           gotslot = bfd_getl32 (buffer);
+         infprintf (is, ".word\t0x%x", gotslot);
+
+         return 4;
+       }
+    }
+  else
+    {
+      info->insn_type = dis_nonbranch;
+      status = (*info->read_memory_func) (memaddr, buffer, 2, info);
+    }
   if (status != 0)
     {
       (*info->memory_error_func) (status, memaddr, info);
@@ -2533,8 +2596,12 @@ print_insn_micromips (bfd_vma memaddr, struct disassemble_info *info)
                    {
                    case 0x000000fc:                            /* mfc0  */
                    case 0x000002fc:                            /* mtc0  */
+                   case 0x000004fc:                            /* mfgc0  */
+                   case 0x000006fc:                            /* mtgc0  */
                    case 0x580000fc:                            /* dmfc0 */
                    case 0x580002fc:                            /* dmtc0 */
+                   case 0x580000e7:                            /* dmfgc0 */
+                   case 0x580002e7:                            /* dmtgc0 */
                      infprintf (is, "%s", mips_cp0_names[GET_OP (insn, RS)]);
                      break;
                    default:
@@ -2634,6 +2701,11 @@ print_insn_micromips (bfd_vma memaddr, struct disassemble_info *info)
                      infprintf (is, "0x%x", msbd + 1);
                      break;
 
+                   case 'j':   /* 9-bit signed offset in bit 0. */
+                     delta = GET_OP_S (insn, EVAOFFSET);
+                     infprintf (is, "%d", delta);
+                     break;
+
                    default:
                      /* xgettext:c-format */
                      infprintf (is,
@@ -2929,27 +3001,26 @@ print_insn_micromips (bfd_vma memaddr, struct disassemble_info *info)
 static bfd_boolean
 is_compressed_mode_p (struct disassemble_info *info)
 {
-  elf_symbol_type *symbol;
-  int pos;
   int i;
-
-  for (i = 0; i < info->num_symbols; i++)
-    {
-      pos = info->symtab_pos + i;
-
-      if (bfd_asymbol_flavour (info->symtab[pos]) != bfd_target_elf_flavour)
-       continue;
-
-      if (info->symtab[pos]->section != info->section)
-       continue;
-
-      symbol = (elf_symbol_type *) info->symtab[pos];
-      if ((!micromips_ase
-          && ELF_ST_IS_MIPS16 (symbol->internal_elf_sym.st_other))
-         || (micromips_ase
-             && ELF_ST_IS_MICROMIPS (symbol->internal_elf_sym.st_other)))
-           return 1;
-    }
+  int l;
+
+  for (i = info->symtab_pos, l = i + info->num_symbols; i < l; i++)
+    if (((info->symtab[i])->flags & BSF_SYNTHETIC) != 0
+       && ((!micromips_ase
+            && ELF_ST_IS_MIPS16 ((*info->symbols)->udata.i))
+           || (micromips_ase
+               && ELF_ST_IS_MICROMIPS ((*info->symbols)->udata.i))))
+      return 1;
+    else if (bfd_asymbol_flavour (info->symtab[i]) == bfd_target_elf_flavour
+             && info->symtab[i]->section == info->section)
+      {
+       elf_symbol_type *symbol = (elf_symbol_type *) info->symtab[i];
+       if ((!micromips_ase
+            && ELF_ST_IS_MIPS16 (symbol->internal_elf_sym.st_other))
+           || (micromips_ase
+               && ELF_ST_IS_MICROMIPS (symbol->internal_elf_sym.st_other)))
+         return 1;
+      }
 
   return 0;
 }
@@ -3031,6 +3102,9 @@ print_mips_disassembler_options (FILE *stream)
 The following MIPS specific disassembler options are supported for use\n\
 with the -M switch (multiple options should be separated by commas):\n"));
 
+  fprintf (stream, _("\n\
+  virt            Recognize the virtualization ASE instructions.\n"));
+
   fprintf (stream, _("\n\
   gpr-names=ABI            Print GPR names according to  specified ABI.\n\
                            Default: based on binary being disassembled.\n"));
This page took 0.029063 seconds and 4 git commands to generate.