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