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