Home | History | Annotate | Download | only in cpu
      1 /* Fujitsu FRV opcode support, for GNU Binutils.  -*- C -*-
      2 
      3    Copyright 2000, 2001, 2003, 2004, 2005, 2007, 2009
      4    Free Software Foundation, Inc.
      5 
      6    Contributed by Red Hat Inc; developed under contract from Fujitsu.
      7 
      8    This file is part of the GNU Binutils.
      9 
     10    This program is free software; you can redistribute it and/or modify
     11    it under the terms of the GNU General Public License as published by
     12    the Free Software Foundation; either version 3 of the License, or
     13    (at your option) any later version.
     14 
     15    This program is distributed in the hope that it will be useful,
     16    but WITHOUT ANY WARRANTY; without even the implied warranty of
     17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     18    GNU General Public License for more details.
     19 
     20    You should have received a copy of the GNU General Public License
     21    along with this program; if not, write to the Free Software
     22    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     23    MA 02110-1301, USA.  */
     24 
     25 
     26 /* This file is an addendum to frv.cpu.  Heavy use of C code isn't
     27    appropriate in .cpu files, so it resides here.  This especially applies
     28    to assembly/disassembly where parsing/printing can be quite involved.
     29    Such things aren't really part of the specification of the cpu, per se,
     30    so .cpu files provide the general framework and .opc files handle the
     31    nitty-gritty details as necessary.
     32 
     33    Each section is delimited with start and end markers.
     34 
     35    <arch>-opc.h additions use: "-- opc.h"
     36    <arch>-opc.c additions use: "-- opc.c"
     37    <arch>-asm.c additions use: "-- asm.c"
     38    <arch>-dis.c additions use: "-- dis.c"
     39    <arch>-ibd.h additions use: "-- ibd.h".  */
     40 
     41 /* -- opc.h */
     43 
     44 #undef  CGEN_DIS_HASH_SIZE
     45 #define CGEN_DIS_HASH_SIZE 128
     46 #undef  CGEN_DIS_HASH
     47 #define CGEN_DIS_HASH(buffer, value) (((value) >> 18) & 127)
     48 
     49 /* Allows reason codes to be output when assembler errors occur.  */
     50 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
     51 
     52 /* Vliw support.  */
     53 #define FRV_VLIW_SIZE 8 /* fr550 has largest vliw size of 8.  */
     54 #define PAD_VLIW_COMBO ,UNIT_NIL,UNIT_NIL,UNIT_NIL,UNIT_NIL
     55 
     56 typedef CGEN_ATTR_VALUE_ENUM_TYPE VLIW_COMBO[FRV_VLIW_SIZE];
     57 
     58 typedef struct
     59 {
     60   int                    next_slot;
     61   int                    constraint_violation;
     62   unsigned long          mach;
     63   unsigned long          elf_flags;
     64   CGEN_ATTR_VALUE_ENUM_TYPE * unit_mapping;
     65   VLIW_COMBO *           current_vliw;
     66   CGEN_ATTR_VALUE_ENUM_TYPE   major[FRV_VLIW_SIZE];
     67   const CGEN_INSN *      insn[FRV_VLIW_SIZE];
     68 } FRV_VLIW;
     69 
     70 int frv_is_branch_major (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long);
     71 int frv_is_float_major  (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long);
     72 int frv_is_media_major  (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long);
     73 int frv_is_branch_insn  (const CGEN_INSN *);
     74 int frv_is_float_insn   (const CGEN_INSN *);
     75 int frv_is_media_insn   (const CGEN_INSN *);
     76 void frv_vliw_reset     (FRV_VLIW *, unsigned long, unsigned long);
     77 int frv_vliw_add_insn   (FRV_VLIW *, const CGEN_INSN *);
     78 int spr_valid           (long);
     79 /* -- */
     80 
     81 /* -- opc.c */
     83 #include "elf/frv.h"
     84 #include <stdio.h>
     85 
     86 /* DEBUG appears below as argument of OP macro.  */
     87 #undef DEBUG
     88 
     89 /* Returns TRUE if {MAJOR,MACH} is a major branch of the FRV
     90    development tree.  */
     91 
     92 bfd_boolean
     93 frv_is_branch_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach)
     94 {
     95   switch (mach)
     96     {
     97     case bfd_mach_fr400:
     98       if (major >= FR400_MAJOR_B_1 && major <= FR400_MAJOR_B_6)
     99 	return TRUE;
    100       break;
    101     case bfd_mach_fr450:
    102       if (major >= FR450_MAJOR_B_1 && major <= FR450_MAJOR_B_6)
    103 	return TRUE;
    104       break;
    105     default:
    106       if (major >= FR500_MAJOR_B_1 && major <= FR500_MAJOR_B_6)
    107 	return TRUE;
    108       break;
    109     }
    110 
    111   return FALSE;
    112 }
    113 
    114 /* Returns TRUE if {MAJOR,MACH} supports floating point insns.  */
    115 
    116 bfd_boolean
    117 frv_is_float_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach)
    118 {
    119   switch (mach)
    120     {
    121     case bfd_mach_fr400:
    122     case bfd_mach_fr450:
    123       return FALSE;
    124     default:
    125       if (major >= FR500_MAJOR_F_1 && major <= FR500_MAJOR_F_8)
    126 	return TRUE;
    127       break;
    128     }
    129 
    130   return FALSE;
    131 }
    132 
    133 /* Returns TRUE if {MAJOR,MACH} supports media insns.  */
    134 
    135 bfd_boolean
    136 frv_is_media_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach)
    137 {
    138   switch (mach)
    139     {
    140     case bfd_mach_fr400:
    141       if (major >= FR400_MAJOR_M_1 && major <= FR400_MAJOR_M_2)
    142 	return TRUE;
    143       break;
    144     case bfd_mach_fr450:
    145       if (major >= FR450_MAJOR_M_1 && major <= FR450_MAJOR_M_6)
    146 	return TRUE;
    147       break;
    148     default:
    149       if (major >= FR500_MAJOR_M_1 && major <= FR500_MAJOR_M_8)
    150 	return TRUE;
    151       break;
    152     }
    153 
    154   return FALSE;
    155 }
    156 
    157 bfd_boolean
    158 frv_is_branch_insn (const CGEN_INSN *insn)
    159 {
    160   if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
    161 			   bfd_mach_fr400))
    162     return TRUE;
    163   if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
    164 			   bfd_mach_fr450))
    165     return TRUE;
    166   if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
    167 			   bfd_mach_fr500))
    168     return TRUE;
    169 
    170   return FALSE;
    171 }
    172 
    173 bfd_boolean
    174 frv_is_float_insn (const CGEN_INSN *insn)
    175 {
    176   if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
    177 			  bfd_mach_fr400))
    178     return TRUE;
    179   if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
    180 			  bfd_mach_fr450))
    181     return TRUE;
    182   if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
    183 			  bfd_mach_fr500))
    184     return TRUE;
    185 
    186   return FALSE;
    187 }
    188 
    189 bfd_boolean
    190 frv_is_media_insn (const CGEN_INSN *insn)
    191 {
    192   if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
    193 			  bfd_mach_fr400))
    194     return TRUE;
    195   if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
    196 			  bfd_mach_fr450))
    197     return TRUE;
    198   if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
    199 			  bfd_mach_fr500))
    200     return TRUE;
    201 
    202   return FALSE;
    203 }
    204 
    205 /* This table represents the allowable packing for vliw insns for the fr400.
    206    The fr400 has only 2 vliw slots. Represent this by not allowing any insns
    207    in the extra slots.
    208    Subsets of any given row are also allowed.  */
    209 static VLIW_COMBO fr400_allowed_vliw[] =
    210 {
    211   /*  slot0       slot1       slot2       slot3    */
    212   {  UNIT_I0,    UNIT_I1,    UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
    213   {  UNIT_I0,    UNIT_FM0,   UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
    214   {  UNIT_I0,    UNIT_B0,    UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
    215   {  UNIT_FM0,   UNIT_FM1,   UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
    216   {  UNIT_FM0,   UNIT_B0,    UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
    217   {  UNIT_B0,    UNIT_NIL,   UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
    218   {  UNIT_C,     UNIT_NIL,   UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
    219   {  UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO }
    220 };
    221 
    222 /* This table represents the allowable packing for vliw insns for the fr500.
    223    The fr500 has only 4 vliw slots. Represent this by not allowing any insns
    224    in the extra slots.
    225    Subsets of any given row are also allowed.  */
    226 static VLIW_COMBO fr500_allowed_vliw[] =
    227 {
    228   /*  slot0       slot1       slot2       slot3    */
    229   {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1  PAD_VLIW_COMBO },
    230   {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_B0   PAD_VLIW_COMBO },
    231   {  UNIT_I0,    UNIT_FM0,   UNIT_FM1,   UNIT_B0   PAD_VLIW_COMBO },
    232   {  UNIT_I0,    UNIT_FM0,   UNIT_B0,    UNIT_B1   PAD_VLIW_COMBO },
    233   {  UNIT_I0,    UNIT_I1,    UNIT_B0,    UNIT_B1   PAD_VLIW_COMBO },
    234   {  UNIT_I0,    UNIT_B0,    UNIT_B1,    UNIT_NIL  PAD_VLIW_COMBO },
    235   {  UNIT_FM0,   UNIT_FM1,   UNIT_B0,    UNIT_B1   PAD_VLIW_COMBO },
    236   {  UNIT_FM0,   UNIT_B0,    UNIT_B1,    UNIT_NIL  PAD_VLIW_COMBO },
    237   {  UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
    238   {  UNIT_C,     UNIT_NIL,   UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
    239   {  UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO }
    240 };
    241 
    242 /* This table represents the allowable packing for vliw insns for the fr550.
    243    Subsets of any given row are also allowed.  */
    244 static VLIW_COMBO fr550_allowed_vliw[] =
    245 {
    246   /*  slot0       slot1       slot2       slot3       slot4       slot5       slot6       slot7   */
    247   {  UNIT_I0,    UNIT_I1,    UNIT_I2,    UNIT_I3,    UNIT_B0,    UNIT_B1 ,   UNIT_NIL,   UNIT_NIL },
    248   {  UNIT_I0,    UNIT_I1,    UNIT_I2,    UNIT_B0,    UNIT_B1 ,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
    249   {  UNIT_I0,    UNIT_I1,    UNIT_B0,    UNIT_B1 ,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
    250   {  UNIT_I0,    UNIT_B0,    UNIT_B1 ,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
    251   {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_I2,    UNIT_FM2,   UNIT_I3,    UNIT_FM3 },
    252   {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_I2,    UNIT_FM2,   UNIT_I3,    UNIT_B0  },
    253   {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_I2,    UNIT_FM2,   UNIT_FM3,   UNIT_B0  },
    254   {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_I2,    UNIT_FM2,   UNIT_B0,    UNIT_B1  },
    255   {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_I2,    UNIT_I3,    UNIT_B0,    UNIT_B1  },
    256   {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_I2,    UNIT_B0,    UNIT_B1,    UNIT_NIL },
    257   {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_FM2,   UNIT_FM3,   UNIT_B0,    UNIT_B1  },
    258   {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_FM2,   UNIT_FM3,   UNIT_B0,    UNIT_B1  },
    259   {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_FM2,   UNIT_B0,    UNIT_B1,    UNIT_NIL },
    260   {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1,   UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL },
    261   {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_I2,    UNIT_I3,    UNIT_B0,    UNIT_B1,    UNIT_NIL },
    262   {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_I2,    UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL },
    263   {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
    264   {  UNIT_I0,    UNIT_FM0,   UNIT_FM1,   UNIT_FM2,   UNIT_FM3,   UNIT_B0,    UNIT_B1,    UNIT_NIL },
    265   {  UNIT_I0,    UNIT_FM0,   UNIT_FM1,   UNIT_FM2,   UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL },
    266   {  UNIT_I0,    UNIT_FM0,   UNIT_FM1,   UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
    267   {  UNIT_I0,    UNIT_FM0,   UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
    268   {  UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
    269   {  UNIT_C,     UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
    270   {  UNIT_FM0,   UNIT_FM1,   UNIT_FM2,   UNIT_FM3,   UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL },
    271   {  UNIT_FM0,   UNIT_FM1,   UNIT_FM2,   UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
    272   {  UNIT_FM0,   UNIT_FM1,   UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
    273   {  UNIT_FM0,   UNIT_B0,    UNIT_B1,    UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL },
    274   {  UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL }
    275 };
    276 
    277 /* Some insns are assigned specialized implementation units which map to
    278    different actual implementation units on different machines.  These
    279    tables perform that mapping.  */
    280 static CGEN_ATTR_VALUE_ENUM_TYPE fr400_unit_mapping[] =
    281 {
    282 /* unit in insn    actual unit */
    283 /* NIL      */     UNIT_NIL,
    284 /* I0       */     UNIT_I0,
    285 /* I1       */     UNIT_I1,
    286 /* I01      */     UNIT_I01,
    287 /* I2       */     UNIT_NIL, /* no I2 or I3 unit */
    288 /* I3       */     UNIT_NIL,
    289 /* IALL     */     UNIT_I01, /* only I0 and I1 units */
    290 /* FM0      */     UNIT_FM0,
    291 /* FM1      */     UNIT_FM1,
    292 /* FM01     */     UNIT_FM01,
    293 /* FM2      */     UNIT_NIL, /* no F2 or M2 units */
    294 /* FM3      */     UNIT_NIL, /* no F3 or M3 units */
    295 /* FMALL    */     UNIT_FM01,/* Only F0,F1,M0,M1 units */
    296 /* FMLOW    */     UNIT_FM0, /* Only F0,M0 units */
    297 /* B0       */     UNIT_B0,  /* branches only in B0 unit.  */
    298 /* B1       */     UNIT_B0,
    299 /* B01      */     UNIT_B0,
    300 /* C        */     UNIT_C,
    301 /* MULT-DIV */     UNIT_I0,  /* multiply and divide only in I0  unit.  */
    302 /* IACC     */     UNIT_I01, /* iacc multiply       in I0 or I1 unit.  */
    303 /* LOAD     */     UNIT_I0,  /* load                only in I0  unit.  */
    304 /* STORE    */     UNIT_I0,  /* store               only in I0  unit.  */
    305 /* SCAN     */     UNIT_I0,  /* scan                only in I0  unit.  */
    306 /* DCPL     */     UNIT_C,   /* dcpl                only in C   unit.  */
    307 /* MDUALACC */     UNIT_FM0, /* media dual acc insn only in FM0 unit.  */
    308 /* MDCUTSSI */     UNIT_FM0, /* mdcutssi            only in FM0 unit.  */
    309 /* MCLRACC-1*/     UNIT_FM0  /* mclracc,A==1   insn only in FM0 unit.  */
    310 };
    311 
    312 /* Some insns are assigned specialized implementation units which map to
    313    different actual implementation units on different machines.  These
    314    tables perform that mapping.  */
    315 static CGEN_ATTR_VALUE_ENUM_TYPE fr450_unit_mapping[] =
    316 {
    317 /* unit in insn    actual unit */
    318 /* NIL      */     UNIT_NIL,
    319 /* I0       */     UNIT_I0,
    320 /* I1       */     UNIT_I1,
    321 /* I01      */     UNIT_I01,
    322 /* I2       */     UNIT_NIL, /* no I2 or I3 unit */
    323 /* I3       */     UNIT_NIL,
    324 /* IALL     */     UNIT_I01, /* only I0 and I1 units */
    325 /* FM0      */     UNIT_FM0,
    326 /* FM1      */     UNIT_FM1,
    327 /* FM01     */     UNIT_FM01,
    328 /* FM2      */     UNIT_NIL, /* no F2 or M2 units */
    329 /* FM3      */     UNIT_NIL, /* no F3 or M3 units */
    330 /* FMALL    */     UNIT_FM01,/* Only F0,F1,M0,M1 units */
    331 /* FMLOW    */     UNIT_FM0, /* Only F0,M0 units */
    332 /* B0       */     UNIT_B0,  /* branches only in B0 unit.  */
    333 /* B1       */     UNIT_B0,
    334 /* B01      */     UNIT_B0,
    335 /* C        */     UNIT_C,
    336 /* MULT-DIV */     UNIT_I0,  /* multiply and divide only in I0  unit.  */
    337 /* IACC     */     UNIT_I01, /* iacc multiply       in I0 or I1 unit.  */
    338 /* LOAD     */     UNIT_I0,  /* load                only in I0  unit.  */
    339 /* STORE    */     UNIT_I0,  /* store               only in I0  unit.  */
    340 /* SCAN     */     UNIT_I0,  /* scan                only in I0  unit.  */
    341 /* DCPL     */     UNIT_I0,  /* dcpl                only in I0  unit.  */
    342 /* MDUALACC */     UNIT_FM0, /* media dual acc insn only in FM0 unit.  */
    343 /* MDCUTSSI */     UNIT_FM01, /* mdcutssi           in FM0 or FM1.  */
    344 /* MCLRACC-1*/     UNIT_FM0  /* mclracc,A==1   insn only in FM0 unit.  */
    345 };
    346 
    347 static CGEN_ATTR_VALUE_ENUM_TYPE fr500_unit_mapping[] =
    348 {
    349 /* unit in insn    actual unit */
    350 /* NIL      */     UNIT_NIL,
    351 /* I0       */     UNIT_I0,
    352 /* I1       */     UNIT_I1,
    353 /* I01      */     UNIT_I01,
    354 /* I2       */     UNIT_NIL, /* no I2 or I3 unit */
    355 /* I3       */     UNIT_NIL,
    356 /* IALL     */     UNIT_I01, /* only I0 and I1 units */
    357 /* FM0      */     UNIT_FM0,
    358 /* FM1      */     UNIT_FM1,
    359 /* FM01     */     UNIT_FM01,
    360 /* FM2      */     UNIT_NIL, /* no F2 or M2 units */
    361 /* FM3      */     UNIT_NIL, /* no F3 or M2 units */
    362 /* FMALL    */     UNIT_FM01,/* Only F0,F1,M0,M1 units */
    363 /* FMLOW    */     UNIT_FM0, /* Only F0,M0 units */
    364 /* B0       */     UNIT_B0,
    365 /* B1       */     UNIT_B1,
    366 /* B01      */     UNIT_B01,
    367 /* C        */     UNIT_C,
    368 /* MULT-DIV */     UNIT_I01, /* multiply and divide in I0 or I1 unit.  */
    369 /* IACC     */     UNIT_NIL, /* iacc multiply       not implemented */
    370 /* LOAD     */     UNIT_I01, /* load                in I0 or I1 unit.  */
    371 /* STORE    */     UNIT_I0,  /* store               only in I0 unit.  */
    372 /* SCAN     */     UNIT_I01, /* scan                in I0 or I1 unit.  */
    373 /* DCPL     */     UNIT_C,   /* dcpl                only in C unit.  */
    374 /* MDUALACC */     UNIT_FM0, /* media dual acc insn only in FM0 unit.  */
    375 /* MDCUTSSI */     UNIT_FM0, /* mdcutssi            only in FM0 unit.  */
    376 /* MCLRACC-1*/     UNIT_FM01 /* mclracc,A==1 in FM0 or FM1 unit.  */
    377 };
    378 
    379 static CGEN_ATTR_VALUE_ENUM_TYPE fr550_unit_mapping[] =
    380 {
    381 /* unit in insn    actual unit */
    382 /* NIL      */     UNIT_NIL,
    383 /* I0       */     UNIT_I0,
    384 /* I1       */     UNIT_I1,
    385 /* I01      */     UNIT_I01,
    386 /* I2       */     UNIT_I2,
    387 /* I3       */     UNIT_I3,
    388 /* IALL     */     UNIT_IALL,
    389 /* FM0      */     UNIT_FM0,
    390 /* FM1      */     UNIT_FM1,
    391 /* FM01     */     UNIT_FM01,
    392 /* FM2      */     UNIT_FM2,
    393 /* FM3      */     UNIT_FM3,
    394 /* FMALL    */     UNIT_FMALL,
    395 /* FMLOW    */     UNIT_FM01, /* Only F0,F1,M0,M1 units */
    396 /* B0       */     UNIT_B0,
    397 /* B1       */     UNIT_B1,
    398 /* B01      */     UNIT_B01,
    399 /* C        */     UNIT_C,
    400 /* MULT-DIV */     UNIT_I01,  /* multiply and divide in I0 or I1 unit.    */
    401 /* IACC     */     UNIT_NIL,  /* iacc multiply       not implemented.     */
    402 /* LOAD     */     UNIT_I01,  /* load                in I0 or I1 unit.    */
    403 /* STORE    */     UNIT_I01,  /* store               in I0 or I1 unit.    */
    404 /* SCAN     */     UNIT_IALL, /* scan                in any integer unit. */
    405 /* DCPL     */     UNIT_I0,   /* dcpl                only in I0 unit.     */
    406 /* MDUALACC */     UNIT_FMALL,/* media dual acc insn in all media units   */
    407 /* MDCUTSSI */     UNIT_FM01, /* mdcutssi            in FM0 or FM1 unit.  */
    408 /* MCLRACC-1*/     UNIT_FM01  /* mclracc,A==1 in FM0 or FM1 unit.         */
    409 };
    410 
    411 void
    412 frv_vliw_reset (FRV_VLIW *vliw, unsigned long mach, unsigned long elf_flags)
    413 {
    414   vliw->next_slot = 0;
    415   vliw->constraint_violation = 0;
    416   vliw->mach = mach;
    417   vliw->elf_flags = elf_flags;
    418 
    419   switch (mach)
    420     {
    421     case bfd_mach_fr400:
    422       vliw->current_vliw = fr400_allowed_vliw;
    423       vliw->unit_mapping = fr400_unit_mapping;
    424       break;
    425     case bfd_mach_fr450:
    426       vliw->current_vliw = fr400_allowed_vliw;
    427       vliw->unit_mapping = fr450_unit_mapping;
    428       break;
    429     case bfd_mach_fr550:
    430       vliw->current_vliw = fr550_allowed_vliw;
    431       vliw->unit_mapping = fr550_unit_mapping;
    432       break;
    433     default:
    434       vliw->current_vliw = fr500_allowed_vliw;
    435       vliw->unit_mapping = fr500_unit_mapping;
    436       break;
    437     }
    438 }
    439 
    440 /* Return TRUE if unit1 is a match for unit2.
    441    Unit1 comes from the insn's UNIT attribute. unit2 comes from one of the
    442    *_allowed_vliw tables above.  */
    443 static bfd_boolean
    444 match_unit (FRV_VLIW *vliw,
    445 	    CGEN_ATTR_VALUE_ENUM_TYPE unit1, CGEN_ATTR_VALUE_ENUM_TYPE unit2)
    446 {
    447   /* Map any specialized implementation units to actual ones.  */
    448   unit1 = vliw->unit_mapping[unit1];
    449 
    450   if (unit1 == unit2)
    451     return TRUE;
    452   if (unit1 < unit2)
    453     return FALSE;
    454 
    455   switch (unit1)
    456     {
    457     case UNIT_I01:
    458     case UNIT_FM01:
    459     case UNIT_B01:
    460       /* The 01 versions of these units are within 2 enums of the 0 or 1
    461 	 versions.  */
    462       if (unit1 - unit2 <= 2)
    463 	return TRUE;
    464       break;
    465     case UNIT_IALL:
    466     case UNIT_FMALL:
    467       /* The ALL versions of these units are within 5 enums of the 0, 1, 2 or 3
    468 	 versions.  */
    469       if (unit1 - unit2 <= 5)
    470 	return TRUE;
    471       break;
    472     default:
    473       break;
    474     }
    475 
    476   return FALSE;
    477 }
    478 
    479 /* Return TRUE if the vliws match, FALSE otherwise.  */
    480 
    481 static bfd_boolean
    482 match_vliw (VLIW_COMBO *vliw1, VLIW_COMBO *vliw2, int vliw_size)
    483 {
    484   int i;
    485 
    486   for (i = 0; i < vliw_size; ++i)
    487     if ((*vliw1)[i] != (*vliw2)[i])
    488       return FALSE;
    489 
    490   return TRUE;
    491 }
    492 
    493 /* Find the next vliw vliw in the table that can accomodate the new insn.
    494    If one is found then return it. Otherwise return NULL.  */
    495 
    496 static VLIW_COMBO *
    497 add_next_to_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE unit)
    498 {
    499   int           next    = vliw->next_slot;
    500   VLIW_COMBO    *current = vliw->current_vliw;
    501   VLIW_COMBO    *potential;
    502 
    503   if (next <= 0)
    504     {
    505       fprintf (stderr, "frv-opc.c line %d: bad vliw->next_slot value.\n",
    506 	       __LINE__);
    507       abort (); /* Should never happen.  */
    508     }
    509 
    510   /* The table is sorted by units allowed within slots, so vliws with
    511      identical starting sequences are together.  */
    512   potential = current;
    513   do
    514     {
    515       if (match_unit (vliw, unit, (*potential)[next]))
    516 	return potential;
    517       ++potential;
    518     }
    519   while (match_vliw (potential, current, next));
    520 
    521   return NULL;
    522 }
    523 
    524 /* Look for the given major insn type in the given vliw.
    525    Returns TRUE if found, FALSE otherwise.  */
    526 
    527 static bfd_boolean
    528 find_major_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
    529 {
    530   int i;
    531 
    532   for (i = 0; i < vliw->next_slot; ++i)
    533     if (vliw->major[i] == major)
    534       return TRUE;
    535 
    536   return FALSE;
    537 }
    538 
    539 /* Check for constraints between the insns in the vliw due to major insn
    540    types.  */
    541 
    542 static bfd_boolean
    543 fr400_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
    544 {
    545   /* In the cpu file, all media insns are represented as being allowed in
    546      both media units. This makes it easier since this is the case for fr500.
    547      Catch the invalid combinations here.  Insns of major class FR400_MAJOR_M_2
    548      cannot coexist with any other media insn in a vliw.  */
    549   switch (major)
    550     {
    551     case FR400_MAJOR_M_2:
    552       return ! find_major_in_vliw (vliw, FR400_MAJOR_M_1)
    553 	&&   ! find_major_in_vliw (vliw, FR400_MAJOR_M_2);
    554     case FR400_MAJOR_M_1:
    555       return ! find_major_in_vliw (vliw, FR400_MAJOR_M_2);
    556     default:
    557       break;
    558     }
    559   return TRUE;
    560 }
    561 
    562 static bfd_boolean
    563 fr450_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
    564 {
    565   CGEN_ATTR_VALUE_ENUM_TYPE other_major;
    566 
    567   /* Our caller guarantees there's at least one other instruction.  */
    568   other_major = CGEN_INSN_ATTR_VALUE (vliw->insn[0], CGEN_INSN_FR450_MAJOR);
    569 
    570   /* (M4, M5) and (M4, M6) are allowed.  */
    571   if (other_major == FR450_MAJOR_M_4)
    572     if (major == FR450_MAJOR_M_5 || major == FR450_MAJOR_M_6)
    573       return TRUE;
    574 
    575   /* Otherwise, instructions in even-numbered media categories cannot be
    576      executed in parallel with other media instructions.  */
    577   switch (major)
    578     {
    579     case FR450_MAJOR_M_2:
    580     case FR450_MAJOR_M_4:
    581     case FR450_MAJOR_M_6:
    582       return !(other_major >= FR450_MAJOR_M_1
    583 	       && other_major <= FR450_MAJOR_M_6);
    584 
    585     case FR450_MAJOR_M_1:
    586     case FR450_MAJOR_M_3:
    587     case FR450_MAJOR_M_5:
    588       return !(other_major == FR450_MAJOR_M_2
    589 	       || other_major == FR450_MAJOR_M_4
    590 	       || other_major == FR450_MAJOR_M_6);
    591 
    592     default:
    593       return TRUE;
    594     }
    595 }
    596 
    597 static bfd_boolean
    598 find_unit_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE unit)
    599 {
    600   int i;
    601 
    602   for (i = 0; i < vliw->next_slot; ++i)
    603     if (CGEN_INSN_ATTR_VALUE (vliw->insn[i], CGEN_INSN_UNIT) == unit)
    604       return TRUE;
    605 
    606   return FALSE; /* Not found.  */
    607 }
    608 
    609 static bfd_boolean
    610 find_major_in_slot (FRV_VLIW *vliw,
    611 		    CGEN_ATTR_VALUE_ENUM_TYPE major,
    612 		    CGEN_ATTR_VALUE_ENUM_TYPE slot)
    613 {
    614   int i;
    615 
    616   for (i = 0; i < vliw->next_slot; ++i)
    617     if (vliw->major[i] == major && (*vliw->current_vliw)[i] == slot)
    618       return TRUE;
    619 
    620   return FALSE;
    621 }
    622 
    623 static bfd_boolean
    624 fr550_find_media_in_vliw (FRV_VLIW *vliw)
    625 {
    626   int i;
    627 
    628   for (i = 0; i < vliw->next_slot; ++i)
    629     {
    630       if (vliw->major[i] < FR550_MAJOR_M_1 || vliw->major[i] > FR550_MAJOR_M_5)
    631 	continue;
    632 
    633       /* Found a media insn, however, MNOP and MCLRACC don't count.  */
    634       if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MNOP
    635 	  || CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MCLRACC_0
    636 	  || CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MCLRACC_1)
    637 	continue;
    638 
    639       return TRUE; /* Found one.  */
    640     }
    641 
    642   return FALSE;
    643 }
    644 
    645 static bfd_boolean
    646 fr550_find_float_in_vliw (FRV_VLIW *vliw)
    647 {
    648   int i;
    649 
    650   for (i = 0; i < vliw->next_slot; ++i)
    651     {
    652       if (vliw->major[i] < FR550_MAJOR_F_1 || vliw->major[i] > FR550_MAJOR_F_4)
    653 	continue;
    654 
    655       /* Found a floating point insn, however, FNOP doesn't count.  */
    656       if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_FNOP)
    657 	continue;
    658 
    659       return TRUE; /* Found one.  */
    660     }
    661 
    662   return FALSE;
    663 }
    664 
    665 static bfd_boolean
    666 fr550_check_insn_major_constraints (FRV_VLIW *vliw,
    667 				    CGEN_ATTR_VALUE_ENUM_TYPE major,
    668 				    const CGEN_INSN *insn)
    669 {
    670   CGEN_ATTR_VALUE_ENUM_TYPE unit;
    671   CGEN_ATTR_VALUE_ENUM_TYPE slot = (*vliw->current_vliw)[vliw->next_slot];
    672   switch (slot)
    673     {
    674     case UNIT_I2:
    675       /* If it's a store, then there must be another store in I1 */
    676       unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
    677       if (unit == UNIT_STORE)
    678 	return find_unit_in_vliw (vliw, UNIT_STORE);
    679       break;
    680     case UNIT_FM2:
    681     case UNIT_FM3:
    682       /* Floating point insns other than FNOP in slot f2 or f3 cannot coexist
    683 	 with media insns.  */
    684       if (major >= FR550_MAJOR_F_1 && major <= FR550_MAJOR_F_4
    685 	  && CGEN_INSN_NUM (insn) != FRV_INSN_FNOP)
    686 	return ! fr550_find_media_in_vliw (vliw);
    687       /* Media insns other than MNOP in slot m2 or m3 cannot coexist with
    688 	 floating point insns.  */
    689       if (major >= FR550_MAJOR_M_1 && major <= FR550_MAJOR_M_5
    690 	  && CGEN_INSN_NUM (insn) != FRV_INSN_MNOP)
    691 	return ! fr550_find_float_in_vliw (vliw);
    692       /* F-2 in slot f2 or f3 cannot coexist with F-2 or F-4 in slot f1 or f2
    693 	 respectively.  */
    694       if (major == FR550_MAJOR_F_2)
    695 	return ! find_major_in_slot (vliw, FR550_MAJOR_F_2,
    696 				     slot - (UNIT_FM2 - UNIT_FM0))
    697 	  &&   ! find_major_in_slot (vliw, FR550_MAJOR_F_4,
    698 				     slot - (UNIT_FM2 - UNIT_FM0));
    699       /* M-2 or M-5 in slot m2 or m3 cannot coexist with M-2 in slot m1 or m2
    700 	 respectively.  */
    701       if (major == FR550_MAJOR_M_2 || major == FR550_MAJOR_M_5)
    702 	return ! find_major_in_slot (vliw, FR550_MAJOR_M_2,
    703 				     slot - (UNIT_FM2 - UNIT_FM0));
    704       /* M-4 in slot m2 or m3 cannot coexist with M-4 in slot m1 or m2
    705 	 respectively.  */
    706       if (major == FR550_MAJOR_M_4)
    707 	return ! find_major_in_slot (vliw, FR550_MAJOR_M_4,
    708 				     slot - (UNIT_FM2 - UNIT_FM0));
    709       break;
    710     default:
    711       break;
    712     }
    713   return TRUE; /* All OK.  */
    714 }
    715 
    716 static bfd_boolean
    717 fr500_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
    718 {
    719   /* TODO: A table might be faster for some of the more complex instances
    720      here.  */
    721   switch (major)
    722     {
    723     case FR500_MAJOR_I_1:
    724     case FR500_MAJOR_I_4:
    725     case FR500_MAJOR_I_5:
    726     case FR500_MAJOR_I_6:
    727     case FR500_MAJOR_B_1:
    728     case FR500_MAJOR_B_2:
    729     case FR500_MAJOR_B_3:
    730     case FR500_MAJOR_B_4:
    731     case FR500_MAJOR_B_5:
    732     case FR500_MAJOR_B_6:
    733     case FR500_MAJOR_F_4:
    734     case FR500_MAJOR_F_8:
    735     case FR500_MAJOR_M_8:
    736       return TRUE; /* OK */
    737     case FR500_MAJOR_I_2:
    738       /* Cannot coexist with I-3 insn.  */
    739       return ! find_major_in_vliw (vliw, FR500_MAJOR_I_3);
    740     case FR500_MAJOR_I_3:
    741       /* Cannot coexist with I-2 insn.  */
    742       return ! find_major_in_vliw (vliw, FR500_MAJOR_I_2);
    743     case FR500_MAJOR_F_1:
    744     case FR500_MAJOR_F_2:
    745       /* Cannot coexist with F-5, F-6, or M-7 insn.  */
    746       return ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
    747 	&&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
    748 	&&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
    749     case FR500_MAJOR_F_3:
    750       /* Cannot coexist with F-7, or M-7 insn.  */
    751       return ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
    752 	&&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
    753     case FR500_MAJOR_F_5:
    754       /* Cannot coexist with F-1, F-2, F-6, F-7, or M-7 insn.  */
    755       return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
    756 	&&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
    757 	&&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
    758 	&&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
    759 	&&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
    760     case FR500_MAJOR_F_6:
    761       /* Cannot coexist with F-1, F-2, F-5, F-6, or M-7 insn.  */
    762       return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
    763 	&&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
    764 	&&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
    765 	&&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
    766 	&&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
    767     case FR500_MAJOR_F_7:
    768       /* Cannot coexist with F-3, F-5, F-7, or M-7 insn.  */
    769       return ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
    770 	&&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
    771 	&&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
    772 	&&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
    773     case FR500_MAJOR_M_1:
    774       /* Cannot coexist with M-7 insn.  */
    775       return ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
    776     case FR500_MAJOR_M_2:
    777     case FR500_MAJOR_M_3:
    778       /* Cannot coexist with M-5, M-6 or M-7 insn.  */
    779       return ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
    780 	&&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
    781 	&&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
    782     case FR500_MAJOR_M_4:
    783       /* Cannot coexist with M-6 insn.  */
    784       return ! find_major_in_vliw (vliw, FR500_MAJOR_M_6);
    785     case FR500_MAJOR_M_5:
    786       /* Cannot coexist with M-2, M-3, M-5, M-6  or M-7 insn.  */
    787       return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
    788 	&&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
    789 	&&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
    790 	&&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
    791 	&&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
    792     case FR500_MAJOR_M_6:
    793       /* Cannot coexist with M-2, M-3, M-4, M-5, M-6  or M-7 insn.  */
    794       return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
    795 	&&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
    796 	&&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_4)
    797 	&&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
    798 	&&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
    799 	&&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
    800     case FR500_MAJOR_M_7:
    801       /* Cannot coexist with M-1, M-2, M-3, M-5, M-6  or M-7 insn.  */
    802       return ! find_major_in_vliw (vliw, FR500_MAJOR_M_1)
    803 	&&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
    804 	&&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
    805 	&&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
    806 	&&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
    807 	&&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7)
    808 	&&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
    809 	&&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
    810 	&&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
    811 	&&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
    812 	&&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
    813 	&&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_7);
    814     default:
    815       fprintf (stderr, "frv-opc.c, line %d: bad major code, aborting.\n",
    816 	       __LINE__);
    817       abort ();
    818       break;
    819     }
    820   return TRUE;
    821 }
    822 
    823 static bfd_boolean
    824 check_insn_major_constraints (FRV_VLIW *vliw,
    825 			      CGEN_ATTR_VALUE_ENUM_TYPE major,
    826 			      const CGEN_INSN *insn)
    827 {
    828   switch (vliw->mach)
    829     {
    830     case bfd_mach_fr400:
    831       return fr400_check_insn_major_constraints (vliw, major);
    832 
    833     case bfd_mach_fr450:
    834       return fr450_check_insn_major_constraints (vliw, major);
    835 
    836     case bfd_mach_fr550:
    837       return fr550_check_insn_major_constraints (vliw, major, insn);
    838 
    839     default:
    840       return fr500_check_insn_major_constraints (vliw, major);
    841     }
    842 }
    843 
    844 /* Add in insn to the VLIW vliw if possible.
    845    Return 0 if successful, non-zero otherwise.  */
    846 
    847 int
    848 frv_vliw_add_insn (FRV_VLIW *vliw, const CGEN_INSN *insn)
    849 {
    850   int slot_index;
    851   CGEN_ATTR_VALUE_ENUM_TYPE major;
    852   CGEN_ATTR_VALUE_ENUM_TYPE unit;
    853   VLIW_COMBO *new_vliw;
    854 
    855   if (vliw->constraint_violation || CGEN_INSN_INVALID_P (insn))
    856     return 1;
    857 
    858   slot_index = vliw->next_slot;
    859   if (slot_index >= FRV_VLIW_SIZE)
    860     return 1;
    861 
    862   unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
    863   if (unit == UNIT_NIL)
    864     {
    865       fprintf (stderr, "frv-opc.c line %d: bad insn unit.\n",
    866 	       __LINE__);
    867       abort (); /* No UNIT specified for this insn in frv.cpu.  */
    868     }
    869 
    870   switch (vliw->mach)
    871     {
    872     case bfd_mach_fr400:
    873       major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR);
    874       break;
    875     case bfd_mach_fr450:
    876       major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR);
    877       break;
    878     case bfd_mach_fr550:
    879       major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR550_MAJOR);
    880       break;
    881     default:
    882       major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR);
    883       break;
    884     }
    885 
    886   if (slot_index <= 0)
    887     {
    888       /* Any insn can be added to slot 0.  */
    889       while (! match_unit (vliw, unit, (*vliw->current_vliw)[0]))
    890 	++vliw->current_vliw;
    891       vliw->major[0] = major;
    892       vliw->insn[0] = insn;
    893       vliw->next_slot = 1;
    894       return 0;
    895     }
    896 
    897   /* If there are already insns in the vliw(s) check to see that
    898      this one can be added.  Do this by finding an allowable vliw
    899      combination that can accept the new insn.  */
    900   if (! (vliw->elf_flags & EF_FRV_NOPACK))
    901     {
    902       new_vliw = add_next_to_vliw (vliw, unit);
    903       if (new_vliw && check_insn_major_constraints (vliw, major, insn))
    904 	{
    905 	  vliw->current_vliw = new_vliw;
    906 	  vliw->major[slot_index] = major;
    907 	  vliw->insn[slot_index] = insn;
    908 	  vliw->next_slot++;
    909 	  return 0;
    910 	}
    911 
    912       /* The frv machine supports all packing conbinations.  If we fail,
    913 	 to add the insn, then it could not be handled as if it was the fr500.
    914 	 Just return as if it was handled ok.  */
    915       if (vliw->mach == bfd_mach_frv)
    916 	return 0;
    917     }
    918 
    919   vliw->constraint_violation = 1;
    920   return 1;
    921 }
    922 
    923 bfd_boolean
    924 spr_valid (long regno)
    925 {
    926   if (regno < 0)     return FALSE;
    927   if (regno <= 4095) return TRUE;
    928   return FALSE;
    929 }
    930 /* -- */
    931 
    932 /* -- asm.c */
    934 inline static const char *
    935 parse_symbolic_address (CGEN_CPU_DESC cd,
    936 			const char **strp,
    937 			int opindex,
    938 			int opinfo,
    939 			enum cgen_parse_operand_result *resultp,
    940 			bfd_vma *valuep)
    941 {
    942   enum cgen_parse_operand_result result_type;
    943   const char *errmsg = (* cd->parse_operand_fn)
    944     (cd, CGEN_PARSE_OPERAND_SYMBOLIC, strp, opindex, opinfo,
    945      &result_type, valuep);
    946 
    947   if (errmsg == NULL
    948       && result_type != CGEN_PARSE_OPERAND_RESULT_QUEUED)
    949     return "symbolic expression required";
    950 
    951   if (resultp)
    952     *resultp = result_type;
    953 
    954   return errmsg;
    955 }
    956 
    957 static const char *
    958 parse_ldd_annotation (CGEN_CPU_DESC cd,
    959 		      const char **strp,
    960 		      int opindex,
    961 		      unsigned long *valuep)
    962 {
    963   const char *errmsg;
    964   enum cgen_parse_operand_result result_type;
    965   bfd_vma value;
    966 
    967   if (**strp == '#' || **strp == '%')
    968     {
    969       if (strncasecmp (*strp + 1, "tlsdesc(", 8) == 0)
    970 	{
    971 	  *strp += 9;
    972 	  errmsg = parse_symbolic_address (cd, strp, opindex,
    973 					   BFD_RELOC_FRV_TLSDESC_RELAX,
    974 					   &result_type, &value);
    975 	  if (**strp != ')')
    976 	    return "missing ')'";
    977 	  if (valuep)
    978 	    *valuep = value;
    979 	  ++*strp;
    980 	  if (errmsg)
    981 	    return errmsg;
    982 	}
    983     }
    984 
    985   while (**strp == ' ' || **strp == '\t')
    986     ++*strp;
    987 
    988   if (**strp != '@')
    989     return "missing `@'";
    990 
    991   ++*strp;
    992 
    993   return NULL;
    994 }
    995 
    996 static const char *
    997 parse_call_annotation (CGEN_CPU_DESC cd,
    998 		       const char **strp,
    999 		       int opindex,
   1000 		       unsigned long *valuep)
   1001 {
   1002   const char *errmsg;
   1003   enum cgen_parse_operand_result result_type;
   1004   bfd_vma value;
   1005 
   1006   if (**strp == '#' || **strp == '%')
   1007     {
   1008       if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0)
   1009 	{
   1010 	  *strp += 11;
   1011 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1012 					   BFD_RELOC_FRV_GETTLSOFF_RELAX,
   1013 					   &result_type, &value);
   1014 	  if (**strp != ')')
   1015 	    return "missing ')'";
   1016 	  if (valuep)
   1017 	    *valuep = value;
   1018 	  ++*strp;
   1019 	  if (errmsg)
   1020 	    return errmsg;
   1021 	}
   1022     }
   1023 
   1024   while (**strp == ' ' || **strp == '\t')
   1025     ++*strp;
   1026 
   1027   if (**strp != '@')
   1028     return "missing `@'";
   1029 
   1030   ++*strp;
   1031 
   1032   return NULL;
   1033 }
   1034 
   1035 static const char *
   1036 parse_ld_annotation (CGEN_CPU_DESC cd,
   1037 		     const char **strp,
   1038 		     int opindex,
   1039 		     unsigned long *valuep)
   1040 {
   1041   const char *errmsg;
   1042   enum cgen_parse_operand_result result_type;
   1043   bfd_vma value;
   1044 
   1045   if (**strp == '#' || **strp == '%')
   1046     {
   1047       if (strncasecmp (*strp + 1, "tlsoff(", 7) == 0)
   1048 	{
   1049 	  *strp += 8;
   1050 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1051 					   BFD_RELOC_FRV_TLSOFF_RELAX,
   1052 					   &result_type, &value);
   1053 	  if (**strp != ')')
   1054 	    return "missing ')'";
   1055 	  if (valuep)
   1056 	    *valuep = value;
   1057 	  ++*strp;
   1058 	  if (errmsg)
   1059 	    return errmsg;
   1060 	}
   1061     }
   1062 
   1063   while (**strp == ' ' || **strp == '\t')
   1064     ++*strp;
   1065 
   1066   if (**strp != '@')
   1067     return "missing `@'";
   1068 
   1069   ++*strp;
   1070 
   1071   return NULL;
   1072 }
   1073 
   1074 static const char *
   1075 parse_ulo16 (CGEN_CPU_DESC cd,
   1076 	     const char **strp,
   1077 	     int opindex,
   1078 	     unsigned long *valuep)
   1079 {
   1080   const char *errmsg;
   1081   enum cgen_parse_operand_result result_type;
   1082   bfd_vma value;
   1083 
   1084   if (**strp == '#' || **strp == '%')
   1085     {
   1086       if (strncasecmp (*strp + 1, "lo(", 3) == 0)
   1087 	{
   1088 	  *strp += 4;
   1089 	  errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
   1090 				       & result_type, & value);
   1091 	  if (**strp != ')')
   1092 	    return "missing `)'";
   1093 	  ++*strp;
   1094 	  if (errmsg == NULL
   1095 	      && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
   1096 	    value &= 0xffff;
   1097 	  *valuep = value;
   1098 	  return errmsg;
   1099 	}
   1100       if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
   1101 	{
   1102 	  *strp += 9;
   1103 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1104 					   BFD_RELOC_FRV_GPRELLO,
   1105 					   & result_type, & value);
   1106 	  if (**strp != ')')
   1107 	    return "missing ')'";
   1108 	  ++*strp;
   1109 	  *valuep = value;
   1110 	  return errmsg;
   1111 	}
   1112       else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
   1113 	{
   1114 	  *strp += 7;
   1115 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1116 					   BFD_RELOC_FRV_GOTLO,
   1117 					   & result_type, & value);
   1118 	  if (**strp != ')')
   1119 	    return "missing ')'";
   1120 	  ++*strp;
   1121 	  *valuep = value;
   1122 	  return errmsg;
   1123 	}
   1124       else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
   1125 	{
   1126 	  *strp += 15;
   1127 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1128 					   BFD_RELOC_FRV_FUNCDESC_GOTLO,
   1129 					   & result_type, & value);
   1130 	  if (**strp != ')')
   1131 	    return "missing ')'";
   1132 	  ++*strp;
   1133 	  *valuep = value;
   1134 	  return errmsg;
   1135 	}
   1136       else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
   1137 	{
   1138 	  *strp += 10;
   1139 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1140 					   BFD_RELOC_FRV_GOTOFFLO,
   1141 					   & result_type, & value);
   1142 	  if (**strp != ')')
   1143 	    return "missing ')'";
   1144 	  ++*strp;
   1145 	  *valuep = value;
   1146 	  return errmsg;
   1147 	}
   1148       else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
   1149 	{
   1150 	  *strp += 18;
   1151 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1152 					   BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
   1153 					   & result_type, & value);
   1154 	  if (**strp != ')')
   1155 	    return "missing ')'";
   1156 	  ++*strp;
   1157 	  *valuep = value;
   1158 	  return errmsg;
   1159 	}
   1160       else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0)
   1161 	{
   1162 	  *strp += 14;
   1163 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1164 					   BFD_RELOC_FRV_GOTTLSDESCLO,
   1165 					   & result_type, & value);
   1166 	  if (**strp != ')')
   1167 	    return "missing ')'";
   1168 	  ++*strp;
   1169 	  *valuep = value;
   1170 	  return errmsg;
   1171 	}
   1172       else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0)
   1173 	{
   1174 	  *strp += 11;
   1175 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1176 					   BFD_RELOC_FRV_TLSMOFFLO,
   1177 					   & result_type, & value);
   1178 	  if (**strp != ')')
   1179 	    return "missing ')'";
   1180 	  ++*strp;
   1181 	  *valuep = value;
   1182 	  return errmsg;
   1183 	}
   1184       else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0)
   1185 	{
   1186 	  *strp += 13;
   1187 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1188 					   BFD_RELOC_FRV_GOTTLSOFFLO,
   1189 					   & result_type, & value);
   1190 	  if (**strp != ')')
   1191 	    return "missing ')'";
   1192 	  ++*strp;
   1193 	  *valuep = value;
   1194 	  return errmsg;
   1195 	}
   1196     }
   1197   return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
   1198 }
   1199 
   1200 static const char *
   1201 parse_uslo16 (CGEN_CPU_DESC cd,
   1202 	      const char **strp,
   1203 	      int opindex,
   1204 	      signed long *valuep)
   1205 {
   1206   const char *errmsg;
   1207   enum cgen_parse_operand_result result_type;
   1208   bfd_vma value;
   1209 
   1210   if (**strp == '#' || **strp == '%')
   1211     {
   1212       if (strncasecmp (*strp + 1, "lo(", 3) == 0)
   1213 	{
   1214 	  *strp += 4;
   1215 	  errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
   1216 				       & result_type, & value);
   1217 	  if (**strp != ')')
   1218 	    return "missing `)'";
   1219 	  ++*strp;
   1220 	  if (errmsg == NULL
   1221 	      && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
   1222 	    value &= 0xffff;
   1223 	  *valuep = value;
   1224 	  return errmsg;
   1225 	}
   1226       else if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
   1227 	{
   1228 	  *strp += 9;
   1229 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1230 					   BFD_RELOC_FRV_GPRELLO,
   1231 					   & result_type, & value);
   1232 	  if (**strp != ')')
   1233 	    return "missing ')'";
   1234 	  ++*strp;
   1235 	  *valuep = value;
   1236 	  return errmsg;
   1237 	}
   1238       else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
   1239 	{
   1240 	  *strp += 7;
   1241 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1242 					   BFD_RELOC_FRV_GOTLO,
   1243 					   & result_type, & value);
   1244 	  if (**strp != ')')
   1245 	    return "missing ')'";
   1246 	  ++*strp;
   1247 	  *valuep = value;
   1248 	  return errmsg;
   1249 	}
   1250       else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
   1251 	{
   1252 	  *strp += 15;
   1253 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1254 					   BFD_RELOC_FRV_FUNCDESC_GOTLO,
   1255 					   & result_type, & value);
   1256 	  if (**strp != ')')
   1257 	    return "missing ')'";
   1258 	  ++*strp;
   1259 	  *valuep = value;
   1260 	  return errmsg;
   1261 	}
   1262       else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
   1263 	{
   1264 	  *strp += 10;
   1265 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1266 					   BFD_RELOC_FRV_GOTOFFLO,
   1267 					   & result_type, & value);
   1268 	  if (**strp != ')')
   1269 	    return "missing ')'";
   1270 	  ++*strp;
   1271 	  *valuep = value;
   1272 	  return errmsg;
   1273 	}
   1274       else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
   1275 	{
   1276 	  *strp += 18;
   1277 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1278 					   BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
   1279 					   & result_type, & value);
   1280 	  if (**strp != ')')
   1281 	    return "missing ')'";
   1282 	  ++*strp;
   1283 	  *valuep = value;
   1284 	  return errmsg;
   1285 	}
   1286       else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0)
   1287 	{
   1288 	  *strp += 14;
   1289 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1290 					   BFD_RELOC_FRV_GOTTLSDESCLO,
   1291 					   & result_type, & value);
   1292 	  if (**strp != ')')
   1293 	    return "missing ')'";
   1294 	  ++*strp;
   1295 	  *valuep = value;
   1296 	  return errmsg;
   1297 	}
   1298       else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0)
   1299 	{
   1300 	  *strp += 11;
   1301 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1302 					   BFD_RELOC_FRV_TLSMOFFLO,
   1303 					   & result_type, & value);
   1304 	  if (**strp != ')')
   1305 	    return "missing ')'";
   1306 	  ++*strp;
   1307 	  *valuep = value;
   1308 	  return errmsg;
   1309 	}
   1310       else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0)
   1311 	{
   1312 	  *strp += 13;
   1313 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1314 					   BFD_RELOC_FRV_GOTTLSOFFLO,
   1315 					   & result_type, & value);
   1316 	  if (**strp != ')')
   1317 	    return "missing ')'";
   1318 	  ++*strp;
   1319 	  *valuep = value;
   1320 	  return errmsg;
   1321 	}
   1322     }
   1323   return cgen_parse_signed_integer (cd, strp, opindex, valuep);
   1324 }
   1325 
   1326 static const char *
   1327 parse_uhi16 (CGEN_CPU_DESC cd,
   1328 	     const char **strp,
   1329 	     int opindex,
   1330 	     unsigned long *valuep)
   1331 {
   1332   const char *errmsg;
   1333   enum cgen_parse_operand_result result_type;
   1334   bfd_vma value;
   1335 
   1336   if (**strp == '#' || **strp == '%')
   1337     {
   1338       if (strncasecmp (*strp + 1, "hi(", 3) == 0)
   1339 	{
   1340 	  *strp += 4;
   1341 	  errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_HI16,
   1342 				       & result_type, & value);
   1343 	  if (**strp != ')')
   1344 	    return "missing `)'";
   1345 	  ++*strp;
   1346 	  if (errmsg == NULL
   1347 	      && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
   1348 	    {
   1349  	      /* If value is wider than 32 bits then be
   1350  		 careful about how we extract bits 16-31.  */
   1351  	      if (sizeof (value) > 4)
   1352  		value &= (((bfd_vma)1 << 16) << 16) - 1;
   1353 
   1354 	      value >>= 16;
   1355 	    }
   1356 	  *valuep = value;
   1357 	  return errmsg;
   1358 	}
   1359       else if (strncasecmp (*strp + 1, "gprelhi(", 8) == 0)
   1360 	{
   1361 	  *strp += 9;
   1362 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1363 					   BFD_RELOC_FRV_GPRELHI,
   1364 					   & result_type, & value);
   1365 	  if (**strp != ')')
   1366 	    return "missing ')'";
   1367 	  ++*strp;
   1368 	  *valuep = value;
   1369 	  return errmsg;
   1370 	}
   1371       else if (strncasecmp (*strp + 1, "gothi(", 6) == 0)
   1372 	{
   1373 	  *strp += 7;
   1374 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1375 					   BFD_RELOC_FRV_GOTHI,
   1376 					   & result_type, & value);
   1377 	  if (**strp != ')')
   1378 	    return "missing ')'";
   1379 	  ++*strp;
   1380 	  *valuep = value;
   1381 	  return errmsg;
   1382 	}
   1383       else if (strncasecmp (*strp + 1, "gotfuncdeschi(", 14) == 0)
   1384 	{
   1385 	  *strp += 15;
   1386 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1387 					   BFD_RELOC_FRV_FUNCDESC_GOTHI,
   1388 					   & result_type, & value);
   1389 	  if (**strp != ')')
   1390 	    return "missing ')'";
   1391 	  ++*strp;
   1392 	  *valuep = value;
   1393 	  return errmsg;
   1394 	}
   1395       else if (strncasecmp (*strp + 1, "gotoffhi(", 9) == 0)
   1396 	{
   1397 	  *strp += 10;
   1398 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1399 					   BFD_RELOC_FRV_GOTOFFHI,
   1400 					   & result_type, & value);
   1401 	  if (**strp != ')')
   1402 	    return "missing ')'";
   1403 	  ++*strp;
   1404 	  *valuep = value;
   1405 	  return errmsg;
   1406 	}
   1407       else if (strncasecmp (*strp + 1, "gotofffuncdeschi(", 17) == 0)
   1408 	{
   1409 	  *strp += 18;
   1410 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1411 					   BFD_RELOC_FRV_FUNCDESC_GOTOFFHI,
   1412 					   & result_type, & value);
   1413 	  if (**strp != ')')
   1414 	    return "missing ')'";
   1415 	  ++*strp;
   1416 	  *valuep = value;
   1417 	  return errmsg;
   1418 	}
   1419       else if (strncasecmp (*strp + 1, "gottlsdeschi(", 13) == 0)
   1420 	{
   1421 	  *strp += 14;
   1422 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1423 					   BFD_RELOC_FRV_GOTTLSDESCHI,
   1424 					   &result_type, &value);
   1425 	  if (**strp != ')')
   1426 	    return "missing ')'";
   1427 	  ++*strp;
   1428 	  *valuep = value;
   1429 	  return errmsg;
   1430 	}
   1431       else if (strncasecmp (*strp + 1, "tlsmoffhi(", 10) == 0)
   1432 	{
   1433 	  *strp += 11;
   1434 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1435 					   BFD_RELOC_FRV_TLSMOFFHI,
   1436 					   & result_type, & value);
   1437 	  if (**strp != ')')
   1438 	    return "missing ')'";
   1439 	  ++*strp;
   1440 	  *valuep = value;
   1441 	  return errmsg;
   1442 	}
   1443       else if (strncasecmp (*strp + 1, "gottlsoffhi(", 12) == 0)
   1444 	{
   1445 	  *strp += 13;
   1446 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1447 					   BFD_RELOC_FRV_GOTTLSOFFHI,
   1448 					   & result_type, & value);
   1449 	  if (**strp != ')')
   1450 	    return "missing ')'";
   1451 	  ++*strp;
   1452 	  *valuep = value;
   1453 	  return errmsg;
   1454 	}
   1455     }
   1456   return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
   1457 }
   1458 
   1459 static long
   1460 parse_register_number (const char **strp)
   1461 {
   1462   int regno;
   1463 
   1464   if (**strp < '0' || **strp > '9')
   1465     return -1; /* error */
   1466 
   1467   regno = **strp - '0';
   1468   for (++*strp; **strp >= '0' && **strp <= '9'; ++*strp)
   1469     regno = regno * 10 + (**strp - '0');
   1470 
   1471   return regno;
   1472 }
   1473 
   1474 static const char *
   1475 parse_spr (CGEN_CPU_DESC cd,
   1476 	   const char **strp,
   1477 	   CGEN_KEYWORD * table,
   1478 	   long *valuep)
   1479 {
   1480   const char *save_strp;
   1481   long regno;
   1482 
   1483   /* Check for spr index notation.  */
   1484   if (strncasecmp (*strp, "spr[", 4) == 0)
   1485     {
   1486       *strp += 4;
   1487       regno = parse_register_number (strp);
   1488       if (**strp != ']')
   1489         return _("missing `]'");
   1490       ++*strp;
   1491       if (! spr_valid (regno))
   1492 	return _("Special purpose register number is out of range");
   1493       *valuep = regno;
   1494       return NULL;
   1495     }
   1496 
   1497   save_strp = *strp;
   1498   regno = parse_register_number (strp);
   1499   if (regno != -1)
   1500     {
   1501       if (! spr_valid (regno))
   1502 	return _("Special purpose register number is out of range");
   1503       *valuep = regno;
   1504       return NULL;
   1505     }
   1506 
   1507   *strp = save_strp;
   1508   return cgen_parse_keyword (cd, strp, table, valuep);
   1509 }
   1510 
   1511 static const char *
   1512 parse_d12 (CGEN_CPU_DESC cd,
   1513 	   const char **strp,
   1514 	   int opindex,
   1515 	   long *valuep)
   1516 {
   1517   const char *errmsg;
   1518   enum cgen_parse_operand_result result_type;
   1519   bfd_vma value;
   1520 
   1521   /* Check for small data reference.  */
   1522   if (**strp == '#' || **strp == '%')
   1523     {
   1524       if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
   1525         {
   1526           *strp += 9;
   1527           errmsg = parse_symbolic_address (cd, strp, opindex,
   1528 					   BFD_RELOC_FRV_GPREL12,
   1529 					   & result_type, & value);
   1530           if (**strp != ')')
   1531             return "missing `)'";
   1532           ++*strp;
   1533           *valuep = value;
   1534           return errmsg;
   1535         }
   1536       else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
   1537 	{
   1538 	  *strp += 7;
   1539 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1540 					   BFD_RELOC_FRV_GOT12,
   1541 					   & result_type, & value);
   1542 	  if (**strp != ')')
   1543 	    return "missing ')'";
   1544 	  ++*strp;
   1545 	  *valuep = value;
   1546 	  return errmsg;
   1547 	}
   1548       else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
   1549 	{
   1550 	  *strp += 15;
   1551 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1552 					   BFD_RELOC_FRV_FUNCDESC_GOT12,
   1553 					   & result_type, & value);
   1554 	  if (**strp != ')')
   1555 	    return "missing ')'";
   1556 	  ++*strp;
   1557 	  *valuep = value;
   1558 	  return errmsg;
   1559 	}
   1560       else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
   1561 	{
   1562 	  *strp += 10;
   1563 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1564 					   BFD_RELOC_FRV_GOTOFF12,
   1565 					   & result_type, & value);
   1566 	  if (**strp != ')')
   1567 	    return "missing ')'";
   1568 	  ++*strp;
   1569 	  *valuep = value;
   1570 	  return errmsg;
   1571 	}
   1572       else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
   1573 	{
   1574 	  *strp += 18;
   1575 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1576 					   BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
   1577 					   & result_type, & value);
   1578 	  if (**strp != ')')
   1579 	    return "missing ')'";
   1580 	  ++*strp;
   1581 	  *valuep = value;
   1582 	  return errmsg;
   1583 	}
   1584       else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0)
   1585 	{
   1586 	  *strp += 14;
   1587 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1588 					   BFD_RELOC_FRV_GOTTLSDESC12,
   1589 					   & result_type, & value);
   1590 	  if (**strp != ')')
   1591 	    return "missing ')'";
   1592 	  ++*strp;
   1593 	  *valuep = value;
   1594 	  return errmsg;
   1595 	}
   1596       else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0)
   1597 	{
   1598 	  *strp += 11;
   1599 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1600 					   BFD_RELOC_FRV_TLSMOFF12,
   1601 					   & result_type, & value);
   1602 	  if (**strp != ')')
   1603 	    return "missing ')'";
   1604 	  ++*strp;
   1605 	  *valuep = value;
   1606 	  return errmsg;
   1607 	}
   1608       else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0)
   1609 	{
   1610 	  *strp += 13;
   1611 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1612 					   BFD_RELOC_FRV_GOTTLSOFF12,
   1613 					   & result_type, & value);
   1614 	  if (**strp != ')')
   1615 	    return "missing ')'";
   1616 	  ++*strp;
   1617 	  *valuep = value;
   1618 	  return errmsg;
   1619 	}
   1620     }
   1621   return cgen_parse_signed_integer (cd, strp, opindex, valuep);
   1622 }
   1623 
   1624 static const char *
   1625 parse_s12 (CGEN_CPU_DESC cd,
   1626 	   const char **strp,
   1627 	   int opindex,
   1628 	   long *valuep)
   1629 {
   1630   const char *errmsg;
   1631   enum cgen_parse_operand_result result_type;
   1632   bfd_vma value;
   1633 
   1634   /* Check for small data reference.  */
   1635   if (**strp == '#' || **strp == '%')
   1636     {
   1637       if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
   1638 	{
   1639 	  *strp += 9;
   1640 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1641 					   BFD_RELOC_FRV_GPREL12,
   1642 					   & result_type, & value);
   1643 	  if (**strp != ')')
   1644 	    return "missing `)'";
   1645 	  ++*strp;
   1646 	  *valuep = value;
   1647 	  return errmsg;
   1648 	}
   1649       else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
   1650 	{
   1651 	  *strp += 7;
   1652 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1653 					   BFD_RELOC_FRV_GOT12,
   1654 					   & result_type, & value);
   1655 	  if (**strp != ')')
   1656 	    return "missing ')'";
   1657 	  ++*strp;
   1658 	  *valuep = value;
   1659 	  return errmsg;
   1660 	}
   1661       else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
   1662 	{
   1663 	  *strp += 15;
   1664 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1665 					   BFD_RELOC_FRV_FUNCDESC_GOT12,
   1666 					   & result_type, & value);
   1667 	  if (**strp != ')')
   1668 	    return "missing ')'";
   1669 	  ++*strp;
   1670 	  *valuep = value;
   1671 	  return errmsg;
   1672 	}
   1673       else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
   1674 	{
   1675 	  *strp += 10;
   1676 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1677 					   BFD_RELOC_FRV_GOTOFF12,
   1678 					   & result_type, & value);
   1679 	  if (**strp != ')')
   1680 	    return "missing ')'";
   1681 	  ++*strp;
   1682 	  *valuep = value;
   1683 	  return errmsg;
   1684 	}
   1685       else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
   1686 	{
   1687 	  *strp += 18;
   1688 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1689 					   BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
   1690 					   & result_type, & value);
   1691 	  if (**strp != ')')
   1692 	    return "missing ')'";
   1693 	  ++*strp;
   1694 	  *valuep = value;
   1695 	  return errmsg;
   1696 	}
   1697       else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0)
   1698 	{
   1699 	  *strp += 14;
   1700 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1701 					   BFD_RELOC_FRV_GOTTLSDESC12,
   1702 					   & result_type, & value);
   1703 	  if (**strp != ')')
   1704 	    return "missing ')'";
   1705 	  ++*strp;
   1706 	  *valuep = value;
   1707 	  return errmsg;
   1708 	}
   1709       else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0)
   1710 	{
   1711 	  *strp += 11;
   1712 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1713 					   BFD_RELOC_FRV_TLSMOFF12,
   1714 					   & result_type, & value);
   1715 	  if (**strp != ')')
   1716 	    return "missing ')'";
   1717 	  ++*strp;
   1718 	  *valuep = value;
   1719 	  return errmsg;
   1720 	}
   1721       else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0)
   1722 	{
   1723 	  *strp += 13;
   1724 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1725 					   BFD_RELOC_FRV_GOTTLSOFF12,
   1726 					   & result_type, & value);
   1727 	  if (**strp != ')')
   1728 	    return "missing ')'";
   1729 	  ++*strp;
   1730 	  *valuep = value;
   1731 	  return errmsg;
   1732 	}
   1733     }
   1734 
   1735   if (**strp == '#')
   1736     ++*strp;
   1737   return cgen_parse_signed_integer (cd, strp, opindex, valuep);
   1738 }
   1739 
   1740 static const char *
   1741 parse_u12 (CGEN_CPU_DESC cd,
   1742 	   const char **strp,
   1743 	   int opindex,
   1744 	   long *valuep)
   1745 {
   1746   const char *errmsg;
   1747   enum cgen_parse_operand_result result_type;
   1748   bfd_vma value;
   1749 
   1750   /* Check for small data reference.  */
   1751   if ((**strp == '#' || **strp == '%')
   1752       && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
   1753     {
   1754       *strp += 9;
   1755       errmsg = parse_symbolic_address (cd, strp, opindex,
   1756 				       BFD_RELOC_FRV_GPRELU12,
   1757 				       & result_type, & value);
   1758       if (**strp != ')')
   1759         return "missing `)'";
   1760       ++*strp;
   1761       *valuep = value;
   1762       return errmsg;
   1763     }
   1764   else
   1765     {
   1766       if (**strp == '#')
   1767         ++*strp;
   1768       return cgen_parse_signed_integer (cd, strp, opindex, valuep);
   1769     }
   1770 }
   1771 
   1772 static const char *
   1773 parse_A (CGEN_CPU_DESC cd,
   1774 	 const char **strp,
   1775 	 int opindex,
   1776 	 unsigned long *valuep,
   1777 	 unsigned long A)
   1778 {
   1779   const char *errmsg;
   1780 
   1781   if (**strp == '#')
   1782     ++*strp;
   1783 
   1784   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
   1785   if (errmsg)
   1786     return errmsg;
   1787 
   1788   if (*valuep != A)
   1789     return _("Value of A operand must be 0 or 1");
   1790 
   1791   return NULL;
   1792 }
   1793 
   1794 static const char *
   1795 parse_A0 (CGEN_CPU_DESC cd,
   1796 	  const char **strp,
   1797 	  int opindex,
   1798 	  unsigned long *valuep)
   1799 {
   1800   return parse_A (cd, strp, opindex, valuep, 0);
   1801 }
   1802 
   1803 static const char *
   1804 parse_A1 (CGEN_CPU_DESC cd,
   1805 	  const char **strp,
   1806 	  int opindex,
   1807 	  unsigned long *valuep)
   1808 {
   1809   return parse_A (cd, strp, opindex, valuep, 1);
   1810 }
   1811 
   1812 static const char *
   1813 parse_even_register (CGEN_CPU_DESC  cd,
   1814 		     const char **  strP,
   1815 		     CGEN_KEYWORD * tableP,
   1816 		     long *         valueP)
   1817 {
   1818   const char * errmsg;
   1819   const char * saved_star_strP = * strP;
   1820 
   1821   errmsg = cgen_parse_keyword (cd, strP, tableP, valueP);
   1822 
   1823   if (errmsg == NULL && ((* valueP) & 1))
   1824     {
   1825       errmsg = _("register number must be even");
   1826       * strP = saved_star_strP;
   1827     }
   1828 
   1829   return errmsg;
   1830 }
   1831 
   1832 static const char *
   1833 parse_call_label (CGEN_CPU_DESC cd,
   1834 		  const char **strp,
   1835 		  int opindex,
   1836 		  int opinfo,
   1837 		  enum cgen_parse_operand_result *resultp,
   1838 		  bfd_vma *valuep)
   1839 {
   1840   const char *errmsg;
   1841   bfd_vma value;
   1842 
   1843   /* Check for small data reference.  */
   1844   if (opinfo == 0 && (**strp == '#' || **strp == '%'))
   1845     {
   1846       if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0)
   1847 	{
   1848 	  *strp += 11;
   1849 	  errmsg = parse_symbolic_address (cd, strp, opindex,
   1850 					   BFD_RELOC_FRV_GETTLSOFF,
   1851 					   resultp, &value);
   1852 	  if (**strp != ')')
   1853 	    return _("missing `)'");
   1854 	  ++*strp;
   1855 	  *valuep = value;
   1856 	  return errmsg;
   1857 	}
   1858     }
   1859 
   1860   return cgen_parse_address (cd, strp, opindex, opinfo, resultp, valuep);
   1861 }
   1862 
   1863 /* -- */
   1864 
   1865 /* -- dis.c */
   1867 static void
   1868 print_at (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
   1869 	  void * dis_info,
   1870 	  long reloc_ann ATTRIBUTE_UNUSED,
   1871 	  long value ATTRIBUTE_UNUSED,
   1872 	  bfd_vma pc ATTRIBUTE_UNUSED,
   1873 	  int length ATTRIBUTE_UNUSED)
   1874 {
   1875   disassemble_info *info = (disassemble_info *) dis_info;
   1876 
   1877   (*info->fprintf_func) (info->stream, "@");
   1878 }
   1879 
   1880 static void
   1881 print_spr (CGEN_CPU_DESC cd,
   1882 	   void * dis_info,
   1883 	   CGEN_KEYWORD *names,
   1884 	   long regno,
   1885 	   unsigned int attrs)
   1886 {
   1887   /* Use the register index format for any unnamed registers.  */
   1888   if (cgen_keyword_lookup_value (names, regno) == NULL)
   1889     {
   1890       disassemble_info *info = (disassemble_info *) dis_info;
   1891       (*info->fprintf_func) (info->stream, "spr[%ld]", regno);
   1892     }
   1893   else
   1894     print_keyword (cd, dis_info, names, regno, attrs);
   1895 }
   1896 
   1897 static void
   1898 print_hi (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
   1899 	  void * dis_info,
   1900 	  long value,
   1901 	  unsigned int attrs ATTRIBUTE_UNUSED,
   1902 	  bfd_vma pc ATTRIBUTE_UNUSED,
   1903 	  int length ATTRIBUTE_UNUSED)
   1904 {
   1905   disassemble_info *info = (disassemble_info *) dis_info;
   1906 
   1907   (*info->fprintf_func) (info->stream, value ? "0x%lx" : "hi(0x%lx)", value);
   1908 }
   1909 
   1910 static void
   1911 print_lo (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
   1912 	  void * dis_info,
   1913 	  long value,
   1914 	  unsigned int attrs ATTRIBUTE_UNUSED,
   1915 	  bfd_vma pc ATTRIBUTE_UNUSED,
   1916 	  int length ATTRIBUTE_UNUSED)
   1917 {
   1918   disassemble_info *info = (disassemble_info *) dis_info;
   1919   if (value)
   1920     (*info->fprintf_func) (info->stream, "0x%lx", value);
   1921   else
   1922     (*info->fprintf_func) (info->stream, "lo(0x%lx)", value);
   1923 }
   1924 
   1925 /* -- */
   1926