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-2025 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 "fr30-desc.h"
     36 #include "fr30-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 /* Handle register lists for LDMx and STMx.  */
     55 
     56 static int
     57 parse_register_number (const char **strp)
     58 {
     59   int regno;
     60 
     61   if (**strp < '0' || **strp > '9')
     62     return -1; /* Error.  */
     63   regno = **strp - '0';
     64   ++*strp;
     65 
     66   if (**strp >= '0' && **strp <= '9')
     67     {
     68       regno = regno * 10 + (**strp - '0');
     69       ++*strp;
     70     }
     71 
     72   return regno;
     73 }
     74 
     75 static const char *
     76 parse_register_list (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
     77 		     const char **strp,
     78 		     int opindex ATTRIBUTE_UNUSED,
     79 		     unsigned long *valuep,
     80 		     int high_low,   /* 0 == high, 1 == low.  */
     81 		     int load_store) /* 0 == load, 1 == store.  */
     82 {
     83   *valuep = 0;
     84   while (**strp && **strp != ')')
     85     {
     86       int regno;
     87 
     88       if (**strp != 'R' && **strp != 'r')
     89 	break;
     90       ++*strp;
     91 
     92       regno = parse_register_number (strp);
     93       if (regno == -1)
     94 	return _("Register number is not valid");
     95       if (regno > 7 && !high_low)
     96 	return _("Register must be between r0 and r7");
     97       if (regno < 8 && high_low)
     98 	return _("Register must be between r8 and r15");
     99 
    100       if (high_low)
    101 	regno -= 8;
    102 
    103       if (load_store) /* Mask is reversed for store.  */
    104 	*valuep |= 0x80 >> regno;
    105       else
    106 	*valuep |= 1 << regno;
    107 
    108       if (**strp == ',')
    109 	{
    110 	  if (*(*strp + 1) == ')')
    111 	    break;
    112 	  ++*strp;
    113 	}
    114     }
    115 
    116   if (!*strp || **strp != ')')
    117     return _("Register list is not valid");
    118 
    119   return NULL;
    120 }
    121 
    122 static const char *
    123 parse_low_register_list_ld (CGEN_CPU_DESC cd,
    124 			    const char **strp,
    125 			    int opindex,
    126 			    unsigned long *valuep)
    127 {
    128   return parse_register_list (cd, strp, opindex, valuep,
    129 			      0 /* Low.  */, 0 /* Load.  */);
    130 }
    131 
    132 static const char *
    133 parse_hi_register_list_ld (CGEN_CPU_DESC cd,
    134 			   const char **strp,
    135 			   int opindex,
    136 			   unsigned long *valuep)
    137 {
    138   return parse_register_list (cd, strp, opindex, valuep,
    139 			      1 /* High.  */, 0 /* Load.  */);
    140 }
    141 
    142 static const char *
    143 parse_low_register_list_st (CGEN_CPU_DESC cd,
    144 			    const char **strp,
    145 			    int opindex,
    146 			    unsigned long *valuep)
    147 {
    148   return parse_register_list (cd, strp, opindex, valuep,
    149 			      0 /* Low.  */, 1 /* Store.  */);
    150 }
    151 
    152 static const char *
    153 parse_hi_register_list_st (CGEN_CPU_DESC cd,
    154 			   const char **strp,
    155 			   int opindex,
    156 			   unsigned long *valuep)
    157 {
    158   return parse_register_list (cd, strp, opindex, valuep,
    159 			      1 /* High.  */, 1 /* Store.  */);
    160 }
    161 
    162 /* -- */
    163 
    164 const char * fr30_cgen_parse_operand
    165   (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
    166 
    167 /* Main entry point for operand parsing.
    168 
    169    This function is basically just a big switch statement.  Earlier versions
    170    used tables to look up the function to use, but
    171    - if the table contains both assembler and disassembler functions then
    172      the disassembler contains much of the assembler and vice-versa,
    173    - there's a lot of inlining possibilities as things grow,
    174    - using a switch statement avoids the function call overhead.
    175 
    176    This function could be moved into `parse_insn_normal', but keeping it
    177    separate makes clear the interface between `parse_insn_normal' and each of
    178    the handlers.  */
    179 
    180 const char *
    181 fr30_cgen_parse_operand (CGEN_CPU_DESC cd,
    182 			   int opindex,
    183 			   const char ** strp,
    184 			   CGEN_FIELDS * fields)
    185 {
    186   const char * errmsg = NULL;
    187   /* Used by scalar operands that still need to be parsed.  */
    188   long junk ATTRIBUTE_UNUSED;
    189 
    190   switch (opindex)
    191     {
    192     case FR30_OPERAND_CRI :
    193       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_cr_names, & fields->f_CRi);
    194       break;
    195     case FR30_OPERAND_CRJ :
    196       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_cr_names, & fields->f_CRj);
    197       break;
    198     case FR30_OPERAND_R13 :
    199       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_h_r13, & junk);
    200       break;
    201     case FR30_OPERAND_R14 :
    202       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_h_r14, & junk);
    203       break;
    204     case FR30_OPERAND_R15 :
    205       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_h_r15, & junk);
    206       break;
    207     case FR30_OPERAND_RI :
    208       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_gr_names, & fields->f_Ri);
    209       break;
    210     case FR30_OPERAND_RIC :
    211       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_gr_names, & fields->f_Ric);
    212       break;
    213     case FR30_OPERAND_RJ :
    214       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_gr_names, & fields->f_Rj);
    215       break;
    216     case FR30_OPERAND_RJC :
    217       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_gr_names, & fields->f_Rjc);
    218       break;
    219     case FR30_OPERAND_RS1 :
    220       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_dr_names, & fields->f_Rs1);
    221       break;
    222     case FR30_OPERAND_RS2 :
    223       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_dr_names, & fields->f_Rs2);
    224       break;
    225     case FR30_OPERAND_CC :
    226       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_CC, (unsigned long *) (& fields->f_cc));
    227       break;
    228     case FR30_OPERAND_CCC :
    229       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_CCC, (unsigned long *) (& fields->f_ccc));
    230       break;
    231     case FR30_OPERAND_DIR10 :
    232       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_DIR10, (unsigned long *) (& fields->f_dir10));
    233       break;
    234     case FR30_OPERAND_DIR8 :
    235       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_DIR8, (unsigned long *) (& fields->f_dir8));
    236       break;
    237     case FR30_OPERAND_DIR9 :
    238       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_DIR9, (unsigned long *) (& fields->f_dir9));
    239       break;
    240     case FR30_OPERAND_DISP10 :
    241       errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_DISP10, (long *) (& fields->f_disp10));
    242       break;
    243     case FR30_OPERAND_DISP8 :
    244       errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_DISP8, (long *) (& fields->f_disp8));
    245       break;
    246     case FR30_OPERAND_DISP9 :
    247       errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_DISP9, (long *) (& fields->f_disp9));
    248       break;
    249     case FR30_OPERAND_I20 :
    250       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_I20, (unsigned long *) (& fields->f_i20));
    251       break;
    252     case FR30_OPERAND_I32 :
    253       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_I32, (unsigned long *) (& fields->f_i32));
    254       break;
    255     case FR30_OPERAND_I8 :
    256       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_I8, (unsigned long *) (& fields->f_i8));
    257       break;
    258     case FR30_OPERAND_LABEL12 :
    259       {
    260         bfd_vma value = 0;
    261         errmsg = cgen_parse_address (cd, strp, FR30_OPERAND_LABEL12, 0, NULL,  & value);
    262         fields->f_rel12 = value;
    263       }
    264       break;
    265     case FR30_OPERAND_LABEL9 :
    266       {
    267         bfd_vma value = 0;
    268         errmsg = cgen_parse_address (cd, strp, FR30_OPERAND_LABEL9, 0, NULL,  & value);
    269         fields->f_rel9 = value;
    270       }
    271       break;
    272     case FR30_OPERAND_M4 :
    273       errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_M4, (long *) (& fields->f_m4));
    274       break;
    275     case FR30_OPERAND_PS :
    276       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_h_ps, & junk);
    277       break;
    278     case FR30_OPERAND_REGLIST_HI_LD :
    279       errmsg = parse_hi_register_list_ld (cd, strp, FR30_OPERAND_REGLIST_HI_LD, (unsigned long *) (& fields->f_reglist_hi_ld));
    280       break;
    281     case FR30_OPERAND_REGLIST_HI_ST :
    282       errmsg = parse_hi_register_list_st (cd, strp, FR30_OPERAND_REGLIST_HI_ST, (unsigned long *) (& fields->f_reglist_hi_st));
    283       break;
    284     case FR30_OPERAND_REGLIST_LOW_LD :
    285       errmsg = parse_low_register_list_ld (cd, strp, FR30_OPERAND_REGLIST_LOW_LD, (unsigned long *) (& fields->f_reglist_low_ld));
    286       break;
    287     case FR30_OPERAND_REGLIST_LOW_ST :
    288       errmsg = parse_low_register_list_st (cd, strp, FR30_OPERAND_REGLIST_LOW_ST, (unsigned long *) (& fields->f_reglist_low_st));
    289       break;
    290     case FR30_OPERAND_S10 :
    291       errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_S10, (long *) (& fields->f_s10));
    292       break;
    293     case FR30_OPERAND_U10 :
    294       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_U10, (unsigned long *) (& fields->f_u10));
    295       break;
    296     case FR30_OPERAND_U4 :
    297       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_U4, (unsigned long *) (& fields->f_u4));
    298       break;
    299     case FR30_OPERAND_U4C :
    300       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_U4C, (unsigned long *) (& fields->f_u4c));
    301       break;
    302     case FR30_OPERAND_U8 :
    303       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_U8, (unsigned long *) (& fields->f_u8));
    304       break;
    305     case FR30_OPERAND_UDISP6 :
    306       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_UDISP6, (unsigned long *) (& fields->f_udisp6));
    307       break;
    308 
    309     default :
    310       /* xgettext:c-format */
    311       opcodes_error_handler
    312 	(_("internal error: unrecognized field %d while parsing"),
    313 	 opindex);
    314       abort ();
    315   }
    316 
    317   return errmsg;
    318 }
    319 
    320 cgen_parse_fn * const fr30_cgen_parse_handlers[] =
    321 {
    322   parse_insn_normal,
    323 };
    324 
    325 void
    326 fr30_cgen_init_asm (CGEN_CPU_DESC cd)
    327 {
    328   fr30_cgen_init_opcode_table (cd);
    329   fr30_cgen_init_ibld_table (cd);
    330   cd->parse_handlers = & fr30_cgen_parse_handlers[0];
    331   cd->parse_operand = fr30_cgen_parse_operand;
    332 #ifdef CGEN_ASM_INIT_HOOK
    333 CGEN_ASM_INIT_HOOK
    334 #endif
    335 }
    336 
    337 
    338 
    340 /* Regex construction routine.
    341 
    342    This translates an opcode syntax string into a regex string,
    343    by replacing any non-character syntax element (such as an
    344    opcode) with the pattern '.*'
    345 
    346    It then compiles the regex and stores it in the opcode, for
    347    later use by fr30_cgen_assemble_insn
    348 
    349    Returns NULL for success, an error message for failure.  */
    350 
    351 char *
    352 fr30_cgen_build_insn_regex (CGEN_INSN *insn)
    353 {
    354   CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
    355   const char *mnem = CGEN_INSN_MNEMONIC (insn);
    356   char rxbuf[CGEN_MAX_RX_ELEMENTS];
    357   char *rx = rxbuf;
    358   const CGEN_SYNTAX_CHAR_TYPE *syn;
    359   int reg_err;
    360 
    361   syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
    362 
    363   /* Mnemonics come first in the syntax string.  */
    364   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
    365     return _("missing mnemonic in syntax string");
    366   ++syn;
    367 
    368   /* Generate a case sensitive regular expression that emulates case
    369      insensitive matching in the "C" locale.  We cannot generate a case
    370      insensitive regular expression because in Turkish locales, 'i' and 'I'
    371      are not equal modulo case conversion.  */
    372 
    373   /* Copy the literal mnemonic out of the insn.  */
    374   for (; *mnem; mnem++)
    375     {
    376       char c = *mnem;
    377 
    378       if (ISALPHA (c))
    379 	{
    380 	  *rx++ = '[';
    381 	  *rx++ = TOLOWER (c);
    382 	  *rx++ = TOUPPER (c);
    383 	  *rx++ = ']';
    384 	}
    385       else
    386 	*rx++ = c;
    387     }
    388 
    389   /* Copy any remaining literals from the syntax string into the rx.  */
    390   for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
    391     {
    392       if (CGEN_SYNTAX_CHAR_P (* syn))
    393 	{
    394 	  char c = CGEN_SYNTAX_CHAR (* syn);
    395 
    396 	  switch (c)
    397 	    {
    398 	      /* Escape any regex metacharacters in the syntax.  */
    399 	    case '.': case '[': case '\\':
    400 	    case '*': case '^': case '$':
    401 
    402 #ifdef CGEN_ESCAPE_EXTENDED_REGEX
    403 	    case '?': case '{': case '}':
    404 	    case '(': case ')': case '*':
    405 	    case '|': case '+': case ']':
    406 #endif
    407 	      *rx++ = '\\';
    408 	      *rx++ = c;
    409 	      break;
    410 
    411 	    default:
    412 	      if (ISALPHA (c))
    413 		{
    414 		  *rx++ = '[';
    415 		  *rx++ = TOLOWER (c);
    416 		  *rx++ = TOUPPER (c);
    417 		  *rx++ = ']';
    418 		}
    419 	      else
    420 		*rx++ = c;
    421 	      break;
    422 	    }
    423 	}
    424       else
    425 	{
    426 	  /* Replace non-syntax fields with globs.  */
    427 	  *rx++ = '.';
    428 	  *rx++ = '*';
    429 	}
    430     }
    431 
    432   /* Trailing whitespace ok.  */
    433   * rx++ = '[';
    434   * rx++ = ' ';
    435   * rx++ = '\t';
    436   * rx++ = ']';
    437   * rx++ = '*';
    438 
    439   /* But anchor it after that.  */
    440   * rx++ = '$';
    441   * rx = '\0';
    442 
    443   CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
    444   reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
    445 
    446   if (reg_err == 0)
    447     return NULL;
    448   else
    449     {
    450       static char msg[80];
    451 
    452       regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
    453       regfree ((regex_t *) CGEN_INSN_RX (insn));
    454       free (CGEN_INSN_RX (insn));
    455       (CGEN_INSN_RX (insn)) = NULL;
    456       return msg;
    457     }
    458 }
    459 
    460 
    461 /* Default insn parser.
    463 
    464    The syntax string is scanned and operands are parsed and stored in FIELDS.
    465    Relocs are queued as we go via other callbacks.
    466 
    467    ??? Note that this is currently an all-or-nothing parser.  If we fail to
    468    parse the instruction, we return 0 and the caller will start over from
    469    the beginning.  Backtracking will be necessary in parsing subexpressions,
    470    but that can be handled there.  Not handling backtracking here may get
    471    expensive in the case of the m68k.  Deal with later.
    472 
    473    Returns NULL for success, an error message for failure.  */
    474 
    475 static const char *
    476 parse_insn_normal (CGEN_CPU_DESC cd,
    477 		   const CGEN_INSN *insn,
    478 		   const char **strp,
    479 		   CGEN_FIELDS *fields)
    480 {
    481   /* ??? Runtime added insns not handled yet.  */
    482   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
    483   const char *str = *strp;
    484   const char *errmsg;
    485   const char *p;
    486   const CGEN_SYNTAX_CHAR_TYPE * syn;
    487 #ifdef CGEN_MNEMONIC_OPERANDS
    488   /* FIXME: wip */
    489   int past_opcode_p;
    490 #endif
    491 
    492   /* For now we assume the mnemonic is first (there are no leading operands).
    493      We can parse it without needing to set up operand parsing.
    494      GAS's input scrubber will ensure mnemonics are lowercase, but we may
    495      not be called from GAS.  */
    496   p = CGEN_INSN_MNEMONIC (insn);
    497   while (*p && TOLOWER (*p) == TOLOWER (*str))
    498     ++p, ++str;
    499 
    500   if (* p)
    501     return _("unrecognized instruction");
    502 
    503 #ifndef CGEN_MNEMONIC_OPERANDS
    504   if (* str && ! ISSPACE (* str))
    505     return _("unrecognized instruction");
    506 #endif
    507 
    508   CGEN_INIT_PARSE (cd);
    509   cgen_init_parse_operand (cd);
    510 #ifdef CGEN_MNEMONIC_OPERANDS
    511   past_opcode_p = 0;
    512 #endif
    513 
    514   /* We don't check for (*str != '\0') here because we want to parse
    515      any trailing fake arguments in the syntax string.  */
    516   syn = CGEN_SYNTAX_STRING (syntax);
    517 
    518   /* Mnemonics come first for now, ensure valid string.  */
    519   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
    520     abort ();
    521 
    522   ++syn;
    523 
    524   while (* syn != 0)
    525     {
    526       /* Non operand chars must match exactly.  */
    527       if (CGEN_SYNTAX_CHAR_P (* syn))
    528 	{
    529 	  /* FIXME: While we allow for non-GAS callers above, we assume the
    530 	     first char after the mnemonic part is a space.  */
    531 	  /* FIXME: We also take inappropriate advantage of the fact that
    532 	     GAS's input scrubber will remove extraneous blanks.  */
    533 	  if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
    534 	    {
    535 #ifdef CGEN_MNEMONIC_OPERANDS
    536 	      if (CGEN_SYNTAX_CHAR(* syn) == ' ')
    537 		past_opcode_p = 1;
    538 #endif
    539 	      ++ syn;
    540 	      ++ str;
    541 	    }
    542 	  else if (*str)
    543 	    {
    544 	      /* Syntax char didn't match.  Can't be this insn.  */
    545 	      static char msg [80];
    546 
    547 	      /* xgettext:c-format */
    548 	      sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
    549 		       CGEN_SYNTAX_CHAR(*syn), *str);
    550 	      return msg;
    551 	    }
    552 	  else
    553 	    {
    554 	      /* Ran out of input.  */
    555 	      static char msg [80];
    556 
    557 	      /* xgettext:c-format */
    558 	      sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
    559 		       CGEN_SYNTAX_CHAR(*syn));
    560 	      return msg;
    561 	    }
    562 	  continue;
    563 	}
    564 
    565 #ifdef CGEN_MNEMONIC_OPERANDS
    566       (void) past_opcode_p;
    567 #endif
    568       /* We have an operand of some sort.  */
    569       errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn), &str, fields);
    570       if (errmsg)
    571 	return errmsg;
    572 
    573       /* Done with this operand, continue with next one.  */
    574       ++ syn;
    575     }
    576 
    577   /* If we're at the end of the syntax string, we're done.  */
    578   if (* syn == 0)
    579     {
    580       /* FIXME: For the moment we assume a valid `str' can only contain
    581 	 blanks now.  IE: We needn't try again with a longer version of
    582 	 the insn and it is assumed that longer versions of insns appear
    583 	 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
    584       while (ISSPACE (* str))
    585 	++ str;
    586 
    587       if (* str != '\0')
    588 	return _("junk at end of line"); /* FIXME: would like to include `str' */
    589 
    590       return NULL;
    591     }
    592 
    593   /* We couldn't parse it.  */
    594   return _("unrecognized instruction");
    595 }
    596 
    597 /* Main entry point.
    599    This routine is called for each instruction to be assembled.
    600    STR points to the insn to be assembled.
    601    We assume all necessary tables have been initialized.
    602    The assembled instruction, less any fixups, is stored in BUF.
    603    Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
    604    still needs to be converted to target byte order, otherwise BUF is an array
    605    of bytes in target byte order.
    606    The result is a pointer to the insn's entry in the opcode table,
    607    or NULL if an error occured (an error message will have already been
    608    printed).
    609 
    610    Note that when processing (non-alias) macro-insns,
    611    this function recurses.
    612 
    613    ??? It's possible to make this cpu-independent.
    614    One would have to deal with a few minor things.
    615    At this point in time doing so would be more of a curiosity than useful
    616    [for example this file isn't _that_ big], but keeping the possibility in
    617    mind helps keep the design clean.  */
    618 
    619 const CGEN_INSN *
    620 fr30_cgen_assemble_insn (CGEN_CPU_DESC cd,
    621 			   const char *str,
    622 			   CGEN_FIELDS *fields,
    623 			   CGEN_INSN_BYTES_PTR buf,
    624 			   char **errmsg)
    625 {
    626   const char *start;
    627   CGEN_INSN_LIST *ilist;
    628   const char *parse_errmsg = NULL;
    629   const char *insert_errmsg = NULL;
    630   int recognized_mnemonic = 0;
    631 
    632   /* Skip leading white space.  */
    633   while (ISSPACE (* str))
    634     ++ str;
    635 
    636   /* The instructions are stored in hashed lists.
    637      Get the first in the list.  */
    638   ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
    639 
    640   /* Keep looking until we find a match.  */
    641   start = str;
    642   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
    643     {
    644       const CGEN_INSN *insn = ilist->insn;
    645       recognized_mnemonic = 1;
    646 
    647 #ifdef CGEN_VALIDATE_INSN_SUPPORTED
    648       /* Not usually needed as unsupported opcodes
    649 	 shouldn't be in the hash lists.  */
    650       /* Is this insn supported by the selected cpu?  */
    651       if (! fr30_cgen_insn_supported (cd, insn))
    652 	continue;
    653 #endif
    654       /* If the RELAXED attribute is set, this is an insn that shouldn't be
    655 	 chosen immediately.  Instead, it is used during assembler/linker
    656 	 relaxation if possible.  */
    657       if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
    658 	continue;
    659 
    660       str = start;
    661 
    662       /* Skip this insn if str doesn't look right lexically.  */
    663       if (CGEN_INSN_RX (insn) != NULL &&
    664 	  regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
    665 	continue;
    666 
    667       /* Allow parse/insert handlers to obtain length of insn.  */
    668       CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
    669 
    670       parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
    671       if (parse_errmsg != NULL)
    672 	continue;
    673 
    674       /* ??? 0 is passed for `pc'.  */
    675       insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
    676 						 (bfd_vma) 0);
    677       if (insert_errmsg != NULL)
    678         continue;
    679 
    680       /* It is up to the caller to actually output the insn and any
    681          queued relocs.  */
    682       return insn;
    683     }
    684 
    685   {
    686     static char errbuf[150];
    687     const char *tmp_errmsg;
    688 #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
    689 #define be_verbose 1
    690 #else
    691 #define be_verbose 0
    692 #endif
    693 
    694     if (be_verbose)
    695       {
    696 	/* If requesting verbose error messages, use insert_errmsg.
    697 	   Failing that, use parse_errmsg.  */
    698 	tmp_errmsg = (insert_errmsg ? insert_errmsg :
    699 		      parse_errmsg ? parse_errmsg :
    700 		      recognized_mnemonic ?
    701 		      _("unrecognized form of instruction") :
    702 		      _("unrecognized instruction"));
    703 
    704 	if (strlen (start) > 50)
    705 	  /* xgettext:c-format */
    706 	  sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
    707 	else
    708 	  /* xgettext:c-format */
    709 	  sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
    710       }
    711     else
    712       {
    713 	if (strlen (start) > 50)
    714 	  /* xgettext:c-format */
    715 	  sprintf (errbuf, _("bad instruction `%.50s...'"), start);
    716 	else
    717 	  /* xgettext:c-format */
    718 	  sprintf (errbuf, _("bad instruction `%.50s'"), start);
    719       }
    720 
    721     *errmsg = errbuf;
    722     return NULL;
    723   }
    724 }
    725