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 | |
parent | 0b66f3173809e422f3dfbab2a8afff7fb9fc0ef3 (diff) | |
download | binutils-gdb-3c7b9c2c544319e9f148ef013e8706b1e484e4d5.tar.gz |
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.
-rw-r--r-- | gas/ChangeLog | 14 | ||||
-rw-r--r-- | gas/config/tc-i386-intel.c | 101 | ||||
-rw-r--r-- | gas/config/tc-i386.c | 16 | ||||
-rw-r--r-- | gas/read.c | 1 | ||||
-rw-r--r-- | gas/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gas/testsuite/gas/i386/equ.d | 2 | ||||
-rw-r--r-- | gas/testsuite/gas/i386/equ.s | 3 |
7 files changed, 103 insertions, 40 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 8dcc359f172..2514b288e51 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,5 +1,19 @@ 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. + +2010-04-21 H.J. Lu <hongjiu.lu@intel.com> + * expr.c (expr): Initialize the X_md field. 2010-04-20 Joseph Myers <joseph@codesourcery.com> diff --git a/gas/config/tc-i386-intel.c b/gas/config/tc-i386-intel.c index b3cdcd36d58..cb99518110b 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 db50c62b9e9..1728e60a81d 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) { diff --git a/gas/read.c b/gas/read.c index 4afb190173e..ae0dbb86e70 100644 --- a/gas/read.c +++ b/gas/read.c @@ -471,6 +471,7 @@ get_absolute_expression (void) { expressionS exp; + exp.X_md = 0; return get_absolute_expr (&exp); } diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index f5522ad3e16..9b36f2abc40 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,9 @@ +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. + 2010-04-20 Nick Clifton <nickc@redhat.com> PR gas/11507 diff --git a/gas/testsuite/gas/i386/equ.d b/gas/testsuite/gas/i386/equ.d index c23616fa361..0f270a6ccdf 100644 --- a/gas/testsuite/gas/i386/equ.d +++ b/gas/testsuite/gas/i386/equ.d @@ -22,4 +22,6 @@ Disassembly of section .text: [ 0-9a-f]+:[ 0-9a-f]+mov[ ]+%gs:\(%edx,%edx,8\),%edx [ 0-9a-f]+:[ 0-9a-f]+fadd[ ]+%st\(1\),%st [ 0-9a-f]+:[ 0-9a-f]+fadd[ ]+%st\(7\),%st +[ 0-9a-f]+:[ 0-9a-f]+mov[ ]+0x4\(%edx\),%eax +[ 0-9a-f]+:[ 0-9a-f]+mov[ ]+0x4\(%edx\),%eax #pass diff --git a/gas/testsuite/gas/i386/equ.s b/gas/testsuite/gas/i386/equ.s index 94ec81d384c..e15148a741d 100644 --- a/gas/testsuite/gas/i386/equ.s +++ b/gas/testsuite/gas/i386/equ.s @@ -39,6 +39,9 @@ _start: fadd x .equ x, st(7) fadd x + .equ r, edx + 4 + mov eax, [r] + mov eax, [r] .if s <> gs .err |