Home | History | Annotate | Line # | Download | only in config
tc-frv.c revision 1.1
      1 /* tc-frv.c -- Assembler for the Fujitsu FRV.
      2    Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008
      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 
     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, 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 	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 = (struct vliw_chain *) xmalloc (sizeof (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 = (struct vliw_insn_list *) xmalloc (sizeof (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 = (struct vliw_chain *) xmalloc (sizeof (struct vliw_chain));
    684   struct vliw_chain *single_nop = (struct vliw_chain *) xmalloc (sizeof (struct vliw_chain));
    685   struct vliw_chain *second_part = (struct vliw_chain *) xmalloc (sizeof (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       struct vliw_insn_list *this_insn;
    902 
    903       /* check vliw1 for a label. */
    904       for (this_insn = vliw1->insn_list; this_insn; this_insn = this_insn->next)
    905 	{
    906 	  if (this_insn->type == VLIW_LABEL_TYPE)
    907 	    {
    908 	      if ((temp_insn = frv_find_in_vliw (VLIW_BRANCH_TYPE, vliw2, this_insn->sym)) != NULL)
    909 		{
    910 		  temp_insn->snop_frag->fr_subtype = NOP_KEEP;
    911 		  vliw1 = frv_tomcat_shuffle (VLIW_SINGLE_NOP, vliw2, this_insn);
    912 		  if (tomcat_stats)
    913 		    tomcat_singles++;
    914 		}
    915 	      else
    916 		vliw1 = vliw1->next;
    917               goto workaround_top;
    918             }
    919 	}
    920     }
    921   /* Examine each insn in this VLIW.  Look for the workaround criteria.  */
    922   for (this_insn = vliw1->insn_list; this_insn; this_insn = this_insn->next)
    923     {
    924       /* Don't look at labels or nops.  */
    925       while (this_insn
    926 	     && (this_insn->type == VLIW_LABEL_TYPE
    927                  || this_insn->type == VLIW_NOP_TYPE
    928 		 || this_insn->type == VLIW_BRANCH_HAS_NOPS))
    929 	this_insn = this_insn->next;
    930 
    931       if (!this_insn)
    932         {
    933 	  vliw1 = vliw2;
    934 	  goto workaround_top;
    935 	}
    936 
    937       if (frv_is_branch_insn (this_insn->insn))
    938 	{
    939 	  if ((temp_insn = frv_find_in_vliw (VLIW_LABEL_TYPE, vliw1, this_insn->sym)) != NULL)
    940 	    {
    941 	      /* Insert [nop/nop] [nop] before branch.  */
    942 	      this_insn->snop_frag->fr_subtype = NOP_KEEP;
    943 	      this_insn->dnop_frag->fr_subtype = NOP_KEEP;
    944 	      vliw1 = frv_tomcat_shuffle (VLIW_DOUBLE_THEN_SINGLE_NOP, vliw1, this_insn);
    945 	      goto workaround_top;
    946 	    }
    947 	}
    948 
    949 
    950     }
    951   /* This vliw insn checks out okay.  Take a look at the next one.  */
    952   vliw1 = vliw1->next;
    953   goto workaround_top;
    954 }
    955 
    956 void
    957 frv_tomcat_workaround (void)
    958 {
    959   if (frv_mach != bfd_mach_frvtomcat)
    960     return;
    961 
    962   if (tomcat_debug)
    963     frv_debug_tomcat (vliw_chain_top);
    964 
    965   frv_tomcat_analyze_vliw_chains ();
    966 
    967   if (tomcat_stats)
    968     {
    969       fprintf (stderr, "Inserted %d Single Nops\n", tomcat_singles);
    970       fprintf (stderr, "Inserted %d Double Nops\n", tomcat_doubles);
    971     }
    972 }
    973 
    974 static int
    975 fr550_check_insn_acc_range (frv_insn *insn, int low, int hi)
    976 {
    977   int acc;
    978   switch (CGEN_INSN_NUM (insn->insn))
    979     {
    980     case FRV_INSN_MADDACCS:
    981     case FRV_INSN_MSUBACCS:
    982     case FRV_INSN_MDADDACCS:
    983     case FRV_INSN_MDSUBACCS:
    984     case FRV_INSN_MASACCS:
    985     case FRV_INSN_MDASACCS:
    986       acc = insn->fields.f_ACC40Si;
    987       if (acc < low || acc > hi)
    988 	return 1; /* out of range */
    989       acc = insn->fields.f_ACC40Sk;
    990       if (acc < low || acc > hi)
    991 	return 1; /* out of range */
    992       break;
    993     case FRV_INSN_MMULHS:
    994     case FRV_INSN_MMULHU:
    995     case FRV_INSN_MMULXHS:
    996     case FRV_INSN_MMULXHU:
    997     case FRV_INSN_CMMULHS:
    998     case FRV_INSN_CMMULHU:
    999     case FRV_INSN_MQMULHS:
   1000     case FRV_INSN_MQMULHU:
   1001     case FRV_INSN_MQMULXHS:
   1002     case FRV_INSN_MQMULXHU:
   1003     case FRV_INSN_CMQMULHS:
   1004     case FRV_INSN_CMQMULHU:
   1005     case FRV_INSN_MMACHS:
   1006     case FRV_INSN_MMRDHS:
   1007     case FRV_INSN_CMMACHS:
   1008     case FRV_INSN_MQMACHS:
   1009     case FRV_INSN_CMQMACHS:
   1010     case FRV_INSN_MQXMACHS:
   1011     case FRV_INSN_MQXMACXHS:
   1012     case FRV_INSN_MQMACXHS:
   1013     case FRV_INSN_MCPXRS:
   1014     case FRV_INSN_MCPXIS:
   1015     case FRV_INSN_CMCPXRS:
   1016     case FRV_INSN_CMCPXIS:
   1017     case FRV_INSN_MQCPXRS:
   1018     case FRV_INSN_MQCPXIS:
   1019      acc = insn->fields.f_ACC40Sk;
   1020       if (acc < low || acc > hi)
   1021 	return 1; /* out of range */
   1022       break;
   1023     case FRV_INSN_MMACHU:
   1024     case FRV_INSN_MMRDHU:
   1025     case FRV_INSN_CMMACHU:
   1026     case FRV_INSN_MQMACHU:
   1027     case FRV_INSN_CMQMACHU:
   1028     case FRV_INSN_MCPXRU:
   1029     case FRV_INSN_MCPXIU:
   1030     case FRV_INSN_CMCPXRU:
   1031     case FRV_INSN_CMCPXIU:
   1032     case FRV_INSN_MQCPXRU:
   1033     case FRV_INSN_MQCPXIU:
   1034       acc = insn->fields.f_ACC40Uk;
   1035       if (acc < low || acc > hi)
   1036 	return 1; /* out of range */
   1037       break;
   1038     default:
   1039       break;
   1040     }
   1041   return 0; /* all is ok */
   1042 }
   1043 
   1044 static int
   1045 fr550_check_acc_range (FRV_VLIW *vliw, frv_insn *insn)
   1046 {
   1047   switch ((*vliw->current_vliw)[vliw->next_slot - 1])
   1048     {
   1049     case UNIT_FM0:
   1050     case UNIT_FM2:
   1051       return fr550_check_insn_acc_range (insn, 0, 3);
   1052     case UNIT_FM1:
   1053     case UNIT_FM3:
   1054       return fr550_check_insn_acc_range (insn, 4, 7);
   1055     default:
   1056       break;
   1057     }
   1058   return 0; /* all is ok */
   1059 }
   1060 
   1061 /* Return true if the target implements instruction INSN.  */
   1062 
   1063 static bfd_boolean
   1064 target_implements_insn_p (const CGEN_INSN *insn)
   1065 {
   1066   switch (frv_mach)
   1067     {
   1068     default:
   1069       /* bfd_mach_frv or generic.  */
   1070       return TRUE;
   1071 
   1072     case bfd_mach_fr300:
   1073     case bfd_mach_frvsimple:
   1074       return CGEN_INSN_MACH_HAS_P (insn, MACH_SIMPLE);
   1075 
   1076     case bfd_mach_fr400:
   1077       return ((fr400_audio || !CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_AUDIO))
   1078 	      && CGEN_INSN_MACH_HAS_P (insn, MACH_FR400));
   1079 
   1080     case bfd_mach_fr450:
   1081       return CGEN_INSN_MACH_HAS_P (insn, MACH_FR450);
   1082 
   1083     case bfd_mach_fr500:
   1084       return CGEN_INSN_MACH_HAS_P (insn, MACH_FR500);
   1085 
   1086     case bfd_mach_fr550:
   1087       return CGEN_INSN_MACH_HAS_P (insn, MACH_FR550);
   1088     }
   1089 }
   1090 
   1091 void
   1092 md_assemble (char *str)
   1093 {
   1094   frv_insn insn;
   1095   char *errmsg;
   1096   int packing_constraint;
   1097   finished_insnS  finished_insn;
   1098   fragS *double_nop_frag = NULL;
   1099   fragS *single_nop_frag = NULL;
   1100   struct vliw_insn_list *vliw_insn_list_entry = NULL;
   1101 
   1102   /* Initialize GAS's cgen interface for a new instruction.  */
   1103   gas_cgen_init_parse ();
   1104 
   1105   memset (&insn, 0, sizeof (insn));
   1106 
   1107   insn.insn = frv_cgen_assemble_insn
   1108     (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, &errmsg);
   1109 
   1110   if (!insn.insn)
   1111     {
   1112       as_bad (errmsg);
   1113       return;
   1114     }
   1115 
   1116   /* If the cpu is tomcat, then we need to insert nops to workaround
   1117      hardware limitations.  We need to keep track of each vliw unit
   1118      and examine the length of the unit and the individual insns
   1119      within the unit to determine the number and location of the
   1120      required nops.  */
   1121   if (frv_mach == bfd_mach_frvtomcat)
   1122     {
   1123       /* If we've just finished a VLIW insn OR this is a branch,
   1124 	 then start up a new frag.  Fill it with nops.  We will get rid
   1125 	 of those that are not required after we've seen all of the
   1126 	 instructions but before we start resolving fixups.  */
   1127       if ( !FRV_IS_NOP (insn)
   1128 	  && (frv_is_branch_insn (insn.insn) || insn.fields.f_pack))
   1129 	{
   1130 	  char *buffer;
   1131 
   1132 	  frag_wane (frag_now);
   1133 	  frag_new (0);
   1134 	  double_nop_frag = frag_now;
   1135 	  buffer = frag_var (rs_machine_dependent, 8, 8, NOP_DELETE, NULL, 0, 0);
   1136 	  md_number_to_chars (buffer, FRV_NOP_PACK, 4);
   1137 	  md_number_to_chars (buffer+4, FRV_NOP_NOPACK, 4);
   1138 
   1139 	  frag_wane (frag_now);
   1140 	  frag_new (0);
   1141 	  single_nop_frag = frag_now;
   1142 	  buffer = frag_var (rs_machine_dependent, 4, 4, NOP_DELETE, NULL, 0, 0);
   1143 	  md_number_to_chars (buffer, FRV_NOP_NOPACK, 4);
   1144 	}
   1145 
   1146       vliw_insn_list_entry = frv_insert_vliw_insn (DO_COUNT);
   1147       vliw_insn_list_entry->insn   = insn.insn;
   1148       if (frv_is_branch_insn (insn.insn))
   1149 	vliw_insn_list_entry->type = VLIW_BRANCH_TYPE;
   1150 
   1151       if ( !FRV_IS_NOP (insn)
   1152 	  && (frv_is_branch_insn (insn.insn) || insn.fields.f_pack))
   1153 	{
   1154 	  vliw_insn_list_entry->snop_frag = single_nop_frag;
   1155 	  vliw_insn_list_entry->dnop_frag = double_nop_frag;
   1156 	}
   1157     }
   1158 
   1159   /* Make sure that this insn does not violate the VLIW packing constraints.  */
   1160   /* -mno-pack disallows any packing whatsoever.  */
   1161   if (frv_flags & EF_FRV_NOPACK)
   1162     {
   1163       if (! insn.fields.f_pack)
   1164 	{
   1165 	  as_bad (_("VLIW packing used for -mno-pack"));
   1166 	  return;
   1167 	}
   1168     }
   1169   /* -mcpu=FRV is an idealized FR-V implementation that supports all of the
   1170      instructions, don't do vliw checking.  */
   1171   else if (frv_mach != bfd_mach_frv)
   1172     {
   1173       if (!target_implements_insn_p (insn.insn))
   1174 	{
   1175 	  as_bad (_("Instruction not supported by this architecture"));
   1176 	  return;
   1177 	}
   1178       packing_constraint = frv_vliw_add_insn (& vliw, insn.insn);
   1179       if (frv_mach == bfd_mach_fr550 && ! packing_constraint)
   1180 	packing_constraint = fr550_check_acc_range (& vliw, & insn);
   1181       if (insn.fields.f_pack)
   1182 	frv_vliw_reset (& vliw, frv_mach, frv_flags);
   1183       if (packing_constraint)
   1184 	{
   1185 	  as_bad (_("VLIW packing constraint violation"));
   1186 	  return;
   1187 	}
   1188     }
   1189 
   1190   /* Doesn't really matter what we pass for RELAX_P here.  */
   1191   gas_cgen_finish_insn (insn.insn, insn.buffer,
   1192 			CGEN_FIELDS_BITSIZE (& insn.fields), 1, &finished_insn);
   1193 
   1194 
   1195   /* If the cpu is tomcat, then we need to insert nops to workaround
   1196      hardware limitations.  We need to keep track of each vliw unit
   1197      and examine the length of the unit and the individual insns
   1198      within the unit to determine the number and location of the
   1199      required nops.  */
   1200   if (frv_mach == bfd_mach_frvtomcat)
   1201     {
   1202       if (vliw_insn_list_entry)
   1203         vliw_insn_list_entry->address = finished_insn.addr;
   1204       else
   1205 	abort();
   1206 
   1207       if (insn.fields.f_pack)
   1208 	{
   1209 	  /* We've completed a VLIW insn.  */
   1210 	  previous_vliw_chain = current_vliw_chain;
   1211 	  current_vliw_chain = NULL;
   1212 	  current_vliw_insn  = NULL;
   1213         }
   1214     }
   1215 }
   1216 
   1217 /* The syntax in the manual says constants begin with '#'.
   1218    We just ignore it.  */
   1219 
   1220 void
   1221 md_operand (expressionS *expressionP)
   1222 {
   1223   if (* input_line_pointer == '#')
   1224     {
   1225       input_line_pointer ++;
   1226       expression (expressionP);
   1227     }
   1228 }
   1229 
   1230 valueT
   1231 md_section_align (segT segment, valueT size)
   1232 {
   1233   int align = bfd_get_section_alignment (stdoutput, segment);
   1234   return ((size + (1 << align) - 1) & (-1 << align));
   1235 }
   1236 
   1237 symbolS *
   1238 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
   1239 {
   1240   return 0;
   1241 }
   1242 
   1243 /* Interface to relax_segment.  */
   1245 
   1246 /* FIXME: Build table by hand, get it working, then machine generate.  */
   1247 const relax_typeS md_relax_table[] =
   1248 {
   1249   {1, 1, 0, 0},
   1250   {511 - 2 - 2, -512 - 2 + 2, 0, 2 },
   1251   {0x2000000 - 1 - 2, -0x2000000 - 2, 2, 0 },
   1252   {0x2000000 - 1 - 2, -0x2000000 - 2, 4, 0 }
   1253 };
   1254 
   1255 long
   1256 frv_relax_frag (fragS *fragP ATTRIBUTE_UNUSED, long stretch ATTRIBUTE_UNUSED)
   1257 {
   1258   return 0;
   1259 }
   1260 
   1261 /* Return an initial guess of the length by which a fragment must grow to
   1262    hold a branch to reach its destination.
   1263    Also updates fr_type/fr_subtype as necessary.
   1264 
   1265    Called just before doing relaxation.
   1266    Any symbol that is now undefined will not become defined.
   1267    The guess for fr_var is ACTUALLY the growth beyond fr_fix.
   1268    Whatever we do to grow fr_fix or fr_var contributes to our returned value.
   1269    Although it may not be explicit in the frag, pretend fr_var starts with a
   1270    0 value.  */
   1271 
   1272 int
   1273 md_estimate_size_before_relax (fragS *fragP, segT segment ATTRIBUTE_UNUSED)
   1274 {
   1275   switch (fragP->fr_subtype)
   1276     {
   1277     case NOP_KEEP:
   1278       return fragP->fr_var;
   1279 
   1280     default:
   1281     case NOP_DELETE:
   1282       return 0;
   1283     }
   1284 }
   1285 
   1286 /* *fragP has been relaxed to its final size, and now needs to have
   1287    the bytes inside it modified to conform to the new size.
   1288 
   1289    Called after relaxation is finished.
   1290    fragP->fr_type == rs_machine_dependent.
   1291    fragP->fr_subtype is the subtype of what the address relaxed to.  */
   1292 
   1293 void
   1294 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
   1295 		 segT sec ATTRIBUTE_UNUSED,
   1296 		 fragS *fragP)
   1297 {
   1298   switch (fragP->fr_subtype)
   1299     {
   1300     default:
   1301     case NOP_DELETE:
   1302       return;
   1303 
   1304     case NOP_KEEP:
   1305       fragP->fr_fix = fragP->fr_var;
   1306       fragP->fr_var = 0;
   1307       return;
   1308     }
   1309 }
   1310 
   1311 /* Functions concerning relocs.  */
   1313 
   1314 /* The location from which a PC relative jump should be calculated,
   1315    given a PC relative reloc.  */
   1316 
   1317 long
   1318 md_pcrel_from_section (fixS *fixP, segT sec)
   1319 {
   1320   if (TC_FORCE_RELOCATION (fixP)
   1321       || (fixP->fx_addsy != (symbolS *) NULL
   1322 	  && S_GET_SEGMENT (fixP->fx_addsy) != sec))
   1323     {
   1324       /* If we can't adjust this relocation, or if it references a
   1325 	 local symbol in a different section (which
   1326 	 TC_FORCE_RELOCATION can't check), let the linker figure it
   1327 	 out.  */
   1328       return 0;
   1329     }
   1330 
   1331   return (fixP->fx_frag->fr_address + fixP->fx_where) & ~1;
   1332 }
   1333 
   1334 /* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
   1335    Returns BFD_RELOC_NONE if no reloc type can be found.
   1336    *FIXP may be modified if desired.  */
   1337 
   1338 bfd_reloc_code_real_type
   1339 md_cgen_lookup_reloc (const CGEN_INSN *insn ATTRIBUTE_UNUSED,
   1340 		      const CGEN_OPERAND *operand,
   1341 		      fixS *fixP)
   1342 {
   1343   switch (operand->type)
   1344     {
   1345     case FRV_OPERAND_LABEL16:
   1346       fixP->fx_pcrel = TRUE;
   1347       return BFD_RELOC_FRV_LABEL16;
   1348 
   1349     case FRV_OPERAND_LABEL24:
   1350       fixP->fx_pcrel = TRUE;
   1351 
   1352       if (fixP->fx_cgen.opinfo != 0)
   1353 	return fixP->fx_cgen.opinfo;
   1354 
   1355       return BFD_RELOC_FRV_LABEL24;
   1356 
   1357     case FRV_OPERAND_UHI16:
   1358     case FRV_OPERAND_ULO16:
   1359     case FRV_OPERAND_SLO16:
   1360     case FRV_OPERAND_CALLANN:
   1361     case FRV_OPERAND_LDANN:
   1362     case FRV_OPERAND_LDDANN:
   1363       /* The relocation type should be recorded in opinfo */
   1364       if (fixP->fx_cgen.opinfo != 0)
   1365         return fixP->fx_cgen.opinfo;
   1366       break;
   1367 
   1368     case FRV_OPERAND_D12:
   1369     case FRV_OPERAND_S12:
   1370       if (fixP->fx_cgen.opinfo != 0)
   1371 	return fixP->fx_cgen.opinfo;
   1372 
   1373       return BFD_RELOC_FRV_GPREL12;
   1374 
   1375     case FRV_OPERAND_U12:
   1376       return BFD_RELOC_FRV_GPRELU12;
   1377 
   1378     default:
   1379       break;
   1380     }
   1381   return BFD_RELOC_NONE;
   1382 }
   1383 
   1384 
   1385 /* See whether we need to force a relocation into the output file.
   1386    This is used to force out switch and PC relative relocations when
   1387    relaxing.  */
   1388 
   1389 int
   1390 frv_force_relocation (fixS *fix)
   1391 {
   1392   switch (fix->fx_r_type < BFD_RELOC_UNUSED
   1393 	  ? (int) fix->fx_r_type
   1394 	  : fix->fx_cgen.opinfo)
   1395     {
   1396     case BFD_RELOC_FRV_GPREL12:
   1397     case BFD_RELOC_FRV_GPRELU12:
   1398     case BFD_RELOC_FRV_GPREL32:
   1399     case BFD_RELOC_FRV_GPRELHI:
   1400     case BFD_RELOC_FRV_GPRELLO:
   1401     case BFD_RELOC_FRV_GOT12:
   1402     case BFD_RELOC_FRV_GOTHI:
   1403     case BFD_RELOC_FRV_GOTLO:
   1404     case BFD_RELOC_FRV_FUNCDESC_VALUE:
   1405     case BFD_RELOC_FRV_FUNCDESC_GOTOFF12:
   1406     case BFD_RELOC_FRV_FUNCDESC_GOTOFFHI:
   1407     case BFD_RELOC_FRV_FUNCDESC_GOTOFFLO:
   1408     case BFD_RELOC_FRV_GOTOFF12:
   1409     case BFD_RELOC_FRV_GOTOFFHI:
   1410     case BFD_RELOC_FRV_GOTOFFLO:
   1411     case BFD_RELOC_FRV_GETTLSOFF:
   1412     case BFD_RELOC_FRV_TLSDESC_VALUE:
   1413     case BFD_RELOC_FRV_GOTTLSDESC12:
   1414     case BFD_RELOC_FRV_GOTTLSDESCHI:
   1415     case BFD_RELOC_FRV_GOTTLSDESCLO:
   1416     case BFD_RELOC_FRV_TLSMOFF12:
   1417     case BFD_RELOC_FRV_TLSMOFFHI:
   1418     case BFD_RELOC_FRV_TLSMOFFLO:
   1419     case BFD_RELOC_FRV_GOTTLSOFF12:
   1420     case BFD_RELOC_FRV_GOTTLSOFFHI:
   1421     case BFD_RELOC_FRV_GOTTLSOFFLO:
   1422     case BFD_RELOC_FRV_TLSOFF:
   1423     case BFD_RELOC_FRV_TLSDESC_RELAX:
   1424     case BFD_RELOC_FRV_GETTLSOFF_RELAX:
   1425     case BFD_RELOC_FRV_TLSOFF_RELAX:
   1426       return 1;
   1427 
   1428     default:
   1429       break;
   1430     }
   1431 
   1432   return generic_force_reloc (fix);
   1433 }
   1434 
   1435 /* Apply a fixup that could be resolved within the assembler.  */
   1436 
   1437 void
   1438 md_apply_fix (fixS *fixP, valueT *valP, segT seg)
   1439 {
   1440   if (fixP->fx_addsy == 0)
   1441     switch (fixP->fx_cgen.opinfo)
   1442       {
   1443       case BFD_RELOC_FRV_HI16:
   1444 	*valP >>= 16;
   1445 	/* Fall through.  */
   1446       case BFD_RELOC_FRV_LO16:
   1447 	*valP &= 0xffff;
   1448 	break;
   1449 
   1450 	/* We need relocations for these, even if their symbols reduce
   1451 	   to constants.  */
   1452       case BFD_RELOC_FRV_GPREL12:
   1453       case BFD_RELOC_FRV_GPRELU12:
   1454       case BFD_RELOC_FRV_GPREL32:
   1455       case BFD_RELOC_FRV_GPRELHI:
   1456       case BFD_RELOC_FRV_GPRELLO:
   1457       case BFD_RELOC_FRV_GOT12:
   1458       case BFD_RELOC_FRV_GOTHI:
   1459       case BFD_RELOC_FRV_GOTLO:
   1460       case BFD_RELOC_FRV_FUNCDESC_VALUE:
   1461       case BFD_RELOC_FRV_FUNCDESC_GOTOFF12:
   1462       case BFD_RELOC_FRV_FUNCDESC_GOTOFFHI:
   1463       case BFD_RELOC_FRV_FUNCDESC_GOTOFFLO:
   1464       case BFD_RELOC_FRV_GOTOFF12:
   1465       case BFD_RELOC_FRV_GOTOFFHI:
   1466       case BFD_RELOC_FRV_GOTOFFLO:
   1467       case BFD_RELOC_FRV_GETTLSOFF:
   1468       case BFD_RELOC_FRV_TLSDESC_VALUE:
   1469       case BFD_RELOC_FRV_GOTTLSDESC12:
   1470       case BFD_RELOC_FRV_GOTTLSDESCHI:
   1471       case BFD_RELOC_FRV_GOTTLSDESCLO:
   1472       case BFD_RELOC_FRV_TLSMOFF12:
   1473       case BFD_RELOC_FRV_TLSMOFFHI:
   1474       case BFD_RELOC_FRV_TLSMOFFLO:
   1475       case BFD_RELOC_FRV_GOTTLSOFF12:
   1476       case BFD_RELOC_FRV_GOTTLSOFFHI:
   1477       case BFD_RELOC_FRV_GOTTLSOFFLO:
   1478       case BFD_RELOC_FRV_TLSOFF:
   1479       case BFD_RELOC_FRV_TLSDESC_RELAX:
   1480       case BFD_RELOC_FRV_GETTLSOFF_RELAX:
   1481       case BFD_RELOC_FRV_TLSOFF_RELAX:
   1482 	fixP->fx_addsy = abs_section_sym;
   1483 	break;
   1484       }
   1485   else
   1486     switch (fixP->fx_cgen.opinfo)
   1487       {
   1488       case BFD_RELOC_FRV_GETTLSOFF:
   1489       case BFD_RELOC_FRV_TLSDESC_VALUE:
   1490       case BFD_RELOC_FRV_GOTTLSDESC12:
   1491       case BFD_RELOC_FRV_GOTTLSDESCHI:
   1492       case BFD_RELOC_FRV_GOTTLSDESCLO:
   1493       case BFD_RELOC_FRV_TLSMOFF12:
   1494       case BFD_RELOC_FRV_TLSMOFFHI:
   1495       case BFD_RELOC_FRV_TLSMOFFLO:
   1496       case BFD_RELOC_FRV_GOTTLSOFF12:
   1497       case BFD_RELOC_FRV_GOTTLSOFFHI:
   1498       case BFD_RELOC_FRV_GOTTLSOFFLO:
   1499       case BFD_RELOC_FRV_TLSOFF:
   1500       case BFD_RELOC_FRV_TLSDESC_RELAX:
   1501       case BFD_RELOC_FRV_GETTLSOFF_RELAX:
   1502       case BFD_RELOC_FRV_TLSOFF_RELAX:
   1503 	/* Mark TLS symbols as such.  */
   1504 	if (S_GET_SEGMENT (fixP->fx_addsy) != absolute_section)
   1505 	  S_SET_THREAD_LOCAL (fixP->fx_addsy);
   1506 	break;
   1507       }
   1508 
   1509   gas_cgen_md_apply_fix (fixP, valP, seg);
   1510   return;
   1511 }
   1512 
   1513 
   1514 /* Write a value out to the object file, using the appropriate endianness.  */
   1516 
   1517 void
   1518 frv_md_number_to_chars (char *buf, valueT val, int n)
   1519 {
   1520   number_to_chars_bigendian (buf, val, n);
   1521 }
   1522 
   1523 char *
   1524 md_atof (int type, char *litP, int *sizeP)
   1525 {
   1526   return ieee_md_atof (type, litP, sizeP, TRUE);
   1527 }
   1528 
   1529 bfd_boolean
   1530 frv_fix_adjustable (fixS *fixP)
   1531 {
   1532   bfd_reloc_code_real_type reloc_type;
   1533 
   1534   if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
   1535     {
   1536       const CGEN_INSN *insn = NULL;
   1537       int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
   1538       const CGEN_OPERAND *operand = cgen_operand_lookup_by_num(gas_cgen_cpu_desc, opindex);
   1539       reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
   1540     }
   1541   else
   1542     reloc_type = fixP->fx_r_type;
   1543 
   1544   /* We need the symbol name for the VTABLE entries */
   1545   if (   reloc_type == BFD_RELOC_VTABLE_INHERIT
   1546       || reloc_type == BFD_RELOC_VTABLE_ENTRY
   1547       || reloc_type == BFD_RELOC_FRV_GPREL12
   1548       || reloc_type == BFD_RELOC_FRV_GPRELU12)
   1549     return 0;
   1550 
   1551   return 1;
   1552 }
   1553 
   1554 /* Allow user to set flags bits.  */
   1555 void
   1556 frv_set_flags (int arg ATTRIBUTE_UNUSED)
   1557 {
   1558   flagword new_flags = get_absolute_expression ();
   1559   flagword new_mask = ~ (flagword)0;
   1560 
   1561   frv_user_set_flags_p = 1;
   1562   if (*input_line_pointer == ',')
   1563     {
   1564       ++input_line_pointer;
   1565       new_mask = get_absolute_expression ();
   1566     }
   1567 
   1568   frv_flags = (frv_flags & ~new_mask) | (new_flags & new_mask);
   1569   bfd_set_private_flags (stdoutput, frv_flags);
   1570 }
   1571 
   1572 /* Frv specific function to handle 4 byte initializations for pointers that are
   1573    considered 'safe' for use with pic support.  Until frv_frob_file{,_section}
   1574    is run, we encode it a BFD_RELOC_CTOR, and it is turned back into a normal
   1575    BFD_RELOC_32 at that time.  */
   1576 
   1577 void
   1578 frv_pic_ptr (int nbytes)
   1579 {
   1580   expressionS exp;
   1581   char *p;
   1582 
   1583   if (nbytes != 4)
   1584     abort ();
   1585 
   1586 #ifdef md_flush_pending_output
   1587   md_flush_pending_output ();
   1588 #endif
   1589 
   1590   if (is_it_end_of_statement ())
   1591     {
   1592       demand_empty_rest_of_line ();
   1593       return;
   1594     }
   1595 
   1596 #ifdef md_cons_align
   1597   md_cons_align (nbytes);
   1598 #endif
   1599 
   1600   do
   1601     {
   1602       bfd_reloc_code_real_type reloc_type = BFD_RELOC_CTOR;
   1603 
   1604       if (strncasecmp (input_line_pointer, "funcdesc(", 9) == 0)
   1605 	{
   1606 	  input_line_pointer += 9;
   1607 	  expression (&exp);
   1608 	  if (*input_line_pointer == ')')
   1609 	    input_line_pointer++;
   1610 	  else
   1611 	    as_bad (_("missing ')'"));
   1612 	  reloc_type = BFD_RELOC_FRV_FUNCDESC;
   1613 	}
   1614       else if (strncasecmp (input_line_pointer, "tlsmoff(", 8) == 0)
   1615 	{
   1616 	  input_line_pointer += 8;
   1617 	  expression (&exp);
   1618 	  if (*input_line_pointer == ')')
   1619 	    input_line_pointer++;
   1620 	  else
   1621 	    as_bad (_("missing ')'"));
   1622 	  reloc_type = BFD_RELOC_FRV_TLSMOFF;
   1623 	}
   1624       else
   1625 	expression (&exp);
   1626 
   1627       p = frag_more (4);
   1628       memset (p, 0, 4);
   1629       fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &exp, 0,
   1630 		   reloc_type);
   1631     }
   1632   while (*input_line_pointer++ == ',');
   1633 
   1634   input_line_pointer--;			/* Put terminator back into stream. */
   1635   demand_empty_rest_of_line ();
   1636 }
   1637 
   1638 
   1639 
   1641 #ifdef DEBUG
   1642 #define DPRINTF1(A)	fprintf (stderr, A)
   1643 #define DPRINTF2(A,B)	fprintf (stderr, A, B)
   1644 #define DPRINTF3(A,B,C)	fprintf (stderr, A, B, C)
   1645 
   1646 #else
   1647 #define DPRINTF1(A)
   1648 #define DPRINTF2(A,B)
   1649 #define DPRINTF3(A,B,C)
   1650 #endif
   1651 
   1652 /* Go through a the sections looking for relocations that are problematical for
   1653    pic.  If not pic, just note that this object can't be linked with pic.  If
   1654    it is pic, see if it needs to be marked so that it will be fixed up, or if
   1655    not possible, issue an error.  */
   1656 
   1657 static void
   1658 frv_frob_file_section (bfd *abfd, asection *sec, void *ptr ATTRIBUTE_UNUSED)
   1659 {
   1660   segment_info_type *seginfo = seg_info (sec);
   1661   fixS *fixp;
   1662   CGEN_CPU_DESC cd = gas_cgen_cpu_desc;
   1663   flagword flags = bfd_get_section_flags (abfd, sec);
   1664 
   1665   /* Skip relocations in known sections (.ctors, .dtors, and .gcc_except_table)
   1666      since we can fix those up by hand.  */
   1667   int known_section_p = (sec->name
   1668 			 && sec->name[0] == '.'
   1669 			 && ((sec->name[1] == 'c'
   1670 			      && strcmp (sec->name, ".ctor") == 0)
   1671 			     || (sec->name[1] == 'd'
   1672 				 && strcmp (sec->name, ".dtor") == 0)
   1673 			     || (sec->name[1] == 'g'
   1674 				 && strcmp (sec->name, ".gcc_except_table") == 0)));
   1675 
   1676   DPRINTF3 ("\nFrv section %s%s\n", sec->name, (known_section_p) ? ", known section" : "");
   1677   if ((flags & SEC_ALLOC) == 0)
   1678     {
   1679       DPRINTF1 ("\tSkipping non-loaded section\n");
   1680       return;
   1681     }
   1682 
   1683   for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next)
   1684     {
   1685       symbolS *s = fixp->fx_addsy;
   1686       bfd_reloc_code_real_type reloc;
   1687       int non_pic_p;
   1688       int opindex;
   1689       const CGEN_OPERAND *operand;
   1690       const CGEN_INSN *insn = fixp->fx_cgen.insn;
   1691 
   1692       if (fixp->fx_done)
   1693 	{
   1694 	  DPRINTF1 ("\tSkipping reloc that has already been done\n");
   1695 	  continue;
   1696 	}
   1697 
   1698       if (fixp->fx_pcrel)
   1699 	{
   1700 	  DPRINTF1 ("\tSkipping reloc that is PC relative\n");
   1701 	  continue;
   1702 	}
   1703 
   1704       if (! s)
   1705 	{
   1706 	  DPRINTF1 ("\tSkipping reloc without symbol\n");
   1707 	  continue;
   1708 	}
   1709 
   1710       if (fixp->fx_r_type < BFD_RELOC_UNUSED)
   1711 	{
   1712 	  opindex = -1;
   1713 	  reloc = fixp->fx_r_type;
   1714 	}
   1715       else
   1716 	{
   1717 	  opindex = (int) fixp->fx_r_type - (int) BFD_RELOC_UNUSED;
   1718 	  operand = cgen_operand_lookup_by_num (cd, opindex);
   1719 	  reloc = md_cgen_lookup_reloc (insn, operand, fixp);
   1720 	}
   1721 
   1722       DPRINTF3 ("\treloc %s\t%s", bfd_get_reloc_code_name (reloc), S_GET_NAME (s));
   1723 
   1724       non_pic_p = 0;
   1725       switch (reloc)
   1726 	{
   1727 	default:
   1728 	  break;
   1729 
   1730 	case BFD_RELOC_32:
   1731 	  /* Skip relocations in known sections (.ctors, .dtors, and
   1732 	     .gcc_except_table) since we can fix those up by hand.  Also
   1733 	     skip forward references to constants.  Also skip a difference
   1734 	     of two symbols, which still uses the BFD_RELOC_32 at this
   1735 	     point.  */
   1736 	  if (! known_section_p
   1737 	      && S_GET_SEGMENT (s) != absolute_section
   1738 	      && !fixp->fx_subsy
   1739 	      && (flags & (SEC_READONLY | SEC_CODE)) == 0)
   1740 	    {
   1741 	      non_pic_p = 1;
   1742 	    }
   1743 	  break;
   1744 
   1745 	  /* FIXME -- should determine if any of the GP relocation really uses
   1746 	     gr16 (which is not pic safe) or not.  Right now, assume if we
   1747 	     aren't being compiled with -mpic, the usage is non pic safe, but
   1748 	     is safe with -mpic.  */
   1749 	case BFD_RELOC_FRV_GPREL12:
   1750 	case BFD_RELOC_FRV_GPRELU12:
   1751 	case BFD_RELOC_FRV_GPREL32:
   1752 	case BFD_RELOC_FRV_GPRELHI:
   1753 	case BFD_RELOC_FRV_GPRELLO:
   1754 	  non_pic_p = ! frv_pic_p;
   1755 	  break;
   1756 
   1757 	case BFD_RELOC_FRV_LO16:
   1758 	case BFD_RELOC_FRV_HI16:
   1759 	  if (S_GET_SEGMENT (s) != absolute_section)
   1760 	    non_pic_p = 1;
   1761 	  break;
   1762 
   1763 	case BFD_RELOC_VTABLE_INHERIT:
   1764 	case BFD_RELOC_VTABLE_ENTRY:
   1765 	  non_pic_p = 1;
   1766 	  break;
   1767 
   1768 	  /* If this is a blessed BFD_RELOC_32, convert it back to the normal
   1769              relocation.  */
   1770 	case BFD_RELOC_CTOR:
   1771 	  fixp->fx_r_type = BFD_RELOC_32;
   1772 	  break;
   1773 	}
   1774 
   1775       if (non_pic_p)
   1776 	{
   1777 	  DPRINTF1 (" (Non-pic relocation)\n");
   1778 	  if (frv_pic_p)
   1779 	    as_warn_where (fixp->fx_file, fixp->fx_line,
   1780 			   _("Relocation %s is not safe for %s"),
   1781 			   bfd_get_reloc_code_name (reloc), frv_pic_flag);
   1782 
   1783 	  else if ((frv_flags & EF_FRV_NON_PIC_RELOCS) == 0)
   1784 	    {
   1785 	      frv_flags |= EF_FRV_NON_PIC_RELOCS;
   1786 	      bfd_set_private_flags (abfd, frv_flags);
   1787 	    }
   1788 	}
   1789 #ifdef DEBUG
   1790       else
   1791 	DPRINTF1 ("\n");
   1792 #endif
   1793     }
   1794 }
   1795 
   1796 /* After all of the symbols have been adjusted, go over the file looking
   1797    for any relocations that pic won't support.  */
   1798 
   1799 void
   1800 frv_frob_file (void)
   1801 {
   1802   bfd_map_over_sections (stdoutput, frv_frob_file_section, (void *) 0);
   1803 }
   1804 
   1805 void
   1806 frv_frob_label (symbolS *this_label)
   1807 {
   1808   struct vliw_insn_list *vliw_insn_list_entry;
   1809 
   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