[PATCH 46/57][Arm][OBJDUMP] Add support for MVE instructions: vmovl, vmull, vqdmull...
[binutils-gdb.git] / cpu / m32c.opc
blob2796e1c1cffb1bfa3dff4a34baa3947b3621ff4b
1 /* m32c opcode support.  -*- C -*-
3    Copyright 2005, 2007, 2009, 2010 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/basic-modes.h"
44 #include "cgen/basic-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 = 0;
160   long have_zero = 0;
162   if (strncasecmp (*strp, "%dsp8(", 6) == 0)
163     {
164       enum cgen_parse_operand_result result_type;
165       bfd_vma val;
167       *strp += 6;
168       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_8,
169                                    & result_type, & val);
170       if (**strp != ')')
171         return _("missing `)'");
172       (*strp) ++;
174       if (errmsg == NULL
175           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
176         return _("%dsp8() takes a symbolic address, not a number");
178       value = val;
179       *valuep = value;
180       return errmsg;
181     }
183   if (strncmp (*strp, "0x0", 3) == 0 
184       || (**strp == '0' && *(*strp + 1) != 'x'))
185     have_zero = 1;
187   PARSE_UNSIGNED;
189   if (value > 0xff)
190     return _("dsp:8 immediate is out of range");
192   /* If this field may require a relocation then use larger dsp16.  */
193   if (! have_zero && value == 0)
194     return _("dsp:8 immediate is out of range");
196   *valuep = value;
197   return 0;
200 static const char *
201 parse_signed4 (CGEN_CPU_DESC cd, const char **strp,
202                int opindex, signed long *valuep)
204   const char *errmsg = 0;
205   signed long value;
206   long have_zero = 0;
208   if (strncmp (*strp, "0x0", 3) == 0 
209       || (**strp == '0' && *(*strp + 1) != 'x'))
210     have_zero = 1;
212   PARSE_SIGNED;
214   if (value < -8 || value > 7)
215     return _("Immediate is out of range -8 to 7");
217   /* If this field may require a relocation then use larger dsp16.  */
218   if (! have_zero && value == 0)
219     return _("Immediate is out of range -8 to 7");
221   *valuep = value;
222   return 0;
225 static const char *
226 parse_signed4n (CGEN_CPU_DESC cd, const char **strp,
227                 int opindex, signed long *valuep)
229   const char *errmsg = 0;
230   signed long value;
231   long have_zero = 0;
233   if (strncmp (*strp, "0x0", 3) == 0 
234       || (**strp == '0' && *(*strp + 1) != 'x'))
235     have_zero = 1;
237   PARSE_SIGNED;
239   if (value < -7 || value > 8)
240     return _("Immediate is out of range -7 to 8");
242   /* If this field may require a relocation then use larger dsp16.  */
243   if (! have_zero && value == 0)
244     return _("Immediate is out of range -7 to 8");
246   *valuep = -value;
247   return 0;
250 static const char *
251 parse_signed8 (CGEN_CPU_DESC cd, const char **strp,
252                int opindex, signed long *valuep)
254   const char *errmsg = 0;
255   signed long value = 0;
257   if (strncasecmp (*strp, "%hi8(", 5) == 0)
258     {
259       enum cgen_parse_operand_result result_type;
260       bfd_vma val;
262       *strp += 5;
263       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32C_HI8,
264                                    & result_type, & val);
265       if (**strp != ')')
266         return _("missing `)'");
267       (*strp) ++;
269       if (errmsg == NULL
270           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
271         val >>= 16;
273       value = val;
274       *valuep = value;
275       return errmsg;
276     }
278   PARSE_SIGNED;
280   if (value <= 255 && value > 127)
281     value -= 0x100;
283   if (value < -128 || value > 127)
284     return _("dsp:8 immediate is out of range");
286   *valuep = value;
287   return 0;
290 static const char *
291 parse_unsigned16 (CGEN_CPU_DESC cd, const char **strp,
292                  int opindex, unsigned long *valuep)
294   const char *errmsg = 0;
295   unsigned long value = 0;
296   long have_zero = 0;
298   if (strncasecmp (*strp, "%dsp16(", 7) == 0)
299     {
300       enum cgen_parse_operand_result result_type;
301       bfd_vma val;
303       *strp += 7;
304       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_16,
305                                    & result_type, & val);
306       if (**strp != ')')
307         return _("missing `)'");
308       (*strp) ++;
310       if (errmsg == NULL
311           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
312         return _("%dsp16() takes a symbolic address, not a number");
314       value = val;
315       *valuep = value;
316       return errmsg;
317     }
319   /* Don't successfully parse literals beginning with '['.  */
320   if (**strp == '[')
321     return "Invalid literal"; /* Anything -- will not be seen.  */
323   /* Don't successfully parse register names.  */
324   if (m32c_cgen_isa_register (strp))
325     return "Invalid literal"; /* Anything -- will not be seen.  */
327   if (strncmp (*strp, "0x0", 3) == 0 
328       || (**strp == '0' && *(*strp + 1) != 'x'))
329     have_zero = 1;
330   
331   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
332   if (errmsg)
333     return errmsg;
335   if (value > 0xffff)
336     return _("dsp:16 immediate is out of range");
338   /* If this field may require a relocation then use larger dsp24.  */
339   if (cd->machs == MACH_M32C && ! have_zero && value == 0
340       && (strncmp (*strp, "[a", 2) == 0
341           || **strp == ','
342           || **strp == 0))
343     return _("dsp:16 immediate is out of range");
345   *valuep = value;
346   return 0;
349 static const char *
350 parse_signed16 (CGEN_CPU_DESC cd, const char **strp,
351                int opindex, signed long *valuep)
353   const char *errmsg = 0;
354   signed long value = 0;
356   if (strncasecmp (*strp, "%lo16(", 6) == 0)
357     {
358       enum cgen_parse_operand_result result_type;
359       bfd_vma val;
361       *strp += 6;
362       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
363                                    & result_type, & val);
364       if (**strp != ')')
365         return _("missing `)'");
366       (*strp) ++;
368       if (errmsg == NULL
369           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
370         val &= 0xffff;
372       value = val;
373       *valuep = value;
374       return errmsg;
375     }
377   if (strncasecmp (*strp, "%hi16(", 6) == 0)
378     {
379       enum cgen_parse_operand_result result_type;
380       bfd_vma val;
382       *strp += 6;
383       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16,
384                                    & result_type, & val);
385       if (**strp != ')')
386         return _("missing `)'");
387       (*strp) ++;
389       if (errmsg == NULL
390           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
391         val >>= 16;
393       value = val;
394       *valuep = value;
395       return errmsg;
396     }
398   PARSE_SIGNED;
400   if (value <= 65535 && value > 32767)
401     value -= 0x10000;
403   if (value < -32768 || value > 32767)
404     return _("dsp:16 immediate is out of range");
406   *valuep = value;
407   return 0;
410 static const char *
411 parse_unsigned20 (CGEN_CPU_DESC cd, const char **strp,
412                  int opindex, unsigned long *valuep)
414   const char *errmsg = 0;
415   unsigned long value;
416   
417   /* Don't successfully parse literals beginning with '['.  */
418   if (**strp == '[')
419     return "Invalid literal"; /* Anything -- will not be seen.  */
421   /* Don't successfully parse register names.  */
422   if (m32c_cgen_isa_register (strp))
423     return "Invalid literal"; /* Anything -- will not be seen.  */
425   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
426   if (errmsg)
427     return errmsg;
429   if (value > 0xfffff)
430     return _("dsp:20 immediate is out of range");
432   *valuep = value;
433   return 0;
436 static const char *
437 parse_unsigned24 (CGEN_CPU_DESC cd, const char **strp,
438                  int opindex, unsigned long *valuep)
440   const char *errmsg = 0;
441   unsigned long value;
442   
443   /* Don't successfully parse literals beginning with '['.  */
444   if (**strp == '[')
445     return "Invalid literal"; /* Anything -- will not be seen.  */
447   /* Don't successfully parse register names.  */
448   if (m32c_cgen_isa_register (strp))
449     return "Invalid literal"; /* Anything -- will not be seen.  */
451   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
452   if (errmsg)
453     return errmsg;
455   if (value > 0xffffff)
456     return _("dsp:24 immediate is out of range");
458   *valuep = value;
459   return 0;
462 /* This should only be used for #imm->reg.  */
463 static const char *
464 parse_signed24 (CGEN_CPU_DESC cd, const char **strp,
465                  int opindex, signed long *valuep)
467   const char *errmsg = 0;
468   signed long value;
470   PARSE_SIGNED;
472   if (value <= 0xffffff && value > 0x7fffff)
473     value -= 0x1000000;
475   if (value > 0xffffff)
476     return _("dsp:24 immediate is out of range");
478   *valuep = value;
479   return 0;
482 static const char *
483 parse_signed32 (CGEN_CPU_DESC cd, const char **strp,
484                 int opindex, signed long *valuep)
486   const char *errmsg = 0;
487   signed long value;
488   
489   errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
490   if (errmsg)
491     return errmsg;
493   *valuep = value;
494   return 0;
497 static const char *
498 parse_imm1_S (CGEN_CPU_DESC cd, const char **strp,
499              int opindex, signed long *valuep)
501   const char *errmsg = 0;
502   signed long value;
504   errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
505   if (errmsg)
506     return errmsg;
508   if (value < 1 || value > 2)
509     return _("immediate is out of range 1-2");
511   *valuep = value;
512   return 0;
515 static const char *
516 parse_imm3_S (CGEN_CPU_DESC cd, const char **strp,
517              int opindex, signed long *valuep)
519   const char *errmsg = 0;
520   signed long value;
521   
522   errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
523   if (errmsg)
524     return errmsg;
526   if (value < 1 || value > 8)
527     return _("immediate is out of range 1-8");
529   *valuep = value;
530   return 0;
533 static const char *
534 parse_bit3_S (CGEN_CPU_DESC cd, const char **strp,
535              int opindex, signed long *valuep)
537   const char *errmsg = 0;
538   signed long value;
539   
540   errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
541   if (errmsg)
542     return errmsg;
544   if (value < 0 || value > 7)
545     return _("immediate is out of range 0-7");
547   *valuep = value;
548   return 0;
551 static const char *
552 parse_lab_5_3 (CGEN_CPU_DESC cd,
553                const char **strp,
554                int opindex ATTRIBUTE_UNUSED,
555                int opinfo,
556                enum cgen_parse_operand_result *type_addr,
557                bfd_vma *valuep)
559   const char *errmsg = 0;
560   bfd_vma value;
561   enum cgen_parse_operand_result op_res;
563   errmsg = cgen_parse_address (cd, strp, M32C_OPERAND_LAB_5_3,
564                                opinfo, & op_res, & value);
566   if (type_addr)
567     *type_addr = op_res;
569   if (op_res == CGEN_PARSE_OPERAND_RESULT_QUEUED)
570     {
571       /* This is a hack; the field cannot handle near-zero signed
572          offsets that CGEN wants to put in to indicate an "empty"
573          operand at first.  */
574       *valuep = 2;
575       return 0;
576     }
577   if (errmsg)
578     return errmsg;
580   if (value < 2 || value > 9)
581     return _("immediate is out of range 2-9");
583   *valuep = value;
584   return 0;
587 static const char *
588 parse_Bitno16R (CGEN_CPU_DESC cd, const char **strp,
589                 int opindex, unsigned long *valuep)
591   const char *errmsg = 0;
592   unsigned long value;
594   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
595   if (errmsg)
596     return errmsg;
598   if (value > 15)
599     return _("Bit number for indexing general register is out of range 0-15");
601   *valuep = value;
602   return 0;
605 static const char *
606 parse_unsigned_bitbase (CGEN_CPU_DESC cd, const char **strp,
607                         int opindex, unsigned long *valuep,
608                         unsigned bits, int allow_syms)
610   const char *errmsg = 0;
611   unsigned long bit;
612   unsigned long base;
613   const char *newp = *strp;
614   unsigned long long bitbase;
615   long have_zero = 0;
617   errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & bit);
618   if (errmsg)
619     return errmsg;
621   if (*newp != ',')
622     return "Missing base for bit,base:8";
624   ++newp;
626   if (strncmp (newp, "0x0", 3) == 0 
627       || (newp[0] == '0' && newp[1] != 'x'))
628     have_zero = 1;
630   errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & base);
631   if (errmsg)
632     return errmsg;
634   bitbase = (unsigned long long) bit + ((unsigned long long) base * 8);
636   if (bitbase >= (1ull << bits))
637     return _("bit,base is out of range");
639   /* If this field may require a relocation then use larger displacement.  */
640   if (! have_zero && base == 0)
641     {
642       switch (allow_syms) {
643       case 0:
644         return _("bit,base out of range for symbol");
645       case 1:
646         break;
647       case 2:
648         if (strncmp (newp, "[sb]", 4) != 0)
649           return _("bit,base out of range for symbol");
650         break;
651       }
652     }
654   *valuep = bitbase;
655   *strp = newp;
656   return 0;
659 static const char *
660 parse_signed_bitbase (CGEN_CPU_DESC cd, const char **strp,
661                       int opindex, signed long *valuep,
662                       unsigned bits, int allow_syms)
664   const char *errmsg = 0;
665   unsigned long bit;
666   signed long base;
667   const char *newp = *strp;
668   long long bitbase;
669   long long limit;
670   long have_zero = 0;
672   errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & bit);
673   if (errmsg)
674     return errmsg;
676   if (*newp != ',')
677     return "Missing base for bit,base:8";
679   ++newp;
681   if (strncmp (newp, "0x0", 3) == 0 
682       || (newp[0] == '0' && newp[1] != 'x'))
683     have_zero = 1;
685   errmsg = cgen_parse_signed_integer (cd, & newp, opindex, & base);
686   if (errmsg)
687     return errmsg;
689   bitbase = (long long)bit + ((long long)base * 8);
691   limit = 1ll << (bits - 1);
692   if (bitbase < -limit || bitbase >= limit)
693     return _("bit,base is out of range");
695   /* If this field may require a relocation then use larger displacement.  */
696   if (! have_zero && base == 0 && ! allow_syms)
697     return _("bit,base out of range for symbol");
699   *valuep = bitbase;
700   *strp = newp;
701   return 0;
704 static const char *
705 parse_unsigned_bitbase8 (CGEN_CPU_DESC cd, const char **strp,
706                          int opindex, unsigned long *valuep)
708   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 8, 0);
711 static const char *
712 parse_unsigned_bitbase11 (CGEN_CPU_DESC cd, const char **strp,
713                          int opindex, unsigned long *valuep)
715   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 11, 0);
718 static const char *
719 parse_unsigned_bitbase16 (CGEN_CPU_DESC cd, const char **strp,
720                           int opindex, unsigned long *valuep)
722   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 16, 1);
725 static const char *
726 parse_unsigned_bitbase19 (CGEN_CPU_DESC cd, const char **strp,
727                          int opindex, unsigned long *valuep)
729   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 19, 2);
732 static const char *
733 parse_unsigned_bitbase27 (CGEN_CPU_DESC cd, const char **strp,
734                          int opindex, unsigned long *valuep)
736   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 27, 1);
739 static const char *
740 parse_signed_bitbase8 (CGEN_CPU_DESC cd, const char **strp,
741                        int opindex, signed long *valuep)
743   return parse_signed_bitbase (cd, strp, opindex, valuep, 8, 1);
746 static const char *
747 parse_signed_bitbase11 (CGEN_CPU_DESC cd, const char **strp,
748                        int opindex, signed long *valuep)
750   return parse_signed_bitbase (cd, strp, opindex, valuep, 11, 0);
753 static const char *
754 parse_signed_bitbase19 (CGEN_CPU_DESC cd, const char **strp,
755                        int opindex, signed long *valuep)
757   return parse_signed_bitbase (cd, strp, opindex, valuep, 19, 1);
760 /* Parse the suffix as :<char> or as nothing followed by a whitespace.  */
762 static const char *
763 parse_suffix (const char **strp, char suffix)
765   const char *newp = *strp;
766   
767   if (**strp == ':' && TOLOWER (*(*strp + 1)) == suffix)
768     newp = *strp + 2;
770   if (ISSPACE (*newp))
771     {
772       *strp = newp;
773       return 0;
774     }
775         
776   return "Invalid suffix"; /* Anything -- will not be seen.  */
779 static const char *
780 parse_S (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
781          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
783   return parse_suffix (strp, 's');
786 static const char *
787 parse_G (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
788          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
790   return parse_suffix (strp, 'g');
793 static const char *
794 parse_Q (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
795          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
797   return parse_suffix (strp, 'q');
800 static const char *
801 parse_Z (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
802          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
804   return parse_suffix (strp, 'z');
807 /* Parse an empty suffix. Fail if the next char is ':'.  */
809 static const char *
810 parse_X (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
811          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
813   if (**strp == ':')
814     return "Unexpected suffix";
815   return 0;
818 static const char *
819 parse_r0l_r0h (CGEN_CPU_DESC cd, const char **strp,
820                int opindex ATTRIBUTE_UNUSED, signed long *valuep)
822   const char *errmsg;
823   signed long value;
824   signed long junk;
825   const char *newp = *strp;
827   /* Parse r0[hl].  */
828   errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0l_r0h, & value);
829   if (errmsg)
830     return errmsg;
832   if (*newp != ',')
833     return _("not a valid r0l/r0h pair");
834   ++newp;
836   /* Parse the second register in the pair.  */
837   if (value == 0) /* r0l */
838     errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0h, & junk);
839   else
840     errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0l, & junk);
841   if (errmsg)
842     return errmsg;
844   *strp = newp;
845   *valuep = ! value;
846   return 0;
849 /* Accept .b or .w in any case.  */
851 static const char *
852 parse_size (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
853             int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
855   if (**strp == '.'
856       && (*(*strp + 1) == 'b' || *(*strp + 1) == 'B'
857           || *(*strp + 1) == 'w' || *(*strp + 1) == 'W'))
858     {
859       *strp += 2;
860       return NULL;
861     }
863   return _("Invalid size specifier");
866 /* Special check to ensure that instruction exists for given machine.  */
869 m32c_cgen_insn_supported (CGEN_CPU_DESC cd,
870                           const CGEN_INSN *insn)
872   int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
873   CGEN_BITSET isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA);
875   /* If attributes are absent, assume no restriction.  */
876   if (machs == 0)
877     machs = ~0;
879   return ((machs & cd->machs)
880           && cgen_bitset_intersect_p (& isas, cd->isas));
883 /* Parse a set of registers, R0,R1,A0,A1,SB,FB.  */
885 static const char *
886 parse_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
887               const char **strp,
888               int opindex ATTRIBUTE_UNUSED,
889               unsigned long *valuep,
890               int push)
892   const char *errmsg = 0;
893   int regno = 0;
895   *valuep = 0;
896   while (**strp && **strp != ')')
897     {
898       if (**strp == 'r' || **strp == 'R')
899         {
900           ++*strp;
901           regno = **strp - '0';
902           if (regno > 4)
903             errmsg = _("Register number is not valid");
904         }
905       else if (**strp == 'a' || **strp == 'A')
906         {
907           ++*strp;
908           regno = **strp - '0';
909           if (regno > 2)
910             errmsg = _("Register number is not valid");
911           regno = **strp - '0' + 4;
912         }
913       
914       else if (strncasecmp (*strp, "sb", 2) == 0 || strncasecmp (*strp, "SB", 2) == 0)
915         {
916           regno = 6;
917           ++*strp;
918         }
919       
920       else if (strncasecmp (*strp, "fb", 2) == 0 || strncasecmp (*strp, "FB", 2) == 0)
921         {
922           regno = 7;
923           ++*strp;
924         }
925       
926       if (push) /* Mask is reversed for push.  */
927         *valuep |= 0x80 >> regno;
928       else
929         *valuep |= 1 << regno;
931       ++*strp;
932       if (**strp == ',')
933         {
934           if (*(*strp + 1) == ')')
935             break;
936           ++*strp;
937         }
938     }
940   if (!*strp)
941     errmsg = _("Register list is not valid");
943   return errmsg;
946 #define POP  0
947 #define PUSH 1
949 static const char *
950 parse_pop_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
951                   const char **strp,
952                   int opindex ATTRIBUTE_UNUSED,
953                   unsigned long *valuep)
955   return parse_regset (cd, strp, opindex, valuep, POP);
958 static const char *
959 parse_push_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
960                    const char **strp,
961                    int opindex ATTRIBUTE_UNUSED,
962                    unsigned long *valuep)
964   return parse_regset (cd, strp, opindex, valuep, PUSH);
967 /* -- dis.c */
969 #include "elf/m32c.h"
970 #include "elf-bfd.h"
972 /* Always print the short insn format suffix as ':<char>'.  */
974 static void
975 print_suffix (void * dis_info, char suffix)
977   disassemble_info *info = dis_info;
979   (*info->fprintf_func) (info->stream, ":%c", suffix);
982 static void
983 print_S (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
984          void * dis_info,
985          long value ATTRIBUTE_UNUSED,
986          unsigned int attrs ATTRIBUTE_UNUSED,
987          bfd_vma pc ATTRIBUTE_UNUSED,
988          int length ATTRIBUTE_UNUSED)
990   print_suffix (dis_info, 's');
994 static void
995 print_G (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
996          void * dis_info,
997          long value ATTRIBUTE_UNUSED,
998          unsigned int attrs ATTRIBUTE_UNUSED,
999          bfd_vma pc ATTRIBUTE_UNUSED,
1000          int length ATTRIBUTE_UNUSED)
1002   print_suffix (dis_info, 'g');
1005 static void
1006 print_Q (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1007          void * dis_info,
1008          long value ATTRIBUTE_UNUSED,
1009          unsigned int attrs ATTRIBUTE_UNUSED,
1010          bfd_vma pc ATTRIBUTE_UNUSED,
1011          int length ATTRIBUTE_UNUSED)
1013   print_suffix (dis_info, 'q');
1016 static void
1017 print_Z (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1018          void * dis_info,
1019          long value ATTRIBUTE_UNUSED,
1020          unsigned int attrs ATTRIBUTE_UNUSED,
1021          bfd_vma pc ATTRIBUTE_UNUSED,
1022          int length ATTRIBUTE_UNUSED)
1024   print_suffix (dis_info, 'z');
1027 /* Print the empty suffix.  */
1029 static void
1030 print_X (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1031          void * dis_info ATTRIBUTE_UNUSED,
1032          long value ATTRIBUTE_UNUSED,
1033          unsigned int attrs ATTRIBUTE_UNUSED,
1034          bfd_vma pc ATTRIBUTE_UNUSED,
1035          int length ATTRIBUTE_UNUSED)
1037   return;
1040 static void
1041 print_r0l_r0h (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1042                void * dis_info,
1043                long value,
1044                unsigned int attrs ATTRIBUTE_UNUSED,
1045                bfd_vma pc ATTRIBUTE_UNUSED,
1046                int length ATTRIBUTE_UNUSED)
1048   disassemble_info *info = dis_info;
1050   if (value == 0)
1051     (*info->fprintf_func) (info->stream, "r0h,r0l");
1052   else
1053     (*info->fprintf_func) (info->stream, "r0l,r0h");
1056 static void
1057 print_unsigned_bitbase (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1058                         void * dis_info,
1059                         unsigned long value,
1060                         unsigned int attrs ATTRIBUTE_UNUSED,
1061                         bfd_vma pc ATTRIBUTE_UNUSED,
1062                         int length ATTRIBUTE_UNUSED)
1064   disassemble_info *info = dis_info;
1066   (*info->fprintf_func) (info->stream, "%ld,0x%lx", value & 0x7, value >> 3);
1069 static void
1070 print_signed_bitbase (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1071                       void * dis_info,
1072                       signed long value,
1073                       unsigned int attrs ATTRIBUTE_UNUSED,
1074                       bfd_vma pc ATTRIBUTE_UNUSED,
1075                       int length ATTRIBUTE_UNUSED)
1077   disassemble_info *info = dis_info;
1079   (*info->fprintf_func) (info->stream, "%ld,%ld", value & 0x7, value >> 3);
1082 static void
1083 print_size (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1084             void * dis_info,
1085             long value ATTRIBUTE_UNUSED,
1086             unsigned int attrs ATTRIBUTE_UNUSED,
1087             bfd_vma pc ATTRIBUTE_UNUSED,
1088             int length ATTRIBUTE_UNUSED)
1090   /* Always print the size as '.w'.  */
1091   disassemble_info *info = dis_info;
1093   (*info->fprintf_func) (info->stream, ".w");
1096 #define POP  0
1097 #define PUSH 1
1099 static void print_pop_regset  (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
1100 static void print_push_regset (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
1102 /* Print a set of registers, R0,R1,A0,A1,SB,FB.  */
1104 static void
1105 print_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1106               void * dis_info,
1107               long value,
1108               unsigned int attrs ATTRIBUTE_UNUSED,
1109               bfd_vma pc ATTRIBUTE_UNUSED,
1110               int length ATTRIBUTE_UNUSED,
1111               int push)
1113   static char * m16c_register_names [] = 
1114   {
1115     "r0", "r1", "r2", "r3", "a0", "a1", "sb", "fb"
1116   };
1117   disassemble_info *info = dis_info;
1118   int mask;
1119   int reg_index = 0;
1120   char* comma = "";
1122   if (push)
1123     mask = 0x80;
1124   else
1125     mask = 1;
1127   if (value & mask)
1128     {
1129       (*info->fprintf_func) (info->stream, "%s", m16c_register_names [0]);
1130       comma = ",";
1131     }
1133   for (reg_index = 1; reg_index <= 7; ++reg_index)
1134     {
1135       if (push)
1136         mask >>= 1;
1137       else
1138         mask <<= 1;
1140       if (value & mask)
1141         {
1142           (*info->fprintf_func) (info->stream, "%s%s", comma,
1143                                  m16c_register_names [reg_index]);
1144           comma = ",";
1145         }
1146     }
1149 static void
1150 print_pop_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1151                   void * dis_info,
1152                   long value,
1153                   unsigned int attrs ATTRIBUTE_UNUSED,
1154                   bfd_vma pc ATTRIBUTE_UNUSED,
1155                   int length ATTRIBUTE_UNUSED)
1157   print_regset (cd, dis_info, value, attrs, pc, length, POP);
1160 static void
1161 print_push_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1162                    void * dis_info,
1163                    long value,
1164                    unsigned int attrs ATTRIBUTE_UNUSED,
1165                    bfd_vma pc ATTRIBUTE_UNUSED,
1166                    int length ATTRIBUTE_UNUSED)
1168   print_regset (cd, dis_info, value, attrs, pc, length, PUSH);
1171 static void
1172 print_signed4n (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1173                 void * dis_info,
1174                 signed long value,
1175                 unsigned int attrs ATTRIBUTE_UNUSED,
1176                 bfd_vma pc ATTRIBUTE_UNUSED,
1177                 int length ATTRIBUTE_UNUSED)
1179   disassemble_info *info = dis_info;
1181   (*info->fprintf_func) (info->stream, "%ld", -value);