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