arm: Support pac_key_* register operand for MRS/MSR in Armv8.1-M Mainline
[binutils-gdb.git] / cpu / mep.opc
blob33dd63b4b9d1f3344be435eda0b58bc31755a62b
1 /* MeP opcode support.  -*- C -*-
2    Copyright 2011 Free Software Foundation, Inc.
4    Contributed by Red Hat Inc;
6    This file is part of the GNU Binutils.
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.
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.
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.  */
23 /* -- opc.h */
25 #undef  CGEN_DIS_HASH_SIZE
26 #define CGEN_DIS_HASH_SIZE 1
28 #undef  CGEN_DIS_HASH
29 #define CGEN_DIS_HASH(buffer, insn) 0
31 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
33 typedef struct
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;
49 extern mep_config_map_struct mep_config_map[];
50 extern int mep_config_index;
52 extern void init_mep_all_core_isas_mask (void);
53 extern void init_mep_all_cop_isas_mask  (void);
54 extern CGEN_ATTR_VALUE_BITSET_TYPE mep_cop_isa  (void);
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)
69 /* begin-cop-ip-supported-defines */
70 #define MEP_IVC2_SUPPORTED 1
71 /* end-cop-ip-supported-defines */
73 extern int mep_insn_supported_by_isa (const CGEN_INSN *, CGEN_ATTR_VALUE_BITSET_TYPE *);
75 /* A mask for all ISAs executed by the core.  */
76 #define MEP_ALL_CORE_ISAS_MASK mep_all_core_isas_mask
77 extern CGEN_ATTR_VALUE_BITSET_TYPE mep_all_core_isas_mask;
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) \
84 /* A mask for all ISAs executed by a VLIW coprocessor.  */
85 #define MEP_ALL_COP_ISAS_MASK mep_all_cop_isas_mask
86 extern CGEN_ATTR_VALUE_BITSET_TYPE mep_all_cop_isas_mask;
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) \
93 extern int mep_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
94 extern int mep_cgen_insn_supported_asm (CGEN_CPU_DESC, const CGEN_INSN *);
96 /* -- asm.c */
98 #include "elf/mep.h"
100 #define CGEN_VALIDATE_INSN_SUPPORTED
101 #define mep_cgen_insn_supported mep_cgen_insn_supported_asm
103        const char * parse_csrn       (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *);
104        const char * parse_tpreg      (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *);
105        const char * parse_spreg      (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *);
106        const char * parse_mep_align  (CGEN_CPU_DESC, const char **, enum cgen_operand_type, long *);
107        const char * parse_mep_alignu (CGEN_CPU_DESC, const char **, enum cgen_operand_type, unsigned long *);
108 static const char * parse_signed16   (CGEN_CPU_DESC, const char **, int, long *);
109 static const char * parse_signed16_range   (CGEN_CPU_DESC, const char **, int, long *) ATTRIBUTE_UNUSED;
110 static const char * parse_unsigned16 (CGEN_CPU_DESC, const char **, int, unsigned long *);
111 static const char * parse_unsigned16_range (CGEN_CPU_DESC, const char **, int, unsigned long *) ATTRIBUTE_UNUSED;
112 static const char * parse_lo16       (CGEN_CPU_DESC, const char **, int, long *, long);
113 static const char * parse_unsigned7  (CGEN_CPU_DESC, const char **, enum cgen_operand_type, unsigned long *);
114 static const char * parse_zero       (CGEN_CPU_DESC, const char **, int, long *);
116 const char *
117 parse_csrn (CGEN_CPU_DESC cd, const char **strp,
118             CGEN_KEYWORD *keyword_table, long *field)
120   const char *err;
121   unsigned long value;
123   err = cgen_parse_keyword (cd, strp, keyword_table, field);
124   if (!err)
125     return NULL;
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;
134 /* begin-cop-ip-parse-handlers */
135 static const char *
136 parse_ivc2_cr (CGEN_CPU_DESC,
137         const char **,
138         CGEN_KEYWORD *,
139         long *) ATTRIBUTE_UNUSED;
140 static const char *
141 parse_ivc2_cr (CGEN_CPU_DESC cd,
142         const char **strp,
143         CGEN_KEYWORD *keyword_table  ATTRIBUTE_UNUSED,
144         long *field)
146   return cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_cr_ivc2, field);
148 static const char *
149 parse_ivc2_ccr (CGEN_CPU_DESC,
150         const char **,
151         CGEN_KEYWORD *,
152         long *) ATTRIBUTE_UNUSED;
153 static const char *
154 parse_ivc2_ccr (CGEN_CPU_DESC cd,
155         const char **strp,
156         CGEN_KEYWORD *keyword_table  ATTRIBUTE_UNUSED,
157         long *field)
159   return cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_ccr_ivc2, field);
161 /* end-cop-ip-parse-handlers */
163 const char *
164 parse_tpreg (CGEN_CPU_DESC cd, const char ** strp,
165              CGEN_KEYWORD *keyword_table, long *field)
167   const char *err;
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;
177 const char *
178 parse_spreg (CGEN_CPU_DESC cd, const char ** strp,
179              CGEN_KEYWORD *keyword_table, long *field)
181   const char *err;
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;
191 const char *
192 parse_mep_align (CGEN_CPU_DESC cd, const char ** strp,
193                  enum cgen_operand_type type, long *field)
195   long lsbs = 0;
196   const char *err;
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;
248 const char *
249 parse_mep_alignu (CGEN_CPU_DESC cd, const char ** strp,
250                  enum cgen_operand_type type, unsigned long *field)
252   return parse_mep_align (cd, strp, type, (long *) field);
256 /* Handle %lo(), %tpoff(), %sdaoff(), %hi(), and other signed
257    constants in a signed context.  */
259 static const char *
260 parse_signed16 (CGEN_CPU_DESC cd,
261                 const char **strp,
262                 int opindex,
263                 long *valuep)
265   return parse_lo16 (cd, strp, opindex, valuep, 1);
268 static const char *
269 parse_lo16 (CGEN_CPU_DESC cd,
270             const char **strp,
271             int opindex,
272             long *valuep,
273             long signedp)
275   const char *errmsg;
276   enum cgen_parse_operand_result result_type;
277   bfd_vma value;
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     }
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     }
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     }
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     }
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     }
351   if (**strp == '%')
352     /* xgettext:no-c-format */
353     return _("invalid %function() here");
355   return cgen_parse_signed_integer (cd, strp, opindex, valuep);
358 static const char *
359 parse_unsigned16 (CGEN_CPU_DESC cd,
360                   const char **strp,
361                   int opindex,
362                   unsigned long *valuep)
364   return parse_lo16 (cd, strp, opindex, (long *) valuep, 0);
367 static const char *
368 parse_signed16_range (CGEN_CPU_DESC cd,
369                       const char **strp,
370                       int opindex,
371                       signed long *valuep)
373   const char *errmsg = 0;
374   signed long value;
376   errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
377   if (errmsg)
378     return errmsg;
380   if (value < -32768 || value > 32767)
381     return _("Immediate is out of range -32768 to 32767");
383   *valuep = value;
384   return 0;
387 static const char *
388 parse_unsigned16_range (CGEN_CPU_DESC cd,
389                         const char **strp,
390                         int opindex,
391                         unsigned long *valuep)
393   const char *errmsg = 0;
394   unsigned long value;
396   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
397   if (errmsg)
398     return errmsg;
400   if (value > 65535)
401     return _("Immediate is out of range 0 to 65535");
403   *valuep = value;
404   return 0;
407 /* A special case of parse_signed16 which accepts only the value zero.  */
409 static const char *
410 parse_zero (CGEN_CPU_DESC cd, const char **strp, int opindex, long *valuep)
412   const char *errmsg;
413   enum cgen_parse_operand_result result_type;
414   bfd_vma value;
416   /*fprintf(stderr, "dj: signed parse opindex `%s'\n", *strp);*/
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.  */
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     }
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     }
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     }
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     }
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     }
499   if (**strp == '%')
500     return "invalid %function() here";
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.  */
508   return errmsg;
511 static const char *
512 parse_unsigned7 (CGEN_CPU_DESC cd, const char **strp,
513                  enum cgen_operand_type opindex, unsigned long *valuep)
515   const char *errmsg;
516   bfd_vma value;
518   /* fprintf(stderr, "dj: unsigned7 parse `%s'\n", *strp); */
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     }
548   if (**strp == '%')
549     /* xgettext:no-c-format */
550     return _("invalid %function() here");
552   return parse_mep_alignu (cd, strp, opindex, valuep);
555 static ATTRIBUTE_UNUSED const char *
556 parse_cdisp10 (CGEN_CPU_DESC cd,
557                const char **strp,
558                int opindex,
559                long *valuep)
561   const char *errmsg = 0;
562   signed long value;
563   long have_zero = 0;
564   int wide = 0;
565   int alignment;
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     }
581   if ((MEP_CPU & EF_MEP_CPU_MASK) == EF_MEP_CPU_C5)
582     wide = 1;
584   if (strncmp (*strp, "0x0", 3) == 0
585       || (**strp == '0' && *(*strp + 1) != 'x'))
586     have_zero = 1;
588   errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
589   if (errmsg)
590     return errmsg;
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     }
603   if (value & ((1<<alignment)-1))
604     return _("Value is not aligned enough");
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"));
611   *valuep = value;
612   return 0;
615 /* BEGIN LIGHTWEIGHT MACRO PROCESSOR.  */
617 #define MAXARGS 9
619 typedef struct
621   char *name;
622   char *expansion;
623 }  macro;
625 typedef struct
627   const char *start;
628   int len;
629 } arg;
631 static macro const macros[] =
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 }
643 static char  * expand_string    (const char *, int);
645 static const char *
646 mep_cgen_expand_macros_and_parse_operand
647   (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
649 static char *
650 str_append (char *dest, const char *input, int len)
652   char *new_dest;
653   int oldlen;
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);
664 static const macro *
665 lookup_macro (const char *name)
667   const macro *m;
669   for (m = macros; m->name; ++m)
670     if (strncmp (m->name, name, strlen(m->name)) == 0)
671       return m;
673   return 0;
676 static char *
677 expand_macro (arg *args, int narg, const macro *mac)
679   char *result = 0, *rescanned_result = 0;
680   char *e = mac->expansion;
681   char *mark = e;
682   int mac_arg = 0;
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     }
702   if (mark != e)
703     result = str_append (result, mark, e - mark);
705   if (result)
706     {
707       rescanned_result = expand_string (result, 0);
708       free (result);
709       return rescanned_result;
710     }
711   else
712     return result;
715 #define IN_TEXT 0
716 #define IN_ARGS 1
718 static char *
719 expand_string (const char *in, int first_only)
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;
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     }
812   if (mark != in)
813     result = str_append (result, mark, in - mark);
815   return result;
818 #undef IN_ARGS
819 #undef IN_TEXT
820 #undef MAXARGS
823 /* END LIGHTWEIGHT MACRO PROCESSOR.  */
825 const char * mep_cgen_parse_operand
826   (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
828 const char *
829 mep_cgen_expand_macros_and_parse_operand (CGEN_CPU_DESC cd, int opindex,
830                                           const char ** strp_in, CGEN_FIELDS * fields)
832   const char * errmsg = NULL;
833   char *str = 0, *hold = 0;
834   const char **strp = 0;
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); */
840   hold = str;
841   strp = (const char **)(&str);
843   errmsg = mep_cgen_parse_operand (cd, opindex, strp, fields);
845   /* Now work out the advance.  */
846   if (strlen (str) == 0)
847     *strp_in += strlen (*strp_in);
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     }
859   free (hold);
861   return errmsg;
864 #define CGEN_ASM_INIT_HOOK (cd->parse_operand = mep_cgen_expand_macros_and_parse_operand);
866 /* -- dis.c */
868 #include "elf/mep.h"
869 #include "elf-bfd.h"
871 #define CGEN_VALIDATE_INSN_SUPPORTED
873 static void
874 print_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)
878   disassemble_info *info = (disassemble_info *) dis_info;
880   (*info->fprintf_func) (info->stream, "$tp");
883 static void
884 print_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)
888   disassemble_info *info = (disassemble_info *) dis_info;
890   (*info->fprintf_func) (info->stream, "$sp");
893 /* begin-cop-ip-print-handlers */
894 static void
895 print_ivc2_cr (CGEN_CPU_DESC,
896         void *,
897         CGEN_KEYWORD *,
898         long,
899         unsigned int) ATTRIBUTE_UNUSED;
900 static void
901 print_ivc2_cr (CGEN_CPU_DESC cd,
902         void *dis_info,
903         CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED,
904         long value,
905         unsigned int attrs)
907   print_keyword (cd, dis_info, & mep_cgen_opval_h_cr_ivc2, value, attrs);
909 static void
910 print_ivc2_ccr (CGEN_CPU_DESC,
911         void *,
912         CGEN_KEYWORD *,
913         long,
914         unsigned int) ATTRIBUTE_UNUSED;
915 static void
916 print_ivc2_ccr (CGEN_CPU_DESC cd,
917         void *dis_info,
918         CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED,
919         long value,
920         unsigned int attrs)
922   print_keyword (cd, dis_info, & mep_cgen_opval_h_ccr_ivc2, value, attrs);
924 /* end-cop-ip-print-handlers */
926 /************************************************************\
927 *********************** Experimental *************************
928 \************************************************************/
930 #undef  CGEN_PRINT_INSN
931 #define CGEN_PRINT_INSN mep_print_insn
933 static int
934 mep_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)
938   int i;
939   int status = 0;
940   /* char insnbuf[CGEN_MAX_INSN_SIZE]; */
941   bfd_byte insnbuf[64];
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;
950       for (i = 0; i < corelength; i++ )
951         insnbuf[i] = buf[i];
952       cd->isas = & MEP_CORE_ISA;
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;
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     }
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;
978       for (i = corelength; i < corelength + copro1length; i++ )
979         insnbuf[i - corelength] = buf[i];
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         }
1002       my_status = print_insn (cd, pc, info, insnbuf, copro1length);
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     }
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;
1024       for (i = 0; i < 64 ; i++)
1025         insnbuf[i] = 0;
1027       for (i = corelength + copro1length; i < 64; i++)
1028         insnbuf[i - (corelength + copro1length)] = buf[i];
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         }
1049       my_status = print_insn (cd, pc, info, insnbuf, copro2length);
1051       if (my_status != copro2length)
1052         {
1053           (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
1054           my_status = copro2length;
1055         }
1057       status += my_status;
1058     }
1059 #endif
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.  */
1064   if ((!MEP_VLIW64 && (status != 4)) || (MEP_VLIW64 && (status != 8)))
1065     return -1;
1066   else
1067     return status;
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.
1076    At this time only the following combinations are supported:
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.
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)
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.  */
1095 static int
1096 mep_examine_vliw32_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
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];
1107   /* At this time we're not supporting internally parallel coprocessors,
1108      so cop2buflength will always be 0.  */
1109   cop2buflength = 0;
1111   /* Read in 32 bits.  */
1112   buflength = 4; /* VLIW insn spans 4 bytes.  */
1113   status = (*info->read_memory_func) (pc, buf, buflength, info);
1115   if (status != 0)
1116     {
1117       (*info->memory_error_func) (status, pc, info);
1118       return -1;
1119     }
1121   /* Put the big endian representation of the bytes to be examined
1122      in the temporary buffers for examination.  */
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     }
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.  */
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     }
1163   /* Now we have the distrubution set.  Print them out.  */
1164   status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength,
1165                                  cop1buflength, cop2buflength);
1167   return status;
1170 static int
1171 mep_examine_vliw64_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
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];
1182   /* At this time we're not supporting internally parallel
1183      coprocessors, so cop2buflength will always be 0.  */
1184   cop2buflength = 0;
1186   /* Read in 64 bits.  */
1187   buflength = 8; /* VLIW insn spans 8 bytes.  */
1188   status = (*info->read_memory_func) (pc, buf, buflength, info);
1190   if (status != 0)
1191     {
1192       (*info->memory_error_func) (status, pc, info);
1193       return -1;
1194     }
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.  */
1204   /* Put the big endian representation of the bytes to be examined
1205      in the temporary buffers for examination.  */
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     }
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.  */
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     }
1252   /* Now we have the distrubution set.  Print them out. */
1253   status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength,
1254                                  cop1buflength, cop2buflength);
1256   return status;
1259 #ifdef MEP_IVC2_SUPPORTED
1261 static int
1262 print_slot_insn (CGEN_CPU_DESC cd,
1263                  bfd_vma pc,
1264                  disassemble_info *info,
1265                  SLOTS_ATTR slot,
1266                  bfd_byte *buf)
1268   const CGEN_INSN_LIST *insn_list;
1269   CGEN_INSN_INT insn_value;
1270   CGEN_EXTRACT_INFO ex_info;
1272   insn_value = cgen_get_insn_value (cd, buf, 32, cd->insn_endian);
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;
1281   /* The instructions are stored in hash lists.
1282      Pick the first one and keep trying until we find the right one.  */
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;
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         }
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.  */
1306           length = CGEN_EXTRACT_FN (cd, insn)
1307             (cd, insn, &ex_info, insn_value, &fields, pc);
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         }
1320       insn_list = CGEN_DIS_NEXT_INSN (insn_list);
1321     }
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;
1334 static int
1335 mep_examine_ivc2_insns (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, bfd_vma pc ATTRIBUTE_UNUSED, disassemble_info *info ATTRIBUTE_UNUSED)
1337   int status;
1338   int buflength;
1339   bfd_byte buf[8];
1340   bfd_byte insn[8];
1341   int e;
1343   /* Read in 64 bits.  */
1344   buflength = 8; /* VLIW insn spans 8 bytes.  */
1345   status = (*info->read_memory_func) (pc, buf, buflength, info);
1347   if (status != 0)
1348     {
1349       (*info->memory_error_func) (status, pc, info);
1350       return -1;
1351     }
1353   if (info->endian == BFD_ENDIAN_LITTLE)
1354     e = 1;
1355   else
1356     e = 0;
1358   if (((unsigned char)buf[0^e] & 0xf0) < 0xc0)
1359     {
1360       /*      <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */
1361       /* V1   [-----core-----][--------p0s-------][------------p1------------] */
1363       print_insn (cd, pc, info, buf, 2);
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);
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 */
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);
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);
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     }
1412   return 8;
1415 #endif /* MEP_IVC2_SUPPORTED */
1417 /* This is a hack.  SID calls this to update the disassembler as the
1418    CPU changes modes.  */
1419 static int mep_ivc2_disassemble_p = 0;
1420 static int mep_ivc2_vliw_disassemble_p = 0;
1422 void
1423 mep_print_insn_set_ivc2_mode (int ivc2_p, int vliw_p, int cfg_idx);
1424 void
1425 mep_print_insn_set_ivc2_mode (int ivc2_p, int vliw_p, int cfg_idx)
1427   mep_ivc2_disassemble_p = ivc2_p;
1428   mep_ivc2_vliw_disassemble_p = vliw_p;
1429   mep_config_index = cfg_idx;
1432 static int
1433 mep_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
1435   int status;
1436   int cop_type;
1437   int ivc2 = 0;
1438   static CGEN_ATTR_VALUE_BITSET_TYPE *ivc2_core_isa = NULL;
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     }
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 */
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;
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             }
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     }
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
1531       status = default_print_insn (cd, pc, info);
1532     }
1534   return status;
1538 /* -- opc.c */
1539 #include "elf/mep.h"
1541 /* A mask for all ISAs executed by the core. */
1542 CGEN_ATTR_VALUE_BITSET_TYPE mep_all_core_isas_mask = {0, 0};
1544 void
1545 init_mep_all_core_isas_mask (void)
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 */
1556 CGEN_ATTR_VALUE_BITSET_TYPE mep_all_cop_isas_mask = {0, 0};
1558 void
1559 init_mep_all_cop_isas_mask (void)
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 */
1573 mep_insn_supported_by_isa (const CGEN_INSN *insn, CGEN_ATTR_VALUE_BITSET_TYPE *isa_mask)
1575   CGEN_BITSET insn_isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA);
1576   return cgen_bitset_intersect_p (& insn_isas, isa_mask);
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) )
1596 mep_config_map_struct mep_config_map[] =
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 }
1618 int mep_config_index = 0;
1620 static int
1621 check_configured_mach (int machs)
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;
1645 mep_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
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;
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;
1659   /* If attributes are absent, assume no restriction. */
1660   if (machs == 0)
1661     machs = ~0;
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);
1669   return (ok1 && ok2 && ok3);
1673 mep_cgen_insn_supported_asm (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
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
1683   return mep_cgen_insn_supported (cd, insn);