Automatic date update in version.in
[deliverable/binutils-gdb.git] / opcodes / fr30-asm.c
index 959910a46cf350964286179a119d288043293c37..d3be9ed7553ba3c7516b3530bcfc5889f290c68e 100644 (file)
+/* 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
-
-static const char * insert_normal
-     PARAMS ((CGEN_OPCODE_DESC, long, unsigned int, int, int, 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
+parse_register_number (const char **strp)
+{
+  int regno;
+
+  if (**strp < '0' || **strp > '9')
+    return -1; /* Error.  */
+  regno = **strp - '0';
+  ++*strp;
+
+  if (**strp >= '0' && **strp <= '9')
+    {
+      regno = regno * 10 + (**strp - '0');
+      ++*strp;
+    }
+
+  return regno;
+}
 
 static const char *
 
 static const char *
-parse_reglist_low (od, strp, opindex, valuep)
-     CGEN_OPCODE_DESC od;
-     const char **strp;
-     int opindex;
-     unsigned long *valuep;
+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.  */
 {
   *valuep = 0;
   while (**strp && **strp != ')')
     {
 {
   *valuep = 0;
   while (**strp && **strp != ')')
     {
+      int regno;
+
+      if (**strp != 'R' && **strp != 'r')
+       break;
       ++*strp;
       ++*strp;
+
+      regno = parse_register_number (strp);
+      if (regno == -1)
+       return _("Register number is not valid");
+      if (regno > 7 && !high_low)
+       return _("Register must be between r0 and r7");
+      if (regno < 8 && high_low)
+       return _("Register must be between r8 and r15");
+
+      if (high_low)
+       regno -= 8;
+
+      if (load_store) /* Mask is reversed for store.  */
+       *valuep |= 0x80 >> regno;
+      else
+       *valuep |= 1 << regno;
+
+      if (**strp == ',')
+       {
+         if (*(*strp + 1) == ')')
+           break;
+         ++*strp;
+       }
     }
 
     }
 
-  if (!*strp)
-    return "Register list is not valid";
+  if (!*strp || **strp != ')')
+    return _("Register list is not valid");
 
   return NULL;
 }
 
 static const char *
 
   return NULL;
 }
 
 static const char *
-parse_reglist_hi (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_reglist_low (od, strp, opindex, valuep);
+  return parse_register_list (cd, strp, opindex, valuep,
+                             0 /* Low.  */, 0 /* Load.  */);
+}
+
+static const char *
+parse_hi_register_list_ld (CGEN_CPU_DESC cd,
+                          const char **strp,
+                          int opindex,
+                          unsigned long *valuep)
+{
+  return parse_register_list (cd, strp, opindex, valuep,
+                             1 /* High.  */, 0 /* Load.  */);
+}
+
+static const char *
+parse_low_register_list_st (CGEN_CPU_DESC cd,
+                           const char **strp,
+                           int opindex,
+                           unsigned long *valuep)
+{
+  return parse_register_list (cd, strp, opindex, valuep,
+                             0 /* Low.  */, 1 /* Store.  */);
+}
+
+static const char *
+parse_hi_register_list_st (CGEN_CPU_DESC cd,
+                          const char **strp,
+                          int opindex,
+                          unsigned long *valuep)
+{
+  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
@@ -98,621 +174,287 @@ parse_reglist_hi (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);
-      break;
-    case FR30_OPERAND_PS :
-      errmsg = cgen_parse_keyword (od, strp, & fr30_cgen_opval_h_ps, & fields->f_nil);
-      break;
-    case FR30_OPERAND_U4 :
-      errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_U4, &fields->f_u4);
-      break;
-    case FR30_OPERAND_U4C :
-      errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_U4C, &fields->f_u4c);
-      break;
-    case FR30_OPERAND_M4 :
-      errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_M4, &fields->f_m4);
-      break;
-    case FR30_OPERAND_U8 :
-      errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_U8, &fields->f_u8);
-      break;
-    case FR30_OPERAND_I8 :
-      errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_I8, &fields->f_i8);
-      break;
-    case FR30_OPERAND_UDISP6 :
-      errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_UDISP6, &fields->f_udisp6);
-      break;
-    case FR30_OPERAND_DISP8 :
-      errmsg = cgen_parse_signed_integer (od, strp, FR30_OPERAND_DISP8, &fields->f_disp8);
-      break;
-    case FR30_OPERAND_DISP9 :
-      errmsg = cgen_parse_signed_integer (od, strp, FR30_OPERAND_DISP9, &fields->f_disp9);
-      break;
-    case FR30_OPERAND_DISP10 :
-      errmsg = cgen_parse_signed_integer (od, strp, FR30_OPERAND_DISP10, &fields->f_disp10);
-      break;
-    case FR30_OPERAND_S10 :
-      errmsg = cgen_parse_signed_integer (od, strp, FR30_OPERAND_S10, &fields->f_s10);
-      break;
-    case FR30_OPERAND_U10 :
-      errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_U10, &fields->f_u10);
-      break;
-    case FR30_OPERAND_I32 :
-      errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_I32, &fields->f_i32);
-      break;
-    case FR30_OPERAND_DIR8 :
-      errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_DIR8, &fields->f_dir8);
-      break;
-    case FR30_OPERAND_DIR9 :
-      errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_DIR9, &fields->f_dir9);
+      errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_h_r15, & junk);
       break;
       break;
-    case FR30_OPERAND_DIR10 :
-      errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_DIR10, &fields->f_dir10);
-      break;
-    case FR30_OPERAND_LABEL9 :
-      errmsg = cgen_parse_signed_integer (od, strp, FR30_OPERAND_LABEL9, &fields->f_rel9);
-      break;
-    case FR30_OPERAND_LABEL12 :
-      errmsg = cgen_parse_signed_integer (od, strp, FR30_OPERAND_LABEL12, &fields->f_rel12);
-      break;
-    case FR30_OPERAND_REGLIST_LOW :
-      errmsg = parse_reglist_low (od, strp, FR30_OPERAND_REGLIST_LOW, &fields->f_reglist_low);
-      break;
-    case FR30_OPERAND_REGLIST_HI :
-      errmsg = parse_reglist_hi (od, strp, FR30_OPERAND_REGLIST_HI, &fields->f_reglist_hi);
-      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;
-
-  switch (opindex)
-    {
     case FR30_OPERAND_RI :
     case FR30_OPERAND_RI :
-      errmsg = insert_normal (od, fields->f_Ri, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
-      break;
-    case FR30_OPERAND_RJ :
-      errmsg = insert_normal (od, fields->f_Rj, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
+      errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_gr_names, & fields->f_Ri);
       break;
     case FR30_OPERAND_RIC :
       break;
     case FR30_OPERAND_RIC :
-      errmsg = insert_normal (od, fields->f_Ric, 0|(1<<CGEN_OPERAND_UNSIGNED), 28, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
-      break;
-    case FR30_OPERAND_RJC :
-      errmsg = insert_normal (od, fields->f_Rjc, 0|(1<<CGEN_OPERAND_UNSIGNED), 24, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
+      errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_gr_names, & fields->f_Ric);
       break;
       break;
-    case FR30_OPERAND_CRI :
-      errmsg = insert_normal (od, fields->f_CRi, 0|(1<<CGEN_OPERAND_UNSIGNED), 28, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
+    case FR30_OPERAND_RJ :
+      errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_gr_names, & fields->f_Rj);
       break;
       break;
-    case FR30_OPERAND_CRJ :
-      errmsg = insert_normal (od, fields->f_CRj, 0|(1<<CGEN_OPERAND_UNSIGNED), 24, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
+    case FR30_OPERAND_RJC :
+      errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_gr_names, & fields->f_Rjc);
       break;
     case FR30_OPERAND_RS1 :
       break;
     case FR30_OPERAND_RS1 :
-      errmsg = insert_normal (od, fields->f_Rs1, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
+      errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_dr_names, & fields->f_Rs1);
       break;
     case FR30_OPERAND_RS2 :
       break;
     case FR30_OPERAND_RS2 :
-      errmsg = insert_normal (od, fields->f_Rs2, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
+      errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_dr_names, & fields->f_Rs2);
       break;
       break;
-    case FR30_OPERAND_R13 :
-      errmsg = insert_normal (od, fields->f_nil, 0, 0, 0, CGEN_FIELDS_BITSIZE (fields), buffer);
+    case FR30_OPERAND_CC :
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_CC, (unsigned long *) (& fields->f_cc));
       break;
       break;
-    case FR30_OPERAND_R14 :
-      errmsg = insert_normal (od, fields->f_nil, 0, 0, 0, CGEN_FIELDS_BITSIZE (fields), buffer);
+    case FR30_OPERAND_CCC :
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_CCC, (unsigned long *) (& fields->f_ccc));
       break;
       break;
-    case FR30_OPERAND_R15 :
-      errmsg = insert_normal (od, fields->f_nil, 0, 0, 0, CGEN_FIELDS_BITSIZE (fields), buffer);
+    case FR30_OPERAND_DIR10 :
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_DIR10, (unsigned long *) (& fields->f_dir10));
       break;
       break;
-    case FR30_OPERAND_PS :
-      errmsg = insert_normal (od, fields->f_nil, 0, 0, 0, CGEN_FIELDS_BITSIZE (fields), buffer);
+    case FR30_OPERAND_DIR8 :
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_DIR8, (unsigned long *) (& fields->f_dir8));
       break;
       break;
-    case FR30_OPERAND_U4 :
-      errmsg = insert_normal (od, fields->f_u4, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 8, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
+    case FR30_OPERAND_DIR9 :
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_DIR9, (unsigned long *) (& fields->f_dir9));
       break;
       break;
-    case FR30_OPERAND_U4C :
-      errmsg = insert_normal (od, fields->f_u4c, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
+    case FR30_OPERAND_DISP10 :
+      errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_DISP10, (long *) (& fields->f_disp10));
       break;
       break;
-    case FR30_OPERAND_M4 :
-      {
-        long value = fields->f_m4;
-        value = ((value) & (15));
-        errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 8, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
-      }
+    case FR30_OPERAND_DISP8 :
+      errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_DISP8, (long *) (& fields->f_disp8));
       break;
       break;
-    case FR30_OPERAND_U8 :
-      errmsg = insert_normal (od, fields->f_u8, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
+    case FR30_OPERAND_DISP9 :
+      errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_DISP9, (long *) (& fields->f_disp9));
       break;
       break;
-    case FR30_OPERAND_I8 :
-      errmsg = insert_normal (od, fields->f_i8, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 4, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
+    case FR30_OPERAND_I20 :
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_I20, (unsigned long *) (& fields->f_i20));
       break;
       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), 8, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
-      }
+    case FR30_OPERAND_I32 :
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_I32, (unsigned long *) (& fields->f_i32));
       break;
       break;
-    case FR30_OPERAND_DISP8 :
-      errmsg = insert_normal (od, fields->f_disp8, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), 4, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
+    case FR30_OPERAND_I8 :
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_I8, (unsigned long *) (& fields->f_i8));
       break;
       break;
-    case FR30_OPERAND_DISP9 :
+    case FR30_OPERAND_LABEL12 :
       {
       {
-        long value = fields->f_disp9;
-        value = ((int) (value) >> (1));
-        errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), 4, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
+        bfd_vma value = 0;
+        errmsg = cgen_parse_address (cd, strp, FR30_OPERAND_LABEL12, 0, NULL,  & value);
+        fields->f_rel12 = value;
       }
       break;
       }
       break;
-    case FR30_OPERAND_DISP10 :
+    case FR30_OPERAND_LABEL9 :
       {
       {
-        long value = fields->f_disp10;
-        value = ((int) (value) >> (2));
-        errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), 4, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
+        bfd_vma value = 0;
+        errmsg = cgen_parse_address (cd, strp, FR30_OPERAND_LABEL9, 0, NULL,  & value);
+        fields->f_rel9 = value;
       }
       break;
       }
       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)|(1<<CGEN_OPERAND_SIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
-      }
+    case FR30_OPERAND_M4 :
+      errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_M4, (long *) (& fields->f_m4));
       break;
       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), 8, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
-      }
+    case FR30_OPERAND_PS :
+      errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_h_ps, & junk);
       break;
       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, 32, CGEN_FIELDS_BITSIZE (fields), buffer);
+    case FR30_OPERAND_REGLIST_HI_LD :
+      errmsg = parse_hi_register_list_ld (cd, strp, FR30_OPERAND_REGLIST_HI_LD, (unsigned long *) (& fields->f_reglist_hi_ld));
       break;
       break;
-    case FR30_OPERAND_DIR8 :
-      errmsg = insert_normal (od, fields->f_dir8, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
+    case FR30_OPERAND_REGLIST_HI_ST :
+      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_DIR9 :
-      {
-        long value = fields->f_dir9;
-        value = ((unsigned int) (value) >> (1));
-        errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), 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_DIR10 :
-      {
-        long value = fields->f_dir10;
-        value = ((unsigned int) (value) >> (2));
-        errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), 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_LABEL9 :
-      {
-        long value = fields->f_rel9;
-        value = ((int) (((value) - (((pc) & (-2))))) >> (1));
-        errmsg = insert_normal (od, value, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR)|(1<<CGEN_OPERAND_SIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
-      }
+    case FR30_OPERAND_S10 :
+      errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_S10, (long *) (& fields->f_s10));
       break;
       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_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR)|(1<<CGEN_OPERAND_SIGNED), 5, 11, CGEN_FIELDS_BITSIZE (fields), buffer);
-      }
+    case FR30_OPERAND_U10 :
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_U10, (unsigned long *) (& fields->f_u10));
       break;
       break;
-    case FR30_OPERAND_REGLIST_LOW :
-      errmsg = insert_normal (od, fields->f_reglist_low, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
+    case FR30_OPERAND_U4 :
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_U4, (unsigned long *) (& fields->f_u4));
       break;
       break;
-    case FR30_OPERAND_REGLIST_HI :
-      errmsg = insert_normal (od, fields->f_reglist_hi, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
+    case FR30_OPERAND_U4C :
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_U4C, (unsigned long *) (& fields->f_u4c));
       break;
       break;
-    case FR30_OPERAND_CC :
-      errmsg = insert_normal (od, fields->f_cc, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, CGEN_FIELDS_BITSIZE (fields), buffer);
+    case FR30_OPERAND_U8 :
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_U8, (unsigned long *) (& fields->f_u8));
       break;
       break;
-    case FR30_OPERAND_CCC :
-      errmsg = insert_normal (od, fields->f_ccc, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 16, 8, CGEN_FIELDS_BITSIZE (fields), buffer);
+    case FR30_OPERAND_UDISP6 :
+      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.  */
-
-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;
-
-  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 ();
-    }
-
-  /* Written this way to avoid undefined behaviour.  */
-  mask = (((1L << (length - 1)) - 1) << 1) | 1;
-  if (CGEN_INSN_LSB0_P)
-    shift = start;
-  else
-    shift = (word_length - (start + length));
-  x = (x & ~(mask << shift)) | ((value & mask) << shift);
-
-  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.
+/* Regex construction routine.
 
 
-   ATTRS is a mask of the boolean attributes.
-   START is the starting bit number, architecture origin.
-   LENGTH is the length of VALUE in bits.
-   TOTAL_LENGTH is the total length of the insn.
+   This translates an opcode syntax string into a regex string,
+   by replacing any non-character syntax element (such as an
+   opcode) with the pattern '.*'
 
 
-   The result is an error message or NULL if success.  */
+   It then compiles the regex and stores it in the opcode, for
+   later use by fr30_cgen_assemble_insn
 
 
-/* ??? This duplicates functionality with bfd's howto table and
-   bfd_install_relocation.  */
-/* ??? For architectures where insns can be representable as ints,
-   store insn in `field' struct and add registers, etc. while parsing?  */
-/* ??? This doesn't handle bfd_vma's.  Create another function when
-   necessary.  */
+   Returns NULL for success, an error message for failure.  */
 
 
-static const char *
-insert_normal (od, value, attrs, start, length, total_length, buffer)
-     CGEN_OPCODE_DESC od;
-     long value;
-     unsigned int attrs;
-     int start;
-     int length;
-     int 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;
+  syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
 
 
-  /* Ensure VALUE will fit.  */
-  if ((attrs & CGEN_ATTR_MASK (CGEN_OPERAND_UNSIGNED)) != 0)
-    {
-      unsigned long maxval = mask;
-      if ((unsigned long) value > maxval)
-       {
-         /* xgettext:c-format */
-         sprintf (errbuf,
-                  _("operand out of range (%lu not between 0 and %lu)"),
-                  value, maxval);
-         return errbuf;
-       }
-    }
-  else
-    {
-      long minval = - (1L << (length - 1));
-      long maxval = (1L << (length - 1)) - 1;
-      if (value < minval || value > maxval)
-       {
-         sprintf
-           /* xgettext:c-format */
-           (errbuf, _("operand out of range (%ld not between %ld and %ld)"),
-            value, minval, maxval);
-         return errbuf;
-       }
-    }
-
-#if CGEN_INT_INSN_P
-
-  if (total_length > 32) /* 32 bits in a portable host int */
-    abort ();
-  {
-    int shift;
-
-    if (CGEN_INSN_LSB0_P)
-      shift = start;
-    else
-      shift = total_length - (start + length);
-    *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
-  }
-
-#else
-
-  /* FIXME: unfinished and untested */
-
-  /* The hard case is probably too slow for the normal cases.
-     It's certainly more difficult to understand than the normal case.
-     Thus this is split into two.  The hard case is defined
-     to be when a field straddles a (loosely defined) word boundary
-     (??? which may require target specific help to determine).  */
-
-#if 0 /*wip*/
+  /* Mnemonics come first in the syntax string.  */
+  if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
+    return _("missing mnemonic in syntax string");
+  ++syn;
 
 
-#define HARD_CASE_P 0 /* FIXME:wip */
+  /* 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.  */
 
 
-  if (HARD_CASE_P)
+  /* Copy the literal mnemonic out of the insn.  */
+  for (; *mnem; mnem++)
     {
     {
-      unsigned char *bufp = (unsigned char *) buffer;
-      int insn_length_left = total_length;
+      char c = *mnem;
 
 
-      if (CGEN_INSN_LSB0_P)
+      if (ISALPHA (c))
        {
        {
-         int word_offset = (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG
-                            ? ...
-                            : start / CGEN_BASE_INSN_BITSIZE);
-         bufp += word_offset * (CGEN_BASE_INSN_BITSIZE / 8);
-         if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG)
-         else
-           start -= word_offset * CGEN_BASE_INSN_BITSIZE;
+         *rx++ = '[';
+         *rx++ = TOLOWER (c);
+         *rx++ = TOUPPER (c);
+         *rx++ = ']';
        }
       else
        }
       else
-       {
-         int word_offset = (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG
-                            ? start / CGEN_BASE_INSN_BITSIZE
-                            : ...);
-         bufp += word_offset * (CGEN_BASE_INSN_BITSIZE / 8);
-         if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG)
-           start -= word_offset * CGEN_BASE_INSN_BITSIZE;
-         else
-       }
-
-      /* Loop so we handle a field straddling an insn word boundary
-        (remember, "insn word boundary" is loosely defined here).  */
-
-      while (length > 0)
-       {
-         int this_pass_length = length;
-         int this_pass_start = start;
-         int this_pass_word_length = min (insn_length_left,
-                                          (CGEN_BASE_INSN_BITSIZE == 8
-                                           ? 32
-                                           : CGEN_BASE_INSN_BITSIZE));
-
-         insert_1 (od, value, attrs,
-                   this_pass_start, this_pass_length, this_pass_word_length,
-                   bufp);
-
-         length -= this_pass_length;
-         insn_length_left -= this_pass_word_length;
-         if (???)
-           {
-             value >>= ???;
-             start += ???;
-           }
-         else
-           {
-             value >>= ???;
-             start += ???;
-           }
-         bufp += this_pass_word_length / 8;
-       }
+       *rx++ = c;
     }
     }
-  else
-#endif /* 0 */
-    {
-      unsigned char *bufp = (unsigned char *) buffer;
-
-      if (length > 32)
-       abort ();
 
 
-      /* Adjust start,total_length,bufp to point to the pseudo-word that holds
-        the value.  For example in a 48 bit insn where the value to insert
-        (say an immediate value) is the last 16 bits then fetch_length here
-        would be 16.  To handle a 24 bit insn with an 18 bit immediate,
-        insert_1 handles 24 bits.  */
-
-      if (total_length > 32)
+  /* Copy any remaining literals from the syntax string into the rx.  */
+  for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
+    {
+      if (CGEN_SYNTAX_CHAR_P (* syn))
        {
        {
-         int needed_width = start % 8 + length;
-         int fetch_length = (needed_width <= 8 ? 8
-                             : needed_width <= 16 ? 16
-                             : 32);
+         char c = CGEN_SYNTAX_CHAR (* syn);
 
 
-         if (CGEN_INSN_LSB0_P)
+         switch (c)
            {
            {
-             if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG)
-               {
-                 abort (); /* wip */
-               }
-             else
-               {
-                 int offset = start & ~7;
+             /* 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;
 
 
-                 bufp += offset / 8;
-                 start -= offset;
-                 total_length = fetch_length;
-               }
-           }
-         else
-           {
-             if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG)
+           default:
+             if (ISALPHA (c))
                {
                {
-                 int offset = start & ~7;
-
-                 bufp += offset / 8;
-                 start -= offset;
-                 total_length = fetch_length;
+                 *rx++ = '[';
+                 *rx++ = TOLOWER (c);
+                 *rx++ = TOUPPER (c);
+                 *rx++ = ']';
                }
              else
                }
              else
-               {
-                 abort (); /* wip */
-               }
+               *rx++ = c;
+             break;
            }
        }
            }
        }
-
-      insert_1 (od, value, start, length, total_length, bufp);
+      else
+       {
+         /* Replace non-syntax fields with globs.  */
+         *rx++ = '.';
+         *rx++ = '*';
+       }
     }
 
     }
 
-#endif /* ! CGEN_INT_INSN_P */
+  /* Trailing whitespace ok.  */
+  * rx++ = '[';
+  * rx++ = ' ';
+  * rx++ = '\t';
+  * rx++ = ']';
+  * rx++ = '*';
 
 
-  return NULL;
+  /* 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);
+
+  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.
 
 \f
 /* Default insn parser.
 
@@ -725,21 +467,20 @@ insert_normal (od, value, attrs, start, length, total_length, buffer)
    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;
@@ -750,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
@@ -777,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;
 
@@ -807,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')
@@ -825,62 +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_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 */
-
-  /* ??? Rather than scanning the syntax string again, we could store
-     in `fields' a null terminated list of the fields that are present.  */
-
-  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.
@@ -895,107 +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;
 
-      /* Record a default length for the insn.  This will get set to the
-        correct value while parsing.  */
-      /* FIXME: wip */
+      /* 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);
 
       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.050464 seconds and 4 git commands to generate.