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