Mark generated cgen files read-only
[external/binutils.git] / opcodes / or1k-asm.c
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-2017 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 \f
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 \f
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 \f
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 \f
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 }