summaryrefslogtreecommitdiffstats
path: root/contrib/binutils/gas/config/tc-i386.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/binutils/gas/config/tc-i386.c')
-rw-r--r--contrib/binutils/gas/config/tc-i386.c455
1 files changed, 235 insertions, 220 deletions
diff --git a/contrib/binutils/gas/config/tc-i386.c b/contrib/binutils/gas/config/tc-i386.c
index fc1bd13..5de6a55 100644
--- a/contrib/binutils/gas/config/tc-i386.c
+++ b/contrib/binutils/gas/config/tc-i386.c
@@ -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, 2004
Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@@ -23,6 +23,7 @@
/* Intel 80386 machine specific gas.
Written by Eliot Dresselhaus (eliot@mgm.mit.edu).
x86_64 support by Jan Hubicka (jh@suse.cz)
+ VIA PadLock support by Michal Ludvig (mludvig@suse.cz)
Bugs & suggestions are completely welcome. This is free software.
Please help us make it better. */
@@ -30,6 +31,7 @@
#include "safe-ctype.h"
#include "subsegs.h"
#include "dwarf2dbg.h"
+#include "dw2gencfi.h"
#include "opcode/i386.h"
#ifndef REGISTER_WARNINGS
@@ -48,12 +50,6 @@
#define SCALE1_WHEN_NO_INDEX 1
#endif
-#ifdef BFD_ASSEMBLER
-#define RELOC_ENUM enum bfd_reloc_code_real
-#else
-#define RELOC_ENUM int
-#endif
-
#ifndef DEFAULT_ARCH
#define DEFAULT_ARCH "i386"
#endif
@@ -154,7 +150,7 @@ struct _i386_insn
#define Operand_PCrel 1
/* Relocation type for operand */
- RELOC_ENUM reloc[MAX_OPERANDS];
+ enum bfd_reloc_code_real reloc[MAX_OPERANDS];
/* BASE_REG, INDEX_REG, and LOG2_SCALE_FACTOR are used to encode
the base index byte below. */
@@ -207,7 +203,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 +211,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[] = ";";
@@ -244,7 +240,7 @@ static char digit_chars[256];
#define is_identifier_char(x) (identifier_chars[(unsigned char) x])
#define is_digit_char(x) (digit_chars[(unsigned char) x])
-/* All non-digit non-letter charcters that may occur in an operand. */
+/* All non-digit non-letter characters that may occur in an operand. */
static char operand_special_chars[] = "%$-+(,)*._~/<>|&^!:[@]";
/* md_assemble() always leaves the strings it's passed unaltered. To
@@ -302,6 +298,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 +317,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
@@ -523,26 +528,45 @@ i386_align_code (fragP, count)
f32_15, f32_15, f32_15, f32_15, f32_15, f32_15, f32_15
};
- /* ??? We can't use these fillers for x86_64, since they often kills the
- upper halves. Solve later. */
- if (flag_code == CODE_64BIT)
- count = 1;
+ if (count <= 0 || count > 15)
+ return;
- if (count > 0 && count <= 15)
+ /* The recommended way to pad 64bit code is to use NOPs preceded by
+ maximally four 0x66 prefixes. Balance the size of nops. */
+ if (flag_code == CODE_64BIT)
{
- if (flag_code == CODE_16BIT)
+ int i;
+ int nnops = (count + 3) / 4;
+ int len = count / nnops;
+ int remains = count - nnops * len;
+ int pos = 0;
+
+ for (i = 0; i < remains; i++)
{
- memcpy (fragP->fr_literal + fragP->fr_fix,
- f16_patt[count - 1], count);
- if (count > 8)
- /* Adjust jump offset. */
- fragP->fr_literal[fragP->fr_fix + 1] = count - 2;
+ memset (fragP->fr_literal + fragP->fr_fix + pos, 0x66, len);
+ fragP->fr_literal[fragP->fr_fix + pos + len] = 0x90;
+ pos += len + 1;
+ }
+ for (; i < nnops; i++)
+ {
+ memset (fragP->fr_literal + fragP->fr_fix + pos, 0x66, len - 1);
+ fragP->fr_literal[fragP->fr_fix + pos + len - 1] = 0x90;
+ pos += len;
}
- else
- memcpy (fragP->fr_literal + fragP->fr_fix,
- f32_patt[count - 1], count);
- fragP->fr_var = count;
}
+ else
+ if (flag_code == CODE_16BIT)
+ {
+ memcpy (fragP->fr_literal + fragP->fr_fix,
+ f16_patt[count - 1], count);
+ if (count > 8)
+ /* Adjust jump offset. */
+ fragP->fr_literal[fragP->fr_fix + 1] = count - 2;
+ }
+ else
+ memcpy (fragP->fr_literal + fragP->fr_fix,
+ f32_patt[count - 1], count);
+ fragP->fr_var = count;
}
static INLINE unsigned int
@@ -776,15 +800,8 @@ set_intel_syntax (syntax_flag)
intel_syntax = syntax_flag;
if (ask_naked_reg == 0)
- {
-#ifdef BFD_ASSEMBLER
- allow_naked_reg = (intel_syntax
- && (bfd_get_symbol_leading_char (stdoutput) != '\0'));
-#else
- /* Conservative default. */
- allow_naked_reg = 0;
-#endif
- }
+ allow_naked_reg = (intel_syntax
+ && (bfd_get_symbol_leading_char (stdoutput) != '\0'));
else
allow_naked_reg = (ask_naked_reg < 0);
}
@@ -839,7 +856,6 @@ set_cpu_arch (dummy)
demand_empty_rest_of_line ();
}
-#ifdef BFD_ASSEMBLER
unsigned long
i386_mach ()
{
@@ -850,7 +866,6 @@ i386_mach ()
else
as_fatal (_("Unknown architecture"));
}
-#endif
void
md_begin ()
@@ -967,6 +982,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
@@ -1132,7 +1158,6 @@ pt (t)
#endif /* DEBUG386 */
-#ifdef BFD_ASSEMBLER
static bfd_reloc_code_real_type reloc
PARAMS ((int, int, int, bfd_reloc_code_real_type));
@@ -1194,15 +1219,17 @@ tc_i386_fix_adjustable (fixP)
if (OUTPUT_FLAVOR != bfd_target_elf_flavour)
return 1;
- /* Prevent all adjustments to global symbols, or else dynamic
- linking will not work correctly. */
- if (S_IS_EXTERNAL (fixP->fx_addsy)
- || S_IS_WEAK (fixP->fx_addsy)
- /* Don't adjust pc-relative references to merge sections in 64-bit
- mode. */
- || (use_rela_relocations
- && (S_GET_SEGMENT (fixP->fx_addsy)->flags & SEC_MERGE) != 0
- && fixP->fx_pcrel))
+ /* Don't adjust pc-relative references to merge sections in 64-bit
+ mode. */
+ if (use_rela_relocations
+ && (S_GET_SEGMENT (fixP->fx_addsy)->flags & SEC_MERGE) != 0
+ && fixP->fx_pcrel)
+ return 0;
+
+ /* The x86_64 GOTPCREL are represented as 32bit PCrel relocations
+ and changed later by validate_fix. */
+ if (GOT_symbol && fixP->fx_subsy == GOT_symbol
+ && fixP->fx_r_type == BFD_RELOC_32_PCREL)
return 0;
/* adjust_reloc_syms doesn't know about the GOT. */
@@ -1220,35 +1247,17 @@ 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;
#endif
return 1;
}
-#else
-#define reloc(SIZE,PCREL,SIGN,OTHER) 0
-#define BFD_RELOC_8 0
-#define BFD_RELOC_16 0
-#define BFD_RELOC_32 0
-#define BFD_RELOC_8_PCREL 0
-#define BFD_RELOC_16_PCREL 0
-#define BFD_RELOC_32_PCREL 0
-#define BFD_RELOC_386_PLT32 0
-#define BFD_RELOC_386_GOT32 0
-#define BFD_RELOC_386_GOTOFF 0
-#define BFD_RELOC_386_TLS_GD 0
-#define BFD_RELOC_386_TLS_LDM 0
-#define BFD_RELOC_386_TLS_LDO_32 0
-#define BFD_RELOC_386_TLS_IE_32 0
-#define BFD_RELOC_386_TLS_IE 0
-#define BFD_RELOC_386_TLS_GOTIE 0
-#define BFD_RELOC_386_TLS_LE_32 0
-#define BFD_RELOC_386_TLS_LE 0
-#define BFD_RELOC_X86_64_PLT32 0
-#define BFD_RELOC_X86_64_GOT32 0
-#define BFD_RELOC_X86_64_GOTPCREL 0
-#endif
static int intel_float_operand PARAMS ((const char *mnemonic));
@@ -1367,13 +1376,28 @@ md_assemble (line)
if (i.tm.opcode_modifier & ImmExt)
{
+ expressionS *exp;
+
+ if ((i.tm.cpu_flags & CpuPNI) && i.operands > 0)
+ {
+ /* These Intel Prescott 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++];
@@ -1758,7 +1782,7 @@ swap_operands ()
{
union i386_op temp_op;
unsigned int temp_type;
- RELOC_ENUM temp_reloc;
+ enum bfd_reloc_code_real temp_reloc;
int xchg1 = 0;
int xchg2 = 0;
@@ -3100,7 +3124,6 @@ output_interseg_jump ()
md_number_to_chars (p + size, (valueT) i.op[0].imms->X_add_number, 2);
}
-
static void
output_insn ()
{
@@ -3128,10 +3151,23 @@ output_insn ()
char *p;
unsigned char *q;
- /* All opcodes on i386 have either 1 or 2 bytes. We may use third
- byte for the SSE instructions to specify a prefix they require. */
- if (i.tm.base_opcode & 0xff0000)
- add_prefix ((i.tm.base_opcode >> 16) & 0xff);
+ /* All opcodes on i386 have either 1 or 2 bytes, PadLock instructions
+ have 3 bytes. We may use one more higher byte to specify a prefix
+ the instruction requires. */
+ if ((i.tm.cpu_flags & CpuPadLock) != 0
+ && (i.tm.base_opcode & 0xff000000) != 0)
+ {
+ unsigned int prefix;
+ prefix = (i.tm.base_opcode >> 24) & 0xff;
+
+ if (prefix != REPE_PREFIX_OPCODE
+ || i.prefix[LOCKREP_PREFIX] != REPE_PREFIX_OPCODE)
+ add_prefix (prefix);
+ }
+ else
+ if ((i.tm.cpu_flags & CpuPadLock) == 0
+ && (i.tm.base_opcode & 0xff0000) != 0)
+ add_prefix ((i.tm.base_opcode >> 16) & 0xff);
/* The prefix bytes. */
for (q = i.prefix;
@@ -3152,7 +3188,14 @@ output_insn ()
}
else
{
- p = frag_more (2);
+ if ((i.tm.cpu_flags & CpuPadLock) != 0)
+ {
+ p = frag_more (3);
+ *p++ = (i.tm.base_opcode >> 16) & 0xff;
+ }
+ else
+ p = frag_more (2);
+
/* Put out high byte first: can't use md_number_to_chars! */
*p++ = (i.tm.base_opcode >> 8) & 0xff;
*p = i.tm.base_opcode & 0xff;
@@ -3232,7 +3275,7 @@ output_disp (insn_start_frag, insn_start_off)
}
else
{
- RELOC_ENUM reloc_type;
+ enum bfd_reloc_code_real reloc_type;
int size = 4;
int sign = 0;
int pcrel = (i.flags[n] & Operand_PCrel) != 0;
@@ -3276,7 +3319,6 @@ output_disp (insn_start_frag, insn_start_off)
p = frag_more (size);
reloc_type = reloc (size, pcrel, sign, i.reloc[n]);
-#ifdef BFD_ASSEMBLER
if (reloc_type == BFD_RELOC_32
&& GOT_symbol
&& GOT_symbol == i.op[n].disps->X_add_symbol
@@ -3307,7 +3349,6 @@ output_disp (insn_start_frag, insn_start_off)
reloc_type = BFD_RELOC_386_GOTPC;
i.op[n].disps->X_add_number += add;
}
-#endif
fix_new_exp (frag_now, p - frag_now->fr_literal, size,
i.op[n].disps, pcrel, reloc_type);
}
@@ -3352,7 +3393,7 @@ output_imm (insn_start_frag, insn_start_off)
Need a 32-bit fixup (don't support 8bit
non-absolute imms). Try to support other
sizes ... */
- RELOC_ENUM reloc_type;
+ enum bfd_reloc_code_real reloc_type;
int size = 4;
int sign = 0;
@@ -3370,7 +3411,7 @@ output_imm (insn_start_frag, insn_start_off)
p = frag_more (size);
reloc_type = reloc (size, 0, sign, i.reloc[n]);
-#ifdef BFD_ASSEMBLER
+
/* This is tough to explain. We end up with this one if we
* have operands that look like
* "_GLOBAL_OFFSET_TABLE_+[.-.L284]". The goal here is to
@@ -3443,7 +3484,6 @@ output_imm (insn_start_frag, insn_start_off)
reloc_type = BFD_RELOC_386_GOTPC;
i.op[n].imms->X_add_number += add;
}
-#endif
fix_new_exp (frag_now, p - frag_now->fr_literal, size,
i.op[n].imms, 0, reloc_type);
}
@@ -3452,7 +3492,7 @@ output_imm (insn_start_frag, insn_start_off)
}
#ifndef LEX_AT
-static char *lex_got PARAMS ((RELOC_ENUM *, int *));
+static char *lex_got PARAMS ((enum bfd_reloc_code_real *, int *));
/* Parse operands of the form
<symbol>@GOTOFF+<nnn>
@@ -3465,23 +3505,24 @@ static char *lex_got PARAMS ((RELOC_ENUM *, int *));
input line. Otherwise return NULL. */
static char *
lex_got (reloc, adjust)
- RELOC_ENUM *reloc;
+ enum bfd_reloc_code_real *reloc;
int *adjust;
{
static const char * const mode_name[NUM_FLAG_CODE] = { "32", "16", "64" };
static const struct {
const char *str;
- const RELOC_ENUM rel[NUM_FLAG_CODE];
+ const enum bfd_reloc_code_real rel[NUM_FLAG_CODE];
} gotrel[] = {
{ "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 } }
@@ -3548,7 +3589,7 @@ lex_got (reloc, adjust)
/* x86_cons_fix_new is called via the expression parsing code when a
reloc is needed. We use this hook to get the correct .got reloc. */
-static RELOC_ENUM got_reloc = NO_RELOC;
+static enum bfd_reloc_code_real got_reloc = NO_RELOC;
void
x86_cons_fix_new (frag, off, len, exp)
@@ -3557,7 +3598,7 @@ x86_cons_fix_new (frag, off, len, exp)
unsigned int len;
expressionS *exp;
{
- RELOC_ENUM r = reloc (len, 0, 0, got_reloc);
+ enum bfd_reloc_code_real r = reloc (len, 0, 0, got_reloc);
got_reloc = NO_RELOC;
fix_new_exp (frag, off, len, exp, 0, r);
}
@@ -3663,25 +3704,15 @@ i386_immediate (imm_start)
exp->X_add_number = (exp->X_add_number ^ ((addressT) 1 << 31)) - ((addressT) 1 << 31);
}
#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT))
- else if (1
-#ifdef BFD_ASSEMBLER
- && OUTPUT_FLAVOR == bfd_target_aout_flavour
-#endif
+ else if (OUTPUT_FLAVOR == bfd_target_aout_flavour
&& exp_seg != absolute_section
&& exp_seg != text_section
&& exp_seg != data_section
&& exp_seg != bss_section
&& exp_seg != undefined_section
-#ifdef BFD_ASSEMBLER
- && !bfd_is_com_section (exp_seg)
-#endif
- )
+ && !bfd_is_com_section (exp_seg))
{
-#ifdef BFD_ASSEMBLER
as_bad (_("unimplemented segment %s in operand"), exp_seg->name);
-#else
- as_bad (_("unimplemented segment type %d in operand"), exp_seg);
-#endif
return 0;
}
#endif
@@ -3838,7 +3869,6 @@ i386_displacement (disp_start, disp_end)
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
to be relative to the beginning of the section. */
@@ -3864,7 +3894,6 @@ i386_displacement (disp_start, disp_end)
else
i.reloc[this_operand] = BFD_RELOC_32;
}
-#endif
if (exp->X_op == O_absent || exp->X_op == O_big)
{
@@ -3879,24 +3908,15 @@ i386_displacement (disp_start, disp_end)
#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT))
if (exp->X_op != O_constant
-#ifdef BFD_ASSEMBLER
&& OUTPUT_FLAVOR == bfd_target_aout_flavour
-#endif
&& exp_seg != absolute_section
&& exp_seg != text_section
&& exp_seg != data_section
&& exp_seg != bss_section
&& exp_seg != undefined_section
-#ifdef BFD_ASSEMBLER
- && !bfd_is_com_section (exp_seg)
-#endif
- )
+ && !bfd_is_com_section (exp_seg))
{
-#ifdef BFD_ASSEMBLER
as_bad (_("unimplemented segment %s in operand"), exp_seg->name);
-#else
- as_bad (_("unimplemented segment type %d in operand"), exp_seg);
-#endif
return 0;
}
#endif
@@ -4325,7 +4345,7 @@ md_estimate_size_before_relax (fragP, segment)
/* Symbol is undefined in this segment, or we need to keep a
reloc so that weak symbols can be overridden. */
int size = (fragP->fr_subtype & CODE16) ? 2 : 4;
- RELOC_ENUM reloc_type;
+ enum bfd_reloc_code_real reloc_type;
unsigned char *opcode;
int old_fr_fix;
@@ -4424,19 +4444,11 @@ md_estimate_size_before_relax (fragP, segment)
Out: Any fixSs and constants are set up.
Caller will turn frag into a ".space 0". */
-#ifndef BFD_ASSEMBLER
-void
-md_convert_frag (headers, sec, fragP)
- object_headers *headers ATTRIBUTE_UNUSED;
- segT sec ATTRIBUTE_UNUSED;
- fragS *fragP;
-#else
void
md_convert_frag (abfd, sec, fragP)
bfd *abfd ATTRIBUTE_UNUSED;
segT sec ATTRIBUTE_UNUSED;
fragS *fragP;
-#endif
{
unsigned char *opcode;
unsigned char *where_to_put_displacement = NULL;
@@ -4575,7 +4587,7 @@ md_apply_fix3 (fixP, valP, seg)
char *p = fixP->fx_where + fixP->fx_frag->fr_literal;
valueT value = *valP;
-#if defined (BFD_ASSEMBLER) && !defined (TE_Mach)
+#if !defined (TE_Mach)
if (fixP->fx_pcrel)
{
switch (fixP->fx_r_type)
@@ -4595,7 +4607,7 @@ md_apply_fix3 (fixP, valP, seg)
}
}
- if (fixP->fx_pcrel
+ if (fixP->fx_addsy != NULL
&& (fixP->fx_r_type == BFD_RELOC_32_PCREL
|| fixP->fx_r_type == BFD_RELOC_16_PCREL
|| fixP->fx_r_type == BFD_RELOC_8_PCREL)
@@ -4616,19 +4628,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;
}
@@ -4643,7 +4652,7 @@ md_apply_fix3 (fixP, valP, seg)
}
/* Fix a few things - the dynamic linker expects certain values here,
- and we must not dissappoint it. */
+ and we must not disappoint it. */
#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
if (OUTPUT_FLAVOR == bfd_target_elf_flavour
&& fixP->fx_addsy)
@@ -4656,12 +4665,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;
@@ -4676,12 +4698,11 @@ md_apply_fix3 (fixP, valP, seg)
}
#endif /* defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) */
*valP = value;
-#endif /* defined (BFD_ASSEMBLER) && !defined (TE_Mach) */
+#endif /* !defined (TE_Mach) */
/* Are we finished with this relocation now? */
if (fixP->fx_addsy == NULL)
fixP->fx_done = 1;
-#ifdef BFD_ASSEMBLER
else if (use_rela_relocations)
{
fixP->fx_no_overflow = 1;
@@ -4689,7 +4710,7 @@ md_apply_fix3 (fixP, valP, seg)
fixP->fx_addnumber = value;
value = 0;
}
-#endif
+
md_number_to_chars (p, value, fixP->fx_size);
}
@@ -4835,9 +4856,9 @@ parse_register (reg_string, end_op)
}
#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[] = {
@@ -4858,6 +4879,10 @@ md_parse_option (c, arg)
{
switch (c)
{
+ case 'n':
+ optimize_align_code = 0;
+ break;
+
case 'q':
quiet_warnings = 1;
break;
@@ -4919,15 +4944,16 @@ 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
}
-#ifdef BFD_ASSEMBLER
#if ((defined (OBJ_MAYBE_COFF) && defined (OBJ_MAYBE_AOUT)) \
|| defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF))
@@ -5009,7 +5035,6 @@ void i386_elf_emit_arch_note ()
}
}
#endif
-#endif /* BFD_ASSEMBLER */
symbolS *
md_undefined_symbol (name)
@@ -5039,7 +5064,6 @@ md_section_align (segment, size)
segT segment ATTRIBUTE_UNUSED;
valueT size;
{
-#ifdef BFD_ASSEMBLER
#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT))
if (OUTPUT_FLAVOR == bfd_target_aout_flavour)
{
@@ -5054,7 +5078,6 @@ md_section_align (segment, size)
size = ((size + (1 << align) - 1) & ((valueT) -1 << align));
}
#endif
-#endif
return size;
}
@@ -5085,8 +5108,6 @@ s_bss (ignore)
#endif
-#ifdef BFD_ASSEMBLER
-
void
i386_validate_fix (fixp)
fixS *fixp;
@@ -5136,6 +5157,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:
@@ -5213,6 +5239,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:
@@ -5238,73 +5267,6 @@ tc_gen_reloc (section, fixp)
return rel;
}
-#else /* !BFD_ASSEMBLER */
-
-#if (defined(OBJ_AOUT) | defined(OBJ_BOUT))
-void
-tc_aout_fix_to_chars (where, fixP, segment_address_in_file)
- char *where;
- fixS *fixP;
- relax_addressT segment_address_in_file;
-{
- /* In: length of relocation (or of address) in chars: 1, 2 or 4.
- Out: GNU LD relocation length code: 0, 1, or 2. */
-
- static const unsigned char nbytes_r_length[] = { 42, 0, 1, 42, 2 };
- long r_symbolnum;
-
- know (fixP->fx_addsy != NULL);
-
- md_number_to_chars (where,
- (valueT) (fixP->fx_frag->fr_address
- + fixP->fx_where - segment_address_in_file),
- 4);
-
- r_symbolnum = (S_IS_DEFINED (fixP->fx_addsy)
- ? S_GET_TYPE (fixP->fx_addsy)
- : fixP->fx_addsy->sy_number);
-
- where[6] = (r_symbolnum >> 16) & 0x0ff;
- where[5] = (r_symbolnum >> 8) & 0x0ff;
- where[4] = r_symbolnum & 0x0ff;
- where[7] = ((((!S_IS_DEFINED (fixP->fx_addsy)) << 3) & 0x08)
- | ((nbytes_r_length[fixP->fx_size] << 1) & 0x06)
- | (((fixP->fx_pcrel << 0) & 0x01) & 0x0f));
-}
-
-#endif /* OBJ_AOUT or OBJ_BOUT. */
-
-#if defined (I386COFF)
-
-short
-tc_coff_fix2rtype (fixP)
- fixS *fixP;
-{
- if (fixP->fx_r_type == R_IMAGEBASE)
- return R_IMAGEBASE;
-
- return (fixP->fx_pcrel ?
- (fixP->fx_size == 1 ? R_PCRBYTE :
- fixP->fx_size == 2 ? R_PCRWORD :
- R_PCRLONG) :
- (fixP->fx_size == 1 ? R_RELBYTE :
- fixP->fx_size == 2 ? R_RELWORD :
- R_DIR32));
-}
-
-int
-tc_coff_sizemachdep (frag)
- fragS *frag;
-{
- if (frag->fr_next)
- return (frag->fr_next->fr_address - frag->fr_address);
- else
- return 0;
-}
-
-#endif /* I386COFF */
-
-#endif /* !BFD_ASSEMBLER */
/* 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
@@ -5535,8 +5497,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);
}
}
@@ -6255,3 +6218,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);
+}
OpenPOWER on IntegriCloud