Imported Upstream version 7.9
[platform/upstream/gdb.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 (C) 1996-2015 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
415   if (errmsg == NULL)
416     *valuep &= 0xffff;
417   return errmsg;
418 }
419
420 /* -- */
421
422 const char * or1k_cgen_parse_operand
423   (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
424
425 /* Main entry point for operand parsing.
426
427    This function is basically just a big switch statement.  Earlier versions
428    used tables to look up the function to use, but
429    - if the table contains both assembler and disassembler functions then
430      the disassembler contains much of the assembler and vice-versa,
431    - there's a lot of inlining possibilities as things grow,
432    - using a switch statement avoids the function call overhead.
433
434    This function could be moved into `parse_insn_normal', but keeping it
435    separate makes clear the interface between `parse_insn_normal' and each of
436    the handlers.  */
437
438 const char *
439 or1k_cgen_parse_operand (CGEN_CPU_DESC cd,
440                            int opindex,
441                            const char ** strp,
442                            CGEN_FIELDS * fields)
443 {
444   const char * errmsg = NULL;
445   /* Used by scalar operands that still need to be parsed.  */
446   long junk ATTRIBUTE_UNUSED;
447
448   switch (opindex)
449     {
450     case OR1K_OPERAND_DISP26 :
451       {
452         bfd_vma value = 0;
453         errmsg = parse_disp26 (cd, strp, OR1K_OPERAND_DISP26, 0, NULL,  & value);
454         fields->f_disp26 = value;
455       }
456       break;
457     case OR1K_OPERAND_RA :
458       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r2);
459       break;
460     case OR1K_OPERAND_RADF :
461       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fdr, & fields->f_r1);
462       break;
463     case OR1K_OPERAND_RASF :
464       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r2);
465       break;
466     case OR1K_OPERAND_RB :
467       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r3);
468       break;
469     case OR1K_OPERAND_RBDF :
470       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fdr, & fields->f_r1);
471       break;
472     case OR1K_OPERAND_RBSF :
473       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r3);
474       break;
475     case OR1K_OPERAND_RD :
476       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r1);
477       break;
478     case OR1K_OPERAND_RDDF :
479       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fdr, & fields->f_r1);
480       break;
481     case OR1K_OPERAND_RDSF :
482       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r1);
483       break;
484     case OR1K_OPERAND_SIMM16 :
485       errmsg = parse_simm16 (cd, strp, OR1K_OPERAND_SIMM16, (long *) (& fields->f_simm16));
486       break;
487     case OR1K_OPERAND_SIMM16_SPLIT :
488       errmsg = parse_simm16 (cd, strp, OR1K_OPERAND_SIMM16_SPLIT, (long *) (& fields->f_simm16_split));
489       break;
490     case OR1K_OPERAND_UIMM16 :
491       errmsg = parse_uimm16 (cd, strp, OR1K_OPERAND_UIMM16, (unsigned long *) (& fields->f_uimm16));
492       break;
493     case OR1K_OPERAND_UIMM16_SPLIT :
494       errmsg = parse_uimm16 (cd, strp, OR1K_OPERAND_UIMM16_SPLIT, (unsigned long *) (& fields->f_uimm16_split));
495       break;
496     case OR1K_OPERAND_UIMM6 :
497       errmsg = cgen_parse_unsigned_integer (cd, strp, OR1K_OPERAND_UIMM6, (unsigned long *) (& fields->f_uimm6));
498       break;
499
500     default :
501       /* xgettext:c-format */
502       fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
503       abort ();
504   }
505
506   return errmsg;
507 }
508
509 cgen_parse_fn * const or1k_cgen_parse_handlers[] = 
510 {
511   parse_insn_normal,
512 };
513
514 void
515 or1k_cgen_init_asm (CGEN_CPU_DESC cd)
516 {
517   or1k_cgen_init_opcode_table (cd);
518   or1k_cgen_init_ibld_table (cd);
519   cd->parse_handlers = & or1k_cgen_parse_handlers[0];
520   cd->parse_operand = or1k_cgen_parse_operand;
521 #ifdef CGEN_ASM_INIT_HOOK
522 CGEN_ASM_INIT_HOOK
523 #endif
524 }
525
526 \f
527
528 /* Regex construction routine.
529
530    This translates an opcode syntax string into a regex string,
531    by replacing any non-character syntax element (such as an
532    opcode) with the pattern '.*'
533
534    It then compiles the regex and stores it in the opcode, for
535    later use by or1k_cgen_assemble_insn
536
537    Returns NULL for success, an error message for failure.  */
538
539 char * 
540 or1k_cgen_build_insn_regex (CGEN_INSN *insn)
541 {  
542   CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
543   const char *mnem = CGEN_INSN_MNEMONIC (insn);
544   char rxbuf[CGEN_MAX_RX_ELEMENTS];
545   char *rx = rxbuf;
546   const CGEN_SYNTAX_CHAR_TYPE *syn;
547   int reg_err;
548
549   syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
550
551   /* Mnemonics come first in the syntax string.  */
552   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
553     return _("missing mnemonic in syntax string");
554   ++syn;
555
556   /* Generate a case sensitive regular expression that emulates case
557      insensitive matching in the "C" locale.  We cannot generate a case
558      insensitive regular expression because in Turkish locales, 'i' and 'I'
559      are not equal modulo case conversion.  */
560
561   /* Copy the literal mnemonic out of the insn.  */
562   for (; *mnem; mnem++)
563     {
564       char c = *mnem;
565
566       if (ISALPHA (c))
567         {
568           *rx++ = '[';
569           *rx++ = TOLOWER (c);
570           *rx++ = TOUPPER (c);
571           *rx++ = ']';
572         }
573       else
574         *rx++ = c;
575     }
576
577   /* Copy any remaining literals from the syntax string into the rx.  */
578   for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
579     {
580       if (CGEN_SYNTAX_CHAR_P (* syn)) 
581         {
582           char c = CGEN_SYNTAX_CHAR (* syn);
583
584           switch (c) 
585             {
586               /* Escape any regex metacharacters in the syntax.  */
587             case '.': case '[': case '\\': 
588             case '*': case '^': case '$': 
589
590 #ifdef CGEN_ESCAPE_EXTENDED_REGEX
591             case '?': case '{': case '}': 
592             case '(': case ')': case '*':
593             case '|': case '+': case ']':
594 #endif
595               *rx++ = '\\';
596               *rx++ = c;
597               break;
598
599             default:
600               if (ISALPHA (c))
601                 {
602                   *rx++ = '[';
603                   *rx++ = TOLOWER (c);
604                   *rx++ = TOUPPER (c);
605                   *rx++ = ']';
606                 }
607               else
608                 *rx++ = c;
609               break;
610             }
611         }
612       else
613         {
614           /* Replace non-syntax fields with globs.  */
615           *rx++ = '.';
616           *rx++ = '*';
617         }
618     }
619
620   /* Trailing whitespace ok.  */
621   * rx++ = '['; 
622   * rx++ = ' '; 
623   * rx++ = '\t'; 
624   * rx++ = ']'; 
625   * rx++ = '*'; 
626
627   /* But anchor it after that.  */
628   * rx++ = '$'; 
629   * rx = '\0';
630
631   CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
632   reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
633
634   if (reg_err == 0) 
635     return NULL;
636   else
637     {
638       static char msg[80];
639
640       regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
641       regfree ((regex_t *) CGEN_INSN_RX (insn));
642       free (CGEN_INSN_RX (insn));
643       (CGEN_INSN_RX (insn)) = NULL;
644       return msg;
645     }
646 }
647
648 \f
649 /* Default insn parser.
650
651    The syntax string is scanned and operands are parsed and stored in FIELDS.
652    Relocs are queued as we go via other callbacks.
653
654    ??? Note that this is currently an all-or-nothing parser.  If we fail to
655    parse the instruction, we return 0 and the caller will start over from
656    the beginning.  Backtracking will be necessary in parsing subexpressions,
657    but that can be handled there.  Not handling backtracking here may get
658    expensive in the case of the m68k.  Deal with later.
659
660    Returns NULL for success, an error message for failure.  */
661
662 static const char *
663 parse_insn_normal (CGEN_CPU_DESC cd,
664                    const CGEN_INSN *insn,
665                    const char **strp,
666                    CGEN_FIELDS *fields)
667 {
668   /* ??? Runtime added insns not handled yet.  */
669   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
670   const char *str = *strp;
671   const char *errmsg;
672   const char *p;
673   const CGEN_SYNTAX_CHAR_TYPE * syn;
674 #ifdef CGEN_MNEMONIC_OPERANDS
675   /* FIXME: wip */
676   int past_opcode_p;
677 #endif
678
679   /* For now we assume the mnemonic is first (there are no leading operands).
680      We can parse it without needing to set up operand parsing.
681      GAS's input scrubber will ensure mnemonics are lowercase, but we may
682      not be called from GAS.  */
683   p = CGEN_INSN_MNEMONIC (insn);
684   while (*p && TOLOWER (*p) == TOLOWER (*str))
685     ++p, ++str;
686
687   if (* p)
688     return _("unrecognized instruction");
689
690 #ifndef CGEN_MNEMONIC_OPERANDS
691   if (* str && ! ISSPACE (* str))
692     return _("unrecognized instruction");
693 #endif
694
695   CGEN_INIT_PARSE (cd);
696   cgen_init_parse_operand (cd);
697 #ifdef CGEN_MNEMONIC_OPERANDS
698   past_opcode_p = 0;
699 #endif
700
701   /* We don't check for (*str != '\0') here because we want to parse
702      any trailing fake arguments in the syntax string.  */
703   syn = CGEN_SYNTAX_STRING (syntax);
704
705   /* Mnemonics come first for now, ensure valid string.  */
706   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
707     abort ();
708
709   ++syn;
710
711   while (* syn != 0)
712     {
713       /* Non operand chars must match exactly.  */
714       if (CGEN_SYNTAX_CHAR_P (* syn))
715         {
716           /* FIXME: While we allow for non-GAS callers above, we assume the
717              first char after the mnemonic part is a space.  */
718           /* FIXME: We also take inappropriate advantage of the fact that
719              GAS's input scrubber will remove extraneous blanks.  */
720           if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
721             {
722 #ifdef CGEN_MNEMONIC_OPERANDS
723               if (CGEN_SYNTAX_CHAR(* syn) == ' ')
724                 past_opcode_p = 1;
725 #endif
726               ++ syn;
727               ++ str;
728             }
729           else if (*str)
730             {
731               /* Syntax char didn't match.  Can't be this insn.  */
732               static char msg [80];
733
734               /* xgettext:c-format */
735               sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
736                        CGEN_SYNTAX_CHAR(*syn), *str);
737               return msg;
738             }
739           else
740             {
741               /* Ran out of input.  */
742               static char msg [80];
743
744               /* xgettext:c-format */
745               sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
746                        CGEN_SYNTAX_CHAR(*syn));
747               return msg;
748             }
749           continue;
750         }
751
752 #ifdef CGEN_MNEMONIC_OPERANDS
753       (void) past_opcode_p;
754 #endif
755       /* We have an operand of some sort.  */
756       errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn), &str, fields);
757       if (errmsg)
758         return errmsg;
759
760       /* Done with this operand, continue with next one.  */
761       ++ syn;
762     }
763
764   /* If we're at the end of the syntax string, we're done.  */
765   if (* syn == 0)
766     {
767       /* FIXME: For the moment we assume a valid `str' can only contain
768          blanks now.  IE: We needn't try again with a longer version of
769          the insn and it is assumed that longer versions of insns appear
770          before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
771       while (ISSPACE (* str))
772         ++ str;
773
774       if (* str != '\0')
775         return _("junk at end of line"); /* FIXME: would like to include `str' */
776
777       return NULL;
778     }
779
780   /* We couldn't parse it.  */
781   return _("unrecognized instruction");
782 }
783 \f
784 /* Main entry point.
785    This routine is called for each instruction to be assembled.
786    STR points to the insn to be assembled.
787    We assume all necessary tables have been initialized.
788    The assembled instruction, less any fixups, is stored in BUF.
789    Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
790    still needs to be converted to target byte order, otherwise BUF is an array
791    of bytes in target byte order.
792    The result is a pointer to the insn's entry in the opcode table,
793    or NULL if an error occured (an error message will have already been
794    printed).
795
796    Note that when processing (non-alias) macro-insns,
797    this function recurses.
798
799    ??? It's possible to make this cpu-independent.
800    One would have to deal with a few minor things.
801    At this point in time doing so would be more of a curiosity than useful
802    [for example this file isn't _that_ big], but keeping the possibility in
803    mind helps keep the design clean.  */
804
805 const CGEN_INSN *
806 or1k_cgen_assemble_insn (CGEN_CPU_DESC cd,
807                            const char *str,
808                            CGEN_FIELDS *fields,
809                            CGEN_INSN_BYTES_PTR buf,
810                            char **errmsg)
811 {
812   const char *start;
813   CGEN_INSN_LIST *ilist;
814   const char *parse_errmsg = NULL;
815   const char *insert_errmsg = NULL;
816   int recognized_mnemonic = 0;
817
818   /* Skip leading white space.  */
819   while (ISSPACE (* str))
820     ++ str;
821
822   /* The instructions are stored in hashed lists.
823      Get the first in the list.  */
824   ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
825
826   /* Keep looking until we find a match.  */
827   start = str;
828   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
829     {
830       const CGEN_INSN *insn = ilist->insn;
831       recognized_mnemonic = 1;
832
833 #ifdef CGEN_VALIDATE_INSN_SUPPORTED 
834       /* Not usually needed as unsupported opcodes
835          shouldn't be in the hash lists.  */
836       /* Is this insn supported by the selected cpu?  */
837       if (! or1k_cgen_insn_supported (cd, insn))
838         continue;
839 #endif
840       /* If the RELAXED attribute is set, this is an insn that shouldn't be
841          chosen immediately.  Instead, it is used during assembler/linker
842          relaxation if possible.  */
843       if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
844         continue;
845
846       str = start;
847
848       /* Skip this insn if str doesn't look right lexically.  */
849       if (CGEN_INSN_RX (insn) != NULL &&
850           regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
851         continue;
852
853       /* Allow parse/insert handlers to obtain length of insn.  */
854       CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
855
856       parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
857       if (parse_errmsg != NULL)
858         continue;
859
860       /* ??? 0 is passed for `pc'.  */
861       insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
862                                                  (bfd_vma) 0);
863       if (insert_errmsg != NULL)
864         continue;
865
866       /* It is up to the caller to actually output the insn and any
867          queued relocs.  */
868       return insn;
869     }
870
871   {
872     static char errbuf[150];
873     const char *tmp_errmsg;
874 #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
875 #define be_verbose 1
876 #else
877 #define be_verbose 0
878 #endif
879
880     if (be_verbose)
881       {
882         /* If requesting verbose error messages, use insert_errmsg.
883            Failing that, use parse_errmsg.  */
884         tmp_errmsg = (insert_errmsg ? insert_errmsg :
885                       parse_errmsg ? parse_errmsg :
886                       recognized_mnemonic ?
887                       _("unrecognized form of instruction") :
888                       _("unrecognized instruction"));
889
890         if (strlen (start) > 50)
891           /* xgettext:c-format */
892           sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
893         else 
894           /* xgettext:c-format */
895           sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
896       }
897     else
898       {
899         if (strlen (start) > 50)
900           /* xgettext:c-format */
901           sprintf (errbuf, _("bad instruction `%.50s...'"), start);
902         else 
903           /* xgettext:c-format */
904           sprintf (errbuf, _("bad instruction `%.50s'"), start);
905       }
906       
907     *errmsg = errbuf;
908     return NULL;
909   }
910 }