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