* elf32-spu.c (build_stub): Fix malloc under-allocation.
[binutils.git] / cpu / mep.opc
blob6b4e9ff821207b1d68f74f96e748b6b1ca5314a2
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 macro 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 macro *
663 lookup_macro (const char *name)
665   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, 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   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                 default:
794                   args[narg].len++;
795                   break;                  
796                 }
797             } 
798           else
799             {
800               if (*in == ')')
801                 depth--;
802               if (narg > -1)
803                 args[narg].len++;
804             }
805           
806         }
807       ++in;
808     }
809   
810   if (mark != in)
811     result = str_append (result, mark, in - mark);
812   
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   if (hold)
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 print_tpreg (CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned int);
873 static void print_spreg (CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned int);
875 static void
876 print_tpreg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, PTR dis_info,
877              CGEN_KEYWORD *table ATTRIBUTE_UNUSED, long val ATTRIBUTE_UNUSED,
878              unsigned int flags ATTRIBUTE_UNUSED)
880   disassemble_info *info = (disassemble_info *) dis_info;
882   (*info->fprintf_func) (info->stream, "$tp");
885 static void
886 print_spreg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, PTR dis_info, 
887              CGEN_KEYWORD *table ATTRIBUTE_UNUSED, long val ATTRIBUTE_UNUSED,
888              unsigned int flags ATTRIBUTE_UNUSED)
890   disassemble_info *info = (disassemble_info *) dis_info;
892   (*info->fprintf_func) (info->stream, "$sp");
895 /* begin-cop-ip-print-handlers */
896 static void
897 print_ivc2_cr (CGEN_CPU_DESC,
898         void *,
899         CGEN_KEYWORD *,
900         long,
901         unsigned int) ATTRIBUTE_UNUSED;
902 static void
903 print_ivc2_cr (CGEN_CPU_DESC cd,
904         void *dis_info,
905         CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED,
906         long value,
907         unsigned int attrs)
909   print_keyword (cd, dis_info, & mep_cgen_opval_h_cr_ivc2, value, attrs);
911 static void
912 print_ivc2_ccr (CGEN_CPU_DESC,
913         void *,
914         CGEN_KEYWORD *,
915         long,
916         unsigned int) ATTRIBUTE_UNUSED;
917 static void
918 print_ivc2_ccr (CGEN_CPU_DESC cd,
919         void *dis_info,
920         CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED,
921         long value,
922         unsigned int attrs)
924   print_keyword (cd, dis_info, & mep_cgen_opval_h_ccr_ivc2, value, attrs);
926 /* end-cop-ip-print-handlers */
928 /************************************************************\
929 *********************** Experimental *************************
930 \************************************************************/
932 #undef  CGEN_PRINT_INSN
933 #define CGEN_PRINT_INSN mep_print_insn
935 static int
936 mep_print_vliw_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info,
937                       bfd_byte *buf, int corelength, int copro1length,
938                       int copro2length ATTRIBUTE_UNUSED)
940   int i;
941   int status = 0;
942   /* char insnbuf[CGEN_MAX_INSN_SIZE]; */
943   bfd_byte insnbuf[64];
945   /* If corelength > 0 then there is a core insn present. It
946      will be at the beginning of the buffer.  After printing
947      the core insn, we need to print the + on the next line.  */
948   if (corelength > 0)
949     {
950       int my_status = 0;
951          
952       for (i = 0; i < corelength; i++ )
953         insnbuf[i] = buf[i];
954       cd->isas = & MEP_CORE_ISA;
955          
956       my_status = print_insn (cd, pc, info, insnbuf, corelength);
957       if (my_status != corelength)
958         {
959           (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
960           my_status = corelength;
961         }
962       status += my_status;
964       /* Print the + to indicate that the following copro insn is   */
965       /* part of a vliw group.                                      */
966       if (copro1length > 0)
967         (*info->fprintf_func) (info->stream, " + "); 
968     }
970   /* Now all that is left to be processed is the coprocessor insns
971      In vliw mode, there will always be one.  Its positioning will
972      be from byte corelength to byte corelength+copro1length -1.
973      No need to check for existence.   Also, the first vliw insn,
974      will, as spec'd, always be at least as long as the core insn
975      so we don't need to flush the buffer.  */
976   if (copro1length > 0)
977     {
978       int my_status = 0;
979          
980       for (i = corelength; i < corelength + copro1length; i++ )
981         insnbuf[i - corelength] = buf[i];
983       switch (copro1length)
984         {
985         case 0:
986           break;
987         case 2:
988           cd->isas = & MEP_COP16_ISA;
989           break;
990         case 4:
991           cd->isas = & MEP_COP32_ISA;
992           break;
993         case 6:
994           cd->isas = & MEP_COP48_ISA;
995           break;
996         case 8:
997           cd->isas = & MEP_COP64_ISA;
998           break; 
999         default:
1000           /* Shouldn't be anything but 16,32,48,64.  */
1001           break;
1002         }
1004       my_status = print_insn (cd, pc, info, insnbuf, copro1length);
1006       if (my_status != copro1length)
1007         {
1008           (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
1009           my_status = copro1length;
1010         }
1011       status += my_status;
1012     }
1014 #if 0
1015   /* Now we need to process the second copro insn if it exists. We
1016      have no guarantee that the second copro insn will be longer
1017      than the first, so we have to flush the buffer if we are have
1018      a second copro insn to process.  If present, this insn will
1019      be in the position from byte corelength+copro1length to byte
1020      corelength+copro1length+copro2length-1 (which better equal 8
1021      or else we're in big trouble.  */
1022   if (copro2length > 0)
1023     {
1024       int my_status = 0;
1026       for (i = 0; i < 64 ; i++)
1027         insnbuf[i] = 0;
1029       for (i = corelength + copro1length; i < 64; i++)
1030         insnbuf[i - (corelength + copro1length)] = buf[i];
1031       
1032       switch (copro2length)
1033         {
1034         case 2:
1035           cd->isas = 1 << ISA_EXT_COP1_16;
1036           break;
1037         case 4:
1038           cd->isas = 1 << ISA_EXT_COP1_32;
1039           break;
1040         case 6:
1041           cd->isas = 1 << ISA_EXT_COP1_48;
1042           break;
1043         case 8:
1044           cd->isas = 1 << ISA_EXT_COP1_64; 
1045           break;
1046         default:
1047           /* Shouldn't be anything but 16,32,48,64.  */
1048           break;
1049         }
1051       my_status = print_insn (cd, pc, info, insnbuf, copro2length);
1053       if (my_status != copro2length)
1054         {
1055           (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
1056           my_status = copro2length;
1057         }
1059       status += my_status;
1060     }
1061 #endif
1063   /* Status should now be the number of bytes that were printed
1064      which should be 4 for VLIW32 mode and 64 for VLIW64 mode.  */
1066   if ((!MEP_VLIW64 && (status != 4)) || (MEP_VLIW64 && (status != 8)))
1067     return -1;
1068   else
1069     return status;
1072 /* The two functions mep_examine_vliw[32,64]_insns are used find out 
1073    which vliw combinaion (16 bit core with 48 bit copro, 32 bit core 
1074    with 32 bit copro, etc.) is present.  Later on, when internally   
1075    parallel coprocessors are handled, only these functions should    
1076    need to be changed.                                               
1078    At this time only the following combinations are supported: 
1079    
1080    VLIW32 Mode:
1081    16 bit core insn (core) and 16 bit coprocessor insn (cop1)
1082    32 bit core insn (core)
1083    32 bit coprocessor insn (cop1)
1084    Note: As of this time, I do not believe we have enough information
1085          to distinguish a 32 bit core insn from a 32 bit cop insn. Also,
1086          no 16 bit coprocessor insns have been specified.  
1088    VLIW64 Mode:
1089    16 bit core insn (core) and 48 bit coprocessor insn (cop1)
1090    32 bit core insn (core) and 32 bit coprocessor insn (cop1)
1091    64 bit coprocessor insn (cop1)
1092   
1093    The framework for an internally parallel coprocessor is also
1094    present (2nd coprocessor insn is cop2), but at this time it 
1095    is not used.  This only appears to be valid in VLIW64 mode.  */
1097 static int
1098 mep_examine_vliw32_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
1100   int status;
1101   int buflength;
1102   int corebuflength;
1103   int cop1buflength;
1104   int cop2buflength;
1105   bfd_byte buf[CGEN_MAX_INSN_SIZE];  
1106   char indicator16[1];
1107   char indicatorcop32[2]; 
1109   /* At this time we're not supporting internally parallel coprocessors,
1110      so cop2buflength will always be 0.  */
1111   cop2buflength = 0;
1113   /* Read in 32 bits.  */
1114   buflength = 4; /* VLIW insn spans 4 bytes.  */
1115   status = (*info->read_memory_func) (pc, buf, buflength, info);
1117   if (status != 0)
1118     {
1119       (*info->memory_error_func) (status, pc, info);
1120       return -1;
1121     }
1123   /* Put the big endian representation of the bytes to be examined
1124      in the temporary buffers for examination.  */
1126   if (info->endian == BFD_ENDIAN_BIG)
1127     {
1128       indicator16[0] = buf[0];
1129       indicatorcop32[0] = buf[0];
1130       indicatorcop32[1] = buf[1];
1131     }
1132   else
1133     {
1134       indicator16[0] = buf[1];
1135       indicatorcop32[0] = buf[1];
1136       indicatorcop32[1] = buf[0];
1137     }
1139   /* If the two high order bits are 00, 01 or 10, we have a 16 bit
1140      core insn and a 48 bit copro insn.  */
1142   if ((indicator16[0] & 0x80) && (indicator16[0] & 0x40))
1143     {
1144       if ((indicatorcop32[0] & 0xf0) == 0xf0 && (indicatorcop32[1] & 0x07) == 0x07)
1145         {
1146           /* We have a 32 bit copro insn.  */
1147           corebuflength = 0;
1148           /* All 4 4ytes are one copro insn. */
1149           cop1buflength = 4;
1150         }
1151       else
1152         {
1153           /* We have a 32 bit core.  */
1154           corebuflength = 4;
1155           cop1buflength = 0;
1156         }
1157     }
1158   else
1159     {
1160       /* We have a 16 bit core insn and a 16 bit copro insn.  */
1161       corebuflength = 2;
1162       cop1buflength = 2;
1163     }
1165   /* Now we have the distrubution set.  Print them out.  */
1166   status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength,
1167                                  cop1buflength, cop2buflength);
1169   return status;
1172 static int
1173 mep_examine_vliw64_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
1175   int status;
1176   int buflength;
1177   int corebuflength;
1178   int cop1buflength;
1179   int cop2buflength;
1180   bfd_byte buf[CGEN_MAX_INSN_SIZE];
1181   char indicator16[1];
1182   char indicator64[4];
1184   /* At this time we're not supporting internally parallel
1185      coprocessors, so cop2buflength will always be 0.  */
1186   cop2buflength = 0;
1188   /* Read in 64 bits.  */
1189   buflength = 8; /* VLIW insn spans 8 bytes.  */
1190   status = (*info->read_memory_func) (pc, buf, buflength, info);
1192   if (status != 0)
1193     {
1194       (*info->memory_error_func) (status, pc, info);
1195       return -1;
1196     }
1198   /* We have all 64 bits in the buffer now.  We have to figure out
1199      what combination of instruction sizes are present.  The two
1200      high order bits will indicate whether or not we have a 16 bit
1201      core insn or not.  If not, then we have to look at the 7,8th
1202      bytes to tell whether we have 64 bit copro insn or a 32 bit
1203      core insn with a 32 bit copro insn.  Endianness will make a
1204      difference here.  */
1206   /* Put the big endian representation of the bytes to be examined
1207      in the temporary buffers for examination.  */
1209   /* indicator16[0] = buf[0];  */
1210   if (info->endian == BFD_ENDIAN_BIG)
1211     {
1212       indicator16[0] = buf[0];
1213       indicator64[0] = buf[0];
1214       indicator64[1] = buf[1];
1215       indicator64[2] = buf[2];
1216       indicator64[3] = buf[3];
1217     }
1218   else
1219     {
1220       indicator16[0] = buf[1];
1221       indicator64[0] = buf[1];
1222       indicator64[1] = buf[0];
1223       indicator64[2] = buf[3];
1224       indicator64[3] = buf[2];
1225     }
1227   /* If the two high order bits are 00, 01 or 10, we have a 16 bit
1228      core insn and a 48 bit copro insn.  */
1230   if ((indicator16[0] & 0x80) && (indicator16[0] & 0x40))
1231     {
1232       if ((indicator64[0] & 0xf0) == 0xf0 && (indicator64[1] & 0x07) == 0x07
1233           && ((indicator64[2] & 0xfe) != 0xf0 || (indicator64[3] & 0xf4) != 0))
1234         {
1235           /* We have a 64 bit copro insn.  */
1236           corebuflength = 0;
1237           /* All 8 bytes are one copro insn.  */
1238           cop1buflength = 8;
1239         }
1240       else
1241         {
1242           /* We have a 32 bit core insn and a 32 bit copro insn.  */
1243           corebuflength = 4;
1244           cop1buflength = 4;
1245         }
1246     }
1247   else
1248     {
1249       /* We have a 16 bit core insn and a 48 bit copro insn.  */
1250       corebuflength = 2;
1251       cop1buflength = 6;
1252     }
1254   /* Now we have the distrubution set.  Print them out. */
1255   status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength,
1256                                  cop1buflength, cop2buflength);
1258   return status;
1261 #ifdef MEP_IVC2_SUPPORTED
1263 static int
1264 print_slot_insn (CGEN_CPU_DESC cd,
1265                  bfd_vma pc,
1266                  disassemble_info *info,
1267                  SLOTS_ATTR slot,
1268                  bfd_byte *buf)
1270   const CGEN_INSN_LIST *insn_list;
1271   CGEN_INSN_INT insn_value;
1272   CGEN_EXTRACT_INFO ex_info;
1274   insn_value = cgen_get_insn_value (cd, buf, 32);
1276   /* Fill in ex_info fields like read_insn would.  Don't actually call
1277      read_insn, since the incoming buffer is already read (and possibly
1278      modified a la m32r).  */
1279   ex_info.valid = (1 << 8) - 1;
1280   ex_info.dis_info = info;
1281   ex_info.insn_bytes = buf;
1283   /* The instructions are stored in hash lists.
1284      Pick the first one and keep trying until we find the right one.  */
1286   insn_list = CGEN_DIS_LOOKUP_INSN (cd, (char *) buf, insn_value);
1287   while (insn_list != NULL)
1288     {
1289       const CGEN_INSN *insn = insn_list->insn;
1290       CGEN_FIELDS fields;
1291       int length;
1293       if ((CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG)
1294            && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG) != MEP_CONFIG)
1295           || ! (CGEN_ATTR_CGEN_INSN_SLOTS_VALUE (CGEN_INSN_ATTRS (insn)) & (1 << slot)))
1296         {
1297           insn_list = CGEN_DIS_NEXT_INSN (insn_list);
1298           continue;
1299         }
1301       if ((insn_value & CGEN_INSN_BASE_MASK (insn))
1302           == CGEN_INSN_BASE_VALUE (insn))
1303         {
1304           /* Printing is handled in two passes.  The first pass parses the
1305              machine insn and extracts the fields.  The second pass prints
1306              them.  */
1308           length = CGEN_EXTRACT_FN (cd, insn)
1309             (cd, insn, &ex_info, insn_value, &fields, pc);
1311           /* Length < 0 -> error.  */
1312           if (length < 0)
1313             return length;
1314           if (length > 0)
1315             {
1316               CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
1317               /* Length is in bits, result is in bytes.  */
1318               return length / 8;
1319             }
1320         }
1322       insn_list = CGEN_DIS_NEXT_INSN (insn_list);
1323     }
1325   if (slot == SLOTS_P0S)
1326     (*info->fprintf_func) (info->stream, "*unknown-p0s*");
1327   else if (slot == SLOTS_P0)
1328     (*info->fprintf_func) (info->stream, "*unknown-p0*");
1329   else if (slot == SLOTS_P1)
1330     (*info->fprintf_func) (info->stream, "*unknown-p1*");
1331   else if (slot == SLOTS_C3)
1332     (*info->fprintf_func) (info->stream, "*unknown-c3*");
1333   return 0;
1336 static int
1337 mep_examine_ivc2_insns (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, bfd_vma pc ATTRIBUTE_UNUSED, disassemble_info *info ATTRIBUTE_UNUSED)
1339   int status;
1340   int buflength;
1341   bfd_byte buf[8];
1342   bfd_byte insn[8];
1343   int e;
1345   /* Read in 64 bits.  */
1346   buflength = 8; /* VLIW insn spans 8 bytes.  */
1347   status = (*info->read_memory_func) (pc, buf, buflength, info);
1349   if (status != 0)
1350     {
1351       (*info->memory_error_func) (status, pc, info);
1352       return -1;
1353     }
1355   if (info->endian == BFD_ENDIAN_LITTLE)
1356     e = 1;
1357   else
1358     e = 0;
1360   if (((unsigned char)buf[0^e] & 0xf0) < 0xc0)
1361     {
1362       /*      <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */
1363       /* V1   [-----core-----][--------p0s-------][------------p1------------] */
1365       print_insn (cd, pc, info, buf, 2);
1367       insn[0^e] = 0;
1368       insn[1^e] = buf[2^e];
1369       insn[2^e] = buf[3^e];
1370       insn[3^e] = buf[4^e] & 0xf0;
1371       (*info->fprintf_func) (info->stream, " + ");
1372       print_slot_insn (cd, pc, info, SLOTS_P0S, insn);
1374       insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4;
1375       insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4;
1376       insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4;
1377       insn[3^e] = buf[7^e] << 4;
1378       (*info->fprintf_func) (info->stream, " + ");
1379       print_slot_insn (cd, pc, info, SLOTS_P1, insn);
1380     }
1381   else if ((buf[0^e] & 0xf0) == 0xf0 && (buf[1^e] & 0x0f) == 0x07)
1382     {
1383       /*      <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */
1384       /* V3   1111[--p0--]0111[--------p0--------][------------p1------------] */
1385       /*                                          00000000111111112222222233333333 */
1387       insn[0^e] = buf[0^e] << 4 | buf[1^e] >> 4;
1388       insn[1^e] = buf[2^e];
1389       insn[2^e] = buf[3^e];
1390       insn[3^e] = buf[4^e] & 0xf0;
1391       print_slot_insn (cd, pc, info, SLOTS_P0, insn);
1393       insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4;
1394       insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4;
1395       insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4;
1396       insn[3^e] = buf[7^e] << 4;
1397       (*info->fprintf_func) (info->stream, " + ");
1398       print_slot_insn (cd, pc, info, SLOTS_P1, insn);
1399     }
1400   else
1401     {
1402       /*      <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */
1403       /* V2   [-------------core-------------]xxxx[------------p1------------] */
1404       print_insn (cd, pc, info, buf, 4);
1406       insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4;
1407       insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4;
1408       insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4;
1409       insn[3^e] = buf[7^e] << 4;
1410       (*info->fprintf_func) (info->stream, " + ");
1411       print_slot_insn (cd, pc, info, SLOTS_P1, insn);
1412     }
1414   return 8;
1417 #endif /* MEP_IVC2_SUPPORTED */
1419 /* This is a hack.  SID calls this to update the disassembler as the
1420    CPU changes modes.  */
1421 static int mep_ivc2_disassemble_p = 0;
1422 static int mep_ivc2_vliw_disassemble_p = 0;
1424 void
1425 mep_print_insn_set_ivc2_mode (int ivc2_p, int vliw_p, int cfg_idx);
1426 void
1427 mep_print_insn_set_ivc2_mode (int ivc2_p, int vliw_p, int cfg_idx)
1429   mep_ivc2_disassemble_p = ivc2_p;
1430   mep_ivc2_vliw_disassemble_p = vliw_p;
1431   mep_config_index = cfg_idx;
1434 static int
1435 mep_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
1437   int status;
1438   int cop_type;
1439   int ivc2 = 0;
1440   static CGEN_ATTR_VALUE_BITSET_TYPE *ivc2_core_isa = NULL;
1442   if (ivc2_core_isa == NULL)
1443     {
1444       /* IVC2 has some core-only coprocessor instructions.  We
1445          use COP32 to flag those, and COP64 for the VLIW ones,
1446          since they have the same names.  */
1447       ivc2_core_isa = cgen_bitset_create (MAX_ISAS);
1448     }
1450   /* Extract and adapt to configuration number, if available. */
1451   if (info->section && info->section->owner)
1452     {
1453       bfd *abfd = info->section->owner;
1454       mep_config_index = abfd->tdata.elf_obj_data->elf_header->e_flags & EF_MEP_INDEX_MASK;
1455       /* This instantly redefines MEP_CONFIG, MEP_OMASK, .... MEP_VLIW64 */
1457       cop_type = abfd->tdata.elf_obj_data->elf_header->e_flags & EF_MEP_COP_MASK;
1458       if (cop_type == EF_MEP_COP_IVC2)
1459         ivc2 = 1;
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);