Fix regeneration of ld configure and makefiles
[binutils-gdb.git] / cpu / mep.opc
blob75ae8308599a5372e7d513ca504cfc061932d569
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)
649 {  
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         }
808       ++in;
809     }
810   
811   if (mark != in)
812     result = str_append (result, mark, in - mark);
813   
814   return result;
817 #undef IN_ARGS
818 #undef IN_TEXT
819 #undef MAXARGS
822 /* END LIGHTWEIGHT MACRO PROCESSOR.  */
824 const char * mep_cgen_parse_operand
825   (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
827 const char *
828 mep_cgen_expand_macros_and_parse_operand (CGEN_CPU_DESC cd, int opindex,
829                                           const char ** strp_in, CGEN_FIELDS * fields)
831   const char * errmsg = NULL;
832   char *str = 0, *hold = 0;
833   const char **strp = 0;
835   /* Set up a new pointer to macro-expanded string.  */
836   str = expand_string (*strp_in, 1);
837   /* fprintf (stderr, " expanded <<%s>> to <<%s>>\n", *strp_in, str); */
839   hold = str;
840   strp = (const char **)(&str);
842   errmsg = mep_cgen_parse_operand (cd, opindex, strp, fields);
844   /* Now work out the advance.  */
845   if (strlen (str) == 0)
846     *strp_in += strlen (*strp_in);
848   else
849     {
850       if (strstr (*strp_in, str))
851         /* A macro-expansion was pulled off the front.  */
852         *strp_in = strstr (*strp_in, str);  
853       else
854         /* A non-macro-expansion was pulled off the front.  */
855         *strp_in += (str - hold); 
856     }
858   free (hold);
860   return errmsg;
863 #define CGEN_ASM_INIT_HOOK (cd->parse_operand = mep_cgen_expand_macros_and_parse_operand); 
865 /* -- dis.c */
867 #include "elf/mep.h"
868 #include "elf-bfd.h"
870 #define CGEN_VALIDATE_INSN_SUPPORTED
872 static void
873 print_tpreg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, void *dis_info,
874              CGEN_KEYWORD *table ATTRIBUTE_UNUSED, long val ATTRIBUTE_UNUSED,
875              unsigned int flags ATTRIBUTE_UNUSED)
877   disassemble_info *info = (disassemble_info *) dis_info;
879   (*info->fprintf_func) (info->stream, "$tp");
882 static void
883 print_spreg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, void *dis_info,
884              CGEN_KEYWORD *table ATTRIBUTE_UNUSED, long val ATTRIBUTE_UNUSED,
885              unsigned int flags ATTRIBUTE_UNUSED)
887   disassemble_info *info = (disassemble_info *) dis_info;
889   (*info->fprintf_func) (info->stream, "$sp");
892 /* begin-cop-ip-print-handlers */
893 static void
894 print_ivc2_cr (CGEN_CPU_DESC,
895         void *,
896         CGEN_KEYWORD *,
897         long,
898         unsigned int) ATTRIBUTE_UNUSED;
899 static void
900 print_ivc2_cr (CGEN_CPU_DESC cd,
901         void *dis_info,
902         CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED,
903         long value,
904         unsigned int attrs)
906   print_keyword (cd, dis_info, & mep_cgen_opval_h_cr_ivc2, value, attrs);
908 static void
909 print_ivc2_ccr (CGEN_CPU_DESC,
910         void *,
911         CGEN_KEYWORD *,
912         long,
913         unsigned int) ATTRIBUTE_UNUSED;
914 static void
915 print_ivc2_ccr (CGEN_CPU_DESC cd,
916         void *dis_info,
917         CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED,
918         long value,
919         unsigned int attrs)
921   print_keyword (cd, dis_info, & mep_cgen_opval_h_ccr_ivc2, value, attrs);
923 /* end-cop-ip-print-handlers */
925 /************************************************************\
926 *********************** Experimental *************************
927 \************************************************************/
929 #undef  CGEN_PRINT_INSN
930 #define CGEN_PRINT_INSN mep_print_insn
932 static int
933 mep_print_vliw_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info,
934                       bfd_byte *buf, int corelength, int copro1length,
935                       int copro2length ATTRIBUTE_UNUSED)
937   int i;
938   int status = 0;
939   /* char insnbuf[CGEN_MAX_INSN_SIZE]; */
940   bfd_byte insnbuf[64];
942   /* If corelength > 0 then there is a core insn present. It
943      will be at the beginning of the buffer.  After printing
944      the core insn, we need to print the + on the next line.  */
945   if (corelength > 0)
946     {
947       int my_status = 0;
948          
949       for (i = 0; i < corelength; i++ )
950         insnbuf[i] = buf[i];
951       cd->isas = & MEP_CORE_ISA;
952          
953       my_status = print_insn (cd, pc, info, insnbuf, corelength);
954       if (my_status != corelength)
955         {
956           (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
957           my_status = corelength;
958         }
959       status += my_status;
961       /* Print the + to indicate that the following copro insn is   */
962       /* part of a vliw group.                                      */
963       if (copro1length > 0)
964         (*info->fprintf_func) (info->stream, " + "); 
965     }
967   /* Now all that is left to be processed is the coprocessor insns
968      In vliw mode, there will always be one.  Its positioning will
969      be from byte corelength to byte corelength+copro1length -1.
970      No need to check for existence.   Also, the first vliw insn,
971      will, as spec'd, always be at least as long as the core insn
972      so we don't need to flush the buffer.  */
973   if (copro1length > 0)
974     {
975       int my_status = 0;
976          
977       for (i = corelength; i < corelength + copro1length; i++ )
978         insnbuf[i - corelength] = buf[i];
980       switch (copro1length)
981         {
982         case 0:
983           break;
984         case 2:
985           cd->isas = & MEP_COP16_ISA;
986           break;
987         case 4:
988           cd->isas = & MEP_COP32_ISA;
989           break;
990         case 6:
991           cd->isas = & MEP_COP48_ISA;
992           break;
993         case 8:
994           cd->isas = & MEP_COP64_ISA;
995           break; 
996         default:
997           /* Shouldn't be anything but 16,32,48,64.  */
998           break;
999         }
1001       my_status = print_insn (cd, pc, info, insnbuf, copro1length);
1003       if (my_status != copro1length)
1004         {
1005           (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
1006           my_status = copro1length;
1007         }
1008       status += my_status;
1009     }
1011 #if 0
1012   /* Now we need to process the second copro insn if it exists. We
1013      have no guarantee that the second copro insn will be longer
1014      than the first, so we have to flush the buffer if we are have
1015      a second copro insn to process.  If present, this insn will
1016      be in the position from byte corelength+copro1length to byte
1017      corelength+copro1length+copro2length-1 (which better equal 8
1018      or else we're in big trouble.  */
1019   if (copro2length > 0)
1020     {
1021       int my_status = 0;
1023       for (i = 0; i < 64 ; i++)
1024         insnbuf[i] = 0;
1026       for (i = corelength + copro1length; i < 64; i++)
1027         insnbuf[i - (corelength + copro1length)] = buf[i];
1028       
1029       switch (copro2length)
1030         {
1031         case 2:
1032           cd->isas = 1 << ISA_EXT_COP1_16;
1033           break;
1034         case 4:
1035           cd->isas = 1 << ISA_EXT_COP1_32;
1036           break;
1037         case 6:
1038           cd->isas = 1 << ISA_EXT_COP1_48;
1039           break;
1040         case 8:
1041           cd->isas = 1 << ISA_EXT_COP1_64; 
1042           break;
1043         default:
1044           /* Shouldn't be anything but 16,32,48,64.  */
1045           break;
1046         }
1048       my_status = print_insn (cd, pc, info, insnbuf, copro2length);
1050       if (my_status != copro2length)
1051         {
1052           (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
1053           my_status = copro2length;
1054         }
1056       status += my_status;
1057     }
1058 #endif
1060   /* Status should now be the number of bytes that were printed
1061      which should be 4 for VLIW32 mode and 64 for VLIW64 mode.  */
1063   if ((!MEP_VLIW64 && (status != 4)) || (MEP_VLIW64 && (status != 8)))
1064     return -1;
1065   else
1066     return status;
1069 /* The two functions mep_examine_vliw[32,64]_insns are used find out 
1070    which vliw combinaion (16 bit core with 48 bit copro, 32 bit core 
1071    with 32 bit copro, etc.) is present.  Later on, when internally   
1072    parallel coprocessors are handled, only these functions should    
1073    need to be changed.                                               
1075    At this time only the following combinations are supported: 
1076    
1077    VLIW32 Mode:
1078    16 bit core insn (core) and 16 bit coprocessor insn (cop1)
1079    32 bit core insn (core)
1080    32 bit coprocessor insn (cop1)
1081    Note: As of this time, I do not believe we have enough information
1082          to distinguish a 32 bit core insn from a 32 bit cop insn. Also,
1083          no 16 bit coprocessor insns have been specified.  
1085    VLIW64 Mode:
1086    16 bit core insn (core) and 48 bit coprocessor insn (cop1)
1087    32 bit core insn (core) and 32 bit coprocessor insn (cop1)
1088    64 bit coprocessor insn (cop1)
1089   
1090    The framework for an internally parallel coprocessor is also
1091    present (2nd coprocessor insn is cop2), but at this time it 
1092    is not used.  This only appears to be valid in VLIW64 mode.  */
1094 static int
1095 mep_examine_vliw32_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
1097   int status;
1098   int buflength;
1099   int corebuflength;
1100   int cop1buflength;
1101   int cop2buflength;
1102   bfd_byte buf[CGEN_MAX_INSN_SIZE];  
1103   char indicator16[1];
1104   char indicatorcop32[2]; 
1106   /* At this time we're not supporting internally parallel coprocessors,
1107      so cop2buflength will always be 0.  */
1108   cop2buflength = 0;
1110   /* Read in 32 bits.  */
1111   buflength = 4; /* VLIW insn spans 4 bytes.  */
1112   status = (*info->read_memory_func) (pc, buf, buflength, info);
1114   if (status != 0)
1115     {
1116       (*info->memory_error_func) (status, pc, info);
1117       return -1;
1118     }
1120   /* Put the big endian representation of the bytes to be examined
1121      in the temporary buffers for examination.  */
1123   if (info->endian == BFD_ENDIAN_BIG)
1124     {
1125       indicator16[0] = buf[0];
1126       indicatorcop32[0] = buf[0];
1127       indicatorcop32[1] = buf[1];
1128     }
1129   else
1130     {
1131       indicator16[0] = buf[1];
1132       indicatorcop32[0] = buf[1];
1133       indicatorcop32[1] = buf[0];
1134     }
1136   /* If the two high order bits are 00, 01 or 10, we have a 16 bit
1137      core insn and a 48 bit copro insn.  */
1139   if ((indicator16[0] & 0x80) && (indicator16[0] & 0x40))
1140     {
1141       if ((indicatorcop32[0] & 0xf0) == 0xf0 && (indicatorcop32[1] & 0x07) == 0x07)
1142         {
1143           /* We have a 32 bit copro insn.  */
1144           corebuflength = 0;
1145           /* All 4 4ytes are one copro insn. */
1146           cop1buflength = 4;
1147         }
1148       else
1149         {
1150           /* We have a 32 bit core.  */
1151           corebuflength = 4;
1152           cop1buflength = 0;
1153         }
1154     }
1155   else
1156     {
1157       /* We have a 16 bit core insn and a 16 bit copro insn.  */
1158       corebuflength = 2;
1159       cop1buflength = 2;
1160     }
1162   /* Now we have the distrubution set.  Print them out.  */
1163   status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength,
1164                                  cop1buflength, cop2buflength);
1166   return status;
1169 static int
1170 mep_examine_vliw64_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
1172   int status;
1173   int buflength;
1174   int corebuflength;
1175   int cop1buflength;
1176   int cop2buflength;
1177   bfd_byte buf[CGEN_MAX_INSN_SIZE];
1178   char indicator16[1];
1179   char indicator64[4];
1181   /* At this time we're not supporting internally parallel
1182      coprocessors, so cop2buflength will always be 0.  */
1183   cop2buflength = 0;
1185   /* Read in 64 bits.  */
1186   buflength = 8; /* VLIW insn spans 8 bytes.  */
1187   status = (*info->read_memory_func) (pc, buf, buflength, info);
1189   if (status != 0)
1190     {
1191       (*info->memory_error_func) (status, pc, info);
1192       return -1;
1193     }
1195   /* We have all 64 bits in the buffer now.  We have to figure out
1196      what combination of instruction sizes are present.  The two
1197      high order bits will indicate whether or not we have a 16 bit
1198      core insn or not.  If not, then we have to look at the 7,8th
1199      bytes to tell whether we have 64 bit copro insn or a 32 bit
1200      core insn with a 32 bit copro insn.  Endianness will make a
1201      difference here.  */
1203   /* Put the big endian representation of the bytes to be examined
1204      in the temporary buffers for examination.  */
1206   /* indicator16[0] = buf[0];  */
1207   if (info->endian == BFD_ENDIAN_BIG)
1208     {
1209       indicator16[0] = buf[0];
1210       indicator64[0] = buf[0];
1211       indicator64[1] = buf[1];
1212       indicator64[2] = buf[2];
1213       indicator64[3] = buf[3];
1214     }
1215   else
1216     {
1217       indicator16[0] = buf[1];
1218       indicator64[0] = buf[1];
1219       indicator64[1] = buf[0];
1220       indicator64[2] = buf[3];
1221       indicator64[3] = buf[2];
1222     }
1224   /* If the two high order bits are 00, 01 or 10, we have a 16 bit
1225      core insn and a 48 bit copro insn.  */
1227   if ((indicator16[0] & 0x80) && (indicator16[0] & 0x40))
1228     {
1229       if ((indicator64[0] & 0xf0) == 0xf0 && (indicator64[1] & 0x07) == 0x07
1230           && ((indicator64[2] & 0xfe) != 0xf0 || (indicator64[3] & 0xf4) != 0))
1231         {
1232           /* We have a 64 bit copro insn.  */
1233           corebuflength = 0;
1234           /* All 8 bytes are one copro insn.  */
1235           cop1buflength = 8;
1236         }
1237       else
1238         {
1239           /* We have a 32 bit core insn and a 32 bit copro insn.  */
1240           corebuflength = 4;
1241           cop1buflength = 4;
1242         }
1243     }
1244   else
1245     {
1246       /* We have a 16 bit core insn and a 48 bit copro insn.  */
1247       corebuflength = 2;
1248       cop1buflength = 6;
1249     }
1251   /* Now we have the distrubution set.  Print them out. */
1252   status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength,
1253                                  cop1buflength, cop2buflength);
1255   return status;
1258 #ifdef MEP_IVC2_SUPPORTED
1260 static int
1261 print_slot_insn (CGEN_CPU_DESC cd,
1262                  bfd_vma pc,
1263                  disassemble_info *info,
1264                  SLOTS_ATTR slot,
1265                  bfd_byte *buf)
1267   const CGEN_INSN_LIST *insn_list;
1268   CGEN_INSN_INT insn_value;
1269   CGEN_EXTRACT_INFO ex_info;
1271   insn_value = cgen_get_insn_value (cd, buf, 32, cd->insn_endian);
1273   /* Fill in ex_info fields like read_insn would.  Don't actually call
1274      read_insn, since the incoming buffer is already read (and possibly
1275      modified a la m32r).  */
1276   ex_info.valid = (1 << 8) - 1;
1277   ex_info.dis_info = info;
1278   ex_info.insn_bytes = buf;
1280   /* The instructions are stored in hash lists.
1281      Pick the first one and keep trying until we find the right one.  */
1283   insn_list = CGEN_DIS_LOOKUP_INSN (cd, (char *) buf, insn_value);
1284   while (insn_list != NULL)
1285     {
1286       const CGEN_INSN *insn = insn_list->insn;
1287       CGEN_FIELDS fields;
1288       int length;
1290       if ((CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG)
1291            && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG) != MEP_CONFIG)
1292           || ! (CGEN_ATTR_CGEN_INSN_SLOTS_VALUE (CGEN_INSN_ATTRS (insn)) & (1 << slot)))
1293         {
1294           insn_list = CGEN_DIS_NEXT_INSN (insn_list);
1295           continue;
1296         }
1298       if ((insn_value & CGEN_INSN_BASE_MASK (insn))
1299           == CGEN_INSN_BASE_VALUE (insn))
1300         {
1301           /* Printing is handled in two passes.  The first pass parses the
1302              machine insn and extracts the fields.  The second pass prints
1303              them.  */
1305           length = CGEN_EXTRACT_FN (cd, insn)
1306             (cd, insn, &ex_info, insn_value, &fields, pc);
1308           /* Length < 0 -> error.  */
1309           if (length < 0)
1310             return length;
1311           if (length > 0)
1312             {
1313               CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
1314               /* Length is in bits, result is in bytes.  */
1315               return length / 8;
1316             }
1317         }
1319       insn_list = CGEN_DIS_NEXT_INSN (insn_list);
1320     }
1322   if (slot == SLOTS_P0S)
1323     (*info->fprintf_func) (info->stream, "*unknown-p0s*");
1324   else if (slot == SLOTS_P0)
1325     (*info->fprintf_func) (info->stream, "*unknown-p0*");
1326   else if (slot == SLOTS_P1)
1327     (*info->fprintf_func) (info->stream, "*unknown-p1*");
1328   else if (slot == SLOTS_C3)
1329     (*info->fprintf_func) (info->stream, "*unknown-c3*");
1330   return 0;
1333 static int
1334 mep_examine_ivc2_insns (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, bfd_vma pc ATTRIBUTE_UNUSED, disassemble_info *info ATTRIBUTE_UNUSED)
1336   int status;
1337   int buflength;
1338   bfd_byte buf[8];
1339   bfd_byte insn[8];
1340   int e;
1342   /* Read in 64 bits.  */
1343   buflength = 8; /* VLIW insn spans 8 bytes.  */
1344   status = (*info->read_memory_func) (pc, buf, buflength, info);
1346   if (status != 0)
1347     {
1348       (*info->memory_error_func) (status, pc, info);
1349       return -1;
1350     }
1352   if (info->endian == BFD_ENDIAN_LITTLE)
1353     e = 1;
1354   else
1355     e = 0;
1357   if (((unsigned char)buf[0^e] & 0xf0) < 0xc0)
1358     {
1359       /*      <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */
1360       /* V1   [-----core-----][--------p0s-------][------------p1------------] */
1362       print_insn (cd, pc, info, buf, 2);
1364       insn[0^e] = 0;
1365       insn[1^e] = buf[2^e];
1366       insn[2^e] = buf[3^e];
1367       insn[3^e] = buf[4^e] & 0xf0;
1368       (*info->fprintf_func) (info->stream, " + ");
1369       print_slot_insn (cd, pc, info, SLOTS_P0S, insn);
1371       insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4;
1372       insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4;
1373       insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4;
1374       insn[3^e] = buf[7^e] << 4;
1375       (*info->fprintf_func) (info->stream, " + ");
1376       print_slot_insn (cd, pc, info, SLOTS_P1, insn);
1377     }
1378   else if ((buf[0^e] & 0xf0) == 0xf0 && (buf[1^e] & 0x0f) == 0x07)
1379     {
1380       /*      <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */
1381       /* V3   1111[--p0--]0111[--------p0--------][------------p1------------] */
1382       /*                                          00000000111111112222222233333333 */
1384       insn[0^e] = buf[0^e] << 4 | buf[1^e] >> 4;
1385       insn[1^e] = buf[2^e];
1386       insn[2^e] = buf[3^e];
1387       insn[3^e] = buf[4^e] & 0xf0;
1388       print_slot_insn (cd, pc, info, SLOTS_P0, insn);
1390       insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4;
1391       insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4;
1392       insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4;
1393       insn[3^e] = buf[7^e] << 4;
1394       (*info->fprintf_func) (info->stream, " + ");
1395       print_slot_insn (cd, pc, info, SLOTS_P1, insn);
1396     }
1397   else
1398     {
1399       /*      <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */
1400       /* V2   [-------------core-------------]xxxx[------------p1------------] */
1401       print_insn (cd, pc, info, buf, 4);
1403       insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4;
1404       insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4;
1405       insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4;
1406       insn[3^e] = buf[7^e] << 4;
1407       (*info->fprintf_func) (info->stream, " + ");
1408       print_slot_insn (cd, pc, info, SLOTS_P1, insn);
1409     }
1411   return 8;
1414 #endif /* MEP_IVC2_SUPPORTED */
1416 /* This is a hack.  SID calls this to update the disassembler as the
1417    CPU changes modes.  */
1418 static int mep_ivc2_disassemble_p = 0;
1419 static int mep_ivc2_vliw_disassemble_p = 0;
1421 void
1422 mep_print_insn_set_ivc2_mode (int ivc2_p, int vliw_p, int cfg_idx);
1423 void
1424 mep_print_insn_set_ivc2_mode (int ivc2_p, int vliw_p, int cfg_idx)
1426   mep_ivc2_disassemble_p = ivc2_p;
1427   mep_ivc2_vliw_disassemble_p = vliw_p;
1428   mep_config_index = cfg_idx;
1431 static int
1432 mep_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
1434   int status;
1435   int cop_type;
1436   int ivc2 = 0;
1437   static CGEN_ATTR_VALUE_BITSET_TYPE *ivc2_core_isa = NULL;
1439   if (ivc2_core_isa == NULL)
1440     {
1441       /* IVC2 has some core-only coprocessor instructions.  We
1442          use COP32 to flag those, and COP64 for the VLIW ones,
1443          since they have the same names.  */
1444       ivc2_core_isa = cgen_bitset_create (MAX_ISAS);
1445     }
1447   /* Extract and adapt to configuration number, if available. */
1448   if (info->section && info->section->owner)
1449     {
1450       bfd *abfd = info->section->owner;
1451       if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
1452         {
1453           mep_config_index = abfd->tdata.elf_obj_data->elf_header->e_flags & EF_MEP_INDEX_MASK;
1454           /* This instantly redefines MEP_CONFIG, MEP_OMASK, .... MEP_VLIW64 */
1456           cop_type = abfd->tdata.elf_obj_data->elf_header->e_flags & EF_MEP_COP_MASK;
1457           if (cop_type == EF_MEP_COP_IVC2)
1458             ivc2 = 1;
1459         }
1460     }
1462   /* Picking the right ISA bitmask for the current context is tricky.  */
1463   if (info->section)
1464     {
1465       if (info->section->flags & SEC_MEP_VLIW)
1466         {
1467 #ifdef MEP_IVC2_SUPPORTED
1468           if (ivc2)
1469             {
1470               /* ivc2 has its own way of selecting its functions.  */
1471               cd->isas = & MEP_CORE_ISA;
1472               status = mep_examine_ivc2_insns (cd, pc, info);
1473             }
1474           else
1475 #endif
1476             /* Are we in 32 or 64 bit vliw mode?  */
1477             if (MEP_VLIW64)
1478               status = mep_examine_vliw64_insns (cd, pc, info);
1479             else
1480               status = mep_examine_vliw32_insns (cd, pc, info);
1481           /* Both the above branches set their own isa bitmasks.  */
1482         }
1483       else
1484         {
1485           if (ivc2)
1486             {
1487               cgen_bitset_clear (ivc2_core_isa);
1488               cgen_bitset_union (ivc2_core_isa, &MEP_CORE_ISA, ivc2_core_isa);
1489               cgen_bitset_union (ivc2_core_isa, &MEP_COP32_ISA, ivc2_core_isa);
1490               cd->isas = ivc2_core_isa;
1491             }
1492           else
1493             cd->isas = & MEP_CORE_ISA;
1494           status = default_print_insn (cd, pc, info);
1495         }
1496     }
1497   else /* sid or gdb */
1498     {
1499 #ifdef MEP_IVC2_SUPPORTED
1500       if (mep_ivc2_disassemble_p)
1501         {
1502           if (mep_ivc2_vliw_disassemble_p)
1503             {
1504               cd->isas = & MEP_CORE_ISA;
1505               status = mep_examine_ivc2_insns (cd, pc, info);
1506               return status;
1507             }
1508           else
1509             {
1510               if (ivc2)
1511                 cd->isas = ivc2_core_isa;
1512             }
1513         }
1514 #endif
1516       status = default_print_insn (cd, pc, info);
1517     }
1519   return status;
1523 /* -- opc.c */
1524 #include "elf/mep.h"
1526 /* A mask for all ISAs executed by the core. */
1527 CGEN_ATTR_VALUE_BITSET_TYPE mep_all_core_isas_mask = {0, 0};
1529 void
1530 init_mep_all_core_isas_mask (void)
1532   if (mep_all_core_isas_mask.length != 0)
1533     return;
1534   cgen_bitset_init (& mep_all_core_isas_mask, ISA_MAX);
1535   cgen_bitset_set (& mep_all_core_isas_mask, ISA_MEP);
1536   /* begin-all-core-isas */
1537   cgen_bitset_add (& mep_all_core_isas_mask, ISA_EXT_CORE1);
1538   /* end-all-core-isas */
1541 CGEN_ATTR_VALUE_BITSET_TYPE mep_all_cop_isas_mask = {0, 0};
1543 void
1544 init_mep_all_cop_isas_mask (void)
1546   if (mep_all_cop_isas_mask.length != 0)
1547     return;
1548   cgen_bitset_init (& mep_all_cop_isas_mask, ISA_MAX);
1549   /* begin-all-cop-isas */
1550   cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_16);
1551   cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_32);
1552   cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_48);
1553   cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_64);
1554   /* end-all-cop-isas */
1558 mep_insn_supported_by_isa (const CGEN_INSN *insn, CGEN_ATTR_VALUE_BITSET_TYPE *isa_mask)
1560   CGEN_BITSET insn_isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA);
1561   return cgen_bitset_intersect_p (& insn_isas, isa_mask);
1564 #define OPTION_MASK \
1565         ( (1 << CGEN_INSN_OPTIONAL_BIT_INSN) \
1566         | (1 << CGEN_INSN_OPTIONAL_MUL_INSN) \
1567         | (1 << CGEN_INSN_OPTIONAL_DIV_INSN) \
1568         | (1 << CGEN_INSN_OPTIONAL_DEBUG_INSN) \
1569         | (1 << CGEN_INSN_OPTIONAL_LDZ_INSN) \
1570         | (1 << CGEN_INSN_OPTIONAL_ABS_INSN) \
1571         | (1 << CGEN_INSN_OPTIONAL_AVE_INSN) \
1572         | (1 << CGEN_INSN_OPTIONAL_MINMAX_INSN) \
1573         | (1 << CGEN_INSN_OPTIONAL_CLIP_INSN) \
1574         | (1 << CGEN_INSN_OPTIONAL_SAT_INSN) \
1575         | (1 << CGEN_INSN_OPTIONAL_UCI_INSN) \
1576         | (1 << CGEN_INSN_OPTIONAL_DSP_INSN) \
1577         | (1 << CGEN_INSN_OPTIONAL_CP_INSN) \
1578         | (1 << CGEN_INSN_OPTIONAL_CP64_INSN) )
1581 mep_config_map_struct mep_config_map[] =
1583   /* config-map-start */
1584   /* Default entry: first module, with all options enabled. */
1585   { "", 0,  EF_MEP_COP_IVC2 | EF_MEP_CPU_C5,0, 64, { 1, "\x20" }, { 1, "\x10" }, { 1, "\x8" }, { 1, "\x4" }, { 1, "\x3c" }, { 1, "\xc0" }, OPTION_MASK | (1 << CGEN_INSN_OPTIONAL_DSP_INSN) | (1 << CGEN_INSN_OPTIONAL_UCI_INSN) },
1586   { "default", CONFIG_DEFAULT, EF_MEP_COP_IVC2 | EF_MEP_CPU_C5, 0, 64, { 1, "\x20" }, { 1, "\x10" }, { 1, "\x8" }, { 1, "\x4" }, { 1, "\x3c" }, { 1, "\xc0" },
1587           0
1588         | (1 << CGEN_INSN_OPTIONAL_CP_INSN)
1589         | (1 << CGEN_INSN_OPTIONAL_CP64_INSN)
1590         | (1 << CGEN_INSN_OPTIONAL_MUL_INSN)
1591         | (1 << CGEN_INSN_OPTIONAL_DIV_INSN)
1592         | (1 << CGEN_INSN_OPTIONAL_BIT_INSN)
1593         | (1 << CGEN_INSN_OPTIONAL_LDZ_INSN)
1594         | (1 << CGEN_INSN_OPTIONAL_ABS_INSN)
1595         | (1 << CGEN_INSN_OPTIONAL_AVE_INSN)
1596         | (1 << CGEN_INSN_OPTIONAL_MINMAX_INSN)
1597         | (1 << CGEN_INSN_OPTIONAL_CLIP_INSN)
1598         | (1 << CGEN_INSN_OPTIONAL_SAT_INSN) },
1599   /* config-map-end */
1600   { 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, 0 }
1603 int mep_config_index = 0;
1605 static int
1606 check_configured_mach (int machs)
1608   /* All base insns are supported.  */
1609   int mach = 1 << MACH_BASE;
1610   switch (MEP_CPU & EF_MEP_CPU_MASK)
1611     {
1612     case EF_MEP_CPU_C2:
1613     case EF_MEP_CPU_C3:
1614       mach |= (1 << MACH_MEP);
1615       break;
1616     case EF_MEP_CPU_H1:
1617       mach |= (1 << MACH_H1);
1618       break;
1619     case EF_MEP_CPU_C5:
1620       mach |= (1 << MACH_MEP);
1621       mach |= (1 << MACH_C5);
1622       break;
1623     default:
1624       break;
1625     }
1626   return machs & mach;
1630 mep_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
1632   int iconfig = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG);
1633   int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
1634   CGEN_BITSET isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA);
1635   int ok1;
1636   int ok2;
1637   int ok3;
1639   /* If the insn has an option bit set that we don't want,
1640      reject it.  */
1641   if (CGEN_INSN_ATTRS (insn)->bool_ & OPTION_MASK & ~MEP_OMASK)
1642     return 0;
1644   /* If attributes are absent, assume no restriction. */
1645   if (machs == 0)
1646     machs = ~0;
1648   ok1 = ((machs & cd->machs) && cgen_bitset_intersect_p (& isas, cd->isas));
1649   /* If the insn is config-specific, make sure it matches.  */
1650   ok2 =  (iconfig == 0 || iconfig == MEP_CONFIG);
1651   /* Make sure the insn is supported by the configured mach  */
1652   ok3 = check_configured_mach (machs);
1654   return (ok1 && ok2 && ok3);
1658 mep_cgen_insn_supported_asm (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
1660 #ifdef MEP_IVC2_SUPPORTED
1661   /* If we're assembling VLIW packets, ignore the 12-bit BSR as we
1662      can't relax that.  The 24-bit BSR is matched instead.  */
1663   if (insn->base->num == MEP_INSN_BSR12
1664       && cgen_bitset_contains (cd->isas, ISA_EXT_COP1_64))
1665     return 0;
1666 #endif
1668   return mep_cgen_insn_supported (cd, insn);