-/* Copyright (C) 2007-2020 Free Software Foundation, Inc.
+/* Copyright (C) 2007-2023 Free Software Foundation, Inc.
This file is part of the GNU opcodes library.
MA 02110-1301, USA. */
#include "sysdep.h"
+#include <stdbool.h>
#include <stdio.h>
#include <errno.h>
#include "getopt.h"
#include "i386-opc.h"
-#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;
-typedef struct initializer
+typedef struct dependency
{
const char *name;
- const char *init;
-} initializer;
+ /* Note: Only direct dependencies should be enumerated. */
+ const char *deps;
+} dependency;
-static initializer cpu_flag_init[] =
+static const dependency isa_dependencies[] =
{
- { "CPU_UNKNOWN_FLAGS",
- "~(CpuL1OM|CpuK1OM)" },
- { "CPU_GENERIC32_FLAGS",
- "Cpu186|Cpu286|Cpu386" },
- { "CPU_GENERIC64_FLAGS",
- "CPU_PENTIUMPRO_FLAGS|CpuClflush|CpuSYSCALL|CPU_MMX_FLAGS|CPU_SSE2_FLAGS|CpuLM" },
- { "CPU_NONE_FLAGS",
- "0" },
- { "CPU_I186_FLAGS",
- "Cpu186" },
- { "CPU_I286_FLAGS",
- "CPU_I186_FLAGS|Cpu286" },
- { "CPU_I386_FLAGS",
- "CPU_I286_FLAGS|Cpu386" },
- { "CPU_I486_FLAGS",
- "CPU_I386_FLAGS|Cpu486" },
- { "CPU_I586_FLAGS",
- "CPU_I486_FLAGS|Cpu387|Cpu586" },
- { "CPU_I686_FLAGS",
- "CPU_I586_FLAGS|Cpu686|Cpu687|CpuCMOV|CpuFXSR" },
- { "CPU_PENTIUMPRO_FLAGS",
- "CPU_I686_FLAGS|CpuNop" },
- { "CPU_P2_FLAGS",
- "CPU_PENTIUMPRO_FLAGS|CPU_MMX_FLAGS" },
- { "CPU_P3_FLAGS",
- "CPU_P2_FLAGS|CPU_SSE_FLAGS" },
- { "CPU_P4_FLAGS",
- "CPU_P3_FLAGS|CpuClflush|CPU_SSE2_FLAGS" },
- { "CPU_NOCONA_FLAGS",
- "CPU_GENERIC64_FLAGS|CpuFISTTP|CPU_SSE3_FLAGS|CpuCX16" },
- { "CPU_CORE_FLAGS",
- "CPU_P4_FLAGS|CpuFISTTP|CPU_SSE3_FLAGS|CpuCX16" },
- { "CPU_CORE2_FLAGS",
- "CPU_NOCONA_FLAGS|CPU_SSSE3_FLAGS" },
- { "CPU_COREI7_FLAGS",
- "CPU_CORE2_FLAGS|CPU_SSE4_2_FLAGS|CpuRdtscp" },
- { "CPU_K6_FLAGS",
- "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|CpuSYSCALL|Cpu387|CPU_MMX_FLAGS" },
- { "CPU_K6_2_FLAGS",
- "CPU_K6_FLAGS|Cpu3dnow" },
- { "CPU_ATHLON_FLAGS",
- "CPU_K6_2_FLAGS|Cpu686|Cpu687|CpuNop|Cpu3dnowA" },
- { "CPU_K8_FLAGS",
- "CPU_ATHLON_FLAGS|CpuRdtscp|CPU_SSE2_FLAGS|CpuLM" },
- { "CPU_AMDFAM10_FLAGS",
- "CPU_K8_FLAGS|CpuFISTTP|CPU_SSE4A_FLAGS|CpuABM" },
- { "CPU_BDVER1_FLAGS",
- "CPU_GENERIC64_FLAGS|CpuFISTTP|CpuRdtscp|CpuCX16|CPU_XOP_FLAGS|CpuABM|CpuLWP|CpuSVME|CpuAES|CpuPCLMUL|CpuLZCNT|CpuPRFCHW" },
- { "CPU_BDVER2_FLAGS",
- "CPU_BDVER1_FLAGS|CpuFMA|CpuBMI|CpuTBM|CpuF16C" },
- { "CPU_BDVER3_FLAGS",
- "CPU_BDVER2_FLAGS|CpuXsaveopt|CpuFSGSBase" },
- { "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_ZNVER2_FLAGS",
- "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_BTVER2_FLAGS",
- "CPU_BTVER1_FLAGS|CPU_AVX_FLAGS|CpuBMI|CpuF16C|CpuAES|CpuPCLMUL|CpuMovbe|CpuXsaveopt|CpuPRFCHW" },
- { "CPU_8087_FLAGS",
- "Cpu8087" },
- { "CPU_287_FLAGS",
- "Cpu287" },
- { "CPU_387_FLAGS",
- "Cpu387" },
- { "CPU_687_FLAGS",
- "CPU_387_FLAGS|Cpu687" },
- { "CPU_CMOV_FLAGS",
- "CpuCMOV" },
- { "CPU_FXSR_FLAGS",
- "CpuFXSR" },
- { "CPU_CLFLUSH_FLAGS",
- "CpuClflush" },
- { "CPU_NOP_FLAGS",
- "CpuNop" },
- { "CPU_SYSCALL_FLAGS",
- "CpuSYSCALL" },
- { "CPU_MMX_FLAGS",
- "CpuMMX" },
- { "CPU_SSE_FLAGS",
- "CpuSSE" },
- { "CPU_SSE2_FLAGS",
- "CPU_SSE_FLAGS|CpuSSE2" },
- { "CPU_SSE3_FLAGS",
- "CPU_SSE2_FLAGS|CpuSSE3" },
- { "CPU_SSSE3_FLAGS",
- "CPU_SSE3_FLAGS|CpuSSSE3" },
- { "CPU_SSE4_1_FLAGS",
- "CPU_SSSE3_FLAGS|CpuSSE4_1" },
- { "CPU_SSE4_2_FLAGS",
- "CPU_SSE4_1_FLAGS|CpuSSE4_2" },
- { "CPU_VMX_FLAGS",
- "CpuVMX" },
- { "CPU_SMX_FLAGS",
- "CpuSMX" },
- { "CPU_XSAVE_FLAGS",
- "CpuXsave" },
- { "CPU_XSAVEOPT_FLAGS",
- "CPU_XSAVE_FLAGS|CpuXsaveopt" },
- { "CPU_AES_FLAGS",
- "CPU_SSE2_FLAGS|CpuAES" },
- { "CPU_PCLMUL_FLAGS",
- "CPU_SSE2_FLAGS|CpuPCLMUL" },
- { "CPU_FMA_FLAGS",
- "CPU_AVX_FLAGS|CpuFMA" },
- { "CPU_FMA4_FLAGS",
- "CPU_AVX_FLAGS|CpuFMA4" },
- { "CPU_XOP_FLAGS",
- "CPU_SSE4A_FLAGS|CPU_FMA4_FLAGS|CpuXOP" },
- { "CPU_LWP_FLAGS",
- "CPU_XSAVE_FLAGS|CpuLWP" },
- { "CPU_BMI_FLAGS",
- "CpuBMI" },
- { "CPU_TBM_FLAGS",
- "CpuTBM" },
- { "CPU_MOVBE_FLAGS",
- "CpuMovbe" },
- { "CPU_CX16_FLAGS",
- "CpuCX16" },
- { "CPU_RDTSCP_FLAGS",
- "CpuRdtscp" },
- { "CPU_EPT_FLAGS",
- "CpuEPT" },
- { "CPU_FSGSBASE_FLAGS",
- "CpuFSGSBase" },
- { "CPU_RDRND_FLAGS",
- "CpuRdRnd" },
- { "CPU_F16C_FLAGS",
- "CPU_AVX_FLAGS|CpuF16C" },
- { "CPU_BMI2_FLAGS",
- "CpuBMI2" },
- { "CPU_LZCNT_FLAGS",
- "CpuLZCNT" },
- { "CPU_HLE_FLAGS",
- "CpuHLE" },
- { "CPU_RTM_FLAGS",
- "CpuRTM" },
- { "CPU_INVPCID_FLAGS",
- "CpuINVPCID" },
- { "CPU_VMFUNC_FLAGS",
- "CpuVMFUNC" },
- { "CPU_3DNOW_FLAGS",
- "CPU_MMX_FLAGS|Cpu3dnow" },
- { "CPU_3DNOWA_FLAGS",
- "CPU_3DNOW_FLAGS|Cpu3dnowA" },
- { "CPU_PADLOCK_FLAGS",
- "CpuPadLock" },
- { "CPU_SVME_FLAGS",
- "CpuSVME" },
- { "CPU_SSE4A_FLAGS",
- "CPU_SSE3_FLAGS|CpuSSE4a" },
- { "CPU_ABM_FLAGS",
- "CpuABM" },
- { "CPU_AVX_FLAGS",
- "CPU_SSE4_2_FLAGS|CPU_XSAVE_FLAGS|CpuAVX" },
- { "CPU_AVX2_FLAGS",
- "CPU_AVX_FLAGS|CpuAVX2" },
- { "CPU_AVX512F_FLAGS",
- "CPU_AVX2_FLAGS|CpuAVX512F" },
- { "CPU_AVX512CD_FLAGS",
- "CPU_AVX512F_FLAGS|CpuAVX512CD" },
- { "CPU_AVX512ER_FLAGS",
- "CPU_AVX512F_FLAGS|CpuAVX512ER" },
- { "CPU_AVX512PF_FLAGS",
- "CPU_AVX512F_FLAGS|CpuAVX512PF" },
- { "CPU_AVX512DQ_FLAGS",
- "CPU_AVX512F_FLAGS|CpuAVX512DQ" },
- { "CPU_AVX512BW_FLAGS",
- "CPU_AVX512F_FLAGS|CpuAVX512BW" },
- { "CPU_AVX512VL_FLAGS",
- "CPU_AVX512F_FLAGS|CpuAVX512VL" },
- { "CPU_AVX512IFMA_FLAGS",
- "CPU_AVX512F_FLAGS|CpuAVX512IFMA" },
- { "CPU_AVX512VBMI_FLAGS",
- "CPU_AVX512F_FLAGS|CpuAVX512VBMI" },
- { "CPU_AVX512_4FMAPS_FLAGS",
- "CPU_AVX512F_FLAGS|CpuAVX512_4FMAPS" },
- { "CPU_AVX512_4VNNIW_FLAGS",
- "CPU_AVX512F_FLAGS|CpuAVX512_4VNNIW" },
- { "CPU_AVX512_VPOPCNTDQ_FLAGS",
- "CPU_AVX512F_FLAGS|CpuAVX512_VPOPCNTDQ" },
- { "CPU_AVX512_VBMI2_FLAGS",
- "CPU_AVX512F_FLAGS|CpuAVX512_VBMI2" },
- { "CPU_AVX512_VNNI_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",
- "unknown" },
- { "CPU_IAMCU_FLAGS",
- "Cpu186|Cpu286|Cpu386|Cpu486|Cpu586" },
- { "CPU_ADX_FLAGS",
- "CpuADX" },
- { "CPU_RDSEED_FLAGS",
- "CpuRdSeed" },
- { "CPU_PRFCHW_FLAGS",
- "CpuPRFCHW" },
- { "CPU_SMAP_FLAGS",
- "CpuSMAP" },
- { "CPU_MPX_FLAGS",
- "CPU_XSAVE_FLAGS|CpuMPX" },
- { "CPU_SHA_FLAGS",
- "CPU_SSE2_FLAGS|CpuSHA" },
- { "CPU_CLFLUSHOPT_FLAGS",
- "CpuClflushOpt" },
- { "CPU_XSAVES_FLAGS",
- "CPU_XSAVE_FLAGS|CpuXSAVES" },
- { "CPU_XSAVEC_FLAGS",
- "CPU_XSAVE_FLAGS|CpuXSAVEC" },
- { "CPU_PREFETCHWT1_FLAGS",
- "CpuPREFETCHWT1" },
- { "CPU_SE1_FLAGS",
- "CpuSE1" },
- { "CPU_CLWB_FLAGS",
- "CpuCLWB" },
- { "CPU_CLZERO_FLAGS",
- "CpuCLZERO" },
- { "CPU_MWAITX_FLAGS",
- "CpuMWAITX" },
- { "CPU_OSPKE_FLAGS",
- "CPU_XSAVE_FLAGS|CpuOSPKE" },
- { "CPU_RDPID_FLAGS",
- "CpuRDPID" },
- { "CPU_PTWRITE_FLAGS",
- "CpuPTWRITE" },
- { "CPU_IBT_FLAGS",
- "CpuIBT" },
- { "CPU_SHSTK_FLAGS",
- "CpuSHSTK" },
- { "CPU_GFNI_FLAGS",
- "CpuGFNI" },
- { "CPU_VAES_FLAGS",
- "CpuVAES" },
- { "CPU_VPCLMULQDQ_FLAGS",
- "CpuVPCLMULQDQ" },
- { "CPU_WBNOINVD_FLAGS",
- "CpuWBNOINVD" },
- { "CPU_PCONFIG_FLAGS",
- "CpuPCONFIG" },
- { "CPU_WAITPKG_FLAGS",
- "CpuWAITPKG" },
- { "CPU_CLDEMOTE_FLAGS",
- "CpuCLDEMOTE" },
- { "CPU_MOVDIRI_FLAGS",
- "CpuMOVDIRI" },
- { "CPU_MOVDIR64B_FLAGS",
- "CpuMOVDIR64B" },
- { "CPU_ENQCMD_FLAGS",
- "CpuENQCMD" },
- { "CPU_AVX512_VP2INTERSECT_FLAGS",
- "CpuAVX512_VP2INTERSECT" },
- { "CPU_RDPRU_FLAGS",
- "CpuRDPRU" },
- { "CPU_MCOMMIT_FLAGS",
- "CpuMCOMMIT" },
- { "CPU_ANY_X87_FLAGS",
- "CPU_ANY_287_FLAGS|Cpu8087" },
- { "CPU_ANY_287_FLAGS",
- "CPU_ANY_387_FLAGS|Cpu287" },
- { "CPU_ANY_387_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" },
- { "CPU_ANY_SSE2_FLAGS",
- "CPU_ANY_SSE3_FLAGS|CpuSSE2" },
- { "CPU_ANY_SSE3_FLAGS",
- "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",
- "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" },
- { "CPU_ANY_AVX512CD_FLAGS",
- "CpuAVX512CD" },
- { "CPU_ANY_AVX512ER_FLAGS",
- "CpuAVX512ER" },
- { "CPU_ANY_AVX512PF_FLAGS",
- "CpuAVX512PF" },
- { "CPU_ANY_AVX512DQ_FLAGS",
- "CpuAVX512DQ" },
- { "CPU_ANY_AVX512BW_FLAGS",
- "CpuAVX512BW" },
- { "CPU_ANY_AVX512VL_FLAGS",
- "CpuAVX512VL" },
- { "CPU_ANY_AVX512IFMA_FLAGS",
- "CpuAVX512IFMA" },
- { "CPU_ANY_AVX512VBMI_FLAGS",
- "CpuAVX512VBMI" },
- { "CPU_ANY_AVX512_4FMAPS_FLAGS",
- "CpuAVX512_4FMAPS" },
- { "CPU_ANY_AVX512_4VNNIW_FLAGS",
- "CpuAVX512_4VNNIW" },
- { "CPU_ANY_AVX512_VPOPCNTDQ_FLAGS",
- "CpuAVX512_VPOPCNTDQ" },
- { "CPU_ANY_IBT_FLAGS",
- "CpuIBT" },
- { "CPU_ANY_SHSTK_FLAGS",
- "CpuSHSTK" },
- { "CPU_ANY_AVX512_VBMI2_FLAGS",
- "CpuAVX512_VBMI2" },
- { "CPU_ANY_AVX512_VNNI_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" },
- { "CPU_ANY_ENQCMD_FLAGS",
- "CpuENQCMD" },
- { "CPU_ANY_AVX512_VP2INTERSECT_FLAGS",
- "CpuAVX512_VP2INTERSECT" },
-};
-
-static initializer operand_type_init[] =
-{
- { "OPERAND_TYPE_NONE",
+ { "UNKNOWN",
+ "~IAMCU" },
+ { "GENERIC32",
+ "386" },
+ { "GENERIC64",
+ "PENTIUMPRO|Clflush|SYSCALL|MMX|SSE2|LM" },
+ { "NONE",
"0" },
- { "OPERAND_TYPE_REG8",
- "Class=Reg|Byte" },
- { "OPERAND_TYPE_REG16",
- "Class=Reg|Word" },
- { "OPERAND_TYPE_REG32",
- "Class=Reg|Dword" },
- { "OPERAND_TYPE_REG64",
- "Class=Reg|Qword" },
- { "OPERAND_TYPE_IMM1",
- "Imm1" },
- { "OPERAND_TYPE_IMM8",
- "Imm8" },
- { "OPERAND_TYPE_IMM8S",
- "Imm8S" },
- { "OPERAND_TYPE_IMM16",
- "Imm16" },
- { "OPERAND_TYPE_IMM32",
- "Imm32" },
- { "OPERAND_TYPE_IMM32S",
- "Imm32S" },
- { "OPERAND_TYPE_IMM64",
- "Imm64" },
- { "OPERAND_TYPE_BASEINDEX",
- "BaseIndex" },
- { "OPERAND_TYPE_DISP8",
- "Disp8" },
- { "OPERAND_TYPE_DISP16",
- "Disp16" },
- { "OPERAND_TYPE_DISP32",
- "Disp32" },
- { "OPERAND_TYPE_DISP32S",
- "Disp32S" },
- { "OPERAND_TYPE_DISP64",
- "Disp64" },
- { "OPERAND_TYPE_INOUTPORTREG",
- "Instance=RegD|Word" },
- { "OPERAND_TYPE_SHIFTCOUNT",
- "Instance=RegC|Byte" },
- { "OPERAND_TYPE_CONTROL",
- "Class=RegCR" },
- { "OPERAND_TYPE_TEST",
- "Class=RegTR" },
- { "OPERAND_TYPE_DEBUG",
- "Class=RegDR" },
- { "OPERAND_TYPE_FLOATREG",
- "Class=Reg|Tbyte" },
- { "OPERAND_TYPE_FLOATACC",
- "Instance=Accum|Tbyte" },
- { "OPERAND_TYPE_SREG",
- "Class=SReg" },
- { "OPERAND_TYPE_REGMMX",
- "Class=RegMMX" },
- { "OPERAND_TYPE_REGXMM",
- "Class=RegSIMD|Xmmword" },
- { "OPERAND_TYPE_REGYMM",
- "Class=RegSIMD|Ymmword" },
- { "OPERAND_TYPE_REGZMM",
- "Class=RegSIMD|Zmmword" },
- { "OPERAND_TYPE_REGMASK",
- "Class=RegMask" },
- { "OPERAND_TYPE_REGBND",
- "Class=RegBND" },
- { "OPERAND_TYPE_ACC8",
- "Instance=Accum|Byte" },
- { "OPERAND_TYPE_ACC16",
- "Instance=Accum|Word" },
- { "OPERAND_TYPE_ACC32",
- "Instance=Accum|Dword" },
- { "OPERAND_TYPE_ACC64",
- "Instance=Accum|Qword" },
- { "OPERAND_TYPE_DISP16_32",
- "Disp16|Disp32" },
- { "OPERAND_TYPE_ANYDISP",
- "Disp8|Disp16|Disp32|Disp32S|Disp64" },
- { "OPERAND_TYPE_IMM16_32",
- "Imm16|Imm32" },
- { "OPERAND_TYPE_IMM16_32S",
- "Imm16|Imm32S" },
- { "OPERAND_TYPE_IMM16_32_32S",
- "Imm16|Imm32|Imm32S" },
- { "OPERAND_TYPE_IMM32_64",
- "Imm32|Imm64" },
- { "OPERAND_TYPE_IMM32_32S_DISP32",
- "Imm32|Imm32S|Disp32" },
- { "OPERAND_TYPE_IMM64_DISP64",
- "Imm64|Disp64" },
- { "OPERAND_TYPE_IMM32_32S_64_DISP32",
- "Imm32|Imm32S|Imm64|Disp32" },
- { "OPERAND_TYPE_IMM32_32S_64_DISP32_64",
- "Imm32|Imm32S|Imm64|Disp32|Disp64" },
- { "OPERAND_TYPE_ANYIMM",
- "Imm1|Imm8|Imm8S|Imm16|Imm32|Imm32S|Imm64" },
+ { "PENTIUMPRO",
+ "686|Nop" },
+ { "P2",
+ "PENTIUMPRO|MMX" },
+ { "P3",
+ "P2|SSE" },
+ { "P4",
+ "P3|Clflush|SSE2" },
+ { "NOCONA",
+ "GENERIC64|FISTTP|SSE3|MONITOR|CX16" },
+ { "CORE",
+ "P4|FISTTP|SSE3|MONITOR|CX16" },
+ { "CORE2",
+ "NOCONA|SSSE3" },
+ { "COREI7",
+ "CORE2|SSE4_2|Rdtscp|LAHF_SAHF" },
+ { "K6",
+ "186|286|386|486|586|SYSCALL|387|MMX" },
+ { "K6_2",
+ "K6|3dnow" },
+ { "ATHLON",
+ "K6_2|686:min|687|Nop|3dnowA" },
+ { "K8",
+ "ATHLON|Rdtscp|SSE2|LM" },
+ { "AMDFAM10",
+ "K8|FISTTP|SSE4A|ABM|MONITOR" },
+ { "BDVER1",
+ "GENERIC64|FISTTP|Rdtscp|MONITOR|CX16|LAHF_SAHF|XOP|ABM|LWP|SVME|AES|PCLMUL|PRFCHW" },
+ { "BDVER2",
+ "BDVER1|FMA|BMI|TBM|F16C" },
+ { "BDVER3",
+ "BDVER2|Xsaveopt|FSGSBase" },
+ { "BDVER4",
+ "BDVER3|AVX2|Movbe|BMI2|RdRnd|MWAITX" },
+ { "ZNVER1",
+ "GENERIC64|FISTTP|Rdtscp|MONITOR|CX16|LAHF_SAHF|AVX2|SSE4A|ABM|SVME|AES|PCLMUL|PRFCHW|FMA|BMI|F16C|Xsaveopt|FSGSBase|Movbe|BMI2|RdRnd|ADX|RdSeed|SMAP|SHA|XSAVEC|XSAVES|ClflushOpt|CLZERO|MWAITX" },
+ { "ZNVER2",
+ "ZNVER1|CLWB|RDPID|RDPRU|MCOMMIT|WBNOINVD" },
+ { "ZNVER3",
+ "ZNVER2|INVLPGB|TLBSYNC|VAES|VPCLMULQDQ|INVPCID|SNP|OSPKE" },
+ { "ZNVER4",
+ "ZNVER3|AVX512F|AVX512DQ|AVX512IFMA|AVX512CD|AVX512BW|AVX512VL|AVX512_BF16|AVX512VBMI|AVX512_VBMI2|AVX512_VNNI|AVX512_BITALG|AVX512_VPOPCNTDQ|GFNI|RMPQUERY" },
+ { "BTVER1",
+ "GENERIC64|FISTTP|MONITOR|CX16|LAHF_SAHF|Rdtscp|SSSE3|SSE4A|ABM|PRFCHW|Clflush|FISTTP|SVME" },
+ { "BTVER2",
+ "BTVER1|AVX|BMI|F16C|AES|PCLMUL|Movbe|Xsaveopt|PRFCHW" },
+ { "286",
+ "186" },
+ { "386",
+ "286" },
+ { "486",
+ "386" },
+ { "586",
+ "486|387" },
+ { "586:nofpu",
+ "486" },
+ { "686",
+ "586|687|CMOV|FXSR" },
+ { "686:min",
+ "586|687" },
+ { "687",
+ "387" },
+ { "FISTTP",
+ "687" },
+ { "SSE",
+ "FXSR" },
+ { "SSE2",
+ "SSE" },
+ { "SSE3",
+ "SSE2" },
+ { "SSSE3",
+ "SSE3" },
+ { "SSE4_1",
+ "SSSE3" },
+ { "SSE4_2",
+ "SSE4_1|POPCNT" },
+ { "Xsaveopt",
+ "XSAVE" },
+ { "AES",
+ "SSE2" },
+ { "PCLMUL",
+ "SSE2" },
+ { "FMA",
+ "AVX" },
+ { "FMA4",
+ "AVX" },
+ { "XOP",
+ "SSE4A|FMA4" },
+ { "LWP",
+ "XSAVE" },
+ { "F16C",
+ "AVX" },
+ { "3dnow",
+ "MMX" },
+ { "3dnowA",
+ "3dnow" },
+ { "SSE4a",
+ "SSE3" },
+ { "ABM",
+ "LZCNT|POPCNT" },
+ { "AVX",
+ "SSE4_2|XSAVE" },
+ { "AVX2",
+ "AVX" },
+ { "AVX_VNNI",
+ "AVX2" },
+ { "AVX_IFMA",
+ "AVX2" },
+ { "AVX_VNNI_INT8",
+ "AVX2" },
+ { "AVX_NE_CONVERT",
+ "AVX2" },
+ { "FRED",
+ "LKGS" },
+ { "AVX512F",
+ "AVX2" },
+ { "AVX512CD",
+ "AVX512F" },
+ { "AVX512ER",
+ "AVX512F" },
+ { "AVX512PF",
+ "AVX512F" },
+ { "AVX512DQ",
+ "AVX512F" },
+ { "AVX512BW",
+ "AVX512F" },
+ { "AVX512VL",
+ "AVX512F" },
+ { "AVX512IFMA",
+ "AVX512F" },
+ { "AVX512VBMI",
+ "AVX512BW" },
+ { "AVX512_4FMAPS",
+ "AVX512F" },
+ { "AVX512_4VNNIW",
+ "AVX512F" },
+ { "AVX512_VPOPCNTDQ",
+ "AVX512F" },
+ { "AVX512_VBMI2",
+ "AVX512BW" },
+ { "AVX512_VNNI",
+ "AVX512F" },
+ { "AVX512_BITALG",
+ "AVX512BW" },
+ { "AVX512_VP2INTERSECT",
+ "AVX512F" },
+ { "AVX512_BF16",
+ "AVX512BW" },
+ { "AVX512_FP16",
+ "AVX512BW" },
+ { "IAMCU",
+ "586:nofpu" },
+ { "EPT",
+ "VMX" },
+ { "VMFUNC",
+ "VMX" },
+ { "MPX",
+ "XSAVE" },
+ { "SHA",
+ "SSE2" },
+ { "XSAVES",
+ "XSAVEC" },
+ { "XSAVEC",
+ "XSAVE" },
+ { "OSPKE",
+ "XSAVE" },
+ { "GFNI",
+ "SSE2" },
+ { "VAES",
+ "AVX2" },
+ { "VPCLMULQDQ",
+ "AVX2" },
+ { "SEV_ES",
+ "SVME" },
+ { "SNP",
+ "SEV_ES" },
+ { "RMPQUERY",
+ "SNP" },
+ { "TSX",
+ "RTM|HLE" },
+ { "TSXLDTRK",
+ "RTM" },
+ { "AMX_TILE",
+ "XSAVE" },
+ { "AMX_INT8",
+ "AMX_TILE" },
+ { "AMX_BF16",
+ "AMX_TILE" },
+ { "AMX_FP16",
+ "AMX_TILE" },
+ { "AMX_COMPLEX",
+ "AMX_TILE" },
+ { "KL",
+ "SSE2" },
+ { "WIDEKL",
+ "KL" },
};
+/* This array is populated as process_i386_initializers() walks cpu_flags[]. */
+static unsigned char isa_reverse_deps[Cpu64][Cpu64];
+
typedef struct bitfield
{
int position;
const char *name;
} bitfield;
-#define BITFIELD(n) { n, 0, #n }
+#define BITFIELD(n) { Cpu##n, 0, #n }
static bitfield cpu_flags[] =
{
- BITFIELD (Cpu186),
- BITFIELD (Cpu286),
- BITFIELD (Cpu386),
- BITFIELD (Cpu486),
- BITFIELD (Cpu586),
- BITFIELD (Cpu686),
- BITFIELD (CpuCMOV),
- BITFIELD (CpuFXSR),
- BITFIELD (CpuClflush),
- BITFIELD (CpuNop),
- BITFIELD (CpuSYSCALL),
- BITFIELD (Cpu8087),
- BITFIELD (Cpu287),
- BITFIELD (Cpu387),
- BITFIELD (Cpu687),
- BITFIELD (CpuFISTTP),
- BITFIELD (CpuMMX),
- BITFIELD (CpuSSE),
- BITFIELD (CpuSSE2),
- BITFIELD (CpuSSE3),
- BITFIELD (CpuSSSE3),
- BITFIELD (CpuSSE4_1),
- BITFIELD (CpuSSE4_2),
- BITFIELD (CpuAVX),
- BITFIELD (CpuAVX2),
- BITFIELD (CpuAVX512F),
- BITFIELD (CpuAVX512CD),
- BITFIELD (CpuAVX512ER),
- BITFIELD (CpuAVX512PF),
- BITFIELD (CpuAVX512VL),
- BITFIELD (CpuAVX512DQ),
- BITFIELD (CpuAVX512BW),
- BITFIELD (CpuL1OM),
- BITFIELD (CpuK1OM),
- BITFIELD (CpuIAMCU),
- BITFIELD (CpuSSE4a),
- BITFIELD (Cpu3dnow),
- BITFIELD (Cpu3dnowA),
- BITFIELD (CpuPadLock),
- BITFIELD (CpuSVME),
- BITFIELD (CpuVMX),
- BITFIELD (CpuSMX),
- BITFIELD (CpuABM),
- BITFIELD (CpuXsave),
- BITFIELD (CpuXsaveopt),
- BITFIELD (CpuAES),
- BITFIELD (CpuPCLMUL),
- BITFIELD (CpuFMA),
- BITFIELD (CpuFMA4),
- BITFIELD (CpuXOP),
- BITFIELD (CpuLWP),
- BITFIELD (CpuBMI),
- BITFIELD (CpuTBM),
- BITFIELD (CpuLM),
- BITFIELD (CpuMovbe),
- BITFIELD (CpuCX16),
- BITFIELD (CpuEPT),
- BITFIELD (CpuRdtscp),
- BITFIELD (CpuFSGSBase),
- BITFIELD (CpuRdRnd),
- BITFIELD (CpuF16C),
- BITFIELD (CpuBMI2),
- BITFIELD (CpuLZCNT),
- BITFIELD (CpuHLE),
- BITFIELD (CpuRTM),
- BITFIELD (CpuINVPCID),
- BITFIELD (CpuVMFUNC),
- BITFIELD (CpuRDSEED),
- BITFIELD (CpuADX),
- BITFIELD (CpuPRFCHW),
- BITFIELD (CpuSMAP),
- BITFIELD (CpuSHA),
- BITFIELD (CpuClflushOpt),
- BITFIELD (CpuXSAVES),
- BITFIELD (CpuXSAVEC),
- BITFIELD (CpuPREFETCHWT1),
- BITFIELD (CpuSE1),
- BITFIELD (CpuCLWB),
- BITFIELD (Cpu64),
- BITFIELD (CpuNo64),
- BITFIELD (CpuMPX),
- BITFIELD (CpuAVX512IFMA),
- BITFIELD (CpuAVX512VBMI),
- BITFIELD (CpuAVX512_4FMAPS),
- BITFIELD (CpuAVX512_4VNNIW),
- BITFIELD (CpuAVX512_VPOPCNTDQ),
- BITFIELD (CpuAVX512_VBMI2),
- BITFIELD (CpuAVX512_VNNI),
- BITFIELD (CpuAVX512_BITALG),
- BITFIELD (CpuAVX512_BF16),
- BITFIELD (CpuAVX512_VP2INTERSECT),
- BITFIELD (CpuMWAITX),
- BITFIELD (CpuCLZERO),
- BITFIELD (CpuOSPKE),
- BITFIELD (CpuRDPID),
- BITFIELD (CpuPTWRITE),
- BITFIELD (CpuIBT),
- BITFIELD (CpuSHSTK),
- BITFIELD (CpuGFNI),
- BITFIELD (CpuVAES),
- BITFIELD (CpuVPCLMULQDQ),
- BITFIELD (CpuWBNOINVD),
- BITFIELD (CpuPCONFIG),
- BITFIELD (CpuWAITPKG),
- BITFIELD (CpuCLDEMOTE),
- BITFIELD (CpuMOVDIRI),
- BITFIELD (CpuMOVDIR64B),
- BITFIELD (CpuENQCMD),
- BITFIELD (CpuRDPRU),
- BITFIELD (CpuMCOMMIT),
+ BITFIELD (186),
+ BITFIELD (286),
+ BITFIELD (386),
+ BITFIELD (486),
+ BITFIELD (586),
+ BITFIELD (686),
+ BITFIELD (CMOV),
+ BITFIELD (FXSR),
+ BITFIELD (Clflush),
+ BITFIELD (Nop),
+ BITFIELD (SYSCALL),
+ BITFIELD (8087),
+ BITFIELD (287),
+ BITFIELD (387),
+ BITFIELD (687),
+ BITFIELD (FISTTP),
+ BITFIELD (MMX),
+ BITFIELD (SSE),
+ BITFIELD (SSE2),
+ BITFIELD (SSE3),
+ BITFIELD (SSSE3),
+ BITFIELD (SSE4_1),
+ BITFIELD (SSE4_2),
+ BITFIELD (AVX),
+ BITFIELD (AVX2),
+ BITFIELD (AVX512F),
+ BITFIELD (AVX512CD),
+ BITFIELD (AVX512ER),
+ BITFIELD (AVX512PF),
+ BITFIELD (AVX512VL),
+ BITFIELD (AVX512DQ),
+ BITFIELD (AVX512BW),
+ BITFIELD (IAMCU),
+ BITFIELD (SSE4a),
+ BITFIELD (3dnow),
+ BITFIELD (3dnowA),
+ BITFIELD (PadLock),
+ BITFIELD (SVME),
+ BITFIELD (VMX),
+ BITFIELD (SMX),
+ BITFIELD (Xsave),
+ BITFIELD (Xsaveopt),
+ BITFIELD (AES),
+ BITFIELD (PCLMUL),
+ BITFIELD (FMA),
+ BITFIELD (FMA4),
+ BITFIELD (XOP),
+ BITFIELD (LWP),
+ BITFIELD (BMI),
+ BITFIELD (TBM),
+ BITFIELD (LM),
+ BITFIELD (Movbe),
+ BITFIELD (CX16),
+ BITFIELD (LAHF_SAHF),
+ BITFIELD (EPT),
+ BITFIELD (Rdtscp),
+ BITFIELD (FSGSBase),
+ BITFIELD (RdRnd),
+ BITFIELD (F16C),
+ BITFIELD (BMI2),
+ BITFIELD (LZCNT),
+ BITFIELD (POPCNT),
+ BITFIELD (MONITOR),
+ BITFIELD (HLE),
+ BITFIELD (RTM),
+ BITFIELD (INVPCID),
+ BITFIELD (VMFUNC),
+ BITFIELD (RDSEED),
+ BITFIELD (ADX),
+ BITFIELD (PRFCHW),
+ BITFIELD (SMAP),
+ BITFIELD (SHA),
+ BITFIELD (ClflushOpt),
+ BITFIELD (XSAVES),
+ BITFIELD (XSAVEC),
+ BITFIELD (PREFETCHWT1),
+ BITFIELD (SE1),
+ BITFIELD (CLWB),
+ BITFIELD (MPX),
+ BITFIELD (AVX512IFMA),
+ BITFIELD (AVX512VBMI),
+ BITFIELD (AVX512_4FMAPS),
+ BITFIELD (AVX512_4VNNIW),
+ BITFIELD (AVX512_VPOPCNTDQ),
+ BITFIELD (AVX512_VBMI2),
+ BITFIELD (AVX512_VNNI),
+ BITFIELD (AVX512_BITALG),
+ BITFIELD (AVX512_BF16),
+ BITFIELD (AVX512_VP2INTERSECT),
+ BITFIELD (TDX),
+ BITFIELD (AVX_VNNI),
+ BITFIELD (AVX512_FP16),
+ BITFIELD (PREFETCHI),
+ BITFIELD (AVX_IFMA),
+ BITFIELD (AVX_VNNI_INT8),
+ BITFIELD (CMPCCXADD),
+ BITFIELD (WRMSRNS),
+ BITFIELD (MSRLIST),
+ BITFIELD (AVX_NE_CONVERT),
+ BITFIELD (RAO_INT),
+ BITFIELD (FRED),
+ BITFIELD (LKGS),
+ BITFIELD (MWAITX),
+ BITFIELD (CLZERO),
+ BITFIELD (OSPKE),
+ BITFIELD (RDPID),
+ BITFIELD (PTWRITE),
+ BITFIELD (IBT),
+ BITFIELD (SHSTK),
+ BITFIELD (GFNI),
+ BITFIELD (VAES),
+ BITFIELD (VPCLMULQDQ),
+ BITFIELD (WBNOINVD),
+ BITFIELD (PCONFIG),
+ BITFIELD (WAITPKG),
+ BITFIELD (UINTR),
+ BITFIELD (CLDEMOTE),
+ BITFIELD (AMX_INT8),
+ BITFIELD (AMX_BF16),
+ BITFIELD (AMX_FP16),
+ BITFIELD (AMX_COMPLEX),
+ BITFIELD (AMX_TILE),
+ BITFIELD (MOVDIRI),
+ BITFIELD (MOVDIR64B),
+ BITFIELD (ENQCMD),
+ BITFIELD (SERIALIZE),
+ BITFIELD (RDPRU),
+ BITFIELD (MCOMMIT),
+ BITFIELD (SEV_ES),
+ BITFIELD (TSXLDTRK),
+ BITFIELD (KL),
+ BITFIELD (WideKL),
+ BITFIELD (HRESET),
+ BITFIELD (INVLPGB),
+ BITFIELD (TLBSYNC),
+ BITFIELD (SNP),
+ BITFIELD (RMPQUERY),
+ BITFIELD (64),
+ BITFIELD (No64),
#ifdef CpuUnused
- BITFIELD (CpuUnused),
+ BITFIELD (Unused),
#endif
};
+#undef BITFIELD
+#define BITFIELD(n) { n, 0, #n }
+
static bitfield opcode_modifiers[] =
{
BITFIELD (D),
BITFIELD (Modrm),
BITFIELD (Jump),
BITFIELD (FloatMF),
- BITFIELD (FloatR),
BITFIELD (Size),
- BITFIELD (CheckRegSize),
- BITFIELD (IgnoreSize),
- BITFIELD (DefaultSize),
- BITFIELD (Anysize),
+ BITFIELD (CheckOperandSize),
+ BITFIELD (OperandConstraint),
+ BITFIELD (MnemonicSize),
BITFIELD (No_bSuf),
BITFIELD (No_wSuf),
BITFIELD (No_lSuf),
BITFIELD (No_sSuf),
BITFIELD (No_qSuf),
- BITFIELD (No_ldSuf),
BITFIELD (FWait),
BITFIELD (IsString),
BITFIELD (RegMem),
BITFIELD (BNDPrefixOk),
- BITFIELD (NoTrackPrefixOk),
- BITFIELD (IsLockable),
- BITFIELD (RegKludge),
- BITFIELD (Implicit1stXmm0),
- BITFIELD (RepPrefixOk),
- BITFIELD (HLEPrefixOk),
- BITFIELD (ToDword),
- BITFIELD (ToQword),
- BITFIELD (AddrPrefixOpReg),
+ BITFIELD (PrefixOk),
BITFIELD (IsPrefix),
BITFIELD (ImmExt),
BITFIELD (NoRex64),
- BITFIELD (Rex64),
- BITFIELD (Ugh),
BITFIELD (Vex),
BITFIELD (VexVVVV),
BITFIELD (VexW),
- BITFIELD (VexOpcode),
- BITFIELD (VexSources),
- BITFIELD (VecSIB),
+ BITFIELD (OpcodePrefix),
+ BITFIELD (SIB),
BITFIELD (SSE2AVX),
- BITFIELD (NoAVX),
BITFIELD (EVex),
BITFIELD (Masking),
BITFIELD (Broadcast),
BITFIELD (StaticRounding),
BITFIELD (SAE),
BITFIELD (Disp8MemShift),
- BITFIELD (NoDefMask),
- BITFIELD (ImplicitQuadGroup),
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),
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 {
+ struct template *next;
+ const char *name;
+ const struct template_instance *instances;
+ const struct template_param *params;
+};
+
+static struct template *templates;
+
static int
compare (const void *x, const void *y)
{
va_list args;
va_start (args, message);
- fprintf (stderr, _("%s: error: "), program_name);
+ fprintf (stderr, "%s: error: ", program_name);
vfprintf (stderr, message, args);
va_end (args);
xexit (1);
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-2023 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_cpu_flag_init (char *f, bitfield *array, unsigned int size,
- int lineno)
-{
- char *str, *next, *last;
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
- if (strcmp (cpu_flag_init[i].name, f) == 0)
- {
- /* Turn on selective bits. */
- char *init = xstrdup (cpu_flag_init[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;
-}
-
static void
set_bitfield (char *f, bitfield *array, int value,
unsigned int size, int lineno)
{
unsigned int i;
- 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";
+ /* Ignore empty fields; they may result from template expansions. */
+ if (*f == '\0')
+ return;
for (i = 0; i < size; i++)
if (strcasecmp (array[i].name, f) == 0)
}
}
- /* Handle CPU_XXX_FLAGS. */
- if (value == 1 && !set_bitfield_from_cpu_flag_init (f, array, size, lineno))
- return;
-
if (lineno != -1)
- fail (_("%s: %d: unknown bitfield: %s\n"), filename, lineno, f);
+ fail ("%s: %d: unknown bitfield: %s\n", filename, lineno, f);
else
- fail (_("unknown bitfield: %s\n"), f);
+ fail ("unknown bitfield: %s\n", f);
+}
+
+static void
+add_isa_dependencies (bitfield *flags, const char *f, int value,
+ unsigned int reverse)
+{
+ unsigned int i;
+ char *str = NULL;
+ const char *isa = f;
+ bool is_isa = false, is_avx = false;
+
+ /* Need to find base entry for references to auxiliary ones. */
+ if (strchr (f, ':'))
+ {
+ str = xstrdup (f);
+ *strchr (str, ':') = '\0';
+ isa = str;
+ }
+ for (i = 0; i < Cpu64; ++i)
+ if (strcasecmp (flags[i].name, isa) == 0)
+ {
+ flags[i].value = value;
+ if (reverse < ARRAY_SIZE (isa_reverse_deps[0])
+ /* Don't record the feature itself here. */
+ && reverse != i
+ /* Don't record base architectures. */
+ && reverse > Cpu686)
+ isa_reverse_deps[i][reverse] = 1;
+ is_isa = true;
+ if (i == CpuAVX || i == CpuXOP)
+ is_avx = true;
+ break;
+ }
+ free (str);
+
+ /* Do not turn off dependencies. */
+ if (is_isa && !value)
+ return;
+
+ for (i = 0; i < ARRAY_SIZE (isa_dependencies); ++i)
+ if (strcasecmp (isa_dependencies[i].name, f) == 0)
+ {
+ char *deps = xstrdup (isa_dependencies[i].deps);
+ char *next = deps;
+ char *last = deps + strlen (deps);
+
+ for (; next && next < last; )
+ {
+ char *str = next_field (next, '|', &next, last);
+
+ /* No AVX/XOP -> SSE reverse dependencies. */
+ if (is_avx && strncmp (str, "SSE", 3) == 0)
+ add_isa_dependencies (flags, str, value, CpuMax);
+ else
+ add_isa_dependencies (flags, str, value, reverse);
+ }
+ free (deps);
+
+ /* ISA extensions with dependencies need CPU_ANY_*_FLAGS emitted. */
+ if (reverse < ARRAY_SIZE (isa_reverse_deps[0]))
+ isa_reverse_deps[reverse][reverse] = 1;
+
+ return;
+ }
+
+ if (!is_isa)
+ fail ("unknown bitfield: %s\n", f);
}
static void
}
static void
-process_i386_cpu_flag (FILE *table, char *flag, int macro,
+process_i386_cpu_flag (FILE *table, char *flag,
+ const char *name,
const char *comma, const char *indent,
- int lineno)
+ int lineno, unsigned int reverse)
{
- char *str, *next, *last;
+ char *str, *next = flag, *last;
unsigned int i;
+ int value = 1;
+ bool is_isa = false;
bitfield flags [ARRAY_SIZE (cpu_flags)];
/* Copy the default cpu flags. */
memcpy (flags, cpu_flags, sizeof (cpu_flags));
- if (strcasecmp (flag, "unknown") == 0)
+ if (flag == NULL)
{
- /* 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;
+ for (i = 0; i < ARRAY_SIZE (isa_reverse_deps[0]); ++i)
+ flags[i].value = isa_reverse_deps[reverse][i];
+ goto output;
}
- else if (flag[0] == '~')
+
+ if (flag[0] == '~')
{
last = flag + strlen (flag);
last -= 1;
next = flag + 2;
if (*last != ')')
- fail (_("%s: %d: missing `)' in bitfield: %s\n"), filename,
+ fail ("%s: %d: missing `)' in bitfield: %s\n", filename,
lineno, flag);
*last = '\0';
}
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. */
+ value = 0;
+ }
+
+ if (name != NULL && value != 0)
+ {
+ for (i = 0; i < ARRAY_SIZE (flags); i++)
+ if (strcasecmp (flags[i].name, name) == 0)
+ {
+ add_isa_dependencies (flags, name, 1, reverse);
+ is_isa = true;
+ break;
+ }
+ }
+
+ if (strcmp (flag, "0"))
+ {
+ if (is_isa)
+ return;
+
+ /* Turn on/off selective bits. */
+ last = flag + strlen (flag);
for (; next && next < last; )
{
str = next_field (next, '|', &next, last);
- if (str)
- set_bitfield (str, flags, 0, ARRAY_SIZE (flags), lineno);
+ if (name == NULL)
+ set_bitfield (str, flags, value, ARRAY_SIZE (flags), lineno);
+ else
+ add_isa_dependencies (flags, str, value, reverse);
}
}
- else if (strcmp (flag, "0"))
+
+ output:
+ if (name != NULL)
{
- /* Turn on selective bits. */
- last = flag + strlen (flag);
- for (next = flag; next && next < last; )
+ size_t len = strlen (name);
+ char *upper = xmalloc (len + 1);
+
+ for (i = 0; i < len; ++i)
{
- str = next_field (next, '|', &next, last);
- if (str)
- set_bitfield (str, flags, 1, ARRAY_SIZE (flags), lineno);
+ /* Don't emit #define-s for auxiliary entries. */
+ if (name[i] == ':')
+ return;
+ upper[i] = TOUPPER (name[i]);
}
+ upper[i] = '\0';
+ fprintf (table, "\n#define CPU_%s%s_FLAGS \\\n",
+ flag != NULL ? "": "ANY_", upper);
+ free (upper);
}
- output_cpu_flags (table, flags, ARRAY_SIZE (flags), macro,
+ output_cpu_flags (table, flags, ARRAY_SIZE (flags), name != NULL,
comma, indent);
}
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, const char *extension_opcode,
+ char **opnd, int lineno)
{
char *str, *next, *last;
bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
+ static const char *const spaces[] = {
+#define SPACE(n) [SPACE_##n] = #n
+ SPACE(BASE),
+ SPACE(0F),
+ SPACE(0F38),
+ SPACE(0F3A),
+ SPACE(EVEXMAP5),
+ SPACE(EVEXMAP6),
+ SPACE(XOP08),
+ SPACE(XOP09),
+ SPACE(XOP0A),
+#undef SPACE
+ };
active_isstring = 0;
if (str)
{
int val = 1;
+
+ if (strncmp(str, "OpcodeSpace", 11) == 0)
+ {
+ char *end;
+
+ if (str[11] != '=')
+ fail ("%s:%d: Missing value for `OpcodeSpace'\n",
+ filename, lineno);
+
+ val = strtol (str + 12, &end, 0);
+ if (*end)
+ fail ("%s:%d: Bogus value `%s' for `OpcodeSpace'\n",
+ filename, lineno, end);
+
+ if (space)
+ {
+ if (val != space)
+ fail ("%s:%d: Conflicting opcode space specifications\n",
+ filename, lineno);
+ fprintf (stderr,
+ "%s:%d: Warning: redundant opcode space specification\n",
+ filename, lineno);
+ }
+
+ space = val;
+ continue;
+ }
+
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 (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))
"%s: %d: W modifier without Word/Dword/Qword operand(s)\n",
filename, lineno);
}
+
+ if (space >= ARRAY_SIZE (spaces) || !spaces[space])
+ fail ("%s:%d: Unknown opcode space %u\n", filename, lineno, space);
+
+ fprintf (table, " SPACE_%s, %s,\n",
+ spaces[space], extension_opcode ? extension_opcode : "None");
+
output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
}
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),
stage, indent);
}
+static char *mkident (const char *mnem)
+{
+ char *ident = xstrdup (mnem), *p = ident;
+
+ do
+ {
+ if (!ISALNUM (*p))
+ *p = '_';
+ }
+ while (*++p);
+
+ return ident;
+}
+
static void
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, *ident;
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 extension_opcode, if any. */
+ extension_opcode = strchr (base_opcode, '/');
+ if (extension_opcode)
+ *extension_opcode++ = '\0';
/* 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);
+
+ ident = mkident (name);
+ fprintf (table, " { MN_%s, 0x%0*llx%s, %u,",
+ ident, 2 * (int)length, opcode, end, i);
+ free (ident);
- process_i386_cpu_flag (table, cpu_flags, 0, ",", " ", lineno);
+ process_i386_opcode_modifier (table, opcode_modifier, space, prefix,
+ extension_opcode, operand_types, lineno);
- process_i386_opcode_modifier (table, opcode_modifier, operand_types, lineno);
+ process_i386_cpu_flag (table, cpu_flags, NULL, ",", " ", lineno, CpuMax);
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 ",
struct opcode_hash_entry
{
- struct opcode_hash_entry *next;
- char *name;
- char *opcode;
- int lineno;
+ const char *name;
+ struct opcode_entry
+ {
+ struct opcode_entry *next;
+ char *opcode;
+ int lineno;
+ } entry;
};
/* Calculate the hash value of an opcode hash entry P. */
return strcmp (name, entry->name) == 0;
}
+static void
+parse_template (char *buf, int lineno)
+{
+ char sep, *end, *name;
+ struct template *tmpl;
+ struct template_instance *last_inst = NULL;
+
+ buf = remove_leading_whitespaces (buf + 1);
+ end = strchr (buf, ':');
+ if (end == NULL)
+ {
+ 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;
+ 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));
+ inst->next = NULL;
+ inst->args = NULL;
+
+ cur = next_field (buf, ':', &next, end);
+ inst->name = *cur != '$' ? 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;
+ struct opcode_entry *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]->name = xstrdup (name);
+ *hash_slot = opcode_array[idx];
+ entry = &opcode_array[idx]->entry;
+ idx++;
+ }
+ else
+ {
+ /* Append it to the existing one. */
+ struct opcode_entry **entryp = &(*hash_slot)->entry.next;
+
+ while (*entryp != NULL)
+ entryp = &(*entryp)->next;
+ entry = (struct opcode_entry *)xmalloc (sizeof (struct opcode_entry));
+ *entryp = entry;
+ }
+
+ entry->next = NULL;
+ 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 int mnemonic_cmp(const void *p1, const void *p2)
+{
+ const struct opcode_hash_entry *const *e1 = p1, *const *e2 = p2;
+ const char *s1 = (*e1)->name, *s2 = (*e2)->name;
+ unsigned int i;
+ size_t l1 = strlen (s1), l2 = strlen (s2);
+
+ for (i = 1; i <= l1 && i <= l2; ++i)
+ {
+ if (s1[l1 - i] != s2[l2 - i])
+ return (unsigned char)s1[l1 - i] - (unsigned char)s2[l2 - i];
+ }
+
+ return (int)(l1 - l2);
+}
+
static void
process_i386_opcodes (FILE *table)
{
FILE *fp;
char buf[2048];
- unsigned int i, j;
- char *str, *p, *last, *name;
- struct opcode_hash_entry **hash_slot, **entry, *next;
+ unsigned int i, j, nr, offs;
+ size_t l;
+ char *str, *p, *last;
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);
+ fprintf (table, "\n#include \"i386-mnem.h\"\n");
fprintf (table, "\n/* i386 opcode table. */\n\n");
- fprintf (table, "const insn_template i386_optab[] =\n{\n");
+ fprintf (table, "static const insn_template i386_optab[] =\n{\n");
/* Put everything on opcode array. */
while (!feof (fp))
{
+ char *name;
+
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])
{
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++)
{
- for (next = opcode_array[j]; next; next = next->next)
+ const char *name = opcode_array[j]->name;
+ struct opcode_entry *next;
+
+ for (next = &opcode_array[j]->entry; next; next = next->next)
{
- name = next->name;
str = next->opcode;
lineno = next->lineno;
last = str + strlen (str);
fclose (fp);
- fprintf (table, " { NULL, 0, 0, 0, 0,\n");
+ fprintf (table, "};\n");
- process_i386_cpu_flag (table, "0", 0, ",", " ", -1);
+ /* Generate opcode sets array. */
+ fprintf (table, "\n/* i386 opcode sets table. */\n\n");
+ fprintf (table, "static const insn_template *const i386_op_sets[] =\n{\n");
+ fprintf (table, " i386_optab,\n");
- process_i386_opcode_modifier (table, "0", NULL, -1);
+ for (nr = j = 0; j < i; j++)
+ {
+ struct opcode_entry *next = &opcode_array[j]->entry;
- fprintf (table, " { ");
- process_i386_operand_type (table, "0", stage_opcodes, "\t ", -1);
- fprintf (table, " } }\n");
+ do
+ {
+ ++nr;
+ next = next->next;
+ }
+ while (next);
+ fprintf (table, " i386_optab + %u,\n", nr);
+ }
fprintf (table, "};\n");
+
+ /* Emit mnemonics and associated #define-s. */
+ qsort (opcode_array, i, sizeof (*opcode_array), mnemonic_cmp);
+
+ fp = fopen ("i386-mnem.h", "w");
+ if (fp == NULL)
+ fail ("can't create i386-mnem.h, errno = %s\n",
+ xstrerror (errno));
+
+ process_copyright (fp);
+
+ fprintf (table, "\n/* i386 mnemonics table. */\n\n");
+ fprintf (table, "const char i386_mnemonics[] =\n");
+ fprintf (fp, "\nextern const char i386_mnemonics[];\n\n");
+
+ str = NULL;
+ for (l = strlen (opcode_array[offs = j = 0]->name); j < i; j++)
+ {
+ const char *name = opcode_array[j]->name;
+ const char *next = NULL;
+ size_t l1 = j + 1 < i ? strlen(next = opcode_array[j + 1]->name) : 0;
+
+ if (str == NULL)
+ str = mkident (name);
+ if (l < l1 && !strcmp(name, next + l1 - l))
+ {
+ fprintf (fp, "#define MN_%s ", str);
+ free (str);
+ str = mkident (next);
+ fprintf (fp, "(MN_%s + %u)\n", str, l1 - l);
+ }
+ else
+ {
+ fprintf (table, " \"\\0\"\"%s\"\n", name);
+ fprintf (fp, "#define MN_%s %#x\n", str, offs + 1);
+ offs += strlen (name) + 1;
+ free (str);
+ str = NULL;
+ }
+ l = l1;
+ }
+
+ fprintf (table, " \"\\0\"\".insn\"\n");
+ fprintf (fp, "#define MN__insn %#x\n", offs + 1);
+
+ fprintf (table, ";\n");
+
+ fclose (fp);
}
static void
filename = "i386-reg.tbl";
fp = fopen (filename, "r");
if (fp == NULL)
- fail (_("can't find i386-reg.tbl for reading, errno = %s\n"),
+ fail ("can't find i386-reg.tbl for reading, errno = %s\n",
xstrerror (errno));
fprintf (table, "\n/* i386 register table. */\n\n");
- fprintf (table, "const reg_entry i386_regtab[] =\n{\n");
+ fprintf (table, "static const reg_entry i386_regtab[] =\n{\n");
while (!feof (fp))
{
fprintf (table, "};\n");
- fprintf (table, "\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
+ fprintf (table, "\nstatic const unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
}
static void
{
unsigned int i;
FILE *fp = fopen ("i386-init.h", "w");
- char *init;
if (fp == NULL)
- fail (_("can't create i386-init.h, errno = %s\n"),
+ fail ("can't create i386-init.h, errno = %s\n",
xstrerror (errno));
process_copyright (fp);
- for (i = 0; i < ARRAY_SIZE (cpu_flag_init); i++)
+ for (i = 0; i < Cpu64; i++)
+ process_i386_cpu_flag (fp, "0", cpu_flags[i].name, "", " ", -1, i);
+
+ for (i = 0; i < ARRAY_SIZE (isa_dependencies); i++)
{
- fprintf (fp, "\n#define %s \\\n", cpu_flag_init[i].name);
- init = xstrdup (cpu_flag_init[i].init);
- process_i386_cpu_flag (fp, init, 1, "", " ", -1);
- free (init);
+ char *deps = xstrdup (isa_dependencies[i].deps);
+
+ process_i386_cpu_flag (fp, deps, isa_dependencies[i].name,
+ "", " ", -1, CpuMax);
+ free (deps);
}
- for (i = 0; i < ARRAY_SIZE (operand_type_init); i++)
+ /* Early x87 is somewhat special: Both 287 and 387 not only add new insns
+ but also remove some. Hence 8087 isn't a prereq to 287, and 287 isn't
+ one to 387. We want the reverse to be true though: Disabling 8087 also
+ is to disable 287+ and later; disabling 287 also means disabling 387+. */
+ memcpy (isa_reverse_deps[Cpu287], isa_reverse_deps[Cpu387],
+ sizeof (isa_reverse_deps[0]));
+ isa_reverse_deps[Cpu287][Cpu387] = 1;
+ memcpy (isa_reverse_deps[Cpu8087], isa_reverse_deps[Cpu287],
+ sizeof (isa_reverse_deps[0]));
+ isa_reverse_deps[Cpu8087][Cpu287] = 1;
+
+ /* While we treat POPCNT as a prereq to SSE4.2, its disabling should not
+ lead to disabling of anything else. */
+ memset (isa_reverse_deps[CpuPOPCNT], 0, sizeof (isa_reverse_deps[0]));
+
+ for (i = Cpu686 + 1; i < ARRAY_SIZE (isa_reverse_deps); i++)
{
- fprintf (fp, "\n\n#define %s \\\n ", operand_type_init[i].name);
- init = xstrdup (operand_type_init[i].init);
- process_i386_operand_type (fp, init, stage_macros, " ", -1);
- free (init);
+ size_t len;
+ char *upper;
+
+ if (memchr(isa_reverse_deps[i], 1,
+ ARRAY_SIZE (isa_reverse_deps[0])) == NULL)
+ continue;
+
+ isa_reverse_deps[i][i] = 1;
+ process_i386_cpu_flag (fp, NULL, cpu_flags[i].name, "", " ", -1, i);
}
+
fprintf (fp, "\n");
fclose (fp);
if (srcdir != NULL)
if (chdir (srcdir) != 0)
- fail (_("unable to change directory to \"%s\", errno = %s\n"),
+ fail ("unable to change directory to \"%s\", errno = %s\n",
srcdir, xstrerror (errno));
/* cpu_flags isn't sorted by position. */
static_assert (ARRAY_SIZE (cpu_flags) == CpuMax + 2);
if ((cpumax - 1) != CpuMax)
- fail (_("CpuMax != %d!\n"), cpumax);
+ fail ("CpuMax != %d!\n", cpumax);
#else
static_assert (ARRAY_SIZE (cpu_flags) == CpuMax + 1);
if (cpumax != CpuMax)
- fail (_("CpuMax != %d!\n"), cpumax);
+ fail ("CpuMax != %d!\n", cpumax);
c = CpuNumOfBits - CpuMax - 1;
if (c)
- fail (_("%d unused bits in i386_cpu_flags.\n"), c);
+ fail ("%d unused bits in i386_cpu_flags.\n", c);
#endif
static_assert (ARRAY_SIZE (opcode_modifiers) == Opcode_Modifier_Num);
c = OTNumOfBits - OTNum;
if (c)
- fail (_("%d unused bits in i386_operand_type.\n"), c);
+ fail ("%d unused bits in i386_operand_type.\n", c);
#endif
qsort (cpu_flags, ARRAY_SIZE (cpu_flags), sizeof (cpu_flags [0]),
table = fopen ("i386-tbl.h", "w");
if (table == NULL)
- fail (_("can't create i386-tbl.h, errno = %s\n"),
+ fail ("can't create i386-tbl.h, errno = %s\n",
xstrerror (errno));
process_copyright (table);