From a272d17f337aa90fdf3d5462988191b965e06679 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Wed, 21 Apr 2010 18:09:48 +0000 Subject: [PATCH] Properly handle ".equ symbol, reg + NUM" in x86 Intel syntax. gas/ 2010-04-21 H.J. Lu 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 PR gas/11509 * gas/i386/equ.s: Add tests for ".equ symbol, reg + NUM". * gas/i386/equ.d: Updated. --- gas/ChangeLog | 14 ++++++ gas/config/tc-i386-intel.c | 101 +++++++++++++++++++++++++++---------------- gas/config/tc-i386.c | 16 +++++-- gas/read.c | 1 + gas/testsuite/ChangeLog | 6 +++ gas/testsuite/gas/i386/equ.d | 2 + gas/testsuite/gas/i386/equ.s | 3 ++ 7 files changed, 103 insertions(+), 40 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index 8dcc359f1..2514b288e 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,5 +1,19 @@ 2010-04-21 H.J. Lu + 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 + * expr.c (expr): Initialize the X_md field. 2010-04-20 Joseph Myers diff --git a/gas/config/tc-i386-intel.c b/gas/config/tc-i386-intel.c index b3cdcd36d..cb9951811 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 db50c62b9..1728e60a8 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 4afb19017..ae0dbb86e 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 f5522ad3e..9b36f2abc 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2010-04-21 H.J. Lu + + PR gas/11509 + * gas/i386/equ.s: Add tests for ".equ symbol, reg + NUM". + * gas/i386/equ.d: Updated. + 2010-04-20 Nick Clifton PR gas/11507 diff --git a/gas/testsuite/gas/i386/equ.d b/gas/testsuite/gas/i386/equ.d index c23616fa3..0f270a6cc 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 94ec81d38..e15148a74 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 -- 2.11.4.GIT