-/* Copyright (C) 2007-2020 Free Software Foundation, Inc.
+/* Copyright (C) 2007-2021 Free Software Foundation, Inc.
This file is part of the GNU opcodes library.
"CPU_GENERIC64_FLAGS|CpuFISTTP|CpuRdtscp|CpuCX16|CPU_AVX2_FLAGS|CpuSSE4A|CpuLZCNT|CpuPOPCNT|CpuSVME|CpuAES|CpuPCLMUL|CpuPRFCHW|CpuFMA|CpuBMI|CpuF16C|CpuXsaveopt|CpuFSGSBase|CpuMovbe|CpuBMI2|CpuRdRnd|CpuADX|CpuRdSeed|CpuSMAP|CpuSHA|CpuXSAVEC|CpuXSAVES|CpuClflushOpt|CpuCLZERO|CpuMWAITX" },
{ "CPU_ZNVER2_FLAGS",
"CPU_ZNVER1_FLAGS|CpuCLWB|CpuRDPID|CpuRDPRU|CpuMCOMMIT|CpuWBNOINVD" },
+ { "CPU_ZNVER3_FLAGS",
+ "CPU_ZNVER2_FLAGS|CpuINVLPGB|CpuTLBSYNC|CpuVAES|CpuVPCLMULQDQ|CpuINVPCID|CpuSNP|CpuOSPKE" },
{ "CPU_BTVER1_FLAGS",
"CPU_GENERIC64_FLAGS|CpuFISTTP|CpuCX16|CpuRdtscp|CPU_SSSE3_FLAGS|CpuSSE4A|CpuLZCNT|CpuPOPCNT|CpuPRFCHW|CpuCX16|CpuClflush|CpuFISTTP|CpuSVME" },
{ "CPU_BTVER2_FLAGS",
"CpuWideKL" },
{ "CPU_HRESET_FLAGS",
"CpuHRESET"},
+ { "CPU_INVLPGB_FLAGS",
+ "CpuINVLPGB" },
+ { "CPU_TLBSYNC_FLAGS",
+ "CpuTLBSYNC" },
+ { "CPU_SNP_FLAGS",
+ "CpuSNP" },
{ "CPU_ANY_X87_FLAGS",
"CPU_ANY_287_FLAGS|Cpu8087" },
{ "CPU_ANY_287_FLAGS",
BITFIELD (CpuKL),
BITFIELD (CpuWideKL),
BITFIELD (CpuHRESET),
+ BITFIELD (CpuINVLPGB),
+ BITFIELD (CpuTLBSYNC),
+ BITFIELD (CpuSNP),
#ifdef CpuUnused
BITFIELD (CpuUnused),
#endif
BITFIELD (IsString),
BITFIELD (RegMem),
BITFIELD (BNDPrefixOk),
- BITFIELD (NoTrackPrefixOk),
- BITFIELD (IsLockable),
BITFIELD (RegKludge),
BITFIELD (Implicit1stXmm0),
- BITFIELD (RepPrefixOk),
- BITFIELD (HLEPrefixOk),
+ BITFIELD (PrefixOk),
BITFIELD (ToDword),
BITFIELD (ToQword),
BITFIELD (AddrPrefixOpReg),
BITFIELD (Vex),
BITFIELD (VexVVVV),
BITFIELD (VexW),
+ BITFIELD (OpcodeSpace),
BITFIELD (OpcodePrefix),
BITFIELD (VexSources),
BITFIELD (SIB),
process_copyright (FILE *fp)
{
fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\
-/* Copyright (C) 2007-2020 Free Software Foundation, Inc.\n\
+/* Copyright (C) 2007-2021 Free Software Foundation, Inc.\n\
\n\
This file is part of the GNU opcodes library.\n\
\n\
if (*f == '\0')
return;
- if (strcmp (f, "CpuFP") == 0)
- {
- set_bitfield("Cpu387", array, value, size, lineno);
- set_bitfield("Cpu287", array, value, size, lineno);
- f = "Cpu8087";
- }
- else if (strcmp (f, "Mmword") == 0)
- f= "Qword";
- else if (strcmp (f, "Oword") == 0)
- f= "Xmmword";
-
for (i = 0; i < size; i++)
if (strcasecmp (array[i].name, f) == 0)
{
return bcst_type;
}
-static int
-process_i386_opcode_modifier (FILE *table, char *mod, char **opnd, int lineno)
+static void
+process_i386_opcode_modifier (FILE *table, char *mod, unsigned int space,
+ unsigned int prefix, char **opnd, int lineno)
{
char *str, *next, *last;
bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
- unsigned int regular_encoding = 1;
active_isstring = 0;
{
int val = 1;
if (strcasecmp(str, "Broadcast") == 0)
- {
- val = adjust_broadcast_modifier (opnd);
- regular_encoding = 0;
- }
- else if (strcasecmp(str, "Vex") == 0
- || strncasecmp(str, "Vex=", 4) == 0
- || strcasecmp(str, "EVex") == 0
- || strncasecmp(str, "EVex=", 5) == 0
- || strncasecmp(str, "Disp8MemShift=", 14) == 0
- || strncasecmp(str, "Masking=", 8) == 0
- || strcasecmp(str, "SAE") == 0
- || strcasecmp(str, "IsPrefix") == 0)
- regular_encoding = 0;
+ val = adjust_broadcast_modifier (opnd);
set_bitfield (str, modifiers, val, ARRAY_SIZE (modifiers),
lineno);
}
}
+ if (space)
+ {
+ if (!modifiers[OpcodeSpace].value)
+ modifiers[OpcodeSpace].value = space;
+ else if (modifiers[OpcodeSpace].value != space)
+ fail (_("%s:%d: Conflicting opcode space specifications\n"),
+ filename, lineno);
+ else
+ fprintf (stderr,
+ _("%s:%d: Warning: redundant opcode space specification\n"),
+ filename, lineno);
+ }
+
+ if (prefix)
+ {
+ if (!modifiers[OpcodePrefix].value)
+ modifiers[OpcodePrefix].value = prefix;
+ else if (modifiers[OpcodePrefix].value != prefix)
+ fail (_("%s:%d: Conflicting prefix specifications\n"),
+ filename, lineno);
+ else
+ fprintf (stderr,
+ _("%s:%d: Warning: redundant prefix specification\n"),
+ filename, lineno);
+ }
+
if (have_w && !bwlq_suf)
fail ("%s: %d: stray W modifier\n", filename, lineno);
if (have_w && !(bwlq_suf & 1))
filename, lineno);
}
output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
-
- return regular_encoding;
}
enum stage {
output_i386_opcode (FILE *table, const char *name, char *str,
char *last, int lineno)
{
- unsigned int i;
- char *operands, *base_opcode, *extension_opcode, *opcode_length;
+ unsigned int i, length, prefix = 0, space = 0;
+ char *base_opcode, *extension_opcode, *end;
char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
-
- /* Find number of operands. */
- operands = next_field (str, ',', &str, last);
+ unsigned long long opcode;
/* Find base_opcode. */
base_opcode = next_field (str, ',', &str, last);
/* Find extension_opcode. */
extension_opcode = next_field (str, ',', &str, last);
- /* Find opcode_length. */
- opcode_length = next_field (str, ',', &str, last);
-
/* Find cpu_flags. */
cpu_flags = next_field (str, ',', &str, last);
if (*str != '{')
abort ();
str = remove_leading_whitespaces (str + 1);
+ remove_trailing_whitespaces (str);
+ /* Remove } and trailing white space. */
i = strlen (str);
-
- /* There are at least "X}". */
- if (i < 2)
+ if (!i || str[i - 1] != '}')
abort ();
+ str[--i] = '\0';
+ remove_trailing_whitespaces (str);
- /* Remove trailing white spaces and }. */
- do
+ if (!*str)
+ operand_types [i = 0] = NULL;
+ else
{
- i--;
- if (ISSPACE (str[i]) || str[i] == '}')
- str[i] = '\0';
- else
- break;
+ last = str + strlen (str);
+
+ /* Find operand_types. */
+ for (i = 0; i < ARRAY_SIZE (operand_types); i++)
+ {
+ if (str >= last)
+ {
+ operand_types [i] = NULL;
+ break;
+ }
+
+ operand_types [i] = next_field (str, ',', &str, last);
+ }
}
- while (i != 0);
- last = str + i;
+ opcode = strtoull (base_opcode, &end, 0);
- /* Find operand_types. */
- for (i = 0; i < ARRAY_SIZE (operand_types); i++)
+ /* Determine opcode length. */
+ for (length = 1; length < 8; ++length)
+ if (!(opcode >> (8 * length)))
+ break;
+
+ /* Transform prefixes encoded in the opcode into opcode modifier
+ representation. */
+ if (length > 1)
{
- if (str >= last)
+ switch (opcode >> (8 * length - 8))
{
- operand_types [i] = NULL;
- break;
+ case 0x66: prefix = PREFIX_0X66; break;
+ case 0xF3: prefix = PREFIX_0XF3; break;
+ case 0xF2: prefix = PREFIX_0XF2; break;
}
- operand_types [i] = next_field (str, ',', &str, last);
- if (*operand_types[i] == '0')
- {
- if (i != 0)
- operand_types[i] = NULL;
- break;
- }
+ if (prefix)
+ opcode &= (1ULL << (8 * --length)) - 1;
}
- fprintf (table, " { \"%s\", %s, %s, %s, %s,\n",
- name, base_opcode, extension_opcode, opcode_length, operands);
-
- process_i386_cpu_flag (table, cpu_flags, 0, ",", " ", lineno);
-
- if (process_i386_opcode_modifier (table, opcode_modifier,
- operand_types, lineno))
+ /* Transform opcode space encoded in the opcode into opcode modifier
+ representation. */
+ if (length > 1 && (opcode >> (8 * length - 8)) == 0xf)
{
- char *end;
- unsigned long int length = strtoul (opcode_length, &end, 0);
- unsigned long int opcode = strtoul (base_opcode, &end, 0);
- switch (length)
+ switch ((opcode >> (8 * length - 16)) & 0xff)
{
- case 4:
- break;
- case 3:
- if ((opcode >> 24) != 0)
- fail (_("%s: %s: (base_opcode >> 24) != 0: %s\n"),
- filename, name, base_opcode);
- break;
- case 2:
- if ((opcode >> 16) != 0)
- fail (_("%s: %s: (base_opcode >> 16) != 0: %s\n"),
- filename, name, base_opcode);
- break;
- case 1:
- if ((opcode >> 8) != 0)
- fail (_("%s: %s: (base_opcode >> 8) != 0: %s\n"),
- filename, name, base_opcode);
- break;
- case 0:
- if (opcode != 0)
- fail (_("%s: %s: base_opcode != 0: %s\n"),
- filename, name, base_opcode);
- break;
- default:
- fail (_("%s: %s: invalid opcode length: %s\n"),
- filename, name, opcode_length);
- break;
+ default: space = SPACE_0F; break;
+ case 0x38: space = SPACE_0F38; break;
+ case 0x3A: space = SPACE_0F3A; break;
}
+
+ if (space != SPACE_0F && --length == 1)
+ fail (_("%s:%d: %s: unrecognized opcode encoding space\n"),
+ filename, lineno, name);
+ opcode &= (1ULL << (8 * --length)) - 1;
}
+ if (length > 2)
+ fail (_("%s:%d: %s: residual opcode (0x%0*llx) too large\n"),
+ filename, lineno, name, 2 * length, opcode);
+
+ fprintf (table, " { \"%s\", 0x%0*llx%s, %s, %lu,\n",
+ name, 2 * (int)length, opcode, end, extension_opcode, i);
+
+ process_i386_opcode_modifier (table, opcode_modifier, space, prefix,
+ operand_types, lineno);
+
+ process_i386_cpu_flag (table, cpu_flags, 0, ",", " ", lineno);
+
fprintf (table, " { ");
for (i = 0; i < ARRAY_SIZE (operand_types); i++)
{
- if (operand_types[i] == NULL || *operand_types[i] == '0')
+ if (!operand_types[i])
{
if (i == 0)
process_i386_operand_type (table, "0", stage_opcodes, "\t ",
*end++ = '\0';
inst = xmalloc (sizeof (*inst));
+ inst->next = NULL;
+ inst->args = NULL;
cur = next_field (buf, ':', &next, end);
- inst->name = xstrdup (cur);
+ inst->name = *cur != '$' ? xstrdup (cur) : "";
for (param = tmpl->params; param; param = param->next)
{
fclose (fp);
- fprintf (table, " { NULL, 0, 0, 0, 0,\n");
+ fprintf (table, " { NULL, 0, 0, 0,\n");
- process_i386_cpu_flag (table, "0", 0, ",", " ", -1);
+ process_i386_opcode_modifier (table, "0", 0, 0, NULL, -1);
- process_i386_opcode_modifier (table, "0", NULL, -1);
+ process_i386_cpu_flag (table, "0", 0, ",", " ", -1);
fprintf (table, " { ");
process_i386_operand_type (table, "0", stage_opcodes, "\t ", -1);