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