* symbols.c (S_FORCE_RELOC): Add "strict" param.
[external/binutils.git] / gas / config / tc-frv.c
1 /* tc-frv.c -- Assembler for the Fujitsu FRV.
2    Copyright 2002, 2003 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, 59 Temple Place - Suite 330,
19    Boston, MA 02111-1307, USA.  */
20
21 #include <stdio.h>
22 #include "as.h"
23 #include "dwarf2dbg.h"
24 #include "subsegs.h"     
25 #include "symcat.h"
26 #include "opcodes/frv-desc.h"
27 #include "opcodes/frv-opc.h"
28 #include "cgen.h"
29 #include "libbfd.h"
30 #include "elf/common.h"
31 #include "elf/frv.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 #define DEFAULT_MACHINE bfd_mach_fr500
153 #define DEFAULT_FLAGS   EF_FRV_CPU_FR500
154 #endif
155 #endif
156 #endif
157 #endif
158 #endif
159
160 static unsigned long frv_mach = bfd_mach_frv;
161
162 /* Flags to set in the elf header */
163 static flagword frv_flags = DEFAULT_FLAGS;
164
165 static int frv_user_set_flags_p = 0;
166 static int frv_pic_p = 0;
167 static const char *frv_pic_flag = (const char *)0;
168
169 /* Print tomcat-specific debugging info.  */
170 static int tomcat_debug = 0;
171
172 /* Tomcat-specific NOP statistics.  */
173 static int tomcat_stats = 0;
174 static int tomcat_doubles = 0;
175 static int tomcat_singles = 0;
176
177 /* Forward reference to static functions */
178 static void frv_set_flags               PARAMS ((int));
179 static void frv_pic_ptr                 PARAMS ((int));
180 static void frv_frob_file_section       PARAMS ((bfd *, asection *, PTR));
181
182 /* The target specific pseudo-ops which we support.  */
183 const pseudo_typeS md_pseudo_table[] =
184 {
185   { "eflags",   frv_set_flags,          0 },
186   { "word",     cons,                   4 },
187   { "picptr",   frv_pic_ptr,            4 },
188   { "file",     (void (*) PARAMS ((int))) dwarf2_directive_file, 0 },
189   { "loc",      dwarf2_directive_loc,   0 },
190   { NULL,       NULL,                   0 }
191 };
192
193 \f
194 #define FRV_SHORTOPTS "G:"
195 const char * md_shortopts = FRV_SHORTOPTS;
196
197 #define OPTION_GPR_32           (OPTION_MD_BASE)
198 #define OPTION_GPR_64           (OPTION_MD_BASE + 1)
199 #define OPTION_FPR_32           (OPTION_MD_BASE + 2)
200 #define OPTION_FPR_64           (OPTION_MD_BASE + 3)
201 #define OPTION_SOFT_FLOAT       (OPTION_MD_BASE + 4)
202 #define OPTION_DWORD_YES        (OPTION_MD_BASE + 5)
203 #define OPTION_DWORD_NO         (OPTION_MD_BASE + 6)
204 #define OPTION_DOUBLE           (OPTION_MD_BASE + 7)
205 #define OPTION_NO_DOUBLE        (OPTION_MD_BASE + 8)
206 #define OPTION_MEDIA            (OPTION_MD_BASE + 9)
207 #define OPTION_NO_MEDIA         (OPTION_MD_BASE + 10)
208 #define OPTION_CPU              (OPTION_MD_BASE + 11)
209 #define OPTION_PIC              (OPTION_MD_BASE + 12)
210 #define OPTION_BIGPIC           (OPTION_MD_BASE + 13)
211 #define OPTION_LIBPIC           (OPTION_MD_BASE + 14)
212 #define OPTION_MULADD           (OPTION_MD_BASE + 15)
213 #define OPTION_NO_MULADD        (OPTION_MD_BASE + 16)
214 #define OPTION_TOMCAT_DEBUG     (OPTION_MD_BASE + 17)
215 #define OPTION_TOMCAT_STATS     (OPTION_MD_BASE + 18)
216 #define OPTION_PACK             (OPTION_MD_BASE + 19)
217 #define OPTION_NO_PACK          (OPTION_MD_BASE + 20)
218
219 struct option md_longopts[] =
220 {
221   { "mgpr-32",          no_argument,            NULL, OPTION_GPR_32        },
222   { "mgpr-64",          no_argument,            NULL, OPTION_GPR_64        },
223   { "mfpr-32",          no_argument,            NULL, OPTION_FPR_32        },
224   { "mfpr-64",          no_argument,            NULL, OPTION_FPR_64        },
225   { "mhard-float",      no_argument,            NULL, OPTION_FPR_64        },
226   { "msoft-float",      no_argument,            NULL, OPTION_SOFT_FLOAT    },
227   { "mdword",           no_argument,            NULL, OPTION_DWORD_YES     },
228   { "mno-dword",        no_argument,            NULL, OPTION_DWORD_NO      },
229   { "mdouble",          no_argument,            NULL, OPTION_DOUBLE        },
230   { "mno-double",       no_argument,            NULL, OPTION_NO_DOUBLE     },
231   { "mmedia",           no_argument,            NULL, OPTION_MEDIA         },
232   { "mno-media",        no_argument,            NULL, OPTION_NO_MEDIA      },
233   { "mcpu",             required_argument,      NULL, OPTION_CPU           },
234   { "mpic",             no_argument,            NULL, OPTION_PIC           },
235   { "mPIC",             no_argument,            NULL, OPTION_BIGPIC        },
236   { "mlibrary-pic",     no_argument,            NULL, OPTION_LIBPIC        },
237   { "mmuladd",          no_argument,            NULL, OPTION_MULADD        },
238   { "mno-muladd",       no_argument,            NULL, OPTION_NO_MULADD     },
239   { "mtomcat-debug",    no_argument,            NULL, OPTION_TOMCAT_DEBUG  },
240   { "mtomcat-stats",    no_argument,            NULL, OPTION_TOMCAT_STATS  },
241   { "mpack",            no_argument,            NULL, OPTION_PACK          },
242   { "mno-pack",         no_argument,            NULL, OPTION_NO_PACK       },
243   { NULL,               no_argument,            NULL, 0                 },
244 };
245
246 size_t md_longopts_size = sizeof (md_longopts);
247
248 /* What value to give to bfd_set_gp_size.  */
249 static int g_switch_value = 8;
250
251 int
252 md_parse_option (c, arg)
253      int    c;
254      char * arg;
255 {
256   switch (c)
257     {
258     default:
259       return 0;
260
261     case 'G':
262       g_switch_value = atoi (arg);
263       if (! g_switch_value)
264         frv_flags |= EF_FRV_G0;
265       break;
266
267     case OPTION_GPR_32:
268       frv_flags = (frv_flags & ~EF_FRV_GPR_MASK) | EF_FRV_GPR_32;
269       break;
270
271     case OPTION_GPR_64:
272       frv_flags = (frv_flags & ~EF_FRV_GPR_MASK) | EF_FRV_GPR_64;
273       break;
274
275     case OPTION_FPR_32:
276       frv_flags = (frv_flags & ~EF_FRV_FPR_MASK) | EF_FRV_FPR_32;
277       break;
278
279     case OPTION_FPR_64:
280       frv_flags = (frv_flags & ~EF_FRV_FPR_MASK) | EF_FRV_FPR_64;
281       break;
282
283     case OPTION_SOFT_FLOAT:
284       frv_flags = (frv_flags & ~EF_FRV_FPR_MASK) | EF_FRV_FPR_NONE;
285       break;
286
287     case OPTION_DWORD_YES:
288       frv_flags = (frv_flags & ~EF_FRV_DWORD_MASK) | EF_FRV_DWORD_YES;
289       break;
290
291     case OPTION_DWORD_NO:
292       frv_flags = (frv_flags & ~EF_FRV_DWORD_MASK) | EF_FRV_DWORD_NO;
293       break;
294
295     case OPTION_DOUBLE:
296       frv_flags |= EF_FRV_DOUBLE;
297       break;
298
299     case OPTION_NO_DOUBLE:
300       frv_flags &= ~EF_FRV_DOUBLE;
301       break;
302
303     case OPTION_MEDIA:
304       frv_flags |= EF_FRV_MEDIA;
305       break;
306
307     case OPTION_NO_MEDIA:
308       frv_flags &= ~EF_FRV_MEDIA;
309       break;
310
311     case OPTION_MULADD:
312       frv_flags |= EF_FRV_MULADD;
313       break;
314
315     case OPTION_NO_MULADD:
316       frv_flags &= ~EF_FRV_MULADD;
317       break;
318
319     case OPTION_PACK:
320       frv_flags &= ~EF_FRV_NOPACK;
321       break;
322
323     case OPTION_NO_PACK:
324       frv_flags |= EF_FRV_NOPACK;
325       break;
326
327     case OPTION_CPU:
328       {
329         char *p;
330         int cpu_flags = EF_FRV_CPU_GENERIC;
331
332         /* Identify the processor type */
333         p = arg;
334         if (strcmp (p, "frv") == 0)
335           {
336             cpu_flags = EF_FRV_CPU_GENERIC;
337             frv_mach = bfd_mach_frv;
338           }
339
340         else if (strcmp (p, "fr500") == 0)
341           {
342             cpu_flags = EF_FRV_CPU_FR500;
343             frv_mach = bfd_mach_fr500;
344           }
345
346         else if (strcmp (p, "fr400") == 0)
347           {
348             cpu_flags = EF_FRV_CPU_FR400;
349             frv_mach = bfd_mach_fr400;
350           }
351
352         else if (strcmp (p, "fr300") == 0)
353           {
354             cpu_flags = EF_FRV_CPU_FR300;
355             frv_mach = bfd_mach_fr300;
356           }
357
358         else if (strcmp (p, "simple") == 0)
359           {
360             cpu_flags = EF_FRV_CPU_SIMPLE;
361             frv_mach = bfd_mach_frvsimple;
362             frv_flags |= EF_FRV_NOPACK;
363           }
364
365         else if (strcmp (p, "tomcat") == 0)
366           {
367             cpu_flags = EF_FRV_CPU_TOMCAT;
368             frv_mach = bfd_mach_frvtomcat;
369           }
370
371         else
372           {
373             as_fatal ("Unknown cpu -mcpu=%s", arg);
374             return 0;
375           }
376
377         frv_flags = (frv_flags & ~EF_FRV_CPU_MASK) | cpu_flags;
378       }
379       break;
380
381     case OPTION_PIC:
382       frv_flags |= EF_FRV_PIC;
383       frv_pic_p = 1;
384       frv_pic_flag = "-fpic";
385       break;
386
387     case OPTION_BIGPIC:
388       frv_flags |= EF_FRV_BIGPIC;
389       frv_pic_p = 1;
390       frv_pic_flag = "-fPIC";
391       break;
392
393     case OPTION_LIBPIC:
394       frv_flags |= (EF_FRV_LIBPIC | EF_FRV_G0);
395       frv_pic_p = 1;
396       frv_pic_flag = "-mlibrary-pic";
397       g_switch_value = 0;
398       break;
399
400     case OPTION_TOMCAT_DEBUG:
401       tomcat_debug = 1;
402       break;
403
404     case OPTION_TOMCAT_STATS:
405       tomcat_stats = 1;
406       break;
407     }
408
409   return 1;
410 }
411
412 void
413 md_show_usage (stream)
414   FILE * stream;
415 {
416   fprintf (stream, _("FRV specific command line options:\n"));
417   fprintf (stream, _("-G n         Data >= n bytes is in small data area\n"));
418   fprintf (stream, _("-mgpr-32     Note 32 gprs are used\n"));
419   fprintf (stream, _("-mgpr-64     Note 64 gprs are used\n"));
420   fprintf (stream, _("-mfpr-32     Note 32 fprs are used\n"));
421   fprintf (stream, _("-mfpr-64     Note 64 fprs are used\n"));
422   fprintf (stream, _("-msoft-float Note software fp is used\n"));
423   fprintf (stream, _("-mdword      Note stack is aligned to a 8 byte boundary\n"));
424   fprintf (stream, _("-mno-dword   Note stack is aligned to a 4 byte boundary\n"));
425   fprintf (stream, _("-mdouble     Note fp double insns are used\n"));
426   fprintf (stream, _("-mmedia      Note media insns are used\n"));
427   fprintf (stream, _("-mmuladd     Note multiply add/subtract insns are used\n"));
428   fprintf (stream, _("-mpack       Note instructions are packed\n"));
429   fprintf (stream, _("-mno-pack    Do not allow instructions to be packed\n"));
430   fprintf (stream, _("-mpic        Note small position independent code\n"));
431   fprintf (stream, _("-mPIC        Note large position independent code\n"));
432   fprintf (stream, _("-mlibrary-pic Compile library for large position indepedent code\n"));
433   fprintf (stream, _("-mcpu={fr500|fr400|fr300|frv|simple|tomcat}\n"));
434   fprintf (stream, _("             Record the cpu type\n"));
435   fprintf (stream, _("-mtomcat-stats Print out stats for tomcat workarounds\n"));
436   fprintf (stream, _("-mtomcat-debug Debug tomcat workarounds\n"));
437
438
439 \f
440 void
441 md_begin ()
442 {
443   /* Initialize the `cgen' interface.  */
444   
445   /* Set the machine number and endian.  */
446   gas_cgen_cpu_desc = frv_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, 0,
447                                          CGEN_CPU_OPEN_ENDIAN,
448                                          CGEN_ENDIAN_BIG,
449                                          CGEN_CPU_OPEN_END);
450   frv_cgen_init_asm (gas_cgen_cpu_desc);
451
452   /* This is a callback from cgen to gas to parse operands.  */
453   cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
454
455   /* Set the ELF flags if desired. */
456   if (frv_flags)
457     bfd_set_private_flags (stdoutput, frv_flags);
458
459   /* Set the machine type */
460   bfd_default_set_arch_mach (stdoutput, bfd_arch_frv, frv_mach);
461
462   /* Set up gp size so we can put local common items in .sbss */
463   bfd_set_gp_size (stdoutput, g_switch_value);
464
465   frv_vliw_reset (& vliw, frv_mach, frv_flags);
466 }
467
468 int chain_num = 0;
469
470 struct vliw_insn_list *frv_insert_vliw_insn PARAMS ((bfd_boolean));
471
472 struct vliw_insn_list *
473 frv_insert_vliw_insn (count)
474       bfd_boolean count;
475 {
476   struct vliw_insn_list *vliw_insn_list_entry;
477   struct vliw_chain     *vliw_chain_entry;
478
479   if (current_vliw_chain == NULL)
480     {
481       vliw_chain_entry = (struct vliw_chain *) xmalloc (sizeof (struct vliw_chain));
482       vliw_chain_entry->insn_count = 0;
483       vliw_chain_entry->insn_list  = NULL;
484       vliw_chain_entry->next       = NULL;
485       vliw_chain_entry->num        = chain_num++;
486
487       if (!vliw_chain_top)
488         vliw_chain_top = vliw_chain_entry;
489       current_vliw_chain = vliw_chain_entry;
490       if (previous_vliw_chain)
491         previous_vliw_chain->next = vliw_chain_entry;
492     }
493
494   vliw_insn_list_entry = (struct vliw_insn_list *) xmalloc (sizeof (struct vliw_insn_list));
495   vliw_insn_list_entry->type      = VLIW_GENERIC_TYPE;
496   vliw_insn_list_entry->insn      = NULL;
497   vliw_insn_list_entry->sym       = NULL;
498   vliw_insn_list_entry->snop_frag = NULL;
499   vliw_insn_list_entry->dnop_frag = NULL;
500   vliw_insn_list_entry->next      = NULL;
501
502   if (count)
503     current_vliw_chain->insn_count++;
504
505   if (current_vliw_insn)
506     current_vliw_insn->next = vliw_insn_list_entry;
507   current_vliw_insn = vliw_insn_list_entry;
508
509   if (!current_vliw_chain->insn_list)
510     current_vliw_chain->insn_list = current_vliw_insn;
511
512   return vliw_insn_list_entry;
513 }
514
515   /* Identify the following cases:
516  
517      1) A VLIW insn that contains both a branch and the branch destination.
518         This requires the insertion of two vliw instructions before the
519         branch.  The first consists of two nops.  The second consists of
520         a single nop.
521  
522      2) A single instruction VLIW insn which is the destination of a branch
523         that is in the next VLIW insn.  This requires the insertion of a vliw
524         insn containing two nops before the branch.
525  
526      3) A double instruction VLIW insn which contains the destination of a
527         branch that is in the next VLIW insn.  This requires the insertion of
528         a VLIW insn containing a single nop before the branch.
529  
530      4) A single instruction VLIW insn which contains branch destination (x),
531         followed by a single instruction VLIW insn which does not contain
532         the branch to (x), followed by a VLIW insn which does contain the branch
533         to (x).  This requires the insertion of a VLIW insn containing a single
534         nop before the VLIW instruction containing the branch.
535  
536   */
537 #define FRV_IS_NOP(insn) (insn.buffer[0] == FRV_NOP_PACK || insn.buffer[0] == FRV_NOP_NOPACK)
538 #define FRV_NOP_PACK   0x00880000  /* ori.p  gr0,0,gr0 */
539 #define FRV_NOP_NOPACK 0x80880000  /* ori    gr0,0,gr0 */
540
541 /* Check a vliw insn for an insn of type containing the sym passed in label_sym.  */
542
543 static struct vliw_insn_list *frv_find_in_vliw
544   PARAMS ((enum vliw_insn_type, struct vliw_chain *, symbolS *));
545
546 static struct vliw_insn_list *
547 frv_find_in_vliw (vliw_insn_type, this_chain, label_sym)
548     enum vliw_insn_type vliw_insn_type;
549     struct vliw_chain *this_chain;
550     symbolS *label_sym;
551 {
552
553   struct vliw_insn_list *the_insn;
554
555   if (!this_chain)
556     return NULL;
557
558   for (the_insn = this_chain->insn_list; the_insn; the_insn = the_insn->next)
559     {
560       if (the_insn->type == vliw_insn_type
561           && the_insn->sym == label_sym)
562         return the_insn;
563     }
564
565   return NULL;
566 }
567
568 enum vliw_nop_type
569 {
570   /* A Vliw insn containing a single nop insn.  */
571   VLIW_SINGLE_NOP,
572   
573   /* A Vliw insn containing two nop insns.  */
574   VLIW_DOUBLE_NOP,
575
576   /* Two vliw insns.  The first containing two nop insns.  
577      The second contain a single nop insn.  */
578   VLIW_DOUBLE_THEN_SINGLE_NOP
579 };
580
581 static void frv_debug_tomcat PARAMS ((struct vliw_chain *));
582
583 static void
584 frv_debug_tomcat (start_chain)
585    struct vliw_chain *start_chain;
586 {
587    struct vliw_chain *this_chain;
588    struct vliw_insn_list *this_insn;
589    int i = 1;
590
591   for (this_chain = start_chain; this_chain; this_chain = this_chain->next, i++)
592     {
593       fprintf (stderr, "\nVliw Insn #%d, #insns: %d\n", i, this_chain->insn_count);
594
595       for (this_insn = this_chain->insn_list; this_insn; this_insn = this_insn->next)
596         {
597           if (this_insn->type == VLIW_LABEL_TYPE)
598             fprintf (stderr, "Label Value: %d\n", (int) this_insn->sym);
599           else if (this_insn->type == VLIW_BRANCH_TYPE)
600             fprintf (stderr, "%s to %d\n", this_insn->insn->base->name, (int) this_insn->sym);
601           else if (this_insn->type == VLIW_BRANCH_HAS_NOPS)
602             fprintf (stderr, "nop'd %s to %d\n", this_insn->insn->base->name, (int) this_insn->sym);
603           else if (this_insn->type == VLIW_NOP_TYPE)
604             fprintf (stderr, "Nop\n");
605           else
606             fprintf (stderr, "  %s\n", this_insn->insn->base->name);
607         }
608    }
609 }
610
611 static void frv_adjust_vliw_count PARAMS ((struct vliw_chain *));
612
613 static void
614 frv_adjust_vliw_count (this_chain)
615     struct vliw_chain *this_chain;
616 {
617   struct vliw_insn_list *this_insn;
618
619   this_chain->insn_count = 0;
620
621   for (this_insn = this_chain->insn_list;
622        this_insn;
623        this_insn = this_insn->next)
624     {
625       if (this_insn->type != VLIW_LABEL_TYPE)
626         this_chain->insn_count++;
627     }
628
629 }
630
631 /* Insert the desired nop combination in the vliw chain before insert_before_insn.
632    Rechain the vliw insn.  */
633
634 static struct vliw_chain *frv_tomcat_shuffle
635   PARAMS ((enum vliw_nop_type, struct vliw_chain *, struct vliw_insn_list *));
636
637 static struct vliw_chain *
638 frv_tomcat_shuffle (this_nop_type, vliw_to_split, insert_before_insn)
639    enum vliw_nop_type    this_nop_type;
640    struct vliw_chain     *vliw_to_split;
641    struct vliw_insn_list *insert_before_insn;
642 {
643
644   bfd_boolean pack_prev = FALSE;
645   struct vliw_chain *return_me = NULL;
646   struct vliw_insn_list *prev_insn = NULL;
647   struct vliw_insn_list *curr_insn = vliw_to_split->insn_list;
648
649   struct vliw_chain *double_nop = (struct vliw_chain *) xmalloc (sizeof (struct vliw_chain));
650   struct vliw_chain *single_nop = (struct vliw_chain *) xmalloc (sizeof (struct vliw_chain));
651   struct vliw_chain *second_part = (struct vliw_chain *) xmalloc (sizeof (struct vliw_chain));
652   struct vliw_chain *curr_vliw = vliw_chain_top;
653   struct vliw_chain *prev_vliw = NULL;
654
655   while (curr_insn && curr_insn != insert_before_insn)
656     {
657       /* We can't set the packing bit on a label.  If we have the case
658          label 1:
659          label 2:
660          label 3:
661            branch that needs nops
662         Then don't set pack bit later.  */
663
664       if (curr_insn->type != VLIW_LABEL_TYPE)
665         pack_prev = TRUE;
666       prev_insn = curr_insn;
667       curr_insn = curr_insn->next;
668     } 
669
670   while (curr_vliw && curr_vliw != vliw_to_split)
671     {
672       prev_vliw = curr_vliw;
673       curr_vliw = curr_vliw->next;
674     }
675
676   switch (this_nop_type)
677     {
678     case VLIW_SINGLE_NOP:
679       if (!prev_insn)
680         {
681         /* Branch is first,  Insert the NOP prior to this vliw insn.  */
682         if (prev_vliw)
683           prev_vliw->next = single_nop;
684         else
685           vliw_chain_top = single_nop;
686         single_nop->next = vliw_to_split;
687         vliw_to_split->insn_list->type = VLIW_BRANCH_HAS_NOPS;
688         return_me = vliw_to_split;
689         }
690       else
691         {
692           /* Set the packing bit on the previous insn.  */
693           if (pack_prev)
694             {
695               unsigned char *buffer = prev_insn->address;
696               buffer[0] |= 0x80;
697             }
698           /* The branch is in the middle.  Split this vliw insn into first
699              and second parts.  Insert the NOP inbetween.  */
700
701           second_part->insn_list = insert_before_insn;
702           second_part->insn_list->type = VLIW_BRANCH_HAS_NOPS;
703           second_part->next      = vliw_to_split->next;
704           frv_adjust_vliw_count (second_part);
705
706           single_nop->next       = second_part;
707  
708           vliw_to_split->next    = single_nop;
709           prev_insn->next        = NULL;
710  
711           return_me = second_part;
712           frv_adjust_vliw_count (vliw_to_split);
713         }
714       break;
715
716     case VLIW_DOUBLE_NOP:
717       if (!prev_insn)
718         {
719         /* Branch is first,  Insert the NOP prior to this vliw insn.  */
720         if (prev_vliw)
721           prev_vliw->next = double_nop;
722         else
723           vliw_chain_top = double_nop;
724
725         double_nop->next = vliw_to_split;
726         return_me = vliw_to_split;
727         vliw_to_split->insn_list->type = VLIW_BRANCH_HAS_NOPS;
728         }
729       else
730         {
731           /* Set the packing bit on the previous insn.  */
732           if (pack_prev)
733             {
734               unsigned char *buffer = prev_insn->address;
735               buffer[0] |= 0x80;
736             }
737
738         /* The branch is in the middle.  Split this vliw insn into first
739            and second parts.  Insert the NOP inbetween.  */
740           second_part->insn_list = insert_before_insn;
741           second_part->insn_list->type = VLIW_BRANCH_HAS_NOPS;
742           second_part->next      = vliw_to_split->next;
743           frv_adjust_vliw_count (second_part);
744  
745           double_nop->next       = second_part;
746  
747           vliw_to_split->next    = single_nop;
748           prev_insn->next        = NULL;
749           frv_adjust_vliw_count (vliw_to_split);
750  
751           return_me = second_part;
752         }
753       break;
754
755     case VLIW_DOUBLE_THEN_SINGLE_NOP:
756       double_nop->next = single_nop;
757       double_nop->insn_count = 2;
758       double_nop->insn_list = &double_nop_insn;
759       single_nop->insn_count = 1;
760       single_nop->insn_list = &single_nop_insn;
761
762       if (!prev_insn)
763         {
764           /* The branch is the first insn in this vliw.  Don't split the vliw.  Insert
765              the nops prior to this vliw.  */
766           if (prev_vliw)
767             prev_vliw->next = double_nop;
768           else
769             vliw_chain_top = double_nop;
770  
771           single_nop->next = vliw_to_split;
772           return_me = vliw_to_split;
773           vliw_to_split->insn_list->type = VLIW_BRANCH_HAS_NOPS;
774         }
775       else
776         {
777           /* Set the packing bit on the previous insn.  */
778           if (pack_prev)
779             {
780               unsigned char *buffer = prev_insn->address;
781               buffer[0] |= 0x80;
782             }
783
784           /* The branch is in the middle of this vliw insn.  Split into first and
785              second parts.  Insert the nop vliws in between.  */  
786           second_part->insn_list = insert_before_insn;
787           second_part->insn_list->type = VLIW_BRANCH_HAS_NOPS;
788           second_part->next      = vliw_to_split->next;
789           frv_adjust_vliw_count (second_part);
790
791           single_nop->next       = second_part;
792
793           vliw_to_split->next    = double_nop;
794           prev_insn->next        = NULL;
795           frv_adjust_vliw_count (vliw_to_split);
796
797           return_me = second_part;
798         }
799       break;
800     }
801
802   return return_me;
803 }
804
805 static void frv_tomcat_analyze_vliw_chains PARAMS ((void));
806
807 static void
808 frv_tomcat_analyze_vliw_chains ()
809 {
810   struct vliw_chain *vliw1 = NULL;
811   struct vliw_chain *vliw2 = NULL;
812   struct vliw_chain *vliw3 = NULL;
813
814   struct vliw_insn_list *this_insn = NULL;
815   struct vliw_insn_list *temp_insn = NULL;
816
817   /* We potentially need to look at three VLIW insns to determine if the
818      workaround is required.  Set them up.  Ignore existing nops during analysis. */
819
820 #define FRV_SET_VLIW_WINDOW(VLIW1, VLIW2, VLIW3) \
821   if (VLIW1 && VLIW1->next)                      \
822     VLIW2 = VLIW1->next;                         \
823   else                                           \
824     VLIW2 = NULL;                                \
825   if (VLIW2 && VLIW2->next)                      \
826     VLIW3 = VLIW2->next;                         \
827   else                                           \
828     VLIW3 = NULL
829
830   vliw1 = vliw_chain_top;
831
832 workaround_top:
833
834   FRV_SET_VLIW_WINDOW (vliw1, vliw2, vliw3);
835
836   if (!vliw1)
837     return;
838
839   if (vliw1->insn_count == 1)
840     {
841       /* check vliw1 for a label. */
842       if (vliw1->insn_list->type == VLIW_LABEL_TYPE)
843         {
844           temp_insn = frv_find_in_vliw (VLIW_BRANCH_TYPE, vliw2, vliw1->insn_list->sym);
845           if (temp_insn)
846             {
847               vliw1 = frv_tomcat_shuffle (VLIW_DOUBLE_NOP, vliw2, vliw1->insn_list);
848               temp_insn->dnop_frag->fr_subtype = NOP_KEEP;
849               vliw1 = vliw1->next;
850               if (tomcat_stats)
851                 tomcat_doubles++;
852               goto workaround_top;
853             }
854           else if (vliw2 
855                    && vliw2->insn_count == 1
856                    && (temp_insn = frv_find_in_vliw (VLIW_BRANCH_TYPE, vliw3, vliw1->insn_list->sym)) != NULL)
857             {
858               temp_insn->snop_frag->fr_subtype = NOP_KEEP;
859               vliw1 = frv_tomcat_shuffle (VLIW_SINGLE_NOP, vliw3, vliw3->insn_list);
860               if (tomcat_stats)
861                 tomcat_singles++;
862               goto workaround_top;
863             }
864         }
865     }
866
867   if (vliw1->insn_count == 2)
868     {
869       struct vliw_insn_list *this_insn;
870  
871       /* check vliw1 for a label. */
872       for (this_insn = vliw1->insn_list; this_insn; this_insn = this_insn->next)
873         {
874           if (this_insn->type == VLIW_LABEL_TYPE)
875             {
876               if ((temp_insn = frv_find_in_vliw (VLIW_BRANCH_TYPE, vliw2, this_insn->sym)) != NULL)
877                 {
878                   temp_insn->snop_frag->fr_subtype = NOP_KEEP;
879                   vliw1 = frv_tomcat_shuffle (VLIW_SINGLE_NOP, vliw2, this_insn);
880                   if (tomcat_stats)
881                     tomcat_singles++;
882                 }
883               else
884                 vliw1 = vliw1->next;
885               goto workaround_top;
886             }
887         }
888     }
889   /* Examine each insn in this VLIW.  Look for the workaround criteria.  */
890   for (this_insn = vliw1->insn_list; this_insn; this_insn = this_insn->next)
891     {
892       /* Don't look at labels or nops.  */
893       while (this_insn
894              && (this_insn->type == VLIW_LABEL_TYPE
895                  || this_insn->type == VLIW_NOP_TYPE
896                  || this_insn->type == VLIW_BRANCH_HAS_NOPS))
897         this_insn = this_insn->next;
898
899       if (!this_insn)
900         {
901           vliw1 = vliw2;
902           goto workaround_top;
903         }
904
905       if (frv_is_branch_insn (this_insn->insn))
906         {
907           if ((temp_insn = frv_find_in_vliw (VLIW_LABEL_TYPE, vliw1, this_insn->sym)) != NULL)
908             {
909               /* Insert [nop/nop] [nop] before branch.  */
910               this_insn->snop_frag->fr_subtype = NOP_KEEP;
911               this_insn->dnop_frag->fr_subtype = NOP_KEEP;
912               vliw1 = frv_tomcat_shuffle (VLIW_DOUBLE_THEN_SINGLE_NOP, vliw1, this_insn);
913               goto workaround_top;
914             }
915         }
916
917
918     }
919   /* This vliw insn checks out okay.  Take a look at the next one.  */
920   vliw1 = vliw1->next;
921   goto workaround_top;
922 }
923
924 void
925 frv_tomcat_workaround ()
926 {
927   if (frv_mach != bfd_mach_frvtomcat)
928     return;
929
930   if (tomcat_debug)
931     frv_debug_tomcat (vliw_chain_top);
932
933   frv_tomcat_analyze_vliw_chains ();
934
935   if (tomcat_stats)
936     {
937       fprintf (stderr, "Inserted %d Single Nops\n", tomcat_singles);
938       fprintf (stderr, "Inserted %d Double Nops\n", tomcat_doubles);
939     }
940 }
941
942 void
943 md_assemble (str)
944      char * str;
945 {
946   frv_insn insn;
947   char *errmsg;
948   int packing_constraint;
949   finished_insnS  finished_insn;
950   fragS *double_nop_frag = NULL;
951   fragS *single_nop_frag = NULL;
952   struct vliw_insn_list *vliw_insn_list_entry = NULL;
953
954   /* Initialize GAS's cgen interface for a new instruction.  */
955   gas_cgen_init_parse ();
956
957   insn.insn = frv_cgen_assemble_insn
958     (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, &errmsg);
959   
960   if (!insn.insn)
961     {
962       as_bad (errmsg);
963       return;
964     }
965   
966   /* If the cpu is tomcat, then we need to insert nops to workaround
967      hardware limitations.  We need to keep track of each vliw unit
968      and examine the length of the unit and the individual insns
969      within the unit to determine the number and location of the
970      required nops.  */
971   if (frv_mach == bfd_mach_frvtomcat)
972     {
973       /* If we've just finished a VLIW insn OR this is a branch,
974          then start up a new frag.  Fill it with nops.  We will get rid
975          of those that are not required after we've seen all of the 
976          instructions but before we start resolving fixups.  */
977       if ( !FRV_IS_NOP (insn)
978           && (frv_is_branch_insn (insn.insn) || insn.fields.f_pack))
979         {
980           char *buffer;
981
982           frag_wane (frag_now);
983           frag_new (0);
984           double_nop_frag = frag_now;
985           buffer = frag_var (rs_machine_dependent, 8, 8, NOP_DELETE, NULL, 0, 0);
986           md_number_to_chars (buffer, FRV_NOP_PACK, 4);
987           md_number_to_chars (buffer+4, FRV_NOP_NOPACK, 4);
988
989           frag_wane (frag_now);
990           frag_new (0);
991           single_nop_frag = frag_now;
992           buffer = frag_var (rs_machine_dependent, 4, 4, NOP_DELETE, NULL, 0, 0);
993           md_number_to_chars (buffer, FRV_NOP_NOPACK, 4);
994         }
995
996       vliw_insn_list_entry = frv_insert_vliw_insn (DO_COUNT);
997       vliw_insn_list_entry->insn   = insn.insn;
998       if (frv_is_branch_insn (insn.insn))
999         vliw_insn_list_entry->type = VLIW_BRANCH_TYPE;
1000
1001       if ( !FRV_IS_NOP (insn)
1002           && (frv_is_branch_insn (insn.insn) || insn.fields.f_pack))
1003         {
1004           vliw_insn_list_entry->snop_frag = single_nop_frag;
1005           vliw_insn_list_entry->dnop_frag = double_nop_frag;
1006         }
1007     }
1008
1009   /* Make sure that this insn does not violate the VLIW packing constraints.  */
1010   /* -mno-pack disallows any packing whatsoever.  */
1011   if (frv_flags & EF_FRV_NOPACK)
1012     {
1013       if (! insn.fields.f_pack)
1014         {
1015           as_bad (_("VLIW packing used for -mno-pack"));
1016           return;
1017         }
1018     }
1019   /* -mcpu=FRV is an idealized FR-V implementation that supports all of the
1020      instructions, don't do vliw checking.  */
1021   else if (frv_mach != bfd_mach_frv)
1022     {
1023       packing_constraint = frv_vliw_add_insn (& vliw, insn.insn);
1024       if (insn.fields.f_pack)
1025         frv_vliw_reset (& vliw, frv_mach, frv_flags);
1026       if (packing_constraint)
1027         {
1028           as_bad (_("VLIW packing constraint violation"));
1029           return;
1030         }
1031     }
1032
1033   /* Doesn't really matter what we pass for RELAX_P here.  */
1034   gas_cgen_finish_insn (insn.insn, insn.buffer,
1035                         CGEN_FIELDS_BITSIZE (& insn.fields), 1, &finished_insn);
1036
1037
1038   /* If the cpu is tomcat, then we need to insert nops to workaround
1039      hardware limitations.  We need to keep track of each vliw unit
1040      and examine the length of the unit and the individual insns
1041      within the unit to determine the number and location of the
1042      required nops.  */
1043   if (frv_mach == bfd_mach_frvtomcat)
1044     {
1045       if (vliw_insn_list_entry)
1046         vliw_insn_list_entry->address = finished_insn.addr;
1047       else
1048         abort();
1049
1050       if (insn.fields.f_pack)
1051         {
1052           /* We've completed a VLIW insn.  */
1053           previous_vliw_chain = current_vliw_chain;
1054           current_vliw_chain = NULL;
1055           current_vliw_insn  = NULL;
1056         } 
1057     }
1058 }
1059
1060 /* The syntax in the manual says constants begin with '#'.
1061    We just ignore it.  */
1062
1063 void 
1064 md_operand (expressionP)
1065      expressionS * expressionP;
1066 {
1067   if (* input_line_pointer == '#')
1068     {
1069       input_line_pointer ++;
1070       expression (expressionP);
1071     }
1072 }
1073
1074 valueT
1075 md_section_align (segment, size)
1076      segT   segment;
1077      valueT size;
1078 {
1079   int align = bfd_get_section_alignment (stdoutput, segment);
1080   return ((size + (1 << align) - 1) & (-1 << align));
1081 }
1082
1083 symbolS *
1084 md_undefined_symbol (name)
1085   char * name ATTRIBUTE_UNUSED;
1086 {
1087   return 0;
1088 }
1089 \f
1090 /* Interface to relax_segment.  */
1091
1092 /* FIXME: Build table by hand, get it working, then machine generate.  */
1093 const relax_typeS md_relax_table[] =
1094 {
1095   {1, 1, 0, 0},
1096   {511 - 2 - 2, -512 - 2 + 2, 0, 2 },
1097   {0x2000000 - 1 - 2, -0x2000000 - 2, 2, 0 },
1098   {0x2000000 - 1 - 2, -0x2000000 - 2, 4, 0 }
1099 };
1100
1101 long
1102 frv_relax_frag (fragP, stretch)
1103      fragS   *fragP ATTRIBUTE_UNUSED;
1104      long    stretch ATTRIBUTE_UNUSED;
1105 {
1106   return 0;
1107 }
1108
1109 /* Return an initial guess of the length by which a fragment must grow to
1110    hold a branch to reach its destination.
1111    Also updates fr_type/fr_subtype as necessary.
1112
1113    Called just before doing relaxation.
1114    Any symbol that is now undefined will not become defined.
1115    The guess for fr_var is ACTUALLY the growth beyond fr_fix.
1116    Whatever we do to grow fr_fix or fr_var contributes to our returned value.
1117    Although it may not be explicit in the frag, pretend fr_var starts with a
1118    0 value.  */
1119
1120 int
1121 md_estimate_size_before_relax (fragP, segment)
1122      fragS * fragP;
1123      segT    segment ATTRIBUTE_UNUSED;
1124 {
1125   switch (fragP->fr_subtype)
1126     {
1127     case NOP_KEEP:
1128       return fragP->fr_var;
1129
1130     default:
1131     case NOP_DELETE:
1132       return 0;
1133     }     
1134
1135
1136 /* *fragP has been relaxed to its final size, and now needs to have
1137    the bytes inside it modified to conform to the new size.
1138
1139    Called after relaxation is finished.
1140    fragP->fr_type == rs_machine_dependent.
1141    fragP->fr_subtype is the subtype of what the address relaxed to.  */
1142
1143 void
1144 md_convert_frag (abfd, sec, fragP)
1145   bfd *   abfd ATTRIBUTE_UNUSED;
1146   segT    sec ATTRIBUTE_UNUSED;
1147   fragS * fragP;
1148 {
1149   switch (fragP->fr_subtype)
1150     {
1151     default:
1152     case NOP_DELETE:
1153       return;
1154
1155     case NOP_KEEP:
1156       fragP->fr_fix = fragP->fr_var;
1157       fragP->fr_var = 0;
1158       return;   
1159     }
1160 }
1161 \f
1162 /* Functions concerning relocs.  */
1163
1164 /* The location from which a PC relative jump should be calculated,
1165    given a PC relative reloc.  */
1166
1167 long
1168 md_pcrel_from_section (fixP, sec)
1169      fixS * fixP;
1170      segT   sec;
1171 {
1172   if (fixP->fx_addsy != (symbolS *) NULL
1173       && (! S_IS_DEFINED (fixP->fx_addsy)
1174           || S_GET_SEGMENT (fixP->fx_addsy) != sec))
1175     {
1176       /* The symbol is undefined (or is defined but not in this section).
1177          Let the linker figure it out.  */
1178       return 0;
1179     }
1180
1181   return (fixP->fx_frag->fr_address + fixP->fx_where) & ~1;
1182 }
1183
1184 /* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
1185    Returns BFD_RELOC_NONE if no reloc type can be found.
1186    *FIXP may be modified if desired.  */
1187
1188 bfd_reloc_code_real_type
1189 md_cgen_lookup_reloc (insn, operand, fixP)
1190      const CGEN_INSN *    insn ATTRIBUTE_UNUSED;
1191      const CGEN_OPERAND * operand;
1192      fixS *               fixP;
1193 {
1194   switch (operand->type)
1195     {
1196     case FRV_OPERAND_LABEL16:
1197       fixP->fx_pcrel = TRUE;
1198       return BFD_RELOC_FRV_LABEL16;
1199
1200     case FRV_OPERAND_LABEL24:
1201       fixP->fx_pcrel = TRUE;
1202       return BFD_RELOC_FRV_LABEL24;
1203
1204     case FRV_OPERAND_UHI16:
1205     case FRV_OPERAND_ULO16:
1206     case FRV_OPERAND_SLO16:
1207
1208       /* The relocation type should be recorded in opinfo */
1209       if (fixP->fx_cgen.opinfo != 0)
1210         return fixP->fx_cgen.opinfo;
1211       break;
1212
1213     case FRV_OPERAND_D12:
1214     case FRV_OPERAND_S12:
1215       return BFD_RELOC_FRV_GPREL12;
1216
1217     case FRV_OPERAND_U12:
1218       return BFD_RELOC_FRV_GPRELU12;
1219
1220     default: 
1221       break;
1222     }
1223   return BFD_RELOC_NONE;
1224 }
1225
1226
1227 /* See whether we need to force a relocation into the output file.
1228    This is used to force out switch and PC relative relocations when
1229    relaxing.  */
1230
1231 int
1232 frv_force_relocation (fix)
1233      fixS * fix;
1234 {
1235   if (fix->fx_r_type == BFD_RELOC_FRV_GPREL12
1236       || fix->fx_r_type == BFD_RELOC_FRV_GPRELU12)
1237     return 1;
1238
1239   return generic_force_reloc (fix);
1240 }
1241 \f
1242 /* Write a value out to the object file, using the appropriate endianness.  */
1243
1244 void
1245 frv_md_number_to_chars (buf, val, n)
1246      char * buf;
1247      valueT val;
1248      int    n;
1249 {
1250   number_to_chars_bigendian (buf, val, n);
1251 }
1252
1253 /* Turn a string in input_line_pointer into a floating point constant of type
1254    type, and store the appropriate bytes in *litP.  The number of LITTLENUMS
1255    emitted is stored in *sizeP .  An error message is returned, or NULL on OK.
1256 */
1257
1258 /* Equal to MAX_PRECISION in atof-ieee.c */
1259 #define MAX_LITTLENUMS 6
1260
1261 char *
1262 md_atof (type, litP, sizeP)
1263      char   type;
1264      char * litP;
1265      int *  sizeP;
1266 {
1267   int              i;
1268   int              prec;
1269   LITTLENUM_TYPE   words [MAX_LITTLENUMS];
1270   char *           t;
1271
1272   switch (type)
1273     {
1274     case 'f':
1275     case 'F':
1276     case 's':
1277     case 'S':
1278       prec = 2;
1279       break;
1280
1281     case 'd':
1282     case 'D':
1283     case 'r':
1284     case 'R':
1285       prec = 4;
1286       break;
1287
1288    /* FIXME: Some targets allow other format chars for bigger sizes here.  */
1289
1290     default:
1291       * sizeP = 0;
1292       return _("Bad call to md_atof()");
1293     }
1294
1295   t = atof_ieee (input_line_pointer, type, words);
1296   if (t)
1297     input_line_pointer = t;
1298   * sizeP = prec * sizeof (LITTLENUM_TYPE);
1299
1300   for (i = 0; i < prec; i++)
1301     {
1302       md_number_to_chars (litP, (valueT) words[i],
1303                           sizeof (LITTLENUM_TYPE));
1304       litP += sizeof (LITTLENUM_TYPE);
1305     }
1306      
1307   return 0;
1308 }
1309
1310 bfd_boolean
1311 frv_fix_adjustable (fixP)
1312    fixS * fixP;
1313 {
1314   bfd_reloc_code_real_type reloc_type;
1315
1316   if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
1317     {
1318       const CGEN_INSN *insn = NULL;
1319       int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
1320       const CGEN_OPERAND *operand = cgen_operand_lookup_by_num(gas_cgen_cpu_desc, opindex);
1321       reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
1322     }
1323   else
1324     reloc_type = fixP->fx_r_type;
1325
1326   /* We need the symbol name for the VTABLE entries */
1327   if (   reloc_type == BFD_RELOC_VTABLE_INHERIT
1328       || reloc_type == BFD_RELOC_VTABLE_ENTRY
1329       || reloc_type == BFD_RELOC_FRV_GPREL12
1330       || reloc_type == BFD_RELOC_FRV_GPRELU12)
1331     return 0;
1332
1333   return 1;
1334 }
1335
1336 /* Allow user to set flags bits.  */
1337 void
1338 frv_set_flags (arg)
1339      int arg ATTRIBUTE_UNUSED;
1340 {
1341   flagword new_flags = get_absolute_expression ();
1342   flagword new_mask = ~ (flagword)0;
1343
1344   frv_user_set_flags_p = 1;
1345   if (*input_line_pointer == ',')
1346     {
1347       ++input_line_pointer;
1348       new_mask = get_absolute_expression ();
1349     }
1350
1351   frv_flags = (frv_flags & ~new_mask) | (new_flags & new_mask);
1352   bfd_set_private_flags (stdoutput, frv_flags);
1353 }
1354
1355 /* Frv specific function to handle 4 byte initializations for pointers that are
1356    considered 'safe' for use with pic support.  Until frv_frob_file{,_section}
1357    is run, we encode it a BFD_RELOC_CTOR, and it is turned back into a normal
1358    BFD_RELOC_32 at that time.  */
1359
1360 void
1361 frv_pic_ptr (nbytes)
1362      int nbytes;
1363 {
1364   expressionS exp;
1365   char *p;
1366
1367   if (nbytes != 4)
1368     abort ();
1369
1370 #ifdef md_flush_pending_output
1371   md_flush_pending_output ();
1372 #endif
1373
1374   if (is_it_end_of_statement ())
1375     {
1376       demand_empty_rest_of_line ();
1377       return;
1378     }
1379
1380 #ifdef md_cons_align
1381   md_cons_align (nbytes);
1382 #endif
1383
1384   do
1385     {
1386       expression (&exp);
1387
1388       p = frag_more (4);
1389       memset (p, 0, 4);
1390       fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &exp, 0,
1391                    BFD_RELOC_CTOR);
1392     }
1393   while (*input_line_pointer++ == ',');
1394
1395   input_line_pointer--;                 /* Put terminator back into stream. */
1396   demand_empty_rest_of_line ();
1397 }
1398
1399 \f
1400
1401 #ifdef DEBUG
1402 #define DPRINTF1(A)     fprintf (stderr, A)
1403 #define DPRINTF2(A,B)   fprintf (stderr, A, B)
1404 #define DPRINTF3(A,B,C) fprintf (stderr, A, B, C)
1405
1406 #else
1407 #define DPRINTF1(A)
1408 #define DPRINTF2(A,B)
1409 #define DPRINTF3(A,B,C)
1410 #endif
1411
1412 /* Go through a the sections looking for relocations that are problematical for
1413    pic.  If not pic, just note that this object can't be linked with pic.  If
1414    it is pic, see if it needs to be marked so that it will be fixed up, or if
1415    not possible, issue an error.  */
1416
1417 static void
1418 frv_frob_file_section (abfd, sec, ptr)
1419      bfd *abfd;
1420      asection *sec;
1421      PTR ptr ATTRIBUTE_UNUSED;
1422 {
1423   segment_info_type *seginfo = seg_info (sec);
1424   fixS *fixp;
1425   CGEN_CPU_DESC cd = gas_cgen_cpu_desc;
1426   flagword flags = bfd_get_section_flags (abfd, sec);
1427
1428   /* Skip relocations in known sections (.ctors, .dtors, and .gcc_except_table)
1429      since we can fix those up by hand.  */
1430   int known_section_p = (sec->name
1431                          && sec->name[0] == '.'
1432                          && ((sec->name[1] == 'c'
1433                               && strcmp (sec->name, ".ctor") == 0)
1434                              || (sec->name[1] == 'd'
1435                                  && strcmp (sec->name, ".dtor") == 0)
1436                              || (sec->name[1] == 'g'
1437                                  && strcmp (sec->name, ".gcc_except_table") == 0)));
1438
1439   DPRINTF3 ("\nFrv section %s%s\n", sec->name, (known_section_p) ? ", known section" : "");
1440   if ((flags & SEC_ALLOC) == 0)
1441     {
1442       DPRINTF1 ("\tSkipping non-loaded section\n");
1443       return;
1444     }
1445
1446   for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next)
1447     {
1448       symbolS *s = fixp->fx_addsy;
1449       bfd_reloc_code_real_type reloc;
1450       int non_pic_p;
1451       int opindex;
1452       const CGEN_OPERAND *operand;
1453       const CGEN_INSN *insn = fixp->fx_cgen.insn;
1454
1455       if (fixp->fx_done)
1456         {
1457           DPRINTF1 ("\tSkipping reloc that has already been done\n");
1458           continue;
1459         }
1460
1461       if (fixp->fx_pcrel)
1462         {
1463           DPRINTF1 ("\tSkipping reloc that is PC relative\n");
1464           continue;
1465         }
1466
1467       if (! s)
1468         {
1469           DPRINTF1 ("\tSkipping reloc without symbol\n");
1470           continue;
1471         }
1472
1473       if (fixp->fx_r_type < BFD_RELOC_UNUSED)
1474         {
1475           opindex = -1;
1476           reloc = fixp->fx_r_type;
1477         }
1478       else
1479         {
1480           opindex = (int) fixp->fx_r_type - (int) BFD_RELOC_UNUSED;
1481           operand = cgen_operand_lookup_by_num (cd, opindex);
1482           reloc = md_cgen_lookup_reloc (insn, operand, fixp);
1483         }
1484
1485       DPRINTF3 ("\treloc %s\t%s", bfd_get_reloc_code_name (reloc), S_GET_NAME (s));
1486
1487       non_pic_p = 0;
1488       switch (reloc)
1489         {
1490         default:
1491           break;
1492
1493         case BFD_RELOC_32:
1494           /* Skip relocations in known sections (.ctors, .dtors, and
1495              .gcc_except_table) since we can fix those up by hand.  Also
1496              skip forward references to constants.  Also skip a difference
1497              of two symbols, which still uses the BFD_RELOC_32 at this
1498              point.  */
1499           if (! known_section_p
1500               && S_GET_SEGMENT (s) != absolute_section
1501               && !fixp->fx_subsy
1502               && (flags & (SEC_READONLY | SEC_CODE)) == 0)
1503             {
1504               non_pic_p = 1;
1505             }
1506           break;
1507
1508           /* FIXME -- should determine if any of the GP relocation really uses
1509              gr16 (which is not pic safe) or not.  Right now, assume if we
1510              aren't being compiled with -mpic, the usage is non pic safe, but
1511              is safe with -mpic.  */
1512         case BFD_RELOC_FRV_GPREL12:
1513         case BFD_RELOC_FRV_GPRELU12:
1514         case BFD_RELOC_FRV_GPREL32:
1515         case BFD_RELOC_FRV_GPRELHI:
1516         case BFD_RELOC_FRV_GPRELLO:
1517           non_pic_p = ! frv_pic_p;
1518           break;
1519
1520         case BFD_RELOC_FRV_LO16:
1521         case BFD_RELOC_FRV_HI16:
1522           if (S_GET_SEGMENT (s) != absolute_section)
1523             non_pic_p = 1;
1524           break;
1525
1526         case BFD_RELOC_VTABLE_INHERIT:
1527         case BFD_RELOC_VTABLE_ENTRY:
1528           non_pic_p = 1;
1529           break;
1530
1531           /* If this is a blessed BFD_RELOC_32, convert it back to the normal
1532              relocation.  */
1533         case BFD_RELOC_CTOR:
1534           fixp->fx_r_type = BFD_RELOC_32;
1535           break;
1536         }
1537
1538       if (non_pic_p)
1539         {
1540           DPRINTF1 (" (Non-pic relocation)\n");
1541           if (frv_pic_p)
1542             as_warn_where (fixp->fx_file, fixp->fx_line,
1543                            _("Relocation %s is not safe for %s"),
1544                            bfd_get_reloc_code_name (reloc), frv_pic_flag);
1545
1546           else if ((frv_flags & EF_FRV_NON_PIC_RELOCS) == 0)
1547             {
1548               frv_flags |= EF_FRV_NON_PIC_RELOCS;
1549               bfd_set_private_flags (abfd, frv_flags);
1550             }
1551         }
1552 #ifdef DEBUG
1553       else
1554         DPRINTF1 ("\n");
1555 #endif
1556     }
1557 }
1558
1559 /* After all of the symbols have been adjusted, go over the file looking
1560    for any relocations that pic won't support.  */
1561
1562 void
1563 frv_frob_file ()
1564 {
1565   bfd_map_over_sections (stdoutput, frv_frob_file_section, (PTR)0);
1566 }
1567
1568 void
1569 frv_frob_label (this_label)
1570     symbolS *this_label;
1571 {
1572   struct vliw_insn_list *vliw_insn_list_entry;
1573
1574   if (frv_mach != bfd_mach_frvtomcat)
1575     return;
1576
1577   if (now_seg != text_section)
1578     return;
1579
1580   vliw_insn_list_entry = frv_insert_vliw_insn(DONT_COUNT);
1581   vliw_insn_list_entry->type = VLIW_LABEL_TYPE;
1582   vliw_insn_list_entry->sym  = this_label; 
1583 }
1584
1585 fixS *
1586 frv_cgen_record_fixup_exp (frag, where, insn, length, operand, opinfo, exp)
1587      fragS *              frag;
1588      int                  where;
1589      const CGEN_INSN *    insn;
1590      int                  length;
1591      const CGEN_OPERAND * operand;
1592      int                  opinfo;
1593      expressionS *        exp;
1594 {
1595   fixS * fixP = gas_cgen_record_fixup_exp (frag, where, insn, length,
1596                                            operand, opinfo, exp);
1597
1598   if (frv_mach == bfd_mach_frvtomcat
1599       && current_vliw_insn
1600       && current_vliw_insn->type == VLIW_BRANCH_TYPE
1601       && exp != NULL)
1602     current_vliw_insn->sym = exp->X_add_symbol;
1603     
1604   return fixP;
1605 }