X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-i386.c;h=2c087e42e0de4486ce1b89d6c2d1b1d36ded1a9e;hb=72aea32839b5f4a2c8fa67e60451169b841941c0;hp=1f2b298369b09cb1d7617b8fe126804e5d65ba80;hpb=21df382b918888de64749e977f185c4e10a5b838;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 1f2b298369..2c087e42e0 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-2019 Free Software Foundation, Inc. + Copyright (C) 1989-2020 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -182,6 +182,7 @@ static char *parse_insn (char *, char *); static char *parse_operands (char *, const char *); static void swap_operands (void); static void swap_2_operands (int, int); +static enum flag_code i386_addressing_mode (void); static void optimize_imm (void); static void optimize_disp (void); static const insn_template *match_template (char); @@ -353,6 +354,9 @@ struct _i386_insn unsigned int prefixes; unsigned char prefix[MAX_PREFIXES]; + /* The operand to a branch insn indicates an absolute branch. */ + bfd_boolean jumpabsolute; + /* Has MMX register operands. */ bfd_boolean has_regmmx; @@ -365,6 +369,9 @@ struct _i386_insn /* Has ZMM register operands. */ bfd_boolean has_regzmm; + /* Has GOTPC or TLS relocation. */ + bfd_boolean has_gotpc_tls_reloc; + /* RM and SIB are the modrm byte and the sib byte where the addressing modes of this insn are encoded. */ modrm_byte rm; @@ -559,6 +566,8 @@ static enum flag_code flag_code; static unsigned int object_64bit; static unsigned int disallow_64bit_reloc; static int use_rela_relocations = 0; +/* __tls_get_addr/___tls_get_addr symbol for TLS. */ +static const char *tls_get_addr; #if ((defined (OBJ_MAYBE_COFF) && defined (OBJ_MAYBE_AOUT)) \ || defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) \ @@ -619,6 +628,21 @@ static int omit_lock_prefix = 0; "lock addl $0, (%{re}sp)". */ static int avoid_fence = 0; +/* Type of the previous instruction. */ +static struct + { + segT seg; + const char *file; + const char *name; + unsigned int line; + enum last_insn_kind + { + last_insn_other = 0, + last_insn_directive, + last_insn_prefix + } kind; + } last_insn; + /* 1 if the assembler should generate relax relocations. */ static int generate_relax_relocations @@ -632,6 +656,44 @@ static enum check_kind } sse_check, operand_check = check_warning; +/* Non-zero if branches should be aligned within power of 2 boundary. */ +static int align_branch_power = 0; + +/* Types of branches to align. */ +enum align_branch_kind + { + align_branch_none = 0, + align_branch_jcc = 1, + align_branch_fused = 2, + align_branch_jmp = 3, + align_branch_call = 4, + align_branch_indirect = 5, + align_branch_ret = 6 + }; + +/* Type bits of branches to align. */ +enum align_branch_bit + { + align_branch_jcc_bit = 1 << align_branch_jcc, + align_branch_fused_bit = 1 << align_branch_fused, + align_branch_jmp_bit = 1 << align_branch_jmp, + align_branch_call_bit = 1 << align_branch_call, + align_branch_indirect_bit = 1 << align_branch_indirect, + align_branch_ret_bit = 1 << align_branch_ret + }; + +static unsigned int align_branch = (align_branch_jcc_bit + | align_branch_fused_bit + | align_branch_jmp_bit); + +/* The maximum padding size for fused jcc. CMP like instruction can + be 9 bytes and jcc can be 6 bytes. Leave room just in case for + prefixes. */ +#define MAX_FUSED_JCC_PADDING_SIZE 20 + +/* The maximum number of prefixes added for an instruction. */ +static unsigned int align_branch_prefix_size = 5; + /* Optimization: 1. Clear the REX_W bit with register operand if possible. 2. Above plus use 128bit vector instruction to clear the full vector @@ -735,12 +797,19 @@ int x86_cie_data_alignment; /* Interface to relax_segment. There are 3 major relax states for 386 jump insns because the different types of jumps add different sizes to frags when we're - figuring out what sort of jump to choose to reach a given label. */ + figuring out what sort of jump to choose to reach a given label. + + BRANCH_PADDING, BRANCH_PREFIX and FUSED_JCC_PADDING are used to align + branches which are handled by md_estimate_size_before_relax() and + i386_generic_table_relax_frag(). */ /* Types. */ #define UNCOND_JUMP 0 #define COND_JUMP 1 #define COND_JUMP86 2 +#define BRANCH_PADDING 3 +#define BRANCH_PREFIX 4 +#define FUSED_JCC_PADDING 5 /* Sizes. */ #define CODE16 1 @@ -1089,6 +1158,10 @@ static const arch_entry cpu_arch[] = CPU_AVX512_VP2INTERSECT_FLAGS, 0 }, { STRING_COMMA_LEN (".enqcmd"), PROCESSOR_UNKNOWN, CPU_ENQCMD_FLAGS, 0 }, + { STRING_COMMA_LEN (".rdpru"), PROCESSOR_UNKNOWN, + CPU_RDPRU_FLAGS, 0 }, + { STRING_COMMA_LEN (".mcommit"), PROCESSOR_UNKNOWN, + CPU_MCOMMIT_FLAGS, 0 }, }; static const noarch_entry cpu_noarch[] = @@ -1377,6 +1450,12 @@ i386_generate_nops (fragS *fragP, char *where, offsetT count, int limit) case rs_fill_nop: case rs_align_code: break; + case rs_machine_dependent: + /* Allow NOP padding for jumps and calls. */ + if (TYPE_FROM_RELAX_STATE (fragP->fr_subtype) == BRANCH_PADDING + || TYPE_FROM_RELAX_STATE (fragP->fr_subtype) == FUSED_JCC_PADDING) + break; + /* Fall through. */ default: return; } @@ -1521,7 +1600,7 @@ i386_generate_nops (fragS *fragP, char *where, offsetT count, int limit) return; } } - else + else if (fragP->fr_type != rs_machine_dependent) fragP->fr_var = count; if ((count / max_single_nop_size) > max_number_of_nops) @@ -1607,6 +1686,9 @@ operand_type_set (union i386_operand_type *x, unsigned int v) default: abort (); } + + x->bitfield.class = ClassNone; + x->bitfield.instance = InstanceNone; } static INLINE int @@ -1821,6 +1903,11 @@ cpu_flags_match (const insn_template *t) static INLINE i386_operand_type operand_type_and (i386_operand_type x, i386_operand_type y) { + if (x.bitfield.class != y.bitfield.class) + x.bitfield.class = ClassNone; + if (x.bitfield.instance != y.bitfield.instance) + x.bitfield.instance = InstanceNone; + switch (ARRAY_SIZE (x.array)) { case 3: @@ -1841,6 +1928,9 @@ operand_type_and (i386_operand_type x, i386_operand_type y) static INLINE i386_operand_type operand_type_and_not (i386_operand_type x, i386_operand_type y) { + gas_assert (y.bitfield.class == ClassNone); + gas_assert (y.bitfield.instance == InstanceNone); + switch (ARRAY_SIZE (x.array)) { case 3: @@ -1861,6 +1951,13 @@ operand_type_and_not (i386_operand_type x, i386_operand_type y) static INLINE i386_operand_type operand_type_or (i386_operand_type x, i386_operand_type y) { + gas_assert (x.bitfield.class == ClassNone || + y.bitfield.class == ClassNone || + x.bitfield.class == y.bitfield.class); + gas_assert (x.bitfield.instance == InstanceNone || + y.bitfield.instance == InstanceNone || + x.bitfield.instance == y.bitfield.instance); + switch (ARRAY_SIZE (x.array)) { case 3: @@ -1881,6 +1978,9 @@ operand_type_or (i386_operand_type x, i386_operand_type y) static INLINE i386_operand_type operand_type_xor (i386_operand_type x, i386_operand_type y) { + gas_assert (y.bitfield.class == ClassNone); + gas_assert (y.bitfield.instance == InstanceNone); + switch (ARRAY_SIZE (x.array)) { case 3: @@ -1902,8 +2002,8 @@ static const i386_operand_type disp16 = OPERAND_TYPE_DISP16; static const i386_operand_type disp32 = OPERAND_TYPE_DISP32; static const i386_operand_type disp32s = OPERAND_TYPE_DISP32S; static const i386_operand_type disp16_32 = OPERAND_TYPE_DISP16_32; -static const i386_operand_type anydisp - = OPERAND_TYPE_ANYDISP; +static const i386_operand_type anydisp = OPERAND_TYPE_ANYDISP; +static const i386_operand_type anyimm = OPERAND_TYPE_ANYIMM; static const i386_operand_type regxmm = OPERAND_TYPE_REGXMM; static const i386_operand_type regmask = OPERAND_TYPE_REGMASK; static const i386_operand_type imm8 = OPERAND_TYPE_IMM8; @@ -1930,7 +2030,7 @@ operand_type_check (i386_operand_type t, enum operand_type c) switch (c) { case reg: - return t.bitfield.reg; + return t.bitfield.class == Reg; case imm: return (t.bitfield.imm8 @@ -2013,7 +2113,7 @@ match_mem_size (const insn_template *t, unsigned int wanted, operands at the same time, some special casing is needed here. Also for v{,p}broadcast*, {,v}pmov{s,z}*, and down-conversion vpmov*. */ - || ((t->operand_types[wanted].bitfield.regsimd + || ((t->operand_types[wanted].bitfield.class == RegSIMD && !t->opcode_modifier.broadcast && (t->operand_types[wanted].bitfield.byte || t->operand_types[wanted].bitfield.word @@ -2038,35 +2138,34 @@ operand_size_match (const insn_template *t) { unsigned int j, match = MATCH_STRAIGHT; - /* Don't check jump instructions. */ + /* Don't check non-absolute jump instructions. */ if (t->opcode_modifier.jump - || t->opcode_modifier.jumpbyte - || t->opcode_modifier.jumpdword - || t->opcode_modifier.jumpintersegment) + && t->opcode_modifier.jump != JUMP_ABSOLUTE) return match; /* Check memory and accumulator operand size. */ for (j = 0; j < i.operands; j++) { - if (!i.types[j].bitfield.reg && !i.types[j].bitfield.regsimd - && t->operand_types[j].bitfield.anysize) + if (i.types[j].bitfield.class != Reg + && i.types[j].bitfield.class != RegSIMD + && t->opcode_modifier.anysize) continue; - if (t->operand_types[j].bitfield.reg + if (t->operand_types[j].bitfield.class == Reg && !match_operand_size (t, j, j)) { match = 0; break; } - if (t->operand_types[j].bitfield.regsimd + if (t->operand_types[j].bitfield.class == RegSIMD && !match_simd_size (t, j, j)) { match = 0; break; } - if (t->operand_types[j].bitfield.acc + if (t->operand_types[j].bitfield.instance == Accum && (!match_operand_size (t, j, j) || !match_simd_size (t, j, j))) { match = 0; @@ -2095,15 +2194,15 @@ mismatch: { unsigned int given = i.operands - j - 1; - if (t->operand_types[j].bitfield.reg + if (t->operand_types[j].bitfield.class == Reg && !match_operand_size (t, j, given)) goto mismatch; - if (t->operand_types[j].bitfield.regsimd + if (t->operand_types[j].bitfield.class == RegSIMD && !match_simd_size (t, j, given)) goto mismatch; - if (t->operand_types[j].bitfield.acc + if (t->operand_types[j].bitfield.instance == Accum && (!match_operand_size (t, j, given) || !match_simd_size (t, j, given))) goto mismatch; @@ -2121,7 +2220,6 @@ operand_type_match (i386_operand_type overlap, { i386_operand_type temp = overlap; - temp.bitfield.jumpabsolute = 0; temp.bitfield.unspecified = 0; temp.bitfield.byte = 0; temp.bitfield.word = 0; @@ -2135,8 +2233,7 @@ operand_type_match (i386_operand_type overlap, if (operand_type_all_zero (&temp)) goto mismatch; - if (given.bitfield.baseindex == overlap.bitfield.baseindex - && given.bitfield.jumpabsolute == overlap.bitfield.jumpabsolute) + if (given.bitfield.baseindex == overlap.bitfield.baseindex) return 1; mismatch: @@ -2155,18 +2252,18 @@ operand_type_register_match (i386_operand_type g0, i386_operand_type g1, i386_operand_type t1) { - if (!g0.bitfield.reg - && !g0.bitfield.regsimd + if (g0.bitfield.class != Reg + && g0.bitfield.class != RegSIMD && (!operand_type_check (g0, anymem) || g0.bitfield.unspecified - || !t0.bitfield.regsimd)) + || t0.bitfield.class != RegSIMD)) return 1; - if (!g1.bitfield.reg - && !g1.bitfield.regsimd + if (g1.bitfield.class != Reg + && g1.bitfield.class != RegSIMD && (!operand_type_check (g1, anymem) || g1.bitfield.unspecified - || !t1.bitfield.regsimd)) + || t1.bitfield.class != RegSIMD)) return 1; if (g0.bitfield.byte == g1.bitfield.byte @@ -2986,6 +3083,11 @@ md_begin (void) x86_dwarf2_return_column = 8; x86_cie_data_alignment = -4; } + + /* NB: FUSED_JCC_PADDING frag must have sufficient room so that it + can be turned into BRANCH_PREFIX frag. */ + if (align_branch_prefix_size > MAX_FUSED_JCC_PADDING_SIZE) + abort (); } void @@ -3028,13 +3130,13 @@ pi (const char *line, i386_insn *x) fprintf (stdout, " #%d: ", j + 1); pt (x->types[j]); fprintf (stdout, "\n"); - if (x->types[j].bitfield.reg - || x->types[j].bitfield.regmmx - || x->types[j].bitfield.regsimd - || x->types[j].bitfield.sreg - || x->types[j].bitfield.control - || x->types[j].bitfield.debug - || x->types[j].bitfield.test) + if (x->types[j].bitfield.class == Reg + || x->types[j].bitfield.class == RegMMX + || x->types[j].bitfield.class == RegSIMD + || x->types[j].bitfield.class == SReg + || x->types[j].bitfield.class == RegCR + || x->types[j].bitfield.class == RegDR + || x->types[j].bitfield.class == RegTR) fprintf (stdout, "%s\n", x->op[j].regs->reg_name); if (operand_type_check (x->types[j], imm)) pe (x->op[j].imms); @@ -3129,13 +3231,11 @@ const type_names[] = { OPERAND_TYPE_FLOATREG, "FReg" }, { OPERAND_TYPE_FLOATACC, "FAcc" }, { OPERAND_TYPE_SREG, "SReg" }, - { OPERAND_TYPE_JUMPABSOLUTE, "Jump Absolute" }, { OPERAND_TYPE_REGMMX, "rMMX" }, { OPERAND_TYPE_REGXMM, "rXMM" }, { OPERAND_TYPE_REGYMM, "rYMM" }, { OPERAND_TYPE_REGZMM, "rZMM" }, { OPERAND_TYPE_REGMASK, "Mask reg" }, - { OPERAND_TYPE_ESSEG, "es" }, }; static void @@ -3824,52 +3924,6 @@ process_immext (void) { expressionS *exp; - if ((i.tm.cpu_flags.bitfield.cpusse3 || i.tm.cpu_flags.bitfield.cpusvme) - && i.operands > 0) - { - /* MONITOR/MWAIT as well as SVME 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; - - for (x = 0; x < i.operands; x++) - if (register_number (i.op[x].regs) != x) - 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; - } - - 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 @@ -3918,8 +3972,7 @@ check_hle (void) i.tm.name); return 0; } - if (i.mem_operands == 0 - || !operand_type_check (i.types[i.operands - 1], anymem)) + if (i.mem_operands == 0 || !(i.flags[i.operands - 1] & Operand_Mem)) { as_bad (_("memory destination needed for instruction `%s'" " after `xrelease'"), i.tm.name); @@ -3937,13 +3990,13 @@ optimize_encoding (void) unsigned int j; if (optimize_for_space + && !is_any_vex_encoding (&i.tm) && i.reg_operands == 1 && i.imm_operands == 1 && !i.types[1].bitfield.byte && i.op[0].imms->X_op == O_constant && fits_in_imm7 (i.op[0].imms->X_add_number) - && ((i.tm.base_opcode == 0xa8 - && i.tm.extension_opcode == None) + && (i.tm.base_opcode == 0xa8 || (i.tm.base_opcode == 0xf6 && i.tm.extension_opcode == 0x0))) { @@ -3956,36 +4009,34 @@ optimize_encoding (void) i.types[1].bitfield.byte = 1; /* Ignore the suffix. */ i.suffix = 0; - if (base_regnum >= 4 - && !(i.op[1].regs->reg_flags & RegRex)) - { - /* Handle SP, BP, SI and DI registers. */ - if (i.types[1].bitfield.word) - j = 16; - else if (i.types[1].bitfield.dword) - j = 32; - else - j = 48; - i.op[1].regs -= j; - } + /* Convert to byte registers. */ + if (i.types[1].bitfield.word) + j = 16; + else if (i.types[1].bitfield.dword) + j = 32; + else + j = 48; + if (!(i.op[1].regs->reg_flags & RegRex) && base_regnum < 4) + j += 8; + i.op[1].regs -= j; } } else if (flag_code == CODE_64BIT + && !is_any_vex_encoding (&i.tm) && ((i.types[1].bitfield.qword && i.reg_operands == 1 && i.imm_operands == 1 && i.op[0].imms->X_op == O_constant - && ((i.tm.base_opcode == 0xb0 + && ((i.tm.base_opcode == 0xb8 && i.tm.extension_opcode == None && fits_in_unsigned_long (i.op[0].imms->X_add_number)) || (fits_in_imm31 (i.op[0].imms->X_add_number) - && (((i.tm.base_opcode == 0x24 - || i.tm.base_opcode == 0xa8) - && i.tm.extension_opcode == None) + && ((i.tm.base_opcode == 0x24 + || i.tm.base_opcode == 0xa8) || (i.tm.base_opcode == 0x80 && i.tm.extension_opcode == 0x4) || ((i.tm.base_opcode == 0xf6 - || i.tm.base_opcode == 0xc6) + || (i.tm.base_opcode | 1) == 0xc7) && i.tm.extension_opcode == 0x0))) || (fits_in_imm7 (i.op[0].imms->X_add_number) && i.tm.base_opcode == 0x83 @@ -3993,13 +4044,11 @@ optimize_encoding (void) || (i.types[0].bitfield.qword && ((i.reg_operands == 2 && i.op[0].regs == i.op[1].regs - && ((i.tm.base_opcode == 0x30 - || i.tm.base_opcode == 0x28) - && i.tm.extension_opcode == None)) + && (i.tm.base_opcode == 0x30 + || i.tm.base_opcode == 0x28)) || (i.reg_operands == 1 && i.operands == 1 - && i.tm.base_opcode == 0x30 - && i.tm.extension_opcode == None))))) + && i.tm.base_opcode == 0x30))))) { /* Optimize: -O: andq $imm31, %r64 -> andl $imm31, %r32 @@ -4011,7 +4060,7 @@ optimize_encoding (void) movq $imm32, %r64 -> movl $imm32, %r32 */ i.tm.opcode_modifier.norex64 = 1; - if (i.tm.base_opcode == 0xb0 || i.tm.base_opcode == 0xc6) + if (i.tm.base_opcode == 0xb8 || (i.tm.base_opcode | 1) == 0xc7) { /* Handle movq $imm31, %r64 -> movl $imm31, %r32 @@ -4025,13 +4074,14 @@ optimize_encoding (void) i.types[0].bitfield.imm64 = 0; i.types[1].bitfield.dword = 1; i.types[1].bitfield.qword = 0; - if (i.tm.base_opcode == 0xc6) + if ((i.tm.base_opcode | 1) == 0xc7) { /* Handle movq $imm31, %r64 -> movl $imm31, %r32 */ - i.tm.base_opcode = 0xb0; + i.tm.base_opcode = 0xb8; i.tm.extension_opcode = None; + i.tm.opcode_modifier.w = 0; i.tm.opcode_modifier.shortform = 1; i.tm.opcode_modifier.modrm = 0; } @@ -4039,6 +4089,7 @@ optimize_encoding (void) } else if (optimize > 1 && !optimize_for_space + && !is_any_vex_encoding (&i.tm) && i.reg_operands == 2 && i.op[0].regs == i.op[1].regs && ((i.tm.base_opcode & ~(Opcode_D | 1)) == 0x8 @@ -4136,7 +4187,7 @@ optimize_encoding (void) else return; } - else if (i.tm.operand_types[0].bitfield.regmask) + else if (i.tm.operand_types[0].bitfield.class == RegMask) { i.tm.base_opcode &= 0xff; i.tm.opcode_modifier.vexw = VEXW0; @@ -4309,14 +4360,17 @@ md_assemble (char *line) if (sse_check != check_none && !i.tm.opcode_modifier.noavx && !i.tm.cpu_flags.bitfield.cpuavx + && !i.tm.cpu_flags.bitfield.cpuavx512f && (i.tm.cpu_flags.bitfield.cpusse || i.tm.cpu_flags.bitfield.cpusse2 || i.tm.cpu_flags.bitfield.cpusse3 || i.tm.cpu_flags.bitfield.cpussse3 || i.tm.cpu_flags.bitfield.cpusse4_1 || i.tm.cpu_flags.bitfield.cpusse4_2 + || i.tm.cpu_flags.bitfield.cpusse4a || i.tm.cpu_flags.bitfield.cpupclmul || i.tm.cpu_flags.bitfield.cpuaes + || i.tm.cpu_flags.bitfield.cpusha || i.tm.cpu_flags.bitfield.cpugfni)) { (sse_check == check_warning @@ -4358,7 +4412,7 @@ md_assemble (char *line) && (!i.tm.opcode_modifier.islockable || i.mem_operands == 0 || (i.tm.base_opcode != 0x86 - && !operand_type_check (i.types[i.operands - 1], anymem)))) + && !(i.flags[i.operands - 1] & Operand_Mem)))) { as_bad (_("expecting lockable instruction after `lock'")); return; @@ -4406,8 +4460,9 @@ md_assemble (char *line) } /* Check string instruction segment overrides. */ - if (i.tm.opcode_modifier.isstring && i.mem_operands != 0) + if (i.tm.opcode_modifier.isstring >= IS_STRING_ES_OP0) { + gas_assert (i.mem_operands); if (!check_string ()) return; i.disp_operands = 0; @@ -4435,9 +4490,8 @@ md_assemble (char *line) with 3 operands or less. */ if (i.operands <= 3) for (j = 0; j < i.operands; j++) - if (i.types[j].bitfield.inoutportreg - || i.types[j].bitfield.shiftcount - || (i.types[j].bitfield.acc && !i.types[j].bitfield.xmmword)) + if (i.types[j].bitfield.instance != InstanceNone + && !i.types[j].bitfield.xmmword) i.reg_operands--; /* ImmExt should be processed after SSE2AVX. */ @@ -4483,9 +4537,9 @@ md_assemble (char *line) i.imm_operands = 0; } - if ((i.tm.opcode_modifier.jump - || i.tm.opcode_modifier.jumpbyte - || i.tm.opcode_modifier.jumpdword) + if ((i.tm.opcode_modifier.jump == JUMP + || i.tm.opcode_modifier.jump == JUMP_BYTE + || i.tm.opcode_modifier.jump == JUMP_DWORD) && i.op[0].disps->X_op == O_constant) { /* Convert "jmp constant" (and "call constant") to a jump (call) to @@ -4502,12 +4556,12 @@ md_assemble (char *line) instruction already has a prefix, we need to convert old registers to new ones. */ - if ((i.types[0].bitfield.reg && i.types[0].bitfield.byte + if ((i.types[0].bitfield.class == Reg && i.types[0].bitfield.byte && (i.op[0].regs->reg_flags & RegRex64) != 0) - || (i.types[1].bitfield.reg && i.types[1].bitfield.byte + || (i.types[1].bitfield.class == Reg && i.types[1].bitfield.byte && (i.op[1].regs->reg_flags & RegRex64) != 0) - || (((i.types[0].bitfield.reg && i.types[0].bitfield.byte) - || (i.types[1].bitfield.reg && i.types[1].bitfield.byte)) + || (((i.types[0].bitfield.class == Reg && i.types[0].bitfield.byte) + || (i.types[1].bitfield.class == Reg && i.types[1].bitfield.byte)) && i.rex != 0)) { int x; @@ -4516,9 +4570,10 @@ md_assemble (char *line) for (x = 0; x < 2; x++) { /* Look for 8 bit operand that uses old registers. */ - if (i.types[x].bitfield.reg && i.types[x].bitfield.byte + if (i.types[x].bitfield.class == Reg && i.types[x].bitfield.byte && (i.op[x].regs->reg_flags & RegRex64) == 0) { + gas_assert (!(i.op[x].regs->reg_flags & RegRex)); /* In case it is "hi" register, give up. */ if (i.op[x].regs->reg_num > 3) as_bad (_("can't encode register '%s%s' in an " @@ -4537,15 +4592,16 @@ md_assemble (char *line) if (i.rex == 0 && i.rex_encoding) { /* Check if we can add a REX_OPCODE byte. Look for 8 bit operand - that uses legacy register. If it is "hi" register, don't add + that uses legacy register. If it is "hi" register, don't add the REX_OPCODE byte. */ int x; for (x = 0; x < 2; x++) - if (i.types[x].bitfield.reg + if (i.types[x].bitfield.class == Reg && i.types[x].bitfield.byte && (i.op[x].regs->reg_flags & RegRex64) == 0 && i.op[x].regs->reg_num > 3) { + gas_assert (!(i.op[x].regs->reg_flags & RegRex)); i.rex_encoding = FALSE; break; } @@ -4559,6 +4615,17 @@ md_assemble (char *line) /* We are ready to output the insn. */ output_insn (); + + last_insn.seg = now_seg; + + if (i.tm.opcode_modifier.isprefix) + { + last_insn.kind = last_insn_prefix; + last_insn.name = i.tm.name; + last_insn.file = as_where (&last_insn.line); + } + else + last_insn.kind = last_insn_other; } static char * @@ -4785,8 +4852,8 @@ check_suffix: } } - if (current_templates->start->opcode_modifier.jump - || current_templates->start->opcode_modifier.jumpbyte) + if (current_templates->start->opcode_modifier.jump == JUMP + || current_templates->start->opcode_modifier.jump == JUMP_BYTE) { /* Check for a branch hint. We allow ",pt" and ",pn" for predict taken and predict not taken respectively. @@ -5058,26 +5125,28 @@ optimize_imm (void) else if (i.reg_operands) { /* Figure out a suffix from the last register operand specified. - We can't do this properly yet, ie. excluding InOutPortReg, - but the following works for instructions with immediates. - In any case, we can't set i.suffix yet. */ + We can't do this properly yet, i.e. excluding special register + instances, but the following works for instructions with + immediates. In any case, we can't set i.suffix yet. */ for (op = i.operands; --op >= 0;) - if (i.types[op].bitfield.reg && i.types[op].bitfield.byte) + if (i.types[op].bitfield.class != Reg) + continue; + else if (i.types[op].bitfield.byte) { guess_suffix = BYTE_MNEM_SUFFIX; break; } - else if (i.types[op].bitfield.reg && i.types[op].bitfield.word) + else if (i.types[op].bitfield.word) { guess_suffix = WORD_MNEM_SUFFIX; break; } - else if (i.types[op].bitfield.reg && i.types[op].bitfield.dword) + else if (i.types[op].bitfield.dword) { guess_suffix = LONG_MNEM_SUFFIX; break; } - else if (i.types[op].bitfield.reg && i.types[op].bitfield.qword) + else if (i.types[op].bitfield.qword) { guess_suffix = QWORD_MNEM_SUFFIX; break; @@ -5166,8 +5235,10 @@ optimize_imm (void) for (t = current_templates->start; t < current_templates->end; ++t) - allowed = operand_type_or (allowed, - t->operand_types[op]); + { + allowed = operand_type_or (allowed, t->operand_types[op]); + allowed = operand_type_and (allowed, anyimm); + } switch (guess_suffix) { case QWORD_MNEM_SUFFIX: @@ -5359,10 +5430,10 @@ check_VecOperands (const insn_template *t) gas_assert (i.reg_operands == 2 || i.mask); if (i.reg_operands == 2 && !i.mask) { - gas_assert (i.types[0].bitfield.regsimd); + gas_assert (i.types[0].bitfield.class == RegSIMD); gas_assert (i.types[0].bitfield.xmmword || i.types[0].bitfield.ymmword); - gas_assert (i.types[2].bitfield.regsimd); + gas_assert (i.types[2].bitfield.class == RegSIMD); gas_assert (i.types[2].bitfield.xmmword || i.types[2].bitfield.ymmword); if (operand_check == check_none) @@ -5383,7 +5454,7 @@ check_VecOperands (const insn_template *t) } else if (i.reg_operands == 1 && i.mask) { - if (i.types[1].bitfield.regsimd + if (i.types[1].bitfield.class == RegSIMD && (i.types[1].bitfield.xmmword || i.types[1].bitfield.ymmword || i.types[1].bitfield.zmmword) @@ -5473,7 +5544,7 @@ check_VecOperands (const insn_template *t) { /* Find memory operand. */ for (op = 0; op < i.operands; op++) - if (operand_type_check (i.types[op], anymem)) + if (i.flags[op] & Operand_Mem) break; gas_assert (op < i.operands); /* Check size of the memory operand. */ @@ -5563,7 +5634,7 @@ check_VecOperands (const insn_template *t) i.memshift = 0; for (op = 0; op < i.operands; op++) - if (operand_type_check (i.types[op], anymem)) + if (i.flags[op] & Operand_Mem) { if (t->opcode_modifier.evex == EVEXLIG) i.memshift = 2 + (i.suffix == QWORD_MNEM_SUFFIX); @@ -5574,7 +5645,7 @@ check_VecOperands (const insn_template *t) else if (!i.types[op].bitfield.unspecified) type = &i.types[op]; } - else if (i.types[op].bitfield.regsimd + else if (i.types[op].bitfield.class == RegSIMD && t->opcode_modifier.evex != EVEXLIG) { if (i.types[op].bitfield.zmmword) @@ -5671,7 +5742,7 @@ match_template (char mnem_suffix) i386_operand_type overlap0, overlap1, overlap2, overlap3; i386_operand_type overlap4; unsigned int found_reverse_match; - i386_opcode_modifier suffix_check, mnemsuf_check; + i386_opcode_modifier suffix_check; i386_operand_type operand_types [MAX_OPERANDS]; int addr_prefix_disp; unsigned int j; @@ -5686,33 +5757,33 @@ match_template (char mnem_suffix) found_reverse_match = 0; addr_prefix_disp = -1; + /* Prepare for mnemonic suffix check. */ memset (&suffix_check, 0, sizeof (suffix_check)); - if (intel_syntax && i.broadcast) - /* nothing */; - else if (i.suffix == BYTE_MNEM_SUFFIX) - suffix_check.no_bsuf = 1; - else if (i.suffix == WORD_MNEM_SUFFIX) - suffix_check.no_wsuf = 1; - else if (i.suffix == SHORT_MNEM_SUFFIX) - suffix_check.no_ssuf = 1; - else if (i.suffix == LONG_MNEM_SUFFIX) - suffix_check.no_lsuf = 1; - else if (i.suffix == QWORD_MNEM_SUFFIX) - suffix_check.no_qsuf = 1; - else if (i.suffix == LONG_DOUBLE_MNEM_SUFFIX) - suffix_check.no_ldsuf = 1; - - memset (&mnemsuf_check, 0, sizeof (mnemsuf_check)); - if (intel_syntax) + switch (mnem_suffix) { - switch (mnem_suffix) - { - case BYTE_MNEM_SUFFIX: mnemsuf_check.no_bsuf = 1; break; - case WORD_MNEM_SUFFIX: mnemsuf_check.no_wsuf = 1; break; - case SHORT_MNEM_SUFFIX: mnemsuf_check.no_ssuf = 1; break; - case LONG_MNEM_SUFFIX: mnemsuf_check.no_lsuf = 1; break; - case QWORD_MNEM_SUFFIX: mnemsuf_check.no_qsuf = 1; break; - } + case BYTE_MNEM_SUFFIX: + suffix_check.no_bsuf = 1; + break; + case WORD_MNEM_SUFFIX: + suffix_check.no_wsuf = 1; + break; + case SHORT_MNEM_SUFFIX: + suffix_check.no_ssuf = 1; + break; + case LONG_MNEM_SUFFIX: + suffix_check.no_lsuf = 1; + break; + case QWORD_MNEM_SUFFIX: + suffix_check.no_qsuf = 1; + break; + default: + /* NB: In Intel syntax, normally we can check for memory operand + size when there is no mnemonic suffix. But jmp and call have + 2 different encodings with Dword memory operand size, one with + No_ldSuf and the other without. i.suffix is set to + LONG_DOUBLE_MNEM_SUFFIX to skip the one with No_ldSuf. */ + if (i.suffix == LONG_DOUBLE_MNEM_SUFFIX) + suffix_check.no_ldsuf = 1; } /* Must have right number of operands. */ @@ -5746,29 +5817,32 @@ match_template (char mnem_suffix) || (!intel64 && t->opcode_modifier.intel64)) continue; - /* Check the suffix, except for some instructions in intel mode. */ + /* Check the suffix. */ i.error = invalid_instruction_suffix; - if ((!intel_syntax || !t->opcode_modifier.ignoresize) - && ((t->opcode_modifier.no_bsuf && suffix_check.no_bsuf) - || (t->opcode_modifier.no_wsuf && suffix_check.no_wsuf) - || (t->opcode_modifier.no_lsuf && suffix_check.no_lsuf) - || (t->opcode_modifier.no_ssuf && suffix_check.no_ssuf) - || (t->opcode_modifier.no_qsuf && suffix_check.no_qsuf) - || (t->opcode_modifier.no_ldsuf && suffix_check.no_ldsuf))) - continue; - /* In Intel mode all mnemonic suffixes must be explicitly allowed. */ - if ((t->opcode_modifier.no_bsuf && mnemsuf_check.no_bsuf) - || (t->opcode_modifier.no_wsuf && mnemsuf_check.no_wsuf) - || (t->opcode_modifier.no_lsuf && mnemsuf_check.no_lsuf) - || (t->opcode_modifier.no_ssuf && mnemsuf_check.no_ssuf) - || (t->opcode_modifier.no_qsuf && mnemsuf_check.no_qsuf) - || (t->opcode_modifier.no_ldsuf && mnemsuf_check.no_ldsuf)) + if ((t->opcode_modifier.no_bsuf && suffix_check.no_bsuf) + || (t->opcode_modifier.no_wsuf && suffix_check.no_wsuf) + || (t->opcode_modifier.no_lsuf && suffix_check.no_lsuf) + || (t->opcode_modifier.no_ssuf && suffix_check.no_ssuf) + || (t->opcode_modifier.no_qsuf && suffix_check.no_qsuf) + || (t->opcode_modifier.no_ldsuf && suffix_check.no_ldsuf)) continue; size_match = operand_size_match (t); if (!size_match) continue; + /* This is intentionally not + + if (i.jumpabsolute != (t->opcode_modifier.jump == JUMP_ABSOLUTE)) + + as the case of a missing * on the operand is accepted (perhaps with + a warning, issued further down). */ + if (i.jumpabsolute && t->opcode_modifier.jump != JUMP_ABSOLUTE) + { + i.error = operand_type_mismatch; + continue; + } + for (j = 0; j < MAX_OPERANDS; j++) operand_types[j] = t->operand_types[j]; @@ -5780,10 +5854,10 @@ match_template (char mnem_suffix) && !t->opcode_modifier.broadcast && !intel_float_operand (t->name)) : intel_float_operand (t->name) != 2) - && ((!operand_types[0].bitfield.regmmx - && !operand_types[0].bitfield.regsimd) - || (!operand_types[t->operands > 1].bitfield.regmmx - && !operand_types[t->operands > 1].bitfield.regsimd)) + && ((operand_types[0].bitfield.class != RegMMX + && operand_types[0].bitfield.class != RegSIMD) + || (operand_types[t->operands > 1].bitfield.class != RegMMX + && operand_types[t->operands > 1].bitfield.class != RegSIMD)) && (t->base_opcode != 0x0fc7 || t->extension_opcode != 1 /* cmpxchg8b */)) continue; @@ -5795,10 +5869,11 @@ match_template (char mnem_suffix) ? (!t->opcode_modifier.ignoresize && !intel_float_operand (t->name)) : intel_float_operand (t->name) != 2) - && ((!operand_types[0].bitfield.regmmx - && !operand_types[0].bitfield.regsimd) - || (!operand_types[t->operands > 1].bitfield.regmmx - && !operand_types[t->operands > 1].bitfield.regsimd))) + && ((operand_types[0].bitfield.class != RegMMX + && operand_types[0].bitfield.class != RegSIMD) + || (operand_types[t->operands > 1].bitfield.class != RegMMX + && operand_types[t->operands > 1].bitfield.class + != RegSIMD))) continue; /* Do not verify operands when there are none. */ @@ -5809,51 +5884,50 @@ match_template (char mnem_suffix) break; } - /* Address size prefix will turn Disp64/Disp32/Disp16 operand - into Disp32/Disp16/Disp32 operand. */ - if (i.prefix[ADDR_PREFIX] != 0) - { - /* There should be only one Disp operand. */ - switch (flag_code) - { - case CODE_16BIT: - for (j = 0; j < MAX_OPERANDS; j++) - { - if (operand_types[j].bitfield.disp16) - { - addr_prefix_disp = j; - operand_types[j].bitfield.disp32 = 1; - operand_types[j].bitfield.disp16 = 0; - break; - } - } + if (!t->opcode_modifier.jump + || t->opcode_modifier.jump == JUMP_ABSOLUTE) + { + /* There should be only one Disp operand. */ + for (j = 0; j < MAX_OPERANDS; j++) + if (operand_type_check (operand_types[j], disp)) break; - case CODE_32BIT: - for (j = 0; j < MAX_OPERANDS; j++) + if (j < MAX_OPERANDS) + { + bfd_boolean override = (i.prefix[ADDR_PREFIX] != 0); + + addr_prefix_disp = j; + + /* Address size prefix will turn Disp64/Disp32S/Disp32/Disp16 + operand into Disp32/Disp32/Disp16/Disp32 operand. */ + switch (flag_code) { - if (operand_types[j].bitfield.disp32) + case CODE_16BIT: + override = !override; + /* Fall through. */ + case CODE_32BIT: + if (operand_types[j].bitfield.disp32 + && operand_types[j].bitfield.disp16) { - addr_prefix_disp = j; - operand_types[j].bitfield.disp32 = 0; - operand_types[j].bitfield.disp16 = 1; - break; + operand_types[j].bitfield.disp16 = override; + operand_types[j].bitfield.disp32 = !override; } - } - break; - case CODE_64BIT: - for (j = 0; j < MAX_OPERANDS; j++) - { - if (operand_types[j].bitfield.disp64) + operand_types[j].bitfield.disp32s = 0; + operand_types[j].bitfield.disp64 = 0; + break; + + case CODE_64BIT: + if (operand_types[j].bitfield.disp32s + || operand_types[j].bitfield.disp64) { - addr_prefix_disp = j; - operand_types[j].bitfield.disp64 = 0; - operand_types[j].bitfield.disp32 = 1; - break; + operand_types[j].bitfield.disp64 &= !override; + operand_types[j].bitfield.disp32s &= !override; + operand_types[j].bitfield.disp32 = override; } + operand_types[j].bitfield.disp16 = 0; + break; } - break; } - } + } /* Force 0x8b encoding for "mov foo@GOT, %eax". */ if (i.reloc[0] == BFD_RELOC_386_GOT32 && t->base_opcode == 0xa0) @@ -5883,16 +5957,18 @@ match_template (char mnem_suffix) zero-extend %eax to %rax. */ if (flag_code == CODE_64BIT && t->base_opcode == 0x90 - && i.types[0].bitfield.acc && i.types[0].bitfield.dword - && i.types[1].bitfield.acc && i.types[1].bitfield.dword) + && i.types[0].bitfield.instance == Accum + && i.types[0].bitfield.dword + && i.types[1].bitfield.instance == Accum + && i.types[1].bitfield.dword) continue; /* xrelease mov %eax, is another special case. It must not match the accumulator-only encoding of mov. */ if (flag_code != CODE_64BIT && i.hle_prefix && t->base_opcode == 0xa0 - && i.types[0].bitfield.acc - && operand_type_check (i.types[1], anymem)) + && i.types[0].bitfield.instance == Accum + && (i.flags[1] & Operand_Mem)) continue; /* Fall through. */ @@ -5911,13 +5987,13 @@ match_template (char mnem_suffix) { case dir_encoding_load: if (operand_type_check (operand_types[i.operands - 1], anymem) - || operand_types[i.operands - 1].bitfield.regmem) + || t->opcode_modifier.regmem) goto check_reverse; break; case dir_encoding_store: if (!operand_type_check (operand_types[i.operands - 1], anymem) - && !operand_types[i.operands - 1].bitfield.regmem) + && !t->opcode_modifier.regmem) goto check_reverse; break; @@ -5974,8 +6050,8 @@ check_reverse: found_reverse_match = Opcode_FloatD; else if (operand_types[0].bitfield.xmmword || operand_types[i.operands - 1].bitfield.xmmword - || operand_types[0].bitfield.regmmx - || operand_types[i.operands - 1].bitfield.regmmx + || operand_types[0].bitfield.class == RegMMX + || operand_types[i.operands - 1].bitfield.class == RegMMX || is_any_vex_encoding(t)) found_reverse_match = (t->base_opcode & 0xee) != 0x6e ? Opcode_SIMD_FloatD : Opcode_SIMD_IntD; @@ -6143,11 +6219,8 @@ check_reverse: if (!quiet_warnings) { if (!intel_syntax - && (i.types[0].bitfield.jumpabsolute - != operand_types[0].bitfield.jumpabsolute)) - { - as_warn (_("indirect %s without `*'"), t->name); - } + && (i.jumpabsolute != (t->opcode_modifier.jump == JUMP_ABSOLUTE))) + as_warn (_("indirect %s without `*'"), t->name); if (t->opcode_modifier.isprefix && t->opcode_modifier.ignoresize) @@ -6167,14 +6240,22 @@ check_reverse: if (found_reverse_match) { - /* If we found a reverse match we must alter the opcode - direction bit. found_reverse_match holds bits to change - (different for int & float insns). */ + /* If we found a reverse match we must alter the opcode direction + bit and clear/flip the regmem modifier one. found_reverse_match + holds bits to change (different for int & float insns). */ i.tm.base_opcode ^= found_reverse_match; i.tm.operand_types[0] = operand_types[i.operands - 1]; i.tm.operand_types[i.operands - 1] = operand_types[0]; + + /* Certain SIMD insns have their load forms specified in the opcode + table, and hence we need to _set_ RegMem instead of clearing it. + We need to avoid setting the bit though on insns like KMOVW. */ + i.tm.opcode_modifier.regmem + = i.tm.opcode_modifier.modrm && i.tm.opcode_modifier.d + && i.tm.operands > 2U - i.tm.opcode_modifier.sse2avx + && !i.tm.opcode_modifier.regmem; } return t; @@ -6183,34 +6264,24 @@ check_reverse: static int check_string (void) { - int mem_op = operand_type_check (i.types[0], anymem) ? 0 : 1; - if (i.tm.operand_types[mem_op].bitfield.esseg) - { - if (i.seg[0] != NULL && i.seg[0] != &es) - { - as_bad (_("`%s' operand %d must use `%ses' segment"), - i.tm.name, - mem_op + 1, - register_prefix); - return 0; - } - /* There's only ever one segment override allowed per instruction. - This instruction possibly has a legal segment override on the - second operand, so copy the segment to where non-string - instructions store it, allowing common code. */ - i.seg[0] = i.seg[1]; - } - else if (i.tm.operand_types[mem_op + 1].bitfield.esseg) + unsigned int es_op = i.tm.opcode_modifier.isstring - IS_STRING_ES_OP0; + unsigned int op = i.tm.operand_types[0].bitfield.baseindex ? es_op : 0; + + if (i.seg[op] != NULL && i.seg[op] != &es) { - if (i.seg[1] != NULL && i.seg[1] != &es) - { - as_bad (_("`%s' operand %d must use `%ses' segment"), - i.tm.name, - mem_op + 2, - register_prefix); - return 0; - } + as_bad (_("`%s' operand %u must use `%ses' segment"), + i.tm.name, + intel_syntax ? i.tm.operands - es_op : es_op + 1, + register_prefix); + return 0; } + + /* There's only ever one segment override allowed per instruction. + This instruction possibly has a legal segment override on the + second operand, so copy the segment to where non-string + instructions store it, allowing common code. */ + i.seg[op] = i.seg[1]; + return 1; } @@ -6225,17 +6296,19 @@ process_suffix (void) i.suffix = LONG_MNEM_SUFFIX; else if (i.tm.opcode_modifier.size == SIZE64) i.suffix = QWORD_MNEM_SUFFIX; - else if (i.reg_operands) + else if (i.reg_operands + && (i.operands > 1 || i.types[0].bitfield.class == Reg)) { /* If there's no instruction mnemonic suffix we try to invent one - based on register operands. */ + based on GPR operands. */ if (!i.suffix) { /* We take i.suffix from the last register operand specified, Destination register type is more significant than source register type. crc32 in SSE4.2 prefers source register type. */ - if (i.tm.base_opcode == 0xf20f38f0 && i.types[0].bitfield.reg) + if (i.tm.base_opcode == 0xf20f38f0 + && i.types[0].bitfield.class == Reg) { if (i.types[0].bitfield.byte) i.suffix = BYTE_MNEM_SUFFIX; @@ -6260,10 +6333,10 @@ process_suffix (void) } for (op = i.operands; --op >= 0;) - if (!i.tm.operand_types[op].bitfield.inoutportreg - && !i.tm.operand_types[op].bitfield.shiftcount) + if (i.tm.operand_types[op].bitfield.instance == InstanceNone + || i.tm.operand_types[op].bitfield.instance == Accum) { - if (!i.types[op].bitfield.reg) + if (i.types[op].bitfield.class != Reg) continue; if (i.types[op].bitfield.byte) i.suffix = BYTE_MNEM_SUFFIX; @@ -6328,27 +6401,34 @@ process_suffix (void) else if (i.tm.opcode_modifier.defaultsize && !i.suffix /* exclude fldenv/frstor/fsave/fstenv */ - && i.tm.opcode_modifier.no_ssuf) + && i.tm.opcode_modifier.no_ssuf + /* exclude sysret */ + && i.tm.base_opcode != 0x0f07) { - if (stackop_size == LONG_MNEM_SUFFIX - && i.tm.base_opcode == 0xcf) + i.suffix = stackop_size; + if (stackop_size == LONG_MNEM_SUFFIX) { /* stackop_size is set to LONG_MNEM_SUFFIX for the .code16gcc directive to support 16-bit mode with 32-bit address. For IRET without a suffix, generate 16-bit IRET (opcode 0xcf) to return from an interrupt handler. */ - i.suffix = WORD_MNEM_SUFFIX; - as_warn (_("generating 16-bit `iret' for .code16gcc directive")); + if (i.tm.base_opcode == 0xcf) + { + i.suffix = WORD_MNEM_SUFFIX; + as_warn (_("generating 16-bit `iret' for .code16gcc directive")); + } + /* Warn about changed behavior for segment register push/pop. */ + else if ((i.tm.base_opcode | 1) == 0x07) + as_warn (_("generating 32-bit `%s', unlike earlier gas versions"), + i.tm.name); } - else - i.suffix = stackop_size; } else if (intel_syntax && !i.suffix - && (i.tm.operand_types[0].bitfield.jumpabsolute - || i.tm.opcode_modifier.jumpbyte - || i.tm.opcode_modifier.jumpintersegment + && (i.tm.opcode_modifier.jump == JUMP_ABSOLUTE + || i.tm.opcode_modifier.jump == JUMP_BYTE + || i.tm.opcode_modifier.jump == JUMP_INTERSEGMENT || (i.tm.base_opcode == 0x0f01 /* [ls][gi]dt */ && i.tm.extension_opcode <= 3))) { @@ -6438,9 +6518,9 @@ process_suffix (void) size prefix, except for instructions that will ignore this prefix anyway. */ if (i.reg_operands > 0 - && i.types[0].bitfield.reg + && i.types[0].bitfield.class == Reg && i.tm.opcode_modifier.addrprefixopreg - && (i.tm.opcode_modifier.immext + && (i.tm.operand_types[0].bitfield.instance == Accum || i.operands == 1)) { /* The address size override prefix changes the size of the @@ -6458,11 +6538,11 @@ process_suffix (void) && !is_any_vex_encoding (&i.tm) && ((i.suffix == LONG_MNEM_SUFFIX) == (flag_code == CODE_16BIT) || (flag_code == CODE_64BIT - && i.tm.opcode_modifier.jumpbyte))) + && i.tm.opcode_modifier.jump == JUMP_BYTE))) { unsigned int prefix = DATA_PREFIX_OPCODE; - if (i.tm.opcode_modifier.jumpbyte) /* jcxz, loop */ + if (i.tm.opcode_modifier.jump == JUMP_BYTE) /* jcxz, loop */ prefix = ADDR_PREFIX_OPCODE; if (!add_prefix (prefix)) @@ -6478,8 +6558,10 @@ process_suffix (void) && ! (i.operands == 2 && i.tm.base_opcode == 0x90 && i.tm.extension_opcode == None - && i.types[0].bitfield.acc && i.types[0].bitfield.qword - && i.types[1].bitfield.acc && i.types[1].bitfield.qword)) + && i.types[0].bitfield.instance == Accum + && i.types[0].bitfield.qword + && i.types[1].bitfield.instance == Accum + && i.types[1].bitfield.qword)) i.rex |= REX_W; break; @@ -6488,7 +6570,7 @@ process_suffix (void) if (i.reg_operands != 0 && i.operands > 1 && i.tm.opcode_modifier.addrprefixopreg - && !i.tm.opcode_modifier.immext) + && i.tm.operand_types[0].bitfield.instance != Accum) { /* Check invalid register operand when the address size override prefix changes the size of register operands. */ @@ -6506,7 +6588,7 @@ process_suffix (void) } for (op = 0; op < i.operands; op++) - if (i.types[op].bitfield.reg + if (i.types[op].bitfield.class == Reg && ((need == need_word && !i.op[op].regs->reg_type.bitfield.word) || (need == need_dword @@ -6531,7 +6613,7 @@ check_byte_reg (void) for (op = i.operands; --op >= 0;) { /* Skip non-register operands. */ - if (!i.types[op].bitfield.reg) + if (i.types[op].bitfield.class != Reg) continue; /* If this is an eight bit register, it's OK. If it's the 16 or @@ -6541,7 +6623,8 @@ check_byte_reg (void) continue; /* I/O port address operands are OK too. */ - if (i.tm.operand_types[op].bitfield.inoutportreg) + if (i.tm.operand_types[op].bitfield.instance == RegD + && i.tm.operand_types[op].bitfield.word) continue; /* crc32 doesn't generate this warning. */ @@ -6570,13 +6653,13 @@ check_byte_reg (void) continue; } /* Any other register is bad. */ - if (i.types[op].bitfield.reg - || i.types[op].bitfield.regmmx - || i.types[op].bitfield.regsimd - || i.types[op].bitfield.sreg - || i.types[op].bitfield.control - || i.types[op].bitfield.debug - || i.types[op].bitfield.test) + if (i.types[op].bitfield.class == Reg + || i.types[op].bitfield.class == RegMMX + || i.types[op].bitfield.class == RegSIMD + || i.types[op].bitfield.class == SReg + || i.types[op].bitfield.class == RegCR + || i.types[op].bitfield.class == RegDR + || i.types[op].bitfield.class == RegTR) { as_bad (_("`%s%s' not allowed with `%s%c'"), register_prefix, @@ -6596,13 +6679,13 @@ check_long_reg (void) for (op = i.operands; --op >= 0;) /* Skip non-register operands. */ - if (!i.types[op].bitfield.reg) + if (i.types[op].bitfield.class != Reg) continue; /* Reject eight bit registers, except where the template requires them. (eg. movzb) */ else if (i.types[op].bitfield.byte - && (i.tm.operand_types[op].bitfield.reg - || i.tm.operand_types[op].bitfield.acc) + && (i.tm.operand_types[op].bitfield.class == Reg + || i.tm.operand_types[op].bitfield.instance == Accum) && (i.tm.operand_types[op].bitfield.word || i.tm.operand_types[op].bitfield.dword)) { @@ -6616,8 +6699,8 @@ check_long_reg (void) /* Warn if the e prefix on a general reg is missing. */ else if ((!quiet_warnings || flag_code == CODE_64BIT) && i.types[op].bitfield.word - && (i.tm.operand_types[op].bitfield.reg - || i.tm.operand_types[op].bitfield.acc) + && (i.tm.operand_types[op].bitfield.class == Reg + || i.tm.operand_types[op].bitfield.instance == Accum) && i.tm.operand_types[op].bitfield.dword) { /* Prohibit these changes in the 64bit mode, since the @@ -6638,13 +6721,13 @@ check_long_reg (void) } /* Warn if the r prefix on a general reg is present. */ else if (i.types[op].bitfield.qword - && (i.tm.operand_types[op].bitfield.reg - || i.tm.operand_types[op].bitfield.acc) + && (i.tm.operand_types[op].bitfield.class == Reg + || i.tm.operand_types[op].bitfield.instance == Accum) && i.tm.operand_types[op].bitfield.dword) { if (intel_syntax && i.tm.opcode_modifier.toqword - && !i.types[0].bitfield.regsimd) + && i.types[0].bitfield.class != RegSIMD) { /* Convert to QWORD. We want REX byte. */ i.suffix = QWORD_MNEM_SUFFIX; @@ -6667,13 +6750,13 @@ check_qword_reg (void) for (op = i.operands; --op >= 0; ) /* Skip non-register operands. */ - if (!i.types[op].bitfield.reg) + if (i.types[op].bitfield.class != Reg) continue; /* Reject eight bit registers, except where the template requires them. (eg. movzb) */ else if (i.types[op].bitfield.byte - && (i.tm.operand_types[op].bitfield.reg - || i.tm.operand_types[op].bitfield.acc) + && (i.tm.operand_types[op].bitfield.class == Reg + || i.tm.operand_types[op].bitfield.instance == Accum) && (i.tm.operand_types[op].bitfield.word || i.tm.operand_types[op].bitfield.dword)) { @@ -6687,15 +6770,15 @@ check_qword_reg (void) /* Warn if the r prefix on a general reg is missing. */ else if ((i.types[op].bitfield.word || i.types[op].bitfield.dword) - && (i.tm.operand_types[op].bitfield.reg - || i.tm.operand_types[op].bitfield.acc) + && (i.tm.operand_types[op].bitfield.class == Reg + || i.tm.operand_types[op].bitfield.instance == Accum) && i.tm.operand_types[op].bitfield.qword) { /* Prohibit these changes in the 64bit mode, since the lowering is more complicated. */ if (intel_syntax && i.tm.opcode_modifier.todword - && !i.types[0].bitfield.regsimd) + && i.types[0].bitfield.class != RegSIMD) { /* Convert to DWORD. We don't want REX byte. */ i.suffix = LONG_MNEM_SUFFIX; @@ -6717,13 +6800,13 @@ check_word_reg (void) int op; for (op = i.operands; --op >= 0;) /* Skip non-register operands. */ - if (!i.types[op].bitfield.reg) + if (i.types[op].bitfield.class != Reg) continue; /* Reject eight bit registers, except where the template requires them. (eg. movzb) */ else if (i.types[op].bitfield.byte - && (i.tm.operand_types[op].bitfield.reg - || i.tm.operand_types[op].bitfield.acc) + && (i.tm.operand_types[op].bitfield.class == Reg + || i.tm.operand_types[op].bitfield.instance == Accum) && (i.tm.operand_types[op].bitfield.word || i.tm.operand_types[op].bitfield.dword)) { @@ -6738,8 +6821,8 @@ check_word_reg (void) else if ((!quiet_warnings || flag_code == CODE_64BIT) && (i.types[op].bitfield.dword || i.types[op].bitfield.qword) - && (i.tm.operand_types[op].bitfield.reg - || i.tm.operand_types[op].bitfield.acc) + && (i.tm.operand_types[op].bitfield.class == Reg + || i.tm.operand_types[op].bitfield.instance == Accum) && i.tm.operand_types[op].bitfield.word) { /* Prohibit these changes in the 64bit mode, since the @@ -6864,15 +6947,15 @@ process_operands (void) && MAX_OPERANDS > dupl && operand_type_equal (&i.types[dest], ®xmm)); - if (i.tm.operand_types[0].bitfield.acc + if (i.tm.operand_types[0].bitfield.instance == Accum && i.tm.operand_types[0].bitfield.xmmword) { if (i.tm.opcode_modifier.vexsources == VEX3SOURCES) { /* Keep xmm0 for instructions with VEX prefix and 3 sources. */ - i.tm.operand_types[0].bitfield.acc = 0; - i.tm.operand_types[0].bitfield.regsimd = 1; + i.tm.operand_types[0].bitfield.instance = InstanceNone; + i.tm.operand_types[0].bitfield.class = RegSIMD; goto duplicate; } else @@ -6885,6 +6968,7 @@ process_operands (void) i.op[j - 1] = i.op[j]; i.types[j - 1] = i.types[j]; i.tm.operand_types[j - 1] = i.tm.operand_types[j]; + i.flags[j - 1] = i.flags[j]; } } } @@ -6901,6 +6985,7 @@ process_operands (void) i.op[j] = i.op[j - 1]; i.types[j] = i.types[j - 1]; i.tm.operand_types[j] = i.tm.operand_types[j - 1]; + i.flags[j] = i.flags[j - 1]; } i.op[0].regs = (const reg_entry *) hash_find (reg_hash, "xmm0"); @@ -6916,6 +7001,7 @@ process_operands (void) i.op[dupl] = i.op[dest]; i.types[dupl] = i.types[dest]; i.tm.operand_types[dupl] = i.tm.operand_types[dest]; + i.flags[dupl] = i.flags[dest]; } else { @@ -6927,12 +7013,13 @@ duplicate: i.op[dupl] = i.op[dest]; i.types[dupl] = i.types[dest]; i.tm.operand_types[dupl] = i.tm.operand_types[dest]; + i.flags[dupl] = i.flags[dest]; } if (i.tm.opcode_modifier.immext) process_immext (); } - else if (i.tm.operand_types[0].bitfield.acc + else if (i.tm.operand_types[0].bitfield.instance == Accum && i.tm.operand_types[0].bitfield.xmmword) { unsigned int j; @@ -6945,6 +7032,8 @@ duplicate: /* We need to adjust fields in i.tm since they are used by build_modrm_byte. */ i.tm.operand_types [j - 1] = i.tm.operand_types [j]; + + i.flags[j - 1] = i.flags[j]; } i.operands--; @@ -6956,7 +7045,7 @@ duplicate: unsigned int regnum, first_reg_in_group, last_reg_in_group; /* The second operand must be {x,y,z}mmN, where N is a multiple of 4. */ - gas_assert (i.operands >= 2 && i.types[1].bitfield.regsimd); + gas_assert (i.operands >= 2 && i.types[1].bitfield.class == RegSIMD); regnum = register_number (i.op[1].regs); first_reg_in_group = regnum & ~3; last_reg_in_group = first_reg_in_group + 3; @@ -6989,63 +7078,7 @@ duplicate: i.reg_operands++; } - if (i.tm.opcode_modifier.shortform) - { - if (i.types[0].bitfield.sreg) - { - if (flag_code != CODE_64BIT - ? i.tm.base_opcode == POP_SEG_SHORT - && i.op[0].regs->reg_num == 1 - : (i.tm.base_opcode | 1) == POP_SEG_SHORT - && i.op[0].regs->reg_num < 4) - { - as_bad (_("you can't `%s %s%s'"), - i.tm.name, register_prefix, i.op[0].regs->reg_name); - return 0; - } - if ( i.op[0].regs->reg_num > 3 ) - { - i.tm.base_opcode ^= POP_SEG_SHORT ^ POP_SEG386_SHORT; - i.tm.opcode_length = 2; - } - i.tm.base_opcode |= (i.op[0].regs->reg_num << 3); - } - else - { - /* The register or float register operand is in operand - 0 or 1. */ - unsigned int op; - - if ((i.types[0].bitfield.reg && i.types[0].bitfield.tbyte) - || operand_type_check (i.types[0], reg)) - op = 0; - else - op = 1; - /* Register goes in low 3 bits of opcode. */ - i.tm.base_opcode |= i.op[op].regs->reg_num; - if ((i.op[op].regs->reg_flags & RegRex) != 0) - i.rex |= REX_B; - if (!quiet_warnings && i.tm.opcode_modifier.ugh) - { - /* Warn about some common errors, but press on regardless. - The first case can be generated by gcc (<= 2.8.1). */ - if (i.operands == 2) - { - /* Reversed arguments on faddp, fsubp, etc. */ - as_warn (_("translating to `%s %s%s,%s%s'"), i.tm.name, - register_prefix, i.op[!intel_syntax].regs->reg_name, - register_prefix, i.op[intel_syntax].regs->reg_name); - } - else - { - /* Extraneous `l' suffix on fp insn. */ - as_warn (_("translating to `%s %s%s'"), i.tm.name, - register_prefix, i.op[0].regs->reg_name); - } - } - } - } - else if (i.tm.opcode_modifier.modrm) + if (i.tm.opcode_modifier.modrm) { /* The opcode is completed (modulo i.tm.extension_opcode which must be put into the modrm byte). Now, we make the modrm and @@ -7053,6 +7086,25 @@ duplicate: default_seg = build_modrm_byte (); } + else if (i.types[0].bitfield.class == SReg) + { + if (flag_code != CODE_64BIT + ? i.tm.base_opcode == POP_SEG_SHORT + && i.op[0].regs->reg_num == 1 + : (i.tm.base_opcode | 1) == POP_SEG386_SHORT + && i.op[0].regs->reg_num < 4) + { + as_bad (_("you can't `%s %s%s'"), + i.tm.name, register_prefix, i.op[0].regs->reg_name); + return 0; + } + if ( i.op[0].regs->reg_num > 3 && i.tm.opcode_length == 1 ) + { + i.tm.base_opcode ^= POP_SEG_SHORT ^ POP_SEG386_SHORT; + i.tm.opcode_length = 2; + } + i.tm.base_opcode |= (i.op[0].regs->reg_num << 3); + } else if ((i.tm.base_opcode & ~0x3) == MOV_AX_DISP32) { default_seg = &ds; @@ -7063,6 +7115,35 @@ duplicate: on one of their operands, the default segment is ds. */ default_seg = &ds; } + else if (i.tm.opcode_modifier.shortform) + { + /* The register or float register operand is in operand + 0 or 1. */ + unsigned int op = i.tm.operand_types[0].bitfield.class != Reg; + + /* Register goes in low 3 bits of opcode. */ + i.tm.base_opcode |= i.op[op].regs->reg_num; + if ((i.op[op].regs->reg_flags & RegRex) != 0) + i.rex |= REX_B; + if (!quiet_warnings && i.tm.opcode_modifier.ugh) + { + /* Warn about some common errors, but press on regardless. + The first case can be generated by gcc (<= 2.8.1). */ + if (i.operands == 2) + { + /* Reversed arguments on faddp, fsubp, etc. */ + as_warn (_("translating to `%s %s%s,%s%s'"), i.tm.name, + register_prefix, i.op[!intel_syntax].regs->reg_name, + register_prefix, i.op[intel_syntax].regs->reg_name); + } + else + { + /* Extraneous `l' suffix on fp insn. */ + as_warn (_("translating to `%s %s%s'"), i.tm.name, + register_prefix, i.op[0].regs->reg_name); + } + } + } if (i.tm.base_opcode == 0x8d /* lea */ && i.seg[0] @@ -7109,7 +7190,7 @@ build_modrm_byte (void) || (i.reg_operands == 3 && i.mem_operands == 1)) && i.tm.opcode_modifier.vexvvvv == VEXXDS && i.tm.opcode_modifier.vexw - && i.tm.operand_types[dest].bitfield.regsimd); + && i.tm.operand_types[dest].bitfield.class == RegSIMD); /* If VexW1 is set, the first non-immediate operand is the source and the second non-immediate one is encoded in the immediate operand. */ @@ -7133,7 +7214,7 @@ build_modrm_byte (void) i.types[i.operands] = imm8; i.operands++; - gas_assert (i.tm.operand_types[reg_slot].bitfield.regsimd); + gas_assert (i.tm.operand_types[reg_slot].bitfield.class == RegSIMD); exp->X_op = O_constant; exp->X_add_number = register_number (i.op[reg_slot].regs) << 4; gas_assert ((i.op[reg_slot].regs->reg_flags & RegVRex) == 0); @@ -7147,13 +7228,13 @@ build_modrm_byte (void) /* Turn on Imm8 again so that output_imm will generate it. */ i.types[0].bitfield.imm8 = 1; - gas_assert (i.tm.operand_types[reg_slot].bitfield.regsimd); + gas_assert (i.tm.operand_types[reg_slot].bitfield.class == RegSIMD); i.op[0].imms->X_add_number |= register_number (i.op[reg_slot].regs) << 4; gas_assert ((i.op[reg_slot].regs->reg_flags & RegVRex) == 0); } - gas_assert (i.tm.operand_types[nds].bitfield.regsimd); + gas_assert (i.tm.operand_types[nds].bitfield.class == RegSIMD); i.vex.register_specifier = i.op[nds].regs; } else @@ -7185,9 +7266,11 @@ build_modrm_byte (void) gas_assert (i.imm_operands == 1 || (i.imm_operands == 0 && (i.tm.opcode_modifier.vexvvvv == VEXXDS - || i.types[0].bitfield.shiftcount))); + || (i.types[0].bitfield.instance == RegC + && i.types[0].bitfield.byte)))); if (operand_type_check (i.types[0], imm) - || i.types[0].bitfield.shiftcount) + || (i.types[0].bitfield.instance == RegC + && i.types[0].bitfield.byte)) source = 1; else source = 0; @@ -7255,8 +7338,7 @@ build_modrm_byte (void) { /* For instructions with VexNDS, the register-only source operand must be a 32/64bit integer, XMM, YMM, ZMM, or mask - register. It is encoded in VEX prefix. We need to - clear RegMem bit before calling operand_type_equal. */ + register. It is encoded in VEX prefix. */ i386_operand_type op; unsigned int vvvv; @@ -7273,11 +7355,10 @@ build_modrm_byte (void) vvvv = dest; op = i.tm.operand_types[vvvv]; - op.bitfield.regmem = 0; if ((dest + 1) >= i.operands - || ((!op.bitfield.reg + || ((op.bitfield.class != Reg || (!op.bitfield.dword && !op.bitfield.qword)) - && !op.bitfield.regsimd + && op.bitfield.class != RegSIMD && !operand_type_equal (&op, ®mask))) abort (); i.vex.register_specifier = i.op[vvvv].regs; @@ -7286,22 +7367,22 @@ build_modrm_byte (void) } i.rm.mode = 3; - /* One of the register operands will be encoded in the i.tm.reg - field, the other in the combined i.tm.mode and i.tm.regmem + /* One of the register operands will be encoded in the i.rm.reg + field, the other in the combined i.rm.mode and i.rm.regmem fields. If no form of this instruction supports a memory destination operand, then we assume the source operand may sometimes be a memory operand and so we need to store the destination in the i.rm.reg field. */ - if (!i.tm.operand_types[dest].bitfield.regmem + if (!i.tm.opcode_modifier.regmem && operand_type_check (i.tm.operand_types[dest], anymem) == 0) { i.rm.reg = i.op[dest].regs->reg_num; i.rm.regmem = i.op[source].regs->reg_num; - if (i.op[dest].regs->reg_type.bitfield.regmmx - || i.op[source].regs->reg_type.bitfield.regmmx) + if (i.op[dest].regs->reg_type.bitfield.class == RegMMX + || i.op[source].regs->reg_type.bitfield.class == RegMMX) i.has_regmmx = TRUE; - else if (i.op[dest].regs->reg_type.bitfield.regsimd - || i.op[source].regs->reg_type.bitfield.regsimd) + else if (i.op[dest].regs->reg_type.bitfield.class == RegSIMD + || i.op[source].regs->reg_type.bitfield.class == RegSIMD) { if (i.types[dest].bitfield.zmmword || i.types[source].bitfield.zmmword) @@ -7336,7 +7417,7 @@ build_modrm_byte (void) } if (flag_code != CODE_64BIT && (i.rex & REX_R)) { - if (!i.types[i.tm.operand_types[0].bitfield.regmem].bitfield.control) + if (i.types[!i.tm.opcode_modifier.regmem].bitfield.class != RegCR) abort (); i.rex &= ~REX_R; add_prefix (LOCK_PREFIX_OPCODE); @@ -7352,7 +7433,7 @@ build_modrm_byte (void) unsigned int op; for (op = 0; op < i.operands; op++) - if (operand_type_check (i.types[op], anymem)) + if (i.flags[op] & Operand_Mem) break; gas_assert (op < i.operands); @@ -7652,15 +7733,15 @@ build_modrm_byte (void) for (op = 0; op < i.operands; op++) { - if (i.types[op].bitfield.reg - || i.types[op].bitfield.regbnd - || i.types[op].bitfield.regmask - || i.types[op].bitfield.sreg - || i.types[op].bitfield.control - || i.types[op].bitfield.debug - || i.types[op].bitfield.test) + if (i.types[op].bitfield.class == Reg + || i.types[op].bitfield.class == RegBND + || i.types[op].bitfield.class == RegMask + || i.types[op].bitfield.class == SReg + || i.types[op].bitfield.class == RegCR + || i.types[op].bitfield.class == RegDR + || i.types[op].bitfield.class == RegTR) break; - if (i.types[op].bitfield.regsimd) + if (i.types[op].bitfield.class == RegSIMD) { if (i.types[op].bitfield.zmmword) i.has_regzmm = TRUE; @@ -7670,7 +7751,7 @@ build_modrm_byte (void) i.has_regxmm = TRUE; break; } - if (i.types[op].bitfield.regmmx) + if (i.types[op].bitfield.class == RegMMX) { i.has_regmmx = TRUE; break; @@ -7734,9 +7815,9 @@ build_modrm_byte (void) { i386_operand_type *type = &i.tm.operand_types[vex_reg]; - if ((!type->bitfield.reg + if ((type->bitfield.class != Reg || (!type->bitfield.dword && !type->bitfield.qword)) - && !type->bitfield.regsimd + && type->bitfield.class != RegSIMD && !operand_type_equal (type, ®mask)) abort (); @@ -7780,6 +7861,18 @@ build_modrm_byte (void) return default_seg; } +static unsigned int +flip_code16 (unsigned int code16) +{ + gas_assert (i.tm.operands == 1); + + return !(i.prefix[REX_PREFIX] & REX_W) + && (code16 ? i.tm.operand_types[0].bitfield.disp32 + || i.tm.operand_types[0].bitfield.disp32s + : i.tm.operand_types[0].bitfield.disp16) + ? CODE16 : 0; +} + static void output_branch (void) { @@ -7799,7 +7892,7 @@ output_branch (void) { prefix = 1; i.prefixes -= 1; - code16 ^= CODE16; + code16 ^= flip_code16(code16); } /* Pentium4 branch hints. */ if (i.prefix[SEG_PREFIX] == CS_PREFIX_OPCODE /* not taken */ @@ -7817,12 +7910,12 @@ output_branch (void) /* BND prefixed jump. */ if (i.prefix[BND_PREFIX] != 0) { - FRAG_APPEND_1_CHAR (i.prefix[BND_PREFIX]); - i.prefixes -= 1; + prefix++; + i.prefixes--; } - if (i.prefixes != 0 && !intel_syntax) - as_warn (_("skipping prefixes on this instruction")); + if (i.prefixes != 0) + as_warn (_("skipping prefixes on `%s'"), i.tm.name); /* It's always a symbol; End frag & setup for relax. Make sure there is enough room in this frag for the largest @@ -7837,6 +7930,8 @@ output_branch (void) if (i.prefix[SEG_PREFIX] == CS_PREFIX_OPCODE || i.prefix[SEG_PREFIX] == DS_PREFIX_OPCODE) *p++ = i.prefix[SEG_PREFIX]; + if (i.prefix[BND_PREFIX] != 0) + *p++ = BND_PREFIX_OPCODE; if (i.prefix[REX_PREFIX] != 0) *p++ = i.prefix[REX_PREFIX]; *p = i.tm.base_opcode; @@ -7912,7 +8007,7 @@ output_jump (void) fixS *fixP; bfd_reloc_code_real_type jump_reloc = i.reloc[0]; - if (i.tm.opcode_modifier.jumpbyte) + if (i.tm.opcode_modifier.jump == JUMP_BYTE) { /* This is a loop or jecxz type instruction. */ size = 1; @@ -7941,7 +8036,7 @@ output_jump (void) { FRAG_APPEND_1_CHAR (DATA_PREFIX_OPCODE); i.prefixes -= 1; - code16 ^= CODE16; + code16 ^= flip_code16(code16); } size = 4; @@ -7949,21 +8044,21 @@ output_jump (void) size = 2; } - if (i.prefix[REX_PREFIX] != 0) + /* BND prefixed jump. */ + if (i.prefix[BND_PREFIX] != 0) { - FRAG_APPEND_1_CHAR (i.prefix[REX_PREFIX]); + FRAG_APPEND_1_CHAR (i.prefix[BND_PREFIX]); i.prefixes -= 1; } - /* BND prefixed jump. */ - if (i.prefix[BND_PREFIX] != 0) + if (i.prefix[REX_PREFIX] != 0) { - FRAG_APPEND_1_CHAR (i.prefix[BND_PREFIX]); + FRAG_APPEND_1_CHAR (i.prefix[REX_PREFIX]); i.prefixes -= 1; } - if (i.prefixes != 0 && !intel_syntax) - as_warn (_("skipping prefixes on this instruction")); + if (i.prefixes != 0) + as_warn (_("skipping prefixes on `%s'"), i.tm.name); p = frag_more (i.tm.opcode_length + size); switch (i.tm.opcode_length) @@ -8016,18 +8111,15 @@ output_interseg_jump (void) i.prefixes -= 1; code16 ^= CODE16; } - if (i.prefix[REX_PREFIX] != 0) - { - prefix++; - i.prefixes -= 1; - } + + gas_assert (!i.prefix[REX_PREFIX]); size = 4; if (code16) size = 2; - if (i.prefixes != 0 && !intel_syntax) - as_warn (_("skipping prefixes on this instruction")); + if (i.prefixes != 0) + as_warn (_("skipping prefixes on `%s'"), i.tm.name); /* 1 opcode; 2 segment; offset */ p = frag_more (prefix + 1 + 2 + size); @@ -8093,7 +8185,7 @@ x86_cleanup (void) /* Create the .note.gnu.property section. */ sec = subseg_new (NOTE_GNU_PROPERTY_SECTION_NAME, 0); - bfd_set_section_flags (stdoutput, sec, + bfd_set_section_flags (sec, (SEC_ALLOC | SEC_LOAD | SEC_DATA @@ -8111,7 +8203,7 @@ x86_cleanup (void) alignment = 2; } - bfd_set_section_alignment (stdoutput, sec, alignment); + bfd_set_section_alignment (sec, alignment); elf_section_type (sec) = SHT_NOTE; /* GNU_PROPERTY_X86_ISA_1_USED: 4-byte type + 4-byte data size @@ -8201,65 +8293,260 @@ encoding_length (const fragS *start_frag, offsetT start_off, return len - start_off + (frag_now_ptr - frag_now->fr_literal); } -static void -output_insn (void) +/* Return 1 for test, and, cmp, add, sub, inc and dec which may + be macro-fused with conditional jumps. */ + +static int +maybe_fused_with_jcc_p (void) { - fragS *insn_start_frag; - offsetT insn_start_off; + /* No RIP address. */ + if (i.base_reg && i.base_reg->reg_num == RegIP) + return 0; -#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) - if (IS_ELF && x86_used_note) - { - if (i.tm.cpu_flags.bitfield.cpucmov) - x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_CMOV; - if (i.tm.cpu_flags.bitfield.cpusse) - x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_SSE; - if (i.tm.cpu_flags.bitfield.cpusse2) - x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_SSE2; - if (i.tm.cpu_flags.bitfield.cpusse3) - x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_SSE3; - if (i.tm.cpu_flags.bitfield.cpussse3) - x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_SSSE3; - if (i.tm.cpu_flags.bitfield.cpusse4_1) - x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_SSE4_1; - if (i.tm.cpu_flags.bitfield.cpusse4_2) - x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_SSE4_2; - if (i.tm.cpu_flags.bitfield.cpuavx) - x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX; - if (i.tm.cpu_flags.bitfield.cpuavx2) - x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX2; - if (i.tm.cpu_flags.bitfield.cpufma) - x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_FMA; - if (i.tm.cpu_flags.bitfield.cpuavx512f) - x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512F; - if (i.tm.cpu_flags.bitfield.cpuavx512cd) - x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512CD; - if (i.tm.cpu_flags.bitfield.cpuavx512er) - x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512ER; - if (i.tm.cpu_flags.bitfield.cpuavx512pf) - x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512PF; - if (i.tm.cpu_flags.bitfield.cpuavx512vl) - x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512VL; - if (i.tm.cpu_flags.bitfield.cpuavx512dq) - x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512DQ; - if (i.tm.cpu_flags.bitfield.cpuavx512bw) - x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512BW; - if (i.tm.cpu_flags.bitfield.cpuavx512_4fmaps) - x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512_4FMAPS; - if (i.tm.cpu_flags.bitfield.cpuavx512_4vnniw) - x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512_4VNNIW; - if (i.tm.cpu_flags.bitfield.cpuavx512_bitalg) - x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512_BITALG; - if (i.tm.cpu_flags.bitfield.cpuavx512ifma) - x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512_IFMA; - if (i.tm.cpu_flags.bitfield.cpuavx512vbmi) - x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512_VBMI; - if (i.tm.cpu_flags.bitfield.cpuavx512_vbmi2) - x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512_VBMI2; - if (i.tm.cpu_flags.bitfield.cpuavx512_vnni) - x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512_VNNI; - if (i.tm.cpu_flags.bitfield.cpuavx512_bf16) - x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512_BF16; + /* No VEX/EVEX encoding. */ + if (is_any_vex_encoding (&i.tm)) + return 0; + + /* and, add, sub with destination register. */ + if ((i.tm.base_opcode >= 0x20 && i.tm.base_opcode <= 0x25) + || i.tm.base_opcode <= 5 + || (i.tm.base_opcode >= 0x28 && i.tm.base_opcode <= 0x2d) + || ((i.tm.base_opcode | 3) == 0x83 + && ((i.tm.extension_opcode | 1) == 0x5 + || i.tm.extension_opcode == 0x0))) + return (i.types[1].bitfield.class == Reg + || i.types[1].bitfield.instance == Accum); + + /* test, cmp with any register. */ + if ((i.tm.base_opcode | 1) == 0x85 + || (i.tm.base_opcode | 1) == 0xa9 + || ((i.tm.base_opcode | 1) == 0xf7 + && i.tm.extension_opcode == 0) + || (i.tm.base_opcode >= 0x38 && i.tm.base_opcode <= 0x3d) + || ((i.tm.base_opcode | 3) == 0x83 + && (i.tm.extension_opcode == 0x7))) + return (i.types[0].bitfield.class == Reg + || i.types[0].bitfield.instance == Accum + || i.types[1].bitfield.class == Reg + || i.types[1].bitfield.instance == Accum); + + /* inc, dec with any register. */ + if ((i.tm.cpu_flags.bitfield.cpuno64 + && (i.tm.base_opcode | 0xf) == 0x4f) + || ((i.tm.base_opcode | 1) == 0xff + && i.tm.extension_opcode <= 0x1)) + return (i.types[0].bitfield.class == Reg + || i.types[0].bitfield.instance == Accum); + + return 0; +} + +/* Return 1 if a FUSED_JCC_PADDING frag should be generated. */ + +static int +add_fused_jcc_padding_frag_p (void) +{ + /* NB: Don't work with COND_JUMP86 without i386. */ + if (!align_branch_power + || now_seg == absolute_section + || !cpu_arch_flags.bitfield.cpui386 + || !(align_branch & align_branch_fused_bit)) + return 0; + + if (maybe_fused_with_jcc_p ()) + { + if (last_insn.kind == last_insn_other + || last_insn.seg != now_seg) + return 1; + if (flag_debug) + as_warn_where (last_insn.file, last_insn.line, + _("`%s` skips -malign-branch-boundary on `%s`"), + last_insn.name, i.tm.name); + } + + return 0; +} + +/* Return 1 if a BRANCH_PREFIX frag should be generated. */ + +static int +add_branch_prefix_frag_p (void) +{ + /* NB: Don't work with COND_JUMP86 without i386. Don't add prefix + to PadLock instructions since they include prefixes in opcode. */ + if (!align_branch_power + || !align_branch_prefix_size + || now_seg == absolute_section + || i.tm.cpu_flags.bitfield.cpupadlock + || !cpu_arch_flags.bitfield.cpui386) + return 0; + + /* Don't add prefix if it is a prefix or there is no operand in case + that segment prefix is special. */ + if (!i.operands || i.tm.opcode_modifier.isprefix) + return 0; + + if (last_insn.kind == last_insn_other + || last_insn.seg != now_seg) + return 1; + + if (flag_debug) + as_warn_where (last_insn.file, last_insn.line, + _("`%s` skips -malign-branch-boundary on `%s`"), + last_insn.name, i.tm.name); + + return 0; +} + +/* Return 1 if a BRANCH_PADDING frag should be generated. */ + +static int +add_branch_padding_frag_p (enum align_branch_kind *branch_p) +{ + int add_padding; + + /* NB: Don't work with COND_JUMP86 without i386. */ + if (!align_branch_power + || now_seg == absolute_section + || !cpu_arch_flags.bitfield.cpui386) + return 0; + + add_padding = 0; + + /* Check for jcc and direct jmp. */ + if (i.tm.opcode_modifier.jump == JUMP) + { + if (i.tm.base_opcode == JUMP_PC_RELATIVE) + { + *branch_p = align_branch_jmp; + add_padding = align_branch & align_branch_jmp_bit; + } + else + { + *branch_p = align_branch_jcc; + if ((align_branch & align_branch_jcc_bit)) + add_padding = 1; + } + } + else if (is_any_vex_encoding (&i.tm)) + return 0; + else if ((i.tm.base_opcode | 1) == 0xc3) + { + /* Near ret. */ + *branch_p = align_branch_ret; + if ((align_branch & align_branch_ret_bit)) + add_padding = 1; + } + else + { + /* Check for indirect jmp, direct and indirect calls. */ + if (i.tm.base_opcode == 0xe8) + { + /* Direct call. */ + *branch_p = align_branch_call; + if ((align_branch & align_branch_call_bit)) + add_padding = 1; + } + else if (i.tm.base_opcode == 0xff + && (i.tm.extension_opcode == 2 + || i.tm.extension_opcode == 4)) + { + /* Indirect call and jmp. */ + *branch_p = align_branch_indirect; + if ((align_branch & align_branch_indirect_bit)) + add_padding = 1; + } + + if (add_padding + && i.disp_operands + && tls_get_addr + && (i.op[0].disps->X_op == O_symbol + || (i.op[0].disps->X_op == O_subtract + && i.op[0].disps->X_op_symbol == GOT_symbol))) + { + symbolS *s = i.op[0].disps->X_add_symbol; + /* No padding to call to global or undefined tls_get_addr. */ + if ((S_IS_EXTERNAL (s) || !S_IS_DEFINED (s)) + && strcmp (S_GET_NAME (s), tls_get_addr) == 0) + return 0; + } + } + + if (add_padding + && last_insn.kind != last_insn_other + && last_insn.seg == now_seg) + { + if (flag_debug) + as_warn_where (last_insn.file, last_insn.line, + _("`%s` skips -malign-branch-boundary on `%s`"), + last_insn.name, i.tm.name); + return 0; + } + + return add_padding; +} + +static void +output_insn (void) +{ + fragS *insn_start_frag; + offsetT insn_start_off; + fragS *fragP = NULL; + enum align_branch_kind branch = align_branch_none; + +#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) + if (IS_ELF && x86_used_note) + { + if (i.tm.cpu_flags.bitfield.cpucmov) + x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_CMOV; + if (i.tm.cpu_flags.bitfield.cpusse) + x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_SSE; + if (i.tm.cpu_flags.bitfield.cpusse2) + x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_SSE2; + if (i.tm.cpu_flags.bitfield.cpusse3) + x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_SSE3; + if (i.tm.cpu_flags.bitfield.cpussse3) + x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_SSSE3; + if (i.tm.cpu_flags.bitfield.cpusse4_1) + x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_SSE4_1; + if (i.tm.cpu_flags.bitfield.cpusse4_2) + x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_SSE4_2; + if (i.tm.cpu_flags.bitfield.cpuavx) + x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX; + if (i.tm.cpu_flags.bitfield.cpuavx2) + x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX2; + if (i.tm.cpu_flags.bitfield.cpufma) + x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_FMA; + if (i.tm.cpu_flags.bitfield.cpuavx512f) + x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512F; + if (i.tm.cpu_flags.bitfield.cpuavx512cd) + x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512CD; + if (i.tm.cpu_flags.bitfield.cpuavx512er) + x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512ER; + if (i.tm.cpu_flags.bitfield.cpuavx512pf) + x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512PF; + if (i.tm.cpu_flags.bitfield.cpuavx512vl) + x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512VL; + if (i.tm.cpu_flags.bitfield.cpuavx512dq) + x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512DQ; + if (i.tm.cpu_flags.bitfield.cpuavx512bw) + x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512BW; + if (i.tm.cpu_flags.bitfield.cpuavx512_4fmaps) + x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512_4FMAPS; + if (i.tm.cpu_flags.bitfield.cpuavx512_4vnniw) + x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512_4VNNIW; + if (i.tm.cpu_flags.bitfield.cpuavx512_bitalg) + x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512_BITALG; + if (i.tm.cpu_flags.bitfield.cpuavx512ifma) + x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512_IFMA; + if (i.tm.cpu_flags.bitfield.cpuavx512vbmi) + x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512_VBMI; + if (i.tm.cpu_flags.bitfield.cpuavx512_vbmi2) + x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512_VBMI2; + if (i.tm.cpu_flags.bitfield.cpuavx512_vnni) + x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512_VNNI; + if (i.tm.cpu_flags.bitfield.cpuavx512_bf16) + x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512_BF16; if (i.tm.cpu_flags.bitfield.cpu8087 || i.tm.cpu_flags.bitfield.cpu287 @@ -8267,15 +8554,9 @@ output_insn (void) || i.tm.cpu_flags.bitfield.cpu687 || i.tm.cpu_flags.bitfield.cpufisttp) x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_X87; - /* Don't set GNU_PROPERTY_X86_FEATURE_2_MMX for prefetchtXXX nor - Xfence instructions. */ - if (i.tm.base_opcode != 0xf18 - && i.tm.base_opcode != 0xf0d - && i.tm.base_opcode != 0xfaef8 - && (i.has_regmmx - || i.tm.cpu_flags.bitfield.cpummx - || i.tm.cpu_flags.bitfield.cpua3dnow - || i.tm.cpu_flags.bitfield.cpua3dnowa)) + if (i.has_regmmx + || i.tm.base_opcode == 0xf77 /* emms */ + || i.tm.base_opcode == 0xf0e /* femms */) x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_MMX; if (i.has_regxmm) x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_XMM; @@ -8302,13 +8583,38 @@ output_insn (void) insn_start_frag = frag_now; insn_start_off = frag_now_fix (); + if (add_branch_padding_frag_p (&branch)) + { + char *p; + /* Branch can be 8 bytes. Leave some room for prefixes. */ + unsigned int max_branch_padding_size = 14; + + /* Align section to boundary. */ + record_alignment (now_seg, align_branch_power); + + /* Make room for padding. */ + frag_grow (max_branch_padding_size); + + /* Start of the padding. */ + p = frag_more (0); + + fragP = frag_now; + + frag_var (rs_machine_dependent, max_branch_padding_size, 0, + ENCODE_RELAX_STATE (BRANCH_PADDING, 0), + NULL, 0, p); + + fragP->tc_frag_data.branch_type = branch; + fragP->tc_frag_data.max_bytes = max_branch_padding_size; + } + /* Output jumps. */ - if (i.tm.opcode_modifier.jump) + if (i.tm.opcode_modifier.jump == JUMP) output_branch (); - else if (i.tm.opcode_modifier.jumpbyte - || i.tm.opcode_modifier.jumpdword) + else if (i.tm.opcode_modifier.jump == JUMP_BYTE + || i.tm.opcode_modifier.jump == JUMP_DWORD) output_jump (); - else if (i.tm.opcode_modifier.jumpintersegment) + else if (i.tm.opcode_modifier.jump == JUMP_INTERSEGMENT) output_interseg_jump (); else { @@ -8340,6 +8646,41 @@ output_insn (void) i.prefix[LOCK_PREFIX] = 0; } + if (branch) + /* Skip if this is a branch. */ + ; + else if (add_fused_jcc_padding_frag_p ()) + { + /* Make room for padding. */ + frag_grow (MAX_FUSED_JCC_PADDING_SIZE); + p = frag_more (0); + + fragP = frag_now; + + frag_var (rs_machine_dependent, MAX_FUSED_JCC_PADDING_SIZE, 0, + ENCODE_RELAX_STATE (FUSED_JCC_PADDING, 0), + NULL, 0, p); + + fragP->tc_frag_data.branch_type = align_branch_fused; + fragP->tc_frag_data.max_bytes = MAX_FUSED_JCC_PADDING_SIZE; + } + else if (add_branch_prefix_frag_p ()) + { + unsigned int max_prefix_size = align_branch_prefix_size; + + /* Make room for padding. */ + frag_grow (max_prefix_size); + p = frag_more (0); + + fragP = frag_now; + + frag_var (rs_machine_dependent, max_prefix_size, 0, + ENCODE_RELAX_STATE (BRANCH_PREFIX, 0), + NULL, 0, p); + + fragP->tc_frag_data.max_bytes = max_prefix_size; + } + /* 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) @@ -8487,9 +8828,105 @@ output_insn (void) if (j > 15) as_warn (_("instruction length of %u bytes exceeds the limit of 15"), j); + else if (fragP) + { + /* NB: Don't add prefix with GOTPC relocation since + output_disp() above depends on the fixed encoding + length. Can't add prefix with TLS relocation since + it breaks TLS linker optimization. */ + unsigned int max = i.has_gotpc_tls_reloc ? 0 : 15 - j; + /* Prefix count on the current instruction. */ + unsigned int count = i.vex.length; + unsigned int k; + for (k = 0; k < ARRAY_SIZE (i.prefix); k++) + /* REX byte is encoded in VEX/EVEX prefix. */ + if (i.prefix[k] && (k != REX_PREFIX || !i.vex.length)) + count++; + + /* Count prefixes for extended opcode maps. */ + if (!i.vex.length) + switch (i.tm.opcode_length) + { + case 3: + if (((i.tm.base_opcode >> 16) & 0xff) == 0xf) + { + count++; + switch ((i.tm.base_opcode >> 8) & 0xff) + { + case 0x38: + case 0x3a: + count++; + break; + default: + break; + } + } + break; + case 2: + if (((i.tm.base_opcode >> 8) & 0xff) == 0xf) + count++; + break; + case 1: + break; + default: + abort (); + } + + if (TYPE_FROM_RELAX_STATE (fragP->fr_subtype) + == BRANCH_PREFIX) + { + /* Set the maximum prefix size in BRANCH_PREFIX + frag. */ + if (fragP->tc_frag_data.max_bytes > max) + fragP->tc_frag_data.max_bytes = max; + if (fragP->tc_frag_data.max_bytes > count) + fragP->tc_frag_data.max_bytes -= count; + else + fragP->tc_frag_data.max_bytes = 0; + } + else + { + /* Remember the maximum prefix size in FUSED_JCC_PADDING + frag. */ + unsigned int max_prefix_size; + if (align_branch_prefix_size > max) + max_prefix_size = max; + else + max_prefix_size = align_branch_prefix_size; + if (max_prefix_size > count) + fragP->tc_frag_data.max_prefix_length + = max_prefix_size - count; + } + + /* Use existing segment prefix if possible. Use CS + segment prefix in 64-bit mode. In 32-bit mode, use SS + segment prefix with ESP/EBP base register and use DS + segment prefix without ESP/EBP base register. */ + if (i.prefix[SEG_PREFIX]) + fragP->tc_frag_data.default_prefix = i.prefix[SEG_PREFIX]; + else if (flag_code == CODE_64BIT) + fragP->tc_frag_data.default_prefix = CS_PREFIX_OPCODE; + else if (i.base_reg + && (i.base_reg->reg_num == 4 + || i.base_reg->reg_num == 5)) + fragP->tc_frag_data.default_prefix = SS_PREFIX_OPCODE; + else + fragP->tc_frag_data.default_prefix = DS_PREFIX_OPCODE; + } } } + /* NB: Don't work with COND_JUMP86 without i386. */ + if (align_branch_power + && now_seg != absolute_section + && cpu_arch_flags.bitfield.cpui386) + { + /* Terminate each frag so that we can add prefix and check for + fused jcc. */ + frag_wane (frag_now); + frag_new (0); + } + #ifdef DEBUG386 if (flag_debug) { @@ -8599,6 +9036,7 @@ output_disp (fragS *insn_start_frag, offsetT insn_start_off) if (!object_64bit) { reloc_type = BFD_RELOC_386_GOTPC; + i.has_gotpc_tls_reloc = TRUE; i.op[n].imms->X_add_number += encoding_length (insn_start_frag, insn_start_off, p); } @@ -8610,6 +9048,27 @@ 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; } + else if (align_branch_power) + { + switch (reloc_type) + { + case BFD_RELOC_386_TLS_GD: + case BFD_RELOC_386_TLS_LDM: + case BFD_RELOC_386_TLS_IE: + case BFD_RELOC_386_TLS_IE_32: + case BFD_RELOC_386_TLS_GOTIE: + case BFD_RELOC_386_TLS_GOTDESC: + case BFD_RELOC_386_TLS_DESC_CALL: + case BFD_RELOC_X86_64_TLSGD: + case BFD_RELOC_X86_64_TLSLD: + case BFD_RELOC_X86_64_GOTTPOFF: + case BFD_RELOC_X86_64_GOTPC32_TLSDESC: + case BFD_RELOC_X86_64_TLSDESC_CALL: + i.has_gotpc_tls_reloc = TRUE; + default: + break; + } + } fixP = fix_new_exp (frag_now, p - frag_now->fr_literal, size, i.op[n].disps, pcrel, reloc_type); @@ -8751,6 +9210,7 @@ output_imm (fragS *insn_start_frag, offsetT insn_start_off) reloc_type = BFD_RELOC_X86_64_GOTPC32; else if (size == 8) reloc_type = BFD_RELOC_X86_64_GOTPC64; + i.has_gotpc_tls_reloc = TRUE; i.op[n].imms->X_add_number += encoding_length (insn_start_frag, insn_start_off, p); } @@ -9209,7 +9669,7 @@ check_VecOperations (char *op_string, char *op_end) else if ((mask = parse_register (op_string, &end_op)) != NULL) { /* k0 can't be used for write mask. */ - if (!mask->reg_type.bitfield.regmask || mask->reg_num == 0) + if (mask->reg_type.bitfield.class != RegMask || !mask->reg_num) { as_bad (_("`%s%s' can't be used for write mask"), register_prefix, mask->reg_name); @@ -9487,11 +9947,12 @@ i386_displacement (char *disp_start, char *disp_end) } operand_type_set (&bigdisp, 0); - if ((i.types[this_operand].bitfield.jumpabsolute) - || (!current_templates->start->opcode_modifier.jump - && !current_templates->start->opcode_modifier.jumpdword)) + if (i.jumpabsolute + || i.types[this_operand].bitfield.baseindex + || (current_templates->start->opcode_modifier.jump != JUMP + && current_templates->start->opcode_modifier.jump != JUMP_DWORD)) { - bigdisp.bitfield.disp32 = 1; + i386_addressing_mode (); override = (i.prefix[ADDR_PREFIX] != 0); if (flag_code == CODE_64BIT) { @@ -9500,27 +9961,47 @@ i386_displacement (char *disp_start, char *disp_end) bigdisp.bitfield.disp32s = 1; bigdisp.bitfield.disp64 = 1; } + else + bigdisp.bitfield.disp32 = 1; } else if ((flag_code == CODE_16BIT) ^ override) - { - bigdisp.bitfield.disp32 = 0; bigdisp.bitfield.disp16 = 1; - } + else + bigdisp.bitfield.disp32 = 1; } else { - /* For PC-relative branches, the width of the displacement - is dependent upon data size, not address size. */ + /* For PC-relative branches, the width of the displacement may be + dependent upon data size, but is never dependent upon address size. + Also make sure to not unintentionally match against a non-PC-relative + branch template. */ + static templates aux_templates; + const insn_template *t = current_templates->start; + bfd_boolean has_intel64 = FALSE; + + aux_templates.start = t; + while (++t < current_templates->end) + { + if (t->opcode_modifier.jump + != current_templates->start->opcode_modifier.jump) + break; + if (t->opcode_modifier.intel64) + has_intel64 = TRUE; + } + if (t < current_templates->end) + { + aux_templates.end = t; + current_templates = &aux_templates; + } + override = (i.prefix[DATA_PREFIX] != 0); if (flag_code == CODE_64BIT) { - if (override || i.suffix == WORD_MNEM_SUFFIX) + if ((override || i.suffix == WORD_MNEM_SUFFIX) + && (!intel64 || !has_intel64)) bigdisp.bitfield.disp16 = 1; else - { - bigdisp.bitfield.disp32 = 1; - bigdisp.bitfield.disp32s = 1; - } + bigdisp.bitfield.disp32s = 1; } else { @@ -9693,6 +10174,11 @@ i386_finalize_displacement (segT exp_seg ATTRIBUTE_UNUSED, expressionS *exp, } #endif + if (current_templates->start->opcode_modifier.jump == JUMP_BYTE + /* Constants get taken care of by optimize_disp(). */ + && exp->X_op != O_constant) + i.types[this_operand].bitfield.disp8 = 1; + /* Check if this is a displacement only operand. */ bigdisp = i.types[this_operand]; bigdisp.bitfield.disp8 = 0; @@ -9792,16 +10278,16 @@ i386_index_check (const char *operand_string) if (current_templates->start->opcode_modifier.repprefixok) { - i386_operand_type type = current_templates->end[-1].operand_types[0]; + int es_op = current_templates->end[-1].opcode_modifier.isstring + - IS_STRING_ES_OP0; + int op = 0; - if (!type.bitfield.baseindex + if (!current_templates->end[-1].operand_types[0].bitfield.baseindex || ((!i.mem_operands != !intel_syntax) && current_templates->end[-1].operand_types[1] .bitfield.baseindex)) - type = current_templates->end[-1].operand_types[1]; - expected_reg = hash_find (reg_hash, - di_si[addr_mode][type.bitfield.esseg]); - + op = 1; + expected_reg = hash_find (reg_hash, di_si[addr_mode][op == es_op]); } else expected_reg = hash_find (reg_hash, bx[addr_mode]); @@ -10018,7 +10504,7 @@ i386_att_operand (char *operand_string) ++op_string; if (is_space_char (*op_string)) ++op_string; - i.types[this_operand].bitfield.jumpabsolute = 1; + i.jumpabsolute = TRUE; } /* Check if operand is a register. */ @@ -10031,7 +10517,7 @@ i386_att_operand (char *operand_string) op_string = end_op; if (is_space_char (*op_string)) ++op_string; - if (*op_string == ':' && r->reg_type.bitfield.sreg) + if (*op_string == ':' && r->reg_type.bitfield.class == SReg) { switch (r->reg_num) { @@ -10074,7 +10560,7 @@ i386_att_operand (char *operand_string) ++op_string; if (is_space_char (*op_string)) ++op_string; - i.types[this_operand].bitfield.jumpabsolute = 1; + i.jumpabsolute = TRUE; } goto do_memory_reference; } @@ -10108,7 +10594,7 @@ i386_att_operand (char *operand_string) else if (*op_string == IMMEDIATE_PREFIX) { ++op_string; - if (i.types[this_operand].bitfield.jumpabsolute) + if (i.jumpabsolute) { as_bad (_("immediate operand illegal with absolute jump")); return 0; @@ -10300,7 +10786,8 @@ i386_att_operand (char *operand_string) /* Special case for (%dx) while doing input/output op. */ if (i.base_reg - && i.base_reg->reg_type.bitfield.inoutportreg + && i.base_reg->reg_type.bitfield.instance == RegD + && i.base_reg->reg_type.bitfield.word && i.index_reg == 0 && i.log2_scale_factor == 0 && i.seg[i.mem_operands] == 0 @@ -10375,6 +10862,362 @@ elf_symbol_resolved_in_segment_p (symbolS *fr_symbol, offsetT fr_var) } #endif +/* Return the next non-empty frag. */ + +static fragS * +i386_next_non_empty_frag (fragS *fragP) +{ + /* There may be a frag with a ".fill 0" when there is no room in + the current frag for frag_grow in output_insn. */ + for (fragP = fragP->fr_next; + (fragP != NULL + && fragP->fr_type == rs_fill + && fragP->fr_fix == 0); + fragP = fragP->fr_next) + ; + return fragP; +} + +/* Return the next jcc frag after BRANCH_PADDING. */ + +static fragS * +i386_next_jcc_frag (fragS *fragP) +{ + if (!fragP) + return NULL; + + if (fragP->fr_type == rs_machine_dependent + && (TYPE_FROM_RELAX_STATE (fragP->fr_subtype) + == BRANCH_PADDING)) + { + fragP = i386_next_non_empty_frag (fragP); + if (fragP->fr_type != rs_machine_dependent) + return NULL; + if (TYPE_FROM_RELAX_STATE (fragP->fr_subtype) == COND_JUMP) + return fragP; + } + + return NULL; +} + +/* Classify BRANCH_PADDING, BRANCH_PREFIX and FUSED_JCC_PADDING frags. */ + +static void +i386_classify_machine_dependent_frag (fragS *fragP) +{ + fragS *cmp_fragP; + fragS *pad_fragP; + fragS *branch_fragP; + fragS *next_fragP; + unsigned int max_prefix_length; + + if (fragP->tc_frag_data.classified) + return; + + /* First scan for BRANCH_PADDING and FUSED_JCC_PADDING. Convert + FUSED_JCC_PADDING and merge BRANCH_PADDING. */ + for (next_fragP = fragP; + next_fragP != NULL; + next_fragP = next_fragP->fr_next) + { + next_fragP->tc_frag_data.classified = 1; + if (next_fragP->fr_type == rs_machine_dependent) + switch (TYPE_FROM_RELAX_STATE (next_fragP->fr_subtype)) + { + case BRANCH_PADDING: + /* The BRANCH_PADDING frag must be followed by a branch + frag. */ + branch_fragP = i386_next_non_empty_frag (next_fragP); + next_fragP->tc_frag_data.u.branch_fragP = branch_fragP; + break; + case FUSED_JCC_PADDING: + /* Check if this is a fused jcc: + FUSED_JCC_PADDING + CMP like instruction + BRANCH_PADDING + COND_JUMP + */ + cmp_fragP = i386_next_non_empty_frag (next_fragP); + pad_fragP = i386_next_non_empty_frag (cmp_fragP); + branch_fragP = i386_next_jcc_frag (pad_fragP); + if (branch_fragP) + { + /* The BRANCH_PADDING frag is merged with the + FUSED_JCC_PADDING frag. */ + next_fragP->tc_frag_data.u.branch_fragP = branch_fragP; + /* CMP like instruction size. */ + next_fragP->tc_frag_data.cmp_size = cmp_fragP->fr_fix; + frag_wane (pad_fragP); + /* Skip to branch_fragP. */ + next_fragP = branch_fragP; + } + else if (next_fragP->tc_frag_data.max_prefix_length) + { + /* Turn FUSED_JCC_PADDING into BRANCH_PREFIX if it isn't + a fused jcc. */ + next_fragP->fr_subtype + = ENCODE_RELAX_STATE (BRANCH_PREFIX, 0); + next_fragP->tc_frag_data.max_bytes + = next_fragP->tc_frag_data.max_prefix_length; + /* This will be updated in the BRANCH_PREFIX scan. */ + next_fragP->tc_frag_data.max_prefix_length = 0; + } + else + frag_wane (next_fragP); + break; + } + } + + /* Stop if there is no BRANCH_PREFIX. */ + if (!align_branch_prefix_size) + return; + + /* Scan for BRANCH_PREFIX. */ + for (; fragP != NULL; fragP = fragP->fr_next) + { + if (fragP->fr_type != rs_machine_dependent + || (TYPE_FROM_RELAX_STATE (fragP->fr_subtype) + != BRANCH_PREFIX)) + continue; + + /* Count all BRANCH_PREFIX frags before BRANCH_PADDING and + COND_JUMP_PREFIX. */ + max_prefix_length = 0; + for (next_fragP = fragP; + next_fragP != NULL; + next_fragP = next_fragP->fr_next) + { + if (next_fragP->fr_type == rs_fill) + /* Skip rs_fill frags. */ + continue; + else if (next_fragP->fr_type != rs_machine_dependent) + /* Stop for all other frags. */ + break; + + /* rs_machine_dependent frags. */ + if (TYPE_FROM_RELAX_STATE (next_fragP->fr_subtype) + == BRANCH_PREFIX) + { + /* Count BRANCH_PREFIX frags. */ + if (max_prefix_length >= MAX_FUSED_JCC_PADDING_SIZE) + { + max_prefix_length = MAX_FUSED_JCC_PADDING_SIZE; + frag_wane (next_fragP); + } + else + max_prefix_length + += next_fragP->tc_frag_data.max_bytes; + } + else if ((TYPE_FROM_RELAX_STATE (next_fragP->fr_subtype) + == BRANCH_PADDING) + || (TYPE_FROM_RELAX_STATE (next_fragP->fr_subtype) + == FUSED_JCC_PADDING)) + { + /* Stop at BRANCH_PADDING and FUSED_JCC_PADDING. */ + fragP->tc_frag_data.u.padding_fragP = next_fragP; + break; + } + else + /* Stop for other rs_machine_dependent frags. */ + break; + } + + fragP->tc_frag_data.max_prefix_length = max_prefix_length; + + /* Skip to the next frag. */ + fragP = next_fragP; + } +} + +/* Compute padding size for + + FUSED_JCC_PADDING + CMP like instruction + BRANCH_PADDING + COND_JUMP/UNCOND_JUMP + + or + + BRANCH_PADDING + COND_JUMP/UNCOND_JUMP + */ + +static int +i386_branch_padding_size (fragS *fragP, offsetT address) +{ + unsigned int offset, size, padding_size; + fragS *branch_fragP = fragP->tc_frag_data.u.branch_fragP; + + /* The start address of the BRANCH_PADDING or FUSED_JCC_PADDING frag. */ + if (!address) + address = fragP->fr_address; + address += fragP->fr_fix; + + /* CMP like instrunction size. */ + size = fragP->tc_frag_data.cmp_size; + + /* The base size of the branch frag. */ + size += branch_fragP->fr_fix; + + /* Add opcode and displacement bytes for the rs_machine_dependent + branch frag. */ + if (branch_fragP->fr_type == rs_machine_dependent) + size += md_relax_table[branch_fragP->fr_subtype].rlx_length; + + /* Check if branch is within boundary and doesn't end at the last + byte. */ + offset = address & ((1U << align_branch_power) - 1); + if ((offset + size) >= (1U << align_branch_power)) + /* Padding needed to avoid crossing boundary. */ + padding_size = (1U << align_branch_power) - offset; + else + /* No padding needed. */ + padding_size = 0; + + /* The return value may be saved in tc_frag_data.length which is + unsigned byte. */ + if (!fits_in_unsigned_byte (padding_size)) + abort (); + + return padding_size; +} + +/* i386_generic_table_relax_frag() + + Handle BRANCH_PADDING, BRANCH_PREFIX and FUSED_JCC_PADDING frags to + grow/shrink padding to align branch frags. Hand others to + relax_frag(). */ + +long +i386_generic_table_relax_frag (segT segment, fragS *fragP, long stretch) +{ + if (TYPE_FROM_RELAX_STATE (fragP->fr_subtype) == BRANCH_PADDING + || TYPE_FROM_RELAX_STATE (fragP->fr_subtype) == FUSED_JCC_PADDING) + { + long padding_size = i386_branch_padding_size (fragP, 0); + long grow = padding_size - fragP->tc_frag_data.length; + + /* When the BRANCH_PREFIX frag is used, the computed address + must match the actual address and there should be no padding. */ + if (fragP->tc_frag_data.padding_address + && (fragP->tc_frag_data.padding_address != fragP->fr_address + || padding_size)) + abort (); + + /* Update the padding size. */ + if (grow) + fragP->tc_frag_data.length = padding_size; + + return grow; + } + else if (TYPE_FROM_RELAX_STATE (fragP->fr_subtype) == BRANCH_PREFIX) + { + fragS *padding_fragP, *next_fragP; + long padding_size, left_size, last_size; + + padding_fragP = fragP->tc_frag_data.u.padding_fragP; + if (!padding_fragP) + /* Use the padding set by the leading BRANCH_PREFIX frag. */ + return (fragP->tc_frag_data.length + - fragP->tc_frag_data.last_length); + + /* Compute the relative address of the padding frag in the very + first time where the BRANCH_PREFIX frag sizes are zero. */ + if (!fragP->tc_frag_data.padding_address) + fragP->tc_frag_data.padding_address + = padding_fragP->fr_address - (fragP->fr_address - stretch); + + /* First update the last length from the previous interation. */ + left_size = fragP->tc_frag_data.prefix_length; + for (next_fragP = fragP; + next_fragP != padding_fragP; + next_fragP = next_fragP->fr_next) + if (next_fragP->fr_type == rs_machine_dependent + && (TYPE_FROM_RELAX_STATE (next_fragP->fr_subtype) + == BRANCH_PREFIX)) + { + if (left_size) + { + int max = next_fragP->tc_frag_data.max_bytes; + if (max) + { + int size; + if (max > left_size) + size = left_size; + else + size = max; + left_size -= size; + next_fragP->tc_frag_data.last_length = size; + } + } + else + next_fragP->tc_frag_data.last_length = 0; + } + + /* Check the padding size for the padding frag. */ + padding_size = i386_branch_padding_size + (padding_fragP, (fragP->fr_address + + fragP->tc_frag_data.padding_address)); + + last_size = fragP->tc_frag_data.prefix_length; + /* Check if there is change from the last interation. */ + if (padding_size == last_size) + { + /* Update the expected address of the padding frag. */ + padding_fragP->tc_frag_data.padding_address + = (fragP->fr_address + padding_size + + fragP->tc_frag_data.padding_address); + return 0; + } + + if (padding_size > fragP->tc_frag_data.max_prefix_length) + { + /* No padding if there is no sufficient room. Clear the + expected address of the padding frag. */ + padding_fragP->tc_frag_data.padding_address = 0; + padding_size = 0; + } + else + /* Store the expected address of the padding frag. */ + padding_fragP->tc_frag_data.padding_address + = (fragP->fr_address + padding_size + + fragP->tc_frag_data.padding_address); + + fragP->tc_frag_data.prefix_length = padding_size; + + /* Update the length for the current interation. */ + left_size = padding_size; + for (next_fragP = fragP; + next_fragP != padding_fragP; + next_fragP = next_fragP->fr_next) + if (next_fragP->fr_type == rs_machine_dependent + && (TYPE_FROM_RELAX_STATE (next_fragP->fr_subtype) + == BRANCH_PREFIX)) + { + if (left_size) + { + int max = next_fragP->tc_frag_data.max_bytes; + if (max) + { + int size; + if (max > left_size) + size = left_size; + else + size = max; + left_size -= size; + next_fragP->tc_frag_data.length = size; + } + } + else + next_fragP->tc_frag_data.length = 0; + } + + return (fragP->tc_frag_data.length + - fragP->tc_frag_data.last_length); + } + return relax_frag (segment, fragP, stretch); +} + /* md_estimate_size_before_relax() Called just before relax() for rs_machine_dependent frags. The x86 @@ -10391,6 +11234,14 @@ elf_symbol_resolved_in_segment_p (symbolS *fr_symbol, offsetT fr_var) int md_estimate_size_before_relax (fragS *fragP, segT segment) { + if (TYPE_FROM_RELAX_STATE (fragP->fr_subtype) == BRANCH_PADDING + || TYPE_FROM_RELAX_STATE (fragP->fr_subtype) == BRANCH_PREFIX + || TYPE_FROM_RELAX_STATE (fragP->fr_subtype) == FUSED_JCC_PADDING) + { + i386_classify_machine_dependent_frag (fragP); + return fragP->tc_frag_data.length; + } + /* We've already got fragP->fr_subtype right; all we have to do is check for un-relaxable symbols. On an ELF system, we can't relax an externally visible symbol, because it may be overridden by a @@ -10524,6 +11375,106 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, unsigned int extension = 0; offsetT displacement_from_opcode_start; + if (TYPE_FROM_RELAX_STATE (fragP->fr_subtype) == BRANCH_PADDING + || TYPE_FROM_RELAX_STATE (fragP->fr_subtype) == FUSED_JCC_PADDING + || TYPE_FROM_RELAX_STATE (fragP->fr_subtype) == BRANCH_PREFIX) + { + /* Generate nop padding. */ + unsigned int size = fragP->tc_frag_data.length; + if (size) + { + if (size > fragP->tc_frag_data.max_bytes) + abort (); + + if (flag_debug) + { + const char *msg; + const char *branch = "branch"; + const char *prefix = ""; + fragS *padding_fragP; + if (TYPE_FROM_RELAX_STATE (fragP->fr_subtype) + == BRANCH_PREFIX) + { + padding_fragP = fragP->tc_frag_data.u.padding_fragP; + switch (fragP->tc_frag_data.default_prefix) + { + default: + abort (); + break; + case CS_PREFIX_OPCODE: + prefix = " cs"; + break; + case DS_PREFIX_OPCODE: + prefix = " ds"; + break; + case ES_PREFIX_OPCODE: + prefix = " es"; + break; + case FS_PREFIX_OPCODE: + prefix = " fs"; + break; + case GS_PREFIX_OPCODE: + prefix = " gs"; + break; + case SS_PREFIX_OPCODE: + prefix = " ss"; + break; + } + if (padding_fragP) + msg = _("%s:%u: add %d%s at 0x%llx to align " + "%s within %d-byte boundary\n"); + else + msg = _("%s:%u: add additional %d%s at 0x%llx to " + "align %s within %d-byte boundary\n"); + } + else + { + padding_fragP = fragP; + msg = _("%s:%u: add %d%s-byte nop at 0x%llx to align " + "%s within %d-byte boundary\n"); + } + + if (padding_fragP) + switch (padding_fragP->tc_frag_data.branch_type) + { + case align_branch_jcc: + branch = "jcc"; + break; + case align_branch_fused: + branch = "fused jcc"; + break; + case align_branch_jmp: + branch = "jmp"; + break; + case align_branch_call: + branch = "call"; + break; + case align_branch_indirect: + branch = "indiret branch"; + break; + case align_branch_ret: + branch = "ret"; + break; + default: + break; + } + + fprintf (stdout, msg, + fragP->fr_file, fragP->fr_line, size, prefix, + (long long) fragP->fr_address, branch, + 1 << align_branch_power); + } + if (TYPE_FROM_RELAX_STATE (fragP->fr_subtype) == BRANCH_PREFIX) + memset (fragP->fr_opcode, + fragP->tc_frag_data.default_prefix, size); + else + i386_generate_nops (fragP, (char *) fragP->fr_opcode, + size, 0); + fragP->fr_fix += size; + } + return; + } + opcode = (unsigned char *) fragP->fr_opcode; /* Address we want to reach in file space. */ @@ -10894,19 +11845,20 @@ parse_real_register (char *reg_string, char **end_op) return (const reg_entry *) NULL; if ((r->reg_type.bitfield.dword - || (r->reg_type.bitfield.sreg && r->reg_num > 3) - || r->reg_type.bitfield.control - || r->reg_type.bitfield.debug - || r->reg_type.bitfield.test) + || (r->reg_type.bitfield.class == SReg && r->reg_num > 3) + || r->reg_type.bitfield.class == RegCR + || r->reg_type.bitfield.class == RegDR + || r->reg_type.bitfield.class == RegTR) && !cpu_arch_flags.bitfield.cpui386) return (const reg_entry *) NULL; - if (r->reg_type.bitfield.regmmx && !cpu_arch_flags.bitfield.cpummx) + if (r->reg_type.bitfield.class == RegMMX && !cpu_arch_flags.bitfield.cpummx) return (const reg_entry *) NULL; if (!cpu_arch_flags.bitfield.cpuavx512f) { - if (r->reg_type.bitfield.zmmword || r->reg_type.bitfield.regmask) + if (r->reg_type.bitfield.zmmword + || r->reg_type.bitfield.class == RegMask) return (const reg_entry *) NULL; if (!cpu_arch_flags.bitfield.cpuavx) @@ -10919,7 +11871,7 @@ parse_real_register (char *reg_string, char **end_op) } } - if (r->reg_type.bitfield.regbnd && !cpu_arch_flags.bitfield.cpumpx) + if (r->reg_type.bitfield.class == RegBND && !cpu_arch_flags.bitfield.cpumpx) return (const reg_entry *) NULL; /* Don't allow fake index register unless allow_index_reg isn't 0. */ @@ -10938,11 +11890,12 @@ parse_real_register (char *reg_string, char **end_op) } if (((r->reg_flags & (RegRex64 | RegRex)) || r->reg_type.bitfield.qword) - && (!cpu_arch_flags.bitfield.cpulm || !r->reg_type.bitfield.control) + && (!cpu_arch_flags.bitfield.cpulm || r->reg_type.bitfield.class != RegCR) && flag_code != CODE_64BIT) return (const reg_entry *) NULL; - if (r->reg_type.bitfield.sreg && r->reg_num == RegFlat && !intel_syntax) + if (r->reg_type.bitfield.class == SReg && r->reg_num == RegFlat + && !intel_syntax) return (const reg_entry *) NULL; return r; @@ -11080,6 +12033,10 @@ const char *md_shortopts = "qnO::"; #define OPTION_MFENCE_AS_LOCK_ADD (OPTION_MD_BASE + 24) #define OPTION_X86_USED_NOTE (OPTION_MD_BASE + 25) #define OPTION_MVEXWIG (OPTION_MD_BASE + 26) +#define OPTION_MALIGN_BRANCH_BOUNDARY (OPTION_MD_BASE + 27) +#define OPTION_MALIGN_BRANCH_PREFIX_SIZE (OPTION_MD_BASE + 28) +#define OPTION_MALIGN_BRANCH (OPTION_MD_BASE + 29) +#define OPTION_MBRANCHES_WITH_32B_BOUNDARIES (OPTION_MD_BASE + 30) struct option md_longopts[] = { @@ -11115,6 +12072,10 @@ struct option md_longopts[] = {"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}, + {"malign-branch-boundary", required_argument, NULL, OPTION_MALIGN_BRANCH_BOUNDARY}, + {"malign-branch-prefix-size", required_argument, NULL, OPTION_MALIGN_BRANCH_PREFIX_SIZE}, + {"malign-branch", required_argument, NULL, OPTION_MALIGN_BRANCH}, + {"mbranches-within-32B-boundaries", no_argument, NULL, OPTION_MBRANCHES_WITH_32B_BOUNDARIES}, {"mamd64", no_argument, NULL, OPTION_MAMD64}, {"mintel64", no_argument, NULL, OPTION_MINTEL64}, {NULL, no_argument, NULL, 0} @@ -11125,7 +12086,7 @@ int md_parse_option (int c, const char *arg) { unsigned int j; - char *arch, *next, *saved; + char *arch, *next, *saved, *type; switch (c) { @@ -11426,9 +12387,9 @@ md_parse_option (int c, const char *arg) case OPTION_MVEXWIG: if (strcmp (arg, "0") == 0) - vexwig = evexw0; + vexwig = vexw0; else if (strcmp (arg, "1") == 0) - vexwig = evexw1; + vexwig = vexw1; else as_fatal (_("invalid -mvexwig= option: `%s'"), arg); break; @@ -11503,6 +12464,88 @@ md_parse_option (int c, const char *arg) as_fatal (_("invalid -mrelax-relocations= option: `%s'"), arg); break; + case OPTION_MALIGN_BRANCH_BOUNDARY: + { + char *end; + long int align = strtoul (arg, &end, 0); + if (*end == '\0') + { + if (align == 0) + { + align_branch_power = 0; + break; + } + else if (align >= 16) + { + int align_power; + for (align_power = 0; + (align & 1) == 0; + align >>= 1, align_power++) + continue; + /* Limit alignment power to 31. */ + if (align == 1 && align_power < 32) + { + align_branch_power = align_power; + break; + } + } + } + as_fatal (_("invalid -malign-branch-boundary= value: %s"), arg); + } + break; + + case OPTION_MALIGN_BRANCH_PREFIX_SIZE: + { + char *end; + int align = strtoul (arg, &end, 0); + /* Some processors only support 5 prefixes. */ + if (*end == '\0' && align >= 0 && align < 6) + { + align_branch_prefix_size = align; + break; + } + as_fatal (_("invalid -malign-branch-prefix-size= value: %s"), + arg); + } + break; + + case OPTION_MALIGN_BRANCH: + align_branch = 0; + saved = xstrdup (arg); + type = saved; + do + { + next = strchr (type, '+'); + if (next) + *next++ = '\0'; + if (strcasecmp (type, "jcc") == 0) + align_branch |= align_branch_jcc_bit; + else if (strcasecmp (type, "fused") == 0) + align_branch |= align_branch_fused_bit; + else if (strcasecmp (type, "jmp") == 0) + align_branch |= align_branch_jmp_bit; + else if (strcasecmp (type, "call") == 0) + align_branch |= align_branch_call_bit; + else if (strcasecmp (type, "ret") == 0) + align_branch |= align_branch_ret_bit; + else if (strcasecmp (type, "indirect") == 0) + align_branch |= align_branch_indirect_bit; + else + as_fatal (_("invalid -malign-branch= option: `%s'"), arg); + type = next; + } + while (next != NULL); + free (saved); + break; + + case OPTION_MBRANCHES_WITH_32B_BOUNDARIES: + align_branch_power = 5; + align_branch_prefix_size = 5; + align_branch = (align_branch_jcc_bit + | align_branch_fused_bit + | align_branch_jmp_bit); + break; + case OPTION_MAMD64: intel64 = 0; break; @@ -11755,6 +12798,20 @@ md_show_usage (FILE *stream) fprintf (stream, _("\ generate relax relocations\n")); fprintf (stream, _("\ + -malign-branch-boundary=NUM (default: 0)\n\ + align branches within NUM byte boundary\n")); + fprintf (stream, _("\ + -malign-branch=TYPE[+TYPE...] (default: jcc+fused+jmp)\n\ + TYPE is combination of jcc, fused, jmp, call, ret,\n\ + indirect\n\ + specify types of branches to align\n")); + fprintf (stream, _("\ + -malign-branch-prefix-size=NUM (default: 5)\n\ + align branches with NUM prefixes per instruction\n")); + fprintf (stream, _("\ + -mbranches-within-32B-boundaries\n\ + align branches within 32 byte boundary\n")); + fprintf (stream, _("\ -mamd64 accept only AMD64 ISA [default]\n")); fprintf (stream, _("\ -mintel64 accept only Intel64 ISA\n")); @@ -11838,15 +12895,24 @@ i386_target_format (void) { default: format = ELF_TARGET_FORMAT; +#ifndef TE_SOLARIS + tls_get_addr = "___tls_get_addr"; +#endif break; case X86_64_ABI: use_rela_relocations = 1; object_64bit = 1; +#ifndef TE_SOLARIS + tls_get_addr = "__tls_get_addr"; +#endif format = ELF_TARGET_FORMAT64; break; case X86_64_X32_ABI: use_rela_relocations = 1; object_64bit = 1; +#ifndef TE_SOLARIS + tls_get_addr = "__tls_get_addr"; +#endif disallow_64bit_reloc = 1; format = ELF_TARGET_FORMAT32; break; @@ -11927,7 +12993,7 @@ md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size) work. */ int align; - align = bfd_get_section_alignment (stdoutput, segment); + align = bfd_section_alignment (segment); size = ((size + (1 << align) - 1) & (-((valueT) 1 << align))); } #endif @@ -11963,6 +13029,21 @@ s_bss (int ignore ATTRIBUTE_UNUSED) #endif +/* Remember constant directive. */ + +void +i386_cons_align (int ignore ATTRIBUTE_UNUSED) +{ + if (last_insn.kind != last_insn_directive + && (bfd_section_flags (now_seg) & SEC_CODE)) + { + last_insn.seg = now_seg; + last_insn.kind = last_insn_directive; + last_insn.name = "constant directive"; + last_insn.file = as_where (&last_insn.line); + } +} + void i386_validate_fix (fixS *fixp) { @@ -12370,8 +13451,7 @@ handle_large_common (int small ATTRIBUTE_UNUSED) /* The .lbss section is for local .largecomm symbols. */ lbss_section = subseg_new (".lbss", 0); applicable = bfd_applicable_section_flags (stdoutput); - bfd_set_section_flags (stdoutput, lbss_section, - applicable & SEC_ALLOC); + bfd_set_section_flags (lbss_section, applicable & SEC_ALLOC); seg_info (lbss_section)->bss = 1; subseg_set (seg, subseg);