gas/arc: Additional work to support multiple arc_opcode chains

Building on earlier commits, this commit moves along support for having
multiple arc_opcode entries in the arc_opcodes table that have the same
mnemonic (name) field, but are not stored in a contiguous block in the
table.

In this commit we support looking up the arc_opcode_hash_entry from the
hash table, and passing this along to the find_opcode_match function,
which then finds the specific arc_opcode that we're assembling.  We
still don't actually support the multiple chains of arc_opcode entries
in this commit, but the limitation is now isolated to the
find_opcode_match function.

There is no user visible change after this commit.

gas/ChangeLog:

	* config/tc-arc.c (arc_find_opcode): Now returns
	arc_opcode_hash_entry pointer.
	(find_opcode_match): Update argument type, extract arc_opcode from
	incoming arc_opcode_hash_entry.
	(find_special_case_pseudo): Update return type.
	(find_special_case_flag): Update return type.
	(find_special_case): Update return type.
	(assemble_tokens): Lookup arc_opcode_hash_entry based on
	instruction mnemonic, then use find_opcode_match to identify
	specific arc_opcode.
This commit is contained in:
Andrew Burgess 2016-03-28 16:04:58 +01:00
parent da5be03929
commit b9b47ab79f
2 changed files with 46 additions and 35 deletions

View File

@ -1,3 +1,16 @@
2016-04-07 Andrew Burgess <andrew.burgess@embecosm.com>
* config/tc-arc.c (arc_find_opcode): Now returns
arc_opcode_hash_entry pointer.
(find_opcode_match): Update argument type, extract arc_opcode from
incoming arc_opcode_hash_entry.
(find_special_case_pseudo): Update return type.
(find_special_case_flag): Update return type.
(find_special_case): Update return type.
(assemble_tokens): Lookup arc_opcode_hash_entry based on
instruction mnemonic, then use find_opcode_match to identify
specific arc_opcode.
2016-04-07 Andrew Burgess <andrew.burgess@embecosm.com> 2016-04-07 Andrew Burgess <andrew.burgess@embecosm.com>
* config/tc-arc.c (struct arc_opcode_hash_entry): New structure. * config/tc-arc.c (struct arc_opcode_hash_entry): New structure.

View File

@ -564,27 +564,17 @@ static bfd_boolean assembling_insn = FALSE;
/* Functions implementation. */ /* Functions implementation. */
/* Return a pointer to the first entry in ARC_OPCODE_HASH that matches /* Return a pointer to ARC_OPCODE_HASH_ENTRY that identifies all
NAME, or NULL if there are no matching entries. */ ARC_OPCODE entries in ARC_OPCODE_HASH that match NAME, or NULL if there
are no matching entries in ARC_OPCODE_HASH. */
static const struct arc_opcode * static const struct arc_opcode_hash_entry *
arc_find_opcode (const char *name) arc_find_opcode (const char *name)
{ {
const struct arc_opcode_hash_entry *entry; const struct arc_opcode_hash_entry *entry;
const struct arc_opcode *opcode;
entry = hash_find (arc_opcode_hash, name); entry = hash_find (arc_opcode_hash, name);
if (entry != NULL) return entry;
{
if (entry->count > 1)
as_fatal (_("unable to lookup `%s', too many opcode chains"),
name);
opcode = *entry->opcode;
}
else
opcode = NULL;
return opcode;
} }
/* Like md_number_to_chars but used for limms. The 4-byte limm value, /* Like md_number_to_chars but used for limms. The 4-byte limm value,
@ -1409,13 +1399,14 @@ check_cpu_feature (insn_subclass_t sc)
syntax match. */ syntax match. */
static const struct arc_opcode * static const struct arc_opcode *
find_opcode_match (const struct arc_opcode *first_opcode, find_opcode_match (const struct arc_opcode_hash_entry *entry,
expressionS *tok, expressionS *tok,
int *pntok, int *pntok,
struct arc_flags *first_pflag, struct arc_flags *first_pflag,
int nflgs, int nflgs,
int *pcpumatch) int *pcpumatch)
{ {
const struct arc_opcode *first_opcode = entry->opcode[0];
const struct arc_opcode *opcode = first_opcode; const struct arc_opcode *opcode = first_opcode;
int ntok = *pntok; int ntok = *pntok;
int got_cpu_match = 0; int got_cpu_match = 0;
@ -1423,6 +1414,10 @@ find_opcode_match (const struct arc_opcode *first_opcode,
int bkntok; int bkntok;
expressionS emptyE; expressionS emptyE;
gas_assert (entry->count > 0);
if (entry->count > 1)
as_fatal (_("unable to lookup `%s', too many opcode chains"),
first_opcode->name);
memset (&emptyE, 0, sizeof (emptyE)); memset (&emptyE, 0, sizeof (emptyE));
memcpy (bktok, tok, MAX_INSN_ARGS * sizeof (*tok)); memcpy (bktok, tok, MAX_INSN_ARGS * sizeof (*tok));
bkntok = ntok; bkntok = ntok;
@ -1873,7 +1868,7 @@ find_pseudo_insn (const char *opname,
/* Assumes the expressionS *tok is of sufficient size. */ /* Assumes the expressionS *tok is of sufficient size. */
static const struct arc_opcode * static const struct arc_opcode_hash_entry *
find_special_case_pseudo (const char *opname, find_special_case_pseudo (const char *opname,
int *ntok, int *ntok,
expressionS *tok, expressionS *tok,
@ -1968,7 +1963,7 @@ find_special_case_pseudo (const char *opname,
return arc_find_opcode (pseudo_insn->mnemonic_r); return arc_find_opcode (pseudo_insn->mnemonic_r);
} }
static const struct arc_opcode * static const struct arc_opcode_hash_entry *
find_special_case_flag (const char *opname, find_special_case_flag (const char *opname,
int *nflgs, int *nflgs,
struct arc_flags *pflags) struct arc_flags *pflags)
@ -1978,7 +1973,7 @@ find_special_case_flag (const char *opname,
unsigned flag_idx, flag_arr_idx; unsigned flag_idx, flag_arr_idx;
size_t flaglen, oplen; size_t flaglen, oplen;
const struct arc_flag_special *arc_flag_special_opcode; const struct arc_flag_special *arc_flag_special_opcode;
const struct arc_opcode *opcode; const struct arc_opcode_hash_entry *entry;
/* Search for special case instruction. */ /* Search for special case instruction. */
for (i = 0; i < arc_num_flag_special; i++) for (i = 0; i < arc_num_flag_special; i++)
@ -2001,14 +1996,14 @@ find_special_case_flag (const char *opname,
flaglen = strlen (flagnm); flaglen = strlen (flagnm);
if (strcmp (opname + oplen, flagnm) == 0) if (strcmp (opname + oplen, flagnm) == 0)
{ {
opcode = arc_find_opcode (arc_flag_special_opcode->name); entry = arc_find_opcode (arc_flag_special_opcode->name);
if (*nflgs + 1 > MAX_INSN_FLGS) if (*nflgs + 1 > MAX_INSN_FLGS)
break; break;
memcpy (pflags[*nflgs].name, flagnm, flaglen); memcpy (pflags[*nflgs].name, flagnm, flaglen);
pflags[*nflgs].name[flaglen] = '\0'; pflags[*nflgs].name[flaglen] = '\0';
(*nflgs)++; (*nflgs)++;
return opcode; return entry;
} }
} }
} }
@ -2017,21 +2012,21 @@ find_special_case_flag (const char *opname,
/* Used to find special case opcode. */ /* Used to find special case opcode. */
static const struct arc_opcode * static const struct arc_opcode_hash_entry *
find_special_case (const char *opname, find_special_case (const char *opname,
int *nflgs, int *nflgs,
struct arc_flags *pflags, struct arc_flags *pflags,
expressionS *tok, expressionS *tok,
int *ntok) int *ntok)
{ {
const struct arc_opcode *opcode; const struct arc_opcode_hash_entry *entry;
opcode = find_special_case_pseudo (opname, ntok, tok, nflgs, pflags); entry = find_special_case_pseudo (opname, ntok, tok, nflgs, pflags);
if (opcode == NULL) if (entry == NULL)
opcode = find_special_case_flag (opname, nflgs, pflags); entry = find_special_case_flag (opname, nflgs, pflags);
return opcode; return entry;
} }
/* Given an opcode name, pre-tockenized set of argumenst and the /* Given an opcode name, pre-tockenized set of argumenst and the
@ -2045,27 +2040,30 @@ assemble_tokens (const char *opname,
int nflgs) int nflgs)
{ {
bfd_boolean found_something = FALSE; bfd_boolean found_something = FALSE;
const struct arc_opcode *opcode; const struct arc_opcode_hash_entry *entry;
int cpumatch = 1; int cpumatch = 1;
/* Search opcodes. */ /* Search opcodes. */
opcode = arc_find_opcode (opname); entry = arc_find_opcode (opname);
/* Couldn't find opcode conventional way, try special cases. */ /* Couldn't find opcode conventional way, try special cases. */
if (!opcode) if (entry == NULL)
opcode = find_special_case (opname, &nflgs, pflags, tok, &ntok); entry = find_special_case (opname, &nflgs, pflags, tok, &ntok);
if (opcode) if (entry != NULL)
{ {
const struct arc_opcode *opcode;
pr_debug ("%s:%d: assemble_tokens: %s trying opcode 0x%08X\n", pr_debug ("%s:%d: assemble_tokens: %s trying opcode 0x%08X\n",
frag_now->fr_file, frag_now->fr_line, opcode->name, frag_now->fr_file, frag_now->fr_line, opcode->name,
opcode->opcode); opcode->opcode);
found_something = TRUE; found_something = TRUE;
opcode = find_opcode_match (opcode, tok, &ntok, pflags, nflgs, &cpumatch); opcode = find_opcode_match (entry, tok, &ntok, pflags,
if (opcode) nflgs, &cpumatch);
if (opcode != NULL)
{ {
struct arc_insn insn; struct arc_insn insn;
assemble_insn (opcode, tok, ntok, pflags, nflgs, &insn); assemble_insn (opcode, tok, ntok, pflags, nflgs, &insn);
emit_insn (&insn); emit_insn (&insn);
return; return;