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 "epiphany-desc.h"
35#include "epiphany-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 */
52const char *
53parse_shortregs (CGEN_CPU_DESC cd,
54		 const char ** strp,
55		 CGEN_KEYWORD * keywords,
56		 long * regno)
57{
58  const char * errmsg;
59
60  /* Parse register.  */
61  errmsg = cgen_parse_keyword (cd, strp, keywords, regno);
62
63  if (errmsg)
64    return errmsg;
65
66  if (*regno > 7)
67    errmsg = _("register unavailable for short instructions");
68
69  return errmsg;
70}
71
72static const char * parse_simm_not_reg (CGEN_CPU_DESC, const char **, int,
73					long *);
74
75static const char *
76parse_uimm_not_reg (CGEN_CPU_DESC cd,
77		    const char ** strp,
78		    int opindex,
79		    unsigned long * valuep)
80{
81  long * svalp = (void *) valuep;
82  return parse_simm_not_reg (cd, strp, opindex, svalp);
83}
84
85/* Handle simm3/simm11/imm3/imm12.  */
86
87static const char *
88parse_simm_not_reg (CGEN_CPU_DESC cd,
89		   const char ** strp,
90		   int opindex,
91		   long * valuep)
92{
93  const char * errmsg;
94
95  int   sign = 0;
96  int   bits = 0;
97
98  switch (opindex)
99    {
100    case EPIPHANY_OPERAND_SIMM3:
101      sign = 1; bits = 3; break;
102    case EPIPHANY_OPERAND_SIMM11:
103      sign = 1; bits = 11; break;
104    case EPIPHANY_OPERAND_DISP3:
105      sign = 0; bits = 3; break;
106    case EPIPHANY_OPERAND_DISP11:
107      /* Load/store displacement is a sign-magnitude 12 bit value.  */
108      sign = 0; bits = 11; break;
109    }
110
111  /* First try to parse as a register name and reject the operand.  */
112  errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_gr_names,valuep);
113  if (!errmsg)
114    return _("register name used as immediate value");
115
116  errmsg = (sign ? cgen_parse_signed_integer (cd, strp, opindex, valuep)
117	    : cgen_parse_unsigned_integer (cd, strp, opindex,
118					  (unsigned long *) valuep));
119  if (errmsg)
120    return errmsg;
121
122  if (sign)
123    errmsg = cgen_validate_signed_integer (*valuep,
124					  -((1L << bits) - 1), (1 << (bits - 1)) - 1);
125  else
126    errmsg = cgen_validate_unsigned_integer (*valuep, 0, (1L << bits) - 1);
127
128  return errmsg;
129}
130
131static const char *
132parse_postindex (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
133		 const char ** strp,
134		 int opindex ATTRIBUTE_UNUSED,
135		 unsigned long *valuep)
136{
137  if (**strp == '#')
138    ++*strp;			/* Skip leading hashes.  */
139
140  if (**strp == '-')
141    {
142      *valuep = 1;
143      ++*strp;
144    }
145  else if (**strp == '+')
146    {
147      *valuep = 0;
148      ++*strp;
149    }
150  else
151    *valuep = 0;
152
153  return NULL;
154}
155
156static const char *
157parse_imm8 (CGEN_CPU_DESC cd,
158	    const char ** strp,
159	    int opindex,
160	    bfd_reloc_code_real_type code,
161	    enum cgen_parse_operand_result * result_type,
162	    bfd_vma * valuep)
163{
164  const char * errmsg;
165  enum cgen_parse_operand_result rt;
166  long dummyval;
167
168  if (!result_type)
169    result_type = &rt;
170
171  code = BFD_RELOC_NONE;
172
173  if (!cgen_parse_keyword (cd, strp, &epiphany_cgen_opval_gr_names, &dummyval)
174      || !cgen_parse_keyword (cd, strp, &epiphany_cgen_opval_cr_names,
175			      &dummyval))
176    /* Don't treat "mov ip,ip" as a move-immediate.  */
177    return _("register source in immediate move");
178
179  errmsg = cgen_parse_address (cd, strp, opindex, code, result_type, valuep);
180  if (errmsg)
181    return errmsg;
182
183  if (*result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
184    errmsg = cgen_validate_unsigned_integer (*valuep, 0, 0xff);
185  else
186    errmsg = _("byte relocation unsupported");
187
188  *valuep &= 0xff;
189  return errmsg;
190}
191
192static const char * MISSING_CLOSE_PARENTHESIS = N_("missing `)'");
193
194static const char *
195parse_imm16 (CGEN_CPU_DESC cd,
196	     const char ** strp,
197	     int opindex,
198	     bfd_reloc_code_real_type code ATTRIBUTE_UNUSED,
199	     enum cgen_parse_operand_result * result_type,
200	     bfd_vma * valuep)
201{
202  const char * errmsg;
203  enum cgen_parse_operand_result rt;
204  long dummyval;
205
206  if (!result_type)
207    result_type = &rt;
208
209  if (strncasecmp (*strp, "%high(", 6) == 0)
210    {
211      *strp += 6;
212      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_EPIPHANY_HIGH,
213				   result_type, valuep);
214      if (**strp != ')')
215	return MISSING_CLOSE_PARENTHESIS;
216      ++*strp;
217      *valuep >>= 16;
218    }
219  else if (strncasecmp (*strp, "%low(", 5) == 0)
220    {
221      *strp += 5;
222      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_EPIPHANY_LOW,
223				   result_type, valuep);
224      if (**strp != ')')
225	return MISSING_CLOSE_PARENTHESIS;
226      ++*strp;
227    }
228  else if (!cgen_parse_keyword (cd, strp, &epiphany_cgen_opval_gr_names,
229				&dummyval)
230	   || !cgen_parse_keyword (cd, strp, &epiphany_cgen_opval_cr_names,
231				   &dummyval))
232    /* Don't treat "mov ip,ip" as a move-immediate.  */
233    return _("register source in immediate move");
234  else
235    errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_16,
236				 result_type, valuep);
237
238  if (!errmsg && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
239    errmsg = cgen_validate_unsigned_integer (*valuep, 0, 0xffff);
240
241  *valuep &= 0xffff;
242  return errmsg;
243}
244
245const char *
246parse_branch_addr (CGEN_CPU_DESC cd,
247		   const char ** strp,
248		   int opindex,
249		   int opinfo ATTRIBUTE_UNUSED,
250		   enum cgen_parse_operand_result * resultp ATTRIBUTE_UNUSED,
251		   bfd_vma *valuep ATTRIBUTE_UNUSED)
252{
253  const char * errmsg;
254  enum cgen_parse_operand_result result_type;
255  bfd_reloc_code_real_type code = BFD_RELOC_NONE;
256  bfd_vma value;
257
258  switch (opindex)
259    {
260    case EPIPHANY_OPERAND_SIMM24:
261      code = BFD_RELOC_EPIPHANY_SIMM24;
262      break;
263
264    case EPIPHANY_OPERAND_SIMM8:
265      code = BFD_RELOC_EPIPHANY_SIMM8;
266      break;
267
268    default:
269      errmsg = _("ABORT: unknown operand");
270      return errmsg;
271    }
272
273  errmsg = cgen_parse_address (cd, strp, opindex, code,
274			       &result_type, &value);
275  if (errmsg == NULL)
276    {
277      if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
278	{
279	  /* Act as if we had done a PC-relative branch, ala .+num.  */
280	  char buf[20];
281	  const char * bufp = (const char *) buf;
282
283	  sprintf (buf, ".+%ld", (long) value);
284	  errmsg = cgen_parse_address (cd, &bufp, opindex, code, &result_type,
285				       &value);
286	}
287
288      if (result_type == CGEN_PARSE_OPERAND_RESULT_QUEUED)
289	{
290	  /* This will happen for things like (s2-s1) where s2 and s1
291	     are labels.  */
292	  /* Nothing further to be done.  */
293	}
294      else
295	errmsg = _("Not a pc-relative address.");
296    }
297  return errmsg;
298}
299
300/* -- dis.c */
301
302const char * epiphany_cgen_parse_operand
303  (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
304
305/* Main entry point for operand parsing.
306
307   This function is basically just a big switch statement.  Earlier versions
308   used tables to look up the function to use, but
309   - if the table contains both assembler and disassembler functions then
310     the disassembler contains much of the assembler and vice-versa,
311   - there's a lot of inlining possibilities as things grow,
312   - using a switch statement avoids the function call overhead.
313
314   This function could be moved into `parse_insn_normal', but keeping it
315   separate makes clear the interface between `parse_insn_normal' and each of
316   the handlers.  */
317
318const char *
319epiphany_cgen_parse_operand (CGEN_CPU_DESC cd,
320			   int opindex,
321			   const char ** strp,
322			   CGEN_FIELDS * fields)
323{
324  const char * errmsg = NULL;
325  /* Used by scalar operands that still need to be parsed.  */
326  long junk ATTRIBUTE_UNUSED;
327
328  switch (opindex)
329    {
330    case EPIPHANY_OPERAND_DIRECTION :
331      errmsg = parse_postindex (cd, strp, EPIPHANY_OPERAND_DIRECTION, (unsigned long *) (& fields->f_addsubx));
332      break;
333    case EPIPHANY_OPERAND_DISP11 :
334      errmsg = parse_uimm_not_reg (cd, strp, EPIPHANY_OPERAND_DISP11, (unsigned long *) (& fields->f_disp11));
335      break;
336    case EPIPHANY_OPERAND_DISP3 :
337      errmsg = cgen_parse_unsigned_integer (cd, strp, EPIPHANY_OPERAND_DISP3, (unsigned long *) (& fields->f_disp3));
338      break;
339    case EPIPHANY_OPERAND_DPMI :
340      errmsg = parse_postindex (cd, strp, EPIPHANY_OPERAND_DPMI, (unsigned long *) (& fields->f_subd));
341      break;
342    case EPIPHANY_OPERAND_FRD :
343      errmsg = parse_shortregs (cd, strp, & epiphany_cgen_opval_gr_names, & fields->f_rd);
344      break;
345    case EPIPHANY_OPERAND_FRD6 :
346      errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_gr_names, & fields->f_rd6);
347      break;
348    case EPIPHANY_OPERAND_FRM :
349      errmsg = parse_shortregs (cd, strp, & epiphany_cgen_opval_gr_names, & fields->f_rm);
350      break;
351    case EPIPHANY_OPERAND_FRM6 :
352      errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_gr_names, & fields->f_rm6);
353      break;
354    case EPIPHANY_OPERAND_FRN :
355      errmsg = parse_shortregs (cd, strp, & epiphany_cgen_opval_gr_names, & fields->f_rn);
356      break;
357    case EPIPHANY_OPERAND_FRN6 :
358      errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_gr_names, & fields->f_rn6);
359      break;
360    case EPIPHANY_OPERAND_IMM16 :
361      {
362        bfd_vma value = 0;
363        errmsg = parse_imm16 (cd, strp, EPIPHANY_OPERAND_IMM16, 0, NULL,  & value);
364        fields->f_imm16 = value;
365      }
366      break;
367    case EPIPHANY_OPERAND_IMM8 :
368      {
369        bfd_vma value = 0;
370        errmsg = parse_imm8 (cd, strp, EPIPHANY_OPERAND_IMM8, 0, NULL,  & value);
371        fields->f_imm8 = value;
372      }
373      break;
374    case EPIPHANY_OPERAND_RD :
375      errmsg = parse_shortregs (cd, strp, & epiphany_cgen_opval_gr_names, & fields->f_rd);
376      break;
377    case EPIPHANY_OPERAND_RD6 :
378      errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_gr_names, & fields->f_rd6);
379      break;
380    case EPIPHANY_OPERAND_RM :
381      errmsg = parse_shortregs (cd, strp, & epiphany_cgen_opval_gr_names, & fields->f_rm);
382      break;
383    case EPIPHANY_OPERAND_RM6 :
384      errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_gr_names, & fields->f_rm6);
385      break;
386    case EPIPHANY_OPERAND_RN :
387      errmsg = parse_shortregs (cd, strp, & epiphany_cgen_opval_gr_names, & fields->f_rn);
388      break;
389    case EPIPHANY_OPERAND_RN6 :
390      errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_gr_names, & fields->f_rn6);
391      break;
392    case EPIPHANY_OPERAND_SD :
393      errmsg = parse_shortregs (cd, strp, & epiphany_cgen_opval_cr_names, & fields->f_sd);
394      break;
395    case EPIPHANY_OPERAND_SD6 :
396      errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_cr_names, & fields->f_sd6);
397      break;
398    case EPIPHANY_OPERAND_SDDMA :
399      errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_crdma_names, & fields->f_sd6);
400      break;
401    case EPIPHANY_OPERAND_SDMEM :
402      errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_crmem_names, & fields->f_sd6);
403      break;
404    case EPIPHANY_OPERAND_SDMESH :
405      errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_crmesh_names, & fields->f_sd6);
406      break;
407    case EPIPHANY_OPERAND_SHIFT :
408      errmsg = cgen_parse_unsigned_integer (cd, strp, EPIPHANY_OPERAND_SHIFT, (unsigned long *) (& fields->f_shift));
409      break;
410    case EPIPHANY_OPERAND_SIMM11 :
411      errmsg = parse_simm_not_reg (cd, strp, EPIPHANY_OPERAND_SIMM11, (long *) (& fields->f_sdisp11));
412      break;
413    case EPIPHANY_OPERAND_SIMM24 :
414      {
415        bfd_vma value = 0;
416        errmsg = parse_branch_addr (cd, strp, EPIPHANY_OPERAND_SIMM24, 0, NULL,  & value);
417        fields->f_simm24 = value;
418      }
419      break;
420    case EPIPHANY_OPERAND_SIMM3 :
421      errmsg = parse_simm_not_reg (cd, strp, EPIPHANY_OPERAND_SIMM3, (long *) (& fields->f_sdisp3));
422      break;
423    case EPIPHANY_OPERAND_SIMM8 :
424      {
425        bfd_vma value = 0;
426        errmsg = parse_branch_addr (cd, strp, EPIPHANY_OPERAND_SIMM8, 0, NULL,  & value);
427        fields->f_simm8 = value;
428      }
429      break;
430    case EPIPHANY_OPERAND_SN :
431      errmsg = parse_shortregs (cd, strp, & epiphany_cgen_opval_cr_names, & fields->f_sn);
432      break;
433    case EPIPHANY_OPERAND_SN6 :
434      errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_cr_names, & fields->f_sn6);
435      break;
436    case EPIPHANY_OPERAND_SNDMA :
437      errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_crdma_names, & fields->f_sn6);
438      break;
439    case EPIPHANY_OPERAND_SNMEM :
440      errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_crmem_names, & fields->f_sn6);
441      break;
442    case EPIPHANY_OPERAND_SNMESH :
443      errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_crmesh_names, & fields->f_sn6);
444      break;
445    case EPIPHANY_OPERAND_SWI_NUM :
446      errmsg = parse_uimm_not_reg (cd, strp, EPIPHANY_OPERAND_SWI_NUM, (unsigned long *) (& fields->f_trap_num));
447      break;
448    case EPIPHANY_OPERAND_TRAPNUM6 :
449      errmsg = cgen_parse_unsigned_integer (cd, strp, EPIPHANY_OPERAND_TRAPNUM6, (unsigned long *) (& fields->f_trap_num));
450      break;
451
452    default :
453      /* xgettext:c-format */
454      fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
455      abort ();
456  }
457
458  return errmsg;
459}
460
461cgen_parse_fn * const epiphany_cgen_parse_handlers[] =
462{
463  parse_insn_normal,
464};
465
466void
467epiphany_cgen_init_asm (CGEN_CPU_DESC cd)
468{
469  epiphany_cgen_init_opcode_table (cd);
470  epiphany_cgen_init_ibld_table (cd);
471  cd->parse_handlers = & epiphany_cgen_parse_handlers[0];
472  cd->parse_operand = epiphany_cgen_parse_operand;
473#ifdef CGEN_ASM_INIT_HOOK
474CGEN_ASM_INIT_HOOK
475#endif
476}
477
478
479
480/* Regex construction routine.
481
482   This translates an opcode syntax string into a regex string,
483   by replacing any non-character syntax element (such as an
484   opcode) with the pattern '.*'
485
486   It then compiles the regex and stores it in the opcode, for
487   later use by epiphany_cgen_assemble_insn
488
489   Returns NULL for success, an error message for failure.  */
490
491char *
492epiphany_cgen_build_insn_regex (CGEN_INSN *insn)
493{
494  CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
495  const char *mnem = CGEN_INSN_MNEMONIC (insn);
496  char rxbuf[CGEN_MAX_RX_ELEMENTS];
497  char *rx = rxbuf;
498  const CGEN_SYNTAX_CHAR_TYPE *syn;
499  int reg_err;
500
501  syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
502
503  /* Mnemonics come first in the syntax string.  */
504  if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
505    return _("missing mnemonic in syntax string");
506  ++syn;
507
508  /* Generate a case sensitive regular expression that emulates case
509     insensitive matching in the "C" locale.  We cannot generate a case
510     insensitive regular expression because in Turkish locales, 'i' and 'I'
511     are not equal modulo case conversion.  */
512
513  /* Copy the literal mnemonic out of the insn.  */
514  for (; *mnem; mnem++)
515    {
516      char c = *mnem;
517
518      if (ISALPHA (c))
519	{
520	  *rx++ = '[';
521	  *rx++ = TOLOWER (c);
522	  *rx++ = TOUPPER (c);
523	  *rx++ = ']';
524	}
525      else
526	*rx++ = c;
527    }
528
529  /* Copy any remaining literals from the syntax string into the rx.  */
530  for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
531    {
532      if (CGEN_SYNTAX_CHAR_P (* syn))
533	{
534	  char c = CGEN_SYNTAX_CHAR (* syn);
535
536	  switch (c)
537	    {
538	      /* Escape any regex metacharacters in the syntax.  */
539	    case '.': case '[': case '\\':
540	    case '*': case '^': case '$':
541
542#ifdef CGEN_ESCAPE_EXTENDED_REGEX
543	    case '?': case '{': case '}':
544	    case '(': case ')': case '*':
545	    case '|': case '+': case ']':
546#endif
547	      *rx++ = '\\';
548	      *rx++ = c;
549	      break;
550
551	    default:
552	      if (ISALPHA (c))
553		{
554		  *rx++ = '[';
555		  *rx++ = TOLOWER (c);
556		  *rx++ = TOUPPER (c);
557		  *rx++ = ']';
558		}
559	      else
560		*rx++ = c;
561	      break;
562	    }
563	}
564      else
565	{
566	  /* Replace non-syntax fields with globs.  */
567	  *rx++ = '.';
568	  *rx++ = '*';
569	}
570    }
571
572  /* Trailing whitespace ok.  */
573  * rx++ = '[';
574  * rx++ = ' ';
575  * rx++ = '\t';
576  * rx++ = ']';
577  * rx++ = '*';
578
579  /* But anchor it after that.  */
580  * rx++ = '$';
581  * rx = '\0';
582
583  CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
584  reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
585
586  if (reg_err == 0)
587    return NULL;
588  else
589    {
590      static char msg[80];
591
592      regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
593      regfree ((regex_t *) CGEN_INSN_RX (insn));
594      free (CGEN_INSN_RX (insn));
595      (CGEN_INSN_RX (insn)) = NULL;
596      return msg;
597    }
598}
599
600
601/* Default insn parser.
602
603   The syntax string is scanned and operands are parsed and stored in FIELDS.
604   Relocs are queued as we go via other callbacks.
605
606   ??? Note that this is currently an all-or-nothing parser.  If we fail to
607   parse the instruction, we return 0 and the caller will start over from
608   the beginning.  Backtracking will be necessary in parsing subexpressions,
609   but that can be handled there.  Not handling backtracking here may get
610   expensive in the case of the m68k.  Deal with later.
611
612   Returns NULL for success, an error message for failure.  */
613
614static const char *
615parse_insn_normal (CGEN_CPU_DESC cd,
616		   const CGEN_INSN *insn,
617		   const char **strp,
618		   CGEN_FIELDS *fields)
619{
620  /* ??? Runtime added insns not handled yet.  */
621  const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
622  const char *str = *strp;
623  const char *errmsg;
624  const char *p;
625  const CGEN_SYNTAX_CHAR_TYPE * syn;
626#ifdef CGEN_MNEMONIC_OPERANDS
627  /* FIXME: wip */
628  int past_opcode_p;
629#endif
630
631  /* For now we assume the mnemonic is first (there are no leading operands).
632     We can parse it without needing to set up operand parsing.
633     GAS's input scrubber will ensure mnemonics are lowercase, but we may
634     not be called from GAS.  */
635  p = CGEN_INSN_MNEMONIC (insn);
636  while (*p && TOLOWER (*p) == TOLOWER (*str))
637    ++p, ++str;
638
639  if (* p)
640    return _("unrecognized instruction");
641
642#ifndef CGEN_MNEMONIC_OPERANDS
643  if (* str && ! ISSPACE (* str))
644    return _("unrecognized instruction");
645#endif
646
647  CGEN_INIT_PARSE (cd);
648  cgen_init_parse_operand (cd);
649#ifdef CGEN_MNEMONIC_OPERANDS
650  past_opcode_p = 0;
651#endif
652
653  /* We don't check for (*str != '\0') here because we want to parse
654     any trailing fake arguments in the syntax string.  */
655  syn = CGEN_SYNTAX_STRING (syntax);
656
657  /* Mnemonics come first for now, ensure valid string.  */
658  if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
659    abort ();
660
661  ++syn;
662
663  while (* syn != 0)
664    {
665      /* Non operand chars must match exactly.  */
666      if (CGEN_SYNTAX_CHAR_P (* syn))
667	{
668	  /* FIXME: While we allow for non-GAS callers above, we assume the
669	     first char after the mnemonic part is a space.  */
670	  /* FIXME: We also take inappropriate advantage of the fact that
671	     GAS's input scrubber will remove extraneous blanks.  */
672	  if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
673	    {
674#ifdef CGEN_MNEMONIC_OPERANDS
675	      if (CGEN_SYNTAX_CHAR(* syn) == ' ')
676		past_opcode_p = 1;
677#endif
678	      ++ syn;
679	      ++ str;
680	    }
681	  else if (*str)
682	    {
683	      /* Syntax char didn't match.  Can't be this insn.  */
684	      static char msg [80];
685
686	      /* xgettext:c-format */
687	      sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
688		       CGEN_SYNTAX_CHAR(*syn), *str);
689	      return msg;
690	    }
691	  else
692	    {
693	      /* Ran out of input.  */
694	      static char msg [80];
695
696	      /* xgettext:c-format */
697	      sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
698		       CGEN_SYNTAX_CHAR(*syn));
699	      return msg;
700	    }
701	  continue;
702	}
703
704#ifdef CGEN_MNEMONIC_OPERANDS
705      (void) past_opcode_p;
706#endif
707      /* We have an operand of some sort.  */
708      errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn), &str, fields);
709      if (errmsg)
710	return errmsg;
711
712      /* Done with this operand, continue with next one.  */
713      ++ syn;
714    }
715
716  /* If we're at the end of the syntax string, we're done.  */
717  if (* syn == 0)
718    {
719      /* FIXME: For the moment we assume a valid `str' can only contain
720	 blanks now.  IE: We needn't try again with a longer version of
721	 the insn and it is assumed that longer versions of insns appear
722	 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
723      while (ISSPACE (* str))
724	++ str;
725
726      if (* str != '\0')
727	return _("junk at end of line"); /* FIXME: would like to include `str' */
728
729      return NULL;
730    }
731
732  /* We couldn't parse it.  */
733  return _("unrecognized instruction");
734}
735
736/* Main entry point.
737   This routine is called for each instruction to be assembled.
738   STR points to the insn to be assembled.
739   We assume all necessary tables have been initialized.
740   The assembled instruction, less any fixups, is stored in BUF.
741   Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
742   still needs to be converted to target byte order, otherwise BUF is an array
743   of bytes in target byte order.
744   The result is a pointer to the insn's entry in the opcode table,
745   or NULL if an error occured (an error message will have already been
746   printed).
747
748   Note that when processing (non-alias) macro-insns,
749   this function recurses.
750
751   ??? It's possible to make this cpu-independent.
752   One would have to deal with a few minor things.
753   At this point in time doing so would be more of a curiosity than useful
754   [for example this file isn't _that_ big], but keeping the possibility in
755   mind helps keep the design clean.  */
756
757const CGEN_INSN *
758epiphany_cgen_assemble_insn (CGEN_CPU_DESC cd,
759			   const char *str,
760			   CGEN_FIELDS *fields,
761			   CGEN_INSN_BYTES_PTR buf,
762			   char **errmsg)
763{
764  const char *start;
765  CGEN_INSN_LIST *ilist;
766  const char *parse_errmsg = NULL;
767  const char *insert_errmsg = NULL;
768  int recognized_mnemonic = 0;
769
770  /* Skip leading white space.  */
771  while (ISSPACE (* str))
772    ++ str;
773
774  /* The instructions are stored in hashed lists.
775     Get the first in the list.  */
776  ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
777
778  /* Keep looking until we find a match.  */
779  start = str;
780  for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
781    {
782      const CGEN_INSN *insn = ilist->insn;
783      recognized_mnemonic = 1;
784
785#ifdef CGEN_VALIDATE_INSN_SUPPORTED
786      /* Not usually needed as unsupported opcodes
787	 shouldn't be in the hash lists.  */
788      /* Is this insn supported by the selected cpu?  */
789      if (! epiphany_cgen_insn_supported (cd, insn))
790	continue;
791#endif
792      /* If the RELAXED attribute is set, this is an insn that shouldn't be
793	 chosen immediately.  Instead, it is used during assembler/linker
794	 relaxation if possible.  */
795      if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
796	continue;
797
798      str = start;
799
800      /* Skip this insn if str doesn't look right lexically.  */
801      if (CGEN_INSN_RX (insn) != NULL &&
802	  regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
803	continue;
804
805      /* Allow parse/insert handlers to obtain length of insn.  */
806      CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
807
808      parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
809      if (parse_errmsg != NULL)
810	continue;
811
812      /* ??? 0 is passed for `pc'.  */
813      insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
814						 (bfd_vma) 0);
815      if (insert_errmsg != NULL)
816        continue;
817
818      /* It is up to the caller to actually output the insn and any
819         queued relocs.  */
820      return insn;
821    }
822
823  {
824    static char errbuf[150];
825    const char *tmp_errmsg;
826#ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
827#define be_verbose 1
828#else
829#define be_verbose 0
830#endif
831
832    if (be_verbose)
833      {
834	/* If requesting verbose error messages, use insert_errmsg.
835	   Failing that, use parse_errmsg.  */
836	tmp_errmsg = (insert_errmsg ? insert_errmsg :
837		      parse_errmsg ? parse_errmsg :
838		      recognized_mnemonic ?
839		      _("unrecognized form of instruction") :
840		      _("unrecognized instruction"));
841
842	if (strlen (start) > 50)
843	  /* xgettext:c-format */
844	  sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
845	else
846	  /* xgettext:c-format */
847	  sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
848      }
849    else
850      {
851	if (strlen (start) > 50)
852	  /* xgettext:c-format */
853	  sprintf (errbuf, _("bad instruction `%.50s...'"), start);
854	else
855	  /* xgettext:c-format */
856	  sprintf (errbuf, _("bad instruction `%.50s'"), start);
857      }
858
859    *errmsg = errbuf;
860    return NULL;
861  }
862}
863