Back to index

cell-binutils  2.17cvs20070401
frv-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 "frv-desc.h"
00035 #include "frv-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 inline static const char *
00053 parse_symbolic_address (CGEN_CPU_DESC cd,
00054                      const char **strp,
00055                      int opindex,
00056                      int opinfo,
00057                      enum cgen_parse_operand_result *resultp,
00058                      bfd_vma *valuep)
00059 {
00060   enum cgen_parse_operand_result result_type;
00061   const char *errmsg = (* cd->parse_operand_fn)
00062     (cd, CGEN_PARSE_OPERAND_SYMBOLIC, strp, opindex, opinfo,
00063      &result_type, valuep);
00064 
00065   if (errmsg == NULL
00066       && result_type != CGEN_PARSE_OPERAND_RESULT_QUEUED)
00067     return "symbolic expression required";
00068 
00069   if (resultp)
00070     *resultp = result_type;
00071 
00072   return errmsg;
00073 }
00074 
00075 static const char *
00076 parse_ldd_annotation (CGEN_CPU_DESC cd,
00077                     const char **strp,
00078                     int opindex,
00079                     unsigned long *valuep)
00080 {
00081   const char *errmsg;
00082   enum cgen_parse_operand_result result_type;
00083   bfd_vma value;
00084 
00085   if (**strp == '#' || **strp == '%')
00086     {
00087       if (strncasecmp (*strp + 1, "tlsdesc(", 8) == 0)
00088        {
00089          *strp += 9;
00090          errmsg = parse_symbolic_address (cd, strp, opindex,
00091                                       BFD_RELOC_FRV_TLSDESC_RELAX,
00092                                       &result_type, &value);
00093          if (**strp != ')')
00094            return "missing ')'";
00095          if (valuep)
00096            *valuep = value;
00097          ++*strp;
00098          if (errmsg)
00099            return errmsg;
00100        }
00101     }
00102   
00103   while (**strp == ' ' || **strp == '\t')
00104     ++*strp;
00105   
00106   if (**strp != '@')
00107     return "missing `@'";
00108 
00109   ++*strp;
00110 
00111   return NULL;
00112 }
00113 
00114 static const char *
00115 parse_call_annotation (CGEN_CPU_DESC cd,
00116                      const char **strp,
00117                      int opindex,
00118                      unsigned long *valuep)
00119 {
00120   const char *errmsg;
00121   enum cgen_parse_operand_result result_type;
00122   bfd_vma value;
00123 
00124   if (**strp == '#' || **strp == '%')
00125     {
00126       if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0)
00127        {
00128          *strp += 11;
00129          errmsg = parse_symbolic_address (cd, strp, opindex,
00130                                       BFD_RELOC_FRV_GETTLSOFF_RELAX,
00131                                       &result_type, &value);
00132          if (**strp != ')')
00133            return "missing ')'";
00134          if (valuep)
00135            *valuep = value;
00136          ++*strp;
00137          if (errmsg)
00138            return errmsg;
00139        }
00140     }
00141   
00142   while (**strp == ' ' || **strp == '\t')
00143     ++*strp;
00144   
00145   if (**strp != '@')
00146     return "missing `@'";
00147 
00148   ++*strp;
00149 
00150   return NULL;
00151 }
00152 
00153 static const char *
00154 parse_ld_annotation (CGEN_CPU_DESC cd,
00155                    const char **strp,
00156                    int opindex,
00157                    unsigned long *valuep)
00158 {
00159   const char *errmsg;
00160   enum cgen_parse_operand_result result_type;
00161   bfd_vma value;
00162 
00163   if (**strp == '#' || **strp == '%')
00164     {
00165       if (strncasecmp (*strp + 1, "tlsoff(", 7) == 0)
00166        {
00167          *strp += 8;
00168          errmsg = parse_symbolic_address (cd, strp, opindex,
00169                                       BFD_RELOC_FRV_TLSOFF_RELAX,
00170                                       &result_type, &value);
00171          if (**strp != ')')
00172            return "missing ')'";
00173          if (valuep)
00174            *valuep = value;
00175          ++*strp;
00176          if (errmsg)
00177            return errmsg;
00178        }
00179     }
00180   
00181   while (**strp == ' ' || **strp == '\t')
00182     ++*strp;
00183   
00184   if (**strp != '@')
00185     return "missing `@'";
00186 
00187   ++*strp;
00188 
00189   return NULL;
00190 }
00191 
00192 static const char *
00193 parse_ulo16 (CGEN_CPU_DESC cd,
00194             const char **strp,
00195             int opindex,
00196             unsigned long *valuep)
00197 {
00198   const char *errmsg;
00199   enum cgen_parse_operand_result result_type;
00200   bfd_vma value;
00201  
00202   if (**strp == '#' || **strp == '%')
00203     {
00204       if (strncasecmp (*strp + 1, "lo(", 3) == 0)
00205        {
00206          *strp += 4;
00207          errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
00208                                    & result_type, & value);
00209          if (**strp != ')')
00210            return "missing `)'";
00211          ++*strp;
00212          if (errmsg == NULL
00213              && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
00214            value &= 0xffff;
00215          *valuep = value;
00216          return errmsg;
00217        }
00218       if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
00219        {
00220          *strp += 9;
00221          errmsg = parse_symbolic_address (cd, strp, opindex,
00222                                       BFD_RELOC_FRV_GPRELLO,
00223                                       & result_type, & value);
00224          if (**strp != ')')
00225            return "missing ')'";
00226          ++*strp;
00227          *valuep = value;
00228          return errmsg;
00229        }
00230       else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
00231        {
00232          *strp += 7;
00233          errmsg = parse_symbolic_address (cd, strp, opindex,
00234                                       BFD_RELOC_FRV_GOTLO,
00235                                       & result_type, & value);
00236          if (**strp != ')')
00237            return "missing ')'";
00238          ++*strp;
00239          *valuep = value;
00240          return errmsg;
00241        }
00242       else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
00243        {
00244          *strp += 15;
00245          errmsg = parse_symbolic_address (cd, strp, opindex,
00246                                       BFD_RELOC_FRV_FUNCDESC_GOTLO,
00247                                       & result_type, & value);
00248          if (**strp != ')')
00249            return "missing ')'";
00250          ++*strp;
00251          *valuep = value;
00252          return errmsg;
00253        }
00254       else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
00255        {
00256          *strp += 10;
00257          errmsg = parse_symbolic_address (cd, strp, opindex,
00258                                       BFD_RELOC_FRV_GOTOFFLO,
00259                                       & result_type, & value);
00260          if (**strp != ')')
00261            return "missing ')'";
00262          ++*strp;
00263          *valuep = value;
00264          return errmsg;
00265        }
00266       else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
00267        {
00268          *strp += 18;
00269          errmsg = parse_symbolic_address (cd, strp, opindex,
00270                                       BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
00271                                       & result_type, & value);
00272          if (**strp != ')')
00273            return "missing ')'";
00274          ++*strp;
00275          *valuep = value;
00276          return errmsg;
00277        }
00278       else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0)
00279        {
00280          *strp += 14;
00281          errmsg = parse_symbolic_address (cd, strp, opindex,
00282                                       BFD_RELOC_FRV_GOTTLSDESCLO,
00283                                       & result_type, & value);
00284          if (**strp != ')')
00285            return "missing ')'";
00286          ++*strp;
00287          *valuep = value;
00288          return errmsg;
00289        }
00290       else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0)
00291        {
00292          *strp += 11;
00293          errmsg = parse_symbolic_address (cd, strp, opindex,
00294                                       BFD_RELOC_FRV_TLSMOFFLO,
00295                                       & result_type, & value);
00296          if (**strp != ')')
00297            return "missing ')'";
00298          ++*strp;
00299          *valuep = value;
00300          return errmsg;
00301        }
00302       else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0)
00303        {
00304          *strp += 13;
00305          errmsg = parse_symbolic_address (cd, strp, opindex,
00306                                       BFD_RELOC_FRV_GOTTLSOFFLO,
00307                                       & result_type, & value);
00308          if (**strp != ')')
00309            return "missing ')'";
00310          ++*strp;
00311          *valuep = value;
00312          return errmsg;
00313        }
00314     }
00315   return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
00316 }
00317 
00318 static const char *
00319 parse_uslo16 (CGEN_CPU_DESC cd,
00320              const char **strp,
00321              int opindex,
00322              signed long *valuep)
00323 {
00324   const char *errmsg;
00325   enum cgen_parse_operand_result result_type;
00326   bfd_vma value;
00327  
00328   if (**strp == '#' || **strp == '%')
00329     {
00330       if (strncasecmp (*strp + 1, "lo(", 3) == 0)
00331        {
00332          *strp += 4;
00333          errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
00334                                    & result_type, & value);
00335          if (**strp != ')')
00336            return "missing `)'";
00337          ++*strp;
00338          if (errmsg == NULL
00339              && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
00340            value &= 0xffff;
00341          *valuep = value;
00342          return errmsg;
00343        }
00344       else if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
00345        {
00346          *strp += 9;
00347          errmsg = parse_symbolic_address (cd, strp, opindex,
00348                                       BFD_RELOC_FRV_GPRELLO,
00349                                       & result_type, & value);
00350          if (**strp != ')')
00351            return "missing ')'";
00352          ++*strp;
00353          *valuep = value;
00354          return errmsg;
00355        }
00356       else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
00357        {
00358          *strp += 7;
00359          errmsg = parse_symbolic_address (cd, strp, opindex,
00360                                       BFD_RELOC_FRV_GOTLO,
00361                                       & result_type, & value);
00362          if (**strp != ')')
00363            return "missing ')'";
00364          ++*strp;
00365          *valuep = value;
00366          return errmsg;
00367        }
00368       else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
00369        {
00370          *strp += 15;
00371          errmsg = parse_symbolic_address (cd, strp, opindex,
00372                                       BFD_RELOC_FRV_FUNCDESC_GOTLO,
00373                                       & result_type, & value);
00374          if (**strp != ')')
00375            return "missing ')'";
00376          ++*strp;
00377          *valuep = value;
00378          return errmsg;
00379        }
00380       else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
00381        {
00382          *strp += 10;
00383          errmsg = parse_symbolic_address (cd, strp, opindex,
00384                                       BFD_RELOC_FRV_GOTOFFLO,
00385                                       & result_type, & value);
00386          if (**strp != ')')
00387            return "missing ')'";
00388          ++*strp;
00389          *valuep = value;
00390          return errmsg;
00391        }
00392       else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
00393        {
00394          *strp += 18;
00395          errmsg = parse_symbolic_address (cd, strp, opindex,
00396                                       BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
00397                                       & result_type, & value);
00398          if (**strp != ')')
00399            return "missing ')'";
00400          ++*strp;
00401          *valuep = value;
00402          return errmsg;
00403        }
00404       else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0)
00405        {
00406          *strp += 14;
00407          errmsg = parse_symbolic_address (cd, strp, opindex,
00408                                       BFD_RELOC_FRV_GOTTLSDESCLO,
00409                                       & result_type, & value);
00410          if (**strp != ')')
00411            return "missing ')'";
00412          ++*strp;
00413          *valuep = value;
00414          return errmsg;
00415        }
00416       else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0)
00417        {
00418          *strp += 11;
00419          errmsg = parse_symbolic_address (cd, strp, opindex,
00420                                       BFD_RELOC_FRV_TLSMOFFLO,
00421                                       & result_type, & value);
00422          if (**strp != ')')
00423            return "missing ')'";
00424          ++*strp;
00425          *valuep = value;
00426          return errmsg;
00427        }
00428       else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0)
00429        {
00430          *strp += 13;
00431          errmsg = parse_symbolic_address (cd, strp, opindex,
00432                                       BFD_RELOC_FRV_GOTTLSOFFLO,
00433                                       & result_type, & value);
00434          if (**strp != ')')
00435            return "missing ')'";
00436          ++*strp;
00437          *valuep = value;
00438          return errmsg;
00439        }
00440     }
00441   return cgen_parse_signed_integer (cd, strp, opindex, valuep);
00442 }
00443 
00444 static const char *
00445 parse_uhi16 (CGEN_CPU_DESC cd,
00446             const char **strp,
00447             int opindex,
00448             unsigned long *valuep)
00449 {
00450   const char *errmsg;
00451   enum cgen_parse_operand_result result_type;
00452   bfd_vma value;
00453  
00454   if (**strp == '#' || **strp == '%')
00455     {
00456       if (strncasecmp (*strp + 1, "hi(", 3) == 0)
00457        {
00458          *strp += 4;
00459          errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_HI16,
00460                                    & result_type, & value);
00461          if (**strp != ')')
00462            return "missing `)'";
00463          ++*strp;
00464          if (errmsg == NULL
00465              && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
00466            {
00467              /* If bfd_vma is wider than 32 bits, but we have a sign-
00468                or zero-extension, truncate it.  */
00469              if (value >= - ((bfd_vma)1 << 31)
00470                 || value <= ((bfd_vma)1 << 31) - (bfd_vma)1)
00471               value &= (((bfd_vma)1 << 16) << 16) - 1;
00472              value >>= 16;
00473            }
00474          *valuep = value;
00475          return errmsg;
00476        }
00477       else if (strncasecmp (*strp + 1, "gprelhi(", 8) == 0)
00478        {
00479          *strp += 9;
00480          errmsg = parse_symbolic_address (cd, strp, opindex,
00481                                       BFD_RELOC_FRV_GPRELHI,
00482                                       & result_type, & value);
00483          if (**strp != ')')
00484            return "missing ')'";
00485          ++*strp;
00486          *valuep = value;
00487          return errmsg;
00488        }
00489       else if (strncasecmp (*strp + 1, "gothi(", 6) == 0)
00490        {
00491          *strp += 7;
00492          errmsg = parse_symbolic_address (cd, strp, opindex,
00493                                       BFD_RELOC_FRV_GOTHI,
00494                                       & result_type, & value);
00495          if (**strp != ')')
00496            return "missing ')'";
00497          ++*strp;
00498          *valuep = value;
00499          return errmsg;
00500        }
00501       else if (strncasecmp (*strp + 1, "gotfuncdeschi(", 14) == 0)
00502        {
00503          *strp += 15;
00504          errmsg = parse_symbolic_address (cd, strp, opindex,
00505                                       BFD_RELOC_FRV_FUNCDESC_GOTHI,
00506                                       & result_type, & value);
00507          if (**strp != ')')
00508            return "missing ')'";
00509          ++*strp;
00510          *valuep = value;
00511          return errmsg;
00512        }
00513       else if (strncasecmp (*strp + 1, "gotoffhi(", 9) == 0)
00514        {
00515          *strp += 10;
00516          errmsg = parse_symbolic_address (cd, strp, opindex,
00517                                       BFD_RELOC_FRV_GOTOFFHI,
00518                                       & result_type, & value);
00519          if (**strp != ')')
00520            return "missing ')'";
00521          ++*strp;
00522          *valuep = value;
00523          return errmsg;
00524        }
00525       else if (strncasecmp (*strp + 1, "gotofffuncdeschi(", 17) == 0)
00526        {
00527          *strp += 18;
00528          errmsg = parse_symbolic_address (cd, strp, opindex,
00529                                       BFD_RELOC_FRV_FUNCDESC_GOTOFFHI,
00530                                       & result_type, & value);
00531          if (**strp != ')')
00532            return "missing ')'";
00533          ++*strp;
00534          *valuep = value;
00535          return errmsg;
00536        }
00537       else if (strncasecmp (*strp + 1, "gottlsdeschi(", 13) == 0)
00538        {
00539          *strp += 14;
00540          errmsg = parse_symbolic_address (cd, strp, opindex,
00541                                       BFD_RELOC_FRV_GOTTLSDESCHI,
00542                                       &result_type, &value);
00543          if (**strp != ')')
00544            return "missing ')'";
00545          ++*strp;
00546          *valuep = value;
00547          return errmsg;
00548        }
00549       else if (strncasecmp (*strp + 1, "tlsmoffhi(", 10) == 0)
00550        {
00551          *strp += 11;
00552          errmsg = parse_symbolic_address (cd, strp, opindex,
00553                                       BFD_RELOC_FRV_TLSMOFFHI,
00554                                       & result_type, & value);
00555          if (**strp != ')')
00556            return "missing ')'";
00557          ++*strp;
00558          *valuep = value;
00559          return errmsg;
00560        }
00561       else if (strncasecmp (*strp + 1, "gottlsoffhi(", 12) == 0)
00562        {
00563          *strp += 13;
00564          errmsg = parse_symbolic_address (cd, strp, opindex,
00565                                       BFD_RELOC_FRV_GOTTLSOFFHI,
00566                                       & result_type, & value);
00567          if (**strp != ')')
00568            return "missing ')'";
00569          ++*strp;
00570          *valuep = value;
00571          return errmsg;
00572        }
00573     }
00574   return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
00575 }
00576 
00577 static long
00578 parse_register_number (const char **strp)
00579 {
00580   int regno;
00581 
00582   if (**strp < '0' || **strp > '9')
00583     return -1; /* error */
00584 
00585   regno = **strp - '0';
00586   for (++*strp; **strp >= '0' && **strp <= '9'; ++*strp)
00587     regno = regno * 10 + (**strp - '0');
00588 
00589   return regno;
00590 }
00591 
00592 static const char *
00593 parse_spr (CGEN_CPU_DESC cd,
00594           const char **strp,
00595           CGEN_KEYWORD * table,
00596           long *valuep)
00597 {
00598   const char *save_strp;
00599   long regno;
00600 
00601   /* Check for spr index notation.  */
00602   if (strncasecmp (*strp, "spr[", 4) == 0)
00603     {
00604       *strp += 4;
00605       regno = parse_register_number (strp);
00606       if (**strp != ']')
00607         return _("missing `]'");
00608       ++*strp;
00609       if (! spr_valid (regno))
00610        return _("Special purpose register number is out of range");
00611       *valuep = regno;
00612       return NULL;
00613     }
00614 
00615   save_strp = *strp;
00616   regno = parse_register_number (strp);
00617   if (regno != -1)
00618     {
00619       if (! spr_valid (regno))
00620        return _("Special purpose register number is out of range");
00621       *valuep = regno;
00622       return NULL;
00623     }
00624 
00625   *strp = save_strp;
00626   return cgen_parse_keyword (cd, strp, table, valuep);
00627 }
00628 
00629 static const char *
00630 parse_d12 (CGEN_CPU_DESC cd,
00631           const char **strp,
00632           int opindex,
00633           long *valuep)
00634 {
00635   const char *errmsg;
00636   enum cgen_parse_operand_result result_type;
00637   bfd_vma value;
00638  
00639   /* Check for small data reference.  */
00640   if (**strp == '#' || **strp == '%')
00641     {
00642       if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
00643         {
00644           *strp += 9;
00645           errmsg = parse_symbolic_address (cd, strp, opindex,
00646                                       BFD_RELOC_FRV_GPREL12,
00647                                       & result_type, & value);
00648           if (**strp != ')')
00649             return "missing `)'";
00650           ++*strp;
00651           *valuep = value;
00652           return errmsg;
00653         }
00654       else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
00655        {
00656          *strp += 7;
00657          errmsg = parse_symbolic_address (cd, strp, opindex,
00658                                       BFD_RELOC_FRV_GOT12,
00659                                       & result_type, & value);
00660          if (**strp != ')')
00661            return "missing ')'";
00662          ++*strp;
00663          *valuep = value;
00664          return errmsg;
00665        }
00666       else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
00667        {
00668          *strp += 15;
00669          errmsg = parse_symbolic_address (cd, strp, opindex,
00670                                       BFD_RELOC_FRV_FUNCDESC_GOT12,
00671                                       & result_type, & value);
00672          if (**strp != ')')
00673            return "missing ')'";
00674          ++*strp;
00675          *valuep = value;
00676          return errmsg;
00677        }
00678       else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
00679        {
00680          *strp += 10;
00681          errmsg = parse_symbolic_address (cd, strp, opindex,
00682                                       BFD_RELOC_FRV_GOTOFF12,
00683                                       & result_type, & value);
00684          if (**strp != ')')
00685            return "missing ')'";
00686          ++*strp;
00687          *valuep = value;
00688          return errmsg;
00689        }
00690       else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
00691        {
00692          *strp += 18;
00693          errmsg = parse_symbolic_address (cd, strp, opindex,
00694                                       BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
00695                                       & result_type, & value);
00696          if (**strp != ')')
00697            return "missing ')'";
00698          ++*strp;
00699          *valuep = value;
00700          return errmsg;
00701        }
00702       else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0)
00703        {
00704          *strp += 14;
00705          errmsg = parse_symbolic_address (cd, strp, opindex,
00706                                       BFD_RELOC_FRV_GOTTLSDESC12,
00707                                       & result_type, & value);
00708          if (**strp != ')')
00709            return "missing ')'";
00710          ++*strp;
00711          *valuep = value;
00712          return errmsg;
00713        }
00714       else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0)
00715        {
00716          *strp += 11;
00717          errmsg = parse_symbolic_address (cd, strp, opindex,
00718                                       BFD_RELOC_FRV_TLSMOFF12,
00719                                       & result_type, & value);
00720          if (**strp != ')')
00721            return "missing ')'";
00722          ++*strp;
00723          *valuep = value;
00724          return errmsg;
00725        }
00726       else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0)
00727        {
00728          *strp += 13;
00729          errmsg = parse_symbolic_address (cd, strp, opindex,
00730                                       BFD_RELOC_FRV_GOTTLSOFF12,
00731                                       & result_type, & value);
00732          if (**strp != ')')
00733            return "missing ')'";
00734          ++*strp;
00735          *valuep = value;
00736          return errmsg;
00737        }
00738     }
00739   return cgen_parse_signed_integer (cd, strp, opindex, valuep);
00740 }
00741 
00742 static const char *
00743 parse_s12 (CGEN_CPU_DESC cd,
00744           const char **strp,
00745           int opindex,
00746           long *valuep)
00747 {
00748   const char *errmsg;
00749   enum cgen_parse_operand_result result_type;
00750   bfd_vma value;
00751  
00752   /* Check for small data reference.  */
00753   if (**strp == '#' || **strp == '%')
00754     {
00755       if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
00756        {
00757          *strp += 9;
00758          errmsg = parse_symbolic_address (cd, strp, opindex,
00759                                       BFD_RELOC_FRV_GPREL12,
00760                                       & result_type, & value);
00761          if (**strp != ')')
00762            return "missing `)'";
00763          ++*strp;
00764          *valuep = value;
00765          return errmsg;
00766        }
00767       else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
00768        {
00769          *strp += 7;
00770          errmsg = parse_symbolic_address (cd, strp, opindex,
00771                                       BFD_RELOC_FRV_GOT12,
00772                                       & result_type, & value);
00773          if (**strp != ')')
00774            return "missing ')'";
00775          ++*strp;
00776          *valuep = value;
00777          return errmsg;
00778        }
00779       else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
00780        {
00781          *strp += 15;
00782          errmsg = parse_symbolic_address (cd, strp, opindex,
00783                                       BFD_RELOC_FRV_FUNCDESC_GOT12,
00784                                       & result_type, & value);
00785          if (**strp != ')')
00786            return "missing ')'";
00787          ++*strp;
00788          *valuep = value;
00789          return errmsg;
00790        }
00791       else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
00792        {
00793          *strp += 10;
00794          errmsg = parse_symbolic_address (cd, strp, opindex,
00795                                       BFD_RELOC_FRV_GOTOFF12,
00796                                       & result_type, & value);
00797          if (**strp != ')')
00798            return "missing ')'";
00799          ++*strp;
00800          *valuep = value;
00801          return errmsg;
00802        }
00803       else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
00804        {
00805          *strp += 18;
00806          errmsg = parse_symbolic_address (cd, strp, opindex,
00807                                       BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
00808                                       & result_type, & value);
00809          if (**strp != ')')
00810            return "missing ')'";
00811          ++*strp;
00812          *valuep = value;
00813          return errmsg;
00814        }
00815       else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0)
00816        {
00817          *strp += 14;
00818          errmsg = parse_symbolic_address (cd, strp, opindex,
00819                                       BFD_RELOC_FRV_GOTTLSDESC12,
00820                                       & result_type, & value);
00821          if (**strp != ')')
00822            return "missing ')'";
00823          ++*strp;
00824          *valuep = value;
00825          return errmsg;
00826        }
00827       else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0)
00828        {
00829          *strp += 11;
00830          errmsg = parse_symbolic_address (cd, strp, opindex,
00831                                       BFD_RELOC_FRV_TLSMOFF12,
00832                                       & result_type, & value);
00833          if (**strp != ')')
00834            return "missing ')'";
00835          ++*strp;
00836          *valuep = value;
00837          return errmsg;
00838        }
00839       else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0)
00840        {
00841          *strp += 13;
00842          errmsg = parse_symbolic_address (cd, strp, opindex,
00843                                       BFD_RELOC_FRV_GOTTLSOFF12,
00844                                       & result_type, & value);
00845          if (**strp != ')')
00846            return "missing ')'";
00847          ++*strp;
00848          *valuep = value;
00849          return errmsg;
00850        }
00851     }
00852 
00853   if (**strp == '#')
00854     ++*strp;
00855   return cgen_parse_signed_integer (cd, strp, opindex, valuep);
00856 }
00857 
00858 static const char *
00859 parse_u12 (CGEN_CPU_DESC cd,
00860           const char **strp,
00861           int opindex,
00862           long *valuep)
00863 {
00864   const char *errmsg;
00865   enum cgen_parse_operand_result result_type;
00866   bfd_vma value;
00867  
00868   /* Check for small data reference.  */
00869   if ((**strp == '#' || **strp == '%')
00870       && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
00871     {
00872       *strp += 9;
00873       errmsg = parse_symbolic_address (cd, strp, opindex,
00874                                    BFD_RELOC_FRV_GPRELU12,
00875                                    & result_type, & value);
00876       if (**strp != ')')
00877         return "missing `)'";
00878       ++*strp;
00879       *valuep = value;
00880       return errmsg;
00881     }
00882   else
00883     {
00884       if (**strp == '#')
00885         ++*strp;
00886       return cgen_parse_signed_integer (cd, strp, opindex, valuep);
00887     }
00888 }
00889 
00890 static const char *
00891 parse_A (CGEN_CPU_DESC cd,
00892         const char **strp,
00893         int opindex,
00894         unsigned long *valuep,
00895         unsigned long A)
00896 {
00897   const char *errmsg;
00898  
00899   if (**strp == '#')
00900     ++*strp;
00901 
00902   errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
00903   if (errmsg)
00904     return errmsg;
00905 
00906   if (*valuep != A)
00907     return _("Value of A operand must be 0 or 1");
00908 
00909   return NULL;
00910 }
00911 
00912 static const char *
00913 parse_A0 (CGEN_CPU_DESC cd,
00914          const char **strp,
00915          int opindex,
00916          unsigned long *valuep)
00917 {
00918   return parse_A (cd, strp, opindex, valuep, 0);
00919 }
00920 
00921 static const char *
00922 parse_A1 (CGEN_CPU_DESC cd,
00923          const char **strp,
00924          int opindex,
00925          unsigned long *valuep)
00926 {
00927   return parse_A (cd, strp, opindex, valuep, 1);
00928 }
00929 
00930 static const char *
00931 parse_even_register (CGEN_CPU_DESC  cd,
00932                    const char **  strP,
00933                    CGEN_KEYWORD * tableP,
00934                    long *         valueP)
00935 {
00936   const char * errmsg;
00937   const char * saved_star_strP = * strP;
00938 
00939   errmsg = cgen_parse_keyword (cd, strP, tableP, valueP);
00940 
00941   if (errmsg == NULL && ((* valueP) & 1))
00942     {
00943       errmsg = _("register number must be even");
00944       * strP = saved_star_strP;
00945     }
00946 
00947   return errmsg;
00948 }
00949 
00950 static const char *
00951 parse_call_label (CGEN_CPU_DESC cd,
00952                 const char **strp,
00953                 int opindex,
00954                 int opinfo,
00955                 enum cgen_parse_operand_result *resultp,
00956                 bfd_vma *valuep)
00957 {
00958   const char *errmsg;
00959   bfd_vma value;
00960  
00961   /* Check for small data reference.  */
00962   if (opinfo == 0 && (**strp == '#' || **strp == '%'))
00963     {
00964       if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0)
00965        {
00966          *strp += 11;
00967          errmsg = parse_symbolic_address (cd, strp, opindex,
00968                                       BFD_RELOC_FRV_GETTLSOFF,
00969                                       resultp, &value);
00970          if (**strp != ')')
00971            return _("missing `)'");
00972          ++*strp;
00973          *valuep = value;
00974          return errmsg;
00975        }
00976     }
00977 
00978   return cgen_parse_address (cd, strp, opindex, opinfo, resultp, valuep);
00979 }
00980 
00981 /* -- */
00982 
00983 const char * frv_cgen_parse_operand
00984   (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
00985 
00986 /* Main entry point for operand parsing.
00987 
00988    This function is basically just a big switch statement.  Earlier versions
00989    used tables to look up the function to use, but
00990    - if the table contains both assembler and disassembler functions then
00991      the disassembler contains much of the assembler and vice-versa,
00992    - there's a lot of inlining possibilities as things grow,
00993    - using a switch statement avoids the function call overhead.
00994 
00995    This function could be moved into `parse_insn_normal', but keeping it
00996    separate makes clear the interface between `parse_insn_normal' and each of
00997    the handlers.  */
00998 
00999 const char *
01000 frv_cgen_parse_operand (CGEN_CPU_DESC cd,
01001                         int opindex,
01002                         const char ** strp,
01003                         CGEN_FIELDS * fields)
01004 {
01005   const char * errmsg = NULL;
01006   /* Used by scalar operands that still need to be parsed.  */
01007   long junk ATTRIBUTE_UNUSED;
01008 
01009   switch (opindex)
01010     {
01011     case FRV_OPERAND_A0 :
01012       errmsg = parse_A0 (cd, strp, FRV_OPERAND_A0, (unsigned long *) (& fields->f_A));
01013       break;
01014     case FRV_OPERAND_A1 :
01015       errmsg = parse_A1 (cd, strp, FRV_OPERAND_A1, (unsigned long *) (& fields->f_A));
01016       break;
01017     case FRV_OPERAND_ACC40SI :
01018       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_acc_names, & fields->f_ACC40Si);
01019       break;
01020     case FRV_OPERAND_ACC40SK :
01021       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_acc_names, & fields->f_ACC40Sk);
01022       break;
01023     case FRV_OPERAND_ACC40UI :
01024       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_acc_names, & fields->f_ACC40Ui);
01025       break;
01026     case FRV_OPERAND_ACC40UK :
01027       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_acc_names, & fields->f_ACC40Uk);
01028       break;
01029     case FRV_OPERAND_ACCGI :
01030       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_accg_names, & fields->f_ACCGi);
01031       break;
01032     case FRV_OPERAND_ACCGK :
01033       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_accg_names, & fields->f_ACCGk);
01034       break;
01035     case FRV_OPERAND_CCI :
01036       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cccr_names, & fields->f_CCi);
01037       break;
01038     case FRV_OPERAND_CPRDOUBLEK :
01039       errmsg = parse_even_register (cd, strp, & frv_cgen_opval_cpr_names, & fields->f_CPRk);
01040       break;
01041     case FRV_OPERAND_CPRI :
01042       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cpr_names, & fields->f_CPRi);
01043       break;
01044     case FRV_OPERAND_CPRJ :
01045       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cpr_names, & fields->f_CPRj);
01046       break;
01047     case FRV_OPERAND_CPRK :
01048       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cpr_names, & fields->f_CPRk);
01049       break;
01050     case FRV_OPERAND_CRI :
01051       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cccr_names, & fields->f_CRi);
01052       break;
01053     case FRV_OPERAND_CRJ :
01054       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cccr_names, & fields->f_CRj);
01055       break;
01056     case FRV_OPERAND_CRJ_FLOAT :
01057       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cccr_names, & fields->f_CRj_float);
01058       break;
01059     case FRV_OPERAND_CRJ_INT :
01060       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cccr_names, & fields->f_CRj_int);
01061       break;
01062     case FRV_OPERAND_CRK :
01063       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cccr_names, & fields->f_CRk);
01064       break;
01065     case FRV_OPERAND_FCCI_1 :
01066       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fccr_names, & fields->f_FCCi_1);
01067       break;
01068     case FRV_OPERAND_FCCI_2 :
01069       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fccr_names, & fields->f_FCCi_2);
01070       break;
01071     case FRV_OPERAND_FCCI_3 :
01072       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fccr_names, & fields->f_FCCi_3);
01073       break;
01074     case FRV_OPERAND_FCCK :
01075       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fccr_names, & fields->f_FCCk);
01076       break;
01077     case FRV_OPERAND_FRDOUBLEI :
01078       errmsg = parse_even_register (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRi);
01079       break;
01080     case FRV_OPERAND_FRDOUBLEJ :
01081       errmsg = parse_even_register (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRj);
01082       break;
01083     case FRV_OPERAND_FRDOUBLEK :
01084       errmsg = parse_even_register (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRk);
01085       break;
01086     case FRV_OPERAND_FRI :
01087       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRi);
01088       break;
01089     case FRV_OPERAND_FRINTI :
01090       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRi);
01091       break;
01092     case FRV_OPERAND_FRINTIEVEN :
01093       errmsg = parse_even_register (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRi);
01094       break;
01095     case FRV_OPERAND_FRINTJ :
01096       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRj);
01097       break;
01098     case FRV_OPERAND_FRINTJEVEN :
01099       errmsg = parse_even_register (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRj);
01100       break;
01101     case FRV_OPERAND_FRINTK :
01102       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRk);
01103       break;
01104     case FRV_OPERAND_FRINTKEVEN :
01105       errmsg = parse_even_register (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRk);
01106       break;
01107     case FRV_OPERAND_FRJ :
01108       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRj);
01109       break;
01110     case FRV_OPERAND_FRK :
01111       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRk);
01112       break;
01113     case FRV_OPERAND_FRKHI :
01114       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRk);
01115       break;
01116     case FRV_OPERAND_FRKLO :
01117       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRk);
01118       break;
01119     case FRV_OPERAND_GRDOUBLEK :
01120       errmsg = parse_even_register (cd, strp, & frv_cgen_opval_gr_names, & fields->f_GRk);
01121       break;
01122     case FRV_OPERAND_GRI :
01123       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_gr_names, & fields->f_GRi);
01124       break;
01125     case FRV_OPERAND_GRJ :
01126       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_gr_names, & fields->f_GRj);
01127       break;
01128     case FRV_OPERAND_GRK :
01129       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_gr_names, & fields->f_GRk);
01130       break;
01131     case FRV_OPERAND_GRKHI :
01132       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_gr_names, & fields->f_GRk);
01133       break;
01134     case FRV_OPERAND_GRKLO :
01135       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_gr_names, & fields->f_GRk);
01136       break;
01137     case FRV_OPERAND_ICCI_1 :
01138       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_iccr_names, & fields->f_ICCi_1);
01139       break;
01140     case FRV_OPERAND_ICCI_2 :
01141       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_iccr_names, & fields->f_ICCi_2);
01142       break;
01143     case FRV_OPERAND_ICCI_3 :
01144       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_iccr_names, & fields->f_ICCi_3);
01145       break;
01146     case FRV_OPERAND_LI :
01147       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_LI, (unsigned long *) (& fields->f_LI));
01148       break;
01149     case FRV_OPERAND_LRAD :
01150       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_LRAD, (unsigned long *) (& fields->f_LRAD));
01151       break;
01152     case FRV_OPERAND_LRAE :
01153       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_LRAE, (unsigned long *) (& fields->f_LRAE));
01154       break;
01155     case FRV_OPERAND_LRAS :
01156       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_LRAS, (unsigned long *) (& fields->f_LRAS));
01157       break;
01158     case FRV_OPERAND_TLBPRL :
01159       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_TLBPRL, (unsigned long *) (& fields->f_TLBPRL));
01160       break;
01161     case FRV_OPERAND_TLBPROPX :
01162       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_TLBPROPX, (unsigned long *) (& fields->f_TLBPRopx));
01163       break;
01164     case FRV_OPERAND_AE :
01165       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_AE, (unsigned long *) (& fields->f_ae));
01166       break;
01167     case FRV_OPERAND_CALLANN :
01168       errmsg = parse_call_annotation (cd, strp, FRV_OPERAND_CALLANN, (unsigned long *) (& fields->f_reloc_ann));
01169       break;
01170     case FRV_OPERAND_CCOND :
01171       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_CCOND, (unsigned long *) (& fields->f_ccond));
01172       break;
01173     case FRV_OPERAND_COND :
01174       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_COND, (unsigned long *) (& fields->f_cond));
01175       break;
01176     case FRV_OPERAND_D12 :
01177       errmsg = parse_d12 (cd, strp, FRV_OPERAND_D12, (long *) (& fields->f_d12));
01178       break;
01179     case FRV_OPERAND_DEBUG :
01180       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_DEBUG, (unsigned long *) (& fields->f_debug));
01181       break;
01182     case FRV_OPERAND_EIR :
01183       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_EIR, (unsigned long *) (& fields->f_eir));
01184       break;
01185     case FRV_OPERAND_HINT :
01186       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_HINT, (unsigned long *) (& fields->f_hint));
01187       break;
01188     case FRV_OPERAND_HINT_NOT_TAKEN :
01189       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_h_hint_not_taken, & fields->f_hint);
01190       break;
01191     case FRV_OPERAND_HINT_TAKEN :
01192       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_h_hint_taken, & fields->f_hint);
01193       break;
01194     case FRV_OPERAND_LABEL16 :
01195       {
01196         bfd_vma value = 0;
01197         errmsg = cgen_parse_address (cd, strp, FRV_OPERAND_LABEL16, 0, NULL,  & value);
01198         fields->f_label16 = value;
01199       }
01200       break;
01201     case FRV_OPERAND_LABEL24 :
01202       {
01203         bfd_vma value = 0;
01204         errmsg = parse_call_label (cd, strp, FRV_OPERAND_LABEL24, 0, NULL,  & value);
01205         fields->f_label24 = value;
01206       }
01207       break;
01208     case FRV_OPERAND_LDANN :
01209       errmsg = parse_ld_annotation (cd, strp, FRV_OPERAND_LDANN, (unsigned long *) (& fields->f_reloc_ann));
01210       break;
01211     case FRV_OPERAND_LDDANN :
01212       errmsg = parse_ldd_annotation (cd, strp, FRV_OPERAND_LDDANN, (unsigned long *) (& fields->f_reloc_ann));
01213       break;
01214     case FRV_OPERAND_LOCK :
01215       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_LOCK, (unsigned long *) (& fields->f_lock));
01216       break;
01217     case FRV_OPERAND_PACK :
01218       errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_h_pack, & fields->f_pack);
01219       break;
01220     case FRV_OPERAND_S10 :
01221       errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S10, (long *) (& fields->f_s10));
01222       break;
01223     case FRV_OPERAND_S12 :
01224       errmsg = parse_s12 (cd, strp, FRV_OPERAND_S12, (long *) (& fields->f_d12));
01225       break;
01226     case FRV_OPERAND_S16 :
01227       errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S16, (long *) (& fields->f_s16));
01228       break;
01229     case FRV_OPERAND_S5 :
01230       errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S5, (long *) (& fields->f_s5));
01231       break;
01232     case FRV_OPERAND_S6 :
01233       errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S6, (long *) (& fields->f_s6));
01234       break;
01235     case FRV_OPERAND_S6_1 :
01236       errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S6_1, (long *) (& fields->f_s6_1));
01237       break;
01238     case FRV_OPERAND_SLO16 :
01239       errmsg = parse_uslo16 (cd, strp, FRV_OPERAND_SLO16, (long *) (& fields->f_s16));
01240       break;
01241     case FRV_OPERAND_SPR :
01242       errmsg = parse_spr (cd, strp, & frv_cgen_opval_spr_names, & fields->f_spr);
01243       break;
01244     case FRV_OPERAND_U12 :
01245       errmsg = parse_u12 (cd, strp, FRV_OPERAND_U12, (long *) (& fields->f_u12));
01246       break;
01247     case FRV_OPERAND_U16 :
01248       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_U16, (unsigned long *) (& fields->f_u16));
01249       break;
01250     case FRV_OPERAND_U6 :
01251       errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_U6, (unsigned long *) (& fields->f_u6));
01252       break;
01253     case FRV_OPERAND_UHI16 :
01254       errmsg = parse_uhi16 (cd, strp, FRV_OPERAND_UHI16, (unsigned long *) (& fields->f_u16));
01255       break;
01256     case FRV_OPERAND_ULO16 :
01257       errmsg = parse_ulo16 (cd, strp, FRV_OPERAND_ULO16, (unsigned long *) (& fields->f_u16));
01258       break;
01259 
01260     default :
01261       /* xgettext:c-format */
01262       fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
01263       abort ();
01264   }
01265 
01266   return errmsg;
01267 }
01268 
01269 cgen_parse_fn * const frv_cgen_parse_handlers[] = 
01270 {
01271   parse_insn_normal,
01272 };
01273 
01274 void
01275 frv_cgen_init_asm (CGEN_CPU_DESC cd)
01276 {
01277   frv_cgen_init_opcode_table (cd);
01278   frv_cgen_init_ibld_table (cd);
01279   cd->parse_handlers = & frv_cgen_parse_handlers[0];
01280   cd->parse_operand = frv_cgen_parse_operand;
01281 #ifdef CGEN_ASM_INIT_HOOK
01282 CGEN_ASM_INIT_HOOK
01283 #endif
01284 }
01285 
01286 
01287 
01288 /* Regex construction routine.
01289 
01290    This translates an opcode syntax string into a regex string,
01291    by replacing any non-character syntax element (such as an
01292    opcode) with the pattern '.*'
01293 
01294    It then compiles the regex and stores it in the opcode, for
01295    later use by frv_cgen_assemble_insn
01296 
01297    Returns NULL for success, an error message for failure.  */
01298 
01299 char * 
01300 frv_cgen_build_insn_regex (CGEN_INSN *insn)
01301 {  
01302   CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
01303   const char *mnem = CGEN_INSN_MNEMONIC (insn);
01304   char rxbuf[CGEN_MAX_RX_ELEMENTS];
01305   char *rx = rxbuf;
01306   const CGEN_SYNTAX_CHAR_TYPE *syn;
01307   int reg_err;
01308 
01309   syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
01310 
01311   /* Mnemonics come first in the syntax string.  */
01312   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
01313     return _("missing mnemonic in syntax string");
01314   ++syn;
01315 
01316   /* Generate a case sensitive regular expression that emulates case
01317      insensitive matching in the "C" locale.  We cannot generate a case
01318      insensitive regular expression because in Turkish locales, 'i' and 'I'
01319      are not equal modulo case conversion.  */
01320 
01321   /* Copy the literal mnemonic out of the insn.  */
01322   for (; *mnem; mnem++)
01323     {
01324       char c = *mnem;
01325 
01326       if (ISALPHA (c))
01327        {
01328          *rx++ = '[';
01329          *rx++ = TOLOWER (c);
01330          *rx++ = TOUPPER (c);
01331          *rx++ = ']';
01332        }
01333       else
01334        *rx++ = c;
01335     }
01336 
01337   /* Copy any remaining literals from the syntax string into the rx.  */
01338   for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
01339     {
01340       if (CGEN_SYNTAX_CHAR_P (* syn)) 
01341        {
01342          char c = CGEN_SYNTAX_CHAR (* syn);
01343 
01344          switch (c) 
01345            {
01346              /* Escape any regex metacharacters in the syntax.  */
01347            case '.': case '[': case '\\': 
01348            case '*': case '^': case '$': 
01349 
01350 #ifdef CGEN_ESCAPE_EXTENDED_REGEX
01351            case '?': case '{': case '}': 
01352            case '(': case ')': case '*':
01353            case '|': case '+': case ']':
01354 #endif
01355              *rx++ = '\\';
01356              *rx++ = c;
01357              break;
01358 
01359            default:
01360              if (ISALPHA (c))
01361               {
01362                 *rx++ = '[';
01363                 *rx++ = TOLOWER (c);
01364                 *rx++ = TOUPPER (c);
01365                 *rx++ = ']';
01366               }
01367              else
01368               *rx++ = c;
01369              break;
01370            }
01371        }
01372       else
01373        {
01374          /* Replace non-syntax fields with globs.  */
01375          *rx++ = '.';
01376          *rx++ = '*';
01377        }
01378     }
01379 
01380   /* Trailing whitespace ok.  */
01381   * rx++ = '['; 
01382   * rx++ = ' '; 
01383   * rx++ = '\t'; 
01384   * rx++ = ']'; 
01385   * rx++ = '*'; 
01386 
01387   /* But anchor it after that.  */
01388   * rx++ = '$'; 
01389   * rx = '\0';
01390 
01391   CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
01392   reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
01393 
01394   if (reg_err == 0) 
01395     return NULL;
01396   else
01397     {
01398       static char msg[80];
01399 
01400       regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
01401       regfree ((regex_t *) CGEN_INSN_RX (insn));
01402       free (CGEN_INSN_RX (insn));
01403       (CGEN_INSN_RX (insn)) = NULL;
01404       return msg;
01405     }
01406 }
01407 
01408 
01409 /* Default insn parser.
01410 
01411    The syntax string is scanned and operands are parsed and stored in FIELDS.
01412    Relocs are queued as we go via other callbacks.
01413 
01414    ??? Note that this is currently an all-or-nothing parser.  If we fail to
01415    parse the instruction, we return 0 and the caller will start over from
01416    the beginning.  Backtracking will be necessary in parsing subexpressions,
01417    but that can be handled there.  Not handling backtracking here may get
01418    expensive in the case of the m68k.  Deal with later.
01419 
01420    Returns NULL for success, an error message for failure.  */
01421 
01422 static const char *
01423 parse_insn_normal (CGEN_CPU_DESC cd,
01424                  const CGEN_INSN *insn,
01425                  const char **strp,
01426                  CGEN_FIELDS *fields)
01427 {
01428   /* ??? Runtime added insns not handled yet.  */
01429   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
01430   const char *str = *strp;
01431   const char *errmsg;
01432   const char *p;
01433   const CGEN_SYNTAX_CHAR_TYPE * syn;
01434 #ifdef CGEN_MNEMONIC_OPERANDS
01435   /* FIXME: wip */
01436   int past_opcode_p;
01437 #endif
01438 
01439   /* For now we assume the mnemonic is first (there are no leading operands).
01440      We can parse it without needing to set up operand parsing.
01441      GAS's input scrubber will ensure mnemonics are lowercase, but we may
01442      not be called from GAS.  */
01443   p = CGEN_INSN_MNEMONIC (insn);
01444   while (*p && TOLOWER (*p) == TOLOWER (*str))
01445     ++p, ++str;
01446 
01447   if (* p)
01448     return _("unrecognized instruction");
01449 
01450 #ifndef CGEN_MNEMONIC_OPERANDS
01451   if (* str && ! ISSPACE (* str))
01452     return _("unrecognized instruction");
01453 #endif
01454 
01455   CGEN_INIT_PARSE (cd);
01456   cgen_init_parse_operand (cd);
01457 #ifdef CGEN_MNEMONIC_OPERANDS
01458   past_opcode_p = 0;
01459 #endif
01460 
01461   /* We don't check for (*str != '\0') here because we want to parse
01462      any trailing fake arguments in the syntax string.  */
01463   syn = CGEN_SYNTAX_STRING (syntax);
01464 
01465   /* Mnemonics come first for now, ensure valid string.  */
01466   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
01467     abort ();
01468 
01469   ++syn;
01470 
01471   while (* syn != 0)
01472     {
01473       /* Non operand chars must match exactly.  */
01474       if (CGEN_SYNTAX_CHAR_P (* syn))
01475        {
01476          /* FIXME: While we allow for non-GAS callers above, we assume the
01477             first char after the mnemonic part is a space.  */
01478          /* FIXME: We also take inappropriate advantage of the fact that
01479             GAS's input scrubber will remove extraneous blanks.  */
01480          if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
01481            {
01482 #ifdef CGEN_MNEMONIC_OPERANDS
01483              if (CGEN_SYNTAX_CHAR(* syn) == ' ')
01484               past_opcode_p = 1;
01485 #endif
01486              ++ syn;
01487              ++ str;
01488            }
01489          else if (*str)
01490            {
01491              /* Syntax char didn't match.  Can't be this insn.  */
01492              static char msg [80];
01493 
01494              /* xgettext:c-format */
01495              sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
01496                      CGEN_SYNTAX_CHAR(*syn), *str);
01497              return msg;
01498            }
01499          else
01500            {
01501              /* Ran out of input.  */
01502              static char msg [80];
01503 
01504              /* xgettext:c-format */
01505              sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
01506                      CGEN_SYNTAX_CHAR(*syn));
01507              return msg;
01508            }
01509          continue;
01510        }
01511 
01512       /* We have an operand of some sort.  */
01513       errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn),
01514                                      &str, fields);
01515       if (errmsg)
01516        return errmsg;
01517 
01518       /* Done with this operand, continue with next one.  */
01519       ++ syn;
01520     }
01521 
01522   /* If we're at the end of the syntax string, we're done.  */
01523   if (* syn == 0)
01524     {
01525       /* FIXME: For the moment we assume a valid `str' can only contain
01526         blanks now.  IE: We needn't try again with a longer version of
01527         the insn and it is assumed that longer versions of insns appear
01528         before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
01529       while (ISSPACE (* str))
01530        ++ str;
01531 
01532       if (* str != '\0')
01533        return _("junk at end of line"); /* FIXME: would like to include `str' */
01534 
01535       return NULL;
01536     }
01537 
01538   /* We couldn't parse it.  */
01539   return _("unrecognized instruction");
01540 }
01541 
01542 /* Main entry point.
01543    This routine is called for each instruction to be assembled.
01544    STR points to the insn to be assembled.
01545    We assume all necessary tables have been initialized.
01546    The assembled instruction, less any fixups, is stored in BUF.
01547    Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
01548    still needs to be converted to target byte order, otherwise BUF is an array
01549    of bytes in target byte order.
01550    The result is a pointer to the insn's entry in the opcode table,
01551    or NULL if an error occured (an error message will have already been
01552    printed).
01553 
01554    Note that when processing (non-alias) macro-insns,
01555    this function recurses.
01556 
01557    ??? It's possible to make this cpu-independent.
01558    One would have to deal with a few minor things.
01559    At this point in time doing so would be more of a curiosity than useful
01560    [for example this file isn't _that_ big], but keeping the possibility in
01561    mind helps keep the design clean.  */
01562 
01563 const CGEN_INSN *
01564 frv_cgen_assemble_insn (CGEN_CPU_DESC cd,
01565                         const char *str,
01566                         CGEN_FIELDS *fields,
01567                         CGEN_INSN_BYTES_PTR buf,
01568                         char **errmsg)
01569 {
01570   const char *start;
01571   CGEN_INSN_LIST *ilist;
01572   const char *parse_errmsg = NULL;
01573   const char *insert_errmsg = NULL;
01574   int recognized_mnemonic = 0;
01575 
01576   /* Skip leading white space.  */
01577   while (ISSPACE (* str))
01578     ++ str;
01579 
01580   /* The instructions are stored in hashed lists.
01581      Get the first in the list.  */
01582   ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
01583 
01584   /* Keep looking until we find a match.  */
01585   start = str;
01586   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
01587     {
01588       const CGEN_INSN *insn = ilist->insn;
01589       recognized_mnemonic = 1;
01590 
01591 #ifdef CGEN_VALIDATE_INSN_SUPPORTED 
01592       /* Not usually needed as unsupported opcodes
01593         shouldn't be in the hash lists.  */
01594       /* Is this insn supported by the selected cpu?  */
01595       if (! frv_cgen_insn_supported (cd, insn))
01596        continue;
01597 #endif
01598       /* If the RELAXED attribute is set, this is an insn that shouldn't be
01599         chosen immediately.  Instead, it is used during assembler/linker
01600         relaxation if possible.  */
01601       if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
01602        continue;
01603 
01604       str = start;
01605 
01606       /* Skip this insn if str doesn't look right lexically.  */
01607       if (CGEN_INSN_RX (insn) != NULL &&
01608          regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
01609        continue;
01610 
01611       /* Allow parse/insert handlers to obtain length of insn.  */
01612       CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
01613 
01614       parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
01615       if (parse_errmsg != NULL)
01616        continue;
01617 
01618       /* ??? 0 is passed for `pc'.  */
01619       insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
01620                                            (bfd_vma) 0);
01621       if (insert_errmsg != NULL)
01622         continue;
01623 
01624       /* It is up to the caller to actually output the insn and any
01625          queued relocs.  */
01626       return insn;
01627     }
01628 
01629   {
01630     static char errbuf[150];
01631 #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
01632     const char *tmp_errmsg;
01633 
01634     /* If requesting verbose error messages, use insert_errmsg.
01635        Failing that, use parse_errmsg.  */
01636     tmp_errmsg = (insert_errmsg ? insert_errmsg :
01637                 parse_errmsg ? parse_errmsg :
01638                 recognized_mnemonic ?
01639                 _("unrecognized form of instruction") :
01640                 _("unrecognized instruction"));
01641 
01642     if (strlen (start) > 50)
01643       /* xgettext:c-format */
01644       sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
01645     else 
01646       /* xgettext:c-format */
01647       sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
01648 #else
01649     if (strlen (start) > 50)
01650       /* xgettext:c-format */
01651       sprintf (errbuf, _("bad instruction `%.50s...'"), start);
01652     else 
01653       /* xgettext:c-format */
01654       sprintf (errbuf, _("bad instruction `%.50s'"), start);
01655 #endif
01656       
01657     *errmsg = errbuf;
01658     return NULL;
01659   }
01660 }