diff options
Diffstat (limited to 'binutils-2.25/gas/config/tc-i386.c')
-rw-r--r-- | binutils-2.25/gas/config/tc-i386.c | 281 |
1 files changed, 213 insertions, 68 deletions
diff --git a/binutils-2.25/gas/config/tc-i386.c b/binutils-2.25/gas/config/tc-i386.c index 32f6d48a..6f7a1ae7 100644 --- a/binutils-2.25/gas/config/tc-i386.c +++ b/binutils-2.25/gas/config/tc-i386.c @@ -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-2014 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -516,6 +513,11 @@ enum x86_elf_abi 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 + /* 1 for intel syntax, 0 if att syntax. */ static int intel_syntax = 0; @@ -541,6 +543,10 @@ static int add_bnd_prefix = 0; /* 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 +620,9 @@ static enum 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; @@ -818,6 +827,12 @@ static const arch_entry cpu_arch[] = 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, @@ -830,6 +845,10 @@ static const arch_entry cpu_arch[] = 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, @@ -904,6 +923,20 @@ static const arch_entry cpu_arch[] = 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 }, }; #ifdef I386COFF @@ -1667,8 +1700,6 @@ static const i386_operand_type imm16_32 = OPERAND_TYPE_IMM16_32; 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 { @@ -1923,47 +1954,46 @@ mode_from_disp_size (i386_operand_type t) } 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() */ @@ -2835,9 +2865,12 @@ reloc (unsigned int size, 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")); + { + as_bad (_("there are no pc-relative size relocations")); + return NO_RELOC; + } } #endif @@ -3147,14 +3180,8 @@ build_vex_prefix (const insn_template *t) /* 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; - } + if (i.tm.opcode_modifier.vexw == VEXW1) + w = 1; i.vex.bytes[2] = (w << 7 | register_specifier << 3 @@ -3325,7 +3352,7 @@ build_evex_prefix (void) 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) @@ -3610,11 +3637,20 @@ md_assemble (char *line) as_warn (_("translating to `%sp'"), i.tm.name); } - if (i.tm.opcode_modifier.vex) - build_vex_prefix (t); + 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.evex) - build_evex_prefix (); + if (i.tm.opcode_modifier.vex) + build_vex_prefix (t); + 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 @@ -4345,6 +4381,14 @@ check_VecOperands (const insn_template *t) return 1; } + /* Check if default mask is allowed. */ + if (t->opcode_modifier.nodefmask + && (!i.mask || i.mask->mask->reg_num == 0)) + { + i.error = no_default_mask; + return 1; + } + /* For VSIB byte, we need a vector register for index, and all vector registers must be distinct. */ if (t->opcode_modifier.vecsib) @@ -4365,11 +4409,9 @@ check_VecOperands (const insn_template *t) 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) @@ -4386,6 +4428,22 @@ check_VecOperands (const insn_template *t) } 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 @@ -4412,6 +4470,10 @@ check_VecOperands (const insn_template *t) 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; @@ -4462,14 +4524,6 @@ check_VecOperands (const insn_template *t) return 1; } - /* Check if default mask is allowed. */ - if (t->opcode_modifier.nodefmask - && (!i.mask || i.mask->mask->reg_num == 0)) - { - i.error = no_default_mask; - return 1; - } - /* Check RC/SAE. */ if (i.rounding) { @@ -4671,9 +4725,9 @@ match_template (void) && !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; @@ -4688,7 +4742,7 @@ match_template (void) && ((!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. */ @@ -5418,7 +5472,7 @@ check_long_reg (void) i.suffix); return 0; } - /* Warn if the e prefix on a general reg is missing. */ + /* Warn if the e prefix on a general reg is missing. */ else if ((!quiet_warnings || flag_code == CODE_64BIT) && i.types[op].bitfield.reg16 && (i.tm.operand_types[op].bitfield.reg32 @@ -5440,7 +5494,7 @@ check_long_reg (void) 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)) @@ -5483,7 +5537,7 @@ check_qword_reg (void) 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 @@ -5528,9 +5582,10 @@ check_word_reg (void) 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)) { @@ -6132,8 +6187,8 @@ build_modrm_byte (void) 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) @@ -6894,6 +6949,15 @@ output_insn (void) 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) @@ -6929,6 +6993,17 @@ check_prefix: 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) @@ -7294,16 +7369,13 @@ output_imm (fragS *insn_start_frag, offsetT insn_start_off) /* 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, got_reloc); - - got_reloc = NO_RELOC; + r = reloc (len, 0, cons_sign, r); #ifdef TE_PE if (exp->X_op == O_secrel) @@ -7510,7 +7582,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 ATTRIBUTE_UNUSED) + i386_operand_type *types) { static const struct { @@ -7595,9 +7667,11 @@ lex_got (enum bfd_reloc_code_real *rel ATTRIBUTE_UNUSED, #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; @@ -7644,6 +7718,8 @@ x86_cons (expressionS *exp, int size) if (intel_syntax) i386_intel_simplify (exp); + + return got_reloc; } static void @@ -7704,6 +7780,10 @@ check_VecOperations (char *op_string, char *op_end) 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') { @@ -7903,7 +7983,7 @@ i386_finalize_immediate (segT exp_seg ATTRIBUTE_UNUSED, expressionS *exp, 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); @@ -9096,8 +9176,21 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) #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 @@ -9361,6 +9454,8 @@ parse_register (char *reg_string, char **end_op) 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; @@ -9454,6 +9549,9 @@ const char *md_shortopts = "qn"; #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) struct option md_longopts[] = { @@ -9480,6 +9578,11 @@ struct option md_longopts[] = {"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}, {NULL, no_argument, NULL, 0} }; size_t md_longopts_size = sizeof (md_longopts); @@ -9752,6 +9855,19 @@ md_parse_option (int c, char *arg) 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; @@ -9761,6 +9877,21 @@ md_parse_option (int c, char *arg) 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; + default: return 0; } @@ -9902,6 +10033,10 @@ md_show_usage (FILE *stream) -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")); @@ -9913,6 +10048,13 @@ 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")); +# 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")); } #if ((defined (OBJ_MAYBE_COFF) && defined (OBJ_MAYBE_AOUT)) \ @@ -9951,7 +10093,10 @@ i386_target_format (void) #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"; |