From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pf1-x42b.google.com (mail-pf1-x42b.google.com [IPv6:2607:f8b0:4864:20::42b]) by sourceware.org (Postfix) with ESMTPS id 57B5F3858C31 for ; Thu, 28 Dec 2023 01:53:46 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 57B5F3858C31 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 57B5F3858C31 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::42b ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1703728437; cv=none; b=x+1Cb5ySHgdGFfWgTSCkU0qZQK2WNCGH6tYyhneavDbCRew1zGyKGc1/v86ZVMs1TmeI2VFbS7txnrTUAUXjLbU7yEI3TQU6ISuXrEnJ85x0laRzZQNWytz9sPylx8pxgsRf0h52SRjkqMMHFvz+86dTDDSuMmtF6yRvspCB65c= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1703728437; c=relaxed/simple; bh=7wqB1wQ50T0hHG/BME4+cZVH1aEZr3h1zRCym8OKPb0=; h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version; b=jDMKVmiNmO68ViJW2VKkpJ5Xyn021rmtgPgUGMjlXSqBkrfdlxxy31T4TZOSDcYVosEagTPa13nvrrIZx/JGmhZa8OVKpc/ygcuzyGavTEbjqfvYU09CobPON8G8fVWVHQ6Zd0D3ywIj1xhNA1lCwZZAaXVOnrHspxjbnMffj5A= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pf1-x42b.google.com with SMTP id d2e1a72fcca58-6d9a7233133so1059284b3a.0 for ; Wed, 27 Dec 2023 17:53:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1703728425; x=1704333225; darn=sourceware.org; h=in-reply-to:content-transfer-encoding:content-disposition :mime-version:references:message-id:subject:cc:to:from:date:from:to :cc:subject:date:message-id:reply-to; bh=Q8Ui5p29FfiPrOxt+jXHka2ohjQGvi2hyoYZz/U3CvI=; b=M0UjECC59056uQXPuw6fcTjJ3xofM6tU3vsI9MTnaqp4KqkiSVLx6BByflnZMU3WWY qkfAqa79rVRGMzMr3U5oM7n8tzLIt72G3zFPmOKbgMADFKgmglf7Gt/0Ijo3UOgmt8Xi RfY1ojIz5KLO0qOD3yMnadDXlGkXd+Fm5pu6pGb3jnnTOhRz8chmXLnKHY/bfXKXULDT Rs38bIcJ6awtDKj/Dkw346766VhGfNq0uhQNbxLiZAy6det46zXX5lL+u0tjhmnvlz/0 dIF5ty+X0/mCG5ODiE0XZu8cAo/EiqCjCHxXM/OiuRRWRrg2rpz37yDO2ZeJezOhsdB/ KwUA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1703728425; x=1704333225; h=in-reply-to:content-transfer-encoding:content-disposition :mime-version:references:message-id:subject:cc:to:from:date :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=Q8Ui5p29FfiPrOxt+jXHka2ohjQGvi2hyoYZz/U3CvI=; b=mKgnBhL6CRmKBYqEP2D5Jm2bzUKRv8xvTG53giwgXtZc9kMWAMIW15jd91R5ZYARPo hUmLrf94d/IxlFetP4o4mWDavE+FbVCqYQaZQN8SOgDaKbun9p/So1lOymOXXL4kFwwm hQluxkVfdh6cwctdU96AKgMoSZQlooeILt9r/IcQ17zZLQVEyPWWUTSE8dz64/r12Wav lDkNaysRfVYpNk3pte7b6Oc6ioGz4ILwu1hHiozBMheLxLdKRD2Jn/q9rngPfToJIFtQ ROR+t7Jxjfwr8BEESFL44PiUM68XaLuHP0iJR4oF/moT1fvRf4CwFg/JKG3oxaiZpQ7t YUgg== X-Gm-Message-State: AOJu0YynjexqglB9Nw3Zv4L+3n5f9G3iyf+VzFOoN5N2NtRh69n8uMMn 7rXpRq+AT5IemhKCXfXcrDrhrd2WS0M= X-Google-Smtp-Source: AGHT+IHbpX5sAWi8kJuxqQpQpmEKXCM1SzQC4jUHYvnDFMmU28O8ipCHCesKoIdSvr2sm/kVNncNDA== X-Received: by 2002:aa7:858f:0:b0:6d9:ac82:9291 with SMTP id w15-20020aa7858f000000b006d9ac829291mr2639360pfn.23.1703728424460; Wed, 27 Dec 2023 17:53:44 -0800 (PST) Received: from gnu-cfl-3.localdomain ([172.56.169.119]) by smtp.gmail.com with ESMTPSA id n37-20020a056a000d6500b006d996ce80a6sm9058097pfv.0.2023.12.27.17.53.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 27 Dec 2023 17:53:43 -0800 (PST) Received: by gnu-cfl-3.localdomain (Postfix, from userid 1000) id 61DBB7403E1; Wed, 27 Dec 2023 17:53:42 -0800 (PST) Date: Wed, 27 Dec 2023 17:53:42 -0800 From: "H.J. Lu" To: "Cui, Lili" Cc: binutils@sourceware.org, jbeulich@suse.com Subject: Re: [PATCH V5 1/9] Support APX GPR32 with rex2 prefix Message-ID: References: <20231228012714.2989658-1-lili.cui@intel.com> <20231228012714.2989658-2-lili.cui@intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <20231228012714.2989658-2-lili.cui@intel.com> X-Spam-Status: No, score=-3024.6 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,GIT_PATCH_0,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,TXREP,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: On Thu, Dec 28, 2023 at 01:27:06AM +0000, Cui, Lili wrote: > APX uses the REX2 prefix to support EGPR for map0 and map1 of legacy > instructions. We added the NoEgpr flag in i386-gen.c for instructions > that do not support EGPR. > > gas/ChangeLog: > > 2023-12-28 Lingling Kong > H.J. Lu > Lili Cui > Lin Hu > > * config/tc-i386.c > (enum i386_error): Add unsupported_EGPR_for_addressing > and invalid_pseudo_prefix. > (struct _i386_insn): Add rex2 and rex2_encoding for > gpr32. > (cpu_arch): Add apx_f. > (is_cpu): Ditto. > (register_number): Handle RegRex2 for gpr32. > (is_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. > (establish_rex): Handle rex2 and rex2_encoding. > (optimize_encoding): Handel add r16-r31 for registers. > (md_assemble): Handle apx encoding. > (parse_insn): Handle Prefix_REX2. > (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. > (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. > * doc/c-i386.texi: Document .apx. > * testsuite/gas/i386/ilp32/x86-64-opcode-inval-intel.d: D5 valid > in 64-bit mode. > * testsuite/gas/i386/ilp32/x86-64-opcode-inval.d: Ditto. > * testsuite/gas/i386/rex-bad: Adjust rex testcase. > * testsuite/gas/i386/x86-64-opcode-inval-intel.d: Ditto. > * testsuite/gas/i386/x86-64-opcode-inval.d: Ditto. > * testsuite/gas/i386/x86-64-opcode-inval.s: Ditto. > * testsuite/gas/i386/x86-64-pseudos-bad.l: Add illegal rex2 test. > * testsuite/gas/i386/x86-64-pseudos-bad.s: Ditto. > * testsuite/gas/i386/x86-64-pseudos.d: Add rex2 test. > * testsuite/gas/i386/x86-64-pseudos.s: Ditto. > * testsuite/gas/i386/x86-64.exp: Run APX tests. > * testsuite/gas/i386/x86-64-apx-egpr-inval.l: New test. > * testsuite/gas/i386/x86-64-apx-egpr-inval.s: New test. > * testsuite/gas/i386/x86-64-apx-rex2.d: New test. > * testsuite/gas/i386/x86-64-apx-rex2.s: New test. > > include/ChangeLog: > > * opcode/i386.h (REX2_OPCODE): New. > (REX2_M): Ditto. > > opcodes/ChangeLog: > > * i386-dis.c (struct instr_info): Add erex for gpr32. > Add last_erex_prefix for rex2 prefix. > (REX2_M): Extend for gpr32. > (PREFIX_REX2): Ditto. > (PREFIX_REX2_ILLEGAL): Ditto. > (ckprefix): Ditto. > (prefix_name): Ditto. > (print_insn): Ditto. > (print_register): Ditto. > (OP_E_memory): Ditto. > (OP_REG): Ditto. > (OP_EX): Ditto. > * i386-gen.c (rex2_disallowed): Some instructions are not allowed rex2 prefix. > (process_i386_opcode_modifier): Set NoEgpr for VEX and some special instructions. > (output_i386_opcode): Handle if_entry_needs_special_handle. > * i386-init.h : Regenerated. > * i386-mnem.h : Regenerated. > * i386-opc.h (enum i386_cpu): Add CpuAPX_F. > (NoEgpr): New. > (Prefix_NoOptimize): Ditto. > (Prefix_REX2): Ditto. > (RegRex2): Ditto. > * i386-opc.tbl: Add rex2 prefix. > * i386-reg.tbl: Add egprs (r16-r31). > * i386-tbl.h: Regenerated. > --- > gas/config/tc-i386.c | 178 ++++++++++-- > gas/doc/c-i386.texi | 7 +- > .../i386/ilp32/x86-64-opcode-inval-intel.d | 47 +--- > .../gas/i386/ilp32/x86-64-opcode-inval.d | 47 +--- > gas/testsuite/gas/i386/rex-bad.l | 8 +- > .../gas/i386/x86-64-apx-egpr-inval.l | 15 + > .../gas/i386/x86-64-apx-egpr-inval.s | 18 ++ > gas/testsuite/gas/i386/x86-64-apx-rex2.d | 83 ++++++ > gas/testsuite/gas/i386/x86-64-apx-rex2.s | 85 ++++++ > .../gas/i386/x86-64-opcode-inval-intel.d | 26 +- > gas/testsuite/gas/i386/x86-64-opcode-inval.d | 26 +- > gas/testsuite/gas/i386/x86-64-opcode-inval.s | 4 - > gas/testsuite/gas/i386/x86-64-pseudos-bad.l | 75 ++++- > gas/testsuite/gas/i386/x86-64-pseudos-bad.s | 74 +++++ > gas/testsuite/gas/i386/x86-64-pseudos.d | 21 ++ > gas/testsuite/gas/i386/x86-64-pseudos.s | 21 ++ > gas/testsuite/gas/i386/x86-64.exp | 2 + > include/opcode/i386.h | 4 + > opcodes/i386-dis.c | 257 ++++++++++++------ > opcodes/i386-gen.c | 50 +++- > opcodes/i386-opc.h | 13 +- > opcodes/i386-opc.tbl | 27 +- > opcodes/i386-reg.tbl | 64 +++++ > 23 files changed, 886 insertions(+), 266 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.d > create mode 100644 gas/testsuite/gas/i386/x86-64-apx-rex2.s > > diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c > index cdd3b55c655..bb302f28add 100644 > --- a/gas/config/tc-i386.c > +++ b/gas/config/tc-i386.c > @@ -239,6 +239,7 @@ enum i386_error > bad_imm4, > unsupported_with_intel_mnemonic, > unsupported_syntax, > + unsupported_EGPR_for_addressing, > unsupported, > unsupported_on_arch, > unsupported_64bit, > @@ -249,6 +250,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, > @@ -356,6 +358,7 @@ struct _i386_insn > modrm_byte rm; > rex_byte rex; > rex_byte vrex; > + rex_byte rex2; > sib_byte sib; > vex_prefix vex; > > @@ -429,6 +432,9 @@ struct _i386_insn > /* Prefer the REX byte in encoding. */ > bool rex_encoding; > > + /* Prefer the REX2 prefix in encoding. */ > + bool rex2_encoding; > + > /* Disable instruction size optimization. */ > bool no_optimize; > > @@ -1149,6 +1155,7 @@ static const arch_entry cpu_arch[] = > SUBARCH (pbndkb, PBNDKB, PBNDKB, false), > VECARCH (avx10.1, AVX10_1, ANY_AVX512F, set), > SUBARCH (user_msr, USER_MSR, USER_MSR, false), > + SUBARCH (apx_f, APX_F, APX_F, false), > }; > > #undef SUBARCH > @@ -1664,6 +1671,7 @@ _is_cpu (const i386_cpu_attr *a, enum i386_cpu cpu) > case CpuHLE: return a->bitfield.cpuhle; > case CpuAVX512F: return a->bitfield.cpuavx512f; > case CpuAVX512VL: return a->bitfield.cpuavx512vl; > + case CpuAPX_F: return a->bitfield.cpuapx_f; > case Cpu64: return a->bitfield.cpu64; > case CpuNo64: return a->bitfield.cpuno64; > default: > @@ -2335,7 +2343,7 @@ register_number (const reg_entry *r) > if (r->reg_flags & RegRex) > nr += 8; > > - if (r->reg_flags & RegVRex) > + if (r->reg_flags & (RegVRex | RegRex2)) > nr += 16; > > return nr; > @@ -3871,6 +3879,12 @@ is_any_vex_encoding (const insn_template *t) > return t->opcode_modifier.vex || t->opcode_modifier.evex; > } > > +static INLINE bool > +is_apx_rex2_encoding (void) > +{ > + return i.rex2 || i.rex2_encoding; > +} > + > static unsigned int > get_broadcast_bytes (const insn_template *t, bool diag) > { > @@ -4126,6 +4140,22 @@ 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 | > + > + Rex2 reuses i.vex as they both encode i.tm.opcode_space in their prefixes. > + */ > +static void > +build_rex2_prefix (void) > +{ > + i.vex.length = 2; > + i.vex.bytes[0] = 0xd5; > + /* For the W R X B bits, the variables of rex prefix will be reused. */ > + i.vex.bytes[1] = ((i.tm.opcode_space << 7) > + | (i.rex2 << 4) | i.rex); > +} > + > static void establish_rex (void) > { > /* Note that legacy encodings have at most 2 non-immediate operands. */ > @@ -4140,13 +4170,16 @@ static void establish_rex (void) > registers to new ones. */ > > if ((i.types[first].bitfield.class == Reg && i.types[first].bitfield.byte > - && ((i.op[first].regs->reg_flags & RegRex64) != 0 || i.rex != 0)) > + && ((i.op[first].regs->reg_flags & RegRex64) != 0 || i.rex != 0 > + || i.rex2 != 0)) > || (i.types[last].bitfield.class == Reg && i.types[last].bitfield.byte > - && ((i.op[last].regs->reg_flags & RegRex64) != 0 || i.rex != 0))) > + && ((i.op[last].regs->reg_flags & RegRex64) != 0 || i.rex != 0 > + || i.rex2 != 0))) > { > unsigned int x; > > - i.rex |= REX_OPCODE; > + if (!is_apx_rex2_encoding () && !is_any_vex_encoding(&i.tm)) > + i.rex |= REX_OPCODE; > for (x = first; x <= last; x++) > { > /* Look for 8 bit operand that uses old registers. */ > @@ -4157,7 +4190,7 @@ static void establish_rex (void) > /* 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"), > + "instruction requiring REX/REX2 prefix"), > register_prefix, i.op[x].regs->reg_name); > > /* Otherwise it is equivalent to the extended register. > @@ -4168,11 +4201,11 @@ static void establish_rex (void) > } > } > > - if (i.rex == 0 && i.rex_encoding) > + if (i.rex == 0 && i.rex2 == 0 && (i.rex_encoding || 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 > - the REX_OPCODE byte. */ > + rex and rex2 prefix. */ > unsigned int x; > > for (x = first; x <= last; x++) > @@ -4183,6 +4216,7 @@ static void establish_rex (void) > { > gas_assert (!(i.op[x].regs->reg_flags & RegRex)); > i.rex_encoding = false; > + i.rex2_encoding = false; > break; > } > > @@ -4190,8 +4224,14 @@ static void establish_rex (void) > i.rex = REX_OPCODE; > } > > - if (i.rex != 0) > - add_prefix (REX_OPCODE | i.rex); > + if (is_apx_rex2_encoding ()) > + { > + build_rex2_prefix (); > + /* The individual REX.RXBW bits got consumed. */ > + i.rex &= REX_OPCODE; > + } > + else if (i.rex != 0) > + add_prefix (REX_OPCODE | i.rex); > } > > static void > @@ -4457,14 +4497,22 @@ optimize_encoding (void) > i.types[1].bitfield.byte = 1; > /* Ignore the suffix. */ > i.suffix = 0; > - /* Convert to byte registers. */ > + /* Convert to byte registers. 8-bit registers are special, > + RegRex64 and non-RegRex64 each have 8 registers. */ > if (i.types[1].bitfield.word) > - j = 16; > - else if (i.types[1].bitfield.dword) > + /* 32 (or 40) 8-bit registers. */ > j = 32; > + else if (i.types[1].bitfield.dword) > + /* 32 (or 40) 8-bit registers + 32 16-bit registers. */ > + j = 64; > else > - j = 48; > - if (!(i.op[1].regs->reg_flags & RegRex) && base_regnum < 4) > + /* 32 (or 40) 8-bit registers + 32 16-bit registers > + + 32 32-bit registers. */ > + j = 96; > + > + /* In 64-bit mode, the following byte registers cannot be accessed > + if using the Rex and Rex2 prefix: AH, BH, CH, DH */ > + if (!(i.op[1].regs->reg_flags & (RegRex | RegRex2)) && base_regnum < 4) > j += 8; > i.op[1].regs -= j; > } > @@ -5354,6 +5402,9 @@ md_assemble (char *line) > case unsupported_syntax: > err_msg = _("unsupported syntax"); > break; > + case unsupported_EGPR_for_addressing: > + err_msg = _("extended GPR cannot be used as base/index"); > + break; > case unsupported: > as_bad (_("unsupported instruction `%s'"), > pass1_mnem ? pass1_mnem : insn_name (current_templates.start)); > @@ -5407,6 +5458,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 = _("rex2 pseudo prefix cannot be used"); > + break; > case unsupported_vector_index_register: > err_msg = _("unsupported vector index register"); > break; > @@ -5662,6 +5716,13 @@ md_assemble (char *line) > return; > } > > + /* Check for explicit REX2 prefix. */ > + if (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 > @@ -5868,6 +5929,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; > @@ -7015,6 +7080,43 @@ VEX_check_encoding (const insn_template *t) > return 0; > } > > +/* Check if Egprs operands are valid for the instruction. */ > + > +static bool > +check_EgprOperands (const insn_template *t) > +{ > + if (!t->opcode_modifier.noegpr) > + return 0; > + > + 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 = unsupported_EGPR_for_addressing; > + return 1; > + } > + > + /* Check if pseudo prefix {rex2} is 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, > @@ -7159,6 +7261,13 @@ match_template (char mnem_suffix) > continue; > } > > + /* Check if pseudo prefix {rex2} is valid. */ > + if (t->opcode_modifier.noegpr && i.rex2_encoding) > + { > + specific_error = progress (invalid_pseudo_prefix); > + continue; > + } > + > /* We've found a match; break out of loop. */ > break; > } > @@ -7489,6 +7598,13 @@ match_template (char mnem_suffix) > continue; > } > > + /* Check if EGPR operands(r16-r31) are valid. */ > + if (check_EgprOperands (t)) > + { > + specific_error = progress (i.error); > + continue; > + } > + > /* Check whether to use the shorter VEX encoding for certain insns where > the EVEX encoding comes first in the table. This requires the respective > AVX-* feature to be explicitly enabled. > @@ -8387,6 +8503,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 > @@ -8870,8 +8998,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. */ > @@ -8942,8 +9069,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. */ > @@ -8981,8 +9107,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 > @@ -10126,6 +10251,12 @@ output_insn (const struct last_insn *last_insn) > for (j = ARRAY_SIZE (i.prefix), q = i.prefix; j > 0; j--, q++) > if (*q) > frag_opcode_byte (*q); > + > + if (is_apx_rex2_encoding ()) > + { > + frag_opcode_byte (i.vex.bytes[0]); > + frag_opcode_byte (i.vex.bytes[1]); > + } > } > else > { > @@ -14164,6 +14295,13 @@ 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) > + 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 03ee980bef7..21f48c93300 100644 > --- a/gas/doc/c-i386.texi > +++ b/gas/doc/c-i386.texi > @@ -217,6 +217,7 @@ accept various extension mnemonics. For example, > @code{avx10.1/256}, > @code{avx10.1/128}, > @code{user_msr}, > +@code{apx_f}, > @code{amx_int8}, > @code{amx_bf16}, > @code{amx_fp16}, > @@ -983,6 +984,10 @@ Different encoding options can be specified via pseudo prefixes: > instructions (x86-64 only). Note that this differs from the @samp{rex} > prefix which generates REX prefix unconditionally. > > +@item > +@samp{@{rex2@}} -- prefer REX2 prefix for integer and legacy vector > +instructions (APX_F only). > + > @item > @samp{@{nooptimize@}} -- disable instruction size optimization. > @end itemize > @@ -1663,7 +1668,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_f} > @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..56834371133 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 > @@ -2,49 +2,4 @@ > #as: --32 > #objdump: -dw -Mx86-64 -Mintel > #name: x86-64 (ILP32) illegal opcodes (Intel mode) > - > -.*: +file format .* > - > -Disassembly of section .text: > - > -0+ : > -[ ]*[a-f0-9]+: 37 \(bad\) > - > -0+1 : > -[ ]*[a-f0-9]+: d5 \(bad\) > -[ ]*[a-f0-9]+: 0a .byte 0xa > - > -0+3 : > -[ ]*[a-f0-9]+: d5 \(bad\) > -[ ]*[a-f0-9]+: 02 .byte 0x2 > - > -0+5 : > -[ ]*[a-f0-9]+: d4 \(bad\) > -[ ]*[a-f0-9]+: 0a .byte 0xa > - > -0+7 : > -[ ]*[a-f0-9]+: d4 \(bad\) > -[ ]*[a-f0-9]+: 02 .byte 0x2 > - > -0+9 : > -[ ]*[a-f0-9]+: 3f \(bad\) > - > -0+a : > -[ ]*[a-f0-9]+: 62 .byte 0x62 > -[ ]*[a-f0-9]+: 10 .byte 0x10 > - > -0+c : > -[ ]*[a-f0-9]+: 27 \(bad\) > - > -0+d : > -[ ]*[a-f0-9]+: 2f \(bad\) > - > -0+e : > -[ ]*[a-f0-9]+: ce \(bad\) > - > -0+f : > -[ ]*[a-f0-9]+: 60 \(bad\) > - > -0+10 : > -[ ]*[a-f0-9]+: 61 \(bad\) > -#pass > +#dump: ../x86-64-opcode-inval-intel.d > 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..b5233a5cf93 100644 > --- a/gas/testsuite/gas/i386/ilp32/x86-64-opcode-inval.d > +++ b/gas/testsuite/gas/i386/ilp32/x86-64-opcode-inval.d > @@ -2,49 +2,4 @@ > #as: --32 > #objdump: -dw -Mx86-64 > #name: x86-64 (ILP32) illegal opcodes > - > -.*: +file format .* > - > -Disassembly of section .text: > - > -0+ : > -[ ]*[a-f0-9]+: 37 \(bad\) > - > -0+1 : > -[ ]*[a-f0-9]+: d5 \(bad\) > -[ ]*[a-f0-9]+: 0a .byte 0xa > - > -0+3 : > -[ ]*[a-f0-9]+: d5 \(bad\) > -[ ]*[a-f0-9]+: 02 .byte 0x2 > - > -0+5 : > -[ ]*[a-f0-9]+: d4 \(bad\) > -[ ]*[a-f0-9]+: 0a .byte 0xa > - > -0+7 : > -[ ]*[a-f0-9]+: d4 \(bad\) > -[ ]*[a-f0-9]+: 02 .byte 0x2 > - > -0+9 : > -[ ]*[a-f0-9]+: 3f \(bad\) > - > -0+a : > -[ ]*[a-f0-9]+: 62 .byte 0x62 > -[ ]*[a-f0-9]+: 10 .byte 0x10 > - > -0+c : > -[ ]*[a-f0-9]+: 27 \(bad\) > - > -0+d : > -[ ]*[a-f0-9]+: 2f \(bad\) > - > -0+e : > -[ ]*[a-f0-9]+: ce \(bad\) > - > -0+f : > -[ ]*[a-f0-9]+: 60 \(bad\) > - > -0+10 : > -[ ]*[a-f0-9]+: 61 \(bad\) > -#pass > +#dump: ../x86-64-opcode-inval.d > diff --git a/gas/testsuite/gas/i386/rex-bad.l b/gas/testsuite/gas/i386/rex-bad.l > index 407558ec541..abd4d3045d0 100644 > --- a/gas/testsuite/gas/i386/rex-bad.l > +++ b/gas/testsuite/gas/i386/rex-bad.l > @@ -3,8 +3,8 @@ > .*:5: Error: same .* > .*:6: Error: same .* > .*:7: Error: same .* > -.*:9: Error: .* REX .* > -.*:10: Error: .* REX .* > -.*:12: Error: .* REX .* > -.*:13: Error: .* REX .* > +.*:9: Error: .* REX/REX2 .* > +.*:10: Error: .* REX/REX2 .* > +.*:12: Error: .* REX/REX2 .* > +.*:13: Error: .* REX/REX2 .* > #pass > 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..bb5c602a2e2 > --- /dev/null > +++ b/gas/testsuite/gas/i386/x86-64-apx-egpr-inval.l > @@ -0,0 +1,15 @@ > +.*: Assembler messages: > +.*:4: Error: bad register name `%r17d' > +.*:7: Error: extended GPR cannot be used as base/index for `xsave' > +.*:8: Error: extended GPR cannot be used as base/index for `xsave64' > +.*:9: Error: extended GPR cannot be used as base/index for `xrstor' > +.*:10: Error: extended GPR cannot be used as base/index for `xrstor64' > +.*:11: Error: extended GPR cannot be used as base/index for `xsaves' > +.*:12: Error: extended GPR cannot be used as base/index for `xsaves64' > +.*:13: Error: extended GPR cannot be used as base/index for `xrstors' > +.*:14: Error: extended GPR cannot be used as base/index for `xrstors64' > +.*:15: Error: extended GPR cannot be used as base/index for `xsaveopt' > +.*:16: Error: extended GPR cannot be used as base/index for `xsaveopt64' > +.*:17: Error: extended GPR cannot be used as base/index for `xsavec' > +.*:18: Error: extended GPR cannot be used as base/index for `xsavec64' > +#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..bfb6b3fd03b > --- /dev/null > +++ b/gas/testsuite/gas/i386/x86-64-apx-egpr-inval.s > @@ -0,0 +1,18 @@ > +# Check illegal 64bit APX_F instructions > + .text > + .arch .noapx_f > + test $0x7, %r17d > + .arch .apx_f > + test $0x7, %r17d > + xsave (%r16, %rbx) > + xsave64 (%r16, %r31) > + xrstor (%r16, %rbx) > + xrstor64 (%r16, %rbx) > + xsaves (%rbx, %r16) > + xsaves64 (%r16, %rbx) > + xrstors (%rbx, %r31) > + xrstors64 (%r16, %rbx) > + xsaveopt (%r16, %rbx) > + xsaveopt64 (%r16, %r31) > + xsavec (%r16, %rbx) > + xsavec64 (%r16, %r31) > 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..e3cd534da11 > --- /dev/null > +++ b/gas/testsuite/gas/i386/x86-64-apx-rex2.d > @@ -0,0 +1,83 @@ > +#as: > +#objdump: -dw > +#name: x86-64 APX_F use gpr32 with rex2 prefix > +#source: x86-64-apx-rex2.s > + > +.*: +file format .* > + > + > +Disassembly of section .text: > + > +0+ <_start>: > +[ ]*[a-f0-9]+:[ ]*d5 11 f6 c0 07[ ]+test \$0x7,%r24b > +[ ]*[a-f0-9]+:[ ]*d5 11 f7 c0 07 00 00 00[ ]+test \$0x7,%r24d > +[ ]*[a-f0-9]+:[ ]*d5 19 f7 c0 07 00 00 00[ ]+test \$0x7,%r24 > +[ ]*[a-f0-9]+:[ ]*66 d5 11 f7 c0 07 00[ ]+test \$0x7,%r24w > +[ ]*[a-f0-9]+:[ ]*44 0f af f8[ ]+imul %eax,%r15d > +[ ]*[a-f0-9]+:[ ]*d5 c0 af c0[ ]+imul %eax,%r16d > +[ ]*[a-f0-9]+:[ ]*d5 90 62 12[ ]+punpckldq %mm2,\(%r18\) > +[ ]*[a-f0-9]+:[ ]*d5 40 8d 00[ ]+lea \(%rax\),%r16d > +[ ]*[a-f0-9]+:[ ]*d5 40 8d 08[ ]+lea \(%rax\),%r17d > +[ ]*[a-f0-9]+:[ ]*d5 40 8d 10[ ]+lea \(%rax\),%r18d > +[ ]*[a-f0-9]+:[ ]*d5 40 8d 18[ ]+lea \(%rax\),%r19d > +[ ]*[a-f0-9]+:[ ]*d5 40 8d 20[ ]+lea \(%rax\),%r20d > +[ ]*[a-f0-9]+:[ ]*d5 40 8d 28[ ]+lea \(%rax\),%r21d > +[ ]*[a-f0-9]+:[ ]*d5 40 8d 30[ ]+lea \(%rax\),%r22d > +[ ]*[a-f0-9]+:[ ]*d5 40 8d 38[ ]+lea \(%rax\),%r23d > +[ ]*[a-f0-9]+:[ ]*d5 44 8d 00[ ]+lea \(%rax\),%r24d > +[ ]*[a-f0-9]+:[ ]*d5 44 8d 08[ ]+lea \(%rax\),%r25d > +[ ]*[a-f0-9]+:[ ]*d5 44 8d 10[ ]+lea \(%rax\),%r26d > +[ ]*[a-f0-9]+:[ ]*d5 44 8d 18[ ]+lea \(%rax\),%r27d > +[ ]*[a-f0-9]+:[ ]*d5 44 8d 20[ ]+lea \(%rax\),%r28d > +[ ]*[a-f0-9]+:[ ]*d5 44 8d 28[ ]+lea \(%rax\),%r29d > +[ ]*[a-f0-9]+:[ ]*d5 44 8d 30[ ]+lea \(%rax\),%r30d > +[ ]*[a-f0-9]+:[ ]*d5 44 8d 38[ ]+lea \(%rax\),%r31d > +[ ]*[a-f0-9]+:[ ]*d5 20 8d 04 05 00 00 00 00[ ]+lea 0x0\(,%r16,1\),%eax > +[ ]*[a-f0-9]+:[ ]*d5 20 8d 04 0d 00 00 00 00[ ]+lea 0x0\(,%r17,1\),%eax > +[ ]*[a-f0-9]+:[ ]*d5 20 8d 04 15 00 00 00 00[ ]+lea 0x0\(,%r18,1\),%eax > +[ ]*[a-f0-9]+:[ ]*d5 20 8d 04 1d 00 00 00 00[ ]+lea 0x0\(,%r19,1\),%eax > +[ ]*[a-f0-9]+:[ ]*d5 20 8d 04 25 00 00 00 00[ ]+lea 0x0\(,%r20,1\),%eax > +[ ]*[a-f0-9]+:[ ]*d5 20 8d 04 2d 00 00 00 00[ ]+lea 0x0\(,%r21,1\),%eax > +[ ]*[a-f0-9]+:[ ]*d5 20 8d 04 35 00 00 00 00[ ]+lea 0x0\(,%r22,1\),%eax > +[ ]*[a-f0-9]+:[ ]*d5 20 8d 04 3d 00 00 00 00[ ]+lea 0x0\(,%r23,1\),%eax > +[ ]*[a-f0-9]+:[ ]*d5 22 8d 04 05 00 00 00 00[ ]+lea 0x0\(,%r24,1\),%eax > +[ ]*[a-f0-9]+:[ ]*d5 22 8d 04 0d 00 00 00 00[ ]+lea 0x0\(,%r25,1\),%eax > +[ ]*[a-f0-9]+:[ ]*d5 22 8d 04 15 00 00 00 00[ ]+lea 0x0\(,%r26,1\),%eax > +[ ]*[a-f0-9]+:[ ]*d5 22 8d 04 1d 00 00 00 00[ ]+lea 0x0\(,%r27,1\),%eax > +[ ]*[a-f0-9]+:[ ]*d5 22 8d 04 25 00 00 00 00[ ]+lea 0x0\(,%r28,1\),%eax > +[ ]*[a-f0-9]+:[ ]*d5 22 8d 04 2d 00 00 00 00[ ]+lea 0x0\(,%r29,1\),%eax > +[ ]*[a-f0-9]+:[ ]*d5 22 8d 04 35 00 00 00 00[ ]+lea 0x0\(,%r30,1\),%eax > +[ ]*[a-f0-9]+:[ ]*d5 22 8d 04 3d 00 00 00 00[ ]+lea 0x0\(,%r31,1\),%eax > +[ ]*[a-f0-9]+:[ ]*d5 10 8d 00[ ]+lea \(%r16\),%eax > +[ ]*[a-f0-9]+:[ ]*d5 10 8d 01[ ]+lea \(%r17\),%eax > +[ ]*[a-f0-9]+:[ ]*d5 10 8d 02[ ]+lea \(%r18\),%eax > +[ ]*[a-f0-9]+:[ ]*d5 10 8d 03[ ]+lea \(%r19\),%eax > +[ ]*[a-f0-9]+:[ ]*d5 10 8d 04 24 lea \(%r20\),%eax > +[ ]*[a-f0-9]+:[ ]*d5 10 8d 45 00 lea 0x0\(%r21\),%eax > +[ ]*[a-f0-9]+:[ ]*d5 10 8d 06[ ]+lea \(%r22\),%eax > +[ ]*[a-f0-9]+:[ ]*d5 10 8d 07[ ]+lea \(%r23\),%eax > +[ ]*[a-f0-9]+:[ ]*d5 11 8d 00[ ]+lea \(%r24\),%eax > +[ ]*[a-f0-9]+:[ ]*d5 11 8d 01[ ]+lea \(%r25\),%eax > +[ ]*[a-f0-9]+:[ ]*d5 11 8d 02[ ]+lea \(%r26\),%eax > +[ ]*[a-f0-9]+:[ ]*d5 11 8d 03[ ]+lea \(%r27\),%eax > +[ ]*[a-f0-9]+:[ ]*d5 11 8d 04 24 lea \(%r28\),%eax > +[ ]*[a-f0-9]+:[ ]*d5 11 8d 45 00 lea 0x0\(%r29\),%eax > +[ ]*[a-f0-9]+:[ ]*d5 11 8d 06 lea \(%r30\),%eax > +[ ]*[a-f0-9]+:[ ]*d5 11 8d 07 lea \(%r31\),%eax > +[ ]*[a-f0-9]+:[ ]*4c 8d 38 lea \(%rax\),%r15 > +[ ]*[a-f0-9]+:[ ]*d5 48 8d 00 lea \(%rax\),%r16 > +[ ]*[a-f0-9]+:[ ]*49 8d 07 lea \(%r15\),%rax > +[ ]*[a-f0-9]+:[ ]*d5 18 8d 00 lea \(%r16\),%rax > +[ ]*[a-f0-9]+:[ ]*4a 8d 04 3d 00 00 00 00 lea 0x0\(,%r15,1\),%rax > +[ ]*[a-f0-9]+:[ ]*d5 28 8d 04 05 00 00 00 00 lea 0x0\(,%r16,1\),%rax > +[ ]*[a-f0-9]+:[ ]*d5 1c 03 00 add \(%r16\),%r8 > +[ ]*[a-f0-9]+:[ ]*d5 1c 03 38 add \(%r16\),%r15 > +[ ]*[a-f0-9]+:[ ]*d5 4a 8b 04 0d 00 00 00 00 mov 0x0\(,%r9,1\),%r16 > +[ ]*[a-f0-9]+:[ ]*d5 4a 8b 04 35 00 00 00 00 mov 0x0\(,%r14,1\),%r16 > +[ ]*[a-f0-9]+:[ ]*d5 4d 2b 3a sub \(%r10\),%r31 > +[ ]*[a-f0-9]+:[ ]*d5 4d 2b 7d 00 sub 0x0\(%r13\),%r31 > +[ ]*[a-f0-9]+:[ ]*d5 30 8d 44 20 01 lea 0x1\(%r16,%r20,1\),%eax > +[ ]*[a-f0-9]+:[ ]*d5 76 8d 7c 20 01 lea 0x1\(%r16,%r28,1\),%r31d > +[ ]*[a-f0-9]+:[ ]*d5 12 8d 84 04 81 00 00 00 lea 0x81\(%r20,%r8,1\),%eax > +[ ]*[a-f0-9]+:[ ]*d5 57 8d bc 04 81 00 00 00 lea 0x81\(%r28,%r8,1\),%r31d > +#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..eaaaaa77dd7 > --- /dev/null > +++ b/gas/testsuite/gas/i386/x86-64-apx-rex2.s > @@ -0,0 +1,85 @@ > +# Check 64bit instructions with rex2 prefix encoding > + > + .allow_index_reg > + .text > +_start: > + test $0x7, %r24b > + test $0x7, %r24d > + test $0x7, %r24 > + test $0x7, %r24w > +## REX2.M bit > + imull %eax, %r15d > + imull %eax, %r16d > + punpckldq (%r18), %mm2 > +## REX2.R4 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 > +## REX2.X4 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 > +## REX2.B4 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 > +## REX2.W bit > + leaq (%rax), %r15 > + leaq (%rax), %r16 > + leaq (%r15), %rax > + leaq (%r16), %rax > + leaq (,%r15), %rax > + leaq (,%r16), %rax > +## REX2.R3 bit > + add (%r16), %r8 > + add (%r16), %r15 > +## REX2.X3 bit > + mov (,%r9), %r16 > + mov (,%r14), %r16 > +## REX2.B3 bit > + sub (%r10), %r31 > + sub (%r13), %r31 > +## SIB > + leal 1(%r16, %r20), %eax > + leal 1(%r16, %r28), %r31d > + leal 129(%r20, %r8), %eax > + leal 129(%r28, %r8), %r31d > 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..66c4d2cddc0 100644 > --- a/gas/testsuite/gas/i386/x86-64-opcode-inval-intel.d > +++ b/gas/testsuite/gas/i386/x86-64-opcode-inval-intel.d > @@ -10,41 +10,33 @@ Disassembly of section .text: > 0+ : > [ ]*[a-f0-9]+: 37 \(bad\) > > -0+1 : > -[ ]*[a-f0-9]+: d5 \(bad\) > -[ ]*[a-f0-9]+: 0a .byte 0xa > - > -0+3 : > -[ ]*[a-f0-9]+: d5 \(bad\) > -[ ]*[a-f0-9]+: 02 .byte 0x2 > - > -0+5 : > +0+1 : > [ ]*[a-f0-9]+: d4 \(bad\) > [ ]*[a-f0-9]+: 0a .byte 0xa > > -0+7 : > +0+3 : > [ ]*[a-f0-9]+: d4 \(bad\) > [ ]*[a-f0-9]+: 02 .byte 0x2 > > -0+9 : > +0+5 : > [ ]*[a-f0-9]+: 3f \(bad\) > > -0+a : > +0+6 : > [ ]*[a-f0-9]+: 62 .byte 0x62 > [ ]*[a-f0-9]+: 10 .byte 0x10 > > -0+c : > +0+8 : > [ ]*[a-f0-9]+: 27 \(bad\) > > -0+d : > +0+9 : > [ ]*[a-f0-9]+: 2f \(bad\) > > -0+e : > +0+a : > [ ]*[a-f0-9]+: ce \(bad\) > > -0+f : > +0+b : > [ ]*[a-f0-9]+: 60 \(bad\) > > -0+10 : > +0+c : > [ ]*[a-f0-9]+: 61 \(bad\) > #pass > diff --git a/gas/testsuite/gas/i386/x86-64-opcode-inval.d b/gas/testsuite/gas/i386/x86-64-opcode-inval.d > index 12f02c1766c..fbb850b56da 100644 > --- a/gas/testsuite/gas/i386/x86-64-opcode-inval.d > +++ b/gas/testsuite/gas/i386/x86-64-opcode-inval.d > @@ -9,41 +9,33 @@ Disassembly of section .text: > 0+ : > [ ]*[a-f0-9]+: 37 \(bad\) > > -0+1 : > -[ ]*[a-f0-9]+: d5 \(bad\) > -[ ]*[a-f0-9]+: 0a .byte 0xa > - > -0+3 : > -[ ]*[a-f0-9]+: d5 \(bad\) > -[ ]*[a-f0-9]+: 02 .byte 0x2 > - > -0+5 : > +0+1 : > [ ]*[a-f0-9]+: d4 \(bad\) > [ ]*[a-f0-9]+: 0a .byte 0xa > > -0+7 : > +0+3 : > [ ]*[a-f0-9]+: d4 \(bad\) > [ ]*[a-f0-9]+: 02 .byte 0x2 > > -0+9 : > +0+5 : > [ ]*[a-f0-9]+: 3f \(bad\) > > -0+a : > +0+6 : > [ ]*[a-f0-9]+: 62 .byte 0x62 > [ ]*[a-f0-9]+: 10 .byte 0x10 > > -0+c : > +0+8 : > [ ]*[a-f0-9]+: 27 \(bad\) > > -0+d : > +0+9 : > [ ]*[a-f0-9]+: 2f \(bad\) > > -0+e : > +0+a : > [ ]*[a-f0-9]+: ce \(bad\) > > -0+f : > +0+b : > [ ]*[a-f0-9]+: 60 \(bad\) > > -0+10 : > +0+c : > [ ]*[a-f0-9]+: 61 \(bad\) > #pass > diff --git a/gas/testsuite/gas/i386/x86-64-opcode-inval.s b/gas/testsuite/gas/i386/x86-64-opcode-inval.s > index 6cbfe7705a8..fbcda3df773 100644 > --- a/gas/testsuite/gas/i386/x86-64-opcode-inval.s > +++ b/gas/testsuite/gas/i386/x86-64-opcode-inval.s > @@ -2,10 +2,6 @@ > # All the followings are illegal opcodes for x86-64. > aaa: > aaa > -aad0: > - aad > -aad1: > - aad $2 > aam0: > aam > aam1: > diff --git a/gas/testsuite/gas/i386/x86-64-pseudos-bad.l b/gas/testsuite/gas/i386/x86-64-pseudos-bad.l > index 3f9f67fcf4b..a72f847085d 100644 > --- a/gas/testsuite/gas/i386/x86-64-pseudos-bad.l > +++ b/gas/testsuite/gas/i386/x86-64-pseudos-bad.l > @@ -1,6 +1,71 @@ > .*: Assembler messages: > -.*:3: Error: .*`vmovaps'.* > -.*:4: Error: .*`vmovaps'.* > -.*:5: Error: .*`vmovaps'.* > -.*:6: Error: .*`vmovaps'.* > -.*:7: Error: .*`rorx'.* > +.*:[0-9]+: Error: .*`vmovaps'.* > +.*:[0-9]+: Error: .*`vmovaps'.* > +.*:[0-9]+: Error: .*`vmovaps'.* > +.*:[0-9]+: Error: .*`vmovaps'.* > +.*:[0-9]+: Error: .*`rorx'.* > +.*:[0-9]+: Error: .*`vmovaps'.* > +.*:[0-9]+: Error: .*`xsave'.* > +.*:[0-9]+: Error: .*`xsaves'.* > +.*:[0-9]+: Error: .*`xsaves64'.* > +.*:[0-9]+: Error: .*`xsavec'.* > +.*:[0-9]+: Error: .*`xrstors'.* > +.*:[0-9]+: Error: .*`xrstors64'.* > +.*:[0-9]+: Error: .*`mov'.* > +.*:[0-9]+: Error: .*`movabs'.* > +.*:[0-9]+: Error: .*`cmps'.* > +.*:[0-9]+: Error: .*`lods'.* > +.*:[0-9]+: Error: .*`lods'.* > +.*:[0-9]+: Error: .*`lods'.* > +.*:[0-9]+: Error: .*`movs'.* > +.*:[0-9]+: Error: .*`movs'.* > +.*:[0-9]+: Error: .*`scas'.* > +.*:[0-9]+: Error: .*`scas'.* > +.*:[0-9]+: Error: .*`scas'.* > +.*:[0-9]+: Error: .*`stos'.* > +.*:[0-9]+: Error: .*`stos'.* > +.*:[0-9]+: Error: .*`stos'.* > +.*:[0-9]+: Error: .*`jo'.* > +.*:[0-9]+: Error: .*`jno'.* > +.*:[0-9]+: Error: .*`jb'.* > +.*:[0-9]+: Error: .*`jae'.* > +.*:[0-9]+: Error: .*`je'.* > +.*:[0-9]+: Error: .*`jne'.* > +.*:[0-9]+: Error: .*`jbe'.* > +.*:[0-9]+: Error: .*`ja'.* > +.*:[0-9]+: Error: .*`js'.* > +.*:[0-9]+: Error: .*`jns'.* > +.*:[0-9]+: Error: .*`jp'.* > +.*:[0-9]+: Error: .*`jnp'.* > +.*:[0-9]+: Error: .*`jl'.* > +.*:[0-9]+: Error: .*`jge'.* > +.*:[0-9]+: Error: .*`jle'.* > +.*:[0-9]+: Error: .*`jg'.* > +.*:[0-9]+: Error: .*`jo'.* > +.*:[0-9]+: Error: .*`jno'.* > +.*:[0-9]+: Error: .*`jb'.* > +.*:[0-9]+: Error: .*`jae'.* > +.*:[0-9]+: Error: .*`je'.* > +.*:[0-9]+: Error: .*`jne'.* > +.*:[0-9]+: Error: .*`jbe'.* > +.*:[0-9]+: Error: .*`ja'.* > +.*:[0-9]+: Error: .*`js'.* > +.*:[0-9]+: Error: .*`jns'.* > +.*:[0-9]+: Error: .*`jp'.* > +.*:[0-9]+: Error: .*`jnp'.* > +.*:[0-9]+: Error: .*`jl'.* > +.*:[0-9]+: Error: .*`jge'.* > +.*:[0-9]+: Error: .*`jle'.* > +.*:[0-9]+: Error: .*`jg'.* > +.*:[0-9]+: Error: .*`in'.* > +.*:[0-9]+: Error: .*`in'.* > +.*:[0-9]+: Error: .*`out'.* > +.*:[0-9]+: Error: .*`out'.* > +.*:[0-9]+: Error: .*`jmp'.* > +.*:[0-9]+: Error: .*`loop'.* > +.*:[0-9]+: Error: .*`wrmsr'.* > +.*:[0-9]+: Error: .*`rdtsc'.* > +.*:[0-9]+: Error: .*`rdmsr'.* > +.*:[0-9]+: Error: .*`sysenter'.* > +.*:[0-9]+: Error: .*`sysexit'.* > +.*:[0-9]+: Error: .*`rdpmc'.* > diff --git a/gas/testsuite/gas/i386/x86-64-pseudos-bad.s b/gas/testsuite/gas/i386/x86-64-pseudos-bad.s > index 3b923593a6a..54c17a9eab7 100644 > --- a/gas/testsuite/gas/i386/x86-64-pseudos-bad.s > +++ b/gas/testsuite/gas/i386/x86-64-pseudos-bad.s > @@ -5,3 +5,77 @@ pseudos: > {rex} vmovaps %xmm7,%xmm2 > {rex} vmovaps %xmm17,%xmm2 > {rex} rorx $7,%eax,%ebx > + {rex2} vmovaps %xmm7,%xmm2 > + {rex2} xsave (%rax) > + {rex2} xsaves (%ecx) > + {rex2} xsaves64 (%ecx) > + {rex2} xsavec (%ecx) > + {rex2} xrstors (%ecx) > + {rex2} xrstors64 (%ecx) > + > + #All opcodes in the row 0xA* (map0) prefixed REX2 are illegal. > + #{rex2} test (0xa8) is a special case, it will remap to test (0xf6) > + {rex2} mov 0x90909090,%al > + {rex2} movabs 0x1,%al > + {rex2} cmpsb %es:(%edi),%ds:(%esi) > + {rex2} lodsb > + {rex2} lods %ds:(%esi),%al > + {rex2} lodsb (%esi) > + {rex2} movs > + {rex2} movs (%esi), (%edi) > + {rex2} scasl > + {rex2} scas %es:(%edi),%eax > + {rex2} scasb (%edi) > + {rex2} stosb > + {rex2} stosb (%edi) > + {rex2} stos %eax,%es:(%edi) > + > + #All opcodes in the row 0x7* (map0) and 0x8* (map1) prefixed REX2 are illegal. > + {rex2} jo .+2-0x70 > + {rex2} jno .+2-0x70 > + {rex2} jb .+2-0x70 > + {rex2} jae .+2-0x70 > + {rex2} je .+2-0x70 > + {rex2} jne .+2-0x70 > + {rex2} jbe .+2-0x70 > + {rex2} ja .+2-0x70 > + {rex2} js .+2-0x70 > + {rex2} jns .+2-0x70 > + {rex2} jp .+2-0x70 > + {rex2} jnp .+2-0x70 > + {rex2} jl .+2-0x70 > + {rex2} jge .+2-0x70 > + {rex2} jle .+2-0x70 > + {rex2} jg .+2-0x70 > + {rex2} jo .+6+0x90909090 > + {rex2} jno .+6+0x90909090 > + {rex2} jb .+6+0x90909090 > + {rex2} jae .+6+0x90909090 > + {rex2} je .+6+0x90909090 > + {rex2} jne .+6+0x90909090 > + {rex2} jbe .+6+0x90909090 > + {rex2} ja .+6+0x90909090 > + {rex2} js .+6+0x90909090 > + {rex2} jns .+6+0x90909090 > + {rex2} jp .+6+0x90909090 > + {rex2} jnp .+6+0x90909090 > + {rex2} jl .+6+0x90909090 > + {rex2} jge .+6+0x90909090 > + {rex2} jle .+6+0x90909090 > + {rex2} jg .+6+0x90909090 > + > + #All opcodes in the row 0xE* (map0) prefixed REX2 are illegal. > + {rex2} in $0x90,%al > + {rex2} in $0x90 > + {rex2} out $0x90,%al > + {rex2} out $0x90 > + {rex2} jmp *%eax > + {rex2} loop foo > + > + #All opcodes in the row 0x3* (map1) prefixed REX2 are illegal. > + {rex2} wrmsr > + {rex2} rdtsc > + {rex2} rdmsr > + {rex2} sysenter > + {rex2} sysexitl > + {rex2} rdpmc > diff --git a/gas/testsuite/gas/i386/x86-64-pseudos.d b/gas/testsuite/gas/i386/x86-64-pseudos.d > index 866a804ab92..19dcd8415ac 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 0x0} shl %cl,%eax > + +[a-f0-9]+: d5 00 38 ca {rex2 0x0} cmp %cl,%dl > + +[a-f0-9]+: d5 00 b3 01 {rex2 0x0} mov \$(0x)?1,%bl > + +[a-f0-9]+: d5 00 89 c3 {rex2 0x0} mov %eax,%ebx > + +[a-f0-9]+: d5 01 89 c6 {rex2 0x1} mov %eax,%r14d > + +[a-f0-9]+: d5 01 89 00 {rex2 0x1} mov %eax,\(%r8\) > + +[a-f0-9]+: d5 80 28 d7 {rex2 0x80} movaps %xmm7,%xmm2 > + +[a-f0-9]+: d5 84 28 e7 {rex2 0x84} movaps %xmm7,%xmm12 > + +[a-f0-9]+: d5 80 28 11 {rex2 0x80} movaps \(%rcx\),%xmm2 > + +[a-f0-9]+: d5 81 28 10 {rex2 0x81} movaps \(%r8\),%xmm2 > + +[a-f0-9]+: d5 80 d5 f0 {rex2 0x80} pmullw %mm0,%mm6 > +[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,15 @@ 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 0x0} mov %eax,%ebx > + +[a-f0-9]+: d5 01 89 c6 {rex2 0x1} mov %eax,%r14d > + +[a-f0-9]+: d5 01 89 00 {rex2 0x1} mov %eax,\(%r8\) > + +[a-f0-9]+: d5 80 28 d7 {rex2 0x80} movaps %xmm7,%xmm2 > + +[a-f0-9]+: d5 84 28 e7 {rex2 0x84} movaps %xmm7,%xmm12 > + +[a-f0-9]+: d5 80 28 11 {rex2 0x80} movaps \(%rcx\),%xmm2 > + +[a-f0-9]+: d5 81 28 10 {rex2 0x81} movaps \(%r8\),%xmm2 > + +[a-f0-9]+: d5 80 d5 f0 {rex2 0x80} pmullw %mm0,%mm6 > +[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 06f0b62d049..5a53c363615 100644 > --- a/gas/testsuite/gas/i386/x86-64-pseudos.s > +++ b/gas/testsuite/gas/i386/x86-64-pseudos.s > @@ -360,6 +360,18 @@ _start: > {rex} movaps (%r8),%xmm2 > {rex} phaddw (%rcx),%mm0 > {rex} phaddw (%r8),%mm0 > + {rex2} mov %al,%ah > + {rex2} shl %cl, %eax > + {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 > + {rex2} pmullw %mm0,%mm6 > > movb (%rbp),%al > {disp8} movb (%rbp),%al > @@ -422,6 +434,15 @@ _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] > + {rex2} pmullw mm6,mm0 > > 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 e4b0cc8b85b..91c068d5b40 100644 > --- a/gas/testsuite/gas/i386/x86-64.exp > +++ b/gas/testsuite/gas/i386/x86-64.exp > @@ -363,6 +363,8 @@ 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" > +run_dump_test "x86-64-apx-rex2" > 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..2823d02c68a 100644 > --- a/include/opcode/i386.h > +++ b/include/opcode/i386.h > @@ -112,9 +112,13 @@ > /* 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) > > +/* M0 in rex2 prefix represents map0 or map1. */ > +#define REX2_M 0x8 > /* Indicates 64 bit operand size. */ > #define REX_W 8 > /* High extension to reg field of modrm byte. */ > diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c > index e78a2a9350e..4d6d547b2b6 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; > > + /* Record W R4 X4 B4 bits for rex2. */ > + 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. */ > @@ -265,8 +272,13 @@ struct dis_private { > { \ > if (value) \ > { \ > - if ((ins->rex & value)) \ > + if (ins->rex & value) \ > ins->rex_used |= (value) | REX_OPCODE; \ > + if (ins->rex2 & value) \ > + { \ > + ins->rex2_used |= (value); \ > + ins->rex_used |= REX_OPCODE; \ > + } \ > } \ > else \ > ins->rex_used |= REX_OPCODE; \ > @@ -276,6 +288,7 @@ struct dis_private { > #define EVEX_b_used 1 > #define EVEX_len_used 2 > > + > /* Flags stored in PREFIXES. */ > #define PREFIX_REPZ 1 > #define PREFIX_REPNZ 2 > @@ -289,6 +302,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 > @@ -370,6 +384,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_REX2_ILLEGAL (PREFIX_REX2 << PREFIX_IGNORED_SHIFT) > > /* Opcode prefixes. */ > #define PREFIX_OPCODE (PREFIX_REPZ \ > @@ -1888,23 +1903,23 @@ static const struct dis386 dis386[] = { > { "outs{b|}", { indirDXr, Xb }, 0 }, > { X86_64_TABLE (X86_64_6F) }, > /* 70 */ > - { "joH", { Jb, BND, cond_jump_flag }, 0 }, > - { "jnoH", { Jb, BND, cond_jump_flag }, 0 }, > - { "jbH", { Jb, BND, cond_jump_flag }, 0 }, > - { "jaeH", { Jb, BND, cond_jump_flag }, 0 }, > - { "jeH", { Jb, BND, cond_jump_flag }, 0 }, > - { "jneH", { Jb, BND, cond_jump_flag }, 0 }, > - { "jbeH", { Jb, BND, cond_jump_flag }, 0 }, > - { "jaH", { Jb, BND, cond_jump_flag }, 0 }, > + { "joH", { Jb, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, > + { "jnoH", { Jb, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, > + { "jbH", { Jb, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, > + { "jaeH", { Jb, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, > + { "jeH", { Jb, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, > + { "jneH", { Jb, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, > + { "jbeH", { Jb, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, > + { "jaH", { Jb, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, > /* 78 */ > - { "jsH", { Jb, BND, cond_jump_flag }, 0 }, > - { "jnsH", { Jb, BND, cond_jump_flag }, 0 }, > - { "jpH", { Jb, BND, cond_jump_flag }, 0 }, > - { "jnpH", { Jb, BND, cond_jump_flag }, 0 }, > - { "jlH", { Jb, BND, cond_jump_flag }, 0 }, > - { "jgeH", { Jb, BND, cond_jump_flag }, 0 }, > - { "jleH", { Jb, BND, cond_jump_flag }, 0 }, > - { "jgH", { Jb, BND, cond_jump_flag }, 0 }, > + { "jsH", { Jb, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, > + { "jnsH", { Jb, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, > + { "jpH", { Jb, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, > + { "jnpH", { Jb, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, > + { "jlH", { Jb, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, > + { "jgeH", { Jb, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, > + { "jleH", { Jb, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, > + { "jgH", { Jb, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, > /* 80 */ > { REG_TABLE (REG_80) }, > { REG_TABLE (REG_81) }, > @@ -1942,23 +1957,23 @@ static const struct dis386 dis386[] = { > { "sahf", { XX }, 0 }, > { "lahf", { XX }, 0 }, > /* a0 */ > - { "mov%LB", { AL, Ob }, 0 }, > - { "mov%LS", { eAX, Ov }, 0 }, > - { "mov%LB", { Ob, AL }, 0 }, > - { "mov%LS", { Ov, eAX }, 0 }, > - { "movs{b|}", { Ybr, Xb }, 0 }, > - { "movs{R|}", { Yvr, Xv }, 0 }, > - { "cmps{b|}", { Xb, Yb }, 0 }, > - { "cmps{R|}", { Xv, Yv }, 0 }, > + { "mov%LB", { AL, Ob }, PREFIX_REX2_ILLEGAL }, > + { "mov%LS", { eAX, Ov }, PREFIX_REX2_ILLEGAL }, > + { "mov%LB", { Ob, AL }, PREFIX_REX2_ILLEGAL }, > + { "mov%LS", { Ov, eAX }, PREFIX_REX2_ILLEGAL }, > + { "movs{b|}", { Ybr, Xb }, PREFIX_REX2_ILLEGAL }, > + { "movs{R|}", { Yvr, Xv }, PREFIX_REX2_ILLEGAL }, > + { "cmps{b|}", { Xb, Yb }, PREFIX_REX2_ILLEGAL }, > + { "cmps{R|}", { Xv, Yv }, PREFIX_REX2_ILLEGAL }, > /* a8 */ > - { "testB", { AL, Ib }, 0 }, > - { "testS", { eAX, Iv }, 0 }, > - { "stosB", { Ybr, AL }, 0 }, > - { "stosS", { Yvr, eAX }, 0 }, > - { "lodsB", { ALr, Xb }, 0 }, > - { "lodsS", { eAXr, Xv }, 0 }, > - { "scasB", { AL, Yb }, 0 }, > - { "scasS", { eAX, Yv }, 0 }, > + { "testB", { AL, Ib }, PREFIX_REX2_ILLEGAL }, > + { "testS", { eAX, Iv }, PREFIX_REX2_ILLEGAL }, > + { "stosB", { Ybr, AL }, PREFIX_REX2_ILLEGAL }, > + { "stosS", { Yvr, eAX }, PREFIX_REX2_ILLEGAL }, > + { "lodsB", { ALr, Xb }, PREFIX_REX2_ILLEGAL }, > + { "lodsS", { eAXr, Xv }, PREFIX_REX2_ILLEGAL }, > + { "scasB", { AL, Yb }, PREFIX_REX2_ILLEGAL }, > + { "scasS", { eAX, Yv }, PREFIX_REX2_ILLEGAL }, > /* b0 */ > { "movB", { RMAL, Ib }, 0 }, > { "movB", { RMCL, Ib }, 0 }, > @@ -2014,23 +2029,23 @@ static const struct dis386 dis386[] = { > { FLOAT }, > { FLOAT }, > /* e0 */ > - { "loopneFH", { Jb, XX, loop_jcxz_flag }, 0 }, > - { "loopeFH", { Jb, XX, loop_jcxz_flag }, 0 }, > - { "loopFH", { Jb, XX, loop_jcxz_flag }, 0 }, > - { "jEcxzH", { Jb, XX, loop_jcxz_flag }, 0 }, > - { "inB", { AL, Ib }, 0 }, > - { "inG", { zAX, Ib }, 0 }, > - { "outB", { Ib, AL }, 0 }, > - { "outG", { Ib, zAX }, 0 }, > + { "loopneFH", { Jb, XX, loop_jcxz_flag }, PREFIX_REX2_ILLEGAL }, > + { "loopeFH", { Jb, XX, loop_jcxz_flag }, PREFIX_REX2_ILLEGAL }, > + { "loopFH", { Jb, XX, loop_jcxz_flag }, PREFIX_REX2_ILLEGAL }, > + { "jEcxzH", { Jb, XX, loop_jcxz_flag }, PREFIX_REX2_ILLEGAL }, > + { "inB", { AL, Ib }, PREFIX_REX2_ILLEGAL }, > + { "inG", { zAX, Ib }, PREFIX_REX2_ILLEGAL }, > + { "outB", { Ib, AL }, PREFIX_REX2_ILLEGAL }, > + { "outG", { Ib, zAX }, PREFIX_REX2_ILLEGAL }, > /* e8 */ > { X86_64_TABLE (X86_64_E8) }, > { X86_64_TABLE (X86_64_E9) }, > { X86_64_TABLE (X86_64_EA) }, > - { "jmp", { Jb, BND }, 0 }, > - { "inB", { AL, indirDX }, 0 }, > - { "inG", { zAX, indirDX }, 0 }, > - { "outB", { indirDX, AL }, 0 }, > - { "outG", { indirDX, zAX }, 0 }, > + { "jmp", { Jb, BND }, PREFIX_REX2_ILLEGAL }, > + { "inB", { AL, indirDX }, PREFIX_REX2_ILLEGAL }, > + { "inG", { zAX, indirDX }, PREFIX_REX2_ILLEGAL }, > + { "outB", { indirDX, AL }, PREFIX_REX2_ILLEGAL }, > + { "outG", { indirDX, zAX }, PREFIX_REX2_ILLEGAL }, > /* f0 */ > { Bad_Opcode }, /* lock prefix */ > { "int1", { XX }, 0 }, > @@ -2107,12 +2122,12 @@ static const struct dis386 dis386_twobyte[] = { > { PREFIX_TABLE (PREFIX_0F2E) }, > { PREFIX_TABLE (PREFIX_0F2F) }, > /* 30 */ > - { "wrmsr", { XX }, 0 }, > - { "rdtsc", { XX }, 0 }, > - { "rdmsr", { XX }, 0 }, > - { "rdpmc", { XX }, 0 }, > - { "sysenter", { SEP }, 0 }, > - { "sysexit%LQ", { SEP }, 0 }, > + { "wrmsr", { XX }, PREFIX_REX2_ILLEGAL }, > + { "rdtsc", { XX }, PREFIX_REX2_ILLEGAL }, > + { "rdmsr", { XX }, PREFIX_REX2_ILLEGAL }, > + { "rdpmc", { XX }, PREFIX_REX2_ILLEGAL }, > + { "sysenter", { SEP }, PREFIX_REX2_ILLEGAL }, > + { "sysexit%LQ", { SEP }, PREFIX_REX2_ILLEGAL }, > { Bad_Opcode }, > { "getsec", { XX }, 0 }, > /* 38 */ > @@ -2197,23 +2212,23 @@ static const struct dis386 dis386_twobyte[] = { > { PREFIX_TABLE (PREFIX_0F7E) }, > { PREFIX_TABLE (PREFIX_0F7F) }, > /* 80 */ > - { "joH", { Jv, BND, cond_jump_flag }, 0 }, > - { "jnoH", { Jv, BND, cond_jump_flag }, 0 }, > - { "jbH", { Jv, BND, cond_jump_flag }, 0 }, > - { "jaeH", { Jv, BND, cond_jump_flag }, 0 }, > - { "jeH", { Jv, BND, cond_jump_flag }, 0 }, > - { "jneH", { Jv, BND, cond_jump_flag }, 0 }, > - { "jbeH", { Jv, BND, cond_jump_flag }, 0 }, > - { "jaH", { Jv, BND, cond_jump_flag }, 0 }, > + { "joH", { Jv, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, > + { "jnoH", { Jv, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, > + { "jbH", { Jv, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, > + { "jaeH", { Jv, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, > + { "jeH", { Jv, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, > + { "jneH", { Jv, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, > + { "jbeH", { Jv, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, > + { "jaH", { Jv, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, > /* 88 */ > - { "jsH", { Jv, BND, cond_jump_flag }, 0 }, > - { "jnsH", { Jv, BND, cond_jump_flag }, 0 }, > - { "jpH", { Jv, BND, cond_jump_flag }, 0 }, > - { "jnpH", { Jv, BND, cond_jump_flag }, 0 }, > - { "jlH", { Jv, BND, cond_jump_flag }, 0 }, > - { "jgeH", { Jv, BND, cond_jump_flag }, 0 }, > - { "jleH", { Jv, BND, cond_jump_flag }, 0 }, > - { "jgH", { Jv, BND, cond_jump_flag }, 0 }, > + { "jsH", { Jv, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, > + { "jnsH", { Jv, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, > + { "jpH", { Jv, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, > + { "jnpH", { Jv, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, > + { "jlH", { Jv, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, > + { "jgeH", { Jv, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, > + { "jleH", { Jv, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, > + { "jgH", { Jv, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, > /* 90 */ > { "seto", { Eb }, 0 }, > { "setno", { Eb }, 0 }, > @@ -2406,22 +2421,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", "%?", "%?", > @@ -2810,9 +2833,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_REX2_ILLEGAL }, > + { "xsavec", { FXSAVE }, PREFIX_REX2_ILLEGAL }, > + { "xsaves", { FXSAVE }, PREFIX_REX2_ILLEGAL }, > { MOD_TABLE (MOD_0FC7_REG_6) }, > { MOD_TABLE (MOD_0FC7_REG_7) }, > }, > @@ -3384,7 +3407,7 @@ static const struct dis386 prefix_table[][4] = { > > /* PREFIX_0FAE_REG_4_MOD_0 */ > { > - { "xsave", { FXSAVE }, 0 }, > + { "xsave", { FXSAVE }, PREFIX_REX2_ILLEGAL }, > { "ptwrite{%LQ|}", { Edq }, 0 }, > }, > > @@ -3402,7 +3425,7 @@ static const struct dis386 prefix_table[][4] = { > > /* PREFIX_0FAE_REG_6_MOD_0 */ > { > - { "xsaveopt", { FXSAVE }, PREFIX_OPCODE }, > + { "xsaveopt", { FXSAVE }, PREFIX_OPCODE | PREFIX_REX2_ILLEGAL }, > { "clrssbsy", { Mq }, PREFIX_OPCODE }, > { "clwb", { Mb }, PREFIX_OPCODE }, > }, > @@ -4197,13 +4220,13 @@ static const struct dis386 x86_64_table[][2] = { > /* X86_64_E8 */ > { > { "callP", { Jv, BND }, 0 }, > - { "call@", { Jv, BND }, 0 } > + { "call@", { Jv, BND }, PREFIX_REX2_ILLEGAL } > }, > > /* X86_64_E9 */ > { > { "jmpP", { Jv, BND }, 0 }, > - { "jmp@", { Jv, BND }, 0 } > + { "jmp@", { Jv, BND }, PREFIX_REX2_ILLEGAL } > }, > > /* X86_64_EA */ > @@ -8184,7 +8207,7 @@ static const struct dis386 mod_table[][2] = { > }, > { > /* MOD_0FAE_REG_5 */ > - { "xrstor", { FXSAVE }, PREFIX_OPCODE }, > + { "xrstor", { FXSAVE }, PREFIX_OPCODE | PREFIX_REX2_ILLEGAL }, > { PREFIX_TABLE (PREFIX_0FAE_REG_5_MOD_3) }, > }, > { > @@ -8387,6 +8410,24 @@ ckprefix (instr_info *ins) > return ckp_okay; > ins->last_rex_prefix = i; > break; > + /* REX2 must be the last prefix. */ > + case REX2_OPCODE: > + 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; > @@ -8554,6 +8595,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; > } > @@ -9202,6 +9245,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, > }; > @@ -9367,13 +9411,18 @@ print_insn (bfd_vma pc, disassemble_info *info, int intel_syntax) > goto out; > } > > - if (*ins.codep == 0x0f) > + /* REX2.M in rex2 prefix represents map0 or map1. */ > + if (ins.last_rex2_prefix < 0 ? *ins.codep == 0x0f : (ins.rex2 & REX2_M)) > { > 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]; > @@ -9529,7 +9578,15 @@ print_insn (bfd_vma pc, disassemble_info *info, int intel_syntax) > goto out; > } > > - switch (dp->prefix_requirement) > + if ((dp->prefix_requirement & PREFIX_REX2_ILLEGAL) > + && 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 & ~PREFIX_REX2_ILLEGAL) > { > case PREFIX_DATA: > /* If only the data prefix is marked as mandatory, its absence renders > @@ -9588,6 +9645,13 @@ print_insn (bfd_vma pc, disassemble_info *info, int intel_syntax) > && !ins.need_vex && ins.last_rex_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.rex ^ ins.rex_used) == 0 > + && (ins.rex2 & 0x7)) > + 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 > @@ -9616,7 +9680,11 @@ 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 0x%x} ", name, > + (unsigned int) ins.rex2_payload); > + else > + i386_dis_printf (info, dis_style_mnemonic, "%s ", name); > } > > /* Check maximum code length. */ > @@ -11163,6 +11231,8 @@ print_register (instr_info *ins, unsigned int reg, unsigned int rexmask, > USED_REX (rexmask); > if (ins->rex & rexmask) > reg += 8; > + if (ins->rex2 & rexmask) > + reg += 16; > > switch (bytemode) > { > @@ -11170,7 +11240,7 @@ print_register (instr_info *ins, unsigned int reg, unsigned int rexmask, > case b_swap_mode: > if (reg & 4) > USED_REX (0); > - if (ins->rex) > + if (ins->rex || ins->rex2) > names = att_names8rex; > else > names = att_names8; > @@ -11386,6 +11456,8 @@ OP_E_memory (instr_info *ins, int bytemode, int sizeflag) > int riprel = 0; > int shift; > > + add += (ins->rex2 & REX_B) ? 16 : 0; > + > if (ins->vex.evex) > { > > @@ -11559,6 +11631,9 @@ OP_E_memory (instr_info *ins, int bytemode, int sizeflag) > } > break; > default: > + if (ins->rex2 & REX_X) > + vindex += 16; > + > if (vindex != 4) > indexes = ins->address_mode == mode_64bit && !addr32flag > ? att_names64 : att_names32; > @@ -11946,7 +12021,7 @@ static bool > OP_REG (instr_info *ins, int code, int sizeflag) > { > const char *s; > - int add; > + int add = 0; > > switch (code) > { > @@ -11959,8 +12034,8 @@ OP_REG (instr_info *ins, int code, int sizeflag) > USED_REX (REX_B); > if (ins->rex & REX_B) > add = 8; > - else > - add = 0; > + if (ins->rex2 & REX_B) > + add += 16; > > switch (code) > { > @@ -12674,6 +12749,8 @@ OP_EX (instr_info *ins, int bytemode, int sizeflag) > USED_REX (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 110a8371bd0..dd4850e1855 100644 > --- a/opcodes/i386-gen.c > +++ b/opcodes/i386-gen.c > @@ -275,6 +275,8 @@ static const dependency isa_dependencies[] = > "64" }, > { "USER_MSR", > "64" }, > + { "APX_F", > + "XSAVE|64" }, > }; > > /* This array is populated as process_i386_initializers() walks cpu_flags[]. */ > @@ -397,6 +399,7 @@ static bitfield cpu_flags[] = > BITFIELD (FRED), > BITFIELD (LKGS), > BITFIELD (USER_MSR), > + BITFIELD (APX_F), > BITFIELD (MWAITX), > BITFIELD (CLZERO), > BITFIELD (OSPKE), > @@ -483,6 +486,7 @@ static bitfield opcode_modifiers[] = > BITFIELD (Optimize), > BITFIELD (Dialect), > BITFIELD (ISA64), > + BITFIELD (NoEgpr), > }; > > #define CLASS(n) #n, n > @@ -1069,10 +1073,44 @@ get_element_size (char **opnd, int lineno) > return elem_size; > } > > +static bool > +rex2_disallowed (const unsigned long long opcode, unsigned int length, > + unsigned int space, const char *cpu_flags) > +{ > + /* Some opcodes encode a ModR/M-like byte directly in the opcode. */ > + unsigned int base_opcode = opcode >> (8 * length - 8); > + > + /* All opcodes listed map0 0x4*, 0x7*, 0xa*, 0xe* and map1 0x3*, 0x8* > + are reserved under REX2 and triggers #UD when prefixed with REX2 */ > + if (space == 0) > + switch (base_opcode >> 4) > + { > + case 0x4: > + case 0x7: > + case 0xA: > + case 0xE: > + return true; > + default: > + return false; > + } > + > + if (space == SPACE_0F) > + switch (base_opcode >> 4) > + { > + case 0x3: > + case 0x8: > + return true; > + default: > + return false; > + } > + > + return false; > +} > + > static void > process_i386_opcode_modifier (FILE *table, char *mod, unsigned int space, > unsigned int prefix, const char *extension_opcode, > - char **opnd, int lineno) > + char **opnd, int lineno, bool rex2_disallowed) > { > char *str, *next, *last; > bitfield modifiers [ARRAY_SIZE (opcode_modifiers)]; > @@ -1199,6 +1237,12 @@ process_i386_opcode_modifier (FILE *table, char *mod, unsigned int space, > || modifiers[SAE].value)) > modifiers[EVex].value = EVEXDYN; > > + /* Vex, legacy map2 and map3 and rex2_disallowed do not support EGPR. > + For templates supporting both Vex and EVex allowing EGPR. */ > + if ((modifiers[Vex].value || space > SPACE_0F || rex2_disallowed) > + && !modifiers[EVex].value) > + modifiers[NoEgpr].value = 1; > + > output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers)); > } > > @@ -1423,7 +1467,9 @@ output_i386_opcode (FILE *table, const char *name, char *str, > free (ident); > > process_i386_opcode_modifier (table, opcode_modifier, space, prefix, > - extension_opcode, operand_types, lineno); > + extension_opcode, operand_types, lineno, > + rex2_disallowed (opcode, length, space, > + cpu_flags)); > > process_i386_cpu_flag (table, cpu_flags, NULL, ",", " ", lineno, CpuMax); > > diff --git a/opcodes/i386-opc.h b/opcodes/i386-opc.h > index 03b02bd9681..8c967ea90b0 100644 > --- a/opcodes/i386-opc.h > +++ b/opcodes/i386-opc.h > @@ -319,6 +319,8 @@ enum i386_cpu > CpuAVX512F, > /* Intel AVX-512 VL Instructions support required. */ > CpuAVX512VL, > + /* Intel APX_F Instructions support required. */ > + CpuAPX_F, > /* Not supported in the 64bit mode */ > CpuNo64, > > @@ -354,6 +356,7 @@ enum i386_cpu > cpuhle:1, \ > cpuavx512f:1, \ > cpuavx512vl:1, \ > + cpuapx_f:1, \ > /* NOTE: This field needs to remain last. */ \ > cpuno64:1 > > @@ -735,6 +738,11 @@ enum > #define INTEL64 2 > #define INTEL64ONLY 3 > ISA64, > + > + /* egprs (r16-r31) on instruction illegal. We also use it to judge > + whether the instruction supports pseudo-prefix {rex2}. */ > + NoEgpr, > + > /* The last bitfield in i386_opcode_modifier. */ > Opcode_Modifier_Num > }; > @@ -779,6 +787,7 @@ typedef struct i386_opcode_modifier > unsigned int optimize:1; > unsigned int dialect:2; > unsigned int isa64:2; > + unsigned int noegpr:1; > } i386_opcode_modifier; > > /* Operand classes. */ > @@ -993,7 +1002,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 10 /* {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 > @@ -1020,6 +1030,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 GPRs R16–R31 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 1e54717fa7e..37d3e8663bb 100644 > --- a/opcodes/i386-opc.tbl > +++ b/opcodes/i386-opc.tbl > @@ -892,7 +892,7 @@ rex.wrxb, 0x4f, x64, NoSuf|IsPrefix, {} > load:Load:0, store:Store:0, + > vex:VEX:0, vex2:VEX:0, vex3:VEX3:0, evex:EVEX:0, + > - rex:REX:x64, nooptimize:NoOptimize:0> > + rex:REX:x64, rex2:REX2:APX_F, nooptimize:NoOptimize:0> > > {}, PSEUDO_PREFIX/Prefix_, , NoSuf|IsPrefix, {} > > @@ -1425,16 +1425,17 @@ 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|NoEgpr, { Unspecified|BaseIndex } > +xsave64, 0xfae/4, Xsave&x64, Modrm|NoSuf|Size64|NoEgpr, { Unspecified|BaseIndex } > +xrstor, 0xfae/5, Xsave, Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|NoEgpr, { Unspecified|BaseIndex } > +xrstor64, 0xfae/5, Xsave&x64, Modrm|NoSuf|Size64|NoEgpr, { 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|NoEgpr, { Unspecified|BaseIndex } > +xsaveopt64, 0xfae/6, Xsaveopt&x64, Modrm|NoSuf|Size64|NoEgpr, { Unspecified|BaseIndex } > > // AES instructions. > > @@ -2477,17 +2478,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|NoEgpr, { Unspecified|BaseIndex } > +xrstors64, 0xfc7/3, XSAVES&x64, Modrm|NoSuf|Size64|NoEgpr, { Unspecified|BaseIndex } > +xsaves, 0xfc7/5, XSAVES, Modrm|NoSuf|NoEgpr, { Unspecified|BaseIndex } > +xsaves64, 0xfc7/5, XSAVES&x64, Modrm|NoSuf|Size64|NoEgpr, { 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|NoEgpr, { Unspecified|BaseIndex } > +xsavec64, 0xfc7/4, XSAVEC&x64, Modrm|NoSuf|Size64|NoEgpr, { 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 > -- > 2.25.1 > OK. Thanks. H.J.