[ARM] Support ARMv8.2 RAS extension.
[external/binutils.git] / opcodes / epiphany-asm.c
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-2016 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
46 static const char * parse_insn_normal
47   (CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *);
48 \f
49 /* -- assembler routines inserted here.  */
50
51 /* -- asm.c */
52 const char *
53 parse_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
72 static const char * parse_simm_not_reg (CGEN_CPU_DESC, const char **, int,
73                                         long *);
74
75 static const char *
76 parse_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
87 static const char *
88 parse_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
131 static const char *
132 parse_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
156 static const char *
157 parse_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
192 static const char * MISSING_CLOSE_PARENTHESIS = N_("missing `)'");
193
194 static const char *
195 parse_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
245 const char *
246 parse_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 \f
300 /* -- dis.c */
301
302 const 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
318 const char *
319 epiphany_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
461 cgen_parse_fn * const epiphany_cgen_parse_handlers[] =
462 {
463   parse_insn_normal,
464 };
465
466 void
467 epiphany_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
474 CGEN_ASM_INIT_HOOK
475 #endif
476 }
477
478 \f
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
491 char *
492 epiphany_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 \f
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
614 static const char *
615 parse_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 \f
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
757 const CGEN_INSN *
758 epiphany_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 }