Arm: Prefix register sizes with ARM_
[external/binutils.git] / cpu / mep.opc
1 /* MeP opcode support.  -*- C -*-
2    Copyright 2011 Free Software Foundation, Inc.
3
4    Contributed by Red Hat Inc;
5
6    This file is part of the GNU Binutils.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21    MA 02110-1301, USA.  */
22
23 /* -- opc.h */
24
25 #undef  CGEN_DIS_HASH_SIZE
26 #define CGEN_DIS_HASH_SIZE 1
27
28 #undef  CGEN_DIS_HASH
29 #define CGEN_DIS_HASH(buffer, insn) 0
30
31 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
32
33 typedef struct
34 {
35   char * name;
36   int    config_enum;
37   unsigned cpu_flag;
38   int    big_endian;
39   int    vliw_bits;
40   CGEN_ATTR_VALUE_BITSET_TYPE cop16_isa;
41   CGEN_ATTR_VALUE_BITSET_TYPE cop32_isa;
42   CGEN_ATTR_VALUE_BITSET_TYPE cop48_isa;
43   CGEN_ATTR_VALUE_BITSET_TYPE cop64_isa;
44   CGEN_ATTR_VALUE_BITSET_TYPE cop_isa;
45   CGEN_ATTR_VALUE_BITSET_TYPE core_isa;
46   unsigned int option_mask;
47 } mep_config_map_struct;
48
49 extern mep_config_map_struct mep_config_map[];
50 extern int mep_config_index;
51
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);
55
56 #define MEP_CONFIG     (mep_config_map[mep_config_index].config_enum)
57 #define MEP_CPU        (mep_config_map[mep_config_index].cpu_flag)
58 #define MEP_OMASK      (mep_config_map[mep_config_index].option_mask)
59 #define MEP_VLIW       (mep_config_map[mep_config_index].vliw_bits > 0)
60 #define MEP_VLIW32     (mep_config_map[mep_config_index].vliw_bits == 32)
61 #define MEP_VLIW64     (mep_config_map[mep_config_index].vliw_bits == 64)
62 #define MEP_COP16_ISA  (mep_config_map[mep_config_index].cop16_isa)
63 #define MEP_COP32_ISA  (mep_config_map[mep_config_index].cop32_isa)
64 #define MEP_COP48_ISA  (mep_config_map[mep_config_index].cop48_isa)
65 #define MEP_COP64_ISA  (mep_config_map[mep_config_index].cop64_isa)
66 #define MEP_COP_ISA    (mep_config_map[mep_config_index].cop_isa)
67 #define MEP_CORE_ISA   (mep_config_map[mep_config_index].core_isa)
68
69 /* begin-cop-ip-supported-defines */
70 #define MEP_IVC2_SUPPORTED 1
71 /* end-cop-ip-supported-defines */
72
73 extern int mep_insn_supported_by_isa (const CGEN_INSN *, CGEN_ATTR_VALUE_BITSET_TYPE *);
74
75 /* A mask for all ISAs executed by the core.  */
76 #define MEP_ALL_CORE_ISAS_MASK mep_all_core_isas_mask
77 extern CGEN_ATTR_VALUE_BITSET_TYPE mep_all_core_isas_mask;
78
79 #define MEP_INSN_CORE_P(insn) ( \
80   init_mep_all_core_isas_mask (), \
81   mep_insn_supported_by_isa (insn, & MEP_ALL_CORE_ISAS_MASK) \
82 )
83
84 /* A mask for all ISAs executed by a VLIW coprocessor.  */
85 #define MEP_ALL_COP_ISAS_MASK mep_all_cop_isas_mask 
86 extern CGEN_ATTR_VALUE_BITSET_TYPE mep_all_cop_isas_mask;
87
88 #define MEP_INSN_COP_P(insn) ( \
89   init_mep_all_cop_isas_mask (), \
90   mep_insn_supported_by_isa (insn, & MEP_ALL_COP_ISAS_MASK) \
91 )
92
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 *);
95
96 /* -- asm.c */
97
98 #include "elf/mep.h"
99
100 #define CGEN_VALIDATE_INSN_SUPPORTED
101 #define mep_cgen_insn_supported mep_cgen_insn_supported_asm
102
103        const char * parse_csrn       (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *);
104        const char * parse_tpreg      (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *);
105        const char * parse_spreg      (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *);
106        const char * parse_mep_align  (CGEN_CPU_DESC, const char **, enum cgen_operand_type, long *);
107        const char * parse_mep_alignu (CGEN_CPU_DESC, const char **, enum cgen_operand_type, unsigned long *);
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 *);
115
116 const char *
117 parse_csrn (CGEN_CPU_DESC cd, const char **strp,
118             CGEN_KEYWORD *keyword_table, long *field)
119 {
120   const char *err;
121   unsigned long value;
122
123   err = cgen_parse_keyword (cd, strp, keyword_table, field);
124   if (!err)
125     return NULL;
126
127   err = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_CSRN_IDX, & value);
128   if (err)
129     return err;
130   *field = value;
131   return NULL;
132 }
133
134 /* begin-cop-ip-parse-handlers */
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)
145 {
146   return cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_cr_ivc2, field);
147 }
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)
158 {
159   return cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_ccr_ivc2, field);
160 }
161 /* end-cop-ip-parse-handlers */
162
163 const char *
164 parse_tpreg (CGEN_CPU_DESC cd, const char ** strp,
165              CGEN_KEYWORD *keyword_table, long *field)
166 {
167   const char *err;
168
169   err = cgen_parse_keyword (cd, strp, keyword_table, field);
170   if (err)
171     return err;
172   if (*field != 13)
173     return _("Only $tp or $13 allowed for this opcode");
174   return NULL;
175 }
176
177 const char *
178 parse_spreg (CGEN_CPU_DESC cd, const char ** strp,
179              CGEN_KEYWORD *keyword_table, long *field)
180 {
181   const char *err;
182
183   err = cgen_parse_keyword (cd, strp, keyword_table, field);
184   if (err)
185     return err;
186   if (*field != 15)
187     return _("Only $sp or $15 allowed for this opcode");
188   return NULL;
189 }
190
191 const char *
192 parse_mep_align (CGEN_CPU_DESC cd, const char ** strp,
193                  enum cgen_operand_type type, long *field)
194 {
195   long lsbs = 0;
196   const char *err;
197
198   switch (type)
199     {
200     case MEP_OPERAND_PCREL8A2:
201     case MEP_OPERAND_PCREL12A2:
202     case MEP_OPERAND_PCREL17A2:
203     case MEP_OPERAND_PCREL24A2:
204       err = cgen_parse_signed_integer   (cd, strp, type, field);
205       break;
206     case MEP_OPERAND_PCABS24A2:
207     case MEP_OPERAND_UDISP7:
208     case MEP_OPERAND_UDISP7A2:
209     case MEP_OPERAND_UDISP7A4:
210     case MEP_OPERAND_UIMM7A4:
211     case MEP_OPERAND_ADDR24A4:
212       err = cgen_parse_unsigned_integer (cd, strp, type, (unsigned long *) field);
213       break;
214     default:
215       abort();
216     }
217   if (err)
218     return err;
219   switch (type)
220     {
221     case MEP_OPERAND_UDISP7:
222       lsbs = 0;
223       break;
224     case MEP_OPERAND_PCREL8A2:
225     case MEP_OPERAND_PCREL12A2:
226     case MEP_OPERAND_PCREL17A2:
227     case MEP_OPERAND_PCREL24A2:
228     case MEP_OPERAND_PCABS24A2:
229     case MEP_OPERAND_UDISP7A2:
230       lsbs = *field & 1;
231       break;
232     case MEP_OPERAND_UDISP7A4:
233     case MEP_OPERAND_UIMM7A4:
234     case MEP_OPERAND_ADDR24A4:
235       lsbs = *field & 3;
236       break;
237       lsbs = *field & 7;
238       break;
239     default:
240       /* Safe assumption?  */
241       abort ();
242     }
243   if (lsbs)
244     return "Value is not aligned enough";
245   return NULL;
246 }
247
248 const char *
249 parse_mep_alignu (CGEN_CPU_DESC cd, const char ** strp,
250                  enum cgen_operand_type type, unsigned long *field)
251 {
252   return parse_mep_align (cd, strp, type, (long *) field);
253 }
254
255
256 /* Handle %lo(), %tpoff(), %sdaoff(), %hi(), and other signed
257    constants in a signed context.  */
258
259 static const char *
260 parse_signed16 (CGEN_CPU_DESC cd,
261                 const char **strp,
262                 int opindex,
263                 long *valuep)
264 {
265   return parse_lo16 (cd, strp, opindex, valuep, 1);
266 }
267
268 static const char *
269 parse_lo16 (CGEN_CPU_DESC cd,
270             const char **strp,
271             int opindex,
272             long *valuep,
273             long signedp)
274 {
275   const char *errmsg;
276   enum cgen_parse_operand_result result_type;
277   bfd_vma value;
278
279   if (strncasecmp (*strp, "%lo(", 4) == 0)
280     {
281       *strp += 4;
282       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_LOW16,
283                                    & result_type, & value);
284       if (**strp != ')')
285         return _("missing `)'");
286       ++*strp;
287       if (errmsg == NULL
288           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
289         value &= 0xffff;
290       if (signedp)
291         *valuep = (long)(short) value;
292       else
293         *valuep = value;
294       return errmsg;
295     }
296
297   if (strncasecmp (*strp, "%hi(", 4) == 0)
298     {
299       *strp += 4;
300       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16S,
301                                    & result_type, & value);
302       if (**strp != ')')
303         return _("missing `)'");
304       ++*strp;
305       if (errmsg == NULL
306           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
307         value = (value + 0x8000) >> 16;
308       *valuep = value;
309       return errmsg;
310     }
311
312   if (strncasecmp (*strp, "%uhi(", 5) == 0)
313     {
314       *strp += 5;
315       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16U,
316                                    & result_type, & value);
317       if (**strp != ')')
318         return _("missing `)'");
319       ++*strp;
320       if (errmsg == NULL
321           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
322         value = value >> 16;
323       *valuep = value;
324       return errmsg;
325     }
326
327   if (strncasecmp (*strp, "%sdaoff(", 8) == 0)
328     {
329       *strp += 8;
330       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_GPREL,
331                                    NULL, & value);
332       if (**strp != ')')
333         return _("missing `)'");
334       ++*strp;
335       *valuep = value;
336       return errmsg;
337     }
338
339   if (strncasecmp (*strp, "%tpoff(", 7) == 0)
340     {
341       *strp += 7;
342       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_TPREL,
343                                    NULL, & value);
344       if (**strp != ')')
345         return _("missing `)'");
346       ++*strp;
347       *valuep = value;
348       return errmsg;
349     }
350
351   if (**strp == '%')
352     return _("invalid %function() here");
353
354   return cgen_parse_signed_integer (cd, strp, opindex, valuep);
355 }
356
357 static const char *
358 parse_unsigned16 (CGEN_CPU_DESC cd,
359                   const char **strp,
360                   int opindex,
361                   unsigned long *valuep)
362 {
363   return parse_lo16 (cd, strp, opindex, (long *) valuep, 0);
364 }
365
366 static const char *
367 parse_signed16_range (CGEN_CPU_DESC cd,
368                       const char **strp,
369                       int opindex,
370                       signed long *valuep)
371 {
372   const char *errmsg = 0;
373   signed long value;
374
375   errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
376   if (errmsg)
377     return errmsg;
378
379   if (value < -32768 || value > 32767)
380     return _("Immediate is out of range -32768 to 32767");
381
382   *valuep = value;
383   return 0;
384 }
385
386 static const char *
387 parse_unsigned16_range (CGEN_CPU_DESC cd,
388                         const char **strp,
389                         int opindex,
390                         unsigned long *valuep)
391 {
392   const char *errmsg = 0;
393   unsigned long value;
394
395   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
396   if (errmsg)
397     return errmsg;
398
399   if (value > 65535)
400     return _("Immediate is out of range 0 to 65535");
401
402   *valuep = value;
403   return 0;
404 }
405
406 /* A special case of parse_signed16 which accepts only the value zero.  */
407
408 static const char *
409 parse_zero (CGEN_CPU_DESC cd, const char **strp, int opindex, long *valuep)
410 {
411   const char *errmsg;
412   enum cgen_parse_operand_result result_type;
413   bfd_vma value;
414
415   /*fprintf(stderr, "dj: signed parse opindex `%s'\n", *strp);*/
416
417   /* Prevent ($ry) from being attempted as an expression on 'sw $rx,($ry)'.
418      It will fail and cause ry to be listed as an undefined symbol in the
419      listing.  */
420   if (strncmp (*strp, "($", 2) == 0)
421     return "not zero"; /* any string will do -- will never be seen.  */
422
423   if (strncasecmp (*strp, "%lo(", 4) == 0)
424     {
425       *strp += 4;
426       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_LOW16,
427                                    &result_type, &value);
428       if (**strp != ')')
429         return "missing `)'";
430       ++*strp;
431       if (errmsg == NULL
432           && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
433         return "not zero"; /* any string will do -- will never be seen.  */
434       *valuep = value;
435       return errmsg;
436     }
437
438   if (strncasecmp (*strp, "%hi(", 4) == 0)
439     {
440       *strp += 4;
441       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16S,
442                                    &result_type, &value);
443       if (**strp != ')')
444         return "missing `)'";
445       ++*strp;
446       if (errmsg == NULL
447           && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
448         return "not zero"; /* any string will do -- will never be seen.  */
449       *valuep = value;
450       return errmsg;
451     }
452
453   if (strncasecmp (*strp, "%uhi(", 5) == 0)
454     {
455       *strp += 5;
456       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16U,
457                                    &result_type, &value);
458       if (**strp != ')')
459         return "missing `)'";
460       ++*strp;
461       if (errmsg == NULL
462           && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
463         return "not zero"; /* any string will do -- will never be seen.  */
464       *valuep = value;
465       return errmsg;
466     }
467
468   if (strncasecmp (*strp, "%sdaoff(", 8) == 0)
469     {
470       *strp += 8;
471       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_GPREL,
472                                    &result_type, &value);
473       if (**strp != ')')
474         return "missing `)'";
475       ++*strp;
476       if (errmsg == NULL
477           && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
478         return "not zero"; /* any string will do -- will never be seen.  */
479       *valuep = value;
480       return errmsg;
481     }
482
483   if (strncasecmp (*strp, "%tpoff(", 7) == 0)
484     {
485       *strp += 7;
486       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_TPREL,
487                                    &result_type, &value);
488       if (**strp != ')')
489         return "missing `)'";
490       ++*strp;
491       if (errmsg == NULL
492           && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
493         return "not zero"; /* any string will do -- will never be seen.  */
494       *valuep = value;
495       return errmsg;
496     }
497
498   if (**strp == '%')
499     return "invalid %function() here";
500
501   errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_NONE,
502                                &result_type, &value);
503   if (errmsg == NULL
504       && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
505     return "not zero"; /* any string will do -- will never be seen.  */
506
507   return errmsg;
508 }
509
510 static const char *
511 parse_unsigned7 (CGEN_CPU_DESC cd, const char **strp,
512                  enum cgen_operand_type opindex, unsigned long *valuep)
513 {
514   const char *errmsg;
515   bfd_vma value;
516
517   /* fprintf(stderr, "dj: unsigned7 parse `%s'\n", *strp); */
518
519   if (strncasecmp (*strp, "%tpoff(", 7) == 0)
520     {
521       int reloc;
522       *strp += 7;
523       switch (opindex)
524         {
525         case MEP_OPERAND_UDISP7:
526           reloc = BFD_RELOC_MEP_TPREL7;
527           break;
528         case MEP_OPERAND_UDISP7A2:
529           reloc = BFD_RELOC_MEP_TPREL7A2;
530           break;
531         case MEP_OPERAND_UDISP7A4:
532           reloc = BFD_RELOC_MEP_TPREL7A4;
533           break;
534         default:
535           /* Safe assumption?  */
536           abort (); 
537         }
538       errmsg = cgen_parse_address (cd, strp, opindex, reloc,
539                                    NULL, &value);
540       if (**strp != ')')
541         return "missing `)'";
542       ++*strp;
543       *valuep = value;
544       return errmsg;
545     }
546
547   if (**strp == '%')
548     return _("invalid %function() here");
549
550   return parse_mep_alignu (cd, strp, opindex, valuep);
551 }
552
553 static ATTRIBUTE_UNUSED const char *
554 parse_cdisp10 (CGEN_CPU_DESC cd,
555                const char **strp,
556                int opindex,
557                long *valuep)
558 {
559   const char *errmsg = 0;
560   signed long value;
561   long have_zero = 0;
562   int wide = 0;
563   int alignment;
564
565   switch (opindex)
566     {
567     case MEP_OPERAND_CDISP10A4:
568       alignment = 2;
569       break;
570     case MEP_OPERAND_CDISP10A2:
571       alignment = 1;
572       break;
573     case MEP_OPERAND_CDISP10:
574     default:
575       alignment = 0;
576       break;
577     }
578
579   if ((MEP_CPU & EF_MEP_CPU_MASK) == EF_MEP_CPU_C5)
580     wide = 1;
581
582   if (strncmp (*strp, "0x0", 3) == 0 
583       || (**strp == '0' && *(*strp + 1) != 'x'))
584     have_zero = 1;
585
586   errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
587   if (errmsg)
588     return errmsg;
589
590   if (wide)
591     {
592       if (value < -512 || value > 511)
593         return _("Immediate is out of range -512 to 511");
594     }
595   else
596     {
597       if (value < -128 || value > 127)
598         return _("Immediate is out of range -128 to 127");
599     }
600
601   if (value & ((1<<alignment)-1))
602     return _("Value is not aligned enough");
603
604   /* If this field may require a relocation then use larger dsp16.  */
605   if (! have_zero && value == 0)
606     return (wide ? _("Immediate is out of range -512 to 511")
607             : _("Immediate is out of range -128 to 127"));
608
609   *valuep = value;
610   return 0;
611 }
612
613 /* BEGIN LIGHTWEIGHT MACRO PROCESSOR.  */
614
615 #define MAXARGS 9
616
617 typedef struct
618 {
619   char *name;
620   char *expansion;
621 }  macro;
622
623 typedef struct
624 {
625   const char *start;
626   int len;
627 } arg;
628
629 macro macros[] =
630 {
631   { "sizeof", "(`1.end + (- `1))"},
632   { "startof", "(`1 | 0)" },
633   { "align4", "(`1&(~3))"},
634 /*{ "hi", "(((`1+0x8000)>>16) & 0xffff)" },  */
635 /*{ "lo", "(`1 & 0xffff)" },  */
636 /*{ "sdaoff", "((`1-__sdabase) & 0x7f)"},  */
637 /*{ "tpoff", "((`1-__tpbase) & 0x7f)"},  */
638   { 0,0 }
639 };
640
641 static char  * expand_string    (const char *, int);
642
643 static const char *
644 mep_cgen_expand_macros_and_parse_operand
645   (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
646
647 static char *
648 str_append (char *dest, const char *input, int len)
649 {  
650   char *new_dest;
651   int oldlen;
652
653   if (len == 0)
654     return dest;
655   /* printf("str_append: <<%s>>, <<%s>>, %d\n", dest, input, len); */
656   oldlen = (dest ? strlen(dest) : 0);
657   new_dest = realloc (dest, oldlen + len + 1);
658   memset (new_dest + oldlen, 0, len + 1);
659   return strncat (new_dest, input, len);
660 }
661
662 static macro *
663 lookup_macro (const char *name)
664 {
665   macro *m;
666
667   for (m = macros; m->name; ++m)
668     if (strncmp (m->name, name, strlen(m->name)) == 0)
669       return m;
670
671   return 0;
672 }
673
674 static char *
675 expand_macro (arg *args, int narg, macro *mac)
676 {
677   char *result = 0, *rescanned_result = 0;
678   char *e = mac->expansion;
679   char *mark = e;
680   int mac_arg = 0;
681
682   /*  printf("expanding macro %s with %d args\n", mac->name, narg + 1); */
683   while (*e)
684     {
685       if (*e == '`' && 
686           (*e+1) && 
687           ((*(e + 1) - '1') <= MAXARGS) &&
688           ((*(e + 1) - '1') <= narg))
689         {
690           result = str_append (result, mark, e - mark);
691           mac_arg = (*(e + 1) - '1');
692           /* printf("replacing `%d with %s\n", mac_arg+1, args[mac_arg].start); */
693           result = str_append (result, args[mac_arg].start, args[mac_arg].len);
694           ++e;
695           mark = e+1;
696         }
697       ++e;
698     }
699
700   if (mark != e)
701     result = str_append (result, mark, e - mark);
702
703   if (result)
704     {
705       rescanned_result = expand_string (result, 0);
706       free (result);
707       return rescanned_result;
708     }
709   else 
710     return result;
711 }
712
713 #define IN_TEXT 0
714 #define IN_ARGS 1
715
716 static char *
717 expand_string (const char *in, int first_only)
718 {
719   int num_expansions = 0;
720   int depth = 0;
721   int narg = -1;
722   arg args[MAXARGS];
723   int state = IN_TEXT;
724   const char *mark = in;
725   macro *pmacro = NULL;
726   char *expansion = 0;
727   char *result = 0;
728
729   while (*in)
730     {
731       switch (state)
732         {
733         case IN_TEXT:
734           if (*in == '%' && *(in + 1) && (!first_only || num_expansions == 0)) 
735             {         
736               pmacro = lookup_macro (in + 1);
737               if (pmacro)
738                 {
739                   /* printf("entering state %d at '%s'...\n", state, in); */
740                   result = str_append (result, mark, in - mark);
741                   mark = in;
742                   in += 1 + strlen (pmacro->name);
743                   while (*in == ' ') ++in;
744                   if (*in != '(')
745                     {
746                       state = IN_TEXT;                
747                       pmacro = NULL;
748                     }
749                   else
750                     {
751                       state = IN_ARGS;
752                       narg = 0;
753                       args[narg].start = in + 1;
754                       args[narg].len = 0;
755                       mark = in + 1;                          
756                     }
757                 }
758             }
759           break;
760         case IN_ARGS:
761           if (depth == 0)
762             {
763               switch (*in)
764                 {
765                 case ',':
766                   narg++;
767                   args[narg].start = (in + 1);
768                   args[narg].len = 0;
769                   break;
770                 case ')':
771                   state = IN_TEXT;
772                   /* printf("entering state %d at '%s'...\n", state, in); */
773                   if (pmacro)
774                     {
775                       expansion = 0;
776                       expansion = expand_macro (args, narg, pmacro);
777                       num_expansions++;
778                       if (expansion)
779                         {
780                           result = str_append (result, expansion, strlen (expansion));
781                           free (expansion);
782                         }
783                     }
784                   else
785                     {
786                       result = str_append (result, mark, in - mark);
787                     }
788                   pmacro = NULL;
789                   mark = in + 1;
790                   break;
791                 case '(':
792                   depth++;
793                   /* Fall through.  */
794                 default:
795                   args[narg].len++;
796                   break;                  
797                 }
798             } 
799           else
800             {
801               if (*in == ')')
802                 depth--;
803               if (narg > -1)
804                 args[narg].len++;
805             }
806           
807         }
808       ++in;
809     }
810   
811   if (mark != in)
812     result = str_append (result, mark, in - mark);
813   
814   return result;
815 }
816
817 #undef IN_ARGS
818 #undef IN_TEXT
819 #undef MAXARGS
820
821
822 /* END LIGHTWEIGHT MACRO PROCESSOR.  */
823
824 const char * mep_cgen_parse_operand
825   (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
826
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)
830 {
831   const char * errmsg = NULL;
832   char *str = 0, *hold = 0;
833   const char **strp = 0;
834
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); */
838
839   hold = str;
840   strp = (const char **)(&str);
841
842   errmsg = mep_cgen_parse_operand (cd, opindex, strp, fields);
843
844   /* Now work out the advance.  */
845   if (strlen (str) == 0)
846     *strp_in += strlen (*strp_in);
847
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     }
857
858   if (hold)
859     free (hold);
860
861   return errmsg;
862 }
863
864 #define CGEN_ASM_INIT_HOOK (cd->parse_operand = mep_cgen_expand_macros_and_parse_operand); 
865
866 /* -- dis.c */
867
868 #include "elf/mep.h"
869 #include "elf-bfd.h"
870
871 #define CGEN_VALIDATE_INSN_SUPPORTED
872
873 static void print_tpreg (CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned int);
874 static void print_spreg (CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned int);
875
876 static void
877 print_tpreg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, PTR dis_info,
878              CGEN_KEYWORD *table ATTRIBUTE_UNUSED, long val ATTRIBUTE_UNUSED,
879              unsigned int flags ATTRIBUTE_UNUSED)
880 {
881   disassemble_info *info = (disassemble_info *) dis_info;
882
883   (*info->fprintf_func) (info->stream, "$tp");
884 }
885
886 static void
887 print_spreg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, PTR dis_info, 
888              CGEN_KEYWORD *table ATTRIBUTE_UNUSED, long val ATTRIBUTE_UNUSED,
889              unsigned int flags ATTRIBUTE_UNUSED)
890 {
891   disassemble_info *info = (disassemble_info *) dis_info;
892
893   (*info->fprintf_func) (info->stream, "$sp");
894 }
895
896 /* begin-cop-ip-print-handlers */
897 static void
898 print_ivc2_cr (CGEN_CPU_DESC,
899         void *,
900         CGEN_KEYWORD *,
901         long,
902         unsigned int) ATTRIBUTE_UNUSED;
903 static void
904 print_ivc2_cr (CGEN_CPU_DESC cd,
905         void *dis_info,
906         CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED,
907         long value,
908         unsigned int attrs)
909 {
910   print_keyword (cd, dis_info, & mep_cgen_opval_h_cr_ivc2, value, attrs);
911 }
912 static void
913 print_ivc2_ccr (CGEN_CPU_DESC,
914         void *,
915         CGEN_KEYWORD *,
916         long,
917         unsigned int) ATTRIBUTE_UNUSED;
918 static void
919 print_ivc2_ccr (CGEN_CPU_DESC cd,
920         void *dis_info,
921         CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED,
922         long value,
923         unsigned int attrs)
924 {
925   print_keyword (cd, dis_info, & mep_cgen_opval_h_ccr_ivc2, value, attrs);
926 }
927 /* end-cop-ip-print-handlers */
928
929 /************************************************************\
930 *********************** Experimental *************************
931 \************************************************************/
932
933 #undef  CGEN_PRINT_INSN
934 #define CGEN_PRINT_INSN mep_print_insn
935
936 static int
937 mep_print_vliw_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info,
938                       bfd_byte *buf, int corelength, int copro1length,
939                       int copro2length ATTRIBUTE_UNUSED)
940 {
941   int i;
942   int status = 0;
943   /* char insnbuf[CGEN_MAX_INSN_SIZE]; */
944   bfd_byte insnbuf[64];
945
946   /* If corelength > 0 then there is a core insn present. It
947      will be at the beginning of the buffer.  After printing
948      the core insn, we need to print the + on the next line.  */
949   if (corelength > 0)
950     {
951       int my_status = 0;
952          
953       for (i = 0; i < corelength; i++ )
954         insnbuf[i] = buf[i];
955       cd->isas = & MEP_CORE_ISA;
956          
957       my_status = print_insn (cd, pc, info, insnbuf, corelength);
958       if (my_status != corelength)
959         {
960           (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
961           my_status = corelength;
962         }
963       status += my_status;
964
965       /* Print the + to indicate that the following copro insn is   */
966       /* part of a vliw group.                                      */
967       if (copro1length > 0)
968         (*info->fprintf_func) (info->stream, " + "); 
969     }
970
971   /* Now all that is left to be processed is the coprocessor insns
972      In vliw mode, there will always be one.  Its positioning will
973      be from byte corelength to byte corelength+copro1length -1.
974      No need to check for existence.   Also, the first vliw insn,
975      will, as spec'd, always be at least as long as the core insn
976      so we don't need to flush the buffer.  */
977   if (copro1length > 0)
978     {
979       int my_status = 0;
980          
981       for (i = corelength; i < corelength + copro1length; i++ )
982         insnbuf[i - corelength] = buf[i];
983
984       switch (copro1length)
985         {
986         case 0:
987           break;
988         case 2:
989           cd->isas = & MEP_COP16_ISA;
990           break;
991         case 4:
992           cd->isas = & MEP_COP32_ISA;
993           break;
994         case 6:
995           cd->isas = & MEP_COP48_ISA;
996           break;
997         case 8:
998           cd->isas = & MEP_COP64_ISA;
999           break; 
1000         default:
1001           /* Shouldn't be anything but 16,32,48,64.  */
1002           break;
1003         }
1004
1005       my_status = print_insn (cd, pc, info, insnbuf, copro1length);
1006
1007       if (my_status != copro1length)
1008         {
1009           (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
1010           my_status = copro1length;
1011         }
1012       status += my_status;
1013     }
1014
1015 #if 0
1016   /* Now we need to process the second copro insn if it exists. We
1017      have no guarantee that the second copro insn will be longer
1018      than the first, so we have to flush the buffer if we are have
1019      a second copro insn to process.  If present, this insn will
1020      be in the position from byte corelength+copro1length to byte
1021      corelength+copro1length+copro2length-1 (which better equal 8
1022      or else we're in big trouble.  */
1023   if (copro2length > 0)
1024     {
1025       int my_status = 0;
1026
1027       for (i = 0; i < 64 ; i++)
1028         insnbuf[i] = 0;
1029
1030       for (i = corelength + copro1length; i < 64; i++)
1031         insnbuf[i - (corelength + copro1length)] = buf[i];
1032       
1033       switch (copro2length)
1034         {
1035         case 2:
1036           cd->isas = 1 << ISA_EXT_COP1_16;
1037           break;
1038         case 4:
1039           cd->isas = 1 << ISA_EXT_COP1_32;
1040           break;
1041         case 6:
1042           cd->isas = 1 << ISA_EXT_COP1_48;
1043           break;
1044         case 8:
1045           cd->isas = 1 << ISA_EXT_COP1_64; 
1046           break;
1047         default:
1048           /* Shouldn't be anything but 16,32,48,64.  */
1049           break;
1050         }
1051
1052       my_status = print_insn (cd, pc, info, insnbuf, copro2length);
1053
1054       if (my_status != copro2length)
1055         {
1056           (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
1057           my_status = copro2length;
1058         }
1059
1060       status += my_status;
1061     }
1062 #endif
1063
1064   /* Status should now be the number of bytes that were printed
1065      which should be 4 for VLIW32 mode and 64 for VLIW64 mode.  */
1066
1067   if ((!MEP_VLIW64 && (status != 4)) || (MEP_VLIW64 && (status != 8)))
1068     return -1;
1069   else
1070     return status;
1071 }
1072
1073 /* The two functions mep_examine_vliw[32,64]_insns are used find out 
1074    which vliw combinaion (16 bit core with 48 bit copro, 32 bit core 
1075    with 32 bit copro, etc.) is present.  Later on, when internally   
1076    parallel coprocessors are handled, only these functions should    
1077    need to be changed.                                               
1078
1079    At this time only the following combinations are supported: 
1080    
1081    VLIW32 Mode:
1082    16 bit core insn (core) and 16 bit coprocessor insn (cop1)
1083    32 bit core insn (core)
1084    32 bit coprocessor insn (cop1)
1085    Note: As of this time, I do not believe we have enough information
1086          to distinguish a 32 bit core insn from a 32 bit cop insn. Also,
1087          no 16 bit coprocessor insns have been specified.  
1088
1089    VLIW64 Mode:
1090    16 bit core insn (core) and 48 bit coprocessor insn (cop1)
1091    32 bit core insn (core) and 32 bit coprocessor insn (cop1)
1092    64 bit coprocessor insn (cop1)
1093   
1094    The framework for an internally parallel coprocessor is also
1095    present (2nd coprocessor insn is cop2), but at this time it 
1096    is not used.  This only appears to be valid in VLIW64 mode.  */
1097
1098 static int
1099 mep_examine_vliw32_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
1100 {
1101   int status;
1102   int buflength;
1103   int corebuflength;
1104   int cop1buflength;
1105   int cop2buflength;
1106   bfd_byte buf[CGEN_MAX_INSN_SIZE];  
1107   char indicator16[1];
1108   char indicatorcop32[2]; 
1109
1110   /* At this time we're not supporting internally parallel coprocessors,
1111      so cop2buflength will always be 0.  */
1112   cop2buflength = 0;
1113
1114   /* Read in 32 bits.  */
1115   buflength = 4; /* VLIW insn spans 4 bytes.  */
1116   status = (*info->read_memory_func) (pc, buf, buflength, info);
1117
1118   if (status != 0)
1119     {
1120       (*info->memory_error_func) (status, pc, info);
1121       return -1;
1122     }
1123
1124   /* Put the big endian representation of the bytes to be examined
1125      in the temporary buffers for examination.  */
1126
1127   if (info->endian == BFD_ENDIAN_BIG)
1128     {
1129       indicator16[0] = buf[0];
1130       indicatorcop32[0] = buf[0];
1131       indicatorcop32[1] = buf[1];
1132     }
1133   else
1134     {
1135       indicator16[0] = buf[1];
1136       indicatorcop32[0] = buf[1];
1137       indicatorcop32[1] = buf[0];
1138     }
1139
1140   /* If the two high order bits are 00, 01 or 10, we have a 16 bit
1141      core insn and a 48 bit copro insn.  */
1142
1143   if ((indicator16[0] & 0x80) && (indicator16[0] & 0x40))
1144     {
1145       if ((indicatorcop32[0] & 0xf0) == 0xf0 && (indicatorcop32[1] & 0x07) == 0x07)
1146         {
1147           /* We have a 32 bit copro insn.  */
1148           corebuflength = 0;
1149           /* All 4 4ytes are one copro insn. */
1150           cop1buflength = 4;
1151         }
1152       else
1153         {
1154           /* We have a 32 bit core.  */
1155           corebuflength = 4;
1156           cop1buflength = 0;
1157         }
1158     }
1159   else
1160     {
1161       /* We have a 16 bit core insn and a 16 bit copro insn.  */
1162       corebuflength = 2;
1163       cop1buflength = 2;
1164     }
1165
1166   /* Now we have the distrubution set.  Print them out.  */
1167   status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength,
1168                                  cop1buflength, cop2buflength);
1169
1170   return status;
1171 }
1172
1173 static int
1174 mep_examine_vliw64_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
1175 {
1176   int status;
1177   int buflength;
1178   int corebuflength;
1179   int cop1buflength;
1180   int cop2buflength;
1181   bfd_byte buf[CGEN_MAX_INSN_SIZE];
1182   char indicator16[1];
1183   char indicator64[4];
1184
1185   /* At this time we're not supporting internally parallel
1186      coprocessors, so cop2buflength will always be 0.  */
1187   cop2buflength = 0;
1188
1189   /* Read in 64 bits.  */
1190   buflength = 8; /* VLIW insn spans 8 bytes.  */
1191   status = (*info->read_memory_func) (pc, buf, buflength, info);
1192
1193   if (status != 0)
1194     {
1195       (*info->memory_error_func) (status, pc, info);
1196       return -1;
1197     }
1198
1199   /* We have all 64 bits in the buffer now.  We have to figure out
1200      what combination of instruction sizes are present.  The two
1201      high order bits will indicate whether or not we have a 16 bit
1202      core insn or not.  If not, then we have to look at the 7,8th
1203      bytes to tell whether we have 64 bit copro insn or a 32 bit
1204      core insn with a 32 bit copro insn.  Endianness will make a
1205      difference here.  */
1206
1207   /* Put the big endian representation of the bytes to be examined
1208      in the temporary buffers for examination.  */
1209
1210   /* indicator16[0] = buf[0];  */
1211   if (info->endian == BFD_ENDIAN_BIG)
1212     {
1213       indicator16[0] = buf[0];
1214       indicator64[0] = buf[0];
1215       indicator64[1] = buf[1];
1216       indicator64[2] = buf[2];
1217       indicator64[3] = buf[3];
1218     }
1219   else
1220     {
1221       indicator16[0] = buf[1];
1222       indicator64[0] = buf[1];
1223       indicator64[1] = buf[0];
1224       indicator64[2] = buf[3];
1225       indicator64[3] = buf[2];
1226     }
1227
1228   /* If the two high order bits are 00, 01 or 10, we have a 16 bit
1229      core insn and a 48 bit copro insn.  */
1230
1231   if ((indicator16[0] & 0x80) && (indicator16[0] & 0x40))
1232     {
1233       if ((indicator64[0] & 0xf0) == 0xf0 && (indicator64[1] & 0x07) == 0x07
1234           && ((indicator64[2] & 0xfe) != 0xf0 || (indicator64[3] & 0xf4) != 0))
1235         {
1236           /* We have a 64 bit copro insn.  */
1237           corebuflength = 0;
1238           /* All 8 bytes are one copro insn.  */
1239           cop1buflength = 8;
1240         }
1241       else
1242         {
1243           /* We have a 32 bit core insn and a 32 bit copro insn.  */
1244           corebuflength = 4;
1245           cop1buflength = 4;
1246         }
1247     }
1248   else
1249     {
1250       /* We have a 16 bit core insn and a 48 bit copro insn.  */
1251       corebuflength = 2;
1252       cop1buflength = 6;
1253     }
1254
1255   /* Now we have the distrubution set.  Print them out. */
1256   status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength,
1257                                  cop1buflength, cop2buflength);
1258
1259   return status;
1260 }
1261
1262 #ifdef MEP_IVC2_SUPPORTED
1263
1264 static int
1265 print_slot_insn (CGEN_CPU_DESC cd,
1266                  bfd_vma pc,
1267                  disassemble_info *info,
1268                  SLOTS_ATTR slot,
1269                  bfd_byte *buf)
1270 {
1271   const CGEN_INSN_LIST *insn_list;
1272   CGEN_INSN_INT insn_value;
1273   CGEN_EXTRACT_INFO ex_info;
1274
1275   insn_value = cgen_get_insn_value (cd, buf, 32);
1276
1277   /* Fill in ex_info fields like read_insn would.  Don't actually call
1278      read_insn, since the incoming buffer is already read (and possibly
1279      modified a la m32r).  */
1280   ex_info.valid = (1 << 8) - 1;
1281   ex_info.dis_info = info;
1282   ex_info.insn_bytes = buf;
1283
1284   /* The instructions are stored in hash lists.
1285      Pick the first one and keep trying until we find the right one.  */
1286
1287   insn_list = CGEN_DIS_LOOKUP_INSN (cd, (char *) buf, insn_value);
1288   while (insn_list != NULL)
1289     {
1290       const CGEN_INSN *insn = insn_list->insn;
1291       CGEN_FIELDS fields;
1292       int length;
1293
1294       if ((CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG)
1295            && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG) != MEP_CONFIG)
1296           || ! (CGEN_ATTR_CGEN_INSN_SLOTS_VALUE (CGEN_INSN_ATTRS (insn)) & (1 << slot)))
1297         {
1298           insn_list = CGEN_DIS_NEXT_INSN (insn_list);
1299           continue;
1300         }
1301
1302       if ((insn_value & CGEN_INSN_BASE_MASK (insn))
1303           == CGEN_INSN_BASE_VALUE (insn))
1304         {
1305           /* Printing is handled in two passes.  The first pass parses the
1306              machine insn and extracts the fields.  The second pass prints
1307              them.  */
1308
1309           length = CGEN_EXTRACT_FN (cd, insn)
1310             (cd, insn, &ex_info, insn_value, &fields, pc);
1311
1312           /* Length < 0 -> error.  */
1313           if (length < 0)
1314             return length;
1315           if (length > 0)
1316             {
1317               CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
1318               /* Length is in bits, result is in bytes.  */
1319               return length / 8;
1320             }
1321         }
1322
1323       insn_list = CGEN_DIS_NEXT_INSN (insn_list);
1324     }
1325
1326   if (slot == SLOTS_P0S)
1327     (*info->fprintf_func) (info->stream, "*unknown-p0s*");
1328   else if (slot == SLOTS_P0)
1329     (*info->fprintf_func) (info->stream, "*unknown-p0*");
1330   else if (slot == SLOTS_P1)
1331     (*info->fprintf_func) (info->stream, "*unknown-p1*");
1332   else if (slot == SLOTS_C3)
1333     (*info->fprintf_func) (info->stream, "*unknown-c3*");
1334   return 0;
1335 }
1336
1337 static int
1338 mep_examine_ivc2_insns (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, bfd_vma pc ATTRIBUTE_UNUSED, disassemble_info *info ATTRIBUTE_UNUSED)
1339 {
1340   int status;
1341   int buflength;
1342   bfd_byte buf[8];
1343   bfd_byte insn[8];
1344   int e;
1345
1346   /* Read in 64 bits.  */
1347   buflength = 8; /* VLIW insn spans 8 bytes.  */
1348   status = (*info->read_memory_func) (pc, buf, buflength, info);
1349
1350   if (status != 0)
1351     {
1352       (*info->memory_error_func) (status, pc, info);
1353       return -1;
1354     }
1355
1356   if (info->endian == BFD_ENDIAN_LITTLE)
1357     e = 1;
1358   else
1359     e = 0;
1360
1361   if (((unsigned char)buf[0^e] & 0xf0) < 0xc0)
1362     {
1363       /*      <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */
1364       /* V1   [-----core-----][--------p0s-------][------------p1------------] */
1365
1366       print_insn (cd, pc, info, buf, 2);
1367
1368       insn[0^e] = 0;
1369       insn[1^e] = buf[2^e];
1370       insn[2^e] = buf[3^e];
1371       insn[3^e] = buf[4^e] & 0xf0;
1372       (*info->fprintf_func) (info->stream, " + ");
1373       print_slot_insn (cd, pc, info, SLOTS_P0S, insn);
1374
1375       insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4;
1376       insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4;
1377       insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4;
1378       insn[3^e] = buf[7^e] << 4;
1379       (*info->fprintf_func) (info->stream, " + ");
1380       print_slot_insn (cd, pc, info, SLOTS_P1, insn);
1381     }
1382   else if ((buf[0^e] & 0xf0) == 0xf0 && (buf[1^e] & 0x0f) == 0x07)
1383     {
1384       /*      <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */
1385       /* V3   1111[--p0--]0111[--------p0--------][------------p1------------] */
1386       /*                                          00000000111111112222222233333333 */
1387
1388       insn[0^e] = buf[0^e] << 4 | buf[1^e] >> 4;
1389       insn[1^e] = buf[2^e];
1390       insn[2^e] = buf[3^e];
1391       insn[3^e] = buf[4^e] & 0xf0;
1392       print_slot_insn (cd, pc, info, SLOTS_P0, insn);
1393
1394       insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4;
1395       insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4;
1396       insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4;
1397       insn[3^e] = buf[7^e] << 4;
1398       (*info->fprintf_func) (info->stream, " + ");
1399       print_slot_insn (cd, pc, info, SLOTS_P1, insn);
1400     }
1401   else
1402     {
1403       /*      <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */
1404       /* V2   [-------------core-------------]xxxx[------------p1------------] */
1405       print_insn (cd, pc, info, buf, 4);
1406
1407       insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4;
1408       insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4;
1409       insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4;
1410       insn[3^e] = buf[7^e] << 4;
1411       (*info->fprintf_func) (info->stream, " + ");
1412       print_slot_insn (cd, pc, info, SLOTS_P1, insn);
1413     }
1414
1415   return 8;
1416 }
1417
1418 #endif /* MEP_IVC2_SUPPORTED */
1419
1420 /* This is a hack.  SID calls this to update the disassembler as the
1421    CPU changes modes.  */
1422 static int mep_ivc2_disassemble_p = 0;
1423 static int mep_ivc2_vliw_disassemble_p = 0;
1424
1425 void
1426 mep_print_insn_set_ivc2_mode (int ivc2_p, int vliw_p, int cfg_idx);
1427 void
1428 mep_print_insn_set_ivc2_mode (int ivc2_p, int vliw_p, int cfg_idx)
1429 {
1430   mep_ivc2_disassemble_p = ivc2_p;
1431   mep_ivc2_vliw_disassemble_p = vliw_p;
1432   mep_config_index = cfg_idx;
1433 }
1434
1435 static int
1436 mep_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
1437 {
1438   int status;
1439   int cop_type;
1440   int ivc2 = 0;
1441   static CGEN_ATTR_VALUE_BITSET_TYPE *ivc2_core_isa = NULL;
1442
1443   if (ivc2_core_isa == NULL)
1444     {
1445       /* IVC2 has some core-only coprocessor instructions.  We
1446          use COP32 to flag those, and COP64 for the VLIW ones,
1447          since they have the same names.  */
1448       ivc2_core_isa = cgen_bitset_create (MAX_ISAS);
1449     }
1450
1451   /* Extract and adapt to configuration number, if available. */
1452   if (info->section && info->section->owner)
1453     {
1454       bfd *abfd = info->section->owner;
1455       mep_config_index = abfd->tdata.elf_obj_data->elf_header->e_flags & EF_MEP_INDEX_MASK;
1456       /* This instantly redefines MEP_CONFIG, MEP_OMASK, .... MEP_VLIW64 */
1457
1458       cop_type = abfd->tdata.elf_obj_data->elf_header->e_flags & EF_MEP_COP_MASK;
1459       if (cop_type == EF_MEP_COP_IVC2)
1460         ivc2 = 1;
1461     }
1462
1463   /* Picking the right ISA bitmask for the current context is tricky.  */
1464   if (info->section)
1465     {
1466       if (info->section->flags & SEC_MEP_VLIW)
1467         {
1468 #ifdef MEP_IVC2_SUPPORTED
1469           if (ivc2)
1470             {
1471               /* ivc2 has its own way of selecting its functions.  */
1472               cd->isas = & MEP_CORE_ISA;
1473               status = mep_examine_ivc2_insns (cd, pc, info);
1474             }
1475           else
1476 #endif
1477             /* Are we in 32 or 64 bit vliw mode?  */
1478             if (MEP_VLIW64)
1479               status = mep_examine_vliw64_insns (cd, pc, info);
1480             else
1481               status = mep_examine_vliw32_insns (cd, pc, info);
1482           /* Both the above branches set their own isa bitmasks.  */
1483         }
1484       else
1485         {
1486           if (ivc2)
1487             {
1488               cgen_bitset_clear (ivc2_core_isa);
1489               cgen_bitset_union (ivc2_core_isa, &MEP_CORE_ISA, ivc2_core_isa);
1490               cgen_bitset_union (ivc2_core_isa, &MEP_COP32_ISA, ivc2_core_isa);
1491               cd->isas = ivc2_core_isa;
1492             }
1493           else
1494             cd->isas = & MEP_CORE_ISA;
1495           status = default_print_insn (cd, pc, info);
1496         }
1497     }
1498   else /* sid or gdb */
1499     {
1500 #ifdef MEP_IVC2_SUPPORTED
1501       if (mep_ivc2_disassemble_p)
1502         {
1503           if (mep_ivc2_vliw_disassemble_p)
1504             {
1505               cd->isas = & MEP_CORE_ISA;
1506               status = mep_examine_ivc2_insns (cd, pc, info);
1507               return status;
1508             }
1509           else
1510             {
1511               if (ivc2)
1512                 cd->isas = ivc2_core_isa;
1513             }
1514         }
1515 #endif
1516
1517       status = default_print_insn (cd, pc, info);
1518     }
1519
1520   return status;
1521 }
1522
1523
1524 /* -- opc.c */
1525 #include "elf/mep.h"
1526
1527 /* A mask for all ISAs executed by the core. */
1528 CGEN_ATTR_VALUE_BITSET_TYPE mep_all_core_isas_mask = {0, 0};
1529
1530 void
1531 init_mep_all_core_isas_mask (void)
1532 {
1533   if (mep_all_core_isas_mask.length != 0)
1534     return;
1535   cgen_bitset_init (& mep_all_core_isas_mask, ISA_MAX);
1536   cgen_bitset_set (& mep_all_core_isas_mask, ISA_MEP);
1537   /* begin-all-core-isas */
1538   cgen_bitset_add (& mep_all_core_isas_mask, ISA_EXT_CORE1);
1539   /* end-all-core-isas */
1540 }
1541
1542 CGEN_ATTR_VALUE_BITSET_TYPE mep_all_cop_isas_mask = {0, 0};
1543
1544 void
1545 init_mep_all_cop_isas_mask (void)
1546 {
1547   if (mep_all_cop_isas_mask.length != 0)
1548     return;
1549   cgen_bitset_init (& mep_all_cop_isas_mask, ISA_MAX);
1550   /* begin-all-cop-isas */
1551   cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_16);
1552   cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_32);
1553   cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_48);
1554   cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_64);
1555   /* end-all-cop-isas */
1556 }
1557
1558 int
1559 mep_insn_supported_by_isa (const CGEN_INSN *insn, CGEN_ATTR_VALUE_BITSET_TYPE *isa_mask)
1560 {
1561   CGEN_BITSET insn_isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA);
1562   return cgen_bitset_intersect_p (& insn_isas, isa_mask);
1563 }
1564
1565 #define OPTION_MASK \
1566         ( (1 << CGEN_INSN_OPTIONAL_BIT_INSN) \
1567         | (1 << CGEN_INSN_OPTIONAL_MUL_INSN) \
1568         | (1 << CGEN_INSN_OPTIONAL_DIV_INSN) \
1569         | (1 << CGEN_INSN_OPTIONAL_DEBUG_INSN) \
1570         | (1 << CGEN_INSN_OPTIONAL_LDZ_INSN) \
1571         | (1 << CGEN_INSN_OPTIONAL_ABS_INSN) \
1572         | (1 << CGEN_INSN_OPTIONAL_AVE_INSN) \
1573         | (1 << CGEN_INSN_OPTIONAL_MINMAX_INSN) \
1574         | (1 << CGEN_INSN_OPTIONAL_CLIP_INSN) \
1575         | (1 << CGEN_INSN_OPTIONAL_SAT_INSN) \
1576         | (1 << CGEN_INSN_OPTIONAL_UCI_INSN) \
1577         | (1 << CGEN_INSN_OPTIONAL_DSP_INSN) \
1578         | (1 << CGEN_INSN_OPTIONAL_CP_INSN) \
1579         | (1 << CGEN_INSN_OPTIONAL_CP64_INSN) )
1580
1581
1582 mep_config_map_struct mep_config_map[] =
1583 {
1584   /* config-map-start */
1585   /* Default entry: first module, with all options enabled. */
1586   { "", 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) },
1587   { "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" },
1588           0
1589         | (1 << CGEN_INSN_OPTIONAL_CP_INSN)
1590         | (1 << CGEN_INSN_OPTIONAL_CP64_INSN)
1591         | (1 << CGEN_INSN_OPTIONAL_MUL_INSN)
1592         | (1 << CGEN_INSN_OPTIONAL_DIV_INSN)
1593         | (1 << CGEN_INSN_OPTIONAL_BIT_INSN)
1594         | (1 << CGEN_INSN_OPTIONAL_LDZ_INSN)
1595         | (1 << CGEN_INSN_OPTIONAL_ABS_INSN)
1596         | (1 << CGEN_INSN_OPTIONAL_AVE_INSN)
1597         | (1 << CGEN_INSN_OPTIONAL_MINMAX_INSN)
1598         | (1 << CGEN_INSN_OPTIONAL_CLIP_INSN)
1599         | (1 << CGEN_INSN_OPTIONAL_SAT_INSN) },
1600   /* config-map-end */
1601   { 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, 0 }
1602 };
1603
1604 int mep_config_index = 0;
1605
1606 static int
1607 check_configured_mach (int machs)
1608 {
1609   /* All base insns are supported.  */
1610   int mach = 1 << MACH_BASE;
1611   switch (MEP_CPU & EF_MEP_CPU_MASK)
1612     {
1613     case EF_MEP_CPU_C2:
1614     case EF_MEP_CPU_C3:
1615       mach |= (1 << MACH_MEP);
1616       break;
1617     case EF_MEP_CPU_H1:
1618       mach |= (1 << MACH_H1);
1619       break;
1620     case EF_MEP_CPU_C5:
1621       mach |= (1 << MACH_MEP);
1622       mach |= (1 << MACH_C5);
1623       break;
1624     default:
1625       break;
1626     }
1627   return machs & mach;
1628 }
1629
1630 int
1631 mep_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
1632 {
1633   int iconfig = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG);
1634   int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
1635   CGEN_BITSET isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA);
1636   int ok1;
1637   int ok2;
1638   int ok3;
1639
1640   /* If the insn has an option bit set that we don't want,
1641      reject it.  */
1642   if (CGEN_INSN_ATTRS (insn)->bool_ & OPTION_MASK & ~MEP_OMASK)
1643     return 0;
1644
1645   /* If attributes are absent, assume no restriction. */
1646   if (machs == 0)
1647     machs = ~0;
1648
1649   ok1 = ((machs & cd->machs) && cgen_bitset_intersect_p (& isas, cd->isas));
1650   /* If the insn is config-specific, make sure it matches.  */
1651   ok2 =  (iconfig == 0 || iconfig == MEP_CONFIG);
1652   /* Make sure the insn is supported by the configured mach  */
1653   ok3 = check_configured_mach (machs);
1654
1655   return (ok1 && ok2 && ok3);
1656 }
1657
1658 int
1659 mep_cgen_insn_supported_asm (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
1660 {
1661 #ifdef MEP_IVC2_SUPPORTED
1662   /* If we're assembling VLIW packets, ignore the 12-bit BSR as we
1663      can't relax that.  The 24-bit BSR is matched instead.  */
1664   if (insn->base->num == MEP_INSN_BSR12
1665       && cgen_bitset_contains (cd->isas, ISA_EXT_COP1_64))
1666     return 0;
1667 #endif
1668
1669   return mep_cgen_insn_supported (cd, insn);
1670 }