]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gas/config/tc-frv.c
Update year range in copyright notice of binutils files
[thirdparty/binutils-gdb.git] / gas / config / tc-frv.c
CommitLineData
0ebb9a87 1/* tc-frv.c -- Assembler for the Fujitsu FRV.
250d07de 2 Copyright (C) 2002-2021 Free Software Foundation, Inc.
0ebb9a87
DB
3
4 This file is part of GAS, the GNU Assembler.
5
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
ec2655a6 8 the Free Software Foundation; either version 3, or (at your option)
0ebb9a87
DB
9 any later version.
10
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.
15
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
4b4da160
NC
18 the Free Software Foundation, 51 Franklin Street - Fifth Floor,
19 Boston, MA 02110-1301, USA. */
0ebb9a87 20
0ebb9a87 21#include "as.h"
3739860c 22#include "subsegs.h"
0ebb9a87
DB
23#include "symcat.h"
24#include "opcodes/frv-desc.h"
25#include "opcodes/frv-opc.h"
26#include "cgen.h"
0ebb9a87
DB
27#include "elf/common.h"
28#include "elf/frv.h"
f2e25d93 29#include "dwarf2dbg.h"
0ebb9a87
DB
30
31/* Structure to hold all of the different components describing
32 an individual instruction. */
33typedef struct
34{
35 const CGEN_INSN * insn;
36 const CGEN_INSN * orig_insn;
37 CGEN_FIELDS fields;
38#if CGEN_INT_INSN_P
39 CGEN_INSN_INT buffer [1];
40#define INSN_VALUE(buf) (*(buf))
41#else
42 unsigned char buffer [CGEN_MAX_INSN_SIZE];
43#define INSN_VALUE(buf) (buf)
44#endif
45 char * addr;
46 fragS * frag;
47 int num_fixups;
48 fixS * fixups [GAS_CGEN_MAX_FIXUPS];
49 int indices [MAX_OPERAND_INSTANCES];
50}
51frv_insn;
52
53enum vliw_insn_type
54{
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. */
60};
61
3739860c 62/* We're going to use these in the fr_subtype field to mark
0ebb9a87
DB
63 whether to keep inserted nops. */
64
65#define NOP_KEEP 1 /* Keep these NOPS. */
66#define NOP_DELETE 2 /* Delete these NOPS. */
67
b34976b6
AM
68#define DO_COUNT TRUE
69#define DONT_COUNT FALSE
0ebb9a87
DB
70
71/* A list of insns within a VLIW insn. */
72struct vliw_insn_list
73{
74 /* The type of this insn. */
75 enum vliw_insn_type type;
76
77 /* The corresponding gas insn information. */
78 const CGEN_INSN *insn;
79
80 /* For branches and labels, the symbol that is referenced. */
81 symbolS *sym;
82
83 /* For branches, the frag containing the single nop that was generated. */
84 fragS *snop_frag;
85
86 /* For branches, the frag containing the double nop that was generated. */
87 fragS *dnop_frag;
88
89 /* Pointer to raw data for this insn. */
90 char *address;
91
92 /* Next insn in list. */
93 struct vliw_insn_list *next;
94};
95
96static struct vliw_insn_list single_nop_insn = {
97 VLIW_NOP_TYPE, NULL, NULL, NULL, NULL, NULL, NULL };
98
99static struct vliw_insn_list double_nop_insn = {
100 VLIW_NOP_TYPE, NULL, NULL, NULL, NULL, NULL, NULL };
101
102struct vliw_chain
103{
104 int num;
105 int insn_count;
106 struct vliw_insn_list *insn_list;
107 struct vliw_chain *next;
108};
109
110static struct vliw_chain *vliw_chain_top;
111static struct vliw_chain *current_vliw_chain;
112static struct vliw_chain *previous_vliw_chain;
113static struct vliw_insn_list *current_vliw_insn;
114
115const char comment_chars[] = ";";
116const char line_comment_chars[] = "#";
3739860c 117const char line_separator_chars[] = "!";
0ebb9a87
DB
118const char EXP_CHARS[] = "eE";
119const char FLT_CHARS[] = "dD";
120
121static FRV_VLIW vliw;
122
123/* Default machine */
124
125#ifdef DEFAULT_CPU_FRV
126#define DEFAULT_MACHINE bfd_mach_frv
127#define DEFAULT_FLAGS EF_FRV_CPU_GENERIC
128
129#else
130#ifdef DEFAULT_CPU_FR300
131#define DEFAULT_MACHINE bfd_mach_fr300
132#define DEFAULT_FLAGS EF_FRV_CPU_FR300
133
134#else
135#ifdef DEFAULT_CPU_SIMPLE
136#define DEFAULT_MACHINE bfd_mach_frvsimple
137#define DEFAULT_FLAGS EF_FRV_CPU_SIMPLE
138
139#else
140#ifdef DEFAULT_CPU_TOMCAT
141#define DEFAULT_MACHINE bfd_mach_frvtomcat
142#define DEFAULT_FLAGS EF_FRV_CPU_TOMCAT
143
144#else
145#ifdef DEFAULT_CPU_FR400
146#define DEFAULT_MACHINE bfd_mach_fr400
147#define DEFAULT_FLAGS EF_FRV_CPU_FR400
148
1ae31fee
DB
149#else
150#ifdef DEFAULT_CPU_FR550
151#define DEFAULT_MACHINE bfd_mach_fr550
152#define DEFAULT_FLAGS EF_FRV_CPU_FR550
153
0ebb9a87
DB
154#else
155#define DEFAULT_MACHINE bfd_mach_fr500
156#define DEFAULT_FLAGS EF_FRV_CPU_FR500
157#endif
158#endif
159#endif
160#endif
161#endif
1ae31fee 162#endif
0ebb9a87 163
996991aa
AO
164#ifdef TE_LINUX
165# define DEFAULT_FDPIC EF_FRV_FDPIC
166#else
167# define DEFAULT_FDPIC 0
168#endif
169
0ebb9a87 170static unsigned long frv_mach = bfd_mach_frv;
676a64f4 171static bfd_boolean fr400_audio;
0ebb9a87
DB
172
173/* Flags to set in the elf header */
996991aa 174static flagword frv_flags = DEFAULT_FLAGS | DEFAULT_FDPIC;
0ebb9a87
DB
175
176static int frv_user_set_flags_p = 0;
177static int frv_pic_p = 0;
996991aa 178static const char *frv_pic_flag = DEFAULT_FDPIC ? "-mfdpic" : (const char *)0;
0ebb9a87
DB
179
180/* Print tomcat-specific debugging info. */
181static int tomcat_debug = 0;
182
183/* Tomcat-specific NOP statistics. */
184static int tomcat_stats = 0;
185static int tomcat_doubles = 0;
186static int tomcat_singles = 0;
187
188/* Forward reference to static functions */
5a49b8ac
AM
189static void frv_set_flags (int);
190static void frv_pic_ptr (int);
0ebb9a87
DB
191
192/* The target specific pseudo-ops which we support. */
193const pseudo_typeS md_pseudo_table[] =
194{
195 { "eflags", frv_set_flags, 0 },
196 { "word", cons, 4 },
197 { "picptr", frv_pic_ptr, 4 },
0ebb9a87
DB
198 { NULL, NULL, 0 }
199};
200
201\f
202#define FRV_SHORTOPTS "G:"
203const char * md_shortopts = FRV_SHORTOPTS;
204
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)
99d09cdb 226#define OPTION_FDPIC (OPTION_MD_BASE + 21)
996991aa 227#define OPTION_NOPIC (OPTION_MD_BASE + 22)
0ebb9a87
DB
228
229struct option md_longopts[] =
230{
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 },
99d09cdb 253 { "mfdpic", no_argument, NULL, OPTION_FDPIC },
996991aa 254 { "mnopic", no_argument, NULL, OPTION_NOPIC },
0ebb9a87
DB
255 { NULL, no_argument, NULL, 0 },
256};
257
258size_t md_longopts_size = sizeof (md_longopts);
259
260/* What value to give to bfd_set_gp_size. */
261static int g_switch_value = 8;
262
263int
17b9d67d 264md_parse_option (int c, const char *arg)
0ebb9a87
DB
265{
266 switch (c)
267 {
268 default:
269 return 0;
270
271 case 'G':
272 g_switch_value = atoi (arg);
273 if (! g_switch_value)
274 frv_flags |= EF_FRV_G0;
275 break;
276
277 case OPTION_GPR_32:
278 frv_flags = (frv_flags & ~EF_FRV_GPR_MASK) | EF_FRV_GPR_32;
279 break;
280
281 case OPTION_GPR_64:
282 frv_flags = (frv_flags & ~EF_FRV_GPR_MASK) | EF_FRV_GPR_64;
283 break;
284
285 case OPTION_FPR_32:
286 frv_flags = (frv_flags & ~EF_FRV_FPR_MASK) | EF_FRV_FPR_32;
287 break;
288
289 case OPTION_FPR_64:
290 frv_flags = (frv_flags & ~EF_FRV_FPR_MASK) | EF_FRV_FPR_64;
291 break;
292
293 case OPTION_SOFT_FLOAT:
294 frv_flags = (frv_flags & ~EF_FRV_FPR_MASK) | EF_FRV_FPR_NONE;
295 break;
296
297 case OPTION_DWORD_YES:
298 frv_flags = (frv_flags & ~EF_FRV_DWORD_MASK) | EF_FRV_DWORD_YES;
299 break;
300
301 case OPTION_DWORD_NO:
302 frv_flags = (frv_flags & ~EF_FRV_DWORD_MASK) | EF_FRV_DWORD_NO;
303 break;
304
305 case OPTION_DOUBLE:
306 frv_flags |= EF_FRV_DOUBLE;
307 break;
308
309 case OPTION_NO_DOUBLE:
310 frv_flags &= ~EF_FRV_DOUBLE;
311 break;
312
313 case OPTION_MEDIA:
314 frv_flags |= EF_FRV_MEDIA;
315 break;
316
317 case OPTION_NO_MEDIA:
318 frv_flags &= ~EF_FRV_MEDIA;
319 break;
320
321 case OPTION_MULADD:
322 frv_flags |= EF_FRV_MULADD;
323 break;
324
325 case OPTION_NO_MULADD:
326 frv_flags &= ~EF_FRV_MULADD;
327 break;
328
329 case OPTION_PACK:
330 frv_flags &= ~EF_FRV_NOPACK;
331 break;
332
333 case OPTION_NO_PACK:
334 frv_flags |= EF_FRV_NOPACK;
335 break;
336
337 case OPTION_CPU:
338 {
17b9d67d 339 const char *p;
0ebb9a87
DB
340 int cpu_flags = EF_FRV_CPU_GENERIC;
341
342 /* Identify the processor type */
343 p = arg;
344 if (strcmp (p, "frv") == 0)
345 {
346 cpu_flags = EF_FRV_CPU_GENERIC;
347 frv_mach = bfd_mach_frv;
348 }
349
350 else if (strcmp (p, "fr500") == 0)
351 {
352 cpu_flags = EF_FRV_CPU_FR500;
353 frv_mach = bfd_mach_fr500;
354 }
355
1ae31fee
DB
356 else if (strcmp (p, "fr550") == 0)
357 {
358 cpu_flags = EF_FRV_CPU_FR550;
359 frv_mach = bfd_mach_fr550;
360 }
361
676a64f4
RS
362 else if (strcmp (p, "fr450") == 0)
363 {
364 cpu_flags = EF_FRV_CPU_FR450;
365 frv_mach = bfd_mach_fr450;
366 }
367
368 else if (strcmp (p, "fr405") == 0)
369 {
370 cpu_flags = EF_FRV_CPU_FR405;
371 frv_mach = bfd_mach_fr400;
372 fr400_audio = TRUE;
373 }
374
0ebb9a87
DB
375 else if (strcmp (p, "fr400") == 0)
376 {
377 cpu_flags = EF_FRV_CPU_FR400;
378 frv_mach = bfd_mach_fr400;
676a64f4 379 fr400_audio = FALSE;
0ebb9a87
DB
380 }
381
382 else if (strcmp (p, "fr300") == 0)
383 {
384 cpu_flags = EF_FRV_CPU_FR300;
385 frv_mach = bfd_mach_fr300;
386 }
387
388 else if (strcmp (p, "simple") == 0)
389 {
390 cpu_flags = EF_FRV_CPU_SIMPLE;
391 frv_mach = bfd_mach_frvsimple;
392 frv_flags |= EF_FRV_NOPACK;
393 }
394
395 else if (strcmp (p, "tomcat") == 0)
396 {
397 cpu_flags = EF_FRV_CPU_TOMCAT;
398 frv_mach = bfd_mach_frvtomcat;
399 }
400
401 else
402 {
bd3ba5d1 403 as_fatal (_("Unknown cpu -mcpu=%s"), arg);
0ebb9a87
DB
404 return 0;
405 }
406
407 frv_flags = (frv_flags & ~EF_FRV_CPU_MASK) | cpu_flags;
408 }
409 break;
410
411 case OPTION_PIC:
412 frv_flags |= EF_FRV_PIC;
413 frv_pic_p = 1;
414 frv_pic_flag = "-fpic";
415 break;
416
417 case OPTION_BIGPIC:
418 frv_flags |= EF_FRV_BIGPIC;
419 frv_pic_p = 1;
420 frv_pic_flag = "-fPIC";
421 break;
422
423 case OPTION_LIBPIC:
424 frv_flags |= (EF_FRV_LIBPIC | EF_FRV_G0);
425 frv_pic_p = 1;
426 frv_pic_flag = "-mlibrary-pic";
427 g_switch_value = 0;
428 break;
429
99d09cdb
AO
430 case OPTION_FDPIC:
431 frv_flags |= EF_FRV_FDPIC;
432 frv_pic_flag = "-mfdpic";
433 break;
434
996991aa
AO
435 case OPTION_NOPIC:
436 frv_flags &= ~(EF_FRV_FDPIC | EF_FRV_PIC
437 | EF_FRV_BIGPIC | EF_FRV_LIBPIC);
438 frv_pic_flag = 0;
439 break;
440
0ebb9a87
DB
441 case OPTION_TOMCAT_DEBUG:
442 tomcat_debug = 1;
443 break;
444
445 case OPTION_TOMCAT_STATS:
446 tomcat_stats = 1;
447 break;
448 }
449
450 return 1;
451}
452
453void
42477147 454md_show_usage (FILE * stream)
0ebb9a87
DB
455{
456 fprintf (stream, _("FRV specific command line options:\n"));
42477147
NC
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"));
33eaf5de 472 fprintf (stream, _("-mlibrary-pic Mark generated file as using position independent code for libraries\n"));
42477147
NC
473 fprintf (stream, _("-mfdpic Assemble for the FDPIC ABI\n"));
474 fprintf (stream, _("-mnopic Disable -mpic, -mPIC, -mlibrary-pic and -mfdpic\n"));
676a64f4 475 fprintf (stream, _("-mcpu={fr500|fr550|fr400|fr405|fr450|fr300|frv|simple|tomcat}\n"));
42477147
NC
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"));
3739860c 479}
0ebb9a87
DB
480
481\f
482void
5a49b8ac 483md_begin (void)
0ebb9a87
DB
484{
485 /* Initialize the `cgen' interface. */
3739860c 486
0ebb9a87
DB
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,
490 CGEN_ENDIAN_BIG,
491 CGEN_CPU_OPEN_END);
492 frv_cgen_init_asm (gas_cgen_cpu_desc);
493
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);
496
497 /* Set the ELF flags if desired. */
498 if (frv_flags)
499 bfd_set_private_flags (stdoutput, frv_flags);
500
501 /* Set the machine type */
502 bfd_default_set_arch_mach (stdoutput, bfd_arch_frv, frv_mach);
503
504 /* Set up gp size so we can put local common items in .sbss */
505 bfd_set_gp_size (stdoutput, g_switch_value);
506
507 frv_vliw_reset (& vliw, frv_mach, frv_flags);
508}
509
996991aa
AO
510bfd_boolean
511frv_md_fdpic_enabled (void)
512{
513 return (frv_flags & EF_FRV_FDPIC) != 0;
514}
515
0ebb9a87
DB
516int chain_num = 0;
517
5a49b8ac
AM
518static struct vliw_insn_list *
519frv_insert_vliw_insn (bfd_boolean count)
0ebb9a87
DB
520{
521 struct vliw_insn_list *vliw_insn_list_entry;
522 struct vliw_chain *vliw_chain_entry;
523
524 if (current_vliw_chain == NULL)
525 {
add39d23 526 vliw_chain_entry = XNEW (struct vliw_chain);
0ebb9a87
DB
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++;
531
532 if (!vliw_chain_top)
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;
537 }
538
add39d23 539 vliw_insn_list_entry = XNEW (struct vliw_insn_list);
0ebb9a87
DB
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;
546
547 if (count)
548 current_vliw_chain->insn_count++;
549
550 if (current_vliw_insn)
551 current_vliw_insn->next = vliw_insn_list_entry;
552 current_vliw_insn = vliw_insn_list_entry;
553
554 if (!current_vliw_chain->insn_list)
555 current_vliw_chain->insn_list = current_vliw_insn;
556
557 return vliw_insn_list_entry;
558}
559
560 /* Identify the following cases:
3739860c 561
0ebb9a87
DB
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
565 a single nop.
3739860c 566
0ebb9a87
DB
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.
3739860c 570
0ebb9a87
DB
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.
3739860c 574
0ebb9a87
DB
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.
3739860c 580
0ebb9a87
DB
581 */
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 */
585
586/* Check a vliw insn for an insn of type containing the sym passed in label_sym. */
587
588static struct vliw_insn_list *
5a49b8ac
AM
589frv_find_in_vliw (enum vliw_insn_type vliw_insn_type,
590 struct vliw_chain *this_chain,
591 symbolS *label_sym)
0ebb9a87
DB
592{
593
594 struct vliw_insn_list *the_insn;
595
596 if (!this_chain)
597 return NULL;
598
599 for (the_insn = this_chain->insn_list; the_insn; the_insn = the_insn->next)
600 {
601 if (the_insn->type == vliw_insn_type
602 && the_insn->sym == label_sym)
603 return the_insn;
604 }
605
606 return NULL;
607}
608
609enum vliw_nop_type
610{
611 /* A Vliw insn containing a single nop insn. */
612 VLIW_SINGLE_NOP,
3739860c 613
0ebb9a87
DB
614 /* A Vliw insn containing two nop insns. */
615 VLIW_DOUBLE_NOP,
616
3739860c 617 /* Two vliw insns. The first containing two nop insns.
0ebb9a87
DB
618 The second contain a single nop insn. */
619 VLIW_DOUBLE_THEN_SINGLE_NOP
620};
621
622static void
5a49b8ac 623frv_debug_tomcat (struct vliw_chain *start_chain)
0ebb9a87
DB
624{
625 struct vliw_chain *this_chain;
626 struct vliw_insn_list *this_insn;
627 int i = 1;
628
629 for (this_chain = start_chain; this_chain; this_chain = this_chain->next, i++)
630 {
631 fprintf (stderr, "\nVliw Insn #%d, #insns: %d\n", i, this_chain->insn_count);
632
633 for (this_insn = this_chain->insn_list; this_insn; this_insn = this_insn->next)
634 {
635 if (this_insn->type == VLIW_LABEL_TYPE)
8ad7c533 636 fprintf (stderr, "Label Value: %p\n", this_insn->sym);
0ebb9a87 637 else if (this_insn->type == VLIW_BRANCH_TYPE)
8ad7c533 638 fprintf (stderr, "%s to %p\n", this_insn->insn->base->name, this_insn->sym);
0ebb9a87 639 else if (this_insn->type == VLIW_BRANCH_HAS_NOPS)
8ad7c533 640 fprintf (stderr, "nop'd %s to %p\n", this_insn->insn->base->name, this_insn->sym);
0ebb9a87
DB
641 else if (this_insn->type == VLIW_NOP_TYPE)
642 fprintf (stderr, "Nop\n");
643 else
644 fprintf (stderr, " %s\n", this_insn->insn->base->name);
645 }
646 }
647}
648
0ebb9a87 649static void
5a49b8ac 650frv_adjust_vliw_count (struct vliw_chain *this_chain)
0ebb9a87
DB
651{
652 struct vliw_insn_list *this_insn;
653
654 this_chain->insn_count = 0;
655
656 for (this_insn = this_chain->insn_list;
657 this_insn;
658 this_insn = this_insn->next)
659 {
660 if (this_insn->type != VLIW_LABEL_TYPE)
661 this_chain->insn_count++;
662 }
663
664}
665
666/* Insert the desired nop combination in the vliw chain before insert_before_insn.
667 Rechain the vliw insn. */
668
0ebb9a87 669static struct vliw_chain *
5a49b8ac
AM
670frv_tomcat_shuffle (enum vliw_nop_type this_nop_type,
671 struct vliw_chain *vliw_to_split,
672 struct vliw_insn_list *insert_before_insn)
0ebb9a87
DB
673{
674
b34976b6 675 bfd_boolean pack_prev = FALSE;
0ebb9a87
DB
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;
679
add39d23
TS
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);
0ebb9a87
DB
683 struct vliw_chain *curr_vliw = vliw_chain_top;
684 struct vliw_chain *prev_vliw = NULL;
685
686 while (curr_insn && curr_insn != insert_before_insn)
687 {
688 /* We can't set the packing bit on a label. If we have the case
689 label 1:
690 label 2:
691 label 3:
692 branch that needs nops
693 Then don't set pack bit later. */
694
695 if (curr_insn->type != VLIW_LABEL_TYPE)
b34976b6 696 pack_prev = TRUE;
0ebb9a87
DB
697 prev_insn = curr_insn;
698 curr_insn = curr_insn->next;
3739860c 699 }
0ebb9a87
DB
700
701 while (curr_vliw && curr_vliw != vliw_to_split)
702 {
703 prev_vliw = curr_vliw;
704 curr_vliw = curr_vliw->next;
705 }
706
707 switch (this_nop_type)
708 {
709 case VLIW_SINGLE_NOP:
710 if (!prev_insn)
711 {
712 /* Branch is first, Insert the NOP prior to this vliw insn. */
713 if (prev_vliw)
714 prev_vliw->next = single_nop;
715 else
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;
720 }
721 else
722 {
723 /* Set the packing bit on the previous insn. */
724 if (pack_prev)
725 {
2132e3a3 726 char *buffer = prev_insn->address;
0ebb9a87
DB
727 buffer[0] |= 0x80;
728 }
729 /* The branch is in the middle. Split this vliw insn into first
2b0f3761 730 and second parts. Insert the NOP between. */
0ebb9a87
DB
731
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);
736
737 single_nop->next = second_part;
3739860c 738
0ebb9a87
DB
739 vliw_to_split->next = single_nop;
740 prev_insn->next = NULL;
3739860c 741
0ebb9a87
DB
742 return_me = second_part;
743 frv_adjust_vliw_count (vliw_to_split);
744 }
745 break;
746
747 case VLIW_DOUBLE_NOP:
748 if (!prev_insn)
749 {
750 /* Branch is first, Insert the NOP prior to this vliw insn. */
751 if (prev_vliw)
752 prev_vliw->next = double_nop;
753 else
754 vliw_chain_top = double_nop;
755
756 double_nop->next = vliw_to_split;
757 return_me = vliw_to_split;
758 vliw_to_split->insn_list->type = VLIW_BRANCH_HAS_NOPS;
759 }
760 else
761 {
762 /* Set the packing bit on the previous insn. */
763 if (pack_prev)
764 {
2132e3a3 765 char *buffer = prev_insn->address;
0ebb9a87
DB
766 buffer[0] |= 0x80;
767 }
768
769 /* The branch is in the middle. Split this vliw insn into first
2b0f3761 770 and second parts. Insert the NOP in between. */
0ebb9a87
DB
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);
3739860c 775
0ebb9a87 776 double_nop->next = second_part;
3739860c 777
0ebb9a87
DB
778 vliw_to_split->next = single_nop;
779 prev_insn->next = NULL;
780 frv_adjust_vliw_count (vliw_to_split);
3739860c 781
0ebb9a87
DB
782 return_me = second_part;
783 }
784 break;
785
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;
792
793 if (!prev_insn)
794 {
795 /* The branch is the first insn in this vliw. Don't split the vliw. Insert
796 the nops prior to this vliw. */
797 if (prev_vliw)
798 prev_vliw->next = double_nop;
799 else
800 vliw_chain_top = double_nop;
3739860c 801
0ebb9a87
DB
802 single_nop->next = vliw_to_split;
803 return_me = vliw_to_split;
804 vliw_to_split->insn_list->type = VLIW_BRANCH_HAS_NOPS;
805 }
806 else
807 {
808 /* Set the packing bit on the previous insn. */
809 if (pack_prev)
810 {
2132e3a3 811 char *buffer = prev_insn->address;
0ebb9a87
DB
812 buffer[0] |= 0x80;
813 }
814
815 /* The branch is in the middle of this vliw insn. Split into first and
3739860c 816 second parts. Insert the nop vliws in between. */
0ebb9a87
DB
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);
821
822 single_nop->next = second_part;
823
824 vliw_to_split->next = double_nop;
825 prev_insn->next = NULL;
826 frv_adjust_vliw_count (vliw_to_split);
827
828 return_me = second_part;
829 }
830 break;
831 }
832
833 return return_me;
834}
835
836static void
5a49b8ac 837frv_tomcat_analyze_vliw_chains (void)
0ebb9a87
DB
838{
839 struct vliw_chain *vliw1 = NULL;
840 struct vliw_chain *vliw2 = NULL;
841 struct vliw_chain *vliw3 = NULL;
842
843 struct vliw_insn_list *this_insn = NULL;
844 struct vliw_insn_list *temp_insn = NULL;
845
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. */
848
849#define FRV_SET_VLIW_WINDOW(VLIW1, VLIW2, VLIW3) \
850 if (VLIW1 && VLIW1->next) \
851 VLIW2 = VLIW1->next; \
852 else \
853 VLIW2 = NULL; \
854 if (VLIW2 && VLIW2->next) \
855 VLIW3 = VLIW2->next; \
856 else \
857 VLIW3 = NULL
858
859 vliw1 = vliw_chain_top;
860
dc1e8a47 861 workaround_top:
0ebb9a87
DB
862
863 FRV_SET_VLIW_WINDOW (vliw1, vliw2, vliw3);
864
865 if (!vliw1)
866 return;
867
868 if (vliw1->insn_count == 1)
869 {
870 /* check vliw1 for a label. */
871 if (vliw1->insn_list->type == VLIW_LABEL_TYPE)
872 {
873 temp_insn = frv_find_in_vliw (VLIW_BRANCH_TYPE, vliw2, vliw1->insn_list->sym);
874 if (temp_insn)
875 {
876 vliw1 = frv_tomcat_shuffle (VLIW_DOUBLE_NOP, vliw2, vliw1->insn_list);
877 temp_insn->dnop_frag->fr_subtype = NOP_KEEP;
878 vliw1 = vliw1->next;
879 if (tomcat_stats)
880 tomcat_doubles++;
881 goto workaround_top;
882 }
3739860c 883 else if (vliw2
0ebb9a87
DB
884 && vliw2->insn_count == 1
885 && (temp_insn = frv_find_in_vliw (VLIW_BRANCH_TYPE, vliw3, vliw1->insn_list->sym)) != NULL)
886 {
887 temp_insn->snop_frag->fr_subtype = NOP_KEEP;
888 vliw1 = frv_tomcat_shuffle (VLIW_SINGLE_NOP, vliw3, vliw3->insn_list);
889 if (tomcat_stats)
890 tomcat_singles++;
891 goto workaround_top;
892 }
893 }
894 }
895
896 if (vliw1->insn_count == 2)
897 {
91d6fa6a 898 /* Check vliw1 for a label. */
0ebb9a87
DB
899 for (this_insn = vliw1->insn_list; this_insn; this_insn = this_insn->next)
900 {
901 if (this_insn->type == VLIW_LABEL_TYPE)
902 {
a08333bb 903 if ((temp_insn = frv_find_in_vliw (VLIW_BRANCH_TYPE, vliw2, this_insn->sym)) != NULL)
0ebb9a87
DB
904 {
905 temp_insn->snop_frag->fr_subtype = NOP_KEEP;
906 vliw1 = frv_tomcat_shuffle (VLIW_SINGLE_NOP, vliw2, this_insn);
907 if (tomcat_stats)
908 tomcat_singles++;
909 }
910 else
911 vliw1 = vliw1->next;
912 goto workaround_top;
913 }
914 }
915 }
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)
918 {
919 /* Don't look at labels or nops. */
920 while (this_insn
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;
925
926 if (!this_insn)
927 {
928 vliw1 = vliw2;
929 goto workaround_top;
930 }
931
932 if (frv_is_branch_insn (this_insn->insn))
933 {
a08333bb 934 if ((temp_insn = frv_find_in_vliw (VLIW_LABEL_TYPE, vliw1, this_insn->sym)) != NULL)
0ebb9a87
DB
935 {
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);
940 goto workaround_top;
941 }
942 }
943
944
945 }
946 /* This vliw insn checks out okay. Take a look at the next one. */
947 vliw1 = vliw1->next;
948 goto workaround_top;
949}
950
951void
5a49b8ac 952frv_tomcat_workaround (void)
0ebb9a87
DB
953{
954 if (frv_mach != bfd_mach_frvtomcat)
955 return;
956
957 if (tomcat_debug)
958 frv_debug_tomcat (vliw_chain_top);
959
960 frv_tomcat_analyze_vliw_chains ();
961
962 if (tomcat_stats)
963 {
964 fprintf (stderr, "Inserted %d Single Nops\n", tomcat_singles);
965 fprintf (stderr, "Inserted %d Double Nops\n", tomcat_doubles);
966 }
967}
968
1ae31fee
DB
969static int
970fr550_check_insn_acc_range (frv_insn *insn, int low, int hi)
971{
972 int acc;
973 switch (CGEN_INSN_NUM (insn->insn))
974 {
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 */
987 break;
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:
3739860c 1002 case FRV_INSN_CMMACHS:
1ae31fee
DB
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 */
1017 break;
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 */
1032 break;
1033 default:
1034 break;
1035 }
1036 return 0; /* all is ok */
1037}
1038
1039static int
91d6fa6a 1040fr550_check_acc_range (FRV_VLIW *vlw, frv_insn *insn)
1ae31fee 1041{
91d6fa6a 1042 switch ((*vlw->current_vliw)[vlw->next_slot - 1])
1ae31fee
DB
1043 {
1044 case UNIT_FM0:
1045 case UNIT_FM2:
1046 return fr550_check_insn_acc_range (insn, 0, 3);
1047 case UNIT_FM1:
1048 case UNIT_FM3:
1049 return fr550_check_insn_acc_range (insn, 4, 7);
1050 default:
1051 break;
1052 }
1053 return 0; /* all is ok */
1054}
1055
676a64f4
RS
1056/* Return true if the target implements instruction INSN. */
1057
1058static bfd_boolean
1059target_implements_insn_p (const CGEN_INSN *insn)
1060{
1061 switch (frv_mach)
1062 {
1063 default:
1064 /* bfd_mach_frv or generic. */
1065 return TRUE;
1066
1067 case bfd_mach_fr300:
1068 case bfd_mach_frvsimple:
1069 return CGEN_INSN_MACH_HAS_P (insn, MACH_SIMPLE);
1070
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));
1074
1075 case bfd_mach_fr450:
1076 return CGEN_INSN_MACH_HAS_P (insn, MACH_FR450);
1077
1078 case bfd_mach_fr500:
1079 return CGEN_INSN_MACH_HAS_P (insn, MACH_FR500);
1080
1081 case bfd_mach_fr550:
1082 return CGEN_INSN_MACH_HAS_P (insn, MACH_FR550);
1083 }
1084}
1085
0ebb9a87 1086void
5a49b8ac 1087md_assemble (char *str)
0ebb9a87
DB
1088{
1089 frv_insn insn;
1090 char *errmsg;
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;
1096
1097 /* Initialize GAS's cgen interface for a new instruction. */
1098 gas_cgen_init_parse ();
1099
99d09cdb
AO
1100 memset (&insn, 0, sizeof (insn));
1101
0ebb9a87
DB
1102 insn.insn = frv_cgen_assemble_insn
1103 (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, &errmsg);
3739860c 1104
0ebb9a87
DB
1105 if (!insn.insn)
1106 {
20203fb9 1107 as_bad ("%s", errmsg);
0ebb9a87
DB
1108 return;
1109 }
3739860c 1110
0ebb9a87
DB
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
1115 required nops. */
1116 if (frv_mach == bfd_mach_frvtomcat)
1117 {
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
3739860c 1120 of those that are not required after we've seen all of the
0ebb9a87
DB
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))
1124 {
1125 char *buffer;
1126
1127 frag_wane (frag_now);
1128 frag_new (0);
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);
1133
1134 frag_wane (frag_now);
1135 frag_new (0);
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);
1139 }
1140
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;
1145
1146 if ( !FRV_IS_NOP (insn)
1147 && (frv_is_branch_insn (insn.insn) || insn.fields.f_pack))
1148 {
1149 vliw_insn_list_entry->snop_frag = single_nop_frag;
1150 vliw_insn_list_entry->dnop_frag = double_nop_frag;
1151 }
1152 }
1153
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)
1157 {
1158 if (! insn.fields.f_pack)
1159 {
1160 as_bad (_("VLIW packing used for -mno-pack"));
1161 return;
1162 }
1163 }
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)
1167 {
676a64f4
RS
1168 if (!target_implements_insn_p (insn.insn))
1169 {
1170 as_bad (_("Instruction not supported by this architecture"));
1171 return;
1172 }
0ebb9a87 1173 packing_constraint = frv_vliw_add_insn (& vliw, insn.insn);
1ae31fee
DB
1174 if (frv_mach == bfd_mach_fr550 && ! packing_constraint)
1175 packing_constraint = fr550_check_acc_range (& vliw, & insn);
0ebb9a87
DB
1176 if (insn.fields.f_pack)
1177 frv_vliw_reset (& vliw, frv_mach, frv_flags);
1178 if (packing_constraint)
1179 {
1180 as_bad (_("VLIW packing constraint violation"));
1181 return;
1182 }
1183 }
1184
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);
1188
1189
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
1194 required nops. */
1195 if (frv_mach == bfd_mach_frvtomcat)
1196 {
1197 if (vliw_insn_list_entry)
1198 vliw_insn_list_entry->address = finished_insn.addr;
1199 else
1200 abort();
1201
1202 if (insn.fields.f_pack)
1203 {
1204 /* We've completed a VLIW insn. */
1205 previous_vliw_chain = current_vliw_chain;
1206 current_vliw_chain = NULL;
1207 current_vliw_insn = NULL;
3739860c 1208 }
0ebb9a87
DB
1209 }
1210}
1211
1212/* The syntax in the manual says constants begin with '#'.
1213 We just ignore it. */
1214
3739860c 1215void
5a49b8ac 1216md_operand (expressionS *expressionP)
0ebb9a87
DB
1217{
1218 if (* input_line_pointer == '#')
1219 {
1220 input_line_pointer ++;
1221 expression (expressionP);
1222 }
1223}
1224
1225valueT
5a49b8ac 1226md_section_align (segT segment, valueT size)
0ebb9a87 1227{
fd361982 1228 int align = bfd_section_alignment (segment);
8d3842cd 1229 return ((size + (1 << align) - 1) & -(1 << align));
0ebb9a87
DB
1230}
1231
1232symbolS *
5a49b8ac 1233md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
0ebb9a87
DB
1234{
1235 return 0;
1236}
1237\f
1238/* Interface to relax_segment. */
1239
1240/* FIXME: Build table by hand, get it working, then machine generate. */
1241const relax_typeS md_relax_table[] =
1242{
1243 {1, 1, 0, 0},
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 }
1247};
1248
1249long
5a49b8ac 1250frv_relax_frag (fragS *fragP ATTRIBUTE_UNUSED, long stretch ATTRIBUTE_UNUSED)
0ebb9a87
DB
1251{
1252 return 0;
1253}
1254
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.
1258
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
1264 0 value. */
1265
1266int
5a49b8ac 1267md_estimate_size_before_relax (fragS *fragP, segT segment ATTRIBUTE_UNUSED)
0ebb9a87
DB
1268{
1269 switch (fragP->fr_subtype)
1270 {
1271 case NOP_KEEP:
1272 return fragP->fr_var;
1273
1274 default:
1275 case NOP_DELETE:
1276 return 0;
3739860c
L
1277 }
1278}
0ebb9a87
DB
1279
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.
1282
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. */
1286
1287void
5a49b8ac
AM
1288md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
1289 segT sec ATTRIBUTE_UNUSED,
1290 fragS *fragP)
0ebb9a87
DB
1291{
1292 switch (fragP->fr_subtype)
1293 {
1294 default:
1295 case NOP_DELETE:
1296 return;
1297
1298 case NOP_KEEP:
1299 fragP->fr_fix = fragP->fr_var;
1300 fragP->fr_var = 0;
3739860c 1301 return;
0ebb9a87
DB
1302 }
1303}
1304\f
1305/* Functions concerning relocs. */
1306
1307/* The location from which a PC relative jump should be calculated,
1308 given a PC relative reloc. */
1309
1310long
5a49b8ac 1311md_pcrel_from_section (fixS *fixP, segT sec)
0ebb9a87 1312{
a939d090
AO
1313 if (TC_FORCE_RELOCATION (fixP)
1314 || (fixP->fx_addsy != (symbolS *) NULL
1315 && S_GET_SEGMENT (fixP->fx_addsy) != sec))
1316 {
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
1320 out. */
1321 return 0;
1322 }
0ebb9a87
DB
1323
1324 return (fixP->fx_frag->fr_address + fixP->fx_where) & ~1;
1325}
1326
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. */
1330
1331bfd_reloc_code_real_type
5a49b8ac
AM
1332md_cgen_lookup_reloc (const CGEN_INSN *insn ATTRIBUTE_UNUSED,
1333 const CGEN_OPERAND *operand,
1334 fixS *fixP)
0ebb9a87
DB
1335{
1336 switch (operand->type)
1337 {
1338 case FRV_OPERAND_LABEL16:
b34976b6 1339 fixP->fx_pcrel = TRUE;
0ebb9a87
DB
1340 return BFD_RELOC_FRV_LABEL16;
1341
1342 case FRV_OPERAND_LABEL24:
b34976b6 1343 fixP->fx_pcrel = TRUE;
90219bd0
AO
1344
1345 if (fixP->fx_cgen.opinfo != 0)
1346 return fixP->fx_cgen.opinfo;
1347
0ebb9a87
DB
1348 return BFD_RELOC_FRV_LABEL24;
1349
1350 case FRV_OPERAND_UHI16:
1351 case FRV_OPERAND_ULO16:
1352 case FRV_OPERAND_SLO16:
90219bd0
AO
1353 case FRV_OPERAND_CALLANN:
1354 case FRV_OPERAND_LDANN:
1355 case FRV_OPERAND_LDDANN:
0ebb9a87
DB
1356 /* The relocation type should be recorded in opinfo */
1357 if (fixP->fx_cgen.opinfo != 0)
1358 return fixP->fx_cgen.opinfo;
1359 break;
1360
1361 case FRV_OPERAND_D12:
1362 case FRV_OPERAND_S12:
99d09cdb
AO
1363 if (fixP->fx_cgen.opinfo != 0)
1364 return fixP->fx_cgen.opinfo;
1365
0ebb9a87
DB
1366 return BFD_RELOC_FRV_GPREL12;
1367
1368 case FRV_OPERAND_U12:
1369 return BFD_RELOC_FRV_GPRELU12;
1370
3739860c 1371 default:
0ebb9a87
DB
1372 break;
1373 }
1374 return BFD_RELOC_NONE;
1375}
1376
1377
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
1380 relaxing. */
1381
1382int
5a49b8ac 1383frv_force_relocation (fixS *fix)
0ebb9a87 1384{
90219bd0 1385 switch (fix->fx_r_type < BFD_RELOC_UNUSED
f17c130b 1386 ? (int) fix->fx_r_type
90219bd0
AO
1387 : fix->fx_cgen.opinfo)
1388 {
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:
1419 return 1;
1420
1421 default:
1422 break;
1423 }
0ebb9a87 1424
ae6063d4 1425 return generic_force_reloc (fix);
0ebb9a87 1426}
99d09cdb
AO
1427
1428/* Apply a fixup that could be resolved within the assembler. */
1429
1430void
5a49b8ac 1431md_apply_fix (fixS *fixP, valueT *valP, segT seg)
99d09cdb
AO
1432{
1433 if (fixP->fx_addsy == 0)
1434 switch (fixP->fx_cgen.opinfo)
1435 {
1436 case BFD_RELOC_FRV_HI16:
1437 *valP >>= 16;
1438 /* Fall through. */
1439 case BFD_RELOC_FRV_LO16:
1440 *valP &= 0xffff;
1441 break;
90219bd0
AO
1442
1443 /* We need relocations for these, even if their symbols reduce
1444 to constants. */
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:
455bde50 1475 fixP->fx_addsy = abs_section_sym;
90219bd0
AO
1476 break;
1477 }
1478 else
1479 switch (fixP->fx_cgen.opinfo)
1480 {
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);
1499 break;
99d09cdb
AO
1500 }
1501
55cf6793 1502 gas_cgen_md_apply_fix (fixP, valP, seg);
99d09cdb
AO
1503 return;
1504}
1505
0ebb9a87
DB
1506\f
1507/* Write a value out to the object file, using the appropriate endianness. */
1508
1509void
5a49b8ac 1510frv_md_number_to_chars (char *buf, valueT val, int n)
0ebb9a87
DB
1511{
1512 number_to_chars_bigendian (buf, val, n);
1513}
1514
6d4af3c2 1515const char *
5a49b8ac 1516md_atof (int type, char *litP, int *sizeP)
0ebb9a87 1517{
499ac353 1518 return ieee_md_atof (type, litP, sizeP, TRUE);
0ebb9a87
DB
1519}
1520
b34976b6 1521bfd_boolean
5a49b8ac 1522frv_fix_adjustable (fixS *fixP)
0ebb9a87
DB
1523{
1524 bfd_reloc_code_real_type reloc_type;
1525
1526 if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
1527 {
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);
1532 }
1533 else
1534 reloc_type = fixP->fx_r_type;
1535
0ebb9a87
DB
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)
1541 return 0;
1542
1543 return 1;
1544}
1545
1546/* Allow user to set flags bits. */
1547void
5a49b8ac 1548frv_set_flags (int arg ATTRIBUTE_UNUSED)
0ebb9a87
DB
1549{
1550 flagword new_flags = get_absolute_expression ();
1551 flagword new_mask = ~ (flagword)0;
1552
1553 frv_user_set_flags_p = 1;
1554 if (*input_line_pointer == ',')
1555 {
1556 ++input_line_pointer;
1557 new_mask = get_absolute_expression ();
1558 }
1559
1560 frv_flags = (frv_flags & ~new_mask) | (new_flags & new_mask);
1561 bfd_set_private_flags (stdoutput, frv_flags);
1562}
1563
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. */
1568
1569void
5a49b8ac 1570frv_pic_ptr (int nbytes)
0ebb9a87
DB
1571{
1572 expressionS exp;
1573 char *p;
1574
1575 if (nbytes != 4)
1576 abort ();
1577
1578#ifdef md_flush_pending_output
1579 md_flush_pending_output ();
1580#endif
1581
1582 if (is_it_end_of_statement ())
1583 {
1584 demand_empty_rest_of_line ();
1585 return;
1586 }
1587
1588#ifdef md_cons_align
1589 md_cons_align (nbytes);
1590#endif
1591
1592 do
1593 {
99d09cdb 1594 bfd_reloc_code_real_type reloc_type = BFD_RELOC_CTOR;
3739860c 1595
99d09cdb
AO
1596 if (strncasecmp (input_line_pointer, "funcdesc(", 9) == 0)
1597 {
1598 input_line_pointer += 9;
1599 expression (&exp);
1600 if (*input_line_pointer == ')')
1601 input_line_pointer++;
1602 else
bd3ba5d1 1603 as_bad (_("missing ')'"));
99d09cdb
AO
1604 reloc_type = BFD_RELOC_FRV_FUNCDESC;
1605 }
90219bd0
AO
1606 else if (strncasecmp (input_line_pointer, "tlsmoff(", 8) == 0)
1607 {
1608 input_line_pointer += 8;
1609 expression (&exp);
1610 if (*input_line_pointer == ')')
1611 input_line_pointer++;
1612 else
bd3ba5d1 1613 as_bad (_("missing ')'"));
90219bd0
AO
1614 reloc_type = BFD_RELOC_FRV_TLSMOFF;
1615 }
99d09cdb
AO
1616 else
1617 expression (&exp);
0ebb9a87
DB
1618
1619 p = frag_more (4);
1620 memset (p, 0, 4);
1621 fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &exp, 0,
99d09cdb 1622 reloc_type);
0ebb9a87
DB
1623 }
1624 while (*input_line_pointer++ == ',');
1625
1626 input_line_pointer--; /* Put terminator back into stream. */
1627 demand_empty_rest_of_line ();
1628}
1629
1630\f
1631
1632#ifdef DEBUG
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)
1636
1637#else
1638#define DPRINTF1(A)
1639#define DPRINTF2(A,B)
1640#define DPRINTF3(A,B,C)
1641#endif
1642
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. */
1647
1648static void
5a49b8ac 1649frv_frob_file_section (bfd *abfd, asection *sec, void *ptr ATTRIBUTE_UNUSED)
0ebb9a87
DB
1650{
1651 segment_info_type *seginfo = seg_info (sec);
1652 fixS *fixp;
1653 CGEN_CPU_DESC cd = gas_cgen_cpu_desc;
fd361982 1654 flagword flags = bfd_section_flags (sec);
0ebb9a87
DB
1655
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)));
1666
1667 DPRINTF3 ("\nFrv section %s%s\n", sec->name, (known_section_p) ? ", known section" : "");
1668 if ((flags & SEC_ALLOC) == 0)
1669 {
1670 DPRINTF1 ("\tSkipping non-loaded section\n");
1671 return;
1672 }
1673
1674 for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next)
1675 {
1676 symbolS *s = fixp->fx_addsy;
1677 bfd_reloc_code_real_type reloc;
1678 int non_pic_p;
1679 int opindex;
1680 const CGEN_OPERAND *operand;
1681 const CGEN_INSN *insn = fixp->fx_cgen.insn;
1682
1683 if (fixp->fx_done)
1684 {
1685 DPRINTF1 ("\tSkipping reloc that has already been done\n");
1686 continue;
1687 }
1688
1689 if (fixp->fx_pcrel)
1690 {
1691 DPRINTF1 ("\tSkipping reloc that is PC relative\n");
1692 continue;
1693 }
1694
1695 if (! s)
1696 {
1697 DPRINTF1 ("\tSkipping reloc without symbol\n");
1698 continue;
1699 }
1700
1701 if (fixp->fx_r_type < BFD_RELOC_UNUSED)
1702 {
1703 opindex = -1;
1704 reloc = fixp->fx_r_type;
1705 }
1706 else
1707 {
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);
1711 }
1712
1713 DPRINTF3 ("\treloc %s\t%s", bfd_get_reloc_code_name (reloc), S_GET_NAME (s));
1714
1715 non_pic_p = 0;
1716 switch (reloc)
1717 {
1718 default:
1719 break;
1720
1721 case BFD_RELOC_32:
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
1726 point. */
1727 if (! known_section_p
1728 && S_GET_SEGMENT (s) != absolute_section
1729 && !fixp->fx_subsy
1730 && (flags & (SEC_READONLY | SEC_CODE)) == 0)
1731 {
1732 non_pic_p = 1;
1733 }
1734 break;
1735
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;
1746 break;
1747
1748 case BFD_RELOC_FRV_LO16:
1749 case BFD_RELOC_FRV_HI16:
1750 if (S_GET_SEGMENT (s) != absolute_section)
1751 non_pic_p = 1;
1752 break;
1753
1754 case BFD_RELOC_VTABLE_INHERIT:
1755 case BFD_RELOC_VTABLE_ENTRY:
1756 non_pic_p = 1;
1757 break;
1758
1759 /* If this is a blessed BFD_RELOC_32, convert it back to the normal
1760 relocation. */
1761 case BFD_RELOC_CTOR:
1762 fixp->fx_r_type = BFD_RELOC_32;
1763 break;
1764 }
1765
1766 if (non_pic_p)
1767 {
1768 DPRINTF1 (" (Non-pic relocation)\n");
1769 if (frv_pic_p)
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);
1773
1774 else if ((frv_flags & EF_FRV_NON_PIC_RELOCS) == 0)
1775 {
1776 frv_flags |= EF_FRV_NON_PIC_RELOCS;
1777 bfd_set_private_flags (abfd, frv_flags);
1778 }
1779 }
1780#ifdef DEBUG
1781 else
1782 DPRINTF1 ("\n");
1783#endif
1784 }
1785}
1786
1787/* After all of the symbols have been adjusted, go over the file looking
1788 for any relocations that pic won't support. */
1789
1790void
5a49b8ac 1791frv_frob_file (void)
0ebb9a87 1792{
5a49b8ac 1793 bfd_map_over_sections (stdoutput, frv_frob_file_section, (void *) 0);
0ebb9a87
DB
1794}
1795
1796void
5a49b8ac 1797frv_frob_label (symbolS *this_label)
0ebb9a87
DB
1798{
1799 struct vliw_insn_list *vliw_insn_list_entry;
1800
f2e25d93 1801 dwarf2_emit_label (this_label);
0ebb9a87
DB
1802 if (frv_mach != bfd_mach_frvtomcat)
1803 return;
1804
1805 if (now_seg != text_section)
1806 return;
1807
1808 vliw_insn_list_entry = frv_insert_vliw_insn(DONT_COUNT);
1809 vliw_insn_list_entry->type = VLIW_LABEL_TYPE;
3739860c 1810 vliw_insn_list_entry->sym = this_label;
0ebb9a87
DB
1811}
1812
1813fixS *
5a49b8ac
AM
1814frv_cgen_record_fixup_exp (fragS *frag,
1815 int where,
1816 const CGEN_INSN *insn,
1817 int length,
1818 const CGEN_OPERAND *operand,
1819 int opinfo,
1820 expressionS *exp)
0ebb9a87
DB
1821{
1822 fixS * fixP = gas_cgen_record_fixup_exp (frag, where, insn, length,
1823 operand, opinfo, exp);
1824
1825 if (frv_mach == bfd_mach_frvtomcat
1826 && current_vliw_insn
1827 && current_vliw_insn->type == VLIW_BRANCH_TYPE
1828 && exp != NULL)
1829 current_vliw_insn->sym = exp->X_add_symbol;
3739860c 1830
0ebb9a87
DB
1831 return fixP;
1832}