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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [binutils-2.20.1/] [gas/] [config/] [tc-frv.c] - Blame information for rev 205

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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