This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 2/2] x86: replace Intel syntax parser


This patch removes the old, ad-hoc (and slightly incomplete) Intel
syntax parser that was usable only for instruction operands, and
replaces it with one hooked up to the normal expression parser, thus
now usable also in expressions used in directives.

There's one particular aspect where masm would reject a construct gas
now accepts - this is recorded as two "#XXX?"-commented cases in the
intelbad.[sl] test: masm apparently treats [] as having a higher
precedence than the unary offset operator, something not easily doable
in gas' expression handling, which assumes that all unary operators
have a higher precedence than all binary operators. This is not viewed
as a problem, however, as the meaning of these constructs is
unambiguous and would never occur in ported over sources.

gas/
2009-04-16  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-16  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-15/gas/Makefile.am	2009-04-15 08:47:20.000000000 +0200
+++ 2009-04-15/gas/Makefile.am	2009-02-05 14:42:22.000000000 +0100
@@ -614,6 +614,8 @@ e-crisaout.o: $(srcdir)/config/e-crisaou
 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
 
--- 2009-04-15/gas/Makefile.in	2009-04-15 08:47:20.000000000 +0200
+++ 2009-04-15/gas/Makefile.in	2009-02-05 14:42:22.000000000 +0100
@@ -2667,6 +2667,8 @@ e-crisaout.o: $(srcdir)/config/e-crisaou
 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
 
--- 2009-04-15/gas/config/tc-i386-intel.c	1970-01-01 01:00:00.000000000 +0100
+++ 2009-04-15/gas/config/tc-i386-intel.c	2009-04-16 09:46:32.000000000 +0200
@@ -0,0 +1,845 @@
+/* tc-i386.c -- Assemble Intel syntax code for ix86/x86-64
+   Copyright 2008
+   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;
+}
--- 2009-04-15/gas/config/tc-i386.c	2009-04-15 08:47:23.000000000 +0200
+++ 2009-04-15/gas/config/tc-i386.c	2009-04-15 14:04:44.000000000 +0200
@@ -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_
 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, cha
 #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, cha
 
   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, cha
     }
 #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
     }
   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)
--- 2009-04-15/gas/config/tc-i386.h	2009-04-15 08:47:24.000000000 +0200
+++ 2009-04-15/gas/config/tc-i386.h	2008-11-12 16:08:49.000000000 +0100
@@ -157,6 +157,12 @@ extern int tc_i386_fix_adjustable (struc
 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 *
 
 #endif /* TE_PE */
 
+/* X_add_symbol:X_op_symbol (Intel mode only) */
+#define O_full_ptr O_md2
+
 #endif /* TC_I386 */
--- 2009-04-15/gas/testsuite/gas/i386/equ.d	2005-10-27 15:33:57.000000000 +0200
+++ 2009-04-15/gas/testsuite/gas/i386/equ.d	2008-08-26 16:07:28.000000000 +0200
@@ -1,6 +1,5 @@
 #objdump: -drw
 #name: i386 equates
-#stderr: equ.e
 
 .*: +file format .*
 
--- 2009-04-15/gas/testsuite/gas/i386/equ.s	2005-11-24 16:55:10.000000000 +0100
+++ 2009-04-15/gas/testsuite/gas/i386/equ.s	2008-08-26 16:08:15.000000000 +0200
@@ -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]
--- 2009-04-15/gas/testsuite/gas/i386/i386.exp	2009-02-05 08:59:53.000000000 +0100
+++ 2009-04-15/gas/testsuite/gas/i386/i386.exp	2009-04-16 09:50:24.000000000 +0200
@@ -197,6 +197,7 @@ if [expr ([istarget "i*86-*-*"] ||  [ist
 }
 
 if [expr [istarget "i*86-*-*"] || [istarget "x86_64-*-*"]] then {
+    run_dump_test "intel-expr"
     run_dump_test "string-ok"
     run_list_test "string-bad" ""
 }
--- 2009-04-15/gas/testsuite/gas/i386/intel-expr.d	1970-01-01 01:00:00.000000000 +0100
+++ 2009-04-15/gas/testsuite/gas/i386/intel-expr.d	2009-04-16 09:50:37.000000000 +0200
@@ -0,0 +1,13 @@
+#objdump: -sj .data
+#name: x86 Intel expressions
+
+.*:     file format .*
+
+Contents of section .data:
+ 0000 00000000 01000000 feffffff fcffffff  .*
+ 0010 05000000 03000000 12000000 0[17]000000  .*
+ 0020 03000000 40020000 00000000 08000000  .*
+ 0030 05000000 0f000000 ffffffff 00000000  .*
+ 0040 ffffffff 00000000 ffffffff 00000000  .*
+ 0050 01020406 080a1010 20cccccc cccccccc  .*
+ 0060 02ff05ff 04ff06ff 08ff06ff cccccccc  .*
--- 2009-04-15/gas/testsuite/gas/i386/intel-expr.s	1970-01-01 01:00:00.000000000 +0100
+++ 2009-04-15/gas/testsuite/gas/i386/intel-expr.s	2008-11-13 10:54:52.000000000 +0100
@@ -0,0 +1,40 @@
+	.intel_syntax
+	.data
+
+	.long	0
+	.long	+ 1
+	.long	- 2
+	.long	not 3
+	.long	4 + 1
+	.long	5 - 2
+	.long	6 * 3
+	.long	7 / 4
+	.long	8 mod 5
+	.long	9 shl 6
+	.long	10 shr 7
+	.long	11 and 8
+	.long	12 xor 9
+	.long	13 or 10
+	.long	14 eq 14
+	.long	15 ne 15
+	.long	16 le 16
+	.long	17 lt 17
+	.long	18 ge 18
+	.long	19 gt 19
+
+	.p2align 4, 0xcc
+
+	.byte	byte, word, dword, fword, qword, tbyte, oword, xmmword, ymmword
+
+	.p2align 4, 0xcc
+
+	.code16
+	.word	near, far
+
+	.code32
+	.word	near, far
+
+	.code64
+	.word	near, far
+
+	.p2align 4, 0xcc
--- 2009-04-15/gas/testsuite/gas/i386/intel.e	2008-08-28 17:58:02.000000000 +0200
+++ 2009-04-15/gas/testsuite/gas/i386/intel.e	2008-11-13 11:17:13.000000000 +0100
@@ -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,st\(3\)'
--- 2009-04-15/gas/testsuite/gas/i386/intel.s	2009-02-05 08:59:53.000000000 +0100
+++ 2009-04-15/gas/testsuite/gas/i386/intel.s	2008-11-12 16:08:49.000000000 +0100
@@ -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
--- 2009-04-15/gas/testsuite/gas/i386/intel16.d	2007-05-02 11:04:08.000000000 +0200
+++ 2009-04-15/gas/testsuite/gas/i386/intel16.d	2008-08-26 10:01:18.000000000 +0200
@@ -1,6 +1,5 @@
 #objdump: -dw -mi8086
 #name: i386 intel16
-#stderr: intel16.e
 
 .*: +file format .*
 
--- 2009-04-15/gas/testsuite/gas/i386/intel16.s	2005-03-11 17:09:30.000000000 +0100
+++ 2009-04-15/gas/testsuite/gas/i386/intel16.s	2008-08-26 10:01:54.000000000 +0200
@@ -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]
--- 2009-04-15/gas/testsuite/gas/i386/intelbad.l	2008-02-13 13:21:45.000000000 +0100
+++ 2009-04-15/gas/testsuite/gas/i386/intelbad.l	2008-11-13 10:46:14.000000000 +0100
@@ -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: .*
--- 2009-04-15/gas/testsuite/gas/i386/intelbad.s	2008-02-13 13:16:43.000000000 +0100
+++ 2009-04-15/gas/testsuite/gas/i386/intelbad.s	2008-08-28 09:52:06.000000000 +0200
@@ -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]
--- 2009-04-15/gas/testsuite/gas/i386/intelok.d	2008-02-13 13:16:43.000000000 +0100
+++ 2009-04-15/gas/testsuite/gas/i386/intelok.d	2008-11-12 16:44:47.000000000 +0100
@@ -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
--- 2009-04-15/gas/testsuite/gas/i386/intelok.s	2008-02-13 14:41:30.000000000 +0100
+++ 2009-04-15/gas/testsuite/gas/i386/intelok.s	2008-11-12 16:40:04.000000000 +0100
@@ -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
 
--- 2009-04-15/gas/testsuite/gas/i386/x86_64.d	2008-02-11 08:33:05.000000000 +0100
+++ 2009-04-15/gas/testsuite/gas/i386/x86_64.d	2008-11-12 16:49:38.000000000 +0100
@@ -1,7 +1,6 @@
 #as: -J
 #objdump: -dw
 #name: x86_64
-#stderr: x86_64.e
 .*: +file format .*
 
 Disassembly of section .text:
--- 2009-04-15/gas/testsuite/gas/i386/x86_64.s	2008-02-13 14:02:34.000000000 +0100
+++ 2009-04-15/gas/testsuite/gas/i386/x86_64.s	2008-11-12 16:08:49.000000000 +0100
@@ -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



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]