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