~ubuntu-branches/ubuntu/utopic/binutils-arm64-cross/utopic

« back to all changes in this revision

Viewing changes to binutils-2.23.52.20130611/gas/config/tc-frv.c

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2013-06-20 17:38:09 UTC
  • Revision ID: package-import@ubuntu.com-20130620173809-app8lzgvymy5fg6c
Tags: 0.7
Build-depend on binutils-source (>= 2.23.52.20130620-1~).

Show diffs side-by-side

added added

removed removed

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