summaryrefslogtreecommitdiff
path: root/gas/config/tc-i386.c
diff options
context:
space:
mode:
Diffstat (limited to 'gas/config/tc-i386.c')
-rw-r--r--gas/config/tc-i386.c84
1 files changed, 66 insertions, 18 deletions
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index bbc0969da18..ffcca070482 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -369,6 +369,9 @@ struct _i386_insn
/* Have BND prefix. */
const char *bnd_prefix;
+ /* Have RELAX prefix. */
+ int relax_prefix;
+
/* Need VREX to support upper 16 registers. */
int need_vrex;
@@ -2067,6 +2070,20 @@ add_prefix (unsigned int prefix)
default:
abort ();
+ case PSEUDO_RELAX_PREFIX_OPCODE:
+ i.relax_prefix = prefix;
+ if (object_64bit)
+ {
+ prefix = DATA_PREFIX_OPCODE;
+ q = DATA_PREFIX;
+ }
+ else
+ {
+ prefix = CS_PREFIX_OPCODE;
+ q = SEG_PREFIX;
+ }
+ break;
+
case CS_PREFIX_OPCODE:
case DS_PREFIX_OPCODE:
case ES_PREFIX_OPCODE:
@@ -2748,6 +2765,7 @@ static bfd_reloc_code_real_type
reloc (unsigned int size,
int pcrel,
int sign,
+ int relax_prefix,
bfd_reloc_code_real_type other)
{
if (other != NO_RELOC)
@@ -2826,7 +2844,11 @@ reloc (unsigned int size,
{
case 1: return BFD_RELOC_8_PCREL;
case 2: return BFD_RELOC_16_PCREL;
- case 4: return BFD_RELOC_32_PCREL;
+ case 4: return (relax_prefix
+ ? (object_64bit
+ ? BFD_RELOC_X86_64_RELAX_PC32
+ : -1)
+ : BFD_RELOC_32_PCREL);
case 8: return BFD_RELOC_64_PCREL;
}
as_bad (_("cannot do %u byte pc-relative relocation"), size);
@@ -6628,7 +6650,8 @@ output_branch (void)
{
prefix = 1;
i.prefixes -= 1;
- code16 ^= CODE16;
+ if (!i.relax_prefix)
+ code16 ^= CODE16;
}
/* Pentium4 branch hints. */
if (i.prefix[SEG_PREFIX] == CS_PREFIX_OPCODE /* not taken */
@@ -6691,7 +6714,13 @@ output_branch (void)
/* 1 possible extra opcode + 4 byte displacement go in var part.
Pass reloc in fr_var. */
- frag_var (rs_machine_dependent, 5, i.reloc[0], subtype, sym, off, p);
+ frag_var (rs_machine_dependent, 5,
+ ((!object_64bit
+ || i.reloc[0] != NO_RELOC
+ || !i.relax_prefix)
+ ? i.reloc[0]
+ : BFD_RELOC_X86_64_RELAX_PC32),
+ subtype, sym, off, p);
}
static void
@@ -6730,7 +6759,8 @@ output_jump (void)
{
FRAG_APPEND_1_CHAR (DATA_PREFIX_OPCODE);
i.prefixes -= 1;
- code16 ^= CODE16;
+ if (!i.relax_prefix)
+ code16 ^= CODE16;
}
size = 4;
@@ -6767,7 +6797,9 @@ output_jump (void)
}
fixP = fix_new_exp (frag_now, p - frag_now->fr_literal, size,
- i.op[0].disps, 1, reloc (size, 1, 1, i.reloc[0]));
+ i.op[0].disps, 1, reloc (size, 1, 1,
+ i.relax_prefix,
+ 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
@@ -6793,6 +6825,7 @@ output_interseg_jump (void)
{
prefix = 1;
i.prefixes -= 1;
+ gas_assert (!i.relax_prefix);
code16 ^= CODE16;
}
if (i.prefix[REX_PREFIX] != 0)
@@ -6833,7 +6866,7 @@ output_interseg_jump (void)
}
else
fix_new_exp (frag_now, p - frag_now->fr_literal, size,
- i.op[1].imms, 0, reloc (size, 0, 0, i.reloc[1]));
+ i.op[1].imms, 0, reloc (size, 0, 0, 0, i.reloc[1]));
if (i.op[0].imms->X_op != O_constant)
as_bad (_("can't handle non absolute segment in `%s'"),
i.tm.name);
@@ -7112,7 +7145,9 @@ output_disp (fragS *insn_start_frag, offsetT insn_start_off)
}
p = frag_more (size);
- reloc_type = reloc (size, pcrel, sign, i.reloc[n]);
+ reloc_type = reloc (size, pcrel, sign,
+ i.relax_prefix,
+ i.reloc[n]);
if (GOT_symbol
&& GOT_symbol == i.op[n].disps->X_add_symbol
&& (((reloc_type == BFD_RELOC_32
@@ -7203,7 +7238,7 @@ output_imm (fragS *insn_start_frag, offsetT insn_start_off)
sign = 0;
p = frag_more (size);
- reloc_type = reloc (size, 0, sign, i.reloc[n]);
+ reloc_type = reloc (size, 0, sign, 0, i.reloc[n]);
/* This is tough to explain. We end up with this one if we
* have operands that look like
@@ -7296,7 +7331,7 @@ void
x86_cons_fix_new (fragS *frag, unsigned int off, unsigned int len,
expressionS *exp, bfd_reloc_code_real_type r)
{
- r = reloc (len, 0, cons_sign, r);
+ r = reloc (len, 0, cons_sign, 0, r);
#ifdef TE_PE
if (exp->X_op == O_secrel)
@@ -7322,7 +7357,7 @@ x86_address_bytes (void)
#if !(defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) || defined (OBJ_MACH_O)) \
|| defined (LEX_AT)
-# define lex_got(reloc, adjust, types) NULL
+# define lex_got(reloc, adjust, types, relax_prefix) NULL
#else
/* Parse operands of the form
<symbol>@GOTOFF+<nnn>
@@ -7336,7 +7371,8 @@ x86_address_bytes (void)
static char *
lex_got (enum bfd_reloc_code_real *rel,
int *adjust,
- i386_operand_type *types)
+ i386_operand_type *types,
+ int relax_prefix)
{
/* Some of the relocations depend on the size of what field is to
be relocated. But in our callers i386_immediate and i386_displacement
@@ -7471,6 +7507,8 @@ lex_got (enum bfd_reloc_code_real *rel,
*adjust = len;
memcpy (tmpbuf + first, past_reloc, second);
tmpbuf[first + second] = '\0';
+ if (relax_prefix && *rel == BFD_RELOC_X86_64_PLT32)
+ *rel = BFD_RELOC_X86_64_RELAX_PLT32;
return tmpbuf;
}
@@ -7503,7 +7541,8 @@ lex_got (enum bfd_reloc_code_real *rel,
static char *
lex_got (enum bfd_reloc_code_real *rel ATTRIBUTE_UNUSED,
int *adjust ATTRIBUTE_UNUSED,
- i386_operand_type *types)
+ i386_operand_type *types,
+ int relax_prefix ATTRIBUTE_UNUSED)
{
static const struct
{
@@ -7604,7 +7643,7 @@ x86_cons (expressionS *exp, int size)
int adjust = 0;
save = input_line_pointer;
- gotfree_input_line = lex_got (&got_reloc, &adjust, NULL);
+ gotfree_input_line = lex_got (&got_reloc, &adjust, NULL, 0);
if (gotfree_input_line)
input_line_pointer = gotfree_input_line;
@@ -7838,7 +7877,8 @@ i386_immediate (char *imm_start)
save_input_line_pointer = input_line_pointer;
input_line_pointer = imm_start;
- gotfree_input_line = lex_got (&i.reloc[this_operand], NULL, &types);
+ gotfree_input_line = lex_got (&i.reloc[this_operand], NULL, &types,
+ i.relax_prefix);
if (gotfree_input_line)
input_line_pointer = gotfree_input_line;
@@ -8016,7 +8056,7 @@ i386_displacement (char *disp_start, char *disp_end)
{
/* For PC-relative branches, the width of the displacement
is dependent upon data size, not address size. */
- override = (i.prefix[DATA_PREFIX] != 0);
+ override = i.prefix[DATA_PREFIX] != 0 && !i.relax_prefix;
if (flag_code == CODE_64BIT)
{
if (override || i.suffix == WORD_MNEM_SUFFIX)
@@ -8095,7 +8135,8 @@ i386_displacement (char *disp_start, char *disp_end)
*displacement_string_end = '0';
}
#endif
- gotfree_input_line = lex_got (&i.reloc[this_operand], NULL, &types);
+ gotfree_input_line = lex_got (&i.reloc[this_operand], NULL, &types,
+ i.relax_prefix);
if (gotfree_input_line)
input_line_pointer = gotfree_input_line;
@@ -9075,7 +9116,8 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
&& (fixP->fx_r_type == BFD_RELOC_32_PCREL
|| fixP->fx_r_type == BFD_RELOC_64_PCREL
|| fixP->fx_r_type == BFD_RELOC_16_PCREL
- || fixP->fx_r_type == BFD_RELOC_8_PCREL)
+ || fixP->fx_r_type == BFD_RELOC_8_PCREL
+ || fixP->fx_r_type == BFD_RELOC_X86_64_RELAX_PC32)
&& !use_rela_relocations)
{
/* This is a hack. There should be a better way to handle this.
@@ -9144,6 +9186,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
{
case BFD_RELOC_386_PLT32:
case BFD_RELOC_X86_64_PLT32:
+ case BFD_RELOC_X86_64_RELAX_PLT32:
/* Make the jump instruction point to the address of the operand. At
runtime we merely add the offset to the actual PLT entry. */
value = -4;
@@ -10233,6 +10276,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
#endif
case BFD_RELOC_X86_64_PLT32:
+ case BFD_RELOC_X86_64_RELAX_PLT32:
case BFD_RELOC_X86_64_GOT32:
case BFD_RELOC_X86_64_GOTPCREL:
case BFD_RELOC_386_PLT32:
@@ -10293,7 +10337,10 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
break;
case 1: code = BFD_RELOC_8_PCREL; break;
case 2: code = BFD_RELOC_16_PCREL; break;
- case 4: code = BFD_RELOC_32_PCREL; break;
+ case 4:
+ code = (fixp->fx_r_type == BFD_RELOC_X86_64_RELAX_PC32
+ ? fixp-> fx_r_type : BFD_RELOC_32_PCREL);
+ break;
#ifdef BFD64
case 8: code = BFD_RELOC_64_PCREL; break;
#endif
@@ -10386,6 +10433,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
switch (code)
{
case BFD_RELOC_X86_64_PLT32:
+ case BFD_RELOC_X86_64_RELAX_PLT32:
case BFD_RELOC_X86_64_GOT32:
case BFD_RELOC_X86_64_GOTPCREL:
case BFD_RELOC_X86_64_TLSGD: