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