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