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