aboutsummaryrefslogtreecommitdiff
path: root/gas/config
diff options
context:
space:
mode:
authorCui, Lili <lili.cui@intel.com>2024-06-18 10:45:49 +0800
committerCui, Lili <lili.cui@intel.com>2024-06-18 10:52:40 +0800
commitd8ba1c40371a664fe6fa3ed768dbf78289548359 (patch)
tree8087faa358f411cbdb586ef6453c6ad90ef9b799 /gas/config
parent8864c4afdf2ff75e7edda6075286e07b9714ce12 (diff)
downloadgdb-d8ba1c40371a664fe6fa3ed768dbf78289548359.zip
gdb-d8ba1c40371a664fe6fa3ed768dbf78289548359.tar.gz
gdb-d8ba1c40371a664fe6fa3ed768dbf78289548359.tar.bz2
Support APX CCMP and CTEST
CCMP and CTEST are two new sets of instructions for conditional CMP and TEST, SCC and OSZC flags are given as suffixes of CCMP or CTEST in the instruction mnemonic, e.g.: ccmp<cc> { dfv=sf , cf , of } %eax, %ecx also add {evex} cmp/test %eax, %ecx as an alias for ccmpt. For the encoder part, add function check_Scc_OszcOperation to parse '{ dfv=of , sf, sf, cf}', store scc in the lower 4 bits of base_opcode, and adjust base_opcode to its normal meaning in install_template. For the decoder part, add 'SC' and 'DF' macros to add scc and oszc flags suffixes. gas/ChangeLog: * config/tc-i386.c (OSZC_CF): New. (OSZC_ZF): Ditto. (OSZC_SF): Ditto. (OSZC_OF): Ditto. (set_oszc_flags): Set oszc flags and report error for using the same oszc flags twice. (check_Scc_OszcOperations): Handle SCC OSZC flags. (install_template): Add scc and oszc_flags. (build_apx_evex_prefix): Encode SCC and oszc flags bits. (parse_insn): Handle check_Scc_OszcOperations. * testsuite/gas/i386/x86-64-apx-evex-promoted-bad.d: Add ivalid test case. * testsuite/gas/i386/x86-64-apx-evex-promoted-bad.s: Ditto. * testsuite/gas/i386/x86-64.exp: Add test for ccmp and ctest. * testsuite/gas/i386/x86-64-apx-ccmp-ctest-intel.d: New test. * testsuite/gas/i386/x86-64-apx-ccmp-ctest-inval.l: Ditto. * testsuite/gas/i386/x86-64-apx-ccmp-ctest-inval.s: Ditto. * testsuite/gas/i386/x86-64-apx-ccmp-ctest.d: Ditto. * testsuite/gas/i386/x86-64-apx-ccmp-ctest.s: Ditto. opcodes/ChangeLog: * i386-dis-evex-reg.h: Add ccmp and ctest. * i386-dis-evex.h: Ditto. * i386-dis.c (struct instr_info): add scc. (struct dis386): Add new micro 'NE','SC' and'DF'. (get_valid_dis386): Get scc value and move MAP4 invalid check to print_insn. (putop): Handle %NE, %SC and %DF. * i386-opc.h (SCC): New. * i386-opc.tbl: Add ccmp/ctest and evex format for cmp/test. * i386-mnem.h: Regenerated. * i386-tbl.h: Ditto.
Diffstat (limited to 'gas/config')
-rw-r--r--gas/config/tc-i386.c146
1 files changed, 145 insertions, 1 deletions
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index e0c6964..b8fc3c4 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -416,6 +416,16 @@ struct _i386_insn
/* Compressed disp8*N attribute. */
unsigned int memshift;
+ /* SCC = EVEX.[SC3,SC2,SC1,SC0]. */
+ unsigned int scc;
+
+ /* Store 4 bits of EVEX.[OF,SF,ZF,CF]. */
+#define OSZC_CF 1
+#define OSZC_ZF 2
+#define OSZC_SF 4
+#define OSZC_OF 8
+ unsigned int oszc_flags;
+
/* Prefer load or store in encoding. */
enum
{
@@ -1929,6 +1939,110 @@ static INLINE bool need_evex_encoding (const insn_template *t)
#define CPU_FLAGS_PERFECT_MATCH \
(CPU_FLAGS_ARCH_MATCH | CPU_FLAGS_64BIT_MATCH)
+static INLINE bool set_oszc_flags (unsigned int oszc_shift)
+{
+ if (i.oszc_flags & oszc_shift)
+ {
+ as_bad (_("same oszc flag used twice"));
+ return false;
+ }
+ i.oszc_flags |= oszc_shift;
+ return true;
+}
+
+/* Handle SCC OSZC flags. */
+
+static int
+check_Scc_OszcOperations (const char *l)
+{
+ const char *suffix_string = l;
+
+ while (is_space_char (*suffix_string))
+ suffix_string++;
+
+ /* If {oszc flags} is absent, just return. */
+ if (*suffix_string != '{')
+ return 0;
+
+ /* Skip '{'. */
+ suffix_string++;
+
+ /* Parse 'dfv='. */
+ while (is_space_char (*suffix_string))
+ suffix_string++;
+
+ if (strncasecmp (suffix_string, "dfv", 3) == 0)
+ suffix_string += 3;
+ else
+ {
+ as_bad (_("unrecognized pseudo-suffix"));
+ return -1;
+ }
+
+ while (is_space_char (*suffix_string))
+ suffix_string++;
+
+ if (*suffix_string == '=')
+ suffix_string++;
+ else
+ {
+ as_bad (_("unrecognized pseudo-suffix"));
+ return -1;
+ }
+
+ /* Parse 'of, sf, zf, cf}'. */
+ while (*suffix_string)
+ {
+ while (is_space_char (*suffix_string))
+ suffix_string++;
+
+ /* Return for '{dfv=}'. */
+ if (*suffix_string == '}')
+ return suffix_string + 1 - l;
+
+ if (strncasecmp (suffix_string, "of", 2) == 0)
+ {
+ if (!set_oszc_flags (OSZC_OF))
+ return -1;
+ }
+ else if (strncasecmp (suffix_string, "sf", 2) == 0)
+ {
+ if (!set_oszc_flags (OSZC_SF))
+ return -1;
+ }
+ else if (strncasecmp (suffix_string, "zf", 2) == 0)
+ {
+ if (!set_oszc_flags (OSZC_ZF))
+ return -1;
+ }
+ else if (strncasecmp (suffix_string, "cf", 2) == 0)
+ {
+ if (!set_oszc_flags (OSZC_CF))
+ return -1;
+ }
+ else
+ {
+ as_bad (_("unrecognized oszc flags or illegal `,' in pseudo-suffix"));
+ return -1;
+ }
+
+ suffix_string += 2;
+
+ while (is_space_char (*suffix_string))
+ suffix_string++;
+
+ if (*suffix_string == '}')
+ return ++suffix_string - l;
+
+ if (*suffix_string != ',')
+ break;
+ suffix_string ++;
+ }
+
+ as_bad (_("missing `}' or `,' in pseudo-suffix"));
+ return -1;
+}
+
/* Return CPU flags match bits. */
static int
@@ -3793,10 +3907,19 @@ install_template (const insn_template *t)
}
}
+ /* For CCMP and CTEST the template has EVEX.SCC in base_opcode. Move it out of
+ there, to then adjust base_opcode to obtain its normal meaning. */
+ if (i.tm.opcode_modifier.operandconstraint == SCC)
+ {
+ /* Get EVEX.SCC value from the lower 4 bits of base_opcode. */
+ i.scc = i.tm.base_opcode & 0xf;
+ i.tm.base_opcode >>= 8;
+ }
+
/* Note that for pseudo prefixes this produces a length of 1. But for them
the length isn't interesting at all. */
for (l = 1; l < 4; ++l)
- if (!(t->base_opcode >> (8 * l)))
+ if (!(i.tm.base_opcode >> (8 * l)))
break;
i.opcode_length = l;
@@ -4290,6 +4413,18 @@ build_apx_evex_prefix (void)
|| i.tm.opcode_modifier.operandconstraint == ZERO_UPPER)
i.vex.bytes[3] |= 0x10;
+ /* Encode SCC and oszc flags bits. */
+ if (i.tm.opcode_modifier.operandconstraint == SCC)
+ {
+ /* The default value of vvvv is 1111 and needs to be cleared. */
+ i.vex.bytes[2] &= ~0x78;
+ i.vex.bytes[2] |= (i.oszc_flags << 3);
+ /* ND and aaa bits shold be 0. */
+ know (!(i.vex.bytes[3] & 0x17));
+ /* The default value of V' is 1 and needs to be cleared. */
+ i.vex.bytes[3] = (i.vex.bytes[3] & ~0x08) | i.scc;
+ }
+
/* Encode the NF bit. */
if (i.has_nf)
i.vex.bytes[3] |= 0x04;
@@ -7428,6 +7563,15 @@ parse_insn (const char *line, char *mnemonic, bool prefix_only)
}
}
+ /* Handle SCC OSZC flgs. */
+ if (current_templates.start->opcode_modifier.operandconstraint == SCC)
+ {
+ int length = check_Scc_OszcOperations (l);
+ if (length < 0)
+ return NULL;
+ l += length;
+ }
+
if (current_templates.start->opcode_modifier.jump == JUMP
|| current_templates.start->opcode_modifier.jump == JUMP_BYTE)
{