2001-07-21 Chris Demetriou <cgd@broadcom.com>
[deliverable/binutils-gdb.git] / opcodes / cgen-asm.in
index ad6d1722fab769373483ba0d9a35a720a4478816..20380a297951f240fbb9de5da64c429f8871ea22 100644 (file)
@@ -4,7 +4,7 @@
 THIS FILE IS MACHINE GENERATED WITH CGEN.
 - the resultant file is machine generated, cgen-asm.in isn't
 
-Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+Copyright 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
 
 This file is part of the GNU Binutils and GDB, the GNU debugger.
 
@@ -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.
 
@@ -71,7 +170,7 @@ parse_insn_normal (cd, insn, strp, fields)
   const char *str = *strp;
   const char *errmsg;
   const char *p;
-  const unsigned char * syn;
+  const CGEN_SYNTAX_CHAR_TYPE * syn;
 #ifdef CGEN_MNEMONIC_OPERANDS
   /* FIXME: wip */
   int past_opcode_p;
@@ -121,19 +220,28 @@ parse_insn_normal (cd, insn, strp, fields)
          if (tolower (*str) == tolower (CGEN_SYNTAX_CHAR (* syn)))
            {
 #ifdef CGEN_MNEMONIC_OPERANDS
-             if (* syn == ' ')
+             if (CGEN_SYNTAX_CHAR(* syn) == ' ')
                past_opcode_p = 1;
 #endif
              ++ syn;
              ++ str;
            }
-         else
+         else if (*str)
            {
              /* Syntax char didn't match.  Can't be this insn.  */
              static char msg [80];
              /* xgettext:c-format */
              sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
-                      *syn, *str);
+                      CGEN_SYNTAX_CHAR(*syn), *str);
+             return msg;
+           }
+         else
+           {
+             /* Ran out of input.  */
+             static char msg [80];
+             /* xgettext:c-format */
+             sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
+                      CGEN_SYNTAX_CHAR(*syn));
              return msg;
            }
          continue;
@@ -150,7 +258,7 @@ parse_insn_normal (cd, insn, strp, fields)
     }
 
   /* If we're at the end of the syntax string, we're done.  */
-  if (* syn == '\0')
+  if (* syn == 0)
     {
       /* FIXME: For the moment we assume a valid `str' can only contain
         blanks now.  IE: We needn't try again with a longer version of
@@ -202,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))
@@ -217,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 */
@@ -233,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);
 
@@ -253,13 +368,14 @@ const CGEN_INSN *
 
   {
     static char errbuf[150];
+#ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
     const char *tmp_errmsg;
 
-#ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
     /* If requesting verbose error messages, use insert_errmsg.
        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)
This page took 0.028392 seconds and 4 git commands to generate.