diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2015-05-08 15:14:49 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2015-05-08 15:14:49 -0700 |
commit | dc914386c07fda6ba99c88ec95fa0b9ebac026ce (patch) | |
tree | 7bde5a52c80c90a0333820c154d0eb68ef6c880c | |
parent | b415344da2ee040cced697331e41510112ef0f4e (diff) | |
download | binutils-gdb-users/hjl/releax.tar.gz |
Add pseudo RELAX prefixusers/hjl/releax
-rw-r--r-- | gas/config/tc-i386-intel.c | 3 | ||||
-rw-r--r-- | gas/config/tc-i386.c | 84 | ||||
-rw-r--r-- | include/opcode/i386.h | 2 | ||||
-rw-r--r-- | opcodes/i386-opc.tbl | 3 | ||||
-rw-r--r-- | opcodes/i386-tbl.h | 13 |
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, |