Back to index

cell-binutils  2.17cvs20070401
xc16x-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 "xc16x-desc.h"
00035 #include "xc16x-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 '#' prefixes (i.e. skip over them).  */
00053 
00054 static const char *
00055 parse_hash (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
00056            const char **strp,
00057            int opindex ATTRIBUTE_UNUSED,
00058            long *valuep ATTRIBUTE_UNUSED)
00059 {
00060   if (**strp == '#')
00061     {
00062       ++*strp;
00063       return NULL;
00064     }
00065   return _("Missing '#' prefix");
00066 }
00067 
00068 /* Handle '.' prefixes (i.e. skip over them).  */
00069 
00070 static const char *
00071 parse_dot (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
00072           const char **strp,
00073           int opindex ATTRIBUTE_UNUSED,
00074           long *valuep ATTRIBUTE_UNUSED)
00075 {
00076   if (**strp == '.')
00077     {
00078       ++*strp;
00079       return NULL;
00080     }
00081   return _("Missing '.' prefix");
00082 }
00083 
00084 /* Handle 'pof:' prefixes (i.e. skip over them).  */
00085 
00086 static const char *
00087 parse_pof (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
00088           const char **strp,
00089           int opindex ATTRIBUTE_UNUSED,
00090           long *valuep ATTRIBUTE_UNUSED)
00091 {
00092   if (strncasecmp (*strp, "pof:", 4) == 0)
00093     {
00094       *strp += 4;
00095       return NULL;
00096     }
00097   return _("Missing 'pof:' prefix");  
00098 }
00099 
00100 /* Handle 'pag:' prefixes (i.e. skip over them).  */
00101 
00102 static const char *
00103 parse_pag (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
00104           const char **strp,
00105           int opindex ATTRIBUTE_UNUSED,
00106           long *valuep ATTRIBUTE_UNUSED)
00107 {
00108   if (strncasecmp (*strp, "pag:", 4) == 0)
00109     {
00110       *strp += 4;
00111       return NULL;
00112     }
00113   return _("Missing 'pag:' prefix");
00114 }
00115 
00116 /* Handle 'sof' prefixes (i.e. skip over them).  */
00117 
00118 static const char *
00119 parse_sof (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
00120           const char **strp,
00121           int opindex ATTRIBUTE_UNUSED,
00122           long *valuep ATTRIBUTE_UNUSED)
00123 {
00124   if (strncasecmp (*strp, "sof:", 4) == 0)
00125     {
00126       *strp += 4;
00127       return NULL;
00128     }
00129   return _("Missing 'sof:' prefix");
00130 }
00131 
00132 /* Handle 'seg' prefixes (i.e. skip over them).  */
00133 
00134 static const char *
00135 parse_seg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
00136           const char **strp,
00137           int opindex ATTRIBUTE_UNUSED,
00138           long *valuep ATTRIBUTE_UNUSED)
00139 {
00140   if (strncasecmp (*strp, "seg:", 4) == 0)
00141     {
00142       *strp += 4;
00143       return NULL;
00144     }
00145   return _("Missing 'seg:' prefix");
00146 }
00147 /* -- */
00148 
00149 const char * xc16x_cgen_parse_operand
00150   (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
00151 
00152 /* Main entry point for operand parsing.
00153 
00154    This function is basically just a big switch statement.  Earlier versions
00155    used tables to look up the function to use, but
00156    - if the table contains both assembler and disassembler functions then
00157      the disassembler contains much of the assembler and vice-versa,
00158    - there's a lot of inlining possibilities as things grow,
00159    - using a switch statement avoids the function call overhead.
00160 
00161    This function could be moved into `parse_insn_normal', but keeping it
00162    separate makes clear the interface between `parse_insn_normal' and each of
00163    the handlers.  */
00164 
00165 const char *
00166 xc16x_cgen_parse_operand (CGEN_CPU_DESC cd,
00167                         int opindex,
00168                         const char ** strp,
00169                         CGEN_FIELDS * fields)
00170 {
00171   const char * errmsg = NULL;
00172   /* Used by scalar operands that still need to be parsed.  */
00173   long junk ATTRIBUTE_UNUSED;
00174 
00175   switch (opindex)
00176     {
00177     case XC16X_OPERAND_REGNAM :
00178       errmsg = cgen_parse_keyword (cd, strp, & xc16x_cgen_opval_psw_names, & fields->f_reg8);
00179       break;
00180     case XC16X_OPERAND_BIT01 :
00181       errmsg = cgen_parse_unsigned_integer (cd, strp, XC16X_OPERAND_BIT01, (unsigned long *) (& fields->f_op_1bit));
00182       break;
00183     case XC16X_OPERAND_BIT1 :
00184       errmsg = cgen_parse_unsigned_integer (cd, strp, XC16X_OPERAND_BIT1, (unsigned long *) (& fields->f_op_bit1));
00185       break;
00186     case XC16X_OPERAND_BIT2 :
00187       errmsg = cgen_parse_unsigned_integer (cd, strp, XC16X_OPERAND_BIT2, (unsigned long *) (& fields->f_op_bit2));
00188       break;
00189     case XC16X_OPERAND_BIT4 :
00190       errmsg = cgen_parse_unsigned_integer (cd, strp, XC16X_OPERAND_BIT4, (unsigned long *) (& fields->f_op_bit4));
00191       break;
00192     case XC16X_OPERAND_BIT8 :
00193       errmsg = cgen_parse_unsigned_integer (cd, strp, XC16X_OPERAND_BIT8, (unsigned long *) (& fields->f_op_bit8));
00194       break;
00195     case XC16X_OPERAND_BITONE :
00196       errmsg = cgen_parse_unsigned_integer (cd, strp, XC16X_OPERAND_BITONE, (unsigned long *) (& fields->f_op_onebit));
00197       break;
00198     case XC16X_OPERAND_CADDR :
00199       {
00200         bfd_vma value = 0;
00201         errmsg = cgen_parse_address (cd, strp, XC16X_OPERAND_CADDR, 0, NULL,  & value);
00202         fields->f_offset16 = value;
00203       }
00204       break;
00205     case XC16X_OPERAND_COND :
00206       errmsg = cgen_parse_keyword (cd, strp, & xc16x_cgen_opval_conditioncode_names, & fields->f_condcode);
00207       break;
00208     case XC16X_OPERAND_DATA8 :
00209       errmsg = cgen_parse_unsigned_integer (cd, strp, XC16X_OPERAND_DATA8, (unsigned long *) (& fields->f_data8));
00210       break;
00211     case XC16X_OPERAND_DATAHI8 :
00212       errmsg = cgen_parse_unsigned_integer (cd, strp, XC16X_OPERAND_DATAHI8, (unsigned long *) (& fields->f_datahi8));
00213       break;
00214     case XC16X_OPERAND_DOT :
00215       errmsg = parse_dot (cd, strp, XC16X_OPERAND_DOT, (long *) (& junk));
00216       break;
00217     case XC16X_OPERAND_DR :
00218       errmsg = cgen_parse_keyword (cd, strp, & xc16x_cgen_opval_gr_names, & fields->f_r1);
00219       break;
00220     case XC16X_OPERAND_DRB :
00221       errmsg = cgen_parse_keyword (cd, strp, & xc16x_cgen_opval_grb_names, & fields->f_r1);
00222       break;
00223     case XC16X_OPERAND_DRI :
00224       errmsg = cgen_parse_keyword (cd, strp, & xc16x_cgen_opval_gr_names, & fields->f_r4);
00225       break;
00226     case XC16X_OPERAND_EXTCOND :
00227       errmsg = cgen_parse_keyword (cd, strp, & xc16x_cgen_opval_extconditioncode_names, & fields->f_extccode);
00228       break;
00229     case XC16X_OPERAND_GENREG :
00230       errmsg = cgen_parse_keyword (cd, strp, & xc16x_cgen_opval_r8_names, & fields->f_regb8);
00231       break;
00232     case XC16X_OPERAND_HASH :
00233       errmsg = parse_hash (cd, strp, XC16X_OPERAND_HASH, (long *) (& junk));
00234       break;
00235     case XC16X_OPERAND_ICOND :
00236       errmsg = cgen_parse_keyword (cd, strp, & xc16x_cgen_opval_conditioncode_names, & fields->f_icondcode);
00237       break;
00238     case XC16X_OPERAND_LBIT2 :
00239       errmsg = cgen_parse_unsigned_integer (cd, strp, XC16X_OPERAND_LBIT2, (unsigned long *) (& fields->f_op_lbit2));
00240       break;
00241     case XC16X_OPERAND_LBIT4 :
00242       errmsg = cgen_parse_unsigned_integer (cd, strp, XC16X_OPERAND_LBIT4, (unsigned long *) (& fields->f_op_lbit4));
00243       break;
00244     case XC16X_OPERAND_MASK8 :
00245       errmsg = cgen_parse_unsigned_integer (cd, strp, XC16X_OPERAND_MASK8, (unsigned long *) (& fields->f_mask8));
00246       break;
00247     case XC16X_OPERAND_MASKLO8 :
00248       errmsg = cgen_parse_unsigned_integer (cd, strp, XC16X_OPERAND_MASKLO8, (unsigned long *) (& fields->f_datahi8));
00249       break;
00250     case XC16X_OPERAND_MEMGR8 :
00251       errmsg = cgen_parse_keyword (cd, strp, & xc16x_cgen_opval_memgr8_names, & fields->f_memgr8);
00252       break;
00253     case XC16X_OPERAND_MEMORY :
00254       {
00255         bfd_vma value = 0;
00256         errmsg = cgen_parse_address (cd, strp, XC16X_OPERAND_MEMORY, 0, NULL,  & value);
00257         fields->f_memory = value;
00258       }
00259       break;
00260     case XC16X_OPERAND_PAG :
00261       errmsg = parse_pag (cd, strp, XC16X_OPERAND_PAG, (long *) (& junk));
00262       break;
00263     case XC16X_OPERAND_PAGENUM :
00264       errmsg = cgen_parse_unsigned_integer (cd, strp, XC16X_OPERAND_PAGENUM, (unsigned long *) (& fields->f_pagenum));
00265       break;
00266     case XC16X_OPERAND_POF :
00267       errmsg = parse_pof (cd, strp, XC16X_OPERAND_POF, (long *) (& junk));
00268       break;
00269     case XC16X_OPERAND_QBIT :
00270       errmsg = cgen_parse_unsigned_integer (cd, strp, XC16X_OPERAND_QBIT, (unsigned long *) (& fields->f_qbit));
00271       break;
00272     case XC16X_OPERAND_QHIBIT :
00273       errmsg = cgen_parse_unsigned_integer (cd, strp, XC16X_OPERAND_QHIBIT, (unsigned long *) (& fields->f_qhibit));
00274       break;
00275     case XC16X_OPERAND_QLOBIT :
00276       errmsg = cgen_parse_unsigned_integer (cd, strp, XC16X_OPERAND_QLOBIT, (unsigned long *) (& fields->f_qlobit));
00277       break;
00278     case XC16X_OPERAND_REG8 :
00279       errmsg = cgen_parse_keyword (cd, strp, & xc16x_cgen_opval_r8_names, & fields->f_reg8);
00280       break;
00281     case XC16X_OPERAND_REGB8 :
00282       errmsg = cgen_parse_keyword (cd, strp, & xc16x_cgen_opval_grb8_names, & fields->f_regb8);
00283       break;
00284     case XC16X_OPERAND_REGBMEM8 :
00285       errmsg = cgen_parse_keyword (cd, strp, & xc16x_cgen_opval_regbmem8_names, & fields->f_regmem8);
00286       break;
00287     case XC16X_OPERAND_REGHI8 :
00288       errmsg = cgen_parse_keyword (cd, strp, & xc16x_cgen_opval_r8_names, & fields->f_reghi8);
00289       break;
00290     case XC16X_OPERAND_REGMEM8 :
00291       errmsg = cgen_parse_keyword (cd, strp, & xc16x_cgen_opval_regmem8_names, & fields->f_regmem8);
00292       break;
00293     case XC16X_OPERAND_REGOFF8 :
00294       errmsg = cgen_parse_keyword (cd, strp, & xc16x_cgen_opval_r8_names, & fields->f_regoff8);
00295       break;
00296     case XC16X_OPERAND_REL :
00297       errmsg = cgen_parse_signed_integer (cd, strp, XC16X_OPERAND_REL, (long *) (& fields->f_rel8));
00298       break;
00299     case XC16X_OPERAND_RELHI :
00300       errmsg = cgen_parse_signed_integer (cd, strp, XC16X_OPERAND_RELHI, (long *) (& fields->f_relhi8));
00301       break;
00302     case XC16X_OPERAND_SEG :
00303       errmsg = cgen_parse_unsigned_integer (cd, strp, XC16X_OPERAND_SEG, (unsigned long *) (& fields->f_seg8));
00304       break;
00305     case XC16X_OPERAND_SEGHI8 :
00306       errmsg = cgen_parse_unsigned_integer (cd, strp, XC16X_OPERAND_SEGHI8, (unsigned long *) (& fields->f_segnum8));
00307       break;
00308     case XC16X_OPERAND_SEGM :
00309       errmsg = parse_seg (cd, strp, XC16X_OPERAND_SEGM, (long *) (& junk));
00310       break;
00311     case XC16X_OPERAND_SOF :
00312       errmsg = parse_sof (cd, strp, XC16X_OPERAND_SOF, (long *) (& junk));
00313       break;
00314     case XC16X_OPERAND_SR :
00315       errmsg = cgen_parse_keyword (cd, strp, & xc16x_cgen_opval_gr_names, & fields->f_r2);
00316       break;
00317     case XC16X_OPERAND_SR2 :
00318       errmsg = cgen_parse_keyword (cd, strp, & xc16x_cgen_opval_gr_names, & fields->f_r0);
00319       break;
00320     case XC16X_OPERAND_SRB :
00321       errmsg = cgen_parse_keyword (cd, strp, & xc16x_cgen_opval_grb_names, & fields->f_r2);
00322       break;
00323     case XC16X_OPERAND_SRC1 :
00324       errmsg = cgen_parse_keyword (cd, strp, & xc16x_cgen_opval_gr_names, & fields->f_r1);
00325       break;
00326     case XC16X_OPERAND_SRC2 :
00327       errmsg = cgen_parse_keyword (cd, strp, & xc16x_cgen_opval_gr_names, & fields->f_r2);
00328       break;
00329     case XC16X_OPERAND_SRDIV :
00330       errmsg = cgen_parse_keyword (cd, strp, & xc16x_cgen_opval_regdiv8_names, & fields->f_reg8);
00331       break;
00332     case XC16X_OPERAND_U4 :
00333       errmsg = cgen_parse_keyword (cd, strp, & xc16x_cgen_opval_reg0_name, & fields->f_uimm4);
00334       break;
00335     case XC16X_OPERAND_UIMM16 :
00336       errmsg = cgen_parse_unsigned_integer (cd, strp, XC16X_OPERAND_UIMM16, (unsigned long *) (& fields->f_uimm16));
00337       break;
00338     case XC16X_OPERAND_UIMM2 :
00339       errmsg = cgen_parse_keyword (cd, strp, & xc16x_cgen_opval_ext_names, & fields->f_uimm2);
00340       break;
00341     case XC16X_OPERAND_UIMM3 :
00342       errmsg = cgen_parse_keyword (cd, strp, & xc16x_cgen_opval_reg0_name1, & fields->f_uimm3);
00343       break;
00344     case XC16X_OPERAND_UIMM4 :
00345       errmsg = cgen_parse_unsigned_integer (cd, strp, XC16X_OPERAND_UIMM4, (unsigned long *) (& fields->f_uimm4));
00346       break;
00347     case XC16X_OPERAND_UIMM7 :
00348       errmsg = cgen_parse_unsigned_integer (cd, strp, XC16X_OPERAND_UIMM7, (unsigned long *) (& fields->f_uimm7));
00349       break;
00350     case XC16X_OPERAND_UIMM8 :
00351       errmsg = cgen_parse_unsigned_integer (cd, strp, XC16X_OPERAND_UIMM8, (unsigned long *) (& fields->f_uimm8));
00352       break;
00353     case XC16X_OPERAND_UPAG16 :
00354       errmsg = cgen_parse_unsigned_integer (cd, strp, XC16X_OPERAND_UPAG16, (unsigned long *) (& fields->f_uimm16));
00355       break;
00356     case XC16X_OPERAND_UPOF16 :
00357       {
00358         bfd_vma value = 0;
00359         errmsg = cgen_parse_address (cd, strp, XC16X_OPERAND_UPOF16, 0, NULL,  & value);
00360         fields->f_memory = value;
00361       }
00362       break;
00363     case XC16X_OPERAND_USEG16 :
00364       errmsg = cgen_parse_unsigned_integer (cd, strp, XC16X_OPERAND_USEG16, (unsigned long *) (& fields->f_offset16));
00365       break;
00366     case XC16X_OPERAND_USEG8 :
00367       errmsg = cgen_parse_unsigned_integer (cd, strp, XC16X_OPERAND_USEG8, (unsigned long *) (& fields->f_seg8));
00368       break;
00369     case XC16X_OPERAND_USOF16 :
00370       errmsg = cgen_parse_unsigned_integer (cd, strp, XC16X_OPERAND_USOF16, (unsigned long *) (& fields->f_offset16));
00371       break;
00372 
00373     default :
00374       /* xgettext:c-format */
00375       fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
00376       abort ();
00377   }
00378 
00379   return errmsg;
00380 }
00381 
00382 cgen_parse_fn * const xc16x_cgen_parse_handlers[] = 
00383 {
00384   parse_insn_normal,
00385 };
00386 
00387 void
00388 xc16x_cgen_init_asm (CGEN_CPU_DESC cd)
00389 {
00390   xc16x_cgen_init_opcode_table (cd);
00391   xc16x_cgen_init_ibld_table (cd);
00392   cd->parse_handlers = & xc16x_cgen_parse_handlers[0];
00393   cd->parse_operand = xc16x_cgen_parse_operand;
00394 #ifdef CGEN_ASM_INIT_HOOK
00395 CGEN_ASM_INIT_HOOK
00396 #endif
00397 }
00398 
00399 
00400 
00401 /* Regex construction routine.
00402 
00403    This translates an opcode syntax string into a regex string,
00404    by replacing any non-character syntax element (such as an
00405    opcode) with the pattern '.*'
00406 
00407    It then compiles the regex and stores it in the opcode, for
00408    later use by xc16x_cgen_assemble_insn
00409 
00410    Returns NULL for success, an error message for failure.  */
00411 
00412 char * 
00413 xc16x_cgen_build_insn_regex (CGEN_INSN *insn)
00414 {  
00415   CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
00416   const char *mnem = CGEN_INSN_MNEMONIC (insn);
00417   char rxbuf[CGEN_MAX_RX_ELEMENTS];
00418   char *rx = rxbuf;
00419   const CGEN_SYNTAX_CHAR_TYPE *syn;
00420   int reg_err;
00421 
00422   syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
00423 
00424   /* Mnemonics come first in the syntax string.  */
00425   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
00426     return _("missing mnemonic in syntax string");
00427   ++syn;
00428 
00429   /* Generate a case sensitive regular expression that emulates case
00430      insensitive matching in the "C" locale.  We cannot generate a case
00431      insensitive regular expression because in Turkish locales, 'i' and 'I'
00432      are not equal modulo case conversion.  */
00433 
00434   /* Copy the literal mnemonic out of the insn.  */
00435   for (; *mnem; mnem++)
00436     {
00437       char c = *mnem;
00438 
00439       if (ISALPHA (c))
00440        {
00441          *rx++ = '[';
00442          *rx++ = TOLOWER (c);
00443          *rx++ = TOUPPER (c);
00444          *rx++ = ']';
00445        }
00446       else
00447        *rx++ = c;
00448     }
00449 
00450   /* Copy any remaining literals from the syntax string into the rx.  */
00451   for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
00452     {
00453       if (CGEN_SYNTAX_CHAR_P (* syn)) 
00454        {
00455          char c = CGEN_SYNTAX_CHAR (* syn);
00456 
00457          switch (c) 
00458            {
00459              /* Escape any regex metacharacters in the syntax.  */
00460            case '.': case '[': case '\\': 
00461            case '*': case '^': case '$': 
00462 
00463 #ifdef CGEN_ESCAPE_EXTENDED_REGEX
00464            case '?': case '{': case '}': 
00465            case '(': case ')': case '*':
00466            case '|': case '+': case ']':
00467 #endif
00468              *rx++ = '\\';
00469              *rx++ = c;
00470              break;
00471 
00472            default:
00473              if (ISALPHA (c))
00474               {
00475                 *rx++ = '[';
00476                 *rx++ = TOLOWER (c);
00477                 *rx++ = TOUPPER (c);
00478                 *rx++ = ']';
00479               }
00480              else
00481               *rx++ = c;
00482              break;
00483            }
00484        }
00485       else
00486        {
00487          /* Replace non-syntax fields with globs.  */
00488          *rx++ = '.';
00489          *rx++ = '*';
00490        }
00491     }
00492 
00493   /* Trailing whitespace ok.  */
00494   * rx++ = '['; 
00495   * rx++ = ' '; 
00496   * rx++ = '\t'; 
00497   * rx++ = ']'; 
00498   * rx++ = '*'; 
00499 
00500   /* But anchor it after that.  */
00501   * rx++ = '$'; 
00502   * rx = '\0';
00503 
00504   CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
00505   reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
00506 
00507   if (reg_err == 0) 
00508     return NULL;
00509   else
00510     {
00511       static char msg[80];
00512 
00513       regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
00514       regfree ((regex_t *) CGEN_INSN_RX (insn));
00515       free (CGEN_INSN_RX (insn));
00516       (CGEN_INSN_RX (insn)) = NULL;
00517       return msg;
00518     }
00519 }
00520 
00521 
00522 /* Default insn parser.
00523 
00524    The syntax string is scanned and operands are parsed and stored in FIELDS.
00525    Relocs are queued as we go via other callbacks.
00526 
00527    ??? Note that this is currently an all-or-nothing parser.  If we fail to
00528    parse the instruction, we return 0 and the caller will start over from
00529    the beginning.  Backtracking will be necessary in parsing subexpressions,
00530    but that can be handled there.  Not handling backtracking here may get
00531    expensive in the case of the m68k.  Deal with later.
00532 
00533    Returns NULL for success, an error message for failure.  */
00534 
00535 static const char *
00536 parse_insn_normal (CGEN_CPU_DESC cd,
00537                  const CGEN_INSN *insn,
00538                  const char **strp,
00539                  CGEN_FIELDS *fields)
00540 {
00541   /* ??? Runtime added insns not handled yet.  */
00542   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
00543   const char *str = *strp;
00544   const char *errmsg;
00545   const char *p;
00546   const CGEN_SYNTAX_CHAR_TYPE * syn;
00547 #ifdef CGEN_MNEMONIC_OPERANDS
00548   /* FIXME: wip */
00549   int past_opcode_p;
00550 #endif
00551 
00552   /* For now we assume the mnemonic is first (there are no leading operands).
00553      We can parse it without needing to set up operand parsing.
00554      GAS's input scrubber will ensure mnemonics are lowercase, but we may
00555      not be called from GAS.  */
00556   p = CGEN_INSN_MNEMONIC (insn);
00557   while (*p && TOLOWER (*p) == TOLOWER (*str))
00558     ++p, ++str;
00559 
00560   if (* p)
00561     return _("unrecognized instruction");
00562 
00563 #ifndef CGEN_MNEMONIC_OPERANDS
00564   if (* str && ! ISSPACE (* str))
00565     return _("unrecognized instruction");
00566 #endif
00567 
00568   CGEN_INIT_PARSE (cd);
00569   cgen_init_parse_operand (cd);
00570 #ifdef CGEN_MNEMONIC_OPERANDS
00571   past_opcode_p = 0;
00572 #endif
00573 
00574   /* We don't check for (*str != '\0') here because we want to parse
00575      any trailing fake arguments in the syntax string.  */
00576   syn = CGEN_SYNTAX_STRING (syntax);
00577 
00578   /* Mnemonics come first for now, ensure valid string.  */
00579   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
00580     abort ();
00581 
00582   ++syn;
00583 
00584   while (* syn != 0)
00585     {
00586       /* Non operand chars must match exactly.  */
00587       if (CGEN_SYNTAX_CHAR_P (* syn))
00588        {
00589          /* FIXME: While we allow for non-GAS callers above, we assume the
00590             first char after the mnemonic part is a space.  */
00591          /* FIXME: We also take inappropriate advantage of the fact that
00592             GAS's input scrubber will remove extraneous blanks.  */
00593          if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
00594            {
00595 #ifdef CGEN_MNEMONIC_OPERANDS
00596              if (CGEN_SYNTAX_CHAR(* syn) == ' ')
00597               past_opcode_p = 1;
00598 #endif
00599              ++ syn;
00600              ++ str;
00601            }
00602          else if (*str)
00603            {
00604              /* Syntax char didn't match.  Can't be this insn.  */
00605              static char msg [80];
00606 
00607              /* xgettext:c-format */
00608              sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
00609                      CGEN_SYNTAX_CHAR(*syn), *str);
00610              return msg;
00611            }
00612          else
00613            {
00614              /* Ran out of input.  */
00615              static char msg [80];
00616 
00617              /* xgettext:c-format */
00618              sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
00619                      CGEN_SYNTAX_CHAR(*syn));
00620              return msg;
00621            }
00622          continue;
00623        }
00624 
00625       /* We have an operand of some sort.  */
00626       errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn),
00627                                      &str, fields);
00628       if (errmsg)
00629        return errmsg;
00630 
00631       /* Done with this operand, continue with next one.  */
00632       ++ syn;
00633     }
00634 
00635   /* If we're at the end of the syntax string, we're done.  */
00636   if (* syn == 0)
00637     {
00638       /* FIXME: For the moment we assume a valid `str' can only contain
00639         blanks now.  IE: We needn't try again with a longer version of
00640         the insn and it is assumed that longer versions of insns appear
00641         before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
00642       while (ISSPACE (* str))
00643        ++ str;
00644 
00645       if (* str != '\0')
00646        return _("junk at end of line"); /* FIXME: would like to include `str' */
00647 
00648       return NULL;
00649     }
00650 
00651   /* We couldn't parse it.  */
00652   return _("unrecognized instruction");
00653 }
00654 
00655 /* Main entry point.
00656    This routine is called for each instruction to be assembled.
00657    STR points to the insn to be assembled.
00658    We assume all necessary tables have been initialized.
00659    The assembled instruction, less any fixups, is stored in BUF.
00660    Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
00661    still needs to be converted to target byte order, otherwise BUF is an array
00662    of bytes in target byte order.
00663    The result is a pointer to the insn's entry in the opcode table,
00664    or NULL if an error occured (an error message will have already been
00665    printed).
00666 
00667    Note that when processing (non-alias) macro-insns,
00668    this function recurses.
00669 
00670    ??? It's possible to make this cpu-independent.
00671    One would have to deal with a few minor things.
00672    At this point in time doing so would be more of a curiosity than useful
00673    [for example this file isn't _that_ big], but keeping the possibility in
00674    mind helps keep the design clean.  */
00675 
00676 const CGEN_INSN *
00677 xc16x_cgen_assemble_insn (CGEN_CPU_DESC cd,
00678                         const char *str,
00679                         CGEN_FIELDS *fields,
00680                         CGEN_INSN_BYTES_PTR buf,
00681                         char **errmsg)
00682 {
00683   const char *start;
00684   CGEN_INSN_LIST *ilist;
00685   const char *parse_errmsg = NULL;
00686   const char *insert_errmsg = NULL;
00687   int recognized_mnemonic = 0;
00688 
00689   /* Skip leading white space.  */
00690   while (ISSPACE (* str))
00691     ++ str;
00692 
00693   /* The instructions are stored in hashed lists.
00694      Get the first in the list.  */
00695   ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
00696 
00697   /* Keep looking until we find a match.  */
00698   start = str;
00699   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
00700     {
00701       const CGEN_INSN *insn = ilist->insn;
00702       recognized_mnemonic = 1;
00703 
00704 #ifdef CGEN_VALIDATE_INSN_SUPPORTED 
00705       /* Not usually needed as unsupported opcodes
00706         shouldn't be in the hash lists.  */
00707       /* Is this insn supported by the selected cpu?  */
00708       if (! xc16x_cgen_insn_supported (cd, insn))
00709        continue;
00710 #endif
00711       /* If the RELAXED attribute is set, this is an insn that shouldn't be
00712         chosen immediately.  Instead, it is used during assembler/linker
00713         relaxation if possible.  */
00714       if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
00715        continue;
00716 
00717       str = start;
00718 
00719       /* Skip this insn if str doesn't look right lexically.  */
00720       if (CGEN_INSN_RX (insn) != NULL &&
00721          regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
00722        continue;
00723 
00724       /* Allow parse/insert handlers to obtain length of insn.  */
00725       CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
00726 
00727       parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
00728       if (parse_errmsg != NULL)
00729        continue;
00730 
00731       /* ??? 0 is passed for `pc'.  */
00732       insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
00733                                            (bfd_vma) 0);
00734       if (insert_errmsg != NULL)
00735         continue;
00736 
00737       /* It is up to the caller to actually output the insn and any
00738          queued relocs.  */
00739       return insn;
00740     }
00741 
00742   {
00743     static char errbuf[150];
00744 #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
00745     const char *tmp_errmsg;
00746 
00747     /* If requesting verbose error messages, use insert_errmsg.
00748        Failing that, use parse_errmsg.  */
00749     tmp_errmsg = (insert_errmsg ? insert_errmsg :
00750                 parse_errmsg ? parse_errmsg :
00751                 recognized_mnemonic ?
00752                 _("unrecognized form of instruction") :
00753                 _("unrecognized instruction"));
00754 
00755     if (strlen (start) > 50)
00756       /* xgettext:c-format */
00757       sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
00758     else 
00759       /* xgettext:c-format */
00760       sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
00761 #else
00762     if (strlen (start) > 50)
00763       /* xgettext:c-format */
00764       sprintf (errbuf, _("bad instruction `%.50s...'"), start);
00765     else 
00766       /* xgettext:c-format */
00767       sprintf (errbuf, _("bad instruction `%.50s'"), start);
00768 #endif
00769       
00770     *errmsg = errbuf;
00771     return NULL;
00772   }
00773 }