Back to index

cell-binutils  2.17cvs20070401
iq2000-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 "iq2000-desc.h"
00035 #include "iq2000-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 #include "safe-ctype.h"
00054 
00055 static const char * MISSING_CLOSING_PARENTHESIS = N_("missing `)'");
00056 
00057 /* Special check to ensure that instruction exists for given machine.  */
00058 
00059 int
00060 iq2000_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
00061 {
00062   int machs = cd->machs;
00063 
00064   return (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH) & machs) != 0;
00065 }
00066 
00067 static int
00068 iq2000_cgen_isa_register (const char **strp)
00069 {
00070   int len;
00071   int ch1, ch2;
00072 
00073   if (**strp == 'r' || **strp == 'R') 
00074     {
00075       len = strlen (*strp);
00076       if (len == 2) 
00077         {
00078           ch1 = (*strp)[1];
00079           if ('0' <= ch1 && ch1 <= '9')
00080             return 1;
00081         } 
00082       else if (len == 3) 
00083         {
00084          ch1 = (*strp)[1];
00085           ch2 = (*strp)[2];
00086           if (('1' <= ch1 && ch1 <= '2') && ('0' <= ch2 && ch2 <= '9'))
00087             return 1;
00088           if ('3' == ch1 && (ch2 == '0' || ch2 == '1'))
00089             return 1;
00090         }
00091     }
00092   if (**strp == '%'
00093       && TOLOWER ((*strp)[1]) != 'l'
00094       && TOLOWER ((*strp)[1]) != 'h')
00095     return 1;
00096   return 0;
00097 }
00098 
00099 /* Handle negated literal.  */
00100 
00101 static const char *
00102 parse_mimm (CGEN_CPU_DESC cd,
00103            const char **strp,
00104            int opindex,
00105            unsigned long *valuep)
00106 {
00107   const char *errmsg;
00108 
00109   /* Verify this isn't a register.  */
00110   if (iq2000_cgen_isa_register (strp))
00111     errmsg = _("immediate value cannot be register");
00112   else
00113     {
00114       long value;
00115       
00116       errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
00117       if (errmsg == NULL)
00118        {
00119          long x = (-value) & 0xFFFF0000;
00120 
00121          if (x != 0 && x != (long) 0xFFFF0000)
00122            errmsg = _("immediate value out of range");
00123          else
00124            *valuep = (-value & 0xFFFF);
00125        }
00126     }
00127   return errmsg;
00128 }
00129 
00130 /* Handle signed/unsigned literal.  */
00131 
00132 static const char *
00133 parse_imm (CGEN_CPU_DESC cd,
00134           const char **strp,
00135           int opindex,
00136           unsigned long *valuep)
00137 {
00138   const char *errmsg;
00139 
00140   if (iq2000_cgen_isa_register (strp))
00141     errmsg = _("immediate value cannot be register");
00142   else
00143     {
00144       long value;
00145 
00146       errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
00147       if (errmsg == NULL)
00148        {
00149          long x = value & 0xFFFF0000;
00150 
00151          if (x != 0 && x != (long) 0xFFFF0000)
00152            errmsg = _("immediate value out of range");
00153          else
00154            *valuep = (value & 0xFFFF);
00155        }
00156     }
00157   return errmsg;
00158 }
00159 
00160 /* Handle iq10 21-bit jmp offset.  */
00161 
00162 static const char *
00163 parse_jtargq10 (CGEN_CPU_DESC cd,
00164               const char **strp,
00165               int opindex,
00166               int reloc ATTRIBUTE_UNUSED,
00167               enum cgen_parse_operand_result *type_addr ATTRIBUTE_UNUSED,
00168               bfd_vma *valuep)
00169 {
00170   const char *errmsg;
00171   bfd_vma value;
00172   enum cgen_parse_operand_result result_type = CGEN_PARSE_OPERAND_RESULT_NUMBER;
00173 
00174   errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IQ2000_OFFSET_21,
00175                             & result_type, & value);
00176   if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
00177     {
00178       /* Check value is within 23-bits
00179         (remembering that 2-bit shift right will occur).  */
00180       if (value > 0x7fffff)
00181         return _("21-bit offset out of range");
00182     }
00183   *valuep = (value & 0x7FFFFF);
00184   return errmsg;
00185 }
00186 
00187 /* Handle high().  */
00188 
00189 static const char *
00190 parse_hi16 (CGEN_CPU_DESC cd,
00191            const char **strp,
00192            int opindex,
00193            unsigned long *valuep)
00194 {
00195   if (strncasecmp (*strp, "%hi(", 4) == 0)
00196     {
00197       enum cgen_parse_operand_result result_type;
00198       bfd_vma value;
00199       const char *errmsg;
00200 
00201       *strp += 4;
00202       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16,
00203                                & result_type, & value);
00204       if (**strp != ')')
00205        return MISSING_CLOSING_PARENTHESIS;
00206 
00207       ++*strp;
00208       if (errmsg == NULL
00209          && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
00210        {
00211          /* If value has top-bit of %lo on, then it will
00212             sign-propagate and so we compensate by adding
00213             1 to the resultant %hi value.  */
00214          if (value & 0x8000)
00215            value += 0x10000;
00216          value >>= 16;
00217          value &= 0xffff;
00218        }
00219       *valuep = value;
00220 
00221       return errmsg;
00222     }
00223 
00224   /* We add %uhi in case a user just wants the high 16-bits or is using
00225      an insn like ori for %lo which does not sign-propagate.  */
00226   if (strncasecmp (*strp, "%uhi(", 5) == 0)
00227     {
00228       enum cgen_parse_operand_result result_type;
00229       bfd_vma value;
00230       const char *errmsg;
00231 
00232       *strp += 5;
00233       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IQ2000_UHI16,
00234                                & result_type, & value);
00235       if (**strp != ')')
00236        return MISSING_CLOSING_PARENTHESIS;
00237 
00238       ++*strp;
00239       if (errmsg == NULL
00240          && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
00241        value >>= 16;
00242 
00243       value &= 0xffff;
00244       *valuep = value;
00245 
00246       return errmsg;
00247     }
00248 
00249   return parse_imm (cd, strp, opindex, valuep);
00250 }
00251 
00252 /* Handle %lo in a signed context.
00253    The signedness of the value doesn't matter to %lo(), but this also
00254    handles the case where %lo() isn't present.  */
00255 
00256 static const char *
00257 parse_lo16 (CGEN_CPU_DESC cd,
00258            const char **strp,
00259            int opindex,
00260            unsigned long *valuep)
00261 {
00262   if (strncasecmp (*strp, "%lo(", 4) == 0)
00263     {
00264       const char *errmsg;
00265       enum cgen_parse_operand_result result_type;
00266       bfd_vma value;
00267 
00268       *strp += 4;
00269       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
00270                                & result_type, & value);
00271       if (**strp != ')')
00272        return MISSING_CLOSING_PARENTHESIS;
00273       ++*strp;
00274       if (errmsg == NULL
00275          && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
00276        value &= 0xffff;
00277       *valuep = value;
00278       return errmsg;
00279     }
00280 
00281   return parse_imm (cd, strp, opindex, valuep);
00282 }
00283 
00284 /* Handle %lo in a negated signed context.
00285    The signedness of the value doesn't matter to %lo(), but this also
00286    handles the case where %lo() isn't present.  */
00287 
00288 static const char *
00289 parse_mlo16 (CGEN_CPU_DESC cd,
00290             const char **strp,
00291             int opindex,
00292             unsigned long *valuep)
00293 {
00294   if (strncasecmp (*strp, "%lo(", 4) == 0)
00295     {
00296       const char *errmsg;
00297       enum cgen_parse_operand_result result_type;
00298       bfd_vma value;
00299 
00300       *strp += 4;
00301       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
00302                                & result_type, & value);
00303       if (**strp != ')')
00304        return MISSING_CLOSING_PARENTHESIS;
00305       ++*strp;
00306       if (errmsg == NULL
00307          && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
00308        value = (-value) & 0xffff;
00309       *valuep = value;
00310       return errmsg;
00311     }
00312 
00313   return parse_mimm (cd, strp, opindex, valuep);
00314 }
00315 
00316 /* -- */
00317 
00318 const char * iq2000_cgen_parse_operand
00319   (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
00320 
00321 /* Main entry point for operand parsing.
00322 
00323    This function is basically just a big switch statement.  Earlier versions
00324    used tables to look up the function to use, but
00325    - if the table contains both assembler and disassembler functions then
00326      the disassembler contains much of the assembler and vice-versa,
00327    - there's a lot of inlining possibilities as things grow,
00328    - using a switch statement avoids the function call overhead.
00329 
00330    This function could be moved into `parse_insn_normal', but keeping it
00331    separate makes clear the interface between `parse_insn_normal' and each of
00332    the handlers.  */
00333 
00334 const char *
00335 iq2000_cgen_parse_operand (CGEN_CPU_DESC cd,
00336                         int opindex,
00337                         const char ** strp,
00338                         CGEN_FIELDS * fields)
00339 {
00340   const char * errmsg = NULL;
00341   /* Used by scalar operands that still need to be parsed.  */
00342   long junk ATTRIBUTE_UNUSED;
00343 
00344   switch (opindex)
00345     {
00346     case IQ2000_OPERAND__INDEX :
00347       errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND__INDEX, (unsigned long *) (& fields->f_index));
00348       break;
00349     case IQ2000_OPERAND_BASE :
00350       errmsg = cgen_parse_keyword (cd, strp, & iq2000_cgen_opval_gr_names, & fields->f_rs);
00351       break;
00352     case IQ2000_OPERAND_BASEOFF :
00353       {
00354         bfd_vma value = 0;
00355         errmsg = cgen_parse_address (cd, strp, IQ2000_OPERAND_BASEOFF, 0, NULL,  & value);
00356         fields->f_imm = value;
00357       }
00358       break;
00359     case IQ2000_OPERAND_BITNUM :
00360       errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_BITNUM, (unsigned long *) (& fields->f_rt));
00361       break;
00362     case IQ2000_OPERAND_BYTECOUNT :
00363       errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_BYTECOUNT, (unsigned long *) (& fields->f_bytecount));
00364       break;
00365     case IQ2000_OPERAND_CAM_Y :
00366       errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_CAM_Y, (unsigned long *) (& fields->f_cam_y));
00367       break;
00368     case IQ2000_OPERAND_CAM_Z :
00369       errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_CAM_Z, (unsigned long *) (& fields->f_cam_z));
00370       break;
00371     case IQ2000_OPERAND_CM_3FUNC :
00372       errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_CM_3FUNC, (unsigned long *) (& fields->f_cm_3func));
00373       break;
00374     case IQ2000_OPERAND_CM_3Z :
00375       errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_CM_3Z, (unsigned long *) (& fields->f_cm_3z));
00376       break;
00377     case IQ2000_OPERAND_CM_4FUNC :
00378       errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_CM_4FUNC, (unsigned long *) (& fields->f_cm_4func));
00379       break;
00380     case IQ2000_OPERAND_CM_4Z :
00381       errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_CM_4Z, (unsigned long *) (& fields->f_cm_4z));
00382       break;
00383     case IQ2000_OPERAND_COUNT :
00384       errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_COUNT, (unsigned long *) (& fields->f_count));
00385       break;
00386     case IQ2000_OPERAND_EXECODE :
00387       errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_EXECODE, (unsigned long *) (& fields->f_excode));
00388       break;
00389     case IQ2000_OPERAND_HI16 :
00390       errmsg = parse_hi16 (cd, strp, IQ2000_OPERAND_HI16, (unsigned long *) (& fields->f_imm));
00391       break;
00392     case IQ2000_OPERAND_IMM :
00393       errmsg = parse_imm (cd, strp, IQ2000_OPERAND_IMM, (unsigned long *) (& fields->f_imm));
00394       break;
00395     case IQ2000_OPERAND_JMPTARG :
00396       {
00397         bfd_vma value = 0;
00398         errmsg = cgen_parse_address (cd, strp, IQ2000_OPERAND_JMPTARG, 0, NULL,  & value);
00399         fields->f_jtarg = value;
00400       }
00401       break;
00402     case IQ2000_OPERAND_JMPTARGQ10 :
00403       {
00404         bfd_vma value = 0;
00405         errmsg = parse_jtargq10 (cd, strp, IQ2000_OPERAND_JMPTARGQ10, 0, NULL,  & value);
00406         fields->f_jtargq10 = value;
00407       }
00408       break;
00409     case IQ2000_OPERAND_LO16 :
00410       errmsg = parse_lo16 (cd, strp, IQ2000_OPERAND_LO16, (unsigned long *) (& fields->f_imm));
00411       break;
00412     case IQ2000_OPERAND_MASK :
00413       errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_MASK, (unsigned long *) (& fields->f_mask));
00414       break;
00415     case IQ2000_OPERAND_MASKL :
00416       errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_MASKL, (unsigned long *) (& fields->f_maskl));
00417       break;
00418     case IQ2000_OPERAND_MASKQ10 :
00419       errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_MASKQ10, (unsigned long *) (& fields->f_maskq10));
00420       break;
00421     case IQ2000_OPERAND_MASKR :
00422       errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_MASKR, (unsigned long *) (& fields->f_rs));
00423       break;
00424     case IQ2000_OPERAND_MLO16 :
00425       errmsg = parse_mlo16 (cd, strp, IQ2000_OPERAND_MLO16, (unsigned long *) (& fields->f_imm));
00426       break;
00427     case IQ2000_OPERAND_OFFSET :
00428       {
00429         bfd_vma value = 0;
00430         errmsg = cgen_parse_address (cd, strp, IQ2000_OPERAND_OFFSET, 0, NULL,  & value);
00431         fields->f_offset = value;
00432       }
00433       break;
00434     case IQ2000_OPERAND_RD :
00435       errmsg = cgen_parse_keyword (cd, strp, & iq2000_cgen_opval_gr_names, & fields->f_rd);
00436       break;
00437     case IQ2000_OPERAND_RD_RS :
00438       errmsg = cgen_parse_keyword (cd, strp, & iq2000_cgen_opval_gr_names, & fields->f_rd_rs);
00439       break;
00440     case IQ2000_OPERAND_RD_RT :
00441       errmsg = cgen_parse_keyword (cd, strp, & iq2000_cgen_opval_gr_names, & fields->f_rd_rt);
00442       break;
00443     case IQ2000_OPERAND_RS :
00444       errmsg = cgen_parse_keyword (cd, strp, & iq2000_cgen_opval_gr_names, & fields->f_rs);
00445       break;
00446     case IQ2000_OPERAND_RT :
00447       errmsg = cgen_parse_keyword (cd, strp, & iq2000_cgen_opval_gr_names, & fields->f_rt);
00448       break;
00449     case IQ2000_OPERAND_RT_RS :
00450       errmsg = cgen_parse_keyword (cd, strp, & iq2000_cgen_opval_gr_names, & fields->f_rt_rs);
00451       break;
00452     case IQ2000_OPERAND_SHAMT :
00453       errmsg = cgen_parse_unsigned_integer (cd, strp, IQ2000_OPERAND_SHAMT, (unsigned long *) (& fields->f_shamt));
00454       break;
00455 
00456     default :
00457       /* xgettext:c-format */
00458       fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
00459       abort ();
00460   }
00461 
00462   return errmsg;
00463 }
00464 
00465 cgen_parse_fn * const iq2000_cgen_parse_handlers[] = 
00466 {
00467   parse_insn_normal,
00468 };
00469 
00470 void
00471 iq2000_cgen_init_asm (CGEN_CPU_DESC cd)
00472 {
00473   iq2000_cgen_init_opcode_table (cd);
00474   iq2000_cgen_init_ibld_table (cd);
00475   cd->parse_handlers = & iq2000_cgen_parse_handlers[0];
00476   cd->parse_operand = iq2000_cgen_parse_operand;
00477 #ifdef CGEN_ASM_INIT_HOOK
00478 CGEN_ASM_INIT_HOOK
00479 #endif
00480 }
00481 
00482 
00483 
00484 /* Regex construction routine.
00485 
00486    This translates an opcode syntax string into a regex string,
00487    by replacing any non-character syntax element (such as an
00488    opcode) with the pattern '.*'
00489 
00490    It then compiles the regex and stores it in the opcode, for
00491    later use by iq2000_cgen_assemble_insn
00492 
00493    Returns NULL for success, an error message for failure.  */
00494 
00495 char * 
00496 iq2000_cgen_build_insn_regex (CGEN_INSN *insn)
00497 {  
00498   CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
00499   const char *mnem = CGEN_INSN_MNEMONIC (insn);
00500   char rxbuf[CGEN_MAX_RX_ELEMENTS];
00501   char *rx = rxbuf;
00502   const CGEN_SYNTAX_CHAR_TYPE *syn;
00503   int reg_err;
00504 
00505   syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
00506 
00507   /* Mnemonics come first in the syntax string.  */
00508   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
00509     return _("missing mnemonic in syntax string");
00510   ++syn;
00511 
00512   /* Generate a case sensitive regular expression that emulates case
00513      insensitive matching in the "C" locale.  We cannot generate a case
00514      insensitive regular expression because in Turkish locales, 'i' and 'I'
00515      are not equal modulo case conversion.  */
00516 
00517   /* Copy the literal mnemonic out of the insn.  */
00518   for (; *mnem; mnem++)
00519     {
00520       char c = *mnem;
00521 
00522       if (ISALPHA (c))
00523        {
00524          *rx++ = '[';
00525          *rx++ = TOLOWER (c);
00526          *rx++ = TOUPPER (c);
00527          *rx++ = ']';
00528        }
00529       else
00530        *rx++ = c;
00531     }
00532 
00533   /* Copy any remaining literals from the syntax string into the rx.  */
00534   for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
00535     {
00536       if (CGEN_SYNTAX_CHAR_P (* syn)) 
00537        {
00538          char c = CGEN_SYNTAX_CHAR (* syn);
00539 
00540          switch (c) 
00541            {
00542              /* Escape any regex metacharacters in the syntax.  */
00543            case '.': case '[': case '\\': 
00544            case '*': case '^': case '$': 
00545 
00546 #ifdef CGEN_ESCAPE_EXTENDED_REGEX
00547            case '?': case '{': case '}': 
00548            case '(': case ')': case '*':
00549            case '|': case '+': case ']':
00550 #endif
00551              *rx++ = '\\';
00552              *rx++ = c;
00553              break;
00554 
00555            default:
00556              if (ISALPHA (c))
00557               {
00558                 *rx++ = '[';
00559                 *rx++ = TOLOWER (c);
00560                 *rx++ = TOUPPER (c);
00561                 *rx++ = ']';
00562               }
00563              else
00564               *rx++ = c;
00565              break;
00566            }
00567        }
00568       else
00569        {
00570          /* Replace non-syntax fields with globs.  */
00571          *rx++ = '.';
00572          *rx++ = '*';
00573        }
00574     }
00575 
00576   /* Trailing whitespace ok.  */
00577   * rx++ = '['; 
00578   * rx++ = ' '; 
00579   * rx++ = '\t'; 
00580   * rx++ = ']'; 
00581   * rx++ = '*'; 
00582 
00583   /* But anchor it after that.  */
00584   * rx++ = '$'; 
00585   * rx = '\0';
00586 
00587   CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
00588   reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
00589 
00590   if (reg_err == 0) 
00591     return NULL;
00592   else
00593     {
00594       static char msg[80];
00595 
00596       regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
00597       regfree ((regex_t *) CGEN_INSN_RX (insn));
00598       free (CGEN_INSN_RX (insn));
00599       (CGEN_INSN_RX (insn)) = NULL;
00600       return msg;
00601     }
00602 }
00603 
00604 
00605 /* Default insn parser.
00606 
00607    The syntax string is scanned and operands are parsed and stored in FIELDS.
00608    Relocs are queued as we go via other callbacks.
00609 
00610    ??? Note that this is currently an all-or-nothing parser.  If we fail to
00611    parse the instruction, we return 0 and the caller will start over from
00612    the beginning.  Backtracking will be necessary in parsing subexpressions,
00613    but that can be handled there.  Not handling backtracking here may get
00614    expensive in the case of the m68k.  Deal with later.
00615 
00616    Returns NULL for success, an error message for failure.  */
00617 
00618 static const char *
00619 parse_insn_normal (CGEN_CPU_DESC cd,
00620                  const CGEN_INSN *insn,
00621                  const char **strp,
00622                  CGEN_FIELDS *fields)
00623 {
00624   /* ??? Runtime added insns not handled yet.  */
00625   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
00626   const char *str = *strp;
00627   const char *errmsg;
00628   const char *p;
00629   const CGEN_SYNTAX_CHAR_TYPE * syn;
00630 #ifdef CGEN_MNEMONIC_OPERANDS
00631   /* FIXME: wip */
00632   int past_opcode_p;
00633 #endif
00634 
00635   /* For now we assume the mnemonic is first (there are no leading operands).
00636      We can parse it without needing to set up operand parsing.
00637      GAS's input scrubber will ensure mnemonics are lowercase, but we may
00638      not be called from GAS.  */
00639   p = CGEN_INSN_MNEMONIC (insn);
00640   while (*p && TOLOWER (*p) == TOLOWER (*str))
00641     ++p, ++str;
00642 
00643   if (* p)
00644     return _("unrecognized instruction");
00645 
00646 #ifndef CGEN_MNEMONIC_OPERANDS
00647   if (* str && ! ISSPACE (* str))
00648     return _("unrecognized instruction");
00649 #endif
00650 
00651   CGEN_INIT_PARSE (cd);
00652   cgen_init_parse_operand (cd);
00653 #ifdef CGEN_MNEMONIC_OPERANDS
00654   past_opcode_p = 0;
00655 #endif
00656 
00657   /* We don't check for (*str != '\0') here because we want to parse
00658      any trailing fake arguments in the syntax string.  */
00659   syn = CGEN_SYNTAX_STRING (syntax);
00660 
00661   /* Mnemonics come first for now, ensure valid string.  */
00662   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
00663     abort ();
00664 
00665   ++syn;
00666 
00667   while (* syn != 0)
00668     {
00669       /* Non operand chars must match exactly.  */
00670       if (CGEN_SYNTAX_CHAR_P (* syn))
00671        {
00672          /* FIXME: While we allow for non-GAS callers above, we assume the
00673             first char after the mnemonic part is a space.  */
00674          /* FIXME: We also take inappropriate advantage of the fact that
00675             GAS's input scrubber will remove extraneous blanks.  */
00676          if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
00677            {
00678 #ifdef CGEN_MNEMONIC_OPERANDS
00679              if (CGEN_SYNTAX_CHAR(* syn) == ' ')
00680               past_opcode_p = 1;
00681 #endif
00682              ++ syn;
00683              ++ str;
00684            }
00685          else if (*str)
00686            {
00687              /* Syntax char didn't match.  Can't be this insn.  */
00688              static char msg [80];
00689 
00690              /* xgettext:c-format */
00691              sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
00692                      CGEN_SYNTAX_CHAR(*syn), *str);
00693              return msg;
00694            }
00695          else
00696            {
00697              /* Ran out of input.  */
00698              static char msg [80];
00699 
00700              /* xgettext:c-format */
00701              sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
00702                      CGEN_SYNTAX_CHAR(*syn));
00703              return msg;
00704            }
00705          continue;
00706        }
00707 
00708       /* We have an operand of some sort.  */
00709       errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn),
00710                                      &str, fields);
00711       if (errmsg)
00712        return errmsg;
00713 
00714       /* Done with this operand, continue with next one.  */
00715       ++ syn;
00716     }
00717 
00718   /* If we're at the end of the syntax string, we're done.  */
00719   if (* syn == 0)
00720     {
00721       /* FIXME: For the moment we assume a valid `str' can only contain
00722         blanks now.  IE: We needn't try again with a longer version of
00723         the insn and it is assumed that longer versions of insns appear
00724         before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
00725       while (ISSPACE (* str))
00726        ++ str;
00727 
00728       if (* str != '\0')
00729        return _("junk at end of line"); /* FIXME: would like to include `str' */
00730 
00731       return NULL;
00732     }
00733 
00734   /* We couldn't parse it.  */
00735   return _("unrecognized instruction");
00736 }
00737 
00738 /* Main entry point.
00739    This routine is called for each instruction to be assembled.
00740    STR points to the insn to be assembled.
00741    We assume all necessary tables have been initialized.
00742    The assembled instruction, less any fixups, is stored in BUF.
00743    Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
00744    still needs to be converted to target byte order, otherwise BUF is an array
00745    of bytes in target byte order.
00746    The result is a pointer to the insn's entry in the opcode table,
00747    or NULL if an error occured (an error message will have already been
00748    printed).
00749 
00750    Note that when processing (non-alias) macro-insns,
00751    this function recurses.
00752 
00753    ??? It's possible to make this cpu-independent.
00754    One would have to deal with a few minor things.
00755    At this point in time doing so would be more of a curiosity than useful
00756    [for example this file isn't _that_ big], but keeping the possibility in
00757    mind helps keep the design clean.  */
00758 
00759 const CGEN_INSN *
00760 iq2000_cgen_assemble_insn (CGEN_CPU_DESC cd,
00761                         const char *str,
00762                         CGEN_FIELDS *fields,
00763                         CGEN_INSN_BYTES_PTR buf,
00764                         char **errmsg)
00765 {
00766   const char *start;
00767   CGEN_INSN_LIST *ilist;
00768   const char *parse_errmsg = NULL;
00769   const char *insert_errmsg = NULL;
00770   int recognized_mnemonic = 0;
00771 
00772   /* Skip leading white space.  */
00773   while (ISSPACE (* str))
00774     ++ str;
00775 
00776   /* The instructions are stored in hashed lists.
00777      Get the first in the list.  */
00778   ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
00779 
00780   /* Keep looking until we find a match.  */
00781   start = str;
00782   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
00783     {
00784       const CGEN_INSN *insn = ilist->insn;
00785       recognized_mnemonic = 1;
00786 
00787 #ifdef CGEN_VALIDATE_INSN_SUPPORTED 
00788       /* Not usually needed as unsupported opcodes
00789         shouldn't be in the hash lists.  */
00790       /* Is this insn supported by the selected cpu?  */
00791       if (! iq2000_cgen_insn_supported (cd, insn))
00792        continue;
00793 #endif
00794       /* If the RELAXED attribute is set, this is an insn that shouldn't be
00795         chosen immediately.  Instead, it is used during assembler/linker
00796         relaxation if possible.  */
00797       if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
00798        continue;
00799 
00800       str = start;
00801 
00802       /* Skip this insn if str doesn't look right lexically.  */
00803       if (CGEN_INSN_RX (insn) != NULL &&
00804          regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
00805        continue;
00806 
00807       /* Allow parse/insert handlers to obtain length of insn.  */
00808       CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
00809 
00810       parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
00811       if (parse_errmsg != NULL)
00812        continue;
00813 
00814       /* ??? 0 is passed for `pc'.  */
00815       insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
00816                                            (bfd_vma) 0);
00817       if (insert_errmsg != NULL)
00818         continue;
00819 
00820       /* It is up to the caller to actually output the insn and any
00821          queued relocs.  */
00822       return insn;
00823     }
00824 
00825   {
00826     static char errbuf[150];
00827 #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
00828     const char *tmp_errmsg;
00829 
00830     /* If requesting verbose error messages, use insert_errmsg.
00831        Failing that, use parse_errmsg.  */
00832     tmp_errmsg = (insert_errmsg ? insert_errmsg :
00833                 parse_errmsg ? parse_errmsg :
00834                 recognized_mnemonic ?
00835                 _("unrecognized form of instruction") :
00836                 _("unrecognized instruction"));
00837 
00838     if (strlen (start) > 50)
00839       /* xgettext:c-format */
00840       sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
00841     else 
00842       /* xgettext:c-format */
00843       sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
00844 #else
00845     if (strlen (start) > 50)
00846       /* xgettext:c-format */
00847       sprintf (errbuf, _("bad instruction `%.50s...'"), start);
00848     else 
00849       /* xgettext:c-format */
00850       sprintf (errbuf, _("bad instruction `%.50s'"), start);
00851 #endif
00852       
00853     *errmsg = errbuf;
00854     return NULL;
00855   }
00856 }