summaryrefslogtreecommitdiff
path: root/opcodes/tic4x-dis.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2020-01-15 16:07:16 +1030
committerAlan Modra <amodra@gmail.com>2020-01-16 00:01:13 +1030
commitaad09917e04b33da463f1703aab8d057cfe3f54e (patch)
treedcf1d4382c6f91f58bb66771a768baa7489763ce /opcodes/tic4x-dis.c
parent131cb553d6d10412b20cf49bb0e3a5e736a90a36 (diff)
downloadbinutils-gdb-aad09917e04b33da463f1703aab8d057cfe3f54e.tar.gz
tic4x disassembly static variables
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.
Diffstat (limited to 'opcodes/tic4x-dis.c')
-rw-r--r--opcodes/tic4x-dis.c75
1 files changed, 44 insertions, 31 deletions
diff --git a/opcodes/tic4x-dis.c b/opcodes/tic4x-dis.c
index 34e270b7138..33d75c878b8 100644
--- a/opcodes/tic4x-dis.c
+++ b/opcodes/tic4x-dis.c
@@ -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. */