From b9b47ab79f7c3de0537cacfac061560d5811a84a Mon Sep 17 00:00:00 2001 From: Andrew Burgess Date: Mon, 28 Mar 2016 16:04:58 +0100 Subject: [PATCH] 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. --- gas/ChangeLog | 13 +++++++++ gas/config/tc-arc.c | 68 ++++++++++++++++++++++----------------------- 2 files changed, 46 insertions(+), 35 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index d730b2a934a..f15549d818d 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,16 @@ +2016-04-07 Andrew Burgess + + * 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 * config/tc-arc.c (struct arc_opcode_hash_entry): New structure. diff --git a/gas/config/tc-arc.c b/gas/config/tc-arc.c index 71c8f253b27..4c5af3f85f4 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; -- 2.30.2