Back to index

cell-binutils  2.17cvs20070401
mt-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 "mt-desc.h"
00035 #include "mt-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 /* Range checking for signed numbers.  Returns 0 if acceptable
00053    and 1 if the value is out of bounds for a signed quantity.  */
00054 
00055 static int 
00056 signed_out_of_bounds (long val)
00057 {
00058   if ((val < -32768) || (val > 32767))
00059     return 1;
00060   return 0;
00061 }
00062 
00063 static const char *
00064 parse_loopsize (CGEN_CPU_DESC cd,
00065               const char **strp,
00066               int opindex,
00067               void *arg)
00068 {
00069   signed long * valuep = (signed long *) arg;
00070   const char *errmsg;
00071   bfd_reloc_code_real_type code = BFD_RELOC_NONE;
00072   enum cgen_parse_operand_result result_type;
00073   bfd_vma value;
00074 
00075   /* Is it a control transfer instructions?  */ 
00076   if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_LOOPSIZE)
00077     {
00078       code = BFD_RELOC_MT_PCINSN8;
00079       errmsg = cgen_parse_address (cd, strp, opindex, code,
00080                                    & result_type, & value);
00081       *valuep = value;
00082       return errmsg;
00083     }
00084 
00085   abort ();
00086 }
00087 
00088 static const char *
00089 parse_imm16 (CGEN_CPU_DESC cd,
00090             const char **strp,
00091             int opindex,
00092             void *arg)
00093 {
00094   signed long * valuep = (signed long *) arg;
00095   const char *errmsg;
00096   enum cgen_parse_operand_result result_type;
00097   bfd_reloc_code_real_type code = BFD_RELOC_NONE;
00098   bfd_vma value;
00099 
00100   /* Is it a control transfer instructions?  */ 
00101   if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_IMM16O)
00102     {
00103       code = BFD_RELOC_16_PCREL;
00104       errmsg = cgen_parse_address (cd, strp, opindex, code,
00105                                    & result_type, & value);
00106       if (errmsg == NULL)
00107        {
00108          if (signed_out_of_bounds (value))
00109            errmsg = _("Operand out of range. Must be between -32768 and 32767.");
00110        }
00111       *valuep = value;
00112       return errmsg;
00113     }
00114 
00115   /* If it's not a control transfer instruction, then
00116      we have to check for %OP relocating operators.  */
00117   if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_IMM16L)
00118     ;
00119   else if (strncmp (*strp, "%hi16", 5) == 0)
00120     {
00121       *strp += 5;
00122       code = BFD_RELOC_HI16;
00123     }
00124   else if (strncmp (*strp, "%lo16", 5) == 0)
00125     {
00126       *strp += 5;
00127       code = BFD_RELOC_LO16;
00128     }
00129 
00130   /* If we found a %OP relocating operator, then parse it as an address.
00131      If not, we need to parse it as an integer, either signed or unsigned
00132      depending on which operand type we have.  */
00133   if (code != BFD_RELOC_NONE)
00134     {
00135        /* %OP relocating operator found.  */
00136        errmsg = cgen_parse_address (cd, strp, opindex, code,
00137                                    & result_type, & value);
00138        if (errmsg == NULL)
00139         {
00140            switch (result_type)
00141             {
00142             case (CGEN_PARSE_OPERAND_RESULT_NUMBER):
00143               if (code == BFD_RELOC_HI16)
00144                value = (value >> 16) & 0xFFFF;
00145               else if (code == BFD_RELOC_LO16)
00146                value = value  & 0xFFFF;
00147               else 
00148                errmsg = _("Biiiig Trouble in parse_imm16!");
00149               break;
00150 
00151             case (CGEN_PARSE_OPERAND_RESULT_QUEUED):
00152               /* No special processing for this case.  */
00153               break;
00154 
00155             default:
00156               errmsg = _("%operator operand is not a symbol");
00157               break;
00158              }
00159         }
00160        *valuep = value;
00161     }
00162   else
00163     {
00164       /* Parse hex values like 0xffff as unsigned, and sign extend
00165         them manually.  */
00166       int parse_signed = (opindex == (CGEN_OPERAND_TYPE)MT_OPERAND_IMM16);
00167 
00168       if ((*strp)[0] == '0'
00169          && ((*strp)[1] == 'x' || (*strp)[1] == 'X'))
00170        parse_signed = 0;
00171 
00172       /* No relocating operator.  Parse as an number.  */
00173       if (parse_signed)
00174        {
00175           /* Parse as as signed integer.  */
00176  
00177           errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep);
00178 
00179           if (errmsg == NULL) 
00180            {
00181 #if 0
00182              /* Manual range checking is needed for the signed case.  */
00183              if (*valuep & 0x8000)
00184                 value = 0xffff0000 | *valuep;
00185              else 
00186                 value = *valuep;
00187 
00188              if (signed_out_of_bounds (value))
00189                errmsg = _("Operand out of range. Must be between -32768 and 32767.");
00190              /* Truncate to 16 bits. This is necessary
00191                because cgen will have sign extended *valuep.  */
00192              *valuep &= 0xFFFF; 
00193 #endif
00194            }
00195        }
00196       else  
00197        {
00198           /* MT_OPERAND_IMM16Z.  Parse as an unsigned integer.  */
00199           errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, (unsigned long *) valuep);
00200 
00201          if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_IMM16
00202              && *valuep >= 0x8000
00203              && *valuep <= 0xffff)
00204            *valuep -= 0x10000;
00205        }
00206     }
00207 
00208   return errmsg;
00209 }
00210 
00211 
00212 static const char *
00213 parse_dup (CGEN_CPU_DESC cd,
00214           const char **strp,
00215           int opindex,
00216           unsigned long *valuep)
00217 {
00218   const char *errmsg = NULL;
00219 
00220   if (strncmp (*strp, "dup", 3) == 0 || strncmp (*strp, "DUP", 3) == 0)
00221     {
00222       *strp += 3;
00223       *valuep = 1;
00224     }
00225   else if (strncmp (*strp, "xx", 2) == 0 || strncmp (*strp, "XX", 2) == 0)
00226     {
00227       *strp += 2;
00228       *valuep = 0;
00229     }
00230   else
00231     errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
00232 
00233   return errmsg;
00234 }
00235 
00236 
00237 static const char *
00238 parse_ball (CGEN_CPU_DESC cd,
00239            const char **strp,
00240            int opindex,
00241            unsigned long *valuep)
00242 {
00243   const char *errmsg = NULL;
00244 
00245   if (strncmp (*strp, "all", 3) == 0 || strncmp (*strp, "ALL", 3) == 0)
00246     {
00247       *strp += 3;
00248       *valuep = 1;
00249     }
00250   else if (strncmp (*strp, "one", 3) == 0 || strncmp (*strp, "ONE", 3) == 0)
00251     {
00252       *strp += 3;
00253       *valuep = 0;
00254     }
00255   else
00256     errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
00257 
00258   return errmsg;
00259 }
00260 
00261 static const char *
00262 parse_xmode (CGEN_CPU_DESC cd,
00263             const char **strp,
00264             int opindex,
00265             unsigned long *valuep)
00266 {
00267   const char *errmsg = NULL;
00268 
00269   if (strncmp (*strp, "pm", 2) == 0 || strncmp (*strp, "PM", 2) == 0)
00270     {
00271       *strp += 2;
00272       *valuep = 1;
00273     }
00274   else if (strncmp (*strp, "xm", 2) == 0 || strncmp (*strp, "XM", 2) == 0)
00275     {
00276       *strp += 2;
00277       *valuep = 0;
00278     }
00279   else
00280     errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
00281 
00282   return errmsg;
00283 }
00284 
00285 static const char *
00286 parse_rc (CGEN_CPU_DESC cd,
00287          const char **strp,
00288          int opindex,
00289          unsigned long *valuep)
00290 {
00291   const char *errmsg = NULL;
00292 
00293   if (strncmp (*strp, "r", 1) == 0 || strncmp (*strp, "R", 1) == 0)
00294     {
00295       *strp += 1;
00296       *valuep = 1;
00297     }
00298   else if (strncmp (*strp, "c", 1) == 0 || strncmp (*strp, "C", 1) == 0)
00299     {
00300       *strp += 1;
00301       *valuep = 0;
00302     }
00303   else
00304     errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
00305 
00306   return errmsg;
00307 }
00308 
00309 static const char *
00310 parse_cbrb (CGEN_CPU_DESC cd,
00311            const char **strp,
00312            int opindex,
00313            unsigned long *valuep)
00314 {
00315   const char *errmsg = NULL;
00316 
00317   if (strncmp (*strp, "rb", 2) == 0 || strncmp (*strp, "RB", 2) == 0)
00318     {
00319       *strp += 2;
00320       *valuep = 1;
00321     }
00322   else if (strncmp (*strp, "cb", 2) == 0 || strncmp (*strp, "CB", 2) == 0)
00323     {
00324       *strp += 2;
00325       *valuep = 0;
00326     }
00327   else
00328     errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
00329 
00330   return errmsg;
00331 }
00332 
00333 static const char *
00334 parse_rbbc (CGEN_CPU_DESC cd,
00335            const char **strp,
00336            int opindex,
00337            unsigned long *valuep)
00338 {
00339   const char *errmsg = NULL;
00340 
00341   if (strncmp (*strp, "rt", 2) == 0 || strncmp (*strp, "RT", 2) == 0)
00342     {
00343       *strp += 2;
00344       *valuep = 0;
00345     }
00346   else if (strncmp (*strp, "br1", 3) == 0 || strncmp (*strp, "BR1", 3) == 0)
00347     {
00348       *strp += 3;
00349       *valuep = 1;
00350     }
00351   else if (strncmp (*strp, "br2", 3) == 0 || strncmp (*strp, "BR2", 3) == 0)
00352     {
00353       *strp += 3;
00354       *valuep = 2;
00355     }
00356   else if (strncmp (*strp, "cs", 2) == 0 || strncmp (*strp, "CS", 2) == 0)
00357     {
00358       *strp += 2;
00359       *valuep = 3;
00360     }
00361   else
00362     errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
00363 
00364   return errmsg;
00365 }
00366 
00367 static const char *
00368 parse_type (CGEN_CPU_DESC cd,
00369            const char **strp,
00370            int opindex,
00371            unsigned long *valuep)
00372 {
00373   const char *errmsg = NULL;
00374 
00375   if (strncmp (*strp, "odd", 3) == 0 || strncmp (*strp, "ODD", 3) == 0)
00376     {
00377       *strp += 3;
00378       *valuep = 0;
00379     }
00380   else if (strncmp (*strp, "even", 4) == 0 || strncmp (*strp, "EVEN", 4) == 0)
00381     {
00382       *strp += 4;
00383       *valuep = 1;
00384     }
00385   else if (strncmp (*strp, "oe", 2) == 0 || strncmp (*strp, "OE", 2) == 0)
00386     {
00387       *strp += 2;
00388       *valuep = 2;
00389     }
00390   else
00391     errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
00392 
00393  if ((errmsg == NULL) && (*valuep == 3))
00394     errmsg = _("invalid operand.  type may have values 0,1,2 only.");
00395 
00396   return errmsg;
00397 }
00398 
00399 /* -- dis.c */
00400 
00401 const char * mt_cgen_parse_operand
00402   (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
00403 
00404 /* Main entry point for operand parsing.
00405 
00406    This function is basically just a big switch statement.  Earlier versions
00407    used tables to look up the function to use, but
00408    - if the table contains both assembler and disassembler functions then
00409      the disassembler contains much of the assembler and vice-versa,
00410    - there's a lot of inlining possibilities as things grow,
00411    - using a switch statement avoids the function call overhead.
00412 
00413    This function could be moved into `parse_insn_normal', but keeping it
00414    separate makes clear the interface between `parse_insn_normal' and each of
00415    the handlers.  */
00416 
00417 const char *
00418 mt_cgen_parse_operand (CGEN_CPU_DESC cd,
00419                         int opindex,
00420                         const char ** strp,
00421                         CGEN_FIELDS * fields)
00422 {
00423   const char * errmsg = NULL;
00424   /* Used by scalar operands that still need to be parsed.  */
00425   long junk ATTRIBUTE_UNUSED;
00426 
00427   switch (opindex)
00428     {
00429     case MT_OPERAND_A23 :
00430       errmsg = cgen_parse_unsigned_integer (cd, strp, MT_OPERAND_A23, (unsigned long *) (& fields->f_a23));
00431       break;
00432     case MT_OPERAND_BALL :
00433       errmsg = parse_ball (cd, strp, MT_OPERAND_BALL, (unsigned long *) (& fields->f_ball));
00434       break;
00435     case MT_OPERAND_BALL2 :
00436       errmsg = parse_ball (cd, strp, MT_OPERAND_BALL2, (unsigned long *) (& fields->f_ball2));
00437       break;
00438     case MT_OPERAND_BANKADDR :
00439       errmsg = cgen_parse_unsigned_integer (cd, strp, MT_OPERAND_BANKADDR, (unsigned long *) (& fields->f_bankaddr));
00440       break;
00441     case MT_OPERAND_BRC :
00442       errmsg = cgen_parse_unsigned_integer (cd, strp, MT_OPERAND_BRC, (unsigned long *) (& fields->f_brc));
00443       break;
00444     case MT_OPERAND_BRC2 :
00445       errmsg = cgen_parse_unsigned_integer (cd, strp, MT_OPERAND_BRC2, (unsigned long *) (& fields->f_brc2));
00446       break;
00447     case MT_OPERAND_CB1INCR :
00448       errmsg = cgen_parse_signed_integer (cd, strp, MT_OPERAND_CB1INCR, (long *) (& fields->f_cb1incr));
00449       break;
00450     case MT_OPERAND_CB1SEL :
00451       errmsg = cgen_parse_unsigned_integer (cd, strp, MT_OPERAND_CB1SEL, (unsigned long *) (& fields->f_cb1sel));
00452       break;
00453     case MT_OPERAND_CB2INCR :
00454       errmsg = cgen_parse_signed_integer (cd, strp, MT_OPERAND_CB2INCR, (long *) (& fields->f_cb2incr));
00455       break;
00456     case MT_OPERAND_CB2SEL :
00457       errmsg = cgen_parse_unsigned_integer (cd, strp, MT_OPERAND_CB2SEL, (unsigned long *) (& fields->f_cb2sel));
00458       break;
00459     case MT_OPERAND_CBRB :
00460       errmsg = parse_cbrb (cd, strp, MT_OPERAND_CBRB, (unsigned long *) (& fields->f_cbrb));
00461       break;
00462     case MT_OPERAND_CBS :
00463       errmsg = cgen_parse_unsigned_integer (cd, strp, MT_OPERAND_CBS, (unsigned long *) (& fields->f_cbs));
00464       break;
00465     case MT_OPERAND_CBX :
00466       errmsg = cgen_parse_unsigned_integer (cd, strp, MT_OPERAND_CBX, (unsigned long *) (& fields->f_cbx));
00467       break;
00468     case MT_OPERAND_CCB :
00469       errmsg = cgen_parse_unsigned_integer (cd, strp, MT_OPERAND_CCB, (unsigned long *) (& fields->f_ccb));
00470       break;
00471     case MT_OPERAND_CDB :
00472       errmsg = cgen_parse_unsigned_integer (cd, strp, MT_OPERAND_CDB, (unsigned long *) (& fields->f_cdb));
00473       break;
00474     case MT_OPERAND_CELL :
00475       errmsg = cgen_parse_unsigned_integer (cd, strp, MT_OPERAND_CELL, (unsigned long *) (& fields->f_cell));
00476       break;
00477     case MT_OPERAND_COLNUM :
00478       errmsg = cgen_parse_unsigned_integer (cd, strp, MT_OPERAND_COLNUM, (unsigned long *) (& fields->f_colnum));
00479       break;
00480     case MT_OPERAND_CONTNUM :
00481       errmsg = cgen_parse_unsigned_integer (cd, strp, MT_OPERAND_CONTNUM, (unsigned long *) (& fields->f_contnum));
00482       break;
00483     case MT_OPERAND_CR :
00484       errmsg = cgen_parse_unsigned_integer (cd, strp, MT_OPERAND_CR, (unsigned long *) (& fields->f_cr));
00485       break;
00486     case MT_OPERAND_CTXDISP :
00487       errmsg = cgen_parse_unsigned_integer (cd, strp, MT_OPERAND_CTXDISP, (unsigned long *) (& fields->f_ctxdisp));
00488       break;
00489     case MT_OPERAND_DUP :
00490       errmsg = parse_dup (cd, strp, MT_OPERAND_DUP, (unsigned long *) (& fields->f_dup));
00491       break;
00492     case MT_OPERAND_FBDISP :
00493       errmsg = cgen_parse_unsigned_integer (cd, strp, MT_OPERAND_FBDISP, (unsigned long *) (& fields->f_fbdisp));
00494       break;
00495     case MT_OPERAND_FBINCR :
00496       errmsg = cgen_parse_unsigned_integer (cd, strp, MT_OPERAND_FBINCR, (unsigned long *) (& fields->f_fbincr));
00497       break;
00498     case MT_OPERAND_FRDR :
00499       errmsg = cgen_parse_keyword (cd, strp, & mt_cgen_opval_h_spr, & fields->f_dr);
00500       break;
00501     case MT_OPERAND_FRDRRR :
00502       errmsg = cgen_parse_keyword (cd, strp, & mt_cgen_opval_h_spr, & fields->f_drrr);
00503       break;
00504     case MT_OPERAND_FRSR1 :
00505       errmsg = cgen_parse_keyword (cd, strp, & mt_cgen_opval_h_spr, & fields->f_sr1);
00506       break;
00507     case MT_OPERAND_FRSR2 :
00508       errmsg = cgen_parse_keyword (cd, strp, & mt_cgen_opval_h_spr, & fields->f_sr2);
00509       break;
00510     case MT_OPERAND_ID :
00511       errmsg = cgen_parse_unsigned_integer (cd, strp, MT_OPERAND_ID, (unsigned long *) (& fields->f_id));
00512       break;
00513     case MT_OPERAND_IMM16 :
00514       errmsg = parse_imm16 (cd, strp, MT_OPERAND_IMM16, (long *) (& fields->f_imm16s));
00515       break;
00516     case MT_OPERAND_IMM16L :
00517       errmsg = cgen_parse_unsigned_integer (cd, strp, MT_OPERAND_IMM16L, (unsigned long *) (& fields->f_imm16l));
00518       break;
00519     case MT_OPERAND_IMM16O :
00520       errmsg = parse_imm16 (cd, strp, MT_OPERAND_IMM16O, (unsigned long *) (& fields->f_imm16s));
00521       break;
00522     case MT_OPERAND_IMM16Z :
00523       errmsg = parse_imm16 (cd, strp, MT_OPERAND_IMM16Z, (unsigned long *) (& fields->f_imm16u));
00524       break;
00525     case MT_OPERAND_INCAMT :
00526       errmsg = cgen_parse_unsigned_integer (cd, strp, MT_OPERAND_INCAMT, (unsigned long *) (& fields->f_incamt));
00527       break;
00528     case MT_OPERAND_INCR :
00529       errmsg = cgen_parse_unsigned_integer (cd, strp, MT_OPERAND_INCR, (unsigned long *) (& fields->f_incr));
00530       break;
00531     case MT_OPERAND_LENGTH :
00532       errmsg = cgen_parse_unsigned_integer (cd, strp, MT_OPERAND_LENGTH, (unsigned long *) (& fields->f_length));
00533       break;
00534     case MT_OPERAND_LOOPSIZE :
00535       errmsg = parse_loopsize (cd, strp, MT_OPERAND_LOOPSIZE, (unsigned long *) (& fields->f_loopo));
00536       break;
00537     case MT_OPERAND_MASK :
00538       errmsg = cgen_parse_unsigned_integer (cd, strp, MT_OPERAND_MASK, (unsigned long *) (& fields->f_mask));
00539       break;
00540     case MT_OPERAND_MASK1 :
00541       errmsg = cgen_parse_unsigned_integer (cd, strp, MT_OPERAND_MASK1, (unsigned long *) (& fields->f_mask1));
00542       break;
00543     case MT_OPERAND_MODE :
00544       errmsg = cgen_parse_unsigned_integer (cd, strp, MT_OPERAND_MODE, (unsigned long *) (& fields->f_mode));
00545       break;
00546     case MT_OPERAND_PERM :
00547       errmsg = cgen_parse_unsigned_integer (cd, strp, MT_OPERAND_PERM, (unsigned long *) (& fields->f_perm));
00548       break;
00549     case MT_OPERAND_RBBC :
00550       errmsg = parse_rbbc (cd, strp, MT_OPERAND_RBBC, (unsigned long *) (& fields->f_rbbc));
00551       break;
00552     case MT_OPERAND_RC :
00553       errmsg = parse_rc (cd, strp, MT_OPERAND_RC, (unsigned long *) (& fields->f_rc));
00554       break;
00555     case MT_OPERAND_RC1 :
00556       errmsg = parse_rc (cd, strp, MT_OPERAND_RC1, (unsigned long *) (& fields->f_rc1));
00557       break;
00558     case MT_OPERAND_RC2 :
00559       errmsg = parse_rc (cd, strp, MT_OPERAND_RC2, (unsigned long *) (& fields->f_rc2));
00560       break;
00561     case MT_OPERAND_RC3 :
00562       errmsg = parse_rc (cd, strp, MT_OPERAND_RC3, (unsigned long *) (& fields->f_rc3));
00563       break;
00564     case MT_OPERAND_RCNUM :
00565       errmsg = cgen_parse_unsigned_integer (cd, strp, MT_OPERAND_RCNUM, (unsigned long *) (& fields->f_rcnum));
00566       break;
00567     case MT_OPERAND_RDA :
00568       errmsg = cgen_parse_unsigned_integer (cd, strp, MT_OPERAND_RDA, (unsigned long *) (& fields->f_rda));
00569       break;
00570     case MT_OPERAND_ROWNUM :
00571       errmsg = cgen_parse_unsigned_integer (cd, strp, MT_OPERAND_ROWNUM, (unsigned long *) (& fields->f_rownum));
00572       break;
00573     case MT_OPERAND_ROWNUM1 :
00574       errmsg = cgen_parse_unsigned_integer (cd, strp, MT_OPERAND_ROWNUM1, (unsigned long *) (& fields->f_rownum1));
00575       break;
00576     case MT_OPERAND_ROWNUM2 :
00577       errmsg = cgen_parse_unsigned_integer (cd, strp, MT_OPERAND_ROWNUM2, (unsigned long *) (& fields->f_rownum2));
00578       break;
00579     case MT_OPERAND_SIZE :
00580       errmsg = cgen_parse_unsigned_integer (cd, strp, MT_OPERAND_SIZE, (unsigned long *) (& fields->f_size));
00581       break;
00582     case MT_OPERAND_TYPE :
00583       errmsg = parse_type (cd, strp, MT_OPERAND_TYPE, (unsigned long *) (& fields->f_type));
00584       break;
00585     case MT_OPERAND_WR :
00586       errmsg = cgen_parse_unsigned_integer (cd, strp, MT_OPERAND_WR, (unsigned long *) (& fields->f_wr));
00587       break;
00588     case MT_OPERAND_XMODE :
00589       errmsg = parse_xmode (cd, strp, MT_OPERAND_XMODE, (unsigned long *) (& fields->f_xmode));
00590       break;
00591 
00592     default :
00593       /* xgettext:c-format */
00594       fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
00595       abort ();
00596   }
00597 
00598   return errmsg;
00599 }
00600 
00601 cgen_parse_fn * const mt_cgen_parse_handlers[] = 
00602 {
00603   parse_insn_normal,
00604 };
00605 
00606 void
00607 mt_cgen_init_asm (CGEN_CPU_DESC cd)
00608 {
00609   mt_cgen_init_opcode_table (cd);
00610   mt_cgen_init_ibld_table (cd);
00611   cd->parse_handlers = & mt_cgen_parse_handlers[0];
00612   cd->parse_operand = mt_cgen_parse_operand;
00613 #ifdef CGEN_ASM_INIT_HOOK
00614 CGEN_ASM_INIT_HOOK
00615 #endif
00616 }
00617 
00618 
00619 
00620 /* Regex construction routine.
00621 
00622    This translates an opcode syntax string into a regex string,
00623    by replacing any non-character syntax element (such as an
00624    opcode) with the pattern '.*'
00625 
00626    It then compiles the regex and stores it in the opcode, for
00627    later use by mt_cgen_assemble_insn
00628 
00629    Returns NULL for success, an error message for failure.  */
00630 
00631 char * 
00632 mt_cgen_build_insn_regex (CGEN_INSN *insn)
00633 {  
00634   CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
00635   const char *mnem = CGEN_INSN_MNEMONIC (insn);
00636   char rxbuf[CGEN_MAX_RX_ELEMENTS];
00637   char *rx = rxbuf;
00638   const CGEN_SYNTAX_CHAR_TYPE *syn;
00639   int reg_err;
00640 
00641   syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
00642 
00643   /* Mnemonics come first in the syntax string.  */
00644   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
00645     return _("missing mnemonic in syntax string");
00646   ++syn;
00647 
00648   /* Generate a case sensitive regular expression that emulates case
00649      insensitive matching in the "C" locale.  We cannot generate a case
00650      insensitive regular expression because in Turkish locales, 'i' and 'I'
00651      are not equal modulo case conversion.  */
00652 
00653   /* Copy the literal mnemonic out of the insn.  */
00654   for (; *mnem; mnem++)
00655     {
00656       char c = *mnem;
00657 
00658       if (ISALPHA (c))
00659        {
00660          *rx++ = '[';
00661          *rx++ = TOLOWER (c);
00662          *rx++ = TOUPPER (c);
00663          *rx++ = ']';
00664        }
00665       else
00666        *rx++ = c;
00667     }
00668 
00669   /* Copy any remaining literals from the syntax string into the rx.  */
00670   for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
00671     {
00672       if (CGEN_SYNTAX_CHAR_P (* syn)) 
00673        {
00674          char c = CGEN_SYNTAX_CHAR (* syn);
00675 
00676          switch (c) 
00677            {
00678              /* Escape any regex metacharacters in the syntax.  */
00679            case '.': case '[': case '\\': 
00680            case '*': case '^': case '$': 
00681 
00682 #ifdef CGEN_ESCAPE_EXTENDED_REGEX
00683            case '?': case '{': case '}': 
00684            case '(': case ')': case '*':
00685            case '|': case '+': case ']':
00686 #endif
00687              *rx++ = '\\';
00688              *rx++ = c;
00689              break;
00690 
00691            default:
00692              if (ISALPHA (c))
00693               {
00694                 *rx++ = '[';
00695                 *rx++ = TOLOWER (c);
00696                 *rx++ = TOUPPER (c);
00697                 *rx++ = ']';
00698               }
00699              else
00700               *rx++ = c;
00701              break;
00702            }
00703        }
00704       else
00705        {
00706          /* Replace non-syntax fields with globs.  */
00707          *rx++ = '.';
00708          *rx++ = '*';
00709        }
00710     }
00711 
00712   /* Trailing whitespace ok.  */
00713   * rx++ = '['; 
00714   * rx++ = ' '; 
00715   * rx++ = '\t'; 
00716   * rx++ = ']'; 
00717   * rx++ = '*'; 
00718 
00719   /* But anchor it after that.  */
00720   * rx++ = '$'; 
00721   * rx = '\0';
00722 
00723   CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
00724   reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
00725 
00726   if (reg_err == 0) 
00727     return NULL;
00728   else
00729     {
00730       static char msg[80];
00731 
00732       regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
00733       regfree ((regex_t *) CGEN_INSN_RX (insn));
00734       free (CGEN_INSN_RX (insn));
00735       (CGEN_INSN_RX (insn)) = NULL;
00736       return msg;
00737     }
00738 }
00739 
00740 
00741 /* Default insn parser.
00742 
00743    The syntax string is scanned and operands are parsed and stored in FIELDS.
00744    Relocs are queued as we go via other callbacks.
00745 
00746    ??? Note that this is currently an all-or-nothing parser.  If we fail to
00747    parse the instruction, we return 0 and the caller will start over from
00748    the beginning.  Backtracking will be necessary in parsing subexpressions,
00749    but that can be handled there.  Not handling backtracking here may get
00750    expensive in the case of the m68k.  Deal with later.
00751 
00752    Returns NULL for success, an error message for failure.  */
00753 
00754 static const char *
00755 parse_insn_normal (CGEN_CPU_DESC cd,
00756                  const CGEN_INSN *insn,
00757                  const char **strp,
00758                  CGEN_FIELDS *fields)
00759 {
00760   /* ??? Runtime added insns not handled yet.  */
00761   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
00762   const char *str = *strp;
00763   const char *errmsg;
00764   const char *p;
00765   const CGEN_SYNTAX_CHAR_TYPE * syn;
00766 #ifdef CGEN_MNEMONIC_OPERANDS
00767   /* FIXME: wip */
00768   int past_opcode_p;
00769 #endif
00770 
00771   /* For now we assume the mnemonic is first (there are no leading operands).
00772      We can parse it without needing to set up operand parsing.
00773      GAS's input scrubber will ensure mnemonics are lowercase, but we may
00774      not be called from GAS.  */
00775   p = CGEN_INSN_MNEMONIC (insn);
00776   while (*p && TOLOWER (*p) == TOLOWER (*str))
00777     ++p, ++str;
00778 
00779   if (* p)
00780     return _("unrecognized instruction");
00781 
00782 #ifndef CGEN_MNEMONIC_OPERANDS
00783   if (* str && ! ISSPACE (* str))
00784     return _("unrecognized instruction");
00785 #endif
00786 
00787   CGEN_INIT_PARSE (cd);
00788   cgen_init_parse_operand (cd);
00789 #ifdef CGEN_MNEMONIC_OPERANDS
00790   past_opcode_p = 0;
00791 #endif
00792 
00793   /* We don't check for (*str != '\0') here because we want to parse
00794      any trailing fake arguments in the syntax string.  */
00795   syn = CGEN_SYNTAX_STRING (syntax);
00796 
00797   /* Mnemonics come first for now, ensure valid string.  */
00798   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
00799     abort ();
00800 
00801   ++syn;
00802 
00803   while (* syn != 0)
00804     {
00805       /* Non operand chars must match exactly.  */
00806       if (CGEN_SYNTAX_CHAR_P (* syn))
00807        {
00808          /* FIXME: While we allow for non-GAS callers above, we assume the
00809             first char after the mnemonic part is a space.  */
00810          /* FIXME: We also take inappropriate advantage of the fact that
00811             GAS's input scrubber will remove extraneous blanks.  */
00812          if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
00813            {
00814 #ifdef CGEN_MNEMONIC_OPERANDS
00815              if (CGEN_SYNTAX_CHAR(* syn) == ' ')
00816               past_opcode_p = 1;
00817 #endif
00818              ++ syn;
00819              ++ str;
00820            }
00821          else if (*str)
00822            {
00823              /* Syntax char didn't match.  Can't be this insn.  */
00824              static char msg [80];
00825 
00826              /* xgettext:c-format */
00827              sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
00828                      CGEN_SYNTAX_CHAR(*syn), *str);
00829              return msg;
00830            }
00831          else
00832            {
00833              /* Ran out of input.  */
00834              static char msg [80];
00835 
00836              /* xgettext:c-format */
00837              sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
00838                      CGEN_SYNTAX_CHAR(*syn));
00839              return msg;
00840            }
00841          continue;
00842        }
00843 
00844       /* We have an operand of some sort.  */
00845       errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn),
00846                                      &str, fields);
00847       if (errmsg)
00848        return errmsg;
00849 
00850       /* Done with this operand, continue with next one.  */
00851       ++ syn;
00852     }
00853 
00854   /* If we're at the end of the syntax string, we're done.  */
00855   if (* syn == 0)
00856     {
00857       /* FIXME: For the moment we assume a valid `str' can only contain
00858         blanks now.  IE: We needn't try again with a longer version of
00859         the insn and it is assumed that longer versions of insns appear
00860         before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
00861       while (ISSPACE (* str))
00862        ++ str;
00863 
00864       if (* str != '\0')
00865        return _("junk at end of line"); /* FIXME: would like to include `str' */
00866 
00867       return NULL;
00868     }
00869 
00870   /* We couldn't parse it.  */
00871   return _("unrecognized instruction");
00872 }
00873 
00874 /* Main entry point.
00875    This routine is called for each instruction to be assembled.
00876    STR points to the insn to be assembled.
00877    We assume all necessary tables have been initialized.
00878    The assembled instruction, less any fixups, is stored in BUF.
00879    Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
00880    still needs to be converted to target byte order, otherwise BUF is an array
00881    of bytes in target byte order.
00882    The result is a pointer to the insn's entry in the opcode table,
00883    or NULL if an error occured (an error message will have already been
00884    printed).
00885 
00886    Note that when processing (non-alias) macro-insns,
00887    this function recurses.
00888 
00889    ??? It's possible to make this cpu-independent.
00890    One would have to deal with a few minor things.
00891    At this point in time doing so would be more of a curiosity than useful
00892    [for example this file isn't _that_ big], but keeping the possibility in
00893    mind helps keep the design clean.  */
00894 
00895 const CGEN_INSN *
00896 mt_cgen_assemble_insn (CGEN_CPU_DESC cd,
00897                         const char *str,
00898                         CGEN_FIELDS *fields,
00899                         CGEN_INSN_BYTES_PTR buf,
00900                         char **errmsg)
00901 {
00902   const char *start;
00903   CGEN_INSN_LIST *ilist;
00904   const char *parse_errmsg = NULL;
00905   const char *insert_errmsg = NULL;
00906   int recognized_mnemonic = 0;
00907 
00908   /* Skip leading white space.  */
00909   while (ISSPACE (* str))
00910     ++ str;
00911 
00912   /* The instructions are stored in hashed lists.
00913      Get the first in the list.  */
00914   ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
00915 
00916   /* Keep looking until we find a match.  */
00917   start = str;
00918   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
00919     {
00920       const CGEN_INSN *insn = ilist->insn;
00921       recognized_mnemonic = 1;
00922 
00923 #ifdef CGEN_VALIDATE_INSN_SUPPORTED 
00924       /* Not usually needed as unsupported opcodes
00925         shouldn't be in the hash lists.  */
00926       /* Is this insn supported by the selected cpu?  */
00927       if (! mt_cgen_insn_supported (cd, insn))
00928        continue;
00929 #endif
00930       /* If the RELAXED attribute is set, this is an insn that shouldn't be
00931         chosen immediately.  Instead, it is used during assembler/linker
00932         relaxation if possible.  */
00933       if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
00934        continue;
00935 
00936       str = start;
00937 
00938       /* Skip this insn if str doesn't look right lexically.  */
00939       if (CGEN_INSN_RX (insn) != NULL &&
00940          regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
00941        continue;
00942 
00943       /* Allow parse/insert handlers to obtain length of insn.  */
00944       CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
00945 
00946       parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
00947       if (parse_errmsg != NULL)
00948        continue;
00949 
00950       /* ??? 0 is passed for `pc'.  */
00951       insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
00952                                            (bfd_vma) 0);
00953       if (insert_errmsg != NULL)
00954         continue;
00955 
00956       /* It is up to the caller to actually output the insn and any
00957          queued relocs.  */
00958       return insn;
00959     }
00960 
00961   {
00962     static char errbuf[150];
00963 #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
00964     const char *tmp_errmsg;
00965 
00966     /* If requesting verbose error messages, use insert_errmsg.
00967        Failing that, use parse_errmsg.  */
00968     tmp_errmsg = (insert_errmsg ? insert_errmsg :
00969                 parse_errmsg ? parse_errmsg :
00970                 recognized_mnemonic ?
00971                 _("unrecognized form of instruction") :
00972                 _("unrecognized instruction"));
00973 
00974     if (strlen (start) > 50)
00975       /* xgettext:c-format */
00976       sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
00977     else 
00978       /* xgettext:c-format */
00979       sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
00980 #else
00981     if (strlen (start) > 50)
00982       /* xgettext:c-format */
00983       sprintf (errbuf, _("bad instruction `%.50s...'"), start);
00984     else 
00985       /* xgettext:c-format */
00986       sprintf (errbuf, _("bad instruction `%.50s'"), start);
00987 #endif
00988       
00989     *errmsg = errbuf;
00990     return NULL;
00991   }
00992 }