Back to index

cell-binutils  2.17cvs20070401
mep-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 "mep-desc.h"
00035 #include "mep-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 
00053 #define CGEN_VALIDATE_INSN_SUPPORTED
00054 
00055        const char * parse_csrn       (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *);
00056        const char * parse_tpreg      (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *);
00057        const char * parse_spreg      (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *);
00058        const char * parse_mep_align  (CGEN_CPU_DESC, const char **, enum cgen_operand_type, long *);
00059        const char * parse_mep_alignu (CGEN_CPU_DESC, const char **, enum cgen_operand_type, unsigned long *);
00060 static const char * parse_signed16   (CGEN_CPU_DESC, const char **, int, long *);
00061 static const char * parse_unsigned16 (CGEN_CPU_DESC, const char **, int, unsigned long *);
00062 static const char * parse_lo16       (CGEN_CPU_DESC, const char **, int, long *, long);
00063 static const char * parse_unsigned7  (CGEN_CPU_DESC, const char **, enum cgen_operand_type, unsigned long *);
00064 static const char * parse_zero       (CGEN_CPU_DESC, const char **, int, long *);
00065 
00066 const char *
00067 parse_csrn (CGEN_CPU_DESC cd, const char **strp,
00068            CGEN_KEYWORD *keyword_table, long *field)
00069 {
00070   const char *err;
00071   unsigned long value;
00072 
00073   err = cgen_parse_keyword (cd, strp, keyword_table, field);
00074   if (!err)
00075     return NULL;
00076 
00077   err = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_CSRN_IDX, & value);
00078   if (err)
00079     return err;
00080   *field = value;
00081   return NULL;
00082 }
00083 
00084 /* begin-cop-ip-parse-handlers */
00085 static const char *
00086 parse_fmax_cr (CGEN_CPU_DESC cd,
00087        const char **strp,
00088        CGEN_KEYWORD *keyword_table  ATTRIBUTE_UNUSED,
00089        long *field)
00090 {
00091   return cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_cr_fmax, field);
00092 }
00093 static const char *
00094 parse_fmax_ccr (CGEN_CPU_DESC cd,
00095        const char **strp,
00096        CGEN_KEYWORD *keyword_table  ATTRIBUTE_UNUSED,
00097        long *field)
00098 {
00099   return cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_ccr_fmax, field);
00100 }
00101 /* end-cop-ip-parse-handlers */
00102 
00103 const char *
00104 parse_tpreg (CGEN_CPU_DESC cd, const char ** strp,
00105             CGEN_KEYWORD *keyword_table, long *field)
00106 {
00107   const char *err;
00108 
00109   err = cgen_parse_keyword (cd, strp, keyword_table, field);
00110   if (err)
00111     return err;
00112   if (*field != 13)
00113     return _("Only $tp or $13 allowed for this opcode");
00114   return NULL;
00115 }
00116 
00117 const char *
00118 parse_spreg (CGEN_CPU_DESC cd, const char ** strp,
00119             CGEN_KEYWORD *keyword_table, long *field)
00120 {
00121   const char *err;
00122 
00123   err = cgen_parse_keyword (cd, strp, keyword_table, field);
00124   if (err)
00125     return err;
00126   if (*field != 15)
00127     return _("Only $sp or $15 allowed for this opcode");
00128   return NULL;
00129 }
00130 
00131 const char *
00132 parse_mep_align (CGEN_CPU_DESC cd, const char ** strp,
00133                enum cgen_operand_type type, long *field)
00134 {
00135   long lsbs = 0;
00136   const char *err;
00137 
00138   switch (type)
00139     {
00140     case MEP_OPERAND_PCREL8A2:
00141     case MEP_OPERAND_PCREL12A2:
00142     case MEP_OPERAND_PCREL17A2:
00143     case MEP_OPERAND_PCREL24A2:
00144     case MEP_OPERAND_CDISP8A2:
00145     case MEP_OPERAND_CDISP8A4:
00146     case MEP_OPERAND_CDISP8A8:
00147       err = cgen_parse_signed_integer   (cd, strp, type, field);
00148       break;
00149     case MEP_OPERAND_PCABS24A2:
00150     case MEP_OPERAND_UDISP7:
00151     case MEP_OPERAND_UDISP7A2:
00152     case MEP_OPERAND_UDISP7A4:
00153     case MEP_OPERAND_UIMM7A4:
00154     case MEP_OPERAND_ADDR24A4:
00155       err = cgen_parse_unsigned_integer (cd, strp, type, (unsigned long *) field);
00156       break;
00157     default:
00158       abort();
00159     }
00160   if (err)
00161     return err;
00162   switch (type)
00163     {
00164     case MEP_OPERAND_UDISP7:
00165       lsbs = 0;
00166       break;
00167     case MEP_OPERAND_PCREL8A2:
00168     case MEP_OPERAND_PCREL12A2:
00169     case MEP_OPERAND_PCREL17A2:
00170     case MEP_OPERAND_PCREL24A2:
00171     case MEP_OPERAND_PCABS24A2:
00172     case MEP_OPERAND_UDISP7A2:
00173     case MEP_OPERAND_CDISP8A2:
00174       lsbs = *field & 1;
00175       break;
00176     case MEP_OPERAND_UDISP7A4:
00177     case MEP_OPERAND_UIMM7A4:
00178     case MEP_OPERAND_ADDR24A4:
00179     case MEP_OPERAND_CDISP8A4:
00180       lsbs = *field & 3;
00181       break;
00182     case MEP_OPERAND_CDISP8A8:
00183       lsbs = *field & 7;
00184       break;
00185     default:
00186       /* Safe assumption?  */
00187       abort ();
00188     }
00189   if (lsbs)
00190     return "Value is not aligned enough";
00191   return NULL;
00192 }
00193 
00194 const char *
00195 parse_mep_alignu (CGEN_CPU_DESC cd, const char ** strp,
00196                enum cgen_operand_type type, unsigned long *field)
00197 {
00198   return parse_mep_align (cd, strp, type, (long *) field);
00199 }
00200 
00201 
00202 /* Handle %lo(), %tpoff(), %sdaoff(), %hi(), and other signed
00203    constants in a signed context.  */
00204 
00205 static const char *
00206 parse_signed16 (CGEN_CPU_DESC cd,
00207               const char **strp,
00208               int opindex,
00209               long *valuep)
00210 {
00211   return parse_lo16 (cd, strp, opindex, valuep, 1);
00212 }
00213 
00214 static const char *
00215 parse_lo16 (CGEN_CPU_DESC cd,
00216            const char **strp,
00217            int opindex,
00218            long *valuep,
00219            long signedp)
00220 {
00221   const char *errmsg;
00222   enum cgen_parse_operand_result result_type;
00223   bfd_vma value;
00224 
00225   if (strncasecmp (*strp, "%lo(", 4) == 0)
00226     {
00227       *strp += 4;
00228       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_LOW16,
00229                                & result_type, & value);
00230       if (**strp != ')')
00231        return _("missing `)'");
00232       ++*strp;
00233       if (errmsg == NULL
00234          && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
00235        value &= 0xffff;
00236       if (signedp)
00237        *valuep = (long)(short) value;
00238       else
00239        *valuep = value;
00240       return errmsg;
00241     }
00242 
00243   if (strncasecmp (*strp, "%hi(", 4) == 0)
00244     {
00245       *strp += 4;
00246       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16S,
00247                                & result_type, & value);
00248       if (**strp != ')')
00249        return _("missing `)'");
00250       ++*strp;
00251       if (errmsg == NULL
00252          && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
00253        value = (value + 0x8000) >> 16;
00254       *valuep = value;
00255       return errmsg;
00256     }
00257 
00258   if (strncasecmp (*strp, "%uhi(", 5) == 0)
00259     {
00260       *strp += 5;
00261       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16U,
00262                                & result_type, & value);
00263       if (**strp != ')')
00264        return _("missing `)'");
00265       ++*strp;
00266       if (errmsg == NULL
00267          && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
00268        value = value >> 16;
00269       *valuep = value;
00270       return errmsg;
00271     }
00272 
00273   if (strncasecmp (*strp, "%sdaoff(", 8) == 0)
00274     {
00275       *strp += 8;
00276       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_GPREL,
00277                                NULL, & value);
00278       if (**strp != ')')
00279        return _("missing `)'");
00280       ++*strp;
00281       *valuep = value;
00282       return errmsg;
00283     }
00284 
00285   if (strncasecmp (*strp, "%tpoff(", 7) == 0)
00286     {
00287       *strp += 7;
00288       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_TPREL,
00289                                NULL, & value);
00290       if (**strp != ')')
00291        return _("missing `)'");
00292       ++*strp;
00293       *valuep = value;
00294       return errmsg;
00295     }
00296 
00297   if (**strp == '%')
00298     return _("invalid %function() here");
00299 
00300   return cgen_parse_signed_integer (cd, strp, opindex, valuep);
00301 }
00302 
00303 static const char *
00304 parse_unsigned16 (CGEN_CPU_DESC cd,
00305                 const char **strp,
00306                 int opindex,
00307                 unsigned long *valuep)
00308 {
00309   return parse_lo16 (cd, strp, opindex, (long *) valuep, 0);
00310 }
00311 
00312 /* A special case of parse_signed16 which accepts only the value zero.  */
00313 
00314 static const char *
00315 parse_zero (CGEN_CPU_DESC cd, const char **strp, int opindex, long *valuep)
00316 {
00317   const char *errmsg;
00318   enum cgen_parse_operand_result result_type;
00319   bfd_vma value;
00320 
00321   /*fprintf(stderr, "dj: signed parse opindex `%s'\n", *strp);*/
00322 
00323   /* Prevent ($ry) from being attempted as an expression on 'sw $rx,($ry)'.
00324      It will fail and cause ry to be listed as an undefined symbol in the
00325      listing.  */
00326   if (strncmp (*strp, "($", 2) == 0)
00327     return "not zero"; /* any string will do -- will never be seen.  */
00328 
00329   if (strncasecmp (*strp, "%lo(", 4) == 0)
00330     {
00331       *strp += 4;
00332       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_LOW16,
00333                                &result_type, &value);
00334       if (**strp != ')')
00335        return "missing `)'";
00336       ++*strp;
00337       if (errmsg == NULL
00338          && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
00339        return "not zero"; /* any string will do -- will never be seen.  */
00340       *valuep = value;
00341       return errmsg;
00342     }
00343 
00344   if (strncasecmp (*strp, "%hi(", 4) == 0)
00345     {
00346       *strp += 4;
00347       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16S,
00348                                &result_type, &value);
00349       if (**strp != ')')
00350        return "missing `)'";
00351       ++*strp;
00352       if (errmsg == NULL
00353          && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
00354        return "not zero"; /* any string will do -- will never be seen.  */
00355       *valuep = value;
00356       return errmsg;
00357     }
00358 
00359   if (strncasecmp (*strp, "%uhi(", 5) == 0)
00360     {
00361       *strp += 5;
00362       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16U,
00363                                &result_type, &value);
00364       if (**strp != ')')
00365        return "missing `)'";
00366       ++*strp;
00367       if (errmsg == NULL
00368          && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
00369        return "not zero"; /* any string will do -- will never be seen.  */
00370       *valuep = value;
00371       return errmsg;
00372     }
00373 
00374   if (strncasecmp (*strp, "%sdaoff(", 8) == 0)
00375     {
00376       *strp += 8;
00377       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_GPREL,
00378                                &result_type, &value);
00379       if (**strp != ')')
00380        return "missing `)'";
00381       ++*strp;
00382       if (errmsg == NULL
00383          && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
00384        return "not zero"; /* any string will do -- will never be seen.  */
00385       *valuep = value;
00386       return errmsg;
00387     }
00388 
00389   if (strncasecmp (*strp, "%tpoff(", 7) == 0)
00390     {
00391       *strp += 7;
00392       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_TPREL,
00393                                &result_type, &value);
00394       if (**strp != ')')
00395        return "missing `)'";
00396       ++*strp;
00397       if (errmsg == NULL
00398          && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
00399        return "not zero"; /* any string will do -- will never be seen.  */
00400       *valuep = value;
00401       return errmsg;
00402     }
00403 
00404   if (**strp == '%')
00405     return "invalid %function() here";
00406 
00407   errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_NONE,
00408                             &result_type, &value);
00409   if (errmsg == NULL
00410       && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
00411     return "not zero"; /* any string will do -- will never be seen.  */
00412 
00413   return errmsg;
00414 }
00415 
00416 static const char *
00417 parse_unsigned7 (CGEN_CPU_DESC cd, const char **strp,
00418                enum cgen_operand_type opindex, unsigned long *valuep)
00419 {
00420   const char *errmsg;
00421   bfd_vma value;
00422 
00423   /* fprintf(stderr, "dj: unsigned7 parse `%s'\n", *strp); */
00424 
00425   if (strncasecmp (*strp, "%tpoff(", 7) == 0)
00426     {
00427       int reloc;
00428       *strp += 7;
00429       switch (opindex)
00430        {
00431        case MEP_OPERAND_UDISP7:
00432          reloc = BFD_RELOC_MEP_TPREL7;
00433          break;
00434        case MEP_OPERAND_UDISP7A2:
00435          reloc = BFD_RELOC_MEP_TPREL7A2;
00436          break;
00437        case MEP_OPERAND_UDISP7A4:
00438          reloc = BFD_RELOC_MEP_TPREL7A4;
00439          break;
00440        default:
00441          /* Safe assumption?  */
00442          abort (); 
00443        }
00444       errmsg = cgen_parse_address (cd, strp, opindex, reloc,
00445                                NULL, &value);
00446       if (**strp != ')')
00447        return "missing `)'";
00448       ++*strp;
00449       *valuep = value;
00450       return errmsg;
00451     }
00452 
00453   if (**strp == '%')
00454     return _("invalid %function() here");
00455 
00456   return parse_mep_alignu (cd, strp, opindex, valuep);
00457 }
00458 
00459 /* BEGIN LIGHTWEIGHT MACRO PROCESSOR.  */
00460 
00461 #define MAXARGS 9
00462 
00463 typedef struct
00464 {
00465   char *name;
00466   char *expansion;
00467 }  macro;
00468 
00469 typedef struct
00470 {
00471   const char *start;
00472   int len;
00473 } arg;
00474 
00475 macro macros[] =
00476 {
00477   { "sizeof", "(`1.end + (- `1))"},
00478   { "startof", "(`1 | 0)" },
00479   { "align4", "(`1&(~3))"},
00480 /*{ "hi", "(((`1+0x8000)>>16) & 0xffff)" },  */
00481 /*{ "lo", "(`1 & 0xffff)" },  */
00482 /*{ "sdaoff", "((`1-__sdabase) & 0x7f)"},  */
00483 /*{ "tpoff", "((`1-__tpbase) & 0x7f)"},  */
00484   { 0,0 }
00485 };
00486 
00487 static char  * expand_string    (const char *, int);
00488 
00489 static const char *
00490 mep_cgen_expand_macros_and_parse_operand
00491   (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
00492 
00493 static char *
00494 str_append (char *dest, const char *input, int len)
00495 {  
00496   char *new_dest;
00497   int oldlen;
00498 
00499   if (len == 0)
00500     return dest;
00501   /* printf("str_append: <<%s>>, <<%s>>, %d\n", dest, input, len); */
00502   oldlen = (dest ? strlen(dest) : 0);
00503   new_dest = realloc (dest, oldlen + len + 1);
00504   memset (new_dest + oldlen, 0, len + 1);
00505   return strncat (new_dest, input, len);
00506 }
00507 
00508 static macro *
00509 lookup_macro (const char *name)
00510 {
00511   macro *m;
00512 
00513   for (m = macros; m->name; ++m)
00514     if (strncmp (m->name, name, strlen(m->name)) == 0)
00515       return m;
00516 
00517   return 0;
00518 }
00519 
00520 static char *
00521 expand_macro (arg *args, int narg, macro *mac)
00522 {
00523   char *result = 0, *rescanned_result = 0;
00524   char *e = mac->expansion;
00525   char *mark = e;
00526   int arg = 0;
00527 
00528   /*  printf("expanding macro %s with %d args\n", mac->name, narg + 1); */
00529   while (*e)
00530     {
00531       if (*e == '`' && 
00532          (*e+1) && 
00533          ((*(e + 1) - '1') <= MAXARGS) &&
00534          ((*(e + 1) - '1') <= narg))
00535        {
00536          result = str_append (result, mark, e - mark);
00537          arg = (*(e + 1) - '1');
00538          /* printf("replacing `%d with %s\n", arg+1, args[arg].start); */
00539          result = str_append (result, args[arg].start, args[arg].len);
00540          ++e;
00541          mark = e+1;
00542        }
00543       ++e;
00544     }
00545 
00546   if (mark != e)
00547     result = str_append (result, mark, e - mark);
00548 
00549   if (result)
00550     {
00551       rescanned_result = expand_string (result, 0);
00552       free (result);
00553       return rescanned_result;
00554     }
00555   else 
00556     return result;
00557 }
00558 
00559 #define IN_TEXT 0
00560 #define IN_ARGS 1
00561 
00562 static char *
00563 expand_string (const char *in, int first_only)
00564 {
00565   int num_expansions = 0;
00566   int depth = 0;
00567   int narg = -1;
00568   arg args[MAXARGS];
00569   int state = IN_TEXT;
00570   const char *mark = in;
00571   macro *macro = 0;
00572 
00573   char *expansion = 0;
00574   char *result = 0;
00575 
00576   while (*in)
00577     {
00578       switch (state)
00579        {
00580        case IN_TEXT:
00581          if (*in == '%' && *(in + 1) && (!first_only || num_expansions == 0)) 
00582            {        
00583              macro = lookup_macro (in + 1);
00584              if (macro)
00585               {
00586                 /* printf("entering state %d at '%s'...\n", state, in); */
00587                 result = str_append (result, mark, in - mark);
00588                 mark = in;
00589                 in += 1 + strlen (macro->name);
00590                 while (*in == ' ') ++in;
00591                 if (*in != '(')
00592                   {
00593                     state = IN_TEXT;                   
00594                     macro = 0;
00595                   }
00596                 else
00597                   {
00598                     state = IN_ARGS;
00599                     narg = 0;
00600                     args[narg].start = in + 1;
00601                     args[narg].len = 0;
00602                     mark = in + 1;                     
00603                   }
00604               }
00605            }
00606          break;
00607        case IN_ARGS:
00608          if (depth == 0)
00609            {
00610              switch (*in)
00611               {
00612               case ',':
00613                 narg++;
00614                 args[narg].start = (in + 1);
00615                 args[narg].len = 0;
00616                 break;
00617               case ')':
00618                 state = IN_TEXT;
00619                 /* printf("entering state %d at '%s'...\n", state, in); */
00620                 if (macro)
00621                   {
00622                     expansion = 0;
00623                     expansion = expand_macro (args, narg, macro);
00624                     num_expansions++;
00625                     if (expansion)
00626                      {
00627                        result = str_append (result, expansion, strlen (expansion));
00628                        free (expansion);
00629                      }
00630                   }
00631                 else
00632                   {
00633                     result = str_append (result, mark, in - mark);
00634                   }
00635                 macro = 0;
00636                 mark = in + 1;
00637                 break;
00638               case '(':
00639                 depth++;
00640               default:
00641                 args[narg].len++;
00642                 break;               
00643               }
00644            } 
00645          else
00646            {
00647              if (*in == ')')
00648               depth--;
00649              if (narg > -1)
00650               args[narg].len++;
00651            }
00652          
00653        }
00654       ++in;
00655     }
00656   
00657   if (mark != in)
00658     result = str_append (result, mark, in - mark);
00659   
00660   return result;
00661 }
00662 
00663 #undef IN_ARGS
00664 #undef IN_TEXT
00665 #undef MAXARGS
00666 
00667 
00668 /* END LIGHTWEIGHT MACRO PROCESSOR.  */
00669 
00670 const char * mep_cgen_parse_operand
00671   (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
00672 
00673 const char *
00674 mep_cgen_expand_macros_and_parse_operand (CGEN_CPU_DESC cd, int opindex,
00675                                      const char ** strp_in, CGEN_FIELDS * fields)
00676 {
00677   const char * errmsg = NULL;
00678   char *str = 0, *hold = 0;
00679   const char **strp = 0;
00680 
00681   /* Set up a new pointer to macro-expanded string.  */
00682   str = expand_string (*strp_in, 1);
00683   /* fprintf (stderr, " expanded <<%s>> to <<%s>>\n", *strp_in, str); */
00684 
00685   hold = str;
00686   strp = (const char **)(&str);
00687 
00688   errmsg = mep_cgen_parse_operand (cd, opindex, strp, fields);
00689 
00690   /* Now work out the advance.  */
00691   if (strlen (str) == 0)
00692     *strp_in += strlen (*strp_in);
00693 
00694   else
00695     {
00696       if (strstr (*strp_in, str))
00697        /* A macro-expansion was pulled off the front.  */
00698        *strp_in = strstr (*strp_in, str);  
00699       else
00700        /* A non-macro-expansion was pulled off the front.  */
00701        *strp_in += (str - hold); 
00702     }
00703 
00704   if (hold)
00705     free (hold);
00706 
00707   return errmsg;
00708 }
00709 
00710 #define CGEN_ASM_INIT_HOOK (cd->parse_operand = mep_cgen_expand_macros_and_parse_operand); 
00711 
00712 /* -- dis.c */
00713 
00714 const char * mep_cgen_parse_operand
00715   (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
00716 
00717 /* Main entry point for operand parsing.
00718 
00719    This function is basically just a big switch statement.  Earlier versions
00720    used tables to look up the function to use, but
00721    - if the table contains both assembler and disassembler functions then
00722      the disassembler contains much of the assembler and vice-versa,
00723    - there's a lot of inlining possibilities as things grow,
00724    - using a switch statement avoids the function call overhead.
00725 
00726    This function could be moved into `parse_insn_normal', but keeping it
00727    separate makes clear the interface between `parse_insn_normal' and each of
00728    the handlers.  */
00729 
00730 const char *
00731 mep_cgen_parse_operand (CGEN_CPU_DESC cd,
00732                         int opindex,
00733                         const char ** strp,
00734                         CGEN_FIELDS * fields)
00735 {
00736   const char * errmsg = NULL;
00737   /* Used by scalar operands that still need to be parsed.  */
00738   long junk ATTRIBUTE_UNUSED;
00739 
00740   switch (opindex)
00741     {
00742     case MEP_OPERAND_ADDR24A4 :
00743       errmsg = parse_mep_alignu (cd, strp, MEP_OPERAND_ADDR24A4, (unsigned long *) (& fields->f_24u8a4n));
00744       break;
00745     case MEP_OPERAND_CALLNUM :
00746       errmsg = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_CALLNUM, (unsigned long *) (& fields->f_callnum));
00747       break;
00748     case MEP_OPERAND_CCCC :
00749       errmsg = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_CCCC, (unsigned long *) (& fields->f_rm));
00750       break;
00751     case MEP_OPERAND_CCRN :
00752       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_ccr, & fields->f_ccrn);
00753       break;
00754     case MEP_OPERAND_CDISP8 :
00755       errmsg = cgen_parse_signed_integer (cd, strp, MEP_OPERAND_CDISP8, (long *) (& fields->f_8s24));
00756       break;
00757     case MEP_OPERAND_CDISP8A2 :
00758       errmsg = parse_mep_align (cd, strp, MEP_OPERAND_CDISP8A2, (long *) (& fields->f_8s24a2));
00759       break;
00760     case MEP_OPERAND_CDISP8A4 :
00761       errmsg = parse_mep_align (cd, strp, MEP_OPERAND_CDISP8A4, (long *) (& fields->f_8s24a4));
00762       break;
00763     case MEP_OPERAND_CDISP8A8 :
00764       errmsg = parse_mep_align (cd, strp, MEP_OPERAND_CDISP8A8, (long *) (& fields->f_8s24a8));
00765       break;
00766     case MEP_OPERAND_CIMM4 :
00767       errmsg = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_CIMM4, (unsigned long *) (& fields->f_rn));
00768       break;
00769     case MEP_OPERAND_CIMM5 :
00770       errmsg = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_CIMM5, (unsigned long *) (& fields->f_5u24));
00771       break;
00772     case MEP_OPERAND_CODE16 :
00773       errmsg = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_CODE16, (unsigned long *) (& fields->f_16u16));
00774       break;
00775     case MEP_OPERAND_CODE24 :
00776       errmsg = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_CODE24, (unsigned long *) (& fields->f_24u4n));
00777       break;
00778     case MEP_OPERAND_CP_FLAG :
00779       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_ccr, & junk);
00780       break;
00781     case MEP_OPERAND_CRN :
00782       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_cr, & fields->f_crn);
00783       break;
00784     case MEP_OPERAND_CRN64 :
00785       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_cr64, & fields->f_crn);
00786       break;
00787     case MEP_OPERAND_CRNX :
00788       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_cr, & fields->f_crnx);
00789       break;
00790     case MEP_OPERAND_CRNX64 :
00791       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_cr64, & fields->f_crnx);
00792       break;
00793     case MEP_OPERAND_CSRN :
00794       errmsg = parse_csrn (cd, strp, & mep_cgen_opval_h_csr, & fields->f_csrn);
00795       break;
00796     case MEP_OPERAND_CSRN_IDX :
00797       errmsg = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_CSRN_IDX, (unsigned long *) (& fields->f_csrn));
00798       break;
00799     case MEP_OPERAND_DBG :
00800       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk);
00801       break;
00802     case MEP_OPERAND_DEPC :
00803       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk);
00804       break;
00805     case MEP_OPERAND_EPC :
00806       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk);
00807       break;
00808     case MEP_OPERAND_EXC :
00809       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk);
00810       break;
00811     case MEP_OPERAND_FMAX_CCRN :
00812       errmsg = parse_fmax_ccr (cd, strp, & mep_cgen_opval_h_ccr, & fields->f_fmax_4_4);
00813       break;
00814     case MEP_OPERAND_FMAX_FRD :
00815       errmsg = parse_fmax_cr (cd, strp, & mep_cgen_opval_h_cr, & fields->f_fmax_frd);
00816       break;
00817     case MEP_OPERAND_FMAX_FRD_INT :
00818       errmsg = parse_fmax_cr (cd, strp, & mep_cgen_opval_h_cr, & fields->f_fmax_frd);
00819       break;
00820     case MEP_OPERAND_FMAX_FRM :
00821       errmsg = parse_fmax_cr (cd, strp, & mep_cgen_opval_h_cr, & fields->f_fmax_frm);
00822       break;
00823     case MEP_OPERAND_FMAX_FRN :
00824       errmsg = parse_fmax_cr (cd, strp, & mep_cgen_opval_h_cr, & fields->f_fmax_frn);
00825       break;
00826     case MEP_OPERAND_FMAX_FRN_INT :
00827       errmsg = parse_fmax_cr (cd, strp, & mep_cgen_opval_h_cr, & fields->f_fmax_frn);
00828       break;
00829     case MEP_OPERAND_FMAX_RM :
00830       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_fmax_rm);
00831       break;
00832     case MEP_OPERAND_HI :
00833       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk);
00834       break;
00835     case MEP_OPERAND_LO :
00836       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk);
00837       break;
00838     case MEP_OPERAND_LP :
00839       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk);
00840       break;
00841     case MEP_OPERAND_MB0 :
00842       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk);
00843       break;
00844     case MEP_OPERAND_MB1 :
00845       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk);
00846       break;
00847     case MEP_OPERAND_ME0 :
00848       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk);
00849       break;
00850     case MEP_OPERAND_ME1 :
00851       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk);
00852       break;
00853     case MEP_OPERAND_NPC :
00854       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk);
00855       break;
00856     case MEP_OPERAND_OPT :
00857       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk);
00858       break;
00859     case MEP_OPERAND_PCABS24A2 :
00860       errmsg = parse_mep_alignu (cd, strp, MEP_OPERAND_PCABS24A2, (unsigned long *) (& fields->f_24u5a2n));
00861       break;
00862     case MEP_OPERAND_PCREL12A2 :
00863       errmsg = parse_mep_align (cd, strp, MEP_OPERAND_PCREL12A2, (long *) (& fields->f_12s4a2));
00864       break;
00865     case MEP_OPERAND_PCREL17A2 :
00866       errmsg = parse_mep_align (cd, strp, MEP_OPERAND_PCREL17A2, (long *) (& fields->f_17s16a2));
00867       break;
00868     case MEP_OPERAND_PCREL24A2 :
00869       errmsg = parse_mep_align (cd, strp, MEP_OPERAND_PCREL24A2, (long *) (& fields->f_24s5a2n));
00870       break;
00871     case MEP_OPERAND_PCREL8A2 :
00872       errmsg = parse_mep_align (cd, strp, MEP_OPERAND_PCREL8A2, (long *) (& fields->f_8s8a2));
00873       break;
00874     case MEP_OPERAND_PSW :
00875       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk);
00876       break;
00877     case MEP_OPERAND_R0 :
00878       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & junk);
00879       break;
00880     case MEP_OPERAND_R1 :
00881       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & junk);
00882       break;
00883     case MEP_OPERAND_RL :
00884       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rl);
00885       break;
00886     case MEP_OPERAND_RM :
00887       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rm);
00888       break;
00889     case MEP_OPERAND_RMA :
00890       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rm);
00891       break;
00892     case MEP_OPERAND_RN :
00893       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn);
00894       break;
00895     case MEP_OPERAND_RN3 :
00896       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn3);
00897       break;
00898     case MEP_OPERAND_RN3C :
00899       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn3);
00900       break;
00901     case MEP_OPERAND_RN3L :
00902       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn3);
00903       break;
00904     case MEP_OPERAND_RN3S :
00905       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn3);
00906       break;
00907     case MEP_OPERAND_RN3UC :
00908       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn3);
00909       break;
00910     case MEP_OPERAND_RN3UL :
00911       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn3);
00912       break;
00913     case MEP_OPERAND_RN3US :
00914       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn3);
00915       break;
00916     case MEP_OPERAND_RNC :
00917       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn);
00918       break;
00919     case MEP_OPERAND_RNL :
00920       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn);
00921       break;
00922     case MEP_OPERAND_RNS :
00923       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn);
00924       break;
00925     case MEP_OPERAND_RNUC :
00926       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn);
00927       break;
00928     case MEP_OPERAND_RNUL :
00929       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn);
00930       break;
00931     case MEP_OPERAND_RNUS :
00932       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & fields->f_rn);
00933       break;
00934     case MEP_OPERAND_SAR :
00935       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_csr, & junk);
00936       break;
00937     case MEP_OPERAND_SDISP16 :
00938       errmsg = parse_signed16 (cd, strp, MEP_OPERAND_SDISP16, (long *) (& fields->f_16s16));
00939       break;
00940     case MEP_OPERAND_SIMM16 :
00941       errmsg = parse_signed16 (cd, strp, MEP_OPERAND_SIMM16, (long *) (& fields->f_16s16));
00942       break;
00943     case MEP_OPERAND_SIMM6 :
00944       errmsg = cgen_parse_signed_integer (cd, strp, MEP_OPERAND_SIMM6, (long *) (& fields->f_6s8));
00945       break;
00946     case MEP_OPERAND_SIMM8 :
00947       errmsg = cgen_parse_signed_integer (cd, strp, MEP_OPERAND_SIMM8, (long *) (& fields->f_8s8));
00948       break;
00949     case MEP_OPERAND_SP :
00950       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & junk);
00951       break;
00952     case MEP_OPERAND_SPR :
00953       errmsg = parse_spreg (cd, strp, & mep_cgen_opval_h_gpr, & junk);
00954       break;
00955     case MEP_OPERAND_TP :
00956       errmsg = cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_gpr, & junk);
00957       break;
00958     case MEP_OPERAND_TPR :
00959       errmsg = parse_tpreg (cd, strp, & mep_cgen_opval_h_gpr, & junk);
00960       break;
00961     case MEP_OPERAND_UDISP2 :
00962       errmsg = cgen_parse_signed_integer (cd, strp, MEP_OPERAND_UDISP2, (long *) (& fields->f_2u6));
00963       break;
00964     case MEP_OPERAND_UDISP7 :
00965       errmsg = parse_unsigned7 (cd, strp, MEP_OPERAND_UDISP7, (unsigned long *) (& fields->f_7u9));
00966       break;
00967     case MEP_OPERAND_UDISP7A2 :
00968       errmsg = parse_unsigned7 (cd, strp, MEP_OPERAND_UDISP7A2, (unsigned long *) (& fields->f_7u9a2));
00969       break;
00970     case MEP_OPERAND_UDISP7A4 :
00971       errmsg = parse_unsigned7 (cd, strp, MEP_OPERAND_UDISP7A4, (unsigned long *) (& fields->f_7u9a4));
00972       break;
00973     case MEP_OPERAND_UIMM16 :
00974       errmsg = parse_unsigned16 (cd, strp, MEP_OPERAND_UIMM16, (unsigned long *) (& fields->f_16u16));
00975       break;
00976     case MEP_OPERAND_UIMM2 :
00977       errmsg = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_UIMM2, (unsigned long *) (& fields->f_2u10));
00978       break;
00979     case MEP_OPERAND_UIMM24 :
00980       errmsg = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_UIMM24, (unsigned long *) (& fields->f_24u8n));
00981       break;
00982     case MEP_OPERAND_UIMM3 :
00983       errmsg = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_UIMM3, (unsigned long *) (& fields->f_3u5));
00984       break;
00985     case MEP_OPERAND_UIMM4 :
00986       errmsg = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_UIMM4, (unsigned long *) (& fields->f_4u8));
00987       break;
00988     case MEP_OPERAND_UIMM5 :
00989       errmsg = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_UIMM5, (unsigned long *) (& fields->f_5u8));
00990       break;
00991     case MEP_OPERAND_UIMM7A4 :
00992       errmsg = parse_mep_alignu (cd, strp, MEP_OPERAND_UIMM7A4, (unsigned long *) (& fields->f_7u9a4));
00993       break;
00994     case MEP_OPERAND_ZERO :
00995       errmsg = parse_zero (cd, strp, MEP_OPERAND_ZERO, (long *) (& junk));
00996       break;
00997 
00998     default :
00999       /* xgettext:c-format */
01000       fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
01001       abort ();
01002   }
01003 
01004   return errmsg;
01005 }
01006 
01007 cgen_parse_fn * const mep_cgen_parse_handlers[] = 
01008 {
01009   parse_insn_normal,
01010 };
01011 
01012 void
01013 mep_cgen_init_asm (CGEN_CPU_DESC cd)
01014 {
01015   mep_cgen_init_opcode_table (cd);
01016   mep_cgen_init_ibld_table (cd);
01017   cd->parse_handlers = & mep_cgen_parse_handlers[0];
01018   cd->parse_operand = mep_cgen_parse_operand;
01019 #ifdef CGEN_ASM_INIT_HOOK
01020 CGEN_ASM_INIT_HOOK
01021 #endif
01022 }
01023 
01024 
01025 
01026 /* Regex construction routine.
01027 
01028    This translates an opcode syntax string into a regex string,
01029    by replacing any non-character syntax element (such as an
01030    opcode) with the pattern '.*'
01031 
01032    It then compiles the regex and stores it in the opcode, for
01033    later use by mep_cgen_assemble_insn
01034 
01035    Returns NULL for success, an error message for failure.  */
01036 
01037 char * 
01038 mep_cgen_build_insn_regex (CGEN_INSN *insn)
01039 {  
01040   CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
01041   const char *mnem = CGEN_INSN_MNEMONIC (insn);
01042   char rxbuf[CGEN_MAX_RX_ELEMENTS];
01043   char *rx = rxbuf;
01044   const CGEN_SYNTAX_CHAR_TYPE *syn;
01045   int reg_err;
01046 
01047   syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
01048 
01049   /* Mnemonics come first in the syntax string.  */
01050   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
01051     return _("missing mnemonic in syntax string");
01052   ++syn;
01053 
01054   /* Generate a case sensitive regular expression that emulates case
01055      insensitive matching in the "C" locale.  We cannot generate a case
01056      insensitive regular expression because in Turkish locales, 'i' and 'I'
01057      are not equal modulo case conversion.  */
01058 
01059   /* Copy the literal mnemonic out of the insn.  */
01060   for (; *mnem; mnem++)
01061     {
01062       char c = *mnem;
01063 
01064       if (ISALPHA (c))
01065        {
01066          *rx++ = '[';
01067          *rx++ = TOLOWER (c);
01068          *rx++ = TOUPPER (c);
01069          *rx++ = ']';
01070        }
01071       else
01072        *rx++ = c;
01073     }
01074 
01075   /* Copy any remaining literals from the syntax string into the rx.  */
01076   for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
01077     {
01078       if (CGEN_SYNTAX_CHAR_P (* syn)) 
01079        {
01080          char c = CGEN_SYNTAX_CHAR (* syn);
01081 
01082          switch (c) 
01083            {
01084              /* Escape any regex metacharacters in the syntax.  */
01085            case '.': case '[': case '\\': 
01086            case '*': case '^': case '$': 
01087 
01088 #ifdef CGEN_ESCAPE_EXTENDED_REGEX
01089            case '?': case '{': case '}': 
01090            case '(': case ')': case '*':
01091            case '|': case '+': case ']':
01092 #endif
01093              *rx++ = '\\';
01094              *rx++ = c;
01095              break;
01096 
01097            default:
01098              if (ISALPHA (c))
01099               {
01100                 *rx++ = '[';
01101                 *rx++ = TOLOWER (c);
01102                 *rx++ = TOUPPER (c);
01103                 *rx++ = ']';
01104               }
01105              else
01106               *rx++ = c;
01107              break;
01108            }
01109        }
01110       else
01111        {
01112          /* Replace non-syntax fields with globs.  */
01113          *rx++ = '.';
01114          *rx++ = '*';
01115        }
01116     }
01117 
01118   /* Trailing whitespace ok.  */
01119   * rx++ = '['; 
01120   * rx++ = ' '; 
01121   * rx++ = '\t'; 
01122   * rx++ = ']'; 
01123   * rx++ = '*'; 
01124 
01125   /* But anchor it after that.  */
01126   * rx++ = '$'; 
01127   * rx = '\0';
01128 
01129   CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
01130   reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
01131 
01132   if (reg_err == 0) 
01133     return NULL;
01134   else
01135     {
01136       static char msg[80];
01137 
01138       regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
01139       regfree ((regex_t *) CGEN_INSN_RX (insn));
01140       free (CGEN_INSN_RX (insn));
01141       (CGEN_INSN_RX (insn)) = NULL;
01142       return msg;
01143     }
01144 }
01145 
01146 
01147 /* Default insn parser.
01148 
01149    The syntax string is scanned and operands are parsed and stored in FIELDS.
01150    Relocs are queued as we go via other callbacks.
01151 
01152    ??? Note that this is currently an all-or-nothing parser.  If we fail to
01153    parse the instruction, we return 0 and the caller will start over from
01154    the beginning.  Backtracking will be necessary in parsing subexpressions,
01155    but that can be handled there.  Not handling backtracking here may get
01156    expensive in the case of the m68k.  Deal with later.
01157 
01158    Returns NULL for success, an error message for failure.  */
01159 
01160 static const char *
01161 parse_insn_normal (CGEN_CPU_DESC cd,
01162                  const CGEN_INSN *insn,
01163                  const char **strp,
01164                  CGEN_FIELDS *fields)
01165 {
01166   /* ??? Runtime added insns not handled yet.  */
01167   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
01168   const char *str = *strp;
01169   const char *errmsg;
01170   const char *p;
01171   const CGEN_SYNTAX_CHAR_TYPE * syn;
01172 #ifdef CGEN_MNEMONIC_OPERANDS
01173   /* FIXME: wip */
01174   int past_opcode_p;
01175 #endif
01176 
01177   /* For now we assume the mnemonic is first (there are no leading operands).
01178      We can parse it without needing to set up operand parsing.
01179      GAS's input scrubber will ensure mnemonics are lowercase, but we may
01180      not be called from GAS.  */
01181   p = CGEN_INSN_MNEMONIC (insn);
01182   while (*p && TOLOWER (*p) == TOLOWER (*str))
01183     ++p, ++str;
01184 
01185   if (* p)
01186     return _("unrecognized instruction");
01187 
01188 #ifndef CGEN_MNEMONIC_OPERANDS
01189   if (* str && ! ISSPACE (* str))
01190     return _("unrecognized instruction");
01191 #endif
01192 
01193   CGEN_INIT_PARSE (cd);
01194   cgen_init_parse_operand (cd);
01195 #ifdef CGEN_MNEMONIC_OPERANDS
01196   past_opcode_p = 0;
01197 #endif
01198 
01199   /* We don't check for (*str != '\0') here because we want to parse
01200      any trailing fake arguments in the syntax string.  */
01201   syn = CGEN_SYNTAX_STRING (syntax);
01202 
01203   /* Mnemonics come first for now, ensure valid string.  */
01204   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
01205     abort ();
01206 
01207   ++syn;
01208 
01209   while (* syn != 0)
01210     {
01211       /* Non operand chars must match exactly.  */
01212       if (CGEN_SYNTAX_CHAR_P (* syn))
01213        {
01214          /* FIXME: While we allow for non-GAS callers above, we assume the
01215             first char after the mnemonic part is a space.  */
01216          /* FIXME: We also take inappropriate advantage of the fact that
01217             GAS's input scrubber will remove extraneous blanks.  */
01218          if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
01219            {
01220 #ifdef CGEN_MNEMONIC_OPERANDS
01221              if (CGEN_SYNTAX_CHAR(* syn) == ' ')
01222               past_opcode_p = 1;
01223 #endif
01224              ++ syn;
01225              ++ str;
01226            }
01227          else if (*str)
01228            {
01229              /* Syntax char didn't match.  Can't be this insn.  */
01230              static char msg [80];
01231 
01232              /* xgettext:c-format */
01233              sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
01234                      CGEN_SYNTAX_CHAR(*syn), *str);
01235              return msg;
01236            }
01237          else
01238            {
01239              /* Ran out of input.  */
01240              static char msg [80];
01241 
01242              /* xgettext:c-format */
01243              sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
01244                      CGEN_SYNTAX_CHAR(*syn));
01245              return msg;
01246            }
01247          continue;
01248        }
01249 
01250       /* We have an operand of some sort.  */
01251       errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn),
01252                                      &str, fields);
01253       if (errmsg)
01254        return errmsg;
01255 
01256       /* Done with this operand, continue with next one.  */
01257       ++ syn;
01258     }
01259 
01260   /* If we're at the end of the syntax string, we're done.  */
01261   if (* syn == 0)
01262     {
01263       /* FIXME: For the moment we assume a valid `str' can only contain
01264         blanks now.  IE: We needn't try again with a longer version of
01265         the insn and it is assumed that longer versions of insns appear
01266         before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
01267       while (ISSPACE (* str))
01268        ++ str;
01269 
01270       if (* str != '\0')
01271        return _("junk at end of line"); /* FIXME: would like to include `str' */
01272 
01273       return NULL;
01274     }
01275 
01276   /* We couldn't parse it.  */
01277   return _("unrecognized instruction");
01278 }
01279 
01280 /* Main entry point.
01281    This routine is called for each instruction to be assembled.
01282    STR points to the insn to be assembled.
01283    We assume all necessary tables have been initialized.
01284    The assembled instruction, less any fixups, is stored in BUF.
01285    Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
01286    still needs to be converted to target byte order, otherwise BUF is an array
01287    of bytes in target byte order.
01288    The result is a pointer to the insn's entry in the opcode table,
01289    or NULL if an error occured (an error message will have already been
01290    printed).
01291 
01292    Note that when processing (non-alias) macro-insns,
01293    this function recurses.
01294 
01295    ??? It's possible to make this cpu-independent.
01296    One would have to deal with a few minor things.
01297    At this point in time doing so would be more of a curiosity than useful
01298    [for example this file isn't _that_ big], but keeping the possibility in
01299    mind helps keep the design clean.  */
01300 
01301 const CGEN_INSN *
01302 mep_cgen_assemble_insn (CGEN_CPU_DESC cd,
01303                         const char *str,
01304                         CGEN_FIELDS *fields,
01305                         CGEN_INSN_BYTES_PTR buf,
01306                         char **errmsg)
01307 {
01308   const char *start;
01309   CGEN_INSN_LIST *ilist;
01310   const char *parse_errmsg = NULL;
01311   const char *insert_errmsg = NULL;
01312   int recognized_mnemonic = 0;
01313 
01314   /* Skip leading white space.  */
01315   while (ISSPACE (* str))
01316     ++ str;
01317 
01318   /* The instructions are stored in hashed lists.
01319      Get the first in the list.  */
01320   ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
01321 
01322   /* Keep looking until we find a match.  */
01323   start = str;
01324   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
01325     {
01326       const CGEN_INSN *insn = ilist->insn;
01327       recognized_mnemonic = 1;
01328 
01329 #ifdef CGEN_VALIDATE_INSN_SUPPORTED 
01330       /* Not usually needed as unsupported opcodes
01331         shouldn't be in the hash lists.  */
01332       /* Is this insn supported by the selected cpu?  */
01333       if (! mep_cgen_insn_supported (cd, insn))
01334        continue;
01335 #endif
01336       /* If the RELAXED attribute is set, this is an insn that shouldn't be
01337         chosen immediately.  Instead, it is used during assembler/linker
01338         relaxation if possible.  */
01339       if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
01340        continue;
01341 
01342       str = start;
01343 
01344       /* Skip this insn if str doesn't look right lexically.  */
01345       if (CGEN_INSN_RX (insn) != NULL &&
01346          regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
01347        continue;
01348 
01349       /* Allow parse/insert handlers to obtain length of insn.  */
01350       CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
01351 
01352       parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
01353       if (parse_errmsg != NULL)
01354        continue;
01355 
01356       /* ??? 0 is passed for `pc'.  */
01357       insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
01358                                            (bfd_vma) 0);
01359       if (insert_errmsg != NULL)
01360         continue;
01361 
01362       /* It is up to the caller to actually output the insn and any
01363          queued relocs.  */
01364       return insn;
01365     }
01366 
01367   {
01368     static char errbuf[150];
01369 #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
01370     const char *tmp_errmsg;
01371 
01372     /* If requesting verbose error messages, use insert_errmsg.
01373        Failing that, use parse_errmsg.  */
01374     tmp_errmsg = (insert_errmsg ? insert_errmsg :
01375                 parse_errmsg ? parse_errmsg :
01376                 recognized_mnemonic ?
01377                 _("unrecognized form of instruction") :
01378                 _("unrecognized instruction"));
01379 
01380     if (strlen (start) > 50)
01381       /* xgettext:c-format */
01382       sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
01383     else 
01384       /* xgettext:c-format */
01385       sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
01386 #else
01387     if (strlen (start) > 50)
01388       /* xgettext:c-format */
01389       sprintf (errbuf, _("bad instruction `%.50s...'"), start);
01390     else 
01391       /* xgettext:c-format */
01392       sprintf (errbuf, _("bad instruction `%.50s'"), start);
01393 #endif
01394       
01395     *errmsg = errbuf;
01396     return NULL;
01397   }
01398 }