Back to index

cell-binutils  2.17cvs20070401
fr30-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 "fr30-desc.h"
00035 #include "fr30-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 /* Handle register lists for LDMx and STMx.  */
00053 
00054 static int
00055 parse_register_number (const char **strp)
00056 {
00057   int regno;
00058 
00059   if (**strp < '0' || **strp > '9')
00060     return -1; /* Error.  */
00061   regno = **strp - '0';
00062   ++*strp;
00063 
00064   if (**strp >= '0' && **strp <= '9')
00065     {
00066       regno = regno * 10 + (**strp - '0');
00067       ++*strp;
00068     }
00069 
00070   return regno;
00071 }
00072 
00073 static const char *
00074 parse_register_list (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
00075                    const char **strp,
00076                    int opindex ATTRIBUTE_UNUSED,
00077                    unsigned long *valuep,
00078                    int high_low,   /* 0 == high, 1 == low.  */
00079                    int load_store) /* 0 == load, 1 == store.  */
00080 {
00081   *valuep = 0;
00082   while (**strp && **strp != ')')
00083     {
00084       int regno;
00085 
00086       if (**strp != 'R' && **strp != 'r')
00087        break;
00088       ++*strp;
00089 
00090       regno = parse_register_number (strp);
00091       if (regno == -1)
00092        return _("Register number is not valid");
00093       if (regno > 7 && !high_low)
00094        return _("Register must be between r0 and r7");
00095       if (regno < 8 && high_low)
00096        return _("Register must be between r8 and r15");
00097 
00098       if (high_low)
00099        regno -= 8;
00100 
00101       if (load_store) /* Mask is reversed for store.  */
00102        *valuep |= 0x80 >> regno;
00103       else
00104        *valuep |= 1 << regno;
00105 
00106       if (**strp == ',')
00107        {
00108          if (*(*strp + 1) == ')')
00109            break;
00110          ++*strp;
00111        }
00112     }
00113 
00114   if (!*strp || **strp != ')')
00115     return _("Register list is not valid");
00116 
00117   return NULL;
00118 }
00119 
00120 static const char *
00121 parse_low_register_list_ld (CGEN_CPU_DESC cd,
00122                          const char **strp,
00123                          int opindex,
00124                          unsigned long *valuep)
00125 {
00126   return parse_register_list (cd, strp, opindex, valuep,
00127                            0 /* Low.  */, 0 /* Load.  */);
00128 }
00129 
00130 static const char *
00131 parse_hi_register_list_ld (CGEN_CPU_DESC cd,
00132                         const char **strp,
00133                         int opindex,
00134                         unsigned long *valuep)
00135 {
00136   return parse_register_list (cd, strp, opindex, valuep,
00137                            1 /* High.  */, 0 /* Load.  */);
00138 }
00139 
00140 static const char *
00141 parse_low_register_list_st (CGEN_CPU_DESC cd,
00142                          const char **strp,
00143                          int opindex,
00144                          unsigned long *valuep)
00145 {
00146   return parse_register_list (cd, strp, opindex, valuep,
00147                            0 /* Low.  */, 1 /* Store.  */);
00148 }
00149 
00150 static const char *
00151 parse_hi_register_list_st (CGEN_CPU_DESC cd,
00152                         const char **strp,
00153                         int opindex,
00154                         unsigned long *valuep)
00155 {
00156   return parse_register_list (cd, strp, opindex, valuep,
00157                            1 /* High.  */, 1 /* Store.  */);
00158 }
00159 
00160 /* -- */
00161 
00162 const char * fr30_cgen_parse_operand
00163   (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
00164 
00165 /* Main entry point for operand parsing.
00166 
00167    This function is basically just a big switch statement.  Earlier versions
00168    used tables to look up the function to use, but
00169    - if the table contains both assembler and disassembler functions then
00170      the disassembler contains much of the assembler and vice-versa,
00171    - there's a lot of inlining possibilities as things grow,
00172    - using a switch statement avoids the function call overhead.
00173 
00174    This function could be moved into `parse_insn_normal', but keeping it
00175    separate makes clear the interface between `parse_insn_normal' and each of
00176    the handlers.  */
00177 
00178 const char *
00179 fr30_cgen_parse_operand (CGEN_CPU_DESC cd,
00180                         int opindex,
00181                         const char ** strp,
00182                         CGEN_FIELDS * fields)
00183 {
00184   const char * errmsg = NULL;
00185   /* Used by scalar operands that still need to be parsed.  */
00186   long junk ATTRIBUTE_UNUSED;
00187 
00188   switch (opindex)
00189     {
00190     case FR30_OPERAND_CRI :
00191       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_cr_names, & fields->f_CRi);
00192       break;
00193     case FR30_OPERAND_CRJ :
00194       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_cr_names, & fields->f_CRj);
00195       break;
00196     case FR30_OPERAND_R13 :
00197       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_h_r13, & junk);
00198       break;
00199     case FR30_OPERAND_R14 :
00200       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_h_r14, & junk);
00201       break;
00202     case FR30_OPERAND_R15 :
00203       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_h_r15, & junk);
00204       break;
00205     case FR30_OPERAND_RI :
00206       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_gr_names, & fields->f_Ri);
00207       break;
00208     case FR30_OPERAND_RIC :
00209       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_gr_names, & fields->f_Ric);
00210       break;
00211     case FR30_OPERAND_RJ :
00212       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_gr_names, & fields->f_Rj);
00213       break;
00214     case FR30_OPERAND_RJC :
00215       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_gr_names, & fields->f_Rjc);
00216       break;
00217     case FR30_OPERAND_RS1 :
00218       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_dr_names, & fields->f_Rs1);
00219       break;
00220     case FR30_OPERAND_RS2 :
00221       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_dr_names, & fields->f_Rs2);
00222       break;
00223     case FR30_OPERAND_CC :
00224       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_CC, (unsigned long *) (& fields->f_cc));
00225       break;
00226     case FR30_OPERAND_CCC :
00227       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_CCC, (unsigned long *) (& fields->f_ccc));
00228       break;
00229     case FR30_OPERAND_DIR10 :
00230       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_DIR10, (unsigned long *) (& fields->f_dir10));
00231       break;
00232     case FR30_OPERAND_DIR8 :
00233       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_DIR8, (unsigned long *) (& fields->f_dir8));
00234       break;
00235     case FR30_OPERAND_DIR9 :
00236       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_DIR9, (unsigned long *) (& fields->f_dir9));
00237       break;
00238     case FR30_OPERAND_DISP10 :
00239       errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_DISP10, (long *) (& fields->f_disp10));
00240       break;
00241     case FR30_OPERAND_DISP8 :
00242       errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_DISP8, (long *) (& fields->f_disp8));
00243       break;
00244     case FR30_OPERAND_DISP9 :
00245       errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_DISP9, (long *) (& fields->f_disp9));
00246       break;
00247     case FR30_OPERAND_I20 :
00248       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_I20, (unsigned long *) (& fields->f_i20));
00249       break;
00250     case FR30_OPERAND_I32 :
00251       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_I32, (unsigned long *) (& fields->f_i32));
00252       break;
00253     case FR30_OPERAND_I8 :
00254       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_I8, (unsigned long *) (& fields->f_i8));
00255       break;
00256     case FR30_OPERAND_LABEL12 :
00257       {
00258         bfd_vma value = 0;
00259         errmsg = cgen_parse_address (cd, strp, FR30_OPERAND_LABEL12, 0, NULL,  & value);
00260         fields->f_rel12 = value;
00261       }
00262       break;
00263     case FR30_OPERAND_LABEL9 :
00264       {
00265         bfd_vma value = 0;
00266         errmsg = cgen_parse_address (cd, strp, FR30_OPERAND_LABEL9, 0, NULL,  & value);
00267         fields->f_rel9 = value;
00268       }
00269       break;
00270     case FR30_OPERAND_M4 :
00271       errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_M4, (long *) (& fields->f_m4));
00272       break;
00273     case FR30_OPERAND_PS :
00274       errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_h_ps, & junk);
00275       break;
00276     case FR30_OPERAND_REGLIST_HI_LD :
00277       errmsg = parse_hi_register_list_ld (cd, strp, FR30_OPERAND_REGLIST_HI_LD, (unsigned long *) (& fields->f_reglist_hi_ld));
00278       break;
00279     case FR30_OPERAND_REGLIST_HI_ST :
00280       errmsg = parse_hi_register_list_st (cd, strp, FR30_OPERAND_REGLIST_HI_ST, (unsigned long *) (& fields->f_reglist_hi_st));
00281       break;
00282     case FR30_OPERAND_REGLIST_LOW_LD :
00283       errmsg = parse_low_register_list_ld (cd, strp, FR30_OPERAND_REGLIST_LOW_LD, (unsigned long *) (& fields->f_reglist_low_ld));
00284       break;
00285     case FR30_OPERAND_REGLIST_LOW_ST :
00286       errmsg = parse_low_register_list_st (cd, strp, FR30_OPERAND_REGLIST_LOW_ST, (unsigned long *) (& fields->f_reglist_low_st));
00287       break;
00288     case FR30_OPERAND_S10 :
00289       errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_S10, (long *) (& fields->f_s10));
00290       break;
00291     case FR30_OPERAND_U10 :
00292       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_U10, (unsigned long *) (& fields->f_u10));
00293       break;
00294     case FR30_OPERAND_U4 :
00295       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_U4, (unsigned long *) (& fields->f_u4));
00296       break;
00297     case FR30_OPERAND_U4C :
00298       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_U4C, (unsigned long *) (& fields->f_u4c));
00299       break;
00300     case FR30_OPERAND_U8 :
00301       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_U8, (unsigned long *) (& fields->f_u8));
00302       break;
00303     case FR30_OPERAND_UDISP6 :
00304       errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_UDISP6, (unsigned long *) (& fields->f_udisp6));
00305       break;
00306 
00307     default :
00308       /* xgettext:c-format */
00309       fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
00310       abort ();
00311   }
00312 
00313   return errmsg;
00314 }
00315 
00316 cgen_parse_fn * const fr30_cgen_parse_handlers[] = 
00317 {
00318   parse_insn_normal,
00319 };
00320 
00321 void
00322 fr30_cgen_init_asm (CGEN_CPU_DESC cd)
00323 {
00324   fr30_cgen_init_opcode_table (cd);
00325   fr30_cgen_init_ibld_table (cd);
00326   cd->parse_handlers = & fr30_cgen_parse_handlers[0];
00327   cd->parse_operand = fr30_cgen_parse_operand;
00328 #ifdef CGEN_ASM_INIT_HOOK
00329 CGEN_ASM_INIT_HOOK
00330 #endif
00331 }
00332 
00333 
00334 
00335 /* Regex construction routine.
00336 
00337    This translates an opcode syntax string into a regex string,
00338    by replacing any non-character syntax element (such as an
00339    opcode) with the pattern '.*'
00340 
00341    It then compiles the regex and stores it in the opcode, for
00342    later use by fr30_cgen_assemble_insn
00343 
00344    Returns NULL for success, an error message for failure.  */
00345 
00346 char * 
00347 fr30_cgen_build_insn_regex (CGEN_INSN *insn)
00348 {  
00349   CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
00350   const char *mnem = CGEN_INSN_MNEMONIC (insn);
00351   char rxbuf[CGEN_MAX_RX_ELEMENTS];
00352   char *rx = rxbuf;
00353   const CGEN_SYNTAX_CHAR_TYPE *syn;
00354   int reg_err;
00355 
00356   syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
00357 
00358   /* Mnemonics come first in the syntax string.  */
00359   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
00360     return _("missing mnemonic in syntax string");
00361   ++syn;
00362 
00363   /* Generate a case sensitive regular expression that emulates case
00364      insensitive matching in the "C" locale.  We cannot generate a case
00365      insensitive regular expression because in Turkish locales, 'i' and 'I'
00366      are not equal modulo case conversion.  */
00367 
00368   /* Copy the literal mnemonic out of the insn.  */
00369   for (; *mnem; mnem++)
00370     {
00371       char c = *mnem;
00372 
00373       if (ISALPHA (c))
00374        {
00375          *rx++ = '[';
00376          *rx++ = TOLOWER (c);
00377          *rx++ = TOUPPER (c);
00378          *rx++ = ']';
00379        }
00380       else
00381        *rx++ = c;
00382     }
00383 
00384   /* Copy any remaining literals from the syntax string into the rx.  */
00385   for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
00386     {
00387       if (CGEN_SYNTAX_CHAR_P (* syn)) 
00388        {
00389          char c = CGEN_SYNTAX_CHAR (* syn);
00390 
00391          switch (c) 
00392            {
00393              /* Escape any regex metacharacters in the syntax.  */
00394            case '.': case '[': case '\\': 
00395            case '*': case '^': case '$': 
00396 
00397 #ifdef CGEN_ESCAPE_EXTENDED_REGEX
00398            case '?': case '{': case '}': 
00399            case '(': case ')': case '*':
00400            case '|': case '+': case ']':
00401 #endif
00402              *rx++ = '\\';
00403              *rx++ = c;
00404              break;
00405 
00406            default:
00407              if (ISALPHA (c))
00408               {
00409                 *rx++ = '[';
00410                 *rx++ = TOLOWER (c);
00411                 *rx++ = TOUPPER (c);
00412                 *rx++ = ']';
00413               }
00414              else
00415               *rx++ = c;
00416              break;
00417            }
00418        }
00419       else
00420        {
00421          /* Replace non-syntax fields with globs.  */
00422          *rx++ = '.';
00423          *rx++ = '*';
00424        }
00425     }
00426 
00427   /* Trailing whitespace ok.  */
00428   * rx++ = '['; 
00429   * rx++ = ' '; 
00430   * rx++ = '\t'; 
00431   * rx++ = ']'; 
00432   * rx++ = '*'; 
00433 
00434   /* But anchor it after that.  */
00435   * rx++ = '$'; 
00436   * rx = '\0';
00437 
00438   CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
00439   reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
00440 
00441   if (reg_err == 0) 
00442     return NULL;
00443   else
00444     {
00445       static char msg[80];
00446 
00447       regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
00448       regfree ((regex_t *) CGEN_INSN_RX (insn));
00449       free (CGEN_INSN_RX (insn));
00450       (CGEN_INSN_RX (insn)) = NULL;
00451       return msg;
00452     }
00453 }
00454 
00455 
00456 /* Default insn parser.
00457 
00458    The syntax string is scanned and operands are parsed and stored in FIELDS.
00459    Relocs are queued as we go via other callbacks.
00460 
00461    ??? Note that this is currently an all-or-nothing parser.  If we fail to
00462    parse the instruction, we return 0 and the caller will start over from
00463    the beginning.  Backtracking will be necessary in parsing subexpressions,
00464    but that can be handled there.  Not handling backtracking here may get
00465    expensive in the case of the m68k.  Deal with later.
00466 
00467    Returns NULL for success, an error message for failure.  */
00468 
00469 static const char *
00470 parse_insn_normal (CGEN_CPU_DESC cd,
00471                  const CGEN_INSN *insn,
00472                  const char **strp,
00473                  CGEN_FIELDS *fields)
00474 {
00475   /* ??? Runtime added insns not handled yet.  */
00476   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
00477   const char *str = *strp;
00478   const char *errmsg;
00479   const char *p;
00480   const CGEN_SYNTAX_CHAR_TYPE * syn;
00481 #ifdef CGEN_MNEMONIC_OPERANDS
00482   /* FIXME: wip */
00483   int past_opcode_p;
00484 #endif
00485 
00486   /* For now we assume the mnemonic is first (there are no leading operands).
00487      We can parse it without needing to set up operand parsing.
00488      GAS's input scrubber will ensure mnemonics are lowercase, but we may
00489      not be called from GAS.  */
00490   p = CGEN_INSN_MNEMONIC (insn);
00491   while (*p && TOLOWER (*p) == TOLOWER (*str))
00492     ++p, ++str;
00493 
00494   if (* p)
00495     return _("unrecognized instruction");
00496 
00497 #ifndef CGEN_MNEMONIC_OPERANDS
00498   if (* str && ! ISSPACE (* str))
00499     return _("unrecognized instruction");
00500 #endif
00501 
00502   CGEN_INIT_PARSE (cd);
00503   cgen_init_parse_operand (cd);
00504 #ifdef CGEN_MNEMONIC_OPERANDS
00505   past_opcode_p = 0;
00506 #endif
00507 
00508   /* We don't check for (*str != '\0') here because we want to parse
00509      any trailing fake arguments in the syntax string.  */
00510   syn = CGEN_SYNTAX_STRING (syntax);
00511 
00512   /* Mnemonics come first for now, ensure valid string.  */
00513   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
00514     abort ();
00515 
00516   ++syn;
00517 
00518   while (* syn != 0)
00519     {
00520       /* Non operand chars must match exactly.  */
00521       if (CGEN_SYNTAX_CHAR_P (* syn))
00522        {
00523          /* FIXME: While we allow for non-GAS callers above, we assume the
00524             first char after the mnemonic part is a space.  */
00525          /* FIXME: We also take inappropriate advantage of the fact that
00526             GAS's input scrubber will remove extraneous blanks.  */
00527          if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
00528            {
00529 #ifdef CGEN_MNEMONIC_OPERANDS
00530              if (CGEN_SYNTAX_CHAR(* syn) == ' ')
00531               past_opcode_p = 1;
00532 #endif
00533              ++ syn;
00534              ++ str;
00535            }
00536          else if (*str)
00537            {
00538              /* Syntax char didn't match.  Can't be this insn.  */
00539              static char msg [80];
00540 
00541              /* xgettext:c-format */
00542              sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
00543                      CGEN_SYNTAX_CHAR(*syn), *str);
00544              return msg;
00545            }
00546          else
00547            {
00548              /* Ran out of input.  */
00549              static char msg [80];
00550 
00551              /* xgettext:c-format */
00552              sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
00553                      CGEN_SYNTAX_CHAR(*syn));
00554              return msg;
00555            }
00556          continue;
00557        }
00558 
00559       /* We have an operand of some sort.  */
00560       errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn),
00561                                      &str, fields);
00562       if (errmsg)
00563        return errmsg;
00564 
00565       /* Done with this operand, continue with next one.  */
00566       ++ syn;
00567     }
00568 
00569   /* If we're at the end of the syntax string, we're done.  */
00570   if (* syn == 0)
00571     {
00572       /* FIXME: For the moment we assume a valid `str' can only contain
00573         blanks now.  IE: We needn't try again with a longer version of
00574         the insn and it is assumed that longer versions of insns appear
00575         before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
00576       while (ISSPACE (* str))
00577        ++ str;
00578 
00579       if (* str != '\0')
00580        return _("junk at end of line"); /* FIXME: would like to include `str' */
00581 
00582       return NULL;
00583     }
00584 
00585   /* We couldn't parse it.  */
00586   return _("unrecognized instruction");
00587 }
00588 
00589 /* Main entry point.
00590    This routine is called for each instruction to be assembled.
00591    STR points to the insn to be assembled.
00592    We assume all necessary tables have been initialized.
00593    The assembled instruction, less any fixups, is stored in BUF.
00594    Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
00595    still needs to be converted to target byte order, otherwise BUF is an array
00596    of bytes in target byte order.
00597    The result is a pointer to the insn's entry in the opcode table,
00598    or NULL if an error occured (an error message will have already been
00599    printed).
00600 
00601    Note that when processing (non-alias) macro-insns,
00602    this function recurses.
00603 
00604    ??? It's possible to make this cpu-independent.
00605    One would have to deal with a few minor things.
00606    At this point in time doing so would be more of a curiosity than useful
00607    [for example this file isn't _that_ big], but keeping the possibility in
00608    mind helps keep the design clean.  */
00609 
00610 const CGEN_INSN *
00611 fr30_cgen_assemble_insn (CGEN_CPU_DESC cd,
00612                         const char *str,
00613                         CGEN_FIELDS *fields,
00614                         CGEN_INSN_BYTES_PTR buf,
00615                         char **errmsg)
00616 {
00617   const char *start;
00618   CGEN_INSN_LIST *ilist;
00619   const char *parse_errmsg = NULL;
00620   const char *insert_errmsg = NULL;
00621   int recognized_mnemonic = 0;
00622 
00623   /* Skip leading white space.  */
00624   while (ISSPACE (* str))
00625     ++ str;
00626 
00627   /* The instructions are stored in hashed lists.
00628      Get the first in the list.  */
00629   ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
00630 
00631   /* Keep looking until we find a match.  */
00632   start = str;
00633   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
00634     {
00635       const CGEN_INSN *insn = ilist->insn;
00636       recognized_mnemonic = 1;
00637 
00638 #ifdef CGEN_VALIDATE_INSN_SUPPORTED 
00639       /* Not usually needed as unsupported opcodes
00640         shouldn't be in the hash lists.  */
00641       /* Is this insn supported by the selected cpu?  */
00642       if (! fr30_cgen_insn_supported (cd, insn))
00643        continue;
00644 #endif
00645       /* If the RELAXED attribute is set, this is an insn that shouldn't be
00646         chosen immediately.  Instead, it is used during assembler/linker
00647         relaxation if possible.  */
00648       if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
00649        continue;
00650 
00651       str = start;
00652 
00653       /* Skip this insn if str doesn't look right lexically.  */
00654       if (CGEN_INSN_RX (insn) != NULL &&
00655          regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
00656        continue;
00657 
00658       /* Allow parse/insert handlers to obtain length of insn.  */
00659       CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
00660 
00661       parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
00662       if (parse_errmsg != NULL)
00663        continue;
00664 
00665       /* ??? 0 is passed for `pc'.  */
00666       insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
00667                                            (bfd_vma) 0);
00668       if (insert_errmsg != NULL)
00669         continue;
00670 
00671       /* It is up to the caller to actually output the insn and any
00672          queued relocs.  */
00673       return insn;
00674     }
00675 
00676   {
00677     static char errbuf[150];
00678 #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
00679     const char *tmp_errmsg;
00680 
00681     /* If requesting verbose error messages, use insert_errmsg.
00682        Failing that, use parse_errmsg.  */
00683     tmp_errmsg = (insert_errmsg ? insert_errmsg :
00684                 parse_errmsg ? parse_errmsg :
00685                 recognized_mnemonic ?
00686                 _("unrecognized form of instruction") :
00687                 _("unrecognized instruction"));
00688 
00689     if (strlen (start) > 50)
00690       /* xgettext:c-format */
00691       sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
00692     else 
00693       /* xgettext:c-format */
00694       sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
00695 #else
00696     if (strlen (start) > 50)
00697       /* xgettext:c-format */
00698       sprintf (errbuf, _("bad instruction `%.50s...'"), start);
00699     else 
00700       /* xgettext:c-format */
00701       sprintf (errbuf, _("bad instruction `%.50s'"), start);
00702 #endif
00703       
00704     *errmsg = errbuf;
00705     return NULL;
00706   }
00707 }