Home | History | Annotate | Line # | Download | only in config
tc-frv.c revision 1.1.1.2
      1 /* tc-frv.c -- Assembler for the Fujitsu FRV.
      2    Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
      3    Free Software Foundation. Inc.
      4 
      5    This file is part of GAS, the GNU Assembler.
      6 
      7    GAS is free software; you can redistribute it and/or modify
      8    it under the terms of the GNU General Public License as published by
      9    the Free Software Foundation; either version 3, or (at your option)
     10    any later version.
     11 
     12    GAS is distributed in the hope that it will be useful,
     13    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15    GNU General Public License for more details.
     16 
     17    You should have received a copy of the GNU General Public License
     18    along with GAS; see the file COPYING.  If not, write to
     19    the Free Software Foundation, 51 Franklin Street - Fifth Floor,
     20    Boston, MA 02110-1301, USA.  */
     21 
     22 #include "as.h"
     23 #include "subsegs.h"
     24 #include "symcat.h"
     25 #include "opcodes/frv-desc.h"
     26 #include "opcodes/frv-opc.h"
     27 #include "cgen.h"
     28 #include "libbfd.h"
     29 #include "elf/common.h"
     30 #include "elf/frv.h"
     31 #include "dwarf2dbg.h"
     32 
     33 /* Structure to hold all of the different components describing
     34    an individual instruction.  */
     35 typedef struct
     36 {
     37   const CGEN_INSN *	insn;
     38   const CGEN_INSN *	orig_insn;
     39   CGEN_FIELDS		fields;
     40 #if CGEN_INT_INSN_P
     41   CGEN_INSN_INT         buffer [1];
     42 #define INSN_VALUE(buf) (*(buf))
     43 #else
     44   unsigned char         buffer [CGEN_MAX_INSN_SIZE];
     45 #define INSN_VALUE(buf) (buf)
     46 #endif
     47   char *		addr;
     48   fragS *		frag;
     49   int                   num_fixups;
     50   fixS *                fixups [GAS_CGEN_MAX_FIXUPS];
     51   int                   indices [MAX_OPERAND_INSTANCES];
     52 }
     53 frv_insn;
     54 
     55 enum vliw_insn_type
     56 {
     57   VLIW_GENERIC_TYPE,		/* Don't care about this insn.  */
     58   VLIW_BRANCH_TYPE,		/* A Branch.  */
     59   VLIW_LABEL_TYPE,		/* A Label.  */
     60   VLIW_NOP_TYPE,		/* A NOP.  */
     61   VLIW_BRANCH_HAS_NOPS		/* A Branch that requires NOPS.  */
     62 };
     63 
     64 /* We're going to use these in the fr_subtype field to mark
     65    whether to keep inserted nops.  */
     66 
     67 #define NOP_KEEP 1		/* Keep these NOPS.  */
     68 #define NOP_DELETE 2		/* Delete these NOPS.  */
     69 
     70 #define DO_COUNT    TRUE
     71 #define DONT_COUNT  FALSE
     72 
     73 /* A list of insns within a VLIW insn.  */
     74 struct vliw_insn_list
     75 {
     76   /*  The type of this insn.  */
     77   enum vliw_insn_type	type;
     78 
     79   /*  The corresponding gas insn information.  */
     80   const CGEN_INSN	*insn;
     81 
     82   /*  For branches and labels, the symbol that is referenced.  */
     83   symbolS		*sym;
     84 
     85   /*  For branches, the frag containing the single nop that was generated.  */
     86   fragS			*snop_frag;
     87 
     88   /*  For branches, the frag containing the double nop that was generated.  */
     89   fragS			*dnop_frag;
     90 
     91   /*  Pointer to raw data for this insn.  */
     92   char			*address;
     93 
     94   /* Next insn in list.  */
     95   struct vliw_insn_list *next;
     96 };
     97 
     98 static struct vliw_insn_list single_nop_insn = {
     99    VLIW_NOP_TYPE, NULL, NULL, NULL, NULL, NULL, NULL };
    100 
    101 static struct vliw_insn_list double_nop_insn = {
    102    VLIW_NOP_TYPE, NULL, NULL, NULL, NULL, NULL, NULL };
    103 
    104 struct vliw_chain
    105 {
    106   int			num;
    107   int			insn_count;
    108   struct vliw_insn_list *insn_list;
    109   struct vliw_chain     *next;
    110 };
    111 
    112 static struct vliw_chain	*vliw_chain_top;
    113 static struct vliw_chain	*current_vliw_chain;
    114 static struct vliw_chain	*previous_vliw_chain;
    115 static struct vliw_insn_list	*current_vliw_insn;
    116 
    117 const char comment_chars[]        = ";";
    118 const char line_comment_chars[]   = "#";
    119 const char line_separator_chars[] = "!";
    120 const char EXP_CHARS[]            = "eE";
    121 const char FLT_CHARS[]            = "dD";
    122 
    123 static FRV_VLIW vliw;
    124 
    125 /* Default machine */
    126 
    127 #ifdef  DEFAULT_CPU_FRV
    128 #define DEFAULT_MACHINE bfd_mach_frv
    129 #define DEFAULT_FLAGS	EF_FRV_CPU_GENERIC
    130 
    131 #else
    132 #ifdef  DEFAULT_CPU_FR300
    133 #define DEFAULT_MACHINE	bfd_mach_fr300
    134 #define DEFAULT_FLAGS	EF_FRV_CPU_FR300
    135 
    136 #else
    137 #ifdef	DEFAULT_CPU_SIMPLE
    138 #define	DEFAULT_MACHINE bfd_mach_frvsimple
    139 #define DEFAULT_FLAGS	EF_FRV_CPU_SIMPLE
    140 
    141 #else
    142 #ifdef	DEFAULT_CPU_TOMCAT
    143 #define	DEFAULT_MACHINE bfd_mach_frvtomcat
    144 #define DEFAULT_FLAGS	EF_FRV_CPU_TOMCAT
    145 
    146 #else
    147 #ifdef  DEFAULT_CPU_FR400
    148 #define DEFAULT_MACHINE	bfd_mach_fr400
    149 #define DEFAULT_FLAGS	EF_FRV_CPU_FR400
    150 
    151 #else
    152 #ifdef  DEFAULT_CPU_FR550
    153 #define DEFAULT_MACHINE	bfd_mach_fr550
    154 #define DEFAULT_FLAGS	EF_FRV_CPU_FR550
    155 
    156 #else
    157 #define DEFAULT_MACHINE	bfd_mach_fr500
    158 #define DEFAULT_FLAGS	EF_FRV_CPU_FR500
    159 #endif
    160 #endif
    161 #endif
    162 #endif
    163 #endif
    164 #endif
    165 
    166 #ifdef TE_LINUX
    167 # define DEFAULT_FDPIC	EF_FRV_FDPIC
    168 #else
    169 # define DEFAULT_FDPIC	0
    170 #endif
    171 
    172 static unsigned long frv_mach = bfd_mach_frv;
    173 static bfd_boolean fr400_audio;
    174 
    175 /* Flags to set in the elf header */
    176 static flagword frv_flags = DEFAULT_FLAGS | DEFAULT_FDPIC;
    177 
    178 static int frv_user_set_flags_p = 0;
    179 static int frv_pic_p = 0;
    180 static const char *frv_pic_flag = DEFAULT_FDPIC ? "-mfdpic" : (const char *)0;
    181 
    182 /* Print tomcat-specific debugging info.  */
    183 static int tomcat_debug = 0;
    184 
    185 /* Tomcat-specific NOP statistics.  */
    186 static int tomcat_stats = 0;
    187 static int tomcat_doubles = 0;
    188 static int tomcat_singles = 0;
    189 
    190 /* Forward reference to static functions */
    191 static void frv_set_flags (int);
    192 static void frv_pic_ptr (int);
    193 
    194 /* The target specific pseudo-ops which we support.  */
    195 const pseudo_typeS md_pseudo_table[] =
    196 {
    197   { "eflags",	frv_set_flags,		0 },
    198   { "word",	cons,			4 },
    199   { "picptr",	frv_pic_ptr,		4 },
    200   { NULL, 	NULL,			0 }
    201 };
    202 
    203 
    204 #define FRV_SHORTOPTS "G:"
    206 const char * md_shortopts = FRV_SHORTOPTS;
    207 
    208 #define OPTION_GPR_32		(OPTION_MD_BASE)
    209 #define OPTION_GPR_64		(OPTION_MD_BASE + 1)
    210 #define OPTION_FPR_32		(OPTION_MD_BASE + 2)
    211 #define OPTION_FPR_64		(OPTION_MD_BASE + 3)
    212 #define OPTION_SOFT_FLOAT	(OPTION_MD_BASE + 4)
    213 #define OPTION_DWORD_YES	(OPTION_MD_BASE + 5)
    214 #define OPTION_DWORD_NO		(OPTION_MD_BASE + 6)
    215 #define OPTION_DOUBLE		(OPTION_MD_BASE + 7)
    216 #define OPTION_NO_DOUBLE	(OPTION_MD_BASE + 8)
    217 #define OPTION_MEDIA		(OPTION_MD_BASE + 9)
    218 #define OPTION_NO_MEDIA		(OPTION_MD_BASE + 10)
    219 #define OPTION_CPU		(OPTION_MD_BASE + 11)
    220 #define OPTION_PIC		(OPTION_MD_BASE + 12)
    221 #define OPTION_BIGPIC		(OPTION_MD_BASE + 13)
    222 #define OPTION_LIBPIC		(OPTION_MD_BASE + 14)
    223 #define OPTION_MULADD		(OPTION_MD_BASE + 15)
    224 #define OPTION_NO_MULADD	(OPTION_MD_BASE + 16)
    225 #define OPTION_TOMCAT_DEBUG	(OPTION_MD_BASE + 17)
    226 #define OPTION_TOMCAT_STATS	(OPTION_MD_BASE + 18)
    227 #define OPTION_PACK	        (OPTION_MD_BASE + 19)
    228 #define OPTION_NO_PACK	        (OPTION_MD_BASE + 20)
    229 #define OPTION_FDPIC		(OPTION_MD_BASE + 21)
    230 #define OPTION_NOPIC		(OPTION_MD_BASE + 22)
    231 
    232 struct option md_longopts[] =
    233 {
    234   { "mgpr-32",		no_argument,		NULL, OPTION_GPR_32        },
    235   { "mgpr-64",		no_argument,		NULL, OPTION_GPR_64        },
    236   { "mfpr-32",		no_argument,		NULL, OPTION_FPR_32        },
    237   { "mfpr-64",		no_argument,		NULL, OPTION_FPR_64        },
    238   { "mhard-float",	no_argument,		NULL, OPTION_FPR_64        },
    239   { "msoft-float",	no_argument,		NULL, OPTION_SOFT_FLOAT    },
    240   { "mdword",		no_argument,		NULL, OPTION_DWORD_YES     },
    241   { "mno-dword",	no_argument,		NULL, OPTION_DWORD_NO      },
    242   { "mdouble",		no_argument,		NULL, OPTION_DOUBLE        },
    243   { "mno-double",	no_argument,		NULL, OPTION_NO_DOUBLE     },
    244   { "mmedia",		no_argument,		NULL, OPTION_MEDIA         },
    245   { "mno-media",	no_argument,		NULL, OPTION_NO_MEDIA      },
    246   { "mcpu",		required_argument,	NULL, OPTION_CPU           },
    247   { "mpic",		no_argument,		NULL, OPTION_PIC           },
    248   { "mPIC",		no_argument,		NULL, OPTION_BIGPIC        },
    249   { "mlibrary-pic",	no_argument,		NULL, OPTION_LIBPIC        },
    250   { "mmuladd",		no_argument,		NULL, OPTION_MULADD        },
    251   { "mno-muladd",	no_argument,		NULL, OPTION_NO_MULADD     },
    252   { "mtomcat-debug",    no_argument,            NULL, OPTION_TOMCAT_DEBUG  },
    253   { "mtomcat-stats",	no_argument,		NULL, OPTION_TOMCAT_STATS  },
    254   { "mpack",        	no_argument,		NULL, OPTION_PACK          },
    255   { "mno-pack",        	no_argument,		NULL, OPTION_NO_PACK       },
    256   { "mfdpic",		no_argument,		NULL, OPTION_FDPIC	   },
    257   { "mnopic",		no_argument,		NULL, OPTION_NOPIC	   },
    258   { NULL,		no_argument,		NULL, 0                 },
    259 };
    260 
    261 size_t md_longopts_size = sizeof (md_longopts);
    262 
    263 /* What value to give to bfd_set_gp_size.  */
    264 static int g_switch_value = 8;
    265 
    266 int
    267 md_parse_option (int c, char *arg)
    268 {
    269   switch (c)
    270     {
    271     default:
    272       return 0;
    273 
    274     case 'G':
    275       g_switch_value = atoi (arg);
    276       if (! g_switch_value)
    277 	frv_flags |= EF_FRV_G0;
    278       break;
    279 
    280     case OPTION_GPR_32:
    281       frv_flags = (frv_flags & ~EF_FRV_GPR_MASK) | EF_FRV_GPR_32;
    282       break;
    283 
    284     case OPTION_GPR_64:
    285       frv_flags = (frv_flags & ~EF_FRV_GPR_MASK) | EF_FRV_GPR_64;
    286       break;
    287 
    288     case OPTION_FPR_32:
    289       frv_flags = (frv_flags & ~EF_FRV_FPR_MASK) | EF_FRV_FPR_32;
    290       break;
    291 
    292     case OPTION_FPR_64:
    293       frv_flags = (frv_flags & ~EF_FRV_FPR_MASK) | EF_FRV_FPR_64;
    294       break;
    295 
    296     case OPTION_SOFT_FLOAT:
    297       frv_flags = (frv_flags & ~EF_FRV_FPR_MASK) | EF_FRV_FPR_NONE;
    298       break;
    299 
    300     case OPTION_DWORD_YES:
    301       frv_flags = (frv_flags & ~EF_FRV_DWORD_MASK) | EF_FRV_DWORD_YES;
    302       break;
    303 
    304     case OPTION_DWORD_NO:
    305       frv_flags = (frv_flags & ~EF_FRV_DWORD_MASK) | EF_FRV_DWORD_NO;
    306       break;
    307 
    308     case OPTION_DOUBLE:
    309       frv_flags |= EF_FRV_DOUBLE;
    310       break;
    311 
    312     case OPTION_NO_DOUBLE:
    313       frv_flags &= ~EF_FRV_DOUBLE;
    314       break;
    315 
    316     case OPTION_MEDIA:
    317       frv_flags |= EF_FRV_MEDIA;
    318       break;
    319 
    320     case OPTION_NO_MEDIA:
    321       frv_flags &= ~EF_FRV_MEDIA;
    322       break;
    323 
    324     case OPTION_MULADD:
    325       frv_flags |= EF_FRV_MULADD;
    326       break;
    327 
    328     case OPTION_NO_MULADD:
    329       frv_flags &= ~EF_FRV_MULADD;
    330       break;
    331 
    332     case OPTION_PACK:
    333       frv_flags &= ~EF_FRV_NOPACK;
    334       break;
    335 
    336     case OPTION_NO_PACK:
    337       frv_flags |= EF_FRV_NOPACK;
    338       break;
    339 
    340     case OPTION_CPU:
    341       {
    342 	char *p;
    343 	int cpu_flags = EF_FRV_CPU_GENERIC;
    344 
    345 	/* Identify the processor type */
    346 	p = arg;
    347 	if (strcmp (p, "frv") == 0)
    348 	  {
    349 	    cpu_flags = EF_FRV_CPU_GENERIC;
    350 	    frv_mach = bfd_mach_frv;
    351 	  }
    352 
    353 	else if (strcmp (p, "fr500") == 0)
    354 	  {
    355 	    cpu_flags = EF_FRV_CPU_FR500;
    356 	    frv_mach = bfd_mach_fr500;
    357 	  }
    358 
    359 	else if (strcmp (p, "fr550") == 0)
    360 	  {
    361 	    cpu_flags = EF_FRV_CPU_FR550;
    362 	    frv_mach = bfd_mach_fr550;
    363 	  }
    364 
    365 	else if (strcmp (p, "fr450") == 0)
    366 	  {
    367 	    cpu_flags = EF_FRV_CPU_FR450;
    368 	    frv_mach = bfd_mach_fr450;
    369 	  }
    370 
    371 	else if (strcmp (p, "fr405") == 0)
    372 	  {
    373 	    cpu_flags = EF_FRV_CPU_FR405;
    374 	    frv_mach = bfd_mach_fr400;
    375 	    fr400_audio = TRUE;
    376 	  }
    377 
    378 	else if (strcmp (p, "fr400") == 0)
    379 	  {
    380 	    cpu_flags = EF_FRV_CPU_FR400;
    381 	    frv_mach = bfd_mach_fr400;
    382 	    fr400_audio = FALSE;
    383 	  }
    384 
    385 	else if (strcmp (p, "fr300") == 0)
    386 	  {
    387 	    cpu_flags = EF_FRV_CPU_FR300;
    388 	    frv_mach = bfd_mach_fr300;
    389 	  }
    390 
    391 	else if (strcmp (p, "simple") == 0)
    392 	  {
    393 	    cpu_flags = EF_FRV_CPU_SIMPLE;
    394 	    frv_mach = bfd_mach_frvsimple;
    395 	    frv_flags |= EF_FRV_NOPACK;
    396 	  }
    397 
    398         else if (strcmp (p, "tomcat") == 0)
    399           {
    400             cpu_flags = EF_FRV_CPU_TOMCAT;
    401             frv_mach = bfd_mach_frvtomcat;
    402           }
    403 
    404 	else
    405 	  {
    406 	    as_fatal (_("Unknown cpu -mcpu=%s"), arg);
    407 	    return 0;
    408 	  }
    409 
    410 	frv_flags = (frv_flags & ~EF_FRV_CPU_MASK) | cpu_flags;
    411       }
    412       break;
    413 
    414     case OPTION_PIC:
    415       frv_flags |= EF_FRV_PIC;
    416       frv_pic_p = 1;
    417       frv_pic_flag = "-fpic";
    418       break;
    419 
    420     case OPTION_BIGPIC:
    421       frv_flags |= EF_FRV_BIGPIC;
    422       frv_pic_p = 1;
    423       frv_pic_flag = "-fPIC";
    424       break;
    425 
    426     case OPTION_LIBPIC:
    427       frv_flags |= (EF_FRV_LIBPIC | EF_FRV_G0);
    428       frv_pic_p = 1;
    429       frv_pic_flag = "-mlibrary-pic";
    430       g_switch_value = 0;
    431       break;
    432 
    433     case OPTION_FDPIC:
    434       frv_flags |= EF_FRV_FDPIC;
    435       frv_pic_flag = "-mfdpic";
    436       break;
    437 
    438     case OPTION_NOPIC:
    439       frv_flags &= ~(EF_FRV_FDPIC | EF_FRV_PIC
    440 		     | EF_FRV_BIGPIC | EF_FRV_LIBPIC);
    441       frv_pic_flag = 0;
    442       break;
    443 
    444     case OPTION_TOMCAT_DEBUG:
    445       tomcat_debug = 1;
    446       break;
    447 
    448     case OPTION_TOMCAT_STATS:
    449       tomcat_stats = 1;
    450       break;
    451     }
    452 
    453   return 1;
    454 }
    455 
    456 void
    457 md_show_usage (FILE * stream)
    458 {
    459   fprintf (stream, _("FRV specific command line options:\n"));
    460   fprintf (stream, _("-G n            Put data <= n bytes in the small data area\n"));
    461   fprintf (stream, _("-mgpr-32        Mark generated file as only using 32 GPRs\n"));
    462   fprintf (stream, _("-mgpr-64        Mark generated file as using all 64 GPRs\n"));
    463   fprintf (stream, _("-mfpr-32        Mark generated file as only using 32 FPRs\n"));
    464   fprintf (stream, _("-mfpr-64        Mark generated file as using all 64 FPRs\n"));
    465   fprintf (stream, _("-msoft-float    Mark generated file as using software FP\n"));
    466   fprintf (stream, _("-mdword         Mark generated file as using a 8-byte stack alignment\n"));
    467   fprintf (stream, _("-mno-dword      Mark generated file as using a 4-byte stack alignment\n"));
    468   fprintf (stream, _("-mdouble        Mark generated file as using double precision FP insns\n"));
    469   fprintf (stream, _("-mmedia         Mark generated file as using media insns\n"));
    470   fprintf (stream, _("-mmuladd        Mark generated file as using multiply add/subtract insns\n"));
    471   fprintf (stream, _("-mpack          Allow instructions to be packed\n"));
    472   fprintf (stream, _("-mno-pack       Do not allow instructions to be packed\n"));
    473   fprintf (stream, _("-mpic           Mark generated file as using small position independent code\n"));
    474   fprintf (stream, _("-mPIC           Mark generated file as using large position independent code\n"));
    475   fprintf (stream, _("-mlibrary-pic   Mark generated file as using position indepedent code for libraries\n"));
    476   fprintf (stream, _("-mfdpic         Assemble for the FDPIC ABI\n"));
    477   fprintf (stream, _("-mnopic         Disable -mpic, -mPIC, -mlibrary-pic and -mfdpic\n"));
    478   fprintf (stream, _("-mcpu={fr500|fr550|fr400|fr405|fr450|fr300|frv|simple|tomcat}\n"));
    479   fprintf (stream, _("                Record the cpu type\n"));
    480   fprintf (stream, _("-mtomcat-stats  Print out stats for tomcat workarounds\n"));
    481   fprintf (stream, _("-mtomcat-debug  Debug tomcat workarounds\n"));
    482 }
    483 
    484 
    485 void
    487 md_begin (void)
    488 {
    489   /* Initialize the `cgen' interface.  */
    490 
    491   /* Set the machine number and endian.  */
    492   gas_cgen_cpu_desc = frv_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, 0,
    493 					 CGEN_CPU_OPEN_ENDIAN,
    494 					 CGEN_ENDIAN_BIG,
    495 					 CGEN_CPU_OPEN_END);
    496   frv_cgen_init_asm (gas_cgen_cpu_desc);
    497 
    498   /* This is a callback from cgen to gas to parse operands.  */
    499   cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
    500 
    501   /* Set the ELF flags if desired. */
    502   if (frv_flags)
    503     bfd_set_private_flags (stdoutput, frv_flags);
    504 
    505   /* Set the machine type */
    506   bfd_default_set_arch_mach (stdoutput, bfd_arch_frv, frv_mach);
    507 
    508   /* Set up gp size so we can put local common items in .sbss */
    509   bfd_set_gp_size (stdoutput, g_switch_value);
    510 
    511   frv_vliw_reset (& vliw, frv_mach, frv_flags);
    512 }
    513 
    514 bfd_boolean
    515 frv_md_fdpic_enabled (void)
    516 {
    517   return (frv_flags & EF_FRV_FDPIC) != 0;
    518 }
    519 
    520 int chain_num = 0;
    521 
    522 static struct vliw_insn_list *
    523 frv_insert_vliw_insn (bfd_boolean count)
    524 {
    525   struct vliw_insn_list *vliw_insn_list_entry;
    526   struct vliw_chain     *vliw_chain_entry;
    527 
    528   if (current_vliw_chain == NULL)
    529     {
    530       vliw_chain_entry = (struct vliw_chain *) xmalloc (sizeof (struct vliw_chain));
    531       vliw_chain_entry->insn_count = 0;
    532       vliw_chain_entry->insn_list  = NULL;
    533       vliw_chain_entry->next       = NULL;
    534       vliw_chain_entry->num        = chain_num++;
    535 
    536       if (!vliw_chain_top)
    537 	vliw_chain_top = vliw_chain_entry;
    538       current_vliw_chain = vliw_chain_entry;
    539       if (previous_vliw_chain)
    540 	previous_vliw_chain->next = vliw_chain_entry;
    541     }
    542 
    543   vliw_insn_list_entry = (struct vliw_insn_list *) xmalloc (sizeof (struct vliw_insn_list));
    544   vliw_insn_list_entry->type      = VLIW_GENERIC_TYPE;
    545   vliw_insn_list_entry->insn      = NULL;
    546   vliw_insn_list_entry->sym       = NULL;
    547   vliw_insn_list_entry->snop_frag = NULL;
    548   vliw_insn_list_entry->dnop_frag = NULL;
    549   vliw_insn_list_entry->next      = NULL;
    550 
    551   if (count)
    552     current_vliw_chain->insn_count++;
    553 
    554   if (current_vliw_insn)
    555     current_vliw_insn->next = vliw_insn_list_entry;
    556   current_vliw_insn = vliw_insn_list_entry;
    557 
    558   if (!current_vliw_chain->insn_list)
    559     current_vliw_chain->insn_list = current_vliw_insn;
    560 
    561   return vliw_insn_list_entry;
    562 }
    563 
    564   /* Identify the following cases:
    565 
    566      1) A VLIW insn that contains both a branch and the branch destination.
    567         This requires the insertion of two vliw instructions before the
    568         branch.  The first consists of two nops.  The second consists of
    569         a single nop.
    570 
    571      2) A single instruction VLIW insn which is the destination of a branch
    572         that is in the next VLIW insn.  This requires the insertion of a vliw
    573         insn containing two nops before the branch.
    574 
    575      3) A double instruction VLIW insn which contains the destination of a
    576         branch that is in the next VLIW insn.  This requires the insertion of
    577         a VLIW insn containing a single nop before the branch.
    578 
    579      4) A single instruction VLIW insn which contains branch destination (x),
    580         followed by a single instruction VLIW insn which does not contain
    581         the branch to (x), followed by a VLIW insn which does contain the branch
    582         to (x).  This requires the insertion of a VLIW insn containing a single
    583         nop before the VLIW instruction containing the branch.
    584 
    585   */
    586 #define FRV_IS_NOP(insn) (insn.buffer[0] == FRV_NOP_PACK || insn.buffer[0] == FRV_NOP_NOPACK)
    587 #define FRV_NOP_PACK   0x00880000  /* ori.p  gr0,0,gr0 */
    588 #define FRV_NOP_NOPACK 0x80880000  /* ori    gr0,0,gr0 */
    589 
    590 /* Check a vliw insn for an insn of type containing the sym passed in label_sym.  */
    591 
    592 static struct vliw_insn_list *
    593 frv_find_in_vliw (enum vliw_insn_type vliw_insn_type,
    594 		  struct vliw_chain *this_chain,
    595 		  symbolS *label_sym)
    596 {
    597 
    598   struct vliw_insn_list *the_insn;
    599 
    600   if (!this_chain)
    601     return NULL;
    602 
    603   for (the_insn = this_chain->insn_list; the_insn; the_insn = the_insn->next)
    604     {
    605       if (the_insn->type == vliw_insn_type
    606 	  && the_insn->sym == label_sym)
    607 	return the_insn;
    608     }
    609 
    610   return NULL;
    611 }
    612 
    613 enum vliw_nop_type
    614 {
    615   /* A Vliw insn containing a single nop insn.  */
    616   VLIW_SINGLE_NOP,
    617 
    618   /* A Vliw insn containing two nop insns.  */
    619   VLIW_DOUBLE_NOP,
    620 
    621   /* Two vliw insns.  The first containing two nop insns.
    622      The second contain a single nop insn.  */
    623   VLIW_DOUBLE_THEN_SINGLE_NOP
    624 };
    625 
    626 static void
    627 frv_debug_tomcat (struct vliw_chain *start_chain)
    628 {
    629    struct vliw_chain *this_chain;
    630    struct vliw_insn_list *this_insn;
    631    int i = 1;
    632 
    633   for (this_chain = start_chain; this_chain; this_chain = this_chain->next, i++)
    634     {
    635       fprintf (stderr, "\nVliw Insn #%d, #insns: %d\n", i, this_chain->insn_count);
    636 
    637       for (this_insn = this_chain->insn_list; this_insn; this_insn = this_insn->next)
    638 	{
    639 	  if (this_insn->type == VLIW_LABEL_TYPE)
    640 	    fprintf (stderr, "Label Value: %p\n", this_insn->sym);
    641 	  else if (this_insn->type == VLIW_BRANCH_TYPE)
    642 	    fprintf (stderr, "%s to %p\n", this_insn->insn->base->name, this_insn->sym);
    643 	  else if (this_insn->type == VLIW_BRANCH_HAS_NOPS)
    644 	    fprintf (stderr, "nop'd %s to %p\n", this_insn->insn->base->name, this_insn->sym);
    645 	  else if (this_insn->type == VLIW_NOP_TYPE)
    646 	    fprintf (stderr, "Nop\n");
    647 	  else
    648 	    fprintf (stderr, "	%s\n", this_insn->insn->base->name);
    649 	}
    650    }
    651 }
    652 
    653 static void
    654 frv_adjust_vliw_count (struct vliw_chain *this_chain)
    655 {
    656   struct vliw_insn_list *this_insn;
    657 
    658   this_chain->insn_count = 0;
    659 
    660   for (this_insn = this_chain->insn_list;
    661        this_insn;
    662        this_insn = this_insn->next)
    663     {
    664       if (this_insn->type != VLIW_LABEL_TYPE)
    665   	this_chain->insn_count++;
    666     }
    667 
    668 }
    669 
    670 /* Insert the desired nop combination in the vliw chain before insert_before_insn.
    671    Rechain the vliw insn.  */
    672 
    673 static struct vliw_chain *
    674 frv_tomcat_shuffle (enum vliw_nop_type this_nop_type,
    675 		    struct vliw_chain *vliw_to_split,
    676 		    struct vliw_insn_list *insert_before_insn)
    677 {
    678 
    679   bfd_boolean pack_prev = FALSE;
    680   struct vliw_chain *return_me = NULL;
    681   struct vliw_insn_list *prev_insn = NULL;
    682   struct vliw_insn_list *curr_insn = vliw_to_split->insn_list;
    683 
    684   struct vliw_chain *double_nop = (struct vliw_chain *) xmalloc (sizeof (struct vliw_chain));
    685   struct vliw_chain *single_nop = (struct vliw_chain *) xmalloc (sizeof (struct vliw_chain));
    686   struct vliw_chain *second_part = (struct vliw_chain *) xmalloc (sizeof (struct vliw_chain));
    687   struct vliw_chain *curr_vliw = vliw_chain_top;
    688   struct vliw_chain *prev_vliw = NULL;
    689 
    690   while (curr_insn && curr_insn != insert_before_insn)
    691     {
    692       /* We can't set the packing bit on a label.  If we have the case
    693 	 label 1:
    694 	 label 2:
    695 	 label 3:
    696 	   branch that needs nops
    697 	Then don't set pack bit later.  */
    698 
    699       if (curr_insn->type != VLIW_LABEL_TYPE)
    700 	pack_prev = TRUE;
    701       prev_insn = curr_insn;
    702       curr_insn = curr_insn->next;
    703     }
    704 
    705   while (curr_vliw && curr_vliw != vliw_to_split)
    706     {
    707       prev_vliw = curr_vliw;
    708       curr_vliw = curr_vliw->next;
    709     }
    710 
    711   switch (this_nop_type)
    712     {
    713     case VLIW_SINGLE_NOP:
    714       if (!prev_insn)
    715 	{
    716 	/* Branch is first,  Insert the NOP prior to this vliw insn.  */
    717 	if (prev_vliw)
    718 	  prev_vliw->next = single_nop;
    719 	else
    720 	  vliw_chain_top = single_nop;
    721 	single_nop->next = vliw_to_split;
    722 	vliw_to_split->insn_list->type = VLIW_BRANCH_HAS_NOPS;
    723 	return_me = vliw_to_split;
    724 	}
    725       else
    726 	{
    727 	  /* Set the packing bit on the previous insn.  */
    728 	  if (pack_prev)
    729 	    {
    730 	      char *buffer = prev_insn->address;
    731 	      buffer[0] |= 0x80;
    732 	    }
    733 	  /* The branch is in the middle.  Split this vliw insn into first
    734 	     and second parts.  Insert the NOP inbetween.  */
    735 
    736           second_part->insn_list = insert_before_insn;
    737 	  second_part->insn_list->type = VLIW_BRANCH_HAS_NOPS;
    738           second_part->next      = vliw_to_split->next;
    739  	  frv_adjust_vliw_count (second_part);
    740 
    741           single_nop->next       = second_part;
    742 
    743           vliw_to_split->next    = single_nop;
    744           prev_insn->next        = NULL;
    745 
    746           return_me = second_part;
    747 	  frv_adjust_vliw_count (vliw_to_split);
    748 	}
    749       break;
    750 
    751     case VLIW_DOUBLE_NOP:
    752       if (!prev_insn)
    753 	{
    754 	/* Branch is first,  Insert the NOP prior to this vliw insn.  */
    755         if (prev_vliw)
    756           prev_vliw->next = double_nop;
    757         else
    758           vliw_chain_top = double_nop;
    759 
    760 	double_nop->next = vliw_to_split;
    761 	return_me = vliw_to_split;
    762 	vliw_to_split->insn_list->type = VLIW_BRANCH_HAS_NOPS;
    763 	}
    764       else
    765 	{
    766 	  /* Set the packing bit on the previous insn.  */
    767 	  if (pack_prev)
    768 	    {
    769 	      char *buffer = prev_insn->address;
    770 	      buffer[0] |= 0x80;
    771 	    }
    772 
    773 	/* The branch is in the middle.  Split this vliw insn into first
    774 	   and second parts.  Insert the NOP inbetween.  */
    775           second_part->insn_list = insert_before_insn;
    776 	  second_part->insn_list->type = VLIW_BRANCH_HAS_NOPS;
    777           second_part->next      = vliw_to_split->next;
    778  	  frv_adjust_vliw_count (second_part);
    779 
    780           double_nop->next       = second_part;
    781 
    782           vliw_to_split->next    = single_nop;
    783           prev_insn->next        = NULL;
    784  	  frv_adjust_vliw_count (vliw_to_split);
    785 
    786           return_me = second_part;
    787 	}
    788       break;
    789 
    790     case VLIW_DOUBLE_THEN_SINGLE_NOP:
    791       double_nop->next = single_nop;
    792       double_nop->insn_count = 2;
    793       double_nop->insn_list = &double_nop_insn;
    794       single_nop->insn_count = 1;
    795       single_nop->insn_list = &single_nop_insn;
    796 
    797       if (!prev_insn)
    798 	{
    799 	  /* The branch is the first insn in this vliw.  Don't split the vliw.  Insert
    800 	     the nops prior to this vliw.  */
    801           if (prev_vliw)
    802             prev_vliw->next = double_nop;
    803           else
    804             vliw_chain_top = double_nop;
    805 
    806 	  single_nop->next = vliw_to_split;
    807 	  return_me = vliw_to_split;
    808 	  vliw_to_split->insn_list->type = VLIW_BRANCH_HAS_NOPS;
    809 	}
    810       else
    811 	{
    812 	  /* Set the packing bit on the previous insn.  */
    813 	  if (pack_prev)
    814 	    {
    815 	      char *buffer = prev_insn->address;
    816 	      buffer[0] |= 0x80;
    817 	    }
    818 
    819 	  /* The branch is in the middle of this vliw insn.  Split into first and
    820 	     second parts.  Insert the nop vliws in between.  */
    821 	  second_part->insn_list = insert_before_insn;
    822 	  second_part->insn_list->type = VLIW_BRANCH_HAS_NOPS;
    823 	  second_part->next      = vliw_to_split->next;
    824  	  frv_adjust_vliw_count (second_part);
    825 
    826 	  single_nop->next       = second_part;
    827 
    828 	  vliw_to_split->next	 = double_nop;
    829 	  prev_insn->next	 = NULL;
    830  	  frv_adjust_vliw_count (vliw_to_split);
    831 
    832 	  return_me = second_part;
    833 	}
    834       break;
    835     }
    836 
    837   return return_me;
    838 }
    839 
    840 static void
    841 frv_tomcat_analyze_vliw_chains (void)
    842 {
    843   struct vliw_chain *vliw1 = NULL;
    844   struct vliw_chain *vliw2 = NULL;
    845   struct vliw_chain *vliw3 = NULL;
    846 
    847   struct vliw_insn_list *this_insn = NULL;
    848   struct vliw_insn_list *temp_insn = NULL;
    849 
    850   /* We potentially need to look at three VLIW insns to determine if the
    851      workaround is required.  Set them up.  Ignore existing nops during analysis. */
    852 
    853 #define FRV_SET_VLIW_WINDOW(VLIW1, VLIW2, VLIW3) \
    854   if (VLIW1 && VLIW1->next)			 \
    855     VLIW2 = VLIW1->next;			 \
    856   else						 \
    857     VLIW2 = NULL;				 \
    858   if (VLIW2 && VLIW2->next)			 \
    859     VLIW3 = VLIW2->next;			 \
    860   else						 \
    861     VLIW3 = NULL
    862 
    863   vliw1 = vliw_chain_top;
    864 
    865 workaround_top:
    866 
    867   FRV_SET_VLIW_WINDOW (vliw1, vliw2, vliw3);
    868 
    869   if (!vliw1)
    870     return;
    871 
    872   if (vliw1->insn_count == 1)
    873     {
    874       /* check vliw1 for a label. */
    875       if (vliw1->insn_list->type == VLIW_LABEL_TYPE)
    876 	{
    877 	  temp_insn = frv_find_in_vliw (VLIW_BRANCH_TYPE, vliw2, vliw1->insn_list->sym);
    878 	  if (temp_insn)
    879 	    {
    880 	      vliw1 = frv_tomcat_shuffle (VLIW_DOUBLE_NOP, vliw2, vliw1->insn_list);
    881 	      temp_insn->dnop_frag->fr_subtype = NOP_KEEP;
    882 	      vliw1 = vliw1->next;
    883 	      if (tomcat_stats)
    884 		tomcat_doubles++;
    885 	      goto workaround_top;
    886 	    }
    887 	  else if (vliw2
    888 		   && vliw2->insn_count == 1
    889 		   && (temp_insn = frv_find_in_vliw (VLIW_BRANCH_TYPE, vliw3, vliw1->insn_list->sym)) != NULL)
    890 	    {
    891 	      temp_insn->snop_frag->fr_subtype = NOP_KEEP;
    892 	      vliw1 = frv_tomcat_shuffle (VLIW_SINGLE_NOP, vliw3, vliw3->insn_list);
    893 	      if (tomcat_stats)
    894 		tomcat_singles++;
    895 	      goto workaround_top;
    896 	    }
    897 	}
    898     }
    899 
    900   if (vliw1->insn_count == 2)
    901     {
    902       /* Check vliw1 for a label. */
    903       for (this_insn = vliw1->insn_list; this_insn; this_insn = this_insn->next)
    904 	{
    905 	  if (this_insn->type == VLIW_LABEL_TYPE)
    906 	    {
    907 	      if ((temp_insn = frv_find_in_vliw (VLIW_BRANCH_TYPE, vliw2, this_insn->sym)) != NULL)
    908 		{
    909 		  temp_insn->snop_frag->fr_subtype = NOP_KEEP;
    910 		  vliw1 = frv_tomcat_shuffle (VLIW_SINGLE_NOP, vliw2, this_insn);
    911 		  if (tomcat_stats)
    912 		    tomcat_singles++;
    913 		}
    914 	      else
    915 		vliw1 = vliw1->next;
    916               goto workaround_top;
    917             }
    918 	}
    919     }
    920   /* Examine each insn in this VLIW.  Look for the workaround criteria.  */
    921   for (this_insn = vliw1->insn_list; this_insn; this_insn = this_insn->next)
    922     {
    923       /* Don't look at labels or nops.  */
    924       while (this_insn
    925 	     && (this_insn->type == VLIW_LABEL_TYPE
    926                  || this_insn->type == VLIW_NOP_TYPE
    927 		 || this_insn->type == VLIW_BRANCH_HAS_NOPS))
    928 	this_insn = this_insn->next;
    929 
    930       if (!this_insn)
    931         {
    932 	  vliw1 = vliw2;
    933 	  goto workaround_top;
    934 	}
    935 
    936       if (frv_is_branch_insn (this_insn->insn))
    937 	{
    938 	  if ((temp_insn = frv_find_in_vliw (VLIW_LABEL_TYPE, vliw1, this_insn->sym)) != NULL)
    939 	    {
    940 	      /* Insert [nop/nop] [nop] before branch.  */
    941 	      this_insn->snop_frag->fr_subtype = NOP_KEEP;
    942 	      this_insn->dnop_frag->fr_subtype = NOP_KEEP;
    943 	      vliw1 = frv_tomcat_shuffle (VLIW_DOUBLE_THEN_SINGLE_NOP, vliw1, this_insn);
    944 	      goto workaround_top;
    945 	    }
    946 	}
    947 
    948 
    949     }
    950   /* This vliw insn checks out okay.  Take a look at the next one.  */
    951   vliw1 = vliw1->next;
    952   goto workaround_top;
    953 }
    954 
    955 void
    956 frv_tomcat_workaround (void)
    957 {
    958   if (frv_mach != bfd_mach_frvtomcat)
    959     return;
    960 
    961   if (tomcat_debug)
    962     frv_debug_tomcat (vliw_chain_top);
    963 
    964   frv_tomcat_analyze_vliw_chains ();
    965 
    966   if (tomcat_stats)
    967     {
    968       fprintf (stderr, "Inserted %d Single Nops\n", tomcat_singles);
    969       fprintf (stderr, "Inserted %d Double Nops\n", tomcat_doubles);
    970     }
    971 }
    972 
    973 static int
    974 fr550_check_insn_acc_range (frv_insn *insn, int low, int hi)
    975 {
    976   int acc;
    977   switch (CGEN_INSN_NUM (insn->insn))
    978     {
    979     case FRV_INSN_MADDACCS:
    980     case FRV_INSN_MSUBACCS:
    981     case FRV_INSN_MDADDACCS:
    982     case FRV_INSN_MDSUBACCS:
    983     case FRV_INSN_MASACCS:
    984     case FRV_INSN_MDASACCS:
    985       acc = insn->fields.f_ACC40Si;
    986       if (acc < low || acc > hi)
    987 	return 1; /* out of range */
    988       acc = insn->fields.f_ACC40Sk;
    989       if (acc < low || acc > hi)
    990 	return 1; /* out of range */
    991       break;
    992     case FRV_INSN_MMULHS:
    993     case FRV_INSN_MMULHU:
    994     case FRV_INSN_MMULXHS:
    995     case FRV_INSN_MMULXHU:
    996     case FRV_INSN_CMMULHS:
    997     case FRV_INSN_CMMULHU:
    998     case FRV_INSN_MQMULHS:
    999     case FRV_INSN_MQMULHU:
   1000     case FRV_INSN_MQMULXHS:
   1001     case FRV_INSN_MQMULXHU:
   1002     case FRV_INSN_CMQMULHS:
   1003     case FRV_INSN_CMQMULHU:
   1004     case FRV_INSN_MMACHS:
   1005     case FRV_INSN_MMRDHS:
   1006     case FRV_INSN_CMMACHS:
   1007     case FRV_INSN_MQMACHS:
   1008     case FRV_INSN_CMQMACHS:
   1009     case FRV_INSN_MQXMACHS:
   1010     case FRV_INSN_MQXMACXHS:
   1011     case FRV_INSN_MQMACXHS:
   1012     case FRV_INSN_MCPXRS:
   1013     case FRV_INSN_MCPXIS:
   1014     case FRV_INSN_CMCPXRS:
   1015     case FRV_INSN_CMCPXIS:
   1016     case FRV_INSN_MQCPXRS:
   1017     case FRV_INSN_MQCPXIS:
   1018      acc = insn->fields.f_ACC40Sk;
   1019       if (acc < low || acc > hi)
   1020 	return 1; /* out of range */
   1021       break;
   1022     case FRV_INSN_MMACHU:
   1023     case FRV_INSN_MMRDHU:
   1024     case FRV_INSN_CMMACHU:
   1025     case FRV_INSN_MQMACHU:
   1026     case FRV_INSN_CMQMACHU:
   1027     case FRV_INSN_MCPXRU:
   1028     case FRV_INSN_MCPXIU:
   1029     case FRV_INSN_CMCPXRU:
   1030     case FRV_INSN_CMCPXIU:
   1031     case FRV_INSN_MQCPXRU:
   1032     case FRV_INSN_MQCPXIU:
   1033       acc = insn->fields.f_ACC40Uk;
   1034       if (acc < low || acc > hi)
   1035 	return 1; /* out of range */
   1036       break;
   1037     default:
   1038       break;
   1039     }
   1040   return 0; /* all is ok */
   1041 }
   1042 
   1043 static int
   1044 fr550_check_acc_range (FRV_VLIW *vlw, frv_insn *insn)
   1045 {
   1046   switch ((*vlw->current_vliw)[vlw->next_slot - 1])
   1047     {
   1048     case UNIT_FM0:
   1049     case UNIT_FM2:
   1050       return fr550_check_insn_acc_range (insn, 0, 3);
   1051     case UNIT_FM1:
   1052     case UNIT_FM3:
   1053       return fr550_check_insn_acc_range (insn, 4, 7);
   1054     default:
   1055       break;
   1056     }
   1057   return 0; /* all is ok */
   1058 }
   1059 
   1060 /* Return true if the target implements instruction INSN.  */
   1061 
   1062 static bfd_boolean
   1063 target_implements_insn_p (const CGEN_INSN *insn)
   1064 {
   1065   switch (frv_mach)
   1066     {
   1067     default:
   1068       /* bfd_mach_frv or generic.  */
   1069       return TRUE;
   1070 
   1071     case bfd_mach_fr300:
   1072     case bfd_mach_frvsimple:
   1073       return CGEN_INSN_MACH_HAS_P (insn, MACH_SIMPLE);
   1074 
   1075     case bfd_mach_fr400:
   1076       return ((fr400_audio || !CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_AUDIO))
   1077 	      && CGEN_INSN_MACH_HAS_P (insn, MACH_FR400));
   1078 
   1079     case bfd_mach_fr450:
   1080       return CGEN_INSN_MACH_HAS_P (insn, MACH_FR450);
   1081 
   1082     case bfd_mach_fr500:
   1083       return CGEN_INSN_MACH_HAS_P (insn, MACH_FR500);
   1084 
   1085     case bfd_mach_fr550:
   1086       return CGEN_INSN_MACH_HAS_P (insn, MACH_FR550);
   1087     }
   1088 }
   1089 
   1090 void
   1091 md_assemble (char *str)
   1092 {
   1093   frv_insn insn;
   1094   char *errmsg;
   1095   int packing_constraint;
   1096   finished_insnS  finished_insn;
   1097   fragS *double_nop_frag = NULL;
   1098   fragS *single_nop_frag = NULL;
   1099   struct vliw_insn_list *vliw_insn_list_entry = NULL;
   1100 
   1101   /* Initialize GAS's cgen interface for a new instruction.  */
   1102   gas_cgen_init_parse ();
   1103 
   1104   memset (&insn, 0, sizeof (insn));
   1105 
   1106   insn.insn = frv_cgen_assemble_insn
   1107     (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, &errmsg);
   1108 
   1109   if (!insn.insn)
   1110     {
   1111       as_bad ("%s", errmsg);
   1112       return;
   1113     }
   1114 
   1115   /* If the cpu is tomcat, then we need to insert nops to workaround
   1116      hardware limitations.  We need to keep track of each vliw unit
   1117      and examine the length of the unit and the individual insns
   1118      within the unit to determine the number and location of the
   1119      required nops.  */
   1120   if (frv_mach == bfd_mach_frvtomcat)
   1121     {
   1122       /* If we've just finished a VLIW insn OR this is a branch,
   1123 	 then start up a new frag.  Fill it with nops.  We will get rid
   1124 	 of those that are not required after we've seen all of the
   1125 	 instructions but before we start resolving fixups.  */
   1126       if ( !FRV_IS_NOP (insn)
   1127 	  && (frv_is_branch_insn (insn.insn) || insn.fields.f_pack))
   1128 	{
   1129 	  char *buffer;
   1130 
   1131 	  frag_wane (frag_now);
   1132 	  frag_new (0);
   1133 	  double_nop_frag = frag_now;
   1134 	  buffer = frag_var (rs_machine_dependent, 8, 8, NOP_DELETE, NULL, 0, 0);
   1135 	  md_number_to_chars (buffer, FRV_NOP_PACK, 4);
   1136 	  md_number_to_chars (buffer+4, FRV_NOP_NOPACK, 4);
   1137 
   1138 	  frag_wane (frag_now);
   1139 	  frag_new (0);
   1140 	  single_nop_frag = frag_now;
   1141 	  buffer = frag_var (rs_machine_dependent, 4, 4, NOP_DELETE, NULL, 0, 0);
   1142 	  md_number_to_chars (buffer, FRV_NOP_NOPACK, 4);
   1143 	}
   1144 
   1145       vliw_insn_list_entry = frv_insert_vliw_insn (DO_COUNT);
   1146       vliw_insn_list_entry->insn   = insn.insn;
   1147       if (frv_is_branch_insn (insn.insn))
   1148 	vliw_insn_list_entry->type = VLIW_BRANCH_TYPE;
   1149 
   1150       if ( !FRV_IS_NOP (insn)
   1151 	  && (frv_is_branch_insn (insn.insn) || insn.fields.f_pack))
   1152 	{
   1153 	  vliw_insn_list_entry->snop_frag = single_nop_frag;
   1154 	  vliw_insn_list_entry->dnop_frag = double_nop_frag;
   1155 	}
   1156     }
   1157 
   1158   /* Make sure that this insn does not violate the VLIW packing constraints.  */
   1159   /* -mno-pack disallows any packing whatsoever.  */
   1160   if (frv_flags & EF_FRV_NOPACK)
   1161     {
   1162       if (! insn.fields.f_pack)
   1163 	{
   1164 	  as_bad (_("VLIW packing used for -mno-pack"));
   1165 	  return;
   1166 	}
   1167     }
   1168   /* -mcpu=FRV is an idealized FR-V implementation that supports all of the
   1169      instructions, don't do vliw checking.  */
   1170   else if (frv_mach != bfd_mach_frv)
   1171     {
   1172       if (!target_implements_insn_p (insn.insn))
   1173 	{
   1174 	  as_bad (_("Instruction not supported by this architecture"));
   1175 	  return;
   1176 	}
   1177       packing_constraint = frv_vliw_add_insn (& vliw, insn.insn);
   1178       if (frv_mach == bfd_mach_fr550 && ! packing_constraint)
   1179 	packing_constraint = fr550_check_acc_range (& vliw, & insn);
   1180       if (insn.fields.f_pack)
   1181 	frv_vliw_reset (& vliw, frv_mach, frv_flags);
   1182       if (packing_constraint)
   1183 	{
   1184 	  as_bad (_("VLIW packing constraint violation"));
   1185 	  return;
   1186 	}
   1187     }
   1188 
   1189   /* Doesn't really matter what we pass for RELAX_P here.  */
   1190   gas_cgen_finish_insn (insn.insn, insn.buffer,
   1191 			CGEN_FIELDS_BITSIZE (& insn.fields), 1, &finished_insn);
   1192 
   1193 
   1194   /* If the cpu is tomcat, then we need to insert nops to workaround
   1195      hardware limitations.  We need to keep track of each vliw unit
   1196      and examine the length of the unit and the individual insns
   1197      within the unit to determine the number and location of the
   1198      required nops.  */
   1199   if (frv_mach == bfd_mach_frvtomcat)
   1200     {
   1201       if (vliw_insn_list_entry)
   1202         vliw_insn_list_entry->address = finished_insn.addr;
   1203       else
   1204 	abort();
   1205 
   1206       if (insn.fields.f_pack)
   1207 	{
   1208 	  /* We've completed a VLIW insn.  */
   1209 	  previous_vliw_chain = current_vliw_chain;
   1210 	  current_vliw_chain = NULL;
   1211 	  current_vliw_insn  = NULL;
   1212         }
   1213     }
   1214 }
   1215 
   1216 /* The syntax in the manual says constants begin with '#'.
   1217    We just ignore it.  */
   1218 
   1219 void
   1220 md_operand (expressionS *expressionP)
   1221 {
   1222   if (* input_line_pointer == '#')
   1223     {
   1224       input_line_pointer ++;
   1225       expression (expressionP);
   1226     }
   1227 }
   1228 
   1229 valueT
   1230 md_section_align (segT segment, valueT size)
   1231 {
   1232   int align = bfd_get_section_alignment (stdoutput, segment);
   1233   return ((size + (1 << align) - 1) & (-1 << align));
   1234 }
   1235 
   1236 symbolS *
   1237 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
   1238 {
   1239   return 0;
   1240 }
   1241 
   1242 /* Interface to relax_segment.  */
   1244 
   1245 /* FIXME: Build table by hand, get it working, then machine generate.  */
   1246 const relax_typeS md_relax_table[] =
   1247 {
   1248   {1, 1, 0, 0},
   1249   {511 - 2 - 2, -512 - 2 + 2, 0, 2 },
   1250   {0x2000000 - 1 - 2, -0x2000000 - 2, 2, 0 },
   1251   {0x2000000 - 1 - 2, -0x2000000 - 2, 4, 0 }
   1252 };
   1253 
   1254 long
   1255 frv_relax_frag (fragS *fragP ATTRIBUTE_UNUSED, long stretch ATTRIBUTE_UNUSED)
   1256 {
   1257   return 0;
   1258 }
   1259 
   1260 /* Return an initial guess of the length by which a fragment must grow to
   1261    hold a branch to reach its destination.
   1262    Also updates fr_type/fr_subtype as necessary.
   1263 
   1264    Called just before doing relaxation.
   1265    Any symbol that is now undefined will not become defined.
   1266    The guess for fr_var is ACTUALLY the growth beyond fr_fix.
   1267    Whatever we do to grow fr_fix or fr_var contributes to our returned value.
   1268    Although it may not be explicit in the frag, pretend fr_var starts with a
   1269    0 value.  */
   1270 
   1271 int
   1272 md_estimate_size_before_relax (fragS *fragP, segT segment ATTRIBUTE_UNUSED)
   1273 {
   1274   switch (fragP->fr_subtype)
   1275     {
   1276     case NOP_KEEP:
   1277       return fragP->fr_var;
   1278 
   1279     default:
   1280     case NOP_DELETE:
   1281       return 0;
   1282     }
   1283 }
   1284 
   1285 /* *fragP has been relaxed to its final size, and now needs to have
   1286    the bytes inside it modified to conform to the new size.
   1287 
   1288    Called after relaxation is finished.
   1289    fragP->fr_type == rs_machine_dependent.
   1290    fragP->fr_subtype is the subtype of what the address relaxed to.  */
   1291 
   1292 void
   1293 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
   1294 		 segT sec ATTRIBUTE_UNUSED,
   1295 		 fragS *fragP)
   1296 {
   1297   switch (fragP->fr_subtype)
   1298     {
   1299     default:
   1300     case NOP_DELETE:
   1301       return;
   1302 
   1303     case NOP_KEEP:
   1304       fragP->fr_fix = fragP->fr_var;
   1305       fragP->fr_var = 0;
   1306       return;
   1307     }
   1308 }
   1309 
   1310 /* Functions concerning relocs.  */
   1312 
   1313 /* The location from which a PC relative jump should be calculated,
   1314    given a PC relative reloc.  */
   1315 
   1316 long
   1317 md_pcrel_from_section (fixS *fixP, segT sec)
   1318 {
   1319   if (TC_FORCE_RELOCATION (fixP)
   1320       || (fixP->fx_addsy != (symbolS *) NULL
   1321 	  && S_GET_SEGMENT (fixP->fx_addsy) != sec))
   1322     {
   1323       /* If we can't adjust this relocation, or if it references a
   1324 	 local symbol in a different section (which
   1325 	 TC_FORCE_RELOCATION can't check), let the linker figure it
   1326 	 out.  */
   1327       return 0;
   1328     }
   1329 
   1330   return (fixP->fx_frag->fr_address + fixP->fx_where) & ~1;
   1331 }
   1332 
   1333 /* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
   1334    Returns BFD_RELOC_NONE if no reloc type can be found.
   1335    *FIXP may be modified if desired.  */
   1336 
   1337 bfd_reloc_code_real_type
   1338 md_cgen_lookup_reloc (const CGEN_INSN *insn ATTRIBUTE_UNUSED,
   1339 		      const CGEN_OPERAND *operand,
   1340 		      fixS *fixP)
   1341 {
   1342   switch (operand->type)
   1343     {
   1344     case FRV_OPERAND_LABEL16:
   1345       fixP->fx_pcrel = TRUE;
   1346       return BFD_RELOC_FRV_LABEL16;
   1347 
   1348     case FRV_OPERAND_LABEL24:
   1349       fixP->fx_pcrel = TRUE;
   1350 
   1351       if (fixP->fx_cgen.opinfo != 0)
   1352 	return fixP->fx_cgen.opinfo;
   1353 
   1354       return BFD_RELOC_FRV_LABEL24;
   1355 
   1356     case FRV_OPERAND_UHI16:
   1357     case FRV_OPERAND_ULO16:
   1358     case FRV_OPERAND_SLO16:
   1359     case FRV_OPERAND_CALLANN:
   1360     case FRV_OPERAND_LDANN:
   1361     case FRV_OPERAND_LDDANN:
   1362       /* The relocation type should be recorded in opinfo */
   1363       if (fixP->fx_cgen.opinfo != 0)
   1364         return fixP->fx_cgen.opinfo;
   1365       break;
   1366 
   1367     case FRV_OPERAND_D12:
   1368     case FRV_OPERAND_S12:
   1369       if (fixP->fx_cgen.opinfo != 0)
   1370 	return fixP->fx_cgen.opinfo;
   1371 
   1372       return BFD_RELOC_FRV_GPREL12;
   1373 
   1374     case FRV_OPERAND_U12:
   1375       return BFD_RELOC_FRV_GPRELU12;
   1376 
   1377     default:
   1378       break;
   1379     }
   1380   return BFD_RELOC_NONE;
   1381 }
   1382 
   1383 
   1384 /* See whether we need to force a relocation into the output file.
   1385    This is used to force out switch and PC relative relocations when
   1386    relaxing.  */
   1387 
   1388 int
   1389 frv_force_relocation (fixS *fix)
   1390 {
   1391   switch (fix->fx_r_type < BFD_RELOC_UNUSED
   1392 	  ? (int) fix->fx_r_type
   1393 	  : fix->fx_cgen.opinfo)
   1394     {
   1395     case BFD_RELOC_FRV_GPREL12:
   1396     case BFD_RELOC_FRV_GPRELU12:
   1397     case BFD_RELOC_FRV_GPREL32:
   1398     case BFD_RELOC_FRV_GPRELHI:
   1399     case BFD_RELOC_FRV_GPRELLO:
   1400     case BFD_RELOC_FRV_GOT12:
   1401     case BFD_RELOC_FRV_GOTHI:
   1402     case BFD_RELOC_FRV_GOTLO:
   1403     case BFD_RELOC_FRV_FUNCDESC_VALUE:
   1404     case BFD_RELOC_FRV_FUNCDESC_GOTOFF12:
   1405     case BFD_RELOC_FRV_FUNCDESC_GOTOFFHI:
   1406     case BFD_RELOC_FRV_FUNCDESC_GOTOFFLO:
   1407     case BFD_RELOC_FRV_GOTOFF12:
   1408     case BFD_RELOC_FRV_GOTOFFHI:
   1409     case BFD_RELOC_FRV_GOTOFFLO:
   1410     case BFD_RELOC_FRV_GETTLSOFF:
   1411     case BFD_RELOC_FRV_TLSDESC_VALUE:
   1412     case BFD_RELOC_FRV_GOTTLSDESC12:
   1413     case BFD_RELOC_FRV_GOTTLSDESCHI:
   1414     case BFD_RELOC_FRV_GOTTLSDESCLO:
   1415     case BFD_RELOC_FRV_TLSMOFF12:
   1416     case BFD_RELOC_FRV_TLSMOFFHI:
   1417     case BFD_RELOC_FRV_TLSMOFFLO:
   1418     case BFD_RELOC_FRV_GOTTLSOFF12:
   1419     case BFD_RELOC_FRV_GOTTLSOFFHI:
   1420     case BFD_RELOC_FRV_GOTTLSOFFLO:
   1421     case BFD_RELOC_FRV_TLSOFF:
   1422     case BFD_RELOC_FRV_TLSDESC_RELAX:
   1423     case BFD_RELOC_FRV_GETTLSOFF_RELAX:
   1424     case BFD_RELOC_FRV_TLSOFF_RELAX:
   1425       return 1;
   1426 
   1427     default:
   1428       break;
   1429     }
   1430 
   1431   return generic_force_reloc (fix);
   1432 }
   1433 
   1434 /* Apply a fixup that could be resolved within the assembler.  */
   1435 
   1436 void
   1437 md_apply_fix (fixS *fixP, valueT *valP, segT seg)
   1438 {
   1439   if (fixP->fx_addsy == 0)
   1440     switch (fixP->fx_cgen.opinfo)
   1441       {
   1442       case BFD_RELOC_FRV_HI16:
   1443 	*valP >>= 16;
   1444 	/* Fall through.  */
   1445       case BFD_RELOC_FRV_LO16:
   1446 	*valP &= 0xffff;
   1447 	break;
   1448 
   1449 	/* We need relocations for these, even if their symbols reduce
   1450 	   to constants.  */
   1451       case BFD_RELOC_FRV_GPREL12:
   1452       case BFD_RELOC_FRV_GPRELU12:
   1453       case BFD_RELOC_FRV_GPREL32:
   1454       case BFD_RELOC_FRV_GPRELHI:
   1455       case BFD_RELOC_FRV_GPRELLO:
   1456       case BFD_RELOC_FRV_GOT12:
   1457       case BFD_RELOC_FRV_GOTHI:
   1458       case BFD_RELOC_FRV_GOTLO:
   1459       case BFD_RELOC_FRV_FUNCDESC_VALUE:
   1460       case BFD_RELOC_FRV_FUNCDESC_GOTOFF12:
   1461       case BFD_RELOC_FRV_FUNCDESC_GOTOFFHI:
   1462       case BFD_RELOC_FRV_FUNCDESC_GOTOFFLO:
   1463       case BFD_RELOC_FRV_GOTOFF12:
   1464       case BFD_RELOC_FRV_GOTOFFHI:
   1465       case BFD_RELOC_FRV_GOTOFFLO:
   1466       case BFD_RELOC_FRV_GETTLSOFF:
   1467       case BFD_RELOC_FRV_TLSDESC_VALUE:
   1468       case BFD_RELOC_FRV_GOTTLSDESC12:
   1469       case BFD_RELOC_FRV_GOTTLSDESCHI:
   1470       case BFD_RELOC_FRV_GOTTLSDESCLO:
   1471       case BFD_RELOC_FRV_TLSMOFF12:
   1472       case BFD_RELOC_FRV_TLSMOFFHI:
   1473       case BFD_RELOC_FRV_TLSMOFFLO:
   1474       case BFD_RELOC_FRV_GOTTLSOFF12:
   1475       case BFD_RELOC_FRV_GOTTLSOFFHI:
   1476       case BFD_RELOC_FRV_GOTTLSOFFLO:
   1477       case BFD_RELOC_FRV_TLSOFF:
   1478       case BFD_RELOC_FRV_TLSDESC_RELAX:
   1479       case BFD_RELOC_FRV_GETTLSOFF_RELAX:
   1480       case BFD_RELOC_FRV_TLSOFF_RELAX:
   1481 	fixP->fx_addsy = abs_section_sym;
   1482 	break;
   1483       }
   1484   else
   1485     switch (fixP->fx_cgen.opinfo)
   1486       {
   1487       case BFD_RELOC_FRV_GETTLSOFF:
   1488       case BFD_RELOC_FRV_TLSDESC_VALUE:
   1489       case BFD_RELOC_FRV_GOTTLSDESC12:
   1490       case BFD_RELOC_FRV_GOTTLSDESCHI:
   1491       case BFD_RELOC_FRV_GOTTLSDESCLO:
   1492       case BFD_RELOC_FRV_TLSMOFF12:
   1493       case BFD_RELOC_FRV_TLSMOFFHI:
   1494       case BFD_RELOC_FRV_TLSMOFFLO:
   1495       case BFD_RELOC_FRV_GOTTLSOFF12:
   1496       case BFD_RELOC_FRV_GOTTLSOFFHI:
   1497       case BFD_RELOC_FRV_GOTTLSOFFLO:
   1498       case BFD_RELOC_FRV_TLSOFF:
   1499       case BFD_RELOC_FRV_TLSDESC_RELAX:
   1500       case BFD_RELOC_FRV_GETTLSOFF_RELAX:
   1501       case BFD_RELOC_FRV_TLSOFF_RELAX:
   1502 	/* Mark TLS symbols as such.  */
   1503 	if (S_GET_SEGMENT (fixP->fx_addsy) != absolute_section)
   1504 	  S_SET_THREAD_LOCAL (fixP->fx_addsy);
   1505 	break;
   1506       }
   1507 
   1508   gas_cgen_md_apply_fix (fixP, valP, seg);
   1509   return;
   1510 }
   1511 
   1512 
   1513 /* Write a value out to the object file, using the appropriate endianness.  */
   1515 
   1516 void
   1517 frv_md_number_to_chars (char *buf, valueT val, int n)
   1518 {
   1519   number_to_chars_bigendian (buf, val, n);
   1520 }
   1521 
   1522 char *
   1523 md_atof (int type, char *litP, int *sizeP)
   1524 {
   1525   return ieee_md_atof (type, litP, sizeP, TRUE);
   1526 }
   1527 
   1528 bfd_boolean
   1529 frv_fix_adjustable (fixS *fixP)
   1530 {
   1531   bfd_reloc_code_real_type reloc_type;
   1532 
   1533   if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
   1534     {
   1535       const CGEN_INSN *insn = NULL;
   1536       int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
   1537       const CGEN_OPERAND *operand = cgen_operand_lookup_by_num(gas_cgen_cpu_desc, opindex);
   1538       reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
   1539     }
   1540   else
   1541     reloc_type = fixP->fx_r_type;
   1542 
   1543   /* We need the symbol name for the VTABLE entries */
   1544   if (   reloc_type == BFD_RELOC_VTABLE_INHERIT
   1545       || reloc_type == BFD_RELOC_VTABLE_ENTRY
   1546       || reloc_type == BFD_RELOC_FRV_GPREL12
   1547       || reloc_type == BFD_RELOC_FRV_GPRELU12)
   1548     return 0;
   1549 
   1550   return 1;
   1551 }
   1552 
   1553 /* Allow user to set flags bits.  */
   1554 void
   1555 frv_set_flags (int arg ATTRIBUTE_UNUSED)
   1556 {
   1557   flagword new_flags = get_absolute_expression ();
   1558   flagword new_mask = ~ (flagword)0;
   1559 
   1560   frv_user_set_flags_p = 1;
   1561   if (*input_line_pointer == ',')
   1562     {
   1563       ++input_line_pointer;
   1564       new_mask = get_absolute_expression ();
   1565     }
   1566 
   1567   frv_flags = (frv_flags & ~new_mask) | (new_flags & new_mask);
   1568   bfd_set_private_flags (stdoutput, frv_flags);
   1569 }
   1570 
   1571 /* Frv specific function to handle 4 byte initializations for pointers that are
   1572    considered 'safe' for use with pic support.  Until frv_frob_file{,_section}
   1573    is run, we encode it a BFD_RELOC_CTOR, and it is turned back into a normal
   1574    BFD_RELOC_32 at that time.  */
   1575 
   1576 void
   1577 frv_pic_ptr (int nbytes)
   1578 {
   1579   expressionS exp;
   1580   char *p;
   1581 
   1582   if (nbytes != 4)
   1583     abort ();
   1584 
   1585 #ifdef md_flush_pending_output
   1586   md_flush_pending_output ();
   1587 #endif
   1588 
   1589   if (is_it_end_of_statement ())
   1590     {
   1591       demand_empty_rest_of_line ();
   1592       return;
   1593     }
   1594 
   1595 #ifdef md_cons_align
   1596   md_cons_align (nbytes);
   1597 #endif
   1598 
   1599   do
   1600     {
   1601       bfd_reloc_code_real_type reloc_type = BFD_RELOC_CTOR;
   1602 
   1603       if (strncasecmp (input_line_pointer, "funcdesc(", 9) == 0)
   1604 	{
   1605 	  input_line_pointer += 9;
   1606 	  expression (&exp);
   1607 	  if (*input_line_pointer == ')')
   1608 	    input_line_pointer++;
   1609 	  else
   1610 	    as_bad (_("missing ')'"));
   1611 	  reloc_type = BFD_RELOC_FRV_FUNCDESC;
   1612 	}
   1613       else if (strncasecmp (input_line_pointer, "tlsmoff(", 8) == 0)
   1614 	{
   1615 	  input_line_pointer += 8;
   1616 	  expression (&exp);
   1617 	  if (*input_line_pointer == ')')
   1618 	    input_line_pointer++;
   1619 	  else
   1620 	    as_bad (_("missing ')'"));
   1621 	  reloc_type = BFD_RELOC_FRV_TLSMOFF;
   1622 	}
   1623       else
   1624 	expression (&exp);
   1625 
   1626       p = frag_more (4);
   1627       memset (p, 0, 4);
   1628       fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &exp, 0,
   1629 		   reloc_type);
   1630     }
   1631   while (*input_line_pointer++ == ',');
   1632 
   1633   input_line_pointer--;			/* Put terminator back into stream. */
   1634   demand_empty_rest_of_line ();
   1635 }
   1636 
   1637 
   1638 
   1640 #ifdef DEBUG
   1641 #define DPRINTF1(A)	fprintf (stderr, A)
   1642 #define DPRINTF2(A,B)	fprintf (stderr, A, B)
   1643 #define DPRINTF3(A,B,C)	fprintf (stderr, A, B, C)
   1644 
   1645 #else
   1646 #define DPRINTF1(A)
   1647 #define DPRINTF2(A,B)
   1648 #define DPRINTF3(A,B,C)
   1649 #endif
   1650 
   1651 /* Go through a the sections looking for relocations that are problematical for
   1652    pic.  If not pic, just note that this object can't be linked with pic.  If
   1653    it is pic, see if it needs to be marked so that it will be fixed up, or if
   1654    not possible, issue an error.  */
   1655 
   1656 static void
   1657 frv_frob_file_section (bfd *abfd, asection *sec, void *ptr ATTRIBUTE_UNUSED)
   1658 {
   1659   segment_info_type *seginfo = seg_info (sec);
   1660   fixS *fixp;
   1661   CGEN_CPU_DESC cd = gas_cgen_cpu_desc;
   1662   flagword flags = bfd_get_section_flags (abfd, sec);
   1663 
   1664   /* Skip relocations in known sections (.ctors, .dtors, and .gcc_except_table)
   1665      since we can fix those up by hand.  */
   1666   int known_section_p = (sec->name
   1667 			 && sec->name[0] == '.'
   1668 			 && ((sec->name[1] == 'c'
   1669 			      && strcmp (sec->name, ".ctor") == 0)
   1670 			     || (sec->name[1] == 'd'
   1671 				 && strcmp (sec->name, ".dtor") == 0)
   1672 			     || (sec->name[1] == 'g'
   1673 				 && strcmp (sec->name, ".gcc_except_table") == 0)));
   1674 
   1675   DPRINTF3 ("\nFrv section %s%s\n", sec->name, (known_section_p) ? ", known section" : "");
   1676   if ((flags & SEC_ALLOC) == 0)
   1677     {
   1678       DPRINTF1 ("\tSkipping non-loaded section\n");
   1679       return;
   1680     }
   1681 
   1682   for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next)
   1683     {
   1684       symbolS *s = fixp->fx_addsy;
   1685       bfd_reloc_code_real_type reloc;
   1686       int non_pic_p;
   1687       int opindex;
   1688       const CGEN_OPERAND *operand;
   1689       const CGEN_INSN *insn = fixp->fx_cgen.insn;
   1690 
   1691       if (fixp->fx_done)
   1692 	{
   1693 	  DPRINTF1 ("\tSkipping reloc that has already been done\n");
   1694 	  continue;
   1695 	}
   1696 
   1697       if (fixp->fx_pcrel)
   1698 	{
   1699 	  DPRINTF1 ("\tSkipping reloc that is PC relative\n");
   1700 	  continue;
   1701 	}
   1702 
   1703       if (! s)
   1704 	{
   1705 	  DPRINTF1 ("\tSkipping reloc without symbol\n");
   1706 	  continue;
   1707 	}
   1708 
   1709       if (fixp->fx_r_type < BFD_RELOC_UNUSED)
   1710 	{
   1711 	  opindex = -1;
   1712 	  reloc = fixp->fx_r_type;
   1713 	}
   1714       else
   1715 	{
   1716 	  opindex = (int) fixp->fx_r_type - (int) BFD_RELOC_UNUSED;
   1717 	  operand = cgen_operand_lookup_by_num (cd, opindex);
   1718 	  reloc = md_cgen_lookup_reloc (insn, operand, fixp);
   1719 	}
   1720 
   1721       DPRINTF3 ("\treloc %s\t%s", bfd_get_reloc_code_name (reloc), S_GET_NAME (s));
   1722 
   1723       non_pic_p = 0;
   1724       switch (reloc)
   1725 	{
   1726 	default:
   1727 	  break;
   1728 
   1729 	case BFD_RELOC_32:
   1730 	  /* Skip relocations in known sections (.ctors, .dtors, and
   1731 	     .gcc_except_table) since we can fix those up by hand.  Also
   1732 	     skip forward references to constants.  Also skip a difference
   1733 	     of two symbols, which still uses the BFD_RELOC_32 at this
   1734 	     point.  */
   1735 	  if (! known_section_p
   1736 	      && S_GET_SEGMENT (s) != absolute_section
   1737 	      && !fixp->fx_subsy
   1738 	      && (flags & (SEC_READONLY | SEC_CODE)) == 0)
   1739 	    {
   1740 	      non_pic_p = 1;
   1741 	    }
   1742 	  break;
   1743 
   1744 	  /* FIXME -- should determine if any of the GP relocation really uses
   1745 	     gr16 (which is not pic safe) or not.  Right now, assume if we
   1746 	     aren't being compiled with -mpic, the usage is non pic safe, but
   1747 	     is safe with -mpic.  */
   1748 	case BFD_RELOC_FRV_GPREL12:
   1749 	case BFD_RELOC_FRV_GPRELU12:
   1750 	case BFD_RELOC_FRV_GPREL32:
   1751 	case BFD_RELOC_FRV_GPRELHI:
   1752 	case BFD_RELOC_FRV_GPRELLO:
   1753 	  non_pic_p = ! frv_pic_p;
   1754 	  break;
   1755 
   1756 	case BFD_RELOC_FRV_LO16:
   1757 	case BFD_RELOC_FRV_HI16:
   1758 	  if (S_GET_SEGMENT (s) != absolute_section)
   1759 	    non_pic_p = 1;
   1760 	  break;
   1761 
   1762 	case BFD_RELOC_VTABLE_INHERIT:
   1763 	case BFD_RELOC_VTABLE_ENTRY:
   1764 	  non_pic_p = 1;
   1765 	  break;
   1766 
   1767 	  /* If this is a blessed BFD_RELOC_32, convert it back to the normal
   1768              relocation.  */
   1769 	case BFD_RELOC_CTOR:
   1770 	  fixp->fx_r_type = BFD_RELOC_32;
   1771 	  break;
   1772 	}
   1773 
   1774       if (non_pic_p)
   1775 	{
   1776 	  DPRINTF1 (" (Non-pic relocation)\n");
   1777 	  if (frv_pic_p)
   1778 	    as_warn_where (fixp->fx_file, fixp->fx_line,
   1779 			   _("Relocation %s is not safe for %s"),
   1780 			   bfd_get_reloc_code_name (reloc), frv_pic_flag);
   1781 
   1782 	  else if ((frv_flags & EF_FRV_NON_PIC_RELOCS) == 0)
   1783 	    {
   1784 	      frv_flags |= EF_FRV_NON_PIC_RELOCS;
   1785 	      bfd_set_private_flags (abfd, frv_flags);
   1786 	    }
   1787 	}
   1788 #ifdef DEBUG
   1789       else
   1790 	DPRINTF1 ("\n");
   1791 #endif
   1792     }
   1793 }
   1794 
   1795 /* After all of the symbols have been adjusted, go over the file looking
   1796    for any relocations that pic won't support.  */
   1797 
   1798 void
   1799 frv_frob_file (void)
   1800 {
   1801   bfd_map_over_sections (stdoutput, frv_frob_file_section, (void *) 0);
   1802 }
   1803 
   1804 void
   1805 frv_frob_label (symbolS *this_label)
   1806 {
   1807   struct vliw_insn_list *vliw_insn_list_entry;
   1808 
   1809   dwarf2_emit_label (this_label);
   1810   if (frv_mach != bfd_mach_frvtomcat)
   1811     return;
   1812 
   1813   if (now_seg != text_section)
   1814     return;
   1815 
   1816   vliw_insn_list_entry = frv_insert_vliw_insn(DONT_COUNT);
   1817   vliw_insn_list_entry->type = VLIW_LABEL_TYPE;
   1818   vliw_insn_list_entry->sym  = this_label;
   1819 }
   1820 
   1821 fixS *
   1822 frv_cgen_record_fixup_exp (fragS *frag,
   1823 			   int where,
   1824 			   const CGEN_INSN *insn,
   1825 			   int length,
   1826 			   const CGEN_OPERAND *operand,
   1827 			   int opinfo,
   1828 			   expressionS *exp)
   1829 {
   1830   fixS * fixP = gas_cgen_record_fixup_exp (frag, where, insn, length,
   1831                                            operand, opinfo, exp);
   1832 
   1833   if (frv_mach == bfd_mach_frvtomcat
   1834       && current_vliw_insn
   1835       && current_vliw_insn->type == VLIW_BRANCH_TYPE
   1836       && exp != NULL)
   1837     current_vliw_insn->sym = exp->X_add_symbol;
   1838 
   1839   return fixP;
   1840 }
   1841