(linenum→info "unix/slp.c:2238")

binutils/2.18/opcodes/cgen-asm.in

    1: /* Assembler interface for targets using CGEN. -*- C -*-
    2:    CGEN: Cpu tools GENerator
    3: 
    4:    THIS FILE IS MACHINE GENERATED WITH CGEN.
    5:    - the resultant file is machine generated, cgen-asm.in isn't
    6: 
    7:    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2005, 2007
    8:    Free Software Foundation, Inc.
    9: 
   10:    This file is part of libopcodes.
   11: 
   12:    This library is free software; you can redistribute it and/or modify
   13:    it under the terms of the GNU General Public License as published by
   14:    the Free Software Foundation; either version 3, or (at your option)
   15:    any later version.
   16: 
   17:    It is distributed in the hope that it will be useful, but WITHOUT
   18:    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   19:    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
   20:    License for more details.
   21: 
   22:    You should have received a copy of the GNU General Public License
   23:    along with this program; if not, write to the Free Software Foundation, Inc.,
   24:    51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
   25: 
   26: 
   27: /* ??? Eventually more and more of this stuff can go to cpu-independent files.
   28:    Keep that in mind.  */
   29: 
   30: #include "sysdep.h"
   31: #include <stdio.h>
   32: #include "ansidecl.h"
   33: #include "bfd.h"
   34: #include "symcat.h"
   35: #include "@prefix@-desc.h"
   36: #include "@prefix@-opc.h"
   37: #include "opintl.h"
   38: #include "xregex.h"
   39: #include "libiberty.h"
   40: #include "safe-ctype.h"
   41: 
   42: #undef  min
   43: #define min(a,b) ((a) < (b) ? (a) : (b))
   44: #undef  max
   45: #define max(a,b) ((a) > (b) ? (a) : (b))
   46: 
   47: static const char * parse_insn_normal
   48:   (CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *);
   49: ^L
   50: /* -- assembler routines inserted here.  */
   51: ^L
   52: 
   53: /* Regex construction routine.
   54: 
   55:    This translates an opcode syntax string into a regex string,
   56:    by replacing any non-character syntax element (such as an
   57:    opcode) with the pattern '.*'
   58: 
   59:    It then compiles the regex and stores it in the opcode, for
   60:    later use by @arch@_cgen_assemble_insn
   61: 
   62:    Returns NULL for success, an error message for failure.  */
   63: 
   64: char * 
   65: @arch@_cgen_build_insn_regex (CGEN_INSN *insn)
   66: {  
   67:   CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
   68:   const char *mnem = CGEN_INSN_MNEMONIC (insn);
   69:   char rxbuf[CGEN_MAX_RX_ELEMENTS];
   70:   char *rx = rxbuf;
   71:   const CGEN_SYNTAX_CHAR_TYPE *syn;
   72:   int reg_err;
   73: 
   74:   syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
   75: 
   76:   /* Mnemonics come first in the syntax string.  */
   77:   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
   78:     return _("missing mnemonic in syntax string");
   79:   ++syn;
   80: 
   81:   /* Generate a case sensitive regular expression that emulates case
   82:      insensitive matching in the "C" locale.  We cannot generate a case
   83:      insensitive regular expression because in Turkish locales, 'i' and 'I'
   84:      are not equal modulo case conversion.  */
   85: 
   86:   /* Copy the literal mnemonic out of the insn.  */
   87:   for (; *mnem; mnem++)
   88:     {
   89:       char c = *mnem;
   90: 
   91:       if (ISALPHA (c))
   92:         {
   93:           *rx++ = '[';
   94:           *rx++ = TOLOWER (c);
   95:           *rx++ = TOUPPER (c);
   96:           *rx++ = ']';
   97:         }
   98:       else
   99:         *rx++ = c;
  100:     }
  101: 
  102:   /* Copy any remaining literals from the syntax string into the rx.  */
  103:   for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
  104:     {
  105:       if (CGEN_SYNTAX_CHAR_P (* syn)) 
  106:         {
  107:           char c = CGEN_SYNTAX_CHAR (* syn);
  108: 
  109:           switch (c) 
  110:             {
  111:               /* Escape any regex metacharacters in the syntax.  */
  112:             case '.': case '[': case '\\': 
  113:             case '*': case '^': case '$': 
  114: 
  115: #ifdef CGEN_ESCAPE_EXTENDED_REGEX
  116:             case '?': case '{': case '}': 
  117:             case '(': case ')': case '*':
  118:             case '|': case '+': case ']':
  119: #endif
  120:               *rx++ = '\\';
  121:               *rx++ = c;
  122:               break;
  123: 
  124:             default:
  125:               if (ISALPHA (c))
  126:                 {
  127:                   *rx++ = '[';
  128:                   *rx++ = TOLOWER (c);
  129:                   *rx++ = TOUPPER (c);
  130:                   *rx++ = ']';
  131:                 }
  132:               else
  133:                 *rx++ = c;
  134:               break;
  135:             }
  136:         }
  137:       else
  138:         {
  139:           /* Replace non-syntax fields with globs.  */
  140:           *rx++ = '.';
  141:           *rx++ = '*';
  142:         }
  143:     }
  144: 
  145:   /* Trailing whitespace ok.  */
  146:   * rx++ = '['; 
  147:   * rx++ = ' '; 
  148:   * rx++ = '\t'; 
  149:   * rx++ = ']'; 
  150:   * rx++ = '*'; 
  151: 
  152:   /* But anchor it after that.  */
  153:   * rx++ = '$'; 
  154:   * rx = '\0';
  155: 
  156:   CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
  157:   reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
  158: 
  159:   if (reg_err == 0) 
  160:     return NULL;
  161:   else
  162:     {
  163:       static char msg[80];
  164: 
  165:       regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
  166:       regfree ((regex_t *) CGEN_INSN_RX (insn));
  167:       free (CGEN_INSN_RX (insn));
  168:       (CGEN_INSN_RX (insn)) = NULL;
  169:       return msg;
  170:     }
  171: }
  172: 
  173: ^L
  174: /* Default insn parser.
  175: 
  176:    The syntax string is scanned and operands are parsed and stored in FIELDS.
  177:    Relocs are queued as we go via other callbacks.
  178: 
  179:    ??? Note that this is currently an all-or-nothing parser.  If we fail to
  180:    parse the instruction, we return 0 and the caller will start over from
  181:    the beginning.  Backtracking will be necessary in parsing subexpressions,
  182:    but that can be handled there.  Not handling backtracking here may get
  183:    expensive in the case of the m68k.  Deal with later.
  184: 
  185:    Returns NULL for success, an error message for failure.  */
  186: 
  187: static const char *
  188: parse_insn_normal (CGEN_CPU_DESC cd,
  189:                    const CGEN_INSN *insn,
  190:                    const char **strp,
  191:                    CGEN_FIELDS *fields)
  192: {
  193:   /* ??? Runtime added insns not handled yet.  */
  194:   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
  195:   const char *str = *strp;
  196:   const char *errmsg;
  197:   const char *p;
  198:   const CGEN_SYNTAX_CHAR_TYPE * syn;
  199: #ifdef CGEN_MNEMONIC_OPERANDS
  200:   /* FIXME: wip */
  201:   int past_opcode_p;
  202: #endif
  203: 
  204:   /* For now we assume the mnemonic is first (there are no leading operands).
  205:      We can parse it without needing to set up operand parsing.
  206:      GAS's input scrubber will ensure mnemonics are lowercase, but we may
  207:      not be called from GAS.  */
  208:   p = CGEN_INSN_MNEMONIC (insn);
  209:   while (*p && TOLOWER (*p) == TOLOWER (*str))
  210:     ++p, ++str;
  211: 
  212:   if (* p)
  213:     return _("unrecognized instruction");
  214: 
  215: #ifndef CGEN_MNEMONIC_OPERANDS
  216:   if (* str && ! ISSPACE (* str))
  217:     return _("unrecognized instruction");
  218: #endif
  219: 
  220:   CGEN_INIT_PARSE (cd);
  221:   cgen_init_parse_operand (cd);
  222: #ifdef CGEN_MNEMONIC_OPERANDS
  223:   past_opcode_p = 0;
  224: #endif
  225: 
  226:   /* We don't check for (*str != '\0') here because we want to parse
  227:      any trailing fake arguments in the syntax string.  */
  228:   syn = CGEN_SYNTAX_STRING (syntax);
  229: 
  230:   /* Mnemonics come first for now, ensure valid string.  */
  231:   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
  232:     abort ();
  233: 
  234:   ++syn;
  235: 
  236:   while (* syn != 0)
  237:     {
  238:       /* Non operand chars must match exactly.  */
  239:       if (CGEN_SYNTAX_CHAR_P (* syn))
  240:         {
  241:           /* FIXME: While we allow for non-GAS callers above, we assume the
  242:              first char after the mnemonic part is a space.  */
  243:           /* FIXME: We also take inappropriate advantage of the fact that
  244:              GAS's input scrubber will remove extraneous blanks.  */
  245:           if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
  246:             {
  247: #ifdef CGEN_MNEMONIC_OPERANDS
  248:               if (CGEN_SYNTAX_CHAR(* syn) == ' ')
  249:                 past_opcode_p = 1;
  250: #endif
  251:               ++ syn;
  252:               ++ str;
  253:             }
  254:           else if (*str)
  255:             {
  256:               /* Syntax char didn't match.  Can't be this insn.  */
  257:               static char msg [80];
  258: 
  259:               /* xgettext:c-format */
  260:               sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
  261:                        CGEN_SYNTAX_CHAR(*syn), *str);
  262:               return msg;
  263:             }
  264:           else
  265:             {
  266:               /* Ran out of input.  */
  267:               static char msg [80];
  268: 
  269:               /* xgettext:c-format */
  270:               sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
  271:                        CGEN_SYNTAX_CHAR(*syn));
  272:               return msg;
  273:             }
  274:           continue;
  275:         }
  276: 
  277:       /* We have an operand of some sort.  */
  278:       errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn),
  279:                                           &str, fields);
  280:       if (errmsg)
  281:         return errmsg;
  282: 
  283:       /* Done with this operand, continue with next one.  */
  284:       ++ syn;
  285:     }
  286: 
  287:   /* If we're at the end of the syntax string, we're done.  */
  288:   if (* syn == 0)
  289:     {
  290:       /* FIXME: For the moment we assume a valid `str' can only contain
  291:          blanks now.  IE: We needn't try again with a longer version of
  292:          the insn and it is assumed that longer versions of insns appear
  293:          before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
  294:       while (ISSPACE (* str))
  295:         ++ str;
  296: 
  297:       if (* str != '\0')
  298:         return _("junk at end of line"); /* FIXME: would like to include `str' */
  299: 
  300:       return NULL;
  301:     }
  302: 
  303:   /* We couldn't parse it.  */
  304:   return _("unrecognized instruction");
  305: }
  306: ^L
  307: /* Main entry point.
  308:    This routine is called for each instruction to be assembled.
  309:    STR points to the insn to be assembled.
  310:    We assume all necessary tables have been initialized.
  311:    The assembled instruction, less any fixups, is stored in BUF.
  312:    Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
  313:    still needs to be converted to target byte order, otherwise BUF is an array
  314:    of bytes in target byte order.
  315:    The result is a pointer to the insn's entry in the opcode table,
  316:    or NULL if an error occured (an error message will have already been
  317:    printed).
  318: 
  319:    Note that when processing (non-alias) macro-insns,
  320:    this function recurses.
  321: 
  322:    ??? It's possible to make this cpu-independent.
  323:    One would have to deal with a few minor things.
  324:    At this point in time doing so would be more of a curiosity than useful
  325:    [for example this file isn't _that_ big], but keeping the possibility in
  326:    mind helps keep the design clean.  */
  327: 
  328: const CGEN_INSN *
  329: @arch@_cgen_assemble_insn (CGEN_CPU_DESC cd,
  330:                            const char *str,
  331:                            CGEN_FIELDS *fields,
  332:                            CGEN_INSN_BYTES_PTR buf,
  333:                            char **errmsg)
  334: {
  335:   const char *start;
  336:   CGEN_INSN_LIST *ilist;
  337:   const char *parse_errmsg = NULL;
  338:   const char *insert_errmsg = NULL;
  339:   int recognized_mnemonic = 0;
  340: 
  341:   /* Skip leading white space.  */
  342:   while (ISSPACE (* str))
  343:     ++ str;
  344: 
  345:   /* The instructions are stored in hashed lists.
  346:      Get the first in the list.  */
  347:   ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
  348: 
  349:   /* Keep looking until we find a match.  */
  350:   start = str;
  351:   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
  352:     {
  353:       const CGEN_INSN *insn = ilist->insn;
  354:       recognized_mnemonic = 1;
  355: 
  356: #ifdef CGEN_VALIDATE_INSN_SUPPORTED 
  357:       /* Not usually needed as unsupported opcodes
  358:          shouldn't be in the hash lists.  */
  359:       /* Is this insn supported by the selected cpu?  */
  360:       if (! @arch@_cgen_insn_supported (cd, insn))
  361:         continue;
  362: #endif
  363:       /* If the RELAXED attribute is set, this is an insn that shouldn't be
  364:          chosen immediately.  Instead, it is used during assembler/linker
  365:          relaxation if possible.  */
  366:       if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
  367:         continue;
  368: 
  369:       str = start;
  370: 
  371:       /* Skip this insn if str doesn't look right lexically.  */
  372:       if (CGEN_INSN_RX (insn) != NULL &&
  373:           regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
  374:         continue;
  375: 
  376:       /* Allow parse/insert handlers to obtain length of insn.  */
  377:       CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
  378: 
  379:       parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
  380:       if (parse_errmsg != NULL)
  381:         continue;
  382: 
  383:       /* ??? 0 is passed for `pc'.  */
  384:       insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
  385:                                                  (bfd_vma) 0);
  386:       if (insert_errmsg != NULL)
  387:         continue;
  388: 
  389:       /* It is up to the caller to actually output the insn and any
  390:          queued relocs.  */
  391:       return insn;
  392:     }
  393: 
  394:   {
  395:     static char errbuf[150];
  396: #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
  397:     const char *tmp_errmsg;
  398: 
  399:     /* If requesting verbose error messages, use insert_errmsg.
  400:        Failing that, use parse_errmsg.  */
  401:     tmp_errmsg = (insert_errmsg ? insert_errmsg :
  402:                   parse_errmsg ? parse_errmsg :
  403:                   recognized_mnemonic ?
  404:                   _("unrecognized form of instruction") :
  405:                   _("unrecognized instruction"));
  406: 
  407:     if (strlen (start) > 50)
  408:       /* xgettext:c-format */
  409:       sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
  410:     else 
  411:       /* xgettext:c-format */
  412:       sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
  413: #else
  414:     if (strlen (start) > 50)
  415:       /* xgettext:c-format */
  416:       sprintf (errbuf, _("bad instruction `%.50s...'"), start);
  417:     else 
  418:       /* xgettext:c-format */
  419:       sprintf (errbuf, _("bad instruction `%.50s'"), start);
  420: #endif
  421:       
  422:     *errmsg = errbuf;
  423:     return NULL;
  424:   }
  425: }
Syntax (Markdown)