2009-06-19 Tristan Gingold <gingold@adacore.com>
[binutils.git] / cpu / m32c.opc
blob0d9dafe41cc814cf1abe78b7fe0ef835a132bbca
1 /* m32c opcode support.  -*- C -*-
3    Copyright 2005, 2007 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 3 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,
22    MA 02110-1301, USA.  */
25 /* This file is an addendum to m32c.cpu.  Heavy use of C code isn't
26    appropriate in .cpu files, so it resides here.  This especially applies
27    to assembly/disassembly where parsing/printing can be quite involved.
28    Such things aren't really part of the specification of the cpu, per se,
29    so .cpu files provide the general framework and .opc files handle the
30    nitty-gritty details as necessary.
32    Each section is delimited with start and end markers.
34    <arch>-opc.h additions use: "-- opc.h"
35    <arch>-opc.c additions use: "-- opc.c"
36    <arch>-asm.c additions use: "-- asm.c"
37    <arch>-dis.c additions use: "-- dis.c"
38    <arch>-ibd.h additions use: "-- ibd.h".  */
40 /* -- opc.h */
42 /* Needed for RTL's 'ext' and 'trunc' operators.  */
43 #include "cgen-types.h"
44 #include "cgen-ops.h"
46 /* We can't use the default hash size because many bits are used by
47    operands.  */
48 #define CGEN_DIS_HASH_SIZE 1
49 #define CGEN_DIS_HASH(buf, value) 0
50 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
51 #define CGEN_VALIDATE_INSN_SUPPORTED
53 extern int m32c_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
55 #define CGEN_ASM_HASH_SIZE 0xffff
56 #define CGEN_ASM_HASH(mnem) m32c_asm_hash ((mnem))
58 /* -- */
60 /* -- opc.c */
61 static unsigned int
62 m32c_asm_hash (const char *mnem)
64   unsigned int h;
65   
66   /* The length of the mnemonic for the Jcnd insns is 1.  Hash jsri.  */
67   if (mnem[0] == 'j' && mnem[1] != 's')
68     return 'j';
69   
70   /* Don't hash scCND  */
71   if (mnem[0] == 's' && mnem[1] == 'c')
72     return 's';
73   
74   /* Don't hash bmCND  */
75   if (mnem[0] == 'b' && mnem[1] == 'm')
76     return 'b';
77   
78   for (h = 0; *mnem && *mnem != ' ' && *mnem != ':'; ++mnem)
79     h += *mnem;
80   return h % CGEN_ASM_HASH_SIZE;
83 /* -- asm.c */
84 #include "safe-ctype.h"
86 #define MACH_M32C 5             /* Must match md_begin.  */
88 static int
89 m32c_cgen_isa_register (const char **strp)
90  {
91    int u;
92    const char *s = *strp;
93    static char * m32c_register_names [] = 
94      {
95        "r0", "r1", "r2", "r3", "r0l", "r0h", "r1l", "r1h",
96        "a0", "a1", "r2r0", "r3r1", "sp", "fb", "dct0", "dct1", "flg", "svf",
97        "drc0", "drc1", "dmd0", "dmd1", "intb", "svp", "vct", "isp", "dma0",
98        "dma1", "dra0", "dra1", "dsa0", "dsa1", 0
99      };
101    for (u = 0; m32c_register_names[u]; u++)
102      {
103        int len = strlen (m32c_register_names[u]);
105        if (memcmp (m32c_register_names[u], s, len) == 0
106            && (s[len] == 0 || ! ISALNUM (s[len])))
107         return 1;
108      }
109    return 0;
112 #define PARSE_UNSIGNED                                                  \
113   do                                                                    \
114     {                                                                   \
115       /* Don't successfully parse literals beginning with '['.  */      \
116       if (**strp == '[')                                                \
117         return "Invalid literal"; /* Anything -- will not be seen.  */  \
118                                                                         \
119       errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);\
120       if (errmsg)                                                       \
121         return errmsg;                                                  \
122     }                                                                   \
123   while (0)
125 #define PARSE_SIGNED                                                    \
126   do                                                                    \
127     {                                                                   \
128       /* Don't successfully parse literals beginning with '['.  */      \
129       if (**strp == '[')                                                \
130         return "Invalid literal"; /* Anything -- will not be seen.  */  \
131                                                                         \
132       errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);  \
133       if (errmsg)                                                       \
134         return errmsg;                                                  \
135     }                                                                   \
136   while (0)
138 static const char *
139 parse_unsigned6 (CGEN_CPU_DESC cd, const char **strp,
140                  int opindex, unsigned long *valuep)
142   const char *errmsg = 0;
143   unsigned long value;
145   PARSE_UNSIGNED;
147   if (value > 0x3f)
148     return _("imm:6 immediate is out of range");
150   *valuep = value;
151   return 0;
154 static const char *
155 parse_unsigned8 (CGEN_CPU_DESC cd, const char **strp,
156                  int opindex, unsigned long *valuep)
158   const char *errmsg = 0;
159   unsigned long value;
160   long have_zero = 0;
162   if (strncasecmp (*strp, "%dsp8(", 6) == 0)
163     {
164       enum cgen_parse_operand_result result_type;
165       bfd_vma value;
166       const char *errmsg;
168       *strp += 6;
169       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_8,
170                                    & result_type, & value);
171       if (**strp != ')')
172         return _("missing `)'");
173       (*strp) ++;
175       if (errmsg == NULL
176           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
177         {
178           return _("%dsp8() takes a symbolic address, not a number");
179         }
180       *valuep = value;
181       return errmsg;
182     }
184   if (strncmp (*strp, "0x0", 3) == 0 
185       || (**strp == '0' && *(*strp + 1) != 'x'))
186     have_zero = 1;
188   PARSE_UNSIGNED;
190   if (value > 0xff)
191     return _("dsp:8 immediate is out of range");
193   /* If this field may require a relocation then use larger dsp16.  */
194   if (! have_zero && value == 0)
195     return _("dsp:8 immediate is out of range");
197   *valuep = value;
198   return 0;
201 static const char *
202 parse_signed4 (CGEN_CPU_DESC cd, const char **strp,
203                int opindex, signed long *valuep)
205   const char *errmsg = 0;
206   signed long value;
207   long have_zero = 0;
209   if (strncmp (*strp, "0x0", 3) == 0 
210       || (**strp == '0' && *(*strp + 1) != 'x'))
211     have_zero = 1;
213   PARSE_SIGNED;
215   if (value < -8 || value > 7)
216     return _("Immediate is out of range -8 to 7");
218   /* If this field may require a relocation then use larger dsp16.  */
219   if (! have_zero && value == 0)
220     return _("Immediate is out of range -8 to 7");
222   *valuep = value;
223   return 0;
226 static const char *
227 parse_signed4n (CGEN_CPU_DESC cd, const char **strp,
228                 int opindex, signed long *valuep)
230   const char *errmsg = 0;
231   signed long value;
232   long have_zero = 0;
234   if (strncmp (*strp, "0x0", 3) == 0 
235       || (**strp == '0' && *(*strp + 1) != 'x'))
236     have_zero = 1;
238   PARSE_SIGNED;
240   if (value < -7 || value > 8)
241     return _("Immediate is out of range -7 to 8");
243   /* If this field may require a relocation then use larger dsp16.  */
244   if (! have_zero && value == 0)
245     return _("Immediate is out of range -7 to 8");
247   *valuep = -value;
248   return 0;
251 static const char *
252 parse_signed8 (CGEN_CPU_DESC cd, const char **strp,
253                int opindex, signed long *valuep)
255   const char *errmsg = 0;
256   signed long value;
258   if (strncasecmp (*strp, "%hi8(", 5) == 0)
259     {
260       enum cgen_parse_operand_result result_type;
261       bfd_vma value;
262       const char *errmsg;
264       *strp += 5;
265       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32C_HI8,
266                                    & result_type, & value);
267       if (**strp != ')')
268         return _("missing `)'");
269       (*strp) ++;
271       if (errmsg == NULL
272           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
273         {
274           value >>= 16;
275         }
276       *valuep = value;
277       return errmsg;
278     }
280   PARSE_SIGNED;
282   if (value <= 255 && value > 127)
283     value -= 0x100;
285   if (value < -128 || value > 127)
286     return _("dsp:8 immediate is out of range");
288   *valuep = value;
289   return 0;
292 static const char *
293 parse_unsigned16 (CGEN_CPU_DESC cd, const char **strp,
294                  int opindex, unsigned long *valuep)
296   const char *errmsg = 0;
297   unsigned long value;
298   long have_zero = 0;
300   if (strncasecmp (*strp, "%dsp16(", 7) == 0)
301     {
302       enum cgen_parse_operand_result result_type;
303       bfd_vma value;
304       const char *errmsg;
306       *strp += 7;
307       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_16,
308                                    & result_type, & value);
309       if (**strp != ')')
310         return _("missing `)'");
311       (*strp) ++;
313       if (errmsg == NULL
314           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
315         {
316           return _("%dsp16() takes a symbolic address, not a number");
317         }
318       *valuep = value;
319       return errmsg;
320     }
322   /* Don't successfully parse literals beginning with '['.  */
323   if (**strp == '[')
324     return "Invalid literal"; /* Anything -- will not be seen.  */
326   /* Don't successfully parse register names.  */
327   if (m32c_cgen_isa_register (strp))
328     return "Invalid literal"; /* Anything -- will not be seen.  */
330   if (strncmp (*strp, "0x0", 3) == 0 
331       || (**strp == '0' && *(*strp + 1) != 'x'))
332     have_zero = 1;
333   
334   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
335   if (errmsg)
336     return errmsg;
338   if (value > 0xffff)
339     return _("dsp:16 immediate is out of range");
341   /* If this field may require a relocation then use larger dsp24.  */
342   if (cd->machs == MACH_M32C && ! have_zero && value == 0
343       && (strncmp (*strp, "[a", 2) == 0
344           || **strp == ','
345           || **strp == 0))
346     return _("dsp:16 immediate is out of range");
348   *valuep = value;
349   return 0;
352 static const char *
353 parse_signed16 (CGEN_CPU_DESC cd, const char **strp,
354                int opindex, signed long *valuep)
356   const char *errmsg = 0;
357   signed long value;
359   if (strncasecmp (*strp, "%lo16(", 6) == 0)
360     {
361       enum cgen_parse_operand_result result_type;
362       bfd_vma value;
363       const char *errmsg;
365       *strp += 6;
366       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
367                                    & result_type, & value);
368       if (**strp != ')')
369         return _("missing `)'");
370       (*strp) ++;
372       if (errmsg == NULL
373           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
374         {
375           value &= 0xffff;
376         }
377       *valuep = value;
378       return errmsg;
379     }
381   if (strncasecmp (*strp, "%hi16(", 6) == 0)
382     {
383       enum cgen_parse_operand_result result_type;
384       bfd_vma value;
385       const char *errmsg;
387       *strp += 6;
388       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16,
389                                    & result_type, & value);
390       if (**strp != ')')
391         return _("missing `)'");
392       (*strp) ++;
394       if (errmsg == NULL
395           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
396         {
397           value >>= 16;
398         }
399       *valuep = value;
400       return errmsg;
401     }
403   PARSE_SIGNED;
405   if (value <= 65535 && value > 32767)
406     value -= 0x10000;
408   if (value < -32768 || value > 32767)
409     return _("dsp:16 immediate is out of range");
411   *valuep = value;
412   return 0;
415 static const char *
416 parse_unsigned20 (CGEN_CPU_DESC cd, const char **strp,
417                  int opindex, unsigned long *valuep)
419   const char *errmsg = 0;
420   unsigned long value;
421   
422   /* Don't successfully parse literals beginning with '['.  */
423   if (**strp == '[')
424     return "Invalid literal"; /* Anything -- will not be seen.  */
426   /* Don't successfully parse register names.  */
427   if (m32c_cgen_isa_register (strp))
428     return "Invalid literal"; /* Anything -- will not be seen.  */
430   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
431   if (errmsg)
432     return errmsg;
434   if (value > 0xfffff)
435     return _("dsp:20 immediate is out of range");
437   *valuep = value;
438   return 0;
441 static const char *
442 parse_unsigned24 (CGEN_CPU_DESC cd, const char **strp,
443                  int opindex, unsigned long *valuep)
445   const char *errmsg = 0;
446   unsigned long value;
447   
448   /* Don't successfully parse literals beginning with '['.  */
449   if (**strp == '[')
450     return "Invalid literal"; /* Anything -- will not be seen.  */
452   /* Don't successfully parse register names.  */
453   if (m32c_cgen_isa_register (strp))
454     return "Invalid literal"; /* Anything -- will not be seen.  */
456   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
457   if (errmsg)
458     return errmsg;
460   if (value > 0xffffff)
461     return _("dsp:24 immediate is out of range");
463   *valuep = value;
464   return 0;
467 /* This should only be used for #imm->reg.  */
468 static const char *
469 parse_signed24 (CGEN_CPU_DESC cd, const char **strp,
470                  int opindex, signed long *valuep)
472   const char *errmsg = 0;
473   signed long value;
475   PARSE_SIGNED;
477   if (value <= 0xffffff && value > 0x7fffff)
478     value -= 0x1000000;
480   if (value > 0xffffff)
481     return _("dsp:24 immediate is out of range");
483   *valuep = value;
484   return 0;
487 static const char *
488 parse_signed32 (CGEN_CPU_DESC cd, const char **strp,
489                 int opindex, signed long *valuep)
491   const char *errmsg = 0;
492   signed long value;
493   
494   errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
495   if (errmsg)
496     return errmsg;
498   *valuep = value;
499   return 0;
502 static const char *
503 parse_imm1_S (CGEN_CPU_DESC cd, const char **strp,
504              int opindex, signed long *valuep)
506   const char *errmsg = 0;
507   signed long value;
509   errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
510   if (errmsg)
511     return errmsg;
513   if (value < 1 || value > 2)
514     return _("immediate is out of range 1-2");
516   *valuep = value;
517   return 0;
520 static const char *
521 parse_imm3_S (CGEN_CPU_DESC cd, const char **strp,
522              int opindex, signed long *valuep)
524   const char *errmsg = 0;
525   signed long value;
526   
527   errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
528   if (errmsg)
529     return errmsg;
531   if (value < 1 || value > 8)
532     return _("immediate is out of range 1-8");
534   *valuep = value;
535   return 0;
538 static const char *
539 parse_bit3_S (CGEN_CPU_DESC cd, const char **strp,
540              int opindex, signed long *valuep)
542   const char *errmsg = 0;
543   signed long value;
544   
545   errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
546   if (errmsg)
547     return errmsg;
549   if (value < 0 || value > 7)
550     return _("immediate is out of range 0-7");
552   *valuep = value;
553   return 0;
556 static const char *
557 parse_lab_5_3 (CGEN_CPU_DESC cd,
558                const char **strp,
559                int opindex ATTRIBUTE_UNUSED,
560                int opinfo,
561                enum cgen_parse_operand_result *type_addr,
562                bfd_vma *valuep)
564   const char *errmsg = 0;
565   bfd_vma value;
566   enum cgen_parse_operand_result op_res;
568   errmsg = cgen_parse_address (cd, strp, M32C_OPERAND_LAB_5_3,
569                                opinfo, & op_res, & value);
571   if (type_addr)
572     *type_addr = op_res;
574   if (op_res == CGEN_PARSE_OPERAND_ADDRESS)
575     {
576       /* This is a hack; the field cannot handle near-zero signed
577          offsets that CGEN wants to put in to indicate an "empty"
578          operand at first.  */
579       *valuep = 2;
580       return 0;
581     }
582   if (errmsg)
583     return errmsg;
585   if (value < 2 || value > 9)
586     return _("immediate is out of range 2-9");
588   *valuep = value;
589   return 0;
592 static const char *
593 parse_Bitno16R (CGEN_CPU_DESC cd, const char **strp,
594                 int opindex, unsigned long *valuep)
596   const char *errmsg = 0;
597   unsigned long value;
599   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
600   if (errmsg)
601     return errmsg;
603   if (value > 15)
604     return _("Bit number for indexing general register is out of range 0-15");
606   *valuep = value;
607   return 0;
610 static const char *
611 parse_unsigned_bitbase (CGEN_CPU_DESC cd, const char **strp,
612                         int opindex, unsigned long *valuep,
613                         unsigned bits, int allow_syms)
615   const char *errmsg = 0;
616   unsigned long bit;
617   unsigned long base;
618   const char *newp = *strp;
619   unsigned long long bitbase;
620   long have_zero = 0;
622   errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & bit);
623   if (errmsg)
624     return errmsg;
626   if (*newp != ',')
627     return "Missing base for bit,base:8";
629   ++newp;
631   if (strncmp (newp, "0x0", 3) == 0 
632       || (newp[0] == '0' && newp[1] != 'x'))
633     have_zero = 1;
635   errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & base);
636   if (errmsg)
637     return errmsg;
639   bitbase = (unsigned long long) bit + ((unsigned long long) base * 8);
641   if (bitbase >= (1ull << bits))
642     return _("bit,base is out of range");
644   /* If this field may require a relocation then use larger displacement.  */
645   if (! have_zero && base == 0)
646     {
647       switch (allow_syms) {
648       case 0:
649         return _("bit,base out of range for symbol");
650       case 1:
651         break;
652       case 2:
653         if (strncmp (newp, "[sb]", 4) != 0)
654           return _("bit,base out of range for symbol");
655         break;
656       }
657     }
659   *valuep = bitbase;
660   *strp = newp;
661   return 0;
664 static const char *
665 parse_signed_bitbase (CGEN_CPU_DESC cd, const char **strp,
666                       int opindex, signed long *valuep,
667                       unsigned bits, int allow_syms)
669   const char *errmsg = 0;
670   unsigned long bit;
671   signed long base;
672   const char *newp = *strp;
673   long long bitbase;
674   long long limit;
675   long have_zero = 0;
677   errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & bit);
678   if (errmsg)
679     return errmsg;
681   if (*newp != ',')
682     return "Missing base for bit,base:8";
684   ++newp;
686   if (strncmp (newp, "0x0", 3) == 0 
687       || (newp[0] == '0' && newp[1] != 'x'))
688     have_zero = 1;
690   errmsg = cgen_parse_signed_integer (cd, & newp, opindex, & base);
691   if (errmsg)
692     return errmsg;
694   bitbase = (long long)bit + ((long long)base * 8);
696   limit = 1ll << (bits - 1);
697   if (bitbase < -limit || bitbase >= limit)
698     return _("bit,base is out of range");
700   /* If this field may require a relocation then use larger displacement.  */
701   if (! have_zero && base == 0 && ! allow_syms)
702     return _("bit,base out of range for symbol");
704   *valuep = bitbase;
705   *strp = newp;
706   return 0;
709 static const char *
710 parse_unsigned_bitbase8 (CGEN_CPU_DESC cd, const char **strp,
711                          int opindex, unsigned long *valuep)
713   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 8, 0);
716 static const char *
717 parse_unsigned_bitbase11 (CGEN_CPU_DESC cd, const char **strp,
718                          int opindex, unsigned long *valuep)
720   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 11, 0);
723 static const char *
724 parse_unsigned_bitbase16 (CGEN_CPU_DESC cd, const char **strp,
725                           int opindex, unsigned long *valuep)
727   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 16, 1);
730 static const char *
731 parse_unsigned_bitbase19 (CGEN_CPU_DESC cd, const char **strp,
732                          int opindex, unsigned long *valuep)
734   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 19, 2);
737 static const char *
738 parse_unsigned_bitbase27 (CGEN_CPU_DESC cd, const char **strp,
739                          int opindex, unsigned long *valuep)
741   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 27, 1);
744 static const char *
745 parse_signed_bitbase8 (CGEN_CPU_DESC cd, const char **strp,
746                        int opindex, signed long *valuep)
748   return parse_signed_bitbase (cd, strp, opindex, valuep, 8, 1);
751 static const char *
752 parse_signed_bitbase11 (CGEN_CPU_DESC cd, const char **strp,
753                        int opindex, signed long *valuep)
755   return parse_signed_bitbase (cd, strp, opindex, valuep, 11, 0);
758 static const char *
759 parse_signed_bitbase19 (CGEN_CPU_DESC cd, const char **strp,
760                        int opindex, signed long *valuep)
762   return parse_signed_bitbase (cd, strp, opindex, valuep, 19, 1);
765 /* Parse the suffix as :<char> or as nothing followed by a whitespace.  */
767 static const char *
768 parse_suffix (const char **strp, char suffix)
770   const char *newp = *strp;
771   
772   if (**strp == ':' && TOLOWER (*(*strp + 1)) == suffix)
773     newp = *strp + 2;
775   if (ISSPACE (*newp))
776     {
777       *strp = newp;
778       return 0;
779     }
780         
781   return "Invalid suffix"; /* Anything -- will not be seen.  */
784 static const char *
785 parse_S (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
786          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
788   return parse_suffix (strp, 's');
791 static const char *
792 parse_G (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
793          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
795   return parse_suffix (strp, 'g');
798 static const char *
799 parse_Q (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
800          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
802   return parse_suffix (strp, 'q');
805 static const char *
806 parse_Z (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
807          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
809   return parse_suffix (strp, 'z');
812 /* Parse an empty suffix. Fail if the next char is ':'.  */
814 static const char *
815 parse_X (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
816          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
818   if (**strp == ':')
819     return "Unexpected suffix";
820   return 0;
823 static const char *
824 parse_r0l_r0h (CGEN_CPU_DESC cd, const char **strp,
825                int opindex ATTRIBUTE_UNUSED, signed long *valuep)
827   const char *errmsg;
828   signed long value;
829   signed long junk;
830   const char *newp = *strp;
832   /* Parse r0[hl].  */
833   errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0l_r0h, & value);
834   if (errmsg)
835     return errmsg;
837   if (*newp != ',')
838     return _("not a valid r0l/r0h pair");
839   ++newp;
841   /* Parse the second register in the pair.  */
842   if (value == 0) /* r0l */
843     errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0h, & junk);
844   else
845     errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0l, & junk);
846   if (errmsg)
847     return errmsg;
849   *strp = newp;
850   *valuep = ! value;
851   return 0;
854 /* Accept .b or .w in any case.  */
856 static const char *
857 parse_size (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
858             int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
860   if (**strp == '.'
861       && (*(*strp + 1) == 'b' || *(*strp + 1) == 'B'
862           || *(*strp + 1) == 'w' || *(*strp + 1) == 'W'))
863     {
864       *strp += 2;
865       return NULL;
866     }
868   return _("Invalid size specifier");
871 /* Special check to ensure that instruction exists for given machine.  */
874 m32c_cgen_insn_supported (CGEN_CPU_DESC cd,
875                           const CGEN_INSN *insn)
877   int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
878   CGEN_BITSET isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA);
880   /* If attributes are absent, assume no restriction.  */
881   if (machs == 0)
882     machs = ~0;
884   return ((machs & cd->machs)
885           && cgen_bitset_intersect_p (& isas, cd->isas));
888 /* Parse a set of registers, R0,R1,A0,A1,SB,FB.  */
890 static const char *
891 parse_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
892               const char **strp,
893               int opindex ATTRIBUTE_UNUSED,
894               unsigned long *valuep,
895               int push)
897   const char *errmsg = 0;
898   int regno = 0;
900   *valuep = 0;
901   while (**strp && **strp != ')')
902     {
903       if (**strp == 'r' || **strp == 'R')
904         {
905           ++*strp;
906           regno = **strp - '0';
907           if (regno > 4)
908             errmsg = _("Register number is not valid");
909         }
910       else if (**strp == 'a' || **strp == 'A')
911         {
912           ++*strp;
913           regno = **strp - '0';
914           if (regno > 2)
915             errmsg = _("Register number is not valid");
916           regno = **strp - '0' + 4;
917         }
918       
919       else if (strncasecmp (*strp, "sb", 2) == 0 || strncasecmp (*strp, "SB", 2) == 0)
920         {
921           regno = 6;
922           ++*strp;
923         }
924       
925       else if (strncasecmp (*strp, "fb", 2) == 0 || strncasecmp (*strp, "FB", 2) == 0)
926         {
927           regno = 7;
928           ++*strp;
929         }
930       
931       if (push) /* Mask is reversed for push.  */
932         *valuep |= 0x80 >> regno;
933       else
934         *valuep |= 1 << regno;
936       ++*strp;
937       if (**strp == ',')
938         {
939           if (*(*strp + 1) == ')')
940             break;
941           ++*strp;
942         }
943     }
945   if (!*strp)
946     errmsg = _("Register list is not valid");
948   return errmsg;
951 #define POP  0
952 #define PUSH 1
954 static const char *
955 parse_pop_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
956                   const char **strp,
957                   int opindex ATTRIBUTE_UNUSED,
958                   unsigned long *valuep)
960   return parse_regset (cd, strp, opindex, valuep, POP);
963 static const char *
964 parse_push_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
965                    const char **strp,
966                    int opindex ATTRIBUTE_UNUSED,
967                    unsigned long *valuep)
969   return parse_regset (cd, strp, opindex, valuep, PUSH);
972 /* -- dis.c */
974 #include "elf/m32c.h"
975 #include "elf-bfd.h"
977 /* Always print the short insn format suffix as ':<char>'.  */
979 static void
980 print_suffix (void * dis_info, char suffix)
982   disassemble_info *info = dis_info;
984   (*info->fprintf_func) (info->stream, ":%c", suffix);
987 static void
988 print_S (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
989          void * dis_info,
990          long value ATTRIBUTE_UNUSED,
991          unsigned int attrs ATTRIBUTE_UNUSED,
992          bfd_vma pc ATTRIBUTE_UNUSED,
993          int length ATTRIBUTE_UNUSED)
995   print_suffix (dis_info, 's');
999 static void
1000 print_G (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1001          void * dis_info,
1002          long value ATTRIBUTE_UNUSED,
1003          unsigned int attrs ATTRIBUTE_UNUSED,
1004          bfd_vma pc ATTRIBUTE_UNUSED,
1005          int length ATTRIBUTE_UNUSED)
1007   print_suffix (dis_info, 'g');
1010 static void
1011 print_Q (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1012          void * dis_info,
1013          long value ATTRIBUTE_UNUSED,
1014          unsigned int attrs ATTRIBUTE_UNUSED,
1015          bfd_vma pc ATTRIBUTE_UNUSED,
1016          int length ATTRIBUTE_UNUSED)
1018   print_suffix (dis_info, 'q');
1021 static void
1022 print_Z (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1023          void * dis_info,
1024          long value ATTRIBUTE_UNUSED,
1025          unsigned int attrs ATTRIBUTE_UNUSED,
1026          bfd_vma pc ATTRIBUTE_UNUSED,
1027          int length ATTRIBUTE_UNUSED)
1029   print_suffix (dis_info, 'z');
1032 /* Print the empty suffix.  */
1034 static void
1035 print_X (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1036          void * dis_info ATTRIBUTE_UNUSED,
1037          long value ATTRIBUTE_UNUSED,
1038          unsigned int attrs ATTRIBUTE_UNUSED,
1039          bfd_vma pc ATTRIBUTE_UNUSED,
1040          int length ATTRIBUTE_UNUSED)
1042   return;
1045 static void
1046 print_r0l_r0h (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1047                void * dis_info,
1048                long value,
1049                unsigned int attrs ATTRIBUTE_UNUSED,
1050                bfd_vma pc ATTRIBUTE_UNUSED,
1051                int length ATTRIBUTE_UNUSED)
1053   disassemble_info *info = dis_info;
1055   if (value == 0)
1056     (*info->fprintf_func) (info->stream, "r0h,r0l");
1057   else
1058     (*info->fprintf_func) (info->stream, "r0l,r0h");
1061 static void
1062 print_unsigned_bitbase (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1063                         void * dis_info,
1064                         unsigned long value,
1065                         unsigned int attrs ATTRIBUTE_UNUSED,
1066                         bfd_vma pc ATTRIBUTE_UNUSED,
1067                         int length ATTRIBUTE_UNUSED)
1069   disassemble_info *info = dis_info;
1071   (*info->fprintf_func) (info->stream, "%ld,0x%lx", value & 0x7, value >> 3);
1074 static void
1075 print_signed_bitbase (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1076                       void * dis_info,
1077                       signed long value,
1078                       unsigned int attrs ATTRIBUTE_UNUSED,
1079                       bfd_vma pc ATTRIBUTE_UNUSED,
1080                       int length ATTRIBUTE_UNUSED)
1082   disassemble_info *info = dis_info;
1084   (*info->fprintf_func) (info->stream, "%ld,%ld", value & 0x7, value >> 3);
1087 static void
1088 print_size (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1089             void * dis_info,
1090             long value ATTRIBUTE_UNUSED,
1091             unsigned int attrs ATTRIBUTE_UNUSED,
1092             bfd_vma pc ATTRIBUTE_UNUSED,
1093             int length ATTRIBUTE_UNUSED)
1095   /* Always print the size as '.w'.  */
1096   disassemble_info *info = dis_info;
1098   (*info->fprintf_func) (info->stream, ".w");
1101 #define POP  0
1102 #define PUSH 1
1104 static void print_pop_regset  (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
1105 static void print_push_regset (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
1107 /* Print a set of registers, R0,R1,A0,A1,SB,FB.  */
1109 static void
1110 print_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1111               void * dis_info,
1112               long value,
1113               unsigned int attrs ATTRIBUTE_UNUSED,
1114               bfd_vma pc ATTRIBUTE_UNUSED,
1115               int length ATTRIBUTE_UNUSED,
1116               int push)
1118   static char * m16c_register_names [] = 
1119   {
1120     "r0", "r1", "r2", "r3", "a0", "a1", "sb", "fb"
1121   };
1122   disassemble_info *info = dis_info;
1123   int mask;
1124   int index = 0;
1125   char* comma = "";
1127   if (push)
1128     mask = 0x80;
1129   else
1130     mask = 1;
1132   if (value & mask)
1133     {
1134       (*info->fprintf_func) (info->stream, "%s", m16c_register_names [0]);
1135       comma = ",";
1136     }
1138   for (index = 1; index <= 7; ++index)
1139     {
1140       if (push)
1141         mask >>= 1;
1142       else
1143         mask <<= 1;
1145       if (value & mask)
1146         {
1147           (*info->fprintf_func) (info->stream, "%s%s", comma,
1148                                  m16c_register_names [index]);
1149           comma = ",";
1150         }
1151     }
1154 static void
1155 print_pop_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1156                   void * dis_info,
1157                   long value,
1158                   unsigned int attrs ATTRIBUTE_UNUSED,
1159                   bfd_vma pc ATTRIBUTE_UNUSED,
1160                   int length ATTRIBUTE_UNUSED)
1162   print_regset (cd, dis_info, value, attrs, pc, length, POP);
1165 static void
1166 print_push_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1167                    void * dis_info,
1168                    long value,
1169                    unsigned int attrs ATTRIBUTE_UNUSED,
1170                    bfd_vma pc ATTRIBUTE_UNUSED,
1171                    int length ATTRIBUTE_UNUSED)
1173   print_regset (cd, dis_info, value, attrs, pc, length, PUSH);
1176 static void
1177 print_signed4n (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1178                 void * dis_info,
1179                 signed long value,
1180                 unsigned int attrs ATTRIBUTE_UNUSED,
1181                 bfd_vma pc ATTRIBUTE_UNUSED,
1182                 int length ATTRIBUTE_UNUSED)
1184   disassemble_info *info = dis_info;
1186   (*info->fprintf_func) (info->stream, "%ld", -value);