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