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