-/* Copyright (C) 2007-2018 Free Software Foundation, Inc.
+/* Copyright (C) 2007-2020 Free Software Foundation, Inc.
This file is part of the GNU opcodes library.
#include <libintl.h>
#define _(String) gettext (String)
+/* Build-time checks are preferrable over runtime ones. Use this construct
+ in preference where possible. */
+#define static_assert(e) ((void)sizeof (struct { int _:1 - 2 * !(e); }))
+
static const char *program_name = NULL;
static int debug = 0;
{ "CPU_I586_FLAGS",
"CPU_I486_FLAGS|Cpu387|Cpu586" },
{ "CPU_I686_FLAGS",
- "CPU_I586_FLAGS|Cpu686|Cpu687" },
+ "CPU_I586_FLAGS|Cpu686|Cpu687|CpuCMOV|CpuFXSR" },
{ "CPU_PENTIUMPRO_FLAGS",
"CPU_I686_FLAGS|CpuNop" },
{ "CPU_P2_FLAGS",
{ "CPU_K8_FLAGS",
"CPU_ATHLON_FLAGS|CpuRdtscp|CPU_SSE2_FLAGS|CpuLM" },
{ "CPU_AMDFAM10_FLAGS",
- "CPU_K8_FLAGS|CpuFISTTP|CPU_SSE4A_FLAGS|CpuABM" },
+ "CPU_K8_FLAGS|CpuFISTTP|CPU_SSE4A_FLAGS|CpuLZCNT|CpuPOPCNT" },
{ "CPU_BDVER1_FLAGS",
- "CPU_GENERIC64_FLAGS|CpuFISTTP|CpuRdtscp|CpuCX16|CPU_XOP_FLAGS|CpuABM|CpuLWP|CpuSVME|CpuAES|CpuPCLMUL|CpuLZCNT|CpuPRFCHW" },
+ "CPU_GENERIC64_FLAGS|CpuFISTTP|CpuRdtscp|CpuCX16|CPU_XOP_FLAGS|CpuLZCNT|CpuPOPCNT|CpuLWP|CpuSVME|CpuAES|CpuPCLMUL|CpuPRFCHW" },
{ "CPU_BDVER2_FLAGS",
"CPU_BDVER1_FLAGS|CpuFMA|CpuBMI|CpuTBM|CpuF16C" },
{ "CPU_BDVER3_FLAGS",
{ "CPU_BDVER4_FLAGS",
"CPU_BDVER3_FLAGS|CpuAVX2|CpuMovbe|CpuBMI2|CpuRdRnd|CpuMWAITX" },
{ "CPU_ZNVER1_FLAGS",
- "CPU_GENERIC64_FLAGS|CpuFISTTP|CpuRdtscp|CpuCX16|CPU_AVX2_FLAGS|CpuSSE4A|CpuABM|CpuSVME|CpuAES|CpuPCLMUL|CpuLZCNT|CpuPRFCHW|CpuFMA|CpuBMI|CpuF16C|CpuXsaveopt|CpuFSGSBase|CpuMovbe|CpuBMI2|CpuRdRnd|CpuADX|CpuRdSeed|CpuSMAP|CpuSHA|CpuXSAVEC|CpuXSAVES|CpuClflushOpt|CpuCLZERO|CpuMWAITX" },
+ "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|CpuRDPID|CpuWBNOINVD|CpuCLWB" },
+ "CPU_ZNVER1_FLAGS|CpuCLWB|CpuRDPID|CpuRDPRU|CpuMCOMMIT|CpuWBNOINVD" },
{ "CPU_BTVER1_FLAGS",
- "CPU_GENERIC64_FLAGS|CpuFISTTP|CpuCX16|CpuRdtscp|CPU_SSSE3_FLAGS|CpuSSE4A|CpuABM|CpuPRFCHW|CpuCX16|CpuClflush|CpuFISTTP|CpuSVME|CpuLZCNT" },
+ "CPU_GENERIC64_FLAGS|CpuFISTTP|CpuCX16|CpuRdtscp|CPU_SSSE3_FLAGS|CpuSSE4A|CpuLZCNT|CpuPOPCNT|CpuPRFCHW|CpuCX16|CpuClflush|CpuFISTTP|CpuSVME" },
{ "CPU_BTVER2_FLAGS",
"CPU_BTVER1_FLAGS|CPU_AVX_FLAGS|CpuBMI|CpuF16C|CpuAES|CpuPCLMUL|CpuMovbe|CpuXsaveopt|CpuPRFCHW" },
{ "CPU_8087_FLAGS",
"Cpu387" },
{ "CPU_687_FLAGS",
"CPU_387_FLAGS|Cpu687" },
+ { "CPU_CMOV_FLAGS",
+ "CpuCMOV" },
+ { "CPU_FXSR_FLAGS",
+ "CpuFXSR" },
{ "CPU_CLFLUSH_FLAGS",
"CpuClflush" },
{ "CPU_NOP_FLAGS",
{ "CPU_SSE4_1_FLAGS",
"CPU_SSSE3_FLAGS|CpuSSE4_1" },
{ "CPU_SSE4_2_FLAGS",
- "CPU_SSE4_1_FLAGS|CpuSSE4_2" },
+ "CPU_SSE4_1_FLAGS|CpuSSE4_2|CpuPOPCNT" },
{ "CPU_VMX_FLAGS",
"CpuVMX" },
{ "CPU_SMX_FLAGS",
"CpuBMI2" },
{ "CPU_LZCNT_FLAGS",
"CpuLZCNT" },
+ { "CPU_POPCNT_FLAGS",
+ "CpuPOPCNT" },
{ "CPU_HLE_FLAGS",
"CpuHLE" },
{ "CPU_RTM_FLAGS",
{ "CPU_SSE4A_FLAGS",
"CPU_SSE3_FLAGS|CpuSSE4a" },
{ "CPU_ABM_FLAGS",
- "CpuABM" },
+ "CpuLZCNT|CpuPOPCNT" },
{ "CPU_AVX_FLAGS",
"CPU_SSE4_2_FLAGS|CPU_XSAVE_FLAGS|CpuAVX" },
{ "CPU_AVX2_FLAGS",
"CPU_AVX512F_FLAGS|CpuAVX512_VNNI" },
{ "CPU_AVX512_BITALG_FLAGS",
"CPU_AVX512F_FLAGS|CpuAVX512_BITALG" },
+ { "CPU_AVX512_BF16_FLAGS",
+ "CPU_AVX512F_FLAGS|CpuAVX512_BF16" },
{ "CPU_L1OM_FLAGS",
"unknown" },
{ "CPU_K1OM_FLAGS",
"CpuMOVDIRI" },
{ "CPU_MOVDIR64B_FLAGS",
"CpuMOVDIR64B" },
+ { "CPU_ENQCMD_FLAGS",
+ "CpuENQCMD" },
+ { "CPU_SERIALIZE_FLAGS",
+ "CpuSERIALIZE" },
+ { "CPU_AVX512_VP2INTERSECT_FLAGS",
+ "CpuAVX512_VP2INTERSECT" },
+ { "CPU_RDPRU_FLAGS",
+ "CpuRDPRU" },
+ { "CPU_MCOMMIT_FLAGS",
+ "CpuMCOMMIT" },
+ { "CPU_SEV_ES_FLAGS",
+ "CpuSEV_ES" },
+ { "CPU_TSXLDTRK_FLAGS",
+ "CpuTSXLDTRK"},
{ "CPU_ANY_X87_FLAGS",
"CPU_ANY_287_FLAGS|Cpu8087" },
{ "CPU_ANY_287_FLAGS",
"CPU_ANY_687_FLAGS|Cpu387" },
{ "CPU_ANY_687_FLAGS",
"Cpu687|CpuFISTTP" },
+ { "CPU_ANY_CMOV_FLAGS",
+ "CpuCMOV" },
+ { "CPU_ANY_FXSR_FLAGS",
+ "CpuFXSR" },
{ "CPU_ANY_MMX_FLAGS",
"CPU_3DNOWA_FLAGS" },
{ "CPU_ANY_SSE_FLAGS",
- "CPU_ANY_SSE2_FLAGS|CpuSSE|CpuSSE4a" },
+ "CPU_ANY_SSE2_FLAGS|CpuSSE" },
{ "CPU_ANY_SSE2_FLAGS",
"CPU_ANY_SSE3_FLAGS|CpuSSE2" },
{ "CPU_ANY_SSE3_FLAGS",
- "CPU_ANY_SSSE3_FLAGS|CpuSSE3" },
+ "CPU_ANY_SSSE3_FLAGS|CpuSSE3|CpuSSE4a" },
{ "CPU_ANY_SSSE3_FLAGS",
"CPU_ANY_SSE4_1_FLAGS|CpuSSSE3" },
{ "CPU_ANY_SSE4_1_FLAGS",
"CPU_ANY_SSE4_2_FLAGS|CpuSSE4_1" },
{ "CPU_ANY_SSE4_2_FLAGS",
"CpuSSE4_2" },
+ { "CPU_ANY_SSE4A_FLAGS",
+ "CpuSSE4a" },
{ "CPU_ANY_AVX_FLAGS",
"CPU_ANY_AVX2_FLAGS|CpuF16C|CpuFMA|CpuFMA4|CpuXOP|CpuAVX" },
{ "CPU_ANY_AVX2_FLAGS",
- "CpuAVX2" },
+ "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" },
+ "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" },
{ "CPU_ANY_AVX512CD_FLAGS",
"CpuAVX512CD" },
{ "CPU_ANY_AVX512ER_FLAGS",
"CpuAVX512_VNNI" },
{ "CPU_ANY_AVX512_BITALG_FLAGS",
"CpuAVX512_BITALG" },
+ { "CPU_ANY_AVX512_BF16_FLAGS",
+ "CpuAVX512_BF16" },
{ "CPU_ANY_MOVDIRI_FLAGS",
"CpuMOVDIRI" },
{ "CPU_ANY_MOVDIR64B_FLAGS",
"CpuMOVDIR64B" },
-};
-
-static const initializer operand_type_shorthands[] =
-{
- { "Reg8", "Reg|Byte" },
- { "Reg16", "Reg|Word" },
- { "Reg32", "Reg|Dword" },
- { "Reg64", "Reg|Qword" },
- { "FloatAcc", "Acc|Tbyte" },
- { "FloatReg", "Reg|Tbyte" },
- { "RegXMM", "RegSIMD|Xmmword" },
- { "RegYMM", "RegSIMD|Ymmword" },
- { "RegZMM", "RegSIMD|Zmmword" },
+ { "CPU_ANY_ENQCMD_FLAGS",
+ "CpuENQCMD" },
+ { "CPU_ANY_SERIALIZE_FLAGS",
+ "CpuSERIALIZE" },
+ { "CPU_ANY_AVX512_VP2INTERSECT_FLAGS",
+ "CpuAVX512_VP2INTERSECT" },
+ { "CPU_ANY_TSXLDTRK_FLAGS",
+ "CpuTSXLDTRK" },
};
static initializer operand_type_init[] =
{ "OPERAND_TYPE_NONE",
"0" },
{ "OPERAND_TYPE_REG8",
- "Reg8" },
+ "Class=Reg|Byte" },
{ "OPERAND_TYPE_REG16",
- "Reg16" },
+ "Class=Reg|Word" },
{ "OPERAND_TYPE_REG32",
- "Reg32" },
+ "Class=Reg|Dword" },
{ "OPERAND_TYPE_REG64",
- "Reg64" },
+ "Class=Reg|Qword" },
{ "OPERAND_TYPE_IMM1",
"Imm1" },
{ "OPERAND_TYPE_IMM8",
{ "OPERAND_TYPE_DISP64",
"Disp64" },
{ "OPERAND_TYPE_INOUTPORTREG",
- "InOutPortReg" },
+ "Instance=RegD|Word" },
{ "OPERAND_TYPE_SHIFTCOUNT",
- "ShiftCount" },
+ "Instance=RegC|Byte" },
{ "OPERAND_TYPE_CONTROL",
- "Control" },
+ "Class=RegCR" },
{ "OPERAND_TYPE_TEST",
- "Test" },
+ "Class=RegTR" },
{ "OPERAND_TYPE_DEBUG",
- "FloatReg" },
+ "Class=RegDR" },
{ "OPERAND_TYPE_FLOATREG",
- "FloatReg" },
+ "Class=Reg|Tbyte" },
{ "OPERAND_TYPE_FLOATACC",
- "FloatAcc" },
- { "OPERAND_TYPE_SREG2",
- "SReg2" },
- { "OPERAND_TYPE_SREG3",
- "SReg3" },
- { "OPERAND_TYPE_ACC",
- "Acc" },
- { "OPERAND_TYPE_JUMPABSOLUTE",
- "JumpAbsolute" },
+ "Instance=Accum|Tbyte" },
+ { "OPERAND_TYPE_SREG",
+ "Class=SReg" },
{ "OPERAND_TYPE_REGMMX",
- "RegMMX" },
+ "Class=RegMMX" },
{ "OPERAND_TYPE_REGXMM",
- "RegXMM" },
+ "Class=RegSIMD|Xmmword" },
{ "OPERAND_TYPE_REGYMM",
- "RegYMM" },
+ "Class=RegSIMD|Ymmword" },
{ "OPERAND_TYPE_REGZMM",
- "RegZMM" },
+ "Class=RegSIMD|Zmmword" },
{ "OPERAND_TYPE_REGMASK",
- "RegMask" },
- { "OPERAND_TYPE_ESSEG",
- "EsSeg" },
+ "Class=RegMask" },
+ { "OPERAND_TYPE_REGBND",
+ "Class=RegBND" },
+ { "OPERAND_TYPE_ACC8",
+ "Instance=Accum|Byte" },
+ { "OPERAND_TYPE_ACC16",
+ "Instance=Accum|Word" },
{ "OPERAND_TYPE_ACC32",
- "Reg32|Acc|Dword" },
+ "Instance=Accum|Dword" },
{ "OPERAND_TYPE_ACC64",
- "Reg64|Acc|Qword" },
+ "Instance=Accum|Qword" },
{ "OPERAND_TYPE_DISP16_32",
"Disp16|Disp32" },
{ "OPERAND_TYPE_ANYDISP",
"Imm32|Imm32S|Imm64|Disp32" },
{ "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
"Imm32|Imm32S|Imm64|Disp32|Disp64" },
- { "OPERAND_TYPE_VEC_IMM4",
- "Vec_Imm4" },
- { "OPERAND_TYPE_REGBND",
- "RegBND" },
+ { "OPERAND_TYPE_ANYIMM",
+ "Imm1|Imm8|Imm8S|Imm16|Imm32|Imm32S|Imm64" },
};
typedef struct bitfield
BITFIELD (Cpu486),
BITFIELD (Cpu586),
BITFIELD (Cpu686),
+ BITFIELD (CpuCMOV),
+ BITFIELD (CpuFXSR),
BITFIELD (CpuClflush),
BITFIELD (CpuNop),
BITFIELD (CpuSYSCALL),
BITFIELD (CpuSVME),
BITFIELD (CpuVMX),
BITFIELD (CpuSMX),
- BITFIELD (CpuABM),
BITFIELD (CpuXsave),
BITFIELD (CpuXsaveopt),
BITFIELD (CpuAES),
BITFIELD (CpuF16C),
BITFIELD (CpuBMI2),
BITFIELD (CpuLZCNT),
+ BITFIELD (CpuPOPCNT),
BITFIELD (CpuHLE),
BITFIELD (CpuRTM),
BITFIELD (CpuINVPCID),
BITFIELD (CpuAVX512_VBMI2),
BITFIELD (CpuAVX512_VNNI),
BITFIELD (CpuAVX512_BITALG),
+ BITFIELD (CpuAVX512_BF16),
+ BITFIELD (CpuAVX512_VP2INTERSECT),
BITFIELD (CpuMWAITX),
BITFIELD (CpuCLZERO),
BITFIELD (CpuOSPKE),
BITFIELD (CpuCLDEMOTE),
BITFIELD (CpuMOVDIRI),
BITFIELD (CpuMOVDIR64B),
+ BITFIELD (CpuENQCMD),
+ BITFIELD (CpuSERIALIZE),
+ BITFIELD (CpuRDPRU),
+ BITFIELD (CpuMCOMMIT),
+ BITFIELD (CpuSEV_ES),
+ BITFIELD (CpuTSXLDTRK),
#ifdef CpuUnused
BITFIELD (CpuUnused),
#endif
BITFIELD (W),
BITFIELD (Load),
BITFIELD (Modrm),
- BITFIELD (ShortForm),
BITFIELD (Jump),
- BITFIELD (JumpDword),
- BITFIELD (JumpByte),
- BITFIELD (JumpInterSegment),
BITFIELD (FloatMF),
BITFIELD (FloatR),
- BITFIELD (Size16),
- BITFIELD (Size32),
- BITFIELD (Size64),
+ BITFIELD (Size),
BITFIELD (CheckRegSize),
- BITFIELD (IgnoreSize),
- BITFIELD (DefaultSize),
+ BITFIELD (MnemonicSize),
+ BITFIELD (Anysize),
BITFIELD (No_bSuf),
BITFIELD (No_wSuf),
BITFIELD (No_lSuf),
BITFIELD (No_ldSuf),
BITFIELD (FWait),
BITFIELD (IsString),
+ BITFIELD (RegMem),
BITFIELD (BNDPrefixOk),
BITFIELD (NoTrackPrefixOk),
BITFIELD (IsLockable),
BITFIELD (IsPrefix),
BITFIELD (ImmExt),
BITFIELD (NoRex64),
- BITFIELD (Rex64),
BITFIELD (Ugh),
BITFIELD (Vex),
BITFIELD (VexVVVV),
BITFIELD (VexW),
BITFIELD (VexOpcode),
BITFIELD (VexSources),
- BITFIELD (VecSIB),
+ BITFIELD (SIB),
BITFIELD (SSE2AVX),
BITFIELD (NoAVX),
BITFIELD (EVex),
BITFIELD (Disp8MemShift),
BITFIELD (NoDefMask),
BITFIELD (ImplicitQuadGroup),
+ BITFIELD (SwapSources),
BITFIELD (Optimize),
BITFIELD (ATTMnemonic),
BITFIELD (ATTSyntax),
BITFIELD (IntelSyntax),
- BITFIELD (AMD64),
- BITFIELD (Intel64),
+ BITFIELD (ISA64),
};
+#define CLASS(n) #n, n
+
+static const struct {
+ const char *name;
+ enum operand_class value;
+} operand_classes[] = {
+ CLASS (Reg),
+ CLASS (SReg),
+ CLASS (RegCR),
+ CLASS (RegDR),
+ CLASS (RegTR),
+ CLASS (RegMMX),
+ CLASS (RegSIMD),
+ CLASS (RegMask),
+ CLASS (RegBND),
+};
+
+#undef CLASS
+
+#define INSTANCE(n) #n, n
+
+static const struct {
+ const char *name;
+ enum operand_instance value;
+} operand_instances[] = {
+ INSTANCE (Accum),
+ INSTANCE (RegC),
+ INSTANCE (RegD),
+ INSTANCE (RegB),
+};
+
+#undef INSTANCE
+
static bitfield operand_types[] =
{
- BITFIELD (Reg),
- BITFIELD (RegMMX),
- BITFIELD (RegSIMD),
- BITFIELD (RegMask),
BITFIELD (Imm1),
BITFIELD (Imm8),
BITFIELD (Imm8S),
BITFIELD (Disp32),
BITFIELD (Disp32S),
BITFIELD (Disp64),
- BITFIELD (InOutPortReg),
- BITFIELD (ShiftCount),
- BITFIELD (Control),
- BITFIELD (Debug),
- BITFIELD (Test),
- BITFIELD (SReg2),
- BITFIELD (SReg3),
- BITFIELD (Acc),
- BITFIELD (JumpAbsolute),
- BITFIELD (EsSeg),
- BITFIELD (RegMem),
- BITFIELD (Mem),
BITFIELD (Byte),
BITFIELD (Word),
BITFIELD (Dword),
BITFIELD (Ymmword),
BITFIELD (Zmmword),
BITFIELD (Unspecified),
- BITFIELD (Anysize),
- BITFIELD (Vec_Imm4),
- BITFIELD (RegBND),
#ifdef OTUnused
BITFIELD (OTUnused),
#endif
static i386_cpu_flags active_cpu_flags;
static int active_isstring;
+struct template_arg {
+ const struct template_arg *next;
+ const char *val;
+};
+
+struct template_instance {
+ const struct template_instance *next;
+ const char *name;
+ const struct template_arg *args;
+};
+
+struct template_param {
+ const struct template_param *next;
+ const char *name;
+};
+
+struct template {
+ const struct template *next;
+ const char *name;
+ const struct template_instance *instances;
+ const struct template_param *params;
+};
+
+static const 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-2018 Free Software Foundation, Inc.\n\
+/* Copyright (C) 2007-2020 Free Software Foundation, Inc.\n\
\n\
This file is part of the GNU opcodes library.\n\
\n\
static void set_bitfield (char *, bitfield *, int, unsigned int, int);
static int
-set_bitfield_from_shorthand (char *f, bitfield *array, unsigned int size,
- int lineno)
+set_bitfield_from_cpu_flag_init (char *f, bitfield *array, unsigned int size,
+ int lineno)
{
char *str, *next, *last;
unsigned int i;
return 0;
}
- for (i = 0; i < ARRAY_SIZE (operand_type_shorthands); i++)
- if (strcmp (operand_type_shorthands[i].name, f) == 0)
- {
- /* Turn on selective bits. */
- char *init = xstrdup (operand_type_shorthands[i].init);
- last = init + strlen (init);
- for (next = init; next && next < last; )
- {
- str = next_field (next, '|', &next, last);
- if (str)
- set_bitfield (str, array, 1, size, lineno);
- }
- free (init);
- return 0;
- }
-
return -1;
}
{
unsigned int i;
+ /* Ignore empty fields; they may result from template expansions. */
+ if (*f == '\0')
+ return;
+
if (strcmp (f, "CpuFP") == 0)
{
set_bitfield("Cpu387", array, value, size, lineno);
}
}
- /* Handle shorthands. */
- if (value == 1 && !set_bitfield_from_shorthand (f, array, size, lineno))
+ /* Handle CPU_XXX_FLAGS. */
+ if (value == 1 && !set_bitfield_from_cpu_flag_init (f, array, size, lineno))
return;
if (lineno != -1)
if (strcmp (mod, "0"))
{
+ unsigned int have_w = 0, bwlq_suf = 0xf;
+
last = mod + strlen (mod);
for (next = mod; next && next < last; )
{
lineno);
if (strcasecmp(str, "IsString") == 0)
active_isstring = 1;
+
+ if (strcasecmp(str, "W") == 0)
+ have_w = 1;
+
+ if (strcasecmp(str, "No_bSuf") == 0)
+ bwlq_suf &= ~1;
+ if (strcasecmp(str, "No_wSuf") == 0)
+ bwlq_suf &= ~2;
+ if (strcasecmp(str, "No_lSuf") == 0)
+ bwlq_suf &= ~4;
+ if (strcasecmp(str, "No_qSuf") == 0)
+ bwlq_suf &= ~8;
}
}
+
+ if (have_w && !bwlq_suf)
+ fail ("%s: %d: stray W modifier\n", filename, lineno);
+ if (have_w && !(bwlq_suf & 1))
+ fprintf (stderr, "%s: %d: W modifier without Byte operand(s)\n",
+ filename, lineno);
+ if (have_w && !(bwlq_suf & ~1))
+ fprintf (stderr,
+ "%s: %d: W modifier without Word/Dword/Qword operand(s)\n",
+ filename, lineno);
}
output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
}
};
static void
-output_operand_type (FILE *table, bitfield *types, unsigned int size,
+output_operand_type (FILE *table, enum operand_class class,
+ enum operand_instance instance,
+ const bitfield *types, unsigned int size,
enum stage stage, const char *indent)
{
unsigned int i;
- fprintf (table, "{ { ");
+ fprintf (table, "{ { %d, %d, ", class, instance);
for (i = 0; i < size - 1; i++)
{
- if (((i + 1) % 20) != 0)
+ if (((i + 3) % 20) != 0)
fprintf (table, "%d, ", types[i].value);
else
fprintf (table, "%d,", types[i].value);
- if (((i + 1) % 20) == 0)
+ if (((i + 3) % 20) == 0)
{
/* We need \\ for macro. */
if (stage == stage_macros)
const char *indent, int lineno)
{
char *str, *next, *last;
+ enum operand_class class = ClassNone;
+ enum operand_instance instance = InstanceNone;
bitfield types [ARRAY_SIZE (operand_types)];
/* Copy the default operand type. */
for (next = op; next && next < last; )
{
str = next_field (next, '|', &next, last);
+ if (str)
+ {
+ unsigned int i;
+
+ if (!strncmp(str, "Class=", 6))
+ {
+ for (i = 0; i < ARRAY_SIZE(operand_classes); ++i)
+ if (!strcmp(str + 6, operand_classes[i].name))
+ {
+ class = operand_classes[i].value;
+ str = NULL;
+ break;
+ }
+ }
+
+ if (str && !strncmp(str, "Instance=", 9))
+ {
+ for (i = 0; i < ARRAY_SIZE(operand_instances); ++i)
+ if (!strcmp(str + 9, operand_instances[i].name))
+ {
+ instance = operand_instances[i].value;
+ str = NULL;
+ break;
+ }
+ }
+ }
if (str)
{
set_bitfield (str, types, 1, ARRAY_SIZE (types), lineno);
if (!active_cpu_flags.bitfield.cpu64
&& !active_cpu_flags.bitfield.cpumpx)
set_bitfield("Disp16", types, 1, ARRAY_SIZE (types), lineno);
- set_bitfield("Disp32", 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);
}
}
- output_operand_type (table, types, ARRAY_SIZE (types), stage,
- indent);
+ output_operand_type (table, class, instance, types, ARRAY_SIZE (types),
+ stage, indent);
}
static void
}
fprintf (table, " { \"%s\", %s, %s, %s, %s,\n",
- name, operands, base_opcode, extension_opcode,
- opcode_length);
+ name, base_opcode, extension_opcode, opcode_length, operands);
process_i386_cpu_flag (table, cpu_flags, 0, ",", " ", lineno);
return strcmp (name, entry->name) == 0;
}
+static void
+parse_template (char *buf, int lineno)
+{
+ char sep, *end, *name;
+ struct template *tmpl = xmalloc (sizeof (*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);
+ *end++ = '\0';
+ remove_trailing_whitespaces (buf);
+
+ if (*buf == '\0')
+ fail ("%s: %d: missing template identifier\n", filename, lineno);
+ tmpl->name = xstrdup (buf);
+
+ tmpl->params = NULL;
+ do {
+ struct template_param *param;
+
+ buf = remove_leading_whitespaces (end);
+ end = strpbrk (buf, ":,");
+ if (end == NULL)
+ fail ("%s: %d: missing ':' or ','\n", filename, lineno);
+
+ sep = *end;
+ *end++ = '\0';
+ remove_trailing_whitespaces (buf);
+
+ param = xmalloc (sizeof (*param));
+ param->name = xstrdup (buf);
+ param->next = tmpl->params;
+ tmpl->params = param;
+ } while (sep == ':');
+
+ tmpl->instances = NULL;
+ do {
+ struct template_instance *inst;
+ char *cur, *next;
+ const struct template_param *param;
+
+ buf = remove_leading_whitespaces (end);
+ end = strpbrk (buf, ",>");
+ if (end == NULL)
+ fail ("%s: %d: missing ',' or '>'\n", filename, lineno);
+
+ sep = *end;
+ *end++ = '\0';
+
+ inst = xmalloc (sizeof (*inst));
+
+ cur = next_field (buf, ':', &next, end);
+ inst->name = xstrdup (cur);
+
+ for (param = tmpl->params; param; param = param->next)
+ {
+ struct template_arg *arg = xmalloc (sizeof (*arg));
+
+ cur = next_field (next, ':', &next, end);
+ if (next > end)
+ fail ("%s: %d: missing argument for '%s'\n", filename, lineno, param->name);
+ arg->val = xstrdup (cur);
+ arg->next = inst->args;
+ inst->args = arg;
+ }
+
+ if (tmpl->instances)
+ last_inst->next = inst;
+ else
+ tmpl->instances = inst;
+ last_inst = inst;
+ } while (sep == ',');
+
+ buf = remove_leading_whitespaces (end);
+ if (*buf)
+ fprintf(stderr, "%s: %d: excess characters '%s'\n",
+ filename, lineno, buf);
+
+ tmpl->next = templates;
+ templates = tmpl;
+}
+
+static unsigned int
+expand_templates (char *name, const char *str, htab_t opcode_hash_table,
+ struct opcode_hash_entry ***opcode_array_p, int lineno)
+{
+ static unsigned int idx, opcode_array_size;
+ struct opcode_hash_entry **opcode_array = *opcode_array_p;
+ struct opcode_hash_entry **hash_slot, **entry;
+ char *ptr1 = strchr(name, '<'), *ptr2;
+
+ if (ptr1 == NULL)
+ {
+ /* Get the slot in hash table. */
+ hash_slot = (struct opcode_hash_entry **)
+ htab_find_slot_with_hash (opcode_hash_table, name,
+ htab_hash_string (name),
+ INSERT);
+
+ if (*hash_slot == NULL)
+ {
+ /* It is the new one. Put it on opcode array. */
+ if (idx >= opcode_array_size)
+ {
+ /* Grow the opcode array when needed. */
+ opcode_array_size += 1024;
+ opcode_array = (struct opcode_hash_entry **)
+ xrealloc (opcode_array,
+ sizeof (*opcode_array) * opcode_array_size);
+ *opcode_array_p = opcode_array;
+ }
+
+ opcode_array[idx] = (struct opcode_hash_entry *)
+ xmalloc (sizeof (struct opcode_hash_entry));
+ opcode_array[idx]->next = NULL;
+ opcode_array[idx]->name = xstrdup (name);
+ opcode_array[idx]->opcode = xstrdup (str);
+ opcode_array[idx]->lineno = lineno;
+ *hash_slot = opcode_array[idx];
+ idx++;
+ }
+ else
+ {
+ /* Append it to the existing one. */
+ entry = hash_slot;
+ while ((*entry) != NULL)
+ entry = &(*entry)->next;
+ *entry = (struct opcode_hash_entry *)
+ xmalloc (sizeof (struct opcode_hash_entry));
+ (*entry)->next = NULL;
+ (*entry)->name = (*hash_slot)->name;
+ (*entry)->opcode = xstrdup (str);
+ (*entry)->lineno = lineno;
+ }
+ }
+ else if ((ptr2 = strchr(ptr1 + 1, '>')) == NULL)
+ fail ("%s: %d: missing '>'\n", filename, lineno);
+ else
+ {
+ const struct template *tmpl;
+ const struct template_instance *inst;
+
+ *ptr1 = '\0';
+ ptr1 = remove_leading_whitespaces (ptr1 + 1);
+ remove_trailing_whitespaces (ptr1);
+
+ *ptr2++ = '\0';
+
+ for ( tmpl = templates; tmpl; tmpl = tmpl->next )
+ if (!strcmp(ptr1, tmpl->name))
+ break;
+ if (!tmpl)
+ fail ("reference to unknown template '%s'\n", ptr1);
+
+ for (inst = tmpl->instances; inst; inst = inst->next)
+ {
+ char *name2 = xmalloc(strlen(name) + strlen(inst->name) + strlen(ptr2) + 1);
+ char *str2 = xmalloc(2 * strlen(str));
+ const char *src;
+
+ strcpy (name2, name);
+ strcat (name2, inst->name);
+ strcat (name2, ptr2);
+
+ for (ptr1 = str2, src = str; *src; )
+ {
+ const char *ident = tmpl->name, *end;
+ const struct template_param *param;
+ const struct template_arg *arg;
+
+ if ((*ptr1 = *src++) != '<')
+ {
+ ++ptr1;
+ continue;
+ }
+ while (ISSPACE(*src))
+ ++src;
+ while (*ident && *src == *ident)
+ ++src, ++ident;
+ while (ISSPACE(*src))
+ ++src;
+ if (*src != ':' || *ident != '\0')
+ {
+ memcpy (++ptr1, tmpl->name, ident - tmpl->name);
+ ptr1 += ident - tmpl->name;
+ continue;
+ }
+ while (ISSPACE(*++src))
+ ;
+
+ end = src;
+ while (*end != '\0' && !ISSPACE(*end) && *end != '>')
+ ++end;
+
+ for (param = tmpl->params, arg = inst->args; param;
+ param = param->next, arg = arg->next)
+ {
+ if (end - src == strlen (param->name)
+ && !memcmp (src, param->name, end - src))
+ {
+ src = end;
+ break;
+ }
+ }
+
+ if (param == NULL)
+ fail ("template '%s' has no parameter '%.*s'\n",
+ tmpl->name, (int)(end - src), src);
+
+ while (ISSPACE(*src))
+ ++src;
+ if (*src != '>')
+ fail ("%s: %d: missing '>'\n", filename, lineno);
+
+ memcpy(ptr1, arg->val, strlen(arg->val));
+ ptr1 += strlen(arg->val);
+ ++src;
+ }
+
+ *ptr1 = '\0';
+
+ expand_templates (name2, str2, opcode_hash_table, opcode_array_p,
+ lineno);
+
+ free (str2);
+ free (name2);
+ }
+ }
+
+ return idx;
+}
+
static void
process_i386_opcodes (FILE *table)
{
char buf[2048];
unsigned int i, j;
char *str, *p, *last, *name;
- struct opcode_hash_entry **hash_slot, **entry, *next;
htab_t opcode_hash_table;
- struct opcode_hash_entry **opcode_array;
- unsigned int opcode_array_size = 1024;
+ struct opcode_hash_entry **opcode_array = NULL;
int lineno = 0, marker = 0;
filename = "i386-opc.tbl";
fp = stdin;
i = 0;
- opcode_array = (struct opcode_hash_entry **)
- xmalloc (sizeof (*opcode_array) * opcode_array_size);
-
opcode_hash_table = htab_create_alloc (16, opcode_hash_hash,
opcode_hash_eq, NULL,
xcalloc, free);
case '\0':
continue;
break;
+ case '<':
+ parse_template (p, lineno);
+ continue;
default:
if (!marker)
continue;
/* Find name. */
name = next_field (p, ',', &str, last);
- /* Get the slot in hash table. */
- hash_slot = (struct opcode_hash_entry **)
- htab_find_slot_with_hash (opcode_hash_table, name,
- htab_hash_string (name),
- INSERT);
-
- if (*hash_slot == NULL)
- {
- /* It is the new one. Put it on opcode array. */
- if (i >= opcode_array_size)
- {
- /* Grow the opcode array when needed. */
- opcode_array_size += 1024;
- opcode_array = (struct opcode_hash_entry **)
- xrealloc (opcode_array,
- sizeof (*opcode_array) * opcode_array_size);
- }
-
- opcode_array[i] = (struct opcode_hash_entry *)
- xmalloc (sizeof (struct opcode_hash_entry));
- opcode_array[i]->next = NULL;
- opcode_array[i]->name = xstrdup (name);
- opcode_array[i]->opcode = xstrdup (str);
- opcode_array[i]->lineno = lineno;
- *hash_slot = opcode_array[i];
- i++;
- }
- else
- {
- /* Append it to the existing one. */
- entry = hash_slot;
- while ((*entry) != NULL)
- entry = &(*entry)->next;
- *entry = (struct opcode_hash_entry *)
- xmalloc (sizeof (struct opcode_hash_entry));
- (*entry)->next = NULL;
- (*entry)->name = (*hash_slot)->name;
- (*entry)->opcode = xstrdup (str);
- (*entry)->lineno = lineno;
- }
+ i = expand_templates (name, str, opcode_hash_table, &opcode_array,
+ lineno);
}
/* Process opcode array. */
for (j = 0; j < i; j++)
{
+ struct opcode_hash_entry *next;
+
for (next = opcode_array[j]; next; next = next->next)
{
name = next->name;
/* Check the unused bitfield in i386_cpu_flags. */
#ifdef CpuUnused
+ static_assert (ARRAY_SIZE (cpu_flags) == CpuMax + 2);
+
if ((cpumax - 1) != CpuMax)
fail (_("CpuMax != %d!\n"), cpumax);
#else
+ static_assert (ARRAY_SIZE (cpu_flags) == CpuMax + 1);
+
if (cpumax != CpuMax)
fail (_("CpuMax != %d!\n"), cpumax);
fail (_("%d unused bits in i386_cpu_flags.\n"), c);
#endif
+ static_assert (ARRAY_SIZE (opcode_modifiers) == Opcode_Modifier_Num);
+
/* Check the unused bitfield in i386_operand_type. */
-#ifndef OTUnused
- c = OTNumOfBits - OTMax - 1;
+#ifdef OTUnused
+ static_assert (ARRAY_SIZE (operand_types) + CLASS_WIDTH + INSTANCE_WIDTH
+ == OTNum + 1);
+#else
+ static_assert (ARRAY_SIZE (operand_types) + CLASS_WIDTH + INSTANCE_WIDTH
+ == OTNum);
+
+ c = OTNumOfBits - OTNum;
if (c)
fail (_("%d unused bits in i386_operand_type.\n"), c);
#endif