X-Git-Url: http://drtracing.org/?a=blobdiff_plain;ds=sidebyside;f=gas%2Fconfig%2Ftc-i386.c;h=b1d3c0fb3709d132e1431c389cda3b978bbdac17;hb=1ba585e8f4ec2ed043539e57640945ff6ff3359b;hp=f4e5c5199a82cb60e0846034e5d4dd25fae6c603;hpb=c7b0bd56cec703fd6a409568946b505218defa08;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index f4e5c5199a..b1d3c0fb37 100644 --- a/gas/config/tc-i386.c +++ b/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; @@ -904,6 +906,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 (".xsavec"), PROCESSOR_UNKNOWN, + CPU_XSAVEC_FLAGS, 0, 0 }, + { STRING_COMMA_LEN (".xsaves"), PROCESSOR_UNKNOWN, + CPU_XSAVES_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 (".avx512bw"), PROCESSOR_UNKNOWN, + CPU_AVX512BW_FLAGS, 0, 0 }, + { STRING_COMMA_LEN (".avx512vl"), PROCESSOR_UNKNOWN, + CPU_AVX512VL_FLAGS, 0, 0 }, }; #ifdef I386COFF @@ -1667,8 +1683,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 { @@ -2800,6 +2814,7 @@ 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) @@ -2835,9 +2850,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 @@ -2872,7 +2890,9 @@ reloc (unsigned int size, { case 1: return BFD_RELOC_8_PCREL; case 2: return BFD_RELOC_16_PCREL; - case 4: return BFD_RELOC_32_PCREL; + case 4: return (bnd_prefix && object_64bit + ? BFD_RELOC_X86_64_PC32_BND + : BFD_RELOC_32_PCREL); case 8: return BFD_RELOC_64_PCREL; } as_bad (_("cannot do %u byte pc-relative relocation"), size); @@ -3147,14 +3167,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 @@ -4345,6 +4359,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 +4387,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 +4406,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 +4448,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 +4502,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) { @@ -5418,7 +5450,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 @@ -5434,16 +5466,13 @@ check_long_reg (void) 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); + 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); #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)) @@ -5486,7 +5515,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 @@ -5531,9 +5560,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)) { @@ -5546,14 +5576,11 @@ check_word_reg (void) 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); + 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); #endif } return 1; @@ -6721,7 +6748,13 @@ output_branch (void) /* 1 possible extra opcode + 4 byte displacement go in var part. Pass reloc in fr_var. */ - frag_var (rs_machine_dependent, 5, i.reloc[0], subtype, sym, off, p); + frag_var (rs_machine_dependent, 5, + ((!object_64bit + || i.reloc[0] != NO_RELOC + || (i.bnd_prefix == NULL && !add_bnd_prefix)) + ? i.reloc[0] + : BFD_RELOC_X86_64_PC32_BND), + subtype, sym, off, p); } static void @@ -6797,7 +6830,10 @@ output_jump (void) } fixP = fix_new_exp (frag_now, p - frag_now->fr_literal, size, - i.op[0].disps, 1, reloc (size, 1, 1, i.reloc[0])); + i.op[0].disps, 1, reloc (size, 1, 1, + (i.bnd_prefix != NULL + || add_bnd_prefix), + i.reloc[0])); /* All jumps handled here are signed, but don't use a signed limit check for 32 and 16 bit jumps as we want to allow wrap around at @@ -6863,7 +6899,7 @@ output_interseg_jump (void) } else fix_new_exp (frag_now, p - frag_now->fr_literal, size, - i.op[1].imms, 0, reloc (size, 0, 0, i.reloc[1])); + i.op[1].imms, 0, reloc (size, 0, 0, 0, i.reloc[1])); if (i.op[0].imms->X_op != O_constant) as_bad (_("can't handle non absolute segment in `%s'"), i.tm.name); @@ -7122,7 +7158,10 @@ output_disp (fragS *insn_start_frag, offsetT insn_start_off) } p = frag_more (size); - reloc_type = reloc (size, pcrel, sign, i.reloc[n]); + reloc_type = reloc (size, pcrel, sign, + (i.bnd_prefix != NULL + || add_bnd_prefix), + i.reloc[n]); if (GOT_symbol && GOT_symbol == i.op[n].disps->X_add_symbol && (((reloc_type == BFD_RELOC_32 @@ -7213,7 +7252,7 @@ output_imm (fragS *insn_start_frag, offsetT insn_start_off) sign = 0; p = frag_more (size); - reloc_type = reloc (size, 0, sign, i.reloc[n]); + reloc_type = reloc (size, 0, sign, 0, i.reloc[n]); /* This is tough to explain. We end up with this one if we * have operands that look like @@ -7300,16 +7339,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, 0, r); #ifdef TE_PE if (exp->X_op == O_secrel) @@ -7335,7 +7371,7 @@ x86_address_bytes (void) #if !(defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) || defined (OBJ_MACH_O)) \ || defined (LEX_AT) -# define lex_got(reloc, adjust, types) NULL +# define lex_got(reloc, adjust, types, bnd_prefix) NULL #else /* Parse operands of the form @GOTOFF+ @@ -7349,7 +7385,8 @@ x86_address_bytes (void) static char * lex_got (enum bfd_reloc_code_real *rel, int *adjust, - i386_operand_type *types) + i386_operand_type *types, + int bnd_prefix) { /* Some of the relocations depend on the size of what field is to be relocated. But in our callers i386_immediate and i386_displacement @@ -7484,6 +7521,8 @@ 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; } @@ -7516,7 +7555,8 @@ lex_got (enum bfd_reloc_code_real *rel, static char * lex_got (enum bfd_reloc_code_real *rel ATTRIBUTE_UNUSED, int *adjust ATTRIBUTE_UNUSED, - i386_operand_type *types ATTRIBUTE_UNUSED) + i386_operand_type *types, + int bnd_prefix ATTRIBUTE_UNUSED) { static const struct { @@ -7601,9 +7641,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; @@ -7615,7 +7657,7 @@ x86_cons (expressionS *exp, int size) int adjust = 0; save = input_line_pointer; - gotfree_input_line = lex_got (&got_reloc, &adjust, NULL); + gotfree_input_line = lex_got (&got_reloc, &adjust, NULL, 0); if (gotfree_input_line) input_line_pointer = gotfree_input_line; @@ -7650,6 +7692,8 @@ x86_cons (expressionS *exp, int size) if (intel_syntax) i386_intel_simplify (exp); + + return got_reloc; } static void @@ -7710,6 +7754,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') { @@ -7843,7 +7891,9 @@ i386_immediate (char *imm_start) save_input_line_pointer = input_line_pointer; input_line_pointer = imm_start; - gotfree_input_line = lex_got (&i.reloc[this_operand], NULL, &types); + gotfree_input_line = lex_got (&i.reloc[this_operand], NULL, &types, + (i.bnd_prefix != NULL + || add_bnd_prefix)); if (gotfree_input_line) input_line_pointer = gotfree_input_line; @@ -8100,7 +8150,9 @@ i386_displacement (char *disp_start, char *disp_end) *displacement_string_end = '0'; } #endif - gotfree_input_line = lex_got (&i.reloc[this_operand], NULL, &types); + gotfree_input_line = lex_got (&i.reloc[this_operand], NULL, &types, + (i.bnd_prefix != NULL + || add_bnd_prefix)); if (gotfree_input_line) input_line_pointer = gotfree_input_line; @@ -9060,7 +9112,8 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) && (fixP->fx_r_type == BFD_RELOC_32_PCREL || fixP->fx_r_type == BFD_RELOC_64_PCREL || fixP->fx_r_type == BFD_RELOC_16_PCREL - || fixP->fx_r_type == BFD_RELOC_8_PCREL) + || fixP->fx_r_type == BFD_RELOC_8_PCREL + || fixP->fx_r_type == BFD_RELOC_X86_64_PC32_BND) && !use_rela_relocations) { /* This is a hack. There should be a better way to handle this. @@ -9102,8 +9155,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 @@ -9116,6 +9182,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) { case BFD_RELOC_386_PLT32: case BFD_RELOC_X86_64_PLT32: + case BFD_RELOC_X86_64_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; @@ -9367,6 +9434,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; @@ -9460,6 +9529,7 @@ 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) struct option md_longopts[] = { @@ -9486,6 +9556,9 @@ 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 {NULL, no_argument, NULL, 0} }; size_t md_longopts_size = sizeof (md_longopts); @@ -9767,6 +9840,12 @@ 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 + default: return 0; } @@ -9919,6 +9998,10 @@ 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 } #if ((defined (OBJ_MAYBE_COFF) && defined (OBJ_MAYBE_AOUT)) \ @@ -9957,7 +10040,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"; @@ -10187,6 +10273,7 @@ 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: @@ -10247,7 +10334,10 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp) break; case 1: code = BFD_RELOC_8_PCREL; break; case 2: code = BFD_RELOC_16_PCREL; break; - case 4: code = BFD_RELOC_32_PCREL; break; + case 4: + code = (fixp->fx_r_type == BFD_RELOC_X86_64_PC32_BND + ? fixp-> fx_r_type : BFD_RELOC_32_PCREL); + break; #ifdef BFD64 case 8: code = BFD_RELOC_64_PCREL; break; #endif @@ -10340,6 +10430,7 @@ 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: