1
/* tc-frv.c -- Assembler for the Fujitsu FRV.
2
Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
3
Free Software Foundation. Inc.
5
This file is part of GAS, the GNU Assembler.
7
GAS is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 3, or (at your option)
12
GAS is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
GNU General Public License for more details.
17
You should have received a copy of the GNU General Public License
18
along with GAS; see the file COPYING. If not, write to
19
the Free Software Foundation, 51 Franklin Street - Fifth Floor,
20
Boston, MA 02110-1301, USA. */
25
#include "opcodes/frv-desc.h"
26
#include "opcodes/frv-opc.h"
29
#include "elf/common.h"
31
#include "dwarf2dbg.h"
33
/* Structure to hold all of the different components describing
34
an individual instruction. */
37
const CGEN_INSN * insn;
38
const CGEN_INSN * orig_insn;
41
CGEN_INSN_INT buffer [1];
42
#define INSN_VALUE(buf) (*(buf))
44
unsigned char buffer [CGEN_MAX_INSN_SIZE];
45
#define INSN_VALUE(buf) (buf)
50
fixS * fixups [GAS_CGEN_MAX_FIXUPS];
51
int indices [MAX_OPERAND_INSTANCES];
57
VLIW_GENERIC_TYPE, /* Don't care about this insn. */
58
VLIW_BRANCH_TYPE, /* A Branch. */
59
VLIW_LABEL_TYPE, /* A Label. */
60
VLIW_NOP_TYPE, /* A NOP. */
61
VLIW_BRANCH_HAS_NOPS /* A Branch that requires NOPS. */
64
/* We're going to use these in the fr_subtype field to mark
65
whether to keep inserted nops. */
67
#define NOP_KEEP 1 /* Keep these NOPS. */
68
#define NOP_DELETE 2 /* Delete these NOPS. */
71
#define DONT_COUNT FALSE
73
/* A list of insns within a VLIW insn. */
76
/* The type of this insn. */
77
enum vliw_insn_type type;
79
/* The corresponding gas insn information. */
80
const CGEN_INSN *insn;
82
/* For branches and labels, the symbol that is referenced. */
85
/* For branches, the frag containing the single nop that was generated. */
88
/* For branches, the frag containing the double nop that was generated. */
91
/* Pointer to raw data for this insn. */
94
/* Next insn in list. */
95
struct vliw_insn_list *next;
98
static struct vliw_insn_list single_nop_insn = {
99
VLIW_NOP_TYPE, NULL, NULL, NULL, NULL, NULL, NULL };
101
static struct vliw_insn_list double_nop_insn = {
102
VLIW_NOP_TYPE, NULL, NULL, NULL, NULL, NULL, NULL };
108
struct vliw_insn_list *insn_list;
109
struct vliw_chain *next;
112
static struct vliw_chain *vliw_chain_top;
113
static struct vliw_chain *current_vliw_chain;
114
static struct vliw_chain *previous_vliw_chain;
115
static struct vliw_insn_list *current_vliw_insn;
117
const char comment_chars[] = ";";
118
const char line_comment_chars[] = "#";
119
const char line_separator_chars[] = "!";
120
const char EXP_CHARS[] = "eE";
121
const char FLT_CHARS[] = "dD";
123
static FRV_VLIW vliw;
125
/* Default machine */
127
#ifdef DEFAULT_CPU_FRV
128
#define DEFAULT_MACHINE bfd_mach_frv
129
#define DEFAULT_FLAGS EF_FRV_CPU_GENERIC
132
#ifdef DEFAULT_CPU_FR300
133
#define DEFAULT_MACHINE bfd_mach_fr300
134
#define DEFAULT_FLAGS EF_FRV_CPU_FR300
137
#ifdef DEFAULT_CPU_SIMPLE
138
#define DEFAULT_MACHINE bfd_mach_frvsimple
139
#define DEFAULT_FLAGS EF_FRV_CPU_SIMPLE
142
#ifdef DEFAULT_CPU_TOMCAT
143
#define DEFAULT_MACHINE bfd_mach_frvtomcat
144
#define DEFAULT_FLAGS EF_FRV_CPU_TOMCAT
147
#ifdef DEFAULT_CPU_FR400
148
#define DEFAULT_MACHINE bfd_mach_fr400
149
#define DEFAULT_FLAGS EF_FRV_CPU_FR400
152
#ifdef DEFAULT_CPU_FR550
153
#define DEFAULT_MACHINE bfd_mach_fr550
154
#define DEFAULT_FLAGS EF_FRV_CPU_FR550
157
#define DEFAULT_MACHINE bfd_mach_fr500
158
#define DEFAULT_FLAGS EF_FRV_CPU_FR500
167
# define DEFAULT_FDPIC EF_FRV_FDPIC
169
# define DEFAULT_FDPIC 0
172
static unsigned long frv_mach = bfd_mach_frv;
173
static bfd_boolean fr400_audio;
175
/* Flags to set in the elf header */
176
static flagword frv_flags = DEFAULT_FLAGS | DEFAULT_FDPIC;
178
static int frv_user_set_flags_p = 0;
179
static int frv_pic_p = 0;
180
static const char *frv_pic_flag = DEFAULT_FDPIC ? "-mfdpic" : (const char *)0;
182
/* Print tomcat-specific debugging info. */
183
static int tomcat_debug = 0;
185
/* Tomcat-specific NOP statistics. */
186
static int tomcat_stats = 0;
187
static int tomcat_doubles = 0;
188
static int tomcat_singles = 0;
190
/* Forward reference to static functions */
191
static void frv_set_flags (int);
192
static void frv_pic_ptr (int);
194
/* The target specific pseudo-ops which we support. */
195
const pseudo_typeS md_pseudo_table[] =
197
{ "eflags", frv_set_flags, 0 },
199
{ "picptr", frv_pic_ptr, 4 },
204
#define FRV_SHORTOPTS "G:"
205
const char * md_shortopts = FRV_SHORTOPTS;
207
#define OPTION_GPR_32 (OPTION_MD_BASE)
208
#define OPTION_GPR_64 (OPTION_MD_BASE + 1)
209
#define OPTION_FPR_32 (OPTION_MD_BASE + 2)
210
#define OPTION_FPR_64 (OPTION_MD_BASE + 3)
211
#define OPTION_SOFT_FLOAT (OPTION_MD_BASE + 4)
212
#define OPTION_DWORD_YES (OPTION_MD_BASE + 5)
213
#define OPTION_DWORD_NO (OPTION_MD_BASE + 6)
214
#define OPTION_DOUBLE (OPTION_MD_BASE + 7)
215
#define OPTION_NO_DOUBLE (OPTION_MD_BASE + 8)
216
#define OPTION_MEDIA (OPTION_MD_BASE + 9)
217
#define OPTION_NO_MEDIA (OPTION_MD_BASE + 10)
218
#define OPTION_CPU (OPTION_MD_BASE + 11)
219
#define OPTION_PIC (OPTION_MD_BASE + 12)
220
#define OPTION_BIGPIC (OPTION_MD_BASE + 13)
221
#define OPTION_LIBPIC (OPTION_MD_BASE + 14)
222
#define OPTION_MULADD (OPTION_MD_BASE + 15)
223
#define OPTION_NO_MULADD (OPTION_MD_BASE + 16)
224
#define OPTION_TOMCAT_DEBUG (OPTION_MD_BASE + 17)
225
#define OPTION_TOMCAT_STATS (OPTION_MD_BASE + 18)
226
#define OPTION_PACK (OPTION_MD_BASE + 19)
227
#define OPTION_NO_PACK (OPTION_MD_BASE + 20)
228
#define OPTION_FDPIC (OPTION_MD_BASE + 21)
229
#define OPTION_NOPIC (OPTION_MD_BASE + 22)
231
struct option md_longopts[] =
233
{ "mgpr-32", no_argument, NULL, OPTION_GPR_32 },
234
{ "mgpr-64", no_argument, NULL, OPTION_GPR_64 },
235
{ "mfpr-32", no_argument, NULL, OPTION_FPR_32 },
236
{ "mfpr-64", no_argument, NULL, OPTION_FPR_64 },
237
{ "mhard-float", no_argument, NULL, OPTION_FPR_64 },
238
{ "msoft-float", no_argument, NULL, OPTION_SOFT_FLOAT },
239
{ "mdword", no_argument, NULL, OPTION_DWORD_YES },
240
{ "mno-dword", no_argument, NULL, OPTION_DWORD_NO },
241
{ "mdouble", no_argument, NULL, OPTION_DOUBLE },
242
{ "mno-double", no_argument, NULL, OPTION_NO_DOUBLE },
243
{ "mmedia", no_argument, NULL, OPTION_MEDIA },
244
{ "mno-media", no_argument, NULL, OPTION_NO_MEDIA },
245
{ "mcpu", required_argument, NULL, OPTION_CPU },
246
{ "mpic", no_argument, NULL, OPTION_PIC },
247
{ "mPIC", no_argument, NULL, OPTION_BIGPIC },
248
{ "mlibrary-pic", no_argument, NULL, OPTION_LIBPIC },
249
{ "mmuladd", no_argument, NULL, OPTION_MULADD },
250
{ "mno-muladd", no_argument, NULL, OPTION_NO_MULADD },
251
{ "mtomcat-debug", no_argument, NULL, OPTION_TOMCAT_DEBUG },
252
{ "mtomcat-stats", no_argument, NULL, OPTION_TOMCAT_STATS },
253
{ "mpack", no_argument, NULL, OPTION_PACK },
254
{ "mno-pack", no_argument, NULL, OPTION_NO_PACK },
255
{ "mfdpic", no_argument, NULL, OPTION_FDPIC },
256
{ "mnopic", no_argument, NULL, OPTION_NOPIC },
257
{ NULL, no_argument, NULL, 0 },
260
size_t md_longopts_size = sizeof (md_longopts);
262
/* What value to give to bfd_set_gp_size. */
263
static int g_switch_value = 8;
266
md_parse_option (int c, char *arg)
274
g_switch_value = atoi (arg);
275
if (! g_switch_value)
276
frv_flags |= EF_FRV_G0;
280
frv_flags = (frv_flags & ~EF_FRV_GPR_MASK) | EF_FRV_GPR_32;
284
frv_flags = (frv_flags & ~EF_FRV_GPR_MASK) | EF_FRV_GPR_64;
288
frv_flags = (frv_flags & ~EF_FRV_FPR_MASK) | EF_FRV_FPR_32;
292
frv_flags = (frv_flags & ~EF_FRV_FPR_MASK) | EF_FRV_FPR_64;
295
case OPTION_SOFT_FLOAT:
296
frv_flags = (frv_flags & ~EF_FRV_FPR_MASK) | EF_FRV_FPR_NONE;
299
case OPTION_DWORD_YES:
300
frv_flags = (frv_flags & ~EF_FRV_DWORD_MASK) | EF_FRV_DWORD_YES;
303
case OPTION_DWORD_NO:
304
frv_flags = (frv_flags & ~EF_FRV_DWORD_MASK) | EF_FRV_DWORD_NO;
308
frv_flags |= EF_FRV_DOUBLE;
311
case OPTION_NO_DOUBLE:
312
frv_flags &= ~EF_FRV_DOUBLE;
316
frv_flags |= EF_FRV_MEDIA;
319
case OPTION_NO_MEDIA:
320
frv_flags &= ~EF_FRV_MEDIA;
324
frv_flags |= EF_FRV_MULADD;
327
case OPTION_NO_MULADD:
328
frv_flags &= ~EF_FRV_MULADD;
332
frv_flags &= ~EF_FRV_NOPACK;
336
frv_flags |= EF_FRV_NOPACK;
342
int cpu_flags = EF_FRV_CPU_GENERIC;
344
/* Identify the processor type */
346
if (strcmp (p, "frv") == 0)
348
cpu_flags = EF_FRV_CPU_GENERIC;
349
frv_mach = bfd_mach_frv;
352
else if (strcmp (p, "fr500") == 0)
354
cpu_flags = EF_FRV_CPU_FR500;
355
frv_mach = bfd_mach_fr500;
358
else if (strcmp (p, "fr550") == 0)
360
cpu_flags = EF_FRV_CPU_FR550;
361
frv_mach = bfd_mach_fr550;
364
else if (strcmp (p, "fr450") == 0)
366
cpu_flags = EF_FRV_CPU_FR450;
367
frv_mach = bfd_mach_fr450;
370
else if (strcmp (p, "fr405") == 0)
372
cpu_flags = EF_FRV_CPU_FR405;
373
frv_mach = bfd_mach_fr400;
377
else if (strcmp (p, "fr400") == 0)
379
cpu_flags = EF_FRV_CPU_FR400;
380
frv_mach = bfd_mach_fr400;
384
else if (strcmp (p, "fr300") == 0)
386
cpu_flags = EF_FRV_CPU_FR300;
387
frv_mach = bfd_mach_fr300;
390
else if (strcmp (p, "simple") == 0)
392
cpu_flags = EF_FRV_CPU_SIMPLE;
393
frv_mach = bfd_mach_frvsimple;
394
frv_flags |= EF_FRV_NOPACK;
397
else if (strcmp (p, "tomcat") == 0)
399
cpu_flags = EF_FRV_CPU_TOMCAT;
400
frv_mach = bfd_mach_frvtomcat;
405
as_fatal (_("Unknown cpu -mcpu=%s"), arg);
409
frv_flags = (frv_flags & ~EF_FRV_CPU_MASK) | cpu_flags;
414
frv_flags |= EF_FRV_PIC;
416
frv_pic_flag = "-fpic";
420
frv_flags |= EF_FRV_BIGPIC;
422
frv_pic_flag = "-fPIC";
426
frv_flags |= (EF_FRV_LIBPIC | EF_FRV_G0);
428
frv_pic_flag = "-mlibrary-pic";
433
frv_flags |= EF_FRV_FDPIC;
434
frv_pic_flag = "-mfdpic";
438
frv_flags &= ~(EF_FRV_FDPIC | EF_FRV_PIC
439
| EF_FRV_BIGPIC | EF_FRV_LIBPIC);
443
case OPTION_TOMCAT_DEBUG:
447
case OPTION_TOMCAT_STATS:
456
md_show_usage (FILE * stream)
458
fprintf (stream, _("FRV specific command line options:\n"));
459
fprintf (stream, _("-G n Put data <= n bytes in the small data area\n"));
460
fprintf (stream, _("-mgpr-32 Mark generated file as only using 32 GPRs\n"));
461
fprintf (stream, _("-mgpr-64 Mark generated file as using all 64 GPRs\n"));
462
fprintf (stream, _("-mfpr-32 Mark generated file as only using 32 FPRs\n"));
463
fprintf (stream, _("-mfpr-64 Mark generated file as using all 64 FPRs\n"));
464
fprintf (stream, _("-msoft-float Mark generated file as using software FP\n"));
465
fprintf (stream, _("-mdword Mark generated file as using a 8-byte stack alignment\n"));
466
fprintf (stream, _("-mno-dword Mark generated file as using a 4-byte stack alignment\n"));
467
fprintf (stream, _("-mdouble Mark generated file as using double precision FP insns\n"));
468
fprintf (stream, _("-mmedia Mark generated file as using media insns\n"));
469
fprintf (stream, _("-mmuladd Mark generated file as using multiply add/subtract insns\n"));
470
fprintf (stream, _("-mpack Allow instructions to be packed\n"));
471
fprintf (stream, _("-mno-pack Do not allow instructions to be packed\n"));
472
fprintf (stream, _("-mpic Mark generated file as using small position independent code\n"));
473
fprintf (stream, _("-mPIC Mark generated file as using large position independent code\n"));
474
fprintf (stream, _("-mlibrary-pic Mark generated file as using position indepedent code for libraries\n"));
475
fprintf (stream, _("-mfdpic Assemble for the FDPIC ABI\n"));
476
fprintf (stream, _("-mnopic Disable -mpic, -mPIC, -mlibrary-pic and -mfdpic\n"));
477
fprintf (stream, _("-mcpu={fr500|fr550|fr400|fr405|fr450|fr300|frv|simple|tomcat}\n"));
478
fprintf (stream, _(" Record the cpu type\n"));
479
fprintf (stream, _("-mtomcat-stats Print out stats for tomcat workarounds\n"));
480
fprintf (stream, _("-mtomcat-debug Debug tomcat workarounds\n"));
487
/* Initialize the `cgen' interface. */
489
/* Set the machine number and endian. */
490
gas_cgen_cpu_desc = frv_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, 0,
491
CGEN_CPU_OPEN_ENDIAN,
494
frv_cgen_init_asm (gas_cgen_cpu_desc);
496
/* This is a callback from cgen to gas to parse operands. */
497
cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
499
/* Set the ELF flags if desired. */
501
bfd_set_private_flags (stdoutput, frv_flags);
503
/* Set the machine type */
504
bfd_default_set_arch_mach (stdoutput, bfd_arch_frv, frv_mach);
506
/* Set up gp size so we can put local common items in .sbss */
507
bfd_set_gp_size (stdoutput, g_switch_value);
509
frv_vliw_reset (& vliw, frv_mach, frv_flags);
513
frv_md_fdpic_enabled (void)
515
return (frv_flags & EF_FRV_FDPIC) != 0;
520
static struct vliw_insn_list *
521
frv_insert_vliw_insn (bfd_boolean count)
523
struct vliw_insn_list *vliw_insn_list_entry;
524
struct vliw_chain *vliw_chain_entry;
526
if (current_vliw_chain == NULL)
528
vliw_chain_entry = (struct vliw_chain *) xmalloc (sizeof (struct vliw_chain));
529
vliw_chain_entry->insn_count = 0;
530
vliw_chain_entry->insn_list = NULL;
531
vliw_chain_entry->next = NULL;
532
vliw_chain_entry->num = chain_num++;
535
vliw_chain_top = vliw_chain_entry;
536
current_vliw_chain = vliw_chain_entry;
537
if (previous_vliw_chain)
538
previous_vliw_chain->next = vliw_chain_entry;
541
vliw_insn_list_entry = (struct vliw_insn_list *) xmalloc (sizeof (struct vliw_insn_list));
542
vliw_insn_list_entry->type = VLIW_GENERIC_TYPE;
543
vliw_insn_list_entry->insn = NULL;
544
vliw_insn_list_entry->sym = NULL;
545
vliw_insn_list_entry->snop_frag = NULL;
546
vliw_insn_list_entry->dnop_frag = NULL;
547
vliw_insn_list_entry->next = NULL;
550
current_vliw_chain->insn_count++;
552
if (current_vliw_insn)
553
current_vliw_insn->next = vliw_insn_list_entry;
554
current_vliw_insn = vliw_insn_list_entry;
556
if (!current_vliw_chain->insn_list)
557
current_vliw_chain->insn_list = current_vliw_insn;
559
return vliw_insn_list_entry;
562
/* Identify the following cases:
564
1) A VLIW insn that contains both a branch and the branch destination.
565
This requires the insertion of two vliw instructions before the
566
branch. The first consists of two nops. The second consists of
569
2) A single instruction VLIW insn which is the destination of a branch
570
that is in the next VLIW insn. This requires the insertion of a vliw
571
insn containing two nops before the branch.
573
3) A double instruction VLIW insn which contains the destination of a
574
branch that is in the next VLIW insn. This requires the insertion of
575
a VLIW insn containing a single nop before the branch.
577
4) A single instruction VLIW insn which contains branch destination (x),
578
followed by a single instruction VLIW insn which does not contain
579
the branch to (x), followed by a VLIW insn which does contain the branch
580
to (x). This requires the insertion of a VLIW insn containing a single
581
nop before the VLIW instruction containing the branch.
584
#define FRV_IS_NOP(insn) (insn.buffer[0] == FRV_NOP_PACK || insn.buffer[0] == FRV_NOP_NOPACK)
585
#define FRV_NOP_PACK 0x00880000 /* ori.p gr0,0,gr0 */
586
#define FRV_NOP_NOPACK 0x80880000 /* ori gr0,0,gr0 */
588
/* Check a vliw insn for an insn of type containing the sym passed in label_sym. */
590
static struct vliw_insn_list *
591
frv_find_in_vliw (enum vliw_insn_type vliw_insn_type,
592
struct vliw_chain *this_chain,
596
struct vliw_insn_list *the_insn;
601
for (the_insn = this_chain->insn_list; the_insn; the_insn = the_insn->next)
603
if (the_insn->type == vliw_insn_type
604
&& the_insn->sym == label_sym)
613
/* A Vliw insn containing a single nop insn. */
616
/* A Vliw insn containing two nop insns. */
619
/* Two vliw insns. The first containing two nop insns.
620
The second contain a single nop insn. */
621
VLIW_DOUBLE_THEN_SINGLE_NOP
625
frv_debug_tomcat (struct vliw_chain *start_chain)
627
struct vliw_chain *this_chain;
628
struct vliw_insn_list *this_insn;
631
for (this_chain = start_chain; this_chain; this_chain = this_chain->next, i++)
633
fprintf (stderr, "\nVliw Insn #%d, #insns: %d\n", i, this_chain->insn_count);
635
for (this_insn = this_chain->insn_list; this_insn; this_insn = this_insn->next)
637
if (this_insn->type == VLIW_LABEL_TYPE)
638
fprintf (stderr, "Label Value: %p\n", this_insn->sym);
639
else if (this_insn->type == VLIW_BRANCH_TYPE)
640
fprintf (stderr, "%s to %p\n", this_insn->insn->base->name, this_insn->sym);
641
else if (this_insn->type == VLIW_BRANCH_HAS_NOPS)
642
fprintf (stderr, "nop'd %s to %p\n", this_insn->insn->base->name, this_insn->sym);
643
else if (this_insn->type == VLIW_NOP_TYPE)
644
fprintf (stderr, "Nop\n");
646
fprintf (stderr, " %s\n", this_insn->insn->base->name);
652
frv_adjust_vliw_count (struct vliw_chain *this_chain)
654
struct vliw_insn_list *this_insn;
656
this_chain->insn_count = 0;
658
for (this_insn = this_chain->insn_list;
660
this_insn = this_insn->next)
662
if (this_insn->type != VLIW_LABEL_TYPE)
663
this_chain->insn_count++;
668
/* Insert the desired nop combination in the vliw chain before insert_before_insn.
669
Rechain the vliw insn. */
671
static struct vliw_chain *
672
frv_tomcat_shuffle (enum vliw_nop_type this_nop_type,
673
struct vliw_chain *vliw_to_split,
674
struct vliw_insn_list *insert_before_insn)
677
bfd_boolean pack_prev = FALSE;
678
struct vliw_chain *return_me = NULL;
679
struct vliw_insn_list *prev_insn = NULL;
680
struct vliw_insn_list *curr_insn = vliw_to_split->insn_list;
682
struct vliw_chain *double_nop = (struct vliw_chain *) xmalloc (sizeof (struct vliw_chain));
683
struct vliw_chain *single_nop = (struct vliw_chain *) xmalloc (sizeof (struct vliw_chain));
684
struct vliw_chain *second_part = (struct vliw_chain *) xmalloc (sizeof (struct vliw_chain));
685
struct vliw_chain *curr_vliw = vliw_chain_top;
686
struct vliw_chain *prev_vliw = NULL;
688
while (curr_insn && curr_insn != insert_before_insn)
690
/* We can't set the packing bit on a label. If we have the case
694
branch that needs nops
695
Then don't set pack bit later. */
697
if (curr_insn->type != VLIW_LABEL_TYPE)
699
prev_insn = curr_insn;
700
curr_insn = curr_insn->next;
703
while (curr_vliw && curr_vliw != vliw_to_split)
705
prev_vliw = curr_vliw;
706
curr_vliw = curr_vliw->next;
709
switch (this_nop_type)
711
case VLIW_SINGLE_NOP:
714
/* Branch is first, Insert the NOP prior to this vliw insn. */
716
prev_vliw->next = single_nop;
718
vliw_chain_top = single_nop;
719
single_nop->next = vliw_to_split;
720
vliw_to_split->insn_list->type = VLIW_BRANCH_HAS_NOPS;
721
return_me = vliw_to_split;
725
/* Set the packing bit on the previous insn. */
728
char *buffer = prev_insn->address;
731
/* The branch is in the middle. Split this vliw insn into first
732
and second parts. Insert the NOP inbetween. */
734
second_part->insn_list = insert_before_insn;
735
second_part->insn_list->type = VLIW_BRANCH_HAS_NOPS;
736
second_part->next = vliw_to_split->next;
737
frv_adjust_vliw_count (second_part);
739
single_nop->next = second_part;
741
vliw_to_split->next = single_nop;
742
prev_insn->next = NULL;
744
return_me = second_part;
745
frv_adjust_vliw_count (vliw_to_split);
749
case VLIW_DOUBLE_NOP:
752
/* Branch is first, Insert the NOP prior to this vliw insn. */
754
prev_vliw->next = double_nop;
756
vliw_chain_top = double_nop;
758
double_nop->next = vliw_to_split;
759
return_me = vliw_to_split;
760
vliw_to_split->insn_list->type = VLIW_BRANCH_HAS_NOPS;
764
/* Set the packing bit on the previous insn. */
767
char *buffer = prev_insn->address;
771
/* The branch is in the middle. Split this vliw insn into first
772
and second parts. Insert the NOP inbetween. */
773
second_part->insn_list = insert_before_insn;
774
second_part->insn_list->type = VLIW_BRANCH_HAS_NOPS;
775
second_part->next = vliw_to_split->next;
776
frv_adjust_vliw_count (second_part);
778
double_nop->next = second_part;
780
vliw_to_split->next = single_nop;
781
prev_insn->next = NULL;
782
frv_adjust_vliw_count (vliw_to_split);
784
return_me = second_part;
788
case VLIW_DOUBLE_THEN_SINGLE_NOP:
789
double_nop->next = single_nop;
790
double_nop->insn_count = 2;
791
double_nop->insn_list = &double_nop_insn;
792
single_nop->insn_count = 1;
793
single_nop->insn_list = &single_nop_insn;
797
/* The branch is the first insn in this vliw. Don't split the vliw. Insert
798
the nops prior to this vliw. */
800
prev_vliw->next = double_nop;
802
vliw_chain_top = double_nop;
804
single_nop->next = vliw_to_split;
805
return_me = vliw_to_split;
806
vliw_to_split->insn_list->type = VLIW_BRANCH_HAS_NOPS;
810
/* Set the packing bit on the previous insn. */
813
char *buffer = prev_insn->address;
817
/* The branch is in the middle of this vliw insn. Split into first and
818
second parts. Insert the nop vliws in between. */
819
second_part->insn_list = insert_before_insn;
820
second_part->insn_list->type = VLIW_BRANCH_HAS_NOPS;
821
second_part->next = vliw_to_split->next;
822
frv_adjust_vliw_count (second_part);
824
single_nop->next = second_part;
826
vliw_to_split->next = double_nop;
827
prev_insn->next = NULL;
828
frv_adjust_vliw_count (vliw_to_split);
830
return_me = second_part;
839
frv_tomcat_analyze_vliw_chains (void)
841
struct vliw_chain *vliw1 = NULL;
842
struct vliw_chain *vliw2 = NULL;
843
struct vliw_chain *vliw3 = NULL;
845
struct vliw_insn_list *this_insn = NULL;
846
struct vliw_insn_list *temp_insn = NULL;
848
/* We potentially need to look at three VLIW insns to determine if the
849
workaround is required. Set them up. Ignore existing nops during analysis. */
851
#define FRV_SET_VLIW_WINDOW(VLIW1, VLIW2, VLIW3) \
852
if (VLIW1 && VLIW1->next) \
853
VLIW2 = VLIW1->next; \
856
if (VLIW2 && VLIW2->next) \
857
VLIW3 = VLIW2->next; \
861
vliw1 = vliw_chain_top;
865
FRV_SET_VLIW_WINDOW (vliw1, vliw2, vliw3);
870
if (vliw1->insn_count == 1)
872
/* check vliw1 for a label. */
873
if (vliw1->insn_list->type == VLIW_LABEL_TYPE)
875
temp_insn = frv_find_in_vliw (VLIW_BRANCH_TYPE, vliw2, vliw1->insn_list->sym);
878
vliw1 = frv_tomcat_shuffle (VLIW_DOUBLE_NOP, vliw2, vliw1->insn_list);
879
temp_insn->dnop_frag->fr_subtype = NOP_KEEP;
886
&& vliw2->insn_count == 1
887
&& (temp_insn = frv_find_in_vliw (VLIW_BRANCH_TYPE, vliw3, vliw1->insn_list->sym)) != NULL)
889
temp_insn->snop_frag->fr_subtype = NOP_KEEP;
890
vliw1 = frv_tomcat_shuffle (VLIW_SINGLE_NOP, vliw3, vliw3->insn_list);
898
if (vliw1->insn_count == 2)
900
/* Check vliw1 for a label. */
901
for (this_insn = vliw1->insn_list; this_insn; this_insn = this_insn->next)
903
if (this_insn->type == VLIW_LABEL_TYPE)
905
if ((temp_insn = frv_find_in_vliw (VLIW_BRANCH_TYPE, vliw2, this_insn->sym)) != NULL)
907
temp_insn->snop_frag->fr_subtype = NOP_KEEP;
908
vliw1 = frv_tomcat_shuffle (VLIW_SINGLE_NOP, vliw2, this_insn);
918
/* Examine each insn in this VLIW. Look for the workaround criteria. */
919
for (this_insn = vliw1->insn_list; this_insn; this_insn = this_insn->next)
921
/* Don't look at labels or nops. */
923
&& (this_insn->type == VLIW_LABEL_TYPE
924
|| this_insn->type == VLIW_NOP_TYPE
925
|| this_insn->type == VLIW_BRANCH_HAS_NOPS))
926
this_insn = this_insn->next;
934
if (frv_is_branch_insn (this_insn->insn))
936
if ((temp_insn = frv_find_in_vliw (VLIW_LABEL_TYPE, vliw1, this_insn->sym)) != NULL)
938
/* Insert [nop/nop] [nop] before branch. */
939
this_insn->snop_frag->fr_subtype = NOP_KEEP;
940
this_insn->dnop_frag->fr_subtype = NOP_KEEP;
941
vliw1 = frv_tomcat_shuffle (VLIW_DOUBLE_THEN_SINGLE_NOP, vliw1, this_insn);
948
/* This vliw insn checks out okay. Take a look at the next one. */
954
frv_tomcat_workaround (void)
956
if (frv_mach != bfd_mach_frvtomcat)
960
frv_debug_tomcat (vliw_chain_top);
962
frv_tomcat_analyze_vliw_chains ();
966
fprintf (stderr, "Inserted %d Single Nops\n", tomcat_singles);
967
fprintf (stderr, "Inserted %d Double Nops\n", tomcat_doubles);
972
fr550_check_insn_acc_range (frv_insn *insn, int low, int hi)
975
switch (CGEN_INSN_NUM (insn->insn))
977
case FRV_INSN_MADDACCS:
978
case FRV_INSN_MSUBACCS:
979
case FRV_INSN_MDADDACCS:
980
case FRV_INSN_MDSUBACCS:
981
case FRV_INSN_MASACCS:
982
case FRV_INSN_MDASACCS:
983
acc = insn->fields.f_ACC40Si;
984
if (acc < low || acc > hi)
985
return 1; /* out of range */
986
acc = insn->fields.f_ACC40Sk;
987
if (acc < low || acc > hi)
988
return 1; /* out of range */
990
case FRV_INSN_MMULHS:
991
case FRV_INSN_MMULHU:
992
case FRV_INSN_MMULXHS:
993
case FRV_INSN_MMULXHU:
994
case FRV_INSN_CMMULHS:
995
case FRV_INSN_CMMULHU:
996
case FRV_INSN_MQMULHS:
997
case FRV_INSN_MQMULHU:
998
case FRV_INSN_MQMULXHS:
999
case FRV_INSN_MQMULXHU:
1000
case FRV_INSN_CMQMULHS:
1001
case FRV_INSN_CMQMULHU:
1002
case FRV_INSN_MMACHS:
1003
case FRV_INSN_MMRDHS:
1004
case FRV_INSN_CMMACHS:
1005
case FRV_INSN_MQMACHS:
1006
case FRV_INSN_CMQMACHS:
1007
case FRV_INSN_MQXMACHS:
1008
case FRV_INSN_MQXMACXHS:
1009
case FRV_INSN_MQMACXHS:
1010
case FRV_INSN_MCPXRS:
1011
case FRV_INSN_MCPXIS:
1012
case FRV_INSN_CMCPXRS:
1013
case FRV_INSN_CMCPXIS:
1014
case FRV_INSN_MQCPXRS:
1015
case FRV_INSN_MQCPXIS:
1016
acc = insn->fields.f_ACC40Sk;
1017
if (acc < low || acc > hi)
1018
return 1; /* out of range */
1020
case FRV_INSN_MMACHU:
1021
case FRV_INSN_MMRDHU:
1022
case FRV_INSN_CMMACHU:
1023
case FRV_INSN_MQMACHU:
1024
case FRV_INSN_CMQMACHU:
1025
case FRV_INSN_MCPXRU:
1026
case FRV_INSN_MCPXIU:
1027
case FRV_INSN_CMCPXRU:
1028
case FRV_INSN_CMCPXIU:
1029
case FRV_INSN_MQCPXRU:
1030
case FRV_INSN_MQCPXIU:
1031
acc = insn->fields.f_ACC40Uk;
1032
if (acc < low || acc > hi)
1033
return 1; /* out of range */
1038
return 0; /* all is ok */
1042
fr550_check_acc_range (FRV_VLIW *vlw, frv_insn *insn)
1044
switch ((*vlw->current_vliw)[vlw->next_slot - 1])
1048
return fr550_check_insn_acc_range (insn, 0, 3);
1051
return fr550_check_insn_acc_range (insn, 4, 7);
1055
return 0; /* all is ok */
1058
/* Return true if the target implements instruction INSN. */
1061
target_implements_insn_p (const CGEN_INSN *insn)
1066
/* bfd_mach_frv or generic. */
1069
case bfd_mach_fr300:
1070
case bfd_mach_frvsimple:
1071
return CGEN_INSN_MACH_HAS_P (insn, MACH_SIMPLE);
1073
case bfd_mach_fr400:
1074
return ((fr400_audio || !CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_AUDIO))
1075
&& CGEN_INSN_MACH_HAS_P (insn, MACH_FR400));
1077
case bfd_mach_fr450:
1078
return CGEN_INSN_MACH_HAS_P (insn, MACH_FR450);
1080
case bfd_mach_fr500:
1081
return CGEN_INSN_MACH_HAS_P (insn, MACH_FR500);
1083
case bfd_mach_fr550:
1084
return CGEN_INSN_MACH_HAS_P (insn, MACH_FR550);
1089
md_assemble (char *str)
1093
int packing_constraint;
1094
finished_insnS finished_insn;
1095
fragS *double_nop_frag = NULL;
1096
fragS *single_nop_frag = NULL;
1097
struct vliw_insn_list *vliw_insn_list_entry = NULL;
1099
/* Initialize GAS's cgen interface for a new instruction. */
1100
gas_cgen_init_parse ();
1102
memset (&insn, 0, sizeof (insn));
1104
insn.insn = frv_cgen_assemble_insn
1105
(gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, &errmsg);
1109
as_bad ("%s", errmsg);
1113
/* If the cpu is tomcat, then we need to insert nops to workaround
1114
hardware limitations. We need to keep track of each vliw unit
1115
and examine the length of the unit and the individual insns
1116
within the unit to determine the number and location of the
1118
if (frv_mach == bfd_mach_frvtomcat)
1120
/* If we've just finished a VLIW insn OR this is a branch,
1121
then start up a new frag. Fill it with nops. We will get rid
1122
of those that are not required after we've seen all of the
1123
instructions but before we start resolving fixups. */
1124
if ( !FRV_IS_NOP (insn)
1125
&& (frv_is_branch_insn (insn.insn) || insn.fields.f_pack))
1129
frag_wane (frag_now);
1131
double_nop_frag = frag_now;
1132
buffer = frag_var (rs_machine_dependent, 8, 8, NOP_DELETE, NULL, 0, 0);
1133
md_number_to_chars (buffer, FRV_NOP_PACK, 4);
1134
md_number_to_chars (buffer+4, FRV_NOP_NOPACK, 4);
1136
frag_wane (frag_now);
1138
single_nop_frag = frag_now;
1139
buffer = frag_var (rs_machine_dependent, 4, 4, NOP_DELETE, NULL, 0, 0);
1140
md_number_to_chars (buffer, FRV_NOP_NOPACK, 4);
1143
vliw_insn_list_entry = frv_insert_vliw_insn (DO_COUNT);
1144
vliw_insn_list_entry->insn = insn.insn;
1145
if (frv_is_branch_insn (insn.insn))
1146
vliw_insn_list_entry->type = VLIW_BRANCH_TYPE;
1148
if ( !FRV_IS_NOP (insn)
1149
&& (frv_is_branch_insn (insn.insn) || insn.fields.f_pack))
1151
vliw_insn_list_entry->snop_frag = single_nop_frag;
1152
vliw_insn_list_entry->dnop_frag = double_nop_frag;
1156
/* Make sure that this insn does not violate the VLIW packing constraints. */
1157
/* -mno-pack disallows any packing whatsoever. */
1158
if (frv_flags & EF_FRV_NOPACK)
1160
if (! insn.fields.f_pack)
1162
as_bad (_("VLIW packing used for -mno-pack"));
1166
/* -mcpu=FRV is an idealized FR-V implementation that supports all of the
1167
instructions, don't do vliw checking. */
1168
else if (frv_mach != bfd_mach_frv)
1170
if (!target_implements_insn_p (insn.insn))
1172
as_bad (_("Instruction not supported by this architecture"));
1175
packing_constraint = frv_vliw_add_insn (& vliw, insn.insn);
1176
if (frv_mach == bfd_mach_fr550 && ! packing_constraint)
1177
packing_constraint = fr550_check_acc_range (& vliw, & insn);
1178
if (insn.fields.f_pack)
1179
frv_vliw_reset (& vliw, frv_mach, frv_flags);
1180
if (packing_constraint)
1182
as_bad (_("VLIW packing constraint violation"));
1187
/* Doesn't really matter what we pass for RELAX_P here. */
1188
gas_cgen_finish_insn (insn.insn, insn.buffer,
1189
CGEN_FIELDS_BITSIZE (& insn.fields), 1, &finished_insn);
1192
/* If the cpu is tomcat, then we need to insert nops to workaround
1193
hardware limitations. We need to keep track of each vliw unit
1194
and examine the length of the unit and the individual insns
1195
within the unit to determine the number and location of the
1197
if (frv_mach == bfd_mach_frvtomcat)
1199
if (vliw_insn_list_entry)
1200
vliw_insn_list_entry->address = finished_insn.addr;
1204
if (insn.fields.f_pack)
1206
/* We've completed a VLIW insn. */
1207
previous_vliw_chain = current_vliw_chain;
1208
current_vliw_chain = NULL;
1209
current_vliw_insn = NULL;
1214
/* The syntax in the manual says constants begin with '#'.
1215
We just ignore it. */
1218
md_operand (expressionS *expressionP)
1220
if (* input_line_pointer == '#')
1222
input_line_pointer ++;
1223
expression (expressionP);
1228
md_section_align (segT segment, valueT size)
1230
int align = bfd_get_section_alignment (stdoutput, segment);
1231
return ((size + (1 << align) - 1) & (-1 << align));
1235
md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
1240
/* Interface to relax_segment. */
1242
/* FIXME: Build table by hand, get it working, then machine generate. */
1243
const relax_typeS md_relax_table[] =
1246
{511 - 2 - 2, -512 - 2 + 2, 0, 2 },
1247
{0x2000000 - 1 - 2, -0x2000000 - 2, 2, 0 },
1248
{0x2000000 - 1 - 2, -0x2000000 - 2, 4, 0 }
1252
frv_relax_frag (fragS *fragP ATTRIBUTE_UNUSED, long stretch ATTRIBUTE_UNUSED)
1257
/* Return an initial guess of the length by which a fragment must grow to
1258
hold a branch to reach its destination.
1259
Also updates fr_type/fr_subtype as necessary.
1261
Called just before doing relaxation.
1262
Any symbol that is now undefined will not become defined.
1263
The guess for fr_var is ACTUALLY the growth beyond fr_fix.
1264
Whatever we do to grow fr_fix or fr_var contributes to our returned value.
1265
Although it may not be explicit in the frag, pretend fr_var starts with a
1269
md_estimate_size_before_relax (fragS *fragP, segT segment ATTRIBUTE_UNUSED)
1271
switch (fragP->fr_subtype)
1274
return fragP->fr_var;
1282
/* *fragP has been relaxed to its final size, and now needs to have
1283
the bytes inside it modified to conform to the new size.
1285
Called after relaxation is finished.
1286
fragP->fr_type == rs_machine_dependent.
1287
fragP->fr_subtype is the subtype of what the address relaxed to. */
1290
md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
1291
segT sec ATTRIBUTE_UNUSED,
1294
switch (fragP->fr_subtype)
1301
fragP->fr_fix = fragP->fr_var;
1307
/* Functions concerning relocs. */
1309
/* The location from which a PC relative jump should be calculated,
1310
given a PC relative reloc. */
1313
md_pcrel_from_section (fixS *fixP, segT sec)
1315
if (TC_FORCE_RELOCATION (fixP)
1316
|| (fixP->fx_addsy != (symbolS *) NULL
1317
&& S_GET_SEGMENT (fixP->fx_addsy) != sec))
1319
/* If we can't adjust this relocation, or if it references a
1320
local symbol in a different section (which
1321
TC_FORCE_RELOCATION can't check), let the linker figure it
1326
return (fixP->fx_frag->fr_address + fixP->fx_where) & ~1;
1329
/* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
1330
Returns BFD_RELOC_NONE if no reloc type can be found.
1331
*FIXP may be modified if desired. */
1333
bfd_reloc_code_real_type
1334
md_cgen_lookup_reloc (const CGEN_INSN *insn ATTRIBUTE_UNUSED,
1335
const CGEN_OPERAND *operand,
1338
switch (operand->type)
1340
case FRV_OPERAND_LABEL16:
1341
fixP->fx_pcrel = TRUE;
1342
return BFD_RELOC_FRV_LABEL16;
1344
case FRV_OPERAND_LABEL24:
1345
fixP->fx_pcrel = TRUE;
1347
if (fixP->fx_cgen.opinfo != 0)
1348
return fixP->fx_cgen.opinfo;
1350
return BFD_RELOC_FRV_LABEL24;
1352
case FRV_OPERAND_UHI16:
1353
case FRV_OPERAND_ULO16:
1354
case FRV_OPERAND_SLO16:
1355
case FRV_OPERAND_CALLANN:
1356
case FRV_OPERAND_LDANN:
1357
case FRV_OPERAND_LDDANN:
1358
/* The relocation type should be recorded in opinfo */
1359
if (fixP->fx_cgen.opinfo != 0)
1360
return fixP->fx_cgen.opinfo;
1363
case FRV_OPERAND_D12:
1364
case FRV_OPERAND_S12:
1365
if (fixP->fx_cgen.opinfo != 0)
1366
return fixP->fx_cgen.opinfo;
1368
return BFD_RELOC_FRV_GPREL12;
1370
case FRV_OPERAND_U12:
1371
return BFD_RELOC_FRV_GPRELU12;
1376
return BFD_RELOC_NONE;
1380
/* See whether we need to force a relocation into the output file.
1381
This is used to force out switch and PC relative relocations when
1385
frv_force_relocation (fixS *fix)
1387
switch (fix->fx_r_type < BFD_RELOC_UNUSED
1388
? (int) fix->fx_r_type
1389
: fix->fx_cgen.opinfo)
1391
case BFD_RELOC_FRV_GPREL12:
1392
case BFD_RELOC_FRV_GPRELU12:
1393
case BFD_RELOC_FRV_GPREL32:
1394
case BFD_RELOC_FRV_GPRELHI:
1395
case BFD_RELOC_FRV_GPRELLO:
1396
case BFD_RELOC_FRV_GOT12:
1397
case BFD_RELOC_FRV_GOTHI:
1398
case BFD_RELOC_FRV_GOTLO:
1399
case BFD_RELOC_FRV_FUNCDESC_VALUE:
1400
case BFD_RELOC_FRV_FUNCDESC_GOTOFF12:
1401
case BFD_RELOC_FRV_FUNCDESC_GOTOFFHI:
1402
case BFD_RELOC_FRV_FUNCDESC_GOTOFFLO:
1403
case BFD_RELOC_FRV_GOTOFF12:
1404
case BFD_RELOC_FRV_GOTOFFHI:
1405
case BFD_RELOC_FRV_GOTOFFLO:
1406
case BFD_RELOC_FRV_GETTLSOFF:
1407
case BFD_RELOC_FRV_TLSDESC_VALUE:
1408
case BFD_RELOC_FRV_GOTTLSDESC12:
1409
case BFD_RELOC_FRV_GOTTLSDESCHI:
1410
case BFD_RELOC_FRV_GOTTLSDESCLO:
1411
case BFD_RELOC_FRV_TLSMOFF12:
1412
case BFD_RELOC_FRV_TLSMOFFHI:
1413
case BFD_RELOC_FRV_TLSMOFFLO:
1414
case BFD_RELOC_FRV_GOTTLSOFF12:
1415
case BFD_RELOC_FRV_GOTTLSOFFHI:
1416
case BFD_RELOC_FRV_GOTTLSOFFLO:
1417
case BFD_RELOC_FRV_TLSOFF:
1418
case BFD_RELOC_FRV_TLSDESC_RELAX:
1419
case BFD_RELOC_FRV_GETTLSOFF_RELAX:
1420
case BFD_RELOC_FRV_TLSOFF_RELAX:
1427
return generic_force_reloc (fix);
1430
/* Apply a fixup that could be resolved within the assembler. */
1433
md_apply_fix (fixS *fixP, valueT *valP, segT seg)
1435
if (fixP->fx_addsy == 0)
1436
switch (fixP->fx_cgen.opinfo)
1438
case BFD_RELOC_FRV_HI16:
1441
case BFD_RELOC_FRV_LO16:
1445
/* We need relocations for these, even if their symbols reduce
1447
case BFD_RELOC_FRV_GPREL12:
1448
case BFD_RELOC_FRV_GPRELU12:
1449
case BFD_RELOC_FRV_GPREL32:
1450
case BFD_RELOC_FRV_GPRELHI:
1451
case BFD_RELOC_FRV_GPRELLO:
1452
case BFD_RELOC_FRV_GOT12:
1453
case BFD_RELOC_FRV_GOTHI:
1454
case BFD_RELOC_FRV_GOTLO:
1455
case BFD_RELOC_FRV_FUNCDESC_VALUE:
1456
case BFD_RELOC_FRV_FUNCDESC_GOTOFF12:
1457
case BFD_RELOC_FRV_FUNCDESC_GOTOFFHI:
1458
case BFD_RELOC_FRV_FUNCDESC_GOTOFFLO:
1459
case BFD_RELOC_FRV_GOTOFF12:
1460
case BFD_RELOC_FRV_GOTOFFHI:
1461
case BFD_RELOC_FRV_GOTOFFLO:
1462
case BFD_RELOC_FRV_GETTLSOFF:
1463
case BFD_RELOC_FRV_TLSDESC_VALUE:
1464
case BFD_RELOC_FRV_GOTTLSDESC12:
1465
case BFD_RELOC_FRV_GOTTLSDESCHI:
1466
case BFD_RELOC_FRV_GOTTLSDESCLO:
1467
case BFD_RELOC_FRV_TLSMOFF12:
1468
case BFD_RELOC_FRV_TLSMOFFHI:
1469
case BFD_RELOC_FRV_TLSMOFFLO:
1470
case BFD_RELOC_FRV_GOTTLSOFF12:
1471
case BFD_RELOC_FRV_GOTTLSOFFHI:
1472
case BFD_RELOC_FRV_GOTTLSOFFLO:
1473
case BFD_RELOC_FRV_TLSOFF:
1474
case BFD_RELOC_FRV_TLSDESC_RELAX:
1475
case BFD_RELOC_FRV_GETTLSOFF_RELAX:
1476
case BFD_RELOC_FRV_TLSOFF_RELAX:
1477
fixP->fx_addsy = abs_section_sym;
1481
switch (fixP->fx_cgen.opinfo)
1483
case BFD_RELOC_FRV_GETTLSOFF:
1484
case BFD_RELOC_FRV_TLSDESC_VALUE:
1485
case BFD_RELOC_FRV_GOTTLSDESC12:
1486
case BFD_RELOC_FRV_GOTTLSDESCHI:
1487
case BFD_RELOC_FRV_GOTTLSDESCLO:
1488
case BFD_RELOC_FRV_TLSMOFF12:
1489
case BFD_RELOC_FRV_TLSMOFFHI:
1490
case BFD_RELOC_FRV_TLSMOFFLO:
1491
case BFD_RELOC_FRV_GOTTLSOFF12:
1492
case BFD_RELOC_FRV_GOTTLSOFFHI:
1493
case BFD_RELOC_FRV_GOTTLSOFFLO:
1494
case BFD_RELOC_FRV_TLSOFF:
1495
case BFD_RELOC_FRV_TLSDESC_RELAX:
1496
case BFD_RELOC_FRV_GETTLSOFF_RELAX:
1497
case BFD_RELOC_FRV_TLSOFF_RELAX:
1498
/* Mark TLS symbols as such. */
1499
if (S_GET_SEGMENT (fixP->fx_addsy) != absolute_section)
1500
S_SET_THREAD_LOCAL (fixP->fx_addsy);
1504
gas_cgen_md_apply_fix (fixP, valP, seg);
1509
/* Write a value out to the object file, using the appropriate endianness. */
1512
frv_md_number_to_chars (char *buf, valueT val, int n)
1514
number_to_chars_bigendian (buf, val, n);
1518
md_atof (int type, char *litP, int *sizeP)
1520
return ieee_md_atof (type, litP, sizeP, TRUE);
1524
frv_fix_adjustable (fixS *fixP)
1526
bfd_reloc_code_real_type reloc_type;
1528
if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
1530
const CGEN_INSN *insn = NULL;
1531
int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
1532
const CGEN_OPERAND *operand = cgen_operand_lookup_by_num(gas_cgen_cpu_desc, opindex);
1533
reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
1536
reloc_type = fixP->fx_r_type;
1538
/* We need the symbol name for the VTABLE entries */
1539
if ( reloc_type == BFD_RELOC_VTABLE_INHERIT
1540
|| reloc_type == BFD_RELOC_VTABLE_ENTRY
1541
|| reloc_type == BFD_RELOC_FRV_GPREL12
1542
|| reloc_type == BFD_RELOC_FRV_GPRELU12)
1548
/* Allow user to set flags bits. */
1550
frv_set_flags (int arg ATTRIBUTE_UNUSED)
1552
flagword new_flags = get_absolute_expression ();
1553
flagword new_mask = ~ (flagword)0;
1555
frv_user_set_flags_p = 1;
1556
if (*input_line_pointer == ',')
1558
++input_line_pointer;
1559
new_mask = get_absolute_expression ();
1562
frv_flags = (frv_flags & ~new_mask) | (new_flags & new_mask);
1563
bfd_set_private_flags (stdoutput, frv_flags);
1566
/* Frv specific function to handle 4 byte initializations for pointers that are
1567
considered 'safe' for use with pic support. Until frv_frob_file{,_section}
1568
is run, we encode it a BFD_RELOC_CTOR, and it is turned back into a normal
1569
BFD_RELOC_32 at that time. */
1572
frv_pic_ptr (int nbytes)
1580
#ifdef md_flush_pending_output
1581
md_flush_pending_output ();
1584
if (is_it_end_of_statement ())
1586
demand_empty_rest_of_line ();
1590
#ifdef md_cons_align
1591
md_cons_align (nbytes);
1596
bfd_reloc_code_real_type reloc_type = BFD_RELOC_CTOR;
1598
if (strncasecmp (input_line_pointer, "funcdesc(", 9) == 0)
1600
input_line_pointer += 9;
1602
if (*input_line_pointer == ')')
1603
input_line_pointer++;
1605
as_bad (_("missing ')'"));
1606
reloc_type = BFD_RELOC_FRV_FUNCDESC;
1608
else if (strncasecmp (input_line_pointer, "tlsmoff(", 8) == 0)
1610
input_line_pointer += 8;
1612
if (*input_line_pointer == ')')
1613
input_line_pointer++;
1615
as_bad (_("missing ')'"));
1616
reloc_type = BFD_RELOC_FRV_TLSMOFF;
1623
fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &exp, 0,
1626
while (*input_line_pointer++ == ',');
1628
input_line_pointer--; /* Put terminator back into stream. */
1629
demand_empty_rest_of_line ();
1635
#define DPRINTF1(A) fprintf (stderr, A)
1636
#define DPRINTF2(A,B) fprintf (stderr, A, B)
1637
#define DPRINTF3(A,B,C) fprintf (stderr, A, B, C)
1641
#define DPRINTF2(A,B)
1642
#define DPRINTF3(A,B,C)
1645
/* Go through a the sections looking for relocations that are problematical for
1646
pic. If not pic, just note that this object can't be linked with pic. If
1647
it is pic, see if it needs to be marked so that it will be fixed up, or if
1648
not possible, issue an error. */
1651
frv_frob_file_section (bfd *abfd, asection *sec, void *ptr ATTRIBUTE_UNUSED)
1653
segment_info_type *seginfo = seg_info (sec);
1655
CGEN_CPU_DESC cd = gas_cgen_cpu_desc;
1656
flagword flags = bfd_get_section_flags (abfd, sec);
1658
/* Skip relocations in known sections (.ctors, .dtors, and .gcc_except_table)
1659
since we can fix those up by hand. */
1660
int known_section_p = (sec->name
1661
&& sec->name[0] == '.'
1662
&& ((sec->name[1] == 'c'
1663
&& strcmp (sec->name, ".ctor") == 0)
1664
|| (sec->name[1] == 'd'
1665
&& strcmp (sec->name, ".dtor") == 0)
1666
|| (sec->name[1] == 'g'
1667
&& strcmp (sec->name, ".gcc_except_table") == 0)));
1669
DPRINTF3 ("\nFrv section %s%s\n", sec->name, (known_section_p) ? ", known section" : "");
1670
if ((flags & SEC_ALLOC) == 0)
1672
DPRINTF1 ("\tSkipping non-loaded section\n");
1676
for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next)
1678
symbolS *s = fixp->fx_addsy;
1679
bfd_reloc_code_real_type reloc;
1682
const CGEN_OPERAND *operand;
1683
const CGEN_INSN *insn = fixp->fx_cgen.insn;
1687
DPRINTF1 ("\tSkipping reloc that has already been done\n");
1693
DPRINTF1 ("\tSkipping reloc that is PC relative\n");
1699
DPRINTF1 ("\tSkipping reloc without symbol\n");
1703
if (fixp->fx_r_type < BFD_RELOC_UNUSED)
1706
reloc = fixp->fx_r_type;
1710
opindex = (int) fixp->fx_r_type - (int) BFD_RELOC_UNUSED;
1711
operand = cgen_operand_lookup_by_num (cd, opindex);
1712
reloc = md_cgen_lookup_reloc (insn, operand, fixp);
1715
DPRINTF3 ("\treloc %s\t%s", bfd_get_reloc_code_name (reloc), S_GET_NAME (s));
1724
/* Skip relocations in known sections (.ctors, .dtors, and
1725
.gcc_except_table) since we can fix those up by hand. Also
1726
skip forward references to constants. Also skip a difference
1727
of two symbols, which still uses the BFD_RELOC_32 at this
1729
if (! known_section_p
1730
&& S_GET_SEGMENT (s) != absolute_section
1732
&& (flags & (SEC_READONLY | SEC_CODE)) == 0)
1738
/* FIXME -- should determine if any of the GP relocation really uses
1739
gr16 (which is not pic safe) or not. Right now, assume if we
1740
aren't being compiled with -mpic, the usage is non pic safe, but
1741
is safe with -mpic. */
1742
case BFD_RELOC_FRV_GPREL12:
1743
case BFD_RELOC_FRV_GPRELU12:
1744
case BFD_RELOC_FRV_GPREL32:
1745
case BFD_RELOC_FRV_GPRELHI:
1746
case BFD_RELOC_FRV_GPRELLO:
1747
non_pic_p = ! frv_pic_p;
1750
case BFD_RELOC_FRV_LO16:
1751
case BFD_RELOC_FRV_HI16:
1752
if (S_GET_SEGMENT (s) != absolute_section)
1756
case BFD_RELOC_VTABLE_INHERIT:
1757
case BFD_RELOC_VTABLE_ENTRY:
1761
/* If this is a blessed BFD_RELOC_32, convert it back to the normal
1763
case BFD_RELOC_CTOR:
1764
fixp->fx_r_type = BFD_RELOC_32;
1770
DPRINTF1 (" (Non-pic relocation)\n");
1772
as_warn_where (fixp->fx_file, fixp->fx_line,
1773
_("Relocation %s is not safe for %s"),
1774
bfd_get_reloc_code_name (reloc), frv_pic_flag);
1776
else if ((frv_flags & EF_FRV_NON_PIC_RELOCS) == 0)
1778
frv_flags |= EF_FRV_NON_PIC_RELOCS;
1779
bfd_set_private_flags (abfd, frv_flags);
1789
/* After all of the symbols have been adjusted, go over the file looking
1790
for any relocations that pic won't support. */
1793
frv_frob_file (void)
1795
bfd_map_over_sections (stdoutput, frv_frob_file_section, (void *) 0);
1799
frv_frob_label (symbolS *this_label)
1801
struct vliw_insn_list *vliw_insn_list_entry;
1803
dwarf2_emit_label (this_label);
1804
if (frv_mach != bfd_mach_frvtomcat)
1807
if (now_seg != text_section)
1810
vliw_insn_list_entry = frv_insert_vliw_insn(DONT_COUNT);
1811
vliw_insn_list_entry->type = VLIW_LABEL_TYPE;
1812
vliw_insn_list_entry->sym = this_label;
1816
frv_cgen_record_fixup_exp (fragS *frag,
1818
const CGEN_INSN *insn,
1820
const CGEN_OPERAND *operand,
1824
fixS * fixP = gas_cgen_record_fixup_exp (frag, where, insn, length,
1825
operand, opinfo, exp);
1827
if (frv_mach == bfd_mach_frvtomcat
1828
&& current_vliw_insn
1829
&& current_vliw_insn->type == VLIW_BRANCH_TYPE
1831
current_vliw_insn->sym = exp->X_add_symbol;