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