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