diff options
Diffstat (limited to 'gas/config/tc-i386.c')
-rw-r--r-- | gas/config/tc-i386.c | 150 |
1 files changed, 94 insertions, 56 deletions
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 8fb8a7e..7f7f62b 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -648,7 +648,7 @@ static int this_operand = -1; /* Are we processing a .insn directive? */ #define dot_insn() (i.tm.mnem_off == MN__insn) -enum i386_flag_code i386_flag_code; +static enum i386_flag_code i386_flag_code; #define flag_code i386_flag_code /* Permit to continue using original name. */ static unsigned int object_64bit; static unsigned int disallow_64bit_reloc; @@ -861,7 +861,7 @@ static const char *cpu_arch_name = NULL; static char *cpu_sub_arch_name = NULL; /* CPU feature flags. */ -i386_cpu_flags cpu_arch_flags = CPU_UNKNOWN_FLAGS; +static i386_cpu_flags cpu_arch_flags = CPU_UNKNOWN_FLAGS; /* ISA extensions available in 64-bit mode only. */ static const i386_cpu_flags cpu_64_flags = CPU_ANY_64_FLAGS; @@ -870,13 +870,13 @@ static const i386_cpu_flags cpu_64_flags = CPU_ANY_64_FLAGS; static int cpu_arch_tune_set = 0; /* Cpu we are generating instructions for. */ -enum processor_type cpu_arch_tune = PROCESSOR_UNKNOWN; +static enum processor_type cpu_arch_tune = PROCESSOR_UNKNOWN; /* CPU instruction set architecture used. */ -enum processor_type cpu_arch_isa = PROCESSOR_UNKNOWN; +static enum processor_type cpu_arch_isa = PROCESSOR_UNKNOWN; /* CPU feature flags of instruction set architecture used. */ -i386_cpu_flags cpu_arch_isa_flags; +static i386_cpu_flags cpu_arch_isa_flags; /* If set, conditional jumps are not automatically promoted to handle larger than a byte offset. */ @@ -2303,8 +2303,7 @@ cpu_flags_match (const insn_template *t) || any.bitfield.cpuavx512f || any.bitfield.cpuavx512bw || any.bitfield.cpuavx512dq || any.bitfield.cpuamx_tile || any.bitfield.cpucmpccxadd || any.bitfield.cpuuser_msr - || any.bitfield.cpumsr_imm || any.bitfield.cpuamx_transpose - || any.bitfield.cpuamx_movrs)) + || any.bitfield.cpumsr_imm || any.bitfield.cpuamx_movrs)) { /* These checks (verifying that APX_F() was properly used in the opcode table entry) make sure there's no need for an "else" to @@ -3518,7 +3517,12 @@ set_cpu_arch (int dummy ATTRIBUTE_UNUSED) string = s; if (strcmp (string, "nojumps") == 0) - no_cond_jump_promotion = 1; + { + if (cpu_arch_flags.bitfield.cpui386) + as_bad (_("`%s' only supported with 16-bit architectures"), string); + else + no_cond_jump_promotion = true; + } else if (strcmp (string, "jumps") != 0) { as_bad (_("no such architecture modifier: `%s'"), string); @@ -3896,10 +3900,13 @@ pt (i386_operand_type t) #endif /* DEBUG386 */ static bfd_reloc_code_real_type -reloc (unsigned int size, - int pcrel, - int sign, - bfd_reloc_code_real_type other) +_reloc (unsigned int size, + bool pcrel, + int sign, + bfd_reloc_code_real_type other, + bool code64, + const char *file, + unsigned int line) { if (other != NO_RELOC) { @@ -3940,30 +3947,33 @@ reloc (unsigned int size, other = BFD_RELOC_SIZE64; if (pcrel) { - as_bad (_("there are no pc-relative size relocations")); + as_bad_where (file, line, + _("there are no pc-relative size relocations")); return NO_RELOC; } } #endif /* Sign-checking 4-byte relocations in 16-/32-bit code is pointless. */ - if (size == 4 && (flag_code != CODE_64BIT || disallow_64bit_reloc)) + if (size == 4 && (!code64 || disallow_64bit_reloc)) sign = -1; rel = bfd_reloc_type_lookup (stdoutput, other); if (!rel) - as_bad (_("unknown relocation (%u)"), other); + as_bad_where (file, line, _("unknown relocation (%u)"), other); else if (size != bfd_get_reloc_size (rel)) - as_bad (_("%u-byte relocation cannot be applied to %u-byte field"), - bfd_get_reloc_size (rel), - size); + as_bad_where (file, line, + _("%u-byte relocation cannot be applied to %u-byte field"), + bfd_get_reloc_size (rel), size); else if (pcrel && !rel->pc_relative) - as_bad (_("non-pc-relative relocation for pc-relative field")); + as_bad_where (file, line, + _("non-pc-relative relocation for pc-relative field")); else if ((rel->complain_on_overflow == complain_overflow_signed && !sign) || (rel->complain_on_overflow == complain_overflow_unsigned && sign > 0)) - as_bad (_("relocated field and relocation type differ in signedness")); + as_bad_where (file, line, + _("relocated field and relocation type differ in signedness")); else return other; return NO_RELOC; @@ -3972,7 +3982,8 @@ reloc (unsigned int size, if (pcrel) { if (!sign) - as_bad (_("there are no unsigned pc-relative relocations")); + as_bad_where (file, line, + _("there are no unsigned pc-relative relocations")); switch (size) { case 1: return BFD_RELOC_8_PCREL; @@ -3980,7 +3991,8 @@ reloc (unsigned int size, case 4: return BFD_RELOC_32_PCREL; case 8: return BFD_RELOC_64_PCREL; } - as_bad (_("cannot do %u byte pc-relative relocation"), size); + as_bad_where (file, line, + _("cannot do %u byte pc-relative relocation"), size); } else { @@ -3997,13 +4009,22 @@ reloc (unsigned int size, case 4: return BFD_RELOC_32; case 8: return BFD_RELOC_64; } - as_bad (_("cannot do %s %u byte relocation"), - sign > 0 ? "signed" : "unsigned", size); + as_bad_where (file, line, _("cannot do %s %u byte relocation"), + sign > 0 ? "signed" : "unsigned", size); } return NO_RELOC; } +static bfd_reloc_code_real_type +reloc (unsigned int size, + bool pcrel, + int sign, + bfd_reloc_code_real_type other) +{ + return _reloc (size, pcrel, sign, other, flag_code == CODE_64BIT, NULL, 0); +} + #ifdef OBJ_ELF /* Here we decide which fixups can be adjusted to make them relative to the beginning of the section instead of the symbol. Basically we need @@ -4179,8 +4200,7 @@ install_template (const insn_template *t) || maybe_cpu (t, CpuAVX512F) || maybe_cpu (t, CpuAVX512DQ) || maybe_cpu (t, CpuAVX512BW) || maybe_cpu (t, CpuBMI) || maybe_cpu (t, CpuBMI2) || maybe_cpu (t, CpuUSER_MSR) - || maybe_cpu (t, CpuMSR_IMM) || maybe_cpu (t, CpuAMX_TRANSPOSE) - || maybe_cpu (t, CpuAMX_MOVRS)) + || maybe_cpu (t, CpuMSR_IMM) || maybe_cpu (t, CpuAMX_MOVRS)) && maybe_cpu (t, CpuAPX_F)) { if (need_evex_encoding (t)) @@ -15652,6 +15672,23 @@ i386_att_operand (char *operand_string) return 1; /* Normal return. */ } +/* Initialize the tc_frag_data field of a fragment. */ + +void i386_frag_init (fragS *fragP, size_t max_bytes) +{ + memset (&fragP->tc_frag_data, 0, sizeof (fragP->tc_frag_data)); + fragP->tc_frag_data.isa = cpu_arch_isa; + fragP->tc_frag_data.tune = cpu_arch_tune; + fragP->tc_frag_data.cpunop = cpu_arch_flags.bitfield.cpunop; + fragP->tc_frag_data.isanop = cpu_arch_isa_flags.bitfield.cpunop; + fragP->tc_frag_data.code = i386_flag_code; + fragP->tc_frag_data.max_bytes = max_bytes; + fragP->tc_frag_data.last_insn_normal + = (seg_info(now_seg)->tc_segment_info_data.last_insn.kind + == last_insn_other); + fragP->tc_frag_data.no_cond_jump_promotion = no_cond_jump_promotion; +} + /* Calculate the maximum variable size (i.e., excluding fr_fix) that an rs_machine_dependent frag may reach. */ @@ -16139,18 +16176,15 @@ md_estimate_size_before_relax (fragS *fragP, segT segment) int old_fr_fix; fixS *fixP = NULL; - if (fragP->fr_var != NO_RELOC) - reloc_type = (enum bfd_reloc_code_real) fragP->fr_var; - else if (size == 2) - reloc_type = BFD_RELOC_16_PCREL; + reloc_type = (enum bfd_reloc_code_real) fragP->fr_var; #ifdef OBJ_ELF - else if (fragP->tc_frag_data.code == CODE_64BIT - && fragP->fr_offset == 0 - && need_plt32_p (fragP->fr_symbol)) + if (reloc_type == NO_RELOC + && size != 2 + && fragP->tc_frag_data.code == CODE_64BIT + && fragP->fr_offset == 0 + && need_plt32_p (fragP->fr_symbol)) reloc_type = BFD_RELOC_X86_64_PLT32; #endif - else - reloc_type = BFD_RELOC_32_PCREL; old_fr_fix = fragP->fr_fix; opcode = (unsigned char *) fragP->fr_opcode; @@ -16164,12 +16198,25 @@ md_estimate_size_before_relax (fragS *fragP, segT segment) fixP = fix_new (fragP, old_fr_fix, size, fragP->fr_symbol, fragP->fr_offset, 1, - reloc_type); + _reloc (size, 1, 1, reloc_type, + fragP->tc_frag_data.code == CODE_64BIT, + fragP->fr_file, fragP->fr_line)); break; case COND_JUMP86: - if (size == 2 - && (!no_cond_jump_promotion || fragP->fr_var != NO_RELOC)) + if (fragP->tc_frag_data.no_cond_jump_promotion + && fragP->fr_var == NO_RELOC) + { + fragP->fr_fix += 1; + fixP = fix_new (fragP, old_fr_fix, 1, + fragP->fr_symbol, + fragP->fr_offset, 1, + BFD_RELOC_8_PCREL); + fixP->fx_signed = 1; + break; + } + + if (size == 2) { /* Negate the condition, and branch past an unconditional jump. */ @@ -16183,23 +16230,14 @@ md_estimate_size_before_relax (fragS *fragP, segT segment) fix_new (fragP, old_fr_fix + 2, 2, fragP->fr_symbol, fragP->fr_offset, 1, - reloc_type); + _reloc (size, 1, 1, reloc_type, + fragP->tc_frag_data.code == CODE_64BIT, + fragP->fr_file, fragP->fr_line)); break; } /* Fall through. */ case COND_JUMP: - if (no_cond_jump_promotion && fragP->fr_var == NO_RELOC) - { - fragP->fr_fix += 1; - fixP = fix_new (fragP, old_fr_fix, 1, - fragP->fr_symbol, - fragP->fr_offset, 1, - BFD_RELOC_8_PCREL); - fixP->fx_signed = 1; - break; - } - /* This changes the byte-displacement jump 0x7N to the (d)word-displacement jump 0x0f,0x8N. */ opcode[1] = opcode[0] + 0x10; @@ -16209,7 +16247,9 @@ md_estimate_size_before_relax (fragS *fragP, segT segment) fixP = fix_new (fragP, old_fr_fix + 1, size, fragP->fr_symbol, fragP->fr_offset, 1, - reloc_type); + _reloc (size, 1, 1, reloc_type, + fragP->tc_frag_data.code == CODE_64BIT, + fragP->fr_file, fragP->fr_line)); break; default: @@ -16375,7 +16415,7 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, } else { - if (no_cond_jump_promotion + if (fragP->tc_frag_data.no_cond_jump_promotion && TYPE_FROM_RELAX_STATE (fragP->fr_subtype) != UNCOND_JUMP) as_warn_where (fragP->fr_file, fragP->fr_line, _("long jump required")); @@ -18669,17 +18709,15 @@ i386_solaris_fix_up_eh_frame (segT sec) /* For ELF on x86-64, add support for SHF_X86_64_LARGE. */ bfd_vma -x86_64_section_letter (int letter, const char **ptr_msg) +x86_64_section_letter (int letter, const char **extra) { if (flag_code == CODE_64BIT) { if (letter == 'l') return SHF_X86_64_LARGE; - *ptr_msg = _("bad .section directive: want a,l,w,x,M,S,G,T in string"); + *extra = "l"; } - else - *ptr_msg = _("bad .section directive: want a,w,x,M,S,G,T in string"); return -1; } |