Add fr450 support.
[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_LRAD :
864       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_LRAD, &fields->f_LRAD);
865       break;
866     case FRV_OPERAND_LRAE :
867       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_LRAE, &fields->f_LRAE);
868       break;
869     case FRV_OPERAND_LRAS :
870       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_LRAS, &fields->f_LRAS);
871       break;
872     case FRV_OPERAND_TLBPRL :
873       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_TLBPRL, &fields->f_TLBPRL);
874       break;
875     case FRV_OPERAND_TLBPROPX :
876       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_TLBPROPX, &fields->f_TLBPRopx);
877       break;
878     case FRV_OPERAND_AE :
879       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_AE, &fields->f_ae);
880       break;
881     case FRV_OPERAND_CCOND :
882       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_CCOND, &fields->f_ccond);
883       break;
884     case FRV_OPERAND_COND :
885       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_COND, &fields->f_cond);
886       break;
887     case FRV_OPERAND_D12 :
888       errmsg = parse_d12 (cd, strp, FRV_OPERAND_D12, &fields->f_d12);
889       break;
890     case FRV_OPERAND_DEBUG :
891       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_DEBUG, &fields->f_debug);
892       break;
893     case FRV_OPERAND_EIR :
894       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_EIR, &fields->f_eir);
895       break;
896     case FRV_OPERAND_HINT :
897       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_HINT, &fields->f_hint);
898       break;
899     case FRV_OPERAND_HINT_NOT_TAKEN :
900       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_h_hint_not_taken, & fields->f_hint);
901       break;
902     case FRV_OPERAND_HINT_TAKEN :
903       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_h_hint_taken, & fields->f_hint);
904       break;
905     case FRV_OPERAND_LABEL16 :
906       {
907         bfd_vma value;
908         errmsg = cgen_parse_address (cd, strp, FRV_OPERAND_LABEL16, 0, NULL,  & value);
909         fields->f_label16 = value;
910       }
911       break;
912     case FRV_OPERAND_LABEL24 :
913       {
914         bfd_vma value;
915         errmsg = cgen_parse_address (cd, strp, FRV_OPERAND_LABEL24, 0, NULL,  & value);
916         fields->f_label24 = value;
917       }
918       break;
919     case FRV_OPERAND_LOCK :
920       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_LOCK, &fields->f_lock);
921       break;
922     case FRV_OPERAND_PACK :
923       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_h_pack, & fields->f_pack);
924       break;
925     case FRV_OPERAND_S10 :
926       errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S10, &fields->f_s10);
927       break;
928     case FRV_OPERAND_S12 :
929       errmsg = parse_s12 (cd, strp, FRV_OPERAND_S12, &fields->f_d12);
930       break;
931     case FRV_OPERAND_S16 :
932       errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S16, &fields->f_s16);
933       break;
934     case FRV_OPERAND_S5 :
935       errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S5, &fields->f_s5);
936       break;
937     case FRV_OPERAND_S6 :
938       errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S6, &fields->f_s6);
939       break;
940     case FRV_OPERAND_S6_1 :
941       errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S6_1, &fields->f_s6_1);
942       break;
943     case FRV_OPERAND_SLO16 :
944       errmsg = parse_uslo16 (cd, strp, FRV_OPERAND_SLO16, &fields->f_s16);
945       break;
946     case FRV_OPERAND_SPR :
947       errmsg = parse_spr (cd, strp, & frv_cgen_opval_spr_names, & fields->f_spr);
948       break;
949     case FRV_OPERAND_U12 :
950       errmsg = parse_u12 (cd, strp, FRV_OPERAND_U12, &fields->f_u12);
951       break;
952     case FRV_OPERAND_U16 :
953       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_U16, &fields->f_u16);
954       break;
955     case FRV_OPERAND_U6 :
956       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_U6, &fields->f_u6);
957       break;
958     case FRV_OPERAND_UHI16 :
959       errmsg = parse_uhi16 (cd, strp, FRV_OPERAND_UHI16, &fields->f_u16);
960       break;
961     case FRV_OPERAND_ULO16 :
962       errmsg = parse_ulo16 (cd, strp, FRV_OPERAND_ULO16, &fields->f_u16);
963       break;
964
965     default :
966       /* xgettext:c-format */
967       fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
968       abort ();
969   }
970
971   return errmsg;
972 }
973
974 cgen_parse_fn * const frv_cgen_parse_handlers[] = 
975 {
976   parse_insn_normal,
977 };
978
979 void
980 frv_cgen_init_asm (cd)
981      CGEN_CPU_DESC cd;
982 {
983   frv_cgen_init_opcode_table (cd);
984   frv_cgen_init_ibld_table (cd);
985   cd->parse_handlers = & frv_cgen_parse_handlers[0];
986   cd->parse_operand = frv_cgen_parse_operand;
987 }
988
989 \f
990
991 /* Regex construction routine.
992
993    This translates an opcode syntax string into a regex string,
994    by replacing any non-character syntax element (such as an
995    opcode) with the pattern '.*'
996
997    It then compiles the regex and stores it in the opcode, for
998    later use by frv_cgen_assemble_insn
999
1000    Returns NULL for success, an error message for failure.  */
1001
1002 char * 
1003 frv_cgen_build_insn_regex (CGEN_INSN *insn)
1004 {  
1005   CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
1006   const char *mnem = CGEN_INSN_MNEMONIC (insn);
1007   char rxbuf[CGEN_MAX_RX_ELEMENTS];
1008   char *rx = rxbuf;
1009   const CGEN_SYNTAX_CHAR_TYPE *syn;
1010   int reg_err;
1011
1012   syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
1013
1014   /* Mnemonics come first in the syntax string.  */
1015   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
1016     return _("missing mnemonic in syntax string");
1017   ++syn;
1018
1019   /* Generate a case sensitive regular expression that emulates case
1020      insensitive matching in the "C" locale.  We cannot generate a case
1021      insensitive regular expression because in Turkish locales, 'i' and 'I'
1022      are not equal modulo case conversion.  */
1023
1024   /* Copy the literal mnemonic out of the insn.  */
1025   for (; *mnem; mnem++)
1026     {
1027       char c = *mnem;
1028
1029       if (ISALPHA (c))
1030         {
1031           *rx++ = '[';
1032           *rx++ = TOLOWER (c);
1033           *rx++ = TOUPPER (c);
1034           *rx++ = ']';
1035         }
1036       else
1037         *rx++ = c;
1038     }
1039
1040   /* Copy any remaining literals from the syntax string into the rx.  */
1041   for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
1042     {
1043       if (CGEN_SYNTAX_CHAR_P (* syn)) 
1044         {
1045           char c = CGEN_SYNTAX_CHAR (* syn);
1046
1047           switch (c) 
1048             {
1049               /* Escape any regex metacharacters in the syntax.  */
1050             case '.': case '[': case '\\': 
1051             case '*': case '^': case '$': 
1052
1053 #ifdef CGEN_ESCAPE_EXTENDED_REGEX
1054             case '?': case '{': case '}': 
1055             case '(': case ')': case '*':
1056             case '|': case '+': case ']':
1057 #endif
1058               *rx++ = '\\';
1059               *rx++ = c;
1060               break;
1061
1062             default:
1063               if (ISALPHA (c))
1064                 {
1065                   *rx++ = '[';
1066                   *rx++ = TOLOWER (c);
1067                   *rx++ = TOUPPER (c);
1068                   *rx++ = ']';
1069                 }
1070               else
1071                 *rx++ = c;
1072               break;
1073             }
1074         }
1075       else
1076         {
1077           /* Replace non-syntax fields with globs.  */
1078           *rx++ = '.';
1079           *rx++ = '*';
1080         }
1081     }
1082
1083   /* Trailing whitespace ok.  */
1084   * rx++ = '['; 
1085   * rx++ = ' '; 
1086   * rx++ = '\t'; 
1087   * rx++ = ']'; 
1088   * rx++ = '*'; 
1089
1090   /* But anchor it after that.  */
1091   * rx++ = '$'; 
1092   * rx = '\0';
1093
1094   CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
1095   reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
1096
1097   if (reg_err == 0) 
1098     return NULL;
1099   else
1100     {
1101       static char msg[80];
1102
1103       regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
1104       regfree ((regex_t *) CGEN_INSN_RX (insn));
1105       free (CGEN_INSN_RX (insn));
1106       (CGEN_INSN_RX (insn)) = NULL;
1107       return msg;
1108     }
1109 }
1110
1111 \f
1112 /* Default insn parser.
1113
1114    The syntax string is scanned and operands are parsed and stored in FIELDS.
1115    Relocs are queued as we go via other callbacks.
1116
1117    ??? Note that this is currently an all-or-nothing parser.  If we fail to
1118    parse the instruction, we return 0 and the caller will start over from
1119    the beginning.  Backtracking will be necessary in parsing subexpressions,
1120    but that can be handled there.  Not handling backtracking here may get
1121    expensive in the case of the m68k.  Deal with later.
1122
1123    Returns NULL for success, an error message for failure.  */
1124
1125 static const char *
1126 parse_insn_normal (CGEN_CPU_DESC cd,
1127                    const CGEN_INSN *insn,
1128                    const char **strp,
1129                    CGEN_FIELDS *fields)
1130 {
1131   /* ??? Runtime added insns not handled yet.  */
1132   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
1133   const char *str = *strp;
1134   const char *errmsg;
1135   const char *p;
1136   const CGEN_SYNTAX_CHAR_TYPE * syn;
1137 #ifdef CGEN_MNEMONIC_OPERANDS
1138   /* FIXME: wip */
1139   int past_opcode_p;
1140 #endif
1141
1142   /* For now we assume the mnemonic is first (there are no leading operands).
1143      We can parse it without needing to set up operand parsing.
1144      GAS's input scrubber will ensure mnemonics are lowercase, but we may
1145      not be called from GAS.  */
1146   p = CGEN_INSN_MNEMONIC (insn);
1147   while (*p && TOLOWER (*p) == TOLOWER (*str))
1148     ++p, ++str;
1149
1150   if (* p)
1151     return _("unrecognized instruction");
1152
1153 #ifndef CGEN_MNEMONIC_OPERANDS
1154   if (* str && ! ISSPACE (* str))
1155     return _("unrecognized instruction");
1156 #endif
1157
1158   CGEN_INIT_PARSE (cd);
1159   cgen_init_parse_operand (cd);
1160 #ifdef CGEN_MNEMONIC_OPERANDS
1161   past_opcode_p = 0;
1162 #endif
1163
1164   /* We don't check for (*str != '\0') here because we want to parse
1165      any trailing fake arguments in the syntax string.  */
1166   syn = CGEN_SYNTAX_STRING (syntax);
1167
1168   /* Mnemonics come first for now, ensure valid string.  */
1169   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
1170     abort ();
1171
1172   ++syn;
1173
1174   while (* syn != 0)
1175     {
1176       /* Non operand chars must match exactly.  */
1177       if (CGEN_SYNTAX_CHAR_P (* syn))
1178         {
1179           /* FIXME: While we allow for non-GAS callers above, we assume the
1180              first char after the mnemonic part is a space.  */
1181           /* FIXME: We also take inappropriate advantage of the fact that
1182              GAS's input scrubber will remove extraneous blanks.  */
1183           if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
1184             {
1185 #ifdef CGEN_MNEMONIC_OPERANDS
1186               if (CGEN_SYNTAX_CHAR(* syn) == ' ')
1187                 past_opcode_p = 1;
1188 #endif
1189               ++ syn;
1190               ++ str;
1191             }
1192           else if (*str)
1193             {
1194               /* Syntax char didn't match.  Can't be this insn.  */
1195               static char msg [80];
1196
1197               /* xgettext:c-format */
1198               sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
1199                        CGEN_SYNTAX_CHAR(*syn), *str);
1200               return msg;
1201             }
1202           else
1203             {
1204               /* Ran out of input.  */
1205               static char msg [80];
1206
1207               /* xgettext:c-format */
1208               sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
1209                        CGEN_SYNTAX_CHAR(*syn));
1210               return msg;
1211             }
1212           continue;
1213         }
1214
1215       /* We have an operand of some sort.  */
1216       errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn),
1217                                           &str, fields);
1218       if (errmsg)
1219         return errmsg;
1220
1221       /* Done with this operand, continue with next one.  */
1222       ++ syn;
1223     }
1224
1225   /* If we're at the end of the syntax string, we're done.  */
1226   if (* syn == 0)
1227     {
1228       /* FIXME: For the moment we assume a valid `str' can only contain
1229          blanks now.  IE: We needn't try again with a longer version of
1230          the insn and it is assumed that longer versions of insns appear
1231          before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
1232       while (ISSPACE (* str))
1233         ++ str;
1234
1235       if (* str != '\0')
1236         return _("junk at end of line"); /* FIXME: would like to include `str' */
1237
1238       return NULL;
1239     }
1240
1241   /* We couldn't parse it.  */
1242   return _("unrecognized instruction");
1243 }
1244 \f
1245 /* Main entry point.
1246    This routine is called for each instruction to be assembled.
1247    STR points to the insn to be assembled.
1248    We assume all necessary tables have been initialized.
1249    The assembled instruction, less any fixups, is stored in BUF.
1250    Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
1251    still needs to be converted to target byte order, otherwise BUF is an array
1252    of bytes in target byte order.
1253    The result is a pointer to the insn's entry in the opcode table,
1254    or NULL if an error occured (an error message will have already been
1255    printed).
1256
1257    Note that when processing (non-alias) macro-insns,
1258    this function recurses.
1259
1260    ??? It's possible to make this cpu-independent.
1261    One would have to deal with a few minor things.
1262    At this point in time doing so would be more of a curiosity than useful
1263    [for example this file isn't _that_ big], but keeping the possibility in
1264    mind helps keep the design clean.  */
1265
1266 const CGEN_INSN *
1267 frv_cgen_assemble_insn (CGEN_CPU_DESC cd,
1268                            const char *str,
1269                            CGEN_FIELDS *fields,
1270                            CGEN_INSN_BYTES_PTR buf,
1271                            char **errmsg)
1272 {
1273   const char *start;
1274   CGEN_INSN_LIST *ilist;
1275   const char *parse_errmsg = NULL;
1276   const char *insert_errmsg = NULL;
1277   int recognized_mnemonic = 0;
1278
1279   /* Skip leading white space.  */
1280   while (ISSPACE (* str))
1281     ++ str;
1282
1283   /* The instructions are stored in hashed lists.
1284      Get the first in the list.  */
1285   ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
1286
1287   /* Keep looking until we find a match.  */
1288   start = str;
1289   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
1290     {
1291       const CGEN_INSN *insn = ilist->insn;
1292       recognized_mnemonic = 1;
1293
1294 #ifdef CGEN_VALIDATE_INSN_SUPPORTED 
1295       /* Not usually needed as unsupported opcodes
1296          shouldn't be in the hash lists.  */
1297       /* Is this insn supported by the selected cpu?  */
1298       if (! frv_cgen_insn_supported (cd, insn))
1299         continue;
1300 #endif
1301       /* If the RELAXED attribute is set, this is an insn that shouldn't be
1302          chosen immediately.  Instead, it is used during assembler/linker
1303          relaxation if possible.  */
1304       if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
1305         continue;
1306
1307       str = start;
1308
1309       /* Skip this insn if str doesn't look right lexically.  */
1310       if (CGEN_INSN_RX (insn) != NULL &&
1311           regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
1312         continue;
1313
1314       /* Allow parse/insert handlers to obtain length of insn.  */
1315       CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
1316
1317       parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
1318       if (parse_errmsg != NULL)
1319         continue;
1320
1321       /* ??? 0 is passed for `pc'.  */
1322       insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
1323                                                  (bfd_vma) 0);
1324       if (insert_errmsg != NULL)
1325         continue;
1326
1327       /* It is up to the caller to actually output the insn and any
1328          queued relocs.  */
1329       return insn;
1330     }
1331
1332   {
1333     static char errbuf[150];
1334 #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
1335     const char *tmp_errmsg;
1336
1337     /* If requesting verbose error messages, use insert_errmsg.
1338        Failing that, use parse_errmsg.  */
1339     tmp_errmsg = (insert_errmsg ? insert_errmsg :
1340                   parse_errmsg ? parse_errmsg :
1341                   recognized_mnemonic ?
1342                   _("unrecognized form of instruction") :
1343                   _("unrecognized instruction"));
1344
1345     if (strlen (start) > 50)
1346       /* xgettext:c-format */
1347       sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
1348     else 
1349       /* xgettext:c-format */
1350       sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
1351 #else
1352     if (strlen (start) > 50)
1353       /* xgettext:c-format */
1354       sprintf (errbuf, _("bad instruction `%.50s...'"), start);
1355     else 
1356       /* xgettext:c-format */
1357       sprintf (errbuf, _("bad instruction `%.50s'"), start);
1358 #endif
1359       
1360     *errmsg = errbuf;
1361     return NULL;
1362   }
1363 }
1364 \f
1365 #if 0 /* This calls back to GAS which we can't do without care.  */
1366
1367 /* Record each member of OPVALS in the assembler's symbol table.
1368    This lets GAS parse registers for us.
1369    ??? Interesting idea but not currently used.  */
1370
1371 /* Record each member of OPVALS in the assembler's symbol table.
1372    FIXME: Not currently used.  */
1373
1374 void
1375 frv_cgen_asm_hash_keywords (CGEN_CPU_DESC cd, CGEN_KEYWORD *opvals)
1376 {
1377   CGEN_KEYWORD_SEARCH search = cgen_keyword_search_init (opvals, NULL);
1378   const CGEN_KEYWORD_ENTRY * ke;
1379
1380   while ((ke = cgen_keyword_search_next (& search)) != NULL)
1381     {
1382 #if 0 /* Unnecessary, should be done in the search routine.  */
1383       if (! frv_cgen_opval_supported (ke))
1384         continue;
1385 #endif
1386       cgen_asm_record_register (cd, ke->name, ke->value);
1387     }
1388 }
1389
1390 #endif /* 0 */