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