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