OSDN Git Service

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