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 /* xgettext:no-c-format */
353 return _("invalid %function() here");
355 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
359 parse_unsigned16 (CGEN_CPU_DESC cd,
362 unsigned long *valuep)
364 return parse_lo16 (cd, strp, opindex, (long *) valuep, 0);
368 parse_signed16_range (CGEN_CPU_DESC cd,
373 const char *errmsg = 0;
376 errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
380 if (value < -32768 || value > 32767)
381 return _("Immediate is out of range -32768 to 32767");
388 parse_unsigned16_range (CGEN_CPU_DESC cd,
391 unsigned long *valuep)
393 const char *errmsg = 0;
396 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
401 return _("Immediate is out of range 0 to 65535");
407 /* A special case of parse_signed16 which accepts only the value zero. */
410 parse_zero (CGEN_CPU_DESC cd, const char **strp, int opindex, long *valuep)
413 enum cgen_parse_operand_result result_type;
416 /*fprintf(stderr, "dj: signed parse opindex `%s'\n", *strp);*/
418 /* Prevent ($ry) from being attempted as an expression on 'sw $rx,($ry)'.
419 It will fail and cause ry to be listed as an undefined symbol in the
421 if (strncmp (*strp, "($", 2) == 0)
422 return "not zero"; /* any string will do -- will never be seen. */
424 if (strncasecmp (*strp, "%lo(", 4) == 0)
427 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_LOW16,
428 &result_type, &value);
430 return "missing `)'";
433 && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
434 return "not zero"; /* any string will do -- will never be seen. */
439 if (strncasecmp (*strp, "%hi(", 4) == 0)
442 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16S,
443 &result_type, &value);
445 return "missing `)'";
448 && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
449 return "not zero"; /* any string will do -- will never be seen. */
454 if (strncasecmp (*strp, "%uhi(", 5) == 0)
457 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16U,
458 &result_type, &value);
460 return "missing `)'";
463 && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
464 return "not zero"; /* any string will do -- will never be seen. */
469 if (strncasecmp (*strp, "%sdaoff(", 8) == 0)
472 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_GPREL,
473 &result_type, &value);
475 return "missing `)'";
478 && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
479 return "not zero"; /* any string will do -- will never be seen. */
484 if (strncasecmp (*strp, "%tpoff(", 7) == 0)
487 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_TPREL,
488 &result_type, &value);
490 return "missing `)'";
493 && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
494 return "not zero"; /* any string will do -- will never be seen. */
500 return "invalid %function() here";
502 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_NONE,
503 &result_type, &value);
505 && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
506 return "not zero"; /* any string will do -- will never be seen. */
512 parse_unsigned7 (CGEN_CPU_DESC cd, const char **strp,
513 enum cgen_operand_type opindex, unsigned long *valuep)
518 /* fprintf(stderr, "dj: unsigned7 parse `%s'\n", *strp); */
520 if (strncasecmp (*strp, "%tpoff(", 7) == 0)
526 case MEP_OPERAND_UDISP7:
527 reloc = BFD_RELOC_MEP_TPREL7;
529 case MEP_OPERAND_UDISP7A2:
530 reloc = BFD_RELOC_MEP_TPREL7A2;
532 case MEP_OPERAND_UDISP7A4:
533 reloc = BFD_RELOC_MEP_TPREL7A4;
536 /* Safe assumption? */
539 errmsg = cgen_parse_address (cd, strp, opindex, reloc,
542 return "missing `)'";
549 /* xgettext:no-c-format */
550 return _("invalid %function() here");
552 return parse_mep_alignu (cd, strp, opindex, valuep);
555 static ATTRIBUTE_UNUSED const char *
556 parse_cdisp10 (CGEN_CPU_DESC cd,
561 const char *errmsg = 0;
569 case MEP_OPERAND_CDISP10A4:
572 case MEP_OPERAND_CDISP10A2:
575 case MEP_OPERAND_CDISP10:
581 if ((MEP_CPU & EF_MEP_CPU_MASK) == EF_MEP_CPU_C5)
584 if (strncmp (*strp, "0x0", 3) == 0
585 || (**strp == '0' && *(*strp + 1) != 'x'))
588 errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
594 if (value < -512 || value > 511)
595 return _("Immediate is out of range -512 to 511");
599 if (value < -128 || value > 127)
600 return _("Immediate is out of range -128 to 127");
603 if (value & ((1<<alignment)-1))
604 return _("Value is not aligned enough");
606 /* If this field may require a relocation then use larger dsp16. */
607 if (! have_zero && value == 0)
608 return (wide ? _("Immediate is out of range -512 to 511")
609 : _("Immediate is out of range -128 to 127"));
615 /* BEGIN LIGHTWEIGHT MACRO PROCESSOR. */
631 static macro const macros[] =
633 { "sizeof", "(`1.end + (- `1))"},
634 { "startof", "(`1 | 0)" },
635 { "align4", "(`1&(~3))"},
636 /*{ "hi", "(((`1+0x8000)>>16) & 0xffff)" }, */
637 /*{ "lo", "(`1 & 0xffff)" }, */
638 /*{ "sdaoff", "((`1-__sdabase) & 0x7f)"}, */
639 /*{ "tpoff", "((`1-__tpbase) & 0x7f)"}, */
643 static char * expand_string (const char *, int);
646 mep_cgen_expand_macros_and_parse_operand
647 (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
650 str_append (char *dest, const char *input, int len)
657 /* printf("str_append: <<%s>>, <<%s>>, %d\n", dest, input, len); */
658 oldlen = (dest ? strlen(dest) : 0);
659 new_dest = realloc (dest, oldlen + len + 1);
660 memset (new_dest + oldlen, 0, len + 1);
661 return strncat (new_dest, input, len);
665 lookup_macro (const char *name)
669 for (m = macros; m->name; ++m)
670 if (strncmp (m->name, name, strlen(m->name)) == 0)
677 expand_macro (arg *args, int narg, const macro *mac)
679 char *result = 0, *rescanned_result = 0;
680 char *e = mac->expansion;
684 /* printf("expanding macro %s with %d args\n", mac->name, narg + 1); */
689 && ((*(e + 1) - '1') <= MAXARGS)
690 && ((*(e + 1) - '1') <= narg))
692 result = str_append (result, mark, e - mark);
693 mac_arg = (*(e + 1) - '1');
694 /* printf("replacing `%d with %s\n", mac_arg+1, args[mac_arg].start); */
695 result = str_append (result, args[mac_arg].start, args[mac_arg].len);
703 result = str_append (result, mark, e - mark);
707 rescanned_result = expand_string (result, 0);
709 return rescanned_result;
719 expand_string (const char *in, int first_only)
721 int num_expansions = 0;
726 const char *mark = in;
727 const macro *pmacro = NULL;
736 if (*in == '%' && *(in + 1) && (!first_only || num_expansions == 0))
738 pmacro = lookup_macro (in + 1);
741 /* printf("entering state %d at '%s'...\n", state, in); */
742 result = str_append (result, mark, in - mark);
744 in += 1 + strlen (pmacro->name);
745 while (*in == ' ') ++in;
755 args[narg].start = in + 1;
769 args[narg].start = (in + 1);
774 /* printf("entering state %d at '%s'...\n", state, in); */
778 expansion = expand_macro (args, narg, pmacro);
782 result = str_append (result, expansion, strlen (expansion));
788 result = str_append (result, mark, in - mark);
813 result = str_append (result, mark, in - mark);
823 /* END LIGHTWEIGHT MACRO PROCESSOR. */
825 const char * mep_cgen_parse_operand
826 (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
829 mep_cgen_expand_macros_and_parse_operand (CGEN_CPU_DESC cd, int opindex,
830 const char ** strp_in, CGEN_FIELDS * fields)
832 const char * errmsg = NULL;
833 char *str = 0, *hold = 0;
834 const char **strp = 0;
836 /* Set up a new pointer to macro-expanded string. */
837 str = expand_string (*strp_in, 1);
838 /* fprintf (stderr, " expanded <<%s>> to <<%s>>\n", *strp_in, str); */
841 strp = (const char **)(&str);
843 errmsg = mep_cgen_parse_operand (cd, opindex, strp, fields);
845 /* Now work out the advance. */
846 if (strlen (str) == 0)
847 *strp_in += strlen (*strp_in);
851 if (strstr (*strp_in, str))
852 /* A macro-expansion was pulled off the front. */
853 *strp_in = strstr (*strp_in, str);
855 /* A non-macro-expansion was pulled off the front. */
856 *strp_in += (str - hold);
864 #define CGEN_ASM_INIT_HOOK (cd->parse_operand = mep_cgen_expand_macros_and_parse_operand);
871 #define CGEN_VALIDATE_INSN_SUPPORTED
874 print_tpreg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, void *dis_info,
875 CGEN_KEYWORD *table ATTRIBUTE_UNUSED, long val ATTRIBUTE_UNUSED,
876 unsigned int flags ATTRIBUTE_UNUSED)
878 disassemble_info *info = (disassemble_info *) dis_info;
880 (*info->fprintf_func) (info->stream, "$tp");
884 print_spreg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, void *dis_info,
885 CGEN_KEYWORD *table ATTRIBUTE_UNUSED, long val ATTRIBUTE_UNUSED,
886 unsigned int flags ATTRIBUTE_UNUSED)
888 disassemble_info *info = (disassemble_info *) dis_info;
890 (*info->fprintf_func) (info->stream, "$sp");
893 /* begin-cop-ip-print-handlers */
895 print_ivc2_cr (CGEN_CPU_DESC,
899 unsigned int) ATTRIBUTE_UNUSED;
901 print_ivc2_cr (CGEN_CPU_DESC cd,
903 CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED,
907 print_keyword (cd, dis_info, & mep_cgen_opval_h_cr_ivc2, value, attrs);
910 print_ivc2_ccr (CGEN_CPU_DESC,
914 unsigned int) ATTRIBUTE_UNUSED;
916 print_ivc2_ccr (CGEN_CPU_DESC cd,
918 CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED,
922 print_keyword (cd, dis_info, & mep_cgen_opval_h_ccr_ivc2, value, attrs);
924 /* end-cop-ip-print-handlers */
926 /************************************************************\
927 *********************** Experimental *************************
928 \************************************************************/
930 #undef CGEN_PRINT_INSN
931 #define CGEN_PRINT_INSN mep_print_insn
934 mep_print_vliw_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info,
935 bfd_byte *buf, int corelength, int copro1length,
936 int copro2length ATTRIBUTE_UNUSED)
940 /* char insnbuf[CGEN_MAX_INSN_SIZE]; */
941 bfd_byte insnbuf[64];
943 /* If corelength > 0 then there is a core insn present. It
944 will be at the beginning of the buffer. After printing
945 the core insn, we need to print the + on the next line. */
950 for (i = 0; i < corelength; i++ )
952 cd->isas = & MEP_CORE_ISA;
954 my_status = print_insn (cd, pc, info, insnbuf, corelength);
955 if (my_status != corelength)
957 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
958 my_status = corelength;
962 /* Print the + to indicate that the following copro insn is
963 part of a vliw group. */
964 if (copro1length > 0)
965 (*info->fprintf_func) (info->stream, " + ");
968 /* Now all that is left to be processed is the coprocessor insns
969 In vliw mode, there will always be one. Its positioning will
970 be from byte corelength to byte corelength+copro1length -1.
971 No need to check for existence. Also, the first vliw insn,
972 will, as spec'd, always be at least as long as the core insn
973 so we don't need to flush the buffer. */
974 if (copro1length > 0)
978 for (i = corelength; i < corelength + copro1length; i++ )
979 insnbuf[i - corelength] = buf[i];
981 switch (copro1length)
986 cd->isas = & MEP_COP16_ISA;
989 cd->isas = & MEP_COP32_ISA;
992 cd->isas = & MEP_COP48_ISA;
995 cd->isas = & MEP_COP64_ISA;
998 /* Shouldn't be anything but 16,32,48,64. */
1002 my_status = print_insn (cd, pc, info, insnbuf, copro1length);
1004 if (my_status != copro1length)
1006 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
1007 my_status = copro1length;
1009 status += my_status;
1013 /* Now we need to process the second copro insn if it exists. We
1014 have no guarantee that the second copro insn will be longer
1015 than the first, so we have to flush the buffer if we are have
1016 a second copro insn to process. If present, this insn will
1017 be in the position from byte corelength+copro1length to byte
1018 corelength+copro1length+copro2length-1 (which better equal 8
1019 or else we're in big trouble. */
1020 if (copro2length > 0)
1024 for (i = 0; i < 64 ; i++)
1027 for (i = corelength + copro1length; i < 64; i++)
1028 insnbuf[i - (corelength + copro1length)] = buf[i];
1030 switch (copro2length)
1033 cd->isas = 1 << ISA_EXT_COP1_16;
1036 cd->isas = 1 << ISA_EXT_COP1_32;
1039 cd->isas = 1 << ISA_EXT_COP1_48;
1042 cd->isas = 1 << ISA_EXT_COP1_64;
1045 /* Shouldn't be anything but 16,32,48,64. */
1049 my_status = print_insn (cd, pc, info, insnbuf, copro2length);
1051 if (my_status != copro2length)
1053 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
1054 my_status = copro2length;
1057 status += my_status;
1061 /* Status should now be the number of bytes that were printed
1062 which should be 4 for VLIW32 mode and 64 for VLIW64 mode. */
1064 if ((!MEP_VLIW64 && (status != 4)) || (MEP_VLIW64 && (status != 8)))
1070 /* The two functions mep_examine_vliw[32,64]_insns are used find out
1071 which vliw combinaion (16 bit core with 48 bit copro, 32 bit core
1072 with 32 bit copro, etc.) is present. Later on, when internally
1073 parallel coprocessors are handled, only these functions should
1076 At this time only the following combinations are supported:
1079 16 bit core insn (core) and 16 bit coprocessor insn (cop1)
1080 32 bit core insn (core)
1081 32 bit coprocessor insn (cop1)
1082 Note: As of this time, I do not believe we have enough information
1083 to distinguish a 32 bit core insn from a 32 bit cop insn. Also,
1084 no 16 bit coprocessor insns have been specified.
1087 16 bit core insn (core) and 48 bit coprocessor insn (cop1)
1088 32 bit core insn (core) and 32 bit coprocessor insn (cop1)
1089 64 bit coprocessor insn (cop1)
1091 The framework for an internally parallel coprocessor is also
1092 present (2nd coprocessor insn is cop2), but at this time it
1093 is not used. This only appears to be valid in VLIW64 mode. */
1096 mep_examine_vliw32_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
1103 bfd_byte buf[CGEN_MAX_INSN_SIZE];
1104 char indicator16[1];
1105 char indicatorcop32[2];
1107 /* At this time we're not supporting internally parallel coprocessors,
1108 so cop2buflength will always be 0. */
1111 /* Read in 32 bits. */
1112 buflength = 4; /* VLIW insn spans 4 bytes. */
1113 status = (*info->read_memory_func) (pc, buf, buflength, info);
1117 (*info->memory_error_func) (status, pc, info);
1121 /* Put the big endian representation of the bytes to be examined
1122 in the temporary buffers for examination. */
1124 if (info->endian == BFD_ENDIAN_BIG)
1126 indicator16[0] = buf[0];
1127 indicatorcop32[0] = buf[0];
1128 indicatorcop32[1] = buf[1];
1132 indicator16[0] = buf[1];
1133 indicatorcop32[0] = buf[1];
1134 indicatorcop32[1] = buf[0];
1137 /* If the two high order bits are 00, 01 or 10, we have a 16 bit
1138 core insn and a 48 bit copro insn. */
1140 if ((indicator16[0] & 0x80) && (indicator16[0] & 0x40))
1142 if ((indicatorcop32[0] & 0xf0) == 0xf0 && (indicatorcop32[1] & 0x07) == 0x07)
1144 /* We have a 32 bit copro insn. */
1146 /* All 4 4ytes are one copro insn. */
1151 /* We have a 32 bit core. */
1158 /* We have a 16 bit core insn and a 16 bit copro insn. */
1163 /* Now we have the distrubution set. Print them out. */
1164 status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength,
1165 cop1buflength, cop2buflength);
1171 mep_examine_vliw64_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
1178 bfd_byte buf[CGEN_MAX_INSN_SIZE];
1179 char indicator16[1];
1180 char indicator64[4];
1182 /* At this time we're not supporting internally parallel
1183 coprocessors, so cop2buflength will always be 0. */
1186 /* Read in 64 bits. */
1187 buflength = 8; /* VLIW insn spans 8 bytes. */
1188 status = (*info->read_memory_func) (pc, buf, buflength, info);
1192 (*info->memory_error_func) (status, pc, info);
1196 /* We have all 64 bits in the buffer now. We have to figure out
1197 what combination of instruction sizes are present. The two
1198 high order bits will indicate whether or not we have a 16 bit
1199 core insn or not. If not, then we have to look at the 7,8th
1200 bytes to tell whether we have 64 bit copro insn or a 32 bit
1201 core insn with a 32 bit copro insn. Endianness will make a
1204 /* Put the big endian representation of the bytes to be examined
1205 in the temporary buffers for examination. */
1207 /* indicator16[0] = buf[0]; */
1208 if (info->endian == BFD_ENDIAN_BIG)
1210 indicator16[0] = buf[0];
1211 indicator64[0] = buf[0];
1212 indicator64[1] = buf[1];
1213 indicator64[2] = buf[2];
1214 indicator64[3] = buf[3];
1218 indicator16[0] = buf[1];
1219 indicator64[0] = buf[1];
1220 indicator64[1] = buf[0];
1221 indicator64[2] = buf[3];
1222 indicator64[3] = buf[2];
1225 /* If the two high order bits are 00, 01 or 10, we have a 16 bit
1226 core insn and a 48 bit copro insn. */
1228 if ((indicator16[0] & 0x80) && (indicator16[0] & 0x40))
1230 if ((indicator64[0] & 0xf0) == 0xf0 && (indicator64[1] & 0x07) == 0x07
1231 && ((indicator64[2] & 0xfe) != 0xf0 || (indicator64[3] & 0xf4) != 0))
1233 /* We have a 64 bit copro insn. */
1235 /* All 8 bytes are one copro insn. */
1240 /* We have a 32 bit core insn and a 32 bit copro insn. */
1247 /* We have a 16 bit core insn and a 48 bit copro insn. */
1252 /* Now we have the distrubution set. Print them out. */
1253 status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength,
1254 cop1buflength, cop2buflength);
1259 #ifdef MEP_IVC2_SUPPORTED
1262 print_slot_insn (CGEN_CPU_DESC cd,
1264 disassemble_info *info,
1268 const CGEN_INSN_LIST *insn_list;
1269 CGEN_INSN_INT insn_value;
1270 CGEN_EXTRACT_INFO ex_info;
1272 insn_value = cgen_get_insn_value (cd, buf, 32, cd->insn_endian);
1274 /* Fill in ex_info fields like read_insn would. Don't actually call
1275 read_insn, since the incoming buffer is already read (and possibly
1276 modified a la m32r). */
1277 ex_info.valid = (1 << 8) - 1;
1278 ex_info.dis_info = info;
1279 ex_info.insn_bytes = buf;
1281 /* The instructions are stored in hash lists.
1282 Pick the first one and keep trying until we find the right one. */
1284 insn_list = CGEN_DIS_LOOKUP_INSN (cd, (char *) buf, insn_value);
1285 while (insn_list != NULL)
1287 const CGEN_INSN *insn = insn_list->insn;
1291 if ((CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG)
1292 && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG) != MEP_CONFIG)
1293 || ! (CGEN_ATTR_CGEN_INSN_SLOTS_VALUE (CGEN_INSN_ATTRS (insn)) & (1 << slot)))
1295 insn_list = CGEN_DIS_NEXT_INSN (insn_list);
1299 if ((insn_value & CGEN_INSN_BASE_MASK (insn))
1300 == CGEN_INSN_BASE_VALUE (insn))
1302 /* Printing is handled in two passes. The first pass parses the
1303 machine insn and extracts the fields. The second pass prints
1306 length = CGEN_EXTRACT_FN (cd, insn)
1307 (cd, insn, &ex_info, insn_value, &fields, pc);
1309 /* Length < 0 -> error. */
1314 CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
1315 /* Length is in bits, result is in bytes. */
1320 insn_list = CGEN_DIS_NEXT_INSN (insn_list);
1323 if (slot == SLOTS_P0S)
1324 (*info->fprintf_func) (info->stream, "*unknown-p0s*");
1325 else if (slot == SLOTS_P0)
1326 (*info->fprintf_func) (info->stream, "*unknown-p0*");
1327 else if (slot == SLOTS_P1)
1328 (*info->fprintf_func) (info->stream, "*unknown-p1*");
1329 else if (slot == SLOTS_C3)
1330 (*info->fprintf_func) (info->stream, "*unknown-c3*");
1335 mep_examine_ivc2_insns (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, bfd_vma pc ATTRIBUTE_UNUSED, disassemble_info *info ATTRIBUTE_UNUSED)
1343 /* Read in 64 bits. */
1344 buflength = 8; /* VLIW insn spans 8 bytes. */
1345 status = (*info->read_memory_func) (pc, buf, buflength, info);
1349 (*info->memory_error_func) (status, pc, info);
1353 if (info->endian == BFD_ENDIAN_LITTLE)
1358 if (((unsigned char)buf[0^e] & 0xf0) < 0xc0)
1360 /* <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */
1361 /* V1 [-----core-----][--------p0s-------][------------p1------------] */
1363 print_insn (cd, pc, info, buf, 2);
1366 insn[1^e] = buf[2^e];
1367 insn[2^e] = buf[3^e];
1368 insn[3^e] = buf[4^e] & 0xf0;
1369 (*info->fprintf_func) (info->stream, " + ");
1370 print_slot_insn (cd, pc, info, SLOTS_P0S, insn);
1372 insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4;
1373 insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4;
1374 insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4;
1375 insn[3^e] = buf[7^e] << 4;
1376 (*info->fprintf_func) (info->stream, " + ");
1377 print_slot_insn (cd, pc, info, SLOTS_P1, insn);
1379 else if ((buf[0^e] & 0xf0) == 0xf0 && (buf[1^e] & 0x0f) == 0x07)
1381 /* <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */
1382 /* V3 1111[--p0--]0111[--------p0--------][------------p1------------] */
1383 /* 00000000111111112222222233333333 */
1385 insn[0^e] = buf[0^e] << 4 | buf[1^e] >> 4;
1386 insn[1^e] = buf[2^e];
1387 insn[2^e] = buf[3^e];
1388 insn[3^e] = buf[4^e] & 0xf0;
1389 print_slot_insn (cd, pc, info, SLOTS_P0, insn);
1391 insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4;
1392 insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4;
1393 insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4;
1394 insn[3^e] = buf[7^e] << 4;
1395 (*info->fprintf_func) (info->stream, " + ");
1396 print_slot_insn (cd, pc, info, SLOTS_P1, insn);
1400 /* <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */
1401 /* V2 [-------------core-------------]xxxx[------------p1------------] */
1402 print_insn (cd, pc, info, buf, 4);
1404 insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4;
1405 insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4;
1406 insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4;
1407 insn[3^e] = buf[7^e] << 4;
1408 (*info->fprintf_func) (info->stream, " + ");
1409 print_slot_insn (cd, pc, info, SLOTS_P1, insn);
1415 #endif /* MEP_IVC2_SUPPORTED */
1417 /* This is a hack. SID calls this to update the disassembler as the
1418 CPU changes modes. */
1419 static int mep_ivc2_disassemble_p = 0;
1420 static int mep_ivc2_vliw_disassemble_p = 0;
1423 mep_print_insn_set_ivc2_mode (int ivc2_p, int vliw_p, int cfg_idx);
1425 mep_print_insn_set_ivc2_mode (int ivc2_p, int vliw_p, int cfg_idx)
1427 mep_ivc2_disassemble_p = ivc2_p;
1428 mep_ivc2_vliw_disassemble_p = vliw_p;
1429 mep_config_index = cfg_idx;
1433 mep_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
1438 static CGEN_ATTR_VALUE_BITSET_TYPE *ivc2_core_isa = NULL;
1440 if (ivc2_core_isa == NULL)
1442 /* IVC2 has some core-only coprocessor instructions. We
1443 use COP32 to flag those, and COP64 for the VLIW ones,
1444 since they have the same names. */
1445 ivc2_core_isa = cgen_bitset_create (MAX_ISAS);
1448 /* Extract and adapt to configuration number, if available. */
1449 if (info->section && info->section->owner)
1451 bfd *abfd = info->section->owner;
1452 if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
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 /* mep_config_map is a variable sized array, so we do not know how big it is.
1458 The only safe way to check the index therefore is to iterate over the array.
1459 We do know that the last entry is all null. */
1461 for (i = 0; i <= mep_config_index; i++)
1462 if (mep_config_map[i].name == NULL)
1465 if (i < mep_config_index)
1467 opcodes_error_handler (_("illegal MEP INDEX setting '%x' in ELF header e_flags field"), mep_config_index);
1468 mep_config_index = 0;
1471 cop_type = abfd->tdata.elf_obj_data->elf_header->e_flags & EF_MEP_COP_MASK;
1472 if (cop_type == EF_MEP_COP_IVC2)
1477 /* Picking the right ISA bitmask for the current context is tricky. */
1480 if (info->section->flags & SEC_MEP_VLIW)
1482 #ifdef MEP_IVC2_SUPPORTED
1485 /* ivc2 has its own way of selecting its functions. */
1486 cd->isas = & MEP_CORE_ISA;
1487 status = mep_examine_ivc2_insns (cd, pc, info);
1491 /* Are we in 32 or 64 bit vliw mode? */
1493 status = mep_examine_vliw64_insns (cd, pc, info);
1495 status = mep_examine_vliw32_insns (cd, pc, info);
1496 /* Both the above branches set their own isa bitmasks. */
1502 cgen_bitset_clear (ivc2_core_isa);
1503 cgen_bitset_union (ivc2_core_isa, &MEP_CORE_ISA, ivc2_core_isa);
1504 cgen_bitset_union (ivc2_core_isa, &MEP_COP32_ISA, ivc2_core_isa);
1505 cd->isas = ivc2_core_isa;
1508 cd->isas = & MEP_CORE_ISA;
1509 status = default_print_insn (cd, pc, info);
1512 else /* sid or gdb */
1514 #ifdef MEP_IVC2_SUPPORTED
1515 if (mep_ivc2_disassemble_p)
1517 if (mep_ivc2_vliw_disassemble_p)
1519 cd->isas = & MEP_CORE_ISA;
1520 status = mep_examine_ivc2_insns (cd, pc, info);
1526 cd->isas = ivc2_core_isa;
1531 status = default_print_insn (cd, pc, info);
1539 #include "elf/mep.h"
1541 /* A mask for all ISAs executed by the core. */
1542 CGEN_ATTR_VALUE_BITSET_TYPE mep_all_core_isas_mask = {0, 0};
1545 init_mep_all_core_isas_mask (void)
1547 if (mep_all_core_isas_mask.length != 0)
1549 cgen_bitset_init (& mep_all_core_isas_mask, ISA_MAX);
1550 cgen_bitset_set (& mep_all_core_isas_mask, ISA_MEP);
1551 /* begin-all-core-isas */
1552 cgen_bitset_add (& mep_all_core_isas_mask, ISA_EXT_CORE1);
1553 /* end-all-core-isas */
1556 CGEN_ATTR_VALUE_BITSET_TYPE mep_all_cop_isas_mask = {0, 0};
1559 init_mep_all_cop_isas_mask (void)
1561 if (mep_all_cop_isas_mask.length != 0)
1563 cgen_bitset_init (& mep_all_cop_isas_mask, ISA_MAX);
1564 /* begin-all-cop-isas */
1565 cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_16);
1566 cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_32);
1567 cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_48);
1568 cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_64);
1569 /* end-all-cop-isas */
1573 mep_insn_supported_by_isa (const CGEN_INSN *insn, CGEN_ATTR_VALUE_BITSET_TYPE *isa_mask)
1575 CGEN_BITSET insn_isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA);
1576 return cgen_bitset_intersect_p (& insn_isas, isa_mask);
1579 #define OPTION_MASK \
1580 ( (1 << CGEN_INSN_OPTIONAL_BIT_INSN) \
1581 | (1 << CGEN_INSN_OPTIONAL_MUL_INSN) \
1582 | (1 << CGEN_INSN_OPTIONAL_DIV_INSN) \
1583 | (1 << CGEN_INSN_OPTIONAL_DEBUG_INSN) \
1584 | (1 << CGEN_INSN_OPTIONAL_LDZ_INSN) \
1585 | (1 << CGEN_INSN_OPTIONAL_ABS_INSN) \
1586 | (1 << CGEN_INSN_OPTIONAL_AVE_INSN) \
1587 | (1 << CGEN_INSN_OPTIONAL_MINMAX_INSN) \
1588 | (1 << CGEN_INSN_OPTIONAL_CLIP_INSN) \
1589 | (1 << CGEN_INSN_OPTIONAL_SAT_INSN) \
1590 | (1 << CGEN_INSN_OPTIONAL_UCI_INSN) \
1591 | (1 << CGEN_INSN_OPTIONAL_DSP_INSN) \
1592 | (1 << CGEN_INSN_OPTIONAL_CP_INSN) \
1593 | (1 << CGEN_INSN_OPTIONAL_CP64_INSN) )
1596 mep_config_map_struct mep_config_map[] =
1598 /* config-map-start */
1599 /* Default entry: first module, with all options enabled. */
1600 { "", 0, EF_MEP_COP_IVC2 | EF_MEP_CPU_C5,0, 64, { 1, "\x20" }, { 1, "\x10" }, { 1, "\x8" }, { 1, "\x4" }, { 1, "\x3c" }, { 1, "\xc0" }, OPTION_MASK | (1 << CGEN_INSN_OPTIONAL_DSP_INSN) | (1 << CGEN_INSN_OPTIONAL_UCI_INSN) },
1601 { "default", CONFIG_DEFAULT, EF_MEP_COP_IVC2 | EF_MEP_CPU_C5, 0, 64, { 1, "\x20" }, { 1, "\x10" }, { 1, "\x8" }, { 1, "\x4" }, { 1, "\x3c" }, { 1, "\xc0" },
1603 | (1 << CGEN_INSN_OPTIONAL_CP_INSN)
1604 | (1 << CGEN_INSN_OPTIONAL_CP64_INSN)
1605 | (1 << CGEN_INSN_OPTIONAL_MUL_INSN)
1606 | (1 << CGEN_INSN_OPTIONAL_DIV_INSN)
1607 | (1 << CGEN_INSN_OPTIONAL_BIT_INSN)
1608 | (1 << CGEN_INSN_OPTIONAL_LDZ_INSN)
1609 | (1 << CGEN_INSN_OPTIONAL_ABS_INSN)
1610 | (1 << CGEN_INSN_OPTIONAL_AVE_INSN)
1611 | (1 << CGEN_INSN_OPTIONAL_MINMAX_INSN)
1612 | (1 << CGEN_INSN_OPTIONAL_CLIP_INSN)
1613 | (1 << CGEN_INSN_OPTIONAL_SAT_INSN) },
1614 /* config-map-end */
1615 { 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, 0 }
1618 int mep_config_index = 0;
1621 check_configured_mach (int machs)
1623 /* All base insns are supported. */
1624 int mach = 1 << MACH_BASE;
1625 switch (MEP_CPU & EF_MEP_CPU_MASK)
1629 mach |= (1 << MACH_MEP);
1632 mach |= (1 << MACH_H1);
1635 mach |= (1 << MACH_MEP);
1636 mach |= (1 << MACH_C5);
1641 return machs & mach;
1645 mep_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
1647 int iconfig = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG);
1648 int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
1649 CGEN_BITSET isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA);
1654 /* If the insn has an option bit set that we don't want,
1656 if (CGEN_INSN_ATTRS (insn)->bool_ & OPTION_MASK & ~MEP_OMASK)
1659 /* If attributes are absent, assume no restriction. */
1663 ok1 = ((machs & cd->machs) && cgen_bitset_intersect_p (& isas, cd->isas));
1664 /* If the insn is config-specific, make sure it matches. */
1665 ok2 = (iconfig == 0 || iconfig == MEP_CONFIG);
1666 /* Make sure the insn is supported by the configured mach */
1667 ok3 = check_configured_mach (machs);
1669 return (ok1 && ok2 && ok3);
1673 mep_cgen_insn_supported_asm (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
1675 #ifdef MEP_IVC2_SUPPORTED
1676 /* If we're assembling VLIW packets, ignore the 12-bit BSR as we
1677 can't relax that. The 24-bit BSR is matched instead. */
1678 if (insn->base->num == MEP_INSN_BSR12
1679 && cgen_bitset_contains (cd->isas, ISA_EXT_COP1_64))
1683 return mep_cgen_insn_supported (cd, insn);