1 /* m32c opcode support. -*- C -*-
3 Copyright 2005 Free Software Foundation, Inc.
5 Contributed by Red Hat Inc; developed under contract from Renesas
7 This file is part of the GNU Binutils.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
23 /* This file is an addendum to m32c.cpu. Heavy use of C code isn't
24 appropriate in .cpu files, so it resides here. This especially applies
25 to assembly/disassembly where parsing/printing can be quite involved.
26 Such things aren't really part of the specification of the cpu, per se,
27 so .cpu files provide the general framework and .opc files handle the
28 nitty-gritty details as necessary.
30 Each section is delimited with start and end markers.
32 <arch>-opc.h additions use: "-- opc.h"
33 <arch>-opc.c additions use: "-- opc.c"
34 <arch>-asm.c additions use: "-- asm.c"
35 <arch>-dis.c additions use: "-- dis.c"
36 <arch>-ibd.h additions use: "-- ibd.h". */
40 /* Needed for RTL's 'ext' and 'trunc' operators. */
41 #include "cgen-types.h"
44 /* We can't use the default hash size because many bits are used by
46 #define CGEN_DIS_HASH_SIZE 1
47 #define CGEN_DIS_HASH(buf, value) 0
48 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
49 #define CGEN_VALIDATE_INSN_SUPPORTED
51 extern int m32c_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
53 #define CGEN_ASM_HASH_SIZE 0xffff
54 #define CGEN_ASM_HASH(mnem) m32c_asm_hash ((mnem))
60 m32c_asm_hash (const char *mnem)
64 /* The length of the mnemonic for the Jcnd insns is 1. Hash jsri. */
65 if (mnem[0] == 'j' && mnem[1] != 's')
68 /* Don't hash scCND */
69 if (mnem[0] == 's' && mnem[1] == 'c')
72 for (h = 0; *mnem && *mnem != ' ' && *mnem != ':'; ++mnem)
74 return h % CGEN_ASM_HASH_SIZE;
78 #include "safe-ctype.h"
80 #define MACH_M32C 5 /* Must match md_begin. */
83 m32c_cgen_isa_register (const char **strp)
86 const char *s = *strp;
87 static char * m32c_register_names [] =
89 "r0", "r1", "r2", "r3", "r0l", "r0h", "r1l", "r1h",
90 "a0", "a1", "r2r0", "r3r1", "sp", "fb", "dct0", "dct1", "flg", "svf",
91 "drc0", "drc1", "dmd0", "dmd1", "intb", "svp", "vct", "isp", "dma0",
92 "dma1", "dra0", "dra1", "dsa0", "dsa1", 0
95 for (u = 0; m32c_register_names[u]; u++)
97 int len = strlen (m32c_register_names[u]);
99 if (memcmp (m32c_register_names[u], s, len) == 0
100 && (s[len] == 0 || ! ISALNUM (s[len])))
106 #define PARSE_UNSIGNED \
109 /* Don't successfully parse literals beginning with '['. */ \
111 return "Invalid literal"; /* Anything -- will not be seen. */ \
113 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);\
119 #define PARSE_SIGNED \
122 /* Don't successfully parse literals beginning with '['. */ \
124 return "Invalid literal"; /* Anything -- will not be seen. */ \
126 errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value); \
133 parse_unsigned6 (CGEN_CPU_DESC cd, const char **strp,
134 int opindex, unsigned long *valuep)
136 const char *errmsg = 0;
142 return _("imm:6 immediate is out of range");
149 parse_unsigned8 (CGEN_CPU_DESC cd, const char **strp,
150 int opindex, unsigned long *valuep)
152 const char *errmsg = 0;
156 if (strncmp (*strp, "0x0", 3) == 0
157 || (**strp == '0' && *(*strp + 1) != 'x'))
163 return _("dsp:8 immediate is out of range");
165 /* If this field may require a relocation then use larger dsp16. */
166 if (! have_zero && value == 0)
167 return _("dsp:8 immediate is out of range");
174 parse_signed4 (CGEN_CPU_DESC cd, const char **strp,
175 int opindex, signed long *valuep)
177 const char *errmsg = 0;
181 if (strncmp (*strp, "0x0", 3) == 0
182 || (**strp == '0' && *(*strp + 1) != 'x'))
187 if (value < -8 || value > 7)
188 return _("Immediate is out of range -8 to 7");
190 /* If this field may require a relocation then use larger dsp16. */
191 if (! have_zero && value == 0)
192 return _("Immediate is out of range -8 to 7");
199 parse_signed8 (CGEN_CPU_DESC cd, const char **strp,
200 int opindex, signed long *valuep)
202 const char *errmsg = 0;
207 if (value <= 255 && value > 127)
210 if (value < -128 || value > 127)
211 return _("dsp:8 immediate is out of range");
218 parse_unsigned16 (CGEN_CPU_DESC cd, const char **strp,
219 int opindex, unsigned long *valuep)
221 const char *errmsg = 0;
225 /* Don't successfully parse literals beginning with '['. */
227 return "Invalid literal"; /* Anything -- will not be seen. */
229 /* Don't successfully parse register names. */
230 if (m32c_cgen_isa_register (strp))
231 return "Invalid literal"; /* Anything -- will not be seen. */
233 if (strncmp (*strp, "0x0", 3) == 0
234 || (**strp == '0' && *(*strp + 1) != 'x'))
237 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
242 return _("dsp:16 immediate is out of range");
244 /* If this field may require a relocation then use larger dsp24. */
245 if (cd->machs == MACH_M32C && ! have_zero && value == 0
246 && (strncmp (*strp, "[a", 2) == 0
249 return _("dsp:16 immediate is out of range");
256 parse_signed16 (CGEN_CPU_DESC cd, const char **strp,
257 int opindex, signed long *valuep)
259 const char *errmsg = 0;
264 if (value <= 65535 && value > 32767)
267 if (value < -32768 || value > 32767)
268 return _("dsp:16 immediate is out of range");
275 parse_unsigned20 (CGEN_CPU_DESC cd, const char **strp,
276 int opindex, unsigned long *valuep)
278 const char *errmsg = 0;
281 /* Don't successfully parse literals beginning with '['. */
283 return "Invalid literal"; /* Anything -- will not be seen. */
285 /* Don't successfully parse register names. */
286 if (m32c_cgen_isa_register (strp))
287 return "Invalid literal"; /* Anything -- will not be seen. */
289 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
294 return _("dsp:20 immediate is out of range");
301 parse_unsigned24 (CGEN_CPU_DESC cd, const char **strp,
302 int opindex, unsigned long *valuep)
304 const char *errmsg = 0;
307 /* Don't successfully parse literals beginning with '['. */
309 return "Invalid literal"; /* Anything -- will not be seen. */
311 /* Don't successfully parse register names. */
312 if (m32c_cgen_isa_register (strp))
313 return "Invalid literal"; /* Anything -- will not be seen. */
315 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
319 if (value > 0xffffff)
320 return _("dsp:24 immediate is out of range");
327 parse_signed32 (CGEN_CPU_DESC cd, const char **strp,
328 int opindex, signed long *valuep)
330 const char *errmsg = 0;
333 errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
342 parse_imm1_S (CGEN_CPU_DESC cd, const char **strp,
343 int opindex, signed long *valuep)
345 const char *errmsg = 0;
348 errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
352 if (value < 1 || value > 2)
353 return _("immediate is out of range 1-2");
360 parse_imm3_S (CGEN_CPU_DESC cd, const char **strp,
361 int opindex, signed long *valuep)
363 const char *errmsg = 0;
366 errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
370 if (value < 1 || value > 8)
371 return _("immediate is out of range 1-8");
378 parse_lab_5_3 (CGEN_CPU_DESC cd,
380 int opindex ATTRIBUTE_UNUSED,
382 enum cgen_parse_operand_result *type_addr,
383 unsigned long *valuep)
385 const char *errmsg = 0;
387 enum cgen_parse_operand_result op_res;
389 errmsg = cgen_parse_address (cd, strp, M32C_OPERAND_LAB_5_3,
390 opinfo, & op_res, & value);
395 if (op_res == CGEN_PARSE_OPERAND_ADDRESS)
397 /* This is a hack; the field cannot handle near-zero signed
398 offsets that CGEN wants to put in to indicate an "empty"
406 if (value < 2 || value > 9)
407 return _("immediate is out of range 2-9");
414 parse_Bitno16R (CGEN_CPU_DESC cd, const char **strp,
415 int opindex, unsigned long *valuep)
417 const char *errmsg = 0;
420 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
425 return _("Bit number for indexing general register is out of range 0-15");
432 parse_unsigned_bitbase (CGEN_CPU_DESC cd, const char **strp,
433 int opindex, unsigned long *valuep,
436 const char *errmsg = 0;
439 const char *newp = *strp;
440 unsigned long long bitbase;
442 errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & bit);
447 return "Missing base for bit,base:8";
450 errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & base);
454 bitbase = (unsigned long long) bit + ((unsigned long long) base * 8);
456 if (bitbase >= (1ull << bits))
457 return _("bit,base is out of range");
465 parse_signed_bitbase (CGEN_CPU_DESC cd, const char **strp,
466 int opindex, signed long *valuep,
469 const char *errmsg = 0;
472 const char *newp = *strp;
476 errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & bit);
481 return "Missing base for bit,base:8";
484 errmsg = cgen_parse_signed_integer (cd, & newp, opindex, & base);
488 bitbase = (long long)bit + ((long long)base * 8);
490 limit = 1ll << (bits - 1);
491 if (bitbase < -limit || bitbase >= limit)
492 return _("bit,base is out of range");
500 parse_unsigned_bitbase8 (CGEN_CPU_DESC cd, const char **strp,
501 int opindex, unsigned long *valuep)
503 return parse_unsigned_bitbase (cd, strp, opindex, valuep, 8);
507 parse_unsigned_bitbase11 (CGEN_CPU_DESC cd, const char **strp,
508 int opindex, unsigned long *valuep)
510 return parse_unsigned_bitbase (cd, strp, opindex, valuep, 11);
514 parse_unsigned_bitbase16 (CGEN_CPU_DESC cd, const char **strp,
515 int opindex, unsigned long *valuep)
517 return parse_unsigned_bitbase (cd, strp, opindex, valuep, 16);
521 parse_unsigned_bitbase19 (CGEN_CPU_DESC cd, const char **strp,
522 int opindex, unsigned long *valuep)
524 return parse_unsigned_bitbase (cd, strp, opindex, valuep, 19);
528 parse_unsigned_bitbase27 (CGEN_CPU_DESC cd, const char **strp,
529 int opindex, unsigned long *valuep)
531 return parse_unsigned_bitbase (cd, strp, opindex, valuep, 27);
535 parse_signed_bitbase8 (CGEN_CPU_DESC cd, const char **strp,
536 int opindex, signed long *valuep)
538 return parse_signed_bitbase (cd, strp, opindex, valuep, 8);
542 parse_signed_bitbase11 (CGEN_CPU_DESC cd, const char **strp,
543 int opindex, signed long *valuep)
545 return parse_signed_bitbase (cd, strp, opindex, valuep, 11);
549 parse_signed_bitbase19 (CGEN_CPU_DESC cd, const char **strp,
550 int opindex, signed long *valuep)
552 return parse_signed_bitbase (cd, strp, opindex, valuep, 19);
555 /* Parse the suffix as :<char> or as nothing followed by a whitespace. */
558 parse_suffix (const char **strp, char suffix)
560 const char *newp = *strp;
562 if (**strp == ':' && TOLOWER (*(*strp + 1)) == suffix)
571 return "Invalid suffix"; /* Anything -- will not be seen. */
575 parse_S (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
576 int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
578 return parse_suffix (strp, 's');
582 parse_G (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
583 int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
585 return parse_suffix (strp, 'g');
589 parse_Q (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
590 int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
592 return parse_suffix (strp, 'q');
596 parse_Z (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
597 int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
599 return parse_suffix (strp, 'z');
602 /* Parse an empty suffix. Fail if the next char is ':'. */
605 parse_X (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
606 int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
609 return "Unexpected suffix";
614 parse_r0l_r0h (CGEN_CPU_DESC cd, const char **strp,
615 int opindex ATTRIBUTE_UNUSED, signed long *valuep)
620 const char *newp = *strp;
623 errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0l_r0h, & value);
628 return _("not a valid r0l/r0h pair");
631 /* Parse the second register in the pair. */
632 if (value == 0) /* r0l */
633 errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0h, & junk);
635 errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0l, & junk);
644 /* Accept .b or .w in any case. */
647 parse_size (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
648 int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
651 && (*(*strp + 1) == 'b' || *(*strp + 1) == 'B'
652 || *(*strp + 1) == 'w' || *(*strp + 1) == 'W'))
658 return _("Invalid size specifier");
661 /* Special check to ensure that instruction exists for given machine. */
664 m32c_cgen_insn_supported (CGEN_CPU_DESC cd,
665 const CGEN_INSN *insn)
667 int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
668 int isas = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_ISA);
670 /* If attributes are absent, assume no restriction. */
674 return ((machs & cd->machs)
675 && (isas & cd->isas));
678 /* Parse a set of registers, R0,R1,A0,A1,SB,FB. */
681 parse_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
683 int opindex ATTRIBUTE_UNUSED,
684 unsigned long *valuep,
687 const char *errmsg = 0;
691 while (**strp && **strp != ')')
693 if (**strp == 'r' || **strp == 'R')
696 regno = **strp - '0';
698 errmsg = _("Register number is not valid");
700 else if (**strp == 'a' || **strp == 'A')
703 regno = **strp - '0';
705 errmsg = _("Register number is not valid");
706 regno = **strp - '0' + 4;
709 else if (strncasecmp (*strp, "sb", 2) == 0 || strncasecmp (*strp, "SB", 2) == 0)
715 else if (strncasecmp (*strp, "fb", 2) == 0 || strncasecmp (*strp, "FB", 2) == 0)
721 if (push) /* Mask is reversed for push. */
722 *valuep |= 0x80 >> regno;
724 *valuep |= 1 << regno;
729 if (*(*strp + 1) == ')')
736 errmsg = _("Register list is not valid");
745 parse_pop_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
747 int opindex ATTRIBUTE_UNUSED,
748 unsigned long *valuep)
750 return parse_regset (cd, strp, opindex, valuep, POP);
754 parse_push_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
756 int opindex ATTRIBUTE_UNUSED,
757 unsigned long *valuep)
759 return parse_regset (cd, strp, opindex, valuep, PUSH);
764 #include "elf/m32c.h"
767 /* Always print the short insn format suffix as ':<char>'. */
770 print_suffix (void * dis_info, char suffix)
772 disassemble_info *info = dis_info;
774 (*info->fprintf_func) (info->stream, ":%c", suffix);
778 print_S (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
780 long value ATTRIBUTE_UNUSED,
781 unsigned int attrs ATTRIBUTE_UNUSED,
782 bfd_vma pc ATTRIBUTE_UNUSED,
783 int length ATTRIBUTE_UNUSED)
785 print_suffix (dis_info, 's');
790 print_G (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
792 long value ATTRIBUTE_UNUSED,
793 unsigned int attrs ATTRIBUTE_UNUSED,
794 bfd_vma pc ATTRIBUTE_UNUSED,
795 int length ATTRIBUTE_UNUSED)
797 print_suffix (dis_info, 'g');
801 print_Q (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
803 long value ATTRIBUTE_UNUSED,
804 unsigned int attrs ATTRIBUTE_UNUSED,
805 bfd_vma pc ATTRIBUTE_UNUSED,
806 int length ATTRIBUTE_UNUSED)
808 print_suffix (dis_info, 'q');
812 print_Z (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
814 long value ATTRIBUTE_UNUSED,
815 unsigned int attrs ATTRIBUTE_UNUSED,
816 bfd_vma pc ATTRIBUTE_UNUSED,
817 int length ATTRIBUTE_UNUSED)
819 print_suffix (dis_info, 'z');
822 /* Print the empty suffix. */
825 print_X (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
826 void * dis_info ATTRIBUTE_UNUSED,
827 long value ATTRIBUTE_UNUSED,
828 unsigned int attrs ATTRIBUTE_UNUSED,
829 bfd_vma pc ATTRIBUTE_UNUSED,
830 int length ATTRIBUTE_UNUSED)
836 print_r0l_r0h (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
839 unsigned int attrs ATTRIBUTE_UNUSED,
840 bfd_vma pc ATTRIBUTE_UNUSED,
841 int length ATTRIBUTE_UNUSED)
843 disassemble_info *info = dis_info;
846 (*info->fprintf_func) (info->stream, "r0h,r0l");
848 (*info->fprintf_func) (info->stream, "r0l,r0h");
852 print_unsigned_bitbase (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
855 unsigned int attrs ATTRIBUTE_UNUSED,
856 bfd_vma pc ATTRIBUTE_UNUSED,
857 int length ATTRIBUTE_UNUSED)
859 disassemble_info *info = dis_info;
861 (*info->fprintf_func) (info->stream, "%ld,0x%lx", value & 0x7, value >> 3);
865 print_signed_bitbase (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
868 unsigned int attrs ATTRIBUTE_UNUSED,
869 bfd_vma pc ATTRIBUTE_UNUSED,
870 int length ATTRIBUTE_UNUSED)
872 disassemble_info *info = dis_info;
874 (*info->fprintf_func) (info->stream, "%ld,%ld", value & 0x7, value >> 3);
878 print_size (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
880 long value ATTRIBUTE_UNUSED,
881 unsigned int attrs ATTRIBUTE_UNUSED,
882 bfd_vma pc ATTRIBUTE_UNUSED,
883 int length ATTRIBUTE_UNUSED)
885 /* Always print the size as '.w'. */
886 disassemble_info *info = dis_info;
888 (*info->fprintf_func) (info->stream, ".w");
894 static void print_pop_regset (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
895 static void print_push_regset (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
897 /* Print a set of registers, R0,R1,A0,A1,SB,FB. */
900 print_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
903 unsigned int attrs ATTRIBUTE_UNUSED,
904 bfd_vma pc ATTRIBUTE_UNUSED,
905 int length ATTRIBUTE_UNUSED,
908 static char * m16c_register_names [] =
910 "r0", "r1", "r2", "r3", "a0", "a1", "sb", "fb"
912 disassemble_info *info = dis_info;
924 (*info->fprintf_func) (info->stream, "%s", m16c_register_names [0]);
928 for (index = 1; index <= 7; ++index)
937 (*info->fprintf_func) (info->stream, "%s%s", comma,
938 m16c_register_names [index]);
945 print_pop_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
948 unsigned int attrs ATTRIBUTE_UNUSED,
949 bfd_vma pc ATTRIBUTE_UNUSED,
950 int length ATTRIBUTE_UNUSED)
952 print_regset (cd, dis_info, value, attrs, pc, length, POP);
956 print_push_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
959 unsigned int attrs ATTRIBUTE_UNUSED,
960 bfd_vma pc ATTRIBUTE_UNUSED,
961 int length ATTRIBUTE_UNUSED)
963 print_regset (cd, dis_info, value, attrs, pc, length, PUSH);