xref: /netbsd-src/external/gpl3/binutils/dist/opcodes/or1k-asm.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
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       fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
504       abort ();
505   }
506 
507   return errmsg;
508 }
509 
510 cgen_parse_fn * const or1k_cgen_parse_handlers[] =
511 {
512   parse_insn_normal,
513 };
514 
515 void
516 or1k_cgen_init_asm (CGEN_CPU_DESC cd)
517 {
518   or1k_cgen_init_opcode_table (cd);
519   or1k_cgen_init_ibld_table (cd);
520   cd->parse_handlers = & or1k_cgen_parse_handlers[0];
521   cd->parse_operand = or1k_cgen_parse_operand;
522 #ifdef CGEN_ASM_INIT_HOOK
523 CGEN_ASM_INIT_HOOK
524 #endif
525 }
526 
527 
528 
529 /* Regex construction routine.
530 
531    This translates an opcode syntax string into a regex string,
532    by replacing any non-character syntax element (such as an
533    opcode) with the pattern '.*'
534 
535    It then compiles the regex and stores it in the opcode, for
536    later use by or1k_cgen_assemble_insn
537 
538    Returns NULL for success, an error message for failure.  */
539 
540 char *
541 or1k_cgen_build_insn_regex (CGEN_INSN *insn)
542 {
543   CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
544   const char *mnem = CGEN_INSN_MNEMONIC (insn);
545   char rxbuf[CGEN_MAX_RX_ELEMENTS];
546   char *rx = rxbuf;
547   const CGEN_SYNTAX_CHAR_TYPE *syn;
548   int reg_err;
549 
550   syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
551 
552   /* Mnemonics come first in the syntax string.  */
553   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
554     return _("missing mnemonic in syntax string");
555   ++syn;
556 
557   /* Generate a case sensitive regular expression that emulates case
558      insensitive matching in the "C" locale.  We cannot generate a case
559      insensitive regular expression because in Turkish locales, 'i' and 'I'
560      are not equal modulo case conversion.  */
561 
562   /* Copy the literal mnemonic out of the insn.  */
563   for (; *mnem; mnem++)
564     {
565       char c = *mnem;
566 
567       if (ISALPHA (c))
568 	{
569 	  *rx++ = '[';
570 	  *rx++ = TOLOWER (c);
571 	  *rx++ = TOUPPER (c);
572 	  *rx++ = ']';
573 	}
574       else
575 	*rx++ = c;
576     }
577 
578   /* Copy any remaining literals from the syntax string into the rx.  */
579   for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
580     {
581       if (CGEN_SYNTAX_CHAR_P (* syn))
582 	{
583 	  char c = CGEN_SYNTAX_CHAR (* syn);
584 
585 	  switch (c)
586 	    {
587 	      /* Escape any regex metacharacters in the syntax.  */
588 	    case '.': case '[': case '\\':
589 	    case '*': case '^': case '$':
590 
591 #ifdef CGEN_ESCAPE_EXTENDED_REGEX
592 	    case '?': case '{': case '}':
593 	    case '(': case ')': case '*':
594 	    case '|': case '+': case ']':
595 #endif
596 	      *rx++ = '\\';
597 	      *rx++ = c;
598 	      break;
599 
600 	    default:
601 	      if (ISALPHA (c))
602 		{
603 		  *rx++ = '[';
604 		  *rx++ = TOLOWER (c);
605 		  *rx++ = TOUPPER (c);
606 		  *rx++ = ']';
607 		}
608 	      else
609 		*rx++ = c;
610 	      break;
611 	    }
612 	}
613       else
614 	{
615 	  /* Replace non-syntax fields with globs.  */
616 	  *rx++ = '.';
617 	  *rx++ = '*';
618 	}
619     }
620 
621   /* Trailing whitespace ok.  */
622   * rx++ = '[';
623   * rx++ = ' ';
624   * rx++ = '\t';
625   * rx++ = ']';
626   * rx++ = '*';
627 
628   /* But anchor it after that.  */
629   * rx++ = '$';
630   * rx = '\0';
631 
632   CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
633   reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
634 
635   if (reg_err == 0)
636     return NULL;
637   else
638     {
639       static char msg[80];
640 
641       regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
642       regfree ((regex_t *) CGEN_INSN_RX (insn));
643       free (CGEN_INSN_RX (insn));
644       (CGEN_INSN_RX (insn)) = NULL;
645       return msg;
646     }
647 }
648 
649 
650 /* Default insn parser.
651 
652    The syntax string is scanned and operands are parsed and stored in FIELDS.
653    Relocs are queued as we go via other callbacks.
654 
655    ??? Note that this is currently an all-or-nothing parser.  If we fail to
656    parse the instruction, we return 0 and the caller will start over from
657    the beginning.  Backtracking will be necessary in parsing subexpressions,
658    but that can be handled there.  Not handling backtracking here may get
659    expensive in the case of the m68k.  Deal with later.
660 
661    Returns NULL for success, an error message for failure.  */
662 
663 static const char *
664 parse_insn_normal (CGEN_CPU_DESC cd,
665 		   const CGEN_INSN *insn,
666 		   const char **strp,
667 		   CGEN_FIELDS *fields)
668 {
669   /* ??? Runtime added insns not handled yet.  */
670   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
671   const char *str = *strp;
672   const char *errmsg;
673   const char *p;
674   const CGEN_SYNTAX_CHAR_TYPE * syn;
675 #ifdef CGEN_MNEMONIC_OPERANDS
676   /* FIXME: wip */
677   int past_opcode_p;
678 #endif
679 
680   /* For now we assume the mnemonic is first (there are no leading operands).
681      We can parse it without needing to set up operand parsing.
682      GAS's input scrubber will ensure mnemonics are lowercase, but we may
683      not be called from GAS.  */
684   p = CGEN_INSN_MNEMONIC (insn);
685   while (*p && TOLOWER (*p) == TOLOWER (*str))
686     ++p, ++str;
687 
688   if (* p)
689     return _("unrecognized instruction");
690 
691 #ifndef CGEN_MNEMONIC_OPERANDS
692   if (* str && ! ISSPACE (* str))
693     return _("unrecognized instruction");
694 #endif
695 
696   CGEN_INIT_PARSE (cd);
697   cgen_init_parse_operand (cd);
698 #ifdef CGEN_MNEMONIC_OPERANDS
699   past_opcode_p = 0;
700 #endif
701 
702   /* We don't check for (*str != '\0') here because we want to parse
703      any trailing fake arguments in the syntax string.  */
704   syn = CGEN_SYNTAX_STRING (syntax);
705 
706   /* Mnemonics come first for now, ensure valid string.  */
707   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
708     abort ();
709 
710   ++syn;
711 
712   while (* syn != 0)
713     {
714       /* Non operand chars must match exactly.  */
715       if (CGEN_SYNTAX_CHAR_P (* syn))
716 	{
717 	  /* FIXME: While we allow for non-GAS callers above, we assume the
718 	     first char after the mnemonic part is a space.  */
719 	  /* FIXME: We also take inappropriate advantage of the fact that
720 	     GAS's input scrubber will remove extraneous blanks.  */
721 	  if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
722 	    {
723 #ifdef CGEN_MNEMONIC_OPERANDS
724 	      if (CGEN_SYNTAX_CHAR(* syn) == ' ')
725 		past_opcode_p = 1;
726 #endif
727 	      ++ syn;
728 	      ++ str;
729 	    }
730 	  else if (*str)
731 	    {
732 	      /* Syntax char didn't match.  Can't be this insn.  */
733 	      static char msg [80];
734 
735 	      /* xgettext:c-format */
736 	      sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
737 		       CGEN_SYNTAX_CHAR(*syn), *str);
738 	      return msg;
739 	    }
740 	  else
741 	    {
742 	      /* Ran out of input.  */
743 	      static char msg [80];
744 
745 	      /* xgettext:c-format */
746 	      sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
747 		       CGEN_SYNTAX_CHAR(*syn));
748 	      return msg;
749 	    }
750 	  continue;
751 	}
752 
753 #ifdef CGEN_MNEMONIC_OPERANDS
754       (void) past_opcode_p;
755 #endif
756       /* We have an operand of some sort.  */
757       errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn), &str, fields);
758       if (errmsg)
759 	return errmsg;
760 
761       /* Done with this operand, continue with next one.  */
762       ++ syn;
763     }
764 
765   /* If we're at the end of the syntax string, we're done.  */
766   if (* syn == 0)
767     {
768       /* FIXME: For the moment we assume a valid `str' can only contain
769 	 blanks now.  IE: We needn't try again with a longer version of
770 	 the insn and it is assumed that longer versions of insns appear
771 	 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
772       while (ISSPACE (* str))
773 	++ str;
774 
775       if (* str != '\0')
776 	return _("junk at end of line"); /* FIXME: would like to include `str' */
777 
778       return NULL;
779     }
780 
781   /* We couldn't parse it.  */
782   return _("unrecognized instruction");
783 }
784 
785 /* Main entry point.
786    This routine is called for each instruction to be assembled.
787    STR points to the insn to be assembled.
788    We assume all necessary tables have been initialized.
789    The assembled instruction, less any fixups, is stored in BUF.
790    Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
791    still needs to be converted to target byte order, otherwise BUF is an array
792    of bytes in target byte order.
793    The result is a pointer to the insn's entry in the opcode table,
794    or NULL if an error occured (an error message will have already been
795    printed).
796 
797    Note that when processing (non-alias) macro-insns,
798    this function recurses.
799 
800    ??? It's possible to make this cpu-independent.
801    One would have to deal with a few minor things.
802    At this point in time doing so would be more of a curiosity than useful
803    [for example this file isn't _that_ big], but keeping the possibility in
804    mind helps keep the design clean.  */
805 
806 const CGEN_INSN *
807 or1k_cgen_assemble_insn (CGEN_CPU_DESC cd,
808 			   const char *str,
809 			   CGEN_FIELDS *fields,
810 			   CGEN_INSN_BYTES_PTR buf,
811 			   char **errmsg)
812 {
813   const char *start;
814   CGEN_INSN_LIST *ilist;
815   const char *parse_errmsg = NULL;
816   const char *insert_errmsg = NULL;
817   int recognized_mnemonic = 0;
818 
819   /* Skip leading white space.  */
820   while (ISSPACE (* str))
821     ++ str;
822 
823   /* The instructions are stored in hashed lists.
824      Get the first in the list.  */
825   ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
826 
827   /* Keep looking until we find a match.  */
828   start = str;
829   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
830     {
831       const CGEN_INSN *insn = ilist->insn;
832       recognized_mnemonic = 1;
833 
834 #ifdef CGEN_VALIDATE_INSN_SUPPORTED
835       /* Not usually needed as unsupported opcodes
836 	 shouldn't be in the hash lists.  */
837       /* Is this insn supported by the selected cpu?  */
838       if (! or1k_cgen_insn_supported (cd, insn))
839 	continue;
840 #endif
841       /* If the RELAXED attribute is set, this is an insn that shouldn't be
842 	 chosen immediately.  Instead, it is used during assembler/linker
843 	 relaxation if possible.  */
844       if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
845 	continue;
846 
847       str = start;
848 
849       /* Skip this insn if str doesn't look right lexically.  */
850       if (CGEN_INSN_RX (insn) != NULL &&
851 	  regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
852 	continue;
853 
854       /* Allow parse/insert handlers to obtain length of insn.  */
855       CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
856 
857       parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
858       if (parse_errmsg != NULL)
859 	continue;
860 
861       /* ??? 0 is passed for `pc'.  */
862       insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
863 						 (bfd_vma) 0);
864       if (insert_errmsg != NULL)
865         continue;
866 
867       /* It is up to the caller to actually output the insn and any
868          queued relocs.  */
869       return insn;
870     }
871 
872   {
873     static char errbuf[150];
874     const char *tmp_errmsg;
875 #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
876 #define be_verbose 1
877 #else
878 #define be_verbose 0
879 #endif
880 
881     if (be_verbose)
882       {
883 	/* If requesting verbose error messages, use insert_errmsg.
884 	   Failing that, use parse_errmsg.  */
885 	tmp_errmsg = (insert_errmsg ? insert_errmsg :
886 		      parse_errmsg ? parse_errmsg :
887 		      recognized_mnemonic ?
888 		      _("unrecognized form of instruction") :
889 		      _("unrecognized instruction"));
890 
891 	if (strlen (start) > 50)
892 	  /* xgettext:c-format */
893 	  sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
894 	else
895 	  /* xgettext:c-format */
896 	  sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
897       }
898     else
899       {
900 	if (strlen (start) > 50)
901 	  /* xgettext:c-format */
902 	  sprintf (errbuf, _("bad instruction `%.50s...'"), start);
903 	else
904 	  /* xgettext:c-format */
905 	  sprintf (errbuf, _("bad instruction `%.50s'"), start);
906       }
907 
908     *errmsg = errbuf;
909     return NULL;
910   }
911 }
912