X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-i386.c;h=ddbffb95b113b705d410f5859ba745711cb506eb;hb=7c5c05effd92cc5732bee527303077fc2e6b62af;hp=008dc95d24433444ef3e65034b77fa312ed1a1e0;hpb=629cfaf1b0fbb32a985607c774bd8e7870b9fa94;p=binutils-gdb.git diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 008dc95d244..ddbffb95b11 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -309,6 +309,7 @@ struct _i386_insn /* Flags for operands. */ unsigned int flags[MAX_OPERANDS]; #define Operand_PCrel 1 +#define Operand_Mem 2 /* Relocation type for operand */ enum bfd_reloc_code_real reloc[MAX_OPERANDS]; @@ -2010,7 +2011,7 @@ operand_size_match (const insn_template *t) break; } - if (i.types[j].bitfield.mem && !match_mem_size (t, j, j)) + if ((i.flags[j] & Operand_Mem) && !match_mem_size (t, j, j)) { match = 0; break; @@ -2035,8 +2036,7 @@ mismatch: && !match_operand_size (t, j, !j)) goto mismatch; - if (i.types[!j].bitfield.mem - && !match_mem_size (t, j, !j)) + if ((i.flags[!j] & Operand_Mem) && !match_mem_size (t, j, !j)) goto mismatch; } @@ -3478,6 +3478,13 @@ is_evex_encoding (const insn_template *t) || t->opcode_modifier.staticrounding || t->opcode_modifier.sae; } +static INLINE bfd_boolean +is_any_vex_encoding (const insn_template *t) +{ + return t->opcode_modifier.vex || t->opcode_modifier.vexopcode + || is_evex_encoding (t); +} + /* Build the EVEX prefix. */ static void @@ -3760,9 +3767,7 @@ bad_register_operand: gas_assert (i.imm_operands <= 1 && (i.operands <= 2 - || ((i.tm.opcode_modifier.vex - || i.tm.opcode_modifier.vexopcode - || is_evex_encoding (&i.tm)) + || (is_any_vex_encoding (&i.tm) && i.operands <= 4))); exp = &im_expressions[i.imm_operands++]; @@ -3937,7 +3942,11 @@ optimize_encoding (void) || i.tm.base_opcode == 0x66f8 || i.tm.base_opcode == 0x66f9 || i.tm.base_opcode == 0x66fa - || i.tm.base_opcode == 0x66fb) + || i.tm.base_opcode == 0x66fb + || i.tm.base_opcode == 0x42 + || i.tm.base_opcode == 0x6642 + || i.tm.base_opcode == 0x47 + || i.tm.base_opcode == 0x6647) && i.tm.extension_opcode == None)) { /* Optimize: -O2: @@ -3968,6 +3977,12 @@ optimize_encoding (void) EVEX VOP %ymmM, %ymmM, %ymmN -> VEX vpxor %xmmM, %xmmM, %xmmN (M and N < 16) -> EVEX VOP %xmmM, %xmmM, %xmmN (M || N >= 16) + VOP, one of kxord and kxorq: + VEX VOP %kM, %kM, %kN + -> VEX kxorw %kM, %kM, %kN + VOP, one of kandnd and kandnq: + VEX VOP %kM, %kM, %kN + -> VEX kandnw %kM, %kM, %kN */ if (is_evex_encoding (&i.tm)) { @@ -3980,6 +3995,11 @@ optimize_encoding (void) i.tm.opcode_modifier.evex = 0; } } + else if (i.tm.operand_types[0].bitfield.regmask) + { + i.tm.base_opcode &= 0xff; + i.tm.opcode_modifier.vexw = VEXW0; + } else i.tm.opcode_modifier.vex = VEX128; @@ -4125,6 +4145,13 @@ md_assemble (char *line) return; } + /* Check for data size prefix on VEX/XOP/EVEX encoded insns. */ + if (i.prefix[DATA_PREFIX] && is_any_vex_encoding (&i.tm)) + { + as_bad (_("data size prefix invalid with `%s'"), i.tm.name); + return; + } + /* Check if HLE prefix is OK. */ if (i.hle_prefix && !check_hle ()) return; @@ -4211,8 +4238,7 @@ md_assemble (char *line) as_warn (_("translating to `%sp'"), i.tm.name); } - if (i.tm.opcode_modifier.vex || i.tm.opcode_modifier.vexopcode - || is_evex_encoding (&i.tm)) + if (is_any_vex_encoding (&i.tm)) { if (flag_code == CODE_16BIT) { @@ -4727,14 +4753,21 @@ swap_2_operands (int xchg1, int xchg2) { union i386_op temp_op; i386_operand_type temp_type; + unsigned int temp_flags; enum bfd_reloc_code_real temp_reloc; temp_type = i.types[xchg2]; i.types[xchg2] = i.types[xchg1]; i.types[xchg1] = temp_type; + + temp_flags = i.flags[xchg2]; + i.flags[xchg2] = i.flags[xchg1]; + i.flags[xchg1] = temp_flags; + temp_op = i.op[xchg2]; i.op[xchg2] = i.op[xchg1]; i.op[xchg1] = temp_op; + temp_reloc = i.reloc[xchg2]; i.reloc[xchg2] = i.reloc[xchg1]; i.reloc[xchg1] = temp_reloc; @@ -5154,7 +5187,7 @@ check_VecOperands (const insn_template *t) and its broadcast bytes match the memory operand. */ op = i.broadcast->operand; if (!t->opcode_modifier.broadcast - || !i.types[op].bitfield.mem + || !(i.flags[op] & Operand_Mem) || (!i.types[op].bitfield.unspecified && !match_broadcast_size (t, op))) { @@ -5230,13 +5263,39 @@ check_VecOperands (const insn_template *t) op = MAX_OPERANDS - 1; /* Avoid uninitialized variable warning. */ /* Check if requested masking is supported. */ - if (i.mask - && (!t->opcode_modifier.masking - || (i.mask->zeroing - && t->opcode_modifier.masking == MERGING_MASKING))) + if (i.mask) { - i.error = unsupported_masking; - return 1; + switch (t->opcode_modifier.masking) + { + case BOTH_MASKING: + break; + case MERGING_MASKING: + if (i.mask->zeroing) + { + case 0: + i.error = unsupported_masking; + return 1; + } + break; + case DYNAMIC_MASKING: + /* Memory destinations allow only merging masking. */ + if (i.mask->zeroing && i.mem_operands) + { + /* Find memory operand. */ + for (op = 0; op < i.operands; op++) + if (i.flags[op] & Operand_Mem) + break; + gas_assert (op < i.operands); + if (op == i.operands - 1) + { + i.error = unsupported_masking; + return 1; + } + } + break; + default: + abort (); + } } /* Check if masking is applied to dest operand. */ @@ -6137,6 +6196,9 @@ process_suffix (void) else if (i.suffix != QWORD_MNEM_SUFFIX && !i.tm.opcode_modifier.ignoresize && !i.tm.opcode_modifier.floatmf + && !i.tm.opcode_modifier.vex + && !i.tm.opcode_modifier.vexopcode + && !is_evex_encoding (&i.tm) && ((i.suffix == LONG_MNEM_SUFFIX) == (flag_code == CODE_16BIT) || (flag_code == CODE_64BIT && i.tm.opcode_modifier.jumpbyte))) @@ -7032,8 +7094,7 @@ build_modrm_byte (void) if (i.tm.opcode_modifier.vecsib) { - if (i.index_reg->reg_num == RegEiz - || i.index_reg->reg_num == RegRiz) + if (i.index_reg->reg_num == RegIZ) abort (); i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING; @@ -7104,8 +7165,7 @@ build_modrm_byte (void) else if (!i.tm.opcode_modifier.vecsib) { /* !i.base_reg && i.index_reg */ - if (i.index_reg->reg_num == RegEiz - || i.index_reg->reg_num == RegRiz) + if (i.index_reg->reg_num == RegIZ) i.sib.index = NO_INDEX_REGISTER; else i.sib.index = i.index_reg->reg_num; @@ -7131,8 +7191,7 @@ build_modrm_byte (void) } } /* RIP addressing for 64bit mode. */ - else if (i.base_reg->reg_num == RegRip || - i.base_reg->reg_num == RegEip) + else if (i.base_reg->reg_num == RegIP) { gas_assert (!i.tm.opcode_modifier.vecsib); i.rm.regmem = NO_BASE_REGISTER; @@ -7224,8 +7283,7 @@ build_modrm_byte (void) } else if (!i.tm.opcode_modifier.vecsib) { - if (i.index_reg->reg_num == RegEiz - || i.index_reg->reg_num == RegRiz) + if (i.index_reg->reg_num == RegIZ) i.sib.index = NO_INDEX_REGISTER; else i.sib.index = i.index_reg->reg_num; @@ -8071,8 +8129,7 @@ output_disp (fragS *insn_start_frag, offsetT insn_start_off) { fixP->fx_tcbit = i.rex != 0; if (i.base_reg - && (i.base_reg->reg_num == RegRip - || i.base_reg->reg_num == RegEip)) + && (i.base_reg->reg_num == RegIP)) fixP->fx_tcbit2 = 1; } else @@ -9173,9 +9230,7 @@ i386_addressing_mode (void) if (addr_reg) { - if (addr_reg->reg_num == RegEip - || addr_reg->reg_num == RegEiz - || addr_reg->reg_type.bitfield.dword) + if (addr_reg->reg_type.bitfield.dword) addr_mode = CODE_32BIT; else if (flag_code != CODE_64BIT && addr_reg->reg_type.bitfield.word) @@ -9285,21 +9340,18 @@ bad_address: { /* 32-bit/64-bit checks. */ if ((i.base_reg - && (addr_mode == CODE_64BIT - ? !i.base_reg->reg_type.bitfield.qword - : !i.base_reg->reg_type.bitfield.dword) - && (i.index_reg - || (i.base_reg->reg_num - != (addr_mode == CODE_64BIT ? RegRip : RegEip)))) + && ((addr_mode == CODE_64BIT + ? !i.base_reg->reg_type.bitfield.qword + : !i.base_reg->reg_type.bitfield.dword) + || (i.index_reg && i.base_reg->reg_num == RegIP) + || i.base_reg->reg_num == RegIZ)) || (i.index_reg && !i.index_reg->reg_type.bitfield.xmmword && !i.index_reg->reg_type.bitfield.ymmword && !i.index_reg->reg_type.bitfield.zmmword && ((addr_mode == CODE_64BIT - ? !(i.index_reg->reg_type.bitfield.qword - || i.index_reg->reg_num == RegRiz) - : !(i.index_reg->reg_type.bitfield.dword - || i.index_reg->reg_num == RegEiz)) + ? !i.index_reg->reg_type.bitfield.qword + : !i.index_reg->reg_type.bitfield.dword) || !i.index_reg->reg_type.bitfield.baseindex))) goto bad_address; @@ -9308,7 +9360,7 @@ bad_address: || (current_templates->start->base_opcode & ~1) == 0x0f1a) { /* They cannot use RIP-relative addressing. */ - if (i.base_reg && i.base_reg->reg_num == RegRip) + if (i.base_reg && i.base_reg->reg_num == RegIP) { as_bad (_("`%s' cannot be used here"), operand_string); return 0; @@ -9759,7 +9811,7 @@ i386_att_operand (char *operand_string) if (i386_index_check (operand_string) == 0) return 0; - i.types[this_operand].bitfield.mem = 1; + i.flags[this_operand] |= Operand_Mem; if (i.mem_operands == 0) i.memop1_string = xstrdup (operand_string); i.mem_operands++; @@ -10368,15 +10420,14 @@ parse_real_register (char *reg_string, char **end_op) return (const reg_entry *) NULL; /* Don't allow fake index register unless allow_index_reg isn't 0. */ - if (!allow_index_reg - && (r->reg_num == RegEiz || r->reg_num == RegRiz)) + if (!allow_index_reg && r->reg_num == RegIZ) return (const reg_entry *) NULL; /* Upper 16 vector registers are only available with VREX in 64bit mode, and require EVEX encoding. */ if (r->reg_flags & RegVRex) { - if (!cpu_arch_flags.bitfield.cpuvrex + if (!cpu_arch_flags.bitfield.cpuavx512f || flag_code != CODE_64BIT) return (const reg_entry *) NULL; @@ -11101,28 +11152,38 @@ md_show_usage (FILE *stream) fprintf (stream, _("\ -msse2avx encode SSE instructions with VEX prefix\n")); fprintf (stream, _("\ - -msse-check=[none|error|warning]\n\ + -msse-check=[none|error|warning] (default: warning)\n\ check SSE instructions\n")); fprintf (stream, _("\ - -moperand-check=[none|error|warning]\n\ + -moperand-check=[none|error|warning] (default: warning)\n\ check operand combinations for validity\n")); fprintf (stream, _("\ - -mavxscalar=[128|256] encode scalar AVX instructions with specific vector\n\ + -mavxscalar=[128|256] (default: 128)\n\ + encode scalar AVX instructions with specific vector\n\ length\n")); fprintf (stream, _("\ - -mevexlig=[128|256|512] encode scalar EVEX instructions with specific vector\n\ + -mevexlig=[128|256|512] (default: 128)\n\ + encode scalar EVEX instructions with specific vector\n\ length\n")); fprintf (stream, _("\ - -mevexwig=[0|1] encode EVEX instructions with specific EVEX.W value\n\ + -mevexwig=[0|1] (default: 0)\n\ + encode EVEX instructions with specific EVEX.W value\n\ for EVEX.W bit ignored instructions\n")); fprintf (stream, _("\ - -mevexrcig=[rne|rd|ru|rz]\n\ + -mevexrcig=[rne|rd|ru|rz] (default: rne)\n\ encode EVEX instructions with specific EVEX.RC value\n\ for SAE-only ignored instructions\n")); fprintf (stream, _("\ - -mmnemonic=[att|intel] use AT&T/Intel mnemonic\n")); + -mmnemonic=[att|intel] ")); + if (SYSV386_COMPAT) + fprintf (stream, _("(default: att)\n")); + else + fprintf (stream, _("(default: intel)\n")); + fprintf (stream, _("\ + use AT&T/Intel mnemonic\n")); fprintf (stream, _("\ - -msyntax=[att|intel] use AT&T/Intel syntax\n")); + -msyntax=[att|intel] (default: att)\n\ + use AT&T/Intel syntax\n")); fprintf (stream, _("\ -mindex-reg support pseudo index registers\n")); fprintf (stream, _("\ @@ -11136,17 +11197,22 @@ md_show_usage (FILE *stream) -mbig-obj generate big object files\n")); #endif fprintf (stream, _("\ - -momit-lock-prefix=[no|yes]\n\ + -momit-lock-prefix=[no|yes] (default: no)\n\ strip all lock prefixes\n")); fprintf (stream, _("\ - -mfence-as-lock-add=[no|yes]\n\ + -mfence-as-lock-add=[no|yes] (default: no)\n\ encode lfence, mfence and sfence as\n\ lock addl $0x0, (%%{re}sp)\n")); fprintf (stream, _("\ - -mrelax-relocations=[no|yes]\n\ + -mrelax-relocations=[no|yes] ")); + if (DEFAULT_GENERATE_X86_RELAX_RELOCATIONS) + fprintf (stream, _("(default: yes)\n")); + else + fprintf (stream, _("(default: no)\n")); + fprintf (stream, _("\ generate relax relocations\n")); fprintf (stream, _("\ - -mamd64 accept only AMD64 ISA\n")); + -mamd64 accept only AMD64 ISA [default]\n")); fprintf (stream, _("\ -mintel64 accept only Intel64 ISA\n")); }