diff options
author | Andrew Burgess <andrew.burgess@embecosm.com> | 2016-03-28 16:04:58 +0100 |
---|---|---|
committer | Andrew Burgess <andrew.burgess@embecosm.com> | 2016-04-07 18:35:31 +0100 |
commit | b9b47ab79f7c3de0537cacfac061560d5811a84a (patch) | |
tree | cec1e75b0f58bc92d3e5f9b6929d562d24b4968e /gas | |
parent | da5be03929920c8aed305f9ffac19ce37177b3c6 (diff) | |
download | gdb-b9b47ab79f7c3de0537cacfac061560d5811a84a.zip gdb-b9b47ab79f7c3de0537cacfac061560d5811a84a.tar.gz gdb-b9b47ab79f7c3de0537cacfac061560d5811a84a.tar.bz2 |
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.
Diffstat (limited to 'gas')
-rw-r--r-- | gas/ChangeLog | 13 | ||||
-rw-r--r-- | gas/config/tc-arc.c | 68 |
2 files changed, 46 insertions, 35 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index d730b2a..f15549d 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,5 +1,18 @@ 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> + * config/tc-arc.c (struct arc_opcode_hash_entry): New structure. (arc_find_opcode): New function. (find_special_case_pseudo): Use arc_find_opcode. diff --git a/gas/config/tc-arc.c b/gas/config/tc-arc.c index 71c8f25..4c5af3f 100644 --- a/gas/config/tc-arc.c +++ b/gas/config/tc-arc.c @@ -564,27 +564,17 @@ static bfd_boolean assembling_insn = FALSE; /* Functions implementation. */ -/* Return a pointer to the first entry in ARC_OPCODE_HASH that matches - NAME, or NULL if there are no matching entries. */ +/* Return a pointer to ARC_OPCODE_HASH_ENTRY that identifies all + 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) { const struct arc_opcode_hash_entry *entry; - const struct arc_opcode *opcode; entry = hash_find (arc_opcode_hash, name); - if (entry != NULL) - { - if (entry->count > 1) - as_fatal (_("unable to lookup `%s', too many opcode chains"), - name); - opcode = *entry->opcode; - } - else - opcode = NULL; - - return opcode; + return entry; } /* 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. */ 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, int *pntok, struct arc_flags *first_pflag, int nflgs, int *pcpumatch) { + const struct arc_opcode *first_opcode = entry->opcode[0]; const struct arc_opcode *opcode = first_opcode; int ntok = *pntok; int got_cpu_match = 0; @@ -1423,6 +1414,10 @@ find_opcode_match (const struct arc_opcode *first_opcode, int bkntok; 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)); memcpy (bktok, tok, MAX_INSN_ARGS * sizeof (*tok)); bkntok = ntok; @@ -1873,7 +1868,7 @@ find_pseudo_insn (const char *opname, /* 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, int *ntok, expressionS *tok, @@ -1968,7 +1963,7 @@ find_special_case_pseudo (const char *opname, 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, int *nflgs, struct arc_flags *pflags) @@ -1978,7 +1973,7 @@ find_special_case_flag (const char *opname, unsigned flag_idx, flag_arr_idx; size_t flaglen, oplen; 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. */ for (i = 0; i < arc_num_flag_special; i++) @@ -2001,14 +1996,14 @@ find_special_case_flag (const char *opname, flaglen = strlen (flagnm); 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) break; memcpy (pflags[*nflgs].name, flagnm, flaglen); pflags[*nflgs].name[flaglen] = '\0'; (*nflgs)++; - return opcode; + return entry; } } } @@ -2017,21 +2012,21 @@ find_special_case_flag (const char *opname, /* Used to find special case opcode. */ -static const struct arc_opcode * +static const struct arc_opcode_hash_entry * find_special_case (const char *opname, int *nflgs, struct arc_flags *pflags, expressionS *tok, 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) - opcode = find_special_case_flag (opname, nflgs, pflags); + if (entry == NULL) + entry = find_special_case_flag (opname, nflgs, pflags); - return opcode; + return entry; } /* Given an opcode name, pre-tockenized set of argumenst and the @@ -2045,27 +2040,30 @@ assemble_tokens (const char *opname, int nflgs) { bfd_boolean found_something = FALSE; - const struct arc_opcode *opcode; + const struct arc_opcode_hash_entry *entry; int cpumatch = 1; /* Search opcodes. */ - opcode = arc_find_opcode (opname); + entry = arc_find_opcode (opname); /* Couldn't find opcode conventional way, try special cases. */ - if (!opcode) - opcode = find_special_case (opname, &nflgs, pflags, tok, &ntok); + if (entry == NULL) + 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", frag_now->fr_file, frag_now->fr_line, opcode->name, opcode->opcode); - found_something = TRUE; - opcode = find_opcode_match (opcode, tok, &ntok, pflags, nflgs, &cpumatch); - if (opcode) + opcode = find_opcode_match (entry, tok, &ntok, pflags, + nflgs, &cpumatch); + if (opcode != NULL) { struct arc_insn insn; + assemble_insn (opcode, tok, ntok, pflags, nflgs, &insn); emit_insn (&insn); return; |