107163879Schristos /* DO NOT EDIT! -*- buffer-read-only: t -*- vi:set ro: */
2c5dff60aSchristos /* Assembler interface for targets using CGEN. -*- C -*-
3c5dff60aSchristos CGEN: Cpu tools GENerator
4c5dff60aSchristos
5c5dff60aSchristos THIS FILE IS MACHINE GENERATED WITH CGEN.
6c5dff60aSchristos - the resultant file is machine generated, cgen-asm.in isn't
7c5dff60aSchristos
8*1424dfb3Schristos Copyright (C) 1996-2020 Free Software Foundation, Inc.
9c5dff60aSchristos
10c5dff60aSchristos This file is part of libopcodes.
11c5dff60aSchristos
12c5dff60aSchristos This library is free software; you can redistribute it and/or modify
13c5dff60aSchristos it under the terms of the GNU General Public License as published by
14c5dff60aSchristos the Free Software Foundation; either version 3, or (at your option)
15c5dff60aSchristos any later version.
16c5dff60aSchristos
17c5dff60aSchristos It is distributed in the hope that it will be useful, but WITHOUT
18c5dff60aSchristos ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19c5dff60aSchristos or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
20c5dff60aSchristos License for more details.
21c5dff60aSchristos
22c5dff60aSchristos You should have received a copy of the GNU General Public License
23c5dff60aSchristos along with this program; if not, write to the Free Software Foundation, Inc.,
24c5dff60aSchristos 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
25c5dff60aSchristos
26c5dff60aSchristos
27c5dff60aSchristos /* ??? Eventually more and more of this stuff can go to cpu-independent files.
28c5dff60aSchristos Keep that in mind. */
29c5dff60aSchristos
30c5dff60aSchristos #include "sysdep.h"
31c5dff60aSchristos #include <stdio.h>
32c5dff60aSchristos #include "ansidecl.h"
33c5dff60aSchristos #include "bfd.h"
34c5dff60aSchristos #include "symcat.h"
35c5dff60aSchristos #include "xstormy16-desc.h"
36c5dff60aSchristos #include "xstormy16-opc.h"
37c5dff60aSchristos #include "opintl.h"
38c5dff60aSchristos #include "xregex.h"
39c5dff60aSchristos #include "libiberty.h"
40c5dff60aSchristos #include "safe-ctype.h"
41c5dff60aSchristos
42c5dff60aSchristos #undef min
43c5dff60aSchristos #define min(a,b) ((a) < (b) ? (a) : (b))
44c5dff60aSchristos #undef max
45c5dff60aSchristos #define max(a,b) ((a) > (b) ? (a) : (b))
46c5dff60aSchristos
47c5dff60aSchristos static const char * parse_insn_normal
48c5dff60aSchristos (CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *);
49c5dff60aSchristos
50c5dff60aSchristos /* -- assembler routines inserted here. */
51c5dff60aSchristos
52c5dff60aSchristos /* -- asm.c */
53c5dff60aSchristos
54c5dff60aSchristos /* The machine-independent code doesn't know how to disambiguate
55c5dff60aSchristos mov (foo),r3
56c5dff60aSchristos and
57c5dff60aSchristos mov (r2),r3
58c5dff60aSchristos where 'foo' is a label. This helps it out. */
59c5dff60aSchristos
60c5dff60aSchristos static const char *
parse_mem8(CGEN_CPU_DESC cd,const char ** strp,int opindex,unsigned long * valuep)61c5dff60aSchristos parse_mem8 (CGEN_CPU_DESC cd,
62c5dff60aSchristos const char **strp,
63c5dff60aSchristos int opindex,
64c5dff60aSchristos unsigned long *valuep)
65c5dff60aSchristos {
66c5dff60aSchristos if (**strp == '(')
67c5dff60aSchristos {
68c5dff60aSchristos const char *s = *strp;
69c5dff60aSchristos
70c5dff60aSchristos if (s[1] == '-' && s[2] == '-')
71c5dff60aSchristos return _("Bad register in preincrement");
72c5dff60aSchristos
73c5dff60aSchristos while (ISALNUM (*++s))
74c5dff60aSchristos ;
75c5dff60aSchristos if (s[0] == '+' && s[1] == '+' && (s[2] == ')' || s[2] == ','))
76c5dff60aSchristos return _("Bad register in postincrement");
77c5dff60aSchristos if (s[0] == ',' || s[0] == ')')
78c5dff60aSchristos return _("Bad register name");
79c5dff60aSchristos }
80c5dff60aSchristos else if (cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_gr_names,
81c5dff60aSchristos (long *) valuep) == NULL)
82c5dff60aSchristos return _("Label conflicts with register name");
83c5dff60aSchristos else if (strncasecmp (*strp, "rx,", 3) == 0
84c5dff60aSchristos || strncasecmp (*strp, "rxl,", 3) == 0
85c5dff60aSchristos || strncasecmp (*strp, "rxh,", 3) == 0)
86c5dff60aSchristos return _("Label conflicts with `Rx'");
87c5dff60aSchristos else if (**strp == '#')
88c5dff60aSchristos return _("Bad immediate expression");
89c5dff60aSchristos
90c5dff60aSchristos return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
91c5dff60aSchristos }
92c5dff60aSchristos
93c5dff60aSchristos /* For the add and subtract instructions, there are two immediate forms,
94c5dff60aSchristos one for small operands and one for large ones. We want to use
95c5dff60aSchristos the small one when possible, but we do not want to generate relocs
96c5dff60aSchristos of the small size. This is somewhat tricky. */
97c5dff60aSchristos
98c5dff60aSchristos static const char *
parse_small_immediate(CGEN_CPU_DESC cd,const char ** strp,int opindex,unsigned long * valuep)99c5dff60aSchristos parse_small_immediate (CGEN_CPU_DESC cd,
100c5dff60aSchristos const char **strp,
101c5dff60aSchristos int opindex,
102c5dff60aSchristos unsigned long *valuep)
103c5dff60aSchristos {
104c5dff60aSchristos bfd_vma value;
105c5dff60aSchristos enum cgen_parse_operand_result result;
106c5dff60aSchristos const char *errmsg;
107c5dff60aSchristos
108c5dff60aSchristos if (**strp == '@')
109c5dff60aSchristos return _("No relocation for small immediate");
110c5dff60aSchristos
111c5dff60aSchristos errmsg = (* cd->parse_operand_fn)
112c5dff60aSchristos (cd, CGEN_PARSE_OPERAND_INTEGER, strp, opindex, BFD_RELOC_NONE,
113c5dff60aSchristos & result, & value);
114c5dff60aSchristos
115c5dff60aSchristos if (errmsg)
116c5dff60aSchristos return errmsg;
117c5dff60aSchristos
118c5dff60aSchristos if (result != CGEN_PARSE_OPERAND_RESULT_NUMBER)
119c5dff60aSchristos return _("Small operand was not an immediate number");
120c5dff60aSchristos
121c5dff60aSchristos *valuep = value;
122c5dff60aSchristos return NULL;
123c5dff60aSchristos }
124c5dff60aSchristos
125c5dff60aSchristos /* Literal scan be either a normal literal, a @hi() or @lo relocation. */
126c5dff60aSchristos
127c5dff60aSchristos static const char *
parse_immediate16(CGEN_CPU_DESC cd,const char ** strp,int opindex,unsigned long * valuep)128c5dff60aSchristos parse_immediate16 (CGEN_CPU_DESC cd,
129c5dff60aSchristos const char **strp,
130c5dff60aSchristos int opindex,
131c5dff60aSchristos unsigned long *valuep)
132c5dff60aSchristos {
133c5dff60aSchristos const char *errmsg;
134c5dff60aSchristos enum cgen_parse_operand_result result;
135c5dff60aSchristos bfd_reloc_code_real_type code = BFD_RELOC_NONE;
136c5dff60aSchristos bfd_vma value;
137c5dff60aSchristos
138c5dff60aSchristos if (strncmp (*strp, "@hi(", 4) == 0)
139c5dff60aSchristos {
140c5dff60aSchristos *strp += 4;
141c5dff60aSchristos code = BFD_RELOC_HI16;
142c5dff60aSchristos }
143c5dff60aSchristos else
144c5dff60aSchristos if (strncmp (*strp, "@lo(", 4) == 0)
145c5dff60aSchristos {
146c5dff60aSchristos *strp += 4;
147c5dff60aSchristos code = BFD_RELOC_LO16;
148c5dff60aSchristos }
149c5dff60aSchristos
150c5dff60aSchristos if (code == BFD_RELOC_NONE)
151c5dff60aSchristos errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
152c5dff60aSchristos else
153c5dff60aSchristos {
154c5dff60aSchristos errmsg = cgen_parse_address (cd, strp, opindex, code, &result, &value);
155c5dff60aSchristos if ((errmsg == NULL) &&
156c5dff60aSchristos (result != CGEN_PARSE_OPERAND_RESULT_QUEUED))
157c5dff60aSchristos errmsg = _("Operand is not a symbol");
158c5dff60aSchristos
159c5dff60aSchristos *valuep = value;
160c5dff60aSchristos if ((code == BFD_RELOC_HI16 || code == BFD_RELOC_LO16)
161c5dff60aSchristos && **strp == ')')
162c5dff60aSchristos *strp += 1;
163c5dff60aSchristos else
164c5dff60aSchristos {
165c5dff60aSchristos errmsg = _("Syntax error: No trailing ')'");
166c5dff60aSchristos return errmsg;
167c5dff60aSchristos }
168c5dff60aSchristos }
169c5dff60aSchristos return errmsg;
170c5dff60aSchristos }
171c5dff60aSchristos /* -- */
172c5dff60aSchristos
173c5dff60aSchristos const char * xstormy16_cgen_parse_operand
174c5dff60aSchristos (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
175c5dff60aSchristos
176c5dff60aSchristos /* Main entry point for operand parsing.
177c5dff60aSchristos
178c5dff60aSchristos This function is basically just a big switch statement. Earlier versions
179c5dff60aSchristos used tables to look up the function to use, but
180c5dff60aSchristos - if the table contains both assembler and disassembler functions then
181c5dff60aSchristos the disassembler contains much of the assembler and vice-versa,
182c5dff60aSchristos - there's a lot of inlining possibilities as things grow,
183c5dff60aSchristos - using a switch statement avoids the function call overhead.
184c5dff60aSchristos
185c5dff60aSchristos This function could be moved into `parse_insn_normal', but keeping it
186c5dff60aSchristos separate makes clear the interface between `parse_insn_normal' and each of
187c5dff60aSchristos the handlers. */
188c5dff60aSchristos
189c5dff60aSchristos const char *
xstormy16_cgen_parse_operand(CGEN_CPU_DESC cd,int opindex,const char ** strp,CGEN_FIELDS * fields)190c5dff60aSchristos xstormy16_cgen_parse_operand (CGEN_CPU_DESC cd,
191c5dff60aSchristos int opindex,
192c5dff60aSchristos const char ** strp,
193c5dff60aSchristos CGEN_FIELDS * fields)
194c5dff60aSchristos {
195c5dff60aSchristos const char * errmsg = NULL;
196c5dff60aSchristos /* Used by scalar operands that still need to be parsed. */
197c5dff60aSchristos long junk ATTRIBUTE_UNUSED;
198c5dff60aSchristos
199c5dff60aSchristos switch (opindex)
200c5dff60aSchristos {
201c5dff60aSchristos case XSTORMY16_OPERAND_RB :
202c5dff60aSchristos errmsg = cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_gr_Rb_names, & fields->f_Rb);
203c5dff60aSchristos break;
204c5dff60aSchristos case XSTORMY16_OPERAND_RBJ :
205c5dff60aSchristos errmsg = cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_gr_Rb_names, & fields->f_Rbj);
206c5dff60aSchristos break;
207c5dff60aSchristos case XSTORMY16_OPERAND_RD :
208c5dff60aSchristos errmsg = cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_gr_names, & fields->f_Rd);
209c5dff60aSchristos break;
210c5dff60aSchristos case XSTORMY16_OPERAND_RDM :
211c5dff60aSchristos errmsg = cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_gr_names, & fields->f_Rdm);
212c5dff60aSchristos break;
213c5dff60aSchristos case XSTORMY16_OPERAND_RM :
214c5dff60aSchristos errmsg = cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_gr_names, & fields->f_Rm);
215c5dff60aSchristos break;
216c5dff60aSchristos case XSTORMY16_OPERAND_RS :
217c5dff60aSchristos errmsg = cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_gr_names, & fields->f_Rs);
218c5dff60aSchristos break;
219c5dff60aSchristos case XSTORMY16_OPERAND_ABS24 :
220c5dff60aSchristos errmsg = cgen_parse_unsigned_integer (cd, strp, XSTORMY16_OPERAND_ABS24, (unsigned long *) (& fields->f_abs24));
221c5dff60aSchristos break;
222c5dff60aSchristos case XSTORMY16_OPERAND_BCOND2 :
223c5dff60aSchristos errmsg = cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_h_branchcond, & fields->f_op2);
224c5dff60aSchristos break;
225c5dff60aSchristos case XSTORMY16_OPERAND_BCOND5 :
226c5dff60aSchristos errmsg = cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_h_branchcond, & fields->f_op5);
227c5dff60aSchristos break;
228c5dff60aSchristos case XSTORMY16_OPERAND_HMEM8 :
229c5dff60aSchristos errmsg = parse_mem8 (cd, strp, XSTORMY16_OPERAND_HMEM8, (unsigned long *) (& fields->f_hmem8));
230c5dff60aSchristos break;
231c5dff60aSchristos case XSTORMY16_OPERAND_IMM12 :
232c5dff60aSchristos errmsg = cgen_parse_signed_integer (cd, strp, XSTORMY16_OPERAND_IMM12, (long *) (& fields->f_imm12));
233c5dff60aSchristos break;
234c5dff60aSchristos case XSTORMY16_OPERAND_IMM16 :
235c5dff60aSchristos errmsg = parse_immediate16 (cd, strp, XSTORMY16_OPERAND_IMM16, (unsigned long *) (& fields->f_imm16));
236c5dff60aSchristos break;
237c5dff60aSchristos case XSTORMY16_OPERAND_IMM2 :
238c5dff60aSchristos errmsg = cgen_parse_unsigned_integer (cd, strp, XSTORMY16_OPERAND_IMM2, (unsigned long *) (& fields->f_imm2));
239c5dff60aSchristos break;
240c5dff60aSchristos case XSTORMY16_OPERAND_IMM3 :
241c5dff60aSchristos errmsg = cgen_parse_unsigned_integer (cd, strp, XSTORMY16_OPERAND_IMM3, (unsigned long *) (& fields->f_imm3));
242c5dff60aSchristos break;
243c5dff60aSchristos case XSTORMY16_OPERAND_IMM3B :
244c5dff60aSchristos errmsg = cgen_parse_unsigned_integer (cd, strp, XSTORMY16_OPERAND_IMM3B, (unsigned long *) (& fields->f_imm3b));
245c5dff60aSchristos break;
246c5dff60aSchristos case XSTORMY16_OPERAND_IMM4 :
247c5dff60aSchristos errmsg = parse_small_immediate (cd, strp, XSTORMY16_OPERAND_IMM4, (unsigned long *) (& fields->f_imm4));
248c5dff60aSchristos break;
249c5dff60aSchristos case XSTORMY16_OPERAND_IMM8 :
250c5dff60aSchristos errmsg = cgen_parse_unsigned_integer (cd, strp, XSTORMY16_OPERAND_IMM8, (unsigned long *) (& fields->f_imm8));
251c5dff60aSchristos break;
252c5dff60aSchristos case XSTORMY16_OPERAND_IMM8SMALL :
253c5dff60aSchristos errmsg = parse_small_immediate (cd, strp, XSTORMY16_OPERAND_IMM8SMALL, (unsigned long *) (& fields->f_imm8));
254c5dff60aSchristos break;
255c5dff60aSchristos case XSTORMY16_OPERAND_LMEM8 :
256c5dff60aSchristos errmsg = parse_mem8 (cd, strp, XSTORMY16_OPERAND_LMEM8, (unsigned long *) (& fields->f_lmem8));
257c5dff60aSchristos break;
258c5dff60aSchristos case XSTORMY16_OPERAND_REL12 :
259c5dff60aSchristos errmsg = cgen_parse_unsigned_integer (cd, strp, XSTORMY16_OPERAND_REL12, (unsigned long *) (& fields->f_rel12));
260c5dff60aSchristos break;
261c5dff60aSchristos case XSTORMY16_OPERAND_REL12A :
262c5dff60aSchristos errmsg = cgen_parse_unsigned_integer (cd, strp, XSTORMY16_OPERAND_REL12A, (unsigned long *) (& fields->f_rel12a));
263c5dff60aSchristos break;
264c5dff60aSchristos case XSTORMY16_OPERAND_REL8_2 :
265c5dff60aSchristos errmsg = cgen_parse_unsigned_integer (cd, strp, XSTORMY16_OPERAND_REL8_2, (unsigned long *) (& fields->f_rel8_2));
266c5dff60aSchristos break;
267c5dff60aSchristos case XSTORMY16_OPERAND_REL8_4 :
268c5dff60aSchristos errmsg = cgen_parse_unsigned_integer (cd, strp, XSTORMY16_OPERAND_REL8_4, (unsigned long *) (& fields->f_rel8_4));
269c5dff60aSchristos break;
270c5dff60aSchristos case XSTORMY16_OPERAND_WS2 :
271c5dff60aSchristos errmsg = cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_h_wordsize, & fields->f_op2m);
272c5dff60aSchristos break;
273c5dff60aSchristos
274c5dff60aSchristos default :
275c5dff60aSchristos /* xgettext:c-format */
27607163879Schristos opcodes_error_handler
27707163879Schristos (_("internal error: unrecognized field %d while parsing"),
27807163879Schristos opindex);
279c5dff60aSchristos abort ();
280c5dff60aSchristos }
281c5dff60aSchristos
282c5dff60aSchristos return errmsg;
283c5dff60aSchristos }
284c5dff60aSchristos
285c5dff60aSchristos cgen_parse_fn * const xstormy16_cgen_parse_handlers[] =
286c5dff60aSchristos {
287c5dff60aSchristos parse_insn_normal,
288c5dff60aSchristos };
289c5dff60aSchristos
290c5dff60aSchristos void
xstormy16_cgen_init_asm(CGEN_CPU_DESC cd)291c5dff60aSchristos xstormy16_cgen_init_asm (CGEN_CPU_DESC cd)
292c5dff60aSchristos {
293c5dff60aSchristos xstormy16_cgen_init_opcode_table (cd);
294c5dff60aSchristos xstormy16_cgen_init_ibld_table (cd);
295c5dff60aSchristos cd->parse_handlers = & xstormy16_cgen_parse_handlers[0];
296c5dff60aSchristos cd->parse_operand = xstormy16_cgen_parse_operand;
297c5dff60aSchristos #ifdef CGEN_ASM_INIT_HOOK
298c5dff60aSchristos CGEN_ASM_INIT_HOOK
299c5dff60aSchristos #endif
300c5dff60aSchristos }
301c5dff60aSchristos
302c5dff60aSchristos
303c5dff60aSchristos
304c5dff60aSchristos /* Regex construction routine.
305c5dff60aSchristos
306c5dff60aSchristos This translates an opcode syntax string into a regex string,
307c5dff60aSchristos by replacing any non-character syntax element (such as an
308c5dff60aSchristos opcode) with the pattern '.*'
309c5dff60aSchristos
310c5dff60aSchristos It then compiles the regex and stores it in the opcode, for
311c5dff60aSchristos later use by xstormy16_cgen_assemble_insn
312c5dff60aSchristos
313c5dff60aSchristos Returns NULL for success, an error message for failure. */
314c5dff60aSchristos
315c5dff60aSchristos char *
xstormy16_cgen_build_insn_regex(CGEN_INSN * insn)316c5dff60aSchristos xstormy16_cgen_build_insn_regex (CGEN_INSN *insn)
317c5dff60aSchristos {
318c5dff60aSchristos CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
319c5dff60aSchristos const char *mnem = CGEN_INSN_MNEMONIC (insn);
320c5dff60aSchristos char rxbuf[CGEN_MAX_RX_ELEMENTS];
321c5dff60aSchristos char *rx = rxbuf;
322c5dff60aSchristos const CGEN_SYNTAX_CHAR_TYPE *syn;
323c5dff60aSchristos int reg_err;
324c5dff60aSchristos
325c5dff60aSchristos syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
326c5dff60aSchristos
327c5dff60aSchristos /* Mnemonics come first in the syntax string. */
328c5dff60aSchristos if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
329c5dff60aSchristos return _("missing mnemonic in syntax string");
330c5dff60aSchristos ++syn;
331c5dff60aSchristos
332c5dff60aSchristos /* Generate a case sensitive regular expression that emulates case
333c5dff60aSchristos insensitive matching in the "C" locale. We cannot generate a case
334c5dff60aSchristos insensitive regular expression because in Turkish locales, 'i' and 'I'
335c5dff60aSchristos are not equal modulo case conversion. */
336c5dff60aSchristos
337c5dff60aSchristos /* Copy the literal mnemonic out of the insn. */
338c5dff60aSchristos for (; *mnem; mnem++)
339c5dff60aSchristos {
340c5dff60aSchristos char c = *mnem;
341c5dff60aSchristos
342c5dff60aSchristos if (ISALPHA (c))
343c5dff60aSchristos {
344c5dff60aSchristos *rx++ = '[';
345c5dff60aSchristos *rx++ = TOLOWER (c);
346c5dff60aSchristos *rx++ = TOUPPER (c);
347c5dff60aSchristos *rx++ = ']';
348c5dff60aSchristos }
349c5dff60aSchristos else
350c5dff60aSchristos *rx++ = c;
351c5dff60aSchristos }
352c5dff60aSchristos
353c5dff60aSchristos /* Copy any remaining literals from the syntax string into the rx. */
354c5dff60aSchristos for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
355c5dff60aSchristos {
356c5dff60aSchristos if (CGEN_SYNTAX_CHAR_P (* syn))
357c5dff60aSchristos {
358c5dff60aSchristos char c = CGEN_SYNTAX_CHAR (* syn);
359c5dff60aSchristos
360c5dff60aSchristos switch (c)
361c5dff60aSchristos {
362c5dff60aSchristos /* Escape any regex metacharacters in the syntax. */
363c5dff60aSchristos case '.': case '[': case '\\':
364c5dff60aSchristos case '*': case '^': case '$':
365c5dff60aSchristos
366c5dff60aSchristos #ifdef CGEN_ESCAPE_EXTENDED_REGEX
367c5dff60aSchristos case '?': case '{': case '}':
368c5dff60aSchristos case '(': case ')': case '*':
369c5dff60aSchristos case '|': case '+': case ']':
370c5dff60aSchristos #endif
371c5dff60aSchristos *rx++ = '\\';
372c5dff60aSchristos *rx++ = c;
373c5dff60aSchristos break;
374c5dff60aSchristos
375c5dff60aSchristos default:
376c5dff60aSchristos if (ISALPHA (c))
377c5dff60aSchristos {
378c5dff60aSchristos *rx++ = '[';
379c5dff60aSchristos *rx++ = TOLOWER (c);
380c5dff60aSchristos *rx++ = TOUPPER (c);
381c5dff60aSchristos *rx++ = ']';
382c5dff60aSchristos }
383c5dff60aSchristos else
384c5dff60aSchristos *rx++ = c;
385c5dff60aSchristos break;
386c5dff60aSchristos }
387c5dff60aSchristos }
388c5dff60aSchristos else
389c5dff60aSchristos {
390c5dff60aSchristos /* Replace non-syntax fields with globs. */
391c5dff60aSchristos *rx++ = '.';
392c5dff60aSchristos *rx++ = '*';
393c5dff60aSchristos }
394c5dff60aSchristos }
395c5dff60aSchristos
396c5dff60aSchristos /* Trailing whitespace ok. */
397c5dff60aSchristos * rx++ = '[';
398c5dff60aSchristos * rx++ = ' ';
399c5dff60aSchristos * rx++ = '\t';
400c5dff60aSchristos * rx++ = ']';
401c5dff60aSchristos * rx++ = '*';
402c5dff60aSchristos
403c5dff60aSchristos /* But anchor it after that. */
404c5dff60aSchristos * rx++ = '$';
405c5dff60aSchristos * rx = '\0';
406c5dff60aSchristos
407c5dff60aSchristos CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
408c5dff60aSchristos reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
409c5dff60aSchristos
410c5dff60aSchristos if (reg_err == 0)
411c5dff60aSchristos return NULL;
412c5dff60aSchristos else
413c5dff60aSchristos {
414c5dff60aSchristos static char msg[80];
415c5dff60aSchristos
416c5dff60aSchristos regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
417c5dff60aSchristos regfree ((regex_t *) CGEN_INSN_RX (insn));
418c5dff60aSchristos free (CGEN_INSN_RX (insn));
419c5dff60aSchristos (CGEN_INSN_RX (insn)) = NULL;
420c5dff60aSchristos return msg;
421c5dff60aSchristos }
422c5dff60aSchristos }
423c5dff60aSchristos
424c5dff60aSchristos
425c5dff60aSchristos /* Default insn parser.
426c5dff60aSchristos
427c5dff60aSchristos The syntax string is scanned and operands are parsed and stored in FIELDS.
428c5dff60aSchristos Relocs are queued as we go via other callbacks.
429c5dff60aSchristos
430c5dff60aSchristos ??? Note that this is currently an all-or-nothing parser. If we fail to
431c5dff60aSchristos parse the instruction, we return 0 and the caller will start over from
432c5dff60aSchristos the beginning. Backtracking will be necessary in parsing subexpressions,
433c5dff60aSchristos but that can be handled there. Not handling backtracking here may get
434c5dff60aSchristos expensive in the case of the m68k. Deal with later.
435c5dff60aSchristos
436c5dff60aSchristos Returns NULL for success, an error message for failure. */
437c5dff60aSchristos
438c5dff60aSchristos static const char *
parse_insn_normal(CGEN_CPU_DESC cd,const CGEN_INSN * insn,const char ** strp,CGEN_FIELDS * fields)439c5dff60aSchristos parse_insn_normal (CGEN_CPU_DESC cd,
440c5dff60aSchristos const CGEN_INSN *insn,
441c5dff60aSchristos const char **strp,
442c5dff60aSchristos CGEN_FIELDS *fields)
443c5dff60aSchristos {
444c5dff60aSchristos /* ??? Runtime added insns not handled yet. */
445c5dff60aSchristos const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
446c5dff60aSchristos const char *str = *strp;
447c5dff60aSchristos const char *errmsg;
448c5dff60aSchristos const char *p;
449c5dff60aSchristos const CGEN_SYNTAX_CHAR_TYPE * syn;
450c5dff60aSchristos #ifdef CGEN_MNEMONIC_OPERANDS
451c5dff60aSchristos /* FIXME: wip */
452c5dff60aSchristos int past_opcode_p;
453c5dff60aSchristos #endif
454c5dff60aSchristos
455c5dff60aSchristos /* For now we assume the mnemonic is first (there are no leading operands).
456c5dff60aSchristos We can parse it without needing to set up operand parsing.
457c5dff60aSchristos GAS's input scrubber will ensure mnemonics are lowercase, but we may
458c5dff60aSchristos not be called from GAS. */
459c5dff60aSchristos p = CGEN_INSN_MNEMONIC (insn);
460c5dff60aSchristos while (*p && TOLOWER (*p) == TOLOWER (*str))
461c5dff60aSchristos ++p, ++str;
462c5dff60aSchristos
463c5dff60aSchristos if (* p)
464c5dff60aSchristos return _("unrecognized instruction");
465c5dff60aSchristos
466c5dff60aSchristos #ifndef CGEN_MNEMONIC_OPERANDS
467c5dff60aSchristos if (* str && ! ISSPACE (* str))
468c5dff60aSchristos return _("unrecognized instruction");
469c5dff60aSchristos #endif
470c5dff60aSchristos
471c5dff60aSchristos CGEN_INIT_PARSE (cd);
472c5dff60aSchristos cgen_init_parse_operand (cd);
473c5dff60aSchristos #ifdef CGEN_MNEMONIC_OPERANDS
474c5dff60aSchristos past_opcode_p = 0;
475c5dff60aSchristos #endif
476c5dff60aSchristos
477c5dff60aSchristos /* We don't check for (*str != '\0') here because we want to parse
478c5dff60aSchristos any trailing fake arguments in the syntax string. */
479c5dff60aSchristos syn = CGEN_SYNTAX_STRING (syntax);
480c5dff60aSchristos
481c5dff60aSchristos /* Mnemonics come first for now, ensure valid string. */
482c5dff60aSchristos if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
483c5dff60aSchristos abort ();
484c5dff60aSchristos
485c5dff60aSchristos ++syn;
486c5dff60aSchristos
487c5dff60aSchristos while (* syn != 0)
488c5dff60aSchristos {
489c5dff60aSchristos /* Non operand chars must match exactly. */
490c5dff60aSchristos if (CGEN_SYNTAX_CHAR_P (* syn))
491c5dff60aSchristos {
492c5dff60aSchristos /* FIXME: While we allow for non-GAS callers above, we assume the
493c5dff60aSchristos first char after the mnemonic part is a space. */
494c5dff60aSchristos /* FIXME: We also take inappropriate advantage of the fact that
495c5dff60aSchristos GAS's input scrubber will remove extraneous blanks. */
496c5dff60aSchristos if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
497c5dff60aSchristos {
498c5dff60aSchristos #ifdef CGEN_MNEMONIC_OPERANDS
499c5dff60aSchristos if (CGEN_SYNTAX_CHAR(* syn) == ' ')
500c5dff60aSchristos past_opcode_p = 1;
501c5dff60aSchristos #endif
502c5dff60aSchristos ++ syn;
503c5dff60aSchristos ++ str;
504c5dff60aSchristos }
505c5dff60aSchristos else if (*str)
506c5dff60aSchristos {
507c5dff60aSchristos /* Syntax char didn't match. Can't be this insn. */
508c5dff60aSchristos static char msg [80];
509c5dff60aSchristos
510c5dff60aSchristos /* xgettext:c-format */
511c5dff60aSchristos sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
512c5dff60aSchristos CGEN_SYNTAX_CHAR(*syn), *str);
513c5dff60aSchristos return msg;
514c5dff60aSchristos }
515c5dff60aSchristos else
516c5dff60aSchristos {
517c5dff60aSchristos /* Ran out of input. */
518c5dff60aSchristos static char msg [80];
519c5dff60aSchristos
520c5dff60aSchristos /* xgettext:c-format */
521c5dff60aSchristos sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
522c5dff60aSchristos CGEN_SYNTAX_CHAR(*syn));
523c5dff60aSchristos return msg;
524c5dff60aSchristos }
525c5dff60aSchristos continue;
526c5dff60aSchristos }
527c5dff60aSchristos
528c5dff60aSchristos #ifdef CGEN_MNEMONIC_OPERANDS
529c5dff60aSchristos (void) past_opcode_p;
530c5dff60aSchristos #endif
531c5dff60aSchristos /* We have an operand of some sort. */
532c5dff60aSchristos errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn), &str, fields);
533c5dff60aSchristos if (errmsg)
534c5dff60aSchristos return errmsg;
535c5dff60aSchristos
536c5dff60aSchristos /* Done with this operand, continue with next one. */
537c5dff60aSchristos ++ syn;
538c5dff60aSchristos }
539c5dff60aSchristos
540c5dff60aSchristos /* If we're at the end of the syntax string, we're done. */
541c5dff60aSchristos if (* syn == 0)
542c5dff60aSchristos {
543c5dff60aSchristos /* FIXME: For the moment we assume a valid `str' can only contain
544c5dff60aSchristos blanks now. IE: We needn't try again with a longer version of
545c5dff60aSchristos the insn and it is assumed that longer versions of insns appear
546c5dff60aSchristos before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */
547c5dff60aSchristos while (ISSPACE (* str))
548c5dff60aSchristos ++ str;
549c5dff60aSchristos
550c5dff60aSchristos if (* str != '\0')
551c5dff60aSchristos return _("junk at end of line"); /* FIXME: would like to include `str' */
552c5dff60aSchristos
553c5dff60aSchristos return NULL;
554c5dff60aSchristos }
555c5dff60aSchristos
556c5dff60aSchristos /* We couldn't parse it. */
557c5dff60aSchristos return _("unrecognized instruction");
558c5dff60aSchristos }
559c5dff60aSchristos
560c5dff60aSchristos /* Main entry point.
561c5dff60aSchristos This routine is called for each instruction to be assembled.
562c5dff60aSchristos STR points to the insn to be assembled.
563c5dff60aSchristos We assume all necessary tables have been initialized.
564c5dff60aSchristos The assembled instruction, less any fixups, is stored in BUF.
565c5dff60aSchristos Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
566c5dff60aSchristos still needs to be converted to target byte order, otherwise BUF is an array
567c5dff60aSchristos of bytes in target byte order.
568c5dff60aSchristos The result is a pointer to the insn's entry in the opcode table,
569c5dff60aSchristos or NULL if an error occured (an error message will have already been
570c5dff60aSchristos printed).
571c5dff60aSchristos
572c5dff60aSchristos Note that when processing (non-alias) macro-insns,
573c5dff60aSchristos this function recurses.
574c5dff60aSchristos
575c5dff60aSchristos ??? It's possible to make this cpu-independent.
576c5dff60aSchristos One would have to deal with a few minor things.
577c5dff60aSchristos At this point in time doing so would be more of a curiosity than useful
578c5dff60aSchristos [for example this file isn't _that_ big], but keeping the possibility in
579c5dff60aSchristos mind helps keep the design clean. */
580c5dff60aSchristos
581c5dff60aSchristos const CGEN_INSN *
xstormy16_cgen_assemble_insn(CGEN_CPU_DESC cd,const char * str,CGEN_FIELDS * fields,CGEN_INSN_BYTES_PTR buf,char ** errmsg)582c5dff60aSchristos xstormy16_cgen_assemble_insn (CGEN_CPU_DESC cd,
583c5dff60aSchristos const char *str,
584c5dff60aSchristos CGEN_FIELDS *fields,
585c5dff60aSchristos CGEN_INSN_BYTES_PTR buf,
586c5dff60aSchristos char **errmsg)
587c5dff60aSchristos {
588c5dff60aSchristos const char *start;
589c5dff60aSchristos CGEN_INSN_LIST *ilist;
590c5dff60aSchristos const char *parse_errmsg = NULL;
591c5dff60aSchristos const char *insert_errmsg = NULL;
592c5dff60aSchristos int recognized_mnemonic = 0;
593c5dff60aSchristos
594c5dff60aSchristos /* Skip leading white space. */
595c5dff60aSchristos while (ISSPACE (* str))
596c5dff60aSchristos ++ str;
597c5dff60aSchristos
598c5dff60aSchristos /* The instructions are stored in hashed lists.
599c5dff60aSchristos Get the first in the list. */
600c5dff60aSchristos ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
601c5dff60aSchristos
602c5dff60aSchristos /* Keep looking until we find a match. */
603c5dff60aSchristos start = str;
604c5dff60aSchristos for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
605c5dff60aSchristos {
606c5dff60aSchristos const CGEN_INSN *insn = ilist->insn;
607c5dff60aSchristos recognized_mnemonic = 1;
608c5dff60aSchristos
609c5dff60aSchristos #ifdef CGEN_VALIDATE_INSN_SUPPORTED
610c5dff60aSchristos /* Not usually needed as unsupported opcodes
611c5dff60aSchristos shouldn't be in the hash lists. */
612c5dff60aSchristos /* Is this insn supported by the selected cpu? */
613c5dff60aSchristos if (! xstormy16_cgen_insn_supported (cd, insn))
614c5dff60aSchristos continue;
615c5dff60aSchristos #endif
616c5dff60aSchristos /* If the RELAXED attribute is set, this is an insn that shouldn't be
617c5dff60aSchristos chosen immediately. Instead, it is used during assembler/linker
618c5dff60aSchristos relaxation if possible. */
619c5dff60aSchristos if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
620c5dff60aSchristos continue;
621c5dff60aSchristos
622c5dff60aSchristos str = start;
623c5dff60aSchristos
624c5dff60aSchristos /* Skip this insn if str doesn't look right lexically. */
625c5dff60aSchristos if (CGEN_INSN_RX (insn) != NULL &&
626c5dff60aSchristos regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
627c5dff60aSchristos continue;
628c5dff60aSchristos
629c5dff60aSchristos /* Allow parse/insert handlers to obtain length of insn. */
630c5dff60aSchristos CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
631c5dff60aSchristos
632c5dff60aSchristos parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
633c5dff60aSchristos if (parse_errmsg != NULL)
634c5dff60aSchristos continue;
635c5dff60aSchristos
636c5dff60aSchristos /* ??? 0 is passed for `pc'. */
637c5dff60aSchristos insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
638c5dff60aSchristos (bfd_vma) 0);
639c5dff60aSchristos if (insert_errmsg != NULL)
640c5dff60aSchristos continue;
641c5dff60aSchristos
642c5dff60aSchristos /* It is up to the caller to actually output the insn and any
643c5dff60aSchristos queued relocs. */
644c5dff60aSchristos return insn;
645c5dff60aSchristos }
646c5dff60aSchristos
647c5dff60aSchristos {
648c5dff60aSchristos static char errbuf[150];
649c5dff60aSchristos const char *tmp_errmsg;
650c5dff60aSchristos #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
651c5dff60aSchristos #define be_verbose 1
652c5dff60aSchristos #else
653c5dff60aSchristos #define be_verbose 0
654c5dff60aSchristos #endif
655c5dff60aSchristos
656c5dff60aSchristos if (be_verbose)
657c5dff60aSchristos {
658c5dff60aSchristos /* If requesting verbose error messages, use insert_errmsg.
659c5dff60aSchristos Failing that, use parse_errmsg. */
660c5dff60aSchristos tmp_errmsg = (insert_errmsg ? insert_errmsg :
661c5dff60aSchristos parse_errmsg ? parse_errmsg :
662c5dff60aSchristos recognized_mnemonic ?
663c5dff60aSchristos _("unrecognized form of instruction") :
664c5dff60aSchristos _("unrecognized instruction"));
665c5dff60aSchristos
666c5dff60aSchristos if (strlen (start) > 50)
667c5dff60aSchristos /* xgettext:c-format */
668c5dff60aSchristos sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
669c5dff60aSchristos else
670c5dff60aSchristos /* xgettext:c-format */
671c5dff60aSchristos sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
672c5dff60aSchristos }
673c5dff60aSchristos else
674c5dff60aSchristos {
675c5dff60aSchristos if (strlen (start) > 50)
676c5dff60aSchristos /* xgettext:c-format */
677c5dff60aSchristos sprintf (errbuf, _("bad instruction `%.50s...'"), start);
678c5dff60aSchristos else
679c5dff60aSchristos /* xgettext:c-format */
680c5dff60aSchristos sprintf (errbuf, _("bad instruction `%.50s'"), start);
681c5dff60aSchristos }
682c5dff60aSchristos
683c5dff60aSchristos *errmsg = errbuf;
684c5dff60aSchristos return NULL;
685c5dff60aSchristos }
686c5dff60aSchristos }
687