Home | History | Annotate | Line # | Download | only in opcodes
or1k-asm.c revision 1.1.1.3
      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 
     50 /* -- assembler routines inserted here.  */
     52 
     53 /* -- asm.c */
     54 
     55 static const char * MISSING_CLOSING_PARENTHESIS = N_("missing `)'");
     56 
     57 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
     58 
     59 static const char *
     60 parse_disp26 (CGEN_CPU_DESC cd,
     61 	      const char ** strp,
     62 	      int opindex,
     63 	      int opinfo,
     64 	      enum cgen_parse_operand_result * resultp,
     65 	      bfd_vma * valuep)
     66 {
     67   const char *errmsg = NULL;
     68   enum cgen_parse_operand_result result_type;
     69 
     70   if (strncasecmp (*strp, "plt(", 4) == 0)
     71     {
     72       bfd_vma value;
     73 
     74       *strp += 4;
     75       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_OR1K_PLT26,
     76 				   & result_type, & value);
     77       if (**strp != ')')
     78 	return MISSING_CLOSING_PARENTHESIS;
     79       ++*strp;
     80       if (errmsg == NULL
     81 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
     82 	value = (value >> 2) & 0xffff;
     83       *valuep = value;
     84       return errmsg;
     85     }
     86   return cgen_parse_address (cd, strp, opindex, opinfo, resultp, valuep);
     87 }
     88 
     89 static const char *
     90 parse_simm16 (CGEN_CPU_DESC cd, const char ** strp, int opindex, long * valuep)
     91 {
     92   const char *errmsg;
     93   enum cgen_parse_operand_result result_type;
     94   long ret;
     95 
     96   if (**strp == '#')
     97     ++*strp;
     98 
     99   if (strncasecmp (*strp, "hi(", 3) == 0)
    100     {
    101       bfd_vma value;
    102 
    103       *strp += 3;
    104       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16,
    105 				   & result_type, & value);
    106       if (**strp != ')')
    107 	errmsg = MISSING_CLOSING_PARENTHESIS;
    108       ++*strp;
    109 
    110       ret = value;
    111 
    112       if (errmsg == NULL
    113 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    114 	{
    115 	  ret >>= 16;
    116 	  ret &= 0xffff;
    117 	  ret = (ret ^ 0x8000) - 0x8000;
    118 	}
    119     }
    120   else if (strncasecmp (*strp, "lo(", 3) == 0)
    121     {
    122       bfd_vma value;
    123 
    124       *strp += 3;
    125       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
    126 				   & result_type, & value);
    127       if (**strp != ')')
    128 	return MISSING_CLOSING_PARENTHESIS;
    129       ++*strp;
    130 
    131       ret = value;
    132 
    133       if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    134 	{
    135 	  ret &= 0xffff;
    136 	  ret = (ret ^ 0x8000) - 0x8000;
    137 	}
    138     }
    139   else if (strncasecmp (*strp, "got(", 4) == 0)
    140     {
    141       bfd_vma value;
    142 
    143       *strp += 4;
    144       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_OR1K_GOT16,
    145 				   & result_type, & value);
    146       if (**strp != ')')
    147 	return MISSING_CLOSING_PARENTHESIS;
    148       ++*strp;
    149       if (errmsg == NULL
    150 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    151 	value &= 0xffff;
    152       *valuep = value;
    153       return errmsg;
    154     }
    155   else if (strncasecmp (*strp, "gotpchi(", 8) == 0)
    156     {
    157       bfd_vma value;
    158 
    159       *strp += 8;
    160       errmsg = cgen_parse_address (cd, strp, opindex,
    161 				   BFD_RELOC_OR1K_GOTPC_HI16,
    162 				   & result_type, & value);
    163       if (**strp != ')')
    164 	return MISSING_CLOSING_PARENTHESIS;
    165       ++*strp;
    166       if (errmsg == NULL
    167 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    168 	value = (value >> 16) & 0xffff;
    169       *valuep = value;
    170       return errmsg;
    171     }
    172   else if (strncasecmp (*strp, "gotpclo(", 8) == 0)
    173     {
    174       bfd_vma value;
    175 
    176       *strp += 8;
    177       errmsg = cgen_parse_address (cd, strp, opindex,
    178 				   BFD_RELOC_OR1K_GOTPC_LO16,
    179 				   &result_type, &value);
    180       if (**strp != ')')
    181 	return MISSING_CLOSING_PARENTHESIS;
    182       ++*strp;
    183       if (errmsg == NULL
    184 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    185 	value &= 0xffff;
    186       *valuep = value;
    187       return errmsg;
    188     }
    189   else if (strncasecmp (*strp, "gotoffhi(", 9) == 0)
    190     {
    191       bfd_vma value;
    192 
    193       *strp += 9;
    194       errmsg = cgen_parse_address (cd, strp, opindex,
    195 				   BFD_RELOC_OR1K_GOTOFF_HI16,
    196 				   & result_type, & value);
    197 
    198       if (**strp != ')')
    199 	return MISSING_CLOSING_PARENTHESIS;
    200       ++*strp;
    201       if (errmsg == NULL
    202 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    203 	value = (value >> 16) & 0xffff;
    204       *valuep = value;
    205       return errmsg;
    206     }
    207   else if (strncasecmp (*strp, "gotofflo(", 9) == 0)
    208     {
    209       bfd_vma value;
    210 
    211       *strp += 9;
    212       errmsg = cgen_parse_address (cd, strp, opindex,
    213 				   BFD_RELOC_OR1K_GOTOFF_LO16,
    214 				   &result_type, &value);
    215       if (**strp != ')')
    216 	return MISSING_CLOSING_PARENTHESIS;
    217       ++*strp;
    218       if (errmsg == NULL
    219 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    220 	value &= 0xffff;
    221       *valuep = value;
    222       return errmsg;
    223     }
    224   else if (strncasecmp (*strp, "tlsgdhi(", 8) == 0)
    225     {
    226       bfd_vma value;
    227 
    228       *strp += 8;
    229       errmsg = cgen_parse_address (cd, strp, opindex,
    230 				   BFD_RELOC_OR1K_TLS_GD_HI16,
    231 				   & result_type, & value);
    232 
    233       if (**strp != ')')
    234 	return MISSING_CLOSING_PARENTHESIS;
    235       ++*strp;
    236       if (errmsg == NULL
    237 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    238 	value = (value >> 16) & 0xffff;
    239       *valuep = value;
    240       return errmsg;
    241     }
    242   else if (strncasecmp (*strp, "tlsgdlo(", 8) == 0)
    243     {
    244       bfd_vma value;
    245 
    246       *strp += 8;
    247       errmsg = cgen_parse_address (cd, strp, opindex,
    248 				   BFD_RELOC_OR1K_TLS_GD_LO16,
    249 				   &result_type, &value);
    250       if (**strp != ')')
    251 	return MISSING_CLOSING_PARENTHESIS;
    252       ++*strp;
    253       if (errmsg == NULL
    254 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    255 	value &= 0xffff;
    256       *valuep = value;
    257       return errmsg;
    258     }
    259   else if (strncasecmp (*strp, "tlsldmhi(", 9) == 0)
    260     {
    261       bfd_vma value;
    262 
    263       *strp += 9;
    264       errmsg = cgen_parse_address (cd, strp, opindex,
    265 				   BFD_RELOC_OR1K_TLS_LDM_HI16,
    266 				   & result_type, & value);
    267 
    268       if (**strp != ')')
    269 	return MISSING_CLOSING_PARENTHESIS;
    270       ++*strp;
    271       if (errmsg == NULL
    272 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    273 	value = (value >> 16) & 0xffff;
    274       *valuep = value;
    275       return errmsg;
    276     }
    277   else if (strncasecmp (*strp, "tlsldmlo(", 9) == 0)
    278     {
    279       bfd_vma value;
    280 
    281       *strp += 9;
    282       errmsg = cgen_parse_address (cd, strp, opindex,
    283 				   BFD_RELOC_OR1K_TLS_LDM_LO16,
    284 				   &result_type, &value);
    285       if (**strp != ')')
    286 	return MISSING_CLOSING_PARENTHESIS;
    287       ++*strp;
    288       if (errmsg == NULL
    289 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    290 	value &= 0xffff;
    291       *valuep = value;
    292       return errmsg;
    293     }
    294   else if (strncasecmp (*strp, "dtpoffhi(", 9) == 0)
    295     {
    296       bfd_vma value;
    297 
    298       *strp += 9;
    299       errmsg = cgen_parse_address (cd, strp, opindex,
    300 				   BFD_RELOC_OR1K_TLS_LDO_HI16,
    301 				   & result_type, & value);
    302 
    303       if (**strp != ')')
    304 	return MISSING_CLOSING_PARENTHESIS;
    305       ++*strp;
    306       if (errmsg == NULL
    307 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    308 	value = (value >> 16) & 0xffff;
    309       *valuep = value;
    310       return errmsg;
    311     }
    312   else if (strncasecmp (*strp, "dtpofflo(", 9) == 0)
    313     {
    314       bfd_vma value;
    315 
    316       *strp += 9;
    317       errmsg = cgen_parse_address (cd, strp, opindex,
    318 				   BFD_RELOC_OR1K_TLS_LDO_LO16,
    319 				   &result_type, &value);
    320       if (**strp != ')')
    321 	return MISSING_CLOSING_PARENTHESIS;
    322       ++*strp;
    323       if (errmsg == NULL
    324 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    325 	value &= 0xffff;
    326       *valuep = value;
    327       return errmsg;
    328     }
    329   else if (strncasecmp (*strp, "gottpoffhi(", 11) == 0)
    330     {
    331       bfd_vma value;
    332 
    333       *strp += 11;
    334       errmsg = cgen_parse_address (cd, strp, opindex,
    335 				   BFD_RELOC_OR1K_TLS_IE_HI16,
    336 				   & result_type, & value);
    337 
    338       if (**strp != ')')
    339 	return MISSING_CLOSING_PARENTHESIS;
    340       ++*strp;
    341       if (errmsg == NULL
    342 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    343 	value = (value >> 16) & 0xffff;
    344       *valuep = value;
    345       return errmsg;
    346     }
    347   else if (strncasecmp (*strp, "gottpofflo(", 11) == 0)
    348     {
    349       bfd_vma value;
    350 
    351       *strp += 11;
    352       errmsg = cgen_parse_address (cd, strp, opindex,
    353 				   BFD_RELOC_OR1K_TLS_IE_LO16,
    354 				   &result_type, &value);
    355       if (**strp != ')')
    356 	return MISSING_CLOSING_PARENTHESIS;
    357       ++*strp;
    358       if (errmsg == NULL
    359 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    360 	value &= 0xffff;
    361       *valuep = value;
    362       return errmsg;
    363     }
    364   else if (strncasecmp (*strp, "tpoffhi(", 8) == 0)
    365     {
    366       bfd_vma value;
    367 
    368       *strp += 8;
    369       errmsg = cgen_parse_address (cd, strp, opindex,
    370 				   BFD_RELOC_OR1K_TLS_LE_HI16,
    371 				   & result_type, & value);
    372 
    373       if (**strp != ')')
    374 	return MISSING_CLOSING_PARENTHESIS;
    375       ++*strp;
    376       if (errmsg == NULL
    377 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    378 	value = (value >> 16) & 0xffff;
    379       *valuep = value;
    380       return errmsg;
    381     }
    382   else if (strncasecmp (*strp, "tpofflo(", 8) == 0)
    383     {
    384       bfd_vma value;
    385 
    386       *strp += 8;
    387       errmsg = cgen_parse_address (cd, strp, opindex,
    388 				   BFD_RELOC_OR1K_TLS_LE_LO16,
    389 				   &result_type, &value);
    390       if (**strp != ')')
    391 	return MISSING_CLOSING_PARENTHESIS;
    392       ++*strp;
    393       if (errmsg == NULL
    394 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    395 	value &= 0xffff;
    396       *valuep = value;
    397       return errmsg;
    398     }
    399   else
    400     {
    401       long value;
    402       errmsg = cgen_parse_signed_integer (cd, strp, opindex, &value);
    403       ret = value;
    404     }
    405 
    406   if (errmsg == NULL)
    407     *valuep = ret;
    408 
    409   return errmsg;
    410 }
    411 
    412 static const char *
    413 parse_uimm16 (CGEN_CPU_DESC cd, const char ** strp, int opindex, unsigned long * valuep)
    414 {
    415   const char *errmsg = parse_simm16(cd, strp, opindex, (long *) valuep);
    416 
    417   if (errmsg == NULL)
    418     *valuep &= 0xffff;
    419   return errmsg;
    420 }
    421 
    422 /* -- */
    423 
    424 const char * or1k_cgen_parse_operand
    425   (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
    426 
    427 /* Main entry point for operand parsing.
    428 
    429    This function is basically just a big switch statement.  Earlier versions
    430    used tables to look up the function to use, but
    431    - if the table contains both assembler and disassembler functions then
    432      the disassembler contains much of the assembler and vice-versa,
    433    - there's a lot of inlining possibilities as things grow,
    434    - using a switch statement avoids the function call overhead.
    435 
    436    This function could be moved into `parse_insn_normal', but keeping it
    437    separate makes clear the interface between `parse_insn_normal' and each of
    438    the handlers.  */
    439 
    440 const char *
    441 or1k_cgen_parse_operand (CGEN_CPU_DESC cd,
    442 			   int opindex,
    443 			   const char ** strp,
    444 			   CGEN_FIELDS * fields)
    445 {
    446   const char * errmsg = NULL;
    447   /* Used by scalar operands that still need to be parsed.  */
    448   long junk ATTRIBUTE_UNUSED;
    449 
    450   switch (opindex)
    451     {
    452     case OR1K_OPERAND_DISP26 :
    453       {
    454         bfd_vma value = 0;
    455         errmsg = parse_disp26 (cd, strp, OR1K_OPERAND_DISP26, 0, NULL,  & value);
    456         fields->f_disp26 = value;
    457       }
    458       break;
    459     case OR1K_OPERAND_RA :
    460       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r2);
    461       break;
    462     case OR1K_OPERAND_RADF :
    463       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fdr, & fields->f_r1);
    464       break;
    465     case OR1K_OPERAND_RASF :
    466       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r2);
    467       break;
    468     case OR1K_OPERAND_RB :
    469       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r3);
    470       break;
    471     case OR1K_OPERAND_RBDF :
    472       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fdr, & fields->f_r1);
    473       break;
    474     case OR1K_OPERAND_RBSF :
    475       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r3);
    476       break;
    477     case OR1K_OPERAND_RD :
    478       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r1);
    479       break;
    480     case OR1K_OPERAND_RDDF :
    481       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fdr, & fields->f_r1);
    482       break;
    483     case OR1K_OPERAND_RDSF :
    484       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r1);
    485       break;
    486     case OR1K_OPERAND_SIMM16 :
    487       errmsg = parse_simm16 (cd, strp, OR1K_OPERAND_SIMM16, (long *) (& fields->f_simm16));
    488       break;
    489     case OR1K_OPERAND_SIMM16_SPLIT :
    490       errmsg = parse_simm16 (cd, strp, OR1K_OPERAND_SIMM16_SPLIT, (long *) (& fields->f_simm16_split));
    491       break;
    492     case OR1K_OPERAND_UIMM16 :
    493       errmsg = parse_uimm16 (cd, strp, OR1K_OPERAND_UIMM16, (unsigned long *) (& fields->f_uimm16));
    494       break;
    495     case OR1K_OPERAND_UIMM16_SPLIT :
    496       errmsg = parse_uimm16 (cd, strp, OR1K_OPERAND_UIMM16_SPLIT, (unsigned long *) (& fields->f_uimm16_split));
    497       break;
    498     case OR1K_OPERAND_UIMM6 :
    499       errmsg = cgen_parse_unsigned_integer (cd, strp, OR1K_OPERAND_UIMM6, (unsigned long *) (& fields->f_uimm6));
    500       break;
    501 
    502     default :
    503       /* xgettext:c-format */
    504       fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
    505       abort ();
    506   }
    507 
    508   return errmsg;
    509 }
    510 
    511 cgen_parse_fn * const or1k_cgen_parse_handlers[] =
    512 {
    513   parse_insn_normal,
    514 };
    515 
    516 void
    517 or1k_cgen_init_asm (CGEN_CPU_DESC cd)
    518 {
    519   or1k_cgen_init_opcode_table (cd);
    520   or1k_cgen_init_ibld_table (cd);
    521   cd->parse_handlers = & or1k_cgen_parse_handlers[0];
    522   cd->parse_operand = or1k_cgen_parse_operand;
    523 #ifdef CGEN_ASM_INIT_HOOK
    524 CGEN_ASM_INIT_HOOK
    525 #endif
    526 }
    527 
    528 
    529 
    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 
    652 /* Default insn parser.
    654 
    655    The syntax string is scanned and operands are parsed and stored in FIELDS.
    656    Relocs are queued as we go via other callbacks.
    657 
    658    ??? Note that this is currently an all-or-nothing parser.  If we fail to
    659    parse the instruction, we return 0 and the caller will start over from
    660    the beginning.  Backtracking will be necessary in parsing subexpressions,
    661    but that can be handled there.  Not handling backtracking here may get
    662    expensive in the case of the m68k.  Deal with later.
    663 
    664    Returns NULL for success, an error message for failure.  */
    665 
    666 static const char *
    667 parse_insn_normal (CGEN_CPU_DESC cd,
    668 		   const CGEN_INSN *insn,
    669 		   const char **strp,
    670 		   CGEN_FIELDS *fields)
    671 {
    672   /* ??? Runtime added insns not handled yet.  */
    673   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
    674   const char *str = *strp;
    675   const char *errmsg;
    676   const char *p;
    677   const CGEN_SYNTAX_CHAR_TYPE * syn;
    678 #ifdef CGEN_MNEMONIC_OPERANDS
    679   /* FIXME: wip */
    680   int past_opcode_p;
    681 #endif
    682 
    683   /* For now we assume the mnemonic is first (there are no leading operands).
    684      We can parse it without needing to set up operand parsing.
    685      GAS's input scrubber will ensure mnemonics are lowercase, but we may
    686      not be called from GAS.  */
    687   p = CGEN_INSN_MNEMONIC (insn);
    688   while (*p && TOLOWER (*p) == TOLOWER (*str))
    689     ++p, ++str;
    690 
    691   if (* p)
    692     return _("unrecognized instruction");
    693 
    694 #ifndef CGEN_MNEMONIC_OPERANDS
    695   if (* str && ! ISSPACE (* str))
    696     return _("unrecognized instruction");
    697 #endif
    698 
    699   CGEN_INIT_PARSE (cd);
    700   cgen_init_parse_operand (cd);
    701 #ifdef CGEN_MNEMONIC_OPERANDS
    702   past_opcode_p = 0;
    703 #endif
    704 
    705   /* We don't check for (*str != '\0') here because we want to parse
    706      any trailing fake arguments in the syntax string.  */
    707   syn = CGEN_SYNTAX_STRING (syntax);
    708 
    709   /* Mnemonics come first for now, ensure valid string.  */
    710   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
    711     abort ();
    712 
    713   ++syn;
    714 
    715   while (* syn != 0)
    716     {
    717       /* Non operand chars must match exactly.  */
    718       if (CGEN_SYNTAX_CHAR_P (* syn))
    719 	{
    720 	  /* FIXME: While we allow for non-GAS callers above, we assume the
    721 	     first char after the mnemonic part is a space.  */
    722 	  /* FIXME: We also take inappropriate advantage of the fact that
    723 	     GAS's input scrubber will remove extraneous blanks.  */
    724 	  if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
    725 	    {
    726 #ifdef CGEN_MNEMONIC_OPERANDS
    727 	      if (CGEN_SYNTAX_CHAR(* syn) == ' ')
    728 		past_opcode_p = 1;
    729 #endif
    730 	      ++ syn;
    731 	      ++ str;
    732 	    }
    733 	  else if (*str)
    734 	    {
    735 	      /* Syntax char didn't match.  Can't be this insn.  */
    736 	      static char msg [80];
    737 
    738 	      /* xgettext:c-format */
    739 	      sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
    740 		       CGEN_SYNTAX_CHAR(*syn), *str);
    741 	      return msg;
    742 	    }
    743 	  else
    744 	    {
    745 	      /* Ran out of input.  */
    746 	      static char msg [80];
    747 
    748 	      /* xgettext:c-format */
    749 	      sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
    750 		       CGEN_SYNTAX_CHAR(*syn));
    751 	      return msg;
    752 	    }
    753 	  continue;
    754 	}
    755 
    756 #ifdef CGEN_MNEMONIC_OPERANDS
    757       (void) past_opcode_p;
    758 #endif
    759       /* We have an operand of some sort.  */
    760       errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn), &str, fields);
    761       if (errmsg)
    762 	return errmsg;
    763 
    764       /* Done with this operand, continue with next one.  */
    765       ++ syn;
    766     }
    767 
    768   /* If we're at the end of the syntax string, we're done.  */
    769   if (* syn == 0)
    770     {
    771       /* FIXME: For the moment we assume a valid `str' can only contain
    772 	 blanks now.  IE: We needn't try again with a longer version of
    773 	 the insn and it is assumed that longer versions of insns appear
    774 	 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
    775       while (ISSPACE (* str))
    776 	++ str;
    777 
    778       if (* str != '\0')
    779 	return _("junk at end of line"); /* FIXME: would like to include `str' */
    780 
    781       return NULL;
    782     }
    783 
    784   /* We couldn't parse it.  */
    785   return _("unrecognized instruction");
    786 }
    787 
    788 /* Main entry point.
    790    This routine is called for each instruction to be assembled.
    791    STR points to the insn to be assembled.
    792    We assume all necessary tables have been initialized.
    793    The assembled instruction, less any fixups, is stored in BUF.
    794    Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
    795    still needs to be converted to target byte order, otherwise BUF is an array
    796    of bytes in target byte order.
    797    The result is a pointer to the insn's entry in the opcode table,
    798    or NULL if an error occured (an error message will have already been
    799    printed).
    800 
    801    Note that when processing (non-alias) macro-insns,
    802    this function recurses.
    803 
    804    ??? It's possible to make this cpu-independent.
    805    One would have to deal with a few minor things.
    806    At this point in time doing so would be more of a curiosity than useful
    807    [for example this file isn't _that_ big], but keeping the possibility in
    808    mind helps keep the design clean.  */
    809 
    810 const CGEN_INSN *
    811 or1k_cgen_assemble_insn (CGEN_CPU_DESC cd,
    812 			   const char *str,
    813 			   CGEN_FIELDS *fields,
    814 			   CGEN_INSN_BYTES_PTR buf,
    815 			   char **errmsg)
    816 {
    817   const char *start;
    818   CGEN_INSN_LIST *ilist;
    819   const char *parse_errmsg = NULL;
    820   const char *insert_errmsg = NULL;
    821   int recognized_mnemonic = 0;
    822 
    823   /* Skip leading white space.  */
    824   while (ISSPACE (* str))
    825     ++ str;
    826 
    827   /* The instructions are stored in hashed lists.
    828      Get the first in the list.  */
    829   ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
    830 
    831   /* Keep looking until we find a match.  */
    832   start = str;
    833   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
    834     {
    835       const CGEN_INSN *insn = ilist->insn;
    836       recognized_mnemonic = 1;
    837 
    838 #ifdef CGEN_VALIDATE_INSN_SUPPORTED
    839       /* Not usually needed as unsupported opcodes
    840 	 shouldn't be in the hash lists.  */
    841       /* Is this insn supported by the selected cpu?  */
    842       if (! or1k_cgen_insn_supported (cd, insn))
    843 	continue;
    844 #endif
    845       /* If the RELAXED attribute is set, this is an insn that shouldn't be
    846 	 chosen immediately.  Instead, it is used during assembler/linker
    847 	 relaxation if possible.  */
    848       if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
    849 	continue;
    850 
    851       str = start;
    852 
    853       /* Skip this insn if str doesn't look right lexically.  */
    854       if (CGEN_INSN_RX (insn) != NULL &&
    855 	  regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
    856 	continue;
    857 
    858       /* Allow parse/insert handlers to obtain length of insn.  */
    859       CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
    860 
    861       parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
    862       if (parse_errmsg != NULL)
    863 	continue;
    864 
    865       /* ??? 0 is passed for `pc'.  */
    866       insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
    867 						 (bfd_vma) 0);
    868       if (insert_errmsg != NULL)
    869         continue;
    870 
    871       /* It is up to the caller to actually output the insn and any
    872          queued relocs.  */
    873       return insn;
    874     }
    875 
    876   {
    877     static char errbuf[150];
    878     const char *tmp_errmsg;
    879 #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
    880 #define be_verbose 1
    881 #else
    882 #define be_verbose 0
    883 #endif
    884 
    885     if (be_verbose)
    886       {
    887 	/* If requesting verbose error messages, use insert_errmsg.
    888 	   Failing that, use parse_errmsg.  */
    889 	tmp_errmsg = (insert_errmsg ? insert_errmsg :
    890 		      parse_errmsg ? parse_errmsg :
    891 		      recognized_mnemonic ?
    892 		      _("unrecognized form of instruction") :
    893 		      _("unrecognized instruction"));
    894 
    895 	if (strlen (start) > 50)
    896 	  /* xgettext:c-format */
    897 	  sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
    898 	else
    899 	  /* xgettext:c-format */
    900 	  sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
    901       }
    902     else
    903       {
    904 	if (strlen (start) > 50)
    905 	  /* xgettext:c-format */
    906 	  sprintf (errbuf, _("bad instruction `%.50s...'"), start);
    907 	else
    908 	  /* xgettext:c-format */
    909 	  sprintf (errbuf, _("bad instruction `%.50s'"), start);
    910       }
    911 
    912     *errmsg = errbuf;
    913     return NULL;
    914   }
    915 }
    916