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