-/* Copyright (C) 2007-2020 Free Software Foundation, Inc.
+/* Copyright (C) 2007-2022 Free Software Foundation, Inc.
This file is part of the GNU opcodes library.
static initializer cpu_flag_init[] =
{
{ "CPU_UNKNOWN_FLAGS",
- "~(CpuL1OM|CpuK1OM)" },
+ "~CpuIAMCU" },
{ "CPU_GENERIC32_FLAGS",
"Cpu186|Cpu286|Cpu386" },
{ "CPU_GENERIC64_FLAGS",
"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",
"CPU_SSE4_2_FLAGS|CPU_XSAVE_FLAGS|CpuAVX" },
{ "CPU_AVX2_FLAGS",
"CPU_AVX_FLAGS|CpuAVX2" },
+ { "CPU_AVX_VNNI_FLAGS",
+ "CPU_AVX2_FLAGS|CpuAVX_VNNI" },
{ "CPU_AVX512F_FLAGS",
"CPU_AVX2_FLAGS|CpuAVX512F" },
{ "CPU_AVX512CD_FLAGS",
"CPU_AVX512F_FLAGS|CpuAVX512_BITALG" },
{ "CPU_AVX512_BF16_FLAGS",
"CPU_AVX512F_FLAGS|CpuAVX512_BF16" },
- { "CPU_L1OM_FLAGS",
- "unknown" },
- { "CPU_K1OM_FLAGS",
- "unknown" },
+ { "CPU_AVX512_FP16_FLAGS",
+ "CPU_AVX512BW_FLAGS|CpuAVX512_FP16" },
{ "CPU_IAMCU_FLAGS",
- "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586" },
+ "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuIAMCU" },
{ "CPU_ADX_FLAGS",
"CpuADX" },
{ "CPU_RDSEED_FLAGS",
"CpuPCONFIG" },
{ "CPU_WAITPKG_FLAGS",
"CpuWAITPKG" },
+ { "CPU_UINTR_FLAGS",
+ "CpuUINTR" },
{ "CPU_CLDEMOTE_FLAGS",
"CpuCLDEMOTE" },
+ { "CPU_AMX_INT8_FLAGS",
+ "CpuAMX_INT8" },
+ { "CPU_AMX_BF16_FLAGS",
+ "CpuAMX_BF16" },
+ { "CPU_AMX_TILE_FLAGS",
+ "CpuAMX_TILE" },
{ "CPU_MOVDIRI_FLAGS",
"CpuMOVDIRI" },
{ "CPU_MOVDIR64B_FLAGS",
"CpuMOVDIR64B" },
{ "CPU_ENQCMD_FLAGS",
"CpuENQCMD" },
+ { "CPU_SERIALIZE_FLAGS",
+ "CpuSERIALIZE" },
{ "CPU_AVX512_VP2INTERSECT_FLAGS",
"CpuAVX512_VP2INTERSECT" },
+ { "CPU_TDX_FLAGS",
+ "CpuTDX" },
{ "CPU_RDPRU_FLAGS",
"CpuRDPRU" },
{ "CPU_MCOMMIT_FLAGS",
"CpuMCOMMIT" },
{ "CPU_SEV_ES_FLAGS",
"CpuSEV_ES" },
+ { "CPU_TSXLDTRK_FLAGS",
+ "CpuTSXLDTRK"},
+ { "CPU_KL_FLAGS",
+ "CpuKL" },
+ { "CPU_WIDEKL_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",
{ "CPU_ANY_AVX2_FLAGS",
"CPU_ANY_AVX512F_FLAGS|CpuAVX2" },
{ "CPU_ANY_AVX512F_FLAGS",
- "CpuAVX512F|CpuAVX512CD|CpuAVX512ER|CpuAVX512PF|CpuAVX512DQ|CpuAVX512BW|CpuAVX512VL|CpuAVX512IFMA|CpuAVX512VBMI|CpuAVX512_4FMAPS|CpuAVX512_4VNNIW|CpuAVX512_VPOPCNTDQ|CpuAVX512_VBMI2|CpuAVX512_VNNI|CpuAVX512_BITALG|CpuAVX512_BF16|CpuAVX512_VP2INTERSECT" },
+ "CpuAVX512F|CpuAVX512CD|CpuAVX512ER|CpuAVX512PF|CpuAVX512DQ|CPU_ANY_AVX512BW_FLAGS|CpuAVX512VL|CpuAVX512IFMA|CpuAVX512VBMI|CpuAVX512_4FMAPS|CpuAVX512_4VNNIW|CpuAVX512_VPOPCNTDQ|CpuAVX512_VBMI2|CpuAVX512_VNNI|CpuAVX512_BITALG|CpuAVX512_BF16|CpuAVX512_VP2INTERSECT" },
{ "CPU_ANY_AVX512CD_FLAGS",
"CpuAVX512CD" },
{ "CPU_ANY_AVX512ER_FLAGS",
{ "CPU_ANY_AVX512DQ_FLAGS",
"CpuAVX512DQ" },
{ "CPU_ANY_AVX512BW_FLAGS",
- "CpuAVX512BW" },
+ "CpuAVX512BW|CPU_ANY_AVX512_FP16_FLAGS" },
{ "CPU_ANY_AVX512VL_FLAGS",
"CpuAVX512VL" },
{ "CPU_ANY_AVX512IFMA_FLAGS",
"CpuAVX512_BITALG" },
{ "CPU_ANY_AVX512_BF16_FLAGS",
"CpuAVX512_BF16" },
+ { "CPU_ANY_AMX_INT8_FLAGS",
+ "CpuAMX_INT8" },
+ { "CPU_ANY_AMX_BF16_FLAGS",
+ "CpuAMX_BF16" },
+ { "CPU_ANY_AMX_TILE_FLAGS",
+ "CpuAMX_TILE|CpuAMX_INT8|CpuAMX_BF16" },
+ { "CPU_ANY_AVX_VNNI_FLAGS",
+ "CpuAVX_VNNI" },
{ "CPU_ANY_MOVDIRI_FLAGS",
"CpuMOVDIRI" },
+ { "CPU_ANY_UINTR_FLAGS",
+ "CpuUINTR" },
{ "CPU_ANY_MOVDIR64B_FLAGS",
"CpuMOVDIR64B" },
{ "CPU_ANY_ENQCMD_FLAGS",
"CpuENQCMD" },
+ { "CPU_ANY_SERIALIZE_FLAGS",
+ "CpuSERIALIZE" },
{ "CPU_ANY_AVX512_VP2INTERSECT_FLAGS",
"CpuAVX512_VP2INTERSECT" },
+ { "CPU_ANY_TDX_FLAGS",
+ "CpuTDX" },
+ { "CPU_ANY_TSXLDTRK_FLAGS",
+ "CpuTSXLDTRK" },
+ { "CPU_ANY_KL_FLAGS",
+ "CpuKL|CpuWideKL" },
+ { "CPU_ANY_WIDEKL_FLAGS",
+ "CpuWideKL" },
+ { "CPU_ANY_HRESET_FLAGS",
+ "CpuHRESET" },
+ { "CPU_ANY_AVX512_FP16_FLAGS",
+ "CpuAVX512_FP16" },
};
static initializer operand_type_init[] =
"Disp16" },
{ "OPERAND_TYPE_DISP32",
"Disp32" },
- { "OPERAND_TYPE_DISP32S",
- "Disp32S" },
{ "OPERAND_TYPE_DISP64",
"Disp64" },
{ "OPERAND_TYPE_INOUTPORTREG",
"Class=RegSIMD|Ymmword" },
{ "OPERAND_TYPE_REGZMM",
"Class=RegSIMD|Zmmword" },
+ { "OPERAND_TYPE_REGTMM",
+ "Class=RegSIMD|Tmmword" },
{ "OPERAND_TYPE_REGMASK",
"Class=RegMask" },
{ "OPERAND_TYPE_REGBND",
{ "OPERAND_TYPE_DISP16_32",
"Disp16|Disp32" },
{ "OPERAND_TYPE_ANYDISP",
- "Disp8|Disp16|Disp32|Disp32S|Disp64" },
+ "Disp8|Disp16|Disp32|Disp64" },
{ "OPERAND_TYPE_IMM16_32",
"Imm16|Imm32" },
{ "OPERAND_TYPE_IMM16_32S",
BITFIELD (CpuAVX512VL),
BITFIELD (CpuAVX512DQ),
BITFIELD (CpuAVX512BW),
- BITFIELD (CpuL1OM),
- BITFIELD (CpuK1OM),
BITFIELD (CpuIAMCU),
BITFIELD (CpuSSE4a),
BITFIELD (Cpu3dnow),
BITFIELD (CpuPREFETCHWT1),
BITFIELD (CpuSE1),
BITFIELD (CpuCLWB),
- BITFIELD (Cpu64),
- BITFIELD (CpuNo64),
BITFIELD (CpuMPX),
BITFIELD (CpuAVX512IFMA),
BITFIELD (CpuAVX512VBMI),
BITFIELD (CpuAVX512_BITALG),
BITFIELD (CpuAVX512_BF16),
BITFIELD (CpuAVX512_VP2INTERSECT),
+ BITFIELD (CpuTDX),
+ BITFIELD (CpuAVX_VNNI),
+ BITFIELD (CpuAVX512_FP16),
BITFIELD (CpuMWAITX),
BITFIELD (CpuCLZERO),
BITFIELD (CpuOSPKE),
BITFIELD (CpuWBNOINVD),
BITFIELD (CpuPCONFIG),
BITFIELD (CpuWAITPKG),
+ BITFIELD (CpuUINTR),
BITFIELD (CpuCLDEMOTE),
+ BITFIELD (CpuAMX_INT8),
+ BITFIELD (CpuAMX_BF16),
+ BITFIELD (CpuAMX_TILE),
BITFIELD (CpuMOVDIRI),
BITFIELD (CpuMOVDIR64B),
BITFIELD (CpuENQCMD),
+ BITFIELD (CpuSERIALIZE),
BITFIELD (CpuRDPRU),
BITFIELD (CpuMCOMMIT),
BITFIELD (CpuSEV_ES),
+ BITFIELD (CpuTSXLDTRK),
+ BITFIELD (CpuKL),
+ BITFIELD (CpuWideKL),
+ BITFIELD (CpuHRESET),
+ BITFIELD (CpuINVLPGB),
+ BITFIELD (CpuTLBSYNC),
+ BITFIELD (CpuSNP),
+ BITFIELD (Cpu64),
+ BITFIELD (CpuNo64),
#ifdef CpuUnused
BITFIELD (CpuUnused),
#endif
BITFIELD (FloatR),
BITFIELD (Size),
BITFIELD (CheckRegSize),
+ BITFIELD (DistinctDest),
BITFIELD (MnemonicSize),
BITFIELD (Anysize),
BITFIELD (No_bSuf),
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 (ImmExt),
BITFIELD (NoRex64),
BITFIELD (Ugh),
+ BITFIELD (PseudoVexPrefix),
BITFIELD (Vex),
BITFIELD (VexVVVV),
BITFIELD (VexW),
- BITFIELD (VexOpcode),
+ BITFIELD (OpcodeSpace),
+ BITFIELD (OpcodePrefix),
BITFIELD (VexSources),
- BITFIELD (VecSIB),
+ BITFIELD (SIB),
BITFIELD (SSE2AVX),
- BITFIELD (NoAVX),
BITFIELD (EVex),
BITFIELD (Masking),
BITFIELD (Broadcast),
BITFIELD (Disp8MemShift),
BITFIELD (NoDefMask),
BITFIELD (ImplicitQuadGroup),
+ BITFIELD (SwapSources),
BITFIELD (Optimize),
BITFIELD (ATTMnemonic),
BITFIELD (ATTSyntax),
BITFIELD (Disp8),
BITFIELD (Disp16),
BITFIELD (Disp32),
- BITFIELD (Disp32S),
BITFIELD (Disp64),
BITFIELD (Byte),
BITFIELD (Word),
BITFIELD (Xmmword),
BITFIELD (Ymmword),
BITFIELD (Zmmword),
+ BITFIELD (Tmmword),
BITFIELD (Unspecified),
#ifdef OTUnused
BITFIELD (OTUnused),
};
struct template {
- const struct template *next;
+ struct template *next;
const char *name;
const struct template_instance *instances;
const struct template_param *params;
};
-static const struct template *templates;
+static struct template *templates;
static int
compare (const void *x, const void *y)
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-2022 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)
{
const char *comma, const char *indent,
int lineno)
{
- char *str, *next, *last;
+ char *str, *next = flag, *last;
unsigned int i;
+ int value = 1;
bitfield flags [ARRAY_SIZE (cpu_flags)];
/* Copy the default cpu flags. */
memcpy (flags, cpu_flags, sizeof (cpu_flags));
- if (strcasecmp (flag, "unknown") == 0)
- {
- /* We turn on everything except for cpu64 in case of
- CPU_UNKNOWN_FLAGS. */
- for (i = 0; i < ARRAY_SIZE (flags); i++)
- if (flags[i].position != Cpu64)
- flags[i].value = 1;
- }
- else if (flag[0] == '~')
+ if (flag[0] == '~')
{
last = flag + strlen (flag);
else
next = flag + 1;
- /* First we turn on everything except for cpu64. */
+ /* First we turn on everything except for cpu64, cpuno64, and - if
+ present - the padding field. */
for (i = 0; i < ARRAY_SIZE (flags); i++)
- if (flags[i].position != Cpu64)
+ if (flags[i].position < Cpu64)
flags[i].value = 1;
/* Turn off selective bits. */
- for (; next && next < last; )
- {
- str = next_field (next, '|', &next, last);
- if (str)
- set_bitfield (str, flags, 0, ARRAY_SIZE (flags), lineno);
- }
+ value = 0;
}
- else if (strcmp (flag, "0"))
+
+ if (strcmp (flag, "0"))
{
- /* Turn on selective bits. */
+ /* Turn on/off selective bits. */
last = flag + strlen (flag);
- for (next = flag; next && next < last; )
+ for (; next && next < last; )
{
str = next_field (next, '|', &next, last);
if (str)
- set_bitfield (str, flags, 1, ARRAY_SIZE (flags), lineno);
+ set_bitfield (str, flags, value, ARRAY_SIZE (flags), lineno);
}
}
fprintf (table, "%d },\n", modifier[i].value);
}
+/* Returns LOG2 of element size. */
static int
-adjust_broadcast_modifier (char **opnd)
+get_element_size (char **opnd, int lineno)
{
char *str, *next, *last, *op;
- int bcst_type = INT_MAX;
+ const char *full = opnd[0];
+ int elem_size = INT_MAX;
- /* Skip the immediate operand. */
- op = opnd[0];
- if (strcasecmp(op, "Imm8") == 0)
- op = opnd[1];
+ /* Find the memory operand. */
+ while (full != NULL && strstr(full, "BaseIndex") == NULL)
+ full = *++opnd;
+ if (full == NULL)
+ fail (_("%s: %d: no memory operand\n"), filename, lineno);
- op = xstrdup (op);
+ op = xstrdup (full);
last = op + strlen (op);
for (next = op; next && next < last; )
{
{
if (strcasecmp(str, "Byte") == 0)
{
- /* The smalest broadcast type, no need to check
+ /* The smallest element size, no need to check
further. */
- bcst_type = BYTE_BROADCAST;
+ elem_size = 0;
break;
}
else if (strcasecmp(str, "Word") == 0)
{
- if (bcst_type > WORD_BROADCAST)
- bcst_type = WORD_BROADCAST;
+ if (elem_size > 1)
+ elem_size = 1;
}
else if (strcasecmp(str, "Dword") == 0)
{
- if (bcst_type > DWORD_BROADCAST)
- bcst_type = DWORD_BROADCAST;
+ if (elem_size > 2)
+ elem_size = 2;
}
else if (strcasecmp(str, "Qword") == 0)
{
- if (bcst_type > QWORD_BROADCAST)
- bcst_type = QWORD_BROADCAST;
+ if (elem_size > 3)
+ elem_size = 3;
}
}
}
free (op);
- if (bcst_type == INT_MAX)
- fail (_("unknown broadcast operand: %s\n"), op);
+ if (elem_size == INT_MAX)
+ fail (_("%s: %d: unknown element size: %s\n"), filename, lineno, full);
- return bcst_type;
+ return elem_size;
}
static void
-process_i386_opcode_modifier (FILE *table, char *mod, char **opnd, int lineno)
+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)];
{
int val = 1;
if (strcasecmp(str, "Broadcast") == 0)
- val = adjust_broadcast_modifier (opnd);
+ val = get_element_size (opnd, lineno) + BYTE_BROADCAST;
+ else if (strcasecmp(str, "Disp8MemShift") == 0)
+ val = get_element_size (opnd, lineno);
+
set_bitfield (str, modifiers, val, ARRAY_SIZE (modifiers),
- lineno);
+ lineno);
if (strcasecmp(str, "IsString") == 0)
active_isstring = 1;
}
}
+ 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))
if (!active_cpu_flags.bitfield.cpu64
&& !active_cpu_flags.bitfield.cpumpx)
set_bitfield("Disp16", types, 1, ARRAY_SIZE (types), lineno);
- if (!active_cpu_flags.bitfield.cpu64)
- set_bitfield("Disp32", types, 1, ARRAY_SIZE (types), lineno);
- if (!active_cpu_flags.bitfield.cpuno64)
- set_bitfield("Disp32S", types, 1, ARRAY_SIZE (types), lineno);
+ set_bitfield("Disp32", types, 1, ARRAY_SIZE (types), lineno);
}
}
output_operand_type (table, class, instance, types, ARRAY_SIZE (types),
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 (prefix)
+ opcode &= (1ULL << (8 * --length)) - 1;
+ }
+
+ /* Transform opcode space encoded in the opcode into opcode modifier
+ representation. */
+ if (length > 1 && (opcode >> (8 * length - 8)) == 0xf)
+ {
+ switch ((opcode >> (8 * length - 16)) & 0xff)
{
- if (i != 0)
- operand_types[i] = NULL;
- 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;
}
- fprintf (table, " { \"%s\", %s, %s, %s, %s,\n",
- name, base_opcode, extension_opcode, opcode_length, operands);
+ if (length > 2)
+ fail (_("%s:%d: %s: residual opcode (0x%0*llx) too large\n"),
+ filename, lineno, name, 2 * length, opcode);
- process_i386_cpu_flag (table, cpu_flags, 0, ",", " ", lineno);
+ fprintf (table, " { \"%s\", 0x%0*llx%s, %lu, %s,\n",
+ name, 2 * (int)length, opcode, end, i, extension_opcode);
+
+ process_i386_opcode_modifier (table, opcode_modifier, space, prefix,
+ operand_types, lineno);
- process_i386_opcode_modifier (table, opcode_modifier, 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 ",
parse_template (char *buf, int lineno)
{
char sep, *end, *name;
- struct template *tmpl = xmalloc (sizeof (*tmpl));
+ struct template *tmpl;
struct template_instance *last_inst = NULL;
buf = remove_leading_whitespaces (buf + 1);
end = strchr (buf, ':');
if (end == NULL)
- fail ("%s: %d: missing ':'\n", filename, lineno);
+ {
+ struct template *prev = NULL;
+
+ end = strchr (buf, '>');
+ if (end == NULL)
+ fail ("%s: %d: missing ':' or '>'\n", filename, lineno);
+ if (*remove_leading_whitespaces (end + 1))
+ fail ("%s: %d: malformed template purge\n", filename, lineno);
+ *end = '\0';
+ remove_trailing_whitespaces (buf);
+ /* Don't bother freeing the various structures. */
+ for (tmpl = templates; tmpl != NULL; tmpl = (prev = tmpl)->next)
+ if (!strcmp (buf, tmpl->name))
+ break;
+ if (tmpl == NULL)
+ fail ("%s: %d: no template '%s'\n", filename, lineno, buf);
+ if (prev)
+ prev->next = tmpl->next;
+ else
+ templates = tmpl->next;
+ return;
+ }
*end++ = '\0';
remove_trailing_whitespaces (buf);
if (*buf == '\0')
fail ("%s: %d: missing template identifier\n", filename, lineno);
+ tmpl = xmalloc (sizeof (*tmpl));
tmpl->name = xstrdup (buf);
tmpl->params = NULL;
*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)
{
if (fgets (buf, sizeof (buf), fp) == NULL)
break;
- lineno++;
-
p = remove_leading_whitespaces (buf);
- /* Skip comments. */
- str = strstr (p, "//");
- if (str != NULL)
- str[0] = '\0';
+ for ( ; ; )
+ {
+ lineno++;
- /* Remove trailing white spaces. */
- remove_trailing_whitespaces (p);
+ /* Skip comments. */
+ str = strstr (p, "//");
+ if (str != NULL)
+ {
+ str[0] = '\0';
+ remove_trailing_whitespaces (p);
+ break;
+ }
+
+ /* Look for line continuation character. */
+ remove_trailing_whitespaces (p);
+ j = strlen (buf);
+ if (!j || buf[j - 1] != '+')
+ break;
+ if (j >= sizeof (buf) - 1)
+ fail (_("%s: %d: (continued) line too long\n"), filename, lineno);
+
+ if (fgets (buf + j - 1, sizeof (buf) - j + 1, fp) == NULL)
+ {
+ fprintf (stderr, "%s: Line continuation on last line?\n",
+ filename);
+ break;
+ }
+ }
switch (p[0])
{
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);