xref: /netbsd-src/external/gpl3/binutils/dist/cpu/mep.opc (revision cb63e24e8d6aae7ddac1859a9015f48b1d8bd90e)
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    return _("invalid %function() here");
353
354  return cgen_parse_signed_integer (cd, strp, opindex, valuep);
355}
356
357static const char *
358parse_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
366static const char *
367parse_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
386static const char *
387parse_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
408static const char *
409parse_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
510static const char *
511parse_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
553static ATTRIBUTE_UNUSED const char *
554parse_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<<alignment)-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
617typedef struct
618{
619  char *name;
620  char *expansion;
621}  macro;
622
623typedef struct
624{
625  const char *start;
626  int len;
627} arg;
628
629static macro const 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
641static char  * expand_string    (const char *, int);
642
643static const char *
644mep_cgen_expand_macros_and_parse_operand
645  (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
646
647static char *
648str_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
662static const macro *
663lookup_macro (const char *name)
664{
665  const 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
674static char *
675expand_macro (arg *args, int narg, const 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
716static char *
717expand_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  const 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		  /* Fall through.  */
794		default:
795		  args[narg].len++;
796		  break;
797		}
798	    }
799	  else
800	    {
801	      if (*in == ')')
802		depth--;
803	      if (narg > -1)
804		args[narg].len++;
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
823const char * mep_cgen_parse_operand
824  (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
825
826const char *
827mep_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  free (hold);
858
859  return errmsg;
860}
861
862#define CGEN_ASM_INIT_HOOK (cd->parse_operand = mep_cgen_expand_macros_and_parse_operand);
863
864/* -- dis.c */
865
866#include "elf/mep.h"
867#include "elf-bfd.h"
868
869#define CGEN_VALIDATE_INSN_SUPPORTED
870
871static void
872print_tpreg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, void *dis_info,
873	     CGEN_KEYWORD *table ATTRIBUTE_UNUSED, long val ATTRIBUTE_UNUSED,
874	     unsigned int flags ATTRIBUTE_UNUSED)
875{
876  disassemble_info *info = (disassemble_info *) dis_info;
877
878  (*info->fprintf_func) (info->stream, "$tp");
879}
880
881static void
882print_spreg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, void *dis_info,
883	     CGEN_KEYWORD *table ATTRIBUTE_UNUSED, long val ATTRIBUTE_UNUSED,
884	     unsigned int flags ATTRIBUTE_UNUSED)
885{
886  disassemble_info *info = (disassemble_info *) dis_info;
887
888  (*info->fprintf_func) (info->stream, "$sp");
889}
890
891/* begin-cop-ip-print-handlers */
892static void
893print_ivc2_cr (CGEN_CPU_DESC,
894	void *,
895	CGEN_KEYWORD *,
896	long,
897	unsigned int) ATTRIBUTE_UNUSED;
898static void
899print_ivc2_cr (CGEN_CPU_DESC cd,
900	void *dis_info,
901	CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED,
902	long value,
903	unsigned int attrs)
904{
905  print_keyword (cd, dis_info, & mep_cgen_opval_h_cr_ivc2, value, attrs);
906}
907static void
908print_ivc2_ccr (CGEN_CPU_DESC,
909	void *,
910	CGEN_KEYWORD *,
911	long,
912	unsigned int) ATTRIBUTE_UNUSED;
913static void
914print_ivc2_ccr (CGEN_CPU_DESC cd,
915	void *dis_info,
916	CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED,
917	long value,
918	unsigned int attrs)
919{
920  print_keyword (cd, dis_info, & mep_cgen_opval_h_ccr_ivc2, value, attrs);
921}
922/* end-cop-ip-print-handlers */
923
924/************************************************************\
925*********************** Experimental *************************
926\************************************************************/
927
928#undef  CGEN_PRINT_INSN
929#define CGEN_PRINT_INSN mep_print_insn
930
931static int
932mep_print_vliw_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info,
933		      bfd_byte *buf, int corelength, int copro1length,
934		      int copro2length ATTRIBUTE_UNUSED)
935{
936  int i;
937  int status = 0;
938  /* char insnbuf[CGEN_MAX_INSN_SIZE]; */
939  bfd_byte insnbuf[64];
940
941  /* If corelength > 0 then there is a core insn present. It
942     will be at the beginning of the buffer.  After printing
943     the core insn, we need to print the + on the next line.  */
944  if (corelength > 0)
945    {
946      int my_status = 0;
947
948      for (i = 0; i < corelength; i++ )
949	insnbuf[i] = buf[i];
950      cd->isas = & MEP_CORE_ISA;
951
952      my_status = print_insn (cd, pc, info, insnbuf, corelength);
953      if (my_status != corelength)
954	{
955	  (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
956	  my_status = corelength;
957	}
958      status += my_status;
959
960      /* Print the + to indicate that the following copro insn is
961	 part of a vliw group.  */
962      if (copro1length > 0)
963	(*info->fprintf_func) (info->stream, " + ");
964    }
965
966  /* Now all that is left to be processed is the coprocessor insns
967     In vliw mode, there will always be one.  Its positioning will
968     be from byte corelength to byte corelength+copro1length -1.
969     No need to check for existence.   Also, the first vliw insn,
970     will, as spec'd, always be at least as long as the core insn
971     so we don't need to flush the buffer.  */
972  if (copro1length > 0)
973    {
974      int my_status = 0;
975
976      for (i = corelength; i < corelength + copro1length; i++ )
977	insnbuf[i - corelength] = buf[i];
978
979      switch (copro1length)
980	{
981	case 0:
982	  break;
983	case 2:
984	  cd->isas = & MEP_COP16_ISA;
985	  break;
986	case 4:
987	  cd->isas = & MEP_COP32_ISA;
988	  break;
989	case 6:
990	  cd->isas = & MEP_COP48_ISA;
991	  break;
992	case 8:
993	  cd->isas = & MEP_COP64_ISA;
994	  break;
995	default:
996	  /* Shouldn't be anything but 16,32,48,64.  */
997	  break;
998	}
999
1000      my_status = print_insn (cd, pc, info, insnbuf, copro1length);
1001
1002      if (my_status != copro1length)
1003	{
1004	  (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
1005	  my_status = copro1length;
1006	}
1007      status += my_status;
1008    }
1009
1010#if 0
1011  /* Now we need to process the second copro insn if it exists. We
1012     have no guarantee that the second copro insn will be longer
1013     than the first, so we have to flush the buffer if we are have
1014     a second copro insn to process.  If present, this insn will
1015     be in the position from byte corelength+copro1length to byte
1016     corelength+copro1length+copro2length-1 (which better equal 8
1017     or else we're in big trouble.  */
1018  if (copro2length > 0)
1019    {
1020      int my_status = 0;
1021
1022      for (i = 0; i < 64 ; i++)
1023	insnbuf[i] = 0;
1024
1025      for (i = corelength + copro1length; i < 64; i++)
1026	insnbuf[i - (corelength + copro1length)] = buf[i];
1027
1028      switch (copro2length)
1029	{
1030	case 2:
1031	  cd->isas = 1 << ISA_EXT_COP1_16;
1032	  break;
1033	case 4:
1034	  cd->isas = 1 << ISA_EXT_COP1_32;
1035	  break;
1036	case 6:
1037	  cd->isas = 1 << ISA_EXT_COP1_48;
1038	  break;
1039	case 8:
1040	  cd->isas = 1 << ISA_EXT_COP1_64;
1041	  break;
1042	default:
1043	  /* Shouldn't be anything but 16,32,48,64.  */
1044	  break;
1045	}
1046
1047      my_status = print_insn (cd, pc, info, insnbuf, copro2length);
1048
1049      if (my_status != copro2length)
1050	{
1051	  (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
1052	  my_status = copro2length;
1053	}
1054
1055      status += my_status;
1056    }
1057#endif
1058
1059  /* Status should now be the number of bytes that were printed
1060     which should be 4 for VLIW32 mode and 64 for VLIW64 mode.  */
1061
1062  if ((!MEP_VLIW64 && (status != 4)) || (MEP_VLIW64 && (status != 8)))
1063    return -1;
1064  else
1065    return status;
1066}
1067
1068/* The two functions mep_examine_vliw[32,64]_insns are used find out
1069   which vliw combinaion (16 bit core with 48 bit copro, 32 bit core
1070   with 32 bit copro, etc.) is present.  Later on, when internally
1071   parallel coprocessors are handled, only these functions should
1072   need to be changed.
1073
1074   At this time only the following combinations are supported:
1075
1076   VLIW32 Mode:
1077   16 bit core insn (core) and 16 bit coprocessor insn (cop1)
1078   32 bit core insn (core)
1079   32 bit coprocessor insn (cop1)
1080   Note: As of this time, I do not believe we have enough information
1081         to distinguish a 32 bit core insn from a 32 bit cop insn. Also,
1082         no 16 bit coprocessor insns have been specified.
1083
1084   VLIW64 Mode:
1085   16 bit core insn (core) and 48 bit coprocessor insn (cop1)
1086   32 bit core insn (core) and 32 bit coprocessor insn (cop1)
1087   64 bit coprocessor insn (cop1)
1088
1089   The framework for an internally parallel coprocessor is also
1090   present (2nd coprocessor insn is cop2), but at this time it
1091   is not used.  This only appears to be valid in VLIW64 mode.  */
1092
1093static int
1094mep_examine_vliw32_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
1095{
1096  int status;
1097  int buflength;
1098  int corebuflength;
1099  int cop1buflength;
1100  int cop2buflength;
1101  bfd_byte buf[CGEN_MAX_INSN_SIZE];
1102  char indicator16[1];
1103  char indicatorcop32[2];
1104
1105  /* At this time we're not supporting internally parallel coprocessors,
1106     so cop2buflength will always be 0.  */
1107  cop2buflength = 0;
1108
1109  /* Read in 32 bits.  */
1110  buflength = 4; /* VLIW insn spans 4 bytes.  */
1111  status = (*info->read_memory_func) (pc, buf, buflength, info);
1112
1113  if (status != 0)
1114    {
1115      (*info->memory_error_func) (status, pc, info);
1116      return -1;
1117    }
1118
1119  /* Put the big endian representation of the bytes to be examined
1120     in the temporary buffers for examination.  */
1121
1122  if (info->endian == BFD_ENDIAN_BIG)
1123    {
1124      indicator16[0] = buf[0];
1125      indicatorcop32[0] = buf[0];
1126      indicatorcop32[1] = buf[1];
1127    }
1128  else
1129    {
1130      indicator16[0] = buf[1];
1131      indicatorcop32[0] = buf[1];
1132      indicatorcop32[1] = buf[0];
1133    }
1134
1135  /* If the two high order bits are 00, 01 or 10, we have a 16 bit
1136     core insn and a 48 bit copro insn.  */
1137
1138  if ((indicator16[0] & 0x80) && (indicator16[0] & 0x40))
1139    {
1140      if ((indicatorcop32[0] & 0xf0) == 0xf0 && (indicatorcop32[1] & 0x07) == 0x07)
1141	{
1142	  /* We have a 32 bit copro insn.  */
1143	  corebuflength = 0;
1144	  /* All 4 4ytes are one copro insn. */
1145	  cop1buflength = 4;
1146	}
1147      else
1148	{
1149	  /* We have a 32 bit core.  */
1150	  corebuflength = 4;
1151	  cop1buflength = 0;
1152	}
1153    }
1154  else
1155    {
1156      /* We have a 16 bit core insn and a 16 bit copro insn.  */
1157      corebuflength = 2;
1158      cop1buflength = 2;
1159    }
1160
1161  /* Now we have the distrubution set.  Print them out.  */
1162  status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength,
1163				 cop1buflength, cop2buflength);
1164
1165  return status;
1166}
1167
1168static int
1169mep_examine_vliw64_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
1170{
1171  int status;
1172  int buflength;
1173  int corebuflength;
1174  int cop1buflength;
1175  int cop2buflength;
1176  bfd_byte buf[CGEN_MAX_INSN_SIZE];
1177  char indicator16[1];
1178  char indicator64[4];
1179
1180  /* At this time we're not supporting internally parallel
1181     coprocessors, so cop2buflength will always be 0.  */
1182  cop2buflength = 0;
1183
1184  /* Read in 64 bits.  */
1185  buflength = 8; /* VLIW insn spans 8 bytes.  */
1186  status = (*info->read_memory_func) (pc, buf, buflength, info);
1187
1188  if (status != 0)
1189    {
1190      (*info->memory_error_func) (status, pc, info);
1191      return -1;
1192    }
1193
1194  /* We have all 64 bits in the buffer now.  We have to figure out
1195     what combination of instruction sizes are present.  The two
1196     high order bits will indicate whether or not we have a 16 bit
1197     core insn or not.  If not, then we have to look at the 7,8th
1198     bytes to tell whether we have 64 bit copro insn or a 32 bit
1199     core insn with a 32 bit copro insn.  Endianness will make a
1200     difference here.  */
1201
1202  /* Put the big endian representation of the bytes to be examined
1203     in the temporary buffers for examination.  */
1204
1205  /* indicator16[0] = buf[0];  */
1206  if (info->endian == BFD_ENDIAN_BIG)
1207    {
1208      indicator16[0] = buf[0];
1209      indicator64[0] = buf[0];
1210      indicator64[1] = buf[1];
1211      indicator64[2] = buf[2];
1212      indicator64[3] = buf[3];
1213    }
1214  else
1215    {
1216      indicator16[0] = buf[1];
1217      indicator64[0] = buf[1];
1218      indicator64[1] = buf[0];
1219      indicator64[2] = buf[3];
1220      indicator64[3] = buf[2];
1221    }
1222
1223  /* If the two high order bits are 00, 01 or 10, we have a 16 bit
1224     core insn and a 48 bit copro insn.  */
1225
1226  if ((indicator16[0] & 0x80) && (indicator16[0] & 0x40))
1227    {
1228      if ((indicator64[0] & 0xf0) == 0xf0 && (indicator64[1] & 0x07) == 0x07
1229	  && ((indicator64[2] & 0xfe) != 0xf0 || (indicator64[3] & 0xf4) != 0))
1230	{
1231	  /* We have a 64 bit copro insn.  */
1232	  corebuflength = 0;
1233	  /* All 8 bytes are one copro insn.  */
1234	  cop1buflength = 8;
1235	}
1236      else
1237	{
1238	  /* We have a 32 bit core insn and a 32 bit copro insn.  */
1239	  corebuflength = 4;
1240	  cop1buflength = 4;
1241	}
1242    }
1243  else
1244    {
1245      /* We have a 16 bit core insn and a 48 bit copro insn.  */
1246      corebuflength = 2;
1247      cop1buflength = 6;
1248    }
1249
1250  /* Now we have the distrubution set.  Print them out. */
1251  status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength,
1252				 cop1buflength, cop2buflength);
1253
1254  return status;
1255}
1256
1257#ifdef MEP_IVC2_SUPPORTED
1258
1259static int
1260print_slot_insn (CGEN_CPU_DESC cd,
1261		 bfd_vma pc,
1262		 disassemble_info *info,
1263		 SLOTS_ATTR slot,
1264		 bfd_byte *buf)
1265{
1266  const CGEN_INSN_LIST *insn_list;
1267  CGEN_INSN_INT insn_value;
1268  CGEN_EXTRACT_INFO ex_info;
1269
1270  insn_value = cgen_get_insn_value (cd, buf, 32, cd->insn_endian);
1271
1272  /* Fill in ex_info fields like read_insn would.  Don't actually call
1273     read_insn, since the incoming buffer is already read (and possibly
1274     modified a la m32r).  */
1275  ex_info.valid = (1 << 8) - 1;
1276  ex_info.dis_info = info;
1277  ex_info.insn_bytes = buf;
1278
1279  /* The instructions are stored in hash lists.
1280     Pick the first one and keep trying until we find the right one.  */
1281
1282  insn_list = CGEN_DIS_LOOKUP_INSN (cd, (char *) buf, insn_value);
1283  while (insn_list != NULL)
1284    {
1285      const CGEN_INSN *insn = insn_list->insn;
1286      CGEN_FIELDS fields;
1287      int length;
1288
1289      if ((CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG)
1290	   && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG) != MEP_CONFIG)
1291	  || ! (CGEN_ATTR_CGEN_INSN_SLOTS_VALUE (CGEN_INSN_ATTRS (insn)) & (1 << slot)))
1292	{
1293	  insn_list = CGEN_DIS_NEXT_INSN (insn_list);
1294	  continue;
1295	}
1296
1297      if ((insn_value & CGEN_INSN_BASE_MASK (insn))
1298	  == CGEN_INSN_BASE_VALUE (insn))
1299	{
1300	  /* Printing is handled in two passes.  The first pass parses the
1301	     machine insn and extracts the fields.  The second pass prints
1302	     them.  */
1303
1304	  length = CGEN_EXTRACT_FN (cd, insn)
1305	    (cd, insn, &ex_info, insn_value, &fields, pc);
1306
1307	  /* Length < 0 -> error.  */
1308	  if (length < 0)
1309	    return length;
1310	  if (length > 0)
1311	    {
1312	      CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
1313	      /* Length is in bits, result is in bytes.  */
1314	      return length / 8;
1315	    }
1316	}
1317
1318      insn_list = CGEN_DIS_NEXT_INSN (insn_list);
1319    }
1320
1321  if (slot == SLOTS_P0S)
1322    (*info->fprintf_func) (info->stream, "*unknown-p0s*");
1323  else if (slot == SLOTS_P0)
1324    (*info->fprintf_func) (info->stream, "*unknown-p0*");
1325  else if (slot == SLOTS_P1)
1326    (*info->fprintf_func) (info->stream, "*unknown-p1*");
1327  else if (slot == SLOTS_C3)
1328    (*info->fprintf_func) (info->stream, "*unknown-c3*");
1329  return 0;
1330}
1331
1332static int
1333mep_examine_ivc2_insns (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, bfd_vma pc ATTRIBUTE_UNUSED, disassemble_info *info ATTRIBUTE_UNUSED)
1334{
1335  int status;
1336  int buflength;
1337  bfd_byte buf[8];
1338  bfd_byte insn[8];
1339  int e;
1340
1341  /* Read in 64 bits.  */
1342  buflength = 8; /* VLIW insn spans 8 bytes.  */
1343  status = (*info->read_memory_func) (pc, buf, buflength, info);
1344
1345  if (status != 0)
1346    {
1347      (*info->memory_error_func) (status, pc, info);
1348      return -1;
1349    }
1350
1351  if (info->endian == BFD_ENDIAN_LITTLE)
1352    e = 1;
1353  else
1354    e = 0;
1355
1356  if (((unsigned char)buf[0^e] & 0xf0) < 0xc0)
1357    {
1358      /*      <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */
1359      /* V1   [-----core-----][--------p0s-------][------------p1------------] */
1360
1361      print_insn (cd, pc, info, buf, 2);
1362
1363      insn[0^e] = 0;
1364      insn[1^e] = buf[2^e];
1365      insn[2^e] = buf[3^e];
1366      insn[3^e] = buf[4^e] & 0xf0;
1367      (*info->fprintf_func) (info->stream, " + ");
1368      print_slot_insn (cd, pc, info, SLOTS_P0S, insn);
1369
1370      insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4;
1371      insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4;
1372      insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4;
1373      insn[3^e] = buf[7^e] << 4;
1374      (*info->fprintf_func) (info->stream, " + ");
1375      print_slot_insn (cd, pc, info, SLOTS_P1, insn);
1376    }
1377  else if ((buf[0^e] & 0xf0) == 0xf0 && (buf[1^e] & 0x0f) == 0x07)
1378    {
1379      /*      <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */
1380      /* V3   1111[--p0--]0111[--------p0--------][------------p1------------] */
1381      /*                                          00000000111111112222222233333333 */
1382
1383      insn[0^e] = buf[0^e] << 4 | buf[1^e] >> 4;
1384      insn[1^e] = buf[2^e];
1385      insn[2^e] = buf[3^e];
1386      insn[3^e] = buf[4^e] & 0xf0;
1387      print_slot_insn (cd, pc, info, SLOTS_P0, insn);
1388
1389      insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4;
1390      insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4;
1391      insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4;
1392      insn[3^e] = buf[7^e] << 4;
1393      (*info->fprintf_func) (info->stream, " + ");
1394      print_slot_insn (cd, pc, info, SLOTS_P1, insn);
1395    }
1396  else
1397    {
1398      /*      <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */
1399      /* V2   [-------------core-------------]xxxx[------------p1------------] */
1400      print_insn (cd, pc, info, buf, 4);
1401
1402      insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4;
1403      insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4;
1404      insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4;
1405      insn[3^e] = buf[7^e] << 4;
1406      (*info->fprintf_func) (info->stream, " + ");
1407      print_slot_insn (cd, pc, info, SLOTS_P1, insn);
1408    }
1409
1410  return 8;
1411}
1412
1413#endif /* MEP_IVC2_SUPPORTED */
1414
1415/* This is a hack.  SID calls this to update the disassembler as the
1416   CPU changes modes.  */
1417static int mep_ivc2_disassemble_p = 0;
1418static int mep_ivc2_vliw_disassemble_p = 0;
1419
1420void
1421mep_print_insn_set_ivc2_mode (int ivc2_p, int vliw_p, int cfg_idx);
1422void
1423mep_print_insn_set_ivc2_mode (int ivc2_p, int vliw_p, int cfg_idx)
1424{
1425  mep_ivc2_disassemble_p = ivc2_p;
1426  mep_ivc2_vliw_disassemble_p = vliw_p;
1427  mep_config_index = cfg_idx;
1428}
1429
1430static int
1431mep_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
1432{
1433  int status;
1434  int cop_type;
1435  int ivc2 = 0;
1436  static CGEN_ATTR_VALUE_BITSET_TYPE *ivc2_core_isa = NULL;
1437
1438  if (ivc2_core_isa == NULL)
1439    {
1440      /* IVC2 has some core-only coprocessor instructions.  We
1441	 use COP32 to flag those, and COP64 for the VLIW ones,
1442	 since they have the same names.  */
1443      ivc2_core_isa = cgen_bitset_create (MAX_ISAS);
1444    }
1445
1446  /* Extract and adapt to configuration number, if available. */
1447  if (info->section && info->section->owner)
1448    {
1449      bfd *abfd = info->section->owner;
1450      if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
1451	{
1452	  mep_config_index = abfd->tdata.elf_obj_data->elf_header->e_flags & EF_MEP_INDEX_MASK;
1453	  /* This instantly redefines MEP_CONFIG, MEP_OMASK, .... MEP_VLIW64 */
1454
1455	  /* mep_config_map is a variable sized array, so we do not know how big it is.
1456	     The only safe way to check the index therefore is to iterate over the array.
1457	     We do know that the last entry is all null.  */
1458	  int i;
1459	  for (i = 0; i <= mep_config_index; i++)
1460	    if (mep_config_map[i].name == NULL)
1461	      break;
1462
1463	  if (i < mep_config_index)
1464	    {
1465	      opcodes_error_handler (_("illegal MEP INDEX setting '%x' in ELF header e_flags field"), mep_config_index);
1466	      mep_config_index = 0;
1467	    }
1468
1469	  cop_type = abfd->tdata.elf_obj_data->elf_header->e_flags & EF_MEP_COP_MASK;
1470	  if (cop_type == EF_MEP_COP_IVC2)
1471	    ivc2 = 1;
1472	}
1473    }
1474
1475  /* Picking the right ISA bitmask for the current context is tricky.  */
1476  if (info->section)
1477    {
1478      if (info->section->flags & SEC_MEP_VLIW)
1479	{
1480#ifdef MEP_IVC2_SUPPORTED
1481	  if (ivc2)
1482	    {
1483	      /* ivc2 has its own way of selecting its functions.  */
1484	      cd->isas = & MEP_CORE_ISA;
1485	      status = mep_examine_ivc2_insns (cd, pc, info);
1486	    }
1487	  else
1488#endif
1489	    /* Are we in 32 or 64 bit vliw mode?  */
1490	    if (MEP_VLIW64)
1491	      status = mep_examine_vliw64_insns (cd, pc, info);
1492	    else
1493	      status = mep_examine_vliw32_insns (cd, pc, info);
1494	  /* Both the above branches set their own isa bitmasks.  */
1495	}
1496      else
1497	{
1498	  if (ivc2)
1499	    {
1500	      cgen_bitset_clear (ivc2_core_isa);
1501	      cgen_bitset_union (ivc2_core_isa, &MEP_CORE_ISA, ivc2_core_isa);
1502	      cgen_bitset_union (ivc2_core_isa, &MEP_COP32_ISA, ivc2_core_isa);
1503	      cd->isas = ivc2_core_isa;
1504	    }
1505	  else
1506	    cd->isas = & MEP_CORE_ISA;
1507	  status = default_print_insn (cd, pc, info);
1508	}
1509    }
1510  else /* sid or gdb */
1511    {
1512#ifdef MEP_IVC2_SUPPORTED
1513      if (mep_ivc2_disassemble_p)
1514	{
1515	  if (mep_ivc2_vliw_disassemble_p)
1516	    {
1517	      cd->isas = & MEP_CORE_ISA;
1518	      status = mep_examine_ivc2_insns (cd, pc, info);
1519	      return status;
1520	    }
1521	  else
1522	    {
1523	      if (ivc2)
1524		cd->isas = ivc2_core_isa;
1525	    }
1526	}
1527#endif
1528
1529      status = default_print_insn (cd, pc, info);
1530    }
1531
1532  return status;
1533}
1534
1535
1536/* -- opc.c */
1537#include "elf/mep.h"
1538
1539/* A mask for all ISAs executed by the core. */
1540CGEN_ATTR_VALUE_BITSET_TYPE mep_all_core_isas_mask = {0, 0};
1541
1542void
1543init_mep_all_core_isas_mask (void)
1544{
1545  if (mep_all_core_isas_mask.length != 0)
1546    return;
1547  cgen_bitset_init (& mep_all_core_isas_mask, ISA_MAX);
1548  cgen_bitset_set (& mep_all_core_isas_mask, ISA_MEP);
1549  /* begin-all-core-isas */
1550  cgen_bitset_add (& mep_all_core_isas_mask, ISA_EXT_CORE1);
1551  /* end-all-core-isas */
1552}
1553
1554CGEN_ATTR_VALUE_BITSET_TYPE mep_all_cop_isas_mask = {0, 0};
1555
1556void
1557init_mep_all_cop_isas_mask (void)
1558{
1559  if (mep_all_cop_isas_mask.length != 0)
1560    return;
1561  cgen_bitset_init (& mep_all_cop_isas_mask, ISA_MAX);
1562  /* begin-all-cop-isas */
1563  cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_16);
1564  cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_32);
1565  cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_48);
1566  cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_64);
1567  /* end-all-cop-isas */
1568}
1569
1570int
1571mep_insn_supported_by_isa (const CGEN_INSN *insn, CGEN_ATTR_VALUE_BITSET_TYPE *isa_mask)
1572{
1573  CGEN_BITSET insn_isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA);
1574  return cgen_bitset_intersect_p (& insn_isas, isa_mask);
1575}
1576
1577#define OPTION_MASK \
1578	( (1 << CGEN_INSN_OPTIONAL_BIT_INSN) \
1579	| (1 << CGEN_INSN_OPTIONAL_MUL_INSN) \
1580	| (1 << CGEN_INSN_OPTIONAL_DIV_INSN) \
1581	| (1 << CGEN_INSN_OPTIONAL_DEBUG_INSN) \
1582	| (1 << CGEN_INSN_OPTIONAL_LDZ_INSN) \
1583	| (1 << CGEN_INSN_OPTIONAL_ABS_INSN) \
1584	| (1 << CGEN_INSN_OPTIONAL_AVE_INSN) \
1585	| (1 << CGEN_INSN_OPTIONAL_MINMAX_INSN) \
1586	| (1 << CGEN_INSN_OPTIONAL_CLIP_INSN) \
1587	| (1 << CGEN_INSN_OPTIONAL_SAT_INSN) \
1588	| (1 << CGEN_INSN_OPTIONAL_UCI_INSN) \
1589	| (1 << CGEN_INSN_OPTIONAL_DSP_INSN) \
1590	| (1 << CGEN_INSN_OPTIONAL_CP_INSN) \
1591	| (1 << CGEN_INSN_OPTIONAL_CP64_INSN) )
1592
1593
1594mep_config_map_struct mep_config_map[] =
1595{
1596  /* config-map-start */
1597  /* Default entry: first module, with all options enabled. */
1598  { "", 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) },
1599  { "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" },
1600	  0
1601	| (1 << CGEN_INSN_OPTIONAL_CP_INSN)
1602	| (1 << CGEN_INSN_OPTIONAL_CP64_INSN)
1603	| (1 << CGEN_INSN_OPTIONAL_MUL_INSN)
1604	| (1 << CGEN_INSN_OPTIONAL_DIV_INSN)
1605	| (1 << CGEN_INSN_OPTIONAL_BIT_INSN)
1606	| (1 << CGEN_INSN_OPTIONAL_LDZ_INSN)
1607	| (1 << CGEN_INSN_OPTIONAL_ABS_INSN)
1608	| (1 << CGEN_INSN_OPTIONAL_AVE_INSN)
1609	| (1 << CGEN_INSN_OPTIONAL_MINMAX_INSN)
1610	| (1 << CGEN_INSN_OPTIONAL_CLIP_INSN)
1611	| (1 << CGEN_INSN_OPTIONAL_SAT_INSN) },
1612  /* config-map-end */
1613  { 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, 0 }
1614};
1615
1616int mep_config_index = 0;
1617
1618static int
1619check_configured_mach (int machs)
1620{
1621  /* All base insns are supported.  */
1622  int mach = 1 << MACH_BASE;
1623  switch (MEP_CPU & EF_MEP_CPU_MASK)
1624    {
1625    case EF_MEP_CPU_C2:
1626    case EF_MEP_CPU_C3:
1627      mach |= (1 << MACH_MEP);
1628      break;
1629    case EF_MEP_CPU_H1:
1630      mach |= (1 << MACH_H1);
1631      break;
1632    case EF_MEP_CPU_C5:
1633      mach |= (1 << MACH_MEP);
1634      mach |= (1 << MACH_C5);
1635      break;
1636    default:
1637      break;
1638    }
1639  return machs & mach;
1640}
1641
1642int
1643mep_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
1644{
1645  int iconfig = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG);
1646  int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
1647  CGEN_BITSET isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA);
1648  int ok1;
1649  int ok2;
1650  int ok3;
1651
1652  /* If the insn has an option bit set that we don't want,
1653     reject it.  */
1654  if (CGEN_INSN_ATTRS (insn)->bool_ & OPTION_MASK & ~MEP_OMASK)
1655    return 0;
1656
1657  /* If attributes are absent, assume no restriction. */
1658  if (machs == 0)
1659    machs = ~0;
1660
1661  ok1 = ((machs & cd->machs) && cgen_bitset_intersect_p (& isas, cd->isas));
1662  /* If the insn is config-specific, make sure it matches.  */
1663  ok2 =  (iconfig == 0 || iconfig == MEP_CONFIG);
1664  /* Make sure the insn is supported by the configured mach  */
1665  ok3 = check_configured_mach (machs);
1666
1667  return (ok1 && ok2 && ok3);
1668}
1669
1670int
1671mep_cgen_insn_supported_asm (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
1672{
1673#ifdef MEP_IVC2_SUPPORTED
1674  /* If we're assembling VLIW packets, ignore the 12-bit BSR as we
1675     can't relax that.  The 24-bit BSR is matched instead.  */
1676  if (insn->base->num == MEP_INSN_BSR12
1677      && cgen_bitset_contains (cd->isas, ISA_EXT_COP1_64))
1678    return 0;
1679#endif
1680
1681  return mep_cgen_insn_supported (cd, insn);
1682}
1683