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