OSDN Git Service

* cgen-ibld.in (extract_normal): Match type of VALUE and MASK
[pf3gnuchains/pf3gnuchains3x.git] / opcodes / fr30-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 "fr30-desc.h"
35 #include "fr30-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 /* Handle register lists for LDMx and STMx  */
51
52 static int
53 parse_register_number (strp)
54      const char **strp;
55 {
56   int regno;
57   if (**strp < '0' || **strp > '9')
58     return -1; /* error */
59   regno = **strp - '0';
60   ++*strp;
61
62   if (**strp >= '0' && **strp <= '9')
63     {
64       regno = regno * 10 + (**strp - '0');
65       ++*strp;
66     }
67
68   return regno;
69 }
70
71 static const char *
72 parse_register_list (cd, strp, opindex, valuep, high_low, load_store)
73      CGEN_CPU_DESC cd;
74      const char **strp;
75      int opindex;
76      unsigned long *valuep;
77      int high_low;   /* 0 == high, 1 == low */
78      int load_store; /* 0 == load, 1 == store */
79 {
80   int regno;
81   *valuep = 0;
82   while (**strp && **strp != ')')
83     {
84       if (**strp != 'R' && **strp != 'r')
85         break;
86       ++*strp;
87
88       regno = parse_register_number (strp);
89       if (regno == -1)
90         return "Register number is not valid";
91       if (regno > 7 && !high_low)
92         return "Register must be between r0 and r7";
93       if (regno < 8 && high_low)
94         return "Register must be between r8 and r15";
95
96       if (high_low)
97         regno -= 8;
98
99       if (load_store) /* mask is reversed for store */
100         *valuep |= 0x80 >> regno;
101       else
102         *valuep |= 1 << regno;
103
104       if (**strp == ',')
105         {
106           if (*(*strp + 1) == ')')
107             break;
108           ++*strp;
109         }
110     }
111
112   if (!*strp || **strp != ')')
113     return "Register list is not valid";
114
115   return NULL;
116 }
117
118 static const char *
119 parse_low_register_list_ld (cd, strp, opindex, valuep)
120      CGEN_CPU_DESC cd;
121      const char **strp;
122      int opindex;
123      unsigned long *valuep;
124 {
125   return parse_register_list (cd, strp, opindex, valuep, 0/*low*/, 0/*load*/);
126 }
127
128 static const char *
129 parse_hi_register_list_ld (cd, strp, opindex, valuep)
130      CGEN_CPU_DESC cd;
131      const char **strp;
132      int opindex;
133      unsigned long *valuep;
134 {
135   return parse_register_list (cd, strp, opindex, valuep, 1/*high*/, 0/*load*/);
136 }
137
138 static const char *
139 parse_low_register_list_st (cd, strp, opindex, valuep)
140      CGEN_CPU_DESC cd;
141      const char **strp;
142      int opindex;
143      unsigned long *valuep;
144 {
145   return parse_register_list (cd, strp, opindex, valuep, 0/*low*/, 1/*store*/);
146 }
147
148 static const char *
149 parse_hi_register_list_st (cd, strp, opindex, valuep)
150      CGEN_CPU_DESC cd;
151      const char **strp;
152      int opindex;
153      unsigned long *valuep;
154 {
155   return parse_register_list (cd, strp, opindex, valuep, 1/*high*/, 1/*store*/);
156 }
157
158 /* -- */
159
160 /* Main entry point for operand parsing.
161
162    This function is basically just a big switch statement.  Earlier versions
163    used tables to look up the function to use, but
164    - if the table contains both assembler and disassembler functions then
165      the disassembler contains much of the assembler and vice-versa,
166    - there's a lot of inlining possibilities as things grow,
167    - using a switch statement avoids the function call overhead.
168
169    This function could be moved into `parse_insn_normal', but keeping it
170    separate makes clear the interface between `parse_insn_normal' and each of
171    the handlers.
172 */
173
174 const char *
175 fr30_cgen_parse_operand (cd, opindex, strp, fields)
176      CGEN_CPU_DESC cd;
177      int opindex;
178      const char ** strp;
179      CGEN_FIELDS * fields;
180 {
181   const char * errmsg = NULL;
182   /* Used by scalar operands that still need to be parsed.  */
183   long junk;
184
185   switch (opindex)
186     {
187     case FR30_OPERAND_CRI :
188       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_cr_names, & fields->f_CRi);
189       break;
190     case FR30_OPERAND_CRJ :
191       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_cr_names, & fields->f_CRj);
192       break;
193     case FR30_OPERAND_R13 :
194       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_h_r13, & junk);
195       break;
196     case FR30_OPERAND_R14 :
197       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_h_r14, & junk);
198       break;
199     case FR30_OPERAND_R15 :
200       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_h_r15, & junk);
201       break;
202     case FR30_OPERAND_RI :
203       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_gr_names, & fields->f_Ri);
204       break;
205     case FR30_OPERAND_RIC :
206       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_gr_names, & fields->f_Ric);
207       break;
208     case FR30_OPERAND_RJ :
209       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_gr_names, & fields->f_Rj);
210       break;
211     case FR30_OPERAND_RJC :
212       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_gr_names, & fields->f_Rjc);
213       break;
214     case FR30_OPERAND_RS1 :
215       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_dr_names, & fields->f_Rs1);
216       break;
217     case FR30_OPERAND_RS2 :
218       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_dr_names, & fields->f_Rs2);
219       break;
220     case FR30_OPERAND_CC :
221       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_CC, &fields->f_cc);
222       break;
223     case FR30_OPERAND_CCC :
224       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_CCC, &fields->f_ccc);
225       break;
226     case FR30_OPERAND_DIR10 :
227       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_DIR10, &fields->f_dir10);
228       break;
229     case FR30_OPERAND_DIR8 :
230       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_DIR8, &fields->f_dir8);
231       break;
232     case FR30_OPERAND_DIR9 :
233       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_DIR9, &fields->f_dir9);
234       break;
235     case FR30_OPERAND_DISP10 :
236       errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_DISP10, &fields->f_disp10);
237       break;
238     case FR30_OPERAND_DISP8 :
239       errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_DISP8, &fields->f_disp8);
240       break;
241     case FR30_OPERAND_DISP9 :
242       errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_DISP9, &fields->f_disp9);
243       break;
244     case FR30_OPERAND_I20 :
245       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_I20, &fields->f_i20);
246       break;
247     case FR30_OPERAND_I32 :
248       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_I32, &fields->f_i32);
249       break;
250     case FR30_OPERAND_I8 :
251       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_I8, &fields->f_i8);
252       break;
253     case FR30_OPERAND_LABEL12 :
254       {
255         bfd_vma value;
256         errmsg = cgen_parse_address (cd, strp, FR30_OPERAND_LABEL12, 0, NULL,  & value);
257         fields->f_rel12 = value;
258       }
259       break;
260     case FR30_OPERAND_LABEL9 :
261       {
262         bfd_vma value;
263         errmsg = cgen_parse_address (cd, strp, FR30_OPERAND_LABEL9, 0, NULL,  & value);
264         fields->f_rel9 = value;
265       }
266       break;
267     case FR30_OPERAND_M4 :
268       errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_M4, &fields->f_m4);
269       break;
270     case FR30_OPERAND_PS :
271       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_h_ps, & junk);
272       break;
273     case FR30_OPERAND_REGLIST_HI_LD :
274       errmsg = parse_hi_register_list_ld (cd, strp, FR30_OPERAND_REGLIST_HI_LD, &fields->f_reglist_hi_ld);
275       break;
276     case FR30_OPERAND_REGLIST_HI_ST :
277       errmsg = parse_hi_register_list_st (cd, strp, FR30_OPERAND_REGLIST_HI_ST, &fields->f_reglist_hi_st);
278       break;
279     case FR30_OPERAND_REGLIST_LOW_LD :
280       errmsg = parse_low_register_list_ld (cd, strp, FR30_OPERAND_REGLIST_LOW_LD, &fields->f_reglist_low_ld);
281       break;
282     case FR30_OPERAND_REGLIST_LOW_ST :
283       errmsg = parse_low_register_list_st (cd, strp, FR30_OPERAND_REGLIST_LOW_ST, &fields->f_reglist_low_st);
284       break;
285     case FR30_OPERAND_S10 :
286       errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_S10, &fields->f_s10);
287       break;
288     case FR30_OPERAND_U10 :
289       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_U10, &fields->f_u10);
290       break;
291     case FR30_OPERAND_U4 :
292       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_U4, &fields->f_u4);
293       break;
294     case FR30_OPERAND_U4C :
295       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_U4C, &fields->f_u4c);
296       break;
297     case FR30_OPERAND_U8 :
298       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_U8, &fields->f_u8);
299       break;
300     case FR30_OPERAND_UDISP6 :
301       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_UDISP6, &fields->f_udisp6);
302       break;
303
304     default :
305       /* xgettext:c-format */
306       fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
307       abort ();
308   }
309
310   return errmsg;
311 }
312
313 cgen_parse_fn * const fr30_cgen_parse_handlers[] = 
314 {
315   parse_insn_normal,
316 };
317
318 void
319 fr30_cgen_init_asm (cd)
320      CGEN_CPU_DESC cd;
321 {
322   fr30_cgen_init_opcode_table (cd);
323   fr30_cgen_init_ibld_table (cd);
324   cd->parse_handlers = & fr30_cgen_parse_handlers[0];
325   cd->parse_operand = fr30_cgen_parse_operand;
326 }
327
328 \f
329
330 /*
331   Regex construction routine.
332
333   This translates an opcode syntax string into a regex string,
334   by replacing any non-character syntax element (such as an
335   opcode) with the pattern '.*'
336
337   It then compiles the regex and stores it in the opcode, for
338   later use by fr30_cgen_assemble_insn
339
340   returns NULL for success, an error message for failure 
341 */
342
343 char * 
344 fr30_cgen_build_insn_regex (insn)
345      CGEN_INSN *insn;
346 {  
347   CGEN_OPCODE *opc = CGEN_INSN_OPCODE (insn);
348   const char *mnem = CGEN_INSN_MNEMONIC (insn);
349   int mnem_len;
350   char rxbuf[CGEN_MAX_RX_ELEMENTS];
351   char *rx = rxbuf;
352   const CGEN_SYNTAX_CHAR_TYPE *syn;
353   int reg_err;
354
355   syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
356
357   /* Mnemonics come first in the syntax string  */
358   if (! CGEN_SYNTAX_MNEMONIC_P (* syn)) return "missing mnemonic in syntax string";
359   ++syn;
360
361   /* copy the literal mnemonic out of the insn */
362   memset (rx, 0, CGEN_MAX_RX_ELEMENTS);
363   mnem_len = strlen(mnem);
364   memcpy (rx, mnem, mnem_len);
365   rx += mnem_len;
366
367   /* copy any remaining literals from the syntax string into the rx */
368   for(; * syn != 0 && rx < rxbuf + (CGEN_MAX_RX_ELEMENTS - 9); ++syn, ++rx) 
369     {
370       if (CGEN_SYNTAX_CHAR_P (* syn)) 
371         {
372          char tmp = CGEN_SYNTAX_CHAR (* syn);
373          switch (tmp) 
374            {
375              /* escape any regex metacharacters in the syntax */
376            case '.': case '[': case '\\': 
377            case '*': case '^': case '$': 
378
379 #ifdef CGEN_ESCAPE_EXTENDED_REGEX
380            case '?': case '{': case '}': 
381            case '(': case ')': case '*':
382            case '|': case '+': case ']':
383 #endif
384
385              * rx++ = '\\';
386              break;  
387            }
388          /* insert syntax char into rx */
389         * rx = tmp;
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|REG_ICASE);
412
413   if (reg_err == 0) 
414     return NULL;
415   else
416     {
417       static char msg[80];
418       regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
419       regfree ((regex_t *) CGEN_INSN_RX (insn));
420       free (CGEN_INSN_RX (insn));
421       (CGEN_INSN_RX (insn)) = NULL;
422     return msg;
423     }
424 }
425
426 \f
427 /* Default insn parser.
428
429    The syntax string is scanned and operands are parsed and stored in FIELDS.
430    Relocs are queued as we go via other callbacks.
431
432    ??? Note that this is currently an all-or-nothing parser.  If we fail to
433    parse the instruction, we return 0 and the caller will start over from
434    the beginning.  Backtracking will be necessary in parsing subexpressions,
435    but that can be handled there.  Not handling backtracking here may get
436    expensive in the case of the m68k.  Deal with later.
437
438    Returns NULL for success, an error message for failure.
439 */
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               /* xgettext:c-format */
514               sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
515                        CGEN_SYNTAX_CHAR(*syn), *str);
516               return msg;
517             }
518           else
519             {
520               /* Ran out of input.  */
521               static char msg [80];
522               /* xgettext:c-format */
523               sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
524                        CGEN_SYNTAX_CHAR(*syn));
525               return msg;
526             }
527           continue;
528         }
529
530       /* We have an operand of some sort.  */
531       errmsg = fr30_cgen_parse_operand (cd, CGEN_SYNTAX_FIELD (*syn),
532                                           &str, fields);
533       if (errmsg)
534         return errmsg;
535
536       /* Done with this operand, continue with next one.  */
537       ++ syn;
538     }
539
540   /* If we're at the end of the syntax string, we're done.  */
541   if (* syn == 0)
542     {
543       /* FIXME: For the moment we assume a valid `str' can only contain
544          blanks now.  IE: We needn't try again with a longer version of
545          the insn and it is assumed that longer versions of insns appear
546          before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
547       while (isspace (* str))
548         ++ str;
549
550       if (* str != '\0')
551         return _("junk at end of line"); /* FIXME: would like to include `str' */
552
553       return NULL;
554     }
555
556   /* We couldn't parse it.  */
557   return _("unrecognized instruction");
558 }
559 \f
560 /* Main entry point.
561    This routine is called for each instruction to be assembled.
562    STR points to the insn to be assembled.
563    We assume all necessary tables have been initialized.
564    The assembled instruction, less any fixups, is stored in BUF.
565    Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
566    still needs to be converted to target byte order, otherwise BUF is an array
567    of bytes in target byte order.
568    The result is a pointer to the insn's entry in the opcode table,
569    or NULL if an error occured (an error message will have already been
570    printed).
571
572    Note that when processing (non-alias) macro-insns,
573    this function recurses.
574
575    ??? It's possible to make this cpu-independent.
576    One would have to deal with a few minor things.
577    At this point in time doing so would be more of a curiosity than useful
578    [for example this file isn't _that_ big], but keeping the possibility in
579    mind helps keep the design clean.  */
580
581 const CGEN_INSN *
582 fr30_cgen_assemble_insn (cd, str, fields, buf, errmsg)
583      CGEN_CPU_DESC cd;
584      const char *str;
585      CGEN_FIELDS *fields;
586      CGEN_INSN_BYTES_PTR buf;
587      char **errmsg;
588 {
589   const char *start;
590   CGEN_INSN_LIST *ilist;
591   const char *parse_errmsg = NULL;
592   const char *insert_errmsg = NULL;
593   int recognized_mnemonic = 0;
594
595   /* Skip leading white space.  */
596   while (isspace (* str))
597     ++ str;
598
599   /* The instructions are stored in hashed lists.
600      Get the first in the list.  */
601   ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
602
603   /* Keep looking until we find a match.  */
604
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 shouldn't be in the hash lists */
613       /* Is this insn supported by the selected cpu?  */
614       if (! fr30_cgen_insn_supported (cd, insn))
615         continue;
616 #endif
617
618       /* If the RELAX 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_RELAX) != 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 ? _("unrecognized form of instruction") :
659                   _("unrecognized instruction"));
660
661     if (strlen (start) > 50)
662       /* xgettext:c-format */
663       sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
664     else 
665       /* xgettext:c-format */
666       sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
667 #else
668     if (strlen (start) > 50)
669       /* xgettext:c-format */
670       sprintf (errbuf, _("bad instruction `%.50s...'"), start);
671     else 
672       /* xgettext:c-format */
673       sprintf (errbuf, _("bad instruction `%.50s'"), start);
674 #endif
675       
676     *errmsg = errbuf;
677     return NULL;
678   }
679 }
680 \f
681 #if 0 /* This calls back to GAS which we can't do without care.  */
682
683 /* Record each member of OPVALS in the assembler's symbol table.
684    This lets GAS parse registers for us.
685    ??? Interesting idea but not currently used.  */
686
687 /* Record each member of OPVALS in the assembler's symbol table.
688    FIXME: Not currently used.  */
689
690 void
691 fr30_cgen_asm_hash_keywords (cd, opvals)
692      CGEN_CPU_DESC cd;
693      CGEN_KEYWORD *opvals;
694 {
695   CGEN_KEYWORD_SEARCH search = cgen_keyword_search_init (opvals, NULL);
696   const CGEN_KEYWORD_ENTRY * ke;
697
698   while ((ke = cgen_keyword_search_next (& search)) != NULL)
699     {
700 #if 0 /* Unnecessary, should be done in the search routine.  */
701       if (! fr30_cgen_opval_supported (ke))
702         continue;
703 #endif
704       cgen_asm_record_register (cd, ke->name, ke->value);
705     }
706 }
707
708 #endif /* 0 */