OSDN Git Service

* cgen-ibld.in (extract_normal): Match type of VALUE and MASK
authorRichard Henderson <rth@redhat.com>
Sun, 12 Aug 2001 20:16:29 +0000 (20:16 +0000)
committerRichard Henderson <rth@redhat.com>
Sun, 12 Aug 2001 20:16:29 +0000 (20:16 +0000)
        to *VALUEP.  Regenerate all cgen files.

18 files changed:
opcodes/ChangeLog
opcodes/cgen-ibld.in
opcodes/fr30-asm.c
opcodes/fr30-desc.c
opcodes/fr30-dis.c
opcodes/fr30-ibld.c
opcodes/fr30-opc.c
opcodes/m32r-asm.c
opcodes/m32r-desc.c
opcodes/m32r-dis.c
opcodes/m32r-ibld.c
opcodes/m32r-opc.c
opcodes/m32r-opinst.c
opcodes/openrisc-asm.c
opcodes/openrisc-desc.c
opcodes/openrisc-dis.c
opcodes/openrisc-ibld.c
opcodes/openrisc-opc.c

index 2a12444..bd51464 100644 (file)
@@ -1,3 +1,8 @@
+2001-08-12  Richard Henderson  <rth@redhat.com>
+
+       * cgen-ibld.in (extract_normal): Match type of VALUE and MASK
+       to *VALUEP.  Regenerate all cgen files.
+
 2001-08-10  Richard Sandiford  <rsandifo@redhat.com>
 
        * mips-dis.c (print_insn_mips): Remove OPCODE_IS_MEMBER's gp32
index 0ca4200..213b888 100644 (file)
@@ -415,7 +415,7 @@ extract_normal (cd, ex_info, insn_value, attrs, word_offset, start, length,
 #endif
      long *valuep;
 {
-  CGEN_INSN_INT value, mask;
+  long value, mask;
 
   /* If LENGTH is zero, this operand doesn't contribute to the value
      so give it a standard value of zero.  */
index b2a95e3..9ad3f2c 100644 (file)
@@ -34,6 +34,7 @@ along with this program; if not, write to the Free Software Foundation, Inc.,
 #include "fr30-desc.h"
 #include "fr30-opc.h"
 #include "opintl.h"
+#include "xregex.h"
 
 #undef min
 #define min(a,b) ((a) < (b) ? (a) : (b))
@@ -325,6 +326,104 @@ fr30_cgen_init_asm (cd)
 }
 
 \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 fr30_cgen_assemble_insn
+
+  returns NULL for success, an error message for failure 
+*/
+
+char * 
+fr30_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.
 
    The syntax string is scanned and operands are parsed and stored in FIELDS.
@@ -491,6 +590,7 @@ fr30_cgen_assemble_insn (cd, str, fields, buf, errmsg)
   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))
@@ -506,6 +606,7 @@ fr30_cgen_assemble_insn (cd, str, fields, buf, errmsg)
   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 */
@@ -522,6 +623,11 @@ fr30_cgen_assemble_insn (cd, str, fields, buf, errmsg)
 
       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);
 
@@ -542,13 +648,14 @@ fr30_cgen_assemble_insn (cd, str, fields, buf, errmsg)
 
   {
     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)
index 4223833..b2a205f 100644 (file)
@@ -122,8 +122,8 @@ static const CGEN_ISA fr30_cgen_isa_table[] = {
 /* Machine variants.  */
 
 static const CGEN_MACH fr30_cgen_mach_table[] = {
-  { "fr30", "fr30", MACH_FR30 },
-  { 0, 0, 0 }
+  { "fr30", "fr30", MACH_FR30, 0 },
+  { 0, 0, 0, 0 }
 };
 
 static CGEN_KEYWORD_ENTRY fr30_cgen_opval_gr_names_entries[] =
@@ -153,7 +153,7 @@ CGEN_KEYWORD fr30_cgen_opval_gr_names =
 {
   & fr30_cgen_opval_gr_names_entries[0],
   19,
-  0, 0, 0, 0
+  0, 0, 0, 0, ""
 };
 
 static CGEN_KEYWORD_ENTRY fr30_cgen_opval_cr_names_entries[] =
@@ -180,7 +180,7 @@ CGEN_KEYWORD fr30_cgen_opval_cr_names =
 {
   & fr30_cgen_opval_cr_names_entries[0],
   16,
-  0, 0, 0, 0
+  0, 0, 0, 0, ""
 };
 
 static CGEN_KEYWORD_ENTRY fr30_cgen_opval_dr_names_entries[] =
@@ -197,7 +197,7 @@ CGEN_KEYWORD fr30_cgen_opval_dr_names =
 {
   & fr30_cgen_opval_dr_names_entries[0],
   6,
-  0, 0, 0, 0
+  0, 0, 0, 0, ""
 };
 
 static CGEN_KEYWORD_ENTRY fr30_cgen_opval_h_ps_entries[] =
@@ -209,7 +209,7 @@ CGEN_KEYWORD fr30_cgen_opval_h_ps =
 {
   & fr30_cgen_opval_h_ps_entries[0],
   1,
-  0, 0, 0, 0
+  0, 0, 0, 0, ""
 };
 
 static CGEN_KEYWORD_ENTRY fr30_cgen_opval_h_r13_entries[] =
@@ -221,7 +221,7 @@ CGEN_KEYWORD fr30_cgen_opval_h_r13 =
 {
   & fr30_cgen_opval_h_r13_entries[0],
   1,
-  0, 0, 0, 0
+  0, 0, 0, 0, ""
 };
 
 static CGEN_KEYWORD_ENTRY fr30_cgen_opval_h_r14_entries[] =
@@ -233,7 +233,7 @@ CGEN_KEYWORD fr30_cgen_opval_h_r14 =
 {
   & fr30_cgen_opval_h_r14_entries[0],
   1,
-  0, 0, 0, 0
+  0, 0, 0, 0, ""
 };
 
 static CGEN_KEYWORD_ENTRY fr30_cgen_opval_h_r15_entries[] =
@@ -245,7 +245,7 @@ CGEN_KEYWORD fr30_cgen_opval_h_r15 =
 {
   & fr30_cgen_opval_h_r15_entries[0],
   1,
-  0, 0, 0, 0
+  0, 0, 0, 0, ""
 };
 
 
@@ -1476,11 +1476,9 @@ static void
 fr30_cgen_rebuild_tables (cd)
      CGEN_CPU_TABLE *cd;
 {
-  int i,n_isas;
+  int i;
   unsigned int isas = cd->isas;
-#if 0
   unsigned int machs = cd->machs;
-#endif
 
   cd->int_insn_p = CGEN_INT_INSN_P;
 
@@ -1518,20 +1516,26 @@ fr30_cgen_rebuild_tables (cd)
          cd->min_insn_bitsize = isa->min_insn_bitsize;
        if (isa->max_insn_bitsize > cd->max_insn_bitsize)
          cd->max_insn_bitsize = isa->max_insn_bitsize;
-
-       ++n_isas;
       }
 
-#if 0 /* Does nothing?? */
   /* Data derived from the mach spec.  */
   for (i = 0; i < MAX_MACHS; ++i)
     if (((1 << i) & machs) != 0)
       {
        const CGEN_MACH *mach = & fr30_cgen_mach_table[i];
 
-       ++n_machs;
+       if (mach->insn_chunk_bitsize != 0)
+       {
+         if (cd->insn_chunk_bitsize != 0 && cd->insn_chunk_bitsize != mach->insn_chunk_bitsize)
+           {
+             fprintf (stderr, "fr30_cgen_rebuild_tables: conflicting insn-chunk-bitsize values: `%d' vs. `%d'\n",
+                      cd->insn_chunk_bitsize, mach->insn_chunk_bitsize);
+             abort ();
+           }
+
+         cd->insn_chunk_bitsize = mach->insn_chunk_bitsize;
+       }
       }
-#endif
 
   /* Determine which hw elements are used by MACH.  */
   build_hw_table (cd);
index f389dcc..0e4aceb 100644 (file)
@@ -495,13 +495,19 @@ print_insn (cd, pc, info, buf, buflen)
      char *buf;
      int buflen;
 {
-  unsigned long insn_value;
+  CGEN_INSN_INT insn_value;
   const CGEN_INSN_LIST *insn_list;
   CGEN_EXTRACT_INFO ex_info;
 
-  int rc = read_insn (cd, pc, info, buf, buflen, & ex_info, & insn_value);
-  if (rc != 0)
-    return rc;
+  /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
+  insn_value = cgen_get_insn_value (cd, buf, buflen * 8);
+
+  /* Fill in ex_info fields like read_insn would.  Don't actually call
+     read_insn, since the incoming buffer is already read (and possibly
+     modified a la m32r).  */
+  ex_info.valid = (1 << buflen) - 1;
+  ex_info.dis_info = info;
+  ex_info.insn_bytes = buf;
 
   /* The instructions are stored in hash lists.
      Pick the first one and keep trying until we find the right one.  */
@@ -512,6 +518,7 @@ print_insn (cd, pc, info, buf, buflen)
       const CGEN_INSN *insn = insn_list->insn;
       CGEN_FIELDS fields;
       int length;
+      unsigned long insn_value_cropped;
 
 #ifdef CGEN_VALIDATE_INSN_SUPPORTED 
       /* not needed as insn shouldn't be in hash lists if not supported */
@@ -526,7 +533,17 @@ print_insn (cd, pc, info, buf, buflen)
       /* Basic bit mask must be correct.  */
       /* ??? May wish to allow target to defer this check until the extract
         handler.  */
-      if ((insn_value & CGEN_INSN_BASE_MASK (insn))
+
+      /* Base size may exceed this instruction's size.  Extract the
+         relevant part from the buffer. */
+      if ((CGEN_INSN_BITSIZE (insn) / 8) < buflen &&
+         (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
+       insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn), 
+                                          info->endian == BFD_ENDIAN_BIG);
+      else
+       insn_value_cropped = insn_value;
+
+      if ((insn_value_cropped & CGEN_INSN_BASE_MASK (insn))
          == CGEN_INSN_BASE_VALUE (insn))
        {
          /* Printing is handled in two passes.  The first pass parses the
@@ -549,7 +566,7 @@ print_insn (cd, pc, info, buf, buflen)
            }
          else
            length = CGEN_EXTRACT_FN (cd, insn)
-             (cd, insn, &ex_info, insn_value, &fields, pc);
+             (cd, insn, &ex_info, insn_value_cropped, &fields, pc);
 
          /* length < 0 -> error */
          if (length < 0)
@@ -583,18 +600,27 @@ default_print_insn (cd, pc, info)
      disassemble_info *info;
 {
   char buf[CGEN_MAX_INSN_SIZE];
+  int buflen;
   int status;
 
-  /* Read the base part of the insn.  */
+  /* Attempt to read the base part of the insn.  */
+  buflen = cd->base_insn_bitsize / 8;
+  status = (*info->read_memory_func) (pc, buf, buflen, info);
+
+  /* Try again with the minimum part, if min < base.  */
+  if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
+    {
+      buflen = cd->min_insn_bitsize / 8;
+      status = (*info->read_memory_func) (pc, buf, buflen, info);
+    }
 
-  status = (*info->read_memory_func) (pc, buf, cd->base_insn_bitsize / 8, info);
   if (status != 0)
     {
       (*info->memory_error_func) (status, pc, info);
       return -1;
     }
 
-  return print_insn (cd, pc, info, buf, cd->base_insn_bitsize / 8);
+  return print_insn (cd, pc, info, buf, buflen);
 }
 
 /* Main entry point.
index 6bfca21..90ad6ef 100644 (file)
@@ -145,7 +145,22 @@ insert_normal (cd, value, attrs, word_offset, start, length, word_length,
     }
 
   /* Ensure VALUE will fit.  */
-  if (! CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED))
+  if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGN_OPT))
+    {
+      long minval = - (1L << (length - 1));
+      unsigned long maxval = mask;
+      
+      if ((value > 0 && (unsigned long) value > maxval)
+         || value < minval)
+       {
+         /* xgettext:c-format */
+         sprintf (errbuf,
+                  _("operand out of range (%ld not between %ld and %lu)"),
+                  value, minval, maxval);
+         return errbuf;
+       }
+    }
+  else if (! CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED))
     {
       unsigned long maxval = mask;
       
@@ -202,10 +217,10 @@ insert_normal (cd, value, attrs, word_offset, start, length, word_length,
 }
 
 /* Default insn builder (insert handler).
-   The instruction is recorded in CGEN_INT_INSN_P byte order
-   (meaning that if CGEN_INT_INSN_P BUFFER is an int * and thus the value is
-   recorded in host byte order, otherwise BUFFER is an array of bytes and the
-   value is recorded in target byte order).
+   The instruction is recorded in CGEN_INT_INSN_P byte order (meaning
+   that if CGEN_INSN_BYTES_PTR is an int * and thus, the value is
+   recorded in host byte order, otherwise BUFFER is an array of bytes
+   and the value is recorded in target byte order).
    The result is an error message or NULL if success.  */
 
 static const char *
@@ -265,7 +280,7 @@ insert_insn_normal (cd, insn, fields, buffer, pc)
 
 static void
 put_insn_int_value (cd, buf, length, insn_length, value)
-     CGEN_CPU_DESC cd;
+     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
      CGEN_INSN_BYTES_PTR buf;
      int length;
      int insn_length;
@@ -400,7 +415,7 @@ extract_normal (cd, ex_info, insn_value, attrs, word_offset, start, length,
 #endif
      long *valuep;
 {
-  CGEN_INSN_INT value, mask;
+  long value, mask;
 
   /* If LENGTH is zero, this operand doesn't contribute to the value
      so give it a standard value of zero.  */
@@ -428,9 +443,9 @@ extract_normal (cd, ex_info, insn_value, attrs, word_offset, start, length,
        word_length = total_length;
     }
 
-  /* Does the value reside in INSN_VALUE?  */
+  /* Does the value reside in INSN_VALUE, and at the right alignment?  */
 
-  if (CGEN_INT_INSN_P || word_offset == 0)
+  if (CGEN_INT_INSN_P || (word_offset == 0 && word_length == total_length))
     {
       if (CGEN_INSN_LSB0_P)
        value = insn_value >> ((word_offset + start + 1) - length);
index 4d0ab6a..877f26b 100644 (file)
@@ -1368,6 +1368,7 @@ fr30_cgen_init_opcode_table (cd)
     {
       insns[i].base = &ib[i];
       insns[i].opcode = &oc[i];
+      fr30_cgen_build_insn_regex (& insns[i]);
     }
   cd->macro_insn_table.init_entries = insns;
   cd->macro_insn_table.entry_size = sizeof (CGEN_IBASE);
@@ -1376,7 +1377,10 @@ fr30_cgen_init_opcode_table (cd)
   oc = & fr30_cgen_insn_opcode_table[0];
   insns = (CGEN_INSN *) cd->insn_table.init_entries;
   for (i = 0; i < MAX_INSNS; ++i)
-    insns[i].opcode = &oc[i];
+    {
+      insns[i].opcode = &oc[i];
+      fr30_cgen_build_insn_regex (& insns[i]);
+    }
 
   cd->sizeof_fields = sizeof (CGEN_FIELDS);
   cd->set_fields_bitsize = set_fields_bitsize;
index 4d18d64..0e69a80 100644 (file)
@@ -34,6 +34,7 @@ along with this program; if not, write to the Free Software Foundation, Inc.,
 #include "m32r-desc.h"
 #include "m32r-opc.h"
 #include "opintl.h"
+#include "xregex.h"
 
 #undef min
 #define min(a,b) ((a) < (b) ? (a) : (b))
@@ -333,6 +334,104 @@ m32r_cgen_init_asm (cd)
 }
 
 \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 m32r_cgen_assemble_insn
+
+  returns NULL for success, an error message for failure 
+*/
+
+char * 
+m32r_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.
 
    The syntax string is scanned and operands are parsed and stored in FIELDS.
@@ -499,6 +598,7 @@ m32r_cgen_assemble_insn (cd, str, fields, buf, errmsg)
   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))
@@ -514,6 +614,7 @@ m32r_cgen_assemble_insn (cd, str, fields, buf, errmsg)
   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 */
@@ -530,6 +631,11 @@ m32r_cgen_assemble_insn (cd, str, fields, buf, errmsg)
 
       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);
 
@@ -557,6 +663,7 @@ m32r_cgen_assemble_insn (cd, str, fields, buf, 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)
index 8bcd790..d07c657 100644 (file)
@@ -136,9 +136,9 @@ static const CGEN_ISA m32r_cgen_isa_table[] = {
 /* Machine variants.  */
 
 static const CGEN_MACH m32r_cgen_mach_table[] = {
-  { "m32r", "m32r", MACH_M32R },
-  { "m32rx", "m32rx", MACH_M32RX },
-  { 0, 0, 0 }
+  { "m32r", "m32r", MACH_M32R, 0 },
+  { "m32rx", "m32rx", MACH_M32RX, 0 },
+  { 0, 0, 0, 0 }
 };
 
 static CGEN_KEYWORD_ENTRY m32r_cgen_opval_gr_names_entries[] =
@@ -168,7 +168,7 @@ CGEN_KEYWORD m32r_cgen_opval_gr_names =
 {
   & m32r_cgen_opval_gr_names_entries[0],
   19,
-  0, 0, 0, 0
+  0, 0, 0, 0, ""
 };
 
 static CGEN_KEYWORD_ENTRY m32r_cgen_opval_cr_names_entries[] =
@@ -202,7 +202,7 @@ CGEN_KEYWORD m32r_cgen_opval_cr_names =
 {
   & m32r_cgen_opval_cr_names_entries[0],
   23,
-  0, 0, 0, 0
+  0, 0, 0, 0, ""
 };
 
 static CGEN_KEYWORD_ENTRY m32r_cgen_opval_h_accums_entries[] =
@@ -215,7 +215,7 @@ CGEN_KEYWORD m32r_cgen_opval_h_accums =
 {
   & m32r_cgen_opval_h_accums_entries[0],
   2,
-  0, 0, 0, 0
+  0, 0, 0, 0, ""
 };
 
 
@@ -1200,11 +1200,9 @@ static void
 m32r_cgen_rebuild_tables (cd)
      CGEN_CPU_TABLE *cd;
 {
-  int i,n_isas;
+  int i;
   unsigned int isas = cd->isas;
-#if 0
   unsigned int machs = cd->machs;
-#endif
 
   cd->int_insn_p = CGEN_INT_INSN_P;
 
@@ -1242,20 +1240,26 @@ m32r_cgen_rebuild_tables (cd)
          cd->min_insn_bitsize = isa->min_insn_bitsize;
        if (isa->max_insn_bitsize > cd->max_insn_bitsize)
          cd->max_insn_bitsize = isa->max_insn_bitsize;
-
-       ++n_isas;
       }
 
-#if 0 /* Does nothing?? */
   /* Data derived from the mach spec.  */
   for (i = 0; i < MAX_MACHS; ++i)
     if (((1 << i) & machs) != 0)
       {
        const CGEN_MACH *mach = & m32r_cgen_mach_table[i];
 
-       ++n_machs;
+       if (mach->insn_chunk_bitsize != 0)
+       {
+         if (cd->insn_chunk_bitsize != 0 && cd->insn_chunk_bitsize != mach->insn_chunk_bitsize)
+           {
+             fprintf (stderr, "m32r_cgen_rebuild_tables: conflicting insn-chunk-bitsize values: `%d' vs. `%d'\n",
+                      cd->insn_chunk_bitsize, mach->insn_chunk_bitsize);
+             abort ();
+           }
+
+         cd->insn_chunk_bitsize = mach->insn_chunk_bitsize;
+       }
       }
-#endif
 
   /* Determine which hw elements are used by MACH.  */
   build_hw_table (cd);
index 477a85b..687eb51 100644 (file)
@@ -434,12 +434,12 @@ print_insn (cd, pc, info, buf, buflen)
      char *buf;
      int buflen;
 {
-  unsigned long insn_value;
+  CGEN_INSN_INT insn_value;
   const CGEN_INSN_LIST *insn_list;
   CGEN_EXTRACT_INFO ex_info;
 
   /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
-  insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG);
+  insn_value = cgen_get_insn_value (cd, buf, buflen * 8);
 
   /* Fill in ex_info fields like read_insn would.  Don't actually call
      read_insn, since the incoming buffer is already read (and possibly
@@ -505,7 +505,7 @@ print_insn (cd, pc, info, buf, buflen)
            }
          else
            length = CGEN_EXTRACT_FN (cd, insn)
-             (cd, insn, &ex_info, insn_value, &fields, pc);
+             (cd, insn, &ex_info, insn_value_cropped, &fields, pc);
 
          /* length < 0 -> error */
          if (length < 0)
@@ -539,18 +539,27 @@ default_print_insn (cd, pc, info)
      disassemble_info *info;
 {
   char buf[CGEN_MAX_INSN_SIZE];
+  int buflen;
   int status;
 
-  /* Read the base part of the insn.  */
+  /* Attempt to read the base part of the insn.  */
+  buflen = cd->base_insn_bitsize / 8;
+  status = (*info->read_memory_func) (pc, buf, buflen, info);
+
+  /* Try again with the minimum part, if min < base.  */
+  if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
+    {
+      buflen = cd->min_insn_bitsize / 8;
+      status = (*info->read_memory_func) (pc, buf, buflen, info);
+    }
 
-  status = (*info->read_memory_func) (pc, buf, cd->base_insn_bitsize / 8, info);
   if (status != 0)
     {
       (*info->memory_error_func) (status, pc, info);
       return -1;
     }
 
-  return print_insn (cd, pc, info, buf, cd->base_insn_bitsize / 8);
+  return print_insn (cd, pc, info, buf, buflen);
 }
 
 /* Main entry point.
index f999bcd..447f014 100644 (file)
@@ -145,7 +145,22 @@ insert_normal (cd, value, attrs, word_offset, start, length, word_length,
     }
 
   /* Ensure VALUE will fit.  */
-  if (! CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED))
+  if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGN_OPT))
+    {
+      long minval = - (1L << (length - 1));
+      unsigned long maxval = mask;
+      
+      if ((value > 0 && (unsigned long) value > maxval)
+         || value < minval)
+       {
+         /* xgettext:c-format */
+         sprintf (errbuf,
+                  _("operand out of range (%ld not between %ld and %lu)"),
+                  value, minval, maxval);
+         return errbuf;
+       }
+    }
+  else if (! CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED))
     {
       unsigned long maxval = mask;
       
@@ -400,7 +415,7 @@ extract_normal (cd, ex_info, insn_value, attrs, word_offset, start, length,
 #endif
      long *valuep;
 {
-  CGEN_INSN_INT value, mask;
+  long value, mask;
 
   /* If LENGTH is zero, this operand doesn't contribute to the value
      so give it a standard value of zero.  */
@@ -428,9 +443,9 @@ extract_normal (cd, ex_info, insn_value, attrs, word_offset, start, length,
        word_length = total_length;
     }
 
-  /* Does the value reside in INSN_VALUE?  */
+  /* Does the value reside in INSN_VALUE, and at the right alignment?  */
 
-  if (CGEN_INT_INSN_P || word_offset == 0)
+  if (CGEN_INT_INSN_P || (word_offset == 0 && word_length == total_length))
     {
       if (CGEN_INSN_LSB0_P)
        value = insn_value >> ((word_offset + start + 1) - length);
index 3c579a4..12491d7 100644 (file)
@@ -1685,6 +1685,7 @@ m32r_cgen_init_opcode_table (cd)
     {
       insns[i].base = &ib[i];
       insns[i].opcode = &oc[i];
+      m32r_cgen_build_insn_regex (& insns[i]);
     }
   cd->macro_insn_table.init_entries = insns;
   cd->macro_insn_table.entry_size = sizeof (CGEN_IBASE);
@@ -1693,7 +1694,10 @@ m32r_cgen_init_opcode_table (cd)
   oc = & m32r_cgen_insn_opcode_table[0];
   insns = (CGEN_INSN *) cd->insn_table.init_entries;
   for (i = 0; i < MAX_INSNS; ++i)
-    insns[i].opcode = &oc[i];
+    {
+      insns[i].opcode = &oc[i];
+      m32r_cgen_build_insn_regex (& insns[i]);
+    }
 
   cd->sizeof_fields = sizeof (CGEN_FIELDS);
   cd->set_fields_bitsize = set_fields_bitsize;
index 55e7e4f..aaaa1c0 100644 (file)
@@ -137,7 +137,7 @@ static const CGEN_OPINST sfmt_beqz_ops[] = {
 static const CGEN_OPINST sfmt_bl8_ops[] = {
   { INPUT, "disp8", HW_H_IADDR, CGEN_MODE_USI, OP_ENT (DISP8), 0, 0 },
   { INPUT, "pc", HW_H_PC, CGEN_MODE_USI, 0, 0, 0 },
-  { OUTPUT, "h_gr_14", HW_H_GR, CGEN_MODE_SI, 0, 14, 0 },
+  { OUTPUT, "h_gr_SI_14", HW_H_GR, CGEN_MODE_SI, 0, 14, 0 },
   { OUTPUT, "pc", HW_H_PC, CGEN_MODE_USI, 0, 0, 0 },
   { END }
 };
@@ -145,7 +145,7 @@ static const CGEN_OPINST sfmt_bl8_ops[] = {
 static const CGEN_OPINST sfmt_bl24_ops[] = {
   { INPUT, "disp24", HW_H_IADDR, CGEN_MODE_USI, OP_ENT (DISP24), 0, 0 },
   { INPUT, "pc", HW_H_PC, CGEN_MODE_USI, 0, 0, 0 },
-  { OUTPUT, "h_gr_14", HW_H_GR, CGEN_MODE_SI, 0, 14, 0 },
+  { OUTPUT, "h_gr_SI_14", HW_H_GR, CGEN_MODE_SI, 0, 14, 0 },
   { OUTPUT, "pc", HW_H_PC, CGEN_MODE_USI, 0, 0, 0 },
   { END }
 };
@@ -154,7 +154,7 @@ static const CGEN_OPINST sfmt_bcl8_ops[] = {
   { INPUT, "condbit", HW_H_COND, CGEN_MODE_BI, 0, 0, 0 },
   { INPUT, "disp8", HW_H_IADDR, CGEN_MODE_USI, OP_ENT (DISP8), 0, COND_REF },
   { INPUT, "pc", HW_H_PC, CGEN_MODE_USI, 0, 0, COND_REF },
-  { OUTPUT, "h_gr_14", HW_H_GR, CGEN_MODE_SI, 0, 14, COND_REF },
+  { OUTPUT, "h_gr_SI_14", HW_H_GR, CGEN_MODE_SI, 0, 14, COND_REF },
   { OUTPUT, "pc", HW_H_PC, CGEN_MODE_USI, 0, 0, COND_REF },
   { END }
 };
@@ -163,7 +163,7 @@ static const CGEN_OPINST sfmt_bcl24_ops[] = {
   { INPUT, "condbit", HW_H_COND, CGEN_MODE_BI, 0, 0, 0 },
   { INPUT, "disp24", HW_H_IADDR, CGEN_MODE_USI, OP_ENT (DISP24), 0, COND_REF },
   { INPUT, "pc", HW_H_PC, CGEN_MODE_USI, 0, 0, COND_REF },
-  { OUTPUT, "h_gr_14", HW_H_GR, CGEN_MODE_SI, 0, 14, COND_REF },
+  { OUTPUT, "h_gr_SI_14", HW_H_GR, CGEN_MODE_SI, 0, 14, COND_REF },
   { OUTPUT, "pc", HW_H_PC, CGEN_MODE_USI, 0, 0, COND_REF },
   { END }
 };
@@ -217,7 +217,7 @@ static const CGEN_OPINST sfmt_jc_ops[] = {
 static const CGEN_OPINST sfmt_jl_ops[] = {
   { INPUT, "pc", HW_H_PC, CGEN_MODE_USI, 0, 0, 0 },
   { INPUT, "sr", HW_H_GR, CGEN_MODE_SI, OP_ENT (SR), 0, 0 },
-  { OUTPUT, "h_gr_14", HW_H_GR, CGEN_MODE_SI, 0, 14, 0 },
+  { OUTPUT, "h_gr_SI_14", HW_H_GR, CGEN_MODE_SI, 0, 14, 0 },
   { OUTPUT, "pc", HW_H_PC, CGEN_MODE_USI, 0, 0, 0 },
   { END }
 };
@@ -229,14 +229,44 @@ static const CGEN_OPINST sfmt_jmp_ops[] = {
 };
 
 static const CGEN_OPINST sfmt_ld_ops[] = {
-  { INPUT, "h_memory_sr", HW_H_MEMORY, CGEN_MODE_SI, 0, 0, 0 },
+  { INPUT, "h_memory_SI_sr", HW_H_MEMORY, CGEN_MODE_SI, 0, 0, 0 },
   { INPUT, "sr", HW_H_GR, CGEN_MODE_USI, OP_ENT (SR), 0, 0 },
   { OUTPUT, "dr", HW_H_GR, CGEN_MODE_SI, OP_ENT (DR), 0, 0 },
   { END }
 };
 
 static const CGEN_OPINST sfmt_ld_d_ops[] = {
-  { INPUT, "h_memory_add__DFLT_sr_slo16", HW_H_MEMORY, CGEN_MODE_SI, 0, 0, 0 },
+  { INPUT, "h_memory_SI_add__DFLT_sr_slo16", HW_H_MEMORY, CGEN_MODE_SI, 0, 0, 0 },
+  { INPUT, "slo16", HW_H_SLO16, CGEN_MODE_INT, OP_ENT (SLO16), 0, 0 },
+  { INPUT, "sr", HW_H_GR, CGEN_MODE_SI, OP_ENT (SR), 0, 0 },
+  { OUTPUT, "dr", HW_H_GR, CGEN_MODE_SI, OP_ENT (DR), 0, 0 },
+  { END }
+};
+
+static const CGEN_OPINST sfmt_ldb_ops[] = {
+  { INPUT, "h_memory_QI_sr", HW_H_MEMORY, CGEN_MODE_QI, 0, 0, 0 },
+  { INPUT, "sr", HW_H_GR, CGEN_MODE_USI, OP_ENT (SR), 0, 0 },
+  { OUTPUT, "dr", HW_H_GR, CGEN_MODE_SI, OP_ENT (DR), 0, 0 },
+  { END }
+};
+
+static const CGEN_OPINST sfmt_ldb_d_ops[] = {
+  { INPUT, "h_memory_QI_add__DFLT_sr_slo16", HW_H_MEMORY, CGEN_MODE_QI, 0, 0, 0 },
+  { INPUT, "slo16", HW_H_SLO16, CGEN_MODE_INT, OP_ENT (SLO16), 0, 0 },
+  { INPUT, "sr", HW_H_GR, CGEN_MODE_SI, OP_ENT (SR), 0, 0 },
+  { OUTPUT, "dr", HW_H_GR, CGEN_MODE_SI, OP_ENT (DR), 0, 0 },
+  { END }
+};
+
+static const CGEN_OPINST sfmt_ldh_ops[] = {
+  { INPUT, "h_memory_HI_sr", HW_H_MEMORY, CGEN_MODE_HI, 0, 0, 0 },
+  { INPUT, "sr", HW_H_GR, CGEN_MODE_USI, OP_ENT (SR), 0, 0 },
+  { OUTPUT, "dr", HW_H_GR, CGEN_MODE_SI, OP_ENT (DR), 0, 0 },
+  { END }
+};
+
+static const CGEN_OPINST sfmt_ldh_d_ops[] = {
+  { INPUT, "h_memory_HI_add__DFLT_sr_slo16", HW_H_MEMORY, CGEN_MODE_HI, 0, 0, 0 },
   { INPUT, "slo16", HW_H_SLO16, CGEN_MODE_INT, OP_ENT (SLO16), 0, 0 },
   { INPUT, "sr", HW_H_GR, CGEN_MODE_SI, OP_ENT (SR), 0, 0 },
   { OUTPUT, "dr", HW_H_GR, CGEN_MODE_SI, OP_ENT (DR), 0, 0 },
@@ -244,7 +274,7 @@ static const CGEN_OPINST sfmt_ld_d_ops[] = {
 };
 
 static const CGEN_OPINST sfmt_ld_plus_ops[] = {
-  { INPUT, "h_memory_sr", HW_H_MEMORY, CGEN_MODE_SI, 0, 0, 0 },
+  { INPUT, "h_memory_SI_sr", HW_H_MEMORY, CGEN_MODE_SI, 0, 0, 0 },
   { INPUT, "sr", HW_H_GR, CGEN_MODE_USI, OP_ENT (SR), 0, 0 },
   { OUTPUT, "dr", HW_H_GR, CGEN_MODE_SI, OP_ENT (DR), 0, 0 },
   { OUTPUT, "sr", HW_H_GR, CGEN_MODE_SI, OP_ENT (SR), 0, 0 },
@@ -270,10 +300,10 @@ static const CGEN_OPINST sfmt_ldi16_ops[] = {
 };
 
 static const CGEN_OPINST sfmt_lock_ops[] = {
-  { INPUT, "h_memory_sr", HW_H_MEMORY, CGEN_MODE_SI, 0, 0, 0 },
+  { INPUT, "h_memory_SI_sr", HW_H_MEMORY, CGEN_MODE_SI, 0, 0, 0 },
   { INPUT, "sr", HW_H_GR, CGEN_MODE_USI, OP_ENT (SR), 0, 0 },
   { OUTPUT, "dr", HW_H_GR, CGEN_MODE_SI, OP_ENT (DR), 0, 0 },
-  { OUTPUT, "h_lock", HW_H_LOCK, CGEN_MODE_BI, 0, 0, 0 },
+  { OUTPUT, "h_lock_BI", HW_H_LOCK, CGEN_MODE_BI, 0, 0, 0 },
   { END }
 };
 
@@ -369,13 +399,13 @@ static const CGEN_OPINST sfmt_rac_dsi_ops[] = {
 };
 
 static const CGEN_OPINST sfmt_rte_ops[] = {
-  { INPUT, "h_bbpsw", HW_H_BBPSW, CGEN_MODE_UQI, 0, 0, 0 },
-  { INPUT, "h_bpsw", HW_H_BPSW, CGEN_MODE_UQI, 0, 0, 0 },
-  { INPUT, "h_cr_14", HW_H_CR, CGEN_MODE_USI, 0, 14, 0 },
-  { INPUT, "h_cr_6", HW_H_CR, CGEN_MODE_USI, 0, 6, 0 },
-  { OUTPUT, "h_bpsw", HW_H_BPSW, CGEN_MODE_UQI, 0, 0, 0 },
-  { OUTPUT, "h_cr_6", HW_H_CR, CGEN_MODE_USI, 0, 6, 0 },
-  { OUTPUT, "h_psw", HW_H_PSW, CGEN_MODE_UQI, 0, 0, 0 },
+  { INPUT, "h_bbpsw_UQI", HW_H_BBPSW, CGEN_MODE_UQI, 0, 0, 0 },
+  { INPUT, "h_bpsw_UQI", HW_H_BPSW, CGEN_MODE_UQI, 0, 0, 0 },
+  { INPUT, "h_cr_USI_14", HW_H_CR, CGEN_MODE_USI, 0, 14, 0 },
+  { INPUT, "h_cr_USI_6", HW_H_CR, CGEN_MODE_USI, 0, 6, 0 },
+  { OUTPUT, "h_bpsw_UQI", HW_H_BPSW, CGEN_MODE_UQI, 0, 0, 0 },
+  { OUTPUT, "h_cr_USI_6", HW_H_CR, CGEN_MODE_USI, 0, 6, 0 },
+  { OUTPUT, "h_psw_UQI", HW_H_PSW, CGEN_MODE_UQI, 0, 0, 0 },
   { OUTPUT, "pc", HW_H_PC, CGEN_MODE_USI, 0, 0, 0 },
   { END }
 };
@@ -403,7 +433,7 @@ static const CGEN_OPINST sfmt_slli_ops[] = {
 static const CGEN_OPINST sfmt_st_ops[] = {
   { INPUT, "src1", HW_H_GR, CGEN_MODE_SI, OP_ENT (SRC1), 0, 0 },
   { INPUT, "src2", HW_H_GR, CGEN_MODE_USI, OP_ENT (SRC2), 0, 0 },
-  { OUTPUT, "h_memory_src2", HW_H_MEMORY, CGEN_MODE_SI, 0, 0, 0 },
+  { OUTPUT, "h_memory_SI_src2", HW_H_MEMORY, CGEN_MODE_SI, 0, 0, 0 },
   { END }
 };
 
@@ -411,14 +441,14 @@ static const CGEN_OPINST sfmt_st_d_ops[] = {
   { INPUT, "slo16", HW_H_SLO16, CGEN_MODE_INT, OP_ENT (SLO16), 0, 0 },
   { INPUT, "src1", HW_H_GR, CGEN_MODE_SI, OP_ENT (SRC1), 0, 0 },
   { INPUT, "src2", HW_H_GR, CGEN_MODE_SI, OP_ENT (SRC2), 0, 0 },
-  { OUTPUT, "h_memory_add__DFLT_src2_slo16", HW_H_MEMORY, CGEN_MODE_SI, 0, 0, 0 },
+  { OUTPUT, "h_memory_SI_add__DFLT_src2_slo16", HW_H_MEMORY, CGEN_MODE_SI, 0, 0, 0 },
   { END }
 };
 
 static const CGEN_OPINST sfmt_stb_ops[] = {
   { INPUT, "src1", HW_H_GR, CGEN_MODE_QI, OP_ENT (SRC1), 0, 0 },
   { INPUT, "src2", HW_H_GR, CGEN_MODE_USI, OP_ENT (SRC2), 0, 0 },
-  { OUTPUT, "h_memory_src2", HW_H_MEMORY, CGEN_MODE_QI, 0, 0, 0 },
+  { OUTPUT, "h_memory_QI_src2", HW_H_MEMORY, CGEN_MODE_QI, 0, 0, 0 },
   { END }
 };
 
@@ -426,14 +456,14 @@ static const CGEN_OPINST sfmt_stb_d_ops[] = {
   { INPUT, "slo16", HW_H_SLO16, CGEN_MODE_INT, OP_ENT (SLO16), 0, 0 },
   { INPUT, "src1", HW_H_GR, CGEN_MODE_QI, OP_ENT (SRC1), 0, 0 },
   { INPUT, "src2", HW_H_GR, CGEN_MODE_SI, OP_ENT (SRC2), 0, 0 },
-  { OUTPUT, "h_memory_add__DFLT_src2_slo16", HW_H_MEMORY, CGEN_MODE_QI, 0, 0, 0 },
+  { OUTPUT, "h_memory_QI_add__DFLT_src2_slo16", HW_H_MEMORY, CGEN_MODE_QI, 0, 0, 0 },
   { END }
 };
 
 static const CGEN_OPINST sfmt_sth_ops[] = {
   { INPUT, "src1", HW_H_GR, CGEN_MODE_HI, OP_ENT (SRC1), 0, 0 },
   { INPUT, "src2", HW_H_GR, CGEN_MODE_USI, OP_ENT (SRC2), 0, 0 },
-  { OUTPUT, "h_memory_src2", HW_H_MEMORY, CGEN_MODE_HI, 0, 0, 0 },
+  { OUTPUT, "h_memory_HI_src2", HW_H_MEMORY, CGEN_MODE_HI, 0, 0, 0 },
   { END }
 };
 
@@ -441,39 +471,39 @@ static const CGEN_OPINST sfmt_sth_d_ops[] = {
   { INPUT, "slo16", HW_H_SLO16, CGEN_MODE_INT, OP_ENT (SLO16), 0, 0 },
   { INPUT, "src1", HW_H_GR, CGEN_MODE_HI, OP_ENT (SRC1), 0, 0 },
   { INPUT, "src2", HW_H_GR, CGEN_MODE_SI, OP_ENT (SRC2), 0, 0 },
-  { OUTPUT, "h_memory_add__DFLT_src2_slo16", HW_H_MEMORY, CGEN_MODE_HI, 0, 0, 0 },
+  { OUTPUT, "h_memory_HI_add__DFLT_src2_slo16", HW_H_MEMORY, CGEN_MODE_HI, 0, 0, 0 },
   { END }
 };
 
 static const CGEN_OPINST sfmt_st_plus_ops[] = {
   { INPUT, "src1", HW_H_GR, CGEN_MODE_SI, OP_ENT (SRC1), 0, 0 },
   { INPUT, "src2", HW_H_GR, CGEN_MODE_SI, OP_ENT (SRC2), 0, 0 },
-  { OUTPUT, "h_memory_new_src2", HW_H_MEMORY, CGEN_MODE_SI, 0, 0, 0 },
+  { OUTPUT, "h_memory_SI_new_src2", HW_H_MEMORY, CGEN_MODE_SI, 0, 0, 0 },
   { OUTPUT, "src2", HW_H_GR, CGEN_MODE_SI, OP_ENT (SRC2), 0, 0 },
   { END }
 };
 
 static const CGEN_OPINST sfmt_trap_ops[] = {
-  { INPUT, "h_bpsw", HW_H_BPSW, CGEN_MODE_UQI, 0, 0, 0 },
-  { INPUT, "h_cr_6", HW_H_CR, CGEN_MODE_USI, 0, 6, 0 },
-  { INPUT, "h_psw", HW_H_PSW, CGEN_MODE_UQI, 0, 0, 0 },
+  { INPUT, "h_bpsw_UQI", HW_H_BPSW, CGEN_MODE_UQI, 0, 0, 0 },
+  { INPUT, "h_cr_USI_6", HW_H_CR, CGEN_MODE_USI, 0, 6, 0 },
+  { INPUT, "h_psw_UQI", HW_H_PSW, CGEN_MODE_UQI, 0, 0, 0 },
   { INPUT, "pc", HW_H_PC, CGEN_MODE_USI, 0, 0, 0 },
   { INPUT, "uimm4", HW_H_UINT, CGEN_MODE_UINT, OP_ENT (UIMM4), 0, 0 },
-  { OUTPUT, "h_bbpsw", HW_H_BBPSW, CGEN_MODE_UQI, 0, 0, 0 },
-  { OUTPUT, "h_bpsw", HW_H_BPSW, CGEN_MODE_UQI, 0, 0, 0 },
-  { OUTPUT, "h_cr_14", HW_H_CR, CGEN_MODE_USI, 0, 14, 0 },
-  { OUTPUT, "h_cr_6", HW_H_CR, CGEN_MODE_USI, 0, 6, 0 },
-  { OUTPUT, "h_psw", HW_H_PSW, CGEN_MODE_UQI, 0, 0, 0 },
+  { OUTPUT, "h_bbpsw_UQI", HW_H_BBPSW, CGEN_MODE_UQI, 0, 0, 0 },
+  { OUTPUT, "h_bpsw_UQI", HW_H_BPSW, CGEN_MODE_UQI, 0, 0, 0 },
+  { OUTPUT, "h_cr_USI_14", HW_H_CR, CGEN_MODE_USI, 0, 14, 0 },
+  { OUTPUT, "h_cr_USI_6", HW_H_CR, CGEN_MODE_USI, 0, 6, 0 },
+  { OUTPUT, "h_psw_UQI", HW_H_PSW, CGEN_MODE_UQI, 0, 0, 0 },
   { OUTPUT, "pc", HW_H_PC, CGEN_MODE_SI, 0, 0, 0 },
   { END }
 };
 
 static const CGEN_OPINST sfmt_unlock_ops[] = {
-  { INPUT, "h_lock", HW_H_LOCK, CGEN_MODE_BI, 0, 0, 0 },
+  { INPUT, "h_lock_BI", HW_H_LOCK, CGEN_MODE_BI, 0, 0, 0 },
   { INPUT, "src1", HW_H_GR, CGEN_MODE_SI, OP_ENT (SRC1), 0, COND_REF },
   { INPUT, "src2", HW_H_GR, CGEN_MODE_USI, OP_ENT (SRC2), 0, COND_REF },
-  { OUTPUT, "h_lock", HW_H_LOCK, CGEN_MODE_BI, 0, 0, 0 },
-  { OUTPUT, "h_memory_src2", HW_H_MEMORY, CGEN_MODE_SI, 0, 0, COND_REF },
+  { OUTPUT, "h_lock_BI", HW_H_LOCK, CGEN_MODE_BI, 0, 0, 0 },
+  { OUTPUT, "h_memory_SI_src2", HW_H_MEMORY, CGEN_MODE_SI, 0, 0, COND_REF },
   { END }
 };
 
@@ -491,24 +521,24 @@ static const CGEN_OPINST sfmt_sat_ops[] = {
 };
 
 static const CGEN_OPINST sfmt_sadd_ops[] = {
-  { INPUT, "h_accums_0", HW_H_ACCUMS, CGEN_MODE_DI, 0, 0, 0 },
-  { INPUT, "h_accums_1", HW_H_ACCUMS, CGEN_MODE_DI, 0, 1, 0 },
-  { OUTPUT, "h_accums_0", HW_H_ACCUMS, CGEN_MODE_DI, 0, 0, 0 },
+  { INPUT, "h_accums_DI_0", HW_H_ACCUMS, CGEN_MODE_DI, 0, 0, 0 },
+  { INPUT, "h_accums_DI_1", HW_H_ACCUMS, CGEN_MODE_DI, 0, 1, 0 },
+  { OUTPUT, "h_accums_DI_0", HW_H_ACCUMS, CGEN_MODE_DI, 0, 0, 0 },
   { END }
 };
 
 static const CGEN_OPINST sfmt_macwu1_ops[] = {
-  { INPUT, "h_accums_1", HW_H_ACCUMS, CGEN_MODE_DI, 0, 1, 0 },
+  { INPUT, "h_accums_DI_1", HW_H_ACCUMS, CGEN_MODE_DI, 0, 1, 0 },
   { INPUT, "src1", HW_H_GR, CGEN_MODE_SI, OP_ENT (SRC1), 0, 0 },
   { INPUT, "src2", HW_H_GR, CGEN_MODE_SI, OP_ENT (SRC2), 0, 0 },
-  { OUTPUT, "h_accums_1", HW_H_ACCUMS, CGEN_MODE_DI, 0, 1, 0 },
+  { OUTPUT, "h_accums_DI_1", HW_H_ACCUMS, CGEN_MODE_DI, 0, 1, 0 },
   { END }
 };
 
 static const CGEN_OPINST sfmt_mulwu1_ops[] = {
   { INPUT, "src1", HW_H_GR, CGEN_MODE_SI, OP_ENT (SRC1), 0, 0 },
   { INPUT, "src2", HW_H_GR, CGEN_MODE_SI, OP_ENT (SRC2), 0, 0 },
-  { OUTPUT, "h_accums_1", HW_H_ACCUMS, CGEN_MODE_DI, 0, 1, 0 },
+  { OUTPUT, "h_accums_DI_1", HW_H_ACCUMS, CGEN_MODE_DI, 0, 1, 0 },
   { END }
 };
 
@@ -576,14 +606,14 @@ static const CGEN_OPINST *m32r_cgen_opinst_table[MAX_INSNS] = {
   & sfmt_jmp_ops[0],
   & sfmt_ld_ops[0],
   & sfmt_ld_d_ops[0],
-  & sfmt_ld_ops[0],
-  & sfmt_ld_d_ops[0],
-  & sfmt_ld_ops[0],
-  & sfmt_ld_d_ops[0],
-  & sfmt_ld_ops[0],
-  & sfmt_ld_d_ops[0],
-  & sfmt_ld_ops[0],
-  & sfmt_ld_d_ops[0],
+  & sfmt_ldb_ops[0],
+  & sfmt_ldb_d_ops[0],
+  & sfmt_ldh_ops[0],
+  & sfmt_ldh_d_ops[0],
+  & sfmt_ldb_ops[0],
+  & sfmt_ldb_d_ops[0],
+  & sfmt_ldh_ops[0],
+  & sfmt_ldh_d_ops[0],
   & sfmt_ld_plus_ops[0],
   & sfmt_ld24_ops[0],
   & sfmt_ldi8_ops[0],
index 7f2e951..a8ed30b 100644 (file)
@@ -34,6 +34,7 @@ along with this program; if not, write to the Free Software Foundation, Inc.,
 #include "openrisc-desc.h"
 #include "openrisc-opc.h"
 #include "opintl.h"
+#include "xregex.h"
 
 #undef min
 #define min(a,b) ((a) < (b) ? (a) : (b))
@@ -257,6 +258,104 @@ openrisc_cgen_init_asm (cd)
 }
 
 \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 openrisc_cgen_assemble_insn
+
+  returns NULL for success, an error message for failure 
+*/
+
+char * 
+openrisc_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.
 
    The syntax string is scanned and operands are parsed and stored in FIELDS.
@@ -423,6 +522,7 @@ openrisc_cgen_assemble_insn (cd, str, fields, buf, errmsg)
   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))
@@ -438,6 +538,7 @@ openrisc_cgen_assemble_insn (cd, str, fields, buf, errmsg)
   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 */
@@ -454,6 +555,11 @@ openrisc_cgen_assemble_insn (cd, str, fields, buf, errmsg)
 
       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);
 
@@ -481,6 +587,7 @@ openrisc_cgen_assemble_insn (cd, str, fields, buf, 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)
index ff6cba2..f9605e6 100644 (file)
@@ -129,9 +129,9 @@ static const CGEN_ISA openrisc_cgen_isa_table[] = {
 /* Machine variants.  */
 
 static const CGEN_MACH openrisc_cgen_mach_table[] = {
-  { "openrisc", "openrisc", MACH_OPENRISC },
-  { "or1300", "openrisc:1300", MACH_OR1300 },
-  { 0, 0, 0 }
+  { "openrisc", "openrisc", MACH_OPENRISC, 0 },
+  { "or1300", "openrisc:1300", MACH_OR1300, 0 },
+  { 0, 0, 0, 0 }
 };
 
 static CGEN_KEYWORD_ENTRY openrisc_cgen_opval_h_gr_entries[] =
@@ -177,7 +177,7 @@ CGEN_KEYWORD openrisc_cgen_opval_h_gr =
 {
   & openrisc_cgen_opval_h_gr_entries[0],
   35,
-  0, 0, 0, 0
+  0, 0, 0, 0, ""
 };
 
 
@@ -779,11 +779,9 @@ static void
 openrisc_cgen_rebuild_tables (cd)
      CGEN_CPU_TABLE *cd;
 {
-  int i,n_isas;
+  int i;
   unsigned int isas = cd->isas;
-#if 0
   unsigned int machs = cd->machs;
-#endif
 
   cd->int_insn_p = CGEN_INT_INSN_P;
 
@@ -821,20 +819,26 @@ openrisc_cgen_rebuild_tables (cd)
          cd->min_insn_bitsize = isa->min_insn_bitsize;
        if (isa->max_insn_bitsize > cd->max_insn_bitsize)
          cd->max_insn_bitsize = isa->max_insn_bitsize;
-
-       ++n_isas;
       }
 
-#if 0 /* Does nothing?? */
   /* Data derived from the mach spec.  */
   for (i = 0; i < MAX_MACHS; ++i)
     if (((1 << i) & machs) != 0)
       {
        const CGEN_MACH *mach = & openrisc_cgen_mach_table[i];
 
-       ++n_machs;
+       if (mach->insn_chunk_bitsize != 0)
+       {
+         if (cd->insn_chunk_bitsize != 0 && cd->insn_chunk_bitsize != mach->insn_chunk_bitsize)
+           {
+             fprintf (stderr, "openrisc_cgen_rebuild_tables: conflicting insn-chunk-bitsize values: `%d' vs. `%d'\n",
+                      cd->insn_chunk_bitsize, mach->insn_chunk_bitsize);
+             abort ();
+           }
+
+         cd->insn_chunk_bitsize = mach->insn_chunk_bitsize;
+       }
       }
-#endif
 
   /* Determine which hw elements are used by MACH.  */
   build_hw_table (cd);
index 726b301..64cab8e 100644 (file)
@@ -325,13 +325,19 @@ print_insn (cd, pc, info, buf, buflen)
      char *buf;
      int buflen;
 {
-  unsigned long insn_value;
+  CGEN_INSN_INT insn_value;
   const CGEN_INSN_LIST *insn_list;
   CGEN_EXTRACT_INFO ex_info;
 
-  int rc = read_insn (cd, pc, info, buf, buflen, & ex_info, & insn_value);
-  if (rc != 0)
-    return rc;
+  /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
+  insn_value = cgen_get_insn_value (cd, buf, buflen * 8);
+
+  /* Fill in ex_info fields like read_insn would.  Don't actually call
+     read_insn, since the incoming buffer is already read (and possibly
+     modified a la m32r).  */
+  ex_info.valid = (1 << buflen) - 1;
+  ex_info.dis_info = info;
+  ex_info.insn_bytes = buf;
 
   /* The instructions are stored in hash lists.
      Pick the first one and keep trying until we find the right one.  */
@@ -342,6 +348,7 @@ print_insn (cd, pc, info, buf, buflen)
       const CGEN_INSN *insn = insn_list->insn;
       CGEN_FIELDS fields;
       int length;
+      unsigned long insn_value_cropped;
 
 #ifdef CGEN_VALIDATE_INSN_SUPPORTED 
       /* not needed as insn shouldn't be in hash lists if not supported */
@@ -356,7 +363,17 @@ print_insn (cd, pc, info, buf, buflen)
       /* Basic bit mask must be correct.  */
       /* ??? May wish to allow target to defer this check until the extract
         handler.  */
-      if ((insn_value & CGEN_INSN_BASE_MASK (insn))
+
+      /* Base size may exceed this instruction's size.  Extract the
+         relevant part from the buffer. */
+      if ((CGEN_INSN_BITSIZE (insn) / 8) < buflen &&
+         (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
+       insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn), 
+                                          info->endian == BFD_ENDIAN_BIG);
+      else
+       insn_value_cropped = insn_value;
+
+      if ((insn_value_cropped & CGEN_INSN_BASE_MASK (insn))
          == CGEN_INSN_BASE_VALUE (insn))
        {
          /* Printing is handled in two passes.  The first pass parses the
@@ -379,7 +396,7 @@ print_insn (cd, pc, info, buf, buflen)
            }
          else
            length = CGEN_EXTRACT_FN (cd, insn)
-             (cd, insn, &ex_info, insn_value, &fields, pc);
+             (cd, insn, &ex_info, insn_value_cropped, &fields, pc);
 
          /* length < 0 -> error */
          if (length < 0)
@@ -413,18 +430,27 @@ default_print_insn (cd, pc, info)
      disassemble_info *info;
 {
   char buf[CGEN_MAX_INSN_SIZE];
+  int buflen;
   int status;
 
-  /* Read the base part of the insn.  */
+  /* Attempt to read the base part of the insn.  */
+  buflen = cd->base_insn_bitsize / 8;
+  status = (*info->read_memory_func) (pc, buf, buflen, info);
+
+  /* Try again with the minimum part, if min < base.  */
+  if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
+    {
+      buflen = cd->min_insn_bitsize / 8;
+      status = (*info->read_memory_func) (pc, buf, buflen, info);
+    }
 
-  status = (*info->read_memory_func) (pc, buf, cd->base_insn_bitsize / 8, info);
   if (status != 0)
     {
       (*info->memory_error_func) (status, pc, info);
       return -1;
     }
 
-  return print_insn (cd, pc, info, buf, cd->base_insn_bitsize / 8);
+  return print_insn (cd, pc, info, buf, buflen);
 }
 
 /* Main entry point.
index ea7535e..c828aba 100644 (file)
@@ -145,7 +145,22 @@ insert_normal (cd, value, attrs, word_offset, start, length, word_length,
     }
 
   /* Ensure VALUE will fit.  */
-  if (! CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED))
+  if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGN_OPT))
+    {
+      long minval = - (1L << (length - 1));
+      unsigned long maxval = mask;
+      
+      if ((value > 0 && (unsigned long) value > maxval)
+         || value < minval)
+       {
+         /* xgettext:c-format */
+         sprintf (errbuf,
+                  _("operand out of range (%ld not between %ld and %lu)"),
+                  value, minval, maxval);
+         return errbuf;
+       }
+    }
+  else if (! CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED))
     {
       unsigned long maxval = mask;
       
@@ -400,7 +415,7 @@ extract_normal (cd, ex_info, insn_value, attrs, word_offset, start, length,
 #endif
      long *valuep;
 {
-  CGEN_INSN_INT value, mask;
+  long value, mask;
 
   /* If LENGTH is zero, this operand doesn't contribute to the value
      so give it a standard value of zero.  */
@@ -428,9 +443,9 @@ extract_normal (cd, ex_info, insn_value, attrs, word_offset, start, length,
        word_length = total_length;
     }
 
-  /* Does the value reside in INSN_VALUE?  */
+  /* Does the value reside in INSN_VALUE, and at the right alignment?  */
 
-  if (CGEN_INT_INSN_P || word_offset == 0)
+  if (CGEN_INT_INSN_P || (word_offset == 0 && word_length == total_length))
     {
       if (CGEN_INSN_LSB0_P)
        value = insn_value >> ((word_offset + start + 1) - length);
index 86ee35b..c0b2869 100644 (file)
@@ -678,6 +678,7 @@ openrisc_cgen_init_opcode_table (cd)
     {
       insns[i].base = &ib[i];
       insns[i].opcode = &oc[i];
+      openrisc_cgen_build_insn_regex (& insns[i]);
     }
   cd->macro_insn_table.init_entries = insns;
   cd->macro_insn_table.entry_size = sizeof (CGEN_IBASE);
@@ -686,7 +687,10 @@ openrisc_cgen_init_opcode_table (cd)
   oc = & openrisc_cgen_insn_opcode_table[0];
   insns = (CGEN_INSN *) cd->insn_table.init_entries;
   for (i = 0; i < MAX_INSNS; ++i)
-    insns[i].opcode = &oc[i];
+    {
+      insns[i].opcode = &oc[i];
+      openrisc_cgen_build_insn_regex (& insns[i]);
+    }
 
   cd->sizeof_fields = sizeof (CGEN_FIELDS);
   cd->set_fields_bitsize = set_fields_bitsize;