OSDN Git Service

* cgen-ibld.in (extract_normal): Match type of VALUE and MASK
[pf3gnuchains/pf3gnuchains3x.git] / opcodes / m32r-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 <ctype.h>
30 #include <stdio.h>
31 #include "ansidecl.h"
32 #include "bfd.h"
33 #include "symcat.h"
34 #include "m32r-desc.h"
35 #include "m32r-opc.h"
36 #include "opintl.h"
37 #include "xregex.h"
38
39 #undef min
40 #define min(a,b) ((a) < (b) ? (a) : (b))
41 #undef max
42 #define max(a,b) ((a) > (b) ? (a) : (b))
43
44 static const char * parse_insn_normal
45      PARAMS ((CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *));
46 \f
47 /* -- assembler routines inserted here */
48
49 /* -- asm.c */
50
51 /* Handle '#' prefixes (i.e. skip over them).  */
52
53 static const char *
54 parse_hash (cd, strp, opindex, valuep)
55      CGEN_CPU_DESC cd;
56      const char **strp;
57      int opindex;
58      unsigned long *valuep;
59 {
60   if (**strp == '#')
61     ++*strp;
62   return NULL;
63 }
64
65 /* Handle shigh(), high().  */
66
67 static const char *
68 parse_hi16 (cd, strp, opindex, valuep)
69      CGEN_CPU_DESC cd;
70      const char **strp;
71      int opindex;
72      unsigned long *valuep;
73 {
74   const char *errmsg;
75   enum cgen_parse_operand_result result_type;
76   bfd_vma value;
77
78   if (**strp == '#')
79     ++*strp;
80
81   if (strncasecmp (*strp, "high(", 5) == 0)
82     {
83       *strp += 5;
84       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_HI16_ULO,
85                                    &result_type, &value);
86       if (**strp != ')')
87         return "missing `)'";
88       ++*strp;
89       if (errmsg == NULL
90           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
91         value >>= 16;
92       *valuep = value;
93       return errmsg;
94     }
95   else if (strncasecmp (*strp, "shigh(", 6) == 0)
96     {
97       *strp += 6;
98       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_HI16_SLO,
99                                    &result_type, &value);
100       if (**strp != ')')
101         return "missing `)'";
102       ++*strp;
103       if (errmsg == NULL
104           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
105         value = (value >> 16) + (value & 0x8000 ? 1 : 0);
106       *valuep = value;
107       return errmsg;
108     }
109
110   return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
111 }
112
113 /* Handle low() in a signed context.  Also handle sda().
114    The signedness of the value doesn't matter to low(), but this also
115    handles the case where low() isn't present.  */
116
117 static const char *
118 parse_slo16 (cd, strp, opindex, valuep)
119      CGEN_CPU_DESC cd;
120      const char **strp;
121      int opindex;
122      long *valuep;
123 {
124   const char *errmsg;
125   enum cgen_parse_operand_result result_type;
126   bfd_vma value;
127
128   if (**strp == '#')
129     ++*strp;
130
131   if (strncasecmp (*strp, "low(", 4) == 0)
132     {
133       *strp += 4;
134       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_LO16,
135                                    &result_type, &value);
136       if (**strp != ')')
137         return "missing `)'";
138       ++*strp;
139       if (errmsg == NULL
140           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
141         value &= 0xffff;
142       *valuep = value;
143       return errmsg;
144     }
145
146   if (strncasecmp (*strp, "sda(", 4) == 0)
147     {
148       *strp += 4;
149       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_SDA16,
150                                    NULL, &value);
151       if (**strp != ')')
152         return "missing `)'";
153       ++*strp;
154       *valuep = value;
155       return errmsg;
156     }
157
158   return cgen_parse_signed_integer (cd, strp, opindex, valuep);
159 }
160
161 /* Handle low() in an unsigned context.
162    The signedness of the value doesn't matter to low(), but this also
163    handles the case where low() isn't present.  */
164
165 static const char *
166 parse_ulo16 (cd, strp, opindex, valuep)
167      CGEN_CPU_DESC cd;
168      const char **strp;
169      int opindex;
170      unsigned long *valuep;
171 {
172   const char *errmsg;
173   enum cgen_parse_operand_result result_type;
174   bfd_vma value;
175
176   if (**strp == '#')
177     ++*strp;
178
179   if (strncasecmp (*strp, "low(", 4) == 0)
180     {
181       *strp += 4;
182       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_LO16,
183                                    &result_type, &value);
184       if (**strp != ')')
185         return "missing `)'";
186       ++*strp;
187       if (errmsg == NULL
188           && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
189         value &= 0xffff;
190       *valuep = value;
191       return errmsg;
192     }
193
194   return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
195 }
196
197 /* -- */
198
199 /* Main entry point for operand parsing.
200
201    This function is basically just a big switch statement.  Earlier versions
202    used tables to look up the function to use, but
203    - if the table contains both assembler and disassembler functions then
204      the disassembler contains much of the assembler and vice-versa,
205    - there's a lot of inlining possibilities as things grow,
206    - using a switch statement avoids the function call overhead.
207
208    This function could be moved into `parse_insn_normal', but keeping it
209    separate makes clear the interface between `parse_insn_normal' and each of
210    the handlers.
211 */
212
213 const char *
214 m32r_cgen_parse_operand (cd, opindex, strp, fields)
215      CGEN_CPU_DESC cd;
216      int opindex;
217      const char ** strp;
218      CGEN_FIELDS * fields;
219 {
220   const char * errmsg = NULL;
221   /* Used by scalar operands that still need to be parsed.  */
222   long junk;
223
224   switch (opindex)
225     {
226     case M32R_OPERAND_ACC :
227       errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_h_accums, & fields->f_acc);
228       break;
229     case M32R_OPERAND_ACCD :
230       errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_h_accums, & fields->f_accd);
231       break;
232     case M32R_OPERAND_ACCS :
233       errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_h_accums, & fields->f_accs);
234       break;
235     case M32R_OPERAND_DCR :
236       errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_cr_names, & fields->f_r1);
237       break;
238     case M32R_OPERAND_DISP16 :
239       {
240         bfd_vma value;
241         errmsg = cgen_parse_address (cd, strp, M32R_OPERAND_DISP16, 0, NULL,  & value);
242         fields->f_disp16 = value;
243       }
244       break;
245     case M32R_OPERAND_DISP24 :
246       {
247         bfd_vma value;
248         errmsg = cgen_parse_address (cd, strp, M32R_OPERAND_DISP24, 0, NULL,  & value);
249         fields->f_disp24 = value;
250       }
251       break;
252     case M32R_OPERAND_DISP8 :
253       {
254         bfd_vma value;
255         errmsg = cgen_parse_address (cd, strp, M32R_OPERAND_DISP8, 0, NULL,  & value);
256         fields->f_disp8 = value;
257       }
258       break;
259     case M32R_OPERAND_DR :
260       errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_gr_names, & fields->f_r1);
261       break;
262     case M32R_OPERAND_HASH :
263       errmsg = parse_hash (cd, strp, M32R_OPERAND_HASH, &junk);
264       break;
265     case M32R_OPERAND_HI16 :
266       errmsg = parse_hi16 (cd, strp, M32R_OPERAND_HI16, &fields->f_hi16);
267       break;
268     case M32R_OPERAND_IMM1 :
269       errmsg = cgen_parse_unsigned_integer (cd, strp, M32R_OPERAND_IMM1, &fields->f_imm1);
270       break;
271     case M32R_OPERAND_SCR :
272       errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_cr_names, & fields->f_r2);
273       break;
274     case M32R_OPERAND_SIMM16 :
275       errmsg = cgen_parse_signed_integer (cd, strp, M32R_OPERAND_SIMM16, &fields->f_simm16);
276       break;
277     case M32R_OPERAND_SIMM8 :
278       errmsg = cgen_parse_signed_integer (cd, strp, M32R_OPERAND_SIMM8, &fields->f_simm8);
279       break;
280     case M32R_OPERAND_SLO16 :
281       errmsg = parse_slo16 (cd, strp, M32R_OPERAND_SLO16, &fields->f_simm16);
282       break;
283     case M32R_OPERAND_SR :
284       errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_gr_names, & fields->f_r2);
285       break;
286     case M32R_OPERAND_SRC1 :
287       errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_gr_names, & fields->f_r1);
288       break;
289     case M32R_OPERAND_SRC2 :
290       errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_gr_names, & fields->f_r2);
291       break;
292     case M32R_OPERAND_UIMM16 :
293       errmsg = cgen_parse_unsigned_integer (cd, strp, M32R_OPERAND_UIMM16, &fields->f_uimm16);
294       break;
295     case M32R_OPERAND_UIMM24 :
296       {
297         bfd_vma value;
298         errmsg = cgen_parse_address (cd, strp, M32R_OPERAND_UIMM24, 0, NULL,  & value);
299         fields->f_uimm24 = value;
300       }
301       break;
302     case M32R_OPERAND_UIMM4 :
303       errmsg = cgen_parse_unsigned_integer (cd, strp, M32R_OPERAND_UIMM4, &fields->f_uimm4);
304       break;
305     case M32R_OPERAND_UIMM5 :
306       errmsg = cgen_parse_unsigned_integer (cd, strp, M32R_OPERAND_UIMM5, &fields->f_uimm5);
307       break;
308     case M32R_OPERAND_ULO16 :
309       errmsg = parse_ulo16 (cd, strp, M32R_OPERAND_ULO16, &fields->f_uimm16);
310       break;
311
312     default :
313       /* xgettext:c-format */
314       fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
315       abort ();
316   }
317
318   return errmsg;
319 }
320
321 cgen_parse_fn * const m32r_cgen_parse_handlers[] = 
322 {
323   parse_insn_normal,
324 };
325
326 void
327 m32r_cgen_init_asm (cd)
328      CGEN_CPU_DESC cd;
329 {
330   m32r_cgen_init_opcode_table (cd);
331   m32r_cgen_init_ibld_table (cd);
332   cd->parse_handlers = & m32r_cgen_parse_handlers[0];
333   cd->parse_operand = m32r_cgen_parse_operand;
334 }
335
336 \f
337
338 /*
339   Regex construction routine.
340
341   This translates an opcode syntax string into a regex string,
342   by replacing any non-character syntax element (such as an
343   opcode) with the pattern '.*'
344
345   It then compiles the regex and stores it in the opcode, for
346   later use by m32r_cgen_assemble_insn
347
348   returns NULL for success, an error message for failure 
349 */
350
351 char * 
352 m32r_cgen_build_insn_regex (insn)
353      CGEN_INSN *insn;
354 {  
355   CGEN_OPCODE *opc = CGEN_INSN_OPCODE (insn);
356   const char *mnem = CGEN_INSN_MNEMONIC (insn);
357   int mnem_len;
358   char rxbuf[CGEN_MAX_RX_ELEMENTS];
359   char *rx = rxbuf;
360   const CGEN_SYNTAX_CHAR_TYPE *syn;
361   int reg_err;
362
363   syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
364
365   /* Mnemonics come first in the syntax string  */
366   if (! CGEN_SYNTAX_MNEMONIC_P (* syn)) return "missing mnemonic in syntax string";
367   ++syn;
368
369   /* copy the literal mnemonic out of the insn */
370   memset (rx, 0, CGEN_MAX_RX_ELEMENTS);
371   mnem_len = strlen(mnem);
372   memcpy (rx, mnem, mnem_len);
373   rx += mnem_len;
374
375   /* copy any remaining literals from the syntax string into the rx */
376   for(; * syn != 0 && rx < rxbuf + (CGEN_MAX_RX_ELEMENTS - 9); ++syn, ++rx) 
377     {
378       if (CGEN_SYNTAX_CHAR_P (* syn)) 
379         {
380          char tmp = CGEN_SYNTAX_CHAR (* syn);
381          switch (tmp) 
382            {
383              /* escape any regex metacharacters in the syntax */
384            case '.': case '[': case '\\': 
385            case '*': case '^': case '$': 
386
387 #ifdef CGEN_ESCAPE_EXTENDED_REGEX
388            case '?': case '{': case '}': 
389            case '(': case ')': case '*':
390            case '|': case '+': case ']':
391 #endif
392
393              * rx++ = '\\';
394              break;  
395            }
396          /* insert syntax char into rx */
397         * rx = tmp;
398         }
399       else
400         {
401           /* replace non-syntax fields with globs */
402           * rx = '.';
403           * ++rx = '*';
404         }
405     }
406
407   /* trailing whitespace ok */
408   * rx++ = '['; 
409   * rx++ = ' '; 
410   * rx++ = '\t'; 
411   * rx++ = ']'; 
412   * rx++ = '*'; 
413
414   /* but anchor it after that */
415   * rx++ = '$'; 
416   * rx = '\0';
417
418   CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
419   reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB|REG_ICASE);
420
421   if (reg_err == 0) 
422     return NULL;
423   else
424     {
425       static char msg[80];
426       regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
427       regfree ((regex_t *) CGEN_INSN_RX (insn));
428       free (CGEN_INSN_RX (insn));
429       (CGEN_INSN_RX (insn)) = NULL;
430     return msg;
431     }
432 }
433
434 \f
435 /* Default insn parser.
436
437    The syntax string is scanned and operands are parsed and stored in FIELDS.
438    Relocs are queued as we go via other callbacks.
439
440    ??? Note that this is currently an all-or-nothing parser.  If we fail to
441    parse the instruction, we return 0 and the caller will start over from
442    the beginning.  Backtracking will be necessary in parsing subexpressions,
443    but that can be handled there.  Not handling backtracking here may get
444    expensive in the case of the m68k.  Deal with later.
445
446    Returns NULL for success, an error message for failure.
447 */
448
449 static const char *
450 parse_insn_normal (cd, insn, strp, fields)
451      CGEN_CPU_DESC cd;
452      const CGEN_INSN *insn;
453      const char **strp;
454      CGEN_FIELDS *fields;
455 {
456   /* ??? Runtime added insns not handled yet.  */
457   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
458   const char *str = *strp;
459   const char *errmsg;
460   const char *p;
461   const CGEN_SYNTAX_CHAR_TYPE * syn;
462 #ifdef CGEN_MNEMONIC_OPERANDS
463   /* FIXME: wip */
464   int past_opcode_p;
465 #endif
466
467   /* For now we assume the mnemonic is first (there are no leading operands).
468      We can parse it without needing to set up operand parsing.
469      GAS's input scrubber will ensure mnemonics are lowercase, but we may
470      not be called from GAS.  */
471   p = CGEN_INSN_MNEMONIC (insn);
472   while (*p && tolower (*p) == tolower (*str))
473     ++p, ++str;
474
475   if (* p)
476     return _("unrecognized instruction");
477
478 #ifndef CGEN_MNEMONIC_OPERANDS
479   if (* str && !isspace (* str))
480     return _("unrecognized instruction");
481 #endif
482
483   CGEN_INIT_PARSE (cd);
484   cgen_init_parse_operand (cd);
485 #ifdef CGEN_MNEMONIC_OPERANDS
486   past_opcode_p = 0;
487 #endif
488
489   /* We don't check for (*str != '\0') here because we want to parse
490      any trailing fake arguments in the syntax string.  */
491   syn = CGEN_SYNTAX_STRING (syntax);
492
493   /* Mnemonics come first for now, ensure valid string.  */
494   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
495     abort ();
496
497   ++syn;
498
499   while (* syn != 0)
500     {
501       /* Non operand chars must match exactly.  */
502       if (CGEN_SYNTAX_CHAR_P (* syn))
503         {
504           /* FIXME: While we allow for non-GAS callers above, we assume the
505              first char after the mnemonic part is a space.  */
506           /* FIXME: We also take inappropriate advantage of the fact that
507              GAS's input scrubber will remove extraneous blanks.  */
508           if (tolower (*str) == tolower (CGEN_SYNTAX_CHAR (* syn)))
509             {
510 #ifdef CGEN_MNEMONIC_OPERANDS
511               if (CGEN_SYNTAX_CHAR(* syn) == ' ')
512                 past_opcode_p = 1;
513 #endif
514               ++ syn;
515               ++ str;
516             }
517           else if (*str)
518             {
519               /* Syntax char didn't match.  Can't be this insn.  */
520               static char msg [80];
521               /* xgettext:c-format */
522               sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
523                        CGEN_SYNTAX_CHAR(*syn), *str);
524               return msg;
525             }
526           else
527             {
528               /* Ran out of input.  */
529               static char msg [80];
530               /* xgettext:c-format */
531               sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
532                        CGEN_SYNTAX_CHAR(*syn));
533               return msg;
534             }
535           continue;
536         }
537
538       /* We have an operand of some sort.  */
539       errmsg = m32r_cgen_parse_operand (cd, CGEN_SYNTAX_FIELD (*syn),
540                                           &str, fields);
541       if (errmsg)
542         return errmsg;
543
544       /* Done with this operand, continue with next one.  */
545       ++ syn;
546     }
547
548   /* If we're at the end of the syntax string, we're done.  */
549   if (* syn == 0)
550     {
551       /* FIXME: For the moment we assume a valid `str' can only contain
552          blanks now.  IE: We needn't try again with a longer version of
553          the insn and it is assumed that longer versions of insns appear
554          before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
555       while (isspace (* str))
556         ++ str;
557
558       if (* str != '\0')
559         return _("junk at end of line"); /* FIXME: would like to include `str' */
560
561       return NULL;
562     }
563
564   /* We couldn't parse it.  */
565   return _("unrecognized instruction");
566 }
567 \f
568 /* Main entry point.
569    This routine is called for each instruction to be assembled.
570    STR points to the insn to be assembled.
571    We assume all necessary tables have been initialized.
572    The assembled instruction, less any fixups, is stored in BUF.
573    Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
574    still needs to be converted to target byte order, otherwise BUF is an array
575    of bytes in target byte order.
576    The result is a pointer to the insn's entry in the opcode table,
577    or NULL if an error occured (an error message will have already been
578    printed).
579
580    Note that when processing (non-alias) macro-insns,
581    this function recurses.
582
583    ??? It's possible to make this cpu-independent.
584    One would have to deal with a few minor things.
585    At this point in time doing so would be more of a curiosity than useful
586    [for example this file isn't _that_ big], but keeping the possibility in
587    mind helps keep the design clean.  */
588
589 const CGEN_INSN *
590 m32r_cgen_assemble_insn (cd, str, fields, buf, errmsg)
591      CGEN_CPU_DESC cd;
592      const char *str;
593      CGEN_FIELDS *fields;
594      CGEN_INSN_BYTES_PTR buf;
595      char **errmsg;
596 {
597   const char *start;
598   CGEN_INSN_LIST *ilist;
599   const char *parse_errmsg = NULL;
600   const char *insert_errmsg = NULL;
601   int recognized_mnemonic = 0;
602
603   /* Skip leading white space.  */
604   while (isspace (* str))
605     ++ str;
606
607   /* The instructions are stored in hashed lists.
608      Get the first in the list.  */
609   ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
610
611   /* Keep looking until we find a match.  */
612
613   start = str;
614   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
615     {
616       const CGEN_INSN *insn = ilist->insn;
617       recognized_mnemonic = 1;
618
619 #ifdef CGEN_VALIDATE_INSN_SUPPORTED 
620       /* not usually needed as unsupported opcodes shouldn't be in the hash lists */
621       /* Is this insn supported by the selected cpu?  */
622       if (! m32r_cgen_insn_supported (cd, insn))
623         continue;
624 #endif
625
626       /* If the RELAX attribute is set, this is an insn that shouldn't be
627          chosen immediately.  Instead, it is used during assembler/linker
628          relaxation if possible.  */
629       if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAX) != 0)
630         continue;
631
632       str = start;
633
634       /* skip this insn if str doesn't look right lexically */
635       if (CGEN_INSN_RX (insn) != NULL &&
636           regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
637         continue;
638
639       /* Allow parse/insert handlers to obtain length of insn.  */
640       CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
641
642       parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
643       if (parse_errmsg != NULL)
644         continue;
645
646       /* ??? 0 is passed for `pc' */
647       insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
648                                                  (bfd_vma) 0);
649       if (insert_errmsg != NULL)
650         continue;
651
652       /* It is up to the caller to actually output the insn and any
653          queued relocs.  */
654       return insn;
655     }
656
657   {
658     static char errbuf[150];
659 #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
660     const char *tmp_errmsg;
661
662     /* If requesting verbose error messages, use insert_errmsg.
663        Failing that, use parse_errmsg */
664     tmp_errmsg = (insert_errmsg ? insert_errmsg :
665                   parse_errmsg ? parse_errmsg :
666                   recognized_mnemonic ? _("unrecognized form of instruction") :
667                   _("unrecognized instruction"));
668
669     if (strlen (start) > 50)
670       /* xgettext:c-format */
671       sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
672     else 
673       /* xgettext:c-format */
674       sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
675 #else
676     if (strlen (start) > 50)
677       /* xgettext:c-format */
678       sprintf (errbuf, _("bad instruction `%.50s...'"), start);
679     else 
680       /* xgettext:c-format */
681       sprintf (errbuf, _("bad instruction `%.50s'"), start);
682 #endif
683       
684     *errmsg = errbuf;
685     return NULL;
686   }
687 }
688 \f
689 #if 0 /* This calls back to GAS which we can't do without care.  */
690
691 /* Record each member of OPVALS in the assembler's symbol table.
692    This lets GAS parse registers for us.
693    ??? Interesting idea but not currently used.  */
694
695 /* Record each member of OPVALS in the assembler's symbol table.
696    FIXME: Not currently used.  */
697
698 void
699 m32r_cgen_asm_hash_keywords (cd, opvals)
700      CGEN_CPU_DESC cd;
701      CGEN_KEYWORD *opvals;
702 {
703   CGEN_KEYWORD_SEARCH search = cgen_keyword_search_init (opvals, NULL);
704   const CGEN_KEYWORD_ENTRY * ke;
705
706   while ((ke = cgen_keyword_search_next (& search)) != NULL)
707     {
708 #if 0 /* Unnecessary, should be done in the search routine.  */
709       if (! m32r_cgen_opval_supported (ke))
710         continue;
711 #endif
712       cgen_asm_record_register (cd, ke->name, ke->value);
713     }
714 }
715
716 #endif /* 0 */