diff options
author | Cui, Lili <lili.cui@intel.com> | 2024-04-07 17:28:25 +0800 |
---|---|---|
committer | Cui, Lili <lili.cui@intel.com> | 2024-04-07 17:28:25 +0800 |
commit | dd74a603376ea0c32d06ba18ba52b73e77530cde (patch) | |
tree | f304d02f00f07fcf639545d0f78bfa7b70617745 /gas/config/tc-i386.c | |
parent | bc0d0a5596224491ac6f507f758c4be106b6b5b2 (diff) | |
download | binutils-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.c | 35 |
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; |