1 /* tc-frv.c -- Assembler for the Fujitsu FRV.
2 Copyright (C) 2002-2023 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"
27 #include "elf/common.h"
29 #include "dwarf2dbg.h"
31 /* Structure to hold all of the different components describing
32 an individual instruction. */
35 const CGEN_INSN
* insn
;
36 const CGEN_INSN
* orig_insn
;
39 CGEN_INSN_INT buffer
[1];
40 #define INSN_VALUE(buf) (*(buf))
42 unsigned char buffer
[CGEN_MAX_INSN_SIZE
];
43 #define INSN_VALUE(buf) (buf)
48 fixS
* fixups
[GAS_CGEN_MAX_FIXUPS
];
49 int indices
[MAX_OPERAND_INSTANCES
];
55 VLIW_GENERIC_TYPE
, /* Don't care about this insn. */
56 VLIW_BRANCH_TYPE
, /* A Branch. */
57 VLIW_LABEL_TYPE
, /* A Label. */
58 VLIW_NOP_TYPE
, /* A NOP. */
59 VLIW_BRANCH_HAS_NOPS
/* A Branch that requires NOPS. */
62 /* We're going to use these in the fr_subtype field to mark
63 whether to keep inserted nops. */
65 #define NOP_KEEP 1 /* Keep these NOPS. */
66 #define NOP_DELETE 2 /* Delete these NOPS. */
69 #define DONT_COUNT false
71 /* A list of insns within a VLIW insn. */
74 /* The type of this insn. */
75 enum vliw_insn_type type
;
77 /* The corresponding gas insn information. */
78 const CGEN_INSN
*insn
;
80 /* For branches and labels, the symbol that is referenced. */
83 /* For branches, the frag containing the single nop that was generated. */
86 /* For branches, the frag containing the double nop that was generated. */
89 /* Pointer to raw data for this insn. */
92 /* Next insn in list. */
93 struct vliw_insn_list
*next
;
96 static struct vliw_insn_list single_nop_insn
= {
97 VLIW_NOP_TYPE
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
99 static struct vliw_insn_list double_nop_insn
= {
100 VLIW_NOP_TYPE
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
106 struct vliw_insn_list
*insn_list
;
107 struct vliw_chain
*next
;
110 static struct vliw_chain
*vliw_chain_top
;
111 static struct vliw_chain
*current_vliw_chain
;
112 static struct vliw_chain
*previous_vliw_chain
;
113 static struct vliw_insn_list
*current_vliw_insn
;
115 const char comment_chars
[] = ";";
116 const char line_comment_chars
[] = "#";
117 const char line_separator_chars
[] = "!";
118 const char EXP_CHARS
[] = "eE";
119 const char FLT_CHARS
[] = "dD";
121 static FRV_VLIW vliw
;
123 /* Default machine */
125 #ifdef DEFAULT_CPU_FRV
126 #define DEFAULT_MACHINE bfd_mach_frv
127 #define DEFAULT_FLAGS EF_FRV_CPU_GENERIC
130 #ifdef DEFAULT_CPU_FR300
131 #define DEFAULT_MACHINE bfd_mach_fr300
132 #define DEFAULT_FLAGS EF_FRV_CPU_FR300
135 #ifdef DEFAULT_CPU_SIMPLE
136 #define DEFAULT_MACHINE bfd_mach_frvsimple
137 #define DEFAULT_FLAGS EF_FRV_CPU_SIMPLE
140 #ifdef DEFAULT_CPU_TOMCAT
141 #define DEFAULT_MACHINE bfd_mach_frvtomcat
142 #define DEFAULT_FLAGS EF_FRV_CPU_TOMCAT
145 #ifdef DEFAULT_CPU_FR400
146 #define DEFAULT_MACHINE bfd_mach_fr400
147 #define DEFAULT_FLAGS EF_FRV_CPU_FR400
150 #ifdef DEFAULT_CPU_FR550
151 #define DEFAULT_MACHINE bfd_mach_fr550
152 #define DEFAULT_FLAGS EF_FRV_CPU_FR550
155 #define DEFAULT_MACHINE bfd_mach_fr500
156 #define DEFAULT_FLAGS EF_FRV_CPU_FR500
165 # define DEFAULT_FDPIC EF_FRV_FDPIC
167 # define DEFAULT_FDPIC 0
170 static unsigned long frv_mach
= bfd_mach_frv
;
171 static bool fr400_audio
;
173 /* Flags to set in the elf header */
174 static flagword frv_flags
= DEFAULT_FLAGS
| DEFAULT_FDPIC
;
176 static int frv_user_set_flags_p
= 0;
177 static int frv_pic_p
= 0;
178 static const char *frv_pic_flag
= DEFAULT_FDPIC
? "-mfdpic" : (const char *)0;
180 /* Print tomcat-specific debugging info. */
181 static int tomcat_debug
= 0;
183 /* Tomcat-specific NOP statistics. */
184 static int tomcat_stats
= 0;
185 static int tomcat_doubles
= 0;
186 static int tomcat_singles
= 0;
188 /* Forward reference to static functions */
189 static void frv_set_flags (int);
190 static void frv_pic_ptr (int);
192 /* The target specific pseudo-ops which we support. */
193 const pseudo_typeS md_pseudo_table
[] =
195 { "eflags", frv_set_flags
, 0 },
197 { "picptr", frv_pic_ptr
, 4 },
202 #define FRV_SHORTOPTS "G:"
203 const char * md_shortopts
= FRV_SHORTOPTS
;
205 #define OPTION_GPR_32 (OPTION_MD_BASE)
206 #define OPTION_GPR_64 (OPTION_MD_BASE + 1)
207 #define OPTION_FPR_32 (OPTION_MD_BASE + 2)
208 #define OPTION_FPR_64 (OPTION_MD_BASE + 3)
209 #define OPTION_SOFT_FLOAT (OPTION_MD_BASE + 4)
210 #define OPTION_DWORD_YES (OPTION_MD_BASE + 5)
211 #define OPTION_DWORD_NO (OPTION_MD_BASE + 6)
212 #define OPTION_DOUBLE (OPTION_MD_BASE + 7)
213 #define OPTION_NO_DOUBLE (OPTION_MD_BASE + 8)
214 #define OPTION_MEDIA (OPTION_MD_BASE + 9)
215 #define OPTION_NO_MEDIA (OPTION_MD_BASE + 10)
216 #define OPTION_CPU (OPTION_MD_BASE + 11)
217 #define OPTION_PIC (OPTION_MD_BASE + 12)
218 #define OPTION_BIGPIC (OPTION_MD_BASE + 13)
219 #define OPTION_LIBPIC (OPTION_MD_BASE + 14)
220 #define OPTION_MULADD (OPTION_MD_BASE + 15)
221 #define OPTION_NO_MULADD (OPTION_MD_BASE + 16)
222 #define OPTION_TOMCAT_DEBUG (OPTION_MD_BASE + 17)
223 #define OPTION_TOMCAT_STATS (OPTION_MD_BASE + 18)
224 #define OPTION_PACK (OPTION_MD_BASE + 19)
225 #define OPTION_NO_PACK (OPTION_MD_BASE + 20)
226 #define OPTION_FDPIC (OPTION_MD_BASE + 21)
227 #define OPTION_NOPIC (OPTION_MD_BASE + 22)
229 struct option md_longopts
[] =
231 { "mgpr-32", no_argument
, NULL
, OPTION_GPR_32
},
232 { "mgpr-64", no_argument
, NULL
, OPTION_GPR_64
},
233 { "mfpr-32", no_argument
, NULL
, OPTION_FPR_32
},
234 { "mfpr-64", no_argument
, NULL
, OPTION_FPR_64
},
235 { "mhard-float", no_argument
, NULL
, OPTION_FPR_64
},
236 { "msoft-float", no_argument
, NULL
, OPTION_SOFT_FLOAT
},
237 { "mdword", no_argument
, NULL
, OPTION_DWORD_YES
},
238 { "mno-dword", no_argument
, NULL
, OPTION_DWORD_NO
},
239 { "mdouble", no_argument
, NULL
, OPTION_DOUBLE
},
240 { "mno-double", no_argument
, NULL
, OPTION_NO_DOUBLE
},
241 { "mmedia", no_argument
, NULL
, OPTION_MEDIA
},
242 { "mno-media", no_argument
, NULL
, OPTION_NO_MEDIA
},
243 { "mcpu", required_argument
, NULL
, OPTION_CPU
},
244 { "mpic", no_argument
, NULL
, OPTION_PIC
},
245 { "mPIC", no_argument
, NULL
, OPTION_BIGPIC
},
246 { "mlibrary-pic", no_argument
, NULL
, OPTION_LIBPIC
},
247 { "mmuladd", no_argument
, NULL
, OPTION_MULADD
},
248 { "mno-muladd", no_argument
, NULL
, OPTION_NO_MULADD
},
249 { "mtomcat-debug", no_argument
, NULL
, OPTION_TOMCAT_DEBUG
},
250 { "mtomcat-stats", no_argument
, NULL
, OPTION_TOMCAT_STATS
},
251 { "mpack", no_argument
, NULL
, OPTION_PACK
},
252 { "mno-pack", no_argument
, NULL
, OPTION_NO_PACK
},
253 { "mfdpic", no_argument
, NULL
, OPTION_FDPIC
},
254 { "mnopic", no_argument
, NULL
, OPTION_NOPIC
},
255 { NULL
, no_argument
, NULL
, 0 },
258 size_t md_longopts_size
= sizeof (md_longopts
);
260 /* What value to give to bfd_set_gp_size. */
261 static int g_switch_value
= 8;
264 md_parse_option (int c
, const char *arg
)
272 g_switch_value
= atoi (arg
);
273 if (! g_switch_value
)
274 frv_flags
|= EF_FRV_G0
;
278 frv_flags
= (frv_flags
& ~EF_FRV_GPR_MASK
) | EF_FRV_GPR_32
;
282 frv_flags
= (frv_flags
& ~EF_FRV_GPR_MASK
) | EF_FRV_GPR_64
;
286 frv_flags
= (frv_flags
& ~EF_FRV_FPR_MASK
) | EF_FRV_FPR_32
;
290 frv_flags
= (frv_flags
& ~EF_FRV_FPR_MASK
) | EF_FRV_FPR_64
;
293 case OPTION_SOFT_FLOAT
:
294 frv_flags
= (frv_flags
& ~EF_FRV_FPR_MASK
) | EF_FRV_FPR_NONE
;
297 case OPTION_DWORD_YES
:
298 frv_flags
= (frv_flags
& ~EF_FRV_DWORD_MASK
) | EF_FRV_DWORD_YES
;
301 case OPTION_DWORD_NO
:
302 frv_flags
= (frv_flags
& ~EF_FRV_DWORD_MASK
) | EF_FRV_DWORD_NO
;
306 frv_flags
|= EF_FRV_DOUBLE
;
309 case OPTION_NO_DOUBLE
:
310 frv_flags
&= ~EF_FRV_DOUBLE
;
314 frv_flags
|= EF_FRV_MEDIA
;
317 case OPTION_NO_MEDIA
:
318 frv_flags
&= ~EF_FRV_MEDIA
;
322 frv_flags
|= EF_FRV_MULADD
;
325 case OPTION_NO_MULADD
:
326 frv_flags
&= ~EF_FRV_MULADD
;
330 frv_flags
&= ~EF_FRV_NOPACK
;
334 frv_flags
|= EF_FRV_NOPACK
;
340 int cpu_flags
= EF_FRV_CPU_GENERIC
;
342 /* Identify the processor type */
344 if (strcmp (p
, "frv") == 0)
346 cpu_flags
= EF_FRV_CPU_GENERIC
;
347 frv_mach
= bfd_mach_frv
;
350 else if (strcmp (p
, "fr500") == 0)
352 cpu_flags
= EF_FRV_CPU_FR500
;
353 frv_mach
= bfd_mach_fr500
;
356 else if (strcmp (p
, "fr550") == 0)
358 cpu_flags
= EF_FRV_CPU_FR550
;
359 frv_mach
= bfd_mach_fr550
;
362 else if (strcmp (p
, "fr450") == 0)
364 cpu_flags
= EF_FRV_CPU_FR450
;
365 frv_mach
= bfd_mach_fr450
;
368 else if (strcmp (p
, "fr405") == 0)
370 cpu_flags
= EF_FRV_CPU_FR405
;
371 frv_mach
= bfd_mach_fr400
;
375 else if (strcmp (p
, "fr400") == 0)
377 cpu_flags
= EF_FRV_CPU_FR400
;
378 frv_mach
= bfd_mach_fr400
;
382 else if (strcmp (p
, "fr300") == 0)
384 cpu_flags
= EF_FRV_CPU_FR300
;
385 frv_mach
= bfd_mach_fr300
;
388 else if (strcmp (p
, "simple") == 0)
390 cpu_flags
= EF_FRV_CPU_SIMPLE
;
391 frv_mach
= bfd_mach_frvsimple
;
392 frv_flags
|= EF_FRV_NOPACK
;
395 else if (strcmp (p
, "tomcat") == 0)
397 cpu_flags
= EF_FRV_CPU_TOMCAT
;
398 frv_mach
= bfd_mach_frvtomcat
;
403 as_fatal (_("Unknown cpu -mcpu=%s"), arg
);
407 frv_flags
= (frv_flags
& ~EF_FRV_CPU_MASK
) | cpu_flags
;
412 frv_flags
|= EF_FRV_PIC
;
414 frv_pic_flag
= "-fpic";
418 frv_flags
|= EF_FRV_BIGPIC
;
420 frv_pic_flag
= "-fPIC";
424 frv_flags
|= (EF_FRV_LIBPIC
| EF_FRV_G0
);
426 frv_pic_flag
= "-mlibrary-pic";
431 frv_flags
|= EF_FRV_FDPIC
;
432 frv_pic_flag
= "-mfdpic";
436 frv_flags
&= ~(EF_FRV_FDPIC
| EF_FRV_PIC
437 | EF_FRV_BIGPIC
| EF_FRV_LIBPIC
);
441 case OPTION_TOMCAT_DEBUG
:
445 case OPTION_TOMCAT_STATS
:
454 md_show_usage (FILE * stream
)
456 fprintf (stream
, _("FRV specific command line options:\n"));
457 fprintf (stream
, _("-G n Put data <= n bytes in the small data area\n"));
458 fprintf (stream
, _("-mgpr-32 Mark generated file as only using 32 GPRs\n"));
459 fprintf (stream
, _("-mgpr-64 Mark generated file as using all 64 GPRs\n"));
460 fprintf (stream
, _("-mfpr-32 Mark generated file as only using 32 FPRs\n"));
461 fprintf (stream
, _("-mfpr-64 Mark generated file as using all 64 FPRs\n"));
462 fprintf (stream
, _("-msoft-float Mark generated file as using software FP\n"));
463 fprintf (stream
, _("-mdword Mark generated file as using a 8-byte stack alignment\n"));
464 fprintf (stream
, _("-mno-dword Mark generated file as using a 4-byte stack alignment\n"));
465 fprintf (stream
, _("-mdouble Mark generated file as using double precision FP insns\n"));
466 fprintf (stream
, _("-mmedia Mark generated file as using media insns\n"));
467 fprintf (stream
, _("-mmuladd Mark generated file as using multiply add/subtract insns\n"));
468 fprintf (stream
, _("-mpack Allow instructions to be packed\n"));
469 fprintf (stream
, _("-mno-pack Do not allow instructions to be packed\n"));
470 fprintf (stream
, _("-mpic Mark generated file as using small position independent code\n"));
471 fprintf (stream
, _("-mPIC Mark generated file as using large position independent code\n"));
472 fprintf (stream
, _("-mlibrary-pic Mark generated file as using position independent code for libraries\n"));
473 fprintf (stream
, _("-mfdpic Assemble for the FDPIC ABI\n"));
474 fprintf (stream
, _("-mnopic Disable -mpic, -mPIC, -mlibrary-pic and -mfdpic\n"));
475 fprintf (stream
, _("-mcpu={fr500|fr550|fr400|fr405|fr450|fr300|frv|simple|tomcat}\n"));
476 fprintf (stream
, _(" Record the cpu type\n"));
477 fprintf (stream
, _("-mtomcat-stats Print out stats for tomcat workarounds\n"));
478 fprintf (stream
, _("-mtomcat-debug Debug tomcat workarounds\n"));
485 /* Initialize the `cgen' interface. */
487 /* Set the machine number and endian. */
488 gas_cgen_cpu_desc
= frv_cgen_cpu_open (CGEN_CPU_OPEN_MACHS
, 0,
489 CGEN_CPU_OPEN_ENDIAN
,
492 frv_cgen_init_asm (gas_cgen_cpu_desc
);
494 /* This is a callback from cgen to gas to parse operands. */
495 cgen_set_parse_operand_fn (gas_cgen_cpu_desc
, gas_cgen_parse_operand
);
497 /* Set the ELF flags if desired. */
499 bfd_set_private_flags (stdoutput
, frv_flags
);
501 /* Set the machine type */
502 bfd_default_set_arch_mach (stdoutput
, bfd_arch_frv
, frv_mach
);
504 /* Set up gp size so we can put local common items in .sbss */
505 bfd_set_gp_size (stdoutput
, g_switch_value
);
507 frv_vliw_reset (& vliw
, frv_mach
, frv_flags
);
511 frv_md_fdpic_enabled (void)
513 return (frv_flags
& EF_FRV_FDPIC
) != 0;
518 static struct vliw_insn_list
*
519 frv_insert_vliw_insn (bool count
)
521 struct vliw_insn_list
*vliw_insn_list_entry
;
522 struct vliw_chain
*vliw_chain_entry
;
524 if (current_vliw_chain
== NULL
)
526 vliw_chain_entry
= XNEW (struct vliw_chain
);
527 vliw_chain_entry
->insn_count
= 0;
528 vliw_chain_entry
->insn_list
= NULL
;
529 vliw_chain_entry
->next
= NULL
;
530 vliw_chain_entry
->num
= chain_num
++;
533 vliw_chain_top
= vliw_chain_entry
;
534 current_vliw_chain
= vliw_chain_entry
;
535 if (previous_vliw_chain
)
536 previous_vliw_chain
->next
= vliw_chain_entry
;
539 vliw_insn_list_entry
= XNEW (struct vliw_insn_list
);
540 vliw_insn_list_entry
->type
= VLIW_GENERIC_TYPE
;
541 vliw_insn_list_entry
->insn
= NULL
;
542 vliw_insn_list_entry
->sym
= NULL
;
543 vliw_insn_list_entry
->snop_frag
= NULL
;
544 vliw_insn_list_entry
->dnop_frag
= NULL
;
545 vliw_insn_list_entry
->next
= NULL
;
548 current_vliw_chain
->insn_count
++;
550 if (current_vliw_insn
)
551 current_vliw_insn
->next
= vliw_insn_list_entry
;
552 current_vliw_insn
= vliw_insn_list_entry
;
554 if (!current_vliw_chain
->insn_list
)
555 current_vliw_chain
->insn_list
= current_vliw_insn
;
557 return vliw_insn_list_entry
;
560 /* Identify the following cases:
562 1) A VLIW insn that contains both a branch and the branch destination.
563 This requires the insertion of two vliw instructions before the
564 branch. The first consists of two nops. The second consists of
567 2) A single instruction VLIW insn which is the destination of a branch
568 that is in the next VLIW insn. This requires the insertion of a vliw
569 insn containing two nops before the branch.
571 3) A double instruction VLIW insn which contains the destination of a
572 branch that is in the next VLIW insn. This requires the insertion of
573 a VLIW insn containing a single nop before the branch.
575 4) A single instruction VLIW insn which contains branch destination (x),
576 followed by a single instruction VLIW insn which does not contain
577 the branch to (x), followed by a VLIW insn which does contain the branch
578 to (x). This requires the insertion of a VLIW insn containing a single
579 nop before the VLIW instruction containing the branch.
582 #define FRV_IS_NOP(insn) (insn.buffer[0] == FRV_NOP_PACK || insn.buffer[0] == FRV_NOP_NOPACK)
583 #define FRV_NOP_PACK 0x00880000 /* ori.p gr0,0,gr0 */
584 #define FRV_NOP_NOPACK 0x80880000 /* ori gr0,0,gr0 */
586 /* Check a vliw insn for an insn of type containing the sym passed in label_sym. */
588 static struct vliw_insn_list
*
589 frv_find_in_vliw (enum vliw_insn_type vliw_insn_type
,
590 struct vliw_chain
*this_chain
,
594 struct vliw_insn_list
*the_insn
;
599 for (the_insn
= this_chain
->insn_list
; the_insn
; the_insn
= the_insn
->next
)
601 if (the_insn
->type
== vliw_insn_type
602 && the_insn
->sym
== label_sym
)
611 /* A Vliw insn containing a single nop insn. */
614 /* A Vliw insn containing two nop insns. */
617 /* Two vliw insns. The first containing two nop insns.
618 The second contain a single nop insn. */
619 VLIW_DOUBLE_THEN_SINGLE_NOP
623 frv_debug_tomcat (struct vliw_chain
*start_chain
)
625 struct vliw_chain
*this_chain
;
626 struct vliw_insn_list
*this_insn
;
629 for (this_chain
= start_chain
; this_chain
; this_chain
= this_chain
->next
, i
++)
631 fprintf (stderr
, "\nVliw Insn #%d, #insns: %d\n", i
, this_chain
->insn_count
);
633 for (this_insn
= this_chain
->insn_list
; this_insn
; this_insn
= this_insn
->next
)
635 if (this_insn
->type
== VLIW_LABEL_TYPE
)
636 fprintf (stderr
, "Label Value: %p\n", this_insn
->sym
);
637 else if (this_insn
->type
== VLIW_BRANCH_TYPE
)
638 fprintf (stderr
, "%s to %p\n", this_insn
->insn
->base
->name
, this_insn
->sym
);
639 else if (this_insn
->type
== VLIW_BRANCH_HAS_NOPS
)
640 fprintf (stderr
, "nop'd %s to %p\n", this_insn
->insn
->base
->name
, this_insn
->sym
);
641 else if (this_insn
->type
== VLIW_NOP_TYPE
)
642 fprintf (stderr
, "Nop\n");
644 fprintf (stderr
, " %s\n", this_insn
->insn
->base
->name
);
650 frv_adjust_vliw_count (struct vliw_chain
*this_chain
)
652 struct vliw_insn_list
*this_insn
;
654 this_chain
->insn_count
= 0;
656 for (this_insn
= this_chain
->insn_list
;
658 this_insn
= this_insn
->next
)
660 if (this_insn
->type
!= VLIW_LABEL_TYPE
)
661 this_chain
->insn_count
++;
666 /* Insert the desired nop combination in the vliw chain before insert_before_insn.
667 Rechain the vliw insn. */
669 static struct vliw_chain
*
670 frv_tomcat_shuffle (enum vliw_nop_type this_nop_type
,
671 struct vliw_chain
*vliw_to_split
,
672 struct vliw_insn_list
*insert_before_insn
)
675 bool pack_prev
= false;
676 struct vliw_chain
*return_me
= NULL
;
677 struct vliw_insn_list
*prev_insn
= NULL
;
678 struct vliw_insn_list
*curr_insn
= vliw_to_split
->insn_list
;
680 struct vliw_chain
*double_nop
= XNEW (struct vliw_chain
);
681 struct vliw_chain
*single_nop
= XNEW (struct vliw_chain
);
682 struct vliw_chain
*second_part
= XNEW (struct vliw_chain
);
683 struct vliw_chain
*curr_vliw
= vliw_chain_top
;
684 struct vliw_chain
*prev_vliw
= NULL
;
686 while (curr_insn
&& curr_insn
!= insert_before_insn
)
688 /* We can't set the packing bit on a label. If we have the case
692 branch that needs nops
693 Then don't set pack bit later. */
695 if (curr_insn
->type
!= VLIW_LABEL_TYPE
)
697 prev_insn
= curr_insn
;
698 curr_insn
= curr_insn
->next
;
701 while (curr_vliw
&& curr_vliw
!= vliw_to_split
)
703 prev_vliw
= curr_vliw
;
704 curr_vliw
= curr_vliw
->next
;
707 switch (this_nop_type
)
709 case VLIW_SINGLE_NOP
:
712 /* Branch is first, Insert the NOP prior to this vliw insn. */
714 prev_vliw
->next
= single_nop
;
716 vliw_chain_top
= single_nop
;
717 single_nop
->next
= vliw_to_split
;
718 vliw_to_split
->insn_list
->type
= VLIW_BRANCH_HAS_NOPS
;
719 return_me
= vliw_to_split
;
723 /* Set the packing bit on the previous insn. */
726 char *buffer
= prev_insn
->address
;
729 /* The branch is in the middle. Split this vliw insn into first
730 and second parts. Insert the NOP between. */
732 second_part
->insn_list
= insert_before_insn
;
733 second_part
->insn_list
->type
= VLIW_BRANCH_HAS_NOPS
;
734 second_part
->next
= vliw_to_split
->next
;
735 frv_adjust_vliw_count (second_part
);
737 single_nop
->next
= second_part
;
739 vliw_to_split
->next
= single_nop
;
740 prev_insn
->next
= NULL
;
742 return_me
= second_part
;
743 frv_adjust_vliw_count (vliw_to_split
);
747 case VLIW_DOUBLE_NOP
:
750 /* Branch is first, Insert the NOP prior to this vliw insn. */
752 prev_vliw
->next
= double_nop
;
754 vliw_chain_top
= double_nop
;
756 double_nop
->next
= vliw_to_split
;
757 return_me
= vliw_to_split
;
758 vliw_to_split
->insn_list
->type
= VLIW_BRANCH_HAS_NOPS
;
762 /* Set the packing bit on the previous insn. */
765 char *buffer
= prev_insn
->address
;
769 /* The branch is in the middle. Split this vliw insn into first
770 and second parts. Insert the NOP in between. */
771 second_part
->insn_list
= insert_before_insn
;
772 second_part
->insn_list
->type
= VLIW_BRANCH_HAS_NOPS
;
773 second_part
->next
= vliw_to_split
->next
;
774 frv_adjust_vliw_count (second_part
);
776 double_nop
->next
= second_part
;
778 vliw_to_split
->next
= single_nop
;
779 prev_insn
->next
= NULL
;
780 frv_adjust_vliw_count (vliw_to_split
);
782 return_me
= second_part
;
786 case VLIW_DOUBLE_THEN_SINGLE_NOP
:
787 double_nop
->next
= single_nop
;
788 double_nop
->insn_count
= 2;
789 double_nop
->insn_list
= &double_nop_insn
;
790 single_nop
->insn_count
= 1;
791 single_nop
->insn_list
= &single_nop_insn
;
795 /* The branch is the first insn in this vliw. Don't split the vliw. Insert
796 the nops prior to this vliw. */
798 prev_vliw
->next
= double_nop
;
800 vliw_chain_top
= double_nop
;
802 single_nop
->next
= vliw_to_split
;
803 return_me
= vliw_to_split
;
804 vliw_to_split
->insn_list
->type
= VLIW_BRANCH_HAS_NOPS
;
808 /* Set the packing bit on the previous insn. */
811 char *buffer
= prev_insn
->address
;
815 /* The branch is in the middle of this vliw insn. Split into first and
816 second parts. Insert the nop vliws in between. */
817 second_part
->insn_list
= insert_before_insn
;
818 second_part
->insn_list
->type
= VLIW_BRANCH_HAS_NOPS
;
819 second_part
->next
= vliw_to_split
->next
;
820 frv_adjust_vliw_count (second_part
);
822 single_nop
->next
= second_part
;
824 vliw_to_split
->next
= double_nop
;
825 prev_insn
->next
= NULL
;
826 frv_adjust_vliw_count (vliw_to_split
);
828 return_me
= second_part
;
837 frv_tomcat_analyze_vliw_chains (void)
839 struct vliw_chain
*vliw1
= NULL
;
840 struct vliw_chain
*vliw2
= NULL
;
841 struct vliw_chain
*vliw3
= NULL
;
843 struct vliw_insn_list
*this_insn
= NULL
;
844 struct vliw_insn_list
*temp_insn
= NULL
;
846 /* We potentially need to look at three VLIW insns to determine if the
847 workaround is required. Set them up. Ignore existing nops during analysis. */
849 #define FRV_SET_VLIW_WINDOW(VLIW1, VLIW2, VLIW3) \
850 if (VLIW1 && VLIW1->next) \
851 VLIW2 = VLIW1->next; \
854 if (VLIW2 && VLIW2->next) \
855 VLIW3 = VLIW2->next; \
859 vliw1
= vliw_chain_top
;
863 FRV_SET_VLIW_WINDOW (vliw1
, vliw2
, vliw3
);
868 if (vliw1
->insn_count
== 1)
870 /* check vliw1 for a label. */
871 if (vliw1
->insn_list
->type
== VLIW_LABEL_TYPE
)
873 temp_insn
= frv_find_in_vliw (VLIW_BRANCH_TYPE
, vliw2
, vliw1
->insn_list
->sym
);
876 vliw1
= frv_tomcat_shuffle (VLIW_DOUBLE_NOP
, vliw2
, vliw1
->insn_list
);
877 temp_insn
->dnop_frag
->fr_subtype
= NOP_KEEP
;
884 && vliw2
->insn_count
== 1
885 && (temp_insn
= frv_find_in_vliw (VLIW_BRANCH_TYPE
, vliw3
, vliw1
->insn_list
->sym
)) != NULL
)
887 temp_insn
->snop_frag
->fr_subtype
= NOP_KEEP
;
888 vliw1
= frv_tomcat_shuffle (VLIW_SINGLE_NOP
, vliw3
, vliw3
->insn_list
);
896 if (vliw1
->insn_count
== 2)
898 /* Check vliw1 for a label. */
899 for (this_insn
= vliw1
->insn_list
; this_insn
; this_insn
= this_insn
->next
)
901 if (this_insn
->type
== VLIW_LABEL_TYPE
)
903 if ((temp_insn
= frv_find_in_vliw (VLIW_BRANCH_TYPE
, vliw2
, this_insn
->sym
)) != NULL
)
905 temp_insn
->snop_frag
->fr_subtype
= NOP_KEEP
;
906 vliw1
= frv_tomcat_shuffle (VLIW_SINGLE_NOP
, vliw2
, this_insn
);
916 /* Examine each insn in this VLIW. Look for the workaround criteria. */
917 for (this_insn
= vliw1
->insn_list
; this_insn
; this_insn
= this_insn
->next
)
919 /* Don't look at labels or nops. */
921 && (this_insn
->type
== VLIW_LABEL_TYPE
922 || this_insn
->type
== VLIW_NOP_TYPE
923 || this_insn
->type
== VLIW_BRANCH_HAS_NOPS
))
924 this_insn
= this_insn
->next
;
932 if (frv_is_branch_insn (this_insn
->insn
))
934 if ((temp_insn
= frv_find_in_vliw (VLIW_LABEL_TYPE
, vliw1
, this_insn
->sym
)) != NULL
)
936 /* Insert [nop/nop] [nop] before branch. */
937 this_insn
->snop_frag
->fr_subtype
= NOP_KEEP
;
938 this_insn
->dnop_frag
->fr_subtype
= NOP_KEEP
;
939 vliw1
= frv_tomcat_shuffle (VLIW_DOUBLE_THEN_SINGLE_NOP
, vliw1
, this_insn
);
946 /* This vliw insn checks out okay. Take a look at the next one. */
952 frv_tomcat_workaround (void)
954 if (frv_mach
!= bfd_mach_frvtomcat
)
958 frv_debug_tomcat (vliw_chain_top
);
960 frv_tomcat_analyze_vliw_chains ();
964 fprintf (stderr
, "Inserted %d Single Nops\n", tomcat_singles
);
965 fprintf (stderr
, "Inserted %d Double Nops\n", tomcat_doubles
);
970 fr550_check_insn_acc_range (frv_insn
*insn
, int low
, int hi
)
973 switch (CGEN_INSN_NUM (insn
->insn
))
975 case FRV_INSN_MADDACCS
:
976 case FRV_INSN_MSUBACCS
:
977 case FRV_INSN_MDADDACCS
:
978 case FRV_INSN_MDSUBACCS
:
979 case FRV_INSN_MASACCS
:
980 case FRV_INSN_MDASACCS
:
981 acc
= insn
->fields
.f_ACC40Si
;
982 if (acc
< low
|| acc
> hi
)
983 return 1; /* out of range */
984 acc
= insn
->fields
.f_ACC40Sk
;
985 if (acc
< low
|| acc
> hi
)
986 return 1; /* out of range */
988 case FRV_INSN_MMULHS
:
989 case FRV_INSN_MMULHU
:
990 case FRV_INSN_MMULXHS
:
991 case FRV_INSN_MMULXHU
:
992 case FRV_INSN_CMMULHS
:
993 case FRV_INSN_CMMULHU
:
994 case FRV_INSN_MQMULHS
:
995 case FRV_INSN_MQMULHU
:
996 case FRV_INSN_MQMULXHS
:
997 case FRV_INSN_MQMULXHU
:
998 case FRV_INSN_CMQMULHS
:
999 case FRV_INSN_CMQMULHU
:
1000 case FRV_INSN_MMACHS
:
1001 case FRV_INSN_MMRDHS
:
1002 case FRV_INSN_CMMACHS
:
1003 case FRV_INSN_MQMACHS
:
1004 case FRV_INSN_CMQMACHS
:
1005 case FRV_INSN_MQXMACHS
:
1006 case FRV_INSN_MQXMACXHS
:
1007 case FRV_INSN_MQMACXHS
:
1008 case FRV_INSN_MCPXRS
:
1009 case FRV_INSN_MCPXIS
:
1010 case FRV_INSN_CMCPXRS
:
1011 case FRV_INSN_CMCPXIS
:
1012 case FRV_INSN_MQCPXRS
:
1013 case FRV_INSN_MQCPXIS
:
1014 acc
= insn
->fields
.f_ACC40Sk
;
1015 if (acc
< low
|| acc
> hi
)
1016 return 1; /* out of range */
1018 case FRV_INSN_MMACHU
:
1019 case FRV_INSN_MMRDHU
:
1020 case FRV_INSN_CMMACHU
:
1021 case FRV_INSN_MQMACHU
:
1022 case FRV_INSN_CMQMACHU
:
1023 case FRV_INSN_MCPXRU
:
1024 case FRV_INSN_MCPXIU
:
1025 case FRV_INSN_CMCPXRU
:
1026 case FRV_INSN_CMCPXIU
:
1027 case FRV_INSN_MQCPXRU
:
1028 case FRV_INSN_MQCPXIU
:
1029 acc
= insn
->fields
.f_ACC40Uk
;
1030 if (acc
< low
|| acc
> hi
)
1031 return 1; /* out of range */
1036 return 0; /* all is ok */
1040 fr550_check_acc_range (FRV_VLIW
*vlw
, frv_insn
*insn
)
1042 switch ((*vlw
->current_vliw
)[vlw
->next_slot
- 1])
1046 return fr550_check_insn_acc_range (insn
, 0, 3);
1049 return fr550_check_insn_acc_range (insn
, 4, 7);
1053 return 0; /* all is ok */
1056 /* Return true if the target implements instruction INSN. */
1059 target_implements_insn_p (const CGEN_INSN
*insn
)
1064 /* bfd_mach_frv or generic. */
1067 case bfd_mach_fr300
:
1068 case bfd_mach_frvsimple
:
1069 return CGEN_INSN_MACH_HAS_P (insn
, MACH_SIMPLE
);
1071 case bfd_mach_fr400
:
1072 return ((fr400_audio
|| !CGEN_INSN_ATTR_VALUE (insn
, CGEN_INSN_AUDIO
))
1073 && CGEN_INSN_MACH_HAS_P (insn
, MACH_FR400
));
1075 case bfd_mach_fr450
:
1076 return CGEN_INSN_MACH_HAS_P (insn
, MACH_FR450
);
1078 case bfd_mach_fr500
:
1079 return CGEN_INSN_MACH_HAS_P (insn
, MACH_FR500
);
1081 case bfd_mach_fr550
:
1082 return CGEN_INSN_MACH_HAS_P (insn
, MACH_FR550
);
1087 md_assemble (char *str
)
1091 int packing_constraint
;
1092 finished_insnS finished_insn
;
1093 fragS
*double_nop_frag
= NULL
;
1094 fragS
*single_nop_frag
= NULL
;
1095 struct vliw_insn_list
*vliw_insn_list_entry
= NULL
;
1097 /* Initialize GAS's cgen interface for a new instruction. */
1098 gas_cgen_init_parse ();
1100 memset (&insn
, 0, sizeof (insn
));
1102 insn
.insn
= frv_cgen_assemble_insn
1103 (gas_cgen_cpu_desc
, str
, & insn
.fields
, insn
.buffer
, &errmsg
);
1107 as_bad ("%s", errmsg
);
1111 /* If the cpu is tomcat, then we need to insert nops to workaround
1112 hardware limitations. We need to keep track of each vliw unit
1113 and examine the length of the unit and the individual insns
1114 within the unit to determine the number and location of the
1116 if (frv_mach
== bfd_mach_frvtomcat
)
1118 /* If we've just finished a VLIW insn OR this is a branch,
1119 then start up a new frag. Fill it with nops. We will get rid
1120 of those that are not required after we've seen all of the
1121 instructions but before we start resolving fixups. */
1122 if ( !FRV_IS_NOP (insn
)
1123 && (frv_is_branch_insn (insn
.insn
) || insn
.fields
.f_pack
))
1127 frag_wane (frag_now
);
1129 double_nop_frag
= frag_now
;
1130 buffer
= frag_var (rs_machine_dependent
, 8, 8, NOP_DELETE
, NULL
, 0, 0);
1131 md_number_to_chars (buffer
, FRV_NOP_PACK
, 4);
1132 md_number_to_chars (buffer
+4, FRV_NOP_NOPACK
, 4);
1134 frag_wane (frag_now
);
1136 single_nop_frag
= frag_now
;
1137 buffer
= frag_var (rs_machine_dependent
, 4, 4, NOP_DELETE
, NULL
, 0, 0);
1138 md_number_to_chars (buffer
, FRV_NOP_NOPACK
, 4);
1141 vliw_insn_list_entry
= frv_insert_vliw_insn (DO_COUNT
);
1142 vliw_insn_list_entry
->insn
= insn
.insn
;
1143 if (frv_is_branch_insn (insn
.insn
))
1144 vliw_insn_list_entry
->type
= VLIW_BRANCH_TYPE
;
1146 if ( !FRV_IS_NOP (insn
)
1147 && (frv_is_branch_insn (insn
.insn
) || insn
.fields
.f_pack
))
1149 vliw_insn_list_entry
->snop_frag
= single_nop_frag
;
1150 vliw_insn_list_entry
->dnop_frag
= double_nop_frag
;
1154 /* Make sure that this insn does not violate the VLIW packing constraints. */
1155 /* -mno-pack disallows any packing whatsoever. */
1156 if (frv_flags
& EF_FRV_NOPACK
)
1158 if (! insn
.fields
.f_pack
)
1160 as_bad (_("VLIW packing used for -mno-pack"));
1164 /* -mcpu=FRV is an idealized FR-V implementation that supports all of the
1165 instructions, don't do vliw checking. */
1166 else if (frv_mach
!= bfd_mach_frv
)
1168 if (!target_implements_insn_p (insn
.insn
))
1170 as_bad (_("Instruction not supported by this architecture"));
1173 packing_constraint
= frv_vliw_add_insn (& vliw
, insn
.insn
);
1174 if (frv_mach
== bfd_mach_fr550
&& ! packing_constraint
)
1175 packing_constraint
= fr550_check_acc_range (& vliw
, & insn
);
1176 if (insn
.fields
.f_pack
)
1177 frv_vliw_reset (& vliw
, frv_mach
, frv_flags
);
1178 if (packing_constraint
)
1180 as_bad (_("VLIW packing constraint violation"));
1185 /* Doesn't really matter what we pass for RELAX_P here. */
1186 gas_cgen_finish_insn (insn
.insn
, insn
.buffer
,
1187 CGEN_FIELDS_BITSIZE (& insn
.fields
), 1, &finished_insn
);
1190 /* If the cpu is tomcat, then we need to insert nops to workaround
1191 hardware limitations. We need to keep track of each vliw unit
1192 and examine the length of the unit and the individual insns
1193 within the unit to determine the number and location of the
1195 if (frv_mach
== bfd_mach_frvtomcat
)
1197 if (vliw_insn_list_entry
)
1198 vliw_insn_list_entry
->address
= finished_insn
.addr
;
1202 if (insn
.fields
.f_pack
)
1204 /* We've completed a VLIW insn. */
1205 previous_vliw_chain
= current_vliw_chain
;
1206 current_vliw_chain
= NULL
;
1207 current_vliw_insn
= NULL
;
1212 /* The syntax in the manual says constants begin with '#'.
1213 We just ignore it. */
1216 md_operand (expressionS
*expressionP
)
1218 if (* input_line_pointer
== '#')
1220 input_line_pointer
++;
1221 expression (expressionP
);
1226 md_section_align (segT segment
, valueT size
)
1228 int align
= bfd_section_alignment (segment
);
1229 return ((size
+ (1 << align
) - 1) & -(1 << align
));
1233 md_undefined_symbol (char *name ATTRIBUTE_UNUSED
)
1238 /* Interface to relax_segment. */
1240 /* FIXME: Build table by hand, get it working, then machine generate. */
1241 const relax_typeS md_relax_table
[] =
1244 {511 - 2 - 2, -512 - 2 + 2, 0, 2 },
1245 {0x2000000 - 1 - 2, -0x2000000 - 2, 2, 0 },
1246 {0x2000000 - 1 - 2, -0x2000000 - 2, 4, 0 }
1250 frv_relax_frag (fragS
*fragP ATTRIBUTE_UNUSED
, long stretch ATTRIBUTE_UNUSED
)
1255 /* Return an initial guess of the length by which a fragment must grow to
1256 hold a branch to reach its destination.
1257 Also updates fr_type/fr_subtype as necessary.
1259 Called just before doing relaxation.
1260 Any symbol that is now undefined will not become defined.
1261 The guess for fr_var is ACTUALLY the growth beyond fr_fix.
1262 Whatever we do to grow fr_fix or fr_var contributes to our returned value.
1263 Although it may not be explicit in the frag, pretend fr_var starts with a
1267 md_estimate_size_before_relax (fragS
*fragP
, segT segment ATTRIBUTE_UNUSED
)
1269 switch (fragP
->fr_subtype
)
1272 return fragP
->fr_var
;
1280 /* *fragP has been relaxed to its final size, and now needs to have
1281 the bytes inside it modified to conform to the new size.
1283 Called after relaxation is finished.
1284 fragP->fr_type == rs_machine_dependent.
1285 fragP->fr_subtype is the subtype of what the address relaxed to. */
1288 md_convert_frag (bfd
*abfd ATTRIBUTE_UNUSED
,
1289 segT sec ATTRIBUTE_UNUSED
,
1292 switch (fragP
->fr_subtype
)
1299 fragP
->fr_fix
= fragP
->fr_var
;
1305 /* Functions concerning relocs. */
1307 /* The location from which a PC relative jump should be calculated,
1308 given a PC relative reloc. */
1311 md_pcrel_from_section (fixS
*fixP
, segT sec
)
1313 if (TC_FORCE_RELOCATION (fixP
)
1314 || (fixP
->fx_addsy
!= (symbolS
*) NULL
1315 && S_GET_SEGMENT (fixP
->fx_addsy
) != sec
))
1317 /* If we can't adjust this relocation, or if it references a
1318 local symbol in a different section (which
1319 TC_FORCE_RELOCATION can't check), let the linker figure it
1324 return (fixP
->fx_frag
->fr_address
+ fixP
->fx_where
) & ~1;
1327 /* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
1328 Returns BFD_RELOC_NONE if no reloc type can be found.
1329 *FIXP may be modified if desired. */
1331 bfd_reloc_code_real_type
1332 md_cgen_lookup_reloc (const CGEN_INSN
*insn ATTRIBUTE_UNUSED
,
1333 const CGEN_OPERAND
*operand
,
1336 switch (operand
->type
)
1338 case FRV_OPERAND_LABEL16
:
1339 fixP
->fx_pcrel
= true;
1340 return BFD_RELOC_FRV_LABEL16
;
1342 case FRV_OPERAND_LABEL24
:
1343 fixP
->fx_pcrel
= true;
1345 if (fixP
->fx_cgen
.opinfo
!= 0)
1346 return fixP
->fx_cgen
.opinfo
;
1348 return BFD_RELOC_FRV_LABEL24
;
1350 case FRV_OPERAND_UHI16
:
1351 case FRV_OPERAND_ULO16
:
1352 case FRV_OPERAND_SLO16
:
1353 case FRV_OPERAND_CALLANN
:
1354 case FRV_OPERAND_LDANN
:
1355 case FRV_OPERAND_LDDANN
:
1356 /* The relocation type should be recorded in opinfo */
1357 if (fixP
->fx_cgen
.opinfo
!= 0)
1358 return fixP
->fx_cgen
.opinfo
;
1361 case FRV_OPERAND_D12
:
1362 case FRV_OPERAND_S12
:
1363 if (fixP
->fx_cgen
.opinfo
!= 0)
1364 return fixP
->fx_cgen
.opinfo
;
1366 return BFD_RELOC_FRV_GPREL12
;
1368 case FRV_OPERAND_U12
:
1369 return BFD_RELOC_FRV_GPRELU12
;
1374 return BFD_RELOC_NONE
;
1378 /* See whether we need to force a relocation into the output file.
1379 This is used to force out switch and PC relative relocations when
1383 frv_force_relocation (fixS
*fix
)
1385 switch (fix
->fx_r_type
< BFD_RELOC_UNUSED
1386 ? (int) fix
->fx_r_type
1387 : fix
->fx_cgen
.opinfo
)
1389 case BFD_RELOC_FRV_GPREL12
:
1390 case BFD_RELOC_FRV_GPRELU12
:
1391 case BFD_RELOC_FRV_GPREL32
:
1392 case BFD_RELOC_FRV_GPRELHI
:
1393 case BFD_RELOC_FRV_GPRELLO
:
1394 case BFD_RELOC_FRV_GOT12
:
1395 case BFD_RELOC_FRV_GOTHI
:
1396 case BFD_RELOC_FRV_GOTLO
:
1397 case BFD_RELOC_FRV_FUNCDESC_VALUE
:
1398 case BFD_RELOC_FRV_FUNCDESC_GOTOFF12
:
1399 case BFD_RELOC_FRV_FUNCDESC_GOTOFFHI
:
1400 case BFD_RELOC_FRV_FUNCDESC_GOTOFFLO
:
1401 case BFD_RELOC_FRV_GOTOFF12
:
1402 case BFD_RELOC_FRV_GOTOFFHI
:
1403 case BFD_RELOC_FRV_GOTOFFLO
:
1404 case BFD_RELOC_FRV_GETTLSOFF
:
1405 case BFD_RELOC_FRV_TLSDESC_VALUE
:
1406 case BFD_RELOC_FRV_GOTTLSDESC12
:
1407 case BFD_RELOC_FRV_GOTTLSDESCHI
:
1408 case BFD_RELOC_FRV_GOTTLSDESCLO
:
1409 case BFD_RELOC_FRV_TLSMOFF12
:
1410 case BFD_RELOC_FRV_TLSMOFFHI
:
1411 case BFD_RELOC_FRV_TLSMOFFLO
:
1412 case BFD_RELOC_FRV_GOTTLSOFF12
:
1413 case BFD_RELOC_FRV_GOTTLSOFFHI
:
1414 case BFD_RELOC_FRV_GOTTLSOFFLO
:
1415 case BFD_RELOC_FRV_TLSOFF
:
1416 case BFD_RELOC_FRV_TLSDESC_RELAX
:
1417 case BFD_RELOC_FRV_GETTLSOFF_RELAX
:
1418 case BFD_RELOC_FRV_TLSOFF_RELAX
:
1425 return generic_force_reloc (fix
);
1428 /* Apply a fixup that could be resolved within the assembler. */
1431 md_apply_fix (fixS
*fixP
, valueT
*valP
, segT seg
)
1433 if (fixP
->fx_addsy
== 0)
1434 switch (fixP
->fx_cgen
.opinfo
)
1436 case BFD_RELOC_FRV_HI16
:
1439 case BFD_RELOC_FRV_LO16
:
1443 /* We need relocations for these, even if their symbols reduce
1445 case BFD_RELOC_FRV_GPREL12
:
1446 case BFD_RELOC_FRV_GPRELU12
:
1447 case BFD_RELOC_FRV_GPREL32
:
1448 case BFD_RELOC_FRV_GPRELHI
:
1449 case BFD_RELOC_FRV_GPRELLO
:
1450 case BFD_RELOC_FRV_GOT12
:
1451 case BFD_RELOC_FRV_GOTHI
:
1452 case BFD_RELOC_FRV_GOTLO
:
1453 case BFD_RELOC_FRV_FUNCDESC_VALUE
:
1454 case BFD_RELOC_FRV_FUNCDESC_GOTOFF12
:
1455 case BFD_RELOC_FRV_FUNCDESC_GOTOFFHI
:
1456 case BFD_RELOC_FRV_FUNCDESC_GOTOFFLO
:
1457 case BFD_RELOC_FRV_GOTOFF12
:
1458 case BFD_RELOC_FRV_GOTOFFHI
:
1459 case BFD_RELOC_FRV_GOTOFFLO
:
1460 case BFD_RELOC_FRV_GETTLSOFF
:
1461 case BFD_RELOC_FRV_TLSDESC_VALUE
:
1462 case BFD_RELOC_FRV_GOTTLSDESC12
:
1463 case BFD_RELOC_FRV_GOTTLSDESCHI
:
1464 case BFD_RELOC_FRV_GOTTLSDESCLO
:
1465 case BFD_RELOC_FRV_TLSMOFF12
:
1466 case BFD_RELOC_FRV_TLSMOFFHI
:
1467 case BFD_RELOC_FRV_TLSMOFFLO
:
1468 case BFD_RELOC_FRV_GOTTLSOFF12
:
1469 case BFD_RELOC_FRV_GOTTLSOFFHI
:
1470 case BFD_RELOC_FRV_GOTTLSOFFLO
:
1471 case BFD_RELOC_FRV_TLSOFF
:
1472 case BFD_RELOC_FRV_TLSDESC_RELAX
:
1473 case BFD_RELOC_FRV_GETTLSOFF_RELAX
:
1474 case BFD_RELOC_FRV_TLSOFF_RELAX
:
1475 fixP
->fx_addsy
= abs_section_sym
;
1479 switch (fixP
->fx_cgen
.opinfo
)
1481 case BFD_RELOC_FRV_GETTLSOFF
:
1482 case BFD_RELOC_FRV_TLSDESC_VALUE
:
1483 case BFD_RELOC_FRV_GOTTLSDESC12
:
1484 case BFD_RELOC_FRV_GOTTLSDESCHI
:
1485 case BFD_RELOC_FRV_GOTTLSDESCLO
:
1486 case BFD_RELOC_FRV_TLSMOFF12
:
1487 case BFD_RELOC_FRV_TLSMOFFHI
:
1488 case BFD_RELOC_FRV_TLSMOFFLO
:
1489 case BFD_RELOC_FRV_GOTTLSOFF12
:
1490 case BFD_RELOC_FRV_GOTTLSOFFHI
:
1491 case BFD_RELOC_FRV_GOTTLSOFFLO
:
1492 case BFD_RELOC_FRV_TLSOFF
:
1493 case BFD_RELOC_FRV_TLSDESC_RELAX
:
1494 case BFD_RELOC_FRV_GETTLSOFF_RELAX
:
1495 case BFD_RELOC_FRV_TLSOFF_RELAX
:
1496 /* Mark TLS symbols as such. */
1497 if (S_GET_SEGMENT (fixP
->fx_addsy
) != absolute_section
)
1498 S_SET_THREAD_LOCAL (fixP
->fx_addsy
);
1502 gas_cgen_md_apply_fix (fixP
, valP
, seg
);
1507 /* Write a value out to the object file, using the appropriate endianness. */
1510 frv_md_number_to_chars (char *buf
, valueT val
, int n
)
1512 number_to_chars_bigendian (buf
, val
, n
);
1516 md_atof (int type
, char *litP
, int *sizeP
)
1518 return ieee_md_atof (type
, litP
, sizeP
, true);
1522 frv_fix_adjustable (fixS
*fixP
)
1524 bfd_reloc_code_real_type reloc_type
;
1526 if ((int) fixP
->fx_r_type
>= (int) BFD_RELOC_UNUSED
)
1528 const CGEN_INSN
*insn
= NULL
;
1529 int opindex
= (int) fixP
->fx_r_type
- (int) BFD_RELOC_UNUSED
;
1530 const CGEN_OPERAND
*operand
= cgen_operand_lookup_by_num(gas_cgen_cpu_desc
, opindex
);
1531 reloc_type
= md_cgen_lookup_reloc (insn
, operand
, fixP
);
1534 reloc_type
= fixP
->fx_r_type
;
1536 /* We need the symbol name for the VTABLE entries */
1537 if ( reloc_type
== BFD_RELOC_VTABLE_INHERIT
1538 || reloc_type
== BFD_RELOC_VTABLE_ENTRY
1539 || reloc_type
== BFD_RELOC_FRV_GPREL12
1540 || reloc_type
== BFD_RELOC_FRV_GPRELU12
)
1546 /* Allow user to set flags bits. */
1548 frv_set_flags (int arg ATTRIBUTE_UNUSED
)
1550 flagword new_flags
= get_absolute_expression ();
1551 flagword new_mask
= ~ (flagword
)0;
1553 frv_user_set_flags_p
= 1;
1554 if (*input_line_pointer
== ',')
1556 ++input_line_pointer
;
1557 new_mask
= get_absolute_expression ();
1560 frv_flags
= (frv_flags
& ~new_mask
) | (new_flags
& new_mask
);
1561 bfd_set_private_flags (stdoutput
, frv_flags
);
1564 /* Frv specific function to handle 4 byte initializations for pointers that are
1565 considered 'safe' for use with pic support. Until frv_frob_file{,_section}
1566 is run, we encode it a BFD_RELOC_CTOR, and it is turned back into a normal
1567 BFD_RELOC_32 at that time. */
1570 frv_pic_ptr (int nbytes
)
1578 #ifdef md_flush_pending_output
1579 md_flush_pending_output ();
1582 if (is_it_end_of_statement ())
1584 demand_empty_rest_of_line ();
1588 #ifdef md_cons_align
1589 md_cons_align (nbytes
);
1594 bfd_reloc_code_real_type reloc_type
= BFD_RELOC_CTOR
;
1596 if (strncasecmp (input_line_pointer
, "funcdesc(", 9) == 0)
1598 input_line_pointer
+= 9;
1600 if (*input_line_pointer
== ')')
1601 input_line_pointer
++;
1603 as_bad (_("missing ')'"));
1604 reloc_type
= BFD_RELOC_FRV_FUNCDESC
;
1606 else if (strncasecmp (input_line_pointer
, "tlsmoff(", 8) == 0)
1608 input_line_pointer
+= 8;
1610 if (*input_line_pointer
== ')')
1611 input_line_pointer
++;
1613 as_bad (_("missing ')'"));
1614 reloc_type
= BFD_RELOC_FRV_TLSMOFF
;
1621 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
, 4, &exp
, 0,
1624 while (*input_line_pointer
++ == ',');
1626 input_line_pointer
--; /* Put terminator back into stream. */
1627 demand_empty_rest_of_line ();
1633 #define DPRINTF1(A) fprintf (stderr, A)
1634 #define DPRINTF2(A,B) fprintf (stderr, A, B)
1635 #define DPRINTF3(A,B,C) fprintf (stderr, A, B, C)
1639 #define DPRINTF2(A,B)
1640 #define DPRINTF3(A,B,C)
1643 /* Go through a the sections looking for relocations that are problematical for
1644 pic. If not pic, just note that this object can't be linked with pic. If
1645 it is pic, see if it needs to be marked so that it will be fixed up, or if
1646 not possible, issue an error. */
1649 frv_frob_file_section (bfd
*abfd
, asection
*sec
, void *ptr ATTRIBUTE_UNUSED
)
1651 segment_info_type
*seginfo
= seg_info (sec
);
1653 CGEN_CPU_DESC cd
= gas_cgen_cpu_desc
;
1654 flagword flags
= bfd_section_flags (sec
);
1656 /* Skip relocations in known sections (.ctors, .dtors, and .gcc_except_table)
1657 since we can fix those up by hand. */
1658 int known_section_p
= (sec
->name
1659 && sec
->name
[0] == '.'
1660 && ((sec
->name
[1] == 'c'
1661 && strcmp (sec
->name
, ".ctor") == 0)
1662 || (sec
->name
[1] == 'd'
1663 && strcmp (sec
->name
, ".dtor") == 0)
1664 || (sec
->name
[1] == 'g'
1665 && strcmp (sec
->name
, ".gcc_except_table") == 0)));
1667 DPRINTF3 ("\nFrv section %s%s\n", sec
->name
, (known_section_p
) ? ", known section" : "");
1668 if ((flags
& SEC_ALLOC
) == 0)
1670 DPRINTF1 ("\tSkipping non-loaded section\n");
1674 for (fixp
= seginfo
->fix_root
; fixp
; fixp
= fixp
->fx_next
)
1676 symbolS
*s
= fixp
->fx_addsy
;
1677 bfd_reloc_code_real_type reloc
;
1680 const CGEN_OPERAND
*operand
;
1681 const CGEN_INSN
*insn
= fixp
->fx_cgen
.insn
;
1685 DPRINTF1 ("\tSkipping reloc that has already been done\n");
1691 DPRINTF1 ("\tSkipping reloc that is PC relative\n");
1697 DPRINTF1 ("\tSkipping reloc without symbol\n");
1701 if (fixp
->fx_r_type
< BFD_RELOC_UNUSED
)
1704 reloc
= fixp
->fx_r_type
;
1708 opindex
= (int) fixp
->fx_r_type
- (int) BFD_RELOC_UNUSED
;
1709 operand
= cgen_operand_lookup_by_num (cd
, opindex
);
1710 reloc
= md_cgen_lookup_reloc (insn
, operand
, fixp
);
1713 DPRINTF3 ("\treloc %s\t%s", bfd_get_reloc_code_name (reloc
), S_GET_NAME (s
));
1722 /* Skip relocations in known sections (.ctors, .dtors, and
1723 .gcc_except_table) since we can fix those up by hand. Also
1724 skip forward references to constants. Also skip a difference
1725 of two symbols, which still uses the BFD_RELOC_32 at this
1727 if (! known_section_p
1728 && S_GET_SEGMENT (s
) != absolute_section
1730 && (flags
& (SEC_READONLY
| SEC_CODE
)) == 0)
1736 /* FIXME -- should determine if any of the GP relocation really uses
1737 gr16 (which is not pic safe) or not. Right now, assume if we
1738 aren't being compiled with -mpic, the usage is non pic safe, but
1739 is safe with -mpic. */
1740 case BFD_RELOC_FRV_GPREL12
:
1741 case BFD_RELOC_FRV_GPRELU12
:
1742 case BFD_RELOC_FRV_GPREL32
:
1743 case BFD_RELOC_FRV_GPRELHI
:
1744 case BFD_RELOC_FRV_GPRELLO
:
1745 non_pic_p
= ! frv_pic_p
;
1748 case BFD_RELOC_FRV_LO16
:
1749 case BFD_RELOC_FRV_HI16
:
1750 if (S_GET_SEGMENT (s
) != absolute_section
)
1754 case BFD_RELOC_VTABLE_INHERIT
:
1755 case BFD_RELOC_VTABLE_ENTRY
:
1759 /* If this is a blessed BFD_RELOC_32, convert it back to the normal
1761 case BFD_RELOC_CTOR
:
1762 fixp
->fx_r_type
= BFD_RELOC_32
;
1768 DPRINTF1 (" (Non-pic relocation)\n");
1770 as_warn_where (fixp
->fx_file
, fixp
->fx_line
,
1771 _("Relocation %s is not safe for %s"),
1772 bfd_get_reloc_code_name (reloc
), frv_pic_flag
);
1774 else if ((frv_flags
& EF_FRV_NON_PIC_RELOCS
) == 0)
1776 frv_flags
|= EF_FRV_NON_PIC_RELOCS
;
1777 bfd_set_private_flags (abfd
, frv_flags
);
1787 /* After all of the symbols have been adjusted, go over the file looking
1788 for any relocations that pic won't support. */
1791 frv_frob_file (void)
1793 bfd_map_over_sections (stdoutput
, frv_frob_file_section
, (void *) 0);
1797 frv_frob_label (symbolS
*this_label
)
1799 struct vliw_insn_list
*vliw_insn_list_entry
;
1801 dwarf2_emit_label (this_label
);
1802 if (frv_mach
!= bfd_mach_frvtomcat
)
1805 if (now_seg
!= text_section
)
1808 vliw_insn_list_entry
= frv_insert_vliw_insn(DONT_COUNT
);
1809 vliw_insn_list_entry
->type
= VLIW_LABEL_TYPE
;
1810 vliw_insn_list_entry
->sym
= this_label
;
1814 frv_cgen_record_fixup_exp (fragS
*frag
,
1816 const CGEN_INSN
*insn
,
1818 const CGEN_OPERAND
*operand
,
1822 fixS
* fixP
= gas_cgen_record_fixup_exp (frag
, where
, insn
, length
,
1823 operand
, opinfo
, exp
);
1825 if (frv_mach
== bfd_mach_frvtomcat
1826 && current_vliw_insn
1827 && current_vliw_insn
->type
== VLIW_BRANCH_TYPE
1829 current_vliw_insn
->sym
= exp
->X_add_symbol
;