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