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:
parent
131cb553d6
commit
aad09917e0
2 changed files with 54 additions and 31 deletions
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue