2008-09-30 H.J. Lu <hongjiu.lu@intel.com>
authorH.J. Lu <hjl.tools@gmail.com>
Tue, 30 Sep 2008 19:47:14 +0000 (19:47 +0000)
committerH.J. Lu <hjl.tools@gmail.com>
Tue, 30 Sep 2008 19:47:14 +0000 (19:47 +0000)
* i386-gen.c: Include "hashtab.h".
(next_field): Take a new argument, last.  Check last.
(process_i386_cpu_flag): Updated.
(process_i386_opcode_modifier): Likewise.
(process_i386_operand_type): Likewise.
(process_i386_registers): Likewise.
(output_i386_opcode): New.
(opcode_hash_entry): Likewise.
(opcode_hash_table): Likewise.
(opcode_hash_hash): Likewise.
(opcode_hash_eq): Likewise.
(process_i386_opcodes): Use opcode hash table and opcode array.

opcodes/ChangeLog
opcodes/i386-gen.c

index 02642ef692f2c2ef812b1431c7dce270e31b640d..d691664768b5a70e694eb98ba853f56073cb4686 100644 (file)
@@ -1,3 +1,18 @@
+2008-09-30  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * i386-gen.c: Include "hashtab.h".
+       (next_field): Take a new argument, last.  Check last.
+       (process_i386_cpu_flag): Updated.
+       (process_i386_opcode_modifier): Likewise.
+       (process_i386_operand_type): Likewise.
+       (process_i386_registers): Likewise.
+       (output_i386_opcode): New.
+       (opcode_hash_entry): Likewise.
+       (opcode_hash_table): Likewise.
+       (opcode_hash_hash): Likewise.
+       (opcode_hash_eq): Likewise.
+       (process_i386_opcodes): Use opcode hash table and opcode array.
+
 2008-09-30  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>
 
        * s390-opc.txt (stdy, stey): Fix description
index aa9a7ff61e98d6d69372da992157926536a366c2..b9d055ff5249ccecde3fcc9cc2b4a8a46046474d 100644 (file)
@@ -22,6 +22,7 @@
 #include <errno.h>
 #include "getopt.h"
 #include "libiberty.h"
+#include "hashtab.h"
 #include "safe-ctype.h"
 
 #include "i386-opc.h"
@@ -473,7 +474,7 @@ remove_trailing_whitespaces (char *str)
    pointer to the one after it.  */
 
 static char *
-next_field (char *str, char sep, char **next)
+next_field (char *str, char sep, char **next, char *last)
 {
   char *p;
 
@@ -485,6 +486,9 @@ next_field (char *str, char sep, char **next)
 
   *next = str + 1; 
 
+  if (p >= last)
+    abort ();
+
   return p;
 }
 
@@ -559,7 +563,7 @@ process_i386_cpu_flag (FILE *table, char *flag, int macro,
       last = flag + strlen (flag);
       for (next = flag; next && next < last; )
        {
-         str = next_field (next, '|', &next);
+         str = next_field (next, '|', &next, last);
          if (str)
            set_bitfield (str, flags, ARRAY_SIZE (flags));
        }
@@ -600,7 +604,7 @@ process_i386_opcode_modifier (FILE *table, char *mod)
       last = mod + strlen (mod);
       for (next = mod; next && next < last; )
        {
-         str = next_field (next, '|', &next);
+         str = next_field (next, '|', &next, last);
          if (str)
            set_bitfield (str, modifiers, ARRAY_SIZE (modifiers));
        }
@@ -647,7 +651,7 @@ process_i386_operand_type (FILE *table, char *op, int macro,
       last = op + strlen (op);
       for (next = op; next && next < last; )
        {
-         str = next_field (next, '|', &next);
+         str = next_field (next, '|', &next, last);
          if (str)
            set_bitfield (str, types, ARRAY_SIZE (types));
        }
@@ -656,16 +660,140 @@ process_i386_operand_type (FILE *table, char *op, int macro,
                       indent);
 }
 
+static void
+output_i386_opcode (FILE *table, const char *name, char *str,
+                   char *last)
+{
+  unsigned int i;
+  char *operands, *base_opcode, *extension_opcode, *opcode_length;
+  char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
+
+  /* Find number of operands.  */
+  operands = next_field (str, ',', &str, last);
+
+  /* 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 cpu_flags.  */
+  cpu_flags = next_field (str, ',', &str, last);
+
+  /* Find opcode_modifier.  */
+  opcode_modifier = next_field (str, ',', &str, last);
+
+  /* Remove the first {.  */
+  str = remove_leading_whitespaces (str);
+  if (*str != '{')
+    abort ();
+  str = remove_leading_whitespaces (str + 1);
+
+  i = strlen (str);
+
+  /* There are at least "X}".  */
+  if (i < 2)
+    abort ();
+
+  /* Remove trailing white spaces and }. */
+  do
+    {
+      i--;
+      if (ISSPACE (str[i]) || str[i] == '}')
+       str[i] = '\0';
+      else
+       break;
+    }
+  while (i != 0);
+
+  last = str + i;
+
+  /* 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);
+      if (*operand_types[i] == '0')
+       {
+         if (i != 0)
+           operand_types[i] = NULL;
+         break;
+       }
+    }
+
+  fprintf (table, "  { \"%s\", %s, %s, %s, %s,\n",
+          name, operands, base_opcode, extension_opcode,
+          opcode_length);
+
+  process_i386_cpu_flag (table, cpu_flags, 0, ",", "    ");
+
+  process_i386_opcode_modifier (table, opcode_modifier);
+
+  fprintf (table, "    { ");
+
+  for (i = 0; i < ARRAY_SIZE (operand_types); i++)
+    {
+      if (operand_types[i] == NULL || *operand_types[i] == '0')
+       {
+         if (i == 0)
+           process_i386_operand_type (table, "0", 0, "\t  ");
+         break;
+       }
+
+      if (i != 0)
+       fprintf (table, ",\n      ");
+
+      process_i386_operand_type (table, operand_types[i], 0,
+                                "\t  ");
+    }
+  fprintf (table, " } },\n");
+}
+
+struct opcode_hash_entry
+{
+  struct opcode_hash_entry *next;
+  char *name;
+  char *opcode;
+};
+
+/* Calculate the hash value of an opcode hash entry P.  */
+
+static hashval_t
+opcode_hash_hash (const void *p)
+{
+  struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
+  return htab_hash_string (entry->name);
+}
+
+/* Compare a string Q against an opcode hash entry P.  */
+
+static int
+opcode_hash_eq (const void *p, const void *q)
+{
+  struct opcode_hash_entry *entry = (struct opcode_hash_entry *) p;
+  const char *name = (const char *) q;
+  return strcmp (name, entry->name) == 0;
+}
+
 static void
 process_i386_opcodes (FILE *table)
 {
   FILE *fp;
   char buf[2048];
-  unsigned int i;
-  char *str, *p, *last;
-  char *name, *operands, *base_opcode, *extension_opcode;
-  char *opcode_length;
-  char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
+  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;
 
   filename = "i386-opc.tbl";
   fp = fopen (filename, "r");
@@ -674,9 +802,18 @@ process_i386_opcodes (FILE *table)
     fail (_("can't find i386-opc.tbl for reading, errno = %s\n"),
          xstrerror (errno));
 
+  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/* i386 opcode table.  */\n\n");
   fprintf (table, "const template i386_optab[] =\n{\n");
 
+  /* Put everything on opcode array.  */
   while (!feof (fp))
     {
       if (fgets (buf, sizeof (buf), fp) == NULL)
@@ -697,7 +834,7 @@ process_i386_opcodes (FILE *table)
       switch (p[0])
        {
        case '#':
-         fprintf (table, "%s\n", p);
+         /* Ignore comments.  */
        case '\0':
          continue;
          break;
@@ -708,117 +845,58 @@ process_i386_opcodes (FILE *table)
       last = p + strlen (p);
 
       /* Find name.  */
-      name = next_field (p, ',', &str);
-
-      if (str >= last)
-       abort ();
-
-      /* Find number of operands.  */
-      operands = next_field (str, ',', &str);
-
-      if (str >= last)
-       abort ();
-
-      /* Find base_opcode.  */
-      base_opcode = next_field (str, ',', &str);
-
-      if (str >= last)
-       abort ();
-
-      /* Find extension_opcode.  */
-      extension_opcode = next_field (str, ',', &str);
+      name = next_field (p, ',', &str, last);
 
-      if (str >= last)
-       abort ();
-
-      /* Find opcode_length.  */
-      opcode_length = next_field (str, ',', &str);
-
-      if (str >= last)
-       abort ();
-
-      /* Find cpu_flags.  */
-      cpu_flags = next_field (str, ',', &str);
-
-      if (str >= last)
-       abort ();
-
-      /* Find opcode_modifier.  */
-      opcode_modifier = next_field (str, ',', &str);
+      /* 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 (str >= last)
-       abort ();
-
-      /* Remove the first {.  */
-      str = remove_leading_whitespaces (str);
-      if (*str != '{')
-       abort ();
-      str = remove_leading_whitespaces (str + 1);
-
-      i = strlen (str);
-
-      /* There are at least "X}".  */
-      if (i < 2)
-       abort ();
-
-      /* Remove trailing white spaces and }. */
-      do
+      if (*hash_slot == NULL)
        {
-         i--;
-         if (ISSPACE (str[i]) || str[i] == '}')
-           str[i] = '\0';
-         else
-           break;
-       }
-      while (i != 0);
-
-      last = str + i;
-
-      /* Find operand_types.  */
-      for (i = 0; i < ARRAY_SIZE (operand_types); i++)
-       {
-         if (str >= last)
+         /* It is the new one.  Put it on opcode array.  */
+         if (i >= opcode_array_size)
            {
-             operand_types [i] = NULL;
-             break;
+             /* 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);
            }
 
-         operand_types [i] = next_field (str, ',', &str);
-         if (*operand_types[i] == '0')
-           {
-             if (i != 0)
-               operand_types[i] = NULL;
-             break;
-           }
+         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);
+         *hash_slot = opcode_array[i];
+         i++;
        }
-
-      fprintf (table, "  { \"%s\", %s, %s, %s, %s,\n",
-              name, operands, base_opcode, extension_opcode,
-              opcode_length);
-
-      process_i386_cpu_flag (table, cpu_flags, 0, ",", "    ");
-
-      process_i386_opcode_modifier (table, opcode_modifier);
-
-      fprintf (table, "    { ");
-
-      for (i = 0; i < ARRAY_SIZE (operand_types); i++)
+      else
        {
-         if (operand_types[i] == NULL
-             || *operand_types[i] == '0')
-           {
-             if (i == 0)
-               process_i386_operand_type (table, "0", 0, "\t  ");
-             break;
-           }
-
-         if (i != 0)
-           fprintf (table, ",\n      ");
+         /* 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);
+       }
+    }
 
-         process_i386_operand_type (table, operand_types[i], 0,
-                                    "\t  ");
+  /* Process opcode array.  */
+  for (j = 0; j < i; j++)
+    {
+      for (next = opcode_array[j]; next; next = next->next)
+       {
+         name = next->name;
+         str = next->opcode;
+         last = str + strlen (str);
+         output_i386_opcode (table, name, str, last);
        }
-      fprintf (table, " } },\n");
     }
 
   fclose (fp);
@@ -885,41 +963,26 @@ process_i386_registers (FILE *table)
       last = p + strlen (p);
 
       /* Find reg_name.  */
-      reg_name = next_field (p, ',', &str);
-
-      if (str >= last)
-       abort ();
+      reg_name = next_field (p, ',', &str, last);
 
       /* Find reg_type.  */
-      reg_type = next_field (str, ',', &str);
-
-      if (str >= last)
-       abort ();
+      reg_type = next_field (str, ',', &str, last);
 
       /* Find reg_flags.  */
-      reg_flags = next_field (str, ',', &str);
-
-      if (str >= last)
-       abort ();
+      reg_flags = next_field (str, ',', &str, last);
 
       /* Find reg_num.  */
-      reg_num = next_field (str, ',', &str);
-
-      if (str >= last)
-       abort ();
+      reg_num = next_field (str, ',', &str, last);
 
       fprintf (table, "  { \"%s\",\n    ", reg_name);
 
       process_i386_operand_type (table, reg_type, 0, "\t");
 
       /* Find 32-bit Dwarf2 register number.  */
-      dw2_32_num = next_field (str, ',', &str);
-
-      if (str >= last)
-       abort ();
+      dw2_32_num = next_field (str, ',', &str, last);
 
       /* Find 64-bit Dwarf2 register number.  */
-      dw2_64_num = next_field (str, ',', &str);
+      dw2_64_num = next_field (str, ',', &str, last);
 
       fprintf (table, ",\n    %s, %s, { %s, %s } },\n",
               reg_flags, reg_num, dw2_32_num, dw2_64_num);