xref: /netbsd-src/external/gpl3/binutils/dist/gas/config/tc-frv.c (revision 413d532bcc3f62d122e56d92e13ac64825a40baf)
1 /* tc-frv.c -- Assembler for the Fujitsu FRV.
2    Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
3    Free Software Foundation. Inc.
4 
5    This file is part of GAS, the GNU Assembler.
6 
7    GAS is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3, or (at your option)
10    any later version.
11 
12    GAS is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with GAS; see the file COPYING.  If not, write to
19    the Free Software Foundation, 51 Franklin Street - Fifth Floor,
20    Boston, MA 02110-1301, USA.  */
21 
22 #include "as.h"
23 #include "subsegs.h"
24 #include "symcat.h"
25 #include "opcodes/frv-desc.h"
26 #include "opcodes/frv-opc.h"
27 #include "cgen.h"
28 #include "libbfd.h"
29 #include "elf/common.h"
30 #include "elf/frv.h"
31 #include "dwarf2dbg.h"
32 
33 /* Structure to hold all of the different components describing
34    an individual instruction.  */
35 typedef struct
36 {
37   const CGEN_INSN *	insn;
38   const CGEN_INSN *	orig_insn;
39   CGEN_FIELDS		fields;
40 #if CGEN_INT_INSN_P
41   CGEN_INSN_INT         buffer [1];
42 #define INSN_VALUE(buf) (*(buf))
43 #else
44   unsigned char         buffer [CGEN_MAX_INSN_SIZE];
45 #define INSN_VALUE(buf) (buf)
46 #endif
47   char *		addr;
48   fragS *		frag;
49   int                   num_fixups;
50   fixS *                fixups [GAS_CGEN_MAX_FIXUPS];
51   int                   indices [MAX_OPERAND_INSTANCES];
52 }
53 frv_insn;
54 
55 enum vliw_insn_type
56 {
57   VLIW_GENERIC_TYPE,		/* Don't care about this insn.  */
58   VLIW_BRANCH_TYPE,		/* A Branch.  */
59   VLIW_LABEL_TYPE,		/* A Label.  */
60   VLIW_NOP_TYPE,		/* A NOP.  */
61   VLIW_BRANCH_HAS_NOPS		/* A Branch that requires NOPS.  */
62 };
63 
64 /* We're going to use these in the fr_subtype field to mark
65    whether to keep inserted nops.  */
66 
67 #define NOP_KEEP 1		/* Keep these NOPS.  */
68 #define NOP_DELETE 2		/* Delete these NOPS.  */
69 
70 #define DO_COUNT    TRUE
71 #define DONT_COUNT  FALSE
72 
73 /* A list of insns within a VLIW insn.  */
74 struct vliw_insn_list
75 {
76   /*  The type of this insn.  */
77   enum vliw_insn_type	type;
78 
79   /*  The corresponding gas insn information.  */
80   const CGEN_INSN	*insn;
81 
82   /*  For branches and labels, the symbol that is referenced.  */
83   symbolS		*sym;
84 
85   /*  For branches, the frag containing the single nop that was generated.  */
86   fragS			*snop_frag;
87 
88   /*  For branches, the frag containing the double nop that was generated.  */
89   fragS			*dnop_frag;
90 
91   /*  Pointer to raw data for this insn.  */
92   char			*address;
93 
94   /* Next insn in list.  */
95   struct vliw_insn_list *next;
96 };
97 
98 static struct vliw_insn_list single_nop_insn = {
99    VLIW_NOP_TYPE, NULL, NULL, NULL, NULL, NULL, NULL };
100 
101 static struct vliw_insn_list double_nop_insn = {
102    VLIW_NOP_TYPE, NULL, NULL, NULL, NULL, NULL, NULL };
103 
104 struct vliw_chain
105 {
106   int			num;
107   int			insn_count;
108   struct vliw_insn_list *insn_list;
109   struct vliw_chain     *next;
110 };
111 
112 static struct vliw_chain	*vliw_chain_top;
113 static struct vliw_chain	*current_vliw_chain;
114 static struct vliw_chain	*previous_vliw_chain;
115 static struct vliw_insn_list	*current_vliw_insn;
116 
117 const char comment_chars[]        = ";";
118 const char line_comment_chars[]   = "#";
119 const char line_separator_chars[] = "!";
120 const char EXP_CHARS[]            = "eE";
121 const char FLT_CHARS[]            = "dD";
122 
123 static FRV_VLIW vliw;
124 
125 /* Default machine */
126 
127 #ifdef  DEFAULT_CPU_FRV
128 #define DEFAULT_MACHINE bfd_mach_frv
129 #define DEFAULT_FLAGS	EF_FRV_CPU_GENERIC
130 
131 #else
132 #ifdef  DEFAULT_CPU_FR300
133 #define DEFAULT_MACHINE	bfd_mach_fr300
134 #define DEFAULT_FLAGS	EF_FRV_CPU_FR300
135 
136 #else
137 #ifdef	DEFAULT_CPU_SIMPLE
138 #define	DEFAULT_MACHINE bfd_mach_frvsimple
139 #define DEFAULT_FLAGS	EF_FRV_CPU_SIMPLE
140 
141 #else
142 #ifdef	DEFAULT_CPU_TOMCAT
143 #define	DEFAULT_MACHINE bfd_mach_frvtomcat
144 #define DEFAULT_FLAGS	EF_FRV_CPU_TOMCAT
145 
146 #else
147 #ifdef  DEFAULT_CPU_FR400
148 #define DEFAULT_MACHINE	bfd_mach_fr400
149 #define DEFAULT_FLAGS	EF_FRV_CPU_FR400
150 
151 #else
152 #ifdef  DEFAULT_CPU_FR550
153 #define DEFAULT_MACHINE	bfd_mach_fr550
154 #define DEFAULT_FLAGS	EF_FRV_CPU_FR550
155 
156 #else
157 #define DEFAULT_MACHINE	bfd_mach_fr500
158 #define DEFAULT_FLAGS	EF_FRV_CPU_FR500
159 #endif
160 #endif
161 #endif
162 #endif
163 #endif
164 #endif
165 
166 #ifdef TE_LINUX
167 # define DEFAULT_FDPIC	EF_FRV_FDPIC
168 #else
169 # define DEFAULT_FDPIC	0
170 #endif
171 
172 static unsigned long frv_mach = bfd_mach_frv;
173 static bfd_boolean fr400_audio;
174 
175 /* Flags to set in the elf header */
176 static flagword frv_flags = DEFAULT_FLAGS | DEFAULT_FDPIC;
177 
178 static int frv_user_set_flags_p = 0;
179 static int frv_pic_p = 0;
180 static const char *frv_pic_flag = DEFAULT_FDPIC ? "-mfdpic" : (const char *)0;
181 
182 /* Print tomcat-specific debugging info.  */
183 static int tomcat_debug = 0;
184 
185 /* Tomcat-specific NOP statistics.  */
186 static int tomcat_stats = 0;
187 static int tomcat_doubles = 0;
188 static int tomcat_singles = 0;
189 
190 /* Forward reference to static functions */
191 static void frv_set_flags (int);
192 static void frv_pic_ptr (int);
193 
194 /* The target specific pseudo-ops which we support.  */
195 const pseudo_typeS md_pseudo_table[] =
196 {
197   { "eflags",	frv_set_flags,		0 },
198   { "word",	cons,			4 },
199   { "picptr",	frv_pic_ptr,		4 },
200   { NULL, 	NULL,			0 }
201 };
202 
203 
204 #define FRV_SHORTOPTS "G:"
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
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 = (struct vliw_chain *) xmalloc (sizeof (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 = (struct vliw_insn_list *) xmalloc (sizeof (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 = (struct vliw_chain *) xmalloc (sizeof (struct vliw_chain));
683   struct vliw_chain *single_nop = (struct vliw_chain *) xmalloc (sizeof (struct vliw_chain));
684   struct vliw_chain *second_part = (struct vliw_chain *) xmalloc (sizeof (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 inbetween.  */
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 inbetween.  */
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_get_section_alignment (stdoutput, 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.  */
1241 
1242 /* FIXME: Build table by hand, get it working, then machine generate.  */
1243 const relax_typeS md_relax_table[] =
1244 {
1245   {1, 1, 0, 0},
1246   {511 - 2 - 2, -512 - 2 + 2, 0, 2 },
1247   {0x2000000 - 1 - 2, -0x2000000 - 2, 2, 0 },
1248   {0x2000000 - 1 - 2, -0x2000000 - 2, 4, 0 }
1249 };
1250 
1251 long
1252 frv_relax_frag (fragS *fragP ATTRIBUTE_UNUSED, long stretch ATTRIBUTE_UNUSED)
1253 {
1254   return 0;
1255 }
1256 
1257 /* Return an initial guess of the length by which a fragment must grow to
1258    hold a branch to reach its destination.
1259    Also updates fr_type/fr_subtype as necessary.
1260 
1261    Called just before doing relaxation.
1262    Any symbol that is now undefined will not become defined.
1263    The guess for fr_var is ACTUALLY the growth beyond fr_fix.
1264    Whatever we do to grow fr_fix or fr_var contributes to our returned value.
1265    Although it may not be explicit in the frag, pretend fr_var starts with a
1266    0 value.  */
1267 
1268 int
1269 md_estimate_size_before_relax (fragS *fragP, segT segment ATTRIBUTE_UNUSED)
1270 {
1271   switch (fragP->fr_subtype)
1272     {
1273     case NOP_KEEP:
1274       return fragP->fr_var;
1275 
1276     default:
1277     case NOP_DELETE:
1278       return 0;
1279     }
1280 }
1281 
1282 /* *fragP has been relaxed to its final size, and now needs to have
1283    the bytes inside it modified to conform to the new size.
1284 
1285    Called after relaxation is finished.
1286    fragP->fr_type == rs_machine_dependent.
1287    fragP->fr_subtype is the subtype of what the address relaxed to.  */
1288 
1289 void
1290 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
1291 		 segT sec ATTRIBUTE_UNUSED,
1292 		 fragS *fragP)
1293 {
1294   switch (fragP->fr_subtype)
1295     {
1296     default:
1297     case NOP_DELETE:
1298       return;
1299 
1300     case NOP_KEEP:
1301       fragP->fr_fix = fragP->fr_var;
1302       fragP->fr_var = 0;
1303       return;
1304     }
1305 }
1306 
1307 /* Functions concerning relocs.  */
1308 
1309 /* The location from which a PC relative jump should be calculated,
1310    given a PC relative reloc.  */
1311 
1312 long
1313 md_pcrel_from_section (fixS *fixP, segT sec)
1314 {
1315   if (TC_FORCE_RELOCATION (fixP)
1316       || (fixP->fx_addsy != (symbolS *) NULL
1317 	  && S_GET_SEGMENT (fixP->fx_addsy) != sec))
1318     {
1319       /* If we can't adjust this relocation, or if it references a
1320 	 local symbol in a different section (which
1321 	 TC_FORCE_RELOCATION can't check), let the linker figure it
1322 	 out.  */
1323       return 0;
1324     }
1325 
1326   return (fixP->fx_frag->fr_address + fixP->fx_where) & ~1;
1327 }
1328 
1329 /* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
1330    Returns BFD_RELOC_NONE if no reloc type can be found.
1331    *FIXP may be modified if desired.  */
1332 
1333 bfd_reloc_code_real_type
1334 md_cgen_lookup_reloc (const CGEN_INSN *insn ATTRIBUTE_UNUSED,
1335 		      const CGEN_OPERAND *operand,
1336 		      fixS *fixP)
1337 {
1338   switch (operand->type)
1339     {
1340     case FRV_OPERAND_LABEL16:
1341       fixP->fx_pcrel = TRUE;
1342       return BFD_RELOC_FRV_LABEL16;
1343 
1344     case FRV_OPERAND_LABEL24:
1345       fixP->fx_pcrel = TRUE;
1346 
1347       if (fixP->fx_cgen.opinfo != 0)
1348 	return fixP->fx_cgen.opinfo;
1349 
1350       return BFD_RELOC_FRV_LABEL24;
1351 
1352     case FRV_OPERAND_UHI16:
1353     case FRV_OPERAND_ULO16:
1354     case FRV_OPERAND_SLO16:
1355     case FRV_OPERAND_CALLANN:
1356     case FRV_OPERAND_LDANN:
1357     case FRV_OPERAND_LDDANN:
1358       /* The relocation type should be recorded in opinfo */
1359       if (fixP->fx_cgen.opinfo != 0)
1360         return fixP->fx_cgen.opinfo;
1361       break;
1362 
1363     case FRV_OPERAND_D12:
1364     case FRV_OPERAND_S12:
1365       if (fixP->fx_cgen.opinfo != 0)
1366 	return fixP->fx_cgen.opinfo;
1367 
1368       return BFD_RELOC_FRV_GPREL12;
1369 
1370     case FRV_OPERAND_U12:
1371       return BFD_RELOC_FRV_GPRELU12;
1372 
1373     default:
1374       break;
1375     }
1376   return BFD_RELOC_NONE;
1377 }
1378 
1379 
1380 /* See whether we need to force a relocation into the output file.
1381    This is used to force out switch and PC relative relocations when
1382    relaxing.  */
1383 
1384 int
1385 frv_force_relocation (fixS *fix)
1386 {
1387   switch (fix->fx_r_type < BFD_RELOC_UNUSED
1388 	  ? (int) fix->fx_r_type
1389 	  : fix->fx_cgen.opinfo)
1390     {
1391     case BFD_RELOC_FRV_GPREL12:
1392     case BFD_RELOC_FRV_GPRELU12:
1393     case BFD_RELOC_FRV_GPREL32:
1394     case BFD_RELOC_FRV_GPRELHI:
1395     case BFD_RELOC_FRV_GPRELLO:
1396     case BFD_RELOC_FRV_GOT12:
1397     case BFD_RELOC_FRV_GOTHI:
1398     case BFD_RELOC_FRV_GOTLO:
1399     case BFD_RELOC_FRV_FUNCDESC_VALUE:
1400     case BFD_RELOC_FRV_FUNCDESC_GOTOFF12:
1401     case BFD_RELOC_FRV_FUNCDESC_GOTOFFHI:
1402     case BFD_RELOC_FRV_FUNCDESC_GOTOFFLO:
1403     case BFD_RELOC_FRV_GOTOFF12:
1404     case BFD_RELOC_FRV_GOTOFFHI:
1405     case BFD_RELOC_FRV_GOTOFFLO:
1406     case BFD_RELOC_FRV_GETTLSOFF:
1407     case BFD_RELOC_FRV_TLSDESC_VALUE:
1408     case BFD_RELOC_FRV_GOTTLSDESC12:
1409     case BFD_RELOC_FRV_GOTTLSDESCHI:
1410     case BFD_RELOC_FRV_GOTTLSDESCLO:
1411     case BFD_RELOC_FRV_TLSMOFF12:
1412     case BFD_RELOC_FRV_TLSMOFFHI:
1413     case BFD_RELOC_FRV_TLSMOFFLO:
1414     case BFD_RELOC_FRV_GOTTLSOFF12:
1415     case BFD_RELOC_FRV_GOTTLSOFFHI:
1416     case BFD_RELOC_FRV_GOTTLSOFFLO:
1417     case BFD_RELOC_FRV_TLSOFF:
1418     case BFD_RELOC_FRV_TLSDESC_RELAX:
1419     case BFD_RELOC_FRV_GETTLSOFF_RELAX:
1420     case BFD_RELOC_FRV_TLSOFF_RELAX:
1421       return 1;
1422 
1423     default:
1424       break;
1425     }
1426 
1427   return generic_force_reloc (fix);
1428 }
1429 
1430 /* Apply a fixup that could be resolved within the assembler.  */
1431 
1432 void
1433 md_apply_fix (fixS *fixP, valueT *valP, segT seg)
1434 {
1435   if (fixP->fx_addsy == 0)
1436     switch (fixP->fx_cgen.opinfo)
1437       {
1438       case BFD_RELOC_FRV_HI16:
1439 	*valP >>= 16;
1440 	/* Fall through.  */
1441       case BFD_RELOC_FRV_LO16:
1442 	*valP &= 0xffff;
1443 	break;
1444 
1445 	/* We need relocations for these, even if their symbols reduce
1446 	   to constants.  */
1447       case BFD_RELOC_FRV_GPREL12:
1448       case BFD_RELOC_FRV_GPRELU12:
1449       case BFD_RELOC_FRV_GPREL32:
1450       case BFD_RELOC_FRV_GPRELHI:
1451       case BFD_RELOC_FRV_GPRELLO:
1452       case BFD_RELOC_FRV_GOT12:
1453       case BFD_RELOC_FRV_GOTHI:
1454       case BFD_RELOC_FRV_GOTLO:
1455       case BFD_RELOC_FRV_FUNCDESC_VALUE:
1456       case BFD_RELOC_FRV_FUNCDESC_GOTOFF12:
1457       case BFD_RELOC_FRV_FUNCDESC_GOTOFFHI:
1458       case BFD_RELOC_FRV_FUNCDESC_GOTOFFLO:
1459       case BFD_RELOC_FRV_GOTOFF12:
1460       case BFD_RELOC_FRV_GOTOFFHI:
1461       case BFD_RELOC_FRV_GOTOFFLO:
1462       case BFD_RELOC_FRV_GETTLSOFF:
1463       case BFD_RELOC_FRV_TLSDESC_VALUE:
1464       case BFD_RELOC_FRV_GOTTLSDESC12:
1465       case BFD_RELOC_FRV_GOTTLSDESCHI:
1466       case BFD_RELOC_FRV_GOTTLSDESCLO:
1467       case BFD_RELOC_FRV_TLSMOFF12:
1468       case BFD_RELOC_FRV_TLSMOFFHI:
1469       case BFD_RELOC_FRV_TLSMOFFLO:
1470       case BFD_RELOC_FRV_GOTTLSOFF12:
1471       case BFD_RELOC_FRV_GOTTLSOFFHI:
1472       case BFD_RELOC_FRV_GOTTLSOFFLO:
1473       case BFD_RELOC_FRV_TLSOFF:
1474       case BFD_RELOC_FRV_TLSDESC_RELAX:
1475       case BFD_RELOC_FRV_GETTLSOFF_RELAX:
1476       case BFD_RELOC_FRV_TLSOFF_RELAX:
1477 	fixP->fx_addsy = abs_section_sym;
1478 	break;
1479       }
1480   else
1481     switch (fixP->fx_cgen.opinfo)
1482       {
1483       case BFD_RELOC_FRV_GETTLSOFF:
1484       case BFD_RELOC_FRV_TLSDESC_VALUE:
1485       case BFD_RELOC_FRV_GOTTLSDESC12:
1486       case BFD_RELOC_FRV_GOTTLSDESCHI:
1487       case BFD_RELOC_FRV_GOTTLSDESCLO:
1488       case BFD_RELOC_FRV_TLSMOFF12:
1489       case BFD_RELOC_FRV_TLSMOFFHI:
1490       case BFD_RELOC_FRV_TLSMOFFLO:
1491       case BFD_RELOC_FRV_GOTTLSOFF12:
1492       case BFD_RELOC_FRV_GOTTLSOFFHI:
1493       case BFD_RELOC_FRV_GOTTLSOFFLO:
1494       case BFD_RELOC_FRV_TLSOFF:
1495       case BFD_RELOC_FRV_TLSDESC_RELAX:
1496       case BFD_RELOC_FRV_GETTLSOFF_RELAX:
1497       case BFD_RELOC_FRV_TLSOFF_RELAX:
1498 	/* Mark TLS symbols as such.  */
1499 	if (S_GET_SEGMENT (fixP->fx_addsy) != absolute_section)
1500 	  S_SET_THREAD_LOCAL (fixP->fx_addsy);
1501 	break;
1502       }
1503 
1504   gas_cgen_md_apply_fix (fixP, valP, seg);
1505   return;
1506 }
1507 
1508 
1509 /* Write a value out to the object file, using the appropriate endianness.  */
1510 
1511 void
1512 frv_md_number_to_chars (char *buf, valueT val, int n)
1513 {
1514   number_to_chars_bigendian (buf, val, n);
1515 }
1516 
1517 char *
1518 md_atof (int type, char *litP, int *sizeP)
1519 {
1520   return ieee_md_atof (type, litP, sizeP, TRUE);
1521 }
1522 
1523 bfd_boolean
1524 frv_fix_adjustable (fixS *fixP)
1525 {
1526   bfd_reloc_code_real_type reloc_type;
1527 
1528   if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
1529     {
1530       const CGEN_INSN *insn = NULL;
1531       int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
1532       const CGEN_OPERAND *operand = cgen_operand_lookup_by_num(gas_cgen_cpu_desc, opindex);
1533       reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
1534     }
1535   else
1536     reloc_type = fixP->fx_r_type;
1537 
1538   /* We need the symbol name for the VTABLE entries */
1539   if (   reloc_type == BFD_RELOC_VTABLE_INHERIT
1540       || reloc_type == BFD_RELOC_VTABLE_ENTRY
1541       || reloc_type == BFD_RELOC_FRV_GPREL12
1542       || reloc_type == BFD_RELOC_FRV_GPRELU12)
1543     return 0;
1544 
1545   return 1;
1546 }
1547 
1548 /* Allow user to set flags bits.  */
1549 void
1550 frv_set_flags (int arg ATTRIBUTE_UNUSED)
1551 {
1552   flagword new_flags = get_absolute_expression ();
1553   flagword new_mask = ~ (flagword)0;
1554 
1555   frv_user_set_flags_p = 1;
1556   if (*input_line_pointer == ',')
1557     {
1558       ++input_line_pointer;
1559       new_mask = get_absolute_expression ();
1560     }
1561 
1562   frv_flags = (frv_flags & ~new_mask) | (new_flags & new_mask);
1563   bfd_set_private_flags (stdoutput, frv_flags);
1564 }
1565 
1566 /* Frv specific function to handle 4 byte initializations for pointers that are
1567    considered 'safe' for use with pic support.  Until frv_frob_file{,_section}
1568    is run, we encode it a BFD_RELOC_CTOR, and it is turned back into a normal
1569    BFD_RELOC_32 at that time.  */
1570 
1571 void
1572 frv_pic_ptr (int nbytes)
1573 {
1574   expressionS exp;
1575   char *p;
1576 
1577   if (nbytes != 4)
1578     abort ();
1579 
1580 #ifdef md_flush_pending_output
1581   md_flush_pending_output ();
1582 #endif
1583 
1584   if (is_it_end_of_statement ())
1585     {
1586       demand_empty_rest_of_line ();
1587       return;
1588     }
1589 
1590 #ifdef md_cons_align
1591   md_cons_align (nbytes);
1592 #endif
1593 
1594   do
1595     {
1596       bfd_reloc_code_real_type reloc_type = BFD_RELOC_CTOR;
1597 
1598       if (strncasecmp (input_line_pointer, "funcdesc(", 9) == 0)
1599 	{
1600 	  input_line_pointer += 9;
1601 	  expression (&exp);
1602 	  if (*input_line_pointer == ')')
1603 	    input_line_pointer++;
1604 	  else
1605 	    as_bad (_("missing ')'"));
1606 	  reloc_type = BFD_RELOC_FRV_FUNCDESC;
1607 	}
1608       else if (strncasecmp (input_line_pointer, "tlsmoff(", 8) == 0)
1609 	{
1610 	  input_line_pointer += 8;
1611 	  expression (&exp);
1612 	  if (*input_line_pointer == ')')
1613 	    input_line_pointer++;
1614 	  else
1615 	    as_bad (_("missing ')'"));
1616 	  reloc_type = BFD_RELOC_FRV_TLSMOFF;
1617 	}
1618       else
1619 	expression (&exp);
1620 
1621       p = frag_more (4);
1622       memset (p, 0, 4);
1623       fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &exp, 0,
1624 		   reloc_type);
1625     }
1626   while (*input_line_pointer++ == ',');
1627 
1628   input_line_pointer--;			/* Put terminator back into stream. */
1629   demand_empty_rest_of_line ();
1630 }
1631 
1632 
1633 
1634 #ifdef DEBUG
1635 #define DPRINTF1(A)	fprintf (stderr, A)
1636 #define DPRINTF2(A,B)	fprintf (stderr, A, B)
1637 #define DPRINTF3(A,B,C)	fprintf (stderr, A, B, C)
1638 
1639 #else
1640 #define DPRINTF1(A)
1641 #define DPRINTF2(A,B)
1642 #define DPRINTF3(A,B,C)
1643 #endif
1644 
1645 /* Go through a the sections looking for relocations that are problematical for
1646    pic.  If not pic, just note that this object can't be linked with pic.  If
1647    it is pic, see if it needs to be marked so that it will be fixed up, or if
1648    not possible, issue an error.  */
1649 
1650 static void
1651 frv_frob_file_section (bfd *abfd, asection *sec, void *ptr ATTRIBUTE_UNUSED)
1652 {
1653   segment_info_type *seginfo = seg_info (sec);
1654   fixS *fixp;
1655   CGEN_CPU_DESC cd = gas_cgen_cpu_desc;
1656   flagword flags = bfd_get_section_flags (abfd, sec);
1657 
1658   /* Skip relocations in known sections (.ctors, .dtors, and .gcc_except_table)
1659      since we can fix those up by hand.  */
1660   int known_section_p = (sec->name
1661 			 && sec->name[0] == '.'
1662 			 && ((sec->name[1] == 'c'
1663 			      && strcmp (sec->name, ".ctor") == 0)
1664 			     || (sec->name[1] == 'd'
1665 				 && strcmp (sec->name, ".dtor") == 0)
1666 			     || (sec->name[1] == 'g'
1667 				 && strcmp (sec->name, ".gcc_except_table") == 0)));
1668 
1669   DPRINTF3 ("\nFrv section %s%s\n", sec->name, (known_section_p) ? ", known section" : "");
1670   if ((flags & SEC_ALLOC) == 0)
1671     {
1672       DPRINTF1 ("\tSkipping non-loaded section\n");
1673       return;
1674     }
1675 
1676   for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next)
1677     {
1678       symbolS *s = fixp->fx_addsy;
1679       bfd_reloc_code_real_type reloc;
1680       int non_pic_p;
1681       int opindex;
1682       const CGEN_OPERAND *operand;
1683       const CGEN_INSN *insn = fixp->fx_cgen.insn;
1684 
1685       if (fixp->fx_done)
1686 	{
1687 	  DPRINTF1 ("\tSkipping reloc that has already been done\n");
1688 	  continue;
1689 	}
1690 
1691       if (fixp->fx_pcrel)
1692 	{
1693 	  DPRINTF1 ("\tSkipping reloc that is PC relative\n");
1694 	  continue;
1695 	}
1696 
1697       if (! s)
1698 	{
1699 	  DPRINTF1 ("\tSkipping reloc without symbol\n");
1700 	  continue;
1701 	}
1702 
1703       if (fixp->fx_r_type < BFD_RELOC_UNUSED)
1704 	{
1705 	  opindex = -1;
1706 	  reloc = fixp->fx_r_type;
1707 	}
1708       else
1709 	{
1710 	  opindex = (int) fixp->fx_r_type - (int) BFD_RELOC_UNUSED;
1711 	  operand = cgen_operand_lookup_by_num (cd, opindex);
1712 	  reloc = md_cgen_lookup_reloc (insn, operand, fixp);
1713 	}
1714 
1715       DPRINTF3 ("\treloc %s\t%s", bfd_get_reloc_code_name (reloc), S_GET_NAME (s));
1716 
1717       non_pic_p = 0;
1718       switch (reloc)
1719 	{
1720 	default:
1721 	  break;
1722 
1723 	case BFD_RELOC_32:
1724 	  /* Skip relocations in known sections (.ctors, .dtors, and
1725 	     .gcc_except_table) since we can fix those up by hand.  Also
1726 	     skip forward references to constants.  Also skip a difference
1727 	     of two symbols, which still uses the BFD_RELOC_32 at this
1728 	     point.  */
1729 	  if (! known_section_p
1730 	      && S_GET_SEGMENT (s) != absolute_section
1731 	      && !fixp->fx_subsy
1732 	      && (flags & (SEC_READONLY | SEC_CODE)) == 0)
1733 	    {
1734 	      non_pic_p = 1;
1735 	    }
1736 	  break;
1737 
1738 	  /* FIXME -- should determine if any of the GP relocation really uses
1739 	     gr16 (which is not pic safe) or not.  Right now, assume if we
1740 	     aren't being compiled with -mpic, the usage is non pic safe, but
1741 	     is safe with -mpic.  */
1742 	case BFD_RELOC_FRV_GPREL12:
1743 	case BFD_RELOC_FRV_GPRELU12:
1744 	case BFD_RELOC_FRV_GPREL32:
1745 	case BFD_RELOC_FRV_GPRELHI:
1746 	case BFD_RELOC_FRV_GPRELLO:
1747 	  non_pic_p = ! frv_pic_p;
1748 	  break;
1749 
1750 	case BFD_RELOC_FRV_LO16:
1751 	case BFD_RELOC_FRV_HI16:
1752 	  if (S_GET_SEGMENT (s) != absolute_section)
1753 	    non_pic_p = 1;
1754 	  break;
1755 
1756 	case BFD_RELOC_VTABLE_INHERIT:
1757 	case BFD_RELOC_VTABLE_ENTRY:
1758 	  non_pic_p = 1;
1759 	  break;
1760 
1761 	  /* If this is a blessed BFD_RELOC_32, convert it back to the normal
1762              relocation.  */
1763 	case BFD_RELOC_CTOR:
1764 	  fixp->fx_r_type = BFD_RELOC_32;
1765 	  break;
1766 	}
1767 
1768       if (non_pic_p)
1769 	{
1770 	  DPRINTF1 (" (Non-pic relocation)\n");
1771 	  if (frv_pic_p)
1772 	    as_warn_where (fixp->fx_file, fixp->fx_line,
1773 			   _("Relocation %s is not safe for %s"),
1774 			   bfd_get_reloc_code_name (reloc), frv_pic_flag);
1775 
1776 	  else if ((frv_flags & EF_FRV_NON_PIC_RELOCS) == 0)
1777 	    {
1778 	      frv_flags |= EF_FRV_NON_PIC_RELOCS;
1779 	      bfd_set_private_flags (abfd, frv_flags);
1780 	    }
1781 	}
1782 #ifdef DEBUG
1783       else
1784 	DPRINTF1 ("\n");
1785 #endif
1786     }
1787 }
1788 
1789 /* After all of the symbols have been adjusted, go over the file looking
1790    for any relocations that pic won't support.  */
1791 
1792 void
1793 frv_frob_file (void)
1794 {
1795   bfd_map_over_sections (stdoutput, frv_frob_file_section, (void *) 0);
1796 }
1797 
1798 void
1799 frv_frob_label (symbolS *this_label)
1800 {
1801   struct vliw_insn_list *vliw_insn_list_entry;
1802 
1803   dwarf2_emit_label (this_label);
1804   if (frv_mach != bfd_mach_frvtomcat)
1805     return;
1806 
1807   if (now_seg != text_section)
1808     return;
1809 
1810   vliw_insn_list_entry = frv_insert_vliw_insn(DONT_COUNT);
1811   vliw_insn_list_entry->type = VLIW_LABEL_TYPE;
1812   vliw_insn_list_entry->sym  = this_label;
1813 }
1814 
1815 fixS *
1816 frv_cgen_record_fixup_exp (fragS *frag,
1817 			   int where,
1818 			   const CGEN_INSN *insn,
1819 			   int length,
1820 			   const CGEN_OPERAND *operand,
1821 			   int opinfo,
1822 			   expressionS *exp)
1823 {
1824   fixS * fixP = gas_cgen_record_fixup_exp (frag, where, insn, length,
1825                                            operand, opinfo, exp);
1826 
1827   if (frv_mach == bfd_mach_frvtomcat
1828       && current_vliw_insn
1829       && current_vliw_insn->type == VLIW_BRANCH_TYPE
1830       && exp != NULL)
1831     current_vliw_insn->sym = exp->X_add_symbol;
1832 
1833   return fixP;
1834 }
1835