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