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

Subversion Repositories openrisc

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

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 38 julius
/* tc-mep.c -- Assembler for the Toshiba Media Processor.
2
   Copyright (C) 2001, 2002, 2003, 2004, 2005, 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 <stdio.h>
23
#include "as.h"
24
#include "dwarf2dbg.h"
25
#include "subsegs.h"
26
#include "symcat.h"
27
#include "opcodes/mep-desc.h"
28
#include "opcodes/mep-opc.h"
29
#include "cgen.h"
30
#include "elf/common.h"
31
#include "elf/mep.h"
32
#include "libbfd.h"
33
#include "xregex.h"
34
 
35
/* Structure to hold all of the different components describing
36
   an individual instruction.  */
37
typedef struct
38
{
39
  const CGEN_INSN *     insn;
40
  const CGEN_INSN *     orig_insn;
41
  CGEN_FIELDS           fields;
42
#if CGEN_INT_INSN_P
43
  CGEN_INSN_INT         buffer [1];
44
#define INSN_VALUE(buf) (*(buf))
45
#else
46
  unsigned char         buffer [CGEN_MAX_INSN_SIZE];
47
#define INSN_VALUE(buf) (buf)
48
#endif
49
  char *                addr;
50
  fragS *               frag;
51
  int                   num_fixups;
52
  fixS *                fixups [GAS_CGEN_MAX_FIXUPS];
53
  int                   indices [MAX_OPERAND_INSTANCES];
54
} mep_insn;
55
 
56
static int mode = CORE; /* Start in core mode. */
57
static int pluspresent = 0;
58
static int allow_disabled_registers = 0;
59
static int library_flag = 0;
60
 
61
/* We're going to need to store all of the instructions along with
62
   their fixups so that we can parallelization grouping rules. */
63
 
64
static mep_insn saved_insns[MAX_SAVED_FIXUP_CHAINS];
65
static int num_insns_saved = 0;
66
 
67
const char comment_chars[]        = "#";
68
const char line_comment_chars[]   = ";#";
69
const char line_separator_chars[] = ";";
70
const char EXP_CHARS[]            = "eE";
71
const char FLT_CHARS[]            = "dD";
72
 
73
static void mep_switch_to_vliw_mode (int);
74
static void mep_switch_to_core_mode (int);
75
static void mep_s_vtext (int);
76
static void mep_noregerr (int);
77
 
78
/* The target specific pseudo-ops which we support.  */
79
const pseudo_typeS md_pseudo_table[] =
80
{
81
  { "word",     cons,                           4 },
82
  { "file",     (void (*) (int)) dwarf2_directive_file,         0 },
83
  { "loc",      dwarf2_directive_loc,           0 },
84
  { "vliw",     mep_switch_to_vliw_mode,        0 },
85
  { "core",     mep_switch_to_core_mode,        0 },
86
  { "vtext",    mep_s_vtext,                    0 },
87
  { "noregerr", mep_noregerr,                   0 },
88
  { NULL,       NULL,                           0 }
89
};
90
 
91
/* Relocations against symbols are done in two
92
   parts, with a HI relocation and a LO relocation.  Each relocation
93
   has only 16 bits of space to store an addend.  This means that in
94
   order for the linker to handle carries correctly, it must be able
95
   to locate both the HI and the LO relocation.  This means that the
96
   relocations must appear in order in the relocation table.
97
 
98
   In order to implement this, we keep track of each unmatched HI
99
   relocation.  We then sort them so that they immediately precede the
100
   corresponding LO relocation. */
101
 
102
struct mep_hi_fixup
103
{
104
  struct mep_hi_fixup * next;   /* Next HI fixup.  */
105
  fixS * fixp;                  /* This fixup.  */
106
  segT seg;                     /* The section this fixup is in.  */
107
};
108
 
109
/* The list of unmatched HI relocs.  */
110
static struct mep_hi_fixup * mep_hi_fixup_list;
111
 
112
 
113
#define OPTION_EB               (OPTION_MD_BASE + 0)
114
#define OPTION_EL               (OPTION_MD_BASE + 1)
115
#define OPTION_CONFIG           (OPTION_MD_BASE + 2)
116
#define OPTION_AVERAGE          (OPTION_MD_BASE + 3)
117
#define OPTION_NOAVERAGE        (OPTION_MD_BASE + 4)
118
#define OPTION_MULT             (OPTION_MD_BASE + 5)
119
#define OPTION_NOMULT           (OPTION_MD_BASE + 6)
120
#define OPTION_DIV              (OPTION_MD_BASE + 7)
121
#define OPTION_NODIV            (OPTION_MD_BASE + 8)
122
#define OPTION_BITOPS           (OPTION_MD_BASE + 9)
123
#define OPTION_NOBITOPS         (OPTION_MD_BASE + 10)
124
#define OPTION_LEADZ            (OPTION_MD_BASE + 11)
125
#define OPTION_NOLEADZ          (OPTION_MD_BASE + 12)
126
#define OPTION_ABSDIFF          (OPTION_MD_BASE + 13)
127
#define OPTION_NOABSDIFF        (OPTION_MD_BASE + 14)
128
#define OPTION_MINMAX           (OPTION_MD_BASE + 15)
129
#define OPTION_NOMINMAX         (OPTION_MD_BASE + 16)
130
#define OPTION_CLIP             (OPTION_MD_BASE + 17)
131
#define OPTION_NOCLIP           (OPTION_MD_BASE + 18)
132
#define OPTION_SATUR            (OPTION_MD_BASE + 19)
133
#define OPTION_NOSATUR          (OPTION_MD_BASE + 20)
134
#define OPTION_COP32            (OPTION_MD_BASE + 21)
135
#define OPTION_REPEAT           (OPTION_MD_BASE + 25)
136
#define OPTION_NOREPEAT         (OPTION_MD_BASE + 26)
137
#define OPTION_DEBUG            (OPTION_MD_BASE + 27)
138
#define OPTION_NODEBUG          (OPTION_MD_BASE + 28)
139
#define OPTION_LIBRARY          (OPTION_MD_BASE + 29)
140
 
141
struct option md_longopts[] = {
142
  { "EB",          no_argument, NULL, OPTION_EB},
143
  { "EL",          no_argument, NULL, OPTION_EL},
144
  { "mconfig",     required_argument, NULL, OPTION_CONFIG},
145
  { "maverage",    no_argument, NULL, OPTION_AVERAGE},
146
  { "mno-average", no_argument, NULL, OPTION_NOAVERAGE},
147
  { "mmult",       no_argument, NULL, OPTION_MULT},
148
  { "mno-mult",    no_argument, NULL, OPTION_NOMULT},
149
  { "mdiv",        no_argument, NULL, OPTION_DIV},
150
  { "mno-div",     no_argument, NULL, OPTION_NODIV},
151
  { "mbitops",     no_argument, NULL, OPTION_BITOPS},
152
  { "mno-bitops",  no_argument, NULL, OPTION_NOBITOPS},
153
  { "mleadz",      no_argument, NULL, OPTION_LEADZ},
154
  { "mno-leadz",   no_argument, NULL, OPTION_NOLEADZ},
155
  { "mabsdiff",    no_argument, NULL, OPTION_ABSDIFF},
156
  { "mno-absdiff", no_argument, NULL, OPTION_NOABSDIFF},
157
  { "mminmax",     no_argument, NULL, OPTION_MINMAX},
158
  { "mno-minmax",  no_argument, NULL, OPTION_NOMINMAX},
159
  { "mclip",       no_argument, NULL, OPTION_CLIP},
160
  { "mno-clip",    no_argument, NULL, OPTION_NOCLIP},
161
  { "msatur",      no_argument, NULL, OPTION_SATUR},
162
  { "mno-satur",   no_argument, NULL, OPTION_NOSATUR},
163
  { "mcop32",      no_argument, NULL, OPTION_COP32},
164
  { "mdebug",      no_argument, NULL, OPTION_DEBUG},
165
  { "mno-debug",   no_argument, NULL, OPTION_NODEBUG},
166
  { "mlibrary",    no_argument, NULL, OPTION_LIBRARY},
167
  { NULL, 0, NULL, 0 } };
168
size_t md_longopts_size = sizeof (md_longopts);
169
 
170
const char * md_shortopts = "";
171
static int optbits = 0;
172
static int optbitset = 0;
173
 
174
int
175
md_parse_option (int c, char *arg ATTRIBUTE_UNUSED)
176
{
177
  int i, idx;
178
  switch (c)
179
    {
180
    case OPTION_EB:
181
      target_big_endian = 1;
182
      break;
183
    case OPTION_EL:
184
      target_big_endian = 0;
185
      break;
186
    case OPTION_CONFIG:
187
      idx = 0;
188
      for (i=1; mep_config_map[i].name; i++)
189
        if (strcmp (mep_config_map[i].name, arg) == 0)
190
          {
191
            idx = i;
192
            break;
193
          }
194
      if (!idx)
195
        {
196
          fprintf (stderr, "Error: unknown configuration %s\n", arg);
197
          return 0;
198
        }
199
      mep_config_index = idx;
200
      target_big_endian = mep_config_map[idx].big_endian;
201
      break;
202
    case OPTION_AVERAGE:
203
      optbits |= 1 << CGEN_INSN_OPTIONAL_AVE_INSN;
204
      optbitset |= 1 << CGEN_INSN_OPTIONAL_AVE_INSN;
205
      break;
206
    case OPTION_NOAVERAGE:
207
      optbits &= ~(1 << CGEN_INSN_OPTIONAL_AVE_INSN);
208
      optbitset |= 1 << CGEN_INSN_OPTIONAL_AVE_INSN;
209
      break;
210
    case OPTION_MULT:
211
      optbits |= 1 << CGEN_INSN_OPTIONAL_MUL_INSN;
212
      optbitset |= 1 << CGEN_INSN_OPTIONAL_MUL_INSN;
213
      break;
214
    case OPTION_NOMULT:
215
      optbits &= ~(1 << CGEN_INSN_OPTIONAL_MUL_INSN);
216
      optbitset |= 1 << CGEN_INSN_OPTIONAL_MUL_INSN;
217
      break;
218
    case OPTION_DIV:
219
      optbits |= 1 << CGEN_INSN_OPTIONAL_DIV_INSN;
220
      optbitset |= 1 << CGEN_INSN_OPTIONAL_DIV_INSN;
221
      break;
222
    case OPTION_NODIV:
223
      optbits &= ~(1 << CGEN_INSN_OPTIONAL_DIV_INSN);
224
      optbitset |= 1 << CGEN_INSN_OPTIONAL_DIV_INSN;
225
      break;
226
    case OPTION_BITOPS:
227
      optbits |= 1 << CGEN_INSN_OPTIONAL_BIT_INSN;
228
      optbitset |= 1 << CGEN_INSN_OPTIONAL_BIT_INSN;
229
      break;
230
    case OPTION_NOBITOPS:
231
      optbits &= ~(1 << CGEN_INSN_OPTIONAL_BIT_INSN);
232
      optbitset |= 1 << CGEN_INSN_OPTIONAL_BIT_INSN;
233
      break;
234
    case OPTION_LEADZ:
235
      optbits |= 1 << CGEN_INSN_OPTIONAL_LDZ_INSN;
236
      optbitset |= 1 << CGEN_INSN_OPTIONAL_LDZ_INSN;
237
      break;
238
    case OPTION_NOLEADZ:
239
      optbits &= ~(1 << CGEN_INSN_OPTIONAL_LDZ_INSN);
240
      optbitset |= 1 << CGEN_INSN_OPTIONAL_LDZ_INSN;
241
      break;
242
    case OPTION_ABSDIFF:
243
      optbits |= 1 << CGEN_INSN_OPTIONAL_ABS_INSN;
244
      optbitset |= 1 << CGEN_INSN_OPTIONAL_ABS_INSN;
245
      break;
246
    case OPTION_NOABSDIFF:
247
      optbits &= ~(1 << CGEN_INSN_OPTIONAL_ABS_INSN);
248
      optbitset |= 1 << CGEN_INSN_OPTIONAL_ABS_INSN;
249
      break;
250
    case OPTION_MINMAX:
251
      optbits |= 1 << CGEN_INSN_OPTIONAL_MINMAX_INSN;
252
      optbitset |= 1 << CGEN_INSN_OPTIONAL_MINMAX_INSN;
253
      break;
254
    case OPTION_NOMINMAX:
255
      optbits &= ~(1 << CGEN_INSN_OPTIONAL_MINMAX_INSN);
256
      optbitset |= 1 << CGEN_INSN_OPTIONAL_MINMAX_INSN;
257
      break;
258
    case OPTION_CLIP:
259
      optbits |= 1 << CGEN_INSN_OPTIONAL_CLIP_INSN;
260
      optbitset |= 1 << CGEN_INSN_OPTIONAL_CLIP_INSN;
261
      break;
262
    case OPTION_NOCLIP:
263
      optbits &= ~(1 << CGEN_INSN_OPTIONAL_CLIP_INSN);
264
      optbitset |= 1 << CGEN_INSN_OPTIONAL_CLIP_INSN;
265
      break;
266
    case OPTION_SATUR:
267
      optbits |= 1 << CGEN_INSN_OPTIONAL_SAT_INSN;
268
      optbitset |= 1 << CGEN_INSN_OPTIONAL_SAT_INSN;
269
      break;
270
    case OPTION_NOSATUR:
271
      optbits &= ~(1 << CGEN_INSN_OPTIONAL_SAT_INSN);
272
      optbitset |= 1 << CGEN_INSN_OPTIONAL_SAT_INSN;
273
      break;
274
    case OPTION_COP32:
275
      optbits |= 1 << CGEN_INSN_OPTIONAL_CP_INSN;
276
      optbitset |= 1 << CGEN_INSN_OPTIONAL_CP_INSN;
277
      break;
278
    case OPTION_DEBUG:
279
      optbits |= 1 << CGEN_INSN_OPTIONAL_DEBUG_INSN;
280
      optbitset |= 1 << CGEN_INSN_OPTIONAL_DEBUG_INSN;
281
      break;
282
    case OPTION_NODEBUG:
283
      optbits &= ~(1 << CGEN_INSN_OPTIONAL_DEBUG_INSN);
284
      optbitset |= 1 << CGEN_INSN_OPTIONAL_DEBUG_INSN;
285
      break;
286
    case OPTION_LIBRARY:
287
      library_flag = EF_MEP_LIBRARY;
288
      break;
289
    case OPTION_REPEAT:
290
    case OPTION_NOREPEAT:
291
      break;
292
    default:
293
      return 0;
294
    }
295
  return 1;
296
}
297
 
298
void
299
md_show_usage (FILE *stream)
300
{
301
  fprintf (stream, _("MeP specific command line options:\n\
302
  -EB                     assemble for a big endian system (default)\n\
303
  -EL                     assemble for a little endian system\n\
304
  -mconfig=<name>         specify a chip configuration to use\n\
305
  -maverage -mno-average -mmult -mno-mult -mdiv -mno-div\n\
306
  -mbitops -mno-bitops -mleadz -mno-leadz -mabsdiff -mno-absdiff\n\
307
  -mminmax -mno-minmax -mclip -mno-clip -msatur -mno-satur -mcop32\n\
308
                          enable/disable the given opcodes\n\
309
\n\
310
  If -mconfig is given, the other -m options modify it.  Otherwise,\n\
311
  if no -m options are given, all core opcodes are enabled;\n\
312
  if any enabling -m options are given, only those are enabled;\n\
313
  if only disabling -m options are given, only those are disabled.\n\
314
"));
315
  if (mep_config_map[1].name)
316
    {
317
      int i;
318
      fprintf (stream, "  -mconfig=STR            specify the configuration to use\n");
319
      fprintf (stream, "  Configurations:");
320
      for (i=0; mep_config_map[i].name; i++)
321
        fprintf (stream, " %s", mep_config_map[i].name);
322
      fprintf (stream, "\n");
323
    }
324
}
325
 
326
 
327
 
328
static void
329
mep_check_for_disabled_registers (mep_insn *insn)
330
{
331
  static int initted = 0;
332
  static int has_mul_div = 0;
333
  static int has_cop = 0;
334
  static int has_debug = 0;
335
  unsigned int b, r;
336
 
337
  if (allow_disabled_registers)
338
    return;
339
 
340
#if !CGEN_INT_INSN_P
341
  if (target_big_endian)
342
    b = insn->buffer[0] * 256 + insn->buffer[1];
343
  else
344
    b = insn->buffer[1] * 256 + insn->buffer[0];
345
#else
346
  b = insn->buffer[0];
347
#endif
348
 
349
  if ((b & 0xfffff00e) == 0x7008 /* stc */
350
      || (b & 0xfffff00e) == 0x700a /* ldc */)
351
    {
352
      if (!initted)
353
        {
354
          initted = 1;
355
          if ((MEP_OMASK & (1 << CGEN_INSN_OPTIONAL_MUL_INSN))
356
              || (MEP_OMASK & (1 << CGEN_INSN_OPTIONAL_DIV_INSN)))
357
            has_mul_div = 1;
358
          if (MEP_OMASK & (1 << CGEN_INSN_OPTIONAL_DEBUG_INSN))
359
            has_debug = 1;
360
          if (MEP_OMASK & (1 << CGEN_INSN_OPTIONAL_CP_INSN))
361
            has_cop = 1;
362
        }
363
 
364
      r = ((b & 0x00f0) >> 4) | ((b & 0x0001) << 4);
365
      switch (r)
366
        {
367
        case 7: /* $hi */
368
        case 8: /* $lo */
369
          if (!has_mul_div)
370
            as_bad ("$hi and $lo are disabled when MUL and DIV are off");
371
          break;
372
        case 12: /* $mb0 */
373
        case 13: /* $me0 */
374
        case 14: /* $mb1 */
375
        case 15: /* $me1 */
376
          if (!has_cop)
377
            as_bad ("$mb0, $me0, $mb1, and $me1 are disabled when COP is off");
378
          break;
379
        case 24: /* $dbg */
380
        case 25: /* $depc */
381
          if (!has_debug)
382
            as_bad ("$dbg and $depc are disabled when DEBUG is off");
383
          break;
384
        }
385
    }
386
}
387
 
388
static int
389
mep_machine (void)
390
{
391
  switch (MEP_CPU)
392
    {
393
    default: break;
394
    case EF_MEP_CPU_C2: return bfd_mach_mep;
395
    case EF_MEP_CPU_C3: return bfd_mach_mep;
396
    case EF_MEP_CPU_C4: return bfd_mach_mep;
397
    case EF_MEP_CPU_H1: return bfd_mach_mep_h1;
398
    }
399
 
400
  return bfd_mach_mep;
401
}
402
 
403
/* The MeP version of the cgen parse_operand function.  The only difference
404
   from the standard version is that we want to avoid treating '$foo' and
405
   '($foo...)' as references to a symbol called '$foo'.  The chances are
406
   that '$foo' is really a misspelt register.  */
407
 
408
static const char *
409
mep_parse_operand (CGEN_CPU_DESC cd, enum cgen_parse_operand_type want,
410
                   const char **strP, int opindex, int opinfo,
411
                   enum cgen_parse_operand_result *resultP, bfd_vma *valueP)
412
{
413
  if (want == CGEN_PARSE_OPERAND_INTEGER || want == CGEN_PARSE_OPERAND_ADDRESS)
414
    {
415
      const char *next;
416
 
417
      next = *strP;
418
      while (*next == '(')
419
        next++;
420
      if (*next == '$')
421
        return "Not a valid literal";
422
    }
423
  return gas_cgen_parse_operand (cd, want, strP, opindex, opinfo,
424
                                 resultP, valueP);
425
}
426
 
427
void
428
md_begin ()
429
{
430
  /* Initialize the `cgen' interface.  */
431
 
432
  /* If the user specifies no options, we default to allowing
433
     everything.  If the user specifies any enabling options, we
434
     default to allowing only what is specified.  If the user
435
     specifies only disabling options, we only disable what is
436
     specified.  If the user specifies options and a config, the
437
     options modify the config.  */
438
  if (optbits && mep_config_index == 0)
439
    MEP_OMASK = optbits;
440
  else
441
    MEP_OMASK = (MEP_OMASK & ~optbitset) | optbits;
442
 
443
  /* Set the machine number and endian.  */
444
  gas_cgen_cpu_desc = mep_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, 0,
445
                                         CGEN_CPU_OPEN_ENDIAN,
446
                                         target_big_endian
447
                                         ? CGEN_ENDIAN_BIG
448
                                         : CGEN_ENDIAN_LITTLE,
449
                                         CGEN_CPU_OPEN_ISAS, 0,
450
                                         CGEN_CPU_OPEN_END);
451
  mep_cgen_init_asm (gas_cgen_cpu_desc);
452
 
453
  /* This is a callback from cgen to gas to parse operands.  */
454
  cgen_set_parse_operand_fn (gas_cgen_cpu_desc, mep_parse_operand);
455
 
456
  /* Identify the architecture.  */
457
  bfd_default_set_arch_mach (stdoutput, bfd_arch_mep, mep_machine ());
458
 
459
  /* Store the configuration number and core.  */
460
  bfd_set_private_flags (stdoutput, MEP_CPU | MEP_CONFIG | library_flag);
461
 
462
  /* Initialize the array we'll be using to store fixups.  */
463
  gas_cgen_initialize_saved_fixups_array();
464
}
465
 
466
/* Variant of mep_cgen_assemble_insn.  Assemble insn STR of cpu CD as a
467
   coprocessor instruction, if possible, into FIELDS, BUF, and INSN.  */
468
 
469
static const CGEN_INSN *
470
mep_cgen_assemble_cop_insn (CGEN_CPU_DESC cd,
471
                            const char *str,
472
                            CGEN_FIELDS *fields,
473
                            CGEN_INSN_BYTES_PTR buf,
474
                            const struct cgen_insn *pinsn)
475
{
476
  const char *start;
477
  CGEN_INSN_LIST *ilist;
478
  const char *errmsg = NULL;
479
 
480
  /* The instructions are stored in hashed lists. */
481
  ilist = CGEN_ASM_LOOKUP_INSN (gas_cgen_cpu_desc,
482
                                CGEN_INSN_MNEMONIC (pinsn));
483
 
484
  start = str;
485
  for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
486
    {
487
      const CGEN_INSN *insn = ilist->insn;
488
      if (strcmp (CGEN_INSN_MNEMONIC (ilist->insn),
489
                  CGEN_INSN_MNEMONIC (pinsn)) == 0
490
          && MEP_INSN_COP_P (ilist->insn)
491
          && mep_cgen_insn_supported (cd, insn))
492
        {
493
          str = start;
494
 
495
          /* skip this insn if str doesn't look right lexically */
496
          if (CGEN_INSN_RX (insn) != NULL &&
497
              regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
498
            continue;
499
 
500
          /* Allow parse/insert handlers to obtain length of insn.  */
501
          CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
502
 
503
          errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
504
          if (errmsg != NULL)
505
            continue;
506
 
507
          errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
508
                                              (bfd_vma) 0);
509
          if (errmsg != NULL)
510
            continue;
511
 
512
          return insn;
513
        }
514
    }
515
  return pinsn;
516
}
517
 
518
static void
519
mep_save_insn (mep_insn insn)
520
{
521
  /* Consider change MAX_SAVED_FIXUP_CHAINS to MAX_PARALLEL_INSNS. */
522
  if (num_insns_saved < 0 || num_insns_saved >= MAX_SAVED_FIXUP_CHAINS)
523
    {
524
      as_fatal("index into saved_insns[] out of bounds.");
525
      return;
526
    }
527
  saved_insns[num_insns_saved] = insn;
528
  gas_cgen_save_fixups(num_insns_saved);
529
  num_insns_saved++;
530
}
531
 
532
static void
533
mep_check_parallel32_scheduling (void)
534
{
535
  int insn0iscopro, insn1iscopro, insn0length, insn1length;
536
 
537
  /* More than two instructions means that either someone is referring to
538
     an internally parallel core or an internally parallel coprocessor,
539
     neither of which are supported at this time.  */
540
  if ( num_insns_saved > 2 )
541
    as_fatal("Internally paralled cores and coprocessors not supported.");
542
 
543
  /* If there are no insns saved, that's ok.  Just return.  This will
544
     happen when mep_process_saved_insns is called when the end of the
545
     source file is reached and there are no insns left to be processed.  */
546
  if (num_insns_saved == 0)
547
    return;
548
 
549
  /* Check some of the attributes of the first insn.  */
550
  insn0iscopro = MEP_INSN_COP_P (saved_insns[0].insn);
551
  insn0length = CGEN_FIELDS_BITSIZE (& saved_insns[0].fields);
552
 
553
  if (num_insns_saved == 2)
554
    {
555
      /* Check some of the attributes of the first insn.  */
556
      insn1iscopro = MEP_INSN_COP_P (saved_insns[1].insn);
557
      insn1length = CGEN_FIELDS_BITSIZE (& saved_insns[1].fields);
558
 
559
      if ((insn0iscopro && !insn1iscopro)
560
          || (insn1iscopro && !insn0iscopro))
561
        {
562
          /* We have one core and one copro insn.  If their sizes
563
             add up to 32, then the combination is valid.  */
564
          if (insn0length + insn1length == 32)
565
            return;
566
          else
567
            as_bad ("core and copro insn lengths must total 32 bits.");
568
        }
569
      else
570
        as_bad ("vliw group must consist of 1 core and 1 copro insn.");
571
    }
572
  else
573
    {
574
      /* If we arrive here, we have one saved instruction.  There are a
575
         number of possible cases:
576
 
577
         1.  The instruction is a 32 bit core or coprocessor insn and
578
             can be executed by itself.  Valid.
579
 
580
         2.  The instrucion is a core instruction for which a cop nop
581
             exists.  In this case, insert the cop nop into the saved
582
             insn array after the core insn and return.  Valid.
583
 
584
         3.  The instruction is a coprocessor insn for which a core nop
585
             exists.  In this case, move the coprocessor insn to the
586
             second element of the array and put the nop in the first
587
             element then return.  Valid.
588
 
589
         4. The instruction is a core or coprocessor instruction for
590
            which there is no matching coprocessor or core nop to use
591
            to form a valid vliw insn combination.  In this case, we
592
            we have to abort.  */
593
 
594
      if (insn0length > 32)
595
        as_fatal ("Cannot use 48- or 64-bit insns with a 32 bit datapath.");
596
 
597
      if (insn0length == 32)
598
        return;
599
 
600
      /* Insn is smaller than datapath.  If there are no matching
601
         nops for this insn, then terminate assembly.  */
602
      if (CGEN_INSN_ATTR_VALUE (saved_insns[0].insn,
603
                                CGEN_INSN_VLIW32_NO_MATCHING_NOP))
604
        as_fatal ("No valid nop.");
605
 
606
      /* At this point we know that we have a single 16-bit insn that has
607
         a matching nop.  We have to assemble it and put it into the saved
608
         insn and fixup chain arrays. */
609
 
610
      if (insn0iscopro)
611
        {
612
          char *errmsg;
613
          mep_insn insn;
614
 
615
          /* Move the insn and it's fixups to the second element of the
616
             saved insns arrary and insert a 16 bit core nope into the
617
             first element. */
618
             insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "nop",
619
                                                 &insn.fields, insn.buffer,
620
                                                 &errmsg);
621
             if (!insn.insn)
622
               {
623
                 as_bad ("%s", errmsg);
624
                 return;
625
               }
626
 
627
             /* Move the insn in element 0 to element 1 and insert the
628
                 nop into element 0.  Move the fixups in element 0 to
629
                 element 1 and save the current fixups to element 0.
630
                 Really there aren't any fixups at this point because we're
631
                 inserting a nop but we might as well be general so that
632
                 if there's ever a need to insert a general insn, we'll
633
                 have an example. */
634
              saved_insns[1] = saved_insns[0];
635
              saved_insns[0] = insn;
636
              num_insns_saved++;
637
              gas_cgen_swap_fixups (0);
638
              gas_cgen_save_fixups (1);
639
        }
640
      else
641
        {
642
          char * errmsg;
643
          mep_insn insn;
644
          int insn_num = saved_insns[0].insn->base->num;
645
 
646
          /* Use 32 bit branches and skip the nop.  */
647
          if (insn_num == MEP_INSN_BSR12
648
              || insn_num == MEP_INSN_BEQZ
649
              || insn_num == MEP_INSN_BNEZ)
650
            return;
651
 
652
          /* Insert a 16-bit coprocessor nop.  Note that at the time */
653
          /* this was done, no 16-bit coprocessor nop was defined.   */
654
          insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "cpnop16",
655
                                              &insn.fields, insn.buffer,
656
                                              &errmsg);
657
          if (!insn.insn)
658
            {
659
              as_bad ("%s", errmsg);
660
              return;
661
            }
662
 
663
          /* Now put the insn and fixups into the arrays.  */
664
          mep_save_insn (insn);
665
        }
666
    }
667
}
668
 
669
static void
670
mep_check_parallel64_scheduling (void)
671
{
672
  int insn0iscopro, insn1iscopro, insn0length, insn1length;
673
 
674
  /* More than two instructions means that someone is referring to an
675
     internally parallel core or an internally parallel coprocessor.  */
676
  /* These are not currently supported.  */
677
  if (num_insns_saved > 2)
678
    as_fatal ("Internally parallel cores of coprocessors not supported.");
679
 
680
  /* If there are no insns saved, that's ok.  Just return.  This will
681
     happen when mep_process_saved_insns is called when the end of the
682
     source file is reached and there are no insns left to be processed.  */
683
  if (num_insns_saved == 0)
684
    return;
685
 
686
  /* Check some of the attributes of the first insn.  */
687
  insn0iscopro = MEP_INSN_COP_P (saved_insns[0].insn);
688
  insn0length = CGEN_FIELDS_BITSIZE (& saved_insns[0].fields);
689
 
690
  if (num_insns_saved == 2)
691
    {
692
      /* Check some of the attributes of the first insn. */
693
      insn1iscopro = MEP_INSN_COP_P (saved_insns[1].insn);
694
      insn1length = CGEN_FIELDS_BITSIZE (& saved_insns[1].fields);
695
 
696
      if ((insn0iscopro && !insn1iscopro)
697
          || (insn1iscopro && !insn0iscopro))
698
        {
699
          /* We have one core and one copro insn.  If their sizes
700
             add up to 64, then the combination is valid.  */
701
          if (insn0length + insn1length == 64)
702
            return;
703
          else
704
            as_bad ("core and copro insn lengths must total 64 bits.");
705
        }
706
      else
707
        as_bad ("vliw group must consist of 1 core and 1 copro insn.");
708
    }
709
  else
710
    {
711
      /* If we arrive here, we have one saved instruction.  There are a
712
         number of possible cases:
713
 
714
         1.  The instruction is a 64 bit coprocessor insn and can be
715
             executed by itself.  Valid.
716
 
717
         2.  The instrucion is a core instruction for which a cop nop
718
             exists.  In this case, insert the cop nop into the saved
719
             insn array after the core insn and return.  Valid.
720
 
721
         3.  The instruction is a coprocessor insn for which a core nop
722
             exists.  In this case, move the coprocessor insn to the
723
             second element of the array and put the nop in the first
724
             element then return.  Valid.
725
 
726
         4.  The instruction is a core or coprocessor instruction for
727
             which there is no matching coprocessor or core nop to use
728
             to form a valid vliw insn combination.  In this case, we
729
             we have to abort.  */
730
 
731
      /* If the insn is 64 bits long, it can run alone.  The size check
732
         is done indepependantly of whether the insn is core or copro
733
         in case 64 bit coprocessor insns are added later.  */
734
      if (insn0length == 64)
735
        return;
736
 
737
      /* Insn is smaller than datapath.  If there are no matching
738
         nops for this insn, then terminate assembly.  */
739
      if (CGEN_INSN_ATTR_VALUE (saved_insns[0].insn,
740
                                CGEN_INSN_VLIW64_NO_MATCHING_NOP))
741
        as_fatal ("No valid nop.");
742
 
743
      if (insn0iscopro)
744
        {
745
          char *errmsg;
746
          mep_insn insn;
747
          int i;
748
 
749
          /* Initialize the insn buffer.  */
750
          for (i = 0; i < 64; i++)
751
             insn.buffer[i] = '\0';
752
 
753
          /* We have a coprocessor insn.  At this point in time there
754
             are is 32-bit core nop.  There is only a 16-bit core
755
             nop.  The idea is to allow for a relatively arbitrary
756
             coprocessor to be specified.  We aren't looking at
757
             trying to cover future changes in the core at this time
758
             since it is assumed that the core will remain fairly
759
             static.  If there ever are 32 or 48 bit core nops added,
760
             they will require entries below.  */
761
 
762
          if (insn0length == 48)
763
            {
764
              /* Move the insn and fixups to the second element of the
765
                 arrays then assemble and insert a 16 bit core nop.  */
766
              insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "nop",
767
                                                  & insn.fields, insn.buffer,
768
                                                  & errmsg);
769
            }
770
          else
771
            {
772
              /* If this is reached, then we have a single coprocessor
773
                 insn that is not 48 bits long, but for which the assembler
774
                 thinks there is a matching core nop.  If a 32-bit core
775
                 nop has been added, then make the necessary changes and
776
                 handle its assembly and insertion here.  Otherwise,
777
                 go figure out why either:
778
 
779
                 1. The assembler thinks that there is a 32-bit core nop
780
                    to match a 32-bit coprocessor insn, or
781
                 2. The assembler thinks that there is a 48-bit core nop
782
                    to match a 16-bit coprocessor insn.  */
783
 
784
              as_fatal ("Assembler expects a non-existent core nop.");
785
            }
786
 
787
         if (!insn.insn)
788
           {
789
             as_bad ("%s", errmsg);
790
             return;
791
           }
792
 
793
         /* Move the insn in element 0 to element 1 and insert the
794
            nop into element 0.  Move the fixups in element 0 to
795
            element 1 and save the current fixups to element 0.
796
            Really there aren't any fixups at this point because we're
797
            inserting a nop but we might as well be general so that
798
            if there's ever a need to insert a general insn, we'll
799
            have an example. */
800
 
801
         saved_insns[1] = saved_insns[0];
802
         saved_insns[0] = insn;
803
         num_insns_saved++;
804
         gas_cgen_swap_fixups(0);
805
         gas_cgen_save_fixups(1);
806
 
807
        }
808
      else
809
        {
810
          char * errmsg;
811
          mep_insn insn;
812
          int i;
813
 
814
          /* Initialize the insn buffer */
815
          for (i = 0; i < 64; i++)
816
             insn.buffer[i] = '\0';
817
 
818
          /* We have a core insn.  We have to handle all possible nop
819
             lengths.  If a coprocessor doesn't have a nop of a certain
820
             length but there exists core insns that when combined with
821
              a nop of that length would fill the datapath, those core
822
              insns will be flagged with the VLIW_NO_CORRESPONDING_NOP
823
              attribute.  That will ensure that when used in a way that
824
              requires a nop to be inserted, assembly will terminate
825
              before reaching this section of code.  This guarantees
826
              that cases below which would result in the attempted
827
              insertion of nop that doesn't exist will never be entered.  */
828
          if (insn0length == 16)
829
            {
830
              /* Insert 48 bit coprocessor nop.          */
831
              /* Assemble it and put it into the arrays. */
832
              insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "cpnop48",
833
                                                  &insn.fields, insn.buffer,
834
                                                  &errmsg);
835
            }
836
          else if (insn0length == 32)
837
            {
838
              /* Insert 32 bit coprocessor nop. */
839
              insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "cpnop32",
840
                                                  &insn.fields, insn.buffer,
841
                                                  &errmsg);
842
            }
843
          else if (insn0length == 48)
844
            {
845
              /* Insert 16 bit coprocessor nop. */
846
              insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "cpnop16",
847
                                                  &insn.fields, insn.buffer,
848
                                                  &errmsg);
849
            }
850
          else
851
            /* Core insn has an invalid length.  Something has gone wrong. */
852
            as_fatal ("Core insn has invalid length!  Something is wrong!");
853
 
854
          if (!insn.insn)
855
            {
856
              as_bad ("%s", errmsg);
857
              return;
858
            }
859
 
860
          /* Now put the insn and fixups into the arrays.  */
861
          mep_save_insn (insn);
862
        }
863
    }
864
}
865
 
866
/* The scheduling functions are just filters for invalid combinations.
867
   If there is a violation, they terminate assembly.  Otherise they
868
   just fall through.  Succesful combinations cause no side effects
869
   other than valid nop insertion.  */
870
 
871
static void
872
mep_check_parallel_scheduling (void)
873
{
874
  /* This is where we will eventually read the config information
875
     and choose which scheduling checking function to call.  */
876
  if (MEP_VLIW64)
877
    mep_check_parallel64_scheduling ();
878
  else
879
    mep_check_parallel32_scheduling ();
880
}
881
 
882
static void
883
mep_process_saved_insns (void)
884
{
885
  int i;
886
 
887
  gas_cgen_save_fixups (MAX_SAVED_FIXUP_CHAINS - 1);
888
 
889
  /* We have to check for valid scheduling here. */
890
  mep_check_parallel_scheduling ();
891
 
892
  /* If the last call didn't cause assembly to terminate, we have
893
     a valid vliw insn/insn pair saved. Restore this instructions'
894
     fixups and process the insns. */
895
  for (i = 0;i<num_insns_saved;i++)
896
    {
897
      gas_cgen_restore_fixups (i);
898
      gas_cgen_finish_insn (saved_insns[i].insn, saved_insns[i].buffer,
899
                            CGEN_FIELDS_BITSIZE (& saved_insns[i].fields),
900
                            1, NULL);
901
    }
902
  gas_cgen_restore_fixups (MAX_SAVED_FIXUP_CHAINS - 1);
903
 
904
  /* Clear the fixups and reset the number insn saved to 0. */
905
  gas_cgen_initialize_saved_fixups_array ();
906
  num_insns_saved = 0;
907
  listing_prev_line ();
908
}
909
 
910
void
911
md_assemble (char * str)
912
{
913
  static CGEN_BITSET* isas = NULL;
914
  char * errmsg;
915
 
916
  /* Initialize GAS's cgen interface for a new instruction.  */
917
  gas_cgen_init_parse ();
918
 
919
  /* There are two possible modes: core and vliw.  We have to assemble
920
     differently for each.
921
 
922
     Core Mode:  We assemble normally.  All instructions are on a
923
                 single line and are made up of one mnemonic and one
924
                 set of operands.
925
     VLIW Mode:  Vliw combinations are indicated as follows:
926
 
927
                       core insn
928
                     + copro insn
929
 
930
                 We want to handle the general case where more than
931
                 one instruction can be preceeded by a +.  This will
932
                 happen later if we add support for internally parallel
933
                 coprocessors.  We'll make the parsing nice and general
934
                 so that it can handle an arbitrary number of insns
935
                 with leading +'s.  The actual checking for valid
936
                 combinations is done elsewhere.  */
937
 
938
  /* Initialize the isa to refer to the core.  */
939
  if (isas == NULL)
940
    isas = cgen_bitset_copy (& MEP_CORE_ISA);
941
  else
942
    {
943
      cgen_bitset_clear (isas);
944
      cgen_bitset_union (isas, & MEP_CORE_ISA, isas);
945
    }
946
  gas_cgen_cpu_desc->isas = isas;
947
 
948
  if (mode == VLIW)
949
    {
950
      /* VLIW mode.  */
951
 
952
      int thisInsnIsCopro = 0;
953
      mep_insn insn;
954
      int i;
955
 
956
      /* Initialize the insn buffer */
957
 
958
      if (! CGEN_INT_INSN_P)
959
         for (i=0; i < CGEN_MAX_INSN_SIZE; i++)
960
            insn.buffer[i]='\0';
961
 
962
      /* Can't tell core / copro insns apart at parse time! */
963
      cgen_bitset_union (isas, & MEP_COP_ISA, isas);
964
 
965
      /* Assemble the insn so we can examine its attributes. */
966
      insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, str,
967
                                          &insn.fields, insn.buffer,
968
                                          &errmsg);
969
      if (!insn.insn)
970
        {
971
          as_bad ("%s", errmsg);
972
          return;
973
        }
974
      mep_check_for_disabled_registers (&insn);
975
 
976
      /* Check to see if it's a coprocessor instruction. */
977
      thisInsnIsCopro = MEP_INSN_COP_P (insn.insn);
978
 
979
      if (!thisInsnIsCopro)
980
        {
981
          insn.insn = mep_cgen_assemble_cop_insn (gas_cgen_cpu_desc, str,
982
                                                  &insn.fields, insn.buffer,
983
                                                  insn.insn);
984
          thisInsnIsCopro = MEP_INSN_COP_P (insn.insn);
985
          mep_check_for_disabled_registers (&insn);
986
        }
987
 
988
      if (pluspresent)
989
        {
990
          /* A plus was present. */
991
          /* Check for a + with a core insn and abort if found. */
992
          if (!thisInsnIsCopro)
993
            {
994
              as_fatal("A core insn cannot be preceeded by a +.\n");
995
              return;
996
            }
997
 
998
          if (num_insns_saved > 0)
999
            {
1000
              /* There are insns in the queue. Add this one. */
1001
              mep_save_insn (insn);
1002
            }
1003
          else
1004
            {
1005
              /* There are no insns in the queue and a plus is present.
1006
                 This is a syntax error.  Let's not tolerate this.
1007
                 We can relax this later if necessary.  */
1008
              as_bad (_("Invalid use of parallelization operator."));
1009
              return;
1010
            }
1011
        }
1012
      else
1013
        {
1014
          /* No plus was present. */
1015
          if (num_insns_saved > 0)
1016
            {
1017
              /* There are insns saved and we came across an insn without a
1018
                 leading +.  That's the signal to process the saved insns
1019
                 before proceeding then treat the current insn as the first
1020
                 in a new vliw group.  */
1021
              mep_process_saved_insns ();
1022
              num_insns_saved = 0;
1023
              /* mep_save_insn (insn); */
1024
            }
1025
          mep_save_insn (insn);
1026
#if 0
1027
          else
1028
            {
1029
 
1030
              /* Core Insn. Add it to the beginning of the queue. */
1031
              mep_save_insn (insn);
1032
              /* gas_cgen_save_fixups(num_insns_saved); */
1033
            }
1034
#endif
1035
        }
1036
 
1037
      pluspresent = 0;
1038
    }
1039
  else
1040
    {
1041
      /* Core mode.  */
1042
 
1043
      /* Only single instructions are assembled in core mode. */
1044
      mep_insn insn;
1045
 
1046
      /* If a leading '+' was present, issue an error.
1047
         That's not allowed in core mode. */
1048
      if (pluspresent)
1049
        {
1050
          as_bad (_("Leading plus sign not allowed in core mode"));
1051
          return;
1052
        }
1053
 
1054
      insn.insn = mep_cgen_assemble_insn
1055
        (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, & errmsg);
1056
 
1057
      if (!insn.insn)
1058
        {
1059
          as_bad ("%s", errmsg);
1060
          return;
1061
        }
1062
      gas_cgen_finish_insn (insn.insn, insn.buffer,
1063
                            CGEN_FIELDS_BITSIZE (& insn.fields), 1, NULL);
1064
      mep_check_for_disabled_registers (&insn);
1065
    }
1066
}
1067
 
1068
valueT
1069
md_section_align (segT segment, valueT size)
1070
{
1071
  int align = bfd_get_section_alignment (stdoutput, segment);
1072
  return ((size + (1 << align) - 1) & (-1 << align));
1073
}
1074
 
1075
 
1076
symbolS *
1077
md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
1078
{
1079
  return 0;
1080
}
1081
 
1082
/* Interface to relax_segment.  */
1083
 
1084
 
1085
const relax_typeS md_relax_table[] =
1086
{
1087
  /* The fields are:
1088
     1) most positive reach of this state,
1089
     2) most negative reach of this state,
1090
     3) how many bytes this mode will have in the variable part of the frag
1091
     4) which index into the table to try if we can't fit into this one.  */
1092
  /* Note that we use "beq" because "jmp" has a peculiarity - it cannot
1093
     jump to addresses with any bits 27..24 set.  So, we use beq as a
1094
     17-bit pc-relative branch to avoid using jmp, just in case.  */
1095
 
1096
  /* 0 */ {     0,      0, 0, 0 }, /* unused */
1097
  /* 1 */ {     0,      0, 0, 0 }, /* marker for "don't know yet" */
1098
 
1099
  /* 2 */ {  2047,  -2048, 0, 3 }, /* bsr12 */
1100
  /* 3 */ {     0,      0, 2, 0 }, /* bsr16 */
1101
 
1102
  /* 4 */ {  2047,  -2048, 0, 5 }, /* bra */
1103
  /* 5 */ { 65535, -65536, 2, 6 }, /* beq $0,$0 */
1104
  /* 6 */ {     0,      0, 2, 0 }, /* jmp24 */
1105
 
1106
  /* 7 */ { 65535, -65536, 0, 8 }, /* beqi */
1107
  /* 8 */ {     0,      0, 4, 0 }, /* bnei/jmp */
1108
 
1109
  /* 9 */  {   127,   -128, 0, 10 }, /* beqz */
1110
  /* 10 */ { 65535, -65536, 2, 11 }, /* beqi */
1111
  /* 11 */ {     0,      0, 4,  0 }, /* bnei/jmp */
1112
 
1113
  /* 12 */ { 65535, -65536, 0, 13 }, /* bnei */
1114
  /* 13 */ {     0,      0, 4,  0 }, /* beqi/jmp */
1115
 
1116
  /* 14 */ {   127,   -128, 0, 15 }, /* bnez */
1117
  /* 15 */ { 65535, -65536, 2, 16 }, /* bnei */
1118
  /* 16 */ {     0,      0, 4,  0 },  /* beqi/jmp */
1119
 
1120
  /* 17 */ { 65535, -65536, 0, 13 }, /* bgei */
1121
  /* 18 */ {     0,      0, 4,  0 },
1122
  /* 19 */ { 65535, -65536, 0, 13 }, /* blti */
1123
  /* 20 */ {     0,      0, 4,  0 },
1124
  /* 19 */ { 65535, -65536, 0, 13 }, /* bcpeq */
1125
  /* 20 */ {     0,      0, 4,  0 },
1126
  /* 19 */ { 65535, -65536, 0, 13 }, /* bcpne */
1127
  /* 20 */ {     0,      0, 4,  0 },
1128
  /* 19 */ { 65535, -65536, 0, 13 }, /* bcpat */
1129
  /* 20 */ {     0,      0, 4,  0 },
1130
  /* 19 */ { 65535, -65536, 0, 13 }, /* bcpaf */
1131
  /* 20 */ {     0,      0, 4,  0 }
1132
};
1133
 
1134
/* Pseudo-values for 64 bit "insns" which are combinations of two 32
1135
   bit insns.  */
1136
typedef enum {
1137
  MEP_PSEUDO64_NONE,
1138
  MEP_PSEUDO64_16BITCC,
1139
  MEP_PSEUDO64_32BITCC,
1140
} MepPseudo64Values;
1141
 
1142
static struct {
1143
  int insn;
1144
  int growth;
1145
  int insn_for_extern;
1146
} subtype_mappings[] = {
1147
  { 0, 0, 0 },
1148
  { 0, 0, 0 },
1149
  { MEP_INSN_BSR12, 0, MEP_INSN_BSR24 },
1150
  { MEP_INSN_BSR24, 2, MEP_INSN_BSR24 },
1151
  { MEP_INSN_BRA,   0, MEP_INSN_BRA   },
1152
  { MEP_INSN_BEQ,   2, MEP_INSN_BEQ   },
1153
  { MEP_INSN_JMP,   2, MEP_INSN_JMP   },
1154
  { MEP_INSN_BEQI,  0, MEP_INSN_BEQI  },
1155
  { -1,             4, MEP_PSEUDO64_32BITCC },
1156
  { MEP_INSN_BEQZ,  0, MEP_INSN_BEQZ  },
1157
  { MEP_INSN_BEQI,  2, MEP_INSN_BEQI  },
1158
  { -1,             4, MEP_PSEUDO64_16BITCC },
1159
  { MEP_INSN_BNEI,  0, MEP_INSN_BNEI  },
1160
  { -1,             4, MEP_PSEUDO64_32BITCC },
1161
  { MEP_INSN_BNEZ,  0, MEP_INSN_BNEZ  },
1162
  { MEP_INSN_BNEI,  2, MEP_INSN_BNEI  },
1163
  { -1,             4, MEP_PSEUDO64_16BITCC },
1164
  { MEP_INSN_BGEI,  0, MEP_INSN_BGEI  },
1165
  { -1,             4, MEP_PSEUDO64_32BITCC },
1166
  { MEP_INSN_BLTI,  0, MEP_INSN_BLTI  },
1167
  { -1,             4, MEP_PSEUDO64_32BITCC },
1168
  { MEP_INSN_BCPEQ, 0, MEP_INSN_BCPEQ  },
1169
  { -1,             4, MEP_PSEUDO64_32BITCC },
1170
  { MEP_INSN_BCPNE, 0, MEP_INSN_BCPNE  },
1171
  { -1,             4, MEP_PSEUDO64_32BITCC },
1172
  { MEP_INSN_BCPAT, 0, MEP_INSN_BCPAT  },
1173
  { -1,             4, MEP_PSEUDO64_32BITCC },
1174
  { MEP_INSN_BCPAF, 0, MEP_INSN_BCPAF  },
1175
  { -1,             4, MEP_PSEUDO64_32BITCC }
1176
};
1177
#define NUM_MAPPINGS (sizeof (subtype_mappings) / sizeof (subtype_mappings[0]))
1178
 
1179
void
1180
mep_prepare_relax_scan (fragS *fragP, offsetT *aim, relax_substateT this_state)
1181
{
1182
  symbolS *symbolP = fragP->fr_symbol;
1183
  if (symbolP && !S_IS_DEFINED (symbolP))
1184
    *aim = 0;
1185
  /* Adjust for MeP pcrel not being relative to the next opcode.  */
1186
  *aim += 2 + md_relax_table[this_state].rlx_length;
1187
}
1188
 
1189
static int
1190
insn_to_subtype (int insn)
1191
{
1192
  unsigned int i;
1193
  for (i=0; i<NUM_MAPPINGS; i++)
1194
    if (insn == subtype_mappings[i].insn)
1195
      return i;
1196
  abort ();
1197
}
1198
 
1199
/* Return an initial guess of the length by which a fragment must grow
1200
   to hold a branch to reach its destination.  Also updates fr_type
1201
   and fr_subtype as necessary.
1202
 
1203
   Called just before doing relaxation.  Any symbol that is now
1204
   undefined will not become defined.  The guess for fr_var is
1205
   ACTUALLY the growth beyond fr_fix.  Whatever we do to grow fr_fix
1206
   or fr_var contributes to our returned value.  Although it may not
1207
   be explicit in the frag, pretend fr_var starts with a 0 value.  */
1208
 
1209
int
1210
md_estimate_size_before_relax (fragS * fragP, segT segment)
1211
{
1212
  if (fragP->fr_subtype == 1)
1213
    fragP->fr_subtype = insn_to_subtype (fragP->fr_cgen.insn->base->num);
1214
 
1215
  if (S_GET_SEGMENT (fragP->fr_symbol) != segment)
1216
    {
1217
      int new_insn;
1218
 
1219
      new_insn = subtype_mappings[fragP->fr_subtype].insn_for_extern;
1220
      fragP->fr_subtype = insn_to_subtype (new_insn);
1221
    }
1222
 
1223
  if (MEP_VLIW && ! MEP_VLIW64
1224
      && (bfd_get_section_flags (stdoutput, segment) & SEC_MEP_VLIW))
1225
    {
1226
      /* Use 32 bit branches for vliw32 so the vliw word is not split.  */
1227
      switch (fragP->fr_cgen.insn->base->num)
1228
        {
1229
        case MEP_INSN_BSR12:
1230
          fragP->fr_subtype = insn_to_subtype
1231
            (subtype_mappings[fragP->fr_subtype].insn_for_extern);
1232
          break;
1233
        case MEP_INSN_BEQZ:
1234
          fragP->fr_subtype ++;
1235
          break;
1236
        case MEP_INSN_BNEZ:
1237
          fragP->fr_subtype ++;
1238
          break;
1239
        }
1240
    }
1241
 
1242
  if (fragP->fr_cgen.insn->base
1243
      && fragP->fr_cgen.insn->base->num
1244
         != subtype_mappings[fragP->fr_subtype].insn)
1245
    {
1246
      int new_insn= subtype_mappings[fragP->fr_subtype].insn;
1247
      if (new_insn != -1)
1248
        {
1249
          fragP->fr_cgen.insn = (fragP->fr_cgen.insn
1250
                                 - fragP->fr_cgen.insn->base->num
1251
                                 + new_insn);
1252
        }
1253
    }
1254
 
1255
  return subtype_mappings[fragP->fr_subtype].growth;
1256
}
1257
 
1258
/* *fragP has been relaxed to its final size, and now needs to have
1259
   the bytes inside it modified to conform to the new size.
1260
 
1261
   Called after relaxation is finished.
1262
   fragP->fr_type == rs_machine_dependent.
1263
   fragP->fr_subtype is the subtype of what the address relaxed to.  */
1264
 
1265
static int
1266
target_address_for (fragS *frag)
1267
{
1268
  int rv = frag->fr_offset;
1269
  symbolS *sym = frag->fr_symbol;
1270
 
1271
  if (sym)
1272
    rv += S_GET_VALUE (sym);
1273
 
1274
  return rv;
1275
}
1276
 
1277
void
1278
md_convert_frag (bfd *abfd  ATTRIBUTE_UNUSED,
1279
                 segT sec ATTRIBUTE_UNUSED,
1280
                 fragS *fragP)
1281
{
1282
  int addend, rn, bit = 0;
1283
  int operand;
1284
  int where = fragP->fr_opcode - fragP->fr_literal;
1285
  int e = target_big_endian ? 0 : 1;
1286
 
1287
  addend = target_address_for (fragP) - (fragP->fr_address + where);
1288
 
1289
  if (subtype_mappings[fragP->fr_subtype].insn == -1)
1290
    {
1291
      fragP->fr_fix += subtype_mappings[fragP->fr_subtype].growth;
1292
      switch (subtype_mappings[fragP->fr_subtype].insn_for_extern)
1293
        {
1294
        case MEP_PSEUDO64_16BITCC:
1295
          fragP->fr_opcode[1^e] = ((fragP->fr_opcode[1^e] & 1) ^ 1) | 0x06;
1296
          fragP->fr_opcode[2^e] = 0xd8;
1297
          fragP->fr_opcode[3^e] = 0x08;
1298
          fragP->fr_opcode[4^e] = 0;
1299
          fragP->fr_opcode[5^e] = 0;
1300
          where += 2;
1301
          break;
1302
        case MEP_PSEUDO64_32BITCC:
1303
          if (fragP->fr_opcode[0^e] & 0x10)
1304
            fragP->fr_opcode[1^e] ^= 0x01;
1305
          else
1306
            fragP->fr_opcode[1^e] ^= 0x04;
1307
          fragP->fr_opcode[2^e] = 0;
1308
          fragP->fr_opcode[3^e] = 4;
1309
          fragP->fr_opcode[4^e] = 0xd8;
1310
          fragP->fr_opcode[5^e] = 0x08;
1311
          fragP->fr_opcode[6^e] = 0;
1312
          fragP->fr_opcode[7^e] = 0;
1313
          where += 4;
1314
          break;
1315
        default:
1316
          abort ();
1317
        }
1318
      fragP->fr_cgen.insn = (fragP->fr_cgen.insn
1319
                             - fragP->fr_cgen.insn->base->num
1320
                             + MEP_INSN_JMP);
1321
      operand = MEP_OPERAND_PCABS24A2;
1322
    }
1323
  else
1324
    switch (fragP->fr_cgen.insn->base->num)
1325
      {
1326
      case MEP_INSN_BSR12:
1327
        fragP->fr_opcode[0^e] = 0xb0 | ((addend >> 8) & 0x0f);
1328
        fragP->fr_opcode[1^e] = 0x01 | (addend & 0xfe);
1329
        operand = MEP_OPERAND_PCREL12A2;
1330
        break;
1331
 
1332
      case MEP_INSN_BSR24:
1333
        fragP->fr_fix += 2;
1334
        fragP->fr_opcode[0^e] = 0xd8 | ((addend >> 5) & 0x07);
1335
        fragP->fr_opcode[1^e] = 0x09 | ((addend << 3) & 0xf0);
1336
        fragP->fr_opcode[2^e] = 0x00 | ((addend >>16) & 0xff);
1337
        fragP->fr_opcode[3^e] = 0x00 | ((addend >> 8) & 0xff);
1338
        operand = MEP_OPERAND_PCREL24A2;
1339
        break;
1340
 
1341
      case MEP_INSN_BRA:
1342
        fragP->fr_opcode[0^e] = 0xb0 | ((addend >> 8) & 0x0f);
1343
        fragP->fr_opcode[1^e] = 0x00 | (addend & 0xfe);
1344
        operand = MEP_OPERAND_PCREL12A2;
1345
        break;
1346
 
1347
      case MEP_INSN_BEQ:
1348
        /* The default relax_frag doesn't change the state if there is no
1349
           growth, so we must manually handle converting out-of-range BEQ
1350
           instructions to JMP.  */
1351
        if (addend <= 65535 && addend >= -65536)
1352
          {
1353
            fragP->fr_fix += 2;
1354
            fragP->fr_opcode[0^e] = 0xe0;
1355
            fragP->fr_opcode[1^e] = 0x01;
1356
            fragP->fr_opcode[2^e] = 0x00 | ((addend >> 9) & 0xff);
1357
            fragP->fr_opcode[3^e] = 0x00 | ((addend >> 1) & 0xff);
1358
            operand = MEP_OPERAND_PCREL17A2;
1359
            break;
1360
          }
1361
        /* ...FALLTHROUGH... */
1362
 
1363
      case MEP_INSN_JMP:
1364
        addend = target_address_for (fragP);
1365
        fragP->fr_fix += 2;
1366
        fragP->fr_opcode[0^e] = 0xd8 | ((addend >> 5) & 0x07);
1367
        fragP->fr_opcode[1^e] = 0x08 | ((addend << 3) & 0xf0);
1368
        fragP->fr_opcode[2^e] = 0x00 | ((addend >>16) & 0xff);
1369
        fragP->fr_opcode[3^e] = 0x00 | ((addend >> 8) & 0xff);
1370
        operand = MEP_OPERAND_PCABS24A2;
1371
        break;
1372
 
1373
      case MEP_INSN_BNEZ:
1374
        bit = 1;
1375
      case MEP_INSN_BEQZ:
1376
        fragP->fr_opcode[1^e] = bit | (addend & 0xfe);
1377
        operand = MEP_OPERAND_PCREL8A2;
1378
        break;
1379
 
1380
      case MEP_INSN_BNEI:
1381
        bit = 4;
1382
      case MEP_INSN_BEQI:
1383
        if (subtype_mappings[fragP->fr_subtype].growth)
1384
          {
1385
            fragP->fr_fix += subtype_mappings[fragP->fr_subtype].growth;
1386
            rn = fragP->fr_opcode[0^e] & 0x0f;
1387
            fragP->fr_opcode[0^e] = 0xe0 | rn;
1388
            fragP->fr_opcode[1^e] = bit;
1389
          }
1390
        fragP->fr_opcode[2^e] = 0x00 | ((addend >> 9) & 0xff);
1391
        fragP->fr_opcode[3^e] = 0x00 | ((addend >> 1) & 0xff);
1392
        operand = MEP_OPERAND_PCREL17A2;
1393
        break;
1394
 
1395
      case MEP_INSN_BLTI:
1396
      case MEP_INSN_BGEI:
1397
      case MEP_INSN_BCPEQ:
1398
      case MEP_INSN_BCPNE:
1399
      case MEP_INSN_BCPAT:
1400
      case MEP_INSN_BCPAF:
1401
        /* No opcode change needed, just operand.  */
1402
        fragP->fr_opcode[2^e] = (addend >> 9) & 0xff;
1403
        fragP->fr_opcode[3^e] = (addend >> 1) & 0xff;
1404
        operand = MEP_OPERAND_PCREL17A2;
1405
        break;
1406
 
1407
      default:
1408
        abort ();
1409
      }
1410
 
1411
  if (S_GET_SEGMENT (fragP->fr_symbol) != sec
1412
      || operand == MEP_OPERAND_PCABS24A2)
1413
    {
1414
      assert (fragP->fr_cgen.insn != 0);
1415
      gas_cgen_record_fixup (fragP,
1416
                             where,
1417
                             fragP->fr_cgen.insn,
1418
                             (fragP->fr_fix - where) * 8,
1419
                             cgen_operand_lookup_by_num (gas_cgen_cpu_desc,
1420
                                                         operand),
1421
                             fragP->fr_cgen.opinfo,
1422
                             fragP->fr_symbol, fragP->fr_offset);
1423
    }
1424
}
1425
 
1426
 
1427
/* Functions concerning relocs.  */
1428
 
1429
void
1430
mep_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
1431
{
1432
  /* If we already know the fixup value, adjust it in the same
1433
     way that the linker would have done.  */
1434
  if (fixP->fx_addsy == 0)
1435
    switch (fixP->fx_cgen.opinfo)
1436
      {
1437
      case BFD_RELOC_MEP_LOW16:
1438
        *valP = ((long)(*valP & 0xffff)) << 16 >> 16;
1439
        break;
1440
      case BFD_RELOC_MEP_HI16U:
1441
        *valP >>= 16;
1442
        break;
1443
      case BFD_RELOC_MEP_HI16S:
1444
        *valP = (*valP + 0x8000) >> 16;
1445
        break;
1446
      }
1447
 
1448
  /* Now call cgen's md_aply_fix.  */
1449
  gas_cgen_md_apply_fix (fixP, valP, seg);
1450
}
1451
 
1452
long
1453
md_pcrel_from_section (fixS *fixP, segT sec)
1454
{
1455
  if (fixP->fx_addsy != (symbolS *) NULL
1456
      && (! S_IS_DEFINED (fixP->fx_addsy)
1457
          || S_GET_SEGMENT (fixP->fx_addsy) != sec))
1458
    /* The symbol is undefined (or is defined but not in this section).
1459
       Let the linker figure it out.  */
1460
    return 0;
1461
 
1462
  /* Return the address of the opcode - cgen adjusts for opcode size
1463
     itself, to be consistent with the disassembler, which must do
1464
     so.  */
1465
  return fixP->fx_where + fixP->fx_frag->fr_address;
1466
}
1467
 
1468
/* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
1469
   Returns BFD_RELOC_NONE if no reloc type can be found.
1470
   *FIXP may be modified if desired.  */
1471
 
1472
#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
1473
#define MAP(n) case MEP_OPERAND_##n: return BFD_RELOC_MEP_##n;
1474
#else
1475
#define MAP(n) case MEP_OPERAND_/**/n: return BFD_RELOC_MEP_/**/n;
1476
#endif
1477
 
1478
bfd_reloc_code_real_type
1479
md_cgen_lookup_reloc (const CGEN_INSN *insn ATTRIBUTE_UNUSED,
1480
                      const CGEN_OPERAND *operand,
1481
                      fixS *fixP)
1482
{
1483
  enum bfd_reloc_code_real reloc = fixP->fx_cgen.opinfo;
1484
  static char printed[MEP_OPERAND_MAX] = { 0 };
1485
 
1486
  /* If there's a reloc here, it's because the parser saw a %foo() and
1487
     is giving us the correct reloc to use, or because we converted to
1488
     a different size reloc below and want to avoid "converting" more
1489
     than once.  */
1490
  if (reloc && reloc != BFD_RELOC_NONE)
1491
    return reloc;
1492
 
1493
  switch (operand->type)
1494
    {
1495
      MAP (PCREL8A2);   /* beqz */
1496
      MAP (PCREL12A2);  /* bsr16 */
1497
      MAP (PCREL17A2);  /* beqi */
1498
      MAP (PCREL24A2);  /* bsr24 */
1499
      MAP (PCABS24A2);  /* jmp */
1500
      MAP (UIMM24);     /* mov */
1501
      MAP (ADDR24A4);   /* sw/lw */
1502
 
1503
    /* The rest of the relocs should be generated by the parser,
1504
       for things such as %tprel(), etc. */
1505
    case MEP_OPERAND_SIMM16:
1506
#ifdef OBJ_COMPLEX_RELC
1507
      /* coalescing this into RELOC_MEP_16 is actually a bug,
1508
         since it's a signed operand. let the relc code handle it. */
1509
      return BFD_RELOC_RELC;
1510
#endif
1511
 
1512
    case MEP_OPERAND_UIMM16:
1513
    case MEP_OPERAND_SDISP16:
1514
    case MEP_OPERAND_CODE16:
1515
      fixP->fx_where += 2;
1516
      /* to avoid doing the above add twice */
1517
      fixP->fx_cgen.opinfo = BFD_RELOC_MEP_16;
1518
      return BFD_RELOC_MEP_16;
1519
 
1520
    default:
1521
#ifdef OBJ_COMPLEX_RELC
1522
      /* this is not an error, yet.
1523
         pass it to the linker. */
1524
      return BFD_RELOC_RELC;
1525
#endif
1526
      if (printed[operand->type])
1527
        return BFD_RELOC_NONE;
1528
      printed[operand->type] = 1;
1529
 
1530
      as_bad_where (fixP->fx_file, fixP->fx_line,
1531
                    _("Don't know how to relocate plain operands of type %s"),
1532
                    operand->name);
1533
 
1534
      /* Print some helpful hints for the user.  */
1535
      switch (operand->type)
1536
        {
1537
        case MEP_OPERAND_UDISP7:
1538
        case MEP_OPERAND_UDISP7A2:
1539
        case MEP_OPERAND_UDISP7A4:
1540
          as_bad_where (fixP->fx_file, fixP->fx_line,
1541
                        _("Perhaps you are missing %%tpoff()?"));
1542
          break;
1543
        default:
1544
          break;
1545
        }
1546
      return BFD_RELOC_NONE;
1547
    }
1548
}
1549
 
1550
/* Called while parsing an instruction to create a fixup.
1551
   We need to check for HI16 relocs and queue them up for later sorting.  */
1552
 
1553
fixS *
1554
mep_cgen_record_fixup_exp (fragS *frag,
1555
                           int where,
1556
                           const CGEN_INSN *insn,
1557
                           int length,
1558
                           const CGEN_OPERAND *operand,
1559
                           int opinfo,
1560
                           expressionS *exp)
1561
{
1562
  fixS * fixP = gas_cgen_record_fixup_exp (frag, where, insn, length,
1563
                                           operand, opinfo, exp);
1564
  return fixP;
1565
}
1566
 
1567
/* Return BFD reloc type from opinfo field in a fixS.
1568
   It's tricky using fx_r_type in mep_frob_file because the values
1569
   are BFD_RELOC_UNUSED + operand number.  */
1570
#define FX_OPINFO_R_TYPE(f) ((f)->fx_cgen.opinfo)
1571
 
1572
/* Sort any unmatched HI16 relocs so that they immediately precede
1573
   the corresponding LO16 reloc.  This is called before md_apply_fix and
1574
   tc_gen_reloc.  */
1575
 
1576
void
1577
mep_frob_file ()
1578
{
1579
  struct mep_hi_fixup * l;
1580
 
1581
  for (l = mep_hi_fixup_list; l != NULL; l = l->next)
1582
    {
1583
      segment_info_type * seginfo;
1584
      int pass;
1585
 
1586
      assert (FX_OPINFO_R_TYPE (l->fixp) == BFD_RELOC_HI16
1587
              || FX_OPINFO_R_TYPE (l->fixp) == BFD_RELOC_LO16);
1588
 
1589
      /* Check quickly whether the next fixup happens to be a matching low.  */
1590
      if (l->fixp->fx_next != NULL
1591
          && FX_OPINFO_R_TYPE (l->fixp->fx_next) == BFD_RELOC_LO16
1592
          && l->fixp->fx_addsy == l->fixp->fx_next->fx_addsy
1593
          && l->fixp->fx_offset == l->fixp->fx_next->fx_offset)
1594
        continue;
1595
 
1596
      /* Look through the fixups for this segment for a matching
1597
         `low'.  When we find one, move the high just in front of it.
1598
         We do this in two passes.  In the first pass, we try to find
1599
         a unique `low'.  In the second pass, we permit multiple
1600
         high's relocs for a single `low'.  */
1601
      seginfo = seg_info (l->seg);
1602
      for (pass = 0; pass < 2; pass++)
1603
        {
1604
          fixS * f;
1605
          fixS * prev;
1606
 
1607
          prev = NULL;
1608
          for (f = seginfo->fix_root; f != NULL; f = f->fx_next)
1609
            {
1610
              /* Check whether this is a `low' fixup which matches l->fixp.  */
1611
              if (FX_OPINFO_R_TYPE (f) == BFD_RELOC_LO16
1612
                  && f->fx_addsy == l->fixp->fx_addsy
1613
                  && f->fx_offset == l->fixp->fx_offset
1614
                  && (pass == 1
1615
                      || prev == NULL
1616
                      || (FX_OPINFO_R_TYPE (prev) != BFD_RELOC_HI16)
1617
                      || prev->fx_addsy != f->fx_addsy
1618
                      || prev->fx_offset !=  f->fx_offset))
1619
                {
1620
                  fixS ** pf;
1621
 
1622
                  /* Move l->fixp before f.  */
1623
                  for (pf = &seginfo->fix_root;
1624
                       * pf != l->fixp;
1625
                       pf = & (* pf)->fx_next)
1626
                    assert (* pf != NULL);
1627
 
1628
                  * pf = l->fixp->fx_next;
1629
 
1630
                  l->fixp->fx_next = f;
1631
                  if (prev == NULL)
1632
                    seginfo->fix_root = l->fixp;
1633
                  else
1634
                    prev->fx_next = l->fixp;
1635
 
1636
                  break;
1637
                }
1638
 
1639
              prev = f;
1640
            }
1641
 
1642
          if (f != NULL)
1643
            break;
1644
 
1645
          if (pass == 1)
1646
            as_warn_where (l->fixp->fx_file, l->fixp->fx_line,
1647
                           _("Unmatched high relocation"));
1648
        }
1649
    }
1650
}
1651
 
1652
/* See whether we need to force a relocation into the output file. */
1653
 
1654
int
1655
mep_force_relocation (fixS *fixp)
1656
{
1657
  if (   fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
1658
         || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
1659
    return 1;
1660
 
1661
  /* Allow branches to global symbols to be resolved at assembly time.
1662
     This is consistent with way relaxable branches are handled, since
1663
     branches to both global and local symbols are relaxed.  It also
1664
     corresponds to the assumptions made in md_pcrel_from_section.  */
1665
  return S_FORCE_RELOC (fixp->fx_addsy, !fixp->fx_pcrel);
1666
}
1667
 
1668
/* Write a value out to the object file, using the appropriate endianness.  */
1669
 
1670
void
1671
md_number_to_chars (char *buf, valueT val, int n)
1672
{
1673
  if (target_big_endian)
1674
    number_to_chars_bigendian (buf, val, n);
1675
  else
1676
    number_to_chars_littleendian (buf, val, n);
1677
}
1678
 
1679
char *
1680
md_atof (int type, char *litP, int *sizeP)
1681
{
1682
  return ieee_md_atof (type, litP, sizeP, TRUE);
1683
}
1684
 
1685
bfd_boolean
1686
mep_fix_adjustable (fixS *fixP)
1687
{
1688
  bfd_reloc_code_real_type reloc_type;
1689
 
1690
  if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
1691
    {
1692
      const CGEN_INSN *insn = NULL;
1693
      int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
1694
      const CGEN_OPERAND *operand
1695
        = cgen_operand_lookup_by_num(gas_cgen_cpu_desc, opindex);
1696
      reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
1697
    }
1698
  else
1699
    reloc_type = fixP->fx_r_type;
1700
 
1701
  if (fixP->fx_addsy == NULL)
1702
    return 1;
1703
 
1704
  /* Prevent all adjustments to global symbols. */
1705
  if (S_IS_EXTERNAL (fixP->fx_addsy))
1706
    return 0;
1707
 
1708
  if (S_IS_WEAK (fixP->fx_addsy))
1709
    return 0;
1710
 
1711
  /* We need the symbol name for the VTABLE entries */
1712
  if (reloc_type == BFD_RELOC_VTABLE_INHERIT
1713
      || reloc_type == BFD_RELOC_VTABLE_ENTRY)
1714
    return 0;
1715
 
1716
  return 1;
1717
}
1718
 
1719
int
1720
mep_elf_section_letter (int letter, char **ptrmsg)
1721
{
1722
  if (letter == 'v')
1723
    return SHF_MEP_VLIW;
1724
 
1725
  *ptrmsg = _("Bad .section directive: want a,v,w,x,M,S in string");
1726
  return 0;
1727
}
1728
 
1729
flagword
1730
mep_elf_section_flags (flagword flags, int attr, int type ATTRIBUTE_UNUSED)
1731
{
1732
  if (attr & SHF_MEP_VLIW)
1733
    flags |= SEC_MEP_VLIW;
1734
  return flags;
1735
}
1736
 
1737
/* In vliw mode, the default section is .vtext.  We have to be able
1738
   to switch into .vtext using only the .vtext directive.  */
1739
 
1740
static segT
1741
mep_vtext_section (void)
1742
{
1743
  static segT vtext_section;
1744
 
1745
  if (! vtext_section)
1746
    {
1747
      flagword applicable = bfd_applicable_section_flags (stdoutput);
1748
      vtext_section = subseg_new (VTEXT_SECTION_NAME, 0);
1749
      bfd_set_section_flags (stdoutput, vtext_section,
1750
                             applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC
1751
                                           | SEC_CODE | SEC_READONLY
1752
                                           | SEC_MEP_VLIW));
1753
    }
1754
 
1755
  return vtext_section;
1756
}
1757
 
1758
static void
1759
mep_s_vtext (int ignore ATTRIBUTE_UNUSED)
1760
{
1761
  int temp;
1762
 
1763
  /* Record previous_section and previous_subsection.  */
1764
  obj_elf_section_change_hook ();
1765
 
1766
  temp = get_absolute_expression ();
1767
  subseg_set (mep_vtext_section (), (subsegT) temp);
1768
  demand_empty_rest_of_line ();
1769
}
1770
 
1771
static void
1772
mep_switch_to_core_mode (int dummy ATTRIBUTE_UNUSED)
1773
{
1774
  mep_process_saved_insns ();
1775
  pluspresent = 0;
1776
  mode = CORE;
1777
}
1778
 
1779
static void
1780
mep_switch_to_vliw_mode (int dummy ATTRIBUTE_UNUSED)
1781
{
1782
  if (! MEP_VLIW)
1783
    as_bad (_(".vliw unavailable when VLIW is disabled."));
1784
  mode = VLIW;
1785
  /* Switch into .vtext here too. */
1786
  /* mep_s_vtext(); */
1787
}
1788
 
1789
/* This is an undocumented pseudo-op used to disable gas's
1790
   "disabled_registers" check.  Used for code which checks for those
1791
   registers at runtime.  */
1792
static void
1793
mep_noregerr (int i ATTRIBUTE_UNUSED)
1794
{
1795
  allow_disabled_registers = 1;
1796
}
1797
 
1798
/* mep_unrecognized_line: This is called when a line that can't be parsed
1799
   is encountered.  We use it to check for a leading '+' sign which indicates
1800
   that the current instruction is a coprocessor instruction that is to be
1801
   parallelized with a previous core insn.  This function accepts the '+' and
1802
   rejects all other characters that might indicate garbage at the beginning
1803
   of the line.  The '+' character gets lost as the calling loop continues,
1804
   so we need to indicate that we saw it.  */
1805
 
1806
int
1807
mep_unrecognized_line (int ch)
1808
{
1809
  switch (ch)
1810
    {
1811
    case '+':
1812
      pluspresent = 1;
1813
      return 1; /* '+' indicates an instruction to be parallelized. */
1814
    default:
1815
      return 0; /* If it's not a '+', the line can't be parsed. */
1816
    }
1817
}
1818
 
1819
void
1820
mep_cleanup (void)
1821
{
1822
  /* Take care of any insns left to be parallelized when the file ends.
1823
     This is mainly here to handle the case where the file ends with an
1824
     insn preceeded by a + or the file ends unexpectedly.  */
1825
  if (mode == VLIW)
1826
    mep_process_saved_insns ();
1827
}
1828
 
1829
int
1830
mep_flush_pending_output (void)
1831
{
1832
  if (mode == VLIW)
1833
    {
1834
      mep_process_saved_insns ();
1835
      pluspresent = 0;
1836
    }
1837
 
1838
  return 1;
1839
}

powered by: WebSVN 2.1.0

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