ef0ac3bde8cc09ad40d4cad947283e3c07bddf98
[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 /* This should only be used for #imm->reg.  */
437 static const char *
438 parse_signed24 (CGEN_CPU_DESC cd, const char **strp,
439                  int opindex, signed long *valuep)
440 {
441   const char *errmsg = 0;
442   signed long value;
443
444   PARSE_SIGNED;
445
446   if (value <= 0xffffff && value > 0x7fffff)
447     value -= 0x1000000;
448
449   if (value > 0xffffff)
450     return _("dsp:24 immediate is out of range");
451
452   *valuep = value;
453   return 0;
454 }
455
456 static const char *
457 parse_signed32 (CGEN_CPU_DESC cd, const char **strp,
458                 int opindex, signed long *valuep)
459 {
460   const char *errmsg = 0;
461   signed long value;
462   
463   errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
464   if (errmsg)
465     return errmsg;
466
467   *valuep = value;
468   return 0;
469 }
470
471 static const char *
472 parse_imm1_S (CGEN_CPU_DESC cd, const char **strp,
473              int opindex, signed long *valuep)
474 {
475   const char *errmsg = 0;
476   signed long value;
477
478   errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
479   if (errmsg)
480     return errmsg;
481
482   if (value < 1 || value > 2)
483     return _("immediate is out of range 1-2");
484
485   *valuep = value;
486   return 0;
487 }
488
489 static const char *
490 parse_imm3_S (CGEN_CPU_DESC cd, const char **strp,
491              int opindex, signed long *valuep)
492 {
493   const char *errmsg = 0;
494   signed long value;
495   
496   errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
497   if (errmsg)
498     return errmsg;
499
500   if (value < 1 || value > 8)
501     return _("immediate is out of range 1-8");
502
503   *valuep = value;
504   return 0;
505 }
506
507 static const char *
508 parse_lab_5_3 (CGEN_CPU_DESC cd,
509                const char **strp,
510                int opindex ATTRIBUTE_UNUSED,
511                int opinfo,
512                enum cgen_parse_operand_result *type_addr,
513                bfd_vma *valuep)
514 {
515   const char *errmsg = 0;
516   bfd_vma value;
517   enum cgen_parse_operand_result op_res;
518
519   errmsg = cgen_parse_address (cd, strp, M32C_OPERAND_LAB_5_3,
520                                opinfo, & op_res, & value);
521
522   if (type_addr)
523     *type_addr = op_res;
524
525   if (op_res == CGEN_PARSE_OPERAND_ADDRESS)
526     {
527       /* This is a hack; the field cannot handle near-zero signed
528          offsets that CGEN wants to put in to indicate an "empty"
529          operand at first.  */
530       *valuep = 2;
531       return 0;
532     }
533   if (errmsg)
534     return errmsg;
535
536   if (value < 2 || value > 9)
537     return _("immediate is out of range 2-9");
538
539   *valuep = value;
540   return 0;
541 }
542
543 static const char *
544 parse_Bitno16R (CGEN_CPU_DESC cd, const char **strp,
545                 int opindex, unsigned long *valuep)
546 {
547   const char *errmsg = 0;
548   unsigned long value;
549
550   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
551   if (errmsg)
552     return errmsg;
553
554   if (value > 15)
555     return _("Bit number for indexing general register is out of range 0-15");
556
557   *valuep = value;
558   return 0;
559 }
560
561 static const char *
562 parse_unsigned_bitbase (CGEN_CPU_DESC cd, const char **strp,
563                         int opindex, unsigned long *valuep,
564                         unsigned bits)
565 {
566   const char *errmsg = 0;
567   unsigned long bit;
568   unsigned long base;
569   const char *newp = *strp;
570   unsigned long long bitbase;
571
572   errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & bit);
573   if (errmsg)
574     return errmsg;
575
576   if (*newp != ',')
577     return "Missing base for bit,base:8";
578
579   ++newp;
580   errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & base);
581   if (errmsg)
582     return errmsg;
583
584   bitbase = (unsigned long long) bit + ((unsigned long long) base * 8);
585
586   if (bitbase >= (1ull << bits))
587     return _("bit,base is out of range");
588
589   *valuep = bitbase;
590   *strp = newp;
591   return 0;
592 }
593
594 static const char *
595 parse_signed_bitbase (CGEN_CPU_DESC cd, const char **strp,
596                       int opindex, signed long *valuep,
597                       unsigned bits)
598 {
599   const char *errmsg = 0;
600   unsigned long bit;
601   signed long base;
602   const char *newp = *strp;
603   long long bitbase;
604   long long limit;
605
606   errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & bit);
607   if (errmsg)
608     return errmsg;
609
610   if (*newp != ',')
611     return "Missing base for bit,base:8";
612
613   ++newp;
614   errmsg = cgen_parse_signed_integer (cd, & newp, opindex, & base);
615   if (errmsg)
616     return errmsg;
617
618   bitbase = (long long)bit + ((long long)base * 8);
619
620   limit = 1ll << (bits - 1);
621   if (bitbase < -limit || bitbase >= limit)
622     return _("bit,base is out of range");
623
624   *valuep = bitbase;
625   *strp = newp;
626   return 0;
627 }
628
629 static const char *
630 parse_unsigned_bitbase8 (CGEN_CPU_DESC cd, const char **strp,
631                          int opindex, unsigned long *valuep)
632 {
633   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 8);
634 }
635
636 static const char *
637 parse_unsigned_bitbase11 (CGEN_CPU_DESC cd, const char **strp,
638                          int opindex, unsigned long *valuep)
639 {
640   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 11);
641 }
642
643 static const char *
644 parse_unsigned_bitbase16 (CGEN_CPU_DESC cd, const char **strp,
645                           int opindex, unsigned long *valuep)
646 {
647   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 16);
648 }
649
650 static const char *
651 parse_unsigned_bitbase19 (CGEN_CPU_DESC cd, const char **strp,
652                          int opindex, unsigned long *valuep)
653 {
654   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 19);
655 }
656
657 static const char *
658 parse_unsigned_bitbase27 (CGEN_CPU_DESC cd, const char **strp,
659                          int opindex, unsigned long *valuep)
660 {
661   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 27);
662 }
663
664 static const char *
665 parse_signed_bitbase8 (CGEN_CPU_DESC cd, const char **strp,
666                        int opindex, signed long *valuep)
667 {
668   return parse_signed_bitbase (cd, strp, opindex, valuep, 8);
669 }
670
671 static const char *
672 parse_signed_bitbase11 (CGEN_CPU_DESC cd, const char **strp,
673                        int opindex, signed long *valuep)
674 {
675   return parse_signed_bitbase (cd, strp, opindex, valuep, 11);
676 }
677
678 static const char *
679 parse_signed_bitbase19 (CGEN_CPU_DESC cd, const char **strp,
680                        int opindex, signed long *valuep)
681 {
682   return parse_signed_bitbase (cd, strp, opindex, valuep, 19);
683 }
684
685 /* Parse the suffix as :<char> or as nothing followed by a whitespace.  */
686
687 static const char *
688 parse_suffix (const char **strp, char suffix)
689 {
690   const char *newp = *strp;
691   
692   if (**strp == ':' && TOLOWER (*(*strp + 1)) == suffix)
693     newp = *strp + 2;
694
695   if (ISSPACE (*newp))
696     {
697       *strp = newp;
698       return 0;
699     }
700         
701   return "Invalid suffix"; /* Anything -- will not be seen.  */
702 }
703
704 static const char *
705 parse_S (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
706          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
707 {
708   return parse_suffix (strp, 's');
709 }
710
711 static const char *
712 parse_G (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
713          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
714 {
715   return parse_suffix (strp, 'g');
716 }
717
718 static const char *
719 parse_Q (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
720          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
721 {
722   return parse_suffix (strp, 'q');
723 }
724
725 static const char *
726 parse_Z (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
727          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
728 {
729   return parse_suffix (strp, 'z');
730 }
731
732 /* Parse an empty suffix. Fail if the next char is ':'.  */
733
734 static const char *
735 parse_X (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
736          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
737 {
738   if (**strp == ':')
739     return "Unexpected suffix";
740   return 0;
741 }
742
743 static const char *
744 parse_r0l_r0h (CGEN_CPU_DESC cd, const char **strp,
745                int opindex ATTRIBUTE_UNUSED, signed long *valuep)
746 {
747   const char *errmsg;
748   signed long value;
749   signed long junk;
750   const char *newp = *strp;
751
752   /* Parse r0[hl].  */
753   errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0l_r0h, & value);
754   if (errmsg)
755     return errmsg;
756
757   if (*newp != ',')
758     return _("not a valid r0l/r0h pair");
759   ++newp;
760
761   /* Parse the second register in the pair.  */
762   if (value == 0) /* r0l */
763     errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0h, & junk);
764   else
765     errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0l, & junk);
766   if (errmsg)
767     return errmsg;
768
769   *strp = newp;
770   *valuep = ! value;
771   return 0;
772 }
773
774 /* Accept .b or .w in any case.  */
775
776 static const char *
777 parse_size (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
778             int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
779 {
780   if (**strp == '.'
781       && (*(*strp + 1) == 'b' || *(*strp + 1) == 'B'
782           || *(*strp + 1) == 'w' || *(*strp + 1) == 'W'))
783     {
784       *strp += 2;
785       return NULL;
786     }
787
788   return _("Invalid size specifier");
789 }
790
791 /* Special check to ensure that instruction exists for given machine.  */
792
793 int
794 m32c_cgen_insn_supported (CGEN_CPU_DESC cd,
795                           const CGEN_INSN *insn)
796 {
797   int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
798   int isas = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_ISA);
799
800   /* If attributes are absent, assume no restriction.  */
801   if (machs == 0)
802     machs = ~0;
803
804   return ((machs & cd->machs)
805           && (isas & cd->isas));
806 }
807
808 /* Parse a set of registers, R0,R1,A0,A1,SB,FB.  */
809
810 static const char *
811 parse_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
812               const char **strp,
813               int opindex ATTRIBUTE_UNUSED,
814               unsigned long *valuep,
815               int push)
816 {
817   const char *errmsg = 0;
818   int regno = 0;
819  
820   *valuep = 0;
821   while (**strp && **strp != ')')
822     {
823       if (**strp == 'r' || **strp == 'R')
824         {
825           ++*strp;
826           regno = **strp - '0';
827           if (regno > 4)
828             errmsg = _("Register number is not valid");
829         }
830       else if (**strp == 'a' || **strp == 'A')
831         {
832           ++*strp;
833           regno = **strp - '0';
834           if (regno > 2)
835             errmsg = _("Register number is not valid");
836           regno = **strp - '0' + 4;
837         }
838       
839       else if (strncasecmp (*strp, "sb", 2) == 0 || strncasecmp (*strp, "SB", 2) == 0)
840         {
841           regno = 6;
842           ++*strp;
843         }
844       
845       else if (strncasecmp (*strp, "fb", 2) == 0 || strncasecmp (*strp, "FB", 2) == 0)
846         {
847           regno = 7;
848           ++*strp;
849         }
850       
851       if (push) /* Mask is reversed for push.  */
852         *valuep |= 0x80 >> regno;
853       else
854         *valuep |= 1 << regno;
855
856       ++*strp;
857       if (**strp == ',')
858         {
859           if (*(*strp + 1) == ')')
860             break;
861           ++*strp;
862         }
863     }
864
865   if (!*strp)
866     errmsg = _("Register list is not valid");
867
868   return errmsg;
869 }
870
871 #define POP  0
872 #define PUSH 1
873
874 static const char *
875 parse_pop_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
876                   const char **strp,
877                   int opindex ATTRIBUTE_UNUSED,
878                   unsigned long *valuep)
879 {
880   return parse_regset (cd, strp, opindex, valuep, POP);
881 }
882
883 static const char *
884 parse_push_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
885                    const char **strp,
886                    int opindex ATTRIBUTE_UNUSED,
887                    unsigned long *valuep)
888 {
889   return parse_regset (cd, strp, opindex, valuep, PUSH);
890 }
891
892 /* -- dis.c */
893
894 #include "elf/m32c.h"
895 #include "elf-bfd.h"
896
897 /* Always print the short insn format suffix as ':<char>'.  */
898
899 static void
900 print_suffix (void * dis_info, char suffix)
901 {
902   disassemble_info *info = dis_info;
903
904   (*info->fprintf_func) (info->stream, ":%c", suffix);
905 }
906
907 static void
908 print_S (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
909          void * dis_info,
910          long value ATTRIBUTE_UNUSED,
911          unsigned int attrs ATTRIBUTE_UNUSED,
912          bfd_vma pc ATTRIBUTE_UNUSED,
913          int length ATTRIBUTE_UNUSED)
914 {
915   print_suffix (dis_info, 's');
916 }
917
918
919 static void
920 print_G (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
921          void * dis_info,
922          long value ATTRIBUTE_UNUSED,
923          unsigned int attrs ATTRIBUTE_UNUSED,
924          bfd_vma pc ATTRIBUTE_UNUSED,
925          int length ATTRIBUTE_UNUSED)
926 {
927   print_suffix (dis_info, 'g');
928 }
929
930 static void
931 print_Q (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
932          void * dis_info,
933          long value ATTRIBUTE_UNUSED,
934          unsigned int attrs ATTRIBUTE_UNUSED,
935          bfd_vma pc ATTRIBUTE_UNUSED,
936          int length ATTRIBUTE_UNUSED)
937 {
938   print_suffix (dis_info, 'q');
939 }
940
941 static void
942 print_Z (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
943          void * dis_info,
944          long value ATTRIBUTE_UNUSED,
945          unsigned int attrs ATTRIBUTE_UNUSED,
946          bfd_vma pc ATTRIBUTE_UNUSED,
947          int length ATTRIBUTE_UNUSED)
948 {
949   print_suffix (dis_info, 'z');
950 }
951
952 /* Print the empty suffix.  */
953
954 static void
955 print_X (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
956          void * dis_info ATTRIBUTE_UNUSED,
957          long value ATTRIBUTE_UNUSED,
958          unsigned int attrs ATTRIBUTE_UNUSED,
959          bfd_vma pc ATTRIBUTE_UNUSED,
960          int length ATTRIBUTE_UNUSED)
961 {
962   return;
963 }
964
965 static void
966 print_r0l_r0h (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
967                void * dis_info,
968                long value,
969                unsigned int attrs ATTRIBUTE_UNUSED,
970                bfd_vma pc ATTRIBUTE_UNUSED,
971                int length ATTRIBUTE_UNUSED)
972 {
973   disassemble_info *info = dis_info;
974
975   if (value == 0)
976     (*info->fprintf_func) (info->stream, "r0h,r0l");
977   else
978     (*info->fprintf_func) (info->stream, "r0l,r0h");
979 }
980
981 static void
982 print_unsigned_bitbase (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
983                         void * dis_info,
984                         unsigned long value,
985                         unsigned int attrs ATTRIBUTE_UNUSED,
986                         bfd_vma pc ATTRIBUTE_UNUSED,
987                         int length ATTRIBUTE_UNUSED)
988 {
989   disassemble_info *info = dis_info;
990
991   (*info->fprintf_func) (info->stream, "%ld,0x%lx", value & 0x7, value >> 3);
992 }
993
994 static void
995 print_signed_bitbase (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
996                       void * dis_info,
997                       signed 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   (*info->fprintf_func) (info->stream, "%ld,%ld", value & 0x7, value >> 3);
1005 }
1006
1007 static void
1008 print_size (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1009             void * dis_info,
1010             long value ATTRIBUTE_UNUSED,
1011             unsigned int attrs ATTRIBUTE_UNUSED,
1012             bfd_vma pc ATTRIBUTE_UNUSED,
1013             int length ATTRIBUTE_UNUSED)
1014 {
1015   /* Always print the size as '.w'.  */
1016   disassemble_info *info = dis_info;
1017
1018   (*info->fprintf_func) (info->stream, ".w");
1019 }
1020
1021 #define POP  0
1022 #define PUSH 1
1023
1024 static void print_pop_regset  (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
1025 static void print_push_regset (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
1026
1027 /* Print a set of registers, R0,R1,A0,A1,SB,FB.  */
1028
1029 static void
1030 print_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1031               void * dis_info,
1032               long value,
1033               unsigned int attrs ATTRIBUTE_UNUSED,
1034               bfd_vma pc ATTRIBUTE_UNUSED,
1035               int length ATTRIBUTE_UNUSED,
1036               int push)
1037 {
1038   static char * m16c_register_names [] = 
1039   {
1040     "r0", "r1", "r2", "r3", "a0", "a1", "sb", "fb"
1041   };
1042   disassemble_info *info = dis_info;
1043   int mask;
1044   int index = 0;
1045   char* comma = "";
1046
1047   if (push)
1048     mask = 0x80;
1049   else
1050     mask = 1;
1051  
1052   if (value & mask)
1053     {
1054       (*info->fprintf_func) (info->stream, "%s", m16c_register_names [0]);
1055       comma = ",";
1056     }
1057
1058   for (index = 1; index <= 7; ++index)
1059     {
1060       if (push)
1061         mask >>= 1;
1062       else
1063         mask <<= 1;
1064
1065       if (value & mask)
1066         {
1067           (*info->fprintf_func) (info->stream, "%s%s", comma,
1068                                  m16c_register_names [index]);
1069           comma = ",";
1070         }
1071     }
1072 }
1073
1074 static void
1075 print_pop_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1076                   void * dis_info,
1077                   long value,
1078                   unsigned int attrs ATTRIBUTE_UNUSED,
1079                   bfd_vma pc ATTRIBUTE_UNUSED,
1080                   int length ATTRIBUTE_UNUSED)
1081 {
1082   print_regset (cd, dis_info, value, attrs, pc, length, POP);
1083 }
1084
1085 static void
1086 print_push_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1087                    void * dis_info,
1088                    long value,
1089                    unsigned int attrs ATTRIBUTE_UNUSED,
1090                    bfd_vma pc ATTRIBUTE_UNUSED,
1091                    int length ATTRIBUTE_UNUSED)
1092 {
1093   print_regset (cd, dis_info, value, attrs, pc, length, PUSH);
1094 }