X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-i386.c;h=25a0fa20ad896a30efc81a9a7e7b631009d446d3;hb=add39d2344036db9334bdeb1ec20a90beaa3ca49;hp=e3bcc9a0164df764e2d8f9f2485d1ed152a676e1;hpb=9d8596f0792ad0f9d21d6af23ff0db68beb56ccd;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index e3bcc9a016..25a0fa20ad 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -1,5 +1,5 @@ /* tc-i386.c -- Assemble code for the Intel 80386 - Copyright (C) 1989-2014 Free Software Foundation, Inc. + Copyright (C) 1989-2016 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -518,6 +518,11 @@ static enum x86_elf_abi x86_elf_abi = I386_ABI; 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; @@ -547,6 +552,15 @@ static int allow_index_reg = 0; specified explicitly. */ static int omit_lock_prefix = 0; +/* 1 if the assembler should encode lfence, mfence, and sfence as + "lock addl $0, (%{re}sp)". */ +static int avoid_fence = 0; + +/* 1 if the assembler should generate relax relocations. */ + +static int generate_relax_relocations + = DEFAULT_GENERATE_X86_RELAX_RELOCATIONS; + static enum check_kind { check_none = 0, @@ -761,6 +775,8 @@ static const arch_entry cpu_arch[] = 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, @@ -783,6 +799,8 @@ static const arch_entry cpu_arch[] = 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, @@ -933,6 +951,18 @@ static const arch_entry cpu_arch[] = 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 }, + { STRING_COMMA_LEN (".rdpid"), PROCESSOR_UNKNOWN, + CPU_RDPID_FLAGS, 0, 0 }, }; #ifdef I386COFF @@ -1037,173 +1067,97 @@ i386_align_code (fragS *fragP, int count) /* Various efficient no-op patterns for aligning code labels. Note: Don't try to assemble the instructions in the comments. 0L and 0w are not legal. */ - static const char f32_1[] = + static const unsigned char f32_1[] = {0x90}; /* nop */ - static const char f32_2[] = + static const unsigned char f32_2[] = {0x66,0x90}; /* xchg %ax,%ax */ - static const char f32_3[] = + static const unsigned char f32_3[] = {0x8d,0x76,0x00}; /* leal 0(%esi),%esi */ - static const char f32_4[] = + static const unsigned char f32_4[] = {0x8d,0x74,0x26,0x00}; /* leal 0(%esi,1),%esi */ - static const char f32_5[] = + static const unsigned char f32_5[] = {0x90, /* nop */ 0x8d,0x74,0x26,0x00}; /* leal 0(%esi,1),%esi */ - static const char f32_6[] = + static const unsigned char f32_6[] = {0x8d,0xb6,0x00,0x00,0x00,0x00}; /* leal 0L(%esi),%esi */ - static const char f32_7[] = + static const unsigned char f32_7[] = {0x8d,0xb4,0x26,0x00,0x00,0x00,0x00}; /* leal 0L(%esi,1),%esi */ - static const char f32_8[] = + static const unsigned char f32_8[] = {0x90, /* nop */ 0x8d,0xb4,0x26,0x00,0x00,0x00,0x00}; /* leal 0L(%esi,1),%esi */ - static const char f32_9[] = + static const unsigned char f32_9[] = {0x89,0xf6, /* movl %esi,%esi */ 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ - static const char f32_10[] = + static const unsigned char f32_10[] = {0x8d,0x76,0x00, /* leal 0(%esi),%esi */ 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ - static const char f32_11[] = + static const unsigned char f32_11[] = {0x8d,0x74,0x26,0x00, /* leal 0(%esi,1),%esi */ 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ - static const char f32_12[] = + static const unsigned char f32_12[] = {0x8d,0xb6,0x00,0x00,0x00,0x00, /* leal 0L(%esi),%esi */ 0x8d,0xbf,0x00,0x00,0x00,0x00}; /* leal 0L(%edi),%edi */ - static const char f32_13[] = + static const unsigned char f32_13[] = {0x8d,0xb6,0x00,0x00,0x00,0x00, /* leal 0L(%esi),%esi */ 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ - static const char f32_14[] = + static const unsigned char f32_14[] = {0x8d,0xb4,0x26,0x00,0x00,0x00,0x00, /* leal 0L(%esi,1),%esi */ 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ - static const char f16_3[] = + static const unsigned char f16_3[] = {0x8d,0x74,0x00}; /* lea 0(%esi),%esi */ - static const char f16_4[] = + static const unsigned char f16_4[] = {0x8d,0xb4,0x00,0x00}; /* lea 0w(%si),%si */ - static const char f16_5[] = + static const unsigned char f16_5[] = {0x90, /* nop */ 0x8d,0xb4,0x00,0x00}; /* lea 0w(%si),%si */ - static const char f16_6[] = + static const unsigned char f16_6[] = {0x89,0xf6, /* mov %si,%si */ 0x8d,0xbd,0x00,0x00}; /* lea 0w(%di),%di */ - static const char f16_7[] = + static const unsigned char f16_7[] = {0x8d,0x74,0x00, /* lea 0(%si),%si */ 0x8d,0xbd,0x00,0x00}; /* lea 0w(%di),%di */ - static const char f16_8[] = + static const unsigned char f16_8[] = {0x8d,0xb4,0x00,0x00, /* lea 0w(%si),%si */ 0x8d,0xbd,0x00,0x00}; /* lea 0w(%di),%di */ - static const char jump_31[] = + static const unsigned char jump_31[] = {0xeb,0x1d,0x90,0x90,0x90,0x90,0x90, /* jmp .+31; lotsa nops */ 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90}; - static const char *const f32_patt[] = { + static const unsigned char *const f32_patt[] = { f32_1, f32_2, f32_3, f32_4, f32_5, f32_6, f32_7, f32_8, f32_9, f32_10, f32_11, f32_12, f32_13, f32_14 }; - static const char *const f16_patt[] = { + static const unsigned char *const f16_patt[] = { f32_1, f32_2, f16_3, f16_4, f16_5, f16_6, f16_7, f16_8 }; /* nopl (%[re]ax) */ - static const char alt_3[] = + static const unsigned char alt_3[] = {0x0f,0x1f,0x00}; /* nopl 0(%[re]ax) */ - static const char alt_4[] = + static const unsigned char alt_4[] = {0x0f,0x1f,0x40,0x00}; /* nopl 0(%[re]ax,%[re]ax,1) */ - static const char alt_5[] = + static const unsigned char alt_5[] = {0x0f,0x1f,0x44,0x00,0x00}; /* nopw 0(%[re]ax,%[re]ax,1) */ - static const char alt_6[] = + static const unsigned char alt_6[] = {0x66,0x0f,0x1f,0x44,0x00,0x00}; /* nopl 0L(%[re]ax) */ - static const char alt_7[] = + static const unsigned char alt_7[] = {0x0f,0x1f,0x80,0x00,0x00,0x00,0x00}; /* nopl 0L(%[re]ax,%[re]ax,1) */ - static const char alt_8[] = + static const unsigned char alt_8[] = {0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00}; /* nopw 0L(%[re]ax,%[re]ax,1) */ - static const char alt_9[] = + static const unsigned char alt_9[] = {0x66,0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00}; /* nopw %cs:0L(%[re]ax,%[re]ax,1) */ - static const char alt_10[] = + static const unsigned 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[] = { - 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 - }; - static const char *const alt_long_patt[] = { + static const unsigned 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_long_11, alt_long_12, alt_long_13, - alt_long_14, alt_long_15 + alt_9, alt_10 }; /* Only align for at least a positive non-zero boundary. */ @@ -1215,14 +1169,9 @@ i386_align_code (fragS *fragP, int count) 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. - - When -mtune= isn't used, alt_long_patt will be used if + 2. For the rest, alt_patt will be used. + + When -mtune= isn't used, alt_patt will be used if cpu_arch_isa_flags has CpuNop. Otherwise, f32_patt will be used. @@ -1244,7 +1193,7 @@ i386_align_code (fragS *fragP, int count) } else { - const char *const *patt = NULL; + const unsigned char *const *patt = NULL; if (fragP->tc_frag_data.isa == PROCESSOR_UNKNOWN) { @@ -1255,7 +1204,7 @@ i386_align_code (fragS *fragP, int count) /* 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; @@ -1267,20 +1216,20 @@ i386_align_code (fragS *fragP, int count) 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; @@ -1299,17 +1248,19 @@ i386_align_code (fragS *fragP, int count) 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; @@ -1322,12 +1273,12 @@ i386_align_code (fragS *fragP, int count) 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; } } @@ -1358,15 +1309,15 @@ i386_align_code (fragS *fragP, int count) } 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) @@ -1450,23 +1401,6 @@ cpu_flags_all_zero (const union i386_cpu_flags *x) } } -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) @@ -1548,6 +1482,20 @@ cpu_flags_and_not (i386_cpu_flags x, i386_cpu_flags y) 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 @@ -1770,6 +1718,7 @@ match_mem_size (const insn_template *t, unsigned int j) { 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) @@ -1933,6 +1882,9 @@ register_number (const reg_entry *r) if (r->reg_flags & RegRex) nr += 8; + if (r->reg_flags & RegVRex) + nr += 16; + return nr; } @@ -2256,8 +2208,8 @@ set_intel_syntax (int syntax_flag) 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; @@ -2265,7 +2217,7 @@ set_intel_syntax (int syntax_flag) 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 (); @@ -2317,8 +2269,8 @@ set_check (int what) 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; @@ -2328,7 +2280,7 @@ set_check (int what) *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); @@ -2356,6 +2308,11 @@ check_cpu_arch_compatible (const char *name ATTRIBUTE_UNUSED, 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) @@ -2377,8 +2334,8 @@ set_cpu_arch (int dummy ATTRIBUTE_UNUSED) 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; @@ -2419,7 +2376,11 @@ set_cpu_arch (int dummy ATTRIBUTE_UNUSED) 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) { @@ -2434,7 +2395,7 @@ set_cpu_arch (int dummy ATTRIBUTE_UNUSED) cpu_arch_flags = flags; cpu_arch_isa_flags = flags; } - *input_line_pointer = e; + (void) restore_line_pointer (e); demand_empty_rest_of_line (); return; } @@ -2451,8 +2412,11 @@ set_cpu_arch (int dummy ATTRIBUTE_UNUSED) 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; @@ -2461,7 +2425,7 @@ set_cpu_arch (int dummy ATTRIBUTE_UNUSED) else as_bad (_("no such architecture modifier: `%s'"), string); - *input_line_pointer = e; + (void) restore_line_pointer (e); } demand_empty_rest_of_line (); @@ -2484,6 +2448,13 @@ i386_arch (void) 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; } @@ -2512,8 +2483,18 @@ i386_mach (void) else return bfd_mach_x64_32; } - else if (!strcmp (default_arch, "i386")) - return bfd_mach_i386_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")); } @@ -2532,7 +2513,7 @@ md_begin (void) /* Setup for loop. */ optab = i386_optab; - core_optab = (templates *) xmalloc (sizeof (templates)); + core_optab = XNEW (templates); core_optab->start = optab; while (1) @@ -2555,7 +2536,7 @@ md_begin (void) } if (optab->name == NULL) break; - core_optab = (templates *) xmalloc (sizeof (templates)); + core_optab = XNEW (templates); core_optab->start = optab; } } @@ -2826,7 +2807,6 @@ static bfd_reloc_code_real_type reloc (unsigned int size, int pcrel, int sign, - int bnd_prefix, bfd_reloc_code_real_type other) { if (other != NO_RELOC) @@ -2905,9 +2885,7 @@ reloc (unsigned int size, { 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); @@ -2966,6 +2944,7 @@ tc_i386_fix_adjustable (fixS *fixP ATTRIBUTE_UNUSED) || 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 @@ -2979,6 +2958,8 @@ tc_i386_fix_adjustable (fixS *fixP ATTRIBUTE_UNUSED) || 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 @@ -3384,6 +3365,34 @@ process_immext (void) 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 @@ -3974,14 +3983,14 @@ parse_operands (char *l, const char *mnemonic) /* 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), 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 != ',') { @@ -4000,7 +4009,7 @@ parse_operands (char *l, const char *mnemonic) 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), @@ -4223,6 +4232,8 @@ optimize_imm (void) i.op[op].imms->X_add_number = (((i.op[op].imms->X_add_number & 0xffff) ^ 0x8000) - 0x8000); } +#ifdef BFD64 + /* Store 32-bit immediate in 64-bit for 64-bit BFD. */ if ((i.types[op].bitfield.imm32) && ((i.op[op].imms->X_add_number & ~(((offsetT) 2 << 31) - 1)) == 0)) @@ -4231,6 +4242,7 @@ optimize_imm (void) ^ ((offsetT) 1 << 31)) - ((offsetT) 1 << 31)); } +#endif i.types[op] = operand_type_or (i.types[op], smallest_imm_type (i.op[op].imms->X_add_number)); @@ -4311,6 +4323,8 @@ optimize_disp (void) op_disp = (((op_disp & 0xffff) ^ 0x8000) - 0x8000); i.types[op].bitfield.disp64 = 0; } +#ifdef BFD64 + /* Optimize 64-bit displacement to 32-bit for 64-bit BFD. */ if (i.types[op].bitfield.disp32 && (op_disp & ~(((offsetT) 2 << 31) - 1)) == 0) { @@ -4321,6 +4335,7 @@ optimize_disp (void) op_disp = (op_disp ^ ((offsetT) 1 << 31)) - ((addressT) 1 << 31); i.types[op].bitfield.disp64 = 0; } +#endif if (!op_disp && i.types[op].bitfield.baseindex) { i.types[op].bitfield.disp8 = 0; @@ -4562,7 +4577,9 @@ check_VecOperands (const insn_template *t) && i.op[op].disps->X_op == O_constant) { offsetT value = i.op[op].disps->X_add_number; - int vec_disp8_ok = fits_in_vec_disp8 (value); + int vec_disp8_ok + = (i.disp_encoding != disp_encoding_32bit + && fits_in_vec_disp8 (value)); if (t->operand_types [op].bitfield.vec_disp8) { if (vec_disp8_ok) @@ -4801,6 +4818,10 @@ match_template (void) } } + /* 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]); @@ -6772,13 +6793,7 @@ 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, - ((!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 @@ -6854,10 +6869,7 @@ 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.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 @@ -6923,7 +6935,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, 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); @@ -6960,6 +6972,22 @@ output_insn (void) unsigned int j; unsigned int prefix; + if (avoid_fence + && i.tm.base_opcode == 0xfae + && i.operands == 1 + && i.imm_operands == 1 + && (i.op[0].imms->X_add_number == 0xe8 + || i.op[0].imms->X_add_number == 0xf0 + || i.op[0].imms->X_add_number == 0xf8)) + { + /* Encode lfence, mfence, and sfence as + f0 83 04 24 00 lock addl $0x0, (%{re}sp). */ + offsetT val = 0x240483f0ULL; + p = frag_more (5); + md_number_to_chars (p, val, 5); + return; + } + /* Some processors fail on LOCK prefix. This options makes assembler ignore LOCK prefix and serves as a workaround. */ if (omit_lock_prefix) @@ -7176,6 +7204,7 @@ output_disp (fragS *insn_start_frag, offsetT insn_start_off) 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); @@ -7202,10 +7231,7 @@ output_disp (fragS *insn_start_frag, offsetT insn_start_off) } 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 @@ -7247,8 +7273,39 @@ output_disp (fragS *insn_start_frag, offsetT insn_start_off) 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. Always generate R_386_GOT32X for + "sym*GOT" operand in 32-bit mode. */ + if ((generate_relax_relocations + || (!object_64bit + && i.rm.mode == 0 + && i.rm.regmem == 5)) + && (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; + } } } } @@ -7296,7 +7353,7 @@ output_imm (fragS *insn_start_frag, offsetT insn_start_off) 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 @@ -7389,7 +7446,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, 0, r); + r = reloc (len, 0, cons_sign, r); #ifdef TE_PE if (exp->X_op == O_secrel) @@ -7415,7 +7472,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, bnd_prefix) NULL +# define lex_got(reloc, adjust, types) NULL #else /* Parse operands of the form @GOTOFF+ @@ -7429,8 +7486,7 @@ x86_address_bytes (void) 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 @@ -7551,7 +7607,7 @@ lex_got (enum bfd_reloc_code_real *rel, /* Allocate and copy string. The trailing NUL shouldn't be necessary, but be safe. */ - tmpbuf = (char *) xmalloc (first + second + 2); + tmpbuf = XNEWVEC (char, first + second + 2); memcpy (tmpbuf, input_line_pointer, first); if (second != 0 && *past_reloc != ' ') /* Replace the relocation token with ' ', so that @@ -7565,8 +7621,6 @@ lex_got (enum bfd_reloc_code_real *rel, *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; } @@ -7599,8 +7653,7 @@ 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, - int bnd_prefix ATTRIBUTE_UNUSED) + i386_operand_type *types) { static const struct { @@ -7662,7 +7715,7 @@ lex_got (enum bfd_reloc_code_real *rel ATTRIBUTE_UNUSED, /* Allocate and copy string. The trailing NUL shouldn't be necessary, but be safe. */ - tmpbuf = (char *) xmalloc (first + second + 2); + tmpbuf = XNEWVEC (char, first + second + 2); memcpy (tmpbuf, input_line_pointer, first); if (second != 0 && *past_reloc != ' ') /* Replace the relocation token with ' ', so that @@ -7701,7 +7754,7 @@ x86_cons (expressionS *exp, int size) 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; @@ -7935,9 +7988,7 @@ 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, - (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; @@ -8194,9 +8245,7 @@ i386_displacement (char *disp_start, char *disp_end) *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; @@ -8664,6 +8713,7 @@ i386_att_operand (char *operand_string) } else if (is_digit_char (*op_string) || is_identifier_char (*op_string) + || *op_string == '"' || *op_string == '(') { /* This is a memory reference of some sort. */ @@ -8878,6 +8928,40 @@ i386_frag_max_var (fragS *frag) 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 @@ -8901,10 +8985,8 @@ md_estimate_size_before_relax (fragS *fragP, segT segment) 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 @@ -9156,8 +9238,7 @@ 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_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. @@ -9226,7 +9307,6 @@ 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_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; @@ -9302,7 +9382,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) md_number_to_chars (p, value, fixP->fx_size); } -char * +const char * md_atof (int type, char *litP, int *sizeP) { /* This outputs the LITTLENUMs in REVERSE order; @@ -9468,7 +9548,7 @@ parse_register (char *reg_string, char **end_op) 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) { @@ -9574,8 +9654,13 @@ const char *md_shortopts = "qn"; #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_MOMIT_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) +#define OPTION_MFENCE_AS_LOCK_ADD (OPTION_MD_BASE + 24) +#define OPTION_MRELAX_RELOCATIONS (OPTION_MD_BASE + 25) struct option md_longopts[] = { @@ -9586,6 +9671,7 @@ struct option md_longopts[] = #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}, @@ -9605,14 +9691,18 @@ struct option md_longopts[] = # 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}, + {"momit-lock-prefix", required_argument, NULL, OPTION_MOMIT_LOCK_PREFIX}, + {"mfence-as-lock-add", required_argument, NULL, OPTION_MFENCE_AS_LOCK_ADD}, + {"mrelax-relocations", required_argument, NULL, OPTION_MRELAX_RELOCATIONS}, {"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); int -md_parse_option (int c, char *arg) +md_parse_option (int c, const char *arg) { unsigned int j; char *arch, *next; @@ -9646,6 +9736,10 @@ md_parse_option (int c, char *arg) /* -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)) @@ -9703,7 +9797,7 @@ md_parse_option (int c, char *arg) char *n, *t; const char *s; - n = (char *) xmalloc (strlen (i386_comment_chars) + 1); + n = XNEWVEC (char, strlen (i386_comment_chars) + 1); t = n; for (s = i386_comment_chars; *s != '\0'; s++) if (*s != '/') @@ -9755,7 +9849,10 @@ md_parse_option (int c, char *arg) 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) { @@ -9907,7 +10004,7 @@ md_parse_option (int c, char *arg) break; #endif - case OPTION_OMIT_LOCK_PREFIX: + case OPTION_MOMIT_LOCK_PREFIX: if (strcasecmp (arg, "yes") == 0) omit_lock_prefix = 1; else if (strcasecmp (arg, "no") == 0) @@ -9916,6 +10013,38 @@ md_parse_option (int c, char *arg) as_fatal (_("invalid -momit-lock-prefix= option: `%s'"), arg); break; + case OPTION_MFENCE_AS_LOCK_ADD: + if (strcasecmp (arg, "yes") == 0) + avoid_fence = 1; + else if (strcasecmp (arg, "no") == 0) + avoid_fence = 0; + else + as_fatal (_("invalid -mfence-as-lock-add= option: `%s'"), arg); + break; + + case OPTION_MRELAX_RELOCATIONS: + if (strcasecmp (arg, "yes") == 0) + generate_relax_relocations = 1; + else if (strcasecmp (arg, "no") == 0) + generate_relax_relocations = 0; + else + as_fatal (_("invalid -mrelax-relocations= 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; } @@ -10072,6 +10201,8 @@ md_show_usage (FILE *stream) -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")); @@ -10079,6 +10210,17 @@ md_show_usage (FILE *stream) fprintf (stream, _("\ -momit-lock-prefix=[no|yes]\n\ strip all lock prefixes\n")); + fprintf (stream, _("\ + -mfence-as-lock-add=[no|yes]\n\ + encode lfence, mfence and sfence as\n\ + lock addl $0x0, (%%{re}sp)\n")); + fprintf (stream, _("\ + -mrelax-relocations=[no|yes]\n\ + generate relax relocations\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)) \ @@ -10100,6 +10242,27 @@ i386_target_format (void) } 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")); @@ -10157,12 +10320,18 @@ i386_target_format (void) 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; } @@ -10185,48 +10354,6 @@ i386_target_format (void) } #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) @@ -10264,7 +10391,7 @@ md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size) 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 @@ -10302,23 +10429,41 @@ s_bss (int ignore ATTRIBUTE_UNUSED) void i386_validate_fix (fixS *fixp) { - if (fixp->fx_subsy && fixp->fx_subsy == GOT_symbol) + if (fixp->fx_subsy) { - if (fixp->fx_r_type == BFD_RELOC_32_PCREL) + if (fixp->fx_subsy == GOT_symbol) { - if (!object_64bit) - abort (); - fixp->fx_r_type = BFD_RELOC_X86_64_GOTPCREL; - } - else - { - if (!object_64bit) - fixp->fx_r_type = BFD_RELOC_386_GOTOFF; + 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 - fixp->fx_r_type = BFD_RELOC_X86_64_GOTOFF64; + { + if (!object_64bit) + fixp->fx_r_type = BFD_RELOC_386_GOTOFF; + else + fixp->fx_r_type = BFD_RELOC_X86_64_GOTOFF64; + } + fixp->fx_subsy = 0; } - 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 * @@ -10350,11 +10495,13 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp) #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: @@ -10411,10 +10558,7 @@ 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 = (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 @@ -10459,8 +10603,8 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp) code = BFD_RELOC_X86_64_GOTPC64; } - rel = (arelent *) xmalloc (sizeof (arelent)); - rel->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); + rel = XNEW (arelent); + rel->sym_ptr_ptr = XNEW (asymbol *); *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); rel->address = fixp->fx_frag->fr_address + fixp->fx_where; @@ -10507,9 +10651,10 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp) 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: @@ -10640,7 +10785,7 @@ tc_pe_dwarf2_emit_offset (symbolS *symbol, unsigned int size) /* For ELF on x86-64, add support for SHF_X86_64_LARGE. */ bfd_vma -x86_64_section_letter (int letter, char **ptr_msg) +x86_64_section_letter (int letter, const char **ptr_msg) { if (flag_code == CODE_64BIT) {