[gdb/dap] Fix exit race
[binutils-gdb.git] / cpu / mep.opc
blobebe119ae339ec087e79a620c03485ed28fec00d3
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     return _("invalid %function() here");
354   return cgen_parse_signed_integer (cd, strp, opindex, valuep);
357 static const char *
358 parse_unsigned16 (CGEN_CPU_DESC cd,
359                   const char **strp,
360                   int opindex,
361                   unsigned long *valuep)
363   return parse_lo16 (cd, strp, opindex, (long *) valuep, 0);
366 static const char *
367 parse_signed16_range (CGEN_CPU_DESC cd,
368                       const char **strp,
369                       int opindex,
370                       signed long *valuep)
372   const char *errmsg = 0;
373   signed long value;
375   errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
376   if (errmsg)
377     return errmsg;
379   if (value < -32768 || value > 32767)
380     return _("Immediate is out of range -32768 to 32767");
382   *valuep = value;
383   return 0;
386 static const char *
387 parse_unsigned16_range (CGEN_CPU_DESC cd,
388                         const char **strp,
389                         int opindex,
390                         unsigned long *valuep)
392   const char *errmsg = 0;
393   unsigned long value;
395   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
396   if (errmsg)
397     return errmsg;
399   if (value > 65535)
400     return _("Immediate is out of range 0 to 65535");
402   *valuep = value;
403   return 0;
406 /* A special case of parse_signed16 which accepts only the value zero.  */
408 static const char *
409 parse_zero (CGEN_CPU_DESC cd, const char **strp, int opindex, long *valuep)
411   const char *errmsg;
412   enum cgen_parse_operand_result result_type;
413   bfd_vma value;
415   /*fprintf(stderr, "dj: signed parse opindex `%s'\n", *strp);*/
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.  */
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     }
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     }
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     }
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     }
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     }
498   if (**strp == '%')
499     return "invalid %function() here";
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.  */
507   return errmsg;
510 static const char *
511 parse_unsigned7 (CGEN_CPU_DESC cd, const char **strp,
512                  enum cgen_operand_type opindex, unsigned long *valuep)
514   const char *errmsg;
515   bfd_vma value;
517   /* fprintf(stderr, "dj: unsigned7 parse `%s'\n", *strp); */
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     }
547   if (**strp == '%')
548     return _("invalid %function() here");
550   return parse_mep_alignu (cd, strp, opindex, valuep);
553 static ATTRIBUTE_UNUSED const char *
554 parse_cdisp10 (CGEN_CPU_DESC cd,
555                const char **strp,
556                int opindex,
557                long *valuep)
559   const char *errmsg = 0;
560   signed long value;
561   long have_zero = 0;
562   int wide = 0;
563   int alignment;
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     }
579   if ((MEP_CPU & EF_MEP_CPU_MASK) == EF_MEP_CPU_C5)
580     wide = 1;
582   if (strncmp (*strp, "0x0", 3) == 0
583       || (**strp == '0' && *(*strp + 1) != 'x'))
584     have_zero = 1;
586   errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
587   if (errmsg)
588     return errmsg;
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     }
601   if (value & ((1<<alignment)-1))
602     return _("Value is not aligned enough");
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"));
609   *valuep = value;
610   return 0;
613 /* BEGIN LIGHTWEIGHT MACRO PROCESSOR.  */
615 #define MAXARGS 9
617 typedef struct
619   char *name;
620   char *expansion;
621 }  macro;
623 typedef struct
625   const char *start;
626   int len;
627 } arg;
629 static macro const macros[] =
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 }
641 static char  * expand_string    (const char *, int);
643 static const char *
644 mep_cgen_expand_macros_and_parse_operand
645   (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
647 static char *
648 str_append (char *dest, const char *input, int len)
650   char *new_dest;
651   int oldlen;
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);
662 static const macro *
663 lookup_macro (const char *name)
665   const macro *m;
667   for (m = macros; m->name; ++m)
668     if (strncmp (m->name, name, strlen(m->name)) == 0)
669       return m;
671   return 0;
674 static char *
675 expand_macro (arg *args, int narg, const macro *mac)
677   char *result = 0, *rescanned_result = 0;
678   char *e = mac->expansion;
679   char *mark = e;
680   int mac_arg = 0;
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     }
700   if (mark != e)
701     result = str_append (result, mark, e - mark);
703   if (result)
704     {
705       rescanned_result = expand_string (result, 0);
706       free (result);
707       return rescanned_result;
708     }
709   else
710     return result;
713 #define IN_TEXT 0
714 #define IN_ARGS 1
716 static char *
717 expand_string (const char *in, int first_only)
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;
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     }
810   if (mark != in)
811     result = str_append (result, mark, in - mark);
813   return result;
816 #undef IN_ARGS
817 #undef IN_TEXT
818 #undef MAXARGS
821 /* END LIGHTWEIGHT MACRO PROCESSOR.  */
823 const char * mep_cgen_parse_operand
824   (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
826 const char *
827 mep_cgen_expand_macros_and_parse_operand (CGEN_CPU_DESC cd, int opindex,
828                                           const char ** strp_in, CGEN_FIELDS * fields)
830   const char * errmsg = NULL;
831   char *str = 0, *hold = 0;
832   const char **strp = 0;
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); */
838   hold = str;
839   strp = (const char **)(&str);
841   errmsg = mep_cgen_parse_operand (cd, opindex, strp, fields);
843   /* Now work out the advance.  */
844   if (strlen (str) == 0)
845     *strp_in += strlen (*strp_in);
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     }
857   free (hold);
859   return errmsg;
862 #define CGEN_ASM_INIT_HOOK (cd->parse_operand = mep_cgen_expand_macros_and_parse_operand);
864 /* -- dis.c */
866 #include "elf/mep.h"
867 #include "elf-bfd.h"
869 #define CGEN_VALIDATE_INSN_SUPPORTED
871 static void
872 print_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)
876   disassemble_info *info = (disassemble_info *) dis_info;
878   (*info->fprintf_func) (info->stream, "$tp");
881 static void
882 print_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)
886   disassemble_info *info = (disassemble_info *) dis_info;
888   (*info->fprintf_func) (info->stream, "$sp");
891 /* begin-cop-ip-print-handlers */
892 static void
893 print_ivc2_cr (CGEN_CPU_DESC,
894         void *,
895         CGEN_KEYWORD *,
896         long,
897         unsigned int) ATTRIBUTE_UNUSED;
898 static void
899 print_ivc2_cr (CGEN_CPU_DESC cd,
900         void *dis_info,
901         CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED,
902         long value,
903         unsigned int attrs)
905   print_keyword (cd, dis_info, & mep_cgen_opval_h_cr_ivc2, value, attrs);
907 static void
908 print_ivc2_ccr (CGEN_CPU_DESC,
909         void *,
910         CGEN_KEYWORD *,
911         long,
912         unsigned int) ATTRIBUTE_UNUSED;
913 static void
914 print_ivc2_ccr (CGEN_CPU_DESC cd,
915         void *dis_info,
916         CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED,
917         long value,
918         unsigned int attrs)
920   print_keyword (cd, dis_info, & mep_cgen_opval_h_ccr_ivc2, value, attrs);
922 /* end-cop-ip-print-handlers */
924 /************************************************************\
925 *********************** Experimental *************************
926 \************************************************************/
928 #undef  CGEN_PRINT_INSN
929 #define CGEN_PRINT_INSN mep_print_insn
931 static int
932 mep_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)
936   int i;
937   int status = 0;
938   /* char insnbuf[CGEN_MAX_INSN_SIZE]; */
939   bfd_byte insnbuf[64];
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;
948       for (i = 0; i < corelength; i++ )
949         insnbuf[i] = buf[i];
950       cd->isas = & MEP_CORE_ISA;
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;
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     }
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;
976       for (i = corelength; i < corelength + copro1length; i++ )
977         insnbuf[i - corelength] = buf[i];
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         }
1000       my_status = print_insn (cd, pc, info, insnbuf, copro1length);
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     }
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;
1022       for (i = 0; i < 64 ; i++)
1023         insnbuf[i] = 0;
1025       for (i = corelength + copro1length; i < 64; i++)
1026         insnbuf[i - (corelength + copro1length)] = buf[i];
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         }
1047       my_status = print_insn (cd, pc, info, insnbuf, copro2length);
1049       if (my_status != copro2length)
1050         {
1051           (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
1052           my_status = copro2length;
1053         }
1055       status += my_status;
1056     }
1057 #endif
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.  */
1062   if ((!MEP_VLIW64 && (status != 4)) || (MEP_VLIW64 && (status != 8)))
1063     return -1;
1064   else
1065     return status;
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.
1074    At this time only the following combinations are supported:
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.
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)
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.  */
1093 static int
1094 mep_examine_vliw32_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
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];
1105   /* At this time we're not supporting internally parallel coprocessors,
1106      so cop2buflength will always be 0.  */
1107   cop2buflength = 0;
1109   /* Read in 32 bits.  */
1110   buflength = 4; /* VLIW insn spans 4 bytes.  */
1111   status = (*info->read_memory_func) (pc, buf, buflength, info);
1113   if (status != 0)
1114     {
1115       (*info->memory_error_func) (status, pc, info);
1116       return -1;
1117     }
1119   /* Put the big endian representation of the bytes to be examined
1120      in the temporary buffers for examination.  */
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     }
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.  */
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     }
1161   /* Now we have the distrubution set.  Print them out.  */
1162   status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength,
1163                                  cop1buflength, cop2buflength);
1165   return status;
1168 static int
1169 mep_examine_vliw64_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
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];
1180   /* At this time we're not supporting internally parallel
1181      coprocessors, so cop2buflength will always be 0.  */
1182   cop2buflength = 0;
1184   /* Read in 64 bits.  */
1185   buflength = 8; /* VLIW insn spans 8 bytes.  */
1186   status = (*info->read_memory_func) (pc, buf, buflength, info);
1188   if (status != 0)
1189     {
1190       (*info->memory_error_func) (status, pc, info);
1191       return -1;
1192     }
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.  */
1202   /* Put the big endian representation of the bytes to be examined
1203      in the temporary buffers for examination.  */
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     }
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.  */
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     }
1250   /* Now we have the distrubution set.  Print them out. */
1251   status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength,
1252                                  cop1buflength, cop2buflength);
1254   return status;
1257 #ifdef MEP_IVC2_SUPPORTED
1259 static int
1260 print_slot_insn (CGEN_CPU_DESC cd,
1261                  bfd_vma pc,
1262                  disassemble_info *info,
1263                  SLOTS_ATTR slot,
1264                  bfd_byte *buf)
1266   const CGEN_INSN_LIST *insn_list;
1267   CGEN_INSN_INT insn_value;
1268   CGEN_EXTRACT_INFO ex_info;
1270   insn_value = cgen_get_insn_value (cd, buf, 32, cd->insn_endian);
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;
1279   /* The instructions are stored in hash lists.
1280      Pick the first one and keep trying until we find the right one.  */
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;
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         }
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.  */
1304           length = CGEN_EXTRACT_FN (cd, insn)
1305             (cd, insn, &ex_info, insn_value, &fields, pc);
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         }
1318       insn_list = CGEN_DIS_NEXT_INSN (insn_list);
1319     }
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;
1332 static int
1333 mep_examine_ivc2_insns (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, bfd_vma pc ATTRIBUTE_UNUSED, disassemble_info *info ATTRIBUTE_UNUSED)
1335   int status;
1336   int buflength;
1337   bfd_byte buf[8];
1338   bfd_byte insn[8];
1339   int e;
1341   /* Read in 64 bits.  */
1342   buflength = 8; /* VLIW insn spans 8 bytes.  */
1343   status = (*info->read_memory_func) (pc, buf, buflength, info);
1345   if (status != 0)
1346     {
1347       (*info->memory_error_func) (status, pc, info);
1348       return -1;
1349     }
1351   if (info->endian == BFD_ENDIAN_LITTLE)
1352     e = 1;
1353   else
1354     e = 0;
1356   if (((unsigned char)buf[0^e] & 0xf0) < 0xc0)
1357     {
1358       /*      <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */
1359       /* V1   [-----core-----][--------p0s-------][------------p1------------] */
1361       print_insn (cd, pc, info, buf, 2);
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);
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 */
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);
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);
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     }
1410   return 8;
1413 #endif /* MEP_IVC2_SUPPORTED */
1415 /* This is a hack.  SID calls this to update the disassembler as the
1416    CPU changes modes.  */
1417 static int mep_ivc2_disassemble_p = 0;
1418 static int mep_ivc2_vliw_disassemble_p = 0;
1420 void
1421 mep_print_insn_set_ivc2_mode (int ivc2_p, int vliw_p, int cfg_idx);
1422 void
1423 mep_print_insn_set_ivc2_mode (int ivc2_p, int vliw_p, int cfg_idx)
1425   mep_ivc2_disassemble_p = ivc2_p;
1426   mep_ivc2_vliw_disassemble_p = vliw_p;
1427   mep_config_index = cfg_idx;
1430 static int
1431 mep_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
1433   int status;
1434   int cop_type;
1435   int ivc2 = 0;
1436   static CGEN_ATTR_VALUE_BITSET_TYPE *ivc2_core_isa = NULL;
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     }
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 */
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;
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             }
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     }
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
1529       status = default_print_insn (cd, pc, info);
1530     }
1532   return status;
1536 /* -- opc.c */
1537 #include "elf/mep.h"
1539 /* A mask for all ISAs executed by the core. */
1540 CGEN_ATTR_VALUE_BITSET_TYPE mep_all_core_isas_mask = {0, 0};
1542 void
1543 init_mep_all_core_isas_mask (void)
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 */
1554 CGEN_ATTR_VALUE_BITSET_TYPE mep_all_cop_isas_mask = {0, 0};
1556 void
1557 init_mep_all_cop_isas_mask (void)
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 */
1571 mep_insn_supported_by_isa (const CGEN_INSN *insn, CGEN_ATTR_VALUE_BITSET_TYPE *isa_mask)
1573   CGEN_BITSET insn_isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA);
1574   return cgen_bitset_intersect_p (& insn_isas, isa_mask);
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) )
1594 mep_config_map_struct mep_config_map[] =
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 }
1616 int mep_config_index = 0;
1618 static int
1619 check_configured_mach (int machs)
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;
1643 mep_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
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;
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;
1657   /* If attributes are absent, assume no restriction. */
1658   if (machs == 0)
1659     machs = ~0;
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);
1667   return (ok1 && ok2 && ok3);
1671 mep_cgen_insn_supported_asm (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
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
1681   return mep_cgen_insn_supported (cd, insn);