1 /* MeP opcode support. -*- C -*-
2 Copyright (C) 2001, 2002, 2003, 2004, 2005 Red Hat, Inc.
3 This file is part of CGEN.
4 This file is copyrighted with the GNU General Public License.
5 See file COPYING for details. */
9 #undef CGEN_DIS_HASH_SIZE
10 #define CGEN_DIS_HASH_SIZE 1
13 #define CGEN_DIS_HASH(buffer, insn) 0
15 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
24 CGEN_ATTR_VALUE_BITSET_TYPE cop16_isa;
25 CGEN_ATTR_VALUE_BITSET_TYPE cop32_isa;
26 CGEN_ATTR_VALUE_BITSET_TYPE cop48_isa;
27 CGEN_ATTR_VALUE_BITSET_TYPE cop64_isa;
28 CGEN_ATTR_VALUE_BITSET_TYPE cop_isa;
29 CGEN_ATTR_VALUE_BITSET_TYPE core_isa;
30 unsigned int option_mask;
31 } mep_config_map_struct;
33 extern mep_config_map_struct mep_config_map[];
34 extern int mep_config_index;
36 extern void init_mep_all_core_isas_mask (void);
37 extern void init_mep_all_cop_isas_mask (void);
38 extern CGEN_ATTR_VALUE_BITSET_TYPE mep_cop_isa (void);
40 #define MEP_CONFIG (mep_config_map[mep_config_index].config_enum)
41 #define MEP_CPU (mep_config_map[mep_config_index].cpu_flag)
42 #define MEP_OMASK (mep_config_map[mep_config_index].option_mask)
43 #define MEP_VLIW (mep_config_map[mep_config_index].vliw_bits > 0)
44 #define MEP_VLIW32 (mep_config_map[mep_config_index].vliw_bits == 32)
45 #define MEP_VLIW64 (mep_config_map[mep_config_index].vliw_bits == 64)
46 #define MEP_COP16_ISA (mep_config_map[mep_config_index].cop16_isa)
47 #define MEP_COP32_ISA (mep_config_map[mep_config_index].cop32_isa)
48 #define MEP_COP48_ISA (mep_config_map[mep_config_index].cop48_isa)
49 #define MEP_COP64_ISA (mep_config_map[mep_config_index].cop64_isa)
50 #define MEP_COP_ISA (mep_config_map[mep_config_index].cop_isa)
51 #define MEP_CORE_ISA (mep_config_map[mep_config_index].core_isa)
53 /* begin-cop-ip-supported-defines */
54 #define MEP_IVC2_SUPPORTED 1
55 /* end-cop-ip-supported-defines */
57 extern int mep_insn_supported_by_isa (const CGEN_INSN *, CGEN_ATTR_VALUE_BITSET_TYPE *);
59 /* A mask for all ISAs executed by the core. */
60 #define MEP_ALL_CORE_ISAS_MASK mep_all_core_isas_mask
61 extern CGEN_ATTR_VALUE_BITSET_TYPE mep_all_core_isas_mask;
63 #define MEP_INSN_CORE_P(insn) ( \
64 init_mep_all_core_isas_mask (), \
65 mep_insn_supported_by_isa (insn, & MEP_ALL_CORE_ISAS_MASK) \
68 /* A mask for all ISAs executed by a VLIW coprocessor. */
69 #define MEP_ALL_COP_ISAS_MASK mep_all_cop_isas_mask
70 extern CGEN_ATTR_VALUE_BITSET_TYPE mep_all_cop_isas_mask;
72 #define MEP_INSN_COP_P(insn) ( \
73 init_mep_all_cop_isas_mask (), \
74 mep_insn_supported_by_isa (insn, & MEP_ALL_COP_ISAS_MASK) \
77 extern int mep_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
78 extern int mep_cgen_insn_supported_asm (CGEN_CPU_DESC, const CGEN_INSN *);
84 #define CGEN_VALIDATE_INSN_SUPPORTED
85 #define mep_cgen_insn_supported mep_cgen_insn_supported_asm
87 const char * parse_csrn (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *);
88 const char * parse_tpreg (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *);
89 const char * parse_spreg (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *);
90 const char * parse_mep_align (CGEN_CPU_DESC, const char **, enum cgen_operand_type, long *);
91 const char * parse_mep_alignu (CGEN_CPU_DESC, const char **, enum cgen_operand_type, unsigned long *);
92 static const char * parse_signed16 (CGEN_CPU_DESC, const char **, int, long *);
93 static const char * parse_signed16_range (CGEN_CPU_DESC, const char **, int, long *) ATTRIBUTE_UNUSED;
94 static const char * parse_unsigned16 (CGEN_CPU_DESC, const char **, int, unsigned long *);
95 static const char * parse_unsigned16_range (CGEN_CPU_DESC, const char **, int, unsigned long *) ATTRIBUTE_UNUSED;
96 static const char * parse_lo16 (CGEN_CPU_DESC, const char **, int, long *, long);
97 static const char * parse_unsigned7 (CGEN_CPU_DESC, const char **, enum cgen_operand_type, unsigned long *);
98 static const char * parse_zero (CGEN_CPU_DESC, const char **, int, long *);
101 parse_csrn (CGEN_CPU_DESC cd, const char **strp,
102 CGEN_KEYWORD *keyword_table, long *field)
107 err = cgen_parse_keyword (cd, strp, keyword_table, field);
111 err = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_CSRN_IDX, & value);
118 /* begin-cop-ip-parse-handlers */
120 parse_ivc2_cr (CGEN_CPU_DESC,
123 long *) ATTRIBUTE_UNUSED;
125 parse_ivc2_cr (CGEN_CPU_DESC cd,
127 CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED,
130 return cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_cr_ivc2, field);
133 parse_ivc2_ccr (CGEN_CPU_DESC,
136 long *) ATTRIBUTE_UNUSED;
138 parse_ivc2_ccr (CGEN_CPU_DESC cd,
140 CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED,
143 return cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_ccr_ivc2, field);
145 /* end-cop-ip-parse-handlers */
148 parse_tpreg (CGEN_CPU_DESC cd, const char ** strp,
149 CGEN_KEYWORD *keyword_table, long *field)
153 err = cgen_parse_keyword (cd, strp, keyword_table, field);
157 return _("Only $tp or $13 allowed for this opcode");
162 parse_spreg (CGEN_CPU_DESC cd, const char ** strp,
163 CGEN_KEYWORD *keyword_table, long *field)
167 err = cgen_parse_keyword (cd, strp, keyword_table, field);
171 return _("Only $sp or $15 allowed for this opcode");
176 parse_mep_align (CGEN_CPU_DESC cd, const char ** strp,
177 enum cgen_operand_type type, long *field)
184 case MEP_OPERAND_PCREL8A2:
185 case MEP_OPERAND_PCREL12A2:
186 case MEP_OPERAND_PCREL17A2:
187 case MEP_OPERAND_PCREL24A2:
188 err = cgen_parse_signed_integer (cd, strp, type, field);
190 case MEP_OPERAND_PCABS24A2:
191 case MEP_OPERAND_UDISP7:
192 case MEP_OPERAND_UDISP7A2:
193 case MEP_OPERAND_UDISP7A4:
194 case MEP_OPERAND_UIMM7A4:
195 case MEP_OPERAND_ADDR24A4:
196 err = cgen_parse_unsigned_integer (cd, strp, type, (unsigned long *) field);
205 case MEP_OPERAND_UDISP7:
208 case MEP_OPERAND_PCREL8A2:
209 case MEP_OPERAND_PCREL12A2:
210 case MEP_OPERAND_PCREL17A2:
211 case MEP_OPERAND_PCREL24A2:
212 case MEP_OPERAND_PCABS24A2:
213 case MEP_OPERAND_UDISP7A2:
216 case MEP_OPERAND_UDISP7A4:
217 case MEP_OPERAND_UIMM7A4:
218 case MEP_OPERAND_ADDR24A4:
224 /* Safe assumption? */
228 return "Value is not aligned enough";
233 parse_mep_alignu (CGEN_CPU_DESC cd, const char ** strp,
234 enum cgen_operand_type type, unsigned long *field)
236 return parse_mep_align (cd, strp, type, (long *) field);
240 /* Handle %lo(), %tpoff(), %sdaoff(), %hi(), and other signed
241 constants in a signed context. */
244 parse_signed16 (CGEN_CPU_DESC cd,
249 return parse_lo16 (cd, strp, opindex, valuep, 1);
253 parse_lo16 (CGEN_CPU_DESC cd,
260 enum cgen_parse_operand_result result_type;
263 if (strncasecmp (*strp, "%lo(", 4) == 0)
266 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_LOW16,
267 & result_type, & value);
269 return _("missing `)'");
272 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
275 *valuep = (long)(short) value;
281 if (strncasecmp (*strp, "%hi(", 4) == 0)
284 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16S,
285 & result_type, & value);
287 return _("missing `)'");
290 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
291 value = (value + 0x8000) >> 16;
296 if (strncasecmp (*strp, "%uhi(", 5) == 0)
299 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16U,
300 & result_type, & value);
302 return _("missing `)'");
305 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
311 if (strncasecmp (*strp, "%sdaoff(", 8) == 0)
314 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_GPREL,
317 return _("missing `)'");
323 if (strncasecmp (*strp, "%tpoff(", 7) == 0)
326 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_TPREL,
329 return _("missing `)'");
336 return _("invalid %function() here");
338 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
342 parse_unsigned16 (CGEN_CPU_DESC cd,
345 unsigned long *valuep)
347 return parse_lo16 (cd, strp, opindex, (long *) valuep, 0);
351 parse_signed16_range (CGEN_CPU_DESC cd,
356 const char *errmsg = 0;
359 errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
363 if (value < -32768 || value > 32767)
364 return _("Immediate is out of range -32768 to 32767");
371 parse_unsigned16_range (CGEN_CPU_DESC cd,
374 unsigned long *valuep)
376 const char *errmsg = 0;
379 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
384 return _("Immediate is out of range 0 to 65535");
390 /* A special case of parse_signed16 which accepts only the value zero. */
393 parse_zero (CGEN_CPU_DESC cd, const char **strp, int opindex, long *valuep)
396 enum cgen_parse_operand_result result_type;
399 /*fprintf(stderr, "dj: signed parse opindex `%s'\n", *strp);*/
401 /* Prevent ($ry) from being attempted as an expression on 'sw $rx,($ry)'.
402 It will fail and cause ry to be listed as an undefined symbol in the
404 if (strncmp (*strp, "($", 2) == 0)
405 return "not zero"; /* any string will do -- will never be seen. */
407 if (strncasecmp (*strp, "%lo(", 4) == 0)
410 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_LOW16,
411 &result_type, &value);
413 return "missing `)'";
416 && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
417 return "not zero"; /* any string will do -- will never be seen. */
422 if (strncasecmp (*strp, "%hi(", 4) == 0)
425 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16S,
426 &result_type, &value);
428 return "missing `)'";
431 && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
432 return "not zero"; /* any string will do -- will never be seen. */
437 if (strncasecmp (*strp, "%uhi(", 5) == 0)
440 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16U,
441 &result_type, &value);
443 return "missing `)'";
446 && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
447 return "not zero"; /* any string will do -- will never be seen. */
452 if (strncasecmp (*strp, "%sdaoff(", 8) == 0)
455 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_GPREL,
456 &result_type, &value);
458 return "missing `)'";
461 && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
462 return "not zero"; /* any string will do -- will never be seen. */
467 if (strncasecmp (*strp, "%tpoff(", 7) == 0)
470 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_TPREL,
471 &result_type, &value);
473 return "missing `)'";
476 && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
477 return "not zero"; /* any string will do -- will never be seen. */
483 return "invalid %function() here";
485 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_NONE,
486 &result_type, &value);
488 && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
489 return "not zero"; /* any string will do -- will never be seen. */
495 parse_unsigned7 (CGEN_CPU_DESC cd, const char **strp,
496 enum cgen_operand_type opindex, unsigned long *valuep)
501 /* fprintf(stderr, "dj: unsigned7 parse `%s'\n", *strp); */
503 if (strncasecmp (*strp, "%tpoff(", 7) == 0)
509 case MEP_OPERAND_UDISP7:
510 reloc = BFD_RELOC_MEP_TPREL7;
512 case MEP_OPERAND_UDISP7A2:
513 reloc = BFD_RELOC_MEP_TPREL7A2;
515 case MEP_OPERAND_UDISP7A4:
516 reloc = BFD_RELOC_MEP_TPREL7A4;
519 /* Safe assumption? */
522 errmsg = cgen_parse_address (cd, strp, opindex, reloc,
525 return "missing `)'";
532 return _("invalid %function() here");
534 return parse_mep_alignu (cd, strp, opindex, valuep);
537 static ATTRIBUTE_UNUSED const char *
538 parse_cdisp10 (CGEN_CPU_DESC cd,
543 const char *errmsg = 0;
551 case MEP_OPERAND_CDISP10A4:
554 case MEP_OPERAND_CDISP10A2:
557 case MEP_OPERAND_CDISP10:
563 if ((MEP_CPU & EF_MEP_CPU_MASK) == EF_MEP_CPU_C5)
566 if (strncmp (*strp, "0x0", 3) == 0
567 || (**strp == '0' && *(*strp + 1) != 'x'))
570 errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
576 if (value < -512 || value > 511)
577 return _("Immediate is out of range -512 to 511");
581 if (value < -128 || value > 127)
582 return _("Immediate is out of range -128 to 127");
585 if (value & ((1<<alignment)-1))
586 return _("Value is not aligned enough");
588 /* If this field may require a relocation then use larger dsp16. */
589 if (! have_zero && value == 0)
590 return (wide ? _("Immediate is out of range -512 to 511")
591 : _("Immediate is out of range -128 to 127"));
597 /* BEGIN LIGHTWEIGHT MACRO PROCESSOR. */
615 { "sizeof", "(`1.end + (- `1))"},
616 { "startof", "(`1 | 0)" },
617 { "align4", "(`1&(~3))"},
618 /*{ "hi", "(((`1+0x8000)>>16) & 0xffff)" }, */
619 /*{ "lo", "(`1 & 0xffff)" }, */
620 /*{ "sdaoff", "((`1-__sdabase) & 0x7f)"}, */
621 /*{ "tpoff", "((`1-__tpbase) & 0x7f)"}, */
625 static char * expand_string (const char *, int);
628 mep_cgen_expand_macros_and_parse_operand
629 (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
632 str_append (char *dest, const char *input, int len)
639 /* printf("str_append: <<%s>>, <<%s>>, %d\n", dest, input, len); */
640 oldlen = (dest ? strlen(dest) : 0);
641 new_dest = realloc (dest, oldlen + len + 1);
642 memset (new_dest + oldlen, 0, len + 1);
643 return strncat (new_dest, input, len);
647 lookup_macro (const char *name)
651 for (m = macros; m->name; ++m)
652 if (strncmp (m->name, name, strlen(m->name)) == 0)
659 expand_macro (arg *args, int narg, macro *mac)
661 char *result = 0, *rescanned_result = 0;
662 char *e = mac->expansion;
666 /* printf("expanding macro %s with %d args\n", mac->name, narg + 1); */
671 ((*(e + 1) - '1') <= MAXARGS) &&
672 ((*(e + 1) - '1') <= narg))
674 result = str_append (result, mark, e - mark);
675 arg = (*(e + 1) - '1');
676 /* printf("replacing `%d with %s\n", arg+1, args[arg].start); */
677 result = str_append (result, args[arg].start, args[arg].len);
685 result = str_append (result, mark, e - mark);
689 rescanned_result = expand_string (result, 0);
691 return rescanned_result;
701 expand_string (const char *in, int first_only)
703 int num_expansions = 0;
708 const char *mark = in;
719 if (*in == '%' && *(in + 1) && (!first_only || num_expansions == 0))
721 macro = lookup_macro (in + 1);
724 /* printf("entering state %d at '%s'...\n", state, in); */
725 result = str_append (result, mark, in - mark);
727 in += 1 + strlen (macro->name);
728 while (*in == ' ') ++in;
738 args[narg].start = in + 1;
752 args[narg].start = (in + 1);
757 /* printf("entering state %d at '%s'...\n", state, in); */
761 expansion = expand_macro (args, narg, macro);
765 result = str_append (result, expansion, strlen (expansion));
771 result = str_append (result, mark, in - mark);
796 result = str_append (result, mark, in - mark);
806 /* END LIGHTWEIGHT MACRO PROCESSOR. */
808 const char * mep_cgen_parse_operand
809 (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
812 mep_cgen_expand_macros_and_parse_operand (CGEN_CPU_DESC cd, int opindex,
813 const char ** strp_in, CGEN_FIELDS * fields)
815 const char * errmsg = NULL;
816 char *str = 0, *hold = 0;
817 const char **strp = 0;
819 /* Set up a new pointer to macro-expanded string. */
820 str = expand_string (*strp_in, 1);
821 /* fprintf (stderr, " expanded <<%s>> to <<%s>>\n", *strp_in, str); */
824 strp = (const char **)(&str);
826 errmsg = mep_cgen_parse_operand (cd, opindex, strp, fields);
828 /* Now work out the advance. */
829 if (strlen (str) == 0)
830 *strp_in += strlen (*strp_in);
834 if (strstr (*strp_in, str))
835 /* A macro-expansion was pulled off the front. */
836 *strp_in = strstr (*strp_in, str);
838 /* A non-macro-expansion was pulled off the front. */
839 *strp_in += (str - hold);
848 #define CGEN_ASM_INIT_HOOK (cd->parse_operand = mep_cgen_expand_macros_and_parse_operand);
855 #define CGEN_VALIDATE_INSN_SUPPORTED
857 static void print_tpreg (CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned int);
858 static void print_spreg (CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned int);
861 print_tpreg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, PTR dis_info,
862 CGEN_KEYWORD *table ATTRIBUTE_UNUSED, long val ATTRIBUTE_UNUSED,
863 unsigned int flags ATTRIBUTE_UNUSED)
865 disassemble_info *info = (disassemble_info *) dis_info;
867 (*info->fprintf_func) (info->stream, "$tp");
871 print_spreg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, PTR dis_info,
872 CGEN_KEYWORD *table ATTRIBUTE_UNUSED, long val ATTRIBUTE_UNUSED,
873 unsigned int flags ATTRIBUTE_UNUSED)
875 disassemble_info *info = (disassemble_info *) dis_info;
877 (*info->fprintf_func) (info->stream, "$sp");
880 /* begin-cop-ip-print-handlers */
882 print_ivc2_cr (CGEN_CPU_DESC,
886 unsigned int) ATTRIBUTE_UNUSED;
888 print_ivc2_cr (CGEN_CPU_DESC cd,
890 CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED,
894 print_keyword (cd, dis_info, & mep_cgen_opval_h_cr_ivc2, value, attrs);
897 print_ivc2_ccr (CGEN_CPU_DESC,
901 unsigned int) ATTRIBUTE_UNUSED;
903 print_ivc2_ccr (CGEN_CPU_DESC cd,
905 CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED,
909 print_keyword (cd, dis_info, & mep_cgen_opval_h_ccr_ivc2, value, attrs);
911 /* end-cop-ip-print-handlers */
913 /************************************************************\
914 *********************** Experimental *************************
915 \************************************************************/
917 #undef CGEN_PRINT_INSN
918 #define CGEN_PRINT_INSN mep_print_insn
921 mep_print_vliw_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info,
922 bfd_byte *buf, int corelength, int copro1length,
923 int copro2length ATTRIBUTE_UNUSED)
927 /* char insnbuf[CGEN_MAX_INSN_SIZE]; */
928 bfd_byte insnbuf[64];
930 /* If corelength > 0 then there is a core insn present. It
931 will be at the beginning of the buffer. After printing
932 the core insn, we need to print the + on the next line. */
937 for (i = 0; i < corelength; i++ )
939 cd->isas = & MEP_CORE_ISA;
941 my_status = print_insn (cd, pc, info, insnbuf, corelength);
942 if (my_status != corelength)
944 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
945 my_status = corelength;
949 /* Print the + to indicate that the following copro insn is */
950 /* part of a vliw group. */
951 if (copro1length > 0)
952 (*info->fprintf_func) (info->stream, " + ");
955 /* Now all that is left to be processed is the coprocessor insns
956 In vliw mode, there will always be one. Its positioning will
957 be from byte corelength to byte corelength+copro1length -1.
958 No need to check for existence. Also, the first vliw insn,
959 will, as spec'd, always be at least as long as the core insn
960 so we don't need to flush the buffer. */
961 if (copro1length > 0)
965 for (i = corelength; i < corelength + copro1length; i++ )
966 insnbuf[i - corelength] = buf[i];
968 switch (copro1length)
973 cd->isas = & MEP_COP16_ISA;
976 cd->isas = & MEP_COP32_ISA;
979 cd->isas = & MEP_COP48_ISA;
982 cd->isas = & MEP_COP64_ISA;
985 /* Shouldn't be anything but 16,32,48,64. */
989 my_status = print_insn (cd, pc, info, insnbuf, copro1length);
991 if (my_status != copro1length)
993 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
994 my_status = copro1length;
1000 /* Now we need to process the second copro insn if it exists. We
1001 have no guarantee that the second copro insn will be longer
1002 than the first, so we have to flush the buffer if we are have
1003 a second copro insn to process. If present, this insn will
1004 be in the position from byte corelength+copro1length to byte
1005 corelength+copro1length+copro2length-1 (which better equal 8
1006 or else we're in big trouble. */
1007 if (copro2length > 0)
1011 for (i = 0; i < 64 ; i++)
1014 for (i = corelength + copro1length; i < 64; i++)
1015 insnbuf[i - (corelength + copro1length)] = buf[i];
1017 switch (copro2length)
1020 cd->isas = 1 << ISA_EXT_COP1_16;
1023 cd->isas = 1 << ISA_EXT_COP1_32;
1026 cd->isas = 1 << ISA_EXT_COP1_48;
1029 cd->isas = 1 << ISA_EXT_COP1_64;
1032 /* Shouldn't be anything but 16,32,48,64. */
1036 my_status = print_insn (cd, pc, info, insnbuf, copro2length);
1038 if (my_status != copro2length)
1040 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
1041 my_status = copro2length;
1044 status += my_status;
1048 /* Status should now be the number of bytes that were printed
1049 which should be 4 for VLIW32 mode and 64 for VLIW64 mode. */
1051 if ((!MEP_VLIW64 && (status != 4)) || (MEP_VLIW64 && (status != 8)))
1057 /* The two functions mep_examine_vliw[32,64]_insns are used find out
1058 which vliw combinaion (16 bit core with 48 bit copro, 32 bit core
1059 with 32 bit copro, etc.) is present. Later on, when internally
1060 parallel coprocessors are handled, only these functions should
1063 At this time only the following combinations are supported:
1066 16 bit core insn (core) and 16 bit coprocessor insn (cop1)
1067 32 bit core insn (core)
1068 32 bit coprocessor insn (cop1)
1069 Note: As of this time, I do not believe we have enough information
1070 to distinguish a 32 bit core insn from a 32 bit cop insn. Also,
1071 no 16 bit coprocessor insns have been specified.
1074 16 bit core insn (core) and 48 bit coprocessor insn (cop1)
1075 32 bit core insn (core) and 32 bit coprocessor insn (cop1)
1076 64 bit coprocessor insn (cop1)
1078 The framework for an internally parallel coprocessor is also
1079 present (2nd coprocessor insn is cop2), but at this time it
1080 is not used. This only appears to be valid in VLIW64 mode. */
1083 mep_examine_vliw32_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
1090 bfd_byte buf[CGEN_MAX_INSN_SIZE];
1091 char indicator16[1];
1092 char indicatorcop32[2];
1094 /* At this time we're not supporting internally parallel coprocessors,
1095 so cop2buflength will always be 0. */
1098 /* Read in 32 bits. */
1099 buflength = 4; /* VLIW insn spans 4 bytes. */
1100 status = (*info->read_memory_func) (pc, buf, buflength, info);
1104 (*info->memory_error_func) (status, pc, info);
1108 /* Put the big endian representation of the bytes to be examined
1109 in the temporary buffers for examination. */
1111 if (info->endian == BFD_ENDIAN_BIG)
1113 indicator16[0] = buf[0];
1114 indicatorcop32[0] = buf[0];
1115 indicatorcop32[1] = buf[1];
1119 indicator16[0] = buf[1];
1120 indicatorcop32[0] = buf[1];
1121 indicatorcop32[1] = buf[0];
1124 /* If the two high order bits are 00, 01 or 10, we have a 16 bit
1125 core insn and a 48 bit copro insn. */
1127 if ((indicator16[0] & 0x80) && (indicator16[0] & 0x40))
1129 if ((indicatorcop32[0] & 0xf0) == 0xf0 && (indicatorcop32[1] & 0x07) == 0x07)
1131 /* We have a 32 bit copro insn. */
1133 /* All 4 4ytes are one copro insn. */
1138 /* We have a 32 bit core. */
1145 /* We have a 16 bit core insn and a 16 bit copro insn. */
1150 /* Now we have the distrubution set. Print them out. */
1151 status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength,
1152 cop1buflength, cop2buflength);
1158 mep_examine_vliw64_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
1165 bfd_byte buf[CGEN_MAX_INSN_SIZE];
1166 char indicator16[1];
1167 char indicator64[4];
1169 /* At this time we're not supporting internally parallel
1170 coprocessors, so cop2buflength will always be 0. */
1173 /* Read in 64 bits. */
1174 buflength = 8; /* VLIW insn spans 8 bytes. */
1175 status = (*info->read_memory_func) (pc, buf, buflength, info);
1179 (*info->memory_error_func) (status, pc, info);
1183 /* We have all 64 bits in the buffer now. We have to figure out
1184 what combination of instruction sizes are present. The two
1185 high order bits will indicate whether or not we have a 16 bit
1186 core insn or not. If not, then we have to look at the 7,8th
1187 bytes to tell whether we have 64 bit copro insn or a 32 bit
1188 core insn with a 32 bit copro insn. Endianness will make a
1191 /* Put the big endian representation of the bytes to be examined
1192 in the temporary buffers for examination. */
1194 /* indicator16[0] = buf[0]; */
1195 if (info->endian == BFD_ENDIAN_BIG)
1197 indicator16[0] = buf[0];
1198 indicator64[0] = buf[0];
1199 indicator64[1] = buf[1];
1200 indicator64[2] = buf[2];
1201 indicator64[3] = buf[3];
1205 indicator16[0] = buf[1];
1206 indicator64[0] = buf[1];
1207 indicator64[1] = buf[0];
1208 indicator64[2] = buf[3];
1209 indicator64[3] = buf[2];
1212 /* If the two high order bits are 00, 01 or 10, we have a 16 bit
1213 core insn and a 48 bit copro insn. */
1215 if ((indicator16[0] & 0x80) && (indicator16[0] & 0x40))
1217 if ((indicator64[0] & 0xf0) == 0xf0 && (indicator64[1] & 0x07) == 0x07
1218 && ((indicator64[2] & 0xfe) != 0xf0 || (indicator64[3] & 0xf4) != 0))
1220 /* We have a 64 bit copro insn. */
1222 /* All 8 bytes are one copro insn. */
1227 /* We have a 32 bit core insn and a 32 bit copro insn. */
1234 /* We have a 16 bit core insn and a 48 bit copro insn. */
1239 /* Now we have the distrubution set. Print them out. */
1240 status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength,
1241 cop1buflength, cop2buflength);
1246 #ifdef MEP_IVC2_SUPPORTED
1249 print_slot_insn (CGEN_CPU_DESC cd,
1251 disassemble_info *info,
1255 const CGEN_INSN_LIST *insn_list;
1256 CGEN_INSN_INT insn_value;
1257 CGEN_EXTRACT_INFO ex_info;
1259 insn_value = cgen_get_insn_value (cd, buf, 32);
1261 /* Fill in ex_info fields like read_insn would. Don't actually call
1262 read_insn, since the incoming buffer is already read (and possibly
1263 modified a la m32r). */
1264 ex_info.valid = (1 << 8) - 1;
1265 ex_info.dis_info = info;
1266 ex_info.insn_bytes = buf;
1268 /* The instructions are stored in hash lists.
1269 Pick the first one and keep trying until we find the right one. */
1271 insn_list = CGEN_DIS_LOOKUP_INSN (cd, (char *) buf, insn_value);
1272 while (insn_list != NULL)
1274 const CGEN_INSN *insn = insn_list->insn;
1278 if ((CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG)
1279 && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG) != MEP_CONFIG)
1280 || ! (CGEN_ATTR_CGEN_INSN_SLOTS_VALUE (CGEN_INSN_ATTRS (insn)) & (1 << slot)))
1282 insn_list = CGEN_DIS_NEXT_INSN (insn_list);
1286 if ((insn_value & CGEN_INSN_BASE_MASK (insn))
1287 == CGEN_INSN_BASE_VALUE (insn))
1289 /* Printing is handled in two passes. The first pass parses the
1290 machine insn and extracts the fields. The second pass prints
1293 length = CGEN_EXTRACT_FN (cd, insn)
1294 (cd, insn, &ex_info, insn_value, &fields, pc);
1296 /* Length < 0 -> error. */
1301 CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
1302 /* Length is in bits, result is in bytes. */
1307 insn_list = CGEN_DIS_NEXT_INSN (insn_list);
1310 if (slot == SLOTS_P0S)
1311 (*info->fprintf_func) (info->stream, "*unknown-p0s*");
1312 else if (slot == SLOTS_P0)
1313 (*info->fprintf_func) (info->stream, "*unknown-p0*");
1314 else if (slot == SLOTS_P1)
1315 (*info->fprintf_func) (info->stream, "*unknown-p1*");
1316 else if (slot == SLOTS_C3)
1317 (*info->fprintf_func) (info->stream, "*unknown-c3*");
1322 mep_examine_ivc2_insns (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, bfd_vma pc ATTRIBUTE_UNUSED, disassemble_info *info ATTRIBUTE_UNUSED)
1331 /* At this time we're not supporting internally parallel
1332 coprocessors, so cop2buflength will always be 0. */
1335 /* Read in 64 bits. */
1336 buflength = 8; /* VLIW insn spans 8 bytes. */
1337 status = (*info->read_memory_func) (pc, buf, buflength, info);
1341 (*info->memory_error_func) (status, pc, info);
1345 if (info->endian == BFD_ENDIAN_LITTLE)
1350 if (((unsigned char)buf[0^e] & 0xf0) < 0xc0)
1352 /* <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */
1353 /* V1 [-----core-----][--------p0s-------][------------p1------------] */
1355 print_insn (cd, pc, info, buf, 2);
1358 insn[1^e] = buf[2^e];
1359 insn[2^e] = buf[3^e];
1360 insn[3^e] = buf[4^e] & 0xf0;
1361 (*info->fprintf_func) (info->stream, " + ");
1362 print_slot_insn (cd, pc, info, SLOTS_P0S, insn);
1364 insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4;
1365 insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4;
1366 insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4;
1367 insn[3^e] = buf[7^e] << 4;
1368 (*info->fprintf_func) (info->stream, " + ");
1369 print_slot_insn (cd, pc, info, SLOTS_P1, insn);
1371 else if ((buf[0^e] & 0xf0) == 0xf0 && (buf[1^e] & 0x0f) == 0x07)
1373 /* <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */
1374 /* V3 1111[--p0--]0111[--------p0--------][------------p1------------] */
1375 /* 00000000111111112222222233333333 */
1377 insn[0^e] = buf[0^e] << 4 | buf[1^e] >> 4;
1378 insn[1^e] = buf[2^e];
1379 insn[2^e] = buf[3^e];
1380 insn[3^e] = buf[4^e] & 0xf0;
1381 print_slot_insn (cd, pc, info, SLOTS_P0, insn);
1383 insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4;
1384 insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4;
1385 insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4;
1386 insn[3^e] = buf[7^e] << 4;
1387 (*info->fprintf_func) (info->stream, " + ");
1388 print_slot_insn (cd, pc, info, SLOTS_P1, insn);
1392 /* <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */
1393 /* V2 [-------------core-------------]xxxx[------------p1------------] */
1394 print_insn (cd, pc, info, buf, 4);
1396 insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4;
1397 insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4;
1398 insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4;
1399 insn[3^e] = buf[7^e] << 4;
1400 (*info->fprintf_func) (info->stream, " + ");
1401 print_slot_insn (cd, pc, info, SLOTS_P1, insn);
1407 #endif /* MEP_IVC2_SUPPORTED */
1409 /* This is a hack. SID calls this to update the disassembler as the
1410 CPU changes modes. */
1411 static int mep_ivc2_disassemble_p = 0;
1412 static int mep_ivc2_vliw_disassemble_p = 0;
1415 mep_print_insn_set_ivc2_mode (int ivc2_p, int vliw_p, int cfg_idx);
1417 mep_print_insn_set_ivc2_mode (int ivc2_p, int vliw_p, int cfg_idx)
1419 mep_ivc2_disassemble_p = ivc2_p;
1420 mep_ivc2_vliw_disassemble_p = vliw_p;
1421 mep_config_index = cfg_idx;
1425 mep_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
1430 static CGEN_ATTR_VALUE_BITSET_TYPE *ivc2_core_isa = NULL;
1432 if (ivc2_core_isa == NULL)
1434 /* IVC2 has some core-only coprocessor instructions. We
1435 use COP32 to flag those, and COP64 for the VLIW ones,
1436 since they have the same names. */
1437 ivc2_core_isa = cgen_bitset_create (MAX_ISAS);
1440 /* Extract and adapt to configuration number, if available. */
1441 if (info->section && info->section->owner)
1443 bfd *abfd = info->section->owner;
1444 mep_config_index = abfd->tdata.elf_obj_data->elf_header->e_flags & EF_MEP_INDEX_MASK;
1445 /* This instantly redefines MEP_CONFIG, MEP_OMASK, .... MEP_VLIW64 */
1447 cop_type = abfd->tdata.elf_obj_data->elf_header->e_flags & EF_MEP_COP_MASK;
1448 if (cop_type == EF_MEP_COP_IVC2)
1452 /* Picking the right ISA bitmask for the current context is tricky. */
1455 if (info->section->flags & SEC_MEP_VLIW)
1457 #ifdef MEP_IVC2_SUPPORTED
1460 /* ivc2 has its own way of selecting its functions. */
1461 cd->isas = & MEP_CORE_ISA;
1462 status = mep_examine_ivc2_insns (cd, pc, info);
1466 /* Are we in 32 or 64 bit vliw mode? */
1468 status = mep_examine_vliw64_insns (cd, pc, info);
1470 status = mep_examine_vliw32_insns (cd, pc, info);
1471 /* Both the above branches set their own isa bitmasks. */
1477 cgen_bitset_clear (ivc2_core_isa);
1478 cgen_bitset_union (ivc2_core_isa, &MEP_CORE_ISA, ivc2_core_isa);
1479 cgen_bitset_union (ivc2_core_isa, &MEP_COP32_ISA, ivc2_core_isa);
1480 cd->isas = ivc2_core_isa;
1483 cd->isas = & MEP_CORE_ISA;
1484 status = default_print_insn (cd, pc, info);
1487 else /* sid or gdb */
1489 #ifdef MEP_IVC2_SUPPORTED
1490 if (mep_ivc2_disassemble_p)
1492 if (mep_ivc2_vliw_disassemble_p)
1494 cd->isas = & MEP_CORE_ISA;
1495 status = mep_examine_ivc2_insns (cd, pc, info);
1501 cd->isas = ivc2_core_isa;
1506 status = default_print_insn (cd, pc, info);
1514 #include "elf/mep.h"
1516 /* A mask for all ISAs executed by the core. */
1517 CGEN_ATTR_VALUE_BITSET_TYPE mep_all_core_isas_mask = {0, 0};
1520 init_mep_all_core_isas_mask (void)
1522 if (mep_all_core_isas_mask.length != 0)
1524 cgen_bitset_init (& mep_all_core_isas_mask, ISA_MAX);
1525 cgen_bitset_set (& mep_all_core_isas_mask, ISA_MEP);
1526 /* begin-all-core-isas */
1527 cgen_bitset_add (& mep_all_core_isas_mask, ISA_EXT_CORE1);
1528 /* end-all-core-isas */
1531 CGEN_ATTR_VALUE_BITSET_TYPE mep_all_cop_isas_mask = {0, 0};
1534 init_mep_all_cop_isas_mask (void)
1536 if (mep_all_cop_isas_mask.length != 0)
1538 cgen_bitset_init (& mep_all_cop_isas_mask, ISA_MAX);
1539 /* begin-all-cop-isas */
1540 cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_16);
1541 cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_32);
1542 cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_48);
1543 cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_64);
1544 /* end-all-cop-isas */
1548 mep_insn_supported_by_isa (const CGEN_INSN *insn, CGEN_ATTR_VALUE_BITSET_TYPE *isa_mask)
1550 CGEN_BITSET insn_isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA);
1551 return cgen_bitset_intersect_p (& insn_isas, isa_mask);
1554 #define OPTION_MASK \
1555 ( (1 << CGEN_INSN_OPTIONAL_BIT_INSN) \
1556 | (1 << CGEN_INSN_OPTIONAL_MUL_INSN) \
1557 | (1 << CGEN_INSN_OPTIONAL_DIV_INSN) \
1558 | (1 << CGEN_INSN_OPTIONAL_DEBUG_INSN) \
1559 | (1 << CGEN_INSN_OPTIONAL_LDZ_INSN) \
1560 | (1 << CGEN_INSN_OPTIONAL_ABS_INSN) \
1561 | (1 << CGEN_INSN_OPTIONAL_AVE_INSN) \
1562 | (1 << CGEN_INSN_OPTIONAL_MINMAX_INSN) \
1563 | (1 << CGEN_INSN_OPTIONAL_CLIP_INSN) \
1564 | (1 << CGEN_INSN_OPTIONAL_SAT_INSN) \
1565 | (1 << CGEN_INSN_OPTIONAL_UCI_INSN) \
1566 | (1 << CGEN_INSN_OPTIONAL_DSP_INSN) \
1567 | (1 << CGEN_INSN_OPTIONAL_CP_INSN) \
1568 | (1 << CGEN_INSN_OPTIONAL_CP64_INSN) )
1571 mep_config_map_struct mep_config_map[] =
1573 /* config-map-start */
1574 /* Default entry: first module, with all options enabled. */
1575 { "", 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) },
1576 { "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" },
1578 | (1 << CGEN_INSN_OPTIONAL_CP_INSN)
1579 | (1 << CGEN_INSN_OPTIONAL_CP64_INSN)
1580 | (1 << CGEN_INSN_OPTIONAL_MUL_INSN)
1581 | (1 << CGEN_INSN_OPTIONAL_DIV_INSN)
1582 | (1 << CGEN_INSN_OPTIONAL_BIT_INSN)
1583 | (1 << CGEN_INSN_OPTIONAL_LDZ_INSN)
1584 | (1 << CGEN_INSN_OPTIONAL_ABS_INSN)
1585 | (1 << CGEN_INSN_OPTIONAL_AVE_INSN)
1586 | (1 << CGEN_INSN_OPTIONAL_MINMAX_INSN)
1587 | (1 << CGEN_INSN_OPTIONAL_CLIP_INSN)
1588 | (1 << CGEN_INSN_OPTIONAL_SAT_INSN) },
1589 /* config-map-end */
1590 { 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, 0 }
1593 int mep_config_index = 0;
1596 check_configured_mach (int machs)
1598 /* All base insns are supported. */
1599 int mach = 1 << MACH_BASE;
1600 switch (MEP_CPU & EF_MEP_CPU_MASK)
1604 mach |= (1 << MACH_MEP);
1607 mach |= (1 << MACH_H1);
1610 mach |= (1 << MACH_MEP);
1611 mach |= (1 << MACH_C5);
1616 return machs & mach;
1620 mep_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
1622 int iconfig = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG);
1623 int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
1624 CGEN_BITSET isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA);
1629 /* If the insn has an option bit set that we don't want,
1631 if (CGEN_INSN_ATTRS (insn)->bool & OPTION_MASK & ~MEP_OMASK)
1634 /* If attributes are absent, assume no restriction. */
1638 ok1 = ((machs & cd->machs) && cgen_bitset_intersect_p (& isas, cd->isas));
1639 /* If the insn is config-specific, make sure it matches. */
1640 ok2 = (iconfig == 0 || iconfig == MEP_CONFIG);
1641 /* Make sure the insn is supported by the configured mach */
1642 ok3 = check_configured_mach (machs);
1644 return (ok1 && ok2 && ok3);
1648 mep_cgen_insn_supported_asm (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
1650 #ifdef MEP_IVC2_SUPPORTED
1651 /* If we're assembling VLIW packets, ignore the 12-bit BSR as we
1652 can't relax that. The 24-bit BSR is matched instead. */
1653 if (insn->base->num == MEP_INSN_BSR12
1654 && cgen_bitset_contains (cd->isas, ISA_EXT_COP1_64))
1658 return mep_cgen_insn_supported (cd, insn);