summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@novell.com>2009-04-20 06:31:50 +0000
committerJan Beulich <jbeulich@novell.com>2009-04-20 06:31:50 +0000
commit0ed176da19a42aed7671dd0af5264fc2de582c4e (patch)
treee658181177b2b2b8ef5c57c7f12bb22fc14250fb
parent8abc84de9c16c650b76a8cb3950224bc8f2b3775 (diff)
downloadbinutils-redhat-0ed176da19a42aed7671dd0af5264fc2de582c4e.tar.gz
gas/
2009-04-20 Jan Beulich <jbeulich@novell.com> * Makefile.am: Add explicit dependency of tc-i386.o on tc-i386-intel.c. * Makefile.in: Likewise. * config/tc-i386.c (i386_finalize_immediate): Declare, broken out from i386_immediate. (i386_immediate): Slightly re-arrange, call i386_finalize_immediate. (i386_finalize_displacement): Declare, broken out from i386_displacement. (i386_displacement): Slightly re-arrange, call i386_finalize_displacement. (i386_intel_simplify, i386_intel_parse_name): Declare. (this_operand): Initialize to -1. (set_intel_syntax): Set expression rank for O_full_ptr. (md_assemble): Set this_operand back to -1 after parsing operands. (x86_cons): Negate intel_syntax to indicate state. Call i386_intel_simplify. (md_operand): Convert if to switch. Handle '[' for Intel syntax. (i386_intel_operand): Delete, including all helper functions and data. * config/tc-i386-intel.c: New file, all new code. * config/tc-i386.h (i386_operator): Declare. (md_operator): Define to i386_operator. (i386_need_index_operator): Declare. (md_need_index_operator): Define to i386_need_index_operator. (O_full_ptr): Define. gas/testsuite/ 2009-04-20 Jan Beulich <jbeulich@novell.com> * gas/i386/equ.s: Adjust. * gas/i386/equ.d: Remove reference to equ.e. * gas/i386/equ.e: Delete. * gas/i386/intel-expr.s: New. * gas/i386/intel-expr.d: New. * gas/i386/i386.exp: Run new test. * gas/i386/intel.s: Adjust. * gas/i386/intel.e: Remove no longer valid warning messages. * gas/i386/intel16.s: Adjust. * gas/i386/intel16.d: Remove reference to intel16.e. * gas/i386/intel16.e: Delete. * gas/i386/intelbad.s: Add more tests. * gas/i386/intelbad.l: Adjust. * gas/i386/intelok.s: Remove now unneeded equates. Add more tests. * gas/i386/intelok.d: Remove reference to intelok.e. Adjust. * gas/i386/intelok.e: Delete. * gas/i386/x86_64.s: Adjust. * gas/i386/x86_64.d: Remove reference to x86_64.e. * gas/i386/x86_64.e: Delete.
-rw-r--r--gas/ChangeLog31
-rw-r--r--gas/Makefile.am2
-rw-r--r--gas/Makefile.in2
-rw-r--r--gas/config/tc-i386-intel.c845
-rw-r--r--gas/config/tc-i386.c1447
-rw-r--r--gas/config/tc-i386.h9
-rw-r--r--gas/testsuite/ChangeLog23
-rw-r--r--gas/testsuite/gas/i386/equ.d1
-rw-r--r--gas/testsuite/gas/i386/equ.e2
-rw-r--r--gas/testsuite/gas/i386/equ.s2
-rw-r--r--gas/testsuite/gas/i386/i386.exp1
-rw-r--r--gas/testsuite/gas/i386/intel.e6
-rw-r--r--gas/testsuite/gas/i386/intel.s24
-rw-r--r--gas/testsuite/gas/i386/intel16.d1
-rw-r--r--gas/testsuite/gas/i386/intel16.e7
-rw-r--r--gas/testsuite/gas/i386/intel16.s12
-rw-r--r--gas/testsuite/gas/i386/intelbad.l23
-rw-r--r--gas/testsuite/gas/i386/intelbad.s23
-rw-r--r--gas/testsuite/gas/i386/intelok.d74
-rw-r--r--gas/testsuite/gas/i386/intelok.e8
-rw-r--r--gas/testsuite/gas/i386/intelok.s53
-rw-r--r--gas/testsuite/gas/i386/x86_64.d1
-rw-r--r--gas/testsuite/gas/i386/x86_64.e9
-rw-r--r--gas/testsuite/gas/i386/x86_64.s16
24 files changed, 1136 insertions, 1486 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index cf41843190..9caad73603 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,5 +1,36 @@
2009-04-20 Jan Beulich <jbeulich@novell.com>
+ * Makefile.am: Add explicit dependency of tc-i386.o on
+ tc-i386-intel.c.
+ * Makefile.in: Likewise.
+ * config/tc-i386.c (i386_finalize_immediate): Declare, broken
+ out from i386_immediate.
+ (i386_immediate): Slightly re-arrange, call
+ i386_finalize_immediate.
+ (i386_finalize_displacement): Declare, broken out from
+ i386_displacement.
+ (i386_displacement): Slightly re-arrange, call
+ i386_finalize_displacement.
+ (i386_intel_simplify, i386_intel_parse_name): Declare.
+ (this_operand): Initialize to -1.
+ (set_intel_syntax): Set expression rank for O_full_ptr.
+ (md_assemble): Set this_operand back to -1 after parsing
+ operands.
+ (x86_cons): Negate intel_syntax to indicate state. Call
+ i386_intel_simplify.
+ (md_operand): Convert if to switch. Handle '[' for Intel
+ syntax.
+ (i386_intel_operand): Delete, including all helper functions
+ and data.
+ * config/tc-i386-intel.c: New file, all new code.
+ * config/tc-i386.h (i386_operator): Declare.
+ (md_operator): Define to i386_operator.
+ (i386_need_index_operator): Declare.
+ (md_need_index_operator): Define to i386_need_index_operator.
+ (O_full_ptr): Define.
+
+2009-04-20 Jan Beulich <jbeulich@novell.com>
+
* expr.c (operand): Call md_need_index_operator() and
md_operator() if defined. Add unary label.
(operator): Call md_operator() if defined.
diff --git a/gas/Makefile.am b/gas/Makefile.am
index f5c7a84ad7..40c52be39e 100644
--- a/gas/Makefile.am
+++ b/gas/Makefile.am
@@ -614,6 +614,8 @@ e-crisaout.o: $(srcdir)/config/e-crisaout.c
e-criself.o: $(srcdir)/config/e-criself.c
$(COMPILE) -c $(srcdir)/config/e-criself.c
+tc-i386.o: $(srcdir)/config/tc-i386-intel.c
+
xtensa-relax.o: $(srcdir)/config/xtensa-relax.c
$(COMPILE) -c $(srcdir)/config/xtensa-relax.c
diff --git a/gas/Makefile.in b/gas/Makefile.in
index 084407fffa..d65f8e41dd 100644
--- a/gas/Makefile.in
+++ b/gas/Makefile.in
@@ -2667,6 +2667,8 @@ e-crisaout.o: $(srcdir)/config/e-crisaout.c
e-criself.o: $(srcdir)/config/e-criself.c
$(COMPILE) -c $(srcdir)/config/e-criself.c
+tc-i386.o: $(srcdir)/config/tc-i386-intel.c
+
xtensa-relax.o: $(srcdir)/config/xtensa-relax.c
$(COMPILE) -c $(srcdir)/config/xtensa-relax.c
diff --git a/gas/config/tc-i386-intel.c b/gas/config/tc-i386-intel.c
new file mode 100644
index 0000000000..e7a53889e5
--- /dev/null
+++ b/gas/config/tc-i386-intel.c
@@ -0,0 +1,845 @@
+/* tc-i386.c -- Assemble Intel syntax code for ix86/x86-64
+ Copyright 2009
+ Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+static struct
+ {
+ operatorT op_modifier; /* Operand modifier. */
+ int is_mem; /* 1 if operand is memory reference. */
+ unsigned int in_offset; /* >=1 if processing operand of offset. */
+ unsigned int in_bracket; /* >=1 if processing operand in brackets. */
+ unsigned int in_scale; /* >=1 if processing multipication operand
+ * in brackets. */
+ i386_operand_type reloc_types; /* Value obtained from lex_got(). */
+ const reg_entry *base; /* Base register (if any). */
+ const reg_entry *index; /* Index register (if any). */
+ offsetT scale_factor; /* Accumulated scale factor. */
+ symbolS *seg;
+ }
+intel_state;
+
+/* offset X_add_symbol */
+#define O_offset O_md32
+/* byte ptr X_add_symbol */
+#define O_byte_ptr O_md31
+/* word ptr X_add_symbol */
+#define O_word_ptr O_md30
+/* dword ptr X_add_symbol */
+#define O_dword_ptr O_md29
+/* qword ptr X_add_symbol */
+#define O_qword_ptr O_md28
+/* oword ptr X_add_symbol */
+#define O_oword_ptr O_md27
+/* fword ptr X_add_symbol */
+#define O_fword_ptr O_md26
+/* tbyte ptr X_add_symbol */
+#define O_tbyte_ptr O_md25
+/* xmmword ptr X_add_symbol */
+#define O_xmmword_ptr O_md24
+/* ymmword ptr X_add_symbol */
+#define O_ymmword_ptr O_md23
+/* near ptr X_add_symbol */
+#define O_near_ptr O_md22
+/* far ptr X_add_symbol */
+#define O_far_ptr O_md21
+/* offset X_add_symbol */
+#define O_short O_md20
+
+static struct
+ {
+ const char *name;
+ operatorT operator;
+ unsigned int operands;
+ }
+const i386_operators[] =
+ {
+ { "and", O_bit_and, 2 },
+ { "eq", O_eq, 2 },
+ { "ge", O_ge, 2 },
+ { "gt", O_gt, 2 },
+ { "le", O_le, 2 },
+ { "lt", O_lt, 2 },
+ { "mod", O_modulus, 2 },
+ { "ne", O_ne, 2 },
+ { "not", O_bit_not, 1 },
+ { "offset", O_offset, 1 },
+ { "or", O_bit_inclusive_or, 2 },
+ { "shl", O_left_shift, 2 },
+ { "short", O_short, 1 },
+ { "shr", O_right_shift, 2 },
+ { "xor", O_bit_exclusive_or, 2 },
+ { NULL, O_illegal, 0 }
+ };
+
+static struct
+ {
+ const char *name;
+ operatorT operator;
+ unsigned short sz[3];
+ }
+const i386_types[] =
+ {
+#define I386_TYPE(t, n) { #t, O_##t##_ptr, { n, n, n } }
+ I386_TYPE(byte, 1),
+ I386_TYPE(word, 2),
+ I386_TYPE(dword, 4),
+ I386_TYPE(fword, 6),
+ I386_TYPE(qword, 8),
+ I386_TYPE(tbyte, 10),
+ I386_TYPE(oword, 16),
+ I386_TYPE(xmmword, 16),
+ I386_TYPE(ymmword, 32),
+#undef I386_TYPE
+ { "near", O_near_ptr, { 0xff04, 0xff02, 0xff08 } },
+ { "far", O_far_ptr, { 0xff06, 0xff05, 0xff06 } },
+ { NULL, O_illegal, { 0, 0, 0 } }
+ };
+
+operatorT i386_operator (const char *name, unsigned int operands, char *pc)
+{
+ unsigned int j;
+
+ if (!intel_syntax)
+ return O_absent;
+
+ if (!name)
+ {
+ if (operands != 2)
+ return O_illegal;
+ switch (*input_line_pointer)
+ {
+ case ':':
+ ++input_line_pointer;
+ return O_full_ptr;
+ case '[':
+ ++input_line_pointer;
+ return O_index;
+ case '@':
+ if (this_operand >= 0 && i.reloc[this_operand] == NO_RELOC)
+ {
+ int adjust = 0;
+ char *gotfree_input_line = lex_got (&i.reloc[this_operand],
+ &adjust,
+ &intel_state.reloc_types);
+
+ if (!gotfree_input_line)
+ break;
+ free (gotfree_input_line);
+ *input_line_pointer++ = '+';
+ memset (input_line_pointer, '0', adjust - 1);
+ input_line_pointer[adjust - 1] = ' ';
+ return O_add;
+ }
+ break;
+ }
+ return O_illegal;
+ }
+
+ for (j = 0; i386_operators[j].name; ++j)
+ if (strcasecmp(i386_operators[j].name, name) == 0)
+ {
+ if (i386_operators[j].operands
+ && i386_operators[j].operands != operands)
+ return O_illegal;
+ return i386_operators[j].operator;
+ }
+
+ for (j = 0; i386_types[j].name; ++j)
+ if (strcasecmp(i386_types[j].name, name) == 0)
+ break;
+ if (i386_types[j].name && *pc == ' ')
+ {
+ char *name = ++input_line_pointer;
+ char c = get_symbol_end ();
+
+ if (strcasecmp (name, "ptr") == 0)
+ {
+ name[-1] = *pc;
+ *pc = c;
+ if (intel_syntax > 0 || operands != 1)
+ return O_illegal;
+ return i386_types[j].operator;
+ }
+
+ *input_line_pointer = c;
+ input_line_pointer = name - 1;
+ }
+
+ return O_absent;
+}
+
+static int i386_intel_parse_name (const char *name, expressionS *e)
+{
+ unsigned int i;
+
+ for (i = 0; i386_types[i].name; ++i)
+ if (strcasecmp(i386_types[i].name, name) == 0)
+ {
+ e->X_op = O_constant;
+ e->X_add_number = i386_types[i].sz[flag_code];
+ e->X_add_symbol = NULL;
+ e->X_op_symbol = NULL;
+ return 1;
+ }
+
+ return 0;
+}
+
+static INLINE int i386_intel_check (const reg_entry *reg,
+ const reg_entry *base,
+ const reg_entry *index)
+{
+ if ((this_operand >= 0 && reg != i.op[this_operand].regs)
+ || base != intel_state.base || index != intel_state.index)
+ {
+ as_bad (_("invalid use of register"));
+ return 0;
+ }
+ return 1;
+}
+
+static INLINE void i386_intel_fold (expressionS *e, symbolS *sym)
+{
+ if (S_GET_SEGMENT (sym) == absolute_section)
+ {
+ offsetT val = e->X_add_number;
+
+ *e = *symbol_get_value_expression (sym);
+ e->X_add_number += val;
+ }
+ else
+ {
+ e->X_add_symbol = sym;
+ e->X_op_symbol = NULL;
+ e->X_op = O_symbol;
+ }
+}
+
+static int i386_intel_simplify (expressionS *);
+
+static INLINE int i386_intel_simplify_symbol(symbolS *sym)
+{
+ int ret = i386_intel_simplify (symbol_get_value_expression (sym));
+
+ if (ret == 2)
+ {
+ S_SET_SEGMENT(sym, absolute_section);
+ ret = 1;
+ }
+ return ret;
+}
+
+static int i386_intel_simplify (expressionS *e)
+{
+ const reg_entry *reg = this_operand >= 0 ? i.op[this_operand].regs : NULL;
+ const reg_entry *base = intel_state.base;
+ const reg_entry *index = intel_state.index;
+ int ret;
+
+ if (!intel_syntax)
+ return 1;
+
+ switch (e->X_op)
+ {
+ case O_index:
+ if (e->X_add_symbol)
+ {
+ if (!i386_intel_simplify_symbol (e->X_add_symbol)
+ || !i386_intel_check(reg, intel_state.base, intel_state.index))
+ return 0;;
+ }
+ if (!intel_state.in_offset)
+ ++intel_state.in_bracket;
+ ret = i386_intel_simplify_symbol (e->X_op_symbol);
+ if (!intel_state.in_offset)
+ --intel_state.in_bracket;
+ if (!ret)
+ return 0;
+ if (e->X_add_symbol)
+ e->X_op = O_add;
+ else
+ i386_intel_fold (e, e->X_op_symbol);
+ break;
+
+ case O_offset:
+ ++intel_state.in_offset;
+ ret = i386_intel_simplify_symbol (e->X_add_symbol);
+ --intel_state.in_offset;
+ if (!ret || !i386_intel_check(reg, base, index))
+ return 0;
+ i386_intel_fold (e, e->X_add_symbol);
+ return ret;
+
+ case O_byte_ptr:
+ case O_word_ptr:
+ case O_dword_ptr:
+ case O_fword_ptr:
+ case O_qword_ptr:
+ case O_tbyte_ptr:
+ case O_oword_ptr:
+ case O_xmmword_ptr:
+ case O_ymmword_ptr:
+ case O_near_ptr:
+ case O_far_ptr:
+ if (intel_state.op_modifier == O_absent)
+ intel_state.op_modifier = e->X_op;
+ /* FALLTHROUGH */
+ case O_short:
+ if (symbol_get_value_expression (e->X_add_symbol)->X_op == O_register)
+ {
+ as_bad (_("invalid use of register"));
+ return 0;
+ }
+ if (!i386_intel_simplify_symbol (e->X_add_symbol))
+ return 0;
+ i386_intel_fold (e, e->X_add_symbol);
+ break;
+
+ case O_full_ptr:
+ if (symbol_get_value_expression (e->X_op_symbol)->X_op == O_register)
+ {
+ as_bad (_("invalid use of register"));
+ return 0;
+ }
+ if (!i386_intel_simplify_symbol (e->X_op_symbol)
+ || !i386_intel_check(reg, intel_state.base, intel_state.index))
+ return 0;
+ if (!intel_state.in_offset)
+ intel_state.seg = e->X_add_symbol;
+ 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)
+ {
+ expressionS *scale = NULL;
+
+ if (intel_state.index)
+ --scale;
+
+ if (!intel_state.in_scale++)
+ intel_state.scale_factor = 1;
+
+ ret = i386_intel_simplify_symbol (e->X_add_symbol);
+ if (ret && !scale && 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 && intel_state.index)
+ scale = symbol_get_value_expression (e->X_add_symbol);
+
+ if (ret && scale && (scale + 1))
+ {
+ resolve_expression (scale);
+ if (scale->X_op != O_constant
+ || intel_state.index->reg_type.bitfield.reg16)
+ scale->X_add_number = 0;
+ intel_state.scale_factor *= scale->X_add_number;
+ }
+
+ --intel_state.in_scale;
+ if (!ret)
+ return 0;
+
+ if (!intel_state.in_scale)
+ switch (intel_state.scale_factor)
+ {
+ case 1:
+ i.log2_scale_factor = 0;
+ break;
+ case 2:
+ i.log2_scale_factor = 1;
+ break;
+ case 4:
+ i.log2_scale_factor = 2;
+ break;
+ case 8:
+ i.log2_scale_factor = 3;
+ break;
+ default:
+ /* esp is invalid as index */
+ intel_state.index = i386_regtab + REGNAM_EAX + 4;
+ break;
+ }
+
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+ if (e->X_add_symbol && !i386_intel_simplify_symbol (e->X_add_symbol))
+ return 0;
+ if (e->X_op == O_add || e->X_op == O_subtract)
+ {
+ base = intel_state.base;
+ index = intel_state.index;
+ }
+ if (!i386_intel_check (reg, base, index)
+ || (e->X_op_symbol && !i386_intel_simplify_symbol (e->X_op_symbol))
+ || !i386_intel_check (reg,
+ e->X_op != O_add ? base : intel_state.base,
+ e->X_op != O_add ? index : intel_state.index))
+ return 0;
+ break;
+ }
+
+ if (this_operand >= 0 && e->X_op == O_symbol && !intel_state.in_offset)
+ {
+ segT seg = S_GET_SEGMENT (e->X_add_symbol);
+
+ if (seg != absolute_section
+ && seg != reg_section
+ && seg != expr_section)
+ intel_state.is_mem |= 2 - !intel_state.in_bracket;
+ }
+
+ return 1;
+}
+
+int i386_need_index_operator (void)
+{
+ return intel_syntax < 0;
+}
+
+static int
+i386_intel_operand (char *operand_string, int got_a_float)
+{
+ char *saved_input_line_pointer, *buf;
+ segT exp_seg;
+ expressionS exp, *expP;
+ char suffix = 0;
+ int ret;
+
+ /* Initialize state structure. */
+ intel_state.op_modifier = O_absent;
+ intel_state.is_mem = 0;
+ intel_state.base = NULL;
+ intel_state.index = NULL;
+ intel_state.seg = NULL;
+ operand_type_set (&intel_state.reloc_types, ~0);
+ assert (!intel_state.in_offset);
+ assert (!intel_state.in_bracket);
+ assert (!intel_state.in_scale);
+
+ saved_input_line_pointer = input_line_pointer;
+ input_line_pointer = buf = xstrdup (operand_string);
+
+ intel_syntax = -1;
+ memset (&exp, 0, sizeof(exp));
+ exp_seg = expression (&exp);
+ ret = i386_intel_simplify (&exp);
+ intel_syntax = 1;
+
+ SKIP_WHITESPACE ();
+ if (!is_end_of_line[(unsigned char) *input_line_pointer])
+ {
+ as_bad (_("junk `%s' after expression"), input_line_pointer);
+ ret = 0;
+ }
+ else if (exp.X_op == O_illegal || exp.X_op == O_absent)
+ {
+ as_bad (_("invalid expression"));
+ ret = 0;
+ }
+
+ input_line_pointer = saved_input_line_pointer;
+ free (buf);
+
+ assert (!intel_state.in_offset);
+ assert (!intel_state.in_bracket);
+ assert (!intel_state.in_scale);
+
+ if (!ret)
+ return 0;
+
+ if (intel_state.op_modifier != O_absent
+ && current_templates->start->base_opcode != 0x8d /* lea */)
+ {
+ i.types[this_operand].bitfield.unspecified = 0;
+
+ switch (intel_state.op_modifier)
+ {
+ case O_byte_ptr:
+ i.types[this_operand].bitfield.byte = 1;
+ suffix = BYTE_MNEM_SUFFIX;
+ break;
+
+ case O_word_ptr:
+ i.types[this_operand].bitfield.word = 1;
+ if ((current_templates->start->name[0] == 'l'
+ && current_templates->start->name[2] == 's'
+ && current_templates->start->name[3] == 0)
+ || current_templates->start->base_opcode == 0x62 /* bound */)
+ suffix = BYTE_MNEM_SUFFIX; /* so it will cause an error */
+ else if (got_a_float == 2) /* "fi..." */
+ suffix = SHORT_MNEM_SUFFIX;
+ else
+ suffix = WORD_MNEM_SUFFIX;
+ break;
+
+ case O_dword_ptr:
+ i.types[this_operand].bitfield.dword = 1;
+ if ((current_templates->start->name[0] == 'l'
+ && current_templates->start->name[2] == 's'
+ && current_templates->start->name[3] == 0)
+ || current_templates->start->base_opcode == 0x62 /* bound */)
+ suffix = WORD_MNEM_SUFFIX;
+ else if (flag_code == CODE_16BIT
+ && (current_templates->start->opcode_modifier.jump
+ || current_templates->start->opcode_modifier.jumpdword))
+ suffix = LONG_DOUBLE_MNEM_SUFFIX;
+ else if (got_a_float == 1) /* "f..." */
+ suffix = SHORT_MNEM_SUFFIX;
+ else
+ suffix = LONG_MNEM_SUFFIX;
+ break;
+
+ case O_fword_ptr:
+ i.types[this_operand].bitfield.fword = 1;
+ if (current_templates->start->name[0] == 'l'
+ && current_templates->start->name[2] == 's'
+ && current_templates->start->name[3] == 0)
+ suffix = LONG_MNEM_SUFFIX;
+ else if (!got_a_float)
+ {
+ if (flag_code == CODE_16BIT)
+ add_prefix (DATA_PREFIX_OPCODE);
+ suffix = LONG_DOUBLE_MNEM_SUFFIX;
+ }
+ else
+ suffix = BYTE_MNEM_SUFFIX; /* so it will cause an error */
+ break;
+
+ case O_qword_ptr:
+ i.types[this_operand].bitfield.qword = 1;
+ if (current_templates->start->base_opcode == 0x62 /* bound */
+ || got_a_float == 1) /* "f..." */
+ suffix = LONG_MNEM_SUFFIX;
+ else
+ suffix = QWORD_MNEM_SUFFIX;
+ break;
+
+ case O_tbyte_ptr:
+ i.types[this_operand].bitfield.tbyte = 1;
+ if (got_a_float == 1)
+ suffix = LONG_DOUBLE_MNEM_SUFFIX;
+ else
+ suffix = BYTE_MNEM_SUFFIX; /* so it will cause an error */
+ break;
+
+ case O_oword_ptr:
+ case O_xmmword_ptr:
+ i.types[this_operand].bitfield.xmmword = 1;
+ suffix = XMMWORD_MNEM_SUFFIX;
+ break;
+
+ case O_ymmword_ptr:
+ i.types[this_operand].bitfield.ymmword = 1;
+ suffix = YMMWORD_MNEM_SUFFIX;
+ break;
+
+ case O_far_ptr:
+ suffix = LONG_DOUBLE_MNEM_SUFFIX;
+ /* FALLTHROUGH */
+ case O_near_ptr:
+ if (!current_templates->start->opcode_modifier.jump
+ && !current_templates->start->opcode_modifier.jumpdword)
+ suffix = got_a_float /* so it will cause an error */
+ ? BYTE_MNEM_SUFFIX
+ : LONG_DOUBLE_MNEM_SUFFIX;
+ break;
+
+ default:
+ BAD_CASE (intel_state.op_modifier);
+ break;
+ }
+
+ if (!i.suffix)
+ i.suffix = suffix;
+ else if (i.suffix != suffix)
+ {
+ as_bad (_("conflicting operand size modifiers"));
+ return 0;
+ }
+ }
+
+ /* Operands for jump/call need special consideration. */
+ if (current_templates->start->opcode_modifier.jump
+ || current_templates->start->opcode_modifier.jumpdword
+ || current_templates->start->opcode_modifier.jumpintersegment)
+ {
+ if (i.op[this_operand].regs || intel_state.base || intel_state.index
+ || intel_state.is_mem > 1)
+ i.types[this_operand].bitfield.jumpabsolute = 1;
+ else
+ switch (intel_state.op_modifier)
+ {
+ case O_near_ptr:
+ if (intel_state.seg)
+ i.types[this_operand].bitfield.jumpabsolute = 1;
+ else
+ intel_state.is_mem = 1;
+ break;
+ case O_far_ptr:
+ case O_absent:
+ if (!intel_state.seg)
+ {
+ intel_state.is_mem = 1;
+ if (intel_state.op_modifier == O_absent)
+ break;
+ as_bad (_("cannot infer the segment part of the operand"));
+ return 0;
+ }
+ else if (S_GET_SEGMENT (intel_state.seg) == reg_section)
+ i.types[this_operand].bitfield.jumpabsolute = 1;
+ else
+ {
+ i386_operand_type types;
+
+ if (i.imm_operands >= MAX_IMMEDIATE_OPERANDS)
+ {
+ as_bad (_("at most %d immediate operands are allowed"),
+ MAX_IMMEDIATE_OPERANDS);
+ return 0;
+ }
+ expP = &im_expressions[i.imm_operands++];
+ memset (expP, 0, sizeof(*expP));
+ expP->X_op = O_symbol;
+ expP->X_add_symbol = intel_state.seg;
+ i.op[this_operand].imms = expP;
+
+ resolve_expression (expP);
+ operand_type_set (&types, ~0);
+ if (!i386_finalize_immediate (S_GET_SEGMENT (intel_state.seg),
+ expP, types, operand_string))
+ return 0;
+ if (i.operands < MAX_OPERANDS)
+ {
+ this_operand = i.operands++;
+ i.types[this_operand].bitfield.unspecified = 1;
+ }
+ if (suffix == LONG_DOUBLE_MNEM_SUFFIX)
+ i.suffix = 0;
+ intel_state.seg = NULL;
+ intel_state.is_mem = 0;
+ }
+ break;
+ default:
+ i.types[this_operand].bitfield.jumpabsolute = 1;
+ break;
+ }
+ if (i.types[this_operand].bitfield.jumpabsolute)
+ intel_state.is_mem |= 1;
+ }
+ else if (intel_state.seg)
+ intel_state.is_mem |= 1;
+
+ if (i.op[this_operand].regs)
+ {
+ i386_operand_type temp;
+
+ /* Register operand. */
+ if (intel_state.base || intel_state.index || intel_state.seg)
+ {
+ as_bad (_("invalid operand"));
+ return 0;
+ }
+
+ temp = i.op[this_operand].regs->reg_type;
+ temp.bitfield.baseindex = 0;
+ i.types[this_operand] = operand_type_or (i.types[this_operand], temp);
+ i.types[this_operand].bitfield.unspecified = 0;
+ ++i.reg_operands;
+ }
+ else if (intel_state.base || intel_state.index || intel_state.seg
+ || intel_state.is_mem)
+ {
+ /* Memory operand. */
+ if (i.mem_operands
+ >= 2 - !current_templates->start->opcode_modifier.isstring)
+ {
+ as_bad (_("too many memory references for `%s'"),
+ current_templates->start->name);
+ return 0;
+ }
+
+ expP = &disp_expressions[i.disp_operands];
+ memcpy (expP, &exp, sizeof(exp));
+ resolve_expression (expP);
+
+ if (expP->X_op != O_constant || expP->X_add_number
+ || (!intel_state.base && !intel_state.index))
+ {
+ i.op[this_operand].disps = expP;
+ i.disp_operands++;
+
+ if (flag_code == CODE_64BIT)
+ {
+ i.types[this_operand].bitfield.disp32 = 1;
+ if (!i.prefix[ADDR_PREFIX])
+ {
+ i.types[this_operand].bitfield.disp64 = 1;
+ i.types[this_operand].bitfield.disp32s = 1;
+ }
+ }
+ else if (!i.prefix[ADDR_PREFIX] ^ (flag_code == CODE_16BIT))
+ i.types[this_operand].bitfield.disp32 = 1;
+ else
+ i.types[this_operand].bitfield.disp16 = 1;
+
+#if defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT)
+ /*
+ * exp_seg is used only for verification in
+ * i386_finalize_displacement, and we can end up seeing reg_section
+ * here - but we know we removed all registers from the expression
+ * (or error-ed on any remaining ones) in i386_intel_simplify. I
+ * consider the check in i386_finalize_displacement bogus anyway, in
+ * particular because it doesn't allow for expr_section, so I'd
+ * rather see that check (and the similar one in
+ * i386_finalize_immediate) use SEG_NORMAL(), but not being an a.out
+ * expert I can't really say whether that would have other bad side
+ * effects.
+ */
+ if (OUTPUT_FLAVOR == bfd_target_aout_flavour
+ && exp_seg == reg_section)
+ exp_seg = expP->X_op != O_constant ? undefined_section
+ : absolute_section;
+#endif
+
+ if (!i386_finalize_displacement (exp_seg, expP,
+ intel_state.reloc_types,
+ operand_string))
+ return 0;
+ }
+
+ if (intel_state.base || intel_state.index)
+ i.types[this_operand].bitfield.baseindex = 1;
+
+ if (intel_state.seg)
+ {
+ for (;;)
+ {
+ expP = symbol_get_value_expression (intel_state.seg);
+ if (expP->X_op != O_full_ptr)
+ break;
+ intel_state.seg = expP->X_add_symbol;
+ }
+ if (expP->X_op != O_register)
+ {
+ as_bad (_("segment register name expected"));
+ return 0;
+ }
+ if (!i386_regtab[expP->X_add_number].reg_type.bitfield.sreg2
+ && !i386_regtab[expP->X_add_number].reg_type.bitfield.sreg3)
+ {
+ as_bad (_("invalid use of register"));
+ return 0;
+ }
+ switch (i386_regtab[expP->X_add_number].reg_num)
+ {
+ case 0: i.seg[i.mem_operands] = &es; break;
+ case 1: i.seg[i.mem_operands] = &cs; break;
+ case 2: i.seg[i.mem_operands] = &ss; break;
+ case 3: i.seg[i.mem_operands] = &ds; break;
+ case 4: i.seg[i.mem_operands] = &fs; break;
+ case 5: i.seg[i.mem_operands] = &gs; break;
+ case RegFlat: i.seg[i.mem_operands] = NULL; break;
+ }
+ }
+
+ /* Swap base and index in 16-bit memory operands like
+ [si+bx]. Since i386_index_check is also used in AT&T
+ mode we have to do that here. */
+ if (intel_state.base
+ && intel_state.index
+ && intel_state.base->reg_type.bitfield.reg16
+ && intel_state.index->reg_type.bitfield.reg16
+ && intel_state.base->reg_num >= 6
+ && intel_state.index->reg_num < 6)
+ {
+ i.base_reg = intel_state.index;
+ i.index_reg = intel_state.base;
+ }
+ else
+ {
+ i.base_reg = intel_state.base;
+ i.index_reg = intel_state.index;
+ }
+
+ if (!i386_index_check (operand_string))
+ return 0;
+
+ i.types[this_operand].bitfield.mem = 1;
+ ++i.mem_operands;
+ }
+ else
+ {
+ /* Immediate. */
+ if (i.imm_operands >= MAX_IMMEDIATE_OPERANDS)
+ {
+ as_bad (_("at most %d immediate operands are allowed"),
+ MAX_IMMEDIATE_OPERANDS);
+ return 0;
+ }
+
+ expP = &im_expressions[i.imm_operands++];
+ i.op[this_operand].imms = expP;
+ *expP = exp;
+
+ return i386_finalize_immediate (exp_seg, expP, intel_state.reloc_types,
+ operand_string);
+ }
+
+ return 1;
+}
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index 67b477974c..767d1fcee3 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -171,8 +171,14 @@ static void pe_directive_secrel (int);
#endif
static void signed_cons (int);
static char *output_invalid (int c);
+static int i386_finalize_immediate (segT, expressionS *, i386_operand_type,
+ const char *);
+static int i386_finalize_displacement (segT, expressionS *, i386_operand_type,
+ 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_parse_name (const char *, expressionS *);
static const reg_entry *parse_register (char *, char **);
static char *parse_insn (char *, char *);
static char *parse_operands (char *, const char *);
@@ -377,7 +383,7 @@ static expressionS disp_expressions[MAX_MEMORY_OPERANDS];
static expressionS im_expressions[MAX_IMMEDIATE_OPERANDS];
/* Current operand we are working on. */
-static int this_operand;
+static int this_operand = -1;
/* We support four different modes. FLAG_CODE variable is used to distinguish
these. */
@@ -1895,6 +1901,8 @@ set_intel_syntax (int syntax_flag)
else
allow_naked_reg = (ask_naked_reg < 0);
+ expr_set_rank (O_full_ptr, syntax_flag ? 10 : 0);
+
identifier_chars['%'] = intel_syntax && allow_naked_reg ? '%' : 0;
identifier_chars['$'] = intel_syntax ? '$' : 0;
register_prefix = allow_naked_reg ? "" : "%";
@@ -2748,6 +2756,7 @@ md_assemble (char *line)
return;
line = parse_operands (line, mnemonic);
+ this_operand = -1;
if (line == NULL)
return;
@@ -6453,6 +6462,8 @@ lex_got (enum bfd_reloc_code_real *reloc,
void
x86_cons (expressionS *exp, int size)
{
+ intel_syntax = -intel_syntax;
+
if (size == 4 || (object_64bit && size == 8))
{
/* Handle @GOTOFF and the like in an expression. */
@@ -6491,6 +6502,11 @@ x86_cons (expressionS *exp, int size)
}
else
expression (exp);
+
+ intel_syntax = -intel_syntax;
+
+ if (intel_syntax)
+ i386_intel_simplify (exp);
}
#endif
@@ -6563,14 +6579,21 @@ i386_immediate (char *imm_start)
input_line_pointer = save_input_line_pointer;
if (gotfree_input_line)
- free (gotfree_input_line);
+ {
+ free (gotfree_input_line);
+
+ if (exp->X_op == O_constant || exp->X_op == O_register)
+ exp->X_op = O_illegal;
+ }
- if (exp->X_op == O_absent
- || exp->X_op == O_illegal
- || exp->X_op == O_big
- || (gotfree_input_line
- && (exp->X_op == O_constant
- || exp->X_op == O_register)))
+ return i386_finalize_immediate (exp_seg, exp, types, imm_start);
+}
+
+static int
+i386_finalize_immediate (segT exp_seg ATTRIBUTE_UNUSED, expressionS *exp,
+ i386_operand_type types, const char *imm_start)
+{
+ if (exp->X_op == O_absent || exp->X_op == O_illegal || exp->X_op == O_big)
{
as_bad (_("missing or invalid immediate expression `%s'"),
imm_start);
@@ -6803,8 +6826,26 @@ i386_displacement (char *disp_start, char *disp_end)
#endif
input_line_pointer = save_input_line_pointer;
if (gotfree_input_line)
- free (gotfree_input_line);
- ret = 1;
+ {
+ free (gotfree_input_line);
+
+ if (exp->X_op == O_constant || exp->X_op == O_register)
+ exp->X_op = O_illegal;
+ }
+
+ ret = i386_finalize_displacement (exp_seg, exp, types, disp_start);
+
+ RESTORE_END_STRING (disp_end);
+
+ return ret;
+}
+
+static int
+i386_finalize_displacement (segT exp_seg ATTRIBUTE_UNUSED, expressionS *exp,
+ i386_operand_type types, const char *disp_start)
+{
+ i386_operand_type bigdisp;
+ int ret = 1;
/* We do this to make sure that the section symbol is in
the symbol table. We will ultimately change the relocation
@@ -6831,10 +6872,7 @@ i386_displacement (char *disp_start, char *disp_end)
else if (exp->X_op == O_absent
|| exp->X_op == O_illegal
- || exp->X_op == O_big
- || (gotfree_input_line
- && (exp->X_op == O_constant
- || exp->X_op == O_register)))
+ || exp->X_op == O_big)
{
inv_disp:
as_bad (_("missing or invalid displacement expression `%s'"),
@@ -6857,8 +6895,6 @@ i386_displacement (char *disp_start, char *disp_end)
}
#endif
- RESTORE_END_STRING (disp_end);
-
/* Check if this is a displacement only operand. */
bigdisp = i.types[this_operand];
bigdisp.bitfield.disp8 = 0;
@@ -7913,23 +7949,45 @@ i386_parse_name (char *name, expressionS *e, char *nextcharP)
}
input_line_pointer = end;
*end = 0;
- return 0;
+ return intel_syntax ? i386_intel_parse_name (name, e) : 0;
}
void
md_operand (expressionS *e)
{
- if (*input_line_pointer == REGISTER_PREFIX)
- {
- char *end;
- const reg_entry *r = parse_real_register (input_line_pointer, &end);
+ char *end;
+ const reg_entry *r;
+ switch (*input_line_pointer)
+ {
+ case REGISTER_PREFIX:
+ r = parse_real_register (input_line_pointer, &end);
if (r)
{
e->X_op = O_register;
e->X_add_number = r - i386_regtab;
input_line_pointer = end;
}
+ break;
+
+ case '[':
+ assert (intel_syntax);
+ end = input_line_pointer++;
+ expression (e);
+ if (*input_line_pointer == ']')
+ {
+ ++input_line_pointer;
+ e->X_op_symbol = make_expr_symbol (e);
+ e->X_add_symbol = NULL;
+ e->X_add_number = 0;
+ e->X_op = O_index;
+ }
+ else
+ {
+ e->X_op = O_absent;
+ input_line_pointer = end;
+ }
+ break;
}
}
@@ -8642,1352 +8700,7 @@ tc_gen_reloc (section, fixp)
return rel;
}
-
-/* Parse operands using Intel syntax. This implements a recursive descent
- parser based on the BNF grammar published in Appendix B of the MASM 6.1
- Programmer's Guide.
-
- FIXME: We do not recognize the full operand grammar defined in the MASM
- documentation. In particular, all the structure/union and
- high-level macro operands are missing.
-
- Uppercase words are terminals, lower case words are non-terminals.
- Objects surrounded by double brackets '[[' ']]' are optional. Vertical
- bars '|' denote choices. Most grammar productions are implemented in
- functions called 'intel_<production>'.
-
- Initial production is 'expr'.
-
- addOp + | -
-
- alpha [a-zA-Z]
-
- binOp & | AND | \| | OR | ^ | XOR
-
- byteRegister AL | AH | BL | BH | CL | CH | DL | DH
-
- constant digits [[ radixOverride ]]
-
- dataType BYTE | WORD | DWORD | FWORD | QWORD | TBYTE | OWORD | XMMWORD | YMMWORD
-
- digits decdigit
- | digits decdigit
- | digits hexdigit
-
- decdigit [0-9]
-
- e04 e04 addOp e05
- | e05
-
- e05 e05 binOp e06
- | e06
-
- e06 e06 mulOp e09
- | e09
-
- e09 OFFSET e10
- | SHORT e10
- | + e10
- | - e10
- | ~ e10
- | NOT e10
- | e09 PTR e10
- | e09 : e10
- | e10
-
- e10 e10 [ expr ]
- | e11
-
- e11 ( expr )
- | [ expr ]
- | constant
- | dataType
- | id
- | $
- | register
-
- => expr expr cmpOp e04
- | e04
-
- gpRegister AX | EAX | BX | EBX | CX | ECX | DX | EDX
- | BP | EBP | SP | ESP | DI | EDI | SI | ESI
-
- hexdigit a | b | c | d | e | f
- | A | B | C | D | E | F
-
- id alpha
- | id alpha
- | id decdigit
-
- mulOp * | / | % | MOD | << | SHL | >> | SHR
-
- quote " | '
-
- register specialRegister
- | gpRegister
- | byteRegister
-
- segmentRegister CS | DS | ES | FS | GS | SS
-
- specialRegister CR0 | CR2 | CR3 | CR4
- | DR0 | DR1 | DR2 | DR3 | DR6 | DR7
- | TR3 | TR4 | TR5 | TR6 | TR7
-
- We simplify the grammar in obvious places (e.g., register parsing is
- done by calling parse_register) and eliminate immediate left recursion
- to implement a recursive-descent parser.
-
- expr e04 expr'
-
- expr' cmpOp e04 expr'
- | Empty
-
- e04 e05 e04'
-
- e04' addOp e05 e04'
- | Empty
-
- e05 e06 e05'
-
- e05' binOp e06 e05'
- | Empty
-
- e06 e09 e06'
-
- e06' mulOp e09 e06'
- | Empty
-
- e09 OFFSET e10 e09'
- | SHORT e10'
- | + e10'
- | - e10'
- | ~ e10'
- | NOT e10'
- | e10 e09'
-
- e09' PTR e10 e09'
- | : e10 e09'
- | Empty
-
- e10 e11 e10'
-
- e10' [ expr ] e10'
- | Empty
-
- e11 ( expr )
- | [ expr ]
- | BYTE
- | WORD
- | DWORD
- | FWORD
- | QWORD
- | TBYTE
- | OWORD
- | XMMWORD
- | YMMWORD
- | .
- | $
- | register
- | id
- | constant */
-
-/* Parsing structure for the intel syntax parser. Used to implement the
- semantic actions for the operand grammar. */
-struct intel_parser_s
- {
- char *op_string; /* The string being parsed. */
- int got_a_float; /* Whether the operand is a float. */
- int op_modifier; /* Operand modifier. */
- int is_mem; /* 1 if operand is memory reference. */
- int in_offset; /* >=1 if parsing operand of offset. */
- int in_bracket; /* >=1 if parsing operand in brackets. */
- const reg_entry *reg; /* Last register reference found. */
- char *disp; /* Displacement string being built. */
- char *next_operand; /* Resume point when splitting operands. */
- };
-
-static struct intel_parser_s intel_parser;
-
-/* Token structure for parsing intel syntax. */
-struct intel_token
- {
- int code; /* Token code. */
- const reg_entry *reg; /* Register entry for register tokens. */
- char *str; /* String representation. */
- };
-
-static struct intel_token cur_token, prev_token;
-
-/* Token codes for the intel parser. Since T_SHORT is already used
- by COFF, undefine it first to prevent a warning. */
-#define T_NIL -1
-#define T_CONST 1
-#define T_REG 2
-#define T_BYTE 3
-#define T_WORD 4
-#define T_DWORD 5
-#define T_FWORD 6
-#define T_QWORD 7
-#define T_TBYTE 8
-#define T_XMMWORD 9
-#undef T_SHORT
-#define T_SHORT 10
-#define T_OFFSET 11
-#define T_PTR 12
-#define T_ID 13
-#define T_SHL 14
-#define T_SHR 15
-#define T_YMMWORD 16
-
-/* Prototypes for intel parser functions. */
-static int intel_match_token (int);
-static void intel_putback_token (void);
-static void intel_get_token (void);
-static int intel_expr (void);
-static int intel_e04 (void);
-static int intel_e05 (void);
-static int intel_e06 (void);
-static int intel_e09 (void);
-static int intel_e10 (void);
-static int intel_e11 (void);
-
-static int
-i386_intel_operand (char *operand_string, int got_a_float)
-{
- int ret;
- char *p;
- const reg_entry *final_base = i.base_reg;
- const reg_entry *final_index = i.index_reg;
-
- p = intel_parser.op_string = xstrdup (operand_string);
- intel_parser.disp = (char *) xmalloc (strlen (operand_string) + 1);
-
- for (;;)
- {
- /* Initialize token holders. */
- cur_token.code = prev_token.code = T_NIL;
- cur_token.reg = prev_token.reg = NULL;
- cur_token.str = prev_token.str = NULL;
-
- /* Initialize parser structure. */
- intel_parser.got_a_float = got_a_float;
- intel_parser.op_modifier = 0;
- intel_parser.is_mem = 0;
- intel_parser.in_offset = 0;
- intel_parser.in_bracket = 0;
- intel_parser.reg = NULL;
- intel_parser.disp[0] = '\0';
- intel_parser.next_operand = NULL;
-
- i.base_reg = NULL;
- i.index_reg = NULL;
-
- /* Read the first token and start the parser. */
- intel_get_token ();
- ret = intel_expr ();
-
- if (!ret)
- break;
-
- if (cur_token.code != T_NIL)
- {
- as_bad (_("invalid operand for '%s' ('%s' unexpected)"),
- current_templates->start->name, cur_token.str);
- ret = 0;
- }
- /* If we found a memory reference, hand it over to i386_displacement
- to fill in the rest of the operand fields. */
- else if (intel_parser.is_mem)
- {
- if ((i.mem_operands == 1
- && !current_templates->start->opcode_modifier.isstring)
- || i.mem_operands == 2)
- {
- as_bad (_("too many memory references for '%s'"),
- current_templates->start->name);
- ret = 0;
- }
- else
- {
- char *s = intel_parser.disp;
-
- if (!quiet_warnings && intel_parser.is_mem < 0)
- /* See the comments in intel_bracket_expr. */
- as_warn (_("Treating `%s' as memory reference"), operand_string);
-
- /* Add the displacement expression. */
- if (*s != '\0')
- ret = i386_displacement (s, s + strlen (s));
- if (ret)
- {
- /* Swap base and index in 16-bit memory operands like
- [si+bx]. Since i386_index_check is also used in AT&T
- mode we have to do that here. */
- if (i.base_reg
- && i.index_reg
- && i.base_reg->reg_type.bitfield.reg16
- && i.index_reg->reg_type.bitfield.reg16
- && i.base_reg->reg_num >= 6
- && i.index_reg->reg_num < 6)
- {
- const reg_entry *base = i.index_reg;
-
- i.index_reg = i.base_reg;
- i.base_reg = base;
- }
- ret = i386_index_check (operand_string);
- }
- if (ret)
- {
- i.types[this_operand].bitfield.mem = 1;
- i.mem_operands++;
- }
- }
- }
-
- /* Constant and OFFSET expressions are handled by i386_immediate. */
- else if ((intel_parser.op_modifier & (1 << T_OFFSET))
- || intel_parser.reg == NULL)
- {
- if (i.mem_operands < 2 && i.seg[i.mem_operands])
- {
- if (!(intel_parser.op_modifier & (1 << T_OFFSET)))
- as_warn (_("Segment override ignored"));
- i.seg[i.mem_operands] = NULL;
- }
- ret = i386_immediate (intel_parser.disp);
- }
-
- if (!final_base && !final_index)
- {
- final_base = i.base_reg;
- final_index = i.index_reg;
- }
-
- if (intel_parser.next_operand && this_operand >= MAX_OPERANDS - 1)
- ret = 0;
- if (!ret || !intel_parser.next_operand)
- break;
- intel_parser.op_string = intel_parser.next_operand;
- this_operand = i.operands++;
- i.types[this_operand].bitfield.unspecified = 1;
- }
-
- free (p);
- free (intel_parser.disp);
-
- if (final_base || final_index)
- {
- i.base_reg = final_base;
- i.index_reg = final_index;
- }
-
- return ret;
-}
-
-#define NUM_ADDRESS_REGS (!!i.base_reg + !!i.index_reg)
-
-/* expr e04 expr'
-
- expr' cmpOp e04 expr'
- | Empty */
-static int
-intel_expr (void)
-{
- /* XXX Implement the comparison operators. */
- return intel_e04 ();
-}
-
-/* e04 e05 e04'
-
- e04' addOp e05 e04'
- | Empty */
-static int
-intel_e04 (void)
-{
- int nregs = -1;
-
- for (;;)
- {
- if (!intel_e05())
- return 0;
-
- if (nregs >= 0 && NUM_ADDRESS_REGS > nregs)
- i.base_reg = i386_regtab + REGNAM_AL; /* al is invalid as base */
-
- if (cur_token.code == '+')
- nregs = -1;
- else if (cur_token.code == '-')
- nregs = NUM_ADDRESS_REGS;
- else
- return 1;
-
- strcat (intel_parser.disp, cur_token.str);
- intel_match_token (cur_token.code);
- }
-}
-
-/* e05 e06 e05'
-
- e05' binOp e06 e05'
- | Empty */
-static int
-intel_e05 (void)
-{
- int nregs = ~NUM_ADDRESS_REGS;
-
- for (;;)
- {
- if (!intel_e06())
- return 0;
-
- if (cur_token.code == '&'
- || cur_token.code == '|'
- || cur_token.code == '^')
- {
- char str[2];
-
- str[0] = cur_token.code;
- str[1] = 0;
- strcat (intel_parser.disp, str);
- }
- else
- break;
-
- intel_match_token (cur_token.code);
-
- if (nregs < 0)
- nregs = ~nregs;
- }
- if (nregs >= 0 && NUM_ADDRESS_REGS > nregs)
- i.base_reg = i386_regtab + REGNAM_AL + 1; /* cl is invalid as base */
- return 1;
-}
-
-/* e06 e09 e06'
-
- e06' mulOp e09 e06'
- | Empty */
-static int
-intel_e06 (void)
-{
- int nregs = ~NUM_ADDRESS_REGS;
-
- for (;;)
- {
- if (!intel_e09())
- return 0;
-
- if (cur_token.code == '*'
- || cur_token.code == '/'
- || cur_token.code == '%')
- {
- char str[2];
-
- str[0] = cur_token.code;
- str[1] = 0;
- strcat (intel_parser.disp, str);
- }
- else if (cur_token.code == T_SHL)
- strcat (intel_parser.disp, "<<");
- else if (cur_token.code == T_SHR)
- strcat (intel_parser.disp, ">>");
- else
- break;
-
- intel_match_token (cur_token.code);
-
- if (nregs < 0)
- nregs = ~nregs;
- }
- if (nregs >= 0 && NUM_ADDRESS_REGS > nregs)
- i.base_reg = i386_regtab + REGNAM_AL + 2; /* dl is invalid as base */
- return 1;
-}
-
-/* e09 OFFSET e09
- | SHORT e09
- | + e09
- | - e09
- | ~ e09
- | NOT e09
- | e10 e09'
-
- e09' PTR e10 e09'
- | : e10 e09'
- | Empty */
-static int
-intel_e09 (void)
-{
- int nregs = ~NUM_ADDRESS_REGS;
- int in_offset = 0;
-
- for (;;)
- {
- /* Don't consume constants here. */
- if (cur_token.code == '+' || cur_token.code == '-')
- {
- /* Need to look one token ahead - if the next token
- is a constant, the current token is its sign. */
- int next_code;
-
- intel_match_token (cur_token.code);
- next_code = cur_token.code;
- intel_putback_token ();
- if (next_code == T_CONST)
- break;
- }
-
- /* e09 OFFSET e09 */
- if (cur_token.code == T_OFFSET)
- {
- if (!in_offset++)
- ++intel_parser.in_offset;
- }
-
- /* e09 SHORT e09 */
- else if (cur_token.code == T_SHORT)
- intel_parser.op_modifier |= 1 << T_SHORT;
-
- /* e09 + e09 */
- else if (cur_token.code == '+')
- strcat (intel_parser.disp, "+");
-
- /* e09 - e09
- | ~ e09
- | NOT e09 */
- else if (cur_token.code == '-' || cur_token.code == '~')
- {
- char str[2];
-
- if (nregs < 0)
- nregs = ~nregs;
- str[0] = cur_token.code;
- str[1] = 0;
- strcat (intel_parser.disp, str);
- }
-
- /* e09 e10 e09' */
- else
- break;
-
- intel_match_token (cur_token.code);
- }
-
- for (;;)
- {
- if (!intel_e10 ())
- return 0;
-
- /* e09' PTR e10 e09' */
- if (cur_token.code == T_PTR)
- {
- char suffix;
-
- if (prev_token.code == T_BYTE)
- {
- suffix = BYTE_MNEM_SUFFIX;
- i.types[this_operand].bitfield.byte = 1;
- }
-
- else if (prev_token.code == T_WORD)
- {
- if ((current_templates->start->name[0] == 'l'
- && current_templates->start->name[2] == 's'
- && current_templates->start->name[3] == 0)
- || current_templates->start->base_opcode == 0x62 /* bound */)
- suffix = BYTE_MNEM_SUFFIX; /* so it will cause an error */
- else if (intel_parser.got_a_float == 2) /* "fi..." */
- suffix = SHORT_MNEM_SUFFIX;
- else
- suffix = WORD_MNEM_SUFFIX;
- i.types[this_operand].bitfield.word = 1;
- }
-
- else if (prev_token.code == T_DWORD)
- {
- if ((current_templates->start->name[0] == 'l'
- && current_templates->start->name[2] == 's'
- && current_templates->start->name[3] == 0)
- || current_templates->start->base_opcode == 0x62 /* bound */)
- suffix = WORD_MNEM_SUFFIX;
- else if (flag_code == CODE_16BIT
- && (current_templates->start->opcode_modifier.jump
- || current_templates->start->opcode_modifier.jumpdword))
- suffix = LONG_DOUBLE_MNEM_SUFFIX;
- else if (intel_parser.got_a_float == 1) /* "f..." */
- suffix = SHORT_MNEM_SUFFIX;
- else
- suffix = LONG_MNEM_SUFFIX;
- i.types[this_operand].bitfield.dword = 1;
- }
-
- else if (prev_token.code == T_FWORD)
- {
- if (current_templates->start->name[0] == 'l'
- && current_templates->start->name[2] == 's'
- && current_templates->start->name[3] == 0)
- suffix = LONG_MNEM_SUFFIX;
- else if (!intel_parser.got_a_float)
- {
- if (flag_code == CODE_16BIT)
- add_prefix (DATA_PREFIX_OPCODE);
- suffix = LONG_DOUBLE_MNEM_SUFFIX;
- }
- else
- suffix = BYTE_MNEM_SUFFIX; /* so it will cause an error */
- i.types[this_operand].bitfield.fword = 1;
- }
-
- else if (prev_token.code == T_QWORD)
- {
- if (current_templates->start->base_opcode == 0x62 /* bound */
- || intel_parser.got_a_float == 1) /* "f..." */
- suffix = LONG_MNEM_SUFFIX;
- else
- suffix = QWORD_MNEM_SUFFIX;
- i.types[this_operand].bitfield.qword = 1;
- }
-
- else if (prev_token.code == T_TBYTE)
- {
- if (intel_parser.got_a_float == 1)
- suffix = LONG_DOUBLE_MNEM_SUFFIX;
- else
- suffix = BYTE_MNEM_SUFFIX; /* so it will cause an error */
- }
-
- else if (prev_token.code == T_XMMWORD)
- {
- suffix = XMMWORD_MNEM_SUFFIX;
- i.types[this_operand].bitfield.xmmword = 1;
- }
-
- else if (prev_token.code == T_YMMWORD)
- {
- suffix = YMMWORD_MNEM_SUFFIX;
- i.types[this_operand].bitfield.ymmword = 1;
- }
-
- else
- {
- as_bad (_("Unknown operand modifier `%s'"), prev_token.str);
- return 0;
- }
-
- i.types[this_operand].bitfield.unspecified = 0;
-
- /* Operands for jump/call using 'ptr' notation denote absolute
- addresses. */
- if (current_templates->start->opcode_modifier.jump
- || current_templates->start->opcode_modifier.jumpdword)
- i.types[this_operand].bitfield.jumpabsolute = 1;
-
- if (current_templates->start->base_opcode == 0x8d /* lea */)
- ;
- else if (!i.suffix)
- i.suffix = suffix;
- else if (i.suffix != suffix)
- {
- as_bad (_("Conflicting operand modifiers"));
- return 0;
- }
-
- }
-
- /* e09' : e10 e09' */
- else if (cur_token.code == ':')
- {
- if (prev_token.code != T_REG)
- {
- /* While {call,jmp} SSSS:OOOO is MASM syntax only when SSSS is a
- segment/group identifier (which we don't have), using comma
- as the operand separator there is even less consistent, since
- there all branches only have a single operand. */
- if (this_operand != 0
- || intel_parser.in_offset
- || intel_parser.in_bracket
- || (!current_templates->start->opcode_modifier.jump
- && !current_templates->start->opcode_modifier.jumpdword
- && !current_templates->start->opcode_modifier.jumpintersegment
- && !current_templates->start->operand_types[0].bitfield.jumpabsolute))
- return intel_match_token (T_NIL);
- /* Remember the start of the 2nd operand and terminate 1st
- operand here.
- XXX This isn't right, yet (when SSSS:OOOO is right operand of
- another expression), but it gets at least the simplest case
- (a plain number or symbol on the left side) right. */
- intel_parser.next_operand = intel_parser.op_string;
- *--intel_parser.op_string = '\0';
- return intel_match_token (':');
- }
- }
-
- /* e09' Empty */
- else
- break;
-
- intel_match_token (cur_token.code);
-
- }
-
- if (in_offset)
- {
- --intel_parser.in_offset;
- if (nregs < 0)
- nregs = ~nregs;
- if (NUM_ADDRESS_REGS > nregs)
- {
- as_bad (_("Invalid operand to `OFFSET'"));
- return 0;
- }
- intel_parser.op_modifier |= 1 << T_OFFSET;
- }
-
- if (nregs >= 0 && NUM_ADDRESS_REGS > nregs)
- i.base_reg = i386_regtab + REGNAM_AL + 3; /* bl is invalid as base */
- return 1;
-}
-
-static int
-intel_bracket_expr (void)
-{
- int was_offset = intel_parser.op_modifier & (1 << T_OFFSET);
- const char *start = intel_parser.op_string;
- int len;
-
- if (i.op[this_operand].regs)
- return intel_match_token (T_NIL);
-
- intel_match_token ('[');
-
- /* Mark as a memory operand only if it's not already known to be an
- offset expression. If it's an offset expression, we need to keep
- the brace in. */
- if (!intel_parser.in_offset)
- {
- ++intel_parser.in_bracket;
-
- /* Operands for jump/call inside brackets denote absolute addresses. */
- if (current_templates->start->opcode_modifier.jump
- || current_templates->start->opcode_modifier.jumpdword)
- i.types[this_operand].bitfield.jumpabsolute = 1;
-
- /* Unfortunately gas always diverged from MASM in a respect that can't
- be easily fixed without risking to break code sequences likely to be
- encountered (the testsuite even check for this): MASM doesn't consider
- an expression inside brackets unconditionally as a memory reference.
- When that is e.g. a constant, an offset expression, or the sum of the
- two, this is still taken as a constant load. gas, however, always
- treated these as memory references. As a compromise, we'll try to make
- offset expressions inside brackets work the MASM way (since that's
- less likely to be found in real world code), but make constants alone
- continue to work the traditional gas way. In either case, issue a
- warning. */
- intel_parser.op_modifier &= ~was_offset;
- }
- else
- strcat (intel_parser.disp, "[");
-
- /* Add a '+' to the displacement string if necessary. */
- if (*intel_parser.disp != '\0'
- && *(intel_parser.disp + strlen (intel_parser.disp) - 1) != '+')
- strcat (intel_parser.disp, "+");
-
- if (intel_expr ()
- && (len = intel_parser.op_string - start - 1,
- intel_match_token (']')))
- {
- /* Preserve brackets when the operand is an offset expression. */
- if (intel_parser.in_offset)
- strcat (intel_parser.disp, "]");
- else
- {
- --intel_parser.in_bracket;
- if (i.base_reg || i.index_reg)
- intel_parser.is_mem = 1;
- if (!intel_parser.is_mem)
- {
- if (!(intel_parser.op_modifier & (1 << T_OFFSET)))
- /* Defer the warning until all of the operand was parsed. */
- intel_parser.is_mem = -1;
- else if (!quiet_warnings)
- as_warn (_("`[%.*s]' taken to mean just `%.*s'"),
- len, start, len, start);
- }
- }
- intel_parser.op_modifier |= was_offset;
-
- return 1;
- }
- return 0;
-}
-
-/* e10 e11 e10'
-
- e10' [ expr ] e10'
- | Empty */
-static int
-intel_e10 (void)
-{
- if (!intel_e11 ())
- return 0;
-
- while (cur_token.code == '[')
- {
- if (!intel_bracket_expr ())
- return 0;
- }
-
- return 1;
-}
-
-/* e11 ( expr )
- | [ expr ]
- | BYTE
- | WORD
- | DWORD
- | FWORD
- | QWORD
- | TBYTE
- | OWORD
- | XMMWORD
- | YMMWORD
- | $
- | .
- | register
- | id
- | constant */
-static int
-intel_e11 (void)
-{
- switch (cur_token.code)
- {
- /* e11 ( expr ) */
- case '(':
- intel_match_token ('(');
- strcat (intel_parser.disp, "(");
-
- if (intel_expr () && intel_match_token (')'))
- {
- strcat (intel_parser.disp, ")");
- return 1;
- }
- return 0;
-
- /* e11 [ expr ] */
- case '[':
- return intel_bracket_expr ();
-
- /* e11 $
- | . */
- case '.':
- strcat (intel_parser.disp, cur_token.str);
- intel_match_token (cur_token.code);
-
- /* Mark as a memory operand only if it's not already known to be an
- offset expression. */
- if (!intel_parser.in_offset)
- intel_parser.is_mem = 1;
-
- return 1;
-
- /* e11 register */
- case T_REG:
- {
- const reg_entry *reg = intel_parser.reg = cur_token.reg;
-
- intel_match_token (T_REG);
-
- /* Check for segment change. */
- if (cur_token.code == ':')
- {
- if (!reg->reg_type.bitfield.sreg2
- && !reg->reg_type.bitfield.sreg3)
- {
- as_bad (_("`%s' is not a valid segment register"),
- reg->reg_name);
- return 0;
- }
- else if (i.mem_operands >= 2)
- as_warn (_("Segment override ignored"));
- else if (i.seg[i.mem_operands])
- as_warn (_("Extra segment override ignored"));
- else
- {
- if (!intel_parser.in_offset)
- intel_parser.is_mem = 1;
- switch (reg->reg_num)
- {
- case 0:
- i.seg[i.mem_operands] = &es;
- break;
- case 1:
- i.seg[i.mem_operands] = &cs;
- break;
- case 2:
- i.seg[i.mem_operands] = &ss;
- break;
- case 3:
- i.seg[i.mem_operands] = &ds;
- break;
- case 4:
- i.seg[i.mem_operands] = &fs;
- break;
- case 5:
- i.seg[i.mem_operands] = &gs;
- break;
- }
- }
- }
-
- else if (reg->reg_type.bitfield.sreg3 && reg->reg_num == RegFlat)
- {
- as_bad (_("cannot use `FLAT' here"));
- return 0;
- }
-
- /* Not a segment register. Check for register scaling. */
- else if (cur_token.code == '*')
- {
- if (!intel_parser.in_bracket)
- {
- as_bad (_("Register scaling only allowed in memory operands"));
- return 0;
- }
-
- if (reg->reg_type.bitfield.reg16) /* Disallow things like [si*1]. */
- reg = i386_regtab + REGNAM_AX + 4; /* sp is invalid as index */
- else if (i.index_reg)
- reg = i386_regtab + REGNAM_EAX + 4; /* esp is invalid as index */
-
- /* What follows must be a valid scale. */
- intel_match_token ('*');
- i.index_reg = reg;
- i.types[this_operand].bitfield.baseindex = 1;
-
- /* Set the scale after setting the register (otherwise,
- i386_scale will complain) */
- if (cur_token.code == '+' || cur_token.code == '-')
- {
- char *str, sign = cur_token.code;
- intel_match_token (cur_token.code);
- if (cur_token.code != T_CONST)
- {
- as_bad (_("Syntax error: Expecting a constant, got `%s'"),
- cur_token.str);
- return 0;
- }
- str = (char *) xmalloc (strlen (cur_token.str) + 2);
- strcpy (str + 1, cur_token.str);
- *str = sign;
- if (!i386_scale (str))
- return 0;
- free (str);
- }
- else if (!i386_scale (cur_token.str))
- return 0;
- intel_match_token (cur_token.code);
- }
-
- /* No scaling. If this is a memory operand, the register is either a
- base register (first occurrence) or an index register (second
- occurrence). */
- else if (intel_parser.in_bracket)
- {
-
- if (!i.base_reg)
- i.base_reg = reg;
- else if (!i.index_reg)
- i.index_reg = reg;
- else
- {
- as_bad (_("Too many register references in memory operand"));
- return 0;
- }
-
- i.types[this_operand].bitfield.baseindex = 1;
- }
-
- /* It's neither base nor index. */
- else if (!intel_parser.in_offset && !intel_parser.is_mem)
- {
- i386_operand_type temp = reg->reg_type;
- temp.bitfield.baseindex = 0;
- i.types[this_operand] = operand_type_or (i.types[this_operand],
- temp);
- i.types[this_operand].bitfield.unspecified = 0;
- i.op[this_operand].regs = reg;
- i.reg_operands++;
- }
- else
- {
- as_bad (_("Invalid use of register"));
- return 0;
- }
-
- /* Since registers are not part of the displacement string (except
- when we're parsing offset operands), we may need to remove any
- preceding '+' from the displacement string. */
- if (*intel_parser.disp != '\0'
- && !intel_parser.in_offset)
- {
- char *s = intel_parser.disp;
- s += strlen (s) - 1;
- if (*s == '+')
- *s = '\0';
- }
-
- return 1;
- }
-
- /* e11 BYTE
- | WORD
- | DWORD
- | FWORD
- | QWORD
- | TBYTE
- | OWORD
- | XMMWORD
- | YMMWORD */
- case T_BYTE:
- case T_WORD:
- case T_DWORD:
- case T_FWORD:
- case T_QWORD:
- case T_TBYTE:
- case T_XMMWORD:
- case T_YMMWORD:
- intel_match_token (cur_token.code);
-
- if (cur_token.code == T_PTR)
- return 1;
-
- /* It must have been an identifier. */
- intel_putback_token ();
- cur_token.code = T_ID;
- /* FALLTHRU */
-
- /* e11 id
- | constant */
- case T_ID:
- if (!intel_parser.in_offset && intel_parser.is_mem <= 0)
- {
- symbolS *symbolP;
-
- /* The identifier represents a memory reference only if it's not
- preceded by an offset modifier and if it's not an equate. */
- symbolP = symbol_find(cur_token.str);
- if (!symbolP || S_GET_SEGMENT(symbolP) != absolute_section)
- intel_parser.is_mem = 1;
- }
- /* FALLTHRU */
-
- case T_CONST:
- case '-':
- case '+':
- {
- char *save_str, sign = 0;
-
- /* Allow constants that start with `+' or `-'. */
- if (cur_token.code == '-' || cur_token.code == '+')
- {
- sign = cur_token.code;
- intel_match_token (cur_token.code);
- if (cur_token.code != T_CONST)
- {
- as_bad (_("Syntax error: Expecting a constant, got `%s'"),
- cur_token.str);
- return 0;
- }
- }
-
- save_str = (char *) xmalloc (strlen (cur_token.str) + 2);
- strcpy (save_str + !!sign, cur_token.str);
- if (sign)
- *save_str = sign;
-
- /* Get the next token to check for register scaling. */
- intel_match_token (cur_token.code);
-
- /* Check if this constant is a scaling factor for an
- index register. */
- if (cur_token.code == '*')
- {
- if (intel_match_token ('*') && cur_token.code == T_REG)
- {
- const reg_entry *reg = cur_token.reg;
-
- if (!intel_parser.in_bracket)
- {
- as_bad (_("Register scaling only allowed "
- "in memory operands"));
- return 0;
- }
-
- /* Disallow things like [1*si].
- sp and esp are invalid as index. */
- if (reg->reg_type.bitfield.reg16)
- reg = i386_regtab + REGNAM_AX + 4;
- else if (i.index_reg)
- reg = i386_regtab + REGNAM_EAX + 4;
-
- /* The constant is followed by `* reg', so it must be
- a valid scale. */
- i.index_reg = reg;
- i.types[this_operand].bitfield.baseindex = 1;
-
- /* Set the scale after setting the register (otherwise,
- i386_scale will complain) */
- if (!i386_scale (save_str))
- return 0;
- intel_match_token (T_REG);
-
- /* Since registers are not part of the displacement
- string, we may need to remove any preceding '+' from
- the displacement string. */
- if (*intel_parser.disp != '\0')
- {
- char *s = intel_parser.disp;
- s += strlen (s) - 1;
- if (*s == '+')
- *s = '\0';
- }
-
- free (save_str);
-
- return 1;
- }
-
- /* The constant was not used for register scaling. Since we have
- already consumed the token following `*' we now need to put it
- back in the stream. */
- intel_putback_token ();
- }
-
- /* Add the constant to the displacement string. */
- strcat (intel_parser.disp, save_str);
- free (save_str);
-
- return 1;
- }
- }
-
- as_bad (_("Unrecognized token '%s'"), cur_token.str);
- return 0;
-}
-
-/* Match the given token against cur_token. If they match, read the next
- token from the operand string. */
-static int
-intel_match_token (int code)
-{
- if (cur_token.code == code)
- {
- intel_get_token ();
- return 1;
- }
- else
- {
- as_bad (_("Unexpected token `%s'"), cur_token.str);
- return 0;
- }
-}
-
-/* Read a new token from intel_parser.op_string and store it in cur_token. */
-static void
-intel_get_token (void)
-{
- char *end_op;
- const reg_entry *reg;
- struct intel_token new_token;
-
- new_token.code = T_NIL;
- new_token.reg = NULL;
- new_token.str = NULL;
-
- /* Free the memory allocated to the previous token and move
- cur_token to prev_token. */
- if (prev_token.str)
- free (prev_token.str);
-
- prev_token = cur_token;
-
- /* Skip whitespace. */
- while (is_space_char (*intel_parser.op_string))
- intel_parser.op_string++;
-
- /* Return an empty token if we find nothing else on the line. */
- if (*intel_parser.op_string == '\0')
- {
- cur_token = new_token;
- return;
- }
-
- /* The new token cannot be larger than the remainder of the operand
- string. */
- new_token.str = (char *) xmalloc (strlen (intel_parser.op_string) + 1);
- new_token.str[0] = '\0';
-
- if (strchr ("0123456789", *intel_parser.op_string))
- {
- char *p = new_token.str;
- char *q = intel_parser.op_string;
- new_token.code = T_CONST;
-
- /* Allow any kind of identifier char to encompass floating point and
- hexadecimal numbers. */
- while (is_identifier_char (*q))
- *p++ = *q++;
- *p = '\0';
-
- /* Recognize special symbol names [0-9][bf]. */
- if (strlen (intel_parser.op_string) == 2
- && (intel_parser.op_string[1] == 'b'
- || intel_parser.op_string[1] == 'f'))
- new_token.code = T_ID;
- }
-
- else if ((reg = parse_register (intel_parser.op_string, &end_op)) != NULL)
- {
- size_t len = end_op - intel_parser.op_string;
-
- new_token.code = T_REG;
- new_token.reg = reg;
-
- memcpy (new_token.str, intel_parser.op_string, len);
- new_token.str[len] = '\0';
- }
-
- else if (is_identifier_char (*intel_parser.op_string))
- {
- char *p = new_token.str;
- char *q = intel_parser.op_string;
-
- /* A '.' or '$' followed by an identifier char is an identifier.
- Otherwise, it's operator '.' followed by an expression. */
- if ((*q == '.' || *q == '$') && !is_identifier_char (*(q + 1)))
- {
- new_token.code = '.';
- new_token.str[0] = '.';
- new_token.str[1] = '\0';
- }
- else
- {
- while (is_identifier_char (*q) || *q == '@')
- *p++ = *q++;
- *p = '\0';
-
- if (strcasecmp (new_token.str, "NOT") == 0)
- new_token.code = '~';
-
- else if (strcasecmp (new_token.str, "MOD") == 0)
- new_token.code = '%';
-
- else if (strcasecmp (new_token.str, "AND") == 0)
- new_token.code = '&';
-
- else if (strcasecmp (new_token.str, "OR") == 0)
- new_token.code = '|';
-
- else if (strcasecmp (new_token.str, "XOR") == 0)
- new_token.code = '^';
-
- else if (strcasecmp (new_token.str, "SHL") == 0)
- new_token.code = T_SHL;
-
- else if (strcasecmp (new_token.str, "SHR") == 0)
- new_token.code = T_SHR;
-
- else if (strcasecmp (new_token.str, "BYTE") == 0)
- new_token.code = T_BYTE;
-
- else if (strcasecmp (new_token.str, "WORD") == 0)
- new_token.code = T_WORD;
-
- else if (strcasecmp (new_token.str, "DWORD") == 0)
- new_token.code = T_DWORD;
-
- else if (strcasecmp (new_token.str, "FWORD") == 0)
- new_token.code = T_FWORD;
-
- else if (strcasecmp (new_token.str, "QWORD") == 0)
- new_token.code = T_QWORD;
-
- else if (strcasecmp (new_token.str, "TBYTE") == 0
- /* XXX remove (gcc still uses it) */
- || strcasecmp (new_token.str, "XWORD") == 0)
- new_token.code = T_TBYTE;
-
- else if (strcasecmp (new_token.str, "XMMWORD") == 0
- || strcasecmp (new_token.str, "OWORD") == 0)
- new_token.code = T_XMMWORD;
-
- else if (strcasecmp (new_token.str, "YMMWORD") == 0)
- new_token.code = T_YMMWORD;
-
- else if (strcasecmp (new_token.str, "PTR") == 0)
- new_token.code = T_PTR;
-
- else if (strcasecmp (new_token.str, "SHORT") == 0)
- new_token.code = T_SHORT;
-
- else if (strcasecmp (new_token.str, "OFFSET") == 0)
- {
- new_token.code = T_OFFSET;
-
- /* ??? This is not mentioned in the MASM grammar but gcc
- makes use of it with -mintel-syntax. OFFSET may be
- followed by FLAT: */
- if (strncasecmp (q, " FLAT:", 6) == 0)
- strcat (new_token.str, " FLAT:");
- }
-
- else
- new_token.code = T_ID;
- }
- }
-
- else if (strchr ("+-/*%|&^:[]()~", *intel_parser.op_string))
- {
- new_token.code = *intel_parser.op_string;
- new_token.str[0] = *intel_parser.op_string;
- new_token.str[1] = '\0';
- }
-
- else if (strchr ("<>", *intel_parser.op_string)
- && *intel_parser.op_string == *(intel_parser.op_string + 1))
- {
- new_token.code = *intel_parser.op_string == '<' ? T_SHL : T_SHR;
- new_token.str[0] = *intel_parser.op_string;
- new_token.str[1] = *intel_parser.op_string;
- new_token.str[2] = '\0';
- }
-
- else
- as_bad (_("Unrecognized token `%s'"), intel_parser.op_string);
-
- intel_parser.op_string += strlen (new_token.str);
- cur_token = new_token;
-}
-
-/* Put cur_token back into the token stream and make cur_token point to
- prev_token. */
-static void
-intel_putback_token (void)
-{
- if (cur_token.code != T_NIL)
- {
- intel_parser.op_string -= strlen (cur_token.str);
- free (cur_token.str);
- }
- cur_token = prev_token;
-
- /* Forget prev_token. */
- prev_token.code = T_NIL;
- prev_token.reg = NULL;
- prev_token.str = NULL;
-}
+#include "tc-i386-intel.c"
void
tc_x86_parse_to_dw2regnum (expressionS *exp)
diff --git a/gas/config/tc-i386.h b/gas/config/tc-i386.h
index ea2b6530de..dab3c55b8c 100644
--- a/gas/config/tc-i386.h
+++ b/gas/config/tc-i386.h
@@ -157,6 +157,12 @@ extern int tc_i386_fix_adjustable (struct fix *);
extern int i386_parse_name (char *, expressionS *, char *);
#define md_parse_name(s, e, m, c) i386_parse_name (s, e, c)
+extern operatorT i386_operator (const char *name, unsigned int operands, char *);
+#define md_operator i386_operator
+
+extern int i386_need_index_operator (void);
+#define md_need_index_operator i386_need_index_operator
+
#define md_register_arithmetic 0
extern const struct relax_type md_relax_table[];
@@ -281,4 +287,7 @@ void tc_pe_dwarf2_emit_offset (symbolS *, unsigned int);
#endif /* TE_PE */
+/* X_add_symbol:X_op_symbol (Intel mode only) */
+#define O_full_ptr O_md2
+
#endif /* TC_I386 */
diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog
index 66a68b90a1..ad97bc95cb 100644
--- a/gas/testsuite/ChangeLog
+++ b/gas/testsuite/ChangeLog
@@ -1,3 +1,26 @@
+2009-04-20 Jan Beulich <jbeulich@novell.com>
+
+ * gas/i386/equ.s: Adjust.
+ * gas/i386/equ.d: Remove reference to equ.e.
+ * gas/i386/equ.e: Delete.
+ * gas/i386/intel-expr.s: New.
+ * gas/i386/intel-expr.d: New.
+ * gas/i386/i386.exp: Run new test.
+ * gas/i386/intel.s: Adjust.
+ * gas/i386/intel.e: Remove no longer valid warning messages.
+ * gas/i386/intel16.s: Adjust.
+ * gas/i386/intel16.d: Remove reference to intel16.e.
+ * gas/i386/intel16.e: Delete.
+ * gas/i386/intelbad.s: Add more tests.
+ * gas/i386/intelbad.l: Adjust.
+ * gas/i386/intelok.s: Remove now unneeded equates. Add more
+ tests.
+ * gas/i386/intelok.d: Remove reference to intelok.e. Adjust.
+ * gas/i386/intelok.e: Delete.
+ * gas/i386/x86_64.s: Adjust.
+ * gas/i386/x86_64.d: Remove reference to x86_64.e.
+ * gas/i386/x86_64.e: Delete.
+
2009-04-16 Alan Modra <amodra@bigpond.net.au>
* gas/all/gas.exp: Disable assign and assign-ok tests on blackfin.
diff --git a/gas/testsuite/gas/i386/equ.d b/gas/testsuite/gas/i386/equ.d
index f023abf565..c23616fa36 100644
--- a/gas/testsuite/gas/i386/equ.d
+++ b/gas/testsuite/gas/i386/equ.d
@@ -1,6 +1,5 @@
#objdump: -drw
#name: i386 equates
-#stderr: equ.e
.*: +file format .*
diff --git a/gas/testsuite/gas/i386/equ.e b/gas/testsuite/gas/i386/equ.e
deleted file mode 100644
index 8a485d1ee9..0000000000
--- a/gas/testsuite/gas/i386/equ.e
+++ /dev/null
@@ -1,2 +0,0 @@
-.*: Assembler messages:
-.*:30: Warning: Treating .* as memory reference
diff --git a/gas/testsuite/gas/i386/equ.s b/gas/testsuite/gas/i386/equ.s
index 1b7a796ad0..94ec81d384 100644
--- a/gas/testsuite/gas/i386/equ.s
+++ b/gas/testsuite/gas/i386/equ.s
@@ -27,7 +27,7 @@ _start:
.equ r, -2
.equ s, -2
mov eax, r
- mov eax, [r]
+ mov eax, FLAT:[r]
.equ r, xtrn
mov eax, offset r
mov eax, [r]
diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp
index 09d773a604..5352bac981 100644
--- a/gas/testsuite/gas/i386/i386.exp
+++ b/gas/testsuite/gas/i386/i386.exp
@@ -197,6 +197,7 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_32_check]]
}
if [expr [istarget "i*86-*-*"] || [istarget "x86_64-*-*"]] then {
+ run_dump_test "intel-expr"
run_dump_test "string-ok"
run_list_test "string-bad" ""
}
diff --git a/gas/testsuite/gas/i386/intel.e b/gas/testsuite/gas/i386/intel.e
index 6f7b365638..9c0e76c8c2 100644
--- a/gas/testsuite/gas/i386/intel.e
+++ b/gas/testsuite/gas/i386/intel.e
@@ -1,10 +1,4 @@
.*: Assembler messages:
-.*:154: Warning: Treating `\[0x90909090\]' as memory reference
-.*:155: Warning: Treating `\[0x90909090\]' as memory reference
-.*:156: Warning: Treating `\[0x90909090\]' as memory reference
-.*:157: Warning: Treating `\[0x90909090\]' as memory reference
-.*:494: Warning: Treating `\[0x90909090\]' as memory reference
-.*:495: Warning: Treating `\[0x90909090\]' as memory reference
.*:635: Warning: translating to `faddp'
.*:644: Warning: translating to `fdivp'
.*:653: Warning: translating to `fdivp st\(3\),st'
diff --git a/gas/testsuite/gas/i386/intel.s b/gas/testsuite/gas/i386/intel.s
index 7c247e9bb9..a3a07b336a 100644
--- a/gas/testsuite/gas/i386/intel.s
+++ b/gas/testsuite/gas/i386/intel.s
@@ -145,16 +145,16 @@ foo:
xchg edi, eax
cwde
cdq
- call 0x9090,0x90909090
+ call 0x9090:0x90909090
fwait
pushf
popf
sahf
lahf
- mov al, [0x90909090]
- mov eax, [0x90909090]
- mov [0x90909090], al
- mov [0x90909090], eax
+ mov al, FLAT:[0x90909090]
+ mov eax, FLAT:[0x90909090]
+ mov FLAT:[0x90909090], al
+ mov FLAT:[0x90909090], eax
movs byte ptr es:[edi], byte ptr ds:[esi]
movs dword ptr es:[edi], dword ptr ds:[esi]
cmps byte ptr ds:[esi], byte ptr es:[edi]
@@ -226,7 +226,7 @@ foo:
out 0x90, eax
call .+5+0x90909090
jmp .+5+0x90909090
- jmp 0x9090,0x90909090
+ jmp 0x9090:0x90909090
jmp .+2-0x70
in al, dx
in eax, dx
@@ -488,11 +488,11 @@ foo:
xchg di, ax
cbw
cwd
- callw 0x9090,0x9090
+ callw 0x9090:0x9090
pushfw
popfw
- mov ax, [0x90909090]
- mov [0x90909090], ax
+ mov ax, FLAT:[0x90909090]
+ mov FLAT:[0x90909090], ax
movs word ptr es:[edi], word ptr ds:[esi]
cmps word ptr ds:[esi], word ptr es:[edi]
test ax, 0x9090
@@ -525,7 +525,7 @@ foo:
in ax, 0x90
out 0x90, ax
callw .+3+0x9090
- jmpw 0x9090,0x9090
+ jmpw 0x9090:0x9090
in ax, dx
out dx, ax
not word ptr 0x90909090[eax]
@@ -599,7 +599,7 @@ rot5:
mov eax, [ebx*2]
adc BYTE PTR [eax*4+0x90909090], dl
das
- jmp 0x9090,0x90909090
+ jmp 0x9090:0x90909090
movs WORD PTR es:[edi], WORD PTR ds:[esi]
jo .+2-0x70
@@ -617,7 +617,7 @@ rot5:
mov ax, word ptr [ebx+2*eax+(2*(4095+1)*2)]
jmp eax
jmp [eax]
- jmp [bar]
+ jmp FLAT:[bar]
jmp bar
# Check arithmetic operators
diff --git a/gas/testsuite/gas/i386/intel16.d b/gas/testsuite/gas/i386/intel16.d
index e6d0ee28f8..45bb2030db 100644
--- a/gas/testsuite/gas/i386/intel16.d
+++ b/gas/testsuite/gas/i386/intel16.d
@@ -1,6 +1,5 @@
#objdump: -dw -mi8086
#name: i386 intel16
-#stderr: intel16.e
.*: +file format .*
diff --git a/gas/testsuite/gas/i386/intel16.e b/gas/testsuite/gas/i386/intel16.e
deleted file mode 100644
index 62da8a775e..0000000000
--- a/gas/testsuite/gas/i386/intel16.e
+++ /dev/null
@@ -1,7 +0,0 @@
-.*: Assembler messages:
-.*:5: Warning: Treating .word ptr \[0\]. as memory reference
-.*:6: Warning: Treating .byte ptr \[0\]. as memory reference
-.*:7: Warning: Treating .byte ptr \[0\]. as memory reference
-.*:8: Warning: Treating .word ptr \[0\]. as memory reference
-.*:9: Warning: Treating .byte ptr \[0\]. as memory reference
-.*:10: Warning: Treating .byte ptr \[0\]. as memory reference
diff --git a/gas/testsuite/gas/i386/intel16.s b/gas/testsuite/gas/i386/intel16.s
index e27b017310..14a9792479 100644
--- a/gas/testsuite/gas/i386/intel16.s
+++ b/gas/testsuite/gas/i386/intel16.s
@@ -2,12 +2,12 @@
.code16
.text
- movsx eax,word ptr [0]
- movsx eax,byte ptr [0]
- movsx ax,byte ptr [0]
- movzx eax,word ptr [0]
- movzx eax,byte ptr [0]
- movzx ax,byte ptr [0]
+ movsx eax,word ptr ds:[0]
+ movsx eax,byte ptr ds:[0]
+ movsx ax,byte ptr ds:[0]
+ movzx eax,word ptr ds:[0]
+ movzx eax,byte ptr ds:[0]
+ movzx ax,byte ptr ds:[0]
lea ax, [si+bx]
lea ax, [si+bp]
diff --git a/gas/testsuite/gas/i386/intelbad.l b/gas/testsuite/gas/i386/intelbad.l
index b10a6c443c..bdc2645c85 100644
--- a/gas/testsuite/gas/i386/intelbad.l
+++ b/gas/testsuite/gas/i386/intelbad.l
@@ -76,8 +76,9 @@
.*:79: Error: .*
.*:80: Error: .*
.*:91: Error: .*
-.*:92: Error: .*
+.*:92: (Warning|Error): .*
.*:93: Error: .*
+#...
.*:96: Error: .*
.*:97: Error: .*
.*:98: Error: .*
@@ -99,6 +100,7 @@
.*:114: Error: .*
.*:115: Error: .*
.*:116: Error: .*
+#...
.*:117: Error: .*
.*:119: Error: .*
.*:120: Error: .*
@@ -131,18 +133,23 @@
.*:151: Error: .*
.*:152: Error: .*
.*:153: Error: .*
-#...
.*:154: Error: .*
-#...
.*:155: Error: .*
.*:156: Error: .*
-.*:157: Error: .*
-.*:158: Error: .*
+#XXX? .*:157: Error: .*
+#XXX? .*:158: Error: .*
+.*:159: Error: .*
+#...
.*:160: Error: .*
.*:161: Error: .*
.*:162: Error: .*
-.*:163: Warning: .*
-.*:164: Warning: .*
+.*:163: Error: .*
+.*:164: Error: .*
+.*:165: Error: .*
.*:166: Error: .*
-.*:167: Warning: .*
+#...
.*:167: Error: .*
+.*:168: Error: .*
+.*:169: Error: .*
+.*:170: Error: .*
+.*:172: Error: .*
diff --git a/gas/testsuite/gas/i386/intelbad.s b/gas/testsuite/gas/i386/intelbad.s
index 2489c1211d..9df2aa24cb 100644
--- a/gas/testsuite/gas/i386/intelbad.s
+++ b/gas/testsuite/gas/i386/intelbad.s
@@ -149,19 +149,24 @@ start:
mov eax, [ah]
mov eax, [ax]
mov eax, [eax+bx]
+ mov eax, offset [eax]
+ mov eax, offset eax
+ mov eax, offset offset eax
mov eax, offset [1*eax]
mov eax, offset 1*eax
- mov eax, offset x[eax] # ugly diag
- mov eax, offset [x][eax] # ugly diag
+#XXX? mov eax, offset x[eax]
+#XXX? mov eax, offset [x][eax]
mov eax, flat x
mov eax, flat [x]
mov eax, es:eax
-
- mov eax, offset [eax]
- mov eax, offset eax
- mov eax, offset offset eax
- mov eax, es:ss:[eax]
- mov eax, es:[eax]+ss:[eax]
+ mov eax, eax[ebp]
+ movzx eax, 1 ptr [eax]
+ movzx eax, byte word ptr [eax]
+ movzx eax, [byte ptr eax]
+ movzx eax, byte [ptr [eax]]
+ movzx eax, byte ptr [gs:eax]
+ movzx eax, byte gs:ptr [eax]
+ movzx eax, byte ptr 1
+ movzx eax, byte ptr [1]
mov eax, 3:5
- call 3:[5]
diff --git a/gas/testsuite/gas/i386/intelok.d b/gas/testsuite/gas/i386/intelok.d
index 27f1217b2b..e4ede94f62 100644
--- a/gas/testsuite/gas/i386/intelok.d
+++ b/gas/testsuite/gas/i386/intelok.d
@@ -1,7 +1,6 @@
#as: -J --divide
#objdump: -dwMintel
#name: i386 intel-ok
-#stderr: intelok.e
.*: +file format .*
@@ -108,6 +107,19 @@ Disassembly of section .text:
[ ]*[0-9a-f]+: 8b 40 12[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+0x12\]
[ ]*[0-9a-f]+: 8b 04 85 02 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\*4\+(0x)?2\]
[ ]*[0-9a-f]+: 8b 04 85 02 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\*4\+(0x)?2\]
+[ ]*[0-9a-f]+: 0f b7 00[ ]+movzx[ ]+eax,WORD PTR \[eax\]
+[ ]*[0-9a-f]+: 0f b6 00[ ]+movzx[ ]+eax,BYTE PTR \[eax\]
+[ ]*[0-9a-f]+: 26 0f b7 00[ ]+movzx[ ]+eax,WORD PTR es:\[eax\]
+[ ]*[0-9a-f]+: 64 0f b6 00[ ]+movzx[ ]+eax,BYTE PTR fs:\[eax\]
+[ ]*[0-9a-f]+: 65 0f b7 00[ ]+movzx[ ]+eax,WORD PTR gs:\[eax\]
+[ ]*[0-9a-f]+: a1 01 00 00 00[ ]+mov[ ]+eax,ds:(0x)?1
+[ ]*[0-9a-f]+: a1 01 00 00 00[ ]+mov[ ]+eax,ds:(0x)?1
+[ ]*[0-9a-f]+: 65 a1 01 00 00 00[ ]+mov[ ]+eax,gs:(0x)?1
+[ ]*[0-9a-f]+: 65 a1 01 00 00 00[ ]+mov[ ]+eax,gs:(0x)?1
+[ ]*[0-9a-f]+: a1 00 00 00 00[ ]+mov[ ]+eax,ds:(0x)?0
+[ ]*[0-9a-f]+: a1 00 00 00 00[ ]+mov[ ]+eax,ds:(0x)?0
+[ ]*[0-9a-f]+: 65 a1 00 00 00 00[ ]+mov[ ]+eax,gs:(0x)?0
+[ ]*[0-9a-f]+: a1 00 00 00 00[ ]+mov[ ]+eax,ds:(0x)?0
[ ]*[0-9a-f]+: 8b 04 05 00 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\*1\+(0x)?0]
[ ]*[0-9a-f]+: 8b 04 05 00 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\*1\+(0x)?0]
[ ]*[0-9a-f]+: 8b 04 05 00 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\*1\+(0x)?0]
@@ -123,15 +135,20 @@ Disassembly of section .text:
[ ]*[0-9a-f]+: 8b 40 10[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+0x10\]
[ ]*[0-9a-f]+: 8b 40 10[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+0x10\]
[ ]*[0-9a-f]+: 8b 44 08 10[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\*1\+0x10\]
+[ ]*[0-9a-f]+: 8b 04 08[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\*1\]
[ ]*[0-9a-f]+: 8b 44 08 01[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\*1\+(0x)?1\]
-[ ]*[0-9a-f]+: 8b 44 08 01[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\*1\+(0x)?1\]
-[ ]*[0-9a-f]+: 8b 44 08 01[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\*1\+(0x)?1\]
-[ ]*[0-9a-f]+: 8b 44 08 01[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\*1\+(0x)?1\]
-[ ]*[0-9a-f]+: 8b 44 08 01[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\*1\+(0x)?1\]
+[ ]*[0-9a-f]+: 8b 44 08 02[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\*1\+(0x)?2\]
+[ ]*[0-9a-f]+: 8b 44 08 03[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\*1\+(0x)?3\]
+[ ]*[0-9a-f]+: 8b 44 08 04[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\*1\+(0x)?4\]
+[ ]*[0-9a-f]+: 8b 44 08 05[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\*1\+(0x)?5\]
+[ ]*[0-9a-f]+: 8b 44 08 06[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\*1\+(0x)?6\]
+[ ]*[0-9a-f]+: 8b 44 88 07[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\*4\+(0x)?7\]
+[ ]*[0-9a-f]+: 8b 44 88 08[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\*4\+(0x)?8\]
[ ]*[0-9a-f]+: 8b 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\]
[ ]*[0-9a-f]+: 8b 04 08[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\*1\]
[ ]*[0-9a-f]+: 8b 04 08[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+ecx\*1\]
[ ]*[0-9a-f]+: 26 8b 00[ ]+mov[ ]+eax,(DWORD PTR )?es:\[eax\]
+[ ]*[0-9a-f]+: 64 8b 00[ ]+mov[ ]+eax,(DWORD PTR )?fs:\[eax\]
[ ]*[0-9a-f]+: 6a 01[ ]+push[ ]+0x1
[ ]*[0-9a-f]+: 6a ff[ ]+push[ ]+0xffffffff
[ ]*[0-9a-f]+: 6a fe[ ]+push[ ]+0xfffffffe
@@ -151,31 +168,40 @@ Disassembly of section .text:
[ ]*[0-9a-f]+: 6a fb[ ]+push[ ]+0xfffffffb
[ ]*[0-9a-f]+: 6a 03[ ]+push[ ]+0x3
[ ]*[0-9a-f]+: 6a 04[ ]+push[ ]+0x4
-[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,0x0
-[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,0x0
-[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,0x0
-[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,0x0
-[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,0x0
-[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,0x0
-[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,0x0
+[ ]*[0-9a-f]+: b8 01 00 00 00[ ]+mov[ ]+eax,(0x)?1
+[ ]*[0-9a-f]+: b8 01 00 00 00[ ]+mov[ ]+eax,(0x)?1
+[ ]*[0-9a-f]+: b8 01 00 00 00[ ]+mov[ ]+eax,(0x)?1
+[ ]*[0-9a-f]+: b8 01 00 00 00[ ]+mov[ ]+eax,(0x)?1
+[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,(0x)?0
+[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,(0x)?0
+[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,(0x)?0
+[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,(0x)?0
+[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,(0x)?0
+[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,(0x)?0
+[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,(0x)?0
+[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,(0x)?0
+[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,(0x)?0
+[ ]*[0-9a-f]+: a1 00 00 00 00[ ]+mov[ ]+eax,ds:(0x)?0
+[ ]*[0-9a-f]+: 65 a1 00 00 00 00[ ]+mov[ ]+eax,gs:(0x)?0
+[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,(0x)?0
+[ ]*[0-9a-f]+: b8 00 00 00 00[ ]+mov[ ]+eax,(0x)?0
[ ]*[0-9a-f]+: 8b 80 00 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+(0x)?0\]
[ ]*[0-9a-f]+: 8b 40 01[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+(0x)?1]
[ ]*[0-9a-f]+: 8b 80 00 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+(0x)?0\]
+[ ]*[0-9a-f]+: 8b 40 01[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+(0x)?1]
[ ]*[0-9a-f]+: 8b 80 01 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+(0x)?1\]
[ ]*[0-9a-f]+: 8b 80 00 00 00 00[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+(0x)?0\]
[ ]*[0-9a-f]+: 8b 40 01[ ]+mov[ ]+eax,(DWORD PTR )?\[eax\+(0x)?1\]
-[ ]*[0-9a-f]+: a1 01 00 00 00[ ]+mov[ ]+eax,ds:0x1
-[ ]*[0-9a-f]+: a1 ff ff ff ff[ ]+mov[ ]+eax,ds:0xffffffff
-[ ]*[0-9a-f]+: 26 a1 02 00 00 00[ ]+mov[ ]+eax,es:0x2
-#...
-[ ]*[0-9a-f]+: b8 03 00 00 00[ ]+mov[ ]+eax,0x3
-[ ]*[0-9a-f]+: a1 04 00 00 00[ ]+mov[ ]+eax,ds:0x4
-[ ]*[0-9a-f]+: a1 05 00 00 00[ ]+mov[ ]+eax,ds:0x5
-[ ]*[0-9a-f]+: 36 a1 06 00 00 00[ ]+mov[ ]+eax,ss:0x6
-[ ]*[0-9a-f]+: 36 a1 07 00 00 00[ ]+mov[ ]+eax,ss:0x7
-[ ]*[0-9a-f]+: a1 08 00 00 00[ ]+mov[ ]+eax,ds:0x8
+[ ]*[0-9a-f]+: b8 01 00 00 00[ ]+mov[ ]+eax,(0x)?1
+[ ]*[0-9a-f]+: b8 ff ff ff ff[ ]+mov[ ]+eax,(0xffffffff|-1)
+[ ]*[0-9a-f]+: 26 a1 02 00 00 00[ ]+mov[ ]+eax,es:(0x)?2
+[ ]*[0-9a-f]+: b8 03 00 00 00[ ]+mov[ ]+eax,(0x)?3
+[ ]*[0-9a-f]+: b8 04 00 00 00[ ]+mov[ ]+eax,(0x)?4
+[ ]*[0-9a-f]+: b8 05 00 00 00[ ]+mov[ ]+eax,(0x)?5
+[ ]*[0-9a-f]+: 36 a1 06 00 00 00[ ]+mov[ ]+eax,ss:(0x)?6
+[ ]*[0-9a-f]+: 36 a1 07 00 00 00[ ]+mov[ ]+eax,ss:(0x)?7
[ ]*[0-9a-f]+: 9a 05 00 00 00 03 00[ ]+l?call[ ]+0x3[,:]0x5
[ ]*[0-9a-f]+: ea 03 00 00 00 05 00[ ]+l?jmp[ ]+0x5[,:]0x3
-[ ]*[0-9a-f]+: ff 15 00 00 00 00[ ]+call[ ]+(DWORD PTR )?(ds:)?0x0
-[ ]*[0-9a-f]+: 66 ff 25 00 00 00 00[ ]+jmp[ ]+(WORD PTR )?(ds:)?0x0
+[ ]*[0-9a-f]+: ff 15 00 00 00 00[ ]+call[ ]+DWORD PTR (ds:)?(0x)?0
+[ ]*[0-9a-f]+: 66 ff 25 00 00 00 00[ ]+jmp[ ]+WORD PTR (ds:)?(0x)?0
#pass
diff --git a/gas/testsuite/gas/i386/intelok.e b/gas/testsuite/gas/i386/intelok.e
deleted file mode 100644
index e49436ed63..0000000000
--- a/gas/testsuite/gas/i386/intelok.e
+++ /dev/null
@@ -1,8 +0,0 @@
-.*: Assembler messages:
-.*:175: Warning: .* taken to mean just .*
-.*:182: Warning: Treating .* as memory reference
-.*:183: Warning: .* taken to mean just .*
-.*:183: Warning: Treating .* as memory reference
-.*:186: Warning: Treating .* as memory reference
-.*:187: Warning: Treating .* as memory reference
-.*:190: Warning: Treating .* as memory reference
diff --git a/gas/testsuite/gas/i386/intelok.s b/gas/testsuite/gas/i386/intelok.s
index 2f78929d1b..00cf4da717 100644
--- a/gas/testsuite/gas/i386/intelok.s
+++ b/gas/testsuite/gas/i386/intelok.s
@@ -1,12 +1,4 @@
.intel_syntax noprefix
- .equiv byte, 1
- .equiv word, 2
- .equiv dword, 4
- .equiv fword, 6
- .equiv qword, 8
- .equiv tbyte, 10
- .equiv oword, 16
- .equiv xmmword, 16
.text
start:
@@ -115,6 +107,20 @@ start:
mov eax, tbyte[eax+dword*2]
mov eax, [word+eax*dword]
mov eax, word[eax*dword]
+ movzx eax, word ptr byte ptr [eax]
+ movzx eax, byte ptr [word ptr [eax]]
+ movzx eax, word ptr es:[eax]
+ movzx eax, byte ptr [fs:[eax]]
+ movzx eax, gs:word ptr [eax]
+
+ mov eax, FLAT:1
+ mov eax, FLAT:[1]
+ mov eax, gs:1
+ mov eax, gs:[1]
+ mov eax, x
+ mov eax, FLAT:x
+ mov eax, gs:x
+ mov eax, [x]
mov eax, [eax*1]
mov eax, [eax*+1]
@@ -127,19 +133,24 @@ start:
mov eax, [eax]+1
mov eax, [eax - 5 + ecx]
mov eax, [eax + 5 and 3 + ecx]
- mov eax, [eax + 5*3 + ecx]
+ mov eax, [eax + 5 * 3 + ecx]
mov eax, [oword][eax]
mov eax, [eax][oword]
mov eax, xmmword[eax][ecx]
+ mov eax, [eax]+[ecx]
mov eax, [eax]+1[ecx]
- mov eax, [eax][ecx]+1
- mov eax, [1][eax][ecx]
- mov eax, [eax][1][ecx]
- mov eax, [eax][ecx][1]
+ mov eax, [eax+2[ecx]]
+ mov eax, [eax][ecx]+3
+ mov eax, [4][eax][ecx]
+ mov eax, [eax][5][ecx]
+ mov eax, [eax][ecx][6]
+ mov eax, [eax+ecx*(2+2)+7]
+ mov eax, [eax+(ecx+2)*4]
mov eax, [[eax]]
mov eax, [eax[ecx]]
mov eax, [[eax][ecx]]
mov eax, es:[eax]
+ mov eax, fs:gs:[eax]
# expressions
@@ -166,6 +177,10 @@ start:
# offset expressions
+ mov eax, 1
+ mov eax, [1]
+ mov eax, dword ptr 1
+ mov eax, dword ptr [1]
mov eax, offset x
mov eax, offset flat:x
mov eax, offset gs:x
@@ -173,10 +188,17 @@ start:
mov eax, offset flat:[x]
mov eax, offset gs:[x]
mov eax, [offset x]
+ mov eax, [offset [x]]
+ mov eax, dword ptr [offset [x]]
+ mov eax, FLAT:[offset [x]]
+ mov eax, gs:[offset [x]]
+ mov eax, offset [dword ptr [x]]
+ mov eax, offset [gs:[x]]
mov eax, [eax + offset x]
mov eax, [eax + offset 1]
mov eax, [offset x + eax]
- mov eax, offset x+1[eax]
+ mov eax, [offset 1 + eax]
+ mov eax, offset x + 1[eax]
mov eax, [eax] + offset x
mov eax, [eax] + offset 1
mov eax, offset x + [1]
@@ -187,11 +209,10 @@ start:
mov eax, [5] + [offset x]
mov eax, ss:[6] + offset x
mov eax, ss:[7] + [offset x]
- mov eax, dword ptr [8]
# other operands
call 3:5
- jmp 5:3
+ jmp 5:[3]
call dword ptr xtrn
jmp word ptr xtrn
diff --git a/gas/testsuite/gas/i386/x86_64.d b/gas/testsuite/gas/i386/x86_64.d
index cbf769aa40..086cc3ace4 100644
--- a/gas/testsuite/gas/i386/x86_64.d
+++ b/gas/testsuite/gas/i386/x86_64.d
@@ -1,7 +1,6 @@
#as: -J
#objdump: -dw
#name: x86_64
-#stderr: x86_64.e
.*: +file format .*
Disassembly of section .text:
diff --git a/gas/testsuite/gas/i386/x86_64.e b/gas/testsuite/gas/i386/x86_64.e
deleted file mode 100644
index e11e90358f..0000000000
--- a/gas/testsuite/gas/i386/x86_64.e
+++ /dev/null
@@ -1,9 +0,0 @@
-.*.s: Assembler messages:
-.*:51: Warning: Treating .\[0x22222222\]. as memory reference
-.*:89: Warning: Treating .DWORD PTR \[0x22222222\]. as memory reference
-.*:91: Warning: Treating .\[0x8877665544332211\]. as memory reference
-.*:92: Warning: Treating .\[0x8877665544332211\]. as memory reference
-.*:93: Warning: Treating .\[0x8877665544332211\]. as memory reference
-.*:94: Warning: Treating .\[0x8877665544332211\]. as memory reference
-.*:95: Warning: Treating .\[0x8877665544332211\]. as memory reference
-.*:96: Warning: Treating .\[0x8877665544332211\]. as memory reference
diff --git a/gas/testsuite/gas/i386/x86_64.s b/gas/testsuite/gas/i386/x86_64.s
index 34c8cdf8f2..ef887d5b5f 100644
--- a/gas/testsuite/gas/i386/x86_64.s
+++ b/gas/testsuite/gas/i386/x86_64.s
@@ -48,7 +48,7 @@ ADD R8D,[R8]
ADD RAX,[R8]
ADD EAX,[0x22222222+RIP]
ADD EAX,[RBP+0x00]
-ADD EAX,[0x22222222]
+ADD EAX,FLAT:[0x22222222]
ADD EAX,[R13+0]
ADD EAX,[RAX+RAX*4]
ADD EAX,[R8+RAX*4]
@@ -86,14 +86,14 @@ ADD DWORD PTR [RAX*8+0x22222222],0x33
ADD DWORD PTR [RAX+0x22222222],0x33
ADD DWORD PTR [RAX+0x22222222],0x33
ADD DWORD PTR [R8+RBP*8],0x33
-ADD DWORD PTR [0x22222222],0x33
+ADD DWORD PTR FLAT:[0x22222222],0x33
#new instructions
-MOVABS AL,[0x8877665544332211]
-MOVABS EAX,[0x8877665544332211]
-MOVABS [0x8877665544332211],AL
-MOVABS [0x8877665544332211],EAX
-MOVABS RAX,[0x8877665544332211]
-MOVABS [0x8877665544332211],RAX
+MOVABS AL,FLAT:[0x8877665544332211]
+MOVABS EAX,FLAT:[0x8877665544332211]
+MOVABS FLAT:[0x8877665544332211],AL
+MOVABS FLAT:[0x8877665544332211],EAX
+MOVABS RAX,FLAT:[0x8877665544332211]
+MOVABS FLAT:[0x8877665544332211],RAX
cqo
cdqe
movsx rax, eax