summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2015-05-08 15:14:49 -0700
committerH.J. Lu <hjl.tools@gmail.com>2015-05-08 15:14:49 -0700
commitdc914386c07fda6ba99c88ec95fa0b9ebac026ce (patch)
tree7bde5a52c80c90a0333820c154d0eb68ef6c880c
parentb415344da2ee040cced697331e41510112ef0f4e (diff)
downloadbinutils-gdb-users/hjl/releax.tar.gz
Add pseudo RELAX prefixusers/hjl/releax
-rw-r--r--gas/config/tc-i386-intel.c3
-rw-r--r--gas/config/tc-i386.c84
-rw-r--r--include/opcode/i386.h2
-rw-r--r--opcodes/i386-opc.tbl3
-rw-r--r--opcodes/i386-tbl.h13
5 files changed, 86 insertions, 19 deletions
diff --git a/gas/config/tc-i386-intel.c b/gas/config/tc-i386-intel.c
index 2bdcf3520f4..383a71941eb 100644
--- a/gas/config/tc-i386-intel.c
+++ b/gas/config/tc-i386-intel.c
@@ -141,7 +141,8 @@ operatorT i386_operator (const char *name, unsigned int operands, char *pc)
int adjust = 0;
char *gotfree_input_line = lex_got (&i.reloc[this_operand],
&adjust,
- &intel_state.reloc_types);
+ &intel_state.reloc_types,
+ i.relax_prefix);
if (!gotfree_input_line)
break;
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:
diff --git a/include/opcode/i386.h b/include/opcode/i386.h
index 85d253372ae..d60fc1b2aa6 100644
--- a/include/opcode/i386.h
+++ b/include/opcode/i386.h
@@ -78,6 +78,8 @@
#define XRELEASE_PREFIX_OPCODE 0xf3
#define BND_PREFIX_OPCODE 0xf2
+#define PSEUDO_RELAX_PREFIX_OPCODE -1
+
#define TWO_BYTE_OPCODE_ESCAPE 0x0f
#define NOP_OPCODE (char) 0x90
diff --git a/opcodes/i386-opc.tbl b/opcodes/i386-opc.tbl
index 6edc121e1b9..2a85b4acd34 100644
--- a/opcodes/i386-opc.tbl
+++ b/opcodes/i386-opc.tbl
@@ -3059,6 +3059,9 @@ stac, 0, 0xf01, 0xcb, 2, CpuSMAP, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldS
// BND prefix
bnd, 0, 0xf2, None, 1, CpuMPX, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|IsPrefix, { 0 }
+// Pseudo RELAX prefix
+relax, 0, -1, None, 1, 0, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|IsPrefix, { 0 }
+
// MPX instructions.
bndmk, 2, 0xf30f1b, None, 2, CpuMPX, Modrm|IgnoreSize|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { Anysize|BaseIndex|Disp8|Disp32|Disp32S, RegBND }
bndmov, 2, 0x660f1a, None, 2, CpuMPX, Modrm|IgnoreSize|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|NoAVX, { Xmmword|Unspecified|BaseIndex|Disp8|Disp32|Disp32S|RegBND, RegBND }
diff --git a/opcodes/i386-tbl.h b/opcodes/i386-tbl.h
index 36411c5f3e9..8bd5a954ee4 100644
--- a/opcodes/i386-tbl.h
+++ b/opcodes/i386-tbl.h
@@ -70203,6 +70203,19 @@ const insn_template i386_optab[] =
{ { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } } },
+ { "relax", 0, -1, None, 1,
+ { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0 } },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
+ 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0 },
+ { { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } } },
{ "bndmk", 2, 0xf30f1b, None, 2,
{ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,