aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorClaudiu Zissulescu <claziss@gmail.com>2020-01-07 15:29:16 +0200
committerClaudiu Zissulescu <claziss@gmail.com>2020-01-07 15:29:31 +0200
commit2a1ebfb221f5f52a743b7ea4c504a7318956c49c (patch)
tree2cc322ae1838a24b87fcdf27dad55ada867968b2 /gas
parentbb82aefe17866cdcb996ae35a3895bb36b4d674b (diff)
downloadgdb-2a1ebfb221f5f52a743b7ea4c504a7318956c49c.zip
gdb-2a1ebfb221f5f52a743b7ea4c504a7318956c49c.tar.gz
gdb-2a1ebfb221f5f52a743b7ea4c504a7318956c49c.tar.bz2
[ARC] Improve parsing instruction operands.
We use gas' expression function to parse the operands of an instruction in a generic way. There are situations when we have labels and registers having the same name as well as the substraction sign doesn't always stands for the arithmetical operation but for the register range (e.g. enter instruction). This patch improves parsing symbols found in a instruction operand, cleans up code and avoids using default or undefined variables. gas/ xxxx-xx-xx Claudiu Zissulescu <claziss@synopsys.com> * config/tc-arc.c (parse_reloc_symbol): New function. (tokenize_arguments): Clean up, use parse_reloc_symbol function. (md_operand): Set X_md to absent. (arc_parse_name): Check for X_md.
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog7
-rw-r--r--gas/config/tc-arc.c201
2 files changed, 117 insertions, 91 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 5a16b91..1c61732 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,10 @@
+2020-01-07 Claudiu Zissulescu <claziss@synopsys.com>
+
+ * onfig/tc-arc.c (parse_reloc_symbol): New function.
+ (tokenize_arguments): Clean up, use parse_reloc_symbol function.
+ (md_operand): Set X_md to absent.
+ (arc_parse_name): Check for X_md.
+
2020-01-03 Sergey Belyashov <sergey.belyashov@gmail.com>
PR 25311
diff --git a/gas/config/tc-arc.c b/gas/config/tc-arc.c
index ffccfda..ed1e3fb 100644
--- a/gas/config/tc-arc.c
+++ b/gas/config/tc-arc.c
@@ -1092,6 +1092,102 @@ debug_exp (expressionS *t)
fflush (stderr);
}
+/* Helper for parsing an argument, used for sorting out the relocation
+ type. */
+
+static void
+parse_reloc_symbol (expressionS *resultP)
+{
+ char *reloc_name, c, *sym_name;
+ size_t len;
+ int i;
+ const struct arc_reloc_op_tag *r;
+ expressionS right;
+ symbolS *base;
+
+ /* A relocation operand has the following form
+ @identifier@relocation_type. The identifier is already in
+ tok! */
+ if (resultP->X_op != O_symbol)
+ {
+ as_bad (_("No valid label relocation operand"));
+ resultP->X_op = O_illegal;
+ return;
+ }
+
+ /* Parse @relocation_type. */
+ input_line_pointer++;
+ c = get_symbol_name (&reloc_name);
+ len = input_line_pointer - reloc_name;
+ if (len == 0)
+ {
+ as_bad (_("No relocation operand"));
+ resultP->X_op = O_illegal;
+ return;
+ }
+
+ /* Go through known relocation and try to find a match. */
+ r = &arc_reloc_op[0];
+ for (i = arc_num_reloc_op - 1; i >= 0; i--, r++)
+ if (len == r->length
+ && memcmp (reloc_name, r->name, len) == 0)
+ break;
+ if (i < 0)
+ {
+ as_bad (_("Unknown relocation operand: @%s"), reloc_name);
+ resultP->X_op = O_illegal;
+ return;
+ }
+
+ *input_line_pointer = c;
+ SKIP_WHITESPACE_AFTER_NAME ();
+ /* Extra check for TLS: base. */
+ if (*input_line_pointer == '@')
+ {
+ if (resultP->X_op_symbol != NULL
+ || resultP->X_op != O_symbol)
+ {
+ as_bad (_("Unable to parse TLS base: %s"),
+ input_line_pointer);
+ resultP->X_op = O_illegal;
+ return;
+ }
+ input_line_pointer++;
+ c = get_symbol_name (&sym_name);
+ base = symbol_find_or_make (sym_name);
+ resultP->X_op = O_subtract;
+ resultP->X_op_symbol = base;
+ restore_line_pointer (c);
+ right.X_add_number = 0;
+ }
+
+ if ((*input_line_pointer != '+')
+ && (*input_line_pointer != '-'))
+ right.X_add_number = 0;
+ else
+ {
+ /* Parse the constant of a complex relocation expression
+ like @identifier@reloc +/- const. */
+ if (! r->complex_expr)
+ {
+ as_bad (_("@%s is not a complex relocation."), r->name);
+ resultP->X_op = O_illegal;
+ return;
+ }
+ expression (&right);
+ if (right.X_op != O_constant)
+ {
+ as_bad (_("Bad expression: @%s + %s."),
+ r->name, input_line_pointer);
+ resultP->X_op = O_illegal;
+ return;
+ }
+ }
+
+ resultP->X_md = r->op;
+ resultP->X_add_number = right.X_add_number;
+}
+
/* Parse the arguments to an opcode. */
static int
@@ -1104,11 +1200,6 @@ tokenize_arguments (char *str,
bfd_boolean saw_arg = FALSE;
int brk_lvl = 0;
int num_args = 0;
- int i;
- size_t len;
- const struct arc_reloc_op_tag *r;
- expressionS tmpE;
- char *reloc_name, c;
memset (tok, 0, sizeof (*tok) * ntok);
@@ -1170,95 +1261,21 @@ tokenize_arguments (char *str,
goto err;
/* Parse @label. */
+ input_line_pointer++;
tok->X_op = O_symbol;
tok->X_md = O_absent;
expression (tok);
- if (*input_line_pointer != '@')
- goto normalsymbol; /* This is not a relocation. */
-
- relocationsym:
-
- /* A relocation operand has the following form
- @identifier@relocation_type. The identifier is already
- in tok! */
- if (tok->X_op != O_symbol)
- {
- as_bad (_("No valid label relocation operand"));
- goto err;
- }
-
- /* Parse @relocation_type. */
- input_line_pointer++;
- c = get_symbol_name (&reloc_name);
- len = input_line_pointer - reloc_name;
- if (len == 0)
- {
- as_bad (_("No relocation operand"));
- goto err;
- }
-
- /* Go through known relocation and try to find a match. */
- r = &arc_reloc_op[0];
- for (i = arc_num_reloc_op - 1; i >= 0; i--, r++)
- if (len == r->length
- && memcmp (reloc_name, r->name, len) == 0)
- break;
- if (i < 0)
- {
- as_bad (_("Unknown relocation operand: @%s"), reloc_name);
- goto err;
- }
- *input_line_pointer = c;
- SKIP_WHITESPACE_AFTER_NAME ();
- /* Extra check for TLS: base. */
if (*input_line_pointer == '@')
- {
- symbolS *base;
- if (tok->X_op_symbol != NULL
- || tok->X_op != O_symbol)
- {
- as_bad (_("Unable to parse TLS base: %s"),
- input_line_pointer);
- goto err;
- }
- input_line_pointer++;
- char *sym_name;
- c = get_symbol_name (&sym_name);
- base = symbol_find_or_make (sym_name);
- tok->X_op = O_subtract;
- tok->X_op_symbol = base;
- restore_line_pointer (c);
- tmpE.X_add_number = 0;
- }
- if ((*input_line_pointer != '+')
- && (*input_line_pointer != '-'))
- {
- tmpE.X_add_number = 0;
- }
- else
- {
- /* Parse the constant of a complex relocation expression
- like @identifier@reloc +/- const. */
- if (! r->complex_expr)
- {
- as_bad (_("@%s is not a complex relocation."), r->name);
- goto err;
- }
- expression (&tmpE);
- if (tmpE.X_op != O_constant)
- {
- as_bad (_("Bad expression: @%s + %s."),
- r->name, input_line_pointer);
- goto err;
- }
- }
-
- tok->X_md = r->op;
- tok->X_add_number = tmpE.X_add_number;
+ parse_reloc_symbol (tok);
debug_exp (tok);
+ if (tok->X_op == O_illegal
+ || tok->X_op == O_absent
+ || num_args == ntok)
+ goto err;
+
saw_comma = FALSE;
saw_arg = TRUE;
tok++;
@@ -1282,9 +1299,8 @@ tokenize_arguments (char *str,
identifier@relocation_type, if it is the case parse the
relocation type as well. */
if (*input_line_pointer == '@')
- goto relocationsym;
+ parse_reloc_symbol (tok);
- normalsymbol:
debug_exp (tok);
if (tok->X_op == O_illegal
@@ -3336,16 +3352,18 @@ md_atof (int type, char *litP, int *sizeP)
/* Called for any expression that can not be recognized. When the
function is called, `input_line_pointer' will point to the start of
- the expression. */
+ the expression. We use it when we have complex operations like
+ @label1 - @label2. */
void
-md_operand (expressionS *expressionP ATTRIBUTE_UNUSED)
+md_operand (expressionS *expressionP)
{
char *p = input_line_pointer;
if (*p == '@')
{
input_line_pointer++;
expressionP->X_op = O_symbol;
+ expressionP->X_md = O_absent;
expression (expressionP);
}
}
@@ -3364,7 +3382,8 @@ arc_parse_name (const char *name,
if (!assembling_insn)
return FALSE;
- if (e->X_op == O_symbol)
+ if (e->X_op == O_symbol
+ && e->X_md == O_absent)
return FALSE;
sym = hash_find (arc_reg_hash, name);