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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [gas/] [config/] [tc-frv.c] - Blame information for rev 816

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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