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