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