OSDN Git Service

* m32c.cpu (jsri): Fix order so register names aren't treated as
[pf3gnuchains/pf3gnuchains4x.git] / cpu / m32c.opc
1 /* m32c opcode support.  -*- C -*-
2
3    Copyright 2005 Free Software Foundation, Inc.
4
5    Contributed by Red Hat Inc; developed under contract from Renesas
6
7    This file is part of the GNU Binutils.
8
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.
13
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.
18
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.  */
22
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.
29
30    Each section is delimited with start and end markers.
31
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".  */
37 \f
38 /* -- opc.h */
39
40 /* Needed for RTL's 'ext' and 'trunc' operators.  */
41 #include "cgen-types.h"
42 #include "cgen-ops.h"
43
44 /* We can't use the default hash size because many bits are used by
45    operands.  */
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
50
51 extern int m32c_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
52
53 #define CGEN_ASM_HASH_SIZE 0xffff
54 #define CGEN_ASM_HASH(mnem) m32c_asm_hash ((mnem))
55
56 /* -- */
57 \f
58 /* -- opc.c */
59 static unsigned int
60 m32c_asm_hash (const char *mnem)
61 {
62   unsigned int h;
63   
64   /* The length of the mnemonic for the Jcnd insns is 1.  Hash jsri.  */
65   if (mnem[0] == 'j' && mnem[1] != 's')
66     return 'j';
67   
68   /* Don't hash scCND  */
69   if (mnem[0] == 's' && mnem[1] == 'c')
70     return 's';
71   
72   /* Don't hash bmCND  */
73   if (mnem[0] == 'b' && mnem[1] == 'm')
74     return 'b';
75   
76   for (h = 0; *mnem && *mnem != ' ' && *mnem != ':'; ++mnem)
77     h += *mnem;
78   return h % CGEN_ASM_HASH_SIZE;
79 }
80 \f
81 /* -- asm.c */
82 #include "safe-ctype.h"
83
84 #define MACH_M32C 5             /* Must match md_begin.  */
85
86 static int
87 m32c_cgen_isa_register (const char **strp)
88  {
89    int u;
90    const char *s = *strp;
91    static char * m32c_register_names [] = 
92      {
93        "r0", "r1", "r2", "r3", "r0l", "r0h", "r1l", "r1h",
94        "a0", "a1", "r2r0", "r3r1", "sp", "fb", "dct0", "dct1", "flg", "svf",
95        "drc0", "drc1", "dmd0", "dmd1", "intb", "svp", "vct", "isp", "dma0",
96        "dma1", "dra0", "dra1", "dsa0", "dsa1", 0
97      };
98  
99    for (u = 0; m32c_register_names[u]; u++)
100      {
101        int len = strlen (m32c_register_names[u]);
102
103        if (memcmp (m32c_register_names[u], s, len) == 0
104            && (s[len] == 0 || ! ISALNUM (s[len])))
105         return 1;
106      }
107    return 0;
108 }
109
110 #define PARSE_UNSIGNED                                                  \
111   do                                                                    \
112     {                                                                   \
113       /* Don't successfully parse literals beginning with '['.  */      \
114       if (**strp == '[')                                                \
115         return "Invalid literal"; /* Anything -- will not be seen.  */  \
116                                                                         \
117       errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);\
118       if (errmsg)                                                       \
119         return errmsg;                                                  \
120     }                                                                   \
121   while (0)
122
123 #define PARSE_SIGNED                                                    \
124   do                                                                    \
125     {                                                                   \
126       /* Don't successfully parse literals beginning with '['.  */      \
127       if (**strp == '[')                                                \
128         return "Invalid literal"; /* Anything -- will not be seen.  */  \
129                                                                         \
130       errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);  \
131       if (errmsg)                                                       \
132         return errmsg;                                                  \
133     }                                                                   \
134   while (0)
135
136 static const char *
137 parse_unsigned6 (CGEN_CPU_DESC cd, const char **strp,
138                  int opindex, unsigned long *valuep)
139 {
140   const char *errmsg = 0;
141   unsigned long value;
142
143   PARSE_UNSIGNED;
144
145   if (value > 0x3f)
146     return _("imm:6 immediate is out of range");
147
148   *valuep = value;
149   return 0;
150 }
151
152 static const char *
153 parse_unsigned8 (CGEN_CPU_DESC cd, const char **strp,
154                  int opindex, unsigned long *valuep)
155 {
156   const char *errmsg = 0;
157   unsigned long value;
158   long have_zero = 0;
159
160   if (strncasecmp (*strp, "%dsp8(", 6) == 0)
161     {
162       enum cgen_parse_operand_result result_type;
163       bfd_vma value;
164       const char *errmsg;
165
166       *strp += 6;
167       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_8,
168                                    & result_type, & value);
169       if (**strp != ')')
170         return _("missing `)'");
171       (*strp) ++;
172
173       if (errmsg == NULL
174           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
175         {
176           return _("%dsp8() takes a symbolic address, not a number");
177         }
178       *valuep = value;
179       return errmsg;
180     }
181
182   if (strncmp (*strp, "0x0", 3) == 0 
183       || (**strp == '0' && *(*strp + 1) != 'x'))
184     have_zero = 1;
185
186   PARSE_UNSIGNED;
187
188   if (value > 0xff)
189     return _("dsp:8 immediate is out of range");
190
191   /* If this field may require a relocation then use larger dsp16.  */
192   if (! have_zero && value == 0)
193     return _("dsp:8 immediate is out of range");
194
195   *valuep = value;
196   return 0;
197 }
198
199 static const char *
200 parse_signed4 (CGEN_CPU_DESC cd, const char **strp,
201                int opindex, signed long *valuep)
202 {
203   const char *errmsg = 0;
204   signed long value;
205   long have_zero = 0;
206
207   if (strncmp (*strp, "0x0", 3) == 0 
208       || (**strp == '0' && *(*strp + 1) != 'x'))
209     have_zero = 1;
210
211   PARSE_SIGNED;
212
213   if (value < -8 || value > 7)
214     return _("Immediate is out of range -8 to 7");
215
216   /* If this field may require a relocation then use larger dsp16.  */
217   if (! have_zero && value == 0)
218     return _("Immediate is out of range -8 to 7");
219
220   *valuep = value;
221   return 0;
222 }
223
224 static const char *
225 parse_signed4n (CGEN_CPU_DESC cd, const char **strp,
226                 int opindex, signed long *valuep)
227 {
228   const char *errmsg = 0;
229   signed long value;
230   long have_zero = 0;
231
232   if (strncmp (*strp, "0x0", 3) == 0 
233       || (**strp == '0' && *(*strp + 1) != 'x'))
234     have_zero = 1;
235
236   PARSE_SIGNED;
237
238   if (value < -7 || value > 8)
239     return _("Immediate is out of range -7 to 8");
240
241   /* If this field may require a relocation then use larger dsp16.  */
242   if (! have_zero && value == 0)
243     return _("Immediate is out of range -7 to 8");
244
245   *valuep = -value;
246   return 0;
247 }
248
249 static const char *
250 parse_signed8 (CGEN_CPU_DESC cd, const char **strp,
251                int opindex, signed long *valuep)
252 {
253   const char *errmsg = 0;
254   signed long value;
255
256   if (strncasecmp (*strp, "%hi8(", 5) == 0)
257     {
258       enum cgen_parse_operand_result result_type;
259       bfd_vma value;
260       const char *errmsg;
261
262       *strp += 5;
263       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32C_HI8,
264                                    & result_type, & value);
265       if (**strp != ')')
266         return _("missing `)'");
267       (*strp) ++;
268
269       if (errmsg == NULL
270           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
271         {
272           value >>= 16;
273         }
274       *valuep = value;
275       return errmsg;
276     }
277
278   PARSE_SIGNED;
279
280   if (value <= 255 && value > 127)
281     value -= 0x100;
282
283   if (value < -128 || value > 127)
284     return _("dsp:8 immediate is out of range");
285
286   *valuep = value;
287   return 0;
288 }
289
290 static const char *
291 parse_unsigned16 (CGEN_CPU_DESC cd, const char **strp,
292                  int opindex, unsigned long *valuep)
293 {
294   const char *errmsg = 0;
295   unsigned long value;
296   long have_zero = 0;
297
298   if (strncasecmp (*strp, "%dsp16(", 7) == 0)
299     {
300       enum cgen_parse_operand_result result_type;
301       bfd_vma value;
302       const char *errmsg;
303
304       *strp += 7;
305       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_16,
306                                    & result_type, & value);
307       if (**strp != ')')
308         return _("missing `)'");
309       (*strp) ++;
310
311       if (errmsg == NULL
312           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
313         {
314           return _("%dsp16() takes a symbolic address, not a number");
315         }
316       *valuep = value;
317       return errmsg;
318     }
319
320   /* Don't successfully parse literals beginning with '['.  */
321   if (**strp == '[')
322     return "Invalid literal"; /* Anything -- will not be seen.  */
323
324   /* Don't successfully parse register names.  */
325   if (m32c_cgen_isa_register (strp))
326     return "Invalid literal"; /* Anything -- will not be seen.  */
327
328   if (strncmp (*strp, "0x0", 3) == 0 
329       || (**strp == '0' && *(*strp + 1) != 'x'))
330     have_zero = 1;
331   
332   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
333   if (errmsg)
334     return errmsg;
335
336   if (value > 0xffff)
337     return _("dsp:16 immediate is out of range");
338
339   /* If this field may require a relocation then use larger dsp24.  */
340   if (cd->machs == MACH_M32C && ! have_zero && value == 0
341       && (strncmp (*strp, "[a", 2) == 0
342           || **strp == ','
343           || **strp == 0))
344     return _("dsp:16 immediate is out of range");
345
346   *valuep = value;
347   return 0;
348 }
349
350 static const char *
351 parse_signed16 (CGEN_CPU_DESC cd, const char **strp,
352                int opindex, signed long *valuep)
353 {
354   const char *errmsg = 0;
355   signed long value;
356
357   if (strncasecmp (*strp, "%lo16(", 6) == 0)
358     {
359       enum cgen_parse_operand_result result_type;
360       bfd_vma value;
361       const char *errmsg;
362
363       *strp += 6;
364       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
365                                    & result_type, & value);
366       if (**strp != ')')
367         return _("missing `)'");
368       (*strp) ++;
369
370       if (errmsg == NULL
371           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
372         {
373           value &= 0xffff;
374         }
375       *valuep = value;
376       return errmsg;
377     }
378
379   if (strncasecmp (*strp, "%hi16(", 6) == 0)
380     {
381       enum cgen_parse_operand_result result_type;
382       bfd_vma value;
383       const char *errmsg;
384
385       *strp += 6;
386       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16,
387                                    & result_type, & value);
388       if (**strp != ')')
389         return _("missing `)'");
390       (*strp) ++;
391
392       if (errmsg == NULL
393           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
394         {
395           value >>= 16;
396         }
397       *valuep = value;
398       return errmsg;
399     }
400
401   PARSE_SIGNED;
402
403   if (value <= 65535 && value > 32767)
404     value -= 0x10000;
405
406   if (value < -32768 || value > 32767)
407     return _("dsp:16 immediate is out of range");
408
409   *valuep = value;
410   return 0;
411 }
412
413 static const char *
414 parse_unsigned20 (CGEN_CPU_DESC cd, const char **strp,
415                  int opindex, unsigned long *valuep)
416 {
417   const char *errmsg = 0;
418   unsigned long value;
419   
420   /* Don't successfully parse literals beginning with '['.  */
421   if (**strp == '[')
422     return "Invalid literal"; /* Anything -- will not be seen.  */
423
424   /* Don't successfully parse register names.  */
425   if (m32c_cgen_isa_register (strp))
426     return "Invalid literal"; /* Anything -- will not be seen.  */
427
428   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
429   if (errmsg)
430     return errmsg;
431
432   if (value > 0xfffff)
433     return _("dsp:20 immediate is out of range");
434
435   *valuep = value;
436   return 0;
437 }
438
439 static const char *
440 parse_unsigned24 (CGEN_CPU_DESC cd, const char **strp,
441                  int opindex, unsigned long *valuep)
442 {
443   const char *errmsg = 0;
444   unsigned long value;
445   
446   /* Don't successfully parse literals beginning with '['.  */
447   if (**strp == '[')
448     return "Invalid literal"; /* Anything -- will not be seen.  */
449
450   /* Don't successfully parse register names.  */
451   if (m32c_cgen_isa_register (strp))
452     return "Invalid literal"; /* Anything -- will not be seen.  */
453
454   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
455   if (errmsg)
456     return errmsg;
457
458   if (value > 0xffffff)
459     return _("dsp:24 immediate is out of range");
460
461   *valuep = value;
462   return 0;
463 }
464
465 /* This should only be used for #imm->reg.  */
466 static const char *
467 parse_signed24 (CGEN_CPU_DESC cd, const char **strp,
468                  int opindex, signed long *valuep)
469 {
470   const char *errmsg = 0;
471   signed long value;
472
473   PARSE_SIGNED;
474
475   if (value <= 0xffffff && value > 0x7fffff)
476     value -= 0x1000000;
477
478   if (value > 0xffffff)
479     return _("dsp:24 immediate is out of range");
480
481   *valuep = value;
482   return 0;
483 }
484
485 static const char *
486 parse_signed32 (CGEN_CPU_DESC cd, const char **strp,
487                 int opindex, signed long *valuep)
488 {
489   const char *errmsg = 0;
490   signed long value;
491   
492   errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
493   if (errmsg)
494     return errmsg;
495
496   *valuep = value;
497   return 0;
498 }
499
500 static const char *
501 parse_imm1_S (CGEN_CPU_DESC cd, const char **strp,
502              int opindex, signed long *valuep)
503 {
504   const char *errmsg = 0;
505   signed long value;
506
507   errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
508   if (errmsg)
509     return errmsg;
510
511   if (value < 1 || value > 2)
512     return _("immediate is out of range 1-2");
513
514   *valuep = value;
515   return 0;
516 }
517
518 static const char *
519 parse_imm3_S (CGEN_CPU_DESC cd, const char **strp,
520              int opindex, signed long *valuep)
521 {
522   const char *errmsg = 0;
523   signed long value;
524   
525   errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
526   if (errmsg)
527     return errmsg;
528
529   if (value < 1 || value > 8)
530     return _("immediate is out of range 1-8");
531
532   *valuep = value;
533   return 0;
534 }
535
536 static const char *
537 parse_lab_5_3 (CGEN_CPU_DESC cd,
538                const char **strp,
539                int opindex ATTRIBUTE_UNUSED,
540                int opinfo,
541                enum cgen_parse_operand_result *type_addr,
542                bfd_vma *valuep)
543 {
544   const char *errmsg = 0;
545   bfd_vma value;
546   enum cgen_parse_operand_result op_res;
547
548   errmsg = cgen_parse_address (cd, strp, M32C_OPERAND_LAB_5_3,
549                                opinfo, & op_res, & value);
550
551   if (type_addr)
552     *type_addr = op_res;
553
554   if (op_res == CGEN_PARSE_OPERAND_ADDRESS)
555     {
556       /* This is a hack; the field cannot handle near-zero signed
557          offsets that CGEN wants to put in to indicate an "empty"
558          operand at first.  */
559       *valuep = 2;
560       return 0;
561     }
562   if (errmsg)
563     return errmsg;
564
565   if (value < 2 || value > 9)
566     return _("immediate is out of range 2-9");
567
568   *valuep = value;
569   return 0;
570 }
571
572 static const char *
573 parse_Bitno16R (CGEN_CPU_DESC cd, const char **strp,
574                 int opindex, unsigned long *valuep)
575 {
576   const char *errmsg = 0;
577   unsigned long value;
578
579   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
580   if (errmsg)
581     return errmsg;
582
583   if (value > 15)
584     return _("Bit number for indexing general register is out of range 0-15");
585
586   *valuep = value;
587   return 0;
588 }
589
590 static const char *
591 parse_unsigned_bitbase (CGEN_CPU_DESC cd, const char **strp,
592                         int opindex, unsigned long *valuep,
593                         unsigned bits)
594 {
595   const char *errmsg = 0;
596   unsigned long bit;
597   unsigned long base;
598   const char *newp = *strp;
599   unsigned long long bitbase;
600
601   errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & bit);
602   if (errmsg)
603     return errmsg;
604
605   if (*newp != ',')
606     return "Missing base for bit,base:8";
607
608   ++newp;
609   errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & base);
610   if (errmsg)
611     return errmsg;
612
613   bitbase = (unsigned long long) bit + ((unsigned long long) base * 8);
614
615   if (bitbase >= (1ull << bits))
616     return _("bit,base is out of range");
617
618   *valuep = bitbase;
619   *strp = newp;
620   return 0;
621 }
622
623 static const char *
624 parse_signed_bitbase (CGEN_CPU_DESC cd, const char **strp,
625                       int opindex, signed long *valuep,
626                       unsigned bits)
627 {
628   const char *errmsg = 0;
629   unsigned long bit;
630   signed long base;
631   const char *newp = *strp;
632   long long bitbase;
633   long long limit;
634
635   errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & bit);
636   if (errmsg)
637     return errmsg;
638
639   if (*newp != ',')
640     return "Missing base for bit,base:8";
641
642   ++newp;
643   errmsg = cgen_parse_signed_integer (cd, & newp, opindex, & base);
644   if (errmsg)
645     return errmsg;
646
647   bitbase = (long long)bit + ((long long)base * 8);
648
649   limit = 1ll << (bits - 1);
650   if (bitbase < -limit || bitbase >= limit)
651     return _("bit,base is out of range");
652
653   *valuep = bitbase;
654   *strp = newp;
655   return 0;
656 }
657
658 static const char *
659 parse_unsigned_bitbase8 (CGEN_CPU_DESC cd, const char **strp,
660                          int opindex, unsigned long *valuep)
661 {
662   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 8);
663 }
664
665 static const char *
666 parse_unsigned_bitbase11 (CGEN_CPU_DESC cd, const char **strp,
667                          int opindex, unsigned long *valuep)
668 {
669   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 11);
670 }
671
672 static const char *
673 parse_unsigned_bitbase16 (CGEN_CPU_DESC cd, const char **strp,
674                           int opindex, unsigned long *valuep)
675 {
676   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 16);
677 }
678
679 static const char *
680 parse_unsigned_bitbase19 (CGEN_CPU_DESC cd, const char **strp,
681                          int opindex, unsigned long *valuep)
682 {
683   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 19);
684 }
685
686 static const char *
687 parse_unsigned_bitbase27 (CGEN_CPU_DESC cd, const char **strp,
688                          int opindex, unsigned long *valuep)
689 {
690   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 27);
691 }
692
693 static const char *
694 parse_signed_bitbase8 (CGEN_CPU_DESC cd, const char **strp,
695                        int opindex, signed long *valuep)
696 {
697   return parse_signed_bitbase (cd, strp, opindex, valuep, 8);
698 }
699
700 static const char *
701 parse_signed_bitbase11 (CGEN_CPU_DESC cd, const char **strp,
702                        int opindex, signed long *valuep)
703 {
704   return parse_signed_bitbase (cd, strp, opindex, valuep, 11);
705 }
706
707 static const char *
708 parse_signed_bitbase19 (CGEN_CPU_DESC cd, const char **strp,
709                        int opindex, signed long *valuep)
710 {
711   return parse_signed_bitbase (cd, strp, opindex, valuep, 19);
712 }
713
714 /* Parse the suffix as :<char> or as nothing followed by a whitespace.  */
715
716 static const char *
717 parse_suffix (const char **strp, char suffix)
718 {
719   const char *newp = *strp;
720   
721   if (**strp == ':' && TOLOWER (*(*strp + 1)) == suffix)
722     newp = *strp + 2;
723
724   if (ISSPACE (*newp))
725     {
726       *strp = newp;
727       return 0;
728     }
729         
730   return "Invalid suffix"; /* Anything -- will not be seen.  */
731 }
732
733 static const char *
734 parse_S (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
735          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
736 {
737   return parse_suffix (strp, 's');
738 }
739
740 static const char *
741 parse_G (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
742          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
743 {
744   return parse_suffix (strp, 'g');
745 }
746
747 static const char *
748 parse_Q (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
749          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
750 {
751   return parse_suffix (strp, 'q');
752 }
753
754 static const char *
755 parse_Z (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
756          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
757 {
758   return parse_suffix (strp, 'z');
759 }
760
761 /* Parse an empty suffix. Fail if the next char is ':'.  */
762
763 static const char *
764 parse_X (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
765          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
766 {
767   if (**strp == ':')
768     return "Unexpected suffix";
769   return 0;
770 }
771
772 static const char *
773 parse_r0l_r0h (CGEN_CPU_DESC cd, const char **strp,
774                int opindex ATTRIBUTE_UNUSED, signed long *valuep)
775 {
776   const char *errmsg;
777   signed long value;
778   signed long junk;
779   const char *newp = *strp;
780
781   /* Parse r0[hl].  */
782   errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0l_r0h, & value);
783   if (errmsg)
784     return errmsg;
785
786   if (*newp != ',')
787     return _("not a valid r0l/r0h pair");
788   ++newp;
789
790   /* Parse the second register in the pair.  */
791   if (value == 0) /* r0l */
792     errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0h, & junk);
793   else
794     errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0l, & junk);
795   if (errmsg)
796     return errmsg;
797
798   *strp = newp;
799   *valuep = ! value;
800   return 0;
801 }
802
803 /* Accept .b or .w in any case.  */
804
805 static const char *
806 parse_size (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
807             int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
808 {
809   if (**strp == '.'
810       && (*(*strp + 1) == 'b' || *(*strp + 1) == 'B'
811           || *(*strp + 1) == 'w' || *(*strp + 1) == 'W'))
812     {
813       *strp += 2;
814       return NULL;
815     }
816
817   return _("Invalid size specifier");
818 }
819
820 /* Special check to ensure that instruction exists for given machine.  */
821
822 int
823 m32c_cgen_insn_supported (CGEN_CPU_DESC cd,
824                           const CGEN_INSN *insn)
825 {
826   int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
827   CGEN_BITSET isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA);
828
829   /* If attributes are absent, assume no restriction.  */
830   if (machs == 0)
831     machs = ~0;
832
833   return ((machs & cd->machs)
834           && cgen_bitset_intersect_p (& isas, cd->isas));
835 }
836
837 /* Parse a set of registers, R0,R1,A0,A1,SB,FB.  */
838
839 static const char *
840 parse_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
841               const char **strp,
842               int opindex ATTRIBUTE_UNUSED,
843               unsigned long *valuep,
844               int push)
845 {
846   const char *errmsg = 0;
847   int regno = 0;
848  
849   *valuep = 0;
850   while (**strp && **strp != ')')
851     {
852       if (**strp == 'r' || **strp == 'R')
853         {
854           ++*strp;
855           regno = **strp - '0';
856           if (regno > 4)
857             errmsg = _("Register number is not valid");
858         }
859       else if (**strp == 'a' || **strp == 'A')
860         {
861           ++*strp;
862           regno = **strp - '0';
863           if (regno > 2)
864             errmsg = _("Register number is not valid");
865           regno = **strp - '0' + 4;
866         }
867       
868       else if (strncasecmp (*strp, "sb", 2) == 0 || strncasecmp (*strp, "SB", 2) == 0)
869         {
870           regno = 6;
871           ++*strp;
872         }
873       
874       else if (strncasecmp (*strp, "fb", 2) == 0 || strncasecmp (*strp, "FB", 2) == 0)
875         {
876           regno = 7;
877           ++*strp;
878         }
879       
880       if (push) /* Mask is reversed for push.  */
881         *valuep |= 0x80 >> regno;
882       else
883         *valuep |= 1 << regno;
884
885       ++*strp;
886       if (**strp == ',')
887         {
888           if (*(*strp + 1) == ')')
889             break;
890           ++*strp;
891         }
892     }
893
894   if (!*strp)
895     errmsg = _("Register list is not valid");
896
897   return errmsg;
898 }
899
900 #define POP  0
901 #define PUSH 1
902
903 static const char *
904 parse_pop_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
905                   const char **strp,
906                   int opindex ATTRIBUTE_UNUSED,
907                   unsigned long *valuep)
908 {
909   return parse_regset (cd, strp, opindex, valuep, POP);
910 }
911
912 static const char *
913 parse_push_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
914                    const char **strp,
915                    int opindex ATTRIBUTE_UNUSED,
916                    unsigned long *valuep)
917 {
918   return parse_regset (cd, strp, opindex, valuep, PUSH);
919 }
920
921 /* -- dis.c */
922
923 #include "elf/m32c.h"
924 #include "elf-bfd.h"
925
926 /* Always print the short insn format suffix as ':<char>'.  */
927
928 static void
929 print_suffix (void * dis_info, char suffix)
930 {
931   disassemble_info *info = dis_info;
932
933   (*info->fprintf_func) (info->stream, ":%c", suffix);
934 }
935
936 static void
937 print_S (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
938          void * dis_info,
939          long value ATTRIBUTE_UNUSED,
940          unsigned int attrs ATTRIBUTE_UNUSED,
941          bfd_vma pc ATTRIBUTE_UNUSED,
942          int length ATTRIBUTE_UNUSED)
943 {
944   print_suffix (dis_info, 's');
945 }
946
947
948 static void
949 print_G (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
950          void * dis_info,
951          long value ATTRIBUTE_UNUSED,
952          unsigned int attrs ATTRIBUTE_UNUSED,
953          bfd_vma pc ATTRIBUTE_UNUSED,
954          int length ATTRIBUTE_UNUSED)
955 {
956   print_suffix (dis_info, 'g');
957 }
958
959 static void
960 print_Q (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
961          void * dis_info,
962          long value ATTRIBUTE_UNUSED,
963          unsigned int attrs ATTRIBUTE_UNUSED,
964          bfd_vma pc ATTRIBUTE_UNUSED,
965          int length ATTRIBUTE_UNUSED)
966 {
967   print_suffix (dis_info, 'q');
968 }
969
970 static void
971 print_Z (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
972          void * dis_info,
973          long value ATTRIBUTE_UNUSED,
974          unsigned int attrs ATTRIBUTE_UNUSED,
975          bfd_vma pc ATTRIBUTE_UNUSED,
976          int length ATTRIBUTE_UNUSED)
977 {
978   print_suffix (dis_info, 'z');
979 }
980
981 /* Print the empty suffix.  */
982
983 static void
984 print_X (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
985          void * dis_info ATTRIBUTE_UNUSED,
986          long value ATTRIBUTE_UNUSED,
987          unsigned int attrs ATTRIBUTE_UNUSED,
988          bfd_vma pc ATTRIBUTE_UNUSED,
989          int length ATTRIBUTE_UNUSED)
990 {
991   return;
992 }
993
994 static void
995 print_r0l_r0h (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
996                void * dis_info,
997                long value,
998                unsigned int attrs ATTRIBUTE_UNUSED,
999                bfd_vma pc ATTRIBUTE_UNUSED,
1000                int length ATTRIBUTE_UNUSED)
1001 {
1002   disassemble_info *info = dis_info;
1003
1004   if (value == 0)
1005     (*info->fprintf_func) (info->stream, "r0h,r0l");
1006   else
1007     (*info->fprintf_func) (info->stream, "r0l,r0h");
1008 }
1009
1010 static void
1011 print_unsigned_bitbase (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1012                         void * dis_info,
1013                         unsigned long value,
1014                         unsigned int attrs ATTRIBUTE_UNUSED,
1015                         bfd_vma pc ATTRIBUTE_UNUSED,
1016                         int length ATTRIBUTE_UNUSED)
1017 {
1018   disassemble_info *info = dis_info;
1019
1020   (*info->fprintf_func) (info->stream, "%ld,0x%lx", value & 0x7, value >> 3);
1021 }
1022
1023 static void
1024 print_signed_bitbase (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1025                       void * dis_info,
1026                       signed long value,
1027                       unsigned int attrs ATTRIBUTE_UNUSED,
1028                       bfd_vma pc ATTRIBUTE_UNUSED,
1029                       int length ATTRIBUTE_UNUSED)
1030 {
1031   disassemble_info *info = dis_info;
1032
1033   (*info->fprintf_func) (info->stream, "%ld,%ld", value & 0x7, value >> 3);
1034 }
1035
1036 static void
1037 print_size (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1038             void * dis_info,
1039             long value ATTRIBUTE_UNUSED,
1040             unsigned int attrs ATTRIBUTE_UNUSED,
1041             bfd_vma pc ATTRIBUTE_UNUSED,
1042             int length ATTRIBUTE_UNUSED)
1043 {
1044   /* Always print the size as '.w'.  */
1045   disassemble_info *info = dis_info;
1046
1047   (*info->fprintf_func) (info->stream, ".w");
1048 }
1049
1050 #define POP  0
1051 #define PUSH 1
1052
1053 static void print_pop_regset  (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
1054 static void print_push_regset (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
1055
1056 /* Print a set of registers, R0,R1,A0,A1,SB,FB.  */
1057
1058 static void
1059 print_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1060               void * dis_info,
1061               long value,
1062               unsigned int attrs ATTRIBUTE_UNUSED,
1063               bfd_vma pc ATTRIBUTE_UNUSED,
1064               int length ATTRIBUTE_UNUSED,
1065               int push)
1066 {
1067   static char * m16c_register_names [] = 
1068   {
1069     "r0", "r1", "r2", "r3", "a0", "a1", "sb", "fb"
1070   };
1071   disassemble_info *info = dis_info;
1072   int mask;
1073   int index = 0;
1074   char* comma = "";
1075
1076   if (push)
1077     mask = 0x80;
1078   else
1079     mask = 1;
1080  
1081   if (value & mask)
1082     {
1083       (*info->fprintf_func) (info->stream, "%s", m16c_register_names [0]);
1084       comma = ",";
1085     }
1086
1087   for (index = 1; index <= 7; ++index)
1088     {
1089       if (push)
1090         mask >>= 1;
1091       else
1092         mask <<= 1;
1093
1094       if (value & mask)
1095         {
1096           (*info->fprintf_func) (info->stream, "%s%s", comma,
1097                                  m16c_register_names [index]);
1098           comma = ",";
1099         }
1100     }
1101 }
1102
1103 static void
1104 print_pop_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1105                   void * dis_info,
1106                   long value,
1107                   unsigned int attrs ATTRIBUTE_UNUSED,
1108                   bfd_vma pc ATTRIBUTE_UNUSED,
1109                   int length ATTRIBUTE_UNUSED)
1110 {
1111   print_regset (cd, dis_info, value, attrs, pc, length, POP);
1112 }
1113
1114 static void
1115 print_push_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1116                    void * dis_info,
1117                    long value,
1118                    unsigned int attrs ATTRIBUTE_UNUSED,
1119                    bfd_vma pc ATTRIBUTE_UNUSED,
1120                    int length ATTRIBUTE_UNUSED)
1121 {
1122   print_regset (cd, dis_info, value, attrs, pc, length, PUSH);
1123 }
1124
1125 static void
1126 print_signed4n (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1127                 void * dis_info,
1128                 signed long value,
1129                 unsigned int attrs ATTRIBUTE_UNUSED,
1130                 bfd_vma pc ATTRIBUTE_UNUSED,
1131                 int length ATTRIBUTE_UNUSED)
1132 {
1133   disassemble_info *info = dis_info;
1134
1135   (*info->fprintf_func) (info->stream, "%ld", -value);
1136 }