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
46static const char * parse_insn_normal
47  (CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *);
48
49/* -- assembler routines inserted here.  */
50
51/* -- asm.c */
52inline static const char *
53parse_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
75static const char *
76parse_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
114static const char *
115parse_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
153static const char *
154parse_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
192static const char *
193parse_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
318static const char *
319parse_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
444static const char *
445parse_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
577static long
578parse_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
592static const char *
593parse_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
629static const char *
630parse_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
742static const char *
743parse_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
858static const char *
859parse_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
890static const char *
891parse_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
912static const char *
913parse_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
921static const char *
922parse_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
930static const char *
931parse_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
950static const char *
951parse_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
983const 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
999const char *
1000frv_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
1269cgen_parse_fn * const frv_cgen_parse_handlers[] =
1270{
1271  parse_insn_normal,
1272};
1273
1274void
1275frv_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
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
1296char *
1297frv_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
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
1419static const char *
1420parse_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
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
1560const CGEN_INSN *
1561frv_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}
1658