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