aboutsummaryrefslogtreecommitdiff
path: root/gas/config/tc-i386.c
diff options
context:
space:
mode:
authorCui, Lili <lili.cui@intel.com>2024-04-07 17:28:25 +0800
committerCui, Lili <lili.cui@intel.com>2024-04-07 17:28:25 +0800
commitdd74a603376ea0c32d06ba18ba52b73e77530cde (patch)
treef304d02f00f07fcf639545d0f78bfa7b70617745 /gas/config/tc-i386.c
parentbc0d0a5596224491ac6f507f758c4be106b6b5b2 (diff)
downloadbinutils-dd74a603376ea0c32d06ba18ba52b73e77530cde.zip
binutils-dd74a603376ea0c32d06ba18ba52b73e77530cde.tar.gz
binutils-dd74a603376ea0c32d06ba18ba52b73e77530cde.tar.bz2
Support APX NF
For the case when NDD and NF are both 0 in evex-promoted format, we will fully support and test it in another patch. gas/ChangeLog: * NEWS: Support Intel APX NF. * config/tc-i386.c (enum i386_error): Add unsupported_nf. (struct _i386_insn): Add has_nf. (is_apx_evex_encoding): Ditto. (build_apx_evex_prefix): Encode the NF bit. (md_assemble): Handle unsupported_nf. (parse_insn): Handle Prefix_NF and report bad for illegal combination. (can_convert_NDD_to_legacy): Replace i.tm.opcode_modifier.nf with i.has_nf. (match_template): Support D for APX_F insns and check NF support. * testsuite/gas/i386/x86-64-apx-evex-promoted-bad.d: Add bad test for NF bit. * testsuite/gas/i386/x86-64-apx-evex-promoted-bad.s: Ditto. * testsuite/gas/i386/x86-64-apx-inval.l: Ditto. * testsuite/gas/i386/x86-64-apx-inval.s: Ditto. * testsuite/gas/i386/x86-64.exp: Add apx nf tests. * testsuite/gas/i386/x86-64-apx-nf-intel.d: New test. * testsuite/gas/i386/x86-64-apx-nf.d: Ditto. * testsuite/gas/i386/x86-64-apx-nf.s: Ditto. opcodes/ChangeLog: * i386-dis-evex.h: Add %NF to the instructions that support APX NF and add new instruction imul, popcnt, tzcnt and lzcnt to EVEX table. * i386-dis-evex-reg.h: Ditto. * i386-dis.c (struct instr_info): Add nf. (struct dis386): Add "NF" for EVEX.NF. (get_valid_dis386): Set ins->vex.nf and report bad-nf for illegal case. (print_insn): Handle ins.vex.nf. (putop): Handle "%NF". * i386-opc.h (Prefix_NF): New. * i386-opc.tbl: Added new entries to support full APX NF instructions. * i386-mnem.h: Regenerated. * i386-tbl.h: Regenerated.
Diffstat (limited to 'gas/config/tc-i386.c')
-rw-r--r--gas/config/tc-i386.c35
1 files changed, 31 insertions, 4 deletions
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index b022efa..8f6337b 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -242,6 +242,7 @@ enum i386_error
unsupported_with_intel_mnemonic,
unsupported_syntax,
unsupported_EGPR_for_addressing,
+ unsupported_nf,
unsupported,
unsupported_on_arch,
unsupported_64bit,
@@ -439,6 +440,9 @@ struct _i386_insn
/* Prefer the REX2 prefix in encoding. */
bool rex2_encoding;
+ /* No CSPAZO flags update. */
+ bool has_nf;
+
/* Disable instruction size optimization. */
bool no_optimize;
@@ -3944,7 +3948,7 @@ is_any_vex_encoding (const insn_template *t)
static INLINE bool
is_apx_evex_encoding (void)
{
- return i.rex2 || i.tm.opcode_space == SPACE_EVEXMAP4
+ return i.rex2 || i.tm.opcode_space == SPACE_EVEXMAP4 || i.has_nf
|| (i.vex.register_specifier
&& (i.vex.register_specifier->reg_flags & RegRex2));
}
@@ -4251,6 +4255,10 @@ build_apx_evex_prefix (void)
space. */
if (i.vex.register_specifier && i.tm.opcode_space == SPACE_EVEXMAP4)
i.vex.bytes[3] |= 0x10;
+
+ /* Encode the NF bit. */
+ if (i.has_nf)
+ i.vex.bytes[3] |= 0x04;
}
static void establish_rex (void)
@@ -6645,6 +6653,9 @@ md_assemble (char *line)
case unsupported_EGPR_for_addressing:
err_msg = _("extended GPR cannot be used as base/index");
break;
+ case unsupported_nf:
+ err_msg = _("{nf} unsupported");
+ break;
case unsupported:
as_bad (_("unsupported instruction `%s'"),
pass1_mnem ? pass1_mnem : insn_name (current_templates.start));
@@ -7209,6 +7220,12 @@ parse_insn (const char *line, char *mnemonic, bool prefix_only)
/* {rex2} */
i.rex2_encoding = true;
break;
+ case Prefix_NF:
+ /* {nf} */
+ i.has_nf = true;
+ if (i.encoding == encoding_default)
+ i.encoding = encoding_evex;
+ break;
case Prefix_NoOptimize:
/* {nooptimize} */
i.no_optimize = true;
@@ -7216,6 +7233,11 @@ parse_insn (const char *line, char *mnemonic, bool prefix_only)
default:
abort ();
}
+ if (i.has_nf && i.encoding != encoding_evex)
+ {
+ as_bad (_("{nf} cannot be combined with {vex}/{vex3}"));
+ return NULL;
+ }
}
else
{
@@ -8468,8 +8490,7 @@ can_convert_NDD_to_legacy (const insn_template *t)
{
unsigned int match_dest_op = ~0;
- if (!i.tm.opcode_modifier.nf
- && i.reg_operands >= 2)
+ if (!i.has_nf && i.reg_operands >= 2)
{
unsigned int dest = i.operands - 1;
unsigned int src1 = i.operands - 2;
@@ -8559,6 +8580,11 @@ match_template (char mnem_suffix)
: t->opcode_modifier.dialect == INTEL_SYNTAX)
continue;
+ /* Check NF support. */
+ specific_error = progress (unsupported_nf);
+ if (i.has_nf && !t->opcode_modifier.nf)
+ continue;
+
/* Check Intel64/AMD64 ISA. */
switch (isa64)
{
@@ -8902,7 +8928,8 @@ match_template (char mnem_suffix)
found_reverse_match = Opcode_VexW;
goto check_operands_345;
}
- else if (is_cpu (t, CpuAPX_F) && i.operands == 3)
+ else if (t->opcode_space == SPACE_EVEXMAP4
+ && t->opcode_modifier.w)
{
found_reverse_match = Opcode_D;
goto check_operands_345;