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