xref: /netbsd-src/external/gpl3/binutils.old/dist/cpu/mep.opc (revision e992f068c547fd6e84b3f104dc2340adcc955732)
116dce513Schristos/* MeP opcode support.  -*- C -*-
216dce513Schristos   Copyright 2011 Free Software Foundation, Inc.
316dce513Schristos
416dce513Schristos   Contributed by Red Hat Inc;
516dce513Schristos
616dce513Schristos   This file is part of the GNU Binutils.
716dce513Schristos
816dce513Schristos   This program is free software; you can redistribute it and/or modify
916dce513Schristos   it under the terms of the GNU General Public License as published by
1016dce513Schristos   the Free Software Foundation; either version 3 of the License, or
1116dce513Schristos   (at your option) any later version.
1216dce513Schristos
1316dce513Schristos   This program is distributed in the hope that it will be useful,
1416dce513Schristos   but WITHOUT ANY WARRANTY; without even the implied warranty of
1516dce513Schristos   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1616dce513Schristos   GNU General Public License for more details.
1716dce513Schristos
1816dce513Schristos   You should have received a copy of the GNU General Public License
1916dce513Schristos   along with this program; if not, write to the Free Software
2016dce513Schristos   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
2116dce513Schristos   MA 02110-1301, USA.  */
2216dce513Schristos
2316dce513Schristos/* -- opc.h */
2416dce513Schristos
2516dce513Schristos#undef  CGEN_DIS_HASH_SIZE
2616dce513Schristos#define CGEN_DIS_HASH_SIZE 1
2716dce513Schristos
2816dce513Schristos#undef  CGEN_DIS_HASH
2916dce513Schristos#define CGEN_DIS_HASH(buffer, insn) 0
3016dce513Schristos
3116dce513Schristos#define CGEN_VERBOSE_ASSEMBLER_ERRORS
3216dce513Schristos
3316dce513Schristostypedef struct
3416dce513Schristos{
3516dce513Schristos  char * name;
3616dce513Schristos  int    config_enum;
3716dce513Schristos  unsigned cpu_flag;
3816dce513Schristos  int    big_endian;
3916dce513Schristos  int    vliw_bits;
4016dce513Schristos  CGEN_ATTR_VALUE_BITSET_TYPE cop16_isa;
4116dce513Schristos  CGEN_ATTR_VALUE_BITSET_TYPE cop32_isa;
4216dce513Schristos  CGEN_ATTR_VALUE_BITSET_TYPE cop48_isa;
4316dce513Schristos  CGEN_ATTR_VALUE_BITSET_TYPE cop64_isa;
4416dce513Schristos  CGEN_ATTR_VALUE_BITSET_TYPE cop_isa;
4516dce513Schristos  CGEN_ATTR_VALUE_BITSET_TYPE core_isa;
4616dce513Schristos  unsigned int option_mask;
4716dce513Schristos} mep_config_map_struct;
4816dce513Schristos
4916dce513Schristosextern mep_config_map_struct mep_config_map[];
5016dce513Schristosextern int mep_config_index;
5116dce513Schristos
5216dce513Schristosextern void init_mep_all_core_isas_mask (void);
5316dce513Schristosextern void init_mep_all_cop_isas_mask  (void);
5416dce513Schristosextern CGEN_ATTR_VALUE_BITSET_TYPE mep_cop_isa  (void);
5516dce513Schristos
5616dce513Schristos#define MEP_CONFIG     (mep_config_map[mep_config_index].config_enum)
5716dce513Schristos#define MEP_CPU        (mep_config_map[mep_config_index].cpu_flag)
5816dce513Schristos#define MEP_OMASK      (mep_config_map[mep_config_index].option_mask)
5916dce513Schristos#define MEP_VLIW       (mep_config_map[mep_config_index].vliw_bits > 0)
6016dce513Schristos#define MEP_VLIW32     (mep_config_map[mep_config_index].vliw_bits == 32)
6116dce513Schristos#define MEP_VLIW64     (mep_config_map[mep_config_index].vliw_bits == 64)
6216dce513Schristos#define MEP_COP16_ISA  (mep_config_map[mep_config_index].cop16_isa)
6316dce513Schristos#define MEP_COP32_ISA  (mep_config_map[mep_config_index].cop32_isa)
6416dce513Schristos#define MEP_COP48_ISA  (mep_config_map[mep_config_index].cop48_isa)
6516dce513Schristos#define MEP_COP64_ISA  (mep_config_map[mep_config_index].cop64_isa)
6616dce513Schristos#define MEP_COP_ISA    (mep_config_map[mep_config_index].cop_isa)
6716dce513Schristos#define MEP_CORE_ISA   (mep_config_map[mep_config_index].core_isa)
6816dce513Schristos
6916dce513Schristos/* begin-cop-ip-supported-defines */
7016dce513Schristos#define MEP_IVC2_SUPPORTED 1
7116dce513Schristos/* end-cop-ip-supported-defines */
7216dce513Schristos
7316dce513Schristosextern int mep_insn_supported_by_isa (const CGEN_INSN *, CGEN_ATTR_VALUE_BITSET_TYPE *);
7416dce513Schristos
7516dce513Schristos/* A mask for all ISAs executed by the core.  */
7616dce513Schristos#define MEP_ALL_CORE_ISAS_MASK mep_all_core_isas_mask
7716dce513Schristosextern CGEN_ATTR_VALUE_BITSET_TYPE mep_all_core_isas_mask;
7816dce513Schristos
7916dce513Schristos#define MEP_INSN_CORE_P(insn) ( \
8016dce513Schristos  init_mep_all_core_isas_mask (), \
8116dce513Schristos  mep_insn_supported_by_isa (insn, & MEP_ALL_CORE_ISAS_MASK) \
8216dce513Schristos)
8316dce513Schristos
8416dce513Schristos/* A mask for all ISAs executed by a VLIW coprocessor.  */
8516dce513Schristos#define MEP_ALL_COP_ISAS_MASK mep_all_cop_isas_mask
8616dce513Schristosextern CGEN_ATTR_VALUE_BITSET_TYPE mep_all_cop_isas_mask;
8716dce513Schristos
8816dce513Schristos#define MEP_INSN_COP_P(insn) ( \
8916dce513Schristos  init_mep_all_cop_isas_mask (), \
9016dce513Schristos  mep_insn_supported_by_isa (insn, & MEP_ALL_COP_ISAS_MASK) \
9116dce513Schristos)
9216dce513Schristos
9316dce513Schristosextern int mep_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
9416dce513Schristosextern int mep_cgen_insn_supported_asm (CGEN_CPU_DESC, const CGEN_INSN *);
9516dce513Schristos
9616dce513Schristos/* -- asm.c */
9716dce513Schristos
9816dce513Schristos#include "elf/mep.h"
9916dce513Schristos
10016dce513Schristos#define CGEN_VALIDATE_INSN_SUPPORTED
10116dce513Schristos#define mep_cgen_insn_supported mep_cgen_insn_supported_asm
10216dce513Schristos
10316dce513Schristos       const char * parse_csrn       (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *);
10416dce513Schristos       const char * parse_tpreg      (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *);
10516dce513Schristos       const char * parse_spreg      (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *);
10616dce513Schristos       const char * parse_mep_align  (CGEN_CPU_DESC, const char **, enum cgen_operand_type, long *);
10716dce513Schristos       const char * parse_mep_alignu (CGEN_CPU_DESC, const char **, enum cgen_operand_type, unsigned long *);
10816dce513Schristosstatic const char * parse_signed16   (CGEN_CPU_DESC, const char **, int, long *);
10916dce513Schristosstatic const char * parse_signed16_range   (CGEN_CPU_DESC, const char **, int, long *) ATTRIBUTE_UNUSED;
11016dce513Schristosstatic const char * parse_unsigned16 (CGEN_CPU_DESC, const char **, int, unsigned long *);
11116dce513Schristosstatic const char * parse_unsigned16_range (CGEN_CPU_DESC, const char **, int, unsigned long *) ATTRIBUTE_UNUSED;
11216dce513Schristosstatic const char * parse_lo16       (CGEN_CPU_DESC, const char **, int, long *, long);
11316dce513Schristosstatic const char * parse_unsigned7  (CGEN_CPU_DESC, const char **, enum cgen_operand_type, unsigned long *);
11416dce513Schristosstatic const char * parse_zero       (CGEN_CPU_DESC, const char **, int, long *);
11516dce513Schristos
11616dce513Schristosconst char *
11716dce513Schristosparse_csrn (CGEN_CPU_DESC cd, const char **strp,
11816dce513Schristos	    CGEN_KEYWORD *keyword_table, long *field)
11916dce513Schristos{
12016dce513Schristos  const char *err;
12116dce513Schristos  unsigned long value;
12216dce513Schristos
12316dce513Schristos  err = cgen_parse_keyword (cd, strp, keyword_table, field);
12416dce513Schristos  if (!err)
12516dce513Schristos    return NULL;
12616dce513Schristos
12716dce513Schristos  err = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_CSRN_IDX, & value);
12816dce513Schristos  if (err)
12916dce513Schristos    return err;
13016dce513Schristos  *field = value;
13116dce513Schristos  return NULL;
13216dce513Schristos}
13316dce513Schristos
13416dce513Schristos/* begin-cop-ip-parse-handlers */
13516dce513Schristosstatic const char *
13616dce513Schristosparse_ivc2_cr (CGEN_CPU_DESC,
13716dce513Schristos	const char **,
13816dce513Schristos	CGEN_KEYWORD *,
13916dce513Schristos	long *) ATTRIBUTE_UNUSED;
14016dce513Schristosstatic const char *
14116dce513Schristosparse_ivc2_cr (CGEN_CPU_DESC cd,
14216dce513Schristos	const char **strp,
14316dce513Schristos	CGEN_KEYWORD *keyword_table  ATTRIBUTE_UNUSED,
14416dce513Schristos	long *field)
14516dce513Schristos{
14616dce513Schristos  return cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_cr_ivc2, field);
14716dce513Schristos}
14816dce513Schristosstatic const char *
14916dce513Schristosparse_ivc2_ccr (CGEN_CPU_DESC,
15016dce513Schristos	const char **,
15116dce513Schristos	CGEN_KEYWORD *,
15216dce513Schristos	long *) ATTRIBUTE_UNUSED;
15316dce513Schristosstatic const char *
15416dce513Schristosparse_ivc2_ccr (CGEN_CPU_DESC cd,
15516dce513Schristos	const char **strp,
15616dce513Schristos	CGEN_KEYWORD *keyword_table  ATTRIBUTE_UNUSED,
15716dce513Schristos	long *field)
15816dce513Schristos{
15916dce513Schristos  return cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_ccr_ivc2, field);
16016dce513Schristos}
16116dce513Schristos/* end-cop-ip-parse-handlers */
16216dce513Schristos
16316dce513Schristosconst char *
16416dce513Schristosparse_tpreg (CGEN_CPU_DESC cd, const char ** strp,
16516dce513Schristos	     CGEN_KEYWORD *keyword_table, long *field)
16616dce513Schristos{
16716dce513Schristos  const char *err;
16816dce513Schristos
16916dce513Schristos  err = cgen_parse_keyword (cd, strp, keyword_table, field);
17016dce513Schristos  if (err)
17116dce513Schristos    return err;
17216dce513Schristos  if (*field != 13)
17316dce513Schristos    return _("Only $tp or $13 allowed for this opcode");
17416dce513Schristos  return NULL;
17516dce513Schristos}
17616dce513Schristos
17716dce513Schristosconst char *
17816dce513Schristosparse_spreg (CGEN_CPU_DESC cd, const char ** strp,
17916dce513Schristos	     CGEN_KEYWORD *keyword_table, long *field)
18016dce513Schristos{
18116dce513Schristos  const char *err;
18216dce513Schristos
18316dce513Schristos  err = cgen_parse_keyword (cd, strp, keyword_table, field);
18416dce513Schristos  if (err)
18516dce513Schristos    return err;
18616dce513Schristos  if (*field != 15)
18716dce513Schristos    return _("Only $sp or $15 allowed for this opcode");
18816dce513Schristos  return NULL;
18916dce513Schristos}
19016dce513Schristos
19116dce513Schristosconst char *
19216dce513Schristosparse_mep_align (CGEN_CPU_DESC cd, const char ** strp,
19316dce513Schristos		 enum cgen_operand_type type, long *field)
19416dce513Schristos{
19516dce513Schristos  long lsbs = 0;
19616dce513Schristos  const char *err;
19716dce513Schristos
19816dce513Schristos  switch (type)
19916dce513Schristos    {
20016dce513Schristos    case MEP_OPERAND_PCREL8A2:
20116dce513Schristos    case MEP_OPERAND_PCREL12A2:
20216dce513Schristos    case MEP_OPERAND_PCREL17A2:
20316dce513Schristos    case MEP_OPERAND_PCREL24A2:
20416dce513Schristos      err = cgen_parse_signed_integer   (cd, strp, type, field);
20516dce513Schristos      break;
20616dce513Schristos    case MEP_OPERAND_PCABS24A2:
20716dce513Schristos    case MEP_OPERAND_UDISP7:
20816dce513Schristos    case MEP_OPERAND_UDISP7A2:
20916dce513Schristos    case MEP_OPERAND_UDISP7A4:
21016dce513Schristos    case MEP_OPERAND_UIMM7A4:
21116dce513Schristos    case MEP_OPERAND_ADDR24A4:
21216dce513Schristos      err = cgen_parse_unsigned_integer (cd, strp, type, (unsigned long *) field);
21316dce513Schristos      break;
21416dce513Schristos    default:
21516dce513Schristos      abort();
21616dce513Schristos    }
21716dce513Schristos  if (err)
21816dce513Schristos    return err;
21916dce513Schristos  switch (type)
22016dce513Schristos    {
22116dce513Schristos    case MEP_OPERAND_UDISP7:
22216dce513Schristos      lsbs = 0;
22316dce513Schristos      break;
22416dce513Schristos    case MEP_OPERAND_PCREL8A2:
22516dce513Schristos    case MEP_OPERAND_PCREL12A2:
22616dce513Schristos    case MEP_OPERAND_PCREL17A2:
22716dce513Schristos    case MEP_OPERAND_PCREL24A2:
22816dce513Schristos    case MEP_OPERAND_PCABS24A2:
22916dce513Schristos    case MEP_OPERAND_UDISP7A2:
23016dce513Schristos      lsbs = *field & 1;
23116dce513Schristos      break;
23216dce513Schristos    case MEP_OPERAND_UDISP7A4:
23316dce513Schristos    case MEP_OPERAND_UIMM7A4:
23416dce513Schristos    case MEP_OPERAND_ADDR24A4:
23516dce513Schristos      lsbs = *field & 3;
23616dce513Schristos      break;
23716dce513Schristos      lsbs = *field & 7;
23816dce513Schristos      break;
23916dce513Schristos    default:
24016dce513Schristos      /* Safe assumption?  */
24116dce513Schristos      abort ();
24216dce513Schristos    }
24316dce513Schristos  if (lsbs)
24416dce513Schristos    return "Value is not aligned enough";
24516dce513Schristos  return NULL;
24616dce513Schristos}
24716dce513Schristos
24816dce513Schristosconst char *
24916dce513Schristosparse_mep_alignu (CGEN_CPU_DESC cd, const char ** strp,
25016dce513Schristos		 enum cgen_operand_type type, unsigned long *field)
25116dce513Schristos{
25216dce513Schristos  return parse_mep_align (cd, strp, type, (long *) field);
25316dce513Schristos}
25416dce513Schristos
25516dce513Schristos
25616dce513Schristos/* Handle %lo(), %tpoff(), %sdaoff(), %hi(), and other signed
25716dce513Schristos   constants in a signed context.  */
25816dce513Schristos
25916dce513Schristosstatic const char *
26016dce513Schristosparse_signed16 (CGEN_CPU_DESC cd,
26116dce513Schristos		const char **strp,
26216dce513Schristos		int opindex,
26316dce513Schristos		long *valuep)
26416dce513Schristos{
26516dce513Schristos  return parse_lo16 (cd, strp, opindex, valuep, 1);
26616dce513Schristos}
26716dce513Schristos
26816dce513Schristosstatic const char *
26916dce513Schristosparse_lo16 (CGEN_CPU_DESC cd,
27016dce513Schristos	    const char **strp,
27116dce513Schristos	    int opindex,
27216dce513Schristos	    long *valuep,
27316dce513Schristos	    long signedp)
27416dce513Schristos{
27516dce513Schristos  const char *errmsg;
27616dce513Schristos  enum cgen_parse_operand_result result_type;
27716dce513Schristos  bfd_vma value;
27816dce513Schristos
27916dce513Schristos  if (strncasecmp (*strp, "%lo(", 4) == 0)
28016dce513Schristos    {
28116dce513Schristos      *strp += 4;
28216dce513Schristos      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_LOW16,
28316dce513Schristos				   & result_type, & value);
28416dce513Schristos      if (**strp != ')')
28516dce513Schristos	return _("missing `)'");
28616dce513Schristos      ++*strp;
28716dce513Schristos      if (errmsg == NULL
28816dce513Schristos	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
28916dce513Schristos	value &= 0xffff;
29016dce513Schristos      if (signedp)
29116dce513Schristos	*valuep = (long)(short) value;
29216dce513Schristos      else
29316dce513Schristos	*valuep = value;
29416dce513Schristos      return errmsg;
29516dce513Schristos    }
29616dce513Schristos
29716dce513Schristos  if (strncasecmp (*strp, "%hi(", 4) == 0)
29816dce513Schristos    {
29916dce513Schristos      *strp += 4;
30016dce513Schristos      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16S,
30116dce513Schristos				   & result_type, & value);
30216dce513Schristos      if (**strp != ')')
30316dce513Schristos	return _("missing `)'");
30416dce513Schristos      ++*strp;
30516dce513Schristos      if (errmsg == NULL
30616dce513Schristos	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
30716dce513Schristos	value = (value + 0x8000) >> 16;
30816dce513Schristos      *valuep = value;
30916dce513Schristos      return errmsg;
31016dce513Schristos    }
31116dce513Schristos
31216dce513Schristos  if (strncasecmp (*strp, "%uhi(", 5) == 0)
31316dce513Schristos    {
31416dce513Schristos      *strp += 5;
31516dce513Schristos      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16U,
31616dce513Schristos				   & result_type, & value);
31716dce513Schristos      if (**strp != ')')
31816dce513Schristos	return _("missing `)'");
31916dce513Schristos      ++*strp;
32016dce513Schristos      if (errmsg == NULL
32116dce513Schristos	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
32216dce513Schristos	value = value >> 16;
32316dce513Schristos      *valuep = value;
32416dce513Schristos      return errmsg;
32516dce513Schristos    }
32616dce513Schristos
32716dce513Schristos  if (strncasecmp (*strp, "%sdaoff(", 8) == 0)
32816dce513Schristos    {
32916dce513Schristos      *strp += 8;
33016dce513Schristos      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_GPREL,
33116dce513Schristos				   NULL, & value);
33216dce513Schristos      if (**strp != ')')
33316dce513Schristos	return _("missing `)'");
33416dce513Schristos      ++*strp;
33516dce513Schristos      *valuep = value;
33616dce513Schristos      return errmsg;
33716dce513Schristos    }
33816dce513Schristos
33916dce513Schristos  if (strncasecmp (*strp, "%tpoff(", 7) == 0)
34016dce513Schristos    {
34116dce513Schristos      *strp += 7;
34216dce513Schristos      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_TPREL,
34316dce513Schristos				   NULL, & value);
34416dce513Schristos      if (**strp != ')')
34516dce513Schristos	return _("missing `)'");
34616dce513Schristos      ++*strp;
34716dce513Schristos      *valuep = value;
34816dce513Schristos      return errmsg;
34916dce513Schristos    }
35016dce513Schristos
35116dce513Schristos  if (**strp == '%')
35216dce513Schristos    return _("invalid %function() here");
35316dce513Schristos
35416dce513Schristos  return cgen_parse_signed_integer (cd, strp, opindex, valuep);
35516dce513Schristos}
35616dce513Schristos
35716dce513Schristosstatic const char *
35816dce513Schristosparse_unsigned16 (CGEN_CPU_DESC cd,
35916dce513Schristos		  const char **strp,
36016dce513Schristos		  int opindex,
36116dce513Schristos		  unsigned long *valuep)
36216dce513Schristos{
36316dce513Schristos  return parse_lo16 (cd, strp, opindex, (long *) valuep, 0);
36416dce513Schristos}
36516dce513Schristos
36616dce513Schristosstatic const char *
36716dce513Schristosparse_signed16_range (CGEN_CPU_DESC cd,
36816dce513Schristos		      const char **strp,
36916dce513Schristos		      int opindex,
37016dce513Schristos		      signed long *valuep)
37116dce513Schristos{
37216dce513Schristos  const char *errmsg = 0;
37316dce513Schristos  signed long value;
37416dce513Schristos
37516dce513Schristos  errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
37616dce513Schristos  if (errmsg)
37716dce513Schristos    return errmsg;
37816dce513Schristos
37916dce513Schristos  if (value < -32768 || value > 32767)
38016dce513Schristos    return _("Immediate is out of range -32768 to 32767");
38116dce513Schristos
38216dce513Schristos  *valuep = value;
38316dce513Schristos  return 0;
38416dce513Schristos}
38516dce513Schristos
38616dce513Schristosstatic const char *
38716dce513Schristosparse_unsigned16_range (CGEN_CPU_DESC cd,
38816dce513Schristos			const char **strp,
38916dce513Schristos			int opindex,
39016dce513Schristos			unsigned long *valuep)
39116dce513Schristos{
39216dce513Schristos  const char *errmsg = 0;
39316dce513Schristos  unsigned long value;
39416dce513Schristos
39516dce513Schristos  errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
39616dce513Schristos  if (errmsg)
39716dce513Schristos    return errmsg;
39816dce513Schristos
39916dce513Schristos  if (value > 65535)
40016dce513Schristos    return _("Immediate is out of range 0 to 65535");
40116dce513Schristos
40216dce513Schristos  *valuep = value;
40316dce513Schristos  return 0;
40416dce513Schristos}
40516dce513Schristos
40616dce513Schristos/* A special case of parse_signed16 which accepts only the value zero.  */
40716dce513Schristos
40816dce513Schristosstatic const char *
40916dce513Schristosparse_zero (CGEN_CPU_DESC cd, const char **strp, int opindex, long *valuep)
41016dce513Schristos{
41116dce513Schristos  const char *errmsg;
41216dce513Schristos  enum cgen_parse_operand_result result_type;
41316dce513Schristos  bfd_vma value;
41416dce513Schristos
41516dce513Schristos  /*fprintf(stderr, "dj: signed parse opindex `%s'\n", *strp);*/
41616dce513Schristos
41716dce513Schristos  /* Prevent ($ry) from being attempted as an expression on 'sw $rx,($ry)'.
41816dce513Schristos     It will fail and cause ry to be listed as an undefined symbol in the
41916dce513Schristos     listing.  */
42016dce513Schristos  if (strncmp (*strp, "($", 2) == 0)
42116dce513Schristos    return "not zero"; /* any string will do -- will never be seen.  */
42216dce513Schristos
42316dce513Schristos  if (strncasecmp (*strp, "%lo(", 4) == 0)
42416dce513Schristos    {
42516dce513Schristos      *strp += 4;
42616dce513Schristos      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_LOW16,
42716dce513Schristos				   &result_type, &value);
42816dce513Schristos      if (**strp != ')')
42916dce513Schristos	return "missing `)'";
43016dce513Schristos      ++*strp;
43116dce513Schristos      if (errmsg == NULL
43216dce513Schristos	  && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
43316dce513Schristos	return "not zero"; /* any string will do -- will never be seen.  */
43416dce513Schristos      *valuep = value;
43516dce513Schristos      return errmsg;
43616dce513Schristos    }
43716dce513Schristos
43816dce513Schristos  if (strncasecmp (*strp, "%hi(", 4) == 0)
43916dce513Schristos    {
44016dce513Schristos      *strp += 4;
44116dce513Schristos      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16S,
44216dce513Schristos				   &result_type, &value);
44316dce513Schristos      if (**strp != ')')
44416dce513Schristos	return "missing `)'";
44516dce513Schristos      ++*strp;
44616dce513Schristos      if (errmsg == NULL
44716dce513Schristos	  && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
44816dce513Schristos	return "not zero"; /* any string will do -- will never be seen.  */
44916dce513Schristos      *valuep = value;
45016dce513Schristos      return errmsg;
45116dce513Schristos    }
45216dce513Schristos
45316dce513Schristos  if (strncasecmp (*strp, "%uhi(", 5) == 0)
45416dce513Schristos    {
45516dce513Schristos      *strp += 5;
45616dce513Schristos      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16U,
45716dce513Schristos				   &result_type, &value);
45816dce513Schristos      if (**strp != ')')
45916dce513Schristos	return "missing `)'";
46016dce513Schristos      ++*strp;
46116dce513Schristos      if (errmsg == NULL
46216dce513Schristos	  && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
46316dce513Schristos	return "not zero"; /* any string will do -- will never be seen.  */
46416dce513Schristos      *valuep = value;
46516dce513Schristos      return errmsg;
46616dce513Schristos    }
46716dce513Schristos
46816dce513Schristos  if (strncasecmp (*strp, "%sdaoff(", 8) == 0)
46916dce513Schristos    {
47016dce513Schristos      *strp += 8;
47116dce513Schristos      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_GPREL,
47216dce513Schristos				   &result_type, &value);
47316dce513Schristos      if (**strp != ')')
47416dce513Schristos	return "missing `)'";
47516dce513Schristos      ++*strp;
47616dce513Schristos      if (errmsg == NULL
47716dce513Schristos	  && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
47816dce513Schristos	return "not zero"; /* any string will do -- will never be seen.  */
47916dce513Schristos      *valuep = value;
48016dce513Schristos      return errmsg;
48116dce513Schristos    }
48216dce513Schristos
48316dce513Schristos  if (strncasecmp (*strp, "%tpoff(", 7) == 0)
48416dce513Schristos    {
48516dce513Schristos      *strp += 7;
48616dce513Schristos      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_TPREL,
48716dce513Schristos				   &result_type, &value);
48816dce513Schristos      if (**strp != ')')
48916dce513Schristos	return "missing `)'";
49016dce513Schristos      ++*strp;
49116dce513Schristos      if (errmsg == NULL
49216dce513Schristos	  && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
49316dce513Schristos	return "not zero"; /* any string will do -- will never be seen.  */
49416dce513Schristos      *valuep = value;
49516dce513Schristos      return errmsg;
49616dce513Schristos    }
49716dce513Schristos
49816dce513Schristos  if (**strp == '%')
49916dce513Schristos    return "invalid %function() here";
50016dce513Schristos
50116dce513Schristos  errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_NONE,
50216dce513Schristos			       &result_type, &value);
50316dce513Schristos  if (errmsg == NULL
50416dce513Schristos      && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
50516dce513Schristos    return "not zero"; /* any string will do -- will never be seen.  */
50616dce513Schristos
50716dce513Schristos  return errmsg;
50816dce513Schristos}
50916dce513Schristos
51016dce513Schristosstatic const char *
51116dce513Schristosparse_unsigned7 (CGEN_CPU_DESC cd, const char **strp,
51216dce513Schristos		 enum cgen_operand_type opindex, unsigned long *valuep)
51316dce513Schristos{
51416dce513Schristos  const char *errmsg;
51516dce513Schristos  bfd_vma value;
51616dce513Schristos
51716dce513Schristos  /* fprintf(stderr, "dj: unsigned7 parse `%s'\n", *strp); */
51816dce513Schristos
51916dce513Schristos  if (strncasecmp (*strp, "%tpoff(", 7) == 0)
52016dce513Schristos    {
52116dce513Schristos      int reloc;
52216dce513Schristos      *strp += 7;
52316dce513Schristos      switch (opindex)
52416dce513Schristos	{
52516dce513Schristos	case MEP_OPERAND_UDISP7:
52616dce513Schristos	  reloc = BFD_RELOC_MEP_TPREL7;
52716dce513Schristos	  break;
52816dce513Schristos	case MEP_OPERAND_UDISP7A2:
52916dce513Schristos	  reloc = BFD_RELOC_MEP_TPREL7A2;
53016dce513Schristos	  break;
53116dce513Schristos	case MEP_OPERAND_UDISP7A4:
53216dce513Schristos	  reloc = BFD_RELOC_MEP_TPREL7A4;
53316dce513Schristos	  break;
53416dce513Schristos	default:
53516dce513Schristos	  /* Safe assumption?  */
53616dce513Schristos	  abort ();
53716dce513Schristos	}
53816dce513Schristos      errmsg = cgen_parse_address (cd, strp, opindex, reloc,
53916dce513Schristos				   NULL, &value);
54016dce513Schristos      if (**strp != ')')
54116dce513Schristos	return "missing `)'";
54216dce513Schristos      ++*strp;
54316dce513Schristos      *valuep = value;
54416dce513Schristos      return errmsg;
54516dce513Schristos    }
54616dce513Schristos
54716dce513Schristos  if (**strp == '%')
54816dce513Schristos    return _("invalid %function() here");
54916dce513Schristos
55016dce513Schristos  return parse_mep_alignu (cd, strp, opindex, valuep);
55116dce513Schristos}
55216dce513Schristos
55316dce513Schristosstatic ATTRIBUTE_UNUSED const char *
55416dce513Schristosparse_cdisp10 (CGEN_CPU_DESC cd,
55516dce513Schristos	       const char **strp,
55616dce513Schristos	       int opindex,
55716dce513Schristos	       long *valuep)
55816dce513Schristos{
55916dce513Schristos  const char *errmsg = 0;
56016dce513Schristos  signed long value;
56116dce513Schristos  long have_zero = 0;
56216dce513Schristos  int wide = 0;
56316dce513Schristos  int alignment;
56416dce513Schristos
56516dce513Schristos  switch (opindex)
56616dce513Schristos    {
56716dce513Schristos    case MEP_OPERAND_CDISP10A4:
56816dce513Schristos      alignment = 2;
56916dce513Schristos      break;
57016dce513Schristos    case MEP_OPERAND_CDISP10A2:
57116dce513Schristos      alignment = 1;
57216dce513Schristos      break;
57316dce513Schristos    case MEP_OPERAND_CDISP10:
57416dce513Schristos    default:
57516dce513Schristos      alignment = 0;
57616dce513Schristos      break;
57716dce513Schristos    }
57816dce513Schristos
57916dce513Schristos  if ((MEP_CPU & EF_MEP_CPU_MASK) == EF_MEP_CPU_C5)
58016dce513Schristos    wide = 1;
58116dce513Schristos
58216dce513Schristos  if (strncmp (*strp, "0x0", 3) == 0
58316dce513Schristos      || (**strp == '0' && *(*strp + 1) != 'x'))
58416dce513Schristos    have_zero = 1;
58516dce513Schristos
58616dce513Schristos  errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
58716dce513Schristos  if (errmsg)
58816dce513Schristos    return errmsg;
58916dce513Schristos
59016dce513Schristos  if (wide)
59116dce513Schristos    {
59216dce513Schristos      if (value < -512 || value > 511)
59316dce513Schristos	return _("Immediate is out of range -512 to 511");
59416dce513Schristos    }
59516dce513Schristos  else
59616dce513Schristos    {
59716dce513Schristos      if (value < -128 || value > 127)
59816dce513Schristos	return _("Immediate is out of range -128 to 127");
59916dce513Schristos    }
60016dce513Schristos
60116dce513Schristos  if (value & ((1<<alignment)-1))
60216dce513Schristos    return _("Value is not aligned enough");
60316dce513Schristos
60416dce513Schristos  /* If this field may require a relocation then use larger dsp16.  */
60516dce513Schristos  if (! have_zero && value == 0)
60616dce513Schristos    return (wide ? _("Immediate is out of range -512 to 511")
60716dce513Schristos	    : _("Immediate is out of range -128 to 127"));
60816dce513Schristos
60916dce513Schristos  *valuep = value;
61016dce513Schristos  return 0;
61116dce513Schristos}
61216dce513Schristos
61316dce513Schristos/* BEGIN LIGHTWEIGHT MACRO PROCESSOR.  */
61416dce513Schristos
61516dce513Schristos#define MAXARGS 9
61616dce513Schristos
61716dce513Schristostypedef struct
61816dce513Schristos{
61916dce513Schristos  char *name;
62016dce513Schristos  char *expansion;
62116dce513Schristos}  macro;
62216dce513Schristos
62316dce513Schristostypedef struct
62416dce513Schristos{
62516dce513Schristos  const char *start;
62616dce513Schristos  int len;
62716dce513Schristos} arg;
62816dce513Schristos
629*e992f068Schristosstatic macro const macros[] =
63016dce513Schristos{
63116dce513Schristos  { "sizeof", "(`1.end + (- `1))"},
63216dce513Schristos  { "startof", "(`1 | 0)" },
63316dce513Schristos  { "align4", "(`1&(~3))"},
63416dce513Schristos/*{ "hi", "(((`1+0x8000)>>16) & 0xffff)" },  */
63516dce513Schristos/*{ "lo", "(`1 & 0xffff)" },  */
63616dce513Schristos/*{ "sdaoff", "((`1-__sdabase) & 0x7f)"},  */
63716dce513Schristos/*{ "tpoff", "((`1-__tpbase) & 0x7f)"},  */
63816dce513Schristos  { 0,0 }
63916dce513Schristos};
64016dce513Schristos
64116dce513Schristosstatic char  * expand_string    (const char *, int);
64216dce513Schristos
64316dce513Schristosstatic const char *
64416dce513Schristosmep_cgen_expand_macros_and_parse_operand
64516dce513Schristos  (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
64616dce513Schristos
64716dce513Schristosstatic char *
64816dce513Schristosstr_append (char *dest, const char *input, int len)
64916dce513Schristos{
65016dce513Schristos  char *new_dest;
65116dce513Schristos  int oldlen;
65216dce513Schristos
65316dce513Schristos  if (len == 0)
65416dce513Schristos    return dest;
65516dce513Schristos  /* printf("str_append: <<%s>>, <<%s>>, %d\n", dest, input, len); */
65616dce513Schristos  oldlen = (dest ? strlen(dest) : 0);
65716dce513Schristos  new_dest = realloc (dest, oldlen + len + 1);
65816dce513Schristos  memset (new_dest + oldlen, 0, len + 1);
65916dce513Schristos  return strncat (new_dest, input, len);
66016dce513Schristos}
66116dce513Schristos
662*e992f068Schristosstatic const macro *
66316dce513Schristoslookup_macro (const char *name)
66416dce513Schristos{
665*e992f068Schristos  const macro *m;
66616dce513Schristos
66716dce513Schristos  for (m = macros; m->name; ++m)
66816dce513Schristos    if (strncmp (m->name, name, strlen(m->name)) == 0)
66916dce513Schristos      return m;
67016dce513Schristos
67116dce513Schristos  return 0;
67216dce513Schristos}
67316dce513Schristos
67416dce513Schristosstatic char *
675*e992f068Schristosexpand_macro (arg *args, int narg, const macro *mac)
67616dce513Schristos{
67716dce513Schristos  char *result = 0, *rescanned_result = 0;
67816dce513Schristos  char *e = mac->expansion;
67916dce513Schristos  char *mark = e;
68016dce513Schristos  int mac_arg = 0;
68116dce513Schristos
68216dce513Schristos  /*  printf("expanding macro %s with %d args\n", mac->name, narg + 1); */
68316dce513Schristos  while (*e)
68416dce513Schristos    {
68516dce513Schristos      if (*e == '`' &&
68616dce513Schristos	  (*e+1) &&
68716dce513Schristos	  ((*(e + 1) - '1') <= MAXARGS) &&
68816dce513Schristos	  ((*(e + 1) - '1') <= narg))
68916dce513Schristos	{
69016dce513Schristos	  result = str_append (result, mark, e - mark);
69116dce513Schristos	  mac_arg = (*(e + 1) - '1');
69216dce513Schristos	  /* printf("replacing `%d with %s\n", mac_arg+1, args[mac_arg].start); */
69316dce513Schristos	  result = str_append (result, args[mac_arg].start, args[mac_arg].len);
69416dce513Schristos	  ++e;
69516dce513Schristos	  mark = e+1;
69616dce513Schristos	}
69716dce513Schristos      ++e;
69816dce513Schristos    }
69916dce513Schristos
70016dce513Schristos  if (mark != e)
70116dce513Schristos    result = str_append (result, mark, e - mark);
70216dce513Schristos
70316dce513Schristos  if (result)
70416dce513Schristos    {
70516dce513Schristos      rescanned_result = expand_string (result, 0);
70616dce513Schristos      free (result);
70716dce513Schristos      return rescanned_result;
70816dce513Schristos    }
70916dce513Schristos  else
71016dce513Schristos    return result;
71116dce513Schristos}
71216dce513Schristos
71316dce513Schristos#define IN_TEXT 0
71416dce513Schristos#define IN_ARGS 1
71516dce513Schristos
71616dce513Schristosstatic char *
71716dce513Schristosexpand_string (const char *in, int first_only)
71816dce513Schristos{
71916dce513Schristos  int num_expansions = 0;
72016dce513Schristos  int depth = 0;
72116dce513Schristos  int narg = -1;
72216dce513Schristos  arg args[MAXARGS];
72316dce513Schristos  int state = IN_TEXT;
72416dce513Schristos  const char *mark = in;
725*e992f068Schristos  const macro *pmacro = NULL;
72616dce513Schristos  char *expansion = 0;
72716dce513Schristos  char *result = 0;
72816dce513Schristos
72916dce513Schristos  while (*in)
73016dce513Schristos    {
73116dce513Schristos      switch (state)
73216dce513Schristos	{
73316dce513Schristos	case IN_TEXT:
73416dce513Schristos	  if (*in == '%' && *(in + 1) && (!first_only || num_expansions == 0))
73516dce513Schristos	    {
73616dce513Schristos	      pmacro = lookup_macro (in + 1);
73716dce513Schristos	      if (pmacro)
73816dce513Schristos		{
73916dce513Schristos		  /* printf("entering state %d at '%s'...\n", state, in); */
74016dce513Schristos		  result = str_append (result, mark, in - mark);
74116dce513Schristos		  mark = in;
74216dce513Schristos		  in += 1 + strlen (pmacro->name);
74316dce513Schristos		  while (*in == ' ') ++in;
74416dce513Schristos		  if (*in != '(')
74516dce513Schristos		    {
74616dce513Schristos		      state = IN_TEXT;
74716dce513Schristos		      pmacro = NULL;
74816dce513Schristos		    }
74916dce513Schristos		  else
75016dce513Schristos		    {
75116dce513Schristos		      state = IN_ARGS;
75216dce513Schristos		      narg = 0;
75316dce513Schristos		      args[narg].start = in + 1;
75416dce513Schristos		      args[narg].len = 0;
75516dce513Schristos		      mark = in + 1;
75616dce513Schristos		    }
75716dce513Schristos		}
75816dce513Schristos	    }
75916dce513Schristos	  break;
76016dce513Schristos	case IN_ARGS:
76116dce513Schristos	  if (depth == 0)
76216dce513Schristos	    {
76316dce513Schristos	      switch (*in)
76416dce513Schristos		{
76516dce513Schristos		case ',':
76616dce513Schristos		  narg++;
76716dce513Schristos		  args[narg].start = (in + 1);
76816dce513Schristos		  args[narg].len = 0;
76916dce513Schristos		  break;
77016dce513Schristos		case ')':
77116dce513Schristos		  state = IN_TEXT;
77216dce513Schristos		  /* printf("entering state %d at '%s'...\n", state, in); */
77316dce513Schristos		  if (pmacro)
77416dce513Schristos		    {
77516dce513Schristos		      expansion = 0;
77616dce513Schristos		      expansion = expand_macro (args, narg, pmacro);
77716dce513Schristos		      num_expansions++;
77816dce513Schristos		      if (expansion)
77916dce513Schristos			{
78016dce513Schristos			  result = str_append (result, expansion, strlen (expansion));
78116dce513Schristos			  free (expansion);
78216dce513Schristos			}
78316dce513Schristos		    }
78416dce513Schristos		  else
78516dce513Schristos		    {
78616dce513Schristos		      result = str_append (result, mark, in - mark);
78716dce513Schristos		    }
78816dce513Schristos		  pmacro = NULL;
78916dce513Schristos		  mark = in + 1;
79016dce513Schristos		  break;
79116dce513Schristos		case '(':
79216dce513Schristos		  depth++;
793ede78133Schristos		  /* Fall through.  */
79416dce513Schristos		default:
79516dce513Schristos		  args[narg].len++;
79616dce513Schristos		  break;
79716dce513Schristos		}
79816dce513Schristos	    }
79916dce513Schristos	  else
80016dce513Schristos	    {
80116dce513Schristos	      if (*in == ')')
80216dce513Schristos		depth--;
80316dce513Schristos	      if (narg > -1)
80416dce513Schristos		args[narg].len++;
80516dce513Schristos	    }
80616dce513Schristos
80716dce513Schristos	}
80816dce513Schristos      ++in;
80916dce513Schristos    }
81016dce513Schristos
81116dce513Schristos  if (mark != in)
81216dce513Schristos    result = str_append (result, mark, in - mark);
81316dce513Schristos
81416dce513Schristos  return result;
81516dce513Schristos}
81616dce513Schristos
81716dce513Schristos#undef IN_ARGS
81816dce513Schristos#undef IN_TEXT
81916dce513Schristos#undef MAXARGS
82016dce513Schristos
82116dce513Schristos
82216dce513Schristos/* END LIGHTWEIGHT MACRO PROCESSOR.  */
82316dce513Schristos
82416dce513Schristosconst char * mep_cgen_parse_operand
82516dce513Schristos  (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
82616dce513Schristos
82716dce513Schristosconst char *
82816dce513Schristosmep_cgen_expand_macros_and_parse_operand (CGEN_CPU_DESC cd, int opindex,
82916dce513Schristos					  const char ** strp_in, CGEN_FIELDS * fields)
83016dce513Schristos{
83116dce513Schristos  const char * errmsg = NULL;
83216dce513Schristos  char *str = 0, *hold = 0;
83316dce513Schristos  const char **strp = 0;
83416dce513Schristos
83516dce513Schristos  /* Set up a new pointer to macro-expanded string.  */
83616dce513Schristos  str = expand_string (*strp_in, 1);
83716dce513Schristos  /* fprintf (stderr, " expanded <<%s>> to <<%s>>\n", *strp_in, str); */
83816dce513Schristos
83916dce513Schristos  hold = str;
84016dce513Schristos  strp = (const char **)(&str);
84116dce513Schristos
84216dce513Schristos  errmsg = mep_cgen_parse_operand (cd, opindex, strp, fields);
84316dce513Schristos
84416dce513Schristos  /* Now work out the advance.  */
84516dce513Schristos  if (strlen (str) == 0)
84616dce513Schristos    *strp_in += strlen (*strp_in);
84716dce513Schristos
84816dce513Schristos  else
84916dce513Schristos    {
85016dce513Schristos      if (strstr (*strp_in, str))
85116dce513Schristos	/* A macro-expansion was pulled off the front.  */
85216dce513Schristos	*strp_in = strstr (*strp_in, str);
85316dce513Schristos      else
85416dce513Schristos	/* A non-macro-expansion was pulled off the front.  */
85516dce513Schristos	*strp_in += (str - hold);
85616dce513Schristos    }
85716dce513Schristos
85816dce513Schristos  free (hold);
85916dce513Schristos
86016dce513Schristos  return errmsg;
86116dce513Schristos}
86216dce513Schristos
86316dce513Schristos#define CGEN_ASM_INIT_HOOK (cd->parse_operand = mep_cgen_expand_macros_and_parse_operand);
86416dce513Schristos
86516dce513Schristos/* -- dis.c */
86616dce513Schristos
86716dce513Schristos#include "elf/mep.h"
86816dce513Schristos#include "elf-bfd.h"
86916dce513Schristos
87016dce513Schristos#define CGEN_VALIDATE_INSN_SUPPORTED
87116dce513Schristos
87216dce513Schristosstatic void
873*e992f068Schristosprint_tpreg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, void *dis_info,
87416dce513Schristos	     CGEN_KEYWORD *table ATTRIBUTE_UNUSED, long val ATTRIBUTE_UNUSED,
87516dce513Schristos	     unsigned int flags ATTRIBUTE_UNUSED)
87616dce513Schristos{
87716dce513Schristos  disassemble_info *info = (disassemble_info *) dis_info;
87816dce513Schristos
87916dce513Schristos  (*info->fprintf_func) (info->stream, "$tp");
88016dce513Schristos}
88116dce513Schristos
88216dce513Schristosstatic void
883*e992f068Schristosprint_spreg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, void *dis_info,
88416dce513Schristos	     CGEN_KEYWORD *table ATTRIBUTE_UNUSED, long val ATTRIBUTE_UNUSED,
88516dce513Schristos	     unsigned int flags ATTRIBUTE_UNUSED)
88616dce513Schristos{
88716dce513Schristos  disassemble_info *info = (disassemble_info *) dis_info;
88816dce513Schristos
88916dce513Schristos  (*info->fprintf_func) (info->stream, "$sp");
89016dce513Schristos}
89116dce513Schristos
89216dce513Schristos/* begin-cop-ip-print-handlers */
89316dce513Schristosstatic void
89416dce513Schristosprint_ivc2_cr (CGEN_CPU_DESC,
89516dce513Schristos	void *,
89616dce513Schristos	CGEN_KEYWORD *,
89716dce513Schristos	long,
89816dce513Schristos	unsigned int) ATTRIBUTE_UNUSED;
89916dce513Schristosstatic void
90016dce513Schristosprint_ivc2_cr (CGEN_CPU_DESC cd,
90116dce513Schristos	void *dis_info,
90216dce513Schristos	CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED,
90316dce513Schristos	long value,
90416dce513Schristos	unsigned int attrs)
90516dce513Schristos{
90616dce513Schristos  print_keyword (cd, dis_info, & mep_cgen_opval_h_cr_ivc2, value, attrs);
90716dce513Schristos}
90816dce513Schristosstatic void
90916dce513Schristosprint_ivc2_ccr (CGEN_CPU_DESC,
91016dce513Schristos	void *,
91116dce513Schristos	CGEN_KEYWORD *,
91216dce513Schristos	long,
91316dce513Schristos	unsigned int) ATTRIBUTE_UNUSED;
91416dce513Schristosstatic void
91516dce513Schristosprint_ivc2_ccr (CGEN_CPU_DESC cd,
91616dce513Schristos	void *dis_info,
91716dce513Schristos	CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED,
91816dce513Schristos	long value,
91916dce513Schristos	unsigned int attrs)
92016dce513Schristos{
92116dce513Schristos  print_keyword (cd, dis_info, & mep_cgen_opval_h_ccr_ivc2, value, attrs);
92216dce513Schristos}
92316dce513Schristos/* end-cop-ip-print-handlers */
92416dce513Schristos
92516dce513Schristos/************************************************************\
92616dce513Schristos*********************** Experimental *************************
92716dce513Schristos\************************************************************/
92816dce513Schristos
92916dce513Schristos#undef  CGEN_PRINT_INSN
93016dce513Schristos#define CGEN_PRINT_INSN mep_print_insn
93116dce513Schristos
93216dce513Schristosstatic int
93316dce513Schristosmep_print_vliw_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info,
93416dce513Schristos		      bfd_byte *buf, int corelength, int copro1length,
93516dce513Schristos		      int copro2length ATTRIBUTE_UNUSED)
93616dce513Schristos{
93716dce513Schristos  int i;
93816dce513Schristos  int status = 0;
93916dce513Schristos  /* char insnbuf[CGEN_MAX_INSN_SIZE]; */
94016dce513Schristos  bfd_byte insnbuf[64];
94116dce513Schristos
94216dce513Schristos  /* If corelength > 0 then there is a core insn present. It
94316dce513Schristos     will be at the beginning of the buffer.  After printing
94416dce513Schristos     the core insn, we need to print the + on the next line.  */
94516dce513Schristos  if (corelength > 0)
94616dce513Schristos    {
94716dce513Schristos      int my_status = 0;
94816dce513Schristos
94916dce513Schristos      for (i = 0; i < corelength; i++ )
95016dce513Schristos	insnbuf[i] = buf[i];
95116dce513Schristos      cd->isas = & MEP_CORE_ISA;
95216dce513Schristos
95316dce513Schristos      my_status = print_insn (cd, pc, info, insnbuf, corelength);
95416dce513Schristos      if (my_status != corelength)
95516dce513Schristos	{
95616dce513Schristos	  (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
95716dce513Schristos	  my_status = corelength;
95816dce513Schristos	}
95916dce513Schristos      status += my_status;
96016dce513Schristos
96116dce513Schristos      /* Print the + to indicate that the following copro insn is   */
96216dce513Schristos      /* part of a vliw group.                                      */
96316dce513Schristos      if (copro1length > 0)
96416dce513Schristos	(*info->fprintf_func) (info->stream, " + ");
96516dce513Schristos    }
96616dce513Schristos
96716dce513Schristos  /* Now all that is left to be processed is the coprocessor insns
96816dce513Schristos     In vliw mode, there will always be one.  Its positioning will
96916dce513Schristos     be from byte corelength to byte corelength+copro1length -1.
97016dce513Schristos     No need to check for existence.   Also, the first vliw insn,
97116dce513Schristos     will, as spec'd, always be at least as long as the core insn
97216dce513Schristos     so we don't need to flush the buffer.  */
97316dce513Schristos  if (copro1length > 0)
97416dce513Schristos    {
97516dce513Schristos      int my_status = 0;
97616dce513Schristos
97716dce513Schristos      for (i = corelength; i < corelength + copro1length; i++ )
97816dce513Schristos	insnbuf[i - corelength] = buf[i];
97916dce513Schristos
98016dce513Schristos      switch (copro1length)
98116dce513Schristos	{
98216dce513Schristos	case 0:
98316dce513Schristos	  break;
98416dce513Schristos	case 2:
98516dce513Schristos	  cd->isas = & MEP_COP16_ISA;
98616dce513Schristos	  break;
98716dce513Schristos	case 4:
98816dce513Schristos	  cd->isas = & MEP_COP32_ISA;
98916dce513Schristos	  break;
99016dce513Schristos	case 6:
99116dce513Schristos	  cd->isas = & MEP_COP48_ISA;
99216dce513Schristos	  break;
99316dce513Schristos	case 8:
99416dce513Schristos	  cd->isas = & MEP_COP64_ISA;
99516dce513Schristos	  break;
99616dce513Schristos	default:
99716dce513Schristos	  /* Shouldn't be anything but 16,32,48,64.  */
99816dce513Schristos	  break;
99916dce513Schristos	}
100016dce513Schristos
100116dce513Schristos      my_status = print_insn (cd, pc, info, insnbuf, copro1length);
100216dce513Schristos
100316dce513Schristos      if (my_status != copro1length)
100416dce513Schristos	{
100516dce513Schristos	  (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
100616dce513Schristos	  my_status = copro1length;
100716dce513Schristos	}
100816dce513Schristos      status += my_status;
100916dce513Schristos    }
101016dce513Schristos
101116dce513Schristos#if 0
101216dce513Schristos  /* Now we need to process the second copro insn if it exists. We
101316dce513Schristos     have no guarantee that the second copro insn will be longer
101416dce513Schristos     than the first, so we have to flush the buffer if we are have
101516dce513Schristos     a second copro insn to process.  If present, this insn will
101616dce513Schristos     be in the position from byte corelength+copro1length to byte
101716dce513Schristos     corelength+copro1length+copro2length-1 (which better equal 8
101816dce513Schristos     or else we're in big trouble.  */
101916dce513Schristos  if (copro2length > 0)
102016dce513Schristos    {
102116dce513Schristos      int my_status = 0;
102216dce513Schristos
102316dce513Schristos      for (i = 0; i < 64 ; i++)
102416dce513Schristos	insnbuf[i] = 0;
102516dce513Schristos
102616dce513Schristos      for (i = corelength + copro1length; i < 64; i++)
102716dce513Schristos	insnbuf[i - (corelength + copro1length)] = buf[i];
102816dce513Schristos
102916dce513Schristos      switch (copro2length)
103016dce513Schristos	{
103116dce513Schristos	case 2:
103216dce513Schristos	  cd->isas = 1 << ISA_EXT_COP1_16;
103316dce513Schristos	  break;
103416dce513Schristos	case 4:
103516dce513Schristos	  cd->isas = 1 << ISA_EXT_COP1_32;
103616dce513Schristos	  break;
103716dce513Schristos	case 6:
103816dce513Schristos	  cd->isas = 1 << ISA_EXT_COP1_48;
103916dce513Schristos	  break;
104016dce513Schristos	case 8:
104116dce513Schristos	  cd->isas = 1 << ISA_EXT_COP1_64;
104216dce513Schristos	  break;
104316dce513Schristos	default:
104416dce513Schristos	  /* Shouldn't be anything but 16,32,48,64.  */
104516dce513Schristos	  break;
104616dce513Schristos	}
104716dce513Schristos
104816dce513Schristos      my_status = print_insn (cd, pc, info, insnbuf, copro2length);
104916dce513Schristos
105016dce513Schristos      if (my_status != copro2length)
105116dce513Schristos	{
105216dce513Schristos	  (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
105316dce513Schristos	  my_status = copro2length;
105416dce513Schristos	}
105516dce513Schristos
105616dce513Schristos      status += my_status;
105716dce513Schristos    }
105816dce513Schristos#endif
105916dce513Schristos
106016dce513Schristos  /* Status should now be the number of bytes that were printed
106116dce513Schristos     which should be 4 for VLIW32 mode and 64 for VLIW64 mode.  */
106216dce513Schristos
106316dce513Schristos  if ((!MEP_VLIW64 && (status != 4)) || (MEP_VLIW64 && (status != 8)))
106416dce513Schristos    return -1;
106516dce513Schristos  else
106616dce513Schristos    return status;
106716dce513Schristos}
106816dce513Schristos
106916dce513Schristos/* The two functions mep_examine_vliw[32,64]_insns are used find out
107016dce513Schristos   which vliw combinaion (16 bit core with 48 bit copro, 32 bit core
107116dce513Schristos   with 32 bit copro, etc.) is present.  Later on, when internally
107216dce513Schristos   parallel coprocessors are handled, only these functions should
107316dce513Schristos   need to be changed.
107416dce513Schristos
107516dce513Schristos   At this time only the following combinations are supported:
107616dce513Schristos
107716dce513Schristos   VLIW32 Mode:
107816dce513Schristos   16 bit core insn (core) and 16 bit coprocessor insn (cop1)
107916dce513Schristos   32 bit core insn (core)
108016dce513Schristos   32 bit coprocessor insn (cop1)
108116dce513Schristos   Note: As of this time, I do not believe we have enough information
108216dce513Schristos         to distinguish a 32 bit core insn from a 32 bit cop insn. Also,
108316dce513Schristos         no 16 bit coprocessor insns have been specified.
108416dce513Schristos
108516dce513Schristos   VLIW64 Mode:
108616dce513Schristos   16 bit core insn (core) and 48 bit coprocessor insn (cop1)
108716dce513Schristos   32 bit core insn (core) and 32 bit coprocessor insn (cop1)
108816dce513Schristos   64 bit coprocessor insn (cop1)
108916dce513Schristos
109016dce513Schristos   The framework for an internally parallel coprocessor is also
109116dce513Schristos   present (2nd coprocessor insn is cop2), but at this time it
109216dce513Schristos   is not used.  This only appears to be valid in VLIW64 mode.  */
109316dce513Schristos
109416dce513Schristosstatic int
109516dce513Schristosmep_examine_vliw32_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
109616dce513Schristos{
109716dce513Schristos  int status;
109816dce513Schristos  int buflength;
109916dce513Schristos  int corebuflength;
110016dce513Schristos  int cop1buflength;
110116dce513Schristos  int cop2buflength;
110216dce513Schristos  bfd_byte buf[CGEN_MAX_INSN_SIZE];
110316dce513Schristos  char indicator16[1];
110416dce513Schristos  char indicatorcop32[2];
110516dce513Schristos
110616dce513Schristos  /* At this time we're not supporting internally parallel coprocessors,
110716dce513Schristos     so cop2buflength will always be 0.  */
110816dce513Schristos  cop2buflength = 0;
110916dce513Schristos
111016dce513Schristos  /* Read in 32 bits.  */
111116dce513Schristos  buflength = 4; /* VLIW insn spans 4 bytes.  */
111216dce513Schristos  status = (*info->read_memory_func) (pc, buf, buflength, info);
111316dce513Schristos
111416dce513Schristos  if (status != 0)
111516dce513Schristos    {
111616dce513Schristos      (*info->memory_error_func) (status, pc, info);
111716dce513Schristos      return -1;
111816dce513Schristos    }
111916dce513Schristos
112016dce513Schristos  /* Put the big endian representation of the bytes to be examined
112116dce513Schristos     in the temporary buffers for examination.  */
112216dce513Schristos
112316dce513Schristos  if (info->endian == BFD_ENDIAN_BIG)
112416dce513Schristos    {
112516dce513Schristos      indicator16[0] = buf[0];
112616dce513Schristos      indicatorcop32[0] = buf[0];
112716dce513Schristos      indicatorcop32[1] = buf[1];
112816dce513Schristos    }
112916dce513Schristos  else
113016dce513Schristos    {
113116dce513Schristos      indicator16[0] = buf[1];
113216dce513Schristos      indicatorcop32[0] = buf[1];
113316dce513Schristos      indicatorcop32[1] = buf[0];
113416dce513Schristos    }
113516dce513Schristos
113616dce513Schristos  /* If the two high order bits are 00, 01 or 10, we have a 16 bit
113716dce513Schristos     core insn and a 48 bit copro insn.  */
113816dce513Schristos
113916dce513Schristos  if ((indicator16[0] & 0x80) && (indicator16[0] & 0x40))
114016dce513Schristos    {
114116dce513Schristos      if ((indicatorcop32[0] & 0xf0) == 0xf0 && (indicatorcop32[1] & 0x07) == 0x07)
114216dce513Schristos	{
114316dce513Schristos          /* We have a 32 bit copro insn.  */
114416dce513Schristos          corebuflength = 0;
114516dce513Schristos	  /* All 4 4ytes are one copro insn. */
114616dce513Schristos          cop1buflength = 4;
114716dce513Schristos	}
114816dce513Schristos      else
114916dce513Schristos	{
115016dce513Schristos          /* We have a 32 bit core.  */
115116dce513Schristos          corebuflength = 4;
115216dce513Schristos          cop1buflength = 0;
115316dce513Schristos	}
115416dce513Schristos    }
115516dce513Schristos  else
115616dce513Schristos    {
115716dce513Schristos      /* We have a 16 bit core insn and a 16 bit copro insn.  */
115816dce513Schristos      corebuflength = 2;
115916dce513Schristos      cop1buflength = 2;
116016dce513Schristos    }
116116dce513Schristos
116216dce513Schristos  /* Now we have the distrubution set.  Print them out.  */
116316dce513Schristos  status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength,
116416dce513Schristos				 cop1buflength, cop2buflength);
116516dce513Schristos
116616dce513Schristos  return status;
116716dce513Schristos}
116816dce513Schristos
116916dce513Schristosstatic int
117016dce513Schristosmep_examine_vliw64_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
117116dce513Schristos{
117216dce513Schristos  int status;
117316dce513Schristos  int buflength;
117416dce513Schristos  int corebuflength;
117516dce513Schristos  int cop1buflength;
117616dce513Schristos  int cop2buflength;
117716dce513Schristos  bfd_byte buf[CGEN_MAX_INSN_SIZE];
117816dce513Schristos  char indicator16[1];
117916dce513Schristos  char indicator64[4];
118016dce513Schristos
118116dce513Schristos  /* At this time we're not supporting internally parallel
118216dce513Schristos     coprocessors, so cop2buflength will always be 0.  */
118316dce513Schristos  cop2buflength = 0;
118416dce513Schristos
118516dce513Schristos  /* Read in 64 bits.  */
118616dce513Schristos  buflength = 8; /* VLIW insn spans 8 bytes.  */
118716dce513Schristos  status = (*info->read_memory_func) (pc, buf, buflength, info);
118816dce513Schristos
118916dce513Schristos  if (status != 0)
119016dce513Schristos    {
119116dce513Schristos      (*info->memory_error_func) (status, pc, info);
119216dce513Schristos      return -1;
119316dce513Schristos    }
119416dce513Schristos
119516dce513Schristos  /* We have all 64 bits in the buffer now.  We have to figure out
119616dce513Schristos     what combination of instruction sizes are present.  The two
119716dce513Schristos     high order bits will indicate whether or not we have a 16 bit
119816dce513Schristos     core insn or not.  If not, then we have to look at the 7,8th
119916dce513Schristos     bytes to tell whether we have 64 bit copro insn or a 32 bit
120016dce513Schristos     core insn with a 32 bit copro insn.  Endianness will make a
120116dce513Schristos     difference here.  */
120216dce513Schristos
120316dce513Schristos  /* Put the big endian representation of the bytes to be examined
120416dce513Schristos     in the temporary buffers for examination.  */
120516dce513Schristos
120616dce513Schristos  /* indicator16[0] = buf[0];  */
120716dce513Schristos  if (info->endian == BFD_ENDIAN_BIG)
120816dce513Schristos    {
120916dce513Schristos      indicator16[0] = buf[0];
121016dce513Schristos      indicator64[0] = buf[0];
121116dce513Schristos      indicator64[1] = buf[1];
121216dce513Schristos      indicator64[2] = buf[2];
121316dce513Schristos      indicator64[3] = buf[3];
121416dce513Schristos    }
121516dce513Schristos  else
121616dce513Schristos    {
121716dce513Schristos      indicator16[0] = buf[1];
121816dce513Schristos      indicator64[0] = buf[1];
121916dce513Schristos      indicator64[1] = buf[0];
122016dce513Schristos      indicator64[2] = buf[3];
122116dce513Schristos      indicator64[3] = buf[2];
122216dce513Schristos    }
122316dce513Schristos
122416dce513Schristos  /* If the two high order bits are 00, 01 or 10, we have a 16 bit
122516dce513Schristos     core insn and a 48 bit copro insn.  */
122616dce513Schristos
122716dce513Schristos  if ((indicator16[0] & 0x80) && (indicator16[0] & 0x40))
122816dce513Schristos    {
122916dce513Schristos      if ((indicator64[0] & 0xf0) == 0xf0 && (indicator64[1] & 0x07) == 0x07
123016dce513Schristos	  && ((indicator64[2] & 0xfe) != 0xf0 || (indicator64[3] & 0xf4) != 0))
123116dce513Schristos	{
123216dce513Schristos          /* We have a 64 bit copro insn.  */
123316dce513Schristos          corebuflength = 0;
123416dce513Schristos	  /* All 8 bytes are one copro insn.  */
123516dce513Schristos          cop1buflength = 8;
123616dce513Schristos	}
123716dce513Schristos      else
123816dce513Schristos	{
123916dce513Schristos          /* We have a 32 bit core insn and a 32 bit copro insn.  */
124016dce513Schristos          corebuflength = 4;
124116dce513Schristos          cop1buflength = 4;
124216dce513Schristos	}
124316dce513Schristos    }
124416dce513Schristos  else
124516dce513Schristos    {
124616dce513Schristos      /* We have a 16 bit core insn and a 48 bit copro insn.  */
124716dce513Schristos      corebuflength = 2;
124816dce513Schristos      cop1buflength = 6;
124916dce513Schristos    }
125016dce513Schristos
125116dce513Schristos  /* Now we have the distrubution set.  Print them out. */
125216dce513Schristos  status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength,
125316dce513Schristos				 cop1buflength, cop2buflength);
125416dce513Schristos
125516dce513Schristos  return status;
125616dce513Schristos}
125716dce513Schristos
125816dce513Schristos#ifdef MEP_IVC2_SUPPORTED
125916dce513Schristos
126016dce513Schristosstatic int
126116dce513Schristosprint_slot_insn (CGEN_CPU_DESC cd,
126216dce513Schristos		 bfd_vma pc,
126316dce513Schristos		 disassemble_info *info,
126416dce513Schristos		 SLOTS_ATTR slot,
126516dce513Schristos		 bfd_byte *buf)
126616dce513Schristos{
126716dce513Schristos  const CGEN_INSN_LIST *insn_list;
126816dce513Schristos  CGEN_INSN_INT insn_value;
126916dce513Schristos  CGEN_EXTRACT_INFO ex_info;
127016dce513Schristos
1271*e992f068Schristos  insn_value = cgen_get_insn_value (cd, buf, 32, cd->insn_endian);
127216dce513Schristos
127316dce513Schristos  /* Fill in ex_info fields like read_insn would.  Don't actually call
127416dce513Schristos     read_insn, since the incoming buffer is already read (and possibly
127516dce513Schristos     modified a la m32r).  */
127616dce513Schristos  ex_info.valid = (1 << 8) - 1;
127716dce513Schristos  ex_info.dis_info = info;
127816dce513Schristos  ex_info.insn_bytes = buf;
127916dce513Schristos
128016dce513Schristos  /* The instructions are stored in hash lists.
128116dce513Schristos     Pick the first one and keep trying until we find the right one.  */
128216dce513Schristos
128316dce513Schristos  insn_list = CGEN_DIS_LOOKUP_INSN (cd, (char *) buf, insn_value);
128416dce513Schristos  while (insn_list != NULL)
128516dce513Schristos    {
128616dce513Schristos      const CGEN_INSN *insn = insn_list->insn;
128716dce513Schristos      CGEN_FIELDS fields;
128816dce513Schristos      int length;
128916dce513Schristos
129016dce513Schristos      if ((CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG)
129116dce513Schristos	   && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG) != MEP_CONFIG)
129216dce513Schristos	  || ! (CGEN_ATTR_CGEN_INSN_SLOTS_VALUE (CGEN_INSN_ATTRS (insn)) & (1 << slot)))
129316dce513Schristos        {
129416dce513Schristos          insn_list = CGEN_DIS_NEXT_INSN (insn_list);
129516dce513Schristos	  continue;
129616dce513Schristos        }
129716dce513Schristos
129816dce513Schristos      if ((insn_value & CGEN_INSN_BASE_MASK (insn))
129916dce513Schristos	  == CGEN_INSN_BASE_VALUE (insn))
130016dce513Schristos	{
130116dce513Schristos	  /* Printing is handled in two passes.  The first pass parses the
130216dce513Schristos	     machine insn and extracts the fields.  The second pass prints
130316dce513Schristos	     them.  */
130416dce513Schristos
130516dce513Schristos	  length = CGEN_EXTRACT_FN (cd, insn)
130616dce513Schristos	    (cd, insn, &ex_info, insn_value, &fields, pc);
130716dce513Schristos
130816dce513Schristos	  /* Length < 0 -> error.  */
130916dce513Schristos	  if (length < 0)
131016dce513Schristos	    return length;
131116dce513Schristos	  if (length > 0)
131216dce513Schristos	    {
131316dce513Schristos	      CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
131416dce513Schristos	      /* Length is in bits, result is in bytes.  */
131516dce513Schristos	      return length / 8;
131616dce513Schristos	    }
131716dce513Schristos	}
131816dce513Schristos
131916dce513Schristos      insn_list = CGEN_DIS_NEXT_INSN (insn_list);
132016dce513Schristos    }
132116dce513Schristos
132216dce513Schristos  if (slot == SLOTS_P0S)
132316dce513Schristos    (*info->fprintf_func) (info->stream, "*unknown-p0s*");
132416dce513Schristos  else if (slot == SLOTS_P0)
132516dce513Schristos    (*info->fprintf_func) (info->stream, "*unknown-p0*");
132616dce513Schristos  else if (slot == SLOTS_P1)
132716dce513Schristos    (*info->fprintf_func) (info->stream, "*unknown-p1*");
132816dce513Schristos  else if (slot == SLOTS_C3)
132916dce513Schristos    (*info->fprintf_func) (info->stream, "*unknown-c3*");
133016dce513Schristos  return 0;
133116dce513Schristos}
133216dce513Schristos
133316dce513Schristosstatic int
133416dce513Schristosmep_examine_ivc2_insns (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, bfd_vma pc ATTRIBUTE_UNUSED, disassemble_info *info ATTRIBUTE_UNUSED)
133516dce513Schristos{
133616dce513Schristos  int status;
133716dce513Schristos  int buflength;
133816dce513Schristos  bfd_byte buf[8];
133916dce513Schristos  bfd_byte insn[8];
134016dce513Schristos  int e;
134116dce513Schristos
134216dce513Schristos  /* Read in 64 bits.  */
134316dce513Schristos  buflength = 8; /* VLIW insn spans 8 bytes.  */
134416dce513Schristos  status = (*info->read_memory_func) (pc, buf, buflength, info);
134516dce513Schristos
134616dce513Schristos  if (status != 0)
134716dce513Schristos    {
134816dce513Schristos      (*info->memory_error_func) (status, pc, info);
134916dce513Schristos      return -1;
135016dce513Schristos    }
135116dce513Schristos
135216dce513Schristos  if (info->endian == BFD_ENDIAN_LITTLE)
135316dce513Schristos    e = 1;
135416dce513Schristos  else
135516dce513Schristos    e = 0;
135616dce513Schristos
135716dce513Schristos  if (((unsigned char)buf[0^e] & 0xf0) < 0xc0)
135816dce513Schristos    {
135916dce513Schristos      /*      <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */
136016dce513Schristos      /* V1   [-----core-----][--------p0s-------][------------p1------------] */
136116dce513Schristos
136216dce513Schristos      print_insn (cd, pc, info, buf, 2);
136316dce513Schristos
136416dce513Schristos      insn[0^e] = 0;
136516dce513Schristos      insn[1^e] = buf[2^e];
136616dce513Schristos      insn[2^e] = buf[3^e];
136716dce513Schristos      insn[3^e] = buf[4^e] & 0xf0;
136816dce513Schristos      (*info->fprintf_func) (info->stream, " + ");
136916dce513Schristos      print_slot_insn (cd, pc, info, SLOTS_P0S, insn);
137016dce513Schristos
137116dce513Schristos      insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4;
137216dce513Schristos      insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4;
137316dce513Schristos      insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4;
137416dce513Schristos      insn[3^e] = buf[7^e] << 4;
137516dce513Schristos      (*info->fprintf_func) (info->stream, " + ");
137616dce513Schristos      print_slot_insn (cd, pc, info, SLOTS_P1, insn);
137716dce513Schristos    }
137816dce513Schristos  else if ((buf[0^e] & 0xf0) == 0xf0 && (buf[1^e] & 0x0f) == 0x07)
137916dce513Schristos    {
138016dce513Schristos      /*      <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */
138116dce513Schristos      /* V3   1111[--p0--]0111[--------p0--------][------------p1------------] */
138216dce513Schristos      /*                                          00000000111111112222222233333333 */
138316dce513Schristos
138416dce513Schristos      insn[0^e] = buf[0^e] << 4 | buf[1^e] >> 4;
138516dce513Schristos      insn[1^e] = buf[2^e];
138616dce513Schristos      insn[2^e] = buf[3^e];
138716dce513Schristos      insn[3^e] = buf[4^e] & 0xf0;
138816dce513Schristos      print_slot_insn (cd, pc, info, SLOTS_P0, insn);
138916dce513Schristos
139016dce513Schristos      insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4;
139116dce513Schristos      insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4;
139216dce513Schristos      insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4;
139316dce513Schristos      insn[3^e] = buf[7^e] << 4;
139416dce513Schristos      (*info->fprintf_func) (info->stream, " + ");
139516dce513Schristos      print_slot_insn (cd, pc, info, SLOTS_P1, insn);
139616dce513Schristos    }
139716dce513Schristos  else
139816dce513Schristos    {
139916dce513Schristos      /*      <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */
140016dce513Schristos      /* V2   [-------------core-------------]xxxx[------------p1------------] */
140116dce513Schristos      print_insn (cd, pc, info, buf, 4);
140216dce513Schristos
140316dce513Schristos      insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4;
140416dce513Schristos      insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4;
140516dce513Schristos      insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4;
140616dce513Schristos      insn[3^e] = buf[7^e] << 4;
140716dce513Schristos      (*info->fprintf_func) (info->stream, " + ");
140816dce513Schristos      print_slot_insn (cd, pc, info, SLOTS_P1, insn);
140916dce513Schristos    }
141016dce513Schristos
141116dce513Schristos  return 8;
141216dce513Schristos}
141316dce513Schristos
141416dce513Schristos#endif /* MEP_IVC2_SUPPORTED */
141516dce513Schristos
141616dce513Schristos/* This is a hack.  SID calls this to update the disassembler as the
141716dce513Schristos   CPU changes modes.  */
141816dce513Schristosstatic int mep_ivc2_disassemble_p = 0;
141916dce513Schristosstatic int mep_ivc2_vliw_disassemble_p = 0;
142016dce513Schristos
142116dce513Schristosvoid
142216dce513Schristosmep_print_insn_set_ivc2_mode (int ivc2_p, int vliw_p, int cfg_idx);
142316dce513Schristosvoid
142416dce513Schristosmep_print_insn_set_ivc2_mode (int ivc2_p, int vliw_p, int cfg_idx)
142516dce513Schristos{
142616dce513Schristos  mep_ivc2_disassemble_p = ivc2_p;
142716dce513Schristos  mep_ivc2_vliw_disassemble_p = vliw_p;
142816dce513Schristos  mep_config_index = cfg_idx;
142916dce513Schristos}
143016dce513Schristos
143116dce513Schristosstatic int
143216dce513Schristosmep_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
143316dce513Schristos{
143416dce513Schristos  int status;
143516dce513Schristos  int cop_type;
143616dce513Schristos  int ivc2 = 0;
143716dce513Schristos  static CGEN_ATTR_VALUE_BITSET_TYPE *ivc2_core_isa = NULL;
143816dce513Schristos
143916dce513Schristos  if (ivc2_core_isa == NULL)
144016dce513Schristos    {
144116dce513Schristos      /* IVC2 has some core-only coprocessor instructions.  We
144216dce513Schristos	 use COP32 to flag those, and COP64 for the VLIW ones,
144316dce513Schristos	 since they have the same names.  */
144416dce513Schristos      ivc2_core_isa = cgen_bitset_create (MAX_ISAS);
144516dce513Schristos    }
144616dce513Schristos
144716dce513Schristos  /* Extract and adapt to configuration number, if available. */
144816dce513Schristos  if (info->section && info->section->owner)
144916dce513Schristos    {
145016dce513Schristos      bfd *abfd = info->section->owner;
1451*e992f068Schristos      if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
1452*e992f068Schristos	{
145316dce513Schristos	  mep_config_index = abfd->tdata.elf_obj_data->elf_header->e_flags & EF_MEP_INDEX_MASK;
145416dce513Schristos	  /* This instantly redefines MEP_CONFIG, MEP_OMASK, .... MEP_VLIW64 */
145516dce513Schristos
145616dce513Schristos	  cop_type = abfd->tdata.elf_obj_data->elf_header->e_flags & EF_MEP_COP_MASK;
145716dce513Schristos	  if (cop_type == EF_MEP_COP_IVC2)
145816dce513Schristos	    ivc2 = 1;
145916dce513Schristos	}
1460*e992f068Schristos    }
146116dce513Schristos
146216dce513Schristos  /* Picking the right ISA bitmask for the current context is tricky.  */
146316dce513Schristos  if (info->section)
146416dce513Schristos    {
146516dce513Schristos      if (info->section->flags & SEC_MEP_VLIW)
146616dce513Schristos	{
146716dce513Schristos#ifdef MEP_IVC2_SUPPORTED
146816dce513Schristos	  if (ivc2)
146916dce513Schristos	    {
147016dce513Schristos	      /* ivc2 has its own way of selecting its functions.  */
147116dce513Schristos	      cd->isas = & MEP_CORE_ISA;
147216dce513Schristos	      status = mep_examine_ivc2_insns (cd, pc, info);
147316dce513Schristos	    }
147416dce513Schristos	  else
147516dce513Schristos#endif
147616dce513Schristos	    /* Are we in 32 or 64 bit vliw mode?  */
147716dce513Schristos	    if (MEP_VLIW64)
147816dce513Schristos	      status = mep_examine_vliw64_insns (cd, pc, info);
147916dce513Schristos	    else
148016dce513Schristos	      status = mep_examine_vliw32_insns (cd, pc, info);
148116dce513Schristos	  /* Both the above branches set their own isa bitmasks.  */
148216dce513Schristos	}
148316dce513Schristos      else
148416dce513Schristos	{
148516dce513Schristos	  if (ivc2)
148616dce513Schristos	    {
148716dce513Schristos	      cgen_bitset_clear (ivc2_core_isa);
148816dce513Schristos	      cgen_bitset_union (ivc2_core_isa, &MEP_CORE_ISA, ivc2_core_isa);
148916dce513Schristos	      cgen_bitset_union (ivc2_core_isa, &MEP_COP32_ISA, ivc2_core_isa);
149016dce513Schristos	      cd->isas = ivc2_core_isa;
149116dce513Schristos	    }
149216dce513Schristos	  else
149316dce513Schristos	    cd->isas = & MEP_CORE_ISA;
149416dce513Schristos	  status = default_print_insn (cd, pc, info);
149516dce513Schristos	}
149616dce513Schristos    }
149716dce513Schristos  else /* sid or gdb */
149816dce513Schristos    {
149916dce513Schristos#ifdef MEP_IVC2_SUPPORTED
150016dce513Schristos      if (mep_ivc2_disassemble_p)
150116dce513Schristos	{
150216dce513Schristos	  if (mep_ivc2_vliw_disassemble_p)
150316dce513Schristos	    {
150416dce513Schristos	      cd->isas = & MEP_CORE_ISA;
150516dce513Schristos	      status = mep_examine_ivc2_insns (cd, pc, info);
150616dce513Schristos	      return status;
150716dce513Schristos	    }
150816dce513Schristos	  else
150916dce513Schristos	    {
151016dce513Schristos	      if (ivc2)
151116dce513Schristos		cd->isas = ivc2_core_isa;
151216dce513Schristos	    }
151316dce513Schristos	}
151416dce513Schristos#endif
151516dce513Schristos
151616dce513Schristos      status = default_print_insn (cd, pc, info);
151716dce513Schristos    }
151816dce513Schristos
151916dce513Schristos  return status;
152016dce513Schristos}
152116dce513Schristos
152216dce513Schristos
152316dce513Schristos/* -- opc.c */
152416dce513Schristos#include "elf/mep.h"
152516dce513Schristos
152616dce513Schristos/* A mask for all ISAs executed by the core. */
152716dce513SchristosCGEN_ATTR_VALUE_BITSET_TYPE mep_all_core_isas_mask = {0, 0};
152816dce513Schristos
152916dce513Schristosvoid
153016dce513Schristosinit_mep_all_core_isas_mask (void)
153116dce513Schristos{
153216dce513Schristos  if (mep_all_core_isas_mask.length != 0)
153316dce513Schristos    return;
153416dce513Schristos  cgen_bitset_init (& mep_all_core_isas_mask, ISA_MAX);
153516dce513Schristos  cgen_bitset_set (& mep_all_core_isas_mask, ISA_MEP);
153616dce513Schristos  /* begin-all-core-isas */
153716dce513Schristos  cgen_bitset_add (& mep_all_core_isas_mask, ISA_EXT_CORE1);
153816dce513Schristos  /* end-all-core-isas */
153916dce513Schristos}
154016dce513Schristos
154116dce513SchristosCGEN_ATTR_VALUE_BITSET_TYPE mep_all_cop_isas_mask = {0, 0};
154216dce513Schristos
154316dce513Schristosvoid
154416dce513Schristosinit_mep_all_cop_isas_mask (void)
154516dce513Schristos{
154616dce513Schristos  if (mep_all_cop_isas_mask.length != 0)
154716dce513Schristos    return;
154816dce513Schristos  cgen_bitset_init (& mep_all_cop_isas_mask, ISA_MAX);
154916dce513Schristos  /* begin-all-cop-isas */
155016dce513Schristos  cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_16);
155116dce513Schristos  cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_32);
155216dce513Schristos  cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_48);
155316dce513Schristos  cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_64);
155416dce513Schristos  /* end-all-cop-isas */
155516dce513Schristos}
155616dce513Schristos
155716dce513Schristosint
155816dce513Schristosmep_insn_supported_by_isa (const CGEN_INSN *insn, CGEN_ATTR_VALUE_BITSET_TYPE *isa_mask)
155916dce513Schristos{
156016dce513Schristos  CGEN_BITSET insn_isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA);
156116dce513Schristos  return cgen_bitset_intersect_p (& insn_isas, isa_mask);
156216dce513Schristos}
156316dce513Schristos
156416dce513Schristos#define OPTION_MASK \
156516dce513Schristos	( (1 << CGEN_INSN_OPTIONAL_BIT_INSN) \
156616dce513Schristos	| (1 << CGEN_INSN_OPTIONAL_MUL_INSN) \
156716dce513Schristos	| (1 << CGEN_INSN_OPTIONAL_DIV_INSN) \
156816dce513Schristos	| (1 << CGEN_INSN_OPTIONAL_DEBUG_INSN) \
156916dce513Schristos	| (1 << CGEN_INSN_OPTIONAL_LDZ_INSN) \
157016dce513Schristos	| (1 << CGEN_INSN_OPTIONAL_ABS_INSN) \
157116dce513Schristos	| (1 << CGEN_INSN_OPTIONAL_AVE_INSN) \
157216dce513Schristos	| (1 << CGEN_INSN_OPTIONAL_MINMAX_INSN) \
157316dce513Schristos	| (1 << CGEN_INSN_OPTIONAL_CLIP_INSN) \
157416dce513Schristos	| (1 << CGEN_INSN_OPTIONAL_SAT_INSN) \
157516dce513Schristos	| (1 << CGEN_INSN_OPTIONAL_UCI_INSN) \
157616dce513Schristos	| (1 << CGEN_INSN_OPTIONAL_DSP_INSN) \
157716dce513Schristos	| (1 << CGEN_INSN_OPTIONAL_CP_INSN) \
157816dce513Schristos	| (1 << CGEN_INSN_OPTIONAL_CP64_INSN) )
157916dce513Schristos
158016dce513Schristos
158116dce513Schristosmep_config_map_struct mep_config_map[] =
158216dce513Schristos{
158316dce513Schristos  /* config-map-start */
158416dce513Schristos  /* Default entry: first module, with all options enabled. */
158516dce513Schristos  { "", 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) },
158616dce513Schristos  { "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" },
158716dce513Schristos	  0
158816dce513Schristos	| (1 << CGEN_INSN_OPTIONAL_CP_INSN)
158916dce513Schristos	| (1 << CGEN_INSN_OPTIONAL_CP64_INSN)
159016dce513Schristos	| (1 << CGEN_INSN_OPTIONAL_MUL_INSN)
159116dce513Schristos	| (1 << CGEN_INSN_OPTIONAL_DIV_INSN)
159216dce513Schristos	| (1 << CGEN_INSN_OPTIONAL_BIT_INSN)
159316dce513Schristos	| (1 << CGEN_INSN_OPTIONAL_LDZ_INSN)
159416dce513Schristos	| (1 << CGEN_INSN_OPTIONAL_ABS_INSN)
159516dce513Schristos	| (1 << CGEN_INSN_OPTIONAL_AVE_INSN)
159616dce513Schristos	| (1 << CGEN_INSN_OPTIONAL_MINMAX_INSN)
159716dce513Schristos	| (1 << CGEN_INSN_OPTIONAL_CLIP_INSN)
159816dce513Schristos	| (1 << CGEN_INSN_OPTIONAL_SAT_INSN) },
159916dce513Schristos  /* config-map-end */
160016dce513Schristos  { 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, 0 }
160116dce513Schristos};
160216dce513Schristos
160316dce513Schristosint mep_config_index = 0;
160416dce513Schristos
160516dce513Schristosstatic int
160616dce513Schristoscheck_configured_mach (int machs)
160716dce513Schristos{
160816dce513Schristos  /* All base insns are supported.  */
160916dce513Schristos  int mach = 1 << MACH_BASE;
161016dce513Schristos  switch (MEP_CPU & EF_MEP_CPU_MASK)
161116dce513Schristos    {
161216dce513Schristos    case EF_MEP_CPU_C2:
161316dce513Schristos    case EF_MEP_CPU_C3:
161416dce513Schristos      mach |= (1 << MACH_MEP);
161516dce513Schristos      break;
161616dce513Schristos    case EF_MEP_CPU_H1:
161716dce513Schristos      mach |= (1 << MACH_H1);
161816dce513Schristos      break;
161916dce513Schristos    case EF_MEP_CPU_C5:
162016dce513Schristos      mach |= (1 << MACH_MEP);
162116dce513Schristos      mach |= (1 << MACH_C5);
162216dce513Schristos      break;
162316dce513Schristos    default:
162416dce513Schristos      break;
162516dce513Schristos    }
162616dce513Schristos  return machs & mach;
162716dce513Schristos}
162816dce513Schristos
162916dce513Schristosint
163016dce513Schristosmep_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
163116dce513Schristos{
163216dce513Schristos  int iconfig = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG);
163316dce513Schristos  int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
163416dce513Schristos  CGEN_BITSET isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA);
163516dce513Schristos  int ok1;
163616dce513Schristos  int ok2;
163716dce513Schristos  int ok3;
163816dce513Schristos
163916dce513Schristos  /* If the insn has an option bit set that we don't want,
164016dce513Schristos     reject it.  */
164116dce513Schristos  if (CGEN_INSN_ATTRS (insn)->bool_ & OPTION_MASK & ~MEP_OMASK)
164216dce513Schristos    return 0;
164316dce513Schristos
164416dce513Schristos  /* If attributes are absent, assume no restriction. */
164516dce513Schristos  if (machs == 0)
164616dce513Schristos    machs = ~0;
164716dce513Schristos
164816dce513Schristos  ok1 = ((machs & cd->machs) && cgen_bitset_intersect_p (& isas, cd->isas));
164916dce513Schristos  /* If the insn is config-specific, make sure it matches.  */
165016dce513Schristos  ok2 =  (iconfig == 0 || iconfig == MEP_CONFIG);
165116dce513Schristos  /* Make sure the insn is supported by the configured mach  */
165216dce513Schristos  ok3 = check_configured_mach (machs);
165316dce513Schristos
165416dce513Schristos  return (ok1 && ok2 && ok3);
165516dce513Schristos}
165616dce513Schristos
165716dce513Schristosint
165816dce513Schristosmep_cgen_insn_supported_asm (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
165916dce513Schristos{
166016dce513Schristos#ifdef MEP_IVC2_SUPPORTED
166116dce513Schristos  /* If we're assembling VLIW packets, ignore the 12-bit BSR as we
166216dce513Schristos     can't relax that.  The 24-bit BSR is matched instead.  */
166316dce513Schristos  if (insn->base->num == MEP_INSN_BSR12
166416dce513Schristos      && cgen_bitset_contains (cd->isas, ISA_EXT_COP1_64))
166516dce513Schristos    return 0;
166616dce513Schristos#endif
166716dce513Schristos
166816dce513Schristos  return mep_cgen_insn_supported (cd, insn);
166916dce513Schristos}
1670