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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [cpu/] [mep.opc] - Blame information for rev 303

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

Line No. Rev Author Line
1 161 khays
/* MeP opcode support.  -*- C -*-
2
   Copyright 2011 Free Software Foundation, Inc.
3
 
4
   Contributed by Red Hat Inc;
5
 
6
   This file is part of the GNU Binutils.
7
 
8
   This program is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 3 of the License, or
11
   (at your option) any later version.
12
 
13
   This program is distributed in the hope that it will be useful,
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
   GNU General Public License for more details.
17
 
18
   You should have received a copy of the GNU General Public License
19
   along with this program; if not, write to the Free Software
20
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21
   MA 02110-1301, USA.  */
22
 
23
/* -- opc.h */
24
 
25
#undef  CGEN_DIS_HASH_SIZE
26
#define CGEN_DIS_HASH_SIZE 1
27
 
28
#undef  CGEN_DIS_HASH
29
#define CGEN_DIS_HASH(buffer, insn) 0
30
 
31
#define CGEN_VERBOSE_ASSEMBLER_ERRORS
32
 
33
typedef struct
34
{
35
  char * name;
36
  int    config_enum;
37
  unsigned cpu_flag;
38
  int    big_endian;
39
  int    vliw_bits;
40
  CGEN_ATTR_VALUE_BITSET_TYPE cop16_isa;
41
  CGEN_ATTR_VALUE_BITSET_TYPE cop32_isa;
42
  CGEN_ATTR_VALUE_BITSET_TYPE cop48_isa;
43
  CGEN_ATTR_VALUE_BITSET_TYPE cop64_isa;
44
  CGEN_ATTR_VALUE_BITSET_TYPE cop_isa;
45
  CGEN_ATTR_VALUE_BITSET_TYPE core_isa;
46
  unsigned int option_mask;
47
} mep_config_map_struct;
48
 
49
extern mep_config_map_struct mep_config_map[];
50
extern int mep_config_index;
51
 
52
extern void init_mep_all_core_isas_mask (void);
53
extern void init_mep_all_cop_isas_mask  (void);
54
extern CGEN_ATTR_VALUE_BITSET_TYPE mep_cop_isa  (void);
55
 
56
#define MEP_CONFIG     (mep_config_map[mep_config_index].config_enum)
57
#define MEP_CPU        (mep_config_map[mep_config_index].cpu_flag)
58
#define MEP_OMASK      (mep_config_map[mep_config_index].option_mask)
59
#define MEP_VLIW       (mep_config_map[mep_config_index].vliw_bits > 0)
60
#define MEP_VLIW32     (mep_config_map[mep_config_index].vliw_bits == 32)
61
#define MEP_VLIW64     (mep_config_map[mep_config_index].vliw_bits == 64)
62
#define MEP_COP16_ISA  (mep_config_map[mep_config_index].cop16_isa)
63
#define MEP_COP32_ISA  (mep_config_map[mep_config_index].cop32_isa)
64
#define MEP_COP48_ISA  (mep_config_map[mep_config_index].cop48_isa)
65
#define MEP_COP64_ISA  (mep_config_map[mep_config_index].cop64_isa)
66
#define MEP_COP_ISA    (mep_config_map[mep_config_index].cop_isa)
67
#define MEP_CORE_ISA   (mep_config_map[mep_config_index].core_isa)
68
 
69
/* begin-cop-ip-supported-defines */
70
#define MEP_IVC2_SUPPORTED 1
71
/* end-cop-ip-supported-defines */
72
 
73
extern int mep_insn_supported_by_isa (const CGEN_INSN *, CGEN_ATTR_VALUE_BITSET_TYPE *);
74
 
75
/* A mask for all ISAs executed by the core.  */
76
#define MEP_ALL_CORE_ISAS_MASK mep_all_core_isas_mask
77
extern CGEN_ATTR_VALUE_BITSET_TYPE mep_all_core_isas_mask;
78
 
79
#define MEP_INSN_CORE_P(insn) ( \
80
  init_mep_all_core_isas_mask (), \
81
  mep_insn_supported_by_isa (insn, & MEP_ALL_CORE_ISAS_MASK) \
82
)
83
 
84
/* A mask for all ISAs executed by a VLIW coprocessor.  */
85
#define MEP_ALL_COP_ISAS_MASK mep_all_cop_isas_mask
86
extern CGEN_ATTR_VALUE_BITSET_TYPE mep_all_cop_isas_mask;
87
 
88
#define MEP_INSN_COP_P(insn) ( \
89
  init_mep_all_cop_isas_mask (), \
90
  mep_insn_supported_by_isa (insn, & MEP_ALL_COP_ISAS_MASK) \
91
)
92
 
93
extern int mep_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
94
extern int mep_cgen_insn_supported_asm (CGEN_CPU_DESC, const CGEN_INSN *);
95
 
96
/* -- asm.c */
97
 
98
#include "elf/mep.h"
99
 
100
#define CGEN_VALIDATE_INSN_SUPPORTED
101
#define mep_cgen_insn_supported mep_cgen_insn_supported_asm
102
 
103
       const char * parse_csrn       (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *);
104
       const char * parse_tpreg      (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *);
105
       const char * parse_spreg      (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *);
106
       const char * parse_mep_align  (CGEN_CPU_DESC, const char **, enum cgen_operand_type, long *);
107
       const char * parse_mep_alignu (CGEN_CPU_DESC, const char **, enum cgen_operand_type, unsigned long *);
108
static const char * parse_signed16   (CGEN_CPU_DESC, const char **, int, long *);
109
static const char * parse_signed16_range   (CGEN_CPU_DESC, const char **, int, long *) ATTRIBUTE_UNUSED;
110
static const char * parse_unsigned16 (CGEN_CPU_DESC, const char **, int, unsigned long *);
111
static const char * parse_unsigned16_range (CGEN_CPU_DESC, const char **, int, unsigned long *) ATTRIBUTE_UNUSED;
112
static const char * parse_lo16       (CGEN_CPU_DESC, const char **, int, long *, long);
113
static const char * parse_unsigned7  (CGEN_CPU_DESC, const char **, enum cgen_operand_type, unsigned long *);
114
static const char * parse_zero       (CGEN_CPU_DESC, const char **, int, long *);
115
 
116
const char *
117
parse_csrn (CGEN_CPU_DESC cd, const char **strp,
118
            CGEN_KEYWORD *keyword_table, long *field)
119
{
120
  const char *err;
121
  unsigned long value;
122
 
123
  err = cgen_parse_keyword (cd, strp, keyword_table, field);
124
  if (!err)
125
    return NULL;
126
 
127
  err = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_CSRN_IDX, & value);
128
  if (err)
129
    return err;
130
  *field = value;
131
  return NULL;
132
}
133
 
134
/* begin-cop-ip-parse-handlers */
135
static const char *
136
parse_ivc2_cr (CGEN_CPU_DESC,
137
        const char **,
138
        CGEN_KEYWORD *,
139
        long *) ATTRIBUTE_UNUSED;
140
static const char *
141
parse_ivc2_cr (CGEN_CPU_DESC cd,
142
        const char **strp,
143
        CGEN_KEYWORD *keyword_table  ATTRIBUTE_UNUSED,
144
        long *field)
145
{
146
  return cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_cr_ivc2, field);
147
}
148
static const char *
149
parse_ivc2_ccr (CGEN_CPU_DESC,
150
        const char **,
151
        CGEN_KEYWORD *,
152
        long *) ATTRIBUTE_UNUSED;
153
static const char *
154
parse_ivc2_ccr (CGEN_CPU_DESC cd,
155
        const char **strp,
156
        CGEN_KEYWORD *keyword_table  ATTRIBUTE_UNUSED,
157
        long *field)
158
{
159
  return cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_ccr_ivc2, field);
160
}
161
/* end-cop-ip-parse-handlers */
162
 
163
const char *
164
parse_tpreg (CGEN_CPU_DESC cd, const char ** strp,
165
             CGEN_KEYWORD *keyword_table, long *field)
166
{
167
  const char *err;
168
 
169
  err = cgen_parse_keyword (cd, strp, keyword_table, field);
170
  if (err)
171
    return err;
172
  if (*field != 13)
173
    return _("Only $tp or $13 allowed for this opcode");
174
  return NULL;
175
}
176
 
177
const char *
178
parse_spreg (CGEN_CPU_DESC cd, const char ** strp,
179
             CGEN_KEYWORD *keyword_table, long *field)
180
{
181
  const char *err;
182
 
183
  err = cgen_parse_keyword (cd, strp, keyword_table, field);
184
  if (err)
185
    return err;
186
  if (*field != 15)
187
    return _("Only $sp or $15 allowed for this opcode");
188
  return NULL;
189
}
190
 
191
const char *
192
parse_mep_align (CGEN_CPU_DESC cd, const char ** strp,
193
                 enum cgen_operand_type type, long *field)
194
{
195
  long lsbs = 0;
196
  const char *err;
197
 
198
  switch (type)
199
    {
200
    case MEP_OPERAND_PCREL8A2:
201
    case MEP_OPERAND_PCREL12A2:
202
    case MEP_OPERAND_PCREL17A2:
203
    case MEP_OPERAND_PCREL24A2:
204
      err = cgen_parse_signed_integer   (cd, strp, type, field);
205
      break;
206
    case MEP_OPERAND_PCABS24A2:
207
    case MEP_OPERAND_UDISP7:
208
    case MEP_OPERAND_UDISP7A2:
209
    case MEP_OPERAND_UDISP7A4:
210
    case MEP_OPERAND_UIMM7A4:
211
    case MEP_OPERAND_ADDR24A4:
212
      err = cgen_parse_unsigned_integer (cd, strp, type, (unsigned long *) field);
213
      break;
214
    default:
215
      abort();
216
    }
217
  if (err)
218
    return err;
219
  switch (type)
220
    {
221
    case MEP_OPERAND_UDISP7:
222
      lsbs = 0;
223
      break;
224
    case MEP_OPERAND_PCREL8A2:
225
    case MEP_OPERAND_PCREL12A2:
226
    case MEP_OPERAND_PCREL17A2:
227
    case MEP_OPERAND_PCREL24A2:
228
    case MEP_OPERAND_PCABS24A2:
229
    case MEP_OPERAND_UDISP7A2:
230
      lsbs = *field & 1;
231
      break;
232
    case MEP_OPERAND_UDISP7A4:
233
    case MEP_OPERAND_UIMM7A4:
234
    case MEP_OPERAND_ADDR24A4:
235
      lsbs = *field & 3;
236
      break;
237
      lsbs = *field & 7;
238
      break;
239
    default:
240
      /* Safe assumption?  */
241
      abort ();
242
    }
243
  if (lsbs)
244
    return "Value is not aligned enough";
245
  return NULL;
246
}
247
 
248
const char *
249
parse_mep_alignu (CGEN_CPU_DESC cd, const char ** strp,
250
                 enum cgen_operand_type type, unsigned long *field)
251
{
252
  return parse_mep_align (cd, strp, type, (long *) field);
253
}
254
 
255
 
256
/* Handle %lo(), %tpoff(), %sdaoff(), %hi(), and other signed
257
   constants in a signed context.  */
258
 
259
static const char *
260
parse_signed16 (CGEN_CPU_DESC cd,
261
                const char **strp,
262
                int opindex,
263
                long *valuep)
264
{
265
  return parse_lo16 (cd, strp, opindex, valuep, 1);
266
}
267
 
268
static const char *
269
parse_lo16 (CGEN_CPU_DESC cd,
270
            const char **strp,
271
            int opindex,
272
            long *valuep,
273
            long signedp)
274
{
275
  const char *errmsg;
276
  enum cgen_parse_operand_result result_type;
277
  bfd_vma value;
278
 
279
  if (strncasecmp (*strp, "%lo(", 4) == 0)
280
    {
281
      *strp += 4;
282
      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_LOW16,
283
                                   & result_type, & value);
284
      if (**strp != ')')
285
        return _("missing `)'");
286
      ++*strp;
287
      if (errmsg == NULL
288
          && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
289
        value &= 0xffff;
290
      if (signedp)
291
        *valuep = (long)(short) value;
292
      else
293
        *valuep = value;
294
      return errmsg;
295
    }
296
 
297
  if (strncasecmp (*strp, "%hi(", 4) == 0)
298
    {
299
      *strp += 4;
300
      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16S,
301
                                   & result_type, & value);
302
      if (**strp != ')')
303
        return _("missing `)'");
304
      ++*strp;
305
      if (errmsg == NULL
306
          && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
307
        value = (value + 0x8000) >> 16;
308
      *valuep = value;
309
      return errmsg;
310
    }
311
 
312
  if (strncasecmp (*strp, "%uhi(", 5) == 0)
313
    {
314
      *strp += 5;
315
      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16U,
316
                                   & result_type, & value);
317
      if (**strp != ')')
318
        return _("missing `)'");
319
      ++*strp;
320
      if (errmsg == NULL
321
          && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
322
        value = value >> 16;
323
      *valuep = value;
324
      return errmsg;
325
    }
326
 
327
  if (strncasecmp (*strp, "%sdaoff(", 8) == 0)
328
    {
329
      *strp += 8;
330
      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_GPREL,
331
                                   NULL, & value);
332
      if (**strp != ')')
333
        return _("missing `)'");
334
      ++*strp;
335
      *valuep = value;
336
      return errmsg;
337
    }
338
 
339
  if (strncasecmp (*strp, "%tpoff(", 7) == 0)
340
    {
341
      *strp += 7;
342
      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_TPREL,
343
                                   NULL, & value);
344
      if (**strp != ')')
345
        return _("missing `)'");
346
      ++*strp;
347
      *valuep = value;
348
      return errmsg;
349
    }
350
 
351
  if (**strp == '%')
352
    return _("invalid %function() here");
353
 
354
  return cgen_parse_signed_integer (cd, strp, opindex, valuep);
355
}
356
 
357
static const char *
358
parse_unsigned16 (CGEN_CPU_DESC cd,
359
                  const char **strp,
360
                  int opindex,
361
                  unsigned long *valuep)
362
{
363
  return parse_lo16 (cd, strp, opindex, (long *) valuep, 0);
364
}
365
 
366
static const char *
367
parse_signed16_range (CGEN_CPU_DESC cd,
368
                      const char **strp,
369
                      int opindex,
370
                      signed long *valuep)
371
{
372
  const char *errmsg = 0;
373
  signed long value;
374
 
375
  errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
376
  if (errmsg)
377
    return errmsg;
378
 
379
  if (value < -32768 || value > 32767)
380
    return _("Immediate is out of range -32768 to 32767");
381
 
382
  *valuep = value;
383
  return 0;
384
}
385
 
386
static const char *
387
parse_unsigned16_range (CGEN_CPU_DESC cd,
388
                        const char **strp,
389
                        int opindex,
390
                        unsigned long *valuep)
391
{
392
  const char *errmsg = 0;
393
  unsigned long value;
394
 
395
  errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
396
  if (errmsg)
397
    return errmsg;
398
 
399
  if (value > 65535)
400
    return _("Immediate is out of range 0 to 65535");
401
 
402
  *valuep = value;
403
  return 0;
404
}
405
 
406
/* A special case of parse_signed16 which accepts only the value zero.  */
407
 
408
static const char *
409
parse_zero (CGEN_CPU_DESC cd, const char **strp, int opindex, long *valuep)
410
{
411
  const char *errmsg;
412
  enum cgen_parse_operand_result result_type;
413
  bfd_vma value;
414
 
415
  /*fprintf(stderr, "dj: signed parse opindex `%s'\n", *strp);*/
416
 
417
  /* Prevent ($ry) from being attempted as an expression on 'sw $rx,($ry)'.
418
     It will fail and cause ry to be listed as an undefined symbol in the
419
     listing.  */
420
  if (strncmp (*strp, "($", 2) == 0)
421
    return "not zero"; /* any string will do -- will never be seen.  */
422
 
423
  if (strncasecmp (*strp, "%lo(", 4) == 0)
424
    {
425
      *strp += 4;
426
      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_LOW16,
427
                                   &result_type, &value);
428
      if (**strp != ')')
429
        return "missing `)'";
430
      ++*strp;
431
      if (errmsg == NULL
432
          && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
433
        return "not zero"; /* any string will do -- will never be seen.  */
434
      *valuep = value;
435
      return errmsg;
436
    }
437
 
438
  if (strncasecmp (*strp, "%hi(", 4) == 0)
439
    {
440
      *strp += 4;
441
      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16S,
442
                                   &result_type, &value);
443
      if (**strp != ')')
444
        return "missing `)'";
445
      ++*strp;
446
      if (errmsg == NULL
447
          && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
448
        return "not zero"; /* any string will do -- will never be seen.  */
449
      *valuep = value;
450
      return errmsg;
451
    }
452
 
453
  if (strncasecmp (*strp, "%uhi(", 5) == 0)
454
    {
455
      *strp += 5;
456
      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16U,
457
                                   &result_type, &value);
458
      if (**strp != ')')
459
        return "missing `)'";
460
      ++*strp;
461
      if (errmsg == NULL
462
          && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
463
        return "not zero"; /* any string will do -- will never be seen.  */
464
      *valuep = value;
465
      return errmsg;
466
    }
467
 
468
  if (strncasecmp (*strp, "%sdaoff(", 8) == 0)
469
    {
470
      *strp += 8;
471
      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_GPREL,
472
                                   &result_type, &value);
473
      if (**strp != ')')
474
        return "missing `)'";
475
      ++*strp;
476
      if (errmsg == NULL
477
          && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
478
        return "not zero"; /* any string will do -- will never be seen.  */
479
      *valuep = value;
480
      return errmsg;
481
    }
482
 
483
  if (strncasecmp (*strp, "%tpoff(", 7) == 0)
484
    {
485
      *strp += 7;
486
      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_TPREL,
487
                                   &result_type, &value);
488
      if (**strp != ')')
489
        return "missing `)'";
490
      ++*strp;
491
      if (errmsg == NULL
492
          && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
493
        return "not zero"; /* any string will do -- will never be seen.  */
494
      *valuep = value;
495
      return errmsg;
496
    }
497
 
498
  if (**strp == '%')
499
    return "invalid %function() here";
500
 
501
  errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_NONE,
502
                               &result_type, &value);
503
  if (errmsg == NULL
504
      && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
505
    return "not zero"; /* any string will do -- will never be seen.  */
506
 
507
  return errmsg;
508
}
509
 
510
static const char *
511
parse_unsigned7 (CGEN_CPU_DESC cd, const char **strp,
512
                 enum cgen_operand_type opindex, unsigned long *valuep)
513
{
514
  const char *errmsg;
515
  bfd_vma value;
516
 
517
  /* fprintf(stderr, "dj: unsigned7 parse `%s'\n", *strp); */
518
 
519
  if (strncasecmp (*strp, "%tpoff(", 7) == 0)
520
    {
521
      int reloc;
522
      *strp += 7;
523
      switch (opindex)
524
        {
525
        case MEP_OPERAND_UDISP7:
526
          reloc = BFD_RELOC_MEP_TPREL7;
527
          break;
528
        case MEP_OPERAND_UDISP7A2:
529
          reloc = BFD_RELOC_MEP_TPREL7A2;
530
          break;
531
        case MEP_OPERAND_UDISP7A4:
532
          reloc = BFD_RELOC_MEP_TPREL7A4;
533
          break;
534
        default:
535
          /* Safe assumption?  */
536
          abort ();
537
        }
538
      errmsg = cgen_parse_address (cd, strp, opindex, reloc,
539
                                   NULL, &value);
540
      if (**strp != ')')
541
        return "missing `)'";
542
      ++*strp;
543
      *valuep = value;
544
      return errmsg;
545
    }
546
 
547
  if (**strp == '%')
548
    return _("invalid %function() here");
549
 
550
  return parse_mep_alignu (cd, strp, opindex, valuep);
551
}
552
 
553
static ATTRIBUTE_UNUSED const char *
554
parse_cdisp10 (CGEN_CPU_DESC cd,
555
               const char **strp,
556
               int opindex,
557
               long *valuep)
558
{
559
  const char *errmsg = 0;
560
  signed long value;
561
  long have_zero = 0;
562
  int wide = 0;
563
  int alignment;
564
 
565
  switch (opindex)
566
    {
567
    case MEP_OPERAND_CDISP10A4:
568
      alignment = 2;
569
      break;
570
    case MEP_OPERAND_CDISP10A2:
571
      alignment = 1;
572
      break;
573
    case MEP_OPERAND_CDISP10:
574
    default:
575
      alignment = 0;
576
      break;
577
    }
578
 
579
  if ((MEP_CPU & EF_MEP_CPU_MASK) == EF_MEP_CPU_C5)
580
    wide = 1;
581
 
582
  if (strncmp (*strp, "0x0", 3) == 0
583
      || (**strp == '0' && *(*strp + 1) != 'x'))
584
    have_zero = 1;
585
 
586
  errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
587
  if (errmsg)
588
    return errmsg;
589
 
590
  if (wide)
591
    {
592
      if (value < -512 || value > 511)
593
        return _("Immediate is out of range -512 to 511");
594
    }
595
  else
596
    {
597
      if (value < -128 || value > 127)
598
        return _("Immediate is out of range -128 to 127");
599
    }
600
 
601
  if (value & ((1<
602
    return _("Value is not aligned enough");
603
 
604
  /* If this field may require a relocation then use larger dsp16.  */
605
  if (! have_zero && value == 0)
606
    return (wide ? _("Immediate is out of range -512 to 511")
607
            : _("Immediate is out of range -128 to 127"));
608
 
609
  *valuep = value;
610
  return 0;
611
}
612
 
613
/* BEGIN LIGHTWEIGHT MACRO PROCESSOR.  */
614
 
615
#define MAXARGS 9
616
 
617
typedef struct
618
{
619
  char *name;
620
  char *expansion;
621
}  macro;
622
 
623
typedef struct
624
{
625
  const char *start;
626
  int len;
627
} arg;
628
 
629
macro macros[] =
630
{
631
  { "sizeof", "(`1.end + (- `1))"},
632
  { "startof", "(`1 | 0)" },
633
  { "align4", "(`1&(~3))"},
634
/*{ "hi", "(((`1+0x8000)>>16) & 0xffff)" },  */
635
/*{ "lo", "(`1 & 0xffff)" },  */
636
/*{ "sdaoff", "((`1-__sdabase) & 0x7f)"},  */
637
/*{ "tpoff", "((`1-__tpbase) & 0x7f)"},  */
638
  { 0,0 }
639
};
640
 
641
static char  * expand_string    (const char *, int);
642
 
643
static const char *
644
mep_cgen_expand_macros_and_parse_operand
645
  (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
646
 
647
static char *
648
str_append (char *dest, const char *input, int len)
649
{
650
  char *new_dest;
651
  int oldlen;
652
 
653
  if (len == 0)
654
    return dest;
655
  /* printf("str_append: <<%s>>, <<%s>>, %d\n", dest, input, len); */
656
  oldlen = (dest ? strlen(dest) : 0);
657
  new_dest = realloc (dest, oldlen + len + 1);
658
  memset (new_dest + oldlen, 0, len + 1);
659
  return strncat (new_dest, input, len);
660
}
661
 
662
static macro *
663
lookup_macro (const char *name)
664
{
665
  macro *m;
666
 
667
  for (m = macros; m->name; ++m)
668
    if (strncmp (m->name, name, strlen(m->name)) == 0)
669
      return m;
670
 
671
  return 0;
672
}
673
 
674
static char *
675
expand_macro (arg *args, int narg, macro *mac)
676
{
677
  char *result = 0, *rescanned_result = 0;
678
  char *e = mac->expansion;
679
  char *mark = e;
680
  int mac_arg = 0;
681
 
682
  /*  printf("expanding macro %s with %d args\n", mac->name, narg + 1); */
683
  while (*e)
684
    {
685
      if (*e == '`' &&
686
          (*e+1) &&
687
          ((*(e + 1) - '1') <= MAXARGS) &&
688
          ((*(e + 1) - '1') <= narg))
689
        {
690
          result = str_append (result, mark, e - mark);
691
          mac_arg = (*(e + 1) - '1');
692
          /* printf("replacing `%d with %s\n", mac_arg+1, args[mac_arg].start); */
693
          result = str_append (result, args[mac_arg].start, args[mac_arg].len);
694
          ++e;
695
          mark = e+1;
696
        }
697
      ++e;
698
    }
699
 
700
  if (mark != e)
701
    result = str_append (result, mark, e - mark);
702
 
703
  if (result)
704
    {
705
      rescanned_result = expand_string (result, 0);
706
      free (result);
707
      return rescanned_result;
708
    }
709
  else
710
    return result;
711
}
712
 
713
#define IN_TEXT 0
714
#define IN_ARGS 1
715
 
716
static char *
717
expand_string (const char *in, int first_only)
718
{
719
  int num_expansions = 0;
720
  int depth = 0;
721
  int narg = -1;
722
  arg args[MAXARGS];
723
  int state = IN_TEXT;
724
  const char *mark = in;
725
  macro *pmacro = NULL;
726
  char *expansion = 0;
727
  char *result = 0;
728
 
729
  while (*in)
730
    {
731
      switch (state)
732
        {
733
        case IN_TEXT:
734
          if (*in == '%' && *(in + 1) && (!first_only || num_expansions == 0))
735
            {
736
              pmacro = lookup_macro (in + 1);
737
              if (pmacro)
738
                {
739
                  /* printf("entering state %d at '%s'...\n", state, in); */
740
                  result = str_append (result, mark, in - mark);
741
                  mark = in;
742
                  in += 1 + strlen (pmacro->name);
743
                  while (*in == ' ') ++in;
744
                  if (*in != '(')
745
                    {
746
                      state = IN_TEXT;
747
                      pmacro = NULL;
748
                    }
749
                  else
750
                    {
751
                      state = IN_ARGS;
752
                      narg = 0;
753
                      args[narg].start = in + 1;
754
                      args[narg].len = 0;
755
                      mark = in + 1;
756
                    }
757
                }
758
            }
759
          break;
760
        case IN_ARGS:
761
          if (depth == 0)
762
            {
763
              switch (*in)
764
                {
765
                case ',':
766
                  narg++;
767
                  args[narg].start = (in + 1);
768
                  args[narg].len = 0;
769
                  break;
770
                case ')':
771
                  state = IN_TEXT;
772
                  /* printf("entering state %d at '%s'...\n", state, in); */
773
                  if (pmacro)
774
                    {
775
                      expansion = 0;
776
                      expansion = expand_macro (args, narg, pmacro);
777
                      num_expansions++;
778
                      if (expansion)
779
                        {
780
                          result = str_append (result, expansion, strlen (expansion));
781
                          free (expansion);
782
                        }
783
                    }
784
                  else
785
                    {
786
                      result = str_append (result, mark, in - mark);
787
                    }
788
                  pmacro = NULL;
789
                  mark = in + 1;
790
                  break;
791
                case '(':
792
                  depth++;
793
                default:
794
                  args[narg].len++;
795
                  break;
796
                }
797
            }
798
          else
799
            {
800
              if (*in == ')')
801
                depth--;
802
              if (narg > -1)
803
                args[narg].len++;
804
            }
805
 
806
        }
807
      ++in;
808
    }
809
 
810
  if (mark != in)
811
    result = str_append (result, mark, in - mark);
812
 
813
  return result;
814
}
815
 
816
#undef IN_ARGS
817
#undef IN_TEXT
818
#undef MAXARGS
819
 
820
 
821
/* END LIGHTWEIGHT MACRO PROCESSOR.  */
822
 
823
const char * mep_cgen_parse_operand
824
  (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
825
 
826
const char *
827
mep_cgen_expand_macros_and_parse_operand (CGEN_CPU_DESC cd, int opindex,
828
                                          const char ** strp_in, CGEN_FIELDS * fields)
829
{
830
  const char * errmsg = NULL;
831
  char *str = 0, *hold = 0;
832
  const char **strp = 0;
833
 
834
  /* Set up a new pointer to macro-expanded string.  */
835
  str = expand_string (*strp_in, 1);
836
  /* fprintf (stderr, " expanded <<%s>> to <<%s>>\n", *strp_in, str); */
837
 
838
  hold = str;
839
  strp = (const char **)(&str);
840
 
841
  errmsg = mep_cgen_parse_operand (cd, opindex, strp, fields);
842
 
843
  /* Now work out the advance.  */
844
  if (strlen (str) == 0)
845
    *strp_in += strlen (*strp_in);
846
 
847
  else
848
    {
849
      if (strstr (*strp_in, str))
850
        /* A macro-expansion was pulled off the front.  */
851
        *strp_in = strstr (*strp_in, str);
852
      else
853
        /* A non-macro-expansion was pulled off the front.  */
854
        *strp_in += (str - hold);
855
    }
856
 
857
  if (hold)
858
    free (hold);
859
 
860
  return errmsg;
861
}
862
 
863
#define CGEN_ASM_INIT_HOOK (cd->parse_operand = mep_cgen_expand_macros_and_parse_operand);
864
 
865
/* -- dis.c */
866
 
867
#include "elf/mep.h"
868
#include "elf-bfd.h"
869
 
870
#define CGEN_VALIDATE_INSN_SUPPORTED
871
 
872
static void print_tpreg (CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned int);
873
static void print_spreg (CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned int);
874
 
875
static void
876
print_tpreg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, PTR dis_info,
877
             CGEN_KEYWORD *table ATTRIBUTE_UNUSED, long val ATTRIBUTE_UNUSED,
878
             unsigned int flags ATTRIBUTE_UNUSED)
879
{
880
  disassemble_info *info = (disassemble_info *) dis_info;
881
 
882
  (*info->fprintf_func) (info->stream, "$tp");
883
}
884
 
885
static void
886
print_spreg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, PTR dis_info,
887
             CGEN_KEYWORD *table ATTRIBUTE_UNUSED, long val ATTRIBUTE_UNUSED,
888
             unsigned int flags ATTRIBUTE_UNUSED)
889
{
890
  disassemble_info *info = (disassemble_info *) dis_info;
891
 
892
  (*info->fprintf_func) (info->stream, "$sp");
893
}
894
 
895
/* begin-cop-ip-print-handlers */
896
static void
897
print_ivc2_cr (CGEN_CPU_DESC,
898
        void *,
899
        CGEN_KEYWORD *,
900
        long,
901
        unsigned int) ATTRIBUTE_UNUSED;
902
static void
903
print_ivc2_cr (CGEN_CPU_DESC cd,
904
        void *dis_info,
905
        CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED,
906
        long value,
907
        unsigned int attrs)
908
{
909
  print_keyword (cd, dis_info, & mep_cgen_opval_h_cr_ivc2, value, attrs);
910
}
911
static void
912
print_ivc2_ccr (CGEN_CPU_DESC,
913
        void *,
914
        CGEN_KEYWORD *,
915
        long,
916
        unsigned int) ATTRIBUTE_UNUSED;
917
static void
918
print_ivc2_ccr (CGEN_CPU_DESC cd,
919
        void *dis_info,
920
        CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED,
921
        long value,
922
        unsigned int attrs)
923
{
924
  print_keyword (cd, dis_info, & mep_cgen_opval_h_ccr_ivc2, value, attrs);
925
}
926
/* end-cop-ip-print-handlers */
927
 
928
/************************************************************\
929
*********************** Experimental *************************
930
\************************************************************/
931
 
932
#undef  CGEN_PRINT_INSN
933
#define CGEN_PRINT_INSN mep_print_insn
934
 
935
static int
936
mep_print_vliw_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info,
937
                      bfd_byte *buf, int corelength, int copro1length,
938
                      int copro2length ATTRIBUTE_UNUSED)
939
{
940
  int i;
941
  int status = 0;
942
  /* char insnbuf[CGEN_MAX_INSN_SIZE]; */
943
  bfd_byte insnbuf[64];
944
 
945
  /* If corelength > 0 then there is a core insn present. It
946
     will be at the beginning of the buffer.  After printing
947
     the core insn, we need to print the + on the next line.  */
948
  if (corelength > 0)
949
    {
950
      int my_status = 0;
951
 
952
      for (i = 0; i < corelength; i++ )
953
        insnbuf[i] = buf[i];
954
      cd->isas = & MEP_CORE_ISA;
955
 
956
      my_status = print_insn (cd, pc, info, insnbuf, corelength);
957
      if (my_status != corelength)
958
        {
959
          (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
960
          my_status = corelength;
961
        }
962
      status += my_status;
963
 
964
      /* Print the + to indicate that the following copro insn is   */
965
      /* part of a vliw group.                                      */
966
      if (copro1length > 0)
967
        (*info->fprintf_func) (info->stream, " + ");
968
    }
969
 
970
  /* Now all that is left to be processed is the coprocessor insns
971
     In vliw mode, there will always be one.  Its positioning will
972
     be from byte corelength to byte corelength+copro1length -1.
973
     No need to check for existence.   Also, the first vliw insn,
974
     will, as spec'd, always be at least as long as the core insn
975
     so we don't need to flush the buffer.  */
976
  if (copro1length > 0)
977
    {
978
      int my_status = 0;
979
 
980
      for (i = corelength; i < corelength + copro1length; i++ )
981
        insnbuf[i - corelength] = buf[i];
982
 
983
      switch (copro1length)
984
        {
985
        case 0:
986
          break;
987
        case 2:
988
          cd->isas = & MEP_COP16_ISA;
989
          break;
990
        case 4:
991
          cd->isas = & MEP_COP32_ISA;
992
          break;
993
        case 6:
994
          cd->isas = & MEP_COP48_ISA;
995
          break;
996
        case 8:
997
          cd->isas = & MEP_COP64_ISA;
998
          break;
999
        default:
1000
          /* Shouldn't be anything but 16,32,48,64.  */
1001
          break;
1002
        }
1003
 
1004
      my_status = print_insn (cd, pc, info, insnbuf, copro1length);
1005
 
1006
      if (my_status != copro1length)
1007
        {
1008
          (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
1009
          my_status = copro1length;
1010
        }
1011
      status += my_status;
1012
    }
1013
 
1014
#if 0
1015
  /* Now we need to process the second copro insn if it exists. We
1016
     have no guarantee that the second copro insn will be longer
1017
     than the first, so we have to flush the buffer if we are have
1018
     a second copro insn to process.  If present, this insn will
1019
     be in the position from byte corelength+copro1length to byte
1020
     corelength+copro1length+copro2length-1 (which better equal 8
1021
     or else we're in big trouble.  */
1022
  if (copro2length > 0)
1023
    {
1024
      int my_status = 0;
1025
 
1026
      for (i = 0; i < 64 ; i++)
1027
        insnbuf[i] = 0;
1028
 
1029
      for (i = corelength + copro1length; i < 64; i++)
1030
        insnbuf[i - (corelength + copro1length)] = buf[i];
1031
 
1032
      switch (copro2length)
1033
        {
1034
        case 2:
1035
          cd->isas = 1 << ISA_EXT_COP1_16;
1036
          break;
1037
        case 4:
1038
          cd->isas = 1 << ISA_EXT_COP1_32;
1039
          break;
1040
        case 6:
1041
          cd->isas = 1 << ISA_EXT_COP1_48;
1042
          break;
1043
        case 8:
1044
          cd->isas = 1 << ISA_EXT_COP1_64;
1045
          break;
1046
        default:
1047
          /* Shouldn't be anything but 16,32,48,64.  */
1048
          break;
1049
        }
1050
 
1051
      my_status = print_insn (cd, pc, info, insnbuf, copro2length);
1052
 
1053
      if (my_status != copro2length)
1054
        {
1055
          (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
1056
          my_status = copro2length;
1057
        }
1058
 
1059
      status += my_status;
1060
    }
1061
#endif
1062
 
1063
  /* Status should now be the number of bytes that were printed
1064
     which should be 4 for VLIW32 mode and 64 for VLIW64 mode.  */
1065
 
1066
  if ((!MEP_VLIW64 && (status != 4)) || (MEP_VLIW64 && (status != 8)))
1067
    return -1;
1068
  else
1069
    return status;
1070
}
1071
 
1072
/* The two functions mep_examine_vliw[32,64]_insns are used find out
1073
   which vliw combinaion (16 bit core with 48 bit copro, 32 bit core
1074
   with 32 bit copro, etc.) is present.  Later on, when internally
1075
   parallel coprocessors are handled, only these functions should
1076
   need to be changed.
1077
 
1078
   At this time only the following combinations are supported:
1079
 
1080
   VLIW32 Mode:
1081
   16 bit core insn (core) and 16 bit coprocessor insn (cop1)
1082
   32 bit core insn (core)
1083
   32 bit coprocessor insn (cop1)
1084
   Note: As of this time, I do not believe we have enough information
1085
         to distinguish a 32 bit core insn from a 32 bit cop insn. Also,
1086
         no 16 bit coprocessor insns have been specified.
1087
 
1088
   VLIW64 Mode:
1089
   16 bit core insn (core) and 48 bit coprocessor insn (cop1)
1090
   32 bit core insn (core) and 32 bit coprocessor insn (cop1)
1091
   64 bit coprocessor insn (cop1)
1092
 
1093
   The framework for an internally parallel coprocessor is also
1094
   present (2nd coprocessor insn is cop2), but at this time it
1095
   is not used.  This only appears to be valid in VLIW64 mode.  */
1096
 
1097
static int
1098
mep_examine_vliw32_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
1099
{
1100
  int status;
1101
  int buflength;
1102
  int corebuflength;
1103
  int cop1buflength;
1104
  int cop2buflength;
1105
  bfd_byte buf[CGEN_MAX_INSN_SIZE];
1106
  char indicator16[1];
1107
  char indicatorcop32[2];
1108
 
1109
  /* At this time we're not supporting internally parallel coprocessors,
1110
     so cop2buflength will always be 0.  */
1111
  cop2buflength = 0;
1112
 
1113
  /* Read in 32 bits.  */
1114
  buflength = 4; /* VLIW insn spans 4 bytes.  */
1115
  status = (*info->read_memory_func) (pc, buf, buflength, info);
1116
 
1117
  if (status != 0)
1118
    {
1119
      (*info->memory_error_func) (status, pc, info);
1120
      return -1;
1121
    }
1122
 
1123
  /* Put the big endian representation of the bytes to be examined
1124
     in the temporary buffers for examination.  */
1125
 
1126
  if (info->endian == BFD_ENDIAN_BIG)
1127
    {
1128
      indicator16[0] = buf[0];
1129
      indicatorcop32[0] = buf[0];
1130
      indicatorcop32[1] = buf[1];
1131
    }
1132
  else
1133
    {
1134
      indicator16[0] = buf[1];
1135
      indicatorcop32[0] = buf[1];
1136
      indicatorcop32[1] = buf[0];
1137
    }
1138
 
1139
  /* If the two high order bits are 00, 01 or 10, we have a 16 bit
1140
     core insn and a 48 bit copro insn.  */
1141
 
1142
  if ((indicator16[0] & 0x80) && (indicator16[0] & 0x40))
1143
    {
1144
      if ((indicatorcop32[0] & 0xf0) == 0xf0 && (indicatorcop32[1] & 0x07) == 0x07)
1145
        {
1146
          /* We have a 32 bit copro insn.  */
1147
          corebuflength = 0;
1148
          /* All 4 4ytes are one copro insn. */
1149
          cop1buflength = 4;
1150
        }
1151
      else
1152
        {
1153
          /* We have a 32 bit core.  */
1154
          corebuflength = 4;
1155
          cop1buflength = 0;
1156
        }
1157
    }
1158
  else
1159
    {
1160
      /* We have a 16 bit core insn and a 16 bit copro insn.  */
1161
      corebuflength = 2;
1162
      cop1buflength = 2;
1163
    }
1164
 
1165
  /* Now we have the distrubution set.  Print them out.  */
1166
  status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength,
1167
                                 cop1buflength, cop2buflength);
1168
 
1169
  return status;
1170
}
1171
 
1172
static int
1173
mep_examine_vliw64_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
1174
{
1175
  int status;
1176
  int buflength;
1177
  int corebuflength;
1178
  int cop1buflength;
1179
  int cop2buflength;
1180
  bfd_byte buf[CGEN_MAX_INSN_SIZE];
1181
  char indicator16[1];
1182
  char indicator64[4];
1183
 
1184
  /* At this time we're not supporting internally parallel
1185
     coprocessors, so cop2buflength will always be 0.  */
1186
  cop2buflength = 0;
1187
 
1188
  /* Read in 64 bits.  */
1189
  buflength = 8; /* VLIW insn spans 8 bytes.  */
1190
  status = (*info->read_memory_func) (pc, buf, buflength, info);
1191
 
1192
  if (status != 0)
1193
    {
1194
      (*info->memory_error_func) (status, pc, info);
1195
      return -1;
1196
    }
1197
 
1198
  /* We have all 64 bits in the buffer now.  We have to figure out
1199
     what combination of instruction sizes are present.  The two
1200
     high order bits will indicate whether or not we have a 16 bit
1201
     core insn or not.  If not, then we have to look at the 7,8th
1202
     bytes to tell whether we have 64 bit copro insn or a 32 bit
1203
     core insn with a 32 bit copro insn.  Endianness will make a
1204
     difference here.  */
1205
 
1206
  /* Put the big endian representation of the bytes to be examined
1207
     in the temporary buffers for examination.  */
1208
 
1209
  /* indicator16[0] = buf[0];  */
1210
  if (info->endian == BFD_ENDIAN_BIG)
1211
    {
1212
      indicator16[0] = buf[0];
1213
      indicator64[0] = buf[0];
1214
      indicator64[1] = buf[1];
1215
      indicator64[2] = buf[2];
1216
      indicator64[3] = buf[3];
1217
    }
1218
  else
1219
    {
1220
      indicator16[0] = buf[1];
1221
      indicator64[0] = buf[1];
1222
      indicator64[1] = buf[0];
1223
      indicator64[2] = buf[3];
1224
      indicator64[3] = buf[2];
1225
    }
1226
 
1227
  /* If the two high order bits are 00, 01 or 10, we have a 16 bit
1228
     core insn and a 48 bit copro insn.  */
1229
 
1230
  if ((indicator16[0] & 0x80) && (indicator16[0] & 0x40))
1231
    {
1232
      if ((indicator64[0] & 0xf0) == 0xf0 && (indicator64[1] & 0x07) == 0x07
1233
          && ((indicator64[2] & 0xfe) != 0xf0 || (indicator64[3] & 0xf4) != 0))
1234
        {
1235
          /* We have a 64 bit copro insn.  */
1236
          corebuflength = 0;
1237
          /* All 8 bytes are one copro insn.  */
1238
          cop1buflength = 8;
1239
        }
1240
      else
1241
        {
1242
          /* We have a 32 bit core insn and a 32 bit copro insn.  */
1243
          corebuflength = 4;
1244
          cop1buflength = 4;
1245
        }
1246
    }
1247
  else
1248
    {
1249
      /* We have a 16 bit core insn and a 48 bit copro insn.  */
1250
      corebuflength = 2;
1251
      cop1buflength = 6;
1252
    }
1253
 
1254
  /* Now we have the distrubution set.  Print them out. */
1255
  status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength,
1256
                                 cop1buflength, cop2buflength);
1257
 
1258
  return status;
1259
}
1260
 
1261
#ifdef MEP_IVC2_SUPPORTED
1262
 
1263
static int
1264
print_slot_insn (CGEN_CPU_DESC cd,
1265
                 bfd_vma pc,
1266
                 disassemble_info *info,
1267
                 SLOTS_ATTR slot,
1268
                 bfd_byte *buf)
1269
{
1270
  const CGEN_INSN_LIST *insn_list;
1271
  CGEN_INSN_INT insn_value;
1272
  CGEN_EXTRACT_INFO ex_info;
1273
 
1274
  insn_value = cgen_get_insn_value (cd, buf, 32);
1275
 
1276
  /* Fill in ex_info fields like read_insn would.  Don't actually call
1277
     read_insn, since the incoming buffer is already read (and possibly
1278
     modified a la m32r).  */
1279
  ex_info.valid = (1 << 8) - 1;
1280
  ex_info.dis_info = info;
1281
  ex_info.insn_bytes = buf;
1282
 
1283
  /* The instructions are stored in hash lists.
1284
     Pick the first one and keep trying until we find the right one.  */
1285
 
1286
  insn_list = CGEN_DIS_LOOKUP_INSN (cd, (char *) buf, insn_value);
1287
  while (insn_list != NULL)
1288
    {
1289
      const CGEN_INSN *insn = insn_list->insn;
1290
      CGEN_FIELDS fields;
1291
      int length;
1292
 
1293
      if ((CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG)
1294
           && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG) != MEP_CONFIG)
1295
          || ! (CGEN_ATTR_CGEN_INSN_SLOTS_VALUE (CGEN_INSN_ATTRS (insn)) & (1 << slot)))
1296
        {
1297
          insn_list = CGEN_DIS_NEXT_INSN (insn_list);
1298
          continue;
1299
        }
1300
 
1301
      if ((insn_value & CGEN_INSN_BASE_MASK (insn))
1302
          == CGEN_INSN_BASE_VALUE (insn))
1303
        {
1304
          /* Printing is handled in two passes.  The first pass parses the
1305
             machine insn and extracts the fields.  The second pass prints
1306
             them.  */
1307
 
1308
          length = CGEN_EXTRACT_FN (cd, insn)
1309
            (cd, insn, &ex_info, insn_value, &fields, pc);
1310
 
1311
          /* Length < 0 -> error.  */
1312
          if (length < 0)
1313
            return length;
1314
          if (length > 0)
1315
            {
1316
              CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
1317
              /* Length is in bits, result is in bytes.  */
1318
              return length / 8;
1319
            }
1320
        }
1321
 
1322
      insn_list = CGEN_DIS_NEXT_INSN (insn_list);
1323
    }
1324
 
1325
  if (slot == SLOTS_P0S)
1326
    (*info->fprintf_func) (info->stream, "*unknown-p0s*");
1327
  else if (slot == SLOTS_P0)
1328
    (*info->fprintf_func) (info->stream, "*unknown-p0*");
1329
  else if (slot == SLOTS_P1)
1330
    (*info->fprintf_func) (info->stream, "*unknown-p1*");
1331
  else if (slot == SLOTS_C3)
1332
    (*info->fprintf_func) (info->stream, "*unknown-c3*");
1333
  return 0;
1334
}
1335
 
1336
static int
1337
mep_examine_ivc2_insns (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, bfd_vma pc ATTRIBUTE_UNUSED, disassemble_info *info ATTRIBUTE_UNUSED)
1338
{
1339
  int status;
1340
  int buflength;
1341
  bfd_byte buf[8];
1342
  bfd_byte insn[8];
1343
  int e;
1344
 
1345
  /* Read in 64 bits.  */
1346
  buflength = 8; /* VLIW insn spans 8 bytes.  */
1347
  status = (*info->read_memory_func) (pc, buf, buflength, info);
1348
 
1349
  if (status != 0)
1350
    {
1351
      (*info->memory_error_func) (status, pc, info);
1352
      return -1;
1353
    }
1354
 
1355
  if (info->endian == BFD_ENDIAN_LITTLE)
1356
    e = 1;
1357
  else
1358
    e = 0;
1359
 
1360
  if (((unsigned char)buf[0^e] & 0xf0) < 0xc0)
1361
    {
1362
      /*      <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */
1363
      /* V1   [-----core-----][--------p0s-------][------------p1------------] */
1364
 
1365
      print_insn (cd, pc, info, buf, 2);
1366
 
1367
      insn[0^e] = 0;
1368
      insn[1^e] = buf[2^e];
1369
      insn[2^e] = buf[3^e];
1370
      insn[3^e] = buf[4^e] & 0xf0;
1371
      (*info->fprintf_func) (info->stream, " + ");
1372
      print_slot_insn (cd, pc, info, SLOTS_P0S, insn);
1373
 
1374
      insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4;
1375
      insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4;
1376
      insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4;
1377
      insn[3^e] = buf[7^e] << 4;
1378
      (*info->fprintf_func) (info->stream, " + ");
1379
      print_slot_insn (cd, pc, info, SLOTS_P1, insn);
1380
    }
1381
  else if ((buf[0^e] & 0xf0) == 0xf0 && (buf[1^e] & 0x0f) == 0x07)
1382
    {
1383
      /*      <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */
1384
      /* V3   1111[--p0--]0111[--------p0--------][------------p1------------] */
1385
      /*                                          00000000111111112222222233333333 */
1386
 
1387
      insn[0^e] = buf[0^e] << 4 | buf[1^e] >> 4;
1388
      insn[1^e] = buf[2^e];
1389
      insn[2^e] = buf[3^e];
1390
      insn[3^e] = buf[4^e] & 0xf0;
1391
      print_slot_insn (cd, pc, info, SLOTS_P0, insn);
1392
 
1393
      insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4;
1394
      insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4;
1395
      insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4;
1396
      insn[3^e] = buf[7^e] << 4;
1397
      (*info->fprintf_func) (info->stream, " + ");
1398
      print_slot_insn (cd, pc, info, SLOTS_P1, insn);
1399
    }
1400
  else
1401
    {
1402
      /*      <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */
1403
      /* V2   [-------------core-------------]xxxx[------------p1------------] */
1404
      print_insn (cd, pc, info, buf, 4);
1405
 
1406
      insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4;
1407
      insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4;
1408
      insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4;
1409
      insn[3^e] = buf[7^e] << 4;
1410
      (*info->fprintf_func) (info->stream, " + ");
1411
      print_slot_insn (cd, pc, info, SLOTS_P1, insn);
1412
    }
1413
 
1414
  return 8;
1415
}
1416
 
1417
#endif /* MEP_IVC2_SUPPORTED */
1418
 
1419
/* This is a hack.  SID calls this to update the disassembler as the
1420
   CPU changes modes.  */
1421
static int mep_ivc2_disassemble_p = 0;
1422
static int mep_ivc2_vliw_disassemble_p = 0;
1423
 
1424
void
1425
mep_print_insn_set_ivc2_mode (int ivc2_p, int vliw_p, int cfg_idx);
1426
void
1427
mep_print_insn_set_ivc2_mode (int ivc2_p, int vliw_p, int cfg_idx)
1428
{
1429
  mep_ivc2_disassemble_p = ivc2_p;
1430
  mep_ivc2_vliw_disassemble_p = vliw_p;
1431
  mep_config_index = cfg_idx;
1432
}
1433
 
1434
static int
1435
mep_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
1436
{
1437
  int status;
1438
  int cop_type;
1439
  int ivc2 = 0;
1440
  static CGEN_ATTR_VALUE_BITSET_TYPE *ivc2_core_isa = NULL;
1441
 
1442
  if (ivc2_core_isa == NULL)
1443
    {
1444
      /* IVC2 has some core-only coprocessor instructions.  We
1445
         use COP32 to flag those, and COP64 for the VLIW ones,
1446
         since they have the same names.  */
1447
      ivc2_core_isa = cgen_bitset_create (MAX_ISAS);
1448
    }
1449
 
1450
  /* Extract and adapt to configuration number, if available. */
1451
  if (info->section && info->section->owner)
1452
    {
1453
      bfd *abfd = info->section->owner;
1454
      mep_config_index = abfd->tdata.elf_obj_data->elf_header->e_flags & EF_MEP_INDEX_MASK;
1455
      /* This instantly redefines MEP_CONFIG, MEP_OMASK, .... MEP_VLIW64 */
1456
 
1457
      cop_type = abfd->tdata.elf_obj_data->elf_header->e_flags & EF_MEP_COP_MASK;
1458
      if (cop_type == EF_MEP_COP_IVC2)
1459
        ivc2 = 1;
1460
    }
1461
 
1462
  /* Picking the right ISA bitmask for the current context is tricky.  */
1463
  if (info->section)
1464
    {
1465
      if (info->section->flags & SEC_MEP_VLIW)
1466
        {
1467
#ifdef MEP_IVC2_SUPPORTED
1468
          if (ivc2)
1469
            {
1470
              /* ivc2 has its own way of selecting its functions.  */
1471
              cd->isas = & MEP_CORE_ISA;
1472
              status = mep_examine_ivc2_insns (cd, pc, info);
1473
            }
1474
          else
1475
#endif
1476
            /* Are we in 32 or 64 bit vliw mode?  */
1477
            if (MEP_VLIW64)
1478
              status = mep_examine_vliw64_insns (cd, pc, info);
1479
            else
1480
              status = mep_examine_vliw32_insns (cd, pc, info);
1481
          /* Both the above branches set their own isa bitmasks.  */
1482
        }
1483
      else
1484
        {
1485
          if (ivc2)
1486
            {
1487
              cgen_bitset_clear (ivc2_core_isa);
1488
              cgen_bitset_union (ivc2_core_isa, &MEP_CORE_ISA, ivc2_core_isa);
1489
              cgen_bitset_union (ivc2_core_isa, &MEP_COP32_ISA, ivc2_core_isa);
1490
              cd->isas = ivc2_core_isa;
1491
            }
1492
          else
1493
            cd->isas = & MEP_CORE_ISA;
1494
          status = default_print_insn (cd, pc, info);
1495
        }
1496
    }
1497
  else /* sid or gdb */
1498
    {
1499
#ifdef MEP_IVC2_SUPPORTED
1500
      if (mep_ivc2_disassemble_p)
1501
        {
1502
          if (mep_ivc2_vliw_disassemble_p)
1503
            {
1504
              cd->isas = & MEP_CORE_ISA;
1505
              status = mep_examine_ivc2_insns (cd, pc, info);
1506
              return status;
1507
            }
1508
          else
1509
            {
1510
              if (ivc2)
1511
                cd->isas = ivc2_core_isa;
1512
            }
1513
        }
1514
#endif
1515
 
1516
      status = default_print_insn (cd, pc, info);
1517
    }
1518
 
1519
  return status;
1520
}
1521
 
1522
 
1523
/* -- opc.c */
1524
#include "elf/mep.h"
1525
 
1526
/* A mask for all ISAs executed by the core. */
1527
CGEN_ATTR_VALUE_BITSET_TYPE mep_all_core_isas_mask = {0, 0};
1528
 
1529
void
1530
init_mep_all_core_isas_mask (void)
1531
{
1532
  if (mep_all_core_isas_mask.length != 0)
1533
    return;
1534
  cgen_bitset_init (& mep_all_core_isas_mask, ISA_MAX);
1535
  cgen_bitset_set (& mep_all_core_isas_mask, ISA_MEP);
1536
  /* begin-all-core-isas */
1537
  cgen_bitset_add (& mep_all_core_isas_mask, ISA_EXT_CORE1);
1538
  /* end-all-core-isas */
1539
}
1540
 
1541
CGEN_ATTR_VALUE_BITSET_TYPE mep_all_cop_isas_mask = {0, 0};
1542
 
1543
void
1544
init_mep_all_cop_isas_mask (void)
1545
{
1546
  if (mep_all_cop_isas_mask.length != 0)
1547
    return;
1548
  cgen_bitset_init (& mep_all_cop_isas_mask, ISA_MAX);
1549
  /* begin-all-cop-isas */
1550
  cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_16);
1551
  cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_32);
1552
  cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_48);
1553
  cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_64);
1554
  /* end-all-cop-isas */
1555
}
1556
 
1557
int
1558
mep_insn_supported_by_isa (const CGEN_INSN *insn, CGEN_ATTR_VALUE_BITSET_TYPE *isa_mask)
1559
{
1560
  CGEN_BITSET insn_isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA);
1561
  return cgen_bitset_intersect_p (& insn_isas, isa_mask);
1562
}
1563
 
1564
#define OPTION_MASK \
1565
        ( (1 << CGEN_INSN_OPTIONAL_BIT_INSN) \
1566
        | (1 << CGEN_INSN_OPTIONAL_MUL_INSN) \
1567
        | (1 << CGEN_INSN_OPTIONAL_DIV_INSN) \
1568
        | (1 << CGEN_INSN_OPTIONAL_DEBUG_INSN) \
1569
        | (1 << CGEN_INSN_OPTIONAL_LDZ_INSN) \
1570
        | (1 << CGEN_INSN_OPTIONAL_ABS_INSN) \
1571
        | (1 << CGEN_INSN_OPTIONAL_AVE_INSN) \
1572
        | (1 << CGEN_INSN_OPTIONAL_MINMAX_INSN) \
1573
        | (1 << CGEN_INSN_OPTIONAL_CLIP_INSN) \
1574
        | (1 << CGEN_INSN_OPTIONAL_SAT_INSN) \
1575
        | (1 << CGEN_INSN_OPTIONAL_UCI_INSN) \
1576
        | (1 << CGEN_INSN_OPTIONAL_DSP_INSN) \
1577
        | (1 << CGEN_INSN_OPTIONAL_CP_INSN) \
1578
        | (1 << CGEN_INSN_OPTIONAL_CP64_INSN) )
1579
 
1580
 
1581
mep_config_map_struct mep_config_map[] =
1582
{
1583
  /* config-map-start */
1584
  /* Default entry: first module, with all options enabled. */
1585
  { "", 0,  EF_MEP_COP_IVC2 | EF_MEP_CPU_C5,0, 64, { 1, "\x20" }, { 1, "\x10" }, { 1, "\x8" }, { 1, "\x4" }, { 1, "\x3c" }, { 1, "\xc0" }, OPTION_MASK | (1 << CGEN_INSN_OPTIONAL_DSP_INSN) | (1 << CGEN_INSN_OPTIONAL_UCI_INSN) },
1586
  { "default", CONFIG_DEFAULT, EF_MEP_COP_IVC2 | EF_MEP_CPU_C5, 0, 64, { 1, "\x20" }, { 1, "\x10" }, { 1, "\x8" }, { 1, "\x4" }, { 1, "\x3c" }, { 1, "\xc0" },
1587
 
1588
        | (1 << CGEN_INSN_OPTIONAL_CP_INSN)
1589
        | (1 << CGEN_INSN_OPTIONAL_CP64_INSN)
1590
        | (1 << CGEN_INSN_OPTIONAL_MUL_INSN)
1591
        | (1 << CGEN_INSN_OPTIONAL_DIV_INSN)
1592
        | (1 << CGEN_INSN_OPTIONAL_BIT_INSN)
1593
        | (1 << CGEN_INSN_OPTIONAL_LDZ_INSN)
1594
        | (1 << CGEN_INSN_OPTIONAL_ABS_INSN)
1595
        | (1 << CGEN_INSN_OPTIONAL_AVE_INSN)
1596
        | (1 << CGEN_INSN_OPTIONAL_MINMAX_INSN)
1597
        | (1 << CGEN_INSN_OPTIONAL_CLIP_INSN)
1598
        | (1 << CGEN_INSN_OPTIONAL_SAT_INSN) },
1599
  /* config-map-end */
1600
  { 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, 0 }
1601
};
1602
 
1603
int mep_config_index = 0;
1604
 
1605
static int
1606
check_configured_mach (int machs)
1607
{
1608
  /* All base insns are supported.  */
1609
  int mach = 1 << MACH_BASE;
1610
  switch (MEP_CPU & EF_MEP_CPU_MASK)
1611
    {
1612
    case EF_MEP_CPU_C2:
1613
    case EF_MEP_CPU_C3:
1614
      mach |= (1 << MACH_MEP);
1615
      break;
1616
    case EF_MEP_CPU_H1:
1617
      mach |= (1 << MACH_H1);
1618
      break;
1619
    case EF_MEP_CPU_C5:
1620
      mach |= (1 << MACH_MEP);
1621
      mach |= (1 << MACH_C5);
1622
      break;
1623
    default:
1624
      break;
1625
    }
1626
  return machs & mach;
1627
}
1628
 
1629
int
1630
mep_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
1631
{
1632
  int iconfig = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG);
1633
  int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
1634
  CGEN_BITSET isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA);
1635
  int ok1;
1636
  int ok2;
1637
  int ok3;
1638
 
1639
  /* If the insn has an option bit set that we don't want,
1640
     reject it.  */
1641
  if (CGEN_INSN_ATTRS (insn)->bool_ & OPTION_MASK & ~MEP_OMASK)
1642
    return 0;
1643
 
1644
  /* If attributes are absent, assume no restriction. */
1645
  if (machs == 0)
1646
    machs = ~0;
1647
 
1648
  ok1 = ((machs & cd->machs) && cgen_bitset_intersect_p (& isas, cd->isas));
1649
  /* If the insn is config-specific, make sure it matches.  */
1650
  ok2 =  (iconfig == 0 || iconfig == MEP_CONFIG);
1651
  /* Make sure the insn is supported by the configured mach  */
1652
  ok3 = check_configured_mach (machs);
1653
 
1654
  return (ok1 && ok2 && ok3);
1655
}
1656
 
1657
int
1658
mep_cgen_insn_supported_asm (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
1659
{
1660
#ifdef MEP_IVC2_SUPPORTED
1661
  /* If we're assembling VLIW packets, ignore the 12-bit BSR as we
1662
     can't relax that.  The 24-bit BSR is matched instead.  */
1663
  if (insn->base->num == MEP_INSN_BSR12
1664
      && cgen_bitset_contains (cd->isas, ISA_EXT_COP1_64))
1665
    return 0;
1666
#endif
1667
 
1668
  return mep_cgen_insn_supported (cd, insn);
1669
}

powered by: WebSVN 2.1.0

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