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