Back to index

cell-binutils  2.17cvs20070401
m32r-asm.c
Go to the documentation of this file.
00001 /* Assembler interface for targets using CGEN. -*- C -*-
00002    CGEN: Cpu tools GENerator
00003 
00004    THIS FILE IS MACHINE GENERATED WITH CGEN.
00005    - the resultant file is machine generated, cgen-asm.in isn't
00006 
00007    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2005
00008    Free Software Foundation, Inc.
00009 
00010    This file is part of the GNU Binutils and GDB, the GNU debugger.
00011 
00012    This program is free software; you can redistribute it and/or modify
00013    it under the terms of the GNU General Public License as published by
00014    the Free Software Foundation; either version 2, or (at your option)
00015    any later version.
00016 
00017    This program is distributed in the hope that it will be useful,
00018    but WITHOUT ANY WARRANTY; without even the implied warranty of
00019    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020    GNU General Public License for more details.
00021 
00022    You should have received a copy of the GNU General Public License
00023    along with this program; if not, write to the Free Software Foundation, Inc.,
00024    51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00025 
00026 /* ??? Eventually more and more of this stuff can go to cpu-independent files.
00027    Keep that in mind.  */
00028 
00029 #include "sysdep.h"
00030 #include <stdio.h>
00031 #include "ansidecl.h"
00032 #include "bfd.h"
00033 #include "symcat.h"
00034 #include "m32r-desc.h"
00035 #include "m32r-opc.h"
00036 #include "opintl.h"
00037 #include "xregex.h"
00038 #include "libiberty.h"
00039 #include "safe-ctype.h"
00040 
00041 #undef  min
00042 #define min(a,b) ((a) < (b) ? (a) : (b))
00043 #undef  max
00044 #define max(a,b) ((a) > (b) ? (a) : (b))
00045 
00046 static const char * parse_insn_normal
00047   (CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *);
00048 
00049 /* -- assembler routines inserted here.  */
00050 
00051 /* -- asm.c */
00052 static const char * MISSING_CLOSING_PARENTHESIS = N_("missing `)'");
00053 
00054 /* Handle '#' prefixes (i.e. skip over them).  */
00055 
00056 static const char *
00057 parse_hash (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
00058            const char **strp,
00059            int opindex ATTRIBUTE_UNUSED,
00060            long *valuep ATTRIBUTE_UNUSED)
00061 {
00062   if (**strp == '#')
00063     ++*strp;
00064   return NULL;
00065 }
00066 
00067 /* Handle shigh(), high().  */
00068 
00069 static const char *
00070 parse_hi16 (CGEN_CPU_DESC cd,
00071            const char **strp,
00072            int opindex,
00073            unsigned long *valuep)
00074 {
00075   const char *errmsg;
00076   enum cgen_parse_operand_result result_type;
00077   bfd_vma value;
00078 
00079   if (**strp == '#')
00080     ++*strp;
00081 
00082   if (strncasecmp (*strp, "high(", 5) == 0)
00083     {
00084       *strp += 5;
00085       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_HI16_ULO,
00086                                & result_type, & value);
00087       if (**strp != ')')
00088        return MISSING_CLOSING_PARENTHESIS;
00089       ++*strp;
00090       if (errmsg == NULL
00091          && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
00092        {
00093          value >>= 16;
00094          value &= 0xffff;
00095        }
00096       *valuep = value;
00097       return errmsg;
00098     }
00099   else if (strncasecmp (*strp, "shigh(", 6) == 0)
00100     {
00101       *strp += 6;
00102       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_HI16_SLO,
00103                                & result_type, & value);
00104       if (**strp != ')')
00105        return MISSING_CLOSING_PARENTHESIS;
00106       ++*strp;
00107       if (errmsg == NULL
00108          && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
00109        {
00110          value += 0x8000;
00111          value >>= 16;
00112          value &= 0xffff;
00113        }
00114       *valuep = value;
00115       return errmsg;
00116     }
00117 
00118   return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
00119 }
00120 
00121 /* Handle low() in a signed context.  Also handle sda().
00122    The signedness of the value doesn't matter to low(), but this also
00123    handles the case where low() isn't present.  */
00124 
00125 static const char *
00126 parse_slo16 (CGEN_CPU_DESC cd,
00127             const char ** strp,
00128             int opindex,
00129             long * valuep)
00130 {
00131   const char *errmsg;
00132   enum cgen_parse_operand_result result_type;
00133   bfd_vma value;
00134 
00135   if (**strp == '#')
00136     ++*strp;
00137 
00138   if (strncasecmp (*strp, "low(", 4) == 0)
00139     {
00140       *strp += 4;
00141       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_LO16,
00142                                & result_type, & value);
00143       if (**strp != ')')
00144        return MISSING_CLOSING_PARENTHESIS;
00145       ++*strp;
00146       if (errmsg == NULL
00147          && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
00148        value = ((value & 0xffff) ^ 0x8000) - 0x8000;
00149       *valuep = value;
00150       return errmsg;
00151     }
00152 
00153   if (strncasecmp (*strp, "sda(", 4) == 0)
00154     {
00155       *strp += 4;
00156       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_SDA16,
00157                                NULL, & value);
00158       if (**strp != ')')
00159        return MISSING_CLOSING_PARENTHESIS;
00160       ++*strp;
00161       *valuep = value;
00162       return errmsg;
00163     }
00164 
00165   return cgen_parse_signed_integer (cd, strp, opindex, valuep);
00166 }
00167 
00168 /* Handle low() in an unsigned context.
00169    The signedness of the value doesn't matter to low(), but this also
00170    handles the case where low() isn't present.  */
00171 
00172 static const char *
00173 parse_ulo16 (CGEN_CPU_DESC cd,
00174             const char **strp,
00175             int opindex,
00176             unsigned long *valuep)
00177 {
00178   const char *errmsg;
00179   enum cgen_parse_operand_result result_type;
00180   bfd_vma value;
00181 
00182   if (**strp == '#')
00183     ++*strp;
00184 
00185   if (strncasecmp (*strp, "low(", 4) == 0)
00186     {
00187       *strp += 4;
00188       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_LO16,
00189                                & result_type, & value);
00190       if (**strp != ')')
00191        return MISSING_CLOSING_PARENTHESIS;
00192       ++*strp;
00193       if (errmsg == NULL
00194          && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
00195        value &= 0xffff;
00196       *valuep = value;
00197       return errmsg;
00198     }
00199 
00200   return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
00201 }
00202 
00203 /* -- */
00204 
00205 const char * m32r_cgen_parse_operand
00206   (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
00207 
00208 /* Main entry point for operand parsing.
00209 
00210    This function is basically just a big switch statement.  Earlier versions
00211    used tables to look up the function to use, but
00212    - if the table contains both assembler and disassembler functions then
00213      the disassembler contains much of the assembler and vice-versa,
00214    - there's a lot of inlining possibilities as things grow,
00215    - using a switch statement avoids the function call overhead.
00216 
00217    This function could be moved into `parse_insn_normal', but keeping it
00218    separate makes clear the interface between `parse_insn_normal' and each of
00219    the handlers.  */
00220 
00221 const char *
00222 m32r_cgen_parse_operand (CGEN_CPU_DESC cd,
00223                         int opindex,
00224                         const char ** strp,
00225                         CGEN_FIELDS * fields)
00226 {
00227   const char * errmsg = NULL;
00228   /* Used by scalar operands that still need to be parsed.  */
00229   long junk ATTRIBUTE_UNUSED;
00230 
00231   switch (opindex)
00232     {
00233     case M32R_OPERAND_ACC :
00234       errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_h_accums, & fields->f_acc);
00235       break;
00236     case M32R_OPERAND_ACCD :
00237       errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_h_accums, & fields->f_accd);
00238       break;
00239     case M32R_OPERAND_ACCS :
00240       errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_h_accums, & fields->f_accs);
00241       break;
00242     case M32R_OPERAND_DCR :
00243       errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_cr_names, & fields->f_r1);
00244       break;
00245     case M32R_OPERAND_DISP16 :
00246       {
00247         bfd_vma value = 0;
00248         errmsg = cgen_parse_address (cd, strp, M32R_OPERAND_DISP16, 0, NULL,  & value);
00249         fields->f_disp16 = value;
00250       }
00251       break;
00252     case M32R_OPERAND_DISP24 :
00253       {
00254         bfd_vma value = 0;
00255         errmsg = cgen_parse_address (cd, strp, M32R_OPERAND_DISP24, 0, NULL,  & value);
00256         fields->f_disp24 = value;
00257       }
00258       break;
00259     case M32R_OPERAND_DISP8 :
00260       {
00261         bfd_vma value = 0;
00262         errmsg = cgen_parse_address (cd, strp, M32R_OPERAND_DISP8, 0, NULL,  & value);
00263         fields->f_disp8 = value;
00264       }
00265       break;
00266     case M32R_OPERAND_DR :
00267       errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_gr_names, & fields->f_r1);
00268       break;
00269     case M32R_OPERAND_HASH :
00270       errmsg = parse_hash (cd, strp, M32R_OPERAND_HASH, (long *) (& junk));
00271       break;
00272     case M32R_OPERAND_HI16 :
00273       errmsg = parse_hi16 (cd, strp, M32R_OPERAND_HI16, (unsigned long *) (& fields->f_hi16));
00274       break;
00275     case M32R_OPERAND_IMM1 :
00276       errmsg = cgen_parse_unsigned_integer (cd, strp, M32R_OPERAND_IMM1, (unsigned long *) (& fields->f_imm1));
00277       break;
00278     case M32R_OPERAND_SCR :
00279       errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_cr_names, & fields->f_r2);
00280       break;
00281     case M32R_OPERAND_SIMM16 :
00282       errmsg = cgen_parse_signed_integer (cd, strp, M32R_OPERAND_SIMM16, (long *) (& fields->f_simm16));
00283       break;
00284     case M32R_OPERAND_SIMM8 :
00285       errmsg = cgen_parse_signed_integer (cd, strp, M32R_OPERAND_SIMM8, (long *) (& fields->f_simm8));
00286       break;
00287     case M32R_OPERAND_SLO16 :
00288       errmsg = parse_slo16 (cd, strp, M32R_OPERAND_SLO16, (long *) (& fields->f_simm16));
00289       break;
00290     case M32R_OPERAND_SR :
00291       errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_gr_names, & fields->f_r2);
00292       break;
00293     case M32R_OPERAND_SRC1 :
00294       errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_gr_names, & fields->f_r1);
00295       break;
00296     case M32R_OPERAND_SRC2 :
00297       errmsg = cgen_parse_keyword (cd, strp, & m32r_cgen_opval_gr_names, & fields->f_r2);
00298       break;
00299     case M32R_OPERAND_UIMM16 :
00300       errmsg = cgen_parse_unsigned_integer (cd, strp, M32R_OPERAND_UIMM16, (unsigned long *) (& fields->f_uimm16));
00301       break;
00302     case M32R_OPERAND_UIMM24 :
00303       {
00304         bfd_vma value = 0;
00305         errmsg = cgen_parse_address (cd, strp, M32R_OPERAND_UIMM24, 0, NULL,  & value);
00306         fields->f_uimm24 = value;
00307       }
00308       break;
00309     case M32R_OPERAND_UIMM3 :
00310       errmsg = cgen_parse_unsigned_integer (cd, strp, M32R_OPERAND_UIMM3, (unsigned long *) (& fields->f_uimm3));
00311       break;
00312     case M32R_OPERAND_UIMM4 :
00313       errmsg = cgen_parse_unsigned_integer (cd, strp, M32R_OPERAND_UIMM4, (unsigned long *) (& fields->f_uimm4));
00314       break;
00315     case M32R_OPERAND_UIMM5 :
00316       errmsg = cgen_parse_unsigned_integer (cd, strp, M32R_OPERAND_UIMM5, (unsigned long *) (& fields->f_uimm5));
00317       break;
00318     case M32R_OPERAND_UIMM8 :
00319       errmsg = cgen_parse_unsigned_integer (cd, strp, M32R_OPERAND_UIMM8, (unsigned long *) (& fields->f_uimm8));
00320       break;
00321     case M32R_OPERAND_ULO16 :
00322       errmsg = parse_ulo16 (cd, strp, M32R_OPERAND_ULO16, (unsigned long *) (& fields->f_uimm16));
00323       break;
00324 
00325     default :
00326       /* xgettext:c-format */
00327       fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
00328       abort ();
00329   }
00330 
00331   return errmsg;
00332 }
00333 
00334 cgen_parse_fn * const m32r_cgen_parse_handlers[] = 
00335 {
00336   parse_insn_normal,
00337 };
00338 
00339 void
00340 m32r_cgen_init_asm (CGEN_CPU_DESC cd)
00341 {
00342   m32r_cgen_init_opcode_table (cd);
00343   m32r_cgen_init_ibld_table (cd);
00344   cd->parse_handlers = & m32r_cgen_parse_handlers[0];
00345   cd->parse_operand = m32r_cgen_parse_operand;
00346 #ifdef CGEN_ASM_INIT_HOOK
00347 CGEN_ASM_INIT_HOOK
00348 #endif
00349 }
00350 
00351 
00352 
00353 /* Regex construction routine.
00354 
00355    This translates an opcode syntax string into a regex string,
00356    by replacing any non-character syntax element (such as an
00357    opcode) with the pattern '.*'
00358 
00359    It then compiles the regex and stores it in the opcode, for
00360    later use by m32r_cgen_assemble_insn
00361 
00362    Returns NULL for success, an error message for failure.  */
00363 
00364 char * 
00365 m32r_cgen_build_insn_regex (CGEN_INSN *insn)
00366 {  
00367   CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
00368   const char *mnem = CGEN_INSN_MNEMONIC (insn);
00369   char rxbuf[CGEN_MAX_RX_ELEMENTS];
00370   char *rx = rxbuf;
00371   const CGEN_SYNTAX_CHAR_TYPE *syn;
00372   int reg_err;
00373 
00374   syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
00375 
00376   /* Mnemonics come first in the syntax string.  */
00377   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
00378     return _("missing mnemonic in syntax string");
00379   ++syn;
00380 
00381   /* Generate a case sensitive regular expression that emulates case
00382      insensitive matching in the "C" locale.  We cannot generate a case
00383      insensitive regular expression because in Turkish locales, 'i' and 'I'
00384      are not equal modulo case conversion.  */
00385 
00386   /* Copy the literal mnemonic out of the insn.  */
00387   for (; *mnem; mnem++)
00388     {
00389       char c = *mnem;
00390 
00391       if (ISALPHA (c))
00392        {
00393          *rx++ = '[';
00394          *rx++ = TOLOWER (c);
00395          *rx++ = TOUPPER (c);
00396          *rx++ = ']';
00397        }
00398       else
00399        *rx++ = c;
00400     }
00401 
00402   /* Copy any remaining literals from the syntax string into the rx.  */
00403   for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
00404     {
00405       if (CGEN_SYNTAX_CHAR_P (* syn)) 
00406        {
00407          char c = CGEN_SYNTAX_CHAR (* syn);
00408 
00409          switch (c) 
00410            {
00411              /* Escape any regex metacharacters in the syntax.  */
00412            case '.': case '[': case '\\': 
00413            case '*': case '^': case '$': 
00414 
00415 #ifdef CGEN_ESCAPE_EXTENDED_REGEX
00416            case '?': case '{': case '}': 
00417            case '(': case ')': case '*':
00418            case '|': case '+': case ']':
00419 #endif
00420              *rx++ = '\\';
00421              *rx++ = c;
00422              break;
00423 
00424            default:
00425              if (ISALPHA (c))
00426               {
00427                 *rx++ = '[';
00428                 *rx++ = TOLOWER (c);
00429                 *rx++ = TOUPPER (c);
00430                 *rx++ = ']';
00431               }
00432              else
00433               *rx++ = c;
00434              break;
00435            }
00436        }
00437       else
00438        {
00439          /* Replace non-syntax fields with globs.  */
00440          *rx++ = '.';
00441          *rx++ = '*';
00442        }
00443     }
00444 
00445   /* Trailing whitespace ok.  */
00446   * rx++ = '['; 
00447   * rx++ = ' '; 
00448   * rx++ = '\t'; 
00449   * rx++ = ']'; 
00450   * rx++ = '*'; 
00451 
00452   /* But anchor it after that.  */
00453   * rx++ = '$'; 
00454   * rx = '\0';
00455 
00456   CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
00457   reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
00458 
00459   if (reg_err == 0) 
00460     return NULL;
00461   else
00462     {
00463       static char msg[80];
00464 
00465       regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
00466       regfree ((regex_t *) CGEN_INSN_RX (insn));
00467       free (CGEN_INSN_RX (insn));
00468       (CGEN_INSN_RX (insn)) = NULL;
00469       return msg;
00470     }
00471 }
00472 
00473 
00474 /* Default insn parser.
00475 
00476    The syntax string is scanned and operands are parsed and stored in FIELDS.
00477    Relocs are queued as we go via other callbacks.
00478 
00479    ??? Note that this is currently an all-or-nothing parser.  If we fail to
00480    parse the instruction, we return 0 and the caller will start over from
00481    the beginning.  Backtracking will be necessary in parsing subexpressions,
00482    but that can be handled there.  Not handling backtracking here may get
00483    expensive in the case of the m68k.  Deal with later.
00484 
00485    Returns NULL for success, an error message for failure.  */
00486 
00487 static const char *
00488 parse_insn_normal (CGEN_CPU_DESC cd,
00489                  const CGEN_INSN *insn,
00490                  const char **strp,
00491                  CGEN_FIELDS *fields)
00492 {
00493   /* ??? Runtime added insns not handled yet.  */
00494   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
00495   const char *str = *strp;
00496   const char *errmsg;
00497   const char *p;
00498   const CGEN_SYNTAX_CHAR_TYPE * syn;
00499 #ifdef CGEN_MNEMONIC_OPERANDS
00500   /* FIXME: wip */
00501   int past_opcode_p;
00502 #endif
00503 
00504   /* For now we assume the mnemonic is first (there are no leading operands).
00505      We can parse it without needing to set up operand parsing.
00506      GAS's input scrubber will ensure mnemonics are lowercase, but we may
00507      not be called from GAS.  */
00508   p = CGEN_INSN_MNEMONIC (insn);
00509   while (*p && TOLOWER (*p) == TOLOWER (*str))
00510     ++p, ++str;
00511 
00512   if (* p)
00513     return _("unrecognized instruction");
00514 
00515 #ifndef CGEN_MNEMONIC_OPERANDS
00516   if (* str && ! ISSPACE (* str))
00517     return _("unrecognized instruction");
00518 #endif
00519 
00520   CGEN_INIT_PARSE (cd);
00521   cgen_init_parse_operand (cd);
00522 #ifdef CGEN_MNEMONIC_OPERANDS
00523   past_opcode_p = 0;
00524 #endif
00525 
00526   /* We don't check for (*str != '\0') here because we want to parse
00527      any trailing fake arguments in the syntax string.  */
00528   syn = CGEN_SYNTAX_STRING (syntax);
00529 
00530   /* Mnemonics come first for now, ensure valid string.  */
00531   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
00532     abort ();
00533 
00534   ++syn;
00535 
00536   while (* syn != 0)
00537     {
00538       /* Non operand chars must match exactly.  */
00539       if (CGEN_SYNTAX_CHAR_P (* syn))
00540        {
00541          /* FIXME: While we allow for non-GAS callers above, we assume the
00542             first char after the mnemonic part is a space.  */
00543          /* FIXME: We also take inappropriate advantage of the fact that
00544             GAS's input scrubber will remove extraneous blanks.  */
00545          if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
00546            {
00547 #ifdef CGEN_MNEMONIC_OPERANDS
00548              if (CGEN_SYNTAX_CHAR(* syn) == ' ')
00549               past_opcode_p = 1;
00550 #endif
00551              ++ syn;
00552              ++ str;
00553            }
00554          else if (*str)
00555            {
00556              /* Syntax char didn't match.  Can't be this insn.  */
00557              static char msg [80];
00558 
00559              /* xgettext:c-format */
00560              sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
00561                      CGEN_SYNTAX_CHAR(*syn), *str);
00562              return msg;
00563            }
00564          else
00565            {
00566              /* Ran out of input.  */
00567              static char msg [80];
00568 
00569              /* xgettext:c-format */
00570              sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
00571                      CGEN_SYNTAX_CHAR(*syn));
00572              return msg;
00573            }
00574          continue;
00575        }
00576 
00577       /* We have an operand of some sort.  */
00578       errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn),
00579                                      &str, fields);
00580       if (errmsg)
00581        return errmsg;
00582 
00583       /* Done with this operand, continue with next one.  */
00584       ++ syn;
00585     }
00586 
00587   /* If we're at the end of the syntax string, we're done.  */
00588   if (* syn == 0)
00589     {
00590       /* FIXME: For the moment we assume a valid `str' can only contain
00591         blanks now.  IE: We needn't try again with a longer version of
00592         the insn and it is assumed that longer versions of insns appear
00593         before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
00594       while (ISSPACE (* str))
00595        ++ str;
00596 
00597       if (* str != '\0')
00598        return _("junk at end of line"); /* FIXME: would like to include `str' */
00599 
00600       return NULL;
00601     }
00602 
00603   /* We couldn't parse it.  */
00604   return _("unrecognized instruction");
00605 }
00606 
00607 /* Main entry point.
00608    This routine is called for each instruction to be assembled.
00609    STR points to the insn to be assembled.
00610    We assume all necessary tables have been initialized.
00611    The assembled instruction, less any fixups, is stored in BUF.
00612    Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
00613    still needs to be converted to target byte order, otherwise BUF is an array
00614    of bytes in target byte order.
00615    The result is a pointer to the insn's entry in the opcode table,
00616    or NULL if an error occured (an error message will have already been
00617    printed).
00618 
00619    Note that when processing (non-alias) macro-insns,
00620    this function recurses.
00621 
00622    ??? It's possible to make this cpu-independent.
00623    One would have to deal with a few minor things.
00624    At this point in time doing so would be more of a curiosity than useful
00625    [for example this file isn't _that_ big], but keeping the possibility in
00626    mind helps keep the design clean.  */
00627 
00628 const CGEN_INSN *
00629 m32r_cgen_assemble_insn (CGEN_CPU_DESC cd,
00630                         const char *str,
00631                         CGEN_FIELDS *fields,
00632                         CGEN_INSN_BYTES_PTR buf,
00633                         char **errmsg)
00634 {
00635   const char *start;
00636   CGEN_INSN_LIST *ilist;
00637   const char *parse_errmsg = NULL;
00638   const char *insert_errmsg = NULL;
00639   int recognized_mnemonic = 0;
00640 
00641   /* Skip leading white space.  */
00642   while (ISSPACE (* str))
00643     ++ str;
00644 
00645   /* The instructions are stored in hashed lists.
00646      Get the first in the list.  */
00647   ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
00648 
00649   /* Keep looking until we find a match.  */
00650   start = str;
00651   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
00652     {
00653       const CGEN_INSN *insn = ilist->insn;
00654       recognized_mnemonic = 1;
00655 
00656 #ifdef CGEN_VALIDATE_INSN_SUPPORTED 
00657       /* Not usually needed as unsupported opcodes
00658         shouldn't be in the hash lists.  */
00659       /* Is this insn supported by the selected cpu?  */
00660       if (! m32r_cgen_insn_supported (cd, insn))
00661        continue;
00662 #endif
00663       /* If the RELAXED attribute is set, this is an insn that shouldn't be
00664         chosen immediately.  Instead, it is used during assembler/linker
00665         relaxation if possible.  */
00666       if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
00667        continue;
00668 
00669       str = start;
00670 
00671       /* Skip this insn if str doesn't look right lexically.  */
00672       if (CGEN_INSN_RX (insn) != NULL &&
00673          regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
00674        continue;
00675 
00676       /* Allow parse/insert handlers to obtain length of insn.  */
00677       CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
00678 
00679       parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
00680       if (parse_errmsg != NULL)
00681        continue;
00682 
00683       /* ??? 0 is passed for `pc'.  */
00684       insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
00685                                            (bfd_vma) 0);
00686       if (insert_errmsg != NULL)
00687         continue;
00688 
00689       /* It is up to the caller to actually output the insn and any
00690          queued relocs.  */
00691       return insn;
00692     }
00693 
00694   {
00695     static char errbuf[150];
00696 #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
00697     const char *tmp_errmsg;
00698 
00699     /* If requesting verbose error messages, use insert_errmsg.
00700        Failing that, use parse_errmsg.  */
00701     tmp_errmsg = (insert_errmsg ? insert_errmsg :
00702                 parse_errmsg ? parse_errmsg :
00703                 recognized_mnemonic ?
00704                 _("unrecognized form of instruction") :
00705                 _("unrecognized instruction"));
00706 
00707     if (strlen (start) > 50)
00708       /* xgettext:c-format */
00709       sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
00710     else 
00711       /* xgettext:c-format */
00712       sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
00713 #else
00714     if (strlen (start) > 50)
00715       /* xgettext:c-format */
00716       sprintf (errbuf, _("bad instruction `%.50s...'"), start);
00717     else 
00718       /* xgettext:c-format */
00719       sprintf (errbuf, _("bad instruction `%.50s'"), start);
00720 #endif
00721       
00722     *errmsg = errbuf;
00723     return NULL;
00724   }
00725 }