1 /* tc-frv.c -- Assembler for the Fujitsu FRV.
2 Copyright 2002, 2003 Free Software Foundation.
4 This file is part of GAS, the GNU Assembler.
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)
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.
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. */
25 #include "opcodes/frv-desc.h"
26 #include "opcodes/frv-opc.h"
29 #include "elf/common.h"
32 /* Structure to hold all of the different components describing
33 an individual instruction. */
36 const CGEN_INSN
* insn
;
37 const CGEN_INSN
* orig_insn
;
40 CGEN_INSN_INT buffer
[1];
41 #define INSN_VALUE(buf) (*(buf))
43 unsigned char buffer
[CGEN_MAX_INSN_SIZE
];
44 #define INSN_VALUE(buf) (buf)
49 fixS
* fixups
[GAS_CGEN_MAX_FIXUPS
];
50 int indices
[MAX_OPERAND_INSTANCES
];
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. */
63 /* We're going to use these in the fr_subtype field to mark
64 whether to keep inserted nops. */
66 #define NOP_KEEP 1 /* Keep these NOPS. */
67 #define NOP_DELETE 2 /* Delete these NOPS. */
70 #define DONT_COUNT FALSE
72 /* A list of insns within a VLIW insn. */
75 /* The type of this insn. */
76 enum vliw_insn_type type
;
78 /* The corresponding gas insn information. */
79 const CGEN_INSN
*insn
;
81 /* For branches and labels, the symbol that is referenced. */
84 /* For branches, the frag containing the single nop that was generated. */
87 /* For branches, the frag containing the double nop that was generated. */
90 /* Pointer to raw data for this insn. */
93 /* Next insn in list. */
94 struct vliw_insn_list
*next
;
97 static struct vliw_insn_list single_nop_insn
= {
98 VLIW_NOP_TYPE
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
100 static struct vliw_insn_list double_nop_insn
= {
101 VLIW_NOP_TYPE
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
107 struct vliw_insn_list
*insn_list
;
108 struct vliw_chain
*next
;
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
;
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";
122 static FRV_VLIW vliw
;
124 /* Default machine */
126 #ifdef DEFAULT_CPU_FRV
127 #define DEFAULT_MACHINE bfd_mach_frv
128 #define DEFAULT_FLAGS EF_FRV_CPU_GENERIC
131 #ifdef DEFAULT_CPU_FR300
132 #define DEFAULT_MACHINE bfd_mach_fr300
133 #define DEFAULT_FLAGS EF_FRV_CPU_FR300
136 #ifdef DEFAULT_CPU_SIMPLE
137 #define DEFAULT_MACHINE bfd_mach_frvsimple
138 #define DEFAULT_FLAGS EF_FRV_CPU_SIMPLE
141 #ifdef DEFAULT_CPU_TOMCAT
142 #define DEFAULT_MACHINE bfd_mach_frvtomcat
143 #define DEFAULT_FLAGS EF_FRV_CPU_TOMCAT
146 #ifdef DEFAULT_CPU_FR400
147 #define DEFAULT_MACHINE bfd_mach_fr400
148 #define DEFAULT_FLAGS EF_FRV_CPU_FR400
151 #ifdef DEFAULT_CPU_FR550
152 #define DEFAULT_MACHINE bfd_mach_fr550
153 #define DEFAULT_FLAGS EF_FRV_CPU_FR550
156 #define DEFAULT_MACHINE bfd_mach_fr500
157 #define DEFAULT_FLAGS EF_FRV_CPU_FR500
165 static unsigned long frv_mach
= bfd_mach_frv
;
167 /* Flags to set in the elf header */
168 static flagword frv_flags
= DEFAULT_FLAGS
;
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;
174 /* Print tomcat-specific debugging info. */
175 static int tomcat_debug
= 0;
177 /* Tomcat-specific NOP statistics. */
178 static int tomcat_stats
= 0;
179 static int tomcat_doubles
= 0;
180 static int tomcat_singles
= 0;
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
));
187 /* The target specific pseudo-ops which we support. */
188 const pseudo_typeS md_pseudo_table
[] =
190 { "eflags", frv_set_flags
, 0 },
192 { "picptr", frv_pic_ptr
, 4 },
197 #define FRV_SHORTOPTS "G:"
198 const char * md_shortopts
= FRV_SHORTOPTS
;
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)
222 struct option md_longopts
[] =
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 },
249 size_t md_longopts_size
= sizeof (md_longopts
);
251 /* What value to give to bfd_set_gp_size. */
252 static int g_switch_value
= 8;
255 md_parse_option (c
, arg
)
265 g_switch_value
= atoi (arg
);
266 if (! g_switch_value
)
267 frv_flags
|= EF_FRV_G0
;
271 frv_flags
= (frv_flags
& ~EF_FRV_GPR_MASK
) | EF_FRV_GPR_32
;
275 frv_flags
= (frv_flags
& ~EF_FRV_GPR_MASK
) | EF_FRV_GPR_64
;
279 frv_flags
= (frv_flags
& ~EF_FRV_FPR_MASK
) | EF_FRV_FPR_32
;
283 frv_flags
= (frv_flags
& ~EF_FRV_FPR_MASK
) | EF_FRV_FPR_64
;
286 case OPTION_SOFT_FLOAT
:
287 frv_flags
= (frv_flags
& ~EF_FRV_FPR_MASK
) | EF_FRV_FPR_NONE
;
290 case OPTION_DWORD_YES
:
291 frv_flags
= (frv_flags
& ~EF_FRV_DWORD_MASK
) | EF_FRV_DWORD_YES
;
294 case OPTION_DWORD_NO
:
295 frv_flags
= (frv_flags
& ~EF_FRV_DWORD_MASK
) | EF_FRV_DWORD_NO
;
299 frv_flags
|= EF_FRV_DOUBLE
;
302 case OPTION_NO_DOUBLE
:
303 frv_flags
&= ~EF_FRV_DOUBLE
;
307 frv_flags
|= EF_FRV_MEDIA
;
310 case OPTION_NO_MEDIA
:
311 frv_flags
&= ~EF_FRV_MEDIA
;
315 frv_flags
|= EF_FRV_MULADD
;
318 case OPTION_NO_MULADD
:
319 frv_flags
&= ~EF_FRV_MULADD
;
323 frv_flags
&= ~EF_FRV_NOPACK
;
327 frv_flags
|= EF_FRV_NOPACK
;
333 int cpu_flags
= EF_FRV_CPU_GENERIC
;
335 /* Identify the processor type */
337 if (strcmp (p
, "frv") == 0)
339 cpu_flags
= EF_FRV_CPU_GENERIC
;
340 frv_mach
= bfd_mach_frv
;
343 else if (strcmp (p
, "fr500") == 0)
345 cpu_flags
= EF_FRV_CPU_FR500
;
346 frv_mach
= bfd_mach_fr500
;
349 else if (strcmp (p
, "fr550") == 0)
351 cpu_flags
= EF_FRV_CPU_FR550
;
352 frv_mach
= bfd_mach_fr550
;
355 else if (strcmp (p
, "fr400") == 0)
357 cpu_flags
= EF_FRV_CPU_FR400
;
358 frv_mach
= bfd_mach_fr400
;
361 else if (strcmp (p
, "fr300") == 0)
363 cpu_flags
= EF_FRV_CPU_FR300
;
364 frv_mach
= bfd_mach_fr300
;
367 else if (strcmp (p
, "simple") == 0)
369 cpu_flags
= EF_FRV_CPU_SIMPLE
;
370 frv_mach
= bfd_mach_frvsimple
;
371 frv_flags
|= EF_FRV_NOPACK
;
374 else if (strcmp (p
, "tomcat") == 0)
376 cpu_flags
= EF_FRV_CPU_TOMCAT
;
377 frv_mach
= bfd_mach_frvtomcat
;
382 as_fatal ("Unknown cpu -mcpu=%s", arg
);
386 frv_flags
= (frv_flags
& ~EF_FRV_CPU_MASK
) | cpu_flags
;
391 frv_flags
|= EF_FRV_PIC
;
393 frv_pic_flag
= "-fpic";
397 frv_flags
|= EF_FRV_BIGPIC
;
399 frv_pic_flag
= "-fPIC";
403 frv_flags
|= (EF_FRV_LIBPIC
| EF_FRV_G0
);
405 frv_pic_flag
= "-mlibrary-pic";
409 case OPTION_TOMCAT_DEBUG
:
413 case OPTION_TOMCAT_STATS
:
422 md_show_usage (stream
)
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"));
452 /* Initialize the `cgen' interface. */
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
,
459 frv_cgen_init_asm (gas_cgen_cpu_desc
);
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
);
464 /* Set the ELF flags if desired. */
466 bfd_set_private_flags (stdoutput
, frv_flags
);
468 /* Set the machine type */
469 bfd_default_set_arch_mach (stdoutput
, bfd_arch_frv
, frv_mach
);
471 /* Set up gp size so we can put local common items in .sbss */
472 bfd_set_gp_size (stdoutput
, g_switch_value
);
474 frv_vliw_reset (& vliw
, frv_mach
, frv_flags
);
479 struct vliw_insn_list
*frv_insert_vliw_insn
PARAMS ((bfd_boolean
));
481 struct vliw_insn_list
*
482 frv_insert_vliw_insn (count
)
485 struct vliw_insn_list
*vliw_insn_list_entry
;
486 struct vliw_chain
*vliw_chain_entry
;
488 if (current_vliw_chain
== NULL
)
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
++;
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
;
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
;
512 current_vliw_chain
->insn_count
++;
514 if (current_vliw_insn
)
515 current_vliw_insn
->next
= vliw_insn_list_entry
;
516 current_vliw_insn
= vliw_insn_list_entry
;
518 if (!current_vliw_chain
->insn_list
)
519 current_vliw_chain
->insn_list
= current_vliw_insn
;
521 return vliw_insn_list_entry
;
524 /* Identify the following cases:
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
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.
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.
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.
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 */
550 /* Check a vliw insn for an insn of type containing the sym passed in label_sym. */
552 static struct vliw_insn_list
*frv_find_in_vliw
553 PARAMS ((enum vliw_insn_type
, struct vliw_chain
*, symbolS
*));
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
;
562 struct vliw_insn_list
*the_insn
;
567 for (the_insn
= this_chain
->insn_list
; the_insn
; the_insn
= the_insn
->next
)
569 if (the_insn
->type
== vliw_insn_type
570 && the_insn
->sym
== label_sym
)
579 /* A Vliw insn containing a single nop insn. */
582 /* A Vliw insn containing two nop insns. */
585 /* Two vliw insns. The first containing two nop insns.
586 The second contain a single nop insn. */
587 VLIW_DOUBLE_THEN_SINGLE_NOP
590 static void frv_debug_tomcat
PARAMS ((struct vliw_chain
*));
593 frv_debug_tomcat (start_chain
)
594 struct vliw_chain
*start_chain
;
596 struct vliw_chain
*this_chain
;
597 struct vliw_insn_list
*this_insn
;
600 for (this_chain
= start_chain
; this_chain
; this_chain
= this_chain
->next
, i
++)
602 fprintf (stderr
, "\nVliw Insn #%d, #insns: %d\n", i
, this_chain
->insn_count
);
604 for (this_insn
= this_chain
->insn_list
; this_insn
; this_insn
= this_insn
->next
)
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");
615 fprintf (stderr
, " %s\n", this_insn
->insn
->base
->name
);
620 static void frv_adjust_vliw_count
PARAMS ((struct vliw_chain
*));
623 frv_adjust_vliw_count (this_chain
)
624 struct vliw_chain
*this_chain
;
626 struct vliw_insn_list
*this_insn
;
628 this_chain
->insn_count
= 0;
630 for (this_insn
= this_chain
->insn_list
;
632 this_insn
= this_insn
->next
)
634 if (this_insn
->type
!= VLIW_LABEL_TYPE
)
635 this_chain
->insn_count
++;
640 /* Insert the desired nop combination in the vliw chain before insert_before_insn.
641 Rechain the vliw insn. */
643 static struct vliw_chain
*frv_tomcat_shuffle
644 PARAMS ((enum vliw_nop_type
, struct vliw_chain
*, struct vliw_insn_list
*));
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
;
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
;
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
;
664 while (curr_insn
&& curr_insn
!= insert_before_insn
)
666 /* We can't set the packing bit on a label. If we have the case
670 branch that needs nops
671 Then don't set pack bit later. */
673 if (curr_insn
->type
!= VLIW_LABEL_TYPE
)
675 prev_insn
= curr_insn
;
676 curr_insn
= curr_insn
->next
;
679 while (curr_vliw
&& curr_vliw
!= vliw_to_split
)
681 prev_vliw
= curr_vliw
;
682 curr_vliw
= curr_vliw
->next
;
685 switch (this_nop_type
)
687 case VLIW_SINGLE_NOP
:
690 /* Branch is first, Insert the NOP prior to this vliw insn. */
692 prev_vliw
->next
= single_nop
;
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
;
701 /* Set the packing bit on the previous insn. */
704 unsigned char *buffer
= prev_insn
->address
;
707 /* The branch is in the middle. Split this vliw insn into first
708 and second parts. Insert the NOP inbetween. */
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
);
715 single_nop
->next
= second_part
;
717 vliw_to_split
->next
= single_nop
;
718 prev_insn
->next
= NULL
;
720 return_me
= second_part
;
721 frv_adjust_vliw_count (vliw_to_split
);
725 case VLIW_DOUBLE_NOP
:
728 /* Branch is first, Insert the NOP prior to this vliw insn. */
730 prev_vliw
->next
= double_nop
;
732 vliw_chain_top
= double_nop
;
734 double_nop
->next
= vliw_to_split
;
735 return_me
= vliw_to_split
;
736 vliw_to_split
->insn_list
->type
= VLIW_BRANCH_HAS_NOPS
;
740 /* Set the packing bit on the previous insn. */
743 unsigned char *buffer
= prev_insn
->address
;
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
);
754 double_nop
->next
= second_part
;
756 vliw_to_split
->next
= single_nop
;
757 prev_insn
->next
= NULL
;
758 frv_adjust_vliw_count (vliw_to_split
);
760 return_me
= second_part
;
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
;
773 /* The branch is the first insn in this vliw. Don't split the vliw. Insert
774 the nops prior to this vliw. */
776 prev_vliw
->next
= double_nop
;
778 vliw_chain_top
= double_nop
;
780 single_nop
->next
= vliw_to_split
;
781 return_me
= vliw_to_split
;
782 vliw_to_split
->insn_list
->type
= VLIW_BRANCH_HAS_NOPS
;
786 /* Set the packing bit on the previous insn. */
789 unsigned char *buffer
= prev_insn
->address
;
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
);
800 single_nop
->next
= second_part
;
802 vliw_to_split
->next
= double_nop
;
803 prev_insn
->next
= NULL
;
804 frv_adjust_vliw_count (vliw_to_split
);
806 return_me
= second_part
;
814 static void frv_tomcat_analyze_vliw_chains
PARAMS ((void));
817 frv_tomcat_analyze_vliw_chains ()
819 struct vliw_chain
*vliw1
= NULL
;
820 struct vliw_chain
*vliw2
= NULL
;
821 struct vliw_chain
*vliw3
= NULL
;
823 struct vliw_insn_list
*this_insn
= NULL
;
824 struct vliw_insn_list
*temp_insn
= NULL
;
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. */
829 #define FRV_SET_VLIW_WINDOW(VLIW1, VLIW2, VLIW3) \
830 if (VLIW1 && VLIW1->next) \
831 VLIW2 = VLIW1->next; \
834 if (VLIW2 && VLIW2->next) \
835 VLIW3 = VLIW2->next; \
839 vliw1
= vliw_chain_top
;
843 FRV_SET_VLIW_WINDOW (vliw1
, vliw2
, vliw3
);
848 if (vliw1
->insn_count
== 1)
850 /* check vliw1 for a label. */
851 if (vliw1
->insn_list
->type
== VLIW_LABEL_TYPE
)
853 temp_insn
= frv_find_in_vliw (VLIW_BRANCH_TYPE
, vliw2
, vliw1
->insn_list
->sym
);
856 vliw1
= frv_tomcat_shuffle (VLIW_DOUBLE_NOP
, vliw2
, vliw1
->insn_list
);
857 temp_insn
->dnop_frag
->fr_subtype
= NOP_KEEP
;
864 && vliw2
->insn_count
== 1
865 && (temp_insn
= frv_find_in_vliw (VLIW_BRANCH_TYPE
, vliw3
, vliw1
->insn_list
->sym
)) != NULL
)
867 temp_insn
->snop_frag
->fr_subtype
= NOP_KEEP
;
868 vliw1
= frv_tomcat_shuffle (VLIW_SINGLE_NOP
, vliw3
, vliw3
->insn_list
);
876 if (vliw1
->insn_count
== 2)
878 struct vliw_insn_list
*this_insn
;
880 /* check vliw1 for a label. */
881 for (this_insn
= vliw1
->insn_list
; this_insn
; this_insn
= this_insn
->next
)
883 if (this_insn
->type
== VLIW_LABEL_TYPE
)
885 if ((temp_insn
= frv_find_in_vliw (VLIW_BRANCH_TYPE
, vliw2
, this_insn
->sym
)) != NULL
)
887 temp_insn
->snop_frag
->fr_subtype
= NOP_KEEP
;
888 vliw1
= frv_tomcat_shuffle (VLIW_SINGLE_NOP
, vliw2
, this_insn
);
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
)
901 /* Don't look at labels or nops. */
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
;
914 if (frv_is_branch_insn (this_insn
->insn
))
916 if ((temp_insn
= frv_find_in_vliw (VLIW_LABEL_TYPE
, vliw1
, this_insn
->sym
)) != NULL
)
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
);
928 /* This vliw insn checks out okay. Take a look at the next one. */
934 frv_tomcat_workaround ()
936 if (frv_mach
!= bfd_mach_frvtomcat
)
940 frv_debug_tomcat (vliw_chain_top
);
942 frv_tomcat_analyze_vliw_chains ();
946 fprintf (stderr
, "Inserted %d Single Nops\n", tomcat_singles
);
947 fprintf (stderr
, "Inserted %d Double Nops\n", tomcat_doubles
);
952 fr550_check_insn_acc_range (frv_insn
*insn
, int low
, int hi
)
955 switch (CGEN_INSN_NUM (insn
->insn
))
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 */
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 */
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 */
1018 return 0; /* all is ok */
1022 fr550_check_acc_range (FRV_VLIW
*vliw
, frv_insn
*insn
)
1024 switch ((*vliw
->current_vliw
)[vliw
->next_slot
- 1])
1028 return fr550_check_insn_acc_range (insn
, 0, 3);
1031 return fr550_check_insn_acc_range (insn
, 4, 7);
1035 return 0; /* all is ok */
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
;
1050 /* Initialize GAS's cgen interface for a new instruction. */
1051 gas_cgen_init_parse ();
1053 insn
.insn
= frv_cgen_assemble_insn
1054 (gas_cgen_cpu_desc
, str
, & insn
.fields
, insn
.buffer
, &errmsg
);
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
1067 if (frv_mach
== bfd_mach_frvtomcat
)
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
))
1078 frag_wane (frag_now
);
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);
1085 frag_wane (frag_now
);
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);
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
;
1097 if ( !FRV_IS_NOP (insn
)
1098 && (frv_is_branch_insn (insn
.insn
) || insn
.fields
.f_pack
))
1100 vliw_insn_list_entry
->snop_frag
= single_nop_frag
;
1101 vliw_insn_list_entry
->dnop_frag
= double_nop_frag
;
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
)
1109 if (! insn
.fields
.f_pack
)
1111 as_bad (_("VLIW packing used for -mno-pack"));
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
)
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
)
1126 as_bad (_("VLIW packing constraint violation"));
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
);
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
1141 if (frv_mach
== bfd_mach_frvtomcat
)
1143 if (vliw_insn_list_entry
)
1144 vliw_insn_list_entry
->address
= finished_insn
.addr
;
1148 if (insn
.fields
.f_pack
)
1150 /* We've completed a VLIW insn. */
1151 previous_vliw_chain
= current_vliw_chain
;
1152 current_vliw_chain
= NULL
;
1153 current_vliw_insn
= NULL
;
1158 /* The syntax in the manual says constants begin with '#'.
1159 We just ignore it. */
1162 md_operand (expressionP
)
1163 expressionS
* expressionP
;
1165 if (* input_line_pointer
== '#')
1167 input_line_pointer
++;
1168 expression (expressionP
);
1173 md_section_align (segment
, size
)
1177 int align
= bfd_get_section_alignment (stdoutput
, segment
);
1178 return ((size
+ (1 << align
) - 1) & (-1 << align
));
1182 md_undefined_symbol (name
)
1183 char * name ATTRIBUTE_UNUSED
;
1188 /* Interface to relax_segment. */
1190 /* FIXME: Build table by hand, get it working, then machine generate. */
1191 const relax_typeS md_relax_table
[] =
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 }
1200 frv_relax_frag (fragP
, stretch
)
1201 fragS
*fragP ATTRIBUTE_UNUSED
;
1202 long stretch ATTRIBUTE_UNUSED
;
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.
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
1219 md_estimate_size_before_relax (fragP
, segment
)
1221 segT segment ATTRIBUTE_UNUSED
;
1223 switch (fragP
->fr_subtype
)
1226 return fragP
->fr_var
;
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.
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. */
1242 md_convert_frag (abfd
, sec
, fragP
)
1243 bfd
* abfd ATTRIBUTE_UNUSED
;
1244 segT sec ATTRIBUTE_UNUSED
;
1247 switch (fragP
->fr_subtype
)
1254 fragP
->fr_fix
= fragP
->fr_var
;
1260 /* Functions concerning relocs. */
1262 /* The location from which a PC relative jump should be calculated,
1263 given a PC relative reloc. */
1266 md_pcrel_from_section (fixP
, sec
)
1268 segT sec ATTRIBUTE_UNUSED
;
1270 /* Make no adjustment for relocations that will be written out. */
1271 if (TC_FORCE_RELOCATION (fixP
))
1274 return (fixP
->fx_frag
->fr_address
+ fixP
->fx_where
) & ~1;
1277 /* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
1278 Returns BFD_RELOC_NONE if no reloc type can be found.
1279 *FIXP may be modified if desired. */
1281 bfd_reloc_code_real_type
1282 md_cgen_lookup_reloc (insn
, operand
, fixP
)
1283 const CGEN_INSN
* insn ATTRIBUTE_UNUSED
;
1284 const CGEN_OPERAND
* operand
;
1287 switch (operand
->type
)
1289 case FRV_OPERAND_LABEL16
:
1290 fixP
->fx_pcrel
= TRUE
;
1291 return BFD_RELOC_FRV_LABEL16
;
1293 case FRV_OPERAND_LABEL24
:
1294 fixP
->fx_pcrel
= TRUE
;
1295 return BFD_RELOC_FRV_LABEL24
;
1297 case FRV_OPERAND_UHI16
:
1298 case FRV_OPERAND_ULO16
:
1299 case FRV_OPERAND_SLO16
:
1301 /* The relocation type should be recorded in opinfo */
1302 if (fixP
->fx_cgen
.opinfo
!= 0)
1303 return fixP
->fx_cgen
.opinfo
;
1306 case FRV_OPERAND_D12
:
1307 case FRV_OPERAND_S12
:
1308 return BFD_RELOC_FRV_GPREL12
;
1310 case FRV_OPERAND_U12
:
1311 return BFD_RELOC_FRV_GPRELU12
;
1316 return BFD_RELOC_NONE
;
1320 /* See whether we need to force a relocation into the output file.
1321 This is used to force out switch and PC relative relocations when
1325 frv_force_relocation (fix
)
1328 if (fix
->fx_r_type
== BFD_RELOC_FRV_GPREL12
1329 || fix
->fx_r_type
== BFD_RELOC_FRV_GPRELU12
)
1332 return generic_force_reloc (fix
);
1335 /* Write a value out to the object file, using the appropriate endianness. */
1338 frv_md_number_to_chars (buf
, val
, n
)
1343 number_to_chars_bigendian (buf
, val
, n
);
1346 /* Turn a string in input_line_pointer into a floating point constant of type
1347 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
1348 emitted is stored in *sizeP . An error message is returned, or NULL on OK.
1351 /* Equal to MAX_PRECISION in atof-ieee.c */
1352 #define MAX_LITTLENUMS 6
1355 md_atof (type
, litP
, sizeP
)
1362 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
1381 /* FIXME: Some targets allow other format chars for bigger sizes here. */
1385 return _("Bad call to md_atof()");
1388 t
= atof_ieee (input_line_pointer
, type
, words
);
1390 input_line_pointer
= t
;
1391 * sizeP
= prec
* sizeof (LITTLENUM_TYPE
);
1393 for (i
= 0; i
< prec
; i
++)
1395 md_number_to_chars (litP
, (valueT
) words
[i
],
1396 sizeof (LITTLENUM_TYPE
));
1397 litP
+= sizeof (LITTLENUM_TYPE
);
1404 frv_fix_adjustable (fixP
)
1407 bfd_reloc_code_real_type reloc_type
;
1409 if ((int) fixP
->fx_r_type
>= (int) BFD_RELOC_UNUSED
)
1411 const CGEN_INSN
*insn
= NULL
;
1412 int opindex
= (int) fixP
->fx_r_type
- (int) BFD_RELOC_UNUSED
;
1413 const CGEN_OPERAND
*operand
= cgen_operand_lookup_by_num(gas_cgen_cpu_desc
, opindex
);
1414 reloc_type
= md_cgen_lookup_reloc (insn
, operand
, fixP
);
1417 reloc_type
= fixP
->fx_r_type
;
1419 /* We need the symbol name for the VTABLE entries */
1420 if ( reloc_type
== BFD_RELOC_VTABLE_INHERIT
1421 || reloc_type
== BFD_RELOC_VTABLE_ENTRY
1422 || reloc_type
== BFD_RELOC_FRV_GPREL12
1423 || reloc_type
== BFD_RELOC_FRV_GPRELU12
)
1429 /* Allow user to set flags bits. */
1432 int arg ATTRIBUTE_UNUSED
;
1434 flagword new_flags
= get_absolute_expression ();
1435 flagword new_mask
= ~ (flagword
)0;
1437 frv_user_set_flags_p
= 1;
1438 if (*input_line_pointer
== ',')
1440 ++input_line_pointer
;
1441 new_mask
= get_absolute_expression ();
1444 frv_flags
= (frv_flags
& ~new_mask
) | (new_flags
& new_mask
);
1445 bfd_set_private_flags (stdoutput
, frv_flags
);
1448 /* Frv specific function to handle 4 byte initializations for pointers that are
1449 considered 'safe' for use with pic support. Until frv_frob_file{,_section}
1450 is run, we encode it a BFD_RELOC_CTOR, and it is turned back into a normal
1451 BFD_RELOC_32 at that time. */
1454 frv_pic_ptr (nbytes
)
1463 #ifdef md_flush_pending_output
1464 md_flush_pending_output ();
1467 if (is_it_end_of_statement ())
1469 demand_empty_rest_of_line ();
1473 #ifdef md_cons_align
1474 md_cons_align (nbytes
);
1483 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
, 4, &exp
, 0,
1486 while (*input_line_pointer
++ == ',');
1488 input_line_pointer
--; /* Put terminator back into stream. */
1489 demand_empty_rest_of_line ();
1495 #define DPRINTF1(A) fprintf (stderr, A)
1496 #define DPRINTF2(A,B) fprintf (stderr, A, B)
1497 #define DPRINTF3(A,B,C) fprintf (stderr, A, B, C)
1501 #define DPRINTF2(A,B)
1502 #define DPRINTF3(A,B,C)
1505 /* Go through a the sections looking for relocations that are problematical for
1506 pic. If not pic, just note that this object can't be linked with pic. If
1507 it is pic, see if it needs to be marked so that it will be fixed up, or if
1508 not possible, issue an error. */
1511 frv_frob_file_section (abfd
, sec
, ptr
)
1514 PTR ptr ATTRIBUTE_UNUSED
;
1516 segment_info_type
*seginfo
= seg_info (sec
);
1518 CGEN_CPU_DESC cd
= gas_cgen_cpu_desc
;
1519 flagword flags
= bfd_get_section_flags (abfd
, sec
);
1521 /* Skip relocations in known sections (.ctors, .dtors, and .gcc_except_table)
1522 since we can fix those up by hand. */
1523 int known_section_p
= (sec
->name
1524 && sec
->name
[0] == '.'
1525 && ((sec
->name
[1] == 'c'
1526 && strcmp (sec
->name
, ".ctor") == 0)
1527 || (sec
->name
[1] == 'd'
1528 && strcmp (sec
->name
, ".dtor") == 0)
1529 || (sec
->name
[1] == 'g'
1530 && strcmp (sec
->name
, ".gcc_except_table") == 0)));
1532 DPRINTF3 ("\nFrv section %s%s\n", sec
->name
, (known_section_p
) ? ", known section" : "");
1533 if ((flags
& SEC_ALLOC
) == 0)
1535 DPRINTF1 ("\tSkipping non-loaded section\n");
1539 for (fixp
= seginfo
->fix_root
; fixp
; fixp
= fixp
->fx_next
)
1541 symbolS
*s
= fixp
->fx_addsy
;
1542 bfd_reloc_code_real_type reloc
;
1545 const CGEN_OPERAND
*operand
;
1546 const CGEN_INSN
*insn
= fixp
->fx_cgen
.insn
;
1550 DPRINTF1 ("\tSkipping reloc that has already been done\n");
1556 DPRINTF1 ("\tSkipping reloc that is PC relative\n");
1562 DPRINTF1 ("\tSkipping reloc without symbol\n");
1566 if (fixp
->fx_r_type
< BFD_RELOC_UNUSED
)
1569 reloc
= fixp
->fx_r_type
;
1573 opindex
= (int) fixp
->fx_r_type
- (int) BFD_RELOC_UNUSED
;
1574 operand
= cgen_operand_lookup_by_num (cd
, opindex
);
1575 reloc
= md_cgen_lookup_reloc (insn
, operand
, fixp
);
1578 DPRINTF3 ("\treloc %s\t%s", bfd_get_reloc_code_name (reloc
), S_GET_NAME (s
));
1587 /* Skip relocations in known sections (.ctors, .dtors, and
1588 .gcc_except_table) since we can fix those up by hand. Also
1589 skip forward references to constants. Also skip a difference
1590 of two symbols, which still uses the BFD_RELOC_32 at this
1592 if (! known_section_p
1593 && S_GET_SEGMENT (s
) != absolute_section
1595 && (flags
& (SEC_READONLY
| SEC_CODE
)) == 0)
1601 /* FIXME -- should determine if any of the GP relocation really uses
1602 gr16 (which is not pic safe) or not. Right now, assume if we
1603 aren't being compiled with -mpic, the usage is non pic safe, but
1604 is safe with -mpic. */
1605 case BFD_RELOC_FRV_GPREL12
:
1606 case BFD_RELOC_FRV_GPRELU12
:
1607 case BFD_RELOC_FRV_GPREL32
:
1608 case BFD_RELOC_FRV_GPRELHI
:
1609 case BFD_RELOC_FRV_GPRELLO
:
1610 non_pic_p
= ! frv_pic_p
;
1613 case BFD_RELOC_FRV_LO16
:
1614 case BFD_RELOC_FRV_HI16
:
1615 if (S_GET_SEGMENT (s
) != absolute_section
)
1619 case BFD_RELOC_VTABLE_INHERIT
:
1620 case BFD_RELOC_VTABLE_ENTRY
:
1624 /* If this is a blessed BFD_RELOC_32, convert it back to the normal
1626 case BFD_RELOC_CTOR
:
1627 fixp
->fx_r_type
= BFD_RELOC_32
;
1633 DPRINTF1 (" (Non-pic relocation)\n");
1635 as_warn_where (fixp
->fx_file
, fixp
->fx_line
,
1636 _("Relocation %s is not safe for %s"),
1637 bfd_get_reloc_code_name (reloc
), frv_pic_flag
);
1639 else if ((frv_flags
& EF_FRV_NON_PIC_RELOCS
) == 0)
1641 frv_flags
|= EF_FRV_NON_PIC_RELOCS
;
1642 bfd_set_private_flags (abfd
, frv_flags
);
1652 /* After all of the symbols have been adjusted, go over the file looking
1653 for any relocations that pic won't support. */
1658 bfd_map_over_sections (stdoutput
, frv_frob_file_section
, (PTR
)0);
1662 frv_frob_label (this_label
)
1663 symbolS
*this_label
;
1665 struct vliw_insn_list
*vliw_insn_list_entry
;
1667 if (frv_mach
!= bfd_mach_frvtomcat
)
1670 if (now_seg
!= text_section
)
1673 vliw_insn_list_entry
= frv_insert_vliw_insn(DONT_COUNT
);
1674 vliw_insn_list_entry
->type
= VLIW_LABEL_TYPE
;
1675 vliw_insn_list_entry
->sym
= this_label
;
1679 frv_cgen_record_fixup_exp (frag
, where
, insn
, length
, operand
, opinfo
, exp
)
1682 const CGEN_INSN
* insn
;
1684 const CGEN_OPERAND
* operand
;
1688 fixS
* fixP
= gas_cgen_record_fixup_exp (frag
, where
, insn
, length
,
1689 operand
, opinfo
, exp
);
1691 if (frv_mach
== bfd_mach_frvtomcat
1692 && current_vliw_insn
1693 && current_vliw_insn
->type
== VLIW_BRANCH_TYPE
1695 current_vliw_insn
->sym
= exp
->X_add_symbol
;