Use malloc/free in the dbgapi callbacks
[deliverable/binutils-gdb.git] / opcodes / xtensa-dis.c
index bf5f5bfa192c60d9add39a2ecf8458c289d3f144..a7f8d2b9f811f9ce53639c65972b4c6d761d1068 100644 (file)
 /* xtensa-dis.c.  Disassembly functions for Xtensa.
-   Copyright 2003 Free Software Foundation, Inc.
+   Copyright (C) 2003-2020 Free Software Foundation, Inc.
    Contributed by Bob Wilson at Tensilica, Inc. (bwilson@tensilica.com)
 
-   This file is part of GDB, GAS, and the GNU binutils.
+   This file is part of the GNU opcodes library.
 
-   GDB, GAS, and the GNU binutils are free software; you can redistribute
-   them and/or modify them under the terms of the GNU General Public
-   License as published by the Free Software Foundation; either version 2,
-   or (at your option) any later version.
+   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 3, or (at your option)
+   any later version.
 
-   GDB, GAS, and the GNU binutils are distributed in the hope that they
-   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 file; see the file COPYING.  If not, write to the Free
-   Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
-   USA.  */
+   You should have received a copy of the GNU General Public License
+   along with this file; see the file COPYING.  If not, write to the
+   Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
 
+#include "sysdep.h"
 #include <stdlib.h>
 #include <stdio.h>
 #include <sys/types.h>
 #include <string.h>
 #include "xtensa-isa.h"
 #include "ansidecl.h"
-#include "sysdep.h"
-#include "dis-asm.h"
+#include "libiberty.h"
+#include "bfd.h"
+#include "elf/xtensa.h"
+#include "disassemble.h"
 
 #include <setjmp.h>
 
+extern xtensa_isa xtensa_default_isa;
+
 #ifndef MAX
 #define MAX(a,b) (a > b ? a : b)
 #endif
 
-static char* state_names[256] =
+int show_raw_fields;
+
+struct dis_private
 {
-  "lbeg",                      /* 0 */
-  "lend",                      /* 1 */
-  "lcount",                    /* 2 */
-  "sar",                       /* 3 */
-  "br",                                /* 4 */
-
-  "reserved_5",                        /* 5 */
-  "reserved_6",                        /* 6 */
-  "reserved_7",                        /* 7 */
-
-  "av",                                /* 8 */
-  "avh",                       /* 9 */
-  "bv",                                /* 10 */
-  "sav",                       /* 11 */
-  "scompare1",                 /* 12 */
-
-  "reserved_13",               /* 13 */
-  "reserved_14",               /* 14 */
-  "reserved_15",               /* 15 */
-
-  "acclo",                     /* 16 */
-  "acchi",                     /* 17 */
-
-  "reserved_18",               /* 18 */
-  "reserved_19",               /* 19 */
-  "reserved_20",               /* 20 */
-  "reserved_21",               /* 21 */
-  "reserved_22",               /* 22 */
-  "reserved_23",               /* 23 */
-  "reserved_24",               /* 24 */
-  "reserved_25",               /* 25 */
-  "reserved_26",               /* 26 */
-  "reserved_27",               /* 27 */
-  "reserved_28",               /* 28 */
-  "reserved_29",               /* 29 */
-  "reserved_30",               /* 30 */
-  "reserved_31",               /* 31 */
-
-  "mr0",                       /* 32 */
-  "mr1",                       /* 33 */
-  "mr2",                       /* 34 */
-  "mr3",                       /* 35 */
-
-  "reserved_36",               /* 36 */
-  "reserved_37",               /* 37 */
-  "reserved_38",               /* 38 */
-  "reserved_39",               /* 39 */
-  "reserved_40",               /* 40 */
-  "reserved_41",               /* 41 */
-  "reserved_42",               /* 42 */
-  "reserved_43",               /* 43 */
-  "reserved_44",               /* 44 */
-  "reserved_45",               /* 45 */
-  "reserved_46",               /* 46 */
-  "reserved_47",               /* 47 */
-  "reserved_48",               /* 48 */
-  "reserved_49",               /* 49 */
-  "reserved_50",               /* 50 */
-  "reserved_51",               /* 51 */
-  "reserved_52",               /* 52 */
-  "reserved_53",               /* 53 */
-  "reserved_54",               /* 54 */
-  "reserved_55",               /* 55 */
-  "reserved_56",               /* 56 */
-  "reserved_57",               /* 57 */
-  "reserved_58",               /* 58 */
-  "reserved_59",               /* 59 */
-  "reserved_60",               /* 60 */
-  "reserved_61",               /* 61 */
-  "reserved_62",               /* 62 */
-  "reserved_63",               /* 63 */
-
-  "reserved_64",               /* 64 */
-  "reserved_65",               /* 65 */
-  "reserved_66",               /* 66 */
-  "reserved_67",               /* 67 */
-  "reserved_68",               /* 68 */
-  "reserved_69",               /* 69 */
-  "reserved_70",               /* 70 */
-  "reserved_71",               /* 71 */
-
-  "wb",                                /* 72 */
-  "ws",                                /* 73 */
-
-  "reserved_74",               /* 74 */
-  "reserved_75",               /* 75 */
-  "reserved_76",               /* 76 */
-  "reserved_77",               /* 77 */
-  "reserved_78",               /* 78 */
-  "reserved_79",               /* 79 */
-  "reserved_80",               /* 80 */
-  "reserved_81",               /* 81 */
-  "reserved_82",               /* 82 */
-
-  "ptevaddr",                  /* 83 */
-
-  "reserved_84",               /* 84 */
-  "reserved_85",               /* 85 */
-  "reserved_86",               /* 86 */
-  "reserved_87",               /* 87 */
-  "reserved_88",               /* 88 */
-  "reserved_89",               /* 89 */
-
-  "rasid",                     /* 90 */
-  "itlbcfg",                   /* 91 */
-  "dtlbcfg",                   /* 92 */
-
-  "reserved_93",               /* 93 */
-  "reserved_94",               /* 94 */
-  "reserved_95",               /* 95 */
-
-  "ibreakenable",              /* 96 */
-
-  "reserved_97",               /* 97 */
-
-  "cacheattr",                 /* 98 */
-
-  "reserved_99",               /* 99 */
-  "reserved_100",              /* 100 */
-  "reserved_101",              /* 101 */
-  "reserved_102",              /* 102 */
-  "reserved_103",              /* 103 */
-
-  "ddr",                       /* 104 */
-
-  "reserved_105",              /* 105 */
-  "reserved_106",              /* 106 */
-  "reserved_107",              /* 107 */
-  "reserved_108",              /* 108 */
-  "reserved_109",              /* 109 */
-  "reserved_110",              /* 110 */
-  "reserved_111",              /* 111 */
-  "reserved_112",              /* 112 */
-  "reserved_113",              /* 113 */
-  "reserved_114",              /* 114 */
-  "reserved_115",              /* 115 */
-  "reserved_116",              /* 116 */
-  "reserved_117",              /* 117 */
-  "reserved_118",              /* 118 */
-  "reserved_119",              /* 119 */
-  "reserved_120",              /* 120 */
-  "reserved_121",              /* 121 */
-  "reserved_122",              /* 122 */
-  "reserved_123",              /* 123 */
-  "reserved_124",              /* 124 */
-  "reserved_125",              /* 125 */
-  "reserved_126",              /* 126 */
-  "reserved_127",              /* 127 */
-
-  "ibreaka0",                  /* 128 */
-  "ibreaka1",                  /* 129 */
-  "ibreaka2",                  /* 130 */
-  "ibreaka3",                  /* 131 */
-  "ibreaka4",                  /* 132 */
-  "ibreaka5",                  /* 133 */
-  "ibreaka6",                  /* 134 */
-  "ibreaka7",                  /* 135 */
-  "ibreaka8",                  /* 136 */
-  "ibreaka9",                  /* 137 */
-  "ibreaka10",                 /* 138 */
-  "ibreaka11",                 /* 139 */
-  "ibreaka12",                 /* 140 */
-  "ibreaka13",                 /* 141 */
-  "ibreaka14",                 /* 142 */
-  "ibreaka15",                 /* 143 */
-                          
-  "dbreaka0",                  /* 144 */
-  "dbreaka1",                  /* 145 */
-  "dbreaka2",                  /* 146 */
-  "dbreaka3",                  /* 147 */
-  "dbreaka4",                  /* 148 */
-  "dbreaka5",                  /* 149 */
-  "dbreaka6",                  /* 150 */
-  "dbreaka7",                  /* 151 */
-  "dbreaka8",                  /* 152 */
-  "dbreaka9",                  /* 153 */
-  "dbreaka10",                 /* 154 */
-  "dbreaka11",                 /* 155 */
-  "dbreaka12",                 /* 156 */
-  "dbreaka13",                 /* 157 */
-  "dbreaka14",                 /* 158 */
-  "dbreaka15",                 /* 159 */
-                          
-  "dbreakc0",                  /* 160 */
-  "dbreakc1",                  /* 161 */
-  "dbreakc2",                  /* 162 */
-  "dbreakc3",                  /* 163 */
-  "dbreakc4",                  /* 164 */
-  "dbreakc5",                  /* 165 */
-  "dbreakc6",                  /* 166 */
-  "dbreakc7",                  /* 167 */
-  "dbreakc8",                  /* 168 */
-  "dbreakc9",                  /* 169 */
-  "dbreakc10",                 /* 170 */
-  "dbreakc11",                 /* 171 */
-  "dbreakc12",                 /* 172 */
-  "dbreakc13",                 /* 173 */
-  "dbreakc14",                 /* 174 */
-  "dbreakc15",                 /* 175 */
-
-  "reserved_176",              /* 176 */
-
-  "epc1",                      /* 177 */
-  "epc2",                      /* 178 */
-  "epc3",                      /* 179 */
-  "epc4",                      /* 180 */
-  "epc5",                      /* 181 */
-  "epc6",                      /* 182 */
-  "epc7",                      /* 183 */
-  "epc8",                      /* 184 */
-  "epc9",                      /* 185 */
-  "epc10",                     /* 186 */
-  "epc11",                     /* 187 */
-  "epc12",                     /* 188 */
-  "epc13",                     /* 189 */
-  "epc14",                     /* 190 */
-  "epc15",                     /* 191 */
-  "depc",                      /* 192 */
-
-  "reserved_193",              /* 193 */
-
-  "eps2",                      /* 194 */
-  "eps3",                      /* 195 */
-  "eps4",                      /* 196 */
-  "eps5",                      /* 197 */
-  "eps6",                      /* 198 */
-  "eps7",                      /* 199 */
-  "eps8",                      /* 200 */
-  "eps9",                      /* 201 */
-  "eps10",                     /* 202 */
-  "eps11",                     /* 203 */
-  "eps12",                     /* 204 */
-  "eps13",                     /* 205 */
-  "eps14",                     /* 206 */
-  "eps15",                     /* 207 */
-
-  "reserved_208",              /* 208 */
-
-  "excsave1",                  /* 209 */
-  "excsave2",                  /* 210 */
-  "excsave3",                  /* 211 */
-  "excsave4",                  /* 212 */
-  "excsave5",                  /* 213 */
-  "excsave6",                  /* 214 */
-  "excsave7",                  /* 215 */
-  "excsave8",                  /* 216 */
-  "excsave9",                  /* 217 */
-  "excsave10",                 /* 218 */
-  "excsave11",                 /* 219 */
-  "excsave12",                 /* 220 */
-  "excsave13",                 /* 221 */
-  "excsave14",                 /* 222 */
-  "excsave15",                 /* 223 */
-  "cpenable",                  /* 224 */
-
-  "reserved_225",              /* 225 */
-
-  "interrupt",                 /* 226 */
-  "interrupt2",                        /* 227 */
-  "intenable",                 /* 228 */
-
-  "reserved_229",              /* 229 */
-
-  "ps",                                /* 230 */
-
-  "reserved_231",              /* 231 */
-
-  "exccause",                  /* 232 */
-  "debugcause",                        /* 233 */
-  "ccount",                    /* 234 */
-  "prid",                      /* 235 */
-  "icount",                    /* 236 */
-  "icountlvl",                         /* 237 */
-  "excvaddr",                  /* 238 */
-
-  "reserved_239",              /* 239 */
-
-  "ccompare0",                 /* 240 */
-  "ccompare1",                 /* 241 */
-  "ccompare2",                 /* 242 */
-  "ccompare3",                 /* 243 */
-
-  "misc0",                     /* 244 */
-  "misc1",                     /* 245 */
-  "misc2",                     /* 246 */
-  "misc3",                     /* 247 */
-
-  "reserved_248",              /* 248 */
-  "reserved_249",              /* 249 */
-  "reserved_250",              /* 250 */
-  "reserved_251",              /* 251 */
-  "reserved_252",              /* 252 */
-  "reserved_253",              /* 253 */
-  "reserved_254",              /* 254 */
-  "reserved_255",              /* 255 */
+  bfd_byte *byte_buf;
+  OPCODES_SIGJMP_BUF bailout;
+  /* Persistent fields, valid for last_section only.  */
+  asection *last_section;
+  property_table_entry *insn_table_entries;
+  int insn_table_entry_count;
+  /* Cached property table search position.  */
+  bfd_vma insn_table_cur_addr;
+  int insn_table_cur_idx;
 };
 
+static void
+xtensa_coalesce_insn_tables (struct dis_private *priv)
+{
+  const int mask = ~(XTENSA_PROP_DATA | XTENSA_PROP_NO_TRANSFORM);
+  int count = priv->insn_table_entry_count;
+  int i, j;
 
-int show_raw_fields;
+  /* Loop over all entries, combining adjacent ones that differ only in
+     the flag bits XTENSA_PROP_DATA and XTENSA_PROP_NO_TRANSFORM.  */
 
-static int fetch_data
-  PARAMS ((struct disassemble_info *info, bfd_vma memaddr, int numBytes));
-static void print_xtensa_operand
-  PARAMS ((bfd_vma, struct disassemble_info *, xtensa_operand,
-          unsigned operand_val, int print_sr_name));
+  for (i = j = 0; j < count; ++i)
+    {
+      property_table_entry *entry = priv->insn_table_entries + i;
 
-struct dis_private {
-  bfd_byte *byte_buf;
-  jmp_buf bailout;
-};
+      *entry = priv->insn_table_entries[j];
+
+      for (++j; j < count; ++j)
+       {
+         property_table_entry *next = priv->insn_table_entries + j;
+         int fill = xtensa_compute_fill_extra_space (entry);
+         int size = entry->size + fill;
+
+         if (entry->address + size == next->address)
+           {
+             int entry_flags = entry->flags & mask;
+             int next_flags = next->flags & mask;
+
+             if (next_flags == entry_flags)
+               entry->size = next->address - entry->address + next->size;
+             else
+               break;
+           }
+         else
+           {
+             break;
+           }
+       }
+    }
+  priv->insn_table_entry_count = i;
+}
+
+static property_table_entry *
+xtensa_find_table_entry (bfd_vma memaddr, struct disassemble_info *info)
+{
+  struct dis_private *priv = (struct dis_private *) info->private_data;
+  int i;
+
+  if (priv->insn_table_entries == NULL
+      || priv->insn_table_entry_count < 0)
+    return NULL;
+
+  if (memaddr < priv->insn_table_cur_addr)
+    priv->insn_table_cur_idx = 0;
+
+  for (i = priv->insn_table_cur_idx; i < priv->insn_table_entry_count; ++i)
+    {
+      property_table_entry *block = priv->insn_table_entries + i;
+
+      if (block->size != 0)
+       {
+         if ((memaddr >= block->address
+              && memaddr < block->address + block->size)
+             || memaddr < block->address)
+           {
+             priv->insn_table_cur_addr = memaddr;
+             priv->insn_table_cur_idx = i;
+             return block;
+           }
+       }
+    }
+  return NULL;
+}
+
+/* Check whether an instruction crosses an instruction block boundary
+   (according to property tables).
+   If it does, return 0 (doesn't fit), else return 1.  */
+
+static int
+xtensa_instruction_fits (bfd_vma memaddr, int size,
+                        property_table_entry *insn_block)
+{
+  unsigned max_size;
+
+  /* If no property table info, assume it fits.  */
+  if (insn_block == NULL || size <= 0)
+    return 1;
+
+  /* If too high, limit nextstop by the next insn address.  */
+  if (insn_block->address > memaddr)
+    {
+      /* memaddr is not in an instruction block, but is followed by one.  */
+      max_size = insn_block->address - memaddr;
+    }
+  else
+    {
+      /* memaddr is in an instruction block, go no further than the end.  */
+      max_size = insn_block->address + insn_block->size - memaddr;
+    }
+
+  /* Crossing a boundary, doesn't "fit".  */
+  if ((unsigned)size > max_size)
+    return 0;
+  return 1;
+}
 
 static int
-fetch_data (info, memaddr, numBytes)
-     struct disassemble_info *info;
-     bfd_vma memaddr;
-     int numBytes;
+fetch_data (struct disassemble_info *info, bfd_vma memaddr)
 {
   int length, status = 0;
   struct dis_private *priv = (struct dis_private *) info->private_data;
-  int insn_size = (numBytes != 0 ? numBytes :
-                  xtensa_insn_maxlength (xtensa_default_isa));
+  int insn_size = xtensa_isa_maxlength (xtensa_default_isa);
+
+  insn_size = MAX (insn_size, 4);
 
   /* Read the maximum instruction size, padding with zeros if we go past
      the end of the text section.  This code will automatically adjust
@@ -371,22 +181,21 @@ fetch_data (info, memaddr, numBytes)
        return length;
     }
   (*info->memory_error_func) (status, memaddr, info);
-  longjmp (priv->bailout, 1);
+  OPCODES_SIGLONGJMP (priv->bailout, 1);
   /*NOTREACHED*/
 }
 
 
 static void
-print_xtensa_operand (memaddr, info, opnd, operand_val, print_sr_name)
-     bfd_vma memaddr;
-     struct disassemble_info *info;
-     xtensa_operand opnd;
-     unsigned operand_val;
-     int print_sr_name;
+print_xtensa_operand (bfd_vma memaddr,
+                     struct disassemble_info *info,
+                     xtensa_opcode opc,
+                     int opnd,
+                     unsigned operand_val)
 {
-  char *kind = xtensa_operand_kind (opnd);
+  xtensa_isa isa = xtensa_default_isa;
   int signed_operand_val;
-    
+
   if (show_raw_fields)
     {
       if (operand_val < 0xa)
@@ -396,29 +205,42 @@ print_xtensa_operand (memaddr, info, opnd, operand_val, print_sr_name)
       return;
     }
 
-  operand_val = xtensa_operand_decode (opnd, operand_val);
+  (void) xtensa_operand_decode (isa, opc, opnd, &operand_val);
   signed_operand_val = (int) operand_val;
 
-  if (xtensa_operand_isPCRelative (opnd))
+  if (xtensa_operand_is_register (isa, opc, opnd) == 0)
     {
-      operand_val = xtensa_operand_undo_reloc (opnd, operand_val, memaddr);
-      info->target = operand_val;
-      (*info->print_address_func) (info->target, info);
-    }
-  else if (!strcmp (kind, "i"))
-    {
-      if (print_sr_name
-         && signed_operand_val >= 0
-         && signed_operand_val <= 255)
-       (*info->fprintf_func) (info->stream, "%s",
-                              state_names[signed_operand_val]);
-      else if ((signed_operand_val > -256) && (signed_operand_val < 256))
-       (*info->fprintf_func) (info->stream, "%d", signed_operand_val);
+      if (xtensa_operand_is_PCrelative (isa, opc, opnd) == 1)
+       {
+         (void) xtensa_operand_undo_reloc (isa, opc, opnd,
+                                           &operand_val, memaddr);
+         info->target = operand_val;
+         (*info->print_address_func) (info->target, info);
+       }
       else
-       (*info->fprintf_func) (info->stream, "0x%x",signed_operand_val);
+       {
+         if ((signed_operand_val > -256) && (signed_operand_val < 256))
+           (*info->fprintf_func) (info->stream, "%d", signed_operand_val);
+         else
+           (*info->fprintf_func) (info->stream, "0x%x", signed_operand_val);
+       }
     }
   else
-    (*info->fprintf_func) (info->stream, "%s%u", kind, operand_val);
+    {
+      int i = 1;
+      xtensa_regfile opnd_rf = xtensa_operand_regfile (isa, opc, opnd);
+      (*info->fprintf_func) (info->stream, "%s%u",
+                            xtensa_regfile_shortname (isa, opnd_rf),
+                            operand_val);
+      while (i < xtensa_operand_num_regs (isa, opc, opnd))
+       {
+         operand_val++;
+         (*info->fprintf_func) (info->stream, ":%s%u",
+                                xtensa_regfile_shortname (isa, opnd_rf),
+                                operand_val);
+         i++;
+       }
+    }
 }
 
 
@@ -426,25 +248,25 @@ print_xtensa_operand (memaddr, info, opnd, operand_val, print_sr_name)
    Returns length of the instruction in bytes.  */
 
 int
-print_insn_xtensa (memaddr, info)
-     bfd_vma memaddr;
-     struct disassemble_info *info;
+print_insn_xtensa (bfd_vma memaddr, struct disassemble_info *info)
 {
   unsigned operand_val;
-  int bytes_fetched, size, maxsize, i, noperands;
+  int bytes_fetched, size, maxsize, i, n, noperands, nslots;
   xtensa_isa isa;
   xtensa_opcode opc;
-  char *op_name;
-  int print_sr_name;
-  struct dis_private priv;
+  xtensa_format fmt;
+  static struct dis_private priv;
   static bfd_byte *byte_buf = NULL;
   static xtensa_insnbuf insn_buffer = NULL;
+  static xtensa_insnbuf slot_buffer = NULL;
+  int first, first_slot, valid_insn;
+  property_table_entry *insn_block;
 
   if (!xtensa_default_isa)
-    (void) xtensa_isa_init ();
+    xtensa_default_isa = xtensa_isa_init (0, 0);
 
   info->target = 0;
-  maxsize = xtensa_insn_maxlength (xtensa_default_isa);
+  maxsize = xtensa_isa_maxlength (xtensa_default_isa);
 
   /* Set bytes_per_line to control the amount of whitespace between the hex
      values and the opcode.  For Xtensa, we always print one "chunk" and we
@@ -460,64 +282,156 @@ print_insn_xtensa (memaddr, info)
 
   /* Allocate buffers the first time through.  */
   if (!insn_buffer)
-    insn_buffer = xtensa_insnbuf_alloc (xtensa_default_isa);
-  if (!byte_buf)
-    byte_buf = (bfd_byte *) malloc (MAX (maxsize, 4));
+    {
+      insn_buffer = xtensa_insnbuf_alloc (xtensa_default_isa);
+      slot_buffer = xtensa_insnbuf_alloc (xtensa_default_isa);
+      byte_buf = (bfd_byte *) xmalloc (MAX (maxsize, 4));
+    }
 
   priv.byte_buf = byte_buf;
 
-  info->private_data = (PTR) &priv;
-  if (setjmp (priv.bailout) != 0)
+  info->private_data = (void *) &priv;
+
+  /* Prepare instruction tables.  */
+
+  if (info->section != NULL)
+    {
+      asection *section = info->section;
+
+      if (priv.last_section != section)
+       {
+         bfd *abfd = section->owner;
+
+         if (priv.last_section != NULL)
+           {
+             /* Reset insn_table_entries.  */
+             priv.insn_table_entry_count = 0;
+             if (priv.insn_table_entries)
+               free (priv.insn_table_entries);
+             priv.insn_table_entries = NULL;
+           }
+         priv.last_section = section;
+
+         /* Read insn_table_entries.  */
+         priv.insn_table_entry_count =
+           xtensa_read_table_entries (abfd, section,
+                                      &priv.insn_table_entries,
+                                      XTENSA_PROP_SEC_NAME, FALSE);
+         if (priv.insn_table_entry_count == 0)
+           {
+             if (priv.insn_table_entries)
+               free (priv.insn_table_entries);
+             priv.insn_table_entries = NULL;
+             /* Backwards compatibility support.  */
+             priv.insn_table_entry_count =
+               xtensa_read_table_entries (abfd, section,
+                                          &priv.insn_table_entries,
+                                          XTENSA_INSN_SEC_NAME, FALSE);
+           }
+         priv.insn_table_cur_idx = 0;
+         xtensa_coalesce_insn_tables (&priv);
+       }
+      /* Else nothing to do, same section as last time.  */
+    }
+
+  if (OPCODES_SIGSETJMP (priv.bailout) != 0)
       /* Error return.  */
       return -1;
 
-  /* Don't set "isa" before the setjmp to keep the compiler from griping.  */
-  isa = xtensa_default_isa;
-
   /* Fetch the maximum size instruction.  */
-  bytes_fetched = fetch_data (info, memaddr, 0);
+  bytes_fetched = fetch_data (info, memaddr);
 
-  /* Copy the bytes into the decode buffer.  */
-  memset (insn_buffer, 0, (xtensa_insnbuf_size (isa) *
-                          sizeof (xtensa_insnbuf_word)));
-  xtensa_insnbuf_from_chars (isa, insn_buffer, priv.byte_buf);
+  insn_block = xtensa_find_table_entry (memaddr, info);
 
-  opc = xtensa_decode_insn (isa, insn_buffer);
-  if (opc == XTENSA_UNDEFINED
-      || ((size = xtensa_insn_length (isa, opc)) > bytes_fetched))
+  /* Don't set "isa" before the setjmp to keep the compiler from griping.  */
+  isa = xtensa_default_isa;
+  size = 0;
+  nslots = 0;
+  valid_insn = 0;
+  fmt = 0;
+  if (!insn_block || (insn_block->flags & XTENSA_PROP_INSN))
     {
-      (*info->fprintf_func) (info->stream, ".byte %#02x", priv.byte_buf[0]);
-      return 1;
+      /* Copy the bytes into the decode buffer.  */
+      memset (insn_buffer, 0, (xtensa_insnbuf_size (isa) *
+                              sizeof (xtensa_insnbuf_word)));
+      xtensa_insnbuf_from_chars (isa, insn_buffer, priv.byte_buf,
+                                bytes_fetched);
+
+      fmt = xtensa_format_decode (isa, insn_buffer);
+      if (fmt != XTENSA_UNDEFINED
+         && ((size = xtensa_format_length (isa, fmt)) <= bytes_fetched)
+         && xtensa_instruction_fits (memaddr, size, insn_block))
+       {
+         /* Make sure all the opcodes are valid.  */
+         valid_insn = 1;
+         nslots = xtensa_format_num_slots (isa, fmt);
+         for (n = 0; n < nslots; n++)
+           {
+             xtensa_format_get_slot (isa, fmt, n, insn_buffer, slot_buffer);
+             if (xtensa_opcode_decode (isa, fmt, n, slot_buffer)
+                 == XTENSA_UNDEFINED)
+               {
+                 valid_insn = 0;
+                 break;
+               }
+           }
+       }
     }
 
-  op_name = (char *) xtensa_opcode_name (isa, opc);
-  (*info->fprintf_func) (info->stream, "%s", op_name);
+  if (!valid_insn)
+    {
+      if (insn_block && (insn_block->flags & XTENSA_PROP_LITERAL)
+         && (memaddr & 3) == 0 && bytes_fetched >= 4)
+       {
+         return 4;
+       }
+      else
+       {
+         (*info->fprintf_func) (info->stream, ".byte %#02x", priv.byte_buf[0]);
+         return 1;
+       }
+    }
 
-  print_sr_name = (!strcasecmp (op_name, "wsr")
-                  || !strcasecmp (op_name, "xsr")
-                  || !strcasecmp (op_name, "rsr"));
+  if (nslots > 1)
+    (*info->fprintf_func) (info->stream, "{ ");
 
-  /* Print the operands (if any).  */
-  noperands = xtensa_num_operands (isa, opc);
-  if (noperands > 0)
+  first_slot = 1;
+  for (n = 0; n < nslots; n++)
     {
-      int first = 1;
+      if (first_slot)
+       first_slot = 0;
+      else
+       (*info->fprintf_func) (info->stream, "; ");
 
-      (*info->fprintf_func) (info->stream, "\t");
+      xtensa_format_get_slot (isa, fmt, n, insn_buffer, slot_buffer);
+      opc = xtensa_opcode_decode (isa, fmt, n, slot_buffer);
+      (*info->fprintf_func) (info->stream, "%s",
+                            xtensa_opcode_name (isa, opc));
+
+      /* Print the operands (if any).  */
+      noperands = xtensa_opcode_num_operands (isa, opc);
+      first = 1;
       for (i = 0; i < noperands; i++)
        {
-         xtensa_operand opnd = xtensa_get_operand (isa, opc, i);
-
+         if (xtensa_operand_is_visible (isa, opc, i) == 0)
+           continue;
          if (first)
-           first = 0;
+           {
+             (*info->fprintf_func) (info->stream, "\t");
+             first = 0;
+           }
          else
            (*info->fprintf_func) (info->stream, ", ");
-         operand_val = xtensa_operand_get_field (opnd, insn_buffer);
-         print_xtensa_operand (memaddr, info, opnd, operand_val,
-                               print_sr_name);
-        }
+         (void) xtensa_operand_get_field (isa, opc, i, fmt, n,
+                                          slot_buffer, &operand_val);
+
+         print_xtensa_operand (memaddr, info, opc, i, operand_val);
+       }
     }
 
+  if (nslots > 1)
+    (*info->fprintf_func) (info->stream, " }");
+
   info->bytes_per_chunk = size;
   info->display_endian = info->endian;
 
This page took 0.033005 seconds and 4 git commands to generate.