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-2024 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 
50 /* -- assembler routines inserted here.  */
51 
52 /* -- asm.c */
53 inline static const char *
parse_symbolic_address(CGEN_CPU_DESC cd,const char ** strp,int opindex,int opinfo,enum cgen_parse_operand_result * resultp,bfd_vma * valuep)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 *
parse_ldd_annotation(CGEN_CPU_DESC cd,const char ** strp,int opindex,unsigned long * valuep)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 *
parse_call_annotation(CGEN_CPU_DESC cd,const char ** strp,int opindex,unsigned long * valuep)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 *
parse_ld_annotation(CGEN_CPU_DESC cd,const char ** strp,int opindex,unsigned long * valuep)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 *
parse_ulo16(CGEN_CPU_DESC cd,const char ** strp,int opindex,unsigned long * valuep)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 *
parse_uslo16(CGEN_CPU_DESC cd,const char ** strp,int opindex,signed long * valuep)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 *
parse_uhi16(CGEN_CPU_DESC cd,const char ** strp,int opindex,unsigned long * valuep)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
parse_register_number(const char ** strp)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 *
parse_spr(CGEN_CPU_DESC cd,const char ** strp,CGEN_KEYWORD * table,long * valuep)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 *
parse_d12(CGEN_CPU_DESC cd,const char ** strp,int opindex,long * valuep)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 *
parse_s12(CGEN_CPU_DESC cd,const char ** strp,int opindex,long * valuep)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 *
parse_u12(CGEN_CPU_DESC cd,const char ** strp,int opindex,long * valuep)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 *
parse_A(CGEN_CPU_DESC cd,const char ** strp,int opindex,unsigned long * valuep,unsigned long A)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 *
parse_A0(CGEN_CPU_DESC cd,const char ** strp,int opindex,unsigned long * valuep)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 *
parse_A1(CGEN_CPU_DESC cd,const char ** strp,int opindex,unsigned long * valuep)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 *
parse_even_register(CGEN_CPU_DESC cd,const char ** strP,CGEN_KEYWORD * tableP,long * valueP)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 *
parse_call_label(CGEN_CPU_DESC cd,const char ** strp,int opindex,int opinfo,enum cgen_parse_operand_result * resultp,bfd_vma * valuep)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 *
frv_cgen_parse_operand(CGEN_CPU_DESC cd,int opindex,const char ** strp,CGEN_FIELDS * fields)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
frv_cgen_init_asm(CGEN_CPU_DESC cd)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 
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 *
frv_cgen_build_insn_regex(CGEN_INSN * insn)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 
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 *
parse_insn_normal(CGEN_CPU_DESC cd,const CGEN_INSN * insn,const char ** strp,CGEN_FIELDS * fields)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 
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 *
frv_cgen_assemble_insn(CGEN_CPU_DESC cd,const char * str,CGEN_FIELDS * fields,CGEN_INSN_BYTES_PTR buf,char ** errmsg)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 }
1674