xref: /netbsd-src/external/gpl3/binutils/dist/cpu/m32c.opc (revision b1c86f5f087524e68db12794ee9c3e3da1ab17a0)
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
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
53extern 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
60/* -- opc.c */
61static unsigned int
62m32c_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
83/* -- asm.c */
84#include "safe-ctype.h"
85
86#define MACH_M32C 5		/* Must match md_begin.  */
87
88static int
89m32c_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
138static const char *
139parse_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
154static const char *
155parse_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
201static const char *
202parse_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
226static const char *
227parse_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
251static const char *
252parse_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
292static const char *
293parse_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
352static const char *
353parse_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
415static const char *
416parse_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
441static const char *
442parse_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.  */
468static const char *
469parse_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
487static const char *
488parse_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
502static const char *
503parse_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
520static const char *
521parse_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
538static const char *
539parse_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
556static const char *
557parse_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_ADDRESS)
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
592static const char *
593parse_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
610static const char *
611parse_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
664static const char *
665parse_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
709static const char *
710parse_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
716static const char *
717parse_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
723static const char *
724parse_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
730static const char *
731parse_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
737static const char *
738parse_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
744static const char *
745parse_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
751static const char *
752parse_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
758static const char *
759parse_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
767static const char *
768parse_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
784static const char *
785parse_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
791static const char *
792parse_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
798static const char *
799parse_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
805static const char *
806parse_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
814static const char *
815parse_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
823static const char *
824parse_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
856static const char *
857parse_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
873int
874m32c_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
890static const char *
891parse_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
954static const char *
955parse_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
963static const char *
964parse_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
979static void
980print_suffix (void * dis_info, char suffix)
981{
982  disassemble_info *info = dis_info;
983
984  (*info->fprintf_func) (info->stream, ":%c", suffix);
985}
986
987static void
988print_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
999static void
1000print_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
1010static void
1011print_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
1021static void
1022print_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
1034static void
1035print_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
1045static void
1046print_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
1061static void
1062print_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
1074static void
1075print_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
1087static void
1088print_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
1104static void print_pop_regset  (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
1105static 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
1109static void
1110print_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
1154static void
1155print_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
1165static void
1166print_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
1176static void
1177print_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}
1188