Annotation of GNUtools/cc/genrecog.c, revision 1.1

1.1     ! root        1: /* Generate code from machine description to recognize rtl as insns.
        !             2:    Copyright (C) 1987, 1988, 1992, 1993 Free Software Foundation, Inc.
        !             3: 
        !             4: This file is part of GNU CC.
        !             5: 
        !             6: GNU CC is free software; you can redistribute it and/or modify
        !             7: it under the terms of the GNU General Public License as published by
        !             8: the Free Software Foundation; either version 2, or (at your option)
        !             9: any later version.
        !            10: 
        !            11: GNU CC is distributed in the hope that it will be useful,
        !            12: but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            14: GNU General Public License for more details.
        !            15: 
        !            16: You should have received a copy of the GNU General Public License
        !            17: along with GNU CC; see the file COPYING.  If not, write to
        !            18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
        !            19: 
        !            20: 
        !            21: /* This program is used to produce insn-recog.c, which contains
        !            22:    a function called `recog' plus its subroutines.
        !            23:    These functions contain a decision tree
        !            24:    that recognizes whether an rtx, the argument given to recog,
        !            25:    is a valid instruction.
        !            26: 
        !            27:    recog returns -1 if the rtx is not valid.
        !            28:    If the rtx is valid, recog returns a nonnegative number
        !            29:    which is the insn code number for the pattern that matched.
        !            30:    This is the same as the order in the machine description of the
        !            31:    entry that matched.  This number can be used as an index into various
        !            32:    insn_* tables, such as insn_template, insn_outfun, and insn_n_operands
        !            33:    (found in insn-output.c).
        !            34: 
        !            35:    The third argument to recog is an optional pointer to an int.
        !            36:    If present, recog will accept a pattern if it matches except for
        !            37:    missing CLOBBER expressions at the end.  In that case, the value
        !            38:    pointed to by the optional pointer will be set to the number of
        !            39:    CLOBBERs that need to be added (it should be initialized to zero by
        !            40:    the caller).  If it is set nonzero, the caller should allocate a
        !            41:    PARALLEL of the appropriate size, copy the initial entries, and call
        !            42:    add_clobbers (found in insn-emit.c) to fill in the CLOBBERs.
        !            43: 
        !            44:    This program also generates the function `split_insns',
        !            45:    which returns 0 if the rtl could not be split, or
        !            46:    it returns the split rtl in a SEQUENCE.  */
        !            47: 
        !            48: #include <stdio.h>
        !            49: #include "hconfig.h"
        !            50: #include "rtl.h"
        !            51: #include "obstack.h"
        !            52: 
        !            53: static struct obstack obstack;
        !            54: struct obstack *rtl_obstack = &obstack;
        !            55: 
        !            56: #define obstack_chunk_alloc xmalloc
        !            57: #define obstack_chunk_free free
        !            58: 
        !            59: extern void free ();
        !            60: extern rtx read_rtx ();
        !            61: 
        !            62: /* Data structure for a listhead of decision trees.  The alternatives
        !            63:    to a node are kept in a doublely-linked list so we can easily add nodes
        !            64:    to the proper place when merging.  */
        !            65: 
        !            66: struct decision_head { struct decision *first, *last; };
        !            67: 
        !            68: /* Data structure for decision tree for recognizing
        !            69:    legitimate instructions.  */
        !            70: 
        !            71: struct decision
        !            72: {
        !            73:   int number;                  /* Node number, used for labels */
        !            74:   char *position;              /* String denoting position in pattern */
        !            75:   RTX_CODE code;               /* Code to test for or UNKNOWN to suppress */
        !            76:   char ignore_code;            /* If non-zero, need not test code */
        !            77:   char ignore_mode;            /* If non-zero, need not test mode */
        !            78:   int veclen;                  /* Length of vector, if nonzero */
        !            79:   enum machine_mode mode;      /* Machine mode of node */
        !            80:   char enforce_mode;           /* If non-zero, test `mode' */
        !            81:   char retest_code, retest_mode; /* See write_tree_1 */
        !            82:   int test_elt_zero_int;       /* Nonzero if should test XINT (rtl, 0) */
        !            83:   int elt_zero_int;            /* Required value for XINT (rtl, 0) */
        !            84:   int test_elt_one_int;                /* Nonzero if should test XINT (rtl, 1) */
        !            85:   int elt_one_int;             /* Required value for XINT (rtl, 1) */
        !            86:   int test_elt_zero_wide;      /* Nonzero if should test XWINT (rtl, 0) */
        !            87:   HOST_WIDE_INT elt_zero_wide; /* Required value for XWINT (rtl, 0) */
        !            88:   char *tests;                 /* If nonzero predicate to call */
        !            89:   int pred;                    /* `preds' index of predicate or -1 */
        !            90:   char *c_test;                        /* Additional test to perform */
        !            91:   struct decision_head success;        /* Nodes to test on success */
        !            92:   int insn_code_number;                /* Insn number matched, if success */
        !            93:   int num_clobbers_to_add;     /* Number of CLOBBERs to be added to pattern */
        !            94:   struct decision *next;       /* Node to test on failure */
        !            95:   struct decision *prev;       /* Node whose failure tests us */
        !            96:   struct decision *afterward;  /* Node to test on success, but failure of
        !            97:                                   successor nodes */
        !            98:   int opno;                    /* Operand number, if >= 0 */
        !            99:   int dupno;                   /* Number of operand to compare against */
        !           100:   int label_needed;            /* Nonzero if label needed when writing tree */
        !           101:   int subroutine_number;       /* Number of subroutine this node starts */
        !           102: };
        !           103: 
        !           104: #define SUBROUTINE_THRESHOLD 50
        !           105: 
        !           106: static int next_subroutine_number;
        !           107: 
        !           108: /* We can write two types of subroutines: One for insn recognition and
        !           109:    one to split insns.  This defines which type is being written.  */
        !           110: 
        !           111: enum routine_type {RECOG, SPLIT};
        !           112: 
        !           113: /* Next available node number for tree nodes.  */
        !           114: 
        !           115: static int next_number;
        !           116: 
        !           117: /* Next number to use as an insn_code.  */
        !           118: 
        !           119: static int next_insn_code;
        !           120: 
        !           121: /* Similar, but counts all expressions in the MD file; used for
        !           122:    error messages. */
        !           123: 
        !           124: static int next_index;
        !           125: 
        !           126: /* Record the highest depth we ever have so we know how many variables to
        !           127:    allocate in each subroutine we make.  */
        !           128: 
        !           129: static int max_depth;
        !           130: 
        !           131: /* This table contains a list of the rtl codes that can possibly match a
        !           132:    predicate defined in recog.c.  The function `not_both_true' uses it to
        !           133:    deduce that there are no expressions that can be matches by certain pairs
        !           134:    of tree nodes.  Also, if a predicate can match only one code, we can
        !           135:    hardwire that code into the node testing the predicate.  */
        !           136: 
        !           137: static struct pred_table
        !           138: {
        !           139:   char *name;
        !           140:   RTX_CODE codes[NUM_RTX_CODE];
        !           141: } preds[]
        !           142:   = {{"general_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
        !           143:                          LABEL_REF, SUBREG, REG, MEM}},
        !           144: #ifdef PREDICATE_CODES
        !           145:      PREDICATE_CODES
        !           146: #endif
        !           147:      {"address_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
        !           148:                          LABEL_REF, SUBREG, REG, MEM, PLUS, MINUS, MULT}},
        !           149:      {"register_operand", {SUBREG, REG}},
        !           150:      {"scratch_operand", {SCRATCH, REG}},
        !           151:      {"immediate_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
        !           152:                            LABEL_REF}},
        !           153:      {"const_int_operand", {CONST_INT}},
        !           154:      {"const_double_operand", {CONST_INT, CONST_DOUBLE}},
        !           155:      {"nonimmediate_operand", {SUBREG, REG, MEM}},
        !           156:      {"nonmemory_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
        !           157:                            LABEL_REF, SUBREG, REG}},
        !           158:      {"push_operand", {MEM}},
        !           159:      {"memory_operand", {SUBREG, MEM}},
        !           160:      {"indirect_operand", {SUBREG, MEM}},
        !           161:      {"comparison_operator", {EQ, NE, LE, LT, GE, GT, LEU, LTU, GEU, GTU}},
        !           162:      {"mode_independent_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
        !           163:                                   LABEL_REF, SUBREG, REG, MEM}}};
        !           164: 
        !           165: #define NUM_KNOWN_PREDS (sizeof preds / sizeof preds[0])
        !           166: 
        !           167: static struct decision_head make_insn_sequence PROTO((rtx, enum routine_type));
        !           168: static struct decision *add_to_sequence PROTO((rtx, struct decision_head *,
        !           169:                                               char *));
        !           170: static int not_both_true       PROTO((struct decision *, struct decision *,
        !           171:                                       int));
        !           172: static int position_merit      PROTO((struct decision *, enum machine_mode,
        !           173:                                       enum rtx_code));
        !           174: static struct decision_head merge_trees PROTO((struct decision_head,
        !           175:                                               struct decision_head));
        !           176: static int break_out_subroutines PROTO((struct decision_head,
        !           177:                                        enum routine_type, int));
        !           178: static void write_subroutine   PROTO((struct decision *, enum routine_type));
        !           179: static void write_tree_1       PROTO((struct decision *, char *,
        !           180:                                       struct decision *, enum routine_type));
        !           181: static void print_code         PROTO((enum rtx_code));
        !           182: static int same_codes          PROTO((struct decision *, enum rtx_code));
        !           183: static void clear_codes                PROTO((struct decision *));
        !           184: static int same_modes          PROTO((struct decision *, enum machine_mode));
        !           185: static void clear_modes                PROTO((struct decision *));
        !           186: static void write_tree         PROTO((struct decision *, char *,
        !           187:                                       struct decision *, int,
        !           188:                                       enum routine_type));
        !           189: static void change_state       PROTO((char *, char *, int));
        !           190: static char *copystr           PROTO((char *));
        !           191: static void mybzero            PROTO((char *, unsigned));
        !           192: static void mybcopy            PROTO((char *, char *, unsigned));
        !           193: static char *concat            PROTO((char *, char *));
        !           194: static void fatal              PROTO((char *));
        !           195: char *xrealloc                 PROTO((char *, unsigned));
        !           196: char *xmalloc                  PROTO((unsigned));
        !           197: void fancy_abort               PROTO((void));
        !           198: 
        !           199: /* Construct and return a sequence of decisions
        !           200:    that will recognize INSN.
        !           201: 
        !           202:    TYPE says what type of routine we are recognizing (RECOG or SPLIT).  */
        !           203: 
        !           204: static struct decision_head
        !           205: make_insn_sequence (insn, type)
        !           206:      rtx insn;
        !           207:      enum routine_type type;
        !           208: {
        !           209:   rtx x;
        !           210:   char *c_test = XSTR (insn, type == RECOG ? 2 : 1);
        !           211:   struct decision *last;
        !           212:   struct decision_head head;
        !           213: 
        !           214:   if (XVECLEN (insn, type == RECOG) == 1)
        !           215:     x = XVECEXP (insn, type == RECOG, 0);
        !           216:   else
        !           217:     {
        !           218:       x = rtx_alloc (PARALLEL);
        !           219:       XVEC (x, 0) = XVEC (insn, type == RECOG);
        !           220:       PUT_MODE (x, VOIDmode);
        !           221:     }
        !           222: 
        !           223:   last = add_to_sequence (x, &head, "");
        !           224: 
        !           225:   if (c_test[0])
        !           226:     last->c_test = c_test;
        !           227:   last->insn_code_number = next_insn_code;
        !           228:   last->num_clobbers_to_add = 0;
        !           229: 
        !           230:   /* If this is not a DEFINE_SPLIT and X is a PARALLEL, see if it ends with a
        !           231:      group of CLOBBERs of (hard) registers or MATCH_SCRATCHes.  If so, set up
        !           232:      to recognize the pattern without these CLOBBERs.  */
        !           233: 
        !           234:   if (type == RECOG && GET_CODE (x) == PARALLEL)
        !           235:     {
        !           236:       int i;
        !           237: 
        !           238:       for (i = XVECLEN (x, 0); i > 0; i--)
        !           239:        if (GET_CODE (XVECEXP (x, 0, i - 1)) != CLOBBER
        !           240:            || (GET_CODE (XEXP (XVECEXP (x, 0, i - 1), 0)) != REG
        !           241:                && GET_CODE (XEXP (XVECEXP (x, 0, i - 1), 0)) != MATCH_SCRATCH))
        !           242:          break;
        !           243: 
        !           244:       if (i != XVECLEN (x, 0))
        !           245:        {
        !           246:          rtx new;
        !           247:          struct decision_head clobber_head;
        !           248: 
        !           249:          if (i == 1)
        !           250:            new = XVECEXP (x, 0, 0);
        !           251:          else
        !           252:            {
        !           253:              int j;
        !           254: 
        !           255:              new = rtx_alloc (PARALLEL);
        !           256:              XVEC (new, 0) = rtvec_alloc (i);
        !           257:              for (j = i - 1; j >= 0; j--)
        !           258:                XVECEXP (new, 0, j) = XVECEXP (x, 0, j);
        !           259:            }
        !           260: 
        !           261:          last = add_to_sequence (new, &clobber_head, "");
        !           262: 
        !           263:          if (c_test[0])
        !           264:            last->c_test = c_test;
        !           265:          last->insn_code_number = next_insn_code;
        !           266:          last->num_clobbers_to_add = XVECLEN (x, 0) - i;
        !           267: 
        !           268:          head = merge_trees (head, clobber_head);
        !           269:        }
        !           270:     }
        !           271: 
        !           272:   next_insn_code++;
        !           273: 
        !           274:   if (type == SPLIT)
        !           275:     /* Define the subroutine we will call below and emit in genemit.  */
        !           276:     printf ("extern rtx gen_split_%d ();\n", last->insn_code_number);
        !           277: 
        !           278:   return head;
        !           279: }
        !           280: 
        !           281: /* Create a chain of nodes to verify that an rtl expression matches
        !           282:    PATTERN.
        !           283: 
        !           284:    LAST is a pointer to the listhead in the previous node in the chain (or
        !           285:    in the calling function, for the first node).
        !           286: 
        !           287:    POSITION is the string representing the current position in the insn.
        !           288: 
        !           289:    A pointer to the final node in the chain is returned.  */
        !           290: 
        !           291: static struct decision *
        !           292: add_to_sequence (pattern, last, position)
        !           293:      rtx pattern;
        !           294:      struct decision_head *last;
        !           295:      char *position;
        !           296: {
        !           297:   register RTX_CODE code;
        !           298:   register struct decision *new
        !           299:     = (struct decision *) xmalloc (sizeof (struct decision));
        !           300:   struct decision *this;
        !           301:   char *newpos;
        !           302:   register char *fmt;
        !           303:   register int i;
        !           304:   int depth = strlen (position);
        !           305:   int len;
        !           306: 
        !           307:   if (depth > max_depth)
        !           308:     max_depth = depth;
        !           309: 
        !           310:   new->number = next_number++;
        !           311:   new->position = copystr (position);
        !           312:   new->ignore_code = 0;
        !           313:   new->ignore_mode = 0;
        !           314:   new->enforce_mode = 1;
        !           315:   new->retest_code = new->retest_mode = 0;
        !           316:   new->veclen = 0;
        !           317:   new->test_elt_zero_int = 0;
        !           318:   new->test_elt_one_int = 0;
        !           319:   new->test_elt_zero_wide = 0;
        !           320:   new->elt_zero_int = 0;
        !           321:   new->elt_one_int = 0;
        !           322:   new->elt_zero_wide = 0;
        !           323:   new->tests = 0;
        !           324:   new->pred = -1;
        !           325:   new->c_test = 0;
        !           326:   new->success.first = new->success.last = 0;
        !           327:   new->insn_code_number = -1;
        !           328:   new->num_clobbers_to_add = 0;
        !           329:   new->next = 0;
        !           330:   new->prev = 0;
        !           331:   new->afterward = 0;
        !           332:   new->opno = -1;
        !           333:   new->dupno = -1;
        !           334:   new->label_needed = 0;
        !           335:   new->subroutine_number = 0;
        !           336: 
        !           337:   this = new;
        !           338: 
        !           339:   last->first = last->last = new;
        !           340: 
        !           341:   newpos = (char *) alloca (depth + 2);
        !           342:   strcpy (newpos, position);
        !           343:   newpos[depth + 1] = 0;
        !           344: 
        !           345:  restart:
        !           346: 
        !           347:   new->mode = GET_MODE (pattern);
        !           348:   new->code = code = GET_CODE (pattern);
        !           349: 
        !           350:   switch (code)
        !           351:     {
        !           352:     case MATCH_OPERAND:
        !           353:     case MATCH_SCRATCH:
        !           354:     case MATCH_OPERATOR:
        !           355:     case MATCH_PARALLEL:
        !           356:       new->opno = XINT (pattern, 0);
        !           357:       new->code = (code == MATCH_PARALLEL ? PARALLEL : UNKNOWN);
        !           358:       new->enforce_mode = 0;
        !           359: 
        !           360:       if (code == MATCH_SCRATCH)
        !           361:        new->tests = "scratch_operand";
        !           362:       else
        !           363:        new->tests = XSTR (pattern, 1);
        !           364: 
        !           365:       if (*new->tests == 0)
        !           366:        new->tests = 0;
        !           367: 
        !           368:       /* See if we know about this predicate and save its number.  If we do,
        !           369:         and it only accepts one code, note that fact.  The predicate
        !           370:         `const_int_operand' only tests for a CONST_INT, so if we do so we
        !           371:         can avoid calling it at all.
        !           372: 
        !           373:         Finally, if we know that the predicate does not allow CONST_INT, we
        !           374:         know that the only way the predicate can match is if the modes match
        !           375:         (here we use the kluge of relying on the fact that "address_operand"
        !           376:         accepts CONST_INT; otherwise, it would have to be a special case),
        !           377:         so we can test the mode (but we need not).  This fact should
        !           378:         considerably simplify the generated code.  */
        !           379: 
        !           380:       if (new->tests)
        !           381:        {
        !           382:          for (i = 0; i < NUM_KNOWN_PREDS; i++)
        !           383:            if (! strcmp (preds[i].name, new->tests))
        !           384:              {
        !           385:                int j;
        !           386:                int allows_const_int = 0;
        !           387: 
        !           388:                new->pred = i;
        !           389: 
        !           390:                if (preds[i].codes[1] == 0 && new->code == UNKNOWN)
        !           391:                  {
        !           392:                    new->code = preds[i].codes[0];
        !           393:                    if (! strcmp ("const_int_operand", new->tests))
        !           394:                      new->tests = 0, new->pred = -1;
        !           395:                  }
        !           396: 
        !           397:                for (j = 0; j < NUM_RTX_CODE && preds[i].codes[j] != 0; j++)
        !           398:                  if (preds[i].codes[j] == CONST_INT)
        !           399:                    allows_const_int = 1;
        !           400: 
        !           401:                if (! allows_const_int)
        !           402:                  new->enforce_mode = new->ignore_mode= 1;
        !           403: 
        !           404:                break;
        !           405:              }
        !           406: 
        !           407: #ifdef PREDICATE_CODES
        !           408:          /* If the port has a list of the predicates it uses but omits
        !           409:             one, warn.  */
        !           410:          if (i == NUM_KNOWN_PREDS)
        !           411:            fprintf (stderr, "Warning: `%s' not in PREDICATE_CODES\n",
        !           412:                     new->tests);
        !           413: #endif
        !           414:        }
        !           415: 
        !           416:       if (code == MATCH_OPERATOR || code == MATCH_PARALLEL)
        !           417:        {
        !           418:          for (i = 0; i < XVECLEN (pattern, 2); i++)
        !           419:            {
        !           420:              newpos[depth] = i + (code == MATCH_OPERATOR ? '0': 'a');
        !           421:              new = add_to_sequence (XVECEXP (pattern, 2, i),
        !           422:                                     &new->success, newpos);
        !           423:            }
        !           424:        }
        !           425: 
        !           426:       return new;
        !           427: 
        !           428:     case MATCH_OP_DUP:
        !           429:       new->opno = XINT (pattern, 0);
        !           430:       new->dupno = XINT (pattern, 0);
        !           431:       new->code = UNKNOWN;
        !           432:       new->tests = 0;
        !           433:       for (i = 0; i < XVECLEN (pattern, 1); i++)
        !           434:        {
        !           435:          newpos[depth] = i + '0';
        !           436:          new = add_to_sequence (XVECEXP (pattern, 1, i),
        !           437:                                 &new->success, newpos);
        !           438:        }
        !           439:       return new;
        !           440: 
        !           441:     case MATCH_DUP:
        !           442:     case MATCH_PAR_DUP:
        !           443:       new->dupno = XINT (pattern, 0);
        !           444:       new->code = UNKNOWN;
        !           445:       new->enforce_mode = 0;
        !           446:       return new;
        !           447: 
        !           448:     case ADDRESS:
        !           449:       pattern = XEXP (pattern, 0);
        !           450:       goto restart;
        !           451: 
        !           452:     case SET:
        !           453:       newpos[depth] = '0';
        !           454:       new = add_to_sequence (SET_DEST (pattern), &new->success, newpos);
        !           455:       this->success.first->enforce_mode = 1;
        !           456:       newpos[depth] = '1';
        !           457:       new = add_to_sequence (SET_SRC (pattern), &new->success, newpos);
        !           458: 
        !           459:       /* If set are setting CC0 from anything other than a COMPARE, we
        !           460:         must enforce the mode so that we do not produce ambiguous insns.  */
        !           461:       if (GET_CODE (SET_DEST (pattern)) == CC0
        !           462:          && GET_CODE (SET_SRC (pattern)) != COMPARE)
        !           463:        this->success.first->enforce_mode = 1;
        !           464:       return new;
        !           465: 
        !           466:     case SIGN_EXTEND:
        !           467:     case ZERO_EXTEND:
        !           468:     case STRICT_LOW_PART:
        !           469:       newpos[depth] = '0';
        !           470:       new = add_to_sequence (XEXP (pattern, 0), &new->success, newpos);
        !           471:       this->success.first->enforce_mode = 1;
        !           472:       return new;
        !           473: 
        !           474:     case SUBREG:
        !           475:       this->test_elt_one_int = 1;
        !           476:       this->elt_one_int = XINT (pattern, 1);
        !           477:       newpos[depth] = '0';
        !           478:       new = add_to_sequence (XEXP (pattern, 0), &new->success, newpos);
        !           479:       this->success.first->enforce_mode = 1;
        !           480:       return new;
        !           481: 
        !           482:     case ZERO_EXTRACT:
        !           483:     case SIGN_EXTRACT:
        !           484:       newpos[depth] = '0';
        !           485:       new = add_to_sequence (XEXP (pattern, 0), &new->success, newpos);
        !           486:       this->success.first->enforce_mode = 1;
        !           487:       newpos[depth] = '1';
        !           488:       new = add_to_sequence (XEXP (pattern, 1), &new->success, newpos);
        !           489:       newpos[depth] = '2';
        !           490:       new = add_to_sequence (XEXP (pattern, 2), &new->success, newpos);
        !           491:       return new;
        !           492: 
        !           493:     case EQ:   case NE:   case LE:   case LT:   case GE:  case GT:
        !           494:     case LEU:  case LTU:  case GEU:  case GTU:
        !           495:       /* If the first operand is (cc0), we don't have to do anything
        !           496:         special.  */
        !           497:       if (GET_CODE (XEXP (pattern, 0)) == CC0)
        !           498:        break;
        !           499: 
        !           500:       /* ... fall through ... */
        !           501:       
        !           502:     case COMPARE:
        !           503:       /* Enforce the mode on the first operand to avoid ambiguous insns.  */
        !           504:       newpos[depth] = '0';
        !           505:       new = add_to_sequence (XEXP (pattern, 0), &new->success, newpos);
        !           506:       this->success.first->enforce_mode = 1;
        !           507:       newpos[depth] = '1';
        !           508:       new = add_to_sequence (XEXP (pattern, 1), &new->success, newpos);
        !           509:       return new;
        !           510:     }
        !           511: 
        !           512:   fmt = GET_RTX_FORMAT (code);
        !           513:   len = GET_RTX_LENGTH (code);
        !           514:   for (i = 0; i < len; i++)
        !           515:     {
        !           516:       newpos[depth] = '0' + i;
        !           517:       if (fmt[i] == 'e' || fmt[i] == 'u')
        !           518:        new = add_to_sequence (XEXP (pattern, i), &new->success, newpos);
        !           519:       else if (fmt[i] == 'i' && i == 0)
        !           520:        {
        !           521:          this->test_elt_zero_int = 1;
        !           522:          this->elt_zero_int = XINT (pattern, i);
        !           523:        }
        !           524:       else if (fmt[i] == 'i' && i == 1)
        !           525:        {
        !           526:          this->test_elt_one_int = 1;
        !           527:          this->elt_one_int = XINT (pattern, i);
        !           528:        }
        !           529:       else if (fmt[i] == 'w' && i == 0)
        !           530:        {
        !           531:          this->test_elt_zero_wide = 1;
        !           532:          this->elt_zero_wide = XWINT (pattern, i);
        !           533:        }
        !           534:       else if (fmt[i] == 'E')
        !           535:        {
        !           536:          register int j;
        !           537:          /* We do not handle a vector appearing as other than
        !           538:             the first item, just because nothing uses them
        !           539:             and by handling only the special case
        !           540:             we can use one element in newpos for either
        !           541:             the item number of a subexpression
        !           542:             or the element number in a vector.  */
        !           543:          if (i != 0)
        !           544:            abort ();
        !           545:          this->veclen = XVECLEN (pattern, i);
        !           546:          for (j = 0; j < XVECLEN (pattern, i); j++)
        !           547:            {
        !           548:              newpos[depth] = 'a' + j;
        !           549:              new = add_to_sequence (XVECEXP (pattern, i, j),
        !           550:                                     &new->success, newpos);
        !           551:            }
        !           552:        }
        !           553:       else if (fmt[i] != '0')
        !           554:        abort ();
        !           555:     }
        !           556:   return new;
        !           557: }
        !           558: 
        !           559: /* Return 1 if we can prove that there is no RTL that can match both
        !           560:    D1 and D2.  Otherwise, return 0 (it may be that there is an RTL that
        !           561:    can match both or just that we couldn't prove there wasn't such an RTL).
        !           562: 
        !           563:    TOPLEVEL is non-zero if we are to only look at the top level and not
        !           564:    recursively descend.  */
        !           565: 
        !           566: static int
        !           567: not_both_true (d1, d2, toplevel)
        !           568:      struct decision *d1, *d2;
        !           569:      int toplevel;
        !           570: {
        !           571:   struct decision *p1, *p2;
        !           572: 
        !           573:   /* If they are both to test modes and the modes are different, they aren't
        !           574:      both true.  Similarly for codes, integer elements, and vector lengths. */
        !           575: 
        !           576:   if ((d1->enforce_mode && d2->enforce_mode
        !           577:        && d1->mode != VOIDmode && d2->mode != VOIDmode && d1->mode != d2->mode)
        !           578:       || (d1->code != UNKNOWN && d2->code != UNKNOWN && d1->code != d2->code)
        !           579:       || (d1->test_elt_zero_int && d2->test_elt_zero_int
        !           580:          && d1->elt_zero_int != d2->elt_zero_int)
        !           581:       || (d1->test_elt_one_int && d2->test_elt_one_int
        !           582:          && d1->elt_one_int != d2->elt_one_int)
        !           583:       || (d1->test_elt_zero_wide && d2->test_elt_zero_wide
        !           584:          && d1->elt_zero_wide != d2->elt_zero_wide)
        !           585:       || (d1->veclen && d2->veclen && d1->veclen != d2->veclen))
        !           586:     return 1;
        !           587: 
        !           588:   /* If either is a wild-card MATCH_OPERAND without a predicate, it can match
        !           589:      absolutely anything, so we can't say that no intersection is possible.
        !           590:      This case is detected by having a zero TESTS field with a code of
        !           591:      UNKNOWN.  */
        !           592: 
        !           593:   if ((d1->tests == 0 && d1->code == UNKNOWN)
        !           594:       || (d2->tests == 0 && d2->code == UNKNOWN))
        !           595:     return 0;
        !           596: 
        !           597:   /* If either has a predicate that we know something about, set things up so
        !           598:      that D1 is the one that always has a known predicate.  Then see if they
        !           599:      have any codes in common.  */
        !           600: 
        !           601:   if (d1->pred >= 0 || d2->pred >= 0)
        !           602:     {
        !           603:       int i, j;
        !           604: 
        !           605:       if (d2->pred >= 0)
        !           606:        p1 = d1, d1 = d2, d2 = p1;
        !           607: 
        !           608:       /* If D2 tests an explicit code, see if it is in the list of valid codes
        !           609:         for D1's predicate.  */
        !           610:       if (d2->code != UNKNOWN)
        !           611:        {
        !           612:          for (i = 0; i < NUM_RTX_CODE && preds[d1->pred].codes[i] != 0; i++)
        !           613:            if (preds[d1->pred].codes[i] == d2->code)
        !           614:              break;
        !           615: 
        !           616:          if (preds[d1->pred].codes[i] == 0)
        !           617:            return 1;
        !           618:        }
        !           619: 
        !           620:       /* Otherwise see if the predicates have any codes in common.  */
        !           621: 
        !           622:       else if (d2->pred >= 0)
        !           623:        {
        !           624:          for (i = 0; i < NUM_RTX_CODE && preds[d1->pred].codes[i] != 0; i++)
        !           625:            {
        !           626:              for (j = 0; j < NUM_RTX_CODE; j++)
        !           627:                if (preds[d2->pred].codes[j] == 0
        !           628:                    || preds[d2->pred].codes[j] == preds[d1->pred].codes[i])
        !           629:                  break;
        !           630: 
        !           631:              if (preds[d2->pred].codes[j] != 0)
        !           632:                break;
        !           633:            }
        !           634: 
        !           635:          if (preds[d1->pred].codes[i] == 0)
        !           636:            return 1;
        !           637:        }
        !           638:     }
        !           639: 
        !           640:   /* If we got here, we can't prove that D1 and D2 cannot both be true.
        !           641:      If we are only to check the top level, return 0.  Otherwise, see if
        !           642:      we can prove that all choices in both successors are mutually
        !           643:      exclusive.  If either does not have any successors, we can't prove
        !           644:      they can't both be true.  */
        !           645: 
        !           646:   if (toplevel || d1->success.first == 0 || d2->success.first == 0)
        !           647:     return 0;
        !           648: 
        !           649:   for (p1 = d1->success.first; p1; p1 = p1->next)
        !           650:     for (p2 = d2->success.first; p2; p2 = p2->next)
        !           651:       if (! not_both_true (p1, p2, 0))
        !           652:        return 0;
        !           653: 
        !           654:   return 1;
        !           655: }
        !           656: 
        !           657: /* Assuming that we can reorder all the alternatives at a specific point in
        !           658:    the tree (see discussion in merge_trees), we would prefer an ordering of
        !           659:    nodes where groups of consecutive nodes test the same mode and, within each
        !           660:    mode, groups of nodes test the same code.  With this order, we can
        !           661:    construct nested switch statements, the inner one to test the code and
        !           662:    the outer one to test the mode.
        !           663: 
        !           664:    We would like to list nodes testing for specific codes before those
        !           665:    that test predicates to avoid unnecessary function calls.  Similarly,
        !           666:    tests for specific modes should precede nodes that allow any mode.
        !           667: 
        !           668:    This function returns the merit (with 0 being the best) of inserting
        !           669:    a test involving the specified MODE and CODE after node P.  If P is
        !           670:    zero, we are to determine the merit of inserting the test at the front
        !           671:    of the list.  */
        !           672: 
        !           673: static int
        !           674: position_merit (p, mode, code)
        !           675:      struct decision *p;
        !           676:      enum machine_mode mode;
        !           677:      enum rtx_code code;
        !           678: {
        !           679:   enum machine_mode p_mode;
        !           680: 
        !           681:   /* The only time the front of the list is anything other than the worst
        !           682:      position is if we are testing a mode that isn't VOIDmode.  */
        !           683:   if (p == 0)
        !           684:     return mode == VOIDmode ? 3 : 2;
        !           685: 
        !           686:   p_mode = p->enforce_mode ? p->mode : VOIDmode;
        !           687: 
        !           688:   /* The best case is if the codes and modes both match.  */
        !           689:   if (p_mode == mode && p->code== code)
        !           690:     return 0;
        !           691: 
        !           692:   /* If the codes don't match, the next best case is if the modes match.
        !           693:      In that case, the best position for this node depends on whether
        !           694:      we are testing for a specific code or not.  If we are, the best place
        !           695:      is after some other test for an explicit code and our mode or after
        !           696:      the last test in the previous mode if every test in our mode is for
        !           697:      an unknown code.
        !           698: 
        !           699:      If we are testing for UNKNOWN, then the next best case is at the end of
        !           700:      our mode.  */
        !           701: 
        !           702:   if ((code != UNKNOWN
        !           703:        && ((p_mode == mode && p->code != UNKNOWN)
        !           704:           || (p_mode != mode && p->next
        !           705:               && (p->next->enforce_mode ? p->next->mode : VOIDmode) == mode
        !           706:               && (p->next->code == UNKNOWN))))
        !           707:       || (code == UNKNOWN && p_mode == mode
        !           708:          && (p->next == 0
        !           709:              || (p->next->enforce_mode ? p->next->mode : VOIDmode) != mode)))
        !           710:     return 1;
        !           711: 
        !           712:   /* The third best case occurs when nothing is testing MODE.  If MODE
        !           713:      is not VOIDmode, then the third best case is after something of any
        !           714:      mode that is not VOIDmode.  If we are testing VOIDmode, the third best
        !           715:      place is the end of the list.  */
        !           716: 
        !           717:   if (p_mode != mode
        !           718:       && ((mode != VOIDmode && p_mode != VOIDmode)
        !           719:          || (mode == VOIDmode && p->next == 0)))
        !           720:     return 2;
        !           721: 
        !           722:   /* Otherwise, we have the worst case.  */
        !           723:   return 3;
        !           724: }
        !           725: 
        !           726: /* Merge two decision tree listheads OLDH and ADDH,
        !           727:    modifying OLDH destructively, and return the merged tree.  */
        !           728: 
        !           729: static struct decision_head
        !           730: merge_trees (oldh, addh)
        !           731:      register struct decision_head oldh, addh;
        !           732: {
        !           733:   struct decision *add, *next;
        !           734: 
        !           735:   if (oldh.first == 0)
        !           736:     return addh;
        !           737: 
        !           738:   if (addh.first == 0)
        !           739:     return oldh;
        !           740: 
        !           741:   /* If we are adding things at different positions, something is wrong.  */
        !           742:   if (strcmp (oldh.first->position, addh.first->position))
        !           743:     abort ();
        !           744: 
        !           745:   for (add = addh.first; add; add = next)
        !           746:     {
        !           747:       enum machine_mode add_mode = add->enforce_mode ? add->mode : VOIDmode;
        !           748:       struct decision *best_position = 0;
        !           749:       int best_merit = 4;
        !           750:       struct decision *old;
        !           751: 
        !           752:       next = add->next;
        !           753: 
        !           754:       /* The semantics of pattern matching state that the tests are done in
        !           755:         the order given in the MD file so that if an insn matches two
        !           756:         patterns, the first one will be used.  However, in practice, most,
        !           757:         if not all, patterns are unambiguous so that their order is 
        !           758:         independent.  In that case, we can merge identical tests and
        !           759:         group all similar modes and codes together.
        !           760: 
        !           761:         Scan starting from the end of OLDH until we reach a point
        !           762:         where we reach the head of the list or where we pass a pattern
        !           763:         that could also be true if NEW is true.  If we find an identical
        !           764:         pattern, we can merge them.  Also, record the last node that tests
        !           765:         the same code and mode and the last one that tests just the same mode.
        !           766: 
        !           767:         If we have no match, place NEW after the closest match we found.  */
        !           768:         
        !           769:       for (old = oldh.last; old; old = old->prev)
        !           770:        {
        !           771:          int our_merit;
        !           772: 
        !           773:          /* If we don't have anything to test except an additional test,
        !           774:             do not consider the two nodes equal.  If we did, the test below
        !           775:             would cause an infinite recursion.  */
        !           776:          if (old->tests == 0 && old->test_elt_zero_int == 0
        !           777:              && old->test_elt_one_int == 0 && old->veclen == 0
        !           778:              && old->test_elt_zero_wide == 0
        !           779:              && old->dupno == -1 && old->mode == VOIDmode
        !           780:              && old->code == UNKNOWN
        !           781:              && (old->c_test != 0 || add->c_test != 0))
        !           782:            ;
        !           783: 
        !           784:          else if ((old->tests == add->tests
        !           785:                    || (old->pred >= 0 && old->pred == add->pred)
        !           786:                    || (old->tests && add->tests
        !           787:                        && !strcmp (old->tests, add->tests)))
        !           788:                   && old->test_elt_zero_int == add->test_elt_zero_int
        !           789:                   && old->elt_zero_int == add->elt_zero_int
        !           790:                   && old->test_elt_one_int == add->test_elt_one_int
        !           791:                   && old->elt_one_int == add->elt_one_int
        !           792:                   && old->test_elt_zero_wide == add->test_elt_zero_wide
        !           793:                   && old->elt_zero_wide == add->elt_zero_wide
        !           794:                   && old->veclen == add->veclen
        !           795:                   && old->dupno == add->dupno
        !           796:                   && old->opno == add->opno
        !           797:                   && old->code == add->code
        !           798:                   && old->enforce_mode == add->enforce_mode
        !           799:                   && old->mode == add->mode)
        !           800:            {
        !           801:              /* If the additional test is not the same, split both nodes
        !           802:                 into nodes that just contain all things tested before the
        !           803:                 additional test and nodes that contain the additional test
        !           804:                 and actions when it is true.  This optimization is important
        !           805:                 because of the case where we have almost identical patterns
        !           806:                 with different tests on target flags.  */
        !           807: 
        !           808:              if (old->c_test != add->c_test
        !           809:                  && ! (old->c_test && add->c_test
        !           810:                        && !strcmp (old->c_test, add->c_test)))
        !           811:                {
        !           812:                  if (old->insn_code_number >= 0 || old->opno >= 0)
        !           813:                    {
        !           814:                      struct decision *split
        !           815:                        = (struct decision *) xmalloc (sizeof (struct decision));
        !           816: 
        !           817:                      mybcopy ((char *) old, (char *) split,
        !           818:                               sizeof (struct decision));
        !           819: 
        !           820:                      old->success.first = old->success.last = split;
        !           821:                      old->c_test = 0;
        !           822:                      old->opno = -1;
        !           823:                      old->insn_code_number = -1;
        !           824:                      old->num_clobbers_to_add = 0;
        !           825: 
        !           826:                      split->number = next_number++;
        !           827:                      split->next = split->prev = 0;
        !           828:                      split->mode = VOIDmode;
        !           829:                      split->code = UNKNOWN;
        !           830:                      split->veclen = 0;
        !           831:                      split->test_elt_zero_int = 0;
        !           832:                      split->test_elt_one_int = 0;
        !           833:                      split->test_elt_zero_wide = 0;
        !           834:                      split->tests = 0;
        !           835:                      split->pred = -1;
        !           836:                      split->dupno = -1;
        !           837:                    }
        !           838: 
        !           839:                  if (add->insn_code_number >= 0 || add->opno >= 0)
        !           840:                    {
        !           841:                      struct decision *split
        !           842:                        = (struct decision *) xmalloc (sizeof (struct decision));
        !           843: 
        !           844:                      mybcopy ((char *) add, (char *) split,
        !           845:                               sizeof (struct decision));
        !           846: 
        !           847:                      add->success.first = add->success.last = split;
        !           848:                      add->c_test = 0;
        !           849:                      add->opno = -1;
        !           850:                      add->insn_code_number = -1;
        !           851:                      add->num_clobbers_to_add = 0;
        !           852: 
        !           853:                      split->number = next_number++;
        !           854:                      split->next = split->prev = 0;
        !           855:                      split->mode = VOIDmode;
        !           856:                      split->code = UNKNOWN;
        !           857:                      split->veclen = 0;
        !           858:                      split->test_elt_zero_int = 0;
        !           859:                      split->test_elt_one_int = 0;
        !           860:                      split->test_elt_zero_wide = 0;
        !           861:                      split->tests = 0;
        !           862:                      split->pred = -1;
        !           863:                      split->dupno = -1;
        !           864:                    }
        !           865:                }
        !           866: 
        !           867:              if (old->insn_code_number >= 0 && add->insn_code_number >= 0)
        !           868:                {
        !           869:                  /* If one node is for a normal insn and the second is
        !           870:                     for the base insn with clobbers stripped off, the
        !           871:                     second node should be ignored.  */
        !           872: 
        !           873:                  if (old->num_clobbers_to_add == 0
        !           874:                      && add->num_clobbers_to_add > 0)
        !           875:                    /* Nothing to do here.  */
        !           876:                    ;
        !           877:                  else if (old->num_clobbers_to_add > 0
        !           878:                           && add->num_clobbers_to_add == 0)
        !           879:                    {
        !           880:                      /* In this case, replace OLD with ADD.  */
        !           881:                      old->insn_code_number = add->insn_code_number;
        !           882:                      old->num_clobbers_to_add = 0;
        !           883:                    }
        !           884:                  else
        !           885:                    fatal ("Two actions at one point in tree");
        !           886:                }
        !           887: 
        !           888:              if (old->insn_code_number == -1)
        !           889:                old->insn_code_number = add->insn_code_number;
        !           890:              old->success = merge_trees (old->success, add->success);
        !           891:              add = 0;
        !           892:              break;
        !           893:            }
        !           894: 
        !           895:          /* Unless we have already found the best possible insert point,
        !           896:             see if this position is better.  If so, record it.  */
        !           897: 
        !           898:          if (best_merit != 0
        !           899:              && ((our_merit = position_merit (old, add_mode, add->code))
        !           900:                  < best_merit))
        !           901:            best_merit = our_merit, best_position = old;
        !           902: 
        !           903:          if (! not_both_true (old, add, 0))
        !           904:            break;
        !           905:        }
        !           906: 
        !           907:       /* If ADD was duplicate, we are done.  */
        !           908:       if (add == 0)
        !           909:        continue;
        !           910: 
        !           911:       /* Otherwise, find the best place to insert ADD.  Normally this is
        !           912:         BEST_POSITION.  However, if we went all the way to the top of
        !           913:         the list, it might be better to insert at the top.  */
        !           914: 
        !           915:       if (best_position == 0)
        !           916:        abort ();
        !           917: 
        !           918:       if (old == 0
        !           919:          && position_merit (NULL_PTR, add_mode, add->code) < best_merit)
        !           920:        {
        !           921:          add->prev = 0;
        !           922:          add->next = oldh.first;
        !           923:          oldh.first->prev = add;
        !           924:          oldh.first = add;
        !           925:        }
        !           926: 
        !           927:       else
        !           928:        {
        !           929:          add->prev = best_position;
        !           930:          add->next = best_position->next;
        !           931:          best_position->next = add;
        !           932:          if (best_position == oldh.last)
        !           933:            oldh.last = add;
        !           934:          else
        !           935:            add->next->prev = add;
        !           936:        }
        !           937:     }
        !           938: 
        !           939:   return oldh;
        !           940: }
        !           941: 
        !           942: /* Count the number of subnodes of HEAD.  If the number is high enough,
        !           943:    make the first node in HEAD start a separate subroutine in the C code
        !           944:    that is generated.
        !           945: 
        !           946:    TYPE gives the type of routine we are writing.
        !           947: 
        !           948:    INITIAL is non-zero if this is the highest-level node.  We never write
        !           949:    it out here.  */
        !           950: 
        !           951: static int
        !           952: break_out_subroutines (head, type, initial)
        !           953:      struct decision_head head;
        !           954:      enum routine_type type;
        !           955:      int initial;
        !           956: {
        !           957:   int size = 0;
        !           958:   struct decision *node, *sub;
        !           959: 
        !           960:   for (sub = head.first; sub; sub = sub->next)
        !           961:     size += 1 + break_out_subroutines (sub->success, type, 0);
        !           962: 
        !           963:   if (size > SUBROUTINE_THRESHOLD && ! initial)
        !           964:     {
        !           965:       head.first->subroutine_number = ++next_subroutine_number;
        !           966:       write_subroutine (head.first, type);
        !           967:       size = 1;
        !           968:     }
        !           969:   return size;
        !           970: }
        !           971: 
        !           972: /* Write out a subroutine of type TYPE to do comparisons starting at node
        !           973:    TREE.  */
        !           974: 
        !           975: static void
        !           976: write_subroutine (tree, type)
        !           977:      struct decision *tree;
        !           978:      enum routine_type type;
        !           979: {
        !           980:   int i;
        !           981: 
        !           982:   if (type == SPLIT)
        !           983:     printf ("rtx\nsplit");
        !           984:   else
        !           985:     printf ("int\nrecog");
        !           986: 
        !           987:   if (tree != 0 && tree->subroutine_number > 0)
        !           988:     printf ("_%d", tree->subroutine_number);
        !           989:   else if (type == SPLIT)
        !           990:     printf ("_insns");
        !           991: 
        !           992:   printf (" (x0, insn");
        !           993:   if (type == RECOG)
        !           994:     printf (", pnum_clobbers");
        !           995: 
        !           996:   printf (")\n");
        !           997:   printf ("     register rtx x0;\n     rtx insn;\n");
        !           998:   if (type == RECOG)
        !           999:     printf ("     int *pnum_clobbers;\n");
        !          1000: 
        !          1001:   printf ("{\n");
        !          1002:   printf ("  register rtx *ro = &recog_operand[0];\n");
        !          1003: 
        !          1004:   printf ("  register rtx ");
        !          1005:   for (i = 1; i < max_depth; i++)
        !          1006:     printf ("x%d, ", i);
        !          1007: 
        !          1008:   printf ("x%d;\n", max_depth);
        !          1009:   printf ("  %s tem;\n", type == SPLIT ? "rtx" : "int");
        !          1010:   write_tree (tree, "", NULL_PTR, 1, type);
        !          1011:   printf (" ret0: return %d;\n}\n\n", type == SPLIT ? 0 : -1);
        !          1012: }
        !          1013: 
        !          1014: /* This table is used to indent the recog_* functions when we are inside
        !          1015:    conditions or switch statements.  We only support small indentations
        !          1016:    and always indent at least two spaces.  */
        !          1017: 
        !          1018: static char *indents[]
        !          1019:   = {"  ", "  ", "  ", "   ", "    ", "     ", "      ", "       ",
        !          1020:      "\t", "\t ", "\t  ", "\t   ", "\t    ", "\t     ", "\t      ",
        !          1021:      "\t\t", "\t\t ", "\t\t  ", "\t\t   ", "\t\t    ", "\t\t     "};
        !          1022: 
        !          1023: /* Write out C code to perform the decisions in TREE for a subroutine of
        !          1024:    type TYPE.  If all of the choices fail, branch to node AFTERWARD, if
        !          1025:    non-zero, otherwise return.  PREVPOS is the position of the node that
        !          1026:    branched to this test.
        !          1027: 
        !          1028:    When we merged all alternatives, we tried to set up a convenient order.
        !          1029:    Specifically, tests involving the same mode are all grouped together,
        !          1030:    followed by a group that does not contain a mode test.  Within each group
        !          1031:    of the same mode, we also group tests with the same code, followed by a
        !          1032:    group that does not test a code.
        !          1033: 
        !          1034:    Occasionally, we cannot arbitrarily reorder the tests so that multiple
        !          1035:    sequence of groups as described above are present.
        !          1036: 
        !          1037:    We generate two nested switch statements, the outer statement for
        !          1038:    testing modes, and the inner switch for testing RTX codes.  It is
        !          1039:    not worth optimizing cases when only a small number of modes or 
        !          1040:    codes is tested, since the compiler can do that when compiling the
        !          1041:    resulting function.   We do check for when every test is the same mode
        !          1042:    or code.  */
        !          1043: 
        !          1044: static void
        !          1045: write_tree_1 (tree, prevpos, afterward, type)
        !          1046:      struct decision *tree;
        !          1047:      char *prevpos;
        !          1048:      struct decision *afterward;
        !          1049:      enum routine_type type;
        !          1050: {
        !          1051:   register struct decision *p, *p1;
        !          1052:   register int depth = tree ? strlen (tree->position) : 0;
        !          1053:   enum machine_mode switch_mode = VOIDmode;
        !          1054:   RTX_CODE switch_code = UNKNOWN;
        !          1055:   int uncond = 0;
        !          1056:   char modemap[NUM_MACHINE_MODES];
        !          1057:   char codemap[NUM_RTX_CODE];
        !          1058:   int indent = 2;
        !          1059:   int i;
        !          1060: 
        !          1061:   /* One tricky area is what is the exact state when we branch to a
        !          1062:      node's label.  There are two cases where we branch: when looking at
        !          1063:      successors to a node, or when a set of tests fails.
        !          1064: 
        !          1065:      In the former case, we are always branching to the first node in a
        !          1066:      decision list and we want all required tests to be performed.  We
        !          1067:      put the labels for such nodes in front of any switch or test statements.
        !          1068:      These branches are done without updating the position to that of the
        !          1069:      target node.
        !          1070: 
        !          1071:      In the latter case, we are branching to a node that is not the first
        !          1072:      node in a decision list.  We have already checked that it is possible
        !          1073:      for both the node we originally tested at this level and the node we
        !          1074:      are branching to to be both match some pattern.  That means that they
        !          1075:      usually will be testing the same mode and code.  So it is normally safe
        !          1076:      for such labels to be inside switch statements, since the tests done
        !          1077:      by virtue of arriving at that label will usually already have been
        !          1078:      done.  The exception is a branch from a node that does not test a
        !          1079:      mode or code to one that does.  In such cases, we set the `retest_mode'
        !          1080:      or `retest_code' flags.  That will ensure that we start a new switch
        !          1081:      at that position and put the label before the switch. 
        !          1082: 
        !          1083:      The branches in the latter case must set the position to that of the
        !          1084:      target node.  */
        !          1085: 
        !          1086: 
        !          1087:   printf ("\n");
        !          1088:   if (tree && tree->subroutine_number == 0)
        !          1089:     {
        !          1090:       printf ("  L%d:\n", tree->number);
        !          1091:       tree->label_needed = 0;
        !          1092:     }
        !          1093: 
        !          1094:   if (tree)
        !          1095:     {
        !          1096:       change_state (prevpos, tree->position, 2);
        !          1097:       prevpos = tree->position;
        !          1098:     }
        !          1099: 
        !          1100:   for (p = tree; p; p = p->next)
        !          1101:     {
        !          1102:       enum machine_mode mode = p->enforce_mode ? p->mode : VOIDmode;
        !          1103:       int need_bracket;
        !          1104:       int wrote_bracket = 0;
        !          1105:       int inner_indent;
        !          1106: 
        !          1107:       if (p->success.first == 0 && p->insn_code_number < 0)
        !          1108:        abort ();
        !          1109: 
        !          1110:       /* Find the next alternative to p that might be true when p is true.
        !          1111:         Test that one next if p's successors fail.  */
        !          1112: 
        !          1113:       for (p1 = p->next; p1 && not_both_true (p, p1, 1); p1 = p1->next)
        !          1114:        ;
        !          1115:       p->afterward = p1;
        !          1116: 
        !          1117:       if (p1)
        !          1118:        {
        !          1119:          if (mode == VOIDmode && p1->enforce_mode && p1->mode != VOIDmode)
        !          1120:            p1->retest_mode = 1;
        !          1121:          if (p->code == UNKNOWN && p1->code != UNKNOWN)
        !          1122:            p1->retest_code = 1;
        !          1123:          p1->label_needed = 1;
        !          1124:        }
        !          1125: 
        !          1126:       /* If we have a different code or mode than the last node and
        !          1127:         are in a switch on codes, we must either end the switch or
        !          1128:         go to another case.  We must also end the switch if this
        !          1129:         node needs a label and to retest either the mode or code.  */
        !          1130: 
        !          1131:       if (switch_code != UNKNOWN
        !          1132:          && (switch_code != p->code || switch_mode != mode
        !          1133:              || (p->label_needed && (p->retest_mode || p->retest_code))))
        !          1134:        {
        !          1135:          enum rtx_code code = p->code;
        !          1136: 
        !          1137:          /* If P is testing a predicate that we know about and we haven't
        !          1138:             seen any of the codes that are valid for the predicate, we
        !          1139:             can write a series of "case" statement, one for each possible
        !          1140:             code.  Since we are already in a switch, these redundant tests
        !          1141:             are very cheap and will reduce the number of predicate called. */
        !          1142: 
        !          1143:          if (p->pred >= 0)
        !          1144:            {
        !          1145:              for (i = 0; i < NUM_RTX_CODE && preds[p->pred].codes[i] != 0; i++)
        !          1146:                if (codemap[(int) preds[p->pred].codes[i]])
        !          1147:                  break;
        !          1148: 
        !          1149:              if (preds[p->pred].codes[i] == 0)
        !          1150:                code = MATCH_OPERAND;
        !          1151:            }
        !          1152: 
        !          1153:          if (code == UNKNOWN || codemap[(int) code]
        !          1154:              || switch_mode != mode
        !          1155:              || (p->label_needed && (p->retest_mode || p->retest_code)))
        !          1156:            {
        !          1157:              printf ("%s}\n", indents[indent - 2]);
        !          1158:              switch_code = UNKNOWN;
        !          1159:              indent -= 4;
        !          1160:            }
        !          1161:          else
        !          1162:            {
        !          1163:              if (! uncond)
        !          1164:                printf ("%sbreak;\n", indents[indent]);
        !          1165: 
        !          1166:              if (code == MATCH_OPERAND)
        !          1167:                {
        !          1168:                  for (i = 0; i < NUM_RTX_CODE && preds[p->pred].codes[i] != 0; i++)
        !          1169:                    {
        !          1170:                      printf ("%scase ", indents[indent - 2]);
        !          1171:                      print_code (preds[p->pred].codes[i]);
        !          1172:                      printf (":\n");
        !          1173:                      codemap[(int) preds[p->pred].codes[i]] = 1;
        !          1174:                    }
        !          1175:                }
        !          1176:              else
        !          1177:                {
        !          1178:                  printf ("%scase ", indents[indent - 2]);
        !          1179:                  print_code (code);
        !          1180:                  printf (":\n");
        !          1181:                  codemap[(int) p->code] = 1;
        !          1182:                }
        !          1183: 
        !          1184:              switch_code = code;
        !          1185:            }
        !          1186: 
        !          1187:          uncond = 0;
        !          1188:        }
        !          1189: 
        !          1190:       /* If we were previously in a switch on modes and now have a different
        !          1191:         mode, end at least the case, and maybe end the switch if we are
        !          1192:         not testing a mode or testing a mode whose case we already saw.  */
        !          1193: 
        !          1194:       if (switch_mode != VOIDmode
        !          1195:          && (switch_mode != mode || (p->label_needed && p->retest_mode)))
        !          1196:        {
        !          1197:          if (mode == VOIDmode || modemap[(int) mode]
        !          1198:              || (p->label_needed && p->retest_mode))
        !          1199:            {
        !          1200:              printf ("%s}\n", indents[indent - 2]);
        !          1201:              switch_mode = VOIDmode;
        !          1202:              indent -= 4;
        !          1203:            }
        !          1204:          else
        !          1205:            {
        !          1206:              if (! uncond)
        !          1207:                printf ("      break;\n");
        !          1208:              printf ("    case %smode:\n", GET_MODE_NAME (mode));
        !          1209:              switch_mode = mode;
        !          1210:              modemap[(int) mode] = 1;
        !          1211:            }
        !          1212: 
        !          1213:          uncond = 0;
        !          1214:        }
        !          1215: 
        !          1216:       /* If we are about to write dead code, something went wrong.  */
        !          1217:       if (! p->label_needed && uncond)
        !          1218:        abort ();
        !          1219: 
        !          1220:       /* If we need a label and we will want to retest the mode or code at
        !          1221:         that label, write the label now.  We have already ensured that
        !          1222:         things will be valid for the test.  */
        !          1223: 
        !          1224:       if (p->label_needed && (p->retest_mode || p->retest_code))
        !          1225:        {
        !          1226:          printf ("%sL%d:\n", indents[indent - 2], p->number);
        !          1227:          p->label_needed = 0;
        !          1228:        }
        !          1229: 
        !          1230:       uncond = 0;
        !          1231: 
        !          1232:       /* If we are not in any switches, see if we can shortcut things
        !          1233:         by checking for identical modes and codes.  */
        !          1234: 
        !          1235:       if (switch_mode == VOIDmode && switch_code == UNKNOWN)
        !          1236:        {
        !          1237:          /* If p and its alternatives all want the same mode,
        !          1238:             reject all others at once, first, then ignore the mode.  */
        !          1239: 
        !          1240:          if (mode != VOIDmode && p->next && same_modes (p, mode))
        !          1241:            {
        !          1242:              printf ("  if (GET_MODE (x%d) != %smode)\n",
        !          1243:                      depth, GET_MODE_NAME (p->mode));
        !          1244:              if (afterward)
        !          1245:                {
        !          1246:                  printf ("    {\n");
        !          1247:                  change_state (p->position, afterward->position, 6);
        !          1248:                  printf ("      goto L%d;\n    }\n", afterward->number);
        !          1249:                }
        !          1250:              else
        !          1251:                printf ("    goto ret0;\n");
        !          1252:              clear_modes (p);
        !          1253:              mode = VOIDmode;
        !          1254:            }
        !          1255: 
        !          1256:          /* If p and its alternatives all want the same code,
        !          1257:             reject all others at once, first, then ignore the code.  */
        !          1258: 
        !          1259:          if (p->code != UNKNOWN && p->next && same_codes (p, p->code))
        !          1260:            {
        !          1261:              printf ("  if (GET_CODE (x%d) != ", depth);
        !          1262:              print_code (p->code);
        !          1263:              printf (")\n");
        !          1264:              if (afterward)
        !          1265:                {
        !          1266:                  printf ("    {\n");
        !          1267:                  change_state (p->position, afterward->position, indent + 4);
        !          1268:                  printf ("    goto L%d;\n    }\n", afterward->number);
        !          1269:                }
        !          1270:              else
        !          1271:                printf ("    goto ret0;\n");
        !          1272:              clear_codes (p);
        !          1273:            }
        !          1274:        }
        !          1275: 
        !          1276:       /* If we are not in a mode switch and we are testing for a specific
        !          1277:         mode, start a mode switch unless we have just one node or the next
        !          1278:         node is not testing a mode (we have already tested for the case of
        !          1279:         more than one mode, but all of the same mode).  */
        !          1280: 
        !          1281:       if (switch_mode == VOIDmode && mode != VOIDmode && p->next != 0
        !          1282:          && p->next->enforce_mode && p->next->mode != VOIDmode)
        !          1283:        {
        !          1284:          mybzero (modemap, sizeof modemap);
        !          1285:          printf ("%sswitch (GET_MODE (x%d))\n", indents[indent], depth);
        !          1286:          printf ("%s{\n", indents[indent + 2]);
        !          1287:          indent += 4;
        !          1288:          printf ("%scase %smode:\n", indents[indent - 2],
        !          1289:                  GET_MODE_NAME (mode));
        !          1290:          modemap[(int) mode] = 1;
        !          1291:          switch_mode = mode;
        !          1292:        }
        !          1293: 
        !          1294:       /* Similarly for testing codes.  */
        !          1295: 
        !          1296:       if (switch_code == UNKNOWN && p->code != UNKNOWN && ! p->ignore_code
        !          1297:          && p->next != 0 && p->next->code != UNKNOWN)
        !          1298:        {
        !          1299:          mybzero (codemap, sizeof codemap);
        !          1300:          printf ("%sswitch (GET_CODE (x%d))\n", indents[indent], depth);
        !          1301:          printf ("%s{\n", indents[indent + 2]);
        !          1302:          indent += 4;
        !          1303:          printf ("%scase ", indents[indent - 2]);
        !          1304:          print_code (p->code);
        !          1305:          printf (":\n");
        !          1306:          codemap[(int) p->code] = 1;
        !          1307:          switch_code = p->code;
        !          1308:        }
        !          1309: 
        !          1310:       /* Now that most mode and code tests have been done, we can write out
        !          1311:         a label for an inner node, if we haven't already. */
        !          1312:       if (p->label_needed)
        !          1313:        printf ("%sL%d:\n", indents[indent - 2], p->number);
        !          1314: 
        !          1315:       inner_indent = indent;
        !          1316: 
        !          1317:       /* The only way we can have to do a mode or code test here is if
        !          1318:         this node needs such a test but is the only node to be tested.
        !          1319:         In that case, we won't have started a switch.  Note that this is
        !          1320:         the only way the switch and test modes can disagree.  */
        !          1321: 
        !          1322:       if ((mode != switch_mode && ! p->ignore_mode)
        !          1323:          || (p->code != switch_code && p->code != UNKNOWN && ! p->ignore_code)
        !          1324:          || p->test_elt_zero_int || p->test_elt_one_int
        !          1325:          || p->test_elt_zero_wide || p->veclen
        !          1326:          || p->dupno >= 0 || p->tests || p->num_clobbers_to_add)
        !          1327:        {
        !          1328:          printf ("%sif (", indents[indent]);
        !          1329: 
        !          1330:          if (mode != switch_mode && ! p->ignore_mode)
        !          1331:            printf ("GET_MODE (x%d) == %smode && ",
        !          1332:                    depth, GET_MODE_NAME (mode));
        !          1333:          if (p->code != switch_code && p->code != UNKNOWN && ! p->ignore_code)
        !          1334:            {
        !          1335:              printf ("GET_CODE (x%d) == ", depth);
        !          1336:              print_code (p->code);
        !          1337:              printf (" && ");
        !          1338:            }
        !          1339: 
        !          1340:          if (p->test_elt_zero_int)
        !          1341:            printf ("XINT (x%d, 0) == %d && ", depth, p->elt_zero_int);
        !          1342:          if (p->test_elt_one_int)
        !          1343:            printf ("XINT (x%d, 1) == %d && ", depth, p->elt_one_int);
        !          1344:          if (p->test_elt_zero_wide)
        !          1345:            printf (
        !          1346: #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
        !          1347:                    "XWINT (x%d, 0) == %d && ",
        !          1348: #else
        !          1349:                    "XWINT (x%d, 0) == %ld && ",
        !          1350: #endif
        !          1351:                    depth, p->elt_zero_wide);
        !          1352:          if (p->veclen)
        !          1353:            printf ("XVECLEN (x%d, 0) == %d && ", depth, p->veclen);
        !          1354:          if (p->dupno >= 0)
        !          1355:            printf ("rtx_equal_p (x%d, ro[%d]) && ", depth, p->dupno);
        !          1356:          if (p->num_clobbers_to_add)
        !          1357:            printf ("pnum_clobbers != 0 && ");
        !          1358:          if (p->tests)
        !          1359:            printf ("%s (x%d, %smode)", p->tests, depth,
        !          1360:                    GET_MODE_NAME (p->mode));
        !          1361:          else
        !          1362:            printf ("1");
        !          1363: 
        !          1364:          printf (")\n");
        !          1365:          inner_indent += 2;
        !          1366:        }
        !          1367:       else
        !          1368:        uncond = 1;
        !          1369: 
        !          1370:       need_bracket = ! uncond;
        !          1371: 
        !          1372:       if (p->opno >= 0)
        !          1373:        {
        !          1374:          if (need_bracket)
        !          1375:            {
        !          1376:              printf ("%s{\n", indents[inner_indent]);
        !          1377:              inner_indent += 2;
        !          1378:              wrote_bracket = 1;
        !          1379:              need_bracket = 0;
        !          1380:            }
        !          1381: 
        !          1382:          printf ("%sro[%d] = x%d;\n", indents[inner_indent], p->opno, depth);
        !          1383:        }
        !          1384: 
        !          1385:       if (p->c_test)
        !          1386:        {
        !          1387:          printf ("%sif (%s)\n", indents[inner_indent], p->c_test);
        !          1388:          inner_indent += 2;
        !          1389:          uncond = 0;
        !          1390:          need_bracket = 1;
        !          1391:        }
        !          1392: 
        !          1393:       if (p->insn_code_number >= 0)
        !          1394:        {
        !          1395:          if (type == SPLIT)
        !          1396:            printf ("%sreturn gen_split_%d (operands);\n",
        !          1397:                    indents[inner_indent], p->insn_code_number);
        !          1398:          else
        !          1399:            {
        !          1400:              if (p->num_clobbers_to_add)
        !          1401:                {
        !          1402:                  if (need_bracket)
        !          1403:                    {
        !          1404:                      printf ("%s{\n", indents[inner_indent]);
        !          1405:                      inner_indent += 2;
        !          1406:                    }
        !          1407: 
        !          1408:                  printf ("%s*pnum_clobbers = %d;\n",
        !          1409:                          indents[inner_indent], p->num_clobbers_to_add);
        !          1410:                  printf ("%sreturn %d;\n",
        !          1411:                          indents[inner_indent], p->insn_code_number);
        !          1412: 
        !          1413:                  if (need_bracket)
        !          1414:                    {
        !          1415:                      inner_indent -= 2;
        !          1416:                      printf ("%s}\n", indents[inner_indent]);
        !          1417:                    }
        !          1418:                }
        !          1419:              else
        !          1420:                printf ("%sreturn %d;\n",
        !          1421:                        indents[inner_indent], p->insn_code_number);
        !          1422:            }
        !          1423:        }
        !          1424:       else
        !          1425:        printf ("%sgoto L%d;\n", indents[inner_indent],
        !          1426:                p->success.first->number);
        !          1427: 
        !          1428:       if (wrote_bracket)
        !          1429:        printf ("%s}\n", indents[inner_indent - 2]);
        !          1430:     }
        !          1431: 
        !          1432:   /* We have now tested all alternatives.  End any switches we have open
        !          1433:      and branch to the alternative node unless we know that we can't fall
        !          1434:      through to the branch.  */
        !          1435: 
        !          1436:   if (switch_code != UNKNOWN)
        !          1437:     {
        !          1438:       printf ("%s}\n", indents[indent - 2]);
        !          1439:       indent -= 4;
        !          1440:       uncond = 0;
        !          1441:     }
        !          1442: 
        !          1443:   if (switch_mode != VOIDmode)
        !          1444:     {
        !          1445:       printf ("%s}\n", indents[indent - 2]);
        !          1446:       indent -= 4;
        !          1447:       uncond = 0;
        !          1448:     }
        !          1449: 
        !          1450:   if (indent != 2)
        !          1451:     abort ();
        !          1452: 
        !          1453:   if (uncond)
        !          1454:     return;
        !          1455: 
        !          1456:   if (afterward)
        !          1457:     {
        !          1458:       change_state (prevpos, afterward->position, 2);
        !          1459:       printf ("  goto L%d;\n", afterward->number);
        !          1460:     }
        !          1461:   else
        !          1462:     printf ("  goto ret0;\n");
        !          1463: }
        !          1464: 
        !          1465: static void
        !          1466: print_code (code)
        !          1467:      enum rtx_code code;
        !          1468: {
        !          1469:   register char *p1;
        !          1470:   for (p1 = GET_RTX_NAME (code); *p1; p1++)
        !          1471:     {
        !          1472:       if (*p1 >= 'a' && *p1 <= 'z')
        !          1473:        putchar (*p1 + 'A' - 'a');
        !          1474:       else
        !          1475:        putchar (*p1);
        !          1476:     }
        !          1477: }
        !          1478: 
        !          1479: static int
        !          1480: same_codes (p, code)
        !          1481:      register struct decision *p;
        !          1482:      register enum rtx_code code;
        !          1483: {
        !          1484:   for (; p; p = p->next)
        !          1485:     if (p->code != code)
        !          1486:       return 0;
        !          1487: 
        !          1488:   return 1;
        !          1489: }
        !          1490: 
        !          1491: static void
        !          1492: clear_codes (p)
        !          1493:      register struct decision *p;
        !          1494: {
        !          1495:   for (; p; p = p->next)
        !          1496:     p->ignore_code = 1;
        !          1497: }
        !          1498: 
        !          1499: static int
        !          1500: same_modes (p, mode)
        !          1501:      register struct decision *p;
        !          1502:      register enum machine_mode mode;
        !          1503: {
        !          1504:   for (; p; p = p->next)
        !          1505:     if ((p->enforce_mode ? p->mode : VOIDmode) != mode)
        !          1506:       return 0;
        !          1507: 
        !          1508:   return 1;
        !          1509: }
        !          1510: 
        !          1511: static void
        !          1512: clear_modes (p)
        !          1513:      register struct decision *p;
        !          1514: {
        !          1515:   for (; p; p = p->next)
        !          1516:     p->enforce_mode = 0;
        !          1517: }
        !          1518: 
        !          1519: /* Write out the decision tree starting at TREE for a subroutine of type TYPE.
        !          1520: 
        !          1521:    PREVPOS is the position at the node that branched to this node.
        !          1522: 
        !          1523:    INITIAL is nonzero if this is the first node we are writing in a subroutine.
        !          1524: 
        !          1525:    If all nodes are false, branch to the node AFTERWARD.  */
        !          1526: 
        !          1527: static void
        !          1528: write_tree (tree, prevpos, afterward, initial, type)
        !          1529:      struct decision *tree;
        !          1530:      char *prevpos;
        !          1531:      struct decision *afterward;
        !          1532:      int initial;
        !          1533:      enum routine_type type;
        !          1534: {
        !          1535:   register struct decision *p;
        !          1536:   char *name_prefix = (type == SPLIT ? "split" : "recog");
        !          1537:   char *call_suffix = (type == SPLIT ? "" : ", pnum_clobbers");
        !          1538: 
        !          1539:   if (! initial && tree->subroutine_number > 0)
        !          1540:     {
        !          1541:       printf (" L%d:\n", tree->number);
        !          1542: 
        !          1543:       if (afterward)
        !          1544:        {
        !          1545:          printf ("  tem = %s_%d (x0, insn%s);\n",
        !          1546:                  name_prefix, tree->subroutine_number, call_suffix);
        !          1547:          if (type == SPLIT)
        !          1548:            printf ("  if (tem != 0) return tem;\n");
        !          1549:          else
        !          1550:            printf ("  if (tem >= 0) return tem;\n");
        !          1551:          change_state (tree->position, afterward->position, 2);
        !          1552:          printf ("  goto L%d;\n", afterward->number);
        !          1553:        }
        !          1554:       else
        !          1555:        printf ("  return %s_%d (x0, insn%s);\n",
        !          1556:                name_prefix, tree->subroutine_number, call_suffix);
        !          1557:       return;
        !          1558:     }
        !          1559: 
        !          1560:   write_tree_1 (tree, prevpos, afterward, type);
        !          1561: 
        !          1562:   for (p = tree; p; p = p->next)
        !          1563:     if (p->success.first)
        !          1564:       write_tree (p->success.first, p->position,
        !          1565:                  p->afterward ? p->afterward : afterward, 0, type);
        !          1566: }
        !          1567: 
        !          1568: 
        !          1569: /* Assuming that the state of argument is denoted by OLDPOS, take whatever
        !          1570:    actions are necessary to move to NEWPOS.
        !          1571: 
        !          1572:    INDENT says how many blanks to place at the front of lines.  */
        !          1573: 
        !          1574: static void
        !          1575: change_state (oldpos, newpos, indent)
        !          1576:      char *oldpos;
        !          1577:      char *newpos;
        !          1578:      int indent;
        !          1579: {
        !          1580:   int odepth = strlen (oldpos);
        !          1581:   int depth = odepth;
        !          1582:   int ndepth = strlen (newpos);
        !          1583: 
        !          1584:   /* Pop up as many levels as necessary.  */
        !          1585: 
        !          1586:   while (strncmp (oldpos, newpos, depth))
        !          1587:     --depth;
        !          1588: 
        !          1589:   /* Go down to desired level.  */
        !          1590: 
        !          1591:   while (depth < ndepth)
        !          1592:     {
        !          1593:       if (newpos[depth] >= 'a' && newpos[depth] <= 'z')
        !          1594:        printf ("%sx%d = XVECEXP (x%d, 0, %d);\n",
        !          1595:                indents[indent], depth + 1, depth, newpos[depth] - 'a');
        !          1596:       else
        !          1597:        printf ("%sx%d = XEXP (x%d, %c);\n",
        !          1598:                indents[indent], depth + 1, depth, newpos[depth]);
        !          1599:       ++depth;
        !          1600:     }
        !          1601: }
        !          1602: 
        !          1603: static char *
        !          1604: copystr (s1)
        !          1605:      char *s1;
        !          1606: {
        !          1607:   register char *tem;
        !          1608: 
        !          1609:   if (s1 == 0)
        !          1610:     return 0;
        !          1611: 
        !          1612:   tem = (char *) xmalloc (strlen (s1) + 1);
        !          1613:   strcpy (tem, s1);
        !          1614: 
        !          1615:   return tem;
        !          1616: }
        !          1617: 
        !          1618: static void
        !          1619: mybzero (b, length)
        !          1620:      register char *b;
        !          1621:      register unsigned length;
        !          1622: {
        !          1623:   while (length-- > 0)
        !          1624:     *b++ = 0;
        !          1625: }
        !          1626: 
        !          1627: static void
        !          1628: mybcopy (in, out, length)
        !          1629:      register char *in, *out;
        !          1630:      register unsigned length;
        !          1631: {
        !          1632:   while (length-- > 0)
        !          1633:     *out++ = *in++;
        !          1634: }
        !          1635: 
        !          1636: static char *
        !          1637: concat (s1, s2)
        !          1638:      char *s1, *s2;
        !          1639: {
        !          1640:   register char *tem;
        !          1641: 
        !          1642:   if (s1 == 0)
        !          1643:     return s2;
        !          1644:   if (s2 == 0)
        !          1645:     return s1;
        !          1646: 
        !          1647:   tem = (char *) xmalloc (strlen (s1) + strlen (s2) + 2);
        !          1648:   strcpy (tem, s1);
        !          1649:   strcat (tem, " ");
        !          1650:   strcat (tem, s2);
        !          1651: 
        !          1652:   return tem;
        !          1653: }
        !          1654: 
        !          1655: char *
        !          1656: xrealloc (ptr, size)
        !          1657:      char *ptr;
        !          1658:      unsigned size;
        !          1659: {
        !          1660:   char *result = (char *) realloc (ptr, size);
        !          1661:   if (!result)
        !          1662:     fatal ("virtual memory exhausted");
        !          1663:   return result;
        !          1664: }
        !          1665: 
        !          1666: char *
        !          1667: xmalloc (size)
        !          1668:      unsigned size;
        !          1669: {
        !          1670:   register char *val = (char *) malloc (size);
        !          1671: 
        !          1672:   if (val == 0)
        !          1673:     fatal ("virtual memory exhausted");
        !          1674:   return val;
        !          1675: }
        !          1676: 
        !          1677: static void
        !          1678: fatal (s)
        !          1679:      char *s;
        !          1680: {
        !          1681:   fprintf (stderr, "genrecog: ");
        !          1682:   fprintf (stderr, s);
        !          1683:   fprintf (stderr, "\n");
        !          1684:   fprintf (stderr, "after %d definitions\n", next_index);
        !          1685:   exit (FATAL_EXIT_CODE);
        !          1686: }
        !          1687: 
        !          1688: /* More 'friendly' abort that prints the line and file.
        !          1689:    config.h can #define abort fancy_abort if you like that sort of thing.  */
        !          1690: 
        !          1691: void
        !          1692: fancy_abort ()
        !          1693: {
        !          1694:   fatal ("Internal gcc abort.");
        !          1695: }
        !          1696: 
        !          1697: int
        !          1698: main (argc, argv)
        !          1699:      int argc;
        !          1700:      char **argv;
        !          1701: {
        !          1702:   rtx desc;
        !          1703:   struct decision_head recog_tree;
        !          1704:   struct decision_head split_tree;
        !          1705:   FILE *infile;
        !          1706:   register int c;
        !          1707: 
        !          1708:   obstack_init (rtl_obstack);
        !          1709:   recog_tree.first = recog_tree.last = split_tree.first = split_tree.last = 0;
        !          1710: 
        !          1711:   if (argc <= 1)
        !          1712:     fatal ("No input file name.");
        !          1713: 
        !          1714:   infile = fopen (argv[1], "r");
        !          1715:   if (infile == 0)
        !          1716:     {
        !          1717:       perror (argv[1]);
        !          1718:       exit (FATAL_EXIT_CODE);
        !          1719:     }
        !          1720: 
        !          1721:   init_rtl ();
        !          1722:   next_insn_code = 0;
        !          1723:   next_index = 0;
        !          1724: 
        !          1725:   printf ("/* Generated automatically by the program `genrecog'\n\
        !          1726: from the machine description file `md'.  */\n\n");
        !          1727: 
        !          1728:   printf ("#include \"config.h\"\n");
        !          1729:   printf ("#include \"rtl.h\"\n");
        !          1730:   printf ("#include \"insn-config.h\"\n");
        !          1731:   printf ("#include \"recog.h\"\n");
        !          1732:   printf ("#include \"real.h\"\n");
        !          1733:   printf ("#include \"output.h\"\n");
        !          1734:   printf ("#include \"flags.h\"\n");
        !          1735:   printf ("\n");
        !          1736: 
        !          1737:   /* Read the machine description.  */
        !          1738: 
        !          1739:   while (1)
        !          1740:     {
        !          1741:       c = read_skip_spaces (infile);
        !          1742:       if (c == EOF)
        !          1743:        break;
        !          1744:       ungetc (c, infile);
        !          1745: 
        !          1746:       desc = read_rtx (infile);
        !          1747:       if (GET_CODE (desc) == DEFINE_INSN)
        !          1748:        recog_tree = merge_trees (recog_tree,
        !          1749:                                  make_insn_sequence (desc, RECOG));
        !          1750:       else if (GET_CODE (desc) == DEFINE_SPLIT)
        !          1751:        split_tree = merge_trees (split_tree,
        !          1752:                                  make_insn_sequence (desc, SPLIT));
        !          1753:       if (GET_CODE (desc) == DEFINE_PEEPHOLE
        !          1754:          || GET_CODE (desc) == DEFINE_EXPAND)
        !          1755:        next_insn_code++;
        !          1756:       next_index++;
        !          1757:     }
        !          1758: 
        !          1759:   printf ("\n\
        !          1760: /* `recog' contains a decision tree\n\
        !          1761:    that recognizes whether the rtx X0 is a valid instruction.\n\
        !          1762: \n\
        !          1763:    recog returns -1 if the rtx is not valid.\n\
        !          1764:    If the rtx is valid, recog returns a nonnegative number\n\
        !          1765:    which is the insn code number for the pattern that matched.\n");
        !          1766:   printf ("   This is the same as the order in the machine description of\n\
        !          1767:    the entry that matched.  This number can be used as an index into\n\
        !          1768:    entry that matched.  This number can be used as an index into various\n\
        !          1769:    insn_* tables, such as insn_templates, insn_outfun, and insn_n_operands\n\
        !          1770:    (found in insn-output.c).\n\n");
        !          1771:   printf ("   The third argument to recog is an optional pointer to an int.\n\
        !          1772:    If present, recog will accept a pattern if it matches except for\n\
        !          1773:    missing CLOBBER expressions at the end.  In that case, the value\n\
        !          1774:    pointed to by the optional pointer will be set to the number of\n\
        !          1775:    CLOBBERs that need to be added (it should be initialized to zero by\n\
        !          1776:    the caller).  If it is set nonzero, the caller should allocate a\n\
        !          1777:    PARALLEL of the appropriate size, copy the initial entries, and call\n\
        !          1778:    add_clobbers (found in insn-emit.c) to fill in the CLOBBERs.");
        !          1779: 
        !          1780:   if (split_tree.first)
        !          1781:     printf ("\n\n   The function split_insns returns 0 if the rtl could not\n\
        !          1782:    be split or the split rtl in a SEQUENCE if it can be.");
        !          1783: 
        !          1784:   printf ("*/\n\n");
        !          1785: 
        !          1786:   printf ("rtx recog_operand[MAX_RECOG_OPERANDS];\n\n");
        !          1787:   printf ("rtx *recog_operand_loc[MAX_RECOG_OPERANDS];\n\n");
        !          1788:   printf ("rtx *recog_dup_loc[MAX_DUP_OPERANDS];\n\n");
        !          1789:   printf ("char recog_dup_num[MAX_DUP_OPERANDS];\n\n");
        !          1790:   printf ("#define operands recog_operand\n\n");
        !          1791: 
        !          1792:   next_subroutine_number = 0;
        !          1793:   break_out_subroutines (recog_tree, RECOG, 1);
        !          1794:   write_subroutine (recog_tree.first, RECOG);
        !          1795: 
        !          1796:   next_subroutine_number = 0;
        !          1797:   break_out_subroutines (split_tree, SPLIT, 1);
        !          1798:   write_subroutine (split_tree.first, SPLIT);
        !          1799: 
        !          1800:   fflush (stdout);
        !          1801:   exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
        !          1802:   /* NOTREACHED */
        !          1803:   return 0;
        !          1804: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.