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