BFD error message suppression test case
[binutils-gdb.git] / opcodes / i386-gen.c
index 1fe59e6cc14cee9203e64b4b7145314e68257f14..92ee3592929e7167bb89619b4cc25858cff4aaba 100644 (file)
@@ -475,8 +475,6 @@ static initializer operand_type_init[] =
     "Disp16" },
   { "OPERAND_TYPE_DISP32",
     "Disp32" },
-  { "OPERAND_TYPE_DISP32S",
-    "Disp32S" },
   { "OPERAND_TYPE_DISP64",
     "Disp64" },
   { "OPERAND_TYPE_INOUTPORTREG",
@@ -520,7 +518,7 @@ static initializer operand_type_init[] =
   { "OPERAND_TYPE_DISP16_32",
     "Disp16|Disp32" },
   { "OPERAND_TYPE_ANYDISP",
-    "Disp8|Disp16|Disp32|Disp32S|Disp64" },
+    "Disp8|Disp16|Disp32|Disp64" },
   { "OPERAND_TYPE_IMM16_32",
     "Imm16|Imm32" },
   { "OPERAND_TYPE_IMM16_32S",
@@ -529,14 +527,14 @@ static initializer operand_type_init[] =
     "Imm16|Imm32|Imm32S" },
   { "OPERAND_TYPE_IMM32_64",
     "Imm32|Imm64" },
-  { "OPERAND_TYPE_IMM32_32S_DISP32S",
-    "Imm32|Imm32S|Disp32S" },
+  { "OPERAND_TYPE_IMM32_32S_DISP32",
+    "Imm32|Imm32S|Disp32" },
   { "OPERAND_TYPE_IMM64_DISP64",
     "Imm64|Disp64" },
-  { "OPERAND_TYPE_IMM32_32S_64_DISP32S",
-    "Imm32|Imm32S|Imm64|Disp32S" },
-  { "OPERAND_TYPE_IMM32_32S_64_DISP32S_64",
-    "Imm32|Imm32S|Imm64|Disp32S|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" },
 };
@@ -786,7 +784,6 @@ static bitfield operand_types[] =
   BITFIELD (Disp8),
   BITFIELD (Disp16),
   BITFIELD (Disp32),
-  BITFIELD (Disp32S),
   BITFIELD (Disp64),
   BITFIELD (Byte),
   BITFIELD (Word),
@@ -825,13 +822,13 @@ struct template_param {
 };
 
 struct template {
-  const struct template *next;
+  struct template *next;
   const char *name;
   const struct template_instance *instances;
   const struct template_param *params;
 };
 
-static const struct template *templates;
+static struct template *templates;
 
 static int
 compare (const void *x, const void *y)
@@ -1114,18 +1111,21 @@ output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size)
   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; )
     {
@@ -1134,34 +1134,34 @@ adjust_broadcast_modifier (char **opnd)
        {
          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
@@ -1188,7 +1188,9 @@ process_i386_opcode_modifier (FILE *table, char *mod, unsigned int space,
            {
              int val = 1;
              if (strcasecmp(str, "Broadcast") == 0)
-               val = adjust_broadcast_modifier (opnd);
+               val = get_element_size (opnd, lineno) + BYTE_BROADCAST;
+             else if (strcasecmp(str, "Disp8MemShift") == 0)
+               val = get_element_size (opnd, lineno);
 
              set_bitfield (str, modifiers, val, ARRAY_SIZE (modifiers),
                            lineno);
@@ -1343,10 +1345,7 @@ 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);
-         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),
@@ -1450,8 +1449,8 @@ output_i386_opcode (FILE *table, const char *name, char *str,
     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);
+  fprintf (table, "  { \"%s\", 0x%0*llx%s, %lu, %s,\n",
+          name, 2 * (int)length, opcode, end, i, extension_opcode);
 
   process_i386_opcode_modifier (table, opcode_modifier, space, prefix,
                                operand_types, lineno);
@@ -1510,18 +1509,40 @@ static void
 parse_template (char *buf, int lineno)
 {
   char sep, *end, *name;
-  struct template *tmpl = xmalloc (sizeof (*tmpl));
+  struct template *tmpl;
   struct template_instance *last_inst = NULL;
 
   buf = remove_leading_whitespaces (buf + 1);
   end = strchr (buf, ':');
   if (end == NULL)
-    fail ("%s: %d: missing ':'\n", filename, lineno);
+    {
+      struct template *prev = NULL;
+
+      end = strchr (buf, '>');
+      if (end == NULL)
+       fail ("%s: %d: missing ':' or '>'\n", filename, lineno);
+      if (*remove_leading_whitespaces (end + 1))
+       fail ("%s: %d: malformed template purge\n", filename, lineno);
+      *end = '\0';
+      remove_trailing_whitespaces (buf);
+      /* Don't bother freeing the various structures.  */
+      for (tmpl = templates; tmpl != NULL; tmpl = (prev = tmpl)->next)
+       if (!strcmp (buf, tmpl->name))
+         break;
+      if (tmpl == NULL)
+       fail ("%s: %d: no template '%s'\n", filename, lineno, buf);
+      if (prev)
+       prev->next = tmpl->next;
+      else
+       templates = tmpl->next;
+      return;
+    }
   *end++ = '\0';
   remove_trailing_whitespaces (buf);
 
   if (*buf == '\0')
     fail ("%s: %d: missing template identifier\n", filename, lineno);
+  tmpl = xmalloc (sizeof (*tmpl));
   tmpl->name = xstrdup (buf);
 
   tmpl->params = NULL;
@@ -1770,17 +1791,36 @@ process_i386_opcodes (FILE *table)
       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])
        {