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