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