xref: /netbsd-src/external/gpl3/binutils.old/dist/opcodes/or1k-asm.c (revision cef8759bd76c1b621f8eab8faa6f208faabc2e15)
1 /* DO NOT EDIT!  -*- buffer-read-only: t -*- vi:set ro:  */
2 /* Assembler interface for targets using CGEN. -*- C -*-
3    CGEN: Cpu tools GENerator
4 
5    THIS FILE IS MACHINE GENERATED WITH CGEN.
6    - the resultant file is machine generated, cgen-asm.in isn't
7 
8    Copyright (C) 1996-2018 Free Software Foundation, Inc.
9 
10    This file is part of libopcodes.
11 
12    This library is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 3, or (at your option)
15    any later version.
16 
17    It is distributed in the hope that it will be useful, but WITHOUT
18    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
20    License for more details.
21 
22    You should have received a copy of the GNU General Public License
23    along with this program; if not, write to the Free Software Foundation, Inc.,
24    51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
25 
26 
27 /* ??? Eventually more and more of this stuff can go to cpu-independent files.
28    Keep that in mind.  */
29 
30 #include "sysdep.h"
31 #include <stdio.h>
32 #include "ansidecl.h"
33 #include "bfd.h"
34 #include "symcat.h"
35 #include "or1k-desc.h"
36 #include "or1k-opc.h"
37 #include "opintl.h"
38 #include "xregex.h"
39 #include "libiberty.h"
40 #include "safe-ctype.h"
41 
42 #undef  min
43 #define min(a,b) ((a) < (b) ? (a) : (b))
44 #undef  max
45 #define max(a,b) ((a) > (b) ? (a) : (b))
46 
47 static const char * parse_insn_normal
48   (CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *);
49 
50 /* -- assembler routines inserted here.  */
51 
52 /* -- asm.c */
53 
54 static const char * MISSING_CLOSING_PARENTHESIS = N_("missing `)'");
55 
56 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
57 
58 static const char *
59 parse_disp26 (CGEN_CPU_DESC cd,
60 	      const char ** strp,
61 	      int opindex,
62 	      int opinfo,
63 	      enum cgen_parse_operand_result * resultp,
64 	      bfd_vma * valuep)
65 {
66   const char *errmsg = NULL;
67   enum cgen_parse_operand_result result_type;
68 
69   if (strncasecmp (*strp, "plt(", 4) == 0)
70     {
71       bfd_vma value;
72 
73       *strp += 4;
74       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_OR1K_PLT26,
75 				   & result_type, & value);
76       if (**strp != ')')
77 	return MISSING_CLOSING_PARENTHESIS;
78       ++*strp;
79       if (errmsg == NULL
80 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
81 	value = (value >> 2) & 0xffff;
82       *valuep = value;
83       return errmsg;
84     }
85   return cgen_parse_address (cd, strp, opindex, opinfo, resultp, valuep);
86 }
87 
88 static const char *
89 parse_simm16 (CGEN_CPU_DESC cd, const char ** strp, int opindex, long * valuep)
90 {
91   const char *errmsg;
92   enum cgen_parse_operand_result result_type;
93   long ret;
94 
95   if (**strp == '#')
96     ++*strp;
97 
98   if (strncasecmp (*strp, "hi(", 3) == 0)
99     {
100       bfd_vma value;
101 
102       *strp += 3;
103       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16,
104 				   & result_type, & value);
105       if (**strp != ')')
106 	errmsg = MISSING_CLOSING_PARENTHESIS;
107       ++*strp;
108 
109       ret = value;
110 
111       if (errmsg == NULL
112 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
113 	{
114 	  ret >>= 16;
115 	  ret &= 0xffff;
116 	  ret = (ret ^ 0x8000) - 0x8000;
117 	}
118     }
119   else if (strncasecmp (*strp, "lo(", 3) == 0)
120     {
121       bfd_vma value;
122 
123       *strp += 3;
124       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
125 				   & result_type, & value);
126       if (**strp != ')')
127 	return MISSING_CLOSING_PARENTHESIS;
128       ++*strp;
129 
130       ret = value;
131 
132       if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
133 	{
134 	  ret &= 0xffff;
135 	  ret = (ret ^ 0x8000) - 0x8000;
136 	}
137     }
138   else if (strncasecmp (*strp, "got(", 4) == 0)
139     {
140       bfd_vma value;
141 
142       *strp += 4;
143       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_OR1K_GOT16,
144 				   & result_type, & value);
145       if (**strp != ')')
146 	return MISSING_CLOSING_PARENTHESIS;
147       ++*strp;
148       if (errmsg == NULL
149 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
150 	value &= 0xffff;
151       *valuep = value;
152       return errmsg;
153     }
154   else if (strncasecmp (*strp, "gotpchi(", 8) == 0)
155     {
156       bfd_vma value;
157 
158       *strp += 8;
159       errmsg = cgen_parse_address (cd, strp, opindex,
160 				   BFD_RELOC_OR1K_GOTPC_HI16,
161 				   & result_type, & value);
162       if (**strp != ')')
163 	return MISSING_CLOSING_PARENTHESIS;
164       ++*strp;
165       if (errmsg == NULL
166 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
167 	value = (value >> 16) & 0xffff;
168       *valuep = value;
169       return errmsg;
170     }
171   else if (strncasecmp (*strp, "gotpclo(", 8) == 0)
172     {
173       bfd_vma value;
174 
175       *strp += 8;
176       errmsg = cgen_parse_address (cd, strp, opindex,
177 				   BFD_RELOC_OR1K_GOTPC_LO16,
178 				   &result_type, &value);
179       if (**strp != ')')
180 	return MISSING_CLOSING_PARENTHESIS;
181       ++*strp;
182       if (errmsg == NULL
183 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
184 	value &= 0xffff;
185       *valuep = value;
186       return errmsg;
187     }
188   else if (strncasecmp (*strp, "gotoffhi(", 9) == 0)
189     {
190       bfd_vma value;
191 
192       *strp += 9;
193       errmsg = cgen_parse_address (cd, strp, opindex,
194 				   BFD_RELOC_OR1K_GOTOFF_HI16,
195 				   & result_type, & value);
196 
197       if (**strp != ')')
198 	return MISSING_CLOSING_PARENTHESIS;
199       ++*strp;
200       if (errmsg == NULL
201 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
202 	value = (value >> 16) & 0xffff;
203       *valuep = value;
204       return errmsg;
205     }
206   else if (strncasecmp (*strp, "gotofflo(", 9) == 0)
207     {
208       bfd_vma value;
209 
210       *strp += 9;
211       errmsg = cgen_parse_address (cd, strp, opindex,
212 				   BFD_RELOC_OR1K_GOTOFF_LO16,
213 				   &result_type, &value);
214       if (**strp != ')')
215 	return MISSING_CLOSING_PARENTHESIS;
216       ++*strp;
217       if (errmsg == NULL
218 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
219 	value &= 0xffff;
220       *valuep = value;
221       return errmsg;
222     }
223   else if (strncasecmp (*strp, "tlsgdhi(", 8) == 0)
224     {
225       bfd_vma value;
226 
227       *strp += 8;
228       errmsg = cgen_parse_address (cd, strp, opindex,
229 				   BFD_RELOC_OR1K_TLS_GD_HI16,
230 				   & result_type, & value);
231 
232       if (**strp != ')')
233 	return MISSING_CLOSING_PARENTHESIS;
234       ++*strp;
235       if (errmsg == NULL
236 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
237 	value = (value >> 16) & 0xffff;
238       *valuep = value;
239       return errmsg;
240     }
241   else if (strncasecmp (*strp, "tlsgdlo(", 8) == 0)
242     {
243       bfd_vma value;
244 
245       *strp += 8;
246       errmsg = cgen_parse_address (cd, strp, opindex,
247 				   BFD_RELOC_OR1K_TLS_GD_LO16,
248 				   &result_type, &value);
249       if (**strp != ')')
250 	return MISSING_CLOSING_PARENTHESIS;
251       ++*strp;
252       if (errmsg == NULL
253 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
254 	value &= 0xffff;
255       *valuep = value;
256       return errmsg;
257     }
258   else if (strncasecmp (*strp, "tlsldmhi(", 9) == 0)
259     {
260       bfd_vma value;
261 
262       *strp += 9;
263       errmsg = cgen_parse_address (cd, strp, opindex,
264 				   BFD_RELOC_OR1K_TLS_LDM_HI16,
265 				   & result_type, & value);
266 
267       if (**strp != ')')
268 	return MISSING_CLOSING_PARENTHESIS;
269       ++*strp;
270       if (errmsg == NULL
271 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
272 	value = (value >> 16) & 0xffff;
273       *valuep = value;
274       return errmsg;
275     }
276   else if (strncasecmp (*strp, "tlsldmlo(", 9) == 0)
277     {
278       bfd_vma value;
279 
280       *strp += 9;
281       errmsg = cgen_parse_address (cd, strp, opindex,
282 				   BFD_RELOC_OR1K_TLS_LDM_LO16,
283 				   &result_type, &value);
284       if (**strp != ')')
285 	return MISSING_CLOSING_PARENTHESIS;
286       ++*strp;
287       if (errmsg == NULL
288 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
289 	value &= 0xffff;
290       *valuep = value;
291       return errmsg;
292     }
293   else if (strncasecmp (*strp, "dtpoffhi(", 9) == 0)
294     {
295       bfd_vma value;
296 
297       *strp += 9;
298       errmsg = cgen_parse_address (cd, strp, opindex,
299 				   BFD_RELOC_OR1K_TLS_LDO_HI16,
300 				   & result_type, & value);
301 
302       if (**strp != ')')
303 	return MISSING_CLOSING_PARENTHESIS;
304       ++*strp;
305       if (errmsg == NULL
306 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
307 	value = (value >> 16) & 0xffff;
308       *valuep = value;
309       return errmsg;
310     }
311   else if (strncasecmp (*strp, "dtpofflo(", 9) == 0)
312     {
313       bfd_vma value;
314 
315       *strp += 9;
316       errmsg = cgen_parse_address (cd, strp, opindex,
317 				   BFD_RELOC_OR1K_TLS_LDO_LO16,
318 				   &result_type, &value);
319       if (**strp != ')')
320 	return MISSING_CLOSING_PARENTHESIS;
321       ++*strp;
322       if (errmsg == NULL
323 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
324 	value &= 0xffff;
325       *valuep = value;
326       return errmsg;
327     }
328   else if (strncasecmp (*strp, "gottpoffhi(", 11) == 0)
329     {
330       bfd_vma value;
331 
332       *strp += 11;
333       errmsg = cgen_parse_address (cd, strp, opindex,
334 				   BFD_RELOC_OR1K_TLS_IE_HI16,
335 				   & result_type, & value);
336 
337       if (**strp != ')')
338 	return MISSING_CLOSING_PARENTHESIS;
339       ++*strp;
340       if (errmsg == NULL
341 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
342 	value = (value >> 16) & 0xffff;
343       *valuep = value;
344       return errmsg;
345     }
346   else if (strncasecmp (*strp, "gottpofflo(", 11) == 0)
347     {
348       bfd_vma value;
349 
350       *strp += 11;
351       errmsg = cgen_parse_address (cd, strp, opindex,
352 				   BFD_RELOC_OR1K_TLS_IE_LO16,
353 				   &result_type, &value);
354       if (**strp != ')')
355 	return MISSING_CLOSING_PARENTHESIS;
356       ++*strp;
357       if (errmsg == NULL
358 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
359 	value &= 0xffff;
360       *valuep = value;
361       return errmsg;
362     }
363   else if (strncasecmp (*strp, "tpoffhi(", 8) == 0)
364     {
365       bfd_vma value;
366 
367       *strp += 8;
368       errmsg = cgen_parse_address (cd, strp, opindex,
369 				   BFD_RELOC_OR1K_TLS_LE_HI16,
370 				   & result_type, & value);
371 
372       if (**strp != ')')
373 	return MISSING_CLOSING_PARENTHESIS;
374       ++*strp;
375       if (errmsg == NULL
376 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
377 	value = (value >> 16) & 0xffff;
378       *valuep = value;
379       return errmsg;
380     }
381   else if (strncasecmp (*strp, "tpofflo(", 8) == 0)
382     {
383       bfd_vma value;
384 
385       *strp += 8;
386       errmsg = cgen_parse_address (cd, strp, opindex,
387 				   BFD_RELOC_OR1K_TLS_LE_LO16,
388 				   &result_type, &value);
389       if (**strp != ')')
390 	return MISSING_CLOSING_PARENTHESIS;
391       ++*strp;
392       if (errmsg == NULL
393 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
394 	value &= 0xffff;
395       *valuep = value;
396       return errmsg;
397     }
398   else
399     {
400       long value;
401       errmsg = cgen_parse_signed_integer (cd, strp, opindex, &value);
402       ret = value;
403     }
404 
405   if (errmsg == NULL)
406     *valuep = ret;
407 
408   return errmsg;
409 }
410 
411 static const char *
412 parse_uimm16 (CGEN_CPU_DESC cd, const char ** strp, int opindex, unsigned long * valuep)
413 {
414   const char *errmsg = parse_simm16(cd, strp, opindex, (long *) valuep);
415 
416   if (errmsg == NULL)
417     *valuep &= 0xffff;
418   return errmsg;
419 }
420 
421 /* -- */
422 
423 const char * or1k_cgen_parse_operand
424   (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
425 
426 /* Main entry point for operand parsing.
427 
428    This function is basically just a big switch statement.  Earlier versions
429    used tables to look up the function to use, but
430    - if the table contains both assembler and disassembler functions then
431      the disassembler contains much of the assembler and vice-versa,
432    - there's a lot of inlining possibilities as things grow,
433    - using a switch statement avoids the function call overhead.
434 
435    This function could be moved into `parse_insn_normal', but keeping it
436    separate makes clear the interface between `parse_insn_normal' and each of
437    the handlers.  */
438 
439 const char *
440 or1k_cgen_parse_operand (CGEN_CPU_DESC cd,
441 			   int opindex,
442 			   const char ** strp,
443 			   CGEN_FIELDS * fields)
444 {
445   const char * errmsg = NULL;
446   /* Used by scalar operands that still need to be parsed.  */
447   long junk ATTRIBUTE_UNUSED;
448 
449   switch (opindex)
450     {
451     case OR1K_OPERAND_DISP26 :
452       {
453         bfd_vma value = 0;
454         errmsg = parse_disp26 (cd, strp, OR1K_OPERAND_DISP26, 0, NULL,  & value);
455         fields->f_disp26 = value;
456       }
457       break;
458     case OR1K_OPERAND_RA :
459       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r2);
460       break;
461     case OR1K_OPERAND_RADF :
462       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fdr, & fields->f_r1);
463       break;
464     case OR1K_OPERAND_RASF :
465       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r2);
466       break;
467     case OR1K_OPERAND_RB :
468       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r3);
469       break;
470     case OR1K_OPERAND_RBDF :
471       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fdr, & fields->f_r1);
472       break;
473     case OR1K_OPERAND_RBSF :
474       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r3);
475       break;
476     case OR1K_OPERAND_RD :
477       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r1);
478       break;
479     case OR1K_OPERAND_RDDF :
480       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fdr, & fields->f_r1);
481       break;
482     case OR1K_OPERAND_RDSF :
483       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r1);
484       break;
485     case OR1K_OPERAND_SIMM16 :
486       errmsg = parse_simm16 (cd, strp, OR1K_OPERAND_SIMM16, (long *) (& fields->f_simm16));
487       break;
488     case OR1K_OPERAND_SIMM16_SPLIT :
489       errmsg = parse_simm16 (cd, strp, OR1K_OPERAND_SIMM16_SPLIT, (long *) (& fields->f_simm16_split));
490       break;
491     case OR1K_OPERAND_UIMM16 :
492       errmsg = parse_uimm16 (cd, strp, OR1K_OPERAND_UIMM16, (unsigned long *) (& fields->f_uimm16));
493       break;
494     case OR1K_OPERAND_UIMM16_SPLIT :
495       errmsg = parse_uimm16 (cd, strp, OR1K_OPERAND_UIMM16_SPLIT, (unsigned long *) (& fields->f_uimm16_split));
496       break;
497     case OR1K_OPERAND_UIMM6 :
498       errmsg = cgen_parse_unsigned_integer (cd, strp, OR1K_OPERAND_UIMM6, (unsigned long *) (& fields->f_uimm6));
499       break;
500 
501     default :
502       /* xgettext:c-format */
503       opcodes_error_handler
504 	(_("internal error: unrecognized field %d while parsing"),
505 	 opindex);
506       abort ();
507   }
508 
509   return errmsg;
510 }
511 
512 cgen_parse_fn * const or1k_cgen_parse_handlers[] =
513 {
514   parse_insn_normal,
515 };
516 
517 void
518 or1k_cgen_init_asm (CGEN_CPU_DESC cd)
519 {
520   or1k_cgen_init_opcode_table (cd);
521   or1k_cgen_init_ibld_table (cd);
522   cd->parse_handlers = & or1k_cgen_parse_handlers[0];
523   cd->parse_operand = or1k_cgen_parse_operand;
524 #ifdef CGEN_ASM_INIT_HOOK
525 CGEN_ASM_INIT_HOOK
526 #endif
527 }
528 
529 
530 
531 /* Regex construction routine.
532 
533    This translates an opcode syntax string into a regex string,
534    by replacing any non-character syntax element (such as an
535    opcode) with the pattern '.*'
536 
537    It then compiles the regex and stores it in the opcode, for
538    later use by or1k_cgen_assemble_insn
539 
540    Returns NULL for success, an error message for failure.  */
541 
542 char *
543 or1k_cgen_build_insn_regex (CGEN_INSN *insn)
544 {
545   CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
546   const char *mnem = CGEN_INSN_MNEMONIC (insn);
547   char rxbuf[CGEN_MAX_RX_ELEMENTS];
548   char *rx = rxbuf;
549   const CGEN_SYNTAX_CHAR_TYPE *syn;
550   int reg_err;
551 
552   syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
553 
554   /* Mnemonics come first in the syntax string.  */
555   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
556     return _("missing mnemonic in syntax string");
557   ++syn;
558 
559   /* Generate a case sensitive regular expression that emulates case
560      insensitive matching in the "C" locale.  We cannot generate a case
561      insensitive regular expression because in Turkish locales, 'i' and 'I'
562      are not equal modulo case conversion.  */
563 
564   /* Copy the literal mnemonic out of the insn.  */
565   for (; *mnem; mnem++)
566     {
567       char c = *mnem;
568 
569       if (ISALPHA (c))
570 	{
571 	  *rx++ = '[';
572 	  *rx++ = TOLOWER (c);
573 	  *rx++ = TOUPPER (c);
574 	  *rx++ = ']';
575 	}
576       else
577 	*rx++ = c;
578     }
579 
580   /* Copy any remaining literals from the syntax string into the rx.  */
581   for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
582     {
583       if (CGEN_SYNTAX_CHAR_P (* syn))
584 	{
585 	  char c = CGEN_SYNTAX_CHAR (* syn);
586 
587 	  switch (c)
588 	    {
589 	      /* Escape any regex metacharacters in the syntax.  */
590 	    case '.': case '[': case '\\':
591 	    case '*': case '^': case '$':
592 
593 #ifdef CGEN_ESCAPE_EXTENDED_REGEX
594 	    case '?': case '{': case '}':
595 	    case '(': case ')': case '*':
596 	    case '|': case '+': case ']':
597 #endif
598 	      *rx++ = '\\';
599 	      *rx++ = c;
600 	      break;
601 
602 	    default:
603 	      if (ISALPHA (c))
604 		{
605 		  *rx++ = '[';
606 		  *rx++ = TOLOWER (c);
607 		  *rx++ = TOUPPER (c);
608 		  *rx++ = ']';
609 		}
610 	      else
611 		*rx++ = c;
612 	      break;
613 	    }
614 	}
615       else
616 	{
617 	  /* Replace non-syntax fields with globs.  */
618 	  *rx++ = '.';
619 	  *rx++ = '*';
620 	}
621     }
622 
623   /* Trailing whitespace ok.  */
624   * rx++ = '[';
625   * rx++ = ' ';
626   * rx++ = '\t';
627   * rx++ = ']';
628   * rx++ = '*';
629 
630   /* But anchor it after that.  */
631   * rx++ = '$';
632   * rx = '\0';
633 
634   CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
635   reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
636 
637   if (reg_err == 0)
638     return NULL;
639   else
640     {
641       static char msg[80];
642 
643       regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
644       regfree ((regex_t *) CGEN_INSN_RX (insn));
645       free (CGEN_INSN_RX (insn));
646       (CGEN_INSN_RX (insn)) = NULL;
647       return msg;
648     }
649 }
650 
651 
652 /* Default insn parser.
653 
654    The syntax string is scanned and operands are parsed and stored in FIELDS.
655    Relocs are queued as we go via other callbacks.
656 
657    ??? Note that this is currently an all-or-nothing parser.  If we fail to
658    parse the instruction, we return 0 and the caller will start over from
659    the beginning.  Backtracking will be necessary in parsing subexpressions,
660    but that can be handled there.  Not handling backtracking here may get
661    expensive in the case of the m68k.  Deal with later.
662 
663    Returns NULL for success, an error message for failure.  */
664 
665 static const char *
666 parse_insn_normal (CGEN_CPU_DESC cd,
667 		   const CGEN_INSN *insn,
668 		   const char **strp,
669 		   CGEN_FIELDS *fields)
670 {
671   /* ??? Runtime added insns not handled yet.  */
672   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
673   const char *str = *strp;
674   const char *errmsg;
675   const char *p;
676   const CGEN_SYNTAX_CHAR_TYPE * syn;
677 #ifdef CGEN_MNEMONIC_OPERANDS
678   /* FIXME: wip */
679   int past_opcode_p;
680 #endif
681 
682   /* For now we assume the mnemonic is first (there are no leading operands).
683      We can parse it without needing to set up operand parsing.
684      GAS's input scrubber will ensure mnemonics are lowercase, but we may
685      not be called from GAS.  */
686   p = CGEN_INSN_MNEMONIC (insn);
687   while (*p && TOLOWER (*p) == TOLOWER (*str))
688     ++p, ++str;
689 
690   if (* p)
691     return _("unrecognized instruction");
692 
693 #ifndef CGEN_MNEMONIC_OPERANDS
694   if (* str && ! ISSPACE (* str))
695     return _("unrecognized instruction");
696 #endif
697 
698   CGEN_INIT_PARSE (cd);
699   cgen_init_parse_operand (cd);
700 #ifdef CGEN_MNEMONIC_OPERANDS
701   past_opcode_p = 0;
702 #endif
703 
704   /* We don't check for (*str != '\0') here because we want to parse
705      any trailing fake arguments in the syntax string.  */
706   syn = CGEN_SYNTAX_STRING (syntax);
707 
708   /* Mnemonics come first for now, ensure valid string.  */
709   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
710     abort ();
711 
712   ++syn;
713 
714   while (* syn != 0)
715     {
716       /* Non operand chars must match exactly.  */
717       if (CGEN_SYNTAX_CHAR_P (* syn))
718 	{
719 	  /* FIXME: While we allow for non-GAS callers above, we assume the
720 	     first char after the mnemonic part is a space.  */
721 	  /* FIXME: We also take inappropriate advantage of the fact that
722 	     GAS's input scrubber will remove extraneous blanks.  */
723 	  if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
724 	    {
725 #ifdef CGEN_MNEMONIC_OPERANDS
726 	      if (CGEN_SYNTAX_CHAR(* syn) == ' ')
727 		past_opcode_p = 1;
728 #endif
729 	      ++ syn;
730 	      ++ str;
731 	    }
732 	  else if (*str)
733 	    {
734 	      /* Syntax char didn't match.  Can't be this insn.  */
735 	      static char msg [80];
736 
737 	      /* xgettext:c-format */
738 	      sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
739 		       CGEN_SYNTAX_CHAR(*syn), *str);
740 	      return msg;
741 	    }
742 	  else
743 	    {
744 	      /* Ran out of input.  */
745 	      static char msg [80];
746 
747 	      /* xgettext:c-format */
748 	      sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
749 		       CGEN_SYNTAX_CHAR(*syn));
750 	      return msg;
751 	    }
752 	  continue;
753 	}
754 
755 #ifdef CGEN_MNEMONIC_OPERANDS
756       (void) past_opcode_p;
757 #endif
758       /* We have an operand of some sort.  */
759       errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn), &str, fields);
760       if (errmsg)
761 	return errmsg;
762 
763       /* Done with this operand, continue with next one.  */
764       ++ syn;
765     }
766 
767   /* If we're at the end of the syntax string, we're done.  */
768   if (* syn == 0)
769     {
770       /* FIXME: For the moment we assume a valid `str' can only contain
771 	 blanks now.  IE: We needn't try again with a longer version of
772 	 the insn and it is assumed that longer versions of insns appear
773 	 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
774       while (ISSPACE (* str))
775 	++ str;
776 
777       if (* str != '\0')
778 	return _("junk at end of line"); /* FIXME: would like to include `str' */
779 
780       return NULL;
781     }
782 
783   /* We couldn't parse it.  */
784   return _("unrecognized instruction");
785 }
786 
787 /* Main entry point.
788    This routine is called for each instruction to be assembled.
789    STR points to the insn to be assembled.
790    We assume all necessary tables have been initialized.
791    The assembled instruction, less any fixups, is stored in BUF.
792    Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
793    still needs to be converted to target byte order, otherwise BUF is an array
794    of bytes in target byte order.
795    The result is a pointer to the insn's entry in the opcode table,
796    or NULL if an error occured (an error message will have already been
797    printed).
798 
799    Note that when processing (non-alias) macro-insns,
800    this function recurses.
801 
802    ??? It's possible to make this cpu-independent.
803    One would have to deal with a few minor things.
804    At this point in time doing so would be more of a curiosity than useful
805    [for example this file isn't _that_ big], but keeping the possibility in
806    mind helps keep the design clean.  */
807 
808 const CGEN_INSN *
809 or1k_cgen_assemble_insn (CGEN_CPU_DESC cd,
810 			   const char *str,
811 			   CGEN_FIELDS *fields,
812 			   CGEN_INSN_BYTES_PTR buf,
813 			   char **errmsg)
814 {
815   const char *start;
816   CGEN_INSN_LIST *ilist;
817   const char *parse_errmsg = NULL;
818   const char *insert_errmsg = NULL;
819   int recognized_mnemonic = 0;
820 
821   /* Skip leading white space.  */
822   while (ISSPACE (* str))
823     ++ str;
824 
825   /* The instructions are stored in hashed lists.
826      Get the first in the list.  */
827   ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
828 
829   /* Keep looking until we find a match.  */
830   start = str;
831   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
832     {
833       const CGEN_INSN *insn = ilist->insn;
834       recognized_mnemonic = 1;
835 
836 #ifdef CGEN_VALIDATE_INSN_SUPPORTED
837       /* Not usually needed as unsupported opcodes
838 	 shouldn't be in the hash lists.  */
839       /* Is this insn supported by the selected cpu?  */
840       if (! or1k_cgen_insn_supported (cd, insn))
841 	continue;
842 #endif
843       /* If the RELAXED attribute is set, this is an insn that shouldn't be
844 	 chosen immediately.  Instead, it is used during assembler/linker
845 	 relaxation if possible.  */
846       if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
847 	continue;
848 
849       str = start;
850 
851       /* Skip this insn if str doesn't look right lexically.  */
852       if (CGEN_INSN_RX (insn) != NULL &&
853 	  regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
854 	continue;
855 
856       /* Allow parse/insert handlers to obtain length of insn.  */
857       CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
858 
859       parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
860       if (parse_errmsg != NULL)
861 	continue;
862 
863       /* ??? 0 is passed for `pc'.  */
864       insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
865 						 (bfd_vma) 0);
866       if (insert_errmsg != NULL)
867         continue;
868 
869       /* It is up to the caller to actually output the insn and any
870          queued relocs.  */
871       return insn;
872     }
873 
874   {
875     static char errbuf[150];
876     const char *tmp_errmsg;
877 #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
878 #define be_verbose 1
879 #else
880 #define be_verbose 0
881 #endif
882 
883     if (be_verbose)
884       {
885 	/* If requesting verbose error messages, use insert_errmsg.
886 	   Failing that, use parse_errmsg.  */
887 	tmp_errmsg = (insert_errmsg ? insert_errmsg :
888 		      parse_errmsg ? parse_errmsg :
889 		      recognized_mnemonic ?
890 		      _("unrecognized form of instruction") :
891 		      _("unrecognized instruction"));
892 
893 	if (strlen (start) > 50)
894 	  /* xgettext:c-format */
895 	  sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
896 	else
897 	  /* xgettext:c-format */
898 	  sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
899       }
900     else
901       {
902 	if (strlen (start) > 50)
903 	  /* xgettext:c-format */
904 	  sprintf (errbuf, _("bad instruction `%.50s...'"), start);
905 	else
906 	  /* xgettext:c-format */
907 	  sprintf (errbuf, _("bad instruction `%.50s'"), start);
908       }
909 
910     *errmsg = errbuf;
911     return NULL;
912   }
913 }
914