@@ -167,7 +167,7 @@ static int i386_finalize_displacement (s
const char *);
static int i386_att_operand (char *);
static int i386_intel_operand (char *, int);
-static int i386_intel_simplify (expressionS *);
+static int i386_intel_simplify (expressionS *, bool);
static int i386_intel_parse_name (const char *, expressionS *, enum expr_mode);
static const reg_entry *parse_register (const char *, char **);
static const char *parse_insn (const char *, char *, enum parse_mode);
@@ -13526,7 +13526,7 @@ x86_cons (expressionS *exp, int size)
intel_syntax = -intel_syntax;
if (intel_syntax)
- i386_intel_simplify (exp);
+ i386_intel_simplify (exp, false);
/* If not 64bit, massage value, to account for wraparound when !BFD64. */
if (size <= 4 && expr_mode == expr_operator_present
@@ -378,30 +378,56 @@ i386_intel_simplify_register (expression
return 2;
}
-static int
-i386_intel_simplify_symbol (symbolS *sym)
+static symbolS *
+i386_intel_simplify_symbol (symbolS *sym, bool in_equate)
{
if (symbol_resolving_p (sym))
- return 1;
+ return sym;
- symbol_mark_resolving (sym);
- int ret = i386_intel_simplify (symbol_get_value_expression (sym));
- if (ret == 2)
+ segT seg = S_GET_SEGMENT (sym);
+ if (seg != expr_section && seg != reg_section && !symbol_equated_p(sym))
+ return sym;
+
+ for (;;)
{
- S_SET_SEGMENT (sym, absolute_section);
- ret = 1;
+ /* While we're after equates, symbol_equated_p() isn't suitable here. */
+ if (symbol_on_chain(sym, symbol_rootP, symbol_lastP))
+ {
+ in_equate = true;
+ sym = symbol_clone (sym, 0);
+ }
+ else if (in_equate)
+ {
+ expressionS *e = symbol_get_value_expression (sym);
+
+ if (e->X_op == O_symbol && !e->X_add_number)
+ {
+ sym = e->X_add_symbol;
+ continue;
+ }
+ sym = make_expr_symbol (e);
+ }
+
+ break;
}
+
+ symbol_mark_resolving (sym);
+ int ret = i386_intel_simplify (symbol_get_value_expression (sym), in_equate);
+ if (ret == 2)
+ S_SET_SEGMENT (sym, absolute_section);
symbol_clear_resolving (sym);
- return ret;
+
+ return ret ? sym : NULL;
}
static int
-i386_intel_simplify (expressionS *e)
+i386_intel_simplify (expressionS *e, bool in_equate)
{
const reg_entry *the_reg = (this_operand >= 0
? i.op[this_operand].regs : NULL);
const reg_entry *base = intel_state.base;
const reg_entry *state_index = intel_state.index;
+ symbolS *newsym;
int ret;
if (!intel_syntax)
@@ -412,18 +438,21 @@ i386_intel_simplify (expressionS *e)
case O_index:
if (e->X_add_symbol)
{
- if (!i386_intel_simplify_symbol (e->X_add_symbol)
+ newsym = i386_intel_simplify_symbol (e->X_add_symbol, in_equate);
+ if (!newsym
|| !i386_intel_check(the_reg, intel_state.base,
intel_state.index))
return 0;
+ e->X_add_symbol = newsym;
}
if (!intel_state.in_offset)
++intel_state.in_bracket;
- ret = i386_intel_simplify_symbol (e->X_op_symbol);
+ newsym = i386_intel_simplify_symbol (e->X_op_symbol, in_equate);
if (!intel_state.in_offset)
--intel_state.in_bracket;
- if (!ret)
+ if (!newsym)
return 0;
+ e->X_op_symbol = newsym;
if (e->X_add_symbol)
e->X_op = O_add;
else
@@ -433,12 +462,13 @@ i386_intel_simplify (expressionS *e)
case O_offset:
intel_state.has_offset = 1;
++intel_state.in_offset;
- ret = i386_intel_simplify_symbol (e->X_add_symbol);
+ newsym = i386_intel_simplify_symbol (e->X_add_symbol, in_equate);
--intel_state.in_offset;
- if (!ret || !i386_intel_check(the_reg, base, state_index))
+ if (!newsym || !i386_intel_check(the_reg, base, state_index))
return 0;
+ e->X_add_symbol = newsym;
i386_intel_fold (e, e->X_add_symbol);
- return ret;
+ return 1;
case O_byte_ptr:
case O_word_ptr:
@@ -461,8 +491,10 @@ i386_intel_simplify (expressionS *e)
as_bad (_("invalid use of register"));
return 0;
}
- if (!i386_intel_simplify_symbol (e->X_add_symbol))
+ newsym = i386_intel_simplify_symbol (e->X_add_symbol, in_equate);
+ if (!newsym)
return 0;
+ e->X_add_symbol = newsym;
i386_intel_fold (e, e->X_add_symbol);
break;
@@ -473,10 +505,12 @@ i386_intel_simplify (expressionS *e)
as_bad (_("invalid use of register"));
return 0;
}
- if (!i386_intel_simplify_symbol (e->X_op_symbol)
+ newsym = i386_intel_simplify_symbol (e->X_op_symbol, in_equate);
+ if (!newsym
|| !i386_intel_check(the_reg, intel_state.base,
intel_state.index))
return 0;
+ e->X_op_symbol = newsym;
if (!intel_state.in_offset)
{
if (!intel_state.seg)
@@ -503,16 +537,26 @@ i386_intel_simplify (expressionS *e)
if (!intel_state.in_scale++)
intel_state.scale_factor = 1;
- ret = i386_intel_simplify_symbol (e->X_add_symbol);
- if (ret && !has_index && intel_state.index)
- scale = symbol_get_value_expression (e->X_op_symbol);
-
- if (ret)
- ret = i386_intel_simplify_symbol (e->X_op_symbol);
- if (ret && !scale && !has_index && intel_state.index)
- scale = symbol_get_value_expression (e->X_add_symbol);
+ newsym = i386_intel_simplify_symbol (e->X_add_symbol, in_equate);
+ if (newsym)
+ {
+ e->X_add_symbol = newsym;
+
+ if (!has_index && intel_state.index)
+ scale = symbol_get_value_expression (e->X_op_symbol);
+
+ newsym = i386_intel_simplify_symbol (e->X_op_symbol, in_equate);
+ }
+
+ if (newsym)
+ {
+ e->X_op_symbol = newsym;
+
+ if (!scale && !has_index && intel_state.index)
+ scale = symbol_get_value_expression (e->X_add_symbol);
+ }
- if (ret && scale)
+ if (newsym && scale)
{
resolve_expression (scale);
if (scale->X_op != O_constant
@@ -522,7 +566,7 @@ i386_intel_simplify (expressionS *e)
}
--intel_state.in_scale;
- if (!ret)
+ if (!newsym)
return 0;
if (!intel_state.in_scale)
@@ -568,9 +612,13 @@ i386_intel_simplify (expressionS *e)
/* FALLTHROUGH */
default:
fallthrough:
- if (e->X_add_symbol
- && !i386_intel_simplify_symbol (e->X_add_symbol))
- return 0;
+ if (e->X_add_symbol)
+ {
+ newsym = i386_intel_simplify_symbol (e->X_add_symbol, in_equate);
+ if (!newsym)
+ return 0;
+ e->X_add_symbol = newsym;
+ }
if (!the_reg && this_operand >= 0
&& e->X_op == O_symbol && !e->X_add_number)
the_reg = i.op[this_operand].regs;
@@ -579,14 +627,19 @@ i386_intel_simplify (expressionS *e)
base = intel_state.base;
state_index = intel_state.index;
}
- if (!i386_intel_check (the_reg, base, state_index)
- || (e->X_op_symbol
- && !i386_intel_simplify_symbol (e->X_op_symbol))
- || !i386_intel_check (the_reg,
- (e->X_op != O_add
- ? base : intel_state.base),
- (e->X_op != O_add
- ? state_index : intel_state.index)))
+ if (!i386_intel_check (the_reg, base, state_index))
+ return 0;
+ if (e->X_op_symbol)
+ {
+ newsym = i386_intel_simplify_symbol (e->X_op_symbol, in_equate);
+ if (!newsym)
+ return 0;
+ e->X_op_symbol = newsym;
+ }
+ if (!i386_intel_check (the_reg,
+ e->X_op != O_add ? base : intel_state.base,
+ (e->X_op != O_add ? state_index
+ : intel_state.index)))
return 0;
break;
}
@@ -654,7 +707,7 @@ i386_intel_operand (char *operand_string
expr_mode = expr_operator_none;
memset (&exp, 0, sizeof(exp));
exp_seg = expression (&exp);
- ret = i386_intel_simplify (&exp);
+ ret = i386_intel_simplify (&exp, false);
intel_syntax = 1;
SKIP_WHITESPACE ();
@@ -0,0 +1,10 @@
+#source: equ.s
+#objdump: -t
+#name: i386 equates (symtab check)
+
+.*: +file format .*
+
+SYMBOL TABLE:
+.* \.text .*
+!.* \*ABS\* .*
+#pass
@@ -726,6 +726,7 @@ if [gas_32_check] then {
run_dump_test "pcrel-elf"
run_dump_test "relax"
run_dump_test "gotpc"
+ run_dump_test "equ2"
run_dump_test "tlsd"
run_dump_test "tlspic"
run_dump_test "tlsnopic"