* config/tc-i386.c (i386_intel_operand): Always call i386_index_check
[deliverable/binutils-gdb.git] / gas / config / tc-i386.c
index 8bc88f77ef40da8b6486a3c55ca74994c559989b..9f511ab42dc738aa1ef746a8b1cb632090631138 100644 (file)
@@ -1,6 +1,6 @@
 /* i386.c -- Assemble code for the Intel 80386
    Copyright 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002
+   2000, 2001, 2002, 2003
    Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
@@ -30,6 +30,7 @@
 #include "safe-ctype.h"
 #include "subsegs.h"
 #include "dwarf2dbg.h"
+#include "dw2gencfi.h"
 #include "opcode/i386.h"
 
 #ifndef REGISTER_WARNINGS
@@ -207,7 +208,7 @@ const char comment_chars[] = "#/";
    #NO_APP at the beginning of its output.
    Also note that comments started like this one will always work if
    '/' isn't otherwise defined.  */
-const char line_comment_chars[] = "";
+const char line_comment_chars[] = "#";
 
 #else
 /* Putting '/' here makes it impossible to use the divide operator.
@@ -215,7 +216,7 @@ const char line_comment_chars[] = "";
 const char comment_chars[] = "#";
 #define PREFIX_SEPARATOR '/'
 
-const char line_comment_chars[] = "/";
+const char line_comment_chars[] = "/#";
 #endif
 
 const char line_separator_chars[] = ";";
@@ -302,6 +303,9 @@ static int allow_naked_reg = 0;
    frame as in 32 bit mode.  */
 static char stackop_size = '\0';
 
+/* Non-zero to optimize code alignment.  */
+int optimize_align_code = 1;
+
 /* Non-zero to quieten some warnings.  */
 static int quiet_warnings = 0;
 
@@ -318,6 +322,12 @@ static unsigned int no_cond_jump_promotion = 0;
 /* Pre-defined "_GLOBAL_OFFSET_TABLE_".  */
 symbolS *GOT_symbol;
 
+/* The dwarf2 return column, adjusted for 32 or 64 bit.  */
+unsigned int x86_dwarf2_return_column;
+
+/* The dwarf2 data alignment, adjusted for 32 or 64 bit.  */
+int x86_cie_data_alignment;
+
 /* Interface to relax_segment.
    There are 3 major relax states for 386 jump insns because the
    different types of jumps add different sizes to frags when we're
@@ -986,6 +996,17 @@ md_begin ()
       record_alignment (bss_section, 2);
     }
 #endif
+
+  if (flag_code == CODE_64BIT)
+    {
+      x86_dwarf2_return_column = 16;
+      x86_cie_data_alignment = -8;
+    }
+  else
+    {
+      x86_dwarf2_return_column = 8;
+      x86_cie_data_alignment = -4;
+    }
 }
 
 void
@@ -1235,6 +1256,11 @@ tc_i386_fix_adjustable (fixP)
       || fixP->fx_r_type == BFD_RELOC_X86_64_PLT32
       || fixP->fx_r_type == BFD_RELOC_X86_64_GOT32
       || fixP->fx_r_type == BFD_RELOC_X86_64_GOTPCREL
+      || fixP->fx_r_type == BFD_RELOC_X86_64_TLSGD
+      || fixP->fx_r_type == BFD_RELOC_X86_64_TLSLD
+      || fixP->fx_r_type == BFD_RELOC_X86_64_DTPOFF32
+      || fixP->fx_r_type == BFD_RELOC_X86_64_GOTTPOFF
+      || fixP->fx_r_type == BFD_RELOC_X86_64_TPOFF32
       || fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
       || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
     return 0;
@@ -1263,6 +1289,11 @@ tc_i386_fix_adjustable (fixP)
 #define BFD_RELOC_X86_64_PLT32         0
 #define BFD_RELOC_X86_64_GOT32         0
 #define BFD_RELOC_X86_64_GOTPCREL      0
+#define BFD_RELOC_X86_64_TLSGD         0
+#define BFD_RELOC_X86_64_TLSLD         0
+#define BFD_RELOC_X86_64_DTPOFF32      0
+#define BFD_RELOC_X86_64_GOTTPOFF      0
+#define BFD_RELOC_X86_64_TPOFF32       0
 #endif
 
 static int intel_float_operand PARAMS ((const char *mnemonic));
@@ -1382,13 +1413,28 @@ md_assemble (line)
 
   if (i.tm.opcode_modifier & ImmExt)
     {
+      expressionS *exp;
+
+      if ((i.tm.cpu_flags & CpuPNI) && i.operands > 0)
+       {
+         /* These Intel Precott New 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' as operand %d in '%s'."),
+                       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.  */
 
-      expressionS *exp;
-
       assert (i.imm_operands == 0 && i.operands <= 2 && 2 < MAX_OPERANDS);
 
       exp = &im_expressions[i.imm_operands++];
@@ -2604,9 +2650,8 @@ process_operands ()
   else if (i.tm.opcode_modifier & Modrm)
     {
       /* The opcode is completed (modulo i.tm.extension_opcode which
-        must be put into the modrm byte).
-        Now, we make the modrm & index base bytes based on all the
-        info we've collected.  */
+        must be put into the modrm byte).  Now, we make the modrm and
+        index base bytes based on all the info we've collected.  */
 
       default_seg = build_modrm_byte ();
     }
@@ -2633,12 +2678,14 @@ process_operands ()
       default_seg = &ds;
     }
 
-  /* If a segment was explicitly specified,
-     and the specified segment is not the default,
-     use an opcode prefix to select it.
-     If we never figured out what the default segment is,
-     then default_seg will be zero at this point,
-     and the specified segment prefix will always be used.  */
+  if (i.tm.base_opcode == 0x8d /* lea */ && i.seg[0] && !quiet_warnings)
+    as_warn (_("segment override on `lea' is ineffectual"));
+
+  /* If a segment was explicitly specified, and the specified segment
+     is not the default, use an opcode prefix to select it.  If we
+     never figured out what the default segment is, then default_seg
+     will be zero at this point, and the specified segment prefix will
+     always be used.  */
   if ((i.seg[0]) && (i.seg[0] != default_seg))
     {
       if (!add_prefix (i.seg[0]->seg_prefix))
@@ -2989,6 +3036,7 @@ output_jump ()
 {
   char *p;
   int size;
+  fixS *fixP;
 
   if (i.tm.opcode_modifier & JumpByte)
     {
@@ -3039,8 +3087,14 @@ output_jump ()
   p = frag_more (1 + size);
   *p++ = i.tm.base_opcode;
 
-  fix_new_exp (frag_now, p - frag_now->fr_literal, size,
-              i.op[0].disps, 1, reloc (size, 1, 1, i.reloc[0]));
+  fixP = fix_new_exp (frag_now, p - frag_now->fr_literal, size,
+                     i.op[0].disps, 1, reloc (size, 1, 1, i.reloc[0]));
+
+  /* All jumps handled here are signed, but don't use a signed limit
+     check for 32 and 16 bit jumps as we want to allow wrap around at
+     4G and 64k respectively.  */
+  if (size == 1)
+    fixP->fx_signed = 1;
 }
 
 static void
@@ -3483,12 +3537,13 @@ lex_got (reloc, adjust)
     { "PLT",      { BFD_RELOC_386_PLT32,      0, BFD_RELOC_X86_64_PLT32    } },
     { "GOTOFF",   { BFD_RELOC_386_GOTOFF,     0, 0                         } },
     { "GOTPCREL", { 0,                        0, BFD_RELOC_X86_64_GOTPCREL } },
-    { "TLSGD",    { BFD_RELOC_386_TLS_GD,     0, 0                         } },
+    { "TLSGD",    { BFD_RELOC_386_TLS_GD,     0, BFD_RELOC_X86_64_TLSGD    } },
     { "TLSLDM",   { BFD_RELOC_386_TLS_LDM,    0, 0                         } },
-    { "GOTTPOFF", { BFD_RELOC_386_TLS_IE_32,  0, 0                         } },
-    { "TPOFF",    { BFD_RELOC_386_TLS_LE_32,  0, 0                         } },
+    { "TLSLD",    { 0,                        0, BFD_RELOC_X86_64_TLSLD    } },
+    { "GOTTPOFF", { BFD_RELOC_386_TLS_IE_32,  0, BFD_RELOC_X86_64_GOTTPOFF } },
+    { "TPOFF",    { BFD_RELOC_386_TLS_LE_32,  0, BFD_RELOC_X86_64_TPOFF32  } },
     { "NTPOFF",   { BFD_RELOC_386_TLS_LE,     0, 0                         } },
-    { "DTPOFF",   { BFD_RELOC_386_TLS_LDO_32, 0, 0                         } },
+    { "DTPOFF",   { BFD_RELOC_386_TLS_LDO_32, 0, BFD_RELOC_X86_64_DTPOFF32 } },
     { "GOTNTPOFF",{ BFD_RELOC_386_TLS_GOTIE,  0, 0                         } },
     { "INDNTPOFF",{ BFD_RELOC_386_TLS_IE,     0, 0                         } },
     { "GOT",      { BFD_RELOC_386_GOT32,      0, BFD_RELOC_X86_64_GOT32    } }
@@ -4382,11 +4437,14 @@ md_estimate_size_before_relax (fragP, segment)
        case COND_JUMP:
          if (no_cond_jump_promotion && fragP->fr_var == NO_RELOC)
            {
+             fixS *fixP;
+
              fragP->fr_fix += 1;
-             fix_new (fragP, old_fr_fix, 1,
-                      fragP->fr_symbol,
-                      fragP->fr_offset, 1,
-                      BFD_RELOC_8_PCREL);
+             fixP = fix_new (fragP, old_fr_fix, 1,
+                             fragP->fr_symbol,
+                             fragP->fr_offset, 1,
+                             BFD_RELOC_8_PCREL);
+             fixP->fx_signed = 1;
              break;
            }
 
@@ -4620,19 +4678,16 @@ md_apply_fix3 (fixP, valP, seg)
 #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
       if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
        {
-         segT fseg = S_GET_SEGMENT (fixP->fx_addsy);
+         segT sym_seg = S_GET_SEGMENT (fixP->fx_addsy);
 
-         if ((fseg == seg
+         if ((sym_seg == seg
               || (symbol_section_p (fixP->fx_addsy)
-                  && fseg != absolute_section))
-             && !S_IS_EXTERNAL (fixP->fx_addsy)
-             && !S_IS_WEAK (fixP->fx_addsy)
-             && S_IS_DEFINED (fixP->fx_addsy)
-             && !S_IS_COMMON (fixP->fx_addsy))
+                  && sym_seg != absolute_section))
+             && !generic_force_reloc (fixP))
            {
              /* Yes, we add the values in twice.  This is because
-                bfd_perform_relocation subtracts them out again.  I think
-                bfd_perform_relocation is broken, but I don't dare change
+                bfd_install_relocation subtracts them out again.  I think
+                bfd_install_relocation is broken, but I don't dare change
                 it.  FIXME.  */
              value += fixP->fx_where + fixP->fx_frag->fr_address;
            }
@@ -4660,12 +4715,25 @@ md_apply_fix3 (fixP, valP, seg)
        value = -4;
        break;
 
-      case BFD_RELOC_386_GOT32:
       case BFD_RELOC_386_TLS_GD:
       case BFD_RELOC_386_TLS_LDM:
       case BFD_RELOC_386_TLS_IE_32:
       case BFD_RELOC_386_TLS_IE:
       case BFD_RELOC_386_TLS_GOTIE:
+      case BFD_RELOC_X86_64_TLSGD:
+      case BFD_RELOC_X86_64_TLSLD:
+      case BFD_RELOC_X86_64_GOTTPOFF:
+       value = 0; /* Fully resolved at runtime.  No addend.  */
+       /* Fallthrough */
+      case BFD_RELOC_386_TLS_LE:
+      case BFD_RELOC_386_TLS_LDO_32:
+      case BFD_RELOC_386_TLS_LE_32:
+      case BFD_RELOC_X86_64_DTPOFF32:
+      case BFD_RELOC_X86_64_TPOFF32:
+       S_SET_THREAD_LOCAL (fixP->fx_addsy);
+       break;
+
+      case BFD_RELOC_386_GOT32:
       case BFD_RELOC_X86_64_GOT32:
        value = 0; /* Fully resolved at runtime.  No addend.  */
        break;
@@ -4839,9 +4907,9 @@ parse_register (reg_string, end_op)
 }
 \f
 #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
-const char *md_shortopts = "kVQ:sq";
+const char *md_shortopts = "kVQ:sqn";
 #else
-const char *md_shortopts = "q";
+const char *md_shortopts = "qn";
 #endif
 
 struct option md_longopts[] = {
@@ -4862,6 +4930,10 @@ md_parse_option (c, arg)
 {
   switch (c)
     {
+    case 'n':
+      optimize_align_code = 0;
+      break;
+
     case 'q':
       quiet_warnings = 1;
       break;
@@ -4923,10 +4995,12 @@ md_show_usage (stream)
   -Q                      ignored\n\
   -V                      print assembler version number\n\
   -k                      ignored\n\
+  -n                      Do not optimize code alignment\n\
   -q                      quieten some warnings\n\
   -s                      ignored\n"));
 #else
   fprintf (stream, _("\
+  -n                      Do not optimize code alignment\n\
   -q                      quieten some warnings\n"));
 #endif
 }
@@ -5114,17 +5188,6 @@ i386_validate_fix (fixp)
     }
 }
 
-boolean
-i386_force_relocation (fixp)
-     fixS *fixp;
-{
-  if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
-      || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
-    return 1;
-
-  return S_FORCE_RELOC (fixp->fx_addsy);
-}
-
 arelent *
 tc_gen_reloc (section, fixp)
      asection *section ATTRIBUTE_UNUSED;
@@ -5151,6 +5214,11 @@ tc_gen_reloc (section, fixp)
     case BFD_RELOC_386_TLS_LE_32:
     case BFD_RELOC_386_TLS_LE:
     case BFD_RELOC_X86_64_32S:
+    case BFD_RELOC_X86_64_TLSGD:
+    case BFD_RELOC_X86_64_TLSLD:
+    case BFD_RELOC_X86_64_DTPOFF32:
+    case BFD_RELOC_X86_64_GOTTPOFF:
+    case BFD_RELOC_X86_64_TPOFF32:
     case BFD_RELOC_RVA:
     case BFD_RELOC_VTABLE_ENTRY:
     case BFD_RELOC_VTABLE_INHERIT:
@@ -5228,6 +5296,9 @@ tc_gen_reloc (section, fixp)
          case BFD_RELOC_X86_64_PLT32:
          case BFD_RELOC_X86_64_GOT32:
          case BFD_RELOC_X86_64_GOTPCREL:
+         case BFD_RELOC_X86_64_TLSGD:
+         case BFD_RELOC_X86_64_TLSLD:
+         case BFD_RELOC_X86_64_GOTTPOFF:
            rel->addend = fixp->fx_offset - fixp->fx_size;
            break;
          default:
@@ -5550,8 +5621,9 @@ i386_intel_operand (operand_string, got_a_float)
 
              /* Add the displacement expression.  */
              if (*s != '\0')
-               ret = i386_displacement (s, s + strlen (s))
-                     && i386_index_check (s);
+               ret = i386_displacement (s, s + strlen (s));
+             if (ret)
+               ret = i386_index_check (operand_string);
            }
        }
 
@@ -6270,3 +6342,55 @@ intel_putback_token ()
   prev_token.reg = NULL;
   prev_token.str = NULL;
 }
+
+int
+tc_x86_regname_to_dw2regnum (const char *regname)
+{
+  unsigned int regnum;
+  unsigned int regnames_count;
+  char *regnames_32[] =
+    {
+      "eax", "ecx", "edx", "ebx",
+      "esp", "ebp", "esi", "edi",
+      "eip"
+    };
+  char *regnames_64[] =
+    {
+      "rax", "rbx", "rcx", "rdx",
+      "rdi", "rsi", "rbp", "rsp",
+      "r8", "r9", "r10", "r11",
+      "r12", "r13", "r14", "r15",
+      "rip"
+    };
+  char **regnames;
+
+  if (flag_code == CODE_64BIT)
+    {
+      regnames = regnames_64;
+      regnames_count = ARRAY_SIZE (regnames_64);
+    }
+  else
+    {
+      regnames = regnames_32;
+      regnames_count = ARRAY_SIZE (regnames_32);
+    }
+
+  for (regnum = 0; regnum < regnames_count; regnum++)
+    if (strcmp (regname, regnames[regnum]) == 0)
+      return regnum;
+
+  return -1;
+}
+
+void
+tc_x86_frame_initial_instructions (void)
+{
+  static unsigned int sp_regno;
+
+  if (!sp_regno)
+    sp_regno = tc_x86_regname_to_dw2regnum (flag_code == CODE_64BIT
+                                           ? "rsp" : "esp");
+
+  cfi_add_CFA_def_cfa (sp_regno, -x86_cie_data_alignment);
+  cfi_add_CFA_offset (x86_dwarf2_return_column, x86_cie_data_alignment);
+}
This page took 0.027933 seconds and 4 git commands to generate.