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