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.
This commit is contained in:
Alan Modra 2020-01-15 16:07:16 +10:30
parent 131cb553d6
commit aad09917e0
2 changed files with 54 additions and 31 deletions

View 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> 2020-01-14 Sergey Belyashov <sergey.belyashov@gmail.com>
PR 25377 PR 25377

View file

@ -51,8 +51,11 @@ typedef enum
} }
indirect_t; indirect_t;
static int tic4x_version = 0; static unsigned long tic4x_version = 0;
static int tic4x_dp = 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 static int
tic4x_pc_offset (unsigned int op) tic4x_pc_offset (unsigned int op)
@ -130,28 +133,24 @@ tic4x_print_str (struct disassemble_info *info, const char *str)
static int static int
tic4x_print_register (struct disassemble_info *info, unsigned long regno) tic4x_print_register (struct disassemble_info *info, unsigned long regno)
{ {
static tic4x_register_t ** registertable = NULL;
unsigned int i; 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++) for (i = 0; i < tic3x_num_registers; i++)
registertable[tic3x_registers[i].regno] registernames[tic3x_registers[i].regno] = tic3x_registers[i].name;
= (tic4x_register_t *) (tic3x_registers + i);
if (IS_CPU_TIC4X (tic4x_version)) if (IS_CPU_TIC4X (tic4x_version))
{ {
/* Add C4x additional registers, overwriting /* Add C4x additional registers, overwriting
any C3x registers if necessary. */ any C3x registers if necessary. */
for (i = 0; i < tic4x_num_registers; i++) for (i = 0; i < tic4x_num_registers; i++)
registertable[tic4x_registers[i].regno] registernames[tic4x_registers[i].regno] = tic4x_registers[i].name;
= (tic4x_register_t *)(tic4x_registers + i);
} }
} }
if (regno > (IS_CPU_TIC4X (tic4x_version) ? TIC4X_REG_MAX : TIC3X_REG_MAX)) if (regno > (IS_CPU_TIC4X (tic4x_version) ? TIC4X_REG_MAX : TIC3X_REG_MAX))
return 0; return 0;
if (info != NULL) if (info != NULL)
(*info->fprintf_func) (info->stream, "%s", registertable[regno]->name); (*info->fprintf_func) (info->stream, "%s", registernames[regno]);
return 1; return 1;
} }
@ -687,42 +686,56 @@ tic4x_disassemble (unsigned long pc,
unsigned long instruction, unsigned long instruction,
struct disassemble_info *info) struct disassemble_info *info)
{ {
static tic4x_inst_t **optable = NULL;
static tic4x_inst_t **optable_special = NULL;
tic4x_inst_t *p; tic4x_inst_t *p;
int i; int i;
unsigned long tic4x_oplevel; unsigned long tic4x_oplevel;
if (tic4x_version != info->mach)
{
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 = (IS_CPU_TIC4X (tic4x_version)) ? OP_C4X : 0;
tic4x_oplevel |= OP_C3X | OP_LPWR | OP_IDLE2 | OP_ENH; 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 /* Install opcodes in reverse order so that preferred
forms overwrite synonyms. */ forms overwrite synonyms. */
for (i = tic4x_num_insts - 1; i >= 0; i--) 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); tic4x_oplevel);
/* We now need to remove the insn that are special from the /* We now need to remove the insn that are special from the
"normal" optable, to make the disasm search this extra list "normal" optable, to make the disasm search this extra list
for them. */ for them. */
for (i = 0; i < TIC4X_SPESOP_SIZE; i++) for (i = 0; i < TIC4X_SPESOP_SIZE; i++)
if (optable_special[i] != NULL) if (optab_special[i] != NULL)
optable[optable_special[i]->opcode >> (32 - TIC4X_HASH_SIZE)] = NULL; optab[optab_special[i]->opcode >> (32 - TIC4X_HASH_SIZE)] = NULL;
} }
/* See if we can pick up any loading of the DP register... */ /* See if we can pick up any loading of the DP register... */
if ((instruction >> 16) == 0x5070 || (instruction >> 16) == 0x1f70) if ((instruction >> 16) == 0x5070 || (instruction >> 16) == 0x1f70)
tic4x_dp = EXTRU (instruction, 15, 0); tic4x_dp = EXTRU (instruction, 15, 0);
p = optable[instruction >> (32 - TIC4X_HASH_SIZE)]; p = optab[instruction >> (32 - TIC4X_HASH_SIZE)];
if (p != NULL) if (p != NULL)
{ {
if (((instruction & p->opmask) == p->opcode) if (((instruction & p->opmask) == p->opcode)
@ -734,10 +747,10 @@ tic4x_disassemble (unsigned long pc,
else else
{ {
for (i = 0; i<TIC4X_SPESOP_SIZE; i++) for (i = 0; i<TIC4X_SPESOP_SIZE; i++)
if (optable_special[i] != NULL if (optab_special[i] != NULL
&& optable_special[i]->opcode == instruction) && optab_special[i]->opcode == instruction)
{ {
(*info->fprintf_func)(info->stream, "%s", optable_special[i]->name); (*info->fprintf_func)(info->stream, "%s", optab_special[i]->name);
break; break;
} }
if (i == TIC4X_SPESOP_SIZE) if (i == TIC4X_SPESOP_SIZE)