This commit was generated by cvs2svn to track changes on a CVS vendor
[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   /* 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_bit3_S (CGEN_CPU_DESC cd, const char **strp,
538              int opindex, signed long *valuep)
539 {
540   const char *errmsg = 0;
541   signed long value;
542   
543   errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
544   if (errmsg)
545     return errmsg;
546
547   if (value < 0 || value > 7)
548     return _("immediate is out of range 0-7");
549
550   *valuep = value;
551   return 0;
552 }
553
554 static const char *
555 parse_lab_5_3 (CGEN_CPU_DESC cd,
556                const char **strp,
557                int opindex ATTRIBUTE_UNUSED,
558                int opinfo,
559                enum cgen_parse_operand_result *type_addr,
560                bfd_vma *valuep)
561 {
562   const char *errmsg = 0;
563   bfd_vma value;
564   enum cgen_parse_operand_result op_res;
565
566   errmsg = cgen_parse_address (cd, strp, M32C_OPERAND_LAB_5_3,
567                                opinfo, & op_res, & value);
568
569   if (type_addr)
570     *type_addr = op_res;
571
572   if (op_res == CGEN_PARSE_OPERAND_ADDRESS)
573     {
574       /* This is a hack; the field cannot handle near-zero signed
575          offsets that CGEN wants to put in to indicate an "empty"
576          operand at first.  */
577       *valuep = 2;
578       return 0;
579     }
580   if (errmsg)
581     return errmsg;
582
583   if (value < 2 || value > 9)
584     return _("immediate is out of range 2-9");
585
586   *valuep = value;
587   return 0;
588 }
589
590 static const char *
591 parse_Bitno16R (CGEN_CPU_DESC cd, const char **strp,
592                 int opindex, unsigned long *valuep)
593 {
594   const char *errmsg = 0;
595   unsigned long value;
596
597   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
598   if (errmsg)
599     return errmsg;
600
601   if (value > 15)
602     return _("Bit number for indexing general register is out of range 0-15");
603
604   *valuep = value;
605   return 0;
606 }
607
608 static const char *
609 parse_unsigned_bitbase (CGEN_CPU_DESC cd, const char **strp,
610                         int opindex, unsigned long *valuep,
611                         unsigned bits, int allow_syms)
612 {
613   const char *errmsg = 0;
614   unsigned long bit;
615   unsigned long base;
616   const char *newp = *strp;
617   unsigned long long bitbase;
618   long have_zero = 0;
619
620   errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & bit);
621   if (errmsg)
622     return errmsg;
623
624   if (*newp != ',')
625     return "Missing base for bit,base:8";
626
627   ++newp;
628
629   if (strncmp (newp, "0x0", 3) == 0 
630       || (newp[0] == '0' && newp[1] != 'x'))
631     have_zero = 1;
632
633   errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & base);
634   if (errmsg)
635     return errmsg;
636
637   bitbase = (unsigned long long) bit + ((unsigned long long) base * 8);
638
639   if (bitbase >= (1ull << bits))
640     return _("bit,base is out of range");
641
642   /* If this field may require a relocation then use larger displacement.  */
643   if (! have_zero && base == 0)
644     {
645       switch (allow_syms) {
646       case 0:
647         return _("bit,base out of range for symbol");
648       case 1:
649         break;
650       case 2:
651         if (strncmp (newp, "[sb]", 4) != 0)
652           return _("bit,base out of range for symbol");
653         break;
654       }
655     }
656
657   *valuep = bitbase;
658   *strp = newp;
659   return 0;
660 }
661
662 static const char *
663 parse_signed_bitbase (CGEN_CPU_DESC cd, const char **strp,
664                       int opindex, signed long *valuep,
665                       unsigned bits, int allow_syms)
666 {
667   const char *errmsg = 0;
668   unsigned long bit;
669   signed long base;
670   const char *newp = *strp;
671   long long bitbase;
672   long long limit;
673   long have_zero = 0;
674
675   errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & bit);
676   if (errmsg)
677     return errmsg;
678
679   if (*newp != ',')
680     return "Missing base for bit,base:8";
681
682   ++newp;
683
684   if (strncmp (newp, "0x0", 3) == 0 
685       || (newp[0] == '0' && newp[1] != 'x'))
686     have_zero = 1;
687
688   errmsg = cgen_parse_signed_integer (cd, & newp, opindex, & base);
689   if (errmsg)
690     return errmsg;
691
692   bitbase = (long long)bit + ((long long)base * 8);
693
694   limit = 1ll << (bits - 1);
695   if (bitbase < -limit || bitbase >= limit)
696     return _("bit,base is out of range");
697
698   /* If this field may require a relocation then use larger displacement.  */
699   if (! have_zero && base == 0 && ! allow_syms)
700     return _("bit,base out of range for symbol");
701
702   *valuep = bitbase;
703   *strp = newp;
704   return 0;
705 }
706
707 static const char *
708 parse_unsigned_bitbase8 (CGEN_CPU_DESC cd, const char **strp,
709                          int opindex, unsigned long *valuep)
710 {
711   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 8, 0);
712 }
713
714 static const char *
715 parse_unsigned_bitbase11 (CGEN_CPU_DESC cd, const char **strp,
716                          int opindex, unsigned long *valuep)
717 {
718   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 11, 0);
719 }
720
721 static const char *
722 parse_unsigned_bitbase16 (CGEN_CPU_DESC cd, const char **strp,
723                           int opindex, unsigned long *valuep)
724 {
725   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 16, 1);
726 }
727
728 static const char *
729 parse_unsigned_bitbase19 (CGEN_CPU_DESC cd, const char **strp,
730                          int opindex, unsigned long *valuep)
731 {
732   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 19, 2);
733 }
734
735 static const char *
736 parse_unsigned_bitbase27 (CGEN_CPU_DESC cd, const char **strp,
737                          int opindex, unsigned long *valuep)
738 {
739   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 27, 1);
740 }
741
742 static const char *
743 parse_signed_bitbase8 (CGEN_CPU_DESC cd, const char **strp,
744                        int opindex, signed long *valuep)
745 {
746   return parse_signed_bitbase (cd, strp, opindex, valuep, 8, 1);
747 }
748
749 static const char *
750 parse_signed_bitbase11 (CGEN_CPU_DESC cd, const char **strp,
751                        int opindex, signed long *valuep)
752 {
753   return parse_signed_bitbase (cd, strp, opindex, valuep, 11, 0);
754 }
755
756 static const char *
757 parse_signed_bitbase19 (CGEN_CPU_DESC cd, const char **strp,
758                        int opindex, signed long *valuep)
759 {
760   return parse_signed_bitbase (cd, strp, opindex, valuep, 19, 1);
761 }
762
763 /* Parse the suffix as :<char> or as nothing followed by a whitespace.  */
764
765 static const char *
766 parse_suffix (const char **strp, char suffix)
767 {
768   const char *newp = *strp;
769   
770   if (**strp == ':' && TOLOWER (*(*strp + 1)) == suffix)
771     newp = *strp + 2;
772
773   if (ISSPACE (*newp))
774     {
775       *strp = newp;
776       return 0;
777     }
778         
779   return "Invalid suffix"; /* Anything -- will not be seen.  */
780 }
781
782 static const char *
783 parse_S (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
784          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
785 {
786   return parse_suffix (strp, 's');
787 }
788
789 static const char *
790 parse_G (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
791          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
792 {
793   return parse_suffix (strp, 'g');
794 }
795
796 static const char *
797 parse_Q (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
798          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
799 {
800   return parse_suffix (strp, 'q');
801 }
802
803 static const char *
804 parse_Z (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
805          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
806 {
807   return parse_suffix (strp, 'z');
808 }
809
810 /* Parse an empty suffix. Fail if the next char is ':'.  */
811
812 static const char *
813 parse_X (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
814          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
815 {
816   if (**strp == ':')
817     return "Unexpected suffix";
818   return 0;
819 }
820
821 static const char *
822 parse_r0l_r0h (CGEN_CPU_DESC cd, const char **strp,
823                int opindex ATTRIBUTE_UNUSED, signed long *valuep)
824 {
825   const char *errmsg;
826   signed long value;
827   signed long junk;
828   const char *newp = *strp;
829
830   /* Parse r0[hl].  */
831   errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0l_r0h, & value);
832   if (errmsg)
833     return errmsg;
834
835   if (*newp != ',')
836     return _("not a valid r0l/r0h pair");
837   ++newp;
838
839   /* Parse the second register in the pair.  */
840   if (value == 0) /* r0l */
841     errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0h, & junk);
842   else
843     errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0l, & junk);
844   if (errmsg)
845     return errmsg;
846
847   *strp = newp;
848   *valuep = ! value;
849   return 0;
850 }
851
852 /* Accept .b or .w in any case.  */
853
854 static const char *
855 parse_size (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
856             int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
857 {
858   if (**strp == '.'
859       && (*(*strp + 1) == 'b' || *(*strp + 1) == 'B'
860           || *(*strp + 1) == 'w' || *(*strp + 1) == 'W'))
861     {
862       *strp += 2;
863       return NULL;
864     }
865
866   return _("Invalid size specifier");
867 }
868
869 /* Special check to ensure that instruction exists for given machine.  */
870
871 int
872 m32c_cgen_insn_supported (CGEN_CPU_DESC cd,
873                           const CGEN_INSN *insn)
874 {
875   int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
876   CGEN_BITSET isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA);
877
878   /* If attributes are absent, assume no restriction.  */
879   if (machs == 0)
880     machs = ~0;
881
882   return ((machs & cd->machs)
883           && cgen_bitset_intersect_p (& isas, cd->isas));
884 }
885
886 /* Parse a set of registers, R0,R1,A0,A1,SB,FB.  */
887
888 static const char *
889 parse_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
890               const char **strp,
891               int opindex ATTRIBUTE_UNUSED,
892               unsigned long *valuep,
893               int push)
894 {
895   const char *errmsg = 0;
896   int regno = 0;
897  
898   *valuep = 0;
899   while (**strp && **strp != ')')
900     {
901       if (**strp == 'r' || **strp == 'R')
902         {
903           ++*strp;
904           regno = **strp - '0';
905           if (regno > 4)
906             errmsg = _("Register number is not valid");
907         }
908       else if (**strp == 'a' || **strp == 'A')
909         {
910           ++*strp;
911           regno = **strp - '0';
912           if (regno > 2)
913             errmsg = _("Register number is not valid");
914           regno = **strp - '0' + 4;
915         }
916       
917       else if (strncasecmp (*strp, "sb", 2) == 0 || strncasecmp (*strp, "SB", 2) == 0)
918         {
919           regno = 6;
920           ++*strp;
921         }
922       
923       else if (strncasecmp (*strp, "fb", 2) == 0 || strncasecmp (*strp, "FB", 2) == 0)
924         {
925           regno = 7;
926           ++*strp;
927         }
928       
929       if (push) /* Mask is reversed for push.  */
930         *valuep |= 0x80 >> regno;
931       else
932         *valuep |= 1 << regno;
933
934       ++*strp;
935       if (**strp == ',')
936         {
937           if (*(*strp + 1) == ')')
938             break;
939           ++*strp;
940         }
941     }
942
943   if (!*strp)
944     errmsg = _("Register list is not valid");
945
946   return errmsg;
947 }
948
949 #define POP  0
950 #define PUSH 1
951
952 static const char *
953 parse_pop_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
954                   const char **strp,
955                   int opindex ATTRIBUTE_UNUSED,
956                   unsigned long *valuep)
957 {
958   return parse_regset (cd, strp, opindex, valuep, POP);
959 }
960
961 static const char *
962 parse_push_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
963                    const char **strp,
964                    int opindex ATTRIBUTE_UNUSED,
965                    unsigned long *valuep)
966 {
967   return parse_regset (cd, strp, opindex, valuep, PUSH);
968 }
969
970 /* -- dis.c */
971
972 #include "elf/m32c.h"
973 #include "elf-bfd.h"
974
975 /* Always print the short insn format suffix as ':<char>'.  */
976
977 static void
978 print_suffix (void * dis_info, char suffix)
979 {
980   disassemble_info *info = dis_info;
981
982   (*info->fprintf_func) (info->stream, ":%c", suffix);
983 }
984
985 static void
986 print_S (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
987          void * dis_info,
988          long value ATTRIBUTE_UNUSED,
989          unsigned int attrs ATTRIBUTE_UNUSED,
990          bfd_vma pc ATTRIBUTE_UNUSED,
991          int length ATTRIBUTE_UNUSED)
992 {
993   print_suffix (dis_info, 's');
994 }
995
996
997 static void
998 print_G (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
999          void * dis_info,
1000          long value ATTRIBUTE_UNUSED,
1001          unsigned int attrs ATTRIBUTE_UNUSED,
1002          bfd_vma pc ATTRIBUTE_UNUSED,
1003          int length ATTRIBUTE_UNUSED)
1004 {
1005   print_suffix (dis_info, 'g');
1006 }
1007
1008 static void
1009 print_Q (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1010          void * dis_info,
1011          long value ATTRIBUTE_UNUSED,
1012          unsigned int attrs ATTRIBUTE_UNUSED,
1013          bfd_vma pc ATTRIBUTE_UNUSED,
1014          int length ATTRIBUTE_UNUSED)
1015 {
1016   print_suffix (dis_info, 'q');
1017 }
1018
1019 static void
1020 print_Z (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1021          void * dis_info,
1022          long value ATTRIBUTE_UNUSED,
1023          unsigned int attrs ATTRIBUTE_UNUSED,
1024          bfd_vma pc ATTRIBUTE_UNUSED,
1025          int length ATTRIBUTE_UNUSED)
1026 {
1027   print_suffix (dis_info, 'z');
1028 }
1029
1030 /* Print the empty suffix.  */
1031
1032 static void
1033 print_X (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1034          void * dis_info ATTRIBUTE_UNUSED,
1035          long value ATTRIBUTE_UNUSED,
1036          unsigned int attrs ATTRIBUTE_UNUSED,
1037          bfd_vma pc ATTRIBUTE_UNUSED,
1038          int length ATTRIBUTE_UNUSED)
1039 {
1040   return;
1041 }
1042
1043 static void
1044 print_r0l_r0h (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1045                void * dis_info,
1046                long value,
1047                unsigned int attrs ATTRIBUTE_UNUSED,
1048                bfd_vma pc ATTRIBUTE_UNUSED,
1049                int length ATTRIBUTE_UNUSED)
1050 {
1051   disassemble_info *info = dis_info;
1052
1053   if (value == 0)
1054     (*info->fprintf_func) (info->stream, "r0h,r0l");
1055   else
1056     (*info->fprintf_func) (info->stream, "r0l,r0h");
1057 }
1058
1059 static void
1060 print_unsigned_bitbase (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1061                         void * dis_info,
1062                         unsigned long value,
1063                         unsigned int attrs ATTRIBUTE_UNUSED,
1064                         bfd_vma pc ATTRIBUTE_UNUSED,
1065                         int length ATTRIBUTE_UNUSED)
1066 {
1067   disassemble_info *info = dis_info;
1068
1069   (*info->fprintf_func) (info->stream, "%ld,0x%lx", value & 0x7, value >> 3);
1070 }
1071
1072 static void
1073 print_signed_bitbase (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1074                       void * dis_info,
1075                       signed long value,
1076                       unsigned int attrs ATTRIBUTE_UNUSED,
1077                       bfd_vma pc ATTRIBUTE_UNUSED,
1078                       int length ATTRIBUTE_UNUSED)
1079 {
1080   disassemble_info *info = dis_info;
1081
1082   (*info->fprintf_func) (info->stream, "%ld,%ld", value & 0x7, value >> 3);
1083 }
1084
1085 static void
1086 print_size (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1087             void * dis_info,
1088             long value ATTRIBUTE_UNUSED,
1089             unsigned int attrs ATTRIBUTE_UNUSED,
1090             bfd_vma pc ATTRIBUTE_UNUSED,
1091             int length ATTRIBUTE_UNUSED)
1092 {
1093   /* Always print the size as '.w'.  */
1094   disassemble_info *info = dis_info;
1095
1096   (*info->fprintf_func) (info->stream, ".w");
1097 }
1098
1099 #define POP  0
1100 #define PUSH 1
1101
1102 static void print_pop_regset  (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
1103 static void print_push_regset (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
1104
1105 /* Print a set of registers, R0,R1,A0,A1,SB,FB.  */
1106
1107 static void
1108 print_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1109               void * dis_info,
1110               long value,
1111               unsigned int attrs ATTRIBUTE_UNUSED,
1112               bfd_vma pc ATTRIBUTE_UNUSED,
1113               int length ATTRIBUTE_UNUSED,
1114               int push)
1115 {
1116   static char * m16c_register_names [] = 
1117   {
1118     "r0", "r1", "r2", "r3", "a0", "a1", "sb", "fb"
1119   };
1120   disassemble_info *info = dis_info;
1121   int mask;
1122   int index = 0;
1123   char* comma = "";
1124
1125   if (push)
1126     mask = 0x80;
1127   else
1128     mask = 1;
1129  
1130   if (value & mask)
1131     {
1132       (*info->fprintf_func) (info->stream, "%s", m16c_register_names [0]);
1133       comma = ",";
1134     }
1135
1136   for (index = 1; index <= 7; ++index)
1137     {
1138       if (push)
1139         mask >>= 1;
1140       else
1141         mask <<= 1;
1142
1143       if (value & mask)
1144         {
1145           (*info->fprintf_func) (info->stream, "%s%s", comma,
1146                                  m16c_register_names [index]);
1147           comma = ",";
1148         }
1149     }
1150 }
1151
1152 static void
1153 print_pop_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1154                   void * dis_info,
1155                   long value,
1156                   unsigned int attrs ATTRIBUTE_UNUSED,
1157                   bfd_vma pc ATTRIBUTE_UNUSED,
1158                   int length ATTRIBUTE_UNUSED)
1159 {
1160   print_regset (cd, dis_info, value, attrs, pc, length, POP);
1161 }
1162
1163 static void
1164 print_push_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1165                    void * dis_info,
1166                    long value,
1167                    unsigned int attrs ATTRIBUTE_UNUSED,
1168                    bfd_vma pc ATTRIBUTE_UNUSED,
1169                    int length ATTRIBUTE_UNUSED)
1170 {
1171   print_regset (cd, dis_info, value, attrs, pc, length, PUSH);
1172 }
1173
1174 static void
1175 print_signed4n (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1176                 void * dis_info,
1177                 signed long value,
1178                 unsigned int attrs ATTRIBUTE_UNUSED,
1179                 bfd_vma pc ATTRIBUTE_UNUSED,
1180                 int length ATTRIBUTE_UNUSED)
1181 {
1182   disassemble_info *info = dis_info;
1183
1184   (*info->fprintf_func) (info->stream, "%ld", -value);
1185 }