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