include/opcode/
[platform/upstream/binutils.git] / opcodes / frv-asm.c
1 /* Assembler interface for targets using CGEN. -*- C -*-
2    CGEN: Cpu tools GENerator
3
4    THIS FILE IS MACHINE GENERATED WITH CGEN.
5    - the resultant file is machine generated, cgen-asm.in isn't
6
7    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2005, 2007, 2008, 2010
8    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       fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
1264       abort ();
1265   }
1266
1267   return errmsg;
1268 }
1269
1270 cgen_parse_fn * const frv_cgen_parse_handlers[] = 
1271 {
1272   parse_insn_normal,
1273 };
1274
1275 void
1276 frv_cgen_init_asm (CGEN_CPU_DESC cd)
1277 {
1278   frv_cgen_init_opcode_table (cd);
1279   frv_cgen_init_ibld_table (cd);
1280   cd->parse_handlers = & frv_cgen_parse_handlers[0];
1281   cd->parse_operand = frv_cgen_parse_operand;
1282 #ifdef CGEN_ASM_INIT_HOOK
1283 CGEN_ASM_INIT_HOOK
1284 #endif
1285 }
1286
1287 \f
1288
1289 /* Regex construction routine.
1290
1291    This translates an opcode syntax string into a regex string,
1292    by replacing any non-character syntax element (such as an
1293    opcode) with the pattern '.*'
1294
1295    It then compiles the regex and stores it in the opcode, for
1296    later use by frv_cgen_assemble_insn
1297
1298    Returns NULL for success, an error message for failure.  */
1299
1300 char * 
1301 frv_cgen_build_insn_regex (CGEN_INSN *insn)
1302 {  
1303   CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
1304   const char *mnem = CGEN_INSN_MNEMONIC (insn);
1305   char rxbuf[CGEN_MAX_RX_ELEMENTS];
1306   char *rx = rxbuf;
1307   const CGEN_SYNTAX_CHAR_TYPE *syn;
1308   int reg_err;
1309
1310   syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
1311
1312   /* Mnemonics come first in the syntax string.  */
1313   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
1314     return _("missing mnemonic in syntax string");
1315   ++syn;
1316
1317   /* Generate a case sensitive regular expression that emulates case
1318      insensitive matching in the "C" locale.  We cannot generate a case
1319      insensitive regular expression because in Turkish locales, 'i' and 'I'
1320      are not equal modulo case conversion.  */
1321
1322   /* Copy the literal mnemonic out of the insn.  */
1323   for (; *mnem; mnem++)
1324     {
1325       char c = *mnem;
1326
1327       if (ISALPHA (c))
1328         {
1329           *rx++ = '[';
1330           *rx++ = TOLOWER (c);
1331           *rx++ = TOUPPER (c);
1332           *rx++ = ']';
1333         }
1334       else
1335         *rx++ = c;
1336     }
1337
1338   /* Copy any remaining literals from the syntax string into the rx.  */
1339   for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
1340     {
1341       if (CGEN_SYNTAX_CHAR_P (* syn)) 
1342         {
1343           char c = CGEN_SYNTAX_CHAR (* syn);
1344
1345           switch (c) 
1346             {
1347               /* Escape any regex metacharacters in the syntax.  */
1348             case '.': case '[': case '\\': 
1349             case '*': case '^': case '$': 
1350
1351 #ifdef CGEN_ESCAPE_EXTENDED_REGEX
1352             case '?': case '{': case '}': 
1353             case '(': case ')': case '*':
1354             case '|': case '+': case ']':
1355 #endif
1356               *rx++ = '\\';
1357               *rx++ = c;
1358               break;
1359
1360             default:
1361               if (ISALPHA (c))
1362                 {
1363                   *rx++ = '[';
1364                   *rx++ = TOLOWER (c);
1365                   *rx++ = TOUPPER (c);
1366                   *rx++ = ']';
1367                 }
1368               else
1369                 *rx++ = c;
1370               break;
1371             }
1372         }
1373       else
1374         {
1375           /* Replace non-syntax fields with globs.  */
1376           *rx++ = '.';
1377           *rx++ = '*';
1378         }
1379     }
1380
1381   /* Trailing whitespace ok.  */
1382   * rx++ = '['; 
1383   * rx++ = ' '; 
1384   * rx++ = '\t'; 
1385   * rx++ = ']'; 
1386   * rx++ = '*'; 
1387
1388   /* But anchor it after that.  */
1389   * rx++ = '$'; 
1390   * rx = '\0';
1391
1392   CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
1393   reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
1394
1395   if (reg_err == 0) 
1396     return NULL;
1397   else
1398     {
1399       static char msg[80];
1400
1401       regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
1402       regfree ((regex_t *) CGEN_INSN_RX (insn));
1403       free (CGEN_INSN_RX (insn));
1404       (CGEN_INSN_RX (insn)) = NULL;
1405       return msg;
1406     }
1407 }
1408
1409 \f
1410 /* Default insn parser.
1411
1412    The syntax string is scanned and operands are parsed and stored in FIELDS.
1413    Relocs are queued as we go via other callbacks.
1414
1415    ??? Note that this is currently an all-or-nothing parser.  If we fail to
1416    parse the instruction, we return 0 and the caller will start over from
1417    the beginning.  Backtracking will be necessary in parsing subexpressions,
1418    but that can be handled there.  Not handling backtracking here may get
1419    expensive in the case of the m68k.  Deal with later.
1420
1421    Returns NULL for success, an error message for failure.  */
1422
1423 static const char *
1424 parse_insn_normal (CGEN_CPU_DESC cd,
1425                    const CGEN_INSN *insn,
1426                    const char **strp,
1427                    CGEN_FIELDS *fields)
1428 {
1429   /* ??? Runtime added insns not handled yet.  */
1430   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
1431   const char *str = *strp;
1432   const char *errmsg;
1433   const char *p;
1434   const CGEN_SYNTAX_CHAR_TYPE * syn;
1435 #ifdef CGEN_MNEMONIC_OPERANDS
1436   /* FIXME: wip */
1437   int past_opcode_p;
1438 #endif
1439
1440   /* For now we assume the mnemonic is first (there are no leading operands).
1441      We can parse it without needing to set up operand parsing.
1442      GAS's input scrubber will ensure mnemonics are lowercase, but we may
1443      not be called from GAS.  */
1444   p = CGEN_INSN_MNEMONIC (insn);
1445   while (*p && TOLOWER (*p) == TOLOWER (*str))
1446     ++p, ++str;
1447
1448   if (* p)
1449     return _("unrecognized instruction");
1450
1451 #ifndef CGEN_MNEMONIC_OPERANDS
1452   if (* str && ! ISSPACE (* str))
1453     return _("unrecognized instruction");
1454 #endif
1455
1456   CGEN_INIT_PARSE (cd);
1457   cgen_init_parse_operand (cd);
1458 #ifdef CGEN_MNEMONIC_OPERANDS
1459   past_opcode_p = 0;
1460 #endif
1461
1462   /* We don't check for (*str != '\0') here because we want to parse
1463      any trailing fake arguments in the syntax string.  */
1464   syn = CGEN_SYNTAX_STRING (syntax);
1465
1466   /* Mnemonics come first for now, ensure valid string.  */
1467   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
1468     abort ();
1469
1470   ++syn;
1471
1472   while (* syn != 0)
1473     {
1474       /* Non operand chars must match exactly.  */
1475       if (CGEN_SYNTAX_CHAR_P (* syn))
1476         {
1477           /* FIXME: While we allow for non-GAS callers above, we assume the
1478              first char after the mnemonic part is a space.  */
1479           /* FIXME: We also take inappropriate advantage of the fact that
1480              GAS's input scrubber will remove extraneous blanks.  */
1481           if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
1482             {
1483 #ifdef CGEN_MNEMONIC_OPERANDS
1484               if (CGEN_SYNTAX_CHAR(* syn) == ' ')
1485                 past_opcode_p = 1;
1486 #endif
1487               ++ syn;
1488               ++ str;
1489             }
1490           else if (*str)
1491             {
1492               /* Syntax char didn't match.  Can't be this insn.  */
1493               static char msg [80];
1494
1495               /* xgettext:c-format */
1496               sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
1497                        CGEN_SYNTAX_CHAR(*syn), *str);
1498               return msg;
1499             }
1500           else
1501             {
1502               /* Ran out of input.  */
1503               static char msg [80];
1504
1505               /* xgettext:c-format */
1506               sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
1507                        CGEN_SYNTAX_CHAR(*syn));
1508               return msg;
1509             }
1510           continue;
1511         }
1512
1513 #ifdef CGEN_MNEMONIC_OPERANDS
1514       (void) past_opcode_p;
1515 #endif
1516       /* We have an operand of some sort.  */
1517       errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn), &str, fields);
1518       if (errmsg)
1519         return errmsg;
1520
1521       /* Done with this operand, continue with next one.  */
1522       ++ syn;
1523     }
1524
1525   /* If we're at the end of the syntax string, we're done.  */
1526   if (* syn == 0)
1527     {
1528       /* FIXME: For the moment we assume a valid `str' can only contain
1529          blanks now.  IE: We needn't try again with a longer version of
1530          the insn and it is assumed that longer versions of insns appear
1531          before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
1532       while (ISSPACE (* str))
1533         ++ str;
1534
1535       if (* str != '\0')
1536         return _("junk at end of line"); /* FIXME: would like to include `str' */
1537
1538       return NULL;
1539     }
1540
1541   /* We couldn't parse it.  */
1542   return _("unrecognized instruction");
1543 }
1544 \f
1545 /* Main entry point.
1546    This routine is called for each instruction to be assembled.
1547    STR points to the insn to be assembled.
1548    We assume all necessary tables have been initialized.
1549    The assembled instruction, less any fixups, is stored in BUF.
1550    Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
1551    still needs to be converted to target byte order, otherwise BUF is an array
1552    of bytes in target byte order.
1553    The result is a pointer to the insn's entry in the opcode table,
1554    or NULL if an error occured (an error message will have already been
1555    printed).
1556
1557    Note that when processing (non-alias) macro-insns,
1558    this function recurses.
1559
1560    ??? It's possible to make this cpu-independent.
1561    One would have to deal with a few minor things.
1562    At this point in time doing so would be more of a curiosity than useful
1563    [for example this file isn't _that_ big], but keeping the possibility in
1564    mind helps keep the design clean.  */
1565
1566 const CGEN_INSN *
1567 frv_cgen_assemble_insn (CGEN_CPU_DESC cd,
1568                            const char *str,
1569                            CGEN_FIELDS *fields,
1570                            CGEN_INSN_BYTES_PTR buf,
1571                            char **errmsg)
1572 {
1573   const char *start;
1574   CGEN_INSN_LIST *ilist;
1575   const char *parse_errmsg = NULL;
1576   const char *insert_errmsg = NULL;
1577   int recognized_mnemonic = 0;
1578
1579   /* Skip leading white space.  */
1580   while (ISSPACE (* str))
1581     ++ str;
1582
1583   /* The instructions are stored in hashed lists.
1584      Get the first in the list.  */
1585   ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
1586
1587   /* Keep looking until we find a match.  */
1588   start = str;
1589   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
1590     {
1591       const CGEN_INSN *insn = ilist->insn;
1592       recognized_mnemonic = 1;
1593
1594 #ifdef CGEN_VALIDATE_INSN_SUPPORTED 
1595       /* Not usually needed as unsupported opcodes
1596          shouldn't be in the hash lists.  */
1597       /* Is this insn supported by the selected cpu?  */
1598       if (! frv_cgen_insn_supported (cd, insn))
1599         continue;
1600 #endif
1601       /* If the RELAXED attribute is set, this is an insn that shouldn't be
1602          chosen immediately.  Instead, it is used during assembler/linker
1603          relaxation if possible.  */
1604       if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
1605         continue;
1606
1607       str = start;
1608
1609       /* Skip this insn if str doesn't look right lexically.  */
1610       if (CGEN_INSN_RX (insn) != NULL &&
1611           regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
1612         continue;
1613
1614       /* Allow parse/insert handlers to obtain length of insn.  */
1615       CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
1616
1617       parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
1618       if (parse_errmsg != NULL)
1619         continue;
1620
1621       /* ??? 0 is passed for `pc'.  */
1622       insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
1623                                                  (bfd_vma) 0);
1624       if (insert_errmsg != NULL)
1625         continue;
1626
1627       /* It is up to the caller to actually output the insn and any
1628          queued relocs.  */
1629       return insn;
1630     }
1631
1632   {
1633     static char errbuf[150];
1634     const char *tmp_errmsg;
1635 #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
1636 #define be_verbose 1
1637 #else
1638 #define be_verbose 0
1639 #endif
1640
1641     if (be_verbose)
1642       {
1643         /* If requesting verbose error messages, use insert_errmsg.
1644            Failing that, use parse_errmsg.  */
1645         tmp_errmsg = (insert_errmsg ? insert_errmsg :
1646                       parse_errmsg ? parse_errmsg :
1647                       recognized_mnemonic ?
1648                       _("unrecognized form of instruction") :
1649                       _("unrecognized instruction"));
1650
1651         if (strlen (start) > 50)
1652           /* xgettext:c-format */
1653           sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
1654         else 
1655           /* xgettext:c-format */
1656           sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
1657       }
1658     else
1659       {
1660         if (strlen (start) > 50)
1661           /* xgettext:c-format */
1662           sprintf (errbuf, _("bad instruction `%.50s...'"), start);
1663         else 
1664           /* xgettext:c-format */
1665           sprintf (errbuf, _("bad instruction `%.50s'"), start);
1666       }
1667       
1668     *errmsg = errbuf;
1669     return NULL;
1670   }
1671 }