2001-07-12 Jeff Johnston <jjohnstn@redhat.com>
authorJeff Johnston <jjohnstn@redhat.com>
Thu, 12 Jul 2001 21:26:42 +0000 (21:26 +0000)
committerJeff Johnston <jjohnstn@redhat.com>
Thu, 12 Jul 2001 21:26:42 +0000 (21:26 +0000)
        * cgen-asm.in: Include "xregex.h" always to enable the libiberty
        regex support.
        (@arch@_cgen_build_insn_regex): New routine from Graydon.
        (@arch@_cgen_assemble_insn): Add Graydon's code to use regex
        to verify if it is worth parsing the insn as insn "x".  Also update
        error message when insn is not a recognized format of the insn vs
        when the insn is completely unrecognized.

opcodes/ChangeLog
opcodes/cgen-asm.in

index 4adba8a416c9ffb916f81e2491695338ec5b335c..be15b43673777fdc4a0d69165da80df97bf4abdd 100644 (file)
@@ -1,3 +1,13 @@
+2001-07-12  Jeff Johnston  <jjohnstn@redhat.com>
+
+        * cgen-asm.in: Include "xregex.h" always to enable the libiberty
+        regex support.
+        (@arch@_cgen_build_insn_regex): New routine from Graydon.
+        (@arch@_cgen_assemble_insn): Add Graydon's code to use regex 
+       to verify if it is worth parsing the insn as insn "x".  Also update
+       error message when insn is not a recognized format of the insn vs 
+       when the insn is completely unrecognized.
+
 2001-07-11  Frank Ch. Eigler  <fche@redhat.com>
 
        * cgen-dis.in (print_insn): Use cgen_get_insn_value instead of
index aba8e46c2af5ef2b577613af15d4c6c4c3a0038b..20380a297951f240fbb9de5da64c429f8871ea22 100644 (file)
@@ -34,6 +34,7 @@ along with this program; if not, write to the Free Software Foundation, Inc.,
 #include "@prefix@-desc.h"
 #include "@prefix@-opc.h"
 #include "opintl.h"
+#include "xregex.h"
 
 #undef min
 #define min(a,b) ((a) < (b) ? (a) : (b))
@@ -44,6 +45,104 @@ static const char * parse_insn_normal
      PARAMS ((CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *));
 \f
 /* -- assembler routines inserted here */
+\f
+
+/*
+  Regex construction routine.
+
+  This translates an opcode syntax string into a regex string,
+  by replacing any non-character syntax element (such as an
+  opcode) with the pattern '.*'
+
+  It then compiles the regex and stores it in the opcode, for
+  later use by @arch@_cgen_assemble_insn
+
+  returns NULL for success, an error message for failure 
+*/
+
+char * 
+@arch@_cgen_build_insn_regex (insn)
+     CGEN_INSN *insn;
+{  
+  CGEN_OPCODE *opc = CGEN_INSN_OPCODE (insn);
+  const char *mnem = CGEN_INSN_MNEMONIC (insn);
+  int mnem_len;
+  char rxbuf[CGEN_MAX_RX_ELEMENTS];
+  char *rx = rxbuf;
+  const CGEN_SYNTAX_CHAR_TYPE *syn;
+  int reg_err;
+
+  syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
+
+  /* Mnemonics come first in the syntax string  */
+  if (! CGEN_SYNTAX_MNEMONIC_P (* syn)) return "missing mnemonic in syntax string";
+  ++syn;
+
+  /* copy the literal mnemonic out of the insn */
+  memset (rx, 0, CGEN_MAX_RX_ELEMENTS);
+  mnem_len = strlen(mnem);
+  memcpy (rx, mnem, mnem_len);
+  rx += mnem_len;
+
+  /* copy any remaining literals from the syntax string into the rx */
+  for(; * syn != 0 && rx < rxbuf + (CGEN_MAX_RX_ELEMENTS - 9); ++syn, ++rx) 
+    {
+      if (CGEN_SYNTAX_CHAR_P (* syn)) 
+       {
+        char tmp = CGEN_SYNTAX_CHAR (* syn);
+        switch (tmp) 
+           {
+            /* escape any regex metacharacters in the syntax */
+          case '.': case '[': case '\\': 
+          case '*': case '^': case '$': 
+
+#ifdef CGEN_ESCAPE_EXTENDED_REGEX
+          case '?': case '{': case '}': 
+          case '(': case ')': case '*':
+          case '|': case '+': case ']':
+#endif
+
+            * rx++ = '\\';
+            break;  
+          }
+        /* insert syntax char into rx */
+       * rx = tmp;
+       }
+      else
+       {
+         /* replace non-syntax fields with globs */
+         * rx = '.';
+         * ++rx = '*';
+       }
+    }
+
+  /* trailing whitespace ok */
+  * rx++ = '['; 
+  * rx++ = ' '; 
+  * rx++ = '\t'; 
+  * rx++ = ']'; 
+  * rx++ = '*'; 
+
+  /* but anchor it after that */
+  * rx++ = '$'; 
+  * rx = '\0';
+
+  CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
+  reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB|REG_ICASE);
+
+  if (reg_err == 0) 
+    return NULL;
+  else
+    {
+      static char msg[80];
+      regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
+      regfree ((regex_t *) CGEN_INSN_RX (insn));
+      free (CGEN_INSN_RX (insn));
+      (CGEN_INSN_RX (insn)) = NULL;
+    return msg;
+    }
+}
+
 \f
 /* Default insn parser.
 
@@ -211,6 +310,7 @@ const CGEN_INSN *
   CGEN_INSN_LIST *ilist;
   const char *parse_errmsg = NULL;
   const char *insert_errmsg = NULL;
+  int recognized_mnemonic = 0;
 
   /* Skip leading white space.  */
   while (isspace (* str))
@@ -226,6 +326,7 @@ const CGEN_INSN *
   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
     {
       const CGEN_INSN *insn = ilist->insn;
+      recognized_mnemonic = 1;
 
 #ifdef CGEN_VALIDATE_INSN_SUPPORTED 
       /* not usually needed as unsupported opcodes shouldn't be in the hash lists */
@@ -242,6 +343,11 @@ const CGEN_INSN *
 
       str = start;
 
+      /* skip this insn if str doesn't look right lexically */
+      if (CGEN_INSN_RX (insn) != NULL &&
+         regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
+       continue;
+
       /* Allow parse/insert handlers to obtain length of insn.  */
       CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
 
@@ -269,6 +375,7 @@ const CGEN_INSN *
        Failing that, use parse_errmsg */
     tmp_errmsg = (insert_errmsg ? insert_errmsg :
                  parse_errmsg ? parse_errmsg :
+                 recognized_mnemonic ? _("unrecognized form of instruction") :
                  _("unrecognized instruction"));
 
     if (strlen (start) > 50)