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)
221 #define OPTION_FDPIC (OPTION_MD_BASE + 21)
223 struct option md_longopts
[] =
225 { "mgpr-32", no_argument
, NULL
, OPTION_GPR_32
},
226 { "mgpr-64", no_argument
, NULL
, OPTION_GPR_64
},
227 { "mfpr-32", no_argument
, NULL
, OPTION_FPR_32
},
228 { "mfpr-64", no_argument
, NULL
, OPTION_FPR_64
},
229 { "mhard-float", no_argument
, NULL
, OPTION_FPR_64
},
230 { "msoft-float", no_argument
, NULL
, OPTION_SOFT_FLOAT
},
231 { "mdword", no_argument
, NULL
, OPTION_DWORD_YES
},
232 { "mno-dword", no_argument
, NULL
, OPTION_DWORD_NO
},
233 { "mdouble", no_argument
, NULL
, OPTION_DOUBLE
},
234 { "mno-double", no_argument
, NULL
, OPTION_NO_DOUBLE
},
235 { "mmedia", no_argument
, NULL
, OPTION_MEDIA
},
236 { "mno-media", no_argument
, NULL
, OPTION_NO_MEDIA
},
237 { "mcpu", required_argument
, NULL
, OPTION_CPU
},
238 { "mpic", no_argument
, NULL
, OPTION_PIC
},
239 { "mPIC", no_argument
, NULL
, OPTION_BIGPIC
},
240 { "mlibrary-pic", no_argument
, NULL
, OPTION_LIBPIC
},
241 { "mmuladd", no_argument
, NULL
, OPTION_MULADD
},
242 { "mno-muladd", no_argument
, NULL
, OPTION_NO_MULADD
},
243 { "mtomcat-debug", no_argument
, NULL
, OPTION_TOMCAT_DEBUG
},
244 { "mtomcat-stats", no_argument
, NULL
, OPTION_TOMCAT_STATS
},
245 { "mpack", no_argument
, NULL
, OPTION_PACK
},
246 { "mno-pack", no_argument
, NULL
, OPTION_NO_PACK
},
247 { "mfdpic", no_argument
, NULL
, OPTION_FDPIC
},
248 { NULL
, no_argument
, NULL
, 0 },
251 size_t md_longopts_size
= sizeof (md_longopts
);
253 /* What value to give to bfd_set_gp_size. */
254 static int g_switch_value
= 8;
257 md_parse_option (c
, arg
)
267 g_switch_value
= atoi (arg
);
268 if (! g_switch_value
)
269 frv_flags
|= EF_FRV_G0
;
273 frv_flags
= (frv_flags
& ~EF_FRV_GPR_MASK
) | EF_FRV_GPR_32
;
277 frv_flags
= (frv_flags
& ~EF_FRV_GPR_MASK
) | EF_FRV_GPR_64
;
281 frv_flags
= (frv_flags
& ~EF_FRV_FPR_MASK
) | EF_FRV_FPR_32
;
285 frv_flags
= (frv_flags
& ~EF_FRV_FPR_MASK
) | EF_FRV_FPR_64
;
288 case OPTION_SOFT_FLOAT
:
289 frv_flags
= (frv_flags
& ~EF_FRV_FPR_MASK
) | EF_FRV_FPR_NONE
;
292 case OPTION_DWORD_YES
:
293 frv_flags
= (frv_flags
& ~EF_FRV_DWORD_MASK
) | EF_FRV_DWORD_YES
;
296 case OPTION_DWORD_NO
:
297 frv_flags
= (frv_flags
& ~EF_FRV_DWORD_MASK
) | EF_FRV_DWORD_NO
;
301 frv_flags
|= EF_FRV_DOUBLE
;
304 case OPTION_NO_DOUBLE
:
305 frv_flags
&= ~EF_FRV_DOUBLE
;
309 frv_flags
|= EF_FRV_MEDIA
;
312 case OPTION_NO_MEDIA
:
313 frv_flags
&= ~EF_FRV_MEDIA
;
317 frv_flags
|= EF_FRV_MULADD
;
320 case OPTION_NO_MULADD
:
321 frv_flags
&= ~EF_FRV_MULADD
;
325 frv_flags
&= ~EF_FRV_NOPACK
;
329 frv_flags
|= EF_FRV_NOPACK
;
335 int cpu_flags
= EF_FRV_CPU_GENERIC
;
337 /* Identify the processor type */
339 if (strcmp (p
, "frv") == 0)
341 cpu_flags
= EF_FRV_CPU_GENERIC
;
342 frv_mach
= bfd_mach_frv
;
345 else if (strcmp (p
, "fr500") == 0)
347 cpu_flags
= EF_FRV_CPU_FR500
;
348 frv_mach
= bfd_mach_fr500
;
351 else if (strcmp (p
, "fr550") == 0)
353 cpu_flags
= EF_FRV_CPU_FR550
;
354 frv_mach
= bfd_mach_fr550
;
357 else if (strcmp (p
, "fr400") == 0)
359 cpu_flags
= EF_FRV_CPU_FR400
;
360 frv_mach
= bfd_mach_fr400
;
363 else if (strcmp (p
, "fr300") == 0)
365 cpu_flags
= EF_FRV_CPU_FR300
;
366 frv_mach
= bfd_mach_fr300
;
369 else if (strcmp (p
, "simple") == 0)
371 cpu_flags
= EF_FRV_CPU_SIMPLE
;
372 frv_mach
= bfd_mach_frvsimple
;
373 frv_flags
|= EF_FRV_NOPACK
;
376 else if (strcmp (p
, "tomcat") == 0)
378 cpu_flags
= EF_FRV_CPU_TOMCAT
;
379 frv_mach
= bfd_mach_frvtomcat
;
384 as_fatal ("Unknown cpu -mcpu=%s", arg
);
388 frv_flags
= (frv_flags
& ~EF_FRV_CPU_MASK
) | cpu_flags
;
393 frv_flags
|= EF_FRV_PIC
;
395 frv_pic_flag
= "-fpic";
399 frv_flags
|= EF_FRV_BIGPIC
;
401 frv_pic_flag
= "-fPIC";
405 frv_flags
|= (EF_FRV_LIBPIC
| EF_FRV_G0
);
407 frv_pic_flag
= "-mlibrary-pic";
412 frv_flags
|= EF_FRV_FDPIC
;
413 frv_pic_flag
= "-mfdpic";
416 case OPTION_TOMCAT_DEBUG
:
420 case OPTION_TOMCAT_STATS
:
429 md_show_usage (stream
)
432 fprintf (stream
, _("FRV specific command line options:\n"));
433 fprintf (stream
, _("-G n Data >= n bytes is in small data area\n"));
434 fprintf (stream
, _("-mgpr-32 Note 32 gprs are used\n"));
435 fprintf (stream
, _("-mgpr-64 Note 64 gprs are used\n"));
436 fprintf (stream
, _("-mfpr-32 Note 32 fprs are used\n"));
437 fprintf (stream
, _("-mfpr-64 Note 64 fprs are used\n"));
438 fprintf (stream
, _("-msoft-float Note software fp is used\n"));
439 fprintf (stream
, _("-mdword Note stack is aligned to a 8 byte boundary\n"));
440 fprintf (stream
, _("-mno-dword Note stack is aligned to a 4 byte boundary\n"));
441 fprintf (stream
, _("-mdouble Note fp double insns are used\n"));
442 fprintf (stream
, _("-mmedia Note media insns are used\n"));
443 fprintf (stream
, _("-mmuladd Note multiply add/subtract insns are used\n"));
444 fprintf (stream
, _("-mpack Note instructions are packed\n"));
445 fprintf (stream
, _("-mno-pack Do not allow instructions to be packed\n"));
446 fprintf (stream
, _("-mpic Note small position independent code\n"));
447 fprintf (stream
, _("-mPIC Note large position independent code\n"));
448 fprintf (stream
, _("-mlibrary-pic Compile library for large position indepedent code\n"));
449 fprintf (stream
, _("-mcpu={fr500|fr550|fr400|fr300|frv|simple|tomcat}\n"));
450 fprintf (stream
, _(" Record the cpu type\n"));
451 fprintf (stream
, _("-mtomcat-stats Print out stats for tomcat workarounds\n"));
452 fprintf (stream
, _("-mtomcat-debug Debug tomcat workarounds\n"));
459 /* Initialize the `cgen' interface. */
461 /* Set the machine number and endian. */
462 gas_cgen_cpu_desc
= frv_cgen_cpu_open (CGEN_CPU_OPEN_MACHS
, 0,
463 CGEN_CPU_OPEN_ENDIAN
,
466 frv_cgen_init_asm (gas_cgen_cpu_desc
);
468 /* This is a callback from cgen to gas to parse operands. */
469 cgen_set_parse_operand_fn (gas_cgen_cpu_desc
, gas_cgen_parse_operand
);
471 /* Set the ELF flags if desired. */
473 bfd_set_private_flags (stdoutput
, frv_flags
);
475 /* Set the machine type */
476 bfd_default_set_arch_mach (stdoutput
, bfd_arch_frv
, frv_mach
);
478 /* Set up gp size so we can put local common items in .sbss */
479 bfd_set_gp_size (stdoutput
, g_switch_value
);
481 frv_vliw_reset (& vliw
, frv_mach
, frv_flags
);
486 struct vliw_insn_list
*frv_insert_vliw_insn
PARAMS ((bfd_boolean
));
488 struct vliw_insn_list
*
489 frv_insert_vliw_insn (count
)
492 struct vliw_insn_list
*vliw_insn_list_entry
;
493 struct vliw_chain
*vliw_chain_entry
;
495 if (current_vliw_chain
== NULL
)
497 vliw_chain_entry
= (struct vliw_chain
*) xmalloc (sizeof (struct vliw_chain
));
498 vliw_chain_entry
->insn_count
= 0;
499 vliw_chain_entry
->insn_list
= NULL
;
500 vliw_chain_entry
->next
= NULL
;
501 vliw_chain_entry
->num
= chain_num
++;
504 vliw_chain_top
= vliw_chain_entry
;
505 current_vliw_chain
= vliw_chain_entry
;
506 if (previous_vliw_chain
)
507 previous_vliw_chain
->next
= vliw_chain_entry
;
510 vliw_insn_list_entry
= (struct vliw_insn_list
*) xmalloc (sizeof (struct vliw_insn_list
));
511 vliw_insn_list_entry
->type
= VLIW_GENERIC_TYPE
;
512 vliw_insn_list_entry
->insn
= NULL
;
513 vliw_insn_list_entry
->sym
= NULL
;
514 vliw_insn_list_entry
->snop_frag
= NULL
;
515 vliw_insn_list_entry
->dnop_frag
= NULL
;
516 vliw_insn_list_entry
->next
= NULL
;
519 current_vliw_chain
->insn_count
++;
521 if (current_vliw_insn
)
522 current_vliw_insn
->next
= vliw_insn_list_entry
;
523 current_vliw_insn
= vliw_insn_list_entry
;
525 if (!current_vliw_chain
->insn_list
)
526 current_vliw_chain
->insn_list
= current_vliw_insn
;
528 return vliw_insn_list_entry
;
531 /* Identify the following cases:
533 1) A VLIW insn that contains both a branch and the branch destination.
534 This requires the insertion of two vliw instructions before the
535 branch. The first consists of two nops. The second consists of
538 2) A single instruction VLIW insn which is the destination of a branch
539 that is in the next VLIW insn. This requires the insertion of a vliw
540 insn containing two nops before the branch.
542 3) A double instruction VLIW insn which contains the destination of a
543 branch that is in the next VLIW insn. This requires the insertion of
544 a VLIW insn containing a single nop before the branch.
546 4) A single instruction VLIW insn which contains branch destination (x),
547 followed by a single instruction VLIW insn which does not contain
548 the branch to (x), followed by a VLIW insn which does contain the branch
549 to (x). This requires the insertion of a VLIW insn containing a single
550 nop before the VLIW instruction containing the branch.
553 #define FRV_IS_NOP(insn) (insn.buffer[0] == FRV_NOP_PACK || insn.buffer[0] == FRV_NOP_NOPACK)
554 #define FRV_NOP_PACK 0x00880000 /* ori.p gr0,0,gr0 */
555 #define FRV_NOP_NOPACK 0x80880000 /* ori gr0,0,gr0 */
557 /* Check a vliw insn for an insn of type containing the sym passed in label_sym. */
559 static struct vliw_insn_list
*frv_find_in_vliw
560 PARAMS ((enum vliw_insn_type
, struct vliw_chain
*, symbolS
*));
562 static struct vliw_insn_list
*
563 frv_find_in_vliw (vliw_insn_type
, this_chain
, label_sym
)
564 enum vliw_insn_type vliw_insn_type
;
565 struct vliw_chain
*this_chain
;
569 struct vliw_insn_list
*the_insn
;
574 for (the_insn
= this_chain
->insn_list
; the_insn
; the_insn
= the_insn
->next
)
576 if (the_insn
->type
== vliw_insn_type
577 && the_insn
->sym
== label_sym
)
586 /* A Vliw insn containing a single nop insn. */
589 /* A Vliw insn containing two nop insns. */
592 /* Two vliw insns. The first containing two nop insns.
593 The second contain a single nop insn. */
594 VLIW_DOUBLE_THEN_SINGLE_NOP
597 static void frv_debug_tomcat
PARAMS ((struct vliw_chain
*));
600 frv_debug_tomcat (start_chain
)
601 struct vliw_chain
*start_chain
;
603 struct vliw_chain
*this_chain
;
604 struct vliw_insn_list
*this_insn
;
607 for (this_chain
= start_chain
; this_chain
; this_chain
= this_chain
->next
, i
++)
609 fprintf (stderr
, "\nVliw Insn #%d, #insns: %d\n", i
, this_chain
->insn_count
);
611 for (this_insn
= this_chain
->insn_list
; this_insn
; this_insn
= this_insn
->next
)
613 if (this_insn
->type
== VLIW_LABEL_TYPE
)
614 fprintf (stderr
, "Label Value: %d\n", (int) this_insn
->sym
);
615 else if (this_insn
->type
== VLIW_BRANCH_TYPE
)
616 fprintf (stderr
, "%s to %d\n", this_insn
->insn
->base
->name
, (int) this_insn
->sym
);
617 else if (this_insn
->type
== VLIW_BRANCH_HAS_NOPS
)
618 fprintf (stderr
, "nop'd %s to %d\n", this_insn
->insn
->base
->name
, (int) this_insn
->sym
);
619 else if (this_insn
->type
== VLIW_NOP_TYPE
)
620 fprintf (stderr
, "Nop\n");
622 fprintf (stderr
, " %s\n", this_insn
->insn
->base
->name
);
627 static void frv_adjust_vliw_count
PARAMS ((struct vliw_chain
*));
630 frv_adjust_vliw_count (this_chain
)
631 struct vliw_chain
*this_chain
;
633 struct vliw_insn_list
*this_insn
;
635 this_chain
->insn_count
= 0;
637 for (this_insn
= this_chain
->insn_list
;
639 this_insn
= this_insn
->next
)
641 if (this_insn
->type
!= VLIW_LABEL_TYPE
)
642 this_chain
->insn_count
++;
647 /* Insert the desired nop combination in the vliw chain before insert_before_insn.
648 Rechain the vliw insn. */
650 static struct vliw_chain
*frv_tomcat_shuffle
651 PARAMS ((enum vliw_nop_type
, struct vliw_chain
*, struct vliw_insn_list
*));
653 static struct vliw_chain
*
654 frv_tomcat_shuffle (this_nop_type
, vliw_to_split
, insert_before_insn
)
655 enum vliw_nop_type this_nop_type
;
656 struct vliw_chain
*vliw_to_split
;
657 struct vliw_insn_list
*insert_before_insn
;
660 bfd_boolean pack_prev
= FALSE
;
661 struct vliw_chain
*return_me
= NULL
;
662 struct vliw_insn_list
*prev_insn
= NULL
;
663 struct vliw_insn_list
*curr_insn
= vliw_to_split
->insn_list
;
665 struct vliw_chain
*double_nop
= (struct vliw_chain
*) xmalloc (sizeof (struct vliw_chain
));
666 struct vliw_chain
*single_nop
= (struct vliw_chain
*) xmalloc (sizeof (struct vliw_chain
));
667 struct vliw_chain
*second_part
= (struct vliw_chain
*) xmalloc (sizeof (struct vliw_chain
));
668 struct vliw_chain
*curr_vliw
= vliw_chain_top
;
669 struct vliw_chain
*prev_vliw
= NULL
;
671 while (curr_insn
&& curr_insn
!= insert_before_insn
)
673 /* We can't set the packing bit on a label. If we have the case
677 branch that needs nops
678 Then don't set pack bit later. */
680 if (curr_insn
->type
!= VLIW_LABEL_TYPE
)
682 prev_insn
= curr_insn
;
683 curr_insn
= curr_insn
->next
;
686 while (curr_vliw
&& curr_vliw
!= vliw_to_split
)
688 prev_vliw
= curr_vliw
;
689 curr_vliw
= curr_vliw
->next
;
692 switch (this_nop_type
)
694 case VLIW_SINGLE_NOP
:
697 /* Branch is first, Insert the NOP prior to this vliw insn. */
699 prev_vliw
->next
= single_nop
;
701 vliw_chain_top
= single_nop
;
702 single_nop
->next
= vliw_to_split
;
703 vliw_to_split
->insn_list
->type
= VLIW_BRANCH_HAS_NOPS
;
704 return_me
= vliw_to_split
;
708 /* Set the packing bit on the previous insn. */
711 unsigned char *buffer
= prev_insn
->address
;
714 /* The branch is in the middle. Split this vliw insn into first
715 and second parts. Insert the NOP inbetween. */
717 second_part
->insn_list
= insert_before_insn
;
718 second_part
->insn_list
->type
= VLIW_BRANCH_HAS_NOPS
;
719 second_part
->next
= vliw_to_split
->next
;
720 frv_adjust_vliw_count (second_part
);
722 single_nop
->next
= second_part
;
724 vliw_to_split
->next
= single_nop
;
725 prev_insn
->next
= NULL
;
727 return_me
= second_part
;
728 frv_adjust_vliw_count (vliw_to_split
);
732 case VLIW_DOUBLE_NOP
:
735 /* Branch is first, Insert the NOP prior to this vliw insn. */
737 prev_vliw
->next
= double_nop
;
739 vliw_chain_top
= double_nop
;
741 double_nop
->next
= vliw_to_split
;
742 return_me
= vliw_to_split
;
743 vliw_to_split
->insn_list
->type
= VLIW_BRANCH_HAS_NOPS
;
747 /* Set the packing bit on the previous insn. */
750 unsigned char *buffer
= prev_insn
->address
;
754 /* The branch is in the middle. Split this vliw insn into first
755 and second parts. Insert the NOP inbetween. */
756 second_part
->insn_list
= insert_before_insn
;
757 second_part
->insn_list
->type
= VLIW_BRANCH_HAS_NOPS
;
758 second_part
->next
= vliw_to_split
->next
;
759 frv_adjust_vliw_count (second_part
);
761 double_nop
->next
= second_part
;
763 vliw_to_split
->next
= single_nop
;
764 prev_insn
->next
= NULL
;
765 frv_adjust_vliw_count (vliw_to_split
);
767 return_me
= second_part
;
771 case VLIW_DOUBLE_THEN_SINGLE_NOP
:
772 double_nop
->next
= single_nop
;
773 double_nop
->insn_count
= 2;
774 double_nop
->insn_list
= &double_nop_insn
;
775 single_nop
->insn_count
= 1;
776 single_nop
->insn_list
= &single_nop_insn
;
780 /* The branch is the first insn in this vliw. Don't split the vliw. Insert
781 the nops prior to this vliw. */
783 prev_vliw
->next
= double_nop
;
785 vliw_chain_top
= double_nop
;
787 single_nop
->next
= vliw_to_split
;
788 return_me
= vliw_to_split
;
789 vliw_to_split
->insn_list
->type
= VLIW_BRANCH_HAS_NOPS
;
793 /* Set the packing bit on the previous insn. */
796 unsigned char *buffer
= prev_insn
->address
;
800 /* The branch is in the middle of this vliw insn. Split into first and
801 second parts. Insert the nop vliws in between. */
802 second_part
->insn_list
= insert_before_insn
;
803 second_part
->insn_list
->type
= VLIW_BRANCH_HAS_NOPS
;
804 second_part
->next
= vliw_to_split
->next
;
805 frv_adjust_vliw_count (second_part
);
807 single_nop
->next
= second_part
;
809 vliw_to_split
->next
= double_nop
;
810 prev_insn
->next
= NULL
;
811 frv_adjust_vliw_count (vliw_to_split
);
813 return_me
= second_part
;
821 static void frv_tomcat_analyze_vliw_chains
PARAMS ((void));
824 frv_tomcat_analyze_vliw_chains ()
826 struct vliw_chain
*vliw1
= NULL
;
827 struct vliw_chain
*vliw2
= NULL
;
828 struct vliw_chain
*vliw3
= NULL
;
830 struct vliw_insn_list
*this_insn
= NULL
;
831 struct vliw_insn_list
*temp_insn
= NULL
;
833 /* We potentially need to look at three VLIW insns to determine if the
834 workaround is required. Set them up. Ignore existing nops during analysis. */
836 #define FRV_SET_VLIW_WINDOW(VLIW1, VLIW2, VLIW3) \
837 if (VLIW1 && VLIW1->next) \
838 VLIW2 = VLIW1->next; \
841 if (VLIW2 && VLIW2->next) \
842 VLIW3 = VLIW2->next; \
846 vliw1
= vliw_chain_top
;
850 FRV_SET_VLIW_WINDOW (vliw1
, vliw2
, vliw3
);
855 if (vliw1
->insn_count
== 1)
857 /* check vliw1 for a label. */
858 if (vliw1
->insn_list
->type
== VLIW_LABEL_TYPE
)
860 temp_insn
= frv_find_in_vliw (VLIW_BRANCH_TYPE
, vliw2
, vliw1
->insn_list
->sym
);
863 vliw1
= frv_tomcat_shuffle (VLIW_DOUBLE_NOP
, vliw2
, vliw1
->insn_list
);
864 temp_insn
->dnop_frag
->fr_subtype
= NOP_KEEP
;
871 && vliw2
->insn_count
== 1
872 && (temp_insn
= frv_find_in_vliw (VLIW_BRANCH_TYPE
, vliw3
, vliw1
->insn_list
->sym
)) != NULL
)
874 temp_insn
->snop_frag
->fr_subtype
= NOP_KEEP
;
875 vliw1
= frv_tomcat_shuffle (VLIW_SINGLE_NOP
, vliw3
, vliw3
->insn_list
);
883 if (vliw1
->insn_count
== 2)
885 struct vliw_insn_list
*this_insn
;
887 /* check vliw1 for a label. */
888 for (this_insn
= vliw1
->insn_list
; this_insn
; this_insn
= this_insn
->next
)
890 if (this_insn
->type
== VLIW_LABEL_TYPE
)
892 if ((temp_insn
= frv_find_in_vliw (VLIW_BRANCH_TYPE
, vliw2
, this_insn
->sym
)) != NULL
)
894 temp_insn
->snop_frag
->fr_subtype
= NOP_KEEP
;
895 vliw1
= frv_tomcat_shuffle (VLIW_SINGLE_NOP
, vliw2
, this_insn
);
905 /* Examine each insn in this VLIW. Look for the workaround criteria. */
906 for (this_insn
= vliw1
->insn_list
; this_insn
; this_insn
= this_insn
->next
)
908 /* Don't look at labels or nops. */
910 && (this_insn
->type
== VLIW_LABEL_TYPE
911 || this_insn
->type
== VLIW_NOP_TYPE
912 || this_insn
->type
== VLIW_BRANCH_HAS_NOPS
))
913 this_insn
= this_insn
->next
;
921 if (frv_is_branch_insn (this_insn
->insn
))
923 if ((temp_insn
= frv_find_in_vliw (VLIW_LABEL_TYPE
, vliw1
, this_insn
->sym
)) != NULL
)
925 /* Insert [nop/nop] [nop] before branch. */
926 this_insn
->snop_frag
->fr_subtype
= NOP_KEEP
;
927 this_insn
->dnop_frag
->fr_subtype
= NOP_KEEP
;
928 vliw1
= frv_tomcat_shuffle (VLIW_DOUBLE_THEN_SINGLE_NOP
, vliw1
, this_insn
);
935 /* This vliw insn checks out okay. Take a look at the next one. */
941 frv_tomcat_workaround ()
943 if (frv_mach
!= bfd_mach_frvtomcat
)
947 frv_debug_tomcat (vliw_chain_top
);
949 frv_tomcat_analyze_vliw_chains ();
953 fprintf (stderr
, "Inserted %d Single Nops\n", tomcat_singles
);
954 fprintf (stderr
, "Inserted %d Double Nops\n", tomcat_doubles
);
959 fr550_check_insn_acc_range (frv_insn
*insn
, int low
, int hi
)
962 switch (CGEN_INSN_NUM (insn
->insn
))
964 case FRV_INSN_MADDACCS
:
965 case FRV_INSN_MSUBACCS
:
966 case FRV_INSN_MDADDACCS
:
967 case FRV_INSN_MDSUBACCS
:
968 case FRV_INSN_MASACCS
:
969 case FRV_INSN_MDASACCS
:
970 acc
= insn
->fields
.f_ACC40Si
;
971 if (acc
< low
|| acc
> hi
)
972 return 1; /* out of range */
973 acc
= insn
->fields
.f_ACC40Sk
;
974 if (acc
< low
|| acc
> hi
)
975 return 1; /* out of range */
977 case FRV_INSN_MMULHS
:
978 case FRV_INSN_MMULHU
:
979 case FRV_INSN_MMULXHS
:
980 case FRV_INSN_MMULXHU
:
981 case FRV_INSN_CMMULHS
:
982 case FRV_INSN_CMMULHU
:
983 case FRV_INSN_MQMULHS
:
984 case FRV_INSN_MQMULHU
:
985 case FRV_INSN_MQMULXHS
:
986 case FRV_INSN_MQMULXHU
:
987 case FRV_INSN_CMQMULHS
:
988 case FRV_INSN_CMQMULHU
:
989 case FRV_INSN_MMACHS
:
990 case FRV_INSN_MMRDHS
:
991 case FRV_INSN_CMMACHS
:
992 case FRV_INSN_MQMACHS
:
993 case FRV_INSN_CMQMACHS
:
994 case FRV_INSN_MQXMACHS
:
995 case FRV_INSN_MQXMACXHS
:
996 case FRV_INSN_MQMACXHS
:
997 case FRV_INSN_MCPXRS
:
998 case FRV_INSN_MCPXIS
:
999 case FRV_INSN_CMCPXRS
:
1000 case FRV_INSN_CMCPXIS
:
1001 case FRV_INSN_MQCPXRS
:
1002 case FRV_INSN_MQCPXIS
:
1003 acc
= insn
->fields
.f_ACC40Sk
;
1004 if (acc
< low
|| acc
> hi
)
1005 return 1; /* out of range */
1007 case FRV_INSN_MMACHU
:
1008 case FRV_INSN_MMRDHU
:
1009 case FRV_INSN_CMMACHU
:
1010 case FRV_INSN_MQMACHU
:
1011 case FRV_INSN_CMQMACHU
:
1012 case FRV_INSN_MCPXRU
:
1013 case FRV_INSN_MCPXIU
:
1014 case FRV_INSN_CMCPXRU
:
1015 case FRV_INSN_CMCPXIU
:
1016 case FRV_INSN_MQCPXRU
:
1017 case FRV_INSN_MQCPXIU
:
1018 acc
= insn
->fields
.f_ACC40Uk
;
1019 if (acc
< low
|| acc
> hi
)
1020 return 1; /* out of range */
1025 return 0; /* all is ok */
1029 fr550_check_acc_range (FRV_VLIW
*vliw
, frv_insn
*insn
)
1031 switch ((*vliw
->current_vliw
)[vliw
->next_slot
- 1])
1035 return fr550_check_insn_acc_range (insn
, 0, 3);
1038 return fr550_check_insn_acc_range (insn
, 4, 7);
1042 return 0; /* all is ok */
1051 int packing_constraint
;
1052 finished_insnS finished_insn
;
1053 fragS
*double_nop_frag
= NULL
;
1054 fragS
*single_nop_frag
= NULL
;
1055 struct vliw_insn_list
*vliw_insn_list_entry
= NULL
;
1057 /* Initialize GAS's cgen interface for a new instruction. */
1058 gas_cgen_init_parse ();
1060 memset (&insn
, 0, sizeof (insn
));
1062 insn
.insn
= frv_cgen_assemble_insn
1063 (gas_cgen_cpu_desc
, str
, & insn
.fields
, insn
.buffer
, &errmsg
);
1071 /* If the cpu is tomcat, then we need to insert nops to workaround
1072 hardware limitations. We need to keep track of each vliw unit
1073 and examine the length of the unit and the individual insns
1074 within the unit to determine the number and location of the
1076 if (frv_mach
== bfd_mach_frvtomcat
)
1078 /* If we've just finished a VLIW insn OR this is a branch,
1079 then start up a new frag. Fill it with nops. We will get rid
1080 of those that are not required after we've seen all of the
1081 instructions but before we start resolving fixups. */
1082 if ( !FRV_IS_NOP (insn
)
1083 && (frv_is_branch_insn (insn
.insn
) || insn
.fields
.f_pack
))
1087 frag_wane (frag_now
);
1089 double_nop_frag
= frag_now
;
1090 buffer
= frag_var (rs_machine_dependent
, 8, 8, NOP_DELETE
, NULL
, 0, 0);
1091 md_number_to_chars (buffer
, FRV_NOP_PACK
, 4);
1092 md_number_to_chars (buffer
+4, FRV_NOP_NOPACK
, 4);
1094 frag_wane (frag_now
);
1096 single_nop_frag
= frag_now
;
1097 buffer
= frag_var (rs_machine_dependent
, 4, 4, NOP_DELETE
, NULL
, 0, 0);
1098 md_number_to_chars (buffer
, FRV_NOP_NOPACK
, 4);
1101 vliw_insn_list_entry
= frv_insert_vliw_insn (DO_COUNT
);
1102 vliw_insn_list_entry
->insn
= insn
.insn
;
1103 if (frv_is_branch_insn (insn
.insn
))
1104 vliw_insn_list_entry
->type
= VLIW_BRANCH_TYPE
;
1106 if ( !FRV_IS_NOP (insn
)
1107 && (frv_is_branch_insn (insn
.insn
) || insn
.fields
.f_pack
))
1109 vliw_insn_list_entry
->snop_frag
= single_nop_frag
;
1110 vliw_insn_list_entry
->dnop_frag
= double_nop_frag
;
1114 /* Make sure that this insn does not violate the VLIW packing constraints. */
1115 /* -mno-pack disallows any packing whatsoever. */
1116 if (frv_flags
& EF_FRV_NOPACK
)
1118 if (! insn
.fields
.f_pack
)
1120 as_bad (_("VLIW packing used for -mno-pack"));
1124 /* -mcpu=FRV is an idealized FR-V implementation that supports all of the
1125 instructions, don't do vliw checking. */
1126 else if (frv_mach
!= bfd_mach_frv
)
1128 packing_constraint
= frv_vliw_add_insn (& vliw
, insn
.insn
);
1129 if (frv_mach
== bfd_mach_fr550
&& ! packing_constraint
)
1130 packing_constraint
= fr550_check_acc_range (& vliw
, & insn
);
1131 if (insn
.fields
.f_pack
)
1132 frv_vliw_reset (& vliw
, frv_mach
, frv_flags
);
1133 if (packing_constraint
)
1135 as_bad (_("VLIW packing constraint violation"));
1140 /* Doesn't really matter what we pass for RELAX_P here. */
1141 gas_cgen_finish_insn (insn
.insn
, insn
.buffer
,
1142 CGEN_FIELDS_BITSIZE (& insn
.fields
), 1, &finished_insn
);
1145 /* If the cpu is tomcat, then we need to insert nops to workaround
1146 hardware limitations. We need to keep track of each vliw unit
1147 and examine the length of the unit and the individual insns
1148 within the unit to determine the number and location of the
1150 if (frv_mach
== bfd_mach_frvtomcat
)
1152 if (vliw_insn_list_entry
)
1153 vliw_insn_list_entry
->address
= finished_insn
.addr
;
1157 if (insn
.fields
.f_pack
)
1159 /* We've completed a VLIW insn. */
1160 previous_vliw_chain
= current_vliw_chain
;
1161 current_vliw_chain
= NULL
;
1162 current_vliw_insn
= NULL
;
1167 /* The syntax in the manual says constants begin with '#'.
1168 We just ignore it. */
1171 md_operand (expressionP
)
1172 expressionS
* expressionP
;
1174 if (* input_line_pointer
== '#')
1176 input_line_pointer
++;
1177 expression (expressionP
);
1182 md_section_align (segment
, size
)
1186 int align
= bfd_get_section_alignment (stdoutput
, segment
);
1187 return ((size
+ (1 << align
) - 1) & (-1 << align
));
1191 md_undefined_symbol (name
)
1192 char * name ATTRIBUTE_UNUSED
;
1197 /* Interface to relax_segment. */
1199 /* FIXME: Build table by hand, get it working, then machine generate. */
1200 const relax_typeS md_relax_table
[] =
1203 {511 - 2 - 2, -512 - 2 + 2, 0, 2 },
1204 {0x2000000 - 1 - 2, -0x2000000 - 2, 2, 0 },
1205 {0x2000000 - 1 - 2, -0x2000000 - 2, 4, 0 }
1209 frv_relax_frag (fragP
, stretch
)
1210 fragS
*fragP ATTRIBUTE_UNUSED
;
1211 long stretch ATTRIBUTE_UNUSED
;
1216 /* Return an initial guess of the length by which a fragment must grow to
1217 hold a branch to reach its destination.
1218 Also updates fr_type/fr_subtype as necessary.
1220 Called just before doing relaxation.
1221 Any symbol that is now undefined will not become defined.
1222 The guess for fr_var is ACTUALLY the growth beyond fr_fix.
1223 Whatever we do to grow fr_fix or fr_var contributes to our returned value.
1224 Although it may not be explicit in the frag, pretend fr_var starts with a
1228 md_estimate_size_before_relax (fragP
, segment
)
1230 segT segment ATTRIBUTE_UNUSED
;
1232 switch (fragP
->fr_subtype
)
1235 return fragP
->fr_var
;
1243 /* *fragP has been relaxed to its final size, and now needs to have
1244 the bytes inside it modified to conform to the new size.
1246 Called after relaxation is finished.
1247 fragP->fr_type == rs_machine_dependent.
1248 fragP->fr_subtype is the subtype of what the address relaxed to. */
1251 md_convert_frag (abfd
, sec
, fragP
)
1252 bfd
* abfd ATTRIBUTE_UNUSED
;
1253 segT sec ATTRIBUTE_UNUSED
;
1256 switch (fragP
->fr_subtype
)
1263 fragP
->fr_fix
= fragP
->fr_var
;
1269 /* Functions concerning relocs. */
1271 /* The location from which a PC relative jump should be calculated,
1272 given a PC relative reloc. */
1275 md_pcrel_from_section (fixP
, sec
)
1279 if (TC_FORCE_RELOCATION (fixP
)
1280 || (fixP
->fx_addsy
!= (symbolS
*) NULL
1281 && S_GET_SEGMENT (fixP
->fx_addsy
) != sec
))
1283 /* If we can't adjust this relocation, or if it references a
1284 local symbol in a different section (which
1285 TC_FORCE_RELOCATION can't check), let the linker figure it
1290 return (fixP
->fx_frag
->fr_address
+ fixP
->fx_where
) & ~1;
1293 /* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
1294 Returns BFD_RELOC_NONE if no reloc type can be found.
1295 *FIXP may be modified if desired. */
1297 bfd_reloc_code_real_type
1298 md_cgen_lookup_reloc (insn
, operand
, fixP
)
1299 const CGEN_INSN
* insn ATTRIBUTE_UNUSED
;
1300 const CGEN_OPERAND
* operand
;
1303 switch (operand
->type
)
1305 case FRV_OPERAND_LABEL16
:
1306 fixP
->fx_pcrel
= TRUE
;
1307 return BFD_RELOC_FRV_LABEL16
;
1309 case FRV_OPERAND_LABEL24
:
1310 fixP
->fx_pcrel
= TRUE
;
1311 return BFD_RELOC_FRV_LABEL24
;
1313 case FRV_OPERAND_UHI16
:
1314 case FRV_OPERAND_ULO16
:
1315 case FRV_OPERAND_SLO16
:
1317 /* The relocation type should be recorded in opinfo */
1318 if (fixP
->fx_cgen
.opinfo
!= 0)
1319 return fixP
->fx_cgen
.opinfo
;
1322 case FRV_OPERAND_D12
:
1323 case FRV_OPERAND_S12
:
1324 if (fixP
->fx_cgen
.opinfo
!= 0)
1325 return fixP
->fx_cgen
.opinfo
;
1327 return BFD_RELOC_FRV_GPREL12
;
1329 case FRV_OPERAND_U12
:
1330 return BFD_RELOC_FRV_GPRELU12
;
1335 return BFD_RELOC_NONE
;
1339 /* See whether we need to force a relocation into the output file.
1340 This is used to force out switch and PC relative relocations when
1344 frv_force_relocation (fix
)
1347 if (fix
->fx_r_type
== BFD_RELOC_FRV_GPREL12
1348 || fix
->fx_r_type
== BFD_RELOC_FRV_GPRELU12
)
1351 return generic_force_reloc (fix
);
1354 /* Apply a fixup that could be resolved within the assembler. */
1357 md_apply_fix3 (fixP
, valP
, seg
)
1362 if (fixP
->fx_addsy
== 0)
1363 switch (fixP
->fx_cgen
.opinfo
)
1365 case BFD_RELOC_FRV_HI16
:
1368 case BFD_RELOC_FRV_LO16
:
1373 gas_cgen_md_apply_fix3 (fixP
, valP
, seg
);
1378 /* Write a value out to the object file, using the appropriate endianness. */
1381 frv_md_number_to_chars (buf
, val
, n
)
1386 number_to_chars_bigendian (buf
, val
, n
);
1389 /* Turn a string in input_line_pointer into a floating point constant of type
1390 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
1391 emitted is stored in *sizeP . An error message is returned, or NULL on OK.
1394 /* Equal to MAX_PRECISION in atof-ieee.c */
1395 #define MAX_LITTLENUMS 6
1398 md_atof (type
, litP
, sizeP
)
1405 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
1424 /* FIXME: Some targets allow other format chars for bigger sizes here. */
1428 return _("Bad call to md_atof()");
1431 t
= atof_ieee (input_line_pointer
, type
, words
);
1433 input_line_pointer
= t
;
1434 * sizeP
= prec
* sizeof (LITTLENUM_TYPE
);
1436 for (i
= 0; i
< prec
; i
++)
1438 md_number_to_chars (litP
, (valueT
) words
[i
],
1439 sizeof (LITTLENUM_TYPE
));
1440 litP
+= sizeof (LITTLENUM_TYPE
);
1447 frv_fix_adjustable (fixP
)
1450 bfd_reloc_code_real_type reloc_type
;
1452 if ((int) fixP
->fx_r_type
>= (int) BFD_RELOC_UNUSED
)
1454 const CGEN_INSN
*insn
= NULL
;
1455 int opindex
= (int) fixP
->fx_r_type
- (int) BFD_RELOC_UNUSED
;
1456 const CGEN_OPERAND
*operand
= cgen_operand_lookup_by_num(gas_cgen_cpu_desc
, opindex
);
1457 reloc_type
= md_cgen_lookup_reloc (insn
, operand
, fixP
);
1460 reloc_type
= fixP
->fx_r_type
;
1462 /* We need the symbol name for the VTABLE entries */
1463 if ( reloc_type
== BFD_RELOC_VTABLE_INHERIT
1464 || reloc_type
== BFD_RELOC_VTABLE_ENTRY
1465 || reloc_type
== BFD_RELOC_FRV_GPREL12
1466 || reloc_type
== BFD_RELOC_FRV_GPRELU12
)
1472 /* Allow user to set flags bits. */
1475 int arg ATTRIBUTE_UNUSED
;
1477 flagword new_flags
= get_absolute_expression ();
1478 flagword new_mask
= ~ (flagword
)0;
1480 frv_user_set_flags_p
= 1;
1481 if (*input_line_pointer
== ',')
1483 ++input_line_pointer
;
1484 new_mask
= get_absolute_expression ();
1487 frv_flags
= (frv_flags
& ~new_mask
) | (new_flags
& new_mask
);
1488 bfd_set_private_flags (stdoutput
, frv_flags
);
1491 /* Frv specific function to handle 4 byte initializations for pointers that are
1492 considered 'safe' for use with pic support. Until frv_frob_file{,_section}
1493 is run, we encode it a BFD_RELOC_CTOR, and it is turned back into a normal
1494 BFD_RELOC_32 at that time. */
1497 frv_pic_ptr (nbytes
)
1506 #ifdef md_flush_pending_output
1507 md_flush_pending_output ();
1510 if (is_it_end_of_statement ())
1512 demand_empty_rest_of_line ();
1516 #ifdef md_cons_align
1517 md_cons_align (nbytes
);
1522 bfd_reloc_code_real_type reloc_type
= BFD_RELOC_CTOR
;
1524 if (strncasecmp (input_line_pointer
, "funcdesc(", 9) == 0)
1526 input_line_pointer
+= 9;
1528 if (*input_line_pointer
== ')')
1529 input_line_pointer
++;
1531 as_bad ("missing ')'");
1532 reloc_type
= BFD_RELOC_FRV_FUNCDESC
;
1539 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
, 4, &exp
, 0,
1542 while (*input_line_pointer
++ == ',');
1544 input_line_pointer
--; /* Put terminator back into stream. */
1545 demand_empty_rest_of_line ();
1551 #define DPRINTF1(A) fprintf (stderr, A)
1552 #define DPRINTF2(A,B) fprintf (stderr, A, B)
1553 #define DPRINTF3(A,B,C) fprintf (stderr, A, B, C)
1557 #define DPRINTF2(A,B)
1558 #define DPRINTF3(A,B,C)
1561 /* Go through a the sections looking for relocations that are problematical for
1562 pic. If not pic, just note that this object can't be linked with pic. If
1563 it is pic, see if it needs to be marked so that it will be fixed up, or if
1564 not possible, issue an error. */
1567 frv_frob_file_section (abfd
, sec
, ptr
)
1570 PTR ptr ATTRIBUTE_UNUSED
;
1572 segment_info_type
*seginfo
= seg_info (sec
);
1574 CGEN_CPU_DESC cd
= gas_cgen_cpu_desc
;
1575 flagword flags
= bfd_get_section_flags (abfd
, sec
);
1577 /* Skip relocations in known sections (.ctors, .dtors, and .gcc_except_table)
1578 since we can fix those up by hand. */
1579 int known_section_p
= (sec
->name
1580 && sec
->name
[0] == '.'
1581 && ((sec
->name
[1] == 'c'
1582 && strcmp (sec
->name
, ".ctor") == 0)
1583 || (sec
->name
[1] == 'd'
1584 && strcmp (sec
->name
, ".dtor") == 0)
1585 || (sec
->name
[1] == 'g'
1586 && strcmp (sec
->name
, ".gcc_except_table") == 0)));
1588 DPRINTF3 ("\nFrv section %s%s\n", sec
->name
, (known_section_p
) ? ", known section" : "");
1589 if ((flags
& SEC_ALLOC
) == 0)
1591 DPRINTF1 ("\tSkipping non-loaded section\n");
1595 for (fixp
= seginfo
->fix_root
; fixp
; fixp
= fixp
->fx_next
)
1597 symbolS
*s
= fixp
->fx_addsy
;
1598 bfd_reloc_code_real_type reloc
;
1601 const CGEN_OPERAND
*operand
;
1602 const CGEN_INSN
*insn
= fixp
->fx_cgen
.insn
;
1606 DPRINTF1 ("\tSkipping reloc that has already been done\n");
1612 DPRINTF1 ("\tSkipping reloc that is PC relative\n");
1618 DPRINTF1 ("\tSkipping reloc without symbol\n");
1622 if (fixp
->fx_r_type
< BFD_RELOC_UNUSED
)
1625 reloc
= fixp
->fx_r_type
;
1629 opindex
= (int) fixp
->fx_r_type
- (int) BFD_RELOC_UNUSED
;
1630 operand
= cgen_operand_lookup_by_num (cd
, opindex
);
1631 reloc
= md_cgen_lookup_reloc (insn
, operand
, fixp
);
1634 DPRINTF3 ("\treloc %s\t%s", bfd_get_reloc_code_name (reloc
), S_GET_NAME (s
));
1643 /* Skip relocations in known sections (.ctors, .dtors, and
1644 .gcc_except_table) since we can fix those up by hand. Also
1645 skip forward references to constants. Also skip a difference
1646 of two symbols, which still uses the BFD_RELOC_32 at this
1648 if (! known_section_p
1649 && S_GET_SEGMENT (s
) != absolute_section
1651 && (flags
& (SEC_READONLY
| SEC_CODE
)) == 0)
1657 /* FIXME -- should determine if any of the GP relocation really uses
1658 gr16 (which is not pic safe) or not. Right now, assume if we
1659 aren't being compiled with -mpic, the usage is non pic safe, but
1660 is safe with -mpic. */
1661 case BFD_RELOC_FRV_GPREL12
:
1662 case BFD_RELOC_FRV_GPRELU12
:
1663 case BFD_RELOC_FRV_GPREL32
:
1664 case BFD_RELOC_FRV_GPRELHI
:
1665 case BFD_RELOC_FRV_GPRELLO
:
1666 non_pic_p
= ! frv_pic_p
;
1669 case BFD_RELOC_FRV_LO16
:
1670 case BFD_RELOC_FRV_HI16
:
1671 if (S_GET_SEGMENT (s
) != absolute_section
)
1675 case BFD_RELOC_VTABLE_INHERIT
:
1676 case BFD_RELOC_VTABLE_ENTRY
:
1680 /* If this is a blessed BFD_RELOC_32, convert it back to the normal
1682 case BFD_RELOC_CTOR
:
1683 fixp
->fx_r_type
= BFD_RELOC_32
;
1689 DPRINTF1 (" (Non-pic relocation)\n");
1691 as_warn_where (fixp
->fx_file
, fixp
->fx_line
,
1692 _("Relocation %s is not safe for %s"),
1693 bfd_get_reloc_code_name (reloc
), frv_pic_flag
);
1695 else if ((frv_flags
& EF_FRV_NON_PIC_RELOCS
) == 0)
1697 frv_flags
|= EF_FRV_NON_PIC_RELOCS
;
1698 bfd_set_private_flags (abfd
, frv_flags
);
1708 /* After all of the symbols have been adjusted, go over the file looking
1709 for any relocations that pic won't support. */
1714 bfd_map_over_sections (stdoutput
, frv_frob_file_section
, (PTR
)0);
1718 frv_frob_label (this_label
)
1719 symbolS
*this_label
;
1721 struct vliw_insn_list
*vliw_insn_list_entry
;
1723 if (frv_mach
!= bfd_mach_frvtomcat
)
1726 if (now_seg
!= text_section
)
1729 vliw_insn_list_entry
= frv_insert_vliw_insn(DONT_COUNT
);
1730 vliw_insn_list_entry
->type
= VLIW_LABEL_TYPE
;
1731 vliw_insn_list_entry
->sym
= this_label
;
1735 frv_cgen_record_fixup_exp (frag
, where
, insn
, length
, operand
, opinfo
, exp
)
1738 const CGEN_INSN
* insn
;
1740 const CGEN_OPERAND
* operand
;
1744 fixS
* fixP
= gas_cgen_record_fixup_exp (frag
, where
, insn
, length
,
1745 operand
, opinfo
, exp
);
1747 if (frv_mach
== bfd_mach_frvtomcat
1748 && current_vliw_insn
1749 && current_vliw_insn
->type
== VLIW_BRANCH_TYPE
1751 current_vliw_insn
->sym
= exp
->X_add_symbol
;