char *save = input_line_pointer;
char *buf = xstrdup (reg_string), *name;
symbolS *symbolP;
+ offsetT off;
input_line_pointer = buf;
get_symbol_name (&name);
symbolP = symbol_find (name);
- while (symbolP && symbol_equated_p (symbolP))
- {
- const expressionS *e = symbol_get_value_expression(symbolP);
-
- if (e->X_add_number)
- break;
- symbolP = e->X_add_symbol;
- }
- if (symbolP && S_GET_SEGMENT (symbolP) == reg_section)
+ symbolP = symbol_equated_to (symbolP, &off);
+ if (symbolP && off == 0 && S_GET_SEGMENT (symbolP) == reg_section)
{
const expressionS *e = symbol_get_value_expression (symbolP);
/* If the symbol is an alias for another name then use that.
If the symbol is an alias for a number, then return the number. */
if (symbol_equated_p (symbolP))
- name
- = S_GET_NAME (symbol_get_value_expression (symbolP)->X_add_symbol);
+ {
+ offsetT off;
+ symbolP = symbol_equated_to (symbolP, &off);
+ if (symbolP == NULL || off != 0)
+ return -1;
+ name = S_GET_NAME (symbolP);
+ }
else if (accept_numbers)
{
int reg = S_GET_VALUE (symbolP);
void resolve_register (expressionS *expP)
{
symbolS *sym;
- offsetT acc = 0;
- const expressionS *e = expP;
+ offsetT acc;
+ const expressionS *e;
if (expP->X_op != O_symbol)
return;
- do
- {
- if (!md_register_arithmetic && e->X_add_number)
- break;
- sym = e->X_add_symbol;
- acc += e->X_add_number;
- e = symbol_get_value_expression (sym);
- }
- while (symbol_equated_p (sym));
+ sym = symbol_equated_to (expP->X_add_symbol, &acc);
+ acc += expP->X_add_number;
+ if (sym == NULL
+ || (!md_register_arithmetic && acc != 0))
+ return;
+ e = symbol_get_value_expression (sym);
if (e->X_op == O_register)
{
expr_copy (expP, e);
|| S_IS_COMMON (s)));
}
+/* Return the final symbol in a chain of equated symbols, and the offset
+ from that symbol. If the chain has a loop, return NULL.
+ For a non-equated SYM, return SYM. */
+
+symbolS *
+symbol_equated_to (symbolS *sym, offsetT *off)
+{
+ valueT add = 0;
+ symbolS *ret = sym;
+ while (ret && symbol_equated_p (ret))
+ {
+ const expressionS *e = symbol_get_value_expression (ret);
+ add += e->X_add_number;
+ ret->flags.resolving = 1;
+ ret = e->X_add_symbol;
+ if (ret->flags.resolving)
+ ret = NULL;
+ }
+ while (sym && sym->flags.resolving)
+ {
+ const expressionS *e = symbol_get_value_expression (sym);
+ sym->flags.resolving = 0;
+ sym = e->X_add_symbol;
+ }
+ *off = add;
+ return ret;
+}
+
/* Return whether a symbol has a constant value. */
int
extern int symbol_section_p (const symbolS *);
extern int symbol_equated_p (const symbolS *);
extern int symbol_equated_reloc_p (const symbolS *);
+extern symbolS *symbol_equated_to (symbolS *, offsetT *);
extern int symbol_constant_p (const symbolS *);
extern int symbol_shadow_p (const symbolS *);
extern symbolS *symbol_symbolS (symbolS *);