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