* config/tc-s390.c (s390_elf_cons): Correct fixups for PLT
[deliverable/binutils-gdb.git] / gas / config / tc-i386.c
index 843db1fdb5f2c738574f2a703d7570d31acb3bdd..275b3e6c439d6ccef86aa3f5ccc2157d2cc16d6f 100644 (file)
@@ -157,7 +157,7 @@ const char extra_symbol_chars[] = "*%-(";
 
 /* This array holds the chars that always start a comment.  If the
    pre-processor is disabled, these aren't very useful.  */
-#if defined (TE_I386AIX) || ((defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) && ! defined (TE_LINUX) && !defined(TE_FreeBSD))
+#if defined (TE_I386AIX) || ((defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) && ! defined (TE_LINUX) && !defined(TE_FreeBSD) && !defined(TE_NetBSD))
 /* Putting '/' here makes it impossible to use the divide operator.
    However, we need it for compatibility with SVR4 systems.  */
 const char comment_chars[] = "#/";
@@ -175,7 +175,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.  */
-#if defined (TE_I386AIX) || ((defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) && ! defined (TE_LINUX) && !defined(TE_FreeBSD))
+#if defined (TE_I386AIX) || ((defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) && ! defined (TE_LINUX) && !defined(TE_FreeBSD) && !defined(TE_NetBSD))
 const char line_comment_chars[] = "";
 #else
 const char line_comment_chars[] = "/";
@@ -284,9 +284,9 @@ static unsigned int no_cond_jump_promotion = 0;
    figuring out what sort of jump to choose to reach a given label.  */
 
 /* Types.  */
-#define UNCOND_JUMP 1
-#define COND_JUMP 2
-#define COND_JUMP86 3
+#define UNCOND_JUMP 0
+#define COND_JUMP 1
+#define COND_JUMP86 2
 
 /* Sizes.  */
 #define CODE16 1
@@ -323,42 +323,38 @@ const relax_typeS md_relax_table[] =
   /* The fields are:
      1) most positive reach of this state,
      2) most negative reach of this state,
-     3) how many bytes this mode will add to the size of the current frag
+     3) how many bytes this mode will have in the variable part of the frag
      4) which index into the table to try if we can't fit into this one.  */
-  {1, 1, 0, 0},
-  {1, 1, 0, 0},
-  {1, 1, 0, 0},
-  {1, 1, 0, 0},
 
   /* UNCOND_JUMP states.  */
-  {127 + 1, -128 + 1, 0, ENCODE_RELAX_STATE (UNCOND_JUMP, BIG)},
-  {127 + 1, -128 + 1, 0, ENCODE_RELAX_STATE (UNCOND_JUMP, BIG16)},
-  /* dword jmp adds 3 bytes to frag:
-     0 extra opcode bytes, 3 extra displacement bytes.  */
-  {0, 0, 3, 0},
-  /* word jmp adds 1 byte to frag:
-     0 extra opcode bytes, 1 extra displacement byte.  */
-  {0, 0, 1, 0},
-
-  /* COND_JUMP states.  */
-  {127 + 1, -128 + 1, 0, ENCODE_RELAX_STATE (COND_JUMP, BIG)},
-  {127 + 1, -128 + 1, 0, ENCODE_RELAX_STATE (COND_JUMP, BIG16)},
-  /* dword conditionals adds 4 bytes to frag:
-     1 extra opcode byte, 3 extra displacement bytes.  */
+  {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (UNCOND_JUMP, BIG)},
+  {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (UNCOND_JUMP, BIG16)},
+  /* dword jmp adds 4 bytes to frag:
+     0 extra opcode bytes, 4 displacement bytes.  */
   {0, 0, 4, 0},
-  /* word conditionals add 2 bytes to frag:
-     1 extra opcode byte, 1 extra displacement byte.  */
+  /* word jmp adds 2 byte2 to frag:
+     0 extra opcode bytes, 2 displacement bytes.  */
   {0, 0, 2, 0},
 
-  /* COND_JUMP86 states.  */
-  {127 + 1, -128 + 1, 0, ENCODE_RELAX_STATE (COND_JUMP86, BIG)},
-  {127 + 1, -128 + 1, 0, ENCODE_RELAX_STATE (COND_JUMP86, BIG16)},
-  /* dword conditionals adds 4 bytes to frag:
-     1 extra opcode byte, 3 extra displacement bytes.  */
-  {0, 0, 4, 0},
+  /* COND_JUMP states.  */
+  {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (COND_JUMP, BIG)},
+  {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (COND_JUMP, BIG16)},
+  /* dword conditionals adds 5 bytes to frag:
+     1 extra opcode byte, 4 displacement bytes.  */
+  {0, 0, 5, 0},
   /* word conditionals add 3 bytes to frag:
-     1 extra opcode byte, 2 extra displacement bytes.  */
-  {0, 0, 3, 0}
+     1 extra opcode byte, 2 displacement bytes.  */
+  {0, 0, 3, 0},
+
+  /* COND_JUMP86 states.  */
+  {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (COND_JUMP86, BIG)},
+  {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (COND_JUMP86, BIG16)},
+  /* dword conditionals adds 5 bytes to frag:
+     1 extra opcode byte, 4 displacement bytes.  */
+  {0, 0, 5, 0},
+  /* word conditionals add 4 bytes to frag:
+     1 displacement byte and a 3 byte long branch insn.  */
+  {0, 0, 4, 0}
 };
 
 static const arch_entry cpu_arch[] = {
@@ -1235,10 +1231,6 @@ md_assemble (line)
   /* Points to template once we've found it.  */
   const template *t;
 
-  /* Count the size of the instruction generated.  Does not include
-     variable part of jump insns before relax.  */
-  int insn_size = 0;
-
   int j;
 
   char mnemonic[MAX_MNEM_SIZE];
@@ -1277,7 +1269,8 @@ md_assemble (line)
          }
        if (!is_space_char (*l)
            && *l != END_OF_INSN
-           && *l != PREFIX_SEPARATOR)
+           && *l != PREFIX_SEPARATOR
+           && *l != ',')
          {
            as_bad (_("invalid character %s in mnemonic"),
                    output_invalid (*l));
@@ -1368,6 +1361,38 @@ md_assemble (line)
          }
       }
 
+    if (current_templates->start->opcode_modifier & (Jump | JumpByte))
+      {
+       /* Check for a branch hint.  We allow ",pt" and ",pn" for
+          predict taken and predict not taken respectively.
+          I'm not sure that branch hints actually do anything on loop
+          and jcxz insns (JumpByte) for current Pentium4 chips.  They
+          may work in the future and it doesn't hurt to accept them
+          now.  */
+       if (l[0] == ',' && l[1] == 'p')
+         {
+           if (l[2] == 't')
+             {
+               if (! add_prefix (DS_PREFIX_OPCODE))
+                 return;
+               l += 3;
+             }
+           else if (l[2] == 'n')
+             {
+               if (! add_prefix (CS_PREFIX_OPCODE))
+                 return;
+               l += 3;
+             }
+         }
+      }
+    /* Any other comma loses.  */
+    if (*l == ',')
+      {
+       as_bad (_("invalid character %s in mnemonic"),
+               output_invalid (*l));
+       return;
+      }
+
     /* Check if instruction is supported on specified architecture.  */
     if (cpu_arch_flags != 0)
       {
@@ -2706,6 +2731,11 @@ md_assemble (line)
   {
     register char *p;
 
+    /* Tie dwarf2 debug info to the address at the start of the insn.
+       We can't do this after the insn has been output as the current
+       frag may have been closed off.  eg. by frag_var.  */
+    dwarf2_emit_insn (0);
+
     /* Output jumps.  */
     if (i.tm.opcode_modifier & Jump)
       {
@@ -2723,6 +2753,13 @@ md_assemble (line)
            i.prefixes -= 1;
            code16 ^= CODE16;
          }
+       /* Pentium4 branch hints.  */
+       if (i.prefix[SEG_PREFIX] == CS_PREFIX_OPCODE /* not taken */
+           || i.prefix[SEG_PREFIX] == DS_PREFIX_OPCODE /* taken */)
+         {
+           prefix++;
+           i.prefixes--;
+         }
        if (i.prefix[REX_PREFIX])
          {
            prefix++;
@@ -2738,11 +2775,13 @@ md_assemble (line)
           bytes for the opcode and room for the prefix and largest
           displacement.  */
        frag_grow (prefix + 2 + 4);
-       insn_size += prefix + 1;
        /* Prefix and 1 opcode byte go in fr_fix.  */
        p = frag_more (prefix + 1);
        if (i.prefix[DATA_PREFIX])
          *p++ = DATA_PREFIX_OPCODE;
+       if (i.prefix[SEG_PREFIX] == CS_PREFIX_OPCODE
+           || i.prefix[SEG_PREFIX] == DS_PREFIX_OPCODE)
+         *p++ = i.prefix[SEG_PREFIX];
        if (i.prefix[REX_PREFIX])
          *p++ = i.prefix[REX_PREFIX];
        *p = i.tm.base_opcode;
@@ -2770,10 +2809,16 @@ md_assemble (line)
            size = 1;
            if (i.prefix[ADDR_PREFIX])
              {
-               insn_size += 1;
                FRAG_APPEND_1_CHAR (ADDR_PREFIX_OPCODE);
                i.prefixes -= 1;
              }
+           /* Pentium4 branch hints.  */
+           if (i.prefix[SEG_PREFIX] == CS_PREFIX_OPCODE /* not taken */
+               || i.prefix[SEG_PREFIX] == DS_PREFIX_OPCODE /* taken */)
+             {
+               FRAG_APPEND_1_CHAR (i.prefix[SEG_PREFIX]);
+               i.prefixes--;
+             }
          }
        else
          {
@@ -2785,7 +2830,6 @@ md_assemble (line)
 
            if (i.prefix[DATA_PREFIX])
              {
-               insn_size += 1;
                FRAG_APPEND_1_CHAR (DATA_PREFIX_OPCODE);
                i.prefixes -= 1;
                code16 ^= CODE16;
@@ -2799,26 +2843,14 @@ md_assemble (line)
        if (i.prefix[REX_PREFIX])
          {
            FRAG_APPEND_1_CHAR (i.prefix[REX_PREFIX]);
-           insn_size++;
            i.prefixes -= 1;
          }
 
        if (i.prefixes != 0 && !intel_syntax)
          as_warn (_("skipping prefixes on this instruction"));
 
-       if (fits_in_unsigned_byte (i.tm.base_opcode))
-         {
-           insn_size += 1 + size;
-           p = frag_more (1 + size);
-         }
-       else
-         {
-           /* Opcode can be at most two bytes.  */
-           insn_size += 2 + size;
-           p = frag_more (2 + size);
-           *p++ = (i.tm.base_opcode >> 8) & 0xff;
-         }
-       *p++ = i.tm.base_opcode & 0xff;
+       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]));
@@ -2854,7 +2886,6 @@ md_assemble (line)
          as_warn (_("skipping prefixes on this instruction"));
 
        /* 1 opcode; 2 segment; offset  */
-       insn_size += prefix + 1 + 2 + size;
        p = frag_more (prefix + 1 + 2 + size);
 
        if (i.prefix[DATA_PREFIX])
@@ -2902,7 +2933,6 @@ md_assemble (line)
          {
            if (*q)
              {
-               insn_size += 1;
                p = frag_more (1);
                md_number_to_chars (p, (valueT) *q, 1);
              }
@@ -2911,12 +2941,10 @@ md_assemble (line)
        /* Now the opcode; be careful about word order here!  */
        if (fits_in_unsigned_byte (i.tm.base_opcode))
          {
-           insn_size += 1;
            FRAG_APPEND_1_CHAR (i.tm.base_opcode);
          }
        else
          {
-           insn_size += 2;
            p = frag_more (2);
            /* Put out high byte first: can't use md_number_to_chars!  */
            *p++ = (i.tm.base_opcode >> 8) & 0xff;
@@ -2926,7 +2954,6 @@ md_assemble (line)
        /* Now the modrm byte and sib byte (if present).  */
        if (i.tm.opcode_modifier & Modrm)
          {
-           insn_size += 1;
            p = frag_more (1);
            md_number_to_chars (p,
                                (valueT) (i.rm.regmem << 0
@@ -2941,7 +2968,6 @@ md_assemble (line)
                && i.rm.mode != 3
                && !(i.base_reg && (i.base_reg->reg_type & Reg16) != 0))
              {
-               insn_size += 1;
                p = frag_more (1);
                md_number_to_chars (p,
                                    (valueT) (i.sib.base << 0
@@ -2975,7 +3001,6 @@ md_assemble (line)
                          }
                        val = offset_in_range (i.op[n].disps->X_add_number,
                                               size);
-                       insn_size += size;
                        p = frag_more (size);
                        md_number_to_chars (p, val, size);
                      }
@@ -3022,7 +3047,6 @@ md_assemble (line)
                              size = 8;
                          }
 
-                       insn_size += size;
                        p = frag_more (size);
                        fix_new_exp (frag_now, p - frag_now->fr_literal, size,
                                     i.op[n].disps, pcrel,
@@ -3057,7 +3081,6 @@ md_assemble (line)
                          }
                        val = offset_in_range (i.op[n].imms->X_add_number,
                                               size);
-                       insn_size += size;
                        p = frag_more (size);
                        md_number_to_chars (p, val, size);
                      }
@@ -3083,7 +3106,6 @@ md_assemble (line)
                              size = 8;
                          }
 
-                       insn_size += size;
                        p = frag_more (size);
                        reloc_type = reloc (size, 0, sign, i.reloc[n]);
 #ifdef BFD_ASSEMBLER
@@ -3111,8 +3133,6 @@ md_assemble (line)
          }
       }
 
-    dwarf2_emit_insn (insn_size);
-
 #ifdef DEBUG386
     if (flag_debug)
       {
@@ -3161,27 +3181,41 @@ lex_got (reloc, adjust)
       int len;
 
       len = strlen (gotrel[j].str);
-      if (strncmp (cp + 1, gotrel[j].str, len) == 0)
+      if (strncasecmp (cp + 1, gotrel[j].str, len) == 0)
        {
          if (gotrel[j].rel[(unsigned int) flag_code] != 0)
            {
-             int first;
-             char *tmpbuf;
+             int first, second;
+             char *tmpbuf, *past_reloc;
 
              *reloc = gotrel[j].rel[(unsigned int) flag_code];
+             if (adjust)
+               *adjust = len;
 
              if (GOT_symbol == NULL)
                GOT_symbol = symbol_find_or_make (GLOBAL_OFFSET_TABLE_NAME);
 
              /* Replace the relocation token with ' ', so that
                 errors like foo@GOTOFF1 will be detected.  */
+
+             /* The length of the first part of our input line.  */
              first = cp - input_line_pointer;
-             tmpbuf = xmalloc (strlen (input_line_pointer));
+
+             /* The second part goes from after the reloc token until
+                (and including) an end_of_line char.  Don't use strlen
+                here as the end_of_line char may not be a NUL.  */
+             past_reloc = cp + 1 + len;
+             for (cp = past_reloc; !is_end_of_line[(unsigned char) *cp++]; )
+               ;
+             second = cp - past_reloc;
+
+             /* Allocate and copy string.  The trailing NUL shouldn't
+                be necessary, but be safe.  */
+             tmpbuf = xmalloc (first + second + 2);
              memcpy (tmpbuf, input_line_pointer, first);
              tmpbuf[first] = ' ';
-             strcpy (tmpbuf + first + 1, cp + 1 + len);
-             if (adjust)
-               *adjust = len;
+             memcpy (tmpbuf + first + 1, past_reloc, second);
+             tmpbuf[first + second + 1] = '\0';
              return tmpbuf;
            }
 
@@ -3470,6 +3504,19 @@ i386_displacement (disp_start, disp_end)
 
   exp_seg = expression (exp);
 
+  SKIP_WHITESPACE ();
+  if (*input_line_pointer)
+    as_bad (_("junk `%s' after expression"), input_line_pointer);
+#if GCC_ASM_O_HACK
+  RESTORE_END_STRING (disp_end + 1);
+#endif
+  RESTORE_END_STRING (disp_end);
+  input_line_pointer = save_input_line_pointer;
+#ifndef LEX_AT
+  if (gotfree_input_line)
+    free (gotfree_input_line);
+#endif
+
 #ifdef BFD_ASSEMBLER
   /* We do this to make sure that the section symbol is in
      the symbol table.  We will ultimately change the relocation
@@ -3477,10 +3524,18 @@ i386_displacement (disp_start, disp_end)
   if (i.reloc[this_operand] == BFD_RELOC_386_GOTOFF
       || i.reloc[this_operand] == BFD_RELOC_X86_64_GOTPCREL)
     {
+      if (exp->X_op != O_symbol)
+       {
+         as_bad (_("bad expression used with @%s"),
+                 (i.reloc[this_operand] == BFD_RELOC_X86_64_GOTPCREL
+                  ? "GOTPCREL"
+                  : "GOTOFF"));
+         return 0;
+       }
+
       if (S_IS_LOCAL (exp->X_add_symbol)
          && S_GET_SEGMENT (exp->X_add_symbol) != undefined_section)
        section_symbol (S_GET_SEGMENT (exp->X_add_symbol));
-      assert (exp->X_op == O_symbol);
       exp->X_op = O_subtract;
       exp->X_op_symbol = GOT_symbol;
       if (i.reloc[this_operand] == BFD_RELOC_X86_64_GOTPCREL)
@@ -3490,19 +3545,6 @@ i386_displacement (disp_start, disp_end)
     }
 #endif
 
-  SKIP_WHITESPACE ();
-  if (*input_line_pointer)
-    as_bad (_("junk `%s' after expression"), input_line_pointer);
-#if GCC_ASM_O_HACK
-  RESTORE_END_STRING (disp_end + 1);
-#endif
-  RESTORE_END_STRING (disp_end);
-  input_line_pointer = save_input_line_pointer;
-#ifndef LEX_AT
-  if (gotfree_input_line)
-    free (gotfree_input_line);
-#endif
-
   if (exp->X_op == O_absent || exp->X_op == O_big)
     {
       /* Missing or bad expr becomes absolute 0.  */
@@ -3971,7 +4013,8 @@ md_estimate_size_before_relax (fragP, segment)
 
        case COND_JUMP86:
          if (no_cond_jump_promotion)
-           return 1;
+           goto relax_guess;
+
          if (size == 2)
            {
              /* Negate the condition, and branch past an
@@ -3993,7 +4036,8 @@ md_estimate_size_before_relax (fragP, segment)
 
        case COND_JUMP:
          if (no_cond_jump_promotion)
-           return 1;
+           goto relax_guess;
+
          /* This changes the byte-displacement jump 0x7N
             to the (d)word-displacement jump 0x0f,0x8N.  */
          opcode[1] = opcode[0] + 0x10;
@@ -4013,8 +4057,15 @@ md_estimate_size_before_relax (fragP, segment)
       frag_wane (fragP);
       return fragP->fr_fix - old_fr_fix;
     }
-  /* Guess a short jump.  */
-  return 1;
+
+ relax_guess:
+  /* Guess size depending on current relax state.  Initially the relax
+     state will correspond to a short jump and we return 1, because
+     the variable part of the frag (the branch offset) is one byte
+     long.  However, we can relax a section more than once and in that
+     case we must either set fr_subtype back to the unrelaxed state,
+     or return the value for the appropriate branch.  */
+  return md_relax_table[fragP->fr_subtype].rlx_length;
 }
 
 /* Called after relax() is finished.
@@ -4051,10 +4102,6 @@ md_convert_frag (abfd, sec, fragP)
 
   /* Address we want to reach in file space.  */
   target_address = S_GET_VALUE (fragP->fr_symbol) + fragP->fr_offset;
-#ifdef BFD_ASSEMBLER
-  /* Not needed otherwise?  */
-  target_address += symbol_get_frag (fragP->fr_symbol)->fr_address;
-#endif
 
   /* Address opcode resides at in file space.  */
   opcode_address = fragP->fr_address + fragP->fr_fix;
@@ -4738,8 +4785,9 @@ tc_gen_reloc (section, fixp)
          switch (fixp->fx_size)
            {
            default:
-             as_bad (_("can not do %d byte pc-relative relocation"),
-                     fixp->fx_size);
+             as_bad_where (fixp->fx_file, fixp->fx_line,
+                           _("can not do %d byte pc-relative relocation"),
+                           fixp->fx_size);
              code = BFD_RELOC_32_PCREL;
              break;
            case 1: code = BFD_RELOC_8_PCREL;  break;
@@ -4752,7 +4800,9 @@ tc_gen_reloc (section, fixp)
          switch (fixp->fx_size)
            {
            default:
-             as_bad (_("can not do %d byte relocation"), fixp->fx_size);
+             as_bad_where (fixp->fx_file, fixp->fx_line,
+                           _("can not do %d byte relocation"),
+                           fixp->fx_size);
              code = BFD_RELOC_32;
              break;
            case 1: code = BFD_RELOC_8;  break;
This page took 0.02976 seconds and 4 git commands to generate.