Ignore:
Timestamp:
Aug 16, 2003, 6:59:22 PM (22 years ago)
Author:
bird
Message:

binutils v2.14 - offical sources.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/GNU/src/binutils/opcodes/fr30-asm.c

    • Property cvs2svn:cvs-rev changed from 1.1 to 1.1.1.2
    r608 r609  
    2727
    2828#include "sysdep.h"
    29 #include <ctype.h>
    3029#include <stdio.h>
    3130#include "ansidecl.h"
     
    3534#include "fr30-opc.h"
    3635#include "opintl.h"
    37 
    38 #undef min
     36#include "xregex.h"
     37#include "libiberty.h"
     38#include "safe-ctype.h"
     39
     40#undef  min
    3941#define min(a,b) ((a) < (b) ? (a) : (b))
    40 #undef max
     42#undef  max
    4143#define max(a,b) ((a) > (b) ? (a) : (b))
    4244
     
    4547
    4648
    47 /* -- assembler routines inserted here */
     49/* -- assembler routines inserted here. */
    4850
    4951/* -- asm.c */
    50 /* Handle register lists for LDMx and STMx  */
     52/* Handle register lists for LDMx and STMx.  */
     53
     54static int parse_register_number
     55  PARAMS ((const char **));
     56static const char * parse_register_list
     57  PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *, int, int));
     58static const char * parse_low_register_list_ld
     59  PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
     60static const char * parse_hi_register_list_ld
     61  PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
     62static const char * parse_low_register_list_st
     63  PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
     64static const char * parse_hi_register_list_st
     65  PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
    5166
    5267static int
     
    5671  int regno;
    5772  if (**strp < '0' || **strp > '9')
    58     return -1; /* error */
     73    return -1; /* error. */
    5974  regno = **strp - '0';
    6075  ++*strp;
     
    7186static const char *
    7287parse_register_list (cd, strp, opindex, valuep, high_low, load_store)
    73      CGEN_CPU_DESC cd;
     88     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
    7489     const char **strp;
    75      int opindex;
     90     int opindex ATTRIBUTE_UNUSED;
    7691     unsigned long *valuep;
    7792     int high_low;   /* 0 == high, 1 == low */
     
    7994{
    8095  int regno;
     96
    8197  *valuep = 0;
    8298  while (**strp && **strp != ')')
     
    97113        regno -= 8;
    98114
    99       if (load_store) /* mask is reversed for store */
     115      if (load_store) /* Mask is reversed for store. */
    100116        *valuep |= 0x80 >> regno;
    101117      else
     
    158174/* -- */
    159175
     176const char * fr30_cgen_parse_operand
     177  PARAMS ((CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *));
     178
    160179/* Main entry point for operand parsing.
    161180
     
    169188   This function could be moved into `parse_insn_normal', but keeping it
    170189   separate makes clear the interface between `parse_insn_normal' and each of
    171    the handlers.
    172 */
     190   the handlers.  */
    173191
    174192const char *
     
    181199  const char * errmsg = NULL;
    182200  /* Used by scalar operands that still need to be parsed.  */
    183   long junk;
     201  long junk ATTRIBUTE_UNUSED;
    184202
    185203  switch (opindex)
     
    328346
    329347
     348
     349/* Regex construction routine.
     350
     351   This translates an opcode syntax string into a regex string,
     352   by replacing any non-character syntax element (such as an
     353   opcode) with the pattern '.*'
     354
     355   It then compiles the regex and stores it in the opcode, for
     356   later use by fr30_cgen_assemble_insn
     357
     358   Returns NULL for success, an error message for failure.  */
     359
     360char *
     361fr30_cgen_build_insn_regex (insn)
     362     CGEN_INSN *insn;
     363
     364  CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
     365  const char *mnem = CGEN_INSN_MNEMONIC (insn);
     366  char rxbuf[CGEN_MAX_RX_ELEMENTS];
     367  char *rx = rxbuf;
     368  const CGEN_SYNTAX_CHAR_TYPE *syn;
     369  int reg_err;
     370
     371  syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
     372
     373  /* Mnemonics come first in the syntax string.  */
     374  if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
     375    return _("missing mnemonic in syntax string");
     376  ++syn;
     377
     378  /* Generate a case sensitive regular expression that emulates case
     379     insensitive matching in the "C" locale.  We cannot generate a case
     380     insensitive regular expression because in Turkish locales, 'i' and 'I'
     381     are not equal modulo case conversion.  */
     382
     383  /* Copy the literal mnemonic out of the insn.  */
     384  for (; *mnem; mnem++)
     385    {
     386      char c = *mnem;
     387
     388      if (ISALPHA (c))
     389        {
     390          *rx++ = '[';
     391          *rx++ = TOLOWER (c);
     392          *rx++ = TOUPPER (c);
     393          *rx++ = ']';
     394        }
     395      else
     396        *rx++ = c;
     397    }
     398
     399  /* Copy any remaining literals from the syntax string into the rx.  */
     400  for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
     401    {
     402      if (CGEN_SYNTAX_CHAR_P (* syn))
     403        {
     404          char c = CGEN_SYNTAX_CHAR (* syn);
     405
     406          switch (c)
     407            {
     408              /* Escape any regex metacharacters in the syntax.  */
     409            case '.': case '[': case '\\':
     410            case '*': case '^': case '$':
     411
     412#ifdef CGEN_ESCAPE_EXTENDED_REGEX
     413            case '?': case '{': case '}':
     414            case '(': case ')': case '*':
     415            case '|': case '+': case ']':
     416#endif
     417              *rx++ = '\\';
     418              *rx++ = c;
     419              break;
     420
     421            default:
     422              if (ISALPHA (c))
     423                {
     424                  *rx++ = '[';
     425                  *rx++ = TOLOWER (c);
     426                  *rx++ = TOUPPER (c);
     427                  *rx++ = ']';
     428                }
     429              else
     430                *rx++ = c;
     431              break;
     432            }
     433        }
     434      else
     435        {
     436          /* Replace non-syntax fields with globs.  */
     437          *rx++ = '.';
     438          *rx++ = '*';
     439        }
     440    }
     441
     442  /* Trailing whitespace ok.  */
     443  * rx++ = '[';
     444  * rx++ = ' ';
     445  * rx++ = '\t';
     446  * rx++ = ']';
     447  * rx++ = '*';
     448
     449  /* But anchor it after that.  */
     450  * rx++ = '$';
     451  * rx = '\0';
     452
     453  CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
     454  reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
     455
     456  if (reg_err == 0)
     457    return NULL;
     458  else
     459    {
     460      static char msg[80];
     461
     462      regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
     463      regfree ((regex_t *) CGEN_INSN_RX (insn));
     464      free (CGEN_INSN_RX (insn));
     465      (CGEN_INSN_RX (insn)) = NULL;
     466      return msg;
     467    }
     468}
     469
     470
     471
    330472/* Default insn parser.
    331473
     
    339481   expensive in the case of the m68k.  Deal with later.
    340482
    341    Returns NULL for success, an error message for failure.
    342 */
     483   Returns NULL for success, an error message for failure.  */
    343484
    344485static const char *
     
    354495  const char *errmsg;
    355496  const char *p;
    356   const unsigned char * syn;
     497  const CGEN_SYNTAX_CHAR_TYPE * syn;
    357498#ifdef CGEN_MNEMONIC_OPERANDS
    358499  /* FIXME: wip */
     
    365506     not be called from GAS.  */
    366507  p = CGEN_INSN_MNEMONIC (insn);
    367   while (*p && tolower (*p) == tolower (*str))
     508  while (*p && TOLOWER (*p) == TOLOWER (*str))
    368509    ++p, ++str;
    369510
     
    372513
    373514#ifndef CGEN_MNEMONIC_OPERANDS
    374   if (* str && !isspace (* str))
     515  if (* str && ! ISSPACE (* str))
    375516    return _("unrecognized instruction");
    376517#endif
     
    401542          /* FIXME: We also take inappropriate advantage of the fact that
    402543             GAS's input scrubber will remove extraneous blanks.  */
    403           if (tolower (*str) == tolower (CGEN_SYNTAX_CHAR (* syn)))
     544          if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
    404545            {
    405546#ifdef CGEN_MNEMONIC_OPERANDS
    406               if (* syn == ' ')
     547              if (CGEN_SYNTAX_CHAR(* syn) == ' ')
    407548                past_opcode_p = 1;
    408549#endif
     
    410551              ++ str;
    411552            }
    412           else
     553          else if (*str)
    413554            {
    414555              /* Syntax char didn't match.  Can't be this insn.  */
    415556              static char msg [80];
     557
    416558              /* xgettext:c-format */
    417559              sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
    418                        *syn, *str);
     560                       CGEN_SYNTAX_CHAR(*syn), *str);
     561              return msg;
     562            }
     563          else
     564            {
     565              /* Ran out of input.  */
     566              static char msg [80];
     567
     568              /* xgettext:c-format */
     569              sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
     570                       CGEN_SYNTAX_CHAR(*syn));
    419571              return msg;
    420572            }
     
    423575
    424576      /* We have an operand of some sort.  */
    425       errmsg = fr30_cgen_parse_operand (cd, CGEN_SYNTAX_FIELD (*syn),
     577      errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn),
    426578                                          &str, fields);
    427579      if (errmsg)
     
    433585
    434586  /* If we're at the end of the syntax string, we're done.  */
    435   if (* syn == '\0')
     587  if (* syn == 0)
    436588    {
    437589      /* FIXME: For the moment we assume a valid `str' can only contain
     
    439591         the insn and it is assumed that longer versions of insns appear
    440592         before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
    441       while (isspace (* str))
     593      while (ISSPACE (* str))
    442594        ++ str;
    443595
     
    484636  const char *start;
    485637  CGEN_INSN_LIST *ilist;
    486   const char *tmp_errmsg = NULL;
     638  const char *parse_errmsg = NULL;
     639  const char *insert_errmsg = NULL;
     640  int recognized_mnemonic = 0;
    487641
    488642  /* Skip leading white space.  */
    489   while (isspace (* str))
     643  while (ISSPACE (* str))
    490644    ++ str;
    491645
     
    495649
    496650  /* Keep looking until we find a match.  */
    497 
    498651  start = str;
    499652  for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
    500653    {
    501654      const CGEN_INSN *insn = ilist->insn;
     655      recognized_mnemonic = 1;
    502656
    503657#ifdef CGEN_VALIDATE_INSN_SUPPORTED
    504       /* not usually needed as unsupported opcodes shouldn't be in the hash lists */
     658      /* Not usually needed as unsupported opcodes
     659         shouldn't be in the hash lists.  */
    505660      /* Is this insn supported by the selected cpu?  */
    506661      if (! fr30_cgen_insn_supported (cd, insn))
    507662        continue;
    508663#endif
    509 
    510664      /* If the RELAX attribute is set, this is an insn that shouldn't be
    511665         chosen immediately.  Instead, it is used during assembler/linker
     
    516670      str = start;
    517671
     672      /* Skip this insn if str doesn't look right lexically.  */
     673      if (CGEN_INSN_RX (insn) != NULL &&
     674          regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
     675        continue;
     676
    518677      /* Allow parse/insert handlers to obtain length of insn.  */
    519678      CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
    520679
    521       tmp_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
    522       if (tmp_errmsg != NULL)
     680      parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
     681      if (parse_errmsg != NULL)
    523682        continue;
    524683
    525       /* ??? 0 is passed for `pc' */
    526       tmp_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
    527                                               (bfd_vma) 0);
    528       if (tmp_errmsg != NULL)
     684      /* ??? 0 is passed for `pc'. */
     685      insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
     686                                                (bfd_vma) 0);
     687      if (insert_errmsg != NULL)
    529688        continue;
    530689
     
    534693    }
    535694
    536   /* Make sure we leave this with something at this point. */
    537   if (tmp_errmsg == NULL)
    538     tmp_errmsg = "unknown mnemonic";
    539 
    540695  {
    541696    static char errbuf[150];
    542 
    543697#ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
    544     /* if verbose error messages, use errmsg from CGEN_PARSE_FN */
     698    const char *tmp_errmsg;
     699
     700    /* If requesting verbose error messages, use insert_errmsg.
     701       Failing that, use parse_errmsg.  */
     702    tmp_errmsg = (insert_errmsg ? insert_errmsg :
     703                  parse_errmsg ? parse_errmsg :
     704                  recognized_mnemonic ?
     705                  _("unrecognized form of instruction") :
     706                  _("unrecognized instruction"));
     707
    545708    if (strlen (start) > 50)
    546709      /* xgettext:c-format */
Note: See TracChangeset for help on using the changeset viewer.