2003-12-19 Alexandre Oliva <aoliva@redhat.com>
[external/binutils.git] / opcodes / frv-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 "frv-desc.h"
34 #include "frv-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_ulo16
52   PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
53 static const char * parse_uslo16
54   PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
55 static const char * parse_uhi16
56   PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
57 static long parse_register_number
58   PARAMS ((const char **));
59 static const char * parse_spr
60   PARAMS ((CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *));
61 static const char * parse_d12
62   PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
63 static const char * parse_s12
64   PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
65 static const char * parse_u12
66   PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
67 static const char * parse_even_register
68   PARAMS ((CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *));
69 static const char * parse_A0
70   PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
71 static const char * parse_A1
72   PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
73 static const char * parse_A
74   PARAMS ((CGEN_CPU_DESC, const char **, int, long *, long));
75
76 static const char *
77 parse_ulo16 (cd, strp, opindex, valuep)
78      CGEN_CPU_DESC cd;
79      const char **strp;
80      int opindex;
81      unsigned long *valuep;
82 {
83   const char *errmsg;
84   enum cgen_parse_operand_result result_type;
85   bfd_vma value;
86  
87   if (**strp == '#' || **strp == '%')
88     {
89       if (strncasecmp (*strp + 1, "lo(", 3) == 0)
90         {
91           *strp += 4;
92           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
93                                        &result_type, &value);
94           if (**strp != ')')
95             return "missing `)'";
96           ++*strp;
97           if (errmsg == NULL
98               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
99             value &= 0xffff;
100           *valuep = value;
101           return errmsg;
102         }
103       if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
104         {
105           *strp += 9;
106           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELLO,
107                                        &result_type, &value);
108           if (**strp != ')')
109             return "missing ')'";
110           ++*strp;
111           if (errmsg == NULL
112               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
113             value &= 0xffff;
114           *valuep = value;
115           return errmsg;
116         }
117       else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
118         {
119           *strp += 7;
120           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOTLO,
121                                        &result_type, &value);
122           if (**strp != ')')
123             return "missing ')'";
124           ++*strp;
125           if (errmsg == NULL
126               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
127             value &= 0xffff;
128           *valuep = value;
129           return errmsg;
130         }
131       else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
132         {
133           *strp += 15;
134           errmsg = cgen_parse_address (cd, strp, opindex,
135                                        BFD_RELOC_FRV_FUNCDESC_GOTLO,
136                                        &result_type, &value);
137           if (**strp != ')')
138             return "missing ')'";
139           ++*strp;
140           if (errmsg == NULL
141               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
142             value &= 0xffff;
143           *valuep = value;
144           return errmsg;
145         }
146       else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
147         {
148           *strp += 10;
149           errmsg = cgen_parse_address (cd, strp, opindex,
150                                        BFD_RELOC_FRV_GOTOFFLO,
151                                        &result_type, &value);
152           if (**strp != ')')
153             return "missing ')'";
154           ++*strp;
155           if (errmsg == NULL
156               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
157             value &= 0xffff;
158           *valuep = value;
159           return errmsg;
160         }
161       else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
162         {
163           *strp += 18;
164           errmsg = cgen_parse_address (cd, strp, opindex,
165                                        BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
166                                        &result_type, &value);
167           if (**strp != ')')
168             return "missing ')'";
169           ++*strp;
170           if (errmsg == NULL
171               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
172             value &= 0xffff;
173           *valuep = value;
174           return errmsg;
175         }
176     }
177   return cgen_parse_signed_integer (cd, strp, opindex, valuep);
178 }
179
180 static const char *
181 parse_uslo16 (cd, strp, opindex, valuep)
182      CGEN_CPU_DESC cd;
183      const char **strp;
184      int opindex;
185      unsigned long *valuep;
186 {
187   const char *errmsg;
188   enum cgen_parse_operand_result result_type;
189   bfd_vma value;
190  
191   if (**strp == '#' || **strp == '%')
192     {
193       if (strncasecmp (*strp + 1, "lo(", 3) == 0)
194         {
195           *strp += 4;
196           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
197                                        &result_type, &value);
198           if (**strp != ')')
199             return "missing `)'";
200           ++*strp;
201           if (errmsg == NULL
202               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
203             value &= 0xffff;
204           *valuep = value;
205           return errmsg;
206         }
207       else if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
208         {
209           *strp += 9;
210           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELLO,
211                                        &result_type, &value);
212           if (**strp != ')')
213             return "missing ')'";
214           ++*strp;
215           if (errmsg == NULL
216               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
217             value &= 0xffff;
218           *valuep = value;
219           return errmsg;
220         }
221       else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
222         {
223           *strp += 7;
224           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOTLO,
225                                        &result_type, &value);
226           if (**strp != ')')
227             return "missing ')'";
228           ++*strp;
229           if (errmsg == NULL
230               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
231             value &= 0xffff;
232           *valuep = value;
233           return errmsg;
234         }
235       else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
236         {
237           *strp += 15;
238           errmsg = cgen_parse_address (cd, strp, opindex,
239                                        BFD_RELOC_FRV_FUNCDESC_GOTLO,
240                                        &result_type, &value);
241           if (**strp != ')')
242             return "missing ')'";
243           ++*strp;
244           if (errmsg == NULL
245               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
246             value &= 0xffff;
247           *valuep = value;
248           return errmsg;
249         }
250       else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
251         {
252           *strp += 10;
253           errmsg = cgen_parse_address (cd, strp, opindex,
254                                        BFD_RELOC_FRV_GOTOFFLO,
255                                        &result_type, &value);
256           if (**strp != ')')
257             return "missing ')'";
258           ++*strp;
259           if (errmsg == NULL
260               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
261             value &= 0xffff;
262           *valuep = value;
263           return errmsg;
264         }
265       else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
266         {
267           *strp += 18;
268           errmsg = cgen_parse_address (cd, strp, opindex,
269                                        BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
270                                        &result_type, &value);
271           if (**strp != ')')
272             return "missing ')'";
273           ++*strp;
274           if (errmsg == NULL
275               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
276             value &= 0xffff;
277           *valuep = value;
278           return errmsg;
279         }
280     }
281   return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
282 }
283
284 static const char *
285 parse_uhi16 (cd, strp, opindex, valuep)
286      CGEN_CPU_DESC cd;
287      const char **strp;
288      int opindex;
289      unsigned long *valuep;
290 {
291   const char *errmsg;
292   enum cgen_parse_operand_result result_type;
293   bfd_vma value;
294  
295   if (**strp == '#' || **strp == '%')
296     {
297       if (strncasecmp (*strp + 1, "hi(", 3) == 0)
298         {
299           *strp += 4;
300           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_HI16,
301                                        &result_type, &value);
302           if (**strp != ')')
303             return "missing `)'";
304           ++*strp;
305           if (errmsg == NULL
306               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
307             value >>= 16;
308           *valuep = value;
309           return errmsg;
310         }
311       else if (strncasecmp (*strp + 1, "gprelhi(", 8) == 0)
312         {
313           *strp += 9;
314           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELHI,
315                                        &result_type, &value);
316           if (**strp != ')')
317             return "missing ')'";
318           ++*strp;
319           if (errmsg == NULL
320               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
321             value >>= 16;
322           *valuep = value;
323           return errmsg;
324         }
325       else if (strncasecmp (*strp + 1, "gothi(", 6) == 0)
326         {
327           *strp += 7;
328           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOTHI,
329                                        &result_type, &value);
330           if (**strp != ')')
331             return "missing ')'";
332           ++*strp;
333           if (errmsg == NULL
334               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
335             value >>= 16;
336           *valuep = value;
337           return errmsg;
338         }
339       else if (strncasecmp (*strp + 1, "gotfuncdeschi(", 14) == 0)
340         {
341           *strp += 15;
342           errmsg = cgen_parse_address (cd, strp, opindex,
343                                        BFD_RELOC_FRV_FUNCDESC_GOTHI,
344                                        &result_type, &value);
345           if (**strp != ')')
346             return "missing ')'";
347           ++*strp;
348           if (errmsg == NULL
349               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
350             value >>= 16;
351           *valuep = value;
352           return errmsg;
353         }
354       else if (strncasecmp (*strp + 1, "gotoffhi(", 9) == 0)
355         {
356           *strp += 10;
357           errmsg = cgen_parse_address (cd, strp, opindex,
358                                        BFD_RELOC_FRV_GOTOFFHI,
359                                        &result_type, &value);
360           if (**strp != ')')
361             return "missing ')'";
362           ++*strp;
363           if (errmsg == NULL
364               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
365             value >>= 16;
366           *valuep = value;
367           return errmsg;
368         }
369       else if (strncasecmp (*strp + 1, "gotofffuncdeschi(", 17) == 0)
370         {
371           *strp += 18;
372           errmsg = cgen_parse_address (cd, strp, opindex,
373                                        BFD_RELOC_FRV_FUNCDESC_GOTOFFHI,
374                                        &result_type, &value);
375           if (**strp != ')')
376             return "missing ')'";
377           ++*strp;
378           if (errmsg == NULL
379               && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
380             value >>= 16;
381           *valuep = value;
382           return errmsg;
383         }
384     }
385   return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
386 }
387
388 static long
389 parse_register_number (strp)
390      const char **strp;
391 {
392   int regno;
393   if (**strp < '0' || **strp > '9')
394     return -1; /* error */
395
396   regno = **strp - '0';
397   for (++*strp; **strp >= '0' && **strp <= '9'; ++*strp)
398     regno = regno * 10 + (**strp - '0');
399
400   return regno;
401 }
402
403 static const char *
404 parse_spr (cd, strp, table, valuep)
405      CGEN_CPU_DESC cd;
406      const char **strp;
407      CGEN_KEYWORD * table;
408      long *valuep;
409 {
410   const char *save_strp;
411   long regno;
412
413   /* Check for spr index notation.  */
414   if (strncasecmp (*strp, "spr[", 4) == 0)
415     {
416       *strp += 4;
417       regno = parse_register_number (strp);
418       if (**strp != ']')
419         return "missing `]'";
420       ++*strp;
421       if (! spr_valid (regno))
422         return "Special purpose register number is out of range";
423       *valuep = regno;
424       return NULL;
425     }
426
427   save_strp = *strp;
428   regno = parse_register_number (strp);
429   if (regno != -1)
430     {
431       if (! spr_valid (regno))
432         return "Special purpose register number is out of range";
433       *valuep = regno;
434       return NULL;
435     }
436
437   *strp = save_strp;
438   return cgen_parse_keyword (cd, strp, table, valuep);
439 }
440
441 static const char *
442 parse_d12 (cd, strp, opindex, valuep)
443      CGEN_CPU_DESC cd;
444      const char **strp;
445      int opindex;
446      long *valuep;
447 {
448   const char *errmsg;
449   enum cgen_parse_operand_result result_type;
450   bfd_vma value;
451  
452   /* Check for small data reference.  */
453   if (**strp == '#' || **strp == '%')
454     {
455       if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
456         {
457           *strp += 9;
458           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPREL12,
459                                        &result_type, &value);
460           if (**strp != ')')
461             return "missing `)'";
462           ++*strp;
463           *valuep = value;
464           return errmsg;
465         }
466       else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
467         {
468           *strp += 7;
469           errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOT12,
470                                        &result_type, &value);
471           if (**strp != ')')
472             return "missing ')'";
473           ++*strp;
474           *valuep = value;
475           return errmsg;
476         }
477       else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
478         {
479           *strp += 15;
480           errmsg = cgen_parse_address (cd, strp, opindex,
481                                        BFD_RELOC_FRV_FUNCDESC_GOT12,
482                                        &result_type, &value);
483           if (**strp != ')')
484             return "missing ')'";
485           ++*strp;
486           *valuep = value;
487           return errmsg;
488         }
489       else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
490         {
491           *strp += 10;
492           errmsg = cgen_parse_address (cd, strp, opindex,
493                                        BFD_RELOC_FRV_GOTOFF12,
494                                        &result_type, &value);
495           if (**strp != ')')
496             return "missing ')'";
497           ++*strp;
498           *valuep = value;
499           return errmsg;
500         }
501       else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
502         {
503           *strp += 18;
504           errmsg = cgen_parse_address (cd, strp, opindex,
505                                        BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
506                                        &result_type, &value);
507           if (**strp != ')')
508             return "missing ')'";
509           ++*strp;
510           *valuep = value;
511           return errmsg;
512         }
513     }
514   return cgen_parse_signed_integer (cd, strp, opindex, valuep);
515 }
516
517 static const char *
518 parse_s12 (cd, strp, opindex, valuep)
519      CGEN_CPU_DESC cd;
520      const char **strp;
521      int opindex;
522      long *valuep;
523 {
524   const char *errmsg;
525   enum cgen_parse_operand_result result_type;
526   bfd_vma value;
527  
528   /* Check for small data reference.  */
529   if ((**strp == '#' || **strp == '%')
530       && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
531     {
532       *strp += 9;
533       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPREL12,
534                                     &result_type, &value);
535       if (**strp != ')')
536         return "missing `)'";
537       ++*strp;
538       *valuep = value;
539       return errmsg;
540     }
541   else if ((**strp == '#' || **strp == '%')
542            && strncasecmp (*strp + 1, "got12(", 6) == 0)
543     {
544       *strp += 7;
545       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOT12,
546                                    &result_type, &value);
547       if (**strp != ')')
548         return "missing ')'";
549       ++*strp;
550       *valuep = value;
551       return errmsg;
552     }
553   else if ((**strp == '#' || **strp == '%')
554            && strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
555     {
556       *strp += 15;
557       errmsg = cgen_parse_address (cd, strp, opindex,
558                                    BFD_RELOC_FRV_FUNCDESC_GOT12,
559                                    &result_type, &value);
560       if (**strp != ')')
561         return "missing ')'";
562       ++*strp;
563       *valuep = value;
564       return errmsg;
565     }
566   else if ((**strp == '#' || **strp == '%')
567            && strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
568     {
569       *strp += 10;
570       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOTOFF12,
571                                    &result_type, &value);
572       if (**strp != ')')
573         return "missing ')'";
574       ++*strp;
575       *valuep = value;
576       return errmsg;
577     }
578   else if ((**strp == '#' || **strp == '%')
579            && strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
580     {
581       *strp += 18;
582       errmsg = cgen_parse_address (cd, strp, opindex,
583                                    BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
584                                    &result_type, &value);
585       if (**strp != ')')
586         return "missing ')'";
587       ++*strp;
588       *valuep = value;
589       return errmsg;
590     }
591   else
592     {
593       if (**strp == '#')
594         ++*strp;
595       return cgen_parse_signed_integer (cd, strp, opindex, valuep);
596     }
597 }
598
599 static const char *
600 parse_u12 (cd, strp, opindex, valuep)
601      CGEN_CPU_DESC cd;
602      const char **strp;
603      int opindex;
604      long *valuep;
605 {
606   const char *errmsg;
607   enum cgen_parse_operand_result result_type;
608   bfd_vma value;
609  
610   /* Check for small data reference.  */
611   if ((**strp == '#' || **strp == '%')
612       && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
613     {
614       *strp += 9;
615       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELU12,
616                                     &result_type, &value);
617       if (**strp != ')')
618         return "missing `)'";
619       ++*strp;
620       *valuep = value;
621       return errmsg;
622     }
623   else
624     {
625       if (**strp == '#')
626         ++*strp;
627       return cgen_parse_signed_integer (cd, strp, opindex, valuep);
628     }
629 }
630
631 static const char *
632 parse_A (cd, strp, opindex, valuep, A)
633      CGEN_CPU_DESC cd;
634      const char **strp;
635      int opindex;
636      long *valuep;
637      long A;
638 {
639   const char *errmsg;
640  
641   if (**strp == '#')
642     ++*strp;
643
644   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
645   if (errmsg)
646     return errmsg;
647
648   if (*valuep != A)
649     return "Value of A operand must be 0 or 1";
650
651   return NULL;
652 }
653
654 static const char *
655 parse_A0 (cd, strp, opindex, valuep)
656      CGEN_CPU_DESC cd;
657      const char **strp;
658      int opindex;
659      long *valuep;
660 {
661   return parse_A (cd, strp, opindex, valuep, 0);
662 }
663
664 static const char *
665 parse_A1 (cd, strp, opindex, valuep)
666      CGEN_CPU_DESC cd;
667      const char **strp;
668      int opindex;
669      long *valuep;
670 {
671   return parse_A (cd, strp, opindex, valuep, 1);
672 }
673
674 static const char *
675 parse_even_register (cd, strP, tableP, valueP)
676      CGEN_CPU_DESC  cd;
677      const char **  strP;
678      CGEN_KEYWORD * tableP;
679      long *         valueP;
680 {
681   const char * errmsg;
682   const char * saved_star_strP = * strP;
683
684   errmsg = cgen_parse_keyword (cd, strP, tableP, valueP);
685
686   if (errmsg == NULL && ((* valueP) & 1))
687     {
688       errmsg = _("register number must be even");
689       * strP = saved_star_strP;
690     }
691
692   return errmsg;
693 }
694 /* -- */
695
696 const char * frv_cgen_parse_operand
697   PARAMS ((CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *));
698
699 /* Main entry point for operand parsing.
700
701    This function is basically just a big switch statement.  Earlier versions
702    used tables to look up the function to use, but
703    - if the table contains both assembler and disassembler functions then
704      the disassembler contains much of the assembler and vice-versa,
705    - there's a lot of inlining possibilities as things grow,
706    - using a switch statement avoids the function call overhead.
707
708    This function could be moved into `parse_insn_normal', but keeping it
709    separate makes clear the interface between `parse_insn_normal' and each of
710    the handlers.  */
711
712 const char *
713 frv_cgen_parse_operand (cd, opindex, strp, fields)
714      CGEN_CPU_DESC cd;
715      int opindex;
716      const char ** strp;
717      CGEN_FIELDS * fields;
718 {
719   const char * errmsg = NULL;
720   /* Used by scalar operands that still need to be parsed.  */
721   long junk ATTRIBUTE_UNUSED;
722
723   switch (opindex)
724     {
725     case FRV_OPERAND_A0 :
726       errmsg = parse_A0 (cd, strp, FRV_OPERAND_A0, &fields->f_A);
727       break;
728     case FRV_OPERAND_A1 :
729       errmsg = parse_A1 (cd, strp, FRV_OPERAND_A1, &fields->f_A);
730       break;
731     case FRV_OPERAND_ACC40SI :
732       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_acc_names, & fields->f_ACC40Si);
733       break;
734     case FRV_OPERAND_ACC40SK :
735       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_acc_names, & fields->f_ACC40Sk);
736       break;
737     case FRV_OPERAND_ACC40UI :
738       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_acc_names, & fields->f_ACC40Ui);
739       break;
740     case FRV_OPERAND_ACC40UK :
741       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_acc_names, & fields->f_ACC40Uk);
742       break;
743     case FRV_OPERAND_ACCGI :
744       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_accg_names, & fields->f_ACCGi);
745       break;
746     case FRV_OPERAND_ACCGK :
747       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_accg_names, & fields->f_ACCGk);
748       break;
749     case FRV_OPERAND_CCI :
750       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cccr_names, & fields->f_CCi);
751       break;
752     case FRV_OPERAND_CPRDOUBLEK :
753       errmsg = parse_even_register (cd, strp, & frv_cgen_opval_cpr_names, & fields->f_CPRk);
754       break;
755     case FRV_OPERAND_CPRI :
756       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cpr_names, & fields->f_CPRi);
757       break;
758     case FRV_OPERAND_CPRJ :
759       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cpr_names, & fields->f_CPRj);
760       break;
761     case FRV_OPERAND_CPRK :
762       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cpr_names, & fields->f_CPRk);
763       break;
764     case FRV_OPERAND_CRI :
765       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cccr_names, & fields->f_CRi);
766       break;
767     case FRV_OPERAND_CRJ :
768       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cccr_names, & fields->f_CRj);
769       break;
770     case FRV_OPERAND_CRJ_FLOAT :
771       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cccr_names, & fields->f_CRj_float);
772       break;
773     case FRV_OPERAND_CRJ_INT :
774       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cccr_names, & fields->f_CRj_int);
775       break;
776     case FRV_OPERAND_CRK :
777       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cccr_names, & fields->f_CRk);
778       break;
779     case FRV_OPERAND_FCCI_1 :
780       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fccr_names, & fields->f_FCCi_1);
781       break;
782     case FRV_OPERAND_FCCI_2 :
783       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fccr_names, & fields->f_FCCi_2);
784       break;
785     case FRV_OPERAND_FCCI_3 :
786       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fccr_names, & fields->f_FCCi_3);
787       break;
788     case FRV_OPERAND_FCCK :
789       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fccr_names, & fields->f_FCCk);
790       break;
791     case FRV_OPERAND_FRDOUBLEI :
792       errmsg = parse_even_register (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRi);
793       break;
794     case FRV_OPERAND_FRDOUBLEJ :
795       errmsg = parse_even_register (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRj);
796       break;
797     case FRV_OPERAND_FRDOUBLEK :
798       errmsg = parse_even_register (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRk);
799       break;
800     case FRV_OPERAND_FRI :
801       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRi);
802       break;
803     case FRV_OPERAND_FRINTI :
804       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRi);
805       break;
806     case FRV_OPERAND_FRINTIEVEN :
807       errmsg = parse_even_register (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRi);
808       break;
809     case FRV_OPERAND_FRINTJ :
810       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRj);
811       break;
812     case FRV_OPERAND_FRINTJEVEN :
813       errmsg = parse_even_register (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRj);
814       break;
815     case FRV_OPERAND_FRINTK :
816       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRk);
817       break;
818     case FRV_OPERAND_FRINTKEVEN :
819       errmsg = parse_even_register (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRk);
820       break;
821     case FRV_OPERAND_FRJ :
822       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRj);
823       break;
824     case FRV_OPERAND_FRK :
825       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRk);
826       break;
827     case FRV_OPERAND_FRKHI :
828       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRk);
829       break;
830     case FRV_OPERAND_FRKLO :
831       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRk);
832       break;
833     case FRV_OPERAND_GRDOUBLEK :
834       errmsg = parse_even_register (cd, strp, & frv_cgen_opval_gr_names, & fields->f_GRk);
835       break;
836     case FRV_OPERAND_GRI :
837       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_gr_names, & fields->f_GRi);
838       break;
839     case FRV_OPERAND_GRJ :
840       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_gr_names, & fields->f_GRj);
841       break;
842     case FRV_OPERAND_GRK :
843       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_gr_names, & fields->f_GRk);
844       break;
845     case FRV_OPERAND_GRKHI :
846       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_gr_names, & fields->f_GRk);
847       break;
848     case FRV_OPERAND_GRKLO :
849       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_gr_names, & fields->f_GRk);
850       break;
851     case FRV_OPERAND_ICCI_1 :
852       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_iccr_names, & fields->f_ICCi_1);
853       break;
854     case FRV_OPERAND_ICCI_2 :
855       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_iccr_names, & fields->f_ICCi_2);
856       break;
857     case FRV_OPERAND_ICCI_3 :
858       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_iccr_names, & fields->f_ICCi_3);
859       break;
860     case FRV_OPERAND_LI :
861       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_LI, &fields->f_LI);
862       break;
863     case FRV_OPERAND_AE :
864       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_AE, &fields->f_ae);
865       break;
866     case FRV_OPERAND_CCOND :
867       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_CCOND, &fields->f_ccond);
868       break;
869     case FRV_OPERAND_COND :
870       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_COND, &fields->f_cond);
871       break;
872     case FRV_OPERAND_D12 :
873       errmsg = parse_d12 (cd, strp, FRV_OPERAND_D12, &fields->f_d12);
874       break;
875     case FRV_OPERAND_DEBUG :
876       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_DEBUG, &fields->f_debug);
877       break;
878     case FRV_OPERAND_EIR :
879       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_EIR, &fields->f_eir);
880       break;
881     case FRV_OPERAND_HINT :
882       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_HINT, &fields->f_hint);
883       break;
884     case FRV_OPERAND_HINT_NOT_TAKEN :
885       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_h_hint_not_taken, & fields->f_hint);
886       break;
887     case FRV_OPERAND_HINT_TAKEN :
888       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_h_hint_taken, & fields->f_hint);
889       break;
890     case FRV_OPERAND_LABEL16 :
891       {
892         bfd_vma value;
893         errmsg = cgen_parse_address (cd, strp, FRV_OPERAND_LABEL16, 0, NULL,  & value);
894         fields->f_label16 = value;
895       }
896       break;
897     case FRV_OPERAND_LABEL24 :
898       {
899         bfd_vma value;
900         errmsg = cgen_parse_address (cd, strp, FRV_OPERAND_LABEL24, 0, NULL,  & value);
901         fields->f_label24 = value;
902       }
903       break;
904     case FRV_OPERAND_LOCK :
905       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_LOCK, &fields->f_lock);
906       break;
907     case FRV_OPERAND_PACK :
908       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_h_pack, & fields->f_pack);
909       break;
910     case FRV_OPERAND_S10 :
911       errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S10, &fields->f_s10);
912       break;
913     case FRV_OPERAND_S12 :
914       errmsg = parse_s12 (cd, strp, FRV_OPERAND_S12, &fields->f_d12);
915       break;
916     case FRV_OPERAND_S16 :
917       errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S16, &fields->f_s16);
918       break;
919     case FRV_OPERAND_S5 :
920       errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S5, &fields->f_s5);
921       break;
922     case FRV_OPERAND_S6 :
923       errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S6, &fields->f_s6);
924       break;
925     case FRV_OPERAND_S6_1 :
926       errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S6_1, &fields->f_s6_1);
927       break;
928     case FRV_OPERAND_SLO16 :
929       errmsg = parse_uslo16 (cd, strp, FRV_OPERAND_SLO16, &fields->f_s16);
930       break;
931     case FRV_OPERAND_SPR :
932       errmsg = parse_spr (cd, strp, & frv_cgen_opval_spr_names, & fields->f_spr);
933       break;
934     case FRV_OPERAND_U12 :
935       errmsg = parse_u12 (cd, strp, FRV_OPERAND_U12, &fields->f_u12);
936       break;
937     case FRV_OPERAND_U16 :
938       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_U16, &fields->f_u16);
939       break;
940     case FRV_OPERAND_U6 :
941       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_U6, &fields->f_u6);
942       break;
943     case FRV_OPERAND_UHI16 :
944       errmsg = parse_uhi16 (cd, strp, FRV_OPERAND_UHI16, &fields->f_u16);
945       break;
946     case FRV_OPERAND_ULO16 :
947       errmsg = parse_ulo16 (cd, strp, FRV_OPERAND_ULO16, &fields->f_u16);
948       break;
949
950     default :
951       /* xgettext:c-format */
952       fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
953       abort ();
954   }
955
956   return errmsg;
957 }
958
959 cgen_parse_fn * const frv_cgen_parse_handlers[] = 
960 {
961   parse_insn_normal,
962 };
963
964 void
965 frv_cgen_init_asm (cd)
966      CGEN_CPU_DESC cd;
967 {
968   frv_cgen_init_opcode_table (cd);
969   frv_cgen_init_ibld_table (cd);
970   cd->parse_handlers = & frv_cgen_parse_handlers[0];
971   cd->parse_operand = frv_cgen_parse_operand;
972 }
973
974 \f
975
976 /* Regex construction routine.
977
978    This translates an opcode syntax string into a regex string,
979    by replacing any non-character syntax element (such as an
980    opcode) with the pattern '.*'
981
982    It then compiles the regex and stores it in the opcode, for
983    later use by frv_cgen_assemble_insn
984
985    Returns NULL for success, an error message for failure.  */
986
987 char * 
988 frv_cgen_build_insn_regex (CGEN_INSN *insn)
989 {  
990   CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
991   const char *mnem = CGEN_INSN_MNEMONIC (insn);
992   char rxbuf[CGEN_MAX_RX_ELEMENTS];
993   char *rx = rxbuf;
994   const CGEN_SYNTAX_CHAR_TYPE *syn;
995   int reg_err;
996
997   syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
998
999   /* Mnemonics come first in the syntax string.  */
1000   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
1001     return _("missing mnemonic in syntax string");
1002   ++syn;
1003
1004   /* Generate a case sensitive regular expression that emulates case
1005      insensitive matching in the "C" locale.  We cannot generate a case
1006      insensitive regular expression because in Turkish locales, 'i' and 'I'
1007      are not equal modulo case conversion.  */
1008
1009   /* Copy the literal mnemonic out of the insn.  */
1010   for (; *mnem; mnem++)
1011     {
1012       char c = *mnem;
1013
1014       if (ISALPHA (c))
1015         {
1016           *rx++ = '[';
1017           *rx++ = TOLOWER (c);
1018           *rx++ = TOUPPER (c);
1019           *rx++ = ']';
1020         }
1021       else
1022         *rx++ = c;
1023     }
1024
1025   /* Copy any remaining literals from the syntax string into the rx.  */
1026   for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
1027     {
1028       if (CGEN_SYNTAX_CHAR_P (* syn)) 
1029         {
1030           char c = CGEN_SYNTAX_CHAR (* syn);
1031
1032           switch (c) 
1033             {
1034               /* Escape any regex metacharacters in the syntax.  */
1035             case '.': case '[': case '\\': 
1036             case '*': case '^': case '$': 
1037
1038 #ifdef CGEN_ESCAPE_EXTENDED_REGEX
1039             case '?': case '{': case '}': 
1040             case '(': case ')': case '*':
1041             case '|': case '+': case ']':
1042 #endif
1043               *rx++ = '\\';
1044               *rx++ = c;
1045               break;
1046
1047             default:
1048               if (ISALPHA (c))
1049                 {
1050                   *rx++ = '[';
1051                   *rx++ = TOLOWER (c);
1052                   *rx++ = TOUPPER (c);
1053                   *rx++ = ']';
1054                 }
1055               else
1056                 *rx++ = c;
1057               break;
1058             }
1059         }
1060       else
1061         {
1062           /* Replace non-syntax fields with globs.  */
1063           *rx++ = '.';
1064           *rx++ = '*';
1065         }
1066     }
1067
1068   /* Trailing whitespace ok.  */
1069   * rx++ = '['; 
1070   * rx++ = ' '; 
1071   * rx++ = '\t'; 
1072   * rx++ = ']'; 
1073   * rx++ = '*'; 
1074
1075   /* But anchor it after that.  */
1076   * rx++ = '$'; 
1077   * rx = '\0';
1078
1079   CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
1080   reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
1081
1082   if (reg_err == 0) 
1083     return NULL;
1084   else
1085     {
1086       static char msg[80];
1087
1088       regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
1089       regfree ((regex_t *) CGEN_INSN_RX (insn));
1090       free (CGEN_INSN_RX (insn));
1091       (CGEN_INSN_RX (insn)) = NULL;
1092       return msg;
1093     }
1094 }
1095
1096 \f
1097 /* Default insn parser.
1098
1099    The syntax string is scanned and operands are parsed and stored in FIELDS.
1100    Relocs are queued as we go via other callbacks.
1101
1102    ??? Note that this is currently an all-or-nothing parser.  If we fail to
1103    parse the instruction, we return 0 and the caller will start over from
1104    the beginning.  Backtracking will be necessary in parsing subexpressions,
1105    but that can be handled there.  Not handling backtracking here may get
1106    expensive in the case of the m68k.  Deal with later.
1107
1108    Returns NULL for success, an error message for failure.  */
1109
1110 static const char *
1111 parse_insn_normal (CGEN_CPU_DESC cd,
1112                    const CGEN_INSN *insn,
1113                    const char **strp,
1114                    CGEN_FIELDS *fields)
1115 {
1116   /* ??? Runtime added insns not handled yet.  */
1117   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
1118   const char *str = *strp;
1119   const char *errmsg;
1120   const char *p;
1121   const CGEN_SYNTAX_CHAR_TYPE * syn;
1122 #ifdef CGEN_MNEMONIC_OPERANDS
1123   /* FIXME: wip */
1124   int past_opcode_p;
1125 #endif
1126
1127   /* For now we assume the mnemonic is first (there are no leading operands).
1128      We can parse it without needing to set up operand parsing.
1129      GAS's input scrubber will ensure mnemonics are lowercase, but we may
1130      not be called from GAS.  */
1131   p = CGEN_INSN_MNEMONIC (insn);
1132   while (*p && TOLOWER (*p) == TOLOWER (*str))
1133     ++p, ++str;
1134
1135   if (* p)
1136     return _("unrecognized instruction");
1137
1138 #ifndef CGEN_MNEMONIC_OPERANDS
1139   if (* str && ! ISSPACE (* str))
1140     return _("unrecognized instruction");
1141 #endif
1142
1143   CGEN_INIT_PARSE (cd);
1144   cgen_init_parse_operand (cd);
1145 #ifdef CGEN_MNEMONIC_OPERANDS
1146   past_opcode_p = 0;
1147 #endif
1148
1149   /* We don't check for (*str != '\0') here because we want to parse
1150      any trailing fake arguments in the syntax string.  */
1151   syn = CGEN_SYNTAX_STRING (syntax);
1152
1153   /* Mnemonics come first for now, ensure valid string.  */
1154   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
1155     abort ();
1156
1157   ++syn;
1158
1159   while (* syn != 0)
1160     {
1161       /* Non operand chars must match exactly.  */
1162       if (CGEN_SYNTAX_CHAR_P (* syn))
1163         {
1164           /* FIXME: While we allow for non-GAS callers above, we assume the
1165              first char after the mnemonic part is a space.  */
1166           /* FIXME: We also take inappropriate advantage of the fact that
1167              GAS's input scrubber will remove extraneous blanks.  */
1168           if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
1169             {
1170 #ifdef CGEN_MNEMONIC_OPERANDS
1171               if (CGEN_SYNTAX_CHAR(* syn) == ' ')
1172                 past_opcode_p = 1;
1173 #endif
1174               ++ syn;
1175               ++ str;
1176             }
1177           else if (*str)
1178             {
1179               /* Syntax char didn't match.  Can't be this insn.  */
1180               static char msg [80];
1181
1182               /* xgettext:c-format */
1183               sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
1184                        CGEN_SYNTAX_CHAR(*syn), *str);
1185               return msg;
1186             }
1187           else
1188             {
1189               /* Ran out of input.  */
1190               static char msg [80];
1191
1192               /* xgettext:c-format */
1193               sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
1194                        CGEN_SYNTAX_CHAR(*syn));
1195               return msg;
1196             }
1197           continue;
1198         }
1199
1200       /* We have an operand of some sort.  */
1201       errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn),
1202                                           &str, fields);
1203       if (errmsg)
1204         return errmsg;
1205
1206       /* Done with this operand, continue with next one.  */
1207       ++ syn;
1208     }
1209
1210   /* If we're at the end of the syntax string, we're done.  */
1211   if (* syn == 0)
1212     {
1213       /* FIXME: For the moment we assume a valid `str' can only contain
1214          blanks now.  IE: We needn't try again with a longer version of
1215          the insn and it is assumed that longer versions of insns appear
1216          before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
1217       while (ISSPACE (* str))
1218         ++ str;
1219
1220       if (* str != '\0')
1221         return _("junk at end of line"); /* FIXME: would like to include `str' */
1222
1223       return NULL;
1224     }
1225
1226   /* We couldn't parse it.  */
1227   return _("unrecognized instruction");
1228 }
1229 \f
1230 /* Main entry point.
1231    This routine is called for each instruction to be assembled.
1232    STR points to the insn to be assembled.
1233    We assume all necessary tables have been initialized.
1234    The assembled instruction, less any fixups, is stored in BUF.
1235    Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
1236    still needs to be converted to target byte order, otherwise BUF is an array
1237    of bytes in target byte order.
1238    The result is a pointer to the insn's entry in the opcode table,
1239    or NULL if an error occured (an error message will have already been
1240    printed).
1241
1242    Note that when processing (non-alias) macro-insns,
1243    this function recurses.
1244
1245    ??? It's possible to make this cpu-independent.
1246    One would have to deal with a few minor things.
1247    At this point in time doing so would be more of a curiosity than useful
1248    [for example this file isn't _that_ big], but keeping the possibility in
1249    mind helps keep the design clean.  */
1250
1251 const CGEN_INSN *
1252 frv_cgen_assemble_insn (CGEN_CPU_DESC cd,
1253                            const char *str,
1254                            CGEN_FIELDS *fields,
1255                            CGEN_INSN_BYTES_PTR buf,
1256                            char **errmsg)
1257 {
1258   const char *start;
1259   CGEN_INSN_LIST *ilist;
1260   const char *parse_errmsg = NULL;
1261   const char *insert_errmsg = NULL;
1262   int recognized_mnemonic = 0;
1263
1264   /* Skip leading white space.  */
1265   while (ISSPACE (* str))
1266     ++ str;
1267
1268   /* The instructions are stored in hashed lists.
1269      Get the first in the list.  */
1270   ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
1271
1272   /* Keep looking until we find a match.  */
1273   start = str;
1274   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
1275     {
1276       const CGEN_INSN *insn = ilist->insn;
1277       recognized_mnemonic = 1;
1278
1279 #ifdef CGEN_VALIDATE_INSN_SUPPORTED 
1280       /* Not usually needed as unsupported opcodes
1281          shouldn't be in the hash lists.  */
1282       /* Is this insn supported by the selected cpu?  */
1283       if (! frv_cgen_insn_supported (cd, insn))
1284         continue;
1285 #endif
1286       /* If the RELAXED attribute is set, this is an insn that shouldn't be
1287          chosen immediately.  Instead, it is used during assembler/linker
1288          relaxation if possible.  */
1289       if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
1290         continue;
1291
1292       str = start;
1293
1294       /* Skip this insn if str doesn't look right lexically.  */
1295       if (CGEN_INSN_RX (insn) != NULL &&
1296           regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
1297         continue;
1298
1299       /* Allow parse/insert handlers to obtain length of insn.  */
1300       CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
1301
1302       parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
1303       if (parse_errmsg != NULL)
1304         continue;
1305
1306       /* ??? 0 is passed for `pc'.  */
1307       insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
1308                                                  (bfd_vma) 0);
1309       if (insert_errmsg != NULL)
1310         continue;
1311
1312       /* It is up to the caller to actually output the insn and any
1313          queued relocs.  */
1314       return insn;
1315     }
1316
1317   {
1318     static char errbuf[150];
1319 #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
1320     const char *tmp_errmsg;
1321
1322     /* If requesting verbose error messages, use insert_errmsg.
1323        Failing that, use parse_errmsg.  */
1324     tmp_errmsg = (insert_errmsg ? insert_errmsg :
1325                   parse_errmsg ? parse_errmsg :
1326                   recognized_mnemonic ?
1327                   _("unrecognized form of instruction") :
1328                   _("unrecognized instruction"));
1329
1330     if (strlen (start) > 50)
1331       /* xgettext:c-format */
1332       sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
1333     else 
1334       /* xgettext:c-format */
1335       sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
1336 #else
1337     if (strlen (start) > 50)
1338       /* xgettext:c-format */
1339       sprintf (errbuf, _("bad instruction `%.50s...'"), start);
1340     else 
1341       /* xgettext:c-format */
1342       sprintf (errbuf, _("bad instruction `%.50s'"), start);
1343 #endif
1344       
1345     *errmsg = errbuf;
1346     return NULL;
1347   }
1348 }
1349 \f
1350 #if 0 /* This calls back to GAS which we can't do without care.  */
1351
1352 /* Record each member of OPVALS in the assembler's symbol table.
1353    This lets GAS parse registers for us.
1354    ??? Interesting idea but not currently used.  */
1355
1356 /* Record each member of OPVALS in the assembler's symbol table.
1357    FIXME: Not currently used.  */
1358
1359 void
1360 frv_cgen_asm_hash_keywords (CGEN_CPU_DESC cd, CGEN_KEYWORD *opvals)
1361 {
1362   CGEN_KEYWORD_SEARCH search = cgen_keyword_search_init (opvals, NULL);
1363   const CGEN_KEYWORD_ENTRY * ke;
1364
1365   while ((ke = cgen_keyword_search_next (& search)) != NULL)
1366     {
1367 #if 0 /* Unnecessary, should be done in the search routine.  */
1368       if (! frv_cgen_opval_supported (ke))
1369         continue;
1370 #endif
1371       cgen_asm_record_register (cd, ke->name, ke->value);
1372     }
1373 }
1374
1375 #endif /* 0 */