OSDN Git Service

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