Add support to GDB for the Renesas rl78 architecture.
[external/binutils.git] / opcodes / frv-asm.c
index 538ed2d..3da8261 100644 (file)
@@ -1,26 +1,28 @@
 /* Assembler interface for targets using CGEN. -*- C -*-
    CGEN: Cpu tools GENerator
 
-THIS FILE IS MACHINE GENERATED WITH CGEN.
-- the resultant file is machine generated, cgen-asm.in isn't
+   THIS FILE IS MACHINE GENERATED WITH CGEN.
+   - the resultant file is machine generated, cgen-asm.in isn't
 
-Copyright 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2005, 2007, 2008, 2010
+   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.,
+   51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, 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.,
-59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 /* ??? Eventually more and more of this stuff can go to cpu-independent files.
    Keep that in mind.  */
@@ -43,34 +45,156 @@ along with this program; if not, write to the Free Software Foundation, Inc.,
 #define max(a,b) ((a) > (b) ? (a) : (b))
 
 static const char * parse_insn_normal
-     PARAMS ((CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *));
+  (CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *);
 \f
 /* -- assembler routines inserted here.  */
 
 /* -- asm.c */
-static const char * parse_ulo16
-  PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
-static const char * parse_uslo16
-  PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
-static const char * parse_uhi16
-  PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
-static long parse_register_number
-  PARAMS ((const char **));
-static const char * parse_spr
-  PARAMS ((CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *));
-static const char * parse_d12
-  PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
-static const char * parse_s12
-  PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
-static const char * parse_u12
-  PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
+inline static const char *
+parse_symbolic_address (CGEN_CPU_DESC cd,
+                       const char **strp,
+                       int opindex,
+                       int opinfo,
+                       enum cgen_parse_operand_result *resultp,
+                       bfd_vma *valuep)
+{
+  enum cgen_parse_operand_result result_type;
+  const char *errmsg = (* cd->parse_operand_fn)
+    (cd, CGEN_PARSE_OPERAND_SYMBOLIC, strp, opindex, opinfo,
+     &result_type, valuep);
+
+  if (errmsg == NULL
+      && result_type != CGEN_PARSE_OPERAND_RESULT_QUEUED)
+    return "symbolic expression required";
+
+  if (resultp)
+    *resultp = result_type;
+
+  return errmsg;
+}
+
+static const char *
+parse_ldd_annotation (CGEN_CPU_DESC cd,
+                     const char **strp,
+                     int opindex,
+                     unsigned long *valuep)
+{
+  const char *errmsg;
+  enum cgen_parse_operand_result result_type;
+  bfd_vma value;
+
+  if (**strp == '#' || **strp == '%')
+    {
+      if (strncasecmp (*strp + 1, "tlsdesc(", 8) == 0)
+       {
+         *strp += 9;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_TLSDESC_RELAX,
+                                          &result_type, &value);
+         if (**strp != ')')
+           return "missing ')'";
+         if (valuep)
+           *valuep = value;
+         ++*strp;
+         if (errmsg)
+           return errmsg;
+       }
+    }
+  
+  while (**strp == ' ' || **strp == '\t')
+    ++*strp;
+  
+  if (**strp != '@')
+    return "missing `@'";
+
+  ++*strp;
+
+  return NULL;
+}
+
+static const char *
+parse_call_annotation (CGEN_CPU_DESC cd,
+                      const char **strp,
+                      int opindex,
+                      unsigned long *valuep)
+{
+  const char *errmsg;
+  enum cgen_parse_operand_result result_type;
+  bfd_vma value;
+
+  if (**strp == '#' || **strp == '%')
+    {
+      if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0)
+       {
+         *strp += 11;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_GETTLSOFF_RELAX,
+                                          &result_type, &value);
+         if (**strp != ')')
+           return "missing ')'";
+         if (valuep)
+           *valuep = value;
+         ++*strp;
+         if (errmsg)
+           return errmsg;
+       }
+    }
+  
+  while (**strp == ' ' || **strp == '\t')
+    ++*strp;
+  
+  if (**strp != '@')
+    return "missing `@'";
+
+  ++*strp;
+
+  return NULL;
+}
+
+static const char *
+parse_ld_annotation (CGEN_CPU_DESC cd,
+                    const char **strp,
+                    int opindex,
+                    unsigned long *valuep)
+{
+  const char *errmsg;
+  enum cgen_parse_operand_result result_type;
+  bfd_vma value;
+
+  if (**strp == '#' || **strp == '%')
+    {
+      if (strncasecmp (*strp + 1, "tlsoff(", 7) == 0)
+       {
+         *strp += 8;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_TLSOFF_RELAX,
+                                          &result_type, &value);
+         if (**strp != ')')
+           return "missing ')'";
+         if (valuep)
+           *valuep = value;
+         ++*strp;
+         if (errmsg)
+           return errmsg;
+       }
+    }
+  
+  while (**strp == ' ' || **strp == '\t')
+    ++*strp;
+  
+  if (**strp != '@')
+    return "missing `@'";
+
+  ++*strp;
+
+  return NULL;
+}
 
 static const char *
-parse_ulo16 (cd, strp, opindex, valuep)
-     CGEN_CPU_DESC cd;
-     const char **strp;
-     int opindex;
-     unsigned long *valuep;
+parse_ulo16 (CGEN_CPU_DESC cd,
+            const char **strp,
+            int opindex,
+            unsigned long *valuep)
 {
   const char *errmsg;
   enum cgen_parse_operand_result result_type;
@@ -82,7 +206,7 @@ parse_ulo16 (cd, strp, opindex, valuep)
        {
          *strp += 4;
          errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
-                                      &result_type, &value);
+                                      & result_type, & value);
          if (**strp != ')')
            return "missing `)'";
          ++*strp;
@@ -95,27 +219,108 @@ parse_ulo16 (cd, strp, opindex, valuep)
       if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
        {
          *strp += 9;
-         errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELLO,
-                                      &result_type, &value);
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_GPRELLO,
+                                          & result_type, & value);
+         if (**strp != ')')
+           return "missing ')'";
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
+      else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
+       {
+         *strp += 7;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_GOTLO,
+                                          & result_type, & value);
+         if (**strp != ')')
+           return "missing ')'";
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
+      else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
+       {
+         *strp += 15;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_FUNCDESC_GOTLO,
+                                          & result_type, & value);
+         if (**strp != ')')
+           return "missing ')'";
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
+      else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
+       {
+         *strp += 10;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_GOTOFFLO,
+                                          & result_type, & value);
+         if (**strp != ')')
+           return "missing ')'";
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
+      else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
+       {
+         *strp += 18;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
+                                          & result_type, & value);
+         if (**strp != ')')
+           return "missing ')'";
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
+      else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0)
+       {
+         *strp += 14;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_GOTTLSDESCLO,
+                                          & result_type, & value);
+         if (**strp != ')')
+           return "missing ')'";
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
+      else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0)
+       {
+         *strp += 11;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_TLSMOFFLO,
+                                          & result_type, & value);
+         if (**strp != ')')
+           return "missing ')'";
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
+      else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0)
+       {
+         *strp += 13;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_GOTTLSOFFLO,
+                                          & result_type, & value);
          if (**strp != ')')
            return "missing ')'";
          ++*strp;
-         if (errmsg == NULL
-             && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
-           value >>= 16;
          *valuep = value;
          return errmsg;
        }
     }
-  return cgen_parse_signed_integer (cd, strp, opindex, valuep);
+  return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
 }
 
 static const char *
-parse_uslo16 (cd, strp, opindex, valuep)
-     CGEN_CPU_DESC cd;
-     const char **strp;
-     int opindex;
-     unsigned long *valuep;
+parse_uslo16 (CGEN_CPU_DESC cd,
+             const char **strp,
+             int opindex,
+             signed long *valuep)
 {
   const char *errmsg;
   enum cgen_parse_operand_result result_type;
@@ -127,7 +332,7 @@ parse_uslo16 (cd, strp, opindex, valuep)
        {
          *strp += 4;
          errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
-                                      &result_type, &value);
+                                      & result_type, & value);
          if (**strp != ')')
            return "missing `)'";
          ++*strp;
@@ -140,27 +345,108 @@ parse_uslo16 (cd, strp, opindex, valuep)
       else if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
        {
          *strp += 9;
-         errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELLO,
-                                      &result_type, &value);
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_GPRELLO,
+                                          & result_type, & value);
+         if (**strp != ')')
+           return "missing ')'";
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
+      else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
+       {
+         *strp += 7;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_GOTLO,
+                                          & result_type, & value);
+         if (**strp != ')')
+           return "missing ')'";
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
+      else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
+       {
+         *strp += 15;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_FUNCDESC_GOTLO,
+                                          & result_type, & value);
+         if (**strp != ')')
+           return "missing ')'";
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
+      else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
+       {
+         *strp += 10;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_GOTOFFLO,
+                                          & result_type, & value);
+         if (**strp != ')')
+           return "missing ')'";
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
+      else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
+       {
+         *strp += 18;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
+                                          & result_type, & value);
+         if (**strp != ')')
+           return "missing ')'";
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
+      else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0)
+       {
+         *strp += 14;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_GOTTLSDESCLO,
+                                          & result_type, & value);
+         if (**strp != ')')
+           return "missing ')'";
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
+      else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0)
+       {
+         *strp += 11;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_TLSMOFFLO,
+                                          & result_type, & value);
+         if (**strp != ')')
+           return "missing ')'";
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
+      else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0)
+       {
+         *strp += 13;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_GOTTLSOFFLO,
+                                          & result_type, & value);
          if (**strp != ')')
            return "missing ')'";
          ++*strp;
-         if (errmsg == NULL
-             && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
-           value &= 0xffff;
          *valuep = value;
          return errmsg;
        }
     }
-  return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
+  return cgen_parse_signed_integer (cd, strp, opindex, valuep);
 }
 
 static const char *
-parse_uhi16 (cd, strp, opindex, valuep)
-     CGEN_CPU_DESC cd;
-     const char **strp;
-     int opindex;
-     unsigned long *valuep;
+parse_uhi16 (CGEN_CPU_DESC cd,
+            const char **strp,
+            int opindex,
+            unsigned long *valuep)
 {
   const char *errmsg;
   enum cgen_parse_operand_result result_type;
@@ -172,27 +458,116 @@ parse_uhi16 (cd, strp, opindex, valuep)
        {
          *strp += 4;
          errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_HI16,
-                                      &result_type, &value);
+                                      & result_type, & value);
          if (**strp != ')')
            return "missing `)'";
          ++*strp;
          if (errmsg == NULL
              && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
-           value >>= 16;
+           {
+             /* If value is wider than 32 bits then be
+                careful about how we extract bits 16-31.  */
+             if (sizeof (value) > 4)
+               value &= (((bfd_vma)1 << 16) << 16) - 1;
+
+             value >>= 16;
+           }
          *valuep = value;
          return errmsg;
        }
       else if (strncasecmp (*strp + 1, "gprelhi(", 8) == 0)
        {
          *strp += 9;
-         errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELHI,
-                                      &result_type, &value);
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_GPRELHI,
+                                          & result_type, & value);
+         if (**strp != ')')
+           return "missing ')'";
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
+      else if (strncasecmp (*strp + 1, "gothi(", 6) == 0)
+       {
+         *strp += 7;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_GOTHI,
+                                          & result_type, & value);
+         if (**strp != ')')
+           return "missing ')'";
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
+      else if (strncasecmp (*strp + 1, "gotfuncdeschi(", 14) == 0)
+       {
+         *strp += 15;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_FUNCDESC_GOTHI,
+                                          & result_type, & value);
+         if (**strp != ')')
+           return "missing ')'";
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
+      else if (strncasecmp (*strp + 1, "gotoffhi(", 9) == 0)
+       {
+         *strp += 10;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_GOTOFFHI,
+                                          & result_type, & value);
+         if (**strp != ')')
+           return "missing ')'";
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
+      else if (strncasecmp (*strp + 1, "gotofffuncdeschi(", 17) == 0)
+       {
+         *strp += 18;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_FUNCDESC_GOTOFFHI,
+                                          & result_type, & value);
+         if (**strp != ')')
+           return "missing ')'";
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
+      else if (strncasecmp (*strp + 1, "gottlsdeschi(", 13) == 0)
+       {
+         *strp += 14;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_GOTTLSDESCHI,
+                                          &result_type, &value);
+         if (**strp != ')')
+           return "missing ')'";
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
+      else if (strncasecmp (*strp + 1, "tlsmoffhi(", 10) == 0)
+       {
+         *strp += 11;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_TLSMOFFHI,
+                                          & result_type, & value);
+         if (**strp != ')')
+           return "missing ')'";
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
+      else if (strncasecmp (*strp + 1, "gottlsoffhi(", 12) == 0)
+       {
+         *strp += 13;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_GOTTLSOFFHI,
+                                          & result_type, & value);
          if (**strp != ')')
            return "missing ')'";
          ++*strp;
-         if (errmsg == NULL
-             && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
-           value >>= 16;
          *valuep = value;
          return errmsg;
        }
@@ -201,10 +576,10 @@ parse_uhi16 (cd, strp, opindex, valuep)
 }
 
 static long
-parse_register_number (strp)
-     const char **strp;
+parse_register_number (const char **strp)
 {
   int regno;
+
   if (**strp < '0' || **strp > '9')
     return -1; /* error */
 
@@ -216,11 +591,10 @@ parse_register_number (strp)
 }
 
 static const char *
-parse_spr (cd, strp, table, valuep)
-     CGEN_CPU_DESC cd;
-     const char **strp;
-     CGEN_KEYWORD * table;
-     long *valuep;
+parse_spr (CGEN_CPU_DESC cd,
+          const char **strp,
+          CGEN_KEYWORD * table,
+          long *valuep)
 {
   const char *save_strp;
   long regno;
@@ -231,10 +605,10 @@ parse_spr (cd, strp, table, valuep)
       *strp += 4;
       regno = parse_register_number (strp);
       if (**strp != ']')
-        return "missing `]'";
+        return _("missing `]'");
       ++*strp;
       if (! spr_valid (regno))
-       return "Special purpose register number is out of range";
+       return _("Special purpose register number is out of range");
       *valuep = regno;
       return NULL;
     }
@@ -244,7 +618,7 @@ parse_spr (cd, strp, table, valuep)
   if (regno != -1)
     {
       if (! spr_valid (regno))
-       return "Special purpose register number is out of range";
+       return _("Special purpose register number is out of range");
       *valuep = regno;
       return NULL;
     }
@@ -254,11 +628,10 @@ parse_spr (cd, strp, table, valuep)
 }
 
 static const char *
-parse_d12 (cd, strp, opindex, valuep)
-     CGEN_CPU_DESC cd;
-     const char **strp;
-     int opindex;
-     long *valuep;
+parse_d12 (CGEN_CPU_DESC cd,
+          const char **strp,
+          int opindex,
+          long *valuep)
 {
   const char *errmsg;
   enum cgen_parse_operand_result result_type;
@@ -270,56 +643,224 @@ parse_d12 (cd, strp, opindex, valuep)
       if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
         {
           *strp += 9;
-          errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPREL12,
-                                       &result_type, &value);
+          errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_GPREL12,
+                                          & result_type, & value);
           if (**strp != ')')
             return "missing `)'";
           ++*strp;
           *valuep = value;
           return errmsg;
         }
+      else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
+       {
+         *strp += 7;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_GOT12,
+                                          & result_type, & value);
+         if (**strp != ')')
+           return "missing ')'";
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
+      else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
+       {
+         *strp += 15;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_FUNCDESC_GOT12,
+                                          & result_type, & value);
+         if (**strp != ')')
+           return "missing ')'";
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
+      else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
+       {
+         *strp += 10;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_GOTOFF12,
+                                          & result_type, & value);
+         if (**strp != ')')
+           return "missing ')'";
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
+      else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
+       {
+         *strp += 18;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
+                                          & result_type, & value);
+         if (**strp != ')')
+           return "missing ')'";
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
+      else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0)
+       {
+         *strp += 14;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_GOTTLSDESC12,
+                                          & result_type, & value);
+         if (**strp != ')')
+           return "missing ')'";
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
+      else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0)
+       {
+         *strp += 11;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_TLSMOFF12,
+                                          & result_type, & value);
+         if (**strp != ')')
+           return "missing ')'";
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
+      else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0)
+       {
+         *strp += 13;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_GOTTLSOFF12,
+                                          & result_type, & value);
+         if (**strp != ')')
+           return "missing ')'";
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
     }
   return cgen_parse_signed_integer (cd, strp, opindex, valuep);
 }
 
 static const char *
-parse_s12 (cd, strp, opindex, valuep)
-     CGEN_CPU_DESC cd;
-     const char **strp;
-     int opindex;
-     long *valuep;
+parse_s12 (CGEN_CPU_DESC cd,
+          const char **strp,
+          int opindex,
+          long *valuep)
 {
   const char *errmsg;
   enum cgen_parse_operand_result result_type;
   bfd_vma value;
  
   /* Check for small data reference.  */
-  if ((**strp == '#' || **strp == '%')
-      && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
-    {
-      *strp += 9;
-      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPREL12,
-                                    &result_type, &value);
-      if (**strp != ')')
-        return "missing `)'";
-      ++*strp;
-      *valuep = value;
-      return errmsg;
-    }
-  else
+  if (**strp == '#' || **strp == '%')
     {
-      if (**strp == '#')
-        ++*strp;
-      return cgen_parse_signed_integer (cd, strp, opindex, valuep);
+      if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
+       {
+         *strp += 9;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_GPREL12,
+                                          & result_type, & value);
+         if (**strp != ')')
+           return "missing `)'";
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
+      else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
+       {
+         *strp += 7;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_GOT12,
+                                          & result_type, & value);
+         if (**strp != ')')
+           return "missing ')'";
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
+      else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
+       {
+         *strp += 15;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_FUNCDESC_GOT12,
+                                          & result_type, & value);
+         if (**strp != ')')
+           return "missing ')'";
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
+      else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
+       {
+         *strp += 10;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_GOTOFF12,
+                                          & result_type, & value);
+         if (**strp != ')')
+           return "missing ')'";
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
+      else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
+       {
+         *strp += 18;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
+                                          & result_type, & value);
+         if (**strp != ')')
+           return "missing ')'";
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
+      else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0)
+       {
+         *strp += 14;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_GOTTLSDESC12,
+                                          & result_type, & value);
+         if (**strp != ')')
+           return "missing ')'";
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
+      else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0)
+       {
+         *strp += 11;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_TLSMOFF12,
+                                          & result_type, & value);
+         if (**strp != ')')
+           return "missing ')'";
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
+      else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0)
+       {
+         *strp += 13;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_GOTTLSOFF12,
+                                          & result_type, & value);
+         if (**strp != ')')
+           return "missing ')'";
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
     }
+
+  if (**strp == '#')
+    ++*strp;
+  return cgen_parse_signed_integer (cd, strp, opindex, valuep);
 }
 
 static const char *
-parse_u12 (cd, strp, opindex, valuep)
-     CGEN_CPU_DESC cd;
-     const char **strp;
-     int opindex;
-     long *valuep;
+parse_u12 (CGEN_CPU_DESC cd,
+          const char **strp,
+          int opindex,
+          long *valuep)
 {
   const char *errmsg;
   enum cgen_parse_operand_result result_type;
@@ -330,8 +871,9 @@ parse_u12 (cd, strp, opindex, valuep)
       && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
     {
       *strp += 9;
-      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELU12,
-                                    &result_type, &value);
+      errmsg = parse_symbolic_address (cd, strp, opindex,
+                                      BFD_RELOC_FRV_GPRELU12,
+                                      & result_type, & value);
       if (**strp != ')')
         return "missing `)'";
       ++*strp;
@@ -346,10 +888,101 @@ parse_u12 (cd, strp, opindex, valuep)
     }
 }
 
+static const char *
+parse_A (CGEN_CPU_DESC cd,
+        const char **strp,
+        int opindex,
+        unsigned long *valuep,
+        unsigned long A)
+{
+  const char *errmsg;
+  if (**strp == '#')
+    ++*strp;
+
+  errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
+  if (errmsg)
+    return errmsg;
+
+  if (*valuep != A)
+    return _("Value of A operand must be 0 or 1");
+
+  return NULL;
+}
+
+static const char *
+parse_A0 (CGEN_CPU_DESC cd,
+         const char **strp,
+         int opindex,
+         unsigned long *valuep)
+{
+  return parse_A (cd, strp, opindex, valuep, 0);
+}
+
+static const char *
+parse_A1 (CGEN_CPU_DESC cd,
+         const char **strp,
+         int opindex,
+         unsigned long *valuep)
+{
+  return parse_A (cd, strp, opindex, valuep, 1);
+}
+
+static const char *
+parse_even_register (CGEN_CPU_DESC  cd,
+                    const char **  strP,
+                    CGEN_KEYWORD * tableP,
+                    long *         valueP)
+{
+  const char * errmsg;
+  const char * saved_star_strP = * strP;
+
+  errmsg = cgen_parse_keyword (cd, strP, tableP, valueP);
+
+  if (errmsg == NULL && ((* valueP) & 1))
+    {
+      errmsg = _("register number must be even");
+      * strP = saved_star_strP;
+    }
+
+  return errmsg;
+}
+
+static const char *
+parse_call_label (CGEN_CPU_DESC cd,
+                 const char **strp,
+                 int opindex,
+                 int opinfo,
+                 enum cgen_parse_operand_result *resultp,
+                 bfd_vma *valuep)
+{
+  const char *errmsg;
+  bfd_vma value;
+  /* Check for small data reference.  */
+  if (opinfo == 0 && (**strp == '#' || **strp == '%'))
+    {
+      if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0)
+       {
+         *strp += 11;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_GETTLSOFF,
+                                          resultp, &value);
+         if (**strp != ')')
+           return _("missing `)'");
+         ++*strp;
+         *valuep = value;
+         return errmsg;
+       }
+    }
+
+  return cgen_parse_address (cd, strp, opindex, opinfo, resultp, valuep);
+}
+
 /* -- */
 
 const char * frv_cgen_parse_operand
-  PARAMS ((CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *));
+  (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
 
 /* Main entry point for operand parsing.
 
@@ -365,11 +998,10 @@ const char * frv_cgen_parse_operand
    the handlers.  */
 
 const char *
-frv_cgen_parse_operand (cd, opindex, strp, fields)
-     CGEN_CPU_DESC cd;
-     int opindex;
-     const char ** strp;
-     CGEN_FIELDS * fields;
+frv_cgen_parse_operand (CGEN_CPU_DESC cd,
+                          int opindex,
+                          const char ** strp,
+                          CGEN_FIELDS * fields)
 {
   const char * errmsg = NULL;
   /* Used by scalar operands that still need to be parsed.  */
@@ -377,8 +1009,11 @@ frv_cgen_parse_operand (cd, opindex, strp, fields)
 
   switch (opindex)
     {
-    case FRV_OPERAND_A :
-      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_A, &fields->f_A);
+    case FRV_OPERAND_A0 :
+      errmsg = parse_A0 (cd, strp, FRV_OPERAND_A0, (unsigned long *) (& fields->f_A));
+      break;
+    case FRV_OPERAND_A1 :
+      errmsg = parse_A1 (cd, strp, FRV_OPERAND_A1, (unsigned long *) (& fields->f_A));
       break;
     case FRV_OPERAND_ACC40SI :
       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_acc_names, & fields->f_ACC40Si);
@@ -402,7 +1037,7 @@ frv_cgen_parse_operand (cd, opindex, strp, fields)
       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cccr_names, & fields->f_CCi);
       break;
     case FRV_OPERAND_CPRDOUBLEK :
-      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cpr_names, & fields->f_CPRk);
+      errmsg = parse_even_register (cd, strp, & frv_cgen_opval_cpr_names, & fields->f_CPRk);
       break;
     case FRV_OPERAND_CPRI :
       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cpr_names, & fields->f_CPRi);
@@ -441,13 +1076,13 @@ frv_cgen_parse_operand (cd, opindex, strp, fields)
       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fccr_names, & fields->f_FCCk);
       break;
     case FRV_OPERAND_FRDOUBLEI :
-      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRi);
+      errmsg = parse_even_register (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRi);
       break;
     case FRV_OPERAND_FRDOUBLEJ :
-      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRj);
+      errmsg = parse_even_register (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRj);
       break;
     case FRV_OPERAND_FRDOUBLEK :
-      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRk);
+      errmsg = parse_even_register (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRk);
       break;
     case FRV_OPERAND_FRI :
       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRi);
@@ -455,12 +1090,21 @@ frv_cgen_parse_operand (cd, opindex, strp, fields)
     case FRV_OPERAND_FRINTI :
       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRi);
       break;
+    case FRV_OPERAND_FRINTIEVEN :
+      errmsg = parse_even_register (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRi);
+      break;
     case FRV_OPERAND_FRINTJ :
       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRj);
       break;
+    case FRV_OPERAND_FRINTJEVEN :
+      errmsg = parse_even_register (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRj);
+      break;
     case FRV_OPERAND_FRINTK :
       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRk);
       break;
+    case FRV_OPERAND_FRINTKEVEN :
+      errmsg = parse_even_register (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRk);
+      break;
     case FRV_OPERAND_FRJ :
       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRj);
       break;
@@ -474,7 +1118,7 @@ frv_cgen_parse_operand (cd, opindex, strp, fields)
       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRk);
       break;
     case FRV_OPERAND_GRDOUBLEK :
-      errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_gr_names, & fields->f_GRk);
+      errmsg = parse_even_register (cd, strp, & frv_cgen_opval_gr_names, & fields->f_GRk);
       break;
     case FRV_OPERAND_GRI :
       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_gr_names, & fields->f_GRi);
@@ -501,28 +1145,46 @@ frv_cgen_parse_operand (cd, opindex, strp, fields)
       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_iccr_names, & fields->f_ICCi_3);
       break;
     case FRV_OPERAND_LI :
-      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_LI, &fields->f_LI);
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_LI, (unsigned long *) (& fields->f_LI));
+      break;
+    case FRV_OPERAND_LRAD :
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_LRAD, (unsigned long *) (& fields->f_LRAD));
+      break;
+    case FRV_OPERAND_LRAE :
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_LRAE, (unsigned long *) (& fields->f_LRAE));
+      break;
+    case FRV_OPERAND_LRAS :
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_LRAS, (unsigned long *) (& fields->f_LRAS));
+      break;
+    case FRV_OPERAND_TLBPRL :
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_TLBPRL, (unsigned long *) (& fields->f_TLBPRL));
+      break;
+    case FRV_OPERAND_TLBPROPX :
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_TLBPROPX, (unsigned long *) (& fields->f_TLBPRopx));
       break;
     case FRV_OPERAND_AE :
-      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_AE, &fields->f_ae);
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_AE, (unsigned long *) (& fields->f_ae));
+      break;
+    case FRV_OPERAND_CALLANN :
+      errmsg = parse_call_annotation (cd, strp, FRV_OPERAND_CALLANN, (unsigned long *) (& fields->f_reloc_ann));
       break;
     case FRV_OPERAND_CCOND :
-      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_CCOND, &fields->f_ccond);
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_CCOND, (unsigned long *) (& fields->f_ccond));
       break;
     case FRV_OPERAND_COND :
-      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_COND, &fields->f_cond);
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_COND, (unsigned long *) (& fields->f_cond));
       break;
     case FRV_OPERAND_D12 :
-      errmsg = parse_d12 (cd, strp, FRV_OPERAND_D12, &fields->f_d12);
+      errmsg = parse_d12 (cd, strp, FRV_OPERAND_D12, (long *) (& fields->f_d12));
       break;
     case FRV_OPERAND_DEBUG :
-      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_DEBUG, &fields->f_debug);
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_DEBUG, (unsigned long *) (& fields->f_debug));
       break;
     case FRV_OPERAND_EIR :
-      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_EIR, &fields->f_eir);
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_EIR, (unsigned long *) (& fields->f_eir));
       break;
     case FRV_OPERAND_HINT :
-      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_HINT, &fields->f_hint);
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_HINT, (unsigned long *) (& fields->f_hint));
       break;
     case FRV_OPERAND_HINT_NOT_TAKEN :
       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_h_hint_not_taken, & fields->f_hint);
@@ -532,62 +1194,68 @@ frv_cgen_parse_operand (cd, opindex, strp, fields)
       break;
     case FRV_OPERAND_LABEL16 :
       {
-        bfd_vma value;
+        bfd_vma value = 0;
         errmsg = cgen_parse_address (cd, strp, FRV_OPERAND_LABEL16, 0, NULL,  & value);
         fields->f_label16 = value;
       }
       break;
     case FRV_OPERAND_LABEL24 :
       {
-        bfd_vma value;
-        errmsg = cgen_parse_address (cd, strp, FRV_OPERAND_LABEL24, 0, NULL,  & value);
+        bfd_vma value = 0;
+        errmsg = parse_call_label (cd, strp, FRV_OPERAND_LABEL24, 0, NULL,  & value);
         fields->f_label24 = value;
       }
       break;
+    case FRV_OPERAND_LDANN :
+      errmsg = parse_ld_annotation (cd, strp, FRV_OPERAND_LDANN, (unsigned long *) (& fields->f_reloc_ann));
+      break;
+    case FRV_OPERAND_LDDANN :
+      errmsg = parse_ldd_annotation (cd, strp, FRV_OPERAND_LDDANN, (unsigned long *) (& fields->f_reloc_ann));
+      break;
     case FRV_OPERAND_LOCK :
-      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_LOCK, &fields->f_lock);
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_LOCK, (unsigned long *) (& fields->f_lock));
       break;
     case FRV_OPERAND_PACK :
       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_h_pack, & fields->f_pack);
       break;
     case FRV_OPERAND_S10 :
-      errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S10, &fields->f_s10);
+      errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S10, (long *) (& fields->f_s10));
       break;
     case FRV_OPERAND_S12 :
-      errmsg = parse_s12 (cd, strp, FRV_OPERAND_S12, &fields->f_d12);
+      errmsg = parse_s12 (cd, strp, FRV_OPERAND_S12, (long *) (& fields->f_d12));
       break;
     case FRV_OPERAND_S16 :
-      errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S16, &fields->f_s16);
+      errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S16, (long *) (& fields->f_s16));
       break;
     case FRV_OPERAND_S5 :
-      errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S5, &fields->f_s5);
+      errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S5, (long *) (& fields->f_s5));
       break;
     case FRV_OPERAND_S6 :
-      errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S6, &fields->f_s6);
+      errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S6, (long *) (& fields->f_s6));
       break;
     case FRV_OPERAND_S6_1 :
-      errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S6_1, &fields->f_s6_1);
+      errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S6_1, (long *) (& fields->f_s6_1));
       break;
     case FRV_OPERAND_SLO16 :
-      errmsg = parse_uslo16 (cd, strp, FRV_OPERAND_SLO16, &fields->f_s16);
+      errmsg = parse_uslo16 (cd, strp, FRV_OPERAND_SLO16, (long *) (& fields->f_s16));
       break;
     case FRV_OPERAND_SPR :
       errmsg = parse_spr (cd, strp, & frv_cgen_opval_spr_names, & fields->f_spr);
       break;
     case FRV_OPERAND_U12 :
-      errmsg = parse_u12 (cd, strp, FRV_OPERAND_U12, &fields->f_u12);
+      errmsg = parse_u12 (cd, strp, FRV_OPERAND_U12, (long *) (& fields->f_u12));
       break;
     case FRV_OPERAND_U16 :
-      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_U16, &fields->f_u16);
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_U16, (unsigned long *) (& fields->f_u16));
       break;
     case FRV_OPERAND_U6 :
-      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_U6, &fields->f_u6);
+      errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_U6, (unsigned long *) (& fields->f_u6));
       break;
     case FRV_OPERAND_UHI16 :
-      errmsg = parse_uhi16 (cd, strp, FRV_OPERAND_UHI16, &fields->f_u16);
+      errmsg = parse_uhi16 (cd, strp, FRV_OPERAND_UHI16, (unsigned long *) (& fields->f_u16));
       break;
     case FRV_OPERAND_ULO16 :
-      errmsg = parse_ulo16 (cd, strp, FRV_OPERAND_ULO16, &fields->f_u16);
+      errmsg = parse_ulo16 (cd, strp, FRV_OPERAND_ULO16, (unsigned long *) (& fields->f_u16));
       break;
 
     default :
@@ -605,13 +1273,15 @@ cgen_parse_fn * const frv_cgen_parse_handlers[] =
 };
 
 void
-frv_cgen_init_asm (cd)
-     CGEN_CPU_DESC cd;
+frv_cgen_init_asm (CGEN_CPU_DESC cd)
 {
   frv_cgen_init_opcode_table (cd);
   frv_cgen_init_ibld_table (cd);
   cd->parse_handlers = & frv_cgen_parse_handlers[0];
   cd->parse_operand = frv_cgen_parse_operand;
+#ifdef CGEN_ASM_INIT_HOOK
+CGEN_ASM_INIT_HOOK
+#endif
 }
 
 \f
@@ -628,8 +1298,7 @@ frv_cgen_init_asm (cd)
    Returns NULL for success, an error message for failure.  */
 
 char * 
-frv_cgen_build_insn_regex (insn)
-     CGEN_INSN *insn;
+frv_cgen_build_insn_regex (CGEN_INSN *insn)
 {  
   CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
   const char *mnem = CGEN_INSN_MNEMONIC (insn);
@@ -752,11 +1421,10 @@ frv_cgen_build_insn_regex (insn)
    Returns NULL for success, an error message for failure.  */
 
 static const char *
-parse_insn_normal (cd, insn, strp, fields)
-     CGEN_CPU_DESC cd;
-     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)
 {
   /* ??? Runtime added insns not handled yet.  */
   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
@@ -842,9 +1510,11 @@ parse_insn_normal (cd, insn, strp, fields)
          continue;
        }
 
+#ifdef CGEN_MNEMONIC_OPERANDS
+      (void) past_opcode_p;
+#endif
       /* We have an operand of some sort.  */
-      errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn),
-                                         &str, fields);
+      errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn), &str, fields);
       if (errmsg)
        return errmsg;
 
@@ -894,12 +1564,11 @@ parse_insn_normal (cd, insn, strp, fields)
    mind helps keep the design clean.  */
 
 const CGEN_INSN *
-frv_cgen_assemble_insn (cd, str, fields, buf, errmsg)
-     CGEN_CPU_DESC cd;
-     const char *str;
-     CGEN_FIELDS *fields;
-     CGEN_INSN_BYTES_PTR buf;
-     char **errmsg;
+frv_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;
@@ -929,10 +1598,10 @@ frv_cgen_assemble_insn (cd, str, fields, buf, errmsg)
       if (! frv_cgen_insn_supported (cd, insn))
        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.  */
-      if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAX) != 0)
+      if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
        continue;
 
       str = start;
@@ -962,62 +1631,41 @@ frv_cgen_assemble_insn (cd, str, fields, buf, errmsg)
 
   {
     static char errbuf[150];
-#ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
     const char *tmp_errmsg;
-
-    /* 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);
+#ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
+#define be_verbose 1
 #else
-    if (strlen (start) > 50)
-      /* xgettext:c-format */
-      sprintf (errbuf, _("bad instruction `%.50s...'"), start);
-    else 
-      /* xgettext:c-format */
-      sprintf (errbuf, _("bad instruction `%.50s'"), start);
+#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;
   }
 }
-\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
-frv_cgen_asm_hash_keywords (cd, opvals)
-     CGEN_CPU_DESC cd;
-     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 (! frv_cgen_opval_supported (ke))
-       continue;
-#endif
-      cgen_asm_record_register (cd, ke->name, ke->value);
-    }
-}
-
-#endif /* 0 */