X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=opcodes%2Fi386-gen.c;h=6e33fc56df2287ca97213b0979741b40688138c6;hb=e409955ddcc33743044f217a3cc0541e0e6211b7;hp=28212cd28fdc3fd07aea1a7ecdc567d872f6edc4;hpb=75e5731b8f10129ef9a0e4202152c391d70375eb;p=deliverable%2Fbinutils-gdb.git diff --git a/opcodes/i386-gen.c b/opcodes/i386-gen.c index 28212cd28f..6e33fc56df 100644 --- a/opcodes/i386-gen.c +++ b/opcodes/i386-gen.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2019 Free Software Foundation, Inc. +/* Copyright (C) 2007-2020 Free Software Foundation, Inc. This file is part of the GNU opcodes library. @@ -90,9 +90,9 @@ static initializer cpu_flag_init[] = { "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", @@ -100,11 +100,11 @@ static initializer cpu_flag_init[] = { "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|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", @@ -138,7 +138,7 @@ static initializer cpu_flag_init[] = { "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", @@ -181,6 +181,8 @@ static initializer cpu_flag_init[] = "CpuBMI2" }, { "CPU_LZCNT_FLAGS", "CpuLZCNT" }, + { "CPU_POPCNT_FLAGS", + "CpuPOPCNT" }, { "CPU_HLE_FLAGS", "CpuHLE" }, { "CPU_RTM_FLAGS", @@ -200,7 +202,7 @@ static initializer cpu_flag_init[] = { "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", @@ -301,12 +303,18 @@ static initializer cpu_flag_init[] = "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", @@ -322,17 +330,19 @@ static initializer cpu_flag_init[] = { "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", @@ -379,8 +389,12 @@ static initializer cpu_flag_init[] = "CpuMOVDIR64B" }, { "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[] = @@ -437,8 +451,6 @@ static initializer operand_type_init[] = "Instance=Accum|Tbyte" }, { "OPERAND_TYPE_SREG", "Class=SReg" }, - { "OPERAND_TYPE_JUMPABSOLUTE", - "JumpAbsolute" }, { "OPERAND_TYPE_REGMMX", "Class=RegMMX" }, { "OPERAND_TYPE_REGXMM", @@ -451,8 +463,6 @@ static initializer operand_type_init[] = "Class=RegMask" }, { "OPERAND_TYPE_REGBND", "Class=RegBND" }, - { "OPERAND_TYPE_ESSEG", - "EsSeg" }, { "OPERAND_TYPE_ACC8", "Instance=Accum|Byte" }, { "OPERAND_TYPE_ACC16", @@ -538,7 +548,6 @@ static bitfield cpu_flags[] = BITFIELD (CpuSVME), BITFIELD (CpuVMX), BITFIELD (CpuSMX), - BITFIELD (CpuABM), BITFIELD (CpuXsave), BITFIELD (CpuXsaveopt), BITFIELD (CpuAES), @@ -559,6 +568,7 @@ static bitfield cpu_flags[] = BITFIELD (CpuF16C), BITFIELD (CpuBMI2), BITFIELD (CpuLZCNT), + BITFIELD (CpuPOPCNT), BITFIELD (CpuHLE), BITFIELD (CpuRTM), BITFIELD (CpuINVPCID), @@ -604,8 +614,11 @@ static bitfield cpu_flags[] = BITFIELD (CpuMOVDIRI), BITFIELD (CpuMOVDIR64B), BITFIELD (CpuENQCMD), + BITFIELD (CpuSERIALIZE), BITFIELD (CpuRDPRU), BITFIELD (CpuMCOMMIT), + BITFIELD (CpuSEV_ES), + BITFIELD (CpuTSXLDTRK), #ifdef CpuUnused BITFIELD (CpuUnused), #endif @@ -617,17 +630,13 @@ static bitfield opcode_modifiers[] = BITFIELD (W), BITFIELD (Load), BITFIELD (Modrm), - BITFIELD (ShortForm), BITFIELD (Jump), - BITFIELD (JumpDword), - BITFIELD (JumpByte), - BITFIELD (JumpInterSegment), BITFIELD (FloatMF), BITFIELD (FloatR), BITFIELD (Size), BITFIELD (CheckRegSize), - BITFIELD (IgnoreSize), - BITFIELD (DefaultSize), + BITFIELD (MnemonicSize), + BITFIELD (Anysize), BITFIELD (No_bSuf), BITFIELD (No_wSuf), BITFIELD (No_lSuf), @@ -650,7 +659,6 @@ static bitfield opcode_modifiers[] = BITFIELD (IsPrefix), BITFIELD (ImmExt), BITFIELD (NoRex64), - BITFIELD (Rex64), BITFIELD (Ugh), BITFIELD (Vex), BITFIELD (VexVVVV), @@ -672,8 +680,7 @@ static bitfield opcode_modifiers[] = BITFIELD (ATTMnemonic), BITFIELD (ATTSyntax), BITFIELD (IntelSyntax), - BITFIELD (AMD64), - BITFIELD (Intel64), + BITFIELD (ISA64), }; #define CLASS(n) #n, n @@ -704,6 +711,7 @@ static const struct { INSTANCE (Accum), INSTANCE (RegC), INSTANCE (RegD), + INSTANCE (RegB), }; #undef INSTANCE @@ -723,8 +731,6 @@ static bitfield operand_types[] = BITFIELD (Disp32), BITFIELD (Disp32S), BITFIELD (Disp64), - BITFIELD (JumpAbsolute), - BITFIELD (EsSeg), BITFIELD (Byte), BITFIELD (Word), BITFIELD (Dword), @@ -735,7 +741,6 @@ static bitfield operand_types[] = BITFIELD (Ymmword), BITFIELD (Zmmword), BITFIELD (Unspecified), - BITFIELD (Anysize), #ifdef OTUnused BITFIELD (OTUnused), #endif @@ -745,6 +750,31 @@ static const char *filename; 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) { @@ -769,7 +799,7 @@ static void process_copyright (FILE *fp) { fprintf (fp, "/* This file is automatically generated by i386-gen. Do not edit! */\n\ -/* Copyright (C) 2007-2019 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\ @@ -876,6 +906,10 @@ set_bitfield (char *f, bitfield *array, int value, { 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); @@ -1244,7 +1278,8 @@ process_i386_operand_type (FILE *table, char *op, enum stage stage, 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); } @@ -1377,6 +1412,240 @@ opcode_hash_eq (const void *p, const void *q) 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) { @@ -1384,19 +1653,14 @@ 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); @@ -1448,6 +1712,9 @@ process_i386_opcodes (FILE *table) case '\0': continue; break; + case '<': + parse_template (p, lineno); + continue; default: if (!marker) continue; @@ -1459,51 +1726,15 @@ process_i386_opcodes (FILE *table) /* 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; @@ -1746,7 +1977,7 @@ main (int argc, char **argv) static_assert (ARRAY_SIZE (operand_types) + CLASS_WIDTH + INSTANCE_WIDTH == OTNum); - c = OTNumOfBits - OTMax - 1; + c = OTNumOfBits - OTNum; if (c) fail (_("%d unused bits in i386_operand_type.\n"), c); #endif