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