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