* xstormy16-asm.c: Regenerate.
[platform/upstream/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      PARAMS ((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
56 /* The machine-independent code doesn't know how to disambiguate
57      mov (foo),r3
58    and
59      mov (r2),r3
60    where 'foo' is a label.  This helps it out. */
61
62 static const char *
63 parse_mem8 (cd, strp, opindex, valuep)
64      CGEN_CPU_DESC cd;
65      const char **strp;
66      int opindex;
67      unsigned long *valuep;
68 {
69   if (**strp == '(')
70     {
71       const char *s = *strp;
72       
73       if (s[1] == '-' && s[2] == '-')
74         return _("Bad register in preincrement");
75
76       while (ISALNUM (*++s))
77         ;
78       if (s[0] == '+' && s[1] == '+' && (s[2] == ')' || s[2] == ','))
79         return _("Bad register in postincrement");
80       if (s[0] == ',' || s[0] == ')')
81         return _("Bad register name");
82     }
83   else if (cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_gr_names, 
84                                valuep) == NULL)
85     return _("Label conflicts with register name");
86   else if (strncasecmp (*strp, "rx,", 3) == 0
87            || strncasecmp (*strp, "rxl,", 3) == 0
88            || strncasecmp (*strp, "rxh,", 3) == 0)
89     return _("Label conflicts with `Rx'");
90   else if (**strp == '#')
91     return _("Bad immediate expression");
92   
93   return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
94 }
95
96 /* For the add and subtract instructions, there are two immediate forms,
97    one for small operands and one for large ones.  We want to use
98    the small one when possible, but we do not want to generate relocs
99    of the small size.  This is somewhat tricky.  */
100    
101 static const char *
102 parse_small_immediate (cd, strp, opindex, valuep)
103      CGEN_CPU_DESC cd;
104      const char **strp;
105      int opindex;
106      unsigned long *valuep;
107 {
108   bfd_vma value;
109   enum cgen_parse_operand_result result;
110   const char *errmsg;
111
112   if (**strp == '@')
113     return _("No relocation for small immediate");
114
115   errmsg = (* cd->parse_operand_fn)
116     (cd, CGEN_PARSE_OPERAND_INTEGER, strp, opindex, BFD_RELOC_NONE,
117      &result, &value);
118   
119   if (errmsg)
120     return errmsg;
121
122   if (result != CGEN_PARSE_OPERAND_RESULT_NUMBER)
123     return _("Small operand was not an immediate number");
124
125   *valuep = value;
126   return NULL;
127 }
128
129 /* Literal scan be either a normal literal, a @hi() or @lo relocation. */
130    
131 static const char *
132 parse_immediate16 (cd, strp, opindex, valuep)
133      CGEN_CPU_DESC cd;
134      const char **strp;
135      int opindex;
136      unsigned long *valuep;
137 {
138   const char *errmsg;
139   enum cgen_parse_operand_result result;
140   bfd_reloc_code_real_type code = BFD_RELOC_NONE;
141   bfd_vma value;
142
143   if (strncmp (*strp, "@hi(", 4) == 0)
144     {
145       *strp += 4;
146       code = BFD_RELOC_HI16;
147     }
148   else
149   if (strncmp (*strp, "@lo(", 4) == 0)
150     {
151       *strp += 4;
152       code = BFD_RELOC_LO16;
153     }
154
155   if (code == BFD_RELOC_NONE)
156     errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
157   else
158     {
159       errmsg = cgen_parse_address (cd, strp, opindex, code, &result, &value);
160       if ((errmsg == NULL) &&
161           (result != CGEN_PARSE_OPERAND_RESULT_QUEUED))
162         errmsg = _("Operand is not a symbol");
163
164       *valuep = value;
165       if ((code == BFD_RELOC_HI16 || code == BFD_RELOC_LO16)
166           && **strp == ')')        
167         *strp += 1;
168       else
169         {
170           errmsg = _("Syntax error: No trailing ')'");
171           return errmsg;
172         }
173     }
174   return errmsg;
175 }
176 /* -- */
177
178 const char * xstormy16_cgen_parse_operand
179   PARAMS ((CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *));
180
181 /* Main entry point for operand parsing.
182
183    This function is basically just a big switch statement.  Earlier versions
184    used tables to look up the function to use, but
185    - if the table contains both assembler and disassembler functions then
186      the disassembler contains much of the assembler and vice-versa,
187    - there's a lot of inlining possibilities as things grow,
188    - using a switch statement avoids the function call overhead.
189
190    This function could be moved into `parse_insn_normal', but keeping it
191    separate makes clear the interface between `parse_insn_normal' and each of
192    the handlers.  */
193
194 const char *
195 xstormy16_cgen_parse_operand (cd, opindex, strp, fields)
196      CGEN_CPU_DESC cd;
197      int opindex;
198      const char ** strp;
199      CGEN_FIELDS * fields;
200 {
201   const char * errmsg = NULL;
202   /* Used by scalar operands that still need to be parsed.  */
203   long junk ATTRIBUTE_UNUSED;
204
205   switch (opindex)
206     {
207     case XSTORMY16_OPERAND_RB :
208       errmsg = cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_gr_Rb_names, & fields->f_Rb);
209       break;
210     case XSTORMY16_OPERAND_RBJ :
211       errmsg = cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_gr_Rb_names, & fields->f_Rbj);
212       break;
213     case XSTORMY16_OPERAND_RD :
214       errmsg = cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_gr_names, & fields->f_Rd);
215       break;
216     case XSTORMY16_OPERAND_RDM :
217       errmsg = cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_gr_names, & fields->f_Rdm);
218       break;
219     case XSTORMY16_OPERAND_RM :
220       errmsg = cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_gr_names, & fields->f_Rm);
221       break;
222     case XSTORMY16_OPERAND_RS :
223       errmsg = cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_gr_names, & fields->f_Rs);
224       break;
225     case XSTORMY16_OPERAND_ABS24 :
226       errmsg = cgen_parse_unsigned_integer (cd, strp, XSTORMY16_OPERAND_ABS24, &fields->f_abs24);
227       break;
228     case XSTORMY16_OPERAND_BCOND2 :
229       errmsg = cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_h_branchcond, & fields->f_op2);
230       break;
231     case XSTORMY16_OPERAND_BCOND5 :
232       errmsg = cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_h_branchcond, & fields->f_op5);
233       break;
234     case XSTORMY16_OPERAND_HMEM8 :
235       errmsg = parse_mem8 (cd, strp, XSTORMY16_OPERAND_HMEM8, &fields->f_hmem8);
236       break;
237     case XSTORMY16_OPERAND_IMM12 :
238       errmsg = cgen_parse_signed_integer (cd, strp, XSTORMY16_OPERAND_IMM12, &fields->f_imm12);
239       break;
240     case XSTORMY16_OPERAND_IMM16 :
241       errmsg = parse_immediate16 (cd, strp, XSTORMY16_OPERAND_IMM16, &fields->f_imm16);
242       break;
243     case XSTORMY16_OPERAND_IMM2 :
244       errmsg = cgen_parse_unsigned_integer (cd, strp, XSTORMY16_OPERAND_IMM2, &fields->f_imm2);
245       break;
246     case XSTORMY16_OPERAND_IMM3 :
247       errmsg = cgen_parse_unsigned_integer (cd, strp, XSTORMY16_OPERAND_IMM3, &fields->f_imm3);
248       break;
249     case XSTORMY16_OPERAND_IMM3B :
250       errmsg = cgen_parse_unsigned_integer (cd, strp, XSTORMY16_OPERAND_IMM3B, &fields->f_imm3b);
251       break;
252     case XSTORMY16_OPERAND_IMM4 :
253       errmsg = parse_small_immediate (cd, strp, XSTORMY16_OPERAND_IMM4, &fields->f_imm4);
254       break;
255     case XSTORMY16_OPERAND_IMM8 :
256       errmsg = cgen_parse_unsigned_integer (cd, strp, XSTORMY16_OPERAND_IMM8, &fields->f_imm8);
257       break;
258     case XSTORMY16_OPERAND_IMM8SMALL :
259       errmsg = parse_small_immediate (cd, strp, XSTORMY16_OPERAND_IMM8SMALL, &fields->f_imm8);
260       break;
261     case XSTORMY16_OPERAND_LMEM8 :
262       errmsg = parse_mem8 (cd, strp, XSTORMY16_OPERAND_LMEM8, &fields->f_lmem8);
263       break;
264     case XSTORMY16_OPERAND_REL12 :
265       errmsg = cgen_parse_unsigned_integer (cd, strp, XSTORMY16_OPERAND_REL12, &fields->f_rel12);
266       break;
267     case XSTORMY16_OPERAND_REL12A :
268       errmsg = cgen_parse_unsigned_integer (cd, strp, XSTORMY16_OPERAND_REL12A, &fields->f_rel12a);
269       break;
270     case XSTORMY16_OPERAND_REL8_2 :
271       errmsg = cgen_parse_unsigned_integer (cd, strp, XSTORMY16_OPERAND_REL8_2, &fields->f_rel8_2);
272       break;
273     case XSTORMY16_OPERAND_REL8_4 :
274       errmsg = cgen_parse_unsigned_integer (cd, strp, XSTORMY16_OPERAND_REL8_4, &fields->f_rel8_4);
275       break;
276     case XSTORMY16_OPERAND_WS2 :
277       errmsg = cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_h_wordsize, & fields->f_op2m);
278       break;
279
280     default :
281       /* xgettext:c-format */
282       fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
283       abort ();
284   }
285
286   return errmsg;
287 }
288
289 cgen_parse_fn * const xstormy16_cgen_parse_handlers[] = 
290 {
291   parse_insn_normal,
292 };
293
294 void
295 xstormy16_cgen_init_asm (cd)
296      CGEN_CPU_DESC cd;
297 {
298   xstormy16_cgen_init_opcode_table (cd);
299   xstormy16_cgen_init_ibld_table (cd);
300   cd->parse_handlers = & xstormy16_cgen_parse_handlers[0];
301   cd->parse_operand = xstormy16_cgen_parse_operand;
302 }
303
304 \f
305
306 /* Regex construction routine.
307
308    This translates an opcode syntax string into a regex string,
309    by replacing any non-character syntax element (such as an
310    opcode) with the pattern '.*'
311
312    It then compiles the regex and stores it in the opcode, for
313    later use by xstormy16_cgen_assemble_insn
314
315    Returns NULL for success, an error message for failure.  */
316
317 char * 
318 xstormy16_cgen_build_insn_regex (insn)
319      CGEN_INSN *insn;
320 {  
321   CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
322   const char *mnem = CGEN_INSN_MNEMONIC (insn);
323   char rxbuf[CGEN_MAX_RX_ELEMENTS];
324   char *rx = rxbuf;
325   const CGEN_SYNTAX_CHAR_TYPE *syn;
326   int reg_err;
327
328   syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
329
330   /* Mnemonics come first in the syntax string.  */
331   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
332     return _("missing mnemonic in syntax string");
333   ++syn;
334
335   /* Generate a case sensitive regular expression that emulates case
336      insensitive matching in the "C" locale.  We cannot generate a case
337      insensitive regular expression because in Turkish locales, 'i' and 'I'
338      are not equal modulo case conversion.  */
339
340   /* Copy the literal mnemonic out of the insn.  */
341   for (; *mnem; mnem++)
342     {
343       char c = *mnem;
344
345       if (ISALPHA (c))
346         {
347           *rx++ = '[';
348           *rx++ = TOLOWER (c);
349           *rx++ = TOUPPER (c);
350           *rx++ = ']';
351         }
352       else
353         *rx++ = c;
354     }
355
356   /* Copy any remaining literals from the syntax string into the rx.  */
357   for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
358     {
359       if (CGEN_SYNTAX_CHAR_P (* syn)) 
360         {
361           char c = CGEN_SYNTAX_CHAR (* syn);
362
363           switch (c) 
364             {
365               /* Escape any regex metacharacters in the syntax.  */
366             case '.': case '[': case '\\': 
367             case '*': case '^': case '$': 
368
369 #ifdef CGEN_ESCAPE_EXTENDED_REGEX
370             case '?': case '{': case '}': 
371             case '(': case ')': case '*':
372             case '|': case '+': case ']':
373 #endif
374               *rx++ = '\\';
375               *rx++ = c;
376               break;
377
378             default:
379               if (ISALPHA (c))
380                 {
381                   *rx++ = '[';
382                   *rx++ = TOLOWER (c);
383                   *rx++ = TOUPPER (c);
384                   *rx++ = ']';
385                 }
386               else
387                 *rx++ = c;
388               break;
389             }
390         }
391       else
392         {
393           /* Replace non-syntax fields with globs.  */
394           *rx++ = '.';
395           *rx++ = '*';
396         }
397     }
398
399   /* Trailing whitespace ok.  */
400   * rx++ = '['; 
401   * rx++ = ' '; 
402   * rx++ = '\t'; 
403   * rx++ = ']'; 
404   * rx++ = '*'; 
405
406   /* But anchor it after that.  */
407   * rx++ = '$'; 
408   * rx = '\0';
409
410   CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
411   reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
412
413   if (reg_err == 0) 
414     return NULL;
415   else
416     {
417       static char msg[80];
418
419       regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
420       regfree ((regex_t *) CGEN_INSN_RX (insn));
421       free (CGEN_INSN_RX (insn));
422       (CGEN_INSN_RX (insn)) = NULL;
423       return msg;
424     }
425 }
426
427 \f
428 /* Default insn parser.
429
430    The syntax string is scanned and operands are parsed and stored in FIELDS.
431    Relocs are queued as we go via other callbacks.
432
433    ??? Note that this is currently an all-or-nothing parser.  If we fail to
434    parse the instruction, we return 0 and the caller will start over from
435    the beginning.  Backtracking will be necessary in parsing subexpressions,
436    but that can be handled there.  Not handling backtracking here may get
437    expensive in the case of the m68k.  Deal with later.
438
439    Returns NULL for success, an error message for failure.  */
440
441 static const char *
442 parse_insn_normal (cd, insn, strp, fields)
443      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 (cd, str, fields, buf, errmsg)
585      CGEN_CPU_DESC cd;
586      const char *str;
587      CGEN_FIELDS *fields;
588      CGEN_INSN_BYTES_PTR buf;
589      char **errmsg;
590 {
591   const char *start;
592   CGEN_INSN_LIST *ilist;
593   const char *parse_errmsg = NULL;
594   const char *insert_errmsg = NULL;
595   int recognized_mnemonic = 0;
596
597   /* Skip leading white space.  */
598   while (ISSPACE (* str))
599     ++ str;
600
601   /* The instructions are stored in hashed lists.
602      Get the first in the list.  */
603   ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
604
605   /* Keep looking until we find a match.  */
606   start = str;
607   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
608     {
609       const CGEN_INSN *insn = ilist->insn;
610       recognized_mnemonic = 1;
611
612 #ifdef CGEN_VALIDATE_INSN_SUPPORTED 
613       /* Not usually needed as unsupported opcodes
614          shouldn't be in the hash lists.  */
615       /* Is this insn supported by the selected cpu?  */
616       if (! xstormy16_cgen_insn_supported (cd, insn))
617         continue;
618 #endif
619       /* If the RELAX attribute is set, this is an insn that shouldn't be
620          chosen immediately.  Instead, it is used during assembler/linker
621          relaxation if possible.  */
622       if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAX) != 0)
623         continue;
624
625       str = start;
626
627       /* Skip this insn if str doesn't look right lexically.  */
628       if (CGEN_INSN_RX (insn) != NULL &&
629           regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
630         continue;
631
632       /* Allow parse/insert handlers to obtain length of insn.  */
633       CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
634
635       parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
636       if (parse_errmsg != NULL)
637         continue;
638
639       /* ??? 0 is passed for `pc'.  */
640       insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
641                                                  (bfd_vma) 0);
642       if (insert_errmsg != NULL)
643         continue;
644
645       /* It is up to the caller to actually output the insn and any
646          queued relocs.  */
647       return insn;
648     }
649
650   {
651     static char errbuf[150];
652 #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
653     const char *tmp_errmsg;
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 #else
670     if (strlen (start) > 50)
671       /* xgettext:c-format */
672       sprintf (errbuf, _("bad instruction `%.50s...'"), start);
673     else 
674       /* xgettext:c-format */
675       sprintf (errbuf, _("bad instruction `%.50s'"), start);
676 #endif
677       
678     *errmsg = errbuf;
679     return NULL;
680   }
681 }
682 \f
683 #if 0 /* This calls back to GAS which we can't do without care.  */
684
685 /* Record each member of OPVALS in the assembler's symbol table.
686    This lets GAS parse registers for us.
687    ??? Interesting idea but not currently used.  */
688
689 /* Record each member of OPVALS in the assembler's symbol table.
690    FIXME: Not currently used.  */
691
692 void
693 xstormy16_cgen_asm_hash_keywords (cd, opvals)
694      CGEN_CPU_DESC cd;
695      CGEN_KEYWORD *opvals;
696 {
697   CGEN_KEYWORD_SEARCH search = cgen_keyword_search_init (opvals, NULL);
698   const CGEN_KEYWORD_ENTRY * ke;
699
700   while ((ke = cgen_keyword_search_next (& search)) != NULL)
701     {
702 #if 0 /* Unnecessary, should be done in the search routine.  */
703       if (! xstormy16_cgen_opval_supported (ke))
704         continue;
705 #endif
706       cgen_asm_record_register (cd, ke->name, ke->value);
707     }
708 }
709
710 #endif /* 0 */