* elf.c (sym_is_global): Return a bfd_boolean.
[binutils.git] / cpu / m32c.opc
blobf664e9a2cdd9d3ceee39434cb5684bd1c510e046
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   /* 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;
81 /* -- asm.c */
82 #include "safe-ctype.h"
84 #define MACH_M32C 5             /* Must match md_begin.  */
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      };
99    for (u = 0; m32c_register_names[u]; u++)
100      {
101        int len = strlen (m32c_register_names[u]);
103        if (memcmp (m32c_register_names[u], s, len) == 0
104            && (s[len] == 0 || ! ISALNUM (s[len])))
105         return 1;
106      }
107    return 0;
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)
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)
136 static const char *
137 parse_unsigned6 (CGEN_CPU_DESC cd, const char **strp,
138                  int opindex, unsigned long *valuep)
140   const char *errmsg = 0;
141   unsigned long value;
143   PARSE_UNSIGNED;
145   if (value > 0x3f)
146     return _("imm:6 immediate is out of range");
148   *valuep = value;
149   return 0;
152 static const char *
153 parse_unsigned8 (CGEN_CPU_DESC cd, const char **strp,
154                  int opindex, unsigned long *valuep)
156   const char *errmsg = 0;
157   unsigned long value;
158   long have_zero = 0;
160   if (strncasecmp (*strp, "%dsp8(", 6) == 0)
161     {
162       enum cgen_parse_operand_result result_type;
163       bfd_vma value;
164       const char *errmsg;
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) ++;
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     }
182   if (strncmp (*strp, "0x0", 3) == 0 
183       || (**strp == '0' && *(*strp + 1) != 'x'))
184     have_zero = 1;
186   PARSE_UNSIGNED;
188   if (value > 0xff)
189     return _("dsp:8 immediate is out of range");
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");
195   *valuep = value;
196   return 0;
199 static const char *
200 parse_signed4 (CGEN_CPU_DESC cd, const char **strp,
201                int opindex, signed long *valuep)
203   const char *errmsg = 0;
204   signed long value;
205   long have_zero = 0;
207   if (strncmp (*strp, "0x0", 3) == 0 
208       || (**strp == '0' && *(*strp + 1) != 'x'))
209     have_zero = 1;
211   PARSE_SIGNED;
213   if (value < -8 || value > 7)
214     return _("Immediate is out of range -8 to 7");
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");
220   *valuep = value;
221   return 0;
224 static const char *
225 parse_signed4n (CGEN_CPU_DESC cd, const char **strp,
226                 int opindex, signed long *valuep)
228   const char *errmsg = 0;
229   signed long value;
230   long have_zero = 0;
232   if (strncmp (*strp, "0x0", 3) == 0 
233       || (**strp == '0' && *(*strp + 1) != 'x'))
234     have_zero = 1;
236   PARSE_SIGNED;
238   if (value < -7 || value > 8)
239     return _("Immediate is out of range -7 to 8");
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");
245   *valuep = -value;
246   return 0;
249 static const char *
250 parse_signed8 (CGEN_CPU_DESC cd, const char **strp,
251                int opindex, signed long *valuep)
253   const char *errmsg = 0;
254   signed long value;
256   if (strncasecmp (*strp, "%hi8(", 5) == 0)
257     {
258       enum cgen_parse_operand_result result_type;
259       bfd_vma value;
260       const char *errmsg;
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) ++;
269       if (errmsg == NULL
270           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
271         {
272           value >>= 16;
273         }
274       *valuep = value;
275       return errmsg;
276     }
278   PARSE_SIGNED;
280   if (value <= 255 && value > 127)
281     value -= 0x100;
283   if (value < -128 || value > 127)
284     return _("dsp:8 immediate is out of range");
286   *valuep = value;
287   return 0;
290 static const char *
291 parse_unsigned16 (CGEN_CPU_DESC cd, const char **strp,
292                  int opindex, unsigned long *valuep)
294   const char *errmsg = 0;
295   unsigned long value;
296   long have_zero = 0;
298   if (strncasecmp (*strp, "%dsp16(", 7) == 0)
299     {
300       enum cgen_parse_operand_result result_type;
301       bfd_vma value;
302       const char *errmsg;
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) ++;
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     }
320   /* Don't successfully parse literals beginning with '['.  */
321   if (**strp == '[')
322     return "Invalid literal"; /* Anything -- will not be seen.  */
324   /* Don't successfully parse register names.  */
325   if (m32c_cgen_isa_register (strp))
326     return "Invalid literal"; /* Anything -- will not be seen.  */
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;
336   if (value > 0xffff)
337     return _("dsp:16 immediate is out of range");
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");
346   *valuep = value;
347   return 0;
350 static const char *
351 parse_signed16 (CGEN_CPU_DESC cd, const char **strp,
352                int opindex, signed long *valuep)
354   const char *errmsg = 0;
355   signed long value;
357   if (strncasecmp (*strp, "%lo16(", 6) == 0)
358     {
359       enum cgen_parse_operand_result result_type;
360       bfd_vma value;
361       const char *errmsg;
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) ++;
370       if (errmsg == NULL
371           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
372         {
373           value &= 0xffff;
374         }
375       *valuep = value;
376       return errmsg;
377     }
379   if (strncasecmp (*strp, "%hi16(", 6) == 0)
380     {
381       enum cgen_parse_operand_result result_type;
382       bfd_vma value;
383       const char *errmsg;
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) ++;
392       if (errmsg == NULL
393           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
394         {
395           value >>= 16;
396         }
397       *valuep = value;
398       return errmsg;
399     }
401   PARSE_SIGNED;
403   if (value <= 65535 && value > 32767)
404     value -= 0x10000;
406   if (value < -32768 || value > 32767)
407     return _("dsp:16 immediate is out of range");
409   *valuep = value;
410   return 0;
413 static const char *
414 parse_unsigned20 (CGEN_CPU_DESC cd, const char **strp,
415                  int opindex, unsigned long *valuep)
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.  */
424   /* Don't successfully parse register names.  */
425   if (m32c_cgen_isa_register (strp))
426     return "Invalid literal"; /* Anything -- will not be seen.  */
428   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
429   if (errmsg)
430     return errmsg;
432   if (value > 0xfffff)
433     return _("dsp:20 immediate is out of range");
435   *valuep = value;
436   return 0;
439 static const char *
440 parse_unsigned24 (CGEN_CPU_DESC cd, const char **strp,
441                  int opindex, unsigned long *valuep)
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.  */
450   /* Don't successfully parse register names.  */
451   if (m32c_cgen_isa_register (strp))
452     return "Invalid literal"; /* Anything -- will not be seen.  */
454   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
455   if (errmsg)
456     return errmsg;
458   if (value > 0xffffff)
459     return _("dsp:24 immediate is out of range");
461   *valuep = value;
462   return 0;
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)
470   const char *errmsg = 0;
471   signed long value;
473   PARSE_SIGNED;
475   if (value <= 0xffffff && value > 0x7fffff)
476     value -= 0x1000000;
478   if (value > 0xffffff)
479     return _("dsp:24 immediate is out of range");
481   *valuep = value;
482   return 0;
485 static const char *
486 parse_signed32 (CGEN_CPU_DESC cd, const char **strp,
487                 int opindex, signed long *valuep)
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;
496   *valuep = value;
497   return 0;
500 static const char *
501 parse_imm1_S (CGEN_CPU_DESC cd, const char **strp,
502              int opindex, signed long *valuep)
504   const char *errmsg = 0;
505   signed long value;
507   errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
508   if (errmsg)
509     return errmsg;
511   if (value < 1 || value > 2)
512     return _("immediate is out of range 1-2");
514   *valuep = value;
515   return 0;
518 static const char *
519 parse_imm3_S (CGEN_CPU_DESC cd, const char **strp,
520              int opindex, signed long *valuep)
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;
529   if (value < 1 || value > 8)
530     return _("immediate is out of range 1-8");
532   *valuep = value;
533   return 0;
536 static const char *
537 parse_bit3_S (CGEN_CPU_DESC cd, const char **strp,
538              int opindex, signed long *valuep)
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;
547   if (value < 0 || value > 7)
548     return _("immediate is out of range 0-7");
550   *valuep = value;
551   return 0;
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)
562   const char *errmsg = 0;
563   bfd_vma value;
564   enum cgen_parse_operand_result op_res;
566   errmsg = cgen_parse_address (cd, strp, M32C_OPERAND_LAB_5_3,
567                                opinfo, & op_res, & value);
569   if (type_addr)
570     *type_addr = op_res;
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;
583   if (value < 2 || value > 9)
584     return _("immediate is out of range 2-9");
586   *valuep = value;
587   return 0;
590 static const char *
591 parse_Bitno16R (CGEN_CPU_DESC cd, const char **strp,
592                 int opindex, unsigned long *valuep)
594   const char *errmsg = 0;
595   unsigned long value;
597   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
598   if (errmsg)
599     return errmsg;
601   if (value > 15)
602     return _("Bit number for indexing general register is out of range 0-15");
604   *valuep = value;
605   return 0;
608 static const char *
609 parse_unsigned_bitbase (CGEN_CPU_DESC cd, const char **strp,
610                         int opindex, unsigned long *valuep,
611                         unsigned bits)
613   const char *errmsg = 0;
614   unsigned long bit;
615   unsigned long base;
616   const char *newp = *strp;
617   unsigned long long bitbase;
619   errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & bit);
620   if (errmsg)
621     return errmsg;
623   if (*newp != ',')
624     return "Missing base for bit,base:8";
626   ++newp;
627   errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & base);
628   if (errmsg)
629     return errmsg;
631   bitbase = (unsigned long long) bit + ((unsigned long long) base * 8);
633   if (bitbase >= (1ull << bits))
634     return _("bit,base is out of range");
636   *valuep = bitbase;
637   *strp = newp;
638   return 0;
641 static const char *
642 parse_signed_bitbase (CGEN_CPU_DESC cd, const char **strp,
643                       int opindex, signed long *valuep,
644                       unsigned bits)
646   const char *errmsg = 0;
647   unsigned long bit;
648   signed long base;
649   const char *newp = *strp;
650   long long bitbase;
651   long long limit;
653   errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & bit);
654   if (errmsg)
655     return errmsg;
657   if (*newp != ',')
658     return "Missing base for bit,base:8";
660   ++newp;
661   errmsg = cgen_parse_signed_integer (cd, & newp, opindex, & base);
662   if (errmsg)
663     return errmsg;
665   bitbase = (long long)bit + ((long long)base * 8);
667   limit = 1ll << (bits - 1);
668   if (bitbase < -limit || bitbase >= limit)
669     return _("bit,base is out of range");
671   *valuep = bitbase;
672   *strp = newp;
673   return 0;
676 static const char *
677 parse_unsigned_bitbase8 (CGEN_CPU_DESC cd, const char **strp,
678                          int opindex, unsigned long *valuep)
680   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 8);
683 static const char *
684 parse_unsigned_bitbase11 (CGEN_CPU_DESC cd, const char **strp,
685                          int opindex, unsigned long *valuep)
687   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 11);
690 static const char *
691 parse_unsigned_bitbase16 (CGEN_CPU_DESC cd, const char **strp,
692                           int opindex, unsigned long *valuep)
694   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 16);
697 static const char *
698 parse_unsigned_bitbase19 (CGEN_CPU_DESC cd, const char **strp,
699                          int opindex, unsigned long *valuep)
701   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 19);
704 static const char *
705 parse_unsigned_bitbase27 (CGEN_CPU_DESC cd, const char **strp,
706                          int opindex, unsigned long *valuep)
708   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 27);
711 static const char *
712 parse_signed_bitbase8 (CGEN_CPU_DESC cd, const char **strp,
713                        int opindex, signed long *valuep)
715   return parse_signed_bitbase (cd, strp, opindex, valuep, 8);
718 static const char *
719 parse_signed_bitbase11 (CGEN_CPU_DESC cd, const char **strp,
720                        int opindex, signed long *valuep)
722   return parse_signed_bitbase (cd, strp, opindex, valuep, 11);
725 static const char *
726 parse_signed_bitbase19 (CGEN_CPU_DESC cd, const char **strp,
727                        int opindex, signed long *valuep)
729   return parse_signed_bitbase (cd, strp, opindex, valuep, 19);
732 /* Parse the suffix as :<char> or as nothing followed by a whitespace.  */
734 static const char *
735 parse_suffix (const char **strp, char suffix)
737   const char *newp = *strp;
738   
739   if (**strp == ':' && TOLOWER (*(*strp + 1)) == suffix)
740     newp = *strp + 2;
742   if (ISSPACE (*newp))
743     {
744       *strp = newp;
745       return 0;
746     }
747         
748   return "Invalid suffix"; /* Anything -- will not be seen.  */
751 static const char *
752 parse_S (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
753          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
755   return parse_suffix (strp, 's');
758 static const char *
759 parse_G (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
760          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
762   return parse_suffix (strp, 'g');
765 static const char *
766 parse_Q (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
767          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
769   return parse_suffix (strp, 'q');
772 static const char *
773 parse_Z (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
774          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
776   return parse_suffix (strp, 'z');
779 /* Parse an empty suffix. Fail if the next char is ':'.  */
781 static const char *
782 parse_X (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
783          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
785   if (**strp == ':')
786     return "Unexpected suffix";
787   return 0;
790 static const char *
791 parse_r0l_r0h (CGEN_CPU_DESC cd, const char **strp,
792                int opindex ATTRIBUTE_UNUSED, signed long *valuep)
794   const char *errmsg;
795   signed long value;
796   signed long junk;
797   const char *newp = *strp;
799   /* Parse r0[hl].  */
800   errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0l_r0h, & value);
801   if (errmsg)
802     return errmsg;
804   if (*newp != ',')
805     return _("not a valid r0l/r0h pair");
806   ++newp;
808   /* Parse the second register in the pair.  */
809   if (value == 0) /* r0l */
810     errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0h, & junk);
811   else
812     errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0l, & junk);
813   if (errmsg)
814     return errmsg;
816   *strp = newp;
817   *valuep = ! value;
818   return 0;
821 /* Accept .b or .w in any case.  */
823 static const char *
824 parse_size (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
825             int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
827   if (**strp == '.'
828       && (*(*strp + 1) == 'b' || *(*strp + 1) == 'B'
829           || *(*strp + 1) == 'w' || *(*strp + 1) == 'W'))
830     {
831       *strp += 2;
832       return NULL;
833     }
835   return _("Invalid size specifier");
838 /* Special check to ensure that instruction exists for given machine.  */
841 m32c_cgen_insn_supported (CGEN_CPU_DESC cd,
842                           const CGEN_INSN *insn)
844   int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
845   CGEN_BITSET isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA);
847   /* If attributes are absent, assume no restriction.  */
848   if (machs == 0)
849     machs = ~0;
851   return ((machs & cd->machs)
852           && cgen_bitset_intersect_p (& isas, cd->isas));
855 /* Parse a set of registers, R0,R1,A0,A1,SB,FB.  */
857 static const char *
858 parse_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
859               const char **strp,
860               int opindex ATTRIBUTE_UNUSED,
861               unsigned long *valuep,
862               int push)
864   const char *errmsg = 0;
865   int regno = 0;
867   *valuep = 0;
868   while (**strp && **strp != ')')
869     {
870       if (**strp == 'r' || **strp == 'R')
871         {
872           ++*strp;
873           regno = **strp - '0';
874           if (regno > 4)
875             errmsg = _("Register number is not valid");
876         }
877       else if (**strp == 'a' || **strp == 'A')
878         {
879           ++*strp;
880           regno = **strp - '0';
881           if (regno > 2)
882             errmsg = _("Register number is not valid");
883           regno = **strp - '0' + 4;
884         }
885       
886       else if (strncasecmp (*strp, "sb", 2) == 0 || strncasecmp (*strp, "SB", 2) == 0)
887         {
888           regno = 6;
889           ++*strp;
890         }
891       
892       else if (strncasecmp (*strp, "fb", 2) == 0 || strncasecmp (*strp, "FB", 2) == 0)
893         {
894           regno = 7;
895           ++*strp;
896         }
897       
898       if (push) /* Mask is reversed for push.  */
899         *valuep |= 0x80 >> regno;
900       else
901         *valuep |= 1 << regno;
903       ++*strp;
904       if (**strp == ',')
905         {
906           if (*(*strp + 1) == ')')
907             break;
908           ++*strp;
909         }
910     }
912   if (!*strp)
913     errmsg = _("Register list is not valid");
915   return errmsg;
918 #define POP  0
919 #define PUSH 1
921 static const char *
922 parse_pop_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
923                   const char **strp,
924                   int opindex ATTRIBUTE_UNUSED,
925                   unsigned long *valuep)
927   return parse_regset (cd, strp, opindex, valuep, POP);
930 static const char *
931 parse_push_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
932                    const char **strp,
933                    int opindex ATTRIBUTE_UNUSED,
934                    unsigned long *valuep)
936   return parse_regset (cd, strp, opindex, valuep, PUSH);
939 /* -- dis.c */
941 #include "elf/m32c.h"
942 #include "elf-bfd.h"
944 /* Always print the short insn format suffix as ':<char>'.  */
946 static void
947 print_suffix (void * dis_info, char suffix)
949   disassemble_info *info = dis_info;
951   (*info->fprintf_func) (info->stream, ":%c", suffix);
954 static void
955 print_S (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
956          void * dis_info,
957          long value ATTRIBUTE_UNUSED,
958          unsigned int attrs ATTRIBUTE_UNUSED,
959          bfd_vma pc ATTRIBUTE_UNUSED,
960          int length ATTRIBUTE_UNUSED)
962   print_suffix (dis_info, 's');
966 static void
967 print_G (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
968          void * dis_info,
969          long value ATTRIBUTE_UNUSED,
970          unsigned int attrs ATTRIBUTE_UNUSED,
971          bfd_vma pc ATTRIBUTE_UNUSED,
972          int length ATTRIBUTE_UNUSED)
974   print_suffix (dis_info, 'g');
977 static void
978 print_Q (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
979          void * dis_info,
980          long value ATTRIBUTE_UNUSED,
981          unsigned int attrs ATTRIBUTE_UNUSED,
982          bfd_vma pc ATTRIBUTE_UNUSED,
983          int length ATTRIBUTE_UNUSED)
985   print_suffix (dis_info, 'q');
988 static void
989 print_Z (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
990          void * dis_info,
991          long value ATTRIBUTE_UNUSED,
992          unsigned int attrs ATTRIBUTE_UNUSED,
993          bfd_vma pc ATTRIBUTE_UNUSED,
994          int length ATTRIBUTE_UNUSED)
996   print_suffix (dis_info, 'z');
999 /* Print the empty suffix.  */
1001 static void
1002 print_X (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1003          void * dis_info ATTRIBUTE_UNUSED,
1004          long value ATTRIBUTE_UNUSED,
1005          unsigned int attrs ATTRIBUTE_UNUSED,
1006          bfd_vma pc ATTRIBUTE_UNUSED,
1007          int length ATTRIBUTE_UNUSED)
1009   return;
1012 static void
1013 print_r0l_r0h (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1014                void * dis_info,
1015                long value,
1016                unsigned int attrs ATTRIBUTE_UNUSED,
1017                bfd_vma pc ATTRIBUTE_UNUSED,
1018                int length ATTRIBUTE_UNUSED)
1020   disassemble_info *info = dis_info;
1022   if (value == 0)
1023     (*info->fprintf_func) (info->stream, "r0h,r0l");
1024   else
1025     (*info->fprintf_func) (info->stream, "r0l,r0h");
1028 static void
1029 print_unsigned_bitbase (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1030                         void * dis_info,
1031                         unsigned long value,
1032                         unsigned int attrs ATTRIBUTE_UNUSED,
1033                         bfd_vma pc ATTRIBUTE_UNUSED,
1034                         int length ATTRIBUTE_UNUSED)
1036   disassemble_info *info = dis_info;
1038   (*info->fprintf_func) (info->stream, "%ld,0x%lx", value & 0x7, value >> 3);
1041 static void
1042 print_signed_bitbase (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1043                       void * dis_info,
1044                       signed long value,
1045                       unsigned int attrs ATTRIBUTE_UNUSED,
1046                       bfd_vma pc ATTRIBUTE_UNUSED,
1047                       int length ATTRIBUTE_UNUSED)
1049   disassemble_info *info = dis_info;
1051   (*info->fprintf_func) (info->stream, "%ld,%ld", value & 0x7, value >> 3);
1054 static void
1055 print_size (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1056             void * dis_info,
1057             long value ATTRIBUTE_UNUSED,
1058             unsigned int attrs ATTRIBUTE_UNUSED,
1059             bfd_vma pc ATTRIBUTE_UNUSED,
1060             int length ATTRIBUTE_UNUSED)
1062   /* Always print the size as '.w'.  */
1063   disassemble_info *info = dis_info;
1065   (*info->fprintf_func) (info->stream, ".w");
1068 #define POP  0
1069 #define PUSH 1
1071 static void print_pop_regset  (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
1072 static void print_push_regset (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
1074 /* Print a set of registers, R0,R1,A0,A1,SB,FB.  */
1076 static void
1077 print_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1078               void * dis_info,
1079               long value,
1080               unsigned int attrs ATTRIBUTE_UNUSED,
1081               bfd_vma pc ATTRIBUTE_UNUSED,
1082               int length ATTRIBUTE_UNUSED,
1083               int push)
1085   static char * m16c_register_names [] = 
1086   {
1087     "r0", "r1", "r2", "r3", "a0", "a1", "sb", "fb"
1088   };
1089   disassemble_info *info = dis_info;
1090   int mask;
1091   int index = 0;
1092   char* comma = "";
1094   if (push)
1095     mask = 0x80;
1096   else
1097     mask = 1;
1099   if (value & mask)
1100     {
1101       (*info->fprintf_func) (info->stream, "%s", m16c_register_names [0]);
1102       comma = ",";
1103     }
1105   for (index = 1; index <= 7; ++index)
1106     {
1107       if (push)
1108         mask >>= 1;
1109       else
1110         mask <<= 1;
1112       if (value & mask)
1113         {
1114           (*info->fprintf_func) (info->stream, "%s%s", comma,
1115                                  m16c_register_names [index]);
1116           comma = ",";
1117         }
1118     }
1121 static void
1122 print_pop_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1123                   void * dis_info,
1124                   long value,
1125                   unsigned int attrs ATTRIBUTE_UNUSED,
1126                   bfd_vma pc ATTRIBUTE_UNUSED,
1127                   int length ATTRIBUTE_UNUSED)
1129   print_regset (cd, dis_info, value, attrs, pc, length, POP);
1132 static void
1133 print_push_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1134                    void * dis_info,
1135                    long value,
1136                    unsigned int attrs ATTRIBUTE_UNUSED,
1137                    bfd_vma pc ATTRIBUTE_UNUSED,
1138                    int length ATTRIBUTE_UNUSED)
1140   print_regset (cd, dis_info, value, attrs, pc, length, PUSH);
1143 static void
1144 print_signed4n (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1145                 void * dis_info,
1146                 signed long value,
1147                 unsigned int attrs ATTRIBUTE_UNUSED,
1148                 bfd_vma pc ATTRIBUTE_UNUSED,
1149                 int length ATTRIBUTE_UNUSED)
1151   disassemble_info *info = dis_info;
1153   (*info->fprintf_func) (info->stream, "%ld", -value);