OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-binutils/] [binutils-2.19.1/] [gas/] [config/] [tc-frv.c] - Blame information for rev 6

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 6 jlechner
/* tc-frv.c -- Assembler for the Fujitsu FRV.
2
   Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008
3
   Free Software Foundation. Inc.
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
9
   the Free Software Foundation; either version 3, or (at your option)
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
19
   the Free Software Foundation, 51 Franklin Street - Fifth Floor,
20
   Boston, MA 02110-1301, USA.  */
21
 
22
#include "as.h"
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.  */
34
typedef 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
}
52
frv_insn;
53
 
54
enum 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
 
69
#define DO_COUNT    TRUE
70
#define DONT_COUNT  FALSE
71
 
72
/* A list of insns within a VLIW insn.  */
73
struct 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
 
97
static struct vliw_insn_list single_nop_insn = {
98
   VLIW_NOP_TYPE, NULL, NULL, NULL, NULL, NULL, NULL };
99
 
100
static struct vliw_insn_list double_nop_insn = {
101
   VLIW_NOP_TYPE, NULL, NULL, NULL, NULL, NULL, NULL };
102
 
103
struct vliw_chain
104
{
105
  int                   num;
106
  int                   insn_count;
107
  struct vliw_insn_list *insn_list;
108
  struct vliw_chain     *next;
109
};
110
 
111
static struct vliw_chain        *vliw_chain_top;
112
static struct vliw_chain        *current_vliw_chain;
113
static struct vliw_chain        *previous_vliw_chain;
114
static struct vliw_insn_list    *current_vliw_insn;
115
 
116
const char comment_chars[]        = ";";
117
const char line_comment_chars[]   = "#";
118
const char line_separator_chars[] = "!";
119
const char EXP_CHARS[]            = "eE";
120
const char FLT_CHARS[]            = "dD";
121
 
122
static 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
 
150
#else
151
#ifdef  DEFAULT_CPU_FR550
152
#define DEFAULT_MACHINE bfd_mach_fr550
153
#define DEFAULT_FLAGS   EF_FRV_CPU_FR550
154
 
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
163
#endif
164
 
165
#ifdef TE_LINUX
166
# define DEFAULT_FDPIC  EF_FRV_FDPIC
167
#else
168
# define DEFAULT_FDPIC  0
169
#endif
170
 
171
static unsigned long frv_mach = bfd_mach_frv;
172
static bfd_boolean fr400_audio;
173
 
174
/* Flags to set in the elf header */
175
static flagword frv_flags = DEFAULT_FLAGS | DEFAULT_FDPIC;
176
 
177
static int frv_user_set_flags_p = 0;
178
static int frv_pic_p = 0;
179
static const char *frv_pic_flag = DEFAULT_FDPIC ? "-mfdpic" : (const char *)0;
180
 
181
/* Print tomcat-specific debugging info.  */
182
static int tomcat_debug = 0;
183
 
184
/* Tomcat-specific NOP statistics.  */
185
static int tomcat_stats = 0;
186
static int tomcat_doubles = 0;
187
static int tomcat_singles = 0;
188
 
189
/* Forward reference to static functions */
190
static void frv_set_flags (int);
191
static void frv_pic_ptr (int);
192
 
193
/* The target specific pseudo-ops which we support.  */
194
const pseudo_typeS md_pseudo_table[] =
195
{
196
  { "eflags",   frv_set_flags,          0 },
197
  { "word",     cons,                   4 },
198
  { "picptr",   frv_pic_ptr,            4 },
199
  { NULL,       NULL,                   0 }
200
};
201
 
202
 
203
#define FRV_SHORTOPTS "G:"
204
const 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)
227
#define OPTION_FDPIC            (OPTION_MD_BASE + 21)
228
#define OPTION_NOPIC            (OPTION_MD_BASE + 22)
229
 
230
struct 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       },
254
  { "mfdpic",           no_argument,            NULL, OPTION_FDPIC         },
255
  { "mnopic",           no_argument,            NULL, OPTION_NOPIC         },
256
  { NULL,               no_argument,            NULL, 0                 },
257
};
258
 
259
size_t md_longopts_size = sizeof (md_longopts);
260
 
261
/* What value to give to bfd_set_gp_size.  */
262
static int g_switch_value = 8;
263
 
264
int
265
md_parse_option (int c, char *arg)
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
      {
340
        char *p;
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
 
357
        else if (strcmp (p, "fr550") == 0)
358
          {
359
            cpu_flags = EF_FRV_CPU_FR550;
360
            frv_mach = bfd_mach_fr550;
361
          }
362
 
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
 
376
        else if (strcmp (p, "fr400") == 0)
377
          {
378
            cpu_flags = EF_FRV_CPU_FR400;
379
            frv_mach = bfd_mach_fr400;
380
            fr400_audio = FALSE;
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
          {
404
            as_fatal (_("Unknown cpu -mcpu=%s"), arg);
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
 
431
    case OPTION_FDPIC:
432
      frv_flags |= EF_FRV_FDPIC;
433
      frv_pic_flag = "-mfdpic";
434
      break;
435
 
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
 
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
 
454
void
455
md_show_usage (FILE * stream)
456
{
457
  fprintf (stream, _("FRV specific command line options:\n"));
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"));
476
  fprintf (stream, _("-mcpu={fr500|fr550|fr400|fr405|fr450|fr300|frv|simple|tomcat}\n"));
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"));
480
}
481
 
482
 
483
void
484
md_begin (void)
485
{
486
  /* Initialize the `cgen' interface.  */
487
 
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
 
511
bfd_boolean
512
frv_md_fdpic_enabled (void)
513
{
514
  return (frv_flags & EF_FRV_FDPIC) != 0;
515
}
516
 
517
int chain_num = 0;
518
 
519
static struct vliw_insn_list *
520
frv_insert_vliw_insn (bfd_boolean count)
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:
562
 
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.
567
 
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.
571
 
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.
575
 
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.
581
 
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
 
589
static struct vliw_insn_list *
590
frv_find_in_vliw (enum vliw_insn_type vliw_insn_type,
591
                  struct vliw_chain *this_chain,
592
                  symbolS *label_sym)
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
 
610
enum vliw_nop_type
611
{
612
  /* A Vliw insn containing a single nop insn.  */
613
  VLIW_SINGLE_NOP,
614
 
615
  /* A Vliw insn containing two nop insns.  */
616
  VLIW_DOUBLE_NOP,
617
 
618
  /* Two vliw insns.  The first containing two nop insns.
619
     The second contain a single nop insn.  */
620
  VLIW_DOUBLE_THEN_SINGLE_NOP
621
};
622
 
623
static void
624
frv_debug_tomcat (struct vliw_chain *start_chain)
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)
637
            fprintf (stderr, "Label Value: %p\n", this_insn->sym);
638
          else if (this_insn->type == VLIW_BRANCH_TYPE)
639
            fprintf (stderr, "%s to %p\n", this_insn->insn->base->name, this_insn->sym);
640
          else if (this_insn->type == VLIW_BRANCH_HAS_NOPS)
641
            fprintf (stderr, "nop'd %s to %p\n", this_insn->insn->base->name, this_insn->sym);
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
 
650
static void
651
frv_adjust_vliw_count (struct vliw_chain *this_chain)
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
 
670
static struct vliw_chain *
671
frv_tomcat_shuffle (enum vliw_nop_type this_nop_type,
672
                    struct vliw_chain *vliw_to_split,
673
                    struct vliw_insn_list *insert_before_insn)
674
{
675
 
676
  bfd_boolean pack_prev = FALSE;
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)
697
        pack_prev = TRUE;
698
      prev_insn = curr_insn;
699
      curr_insn = curr_insn->next;
700
    }
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
            {
727
              char *buffer = prev_insn->address;
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;
739
 
740
          vliw_to_split->next    = single_nop;
741
          prev_insn->next        = NULL;
742
 
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
            {
766
              char *buffer = prev_insn->address;
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);
776
 
777
          double_nop->next       = second_part;
778
 
779
          vliw_to_split->next    = single_nop;
780
          prev_insn->next        = NULL;
781
          frv_adjust_vliw_count (vliw_to_split);
782
 
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;
802
 
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
            {
812
              char *buffer = prev_insn->address;
813
              buffer[0] |= 0x80;
814
            }
815
 
816
          /* The branch is in the middle of this vliw insn.  Split into first and
817
             second parts.  Insert the nop vliws in between.  */
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
 
837
static void
838
frv_tomcat_analyze_vliw_chains (void)
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
 
862
workaround_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
            }
884
          else if (vliw2
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
    {
899
      struct vliw_insn_list *this_insn;
900
 
901
      /* check vliw1 for a label. */
902
      for (this_insn = vliw1->insn_list; this_insn; this_insn = this_insn->next)
903
        {
904
          if (this_insn->type == VLIW_LABEL_TYPE)
905
            {
906
              if ((temp_insn = frv_find_in_vliw (VLIW_BRANCH_TYPE, vliw2, this_insn->sym)) != NULL)
907
                {
908
                  temp_insn->snop_frag->fr_subtype = NOP_KEEP;
909
                  vliw1 = frv_tomcat_shuffle (VLIW_SINGLE_NOP, vliw2, this_insn);
910
                  if (tomcat_stats)
911
                    tomcat_singles++;
912
                }
913
              else
914
                vliw1 = vliw1->next;
915
              goto workaround_top;
916
            }
917
        }
918
    }
919
  /* Examine each insn in this VLIW.  Look for the workaround criteria.  */
920
  for (this_insn = vliw1->insn_list; this_insn; this_insn = this_insn->next)
921
    {
922
      /* Don't look at labels or nops.  */
923
      while (this_insn
924
             && (this_insn->type == VLIW_LABEL_TYPE
925
                 || this_insn->type == VLIW_NOP_TYPE
926
                 || this_insn->type == VLIW_BRANCH_HAS_NOPS))
927
        this_insn = this_insn->next;
928
 
929
      if (!this_insn)
930
        {
931
          vliw1 = vliw2;
932
          goto workaround_top;
933
        }
934
 
935
      if (frv_is_branch_insn (this_insn->insn))
936
        {
937
          if ((temp_insn = frv_find_in_vliw (VLIW_LABEL_TYPE, vliw1, this_insn->sym)) != NULL)
938
            {
939
              /* Insert [nop/nop] [nop] before branch.  */
940
              this_insn->snop_frag->fr_subtype = NOP_KEEP;
941
              this_insn->dnop_frag->fr_subtype = NOP_KEEP;
942
              vliw1 = frv_tomcat_shuffle (VLIW_DOUBLE_THEN_SINGLE_NOP, vliw1, this_insn);
943
              goto workaround_top;
944
            }
945
        }
946
 
947
 
948
    }
949
  /* This vliw insn checks out okay.  Take a look at the next one.  */
950
  vliw1 = vliw1->next;
951
  goto workaround_top;
952
}
953
 
954
void
955
frv_tomcat_workaround (void)
956
{
957
  if (frv_mach != bfd_mach_frvtomcat)
958
    return;
959
 
960
  if (tomcat_debug)
961
    frv_debug_tomcat (vliw_chain_top);
962
 
963
  frv_tomcat_analyze_vliw_chains ();
964
 
965
  if (tomcat_stats)
966
    {
967
      fprintf (stderr, "Inserted %d Single Nops\n", tomcat_singles);
968
      fprintf (stderr, "Inserted %d Double Nops\n", tomcat_doubles);
969
    }
970
}
971
 
972
static int
973
fr550_check_insn_acc_range (frv_insn *insn, int low, int hi)
974
{
975
  int acc;
976
  switch (CGEN_INSN_NUM (insn->insn))
977
    {
978
    case FRV_INSN_MADDACCS:
979
    case FRV_INSN_MSUBACCS:
980
    case FRV_INSN_MDADDACCS:
981
    case FRV_INSN_MDSUBACCS:
982
    case FRV_INSN_MASACCS:
983
    case FRV_INSN_MDASACCS:
984
      acc = insn->fields.f_ACC40Si;
985
      if (acc < low || acc > hi)
986
        return 1; /* out of range */
987
      acc = insn->fields.f_ACC40Sk;
988
      if (acc < low || acc > hi)
989
        return 1; /* out of range */
990
      break;
991
    case FRV_INSN_MMULHS:
992
    case FRV_INSN_MMULHU:
993
    case FRV_INSN_MMULXHS:
994
    case FRV_INSN_MMULXHU:
995
    case FRV_INSN_CMMULHS:
996
    case FRV_INSN_CMMULHU:
997
    case FRV_INSN_MQMULHS:
998
    case FRV_INSN_MQMULHU:
999
    case FRV_INSN_MQMULXHS:
1000
    case FRV_INSN_MQMULXHU:
1001
    case FRV_INSN_CMQMULHS:
1002
    case FRV_INSN_CMQMULHU:
1003
    case FRV_INSN_MMACHS:
1004
    case FRV_INSN_MMRDHS:
1005
    case FRV_INSN_CMMACHS:
1006
    case FRV_INSN_MQMACHS:
1007
    case FRV_INSN_CMQMACHS:
1008
    case FRV_INSN_MQXMACHS:
1009
    case FRV_INSN_MQXMACXHS:
1010
    case FRV_INSN_MQMACXHS:
1011
    case FRV_INSN_MCPXRS:
1012
    case FRV_INSN_MCPXIS:
1013
    case FRV_INSN_CMCPXRS:
1014
    case FRV_INSN_CMCPXIS:
1015
    case FRV_INSN_MQCPXRS:
1016
    case FRV_INSN_MQCPXIS:
1017
     acc = insn->fields.f_ACC40Sk;
1018
      if (acc < low || acc > hi)
1019
        return 1; /* out of range */
1020
      break;
1021
    case FRV_INSN_MMACHU:
1022
    case FRV_INSN_MMRDHU:
1023
    case FRV_INSN_CMMACHU:
1024
    case FRV_INSN_MQMACHU:
1025
    case FRV_INSN_CMQMACHU:
1026
    case FRV_INSN_MCPXRU:
1027
    case FRV_INSN_MCPXIU:
1028
    case FRV_INSN_CMCPXRU:
1029
    case FRV_INSN_CMCPXIU:
1030
    case FRV_INSN_MQCPXRU:
1031
    case FRV_INSN_MQCPXIU:
1032
      acc = insn->fields.f_ACC40Uk;
1033
      if (acc < low || acc > hi)
1034
        return 1; /* out of range */
1035
      break;
1036
    default:
1037
      break;
1038
    }
1039
  return 0; /* all is ok */
1040
}
1041
 
1042
static int
1043
fr550_check_acc_range (FRV_VLIW *vliw, frv_insn *insn)
1044
{
1045
  switch ((*vliw->current_vliw)[vliw->next_slot - 1])
1046
    {
1047
    case UNIT_FM0:
1048
    case UNIT_FM2:
1049
      return fr550_check_insn_acc_range (insn, 0, 3);
1050
    case UNIT_FM1:
1051
    case UNIT_FM3:
1052
      return fr550_check_insn_acc_range (insn, 4, 7);
1053
    default:
1054
      break;
1055
    }
1056
  return 0; /* all is ok */
1057
}
1058
 
1059
/* Return true if the target implements instruction INSN.  */
1060
 
1061
static bfd_boolean
1062
target_implements_insn_p (const CGEN_INSN *insn)
1063
{
1064
  switch (frv_mach)
1065
    {
1066
    default:
1067
      /* bfd_mach_frv or generic.  */
1068
      return TRUE;
1069
 
1070
    case bfd_mach_fr300:
1071
    case bfd_mach_frvsimple:
1072
      return CGEN_INSN_MACH_HAS_P (insn, MACH_SIMPLE);
1073
 
1074
    case bfd_mach_fr400:
1075
      return ((fr400_audio || !CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_AUDIO))
1076
              && CGEN_INSN_MACH_HAS_P (insn, MACH_FR400));
1077
 
1078
    case bfd_mach_fr450:
1079
      return CGEN_INSN_MACH_HAS_P (insn, MACH_FR450);
1080
 
1081
    case bfd_mach_fr500:
1082
      return CGEN_INSN_MACH_HAS_P (insn, MACH_FR500);
1083
 
1084
    case bfd_mach_fr550:
1085
      return CGEN_INSN_MACH_HAS_P (insn, MACH_FR550);
1086
    }
1087
}
1088
 
1089
void
1090
md_assemble (char *str)
1091
{
1092
  frv_insn insn;
1093
  char *errmsg;
1094
  int packing_constraint;
1095
  finished_insnS  finished_insn;
1096
  fragS *double_nop_frag = NULL;
1097
  fragS *single_nop_frag = NULL;
1098
  struct vliw_insn_list *vliw_insn_list_entry = NULL;
1099
 
1100
  /* Initialize GAS's cgen interface for a new instruction.  */
1101
  gas_cgen_init_parse ();
1102
 
1103
  memset (&insn, 0, sizeof (insn));
1104
 
1105
  insn.insn = frv_cgen_assemble_insn
1106
    (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, &errmsg);
1107
 
1108
  if (!insn.insn)
1109
    {
1110
      as_bad (errmsg);
1111
      return;
1112
    }
1113
 
1114
  /* If the cpu is tomcat, then we need to insert nops to workaround
1115
     hardware limitations.  We need to keep track of each vliw unit
1116
     and examine the length of the unit and the individual insns
1117
     within the unit to determine the number and location of the
1118
     required nops.  */
1119
  if (frv_mach == bfd_mach_frvtomcat)
1120
    {
1121
      /* If we've just finished a VLIW insn OR this is a branch,
1122
         then start up a new frag.  Fill it with nops.  We will get rid
1123
         of those that are not required after we've seen all of the
1124
         instructions but before we start resolving fixups.  */
1125
      if ( !FRV_IS_NOP (insn)
1126
          && (frv_is_branch_insn (insn.insn) || insn.fields.f_pack))
1127
        {
1128
          char *buffer;
1129
 
1130
          frag_wane (frag_now);
1131
          frag_new (0);
1132
          double_nop_frag = frag_now;
1133
          buffer = frag_var (rs_machine_dependent, 8, 8, NOP_DELETE, NULL, 0, 0);
1134
          md_number_to_chars (buffer, FRV_NOP_PACK, 4);
1135
          md_number_to_chars (buffer+4, FRV_NOP_NOPACK, 4);
1136
 
1137
          frag_wane (frag_now);
1138
          frag_new (0);
1139
          single_nop_frag = frag_now;
1140
          buffer = frag_var (rs_machine_dependent, 4, 4, NOP_DELETE, NULL, 0, 0);
1141
          md_number_to_chars (buffer, FRV_NOP_NOPACK, 4);
1142
        }
1143
 
1144
      vliw_insn_list_entry = frv_insert_vliw_insn (DO_COUNT);
1145
      vliw_insn_list_entry->insn   = insn.insn;
1146
      if (frv_is_branch_insn (insn.insn))
1147
        vliw_insn_list_entry->type = VLIW_BRANCH_TYPE;
1148
 
1149
      if ( !FRV_IS_NOP (insn)
1150
          && (frv_is_branch_insn (insn.insn) || insn.fields.f_pack))
1151
        {
1152
          vliw_insn_list_entry->snop_frag = single_nop_frag;
1153
          vliw_insn_list_entry->dnop_frag = double_nop_frag;
1154
        }
1155
    }
1156
 
1157
  /* Make sure that this insn does not violate the VLIW packing constraints.  */
1158
  /* -mno-pack disallows any packing whatsoever.  */
1159
  if (frv_flags & EF_FRV_NOPACK)
1160
    {
1161
      if (! insn.fields.f_pack)
1162
        {
1163
          as_bad (_("VLIW packing used for -mno-pack"));
1164
          return;
1165
        }
1166
    }
1167
  /* -mcpu=FRV is an idealized FR-V implementation that supports all of the
1168
     instructions, don't do vliw checking.  */
1169
  else if (frv_mach != bfd_mach_frv)
1170
    {
1171
      if (!target_implements_insn_p (insn.insn))
1172
        {
1173
          as_bad (_("Instruction not supported by this architecture"));
1174
          return;
1175
        }
1176
      packing_constraint = frv_vliw_add_insn (& vliw, insn.insn);
1177
      if (frv_mach == bfd_mach_fr550 && ! packing_constraint)
1178
        packing_constraint = fr550_check_acc_range (& vliw, & insn);
1179
      if (insn.fields.f_pack)
1180
        frv_vliw_reset (& vliw, frv_mach, frv_flags);
1181
      if (packing_constraint)
1182
        {
1183
          as_bad (_("VLIW packing constraint violation"));
1184
          return;
1185
        }
1186
    }
1187
 
1188
  /* Doesn't really matter what we pass for RELAX_P here.  */
1189
  gas_cgen_finish_insn (insn.insn, insn.buffer,
1190
                        CGEN_FIELDS_BITSIZE (& insn.fields), 1, &finished_insn);
1191
 
1192
 
1193
  /* If the cpu is tomcat, then we need to insert nops to workaround
1194
     hardware limitations.  We need to keep track of each vliw unit
1195
     and examine the length of the unit and the individual insns
1196
     within the unit to determine the number and location of the
1197
     required nops.  */
1198
  if (frv_mach == bfd_mach_frvtomcat)
1199
    {
1200
      if (vliw_insn_list_entry)
1201
        vliw_insn_list_entry->address = finished_insn.addr;
1202
      else
1203
        abort();
1204
 
1205
      if (insn.fields.f_pack)
1206
        {
1207
          /* We've completed a VLIW insn.  */
1208
          previous_vliw_chain = current_vliw_chain;
1209
          current_vliw_chain = NULL;
1210
          current_vliw_insn  = NULL;
1211
        }
1212
    }
1213
}
1214
 
1215
/* The syntax in the manual says constants begin with '#'.
1216
   We just ignore it.  */
1217
 
1218
void
1219
md_operand (expressionS *expressionP)
1220
{
1221
  if (* input_line_pointer == '#')
1222
    {
1223
      input_line_pointer ++;
1224
      expression (expressionP);
1225
    }
1226
}
1227
 
1228
valueT
1229
md_section_align (segT segment, valueT size)
1230
{
1231
  int align = bfd_get_section_alignment (stdoutput, segment);
1232
  return ((size + (1 << align) - 1) & (-1 << align));
1233
}
1234
 
1235
symbolS *
1236
md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
1237
{
1238
  return 0;
1239
}
1240
 
1241
/* Interface to relax_segment.  */
1242
 
1243
/* FIXME: Build table by hand, get it working, then machine generate.  */
1244
const relax_typeS md_relax_table[] =
1245
{
1246
  {1, 1, 0, 0},
1247
  {511 - 2 - 2, -512 - 2 + 2, 0, 2 },
1248
  {0x2000000 - 1 - 2, -0x2000000 - 2, 2, 0 },
1249
  {0x2000000 - 1 - 2, -0x2000000 - 2, 4, 0 }
1250
};
1251
 
1252
long
1253
frv_relax_frag (fragS *fragP ATTRIBUTE_UNUSED, long stretch ATTRIBUTE_UNUSED)
1254
{
1255
  return 0;
1256
}
1257
 
1258
/* Return an initial guess of the length by which a fragment must grow to
1259
   hold a branch to reach its destination.
1260
   Also updates fr_type/fr_subtype as necessary.
1261
 
1262
   Called just before doing relaxation.
1263
   Any symbol that is now undefined will not become defined.
1264
   The guess for fr_var is ACTUALLY the growth beyond fr_fix.
1265
   Whatever we do to grow fr_fix or fr_var contributes to our returned value.
1266
   Although it may not be explicit in the frag, pretend fr_var starts with a
1267
 
1268
 
1269
int
1270
md_estimate_size_before_relax (fragS *fragP, segT segment ATTRIBUTE_UNUSED)
1271
{
1272
  switch (fragP->fr_subtype)
1273
    {
1274
    case NOP_KEEP:
1275
      return fragP->fr_var;
1276
 
1277
    default:
1278
    case NOP_DELETE:
1279
      return 0;
1280
    }
1281
}
1282
 
1283
/* *fragP has been relaxed to its final size, and now needs to have
1284
   the bytes inside it modified to conform to the new size.
1285
 
1286
   Called after relaxation is finished.
1287
   fragP->fr_type == rs_machine_dependent.
1288
   fragP->fr_subtype is the subtype of what the address relaxed to.  */
1289
 
1290
void
1291
md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
1292
                 segT sec ATTRIBUTE_UNUSED,
1293
                 fragS *fragP)
1294
{
1295
  switch (fragP->fr_subtype)
1296
    {
1297
    default:
1298
    case NOP_DELETE:
1299
      return;
1300
 
1301
    case NOP_KEEP:
1302
      fragP->fr_fix = fragP->fr_var;
1303
      fragP->fr_var = 0;
1304
      return;
1305
    }
1306
}
1307
 
1308
/* Functions concerning relocs.  */
1309
 
1310
/* The location from which a PC relative jump should be calculated,
1311
   given a PC relative reloc.  */
1312
 
1313
long
1314
md_pcrel_from_section (fixS *fixP, segT sec)
1315
{
1316
  if (TC_FORCE_RELOCATION (fixP)
1317
      || (fixP->fx_addsy != (symbolS *) NULL
1318
          && S_GET_SEGMENT (fixP->fx_addsy) != sec))
1319
    {
1320
      /* If we can't adjust this relocation, or if it references a
1321
         local symbol in a different section (which
1322
         TC_FORCE_RELOCATION can't check), let the linker figure it
1323
         out.  */
1324
      return 0;
1325
    }
1326
 
1327
  return (fixP->fx_frag->fr_address + fixP->fx_where) & ~1;
1328
}
1329
 
1330
/* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
1331
   Returns BFD_RELOC_NONE if no reloc type can be found.
1332
   *FIXP may be modified if desired.  */
1333
 
1334
bfd_reloc_code_real_type
1335
md_cgen_lookup_reloc (const CGEN_INSN *insn ATTRIBUTE_UNUSED,
1336
                      const CGEN_OPERAND *operand,
1337
                      fixS *fixP)
1338
{
1339
  switch (operand->type)
1340
    {
1341
    case FRV_OPERAND_LABEL16:
1342
      fixP->fx_pcrel = TRUE;
1343
      return BFD_RELOC_FRV_LABEL16;
1344
 
1345
    case FRV_OPERAND_LABEL24:
1346
      fixP->fx_pcrel = TRUE;
1347
 
1348
      if (fixP->fx_cgen.opinfo != 0)
1349
        return fixP->fx_cgen.opinfo;
1350
 
1351
      return BFD_RELOC_FRV_LABEL24;
1352
 
1353
    case FRV_OPERAND_UHI16:
1354
    case FRV_OPERAND_ULO16:
1355
    case FRV_OPERAND_SLO16:
1356
    case FRV_OPERAND_CALLANN:
1357
    case FRV_OPERAND_LDANN:
1358
    case FRV_OPERAND_LDDANN:
1359
      /* The relocation type should be recorded in opinfo */
1360
      if (fixP->fx_cgen.opinfo != 0)
1361
        return fixP->fx_cgen.opinfo;
1362
      break;
1363
 
1364
    case FRV_OPERAND_D12:
1365
    case FRV_OPERAND_S12:
1366
      if (fixP->fx_cgen.opinfo != 0)
1367
        return fixP->fx_cgen.opinfo;
1368
 
1369
      return BFD_RELOC_FRV_GPREL12;
1370
 
1371
    case FRV_OPERAND_U12:
1372
      return BFD_RELOC_FRV_GPRELU12;
1373
 
1374
    default:
1375
      break;
1376
    }
1377
  return BFD_RELOC_NONE;
1378
}
1379
 
1380
 
1381
/* See whether we need to force a relocation into the output file.
1382
   This is used to force out switch and PC relative relocations when
1383
   relaxing.  */
1384
 
1385
int
1386
frv_force_relocation (fixS *fix)
1387
{
1388
  switch (fix->fx_r_type < BFD_RELOC_UNUSED
1389
          ? (int) fix->fx_r_type
1390
          : fix->fx_cgen.opinfo)
1391
    {
1392
    case BFD_RELOC_FRV_GPREL12:
1393
    case BFD_RELOC_FRV_GPRELU12:
1394
    case BFD_RELOC_FRV_GPREL32:
1395
    case BFD_RELOC_FRV_GPRELHI:
1396
    case BFD_RELOC_FRV_GPRELLO:
1397
    case BFD_RELOC_FRV_GOT12:
1398
    case BFD_RELOC_FRV_GOTHI:
1399
    case BFD_RELOC_FRV_GOTLO:
1400
    case BFD_RELOC_FRV_FUNCDESC_VALUE:
1401
    case BFD_RELOC_FRV_FUNCDESC_GOTOFF12:
1402
    case BFD_RELOC_FRV_FUNCDESC_GOTOFFHI:
1403
    case BFD_RELOC_FRV_FUNCDESC_GOTOFFLO:
1404
    case BFD_RELOC_FRV_GOTOFF12:
1405
    case BFD_RELOC_FRV_GOTOFFHI:
1406
    case BFD_RELOC_FRV_GOTOFFLO:
1407
    case BFD_RELOC_FRV_GETTLSOFF:
1408
    case BFD_RELOC_FRV_TLSDESC_VALUE:
1409
    case BFD_RELOC_FRV_GOTTLSDESC12:
1410
    case BFD_RELOC_FRV_GOTTLSDESCHI:
1411
    case BFD_RELOC_FRV_GOTTLSDESCLO:
1412
    case BFD_RELOC_FRV_TLSMOFF12:
1413
    case BFD_RELOC_FRV_TLSMOFFHI:
1414
    case BFD_RELOC_FRV_TLSMOFFLO:
1415
    case BFD_RELOC_FRV_GOTTLSOFF12:
1416
    case BFD_RELOC_FRV_GOTTLSOFFHI:
1417
    case BFD_RELOC_FRV_GOTTLSOFFLO:
1418
    case BFD_RELOC_FRV_TLSOFF:
1419
    case BFD_RELOC_FRV_TLSDESC_RELAX:
1420
    case BFD_RELOC_FRV_GETTLSOFF_RELAX:
1421
    case BFD_RELOC_FRV_TLSOFF_RELAX:
1422
      return 1;
1423
 
1424
    default:
1425
      break;
1426
    }
1427
 
1428
  return generic_force_reloc (fix);
1429
}
1430
 
1431
/* Apply a fixup that could be resolved within the assembler.  */
1432
 
1433
void
1434
md_apply_fix (fixS *fixP, valueT *valP, segT seg)
1435
{
1436
  if (fixP->fx_addsy == 0)
1437
    switch (fixP->fx_cgen.opinfo)
1438
      {
1439
      case BFD_RELOC_FRV_HI16:
1440
        *valP >>= 16;
1441
        /* Fall through.  */
1442
      case BFD_RELOC_FRV_LO16:
1443
        *valP &= 0xffff;
1444
        break;
1445
 
1446
        /* We need relocations for these, even if their symbols reduce
1447
           to constants.  */
1448
      case BFD_RELOC_FRV_GPREL12:
1449
      case BFD_RELOC_FRV_GPRELU12:
1450
      case BFD_RELOC_FRV_GPREL32:
1451
      case BFD_RELOC_FRV_GPRELHI:
1452
      case BFD_RELOC_FRV_GPRELLO:
1453
      case BFD_RELOC_FRV_GOT12:
1454
      case BFD_RELOC_FRV_GOTHI:
1455
      case BFD_RELOC_FRV_GOTLO:
1456
      case BFD_RELOC_FRV_FUNCDESC_VALUE:
1457
      case BFD_RELOC_FRV_FUNCDESC_GOTOFF12:
1458
      case BFD_RELOC_FRV_FUNCDESC_GOTOFFHI:
1459
      case BFD_RELOC_FRV_FUNCDESC_GOTOFFLO:
1460
      case BFD_RELOC_FRV_GOTOFF12:
1461
      case BFD_RELOC_FRV_GOTOFFHI:
1462
      case BFD_RELOC_FRV_GOTOFFLO:
1463
      case BFD_RELOC_FRV_GETTLSOFF:
1464
      case BFD_RELOC_FRV_TLSDESC_VALUE:
1465
      case BFD_RELOC_FRV_GOTTLSDESC12:
1466
      case BFD_RELOC_FRV_GOTTLSDESCHI:
1467
      case BFD_RELOC_FRV_GOTTLSDESCLO:
1468
      case BFD_RELOC_FRV_TLSMOFF12:
1469
      case BFD_RELOC_FRV_TLSMOFFHI:
1470
      case BFD_RELOC_FRV_TLSMOFFLO:
1471
      case BFD_RELOC_FRV_GOTTLSOFF12:
1472
      case BFD_RELOC_FRV_GOTTLSOFFHI:
1473
      case BFD_RELOC_FRV_GOTTLSOFFLO:
1474
      case BFD_RELOC_FRV_TLSOFF:
1475
      case BFD_RELOC_FRV_TLSDESC_RELAX:
1476
      case BFD_RELOC_FRV_GETTLSOFF_RELAX:
1477
      case BFD_RELOC_FRV_TLSOFF_RELAX:
1478
        fixP->fx_addsy = abs_section_sym;
1479
        break;
1480
      }
1481
  else
1482
    switch (fixP->fx_cgen.opinfo)
1483
      {
1484
      case BFD_RELOC_FRV_GETTLSOFF:
1485
      case BFD_RELOC_FRV_TLSDESC_VALUE:
1486
      case BFD_RELOC_FRV_GOTTLSDESC12:
1487
      case BFD_RELOC_FRV_GOTTLSDESCHI:
1488
      case BFD_RELOC_FRV_GOTTLSDESCLO:
1489
      case BFD_RELOC_FRV_TLSMOFF12:
1490
      case BFD_RELOC_FRV_TLSMOFFHI:
1491
      case BFD_RELOC_FRV_TLSMOFFLO:
1492
      case BFD_RELOC_FRV_GOTTLSOFF12:
1493
      case BFD_RELOC_FRV_GOTTLSOFFHI:
1494
      case BFD_RELOC_FRV_GOTTLSOFFLO:
1495
      case BFD_RELOC_FRV_TLSOFF:
1496
      case BFD_RELOC_FRV_TLSDESC_RELAX:
1497
      case BFD_RELOC_FRV_GETTLSOFF_RELAX:
1498
      case BFD_RELOC_FRV_TLSOFF_RELAX:
1499
        /* Mark TLS symbols as such.  */
1500
        if (S_GET_SEGMENT (fixP->fx_addsy) != absolute_section)
1501
          S_SET_THREAD_LOCAL (fixP->fx_addsy);
1502
        break;
1503
      }
1504
 
1505
  gas_cgen_md_apply_fix (fixP, valP, seg);
1506
  return;
1507
}
1508
 
1509
 
1510
/* Write a value out to the object file, using the appropriate endianness.  */
1511
 
1512
void
1513
frv_md_number_to_chars (char *buf, valueT val, int n)
1514
{
1515
  number_to_chars_bigendian (buf, val, n);
1516
}
1517
 
1518
char *
1519
md_atof (int type, char *litP, int *sizeP)
1520
{
1521
  return ieee_md_atof (type, litP, sizeP, TRUE);
1522
}
1523
 
1524
bfd_boolean
1525
frv_fix_adjustable (fixS *fixP)
1526
{
1527
  bfd_reloc_code_real_type reloc_type;
1528
 
1529
  if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
1530
    {
1531
      const CGEN_INSN *insn = NULL;
1532
      int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
1533
      const CGEN_OPERAND *operand = cgen_operand_lookup_by_num(gas_cgen_cpu_desc, opindex);
1534
      reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
1535
    }
1536
  else
1537
    reloc_type = fixP->fx_r_type;
1538
 
1539
  /* We need the symbol name for the VTABLE entries */
1540
  if (   reloc_type == BFD_RELOC_VTABLE_INHERIT
1541
      || reloc_type == BFD_RELOC_VTABLE_ENTRY
1542
      || reloc_type == BFD_RELOC_FRV_GPREL12
1543
      || reloc_type == BFD_RELOC_FRV_GPRELU12)
1544
    return 0;
1545
 
1546
  return 1;
1547
}
1548
 
1549
/* Allow user to set flags bits.  */
1550
void
1551
frv_set_flags (int arg ATTRIBUTE_UNUSED)
1552
{
1553
  flagword new_flags = get_absolute_expression ();
1554
  flagword new_mask = ~ (flagword)0;
1555
 
1556
  frv_user_set_flags_p = 1;
1557
  if (*input_line_pointer == ',')
1558
    {
1559
      ++input_line_pointer;
1560
      new_mask = get_absolute_expression ();
1561
    }
1562
 
1563
  frv_flags = (frv_flags & ~new_mask) | (new_flags & new_mask);
1564
  bfd_set_private_flags (stdoutput, frv_flags);
1565
}
1566
 
1567
/* Frv specific function to handle 4 byte initializations for pointers that are
1568
   considered 'safe' for use with pic support.  Until frv_frob_file{,_section}
1569
   is run, we encode it a BFD_RELOC_CTOR, and it is turned back into a normal
1570
   BFD_RELOC_32 at that time.  */
1571
 
1572
void
1573
frv_pic_ptr (int nbytes)
1574
{
1575
  expressionS exp;
1576
  char *p;
1577
 
1578
  if (nbytes != 4)
1579
    abort ();
1580
 
1581
#ifdef md_flush_pending_output
1582
  md_flush_pending_output ();
1583
#endif
1584
 
1585
  if (is_it_end_of_statement ())
1586
    {
1587
      demand_empty_rest_of_line ();
1588
      return;
1589
    }
1590
 
1591
#ifdef md_cons_align
1592
  md_cons_align (nbytes);
1593
#endif
1594
 
1595
  do
1596
    {
1597
      bfd_reloc_code_real_type reloc_type = BFD_RELOC_CTOR;
1598
 
1599
      if (strncasecmp (input_line_pointer, "funcdesc(", 9) == 0)
1600
        {
1601
          input_line_pointer += 9;
1602
          expression (&exp);
1603
          if (*input_line_pointer == ')')
1604
            input_line_pointer++;
1605
          else
1606
            as_bad (_("missing ')'"));
1607
          reloc_type = BFD_RELOC_FRV_FUNCDESC;
1608
        }
1609
      else if (strncasecmp (input_line_pointer, "tlsmoff(", 8) == 0)
1610
        {
1611
          input_line_pointer += 8;
1612
          expression (&exp);
1613
          if (*input_line_pointer == ')')
1614
            input_line_pointer++;
1615
          else
1616
            as_bad (_("missing ')'"));
1617
          reloc_type = BFD_RELOC_FRV_TLSMOFF;
1618
        }
1619
      else
1620
        expression (&exp);
1621
 
1622
      p = frag_more (4);
1623
      memset (p, 0, 4);
1624
      fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &exp, 0,
1625
                   reloc_type);
1626
    }
1627
  while (*input_line_pointer++ == ',');
1628
 
1629
  input_line_pointer--;                 /* Put terminator back into stream. */
1630
  demand_empty_rest_of_line ();
1631
}
1632
 
1633
 
1634
 
1635
#ifdef DEBUG
1636
#define DPRINTF1(A)     fprintf (stderr, A)
1637
#define DPRINTF2(A,B)   fprintf (stderr, A, B)
1638
#define DPRINTF3(A,B,C) fprintf (stderr, A, B, C)
1639
 
1640
#else
1641
#define DPRINTF1(A)
1642
#define DPRINTF2(A,B)
1643
#define DPRINTF3(A,B,C)
1644
#endif
1645
 
1646
/* Go through a the sections looking for relocations that are problematical for
1647
   pic.  If not pic, just note that this object can't be linked with pic.  If
1648
   it is pic, see if it needs to be marked so that it will be fixed up, or if
1649
   not possible, issue an error.  */
1650
 
1651
static void
1652
frv_frob_file_section (bfd *abfd, asection *sec, void *ptr ATTRIBUTE_UNUSED)
1653
{
1654
  segment_info_type *seginfo = seg_info (sec);
1655
  fixS *fixp;
1656
  CGEN_CPU_DESC cd = gas_cgen_cpu_desc;
1657
  flagword flags = bfd_get_section_flags (abfd, sec);
1658
 
1659
  /* Skip relocations in known sections (.ctors, .dtors, and .gcc_except_table)
1660
     since we can fix those up by hand.  */
1661
  int known_section_p = (sec->name
1662
                         && sec->name[0] == '.'
1663
                         && ((sec->name[1] == 'c'
1664
                              && strcmp (sec->name, ".ctor") == 0)
1665
                             || (sec->name[1] == 'd'
1666
                                 && strcmp (sec->name, ".dtor") == 0)
1667
                             || (sec->name[1] == 'g'
1668
                                 && strcmp (sec->name, ".gcc_except_table") == 0)));
1669
 
1670
  DPRINTF3 ("\nFrv section %s%s\n", sec->name, (known_section_p) ? ", known section" : "");
1671
  if ((flags & SEC_ALLOC) == 0)
1672
    {
1673
      DPRINTF1 ("\tSkipping non-loaded section\n");
1674
      return;
1675
    }
1676
 
1677
  for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next)
1678
    {
1679
      symbolS *s = fixp->fx_addsy;
1680
      bfd_reloc_code_real_type reloc;
1681
      int non_pic_p;
1682
      int opindex;
1683
      const CGEN_OPERAND *operand;
1684
      const CGEN_INSN *insn = fixp->fx_cgen.insn;
1685
 
1686
      if (fixp->fx_done)
1687
        {
1688
          DPRINTF1 ("\tSkipping reloc that has already been done\n");
1689
          continue;
1690
        }
1691
 
1692
      if (fixp->fx_pcrel)
1693
        {
1694
          DPRINTF1 ("\tSkipping reloc that is PC relative\n");
1695
          continue;
1696
        }
1697
 
1698
      if (! s)
1699
        {
1700
          DPRINTF1 ("\tSkipping reloc without symbol\n");
1701
          continue;
1702
        }
1703
 
1704
      if (fixp->fx_r_type < BFD_RELOC_UNUSED)
1705
        {
1706
          opindex = -1;
1707
          reloc = fixp->fx_r_type;
1708
        }
1709
      else
1710
        {
1711
          opindex = (int) fixp->fx_r_type - (int) BFD_RELOC_UNUSED;
1712
          operand = cgen_operand_lookup_by_num (cd, opindex);
1713
          reloc = md_cgen_lookup_reloc (insn, operand, fixp);
1714
        }
1715
 
1716
      DPRINTF3 ("\treloc %s\t%s", bfd_get_reloc_code_name (reloc), S_GET_NAME (s));
1717
 
1718
      non_pic_p = 0;
1719
      switch (reloc)
1720
        {
1721
        default:
1722
          break;
1723
 
1724
        case BFD_RELOC_32:
1725
          /* Skip relocations in known sections (.ctors, .dtors, and
1726
             .gcc_except_table) since we can fix those up by hand.  Also
1727
             skip forward references to constants.  Also skip a difference
1728
             of two symbols, which still uses the BFD_RELOC_32 at this
1729
             point.  */
1730
          if (! known_section_p
1731
              && S_GET_SEGMENT (s) != absolute_section
1732
              && !fixp->fx_subsy
1733
              && (flags & (SEC_READONLY | SEC_CODE)) == 0)
1734
            {
1735
              non_pic_p = 1;
1736
            }
1737
          break;
1738
 
1739
          /* FIXME -- should determine if any of the GP relocation really uses
1740
             gr16 (which is not pic safe) or not.  Right now, assume if we
1741
             aren't being compiled with -mpic, the usage is non pic safe, but
1742
             is safe with -mpic.  */
1743
        case BFD_RELOC_FRV_GPREL12:
1744
        case BFD_RELOC_FRV_GPRELU12:
1745
        case BFD_RELOC_FRV_GPREL32:
1746
        case BFD_RELOC_FRV_GPRELHI:
1747
        case BFD_RELOC_FRV_GPRELLO:
1748
          non_pic_p = ! frv_pic_p;
1749
          break;
1750
 
1751
        case BFD_RELOC_FRV_LO16:
1752
        case BFD_RELOC_FRV_HI16:
1753
          if (S_GET_SEGMENT (s) != absolute_section)
1754
            non_pic_p = 1;
1755
          break;
1756
 
1757
        case BFD_RELOC_VTABLE_INHERIT:
1758
        case BFD_RELOC_VTABLE_ENTRY:
1759
          non_pic_p = 1;
1760
          break;
1761
 
1762
          /* If this is a blessed BFD_RELOC_32, convert it back to the normal
1763
             relocation.  */
1764
        case BFD_RELOC_CTOR:
1765
          fixp->fx_r_type = BFD_RELOC_32;
1766
          break;
1767
        }
1768
 
1769
      if (non_pic_p)
1770
        {
1771
          DPRINTF1 (" (Non-pic relocation)\n");
1772
          if (frv_pic_p)
1773
            as_warn_where (fixp->fx_file, fixp->fx_line,
1774
                           _("Relocation %s is not safe for %s"),
1775
                           bfd_get_reloc_code_name (reloc), frv_pic_flag);
1776
 
1777
          else if ((frv_flags & EF_FRV_NON_PIC_RELOCS) == 0)
1778
            {
1779
              frv_flags |= EF_FRV_NON_PIC_RELOCS;
1780
              bfd_set_private_flags (abfd, frv_flags);
1781
            }
1782
        }
1783
#ifdef DEBUG
1784
      else
1785
        DPRINTF1 ("\n");
1786
#endif
1787
    }
1788
}
1789
 
1790
/* After all of the symbols have been adjusted, go over the file looking
1791
   for any relocations that pic won't support.  */
1792
 
1793
void
1794
frv_frob_file (void)
1795
{
1796
  bfd_map_over_sections (stdoutput, frv_frob_file_section, (void *) 0);
1797
}
1798
 
1799
void
1800
frv_frob_label (symbolS *this_label)
1801
{
1802
  struct vliw_insn_list *vliw_insn_list_entry;
1803
 
1804
  if (frv_mach != bfd_mach_frvtomcat)
1805
    return;
1806
 
1807
  if (now_seg != text_section)
1808
    return;
1809
 
1810
  vliw_insn_list_entry = frv_insert_vliw_insn(DONT_COUNT);
1811
  vliw_insn_list_entry->type = VLIW_LABEL_TYPE;
1812
  vliw_insn_list_entry->sym  = this_label;
1813
}
1814
 
1815
fixS *
1816
frv_cgen_record_fixup_exp (fragS *frag,
1817
                           int where,
1818
                           const CGEN_INSN *insn,
1819
                           int length,
1820
                           const CGEN_OPERAND *operand,
1821
                           int opinfo,
1822
                           expressionS *exp)
1823
{
1824
  fixS * fixP = gas_cgen_record_fixup_exp (frag, where, insn, length,
1825
                                           operand, opinfo, exp);
1826
 
1827
  if (frv_mach == bfd_mach_frvtomcat
1828
      && current_vliw_insn
1829
      && current_vliw_insn->type == VLIW_BRANCH_TYPE
1830
      && exp != NULL)
1831
    current_vliw_insn->sym = exp->X_add_symbol;
1832
 
1833
  return fixP;
1834
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.