Fix building for MS1 and M32C.
[platform/upstream/binutils.git] / cpu / m32c.opc
1 /* m32c opcode support.  -*- C -*-
2
3    Copyright 2005 Free Software Foundation, Inc.
4
5    Contributed by Red Hat Inc; developed under contract from Renesas
6
7    This file is part of the GNU Binutils.
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
22
23 /* This file is an addendum to m32c.cpu.  Heavy use of C code isn't
24    appropriate in .cpu files, so it resides here.  This especially applies
25    to assembly/disassembly where parsing/printing can be quite involved.
26    Such things aren't really part of the specification of the cpu, per se,
27    so .cpu files provide the general framework and .opc files handle the
28    nitty-gritty details as necessary.
29
30    Each section is delimited with start and end markers.
31
32    <arch>-opc.h additions use: "-- opc.h"
33    <arch>-opc.c additions use: "-- opc.c"
34    <arch>-asm.c additions use: "-- asm.c"
35    <arch>-dis.c additions use: "-- dis.c"
36    <arch>-ibd.h additions use: "-- ibd.h".  */
37 \f
38 /* -- opc.h */
39
40 /* Needed for RTL's 'ext' and 'trunc' operators.  */
41 #include "cgen-types.h"
42 #include "cgen-ops.h"
43
44 /* We can't use the default hash size because many bits are used by
45    operands.  */
46 #define CGEN_DIS_HASH_SIZE 1
47 #define CGEN_DIS_HASH(buf, value) 0
48 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
49 #define CGEN_VALIDATE_INSN_SUPPORTED
50
51 extern int m32c_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
52
53 #define CGEN_ASM_HASH_SIZE 0xffff
54 #define CGEN_ASM_HASH(mnem) m32c_asm_hash ((mnem))
55
56 /* -- */
57 \f
58 /* -- opc.c */
59 static unsigned int
60 m32c_asm_hash (const char *mnem)
61 {
62   unsigned int h;
63   
64   /* The length of the mnemonic for the Jcnd insns is 1.  Hash jsri.  */
65   if (mnem[0] == 'j' && mnem[1] != 's')
66     return 'j';
67   
68   /* Don't hash scCND  */
69   if (mnem[0] == 's' && mnem[1] == 'c')
70     return 's';
71   
72   for (h = 0; *mnem && *mnem != ' ' && *mnem != ':'; ++mnem)
73     h += *mnem;
74   return h % CGEN_ASM_HASH_SIZE;
75 }
76 \f
77 /* -- asm.c */
78 #include "safe-ctype.h"
79
80 #define MACH_M32C 5             /* Must match md_begin.  */
81
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      };
94  
95    for (u = 0; m32c_register_names[u]; u++)
96      {
97        int len = strlen (m32c_register_names[u]);
98
99        if (memcmp (m32c_register_names[u], s, len) == 0
100            && (s[len] == 0 || ! ISALNUM (s[len])))
101         return 1;
102      }
103    return 0;
104 }
105
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)
118
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)
131
132 static const char *
133 parse_unsigned6 (CGEN_CPU_DESC cd, const char **strp,
134                  int opindex, unsigned long *valuep)
135 {
136   const char *errmsg = 0;
137   unsigned long value;
138
139   PARSE_UNSIGNED;
140
141   if (value > 0x3f)
142     return _("imm:6 immediate is out of range");
143
144   *valuep = value;
145   return 0;
146 }
147
148 static const char *
149 parse_unsigned8 (CGEN_CPU_DESC cd, const char **strp,
150                  int opindex, unsigned long *valuep)
151 {
152   const char *errmsg = 0;
153   unsigned long value;
154   long have_zero = 0;
155
156   if (strncmp (*strp, "0x0", 3) == 0 
157       || (**strp == '0' && *(*strp + 1) != 'x'))
158     have_zero = 1;
159
160   PARSE_UNSIGNED;
161
162   if (value > 0xff)
163     return _("dsp:8 immediate is out of range");
164
165   /* If this field may require a relocation then use larger dsp16.  */
166   if (! have_zero && value == 0)
167     return _("dsp:8 immediate is out of range");
168
169   *valuep = value;
170   return 0;
171 }
172
173 static const char *
174 parse_signed4 (CGEN_CPU_DESC cd, const char **strp,
175                int opindex, signed long *valuep)
176 {
177   const char *errmsg = 0;
178   signed long value;
179   long have_zero = 0;
180
181   if (strncmp (*strp, "0x0", 3) == 0 
182       || (**strp == '0' && *(*strp + 1) != 'x'))
183     have_zero = 1;
184
185   PARSE_SIGNED;
186
187   if (value < -8 || value > 7)
188     return _("Immediate is out of range -8 to 7");
189
190   /* If this field may require a relocation then use larger dsp16.  */
191   if (! have_zero && value == 0)
192     return _("Immediate is out of range -8 to 7");
193
194   *valuep = value;
195   return 0;
196 }
197
198 static const char *
199 parse_signed8 (CGEN_CPU_DESC cd, const char **strp,
200                int opindex, signed long *valuep)
201 {
202   const char *errmsg = 0;
203   signed long value;
204   
205   PARSE_SIGNED;
206
207   if (value <= 255 && value > 127)
208     value -= 0x100;
209
210   if (value < -128 || value > 127)
211     return _("dsp:8 immediate is out of range");
212
213   *valuep = value;
214   return 0;
215 }
216
217 static const char *
218 parse_unsigned16 (CGEN_CPU_DESC cd, const char **strp,
219                  int opindex, unsigned long *valuep)
220 {
221   const char *errmsg = 0;
222   unsigned long value;
223   long have_zero = 0;
224  
225   /* Don't successfully parse literals beginning with '['.  */
226   if (**strp == '[')
227     return "Invalid literal"; /* Anything -- will not be seen.  */
228
229   /* Don't successfully parse register names.  */
230   if (m32c_cgen_isa_register (strp))
231     return "Invalid literal"; /* Anything -- will not be seen.  */
232
233   if (strncmp (*strp, "0x0", 3) == 0 
234       || (**strp == '0' && *(*strp + 1) != 'x'))
235     have_zero = 1;
236   
237   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
238   if (errmsg)
239     return errmsg;
240
241   if (value > 0xffff)
242     return _("dsp:16 immediate is out of range");
243
244   /* If this field may require a relocation then use larger dsp24.  */
245   if (cd->machs == MACH_M32C && ! have_zero && value == 0
246       && (strncmp (*strp, "[a", 2) == 0
247           || **strp == ','
248           || **strp == 0))
249     return _("dsp:16 immediate is out of range");
250
251   *valuep = value;
252   return 0;
253 }
254
255 static const char *
256 parse_signed16 (CGEN_CPU_DESC cd, const char **strp,
257                int opindex, signed long *valuep)
258 {
259   const char *errmsg = 0;
260   signed long value;
261
262   PARSE_SIGNED;
263
264   if (value <= 65535 && value > 32767)
265     value -= 0x10000;
266
267   if (value < -32768 || value > 32767)
268     return _("dsp:16 immediate is out of range");
269
270   *valuep = value;
271   return 0;
272 }
273
274 static const char *
275 parse_unsigned20 (CGEN_CPU_DESC cd, const char **strp,
276                  int opindex, unsigned long *valuep)
277 {
278   const char *errmsg = 0;
279   unsigned long value;
280   
281   /* Don't successfully parse literals beginning with '['.  */
282   if (**strp == '[')
283     return "Invalid literal"; /* Anything -- will not be seen.  */
284
285   /* Don't successfully parse register names.  */
286   if (m32c_cgen_isa_register (strp))
287     return "Invalid literal"; /* Anything -- will not be seen.  */
288
289   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
290   if (errmsg)
291     return errmsg;
292
293   if (value > 0xfffff)
294     return _("dsp:20 immediate is out of range");
295
296   *valuep = value;
297   return 0;
298 }
299
300 static const char *
301 parse_unsigned24 (CGEN_CPU_DESC cd, const char **strp,
302                  int opindex, unsigned long *valuep)
303 {
304   const char *errmsg = 0;
305   unsigned long value;
306   
307   /* Don't successfully parse literals beginning with '['.  */
308   if (**strp == '[')
309     return "Invalid literal"; /* Anything -- will not be seen.  */
310
311   /* Don't successfully parse register names.  */
312   if (m32c_cgen_isa_register (strp))
313     return "Invalid literal"; /* Anything -- will not be seen.  */
314
315   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
316   if (errmsg)
317     return errmsg;
318
319   if (value > 0xffffff)
320     return _("dsp:24 immediate is out of range");
321
322   *valuep = value;
323   return 0;
324 }
325
326 static const char *
327 parse_signed32 (CGEN_CPU_DESC cd, const char **strp,
328                 int opindex, signed long *valuep)
329 {
330   const char *errmsg = 0;
331   signed long value;
332   
333   errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
334   if (errmsg)
335     return errmsg;
336
337   *valuep = value;
338   return 0;
339 }
340
341 static const char *
342 parse_imm1_S (CGEN_CPU_DESC cd, const char **strp,
343              int opindex, signed long *valuep)
344 {
345   const char *errmsg = 0;
346   signed long value;
347
348   errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
349   if (errmsg)
350     return errmsg;
351
352   if (value < 1 || value > 2)
353     return _("immediate is out of range 1-2");
354
355   *valuep = value;
356   return 0;
357 }
358
359 static const char *
360 parse_imm3_S (CGEN_CPU_DESC cd, const char **strp,
361              int opindex, signed long *valuep)
362 {
363   const char *errmsg = 0;
364   signed long value;
365   
366   errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
367   if (errmsg)
368     return errmsg;
369
370   if (value < 1 || value > 8)
371     return _("immediate is out of range 1-8");
372
373   *valuep = value;
374   return 0;
375 }
376
377 static const char *
378 parse_lab_5_3 (CGEN_CPU_DESC cd,
379                const char **strp,
380                int opindex ATTRIBUTE_UNUSED,
381                int opinfo,
382                enum cgen_parse_operand_result *type_addr,
383                unsigned long *valuep)
384 {
385   const char *errmsg = 0;
386   unsigned long value;
387   enum cgen_parse_operand_result op_res;
388
389   errmsg = cgen_parse_address (cd, strp, M32C_OPERAND_LAB_5_3,
390                                opinfo, & op_res, & value);
391
392   if (type_addr)
393     *type_addr = op_res;
394
395   if (op_res == CGEN_PARSE_OPERAND_ADDRESS)
396     {
397       /* This is a hack; the field cannot handle near-zero signed
398          offsets that CGEN wants to put in to indicate an "empty"
399          operand at first.  */
400       *valuep = 2;
401       return 0;
402     }
403   if (errmsg)
404     return errmsg;
405
406   if (value < 2 || value > 9)
407     return _("immediate is out of range 2-9");
408
409   *valuep = value;
410   return 0;
411 }
412
413 static const char *
414 parse_Bitno16R (CGEN_CPU_DESC cd, const char **strp,
415                 int opindex, unsigned long *valuep)
416 {
417   const char *errmsg = 0;
418   unsigned long value;
419
420   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
421   if (errmsg)
422     return errmsg;
423
424   if (value > 15)
425     return _("Bit number for indexing general register is out of range 0-15");
426
427   *valuep = value;
428   return 0;
429 }
430
431 static const char *
432 parse_unsigned_bitbase (CGEN_CPU_DESC cd, const char **strp,
433                         int opindex, unsigned long *valuep,
434                         unsigned bits)
435 {
436   const char *errmsg = 0;
437   unsigned long bit;
438   unsigned long base;
439   const char *newp = *strp;
440   unsigned long long bitbase;
441
442   errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & bit);
443   if (errmsg)
444     return errmsg;
445
446   if (*newp != ',')
447     return "Missing base for bit,base:8";
448
449   ++newp;
450   errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & base);
451   if (errmsg)
452     return errmsg;
453
454   bitbase = (unsigned long long) bit + ((unsigned long long) base * 8);
455
456   if (bitbase >= (1ull << bits))
457     return _("bit,base is out of range");
458
459   *valuep = bitbase;
460   *strp = newp;
461   return 0;
462 }
463
464 static const char *
465 parse_signed_bitbase (CGEN_CPU_DESC cd, const char **strp,
466                       int opindex, signed long *valuep,
467                       unsigned bits)
468 {
469   const char *errmsg = 0;
470   unsigned long bit;
471   signed long base;
472   const char *newp = *strp;
473   long long bitbase;
474   long long limit;
475
476   errmsg = cgen_parse_unsigned_integer (cd, & newp, opindex, & bit);
477   if (errmsg)
478     return errmsg;
479
480   if (*newp != ',')
481     return "Missing base for bit,base:8";
482
483   ++newp;
484   errmsg = cgen_parse_signed_integer (cd, & newp, opindex, & base);
485   if (errmsg)
486     return errmsg;
487
488   bitbase = (long long)bit + ((long long)base * 8);
489
490   limit = 1ll << (bits - 1);
491   if (bitbase < -limit || bitbase >= limit)
492     return _("bit,base is out of range");
493
494   *valuep = bitbase;
495   *strp = newp;
496   return 0;
497 }
498
499 static const char *
500 parse_unsigned_bitbase8 (CGEN_CPU_DESC cd, const char **strp,
501                          int opindex, unsigned long *valuep)
502 {
503   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 8);
504 }
505
506 static const char *
507 parse_unsigned_bitbase11 (CGEN_CPU_DESC cd, const char **strp,
508                          int opindex, unsigned long *valuep)
509 {
510   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 11);
511 }
512
513 static const char *
514 parse_unsigned_bitbase16 (CGEN_CPU_DESC cd, const char **strp,
515                           int opindex, unsigned long *valuep)
516 {
517   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 16);
518 }
519
520 static const char *
521 parse_unsigned_bitbase19 (CGEN_CPU_DESC cd, const char **strp,
522                          int opindex, unsigned long *valuep)
523 {
524   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 19);
525 }
526
527 static const char *
528 parse_unsigned_bitbase27 (CGEN_CPU_DESC cd, const char **strp,
529                          int opindex, unsigned long *valuep)
530 {
531   return parse_unsigned_bitbase (cd, strp, opindex, valuep, 27);
532 }
533
534 static const char *
535 parse_signed_bitbase8 (CGEN_CPU_DESC cd, const char **strp,
536                        int opindex, signed long *valuep)
537 {
538   return parse_signed_bitbase (cd, strp, opindex, valuep, 8);
539 }
540
541 static const char *
542 parse_signed_bitbase11 (CGEN_CPU_DESC cd, const char **strp,
543                        int opindex, signed long *valuep)
544 {
545   return parse_signed_bitbase (cd, strp, opindex, valuep, 11);
546 }
547
548 static const char *
549 parse_signed_bitbase19 (CGEN_CPU_DESC cd, const char **strp,
550                        int opindex, signed long *valuep)
551 {
552   return parse_signed_bitbase (cd, strp, opindex, valuep, 19);
553 }
554
555 /* Parse the suffix as :<char> or as nothing followed by a whitespace.  */
556
557 static const char *
558 parse_suffix (const char **strp, char suffix)
559 {
560   const char *newp = *strp;
561   
562   if (**strp == ':' && TOLOWER (*(*strp + 1)) == suffix)
563     newp = *strp + 2;
564
565   if (ISSPACE (*newp))
566     {
567       *strp = newp;
568       return 0;
569     }
570         
571   return "Invalid suffix"; /* Anything -- will not be seen.  */
572 }
573
574 static const char *
575 parse_S (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
576          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
577 {
578   return parse_suffix (strp, 's');
579 }
580
581 static const char *
582 parse_G (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
583          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
584 {
585   return parse_suffix (strp, 'g');
586 }
587
588 static const char *
589 parse_Q (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
590          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
591 {
592   return parse_suffix (strp, 'q');
593 }
594
595 static const char *
596 parse_Z (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
597          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
598 {
599   return parse_suffix (strp, 'z');
600 }
601
602 /* Parse an empty suffix. Fail if the next char is ':'.  */
603
604 static const char *
605 parse_X (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
606          int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
607 {
608   if (**strp == ':')
609     return "Unexpected suffix";
610   return 0;
611 }
612
613 static const char *
614 parse_r0l_r0h (CGEN_CPU_DESC cd, const char **strp,
615                int opindex ATTRIBUTE_UNUSED, signed long *valuep)
616 {
617   const char *errmsg;
618   signed long value;
619   signed long junk;
620   const char *newp = *strp;
621
622   /* Parse r0[hl].  */
623   errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0l_r0h, & value);
624   if (errmsg)
625     return errmsg;
626
627   if (*newp != ',')
628     return _("not a valid r0l/r0h pair");
629   ++newp;
630
631   /* Parse the second register in the pair.  */
632   if (value == 0) /* r0l */
633     errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0h, & junk);
634   else
635     errmsg = cgen_parse_keyword (cd, & newp, & m32c_cgen_opval_h_r0l, & junk);
636   if (errmsg)
637     return errmsg;
638
639   *strp = newp;
640   *valuep = ! value;
641   return 0;
642 }
643
644 /* Accept .b or .w in any case.  */
645
646 static const char *
647 parse_size (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, const char **strp,
648             int opindex ATTRIBUTE_UNUSED, signed long *valuep ATTRIBUTE_UNUSED)
649 {
650   if (**strp == '.'
651       && (*(*strp + 1) == 'b' || *(*strp + 1) == 'B'
652           || *(*strp + 1) == 'w' || *(*strp + 1) == 'W'))
653     {
654       *strp += 2;
655       return NULL;
656     }
657
658   return _("Invalid size specifier");
659 }
660
661 /* Special check to ensure that instruction exists for given machine.  */
662
663 int
664 m32c_cgen_insn_supported (CGEN_CPU_DESC cd,
665                           const CGEN_INSN *insn)
666 {
667   int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
668   int isas = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_ISA);
669
670   /* If attributes are absent, assume no restriction.  */
671   if (machs == 0)
672     machs = ~0;
673
674   return ((machs & cd->machs)
675           && (isas & cd->isas));
676 }
677
678 /* Parse a set of registers, R0,R1,A0,A1,SB,FB.  */
679
680 static const char *
681 parse_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
682               const char **strp,
683               int opindex ATTRIBUTE_UNUSED,
684               unsigned long *valuep,
685               int push)
686 {
687   const char *errmsg = 0;
688   int regno = 0;
689  
690   *valuep = 0;
691   while (**strp && **strp != ')')
692     {
693       if (**strp == 'r' || **strp == 'R')
694         {
695           ++*strp;
696           regno = **strp - '0';
697           if (regno > 4)
698             errmsg = _("Register number is not valid");
699         }
700       else if (**strp == 'a' || **strp == 'A')
701         {
702           ++*strp;
703           regno = **strp - '0';
704           if (regno > 2)
705             errmsg = _("Register number is not valid");
706           regno = **strp - '0' + 4;
707         }
708       
709       else if (strncasecmp (*strp, "sb", 2) == 0 || strncasecmp (*strp, "SB", 2) == 0)
710         {
711           regno = 6;
712           ++*strp;
713         }
714       
715       else if (strncasecmp (*strp, "fb", 2) == 0 || strncasecmp (*strp, "FB", 2) == 0)
716         {
717           regno = 7;
718           ++*strp;
719         }
720       
721       if (push) /* Mask is reversed for push.  */
722         *valuep |= 0x80 >> regno;
723       else
724         *valuep |= 1 << regno;
725
726       ++*strp;
727       if (**strp == ',')
728         {
729           if (*(*strp + 1) == ')')
730             break;
731           ++*strp;
732         }
733     }
734
735   if (!*strp)
736     errmsg = _("Register list is not valid");
737
738   return errmsg;
739 }
740
741 #define POP  0
742 #define PUSH 1
743
744 static const char *
745 parse_pop_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
746                   const char **strp,
747                   int opindex ATTRIBUTE_UNUSED,
748                   unsigned long *valuep)
749 {
750   return parse_regset (cd, strp, opindex, valuep, POP);
751 }
752
753 static const char *
754 parse_push_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
755                    const char **strp,
756                    int opindex ATTRIBUTE_UNUSED,
757                    unsigned long *valuep)
758 {
759   return parse_regset (cd, strp, opindex, valuep, PUSH);
760 }
761
762 /* -- dis.c */
763
764 #include "elf/m32c.h"
765 #include "elf-bfd.h"
766
767 /* Always print the short insn format suffix as ':<char>'.  */
768
769 static void
770 print_suffix (void * dis_info, char suffix)
771 {
772   disassemble_info *info = dis_info;
773
774   (*info->fprintf_func) (info->stream, ":%c", suffix);
775 }
776
777 static void
778 print_S (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
779          void * dis_info,
780          long value ATTRIBUTE_UNUSED,
781          unsigned int attrs ATTRIBUTE_UNUSED,
782          bfd_vma pc ATTRIBUTE_UNUSED,
783          int length ATTRIBUTE_UNUSED)
784 {
785   print_suffix (dis_info, 's');
786 }
787
788
789 static void
790 print_G (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
791          void * dis_info,
792          long value ATTRIBUTE_UNUSED,
793          unsigned int attrs ATTRIBUTE_UNUSED,
794          bfd_vma pc ATTRIBUTE_UNUSED,
795          int length ATTRIBUTE_UNUSED)
796 {
797   print_suffix (dis_info, 'g');
798 }
799
800 static void
801 print_Q (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
802          void * dis_info,
803          long value ATTRIBUTE_UNUSED,
804          unsigned int attrs ATTRIBUTE_UNUSED,
805          bfd_vma pc ATTRIBUTE_UNUSED,
806          int length ATTRIBUTE_UNUSED)
807 {
808   print_suffix (dis_info, 'q');
809 }
810
811 static void
812 print_Z (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
813          void * dis_info,
814          long value ATTRIBUTE_UNUSED,
815          unsigned int attrs ATTRIBUTE_UNUSED,
816          bfd_vma pc ATTRIBUTE_UNUSED,
817          int length ATTRIBUTE_UNUSED)
818 {
819   print_suffix (dis_info, 'z');
820 }
821
822 /* Print the empty suffix.  */
823
824 static void
825 print_X (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
826          void * dis_info ATTRIBUTE_UNUSED,
827          long value ATTRIBUTE_UNUSED,
828          unsigned int attrs ATTRIBUTE_UNUSED,
829          bfd_vma pc ATTRIBUTE_UNUSED,
830          int length ATTRIBUTE_UNUSED)
831 {
832   return;
833 }
834
835 static void
836 print_r0l_r0h (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
837                void * dis_info,
838                long value,
839                unsigned int attrs ATTRIBUTE_UNUSED,
840                bfd_vma pc ATTRIBUTE_UNUSED,
841                int length ATTRIBUTE_UNUSED)
842 {
843   disassemble_info *info = dis_info;
844
845   if (value == 0)
846     (*info->fprintf_func) (info->stream, "r0h,r0l");
847   else
848     (*info->fprintf_func) (info->stream, "r0l,r0h");
849 }
850
851 static void
852 print_unsigned_bitbase (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
853                         void * dis_info,
854                         unsigned long value,
855                         unsigned int attrs ATTRIBUTE_UNUSED,
856                         bfd_vma pc ATTRIBUTE_UNUSED,
857                         int length ATTRIBUTE_UNUSED)
858 {
859   disassemble_info *info = dis_info;
860
861   (*info->fprintf_func) (info->stream, "%ld,0x%lx", value & 0x7, value >> 3);
862 }
863
864 static void
865 print_signed_bitbase (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
866                       void * dis_info,
867                       signed long value,
868                       unsigned int attrs ATTRIBUTE_UNUSED,
869                       bfd_vma pc ATTRIBUTE_UNUSED,
870                       int length ATTRIBUTE_UNUSED)
871 {
872   disassemble_info *info = dis_info;
873
874   (*info->fprintf_func) (info->stream, "%ld,%ld", value & 0x7, value >> 3);
875 }
876
877 static void
878 print_size (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
879             void * dis_info,
880             long value ATTRIBUTE_UNUSED,
881             unsigned int attrs ATTRIBUTE_UNUSED,
882             bfd_vma pc ATTRIBUTE_UNUSED,
883             int length ATTRIBUTE_UNUSED)
884 {
885   /* Always print the size as '.w'.  */
886   disassemble_info *info = dis_info;
887
888   (*info->fprintf_func) (info->stream, ".w");
889 }
890
891 #define POP  0
892 #define PUSH 1
893
894 static void print_pop_regset  (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
895 static void print_push_regset (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
896
897 /* Print a set of registers, R0,R1,A0,A1,SB,FB.  */
898
899 static void
900 print_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
901               void * dis_info,
902               long value,
903               unsigned int attrs ATTRIBUTE_UNUSED,
904               bfd_vma pc ATTRIBUTE_UNUSED,
905               int length ATTRIBUTE_UNUSED,
906               int push)
907 {
908   static char * m16c_register_names [] = 
909   {
910     "r0", "r1", "r2", "r3", "a0", "a1", "sb", "fb"
911   };
912   disassemble_info *info = dis_info;
913   int mask;
914   int index = 0;
915   char* comma = "";
916
917   if (push)
918     mask = 0x80;
919   else
920     mask = 1;
921  
922   if (value & mask)
923     {
924       (*info->fprintf_func) (info->stream, "%s", m16c_register_names [0]);
925       comma = ",";
926     }
927
928   for (index = 1; index <= 7; ++index)
929     {
930       if (push)
931         mask >>= 1;
932       else
933         mask <<= 1;
934
935       if (value & mask)
936         {
937           (*info->fprintf_func) (info->stream, "%s%s", comma,
938                                  m16c_register_names [index]);
939           comma = ",";
940         }
941     }
942 }
943
944 static void
945 print_pop_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
946                   void * dis_info,
947                   long value,
948                   unsigned int attrs ATTRIBUTE_UNUSED,
949                   bfd_vma pc ATTRIBUTE_UNUSED,
950                   int length ATTRIBUTE_UNUSED)
951 {
952   print_regset (cd, dis_info, value, attrs, pc, length, POP);
953 }
954
955 static void
956 print_push_regset (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
957                    void * dis_info,
958                    long value,
959                    unsigned int attrs ATTRIBUTE_UNUSED,
960                    bfd_vma pc ATTRIBUTE_UNUSED,
961                    int length ATTRIBUTE_UNUSED)
962 {
963   print_regset (cd, dis_info, value, attrs, pc, length, PUSH);
964 }