]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
tic4x disassembly static variables
authorAlan Modra <amodra@gmail.com>
Wed, 15 Jan 2020 05:37:16 +0000 (16:07 +1030)
committerAlan Modra <amodra@gmail.com>
Wed, 15 Jan 2020 13:31:13 +0000 (00:01 +1030)
tic4x uses a number of static variables for tables that are generated
depending on the current machine (tic4x vs. tic3x).  However, it is
possible to change the machine from one invocation of print_insn_tic4x
to the next.  This patch throws away the old state if that happens,
and uses a relatively small known size array of register names rather
than a malloc'd table.

* tic4x-dis.c (tic4x_version): Make unsigned long.
(optab, optab_special, registernames): New file scope vars.
(tic4x_print_register): Set up registernames rather than
malloc'd registertable.
(tic4x_disassemble): Delete optable and optable_special.  Use
optab and optab_special instead.  Throw away old optab,
optab_special and registernames when info->mach changes.

opcodes/ChangeLog
opcodes/tic4x-dis.c

index accd25a0d86bf32be71da17f6c71017b3d258e2b..e7e963397adb1a8324a9120cc42dabc61b12c826 100644 (file)
@@ -1,3 +1,13 @@
+2020-01-15  Alan Modra  <amodra@gmail.com>
+
+       * tic4x-dis.c (tic4x_version): Make unsigned long.
+       (optab, optab_special, registernames): New file scope vars.
+       (tic4x_print_register): Set up registernames rather than
+       malloc'd registertable.
+       (tic4x_disassemble): Delete optable and optable_special.  Use
+       optab and optab_special instead.  Throw away old optab,
+       optab_special and registernames when info->mach changes.
+
 2020-01-14  Sergey Belyashov  <sergey.belyashov@gmail.com>
 
        PR 25377
index 34e270b71387ff53fa7139e04c9ae59f3fc37598..33d75c878b8cf5fd75e22899b480259becf8d36d 100644 (file)
@@ -51,8 +51,11 @@ typedef enum
 }
 indirect_t;
 
-static int tic4x_version = 0;
+static unsigned long tic4x_version = 0;
 static int tic4x_dp = 0;
+static tic4x_inst_t **optab = NULL;
+static tic4x_inst_t **optab_special = NULL;
+static const char *registernames[REG_TABLE_SIZE];
 
 static int
 tic4x_pc_offset (unsigned int op)
@@ -130,28 +133,24 @@ tic4x_print_str (struct disassemble_info *info, const char *str)
 static int
 tic4x_print_register (struct disassemble_info *info, unsigned long regno)
 {
-  static tic4x_register_t ** registertable = NULL;
   unsigned int i;
 
-  if (registertable == NULL)
+  if (registernames[REG_R0] == NULL)
     {
-      registertable = xmalloc (sizeof (tic4x_register_t *) * REG_TABLE_SIZE);
       for (i = 0; i < tic3x_num_registers; i++)
-       registertable[tic3x_registers[i].regno]
-         = (tic4x_register_t *) (tic3x_registers + i);
+       registernames[tic3x_registers[i].regno] = tic3x_registers[i].name;
       if (IS_CPU_TIC4X (tic4x_version))
        {
          /* Add C4x additional registers, overwriting
             any C3x registers if necessary.  */
          for (i = 0; i < tic4x_num_registers; i++)
-           registertable[tic4x_registers[i].regno]
-             = (tic4x_register_t *)(tic4x_registers + i);
+           registernames[tic4x_registers[i].regno] = tic4x_registers[i].name;
        }
     }
   if (regno > (IS_CPU_TIC4X (tic4x_version) ? TIC4X_REG_MAX : TIC3X_REG_MAX))
     return 0;
   if (info != NULL)
-    (*info->fprintf_func) (info->stream, "%s", registertable[regno]->name);
+    (*info->fprintf_func) (info->stream, "%s", registernames[regno]);
   return 1;
 }
 
@@ -687,61 +686,75 @@ tic4x_disassemble (unsigned long pc,
                   unsigned long instruction,
                   struct disassemble_info *info)
 {
-  static tic4x_inst_t **optable = NULL;
-  static tic4x_inst_t **optable_special = NULL;
   tic4x_inst_t *p;
   int i;
   unsigned long tic4x_oplevel;
 
-  tic4x_version = info->mach;
+  if (tic4x_version != info->mach)
+    {
+      tic4x_version = info->mach;
+      /* Don't stash anything from a previous call using a different
+        machine.  */
+      if (optab)
+       {
+         free (optab);
+         optab = NULL;
+       }
+      if (optab_special)
+       {
+         free (optab_special);
+         optab_special = NULL;
+       }
+      registernames[REG_R0] = NULL;
+    }
 
   tic4x_oplevel  = (IS_CPU_TIC4X (tic4x_version)) ? OP_C4X : 0;
   tic4x_oplevel |= OP_C3X | OP_LPWR | OP_IDLE2 | OP_ENH;
 
-  if (optable == NULL)
+  if (optab == NULL)
     {
-      optable = xcalloc (sizeof (tic4x_inst_t *), (1 << TIC4X_HASH_SIZE));
+      optab = xcalloc (sizeof (tic4x_inst_t *), (1 << TIC4X_HASH_SIZE));
 
-      optable_special = xcalloc (sizeof (tic4x_inst_t *), TIC4X_SPESOP_SIZE);
+      optab_special = xcalloc (sizeof (tic4x_inst_t *), TIC4X_SPESOP_SIZE);
 
       /* Install opcodes in reverse order so that preferred
         forms overwrite synonyms.  */
       for (i = tic4x_num_insts - 1; i >= 0; i--)
-        tic4x_hash_opcode (optable, optable_special, &tic4x_insts[i],
+       tic4x_hash_opcode (optab, optab_special, &tic4x_insts[i],
                           tic4x_oplevel);
 
       /* We now need to remove the insn that are special from the
-         "normal" optable, to make the disasm search this extra list
-         for them.  */
+        "normal" optable, to make the disasm search this extra list
+        for them.  */
       for (i = 0; i < TIC4X_SPESOP_SIZE; i++)
-        if (optable_special[i] != NULL)
-          optable[optable_special[i]->opcode >> (32 - TIC4X_HASH_SIZE)] = NULL;
+       if (optab_special[i] != NULL)
+         optab[optab_special[i]->opcode >> (32 - TIC4X_HASH_SIZE)] = NULL;
     }
 
   /* See if we can pick up any loading of the DP register...  */
   if ((instruction >> 16) == 0x5070 || (instruction >> 16) == 0x1f70)
     tic4x_dp = EXTRU (instruction, 15, 0);
 
-  p = optable[instruction >> (32 - TIC4X_HASH_SIZE)];
+  p = optab[instruction >> (32 - TIC4X_HASH_SIZE)];
   if (p != NULL)
     {
       if (((instruction & p->opmask) == p->opcode)
-           && tic4x_print_op (NULL, instruction, p, pc))
-        tic4x_print_op (info, instruction, p, pc);
+         && tic4x_print_op (NULL, instruction, p, pc))
+       tic4x_print_op (info, instruction, p, pc);
       else
-        (*info->fprintf_func) (info->stream, "%08lx", instruction);
+       (*info->fprintf_func) (info->stream, "%08lx", instruction);
     }
   else
     {
       for (i = 0; i<TIC4X_SPESOP_SIZE; i++)
-        if (optable_special[i] != NULL
-            && optable_special[i]->opcode == instruction)
-          {
-            (*info->fprintf_func)(info->stream, "%s", optable_special[i]->name);
-            break;
-          }
+       if (optab_special[i] != NULL
+           && optab_special[i]->opcode == instruction)
+         {
+           (*info->fprintf_func)(info->stream, "%s", optab_special[i]->name);
+           break;
+         }
       if (i == TIC4X_SPESOP_SIZE)
-        (*info->fprintf_func) (info->stream, "%08lx", instruction);
+       (*info->fprintf_func) (info->stream, "%08lx", instruction);
     }
 
   /* Return size of insn in words.  */