]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gas/config/tc-frv.c
use xstrdup, xmemdup0 and concat more
[thirdparty/binutils-gdb.git] / gas / config / tc-frv.c
CommitLineData
0ebb9a87 1/* tc-frv.c -- Assembler for the Fujitsu FRV.
6f2750fe 2 Copyright (C) 2002-2016 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"
27#include "libbfd.h"
28#include "elf/common.h"
29#include "elf/frv.h"
f2e25d93 30#include "dwarf2dbg.h"
0ebb9a87
DB
31
32/* Structure to hold all of the different components describing
33 an individual instruction. */
34typedef struct
35{
36 const CGEN_INSN * insn;
37 const CGEN_INSN * orig_insn;
38 CGEN_FIELDS fields;
39#if CGEN_INT_INSN_P
40 CGEN_INSN_INT buffer [1];
41#define INSN_VALUE(buf) (*(buf))
42#else
43 unsigned char buffer [CGEN_MAX_INSN_SIZE];
44#define INSN_VALUE(buf) (buf)
45#endif
46 char * addr;
47 fragS * frag;
48 int num_fixups;
49 fixS * fixups [GAS_CGEN_MAX_FIXUPS];
50 int indices [MAX_OPERAND_INSTANCES];
51}
52frv_insn;
53
54enum vliw_insn_type
55{
56 VLIW_GENERIC_TYPE, /* Don't care about this insn. */
57 VLIW_BRANCH_TYPE, /* A Branch. */
58 VLIW_LABEL_TYPE, /* A Label. */
59 VLIW_NOP_TYPE, /* A NOP. */
60 VLIW_BRANCH_HAS_NOPS /* A Branch that requires NOPS. */
61};
62
3739860c 63/* We're going to use these in the fr_subtype field to mark
0ebb9a87
DB
64 whether to keep inserted nops. */
65
66#define NOP_KEEP 1 /* Keep these NOPS. */
67#define NOP_DELETE 2 /* Delete these NOPS. */
68
b34976b6
AM
69#define DO_COUNT TRUE
70#define DONT_COUNT FALSE
0ebb9a87
DB
71
72/* A list of insns within a VLIW insn. */
73struct vliw_insn_list
74{
75 /* The type of this insn. */
76 enum vliw_insn_type type;
77
78 /* The corresponding gas insn information. */
79 const CGEN_INSN *insn;
80
81 /* For branches and labels, the symbol that is referenced. */
82 symbolS *sym;
83
84 /* For branches, the frag containing the single nop that was generated. */
85 fragS *snop_frag;
86
87 /* For branches, the frag containing the double nop that was generated. */
88 fragS *dnop_frag;
89
90 /* Pointer to raw data for this insn. */
91 char *address;
92
93 /* Next insn in list. */
94 struct vliw_insn_list *next;
95};
96
97static struct vliw_insn_list single_nop_insn = {
98 VLIW_NOP_TYPE, NULL, NULL, NULL, NULL, NULL, NULL };
99
100static struct vliw_insn_list double_nop_insn = {
101 VLIW_NOP_TYPE, NULL, NULL, NULL, NULL, NULL, NULL };
102
103struct vliw_chain
104{
105 int num;
106 int insn_count;
107 struct vliw_insn_list *insn_list;
108 struct vliw_chain *next;
109};
110
111static struct vliw_chain *vliw_chain_top;
112static struct vliw_chain *current_vliw_chain;
113static struct vliw_chain *previous_vliw_chain;
114static struct vliw_insn_list *current_vliw_insn;
115
116const char comment_chars[] = ";";
117const char line_comment_chars[] = "#";
3739860c 118const char line_separator_chars[] = "!";
0ebb9a87
DB
119const char EXP_CHARS[] = "eE";
120const char FLT_CHARS[] = "dD";
121
122static FRV_VLIW vliw;
123
124/* Default machine */
125
126#ifdef DEFAULT_CPU_FRV
127#define DEFAULT_MACHINE bfd_mach_frv
128#define DEFAULT_FLAGS EF_FRV_CPU_GENERIC
129
130#else
131#ifdef DEFAULT_CPU_FR300
132#define DEFAULT_MACHINE bfd_mach_fr300
133#define DEFAULT_FLAGS EF_FRV_CPU_FR300
134
135#else
136#ifdef DEFAULT_CPU_SIMPLE
137#define DEFAULT_MACHINE bfd_mach_frvsimple
138#define DEFAULT_FLAGS EF_FRV_CPU_SIMPLE
139
140#else
141#ifdef DEFAULT_CPU_TOMCAT
142#define DEFAULT_MACHINE bfd_mach_frvtomcat
143#define DEFAULT_FLAGS EF_FRV_CPU_TOMCAT
144
145#else
146#ifdef DEFAULT_CPU_FR400
147#define DEFAULT_MACHINE bfd_mach_fr400
148#define DEFAULT_FLAGS EF_FRV_CPU_FR400
149
1ae31fee
DB
150#else
151#ifdef DEFAULT_CPU_FR550
152#define DEFAULT_MACHINE bfd_mach_fr550
153#define DEFAULT_FLAGS EF_FRV_CPU_FR550
154
0ebb9a87
DB
155#else
156#define DEFAULT_MACHINE bfd_mach_fr500
157#define DEFAULT_FLAGS EF_FRV_CPU_FR500
158#endif
159#endif
160#endif
161#endif
162#endif
1ae31fee 163#endif
0ebb9a87 164
996991aa
AO
165#ifdef TE_LINUX
166# define DEFAULT_FDPIC EF_FRV_FDPIC
167#else
168# define DEFAULT_FDPIC 0
169#endif
170
0ebb9a87 171static unsigned long frv_mach = bfd_mach_frv;
676a64f4 172static bfd_boolean fr400_audio;
0ebb9a87
DB
173
174/* Flags to set in the elf header */
996991aa 175static flagword frv_flags = DEFAULT_FLAGS | DEFAULT_FDPIC;
0ebb9a87
DB
176
177static int frv_user_set_flags_p = 0;
178static int frv_pic_p = 0;
996991aa 179static const char *frv_pic_flag = DEFAULT_FDPIC ? "-mfdpic" : (const char *)0;
0ebb9a87
DB
180
181/* Print tomcat-specific debugging info. */
182static int tomcat_debug = 0;
183
184/* Tomcat-specific NOP statistics. */
185static int tomcat_stats = 0;
186static int tomcat_doubles = 0;
187static int tomcat_singles = 0;
188
189/* Forward reference to static functions */
5a49b8ac
AM
190static void frv_set_flags (int);
191static void frv_pic_ptr (int);
0ebb9a87
DB
192
193/* The target specific pseudo-ops which we support. */
194const pseudo_typeS md_pseudo_table[] =
195{
196 { "eflags", frv_set_flags, 0 },
197 { "word", cons, 4 },
198 { "picptr", frv_pic_ptr, 4 },
0ebb9a87
DB
199 { NULL, NULL, 0 }
200};
201
202\f
203#define FRV_SHORTOPTS "G:"
204const char * md_shortopts = FRV_SHORTOPTS;
205
206#define OPTION_GPR_32 (OPTION_MD_BASE)
207#define OPTION_GPR_64 (OPTION_MD_BASE + 1)
208#define OPTION_FPR_32 (OPTION_MD_BASE + 2)
209#define OPTION_FPR_64 (OPTION_MD_BASE + 3)
210#define OPTION_SOFT_FLOAT (OPTION_MD_BASE + 4)
211#define OPTION_DWORD_YES (OPTION_MD_BASE + 5)
212#define OPTION_DWORD_NO (OPTION_MD_BASE + 6)
213#define OPTION_DOUBLE (OPTION_MD_BASE + 7)
214#define OPTION_NO_DOUBLE (OPTION_MD_BASE + 8)
215#define OPTION_MEDIA (OPTION_MD_BASE + 9)
216#define OPTION_NO_MEDIA (OPTION_MD_BASE + 10)
217#define OPTION_CPU (OPTION_MD_BASE + 11)
218#define OPTION_PIC (OPTION_MD_BASE + 12)
219#define OPTION_BIGPIC (OPTION_MD_BASE + 13)
220#define OPTION_LIBPIC (OPTION_MD_BASE + 14)
221#define OPTION_MULADD (OPTION_MD_BASE + 15)
222#define OPTION_NO_MULADD (OPTION_MD_BASE + 16)
223#define OPTION_TOMCAT_DEBUG (OPTION_MD_BASE + 17)
224#define OPTION_TOMCAT_STATS (OPTION_MD_BASE + 18)
225#define OPTION_PACK (OPTION_MD_BASE + 19)
226#define OPTION_NO_PACK (OPTION_MD_BASE + 20)
99d09cdb 227#define OPTION_FDPIC (OPTION_MD_BASE + 21)
996991aa 228#define OPTION_NOPIC (OPTION_MD_BASE + 22)
0ebb9a87
DB
229
230struct option md_longopts[] =
231{
232 { "mgpr-32", no_argument, NULL, OPTION_GPR_32 },
233 { "mgpr-64", no_argument, NULL, OPTION_GPR_64 },
234 { "mfpr-32", no_argument, NULL, OPTION_FPR_32 },
235 { "mfpr-64", no_argument, NULL, OPTION_FPR_64 },
236 { "mhard-float", no_argument, NULL, OPTION_FPR_64 },
237 { "msoft-float", no_argument, NULL, OPTION_SOFT_FLOAT },
238 { "mdword", no_argument, NULL, OPTION_DWORD_YES },
239 { "mno-dword", no_argument, NULL, OPTION_DWORD_NO },
240 { "mdouble", no_argument, NULL, OPTION_DOUBLE },
241 { "mno-double", no_argument, NULL, OPTION_NO_DOUBLE },
242 { "mmedia", no_argument, NULL, OPTION_MEDIA },
243 { "mno-media", no_argument, NULL, OPTION_NO_MEDIA },
244 { "mcpu", required_argument, NULL, OPTION_CPU },
245 { "mpic", no_argument, NULL, OPTION_PIC },
246 { "mPIC", no_argument, NULL, OPTION_BIGPIC },
247 { "mlibrary-pic", no_argument, NULL, OPTION_LIBPIC },
248 { "mmuladd", no_argument, NULL, OPTION_MULADD },
249 { "mno-muladd", no_argument, NULL, OPTION_NO_MULADD },
250 { "mtomcat-debug", no_argument, NULL, OPTION_TOMCAT_DEBUG },
251 { "mtomcat-stats", no_argument, NULL, OPTION_TOMCAT_STATS },
252 { "mpack", no_argument, NULL, OPTION_PACK },
253 { "mno-pack", no_argument, NULL, OPTION_NO_PACK },
99d09cdb 254 { "mfdpic", no_argument, NULL, OPTION_FDPIC },
996991aa 255 { "mnopic", no_argument, NULL, OPTION_NOPIC },
0ebb9a87
DB
256 { NULL, no_argument, NULL, 0 },
257};
258
259size_t md_longopts_size = sizeof (md_longopts);
260
261/* What value to give to bfd_set_gp_size. */
262static int g_switch_value = 8;
263
264int
17b9d67d 265md_parse_option (int c, const char *arg)
0ebb9a87
DB
266{
267 switch (c)
268 {
269 default:
270 return 0;
271
272 case 'G':
273 g_switch_value = atoi (arg);
274 if (! g_switch_value)
275 frv_flags |= EF_FRV_G0;
276 break;
277
278 case OPTION_GPR_32:
279 frv_flags = (frv_flags & ~EF_FRV_GPR_MASK) | EF_FRV_GPR_32;
280 break;
281
282 case OPTION_GPR_64:
283 frv_flags = (frv_flags & ~EF_FRV_GPR_MASK) | EF_FRV_GPR_64;
284 break;
285
286 case OPTION_FPR_32:
287 frv_flags = (frv_flags & ~EF_FRV_FPR_MASK) | EF_FRV_FPR_32;
288 break;
289
290 case OPTION_FPR_64:
291 frv_flags = (frv_flags & ~EF_FRV_FPR_MASK) | EF_FRV_FPR_64;
292 break;
293
294 case OPTION_SOFT_FLOAT:
295 frv_flags = (frv_flags & ~EF_FRV_FPR_MASK) | EF_FRV_FPR_NONE;
296 break;
297
298 case OPTION_DWORD_YES:
299 frv_flags = (frv_flags & ~EF_FRV_DWORD_MASK) | EF_FRV_DWORD_YES;
300 break;
301
302 case OPTION_DWORD_NO:
303 frv_flags = (frv_flags & ~EF_FRV_DWORD_MASK) | EF_FRV_DWORD_NO;
304 break;
305
306 case OPTION_DOUBLE:
307 frv_flags |= EF_FRV_DOUBLE;
308 break;
309
310 case OPTION_NO_DOUBLE:
311 frv_flags &= ~EF_FRV_DOUBLE;
312 break;
313
314 case OPTION_MEDIA:
315 frv_flags |= EF_FRV_MEDIA;
316 break;
317
318 case OPTION_NO_MEDIA:
319 frv_flags &= ~EF_FRV_MEDIA;
320 break;
321
322 case OPTION_MULADD:
323 frv_flags |= EF_FRV_MULADD;
324 break;
325
326 case OPTION_NO_MULADD:
327 frv_flags &= ~EF_FRV_MULADD;
328 break;
329
330 case OPTION_PACK:
331 frv_flags &= ~EF_FRV_NOPACK;
332 break;
333
334 case OPTION_NO_PACK:
335 frv_flags |= EF_FRV_NOPACK;
336 break;
337
338 case OPTION_CPU:
339 {
17b9d67d 340 const char *p;
0ebb9a87
DB
341 int cpu_flags = EF_FRV_CPU_GENERIC;
342
343 /* Identify the processor type */
344 p = arg;
345 if (strcmp (p, "frv") == 0)
346 {
347 cpu_flags = EF_FRV_CPU_GENERIC;
348 frv_mach = bfd_mach_frv;
349 }
350
351 else if (strcmp (p, "fr500") == 0)
352 {
353 cpu_flags = EF_FRV_CPU_FR500;
354 frv_mach = bfd_mach_fr500;
355 }
356
1ae31fee
DB
357 else if (strcmp (p, "fr550") == 0)
358 {
359 cpu_flags = EF_FRV_CPU_FR550;
360 frv_mach = bfd_mach_fr550;
361 }
362
676a64f4
RS
363 else if (strcmp (p, "fr450") == 0)
364 {
365 cpu_flags = EF_FRV_CPU_FR450;
366 frv_mach = bfd_mach_fr450;
367 }
368
369 else if (strcmp (p, "fr405") == 0)
370 {
371 cpu_flags = EF_FRV_CPU_FR405;
372 frv_mach = bfd_mach_fr400;
373 fr400_audio = TRUE;
374 }
375
0ebb9a87
DB
376 else if (strcmp (p, "fr400") == 0)
377 {
378 cpu_flags = EF_FRV_CPU_FR400;
379 frv_mach = bfd_mach_fr400;
676a64f4 380 fr400_audio = FALSE;
0ebb9a87
DB
381 }
382
383 else if (strcmp (p, "fr300") == 0)
384 {
385 cpu_flags = EF_FRV_CPU_FR300;
386 frv_mach = bfd_mach_fr300;
387 }
388
389 else if (strcmp (p, "simple") == 0)
390 {
391 cpu_flags = EF_FRV_CPU_SIMPLE;
392 frv_mach = bfd_mach_frvsimple;
393 frv_flags |= EF_FRV_NOPACK;
394 }
395
396 else if (strcmp (p, "tomcat") == 0)
397 {
398 cpu_flags = EF_FRV_CPU_TOMCAT;
399 frv_mach = bfd_mach_frvtomcat;
400 }
401
402 else
403 {
bd3ba5d1 404 as_fatal (_("Unknown cpu -mcpu=%s"), arg);
0ebb9a87
DB
405 return 0;
406 }
407
408 frv_flags = (frv_flags & ~EF_FRV_CPU_MASK) | cpu_flags;
409 }
410 break;
411
412 case OPTION_PIC:
413 frv_flags |= EF_FRV_PIC;
414 frv_pic_p = 1;
415 frv_pic_flag = "-fpic";
416 break;
417
418 case OPTION_BIGPIC:
419 frv_flags |= EF_FRV_BIGPIC;
420 frv_pic_p = 1;
421 frv_pic_flag = "-fPIC";
422 break;
423
424 case OPTION_LIBPIC:
425 frv_flags |= (EF_FRV_LIBPIC | EF_FRV_G0);
426 frv_pic_p = 1;
427 frv_pic_flag = "-mlibrary-pic";
428 g_switch_value = 0;
429 break;
430
99d09cdb
AO
431 case OPTION_FDPIC:
432 frv_flags |= EF_FRV_FDPIC;
433 frv_pic_flag = "-mfdpic";
434 break;
435
996991aa
AO
436 case OPTION_NOPIC:
437 frv_flags &= ~(EF_FRV_FDPIC | EF_FRV_PIC
438 | EF_FRV_BIGPIC | EF_FRV_LIBPIC);
439 frv_pic_flag = 0;
440 break;
441
0ebb9a87
DB
442 case OPTION_TOMCAT_DEBUG:
443 tomcat_debug = 1;
444 break;
445
446 case OPTION_TOMCAT_STATS:
447 tomcat_stats = 1;
448 break;
449 }
450
451 return 1;
452}
453
454void
42477147 455md_show_usage (FILE * stream)
0ebb9a87
DB
456{
457 fprintf (stream, _("FRV specific command line options:\n"));
42477147
NC
458 fprintf (stream, _("-G n Put data <= n bytes in the small data area\n"));
459 fprintf (stream, _("-mgpr-32 Mark generated file as only using 32 GPRs\n"));
460 fprintf (stream, _("-mgpr-64 Mark generated file as using all 64 GPRs\n"));
461 fprintf (stream, _("-mfpr-32 Mark generated file as only using 32 FPRs\n"));
462 fprintf (stream, _("-mfpr-64 Mark generated file as using all 64 FPRs\n"));
463 fprintf (stream, _("-msoft-float Mark generated file as using software FP\n"));
464 fprintf (stream, _("-mdword Mark generated file as using a 8-byte stack alignment\n"));
465 fprintf (stream, _("-mno-dword Mark generated file as using a 4-byte stack alignment\n"));
466 fprintf (stream, _("-mdouble Mark generated file as using double precision FP insns\n"));
467 fprintf (stream, _("-mmedia Mark generated file as using media insns\n"));
468 fprintf (stream, _("-mmuladd Mark generated file as using multiply add/subtract insns\n"));
469 fprintf (stream, _("-mpack Allow instructions to be packed\n"));
470 fprintf (stream, _("-mno-pack Do not allow instructions to be packed\n"));
471 fprintf (stream, _("-mpic Mark generated file as using small position independent code\n"));
472 fprintf (stream, _("-mPIC Mark generated file as using large position independent code\n"));
473 fprintf (stream, _("-mlibrary-pic Mark generated file as using position indepedent code for libraries\n"));
474 fprintf (stream, _("-mfdpic Assemble for the FDPIC ABI\n"));
475 fprintf (stream, _("-mnopic Disable -mpic, -mPIC, -mlibrary-pic and -mfdpic\n"));
676a64f4 476 fprintf (stream, _("-mcpu={fr500|fr550|fr400|fr405|fr450|fr300|frv|simple|tomcat}\n"));
42477147
NC
477 fprintf (stream, _(" Record the cpu type\n"));
478 fprintf (stream, _("-mtomcat-stats Print out stats for tomcat workarounds\n"));
479 fprintf (stream, _("-mtomcat-debug Debug tomcat workarounds\n"));
3739860c 480}
0ebb9a87
DB
481
482\f
483void
5a49b8ac 484md_begin (void)
0ebb9a87
DB
485{
486 /* Initialize the `cgen' interface. */
3739860c 487
0ebb9a87
DB
488 /* Set the machine number and endian. */
489 gas_cgen_cpu_desc = frv_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, 0,
490 CGEN_CPU_OPEN_ENDIAN,
491 CGEN_ENDIAN_BIG,
492 CGEN_CPU_OPEN_END);
493 frv_cgen_init_asm (gas_cgen_cpu_desc);
494
495 /* This is a callback from cgen to gas to parse operands. */
496 cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
497
498 /* Set the ELF flags if desired. */
499 if (frv_flags)
500 bfd_set_private_flags (stdoutput, frv_flags);
501
502 /* Set the machine type */
503 bfd_default_set_arch_mach (stdoutput, bfd_arch_frv, frv_mach);
504
505 /* Set up gp size so we can put local common items in .sbss */
506 bfd_set_gp_size (stdoutput, g_switch_value);
507
508 frv_vliw_reset (& vliw, frv_mach, frv_flags);
509}
510
996991aa
AO
511bfd_boolean
512frv_md_fdpic_enabled (void)
513{
514 return (frv_flags & EF_FRV_FDPIC) != 0;
515}
516
0ebb9a87
DB
517int chain_num = 0;
518
5a49b8ac
AM
519static struct vliw_insn_list *
520frv_insert_vliw_insn (bfd_boolean count)
0ebb9a87
DB
521{
522 struct vliw_insn_list *vliw_insn_list_entry;
523 struct vliw_chain *vliw_chain_entry;
524
525 if (current_vliw_chain == NULL)
526 {
527 vliw_chain_entry = (struct vliw_chain *) xmalloc (sizeof (struct vliw_chain));
528 vliw_chain_entry->insn_count = 0;
529 vliw_chain_entry->insn_list = NULL;
530 vliw_chain_entry->next = NULL;
531 vliw_chain_entry->num = chain_num++;
532
533 if (!vliw_chain_top)
534 vliw_chain_top = vliw_chain_entry;
535 current_vliw_chain = vliw_chain_entry;
536 if (previous_vliw_chain)
537 previous_vliw_chain->next = vliw_chain_entry;
538 }
539
540 vliw_insn_list_entry = (struct vliw_insn_list *) xmalloc (sizeof (struct vliw_insn_list));
541 vliw_insn_list_entry->type = VLIW_GENERIC_TYPE;
542 vliw_insn_list_entry->insn = NULL;
543 vliw_insn_list_entry->sym = NULL;
544 vliw_insn_list_entry->snop_frag = NULL;
545 vliw_insn_list_entry->dnop_frag = NULL;
546 vliw_insn_list_entry->next = NULL;
547
548 if (count)
549 current_vliw_chain->insn_count++;
550
551 if (current_vliw_insn)
552 current_vliw_insn->next = vliw_insn_list_entry;
553 current_vliw_insn = vliw_insn_list_entry;
554
555 if (!current_vliw_chain->insn_list)
556 current_vliw_chain->insn_list = current_vliw_insn;
557
558 return vliw_insn_list_entry;
559}
560
561 /* Identify the following cases:
3739860c 562
0ebb9a87
DB
563 1) A VLIW insn that contains both a branch and the branch destination.
564 This requires the insertion of two vliw instructions before the
565 branch. The first consists of two nops. The second consists of
566 a single nop.
3739860c 567
0ebb9a87
DB
568 2) A single instruction VLIW insn which is the destination of a branch
569 that is in the next VLIW insn. This requires the insertion of a vliw
570 insn containing two nops before the branch.
3739860c 571
0ebb9a87
DB
572 3) A double instruction VLIW insn which contains the destination of a
573 branch that is in the next VLIW insn. This requires the insertion of
574 a VLIW insn containing a single nop before the branch.
3739860c 575
0ebb9a87
DB
576 4) A single instruction VLIW insn which contains branch destination (x),
577 followed by a single instruction VLIW insn which does not contain
578 the branch to (x), followed by a VLIW insn which does contain the branch
579 to (x). This requires the insertion of a VLIW insn containing a single
580 nop before the VLIW instruction containing the branch.
3739860c 581
0ebb9a87
DB
582 */
583#define FRV_IS_NOP(insn) (insn.buffer[0] == FRV_NOP_PACK || insn.buffer[0] == FRV_NOP_NOPACK)
584#define FRV_NOP_PACK 0x00880000 /* ori.p gr0,0,gr0 */
585#define FRV_NOP_NOPACK 0x80880000 /* ori gr0,0,gr0 */
586
587/* Check a vliw insn for an insn of type containing the sym passed in label_sym. */
588
589static struct vliw_insn_list *
5a49b8ac
AM
590frv_find_in_vliw (enum vliw_insn_type vliw_insn_type,
591 struct vliw_chain *this_chain,
592 symbolS *label_sym)
0ebb9a87
DB
593{
594
595 struct vliw_insn_list *the_insn;
596
597 if (!this_chain)
598 return NULL;
599
600 for (the_insn = this_chain->insn_list; the_insn; the_insn = the_insn->next)
601 {
602 if (the_insn->type == vliw_insn_type
603 && the_insn->sym == label_sym)
604 return the_insn;
605 }
606
607 return NULL;
608}
609
610enum vliw_nop_type
611{
612 /* A Vliw insn containing a single nop insn. */
613 VLIW_SINGLE_NOP,
3739860c 614
0ebb9a87
DB
615 /* A Vliw insn containing two nop insns. */
616 VLIW_DOUBLE_NOP,
617
3739860c 618 /* Two vliw insns. The first containing two nop insns.
0ebb9a87
DB
619 The second contain a single nop insn. */
620 VLIW_DOUBLE_THEN_SINGLE_NOP
621};
622
623static void
5a49b8ac 624frv_debug_tomcat (struct vliw_chain *start_chain)
0ebb9a87
DB
625{
626 struct vliw_chain *this_chain;
627 struct vliw_insn_list *this_insn;
628 int i = 1;
629
630 for (this_chain = start_chain; this_chain; this_chain = this_chain->next, i++)
631 {
632 fprintf (stderr, "\nVliw Insn #%d, #insns: %d\n", i, this_chain->insn_count);
633
634 for (this_insn = this_chain->insn_list; this_insn; this_insn = this_insn->next)
635 {
636 if (this_insn->type == VLIW_LABEL_TYPE)
8ad7c533 637 fprintf (stderr, "Label Value: %p\n", this_insn->sym);
0ebb9a87 638 else if (this_insn->type == VLIW_BRANCH_TYPE)
8ad7c533 639 fprintf (stderr, "%s to %p\n", this_insn->insn->base->name, this_insn->sym);
0ebb9a87 640 else if (this_insn->type == VLIW_BRANCH_HAS_NOPS)
8ad7c533 641 fprintf (stderr, "nop'd %s to %p\n", this_insn->insn->base->name, this_insn->sym);
0ebb9a87
DB
642 else if (this_insn->type == VLIW_NOP_TYPE)
643 fprintf (stderr, "Nop\n");
644 else
645 fprintf (stderr, " %s\n", this_insn->insn->base->name);
646 }
647 }
648}
649
0ebb9a87 650static void
5a49b8ac 651frv_adjust_vliw_count (struct vliw_chain *this_chain)
0ebb9a87
DB
652{
653 struct vliw_insn_list *this_insn;
654
655 this_chain->insn_count = 0;
656
657 for (this_insn = this_chain->insn_list;
658 this_insn;
659 this_insn = this_insn->next)
660 {
661 if (this_insn->type != VLIW_LABEL_TYPE)
662 this_chain->insn_count++;
663 }
664
665}
666
667/* Insert the desired nop combination in the vliw chain before insert_before_insn.
668 Rechain the vliw insn. */
669
0ebb9a87 670static struct vliw_chain *
5a49b8ac
AM
671frv_tomcat_shuffle (enum vliw_nop_type this_nop_type,
672 struct vliw_chain *vliw_to_split,
673 struct vliw_insn_list *insert_before_insn)
0ebb9a87
DB
674{
675
b34976b6 676 bfd_boolean pack_prev = FALSE;
0ebb9a87
DB
677 struct vliw_chain *return_me = NULL;
678 struct vliw_insn_list *prev_insn = NULL;
679 struct vliw_insn_list *curr_insn = vliw_to_split->insn_list;
680
681 struct vliw_chain *double_nop = (struct vliw_chain *) xmalloc (sizeof (struct vliw_chain));
682 struct vliw_chain *single_nop = (struct vliw_chain *) xmalloc (sizeof (struct vliw_chain));
683 struct vliw_chain *second_part = (struct vliw_chain *) xmalloc (sizeof (struct vliw_chain));
684 struct vliw_chain *curr_vliw = vliw_chain_top;
685 struct vliw_chain *prev_vliw = NULL;
686
687 while (curr_insn && curr_insn != insert_before_insn)
688 {
689 /* We can't set the packing bit on a label. If we have the case
690 label 1:
691 label 2:
692 label 3:
693 branch that needs nops
694 Then don't set pack bit later. */
695
696 if (curr_insn->type != VLIW_LABEL_TYPE)
b34976b6 697 pack_prev = TRUE;
0ebb9a87
DB
698 prev_insn = curr_insn;
699 curr_insn = curr_insn->next;
3739860c 700 }
0ebb9a87
DB
701
702 while (curr_vliw && curr_vliw != vliw_to_split)
703 {
704 prev_vliw = curr_vliw;
705 curr_vliw = curr_vliw->next;
706 }
707
708 switch (this_nop_type)
709 {
710 case VLIW_SINGLE_NOP:
711 if (!prev_insn)
712 {
713 /* Branch is first, Insert the NOP prior to this vliw insn. */
714 if (prev_vliw)
715 prev_vliw->next = single_nop;
716 else
717 vliw_chain_top = single_nop;
718 single_nop->next = vliw_to_split;
719 vliw_to_split->insn_list->type = VLIW_BRANCH_HAS_NOPS;
720 return_me = vliw_to_split;
721 }
722 else
723 {
724 /* Set the packing bit on the previous insn. */
725 if (pack_prev)
726 {
2132e3a3 727 char *buffer = prev_insn->address;
0ebb9a87
DB
728 buffer[0] |= 0x80;
729 }
730 /* The branch is in the middle. Split this vliw insn into first
731 and second parts. Insert the NOP inbetween. */
732
733 second_part->insn_list = insert_before_insn;
734 second_part->insn_list->type = VLIW_BRANCH_HAS_NOPS;
735 second_part->next = vliw_to_split->next;
736 frv_adjust_vliw_count (second_part);
737
738 single_nop->next = second_part;
3739860c 739
0ebb9a87
DB
740 vliw_to_split->next = single_nop;
741 prev_insn->next = NULL;
3739860c 742
0ebb9a87
DB
743 return_me = second_part;
744 frv_adjust_vliw_count (vliw_to_split);
745 }
746 break;
747
748 case VLIW_DOUBLE_NOP:
749 if (!prev_insn)
750 {
751 /* Branch is first, Insert the NOP prior to this vliw insn. */
752 if (prev_vliw)
753 prev_vliw->next = double_nop;
754 else
755 vliw_chain_top = double_nop;
756
757 double_nop->next = vliw_to_split;
758 return_me = vliw_to_split;
759 vliw_to_split->insn_list->type = VLIW_BRANCH_HAS_NOPS;
760 }
761 else
762 {
763 /* Set the packing bit on the previous insn. */
764 if (pack_prev)
765 {
2132e3a3 766 char *buffer = prev_insn->address;
0ebb9a87
DB
767 buffer[0] |= 0x80;
768 }
769
770 /* The branch is in the middle. Split this vliw insn into first
771 and second parts. Insert the NOP inbetween. */
772 second_part->insn_list = insert_before_insn;
773 second_part->insn_list->type = VLIW_BRANCH_HAS_NOPS;
774 second_part->next = vliw_to_split->next;
775 frv_adjust_vliw_count (second_part);
3739860c 776
0ebb9a87 777 double_nop->next = second_part;
3739860c 778
0ebb9a87
DB
779 vliw_to_split->next = single_nop;
780 prev_insn->next = NULL;
781 frv_adjust_vliw_count (vliw_to_split);
3739860c 782
0ebb9a87
DB
783 return_me = second_part;
784 }
785 break;
786
787 case VLIW_DOUBLE_THEN_SINGLE_NOP:
788 double_nop->next = single_nop;
789 double_nop->insn_count = 2;
790 double_nop->insn_list = &double_nop_insn;
791 single_nop->insn_count = 1;
792 single_nop->insn_list = &single_nop_insn;
793
794 if (!prev_insn)
795 {
796 /* The branch is the first insn in this vliw. Don't split the vliw. Insert
797 the nops prior to this vliw. */
798 if (prev_vliw)
799 prev_vliw->next = double_nop;
800 else
801 vliw_chain_top = double_nop;
3739860c 802
0ebb9a87
DB
803 single_nop->next = vliw_to_split;
804 return_me = vliw_to_split;
805 vliw_to_split->insn_list->type = VLIW_BRANCH_HAS_NOPS;
806 }
807 else
808 {
809 /* Set the packing bit on the previous insn. */
810 if (pack_prev)
811 {
2132e3a3 812 char *buffer = prev_insn->address;
0ebb9a87
DB
813 buffer[0] |= 0x80;
814 }
815
816 /* The branch is in the middle of this vliw insn. Split into first and
3739860c 817 second parts. Insert the nop vliws in between. */
0ebb9a87
DB
818 second_part->insn_list = insert_before_insn;
819 second_part->insn_list->type = VLIW_BRANCH_HAS_NOPS;
820 second_part->next = vliw_to_split->next;
821 frv_adjust_vliw_count (second_part);
822
823 single_nop->next = second_part;
824
825 vliw_to_split->next = double_nop;
826 prev_insn->next = NULL;
827 frv_adjust_vliw_count (vliw_to_split);
828
829 return_me = second_part;
830 }
831 break;
832 }
833
834 return return_me;
835}
836
837static void
5a49b8ac 838frv_tomcat_analyze_vliw_chains (void)
0ebb9a87
DB
839{
840 struct vliw_chain *vliw1 = NULL;
841 struct vliw_chain *vliw2 = NULL;
842 struct vliw_chain *vliw3 = NULL;
843
844 struct vliw_insn_list *this_insn = NULL;
845 struct vliw_insn_list *temp_insn = NULL;
846
847 /* We potentially need to look at three VLIW insns to determine if the
848 workaround is required. Set them up. Ignore existing nops during analysis. */
849
850#define FRV_SET_VLIW_WINDOW(VLIW1, VLIW2, VLIW3) \
851 if (VLIW1 && VLIW1->next) \
852 VLIW2 = VLIW1->next; \
853 else \
854 VLIW2 = NULL; \
855 if (VLIW2 && VLIW2->next) \
856 VLIW3 = VLIW2->next; \
857 else \
858 VLIW3 = NULL
859
860 vliw1 = vliw_chain_top;
861
862workaround_top:
863
864 FRV_SET_VLIW_WINDOW (vliw1, vliw2, vliw3);
865
866 if (!vliw1)
867 return;
868
869 if (vliw1->insn_count == 1)
870 {
871 /* check vliw1 for a label. */
872 if (vliw1->insn_list->type == VLIW_LABEL_TYPE)
873 {
874 temp_insn = frv_find_in_vliw (VLIW_BRANCH_TYPE, vliw2, vliw1->insn_list->sym);
875 if (temp_insn)
876 {
877 vliw1 = frv_tomcat_shuffle (VLIW_DOUBLE_NOP, vliw2, vliw1->insn_list);
878 temp_insn->dnop_frag->fr_subtype = NOP_KEEP;
879 vliw1 = vliw1->next;
880 if (tomcat_stats)
881 tomcat_doubles++;
882 goto workaround_top;
883 }
3739860c 884 else if (vliw2
0ebb9a87
DB
885 && vliw2->insn_count == 1
886 && (temp_insn = frv_find_in_vliw (VLIW_BRANCH_TYPE, vliw3, vliw1->insn_list->sym)) != NULL)
887 {
888 temp_insn->snop_frag->fr_subtype = NOP_KEEP;
889 vliw1 = frv_tomcat_shuffle (VLIW_SINGLE_NOP, vliw3, vliw3->insn_list);
890 if (tomcat_stats)
891 tomcat_singles++;
892 goto workaround_top;
893 }
894 }
895 }
896
897 if (vliw1->insn_count == 2)
898 {
91d6fa6a 899 /* Check vliw1 for a label. */
0ebb9a87
DB
900 for (this_insn = vliw1->insn_list; this_insn; this_insn = this_insn->next)
901 {
902 if (this_insn->type == VLIW_LABEL_TYPE)
903 {
a08333bb 904 if ((temp_insn = frv_find_in_vliw (VLIW_BRANCH_TYPE, vliw2, this_insn->sym)) != NULL)
0ebb9a87
DB
905 {
906 temp_insn->snop_frag->fr_subtype = NOP_KEEP;
907 vliw1 = frv_tomcat_shuffle (VLIW_SINGLE_NOP, vliw2, this_insn);
908 if (tomcat_stats)
909 tomcat_singles++;
910 }
911 else
912 vliw1 = vliw1->next;
913 goto workaround_top;
914 }
915 }
916 }
917 /* Examine each insn in this VLIW. Look for the workaround criteria. */
918 for (this_insn = vliw1->insn_list; this_insn; this_insn = this_insn->next)
919 {
920 /* Don't look at labels or nops. */
921 while (this_insn
922 && (this_insn->type == VLIW_LABEL_TYPE
923 || this_insn->type == VLIW_NOP_TYPE
924 || this_insn->type == VLIW_BRANCH_HAS_NOPS))
925 this_insn = this_insn->next;
926
927 if (!this_insn)
928 {
929 vliw1 = vliw2;
930 goto workaround_top;
931 }
932
933 if (frv_is_branch_insn (this_insn->insn))
934 {
a08333bb 935 if ((temp_insn = frv_find_in_vliw (VLIW_LABEL_TYPE, vliw1, this_insn->sym)) != NULL)
0ebb9a87
DB
936 {
937 /* Insert [nop/nop] [nop] before branch. */
938 this_insn->snop_frag->fr_subtype = NOP_KEEP;
939 this_insn->dnop_frag->fr_subtype = NOP_KEEP;
940 vliw1 = frv_tomcat_shuffle (VLIW_DOUBLE_THEN_SINGLE_NOP, vliw1, this_insn);
941 goto workaround_top;
942 }
943 }
944
945
946 }
947 /* This vliw insn checks out okay. Take a look at the next one. */
948 vliw1 = vliw1->next;
949 goto workaround_top;
950}
951
952void
5a49b8ac 953frv_tomcat_workaround (void)
0ebb9a87
DB
954{
955 if (frv_mach != bfd_mach_frvtomcat)
956 return;
957
958 if (tomcat_debug)
959 frv_debug_tomcat (vliw_chain_top);
960
961 frv_tomcat_analyze_vliw_chains ();
962
963 if (tomcat_stats)
964 {
965 fprintf (stderr, "Inserted %d Single Nops\n", tomcat_singles);
966 fprintf (stderr, "Inserted %d Double Nops\n", tomcat_doubles);
967 }
968}
969
1ae31fee
DB
970static int
971fr550_check_insn_acc_range (frv_insn *insn, int low, int hi)
972{
973 int acc;
974 switch (CGEN_INSN_NUM (insn->insn))
975 {
976 case FRV_INSN_MADDACCS:
977 case FRV_INSN_MSUBACCS:
978 case FRV_INSN_MDADDACCS:
979 case FRV_INSN_MDSUBACCS:
980 case FRV_INSN_MASACCS:
981 case FRV_INSN_MDASACCS:
982 acc = insn->fields.f_ACC40Si;
983 if (acc < low || acc > hi)
984 return 1; /* out of range */
985 acc = insn->fields.f_ACC40Sk;
986 if (acc < low || acc > hi)
987 return 1; /* out of range */
988 break;
989 case FRV_INSN_MMULHS:
990 case FRV_INSN_MMULHU:
991 case FRV_INSN_MMULXHS:
992 case FRV_INSN_MMULXHU:
993 case FRV_INSN_CMMULHS:
994 case FRV_INSN_CMMULHU:
995 case FRV_INSN_MQMULHS:
996 case FRV_INSN_MQMULHU:
997 case FRV_INSN_MQMULXHS:
998 case FRV_INSN_MQMULXHU:
999 case FRV_INSN_CMQMULHS:
1000 case FRV_INSN_CMQMULHU:
1001 case FRV_INSN_MMACHS:
1002 case FRV_INSN_MMRDHS:
3739860c 1003 case FRV_INSN_CMMACHS:
1ae31fee
DB
1004 case FRV_INSN_MQMACHS:
1005 case FRV_INSN_CMQMACHS:
1006 case FRV_INSN_MQXMACHS:
1007 case FRV_INSN_MQXMACXHS:
1008 case FRV_INSN_MQMACXHS:
1009 case FRV_INSN_MCPXRS:
1010 case FRV_INSN_MCPXIS:
1011 case FRV_INSN_CMCPXRS:
1012 case FRV_INSN_CMCPXIS:
1013 case FRV_INSN_MQCPXRS:
1014 case FRV_INSN_MQCPXIS:
1015 acc = insn->fields.f_ACC40Sk;
1016 if (acc < low || acc > hi)
1017 return 1; /* out of range */
1018 break;
1019 case FRV_INSN_MMACHU:
1020 case FRV_INSN_MMRDHU:
1021 case FRV_INSN_CMMACHU:
1022 case FRV_INSN_MQMACHU:
1023 case FRV_INSN_CMQMACHU:
1024 case FRV_INSN_MCPXRU:
1025 case FRV_INSN_MCPXIU:
1026 case FRV_INSN_CMCPXRU:
1027 case FRV_INSN_CMCPXIU:
1028 case FRV_INSN_MQCPXRU:
1029 case FRV_INSN_MQCPXIU:
1030 acc = insn->fields.f_ACC40Uk;
1031 if (acc < low || acc > hi)
1032 return 1; /* out of range */
1033 break;
1034 default:
1035 break;
1036 }
1037 return 0; /* all is ok */
1038}
1039
1040static int
91d6fa6a 1041fr550_check_acc_range (FRV_VLIW *vlw, frv_insn *insn)
1ae31fee 1042{
91d6fa6a 1043 switch ((*vlw->current_vliw)[vlw->next_slot - 1])
1ae31fee
DB
1044 {
1045 case UNIT_FM0:
1046 case UNIT_FM2:
1047 return fr550_check_insn_acc_range (insn, 0, 3);
1048 case UNIT_FM1:
1049 case UNIT_FM3:
1050 return fr550_check_insn_acc_range (insn, 4, 7);
1051 default:
1052 break;
1053 }
1054 return 0; /* all is ok */
1055}
1056
676a64f4
RS
1057/* Return true if the target implements instruction INSN. */
1058
1059static bfd_boolean
1060target_implements_insn_p (const CGEN_INSN *insn)
1061{
1062 switch (frv_mach)
1063 {
1064 default:
1065 /* bfd_mach_frv or generic. */
1066 return TRUE;
1067
1068 case bfd_mach_fr300:
1069 case bfd_mach_frvsimple:
1070 return CGEN_INSN_MACH_HAS_P (insn, MACH_SIMPLE);
1071
1072 case bfd_mach_fr400:
1073 return ((fr400_audio || !CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_AUDIO))
1074 && CGEN_INSN_MACH_HAS_P (insn, MACH_FR400));
1075
1076 case bfd_mach_fr450:
1077 return CGEN_INSN_MACH_HAS_P (insn, MACH_FR450);
1078
1079 case bfd_mach_fr500:
1080 return CGEN_INSN_MACH_HAS_P (insn, MACH_FR500);
1081
1082 case bfd_mach_fr550:
1083 return CGEN_INSN_MACH_HAS_P (insn, MACH_FR550);
1084 }
1085}
1086
0ebb9a87 1087void
5a49b8ac 1088md_assemble (char *str)
0ebb9a87
DB
1089{
1090 frv_insn insn;
1091 char *errmsg;
1092 int packing_constraint;
1093 finished_insnS finished_insn;
1094 fragS *double_nop_frag = NULL;
1095 fragS *single_nop_frag = NULL;
1096 struct vliw_insn_list *vliw_insn_list_entry = NULL;
1097
1098 /* Initialize GAS's cgen interface for a new instruction. */
1099 gas_cgen_init_parse ();
1100
99d09cdb
AO
1101 memset (&insn, 0, sizeof (insn));
1102
0ebb9a87
DB
1103 insn.insn = frv_cgen_assemble_insn
1104 (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, &errmsg);
3739860c 1105
0ebb9a87
DB
1106 if (!insn.insn)
1107 {
20203fb9 1108 as_bad ("%s", errmsg);
0ebb9a87
DB
1109 return;
1110 }
3739860c 1111
0ebb9a87
DB
1112 /* If the cpu is tomcat, then we need to insert nops to workaround
1113 hardware limitations. We need to keep track of each vliw unit
1114 and examine the length of the unit and the individual insns
1115 within the unit to determine the number and location of the
1116 required nops. */
1117 if (frv_mach == bfd_mach_frvtomcat)
1118 {
1119 /* If we've just finished a VLIW insn OR this is a branch,
1120 then start up a new frag. Fill it with nops. We will get rid
3739860c 1121 of those that are not required after we've seen all of the
0ebb9a87
DB
1122 instructions but before we start resolving fixups. */
1123 if ( !FRV_IS_NOP (insn)
1124 && (frv_is_branch_insn (insn.insn) || insn.fields.f_pack))
1125 {
1126 char *buffer;
1127
1128 frag_wane (frag_now);
1129 frag_new (0);
1130 double_nop_frag = frag_now;
1131 buffer = frag_var (rs_machine_dependent, 8, 8, NOP_DELETE, NULL, 0, 0);
1132 md_number_to_chars (buffer, FRV_NOP_PACK, 4);
1133 md_number_to_chars (buffer+4, FRV_NOP_NOPACK, 4);
1134
1135 frag_wane (frag_now);
1136 frag_new (0);
1137 single_nop_frag = frag_now;
1138 buffer = frag_var (rs_machine_dependent, 4, 4, NOP_DELETE, NULL, 0, 0);
1139 md_number_to_chars (buffer, FRV_NOP_NOPACK, 4);
1140 }
1141
1142 vliw_insn_list_entry = frv_insert_vliw_insn (DO_COUNT);
1143 vliw_insn_list_entry->insn = insn.insn;
1144 if (frv_is_branch_insn (insn.insn))
1145 vliw_insn_list_entry->type = VLIW_BRANCH_TYPE;
1146
1147 if ( !FRV_IS_NOP (insn)
1148 && (frv_is_branch_insn (insn.insn) || insn.fields.f_pack))
1149 {
1150 vliw_insn_list_entry->snop_frag = single_nop_frag;
1151 vliw_insn_list_entry->dnop_frag = double_nop_frag;
1152 }
1153 }
1154
1155 /* Make sure that this insn does not violate the VLIW packing constraints. */
1156 /* -mno-pack disallows any packing whatsoever. */
1157 if (frv_flags & EF_FRV_NOPACK)
1158 {
1159 if (! insn.fields.f_pack)
1160 {
1161 as_bad (_("VLIW packing used for -mno-pack"));
1162 return;
1163 }
1164 }
1165 /* -mcpu=FRV is an idealized FR-V implementation that supports all of the
1166 instructions, don't do vliw checking. */
1167 else if (frv_mach != bfd_mach_frv)
1168 {
676a64f4
RS
1169 if (!target_implements_insn_p (insn.insn))
1170 {
1171 as_bad (_("Instruction not supported by this architecture"));
1172 return;
1173 }
0ebb9a87 1174 packing_constraint = frv_vliw_add_insn (& vliw, insn.insn);
1ae31fee
DB
1175 if (frv_mach == bfd_mach_fr550 && ! packing_constraint)
1176 packing_constraint = fr550_check_acc_range (& vliw, & insn);
0ebb9a87
DB
1177 if (insn.fields.f_pack)
1178 frv_vliw_reset (& vliw, frv_mach, frv_flags);
1179 if (packing_constraint)
1180 {
1181 as_bad (_("VLIW packing constraint violation"));
1182 return;
1183 }
1184 }
1185
1186 /* Doesn't really matter what we pass for RELAX_P here. */
1187 gas_cgen_finish_insn (insn.insn, insn.buffer,
1188 CGEN_FIELDS_BITSIZE (& insn.fields), 1, &finished_insn);
1189
1190
1191 /* If the cpu is tomcat, then we need to insert nops to workaround
1192 hardware limitations. We need to keep track of each vliw unit
1193 and examine the length of the unit and the individual insns
1194 within the unit to determine the number and location of the
1195 required nops. */
1196 if (frv_mach == bfd_mach_frvtomcat)
1197 {
1198 if (vliw_insn_list_entry)
1199 vliw_insn_list_entry->address = finished_insn.addr;
1200 else
1201 abort();
1202
1203 if (insn.fields.f_pack)
1204 {
1205 /* We've completed a VLIW insn. */
1206 previous_vliw_chain = current_vliw_chain;
1207 current_vliw_chain = NULL;
1208 current_vliw_insn = NULL;
3739860c 1209 }
0ebb9a87
DB
1210 }
1211}
1212
1213/* The syntax in the manual says constants begin with '#'.
1214 We just ignore it. */
1215
3739860c 1216void
5a49b8ac 1217md_operand (expressionS *expressionP)
0ebb9a87
DB
1218{
1219 if (* input_line_pointer == '#')
1220 {
1221 input_line_pointer ++;
1222 expression (expressionP);
1223 }
1224}
1225
1226valueT
5a49b8ac 1227md_section_align (segT segment, valueT size)
0ebb9a87
DB
1228{
1229 int align = bfd_get_section_alignment (stdoutput, segment);
8d3842cd 1230 return ((size + (1 << align) - 1) & -(1 << align));
0ebb9a87
DB
1231}
1232
1233symbolS *
5a49b8ac 1234md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
0ebb9a87
DB
1235{
1236 return 0;
1237}
1238\f
1239/* Interface to relax_segment. */
1240
1241/* FIXME: Build table by hand, get it working, then machine generate. */
1242const relax_typeS md_relax_table[] =
1243{
1244 {1, 1, 0, 0},
1245 {511 - 2 - 2, -512 - 2 + 2, 0, 2 },
1246 {0x2000000 - 1 - 2, -0x2000000 - 2, 2, 0 },
1247 {0x2000000 - 1 - 2, -0x2000000 - 2, 4, 0 }
1248};
1249
1250long
5a49b8ac 1251frv_relax_frag (fragS *fragP ATTRIBUTE_UNUSED, long stretch ATTRIBUTE_UNUSED)
0ebb9a87
DB
1252{
1253 return 0;
1254}
1255
1256/* Return an initial guess of the length by which a fragment must grow to
1257 hold a branch to reach its destination.
1258 Also updates fr_type/fr_subtype as necessary.
1259
1260 Called just before doing relaxation.
1261 Any symbol that is now undefined will not become defined.
1262 The guess for fr_var is ACTUALLY the growth beyond fr_fix.
1263 Whatever we do to grow fr_fix or fr_var contributes to our returned value.
1264 Although it may not be explicit in the frag, pretend fr_var starts with a
1265 0 value. */
1266
1267int
5a49b8ac 1268md_estimate_size_before_relax (fragS *fragP, segT segment ATTRIBUTE_UNUSED)
0ebb9a87
DB
1269{
1270 switch (fragP->fr_subtype)
1271 {
1272 case NOP_KEEP:
1273 return fragP->fr_var;
1274
1275 default:
1276 case NOP_DELETE:
1277 return 0;
3739860c
L
1278 }
1279}
0ebb9a87
DB
1280
1281/* *fragP has been relaxed to its final size, and now needs to have
1282 the bytes inside it modified to conform to the new size.
1283
1284 Called after relaxation is finished.
1285 fragP->fr_type == rs_machine_dependent.
1286 fragP->fr_subtype is the subtype of what the address relaxed to. */
1287
1288void
5a49b8ac
AM
1289md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
1290 segT sec ATTRIBUTE_UNUSED,
1291 fragS *fragP)
0ebb9a87
DB
1292{
1293 switch (fragP->fr_subtype)
1294 {
1295 default:
1296 case NOP_DELETE:
1297 return;
1298
1299 case NOP_KEEP:
1300 fragP->fr_fix = fragP->fr_var;
1301 fragP->fr_var = 0;
3739860c 1302 return;
0ebb9a87
DB
1303 }
1304}
1305\f
1306/* Functions concerning relocs. */
1307
1308/* The location from which a PC relative jump should be calculated,
1309 given a PC relative reloc. */
1310
1311long
5a49b8ac 1312md_pcrel_from_section (fixS *fixP, segT sec)
0ebb9a87 1313{
a939d090
AO
1314 if (TC_FORCE_RELOCATION (fixP)
1315 || (fixP->fx_addsy != (symbolS *) NULL
1316 && S_GET_SEGMENT (fixP->fx_addsy) != sec))
1317 {
1318 /* If we can't adjust this relocation, or if it references a
1319 local symbol in a different section (which
1320 TC_FORCE_RELOCATION can't check), let the linker figure it
1321 out. */
1322 return 0;
1323 }
0ebb9a87
DB
1324
1325 return (fixP->fx_frag->fr_address + fixP->fx_where) & ~1;
1326}
1327
1328/* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
1329 Returns BFD_RELOC_NONE if no reloc type can be found.
1330 *FIXP may be modified if desired. */
1331
1332bfd_reloc_code_real_type
5a49b8ac
AM
1333md_cgen_lookup_reloc (const CGEN_INSN *insn ATTRIBUTE_UNUSED,
1334 const CGEN_OPERAND *operand,
1335 fixS *fixP)
0ebb9a87
DB
1336{
1337 switch (operand->type)
1338 {
1339 case FRV_OPERAND_LABEL16:
b34976b6 1340 fixP->fx_pcrel = TRUE;
0ebb9a87
DB
1341 return BFD_RELOC_FRV_LABEL16;
1342
1343 case FRV_OPERAND_LABEL24:
b34976b6 1344 fixP->fx_pcrel = TRUE;
90219bd0
AO
1345
1346 if (fixP->fx_cgen.opinfo != 0)
1347 return fixP->fx_cgen.opinfo;
1348
0ebb9a87
DB
1349 return BFD_RELOC_FRV_LABEL24;
1350
1351 case FRV_OPERAND_UHI16:
1352 case FRV_OPERAND_ULO16:
1353 case FRV_OPERAND_SLO16:
90219bd0
AO
1354 case FRV_OPERAND_CALLANN:
1355 case FRV_OPERAND_LDANN:
1356 case FRV_OPERAND_LDDANN:
0ebb9a87
DB
1357 /* The relocation type should be recorded in opinfo */
1358 if (fixP->fx_cgen.opinfo != 0)
1359 return fixP->fx_cgen.opinfo;
1360 break;
1361
1362 case FRV_OPERAND_D12:
1363 case FRV_OPERAND_S12:
99d09cdb
AO
1364 if (fixP->fx_cgen.opinfo != 0)
1365 return fixP->fx_cgen.opinfo;
1366
0ebb9a87
DB
1367 return BFD_RELOC_FRV_GPREL12;
1368
1369 case FRV_OPERAND_U12:
1370 return BFD_RELOC_FRV_GPRELU12;
1371
3739860c 1372 default:
0ebb9a87
DB
1373 break;
1374 }
1375 return BFD_RELOC_NONE;
1376}
1377
1378
1379/* See whether we need to force a relocation into the output file.
1380 This is used to force out switch and PC relative relocations when
1381 relaxing. */
1382
1383int
5a49b8ac 1384frv_force_relocation (fixS *fix)
0ebb9a87 1385{
90219bd0 1386 switch (fix->fx_r_type < BFD_RELOC_UNUSED
f17c130b 1387 ? (int) fix->fx_r_type
90219bd0
AO
1388 : fix->fx_cgen.opinfo)
1389 {
1390 case BFD_RELOC_FRV_GPREL12:
1391 case BFD_RELOC_FRV_GPRELU12:
1392 case BFD_RELOC_FRV_GPREL32:
1393 case BFD_RELOC_FRV_GPRELHI:
1394 case BFD_RELOC_FRV_GPRELLO:
1395 case BFD_RELOC_FRV_GOT12:
1396 case BFD_RELOC_FRV_GOTHI:
1397 case BFD_RELOC_FRV_GOTLO:
1398 case BFD_RELOC_FRV_FUNCDESC_VALUE:
1399 case BFD_RELOC_FRV_FUNCDESC_GOTOFF12:
1400 case BFD_RELOC_FRV_FUNCDESC_GOTOFFHI:
1401 case BFD_RELOC_FRV_FUNCDESC_GOTOFFLO:
1402 case BFD_RELOC_FRV_GOTOFF12:
1403 case BFD_RELOC_FRV_GOTOFFHI:
1404 case BFD_RELOC_FRV_GOTOFFLO:
1405 case BFD_RELOC_FRV_GETTLSOFF:
1406 case BFD_RELOC_FRV_TLSDESC_VALUE:
1407 case BFD_RELOC_FRV_GOTTLSDESC12:
1408 case BFD_RELOC_FRV_GOTTLSDESCHI:
1409 case BFD_RELOC_FRV_GOTTLSDESCLO:
1410 case BFD_RELOC_FRV_TLSMOFF12:
1411 case BFD_RELOC_FRV_TLSMOFFHI:
1412 case BFD_RELOC_FRV_TLSMOFFLO:
1413 case BFD_RELOC_FRV_GOTTLSOFF12:
1414 case BFD_RELOC_FRV_GOTTLSOFFHI:
1415 case BFD_RELOC_FRV_GOTTLSOFFLO:
1416 case BFD_RELOC_FRV_TLSOFF:
1417 case BFD_RELOC_FRV_TLSDESC_RELAX:
1418 case BFD_RELOC_FRV_GETTLSOFF_RELAX:
1419 case BFD_RELOC_FRV_TLSOFF_RELAX:
1420 return 1;
1421
1422 default:
1423 break;
1424 }
0ebb9a87 1425
ae6063d4 1426 return generic_force_reloc (fix);
0ebb9a87 1427}
99d09cdb
AO
1428
1429/* Apply a fixup that could be resolved within the assembler. */
1430
1431void
5a49b8ac 1432md_apply_fix (fixS *fixP, valueT *valP, segT seg)
99d09cdb
AO
1433{
1434 if (fixP->fx_addsy == 0)
1435 switch (fixP->fx_cgen.opinfo)
1436 {
1437 case BFD_RELOC_FRV_HI16:
1438 *valP >>= 16;
1439 /* Fall through. */
1440 case BFD_RELOC_FRV_LO16:
1441 *valP &= 0xffff;
1442 break;
90219bd0
AO
1443
1444 /* We need relocations for these, even if their symbols reduce
1445 to constants. */
1446 case BFD_RELOC_FRV_GPREL12:
1447 case BFD_RELOC_FRV_GPRELU12:
1448 case BFD_RELOC_FRV_GPREL32:
1449 case BFD_RELOC_FRV_GPRELHI:
1450 case BFD_RELOC_FRV_GPRELLO:
1451 case BFD_RELOC_FRV_GOT12:
1452 case BFD_RELOC_FRV_GOTHI:
1453 case BFD_RELOC_FRV_GOTLO:
1454 case BFD_RELOC_FRV_FUNCDESC_VALUE:
1455 case BFD_RELOC_FRV_FUNCDESC_GOTOFF12:
1456 case BFD_RELOC_FRV_FUNCDESC_GOTOFFHI:
1457 case BFD_RELOC_FRV_FUNCDESC_GOTOFFLO:
1458 case BFD_RELOC_FRV_GOTOFF12:
1459 case BFD_RELOC_FRV_GOTOFFHI:
1460 case BFD_RELOC_FRV_GOTOFFLO:
1461 case BFD_RELOC_FRV_GETTLSOFF:
1462 case BFD_RELOC_FRV_TLSDESC_VALUE:
1463 case BFD_RELOC_FRV_GOTTLSDESC12:
1464 case BFD_RELOC_FRV_GOTTLSDESCHI:
1465 case BFD_RELOC_FRV_GOTTLSDESCLO:
1466 case BFD_RELOC_FRV_TLSMOFF12:
1467 case BFD_RELOC_FRV_TLSMOFFHI:
1468 case BFD_RELOC_FRV_TLSMOFFLO:
1469 case BFD_RELOC_FRV_GOTTLSOFF12:
1470 case BFD_RELOC_FRV_GOTTLSOFFHI:
1471 case BFD_RELOC_FRV_GOTTLSOFFLO:
1472 case BFD_RELOC_FRV_TLSOFF:
1473 case BFD_RELOC_FRV_TLSDESC_RELAX:
1474 case BFD_RELOC_FRV_GETTLSOFF_RELAX:
1475 case BFD_RELOC_FRV_TLSOFF_RELAX:
455bde50 1476 fixP->fx_addsy = abs_section_sym;
90219bd0
AO
1477 break;
1478 }
1479 else
1480 switch (fixP->fx_cgen.opinfo)
1481 {
1482 case BFD_RELOC_FRV_GETTLSOFF:
1483 case BFD_RELOC_FRV_TLSDESC_VALUE:
1484 case BFD_RELOC_FRV_GOTTLSDESC12:
1485 case BFD_RELOC_FRV_GOTTLSDESCHI:
1486 case BFD_RELOC_FRV_GOTTLSDESCLO:
1487 case BFD_RELOC_FRV_TLSMOFF12:
1488 case BFD_RELOC_FRV_TLSMOFFHI:
1489 case BFD_RELOC_FRV_TLSMOFFLO:
1490 case BFD_RELOC_FRV_GOTTLSOFF12:
1491 case BFD_RELOC_FRV_GOTTLSOFFHI:
1492 case BFD_RELOC_FRV_GOTTLSOFFLO:
1493 case BFD_RELOC_FRV_TLSOFF:
1494 case BFD_RELOC_FRV_TLSDESC_RELAX:
1495 case BFD_RELOC_FRV_GETTLSOFF_RELAX:
1496 case BFD_RELOC_FRV_TLSOFF_RELAX:
1497 /* Mark TLS symbols as such. */
1498 if (S_GET_SEGMENT (fixP->fx_addsy) != absolute_section)
1499 S_SET_THREAD_LOCAL (fixP->fx_addsy);
1500 break;
99d09cdb
AO
1501 }
1502
55cf6793 1503 gas_cgen_md_apply_fix (fixP, valP, seg);
99d09cdb
AO
1504 return;
1505}
1506
0ebb9a87
DB
1507\f
1508/* Write a value out to the object file, using the appropriate endianness. */
1509
1510void
5a49b8ac 1511frv_md_number_to_chars (char *buf, valueT val, int n)
0ebb9a87
DB
1512{
1513 number_to_chars_bigendian (buf, val, n);
1514}
1515
6d4af3c2 1516const char *
5a49b8ac 1517md_atof (int type, char *litP, int *sizeP)
0ebb9a87 1518{
499ac353 1519 return ieee_md_atof (type, litP, sizeP, TRUE);
0ebb9a87
DB
1520}
1521
b34976b6 1522bfd_boolean
5a49b8ac 1523frv_fix_adjustable (fixS *fixP)
0ebb9a87
DB
1524{
1525 bfd_reloc_code_real_type reloc_type;
1526
1527 if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
1528 {
1529 const CGEN_INSN *insn = NULL;
1530 int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
1531 const CGEN_OPERAND *operand = cgen_operand_lookup_by_num(gas_cgen_cpu_desc, opindex);
1532 reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
1533 }
1534 else
1535 reloc_type = fixP->fx_r_type;
1536
0ebb9a87
DB
1537 /* We need the symbol name for the VTABLE entries */
1538 if ( reloc_type == BFD_RELOC_VTABLE_INHERIT
1539 || reloc_type == BFD_RELOC_VTABLE_ENTRY
1540 || reloc_type == BFD_RELOC_FRV_GPREL12
1541 || reloc_type == BFD_RELOC_FRV_GPRELU12)
1542 return 0;
1543
1544 return 1;
1545}
1546
1547/* Allow user to set flags bits. */
1548void
5a49b8ac 1549frv_set_flags (int arg ATTRIBUTE_UNUSED)
0ebb9a87
DB
1550{
1551 flagword new_flags = get_absolute_expression ();
1552 flagword new_mask = ~ (flagword)0;
1553
1554 frv_user_set_flags_p = 1;
1555 if (*input_line_pointer == ',')
1556 {
1557 ++input_line_pointer;
1558 new_mask = get_absolute_expression ();
1559 }
1560
1561 frv_flags = (frv_flags & ~new_mask) | (new_flags & new_mask);
1562 bfd_set_private_flags (stdoutput, frv_flags);
1563}
1564
1565/* Frv specific function to handle 4 byte initializations for pointers that are
1566 considered 'safe' for use with pic support. Until frv_frob_file{,_section}
1567 is run, we encode it a BFD_RELOC_CTOR, and it is turned back into a normal
1568 BFD_RELOC_32 at that time. */
1569
1570void
5a49b8ac 1571frv_pic_ptr (int nbytes)
0ebb9a87
DB
1572{
1573 expressionS exp;
1574 char *p;
1575
1576 if (nbytes != 4)
1577 abort ();
1578
1579#ifdef md_flush_pending_output
1580 md_flush_pending_output ();
1581#endif
1582
1583 if (is_it_end_of_statement ())
1584 {
1585 demand_empty_rest_of_line ();
1586 return;
1587 }
1588
1589#ifdef md_cons_align
1590 md_cons_align (nbytes);
1591#endif
1592
1593 do
1594 {
99d09cdb 1595 bfd_reloc_code_real_type reloc_type = BFD_RELOC_CTOR;
3739860c 1596
99d09cdb
AO
1597 if (strncasecmp (input_line_pointer, "funcdesc(", 9) == 0)
1598 {
1599 input_line_pointer += 9;
1600 expression (&exp);
1601 if (*input_line_pointer == ')')
1602 input_line_pointer++;
1603 else
bd3ba5d1 1604 as_bad (_("missing ')'"));
99d09cdb
AO
1605 reloc_type = BFD_RELOC_FRV_FUNCDESC;
1606 }
90219bd0
AO
1607 else if (strncasecmp (input_line_pointer, "tlsmoff(", 8) == 0)
1608 {
1609 input_line_pointer += 8;
1610 expression (&exp);
1611 if (*input_line_pointer == ')')
1612 input_line_pointer++;
1613 else
bd3ba5d1 1614 as_bad (_("missing ')'"));
90219bd0
AO
1615 reloc_type = BFD_RELOC_FRV_TLSMOFF;
1616 }
99d09cdb
AO
1617 else
1618 expression (&exp);
0ebb9a87
DB
1619
1620 p = frag_more (4);
1621 memset (p, 0, 4);
1622 fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &exp, 0,
99d09cdb 1623 reloc_type);
0ebb9a87
DB
1624 }
1625 while (*input_line_pointer++ == ',');
1626
1627 input_line_pointer--; /* Put terminator back into stream. */
1628 demand_empty_rest_of_line ();
1629}
1630
1631\f
1632
1633#ifdef DEBUG
1634#define DPRINTF1(A) fprintf (stderr, A)
1635#define DPRINTF2(A,B) fprintf (stderr, A, B)
1636#define DPRINTF3(A,B,C) fprintf (stderr, A, B, C)
1637
1638#else
1639#define DPRINTF1(A)
1640#define DPRINTF2(A,B)
1641#define DPRINTF3(A,B,C)
1642#endif
1643
1644/* Go through a the sections looking for relocations that are problematical for
1645 pic. If not pic, just note that this object can't be linked with pic. If
1646 it is pic, see if it needs to be marked so that it will be fixed up, or if
1647 not possible, issue an error. */
1648
1649static void
5a49b8ac 1650frv_frob_file_section (bfd *abfd, asection *sec, void *ptr ATTRIBUTE_UNUSED)
0ebb9a87
DB
1651{
1652 segment_info_type *seginfo = seg_info (sec);
1653 fixS *fixp;
1654 CGEN_CPU_DESC cd = gas_cgen_cpu_desc;
1655 flagword flags = bfd_get_section_flags (abfd, sec);
1656
1657 /* Skip relocations in known sections (.ctors, .dtors, and .gcc_except_table)
1658 since we can fix those up by hand. */
1659 int known_section_p = (sec->name
1660 && sec->name[0] == '.'
1661 && ((sec->name[1] == 'c'
1662 && strcmp (sec->name, ".ctor") == 0)
1663 || (sec->name[1] == 'd'
1664 && strcmp (sec->name, ".dtor") == 0)
1665 || (sec->name[1] == 'g'
1666 && strcmp (sec->name, ".gcc_except_table") == 0)));
1667
1668 DPRINTF3 ("\nFrv section %s%s\n", sec->name, (known_section_p) ? ", known section" : "");
1669 if ((flags & SEC_ALLOC) == 0)
1670 {
1671 DPRINTF1 ("\tSkipping non-loaded section\n");
1672 return;
1673 }
1674
1675 for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next)
1676 {
1677 symbolS *s = fixp->fx_addsy;
1678 bfd_reloc_code_real_type reloc;
1679 int non_pic_p;
1680 int opindex;
1681 const CGEN_OPERAND *operand;
1682 const CGEN_INSN *insn = fixp->fx_cgen.insn;
1683
1684 if (fixp->fx_done)
1685 {
1686 DPRINTF1 ("\tSkipping reloc that has already been done\n");
1687 continue;
1688 }
1689
1690 if (fixp->fx_pcrel)
1691 {
1692 DPRINTF1 ("\tSkipping reloc that is PC relative\n");
1693 continue;
1694 }
1695
1696 if (! s)
1697 {
1698 DPRINTF1 ("\tSkipping reloc without symbol\n");
1699 continue;
1700 }
1701
1702 if (fixp->fx_r_type < BFD_RELOC_UNUSED)
1703 {
1704 opindex = -1;
1705 reloc = fixp->fx_r_type;
1706 }
1707 else
1708 {
1709 opindex = (int) fixp->fx_r_type - (int) BFD_RELOC_UNUSED;
1710 operand = cgen_operand_lookup_by_num (cd, opindex);
1711 reloc = md_cgen_lookup_reloc (insn, operand, fixp);
1712 }
1713
1714 DPRINTF3 ("\treloc %s\t%s", bfd_get_reloc_code_name (reloc), S_GET_NAME (s));
1715
1716 non_pic_p = 0;
1717 switch (reloc)
1718 {
1719 default:
1720 break;
1721
1722 case BFD_RELOC_32:
1723 /* Skip relocations in known sections (.ctors, .dtors, and
1724 .gcc_except_table) since we can fix those up by hand. Also
1725 skip forward references to constants. Also skip a difference
1726 of two symbols, which still uses the BFD_RELOC_32 at this
1727 point. */
1728 if (! known_section_p
1729 && S_GET_SEGMENT (s) != absolute_section
1730 && !fixp->fx_subsy
1731 && (flags & (SEC_READONLY | SEC_CODE)) == 0)
1732 {
1733 non_pic_p = 1;
1734 }
1735 break;
1736
1737 /* FIXME -- should determine if any of the GP relocation really uses
1738 gr16 (which is not pic safe) or not. Right now, assume if we
1739 aren't being compiled with -mpic, the usage is non pic safe, but
1740 is safe with -mpic. */
1741 case BFD_RELOC_FRV_GPREL12:
1742 case BFD_RELOC_FRV_GPRELU12:
1743 case BFD_RELOC_FRV_GPREL32:
1744 case BFD_RELOC_FRV_GPRELHI:
1745 case BFD_RELOC_FRV_GPRELLO:
1746 non_pic_p = ! frv_pic_p;
1747 break;
1748
1749 case BFD_RELOC_FRV_LO16:
1750 case BFD_RELOC_FRV_HI16:
1751 if (S_GET_SEGMENT (s) != absolute_section)
1752 non_pic_p = 1;
1753 break;
1754
1755 case BFD_RELOC_VTABLE_INHERIT:
1756 case BFD_RELOC_VTABLE_ENTRY:
1757 non_pic_p = 1;
1758 break;
1759
1760 /* If this is a blessed BFD_RELOC_32, convert it back to the normal
1761 relocation. */
1762 case BFD_RELOC_CTOR:
1763 fixp->fx_r_type = BFD_RELOC_32;
1764 break;
1765 }
1766
1767 if (non_pic_p)
1768 {
1769 DPRINTF1 (" (Non-pic relocation)\n");
1770 if (frv_pic_p)
1771 as_warn_where (fixp->fx_file, fixp->fx_line,
1772 _("Relocation %s is not safe for %s"),
1773 bfd_get_reloc_code_name (reloc), frv_pic_flag);
1774
1775 else if ((frv_flags & EF_FRV_NON_PIC_RELOCS) == 0)
1776 {
1777 frv_flags |= EF_FRV_NON_PIC_RELOCS;
1778 bfd_set_private_flags (abfd, frv_flags);
1779 }
1780 }
1781#ifdef DEBUG
1782 else
1783 DPRINTF1 ("\n");
1784#endif
1785 }
1786}
1787
1788/* After all of the symbols have been adjusted, go over the file looking
1789 for any relocations that pic won't support. */
1790
1791void
5a49b8ac 1792frv_frob_file (void)
0ebb9a87 1793{
5a49b8ac 1794 bfd_map_over_sections (stdoutput, frv_frob_file_section, (void *) 0);
0ebb9a87
DB
1795}
1796
1797void
5a49b8ac 1798frv_frob_label (symbolS *this_label)
0ebb9a87
DB
1799{
1800 struct vliw_insn_list *vliw_insn_list_entry;
1801
f2e25d93 1802 dwarf2_emit_label (this_label);
0ebb9a87
DB
1803 if (frv_mach != bfd_mach_frvtomcat)
1804 return;
1805
1806 if (now_seg != text_section)
1807 return;
1808
1809 vliw_insn_list_entry = frv_insert_vliw_insn(DONT_COUNT);
1810 vliw_insn_list_entry->type = VLIW_LABEL_TYPE;
3739860c 1811 vliw_insn_list_entry->sym = this_label;
0ebb9a87
DB
1812}
1813
1814fixS *
5a49b8ac
AM
1815frv_cgen_record_fixup_exp (fragS *frag,
1816 int where,
1817 const CGEN_INSN *insn,
1818 int length,
1819 const CGEN_OPERAND *operand,
1820 int opinfo,
1821 expressionS *exp)
0ebb9a87
DB
1822{
1823 fixS * fixP = gas_cgen_record_fixup_exp (frag, where, insn, length,
1824 operand, opinfo, exp);
1825
1826 if (frv_mach == bfd_mach_frvtomcat
1827 && current_vliw_insn
1828 && current_vliw_insn->type == VLIW_BRANCH_TYPE
1829 && exp != NULL)
1830 current_vliw_insn->sym = exp->X_add_symbol;
3739860c 1831
0ebb9a87
DB
1832 return fixP;
1833}