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