1 /* MeP opcode support. -*- C -*-
2 Copyright 2011 Free Software Foundation, Inc.
4 Contributed by Red Hat Inc;
6 This file is part of the GNU Binutils.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 MA 02110-1301, USA. */
25 #undef CGEN_DIS_HASH_SIZE
26 #define CGEN_DIS_HASH_SIZE 1
29 #define CGEN_DIS_HASH(buffer, insn) 0
31 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
40 CGEN_ATTR_VALUE_BITSET_TYPE cop16_isa;
41 CGEN_ATTR_VALUE_BITSET_TYPE cop32_isa;
42 CGEN_ATTR_VALUE_BITSET_TYPE cop48_isa;
43 CGEN_ATTR_VALUE_BITSET_TYPE cop64_isa;
44 CGEN_ATTR_VALUE_BITSET_TYPE cop_isa;
45 CGEN_ATTR_VALUE_BITSET_TYPE core_isa;
46 unsigned int option_mask;
47 } mep_config_map_struct;
49 extern mep_config_map_struct mep_config_map[];
50 extern int mep_config_index;
52 extern void init_mep_all_core_isas_mask (void);
53 extern void init_mep_all_cop_isas_mask (void);
54 extern CGEN_ATTR_VALUE_BITSET_TYPE mep_cop_isa (void);
56 #define MEP_CONFIG (mep_config_map[mep_config_index].config_enum)
57 #define MEP_CPU (mep_config_map[mep_config_index].cpu_flag)
58 #define MEP_OMASK (mep_config_map[mep_config_index].option_mask)
59 #define MEP_VLIW (mep_config_map[mep_config_index].vliw_bits > 0)
60 #define MEP_VLIW32 (mep_config_map[mep_config_index].vliw_bits == 32)
61 #define MEP_VLIW64 (mep_config_map[mep_config_index].vliw_bits == 64)
62 #define MEP_COP16_ISA (mep_config_map[mep_config_index].cop16_isa)
63 #define MEP_COP32_ISA (mep_config_map[mep_config_index].cop32_isa)
64 #define MEP_COP48_ISA (mep_config_map[mep_config_index].cop48_isa)
65 #define MEP_COP64_ISA (mep_config_map[mep_config_index].cop64_isa)
66 #define MEP_COP_ISA (mep_config_map[mep_config_index].cop_isa)
67 #define MEP_CORE_ISA (mep_config_map[mep_config_index].core_isa)
69 /* begin-cop-ip-supported-defines */
70 #define MEP_IVC2_SUPPORTED 1
71 /* end-cop-ip-supported-defines */
73 extern int mep_insn_supported_by_isa (const CGEN_INSN *, CGEN_ATTR_VALUE_BITSET_TYPE *);
75 /* A mask for all ISAs executed by the core. */
76 #define MEP_ALL_CORE_ISAS_MASK mep_all_core_isas_mask
77 extern CGEN_ATTR_VALUE_BITSET_TYPE mep_all_core_isas_mask;
79 #define MEP_INSN_CORE_P(insn) ( \
80 init_mep_all_core_isas_mask (), \
81 mep_insn_supported_by_isa (insn, & MEP_ALL_CORE_ISAS_MASK) \
84 /* A mask for all ISAs executed by a VLIW coprocessor. */
85 #define MEP_ALL_COP_ISAS_MASK mep_all_cop_isas_mask
86 extern CGEN_ATTR_VALUE_BITSET_TYPE mep_all_cop_isas_mask;
88 #define MEP_INSN_COP_P(insn) ( \
89 init_mep_all_cop_isas_mask (), \
90 mep_insn_supported_by_isa (insn, & MEP_ALL_COP_ISAS_MASK) \
93 extern int mep_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
94 extern int mep_cgen_insn_supported_asm (CGEN_CPU_DESC, const CGEN_INSN *);
100 #define CGEN_VALIDATE_INSN_SUPPORTED
101 #define mep_cgen_insn_supported mep_cgen_insn_supported_asm
103 const char * parse_csrn (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *);
104 const char * parse_tpreg (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *);
105 const char * parse_spreg (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *);
106 const char * parse_mep_align (CGEN_CPU_DESC, const char **, enum cgen_operand_type, long *);
107 const char * parse_mep_alignu (CGEN_CPU_DESC, const char **, enum cgen_operand_type, unsigned long *);
108 static const char * parse_signed16 (CGEN_CPU_DESC, const char **, int, long *);
109 static const char * parse_signed16_range (CGEN_CPU_DESC, const char **, int, long *) ATTRIBUTE_UNUSED;
110 static const char * parse_unsigned16 (CGEN_CPU_DESC, const char **, int, unsigned long *);
111 static const char * parse_unsigned16_range (CGEN_CPU_DESC, const char **, int, unsigned long *) ATTRIBUTE_UNUSED;
112 static const char * parse_lo16 (CGEN_CPU_DESC, const char **, int, long *, long);
113 static const char * parse_unsigned7 (CGEN_CPU_DESC, const char **, enum cgen_operand_type, unsigned long *);
114 static const char * parse_zero (CGEN_CPU_DESC, const char **, int, long *);
117 parse_csrn (CGEN_CPU_DESC cd, const char **strp,
118 CGEN_KEYWORD *keyword_table, long *field)
123 err = cgen_parse_keyword (cd, strp, keyword_table, field);
127 err = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_CSRN_IDX, & value);
134 /* begin-cop-ip-parse-handlers */
136 parse_ivc2_cr (CGEN_CPU_DESC,
139 long *) ATTRIBUTE_UNUSED;
141 parse_ivc2_cr (CGEN_CPU_DESC cd,
143 CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED,
146 return cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_cr_ivc2, field);
149 parse_ivc2_ccr (CGEN_CPU_DESC,
152 long *) ATTRIBUTE_UNUSED;
154 parse_ivc2_ccr (CGEN_CPU_DESC cd,
156 CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED,
159 return cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_ccr_ivc2, field);
161 /* end-cop-ip-parse-handlers */
164 parse_tpreg (CGEN_CPU_DESC cd, const char ** strp,
165 CGEN_KEYWORD *keyword_table, long *field)
169 err = cgen_parse_keyword (cd, strp, keyword_table, field);
173 return _("Only $tp or $13 allowed for this opcode");
178 parse_spreg (CGEN_CPU_DESC cd, const char ** strp,
179 CGEN_KEYWORD *keyword_table, long *field)
183 err = cgen_parse_keyword (cd, strp, keyword_table, field);
187 return _("Only $sp or $15 allowed for this opcode");
192 parse_mep_align (CGEN_CPU_DESC cd, const char ** strp,
193 enum cgen_operand_type type, long *field)
200 case MEP_OPERAND_PCREL8A2:
201 case MEP_OPERAND_PCREL12A2:
202 case MEP_OPERAND_PCREL17A2:
203 case MEP_OPERAND_PCREL24A2:
204 err = cgen_parse_signed_integer (cd, strp, type, field);
206 case MEP_OPERAND_PCABS24A2:
207 case MEP_OPERAND_UDISP7:
208 case MEP_OPERAND_UDISP7A2:
209 case MEP_OPERAND_UDISP7A4:
210 case MEP_OPERAND_UIMM7A4:
211 case MEP_OPERAND_ADDR24A4:
212 err = cgen_parse_unsigned_integer (cd, strp, type, (unsigned long *) field);
221 case MEP_OPERAND_UDISP7:
224 case MEP_OPERAND_PCREL8A2:
225 case MEP_OPERAND_PCREL12A2:
226 case MEP_OPERAND_PCREL17A2:
227 case MEP_OPERAND_PCREL24A2:
228 case MEP_OPERAND_PCABS24A2:
229 case MEP_OPERAND_UDISP7A2:
232 case MEP_OPERAND_UDISP7A4:
233 case MEP_OPERAND_UIMM7A4:
234 case MEP_OPERAND_ADDR24A4:
240 /* Safe assumption? */
244 return "Value is not aligned enough";
249 parse_mep_alignu (CGEN_CPU_DESC cd, const char ** strp,
250 enum cgen_operand_type type, unsigned long *field)
252 return parse_mep_align (cd, strp, type, (long *) field);
256 /* Handle %lo(), %tpoff(), %sdaoff(), %hi(), and other signed
257 constants in a signed context. */
260 parse_signed16 (CGEN_CPU_DESC cd,
265 return parse_lo16 (cd, strp, opindex, valuep, 1);
269 parse_lo16 (CGEN_CPU_DESC cd,
276 enum cgen_parse_operand_result result_type;
279 if (strncasecmp (*strp, "%lo(", 4) == 0)
282 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_LOW16,
283 & result_type, & value);
285 return _("missing `)'");
288 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
291 *valuep = (long)(short) value;
297 if (strncasecmp (*strp, "%hi(", 4) == 0)
300 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16S,
301 & result_type, & value);
303 return _("missing `)'");
306 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
307 value = (value + 0x8000) >> 16;
312 if (strncasecmp (*strp, "%uhi(", 5) == 0)
315 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16U,
316 & result_type, & value);
318 return _("missing `)'");
321 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
327 if (strncasecmp (*strp, "%sdaoff(", 8) == 0)
330 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_GPREL,
333 return _("missing `)'");
339 if (strncasecmp (*strp, "%tpoff(", 7) == 0)
342 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_TPREL,
345 return _("missing `)'");
352 return _("invalid %function() here");
354 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
358 parse_unsigned16 (CGEN_CPU_DESC cd,
361 unsigned long *valuep)
363 return parse_lo16 (cd, strp, opindex, (long *) valuep, 0);
367 parse_signed16_range (CGEN_CPU_DESC cd,
372 const char *errmsg = 0;
375 errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
379 if (value < -32768 || value > 32767)
380 return _("Immediate is out of range -32768 to 32767");
387 parse_unsigned16_range (CGEN_CPU_DESC cd,
390 unsigned long *valuep)
392 const char *errmsg = 0;
395 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
400 return _("Immediate is out of range 0 to 65535");
406 /* A special case of parse_signed16 which accepts only the value zero. */
409 parse_zero (CGEN_CPU_DESC cd, const char **strp, int opindex, long *valuep)
412 enum cgen_parse_operand_result result_type;
415 /*fprintf(stderr, "dj: signed parse opindex `%s'\n", *strp);*/
417 /* Prevent ($ry) from being attempted as an expression on 'sw $rx,($ry)'.
418 It will fail and cause ry to be listed as an undefined symbol in the
420 if (strncmp (*strp, "($", 2) == 0)
421 return "not zero"; /* any string will do -- will never be seen. */
423 if (strncasecmp (*strp, "%lo(", 4) == 0)
426 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_LOW16,
427 &result_type, &value);
429 return "missing `)'";
432 && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
433 return "not zero"; /* any string will do -- will never be seen. */
438 if (strncasecmp (*strp, "%hi(", 4) == 0)
441 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16S,
442 &result_type, &value);
444 return "missing `)'";
447 && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
448 return "not zero"; /* any string will do -- will never be seen. */
453 if (strncasecmp (*strp, "%uhi(", 5) == 0)
456 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16U,
457 &result_type, &value);
459 return "missing `)'";
462 && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
463 return "not zero"; /* any string will do -- will never be seen. */
468 if (strncasecmp (*strp, "%sdaoff(", 8) == 0)
471 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_GPREL,
472 &result_type, &value);
474 return "missing `)'";
477 && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
478 return "not zero"; /* any string will do -- will never be seen. */
483 if (strncasecmp (*strp, "%tpoff(", 7) == 0)
486 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_TPREL,
487 &result_type, &value);
489 return "missing `)'";
492 && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
493 return "not zero"; /* any string will do -- will never be seen. */
499 return "invalid %function() here";
501 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_NONE,
502 &result_type, &value);
504 && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
505 return "not zero"; /* any string will do -- will never be seen. */
511 parse_unsigned7 (CGEN_CPU_DESC cd, const char **strp,
512 enum cgen_operand_type opindex, unsigned long *valuep)
517 /* fprintf(stderr, "dj: unsigned7 parse `%s'\n", *strp); */
519 if (strncasecmp (*strp, "%tpoff(", 7) == 0)
525 case MEP_OPERAND_UDISP7:
526 reloc = BFD_RELOC_MEP_TPREL7;
528 case MEP_OPERAND_UDISP7A2:
529 reloc = BFD_RELOC_MEP_TPREL7A2;
531 case MEP_OPERAND_UDISP7A4:
532 reloc = BFD_RELOC_MEP_TPREL7A4;
535 /* Safe assumption? */
538 errmsg = cgen_parse_address (cd, strp, opindex, reloc,
541 return "missing `)'";
548 return _("invalid %function() here");
550 return parse_mep_alignu (cd, strp, opindex, valuep);
553 static ATTRIBUTE_UNUSED const char *
554 parse_cdisp10 (CGEN_CPU_DESC cd,
559 const char *errmsg = 0;
567 case MEP_OPERAND_CDISP10A4:
570 case MEP_OPERAND_CDISP10A2:
573 case MEP_OPERAND_CDISP10:
579 if ((MEP_CPU & EF_MEP_CPU_MASK) == EF_MEP_CPU_C5)
582 if (strncmp (*strp, "0x0", 3) == 0
583 || (**strp == '0' && *(*strp + 1) != 'x'))
586 errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
592 if (value < -512 || value > 511)
593 return _("Immediate is out of range -512 to 511");
597 if (value < -128 || value > 127)
598 return _("Immediate is out of range -128 to 127");
601 if (value & ((1<<alignment)-1))
602 return _("Value is not aligned enough");
604 /* If this field may require a relocation then use larger dsp16. */
605 if (! have_zero && value == 0)
606 return (wide ? _("Immediate is out of range -512 to 511")
607 : _("Immediate is out of range -128 to 127"));
613 /* BEGIN LIGHTWEIGHT MACRO PROCESSOR. */
631 { "sizeof", "(`1.end + (- `1))"},
632 { "startof", "(`1 | 0)" },
633 { "align4", "(`1&(~3))"},
634 /*{ "hi", "(((`1+0x8000)>>16) & 0xffff)" }, */
635 /*{ "lo", "(`1 & 0xffff)" }, */
636 /*{ "sdaoff", "((`1-__sdabase) & 0x7f)"}, */
637 /*{ "tpoff", "((`1-__tpbase) & 0x7f)"}, */
641 static char * expand_string (const char *, int);
644 mep_cgen_expand_macros_and_parse_operand
645 (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
648 str_append (char *dest, const char *input, int len)
655 /* printf("str_append: <<%s>>, <<%s>>, %d\n", dest, input, len); */
656 oldlen = (dest ? strlen(dest) : 0);
657 new_dest = realloc (dest, oldlen + len + 1);
658 memset (new_dest + oldlen, 0, len + 1);
659 return strncat (new_dest, input, len);
663 lookup_macro (const char *name)
667 for (m = macros; m->name; ++m)
668 if (strncmp (m->name, name, strlen(m->name)) == 0)
675 expand_macro (arg *args, int narg, macro *mac)
677 char *result = 0, *rescanned_result = 0;
678 char *e = mac->expansion;
682 /* printf("expanding macro %s with %d args\n", mac->name, narg + 1); */
687 ((*(e + 1) - '1') <= MAXARGS) &&
688 ((*(e + 1) - '1') <= narg))
690 result = str_append (result, mark, e - mark);
691 mac_arg = (*(e + 1) - '1');
692 /* printf("replacing `%d with %s\n", mac_arg+1, args[mac_arg].start); */
693 result = str_append (result, args[mac_arg].start, args[mac_arg].len);
701 result = str_append (result, mark, e - mark);
705 rescanned_result = expand_string (result, 0);
707 return rescanned_result;
717 expand_string (const char *in, int first_only)
719 int num_expansions = 0;
724 const char *mark = in;
725 macro *pmacro = NULL;
734 if (*in == '%' && *(in + 1) && (!first_only || num_expansions == 0))
736 pmacro = lookup_macro (in + 1);
739 /* printf("entering state %d at '%s'...\n", state, in); */
740 result = str_append (result, mark, in - mark);
742 in += 1 + strlen (pmacro->name);
743 while (*in == ' ') ++in;
753 args[narg].start = in + 1;
767 args[narg].start = (in + 1);
772 /* printf("entering state %d at '%s'...\n", state, in); */
776 expansion = expand_macro (args, narg, pmacro);
780 result = str_append (result, expansion, strlen (expansion));
786 result = str_append (result, mark, in - mark);
811 result = str_append (result, mark, in - mark);
821 /* END LIGHTWEIGHT MACRO PROCESSOR. */
823 const char * mep_cgen_parse_operand
824 (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
827 mep_cgen_expand_macros_and_parse_operand (CGEN_CPU_DESC cd, int opindex,
828 const char ** strp_in, CGEN_FIELDS * fields)
830 const char * errmsg = NULL;
831 char *str = 0, *hold = 0;
832 const char **strp = 0;
834 /* Set up a new pointer to macro-expanded string. */
835 str = expand_string (*strp_in, 1);
836 /* fprintf (stderr, " expanded <<%s>> to <<%s>>\n", *strp_in, str); */
839 strp = (const char **)(&str);
841 errmsg = mep_cgen_parse_operand (cd, opindex, strp, fields);
843 /* Now work out the advance. */
844 if (strlen (str) == 0)
845 *strp_in += strlen (*strp_in);
849 if (strstr (*strp_in, str))
850 /* A macro-expansion was pulled off the front. */
851 *strp_in = strstr (*strp_in, str);
853 /* A non-macro-expansion was pulled off the front. */
854 *strp_in += (str - hold);
863 #define CGEN_ASM_INIT_HOOK (cd->parse_operand = mep_cgen_expand_macros_and_parse_operand);
870 #define CGEN_VALIDATE_INSN_SUPPORTED
872 static void print_tpreg (CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned int);
873 static void print_spreg (CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned int);
876 print_tpreg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, PTR dis_info,
877 CGEN_KEYWORD *table ATTRIBUTE_UNUSED, long val ATTRIBUTE_UNUSED,
878 unsigned int flags ATTRIBUTE_UNUSED)
880 disassemble_info *info = (disassemble_info *) dis_info;
882 (*info->fprintf_func) (info->stream, "$tp");
886 print_spreg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, PTR dis_info,
887 CGEN_KEYWORD *table ATTRIBUTE_UNUSED, long val ATTRIBUTE_UNUSED,
888 unsigned int flags ATTRIBUTE_UNUSED)
890 disassemble_info *info = (disassemble_info *) dis_info;
892 (*info->fprintf_func) (info->stream, "$sp");
895 /* begin-cop-ip-print-handlers */
897 print_ivc2_cr (CGEN_CPU_DESC,
901 unsigned int) ATTRIBUTE_UNUSED;
903 print_ivc2_cr (CGEN_CPU_DESC cd,
905 CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED,
909 print_keyword (cd, dis_info, & mep_cgen_opval_h_cr_ivc2, value, attrs);
912 print_ivc2_ccr (CGEN_CPU_DESC,
916 unsigned int) ATTRIBUTE_UNUSED;
918 print_ivc2_ccr (CGEN_CPU_DESC cd,
920 CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED,
924 print_keyword (cd, dis_info, & mep_cgen_opval_h_ccr_ivc2, value, attrs);
926 /* end-cop-ip-print-handlers */
928 /************************************************************\
929 *********************** Experimental *************************
930 \************************************************************/
932 #undef CGEN_PRINT_INSN
933 #define CGEN_PRINT_INSN mep_print_insn
936 mep_print_vliw_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info,
937 bfd_byte *buf, int corelength, int copro1length,
938 int copro2length ATTRIBUTE_UNUSED)
942 /* char insnbuf[CGEN_MAX_INSN_SIZE]; */
943 bfd_byte insnbuf[64];
945 /* If corelength > 0 then there is a core insn present. It
946 will be at the beginning of the buffer. After printing
947 the core insn, we need to print the + on the next line. */
952 for (i = 0; i < corelength; i++ )
954 cd->isas = & MEP_CORE_ISA;
956 my_status = print_insn (cd, pc, info, insnbuf, corelength);
957 if (my_status != corelength)
959 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
960 my_status = corelength;
964 /* Print the + to indicate that the following copro insn is */
965 /* part of a vliw group. */
966 if (copro1length > 0)
967 (*info->fprintf_func) (info->stream, " + ");
970 /* Now all that is left to be processed is the coprocessor insns
971 In vliw mode, there will always be one. Its positioning will
972 be from byte corelength to byte corelength+copro1length -1.
973 No need to check for existence. Also, the first vliw insn,
974 will, as spec'd, always be at least as long as the core insn
975 so we don't need to flush the buffer. */
976 if (copro1length > 0)
980 for (i = corelength; i < corelength + copro1length; i++ )
981 insnbuf[i - corelength] = buf[i];
983 switch (copro1length)
988 cd->isas = & MEP_COP16_ISA;
991 cd->isas = & MEP_COP32_ISA;
994 cd->isas = & MEP_COP48_ISA;
997 cd->isas = & MEP_COP64_ISA;
1000 /* Shouldn't be anything but 16,32,48,64. */
1004 my_status = print_insn (cd, pc, info, insnbuf, copro1length);
1006 if (my_status != copro1length)
1008 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
1009 my_status = copro1length;
1011 status += my_status;
1015 /* Now we need to process the second copro insn if it exists. We
1016 have no guarantee that the second copro insn will be longer
1017 than the first, so we have to flush the buffer if we are have
1018 a second copro insn to process. If present, this insn will
1019 be in the position from byte corelength+copro1length to byte
1020 corelength+copro1length+copro2length-1 (which better equal 8
1021 or else we're in big trouble. */
1022 if (copro2length > 0)
1026 for (i = 0; i < 64 ; i++)
1029 for (i = corelength + copro1length; i < 64; i++)
1030 insnbuf[i - (corelength + copro1length)] = buf[i];
1032 switch (copro2length)
1035 cd->isas = 1 << ISA_EXT_COP1_16;
1038 cd->isas = 1 << ISA_EXT_COP1_32;
1041 cd->isas = 1 << ISA_EXT_COP1_48;
1044 cd->isas = 1 << ISA_EXT_COP1_64;
1047 /* Shouldn't be anything but 16,32,48,64. */
1051 my_status = print_insn (cd, pc, info, insnbuf, copro2length);
1053 if (my_status != copro2length)
1055 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
1056 my_status = copro2length;
1059 status += my_status;
1063 /* Status should now be the number of bytes that were printed
1064 which should be 4 for VLIW32 mode and 64 for VLIW64 mode. */
1066 if ((!MEP_VLIW64 && (status != 4)) || (MEP_VLIW64 && (status != 8)))
1072 /* The two functions mep_examine_vliw[32,64]_insns are used find out
1073 which vliw combinaion (16 bit core with 48 bit copro, 32 bit core
1074 with 32 bit copro, etc.) is present. Later on, when internally
1075 parallel coprocessors are handled, only these functions should
1078 At this time only the following combinations are supported:
1081 16 bit core insn (core) and 16 bit coprocessor insn (cop1)
1082 32 bit core insn (core)
1083 32 bit coprocessor insn (cop1)
1084 Note: As of this time, I do not believe we have enough information
1085 to distinguish a 32 bit core insn from a 32 bit cop insn. Also,
1086 no 16 bit coprocessor insns have been specified.
1089 16 bit core insn (core) and 48 bit coprocessor insn (cop1)
1090 32 bit core insn (core) and 32 bit coprocessor insn (cop1)
1091 64 bit coprocessor insn (cop1)
1093 The framework for an internally parallel coprocessor is also
1094 present (2nd coprocessor insn is cop2), but at this time it
1095 is not used. This only appears to be valid in VLIW64 mode. */
1098 mep_examine_vliw32_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
1105 bfd_byte buf[CGEN_MAX_INSN_SIZE];
1106 char indicator16[1];
1107 char indicatorcop32[2];
1109 /* At this time we're not supporting internally parallel coprocessors,
1110 so cop2buflength will always be 0. */
1113 /* Read in 32 bits. */
1114 buflength = 4; /* VLIW insn spans 4 bytes. */
1115 status = (*info->read_memory_func) (pc, buf, buflength, info);
1119 (*info->memory_error_func) (status, pc, info);
1123 /* Put the big endian representation of the bytes to be examined
1124 in the temporary buffers for examination. */
1126 if (info->endian == BFD_ENDIAN_BIG)
1128 indicator16[0] = buf[0];
1129 indicatorcop32[0] = buf[0];
1130 indicatorcop32[1] = buf[1];
1134 indicator16[0] = buf[1];
1135 indicatorcop32[0] = buf[1];
1136 indicatorcop32[1] = buf[0];
1139 /* If the two high order bits are 00, 01 or 10, we have a 16 bit
1140 core insn and a 48 bit copro insn. */
1142 if ((indicator16[0] & 0x80) && (indicator16[0] & 0x40))
1144 if ((indicatorcop32[0] & 0xf0) == 0xf0 && (indicatorcop32[1] & 0x07) == 0x07)
1146 /* We have a 32 bit copro insn. */
1148 /* All 4 4ytes are one copro insn. */
1153 /* We have a 32 bit core. */
1160 /* We have a 16 bit core insn and a 16 bit copro insn. */
1165 /* Now we have the distrubution set. Print them out. */
1166 status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength,
1167 cop1buflength, cop2buflength);
1173 mep_examine_vliw64_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
1180 bfd_byte buf[CGEN_MAX_INSN_SIZE];
1181 char indicator16[1];
1182 char indicator64[4];
1184 /* At this time we're not supporting internally parallel
1185 coprocessors, so cop2buflength will always be 0. */
1188 /* Read in 64 bits. */
1189 buflength = 8; /* VLIW insn spans 8 bytes. */
1190 status = (*info->read_memory_func) (pc, buf, buflength, info);
1194 (*info->memory_error_func) (status, pc, info);
1198 /* We have all 64 bits in the buffer now. We have to figure out
1199 what combination of instruction sizes are present. The two
1200 high order bits will indicate whether or not we have a 16 bit
1201 core insn or not. If not, then we have to look at the 7,8th
1202 bytes to tell whether we have 64 bit copro insn or a 32 bit
1203 core insn with a 32 bit copro insn. Endianness will make a
1206 /* Put the big endian representation of the bytes to be examined
1207 in the temporary buffers for examination. */
1209 /* indicator16[0] = buf[0]; */
1210 if (info->endian == BFD_ENDIAN_BIG)
1212 indicator16[0] = buf[0];
1213 indicator64[0] = buf[0];
1214 indicator64[1] = buf[1];
1215 indicator64[2] = buf[2];
1216 indicator64[3] = buf[3];
1220 indicator16[0] = buf[1];
1221 indicator64[0] = buf[1];
1222 indicator64[1] = buf[0];
1223 indicator64[2] = buf[3];
1224 indicator64[3] = buf[2];
1227 /* If the two high order bits are 00, 01 or 10, we have a 16 bit
1228 core insn and a 48 bit copro insn. */
1230 if ((indicator16[0] & 0x80) && (indicator16[0] & 0x40))
1232 if ((indicator64[0] & 0xf0) == 0xf0 && (indicator64[1] & 0x07) == 0x07
1233 && ((indicator64[2] & 0xfe) != 0xf0 || (indicator64[3] & 0xf4) != 0))
1235 /* We have a 64 bit copro insn. */
1237 /* All 8 bytes are one copro insn. */
1242 /* We have a 32 bit core insn and a 32 bit copro insn. */
1249 /* We have a 16 bit core insn and a 48 bit copro insn. */
1254 /* Now we have the distrubution set. Print them out. */
1255 status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength,
1256 cop1buflength, cop2buflength);
1261 #ifdef MEP_IVC2_SUPPORTED
1264 print_slot_insn (CGEN_CPU_DESC cd,
1266 disassemble_info *info,
1270 const CGEN_INSN_LIST *insn_list;
1271 CGEN_INSN_INT insn_value;
1272 CGEN_EXTRACT_INFO ex_info;
1274 insn_value = cgen_get_insn_value (cd, buf, 32);
1276 /* Fill in ex_info fields like read_insn would. Don't actually call
1277 read_insn, since the incoming buffer is already read (and possibly
1278 modified a la m32r). */
1279 ex_info.valid = (1 << 8) - 1;
1280 ex_info.dis_info = info;
1281 ex_info.insn_bytes = buf;
1283 /* The instructions are stored in hash lists.
1284 Pick the first one and keep trying until we find the right one. */
1286 insn_list = CGEN_DIS_LOOKUP_INSN (cd, (char *) buf, insn_value);
1287 while (insn_list != NULL)
1289 const CGEN_INSN *insn = insn_list->insn;
1293 if ((CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG)
1294 && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG) != MEP_CONFIG)
1295 || ! (CGEN_ATTR_CGEN_INSN_SLOTS_VALUE (CGEN_INSN_ATTRS (insn)) & (1 << slot)))
1297 insn_list = CGEN_DIS_NEXT_INSN (insn_list);
1301 if ((insn_value & CGEN_INSN_BASE_MASK (insn))
1302 == CGEN_INSN_BASE_VALUE (insn))
1304 /* Printing is handled in two passes. The first pass parses the
1305 machine insn and extracts the fields. The second pass prints
1308 length = CGEN_EXTRACT_FN (cd, insn)
1309 (cd, insn, &ex_info, insn_value, &fields, pc);
1311 /* Length < 0 -> error. */
1316 CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
1317 /* Length is in bits, result is in bytes. */
1322 insn_list = CGEN_DIS_NEXT_INSN (insn_list);
1325 if (slot == SLOTS_P0S)
1326 (*info->fprintf_func) (info->stream, "*unknown-p0s*");
1327 else if (slot == SLOTS_P0)
1328 (*info->fprintf_func) (info->stream, "*unknown-p0*");
1329 else if (slot == SLOTS_P1)
1330 (*info->fprintf_func) (info->stream, "*unknown-p1*");
1331 else if (slot == SLOTS_C3)
1332 (*info->fprintf_func) (info->stream, "*unknown-c3*");
1337 mep_examine_ivc2_insns (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, bfd_vma pc ATTRIBUTE_UNUSED, disassemble_info *info ATTRIBUTE_UNUSED)
1345 /* Read in 64 bits. */
1346 buflength = 8; /* VLIW insn spans 8 bytes. */
1347 status = (*info->read_memory_func) (pc, buf, buflength, info);
1351 (*info->memory_error_func) (status, pc, info);
1355 if (info->endian == BFD_ENDIAN_LITTLE)
1360 if (((unsigned char)buf[0^e] & 0xf0) < 0xc0)
1362 /* <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */
1363 /* V1 [-----core-----][--------p0s-------][------------p1------------] */
1365 print_insn (cd, pc, info, buf, 2);
1368 insn[1^e] = buf[2^e];
1369 insn[2^e] = buf[3^e];
1370 insn[3^e] = buf[4^e] & 0xf0;
1371 (*info->fprintf_func) (info->stream, " + ");
1372 print_slot_insn (cd, pc, info, SLOTS_P0S, insn);
1374 insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4;
1375 insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4;
1376 insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4;
1377 insn[3^e] = buf[7^e] << 4;
1378 (*info->fprintf_func) (info->stream, " + ");
1379 print_slot_insn (cd, pc, info, SLOTS_P1, insn);
1381 else if ((buf[0^e] & 0xf0) == 0xf0 && (buf[1^e] & 0x0f) == 0x07)
1383 /* <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */
1384 /* V3 1111[--p0--]0111[--------p0--------][------------p1------------] */
1385 /* 00000000111111112222222233333333 */
1387 insn[0^e] = buf[0^e] << 4 | buf[1^e] >> 4;
1388 insn[1^e] = buf[2^e];
1389 insn[2^e] = buf[3^e];
1390 insn[3^e] = buf[4^e] & 0xf0;
1391 print_slot_insn (cd, pc, info, SLOTS_P0, insn);
1393 insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4;
1394 insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4;
1395 insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4;
1396 insn[3^e] = buf[7^e] << 4;
1397 (*info->fprintf_func) (info->stream, " + ");
1398 print_slot_insn (cd, pc, info, SLOTS_P1, insn);
1402 /* <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */
1403 /* V2 [-------------core-------------]xxxx[------------p1------------] */
1404 print_insn (cd, pc, info, buf, 4);
1406 insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4;
1407 insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4;
1408 insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4;
1409 insn[3^e] = buf[7^e] << 4;
1410 (*info->fprintf_func) (info->stream, " + ");
1411 print_slot_insn (cd, pc, info, SLOTS_P1, insn);
1417 #endif /* MEP_IVC2_SUPPORTED */
1419 /* This is a hack. SID calls this to update the disassembler as the
1420 CPU changes modes. */
1421 static int mep_ivc2_disassemble_p = 0;
1422 static int mep_ivc2_vliw_disassemble_p = 0;
1425 mep_print_insn_set_ivc2_mode (int ivc2_p, int vliw_p, int cfg_idx);
1427 mep_print_insn_set_ivc2_mode (int ivc2_p, int vliw_p, int cfg_idx)
1429 mep_ivc2_disassemble_p = ivc2_p;
1430 mep_ivc2_vliw_disassemble_p = vliw_p;
1431 mep_config_index = cfg_idx;
1435 mep_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
1440 static CGEN_ATTR_VALUE_BITSET_TYPE *ivc2_core_isa = NULL;
1442 if (ivc2_core_isa == NULL)
1444 /* IVC2 has some core-only coprocessor instructions. We
1445 use COP32 to flag those, and COP64 for the VLIW ones,
1446 since they have the same names. */
1447 ivc2_core_isa = cgen_bitset_create (MAX_ISAS);
1450 /* Extract and adapt to configuration number, if available. */
1451 if (info->section && info->section->owner)
1453 bfd *abfd = info->section->owner;
1454 mep_config_index = abfd->tdata.elf_obj_data->elf_header->e_flags & EF_MEP_INDEX_MASK;
1455 /* This instantly redefines MEP_CONFIG, MEP_OMASK, .... MEP_VLIW64 */
1457 cop_type = abfd->tdata.elf_obj_data->elf_header->e_flags & EF_MEP_COP_MASK;
1458 if (cop_type == EF_MEP_COP_IVC2)
1462 /* Picking the right ISA bitmask for the current context is tricky. */
1465 if (info->section->flags & SEC_MEP_VLIW)
1467 #ifdef MEP_IVC2_SUPPORTED
1470 /* ivc2 has its own way of selecting its functions. */
1471 cd->isas = & MEP_CORE_ISA;
1472 status = mep_examine_ivc2_insns (cd, pc, info);
1476 /* Are we in 32 or 64 bit vliw mode? */
1478 status = mep_examine_vliw64_insns (cd, pc, info);
1480 status = mep_examine_vliw32_insns (cd, pc, info);
1481 /* Both the above branches set their own isa bitmasks. */
1487 cgen_bitset_clear (ivc2_core_isa);
1488 cgen_bitset_union (ivc2_core_isa, &MEP_CORE_ISA, ivc2_core_isa);
1489 cgen_bitset_union (ivc2_core_isa, &MEP_COP32_ISA, ivc2_core_isa);
1490 cd->isas = ivc2_core_isa;
1493 cd->isas = & MEP_CORE_ISA;
1494 status = default_print_insn (cd, pc, info);
1497 else /* sid or gdb */
1499 #ifdef MEP_IVC2_SUPPORTED
1500 if (mep_ivc2_disassemble_p)
1502 if (mep_ivc2_vliw_disassemble_p)
1504 cd->isas = & MEP_CORE_ISA;
1505 status = mep_examine_ivc2_insns (cd, pc, info);
1511 cd->isas = ivc2_core_isa;
1516 status = default_print_insn (cd, pc, info);
1524 #include "elf/mep.h"
1526 /* A mask for all ISAs executed by the core. */
1527 CGEN_ATTR_VALUE_BITSET_TYPE mep_all_core_isas_mask = {0, 0};
1530 init_mep_all_core_isas_mask (void)
1532 if (mep_all_core_isas_mask.length != 0)
1534 cgen_bitset_init (& mep_all_core_isas_mask, ISA_MAX);
1535 cgen_bitset_set (& mep_all_core_isas_mask, ISA_MEP);
1536 /* begin-all-core-isas */
1537 cgen_bitset_add (& mep_all_core_isas_mask, ISA_EXT_CORE1);
1538 /* end-all-core-isas */
1541 CGEN_ATTR_VALUE_BITSET_TYPE mep_all_cop_isas_mask = {0, 0};
1544 init_mep_all_cop_isas_mask (void)
1546 if (mep_all_cop_isas_mask.length != 0)
1548 cgen_bitset_init (& mep_all_cop_isas_mask, ISA_MAX);
1549 /* begin-all-cop-isas */
1550 cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_16);
1551 cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_32);
1552 cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_48);
1553 cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_64);
1554 /* end-all-cop-isas */
1558 mep_insn_supported_by_isa (const CGEN_INSN *insn, CGEN_ATTR_VALUE_BITSET_TYPE *isa_mask)
1560 CGEN_BITSET insn_isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA);
1561 return cgen_bitset_intersect_p (& insn_isas, isa_mask);
1564 #define OPTION_MASK \
1565 ( (1 << CGEN_INSN_OPTIONAL_BIT_INSN) \
1566 | (1 << CGEN_INSN_OPTIONAL_MUL_INSN) \
1567 | (1 << CGEN_INSN_OPTIONAL_DIV_INSN) \
1568 | (1 << CGEN_INSN_OPTIONAL_DEBUG_INSN) \
1569 | (1 << CGEN_INSN_OPTIONAL_LDZ_INSN) \
1570 | (1 << CGEN_INSN_OPTIONAL_ABS_INSN) \
1571 | (1 << CGEN_INSN_OPTIONAL_AVE_INSN) \
1572 | (1 << CGEN_INSN_OPTIONAL_MINMAX_INSN) \
1573 | (1 << CGEN_INSN_OPTIONAL_CLIP_INSN) \
1574 | (1 << CGEN_INSN_OPTIONAL_SAT_INSN) \
1575 | (1 << CGEN_INSN_OPTIONAL_UCI_INSN) \
1576 | (1 << CGEN_INSN_OPTIONAL_DSP_INSN) \
1577 | (1 << CGEN_INSN_OPTIONAL_CP_INSN) \
1578 | (1 << CGEN_INSN_OPTIONAL_CP64_INSN) )
1581 mep_config_map_struct mep_config_map[] =
1583 /* config-map-start */
1584 /* Default entry: first module, with all options enabled. */
1585 { "", 0, EF_MEP_COP_IVC2 | EF_MEP_CPU_C5,0, 64, { 1, "\x20" }, { 1, "\x10" }, { 1, "\x8" }, { 1, "\x4" }, { 1, "\x3c" }, { 1, "\xc0" }, OPTION_MASK | (1 << CGEN_INSN_OPTIONAL_DSP_INSN) | (1 << CGEN_INSN_OPTIONAL_UCI_INSN) },
1586 { "default", CONFIG_DEFAULT, EF_MEP_COP_IVC2 | EF_MEP_CPU_C5, 0, 64, { 1, "\x20" }, { 1, "\x10" }, { 1, "\x8" }, { 1, "\x4" }, { 1, "\x3c" }, { 1, "\xc0" },
1588 | (1 << CGEN_INSN_OPTIONAL_CP_INSN)
1589 | (1 << CGEN_INSN_OPTIONAL_CP64_INSN)
1590 | (1 << CGEN_INSN_OPTIONAL_MUL_INSN)
1591 | (1 << CGEN_INSN_OPTIONAL_DIV_INSN)
1592 | (1 << CGEN_INSN_OPTIONAL_BIT_INSN)
1593 | (1 << CGEN_INSN_OPTIONAL_LDZ_INSN)
1594 | (1 << CGEN_INSN_OPTIONAL_ABS_INSN)
1595 | (1 << CGEN_INSN_OPTIONAL_AVE_INSN)
1596 | (1 << CGEN_INSN_OPTIONAL_MINMAX_INSN)
1597 | (1 << CGEN_INSN_OPTIONAL_CLIP_INSN)
1598 | (1 << CGEN_INSN_OPTIONAL_SAT_INSN) },
1599 /* config-map-end */
1600 { 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, 0 }
1603 int mep_config_index = 0;
1606 check_configured_mach (int machs)
1608 /* All base insns are supported. */
1609 int mach = 1 << MACH_BASE;
1610 switch (MEP_CPU & EF_MEP_CPU_MASK)
1614 mach |= (1 << MACH_MEP);
1617 mach |= (1 << MACH_H1);
1620 mach |= (1 << MACH_MEP);
1621 mach |= (1 << MACH_C5);
1626 return machs & mach;
1630 mep_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
1632 int iconfig = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG);
1633 int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
1634 CGEN_BITSET isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA);
1639 /* If the insn has an option bit set that we don't want,
1641 if (CGEN_INSN_ATTRS (insn)->bool_ & OPTION_MASK & ~MEP_OMASK)
1644 /* If attributes are absent, assume no restriction. */
1648 ok1 = ((machs & cd->machs) && cgen_bitset_intersect_p (& isas, cd->isas));
1649 /* If the insn is config-specific, make sure it matches. */
1650 ok2 = (iconfig == 0 || iconfig == MEP_CONFIG);
1651 /* Make sure the insn is supported by the configured mach */
1652 ok3 = check_configured_mach (machs);
1654 return (ok1 && ok2 && ok3);
1658 mep_cgen_insn_supported_asm (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
1660 #ifdef MEP_IVC2_SUPPORTED
1661 /* If we're assembling VLIW packets, ignore the 12-bit BSR as we
1662 can't relax that. The 24-bit BSR is matched instead. */
1663 if (insn->base->num == MEP_INSN_BSR12
1664 && cgen_bitset_contains (cd->isas, ISA_EXT_COP1_64))
1668 return mep_cgen_insn_supported (cd, insn);