diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2010-04-21 18:09:52 +0000 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2010-04-21 18:09:52 +0000 |
commit | 3c7b9c2c544319e9f148ef013e8706b1e484e4d5 (patch) | |
tree | 6f1bf375050d2bb96297c3f1a815a953ef3fc252 /gas/config | |
parent | 0b66f3173809e422f3dfbab2a8afff7fb9fc0ef3 (diff) | |
download | fsf-binutils-gdb-3c7b9c2c544319e9f148ef013e8706b1e484e4d5.zip fsf-binutils-gdb-3c7b9c2c544319e9f148ef013e8706b1e484e4d5.tar.gz fsf-binutils-gdb-3c7b9c2c544319e9f148ef013e8706b1e484e4d5.tar.bz2 |
Properly handle ".equ symbol, reg + NUM" in x86 Intel syntax.
gas/
2010-04-21 H.J. Lu <hongjiu.lu@intel.com>
PR gas/11509
* config/tc-i386-intel.c (i386_intel_simplify_register): New.
(i386_intel_simplify): Use i386_is_register and
i386_intel_simplify_register. Set X_md for O_register and
check X_md for O_constant.
(i386_intel_operand): Use i386_is_register.
* config/tc-i386.c (i386_is_register): New.
(x86_cons): Initialize the X_md field. Use i386_is_register.
(parse_register): Use i386_is_register.
(tc_x86_parse_to_dw2regnum): Likewise.
gas/testsuite/
2010-04-21 H.J. Lu <hongjiu.lu@intel.com>
PR gas/11509
* gas/i386/equ.s: Add tests for ".equ symbol, reg + NUM".
* gas/i386/equ.d: Updated.
Diffstat (limited to 'gas/config')
-rw-r--r-- | gas/config/tc-i386-intel.c | 101 | ||||
-rw-r--r-- | gas/config/tc-i386.c | 16 |
2 files changed, 77 insertions, 40 deletions
diff --git a/gas/config/tc-i386-intel.c b/gas/config/tc-i386-intel.c index b3cdcd3..cb99518 100644 --- a/gas/config/tc-i386-intel.c +++ b/gas/config/tc-i386-intel.c @@ -233,6 +233,49 @@ static INLINE void i386_intel_fold (expressionS *e, symbolS *sym) } } +static int +i386_intel_simplify_register (expressionS *e) +{ + int reg_num; + + if (this_operand < 0 || intel_state.in_offset) + { + as_bad (_("invalid use of register")); + return 0; + } + + if (e->X_op == O_register) + reg_num = e->X_add_number; + else + reg_num = e->X_md - 1; + + if (!intel_state.in_bracket) + { + if (i.op[this_operand].regs) + { + as_bad (_("invalid use of register")); + return 0; + } + if (i386_regtab[reg_num].reg_type.bitfield.sreg3 + && i386_regtab[reg_num].reg_num == RegFlat) + { + as_bad (_("invalid use of pseudo-register")); + return 0; + } + i.op[this_operand].regs = i386_regtab + reg_num; + } + else if (!intel_state.base && !intel_state.in_scale) + intel_state.base = i386_regtab + reg_num; + else if (!intel_state.index) + intel_state.index = i386_regtab + reg_num; + else + { + /* esp is invalid as index */ + intel_state.index = i386_regtab + REGNAM_EAX + 4; + } + return 2; +} + static int i386_intel_simplify (expressionS *); static INLINE int i386_intel_simplify_symbol(symbolS *sym) @@ -304,7 +347,8 @@ static int i386_intel_simplify (expressionS *e) intel_state.op_modifier = e->X_op; /* FALLTHROUGH */ case O_short: - if (symbol_get_value_expression (e->X_add_symbol)->X_op == O_register) + if (i386_is_register (symbol_get_value_expression (e->X_add_symbol), + 1)) { as_bad (_("invalid use of register")); return 0; @@ -315,7 +359,8 @@ static int i386_intel_simplify (expressionS *e) break; case O_full_ptr: - if (symbol_get_value_expression (e->X_op_symbol)->X_op == O_register) + if (i386_is_register (symbol_get_value_expression (e->X_op_symbol), + 1)) { as_bad (_("invalid use of register")); return 0; @@ -328,40 +373,6 @@ static int i386_intel_simplify (expressionS *e) i386_intel_fold (e, e->X_op_symbol); break; - case O_register: - if (this_operand < 0 || intel_state.in_offset) - { - as_bad (_("invalid use of register")); - return 0; - } - if (!intel_state.in_bracket) - { - if (i.op[this_operand].regs) - { - as_bad (_("invalid use of register")); - return 0; - } - if (i386_regtab[e->X_add_number].reg_type.bitfield.sreg3 - && i386_regtab[e->X_add_number].reg_num == RegFlat) - { - as_bad (_("invalid use of pseudo-register")); - return 0; - } - i.op[this_operand].regs = i386_regtab + e->X_add_number; - } - else if (!intel_state.base && !intel_state.in_scale) - intel_state.base = i386_regtab + e->X_add_number; - else if (!intel_state.index) - intel_state.index = i386_regtab + e->X_add_number; - else - { - /* esp is invalid as index */ - intel_state.index = i386_regtab + REGNAM_EAX + 4; - } - e->X_op = O_constant; - e->X_add_number = 0; - return 2; - case O_multiply: if (this_operand >= 0 && intel_state.in_bracket) { @@ -418,6 +429,22 @@ static int i386_intel_simplify (expressionS *e) break; } + + case O_register: + ret = i386_intel_simplify_register (e); + if (ret == 2) + { + gas_assert (e->X_add_number < (unsigned short) -1); + e->X_md = (unsigned short) e->X_add_number + 1; + e->X_op = O_constant; + e->X_add_number = 0; + } + return ret; + + case O_constant: + if (e->X_md) + return i386_intel_simplify_register (e); + /* FALLTHROUGH */ default: if (e->X_add_symbol && !i386_intel_simplify_symbol (e->X_add_symbol)) @@ -832,7 +859,7 @@ i386_intel_operand (char *operand_string, int got_a_float) break; intel_state.seg = expP->X_add_symbol; } - if (expP->X_op != O_register) + if (!i386_is_register (expP, 1)) { as_bad (_("segment register name expected")); return 0; diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index db50c62..1728e60 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -3534,6 +3534,15 @@ swap_operands (void) } } +static int +i386_is_register (const expressionS *e, int is_intel_syntax) +{ + return (e->X_op == O_register + || (is_intel_syntax + && e->X_op == O_constant + && e->X_md)); +} + /* Try to ensure constant immediates are represented in the smallest opcode possible. */ static void @@ -6451,6 +6460,7 @@ x86_cons (expressionS *exp, int size) { intel_syntax = -intel_syntax; + exp->X_md = 0; if (size == 4 || (object_64bit && size == 8)) { /* Handle @GOTOFF and the like in an expression. */ @@ -6477,7 +6487,7 @@ x86_cons (expressionS *exp, int size) if (exp->X_op == O_constant || exp->X_op == O_absent || exp->X_op == O_illegal - || exp->X_op == O_register + || i386_is_register (exp, intel_syntax) || exp->X_op == O_big) { char c = *input_line_pointer; @@ -7956,7 +7966,7 @@ parse_register (char *reg_string, char **end_op) { const expressionS *e = symbol_get_value_expression (symbolP); - know (e->X_op == O_register); + know (i386_is_register (e, intel_syntax)); know (e->X_add_number >= 0 && (valueT) e->X_add_number < i386_regtab_size); r = i386_regtab + e->X_add_number; @@ -8863,7 +8873,7 @@ tc_x86_parse_to_dw2regnum (expressionS *exp) register_chars['.'] = saved_register_dot; allow_naked_reg = saved_naked_reg; - if (exp->X_op == O_register && exp->X_add_number >= 0) + if (i386_is_register (exp, intel_syntax) && exp->X_add_number >= 0) { if ((addressT) exp->X_add_number < i386_regtab_size) { |