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