gas/
[platform/upstream/binutils.git] / gas / config / tc-i386.c
index ecf48bd..80a1ac8 100644 (file)
@@ -413,6 +413,9 @@ static int intel_mnemonic = !SYSV386_COMPAT;
 /* 1 if support old (<= 2.8.1) versions of gcc.  */
 static int old_gcc = OLDGCC_COMPAT;
 
+/* 1 if pseudo registers are permitted.  */
+static int allow_pseudo_reg = 0;
+
 /* 1 if register prefix % not required.  */
 static int allow_naked_reg = 0;
 
@@ -623,6 +626,8 @@ static const arch_entry cpu_arch[] =
     CPU_VMX_FLAGS },
   { ".smx", PROCESSOR_UNKNOWN,
     CPU_SMX_FLAGS },
+  { ".xsave", PROCESSOR_UNKNOWN,
+    CPU_XSAVE_FLAGS },
   { ".3dnow", PROCESSOR_UNKNOWN,
     CPU_3DNOW_FLAGS },
   { ".3dnowa", PROCESSOR_UNKNOWN,
@@ -1019,34 +1024,34 @@ i386_align_code (fragS *fragP, int count)
 }
 
 static INLINE int
-uints_all_zero (const unsigned int *x, unsigned int size)
+operand_type_all_zero (const union i386_operand_type *x)
 {
-  switch (size)
+  switch (ARRAY_SIZE(x->array))
     {
     case 3:
-      if (x[2])
+      if (x->array[2])
        return 0;
     case 2:
-      if (x[1])
+      if (x->array[1])
        return 0;
     case 1:
-      return !x[0];
+      return !x->array[0];
     default:
       abort ();
     }
 }
 
 static INLINE void
-uints_set (unsigned int *x, unsigned int v, unsigned int size)
+operand_type_set (union i386_operand_type *x, unsigned int v)
 {
-  switch (size)
+  switch (ARRAY_SIZE(x->array))
     {
     case 3:
-      x[2] = v;
+      x->array[2] = v;
     case 2:
-      x[1] = v;
+      x->array[1] = v;
     case 1:
-      x[0] = v;
+      x->array[0] = v;
       break;
     default:
       abort ();
@@ -1054,33 +1059,79 @@ uints_set (unsigned int *x, unsigned int v, unsigned int size)
 }
 
 static INLINE int
-uints_equal (const unsigned int *x, const unsigned int *y,
-            unsigned int size)
+operand_type_equal (const union i386_operand_type *x,
+                   const union i386_operand_type *y)
 {
-  switch (size)
+  switch (ARRAY_SIZE(x->array))
+    {
+    case 3:
+      if (x->array[2] != y->array[2])
+       return 0;
+    case 2:
+      if (x->array[1] != y->array[1])
+       return 0;
+    case 1:
+      return x->array[0] == y->array[0];
+      break;
+    default:
+      abort ();
+    }
+}
+
+static INLINE int
+cpu_flags_all_zero (const union i386_cpu_flags *x)
+{
+  switch (ARRAY_SIZE(x->array))
     {
     case 3:
-      if (x[2] != y [2])
+      if (x->array[2])
        return 0;
     case 2:
-      if (x[1] != y [1])
+      if (x->array[1])
        return 0;
     case 1:
-      return x[0] == y [0];
+      return !x->array[0];
+    default:
+      abort ();
+    }
+}
+
+static INLINE void
+cpu_flags_set (union i386_cpu_flags *x, unsigned int v)
+{
+  switch (ARRAY_SIZE(x->array))
+    {
+    case 3:
+      x->array[2] = v;
+    case 2:
+      x->array[1] = v;
+    case 1:
+      x->array[0] = v;
       break;
     default:
       abort ();
     }
 }
 
-#define UINTS_ALL_ZERO(x) \
-  uints_all_zero ((x).array, ARRAY_SIZE ((x).array))
-#define UINTS_SET(x, v) \
-  uints_set ((x).array, v, ARRAY_SIZE ((x).array))
-#define UINTS_CLEAR(x) \
-  uints_set ((x).array, 0, ARRAY_SIZE ((x).array))
-#define UINTS_EQUAL(x, y) \
-  uints_equal ((x).array, (y).array, ARRAY_SIZE ((x).array))
+static INLINE int
+cpu_flags_equal (const union i386_cpu_flags *x,
+                const union i386_cpu_flags *y)
+{
+  switch (ARRAY_SIZE(x->array))
+    {
+    case 3:
+      if (x->array[2] != y->array[2])
+       return 0;
+    case 2:
+      if (x->array[1] != y->array[1])
+       return 0;
+    case 1:
+      return x->array[0] == y->array[0];
+      break;
+    default:
+      abort ();
+    }
+}
 
 static INLINE int
 cpu_flags_check_cpu64 (i386_cpu_flags f)
@@ -1136,7 +1187,7 @@ cpu_flags_match (i386_cpu_flags x)
   x.bitfield.cpu64 = 0;
   x.bitfield.cpuno64 = 0;
 
-  if (UINTS_ALL_ZERO (x))
+  if (cpu_flags_all_zero (&x))
     overlap |= 1;
   else
     {
@@ -1145,7 +1196,7 @@ cpu_flags_match (i386_cpu_flags x)
       cpu.bitfield.cpu64 = 0;
       cpu.bitfield.cpuno64 = 0;
       cpu = cpu_flags_and (x, cpu);
-      overlap |= UINTS_ALL_ZERO (cpu) ? 0 : 1;
+      overlap |= cpu_flags_all_zero (&cpu) ? 0 : 1;
     }
   return overlap;
 }
@@ -1207,6 +1258,8 @@ operand_type_xor (i386_operand_type x, i386_operand_type y)
 static const i386_operand_type acc32 = OPERAND_TYPE_ACC32;
 static const i386_operand_type acc64 = OPERAND_TYPE_ACC64;
 static const i386_operand_type control = OPERAND_TYPE_CONTROL;
+static const i386_operand_type inoutportreg
+  = OPERAND_TYPE_INOUTPORTREG;
 static const i386_operand_type reg16_inoutportreg
   = OPERAND_TYPE_REG16_INOUTPORTREG;
 static const i386_operand_type disp16 = OPERAND_TYPE_DISP16;
@@ -1384,7 +1437,7 @@ operand_type_match (i386_operand_type overlap,
   temp.bitfield.qword = 0;
   temp.bitfield.tbyte = 0;
   temp.bitfield.xmmword = 0;
-  if (UINTS_ALL_ZERO (temp))
+  if (operand_type_all_zero (&temp))
     return 0;
 
   return (given.bitfield.baseindex == overlap.bitfield.baseindex
@@ -1500,7 +1553,7 @@ smallest_imm_type (offsetT num)
 {
   i386_operand_type t;
  
-  UINTS_CLEAR (t);
+  operand_type_set (&t, 0);
   t.bitfield.imm64 = 1;
 
   if (cpu_arch_tune != PROCESSOR_I486 && num == 1)
@@ -1777,14 +1830,14 @@ set_cpu_arch (int dummy ATTRIBUTE_UNUSED)
 
              flags = cpu_flags_or (cpu_arch_flags,
                                    cpu_arch[i].flags);
-             if (!UINTS_EQUAL (flags, cpu_arch_flags))
+             if (!cpu_flags_equal (&flags, &cpu_arch_flags))
                {
                  if (cpu_sub_arch_name)
                    {
                      char *name = cpu_sub_arch_name;
                      cpu_sub_arch_name = concat (name,
                                                  cpu_arch[i].name,
-                                                 NULL);
+                                                 (const char *) NULL);
                      free (name);
                    }
                  else
@@ -2342,13 +2395,56 @@ intel_float_operand (const char *mnemonic)
   return 1;
 }
 
+static void
+process_immext (void)
+{
+  expressionS *exp;
+
+  if (i.tm.cpu_flags.bitfield.cpusse3 && i.operands > 0)
+    {
+      /* SSE3 Instructions have the fixed operands with an opcode
+        suffix which is coded in the same place as an 8-bit immediate
+        field would be.  Here we check those operands and remove them
+        afterwards.  */
+      unsigned int x;
+
+      for (x = 0; x < i.operands; x++)
+       if (i.op[x].regs->reg_num != x)
+         as_bad (_("can't use register '%s%s' as operand %d in '%s'."),
+                 register_prefix, i.op[x].regs->reg_name, x + 1,
+                 i.tm.name);
+
+      i.operands = 0;
+    }
+
+  /* These AMD 3DNow! and SSE2 Instructions have an opcode suffix
+     which is coded in the same place as an 8-bit immediate field
+     would be.  Here we fake an 8-bit immediate operand from the
+     opcode suffix stored in tm.extension_opcode.
+
+     SSE5 also uses this encoding, for some of its 3 argument
+     instructions.  */
+
+  assert (i.imm_operands == 0
+         && (i.operands <= 2
+             || (i.tm.cpu_flags.bitfield.cpusse5
+                 && i.operands <= 3)));
+
+  exp = &im_expressions[i.imm_operands++];
+  i.op[i.operands].imms = exp;
+  i.types[i.operands] = imm8;
+  i.operands++;
+  exp->X_op = O_constant;
+  exp->X_add_number = i.tm.extension_opcode;
+  i.tm.extension_opcode = None;
+}
+
 /* This is the guts of the machine-dependent assembler.  LINE points to a
    machine dependent instruction.  This function is supposed to emit
    the frags/bytes it assembles to.  */
 
 void
-md_assemble (line)
-     char *line;
+md_assemble (char *line)
 {
   unsigned int j;
   char mnemonic[MAX_MNEM_SIZE];
@@ -2458,48 +2554,7 @@ md_assemble (line)
       i.reg_operands--;
 
   if (i.tm.opcode_modifier.immext)
-    {
-      expressionS *exp;
-
-      if (i.tm.cpu_flags.bitfield.cpusse3 && i.operands > 0)
-       {
-         /* Streaming SIMD extensions 3 Instructions have the fixed
-            operands with an opcode suffix which is coded in the same
-            place as an 8-bit immediate field would be. Here we check
-            those operands and remove them afterwards.  */
-         unsigned int x;
-
-         for (x = 0; x < i.operands; x++)
-           if (i.op[x].regs->reg_num != x)
-             as_bad (_("can't use register '%s%s' as operand %d in '%s'."),
-                     register_prefix,
-                     i.op[x].regs->reg_name,
-                     x + 1,
-                     i.tm.name);
-         i.operands = 0;
-       }
-
-      /* These AMD 3DNow! and Intel Katmai New Instructions have an
-        opcode suffix which is coded in the same place as an 8-bit
-        immediate field would be.  Here we fake an 8-bit immediate
-        operand from the opcode suffix stored in tm.extension_opcode.
-        SSE5 also uses this encoding, for some of its 3 argument
-        instructions.  */
-
-      assert (i.imm_operands == 0
-             && (i.operands <= 2
-                 || (i.tm.cpu_flags.bitfield.cpusse5
-                     && i.operands <= 3)));
-
-      exp = &im_expressions[i.imm_operands++];
-      i.op[i.operands].imms = exp;
-      UINTS_CLEAR (i.types[i.operands]);
-      i.types[i.operands].bitfield.imm8 = 1;
-      i.operands++;
-      exp->X_op = O_constant;
-      exp->X_add_number = i.tm.extension_opcode;
-      i.tm.extension_opcode = None;
-    }
+    process_immext ();
 
   /* For insns with operands there are more diddles to do to the opcode.  */
   if (i.operands)
@@ -3080,8 +3135,8 @@ optimize_imm (void)
              i386_operand_type mask, allowed;
              const template *t;
 
-             UINTS_CLEAR (mask);
-             UINTS_CLEAR (allowed);
+             operand_type_set (&mask, 0);
+             operand_type_set (&allowed, 0);
 
              for (t = current_templates->start;
                   t < current_templates->end;
@@ -3107,7 +3162,7 @@ optimize_imm (void)
                  break;
                }
              allowed = operand_type_and (mask, allowed);
-             if (!UINTS_ALL_ZERO (allowed))
+             if (!operand_type_all_zero (&allowed))
                i.types[op] = operand_type_and (i.types[op], mask);
            }
            break;
@@ -3282,6 +3337,19 @@ match_template (void)
              || t->extension_opcode != 1 /* cmpxchg8b */))
        continue;
 
+      /* In general, don't allow 32-bit operands on pre-386.  */
+      else if (i.suffix == LONG_MNEM_SUFFIX
+              && !cpu_arch_flags.bitfield.cpui386
+              && (intel_syntax
+                  ? (!t->opcode_modifier.ignoresize
+                     && !intel_float_operand (t->name))
+                  : intel_float_operand (t->name) != 2)
+              && ((!operand_types[0].bitfield.regmmx
+                   && !operand_types[0].bitfield.regxmm)
+                  || (!operand_types[t->operands > 1].bitfield.regmmx
+                      && !!operand_types[t->operands > 1].bitfield.regxmm)))
+       continue;
+
       /* Do not verify operands when there are none.  */
       else
        {
@@ -3353,8 +3421,8 @@ match_template (void)
             zero-extend %eax to %rax.  */
          if (flag_code == CODE_64BIT
              && t->base_opcode == 0x90
-             && UINTS_EQUAL (i.types [0], acc32)
-             && UINTS_EQUAL (i.types [1], acc32))
+             && operand_type_equal (&i.types [0], &acc32)
+             && operand_type_equal (&i.types [1], &acc32))
            continue;
        case 3:
        case 4:
@@ -3773,8 +3841,8 @@ process_suffix (void)
          if (! (i.operands == 2
                 && i.tm.base_opcode == 0x90
                 && i.tm.extension_opcode == None
-                && UINTS_EQUAL (i.types [0], acc64)
-                && UINTS_EQUAL (i.types [1], acc64))
+                && operand_type_equal (&i.types [0], &acc64)
+                && operand_type_equal (&i.types [1], &acc64))
              && ! (i.operands == 1
                    && i.tm.base_opcode == 0xfc7
                    && i.tm.extension_opcode == 1
@@ -4040,18 +4108,18 @@ update_imm (unsigned int j)
        || overlap.bitfield.imm32
        || overlap.bitfield.imm32s
        || overlap.bitfield.imm64)
-      && !UINTS_EQUAL (overlap, imm8)
-      && !UINTS_EQUAL (overlap, imm8s)
-      && !UINTS_EQUAL (overlap, imm16)
-      && !UINTS_EQUAL (overlap, imm32)
-      && !UINTS_EQUAL (overlap, imm32s)
-      && !UINTS_EQUAL (overlap, imm64))
+      && !operand_type_equal (&overlap, &imm8)
+      && !operand_type_equal (&overlap, &imm8s)
+      && !operand_type_equal (&overlap, &imm16)
+      && !operand_type_equal (&overlap, &imm32)
+      && !operand_type_equal (&overlap, &imm32s)
+      && !operand_type_equal (&overlap, &imm64))
     {
       if (i.suffix)
        {
          i386_operand_type temp;
 
-         UINTS_CLEAR (temp);
+         operand_type_set (&temp, 0);
          if (i.suffix == BYTE_MNEM_SUFFIX) 
            {
              temp.bitfield.imm8 = overlap.bitfield.imm8;
@@ -4068,22 +4136,21 @@ update_imm (unsigned int j)
            temp.bitfield.imm32 = overlap.bitfield.imm32;
          overlap = temp;
        }
-      else if (UINTS_EQUAL (overlap, imm16_32_32s)
-              || UINTS_EQUAL (overlap, imm16_32)
-              || UINTS_EQUAL (overlap, imm16_32s))
+      else if (operand_type_equal (&overlap, &imm16_32_32s)
+              || operand_type_equal (&overlap, &imm16_32)
+              || operand_type_equal (&overlap, &imm16_32s))
        {
-         UINTS_CLEAR (overlap);
          if ((flag_code == CODE_16BIT) ^ (i.prefix[DATA_PREFIX] != 0))
-           overlap.bitfield.imm16 = 1;
+           overlap = imm16;
          else
-           overlap.bitfield.imm32s = 1;
+           overlap = imm32s;
        }
-      if (!UINTS_EQUAL (overlap, imm8)
-         && !UINTS_EQUAL (overlap, imm8s)
-         && !UINTS_EQUAL (overlap, imm16)
-         && !UINTS_EQUAL (overlap, imm32)
-         && !UINTS_EQUAL (overlap, imm32s)
-         && !UINTS_EQUAL (overlap, imm64))
+      if (!operand_type_equal (&overlap, &imm8)
+         && !operand_type_equal (&overlap, &imm8s)
+         && !operand_type_equal (&overlap, &imm16)
+         && !operand_type_equal (&overlap, &imm32)
+         && !operand_type_equal (&overlap, &imm32s)
+         && !operand_type_equal (&overlap, &imm64))
        {
          as_bad (_("no instruction mnemonic suffix given; "
                    "can't determine immediate size"));
@@ -4135,8 +4202,8 @@ process_drex (void)
          && i.op[0].regs->reg_flags == i.op[3].regs->reg_flags)
        {
          /* Clear the arguments that are stored in drex.  */
-         UINTS_CLEAR (i.types[0]); 
-         UINTS_CLEAR (i.types[3]);
+         operand_type_set (&i.types[0], 0); 
+         operand_type_set (&i.types[3], 0);
          i.reg_operands -= 2;
 
          /* There are two different ways to encode a 4 operand 
@@ -4163,8 +4230,8 @@ process_drex (void)
               && i.op[0].regs->reg_flags == i.op[3].regs->reg_flags)
        {
          /* clear the arguments that are stored in drex */
-         UINTS_CLEAR (i.types[0]);
-         UINTS_CLEAR (i.types[3]);
+         operand_type_set (&i.types[0], 0); 
+         operand_type_set (&i.types[3], 0);
          i.reg_operands -= 2;
 
          /* Specify the modrm encoding for memory addressing.  Include 
@@ -4186,8 +4253,8 @@ process_drex (void)
               && i.op[0].regs->reg_flags == i.op[3].regs->reg_flags)
        {
          /* Clear the arguments that are stored in drex.  */
-         UINTS_CLEAR (i.types[0]);
-         UINTS_CLEAR (i.types[3]);
+         operand_type_set (&i.types[0], 0); 
+         operand_type_set (&i.types[3], 0);
          i.reg_operands -= 2;
 
          /* Specify the modrm encoding for memory addressing.  Include
@@ -4209,8 +4276,8 @@ process_drex (void)
               && i.op[2].regs->reg_flags == i.op[3].regs->reg_flags)
        {
          /* clear the arguments that are stored in drex */
-         UINTS_CLEAR (i.types[2]);
-         UINTS_CLEAR (i.types[3]);
+         operand_type_set (&i.types[2], 0); 
+         operand_type_set (&i.types[3], 0);
          i.reg_operands -= 2;
 
          /* There are two different ways to encode a 4 operand 
@@ -4239,8 +4306,8 @@ process_drex (void)
               && i.op[2].regs->reg_flags == i.op[3].regs->reg_flags)
        {
          /* Clear the arguments that are stored in drex.  */
-         UINTS_CLEAR (i.types[2]);
-         UINTS_CLEAR (i.types[3]);
+         operand_type_set (&i.types[2], 0); 
+         operand_type_set (&i.types[3], 0);
          i.reg_operands -= 2;
 
          /* Specify the modrm encoding and remember the register 
@@ -4261,8 +4328,8 @@ process_drex (void)
               && i.op[2].regs->reg_flags == i.op[3].regs->reg_flags)
        {
          /* clear the arguments that are stored in drex */
-         UINTS_CLEAR (i.types[2]);
-         UINTS_CLEAR (i.types[3]);
+         operand_type_set (&i.types[2], 0); 
+         operand_type_set (&i.types[3], 0);
          i.reg_operands -= 2;
 
          /* Specify the modrm encoding and remember the register 
@@ -4296,8 +4363,8 @@ process_drex (void)
          && i.op[0].regs->reg_flags == i.op[3].regs->reg_flags)
        {
          /* clear the arguments that are stored in drex */
-         UINTS_CLEAR (i.types[0]);
-         UINTS_CLEAR (i.types[3]);
+         operand_type_set (&i.types[0], 0); 
+         operand_type_set (&i.types[3], 0);
          i.reg_operands -= 2;
 
          /* Specify the modrm encoding and remember the register 
@@ -4329,7 +4396,7 @@ process_drex (void)
          && i.types[2].bitfield.regxmm != 0)
        {
          /* Clear the arguments that are stored in drex.  */
-         UINTS_CLEAR (i.types[2]);
+         operand_type_set (&i.types[2], 0);
          i.reg_operands--;
 
          /* Specify the modrm encoding and remember the register 
@@ -4347,7 +4414,7 @@ process_drex (void)
               && i.types[2].bitfield.regxmm != 0)
        {
          /* Clear the arguments that are stored in drex.  */
-         UINTS_CLEAR (i.types[2]);
+         operand_type_set (&i.types[2], 0);
          i.reg_operands--;
 
          /* Specify the modrm encoding and remember the register 
@@ -4366,7 +4433,7 @@ process_drex (void)
               && i.types[2].bitfield.regxmm != 0)
        {
          /* Clear the arguments that are stored in drex.  */
-         UINTS_CLEAR (i.types[2]);
+         operand_type_set (&i.types[2], 0);
          i.reg_operands--;
 
          /* Specify the modrm encoding and remember the register 
@@ -4396,7 +4463,7 @@ process_drex (void)
          && i.types[3].bitfield.regxmm != 0)
        {
          /* clear the arguments that are stored in drex */
-         UINTS_CLEAR (i.types[3]);
+         operand_type_set (&i.types[3], 0);
          i.reg_operands--;
 
          /* Specify the modrm encoding and remember the register 
@@ -4418,7 +4485,7 @@ process_drex (void)
               && operand_type_check (i.types[3], imm) != 0)
        {
          /* clear the arguments that are stored in drex */
-         UINTS_CLEAR (i.types[2]);
+         operand_type_set (&i.types[2], 0);
          i.reg_operands--;
 
          /* Specify the modrm encoding and remember the register 
@@ -4459,7 +4526,8 @@ process_operands (void)
       unsigned int j;
 
       /* The first operand is implicit and must be xmm0.  */
-      assert (i.reg_operands && UINTS_EQUAL (i.types[0], regxmm));
+      assert (i.reg_operands
+             && operand_type_equal (&i.types[0], &regxmm));
       if (i.op[0].regs->reg_num != 0)
        {
          if (intel_syntax)
@@ -4826,7 +4894,7 @@ build_modrm_byte (void)
                  && operand_type_check (i.types[op], disp))
                {
                  i386_operand_type temp;
-                 UINTS_CLEAR (temp);
+                 operand_type_set (&temp, 0);
                  temp.bitfield.disp8 = i.types[op].bitfield.disp8;
                  i.types[op] = temp;
                  if (i.prefix[ADDR_PREFIX] == 0)
@@ -5838,7 +5906,7 @@ i386_immediate (char *imm_start)
   expressionS *exp;
   i386_operand_type types;
 
-  UINTS_SET (types, ~0);
+  operand_type_set (&types, ~0);
 
   if (i.imm_operands == MAX_IMMEDIATE_OPERANDS)
     {
@@ -5990,7 +6058,7 @@ i386_displacement (char *disp_start, char *disp_end)
       return 0;
     }
 
-  UINTS_CLEAR (bigdisp);
+  operand_type_set (&bigdisp, 0);
   if ((i.types[this_operand].bitfield.jumpabsolute)
       || (!current_templates->start->opcode_modifier.jump
          && !current_templates->start->opcode_modifier.jumpdword))
@@ -6171,7 +6239,7 @@ i386_displacement (char *disp_start, char *disp_end)
   bigdisp.bitfield.disp32 = 0;
   bigdisp.bitfield.disp32s = 0;
   bigdisp.bitfield.disp64 = 0;
-  if (UINTS_ALL_ZERO (bigdisp))
+  if (operand_type_all_zero (&bigdisp))
     i.types[this_operand] = operand_type_and (i.types[this_operand],
                                              types);
 
@@ -6544,14 +6612,14 @@ i386_att_operand (char *operand_string)
 
       /* Special case for (%dx) while doing input/output op.  */
       if (i.base_reg
-         && UINTS_EQUAL (i.base_reg->reg_type, reg16_inoutportreg)
+         && operand_type_equal (&i.base_reg->reg_type,
+                                &reg16_inoutportreg)
          && i.index_reg == 0
          && i.log2_scale_factor == 0
          && i.seg[i.mem_operands] == 0
          && !operand_type_check (i.types[this_operand], disp))
        {
-         UINTS_CLEAR (i.types[this_operand]);
-         i.types[this_operand].bitfield.inoutportreg = 1;
+         i.types[this_operand] = inoutportreg;
          return 1;
        }
 
@@ -7053,20 +7121,41 @@ parse_real_register (char *reg_string, char **end_op)
        }
     }
 
+  if (r == NULL || allow_pseudo_reg)
+    return r;
+
+  if (operand_type_all_zero (&r->reg_type))
+    return (const reg_entry *) NULL;
+
+  if ((r->reg_type.bitfield.reg32
+       || r->reg_type.bitfield.sreg3
+       || r->reg_type.bitfield.control
+       || r->reg_type.bitfield.debug
+       || r->reg_type.bitfield.test)
+      && !cpu_arch_flags.bitfield.cpui386)
+    return (const reg_entry *) NULL;
+
+  if (r->reg_type.bitfield.regmmx && !cpu_arch_flags.bitfield.cpummx)
+    return (const reg_entry *) NULL;
+
+  if (r->reg_type.bitfield.regxmm && !cpu_arch_flags.bitfield.cpusse)
+    return (const reg_entry *) NULL;
+
   /* Don't allow fake index register unless allow_index_reg isn't 0. */
-  if (r != NULL
-      && !allow_index_reg
+  if (!allow_index_reg
       && (r->reg_num == RegEiz || r->reg_num == RegRiz))
     return (const reg_entry *) NULL;
 
-  if (r != NULL
-      && ((r->reg_flags & (RegRex64 | RegRex))
-         || r->reg_type.bitfield.reg64)
+  if (((r->reg_flags & (RegRex64 | RegRex))
+       || r->reg_type.bitfield.reg64)
       && (!cpu_arch_flags.bitfield.cpulm
-         || !UINTS_EQUAL (r->reg_type, control))
+         || !operand_type_equal (&r->reg_type, &control))
       && flag_code != CODE_64BIT)
     return (const reg_entry *) NULL;
 
+  if (r->reg_type.bitfield.sreg3 && r->reg_num == RegFlat && !intel_syntax)
+    return (const reg_entry *) NULL;
+
   return r;
 }
 
@@ -7292,14 +7381,14 @@ md_parse_option (int c, char *arg)
                  i386_cpu_flags flags;
                  flags = cpu_flags_or (cpu_arch_flags,
                                        cpu_arch[i].flags);
-                 if (!UINTS_EQUAL (flags, cpu_arch_flags))
+                 if (!cpu_flags_equal (&flags, &cpu_arch_flags))
                    {
                      if (cpu_sub_arch_name)
                        {
                          char *name = cpu_sub_arch_name;
                          cpu_sub_arch_name = concat (name,
                                                      cpu_arch[i].name,
-                                                     NULL);
+                                                     (const char *) NULL);
                          free (name);
                        }
                      else
@@ -7408,8 +7497,8 @@ md_show_usage (stream)
                            generic32, generic64\n\
                           EXTENSION is combination of:\n\
                            mmx, sse, sse2, sse3, ssse3, sse4.1, sse4.2, sse4,\n\
-                           vmx, smx, 3dnow, 3dnowa, sse4a, sse5, svme, abm,\n\
-                           padlock\n"));
+                           vmx, smx, xsave, 3dnow, 3dnowa, sse4a, sse5, svme,\n\
+                          abm, padlock\n"));
   fprintf (stream, _("\
   -mtune=CPU              optimize for CPU, CPU is one of:\n\
                            i8086, i186, i286, i386, i486, pentium, pentiumpro,\n\
@@ -7439,7 +7528,7 @@ i386_target_format (void)
   if (!strcmp (default_arch, "x86_64"))
     {
       set_code_flag (CODE_64BIT);
-      if (UINTS_ALL_ZERO (cpu_arch_isa_flags))
+      if (cpu_flags_all_zero (&cpu_arch_isa_flags))
        {
          cpu_arch_isa_flags.bitfield.cpui186 = 1;
          cpu_arch_isa_flags.bitfield.cpui286 = 1;
@@ -7452,7 +7541,7 @@ i386_target_format (void)
          cpu_arch_isa_flags.bitfield.cpusse = 1;
          cpu_arch_isa_flags.bitfield.cpusse2 = 1;
        }
-      if (UINTS_ALL_ZERO (cpu_arch_tune_flags))
+      if (cpu_flags_all_zero (&cpu_arch_tune_flags))
        {
          cpu_arch_tune_flags.bitfield.cpui186 = 1;
          cpu_arch_tune_flags.bitfield.cpui286 = 1;
@@ -7469,13 +7558,13 @@ i386_target_format (void)
   else if (!strcmp (default_arch, "i386"))
     {
       set_code_flag (CODE_32BIT);
-      if (UINTS_ALL_ZERO (cpu_arch_isa_flags))
+      if (cpu_flags_all_zero (&cpu_arch_isa_flags))
        {
          cpu_arch_isa_flags.bitfield.cpui186 = 1;
          cpu_arch_isa_flags.bitfield.cpui286 = 1;
          cpu_arch_isa_flags.bitfield.cpui386 = 1;
        }
-      if (UINTS_ALL_ZERO (cpu_arch_tune_flags))
+      if (cpu_flags_all_zero (&cpu_arch_tune_flags))
        {
          cpu_arch_tune_flags.bitfield.cpui186 = 1;
          cpu_arch_tune_flags.bitfield.cpui286 = 1;
@@ -8124,7 +8213,15 @@ i386_intel_operand (char *operand_string, int got_a_float)
       /* Constant and OFFSET expressions are handled by i386_immediate.  */
       else if ((intel_parser.op_modifier & (1 << T_OFFSET))
               || intel_parser.reg == NULL)
-       ret = i386_immediate (intel_parser.disp);
+       {
+         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 (intel_parser.next_operand && this_operand >= MAX_OPERANDS - 1)
        ret = 0;
@@ -8348,9 +8445,10 @@ intel_e09 (void)
 
          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)
+             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;
@@ -8361,9 +8459,10 @@ intel_e09 (void)
 
          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)
+             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
@@ -8395,10 +8494,11 @@ intel_e09 (void)
 
          else if (prev_token.code == T_QWORD)
            {
-             if (intel_parser.got_a_float == 1)        /* "f..." */
+             if (current_templates->start->base_opcode == 0x62 /* bound */
+                 || intel_parser.got_a_float == 1)     /* "f..." */
                suffix = LONG_MNEM_SUFFIX;
              else
-                 suffix = QWORD_MNEM_SUFFIX;
+               suffix = QWORD_MNEM_SUFFIX;
              i.types[this_operand].bitfield.qword = 1;
            }
 
@@ -8655,6 +8755,8 @@ intel_e11 (void)
                        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
@@ -8685,6 +8787,12 @@ intel_e11 (void)
              }
          }
 
+       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 == '*')
          {
@@ -9076,16 +9184,6 @@ intel_get_token (void)
                strcat (new_token.str, " FLAT:");
            }
 
-         /* ??? This is not mentioned in the MASM grammar.  */
-         else if (strcasecmp (new_token.str, "FLAT") == 0)
-           {
-             new_token.code = T_OFFSET;
-             if (*q == ':')
-               strcat (new_token.str, ":");
-             else
-               as_bad (_("`:' expected"));
-           }
-
          else
            new_token.code = T_ID;
        }
@@ -9132,79 +9230,54 @@ intel_putback_token (void)
   prev_token.str = NULL;
 }
 
-int
-tc_x86_regname_to_dw2regnum (char *regname)
-{
-  unsigned int regnum;
-  unsigned int regnames_count;
-  static const char *const regnames_32[] =
-    {
-      "eax", "ecx", "edx", "ebx",
-      "esp", "ebp", "esi", "edi",
-      "eip", "eflags", NULL,
-      "st0", "st1", "st2", "st3",
-      "st4", "st5", "st6", "st7",
-      NULL, NULL,
-      "xmm0", "xmm1", "xmm2", "xmm3",
-      "xmm4", "xmm5", "xmm6", "xmm7",
-      "mm0", "mm1", "mm2", "mm3",
-      "mm4", "mm5", "mm6", "mm7",
-      "fcw", "fsw", "mxcsr",
-      "es", "cs", "ss", "ds", "fs", "gs", NULL, NULL,
-      "tr", "ldtr"
-    };
-  static const char *const regnames_64[] =
-    {
-      "rax", "rdx", "rcx", "rbx",
-      "rsi", "rdi", "rbp", "rsp",
-      "r8",  "r9",  "r10", "r11",
-      "r12", "r13", "r14", "r15",
-      "rip",
-      "xmm0",  "xmm1",  "xmm2",  "xmm3",
-      "xmm4",  "xmm5",  "xmm6",  "xmm7",
-      "xmm8",  "xmm9",  "xmm10", "xmm11",
-      "xmm12", "xmm13", "xmm14", "xmm15",
-      "st0", "st1", "st2", "st3",
-      "st4", "st5", "st6", "st7",
-      "mm0", "mm1", "mm2", "mm3",
-      "mm4", "mm5", "mm6", "mm7",
-      "rflags",
-      "es", "cs", "ss", "ds", "fs", "gs", NULL, NULL,
-      "fs.base", "gs.base", NULL, NULL,
-      "tr", "ldtr",
-      "mxcsr", "fcw", "fsw"
-    };
-  const char *const *regnames;
+void
+tc_x86_parse_to_dw2regnum (expressionS *exp)
+{
+  int saved_naked_reg;
+  char saved_register_dot;
 
-  if (flag_code == CODE_64BIT)
-    {
-      regnames = regnames_64;
-      regnames_count = ARRAY_SIZE (regnames_64);
-    }
-  else
+  saved_naked_reg = allow_naked_reg;
+  allow_naked_reg = 1;
+  saved_register_dot = register_chars['.'];
+  register_chars['.'] = '.';
+  allow_pseudo_reg = 1;
+  expression_and_evaluate (exp);
+  allow_pseudo_reg = 0;
+  register_chars['.'] = saved_register_dot;
+  allow_naked_reg = saved_naked_reg;
+
+  if (exp->X_op == O_register && exp->X_add_number >= 0)
     {
-      regnames = regnames_32;
-      regnames_count = ARRAY_SIZE (regnames_32);
+      if ((addressT) exp->X_add_number < i386_regtab_size)
+       {
+         exp->X_op = O_constant;
+         exp->X_add_number = i386_regtab[exp->X_add_number]
+                             .dw2_regnum[flag_code >> 1];
+       }
+      else
+       exp->X_op = O_illegal;
     }
-
-  for (regnum = 0; regnum < regnames_count; regnum++)
-    if (regnames[regnum] != NULL
-       && strcmp (regname, regnames[regnum]) == 0)
-      return regnum;
-
-  return -1;
 }
 
 void
 tc_x86_frame_initial_instructions (void)
 {
-  static unsigned int sp_regno;
+  static unsigned int sp_regno[2];
 
-  if (!sp_regno)
-    sp_regno = tc_x86_regname_to_dw2regnum (flag_code == CODE_64BIT
-                                           ? "rsp" : "esp");
+  if (!sp_regno[flag_code >> 1])
+    {
+      char *saved_input = input_line_pointer;
+      char sp[][4] = {"esp", "rsp"};
+      expressionS exp;
+
+      input_line_pointer = sp[flag_code >> 1];
+      tc_x86_parse_to_dw2regnum (&exp);
+      assert (exp.X_op == O_constant);
+      sp_regno[flag_code >> 1] = exp.X_add_number;
+      input_line_pointer = saved_input;
+    }
 
-  cfi_add_CFA_def_cfa (sp_regno, -x86_cie_data_alignment);
+  cfi_add_CFA_def_cfa (sp_regno[flag_code >> 1], -x86_cie_data_alignment);
   cfi_add_CFA_offset (x86_dwarf2_return_column, x86_cie_data_alignment);
 }