1 /* tc-frv.c -- Assembler for the Fujitsu FRV.
2 Copyright (C) 2002-2016 Free Software Foundation, Inc.
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 3, 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, 51 Franklin Street - Fifth Floor,
19 Boston, MA 02110-1301, USA. */
24 #include "opcodes/frv-desc.h"
25 #include "opcodes/frv-opc.h"
28 #include "elf/common.h"
30 #include "dwarf2dbg.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
166 # define DEFAULT_FDPIC EF_FRV_FDPIC
168 # define DEFAULT_FDPIC 0
171 static unsigned long frv_mach
= bfd_mach_frv
;
172 static bfd_boolean fr400_audio
;
174 /* Flags to set in the elf header */
175 static flagword frv_flags
= DEFAULT_FLAGS
| DEFAULT_FDPIC
;
177 static int frv_user_set_flags_p
= 0;
178 static int frv_pic_p
= 0;
179 static const char *frv_pic_flag
= DEFAULT_FDPIC
? "-mfdpic" : (const char *)0;
181 /* Print tomcat-specific debugging info. */
182 static int tomcat_debug
= 0;
184 /* Tomcat-specific NOP statistics. */
185 static int tomcat_stats
= 0;
186 static int tomcat_doubles
= 0;
187 static int tomcat_singles
= 0;
189 /* Forward reference to static functions */
190 static void frv_set_flags (int);
191 static void frv_pic_ptr (int);
193 /* The target specific pseudo-ops which we support. */
194 const pseudo_typeS md_pseudo_table
[] =
196 { "eflags", frv_set_flags
, 0 },
198 { "picptr", frv_pic_ptr
, 4 },
203 #define FRV_SHORTOPTS "G:"
204 const char * md_shortopts
= FRV_SHORTOPTS
;
206 #define OPTION_GPR_32 (OPTION_MD_BASE)
207 #define OPTION_GPR_64 (OPTION_MD_BASE + 1)
208 #define OPTION_FPR_32 (OPTION_MD_BASE + 2)
209 #define OPTION_FPR_64 (OPTION_MD_BASE + 3)
210 #define OPTION_SOFT_FLOAT (OPTION_MD_BASE + 4)
211 #define OPTION_DWORD_YES (OPTION_MD_BASE + 5)
212 #define OPTION_DWORD_NO (OPTION_MD_BASE + 6)
213 #define OPTION_DOUBLE (OPTION_MD_BASE + 7)
214 #define OPTION_NO_DOUBLE (OPTION_MD_BASE + 8)
215 #define OPTION_MEDIA (OPTION_MD_BASE + 9)
216 #define OPTION_NO_MEDIA (OPTION_MD_BASE + 10)
217 #define OPTION_CPU (OPTION_MD_BASE + 11)
218 #define OPTION_PIC (OPTION_MD_BASE + 12)
219 #define OPTION_BIGPIC (OPTION_MD_BASE + 13)
220 #define OPTION_LIBPIC (OPTION_MD_BASE + 14)
221 #define OPTION_MULADD (OPTION_MD_BASE + 15)
222 #define OPTION_NO_MULADD (OPTION_MD_BASE + 16)
223 #define OPTION_TOMCAT_DEBUG (OPTION_MD_BASE + 17)
224 #define OPTION_TOMCAT_STATS (OPTION_MD_BASE + 18)
225 #define OPTION_PACK (OPTION_MD_BASE + 19)
226 #define OPTION_NO_PACK (OPTION_MD_BASE + 20)
227 #define OPTION_FDPIC (OPTION_MD_BASE + 21)
228 #define OPTION_NOPIC (OPTION_MD_BASE + 22)
230 struct option md_longopts
[] =
232 { "mgpr-32", no_argument
, NULL
, OPTION_GPR_32
},
233 { "mgpr-64", no_argument
, NULL
, OPTION_GPR_64
},
234 { "mfpr-32", no_argument
, NULL
, OPTION_FPR_32
},
235 { "mfpr-64", no_argument
, NULL
, OPTION_FPR_64
},
236 { "mhard-float", no_argument
, NULL
, OPTION_FPR_64
},
237 { "msoft-float", no_argument
, NULL
, OPTION_SOFT_FLOAT
},
238 { "mdword", no_argument
, NULL
, OPTION_DWORD_YES
},
239 { "mno-dword", no_argument
, NULL
, OPTION_DWORD_NO
},
240 { "mdouble", no_argument
, NULL
, OPTION_DOUBLE
},
241 { "mno-double", no_argument
, NULL
, OPTION_NO_DOUBLE
},
242 { "mmedia", no_argument
, NULL
, OPTION_MEDIA
},
243 { "mno-media", no_argument
, NULL
, OPTION_NO_MEDIA
},
244 { "mcpu", required_argument
, NULL
, OPTION_CPU
},
245 { "mpic", no_argument
, NULL
, OPTION_PIC
},
246 { "mPIC", no_argument
, NULL
, OPTION_BIGPIC
},
247 { "mlibrary-pic", no_argument
, NULL
, OPTION_LIBPIC
},
248 { "mmuladd", no_argument
, NULL
, OPTION_MULADD
},
249 { "mno-muladd", no_argument
, NULL
, OPTION_NO_MULADD
},
250 { "mtomcat-debug", no_argument
, NULL
, OPTION_TOMCAT_DEBUG
},
251 { "mtomcat-stats", no_argument
, NULL
, OPTION_TOMCAT_STATS
},
252 { "mpack", no_argument
, NULL
, OPTION_PACK
},
253 { "mno-pack", no_argument
, NULL
, OPTION_NO_PACK
},
254 { "mfdpic", no_argument
, NULL
, OPTION_FDPIC
},
255 { "mnopic", no_argument
, NULL
, OPTION_NOPIC
},
256 { NULL
, no_argument
, NULL
, 0 },
259 size_t md_longopts_size
= sizeof (md_longopts
);
261 /* What value to give to bfd_set_gp_size. */
262 static int g_switch_value
= 8;
265 md_parse_option (int c
, const char *arg
)
273 g_switch_value
= atoi (arg
);
274 if (! g_switch_value
)
275 frv_flags
|= EF_FRV_G0
;
279 frv_flags
= (frv_flags
& ~EF_FRV_GPR_MASK
) | EF_FRV_GPR_32
;
283 frv_flags
= (frv_flags
& ~EF_FRV_GPR_MASK
) | EF_FRV_GPR_64
;
287 frv_flags
= (frv_flags
& ~EF_FRV_FPR_MASK
) | EF_FRV_FPR_32
;
291 frv_flags
= (frv_flags
& ~EF_FRV_FPR_MASK
) | EF_FRV_FPR_64
;
294 case OPTION_SOFT_FLOAT
:
295 frv_flags
= (frv_flags
& ~EF_FRV_FPR_MASK
) | EF_FRV_FPR_NONE
;
298 case OPTION_DWORD_YES
:
299 frv_flags
= (frv_flags
& ~EF_FRV_DWORD_MASK
) | EF_FRV_DWORD_YES
;
302 case OPTION_DWORD_NO
:
303 frv_flags
= (frv_flags
& ~EF_FRV_DWORD_MASK
) | EF_FRV_DWORD_NO
;
307 frv_flags
|= EF_FRV_DOUBLE
;
310 case OPTION_NO_DOUBLE
:
311 frv_flags
&= ~EF_FRV_DOUBLE
;
315 frv_flags
|= EF_FRV_MEDIA
;
318 case OPTION_NO_MEDIA
:
319 frv_flags
&= ~EF_FRV_MEDIA
;
323 frv_flags
|= EF_FRV_MULADD
;
326 case OPTION_NO_MULADD
:
327 frv_flags
&= ~EF_FRV_MULADD
;
331 frv_flags
&= ~EF_FRV_NOPACK
;
335 frv_flags
|= EF_FRV_NOPACK
;
341 int cpu_flags
= EF_FRV_CPU_GENERIC
;
343 /* Identify the processor type */
345 if (strcmp (p
, "frv") == 0)
347 cpu_flags
= EF_FRV_CPU_GENERIC
;
348 frv_mach
= bfd_mach_frv
;
351 else if (strcmp (p
, "fr500") == 0)
353 cpu_flags
= EF_FRV_CPU_FR500
;
354 frv_mach
= bfd_mach_fr500
;
357 else if (strcmp (p
, "fr550") == 0)
359 cpu_flags
= EF_FRV_CPU_FR550
;
360 frv_mach
= bfd_mach_fr550
;
363 else if (strcmp (p
, "fr450") == 0)
365 cpu_flags
= EF_FRV_CPU_FR450
;
366 frv_mach
= bfd_mach_fr450
;
369 else if (strcmp (p
, "fr405") == 0)
371 cpu_flags
= EF_FRV_CPU_FR405
;
372 frv_mach
= bfd_mach_fr400
;
376 else if (strcmp (p
, "fr400") == 0)
378 cpu_flags
= EF_FRV_CPU_FR400
;
379 frv_mach
= bfd_mach_fr400
;
383 else if (strcmp (p
, "fr300") == 0)
385 cpu_flags
= EF_FRV_CPU_FR300
;
386 frv_mach
= bfd_mach_fr300
;
389 else if (strcmp (p
, "simple") == 0)
391 cpu_flags
= EF_FRV_CPU_SIMPLE
;
392 frv_mach
= bfd_mach_frvsimple
;
393 frv_flags
|= EF_FRV_NOPACK
;
396 else if (strcmp (p
, "tomcat") == 0)
398 cpu_flags
= EF_FRV_CPU_TOMCAT
;
399 frv_mach
= bfd_mach_frvtomcat
;
404 as_fatal (_("Unknown cpu -mcpu=%s"), arg
);
408 frv_flags
= (frv_flags
& ~EF_FRV_CPU_MASK
) | cpu_flags
;
413 frv_flags
|= EF_FRV_PIC
;
415 frv_pic_flag
= "-fpic";
419 frv_flags
|= EF_FRV_BIGPIC
;
421 frv_pic_flag
= "-fPIC";
425 frv_flags
|= (EF_FRV_LIBPIC
| EF_FRV_G0
);
427 frv_pic_flag
= "-mlibrary-pic";
432 frv_flags
|= EF_FRV_FDPIC
;
433 frv_pic_flag
= "-mfdpic";
437 frv_flags
&= ~(EF_FRV_FDPIC
| EF_FRV_PIC
438 | EF_FRV_BIGPIC
| EF_FRV_LIBPIC
);
442 case OPTION_TOMCAT_DEBUG
:
446 case OPTION_TOMCAT_STATS
:
455 md_show_usage (FILE * stream
)
457 fprintf (stream
, _("FRV specific command line options:\n"));
458 fprintf (stream
, _("-G n Put data <= n bytes in the small data area\n"));
459 fprintf (stream
, _("-mgpr-32 Mark generated file as only using 32 GPRs\n"));
460 fprintf (stream
, _("-mgpr-64 Mark generated file as using all 64 GPRs\n"));
461 fprintf (stream
, _("-mfpr-32 Mark generated file as only using 32 FPRs\n"));
462 fprintf (stream
, _("-mfpr-64 Mark generated file as using all 64 FPRs\n"));
463 fprintf (stream
, _("-msoft-float Mark generated file as using software FP\n"));
464 fprintf (stream
, _("-mdword Mark generated file as using a 8-byte stack alignment\n"));
465 fprintf (stream
, _("-mno-dword Mark generated file as using a 4-byte stack alignment\n"));
466 fprintf (stream
, _("-mdouble Mark generated file as using double precision FP insns\n"));
467 fprintf (stream
, _("-mmedia Mark generated file as using media insns\n"));
468 fprintf (stream
, _("-mmuladd Mark generated file as using multiply add/subtract insns\n"));
469 fprintf (stream
, _("-mpack Allow instructions to be packed\n"));
470 fprintf (stream
, _("-mno-pack Do not allow instructions to be packed\n"));
471 fprintf (stream
, _("-mpic Mark generated file as using small position independent code\n"));
472 fprintf (stream
, _("-mPIC Mark generated file as using large position independent code\n"));
473 fprintf (stream
, _("-mlibrary-pic Mark generated file as using position indepedent code for libraries\n"));
474 fprintf (stream
, _("-mfdpic Assemble for the FDPIC ABI\n"));
475 fprintf (stream
, _("-mnopic Disable -mpic, -mPIC, -mlibrary-pic and -mfdpic\n"));
476 fprintf (stream
, _("-mcpu={fr500|fr550|fr400|fr405|fr450|fr300|frv|simple|tomcat}\n"));
477 fprintf (stream
, _(" Record the cpu type\n"));
478 fprintf (stream
, _("-mtomcat-stats Print out stats for tomcat workarounds\n"));
479 fprintf (stream
, _("-mtomcat-debug Debug tomcat workarounds\n"));
486 /* Initialize the `cgen' interface. */
488 /* Set the machine number and endian. */
489 gas_cgen_cpu_desc
= frv_cgen_cpu_open (CGEN_CPU_OPEN_MACHS
, 0,
490 CGEN_CPU_OPEN_ENDIAN
,
493 frv_cgen_init_asm (gas_cgen_cpu_desc
);
495 /* This is a callback from cgen to gas to parse operands. */
496 cgen_set_parse_operand_fn (gas_cgen_cpu_desc
, gas_cgen_parse_operand
);
498 /* Set the ELF flags if desired. */
500 bfd_set_private_flags (stdoutput
, frv_flags
);
502 /* Set the machine type */
503 bfd_default_set_arch_mach (stdoutput
, bfd_arch_frv
, frv_mach
);
505 /* Set up gp size so we can put local common items in .sbss */
506 bfd_set_gp_size (stdoutput
, g_switch_value
);
508 frv_vliw_reset (& vliw
, frv_mach
, frv_flags
);
512 frv_md_fdpic_enabled (void)
514 return (frv_flags
& EF_FRV_FDPIC
) != 0;
519 static struct vliw_insn_list
*
520 frv_insert_vliw_insn (bfd_boolean count
)
522 struct vliw_insn_list
*vliw_insn_list_entry
;
523 struct vliw_chain
*vliw_chain_entry
;
525 if (current_vliw_chain
== NULL
)
527 vliw_chain_entry
= XNEW (struct vliw_chain
);
528 vliw_chain_entry
->insn_count
= 0;
529 vliw_chain_entry
->insn_list
= NULL
;
530 vliw_chain_entry
->next
= NULL
;
531 vliw_chain_entry
->num
= chain_num
++;
534 vliw_chain_top
= vliw_chain_entry
;
535 current_vliw_chain
= vliw_chain_entry
;
536 if (previous_vliw_chain
)
537 previous_vliw_chain
->next
= vliw_chain_entry
;
540 vliw_insn_list_entry
= XNEW (struct vliw_insn_list
);
541 vliw_insn_list_entry
->type
= VLIW_GENERIC_TYPE
;
542 vliw_insn_list_entry
->insn
= NULL
;
543 vliw_insn_list_entry
->sym
= NULL
;
544 vliw_insn_list_entry
->snop_frag
= NULL
;
545 vliw_insn_list_entry
->dnop_frag
= NULL
;
546 vliw_insn_list_entry
->next
= NULL
;
549 current_vliw_chain
->insn_count
++;
551 if (current_vliw_insn
)
552 current_vliw_insn
->next
= vliw_insn_list_entry
;
553 current_vliw_insn
= vliw_insn_list_entry
;
555 if (!current_vliw_chain
->insn_list
)
556 current_vliw_chain
->insn_list
= current_vliw_insn
;
558 return vliw_insn_list_entry
;
561 /* Identify the following cases:
563 1) A VLIW insn that contains both a branch and the branch destination.
564 This requires the insertion of two vliw instructions before the
565 branch. The first consists of two nops. The second consists of
568 2) A single instruction VLIW insn which is the destination of a branch
569 that is in the next VLIW insn. This requires the insertion of a vliw
570 insn containing two nops before the branch.
572 3) A double instruction VLIW insn which contains the destination of a
573 branch that is in the next VLIW insn. This requires the insertion of
574 a VLIW insn containing a single nop before the branch.
576 4) A single instruction VLIW insn which contains branch destination (x),
577 followed by a single instruction VLIW insn which does not contain
578 the branch to (x), followed by a VLIW insn which does contain the branch
579 to (x). This requires the insertion of a VLIW insn containing a single
580 nop before the VLIW instruction containing the branch.
583 #define FRV_IS_NOP(insn) (insn.buffer[0] == FRV_NOP_PACK || insn.buffer[0] == FRV_NOP_NOPACK)
584 #define FRV_NOP_PACK 0x00880000 /* ori.p gr0,0,gr0 */
585 #define FRV_NOP_NOPACK 0x80880000 /* ori gr0,0,gr0 */
587 /* Check a vliw insn for an insn of type containing the sym passed in label_sym. */
589 static struct vliw_insn_list
*
590 frv_find_in_vliw (enum vliw_insn_type vliw_insn_type
,
591 struct vliw_chain
*this_chain
,
595 struct vliw_insn_list
*the_insn
;
600 for (the_insn
= this_chain
->insn_list
; the_insn
; the_insn
= the_insn
->next
)
602 if (the_insn
->type
== vliw_insn_type
603 && the_insn
->sym
== label_sym
)
612 /* A Vliw insn containing a single nop insn. */
615 /* A Vliw insn containing two nop insns. */
618 /* Two vliw insns. The first containing two nop insns.
619 The second contain a single nop insn. */
620 VLIW_DOUBLE_THEN_SINGLE_NOP
624 frv_debug_tomcat (struct vliw_chain
*start_chain
)
626 struct vliw_chain
*this_chain
;
627 struct vliw_insn_list
*this_insn
;
630 for (this_chain
= start_chain
; this_chain
; this_chain
= this_chain
->next
, i
++)
632 fprintf (stderr
, "\nVliw Insn #%d, #insns: %d\n", i
, this_chain
->insn_count
);
634 for (this_insn
= this_chain
->insn_list
; this_insn
; this_insn
= this_insn
->next
)
636 if (this_insn
->type
== VLIW_LABEL_TYPE
)
637 fprintf (stderr
, "Label Value: %p\n", this_insn
->sym
);
638 else if (this_insn
->type
== VLIW_BRANCH_TYPE
)
639 fprintf (stderr
, "%s to %p\n", this_insn
->insn
->base
->name
, this_insn
->sym
);
640 else if (this_insn
->type
== VLIW_BRANCH_HAS_NOPS
)
641 fprintf (stderr
, "nop'd %s to %p\n", this_insn
->insn
->base
->name
, this_insn
->sym
);
642 else if (this_insn
->type
== VLIW_NOP_TYPE
)
643 fprintf (stderr
, "Nop\n");
645 fprintf (stderr
, " %s\n", this_insn
->insn
->base
->name
);
651 frv_adjust_vliw_count (struct vliw_chain
*this_chain
)
653 struct vliw_insn_list
*this_insn
;
655 this_chain
->insn_count
= 0;
657 for (this_insn
= this_chain
->insn_list
;
659 this_insn
= this_insn
->next
)
661 if (this_insn
->type
!= VLIW_LABEL_TYPE
)
662 this_chain
->insn_count
++;
667 /* Insert the desired nop combination in the vliw chain before insert_before_insn.
668 Rechain the vliw insn. */
670 static struct vliw_chain
*
671 frv_tomcat_shuffle (enum vliw_nop_type this_nop_type
,
672 struct vliw_chain
*vliw_to_split
,
673 struct vliw_insn_list
*insert_before_insn
)
676 bfd_boolean pack_prev
= FALSE
;
677 struct vliw_chain
*return_me
= NULL
;
678 struct vliw_insn_list
*prev_insn
= NULL
;
679 struct vliw_insn_list
*curr_insn
= vliw_to_split
->insn_list
;
681 struct vliw_chain
*double_nop
= XNEW (struct vliw_chain
);
682 struct vliw_chain
*single_nop
= XNEW (struct vliw_chain
);
683 struct vliw_chain
*second_part
= XNEW (struct vliw_chain
);
684 struct vliw_chain
*curr_vliw
= vliw_chain_top
;
685 struct vliw_chain
*prev_vliw
= NULL
;
687 while (curr_insn
&& curr_insn
!= insert_before_insn
)
689 /* We can't set the packing bit on a label. If we have the case
693 branch that needs nops
694 Then don't set pack bit later. */
696 if (curr_insn
->type
!= VLIW_LABEL_TYPE
)
698 prev_insn
= curr_insn
;
699 curr_insn
= curr_insn
->next
;
702 while (curr_vliw
&& curr_vliw
!= vliw_to_split
)
704 prev_vliw
= curr_vliw
;
705 curr_vliw
= curr_vliw
->next
;
708 switch (this_nop_type
)
710 case VLIW_SINGLE_NOP
:
713 /* Branch is first, Insert the NOP prior to this vliw insn. */
715 prev_vliw
->next
= single_nop
;
717 vliw_chain_top
= single_nop
;
718 single_nop
->next
= vliw_to_split
;
719 vliw_to_split
->insn_list
->type
= VLIW_BRANCH_HAS_NOPS
;
720 return_me
= vliw_to_split
;
724 /* Set the packing bit on the previous insn. */
727 char *buffer
= prev_insn
->address
;
730 /* The branch is in the middle. Split this vliw insn into first
731 and second parts. Insert the NOP inbetween. */
733 second_part
->insn_list
= insert_before_insn
;
734 second_part
->insn_list
->type
= VLIW_BRANCH_HAS_NOPS
;
735 second_part
->next
= vliw_to_split
->next
;
736 frv_adjust_vliw_count (second_part
);
738 single_nop
->next
= second_part
;
740 vliw_to_split
->next
= single_nop
;
741 prev_insn
->next
= NULL
;
743 return_me
= second_part
;
744 frv_adjust_vliw_count (vliw_to_split
);
748 case VLIW_DOUBLE_NOP
:
751 /* Branch is first, Insert the NOP prior to this vliw insn. */
753 prev_vliw
->next
= double_nop
;
755 vliw_chain_top
= double_nop
;
757 double_nop
->next
= vliw_to_split
;
758 return_me
= vliw_to_split
;
759 vliw_to_split
->insn_list
->type
= VLIW_BRANCH_HAS_NOPS
;
763 /* Set the packing bit on the previous insn. */
766 char *buffer
= prev_insn
->address
;
770 /* The branch is in the middle. Split this vliw insn into first
771 and second parts. Insert the NOP inbetween. */
772 second_part
->insn_list
= insert_before_insn
;
773 second_part
->insn_list
->type
= VLIW_BRANCH_HAS_NOPS
;
774 second_part
->next
= vliw_to_split
->next
;
775 frv_adjust_vliw_count (second_part
);
777 double_nop
->next
= second_part
;
779 vliw_to_split
->next
= single_nop
;
780 prev_insn
->next
= NULL
;
781 frv_adjust_vliw_count (vliw_to_split
);
783 return_me
= second_part
;
787 case VLIW_DOUBLE_THEN_SINGLE_NOP
:
788 double_nop
->next
= single_nop
;
789 double_nop
->insn_count
= 2;
790 double_nop
->insn_list
= &double_nop_insn
;
791 single_nop
->insn_count
= 1;
792 single_nop
->insn_list
= &single_nop_insn
;
796 /* The branch is the first insn in this vliw. Don't split the vliw. Insert
797 the nops prior to this vliw. */
799 prev_vliw
->next
= double_nop
;
801 vliw_chain_top
= double_nop
;
803 single_nop
->next
= vliw_to_split
;
804 return_me
= vliw_to_split
;
805 vliw_to_split
->insn_list
->type
= VLIW_BRANCH_HAS_NOPS
;
809 /* Set the packing bit on the previous insn. */
812 char *buffer
= prev_insn
->address
;
816 /* The branch is in the middle of this vliw insn. Split into first and
817 second parts. Insert the nop vliws in between. */
818 second_part
->insn_list
= insert_before_insn
;
819 second_part
->insn_list
->type
= VLIW_BRANCH_HAS_NOPS
;
820 second_part
->next
= vliw_to_split
->next
;
821 frv_adjust_vliw_count (second_part
);
823 single_nop
->next
= second_part
;
825 vliw_to_split
->next
= double_nop
;
826 prev_insn
->next
= NULL
;
827 frv_adjust_vliw_count (vliw_to_split
);
829 return_me
= second_part
;
838 frv_tomcat_analyze_vliw_chains (void)
840 struct vliw_chain
*vliw1
= NULL
;
841 struct vliw_chain
*vliw2
= NULL
;
842 struct vliw_chain
*vliw3
= NULL
;
844 struct vliw_insn_list
*this_insn
= NULL
;
845 struct vliw_insn_list
*temp_insn
= NULL
;
847 /* We potentially need to look at three VLIW insns to determine if the
848 workaround is required. Set them up. Ignore existing nops during analysis. */
850 #define FRV_SET_VLIW_WINDOW(VLIW1, VLIW2, VLIW3) \
851 if (VLIW1 && VLIW1->next) \
852 VLIW2 = VLIW1->next; \
855 if (VLIW2 && VLIW2->next) \
856 VLIW3 = VLIW2->next; \
860 vliw1
= vliw_chain_top
;
864 FRV_SET_VLIW_WINDOW (vliw1
, vliw2
, vliw3
);
869 if (vliw1
->insn_count
== 1)
871 /* check vliw1 for a label. */
872 if (vliw1
->insn_list
->type
== VLIW_LABEL_TYPE
)
874 temp_insn
= frv_find_in_vliw (VLIW_BRANCH_TYPE
, vliw2
, vliw1
->insn_list
->sym
);
877 vliw1
= frv_tomcat_shuffle (VLIW_DOUBLE_NOP
, vliw2
, vliw1
->insn_list
);
878 temp_insn
->dnop_frag
->fr_subtype
= NOP_KEEP
;
885 && vliw2
->insn_count
== 1
886 && (temp_insn
= frv_find_in_vliw (VLIW_BRANCH_TYPE
, vliw3
, vliw1
->insn_list
->sym
)) != NULL
)
888 temp_insn
->snop_frag
->fr_subtype
= NOP_KEEP
;
889 vliw1
= frv_tomcat_shuffle (VLIW_SINGLE_NOP
, vliw3
, vliw3
->insn_list
);
897 if (vliw1
->insn_count
== 2)
899 /* Check vliw1 for a label. */
900 for (this_insn
= vliw1
->insn_list
; this_insn
; this_insn
= this_insn
->next
)
902 if (this_insn
->type
== VLIW_LABEL_TYPE
)
904 if ((temp_insn
= frv_find_in_vliw (VLIW_BRANCH_TYPE
, vliw2
, this_insn
->sym
)) != NULL
)
906 temp_insn
->snop_frag
->fr_subtype
= NOP_KEEP
;
907 vliw1
= frv_tomcat_shuffle (VLIW_SINGLE_NOP
, vliw2
, this_insn
);
917 /* Examine each insn in this VLIW. Look for the workaround criteria. */
918 for (this_insn
= vliw1
->insn_list
; this_insn
; this_insn
= this_insn
->next
)
920 /* Don't look at labels or nops. */
922 && (this_insn
->type
== VLIW_LABEL_TYPE
923 || this_insn
->type
== VLIW_NOP_TYPE
924 || this_insn
->type
== VLIW_BRANCH_HAS_NOPS
))
925 this_insn
= this_insn
->next
;
933 if (frv_is_branch_insn (this_insn
->insn
))
935 if ((temp_insn
= frv_find_in_vliw (VLIW_LABEL_TYPE
, vliw1
, this_insn
->sym
)) != NULL
)
937 /* Insert [nop/nop] [nop] before branch. */
938 this_insn
->snop_frag
->fr_subtype
= NOP_KEEP
;
939 this_insn
->dnop_frag
->fr_subtype
= NOP_KEEP
;
940 vliw1
= frv_tomcat_shuffle (VLIW_DOUBLE_THEN_SINGLE_NOP
, vliw1
, this_insn
);
947 /* This vliw insn checks out okay. Take a look at the next one. */
953 frv_tomcat_workaround (void)
955 if (frv_mach
!= bfd_mach_frvtomcat
)
959 frv_debug_tomcat (vliw_chain_top
);
961 frv_tomcat_analyze_vliw_chains ();
965 fprintf (stderr
, "Inserted %d Single Nops\n", tomcat_singles
);
966 fprintf (stderr
, "Inserted %d Double Nops\n", tomcat_doubles
);
971 fr550_check_insn_acc_range (frv_insn
*insn
, int low
, int hi
)
974 switch (CGEN_INSN_NUM (insn
->insn
))
976 case FRV_INSN_MADDACCS
:
977 case FRV_INSN_MSUBACCS
:
978 case FRV_INSN_MDADDACCS
:
979 case FRV_INSN_MDSUBACCS
:
980 case FRV_INSN_MASACCS
:
981 case FRV_INSN_MDASACCS
:
982 acc
= insn
->fields
.f_ACC40Si
;
983 if (acc
< low
|| acc
> hi
)
984 return 1; /* out of range */
985 acc
= insn
->fields
.f_ACC40Sk
;
986 if (acc
< low
|| acc
> hi
)
987 return 1; /* out of range */
989 case FRV_INSN_MMULHS
:
990 case FRV_INSN_MMULHU
:
991 case FRV_INSN_MMULXHS
:
992 case FRV_INSN_MMULXHU
:
993 case FRV_INSN_CMMULHS
:
994 case FRV_INSN_CMMULHU
:
995 case FRV_INSN_MQMULHS
:
996 case FRV_INSN_MQMULHU
:
997 case FRV_INSN_MQMULXHS
:
998 case FRV_INSN_MQMULXHU
:
999 case FRV_INSN_CMQMULHS
:
1000 case FRV_INSN_CMQMULHU
:
1001 case FRV_INSN_MMACHS
:
1002 case FRV_INSN_MMRDHS
:
1003 case FRV_INSN_CMMACHS
:
1004 case FRV_INSN_MQMACHS
:
1005 case FRV_INSN_CMQMACHS
:
1006 case FRV_INSN_MQXMACHS
:
1007 case FRV_INSN_MQXMACXHS
:
1008 case FRV_INSN_MQMACXHS
:
1009 case FRV_INSN_MCPXRS
:
1010 case FRV_INSN_MCPXIS
:
1011 case FRV_INSN_CMCPXRS
:
1012 case FRV_INSN_CMCPXIS
:
1013 case FRV_INSN_MQCPXRS
:
1014 case FRV_INSN_MQCPXIS
:
1015 acc
= insn
->fields
.f_ACC40Sk
;
1016 if (acc
< low
|| acc
> hi
)
1017 return 1; /* out of range */
1019 case FRV_INSN_MMACHU
:
1020 case FRV_INSN_MMRDHU
:
1021 case FRV_INSN_CMMACHU
:
1022 case FRV_INSN_MQMACHU
:
1023 case FRV_INSN_CMQMACHU
:
1024 case FRV_INSN_MCPXRU
:
1025 case FRV_INSN_MCPXIU
:
1026 case FRV_INSN_CMCPXRU
:
1027 case FRV_INSN_CMCPXIU
:
1028 case FRV_INSN_MQCPXRU
:
1029 case FRV_INSN_MQCPXIU
:
1030 acc
= insn
->fields
.f_ACC40Uk
;
1031 if (acc
< low
|| acc
> hi
)
1032 return 1; /* out of range */
1037 return 0; /* all is ok */
1041 fr550_check_acc_range (FRV_VLIW
*vlw
, frv_insn
*insn
)
1043 switch ((*vlw
->current_vliw
)[vlw
->next_slot
- 1])
1047 return fr550_check_insn_acc_range (insn
, 0, 3);
1050 return fr550_check_insn_acc_range (insn
, 4, 7);
1054 return 0; /* all is ok */
1057 /* Return true if the target implements instruction INSN. */
1060 target_implements_insn_p (const CGEN_INSN
*insn
)
1065 /* bfd_mach_frv or generic. */
1068 case bfd_mach_fr300
:
1069 case bfd_mach_frvsimple
:
1070 return CGEN_INSN_MACH_HAS_P (insn
, MACH_SIMPLE
);
1072 case bfd_mach_fr400
:
1073 return ((fr400_audio
|| !CGEN_INSN_ATTR_VALUE (insn
, CGEN_INSN_AUDIO
))
1074 && CGEN_INSN_MACH_HAS_P (insn
, MACH_FR400
));
1076 case bfd_mach_fr450
:
1077 return CGEN_INSN_MACH_HAS_P (insn
, MACH_FR450
);
1079 case bfd_mach_fr500
:
1080 return CGEN_INSN_MACH_HAS_P (insn
, MACH_FR500
);
1082 case bfd_mach_fr550
:
1083 return CGEN_INSN_MACH_HAS_P (insn
, MACH_FR550
);
1088 md_assemble (char *str
)
1092 int packing_constraint
;
1093 finished_insnS finished_insn
;
1094 fragS
*double_nop_frag
= NULL
;
1095 fragS
*single_nop_frag
= NULL
;
1096 struct vliw_insn_list
*vliw_insn_list_entry
= NULL
;
1098 /* Initialize GAS's cgen interface for a new instruction. */
1099 gas_cgen_init_parse ();
1101 memset (&insn
, 0, sizeof (insn
));
1103 insn
.insn
= frv_cgen_assemble_insn
1104 (gas_cgen_cpu_desc
, str
, & insn
.fields
, insn
.buffer
, &errmsg
);
1108 as_bad ("%s", errmsg
);
1112 /* If the cpu is tomcat, then we need to insert nops to workaround
1113 hardware limitations. We need to keep track of each vliw unit
1114 and examine the length of the unit and the individual insns
1115 within the unit to determine the number and location of the
1117 if (frv_mach
== bfd_mach_frvtomcat
)
1119 /* If we've just finished a VLIW insn OR this is a branch,
1120 then start up a new frag. Fill it with nops. We will get rid
1121 of those that are not required after we've seen all of the
1122 instructions but before we start resolving fixups. */
1123 if ( !FRV_IS_NOP (insn
)
1124 && (frv_is_branch_insn (insn
.insn
) || insn
.fields
.f_pack
))
1128 frag_wane (frag_now
);
1130 double_nop_frag
= frag_now
;
1131 buffer
= frag_var (rs_machine_dependent
, 8, 8, NOP_DELETE
, NULL
, 0, 0);
1132 md_number_to_chars (buffer
, FRV_NOP_PACK
, 4);
1133 md_number_to_chars (buffer
+4, FRV_NOP_NOPACK
, 4);
1135 frag_wane (frag_now
);
1137 single_nop_frag
= frag_now
;
1138 buffer
= frag_var (rs_machine_dependent
, 4, 4, NOP_DELETE
, NULL
, 0, 0);
1139 md_number_to_chars (buffer
, FRV_NOP_NOPACK
, 4);
1142 vliw_insn_list_entry
= frv_insert_vliw_insn (DO_COUNT
);
1143 vliw_insn_list_entry
->insn
= insn
.insn
;
1144 if (frv_is_branch_insn (insn
.insn
))
1145 vliw_insn_list_entry
->type
= VLIW_BRANCH_TYPE
;
1147 if ( !FRV_IS_NOP (insn
)
1148 && (frv_is_branch_insn (insn
.insn
) || insn
.fields
.f_pack
))
1150 vliw_insn_list_entry
->snop_frag
= single_nop_frag
;
1151 vliw_insn_list_entry
->dnop_frag
= double_nop_frag
;
1155 /* Make sure that this insn does not violate the VLIW packing constraints. */
1156 /* -mno-pack disallows any packing whatsoever. */
1157 if (frv_flags
& EF_FRV_NOPACK
)
1159 if (! insn
.fields
.f_pack
)
1161 as_bad (_("VLIW packing used for -mno-pack"));
1165 /* -mcpu=FRV is an idealized FR-V implementation that supports all of the
1166 instructions, don't do vliw checking. */
1167 else if (frv_mach
!= bfd_mach_frv
)
1169 if (!target_implements_insn_p (insn
.insn
))
1171 as_bad (_("Instruction not supported by this architecture"));
1174 packing_constraint
= frv_vliw_add_insn (& vliw
, insn
.insn
);
1175 if (frv_mach
== bfd_mach_fr550
&& ! packing_constraint
)
1176 packing_constraint
= fr550_check_acc_range (& vliw
, & insn
);
1177 if (insn
.fields
.f_pack
)
1178 frv_vliw_reset (& vliw
, frv_mach
, frv_flags
);
1179 if (packing_constraint
)
1181 as_bad (_("VLIW packing constraint violation"));
1186 /* Doesn't really matter what we pass for RELAX_P here. */
1187 gas_cgen_finish_insn (insn
.insn
, insn
.buffer
,
1188 CGEN_FIELDS_BITSIZE (& insn
.fields
), 1, &finished_insn
);
1191 /* If the cpu is tomcat, then we need to insert nops to workaround
1192 hardware limitations. We need to keep track of each vliw unit
1193 and examine the length of the unit and the individual insns
1194 within the unit to determine the number and location of the
1196 if (frv_mach
== bfd_mach_frvtomcat
)
1198 if (vliw_insn_list_entry
)
1199 vliw_insn_list_entry
->address
= finished_insn
.addr
;
1203 if (insn
.fields
.f_pack
)
1205 /* We've completed a VLIW insn. */
1206 previous_vliw_chain
= current_vliw_chain
;
1207 current_vliw_chain
= NULL
;
1208 current_vliw_insn
= NULL
;
1213 /* The syntax in the manual says constants begin with '#'.
1214 We just ignore it. */
1217 md_operand (expressionS
*expressionP
)
1219 if (* input_line_pointer
== '#')
1221 input_line_pointer
++;
1222 expression (expressionP
);
1227 md_section_align (segT segment
, valueT size
)
1229 int align
= bfd_get_section_alignment (stdoutput
, segment
);
1230 return ((size
+ (1 << align
) - 1) & -(1 << align
));
1234 md_undefined_symbol (char *name ATTRIBUTE_UNUSED
)
1239 /* Interface to relax_segment. */
1241 /* FIXME: Build table by hand, get it working, then machine generate. */
1242 const relax_typeS md_relax_table
[] =
1245 {511 - 2 - 2, -512 - 2 + 2, 0, 2 },
1246 {0x2000000 - 1 - 2, -0x2000000 - 2, 2, 0 },
1247 {0x2000000 - 1 - 2, -0x2000000 - 2, 4, 0 }
1251 frv_relax_frag (fragS
*fragP ATTRIBUTE_UNUSED
, long stretch ATTRIBUTE_UNUSED
)
1256 /* Return an initial guess of the length by which a fragment must grow to
1257 hold a branch to reach its destination.
1258 Also updates fr_type/fr_subtype as necessary.
1260 Called just before doing relaxation.
1261 Any symbol that is now undefined will not become defined.
1262 The guess for fr_var is ACTUALLY the growth beyond fr_fix.
1263 Whatever we do to grow fr_fix or fr_var contributes to our returned value.
1264 Although it may not be explicit in the frag, pretend fr_var starts with a
1268 md_estimate_size_before_relax (fragS
*fragP
, segT segment ATTRIBUTE_UNUSED
)
1270 switch (fragP
->fr_subtype
)
1273 return fragP
->fr_var
;
1281 /* *fragP has been relaxed to its final size, and now needs to have
1282 the bytes inside it modified to conform to the new size.
1284 Called after relaxation is finished.
1285 fragP->fr_type == rs_machine_dependent.
1286 fragP->fr_subtype is the subtype of what the address relaxed to. */
1289 md_convert_frag (bfd
*abfd ATTRIBUTE_UNUSED
,
1290 segT sec ATTRIBUTE_UNUSED
,
1293 switch (fragP
->fr_subtype
)
1300 fragP
->fr_fix
= fragP
->fr_var
;
1306 /* Functions concerning relocs. */
1308 /* The location from which a PC relative jump should be calculated,
1309 given a PC relative reloc. */
1312 md_pcrel_from_section (fixS
*fixP
, segT sec
)
1314 if (TC_FORCE_RELOCATION (fixP
)
1315 || (fixP
->fx_addsy
!= (symbolS
*) NULL
1316 && S_GET_SEGMENT (fixP
->fx_addsy
) != sec
))
1318 /* If we can't adjust this relocation, or if it references a
1319 local symbol in a different section (which
1320 TC_FORCE_RELOCATION can't check), let the linker figure it
1325 return (fixP
->fx_frag
->fr_address
+ fixP
->fx_where
) & ~1;
1328 /* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
1329 Returns BFD_RELOC_NONE if no reloc type can be found.
1330 *FIXP may be modified if desired. */
1332 bfd_reloc_code_real_type
1333 md_cgen_lookup_reloc (const CGEN_INSN
*insn ATTRIBUTE_UNUSED
,
1334 const CGEN_OPERAND
*operand
,
1337 switch (operand
->type
)
1339 case FRV_OPERAND_LABEL16
:
1340 fixP
->fx_pcrel
= TRUE
;
1341 return BFD_RELOC_FRV_LABEL16
;
1343 case FRV_OPERAND_LABEL24
:
1344 fixP
->fx_pcrel
= TRUE
;
1346 if (fixP
->fx_cgen
.opinfo
!= 0)
1347 return fixP
->fx_cgen
.opinfo
;
1349 return BFD_RELOC_FRV_LABEL24
;
1351 case FRV_OPERAND_UHI16
:
1352 case FRV_OPERAND_ULO16
:
1353 case FRV_OPERAND_SLO16
:
1354 case FRV_OPERAND_CALLANN
:
1355 case FRV_OPERAND_LDANN
:
1356 case FRV_OPERAND_LDDANN
:
1357 /* The relocation type should be recorded in opinfo */
1358 if (fixP
->fx_cgen
.opinfo
!= 0)
1359 return fixP
->fx_cgen
.opinfo
;
1362 case FRV_OPERAND_D12
:
1363 case FRV_OPERAND_S12
:
1364 if (fixP
->fx_cgen
.opinfo
!= 0)
1365 return fixP
->fx_cgen
.opinfo
;
1367 return BFD_RELOC_FRV_GPREL12
;
1369 case FRV_OPERAND_U12
:
1370 return BFD_RELOC_FRV_GPRELU12
;
1375 return BFD_RELOC_NONE
;
1379 /* See whether we need to force a relocation into the output file.
1380 This is used to force out switch and PC relative relocations when
1384 frv_force_relocation (fixS
*fix
)
1386 switch (fix
->fx_r_type
< BFD_RELOC_UNUSED
1387 ? (int) fix
->fx_r_type
1388 : fix
->fx_cgen
.opinfo
)
1390 case BFD_RELOC_FRV_GPREL12
:
1391 case BFD_RELOC_FRV_GPRELU12
:
1392 case BFD_RELOC_FRV_GPREL32
:
1393 case BFD_RELOC_FRV_GPRELHI
:
1394 case BFD_RELOC_FRV_GPRELLO
:
1395 case BFD_RELOC_FRV_GOT12
:
1396 case BFD_RELOC_FRV_GOTHI
:
1397 case BFD_RELOC_FRV_GOTLO
:
1398 case BFD_RELOC_FRV_FUNCDESC_VALUE
:
1399 case BFD_RELOC_FRV_FUNCDESC_GOTOFF12
:
1400 case BFD_RELOC_FRV_FUNCDESC_GOTOFFHI
:
1401 case BFD_RELOC_FRV_FUNCDESC_GOTOFFLO
:
1402 case BFD_RELOC_FRV_GOTOFF12
:
1403 case BFD_RELOC_FRV_GOTOFFHI
:
1404 case BFD_RELOC_FRV_GOTOFFLO
:
1405 case BFD_RELOC_FRV_GETTLSOFF
:
1406 case BFD_RELOC_FRV_TLSDESC_VALUE
:
1407 case BFD_RELOC_FRV_GOTTLSDESC12
:
1408 case BFD_RELOC_FRV_GOTTLSDESCHI
:
1409 case BFD_RELOC_FRV_GOTTLSDESCLO
:
1410 case BFD_RELOC_FRV_TLSMOFF12
:
1411 case BFD_RELOC_FRV_TLSMOFFHI
:
1412 case BFD_RELOC_FRV_TLSMOFFLO
:
1413 case BFD_RELOC_FRV_GOTTLSOFF12
:
1414 case BFD_RELOC_FRV_GOTTLSOFFHI
:
1415 case BFD_RELOC_FRV_GOTTLSOFFLO
:
1416 case BFD_RELOC_FRV_TLSOFF
:
1417 case BFD_RELOC_FRV_TLSDESC_RELAX
:
1418 case BFD_RELOC_FRV_GETTLSOFF_RELAX
:
1419 case BFD_RELOC_FRV_TLSOFF_RELAX
:
1426 return generic_force_reloc (fix
);
1429 /* Apply a fixup that could be resolved within the assembler. */
1432 md_apply_fix (fixS
*fixP
, valueT
*valP
, segT seg
)
1434 if (fixP
->fx_addsy
== 0)
1435 switch (fixP
->fx_cgen
.opinfo
)
1437 case BFD_RELOC_FRV_HI16
:
1440 case BFD_RELOC_FRV_LO16
:
1444 /* We need relocations for these, even if their symbols reduce
1446 case BFD_RELOC_FRV_GPREL12
:
1447 case BFD_RELOC_FRV_GPRELU12
:
1448 case BFD_RELOC_FRV_GPREL32
:
1449 case BFD_RELOC_FRV_GPRELHI
:
1450 case BFD_RELOC_FRV_GPRELLO
:
1451 case BFD_RELOC_FRV_GOT12
:
1452 case BFD_RELOC_FRV_GOTHI
:
1453 case BFD_RELOC_FRV_GOTLO
:
1454 case BFD_RELOC_FRV_FUNCDESC_VALUE
:
1455 case BFD_RELOC_FRV_FUNCDESC_GOTOFF12
:
1456 case BFD_RELOC_FRV_FUNCDESC_GOTOFFHI
:
1457 case BFD_RELOC_FRV_FUNCDESC_GOTOFFLO
:
1458 case BFD_RELOC_FRV_GOTOFF12
:
1459 case BFD_RELOC_FRV_GOTOFFHI
:
1460 case BFD_RELOC_FRV_GOTOFFLO
:
1461 case BFD_RELOC_FRV_GETTLSOFF
:
1462 case BFD_RELOC_FRV_TLSDESC_VALUE
:
1463 case BFD_RELOC_FRV_GOTTLSDESC12
:
1464 case BFD_RELOC_FRV_GOTTLSDESCHI
:
1465 case BFD_RELOC_FRV_GOTTLSDESCLO
:
1466 case BFD_RELOC_FRV_TLSMOFF12
:
1467 case BFD_RELOC_FRV_TLSMOFFHI
:
1468 case BFD_RELOC_FRV_TLSMOFFLO
:
1469 case BFD_RELOC_FRV_GOTTLSOFF12
:
1470 case BFD_RELOC_FRV_GOTTLSOFFHI
:
1471 case BFD_RELOC_FRV_GOTTLSOFFLO
:
1472 case BFD_RELOC_FRV_TLSOFF
:
1473 case BFD_RELOC_FRV_TLSDESC_RELAX
:
1474 case BFD_RELOC_FRV_GETTLSOFF_RELAX
:
1475 case BFD_RELOC_FRV_TLSOFF_RELAX
:
1476 fixP
->fx_addsy
= abs_section_sym
;
1480 switch (fixP
->fx_cgen
.opinfo
)
1482 case BFD_RELOC_FRV_GETTLSOFF
:
1483 case BFD_RELOC_FRV_TLSDESC_VALUE
:
1484 case BFD_RELOC_FRV_GOTTLSDESC12
:
1485 case BFD_RELOC_FRV_GOTTLSDESCHI
:
1486 case BFD_RELOC_FRV_GOTTLSDESCLO
:
1487 case BFD_RELOC_FRV_TLSMOFF12
:
1488 case BFD_RELOC_FRV_TLSMOFFHI
:
1489 case BFD_RELOC_FRV_TLSMOFFLO
:
1490 case BFD_RELOC_FRV_GOTTLSOFF12
:
1491 case BFD_RELOC_FRV_GOTTLSOFFHI
:
1492 case BFD_RELOC_FRV_GOTTLSOFFLO
:
1493 case BFD_RELOC_FRV_TLSOFF
:
1494 case BFD_RELOC_FRV_TLSDESC_RELAX
:
1495 case BFD_RELOC_FRV_GETTLSOFF_RELAX
:
1496 case BFD_RELOC_FRV_TLSOFF_RELAX
:
1497 /* Mark TLS symbols as such. */
1498 if (S_GET_SEGMENT (fixP
->fx_addsy
) != absolute_section
)
1499 S_SET_THREAD_LOCAL (fixP
->fx_addsy
);
1503 gas_cgen_md_apply_fix (fixP
, valP
, seg
);
1508 /* Write a value out to the object file, using the appropriate endianness. */
1511 frv_md_number_to_chars (char *buf
, valueT val
, int n
)
1513 number_to_chars_bigendian (buf
, val
, n
);
1517 md_atof (int type
, char *litP
, int *sizeP
)
1519 return ieee_md_atof (type
, litP
, sizeP
, TRUE
);
1523 frv_fix_adjustable (fixS
*fixP
)
1525 bfd_reloc_code_real_type reloc_type
;
1527 if ((int) fixP
->fx_r_type
>= (int) BFD_RELOC_UNUSED
)
1529 const CGEN_INSN
*insn
= NULL
;
1530 int opindex
= (int) fixP
->fx_r_type
- (int) BFD_RELOC_UNUSED
;
1531 const CGEN_OPERAND
*operand
= cgen_operand_lookup_by_num(gas_cgen_cpu_desc
, opindex
);
1532 reloc_type
= md_cgen_lookup_reloc (insn
, operand
, fixP
);
1535 reloc_type
= fixP
->fx_r_type
;
1537 /* We need the symbol name for the VTABLE entries */
1538 if ( reloc_type
== BFD_RELOC_VTABLE_INHERIT
1539 || reloc_type
== BFD_RELOC_VTABLE_ENTRY
1540 || reloc_type
== BFD_RELOC_FRV_GPREL12
1541 || reloc_type
== BFD_RELOC_FRV_GPRELU12
)
1547 /* Allow user to set flags bits. */
1549 frv_set_flags (int arg ATTRIBUTE_UNUSED
)
1551 flagword new_flags
= get_absolute_expression ();
1552 flagword new_mask
= ~ (flagword
)0;
1554 frv_user_set_flags_p
= 1;
1555 if (*input_line_pointer
== ',')
1557 ++input_line_pointer
;
1558 new_mask
= get_absolute_expression ();
1561 frv_flags
= (frv_flags
& ~new_mask
) | (new_flags
& new_mask
);
1562 bfd_set_private_flags (stdoutput
, frv_flags
);
1565 /* Frv specific function to handle 4 byte initializations for pointers that are
1566 considered 'safe' for use with pic support. Until frv_frob_file{,_section}
1567 is run, we encode it a BFD_RELOC_CTOR, and it is turned back into a normal
1568 BFD_RELOC_32 at that time. */
1571 frv_pic_ptr (int nbytes
)
1579 #ifdef md_flush_pending_output
1580 md_flush_pending_output ();
1583 if (is_it_end_of_statement ())
1585 demand_empty_rest_of_line ();
1589 #ifdef md_cons_align
1590 md_cons_align (nbytes
);
1595 bfd_reloc_code_real_type reloc_type
= BFD_RELOC_CTOR
;
1597 if (strncasecmp (input_line_pointer
, "funcdesc(", 9) == 0)
1599 input_line_pointer
+= 9;
1601 if (*input_line_pointer
== ')')
1602 input_line_pointer
++;
1604 as_bad (_("missing ')'"));
1605 reloc_type
= BFD_RELOC_FRV_FUNCDESC
;
1607 else if (strncasecmp (input_line_pointer
, "tlsmoff(", 8) == 0)
1609 input_line_pointer
+= 8;
1611 if (*input_line_pointer
== ')')
1612 input_line_pointer
++;
1614 as_bad (_("missing ')'"));
1615 reloc_type
= BFD_RELOC_FRV_TLSMOFF
;
1622 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
, 4, &exp
, 0,
1625 while (*input_line_pointer
++ == ',');
1627 input_line_pointer
--; /* Put terminator back into stream. */
1628 demand_empty_rest_of_line ();
1634 #define DPRINTF1(A) fprintf (stderr, A)
1635 #define DPRINTF2(A,B) fprintf (stderr, A, B)
1636 #define DPRINTF3(A,B,C) fprintf (stderr, A, B, C)
1640 #define DPRINTF2(A,B)
1641 #define DPRINTF3(A,B,C)
1644 /* Go through a the sections looking for relocations that are problematical for
1645 pic. If not pic, just note that this object can't be linked with pic. If
1646 it is pic, see if it needs to be marked so that it will be fixed up, or if
1647 not possible, issue an error. */
1650 frv_frob_file_section (bfd
*abfd
, asection
*sec
, void *ptr ATTRIBUTE_UNUSED
)
1652 segment_info_type
*seginfo
= seg_info (sec
);
1654 CGEN_CPU_DESC cd
= gas_cgen_cpu_desc
;
1655 flagword flags
= bfd_get_section_flags (abfd
, sec
);
1657 /* Skip relocations in known sections (.ctors, .dtors, and .gcc_except_table)
1658 since we can fix those up by hand. */
1659 int known_section_p
= (sec
->name
1660 && sec
->name
[0] == '.'
1661 && ((sec
->name
[1] == 'c'
1662 && strcmp (sec
->name
, ".ctor") == 0)
1663 || (sec
->name
[1] == 'd'
1664 && strcmp (sec
->name
, ".dtor") == 0)
1665 || (sec
->name
[1] == 'g'
1666 && strcmp (sec
->name
, ".gcc_except_table") == 0)));
1668 DPRINTF3 ("\nFrv section %s%s\n", sec
->name
, (known_section_p
) ? ", known section" : "");
1669 if ((flags
& SEC_ALLOC
) == 0)
1671 DPRINTF1 ("\tSkipping non-loaded section\n");
1675 for (fixp
= seginfo
->fix_root
; fixp
; fixp
= fixp
->fx_next
)
1677 symbolS
*s
= fixp
->fx_addsy
;
1678 bfd_reloc_code_real_type reloc
;
1681 const CGEN_OPERAND
*operand
;
1682 const CGEN_INSN
*insn
= fixp
->fx_cgen
.insn
;
1686 DPRINTF1 ("\tSkipping reloc that has already been done\n");
1692 DPRINTF1 ("\tSkipping reloc that is PC relative\n");
1698 DPRINTF1 ("\tSkipping reloc without symbol\n");
1702 if (fixp
->fx_r_type
< BFD_RELOC_UNUSED
)
1705 reloc
= fixp
->fx_r_type
;
1709 opindex
= (int) fixp
->fx_r_type
- (int) BFD_RELOC_UNUSED
;
1710 operand
= cgen_operand_lookup_by_num (cd
, opindex
);
1711 reloc
= md_cgen_lookup_reloc (insn
, operand
, fixp
);
1714 DPRINTF3 ("\treloc %s\t%s", bfd_get_reloc_code_name (reloc
), S_GET_NAME (s
));
1723 /* Skip relocations in known sections (.ctors, .dtors, and
1724 .gcc_except_table) since we can fix those up by hand. Also
1725 skip forward references to constants. Also skip a difference
1726 of two symbols, which still uses the BFD_RELOC_32 at this
1728 if (! known_section_p
1729 && S_GET_SEGMENT (s
) != absolute_section
1731 && (flags
& (SEC_READONLY
| SEC_CODE
)) == 0)
1737 /* FIXME -- should determine if any of the GP relocation really uses
1738 gr16 (which is not pic safe) or not. Right now, assume if we
1739 aren't being compiled with -mpic, the usage is non pic safe, but
1740 is safe with -mpic. */
1741 case BFD_RELOC_FRV_GPREL12
:
1742 case BFD_RELOC_FRV_GPRELU12
:
1743 case BFD_RELOC_FRV_GPREL32
:
1744 case BFD_RELOC_FRV_GPRELHI
:
1745 case BFD_RELOC_FRV_GPRELLO
:
1746 non_pic_p
= ! frv_pic_p
;
1749 case BFD_RELOC_FRV_LO16
:
1750 case BFD_RELOC_FRV_HI16
:
1751 if (S_GET_SEGMENT (s
) != absolute_section
)
1755 case BFD_RELOC_VTABLE_INHERIT
:
1756 case BFD_RELOC_VTABLE_ENTRY
:
1760 /* If this is a blessed BFD_RELOC_32, convert it back to the normal
1762 case BFD_RELOC_CTOR
:
1763 fixp
->fx_r_type
= BFD_RELOC_32
;
1769 DPRINTF1 (" (Non-pic relocation)\n");
1771 as_warn_where (fixp
->fx_file
, fixp
->fx_line
,
1772 _("Relocation %s is not safe for %s"),
1773 bfd_get_reloc_code_name (reloc
), frv_pic_flag
);
1775 else if ((frv_flags
& EF_FRV_NON_PIC_RELOCS
) == 0)
1777 frv_flags
|= EF_FRV_NON_PIC_RELOCS
;
1778 bfd_set_private_flags (abfd
, frv_flags
);
1788 /* After all of the symbols have been adjusted, go over the file looking
1789 for any relocations that pic won't support. */
1792 frv_frob_file (void)
1794 bfd_map_over_sections (stdoutput
, frv_frob_file_section
, (void *) 0);
1798 frv_frob_label (symbolS
*this_label
)
1800 struct vliw_insn_list
*vliw_insn_list_entry
;
1802 dwarf2_emit_label (this_label
);
1803 if (frv_mach
!= bfd_mach_frvtomcat
)
1806 if (now_seg
!= text_section
)
1809 vliw_insn_list_entry
= frv_insert_vliw_insn(DONT_COUNT
);
1810 vliw_insn_list_entry
->type
= VLIW_LABEL_TYPE
;
1811 vliw_insn_list_entry
->sym
= this_label
;
1815 frv_cgen_record_fixup_exp (fragS
*frag
,
1817 const CGEN_INSN
*insn
,
1819 const CGEN_OPERAND
*operand
,
1823 fixS
* fixP
= gas_cgen_record_fixup_exp (frag
, where
, insn
, length
,
1824 operand
, opinfo
, exp
);
1826 if (frv_mach
== bfd_mach_frvtomcat
1827 && current_vliw_insn
1828 && current_vliw_insn
->type
== VLIW_BRANCH_TYPE
1830 current_vliw_insn
->sym
= exp
->X_add_symbol
;