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