1,8 → 1,5 |
/* tc-i386.c -- Assemble code for the Intel 80386 |
Copyright 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, |
2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, |
2012 |
Free Software Foundation, Inc. |
Copyright (C) 1989-2015 Free Software Foundation, Inc. |
|
This file is part of GAS, the GNU Assembler. |
|
516,6 → 513,16 |
static enum x86_elf_abi x86_elf_abi = I386_ABI; |
#endif |
|
#if defined (TE_PE) || defined (TE_PEP) |
/* Use big object file format. */ |
static int use_big_obj = 0; |
#endif |
|
#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) |
/* 1 if generating code for a shared library. */ |
static int shared = 0; |
#endif |
|
/* 1 for intel syntax, |
0 if att syntax. */ |
static int intel_syntax = 0; |
541,6 → 548,10 |
/* 1 if pseudo index register, eiz/riz, is allowed . */ |
static int allow_index_reg = 0; |
|
/* 1 if the assembler should ignore LOCK prefix, even if it was |
specified explicitly. */ |
static int omit_lock_prefix = 0; |
|
static enum check_kind |
{ |
check_none = 0, |
614,6 → 625,9 |
evexw1 |
} evexwig; |
|
/* Value to encode in EVEX RC bits, for SAE-only instructions. */ |
static enum rc_type evexrcig = rne; |
|
/* Pre-defined "_GLOBAL_OFFSET_TABLE_". */ |
static symbolS *GOT_symbol; |
|
752,6 → 766,8 |
CPU_L1OM_FLAGS, 0, 0 }, |
{ STRING_COMMA_LEN ("k1om"), PROCESSOR_K1OM, |
CPU_K1OM_FLAGS, 0, 0 }, |
{ STRING_COMMA_LEN ("iamcu"), PROCESSOR_IAMCU, |
CPU_IAMCU_FLAGS, 0, 0 }, |
{ STRING_COMMA_LEN ("k6"), PROCESSOR_K6, |
CPU_K6_FLAGS, 0, 0 }, |
{ STRING_COMMA_LEN ("k6_2"), PROCESSOR_K6, |
772,6 → 788,10 |
CPU_BDVER2_FLAGS, 0, 0 }, |
{ STRING_COMMA_LEN ("bdver3"), PROCESSOR_BD, |
CPU_BDVER3_FLAGS, 0, 0 }, |
{ STRING_COMMA_LEN ("bdver4"), PROCESSOR_BD, |
CPU_BDVER4_FLAGS, 0, 0 }, |
{ STRING_COMMA_LEN ("znver1"), PROCESSOR_ZNVER, |
CPU_ZNVER1_FLAGS, 0, 0 }, |
{ STRING_COMMA_LEN ("btver1"), PROCESSOR_BT, |
CPU_BTVER1_FLAGS, 0, 0 }, |
{ STRING_COMMA_LEN ("btver2"), PROCESSOR_BT, |
816,6 → 836,12 |
CPU_AVX512ER_FLAGS, 0, 0 }, |
{ STRING_COMMA_LEN (".avx512pf"), PROCESSOR_UNKNOWN, |
CPU_AVX512PF_FLAGS, 0, 0 }, |
{ STRING_COMMA_LEN (".avx512dq"), PROCESSOR_UNKNOWN, |
CPU_AVX512DQ_FLAGS, 0, 0 }, |
{ STRING_COMMA_LEN (".avx512bw"), PROCESSOR_UNKNOWN, |
CPU_AVX512BW_FLAGS, 0, 0 }, |
{ STRING_COMMA_LEN (".avx512vl"), PROCESSOR_UNKNOWN, |
CPU_AVX512VL_FLAGS, 0, 0 }, |
{ STRING_COMMA_LEN (".noavx"), PROCESSOR_UNKNOWN, |
CPU_ANY_AVX_FLAGS, 0, 1 }, |
{ STRING_COMMA_LEN (".vmx"), PROCESSOR_UNKNOWN, |
828,6 → 854,10 |
CPU_XSAVE_FLAGS, 0, 0 }, |
{ STRING_COMMA_LEN (".xsaveopt"), PROCESSOR_UNKNOWN, |
CPU_XSAVEOPT_FLAGS, 0, 0 }, |
{ STRING_COMMA_LEN (".xsavec"), PROCESSOR_UNKNOWN, |
CPU_XSAVEC_FLAGS, 0, 0 }, |
{ STRING_COMMA_LEN (".xsaves"), PROCESSOR_UNKNOWN, |
CPU_XSAVES_FLAGS, 0, 0 }, |
{ STRING_COMMA_LEN (".aes"), PROCESSOR_UNKNOWN, |
CPU_AES_FLAGS, 0, 0 }, |
{ STRING_COMMA_LEN (".pclmul"), PROCESSOR_UNKNOWN, |
902,6 → 932,26 |
CPU_MPX_FLAGS, 0, 0 }, |
{ STRING_COMMA_LEN (".sha"), PROCESSOR_UNKNOWN, |
CPU_SHA_FLAGS, 0, 0 }, |
{ STRING_COMMA_LEN (".clflushopt"), PROCESSOR_UNKNOWN, |
CPU_CLFLUSHOPT_FLAGS, 0, 0 }, |
{ STRING_COMMA_LEN (".prefetchwt1"), PROCESSOR_UNKNOWN, |
CPU_PREFETCHWT1_FLAGS, 0, 0 }, |
{ STRING_COMMA_LEN (".se1"), PROCESSOR_UNKNOWN, |
CPU_SE1_FLAGS, 0, 0 }, |
{ STRING_COMMA_LEN (".clwb"), PROCESSOR_UNKNOWN, |
CPU_CLWB_FLAGS, 0, 0 }, |
{ STRING_COMMA_LEN (".pcommit"), PROCESSOR_UNKNOWN, |
CPU_PCOMMIT_FLAGS, 0, 0 }, |
{ STRING_COMMA_LEN (".avx512ifma"), PROCESSOR_UNKNOWN, |
CPU_AVX512IFMA_FLAGS, 0, 0 }, |
{ STRING_COMMA_LEN (".avx512vbmi"), PROCESSOR_UNKNOWN, |
CPU_AVX512VBMI_FLAGS, 0, 0 }, |
{ STRING_COMMA_LEN (".clzero"), PROCESSOR_UNKNOWN, |
CPU_CLZERO_FLAGS, 0, 0 }, |
{ STRING_COMMA_LEN (".mwaitx"), PROCESSOR_UNKNOWN, |
CPU_MWAITX_FLAGS, 0, 0 }, |
{ STRING_COMMA_LEN (".ospke"), PROCESSOR_UNKNOWN, |
CPU_OSPKE_FLAGS, 0, 0 }, |
}; |
|
#ifdef I386COFF |
1094,86 → 1144,10 |
/* nopw %cs:0L(%[re]ax,%[re]ax,1) */ |
static const char alt_10[] = |
{0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00}; |
/* data16 |
nopw %cs:0L(%[re]ax,%[re]ax,1) */ |
static const char alt_long_11[] = |
{0x66, |
0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00}; |
/* data16 |
data16 |
nopw %cs:0L(%[re]ax,%[re]ax,1) */ |
static const char alt_long_12[] = |
{0x66, |
0x66, |
0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00}; |
/* data16 |
data16 |
data16 |
nopw %cs:0L(%[re]ax,%[re]ax,1) */ |
static const char alt_long_13[] = |
{0x66, |
0x66, |
0x66, |
0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00}; |
/* data16 |
data16 |
data16 |
data16 |
nopw %cs:0L(%[re]ax,%[re]ax,1) */ |
static const char alt_long_14[] = |
{0x66, |
0x66, |
0x66, |
0x66, |
0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00}; |
/* data16 |
data16 |
data16 |
data16 |
data16 |
nopw %cs:0L(%[re]ax,%[re]ax,1) */ |
static const char alt_long_15[] = |
{0x66, |
0x66, |
0x66, |
0x66, |
0x66, |
0x66,0x2e,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00}; |
/* nopl 0(%[re]ax,%[re]ax,1) |
nopw 0(%[re]ax,%[re]ax,1) */ |
static const char alt_short_11[] = |
{0x0f,0x1f,0x44,0x00,0x00, |
0x66,0x0f,0x1f,0x44,0x00,0x00}; |
/* nopw 0(%[re]ax,%[re]ax,1) |
nopw 0(%[re]ax,%[re]ax,1) */ |
static const char alt_short_12[] = |
{0x66,0x0f,0x1f,0x44,0x00,0x00, |
0x66,0x0f,0x1f,0x44,0x00,0x00}; |
/* nopw 0(%[re]ax,%[re]ax,1) |
nopl 0L(%[re]ax) */ |
static const char alt_short_13[] = |
{0x66,0x0f,0x1f,0x44,0x00,0x00, |
0x0f,0x1f,0x80,0x00,0x00,0x00,0x00}; |
/* nopl 0L(%[re]ax) |
nopl 0L(%[re]ax) */ |
static const char alt_short_14[] = |
{0x0f,0x1f,0x80,0x00,0x00,0x00,0x00, |
0x0f,0x1f,0x80,0x00,0x00,0x00,0x00}; |
/* nopl 0L(%[re]ax) |
nopl 0L(%[re]ax,%[re]ax,1) */ |
static const char alt_short_15[] = |
{0x0f,0x1f,0x80,0x00,0x00,0x00,0x00, |
0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00}; |
static const char *const alt_short_patt[] = { |
static const char *const alt_patt[] = { |
f32_1, f32_2, alt_3, alt_4, alt_5, alt_6, alt_7, alt_8, |
alt_9, alt_10, alt_short_11, alt_short_12, alt_short_13, |
alt_short_14, alt_short_15 |
alt_9, alt_10 |
}; |
static const char *const alt_long_patt[] = { |
f32_1, f32_2, alt_3, alt_4, alt_5, alt_6, alt_7, alt_8, |
alt_9, alt_10, alt_long_11, alt_long_12, alt_long_13, |
alt_long_14, alt_long_15 |
}; |
|
/* Only align for at least a positive non-zero boundary. */ |
if (count <= 0 || count > MAX_MEM_FOR_RS_ALIGN_CODE) |
1184,14 → 1158,9 |
|
1. For PROCESSOR_I386, PROCESSOR_I486, PROCESSOR_PENTIUM and |
PROCESSOR_GENERIC32, f32_patt will be used. |
2. For PROCESSOR_PENTIUMPRO, PROCESSOR_PENTIUM4, PROCESSOR_NOCONA, |
PROCESSOR_CORE, PROCESSOR_CORE2, PROCESSOR_COREI7, and |
PROCESSOR_GENERIC64, alt_long_patt will be used. |
3. For PROCESSOR_ATHLON, PROCESSOR_K6, PROCESSOR_K8 and |
PROCESSOR_AMDFAM10, PROCESSOR_BD and PROCESSOR_BT, alt_short_patt |
will be used. |
2. For the rest, alt_patt will be used. |
|
When -mtune= isn't used, alt_long_patt will be used if |
When -mtune= isn't used, alt_patt will be used if |
cpu_arch_isa_flags has CpuNop. Otherwise, f32_patt will |
be used. |
|
1224,7 → 1193,7 |
/* We use cpu_arch_isa_flags to check if we SHOULD |
optimize with nops. */ |
if (fragP->tc_frag_data.isa_flags.bitfield.cpunop) |
patt = alt_long_patt; |
patt = alt_patt; |
else |
patt = f32_patt; |
break; |
1236,20 → 1205,20 |
case PROCESSOR_L1OM: |
case PROCESSOR_K1OM: |
case PROCESSOR_GENERIC64: |
patt = alt_long_patt; |
break; |
case PROCESSOR_K6: |
case PROCESSOR_ATHLON: |
case PROCESSOR_K8: |
case PROCESSOR_AMDFAM10: |
case PROCESSOR_BD: |
case PROCESSOR_ZNVER: |
case PROCESSOR_BT: |
patt = alt_short_patt; |
patt = alt_patt; |
break; |
case PROCESSOR_I386: |
case PROCESSOR_I486: |
case PROCESSOR_PENTIUM: |
case PROCESSOR_PENTIUMPRO: |
case PROCESSOR_IAMCU: |
case PROCESSOR_GENERIC32: |
patt = f32_patt; |
break; |
1268,17 → 1237,19 |
case PROCESSOR_I386: |
case PROCESSOR_I486: |
case PROCESSOR_PENTIUM: |
case PROCESSOR_IAMCU: |
case PROCESSOR_K6: |
case PROCESSOR_ATHLON: |
case PROCESSOR_K8: |
case PROCESSOR_AMDFAM10: |
case PROCESSOR_BD: |
case PROCESSOR_ZNVER: |
case PROCESSOR_BT: |
case PROCESSOR_GENERIC32: |
/* We use cpu_arch_isa_flags to check if we CAN optimize |
with nops. */ |
if (fragP->tc_frag_data.isa_flags.bitfield.cpunop) |
patt = alt_short_patt; |
patt = alt_patt; |
else |
patt = f32_patt; |
break; |
1291,12 → 1262,12 |
case PROCESSOR_L1OM: |
case PROCESSOR_K1OM: |
if (fragP->tc_frag_data.isa_flags.bitfield.cpunop) |
patt = alt_long_patt; |
patt = alt_patt; |
else |
patt = f32_patt; |
break; |
case PROCESSOR_GENERIC64: |
patt = alt_long_patt; |
patt = alt_patt; |
break; |
} |
} |
1327,15 → 1298,15 |
} |
else |
{ |
/* Maximum length of an instruction is 15 byte. If the |
padding is greater than 15 bytes and we don't use jump, |
/* Maximum length of an instruction is 10 byte. If the |
padding is greater than 10 bytes and we don't use jump, |
we have to break it into smaller pieces. */ |
int padding = count; |
while (padding > 15) |
while (padding > 10) |
{ |
padding -= 15; |
padding -= 10; |
memcpy (fragP->fr_literal + fragP->fr_fix + padding, |
patt [14], 15); |
patt [9], 10); |
} |
|
if (padding) |
1419,23 → 1390,6 |
} |
} |
|
static INLINE void |
cpu_flags_set (union i386_cpu_flags *x, unsigned int v) |
{ |
switch (ARRAY_SIZE(x->array)) |
{ |
case 3: |
x->array[2] = v; |
case 2: |
x->array[1] = v; |
case 1: |
x->array[0] = v; |
break; |
default: |
abort (); |
} |
} |
|
static INLINE int |
cpu_flags_equal (const union i386_cpu_flags *x, |
const union i386_cpu_flags *y) |
1517,6 → 1471,20 |
return x; |
} |
|
static int |
valid_iamcu_cpu_flags (const i386_cpu_flags *flags) |
{ |
if (cpu_arch_isa == PROCESSOR_IAMCU) |
{ |
static const i386_cpu_flags iamcu_flags = CPU_IAMCU_COMPAT_FLAGS; |
i386_cpu_flags compat_flags; |
compat_flags = cpu_flags_and_not (*flags, iamcu_flags); |
return cpu_flags_all_zero (&compat_flags); |
} |
else |
return 1; |
} |
|
#define CPU_FLAGS_ARCH_MATCH 0x1 |
#define CPU_FLAGS_64BIT_MATCH 0x2 |
#define CPU_FLAGS_AES_MATCH 0x4 |
1665,8 → 1633,6 |
static const i386_operand_type imm16_32s = OPERAND_TYPE_IMM16_32S; |
static const i386_operand_type imm16_32_32s = OPERAND_TYPE_IMM16_32_32S; |
static const i386_operand_type vec_imm4 = OPERAND_TYPE_VEC_IMM4; |
static const i386_operand_type regbnd = OPERAND_TYPE_REGBND; |
static const i386_operand_type vec_disp8 = OPERAND_TYPE_VEC_DISP8; |
|
enum operand_type |
{ |
1741,6 → 1707,7 |
{ |
return (match_reg_size (t, j) |
&& !((i.types[j].bitfield.unspecified |
&& !i.broadcast |
&& !t->operand_types[j].bitfield.unspecified) |
|| (i.types[j].bitfield.fword |
&& !t->operand_types[j].bitfield.fword) |
1921,47 → 1888,46 |
} |
|
static INLINE int |
fits_in_signed_byte (offsetT num) |
fits_in_signed_byte (addressT num) |
{ |
return (num >= -128) && (num <= 127); |
return num + 0x80 <= 0xff; |
} |
|
static INLINE int |
fits_in_unsigned_byte (offsetT num) |
fits_in_unsigned_byte (addressT num) |
{ |
return (num & 0xff) == num; |
return num <= 0xff; |
} |
|
static INLINE int |
fits_in_unsigned_word (offsetT num) |
fits_in_unsigned_word (addressT num) |
{ |
return (num & 0xffff) == num; |
return num <= 0xffff; |
} |
|
static INLINE int |
fits_in_signed_word (offsetT num) |
fits_in_signed_word (addressT num) |
{ |
return (-32768 <= num) && (num <= 32767); |
return num + 0x8000 <= 0xffff; |
} |
|
static INLINE int |
fits_in_signed_long (offsetT num ATTRIBUTE_UNUSED) |
fits_in_signed_long (addressT num ATTRIBUTE_UNUSED) |
{ |
#ifndef BFD64 |
return 1; |
#else |
return (!(((offsetT) -1 << 31) & num) |
|| (((offsetT) -1 << 31) & num) == ((offsetT) -1 << 31)); |
return num + 0x80000000 <= 0xffffffff; |
#endif |
} /* fits_in_signed_long() */ |
|
static INLINE int |
fits_in_unsigned_long (offsetT num ATTRIBUTE_UNUSED) |
fits_in_unsigned_long (addressT num ATTRIBUTE_UNUSED) |
{ |
#ifndef BFD64 |
return 1; |
#else |
return (num & (((offsetT) 2 << 31) - 1)) == num; |
return num <= 0xffffffff; |
#endif |
} /* fits_in_unsigned_long() */ |
|
2228,8 → 2194,8 |
SKIP_WHITESPACE (); |
if (!is_end_of_line[(unsigned char) *input_line_pointer]) |
{ |
char *string = input_line_pointer; |
int e = get_symbol_end (); |
char *string; |
int e = get_symbol_name (&string); |
|
if (strcmp (string, "prefix") == 0) |
ask_naked_reg = 1; |
2237,7 → 2203,7 |
ask_naked_reg = -1; |
else |
as_bad (_("bad argument to syntax directive.")); |
*input_line_pointer = e; |
(void) restore_line_pointer (e); |
} |
demand_empty_rest_of_line (); |
|
2289,8 → 2255,8 |
|
if (!is_end_of_line[(unsigned char) *input_line_pointer]) |
{ |
char *string = input_line_pointer; |
int e = get_symbol_end (); |
char *string; |
int e = get_symbol_name (&string); |
|
if (strcmp (string, "none") == 0) |
*kind = check_none; |
2300,7 → 2266,7 |
*kind = check_error; |
else |
as_bad (_("bad argument to %s_check directive."), str); |
*input_line_pointer = e; |
(void) restore_line_pointer (e); |
} |
else |
as_bad (_("missing argument for %s_check directive"), str); |
2328,6 → 2294,11 |
arch = default_arch; |
} |
|
/* If we are targeting Intel MCU, we must enable it. */ |
if (get_elf_backend_data (stdoutput)->elf_machine_code != EM_IAMCU |
|| new_flag.bitfield.cpuiamcu) |
return; |
|
/* If we are targeting Intel L1OM, we must enable it. */ |
if (get_elf_backend_data (stdoutput)->elf_machine_code != EM_L1OM |
|| new_flag.bitfield.cpul1om) |
2349,8 → 2320,8 |
|
if (!is_end_of_line[(unsigned char) *input_line_pointer]) |
{ |
char *string = input_line_pointer; |
int e = get_symbol_end (); |
char *string; |
int e = get_symbol_name (&string); |
unsigned int j; |
i386_cpu_flags flags; |
|
2391,7 → 2362,11 |
else |
flags = cpu_flags_and_not (cpu_arch_flags, |
cpu_arch[j].flags); |
if (!cpu_flags_equal (&flags, &cpu_arch_flags)) |
|
if (!valid_iamcu_cpu_flags (&flags)) |
as_fatal (_("`%s' isn't valid for Intel MCU"), |
cpu_arch[j].name); |
else if (!cpu_flags_equal (&flags, &cpu_arch_flags)) |
{ |
if (cpu_sub_arch_name) |
{ |
2406,7 → 2381,7 |
cpu_arch_flags = flags; |
cpu_arch_isa_flags = flags; |
} |
*input_line_pointer = e; |
(void) restore_line_pointer (e); |
demand_empty_rest_of_line (); |
return; |
} |
2423,9 → 2398,12 |
if (*input_line_pointer == ',' |
&& !is_end_of_line[(unsigned char) input_line_pointer[1]]) |
{ |
char *string = ++input_line_pointer; |
int e = get_symbol_end (); |
char *string; |
char e; |
|
++input_line_pointer; |
e = get_symbol_name (&string); |
|
if (strcmp (string, "nojumps") == 0) |
no_cond_jump_promotion = 1; |
else if (strcmp (string, "jumps") == 0) |
2433,7 → 2411,7 |
else |
as_bad (_("no such architecture modifier: `%s'"), string); |
|
*input_line_pointer = e; |
(void) restore_line_pointer (e); |
} |
|
demand_empty_rest_of_line (); |
2456,6 → 2434,13 |
as_fatal (_("Intel K1OM is 64bit ELF only")); |
return bfd_arch_k1om; |
} |
else if (cpu_arch_isa == PROCESSOR_IAMCU) |
{ |
if (OUTPUT_FLAVOR != bfd_target_elf_flavour |
|| flag_code == CODE_64BIT) |
as_fatal (_("Intel MCU is 32bit ELF only")); |
return bfd_arch_iamcu; |
} |
else |
return bfd_arch_i386; |
} |
2484,8 → 2469,18 |
else |
return bfd_mach_x64_32; |
} |
else if (!strcmp (default_arch, "i386")) |
else if (!strcmp (default_arch, "i386") |
|| !strcmp (default_arch, "iamcu")) |
{ |
if (cpu_arch_isa == PROCESSOR_IAMCU) |
{ |
if (OUTPUT_FLAVOR != bfd_target_elf_flavour) |
as_fatal (_("Intel MCU is 32bit ELF only")); |
return bfd_mach_i386_iamcu; |
} |
else |
return bfd_mach_i386_i386; |
} |
else |
as_fatal (_("unknown architecture")); |
} |
2798,7 → 2793,6 |
reloc (unsigned int size, |
int pcrel, |
int sign, |
int bnd_prefix, |
bfd_reloc_code_real_type other) |
{ |
if (other != NO_RELOC) |
2811,6 → 2805,9 |
case BFD_RELOC_X86_64_GOT32: |
return BFD_RELOC_X86_64_GOT64; |
break; |
case BFD_RELOC_X86_64_GOTPLT64: |
return BFD_RELOC_X86_64_GOTPLT64; |
break; |
case BFD_RELOC_X86_64_PLTOFF64: |
return BFD_RELOC_X86_64_PLTOFF64; |
break; |
2834,10 → 2831,13 |
if (other == BFD_RELOC_SIZE32) |
{ |
if (size == 8) |
return BFD_RELOC_SIZE64; |
other = BFD_RELOC_SIZE64; |
if (pcrel) |
{ |
as_bad (_("there are no pc-relative size relocations")); |
return NO_RELOC; |
} |
} |
#endif |
|
/* Sign-checking 4-byte relocations in 16-/32-bit code is pointless. */ |
2871,9 → 2871,7 |
{ |
case 1: return BFD_RELOC_8_PCREL; |
case 2: return BFD_RELOC_16_PCREL; |
case 4: return (bnd_prefix && object_64bit |
? BFD_RELOC_X86_64_PC32_BND |
: BFD_RELOC_32_PCREL); |
case 4: return BFD_RELOC_32_PCREL; |
case 8: return BFD_RELOC_64_PCREL; |
} |
as_bad (_("cannot do %u byte pc-relative relocation"), size); |
2932,6 → 2930,7 |
|| fixP->fx_r_type == BFD_RELOC_386_GOTOFF |
|| fixP->fx_r_type == BFD_RELOC_386_PLT32 |
|| fixP->fx_r_type == BFD_RELOC_386_GOT32 |
|| fixP->fx_r_type == BFD_RELOC_386_GOT32X |
|| fixP->fx_r_type == BFD_RELOC_386_TLS_GD |
|| fixP->fx_r_type == BFD_RELOC_386_TLS_LDM |
|| fixP->fx_r_type == BFD_RELOC_386_TLS_LDO_32 |
2945,6 → 2944,8 |
|| 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_GOTPCRELX |
|| fixP->fx_r_type == BFD_RELOC_X86_64_REX_GOTPCRELX |
|| 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 |
3148,14 → 3149,8 |
|
/* Check the REX.W bit. */ |
w = (i.rex & REX_W) ? 1 : 0; |
if (i.tm.opcode_modifier.vexw) |
{ |
if (w) |
abort (); |
|
if (i.tm.opcode_modifier.vexw == VEXW1) |
w = 1; |
} |
|
i.vex.bytes[2] = (w << 7 |
| register_specifier << 3 |
3326,7 → 3321,7 |
if (i.rounding->type != saeonly) |
i.vex.bytes[3] |= 0x10 | (i.rounding->type << 5); |
else |
i.vex.bytes[3] |= 0x10; |
i.vex.bytes[3] |= 0x10 | (evexrcig << 5); |
} |
|
if (i.mask && i.mask->mask) |
3356,6 → 3351,34 |
i.operands = 0; |
} |
|
if (i.tm.cpu_flags.bitfield.cpumwaitx && i.operands > 0) |
{ |
/* MONITORX/MWAITX instructions have 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; |
|
if (i.operands != 3) |
abort(); |
|
for (x = 0; x < 2; x++) |
if (register_number (i.op[x].regs) != x) |
goto bad_register_operand; |
|
/* Check for third operand for mwaitx/monitorx insn. */ |
if (register_number (i.op[x].regs) |
!= (x + (i.tm.extension_opcode == 0xfb))) |
{ |
bad_register_operand: |
as_bad (_("can't use register '%s%s' as operand %d in '%s'."), |
register_prefix, i.op[x].regs->reg_name, x+1, |
i.tm.name); |
} |
|
i.operands = 0; |
} |
|
/* These AMD 3DNow! and SSE2 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 |
3611,11 → 3634,20 |
as_warn (_("translating to `%sp'"), i.tm.name); |
} |
|
if (i.tm.opcode_modifier.vex || i.tm.opcode_modifier.evex) |
{ |
if (flag_code == CODE_16BIT) |
{ |
as_bad (_("instruction `%s' isn't supported in 16-bit mode."), |
i.tm.name); |
return; |
} |
|
if (i.tm.opcode_modifier.vex) |
build_vex_prefix (t); |
|
if (i.tm.opcode_modifier.evex) |
else |
build_evex_prefix (); |
} |
|
/* Handle conversion of 'int $3' --> special int3 insn. XOP or FMA4 |
instructions may define INT_OPCODE as well, so avoid this corner |
3937,7 → 3969,7 |
/* Skip optional white space before operand. */ |
if (is_space_char (*l)) |
++l; |
if (!is_operand_char (*l) && *l != END_OF_INSN) |
if (!is_operand_char (*l) && *l != END_OF_INSN && *l != '"') |
{ |
as_bad (_("invalid character %s before operand %d"), |
output_invalid (*l), |
3944,7 → 3976,7 |
i.operands + 1); |
return NULL; |
} |
token_start = l; /* after white space */ |
token_start = l; /* After white space. */ |
paren_not_balanced = 0; |
while (paren_not_balanced || *l != ',') |
{ |
3963,7 → 3995,7 |
else |
break; /* we are done */ |
} |
else if (!is_operand_char (*l) && !is_space_char (*l)) |
else if (!is_operand_char (*l) && !is_space_char (*l) && *l != '"') |
{ |
as_bad (_("invalid character %s in operand %d"), |
output_invalid (*l), |
4374,11 → 4406,9 |
if (i.reg_operands == 2 && !i.mask) |
{ |
gas_assert (i.types[0].bitfield.regxmm |
|| i.types[0].bitfield.regymm |
|| i.types[0].bitfield.regzmm); |
|| i.types[0].bitfield.regymm); |
gas_assert (i.types[2].bitfield.regxmm |
|| i.types[2].bitfield.regymm |
|| i.types[2].bitfield.regzmm); |
|| i.types[2].bitfield.regymm); |
if (operand_check == check_none) |
return 0; |
if (register_number (i.op[0].regs) |
4395,7 → 4425,23 |
} |
as_warn (_("mask, index, and destination registers should be distinct")); |
} |
else if (i.reg_operands == 1 && i.mask) |
{ |
if ((i.types[1].bitfield.regymm |
|| i.types[1].bitfield.regzmm) |
&& (register_number (i.op[1].regs) |
== register_number (i.index_reg))) |
{ |
if (operand_check == check_error) |
{ |
i.error = invalid_vector_register_set; |
return 1; |
} |
if (operand_check != check_none) |
as_warn (_("index and destination registers should be distinct")); |
} |
} |
} |
|
/* Check if broadcast is supported by the instruction and is applied |
to the memory operand. */ |
4421,6 → 4467,10 |
broadcasted_opnd_size <<= 4; /* Broadcast 1to16. */ |
else if (i.broadcast->type == BROADCAST_1TO8) |
broadcasted_opnd_size <<= 3; /* Broadcast 1to8. */ |
else if (i.broadcast->type == BROADCAST_1TO4) |
broadcasted_opnd_size <<= 2; /* Broadcast 1to4. */ |
else if (i.broadcast->type == BROADCAST_1TO2) |
broadcasted_opnd_size <<= 1; /* Broadcast 1to2. */ |
else |
goto bad_broadcast; |
|
4672,9 → 4722,9 |
&& !operand_types[0].bitfield.regymm |
&& !operand_types[0].bitfield.regzmm) |
|| (!operand_types[t->operands > 1].bitfield.regmmx |
&& !!operand_types[t->operands > 1].bitfield.regxmm |
&& !!operand_types[t->operands > 1].bitfield.regymm |
&& !!operand_types[t->operands > 1].bitfield.regzmm)) |
&& operand_types[t->operands > 1].bitfield.regxmm |
&& operand_types[t->operands > 1].bitfield.regymm |
&& operand_types[t->operands > 1].bitfield.regzmm)) |
&& (t->base_opcode != 0x0fc7 |
|| t->extension_opcode != 1 /* cmpxchg8b */)) |
continue; |
4689,7 → 4739,7 |
&& ((!operand_types[0].bitfield.regmmx |
&& !operand_types[0].bitfield.regxmm) |
|| (!operand_types[t->operands > 1].bitfield.regmmx |
&& !!operand_types[t->operands > 1].bitfield.regxmm))) |
&& operand_types[t->operands > 1].bitfield.regxmm))) |
continue; |
|
/* Do not verify operands when there are none. */ |
4746,6 → 4796,10 |
} |
} |
|
/* Force 0x8b encoding for "mov foo@GOT, %eax". */ |
if (i.reloc[0] == BFD_RELOC_386_GOT32 && t->base_opcode == 0xa0) |
continue; |
|
/* We check register size if needed. */ |
check_register = t->opcode_modifier.checkregsize; |
overlap0 = operand_type_and (i.types[0], operand_types[0]); |
5435,16 → 5489,13 |
return 0; |
} |
#if REGISTER_WARNINGS |
else |
as_warn (_("using `%s%s' instead of `%s%s' due to `%c' suffix"), |
register_prefix, |
(i.op[op].regs + REGNAM_EAX - REGNAM_AX)->reg_name, |
register_prefix, |
i.op[op].regs->reg_name, |
i.suffix); |
register_prefix, i.op[op].regs->reg_name, i.suffix); |
#endif |
} |
/* Warn if the r prefix on a general reg is missing. */ |
/* Warn if the r prefix on a general reg is present. */ |
else if (i.types[op].bitfield.reg64 |
&& (i.tm.operand_types[op].bitfield.reg32 |
|| i.tm.operand_types[op].bitfield.acc)) |
5487,7 → 5538,7 |
i.suffix); |
return 0; |
} |
/* Warn if the e prefix on a general reg is missing. */ |
/* Warn if the r prefix on a general reg is missing. */ |
else if ((i.types[op].bitfield.reg16 |
|| i.types[op].bitfield.reg32) |
&& (i.tm.operand_types[op].bitfield.reg32 |
5532,9 → 5583,10 |
i.suffix); |
return 0; |
} |
/* Warn if the e prefix on a general reg is present. */ |
/* Warn if the e or r prefix on a general reg is present. */ |
else if ((!quiet_warnings || flag_code == CODE_64BIT) |
&& i.types[op].bitfield.reg32 |
&& (i.types[op].bitfield.reg32 |
|| i.types[op].bitfield.reg64) |
&& (i.tm.operand_types[op].bitfield.reg16 |
|| i.tm.operand_types[op].bitfield.acc)) |
{ |
5547,14 → 5599,11 |
i.suffix); |
return 0; |
} |
else |
#if REGISTER_WARNINGS |
as_warn (_("using `%s%s' instead of `%s%s' due to `%c' suffix"), |
register_prefix, |
(i.op[op].regs + REGNAM_AX - REGNAM_EAX)->reg_name, |
register_prefix, |
i.op[op].regs->reg_name, |
i.suffix); |
register_prefix, i.op[op].regs->reg_name, i.suffix); |
#endif |
} |
return 1; |
6139,8 → 6188,8 |
op = i.tm.operand_types[vvvv]; |
op.bitfield.regmem = 0; |
if ((dest + 1) >= i.operands |
|| (op.bitfield.reg32 != 1 |
&& !op.bitfield.reg64 != 1 |
|| (!op.bitfield.reg32 |
&& op.bitfield.reg64 |
&& !operand_type_equal (&op, ®xmm) |
&& !operand_type_equal (&op, ®ymm) |
&& !operand_type_equal (&op, ®zmm) |
6722,13 → 6771,7 |
|
/* 1 possible extra opcode + 4 byte displacement go in var part. |
Pass reloc in fr_var. */ |
frag_var (rs_machine_dependent, 5, |
((!object_64bit |
|| i.reloc[0] != NO_RELOC |
|| (i.bnd_prefix == NULL && !add_bnd_prefix)) |
? i.reloc[0] |
: BFD_RELOC_X86_64_PC32_BND), |
subtype, sym, off, p); |
frag_var (rs_machine_dependent, 5, i.reloc[0], subtype, sym, off, p); |
} |
|
static void |
6804,10 → 6847,7 |
} |
|
fixP = fix_new_exp (frag_now, p - frag_now->fr_literal, size, |
i.op[0].disps, 1, reloc (size, 1, 1, |
(i.bnd_prefix != NULL |
|| add_bnd_prefix), |
i.reloc[0])); |
i.op[0].disps, 1, reloc (size, 1, 1, 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 |
6873,7 → 6913,7 |
} |
else |
fix_new_exp (frag_now, p - frag_now->fr_literal, size, |
i.op[1].imms, 0, reloc (size, 0, 0, 0, i.reloc[1])); |
i.op[1].imms, 0, reloc (size, 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); |
6910,6 → 6950,15 |
unsigned int j; |
unsigned int prefix; |
|
/* Some processors fail on LOCK prefix. This options makes |
assembler ignore LOCK prefix and serves as a workaround. */ |
if (omit_lock_prefix) |
{ |
if (i.tm.base_opcode == LOCK_PREFIX_OPCODE) |
return; |
i.prefix[LOCK_PREFIX] = 0; |
} |
|
/* Since the VEX/EVEX prefix contains the implicit prefix, we |
don't need the explicit prefix. */ |
if (!i.tm.opcode_modifier.vex && !i.tm.opcode_modifier.evex) |
6945,6 → 6994,17 |
abort (); |
} |
|
#if defined (OBJ_MAYBE_ELF) || defined (OBJ_ELF) |
/* For x32, add a dummy REX_OPCODE prefix for mov/add with |
R_X86_64_GOTTPOFF relocation so that linker can safely |
perform IE->LE optimization. */ |
if (x86_elf_abi == X86_64_X32_ABI |
&& i.operands == 2 |
&& i.reloc[0] == BFD_RELOC_X86_64_GOTTPOFF |
&& i.prefix[REX_PREFIX] == 0) |
add_prefix (REX_OPCODE); |
#endif |
|
/* The prefix bytes. */ |
for (j = ARRAY_SIZE (i.prefix), q = i.prefix; j > 0; j--, q++) |
if (*q) |
7106,6 → 7166,7 |
int size = disp_size (n); |
int sign = i.types[n].bitfield.disp32s; |
int pcrel = (i.flags[n] & Operand_PCrel) != 0; |
fixS *fixP; |
|
/* We can't have 8 bit displacement here. */ |
gas_assert (!i.types[n].bitfield.disp8); |
7132,10 → 7193,7 |
} |
|
p = frag_more (size); |
reloc_type = reloc (size, pcrel, sign, |
(i.bnd_prefix != NULL |
|| add_bnd_prefix), |
i.reloc[n]); |
reloc_type = reloc (size, pcrel, sign, i.reloc[n]); |
if (GOT_symbol |
&& GOT_symbol == i.op[n].disps->X_add_symbol |
&& (((reloc_type == BFD_RELOC_32 |
7177,12 → 7235,38 |
insn, and that is taken care of in other code. */ |
reloc_type = BFD_RELOC_X86_64_GOTPC32; |
} |
fix_new_exp (frag_now, p - frag_now->fr_literal, size, |
i.op[n].disps, pcrel, reloc_type); |
fixP = fix_new_exp (frag_now, p - frag_now->fr_literal, |
size, i.op[n].disps, pcrel, |
reloc_type); |
/* Check for "call/jmp *mem", "mov mem, %reg", |
"test %reg, mem" and "binop mem, %reg" where binop |
is one of adc, add, and, cmp, or, sbb, sub, xor |
instructions. */ |
if ((i.rm.mode == 2 |
|| (i.rm.mode == 0 && i.rm.regmem == 5)) |
&& ((i.operands == 1 |
&& i.tm.base_opcode == 0xff |
&& (i.rm.reg == 2 || i.rm.reg == 4)) |
|| (i.operands == 2 |
&& (i.tm.base_opcode == 0x8b |
|| i.tm.base_opcode == 0x85 |
|| (i.tm.base_opcode & 0xc7) == 0x03)))) |
{ |
if (object_64bit) |
{ |
fixP->fx_tcbit = i.rex != 0; |
if (i.base_reg |
&& (i.base_reg->reg_num == RegRip |
|| i.base_reg->reg_num == RegEip)) |
fixP->fx_tcbit2 = 1; |
} |
else |
fixP->fx_tcbit2 = 1; |
} |
} |
} |
} |
} |
|
static void |
output_imm (fragS *insn_start_frag, offsetT insn_start_off) |
7226,7 → 7310,7 |
sign = 0; |
|
p = frag_more (size); |
reloc_type = reloc (size, 0, sign, 0, i.reloc[n]); |
reloc_type = reloc (size, 0, sign, i.reloc[n]); |
|
/* This is tough to explain. We end up with this one if we |
* have operands that look like |
7313,17 → 7397,14 |
|
/* 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 enum bfd_reloc_code_real got_reloc = NO_RELOC; |
static int cons_sign = -1; |
|
void |
x86_cons_fix_new (fragS *frag, unsigned int off, unsigned int len, |
expressionS *exp) |
expressionS *exp, bfd_reloc_code_real_type r) |
{ |
enum bfd_reloc_code_real r = reloc (len, 0, cons_sign, 0, got_reloc); |
r = reloc (len, 0, cons_sign, r); |
|
got_reloc = NO_RELOC; |
|
#ifdef TE_PE |
if (exp->X_op == O_secrel) |
{ |
7348,7 → 7429,7 |
|
#if !(defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) || defined (OBJ_MACH_O)) \ |
|| defined (LEX_AT) |
# define lex_got(reloc, adjust, types, bnd_prefix) NULL |
# define lex_got(reloc, adjust, types) NULL |
#else |
/* Parse operands of the form |
<symbol>@GOTOFF+<nnn> |
7362,8 → 7443,7 |
static char * |
lex_got (enum bfd_reloc_code_real *rel, |
int *adjust, |
i386_operand_type *types, |
int bnd_prefix) |
i386_operand_type *types) |
{ |
/* Some of the relocations depend on the size of what field is to |
be relocated. But in our callers i386_immediate and i386_displacement |
7498,8 → 7578,6 |
*adjust = len; |
memcpy (tmpbuf + first, past_reloc, second); |
tmpbuf[first + second] = '\0'; |
if (bnd_prefix && *rel == BFD_RELOC_X86_64_PLT32) |
*rel = BFD_RELOC_X86_64_PLT32_BND; |
return tmpbuf; |
} |
|
7532,8 → 7610,7 |
static char * |
lex_got (enum bfd_reloc_code_real *rel ATTRIBUTE_UNUSED, |
int *adjust ATTRIBUTE_UNUSED, |
i386_operand_type *types, |
int bnd_prefix ATTRIBUTE_UNUSED) |
i386_operand_type *types) |
{ |
static const struct |
{ |
7618,9 → 7695,11 |
|
#endif /* TE_PE */ |
|
void |
bfd_reloc_code_real_type |
x86_cons (expressionS *exp, int size) |
{ |
bfd_reloc_code_real_type got_reloc = NO_RELOC; |
|
intel_syntax = -intel_syntax; |
|
exp->X_md = 0; |
7632,7 → 7711,7 |
int adjust = 0; |
|
save = input_line_pointer; |
gotfree_input_line = lex_got (&got_reloc, &adjust, NULL, 0); |
gotfree_input_line = lex_got (&got_reloc, &adjust, NULL); |
if (gotfree_input_line) |
input_line_pointer = gotfree_input_line; |
|
7667,6 → 7746,8 |
|
if (intel_syntax) |
i386_intel_simplify (exp); |
|
return got_reloc; |
} |
|
static void |
7727,6 → 7808,10 |
op_string += 3; |
if (*op_string == '8') |
bcst_type = BROADCAST_1TO8; |
else if (*op_string == '4') |
bcst_type = BROADCAST_1TO4; |
else if (*op_string == '2') |
bcst_type = BROADCAST_1TO2; |
else if (*op_string == '1' |
&& *(op_string+1) == '6') |
{ |
7860,9 → 7945,7 |
save_input_line_pointer = input_line_pointer; |
input_line_pointer = imm_start; |
|
gotfree_input_line = lex_got (&i.reloc[this_operand], NULL, &types, |
(i.bnd_prefix != NULL |
|| add_bnd_prefix)); |
gotfree_input_line = lex_got (&i.reloc[this_operand], NULL, &types); |
if (gotfree_input_line) |
input_line_pointer = gotfree_input_line; |
|
7928,7 → 8011,7 |
return 0; |
} |
#endif |
else if (!intel_syntax && exp->X_op == O_register) |
else if (!intel_syntax && exp_seg == reg_section) |
{ |
if (imm_start) |
as_bad (_("illegal immediate register operand %s"), imm_start); |
8119,9 → 8202,7 |
*displacement_string_end = '0'; |
} |
#endif |
gotfree_input_line = lex_got (&i.reloc[this_operand], NULL, &types, |
(i.bnd_prefix != NULL |
|| add_bnd_prefix)); |
gotfree_input_line = lex_got (&i.reloc[this_operand], NULL, &types); |
if (gotfree_input_line) |
input_line_pointer = gotfree_input_line; |
|
8589,6 → 8670,7 |
} |
else if (is_digit_char (*op_string) |
|| is_identifier_char (*op_string) |
|| *op_string == '"' |
|| *op_string == '(') |
{ |
/* This is a memory reference of some sort. */ |
8803,6 → 8885,40 |
return TYPE_FROM_RELAX_STATE (frag->fr_subtype) == UNCOND_JUMP ? 4 : 5; |
} |
|
#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) |
static int |
elf_symbol_resolved_in_segment_p (symbolS *fr_symbol, offsetT fr_var) |
{ |
/* STT_GNU_IFUNC symbol must go through PLT. */ |
if ((symbol_get_bfdsym (fr_symbol)->flags |
& BSF_GNU_INDIRECT_FUNCTION) != 0) |
return 0; |
|
if (!S_IS_EXTERNAL (fr_symbol)) |
/* Symbol may be weak or local. */ |
return !S_IS_WEAK (fr_symbol); |
|
/* Global symbols with non-default visibility can't be preempted. */ |
if (ELF_ST_VISIBILITY (S_GET_OTHER (fr_symbol)) != STV_DEFAULT) |
return 1; |
|
if (fr_var != NO_RELOC) |
switch ((enum bfd_reloc_code_real) fr_var) |
{ |
case BFD_RELOC_386_PLT32: |
case BFD_RELOC_X86_64_PLT32: |
/* Symbol with PLT relocatin may be preempted. */ |
return 0; |
default: |
abort (); |
} |
|
/* Global symbols with default visibility in a shared library may be |
preempted by another definition. */ |
return !shared; |
} |
#endif |
|
/* md_estimate_size_before_relax() |
|
Called just before relax() for rs_machine_dependent frags. The x86 |
8826,10 → 8942,8 |
if (S_GET_SEGMENT (fragP->fr_symbol) != segment |
#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) |
|| (IS_ELF |
&& (S_IS_EXTERNAL (fragP->fr_symbol) |
|| S_IS_WEAK (fragP->fr_symbol) |
|| ((symbol_get_bfdsym (fragP->fr_symbol)->flags |
& BSF_GNU_INDIRECT_FUNCTION)))) |
&& !elf_symbol_resolved_in_segment_p (fragP->fr_symbol, |
fragP->fr_var)) |
#endif |
#if defined (OBJ_COFF) && defined (TE_PE) |
|| (OUTPUT_FLAVOR == bfd_target_coff_flavour |
9081,8 → 9195,7 |
&& (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_X86_64_PC32_BND) |
|| fixP->fx_r_type == BFD_RELOC_8_PCREL) |
&& !use_rela_relocations) |
{ |
/* This is a hack. There should be a better way to handle this. |
9124,8 → 9237,21 |
#endif |
} |
#if defined (OBJ_COFF) && defined (TE_PE) |
if (fixP->fx_addsy != NULL && S_IS_WEAK (fixP->fx_addsy)) |
if (fixP->fx_addsy != NULL |
&& S_IS_WEAK (fixP->fx_addsy) |
/* PR 16858: Do not modify weak function references. */ |
&& ! fixP->fx_pcrel) |
{ |
#if !defined (TE_PEP) |
/* For x86 PE weak function symbols are neither PC-relative |
nor do they set S_IS_FUNCTION. So the only reliable way |
to detect them is to check the flags of their containing |
section. */ |
if (S_GET_SEGMENT (fixP->fx_addsy) != NULL |
&& S_GET_SEGMENT (fixP->fx_addsy)->flags & SEC_CODE) |
; |
else |
#endif |
value -= S_GET_VALUE (fixP->fx_addsy); |
} |
#endif |
9138,7 → 9264,6 |
{ |
case BFD_RELOC_386_PLT32: |
case BFD_RELOC_X86_64_PLT32: |
case BFD_RELOC_X86_64_PLT32_BND: |
/* 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; |
9380,7 → 9505,7 |
symbolS *symbolP; |
|
input_line_pointer = reg_string; |
c = get_symbol_end (); |
c = get_symbol_name (®_string); |
symbolP = symbol_find (reg_string); |
if (symbolP && S_GET_SEGMENT (symbolP) == reg_section) |
{ |
9390,6 → 9515,8 |
know (e->X_add_number >= 0 |
&& (valueT) e->X_add_number < i386_regtab_size); |
r = i386_regtab + e->X_add_number; |
if ((r->reg_flags & RegVRex)) |
i.need_vrex = 1; |
*end_op = input_line_pointer; |
} |
*input_line_pointer = c; |
9483,6 → 9610,12 |
#define OPTION_MADD_BND_PREFIX (OPTION_MD_BASE + 15) |
#define OPTION_MEVEXLIG (OPTION_MD_BASE + 16) |
#define OPTION_MEVEXWIG (OPTION_MD_BASE + 17) |
#define OPTION_MBIG_OBJ (OPTION_MD_BASE + 18) |
#define OPTION_OMIT_LOCK_PREFIX (OPTION_MD_BASE + 19) |
#define OPTION_MEVEXRCIG (OPTION_MD_BASE + 20) |
#define OPTION_MSHARED (OPTION_MD_BASE + 21) |
#define OPTION_MAMD64 (OPTION_MD_BASE + 22) |
#define OPTION_MINTEL64 (OPTION_MD_BASE + 23) |
|
struct option md_longopts[] = |
{ |
9493,6 → 9626,7 |
#endif |
#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) |
{"x32", no_argument, NULL, OPTION_X32}, |
{"mshared", no_argument, NULL, OPTION_MSHARED}, |
#endif |
{"divide", no_argument, NULL, OPTION_DIVIDE}, |
{"march", required_argument, NULL, OPTION_MARCH}, |
9509,6 → 9643,13 |
{"madd-bnd-prefix", no_argument, NULL, OPTION_MADD_BND_PREFIX}, |
{"mevexlig", required_argument, NULL, OPTION_MEVEXLIG}, |
{"mevexwig", required_argument, NULL, OPTION_MEVEXWIG}, |
# if defined (TE_PE) || defined (TE_PEP) |
{"mbig-obj", no_argument, NULL, OPTION_MBIG_OBJ}, |
#endif |
{"momit-lock-prefix", required_argument, NULL, OPTION_OMIT_LOCK_PREFIX}, |
{"mevexrcig", required_argument, NULL, OPTION_MEVEXRCIG}, |
{"mamd64", no_argument, NULL, OPTION_MAMD64}, |
{"mintel64", no_argument, NULL, OPTION_MINTEL64}, |
{NULL, no_argument, NULL, 0} |
}; |
size_t md_longopts_size = sizeof (md_longopts); |
9548,6 → 9689,10 |
/* -s: On i386 Solaris, this tells the native assembler to use |
.stab instead of .stab.excl. We always use .stab anyhow. */ |
break; |
|
case OPTION_MSHARED: |
shared = 1; |
break; |
#endif |
#if (defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) \ |
|| defined (TE_PE) || defined (TE_PEP) || defined (OBJ_MACH_O)) |
9657,7 → 9802,10 |
else |
flags = cpu_flags_and_not (cpu_arch_flags, |
cpu_arch[j].flags); |
if (!cpu_flags_equal (&flags, &cpu_arch_flags)) |
|
if (!valid_iamcu_cpu_flags (&flags)) |
as_fatal (_("`%s' isn't valid for Intel MCU"), arch); |
else if (!cpu_flags_equal (&flags, &cpu_arch_flags)) |
{ |
if (cpu_sub_arch_name) |
{ |
9781,6 → 9929,19 |
as_fatal (_("invalid -mevexlig= option: `%s'"), arg); |
break; |
|
case OPTION_MEVEXRCIG: |
if (strcmp (arg, "rne") == 0) |
evexrcig = rne; |
else if (strcmp (arg, "rd") == 0) |
evexrcig = rd; |
else if (strcmp (arg, "ru") == 0) |
evexrcig = ru; |
else if (strcmp (arg, "rz") == 0) |
evexrcig = rz; |
else |
as_fatal (_("invalid -mevexrcig= option: `%s'"), arg); |
break; |
|
case OPTION_MEVEXWIG: |
if (strcmp (arg, "0") == 0) |
evexwig = evexw0; |
9790,6 → 9951,35 |
as_fatal (_("invalid -mevexwig= option: `%s'"), arg); |
break; |
|
# if defined (TE_PE) || defined (TE_PEP) |
case OPTION_MBIG_OBJ: |
use_big_obj = 1; |
break; |
#endif |
|
case OPTION_OMIT_LOCK_PREFIX: |
if (strcasecmp (arg, "yes") == 0) |
omit_lock_prefix = 1; |
else if (strcasecmp (arg, "no") == 0) |
omit_lock_prefix = 0; |
else |
as_fatal (_("invalid -momit-lock-prefix= option: `%s'"), arg); |
break; |
|
case OPTION_MAMD64: |
cpu_arch_flags.bitfield.cpuamd64 = 1; |
cpu_arch_flags.bitfield.cpuintel64 = 0; |
cpu_arch_isa_flags.bitfield.cpuamd64 = 1; |
cpu_arch_isa_flags.bitfield.cpuintel64 = 0; |
break; |
|
case OPTION_MINTEL64: |
cpu_arch_flags.bitfield.cpuamd64 = 0; |
cpu_arch_flags.bitfield.cpuintel64 = 1; |
cpu_arch_isa_flags.bitfield.cpuamd64 = 0; |
cpu_arch_isa_flags.bitfield.cpuintel64 = 1; |
break; |
|
default: |
return 0; |
} |
9931,6 → 10121,10 |
-mevexwig=[0|1] encode EVEX instructions with specific EVEX.W value\n\ |
for EVEX.W bit ignored instructions\n")); |
fprintf (stream, _("\ |
-mevexrcig=[rne|rd|ru|rz]\n\ |
encode EVEX instructions with specific EVEX.RC value\n\ |
for SAE-only ignored instructions\n")); |
fprintf (stream, _("\ |
-mmnemonic=[att|intel] use AT&T/Intel mnemonic\n")); |
fprintf (stream, _("\ |
-msyntax=[att|intel] use AT&T/Intel syntax\n")); |
9942,6 → 10136,19 |
-mold-gcc support old (<= 2.8.1) versions of gcc\n")); |
fprintf (stream, _("\ |
-madd-bnd-prefix add BND prefix for all valid branches\n")); |
fprintf (stream, _("\ |
-mshared disable branch optimization for shared code\n")); |
# if defined (TE_PE) || defined (TE_PEP) |
fprintf (stream, _("\ |
-mbig-obj generate big object files\n")); |
#endif |
fprintf (stream, _("\ |
-momit-lock-prefix=[no|yes]\n\ |
strip all lock prefixes\n")); |
fprintf (stream, _("\ |
-mamd64 accept only AMD64 ISA\n")); |
fprintf (stream, _("\ |
-mintel64 accept only Intel64 ISA\n")); |
} |
|
#if ((defined (OBJ_MAYBE_COFF) && defined (OBJ_MAYBE_AOUT)) \ |
9963,7 → 10170,28 |
} |
else if (!strcmp (default_arch, "i386")) |
update_code_flag (CODE_32BIT, 1); |
else if (!strcmp (default_arch, "iamcu")) |
{ |
update_code_flag (CODE_32BIT, 1); |
if (cpu_arch_isa == PROCESSOR_UNKNOWN) |
{ |
static const i386_cpu_flags iamcu_flags = CPU_IAMCU_FLAGS; |
cpu_arch_name = "iamcu"; |
cpu_sub_arch_name = NULL; |
cpu_arch_flags = iamcu_flags; |
cpu_arch_isa = PROCESSOR_IAMCU; |
cpu_arch_isa_flags = iamcu_flags; |
if (!cpu_arch_tune_set) |
{ |
cpu_arch_tune = cpu_arch_isa; |
cpu_arch_tune_flags = cpu_arch_isa_flags; |
} |
} |
else |
as_fatal (_("Intel MCU doesn't support `%s' architecture"), |
cpu_arch_name); |
} |
else |
as_fatal (_("unknown architecture")); |
|
if (cpu_flags_all_zero (&cpu_arch_isa_flags)) |
9980,7 → 10208,10 |
#if defined (OBJ_MAYBE_COFF) || defined (OBJ_COFF) |
# if defined (TE_PE) || defined (TE_PEP) |
case bfd_target_coff_flavour: |
return flag_code == CODE_64BIT ? "pe-x86-64" : "pe-i386"; |
if (flag_code == CODE_64BIT) |
return use_big_obj ? "pe-bigobj-x86-64" : "pe-x86-64"; |
else |
return "pe-i386"; |
# elif defined (TE_GO32) |
case bfd_target_coff_flavour: |
return "coff-go32"; |
10017,12 → 10248,18 |
as_fatal (_("Intel L1OM is 64bit only")); |
return ELF_TARGET_L1OM_FORMAT; |
} |
if (cpu_arch_isa == PROCESSOR_K1OM) |
else if (cpu_arch_isa == PROCESSOR_K1OM) |
{ |
if (x86_elf_abi != X86_64_ABI) |
as_fatal (_("Intel K1OM is 64bit only")); |
return ELF_TARGET_K1OM_FORMAT; |
} |
else if (cpu_arch_isa == PROCESSOR_IAMCU) |
{ |
if (x86_elf_abi != I386_ABI) |
as_fatal (_("Intel MCU is 32bit only")); |
return ELF_TARGET_IAMCU_FORMAT; |
} |
else |
return format; |
} |
10046,48 → 10283,6 |
|
#endif /* OBJ_MAYBE_ more than one */ |
|
#if (defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) |
void |
i386_elf_emit_arch_note (void) |
{ |
if (IS_ELF && cpu_arch_name != NULL) |
{ |
char *p; |
asection *seg = now_seg; |
subsegT subseg = now_subseg; |
Elf_Internal_Note i_note; |
Elf_External_Note e_note; |
asection *note_secp; |
int len; |
|
/* Create the .note section. */ |
note_secp = subseg_new (".note", 0); |
bfd_set_section_flags (stdoutput, |
note_secp, |
SEC_HAS_CONTENTS | SEC_READONLY); |
|
/* Process the arch string. */ |
len = strlen (cpu_arch_name); |
|
i_note.namesz = len + 1; |
i_note.descsz = 0; |
i_note.type = NT_ARCH; |
p = frag_more (sizeof (e_note.namesz)); |
md_number_to_chars (p, (valueT) i_note.namesz, sizeof (e_note.namesz)); |
p = frag_more (sizeof (e_note.descsz)); |
md_number_to_chars (p, (valueT) i_note.descsz, sizeof (e_note.descsz)); |
p = frag_more (sizeof (e_note.type)); |
md_number_to_chars (p, (valueT) i_note.type, sizeof (e_note.type)); |
p = frag_more (len + 1); |
strcpy (p, cpu_arch_name); |
|
frag_align (2, 0, 0); |
|
subseg_set (seg, subseg); |
} |
} |
#endif |
|
symbolS * |
md_undefined_symbol (char *name) |
{ |
10124,7 → 10319,7 |
int align; |
|
align = bfd_get_section_alignment (stdoutput, segment); |
size = ((size + (1 << align) - 1) & ((valueT) -1 << align)); |
size = ((size + (1 << align) - 1) & (-((valueT) 1 << align))); |
} |
#endif |
|
10162,12 → 10357,21 |
void |
i386_validate_fix (fixS *fixp) |
{ |
if (fixp->fx_subsy && fixp->fx_subsy == GOT_symbol) |
if (fixp->fx_subsy) |
{ |
if (fixp->fx_subsy == GOT_symbol) |
{ |
if (fixp->fx_r_type == BFD_RELOC_32_PCREL) |
{ |
if (!object_64bit) |
abort (); |
#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) |
if (fixp->fx_tcbit2) |
fixp->fx_r_type = (fixp->fx_tcbit |
? BFD_RELOC_X86_64_REX_GOTPCRELX |
: BFD_RELOC_X86_64_GOTPCRELX); |
else |
#endif |
fixp->fx_r_type = BFD_RELOC_X86_64_GOTPCREL; |
} |
else |
10180,6 → 10384,15 |
fixp->fx_subsy = 0; |
} |
} |
#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) |
else if (!object_64bit) |
{ |
if (fixp->fx_r_type == BFD_RELOC_386_GOT32 |
&& fixp->fx_tcbit2) |
fixp->fx_r_type = BFD_RELOC_386_GOT32X; |
} |
#endif |
} |
|
arelent * |
tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp) |
10210,11 → 10423,13 |
#endif |
|
case BFD_RELOC_X86_64_PLT32: |
case BFD_RELOC_X86_64_PLT32_BND: |
case BFD_RELOC_X86_64_GOT32: |
case BFD_RELOC_X86_64_GOTPCREL: |
case BFD_RELOC_X86_64_GOTPCRELX: |
case BFD_RELOC_X86_64_REX_GOTPCRELX: |
case BFD_RELOC_386_PLT32: |
case BFD_RELOC_386_GOT32: |
case BFD_RELOC_386_GOT32X: |
case BFD_RELOC_386_GOTOFF: |
case BFD_RELOC_386_GOTPC: |
case BFD_RELOC_386_TLS_GD: |
10271,10 → 10486,7 |
break; |
case 1: code = BFD_RELOC_8_PCREL; break; |
case 2: code = BFD_RELOC_16_PCREL; break; |
case 4: |
code = (fixp->fx_r_type == BFD_RELOC_X86_64_PC32_BND |
? fixp-> fx_r_type : BFD_RELOC_32_PCREL); |
break; |
case 4: code = BFD_RELOC_32_PCREL; break; |
#ifdef BFD64 |
case 8: code = BFD_RELOC_64_PCREL; break; |
#endif |
10367,9 → 10579,10 |
switch (code) |
{ |
case BFD_RELOC_X86_64_PLT32: |
case BFD_RELOC_X86_64_PLT32_BND: |
case BFD_RELOC_X86_64_GOT32: |
case BFD_RELOC_X86_64_GOTPCREL: |
case BFD_RELOC_X86_64_GOTPCRELX: |
case BFD_RELOC_X86_64_REX_GOTPCRELX: |
case BFD_RELOC_X86_64_TLSGD: |
case BFD_RELOC_X86_64_TLSLD: |
case BFD_RELOC_X86_64_GOTTPOFF: |