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