OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [cpu/] [frv.opc] - Diff between revs 156 and 816

Only display areas with differences | Details | Blame | View Log

Rev 156 Rev 816
/* Fujitsu FRV opcode support, for GNU Binutils.  -*- C -*-
/* Fujitsu FRV opcode support, for GNU Binutils.  -*- C -*-
   Copyright 2000, 2001, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
   Copyright 2000, 2001, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
   Contributed by Red Hat Inc; developed under contract from Fujitsu.
   Contributed by Red Hat Inc; developed under contract from Fujitsu.
   This file is part of the GNU Binutils.
   This file is part of the GNU Binutils.
   This program is free software; you can redistribute it and/or modify
   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
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.
   (at your option) any later version.
   This program is distributed in the hope that it will be useful,
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   GNU General Public License for more details.
   You should have received a copy of the GNU General Public License
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
   MA 02110-1301, USA.  */
   MA 02110-1301, USA.  */
/* This file is an addendum to frv.cpu.  Heavy use of C code isn't
/* 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
   appropriate in .cpu files, so it resides here.  This especially applies
   to assembly/disassembly where parsing/printing can be quite involved.
   to assembly/disassembly where parsing/printing can be quite involved.
   Such things aren't really part of the specification of the cpu, per se,
   Such things aren't really part of the specification of the cpu, per se,
   so .cpu files provide the general framework and .opc files handle the
   so .cpu files provide the general framework and .opc files handle the
   nitty-gritty details as necessary.
   nitty-gritty details as necessary.
   Each section is delimited with start and end markers.
   Each section is delimited with start and end markers.
   -opc.h additions use: "-- opc.h"
   -opc.h additions use: "-- opc.h"
   -opc.c additions use: "-- opc.c"
   -opc.c additions use: "-- opc.c"
   -asm.c additions use: "-- asm.c"
   -asm.c additions use: "-- asm.c"
   -dis.c additions use: "-- dis.c"
   -dis.c additions use: "-- dis.c"
   -ibd.h additions use: "-- ibd.h".  */
   -ibd.h additions use: "-- ibd.h".  */


/* -- opc.h */
/* -- opc.h */
#undef  CGEN_DIS_HASH_SIZE
#undef  CGEN_DIS_HASH_SIZE
#define CGEN_DIS_HASH_SIZE 128
#define CGEN_DIS_HASH_SIZE 128
#undef  CGEN_DIS_HASH
#undef  CGEN_DIS_HASH
#define CGEN_DIS_HASH(buffer, value) (((value) >> 18) & 127)
#define CGEN_DIS_HASH(buffer, value) (((value) >> 18) & 127)
/* Allows reason codes to be output when assembler errors occur.  */
/* Allows reason codes to be output when assembler errors occur.  */
#define CGEN_VERBOSE_ASSEMBLER_ERRORS
#define CGEN_VERBOSE_ASSEMBLER_ERRORS
/* Vliw support.  */
/* Vliw support.  */
#define FRV_VLIW_SIZE 8 /* fr550 has largest vliw size of 8.  */
#define FRV_VLIW_SIZE 8 /* fr550 has largest vliw size of 8.  */
#define PAD_VLIW_COMBO ,UNIT_NIL,UNIT_NIL,UNIT_NIL,UNIT_NIL
#define PAD_VLIW_COMBO ,UNIT_NIL,UNIT_NIL,UNIT_NIL,UNIT_NIL
typedef CGEN_ATTR_VALUE_ENUM_TYPE VLIW_COMBO[FRV_VLIW_SIZE];
typedef CGEN_ATTR_VALUE_ENUM_TYPE VLIW_COMBO[FRV_VLIW_SIZE];
typedef struct
typedef struct
{
{
  int                    next_slot;
  int                    next_slot;
  int                    constraint_violation;
  int                    constraint_violation;
  unsigned long          mach;
  unsigned long          mach;
  unsigned long          elf_flags;
  unsigned long          elf_flags;
  CGEN_ATTR_VALUE_ENUM_TYPE * unit_mapping;
  CGEN_ATTR_VALUE_ENUM_TYPE * unit_mapping;
  VLIW_COMBO *           current_vliw;
  VLIW_COMBO *           current_vliw;
  CGEN_ATTR_VALUE_ENUM_TYPE   major[FRV_VLIW_SIZE];
  CGEN_ATTR_VALUE_ENUM_TYPE   major[FRV_VLIW_SIZE];
  const CGEN_INSN *      insn[FRV_VLIW_SIZE];
  const CGEN_INSN *      insn[FRV_VLIW_SIZE];
} FRV_VLIW;
} FRV_VLIW;
int frv_is_branch_major (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned 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_float_major  (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long);
int frv_is_media_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_branch_insn  (const CGEN_INSN *);
int frv_is_float_insn   (const CGEN_INSN *);
int frv_is_float_insn   (const CGEN_INSN *);
int frv_is_media_insn   (const CGEN_INSN *);
int frv_is_media_insn   (const CGEN_INSN *);
void frv_vliw_reset     (FRV_VLIW *, unsigned long, unsigned long);
void frv_vliw_reset     (FRV_VLIW *, unsigned long, unsigned long);
int frv_vliw_add_insn   (FRV_VLIW *, const CGEN_INSN *);
int frv_vliw_add_insn   (FRV_VLIW *, const CGEN_INSN *);
int spr_valid           (long);
int spr_valid           (long);
/* -- */
/* -- */


/* -- opc.c */
/* -- opc.c */
#include "elf/frv.h"
#include "elf/frv.h"
#include 
#include 
/* Returns TRUE if {MAJOR,MACH} is a major branch of the FRV
/* Returns TRUE if {MAJOR,MACH} is a major branch of the FRV
   development tree.  */
   development tree.  */
bfd_boolean
bfd_boolean
frv_is_branch_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach)
frv_is_branch_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach)
{
{
  switch (mach)
  switch (mach)
    {
    {
    case bfd_mach_fr400:
    case bfd_mach_fr400:
      if (major >= FR400_MAJOR_B_1 && major <= FR400_MAJOR_B_6)
      if (major >= FR400_MAJOR_B_1 && major <= FR400_MAJOR_B_6)
        return TRUE;
        return TRUE;
      break;
      break;
    case bfd_mach_fr450:
    case bfd_mach_fr450:
      if (major >= FR450_MAJOR_B_1 && major <= FR450_MAJOR_B_6)
      if (major >= FR450_MAJOR_B_1 && major <= FR450_MAJOR_B_6)
        return TRUE;
        return TRUE;
      break;
      break;
    default:
    default:
      if (major >= FR500_MAJOR_B_1 && major <= FR500_MAJOR_B_6)
      if (major >= FR500_MAJOR_B_1 && major <= FR500_MAJOR_B_6)
        return TRUE;
        return TRUE;
      break;
      break;
    }
    }
  return FALSE;
  return FALSE;
}
}
/* Returns TRUE if {MAJOR,MACH} supports floating point insns.  */
/* Returns TRUE if {MAJOR,MACH} supports floating point insns.  */
bfd_boolean
bfd_boolean
frv_is_float_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach)
frv_is_float_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach)
{
{
  switch (mach)
  switch (mach)
    {
    {
    case bfd_mach_fr400:
    case bfd_mach_fr400:
    case bfd_mach_fr450:
    case bfd_mach_fr450:
      return FALSE;
      return FALSE;
    default:
    default:
      if (major >= FR500_MAJOR_F_1 && major <= FR500_MAJOR_F_8)
      if (major >= FR500_MAJOR_F_1 && major <= FR500_MAJOR_F_8)
        return TRUE;
        return TRUE;
      break;
      break;
    }
    }
  return FALSE;
  return FALSE;
}
}
/* Returns TRUE if {MAJOR,MACH} supports media insns.  */
/* Returns TRUE if {MAJOR,MACH} supports media insns.  */
bfd_boolean
bfd_boolean
frv_is_media_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach)
frv_is_media_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach)
{
{
  switch (mach)
  switch (mach)
    {
    {
    case bfd_mach_fr400:
    case bfd_mach_fr400:
      if (major >= FR400_MAJOR_M_1 && major <= FR400_MAJOR_M_2)
      if (major >= FR400_MAJOR_M_1 && major <= FR400_MAJOR_M_2)
        return TRUE;
        return TRUE;
      break;
      break;
    case bfd_mach_fr450:
    case bfd_mach_fr450:
      if (major >= FR450_MAJOR_M_1 && major <= FR450_MAJOR_M_6)
      if (major >= FR450_MAJOR_M_1 && major <= FR450_MAJOR_M_6)
        return TRUE;
        return TRUE;
      break;
      break;
    default:
    default:
      if (major >= FR500_MAJOR_M_1 && major <= FR500_MAJOR_M_8)
      if (major >= FR500_MAJOR_M_1 && major <= FR500_MAJOR_M_8)
        return TRUE;
        return TRUE;
      break;
      break;
    }
    }
  return FALSE;
  return FALSE;
}
}
bfd_boolean
bfd_boolean
frv_is_branch_insn (const CGEN_INSN *insn)
frv_is_branch_insn (const CGEN_INSN *insn)
{
{
  if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
  if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
                           bfd_mach_fr400))
                           bfd_mach_fr400))
    return TRUE;
    return TRUE;
  if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
  if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
                           bfd_mach_fr450))
                           bfd_mach_fr450))
    return TRUE;
    return TRUE;
  if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
  if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
                           bfd_mach_fr500))
                           bfd_mach_fr500))
    return TRUE;
    return TRUE;
  return FALSE;
  return FALSE;
}
}
bfd_boolean
bfd_boolean
frv_is_float_insn (const CGEN_INSN *insn)
frv_is_float_insn (const CGEN_INSN *insn)
{
{
  if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
  if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
                          bfd_mach_fr400))
                          bfd_mach_fr400))
    return TRUE;
    return TRUE;
  if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
  if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
                          bfd_mach_fr450))
                          bfd_mach_fr450))
    return TRUE;
    return TRUE;
  if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
  if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
                          bfd_mach_fr500))
                          bfd_mach_fr500))
    return TRUE;
    return TRUE;
  return FALSE;
  return FALSE;
}
}
bfd_boolean
bfd_boolean
frv_is_media_insn (const CGEN_INSN *insn)
frv_is_media_insn (const CGEN_INSN *insn)
{
{
  if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
  if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
                          bfd_mach_fr400))
                          bfd_mach_fr400))
    return TRUE;
    return TRUE;
  if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
  if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
                          bfd_mach_fr450))
                          bfd_mach_fr450))
    return TRUE;
    return TRUE;
  if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
  if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
                          bfd_mach_fr500))
                          bfd_mach_fr500))
    return TRUE;
    return TRUE;
  return FALSE;
  return FALSE;
}
}
/* This table represents the allowable packing for vliw insns for the fr400.
/* This table represents the allowable packing for vliw insns for the fr400.
   The fr400 has only 2 vliw slots. Represent this by not allowing any insns
   The fr400 has only 2 vliw slots. Represent this by not allowing any insns
   in the extra slots.
   in the extra slots.
   Subsets of any given row are also allowed.  */
   Subsets of any given row are also allowed.  */
static VLIW_COMBO fr400_allowed_vliw[] =
static VLIW_COMBO fr400_allowed_vliw[] =
{
{
  /*  slot0       slot1       slot2       slot3    */
  /*  slot0       slot1       slot2       slot3    */
  {  UNIT_I0,    UNIT_I1,    UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
  {  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_FM0,   UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
  {  UNIT_I0,    UNIT_B0,    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_FM1,   UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
  {  UNIT_FM0,   UNIT_B0,    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_B0,    UNIT_NIL,   UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
  {  UNIT_C,     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 }
  {  UNIT_NIL,   UNIT_NIL,   UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO }
};
};
/* This table represents the allowable packing for vliw insns for the fr500.
/* 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
   The fr500 has only 4 vliw slots. Represent this by not allowing any insns
   in the extra slots.
   in the extra slots.
   Subsets of any given row are also allowed.  */
   Subsets of any given row are also allowed.  */
static VLIW_COMBO fr500_allowed_vliw[] =
static VLIW_COMBO fr500_allowed_vliw[] =
{
{
  /*  slot0       slot1       slot2       slot3    */
  /*  slot0       slot1       slot2       slot3    */
  {  UNIT_I0,    UNIT_FM0,   UNIT_I1,    UNIT_FM1  PAD_VLIW_COMBO },
  {  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_I1,    UNIT_B0   PAD_VLIW_COMBO },
  {  UNIT_I0,    UNIT_FM0,   UNIT_FM1,   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_FM0,   UNIT_B0,    UNIT_B1   PAD_VLIW_COMBO },
  {  UNIT_I0,    UNIT_I1,    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_I0,    UNIT_B0,    UNIT_B1,    UNIT_NIL  PAD_VLIW_COMBO },
  {  UNIT_FM0,   UNIT_FM1,   UNIT_B0,    UNIT_B1   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_FM0,   UNIT_B0,    UNIT_B1,    UNIT_NIL  PAD_VLIW_COMBO },
  {  UNIT_B0,    UNIT_B1,    UNIT_NIL,   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_C,     UNIT_NIL,   UNIT_NIL,   UNIT_NIL  PAD_VLIW_COMBO },
  {  UNIT_NIL,   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.
/* This table represents the allowable packing for vliw insns for the fr550.
   Subsets of any given row are also allowed.  */
   Subsets of any given row are also allowed.  */
static VLIW_COMBO fr550_allowed_vliw[] =
static VLIW_COMBO fr550_allowed_vliw[] =
{
{
  /*  slot0       slot1       slot2       slot3       slot4       slot5       slot6       slot7   */
  /*  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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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 }
  {  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
/* Some insns are assigned specialized implementation units which map to
   different actual implementation units on different machines.  These
   different actual implementation units on different machines.  These
   tables perform that mapping.  */
   tables perform that mapping.  */
static CGEN_ATTR_VALUE_ENUM_TYPE fr400_unit_mapping[] =
static CGEN_ATTR_VALUE_ENUM_TYPE fr400_unit_mapping[] =
{
{
/* unit in insn    actual unit */
/* unit in insn    actual unit */
/* NIL      */     UNIT_NIL,
/* NIL      */     UNIT_NIL,
/* I0       */     UNIT_I0,
/* I0       */     UNIT_I0,
/* I1       */     UNIT_I1,
/* I1       */     UNIT_I1,
/* I01      */     UNIT_I01,
/* I01      */     UNIT_I01,
/* I2       */     UNIT_NIL, /* no I2 or I3 unit */
/* I2       */     UNIT_NIL, /* no I2 or I3 unit */
/* I3       */     UNIT_NIL,
/* I3       */     UNIT_NIL,
/* IALL     */     UNIT_I01, /* only I0 and I1 units */
/* IALL     */     UNIT_I01, /* only I0 and I1 units */
/* FM0      */     UNIT_FM0,
/* FM0      */     UNIT_FM0,
/* FM1      */     UNIT_FM1,
/* FM1      */     UNIT_FM1,
/* FM01     */     UNIT_FM01,
/* FM01     */     UNIT_FM01,
/* FM2      */     UNIT_NIL, /* no F2 or M2 units */
/* FM2      */     UNIT_NIL, /* no F2 or M2 units */
/* FM3      */     UNIT_NIL, /* no F3 or M3 units */
/* FM3      */     UNIT_NIL, /* no F3 or M3 units */
/* FMALL    */     UNIT_FM01,/* Only F0,F1,M0,M1 units */
/* FMALL    */     UNIT_FM01,/* Only F0,F1,M0,M1 units */
/* FMLOW    */     UNIT_FM0, /* Only F0,M0 units */
/* FMLOW    */     UNIT_FM0, /* Only F0,M0 units */
/* B0       */     UNIT_B0,  /* branches only in B0 unit.  */
/* B0       */     UNIT_B0,  /* branches only in B0 unit.  */
/* B1       */     UNIT_B0,
/* B1       */     UNIT_B0,
/* B01      */     UNIT_B0,
/* B01      */     UNIT_B0,
/* C        */     UNIT_C,
/* C        */     UNIT_C,
/* MULT-DIV */     UNIT_I0,  /* multiply and divide only in I0  unit.  */
/* MULT-DIV */     UNIT_I0,  /* multiply and divide only in I0  unit.  */
/* IACC     */     UNIT_I01, /* iacc multiply       in I0 or I1 unit.  */
/* IACC     */     UNIT_I01, /* iacc multiply       in I0 or I1 unit.  */
/* LOAD     */     UNIT_I0,  /* load                only in I0  unit.  */
/* LOAD     */     UNIT_I0,  /* load                only in I0  unit.  */
/* STORE    */     UNIT_I0,  /* store               only in I0  unit.  */
/* STORE    */     UNIT_I0,  /* store               only in I0  unit.  */
/* SCAN     */     UNIT_I0,  /* scan                only in I0  unit.  */
/* SCAN     */     UNIT_I0,  /* scan                only in I0  unit.  */
/* DCPL     */     UNIT_C,   /* dcpl                only in C   unit.  */
/* DCPL     */     UNIT_C,   /* dcpl                only in C   unit.  */
/* MDUALACC */     UNIT_FM0, /* media dual acc insn only in FM0 unit.  */
/* MDUALACC */     UNIT_FM0, /* media dual acc insn only in FM0 unit.  */
/* MDCUTSSI */     UNIT_FM0, /* mdcutssi            only in FM0 unit.  */
/* MDCUTSSI */     UNIT_FM0, /* mdcutssi            only in FM0 unit.  */
/* MCLRACC-1*/     UNIT_FM0  /* mclracc,A==1   insn 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
/* Some insns are assigned specialized implementation units which map to
   different actual implementation units on different machines.  These
   different actual implementation units on different machines.  These
   tables perform that mapping.  */
   tables perform that mapping.  */
static CGEN_ATTR_VALUE_ENUM_TYPE fr450_unit_mapping[] =
static CGEN_ATTR_VALUE_ENUM_TYPE fr450_unit_mapping[] =
{
{
/* unit in insn    actual unit */
/* unit in insn    actual unit */
/* NIL      */     UNIT_NIL,
/* NIL      */     UNIT_NIL,
/* I0       */     UNIT_I0,
/* I0       */     UNIT_I0,
/* I1       */     UNIT_I1,
/* I1       */     UNIT_I1,
/* I01      */     UNIT_I01,
/* I01      */     UNIT_I01,
/* I2       */     UNIT_NIL, /* no I2 or I3 unit */
/* I2       */     UNIT_NIL, /* no I2 or I3 unit */
/* I3       */     UNIT_NIL,
/* I3       */     UNIT_NIL,
/* IALL     */     UNIT_I01, /* only I0 and I1 units */
/* IALL     */     UNIT_I01, /* only I0 and I1 units */
/* FM0      */     UNIT_FM0,
/* FM0      */     UNIT_FM0,
/* FM1      */     UNIT_FM1,
/* FM1      */     UNIT_FM1,
/* FM01     */     UNIT_FM01,
/* FM01     */     UNIT_FM01,
/* FM2      */     UNIT_NIL, /* no F2 or M2 units */
/* FM2      */     UNIT_NIL, /* no F2 or M2 units */
/* FM3      */     UNIT_NIL, /* no F3 or M3 units */
/* FM3      */     UNIT_NIL, /* no F3 or M3 units */
/* FMALL    */     UNIT_FM01,/* Only F0,F1,M0,M1 units */
/* FMALL    */     UNIT_FM01,/* Only F0,F1,M0,M1 units */
/* FMLOW    */     UNIT_FM0, /* Only F0,M0 units */
/* FMLOW    */     UNIT_FM0, /* Only F0,M0 units */
/* B0       */     UNIT_B0,  /* branches only in B0 unit.  */
/* B0       */     UNIT_B0,  /* branches only in B0 unit.  */
/* B1       */     UNIT_B0,
/* B1       */     UNIT_B0,
/* B01      */     UNIT_B0,
/* B01      */     UNIT_B0,
/* C        */     UNIT_C,
/* C        */     UNIT_C,
/* MULT-DIV */     UNIT_I0,  /* multiply and divide only in I0  unit.  */
/* MULT-DIV */     UNIT_I0,  /* multiply and divide only in I0  unit.  */
/* IACC     */     UNIT_I01, /* iacc multiply       in I0 or I1 unit.  */
/* IACC     */     UNIT_I01, /* iacc multiply       in I0 or I1 unit.  */
/* LOAD     */     UNIT_I0,  /* load                only in I0  unit.  */
/* LOAD     */     UNIT_I0,  /* load                only in I0  unit.  */
/* STORE    */     UNIT_I0,  /* store               only in I0  unit.  */
/* STORE    */     UNIT_I0,  /* store               only in I0  unit.  */
/* SCAN     */     UNIT_I0,  /* scan                only in I0  unit.  */
/* SCAN     */     UNIT_I0,  /* scan                only in I0  unit.  */
/* DCPL     */     UNIT_I0,  /* dcpl                only in I0  unit.  */
/* DCPL     */     UNIT_I0,  /* dcpl                only in I0  unit.  */
/* MDUALACC */     UNIT_FM0, /* media dual acc insn only in FM0 unit.  */
/* MDUALACC */     UNIT_FM0, /* media dual acc insn only in FM0 unit.  */
/* MDCUTSSI */     UNIT_FM01, /* mdcutssi           in FM0 or FM1.  */
/* MDCUTSSI */     UNIT_FM01, /* mdcutssi           in FM0 or FM1.  */
/* MCLRACC-1*/     UNIT_FM0  /* mclracc,A==1   insn only in FM0 unit.  */
/* MCLRACC-1*/     UNIT_FM0  /* mclracc,A==1   insn only in FM0 unit.  */
};
};
static CGEN_ATTR_VALUE_ENUM_TYPE fr500_unit_mapping[] =
static CGEN_ATTR_VALUE_ENUM_TYPE fr500_unit_mapping[] =
{
{
/* unit in insn    actual unit */
/* unit in insn    actual unit */
/* NIL      */     UNIT_NIL,
/* NIL      */     UNIT_NIL,
/* I0       */     UNIT_I0,
/* I0       */     UNIT_I0,
/* I1       */     UNIT_I1,
/* I1       */     UNIT_I1,
/* I01      */     UNIT_I01,
/* I01      */     UNIT_I01,
/* I2       */     UNIT_NIL, /* no I2 or I3 unit */
/* I2       */     UNIT_NIL, /* no I2 or I3 unit */
/* I3       */     UNIT_NIL,
/* I3       */     UNIT_NIL,
/* IALL     */     UNIT_I01, /* only I0 and I1 units */
/* IALL     */     UNIT_I01, /* only I0 and I1 units */
/* FM0      */     UNIT_FM0,
/* FM0      */     UNIT_FM0,
/* FM1      */     UNIT_FM1,
/* FM1      */     UNIT_FM1,
/* FM01     */     UNIT_FM01,
/* FM01     */     UNIT_FM01,
/* FM2      */     UNIT_NIL, /* no F2 or M2 units */
/* FM2      */     UNIT_NIL, /* no F2 or M2 units */
/* FM3      */     UNIT_NIL, /* no F3 or M2 units */
/* FM3      */     UNIT_NIL, /* no F3 or M2 units */
/* FMALL    */     UNIT_FM01,/* Only F0,F1,M0,M1 units */
/* FMALL    */     UNIT_FM01,/* Only F0,F1,M0,M1 units */
/* FMLOW    */     UNIT_FM0, /* Only F0,M0 units */
/* FMLOW    */     UNIT_FM0, /* Only F0,M0 units */
/* B0       */     UNIT_B0,
/* B0       */     UNIT_B0,
/* B1       */     UNIT_B1,
/* B1       */     UNIT_B1,
/* B01      */     UNIT_B01,
/* B01      */     UNIT_B01,
/* C        */     UNIT_C,
/* C        */     UNIT_C,
/* MULT-DIV */     UNIT_I01, /* multiply and divide in I0 or I1 unit.  */
/* MULT-DIV */     UNIT_I01, /* multiply and divide in I0 or I1 unit.  */
/* IACC     */     UNIT_NIL, /* iacc multiply       not implemented */
/* IACC     */     UNIT_NIL, /* iacc multiply       not implemented */
/* LOAD     */     UNIT_I01, /* load                in I0 or I1 unit.  */
/* LOAD     */     UNIT_I01, /* load                in I0 or I1 unit.  */
/* STORE    */     UNIT_I0,  /* store               only in I0 unit.  */
/* STORE    */     UNIT_I0,  /* store               only in I0 unit.  */
/* SCAN     */     UNIT_I01, /* scan                in I0 or I1 unit.  */
/* SCAN     */     UNIT_I01, /* scan                in I0 or I1 unit.  */
/* DCPL     */     UNIT_C,   /* dcpl                only in C unit.  */
/* DCPL     */     UNIT_C,   /* dcpl                only in C unit.  */
/* MDUALACC */     UNIT_FM0, /* media dual acc insn only in FM0 unit.  */
/* MDUALACC */     UNIT_FM0, /* media dual acc insn only in FM0 unit.  */
/* MDCUTSSI */     UNIT_FM0, /* mdcutssi            only in FM0 unit.  */
/* MDCUTSSI */     UNIT_FM0, /* mdcutssi            only in FM0 unit.  */
/* MCLRACC-1*/     UNIT_FM01 /* mclracc,A==1 in FM0 or FM1 unit.  */
/* MCLRACC-1*/     UNIT_FM01 /* mclracc,A==1 in FM0 or FM1 unit.  */
};
};
static CGEN_ATTR_VALUE_ENUM_TYPE fr550_unit_mapping[] =
static CGEN_ATTR_VALUE_ENUM_TYPE fr550_unit_mapping[] =
{
{
/* unit in insn    actual unit */
/* unit in insn    actual unit */
/* NIL      */     UNIT_NIL,
/* NIL      */     UNIT_NIL,
/* I0       */     UNIT_I0,
/* I0       */     UNIT_I0,
/* I1       */     UNIT_I1,
/* I1       */     UNIT_I1,
/* I01      */     UNIT_I01,
/* I01      */     UNIT_I01,
/* I2       */     UNIT_I2,
/* I2       */     UNIT_I2,
/* I3       */     UNIT_I3,
/* I3       */     UNIT_I3,
/* IALL     */     UNIT_IALL,
/* IALL     */     UNIT_IALL,
/* FM0      */     UNIT_FM0,
/* FM0      */     UNIT_FM0,
/* FM1      */     UNIT_FM1,
/* FM1      */     UNIT_FM1,
/* FM01     */     UNIT_FM01,
/* FM01     */     UNIT_FM01,
/* FM2      */     UNIT_FM2,
/* FM2      */     UNIT_FM2,
/* FM3      */     UNIT_FM3,
/* FM3      */     UNIT_FM3,
/* FMALL    */     UNIT_FMALL,
/* FMALL    */     UNIT_FMALL,
/* FMLOW    */     UNIT_FM01, /* Only F0,F1,M0,M1 units */
/* FMLOW    */     UNIT_FM01, /* Only F0,F1,M0,M1 units */
/* B0       */     UNIT_B0,
/* B0       */     UNIT_B0,
/* B1       */     UNIT_B1,
/* B1       */     UNIT_B1,
/* B01      */     UNIT_B01,
/* B01      */     UNIT_B01,
/* C        */     UNIT_C,
/* C        */     UNIT_C,
/* MULT-DIV */     UNIT_I01,  /* multiply and divide in I0 or I1 unit.    */
/* MULT-DIV */     UNIT_I01,  /* multiply and divide in I0 or I1 unit.    */
/* IACC     */     UNIT_NIL,  /* iacc multiply       not implemented.     */
/* IACC     */     UNIT_NIL,  /* iacc multiply       not implemented.     */
/* LOAD     */     UNIT_I01,  /* load                in I0 or I1 unit.    */
/* LOAD     */     UNIT_I01,  /* load                in I0 or I1 unit.    */
/* STORE    */     UNIT_I01,  /* store               in I0 or I1 unit.    */
/* STORE    */     UNIT_I01,  /* store               in I0 or I1 unit.    */
/* SCAN     */     UNIT_IALL, /* scan                in any integer unit. */
/* SCAN     */     UNIT_IALL, /* scan                in any integer unit. */
/* DCPL     */     UNIT_I0,   /* dcpl                only in I0 unit.     */
/* DCPL     */     UNIT_I0,   /* dcpl                only in I0 unit.     */
/* MDUALACC */     UNIT_FMALL,/* media dual acc insn in all media units   */
/* MDUALACC */     UNIT_FMALL,/* media dual acc insn in all media units   */
/* MDCUTSSI */     UNIT_FM01, /* mdcutssi            in FM0 or FM1 unit.  */
/* MDCUTSSI */     UNIT_FM01, /* mdcutssi            in FM0 or FM1 unit.  */
/* MCLRACC-1*/     UNIT_FM01  /* mclracc,A==1 in FM0 or FM1 unit.         */
/* MCLRACC-1*/     UNIT_FM01  /* mclracc,A==1 in FM0 or FM1 unit.         */
};
};
void
void
frv_vliw_reset (FRV_VLIW *vliw, unsigned long mach, unsigned long elf_flags)
frv_vliw_reset (FRV_VLIW *vliw, unsigned long mach, unsigned long elf_flags)
{
{
  vliw->next_slot = 0;
  vliw->next_slot = 0;
  vliw->constraint_violation = 0;
  vliw->constraint_violation = 0;
  vliw->mach = mach;
  vliw->mach = mach;
  vliw->elf_flags = elf_flags;
  vliw->elf_flags = elf_flags;
  switch (mach)
  switch (mach)
    {
    {
    case bfd_mach_fr400:
    case bfd_mach_fr400:
      vliw->current_vliw = fr400_allowed_vliw;
      vliw->current_vliw = fr400_allowed_vliw;
      vliw->unit_mapping = fr400_unit_mapping;
      vliw->unit_mapping = fr400_unit_mapping;
      break;
      break;
    case bfd_mach_fr450:
    case bfd_mach_fr450:
      vliw->current_vliw = fr400_allowed_vliw;
      vliw->current_vliw = fr400_allowed_vliw;
      vliw->unit_mapping = fr450_unit_mapping;
      vliw->unit_mapping = fr450_unit_mapping;
      break;
      break;
    case bfd_mach_fr550:
    case bfd_mach_fr550:
      vliw->current_vliw = fr550_allowed_vliw;
      vliw->current_vliw = fr550_allowed_vliw;
      vliw->unit_mapping = fr550_unit_mapping;
      vliw->unit_mapping = fr550_unit_mapping;
      break;
      break;
    default:
    default:
      vliw->current_vliw = fr500_allowed_vliw;
      vliw->current_vliw = fr500_allowed_vliw;
      vliw->unit_mapping = fr500_unit_mapping;
      vliw->unit_mapping = fr500_unit_mapping;
      break;
      break;
    }
    }
}
}
/* Return TRUE 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
   Unit1 comes from the insn's UNIT attribute. unit2 comes from one of the
   *_allowed_vliw tables above.  */
   *_allowed_vliw tables above.  */
static bfd_boolean
static bfd_boolean
match_unit (FRV_VLIW *vliw,
match_unit (FRV_VLIW *vliw,
            CGEN_ATTR_VALUE_ENUM_TYPE unit1, CGEN_ATTR_VALUE_ENUM_TYPE unit2)
            CGEN_ATTR_VALUE_ENUM_TYPE unit1, CGEN_ATTR_VALUE_ENUM_TYPE unit2)
{
{
  /* Map any specialized implementation units to actual ones.  */
  /* Map any specialized implementation units to actual ones.  */
  unit1 = vliw->unit_mapping[unit1];
  unit1 = vliw->unit_mapping[unit1];
  if (unit1 == unit2)
  if (unit1 == unit2)
    return TRUE;
    return TRUE;
  if (unit1 < unit2)
  if (unit1 < unit2)
    return FALSE;
    return FALSE;
  switch (unit1)
  switch (unit1)
    {
    {
    case UNIT_I01:
    case UNIT_I01:
    case UNIT_FM01:
    case UNIT_FM01:
    case UNIT_B01:
    case UNIT_B01:
      /* The 01 versions of these units are within 2 enums of the 0 or 1
      /* The 01 versions of these units are within 2 enums of the 0 or 1
         versions.  */
         versions.  */
      if (unit1 - unit2 <= 2)
      if (unit1 - unit2 <= 2)
        return TRUE;
        return TRUE;
      break;
      break;
    case UNIT_IALL:
    case UNIT_IALL:
    case UNIT_FMALL:
    case UNIT_FMALL:
      /* The ALL versions of these units are within 5 enums of the 0, 1, 2 or 3
      /* The ALL versions of these units are within 5 enums of the 0, 1, 2 or 3
         versions.  */
         versions.  */
      if (unit1 - unit2 <= 5)
      if (unit1 - unit2 <= 5)
        return TRUE;
        return TRUE;
      break;
      break;
    default:
    default:
      break;
      break;
    }
    }
  return FALSE;
  return FALSE;
}
}
/* Return TRUE if the vliws match, FALSE otherwise.  */
/* Return TRUE if the vliws match, FALSE otherwise.  */
static bfd_boolean
static bfd_boolean
match_vliw (VLIW_COMBO *vliw1, VLIW_COMBO *vliw2, int vliw_size)
match_vliw (VLIW_COMBO *vliw1, VLIW_COMBO *vliw2, int vliw_size)
{
{
  int i;
  int i;
  for (i = 0; i < vliw_size; ++i)
  for (i = 0; i < vliw_size; ++i)
    if ((*vliw1)[i] != (*vliw2)[i])
    if ((*vliw1)[i] != (*vliw2)[i])
      return FALSE;
      return FALSE;
  return TRUE;
  return TRUE;
}
}
/* Find the next vliw vliw in the table that can accomodate the new insn.
/* Find the next vliw vliw in the table that can accomodate the new insn.
   If one is found then return it. Otherwise return NULL.  */
   If one is found then return it. Otherwise return NULL.  */
static VLIW_COMBO *
static VLIW_COMBO *
add_next_to_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE unit)
add_next_to_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE unit)
{
{
  int           next    = vliw->next_slot;
  int           next    = vliw->next_slot;
  VLIW_COMBO    *current = vliw->current_vliw;
  VLIW_COMBO    *current = vliw->current_vliw;
  VLIW_COMBO    *potential;
  VLIW_COMBO    *potential;
  if (next <= 0)
  if (next <= 0)
    {
    {
      fprintf (stderr, "frv-opc.c line %d: bad vliw->next_slot value.\n",
      fprintf (stderr, "frv-opc.c line %d: bad vliw->next_slot value.\n",
               __LINE__);
               __LINE__);
      abort (); /* Should never happen.  */
      abort (); /* Should never happen.  */
    }
    }
  /* The table is sorted by units allowed within slots, so vliws with
  /* The table is sorted by units allowed within slots, so vliws with
     identical starting sequences are together.  */
     identical starting sequences are together.  */
  potential = current;
  potential = current;
  do
  do
    {
    {
      if (match_unit (vliw, unit, (*potential)[next]))
      if (match_unit (vliw, unit, (*potential)[next]))
        return potential;
        return potential;
      ++potential;
      ++potential;
    }
    }
  while (match_vliw (potential, current, next));
  while (match_vliw (potential, current, next));
  return NULL;
  return NULL;
}
}
/* Look for the given major insn type in the given vliw.
/* Look for the given major insn type in the given vliw.
   Returns TRUE if found, FALSE otherwise.  */
   Returns TRUE if found, FALSE otherwise.  */
static bfd_boolean
static bfd_boolean
find_major_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
find_major_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
{
{
  int i;
  int i;
  for (i = 0; i < vliw->next_slot; ++i)
  for (i = 0; i < vliw->next_slot; ++i)
    if (vliw->major[i] == major)
    if (vliw->major[i] == major)
      return TRUE;
      return TRUE;
  return FALSE;
  return FALSE;
}
}
/* Check for constraints between the insns in the vliw due to major insn
/* Check for constraints between the insns in the vliw due to major insn
   types.  */
   types.  */
static bfd_boolean
static bfd_boolean
fr400_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
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
  /* 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.
     both media units. This makes it easier since this is the case for fr500.
     Catch the invalid combinations here.  Insns of major class FR400_MAJOR_M_2
     Catch the invalid combinations here.  Insns of major class FR400_MAJOR_M_2
     cannot coexist with any other media insn in a vliw.  */
     cannot coexist with any other media insn in a vliw.  */
  switch (major)
  switch (major)
    {
    {
    case FR400_MAJOR_M_2:
    case FR400_MAJOR_M_2:
      return ! find_major_in_vliw (vliw, FR400_MAJOR_M_1)
      return ! find_major_in_vliw (vliw, FR400_MAJOR_M_1)
        &&   ! find_major_in_vliw (vliw, FR400_MAJOR_M_2);
        &&   ! find_major_in_vliw (vliw, FR400_MAJOR_M_2);
    case FR400_MAJOR_M_1:
    case FR400_MAJOR_M_1:
      return ! find_major_in_vliw (vliw, FR400_MAJOR_M_2);
      return ! find_major_in_vliw (vliw, FR400_MAJOR_M_2);
    default:
    default:
      break;
      break;
    }
    }
  return TRUE;
  return TRUE;
}
}
static bfd_boolean
static bfd_boolean
fr450_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
fr450_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
{
{
  CGEN_ATTR_VALUE_ENUM_TYPE other_major;
  CGEN_ATTR_VALUE_ENUM_TYPE other_major;
  /* Our caller guarantees there's at least one other instruction.  */
  /* Our caller guarantees there's at least one other instruction.  */
  other_major = CGEN_INSN_ATTR_VALUE (vliw->insn[0], CGEN_INSN_FR450_MAJOR);
  other_major = CGEN_INSN_ATTR_VALUE (vliw->insn[0], CGEN_INSN_FR450_MAJOR);
  /* (M4, M5) and (M4, M6) are allowed.  */
  /* (M4, M5) and (M4, M6) are allowed.  */
  if (other_major == FR450_MAJOR_M_4)
  if (other_major == FR450_MAJOR_M_4)
    if (major == FR450_MAJOR_M_5 || major == FR450_MAJOR_M_6)
    if (major == FR450_MAJOR_M_5 || major == FR450_MAJOR_M_6)
      return TRUE;
      return TRUE;
  /* Otherwise, instructions in even-numbered media categories cannot be
  /* Otherwise, instructions in even-numbered media categories cannot be
     executed in parallel with other media instructions.  */
     executed in parallel with other media instructions.  */
  switch (major)
  switch (major)
    {
    {
    case FR450_MAJOR_M_2:
    case FR450_MAJOR_M_2:
    case FR450_MAJOR_M_4:
    case FR450_MAJOR_M_4:
    case FR450_MAJOR_M_6:
    case FR450_MAJOR_M_6:
      return !(other_major >= FR450_MAJOR_M_1
      return !(other_major >= FR450_MAJOR_M_1
               && other_major <= FR450_MAJOR_M_6);
               && other_major <= FR450_MAJOR_M_6);
    case FR450_MAJOR_M_1:
    case FR450_MAJOR_M_1:
    case FR450_MAJOR_M_3:
    case FR450_MAJOR_M_3:
    case FR450_MAJOR_M_5:
    case FR450_MAJOR_M_5:
      return !(other_major == FR450_MAJOR_M_2
      return !(other_major == FR450_MAJOR_M_2
               || other_major == FR450_MAJOR_M_4
               || other_major == FR450_MAJOR_M_4
               || other_major == FR450_MAJOR_M_6);
               || other_major == FR450_MAJOR_M_6);
    default:
    default:
      return TRUE;
      return TRUE;
    }
    }
}
}
static bfd_boolean
static bfd_boolean
find_unit_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE unit)
find_unit_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE unit)
{
{
  int i;
  int i;
  for (i = 0; i < vliw->next_slot; ++i)
  for (i = 0; i < vliw->next_slot; ++i)
    if (CGEN_INSN_ATTR_VALUE (vliw->insn[i], CGEN_INSN_UNIT) == unit)
    if (CGEN_INSN_ATTR_VALUE (vliw->insn[i], CGEN_INSN_UNIT) == unit)
      return TRUE;
      return TRUE;
  return FALSE; /* Not found.  */
  return FALSE; /* Not found.  */
}
}
static bfd_boolean
static bfd_boolean
find_major_in_slot (FRV_VLIW *vliw,
find_major_in_slot (FRV_VLIW *vliw,
                    CGEN_ATTR_VALUE_ENUM_TYPE major,
                    CGEN_ATTR_VALUE_ENUM_TYPE major,
                    CGEN_ATTR_VALUE_ENUM_TYPE slot)
                    CGEN_ATTR_VALUE_ENUM_TYPE slot)
{
{
  int i;
  int i;
  for (i = 0; i < vliw->next_slot; ++i)
  for (i = 0; i < vliw->next_slot; ++i)
    if (vliw->major[i] == major && (*vliw->current_vliw)[i] == slot)
    if (vliw->major[i] == major && (*vliw->current_vliw)[i] == slot)
      return TRUE;
      return TRUE;
  return FALSE;
  return FALSE;
}
}
static bfd_boolean
static bfd_boolean
fr550_find_media_in_vliw (FRV_VLIW *vliw)
fr550_find_media_in_vliw (FRV_VLIW *vliw)
{
{
  int i;
  int i;
  for (i = 0; i < vliw->next_slot; ++i)
  for (i = 0; i < vliw->next_slot; ++i)
    {
    {
      if (vliw->major[i] < FR550_MAJOR_M_1 || vliw->major[i] > FR550_MAJOR_M_5)
      if (vliw->major[i] < FR550_MAJOR_M_1 || vliw->major[i] > FR550_MAJOR_M_5)
        continue;
        continue;
      /* Found a media insn, however, MNOP and MCLRACC don't count.  */
      /* Found a media insn, however, MNOP and MCLRACC don't count.  */
      if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MNOP
      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_0
          || CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MCLRACC_1)
          || CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MCLRACC_1)
        continue;
        continue;
      return TRUE; /* Found one.  */
      return TRUE; /* Found one.  */
    }
    }
  return FALSE;
  return FALSE;
}
}
static bfd_boolean
static bfd_boolean
fr550_find_float_in_vliw (FRV_VLIW *vliw)
fr550_find_float_in_vliw (FRV_VLIW *vliw)
{
{
  int i;
  int i;
  for (i = 0; i < vliw->next_slot; ++i)
  for (i = 0; i < vliw->next_slot; ++i)
    {
    {
      if (vliw->major[i] < FR550_MAJOR_F_1 || vliw->major[i] > FR550_MAJOR_F_4)
      if (vliw->major[i] < FR550_MAJOR_F_1 || vliw->major[i] > FR550_MAJOR_F_4)
        continue;
        continue;
      /* Found a floating point insn, however, FNOP doesn't count.  */
      /* Found a floating point insn, however, FNOP doesn't count.  */
      if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_FNOP)
      if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_FNOP)
        continue;
        continue;
      return TRUE; /* Found one.  */
      return TRUE; /* Found one.  */
    }
    }
  return FALSE;
  return FALSE;
}
}
static bfd_boolean
static bfd_boolean
fr550_check_insn_major_constraints (FRV_VLIW *vliw,
fr550_check_insn_major_constraints (FRV_VLIW *vliw,
                                    CGEN_ATTR_VALUE_ENUM_TYPE major,
                                    CGEN_ATTR_VALUE_ENUM_TYPE major,
                                    const CGEN_INSN *insn)
                                    const CGEN_INSN *insn)
{
{
  CGEN_ATTR_VALUE_ENUM_TYPE unit;
  CGEN_ATTR_VALUE_ENUM_TYPE unit;
  CGEN_ATTR_VALUE_ENUM_TYPE slot = (*vliw->current_vliw)[vliw->next_slot];
  CGEN_ATTR_VALUE_ENUM_TYPE slot = (*vliw->current_vliw)[vliw->next_slot];
  switch (slot)
  switch (slot)
    {
    {
    case UNIT_I2:
    case UNIT_I2:
      /* If it's a store, then there must be another store in I1 */
      /* If it's a store, then there must be another store in I1 */
      unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
      unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
      if (unit == UNIT_STORE)
      if (unit == UNIT_STORE)
        return find_unit_in_vliw (vliw, UNIT_STORE);
        return find_unit_in_vliw (vliw, UNIT_STORE);
      break;
      break;
    case UNIT_FM2:
    case UNIT_FM2:
    case UNIT_FM3:
    case UNIT_FM3:
      /* Floating point insns other than FNOP in slot f2 or f3 cannot coexist
      /* Floating point insns other than FNOP in slot f2 or f3 cannot coexist
         with media insns.  */
         with media insns.  */
      if (major >= FR550_MAJOR_F_1 && major <= FR550_MAJOR_F_4
      if (major >= FR550_MAJOR_F_1 && major <= FR550_MAJOR_F_4
          && CGEN_INSN_NUM (insn) != FRV_INSN_FNOP)
          && CGEN_INSN_NUM (insn) != FRV_INSN_FNOP)
        return ! fr550_find_media_in_vliw (vliw);
        return ! fr550_find_media_in_vliw (vliw);
      /* Media insns other than MNOP in slot m2 or m3 cannot coexist with
      /* Media insns other than MNOP in slot m2 or m3 cannot coexist with
         floating point insns.  */
         floating point insns.  */
      if (major >= FR550_MAJOR_M_1 && major <= FR550_MAJOR_M_5
      if (major >= FR550_MAJOR_M_1 && major <= FR550_MAJOR_M_5
          && CGEN_INSN_NUM (insn) != FRV_INSN_MNOP)
          && CGEN_INSN_NUM (insn) != FRV_INSN_MNOP)
        return ! fr550_find_float_in_vliw (vliw);
        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
      /* F-2 in slot f2 or f3 cannot coexist with F-2 or F-4 in slot f1 or f2
         respectively.  */
         respectively.  */
      if (major == FR550_MAJOR_F_2)
      if (major == FR550_MAJOR_F_2)
        return ! find_major_in_slot (vliw, FR550_MAJOR_F_2,
        return ! find_major_in_slot (vliw, FR550_MAJOR_F_2,
                                     slot - (UNIT_FM2 - UNIT_FM0))
                                     slot - (UNIT_FM2 - UNIT_FM0))
          &&   ! find_major_in_slot (vliw, FR550_MAJOR_F_4,
          &&   ! find_major_in_slot (vliw, FR550_MAJOR_F_4,
                                     slot - (UNIT_FM2 - UNIT_FM0));
                                     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
      /* M-2 or M-5 in slot m2 or m3 cannot coexist with M-2 in slot m1 or m2
         respectively.  */
         respectively.  */
      if (major == FR550_MAJOR_M_2 || major == FR550_MAJOR_M_5)
      if (major == FR550_MAJOR_M_2 || major == FR550_MAJOR_M_5)
        return ! find_major_in_slot (vliw, FR550_MAJOR_M_2,
        return ! find_major_in_slot (vliw, FR550_MAJOR_M_2,
                                     slot - (UNIT_FM2 - UNIT_FM0));
                                     slot - (UNIT_FM2 - UNIT_FM0));
      /* M-4 in slot m2 or m3 cannot coexist with M-4 in slot m1 or m2
      /* M-4 in slot m2 or m3 cannot coexist with M-4 in slot m1 or m2
         respectively.  */
         respectively.  */
      if (major == FR550_MAJOR_M_4)
      if (major == FR550_MAJOR_M_4)
        return ! find_major_in_slot (vliw, FR550_MAJOR_M_4,
        return ! find_major_in_slot (vliw, FR550_MAJOR_M_4,
                                     slot - (UNIT_FM2 - UNIT_FM0));
                                     slot - (UNIT_FM2 - UNIT_FM0));
      break;
      break;
    default:
    default:
      break;
      break;
    }
    }
  return TRUE; /* All OK.  */
  return TRUE; /* All OK.  */
}
}
static bfd_boolean
static bfd_boolean
fr500_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
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
  /* TODO: A table might be faster for some of the more complex instances
     here.  */
     here.  */
  switch (major)
  switch (major)
    {
    {
    case FR500_MAJOR_I_1:
    case FR500_MAJOR_I_1:
    case FR500_MAJOR_I_4:
    case FR500_MAJOR_I_4:
    case FR500_MAJOR_I_5:
    case FR500_MAJOR_I_5:
    case FR500_MAJOR_I_6:
    case FR500_MAJOR_I_6:
    case FR500_MAJOR_B_1:
    case FR500_MAJOR_B_1:
    case FR500_MAJOR_B_2:
    case FR500_MAJOR_B_2:
    case FR500_MAJOR_B_3:
    case FR500_MAJOR_B_3:
    case FR500_MAJOR_B_4:
    case FR500_MAJOR_B_4:
    case FR500_MAJOR_B_5:
    case FR500_MAJOR_B_5:
    case FR500_MAJOR_B_6:
    case FR500_MAJOR_B_6:
    case FR500_MAJOR_F_4:
    case FR500_MAJOR_F_4:
    case FR500_MAJOR_F_8:
    case FR500_MAJOR_F_8:
    case FR500_MAJOR_M_8:
    case FR500_MAJOR_M_8:
      return TRUE; /* OK */
      return TRUE; /* OK */
    case FR500_MAJOR_I_2:
    case FR500_MAJOR_I_2:
      /* Cannot coexist with I-3 insn.  */
      /* Cannot coexist with I-3 insn.  */
      return ! find_major_in_vliw (vliw, FR500_MAJOR_I_3);
      return ! find_major_in_vliw (vliw, FR500_MAJOR_I_3);
    case FR500_MAJOR_I_3:
    case FR500_MAJOR_I_3:
      /* Cannot coexist with I-2 insn.  */
      /* Cannot coexist with I-2 insn.  */
      return ! find_major_in_vliw (vliw, FR500_MAJOR_I_2);
      return ! find_major_in_vliw (vliw, FR500_MAJOR_I_2);
    case FR500_MAJOR_F_1:
    case FR500_MAJOR_F_1:
    case FR500_MAJOR_F_2:
    case FR500_MAJOR_F_2:
      /* Cannot coexist with F-5, F-6, or M-7 insn.  */
      /* Cannot coexist with F-5, F-6, or M-7 insn.  */
      return ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
      return ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
    case FR500_MAJOR_F_3:
    case FR500_MAJOR_F_3:
      /* Cannot coexist with F-7, or M-7 insn.  */
      /* Cannot coexist with F-7, or M-7 insn.  */
      return ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
      return ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
    case FR500_MAJOR_F_5:
    case FR500_MAJOR_F_5:
      /* Cannot coexist with F-1, F-2, F-6, F-7, or M-7 insn.  */
      /* Cannot coexist with F-1, F-2, F-6, F-7, or M-7 insn.  */
      return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
      return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
    case FR500_MAJOR_F_6:
    case FR500_MAJOR_F_6:
      /* Cannot coexist with F-1, F-2, F-5, F-6, or M-7 insn.  */
      /* Cannot coexist with F-1, F-2, F-5, F-6, or M-7 insn.  */
      return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
      return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
    case FR500_MAJOR_F_7:
    case FR500_MAJOR_F_7:
      /* Cannot coexist with F-3, F-5, F-7, or M-7 insn.  */
      /* Cannot coexist with F-3, F-5, F-7, or M-7 insn.  */
      return ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
      return ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
    case FR500_MAJOR_M_1:
    case FR500_MAJOR_M_1:
      /* Cannot coexist with M-7 insn.  */
      /* Cannot coexist with M-7 insn.  */
      return ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
      return ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
    case FR500_MAJOR_M_2:
    case FR500_MAJOR_M_2:
    case FR500_MAJOR_M_3:
    case FR500_MAJOR_M_3:
      /* Cannot coexist with M-5, M-6 or M-7 insn.  */
      /* Cannot coexist with M-5, M-6 or M-7 insn.  */
      return ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
      return ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
    case FR500_MAJOR_M_4:
    case FR500_MAJOR_M_4:
      /* Cannot coexist with M-6 insn.  */
      /* Cannot coexist with M-6 insn.  */
      return ! find_major_in_vliw (vliw, FR500_MAJOR_M_6);
      return ! find_major_in_vliw (vliw, FR500_MAJOR_M_6);
    case FR500_MAJOR_M_5:
    case FR500_MAJOR_M_5:
      /* Cannot coexist with M-2, M-3, M-5, M-6  or M-7 insn.  */
      /* Cannot coexist with M-2, M-3, M-5, M-6  or M-7 insn.  */
      return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
      return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
    case FR500_MAJOR_M_6:
    case FR500_MAJOR_M_6:
      /* Cannot coexist with M-2, M-3, M-4, M-5, M-6  or M-7 insn.  */
      /* Cannot coexist with M-2, M-3, M-4, M-5, M-6  or M-7 insn.  */
      return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
      return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_4)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_4)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
    case FR500_MAJOR_M_7:
    case FR500_MAJOR_M_7:
      /* Cannot coexist with M-1, M-2, M-3, M-5, M-6  or M-7 insn.  */
      /* Cannot coexist with M-1, M-2, M-3, M-5, M-6  or M-7 insn.  */
      return ! find_major_in_vliw (vliw, FR500_MAJOR_M_1)
      return ! find_major_in_vliw (vliw, FR500_MAJOR_M_1)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_M_7)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_7);
        &&   ! find_major_in_vliw (vliw, FR500_MAJOR_F_7);
    default:
    default:
      fprintf (stderr, "frv-opc.c, line %d: bad major code, aborting.\n",
      fprintf (stderr, "frv-opc.c, line %d: bad major code, aborting.\n",
               __LINE__);
               __LINE__);
      abort ();
      abort ();
      break;
      break;
    }
    }
  return TRUE;
  return TRUE;
}
}
static bfd_boolean
static bfd_boolean
check_insn_major_constraints (FRV_VLIW *vliw,
check_insn_major_constraints (FRV_VLIW *vliw,
                              CGEN_ATTR_VALUE_ENUM_TYPE major,
                              CGEN_ATTR_VALUE_ENUM_TYPE major,
                              const CGEN_INSN *insn)
                              const CGEN_INSN *insn)
{
{
  switch (vliw->mach)
  switch (vliw->mach)
    {
    {
    case bfd_mach_fr400:
    case bfd_mach_fr400:
      return fr400_check_insn_major_constraints (vliw, major);
      return fr400_check_insn_major_constraints (vliw, major);
    case bfd_mach_fr450:
    case bfd_mach_fr450:
      return fr450_check_insn_major_constraints (vliw, major);
      return fr450_check_insn_major_constraints (vliw, major);
    case bfd_mach_fr550:
    case bfd_mach_fr550:
      return fr550_check_insn_major_constraints (vliw, major, insn);
      return fr550_check_insn_major_constraints (vliw, major, insn);
    default:
    default:
      return fr500_check_insn_major_constraints (vliw, major);
      return fr500_check_insn_major_constraints (vliw, major);
    }
    }
}
}
/* Add in insn to the VLIW vliw if possible.
/* Add in insn to the VLIW vliw if possible.
   Return 0 if successful, non-zero otherwise.  */
   Return 0 if successful, non-zero otherwise.  */
int
int
frv_vliw_add_insn (FRV_VLIW *vliw, const CGEN_INSN *insn)
frv_vliw_add_insn (FRV_VLIW *vliw, const CGEN_INSN *insn)
{
{
  int index;
  int index;
  CGEN_ATTR_VALUE_ENUM_TYPE major;
  CGEN_ATTR_VALUE_ENUM_TYPE major;
  CGEN_ATTR_VALUE_ENUM_TYPE unit;
  CGEN_ATTR_VALUE_ENUM_TYPE unit;
  VLIW_COMBO *new_vliw;
  VLIW_COMBO *new_vliw;
  if (vliw->constraint_violation || CGEN_INSN_INVALID_P (insn))
  if (vliw->constraint_violation || CGEN_INSN_INVALID_P (insn))
    return 1;
    return 1;
  index = vliw->next_slot;
  index = vliw->next_slot;
  if (index >= FRV_VLIW_SIZE)
  if (index >= FRV_VLIW_SIZE)
    return 1;
    return 1;
  unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
  unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
  if (unit == UNIT_NIL)
  if (unit == UNIT_NIL)
    {
    {
      fprintf (stderr, "frv-opc.c line %d: bad insn unit.\n",
      fprintf (stderr, "frv-opc.c line %d: bad insn unit.\n",
               __LINE__);
               __LINE__);
      abort (); /* No UNIT specified for this insn in frv.cpu.  */
      abort (); /* No UNIT specified for this insn in frv.cpu.  */
    }
    }
  switch (vliw->mach)
  switch (vliw->mach)
    {
    {
    case bfd_mach_fr400:
    case bfd_mach_fr400:
      major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR);
      major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR);
      break;
      break;
    case bfd_mach_fr450:
    case bfd_mach_fr450:
      major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR);
      major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR);
      break;
      break;
    case bfd_mach_fr550:
    case bfd_mach_fr550:
      major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR550_MAJOR);
      major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR550_MAJOR);
      break;
      break;
    default:
    default:
      major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR);
      major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR);
      break;
      break;
    }
    }
  if (index <= 0)
  if (index <= 0)
    {
    {
      /* Any insn can be added to slot 0.  */
      /* Any insn can be added to slot 0.  */
      while (! match_unit (vliw, unit, (*vliw->current_vliw)[0]))
      while (! match_unit (vliw, unit, (*vliw->current_vliw)[0]))
        ++vliw->current_vliw;
        ++vliw->current_vliw;
      vliw->major[0] = major;
      vliw->major[0] = major;
      vliw->insn[0] = insn;
      vliw->insn[0] = insn;
      vliw->next_slot = 1;
      vliw->next_slot = 1;
      return 0;
      return 0;
    }
    }
  /* If there are already insns in the vliw(s) check to see that
  /* If there are already insns in the vliw(s) check to see that
     this one can be added.  Do this by finding an allowable vliw
     this one can be added.  Do this by finding an allowable vliw
     combination that can accept the new insn.  */
     combination that can accept the new insn.  */
  if (! (vliw->elf_flags & EF_FRV_NOPACK))
  if (! (vliw->elf_flags & EF_FRV_NOPACK))
    {
    {
      new_vliw = add_next_to_vliw (vliw, unit);
      new_vliw = add_next_to_vliw (vliw, unit);
      if (new_vliw && check_insn_major_constraints (vliw, major, insn))
      if (new_vliw && check_insn_major_constraints (vliw, major, insn))
        {
        {
          vliw->current_vliw = new_vliw;
          vliw->current_vliw = new_vliw;
          vliw->major[index] = major;
          vliw->major[index] = major;
          vliw->insn[index] = insn;
          vliw->insn[index] = insn;
          vliw->next_slot++;
          vliw->next_slot++;
          return 0;
          return 0;
        }
        }
      /* The frv machine supports all packing conbinations.  If we fail,
      /* The frv machine supports all packing conbinations.  If we fail,
         to add the insn, then it could not be handled as if it was the fr500.
         to add the insn, then it could not be handled as if it was the fr500.
         Just return as if it was handled ok.  */
         Just return as if it was handled ok.  */
      if (vliw->mach == bfd_mach_frv)
      if (vliw->mach == bfd_mach_frv)
        return 0;
        return 0;
    }
    }
  vliw->constraint_violation = 1;
  vliw->constraint_violation = 1;
  return 1;
  return 1;
}
}
bfd_boolean
bfd_boolean
spr_valid (long regno)
spr_valid (long regno)
{
{
  if (regno < 0)     return FALSE;
  if (regno < 0)     return FALSE;
  if (regno <= 4095) return TRUE;
  if (regno <= 4095) return TRUE;
  return FALSE;
  return FALSE;
}
}
/* -- */
/* -- */


/* -- asm.c */
/* -- asm.c */
inline static const char *
inline static const char *
parse_symbolic_address (CGEN_CPU_DESC cd,
parse_symbolic_address (CGEN_CPU_DESC cd,
                        const char **strp,
                        const char **strp,
                        int opindex,
                        int opindex,
                        int opinfo,
                        int opinfo,
                        enum cgen_parse_operand_result *resultp,
                        enum cgen_parse_operand_result *resultp,
                        bfd_vma *valuep)
                        bfd_vma *valuep)
{
{
  enum cgen_parse_operand_result result_type;
  enum cgen_parse_operand_result result_type;
  const char *errmsg = (* cd->parse_operand_fn)
  const char *errmsg = (* cd->parse_operand_fn)
    (cd, CGEN_PARSE_OPERAND_SYMBOLIC, strp, opindex, opinfo,
    (cd, CGEN_PARSE_OPERAND_SYMBOLIC, strp, opindex, opinfo,
     &result_type, valuep);
     &result_type, valuep);
  if (errmsg == NULL
  if (errmsg == NULL
      && result_type != CGEN_PARSE_OPERAND_RESULT_QUEUED)
      && result_type != CGEN_PARSE_OPERAND_RESULT_QUEUED)
    return "symbolic expression required";
    return "symbolic expression required";
  if (resultp)
  if (resultp)
    *resultp = result_type;
    *resultp = result_type;
  return errmsg;
  return errmsg;
}
}
static const char *
static const char *
parse_ldd_annotation (CGEN_CPU_DESC cd,
parse_ldd_annotation (CGEN_CPU_DESC cd,
                      const char **strp,
                      const char **strp,
                      int opindex,
                      int opindex,
                      unsigned long *valuep)
                      unsigned long *valuep)
{
{
  const char *errmsg;
  const char *errmsg;
  enum cgen_parse_operand_result result_type;
  enum cgen_parse_operand_result result_type;
  bfd_vma value;
  bfd_vma value;
  if (**strp == '#' || **strp == '%')
  if (**strp == '#' || **strp == '%')
    {
    {
      if (strncasecmp (*strp + 1, "tlsdesc(", 8) == 0)
      if (strncasecmp (*strp + 1, "tlsdesc(", 8) == 0)
        {
        {
          *strp += 9;
          *strp += 9;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_TLSDESC_RELAX,
                                           BFD_RELOC_FRV_TLSDESC_RELAX,
                                           &result_type, &value);
                                           &result_type, &value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          if (valuep)
          if (valuep)
            *valuep = value;
            *valuep = value;
          ++*strp;
          ++*strp;
          if (errmsg)
          if (errmsg)
            return errmsg;
            return errmsg;
        }
        }
    }
    }
  while (**strp == ' ' || **strp == '\t')
  while (**strp == ' ' || **strp == '\t')
    ++*strp;
    ++*strp;
  if (**strp != '@')
  if (**strp != '@')
    return "missing `@'";
    return "missing `@'";
  ++*strp;
  ++*strp;
  return NULL;
  return NULL;
}
}
static const char *
static const char *
parse_call_annotation (CGEN_CPU_DESC cd,
parse_call_annotation (CGEN_CPU_DESC cd,
                       const char **strp,
                       const char **strp,
                       int opindex,
                       int opindex,
                       unsigned long *valuep)
                       unsigned long *valuep)
{
{
  const char *errmsg;
  const char *errmsg;
  enum cgen_parse_operand_result result_type;
  enum cgen_parse_operand_result result_type;
  bfd_vma value;
  bfd_vma value;
  if (**strp == '#' || **strp == '%')
  if (**strp == '#' || **strp == '%')
    {
    {
      if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0)
      if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0)
        {
        {
          *strp += 11;
          *strp += 11;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_GETTLSOFF_RELAX,
                                           BFD_RELOC_FRV_GETTLSOFF_RELAX,
                                           &result_type, &value);
                                           &result_type, &value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          if (valuep)
          if (valuep)
            *valuep = value;
            *valuep = value;
          ++*strp;
          ++*strp;
          if (errmsg)
          if (errmsg)
            return errmsg;
            return errmsg;
        }
        }
    }
    }
  while (**strp == ' ' || **strp == '\t')
  while (**strp == ' ' || **strp == '\t')
    ++*strp;
    ++*strp;
  if (**strp != '@')
  if (**strp != '@')
    return "missing `@'";
    return "missing `@'";
  ++*strp;
  ++*strp;
  return NULL;
  return NULL;
}
}
static const char *
static const char *
parse_ld_annotation (CGEN_CPU_DESC cd,
parse_ld_annotation (CGEN_CPU_DESC cd,
                     const char **strp,
                     const char **strp,
                     int opindex,
                     int opindex,
                     unsigned long *valuep)
                     unsigned long *valuep)
{
{
  const char *errmsg;
  const char *errmsg;
  enum cgen_parse_operand_result result_type;
  enum cgen_parse_operand_result result_type;
  bfd_vma value;
  bfd_vma value;
  if (**strp == '#' || **strp == '%')
  if (**strp == '#' || **strp == '%')
    {
    {
      if (strncasecmp (*strp + 1, "tlsoff(", 7) == 0)
      if (strncasecmp (*strp + 1, "tlsoff(", 7) == 0)
        {
        {
          *strp += 8;
          *strp += 8;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_TLSOFF_RELAX,
                                           BFD_RELOC_FRV_TLSOFF_RELAX,
                                           &result_type, &value);
                                           &result_type, &value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          if (valuep)
          if (valuep)
            *valuep = value;
            *valuep = value;
          ++*strp;
          ++*strp;
          if (errmsg)
          if (errmsg)
            return errmsg;
            return errmsg;
        }
        }
    }
    }
  while (**strp == ' ' || **strp == '\t')
  while (**strp == ' ' || **strp == '\t')
    ++*strp;
    ++*strp;
  if (**strp != '@')
  if (**strp != '@')
    return "missing `@'";
    return "missing `@'";
  ++*strp;
  ++*strp;
  return NULL;
  return NULL;
}
}
static const char *
static const char *
parse_ulo16 (CGEN_CPU_DESC cd,
parse_ulo16 (CGEN_CPU_DESC cd,
             const char **strp,
             const char **strp,
             int opindex,
             int opindex,
             unsigned long *valuep)
             unsigned long *valuep)
{
{
  const char *errmsg;
  const char *errmsg;
  enum cgen_parse_operand_result result_type;
  enum cgen_parse_operand_result result_type;
  bfd_vma value;
  bfd_vma value;
  if (**strp == '#' || **strp == '%')
  if (**strp == '#' || **strp == '%')
    {
    {
      if (strncasecmp (*strp + 1, "lo(", 3) == 0)
      if (strncasecmp (*strp + 1, "lo(", 3) == 0)
        {
        {
          *strp += 4;
          *strp += 4;
          errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
          errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
                                       & result_type, & value);
                                       & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing `)'";
            return "missing `)'";
          ++*strp;
          ++*strp;
          if (errmsg == NULL
          if (errmsg == NULL
              && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
              && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
            value &= 0xffff;
            value &= 0xffff;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
      if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
        {
        {
          *strp += 9;
          *strp += 9;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_GPRELLO,
                                           BFD_RELOC_FRV_GPRELLO,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
      else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
        {
        {
          *strp += 7;
          *strp += 7;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_GOTLO,
                                           BFD_RELOC_FRV_GOTLO,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
      else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
        {
        {
          *strp += 15;
          *strp += 15;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_FUNCDESC_GOTLO,
                                           BFD_RELOC_FRV_FUNCDESC_GOTLO,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
      else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
        {
        {
          *strp += 10;
          *strp += 10;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_GOTOFFLO,
                                           BFD_RELOC_FRV_GOTOFFLO,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
      else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
        {
        {
          *strp += 18;
          *strp += 18;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
                                           BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0)
      else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0)
        {
        {
          *strp += 14;
          *strp += 14;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_GOTTLSDESCLO,
                                           BFD_RELOC_FRV_GOTTLSDESCLO,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0)
      else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0)
        {
        {
          *strp += 11;
          *strp += 11;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_TLSMOFFLO,
                                           BFD_RELOC_FRV_TLSMOFFLO,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0)
      else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0)
        {
        {
          *strp += 13;
          *strp += 13;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_GOTTLSOFFLO,
                                           BFD_RELOC_FRV_GOTTLSOFFLO,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
    }
    }
  return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
  return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
}
}
static const char *
static const char *
parse_uslo16 (CGEN_CPU_DESC cd,
parse_uslo16 (CGEN_CPU_DESC cd,
              const char **strp,
              const char **strp,
              int opindex,
              int opindex,
              signed long *valuep)
              signed long *valuep)
{
{
  const char *errmsg;
  const char *errmsg;
  enum cgen_parse_operand_result result_type;
  enum cgen_parse_operand_result result_type;
  bfd_vma value;
  bfd_vma value;
  if (**strp == '#' || **strp == '%')
  if (**strp == '#' || **strp == '%')
    {
    {
      if (strncasecmp (*strp + 1, "lo(", 3) == 0)
      if (strncasecmp (*strp + 1, "lo(", 3) == 0)
        {
        {
          *strp += 4;
          *strp += 4;
          errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
          errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
                                       & result_type, & value);
                                       & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing `)'";
            return "missing `)'";
          ++*strp;
          ++*strp;
          if (errmsg == NULL
          if (errmsg == NULL
              && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
              && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
            value &= 0xffff;
            value &= 0xffff;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
      else if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
        {
        {
          *strp += 9;
          *strp += 9;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_GPRELLO,
                                           BFD_RELOC_FRV_GPRELLO,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
      else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
        {
        {
          *strp += 7;
          *strp += 7;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_GOTLO,
                                           BFD_RELOC_FRV_GOTLO,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
      else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
        {
        {
          *strp += 15;
          *strp += 15;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_FUNCDESC_GOTLO,
                                           BFD_RELOC_FRV_FUNCDESC_GOTLO,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
      else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
        {
        {
          *strp += 10;
          *strp += 10;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_GOTOFFLO,
                                           BFD_RELOC_FRV_GOTOFFLO,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
      else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
        {
        {
          *strp += 18;
          *strp += 18;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
                                           BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0)
      else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0)
        {
        {
          *strp += 14;
          *strp += 14;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_GOTTLSDESCLO,
                                           BFD_RELOC_FRV_GOTTLSDESCLO,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0)
      else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0)
        {
        {
          *strp += 11;
          *strp += 11;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_TLSMOFFLO,
                                           BFD_RELOC_FRV_TLSMOFFLO,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0)
      else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0)
        {
        {
          *strp += 13;
          *strp += 13;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_GOTTLSOFFLO,
                                           BFD_RELOC_FRV_GOTTLSOFFLO,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
    }
    }
  return cgen_parse_signed_integer (cd, strp, opindex, valuep);
  return cgen_parse_signed_integer (cd, strp, opindex, valuep);
}
}
static const char *
static const char *
parse_uhi16 (CGEN_CPU_DESC cd,
parse_uhi16 (CGEN_CPU_DESC cd,
             const char **strp,
             const char **strp,
             int opindex,
             int opindex,
             unsigned long *valuep)
             unsigned long *valuep)
{
{
  const char *errmsg;
  const char *errmsg;
  enum cgen_parse_operand_result result_type;
  enum cgen_parse_operand_result result_type;
  bfd_vma value;
  bfd_vma value;
  if (**strp == '#' || **strp == '%')
  if (**strp == '#' || **strp == '%')
    {
    {
      if (strncasecmp (*strp + 1, "hi(", 3) == 0)
      if (strncasecmp (*strp + 1, "hi(", 3) == 0)
        {
        {
          *strp += 4;
          *strp += 4;
          errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_HI16,
          errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_HI16,
                                       & result_type, & value);
                                       & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing `)'";
            return "missing `)'";
          ++*strp;
          ++*strp;
          if (errmsg == NULL
          if (errmsg == NULL
              && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
              && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
            {
            {
              /* If bfd_vma is wider than 32 bits, but we have a sign-
              /* If bfd_vma is wider than 32 bits, but we have a sign-
                 or zero-extension, truncate it.  */
                 or zero-extension, truncate it.  */
              if (value >= - ((bfd_vma)1 << 31)
              if (value >= - ((bfd_vma)1 << 31)
                  || value <= ((bfd_vma)1 << 31) - (bfd_vma)1)
                  || value <= ((bfd_vma)1 << 31) - (bfd_vma)1)
                value &= (((bfd_vma)1 << 16) << 16) - 1;
                value &= (((bfd_vma)1 << 16) << 16) - 1;
              value >>= 16;
              value >>= 16;
            }
            }
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "gprelhi(", 8) == 0)
      else if (strncasecmp (*strp + 1, "gprelhi(", 8) == 0)
        {
        {
          *strp += 9;
          *strp += 9;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_GPRELHI,
                                           BFD_RELOC_FRV_GPRELHI,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "gothi(", 6) == 0)
      else if (strncasecmp (*strp + 1, "gothi(", 6) == 0)
        {
        {
          *strp += 7;
          *strp += 7;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_GOTHI,
                                           BFD_RELOC_FRV_GOTHI,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "gotfuncdeschi(", 14) == 0)
      else if (strncasecmp (*strp + 1, "gotfuncdeschi(", 14) == 0)
        {
        {
          *strp += 15;
          *strp += 15;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_FUNCDESC_GOTHI,
                                           BFD_RELOC_FRV_FUNCDESC_GOTHI,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "gotoffhi(", 9) == 0)
      else if (strncasecmp (*strp + 1, "gotoffhi(", 9) == 0)
        {
        {
          *strp += 10;
          *strp += 10;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_GOTOFFHI,
                                           BFD_RELOC_FRV_GOTOFFHI,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "gotofffuncdeschi(", 17) == 0)
      else if (strncasecmp (*strp + 1, "gotofffuncdeschi(", 17) == 0)
        {
        {
          *strp += 18;
          *strp += 18;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_FUNCDESC_GOTOFFHI,
                                           BFD_RELOC_FRV_FUNCDESC_GOTOFFHI,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "gottlsdeschi(", 13) == 0)
      else if (strncasecmp (*strp + 1, "gottlsdeschi(", 13) == 0)
        {
        {
          *strp += 14;
          *strp += 14;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_GOTTLSDESCHI,
                                           BFD_RELOC_FRV_GOTTLSDESCHI,
                                           &result_type, &value);
                                           &result_type, &value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "tlsmoffhi(", 10) == 0)
      else if (strncasecmp (*strp + 1, "tlsmoffhi(", 10) == 0)
        {
        {
          *strp += 11;
          *strp += 11;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_TLSMOFFHI,
                                           BFD_RELOC_FRV_TLSMOFFHI,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "gottlsoffhi(", 12) == 0)
      else if (strncasecmp (*strp + 1, "gottlsoffhi(", 12) == 0)
        {
        {
          *strp += 13;
          *strp += 13;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_GOTTLSOFFHI,
                                           BFD_RELOC_FRV_GOTTLSOFFHI,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
    }
    }
  return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
  return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
}
}
static long
static long
parse_register_number (const char **strp)
parse_register_number (const char **strp)
{
{
  int regno;
  int regno;
  if (**strp < '0' || **strp > '9')
  if (**strp < '0' || **strp > '9')
    return -1; /* error */
    return -1; /* error */
  regno = **strp - '0';
  regno = **strp - '0';
  for (++*strp; **strp >= '0' && **strp <= '9'; ++*strp)
  for (++*strp; **strp >= '0' && **strp <= '9'; ++*strp)
    regno = regno * 10 + (**strp - '0');
    regno = regno * 10 + (**strp - '0');
  return regno;
  return regno;
}
}
static const char *
static const char *
parse_spr (CGEN_CPU_DESC cd,
parse_spr (CGEN_CPU_DESC cd,
           const char **strp,
           const char **strp,
           CGEN_KEYWORD * table,
           CGEN_KEYWORD * table,
           long *valuep)
           long *valuep)
{
{
  const char *save_strp;
  const char *save_strp;
  long regno;
  long regno;
  /* Check for spr index notation.  */
  /* Check for spr index notation.  */
  if (strncasecmp (*strp, "spr[", 4) == 0)
  if (strncasecmp (*strp, "spr[", 4) == 0)
    {
    {
      *strp += 4;
      *strp += 4;
      regno = parse_register_number (strp);
      regno = parse_register_number (strp);
      if (**strp != ']')
      if (**strp != ']')
        return _("missing `]'");
        return _("missing `]'");
      ++*strp;
      ++*strp;
      if (! spr_valid (regno))
      if (! spr_valid (regno))
        return _("Special purpose register number is out of range");
        return _("Special purpose register number is out of range");
      *valuep = regno;
      *valuep = regno;
      return NULL;
      return NULL;
    }
    }
  save_strp = *strp;
  save_strp = *strp;
  regno = parse_register_number (strp);
  regno = parse_register_number (strp);
  if (regno != -1)
  if (regno != -1)
    {
    {
      if (! spr_valid (regno))
      if (! spr_valid (regno))
        return _("Special purpose register number is out of range");
        return _("Special purpose register number is out of range");
      *valuep = regno;
      *valuep = regno;
      return NULL;
      return NULL;
    }
    }
  *strp = save_strp;
  *strp = save_strp;
  return cgen_parse_keyword (cd, strp, table, valuep);
  return cgen_parse_keyword (cd, strp, table, valuep);
}
}
static const char *
static const char *
parse_d12 (CGEN_CPU_DESC cd,
parse_d12 (CGEN_CPU_DESC cd,
           const char **strp,
           const char **strp,
           int opindex,
           int opindex,
           long *valuep)
           long *valuep)
{
{
  const char *errmsg;
  const char *errmsg;
  enum cgen_parse_operand_result result_type;
  enum cgen_parse_operand_result result_type;
  bfd_vma value;
  bfd_vma value;
  /* Check for small data reference.  */
  /* Check for small data reference.  */
  if (**strp == '#' || **strp == '%')
  if (**strp == '#' || **strp == '%')
    {
    {
      if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
      if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
        {
        {
          *strp += 9;
          *strp += 9;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_GPREL12,
                                           BFD_RELOC_FRV_GPREL12,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing `)'";
            return "missing `)'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
      else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
        {
        {
          *strp += 7;
          *strp += 7;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_GOT12,
                                           BFD_RELOC_FRV_GOT12,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
      else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
        {
        {
          *strp += 15;
          *strp += 15;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_FUNCDESC_GOT12,
                                           BFD_RELOC_FRV_FUNCDESC_GOT12,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
      else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
        {
        {
          *strp += 10;
          *strp += 10;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_GOTOFF12,
                                           BFD_RELOC_FRV_GOTOFF12,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
      else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
        {
        {
          *strp += 18;
          *strp += 18;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
                                           BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0)
      else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0)
        {
        {
          *strp += 14;
          *strp += 14;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_GOTTLSDESC12,
                                           BFD_RELOC_FRV_GOTTLSDESC12,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0)
      else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0)
        {
        {
          *strp += 11;
          *strp += 11;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_TLSMOFF12,
                                           BFD_RELOC_FRV_TLSMOFF12,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0)
      else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0)
        {
        {
          *strp += 13;
          *strp += 13;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_GOTTLSOFF12,
                                           BFD_RELOC_FRV_GOTTLSOFF12,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
    }
    }
  return cgen_parse_signed_integer (cd, strp, opindex, valuep);
  return cgen_parse_signed_integer (cd, strp, opindex, valuep);
}
}
static const char *
static const char *
parse_s12 (CGEN_CPU_DESC cd,
parse_s12 (CGEN_CPU_DESC cd,
           const char **strp,
           const char **strp,
           int opindex,
           int opindex,
           long *valuep)
           long *valuep)
{
{
  const char *errmsg;
  const char *errmsg;
  enum cgen_parse_operand_result result_type;
  enum cgen_parse_operand_result result_type;
  bfd_vma value;
  bfd_vma value;
  /* Check for small data reference.  */
  /* Check for small data reference.  */
  if (**strp == '#' || **strp == '%')
  if (**strp == '#' || **strp == '%')
    {
    {
      if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
      if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
        {
        {
          *strp += 9;
          *strp += 9;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_GPREL12,
                                           BFD_RELOC_FRV_GPREL12,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing `)'";
            return "missing `)'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
      else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
        {
        {
          *strp += 7;
          *strp += 7;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_GOT12,
                                           BFD_RELOC_FRV_GOT12,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
      else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
        {
        {
          *strp += 15;
          *strp += 15;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_FUNCDESC_GOT12,
                                           BFD_RELOC_FRV_FUNCDESC_GOT12,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
      else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
        {
        {
          *strp += 10;
          *strp += 10;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_GOTOFF12,
                                           BFD_RELOC_FRV_GOTOFF12,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
      else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
        {
        {
          *strp += 18;
          *strp += 18;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
                                           BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0)
      else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0)
        {
        {
          *strp += 14;
          *strp += 14;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_GOTTLSDESC12,
                                           BFD_RELOC_FRV_GOTTLSDESC12,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0)
      else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0)
        {
        {
          *strp += 11;
          *strp += 11;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_TLSMOFF12,
                                           BFD_RELOC_FRV_TLSMOFF12,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
      else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0)
      else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0)
        {
        {
          *strp += 13;
          *strp += 13;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_GOTTLSOFF12,
                                           BFD_RELOC_FRV_GOTTLSOFF12,
                                           & result_type, & value);
                                           & result_type, & value);
          if (**strp != ')')
          if (**strp != ')')
            return "missing ')'";
            return "missing ')'";
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
    }
    }
  if (**strp == '#')
  if (**strp == '#')
    ++*strp;
    ++*strp;
  return cgen_parse_signed_integer (cd, strp, opindex, valuep);
  return cgen_parse_signed_integer (cd, strp, opindex, valuep);
}
}
static const char *
static const char *
parse_u12 (CGEN_CPU_DESC cd,
parse_u12 (CGEN_CPU_DESC cd,
           const char **strp,
           const char **strp,
           int opindex,
           int opindex,
           long *valuep)
           long *valuep)
{
{
  const char *errmsg;
  const char *errmsg;
  enum cgen_parse_operand_result result_type;
  enum cgen_parse_operand_result result_type;
  bfd_vma value;
  bfd_vma value;
  /* Check for small data reference.  */
  /* Check for small data reference.  */
  if ((**strp == '#' || **strp == '%')
  if ((**strp == '#' || **strp == '%')
      && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
      && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
    {
    {
      *strp += 9;
      *strp += 9;
      errmsg = parse_symbolic_address (cd, strp, opindex,
      errmsg = parse_symbolic_address (cd, strp, opindex,
                                       BFD_RELOC_FRV_GPRELU12,
                                       BFD_RELOC_FRV_GPRELU12,
                                       & result_type, & value);
                                       & result_type, & value);
      if (**strp != ')')
      if (**strp != ')')
        return "missing `)'";
        return "missing `)'";
      ++*strp;
      ++*strp;
      *valuep = value;
      *valuep = value;
      return errmsg;
      return errmsg;
    }
    }
  else
  else
    {
    {
      if (**strp == '#')
      if (**strp == '#')
        ++*strp;
        ++*strp;
      return cgen_parse_signed_integer (cd, strp, opindex, valuep);
      return cgen_parse_signed_integer (cd, strp, opindex, valuep);
    }
    }
}
}
static const char *
static const char *
parse_A (CGEN_CPU_DESC cd,
parse_A (CGEN_CPU_DESC cd,
         const char **strp,
         const char **strp,
         int opindex,
         int opindex,
         unsigned long *valuep,
         unsigned long *valuep,
         unsigned long A)
         unsigned long A)
{
{
  const char *errmsg;
  const char *errmsg;
  if (**strp == '#')
  if (**strp == '#')
    ++*strp;
    ++*strp;
  errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
  errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
  if (errmsg)
  if (errmsg)
    return errmsg;
    return errmsg;
  if (*valuep != A)
  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;
  return NULL;
}
}
static const char *
static const char *
parse_A0 (CGEN_CPU_DESC cd,
parse_A0 (CGEN_CPU_DESC cd,
          const char **strp,
          const char **strp,
          int opindex,
          int opindex,
          unsigned long *valuep)
          unsigned long *valuep)
{
{
  return parse_A (cd, strp, opindex, valuep, 0);
  return parse_A (cd, strp, opindex, valuep, 0);
}
}
static const char *
static const char *
parse_A1 (CGEN_CPU_DESC cd,
parse_A1 (CGEN_CPU_DESC cd,
          const char **strp,
          const char **strp,
          int opindex,
          int opindex,
          unsigned long *valuep)
          unsigned long *valuep)
{
{
  return parse_A (cd, strp, opindex, valuep, 1);
  return parse_A (cd, strp, opindex, valuep, 1);
}
}
static const char *
static const char *
parse_even_register (CGEN_CPU_DESC  cd,
parse_even_register (CGEN_CPU_DESC  cd,
                     const char **  strP,
                     const char **  strP,
                     CGEN_KEYWORD * tableP,
                     CGEN_KEYWORD * tableP,
                     long *         valueP)
                     long *         valueP)
{
{
  const char * errmsg;
  const char * errmsg;
  const char * saved_star_strP = * strP;
  const char * saved_star_strP = * strP;
  errmsg = cgen_parse_keyword (cd, strP, tableP, valueP);
  errmsg = cgen_parse_keyword (cd, strP, tableP, valueP);
  if (errmsg == NULL && ((* valueP) & 1))
  if (errmsg == NULL && ((* valueP) & 1))
    {
    {
      errmsg = _("register number must be even");
      errmsg = _("register number must be even");
      * strP = saved_star_strP;
      * strP = saved_star_strP;
    }
    }
  return errmsg;
  return errmsg;
}
}
static const char *
static const char *
parse_call_label (CGEN_CPU_DESC cd,
parse_call_label (CGEN_CPU_DESC cd,
                  const char **strp,
                  const char **strp,
                  int opindex,
                  int opindex,
                  int opinfo,
                  int opinfo,
                  enum cgen_parse_operand_result *resultp,
                  enum cgen_parse_operand_result *resultp,
                  bfd_vma *valuep)
                  bfd_vma *valuep)
{
{
  const char *errmsg;
  const char *errmsg;
  bfd_vma value;
  bfd_vma value;
  /* Check for small data reference.  */
  /* Check for small data reference.  */
  if (opinfo == 0 && (**strp == '#' || **strp == '%'))
  if (opinfo == 0 && (**strp == '#' || **strp == '%'))
    {
    {
      if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0)
      if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0)
        {
        {
          *strp += 11;
          *strp += 11;
          errmsg = parse_symbolic_address (cd, strp, opindex,
          errmsg = parse_symbolic_address (cd, strp, opindex,
                                           BFD_RELOC_FRV_GETTLSOFF,
                                           BFD_RELOC_FRV_GETTLSOFF,
                                           resultp, &value);
                                           resultp, &value);
          if (**strp != ')')
          if (**strp != ')')
            return _("missing `)'");
            return _("missing `)'");
          ++*strp;
          ++*strp;
          *valuep = value;
          *valuep = value;
          return errmsg;
          return errmsg;
        }
        }
    }
    }
  return cgen_parse_address (cd, strp, opindex, opinfo, resultp, valuep);
  return cgen_parse_address (cd, strp, opindex, opinfo, resultp, valuep);
}
}
/* -- */
/* -- */


/* -- dis.c */
/* -- dis.c */
static void
static void
print_at (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
print_at (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
          void * dis_info,
          void * dis_info,
          long reloc_ann ATTRIBUTE_UNUSED,
          long reloc_ann ATTRIBUTE_UNUSED,
          long value ATTRIBUTE_UNUSED,
          long value ATTRIBUTE_UNUSED,
          bfd_vma pc ATTRIBUTE_UNUSED,
          bfd_vma pc ATTRIBUTE_UNUSED,
          int length ATTRIBUTE_UNUSED)
          int length ATTRIBUTE_UNUSED)
{
{
  disassemble_info *info = (disassemble_info *) dis_info;
  disassemble_info *info = (disassemble_info *) dis_info;
  (*info->fprintf_func) (info->stream, "@");
  (*info->fprintf_func) (info->stream, "@");
}
}
static void
static void
print_spr (CGEN_CPU_DESC cd,
print_spr (CGEN_CPU_DESC cd,
           void * dis_info,
           void * dis_info,
           CGEN_KEYWORD *names,
           CGEN_KEYWORD *names,
           long regno,
           long regno,
           unsigned int attrs)
           unsigned int attrs)
{
{
  /* Use the register index format for any unnamed registers.  */
  /* Use the register index format for any unnamed registers.  */
  if (cgen_keyword_lookup_value (names, regno) == NULL)
  if (cgen_keyword_lookup_value (names, regno) == NULL)
    {
    {
      disassemble_info *info = (disassemble_info *) dis_info;
      disassemble_info *info = (disassemble_info *) dis_info;
      (*info->fprintf_func) (info->stream, "spr[%ld]", regno);
      (*info->fprintf_func) (info->stream, "spr[%ld]", regno);
    }
    }
  else
  else
    print_keyword (cd, dis_info, names, regno, attrs);
    print_keyword (cd, dis_info, names, regno, attrs);
}
}
static void
static void
print_hi (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
print_hi (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
          void * dis_info,
          void * dis_info,
          long value,
          long value,
          unsigned int attrs ATTRIBUTE_UNUSED,
          unsigned int attrs ATTRIBUTE_UNUSED,
          bfd_vma pc ATTRIBUTE_UNUSED,
          bfd_vma pc ATTRIBUTE_UNUSED,
          int length ATTRIBUTE_UNUSED)
          int length ATTRIBUTE_UNUSED)
{
{
  disassemble_info *info = (disassemble_info *) dis_info;
  disassemble_info *info = (disassemble_info *) dis_info;
  (*info->fprintf_func) (info->stream, value ? "0x%lx" : "hi(0x%lx)", value);
  (*info->fprintf_func) (info->stream, value ? "0x%lx" : "hi(0x%lx)", value);
}
}
static void
static void
print_lo (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
print_lo (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
          void * dis_info,
          void * dis_info,
          long value,
          long value,
          unsigned int attrs ATTRIBUTE_UNUSED,
          unsigned int attrs ATTRIBUTE_UNUSED,
          bfd_vma pc ATTRIBUTE_UNUSED,
          bfd_vma pc ATTRIBUTE_UNUSED,
          int length ATTRIBUTE_UNUSED)
          int length ATTRIBUTE_UNUSED)
{
{
  disassemble_info *info = (disassemble_info *) dis_info;
  disassemble_info *info = (disassemble_info *) dis_info;
  if (value)
  if (value)
    (*info->fprintf_func) (info->stream, "0x%lx", value);
    (*info->fprintf_func) (info->stream, "0x%lx", value);
  else
  else
    (*info->fprintf_func) (info->stream, "lo(0x%lx)", value);
    (*info->fprintf_func) (info->stream, "lo(0x%lx)", value);
}
}
/* -- */
/* -- */
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.