xref: /openbsd-src/gnu/usr.bin/binutils/opcodes/m32r-asm.c (revision cf2f2c5620d6d9a4fd01930983c4b9a1f76d7aa3)
1fddef416Sniklas /* Assembler interface for targets using CGEN. -*- C -*-
2fddef416Sniklas    CGEN: Cpu tools GENerator
3fddef416Sniklas 
4f7cc78ecSespie THIS FILE IS MACHINE GENERATED WITH CGEN.
5f7cc78ecSespie - the resultant file is machine generated, cgen-asm.in isn't
6fddef416Sniklas 
7*cf2f2c56Smiod Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2004 Free Software Foundation, Inc.
8fddef416Sniklas 
9fddef416Sniklas This file is part of the GNU Binutils and GDB, the GNU debugger.
10fddef416Sniklas 
11fddef416Sniklas This program is free software; you can redistribute it and/or modify
12fddef416Sniklas it under the terms of the GNU General Public License as published by
13fddef416Sniklas the Free Software Foundation; either version 2, or (at your option)
14fddef416Sniklas any later version.
15fddef416Sniklas 
16fddef416Sniklas This program is distributed in the hope that it will be useful,
17fddef416Sniklas but WITHOUT ANY WARRANTY; without even the implied warranty of
18fddef416Sniklas MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19fddef416Sniklas GNU General Public License for more details.
20fddef416Sniklas 
21fddef416Sniklas You should have received a copy of the GNU General Public License
22f7cc78ecSespie along with this program; if not, write to the Free Software Foundation, Inc.,
23f7cc78ecSespie 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
24f7cc78ecSespie 
25f7cc78ecSespie /* ??? Eventually more and more of this stuff can go to cpu-independent files.
26f7cc78ecSespie    Keep that in mind.  */
27fddef416Sniklas 
28fddef416Sniklas #include "sysdep.h"
29fddef416Sniklas #include <stdio.h>
30fddef416Sniklas #include "ansidecl.h"
31fddef416Sniklas #include "bfd.h"
32f7cc78ecSespie #include "symcat.h"
33f7cc78ecSespie #include "m32r-desc.h"
34fddef416Sniklas #include "m32r-opc.h"
35f7cc78ecSespie #include "opintl.h"
36d2201f2fSdrahn #include "xregex.h"
37d2201f2fSdrahn #include "libiberty.h"
38d2201f2fSdrahn #include "safe-ctype.h"
39fddef416Sniklas 
40f7cc78ecSespie #undef  min
41f7cc78ecSespie #define min(a,b) ((a) < (b) ? (a) : (b))
42f7cc78ecSespie #undef  max
43f7cc78ecSespie #define max(a,b) ((a) > (b) ? (a) : (b))
44fddef416Sniklas 
45fddef416Sniklas static const char * parse_insn_normal
46*cf2f2c56Smiod   (CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *);
47fddef416Sniklas 
48d2201f2fSdrahn /* -- assembler routines inserted here.  */
49f7cc78ecSespie 
50fddef416Sniklas /* -- asm.c */
51d2201f2fSdrahn static const char * parse_hash
52d2201f2fSdrahn   PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
53d2201f2fSdrahn static const char * parse_hi16
54d2201f2fSdrahn   PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
55d2201f2fSdrahn static const char * parse_slo16
56d2201f2fSdrahn   PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
57d2201f2fSdrahn static const char * parse_ulo16
58d2201f2fSdrahn   PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
59fddef416Sniklas 
60f7cc78ecSespie /* Handle '#' prefixes (i.e. skip over them).  */
61f7cc78ecSespie 
62f7cc78ecSespie static const char *
parse_hash(cd,strp,opindex,valuep)63f7cc78ecSespie parse_hash (cd, strp, opindex, valuep)
64d2201f2fSdrahn      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
65f7cc78ecSespie      const char **strp;
66d2201f2fSdrahn      int opindex ATTRIBUTE_UNUSED;
67d2201f2fSdrahn      unsigned long *valuep ATTRIBUTE_UNUSED;
68f7cc78ecSespie {
69f7cc78ecSespie   if (**strp == '#')
70f7cc78ecSespie     ++*strp;
71f7cc78ecSespie   return NULL;
72f7cc78ecSespie }
73f7cc78ecSespie 
74fddef416Sniklas /* Handle shigh(), high().  */
75fddef416Sniklas 
76fddef416Sniklas static const char *
parse_hi16(cd,strp,opindex,valuep)77f7cc78ecSespie parse_hi16 (cd, strp, opindex, valuep)
78f7cc78ecSespie      CGEN_CPU_DESC cd;
79fddef416Sniklas      const char **strp;
80fddef416Sniklas      int opindex;
81fddef416Sniklas      unsigned long *valuep;
82fddef416Sniklas {
83fddef416Sniklas   const char *errmsg;
84f7cc78ecSespie   enum cgen_parse_operand_result result_type;
85f7cc78ecSespie   bfd_vma value;
86fddef416Sniklas 
87fddef416Sniklas   if (**strp == '#')
88fddef416Sniklas     ++*strp;
89fddef416Sniklas 
90f7cc78ecSespie   if (strncasecmp (*strp, "high(", 5) == 0)
91fddef416Sniklas     {
92fddef416Sniklas       *strp += 5;
93f7cc78ecSespie       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_HI16_ULO,
94f7cc78ecSespie 				   &result_type, &value);
95fddef416Sniklas       if (**strp != ')')
96fddef416Sniklas 	return "missing `)'";
97fddef416Sniklas       ++*strp;
98f7cc78ecSespie       if (errmsg == NULL
99f7cc78ecSespie   	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
100f7cc78ecSespie 	value >>= 16;
101f7cc78ecSespie       *valuep = value;
102fddef416Sniklas       return errmsg;
103fddef416Sniklas     }
104f7cc78ecSespie   else if (strncasecmp (*strp, "shigh(", 6) == 0)
105fddef416Sniklas     {
106fddef416Sniklas       *strp += 6;
107f7cc78ecSespie       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_HI16_SLO,
108f7cc78ecSespie  				   &result_type, &value);
109fddef416Sniklas       if (**strp != ')')
110fddef416Sniklas 	return "missing `)'";
111fddef416Sniklas       ++*strp;
112f7cc78ecSespie       if (errmsg == NULL
113f7cc78ecSespie 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
114*cf2f2c56Smiod         {
115*cf2f2c56Smiod           value = value + (value & 0x8000 ? 0x10000 : 0);
116*cf2f2c56Smiod           value >>= 16;
117*cf2f2c56Smiod         }
118f7cc78ecSespie       *valuep = value;
119fddef416Sniklas       return errmsg;
120fddef416Sniklas     }
121fddef416Sniklas 
122f7cc78ecSespie   return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
123fddef416Sniklas }
124fddef416Sniklas 
125fddef416Sniklas /* Handle low() in a signed context.  Also handle sda().
126fddef416Sniklas    The signedness of the value doesn't matter to low(), but this also
127fddef416Sniklas    handles the case where low() isn't present.  */
128fddef416Sniklas 
129fddef416Sniklas static const char *
parse_slo16(cd,strp,opindex,valuep)130f7cc78ecSespie parse_slo16 (cd, strp, opindex, valuep)
131f7cc78ecSespie      CGEN_CPU_DESC cd;
132fddef416Sniklas      const char **strp;
133fddef416Sniklas      int opindex;
134fddef416Sniklas      long *valuep;
135fddef416Sniklas {
136fddef416Sniklas   const char *errmsg;
137f7cc78ecSespie   enum cgen_parse_operand_result result_type;
138f7cc78ecSespie   bfd_vma value;
139fddef416Sniklas 
140fddef416Sniklas   if (**strp == '#')
141fddef416Sniklas     ++*strp;
142fddef416Sniklas 
143f7cc78ecSespie   if (strncasecmp (*strp, "low(", 4) == 0)
144fddef416Sniklas     {
145fddef416Sniklas       *strp += 4;
146f7cc78ecSespie       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_LO16,
147f7cc78ecSespie 				   &result_type, &value);
148fddef416Sniklas       if (**strp != ')')
149fddef416Sniklas 	return "missing `)'";
150fddef416Sniklas       ++*strp;
151f7cc78ecSespie       if (errmsg == NULL
152f7cc78ecSespie 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
153*cf2f2c56Smiod         {
154f7cc78ecSespie 	  value &= 0xffff;
155*cf2f2c56Smiod           if (value & 0x8000)
156*cf2f2c56Smiod              value |= 0xffff0000;
157*cf2f2c56Smiod         }
158f7cc78ecSespie       *valuep = value;
159fddef416Sniklas       return errmsg;
160fddef416Sniklas     }
161fddef416Sniklas 
162f7cc78ecSespie   if (strncasecmp (*strp, "sda(", 4) == 0)
163fddef416Sniklas     {
164fddef416Sniklas       *strp += 4;
165f7cc78ecSespie       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_SDA16,
166f7cc78ecSespie 				   NULL, &value);
167fddef416Sniklas       if (**strp != ')')
168fddef416Sniklas 	return "missing `)'";
169fddef416Sniklas       ++*strp;
170f7cc78ecSespie       *valuep = value;
171fddef416Sniklas       return errmsg;
172fddef416Sniklas     }
173fddef416Sniklas 
174f7cc78ecSespie   return cgen_parse_signed_integer (cd, strp, opindex, valuep);
175fddef416Sniklas }
176fddef416Sniklas 
177fddef416Sniklas /* Handle low() in an unsigned context.
178fddef416Sniklas    The signedness of the value doesn't matter to low(), but this also
179fddef416Sniklas    handles the case where low() isn't present.  */
180fddef416Sniklas 
181fddef416Sniklas static const char *
parse_ulo16(cd,strp,opindex,valuep)182f7cc78ecSespie parse_ulo16 (cd, strp, opindex, valuep)
183f7cc78ecSespie      CGEN_CPU_DESC cd;
184fddef416Sniklas      const char **strp;
185fddef416Sniklas      int opindex;
186fddef416Sniklas      unsigned long *valuep;
187fddef416Sniklas {
188fddef416Sniklas   const char *errmsg;
189f7cc78ecSespie   enum cgen_parse_operand_result result_type;
190f7cc78ecSespie   bfd_vma value;
191fddef416Sniklas 
192fddef416Sniklas   if (**strp == '#')
193fddef416Sniklas     ++*strp;
194fddef416Sniklas 
195f7cc78ecSespie   if (strncasecmp (*strp, "low(", 4) == 0)
196fddef416Sniklas     {
197fddef416Sniklas       *strp += 4;
198f7cc78ecSespie       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_LO16,
199f7cc78ecSespie 				   &result_type, &value);
200fddef416Sniklas       if (**strp != ')')
201fddef416Sniklas 	return "missing `)'";
202fddef416Sniklas       ++*strp;
203f7cc78ecSespie       if (errmsg == NULL
204f7cc78ecSespie 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
205f7cc78ecSespie 	value &= 0xffff;
206f7cc78ecSespie       *valuep = value;
207fddef416Sniklas       return errmsg;
208fddef416Sniklas     }
209fddef416Sniklas 
210f7cc78ecSespie   return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
211fddef416Sniklas }
212fddef416Sniklas 
213fddef416Sniklas /* -- */
214fddef416Sniklas 
215d2201f2fSdrahn const char * m32r_cgen_parse_operand
216d2201f2fSdrahn   PARAMS ((CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *));
217d2201f2fSdrahn 
218fddef416Sniklas /* Main entry point for operand parsing.
219fddef416Sniklas 
220fddef416Sniklas    This function is basically just a big switch statement.  Earlier versions
221fddef416Sniklas    used tables to look up the function to use, but
222fddef416Sniklas    - if the table contains both assembler and disassembler functions then
223fddef416Sniklas      the disassembler contains much of the assembler and vice-versa,
224fddef416Sniklas    - there's a lot of inlining possibilities as things grow,
225fddef416Sniklas    - using a switch statement avoids the function call overhead.
226fddef416Sniklas 
227fddef416Sniklas    This function could be moved into `parse_insn_normal', but keeping it
228fddef416Sniklas    separate makes clear the interface between `parse_insn_normal' and each of
229d2201f2fSdrahn    the handlers.  */
230fddef416Sniklas 
231f7cc78ecSespie const char *
m32r_cgen_parse_operand(cd,opindex,strp,fields)232f7cc78ecSespie m32r_cgen_parse_operand (cd, opindex, strp, fields)
233f7cc78ecSespie      CGEN_CPU_DESC cd;
234fddef416Sniklas      int opindex;
235fddef416Sniklas      const char ** strp;
236f7cc78ecSespie      CGEN_FIELDS * fields;
237fddef416Sniklas {
238fddef416Sniklas   const char * errmsg = NULL;
239f7cc78ecSespie   /* Used by scalar operands that still need to be parsed.  */
240d2201f2fSdrahn   long junk ATTRIBUTE_UNUSED;
241fddef416Sniklas 
242fddef416Sniklas   switch (opindex)
243fddef416Sniklas     {
244f7cc78ecSespie     case M32R_OPERAND_ACC :
245f7cc78ecSespie       errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_h_accums, & fields->f_acc);
246fddef416Sniklas       break;
247f7cc78ecSespie     case M32R_OPERAND_ACCD :
248f7cc78ecSespie       errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_h_accums, & fields->f_accd);
249fddef416Sniklas       break;
250f7cc78ecSespie     case M32R_OPERAND_ACCS :
251f7cc78ecSespie       errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_h_accums, & fields->f_accs);
252fddef416Sniklas       break;
253f7cc78ecSespie     case M32R_OPERAND_DCR :
254f7cc78ecSespie       errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_cr_names, & fields->f_r1);
255fddef416Sniklas       break;
256f7cc78ecSespie     case M32R_OPERAND_DISP16 :
257f7cc78ecSespie       {
258f7cc78ecSespie         bfd_vma value;
259f7cc78ecSespie         errmsg = cgen_parse_address (cd, strp, M32R_OPERAND_DISP16, 0, NULL,  & value);
260f7cc78ecSespie         fields->f_disp16 = value;
261f7cc78ecSespie       }
262fddef416Sniklas       break;
263f7cc78ecSespie     case M32R_OPERAND_DISP24 :
264f7cc78ecSespie       {
265f7cc78ecSespie         bfd_vma value;
266f7cc78ecSespie         errmsg = cgen_parse_address (cd, strp, M32R_OPERAND_DISP24, 0, NULL,  & value);
267f7cc78ecSespie         fields->f_disp24 = value;
268f7cc78ecSespie       }
269fddef416Sniklas       break;
270f7cc78ecSespie     case M32R_OPERAND_DISP8 :
271f7cc78ecSespie       {
272f7cc78ecSespie         bfd_vma value;
273f7cc78ecSespie         errmsg = cgen_parse_address (cd, strp, M32R_OPERAND_DISP8, 0, NULL,  & value);
274f7cc78ecSespie         fields->f_disp8 = value;
275f7cc78ecSespie       }
276fddef416Sniklas       break;
277f7cc78ecSespie     case M32R_OPERAND_DR :
278f7cc78ecSespie       errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_gr_names, & fields->f_r1);
279fddef416Sniklas       break;
280f7cc78ecSespie     case M32R_OPERAND_HASH :
281f7cc78ecSespie       errmsg = parse_hash (cd, strp, M32R_OPERAND_HASH, &junk);
282fddef416Sniklas       break;
283f7cc78ecSespie     case M32R_OPERAND_HI16 :
284f7cc78ecSespie       errmsg = parse_hi16 (cd, strp, M32R_OPERAND_HI16, &fields->f_hi16);
285fddef416Sniklas       break;
286f7cc78ecSespie     case M32R_OPERAND_IMM1 :
287f7cc78ecSespie       errmsg = cgen_parse_unsigned_integer (cd, strp, M32R_OPERAND_IMM1, &fields->f_imm1);
288fddef416Sniklas       break;
289f7cc78ecSespie     case M32R_OPERAND_SCR :
290f7cc78ecSespie       errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_cr_names, & fields->f_r2);
291fddef416Sniklas       break;
292f7cc78ecSespie     case M32R_OPERAND_SIMM16 :
293f7cc78ecSespie       errmsg = cgen_parse_signed_integer (cd, strp, M32R_OPERAND_SIMM16, &fields->f_simm16);
294fddef416Sniklas       break;
295f7cc78ecSespie     case M32R_OPERAND_SIMM8 :
296f7cc78ecSespie       errmsg = cgen_parse_signed_integer (cd, strp, M32R_OPERAND_SIMM8, &fields->f_simm8);
297fddef416Sniklas       break;
298f7cc78ecSespie     case M32R_OPERAND_SLO16 :
299f7cc78ecSespie       errmsg = parse_slo16 (cd, strp, M32R_OPERAND_SLO16, &fields->f_simm16);
300fddef416Sniklas       break;
301f7cc78ecSespie     case M32R_OPERAND_SR :
302f7cc78ecSespie       errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_gr_names, & fields->f_r2);
303fddef416Sniklas       break;
304f7cc78ecSespie     case M32R_OPERAND_SRC1 :
305f7cc78ecSespie       errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_gr_names, & fields->f_r1);
306fddef416Sniklas       break;
307f7cc78ecSespie     case M32R_OPERAND_SRC2 :
308f7cc78ecSespie       errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_gr_names, & fields->f_r2);
309f7cc78ecSespie       break;
310f7cc78ecSespie     case M32R_OPERAND_UIMM16 :
311f7cc78ecSespie       errmsg = cgen_parse_unsigned_integer (cd, strp, M32R_OPERAND_UIMM16, &fields->f_uimm16);
312f7cc78ecSespie       break;
313f7cc78ecSespie     case M32R_OPERAND_UIMM24 :
314f7cc78ecSespie       {
315f7cc78ecSespie         bfd_vma value;
316f7cc78ecSespie         errmsg = cgen_parse_address (cd, strp, M32R_OPERAND_UIMM24, 0, NULL,  & value);
317f7cc78ecSespie         fields->f_uimm24 = value;
318f7cc78ecSespie       }
319f7cc78ecSespie       break;
320*cf2f2c56Smiod     case M32R_OPERAND_UIMM3 :
321*cf2f2c56Smiod       errmsg = cgen_parse_unsigned_integer (cd, strp, M32R_OPERAND_UIMM3, &fields->f_uimm3);
322*cf2f2c56Smiod       break;
323f7cc78ecSespie     case M32R_OPERAND_UIMM4 :
324f7cc78ecSespie       errmsg = cgen_parse_unsigned_integer (cd, strp, M32R_OPERAND_UIMM4, &fields->f_uimm4);
325f7cc78ecSespie       break;
326f7cc78ecSespie     case M32R_OPERAND_UIMM5 :
327f7cc78ecSespie       errmsg = cgen_parse_unsigned_integer (cd, strp, M32R_OPERAND_UIMM5, &fields->f_uimm5);
328f7cc78ecSespie       break;
329*cf2f2c56Smiod     case M32R_OPERAND_UIMM8 :
330*cf2f2c56Smiod       errmsg = cgen_parse_unsigned_integer (cd, strp, M32R_OPERAND_UIMM8, &fields->f_uimm8);
331*cf2f2c56Smiod       break;
332f7cc78ecSespie     case M32R_OPERAND_ULO16 :
333f7cc78ecSespie       errmsg = parse_ulo16 (cd, strp, M32R_OPERAND_ULO16, &fields->f_uimm16);
334fddef416Sniklas       break;
335fddef416Sniklas 
336fddef416Sniklas     default :
337f7cc78ecSespie       /* xgettext:c-format */
338f7cc78ecSespie       fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
339fddef416Sniklas       abort ();
340fddef416Sniklas   }
341fddef416Sniklas 
342fddef416Sniklas   return errmsg;
343fddef416Sniklas }
344fddef416Sniklas 
345f7cc78ecSespie cgen_parse_fn * const m32r_cgen_parse_handlers[] =
346f7cc78ecSespie {
347fddef416Sniklas   parse_insn_normal,
348fddef416Sniklas };
349fddef416Sniklas 
350fddef416Sniklas void
m32r_cgen_init_asm(cd)351f7cc78ecSespie m32r_cgen_init_asm (cd)
352f7cc78ecSespie      CGEN_CPU_DESC cd;
353fddef416Sniklas {
354f7cc78ecSespie   m32r_cgen_init_opcode_table (cd);
355f7cc78ecSespie   m32r_cgen_init_ibld_table (cd);
356f7cc78ecSespie   cd->parse_handlers = & m32r_cgen_parse_handlers[0];
357f7cc78ecSespie   cd->parse_operand = m32r_cgen_parse_operand;
358fddef416Sniklas }
359fddef416Sniklas 
360fddef416Sniklas 
361d2201f2fSdrahn 
362d2201f2fSdrahn /* Regex construction routine.
363d2201f2fSdrahn 
364d2201f2fSdrahn    This translates an opcode syntax string into a regex string,
365d2201f2fSdrahn    by replacing any non-character syntax element (such as an
366d2201f2fSdrahn    opcode) with the pattern '.*'
367d2201f2fSdrahn 
368d2201f2fSdrahn    It then compiles the regex and stores it in the opcode, for
369d2201f2fSdrahn    later use by m32r_cgen_assemble_insn
370d2201f2fSdrahn 
371d2201f2fSdrahn    Returns NULL for success, an error message for failure.  */
372d2201f2fSdrahn 
373d2201f2fSdrahn char *
m32r_cgen_build_insn_regex(CGEN_INSN * insn)374*cf2f2c56Smiod m32r_cgen_build_insn_regex (CGEN_INSN *insn)
375d2201f2fSdrahn {
376d2201f2fSdrahn   CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
377d2201f2fSdrahn   const char *mnem = CGEN_INSN_MNEMONIC (insn);
378d2201f2fSdrahn   char rxbuf[CGEN_MAX_RX_ELEMENTS];
379d2201f2fSdrahn   char *rx = rxbuf;
380d2201f2fSdrahn   const CGEN_SYNTAX_CHAR_TYPE *syn;
381d2201f2fSdrahn   int reg_err;
382d2201f2fSdrahn 
383d2201f2fSdrahn   syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
384d2201f2fSdrahn 
385d2201f2fSdrahn   /* Mnemonics come first in the syntax string.  */
386d2201f2fSdrahn   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
387d2201f2fSdrahn     return _("missing mnemonic in syntax string");
388d2201f2fSdrahn   ++syn;
389d2201f2fSdrahn 
390d2201f2fSdrahn   /* Generate a case sensitive regular expression that emulates case
391d2201f2fSdrahn      insensitive matching in the "C" locale.  We cannot generate a case
392d2201f2fSdrahn      insensitive regular expression because in Turkish locales, 'i' and 'I'
393d2201f2fSdrahn      are not equal modulo case conversion.  */
394d2201f2fSdrahn 
395d2201f2fSdrahn   /* Copy the literal mnemonic out of the insn.  */
396d2201f2fSdrahn   for (; *mnem; mnem++)
397d2201f2fSdrahn     {
398d2201f2fSdrahn       char c = *mnem;
399d2201f2fSdrahn 
400d2201f2fSdrahn       if (ISALPHA (c))
401d2201f2fSdrahn 	{
402d2201f2fSdrahn 	  *rx++ = '[';
403d2201f2fSdrahn 	  *rx++ = TOLOWER (c);
404d2201f2fSdrahn 	  *rx++ = TOUPPER (c);
405d2201f2fSdrahn 	  *rx++ = ']';
406d2201f2fSdrahn 	}
407d2201f2fSdrahn       else
408d2201f2fSdrahn 	*rx++ = c;
409d2201f2fSdrahn     }
410d2201f2fSdrahn 
411d2201f2fSdrahn   /* Copy any remaining literals from the syntax string into the rx.  */
412d2201f2fSdrahn   for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
413d2201f2fSdrahn     {
414d2201f2fSdrahn       if (CGEN_SYNTAX_CHAR_P (* syn))
415d2201f2fSdrahn 	{
416d2201f2fSdrahn 	  char c = CGEN_SYNTAX_CHAR (* syn);
417d2201f2fSdrahn 
418d2201f2fSdrahn 	  switch (c)
419d2201f2fSdrahn 	    {
420d2201f2fSdrahn 	      /* Escape any regex metacharacters in the syntax.  */
421d2201f2fSdrahn 	    case '.': case '[': case '\\':
422d2201f2fSdrahn 	    case '*': case '^': case '$':
423d2201f2fSdrahn 
424d2201f2fSdrahn #ifdef CGEN_ESCAPE_EXTENDED_REGEX
425d2201f2fSdrahn 	    case '?': case '{': case '}':
426d2201f2fSdrahn 	    case '(': case ')': case '*':
427d2201f2fSdrahn 	    case '|': case '+': case ']':
428d2201f2fSdrahn #endif
429d2201f2fSdrahn 	      *rx++ = '\\';
430d2201f2fSdrahn 	      *rx++ = c;
431d2201f2fSdrahn 	      break;
432d2201f2fSdrahn 
433d2201f2fSdrahn 	    default:
434d2201f2fSdrahn 	      if (ISALPHA (c))
435d2201f2fSdrahn 		{
436d2201f2fSdrahn 		  *rx++ = '[';
437d2201f2fSdrahn 		  *rx++ = TOLOWER (c);
438d2201f2fSdrahn 		  *rx++ = TOUPPER (c);
439d2201f2fSdrahn 		  *rx++ = ']';
440d2201f2fSdrahn 		}
441d2201f2fSdrahn 	      else
442d2201f2fSdrahn 		*rx++ = c;
443d2201f2fSdrahn 	      break;
444d2201f2fSdrahn 	    }
445d2201f2fSdrahn 	}
446d2201f2fSdrahn       else
447d2201f2fSdrahn 	{
448d2201f2fSdrahn 	  /* Replace non-syntax fields with globs.  */
449d2201f2fSdrahn 	  *rx++ = '.';
450d2201f2fSdrahn 	  *rx++ = '*';
451d2201f2fSdrahn 	}
452d2201f2fSdrahn     }
453d2201f2fSdrahn 
454d2201f2fSdrahn   /* Trailing whitespace ok.  */
455d2201f2fSdrahn   * rx++ = '[';
456d2201f2fSdrahn   * rx++ = ' ';
457d2201f2fSdrahn   * rx++ = '\t';
458d2201f2fSdrahn   * rx++ = ']';
459d2201f2fSdrahn   * rx++ = '*';
460d2201f2fSdrahn 
461d2201f2fSdrahn   /* But anchor it after that.  */
462d2201f2fSdrahn   * rx++ = '$';
463d2201f2fSdrahn   * rx = '\0';
464d2201f2fSdrahn 
465d2201f2fSdrahn   CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
466d2201f2fSdrahn   reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
467d2201f2fSdrahn 
468d2201f2fSdrahn   if (reg_err == 0)
469d2201f2fSdrahn     return NULL;
470d2201f2fSdrahn   else
471d2201f2fSdrahn     {
472d2201f2fSdrahn       static char msg[80];
473d2201f2fSdrahn 
474d2201f2fSdrahn       regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
475d2201f2fSdrahn       regfree ((regex_t *) CGEN_INSN_RX (insn));
476d2201f2fSdrahn       free (CGEN_INSN_RX (insn));
477d2201f2fSdrahn       (CGEN_INSN_RX (insn)) = NULL;
478d2201f2fSdrahn       return msg;
479d2201f2fSdrahn     }
480d2201f2fSdrahn }
481d2201f2fSdrahn 
482d2201f2fSdrahn 
483fddef416Sniklas /* Default insn parser.
484fddef416Sniklas 
485fddef416Sniklas    The syntax string is scanned and operands are parsed and stored in FIELDS.
486fddef416Sniklas    Relocs are queued as we go via other callbacks.
487fddef416Sniklas 
488fddef416Sniklas    ??? Note that this is currently an all-or-nothing parser.  If we fail to
489fddef416Sniklas    parse the instruction, we return 0 and the caller will start over from
490fddef416Sniklas    the beginning.  Backtracking will be necessary in parsing subexpressions,
491fddef416Sniklas    but that can be handled there.  Not handling backtracking here may get
492fddef416Sniklas    expensive in the case of the m68k.  Deal with later.
493fddef416Sniklas 
494d2201f2fSdrahn    Returns NULL for success, an error message for failure.  */
495fddef416Sniklas 
496fddef416Sniklas static const char *
parse_insn_normal(CGEN_CPU_DESC cd,const CGEN_INSN * insn,const char ** strp,CGEN_FIELDS * fields)497*cf2f2c56Smiod parse_insn_normal (CGEN_CPU_DESC cd,
498*cf2f2c56Smiod 		   const CGEN_INSN *insn,
499*cf2f2c56Smiod 		   const char **strp,
500*cf2f2c56Smiod 		   CGEN_FIELDS *fields)
501fddef416Sniklas {
502f7cc78ecSespie   /* ??? Runtime added insns not handled yet.  */
503f7cc78ecSespie   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
504fddef416Sniklas   const char *str = *strp;
505fddef416Sniklas   const char *errmsg;
506f7cc78ecSespie   const char *p;
507d2201f2fSdrahn   const CGEN_SYNTAX_CHAR_TYPE * syn;
508fddef416Sniklas #ifdef CGEN_MNEMONIC_OPERANDS
509f7cc78ecSespie   /* FIXME: wip */
510fddef416Sniklas   int past_opcode_p;
511fddef416Sniklas #endif
512fddef416Sniklas 
513f7cc78ecSespie   /* For now we assume the mnemonic is first (there are no leading operands).
514f7cc78ecSespie      We can parse it without needing to set up operand parsing.
515f7cc78ecSespie      GAS's input scrubber will ensure mnemonics are lowercase, but we may
516f7cc78ecSespie      not be called from GAS.  */
517f7cc78ecSespie   p = CGEN_INSN_MNEMONIC (insn);
518d2201f2fSdrahn   while (*p && TOLOWER (*p) == TOLOWER (*str))
519fddef416Sniklas     ++p, ++str;
520fddef416Sniklas 
521f7cc78ecSespie   if (* p)
522f7cc78ecSespie     return _("unrecognized instruction");
523f7cc78ecSespie 
524f7cc78ecSespie #ifndef CGEN_MNEMONIC_OPERANDS
525d2201f2fSdrahn   if (* str && ! ISSPACE (* str))
526f7cc78ecSespie     return _("unrecognized instruction");
527fddef416Sniklas #endif
528fddef416Sniklas 
529f7cc78ecSespie   CGEN_INIT_PARSE (cd);
530f7cc78ecSespie   cgen_init_parse_operand (cd);
531fddef416Sniklas #ifdef CGEN_MNEMONIC_OPERANDS
532fddef416Sniklas   past_opcode_p = 0;
533fddef416Sniklas #endif
534fddef416Sniklas 
535fddef416Sniklas   /* We don't check for (*str != '\0') here because we want to parse
536fddef416Sniklas      any trailing fake arguments in the syntax string.  */
537f7cc78ecSespie   syn = CGEN_SYNTAX_STRING (syntax);
538f7cc78ecSespie 
539f7cc78ecSespie   /* Mnemonics come first for now, ensure valid string.  */
540f7cc78ecSespie   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
541f7cc78ecSespie     abort ();
542f7cc78ecSespie 
543f7cc78ecSespie   ++syn;
544f7cc78ecSespie 
545f7cc78ecSespie   while (* syn != 0)
546fddef416Sniklas     {
547fddef416Sniklas       /* Non operand chars must match exactly.  */
548fddef416Sniklas       if (CGEN_SYNTAX_CHAR_P (* syn))
549fddef416Sniklas 	{
550f7cc78ecSespie 	  /* FIXME: While we allow for non-GAS callers above, we assume the
551f7cc78ecSespie 	     first char after the mnemonic part is a space.  */
552f7cc78ecSespie 	  /* FIXME: We also take inappropriate advantage of the fact that
553f7cc78ecSespie 	     GAS's input scrubber will remove extraneous blanks.  */
554d2201f2fSdrahn 	  if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
555fddef416Sniklas 	    {
556fddef416Sniklas #ifdef CGEN_MNEMONIC_OPERANDS
557d2201f2fSdrahn 	      if (CGEN_SYNTAX_CHAR(* syn) == ' ')
558fddef416Sniklas 		past_opcode_p = 1;
559fddef416Sniklas #endif
560fddef416Sniklas 	      ++ syn;
561fddef416Sniklas 	      ++ str;
562fddef416Sniklas 	    }
563d2201f2fSdrahn 	  else if (*str)
564fddef416Sniklas 	    {
565fddef416Sniklas 	      /* Syntax char didn't match.  Can't be this insn.  */
5665f210c2aSfgsch 	      static char msg [80];
567d2201f2fSdrahn 
5685f210c2aSfgsch 	      /* xgettext:c-format */
5695f210c2aSfgsch 	      sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
570d2201f2fSdrahn 		       CGEN_SYNTAX_CHAR(*syn), *str);
571d2201f2fSdrahn 	      return msg;
572d2201f2fSdrahn 	    }
573d2201f2fSdrahn 	  else
574d2201f2fSdrahn 	    {
575d2201f2fSdrahn 	      /* Ran out of input.  */
576d2201f2fSdrahn 	      static char msg [80];
577d2201f2fSdrahn 
578d2201f2fSdrahn 	      /* xgettext:c-format */
579d2201f2fSdrahn 	      sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
580d2201f2fSdrahn 		       CGEN_SYNTAX_CHAR(*syn));
5815f210c2aSfgsch 	      return msg;
582fddef416Sniklas 	    }
583fddef416Sniklas 	  continue;
584fddef416Sniklas 	}
585fddef416Sniklas 
586fddef416Sniklas       /* We have an operand of some sort.  */
587d2201f2fSdrahn       errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn),
588fddef416Sniklas 					  &str, fields);
589fddef416Sniklas       if (errmsg)
590fddef416Sniklas 	return errmsg;
591fddef416Sniklas 
592fddef416Sniklas       /* Done with this operand, continue with next one.  */
593fddef416Sniklas       ++ syn;
594fddef416Sniklas     }
595fddef416Sniklas 
596fddef416Sniklas   /* If we're at the end of the syntax string, we're done.  */
597d2201f2fSdrahn   if (* syn == 0)
598fddef416Sniklas     {
599fddef416Sniklas       /* FIXME: For the moment we assume a valid `str' can only contain
600fddef416Sniklas 	 blanks now.  IE: We needn't try again with a longer version of
601fddef416Sniklas 	 the insn and it is assumed that longer versions of insns appear
602fddef416Sniklas 	 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
603d2201f2fSdrahn       while (ISSPACE (* str))
604fddef416Sniklas 	++ str;
605fddef416Sniklas 
606fddef416Sniklas       if (* str != '\0')
607f7cc78ecSespie 	return _("junk at end of line"); /* FIXME: would like to include `str' */
608fddef416Sniklas 
609fddef416Sniklas       return NULL;
610fddef416Sniklas     }
611fddef416Sniklas 
612fddef416Sniklas   /* We couldn't parse it.  */
613f7cc78ecSespie   return _("unrecognized instruction");
614fddef416Sniklas }
615fddef416Sniklas 
616fddef416Sniklas /* Main entry point.
617fddef416Sniklas    This routine is called for each instruction to be assembled.
618fddef416Sniklas    STR points to the insn to be assembled.
619fddef416Sniklas    We assume all necessary tables have been initialized.
620f7cc78ecSespie    The assembled instruction, less any fixups, is stored in BUF.
621f7cc78ecSespie    Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
622f7cc78ecSespie    still needs to be converted to target byte order, otherwise BUF is an array
623f7cc78ecSespie    of bytes in target byte order.
624fddef416Sniklas    The result is a pointer to the insn's entry in the opcode table,
625fddef416Sniklas    or NULL if an error occured (an error message will have already been
626f7cc78ecSespie    printed).
627fddef416Sniklas 
628f7cc78ecSespie    Note that when processing (non-alias) macro-insns,
629f7cc78ecSespie    this function recurses.
630f7cc78ecSespie 
631f7cc78ecSespie    ??? It's possible to make this cpu-independent.
632f7cc78ecSespie    One would have to deal with a few minor things.
633f7cc78ecSespie    At this point in time doing so would be more of a curiosity than useful
634f7cc78ecSespie    [for example this file isn't _that_ big], but keeping the possibility in
635f7cc78ecSespie    mind helps keep the design clean.  */
636f7cc78ecSespie 
637f7cc78ecSespie const CGEN_INSN *
m32r_cgen_assemble_insn(CGEN_CPU_DESC cd,const char * str,CGEN_FIELDS * fields,CGEN_INSN_BYTES_PTR buf,char ** errmsg)638*cf2f2c56Smiod m32r_cgen_assemble_insn (CGEN_CPU_DESC cd,
639*cf2f2c56Smiod 			   const char *str,
640*cf2f2c56Smiod 			   CGEN_FIELDS *fields,
641*cf2f2c56Smiod 			   CGEN_INSN_BYTES_PTR buf,
642*cf2f2c56Smiod 			   char **errmsg)
643fddef416Sniklas {
644fddef416Sniklas   const char *start;
645fddef416Sniklas   CGEN_INSN_LIST *ilist;
646d2201f2fSdrahn   const char *parse_errmsg = NULL;
647d2201f2fSdrahn   const char *insert_errmsg = NULL;
648d2201f2fSdrahn   int recognized_mnemonic = 0;
649fddef416Sniklas 
650fddef416Sniklas   /* Skip leading white space.  */
651d2201f2fSdrahn   while (ISSPACE (* str))
652fddef416Sniklas     ++ str;
653fddef416Sniklas 
654fddef416Sniklas   /* The instructions are stored in hashed lists.
655fddef416Sniklas      Get the first in the list.  */
656f7cc78ecSespie   ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
657fddef416Sniklas 
658fddef416Sniklas   /* Keep looking until we find a match.  */
659fddef416Sniklas   start = str;
660fddef416Sniklas   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
661fddef416Sniklas     {
662f7cc78ecSespie       const CGEN_INSN *insn = ilist->insn;
663d2201f2fSdrahn       recognized_mnemonic = 1;
664fddef416Sniklas 
665f7cc78ecSespie #ifdef CGEN_VALIDATE_INSN_SUPPORTED
666d2201f2fSdrahn       /* Not usually needed as unsupported opcodes
667d2201f2fSdrahn 	 shouldn't be in the hash lists.  */
668fddef416Sniklas       /* Is this insn supported by the selected cpu?  */
669f7cc78ecSespie       if (! m32r_cgen_insn_supported (cd, insn))
670fddef416Sniklas 	continue;
671fddef416Sniklas #endif
672*cf2f2c56Smiod       /* If the RELAXED attribute is set, this is an insn that shouldn't be
673fddef416Sniklas 	 chosen immediately.  Instead, it is used during assembler/linker
674fddef416Sniklas 	 relaxation if possible.  */
675*cf2f2c56Smiod       if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
676fddef416Sniklas 	continue;
677fddef416Sniklas 
678fddef416Sniklas       str = start;
679fddef416Sniklas 
680d2201f2fSdrahn       /* Skip this insn if str doesn't look right lexically.  */
681d2201f2fSdrahn       if (CGEN_INSN_RX (insn) != NULL &&
682d2201f2fSdrahn 	  regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
683d2201f2fSdrahn 	continue;
684d2201f2fSdrahn 
685f7cc78ecSespie       /* Allow parse/insert handlers to obtain length of insn.  */
686fddef416Sniklas       CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
687fddef416Sniklas 
688d2201f2fSdrahn       parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
689d2201f2fSdrahn       if (parse_errmsg != NULL)
690f7cc78ecSespie 	continue;
6915f210c2aSfgsch 
692d2201f2fSdrahn       /* ??? 0 is passed for `pc'.  */
693d2201f2fSdrahn       insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
6945f210c2aSfgsch 						 (bfd_vma) 0);
695d2201f2fSdrahn       if (insert_errmsg != NULL)
6965f210c2aSfgsch         continue;
6975f210c2aSfgsch 
698fddef416Sniklas       /* It is up to the caller to actually output the insn and any
699fddef416Sniklas          queued relocs.  */
700fddef416Sniklas       return insn;
701fddef416Sniklas     }
702fddef416Sniklas 
703fddef416Sniklas   {
704f7cc78ecSespie     static char errbuf[150];
705f7cc78ecSespie #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
706d2201f2fSdrahn     const char *tmp_errmsg;
707d2201f2fSdrahn 
708d2201f2fSdrahn     /* If requesting verbose error messages, use insert_errmsg.
709d2201f2fSdrahn        Failing that, use parse_errmsg.  */
710d2201f2fSdrahn     tmp_errmsg = (insert_errmsg ? insert_errmsg :
711d2201f2fSdrahn 		  parse_errmsg ? parse_errmsg :
712d2201f2fSdrahn 		  recognized_mnemonic ?
713d2201f2fSdrahn 		  _("unrecognized form of instruction") :
714d2201f2fSdrahn 		  _("unrecognized instruction"));
715d2201f2fSdrahn 
716f7cc78ecSespie     if (strlen (start) > 50)
717f7cc78ecSespie       /* xgettext:c-format */
718f7cc78ecSespie       sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
719f7cc78ecSespie     else
720f7cc78ecSespie       /* xgettext:c-format */
721f7cc78ecSespie       sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
722f7cc78ecSespie #else
723f7cc78ecSespie     if (strlen (start) > 50)
724f7cc78ecSespie       /* xgettext:c-format */
725f7cc78ecSespie       sprintf (errbuf, _("bad instruction `%.50s...'"), start);
726f7cc78ecSespie     else
727f7cc78ecSespie       /* xgettext:c-format */
728f7cc78ecSespie       sprintf (errbuf, _("bad instruction `%.50s'"), start);
729f7cc78ecSespie #endif
730f7cc78ecSespie 
731fddef416Sniklas     *errmsg = errbuf;
732fddef416Sniklas     return NULL;
733fddef416Sniklas   }
734fddef416Sniklas }
735fddef416Sniklas 
736fddef416Sniklas #if 0 /* This calls back to GAS which we can't do without care.  */
737fddef416Sniklas 
738fddef416Sniklas /* Record each member of OPVALS in the assembler's symbol table.
739fddef416Sniklas    This lets GAS parse registers for us.
740fddef416Sniklas    ??? Interesting idea but not currently used.  */
741fddef416Sniklas 
742f7cc78ecSespie /* Record each member of OPVALS in the assembler's symbol table.
743f7cc78ecSespie    FIXME: Not currently used.  */
744f7cc78ecSespie 
745fddef416Sniklas void
746*cf2f2c56Smiod m32r_cgen_asm_hash_keywords (CGEN_CPU_DESC cd, CGEN_KEYWORD *opvals)
747fddef416Sniklas {
748f7cc78ecSespie   CGEN_KEYWORD_SEARCH search = cgen_keyword_search_init (opvals, NULL);
749f7cc78ecSespie   const CGEN_KEYWORD_ENTRY * ke;
750fddef416Sniklas 
751fddef416Sniklas   while ((ke = cgen_keyword_search_next (& search)) != NULL)
752fddef416Sniklas     {
753fddef416Sniklas #if 0 /* Unnecessary, should be done in the search routine.  */
754fddef416Sniklas       if (! m32r_cgen_opval_supported (ke))
755fddef416Sniklas 	continue;
756fddef416Sniklas #endif
757f7cc78ecSespie       cgen_asm_record_register (cd, ke->name, ke->value);
758fddef416Sniklas     }
759fddef416Sniklas }
760fddef416Sniklas 
761fddef416Sniklas #endif /* 0 */
762