OSDN Git Service

cpu/
[pf3gnuchains/pf3gnuchains4x.git] / cpu / m32c.opc
1 /* m32c opcode support.  -*- C -*-
2
3    Copyright 2005, 2007 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-types.h"
44 #include "cgen-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;
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 value;
166       const char *errmsg;
167
168       *strp += 6;
169       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_8,
170                                    & result_type, & value);
171       if (**strp != ')')
172         return _("missing `)'");
173       (*strp) ++;
174
175       if (errmsg == NULL
176           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
177         {
178           return _("%dsp8() takes a symbolic address, not a number");
179         }
180       *valuep = value;
181       return errmsg;
182     }
183
184   if (strncmp (*strp, "0x0", 3) == 0 
185       || (**strp == '0' && *(*strp + 1) != 'x'))
186     have_zero = 1;
187
188   PARSE_UNSIGNED;
189
190   if (value > 0xff)
191     return _("dsp:8 immediate is out of range");
192
193   /* If this field may require a relocation then use larger dsp16.  */
194   if (! have_zero && value == 0)
195     return _("dsp:8 immediate is out of range");
196
197   *valuep = value;
198   return 0;
199 }
200
201 static const char *
202 parse_signed4 (CGEN_CPU_DESC cd, const char **strp,
203                int opindex, signed long *valuep)
204 {
205   const char *errmsg = 0;
206   signed long value;
207   long have_zero = 0;
208
209   if (strncmp (*strp, "0x0", 3) == 0 
210       || (**strp == '0' && *(*strp + 1) != 'x'))
211     have_zero = 1;
212
213   PARSE_SIGNED;
214
215   if (value < -8 || value > 7)
216     return _("Immediate is out of range -8 to 7");
217
218   /* If this field may require a relocation then use larger dsp16.  */
219   if (! have_zero && value == 0)
220     return _("Immediate is out of range -8 to 7");
221
222   *valuep = value;
223   return 0;
224 }
225
226 static const char *
227 parse_signed4n (CGEN_CPU_DESC cd, const char **strp,
228                 int opindex, signed long *valuep)
229 {
230   const char *errmsg = 0;
231   signed long value;
232   long have_zero = 0;
233
234   if (strncmp (*strp, "0x0", 3) == 0 
235       || (**strp == '0' && *(*strp + 1) != 'x'))
236     have_zero = 1;
237
238   PARSE_SIGNED;
239
240   if (value < -7 || value > 8)
241     return _("Immediate is out of range -7 to 8");
242
243   /* If this field may require a relocation then use larger dsp16.  */
244   if (! have_zero && value == 0)
245     return _("Immediate is out of range -7 to 8");
246
247   *valuep = -value;
248   return 0;
249 }
250
251 static const char *
252 parse_signed8 (CGEN_CPU_DESC cd, const char **strp,
253                int opindex, signed long *valuep)
254 {
255   const char *errmsg = 0;
256   signed long value;
257
258   if (strncasecmp (*strp, "%hi8(", 5) == 0)
259     {
260       enum cgen_parse_operand_result result_type;
261       bfd_vma value;
262       const char *errmsg;
263
264       *strp += 5;
265       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32C_HI8,
266                                    & result_type, & value);
267       if (**strp != ')')
268         return _("missing `)'");
269       (*strp) ++;
270
271       if (errmsg == NULL
272           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
273         {
274           value >>= 16;
275         }
276       *valuep = value;
277       return errmsg;
278     }
279
280   PARSE_SIGNED;
281
282   if (value <= 255 && value > 127)
283     value -= 0x100;
284
285   if (value < -128 || value > 127)
286     return _("dsp:8 immediate is out of range");
287
288   *valuep = value;
289   return 0;
290 }
291
292 static const char *
293 parse_unsigned16 (CGEN_CPU_DESC cd, const char **strp,
294                  int opindex, unsigned long *valuep)
295 {
296   const char *errmsg = 0;
297   unsigned long value;
298   long have_zero = 0;
299
300   if (strncasecmp (*strp, "%dsp16(", 7) == 0)
301     {
302       enum cgen_parse_operand_result result_type;
303       bfd_vma value;
304       const char *errmsg;
305
306       *strp += 7;
307       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_16,
308                                    & result_type, & value);
309       if (**strp != ')')
310         return _("missing `)'");
311       (*strp) ++;
312
313       if (errmsg == NULL
314           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
315         {
316           return _("%dsp16() takes a symbolic address, not a number");
317         }
318       *valuep = value;
319       return errmsg;
320     }
321
322   /* Don't successfully parse literals beginning with '['.  */
323   if (**strp == '[')
324     return "Invalid literal"; /* Anything -- will not be seen.  */
325
326   /* Don't successfully parse register names.  */
327   if (m32c_cgen_isa_register (strp))
328     return "Invalid literal"; /* Anything -- will not be seen.  */
329
330   if (strncmp (*strp, "0x0", 3) == 0 
331       || (**strp == '0' && *(*strp + 1) != 'x'))
332     have_zero = 1;
333   
334   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
335   if (errmsg)
336     return errmsg;
337
338   if (value > 0xffff)
339     return _("dsp:16 immediate is out of range");
340
341   /* If this field may require a relocation then use larger dsp24.  */
342   if (cd->machs == MACH_M32C && ! have_zero && value == 0
343       && (strncmp (*strp, "[a", 2) == 0
344           || **strp == ','
345           || **strp == 0))
346     return _("dsp:16 immediate is out of range");
347
348   *valuep = value;
349   return 0;
350 }
351
352 static const char *
353 parse_signed16 (CGEN_CPU_DESC cd, const char **strp,
354                int opindex, signed long *valuep)
355 {
356   const char *errmsg = 0;
357   signed long value;
358
359   if (strncasecmp (*strp, "%lo16(", 6) == 0)
360     {
361       enum cgen_parse_operand_result result_type;
362       bfd_vma value;
363       const char *errmsg;
364
365       *strp += 6;
366       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
367                                    & result_type, & value);
368       if (**strp != ')')
369         return _("missing `)'");
370       (*strp) ++;
371
372       if (errmsg == NULL
373           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
374         {
375           value &= 0xffff;
376         }
377       *valuep = value;
378       return errmsg;
379     }
380
381   if (strncasecmp (*strp, "%hi16(", 6) == 0)
382     {
383       enum cgen_parse_operand_result result_type;
384       bfd_vma value;
385       const char *errmsg;
386
387       *strp += 6;
388       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16,
389                                    & result_type, & value);
390       if (**strp != ')')
391         return _("missing `)'");
392       (*strp) ++;
393
394       if (errmsg == NULL
395           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
396         {
397           value >>= 16;
398         }
399       *valuep = value;
400       return errmsg;
401     }
402
403   PARSE_SIGNED;
404
405   if (value <= 65535 && value > 32767)
406     value -= 0x10000;
407
408   if (value < -32768 || value > 32767)
409     return _("dsp:16 immediate is out of range");
410
411   *valuep = value;
412   return 0;
413 }
414
415 static const char *
416 parse_unsigned20 (CGEN_CPU_DESC cd, const char **strp,
417                  int opindex, unsigned long *valuep)
418 {
419   const char *errmsg = 0;
420   unsigned long value;
421   
422   /* Don't successfully parse literals beginning with '['.  */
423   if (**strp == '[')
424     return "Invalid literal"; /* Anything -- will not be seen.  */
425
426   /* Don't successfully parse register names.  */
427   if (m32c_cgen_isa_register (strp))
428     return "Invalid literal"; /* Anything -- will not be seen.  */
429
430   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
431   if (errmsg)
432     return errmsg;
433
434   if (value > 0xfffff)
435     return _("dsp:20 immediate is out of range");
436
437   *valuep = value;
438   return 0;
439 }
440
441 static const char *
442 parse_unsigned24 (CGEN_CPU_DESC cd, const char **strp,
443                  int opindex, unsigned long *valuep)
444 {
445   const char *errmsg = 0;
446   unsigned long value;
447   
448   /* Don't successfully parse literals beginning with '['.  */
449   if (**strp == '[')
450     return "Invalid literal"; /* Anything -- will not be seen.  */
451
452   /* Don't successfully parse register names.  */
453   if (m32c_cgen_isa_register (strp))
454     return "Invalid literal"; /* Anything -- will not be seen.  */
455
456   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
457   if (errmsg)
458     return errmsg;
459
460   if (value > 0xffffff)
461     return _("dsp:24 immediate is out of range");
462
463   *valuep = value;
464   return 0;
465 }
466
467 /* This should only be used for #imm->reg.  */
468 static const char *
469 parse_signed24 (CGEN_CPU_DESC cd, const char **strp,
470                  int opindex, signed long *valuep)
471 {
472   const char *errmsg = 0;
473   signed long value;
474
475   PARSE_SIGNED;
476
477   if (value <= 0xffffff && value > 0x7fffff)
478     value -= 0x1000000;
479
480   if (value > 0xffffff)
481     return _("dsp:24 immediate is out of range");
482
483   *valuep = value;
484   return 0;
485 }
486
487 static const char *
488 parse_signed32 (CGEN_CPU_DESC cd, const char **strp,
489                 int opindex, signed long *valuep)
490 {
491   const char *errmsg = 0;
492   signed long value;
493   
494   errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
495   if (errmsg)
496     return errmsg;
497
498   *valuep = value;
499   return 0;
500 }
501
502 static const char *
503 parse_imm1_S (CGEN_CPU_DESC cd, const char **strp,
504              int opindex, signed long *valuep)
505 {
506   const char *errmsg = 0;
507   signed long value;
508
509   errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
510   if (errmsg)
511     return errmsg;
512
513   if (value < 1 || value > 2)
514     return _("immediate is out of range 1-2");
515
516   *valuep = value;
517   return 0;
518 }
519
520 static const char *
521 parse_imm3_S (CGEN_CPU_DESC cd, const char **strp,
522              int opindex, signed long *valuep)
523 {
524   const char *errmsg = 0;
525   signed long value;
526   
527   errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
528   if (errmsg)
529     return errmsg;
530
531   if (value < 1 || value > 8)
532     return _("immediate is out of range 1-8");
533
534   *valuep = value;
535   return 0;
536 }
537
538 static const char *
539 parse_bit3_S (CGEN_CPU_DESC cd, const char **strp,
540              int opindex, signed long *valuep)
541 {
542   const char *errmsg = 0;
543   signed long value;
544   
545   errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
546   if (errmsg)
547     return errmsg;
548
549   if (value < 0 || value > 7)
550     return _("immediate is out of range 0-7");
551
552   *valuep = value;
553   return 0;
554 }
555
556 static const char *
557 parse_lab_5_3 (CGEN_CPU_DESC cd,
558                const char **strp,
559                int opindex ATTRIBUTE_UNUSED,
560                int opinfo,
561                enum cgen_parse_operand_result *type_addr,
562                bfd_vma *valuep)
563 {
564   const char *errmsg = 0;
565   bfd_vma value;
566   enum cgen_parse_operand_result op_res;
567
568   errmsg = cgen_parse_address (cd, strp, M32C_OPERAND_LAB_5_3,
569                                opinfo, & op_res, & value);
570
571   if (type_addr)
572     *type_addr = op_res;
573
574   if (op_res == CGEN_PARSE_OPERAND_RESULT_QUEUED)
575     {
576       /* This is a hack; the field cannot handle near-zero signed
577          offsets that CGEN wants to put in to indicate an "empty"
578          operand at first.  */
579       *valuep = 2;
580       return 0;
581     }
582   if (errmsg)
583     return errmsg;
584
585   if (value < 2 || value > 9)
586     return _("immediate is out of range 2-9");
587
588   *valuep = value;
589   return 0;
590 }
591
592 static const char *
593 parse_Bitno16R (CGEN_CPU_DESC cd, const char **strp,
594                 int opindex, unsigned long *valuep)
595 {
596   const char *errmsg = 0;
597   unsigned long value;
598
599   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
600   if (errmsg)
601     return errmsg;
602
603   if (value > 15)
604     return _("Bit number for indexing general register is out of range 0-15");
605
606   *valuep = value;
607   return 0;
608 }
609
610 static const char *
611 parse_unsigned_bitbase (CGEN_CPU_DESC cd, const char **strp,
612                         int opindex, unsigned long *valuep,
613                         unsigned bits, int allow_syms)
614 {
615   const char *errmsg = 0;
616   unsigned long bit;
617   unsigned long base;
618   const char *newp = *strp;
619   unsigned long long bitbase;
620   long have_zero = 0;
621
622   errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & bit);
623   if (errmsg)
624     return errmsg;
625
626   if (*newp != ',')
627     return "Missing base for bit,base:8";
628
629   ++newp;
630
631   if (strncmp (newp, "0x0", 3) == 0 
632       || (newp[0] == '0' && newp[1] != 'x'))
633     have_zero = 1;
634
635   errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & base);
636   if (errmsg)
637     return errmsg;
638
639   bitbase = (unsigned long long) bit + ((unsigned long long) base * 8);
640
641   if (bitbase >= (1ull << bits))
642     return _("bit,base is out of range");
643
644   /* If this field may require a relocation then use larger displacement.  */
645   if (! have_zero && base == 0)
646     {
647       switch (allow_syms) {
648       case 0:
649         return _("bit,base out of range for symbol");
650       case 1:
651         break;
652       case 2:
653         if (strncmp (newp, "[sb]", 4) != 0)
654           return _("bit,base out of range for symbol");
655         break;
656       }
657     }
658
659   *valuep = bitbase;
660   *strp = newp;
661   return 0;
662 }
663
664 static const char *
665 parse_signed_bitbase (CGEN_CPU_DESC cd, const char **strp,
666                       int opindex, signed long *valuep,
667                       unsigned bits, int allow_syms)
668 {
669   const char *errmsg = 0;
670   unsigned long bit;
671   signed long base;
672   const char *newp = *strp;
673   long long bitbase;
674   long long limit;
675   long have_zero = 0;
676
677   errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & bit);
678   if (errmsg)
679     return errmsg;
680
681   if (*newp != ',')
682     return "Missing base for bit,base:8";
683
684   ++newp;
685
686   if (strncmp (newp, "0x0", 3) == 0 
687       || (newp[0] == '0' && newp[1] != 'x'))
688     have_zero = 1;
689
690   errmsg = cgen_parse_signed_integer (cd, & newp, opindex, & base);
691   if (errmsg)
692     return errmsg;
693
694   bitbase = (long long)bit + ((long long)base * 8);
695
696   limit = 1ll << (bits - 1);
697   if (bitbase < -limit || bitbase >= limit)
698     return _("bit,base is out of range");
699
700   /* If this field may require a relocation then use larger displacement.  */
701   if (! have_zero && base == 0 && ! allow_syms)
702     return _("bit,base out of range for symbol");
703
704   *valuep = bitbase;
705   *strp = newp;
706   return 0;
707 }
708
709 static const char *
710 parse_unsigned_bitbase8 (CGEN_CPU_DESC cd, const char **strp,
711                          int opindex, unsigned long *valuep)
712 {
713   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 8, 0);
714 }
715
716 static const char *
717 parse_unsigned_bitbase11 (CGEN_CPU_DESC cd, const char **strp,
718                          int opindex, unsigned long *valuep)
719 {
720   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 11, 0);
721 }
722
723 static const char *
724 parse_unsigned_bitbase16 (CGEN_CPU_DESC cd, const char **strp,
725                           int opindex, unsigned long *valuep)
726 {
727   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 16, 1);
728 }
729
730 static const char *
731 parse_unsigned_bitbase19 (CGEN_CPU_DESC cd, const char **strp,
732                          int opindex, unsigned long *valuep)
733 {
734   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 19, 2);
735 }
736
737 static const char *
738 parse_unsigned_bitbase27 (CGEN_CPU_DESC cd, const char **strp,
739                          int opindex, unsigned long *valuep)
740 {
741   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 27, 1);
742 }
743
744 static const char *
745 parse_signed_bitbase8 (CGEN_CPU_DESC cd, const char **strp,
746                        int opindex, signed long *valuep)
747 {
748   return parse_signed_bitbase (cd, strp, opindex, valuep, 8, 1);
749 }
750
751 static const char *
752 parse_signed_bitbase11 (CGEN_CPU_DESC cd, const char **strp,
753                        int opindex, signed long *valuep)
754 {
755   return parse_signed_bitbase (cd, strp, opindex, valuep, 11, 0);
756 }
757
758 static const char *
759 parse_signed_bitbase19 (CGEN_CPU_DESC cd, const char **strp,
760                        int opindex, signed long *valuep)
761 {
762   return parse_signed_bitbase (cd, strp, opindex, valuep, 19, 1);
763 }
764
765 /* Parse the suffix as :<char> or as nothing followed by a whitespace.  */
766
767 static const char *
768 parse_suffix (const char **strp, char suffix)
769 {
770   const char *newp = *strp;
771   
772   if (**strp == ':' && TOLOWER (*(*strp + 1)) == suffix)
773     newp = *strp + 2;
774
775   if (ISSPACE (*newp))
776     {
777       *strp = newp;
778       return 0;
779     }
780         
781   return "Invalid suffix"; /* Anything -- will not be seen.  */
782 }
783
784 static const char *
785 parse_S (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
786          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
787 {
788   return parse_suffix (strp, 's');
789 }
790
791 static const char *
792 parse_G (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
793          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
794 {
795   return parse_suffix (strp, 'g');
796 }
797
798 static const char *
799 parse_Q (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
800          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
801 {
802   return parse_suffix (strp, 'q');
803 }
804
805 static const char *
806 parse_Z (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
807          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
808 {
809   return parse_suffix (strp, 'z');
810 }
811
812 /* Parse an empty suffix. Fail if the next char is ':'.  */
813
814 static const char *
815 parse_X (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
816          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
817 {
818   if (**strp == ':')
819     return "Unexpected suffix";
820   return 0;
821 }
822
823 static const char *
824 parse_r0l_r0h (CGEN_CPU_DESC cd, const char **strp,
825                int opindex ATTRIBUTE_UNUSED, signed long *valuep)
826 {
827   const char *errmsg;
828   signed long value;
829   signed long junk;
830   const char *newp = *strp;
831
832   /* Parse r0[hl].  */
833   errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0l_r0h, & value);
834   if (errmsg)
835     return errmsg;
836
837   if (*newp != ',')
838     return _("not a valid r0l/r0h pair");
839   ++newp;
840
841   /* Parse the second register in the pair.  */
842   if (value == 0) /* r0l */
843     errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0h, & junk);
844   else
845     errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0l, & junk);
846   if (errmsg)
847     return errmsg;
848
849   *strp = newp;
850   *valuep = ! value;
851   return 0;
852 }
853
854 /* Accept .b or .w in any case.  */
855
856 static const char *
857 parse_size (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
858             int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
859 {
860   if (**strp == '.'
861       && (*(*strp + 1) == 'b' || *(*strp + 1) == 'B'
862           || *(*strp + 1) == 'w' || *(*strp + 1) == 'W'))
863     {
864       *strp += 2;
865       return NULL;
866     }
867
868   return _("Invalid size specifier");
869 }
870
871 /* Special check to ensure that instruction exists for given machine.  */
872
873 int
874 m32c_cgen_insn_supported (CGEN_CPU_DESC cd,
875                           const CGEN_INSN *insn)
876 {
877   int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
878   CGEN_BITSET isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA);
879
880   /* If attributes are absent, assume no restriction.  */
881   if (machs == 0)
882     machs = ~0;
883
884   return ((machs & cd->machs)
885           && cgen_bitset_intersect_p (& isas, cd->isas));
886 }
887
888 /* Parse a set of registers, R0,R1,A0,A1,SB,FB.  */
889
890 static const char *
891 parse_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
892               const char **strp,
893               int opindex ATTRIBUTE_UNUSED,
894               unsigned long *valuep,
895               int push)
896 {
897   const char *errmsg = 0;
898   int regno = 0;
899  
900   *valuep = 0;
901   while (**strp && **strp != ')')
902     {
903       if (**strp == 'r' || **strp == 'R')
904         {
905           ++*strp;
906           regno = **strp - '0';
907           if (regno > 4)
908             errmsg = _("Register number is not valid");
909         }
910       else if (**strp == 'a' || **strp == 'A')
911         {
912           ++*strp;
913           regno = **strp - '0';
914           if (regno > 2)
915             errmsg = _("Register number is not valid");
916           regno = **strp - '0' + 4;
917         }
918       
919       else if (strncasecmp (*strp, "sb", 2) == 0 || strncasecmp (*strp, "SB", 2) == 0)
920         {
921           regno = 6;
922           ++*strp;
923         }
924       
925       else if (strncasecmp (*strp, "fb", 2) == 0 || strncasecmp (*strp, "FB", 2) == 0)
926         {
927           regno = 7;
928           ++*strp;
929         }
930       
931       if (push) /* Mask is reversed for push.  */
932         *valuep |= 0x80 >> regno;
933       else
934         *valuep |= 1 << regno;
935
936       ++*strp;
937       if (**strp == ',')
938         {
939           if (*(*strp + 1) == ')')
940             break;
941           ++*strp;
942         }
943     }
944
945   if (!*strp)
946     errmsg = _("Register list is not valid");
947
948   return errmsg;
949 }
950
951 #define POP  0
952 #define PUSH 1
953
954 static const char *
955 parse_pop_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
956                   const char **strp,
957                   int opindex ATTRIBUTE_UNUSED,
958                   unsigned long *valuep)
959 {
960   return parse_regset (cd, strp, opindex, valuep, POP);
961 }
962
963 static const char *
964 parse_push_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
965                    const char **strp,
966                    int opindex ATTRIBUTE_UNUSED,
967                    unsigned long *valuep)
968 {
969   return parse_regset (cd, strp, opindex, valuep, PUSH);
970 }
971
972 /* -- dis.c */
973
974 #include "elf/m32c.h"
975 #include "elf-bfd.h"
976
977 /* Always print the short insn format suffix as ':<char>'.  */
978
979 static void
980 print_suffix (void * dis_info, char suffix)
981 {
982   disassemble_info *info = dis_info;
983
984   (*info->fprintf_func) (info->stream, ":%c", suffix);
985 }
986
987 static void
988 print_S (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)
994 {
995   print_suffix (dis_info, 's');
996 }
997
998
999 static void
1000 print_G (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1001          void * dis_info,
1002          long value ATTRIBUTE_UNUSED,
1003          unsigned int attrs ATTRIBUTE_UNUSED,
1004          bfd_vma pc ATTRIBUTE_UNUSED,
1005          int length ATTRIBUTE_UNUSED)
1006 {
1007   print_suffix (dis_info, 'g');
1008 }
1009
1010 static void
1011 print_Q (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1012          void * dis_info,
1013          long value ATTRIBUTE_UNUSED,
1014          unsigned int attrs ATTRIBUTE_UNUSED,
1015          bfd_vma pc ATTRIBUTE_UNUSED,
1016          int length ATTRIBUTE_UNUSED)
1017 {
1018   print_suffix (dis_info, 'q');
1019 }
1020
1021 static void
1022 print_Z (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1023          void * dis_info,
1024          long value ATTRIBUTE_UNUSED,
1025          unsigned int attrs ATTRIBUTE_UNUSED,
1026          bfd_vma pc ATTRIBUTE_UNUSED,
1027          int length ATTRIBUTE_UNUSED)
1028 {
1029   print_suffix (dis_info, 'z');
1030 }
1031
1032 /* Print the empty suffix.  */
1033
1034 static void
1035 print_X (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1036          void * dis_info ATTRIBUTE_UNUSED,
1037          long value ATTRIBUTE_UNUSED,
1038          unsigned int attrs ATTRIBUTE_UNUSED,
1039          bfd_vma pc ATTRIBUTE_UNUSED,
1040          int length ATTRIBUTE_UNUSED)
1041 {
1042   return;
1043 }
1044
1045 static void
1046 print_r0l_r0h (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1047                void * dis_info,
1048                long value,
1049                unsigned int attrs ATTRIBUTE_UNUSED,
1050                bfd_vma pc ATTRIBUTE_UNUSED,
1051                int length ATTRIBUTE_UNUSED)
1052 {
1053   disassemble_info *info = dis_info;
1054
1055   if (value == 0)
1056     (*info->fprintf_func) (info->stream, "r0h,r0l");
1057   else
1058     (*info->fprintf_func) (info->stream, "r0l,r0h");
1059 }
1060
1061 static void
1062 print_unsigned_bitbase (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1063                         void * dis_info,
1064                         unsigned long value,
1065                         unsigned int attrs ATTRIBUTE_UNUSED,
1066                         bfd_vma pc ATTRIBUTE_UNUSED,
1067                         int length ATTRIBUTE_UNUSED)
1068 {
1069   disassemble_info *info = dis_info;
1070
1071   (*info->fprintf_func) (info->stream, "%ld,0x%lx", value & 0x7, value >> 3);
1072 }
1073
1074 static void
1075 print_signed_bitbase (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1076                       void * dis_info,
1077                       signed long value,
1078                       unsigned int attrs ATTRIBUTE_UNUSED,
1079                       bfd_vma pc ATTRIBUTE_UNUSED,
1080                       int length ATTRIBUTE_UNUSED)
1081 {
1082   disassemble_info *info = dis_info;
1083
1084   (*info->fprintf_func) (info->stream, "%ld,%ld", value & 0x7, value >> 3);
1085 }
1086
1087 static void
1088 print_size (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1089             void * dis_info,
1090             long value ATTRIBUTE_UNUSED,
1091             unsigned int attrs ATTRIBUTE_UNUSED,
1092             bfd_vma pc ATTRIBUTE_UNUSED,
1093             int length ATTRIBUTE_UNUSED)
1094 {
1095   /* Always print the size as '.w'.  */
1096   disassemble_info *info = dis_info;
1097
1098   (*info->fprintf_func) (info->stream, ".w");
1099 }
1100
1101 #define POP  0
1102 #define PUSH 1
1103
1104 static void print_pop_regset  (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
1105 static void print_push_regset (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
1106
1107 /* Print a set of registers, R0,R1,A0,A1,SB,FB.  */
1108
1109 static void
1110 print_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1111               void * dis_info,
1112               long value,
1113               unsigned int attrs ATTRIBUTE_UNUSED,
1114               bfd_vma pc ATTRIBUTE_UNUSED,
1115               int length ATTRIBUTE_UNUSED,
1116               int push)
1117 {
1118   static char * m16c_register_names [] = 
1119   {
1120     "r0", "r1", "r2", "r3", "a0", "a1", "sb", "fb"
1121   };
1122   disassemble_info *info = dis_info;
1123   int mask;
1124   int index = 0;
1125   char* comma = "";
1126
1127   if (push)
1128     mask = 0x80;
1129   else
1130     mask = 1;
1131  
1132   if (value & mask)
1133     {
1134       (*info->fprintf_func) (info->stream, "%s", m16c_register_names [0]);
1135       comma = ",";
1136     }
1137
1138   for (index = 1; index <= 7; ++index)
1139     {
1140       if (push)
1141         mask >>= 1;
1142       else
1143         mask <<= 1;
1144
1145       if (value & mask)
1146         {
1147           (*info->fprintf_func) (info->stream, "%s%s", comma,
1148                                  m16c_register_names [index]);
1149           comma = ",";
1150         }
1151     }
1152 }
1153
1154 static void
1155 print_pop_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1156                   void * dis_info,
1157                   long value,
1158                   unsigned int attrs ATTRIBUTE_UNUSED,
1159                   bfd_vma pc ATTRIBUTE_UNUSED,
1160                   int length ATTRIBUTE_UNUSED)
1161 {
1162   print_regset (cd, dis_info, value, attrs, pc, length, POP);
1163 }
1164
1165 static void
1166 print_push_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1167                    void * dis_info,
1168                    long value,
1169                    unsigned int attrs ATTRIBUTE_UNUSED,
1170                    bfd_vma pc ATTRIBUTE_UNUSED,
1171                    int length ATTRIBUTE_UNUSED)
1172 {
1173   print_regset (cd, dis_info, value, attrs, pc, length, PUSH);
1174 }
1175
1176 static void
1177 print_signed4n (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1178                 void * dis_info,
1179                 signed long value,
1180                 unsigned int attrs ATTRIBUTE_UNUSED,
1181                 bfd_vma pc ATTRIBUTE_UNUSED,
1182                 int length ATTRIBUTE_UNUSED)
1183 {
1184   disassemble_info *info = dis_info;
1185
1186   (*info->fprintf_func) (info->stream, "%ld", -value);
1187 }