2005-10-22 Paolo Bonzini <bonzini@gnu.org>
[binutils.git] / cpu / m32c.opc
blob19547ae694daf10a4637e2f08ee5f7cfa9ddcb90
1 /* m32c opcode support.  -*- C -*-
3    Copyright 2005 Free Software Foundation, Inc.
5    Contributed by Red Hat Inc; developed under contract from Renesas
7    This file is part of the GNU Binutils.
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.
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.
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.  */
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.
30    Each section is delimited with start and end markers.
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".  */
38 /* -- opc.h */
40 /* Needed for RTL's 'ext' and 'trunc' operators.  */
41 #include "cgen-types.h"
42 #include "cgen-ops.h"
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
51 extern int m32c_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
53 #define CGEN_ASM_HASH_SIZE 0xffff
54 #define CGEN_ASM_HASH(mnem) m32c_asm_hash ((mnem))
56 /* -- */
58 /* -- opc.c */
59 static unsigned int
60 m32c_asm_hash (const char *mnem)
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;
77 /* -- asm.c */
78 #include "safe-ctype.h"
80 #define MACH_M32C 5             /* Must match md_begin.  */
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      };
95    for (u = 0; m32c_register_names[u]; u++)
96      {
97        int len = strlen (m32c_register_names[u]);
99        if (memcmp (m32c_register_names[u], s, len) == 0
100            && (s[len] == 0 || ! ISALNUM (s[len])))
101         return 1;
102      }
103    return 0;
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)
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)
132 static const char *
133 parse_unsigned6 (CGEN_CPU_DESC cd, const char **strp,
134                  int opindex, unsigned long *valuep)
136   const char *errmsg = 0;
137   unsigned long value;
139   PARSE_UNSIGNED;
141   if (value > 0x3f)
142     return _("imm:6 immediate is out of range");
144   *valuep = value;
145   return 0;
148 static const char *
149 parse_unsigned8 (CGEN_CPU_DESC cd, const char **strp,
150                  int opindex, unsigned long *valuep)
152   const char *errmsg = 0;
153   unsigned long value;
154   long have_zero = 0;
156   if (strncasecmp (*strp, "%dsp8(", 6) == 0)
157     {
158       enum cgen_parse_operand_result result_type;
159       bfd_vma value;
160       const char *errmsg;
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) ++;
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     }
178   if (strncmp (*strp, "0x0", 3) == 0 
179       || (**strp == '0' && *(*strp + 1) != 'x'))
180     have_zero = 1;
182   PARSE_UNSIGNED;
184   if (value > 0xff)
185     return _("dsp:8 immediate is out of range");
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");
191   *valuep = value;
192   return 0;
195 static const char *
196 parse_signed4 (CGEN_CPU_DESC cd, const char **strp,
197                int opindex, signed long *valuep)
199   const char *errmsg = 0;
200   signed long value;
201   long have_zero = 0;
203   if (strncmp (*strp, "0x0", 3) == 0 
204       || (**strp == '0' && *(*strp + 1) != 'x'))
205     have_zero = 1;
207   PARSE_SIGNED;
209   if (value < -8 || value > 7)
210     return _("Immediate is out of range -8 to 7");
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");
216   *valuep = value;
217   return 0;
220 static const char *
221 parse_signed8 (CGEN_CPU_DESC cd, const char **strp,
222                int opindex, signed long *valuep)
224   const char *errmsg = 0;
225   signed long value;
227   if (strncasecmp (*strp, "%hi8(", 5) == 0)
228     {
229       enum cgen_parse_operand_result result_type;
230       bfd_vma value;
231       const char *errmsg;
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) ++;
240       if (errmsg == NULL
241           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
242         {
243           value >>= 16;
244         }
245       *valuep = value;
246       return errmsg;
247     }
249   PARSE_SIGNED;
251   if (value <= 255 && value > 127)
252     value -= 0x100;
254   if (value < -128 || value > 127)
255     return _("dsp:8 immediate is out of range");
257   *valuep = value;
258   return 0;
261 static const char *
262 parse_unsigned16 (CGEN_CPU_DESC cd, const char **strp,
263                  int opindex, unsigned long *valuep)
265   const char *errmsg = 0;
266   unsigned long value;
267   long have_zero = 0;
269   if (strncasecmp (*strp, "%dsp16(", 7) == 0)
270     {
271       enum cgen_parse_operand_result result_type;
272       bfd_vma value;
273       const char *errmsg;
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) ++;
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     }
291   /* Don't successfully parse literals beginning with '['.  */
292   if (**strp == '[')
293     return "Invalid literal"; /* Anything -- will not be seen.  */
295   /* Don't successfully parse register names.  */
296   if (m32c_cgen_isa_register (strp))
297     return "Invalid literal"; /* Anything -- will not be seen.  */
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;
307   if (value > 0xffff)
308     return _("dsp:16 immediate is out of range");
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");
317   *valuep = value;
318   return 0;
321 static const char *
322 parse_signed16 (CGEN_CPU_DESC cd, const char **strp,
323                int opindex, signed long *valuep)
325   const char *errmsg = 0;
326   signed long value;
328   if (strncasecmp (*strp, "%lo16(", 6) == 0)
329     {
330       enum cgen_parse_operand_result result_type;
331       bfd_vma value;
332       const char *errmsg;
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) ++;
341       if (errmsg == NULL
342           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
343         {
344           value &= 0xffff;
345         }
346       *valuep = value;
347       return errmsg;
348     }
350   if (strncasecmp (*strp, "%hi16(", 6) == 0)
351     {
352       enum cgen_parse_operand_result result_type;
353       bfd_vma value;
354       const char *errmsg;
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) ++;
363       if (errmsg == NULL
364           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
365         {
366           value >>= 16;
367         }
368       *valuep = value;
369       return errmsg;
370     }
372   PARSE_SIGNED;
374   if (value <= 65535 && value > 32767)
375     value -= 0x10000;
377   if (value < -32768 || value > 32767)
378     return _("dsp:16 immediate is out of range");
380   *valuep = value;
381   return 0;
384 static const char *
385 parse_unsigned20 (CGEN_CPU_DESC cd, const char **strp,
386                  int opindex, unsigned long *valuep)
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.  */
395   /* Don't successfully parse register names.  */
396   if (m32c_cgen_isa_register (strp))
397     return "Invalid literal"; /* Anything -- will not be seen.  */
399   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
400   if (errmsg)
401     return errmsg;
403   if (value > 0xfffff)
404     return _("dsp:20 immediate is out of range");
406   *valuep = value;
407   return 0;
410 static const char *
411 parse_unsigned24 (CGEN_CPU_DESC cd, const char **strp,
412                  int opindex, unsigned long *valuep)
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.  */
421   /* Don't successfully parse register names.  */
422   if (m32c_cgen_isa_register (strp))
423     return "Invalid literal"; /* Anything -- will not be seen.  */
425   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
426   if (errmsg)
427     return errmsg;
429   if (value > 0xffffff)
430     return _("dsp:24 immediate is out of range");
432   *valuep = value;
433   return 0;
436 static const char *
437 parse_signed32 (CGEN_CPU_DESC cd, const char **strp,
438                 int opindex, signed long *valuep)
440   const char *errmsg = 0;
441   signed long value;
442   
443   errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
444   if (errmsg)
445     return errmsg;
447   *valuep = value;
448   return 0;
451 static const char *
452 parse_imm1_S (CGEN_CPU_DESC cd, const char **strp,
453              int opindex, signed long *valuep)
455   const char *errmsg = 0;
456   signed long value;
458   errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
459   if (errmsg)
460     return errmsg;
462   if (value < 1 || value > 2)
463     return _("immediate is out of range 1-2");
465   *valuep = value;
466   return 0;
469 static const char *
470 parse_imm3_S (CGEN_CPU_DESC cd, const char **strp,
471              int opindex, signed long *valuep)
473   const char *errmsg = 0;
474   signed long value;
475   
476   errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
477   if (errmsg)
478     return errmsg;
480   if (value < 1 || value > 8)
481     return _("immediate is out of range 1-8");
483   *valuep = value;
484   return 0;
487 static const char *
488 parse_lab_5_3 (CGEN_CPU_DESC cd,
489                const char **strp,
490                int opindex ATTRIBUTE_UNUSED,
491                int opinfo,
492                enum cgen_parse_operand_result *type_addr,
493                bfd_vma *valuep)
495   const char *errmsg = 0;
496   bfd_vma value;
497   enum cgen_parse_operand_result op_res;
499   errmsg = cgen_parse_address (cd, strp, M32C_OPERAND_LAB_5_3,
500                                opinfo, & op_res, & value);
502   if (type_addr)
503     *type_addr = op_res;
505   if (op_res == CGEN_PARSE_OPERAND_ADDRESS)
506     {
507       /* This is a hack; the field cannot handle near-zero signed
508          offsets that CGEN wants to put in to indicate an "empty"
509          operand at first.  */
510       *valuep = 2;
511       return 0;
512     }
513   if (errmsg)
514     return errmsg;
516   if (value < 2 || value > 9)
517     return _("immediate is out of range 2-9");
519   *valuep = value;
520   return 0;
523 static const char *
524 parse_Bitno16R (CGEN_CPU_DESC cd, const char **strp,
525                 int opindex, unsigned long *valuep)
527   const char *errmsg = 0;
528   unsigned long value;
530   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
531   if (errmsg)
532     return errmsg;
534   if (value > 15)
535     return _("Bit number for indexing general register is out of range 0-15");
537   *valuep = value;
538   return 0;
541 static const char *
542 parse_unsigned_bitbase (CGEN_CPU_DESC cd, const char **strp,
543                         int opindex, unsigned long *valuep,
544                         unsigned bits)
546   const char *errmsg = 0;
547   unsigned long bit;
548   unsigned long base;
549   const char *newp = *strp;
550   unsigned long long bitbase;
552   errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & bit);
553   if (errmsg)
554     return errmsg;
556   if (*newp != ',')
557     return "Missing base for bit,base:8";
559   ++newp;
560   errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & base);
561   if (errmsg)
562     return errmsg;
564   bitbase = (unsigned long long) bit + ((unsigned long long) base * 8);
566   if (bitbase >= (1ull << bits))
567     return _("bit,base is out of range");
569   *valuep = bitbase;
570   *strp = newp;
571   return 0;
574 static const char *
575 parse_signed_bitbase (CGEN_CPU_DESC cd, const char **strp,
576                       int opindex, signed long *valuep,
577                       unsigned bits)
579   const char *errmsg = 0;
580   unsigned long bit;
581   signed long base;
582   const char *newp = *strp;
583   long long bitbase;
584   long long limit;
586   errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & bit);
587   if (errmsg)
588     return errmsg;
590   if (*newp != ',')
591     return "Missing base for bit,base:8";
593   ++newp;
594   errmsg = cgen_parse_signed_integer (cd, & newp, opindex, & base);
595   if (errmsg)
596     return errmsg;
598   bitbase = (long long)bit + ((long long)base * 8);
600   limit = 1ll << (bits - 1);
601   if (bitbase < -limit || bitbase >= limit)
602     return _("bit,base is out of range");
604   *valuep = bitbase;
605   *strp = newp;
606   return 0;
609 static const char *
610 parse_unsigned_bitbase8 (CGEN_CPU_DESC cd, const char **strp,
611                          int opindex, unsigned long *valuep)
613   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 8);
616 static const char *
617 parse_unsigned_bitbase11 (CGEN_CPU_DESC cd, const char **strp,
618                          int opindex, unsigned long *valuep)
620   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 11);
623 static const char *
624 parse_unsigned_bitbase16 (CGEN_CPU_DESC cd, const char **strp,
625                           int opindex, unsigned long *valuep)
627   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 16);
630 static const char *
631 parse_unsigned_bitbase19 (CGEN_CPU_DESC cd, const char **strp,
632                          int opindex, unsigned long *valuep)
634   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 19);
637 static const char *
638 parse_unsigned_bitbase27 (CGEN_CPU_DESC cd, const char **strp,
639                          int opindex, unsigned long *valuep)
641   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 27);
644 static const char *
645 parse_signed_bitbase8 (CGEN_CPU_DESC cd, const char **strp,
646                        int opindex, signed long *valuep)
648   return parse_signed_bitbase (cd, strp, opindex, valuep, 8);
651 static const char *
652 parse_signed_bitbase11 (CGEN_CPU_DESC cd, const char **strp,
653                        int opindex, signed long *valuep)
655   return parse_signed_bitbase (cd, strp, opindex, valuep, 11);
658 static const char *
659 parse_signed_bitbase19 (CGEN_CPU_DESC cd, const char **strp,
660                        int opindex, signed long *valuep)
662   return parse_signed_bitbase (cd, strp, opindex, valuep, 19);
665 /* Parse the suffix as :<char> or as nothing followed by a whitespace.  */
667 static const char *
668 parse_suffix (const char **strp, char suffix)
670   const char *newp = *strp;
671   
672   if (**strp == ':' && TOLOWER (*(*strp + 1)) == suffix)
673     newp = *strp + 2;
675   if (ISSPACE (*newp))
676     {
677       *strp = newp;
678       return 0;
679     }
680         
681   return "Invalid suffix"; /* Anything -- will not be seen.  */
684 static const char *
685 parse_S (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
686          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
688   return parse_suffix (strp, 's');
691 static const char *
692 parse_G (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
693          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
695   return parse_suffix (strp, 'g');
698 static const char *
699 parse_Q (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
700          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
702   return parse_suffix (strp, 'q');
705 static const char *
706 parse_Z (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
707          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
709   return parse_suffix (strp, 'z');
712 /* Parse an empty suffix. Fail if the next char is ':'.  */
714 static const char *
715 parse_X (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
716          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
718   if (**strp == ':')
719     return "Unexpected suffix";
720   return 0;
723 static const char *
724 parse_r0l_r0h (CGEN_CPU_DESC cd, const char **strp,
725                int opindex ATTRIBUTE_UNUSED, signed long *valuep)
727   const char *errmsg;
728   signed long value;
729   signed long junk;
730   const char *newp = *strp;
732   /* Parse r0[hl].  */
733   errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0l_r0h, & value);
734   if (errmsg)
735     return errmsg;
737   if (*newp != ',')
738     return _("not a valid r0l/r0h pair");
739   ++newp;
741   /* Parse the second register in the pair.  */
742   if (value == 0) /* r0l */
743     errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0h, & junk);
744   else
745     errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0l, & junk);
746   if (errmsg)
747     return errmsg;
749   *strp = newp;
750   *valuep = ! value;
751   return 0;
754 /* Accept .b or .w in any case.  */
756 static const char *
757 parse_size (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
758             int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
760   if (**strp == '.'
761       && (*(*strp + 1) == 'b' || *(*strp + 1) == 'B'
762           || *(*strp + 1) == 'w' || *(*strp + 1) == 'W'))
763     {
764       *strp += 2;
765       return NULL;
766     }
768   return _("Invalid size specifier");
771 /* Special check to ensure that instruction exists for given machine.  */
774 m32c_cgen_insn_supported (CGEN_CPU_DESC cd,
775                           const CGEN_INSN *insn)
777   int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
778   int isas = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_ISA);
780   /* If attributes are absent, assume no restriction.  */
781   if (machs == 0)
782     machs = ~0;
784   return ((machs & cd->machs)
785           && (isas & cd->isas));
788 /* Parse a set of registers, R0,R1,A0,A1,SB,FB.  */
790 static const char *
791 parse_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
792               const char **strp,
793               int opindex ATTRIBUTE_UNUSED,
794               unsigned long *valuep,
795               int push)
797   const char *errmsg = 0;
798   int regno = 0;
800   *valuep = 0;
801   while (**strp && **strp != ')')
802     {
803       if (**strp == 'r' || **strp == 'R')
804         {
805           ++*strp;
806           regno = **strp - '0';
807           if (regno > 4)
808             errmsg = _("Register number is not valid");
809         }
810       else if (**strp == 'a' || **strp == 'A')
811         {
812           ++*strp;
813           regno = **strp - '0';
814           if (regno > 2)
815             errmsg = _("Register number is not valid");
816           regno = **strp - '0' + 4;
817         }
818       
819       else if (strncasecmp (*strp, "sb", 2) == 0 || strncasecmp (*strp, "SB", 2) == 0)
820         {
821           regno = 6;
822           ++*strp;
823         }
824       
825       else if (strncasecmp (*strp, "fb", 2) == 0 || strncasecmp (*strp, "FB", 2) == 0)
826         {
827           regno = 7;
828           ++*strp;
829         }
830       
831       if (push) /* Mask is reversed for push.  */
832         *valuep |= 0x80 >> regno;
833       else
834         *valuep |= 1 << regno;
836       ++*strp;
837       if (**strp == ',')
838         {
839           if (*(*strp + 1) == ')')
840             break;
841           ++*strp;
842         }
843     }
845   if (!*strp)
846     errmsg = _("Register list is not valid");
848   return errmsg;
851 #define POP  0
852 #define PUSH 1
854 static const char *
855 parse_pop_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
856                   const char **strp,
857                   int opindex ATTRIBUTE_UNUSED,
858                   unsigned long *valuep)
860   return parse_regset (cd, strp, opindex, valuep, POP);
863 static const char *
864 parse_push_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
865                    const char **strp,
866                    int opindex ATTRIBUTE_UNUSED,
867                    unsigned long *valuep)
869   return parse_regset (cd, strp, opindex, valuep, PUSH);
872 /* -- dis.c */
874 #include "elf/m32c.h"
875 #include "elf-bfd.h"
877 /* Always print the short insn format suffix as ':<char>'.  */
879 static void
880 print_suffix (void * dis_info, char suffix)
882   disassemble_info *info = dis_info;
884   (*info->fprintf_func) (info->stream, ":%c", suffix);
887 static void
888 print_S (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
889          void * dis_info,
890          long value ATTRIBUTE_UNUSED,
891          unsigned int attrs ATTRIBUTE_UNUSED,
892          bfd_vma pc ATTRIBUTE_UNUSED,
893          int length ATTRIBUTE_UNUSED)
895   print_suffix (dis_info, 's');
899 static void
900 print_G (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
901          void * dis_info,
902          long value ATTRIBUTE_UNUSED,
903          unsigned int attrs ATTRIBUTE_UNUSED,
904          bfd_vma pc ATTRIBUTE_UNUSED,
905          int length ATTRIBUTE_UNUSED)
907   print_suffix (dis_info, 'g');
910 static void
911 print_Q (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
912          void * dis_info,
913          long value ATTRIBUTE_UNUSED,
914          unsigned int attrs ATTRIBUTE_UNUSED,
915          bfd_vma pc ATTRIBUTE_UNUSED,
916          int length ATTRIBUTE_UNUSED)
918   print_suffix (dis_info, 'q');
921 static void
922 print_Z (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
923          void * dis_info,
924          long value ATTRIBUTE_UNUSED,
925          unsigned int attrs ATTRIBUTE_UNUSED,
926          bfd_vma pc ATTRIBUTE_UNUSED,
927          int length ATTRIBUTE_UNUSED)
929   print_suffix (dis_info, 'z');
932 /* Print the empty suffix.  */
934 static void
935 print_X (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
936          void * dis_info ATTRIBUTE_UNUSED,
937          long value ATTRIBUTE_UNUSED,
938          unsigned int attrs ATTRIBUTE_UNUSED,
939          bfd_vma pc ATTRIBUTE_UNUSED,
940          int length ATTRIBUTE_UNUSED)
942   return;
945 static void
946 print_r0l_r0h (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
947                void * dis_info,
948                long value,
949                unsigned int attrs ATTRIBUTE_UNUSED,
950                bfd_vma pc ATTRIBUTE_UNUSED,
951                int length ATTRIBUTE_UNUSED)
953   disassemble_info *info = dis_info;
955   if (value == 0)
956     (*info->fprintf_func) (info->stream, "r0h,r0l");
957   else
958     (*info->fprintf_func) (info->stream, "r0l,r0h");
961 static void
962 print_unsigned_bitbase (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
963                         void * dis_info,
964                         unsigned long value,
965                         unsigned int attrs ATTRIBUTE_UNUSED,
966                         bfd_vma pc ATTRIBUTE_UNUSED,
967                         int length ATTRIBUTE_UNUSED)
969   disassemble_info *info = dis_info;
971   (*info->fprintf_func) (info->stream, "%ld,0x%lx", value & 0x7, value >> 3);
974 static void
975 print_signed_bitbase (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
976                       void * dis_info,
977                       signed long value,
978                       unsigned int attrs ATTRIBUTE_UNUSED,
979                       bfd_vma pc ATTRIBUTE_UNUSED,
980                       int length ATTRIBUTE_UNUSED)
982   disassemble_info *info = dis_info;
984   (*info->fprintf_func) (info->stream, "%ld,%ld", value & 0x7, value >> 3);
987 static void
988 print_size (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
989             void * dis_info,
990             long value ATTRIBUTE_UNUSED,
991             unsigned int attrs ATTRIBUTE_UNUSED,
992             bfd_vma pc ATTRIBUTE_UNUSED,
993             int length ATTRIBUTE_UNUSED)
995   /* Always print the size as '.w'.  */
996   disassemble_info *info = dis_info;
998   (*info->fprintf_func) (info->stream, ".w");
1001 #define POP  0
1002 #define PUSH 1
1004 static void print_pop_regset  (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
1005 static void print_push_regset (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
1007 /* Print a set of registers, R0,R1,A0,A1,SB,FB.  */
1009 static void
1010 print_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1011               void * dis_info,
1012               long value,
1013               unsigned int attrs ATTRIBUTE_UNUSED,
1014               bfd_vma pc ATTRIBUTE_UNUSED,
1015               int length ATTRIBUTE_UNUSED,
1016               int push)
1018   static char * m16c_register_names [] = 
1019   {
1020     "r0", "r1", "r2", "r3", "a0", "a1", "sb", "fb"
1021   };
1022   disassemble_info *info = dis_info;
1023   int mask;
1024   int index = 0;
1025   char* comma = "";
1027   if (push)
1028     mask = 0x80;
1029   else
1030     mask = 1;
1032   if (value & mask)
1033     {
1034       (*info->fprintf_func) (info->stream, "%s", m16c_register_names [0]);
1035       comma = ",";
1036     }
1038   for (index = 1; index <= 7; ++index)
1039     {
1040       if (push)
1041         mask >>= 1;
1042       else
1043         mask <<= 1;
1045       if (value & mask)
1046         {
1047           (*info->fprintf_func) (info->stream, "%s%s", comma,
1048                                  m16c_register_names [index]);
1049           comma = ",";
1050         }
1051     }
1054 static void
1055 print_pop_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1056                   void * dis_info,
1057                   long value,
1058                   unsigned int attrs ATTRIBUTE_UNUSED,
1059                   bfd_vma pc ATTRIBUTE_UNUSED,
1060                   int length ATTRIBUTE_UNUSED)
1062   print_regset (cd, dis_info, value, attrs, pc, length, POP);
1065 static void
1066 print_push_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1067                    void * dis_info,
1068                    long value,
1069                    unsigned int attrs ATTRIBUTE_UNUSED,
1070                    bfd_vma pc ATTRIBUTE_UNUSED,
1071                    int length ATTRIBUTE_UNUSED)
1073   print_regset (cd, dis_info, value, attrs, pc, length, PUSH);