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