X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-i386.c;h=b5c27ee859cf37861538e72af2dcad95f5f66b76;hb=e12fe5554c3b70139f68e33ded9e2a8075b9d484;hp=1f9b3463e53f8671180fae7a25cc9ba0cf74d1da;hpb=1dfc6506b7482baf86dbb3c91de5bd2ae3f5acda;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 1f9b3463e5..b5c27ee859 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-2015 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; @@ -761,6 +766,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 +790,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, @@ -929,6 +938,18 @@ static const arch_entry cpu_arch[] = 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 }, }; #ifdef I386COFF @@ -1121,85 +1142,9 @@ i386_align_code (fragS *fragP, int count) /* 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 - }; - 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 + alt_9, alt_10 }; /* Only align for at least a positive non-zero boundary. */ @@ -1211,14 +1156,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. @@ -1251,7 +1191,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; @@ -1263,20 +1203,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; @@ -1295,17 +1235,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; @@ -1318,12 +1260,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; } } @@ -1354,15 +1296,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) @@ -1446,23 +1388,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) @@ -1544,6 +1469,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 @@ -1766,6 +1705,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) @@ -2252,8 +2192,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; @@ -2261,7 +2201,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 (); @@ -2313,8 +2253,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; @@ -2324,7 +2264,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); @@ -2352,6 +2292,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) @@ -2373,8 +2318,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; @@ -2415,7 +2360,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) { @@ -2430,7 +2379,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; } @@ -2447,8 +2396,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; @@ -2457,7 +2409,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 (); @@ -2480,6 +2432,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; } @@ -2508,8 +2467,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")); } @@ -2822,7 +2791,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) @@ -2901,9 +2869,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); @@ -3380,6 +3346,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 @@ -3970,14 +3964,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 != ',') { @@ -3996,7 +3990,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), @@ -6768,13 +6762,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 @@ -6850,10 +6838,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 @@ -6919,7 +6904,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); @@ -7198,10 +7183,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 @@ -7292,7 +7274,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 @@ -7385,7 +7367,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) @@ -7411,7 +7393,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+ @@ -7425,8 +7407,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 @@ -7561,8 +7542,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; } @@ -7595,8 +7574,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 { @@ -7697,7 +7675,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; @@ -7931,9 +7909,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; @@ -8190,9 +8166,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; @@ -8660,6 +8634,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. */ @@ -8874,6 +8849,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 @@ -8897,10 +8906,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 @@ -9152,8 +9159,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. @@ -9222,7 +9228,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; @@ -9464,7 +9469,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) { @@ -9572,6 +9577,9 @@ const char *md_shortopts = "qn"; #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[] = { @@ -9582,6 +9590,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}, @@ -9603,6 +9612,8 @@ struct option md_longopts[] = #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); @@ -9642,6 +9653,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)) @@ -9751,7 +9766,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) { @@ -9912,6 +9930,20 @@ md_parse_option (int c, char *arg) 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; } @@ -10068,6 +10100,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")); @@ -10075,6 +10109,10 @@ md_show_usage (FILE *stream) 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)) \ @@ -10096,6 +10134,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")); @@ -10153,12 +10212,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; } @@ -10181,48 +10246,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) @@ -10346,7 +10369,6 @@ 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_386_PLT32: @@ -10407,10 +10429,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 @@ -10503,7 +10522,6 @@ 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_TLSGD: