Silence ARI for valid calls to abort
[deliverable/binutils-gdb.git] / opcodes / fr30-asm.c
index 8094201310a10cba525a1f2a8f6145cc430f7cb1..d3be9ed7553ba3c7516b3530bcfc5889f290c68e 100644 (file)
@@ -1,71 +1,64 @@
+/* DO NOT EDIT!  -*- buffer-read-only: t -*- vi:set ro:  */
 /* Assembler interface for targets using CGEN. -*- C -*-
    CGEN: Cpu tools GENerator
 
 /* Assembler interface for targets using CGEN. -*- C -*-
    CGEN: Cpu tools GENerator
 
-THIS FILE IS USED TO GENERATE fr30-asm.c.
+   THIS FILE IS MACHINE GENERATED WITH CGEN.
+   - the resultant file is machine generated, cgen-asm.in isn't
 
 
-Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1996-2019 Free Software Foundation, Inc.
 
 
-This file is part of the GNU Binutils and GDB, the GNU debugger.
+   This file is part of libopcodes.
 
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+   This library is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
 
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   It is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
 
 
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software Foundation, Inc.,
-59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation, Inc.,
+   51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+
+/* ??? Eventually more and more of this stuff can go to cpu-independent files.
+   Keep that in mind.  */
 
 #include "sysdep.h"
 
 #include "sysdep.h"
-#include <ctype.h>
 #include <stdio.h>
 #include "ansidecl.h"
 #include "bfd.h"
 #include "symcat.h"
 #include <stdio.h>
 #include "ansidecl.h"
 #include "bfd.h"
 #include "symcat.h"
+#include "fr30-desc.h"
 #include "fr30-opc.h"
 #include "opintl.h"
 #include "fr30-opc.h"
 #include "opintl.h"
+#include "xregex.h"
+#include "libiberty.h"
+#include "safe-ctype.h"
 
 
-#undef min
+#undef  min
 #define min(a,b) ((a) < (b) ? (a) : (b))
 #define min(a,b) ((a) < (b) ? (a) : (b))
-#undef max
+#undef  max
 #define max(a,b) ((a) > (b) ? (a) : (b))
 
 #define max(a,b) ((a) > (b) ? (a) : (b))
 
-#undef INLINE
-#ifdef __GNUC__
-#define INLINE __inline__
-#else
-#define INLINE
-#endif
-
-/* Used by the ifield rtx function.  */
-#define FLD(f) (fields->f)
-
-static const char * insert_normal
-     PARAMS ((CGEN_OPCODE_DESC, long, unsigned int, unsigned int, unsigned int,
-             unsigned int, unsigned int, unsigned int, CGEN_INSN_BYTES_PTR));
 static const char * parse_insn_normal
 static const char * parse_insn_normal
-     PARAMS ((CGEN_OPCODE_DESC, const CGEN_INSN *,
-             const char **, CGEN_FIELDS *));
-static const char * insert_insn_normal
-     PARAMS ((CGEN_OPCODE_DESC, const CGEN_INSN *,
-             CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma));
+  (CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *);
 \f
 \f
-/* -- assembler routines inserted here */
+/* -- assembler routines inserted here.  */
+
 /* -- asm.c */
 /* -- asm.c */
-/* Handle register lists for LDMx and STMx  */
+/* Handle register lists for LDMx and STMx.  */
 
 static int
 
 static int
-parse_register_number (strp)
-     const char **strp;
+parse_register_number (const char **strp)
 {
   int regno;
 {
   int regno;
+
   if (**strp < '0' || **strp > '9')
   if (**strp < '0' || **strp > '9')
-    return -1; /* error */
+    return -1; /* Error.  */
   regno = **strp - '0';
   ++*strp;
 
   regno = **strp - '0';
   ++*strp;
 
@@ -79,34 +72,34 @@ parse_register_number (strp)
 }
 
 static const char *
 }
 
 static const char *
-parse_register_list (od, strp, opindex, valuep, high_low, load_store)
-     CGEN_OPCODE_DESC od;
-     const char **strp;
-     int opindex;
-     unsigned long *valuep;
-     int high_low;   /* 0 == high, 1 == low */
-     int load_store; /* 0 == load, 1 == store */
+parse_register_list (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
+                    const char **strp,
+                    int opindex ATTRIBUTE_UNUSED,
+                    unsigned long *valuep,
+                    int high_low,   /* 0 == high, 1 == low.  */
+                    int load_store) /* 0 == load, 1 == store.  */
 {
 {
-  int regno;
   *valuep = 0;
   while (**strp && **strp != ')')
     {
   *valuep = 0;
   while (**strp && **strp != ')')
     {
+      int regno;
+
       if (**strp != 'R' && **strp != 'r')
        break;
       ++*strp;
 
       regno = parse_register_number (strp);
       if (regno == -1)
       if (**strp != 'R' && **strp != 'r')
        break;
       ++*strp;
 
       regno = parse_register_number (strp);
       if (regno == -1)
-       return "Register number is not valid";
+       return _("Register number is not valid");
       if (regno > 7 && !high_low)
       if (regno > 7 && !high_low)
-       return "Register must be between r0 and r7";
+       return _("Register must be between r0 and r7");
       if (regno < 8 && high_low)
       if (regno < 8 && high_low)
-       return "Register must be between r8 and r15";
+       return _("Register must be between r8 and r15");
 
       if (high_low)
        regno -= 8;
 
 
       if (high_low)
        regno -= 8;
 
-      if (load_store) /* mask is reversed for store */
+      if (load_store) /* Mask is reversed for store.  */
        *valuep |= 0x80 >> regno;
       else
        *valuep |= 1 << regno;
        *valuep |= 0x80 >> regno;
       else
        *valuep |= 1 << regno;
@@ -120,53 +113,56 @@ parse_register_list (od, strp, opindex, valuep, high_low, load_store)
     }
 
   if (!*strp || **strp != ')')
     }
 
   if (!*strp || **strp != ')')
-    return "Register list is not valid";
+    return _("Register list is not valid");
 
   return NULL;
 }
 
 static const char *
 
   return NULL;
 }
 
 static const char *
-parse_low_register_list_ld (od, strp, opindex, valuep)
-     CGEN_OPCODE_DESC od;
-     const char **strp;
-     int opindex;
-     unsigned long *valuep;
+parse_low_register_list_ld (CGEN_CPU_DESC cd,
+                           const char **strp,
+                           int opindex,
+                           unsigned long *valuep)
 {
 {
-  return parse_register_list (od, strp, opindex, valuep, 0/*low*/, 0/*load*/);
+  return parse_register_list (cd, strp, opindex, valuep,
+                             0 /* Low.  */, 0 /* Load.  */);
 }
 
 static const char *
 }
 
 static const char *
-parse_hi_register_list_ld (od, strp, opindex, valuep)
-     CGEN_OPCODE_DESC od;
-     const char **strp;
-     int opindex;
-     unsigned long *valuep;
+parse_hi_register_list_ld (CGEN_CPU_DESC cd,
+                          const char **strp,
+                          int opindex,
+                          unsigned long *valuep)
 {
 {
-  return parse_register_list (od, strp, opindex, valuep, 1/*high*/, 0/*load*/);
+  return parse_register_list (cd, strp, opindex, valuep,
+                             1 /* High.  */, 0 /* Load.  */);
 }
 
 static const char *
 }
 
 static const char *
-parse_low_register_list_st (od, strp, opindex, valuep)
-     CGEN_OPCODE_DESC od;
-     const char **strp;
-     int opindex;
-     unsigned long *valuep;
+parse_low_register_list_st (CGEN_CPU_DESC cd,
+                           const char **strp,
+                           int opindex,
+                           unsigned long *valuep)
 {
 {
-  return parse_register_list (od, strp, opindex, valuep, 0/*low*/, 1/*store*/);
+  return parse_register_list (cd, strp, opindex, valuep,
+                             0 /* Low.  */, 1 /* Store.  */);
 }
 
 static const char *
 }
 
 static const char *
-parse_hi_register_list_st (od, strp, opindex, valuep)
-     CGEN_OPCODE_DESC od;
-     const char **strp;
-     int opindex;
-     unsigned long *valuep;
+parse_hi_register_list_st (CGEN_CPU_DESC cd,
+                          const char **strp,
+                          int opindex,
+                          unsigned long *valuep)
 {
 {
-  return parse_register_list (od, strp, opindex, valuep, 1/*high*/, 1/*store*/);
+  return parse_register_list (cd, strp, opindex, valuep,
+                             1 /* High.  */, 1 /* Store.  */);
 }
 
 /* -- */
 
 }
 
 /* -- */
 
+const char * fr30_cgen_parse_operand
+  (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
+
 /* Main entry point for operand parsing.
 
    This function is basically just a big switch statement.  Earlier versions
 /* Main entry point for operand parsing.
 
    This function is basically just a big switch statement.  Earlier versions
@@ -178,552 +174,287 @@ parse_hi_register_list_st (od, strp, opindex, valuep)
 
    This function could be moved into `parse_insn_normal', but keeping it
    separate makes clear the interface between `parse_insn_normal' and each of
 
    This function could be moved into `parse_insn_normal', but keeping it
    separate makes clear the interface between `parse_insn_normal' and each of
-   the handlers.
-*/
+   the handlers.  */
 
 const char *
 
 const char *
-fr30_cgen_parse_operand (od, opindex, strp, fields)
-     CGEN_OPCODE_DESC od;
-     int opindex;
-     const char ** strp;
-     CGEN_FIELDS * fields;
+fr30_cgen_parse_operand (CGEN_CPU_DESC cd,
+                          int opindex,
+                          const char ** strp,
+                          CGEN_FIELDS * fields)
 {
 {
-  const char * errmsg;
+  const char * errmsg = NULL;
+  /* Used by scalar operands that still need to be parsed.  */
+  long junk ATTRIBUTE_UNUSED;
 
   switch (opindex)
     {
 
   switch (opindex)
     {
-    case FR30_OPERAND_RI :
-      errmsg = cgen_parse_keyword (od, strp, & fr30_cgen_opval_h_gr, & fields->f_Ri);
-      break;
-    case FR30_OPERAND_RJ :
-      errmsg = cgen_parse_keyword (od, strp, & fr30_cgen_opval_h_gr, & fields->f_Rj);
-      break;
-    case FR30_OPERAND_RIC :
-      errmsg = cgen_parse_keyword (od, strp, & fr30_cgen_opval_h_gr, & fields->f_Ric);
-      break;
-    case FR30_OPERAND_RJC :
-      errmsg = cgen_parse_keyword (od, strp, & fr30_cgen_opval_h_gr, & fields->f_Rjc);
-      break;
     case FR30_OPERAND_CRI :
     case FR30_OPERAND_CRI :
-      errmsg = cgen_parse_keyword (od, strp, & fr30_cgen_opval_h_cr, & fields->f_CRi);
+      errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_cr_names, & fields->f_CRi);
       break;
     case FR30_OPERAND_CRJ :
       break;
     case FR30_OPERAND_CRJ :
-      errmsg = cgen_parse_keyword (od, strp, & fr30_cgen_opval_h_cr, & fields->f_CRj);
-      break;
-    case FR30_OPERAND_RS1 :
-      errmsg = cgen_parse_keyword (od, strp, & fr30_cgen_opval_h_dr, & fields->f_Rs1);
-      break;
-    case FR30_OPERAND_RS2 :
-      errmsg = cgen_parse_keyword (od, strp, & fr30_cgen_opval_h_dr, & fields->f_Rs2);
+      errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_cr_names, & fields->f_CRj);
       break;
     case FR30_OPERAND_R13 :
       break;
     case FR30_OPERAND_R13 :
-      errmsg = cgen_parse_keyword (od, strp, & fr30_cgen_opval_h_r13, & fields->f_nil);
+      errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_h_r13, & junk);
       break;
     case FR30_OPERAND_R14 :
       break;
     case FR30_OPERAND_R14 :
-      errmsg = cgen_parse_keyword (od, strp, & fr30_cgen_opval_h_r14, & fields->f_nil);
+      errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_h_r14, & junk);
       break;
     case FR30_OPERAND_R15 :
       break;
     case FR30_OPERAND_R15 :
-      errmsg = cgen_parse_keyword (od, strp, & fr30_cgen_opval_h_r15, & fields->f_nil);
+      errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_h_r15, & junk);
       break;
       break;
-    case FR30_OPERAND_PS :
-      errmsg = cgen_parse_keyword (od, strp, & fr30_cgen_opval_h_ps, & fields->f_nil);
+    case FR30_OPERAND_RI :
+      errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_gr_names, & fields->f_Ri);
       break;
       break;
-    case FR30_OPERAND_U4 :
-      errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_U4, &fields->f_u4);
+    case FR30_OPERAND_RIC :
+      errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_gr_names, & fields->f_Ric);
       break;
       break;
-    case FR30_OPERAND_U4C :
-      errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_U4C, &fields->f_u4c);
+    case FR30_OPERAND_RJ :
+      errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_gr_names, & fields->f_Rj);
       break;
       break;
-    case FR30_OPERAND_U8 :
-      errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_U8, &fields->f_u8);
+    case FR30_OPERAND_RJC :
+      errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_gr_names, & fields->f_Rjc);
       break;
       break;
-    case FR30_OPERAND_I8 :
-      errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_I8, &fields->f_i8);
+    case FR30_OPERAND_RS1 :
+      errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_dr_names, & fields->f_Rs1);
       break;
       break;
-    case FR30_OPERAND_UDISP6 :
-      errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_UDISP6, &fields->f_udisp6);
+    case FR30_OPERAND_RS2 :
+      errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_dr_names, & fields->f_Rs2);
       break;
       break;
-    case FR30_OPERAND_DISP8 :
-      errmsg = cgen_parse_signed_integer (od, strp, FR30_OPERAND_DISP8, &fields->f_disp8);
+    case FR30_OPERAND_CC :
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_CC, (unsigned long *) (& fields->f_cc));
       break;
       break;
-    case FR30_OPERAND_DISP9 :
-      errmsg = cgen_parse_signed_integer (od, strp, FR30_OPERAND_DISP9, &fields->f_disp9);
+    case FR30_OPERAND_CCC :
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_CCC, (unsigned long *) (& fields->f_ccc));
       break;
       break;
-    case FR30_OPERAND_DISP10 :
-      errmsg = cgen_parse_signed_integer (od, strp, FR30_OPERAND_DISP10, &fields->f_disp10);
+    case FR30_OPERAND_DIR10 :
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_DIR10, (unsigned long *) (& fields->f_dir10));
       break;
       break;
-    case FR30_OPERAND_S10 :
-      errmsg = cgen_parse_signed_integer (od, strp, FR30_OPERAND_S10, &fields->f_s10);
+    case FR30_OPERAND_DIR8 :
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_DIR8, (unsigned long *) (& fields->f_dir8));
       break;
       break;
-    case FR30_OPERAND_U10 :
-      errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_U10, &fields->f_u10);
+    case FR30_OPERAND_DIR9 :
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_DIR9, (unsigned long *) (& fields->f_dir9));
       break;
       break;
-    case FR30_OPERAND_I32 :
-      errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_I32, &fields->f_i32);
+    case FR30_OPERAND_DISP10 :
+      errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_DISP10, (long *) (& fields->f_disp10));
       break;
       break;
-    case FR30_OPERAND_M4 :
-      errmsg = cgen_parse_signed_integer (od, strp, FR30_OPERAND_M4, &fields->f_m4);
+    case FR30_OPERAND_DISP8 :
+      errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_DISP8, (long *) (& fields->f_disp8));
+      break;
+    case FR30_OPERAND_DISP9 :
+      errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_DISP9, (long *) (& fields->f_disp9));
       break;
     case FR30_OPERAND_I20 :
       break;
     case FR30_OPERAND_I20 :
-      errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_I20, &fields->f_i20);
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_I20, (unsigned long *) (& fields->f_i20));
       break;
       break;
-    case FR30_OPERAND_DIR8 :
-      errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_DIR8, &fields->f_dir8);
+    case FR30_OPERAND_I32 :
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_I32, (unsigned long *) (& fields->f_i32));
       break;
       break;
-    case FR30_OPERAND_DIR9 :
-      errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_DIR9, &fields->f_dir9);
+    case FR30_OPERAND_I8 :
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_I8, (unsigned long *) (& fields->f_i8));
       break;
       break;
-    case FR30_OPERAND_DIR10 :
-      errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_DIR10, &fields->f_dir10);
+    case FR30_OPERAND_LABEL12 :
+      {
+        bfd_vma value = 0;
+        errmsg = cgen_parse_address (cd, strp, FR30_OPERAND_LABEL12, 0, NULL,  & value);
+        fields->f_rel12 = value;
+      }
       break;
     case FR30_OPERAND_LABEL9 :
       {
       break;
     case FR30_OPERAND_LABEL9 :
       {
-        bfd_vma value;
-        errmsg = cgen_parse_address (od, strp, FR30_OPERAND_LABEL9, 0, NULL,  & value);
+        bfd_vma value = 0;
+        errmsg = cgen_parse_address (cd, strp, FR30_OPERAND_LABEL9, 0, NULL,  & value);
         fields->f_rel9 = value;
       }
       break;
         fields->f_rel9 = value;
       }
       break;
-    case FR30_OPERAND_LABEL12 :
-      {
-        bfd_vma value;
-        errmsg = cgen_parse_address (od, strp, FR30_OPERAND_LABEL12, 0, NULL,  & value);
-        fields->f_rel12 = value;
-      }
+    case FR30_OPERAND_M4 :
+      errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_M4, (long *) (& fields->f_m4));
       break;
       break;
-    case FR30_OPERAND_REGLIST_LOW_LD :
-      errmsg = parse_low_register_list_ld (od, strp, FR30_OPERAND_REGLIST_LOW_LD, &fields->f_reglist_low_ld);
+    case FR30_OPERAND_PS :
+      errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_h_ps, & junk);
       break;
     case FR30_OPERAND_REGLIST_HI_LD :
       break;
     case FR30_OPERAND_REGLIST_HI_LD :
-      errmsg = parse_hi_register_list_ld (od, strp, FR30_OPERAND_REGLIST_HI_LD, &fields->f_reglist_hi_ld);
-      break;
-    case FR30_OPERAND_REGLIST_LOW_ST :
-      errmsg = parse_low_register_list_st (od, strp, FR30_OPERAND_REGLIST_LOW_ST, &fields->f_reglist_low_st);
+      errmsg = parse_hi_register_list_ld (cd, strp, FR30_OPERAND_REGLIST_HI_LD, (unsigned long *) (& fields->f_reglist_hi_ld));
       break;
     case FR30_OPERAND_REGLIST_HI_ST :
       break;
     case FR30_OPERAND_REGLIST_HI_ST :
-      errmsg = parse_hi_register_list_st (od, strp, FR30_OPERAND_REGLIST_HI_ST, &fields->f_reglist_hi_st);
-      break;
-    case FR30_OPERAND_CC :
-      errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_CC, &fields->f_cc);
-      break;
-    case FR30_OPERAND_CCC :
-      errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_CCC, &fields->f_ccc);
-      break;
-
-    default :
-      /* xgettext:c-format */
-      fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
-      abort ();
-  }
-
-  return errmsg;
-}
-
-/* Main entry point for operand insertion.
-
-   This function is basically just a big switch statement.  Earlier versions
-   used tables to look up the function to use, but
-   - if the table contains both assembler and disassembler functions then
-     the disassembler contains much of the assembler and vice-versa,
-   - there's a lot of inlining possibilities as things grow,
-   - using a switch statement avoids the function call overhead.
-
-   This function could be moved into `parse_insn_normal', but keeping it
-   separate makes clear the interface between `parse_insn_normal' and each of
-   the handlers.  It's also needed by GAS to insert operands that couldn't be
-   resolved during parsing.
-*/
-
-const char *
-fr30_cgen_insert_operand (od, opindex, fields, buffer, pc)
-     CGEN_OPCODE_DESC od;
-     int opindex;
-     CGEN_FIELDS * fields;
-     CGEN_INSN_BYTES_PTR buffer;
-     bfd_vma pc;
-{
-  const char * errmsg;
-  unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);
-
-  switch (opindex)
-    {
-    case FR30_OPERAND_RI :
-      errmsg = insert_normal (od, fields->f_Ri, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 12, 4, 16, total_length, buffer);
-      break;
-    case FR30_OPERAND_RJ :
-      errmsg = insert_normal (od, fields->f_Rj, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 4, 16, total_length, buffer);
-      break;
-    case FR30_OPERAND_RIC :
-      errmsg = insert_normal (od, fields->f_Ric, 0|(1<<CGEN_OPERAND_UNSIGNED), 16, 12, 4, 16, total_length, buffer);
+      errmsg = parse_hi_register_list_st (cd, strp, FR30_OPERAND_REGLIST_HI_ST, (unsigned long *) (& fields->f_reglist_hi_st));
       break;
       break;
-    case FR30_OPERAND_RJC :
-      errmsg = insert_normal (od, fields->f_Rjc, 0|(1<<CGEN_OPERAND_UNSIGNED), 16, 8, 4, 16, total_length, buffer);
-      break;
-    case FR30_OPERAND_CRI :
-      errmsg = insert_normal (od, fields->f_CRi, 0|(1<<CGEN_OPERAND_UNSIGNED), 16, 12, 4, 16, total_length, buffer);
-      break;
-    case FR30_OPERAND_CRJ :
-      errmsg = insert_normal (od, fields->f_CRj, 0|(1<<CGEN_OPERAND_UNSIGNED), 16, 8, 4, 16, total_length, buffer);
-      break;
-    case FR30_OPERAND_RS1 :
-      errmsg = insert_normal (od, fields->f_Rs1, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 4, 16, total_length, buffer);
-      break;
-    case FR30_OPERAND_RS2 :
-      errmsg = insert_normal (od, fields->f_Rs2, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 12, 4, 16, total_length, buffer);
-      break;
-    case FR30_OPERAND_R13 :
-      errmsg = insert_normal (od, fields->f_nil, 0, 0, 0, 0, 0, total_length, buffer);
+    case FR30_OPERAND_REGLIST_LOW_LD :
+      errmsg = parse_low_register_list_ld (cd, strp, FR30_OPERAND_REGLIST_LOW_LD, (unsigned long *) (& fields->f_reglist_low_ld));
       break;
       break;
-    case FR30_OPERAND_R14 :
-      errmsg = insert_normal (od, fields->f_nil, 0, 0, 0, 0, 0, total_length, buffer);
+    case FR30_OPERAND_REGLIST_LOW_ST :
+      errmsg = parse_low_register_list_st (cd, strp, FR30_OPERAND_REGLIST_LOW_ST, (unsigned long *) (& fields->f_reglist_low_st));
       break;
       break;
-    case FR30_OPERAND_R15 :
-      errmsg = insert_normal (od, fields->f_nil, 0, 0, 0, 0, 0, total_length, buffer);
+    case FR30_OPERAND_S10 :
+      errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_S10, (long *) (& fields->f_s10));
       break;
       break;
-    case FR30_OPERAND_PS :
-      errmsg = insert_normal (od, fields->f_nil, 0, 0, 0, 0, 0, total_length, buffer);
+    case FR30_OPERAND_U10 :
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_U10, (unsigned long *) (& fields->f_u10));
       break;
     case FR30_OPERAND_U4 :
       break;
     case FR30_OPERAND_U4 :
-      errmsg = insert_normal (od, fields->f_u4, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 4, 16, total_length, buffer);
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_U4, (unsigned long *) (& fields->f_u4));
       break;
     case FR30_OPERAND_U4C :
       break;
     case FR30_OPERAND_U4C :
-      errmsg = insert_normal (od, fields->f_u4c, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 0, 12, 4, 16, total_length, buffer);
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_U4C, (unsigned long *) (& fields->f_u4c));
       break;
     case FR30_OPERAND_U8 :
       break;
     case FR30_OPERAND_U8 :
-      errmsg = insert_normal (od, fields->f_u8, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 8, 16, total_length, buffer);
-      break;
-    case FR30_OPERAND_I8 :
-      errmsg = insert_normal (od, fields->f_i8, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 0, 4, 8, 16, total_length, buffer);
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_U8, (unsigned long *) (& fields->f_u8));
       break;
     case FR30_OPERAND_UDISP6 :
       break;
     case FR30_OPERAND_UDISP6 :
-      {
-        long value = fields->f_udisp6;
-        value = ((unsigned int) (value) >> (2));
-        errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 4, 16, total_length, buffer);
-      }
-      break;
-    case FR30_OPERAND_DISP8 :
-      errmsg = insert_normal (od, fields->f_disp8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), 0, 4, 8, 16, total_length, buffer);
-      break;
-    case FR30_OPERAND_DISP9 :
-      {
-        long value = fields->f_disp9;
-        value = ((int) (value) >> (1));
-        errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_HASH_PREFIX), 0, 4, 8, 16, total_length, buffer);
-      }
-      break;
-    case FR30_OPERAND_DISP10 :
-      {
-        long value = fields->f_disp10;
-        value = ((int) (value) >> (2));
-        errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_HASH_PREFIX), 0, 4, 8, 16, total_length, buffer);
-      }
-      break;
-    case FR30_OPERAND_S10 :
-      {
-        long value = fields->f_s10;
-        value = ((int) (value) >> (2));
-        errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_HASH_PREFIX), 0, 8, 8, 16, total_length, buffer);
-      }
-      break;
-    case FR30_OPERAND_U10 :
-      {
-        long value = fields->f_u10;
-        value = ((unsigned int) (value) >> (2));
-        errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 8, 16, total_length, buffer);
-      }
-      break;
-    case FR30_OPERAND_I32 :
-      errmsg = insert_normal (od, fields->f_i32, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGN_OPT)|(1<<CGEN_OPERAND_UNSIGNED), 16, 0, 32, 32, total_length, buffer);
-      break;
-    case FR30_OPERAND_M4 :
-      {
-        long value = fields->f_m4;
-        value = ((value) & (15));
-        errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 4, 16, total_length, buffer);
-      }
-      break;
-    case FR30_OPERAND_I20 :
-      {
-do {
-  FLD (f_i20_4) = ((unsigned int) (FLD (f_i20)) >> (16));
-  FLD (f_i20_16) = ((FLD (f_i20)) & (65535));
-} while (0);
-        errmsg = insert_normal (od, fields->f_i20_4, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED)|(1<<CGEN_OPERAND_VIRTUAL), 0, 8, 4, 16, total_length, buffer);
-        if (errmsg)
-          break;
-        errmsg = insert_normal (od, fields->f_i20_16, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED)|(1<<CGEN_OPERAND_VIRTUAL), 16, 0, 16, 16, total_length, buffer);
-        if (errmsg)
-          break;
-      }
-      break;
-    case FR30_OPERAND_DIR8 :
-      errmsg = insert_normal (od, fields->f_dir8, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 8, 16, total_length, buffer);
-      break;
-    case FR30_OPERAND_DIR9 :
-      {
-        long value = fields->f_dir9;
-        value = ((unsigned int) (value) >> (1));
-        errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 8, 16, total_length, buffer);
-      }
-      break;
-    case FR30_OPERAND_DIR10 :
-      {
-        long value = fields->f_dir10;
-        value = ((unsigned int) (value) >> (2));
-        errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 8, 16, total_length, buffer);
-      }
-      break;
-    case FR30_OPERAND_LABEL9 :
-      {
-        long value = fields->f_rel9;
-        value = ((int) (((value) - (((pc) + (2))))) >> (1));
-        errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_PCREL_ADDR), 0, 8, 8, 16, total_length, buffer);
-      }
-      break;
-    case FR30_OPERAND_LABEL12 :
-      {
-        long value = fields->f_rel12;
-        value = ((int) (((value) - (((pc) + (2))))) >> (1));
-        errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_PCREL_ADDR), 0, 5, 11, 16, total_length, buffer);
-      }
-      break;
-    case FR30_OPERAND_REGLIST_LOW_LD :
-      errmsg = insert_normal (od, fields->f_reglist_low_ld, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 8, 16, total_length, buffer);
-      break;
-    case FR30_OPERAND_REGLIST_HI_LD :
-      errmsg = insert_normal (od, fields->f_reglist_hi_ld, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 8, 16, total_length, buffer);
-      break;
-    case FR30_OPERAND_REGLIST_LOW_ST :
-      errmsg = insert_normal (od, fields->f_reglist_low_st, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 8, 16, total_length, buffer);
-      break;
-    case FR30_OPERAND_REGLIST_HI_ST :
-      errmsg = insert_normal (od, fields->f_reglist_hi_st, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 8, 16, total_length, buffer);
-      break;
-    case FR30_OPERAND_CC :
-      errmsg = insert_normal (od, fields->f_cc, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 4, 4, 16, total_length, buffer);
-      break;
-    case FR30_OPERAND_CCC :
-      errmsg = insert_normal (od, fields->f_ccc, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 16, 0, 8, 16, total_length, buffer);
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_UDISP6, (unsigned long *) (& fields->f_udisp6));
       break;
 
     default :
       /* xgettext:c-format */
       break;
 
     default :
       /* xgettext:c-format */
-      fprintf (stderr, _("Unrecognized field %d while building insn.\n"),
-              opindex);
+      opcodes_error_handler
+       (_("internal error: unrecognized field %d while parsing"),
+        opindex);
       abort ();
   }
 
   return errmsg;
 }
 
       abort ();
   }
 
   return errmsg;
 }
 
-cgen_parse_fn * const fr30_cgen_parse_handlers[] = 
+cgen_parse_fn * const fr30_cgen_parse_handlers[] =
 {
 {
-  0, /* default */
   parse_insn_normal,
 };
 
   parse_insn_normal,
 };
 
-cgen_insert_fn * const fr30_cgen_insert_handlers[] = 
-{
-  0, /* default */
-  insert_insn_normal,
-};
-
 void
 void
-fr30_cgen_init_asm (od)
-     CGEN_OPCODE_DESC od;
+fr30_cgen_init_asm (CGEN_CPU_DESC cd)
 {
 {
+  fr30_cgen_init_opcode_table (cd);
+  fr30_cgen_init_ibld_table (cd);
+  cd->parse_handlers = & fr30_cgen_parse_handlers[0];
+  cd->parse_operand = fr30_cgen_parse_operand;
+#ifdef CGEN_ASM_INIT_HOOK
+CGEN_ASM_INIT_HOOK
+#endif
 }
 
 \f
 }
 
 \f
-#if ! CGEN_INT_INSN_P
 
 
-/* Subroutine of insert_normal.  */
+/* Regex construction routine.
 
 
-static INLINE void
-insert_1 (od, value, start, length, word_length, bufp)
-     CGEN_OPCODE_DESC od;
-     unsigned long value;
-     int start,length,word_length;
-     unsigned char *bufp;
-{
-  unsigned long x,mask;
-  int shift;
-  int big_p = CGEN_OPCODE_INSN_ENDIAN (od) == CGEN_ENDIAN_BIG;
+   This translates an opcode syntax string into a regex string,
+   by replacing any non-character syntax element (such as an
+   opcode) with the pattern '.*'
 
 
-  switch (word_length)
-    {
-    case 8:
-      x = *bufp;
-      break;
-    case 16:
-      if (big_p)
-       x = bfd_getb16 (bufp);
-      else
-       x = bfd_getl16 (bufp);
-      break;
-    case 24:
-      /* ??? This may need reworking as these cases don't necessarily
-        want the first byte and the last two bytes handled like this.  */
-      if (big_p)
-       x = (bufp[0] << 16) | bfd_getb16 (bufp + 1);
-      else
-       x = bfd_getl16 (bufp) | (bufp[2] << 16);
-      break;
-    case 32:
-      if (big_p)
-       x = bfd_getb32 (bufp);
-      else
-       x = bfd_getl32 (bufp);
-      break;
-    default :
-      abort ();
-    }
+   It then compiles the regex and stores it in the opcode, for
+   later use by fr30_cgen_assemble_insn
 
 
-  /* Written this way to avoid undefined behaviour.  */
-  mask = (((1L << (length - 1)) - 1) << 1) | 1;
-  if (CGEN_INSN_LSB0_P)
-    shift = (start + 1) - length;
-  else
-    shift = (word_length - (start + length));
-  x = (x & ~(mask << shift)) | ((value & mask) << shift);
+   Returns NULL for success, an error message for failure.  */
 
 
-  switch (word_length)
-    {
-    case 8:
-      *bufp = x;
-      break;
-    case 16:
-      if (big_p)
-       bfd_putb16 (x, bufp);
-      else
-       bfd_putl16 (x, bufp);
-      break;
-    case 24:
-      /* ??? This may need reworking as these cases don't necessarily
-        want the first byte and the last two bytes handled like this.  */
-      if (big_p)
-       {
-         bufp[0] = x >> 16;
-         bfd_putb16 (x, bufp + 1);
-       }
-      else
-       {
-         bfd_putl16 (x, bufp);
-         bufp[2] = x >> 16;
-       }
-      break;
-    case 32:
-      if (big_p)
-       bfd_putb32 (x, bufp);
-      else
-       bfd_putl32 (x, bufp);
-      break;
-    default :
-      abort ();
-    }
-}
-
-#endif /* ! CGEN_INT_INSN_P */
-
-/* Default insertion routine.
-
-   ATTRS is a mask of the boolean attributes.
-   WORD_OFFSET is the offset in bits from the start of the insn of the value.
-   WORD_LENGTH is the length of the word in bits in which the value resides.
-   START is the starting bit number in the word, architecture origin.
-   LENGTH is the length of VALUE in bits.
-   TOTAL_LENGTH is the total length of the insn in bits.
-
-   The result is an error message or NULL if success.  */
-
-/* ??? This duplicates functionality with bfd's howto table and
-   bfd_install_relocation.  */
-/* ??? This doesn't handle bfd_vma's.  Create another function when
-   necessary.  */
-
-static const char *
-insert_normal (od, value, attrs, word_offset, start, length, word_length,
-              total_length, buffer)
-     CGEN_OPCODE_DESC od;
-     long value;
-     unsigned int attrs;
-     unsigned int word_offset, start, length, word_length, total_length;
-     CGEN_INSN_BYTES_PTR buffer;
+char *
+fr30_cgen_build_insn_regex (CGEN_INSN *insn)
 {
 {
-  static char errbuf[100];
-  /* Written this way to avoid undefined behaviour.  */
-  unsigned long mask = (((1L << (length - 1)) - 1) << 1) | 1;
+  CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
+  const char *mnem = CGEN_INSN_MNEMONIC (insn);
+  char rxbuf[CGEN_MAX_RX_ELEMENTS];
+  char *rx = rxbuf;
+  const CGEN_SYNTAX_CHAR_TYPE *syn;
+  int reg_err;
 
 
-  /* If LENGTH is zero, this operand doesn't contribute to the value.  */
-  if (length == 0)
-    return NULL;
-
-  if (CGEN_INT_INSN_P
-      && word_offset != 0)
-    abort ();
+  syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
 
 
-  if (word_length > 32)
-    abort ();
+  /* Mnemonics come first in the syntax string.  */
+  if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
+    return _("missing mnemonic in syntax string");
+  ++syn;
 
 
-  /* For architectures with insns smaller than the insn-base-bitsize,
-     word_length may be too big.  */
-#if CGEN_MIN_INSN_BITSIZE < CGEN_BASE_INSN_BITSIZE
-  if (word_offset == 0
-      && word_length > total_length)
-    word_length = total_length;
-#endif
+  /* Generate a case sensitive regular expression that emulates case
+     insensitive matching in the "C" locale.  We cannot generate a case
+     insensitive regular expression because in Turkish locales, 'i' and 'I'
+     are not equal modulo case conversion.  */
 
 
-  /* Ensure VALUE will fit.  */
-  if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED))
+  /* Copy the literal mnemonic out of the insn.  */
+  for (; *mnem; mnem++)
     {
     {
-      unsigned long maxval = mask;
-      if ((unsigned long) value > maxval)
+      char c = *mnem;
+
+      if (ISALPHA (c))
        {
        {
-         /* xgettext:c-format */
-         sprintf (errbuf,
-                  _("operand out of range (%lu not between 0 and %lu)"),
-                  value, maxval);
-         return errbuf;
+         *rx++ = '[';
+         *rx++ = TOLOWER (c);
+         *rx++ = TOUPPER (c);
+         *rx++ = ']';
        }
        }
+      else
+       *rx++ = c;
     }
     }
-  else
+
+  /* Copy any remaining literals from the syntax string into the rx.  */
+  for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
     {
     {
-      long minval = - (1L << (length - 1));
-      long maxval = (1L << (length - 1)) - 1;
-      if (value < minval || value > maxval)
+      if (CGEN_SYNTAX_CHAR_P (* syn))
+       {
+         char c = CGEN_SYNTAX_CHAR (* syn);
+
+         switch (c)
+           {
+             /* 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++ = '\\';
+             *rx++ = c;
+             break;
+
+           default:
+             if (ISALPHA (c))
+               {
+                 *rx++ = '[';
+                 *rx++ = TOLOWER (c);
+                 *rx++ = TOUPPER (c);
+                 *rx++ = ']';
+               }
+             else
+               *rx++ = c;
+             break;
+           }
+       }
+      else
        {
        {
-         sprintf
-           /* xgettext:c-format */
-           (errbuf, _("operand out of range (%ld not between %ld and %ld)"),
-            value, minval, maxval);
-         return errbuf;
+         /* Replace non-syntax fields with globs.  */
+         *rx++ = '.';
+         *rx++ = '*';
        }
     }
 
        }
     }
 
-#if CGEN_INT_INSN_P
-
-  {
-    int shift;
-
-    if (CGEN_INSN_LSB0_P)
-      shift = (start + 1) - length;
-    else
-      shift = word_length - (start + length);
-    *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
-  }
-
-#else /* ! CGEN_INT_INSN_P */
+  /* Trailing whitespace ok.  */
+  * rx++ = '[';
+  * rx++ = ' ';
+  * rx++ = '\t';
+  * rx++ = ']';
+  * rx++ = '*';
 
 
-  {
-    unsigned char *bufp = (unsigned char *) buffer + word_offset / 8;
+  /* But anchor it after that.  */
+  * rx++ = '$';
+  * rx = '\0';
 
 
-    insert_1 (od, value, start, length, word_length, bufp);
-  }
+  CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
+  reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
 
 
-#endif /* ! CGEN_INT_INSN_P */
+  if (reg_err == 0)
+    return NULL;
+  else
+    {
+      static char msg[80];
 
 
-  return NULL;
+      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.
 
 \f
 /* Default insn parser.
 
@@ -736,21 +467,20 @@ insert_normal (od, value, attrs, word_offset, start, length, word_length,
    but that can be handled there.  Not handling backtracking here may get
    expensive in the case of the m68k.  Deal with later.
 
    but that can be handled there.  Not handling backtracking here may get
    expensive in the case of the m68k.  Deal with later.
 
-   Returns NULL for success, an error message for failure.
-*/
+   Returns NULL for success, an error message for failure.  */
 
 static const char *
 
 static const char *
-parse_insn_normal (od, insn, strp, fields)
-     CGEN_OPCODE_DESC od;
-     const CGEN_INSN * insn;
-     const char ** strp;
-     CGEN_FIELDS * fields;
+parse_insn_normal (CGEN_CPU_DESC cd,
+                  const CGEN_INSN *insn,
+                  const char **strp,
+                  CGEN_FIELDS *fields)
 {
 {
-  const CGEN_SYNTAX * syntax = CGEN_INSN_SYNTAX (insn);
-  const char * str = *strp;
-  const char * errmsg;
-  const char * p;
-  const unsigned char * syn;
+  /* ??? Runtime added insns not handled yet.  */
+  const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
+  const char *str = *strp;
+  const char *errmsg;
+  const char *p;
+  const CGEN_SYNTAX_CHAR_TYPE * syn;
 #ifdef CGEN_MNEMONIC_OPERANDS
   /* FIXME: wip */
   int past_opcode_p;
 #ifdef CGEN_MNEMONIC_OPERANDS
   /* FIXME: wip */
   int past_opcode_p;
@@ -761,14 +491,19 @@ parse_insn_normal (od, insn, strp, fields)
      GAS's input scrubber will ensure mnemonics are lowercase, but we may
      not be called from GAS.  */
   p = CGEN_INSN_MNEMONIC (insn);
      GAS's input scrubber will ensure mnemonics are lowercase, but we may
      not be called from GAS.  */
   p = CGEN_INSN_MNEMONIC (insn);
-  while (*p && tolower (*p) == tolower (*str))
+  while (*p && TOLOWER (*p) == TOLOWER (*str))
     ++p, ++str;
     ++p, ++str;
-  
-  if (* p || (* str && !isspace (* str)))
+
+  if (* p)
     return _("unrecognized instruction");
 
     return _("unrecognized instruction");
 
-  CGEN_INIT_PARSE (od);
-  cgen_init_parse_operand (od);
+#ifndef CGEN_MNEMONIC_OPERANDS
+  if (* str && ! ISSPACE (* str))
+    return _("unrecognized instruction");
+#endif
+
+  CGEN_INIT_PARSE (cd);
+  cgen_init_parse_operand (cd);
 #ifdef CGEN_MNEMONIC_OPERANDS
   past_opcode_p = 0;
 #endif
 #ifdef CGEN_MNEMONIC_OPERANDS
   past_opcode_p = 0;
 #endif
@@ -788,28 +523,47 @@ parse_insn_normal (od, insn, strp, fields)
       /* Non operand chars must match exactly.  */
       if (CGEN_SYNTAX_CHAR_P (* syn))
        {
       /* Non operand chars must match exactly.  */
       if (CGEN_SYNTAX_CHAR_P (* syn))
        {
-         if (*str == CGEN_SYNTAX_CHAR (* syn))
+         /* FIXME: While we allow for non-GAS callers above, we assume the
+            first char after the mnemonic part is a space.  */
+         /* FIXME: We also take inappropriate advantage of the fact that
+            GAS's input scrubber will remove extraneous blanks.  */
+         if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
            {
 #ifdef CGEN_MNEMONIC_OPERANDS
            {
 #ifdef CGEN_MNEMONIC_OPERANDS
-             if (* syn == ' ')
+             if (CGEN_SYNTAX_CHAR(* syn) == ' ')
                past_opcode_p = 1;
 #endif
              ++ syn;
              ++ str;
            }
                past_opcode_p = 1;
 #endif
              ++ syn;
              ++ str;
            }
-         else
+         else if (*str)
            {
              /* Syntax char didn't match.  Can't be this insn.  */
            {
              /* Syntax char didn't match.  Can't be this insn.  */
-             /* FIXME: would like to return something like
-                "expected char `c'" */
-             return _("syntax error");
+             static char msg [80];
+
+             /* xgettext:c-format */
+             sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
+                      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;
        }
 
            }
          continue;
        }
 
+#ifdef CGEN_MNEMONIC_OPERANDS
+      (void) past_opcode_p;
+#endif
       /* We have an operand of some sort.  */
       /* We have an operand of some sort.  */
-      errmsg = fr30_cgen_parse_operand (od, CGEN_SYNTAX_FIELD (*syn),
-                                         &str, fields);
+      errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn), &str, fields);
       if (errmsg)
        return errmsg;
 
       if (errmsg)
        return errmsg;
 
@@ -818,13 +572,13 @@ parse_insn_normal (od, insn, strp, fields)
     }
 
   /* If we're at the end of the syntax string, we're done.  */
     }
 
   /* 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
         the insn and it is assumed that longer versions of insns appear
         before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
     {
       /* 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
         the insn and it is assumed that longer versions of insns appear
         before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
-      while (isspace (* str))
+      while (ISSPACE (* str))
        ++ str;
 
       if (* str != '\0')
        ++ str;
 
       if (* str != '\0')
@@ -836,64 +590,6 @@ parse_insn_normal (od, insn, strp, fields)
   /* We couldn't parse it.  */
   return _("unrecognized instruction");
 }
   /* We couldn't parse it.  */
   return _("unrecognized instruction");
 }
-
-/* 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 result is an error message or NULL if success.  */
-
-static const char *
-insert_insn_normal (od, insn, fields, buffer, pc)
-     CGEN_OPCODE_DESC od;
-     const CGEN_INSN * insn;
-     CGEN_FIELDS * fields;
-     CGEN_INSN_BYTES_PTR buffer;
-     bfd_vma pc;
-{
-  const CGEN_SYNTAX * syntax = CGEN_INSN_SYNTAX (insn);
-  unsigned long value;
-  const unsigned char * syn;
-
-  CGEN_INIT_INSERT (od);
-  value = CGEN_INSN_BASE_VALUE (insn);
-
-  /* If we're recording insns as numbers (rather than a string of bytes),
-     target byte order handling is deferred until later.  */
-
-#if CGEN_INT_INSN_P
-
-  *buffer = value;
-
-#else
-
-  cgen_put_insn_value (od, buffer, min (CGEN_BASE_INSN_BITSIZE,
-                                       CGEN_FIELDS_BITSIZE (fields)),
-                      value);
-
-#endif /* ! CGEN_INT_INSN_P */
-
-  /* ??? It would be better to scan the format's fields.
-     Still need to be able to insert a value based on the operand though;
-     e.g. storing a branch displacement that got resolved later.
-     Needs more thought first.  */
-
-  for (syn = CGEN_SYNTAX_STRING (syntax); * syn != '\0'; ++ syn)
-    {
-      const char *errmsg;
-
-      if (CGEN_SYNTAX_CHAR_P (* syn))
-       continue;
-
-      errmsg = fr30_cgen_insert_operand (od, CGEN_SYNTAX_FIELD (*syn),
-                                          fields, buffer, pc);
-      if (errmsg)
-       return errmsg;
-    }
-
-  return NULL;
-}
 \f
 /* Main entry point.
    This routine is called for each instruction to be assembled.
 \f
 /* Main entry point.
    This routine is called for each instruction to be assembled.
@@ -908,105 +604,117 @@ insert_insn_normal (od, insn, fields, buffer, pc)
    printed).
 
    Note that when processing (non-alias) macro-insns,
    printed).
 
    Note that when processing (non-alias) macro-insns,
-   this function recurses.  */
+   this function recurses.
+
+   ??? It's possible to make this cpu-independent.
+   One would have to deal with a few minor things.
+   At this point in time doing so would be more of a curiosity than useful
+   [for example this file isn't _that_ big], but keeping the possibility in
+   mind helps keep the design clean.  */
 
 const CGEN_INSN *
 
 const CGEN_INSN *
-fr30_cgen_assemble_insn (od, str, fields, buf, errmsg)
-     CGEN_OPCODE_DESC od;
-     const char * str;
-     CGEN_FIELDS * fields;
-     CGEN_INSN_BYTES_PTR buf;
-     char ** errmsg;
+fr30_cgen_assemble_insn (CGEN_CPU_DESC cd,
+                          const char *str,
+                          CGEN_FIELDS *fields,
+                          CGEN_INSN_BYTES_PTR buf,
+                          char **errmsg)
 {
 {
-  const char * start;
-  CGEN_INSN_LIST * ilist;
+  const char *start;
+  CGEN_INSN_LIST *ilist;
+  const char *parse_errmsg = NULL;
+  const char *insert_errmsg = NULL;
+  int recognized_mnemonic = 0;
 
   /* Skip leading white space.  */
 
   /* Skip leading white space.  */
-  while (isspace (* str))
+  while (ISSPACE (* str))
     ++ str;
 
   /* The instructions are stored in hashed lists.
      Get the first in the list.  */
     ++ str;
 
   /* The instructions are stored in hashed lists.
      Get the first in the list.  */
-  ilist = CGEN_ASM_LOOKUP_INSN (od, str);
+  ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
 
   /* Keep looking until we find a match.  */
 
   /* Keep looking until we find a match.  */
-
   start = str;
   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
     {
       const CGEN_INSN *insn = ilist->insn;
   start = str;
   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
     {
       const CGEN_INSN *insn = ilist->insn;
+      recognized_mnemonic = 1;
 
 
-#if 0 /* not needed as unsupported opcodes shouldn't be in the hash lists */
+#ifdef CGEN_VALIDATE_INSN_SUPPORTED
+      /* Not usually needed as unsupported opcodes
+        shouldn't be in the hash lists.  */
       /* Is this insn supported by the selected cpu?  */
       /* Is this insn supported by the selected cpu?  */
-      if (! fr30_cgen_insn_supported (od, insn))
+      if (! fr30_cgen_insn_supported (cd, insn))
        continue;
 #endif
        continue;
 #endif
-
-      /* If the RELAX attribute is set, this is an insn that shouldn't be
+      /* If the RELAXED attribute is set, this is an insn that shouldn't be
         chosen immediately.  Instead, it is used during assembler/linker
         relaxation if possible.  */
         chosen immediately.  Instead, it is used during assembler/linker
         relaxation if possible.  */
-      if (CGEN_INSN_ATTR (insn, CGEN_INSN_RELAX) != 0)
+      if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
        continue;
 
       str = start;
 
        continue;
 
       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);
 
       /* Allow parse/insert handlers to obtain length of insn.  */
       CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
 
-      if (! CGEN_PARSE_FN (insn) (od, insn, & str, fields))
-       {
-         /* ??? 0 is passed for `pc' */
-         if (CGEN_INSERT_FN (insn) (od, insn, fields, buf, (bfd_vma) 0) != NULL)
-           continue;
-         /* It is up to the caller to actually output the insn and any
-            queued relocs.  */
-         return insn;
-       }
+      parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
+      if (parse_errmsg != NULL)
+       continue;
+
+      /* ??? 0 is passed for `pc'.  */
+      insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
+                                                (bfd_vma) 0);
+      if (insert_errmsg != NULL)
+        continue;
 
 
-      /* Try the next entry.  */
+      /* It is up to the caller to actually output the insn and any
+         queued relocs.  */
+      return insn;
     }
 
     }
 
-  /* FIXME: We can return a better error message than this.
-     Need to track why it failed and pick the right one.  */
   {
   {
-    static char errbuf[100];
-    if (strlen (start) > 50)
-      /* xgettext:c-format */
-      sprintf (errbuf, _("bad instruction `%.50s...'"), start);
-    else 
-      /* xgettext:c-format */
-      sprintf (errbuf, _("bad instruction `%.50s'"), start);
-      
+    static char errbuf[150];
+    const char *tmp_errmsg;
+#ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
+#define be_verbose 1
+#else
+#define be_verbose 0
+#endif
+
+    if (be_verbose)
+      {
+       /* 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)
+         /* xgettext:c-format */
+         sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
+       else
+         /* xgettext:c-format */
+         sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
+      }
+    else
+      {
+       if (strlen (start) > 50)
+         /* xgettext:c-format */
+         sprintf (errbuf, _("bad instruction `%.50s...'"), start);
+       else
+         /* xgettext:c-format */
+         sprintf (errbuf, _("bad instruction `%.50s'"), start);
+      }
+
     *errmsg = errbuf;
     return NULL;
   }
 }
     *errmsg = errbuf;
     return NULL;
   }
 }
-\f
-#if 0 /* This calls back to GAS which we can't do without care.  */
-
-/* Record each member of OPVALS in the assembler's symbol table.
-   This lets GAS parse registers for us.
-   ??? Interesting idea but not currently used.  */
-
-/* Record each member of OPVALS in the assembler's symbol table.
-   FIXME: Not currently used.  */
-
-void
-fr30_cgen_asm_hash_keywords (od, opvals)
-     CGEN_OPCODE_DESC od;
-     CGEN_KEYWORD * opvals;
-{
-  CGEN_KEYWORD_SEARCH search = cgen_keyword_search_init (opvals, NULL);
-  const CGEN_KEYWORD_ENTRY * ke;
-
-  while ((ke = cgen_keyword_search_next (& search)) != NULL)
-    {
-#if 0 /* Unnecessary, should be done in the search routine.  */
-      if (! fr30_cgen_opval_supported (ke))
-       continue;
-#endif
-      cgen_asm_record_register (od, ke->name, ke->value);
-    }
-}
-
-#endif /* 0 */
This page took 0.0515370000000001 seconds and 4 git commands to generate.