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