jit: c++-ify gdb_block
[deliverable/binutils-gdb.git] / cpu / frv.opc
index cd3572f0bdfc84aff8e86b62db08b7420787b09c..1b0b05c29a061cb1d33076aed7e3893cc1179d6d 100644 (file)
@@ -1,6 +1,7 @@
 /* Fujitsu FRV opcode support, for GNU Binutils.  -*- C -*-
 
-   Copyright 2003 Free Software Foundation, Inc.
+   Copyright 2000, 2001, 2003, 2004, 2005, 2007, 2009
+   Free Software Foundation, Inc.
 
    Contributed by Red Hat Inc; developed under contract from Fujitsu.
 
@@ -8,7 +9,7 @@
 
    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 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -18,9 +19,9 @@
 
    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.
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
 
-*/
 
 /* This file is an addendum to frv.cpu.  Heavy use of C code isn't
    appropriate in .cpu files, so it resides here.  This especially applies
@@ -35,8 +36,7 @@
    <arch>-opc.c additions use: "-- opc.c"
    <arch>-asm.c additions use: "-- asm.c"
    <arch>-dis.c additions use: "-- dis.c"
-   <arch>-ibd.h additions use: "-- ibd.h"
-*/
+   <arch>-ibd.h additions use: "-- ibd.h".  */
 \f
 /* -- opc.h */
 
 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
 
 /* Vliw support.  */
-#define FRV_VLIW_SIZE 4 /* fr500 has largest vliw size of 4.  */
-typedef CGEN_ATTR_VALUE_TYPE VLIW_COMBO[FRV_VLIW_SIZE];
+#define FRV_VLIW_SIZE 8 /* fr550 has largest vliw size of 8.  */
+#define PAD_VLIW_COMBO ,UNIT_NIL,UNIT_NIL,UNIT_NIL,UNIT_NIL
+
+typedef CGEN_ATTR_VALUE_ENUM_TYPE VLIW_COMBO[FRV_VLIW_SIZE];
 
 typedef struct
 {
-  int                   next_slot;
-  int                   constraint_violation;
-  unsigned long         mach;
-  unsigned long         elf_flags;
-  CGEN_ATTR_VALUE_TYPE *unit_mapping;
-  VLIW_COMBO           *current_vliw;
-  CGEN_ATTR_VALUE_TYPE  major[FRV_VLIW_SIZE];
+  int                    next_slot;
+  int                    constraint_violation;
+  unsigned long          mach;
+  unsigned long          elf_flags;
+  CGEN_ATTR_VALUE_ENUM_TYPE * unit_mapping;
+  VLIW_COMBO *           current_vliw;
+  CGEN_ATTR_VALUE_ENUM_TYPE   major[FRV_VLIW_SIZE];
+  const CGEN_INSN *      insn[FRV_VLIW_SIZE];
 } FRV_VLIW;
 
-int frv_is_branch_major PARAMS ((CGEN_ATTR_VALUE_TYPE, unsigned long));
-int frv_is_float_major  PARAMS ((CGEN_ATTR_VALUE_TYPE, unsigned long));
-int frv_is_media_major  PARAMS ((CGEN_ATTR_VALUE_TYPE, unsigned long));
-int frv_is_branch_insn  PARAMS ((const CGEN_INSN *));
-int frv_is_float_insn   PARAMS ((const CGEN_INSN *));
-int frv_is_media_insn   PARAMS ((const CGEN_INSN *));
-void frv_vliw_reset     PARAMS ((FRV_VLIW *, unsigned long mach, unsigned long elf_flags));
-int frv_vliw_add_insn   PARAMS ((FRV_VLIW *, const CGEN_INSN *));
-int spr_valid           PARAMS ((long));
+int frv_is_branch_major (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long);
+int frv_is_float_major  (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long);
+int frv_is_media_major  (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long);
+int frv_is_branch_insn  (const CGEN_INSN *);
+int frv_is_float_insn   (const CGEN_INSN *);
+int frv_is_media_insn   (const CGEN_INSN *);
+void frv_vliw_reset     (FRV_VLIW *, unsigned long, unsigned long);
+int frv_vliw_add_insn   (FRV_VLIW *, const CGEN_INSN *);
+int spr_valid           (long);
 /* -- */
 \f
 /* -- opc.c */
+#include "opintl.h"
 #include "elf/frv.h"
+#include <stdio.h>
 
-static int match_unit
-  PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE, CGEN_ATTR_VALUE_TYPE));
-static int match_vliw
-  PARAMS ((VLIW_COMBO *, VLIW_COMBO *, int));
-static VLIW_COMBO * add_next_to_vliw
-  PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE));
-static int find_major_in_vliw
-  PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE));
-static int fr400_check_insn_major_constraints
-  PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE));
-static int fr500_check_insn_major_constraints
-  PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE));
-static int check_insn_major_constraints
-  PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE));
+/* DEBUG appears below as argument of OP macro.  */
+#undef DEBUG
 
-int
-frv_is_branch_major (CGEN_ATTR_VALUE_TYPE major, unsigned long mach)
+/* Returns TRUE if {MAJOR,MACH} is a major branch of the FRV
+   development tree.  */
+
+bfd_boolean
+frv_is_branch_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach)
 {
   switch (mach)
     {
     case bfd_mach_fr400:
       if (major >= FR400_MAJOR_B_1 && major <= FR400_MAJOR_B_6)
-       return 1; /* is a branch */
+       return TRUE;
+      break;
+    case bfd_mach_fr450:
+      if (major >= FR450_MAJOR_B_1 && major <= FR450_MAJOR_B_6)
+       return TRUE;
       break;
     default:
       if (major >= FR500_MAJOR_B_1 && major <= FR500_MAJOR_B_6)
-       return 1; /* is a branch */
+       return TRUE;
       break;
     }
 
-  return 0; /* not a branch */
+  return FALSE;
 }
 
-int
-frv_is_float_major (CGEN_ATTR_VALUE_TYPE major, unsigned long mach)
+/* Returns TRUE if {MAJOR,MACH} supports floating point insns.  */
+
+bfd_boolean
+frv_is_float_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach)
 {
   switch (mach)
     {
     case bfd_mach_fr400:
-      return 0; /* No float insns */
+    case bfd_mach_fr450:
+      return FALSE;
     default:
       if (major >= FR500_MAJOR_F_1 && major <= FR500_MAJOR_F_8)
-       return 1; /* is a float insn */
+       return TRUE;
       break;
     }
 
-  return 0; /* not a branch */
+  return FALSE;
 }
 
-int
-frv_is_media_major (CGEN_ATTR_VALUE_TYPE major, unsigned long mach)
+/* Returns TRUE if {MAJOR,MACH} supports media insns.  */
+
+bfd_boolean
+frv_is_media_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach)
 {
   switch (mach)
     {
     case bfd_mach_fr400:
       if (major >= FR400_MAJOR_M_1 && major <= FR400_MAJOR_M_2)
-       return 1; /* is a media insn */
+       return TRUE;
+      break;
+    case bfd_mach_fr450:
+      if (major >= FR450_MAJOR_M_1 && major <= FR450_MAJOR_M_6)
+       return TRUE;
       break;
     default:
       if (major >= FR500_MAJOR_M_1 && major <= FR500_MAJOR_M_8)
-       return 1; /* is a media insn */
+       return TRUE;
       break;
     }
 
-  return 0; /* not a branch */
+  return FALSE;
 }
 
-int
+bfd_boolean
 frv_is_branch_insn (const CGEN_INSN *insn)
 {
   if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
                           bfd_mach_fr400))
-    return 1;
+    return TRUE;
+  if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
+                          bfd_mach_fr450))
+    return TRUE;
   if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
                           bfd_mach_fr500))
-    return 1;
+    return TRUE;
 
-  return 0;
+  return FALSE;
 }
 
-int
+bfd_boolean
 frv_is_float_insn (const CGEN_INSN *insn)
 {
   if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
                          bfd_mach_fr400))
-    return 1;
+    return TRUE;
+  if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
+                         bfd_mach_fr450))
+    return TRUE;
   if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
                          bfd_mach_fr500))
-    return 1;
+    return TRUE;
 
-  return 0;
+  return FALSE;
 }
 
-int
+bfd_boolean
 frv_is_media_insn (const CGEN_INSN *insn)
 {
   if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
                          bfd_mach_fr400))
-    return 1;
+    return TRUE;
+  if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
+                         bfd_mach_fr450))
+    return TRUE;
   if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
                          bfd_mach_fr500))
-    return 1;
+    return TRUE;
 
-  return 0;
+  return FALSE;
 }
 
 /* This table represents the allowable packing for vliw insns for the fr400.
@@ -190,48 +208,89 @@ frv_is_media_insn (const CGEN_INSN *insn)
 static VLIW_COMBO fr400_allowed_vliw[] =
 {
   /*  slot0       slot1       slot2       slot3    */
-  {  UNIT_I0,    UNIT_I1,    UNIT_NIL,   UNIT_NIL  },
-  {  UNIT_I0,    UNIT_FM0,   UNIT_NIL,   UNIT_NIL  },
-  {  UNIT_I0,    UNIT_B0,    UNIT_NIL,   UNIT_NIL  },
-  {  UNIT_FM0,   UNIT_FM1,   UNIT_NIL,   UNIT_NIL  },
-  {  UNIT_FM0,   UNIT_B0,    UNIT_NIL,   UNIT_NIL  },
-  {  UNIT_B0,    UNIT_NIL,   UNIT_NIL,   UNIT_NIL  },
-  {  UNIT_C,     UNIT_NIL,   UNIT_NIL,   UNIT_NIL  },
-  {  UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL  }
+  {  UNIT_I0,    UNIT_I1,    UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
+  {  UNIT_I0,    UNIT_FM0,   UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
+  {  UNIT_I0,    UNIT_B0,    UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
+  {  UNIT_FM0,   UNIT_FM1,   UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
+  {  UNIT_FM0,   UNIT_B0,    UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
+  {  UNIT_B0,    UNIT_NIL,   UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
+  {  UNIT_C,     UNIT_NIL,   UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
+  {  UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO }
 };
 
 /* This table represents the allowable packing for vliw insns for the fr500.
+   The fr500 has only 4 vliw slots. Represent this by not allowing any insns
+   in the extra slots.
    Subsets of any given row are also allowed.  */
 static VLIW_COMBO fr500_allowed_vliw[] =
 {
   /*  slot0       slot1       slot2       slot3    */
-  {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1  },
-  {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_B0   },
-  {  UNIT_I0,    UNIT_FM0,   UNIT_FM1,   UNIT_B0   },
-  {  UNIT_I0,    UNIT_FM0,   UNIT_B0,    UNIT_B1   },
-  {  UNIT_I0,    UNIT_I1,    UNIT_B0,    UNIT_B1   },
-  {  UNIT_I0,    UNIT_B0,    UNIT_B1,    UNIT_NIL  },
-  {  UNIT_FM0,   UNIT_FM1,   UNIT_B0,    UNIT_B1   },
-  {  UNIT_FM0,   UNIT_B0,    UNIT_B1,    UNIT_NIL  },
-  {  UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL  },
-  {  UNIT_C,     UNIT_NIL,   UNIT_NIL,   UNIT_NIL  },
-  {  UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL  }
+  {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1  PAD_VLIW_COMBO },
+  {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_B0   PAD_VLIW_COMBO },
+  {  UNIT_I0,    UNIT_FM0,   UNIT_FM1,   UNIT_B0   PAD_VLIW_COMBO },
+  {  UNIT_I0,    UNIT_FM0,   UNIT_B0,    UNIT_B1   PAD_VLIW_COMBO },
+  {  UNIT_I0,    UNIT_I1,    UNIT_B0,    UNIT_B1   PAD_VLIW_COMBO },
+  {  UNIT_I0,    UNIT_B0,    UNIT_B1,    UNIT_NIL  PAD_VLIW_COMBO },
+  {  UNIT_FM0,   UNIT_FM1,   UNIT_B0,    UNIT_B1   PAD_VLIW_COMBO },
+  {  UNIT_FM0,   UNIT_B0,    UNIT_B1,    UNIT_NIL  PAD_VLIW_COMBO },
+  {  UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
+  {  UNIT_C,     UNIT_NIL,   UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
+  {  UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO }
+};
+
+/* This table represents the allowable packing for vliw insns for the fr550.
+   Subsets of any given row are also allowed.  */
+static VLIW_COMBO fr550_allowed_vliw[] =
+{
+  /*  slot0       slot1       slot2       slot3       slot4       slot5       slot6       slot7   */
+  {  UNIT_I0,    UNIT_I1,    UNIT_I2,    UNIT_I3,    UNIT_B0,    UNIT_B1 ,   UNIT_NIL,   UNIT_NIL },
+  {  UNIT_I0,    UNIT_I1,    UNIT_I2,    UNIT_B0,    UNIT_B1 ,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
+  {  UNIT_I0,    UNIT_I1,    UNIT_B0,    UNIT_B1 ,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
+  {  UNIT_I0,    UNIT_B0,    UNIT_B1 ,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
+  {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_I2,    UNIT_FM2,   UNIT_I3,    UNIT_FM3 },
+  {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_I2,    UNIT_FM2,   UNIT_I3,    UNIT_B0  },
+  {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_I2,    UNIT_FM2,   UNIT_FM3,   UNIT_B0  },
+  {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_I2,    UNIT_FM2,   UNIT_B0,    UNIT_B1  },
+  {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_I2,    UNIT_I3,    UNIT_B0,    UNIT_B1  },
+  {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_I2,    UNIT_B0,    UNIT_B1,    UNIT_NIL },
+  {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_FM2,   UNIT_FM3,   UNIT_B0,    UNIT_B1  },
+  {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_FM2,   UNIT_FM3,   UNIT_B0,    UNIT_B1  },
+  {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_FM2,   UNIT_B0,    UNIT_B1,    UNIT_NIL },
+  {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL },
+  {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_I2,    UNIT_I3,    UNIT_B0,    UNIT_B1,    UNIT_NIL },
+  {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_I2,    UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL },
+  {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
+  {  UNIT_I0,    UNIT_FM0,   UNIT_FM1,   UNIT_FM2,   UNIT_FM3,   UNIT_B0,    UNIT_B1,    UNIT_NIL },
+  {  UNIT_I0,    UNIT_FM0,   UNIT_FM1,   UNIT_FM2,   UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL },
+  {  UNIT_I0,    UNIT_FM0,   UNIT_FM1,   UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
+  {  UNIT_I0,    UNIT_FM0,   UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
+  {  UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
+  {  UNIT_C,     UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
+  {  UNIT_FM0,   UNIT_FM1,   UNIT_FM2,   UNIT_FM3,   UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL },
+  {  UNIT_FM0,   UNIT_FM1,   UNIT_FM2,   UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
+  {  UNIT_FM0,   UNIT_FM1,   UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
+  {  UNIT_FM0,   UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
+  {  UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL }
 };
 
 /* Some insns are assigned specialized implementation units which map to
    different actual implementation units on different machines.  These
    tables perform that mapping.  */
-static CGEN_ATTR_VALUE_TYPE fr400_unit_mapping[] =
+static CGEN_ATTR_VALUE_ENUM_TYPE fr400_unit_mapping[] =
 {
 /* unit in insn    actual unit */
 /* NIL      */     UNIT_NIL,
 /* I0       */     UNIT_I0,
 /* I1       */     UNIT_I1,
 /* I01      */     UNIT_I01, 
+/* I2       */     UNIT_NIL, /* no I2 or I3 unit */
+/* I3       */     UNIT_NIL,
 /* IALL     */     UNIT_I01, /* only I0 and I1 units */
 /* FM0      */     UNIT_FM0,
 /* FM1      */     UNIT_FM1,
 /* FM01     */     UNIT_FM01,
+/* FM2      */     UNIT_NIL, /* no F2 or M2 units */
+/* FM3      */     UNIT_NIL, /* no F3 or M3 units */
 /* FMALL    */     UNIT_FM01,/* Only F0,F1,M0,M1 units */
 /* FMLOW    */     UNIT_FM0, /* Only F0,M0 units */
 /* B0       */     UNIT_B0,  /* branches only in B0 unit.  */
@@ -239,25 +298,66 @@ static CGEN_ATTR_VALUE_TYPE fr400_unit_mapping[] =
 /* B01      */     UNIT_B0,
 /* C        */     UNIT_C,
 /* MULT-DIV */     UNIT_I0,  /* multiply and divide only in I0  unit.  */
+/* IACC     */     UNIT_I01, /* iacc multiply       in I0 or I1 unit.  */
 /* LOAD     */     UNIT_I0,  /* load                only in I0  unit.  */
 /* STORE    */     UNIT_I0,  /* store               only in I0  unit.  */
 /* SCAN     */     UNIT_I0,  /* scan                only in I0  unit.  */
 /* DCPL     */     UNIT_C,   /* dcpl                only in C   unit.  */
 /* MDUALACC */     UNIT_FM0, /* media dual acc insn only in FM0 unit.  */
+/* MDCUTSSI */     UNIT_FM0, /* mdcutssi            only in FM0 unit.  */
+/* MCLRACC-1*/     UNIT_FM0  /* mclracc,A==1   insn only in FM0 unit.  */
+};
+
+/* Some insns are assigned specialized implementation units which map to
+   different actual implementation units on different machines.  These
+   tables perform that mapping.  */
+static CGEN_ATTR_VALUE_ENUM_TYPE fr450_unit_mapping[] =
+{
+/* unit in insn    actual unit */
+/* NIL      */     UNIT_NIL,
+/* I0       */     UNIT_I0,
+/* I1       */     UNIT_I1,
+/* I01      */     UNIT_I01, 
+/* I2       */     UNIT_NIL, /* no I2 or I3 unit */
+/* I3       */     UNIT_NIL,
+/* IALL     */     UNIT_I01, /* only I0 and I1 units */
+/* FM0      */     UNIT_FM0,
+/* FM1      */     UNIT_FM1,
+/* FM01     */     UNIT_FM01,
+/* FM2      */     UNIT_NIL, /* no F2 or M2 units */
+/* FM3      */     UNIT_NIL, /* no F3 or M3 units */
+/* FMALL    */     UNIT_FM01,/* Only F0,F1,M0,M1 units */
+/* FMLOW    */     UNIT_FM0, /* Only F0,M0 units */
+/* B0       */     UNIT_B0,  /* branches only in B0 unit.  */
+/* B1       */     UNIT_B0,
+/* B01      */     UNIT_B0,
+/* C        */     UNIT_C,
+/* MULT-DIV */     UNIT_I0,  /* multiply and divide only in I0  unit.  */
+/* IACC     */     UNIT_I01, /* iacc multiply       in I0 or I1 unit.  */
+/* LOAD     */     UNIT_I0,  /* load                only in I0  unit.  */
+/* STORE    */     UNIT_I0,  /* store               only in I0  unit.  */
+/* SCAN     */     UNIT_I0,  /* scan                only in I0  unit.  */
+/* DCPL     */     UNIT_I0,  /* dcpl                only in I0  unit.  */
+/* MDUALACC */     UNIT_FM0, /* media dual acc insn only in FM0 unit.  */
+/* MDCUTSSI */     UNIT_FM01, /* mdcutssi           in FM0 or FM1.  */
 /* MCLRACC-1*/     UNIT_FM0  /* mclracc,A==1   insn only in FM0 unit.  */
 };
 
-static CGEN_ATTR_VALUE_TYPE fr500_unit_mapping[] =
+static CGEN_ATTR_VALUE_ENUM_TYPE fr500_unit_mapping[] =
 {
 /* unit in insn    actual unit */
 /* NIL      */     UNIT_NIL,
 /* I0       */     UNIT_I0,
 /* I1       */     UNIT_I1,
 /* I01      */     UNIT_I01, 
+/* I2       */     UNIT_NIL, /* no I2 or I3 unit */
+/* I3       */     UNIT_NIL,
 /* IALL     */     UNIT_I01, /* only I0 and I1 units */
 /* FM0      */     UNIT_FM0,
 /* FM1      */     UNIT_FM1,
 /* FM01     */     UNIT_FM01,
+/* FM2      */     UNIT_NIL, /* no F2 or M2 units */
+/* FM3      */     UNIT_NIL, /* no F3 or M2 units */
 /* FMALL    */     UNIT_FM01,/* Only F0,F1,M0,M1 units */
 /* FMLOW    */     UNIT_FM0, /* Only F0,M0 units */
 /* B0       */     UNIT_B0,
@@ -265,14 +365,48 @@ static CGEN_ATTR_VALUE_TYPE fr500_unit_mapping[] =
 /* B01      */     UNIT_B01,
 /* C        */     UNIT_C,
 /* MULT-DIV */     UNIT_I01, /* multiply and divide in I0 or I1 unit.  */
+/* IACC     */     UNIT_NIL, /* iacc multiply       not implemented */
 /* LOAD     */     UNIT_I01, /* load                in I0 or I1 unit.  */
 /* STORE    */     UNIT_I0,  /* store               only in I0 unit.  */
 /* SCAN     */     UNIT_I01, /* scan                in I0 or I1 unit.  */
 /* DCPL     */     UNIT_C,   /* dcpl                only in C unit.  */
 /* MDUALACC */     UNIT_FM0, /* media dual acc insn only in FM0 unit.  */
+/* MDCUTSSI */     UNIT_FM0, /* mdcutssi            only in FM0 unit.  */
 /* MCLRACC-1*/     UNIT_FM01 /* mclracc,A==1 in FM0 or FM1 unit.  */
 };
 
+static CGEN_ATTR_VALUE_ENUM_TYPE fr550_unit_mapping[] =
+{
+/* unit in insn    actual unit */
+/* NIL      */     UNIT_NIL,
+/* I0       */     UNIT_I0,
+/* I1       */     UNIT_I1,
+/* I01      */     UNIT_I01, 
+/* I2       */     UNIT_I2,
+/* I3       */     UNIT_I3,
+/* IALL     */     UNIT_IALL, 
+/* FM0      */     UNIT_FM0,
+/* FM1      */     UNIT_FM1,
+/* FM01     */     UNIT_FM01,
+/* FM2      */     UNIT_FM2,
+/* FM3      */     UNIT_FM3,
+/* FMALL    */     UNIT_FMALL,
+/* FMLOW    */     UNIT_FM01, /* Only F0,F1,M0,M1 units */
+/* B0       */     UNIT_B0,
+/* B1       */     UNIT_B1,
+/* B01      */     UNIT_B01,
+/* C        */     UNIT_C,
+/* MULT-DIV */     UNIT_I01,  /* multiply and divide in I0 or I1 unit.    */
+/* IACC     */     UNIT_NIL,  /* iacc multiply       not implemented.     */
+/* LOAD     */     UNIT_I01,  /* load                in I0 or I1 unit.    */
+/* STORE    */     UNIT_I01,  /* store               in I0 or I1 unit.    */
+/* SCAN     */     UNIT_IALL, /* scan                in any integer unit. */
+/* DCPL     */     UNIT_I0,   /* dcpl                only in I0 unit.     */
+/* MDUALACC */     UNIT_FMALL,/* media dual acc insn in all media units   */
+/* MDCUTSSI */     UNIT_FM01, /* mdcutssi            in FM0 or FM1 unit.  */
+/* MCLRACC-1*/     UNIT_FM01  /* mclracc,A==1 in FM0 or FM1 unit.         */
+};
+
 void
 frv_vliw_reset (FRV_VLIW *vliw, unsigned long mach, unsigned long elf_flags)
 {
@@ -287,6 +421,14 @@ frv_vliw_reset (FRV_VLIW *vliw, unsigned long mach, unsigned long elf_flags)
       vliw->current_vliw = fr400_allowed_vliw;
       vliw->unit_mapping = fr400_unit_mapping;
       break;
+    case bfd_mach_fr450:
+      vliw->current_vliw = fr400_allowed_vliw;
+      vliw->unit_mapping = fr450_unit_mapping;
+      break;
+    case bfd_mach_fr550:
+      vliw->current_vliw = fr550_allowed_vliw;
+      vliw->unit_mapping = fr550_unit_mapping;
+      break;
     default:
       vliw->current_vliw = fr500_allowed_vliw;
       vliw->unit_mapping = fr500_unit_mapping;
@@ -294,20 +436,20 @@ frv_vliw_reset (FRV_VLIW *vliw, unsigned long mach, unsigned long elf_flags)
     }
 }
 
-/* Return 1 if unit1 is a match for unit2.
+/* Return TRUE if unit1 is a match for unit2.
    Unit1 comes from the insn's UNIT attribute. unit2 comes from one of the
    *_allowed_vliw tables above.  */
-static int
+static bfd_boolean
 match_unit (FRV_VLIW *vliw,
-           CGEN_ATTR_VALUE_TYPE unit1, CGEN_ATTR_VALUE_TYPE unit2)
+           CGEN_ATTR_VALUE_ENUM_TYPE unit1, CGEN_ATTR_VALUE_ENUM_TYPE unit2)
 {
   /* Map any specialized implementation units to actual ones.  */
   unit1 = vliw->unit_mapping[unit1];
 
   if (unit1 == unit2)
-    return 1;
+    return TRUE;
   if (unit1 < unit2)
-    return 0;
+    return FALSE;
 
   switch (unit1)
     {
@@ -317,43 +459,52 @@ match_unit (FRV_VLIW *vliw,
       /* The 01 versions of these units are within 2 enums of the 0 or 1
         versions.  */
       if (unit1 - unit2 <= 2)
-       return 1;
+       return TRUE;
+      break;
+    case UNIT_IALL:
+    case UNIT_FMALL:
+      /* The ALL versions of these units are within 5 enums of the 0, 1, 2 or 3
+        versions.  */
+      if (unit1 - unit2 <= 5)
+       return TRUE;
       break;
     default:
       break;
     }
 
-  return 0;
+  return FALSE;
 }
 
-/* Return 1 if the vliws match, 0 otherwise.  */
+/* Return TRUE if the vliws match, FALSE otherwise.  */
 
-static int
+static bfd_boolean
 match_vliw (VLIW_COMBO *vliw1, VLIW_COMBO *vliw2, int vliw_size)
 {
   int i;
 
   for (i = 0; i < vliw_size; ++i)
-    {
-      if ((*vliw1)[i] != (*vliw2)[i])
-       return 0;
-    }
+    if ((*vliw1)[i] != (*vliw2)[i])
+      return FALSE;
 
-  return 1;
+  return TRUE;
 }
 
 /* Find the next vliw vliw in the table that can accomodate the new insn.
    If one is found then return it. Otherwise return NULL.  */
 
 static VLIW_COMBO *
-add_next_to_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE unit)
+add_next_to_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE unit)
 {
   int           next    = vliw->next_slot;
   VLIW_COMBO    *current = vliw->current_vliw;
   VLIW_COMBO    *potential;
 
   if (next <= 0)
-    abort (); /* Should never happen */
+    {
+      /* xgettext:c-format */
+      opcodes_error_handler (_("internal error: bad vliw->next_slot value"));
+      abort ();
+    }
 
   /* The table is sorted by units allowed within slots, so vliws with
      identical starting sequences are together.  */
@@ -369,28 +520,26 @@ add_next_to_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE unit)
   return NULL;
 }
 
-/* Look for the given major insn type in the given vliw. Return 1 if found,
-   return 0 otherwise.  */
+/* Look for the given major insn type in the given vliw.
+   Returns TRUE if found, FALSE otherwise.  */
 
-static int
-find_major_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major)
+static bfd_boolean
+find_major_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
 {
   int i;
 
   for (i = 0; i < vliw->next_slot; ++i)
     if (vliw->major[i] == major)
-      return 1;
+      return TRUE;
 
-  return 0;
+  return FALSE;
 }
 
 /* Check for constraints between the insns in the vliw due to major insn
    types.  */
 
-static int
-fr400_check_insn_major_constraints (
-  FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major
-)
+static bfd_boolean
+fr400_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
 {
   /* In the cpu file, all media insns are represented as being allowed in
      both media units. This makes it easier since this is the case for fr500.
@@ -401,16 +550,170 @@ fr400_check_insn_major_constraints (
     case FR400_MAJOR_M_2:
       return ! find_major_in_vliw (vliw, FR400_MAJOR_M_1)
        &&   ! find_major_in_vliw (vliw, FR400_MAJOR_M_2);
+    case FR400_MAJOR_M_1:
+      return ! find_major_in_vliw (vliw, FR400_MAJOR_M_2);
     default:
       break;
     }
-  return 1;
+  return TRUE;
+}
+
+static bfd_boolean
+fr450_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
+{
+  CGEN_ATTR_VALUE_ENUM_TYPE other_major;
+
+  /* Our caller guarantees there's at least one other instruction.  */
+  other_major = CGEN_INSN_ATTR_VALUE (vliw->insn[0], CGEN_INSN_FR450_MAJOR);
+
+  /* (M4, M5) and (M4, M6) are allowed.  */
+  if (other_major == FR450_MAJOR_M_4)
+    if (major == FR450_MAJOR_M_5 || major == FR450_MAJOR_M_6)
+      return TRUE;
+
+  /* Otherwise, instructions in even-numbered media categories cannot be
+     executed in parallel with other media instructions.  */
+  switch (major)
+    {
+    case FR450_MAJOR_M_2:
+    case FR450_MAJOR_M_4:
+    case FR450_MAJOR_M_6:
+      return !(other_major >= FR450_MAJOR_M_1
+              && other_major <= FR450_MAJOR_M_6);
+
+    case FR450_MAJOR_M_1:
+    case FR450_MAJOR_M_3:
+    case FR450_MAJOR_M_5:
+      return !(other_major == FR450_MAJOR_M_2
+              || other_major == FR450_MAJOR_M_4
+              || other_major == FR450_MAJOR_M_6);
+
+    default:
+      return TRUE;
+    }
+}
+
+static bfd_boolean
+find_unit_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE unit)
+{
+  int i;
+
+  for (i = 0; i < vliw->next_slot; ++i)
+    if (CGEN_INSN_ATTR_VALUE (vliw->insn[i], CGEN_INSN_UNIT) == unit)
+      return TRUE;
+
+  return FALSE; /* Not found.  */
+}
+
+static bfd_boolean
+find_major_in_slot (FRV_VLIW *vliw,
+                   CGEN_ATTR_VALUE_ENUM_TYPE major,
+                   CGEN_ATTR_VALUE_ENUM_TYPE slot)
+{
+  int i;
+
+  for (i = 0; i < vliw->next_slot; ++i)
+    if (vliw->major[i] == major && (*vliw->current_vliw)[i] == slot)
+      return TRUE;
+
+  return FALSE;
+}
+
+static bfd_boolean
+fr550_find_media_in_vliw (FRV_VLIW *vliw)
+{
+  int i;
+
+  for (i = 0; i < vliw->next_slot; ++i)
+    {
+      if (vliw->major[i] < FR550_MAJOR_M_1 || vliw->major[i] > FR550_MAJOR_M_5)
+       continue;
+
+      /* Found a media insn, however, MNOP and MCLRACC don't count.  */
+      if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MNOP
+         || CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MCLRACC_0
+         || CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MCLRACC_1)
+       continue;
+
+      return TRUE; /* Found one.  */
+    }
+
+  return FALSE;
+}
+
+static bfd_boolean
+fr550_find_float_in_vliw (FRV_VLIW *vliw)
+{
+  int i;
+
+  for (i = 0; i < vliw->next_slot; ++i)
+    {
+      if (vliw->major[i] < FR550_MAJOR_F_1 || vliw->major[i] > FR550_MAJOR_F_4)
+       continue;
+
+      /* Found a floating point insn, however, FNOP doesn't count.  */
+      if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_FNOP)
+       continue;
+
+      return TRUE; /* Found one.  */
+    }
+
+  return FALSE;
+}
+
+static bfd_boolean
+fr550_check_insn_major_constraints (FRV_VLIW *vliw,
+                                   CGEN_ATTR_VALUE_ENUM_TYPE major,
+                                   const CGEN_INSN *insn)
+{
+  CGEN_ATTR_VALUE_ENUM_TYPE unit;
+  CGEN_ATTR_VALUE_ENUM_TYPE slot = (*vliw->current_vliw)[vliw->next_slot];
+  switch (slot)
+    {
+    case UNIT_I2:
+      /* If it's a store, then there must be another store in I1 */
+      unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
+      if (unit == UNIT_STORE)
+       return find_unit_in_vliw (vliw, UNIT_STORE);
+      break;
+    case UNIT_FM2:
+    case UNIT_FM3:
+      /* Floating point insns other than FNOP in slot f2 or f3 cannot coexist
+        with media insns.  */
+      if (major >= FR550_MAJOR_F_1 && major <= FR550_MAJOR_F_4
+         && CGEN_INSN_NUM (insn) != FRV_INSN_FNOP)
+       return ! fr550_find_media_in_vliw (vliw);
+      /* Media insns other than MNOP in slot m2 or m3 cannot coexist with
+        floating point insns.  */
+      if (major >= FR550_MAJOR_M_1 && major <= FR550_MAJOR_M_5
+         && CGEN_INSN_NUM (insn) != FRV_INSN_MNOP)
+       return ! fr550_find_float_in_vliw (vliw);
+      /* F-2 in slot f2 or f3 cannot coexist with F-2 or F-4 in slot f1 or f2
+        respectively.  */
+      if (major == FR550_MAJOR_F_2)
+       return ! find_major_in_slot (vliw, FR550_MAJOR_F_2,
+                                    slot - (UNIT_FM2 - UNIT_FM0))
+         &&   ! find_major_in_slot (vliw, FR550_MAJOR_F_4,
+                                    slot - (UNIT_FM2 - UNIT_FM0));
+      /* M-2 or M-5 in slot m2 or m3 cannot coexist with M-2 in slot m1 or m2
+        respectively.  */
+      if (major == FR550_MAJOR_M_2 || major == FR550_MAJOR_M_5)
+       return ! find_major_in_slot (vliw, FR550_MAJOR_M_2,
+                                    slot - (UNIT_FM2 - UNIT_FM0));
+      /* M-4 in slot m2 or m3 cannot coexist with M-4 in slot m1 or m2
+        respectively.  */
+      if (major == FR550_MAJOR_M_4)
+       return ! find_major_in_slot (vliw, FR550_MAJOR_M_4,
+                                    slot - (UNIT_FM2 - UNIT_FM0));
+      break;
+    default:
+      break;
+    }
+  return TRUE; /* All OK.  */
 }
 
-static int
-fr500_check_insn_major_constraints (
-  FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major
-)
+static bfd_boolean
+fr500_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
 {
   /* TODO: A table might be faster for some of the more complex instances
      here.  */
@@ -429,7 +732,7 @@ fr500_check_insn_major_constraints (
     case FR500_MAJOR_F_4:
     case FR500_MAJOR_F_8:
     case FR500_MAJOR_M_8:
-      return 1; /* OK */
+      return TRUE; /* OK */
     case FR500_MAJOR_I_2:
       /* Cannot coexist with I-3 insn.  */
       return ! find_major_in_vliw (vliw, FR500_MAJOR_I_3);
@@ -508,67 +811,84 @@ fr500_check_insn_major_constraints (
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_7);
     default:
+      /* xgettext:c-format */
+      opcodes_error_handler (_("internal error: bad major code"));
       abort ();
       break;
     }
-  return 1;
+  return TRUE;
 }
 
-static int
-check_insn_major_constraints (
-  FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major
-)
+static bfd_boolean
+check_insn_major_constraints (FRV_VLIW *vliw,
+                             CGEN_ATTR_VALUE_ENUM_TYPE major,
+                             const CGEN_INSN *insn)
 {
-  int rc;
   switch (vliw->mach)
     {
     case bfd_mach_fr400:
-      rc = fr400_check_insn_major_constraints (vliw, major);
-      break;
+      return fr400_check_insn_major_constraints (vliw, major);
+
+    case bfd_mach_fr450:
+      return fr450_check_insn_major_constraints (vliw, major);
+
+    case bfd_mach_fr550:
+      return fr550_check_insn_major_constraints (vliw, major, insn);
+
     default:
-      rc = fr500_check_insn_major_constraints (vliw, major);
-      break;
+      return fr500_check_insn_major_constraints (vliw, major);
     }
-  return rc;
 }
 
-/* Add in insn to the VLIW vliw if possible. Return 0 if successful,
-   non-zero otherwise.  */
+/* Add in insn to the VLIW vliw if possible.
+   Return 0 if successful, non-zero otherwise.  */
+
 int
 frv_vliw_add_insn (FRV_VLIW *vliw, const CGEN_INSN *insn)
 {
-  int index;
-  CGEN_ATTR_VALUE_TYPE major;
-  CGEN_ATTR_VALUE_TYPE unit;
+  int slot_index;
+  CGEN_ATTR_VALUE_ENUM_TYPE major;
+  CGEN_ATTR_VALUE_ENUM_TYPE unit;
   VLIW_COMBO *new_vliw;
 
   if (vliw->constraint_violation || CGEN_INSN_INVALID_P (insn))
     return 1;
 
-  index = vliw->next_slot;
-  if (index >= FRV_VLIW_SIZE)
+  slot_index = vliw->next_slot;
+  if (slot_index >= FRV_VLIW_SIZE)
     return 1;
 
   unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
   if (unit == UNIT_NIL)
-    abort (); /* no UNIT specified for this insn in frv.cpu  */
+    {
+      /* xgettext:c-format */
+      opcodes_error_handler (_("internal error: bad insn unit"));
+      abort ();
+    }
 
   switch (vliw->mach)
     {
     case bfd_mach_fr400:
       major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR);
       break;
+    case bfd_mach_fr450:
+      major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR);
+      break;
+    case bfd_mach_fr550:
+      major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR550_MAJOR);
+      break;
     default:
       major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR);
       break;
     }
 
-  if (index <= 0)
+  if (slot_index <= 0)
     {
       /* Any insn can be added to slot 0.  */
       while (! match_unit (vliw, unit, (*vliw->current_vliw)[0]))
        ++vliw->current_vliw;
       vliw->major[0] = major;
+      vliw->insn[0] = insn;
       vliw->next_slot = 1;
       return 0;
     }
@@ -579,10 +899,11 @@ frv_vliw_add_insn (FRV_VLIW *vliw, const CGEN_INSN *insn)
   if (! (vliw->elf_flags & EF_FRV_NOPACK))
     {
       new_vliw = add_next_to_vliw (vliw, unit);
-      if (new_vliw && check_insn_major_constraints (vliw, major))
+      if (new_vliw && check_insn_major_constraints (vliw, major, insn))
        {
          vliw->current_vliw = new_vliw;
-         vliw->major[index] = major;
+         vliw->major[slot_index] = major;
+         vliw->insn[slot_index] = insn;
          vliw->next_slot++;
          return 0;
        }
@@ -598,138 +919,161 @@ frv_vliw_add_insn (FRV_VLIW *vliw, const CGEN_INSN *insn)
   return 1;
 }
 
-int
-spr_valid (regno)
-     long regno;
+bfd_boolean
+spr_valid (long regno)
 {
-  if (regno < 0)     return 0;
-  if (regno <= 4095) return 1;
-  return 0;
+  if (regno < 0)     return FALSE;
+  if (regno <= 4095) return TRUE;
+  return FALSE;
 }
 /* -- */
 \f
 /* -- 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 *));
-static const char * parse_even_register
-  PARAMS ((CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *));
-static const char * parse_A0
-  PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
-static const char * parse_A1
-  PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
-static const char * parse_A
-  PARAMS ((CGEN_CPU_DESC, const char **, int, long *, 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_ulo16 (cd, strp, opindex, valuep)
-     CGEN_CPU_DESC cd;
-     const char **strp;
-     int opindex;
-     unsigned long *valuep;
+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, "lo(", 3) == 0)
-       {
-         *strp += 4;
-         errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
-                                      &result_type, &value);
-         if (**strp != ')')
-           return "missing `)'";
-         ++*strp;
-         if (errmsg == NULL
-             && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
-           value &= 0xffff;
-         *valuep = value;
-         return errmsg;
-       }
-      if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
+      if (strncasecmp (*strp + 1, "tlsdesc(", 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_TLSDESC_RELAX,
+                                          &result_type, &value);
          if (**strp != ')')
            return "missing ')'";
+         if (valuep)
+           *valuep = value;
          ++*strp;
-         if (errmsg == NULL
-             && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
-           value >>= 16;
-         *valuep = value;
-         return errmsg;
+         if (errmsg)
+           return errmsg;
        }
     }
-  return cgen_parse_signed_integer (cd, strp, opindex, valuep);
+  
+  while (**strp == ' ' || **strp == '\t')
+    ++*strp;
+  
+  if (**strp != '@')
+    return "missing `@'";
+
+  ++*strp;
+
+  return NULL;
 }
 
 static const char *
-parse_uslo16 (cd, strp, opindex, valuep)
-     CGEN_CPU_DESC cd;
-     const char **strp;
-     int opindex;
-     unsigned long *valuep;
+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, "lo(", 3) == 0)
+      if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0)
        {
-         *strp += 4;
-         errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
-                                      &result_type, &value);
+         *strp += 11;
+         errmsg = parse_symbolic_address (cd, strp, opindex,
+                                          BFD_RELOC_FRV_GETTLSOFF_RELAX,
+                                          &result_type, &value);
          if (**strp != ')')
-           return "missing `)'";
+           return "missing ')'";
+         if (valuep)
+           *valuep = value;
          ++*strp;
-         if (errmsg == NULL
-             && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
-           value &= 0xffff;
-         *valuep = value;
-         return errmsg;
+         if (errmsg)
+           return errmsg;
        }
-      else if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
+    }
+  
+  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 += 9;
-         errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELLO,
-                                      &result_type, &value);
+         *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 == NULL
-             && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
-           value &= 0xffff;
-         *valuep = value;
-         return errmsg;
+         if (errmsg)
+           return errmsg;
        }
     }
-  return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
+  
+  while (**strp == ' ' || **strp == '\t')
+    ++*strp;
+  
+  if (**strp != '@')
+    return "missing `@'";
+
+  ++*strp;
+
+  return NULL;
 }
 
 static const char *
-parse_uhi16 (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;
@@ -737,73 +1081,413 @@ parse_uhi16 (cd, strp, opindex, valuep)
  
   if (**strp == '#' || **strp == '%')
     {
-      if (strncasecmp (*strp + 1, "hi(", 3) == 0)
+      if (strncasecmp (*strp + 1, "lo(", 3) == 0)
        {
          *strp += 4;
-         errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_HI16,
-                                      &result_type, &value);
+         errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
+                                      & result_type, & value);
          if (**strp != ')')
            return "missing `)'";
          ++*strp;
          if (errmsg == NULL
              && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
-           value >>= 16;
+           value &= 0xffff;
          *valuep = value;
          return errmsg;
        }
-      else if (strncasecmp (*strp + 1, "gprelhi(", 8) == 0)
+      if (strncasecmp (*strp + 1, "gprello(", 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_GPRELLO,
+                                          & 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_unsigned_integer (cd, strp, opindex, valuep);
-}
-
-static long
-parse_register_number (strp)
-     const char **strp;
-{
-  int regno;
-  if (**strp < '0' || **strp > '9')
-    return -1; /* error */
-
-  regno = **strp - '0';
-  for (++*strp; **strp >= '0' && **strp <= '9'; ++*strp)
-    regno = regno * 10 + (**strp - '0');
-
-  return regno;
-}
-
-static const char *
-parse_spr (cd, strp, table, valuep)
-     CGEN_CPU_DESC cd;
-     const char **strp;
-     CGEN_KEYWORD * table;
-     long *valuep;
-{
-  const char *save_strp;
-  long regno;
-
-  /* Check for spr index notation.  */
-  if (strncasecmp (*strp, "spr[", 4) == 0)
-    {
-      *strp += 4;
-      regno = parse_register_number (strp);
-      if (**strp != ']')
-        return "missing `]'";
+      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;
+         *valuep = value;
+         return errmsg;
+       }
+    }
+  return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
+}
+
+static const char *
+parse_uslo16 (CGEN_CPU_DESC cd,
+             const char **strp,
+             int opindex,
+             signed long *valuep)
+{
+  const char *errmsg;
+  enum cgen_parse_operand_result result_type;
+  bfd_vma value;
+  if (**strp == '#' || **strp == '%')
+    {
+      if (strncasecmp (*strp + 1, "lo(", 3) == 0)
+       {
+         *strp += 4;
+         errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
+                                      & result_type, & value);
+         if (**strp != ')')
+           return "missing `)'";
+         ++*strp;
+         if (errmsg == NULL
+             && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
+           value &= 0xffff;
+         *valuep = value;
+         return errmsg;
+       }
+      else if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
+       {
+         *strp += 9;
+         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;
+         *valuep = value;
+         return errmsg;
+       }
+    }
+  return cgen_parse_signed_integer (cd, strp, opindex, valuep);
+}
+
+static const char *
+parse_uhi16 (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, "hi(", 3) == 0)
+       {
+         *strp += 4;
+         errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_HI16,
+                                      & result_type, & value);
+         if (**strp != ')')
+           return "missing `)'";
+         ++*strp;
+         if (errmsg == NULL
+             && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
+           {
+             /* 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 = 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;
+         *valuep = value;
+         return errmsg;
+       }
+    }
+  return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
+}
+
+static long
+parse_register_number (const char **strp)
+{
+  int regno;
+
+  if (**strp < '0' || **strp > '9')
+    return -1; /* error */
+
+  regno = **strp - '0';
+  for (++*strp; **strp >= '0' && **strp <= '9'; ++*strp)
+    regno = regno * 10 + (**strp - '0');
+
+  return regno;
+}
+
+static const char *
+parse_spr (CGEN_CPU_DESC cd,
+          const char **strp,
+          CGEN_KEYWORD * table,
+          long *valuep)
+{
+  const char *save_strp;
+  long regno;
+
+  /* Check for spr index notation.  */
+  if (strncasecmp (*strp, "spr[", 4) == 0)
+    {
+      *strp += 4;
+      regno = parse_register_number (strp);
+      if (**strp != ']')
+        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;
     }
@@ -813,7 +1497,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;
     }
@@ -823,11 +1507,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;
@@ -839,56 +1522,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;
@@ -899,8 +1750,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;
@@ -916,12 +1768,11 @@ parse_u12 (cd, strp, opindex, valuep)
 }
 
 static const char *
-parse_A (cd, strp, opindex, valuep, A)
-     CGEN_CPU_DESC cd;
-     const char **strp;
-     int opindex;
-     long *valuep;
-     long A;
+parse_A (CGEN_CPU_DESC cd,
+        const char **strp,
+        int opindex,
+        unsigned long *valuep,
+        unsigned long A)
 {
   const char *errmsg;
  
@@ -933,37 +1784,34 @@ parse_A (cd, strp, opindex, valuep, A)
     return errmsg;
 
   if (*valuep != A)
-    return "Value of A operand must be 0 or 1";
+    return _("Value of A operand must be 0 or 1");
 
   return NULL;
 }
 
 static const char *
-parse_A0 (cd, strp, opindex, valuep)
-     CGEN_CPU_DESC cd;
-     const char **strp;
-     int opindex;
-     long *valuep;
+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 (cd, strp, opindex, valuep)
-     CGEN_CPU_DESC cd;
-     const char **strp;
-     int opindex;
-     long *valuep;
+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 (cd, strP, tableP, valueP)
-     CGEN_CPU_DESC  cd;
-     const char **  strP;
-     CGEN_KEYWORD * tableP;
-     long *         valueP;
+parse_even_register (CGEN_CPU_DESC  cd,
+                    const char **  strP,
+                    CGEN_KEYWORD * tableP,
+                    long *         valueP)
 {
   const char * errmsg;
   const char * saved_star_strP = * strP;
@@ -978,23 +1826,60 @@ parse_even_register (cd, strP, tableP, valueP)
 
   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);
+}
+
 /* -- */
 \f
 /* -- dis.c */
-static void print_spr
-  PARAMS ((CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned));
-static void print_hi
-  PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
-static void print_lo
-  PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
+static void
+print_at (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
+         void * dis_info,
+         long reloc_ann ATTRIBUTE_UNUSED,
+         long value ATTRIBUTE_UNUSED,
+         bfd_vma pc ATTRIBUTE_UNUSED,
+         int length ATTRIBUTE_UNUSED)
+{
+  disassemble_info *info = (disassemble_info *) dis_info;
+
+  (*info->fprintf_func) (info->stream, "@");
+}  
 
 static void
-print_spr (cd, dis_info, names, regno, attrs)
-     CGEN_CPU_DESC cd;
-     PTR dis_info;
-     CGEN_KEYWORD *names;
-     long regno;
-     unsigned int attrs;
+print_spr (CGEN_CPU_DESC cd,
+          void * dis_info,
+          CGEN_KEYWORD *names,
+          long regno,
+          unsigned int attrs)
 {
   /* Use the register index format for any unnamed registers.  */
   if (cgen_keyword_lookup_value (names, regno) == NULL)
@@ -1007,29 +1892,25 @@ print_spr (cd, dis_info, names, regno, attrs)
 }
 
 static void
-print_hi (cd, dis_info, value, attrs, pc, length)
-     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
-     PTR dis_info;
-     long value;
-     unsigned int attrs ATTRIBUTE_UNUSED;
-     bfd_vma pc ATTRIBUTE_UNUSED;
-     int length ATTRIBUTE_UNUSED;
+print_hi (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
+         void * dis_info,
+         long value,
+         unsigned int attrs ATTRIBUTE_UNUSED,
+         bfd_vma pc ATTRIBUTE_UNUSED,
+         int length ATTRIBUTE_UNUSED)
 {
   disassemble_info *info = (disassemble_info *) dis_info;
-  if (value)
-    (*info->fprintf_func) (info->stream, "0x%lx", value);
-  else
-    (*info->fprintf_func) (info->stream, "hi(0x%lx)", value);
+
+  (*info->fprintf_func) (info->stream, value ? "0x%lx" : "hi(0x%lx)", value);
 }
 
 static void
-print_lo (cd, dis_info, value, attrs, pc, length)
-     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
-     PTR dis_info;
-     long value;
-     unsigned int attrs ATTRIBUTE_UNUSED;
-     bfd_vma pc ATTRIBUTE_UNUSED;
-     int length ATTRIBUTE_UNUSED;
+print_lo (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
+         void * dis_info,
+         long value,
+         unsigned int attrs ATTRIBUTE_UNUSED,
+         bfd_vma pc ATTRIBUTE_UNUSED,
+         int length ATTRIBUTE_UNUSED)
 {
   disassemble_info *info = (disassemble_info *) dis_info;
   if (value)
This page took 0.045878 seconds and 4 git commands to generate.