From patchwork Tue Sep 19 15:25:20 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Frager, Neal via Binutils" X-Patchwork-Id: 76388 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id A17CE3854830 for ; Tue, 19 Sep 2023 15:27:45 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A17CE3854830 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1695137265; bh=XcpwT8qeeKX8VM/z+eIQm+CPkPmj8tSyv93yTJa9G+I=; h=To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=PH282URmGA9+17nWj8H2v7rFakkuZsRF9xdB7vD3gvpB9AMDwlqo1N7qqpbcxfRDp t6gVsx2kszU54npEDOfCEhVivZtB2LZkBpC8Z3Ez8nkK96BQe+2kNqLgNzoAw/mY54 q0XxoN9WUcv+oXUNRtmIVm1WYHGvIgBmQrW0ePms= X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from mgamail.intel.com (mgamail.intel.com [134.134.136.20]) by sourceware.org (Postfix) with ESMTPS id 3262A3858C31 for ; Tue, 19 Sep 2023 15:25:33 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 3262A3858C31 X-IronPort-AV: E=McAfee;i="6600,9927,10838"; a="370285662" X-IronPort-AV: E=Sophos;i="6.02,159,1688454000"; d="scan'208";a="370285662" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Sep 2023 08:25:31 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10838"; a="739758912" X-IronPort-AV: E=Sophos;i="6.02,159,1688454000"; d="scan'208";a="739758912" Received: from scymds03.sc.intel.com ([10.148.94.166]) by orsmga007.jf.intel.com with ESMTP; 19 Sep 2023 08:25:31 -0700 Received: from shgcc101.sh.intel.com (shgcc101.sh.intel.com [10.239.85.97]) by scymds03.sc.intel.com (Postfix) with ESMTP id CBC8E6A; Tue, 19 Sep 2023 08:25:29 -0700 (PDT) To: binutils@sourceware.org Cc: jbeulich@suse.com, hongjiu.lu@intel.com, konglin1 Subject: [PATCH 1/8] Support APX GPR32 with rex2 prefix Date: Tue, 19 Sep 2023 15:25:20 +0000 Message-Id: <20230919152527.497773-2-lili.cui@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230919152527.497773-1-lili.cui@intel.com> References: <20230919152527.497773-1-lili.cui@intel.com> MIME-Version: 1.0 X-Spam-Status: No, score=-10.1 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SCC_10_SHORT_WORD_LINES, SCC_5_SHORT_WORD_LINES, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: "Cui, Lili via Binutils" From: "Frager, Neal via Binutils" Reply-To: "Cui, Lili" Errors-To: binutils-bounces+patchwork=sourceware.org@sourceware.org Sender: "Binutils" From: konglin1 gas/ChangeLog: * gas/NEWS: Support Intel APX. * gas/config/tc-i386.c (struct _i386_insn): Add rex2 rex-byte for gpr32 r16-r31. Add has_nf, has_zero_upper. (cpu_arch): Add apx. (register_number): Handle RegRex2 for gpr32. (is_any_apx_encoding): New func. Test apx encoding. (is_any_apx_rex2_encoding): New func. Test rex2 prefix encoding. (build_rex2_prefix): New func. Build legacy insn in opcode 0/1 use gpr32 with rex2 prefix. (optimize_encoding): Handel add r16-r31 for registers. (md_assemble): Handle apx encoding. (check_EgprOperands): New func. Check if Egprs operands are valid for the instruction (match_template): Handle Egpr operands check. (set_rex_rex2): New func. set i.rex and i.rex2. (process_operands): Handle i.rex2. (set_rex_vrex): Ditto. (build_modrm_byte): Ditto. (output_insn): Handle rex2 2-byte prefix output. (check_register): Handle check egpr illegal without target apx, 64-bit mode and with rex_prefix.. (enum i386_error): Add invalid_pseudo_prefix. (struct _i386_insn): Add rex2_encoding. (md_assemble): Handle invalid_pseudo_prefix. (parse_insn): Handle Prefix_REX2. * gas/doc/c-i386.texi: Document .apx. * gas/testsuite/gas/i386/x86-64.exp: Run APX tests. * gas/testsuite/gas/i386/x86-64-apx-egpr-inval.l: New test. * gas/testsuite/gas/i386/x86-64-apx-egpr-inval.s: New test. * testsuite/gas/i386/x86-64.exp: Add x86-64-apx-rex2. * testsuite/gas/i386/x86-64-opcode-inval-intel.d: D5 valid in 64-bit mode. * testsuite/gas/i386/x86-64-opcode-inval.d: Ditto. * testsuite/gas/i386/x86-64-apx-rex2.d: New test. * testsuite/gas/i386/x86-64-apx-rex2.s: Ditto. * testsuite/gas/i386/x86-64-apx-rex2-inval.d: Ditto. * testsuite/gas/i386/x86-64-apx-rex2-inval.s: Ditto. * testsuite/gas/i386/x86-64-pseudos.d: Ditto. * testsuite/gas/i386/x86-64-pseudos.s: Ditto. * testsuite/gas/i386/x86-64-inval-pseudo.l: Add rex2 invalid testcase. * testsuite/gas/i386/x86-64-inval-pseudo.s: Ditto. opcode/ChangeLog: * opcodes/i386-gen.c: Add APX. * opcodes/i386-init.h (CPU_MWAITX_FLAGS): Regenerated. * opcodes/i386-opc.h (CpuAPX): New. (i386_cpu_flags): Add cpuapx. (No_egpr): New define for egprs (r16-r31) on instruction illegal. (i386_opcode_modifier): Add no_egpr. (RegRex2): New define. (Prefix_REX2): New. (Prefix_NoOptimize): Adjust the value. * opcodes/i386-opc.tbl: Handle legacy insn in opcode map0/1 illegal with egprs and add rex2 prefix. * opcodes/i386-reg.tbl: Add egprs (r16-r31). * opcodes/i386-tbl.h: Regenerated. * opcodes/i386-dis.c (struct instr_info): Add erex for gpr32. Add last_erex_prefix for rex2 prefix. (att_names64[][8]): Extend for gpr32. (att_names32[][8]): Ditto. (att_names16[][8]): Ditto. (att_names8rex[][8]): Ditto. (ckprefix): Handle REX2 (0xd5) prefix. (print_insn): Handle rex2 M0 for opcode map. (print_register): Handle erex for gpr32. (OP_E_memory): Ditto. (OP_REG): Ditto. (OP_EM): Ditto. (OP_EX): Ditto. --- gas/NEWS | 3 + gas/config/tc-i386.c | 174 +++++++++++++++-- gas/doc/c-i386.texi | 3 +- .../i386/ilp32/x86-64-opcode-inval-intel.d | 4 +- .../gas/i386/ilp32/x86-64-opcode-inval.d | 4 +- .../gas/i386/x86-64-apx-egpr-inval.l | 24 +++ .../gas/i386/x86-64-apx-egpr-inval.s | 18 ++ .../gas/i386/x86-64-apx-rex2-inval.d | 29 +++ .../gas/i386/x86-64-apx-rex2-inval.s | 25 +++ gas/testsuite/gas/i386/x86-64-apx-rex2.d | 148 +++++++++++++++ gas/testsuite/gas/i386/x86-64-apx-rex2.s | 175 ++++++++++++++++++ gas/testsuite/gas/i386/x86-64-inval-pseudo.l | 12 ++ gas/testsuite/gas/i386/x86-64-inval-pseudo.s | 8 + .../gas/i386/x86-64-opcode-inval-intel.d | 4 +- gas/testsuite/gas/i386/x86-64-opcode-inval.d | 4 +- gas/testsuite/gas/i386/x86-64-pseudos.d | 20 ++ gas/testsuite/gas/i386/x86-64-pseudos.s | 21 +++ gas/testsuite/gas/i386/x86-64.exp | 3 + include/opcode/i386.h | 2 + opcodes/i386-dis.c | 126 +++++++++++-- opcodes/i386-gen.c | 2 + opcodes/i386-opc.h | 14 +- opcodes/i386-opc.tbl | 26 +-- opcodes/i386-reg.tbl | 64 +++++++ 24 files changed, 852 insertions(+), 61 deletions(-) create mode 100644 gas/testsuite/gas/i386/x86-64-apx-egpr-inval.l create mode 100644 gas/testsuite/gas/i386/x86-64-apx-egpr-inval.s create mode 100644 gas/testsuite/gas/i386/x86-64-apx-rex2-inval.d create mode 100644 gas/testsuite/gas/i386/x86-64-apx-rex2-inval.s create mode 100644 gas/testsuite/gas/i386/x86-64-apx-rex2.d create mode 100644 gas/testsuite/gas/i386/x86-64-apx-rex2.s diff --git a/gas/NEWS b/gas/NEWS index 730ffad9bc9..7203ebb1a0b 100644 --- a/gas/NEWS +++ b/gas/NEWS @@ -1,5 +1,8 @@ -*- text -*- + +* Add support for Intel APX instructions. + * Add support for Intel AVX10.1. * Add support for Intel PBNDKB instructions. diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index cec9a02be52..51486985919 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -247,6 +247,7 @@ enum i386_error invalid_vector_register_set, invalid_tmm_register_set, invalid_dest_and_src_register_set, + invalid_pseudo_prefix, unsupported_vector_index_register, unsupported_broadcast, broadcast_needed, @@ -353,6 +354,7 @@ struct _i386_insn modrm_byte rm; rex_byte rex; rex_byte vrex; + rex_byte rex2; // for extends gpr32 r16-r31 sib_byte sib; vex_prefix vex; @@ -405,6 +407,11 @@ struct _i386_insn /* Compressed disp8*N attribute. */ unsigned int memshift; + /* No CSPAZO flags update.*/ + bool has_nf; + + bool has_zero_upper; + /* Prefer load or store in encoding. */ enum { @@ -426,6 +433,9 @@ struct _i386_insn /* Prefer the REX byte in encoding. */ bool rex_encoding; + /* Prefer the REX2 byte in encoding. */ + bool rex2_encoding; + /* Disable instruction size optimization. */ bool no_optimize; @@ -1165,6 +1175,7 @@ static const arch_entry cpu_arch[] = VECARCH (sm4, SM4, ANY_SM4, reset), SUBARCH (pbndkb, PBNDKB, PBNDKB, false), VECARCH (avx10.1, AVX10_1, ANY_AVX512F, set), + SUBARCH (apx_f, APX_F, APX_F, false), }; #undef SUBARCH @@ -1694,6 +1705,7 @@ is_cpu (const insn_template *t, enum i386_cpu cpu) case CpuHLE: return t->cpu.bitfield.cpuhle; case CpuAVX512F: return t->cpu.bitfield.cpuavx512f; case CpuAVX512VL: return t->cpu.bitfield.cpuavx512vl; + case CpuAPX_F: return t->cpu.bitfield.cpuapx_f; case Cpu64: return t->cpu.bitfield.cpu64; case CpuNo64: return t->cpu.bitfield.cpuno64; default: @@ -2332,6 +2344,9 @@ register_number (const reg_entry *r) if (r->reg_flags & RegRex) nr += 8; + if (r->reg_flags & RegRex2) + nr += 16; + if (r->reg_flags & RegVRex) nr += 16; @@ -3832,6 +3847,18 @@ is_any_vex_encoding (const insn_template *t) return t->opcode_modifier.vex || is_evex_encoding (t); } +static INLINE bool +is_any_apx_encoding (void) +{ + return i.rex2 || i.rex2_encoding; +} + +static INLINE bool +is_any_apx_rex2_encoding (void) +{ + return (i.rex2 && i.vex.length == 2) || i.rex2_encoding; +} + static unsigned int get_broadcast_bytes (const insn_template *t, bool diag) { @@ -4089,6 +4116,19 @@ build_evex_prefix (void) i.vex.bytes[3] |= i.mask.reg->reg_num; } +/* Build (2 bytes) rex2 prefix. + | D5h | + | m | R4 X4 B4 | W R X B | +*/ +static void +build_rex2_prefix (void) +{ + i.vex.length = 2; + i.vex.bytes[0] = 0xd5; + i.vex.bytes[1] = ((i.tm.opcode_space << 7) + | (i.rex2 << 4) | i.rex); +} + static void process_immext (void) { @@ -4354,12 +4394,12 @@ optimize_encoding (void) i.suffix = 0; /* Convert to byte registers. */ if (i.types[1].bitfield.word) - j = 16; + j = 16 + 16; // new 16 apx additional gprs. else if (i.types[1].bitfield.dword) - j = 32; + j = 32 + 16 * 2; // new 16 apx additional gprs else - j = 48; - if (!(i.op[1].regs->reg_flags & RegRex) && base_regnum < 4) + j = 48 + 16 * 3; // new 16 apx additional gprs + if (!(i.op[1].regs->reg_flags & (RegRex | RegRex2)) && base_regnum < 4) j += 8; i.op[1].regs -= j; } @@ -5269,6 +5309,9 @@ md_assemble (char *line) case invalid_dest_and_src_register_set: err_msg = _("destination and source registers must be distinct"); break; + case invalid_pseudo_prefix: + err_msg = _("unsupport rex2 pseudo prefix"); + break; case unsupported_vector_index_register: err_msg = _("unsupported vector index register"); break; @@ -5498,7 +5541,17 @@ md_assemble (char *line) as_warn (_("translating to `%sp'"), insn_name (&i.tm)); } - if (is_any_vex_encoding (&i.tm)) + if (is_any_apx_encoding ()) + { + if (!is_any_vex_encoding (&i.tm) + && i.tm.opcode_space <= SPACE_0F + && !i.vex.register_specifier && !i.has_nf && !i.has_zero_upper) + build_rex2_prefix (); + + /* The individual REX.RXBW bits got consumed. */ + i.rex &= REX_OPCODE; + } + else if (is_any_vex_encoding (&i.tm)) { if (!cpu_arch_flags.bitfield.cpui286) { @@ -5514,6 +5567,13 @@ md_assemble (char *line) return; } + /* Check for explicit REX2 prefix. */ + if (i.rex2 || i.rex2_encoding) + { + as_bad (_("REX2 prefix invalid with `%s'"), insn_name (&i.tm)); + return; + } + if (i.tm.opcode_modifier.vex) build_vex_prefix (t); else @@ -5553,11 +5613,11 @@ md_assemble (char *line) && (i.op[1].regs->reg_flags & RegRex64) != 0) || (((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)) + && (i.rex != 0 || i.rex2!=0))) { int x; - - i.rex |= REX_OPCODE; + if (!i.rex2) + i.rex |= REX_OPCODE; for (x = 0; x < 2; x++) { /* Look for 8 bit operand that uses old registers. */ @@ -5567,9 +5627,16 @@ md_assemble (char *line) 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 " - "instruction requiring REX prefix."), - register_prefix, i.op[x].regs->reg_name); + { + if (i.rex) + as_bad (_("can't encode register '%s%s' in an " + "instruction requiring REX prefix."), + register_prefix, i.op[x].regs->reg_name); + else + as_bad (_("can't encode register '%s%s' in an " + "instruction requiring REX2 prefix."), + register_prefix, i.op[x].regs->reg_name); + } /* Otherwise it is equivalent to the extended register. Since the encoding doesn't change this is merely @@ -5580,7 +5647,7 @@ md_assemble (char *line) } } - if (i.rex == 0 && i.rex_encoding) + if ((i.rex == 0 && i.rex_encoding) || (i.rex2 == 0 && i.rex2_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 @@ -5594,6 +5661,7 @@ md_assemble (char *line) { gas_assert (!(i.op[x].regs->reg_flags & RegRex)); i.rex_encoding = false; + i.rex2_encoding = false; break; } @@ -5772,6 +5840,10 @@ parse_insn (const char *line, char *mnemonic, bool prefix_only) /* {rex} */ i.rex_encoding = true; break; + case Prefix_REX2: + /* {rex2} */ + i.rex2_encoding = true; + break; case Prefix_NoOptimize: /* {nooptimize} */ i.no_optimize = true; @@ -6899,6 +6971,42 @@ VEX_check_encoding (const insn_template *t) return 0; } +/* Check if Egprs operands are valid for the instruction. */ + +static int +check_EgprOperands (const insn_template *t) +{ + if (t->opcode_modifier.no_egpr) + { + for (unsigned int op = 0; op < i.operands; op++) + { + if (i.types[op].bitfield.class != Reg) + continue; + + if (i.op[op].regs->reg_flags & RegRex2) + { + i.error = register_type_mismatch; + return 1; + } + } + + if ((i.index_reg && (i.index_reg->reg_flags & RegRex2)) + || (i.base_reg && (i.base_reg->reg_flags & RegRex2))) + { + i.error = register_type_mismatch; + return 1; + } + + /* Check pseudo prefix {rex2} are valid. */ + if (i.rex2_encoding) + { + i.error = invalid_pseudo_prefix; + return 1; + } + } + return 0; +} + /* Helper function for the progress() macro in match_template(). */ static INLINE enum i386_error progress (enum i386_error new, enum i386_error last, @@ -7371,6 +7479,13 @@ match_template (char mnem_suffix) continue; } + /* Check if EGRPS operands(r16-r31) are valid. */ + if (check_EgprOperands (t)) + { + specific_error = progress (i.error); + continue; + } + /* We've found a match; break out of loop. */ break; } @@ -8245,6 +8360,18 @@ static INLINE void set_rex_vrex (const reg_entry *r, unsigned int rex_bit, if (r->reg_flags & RegVRex) i.vrex |= rex_bit; + + if (r->reg_flags & RegRex2) + i.rex2 |= rex_bit; +} + +static INLINE void +set_rex_rex2 (const reg_entry *r, unsigned int rex_bit) +{ + if ((r->reg_flags & RegRex) != 0) + i.rex |= rex_bit; + if ((r->reg_flags & RegRex2) != 0) + i.rex2 |= rex_bit; } static int @@ -8728,8 +8855,7 @@ build_modrm_byte (void) i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING; i.types[op] = operand_type_and_not (i.types[op], anydisp); i.types[op].bitfield.disp32 = 1; - if ((i.index_reg->reg_flags & RegRex) != 0) - i.rex |= REX_X; + set_rex_rex2 (i.index_reg, REX_X); } } /* RIP addressing for 64bit mode. */ @@ -8800,8 +8926,7 @@ build_modrm_byte (void) if (!i.tm.opcode_modifier.sib) i.rm.regmem = i.base_reg->reg_num; - if ((i.base_reg->reg_flags & RegRex) != 0) - i.rex |= REX_B; + set_rex_rex2 (i.base_reg, REX_B); i.sib.base = i.base_reg->reg_num; /* x86-64 ignores REX prefix bit here to avoid decoder complications. */ @@ -8839,8 +8964,7 @@ build_modrm_byte (void) else i.sib.index = i.index_reg->reg_num; i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING; - if ((i.index_reg->reg_flags & RegRex) != 0) - i.rex |= REX_X; + set_rex_rex2 (i.index_reg, REX_X); } if (i.disp_operands @@ -9987,6 +10111,12 @@ output_insn (void) for (j = ARRAY_SIZE (i.prefix), q = i.prefix; j > 0; j--, q++) if (*q) frag_opcode_byte (*q); + + if (is_any_apx_rex2_encoding ()) + { + frag_opcode_byte (i.vex.bytes[0]); + frag_opcode_byte (i.vex.bytes[1]); + } } else { @@ -13985,6 +14115,14 @@ static bool check_register (const reg_entry *r) i.vec_encoding = vex_encoding_error; } + if (r->reg_flags & RegRex2) + { + if (!cpu_arch_flags.bitfield.cpuapx_f + || flag_code != CODE_64BIT + || i.rex_encoding) + return false; + } + if (((r->reg_flags & (RegRex64 | RegRex)) || r->reg_type.bitfield.qword) && (!cpu_arch_flags.bitfield.cpu64 || r->reg_type.bitfield.class != RegCR diff --git a/gas/doc/c-i386.texi b/gas/doc/c-i386.texi index b04e1b00b4b..5d79a332f53 100644 --- a/gas/doc/c-i386.texi +++ b/gas/doc/c-i386.texi @@ -216,6 +216,7 @@ accept various extension mnemonics. For example, @code{avx10.1/512}, @code{avx10.1/256}, @code{avx10.1/128}, +@code{apx}, @code{amx_int8}, @code{amx_bf16}, @code{amx_fp16}, @@ -1662,7 +1663,7 @@ supported on the CPU specified. The choices for @var{cpu_type} are: @item @samp{.lwp} @tab @samp{.fma4} @tab @samp{.xop} @tab @samp{.cx16} @item @samp{.padlock} @tab @samp{.clzero} @tab @samp{.mwaitx} @tab @samp{.rdpru} @item @samp{.mcommit} @tab @samp{.sev_es} @tab @samp{.snp} @tab @samp{.invlpgb} -@item @samp{.tlbsync} +@item @samp{.tlbsync} @tab @samp{.apx} @end multitable Apart from the warning, there are only two other effects on diff --git a/gas/testsuite/gas/i386/ilp32/x86-64-opcode-inval-intel.d b/gas/testsuite/gas/i386/ilp32/x86-64-opcode-inval-intel.d index a2b09d2e74f..605548285f2 100644 --- a/gas/testsuite/gas/i386/ilp32/x86-64-opcode-inval-intel.d +++ b/gas/testsuite/gas/i386/ilp32/x86-64-opcode-inval-intel.d @@ -11,11 +11,11 @@ Disassembly of section .text: [ ]*[a-f0-9]+: 37 \(bad\) 0+1 : -[ ]*[a-f0-9]+: d5 \(bad\) +[ ]*[a-f0-9]+: d5 rex2 [ ]*[a-f0-9]+: 0a .byte 0xa 0+3 : -[ ]*[a-f0-9]+: d5 \(bad\) +[ ]*[a-f0-9]+: d5 rex2 [ ]*[a-f0-9]+: 02 .byte 0x2 0+5 : diff --git a/gas/testsuite/gas/i386/ilp32/x86-64-opcode-inval.d b/gas/testsuite/gas/i386/ilp32/x86-64-opcode-inval.d index 5a17b0b412e..c9d3f2fdbb6 100644 --- a/gas/testsuite/gas/i386/ilp32/x86-64-opcode-inval.d +++ b/gas/testsuite/gas/i386/ilp32/x86-64-opcode-inval.d @@ -11,11 +11,11 @@ Disassembly of section .text: [ ]*[a-f0-9]+: 37 \(bad\) 0+1 : -[ ]*[a-f0-9]+: d5 \(bad\) +[ ]*[a-f0-9]+: d5 rex2 [ ]*[a-f0-9]+: 0a .byte 0xa 0+3 : -[ ]*[a-f0-9]+: d5 \(bad\) +[ ]*[a-f0-9]+: d5 rex2 [ ]*[a-f0-9]+: 02 .byte 0x2 0+5 : diff --git a/gas/testsuite/gas/i386/x86-64-apx-egpr-inval.l b/gas/testsuite/gas/i386/x86-64-apx-egpr-inval.l new file mode 100644 index 00000000000..c419f449f27 --- /dev/null +++ b/gas/testsuite/gas/i386/x86-64-apx-egpr-inval.l @@ -0,0 +1,24 @@ +.*: Assembler messages: +.*:4: Error: bad register name `%r17d' +.*:7: Error: register type mismatch for `xsave' +.*:8: Error: register type mismatch for `xsave64' +.*:9: Error: register type mismatch for `xrstor' +.*:10: Error: register type mismatch for `xrstor64' +.*:11: Error: register type mismatch for `xsaves' +.*:12: Error: register type mismatch for `xsaves64' +.*:13: Error: register type mismatch for `xrstors' +.*:14: Error: register type mismatch for `xrstors64' +.*:15: Error: register type mismatch for `xsaveopt' +.*:16: Error: register type mismatch for `xsaveopt64' +.*:17: Error: register type mismatch for `xsavec' +.*:18: Error: register type mismatch for `xsavec64' +GAS LISTING .* +#... +[ ]*1[ ]+\# Check Illegal 64bit APX instructions +[ ]*2[ ]+\.text +[ ]*3[ ]+\.arch \.noapx_f +[ ]*4[ ]+test \$0x7, %r17d +[ ]*5[ ]+\.arch \.apx_f +[ ]*6[ ]+\?\?\?\? D510F7C1 test \$0x7, %r17d +[ ]*6[ ]+07000000 +#pass diff --git a/gas/testsuite/gas/i386/x86-64-apx-egpr-inval.s b/gas/testsuite/gas/i386/x86-64-apx-egpr-inval.s new file mode 100644 index 00000000000..5249b888046 --- /dev/null +++ b/gas/testsuite/gas/i386/x86-64-apx-egpr-inval.s @@ -0,0 +1,18 @@ +# Check Illegal 64bit APX instructions + .text + .arch .noapx_f + test $0x7, %r17d + .arch .apx_f + test $0x7, %r17d + xsave (%r16, %rbx) + xsave64 (%r16, %rbx) + xrstor (%r16, %rbx) + xrstor64 (%r16, %rbx) + xsaves (%r16, %rbx) + xsaves64 (%r16, %rbx) + xrstors (%r16, %rbx) + xrstors64 (%r16, %rbx) + xsaveopt (%r16, %rbx) + xsaveopt64 (%r16, %rbx) + xsavec (%r16, %rbx) + xsavec64 (%r16, %rbx) diff --git a/gas/testsuite/gas/i386/x86-64-apx-rex2-inval.d b/gas/testsuite/gas/i386/x86-64-apx-rex2-inval.d new file mode 100644 index 00000000000..655792818cc --- /dev/null +++ b/gas/testsuite/gas/i386/x86-64-apx-rex2-inval.d @@ -0,0 +1,29 @@ +#as: +#objdump: -dw +#name: x86-64 APX use gpr32 with rex2 prefix illegal check +#source: x86-64-apx-rex2-inval.s + +.*: +file format .* + + +Disassembly of section .text: + +0+ <_start>: +\s*[a-f0-9]+:\s*d5 f0 d5 f0\s+{rex2} pmullw %mm0,%mm6 +\s*[a-f0-9]+:\s*d5 f9 d5 f9\s+{rex2} pmullw %mm1,%mm7 +\s*[a-f0-9]+:\s*d5 88 d5 f9\s+{rex2} pmullw %mm1,%mm7 +\s*[a-f0-9]+:\s*d5 f7 d5 f9\s+{rex2} pmullw %mm1,%mm7 +\s*[a-f0-9]+:\s*d5 80 d5 f9\s+{rex2} pmullw %mm1,%mm7 +\s*[a-f0-9]+:\s*66 d5 f9 d5 f9\s+{rex2} pmullw %xmm9,%xmm7 +\s*[a-f0-9]+:\s*66 41\s+data16 rex.B +\s*[a-f0-9]+:\s*d5 f9 d5 f9\s+{rex2} pmullw %mm1,%mm7 +\s*[a-f0-9]+:\s*d5 ff 21 f8\s+{rex2} mov %db15,%r24 +\s*[a-f0-9]+:\s*d5 01 21 00\s+{rex2} and %eax,\(%r8\) +\s*[a-f0-9]+:\s*d5 00 00 f7\s+{rex2} add %sil,%dil +\s*[a-f0-9]+:\s*d5 ff 20 f8\s+{rex2} mov %cr15,%r24 +\s*[a-f0-9]+:\s*d5 81 ae\s+\(bad\) +\s*[a-f0-9]+:\s*27\s+\(bad\) +\s*[a-f0-9]+:\s*d5 c1 38\s+\(bad\) +\s*[a-f0-9]+:\s*f6\s+.byte 0xf6 +\s*[a-f0-9]+:\s*07\s+\(bad\) +#pass diff --git a/gas/testsuite/gas/i386/x86-64-apx-rex2-inval.s b/gas/testsuite/gas/i386/x86-64-apx-rex2-inval.s new file mode 100644 index 00000000000..51dd8df79d6 --- /dev/null +++ b/gas/testsuite/gas/i386/x86-64-apx-rex2-inval.s @@ -0,0 +1,25 @@ +# Check 64bit instructions with rex2 prefix bad encoding + + .allow_index_reg + .text +_start: +# check {rex2} pseudo prefix to force REX2 encoding. +.byte 0xd5, 0xf0, 0xd5, 0xf0 +.byte 0xd5, 0xf9, 0xd5, 0xf9 +.byte 0xd5, 0x88, 0xd5, 0xf9 +.byte 0xd5, 0xf7, 0xd5, 0xf9 +.byte 0xd5, 0x80, 0xd5, 0xf9 + +.byte 0x66 +.byte 0xd5, 0xf9, 0xd5, 0xf9 +.byte 0x66, 0x41 +.byte 0xd5, 0xf9, 0xd5, 0xf9 +.byte 0xd5, 0xff, 0x21, 0xf8 +.byte 0xd5, 0x01, 0x21, 0x00 +.byte 0xd5, 0x00, 0x00, 0xf7 +.byte 0xd5, 0xff, 0x20, 0xf8 +# check xsave/xstore are not allowed to use rex2. +.byte 0xd5, 0x81, 0xae, 0x27 +# check rex2 only use for map0/1 +.byte 0xd5, 0xc1, 0x38, 0xf6, 0x07 + diff --git a/gas/testsuite/gas/i386/x86-64-apx-rex2.d b/gas/testsuite/gas/i386/x86-64-apx-rex2.d new file mode 100644 index 00000000000..d64b615ff4d --- /dev/null +++ b/gas/testsuite/gas/i386/x86-64-apx-rex2.d @@ -0,0 +1,148 @@ +#as: +#objdump: -dw +#name: x86-64 APX use gpr32 with rex2 prefix +#source: x86-64-apx-rex2.s + +.*: +file format .* + + +Disassembly of section .text: + +0+ <_start>: +\s*[a-f0-9]+:\s*d5 11 f6 c0 07\s+test \$0x7,%r24b +\s*[a-f0-9]+:\s*d5 11 f7 c0 07 00 00 00 test \$0x7,%r24d +\s*[a-f0-9]+:\s*d5 19 f7 c0 07 00 00 00 test \$0x7,%r24 +\s*[a-f0-9]+:\s*66 d5 11 f7 c0 07 00 test \$0x7,%r24w +\s*[a-f0-9]+:\s*d5 40 8d 00\s+lea \(%rax\),%r16d +\s*[a-f0-9]+:\s*d5 40 8d 08\s+lea \(%rax\),%r17d +\s*[a-f0-9]+:\s*d5 40 8d 10\s+lea \(%rax\),%r18d +\s*[a-f0-9]+:\s*d5 40 8d 18\s+lea \(%rax\),%r19d +\s*[a-f0-9]+:\s*d5 40 8d 20\s+lea \(%rax\),%r20d +\s*[a-f0-9]+:\s*d5 40 8d 28\s+lea \(%rax\),%r21d +\s*[a-f0-9]+:\s*d5 40 8d 30\s+lea \(%rax\),%r22d +\s*[a-f0-9]+:\s*d5 40 8d 38\s+lea \(%rax\),%r23d +\s*[a-f0-9]+:\s*d5 44 8d 00\s+lea \(%rax\),%r24d +\s*[a-f0-9]+:\s*d5 44 8d 08\s+lea \(%rax\),%r25d +\s*[a-f0-9]+:\s*d5 44 8d 10\s+lea \(%rax\),%r26d +\s*[a-f0-9]+:\s*d5 44 8d 18\s+lea \(%rax\),%r27d +\s*[a-f0-9]+:\s*d5 44 8d 20\s+lea \(%rax\),%r28d +\s*[a-f0-9]+:\s*d5 44 8d 28\s+lea \(%rax\),%r29d +\s*[a-f0-9]+:\s*d5 44 8d 30\s+lea \(%rax\),%r30d +\s*[a-f0-9]+:\s*d5 44 8d 38\s+lea \(%rax\),%r31d +\s*[a-f0-9]+:\s*d5 20 8d 04 05 00 00 00 00\s+lea 0x0\(,%r16,1\),%eax +\s*[a-f0-9]+:\s*d5 20 8d 04 0d 00 00 00 00\s+lea 0x0\(,%r17,1\),%eax +\s*[a-f0-9]+:\s*d5 20 8d 04 15 00 00 00 00\s+lea 0x0\(,%r18,1\),%eax +\s*[a-f0-9]+:\s*d5 20 8d 04 1d 00 00 00 00\s+lea 0x0\(,%r19,1\),%eax +\s*[a-f0-9]+:\s*d5 20 8d 04 25 00 00 00 00\s+lea 0x0\(,%r20,1\),%eax +\s*[a-f0-9]+:\s*d5 20 8d 04 2d 00 00 00 00\s+lea 0x0\(,%r21,1\),%eax +\s*[a-f0-9]+:\s*d5 20 8d 04 35 00 00 00 00\s+lea 0x0\(,%r22,1\),%eax +\s*[a-f0-9]+:\s*d5 20 8d 04 3d 00 00 00 00\s+lea 0x0\(,%r23,1\),%eax +\s*[a-f0-9]+:\s*d5 22 8d 04 05 00 00 00 00\s+lea 0x0\(,%r24,1\),%eax +\s*[a-f0-9]+:\s*d5 22 8d 04 0d 00 00 00 00\s+lea 0x0\(,%r25,1\),%eax +\s*[a-f0-9]+:\s*d5 22 8d 04 15 00 00 00 00\s+lea 0x0\(,%r26,1\),%eax +\s*[a-f0-9]+:\s*d5 22 8d 04 1d 00 00 00 00\s+lea 0x0\(,%r27,1\),%eax +\s*[a-f0-9]+:\s*d5 22 8d 04 25 00 00 00 00\s+lea 0x0\(,%r28,1\),%eax +\s*[a-f0-9]+:\s*d5 22 8d 04 2d 00 00 00 00\s+lea 0x0\(,%r29,1\),%eax +\s*[a-f0-9]+:\s*d5 22 8d 04 35 00 00 00 00\s+lea 0x0\(,%r30,1\),%eax +\s*[a-f0-9]+:\s*d5 22 8d 04 3d 00 00 00 00\s+lea 0x0\(,%r31,1\),%eax +\s*[a-f0-9]+:\s*d5 10 8d 00\s+lea \(%r16\),%eax +\s*[a-f0-9]+:\s*d5 10 8d 01\s+lea \(%r17\),%eax +\s*[a-f0-9]+:\s*d5 10 8d 02\s+lea \(%r18\),%eax +\s*[a-f0-9]+:\s*d5 10 8d 03\s+lea \(%r19\),%eax +\s*[a-f0-9]+:\s*d5 10 8d 04 24 lea \(%r20\),%eax +\s*[a-f0-9]+:\s*d5 10 8d 45 00 lea 0x0\(%r21\),%eax +\s*[a-f0-9]+:\s*d5 10 8d 06\s+lea \(%r22\),%eax +\s*[a-f0-9]+:\s*d5 10 8d 07\s+lea \(%r23\),%eax +\s*[a-f0-9]+:\s*d5 11 8d 00\s+lea \(%r24\),%eax +\s*[a-f0-9]+:\s*d5 11 8d 01\s+lea \(%r25\),%eax +\s*[a-f0-9]+:\s*d5 11 8d 02\s+lea \(%r26\),%eax +\s*[a-f0-9]+:\s*d5 11 8d 03\s+lea \(%r27\),%eax +\s*[a-f0-9]+:\s*d5 11 8d 04 24 lea \(%r28\),%eax +\s*[a-f0-9]+:\s*d5 11 8d 45 00 lea 0x0\(%r29\),%eax +\s*[a-f0-9]+:\s*d5 11 8d 06 lea \(%r30\),%eax +\s*[a-f0-9]+:\s*d5 11 8d 07 lea \(%r31\),%eax +\s*[a-f0-9]+:\s*d5 10 8d 44 24 01 lea 0x1\(%r20\),%eax +\s*[a-f0-9]+:\s*d5 11 8d 44 24 01 lea 0x1\(%r28\),%eax +\s*[a-f0-9]+:\s*d5 10 8d 84 24 81 00 00 00 lea 0x81\(%r20\),%eax +\s*[a-f0-9]+:\s*d5 11 8d 84 24 81 00 00 00 lea 0x81\(%r28\),%eax +\s*[a-f0-9]+:\s*4c 8d 38 lea \(%rax\),%r15 +\s*[a-f0-9]+:\s*d5 48 8d 00 lea \(%rax\),%r16 +\s*[a-f0-9]+:\s*49 8d 07 lea \(%r15\),%rax +\s*[a-f0-9]+:\s*d5 18 8d 00 lea \(%r16\),%rax +\s*[a-f0-9]+:\s*4a 8d 04 3d 00 00 00 00 lea 0x0\(,%r15,1\),%rax +\s*[a-f0-9]+:\s*d5 28 8d 04 05 00 00 00 00 lea 0x0\(,%r16,1\),%rax +\s*[a-f0-9]+:\s*44 0f af f8 imul %eax,%r15d +\s*[a-f0-9]+:\s*d5 c0 af c0 imul %eax,%r16d +\s*[a-f0-9]+:\s*d5 90 62 12 punpckldq %mm2,\(%r18\) +\s*[a-f0-9]+:\s*d5 10 b8 01 00 00 00 mov \$0x1,%r16d +\s*[a-f0-9]+:\s*d5 18 63 c0\s+movslq %r16d,%rax +\s*[a-f0-9]+:\s*d5 48 63 c0\s+movslq %eax,%r16 +\s*[a-f0-9]+:\s*d5 58 63 c8\s+movslq %r16d,%r17 +\s*[a-f0-9]+:\s*d5 90 4c c0\s+cmovl %r16d,%eax +\s*[a-f0-9]+:\s*d5 c0 4c c0\s+cmovl %eax,%r16d +\s*[a-f0-9]+:\s*d5 d0 4c c8\s+cmovl %r16d,%r17d +\s*[a-f0-9]+:\s*d5 90 af 1c 00\s+imul \(%r16,%rax,1\),%ebx +\s*[a-f0-9]+:\s*d5 a0 af 1c 00\s+imul \(%rax,%r16,1\),%ebx +\s*[a-f0-9]+:\s*d5 c0 af 04 18\s+imul \(%rax,%rbx,1\),%r16d +\s*[a-f0-9]+:\s*d5 b0 af 04 08\s+imul \(%r16,%r17,1\),%eax +\s*[a-f0-9]+:\s*d5 e0 af 0c 00\s+imul \(%rax,%r16,1\),%r17d +\s*[a-f0-9]+:\s*d5 d0 af 0c 00\s+imul \(%r16,%rax,1\),%r17d +\s*[a-f0-9]+:\s*d5 f0 af 14 08\s+imul \(%r16,%r17,1\),%r18d +\s*[a-f0-9]+:\s*d5 90 4c 1c 00\s+cmovl \(%r16,%rax,1\),%ebx +\s*[a-f0-9]+:\s*d5 a0 4c 1c 00\s+cmovl \(%rax,%r16,1\),%ebx +\s*[a-f0-9]+:\s*d5 c0 4c 04 18\s+cmovl \(%rax,%rbx,1\),%r16d +\s*[a-f0-9]+:\s*d5 b0 4c 04 08\s+cmovl \(%r16,%r17,1\),%eax +\s*[a-f0-9]+:\s*d5 e0 4c 0c 00\s+cmovl \(%rax,%r16,1\),%r17d +\s*[a-f0-9]+:\s*d5 d0 4c 0c 00\s+cmovl \(%r16,%rax,1\),%r17d +\s*[a-f0-9]+:\s*d5 f0 4c 14 08\s+cmovl \(%r16,%r17,1\),%r18d +\s*[a-f0-9]+:\s*d5 10 89 c0 \s+mov %eax,%r16d +\s*[a-f0-9]+:\s*d5 40 89 c0 \s+mov %r16d,%eax +\s*[a-f0-9]+:\s*d5 50 89 c1 \s+mov %r16d,%r17d +\s*[a-f0-9]+:\s*d5 10 8b 1c 00\s+mov \(%r16,%rax,1\),%ebx +\s*[a-f0-9]+:\s*d5 20 8b 1c 00\s+mov \(%rax,%r16,1\),%ebx +\s*[a-f0-9]+:\s*d5 40 8b 04 18\s+mov \(%rax,%rbx,1\),%r16d +\s*[a-f0-9]+:\s*d5 30 8b 04 08\s+mov \(%r16,%r17,1\),%eax +\s*[a-f0-9]+:\s*d5 60 8b 0c 00\s+mov \(%rax,%r16,1\),%r17d +\s*[a-f0-9]+:\s*d5 50 8b 0c 00\s+mov \(%r16,%rax,1\),%r17d +\s*[a-f0-9]+:\s*d5 70 8b 14 08\s+mov \(%r16,%r17,1\),%r18d +\s*[a-f0-9]+:\s*d5 a0 94 04 00\s+sete \(%rax,%r16,1\) +\s*[a-f0-9]+:\s*d5 90 94 04 00\s+sete \(%r16,%rax,1\) +\s*[a-f0-9]+:\s*d5 b0 94 04 08\s+sete \(%r16,%r17,1\) +\s*[a-f0-9]+:\s*d5 a0 1f 04 00\s+nopl \(%rax,%r16,1\) +\s*[a-f0-9]+:\s*d5 90 1f 04 00\s+nopl \(%r16,%rax,1\) +\s*[a-f0-9]+:\s*d5 b0 1f 04 08\s+nopl \(%r16,%r17,1\) +\s*[a-f0-9]+:\s*d5 20 ff 04 00\s+incl \(%rax,%r16,1\) +\s*[a-f0-9]+:\s*d5 10 ff 04 00\s+incl \(%r16,%rax,1\) +\s*[a-f0-9]+:\s*d5 30 ff 04 08\s+incl \(%r16,%r17,1\) +\s*[a-f0-9]+:\s*d5 20 ff 0c 00\s+decl \(%rax,%r16,1\) +\s*[a-f0-9]+:\s*d5 10 ff 0c 00\s+decl \(%r16,%rax,1\) +\s*[a-f0-9]+:\s*d5 30 ff 0c 08\s+decl \(%r16,%r17,1\) +\s*[a-f0-9]+:\s*d5 20 f7 14 00\s+notl \(%rax,%r16,1\) +\s*[a-f0-9]+:\s*d5 10 f7 14 00\s+notl \(%r16,%rax,1\) +\s*[a-f0-9]+:\s*d5 30 f7 14 08\s+notl \(%r16,%r17,1\) +\s*[a-f0-9]+:\s*d5 20 f7 1c 00\s+negl \(%rax,%r16,1\) +\s*[a-f0-9]+:\s*d5 10 f7 1c 00\s+negl \(%r16,%rax,1\) +\s*[a-f0-9]+:\s*d5 30 f7 1c 08\s+negl \(%r16,%r17,1\) +\s*[a-f0-9]+:\s*d5 20 f7 24 00\s+mull \(%rax,%r16,1\) +\s*[a-f0-9]+:\s*d5 10 f7 24 00\s+mull \(%r16,%rax,1\) +\s*[a-f0-9]+:\s*d5 30 f7 24 08\s+mull \(%r16,%r17,1\) +\s*[a-f0-9]+:\s*d5 20 f7 2c 00\s+imull \(%rax,%r16,1\) +\s*[a-f0-9]+:\s*d5 10 f7 2c 00\s+imull \(%r16,%rax,1\) +\s*[a-f0-9]+:\s*d5 30 f7 2c 08\s+imull \(%r16,%r17,1\) +\s*[a-f0-9]+:\s*d5 20 f7 34 00\s+divl \(%rax,%r16,1\) +\s*[a-f0-9]+:\s*d5 10 f7 34 00\s+divl \(%r16,%rax,1\) +\s*[a-f0-9]+:\s*d5 30 f7 34 08\s+divl \(%r16,%r17,1\) +\s*[a-f0-9]+:\s*d5 20 f7 3c 00\s+idivl \(%rax,%r16,1\) +\s*[a-f0-9]+:\s*d5 10 f7 3c 00\s+idivl \(%r16,%rax,1\) +\s*[a-f0-9]+:\s*d5 30 f7 3c 08\s+idivl \(%r16,%r17,1\) +\s*[a-f0-9]+:\s*d5 90 94 c0 \s+sete %r16b +\s*[a-f0-9]+:\s*d5 90 1f c0 \s+nop %r16d +\s*[a-f0-9]+:\s*d5 10 ff c0 \s+inc %r16d +\s*[a-f0-9]+:\s*d5 10 ff c8 \s+dec %r16d +\s*[a-f0-9]+:\s*d5 10 f7 d0 \s+not %r16d +\s*[a-f0-9]+:\s*d5 10 f7 d8 \s+neg %r16d +\s*[a-f0-9]+:\s*d5 10 f7 e0 \s+mul %r16d +\s*[a-f0-9]+:\s*d5 10 f7 e8 \s+imul %r16d +\s*[a-f0-9]+:\s*d5 10 f7 f0 \s+div %r16d +\s*[a-f0-9]+:\s*d5 10 f7 f8 \s+idiv %r16d +#pass diff --git a/gas/testsuite/gas/i386/x86-64-apx-rex2.s b/gas/testsuite/gas/i386/x86-64-apx-rex2.s new file mode 100644 index 00000000000..62bf817aae6 --- /dev/null +++ b/gas/testsuite/gas/i386/x86-64-apx-rex2.s @@ -0,0 +1,175 @@ +# Check 64bit instructions with rex2 prefix encoding + + .allow_index_reg + .text +_start: + test $0x7, %r24b + test $0x7, %r24d + test $0x7, %r24 + test $0x7, %r24w +## R bit + leal (%rax), %r16d + leal (%rax), %r17d + leal (%rax), %r18d + leal (%rax), %r19d + leal (%rax), %r20d + leal (%rax), %r21d + leal (%rax), %r22d + leal (%rax), %r23d + leal (%rax), %r24d + leal (%rax), %r25d + leal (%rax), %r26d + leal (%rax), %r27d + leal (%rax), %r28d + leal (%rax), %r29d + leal (%rax), %r30d + leal (%rax), %r31d +## X bit + leal (,%r16), %eax + leal (,%r17), %eax + leal (,%r18), %eax + leal (,%r19), %eax + leal (,%r20), %eax + leal (,%r21), %eax + leal (,%r22), %eax + leal (,%r23), %eax + leal (,%r24), %eax + leal (,%r25), %eax + leal (,%r26), %eax + leal (,%r27), %eax + leal (,%r28), %eax + leal (,%r29), %eax + leal (,%r30), %eax + leal (,%r31), %eax +## B bit + leal (%r16), %eax + leal (%r17), %eax + leal (%r18), %eax + leal (%r19), %eax + leal (%r20), %eax + leal (%r21), %eax + leal (%r22), %eax + leal (%r23), %eax + leal (%r24), %eax + leal (%r25), %eax + leal (%r26), %eax + leal (%r27), %eax + leal (%r28), %eax + leal (%r29), %eax + leal (%r30), %eax + leal (%r31), %eax +## SIB + leal 1(%r20), %eax + leal 1(%r28), %eax + leal 129(%r20), %eax + leal 129(%r28), %eax +## W bit + leaq (%rax), %r15 + leaq (%rax), %r16 + leaq (%r15), %rax + leaq (%r16), %rax + leaq (,%r15), %rax + leaq (,%r16), %rax +## M bit + imull %eax, %r15d + imull %eax, %r16d + punpckldq (%r18), %mm2 #D5906212 + +## AddRegFrm + movl $1, %r16d +## MRMSrcReg + movslq %r16d, %rax + movslq %eax, %r16 + movslq %r16d, %r17 +## MRMSrcRegCC + cmovll %r16d, %eax + cmovll %eax, %r16d + cmovll %r16d, %r17d +## MRMSrcMem + imull (%r16,%rax), %ebx + imull (%rax,%r16), %ebx + imull (%rax,%rbx), %r16d + imull (%r16,%r17), %eax + imull (%rax,%r16), %r17d + imull (%r16,%rax), %r17d + imull (%r16,%r17), %r18d +## MRMSrcMemCC + cmovll (%r16,%rax), %ebx + cmovll (%rax,%r16), %ebx + cmovll (%rax,%rbx), %r16d + cmovll (%r16,%r17), %eax + cmovll (%rax,%r16), %r17d + cmovll (%r16,%rax), %r17d + cmovll (%r16,%r17), %r18d +## MRMDestReg + movl %eax, %r16d + movl %r16d, %eax + movl %r16d, %r17d +## MRMDestMem + movl (%r16,%rax), %ebx + movl (%rax,%r16), %ebx + movl (%rax,%rbx), %r16d + movl (%r16,%r17), %eax + movl (%rax,%r16), %r17d + movl (%r16,%rax), %r17d + movl (%r16,%r17), %r18d +## MRMXmCC + sete (%rax,%r16) + sete (%r16,%rax) + sete (%r16,%r17) +## MRMXm + nopl (%rax,%r16) + nopl (%r16,%rax) + nopl (%r16,%r17) +## MRM0m + incl (%rax,%r16) + incl (%r16,%rax) + incl (%r16,%r17) +## MRM1m + decl (%rax,%r16) + decl (%r16,%rax) + decl (%r16,%r17) +## MRM2m + notl (%rax,%r16) + notl (%r16,%rax) + notl (%r16,%r17) +## MRM3m + negl (%rax,%r16) + negl (%r16,%rax) + negl (%r16,%r17) +## MRM4m + mull (%rax,%r16) + mull (%r16,%rax) + mull (%r16,%r17) +## MRM5m + imull (%rax,%r16) + imull (%r16,%rax) + imull (%r16,%r17) +## MRM6m + divl (%rax,%r16) + divl (%r16,%rax) + divl (%r16,%r17) +## MRM7m + idivl (%rax,%r16) + idivl (%r16,%rax) + idivl (%r16,%r17) +## MRMXrCC + sete %r16b +## MRMXr + nopl %r16d +## MRM0r + incl %r16d +## MRM1r + decl %r16d +## MRM2r + notl %r16d +## MRM3r + negl %r16d +## MRM4r + mull %r16d +## MRM5r + imull %r16d +## MRM6r + divl %r16d +## MRM7r + idivl %r16d diff --git a/gas/testsuite/gas/i386/x86-64-inval-pseudo.l b/gas/testsuite/gas/i386/x86-64-inval-pseudo.l index 13ad0fb768f..9f5488d8218 100644 --- a/gas/testsuite/gas/i386/x86-64-inval-pseudo.l +++ b/gas/testsuite/gas/i386/x86-64-inval-pseudo.l @@ -1,10 +1,22 @@ .*: Assembler messages: .*:2: Error: .* .*:3: Error: .* +.*:6: Error: .* +.*:7: Error: .* +.*:10: Error: .* +.*:11: Error: .* GAS LISTING .* [ ]*1[ ]+\.text [ ]*2[ ]+\{disp16\} movb \(%ebp\),%al [ ]*3[ ]+\{disp16\} movb \(%rbp\),%al +[ ]*4[ ]+ +[ ]*5[ ]+.* +[ ]*6[ ]+\{rex2\} xsave \(%r15, %rbx\) +[ ]*7[ ]+\{rex2\} xsave64 \(%r15, %rbx\) +[ ]*8[ ]+ +[ ]*9[ ]+.* +[ ]*10[ ]+\{rex\} movl %eax,\(%r16\) +[ ]*11[ ]+\{rex\} movl %r16d,\(%r8\) #... diff --git a/gas/testsuite/gas/i386/x86-64-inval-pseudo.s b/gas/testsuite/gas/i386/x86-64-inval-pseudo.s index c10b14c2099..8b387de9319 100644 --- a/gas/testsuite/gas/i386/x86-64-inval-pseudo.s +++ b/gas/testsuite/gas/i386/x86-64-inval-pseudo.s @@ -1,4 +1,12 @@ .text {disp16} movb (%ebp),%al {disp16} movb (%rbp),%al + + /* Instruction not support APX. */ + {rex2} xsave (%r15, %rbx) + {rex2} xsave64 (%r15, %rbx) + + /* Add pseudo prefix {rex} for GPR32 register. */ + {rex} movl %eax,(%r16) + {rex} movl %r16d,(%r8) .p2align 4,0 diff --git a/gas/testsuite/gas/i386/x86-64-opcode-inval-intel.d b/gas/testsuite/gas/i386/x86-64-opcode-inval-intel.d index 6ee5b2f95ce..03126541f24 100644 --- a/gas/testsuite/gas/i386/x86-64-opcode-inval-intel.d +++ b/gas/testsuite/gas/i386/x86-64-opcode-inval-intel.d @@ -11,11 +11,11 @@ Disassembly of section .text: [ ]*[a-f0-9]+: 37 \(bad\) 0+1 : -[ ]*[a-f0-9]+: d5 \(bad\) +[ ]*[a-f0-9]+: d5 rex2 [ ]*[a-f0-9]+: 0a .byte 0xa 0+3 : -[ ]*[a-f0-9]+: d5 \(bad\) +[ ]*[a-f0-9]+: d5 rex2 [ ]*[a-f0-9]+: 02 .byte 0x2 0+5 : diff --git a/gas/testsuite/gas/i386/x86-64-opcode-inval.d b/gas/testsuite/gas/i386/x86-64-opcode-inval.d index 12f02c1766c..0200f3dfd92 100644 --- a/gas/testsuite/gas/i386/x86-64-opcode-inval.d +++ b/gas/testsuite/gas/i386/x86-64-opcode-inval.d @@ -10,11 +10,11 @@ Disassembly of section .text: [ ]*[a-f0-9]+: 37 \(bad\) 0+1 : -[ ]*[a-f0-9]+: d5 \(bad\) +[ ]*[a-f0-9]+: d5 rex2 [ ]*[a-f0-9]+: 0a .byte 0xa 0+3 : -[ ]*[a-f0-9]+: d5 \(bad\) +[ ]*[a-f0-9]+: d5 rex2 [ ]*[a-f0-9]+: 02 .byte 0x2 0+5 : diff --git a/gas/testsuite/gas/i386/x86-64-pseudos.d b/gas/testsuite/gas/i386/x86-64-pseudos.d index 0cc75ef2457..8cc4040cb77 100644 --- a/gas/testsuite/gas/i386/x86-64-pseudos.d +++ b/gas/testsuite/gas/i386/x86-64-pseudos.d @@ -404,6 +404,18 @@ Disassembly of section .text: +[a-f0-9]+: 41 0f 28 10 movaps \(%r8\),%xmm2 +[a-f0-9]+: 40 0f 38 01 01 rex phaddw \(%rcx\),%mm0 +[a-f0-9]+: 41 0f 38 01 00 phaddw \(%r8\),%mm0 + +[a-f0-9]+: 88 c4 mov %al,%ah + +[a-f0-9]+: d5 00 d3 e0 {rex2} shl %cl,%eax + +[a-f0-9]+: d5 00 a0 01 00 00 00 00 00 00 00 {rex2} movabs 0x1,%al + +[a-f0-9]+: d5 00 38 ca {rex2} cmp %cl,%dl + +[a-f0-9]+: d5 00 b3 01 {rex2} mov \$(0x)?1,%bl + +[a-f0-9]+: d5 00 89 c3 {rex2} mov %eax,%ebx + +[a-f0-9]+: d5 01 89 c6 {rex2} mov %eax,%r14d + +[a-f0-9]+: d5 01 89 00 {rex2} mov %eax,\(%r8\) + +[a-f0-9]+: d5 80 28 d7 {rex2} movaps %xmm7,%xmm2 + +[a-f0-9]+: d5 84 28 e7 {rex2} movaps %xmm7,%xmm12 + +[a-f0-9]+: d5 80 28 11 {rex2} movaps \(%rcx\),%xmm2 + +[a-f0-9]+: d5 81 28 10 {rex2} movaps \(%r8\),%xmm2 +[a-f0-9]+: 8a 45 00 mov 0x0\(%rbp\),%al +[a-f0-9]+: 8a 45 00 mov 0x0\(%rbp\),%al +[a-f0-9]+: 8a 85 00 00 00 00 mov 0x0\(%rbp\),%al @@ -458,6 +470,14 @@ Disassembly of section .text: +[a-f0-9]+: 41 0f 28 10 movaps \(%r8\),%xmm2 +[a-f0-9]+: 40 0f 38 01 01 rex phaddw \(%rcx\),%mm0 +[a-f0-9]+: 41 0f 38 01 00 phaddw \(%r8\),%mm0 + +[a-f0-9]+: 88 c4 mov %al,%ah + +[a-f0-9]+: d5 00 89 c3 {rex2} mov %eax,%ebx + +[a-f0-9]+: d5 01 89 c6 {rex2} mov %eax,%r14d + +[a-f0-9]+: d5 01 89 00 {rex2} mov %eax,\(%r8\) + +[a-f0-9]+: d5 80 28 d7 {rex2} movaps %xmm7,%xmm2 + +[a-f0-9]+: d5 84 28 e7 {rex2} movaps %xmm7,%xmm12 + +[a-f0-9]+: d5 80 28 11 {rex2} movaps \(%rcx\),%xmm2 + +[a-f0-9]+: d5 81 28 10 {rex2} movaps \(%r8\),%xmm2 +[a-f0-9]+: 8a 45 00 mov 0x0\(%rbp\),%al +[a-f0-9]+: 8a 45 00 mov 0x0\(%rbp\),%al +[a-f0-9]+: 8a 85 00 00 00 00 mov 0x0\(%rbp\),%al diff --git a/gas/testsuite/gas/i386/x86-64-pseudos.s b/gas/testsuite/gas/i386/x86-64-pseudos.s index 08fac8381c6..eb25f2a8fbf 100644 --- a/gas/testsuite/gas/i386/x86-64-pseudos.s +++ b/gas/testsuite/gas/i386/x86-64-pseudos.s @@ -360,6 +360,19 @@ _start: {rex} movaps (%r8),%xmm2 {rex} phaddw (%rcx),%mm0 {rex} phaddw (%r8),%mm0 + {rex2} mov %al,%ah + {rex2} shl %cl, %eax + {rex2} movabs 1, %al + {rex2} cmp %cl, %dl + {rex2} mov $1, %bl + {rex2} movl %eax,%ebx + {rex2} movl %eax,%r14d + {rex2} movl %eax,(%r8) + {rex2} movaps %xmm7,%xmm2 + {rex2} movaps %xmm7,%xmm12 + {rex2} movaps (%rcx),%xmm2 + {rex2} movaps (%r8),%xmm2 + movb (%rbp),%al {disp8} movb (%rbp),%al @@ -422,6 +435,14 @@ _start: {rex} movaps xmm2,XMMWORD PTR [r8] {rex} phaddw mm0,QWORD PTR [rcx] {rex} phaddw mm0,QWORD PTR [r8] + {rex2} mov ah,al + {rex2} mov ebx,eax + {rex2} mov r14d,eax + {rex2} mov DWORD PTR [r8],eax + {rex2} movaps xmm2,xmm7 + {rex2} movaps xmm12,xmm7 + {rex2} movaps xmm2,XMMWORD PTR [rcx] + {rex2} movaps xmm2,XMMWORD PTR [r8] mov al, BYTE PTR [rbp] {disp8} mov al, BYTE PTR [rbp] diff --git a/gas/testsuite/gas/i386/x86-64.exp b/gas/testsuite/gas/i386/x86-64.exp index 52711cdcf6f..07df89ba0cc 100644 --- a/gas/testsuite/gas/i386/x86-64.exp +++ b/gas/testsuite/gas/i386/x86-64.exp @@ -360,6 +360,9 @@ run_dump_test "x86-64-avx512f-rcigrne-intel" run_dump_test "x86-64-avx512f-rcigrne" run_dump_test "x86-64-avx512f-rcigru-intel" run_dump_test "x86-64-avx512f-rcigru" +run_list_test "x86-64-apx-egpr-inval" "-al" +run_dump_test "x86-64-apx-rex2" +run_dump_test "x86-64-apx-rex2-inval" run_dump_test "x86-64-avx512f-rcigrz-intel" run_dump_test "x86-64-avx512f-rcigrz" run_dump_test "x86-64-clwb" diff --git a/include/opcode/i386.h b/include/opcode/i386.h index dec7652c1cc..a6af3d54da0 100644 --- a/include/opcode/i386.h +++ b/include/opcode/i386.h @@ -112,6 +112,8 @@ /* x86-64 extension prefix. */ #define REX_OPCODE 0x40 +#define REX2_OPCODE 0xd5 + /* Non-zero if OPCODE is the rex prefix. */ #define REX_PREFIX_P(opcode) (((opcode) & 0xf0) == REX_OPCODE) diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c index 87ecf0f5e23..65bdd6f65db 100644 --- a/opcodes/i386-dis.c +++ b/opcodes/i386-dis.c @@ -144,6 +144,12 @@ struct instr_info /* Bits of REX we've already used. */ uint8_t rex_used; + /* REX2 prefix for the current instruction use gpr32(r16-r31). */ + unsigned char rex2; + /* Bits of REX2 we've already used. */ + unsigned char rex2_used; + unsigned char rex2_payload; + bool need_modrm; unsigned char need_vex; bool has_sib; @@ -169,6 +175,7 @@ struct instr_info signed char last_data_prefix; signed char last_addr_prefix; signed char last_rex_prefix; + signed char last_rex2_prefix; signed char last_seg_prefix; signed char fwait_prefix; /* The active segment register prefix. */ @@ -269,6 +276,12 @@ struct dis_private { ins->rex_used |= REX_OPCODE; \ } +#define USED_REX2(value) \ + { \ + if ((ins->rex2 & value)) \ + ins->rex2_used |= value; \ + } + #define EVEX_b_used 1 #define EVEX_len_used 2 @@ -286,6 +299,7 @@ struct dis_private { #define PREFIX_DATA 0x200 #define PREFIX_ADDR 0x400 #define PREFIX_FWAIT 0x800 +#define PREFIX_REX2 0x1000 /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive) to ADDR (exclusive) are valid. Returns true for success, false @@ -367,6 +381,7 @@ fetch_error (const instr_info *ins) #define PREFIX_IGNORED_DATA (PREFIX_DATA << PREFIX_IGNORED_SHIFT) #define PREFIX_IGNORED_ADDR (PREFIX_ADDR << PREFIX_IGNORED_SHIFT) #define PREFIX_IGNORED_LOCK (PREFIX_LOCK << PREFIX_IGNORED_SHIFT) +#define PREFIX_IGNORED_REX2 (PREFIX_REX2 << PREFIX_IGNORED_SHIFT) /* Opcode prefixes. */ #define PREFIX_OPCODE (PREFIX_REPZ \ @@ -2390,22 +2405,30 @@ static const char intel_index16[][6] = { static const char att_names64[][8] = { "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi", - "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" + "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", + "%r16", "%r17", "%r18", "%r19", "%r20", "%r21", "%r22", "%r23", + "%r24", "%r25", "%r26", "%r27", "%r28", "%r29", "%r30", "%r31" }; static const char att_names32[][8] = { "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi", - "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d" + "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d", + "%r16d", "%r17d", "%r18d", "%r19d", "%r20d", "%r21d", "%r22d", "%r23d", + "%r24d", "%r25d", "%r26d", "%r27d", "%r28d", "%r29d", "%r30d", "%r31d" }; static const char att_names16[][8] = { "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di", - "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w" + "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w", + "%r16w", "%r17w", "%r18w", "%r19w", "%r20w", "%r21w", "%r22w", "%r23w", + "%r24w", "%r25w", "%r26w", "%r27w", "%r28w", "%r29w", "%r30w", "%r31w" }; static const char att_names8[][8] = { "%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh", }; static const char att_names8rex[][8] = { "%al", "%cl", "%dl", "%bl", "%spl", "%bpl", "%sil", "%dil", - "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b" + "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b", + "%r16b", "%r17b", "%r18b", "%r19b", "%r20b", "%r21b", "%r22b", "%r23b", + "%r24b", "%r25b", "%r26b", "%r27b", "%r28b", "%r29b", "%r30b", "%r31b" }; static const char att_names_seg[][4] = { "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "%?", "%?", @@ -2794,9 +2817,9 @@ static const struct dis386 reg_table[][8] = { { Bad_Opcode }, { "cmpxchg8b", { { CMPXCHG8B_Fixup, q_mode } }, 0 }, { Bad_Opcode }, - { "xrstors", { FXSAVE }, 0 }, - { "xsavec", { FXSAVE }, 0 }, - { "xsaves", { FXSAVE }, 0 }, + { "xrstors", { FXSAVE }, PREFIX_IGNORED_REX2 }, + { "xsavec", { FXSAVE }, PREFIX_IGNORED_REX2 }, + { "xsaves", { FXSAVE }, PREFIX_IGNORED_REX2 }, { MOD_TABLE (MOD_0FC7_REG_6) }, { MOD_TABLE (MOD_0FC7_REG_7) }, }, @@ -3364,7 +3387,7 @@ static const struct dis386 prefix_table[][4] = { /* PREFIX_0FAE_REG_4_MOD_0 */ { - { "xsave", { FXSAVE }, 0 }, + { "xsave", { FXSAVE }, PREFIX_IGNORED_REX2 }, { "ptwrite{%LQ|}", { Edq }, 0 }, }, @@ -3382,7 +3405,7 @@ static const struct dis386 prefix_table[][4] = { /* PREFIX_0FAE_REG_6_MOD_0 */ { - { "xsaveopt", { FXSAVE }, PREFIX_OPCODE }, + { "xsaveopt", { FXSAVE }, PREFIX_OPCODE | PREFIX_IGNORED_REX2 }, { "clrssbsy", { Mq }, PREFIX_OPCODE }, { "clwb", { Mb }, PREFIX_OPCODE }, }, @@ -8125,7 +8148,7 @@ static const struct dis386 mod_table[][2] = { }, { /* MOD_0FAE_REG_5 */ - { "xrstor", { FXSAVE }, PREFIX_OPCODE }, + { "xrstor", { FXSAVE }, PREFIX_OPCODE | PREFIX_IGNORED_REX2 }, { PREFIX_TABLE (PREFIX_0FAE_REG_5_MOD_3) }, }, { @@ -8323,6 +8346,24 @@ ckprefix (instr_info *ins) return ckp_okay; ins->last_rex_prefix = i; break; + /* REX2 must be the last prefix. */ + case 0xd5: + if (ins->address_mode == mode_64bit) + { + if (ins->last_rex_prefix >= 0) + return ckp_bogus; + + ins->codep++; + if (!fetch_code (ins->info, ins->codep + 1)) + return ckp_fetch_error; + ins->rex2_payload = *ins->codep; + ins->rex2 = ins->rex2_payload >> 4; + ins->rex = (ins->rex2_payload & 0xf) | REX_OPCODE; + ins->codep++; + ins->last_rex2_prefix = i; + ins->all_prefixes[i] = REX2_OPCODE; + } + return ckp_okay; case 0xf3: ins->prefixes |= PREFIX_REPZ; ins->last_repz_prefix = i; @@ -8490,6 +8531,8 @@ prefix_name (enum address_mode mode, uint8_t pref, int sizeflag) return "bnd"; case NOTRACK_PREFIX: return "notrack"; + case REX2_OPCODE: + return "rex2"; default: return NULL; } @@ -8628,6 +8671,8 @@ get_valid_dis386 (const struct dis386 *dp, instr_info *ins) break; case USE_3BYTE_TABLE: + if (ins->last_rex2_prefix >= 0) + return &bad_opcode; if (!fetch_code (ins->info, ins->codep + 2)) return &err_opcode; vindex = *ins->codep++; @@ -8751,6 +8796,8 @@ get_valid_dis386 (const struct dis386 *dp, instr_info *ins) break; case USE_VEX_C4_TABLE: + if (ins->last_rex2_prefix >= 0) + return &bad_opcode; /* VEX prefix. */ if (!fetch_code (ins->info, ins->codep + 3)) return &err_opcode; @@ -8812,6 +8859,8 @@ get_valid_dis386 (const struct dis386 *dp, instr_info *ins) break; case USE_VEX_C5_TABLE: + if (ins->last_rex2_prefix >= 0) + return &bad_opcode; /* VEX prefix. */ if (!fetch_code (ins->info, ins->codep + 2)) return &err_opcode; @@ -8853,6 +8902,8 @@ get_valid_dis386 (const struct dis386 *dp, instr_info *ins) break; case USE_EVEX_TABLE: + if (ins->last_rex2_prefix >= 0) + return &bad_opcode; ins->two_source_ops = false; /* EVEX prefix. */ ins->vex.evex = true; @@ -9128,6 +9179,7 @@ print_insn (bfd_vma pc, disassemble_info *info, int intel_syntax) .last_data_prefix = -1, .last_addr_prefix = -1, .last_rex_prefix = -1, + .last_rex2_prefix = -1, .last_seg_prefix = -1, .fwait_prefix = -1, }; @@ -9292,13 +9344,17 @@ print_insn (bfd_vma pc, disassemble_info *info, int intel_syntax) goto out; } - if (*ins.codep == 0x0f) + /* M0 in rex2 prefix represents map0 or map1. */ + if (*ins.codep == 0x0f || (ins.rex2 & 0x8)) { unsigned char threebyte; - ins.codep++; - if (!fetch_code (info, ins.codep + 1)) - goto fetch_error_out; + if (!ins.rex2) + { + ins.codep++; + if (!fetch_code (info, ins.codep + 1)) + goto fetch_error_out; + } threebyte = *ins.codep; dp = &dis386_twobyte[threebyte]; ins.need_modrm = twobyte_has_modrm[threebyte]; @@ -9454,6 +9510,14 @@ print_insn (bfd_vma pc, disassemble_info *info, int intel_syntax) goto out; } + if ((dp->prefix_requirement & PREFIX_IGNORED_REX2) + && ins.last_rex2_prefix >= 0) + { + i386_dis_printf (info, dis_style_text, "(bad)"); + ret = ins.end_codep - priv.the_buffer; + goto out; + } + switch (dp->prefix_requirement) { case PREFIX_DATA: @@ -9468,6 +9532,7 @@ print_insn (bfd_vma pc, disassemble_info *info, int intel_syntax) ins.used_prefixes |= PREFIX_DATA; /* Fall through. */ case PREFIX_OPCODE: + case PREFIX_OPCODE | PREFIX_IGNORED_REX2: /* If the mandatory PREFIX_REPZ/PREFIX_REPNZ/PREFIX_DATA prefix is unused, opcode is invalid. Since the PREFIX_DATA prefix may be used by putop and MMX/SSE operand and may be overridden by the @@ -9510,9 +9575,17 @@ print_insn (bfd_vma pc, disassemble_info *info, int intel_syntax) /* Check if the REX prefix is used. */ if ((ins.rex ^ ins.rex_used) == 0 - && !ins.need_vex && ins.last_rex_prefix >= 0) + && !ins.need_vex && ins.last_rex_prefix >= 0 + && ins.last_rex2_prefix < 0) ins.all_prefixes[ins.last_rex_prefix] = 0; + /* Check if the REX2 prefix is used. */ + if (ins.last_rex2_prefix >= 0 + && ((((ins.rex2 & 0x7) ^ (ins.rex2_used & 0x7)) == 0 + && (ins.rex2 & 0x7)) + || dp == &bad_opcode)) + ins.all_prefixes[ins.last_rex2_prefix] = 0; + /* Check if the SEG prefix is used. */ if ((ins.prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS | PREFIX_ES | PREFIX_FS | PREFIX_GS)) != 0 @@ -9541,7 +9614,10 @@ print_insn (bfd_vma pc, disassemble_info *info, int intel_syntax) if (name == NULL) abort (); prefix_length += strlen (name) + 1; - i386_dis_printf (info, dis_style_mnemonic, "%s ", name); + if (ins.all_prefixes[i] == REX2_OPCODE) + i386_dis_printf (info, dis_style_mnemonic, "{%s} ", name); + else + i386_dis_printf (info, dis_style_mnemonic, "%s ", name); } /* Check maximum code length. */ @@ -11086,8 +11162,11 @@ print_register (instr_info *ins, unsigned int reg, unsigned int rexmask, ins->illegal_masking = true; USED_REX (rexmask); + USED_REX2 (rexmask); if (ins->rex & rexmask) reg += 8; + if (ins->rex2 & rexmask) + reg += 16; switch (bytemode) { @@ -11307,6 +11386,7 @@ static bool OP_E_memory (instr_info *ins, int bytemode, int sizeflag) { int add = (ins->rex & REX_B) ? 8 : 0; + add += (ins->rex2 & REX_B) ? 16 : 0; int riprel = 0; int shift; @@ -11414,6 +11494,7 @@ OP_E_memory (instr_info *ins, int bytemode, int sizeflag) shift = 0; USED_REX (REX_B); + USED_REX2 (REX_B); if (ins->intel_syntax) intel_operand_size (ins, bytemode, sizeflag); append_seg (ins); @@ -11444,8 +11525,11 @@ OP_E_memory (instr_info *ins, int bytemode, int sizeflag) { vindex = ins->sib.index; USED_REX (REX_X); + USED_REX2 (REX_X); if (ins->rex & REX_X) vindex += 8; + if (ins->rex2 & REX_X) + vindex += 16; switch (bytemode) { case vex_vsib_d_w_dq_mode: @@ -11866,7 +11950,7 @@ static bool OP_REG (instr_info *ins, int code, int sizeflag) { const char *s; - int add; + int add = 0; switch (code) { @@ -11877,10 +11961,11 @@ OP_REG (instr_info *ins, int code, int sizeflag) } USED_REX (REX_B); + USED_REX2 (REX_B); if (ins->rex & REX_B) add = 8; - else - add = 0; + if (ins->rex2 & REX_B) + add += 16; switch (code) { @@ -12590,8 +12675,11 @@ OP_EX (instr_info *ins, int bytemode, int sizeflag) reg = ins->modrm.rm; USED_REX (REX_B); + USED_REX2 (REX_B); if (ins->rex & REX_B) reg += 8; + if (ins->rex2 & REX_B) + reg += 16; if (ins->vex.evex) { USED_REX (REX_X); diff --git a/opcodes/i386-gen.c b/opcodes/i386-gen.c index cfc5a7a6172..6b8eb729797 100644 --- a/opcodes/i386-gen.c +++ b/opcodes/i386-gen.c @@ -380,6 +380,7 @@ static bitfield cpu_flags[] = BITFIELD (RAO_INT), BITFIELD (FRED), BITFIELD (LKGS), + BITFIELD (APX_F), BITFIELD (MWAITX), BITFIELD (CLZERO), BITFIELD (OSPKE), @@ -469,6 +470,7 @@ static bitfield opcode_modifiers[] = BITFIELD (ATTSyntax), BITFIELD (IntelSyntax), BITFIELD (ISA64), + BITFIELD (No_egpr), }; #define CLASS(n) #n, n diff --git a/opcodes/i386-opc.h b/opcodes/i386-opc.h index 149ae0e950c..a055db5ce42 100644 --- a/opcodes/i386-opc.h +++ b/opcodes/i386-opc.h @@ -317,6 +317,8 @@ enum i386_cpu CpuAVX512F, /* Intel AVX-512 VL Instructions support required. */ CpuAVX512VL, + /* Intel APX Instructions support required. */ + CpuAPX_F, /* Not supported in the 64bit mode */ CpuNo64, @@ -352,6 +354,7 @@ enum i386_cpu cpuhle:1, \ cpuavx512f:1, \ cpuavx512vl:1, \ + cpuapx_f:1, \ /* NOTE: This field needs to remain last. */ \ cpuno64:1 @@ -742,6 +745,10 @@ enum #define INTEL64 2 #define INTEL64ONLY 3 ISA64, + + /* egprs (r16-r31) on instruction illegal. */ + No_egpr, + /* The last bitfield in i386_opcode_modifier. */ Opcode_Modifier_Num }; @@ -789,6 +796,7 @@ typedef struct i386_opcode_modifier unsigned int attsyntax:1; unsigned int intelsyntax:1; unsigned int isa64:2; + unsigned int no_egpr:1; } i386_opcode_modifier; /* Operand classes. */ @@ -988,7 +996,7 @@ typedef struct insn_template AMD 3DNow! instructions. If this template has no extension opcode (the usual case) use None Instructions */ - signed int extension_opcode:9; + signed int extension_opcode:0xA; #define None (-1) /* If no extension_opcode is possible. */ /* Pseudo prefixes. */ @@ -1001,7 +1009,8 @@ typedef struct insn_template #define Prefix_VEX3 6 /* {vex3} */ #define Prefix_EVEX 7 /* {evex} */ #define Prefix_REX 8 /* {rex} */ -#define Prefix_NoOptimize 9 /* {nooptimize} */ +#define Prefix_REX2 9 /* {rex2} */ +#define Prefix_NoOptimize 0xA /* {nooptimize} */ /* the bits in opcode_modifier are used to generate the final opcode from the base_opcode. These bits also are used to detect alternate forms of @@ -1028,6 +1037,7 @@ typedef struct #define RegRex 0x1 /* Extended register. */ #define RegRex64 0x2 /* Extended 8 bit register. */ #define RegVRex 0x4 /* Extended vector register. */ +#define RegRex2 0x8 /* Extended rex2 interge register. */ unsigned char reg_num; #define RegIP ((unsigned char ) ~0) /* EIZ and RIZ are fake index registers. */ diff --git a/opcodes/i386-opc.tbl b/opcodes/i386-opc.tbl index a534c53ca17..80248e5b72c 100644 --- a/opcodes/i386-opc.tbl +++ b/opcodes/i386-opc.tbl @@ -889,7 +889,7 @@ rex.wrxb, 0x4f, x64, NoSuf|IsPrefix, {} + rex:REX:x64, rex2:REX2:x64, nooptimize:NoOptimize:0> {}, PSEUDO_PREFIX/Prefix_, , NoSuf|IsPrefix, {} @@ -1422,16 +1422,16 @@ crc32, 0xf20f38f0, SSE4_2|x64, W|Modrm|No_wSuf|No_lSuf|No_sSuf, { Reg8|Reg64|Uns // xsave/xrstor New Instructions. -xsave, 0xfae/4, Xsave, Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf, { Unspecified|BaseIndex } -xsave64, 0xfae/4, Xsave|x64, Modrm|NoSuf|Size64, { Unspecified|BaseIndex } -xrstor, 0xfae/5, Xsave, Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf, { Unspecified|BaseIndex } -xrstor64, 0xfae/5, Xsave|x64, Modrm|NoSuf|Size64, { Unspecified|BaseIndex } +xsave, 0xfae/4, Xsave, Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_egpr, { Unspecified|BaseIndex } +xsave64, 0xfae/4, Xsave|x64, Modrm|NoSuf|Size64|No_egpr, { Unspecified|BaseIndex } +xrstor, 0xfae/5, Xsave, Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_egpr, { Unspecified|BaseIndex } +xrstor64, 0xfae/5, Xsave|x64, Modrm|NoSuf|Size64|No_egpr, { Unspecified|BaseIndex } xgetbv, 0xf01d0, Xsave, NoSuf, {} xsetbv, 0xf01d1, Xsave, NoSuf, {} // xsaveopt -xsaveopt, 0xfae/6, Xsaveopt, Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf, { Unspecified|BaseIndex } -xsaveopt64, 0xfae/6, Xsaveopt|x64, Modrm|NoSuf|Size64, { Unspecified|BaseIndex } +xsaveopt, 0xfae/6, Xsaveopt, Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_egpr, { Unspecified|BaseIndex } +xsaveopt64, 0xfae/6, Xsaveopt|x64, Modrm|NoSuf|Size64|No_egpr, { Unspecified|BaseIndex } // AES instructions. @@ -2492,17 +2492,17 @@ clflushopt, 0x660fae/7, ClflushOpt, Modrm|Anysize|IgnoreSize|NoSuf, { BaseIndex // XSAVES/XRSTORS instructions. -xrstors, 0xfc7/3, XSAVES, Modrm|NoSuf, { Unspecified|BaseIndex } -xrstors64, 0xfc7/3, XSAVES|x64, Modrm|NoSuf|Size64, { Unspecified|BaseIndex } -xsaves, 0xfc7/5, XSAVES, Modrm|NoSuf, { Unspecified|BaseIndex } -xsaves64, 0xfc7/5, XSAVES|x64, Modrm|NoSuf|Size64, { Unspecified|BaseIndex } +xrstors, 0xfc7/3, XSAVES, Modrm|NoSuf|No_egpr, { Unspecified|BaseIndex } +xrstors64, 0xfc7/3, XSAVES|x64, Modrm|NoSuf|Size64|No_egpr, { Unspecified|BaseIndex } +xsaves, 0xfc7/5, XSAVES, Modrm|NoSuf|No_egpr, { Unspecified|BaseIndex } +xsaves64, 0xfc7/5, XSAVES|x64, Modrm|NoSuf|Size64|No_egpr, { Unspecified|BaseIndex } // XSAVES instructions end. // XSAVEC instructions. -xsavec, 0xfc7/4, XSAVEC, Modrm|NoSuf, { Unspecified|BaseIndex } -xsavec64, 0xfc7/4, XSAVEC|x64, Modrm|NoSuf|Size64, { Unspecified|BaseIndex } +xsavec, 0xfc7/4, XSAVEC, Modrm|NoSuf|No_egpr, { Unspecified|BaseIndex } +xsavec64, 0xfc7/4, XSAVEC|x64, Modrm|NoSuf|Size64|No_egpr, { Unspecified|BaseIndex } // XSAVEC instructions end. diff --git a/opcodes/i386-reg.tbl b/opcodes/i386-reg.tbl index 2ac56e3fd0b..8fead35e320 100644 --- a/opcodes/i386-reg.tbl +++ b/opcodes/i386-reg.tbl @@ -43,6 +43,22 @@ r12b, Class=Reg|Byte, RegRex|RegRex64, 4, Dw2Inval, Dw2Inval r13b, Class=Reg|Byte, RegRex|RegRex64, 5, Dw2Inval, Dw2Inval r14b, Class=Reg|Byte, RegRex|RegRex64, 6, Dw2Inval, Dw2Inval r15b, Class=Reg|Byte, RegRex|RegRex64, 7, Dw2Inval, Dw2Inval +r16b, Class=Reg|Byte, RegRex2|RegRex64, 0, Dw2Inval, Dw2Inval +r17b, Class=Reg|Byte, RegRex2|RegRex64, 1, Dw2Inval, Dw2Inval +r18b, Class=Reg|Byte, RegRex2|RegRex64, 2, Dw2Inval, Dw2Inval +r19b, Class=Reg|Byte, RegRex2|RegRex64, 3, Dw2Inval, Dw2Inval +r20b, Class=Reg|Byte, RegRex2|RegRex64, 4, Dw2Inval, Dw2Inval +r21b, Class=Reg|Byte, RegRex2|RegRex64, 5, Dw2Inval, Dw2Inval +r22b, Class=Reg|Byte, RegRex2|RegRex64, 6, Dw2Inval, Dw2Inval +r23b, Class=Reg|Byte, RegRex2|RegRex64, 7, Dw2Inval, Dw2Inval +r24b, Class=Reg|Byte, RegRex2|RegRex64|RegRex, 0, Dw2Inval, Dw2Inval +r25b, Class=Reg|Byte, RegRex2|RegRex64|RegRex, 1, Dw2Inval, Dw2Inval +r26b, Class=Reg|Byte, RegRex2|RegRex64|RegRex, 2, Dw2Inval, Dw2Inval +r27b, Class=Reg|Byte, RegRex2|RegRex64|RegRex, 3, Dw2Inval, Dw2Inval +r28b, Class=Reg|Byte, RegRex2|RegRex64|RegRex, 4, Dw2Inval, Dw2Inval +r29b, Class=Reg|Byte, RegRex2|RegRex64|RegRex, 5, Dw2Inval, Dw2Inval +r30b, Class=Reg|Byte, RegRex2|RegRex64|RegRex, 6, Dw2Inval, Dw2Inval +r31b, Class=Reg|Byte, RegRex2|RegRex64|RegRex, 7, Dw2Inval, Dw2Inval // 16 bit regs ax, Class=Reg|Instance=Accum|Word, 0, 0, Dw2Inval, Dw2Inval cx, Class=Reg|Word, 0, 1, Dw2Inval, Dw2Inval @@ -60,6 +76,22 @@ r12w, Class=Reg|Word, RegRex, 4, Dw2Inval, Dw2Inval r13w, Class=Reg|Word, RegRex, 5, Dw2Inval, Dw2Inval r14w, Class=Reg|Word, RegRex, 6, Dw2Inval, Dw2Inval r15w, Class=Reg|Word, RegRex, 7, Dw2Inval, Dw2Inval +r16w, Class=Reg|Word, RegRex2, 0, Dw2Inval, Dw2Inval +r17w, Class=Reg|Word, RegRex2, 1, Dw2Inval, Dw2Inval +r18w, Class=Reg|Word, RegRex2, 2, Dw2Inval, Dw2Inval +r19w, Class=Reg|Word, RegRex2, 3, Dw2Inval, Dw2Inval +r20w, Class=Reg|Word, RegRex2, 4, Dw2Inval, Dw2Inval +r21w, Class=Reg|Word, RegRex2, 5, Dw2Inval, Dw2Inval +r22w, Class=Reg|Word, RegRex2, 6, Dw2Inval, Dw2Inval +r23w, Class=Reg|Word, RegRex2, 7, Dw2Inval, Dw2Inval +r24w, Class=Reg|Word, RegRex2|RegRex, 0, Dw2Inval, Dw2Inval +r25w, Class=Reg|Word, RegRex2|RegRex, 1, Dw2Inval, Dw2Inval +r26w, Class=Reg|Word, RegRex2|RegRex, 2, Dw2Inval, Dw2Inval +r27w, Class=Reg|Word, RegRex2|RegRex, 3, Dw2Inval, Dw2Inval +r28w, Class=Reg|Word, RegRex2|RegRex, 4, Dw2Inval, Dw2Inval +r29w, Class=Reg|Word, RegRex2|RegRex, 5, Dw2Inval, Dw2Inval +r30w, Class=Reg|Word, RegRex2|RegRex, 6, Dw2Inval, Dw2Inval +r31w, Class=Reg|Word, RegRex2|RegRex, 7, Dw2Inval, Dw2Inval // 32 bit regs eax, Class=Reg|Instance=Accum|Dword|BaseIndex, 0, 0, 0, Dw2Inval ecx, Class=Reg|Instance=RegC|Dword|BaseIndex, 0, 1, 1, Dw2Inval @@ -77,6 +109,22 @@ r12d, Class=Reg|Dword|BaseIndex, RegRex, 4, Dw2Inval, Dw2Inval r13d, Class=Reg|Dword|BaseIndex, RegRex, 5, Dw2Inval, Dw2Inval r14d, Class=Reg|Dword|BaseIndex, RegRex, 6, Dw2Inval, Dw2Inval r15d, Class=Reg|Dword|BaseIndex, RegRex, 7, Dw2Inval, Dw2Inval +r16d, Class=Reg|Dword|BaseIndex, RegRex2, 0, Dw2Inval, Dw2Inval +r17d, Class=Reg|Dword|BaseIndex, RegRex2, 1, Dw2Inval, Dw2Inval +r18d, Class=Reg|Dword|BaseIndex, RegRex2, 2, Dw2Inval, Dw2Inval +r19d, Class=Reg|Dword|BaseIndex, RegRex2, 3, Dw2Inval, Dw2Inval +r20d, Class=Reg|Dword|BaseIndex, RegRex2, 4, Dw2Inval, Dw2Inval +r21d, Class=Reg|Dword|BaseIndex, RegRex2, 5, Dw2Inval, Dw2Inval +r22d, Class=Reg|Dword|BaseIndex, RegRex2, 6, Dw2Inval, Dw2Inval +r23d, Class=Reg|Dword|BaseIndex, RegRex2, 7, Dw2Inval, Dw2Inval +r24d, Class=Reg|Dword|BaseIndex, RegRex2|RegRex, 0, Dw2Inval, Dw2Inval +r25d, Class=Reg|Dword|BaseIndex, RegRex2|RegRex, 1, Dw2Inval, Dw2Inval +r26d, Class=Reg|Dword|BaseIndex, RegRex2|RegRex, 2, Dw2Inval, Dw2Inval +r27d, Class=Reg|Dword|BaseIndex, RegRex2|RegRex, 3, Dw2Inval, Dw2Inval +r28d, Class=Reg|Dword|BaseIndex, RegRex2|RegRex, 4, Dw2Inval, Dw2Inval +r29d, Class=Reg|Dword|BaseIndex, RegRex2|RegRex, 5, Dw2Inval, Dw2Inval +r30d, Class=Reg|Dword|BaseIndex, RegRex2|RegRex, 6, Dw2Inval, Dw2Inval +r31d, Class=Reg|Dword|BaseIndex, RegRex2|RegRex, 7, Dw2Inval, Dw2Inval rax, Class=Reg|Instance=Accum|Qword|BaseIndex, 0, 0, Dw2Inval, 0 rcx, Class=Reg|Instance=RegC|Qword|BaseIndex, 0, 1, Dw2Inval, 2 rdx, Class=Reg|Instance=RegD|Qword|BaseIndex, 0, 2, Dw2Inval, 1 @@ -93,6 +141,22 @@ r12, Class=Reg|Qword|BaseIndex, RegRex, 4, Dw2Inval, 12 r13, Class=Reg|Qword|BaseIndex, RegRex, 5, Dw2Inval, 13 r14, Class=Reg|Qword|BaseIndex, RegRex, 6, Dw2Inval, 14 r15, Class=Reg|Qword|BaseIndex, RegRex, 7, Dw2Inval, 15 +r16, Class=Reg|Qword|BaseIndex, RegRex2, 0, Dw2Inval, 130 +r17, Class=Reg|Qword|BaseIndex, RegRex2, 1, Dw2Inval, 131 +r18, Class=Reg|Qword|BaseIndex, RegRex2, 2, Dw2Inval, 132 +r19, Class=Reg|Qword|BaseIndex, RegRex2, 3, Dw2Inval, 133 +r20, Class=Reg|Qword|BaseIndex, RegRex2, 4, Dw2Inval, 134 +r21, Class=Reg|Qword|BaseIndex, RegRex2, 5, Dw2Inval, 135 +r22, Class=Reg|Qword|BaseIndex, RegRex2, 6, Dw2Inval, 136 +r23, Class=Reg|Qword|BaseIndex, RegRex2, 7, Dw2Inval, 137 +r24, Class=Reg|Qword|BaseIndex, RegRex2|RegRex, 0, Dw2Inval, 138 +r25, Class=Reg|Qword|BaseIndex, RegRex2|RegRex, 1, Dw2Inval, 139 +r26, Class=Reg|Qword|BaseIndex, RegRex2|RegRex, 2, Dw2Inval, 140 +r27, Class=Reg|Qword|BaseIndex, RegRex2|RegRex, 3, Dw2Inval, 141 +r28, Class=Reg|Qword|BaseIndex, RegRex2|RegRex, 4, Dw2Inval, 142 +r29, Class=Reg|Qword|BaseIndex, RegRex2|RegRex, 5, Dw2Inval, 143 +r30, Class=Reg|Qword|BaseIndex, RegRex2|RegRex, 6, Dw2Inval, 144 +r31, Class=Reg|Qword|BaseIndex, RegRex2|RegRex, 7, Dw2Inval, 145 // Vector mask registers. k0, Class=RegMask, 0, 0, 93, 118 k1, Class=RegMask, 0, 1, 94, 119