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