2008-01-09 H.J. Lu <hongjiu.lu@intel.com>
[platform/upstream/binutils.git] / gas / config / tc-i386.c
index 85ca2bb..7ac2442 100644 (file)
@@ -1,6 +1,6 @@
 /* tc-i386.c -- Assemble code for the Intel 80386
    Copyright 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
    Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
@@ -66,7 +66,7 @@ static void pe_directive_secrel (int);
 #endif
 static void signed_cons (int);
 static char *output_invalid (int c);
-static int i386_operand (char *);
+static int i386_att_operand (char *);
 static int i386_intel_operand (char *, int);
 static const reg_entry *parse_register (char *, char **);
 static char *parse_insn (char *, char *);
@@ -294,7 +294,7 @@ static int old_gcc = OLDGCC_COMPAT;
 /* 1 if register prefix % not required.  */
 static int allow_naked_reg = 0;
 
-/* 1 if fake index register, eiz/riz, is allowed .  */
+/* 1 if pseudo index register, eiz/riz, is allowed .  */
 static int allow_index_reg = 0;
 
 /* Register prefix used for error message.  */
@@ -318,9 +318,6 @@ static const char *cpu_sub_arch_name = NULL;
 /* CPU feature flags.  */
 static i386_cpu_flags cpu_arch_flags = CPU_UNKNOWN_FLAGS;
 
-/* Bitwise NOT of cpu_arch_flags.  */
-static i386_cpu_flags cpu_arch_flags_not;
-
 /* If we have selected a cpu we are generating instructions for.  */
 static int cpu_arch_tune_set = 0;
 
@@ -967,29 +964,6 @@ cpu_flags_check_cpu64 (i386_cpu_flags f)
 }
 
 static INLINE i386_cpu_flags
-cpu_flags_not (i386_cpu_flags x)
-{
-  switch (ARRAY_SIZE (x.array))
-    {
-    case 3:
-      x.array [2] = ~x.array [2];
-    case 2:
-      x.array [1] = ~x.array [1];
-    case 1:
-      x.array [0] = ~x.array [0];
-      break;
-    default:
-      abort ();
-    }
-
-#ifdef CpuUnused
-  x.bitfield.unused = 0;
-#endif
-
-  return x;
-}
-
-static INLINE i386_cpu_flags
 cpu_flags_and (i386_cpu_flags x, i386_cpu_flags y)
 {
   switch (ARRAY_SIZE (x.array))
@@ -1025,19 +999,29 @@ cpu_flags_or (i386_cpu_flags x, i386_cpu_flags y)
   return x;
 }
 
+/* Return 3 if there is a perfect match, 2 if compatible with 64bit,
+   1 if compatible with arch, 0 if there is no match.  */
+
 static int
 cpu_flags_match (i386_cpu_flags x)
 {
-  i386_cpu_flags not = cpu_arch_flags_not;
-
-  not.bitfield.cpu64 = 1;
-  not.bitfield.cpuno64 = 1;
+  int overlap = cpu_flags_check_cpu64 (x) ? 2 : 0;
 
   x.bitfield.cpu64 = 0;
   x.bitfield.cpuno64 = 0;
 
-  not = cpu_flags_and (x, not);
-  return UINTS_ALL_ZERO (not);
+  if (UINTS_ALL_ZERO (x))
+    overlap |= 1;
+  else
+    {
+      i386_cpu_flags cpu = cpu_arch_flags;
+
+      cpu.bitfield.cpu64 = 0;
+      cpu.bitfield.cpuno64 = 0;
+      cpu = cpu_flags_and (x, cpu);
+      overlap |= UINTS_ALL_ZERO (cpu) ? 0 : 1;
+    }
+  return overlap;
 }
 
 static INLINE i386_operand_type
@@ -1445,15 +1429,11 @@ set_code_flag (int value)
     {
       cpu_arch_flags.bitfield.cpu64 = 1;
       cpu_arch_flags.bitfield.cpuno64 = 0;
-      cpu_arch_flags_not.bitfield.cpu64 = 0;
-      cpu_arch_flags_not.bitfield.cpuno64 = 1;
     }
   else
     {
       cpu_arch_flags.bitfield.cpu64 = 0;
       cpu_arch_flags.bitfield.cpuno64 = 1;
-      cpu_arch_flags_not.bitfield.cpu64 = 1;
-      cpu_arch_flags_not.bitfield.cpuno64 = 0;
     }
   if (value == CODE_64BIT && !cpu_arch_flags.bitfield.cpulm )
     {
@@ -1474,8 +1454,6 @@ set_16bit_gcc_code_flag (int new_code_flag)
     abort ();
   cpu_arch_flags.bitfield.cpu64 = 0;
   cpu_arch_flags.bitfield.cpuno64 = 1;
-  cpu_arch_flags_not.bitfield.cpu64 = 1;
-  cpu_arch_flags_not.bitfield.cpuno64 = 0;
   stackop_size = LONG_MNEM_SUFFIX;
 }
 
@@ -1517,37 +1495,7 @@ set_intel_syntax (int syntax_flag)
 static void
 set_intel_mnemonic (int mnemonic_flag)
 {
-  /* Find out if register prefixing is specified.  */
-  int ask_naked_reg = 0;
-
-  SKIP_WHITESPACE ();
-  if (!is_end_of_line[(unsigned char) *input_line_pointer])
-    {
-      char *string = input_line_pointer;
-      int e = get_symbol_end ();
-
-      if (strcmp (string, "prefix") == 0)
-       ask_naked_reg = 1;
-      else if (strcmp (string, "noprefix") == 0)
-       ask_naked_reg = -1;
-      else
-       as_bad (_("bad argument to syntax directive."));
-      *input_line_pointer = e;
-    }
-  demand_empty_rest_of_line ();
-
-  /* intel_mnemonic implies intel_syntax.  */
-  intel_mnemonic = intel_syntax = mnemonic_flag;
-
-  if (ask_naked_reg == 0)
-    allow_naked_reg = (intel_mnemonic
-                      && (bfd_get_symbol_leading_char (stdoutput) != '\0'));
-  else
-    allow_naked_reg = (ask_naked_reg < 0);
-
-  identifier_chars['%'] = intel_mnemonic && allow_naked_reg ? '%' : 0;
-  identifier_chars['$'] = intel_mnemonic ? '$' : 0;
-  register_prefix = allow_naked_reg ? "" : "%";
+  intel_mnemonic = mnemonic_flag;
 }
 
 static void
@@ -1587,7 +1535,6 @@ set_cpu_arch (int dummy ATTRIBUTE_UNUSED)
                      cpu_arch_flags.bitfield.cpu64 = 0;
                      cpu_arch_flags.bitfield.cpuno64 = 1;
                    }
-                 cpu_arch_flags_not = cpu_flags_not (cpu_arch_flags);
                  cpu_arch_isa = cpu_arch[i].type;
                  cpu_arch_isa_flags = cpu_arch[i].flags;
                  if (!cpu_arch_tune_set)
@@ -1604,7 +1551,6 @@ set_cpu_arch (int dummy ATTRIBUTE_UNUSED)
                {
                  cpu_sub_arch_name = cpu_arch[i].name;
                  cpu_arch_flags = flags;
-                 cpu_arch_flags_not = cpu_flags_not (cpu_arch_flags);
                }
              *input_line_pointer = e;
              demand_empty_rest_of_line ();
@@ -1655,8 +1601,6 @@ md_begin ()
 {
   const char *hash_err;
 
-  cpu_arch_flags_not = cpu_flags_not (cpu_arch_flags);
-
   /* Initialize op_hash hash table.  */
   op_hash = hash_new ();
 
@@ -2231,11 +2175,6 @@ md_assemble (line)
 
   if (intel_syntax)
     {
-      /* Undo SYSV386_COMPAT brokenness when in Intel mode.  See i386.h  */
-      if (SYSV386_COMPAT
-         && (i.tm.base_opcode & 0xfffffde0) == 0xdce0)
-       i.tm.base_opcode ^= Opcode_FloatR;
-
       /* Zap movzx and movsx suffix.  The suffix may have been set from
         "word ptr" or "byte ptr" on the source operand, but we'll use
         the suffix later to choose the destination register.  */
@@ -2582,11 +2521,11 @@ parse_insn (char *line, char *mnemonic)
   supported = 0;
   for (t = current_templates->start; t < current_templates->end; ++t)
     {
-      if (cpu_flags_match (t->cpu_flags))
-       supported |= 1;
-      if (cpu_flags_check_cpu64 (t->cpu_flags))
-       supported |= 2;
+      supported |= cpu_flags_match (t->cpu_flags);
+      if (supported == 3)
+       goto skip;
     }
+
   if (!(supported & 2))
     {
       as_bad (flag_code == CODE_64BIT
@@ -2597,12 +2536,14 @@ parse_insn (char *line, char *mnemonic)
     }
   if (!(supported & 1))
     {
-      as_warn (_("`%s' is not supported on `%s%s'"),
-              current_templates->start->name,
-              cpu_arch_name,
-              cpu_sub_arch_name ? cpu_sub_arch_name : "");
+      as_bad (_("`%s' is not supported on `%s%s'"),
+             current_templates->start->name, cpu_arch_name,
+             cpu_sub_arch_name ? cpu_sub_arch_name : "");
+      return NULL;
     }
-  else if (!cpu_arch_flags.bitfield.cpui386
+
+skip:
+  if (!cpu_arch_flags.bitfield.cpui386
           && (flag_code != CODE_16BIT))
     {
       as_warn (_("use .code16 to ensure correct addressing mode"));
@@ -2715,7 +2656,7 @@ parse_operands (char *l, const char *mnemonic)
              i386_intel_operand (token_start,
                                  intel_float_operand (mnemonic));
          else
-           operand_ok = i386_operand (token_start);
+           operand_ok = i386_att_operand (token_start);
 
          RESTORE_END_STRING (l);
          if (!operand_ok)
@@ -3025,7 +2966,8 @@ match_template (void)
   i386_operand_type operand_types [MAX_OPERANDS];
   int addr_prefix_disp;
   unsigned int j;
-  i386_cpu_flags overlap;
+  unsigned int found_cpu_match;
+  unsigned int check_register;
 
 #if MAX_OPERANDS != 4
 # error "MAX_OPERANDS must be 4."
@@ -3047,6 +2989,8 @@ match_template (void)
     suffix_check.no_qsuf = 1;
   else if (i.suffix == LONG_DOUBLE_MNEM_SUFFIX)
     suffix_check.no_ldsuf = 1;
+  else if (i.suffix == XMMWORD_MNEM_SUFFIX)
+    suffix_check.xmmword = 1;
 
   for (t = current_templates->start; t < current_templates->end; t++)
     {
@@ -3056,15 +3000,16 @@ match_template (void)
       if (i.operands != t->operands)
        continue;
 
-      /* Check AT&T mnemonic and old gcc support. */
-      if (t->opcode_modifier.attmnemonic
-         && (intel_mnemonic
-             || (!old_gcc
-                 && t->opcode_modifier.oldgcc)))
+      /* Check old gcc support. */
+      if (!old_gcc && t->opcode_modifier.oldgcc)
        continue;
 
-      /* Check Intel mnemonic. */
-      if (!intel_mnemonic && t->opcode_modifier.intelmnemonic)
+      /* Check AT&T mnemonic.   */
+      if (intel_mnemonic && t->opcode_modifier.attmnemonic)
+       continue;
+
+      /* Check Intel syntax.   */
+      if (intel_syntax && t->opcode_modifier.attsyntax)
        continue;
 
       /* Check the suffix, except for some instructions in intel mode.  */
@@ -3077,6 +3022,18 @@ match_template (void)
              || (t->opcode_modifier.no_ldsuf && suffix_check.no_ldsuf)))
        continue;
 
+      /* Check the memory size in Intel mode when it is provided if
+        needed.  */
+      if (intel_syntax
+         && i.suffix
+         && t->opcode_modifier.checksize
+         && (!t->opcode_modifier.byte || !suffix_check.no_bsuf)
+         && (!t->opcode_modifier.word || !suffix_check.no_wsuf)
+         && (!t->opcode_modifier.dword || !suffix_check.no_lsuf)
+         && (!t->opcode_modifier.qword || !suffix_check.no_qsuf)
+         && (!t->opcode_modifier.xmmword || !suffix_check.xmmword))
+       continue;
+
       for (j = 0; j < MAX_OPERANDS; j++)
        operand_types [j] = t->operand_types [j];
 
@@ -3098,10 +3055,10 @@ match_template (void)
       /* Do not verify operands when there are none.  */
       else 
        {
-         overlap = cpu_flags_and (t->cpu_flags, cpu_arch_flags_not);
+         found_cpu_match = cpu_flags_match (t->cpu_flags) == 3;
          if (!t->operands)
            {
-             if (!UINTS_ALL_ZERO (overlap))
+             if (!found_cpu_match)
                continue;
              /* We've found a match; break out of loop.  */
              break;
@@ -3154,6 +3111,9 @@ match_template (void)
            }
          }
 
+      /* We check register size only if size of operands can be
+        encoded the canonical way.  */
+      check_register = t->opcode_modifier.w;
       overlap0 = operand_type_and (i.types[0], operand_types[0]);
       switch (t->operands)
        {
@@ -3176,19 +3136,8 @@ match_template (void)
          overlap1 = operand_type_and (i.types[1], operand_types[1]);
          if (!operand_type_match (overlap0, i.types[0])
              || !operand_type_match (overlap1, i.types[1])
-             /* monitor in SSE3 is a very special case.  The first
-                register and the second register may have different
-                sizes.  The same applies to crc32 in SSE4.2.  It is
-                also true for invlpga, vmload, vmrun and vmsave in
-                SVME.  */
-             || !((t->base_opcode == 0x0f01
-                   && (t->extension_opcode == 0xc8
-                       || t->extension_opcode == 0xd8
-                       || t->extension_opcode == 0xda
-                       || t->extension_opcode == 0xdb
-                       || t->extension_opcode == 0xdf))
-                  || t->base_opcode == 0xf20f38f1
-                  || operand_type_register_match (overlap0, i.types[0],
+             || (check_register
+                 && !operand_type_register_match (overlap0, i.types[0],
                                                   operand_types[0],
                                                   overlap1, i.types[1],
                                                   operand_types[1])))
@@ -3202,10 +3151,13 @@ match_template (void)
              overlap1 = operand_type_and (i.types[1], operand_types[0]);
              if (!operand_type_match (overlap0, i.types[0])
                  || !operand_type_match (overlap1, i.types[1])
-                 || !operand_type_register_match (overlap0, i.types[0],
-                                                  operand_types[1],
-                                                  overlap1, i.types[1],
-                                                  operand_types[0]))
+                 || (check_register
+                     && !operand_type_register_match (overlap0,
+                                                      i.types[0],
+                                                      operand_types[1],
+                                                      overlap1,
+                                                      i.types[1],
+                                                      operand_types[0])))
                {
                  /* Does not match either direction.  */
                  continue;
@@ -3239,12 +3191,13 @@ match_template (void)
                {
                case 4:
                  if (!operand_type_match (overlap3, i.types[3])
-                     || !operand_type_register_match (overlap2,
-                                                      i.types[2],
-                                                      operand_types[2],
-                                                      overlap3,
-                                                      i.types[3],
-                                                      operand_types[3]))
+                     || (check_register
+                         && !operand_type_register_match (overlap2,
+                                                          i.types[2],
+                                                          operand_types[2],
+                                                          overlap3,
+                                                          i.types[3],
+                                                          operand_types[3])))
                    continue;
                case 3:
                  /* Here we make use of the fact that there are no
@@ -3252,12 +3205,13 @@ match_template (void)
                     operand instructions only need to be checked for
                     register consistency between operands 2 and 3.  */
                  if (!operand_type_match (overlap2, i.types[2])
-                     || !operand_type_register_match (overlap1,
-                                                      i.types[1],
-                                                      operand_types[1],
-                                                      overlap2,
-                                                      i.types[2],
-                                                      operand_types[2]))
+                     || (check_register
+                         && !operand_type_register_match (overlap1,
+                                                          i.types[1],
+                                                          operand_types[1],
+                                                          overlap2,
+                                                          i.types[2],
+                                                          operand_types[2])))
                    continue;
                  break;
                }
@@ -3265,7 +3219,7 @@ match_template (void)
          /* Found either forward/reverse 2, 3 or 4 operand match here:
             slip through to break.  */
        }
-      if (!UINTS_ALL_ZERO (overlap))
+      if (!found_cpu_match)
        {
          found_reverse_match = 0;
          continue;
@@ -3453,6 +3407,11 @@ process_suffix (void)
          if (!check_word_reg ())
            return 0;
        }
+      else if (i.suffix == XMMWORD_MNEM_SUFFIX)
+       {
+         /* Skip if the instruction has x suffix.  match_template
+            should check if it is a valid suffix.  */
+       }
       else if (intel_syntax && i.tm.opcode_modifier.ignoresize)
        /* Do nothing if the instruction is going to ignore the prefix.  */
        ;
@@ -3513,7 +3472,7 @@ process_suffix (void)
            suffixes |= 1 << 1;
          if (!i.tm.opcode_modifier.no_lsuf)
            suffixes |= 1 << 2;
-         if (!i.tm.opcode_modifier.no_lsuf)
+         if (!i.tm.opcode_modifier.no_ldsuf)
            suffixes |= 1 << 3;
          if (!i.tm.opcode_modifier.no_ssuf)
            suffixes |= 1 << 4;
@@ -3535,7 +3494,9 @@ process_suffix (void)
   /* Change the opcode based on the operand size given by i.suffix;
      We don't need to change things for byte insns.  */
 
-  if (i.suffix && i.suffix != BYTE_MNEM_SUFFIX)
+  if (i.suffix
+      && i.suffix != BYTE_MNEM_SUFFIX
+      && i.suffix != XMMWORD_MNEM_SUFFIX)
     {
       /* It's not a byte, select word/dword operation.  */
       if (i.tm.opcode_modifier.w)
@@ -3927,8 +3888,8 @@ finalize_imm (void)
 static void
 process_drex (void)
 {
-  i.drex.modrm_reg = None;
-  i.drex.modrm_regmem = None;
+  i.drex.modrm_reg = 0;
+  i.drex.modrm_regmem = 0;
 
   /* SSE5 4 operand instructions must have the destination the same as 
      one of the inputs.  Figure out the destination register and cache
@@ -6091,7 +6052,7 @@ i386_index_check (const char *operand_string)
    on error.  */
 
 static int
-i386_operand (char *operand_string)
+i386_att_operand (char *operand_string)
 {
   const reg_entry *r;
   char *end_op;
@@ -7136,7 +7097,6 @@ md_parse_option (int c, char *arg)
 
     case OPTION_MOLD_GCC:
       old_gcc = 1;
-      intel_mnemonic = 0;
       break;
 
     default:
@@ -7177,7 +7137,16 @@ md_show_usage (stream)
   -march=CPU/-mtune=CPU   generate code/optimize for CPU, where CPU is one of:\n\
                            i386, i486, pentium, pentiumpro, pentium4, nocona,\n\
                            core, core2, k6, athlon, k8, generic32, generic64\n"));
-
+  fprintf (stream, _("\
+  -mmnemonic=[att|intel]  use AT&T/Intel mnemonic\n"));
+  fprintf (stream, _("\
+  -msyntax=[att|intel]    use AT&T/Intel syntax\n"));
+  fprintf (stream, _("\
+  -mindex-reg             support pseudo index registers\n"));
+  fprintf (stream, _("\
+  -mnaked-reg             don't require `%%' prefix for registers\n"));
+  fprintf (stream, _("\
+  -mold-gcc               support old (<= 2.8.1) versions of gcc\n"));
 }
 
 #if ((defined (OBJ_MAYBE_COFF) && defined (OBJ_MAYBE_AOUT)) \
@@ -8157,8 +8126,7 @@ intel_e09 (void)
 
          else if (prev_token.code == T_XMMWORD)
            {
-             /* XXX ignored for now, but accepted since gcc uses it */
-             suffix = 0;
+             suffix = XMMWORD_MNEM_SUFFIX;
            }
 
          else