Annotation of gcc/genattrtab.c, revision 1.1

1.1     ! root        1: /* Generate code from machine description to compute values of attributes.
        !             2:    Copyright (C) 1991 Free Software Foundation, Inc.
        !             3:    Contributed by Richard Kenner ([email protected])
        !             4: 
        !             5: This file is part of GNU CC.
        !             6: 
        !             7: GNU CC is free software; you can redistribute it and/or modify
        !             8: it under the terms of the GNU General Public License as published by
        !             9: the Free Software Foundation; either version 2, or (at your option)
        !            10: any later version.
        !            11: 
        !            12: GNU CC is distributed in the hope that it will be useful,
        !            13: but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            15: GNU General Public License for more details.
        !            16: 
        !            17: You should have received a copy of the GNU General Public License
        !            18: along with GNU CC; see the file COPYING.  If not, write to
        !            19: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
        !            20: 
        !            21: /* This program handles insn attribues and the DEFINE_DELAY and
        !            22:    DEFINE_FUNCTION_UNIT definitions.
        !            23: 
        !            24:    It produces a series of functions call `get_attr_...', one for each
        !            25:    attribute.  Each of these is given the rtx for an insn and returns a member
        !            26:    of the enum for the attribute.
        !            27: 
        !            28:    These subroutines have the form of a `switch' on the INSN_CODE (via
        !            29:    `recog_memoized').  Each case either returns a constant attribute value
        !            30:    or a value that depends on tests on other attributes, the form of
        !            31:    operands, or some random C expression (encoded with a SYMBOL_REF
        !            32:    expression).
        !            33: 
        !            34:    If the attribute `alternative', or a random C expression is present,
        !            35:    `constrain_operands' is called.  If either of these cases of a reference to
        !            36:    an operand is found, `insn_extract' is called.
        !            37: 
        !            38:    The special attribute `length' is also recognized.  For this operand, 
        !            39:    expressions involving the address of an operand or the current insn,
        !            40:    (address (pc)), are valid.  In this case, an initial pass is made to
        !            41:    set all lengths that do not depend on address.  Those that do are set to
        !            42:    the maximum length.  Then each insn that depends on an address is checked
        !            43:    and possibly has its length changed.  The process repeats until no further
        !            44:    changed are made.  The resulting lengths are saved for use by
        !            45:    `get_attr_length'.
        !            46: 
        !            47:    Internal attributes are defined to handle DEFINE_DELAY and
        !            48:    DEFINE_FUNCTION_UNIT.  Special routines are output for these cases.
        !            49: 
        !            50:    This program works by keeping a list of possible values for each attribute.
        !            51:    These include the basic attribute choices, default values for attribute, and
        !            52:    all derived quantities.
        !            53: 
        !            54:    As the description file is read, the definition for each insn is saved in a
        !            55:    `struct insn_def'.   When the file reading is complete, a `struct insn_ent'
        !            56:    is created for each insn and chained to the corresponding attribute value,
        !            57:    either that specified, or the default.
        !            58: 
        !            59:    An optimization phase is then run.  This simplifies expressions for each
        !            60:    insn.  EQ_ATTR tests are resolved, whenever possible, to a test that
        !            61:    indicates when the attribute has the specified value for the insn.  This
        !            62:    avoids recursive calls during compilation.
        !            63: 
        !            64:    The strategy used when processing DEFINE_DELAY and DEFINE_FUNCTION_UNIT
        !            65:    definitions is to create arbitrarily complex expressions and have the
        !            66:    optimization simplify them.
        !            67: 
        !            68:    Once optimization is complete, any required routines and definitions
        !            69:    will be written.  */
        !            70: 
        !            71: #include <stdio.h>
        !            72: #include "config.h"
        !            73: #include "rtl.h"
        !            74: #include "obstack.h"
        !            75: #include "insn-config.h"       /* For REGISTER_CONSTRAINTS */
        !            76: 
        !            77: static struct obstack obstack;
        !            78: struct obstack *rtl_obstack = &obstack;
        !            79: 
        !            80: #define obstack_chunk_alloc xmalloc
        !            81: #define obstack_chunk_free free
        !            82: 
        !            83: extern void free ();
        !            84: 
        !            85: static void fatal ();
        !            86: void fancy_abort ();
        !            87: 
        !            88: /* Define structures used to record attributes and values.  */
        !            89: 
        !            90: /* As each DEFINE_INSN, DEFINE_PEEPHOLE, or DEFINE_ASM_ATTRIBUTES is
        !            91:    encountered, we store all the relevant information into a
        !            92:    `struct insn_def'.  This is done to allow attribute definitions to occur
        !            93:    anywhere in the file.  */
        !            94: 
        !            95: struct insn_def
        !            96: {
        !            97:   int insn_code;               /* Instruction number. */
        !            98:   int insn_index;              /* Expression numer in file, for errors. */
        !            99:   struct insn_def *next;       /* Next insn in chain. */
        !           100:   rtx def;                     /* The DEFINE_... */
        !           101:   int num_alternatives;                /* Number of alternatives.  */
        !           102:   int vec_idx;                 /* Index of attribute vector in `def'. */
        !           103: };
        !           104: 
        !           105: /* Once everything has been read in, we store in each attribute value a list
        !           106:    of insn codes that have that value.  Here is the structure used for the
        !           107:    list.  */
        !           108: 
        !           109: struct insn_ent
        !           110: {
        !           111:   int insn_code;               /* Instruction number.  */
        !           112:   int insn_index;              /* Index of definition in file */
        !           113:   struct insn_ent *next;       /* Next in chain.  */
        !           114: };
        !           115: 
        !           116: /* Each value of an attribute (either constant or computed) is assigned a
        !           117:    structure which is used as the listhead of the insns that have that
        !           118:    value.  */
        !           119: 
        !           120: struct attr_value
        !           121: {
        !           122:   rtx value;                   /* Value of attribute.  */
        !           123:   struct attr_value *next;     /* Next attribute value in chain.  */
        !           124:   struct insn_ent *first_insn; /* First insn with this value.  */
        !           125:   int num_insns;               /* Number of insns with this value.  */
        !           126:   int has_asm_insn;            /* True if this value used for `asm' insns */
        !           127: };
        !           128: 
        !           129: /* Structure for each attribute.  */
        !           130: 
        !           131: struct attr_desc
        !           132: {
        !           133:   char *name;                  /* Name of attribute. */
        !           134:   struct attr_desc *next;      /* Next attribute. */
        !           135:   int is_numeric;              /* Values of this attribute are numeric. */
        !           136:   int is_special;              /* Don't call `write_attr_set'. */
        !           137:   struct attr_value *first_value; /* First value of this attribute. */
        !           138:   struct attr_value *default_val; /* Default value for this attribute. */
        !           139: };
        !           140: 
        !           141: /* Structure for each DEFINE_DELAY.  */
        !           142: 
        !           143: struct delay_desc
        !           144: {
        !           145:   rtx def;                     /* DEFINE_DELAY expression.  */
        !           146:   struct delay_desc *next;     /* Next DEFINE_DELAY. */
        !           147:   int num;                     /* Number of DEFINE_DELAY, starting at 1.  */
        !           148: };
        !           149: 
        !           150: /* Record information about each DEFINE_FUNCTION_UNIT.  */
        !           151: 
        !           152: struct function_unit_op
        !           153: {
        !           154:   rtx condexp;                 /* Expression TRUE for applicable insn.  */
        !           155:   struct function_unit_op *next; /* Next operation for this function unit.  */
        !           156:   int num;                     /* Ordinal for this operation type in unit.  */
        !           157:   int ready;                   /* Cost until data is ready.  */
        !           158:   rtx busyexp;                 /* Expression computing conflict cost.  */
        !           159: };
        !           160: 
        !           161: /* Record information about each function unit mentioned in a
        !           162:    DEFINE_FUNCTION_UNIT.  */
        !           163: 
        !           164: struct function_unit
        !           165: {
        !           166:   char *name;                  /* Function unit name.  */
        !           167:   struct function_unit *next;  /* Next function unit.  */
        !           168:   int num;                     /* Ordinal of this unit type.  */
        !           169:   int multiplicity;            /* Number of units of this type.  */
        !           170:   int simultaneity;            /* Maximum number of simultaneous insns
        !           171:                                   on this function unit or 0 if unlimited.  */
        !           172:   rtx condexp;                 /* Expression TRUE for insn needing unit. */
        !           173:   rtx costexp;                 /* Worst-case cost as function of insn. */
        !           174:   int num_opclasses;           /* Number of different operation types.  */
        !           175:   struct function_unit_op *ops;        /* Pointer to first operation type.  */
        !           176:   int needs_conflict_function; /* Nonzero if a conflict function required.  */
        !           177:   rtx default_cost;            /* Conflict cost, if constant.  */
        !           178: };
        !           179: 
        !           180: /* Listheads of above structures.  */
        !           181: 
        !           182: static struct attr_desc *attrs;
        !           183: static struct insn_def *defs;
        !           184: static struct delay_desc *delays;
        !           185: static struct function_unit *units;
        !           186: 
        !           187: /* Other variables. */
        !           188: 
        !           189: static int insn_code_number;
        !           190: static int insn_index_number;
        !           191: static int got_define_asm_attributes;
        !           192: static int must_extract;
        !           193: static int must_constrain;
        !           194: static int address_used;
        !           195: static int num_delays;
        !           196: static int have_annul_true, have_annul_false;
        !           197: static int num_units;
        !           198: 
        !           199: /* Used as operand to `operate_exp':  */
        !           200: 
        !           201: enum operator {PLUS_OP, MINUS_OP, OR_OP, MAX_OP};
        !           202: 
        !           203: /* Stores, for each insn code, a bitmap that has bits on for each possible
        !           204:    alternative.  */
        !           205: 
        !           206: static int *insn_alternatives;
        !           207: 
        !           208: /* Used to simplify expressions.  */
        !           209: 
        !           210: static rtx true_rtx, false_rtx;
        !           211: 
        !           212: /* Used to reduce calls to `strcmp' */
        !           213: 
        !           214: static char *alternative_name = "alternative";
        !           215: 
        !           216: /* Simplify an expression.  Only call the routine if there is something to
        !           217:    simplify.  */
        !           218: #define SIMPLIFY_TEST_EXP(EXP,INSN_CODE,INSN_INDEX)    \
        !           219:   (RTX_UNCHANGING_P (EXP) ? (EXP)                      \
        !           220:    : simplify_test_exp (EXP, INSN_CODE, INSN_INDEX))
        !           221:   
        !           222: /* These are referenced by rtlanal.c and hence need to be defined somewhere.
        !           223:    They won't actually be used.  */
        !           224: 
        !           225: rtx frame_pointer_rtx, stack_pointer_rtx, arg_pointer_rtx;
        !           226: 
        !           227: static rtx check_attr_test ();
        !           228: static void check_attr_value ();
        !           229: static rtx convert_set_attr_alternative ();
        !           230: static rtx convert_set_attr ();
        !           231: static void check_defs ();
        !           232: static rtx make_canonical ();
        !           233: static struct attr_value *get_attr_value ();
        !           234: static void expand_delays ();
        !           235: static rtx operate_exp ();
        !           236: static void expand_units ();
        !           237: static void fill_attr ();
        !           238: static rtx substitute_address ();
        !           239: static void make_length_attrs ();
        !           240: static rtx identity_fn ();
        !           241: static rtx zero_fn ();
        !           242: static rtx one_fn ();
        !           243: static rtx max_fn ();
        !           244: static rtx simplify_cond ();
        !           245: static void remove_insn_ent ();
        !           246: static void insert_insn_ent ();
        !           247: static rtx insert_right_side ();
        !           248: static rtx make_alternative_compare ();
        !           249: static int compute_alternative_mask ();
        !           250: static rtx evaluate_eq_attr ();
        !           251: static rtx simplify_and_tree ();
        !           252: static rtx simplify_or_tree ();
        !           253: static rtx simplify_test_exp ();
        !           254: static void optimize_attrs ();
        !           255: static void gen_attr ();
        !           256: static int count_alternatives ();
        !           257: static int compares_alternatives_p ();
        !           258: static int contained_in_p ();
        !           259: static void gen_insn ();
        !           260: static void gen_delay ();
        !           261: static void gen_unit ();
        !           262: static void write_test_expr ();
        !           263: static int max_attr_value ();
        !           264: static void walk_attr_value ();
        !           265: static void write_attr_get ();
        !           266: static rtx eliminate_known_true ();
        !           267: static void write_attr_set ();
        !           268: static void write_attr_case ();
        !           269: static void write_attr_value ();
        !           270: static void write_attr_valueq ();
        !           271: static void write_upcase ();
        !           272: static void write_indent ();
        !           273: static void write_eligible_delay ();
        !           274: static void write_function_unit_info ();
        !           275: static int n_comma_elts ();
        !           276: static char *next_comma_elt ();
        !           277: static struct attr_desc *find_attr ();
        !           278: static void make_internal_attr ();
        !           279: static struct attr_value *find_most_used ();
        !           280: static rtx find_single_value ();
        !           281: static rtx make_numeric_value ();
        !           282: char *xrealloc ();
        !           283: char *xmalloc ();
        !           284: static void fatal ();
        !           285: 
        !           286: /* Given a test expression for an attribute, ensure it is validly formed.
        !           287:    Convert (eq_attr "att" "a1,a2") to (ior (eq_attr ... ) (eq_attrq ..))
        !           288:    and (eq_attr "att" "!a1") to (not (eq_attr "att" "a1")).  Do the latter
        !           289:    test first so that (eq_attr "att" "!a1,a2,a3") works as expected.
        !           290: 
        !           291:    Update the string address in EQ_ATTR expression to be the same used
        !           292:    in the attribute (or `alternative_name') to speed up subsequent
        !           293:    `find_attr' calls and eliminate most `strcmp' calls.
        !           294: 
        !           295:    Return the new expression, if any.   */
        !           296: 
        !           297: static rtx
        !           298: check_attr_test (exp)
        !           299:      rtx exp;
        !           300: {
        !           301:   struct attr_desc *attr;
        !           302:   struct attr_value *av;
        !           303:   char *name_ptr, *p;
        !           304:   rtx orexp, newexp;
        !           305: 
        !           306:   switch (GET_CODE (exp))
        !           307:     {
        !           308:     case EQ_ATTR:
        !           309:       /* Handle negation test.  */
        !           310:       if (XSTR (exp, 1)[0] == '!')
        !           311:        {
        !           312:          XSTR(exp, 1) = &XSTR(exp, 1)[1];
        !           313:          newexp = rtx_alloc (NOT);
        !           314:          XEXP (newexp, 0) = exp;
        !           315: 
        !           316:          return check_attr_test (newexp);
        !           317:        }
        !           318: 
        !           319:       else if (n_comma_elts (XSTR (exp, 1)) == 1)
        !           320:        {
        !           321:          attr = find_attr (XEXP (exp, 0), 0);
        !           322:          if (attr == NULL)
        !           323:            {
        !           324:              if (! strcmp (XSTR (exp, 0), "alternative"))
        !           325:                {
        !           326:                  XSTR (exp, 0) = alternative_name;
        !           327:                  /* This can't be simplified any further.  */
        !           328:                  RTX_UNCHANGING_P (exp) = 1;
        !           329:                  return exp;
        !           330:                }
        !           331:            else
        !           332:                fatal ("Unknown attribute `%s' in EQ_ATTR", XEXP (exp, 0));
        !           333:            }
        !           334: 
        !           335:          XSTR (exp, 0) = attr->name;
        !           336: 
        !           337:          if (attr->is_numeric)
        !           338:            {
        !           339:              for (p = XSTR (exp, 1); *p; p++)
        !           340:                if (*p < '0' || *p > '9')
        !           341:                   fatal ("Attribute `%s' takes only numeric values", 
        !           342:                          XEXP (exp, 0));
        !           343:            }
        !           344:          else
        !           345:            {
        !           346:              for (av = attr->first_value; av; av = av->next)
        !           347:                if (GET_CODE (av->value) == CONST_STRING
        !           348:                    && ! strcmp (XSTR (exp, 1), XSTR (av->value, 0)))
        !           349:                  break;
        !           350: 
        !           351:              if (av == NULL)
        !           352:                fatal ("Unknown value `%s' for `%s' attribute",
        !           353:                       XEXP (exp, 1), XEXP (exp, 0));
        !           354:            }
        !           355:        }
        !           356:       else
        !           357:        {
        !           358:          /* Make an IOR tree of the possible values.  */
        !           359:          orexp = false_rtx;
        !           360:          name_ptr = XSTR (exp, 1);
        !           361:          while ((p = next_comma_elt (&name_ptr)) != NULL)
        !           362:            {
        !           363:              newexp = rtx_alloc (EQ_ATTR);
        !           364:              XSTR (newexp, 0) = XSTR (exp, 0);
        !           365:              XSTR (newexp, 1) = p;
        !           366:              orexp = insert_right_side (IOR, orexp, newexp, -2);
        !           367:            }
        !           368: 
        !           369:          return check_attr_test (orexp);
        !           370:        }
        !           371:       break;
        !           372: 
        !           373:     case CONST_INT:
        !           374:       /* Either TRUE or FALSE.  */
        !           375:       if (XINT (exp, 0))
        !           376:        return true_rtx;
        !           377:       else
        !           378:        return false_rtx;
        !           379: 
        !           380:     case IOR:
        !           381:     case AND:
        !           382:       XEXP (exp, 0) = check_attr_test (XEXP (exp, 0));
        !           383:       XEXP (exp, 1) = check_attr_test (XEXP (exp, 1));
        !           384:       break;
        !           385: 
        !           386:     case NOT:
        !           387:       XEXP (exp, 0) = check_attr_test (XEXP (exp, 0));
        !           388:       break;
        !           389: 
        !           390:     case MATCH_OPERAND:
        !           391:     case LE:  case LT:  case GT:  case GE:
        !           392:     case LEU: case LTU: case GTU: case GEU:
        !           393:     case NE:  case EQ:
        !           394:       /* These cases can't be simplified.  */
        !           395:       RTX_UNCHANGING_P (exp) = 1;
        !           396:       break;
        !           397: 
        !           398:     default:
        !           399:       fatal ("RTL operator \"%s\" not valid in attribute test",
        !           400:             GET_RTX_NAME (GET_CODE (exp)));
        !           401:     }
        !           402: 
        !           403:   return exp;
        !           404: }
        !           405: 
        !           406: /* Given an expression, ensure that it is validly formed and that all named
        !           407:    attribute values are valid for the given attribute.  Issue a fatal error
        !           408:    if not.  If no attribute is specified, assume a numeric attribute.  */
        !           409: 
        !           410: static void
        !           411: check_attr_value (exp, attr)
        !           412:      rtx exp;
        !           413:      struct attr_desc *attr;
        !           414: {
        !           415:   struct attr_value *av;
        !           416:   char *p;
        !           417:   int i;
        !           418: 
        !           419:   switch (GET_CODE (exp))
        !           420:     {
        !           421:     case CONST_INT:
        !           422:       if (attr && ! attr->is_numeric)
        !           423:        fatal ("CONST_INT not valid for non-numeric `%s' attribute",
        !           424:               attr->name);
        !           425: 
        !           426:       if (INTVAL (exp) < 0)
        !           427:        fatal ("Negative numeric value specified for `%s' attribute",
        !           428:               attr->name);
        !           429: 
        !           430:       break;
        !           431: 
        !           432:     case CONST_STRING:
        !           433:       if (! strcmp (XSTR (exp, 0), "*"))
        !           434:        break;
        !           435: 
        !           436:       if (attr == 0 || attr->is_numeric)
        !           437:        {
        !           438:          for (p = XSTR (exp, 0); *p; p++)
        !           439:            if (*p > '9' || *p < '0')
        !           440:              fatal ("Non-numeric value for numeric `%s' attribute",
        !           441:                     attr ? "internal" : attr->name);
        !           442:          break;
        !           443:        }
        !           444: 
        !           445:       for (av = attr->first_value; av; av = av->next)
        !           446:        if (GET_CODE (av->value) == CONST_STRING
        !           447:            && ! strcmp (XSTR (av->value, 0), XSTR (exp, 0)))
        !           448:          break;
        !           449: 
        !           450:       if (av == NULL)
        !           451:        fatal ("Unknown value `%s' for `%s' attribute",
        !           452:               XSTR (exp, 0), attr ? "internal" : attr->name);
        !           453: 
        !           454:       return;
        !           455: 
        !           456:     case IF_THEN_ELSE:
        !           457:       XEXP (exp, 0) = check_attr_test (XEXP (exp, 0));
        !           458:       check_attr_value (XEXP (exp, 1), attr);
        !           459:       check_attr_value (XEXP (exp, 2), attr);
        !           460:       return;
        !           461: 
        !           462:     case COND:
        !           463:       if (XVECLEN (exp, 0) % 2 != 0)
        !           464:        fatal ("First operand of COND must have even length");
        !           465: 
        !           466:       for (i = 0; i < XVECLEN (exp, 0); i += 2)
        !           467:        {
        !           468:          XVECEXP (exp, 0, i) = check_attr_test (XVECEXP (exp, 0, i));
        !           469:          check_attr_value (XVECEXP (exp, 0, i + 1), attr);
        !           470:        }
        !           471: 
        !           472:       check_attr_value (XEXP (exp, 1), attr);
        !           473:       return;
        !           474: 
        !           475:     default:
        !           476:       fatal ("Illegal operation `%s' for attribute value",
        !           477:             GET_RTX_NAME (GET_CODE (exp)));
        !           478:     }
        !           479: }
        !           480: 
        !           481: /* Given an SET_ATTR_ALTERNATIVE expression, convert to the canonical SET.
        !           482:    It becomes a COND with each test being (eq_attr "alternative "n") */
        !           483: 
        !           484: static rtx
        !           485: convert_set_attr_alternative (exp, num_alt, insn_code, insn_index)
        !           486:      rtx exp;
        !           487:      int num_alt;
        !           488:      int insn_code, insn_index;
        !           489: {
        !           490:   rtx newexp;
        !           491:   rtx condexp;
        !           492:   int i;
        !           493: 
        !           494:   if (XVECLEN (exp, 1) != num_alt)
        !           495:     fatal ("Bad number of entries in SET_ATTR_ALTERNATIVE for insn %d",
        !           496:           insn_index);
        !           497: 
        !           498:   /* Make a COND with all tests but the last.  Select the last value via the
        !           499:      default.  */
        !           500:   condexp = rtx_alloc (COND);
        !           501:   XVEC (condexp, 0) = rtvec_alloc ((num_alt - 1) * 2);
        !           502: 
        !           503:   for (i = 0; i < num_alt - 1; i++)
        !           504:     {
        !           505:       XVECEXP (condexp, 0, 2 * i) = rtx_alloc (EQ_ATTR);
        !           506:       XSTR (XVECEXP (condexp, 0, 2 * i), 0) = alternative_name;
        !           507:       XSTR (XVECEXP (condexp, 0, 2 * i), 1) = (char *) xmalloc (3);
        !           508:       sprintf (XSTR (XVECEXP (condexp, 0, 2 * i), 1), "%d", i);
        !           509:       XVECEXP (condexp, 0, 2 * i + 1) = XVECEXP (exp, 1, i);
        !           510:     }
        !           511: 
        !           512:   XEXP (condexp, 1) = XVECEXP (exp, 1, i);
        !           513: 
        !           514:   newexp = rtx_alloc (SET);
        !           515:   XEXP (newexp, 0) = rtx_alloc (ATTR);
        !           516:   XSTR (XEXP (newexp, 0), 0) = XSTR (exp, 0);
        !           517:   XEXP (newexp, 1) = condexp;
        !           518: 
        !           519:   return newexp;
        !           520: }
        !           521: 
        !           522: /* Given a SET_ATTR, convert to the appropriate SET.  If a comma-separated
        !           523:    list of values is given, convert to SET_ATTR_ALTERNATIVE first.  */
        !           524: 
        !           525: static rtx
        !           526: convert_set_attr (exp, num_alt, insn_code, insn_index)
        !           527:      rtx exp;
        !           528:      int num_alt;
        !           529:      int insn_code, insn_index;
        !           530: {
        !           531:   rtx newexp;
        !           532:   char *name_ptr;
        !           533:   char *p;
        !           534:   int n;
        !           535: 
        !           536:   /* See how many alternative specified.  */
        !           537:   n = n_comma_elts (XSTR (exp, 1));
        !           538:   if (n == 1)
        !           539:     {
        !           540:       newexp = rtx_alloc (SET);
        !           541:       XEXP (newexp, 0) = rtx_alloc (ATTR);
        !           542:       XSTR (XEXP (newexp, 0), 0) = XSTR (exp, 0);
        !           543:       XEXP (newexp, 1) = rtx_alloc (CONST_STRING);
        !           544:       XSTR (XEXP (newexp, 1), 0) = XSTR (exp, 1);
        !           545: 
        !           546:       return newexp;
        !           547:     }
        !           548: 
        !           549:   newexp = rtx_alloc (SET_ATTR_ALTERNATIVE);
        !           550:   XSTR (newexp, 0) = XSTR (exp, 0);
        !           551:   XVEC (newexp, 1) = rtvec_alloc (n);
        !           552: 
        !           553:   /* Process each comma-separated name.  */
        !           554:   name_ptr = XSTR (exp, 1);
        !           555:   n = 0;
        !           556:   while ((p = next_comma_elt (&name_ptr)) != NULL)
        !           557:     {
        !           558:       XVECEXP (newexp, 1, n) = rtx_alloc (CONST_STRING);
        !           559:       XSTR (XVECEXP (newexp, 1, n++), 0) = p;
        !           560:     }
        !           561: 
        !           562:   return convert_set_attr_alternative (newexp, num_alt, insn_code, insn_index);
        !           563: }
        !           564: 
        !           565: /* Scan all definitions, checking for validity.  Also, convert any SET_ATTR
        !           566:    and SET_ATTR_ALTERNATIVE expressions to the corresponding SET
        !           567:    expressions. */
        !           568: 
        !           569: static void
        !           570: check_defs ()
        !           571: {
        !           572:   struct insn_def *id;
        !           573:   struct attr_desc *attr;
        !           574:   int i;
        !           575:   rtx value;
        !           576: 
        !           577:   for (id = defs; id; id = id->next)
        !           578:     {
        !           579:       if (XVEC (id->def, id->vec_idx) == NULL)
        !           580:        continue;
        !           581: 
        !           582:       for (i = 0; i < XVECLEN (id->def, id->vec_idx); i++)
        !           583:        {
        !           584:          value = XVECEXP (id->def, id->vec_idx, i);
        !           585:          switch (GET_CODE (value))
        !           586:            {
        !           587:            case SET:
        !           588:              if (GET_CODE (XEXP (value, 0)) != ATTR)
        !           589:                fatal ("Bad attribute set in pattern %d", id->insn_index);
        !           590:              break;
        !           591: 
        !           592:            case SET_ATTR_ALTERNATIVE:
        !           593:              value = convert_set_attr_alternative (value,
        !           594:                                                    id->num_alternatives,
        !           595:                                                    id->insn_code,
        !           596:                                                    id->insn_index);
        !           597:              break;
        !           598: 
        !           599:            case SET_ATTR:
        !           600:              value = convert_set_attr (value, id->num_alternatives,
        !           601:                                        id->insn_code, id->insn_index);
        !           602:              break;
        !           603: 
        !           604:            default:
        !           605:              fatal ("Invalid attribute code `%s' for pattern %d",
        !           606:                     GET_RTX_NAME (GET_CODE (value)), id->insn_index);
        !           607:            }
        !           608: 
        !           609:          if ((attr = find_attr (XSTR (XEXP (value, 0), 0), 0)) == NULL)
        !           610:            fatal ("Unknown attribute `%s' for pattern number %d",
        !           611:                   XSTR (XEXP (value, 0), 0), id->insn_index);
        !           612: 
        !           613:          XVECEXP (id->def, id->vec_idx, i) = value;
        !           614:          check_attr_value (XEXP (value, 1), attr);
        !           615:        }
        !           616:     }
        !           617: }
        !           618: 
        !           619: /* Given a valid expression for an attribute value, remove any IF_THEN_ELSE
        !           620:    expressions by converting them into a COND.  This removes cases from this
        !           621:    program.  Also, replace an attribute value of "*" with the default attribute
        !           622:    value.  */
        !           623: 
        !           624: static rtx
        !           625: make_canonical (attr, exp)
        !           626:      struct attr_desc *attr;
        !           627:      rtx exp;
        !           628: {
        !           629:   int i;
        !           630:   rtx newexp;
        !           631: 
        !           632:   switch (GET_CODE (exp))
        !           633:     {
        !           634:     case CONST_INT:
        !           635:       exp = make_numeric_value (INTVAL (exp));
        !           636:       break;
        !           637: 
        !           638:     case CONST_STRING:
        !           639:       if (! strcmp (XSTR (exp, 0), "*"))
        !           640:        {
        !           641:          if (attr == 0 || attr->default_val == 0)
        !           642:            fatal ("(attr_value \"*\") used in invalid context.");
        !           643:          exp = attr->default_val->value;
        !           644:        }
        !           645: 
        !           646:       break;
        !           647: 
        !           648:     case IF_THEN_ELSE:
        !           649:       newexp = rtx_alloc (COND);
        !           650:       XVEC (newexp, 0) = rtvec_alloc (2);
        !           651:       XVECEXP (newexp, 0, 0) = XEXP (exp, 0);
        !           652:       XVECEXP (newexp, 0, 1) = XEXP (exp, 1);
        !           653: 
        !           654:       XEXP (newexp, 1) = XEXP (exp, 2);
        !           655: 
        !           656:       exp = newexp;
        !           657:       /* Fall through to COND case since this is now a COND.  */
        !           658: 
        !           659:     case COND:
        !           660:       /* First, check for degenerate COND. */
        !           661:       if (XVECLEN (exp, 0) == 0)
        !           662:        return make_canonical (attr, XEXP (exp, 1));
        !           663: 
        !           664:       for (i = 0; i < XVECLEN (exp, 0); i += 2)
        !           665:        XVECEXP (exp, 0, i + 1)
        !           666:                = make_canonical (attr, XVECEXP (exp, 0, i + 1));
        !           667: 
        !           668:       XEXP (exp, 1) = make_canonical (attr, XEXP (exp, 1));
        !           669:       break;
        !           670:     }
        !           671: 
        !           672:   return exp;
        !           673: }
        !           674: 
        !           675: /* Given a value and an attribute description, return a `struct attr_value *'
        !           676:    that represents that value.  This is either an existing structure, if the
        !           677:    value has been previously encountered, or a newly-created structure.
        !           678: 
        !           679:    `insn_code' is the code of an insn whose attribute has the specified
        !           680:    value (-2 if not processing an insn).  We ensure that all insns for
        !           681:    a given value have the same number of alternatives if the value checks
        !           682:    alternatives.  */
        !           683: 
        !           684: static struct attr_value *
        !           685: get_attr_value (value, attr, insn_code)
        !           686:      rtx value;
        !           687:      struct attr_desc *attr;
        !           688:      int insn_code;
        !           689: {
        !           690:   struct attr_value *av;
        !           691:   int num_alt = 0;
        !           692: 
        !           693:   value = make_canonical (attr, value);
        !           694:   if (compares_alternatives_p (value))
        !           695:     {
        !           696:       if (insn_code < 0 || insn_alternatives == NULL)
        !           697:        fatal ("(eq_attr \"alternatives\" ...) used in non-insn context");
        !           698:       else
        !           699:        num_alt = insn_alternatives[insn_code];
        !           700:     }
        !           701: 
        !           702:   for (av = attr->first_value; av; av = av->next)
        !           703:     if (rtx_equal_p (value, av->value)
        !           704:        && (num_alt == 0 || av->first_insn == NULL
        !           705:            || insn_alternatives[av->first_insn->insn_code]))
        !           706:       return av;
        !           707: 
        !           708:   av = (struct attr_value *) xmalloc (sizeof (struct attr_value));
        !           709:   av->value = value;
        !           710:   av->next = attr->first_value;
        !           711:   attr->first_value = av;
        !           712:   av->first_insn = NULL;
        !           713:   av->num_insns = 0;
        !           714:   av->has_asm_insn = 0;
        !           715: 
        !           716:   return av;
        !           717: }
        !           718: 
        !           719: /* After all DEFINE_DELAYs have been read in, create internal attributes
        !           720:    to generate the required routines.
        !           721: 
        !           722:    First, we compute the number of delay slots for each insn (as a COND of
        !           723:    each of the test expressions in DEFINE_DELAYs).  Then, if more than one
        !           724:    delay type is specified, we compute a similar function giving the
        !           725:    DEFINE_DELAY ordinal for each insn.
        !           726: 
        !           727:    Finally, for each [DEFINE_DELAY, slot #] pair, we compute an attribute that
        !           728:    tells whether a given insn can be in that delay slot.
        !           729: 
        !           730:    Normal attrbute filling and optimization expands these to contain the
        !           731:    information needed to handle delay slots.  */
        !           732: 
        !           733: static void
        !           734: expand_delays ()
        !           735: {
        !           736:   struct delay_desc *delay;
        !           737:   rtx condexp;
        !           738:   rtx newexp;
        !           739:   int i;
        !           740:   char *p;
        !           741: 
        !           742:   /* First, generate data for `num_delay_slots' function.  */
        !           743: 
        !           744:   condexp = rtx_alloc (COND);
        !           745:   XVEC (condexp, 0) = rtvec_alloc (num_delays * 2);
        !           746:   XEXP (condexp, 1) = make_numeric_value (0);
        !           747: 
        !           748:   for (i = 0, delay = delays; delay; i += 2, delay = delay->next)
        !           749:     {
        !           750:       XVECEXP (condexp, 0, i) = XEXP (delay->def, 0);
        !           751:       XVECEXP (condexp, 0, i + 1)
        !           752:        = make_numeric_value (XVECLEN (delay->def, 1) / 3);
        !           753:     }
        !           754: 
        !           755:   make_internal_attr ("*num_delay_slots", condexp, 0);
        !           756: 
        !           757:   /* If more than one delay type, do the same for computing the delay type.  */
        !           758:   if (num_delays > 1)
        !           759:     {
        !           760:       condexp = rtx_alloc (COND);
        !           761:       XVEC (condexp, 0) = rtvec_alloc (num_delays * 2);
        !           762:       XEXP (condexp, 1) = make_numeric_value (0);
        !           763: 
        !           764:       for (i = 0, delay = delays; delay; i += 2, delay = delay->next)
        !           765:        {
        !           766:          XVECEXP (condexp, 0, i) = XEXP (delay->def, 0);
        !           767:          XVECEXP (condexp, 0, i + 1) = make_numeric_value (delay->num);
        !           768:        }
        !           769: 
        !           770:       make_internal_attr ("*delay_type", condexp, 1);
        !           771:     }
        !           772: 
        !           773:   /* For each delay possibility and delay slot, compute an eligability
        !           774:      attribute for non-anulled insns and for each type of annulled (annul
        !           775:      if true and annul if false).  */
        !           776:  for (delay = delays; delay; delay = delay->next)
        !           777:    {
        !           778:      for (i = 0; i < XVECLEN (delay->def, 1); i += 3)
        !           779:        {
        !           780:         newexp = rtx_alloc (IF_THEN_ELSE);
        !           781:         condexp = XVECEXP (delay->def, 1, i);
        !           782:         if (condexp == 0) condexp = false_rtx;
        !           783:         XEXP (newexp, 0) = condexp;
        !           784:         XEXP (newexp, 1) = make_numeric_value (1);
        !           785:         XEXP (newexp, 2) = make_numeric_value (0);
        !           786: 
        !           787:         p = (char *) xmalloc (13);
        !           788:         sprintf (p, "*delay_%d_%d", delay->num, i / 3);
        !           789:         make_internal_attr (p, newexp, 1);
        !           790: 
        !           791:         if (have_annul_true)
        !           792:           {
        !           793:             newexp = rtx_alloc (IF_THEN_ELSE);
        !           794:             condexp = XVECEXP (delay->def, 1, i + 1);
        !           795:             if (condexp == 0) condexp = false_rtx;
        !           796:             XEXP (newexp, 0) = condexp;
        !           797:             XEXP (newexp, 1) = make_numeric_value (1);
        !           798:             XEXP (newexp, 2) = make_numeric_value (0);
        !           799:             p = (char *) xmalloc (18);
        !           800:             sprintf (p, "*annul_true_%d_%d", delay->num, i / 3);
        !           801:             make_internal_attr (p, newexp, 1);
        !           802:           }
        !           803: 
        !           804:         if (have_annul_false)
        !           805:           {
        !           806:             newexp = rtx_alloc (IF_THEN_ELSE);
        !           807:             condexp = XVECEXP (delay->def, 1, i + 2);
        !           808:             if (condexp == 0) condexp = false_rtx;
        !           809:             XEXP (newexp, 0) = condexp;
        !           810:             XEXP (newexp, 1) = make_numeric_value (1);
        !           811:             XEXP (newexp, 2) = make_numeric_value (0);
        !           812:             p = (char *) xmalloc (18);
        !           813:             sprintf (p, "*annul_false_%d_%d", delay->num, i / 3);
        !           814:             make_internal_attr (p, newexp, 1);
        !           815:           }
        !           816:        }
        !           817:    }
        !           818: }
        !           819: 
        !           820: /* This function is given a left and right side expression and an operator.
        !           821:    Each side is a conditional expression, each alternative of which has a
        !           822:    numerical value.  The function returns another conditional expression
        !           823:    which, for every possible set of condition values, returns a value that is
        !           824:    the operator applied to the values of the two sides.
        !           825: 
        !           826:    Since this is called early, it must also support IF_THEN_ELSE.  */
        !           827: 
        !           828: static rtx
        !           829: operate_exp (op, left, right)
        !           830:      enum operator op;
        !           831:      rtx left, right;
        !           832: {
        !           833:   int left_value, right_value;
        !           834:   rtx newexp;
        !           835:   int i;
        !           836: 
        !           837:   /* If left is a string, apply operator to it and the right side.  */
        !           838:   if (GET_CODE (left) == CONST_STRING)
        !           839:     {
        !           840:       /* If right is also a string, just perform the operation.  */
        !           841:       if (GET_CODE (right) == CONST_STRING)
        !           842:        {
        !           843:          left_value = atoi (XSTR (left, 0));
        !           844:          right_value = atoi (XSTR (right, 0));
        !           845:          switch (op)
        !           846:            {
        !           847:            case PLUS_OP:
        !           848:              i = left_value + right_value;
        !           849:              break;
        !           850: 
        !           851:            case MINUS_OP:
        !           852:              i = left_value - right_value;
        !           853:              break;
        !           854: 
        !           855:            case OR_OP:
        !           856:              i = left_value | right_value;
        !           857:              break;
        !           858: 
        !           859:            case MAX_OP:
        !           860:              if (left_value > right_value)
        !           861:                i = left_value;
        !           862:              else
        !           863:                i = right_value;
        !           864:              break;
        !           865: 
        !           866:            default:
        !           867:              abort ();
        !           868:            }
        !           869: 
        !           870:          return make_numeric_value (i);
        !           871:        }
        !           872:       else if (GET_CODE (right) == IF_THEN_ELSE)
        !           873:        {
        !           874:          /* Apply recursively to all values within.  */
        !           875:          newexp = rtx_alloc (IF_THEN_ELSE);
        !           876:          XEXP (newexp, 0) = XEXP (right, 0);
        !           877:          XEXP (newexp, 1) = operate_exp (op, left, XEXP (right, 1));
        !           878:          XEXP (newexp, 2) = operate_exp (op, left, XEXP (right, 2));
        !           879: 
        !           880:          return newexp;
        !           881:        }
        !           882:       else if (GET_CODE (right) == COND)
        !           883:        {
        !           884:          newexp = rtx_alloc (COND);
        !           885:          XVEC (newexp, 0) = rtvec_alloc (XVECLEN (right, 0));
        !           886:          for (i = 0; i < XVECLEN (right, 0); i += 2)
        !           887:            {
        !           888:              XVECEXP (newexp, 0, i) = XVECEXP (right, 0, i);
        !           889:              XVECEXP (newexp, 0, i + 1)
        !           890:                = operate_exp (op, left, XVECEXP (right, 0, i + 1));
        !           891:            }
        !           892: 
        !           893:          XEXP (newexp, 1) = operate_exp (op, left, XEXP (right, 1));
        !           894: 
        !           895:          return newexp;
        !           896:        }
        !           897:       else
        !           898:        fatal ("Badly formed attribute value");
        !           899:     }
        !           900: 
        !           901:   /* Otherwise, do recursion the other way.  */
        !           902:   else if (GET_CODE (left) == IF_THEN_ELSE)
        !           903:     {
        !           904:       newexp = rtx_alloc (IF_THEN_ELSE);
        !           905:       XEXP (newexp, 0) = XEXP (left, 0);
        !           906:       XEXP (newexp, 1) = operate_exp (op, XEXP (left, 1), right);
        !           907:       XEXP (newexp, 2) = operate_exp (op, XEXP (left, 2), right);
        !           908: 
        !           909:       return newexp;
        !           910:     }
        !           911: 
        !           912:   else if (GET_CODE (left) == COND)
        !           913:     {
        !           914:       newexp = rtx_alloc (COND);
        !           915:       XVEC (newexp, 0) = rtvec_alloc (XVECLEN (left, 0));
        !           916:       for (i = 0; i < XVECLEN (left, 0); i += 2)
        !           917:        {
        !           918:          XVECEXP (newexp, 0, i) = XVECEXP (left, 0, i);
        !           919:          XVECEXP (newexp, 0, i + 1)
        !           920:            = operate_exp (op, XVECEXP (left, 0, i + 1), right);
        !           921:        }
        !           922: 
        !           923:       XEXP (newexp, 1) = operate_exp (op, XEXP (left, 1), right);
        !           924: 
        !           925:       return newexp;
        !           926:     }
        !           927: 
        !           928:   else
        !           929:     fatal ("Badly formed attribute value.");
        !           930:   /* NOTREACHED */
        !           931:   return NULL;
        !           932: }
        !           933: 
        !           934: /* Once all attributes and DEFINE_FUNCTION_UNITs have been read, we
        !           935:    construct a number of attributes.
        !           936: 
        !           937:    The first produces a function `function_units_used' which is given an
        !           938:    insn and produces a mask showing which function units are required for
        !           939:    the execution of that insn.
        !           940: 
        !           941:    The second produces a function `result_ready_cost' which is used to
        !           942:    determine the time that the result of an insn will be ready and hence
        !           943:    a worst-case schedule.
        !           944: 
        !           945:    Both of these produce quite complex expressions which are then set as the
        !           946:    default value of internal attributes.  Normal attribute simplification
        !           947:    should produce reasonable expressions.
        !           948: 
        !           949:    For each unit, a `<name>_unit_ready_cost' function will take an
        !           950:    insn and give the delay until that unit will be ready with the result
        !           951:    and a `<name>_unit_busy_delay' function is given an insn already
        !           952:    executing on the unit and a candidate to execute and will give the
        !           953:    cost from the time the executing insn started until the candidate
        !           954:    can start (ignore limitations on the number of simultaneous insns).  */
        !           955: 
        !           956: static void
        !           957: expand_units ()
        !           958: {
        !           959:   struct function_unit *unit;
        !           960:   struct function_unit_op *op;
        !           961:   rtx unitsmask;
        !           962:   rtx readycost;
        !           963:   rtx newexp;
        !           964:   char *str;
        !           965: 
        !           966:   /* Initially, cost and masks are zero.  */
        !           967:   unitsmask = readycost = make_numeric_value (0);
        !           968: 
        !           969:   /* Set up a conditional for costs and unit mask.  */
        !           970:   newexp = rtx_alloc (IF_THEN_ELSE);
        !           971:   XEXP (newexp, 2) = make_numeric_value (0);
        !           972: 
        !           973:   /* For each unit, insert its contribution to the above three values.  */
        !           974:   for (unit = units; unit; unit = unit->next)
        !           975:     {
        !           976:       /* An expression that computes the ready cost for this unit.  */
        !           977:       rtx readyexp = rtx_alloc (COND);
        !           978:       /* An expression that maps insns to operation number for conflicts.  */
        !           979:       rtx caseexp = rtx_alloc (COND);
        !           980: 
        !           981:       XVEC (readyexp, 0) = rtvec_alloc ((unit->num_opclasses - 1) * 2);
        !           982:       XVEC (caseexp, 0) = rtvec_alloc ((unit->num_opclasses - 1) * 2);
        !           983: 
        !           984:       for (op = unit->ops; op; op = op->next)
        !           985:        {
        !           986:          str = (char *) xmalloc (strlen (unit->name) + 11);
        !           987: 
        !           988:          /* Validate the expressions we were given for the conditions
        !           989:             and busy cost.  Then make an attribute for use in the conflict
        !           990:             function.  */
        !           991:          op->condexp = check_attr_test (op->condexp);
        !           992:          check_attr_value (op->busyexp, 0);
        !           993:          sprintf (str, "*%s_case_%d", unit->name, op->num);
        !           994:          make_internal_attr (str, make_canonical (0, op->busyexp));
        !           995: 
        !           996:          /* Make our adjustment to the two COND's being computed.  If we are
        !           997:             the last operation class, place our values into the default of
        !           998:             the COND.  */
        !           999:          if (op->num == unit->num_opclasses - 1)
        !          1000:            {
        !          1001:              XEXP (readyexp, 1) = make_numeric_value (op->ready);
        !          1002:              XEXP (caseexp, 1) = make_numeric_value (op->num);
        !          1003:            }
        !          1004:          else
        !          1005:            {
        !          1006:              XVECEXP (readyexp, 0, op->num * 2) = op->condexp;
        !          1007:              XVECEXP (readyexp, 0, op->num * 2 + 1)
        !          1008:                = make_numeric_value (op->ready);
        !          1009:              XVECEXP (caseexp, 0, op->num * 2) = op->condexp;
        !          1010:              XVECEXP (caseexp, 0, op->num * 2 + 1)
        !          1011:                = make_numeric_value (op->num);
        !          1012:            }
        !          1013:        }
        !          1014: 
        !          1015:       /* Make an attribute for the case number and ready delay.  */
        !          1016:       str = (char *) xmalloc (strlen (unit->name) + 8);
        !          1017:       sprintf (str, "*%s_cases", unit->name);
        !          1018:       make_internal_attr (str, caseexp, 1);
        !          1019: 
        !          1020:       str = (char *) xmalloc (strlen (unit->name) + 20);
        !          1021:       sprintf (str, "*%s_unit_ready_cost", unit->name);
        !          1022:       make_internal_attr (str, readyexp, 0);
        !          1023: 
        !          1024:       /* Merge this function unit into the ready cost and unit mask
        !          1025:         attributes.  */
        !          1026:       XEXP (newexp, 0) = check_attr_test (unit->condexp);
        !          1027:       XEXP (newexp, 1) = make_numeric_value (1 << unit->num);
        !          1028:       unitsmask = operate_exp (OR_OP, unitsmask, newexp);
        !          1029: 
        !          1030:       XEXP (newexp, 1) = readyexp;
        !          1031:       readycost = operate_exp (MAX_OP, readycost, newexp);
        !          1032:     }
        !          1033: 
        !          1034:   make_internal_attr ("*function_units_used", unitsmask, 0);
        !          1035:   make_internal_attr ("*result_ready_cost", readycost, 0);
        !          1036: }
        !          1037: 
        !          1038: /* Once all attributes and insns have been read and checked, we construct for
        !          1039:    each attribute value a list of all the insns that have that value for
        !          1040:    the attribute.  */
        !          1041: 
        !          1042: static void
        !          1043: fill_attr (attr)
        !          1044:      struct attr_desc *attr;
        !          1045: {
        !          1046:   struct attr_value *av;
        !          1047:   struct insn_ent *ie;
        !          1048:   struct insn_def *id;
        !          1049:   int i;
        !          1050:   rtx value;
        !          1051: 
        !          1052:   for (id = defs; id; id = id->next)
        !          1053:     {
        !          1054:       /* If no value is specified for this insn for this attribute, use the
        !          1055:         default.  */
        !          1056:       value = NULL;
        !          1057:       if (XVEC (id->def, id->vec_idx))
        !          1058:        for (i = 0; i < XVECLEN (id->def, id->vec_idx); i++)
        !          1059:          if (! strcmp (XSTR (XEXP (XVECEXP (id->def, id->vec_idx, i), 0), 0), 
        !          1060:                        attr->name))
        !          1061:            value = XEXP (XVECEXP (id->def, id->vec_idx, i), 1);
        !          1062: 
        !          1063:       if (value == NULL)
        !          1064:        av = attr->default_val;
        !          1065:       else
        !          1066:        av = get_attr_value (value, attr, id->insn_code);
        !          1067: 
        !          1068:       ie = (struct insn_ent *) xmalloc (sizeof (struct insn_ent));
        !          1069:       ie->insn_code = id->insn_code;
        !          1070:       ie->insn_index = id->insn_code;
        !          1071:       insert_insn_ent (av, ie);
        !          1072:     }
        !          1073: }
        !          1074: 
        !          1075: /* Given an expression EXP, see if it is a COND or IF_THEN_ELSE that has a
        !          1076:    test that checks relative positions of insns (uses MATCH_DUP or PC).
        !          1077:    If so, replace it with what is obtained by passing the expression to
        !          1078:    ADDRESS_FN.  If not but it is a COND or IF_THEN_ELSE, call this routine
        !          1079:    recursively on each value (including the default value).  Otherwise,
        !          1080:    return the value returned by NO_ADDRESS_FN applied to EXP.  */
        !          1081: 
        !          1082: static rtx
        !          1083: substitute_address (exp, no_address_fn, address_fn)
        !          1084:      rtx exp;
        !          1085:      rtx (*no_address_fn) ();
        !          1086:      rtx (*address_fn) ();
        !          1087: {
        !          1088:   int i;
        !          1089:   rtx newexp;
        !          1090: 
        !          1091:   if (GET_CODE (exp) == COND)
        !          1092:     {
        !          1093:       /* See if any tests use addresses.  */
        !          1094:       address_used = 0;
        !          1095:       for (i = 0; i < XVECLEN (exp, 0); i += 2)
        !          1096:        walk_attr_value (XVECEXP (exp, 0, i));
        !          1097: 
        !          1098:       if (address_used)
        !          1099:        return (*address_fn) (exp);
        !          1100: 
        !          1101:       /* Make a new copy of this COND, replacing each element.  */
        !          1102:       newexp = rtx_alloc (COND);
        !          1103:       XVEC (newexp, 0) = rtvec_alloc (XVECLEN (exp, 0));
        !          1104:       for (i = 0; i < XVECLEN (exp, 0); i += 2)
        !          1105:        {
        !          1106:          XVECEXP (newexp, 0, i) = XVECEXP (exp, 0, i);
        !          1107:          XVECEXP (newexp, 0, i + 1)
        !          1108:            = substitute_address (XVECEXP (exp, 0, i + 1),
        !          1109:                                  no_address_fn, address_fn);
        !          1110:        }
        !          1111: 
        !          1112:       XEXP (newexp, 1) = substitute_address (XEXP (exp, 1),
        !          1113:                                             no_address_fn, address_fn);
        !          1114: 
        !          1115:       return newexp;
        !          1116:     }
        !          1117: 
        !          1118:   else if (GET_CODE (exp) == IF_THEN_ELSE)
        !          1119:     {
        !          1120:       address_used = 0;
        !          1121:       walk_attr_value (XEXP (exp, 0));
        !          1122:       if (address_used)
        !          1123:        return (*address_fn) (exp);
        !          1124: 
        !          1125:       newexp = rtx_alloc (IF_THEN_ELSE);
        !          1126:       XEXP (newexp, 0) = substitute_address (XEXP (exp, 0),
        !          1127:                                             no_address_fn, address_fn);
        !          1128:       XEXP (newexp, 1) = substitute_address (XEXP (exp, 1),
        !          1129:                                             no_address_fn, address_fn);
        !          1130:       XEXP (newexp, 2) = substitute_address (XEXP (exp, 2),
        !          1131:                                             no_address_fn, address_fn);
        !          1132: 
        !          1133:       return newexp;
        !          1134:     }
        !          1135: 
        !          1136:   return (*no_address_fn) (exp);
        !          1137: }
        !          1138: 
        !          1139: /* Make new attributes from the `length' attribute.  The following are made,
        !          1140:    each corresponding to a function called from `shorten_branches' or
        !          1141:    `get_attr_length':
        !          1142: 
        !          1143:    *insn_default_length                This is the length of the insn to be returned
        !          1144:                                by `get_attr_length' before `shorten_branches'
        !          1145:                                has been called.  In each case where the length
        !          1146:                                depends on relative addresses, the largest
        !          1147:                                possible is used.  This routine is also used
        !          1148:                                to compute the initial size of the insn.
        !          1149: 
        !          1150:    *insn_variable_length_p     This returns 1 if the insn's length depends
        !          1151:                                on relative addresses, zero otherwise.
        !          1152: 
        !          1153:    *insn_current_length                This is only called when it is known that the
        !          1154:                                insn has a variable length and returns the
        !          1155:                                current length, based on relative addresses.
        !          1156:   */
        !          1157: 
        !          1158: static void
        !          1159: make_length_attrs ()
        !          1160: {
        !          1161:   static char *new_names[] = {"*insn_default_length",
        !          1162:                              "*insn_variable_length_p",
        !          1163:                              "*insn_current_length"};
        !          1164:   static rtx (*no_address_fn[]) () = {identity_fn, zero_fn, zero_fn};
        !          1165:   static rtx (*address_fn[]) () = {max_fn, one_fn, identity_fn};
        !          1166:   int i;
        !          1167:   struct attr_desc *length_attr, *new_attr;
        !          1168:   struct attr_value *av, *new_av;
        !          1169:   struct insn_ent *ie, *new_ie;
        !          1170: 
        !          1171:   /* See if length attribute is defined.  If so, it must be numeric.  Make
        !          1172:      it special so we don't output anything for it.  */
        !          1173:   length_attr = find_attr ("length", 0);
        !          1174:   if (length_attr == 0)
        !          1175:     return;
        !          1176: 
        !          1177:   if (! length_attr->is_numeric)
        !          1178:     fatal ("length attribute must be numeric.");
        !          1179: 
        !          1180:   length_attr->is_special = 1;
        !          1181: 
        !          1182:   /* Make each new attribute, in turn.  */
        !          1183:   for (i = 0; i < sizeof new_names / sizeof new_names[0]; i++)
        !          1184:     {
        !          1185:       make_internal_attr (new_names[i],
        !          1186:                          substitute_address (length_attr->default_val->value,
        !          1187:                                              no_address_fn[i], address_fn[i]),
        !          1188:                          0);
        !          1189:       new_attr = find_attr (new_names[i], 0);
        !          1190:       for (av = length_attr->first_value; av; av = av->next)
        !          1191:        for (ie = av->first_insn; ie; ie = ie->next)
        !          1192:          {
        !          1193:            new_av = get_attr_value (substitute_address (av->value,
        !          1194:                                                         no_address_fn[i],
        !          1195:                                                         address_fn[i]),
        !          1196:                                     new_attr, ie->insn_code);
        !          1197:            new_ie = (struct insn_ent *) xmalloc (sizeof (struct insn_ent));
        !          1198:            new_ie->insn_code = ie->insn_code;
        !          1199:            new_ie->insn_index = ie->insn_index;
        !          1200:            insert_insn_ent (new_av, new_ie);
        !          1201:          }
        !          1202:     }
        !          1203: }
        !          1204: 
        !          1205: /* Utility functions called from above routine.  */
        !          1206: 
        !          1207: static rtx
        !          1208: identity_fn (exp)
        !          1209:      rtx exp;
        !          1210: {
        !          1211:   return exp;
        !          1212: }
        !          1213: 
        !          1214: static rtx
        !          1215: zero_fn (exp)
        !          1216:      rtx exp;
        !          1217: {
        !          1218:   return make_numeric_value (0);
        !          1219: }
        !          1220: 
        !          1221: static rtx
        !          1222: one_fn (exp)
        !          1223:      rtx exp;
        !          1224: {
        !          1225:   return make_numeric_value (1);
        !          1226: }
        !          1227: 
        !          1228: static rtx
        !          1229: max_fn (exp)
        !          1230:      rtx exp;
        !          1231: {
        !          1232:   return make_numeric_value (max_attr_value (exp));
        !          1233: }
        !          1234: 
        !          1235: /* Take a COND expression and see if any of the conditions in it can be
        !          1236:    simplified.  If any are known true or known false for the particular insn
        !          1237:    code, the COND can be further simplified.
        !          1238: 
        !          1239:    Also call ourselves on any COND operations that are values of this COND.
        !          1240: 
        !          1241:    We only do the first replacement found directly and call ourselves
        !          1242:    recursively for subsequent replacements.  */
        !          1243: 
        !          1244: static rtx
        !          1245: simplify_cond (exp, insn_code, insn_index)
        !          1246:      rtx exp;
        !          1247:      int insn_code, insn_index;
        !          1248: {
        !          1249:   int i, j;
        !          1250:   rtx newtest;
        !          1251:   rtx value;
        !          1252:   rtx newexp = exp;
        !          1253: 
        !          1254:   for (i = 0; i < XVECLEN (exp, 0); i += 2)
        !          1255:     {
        !          1256:       newtest = SIMPLIFY_TEST_EXP (XVECEXP (exp, 0, i), insn_code, insn_index);
        !          1257:       if (newtest == true_rtx)
        !          1258:        {
        !          1259:          /* Make a new COND with any previous conditions and the value for
        !          1260:             this pair as the default value.  */
        !          1261:          newexp = rtx_alloc (COND);
        !          1262:          XVEC (newexp, 0) = rtvec_alloc (i);
        !          1263:          for (j = 0; j < i; j++)
        !          1264:            XVECEXP (newexp, 0, j) = XVECEXP (exp, 0, j);
        !          1265: 
        !          1266:          XEXP (newexp, 1) = XVECEXP (exp, 0, i + 1);
        !          1267:          break;
        !          1268:        }
        !          1269: 
        !          1270:       else if (newtest == false_rtx)
        !          1271:        {
        !          1272:          /* Build a new COND without this test.  */
        !          1273:          newexp = rtx_alloc (COND);
        !          1274:          XVEC (newexp, 0) = rtvec_alloc (XVECLEN (exp, 0) - 2);
        !          1275:          for (j = 0; j < i; j++)
        !          1276:            XVECEXP (newexp, 0, j) = XVECEXP (exp, 0, j);
        !          1277: 
        !          1278:          for (j = i; j < XVECLEN (newexp, 0); j++)
        !          1279:            XVECEXP (newexp, 0, j) = XVECEXP (exp, 0, j + 2);
        !          1280: 
        !          1281:          XEXP (newexp, 1) = XEXP (exp, 1);
        !          1282:          break;
        !          1283:        }
        !          1284: 
        !          1285:       else if (newtest != XVECEXP (exp, 0, i))
        !          1286:        {
        !          1287:          newexp = rtx_alloc (COND);
        !          1288:          XVEC (newexp, 0) = rtvec_alloc (XVECLEN (exp, 0));
        !          1289:          for (j = 0; j < XVECLEN (exp, 0); j++)
        !          1290:            XVECEXP (newexp, 0, j) = XVECEXP (exp, 0, j);
        !          1291:          XEXP (newexp, 1) = XEXP (exp, 1);
        !          1292: 
        !          1293:          XVECEXP (newexp, 0, i) = newtest;
        !          1294:          break;
        !          1295:        }
        !          1296: 
        !          1297:       /* See if this value may need simplification.  */
        !          1298:       if (GET_CODE (XVECEXP (exp, 0, i + 1)) == COND)
        !          1299:        {
        !          1300:          value = simplify_cond (XVECEXP (exp, 0, i + 1),
        !          1301:                                 insn_code, insn_index);
        !          1302:          if (value != XVECEXP (exp, 0, i + 1))
        !          1303:            {
        !          1304:              newexp = rtx_alloc (COND);
        !          1305:              XVEC (newexp, 0) = rtvec_alloc (XVECLEN (exp, 0));
        !          1306:              for (j = 0; j < XVECLEN (exp, 0); j++)
        !          1307:                XVECEXP (newexp, 0, j) = XVECEXP (exp, 0, j);
        !          1308:              XEXP (newexp, 1) = XEXP (exp, 1);
        !          1309: 
        !          1310:              XVECEXP (newexp, 0, i + 1) = value;
        !          1311:              break;
        !          1312:            }
        !          1313:        }
        !          1314: 
        !          1315:       /* If this is the last condition in a COND and our value is the same
        !          1316:         as the default value, our test isn't needed.  */
        !          1317:       if (i == XVECLEN (exp, 0) - 2
        !          1318:          && rtx_equal_p (XVECEXP (exp, 0, i + 1), XEXP (exp, 1)))
        !          1319:        {
        !          1320:          newexp = rtx_alloc (COND);
        !          1321:          XVEC (newexp, 0) = rtvec_alloc (XVECLEN (exp, 0) - 2);
        !          1322:          for (j = 0; j < i; j++)
        !          1323:            XVECEXP (newexp, 0, j) = XVECEXP (exp, 0, j);
        !          1324:          XEXP (newexp, 1) = XEXP (exp, 1);
        !          1325:          break;
        !          1326:        }
        !          1327: 
        !          1328:       /* If this value and the value for the next test are the same, merge the
        !          1329:          tests.  */
        !          1330:       else if (i != XVECLEN (exp, 0) - 2
        !          1331:               && rtx_equal_p (XVECEXP (exp, 0, i + 1),
        !          1332:                               XVECEXP (exp, 0, i + 3)))
        !          1333:        {
        !          1334:          newexp = rtx_alloc (COND);
        !          1335:          XVEC (newexp, 0) = rtvec_alloc (XVECLEN (exp, 0) - 2);
        !          1336:          for (j = 0; j < i; j++)
        !          1337:            XVECEXP (newexp, 0, j) = XVECEXP (exp, 0, j);
        !          1338: 
        !          1339:          XVECEXP (newexp, 0, j)
        !          1340:            = insert_right_side (IOR, XVECEXP (exp, 0, i),
        !          1341:                                 XVECEXP (exp, 0, i + 2),
        !          1342:                                 insn_code, insn_index);
        !          1343:          XVECEXP (newexp, 0, j + 1) = XVECEXP (exp, 0, i + 1);
        !          1344: 
        !          1345:          for (j = i + 2; j < XVECLEN (newexp, 0); j++)
        !          1346:            XVECEXP (newexp, 0, j) = XVECEXP (exp, 0, j + 2);
        !          1347: 
        !          1348:          XEXP (newexp, 1) = XEXP (exp, 1);
        !          1349:          break;
        !          1350:        }
        !          1351:     }
        !          1352: 
        !          1353:   /* See if default value needs simplification.  */
        !          1354:   if (GET_CODE (XEXP (exp, 1)) == COND)
        !          1355:     {
        !          1356:       value = simplify_cond (XEXP (exp, 1), insn_code, insn_index);
        !          1357:       if (value != XEXP (exp, 1))
        !          1358:        {
        !          1359:          newexp = rtx_alloc (COND);
        !          1360:          XVEC (newexp, 0) = rtvec_alloc (XVECLEN (exp, 0));
        !          1361:          for (j = 0; j < XVECLEN (exp, 0); j++)
        !          1362:            XVECEXP (newexp, 0, j) = XVECEXP (exp, 0, j);
        !          1363:          XEXP (newexp, 1) = value;
        !          1364:        }
        !          1365:     }
        !          1366:   
        !          1367:   if (exp == newexp)
        !          1368:     return exp;
        !          1369:   else if (XVECLEN (newexp, 0) == 1)
        !          1370:     return XVECEXP (newexp, 0, 0);
        !          1371:   else
        !          1372:     return simplify_cond (newexp, insn_code, insn_index);
        !          1373: }
        !          1374: 
        !          1375: /* Remove an insn entry from an attribute value.  */
        !          1376: 
        !          1377: static void
        !          1378: remove_insn_ent (av, ie)
        !          1379:      struct attr_value *av;
        !          1380:      struct insn_ent *ie;
        !          1381: {
        !          1382:   struct insn_ent *previe;
        !          1383: 
        !          1384:   if (av->first_insn == ie)
        !          1385:     av->first_insn = ie->next;
        !          1386:   else
        !          1387:     {
        !          1388:       for (previe = av->first_insn; previe->next != ie; previe = previe->next)
        !          1389:        ;
        !          1390:       previe->next = ie->next;
        !          1391:     }
        !          1392: 
        !          1393:   av->num_insns--;
        !          1394:   if (ie->insn_code == -1)
        !          1395:     av->has_asm_insn = 0;
        !          1396: }
        !          1397: 
        !          1398: /* Insert an insn entry in an attribute value list.  */
        !          1399: 
        !          1400: static void
        !          1401: insert_insn_ent (av, ie)
        !          1402:      struct attr_value *av;
        !          1403:      struct insn_ent *ie;
        !          1404: {
        !          1405:   ie->next = av->first_insn;
        !          1406:   av->first_insn = ie;
        !          1407:   av->num_insns++;
        !          1408:   if (ie->insn_code == -1)
        !          1409:     av->has_asm_insn = 1;
        !          1410: }
        !          1411: 
        !          1412: /* This is a utility routine to take an expression that is a tree of either
        !          1413:    AND or IOR expressions and insert a new term.  The new term will be
        !          1414:    inserted at the right side of the first node whose code does not match
        !          1415:    the root.  A new node will be created with the root's code.  Its left
        !          1416:    side will be the old right side and its right side will be the new
        !          1417:    term.
        !          1418: 
        !          1419:    If the `term' is itself a tree, all its leaves will be inserted.  */
        !          1420: 
        !          1421: static rtx
        !          1422: insert_right_side (code, exp, term, insn_code, insn_index)
        !          1423:      RTX_CODE code;
        !          1424:      rtx exp;
        !          1425:      rtx term;
        !          1426:      int insn_code, insn_index;
        !          1427: {
        !          1428:   rtx newexp;
        !          1429: 
        !          1430:   if (GET_CODE (term) == code)
        !          1431:     {
        !          1432:       exp = insert_right_side (code, exp, XEXP (term, 0),
        !          1433:                               insn_code, insn_index);
        !          1434:       exp = insert_right_side (code, exp, XEXP (term, 1),
        !          1435:                               insn_code, insn_index);
        !          1436: 
        !          1437:       return exp;
        !          1438:     }
        !          1439: 
        !          1440:   if (GET_CODE (exp) == code)
        !          1441:     {
        !          1442:       /* Make a copy of this expression and call recursively.  */
        !          1443:       newexp = rtx_alloc (code);
        !          1444:       XEXP (newexp, 0) = XEXP (exp, 0);
        !          1445:       XEXP (newexp, 1) = insert_right_side (code, XEXP (exp, 1),
        !          1446:                                            term, insn_code, insn_index);
        !          1447:     }
        !          1448:   else
        !          1449:     {
        !          1450:       /* Insert the new term.  */
        !          1451:       newexp = rtx_alloc (code);
        !          1452:       XEXP (newexp, 0) = exp;
        !          1453:       XEXP (newexp, 1) = term;
        !          1454:       }
        !          1455: 
        !          1456:   return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
        !          1457: }
        !          1458: 
        !          1459: /* If we have an expression which AND's a bunch of
        !          1460:        (not (eq_attrq "alternative" "n"))
        !          1461:    terms, we may have covered all or all but one of the possible alternatives.
        !          1462:    If so, we can optimize.  Similarly for IOR's of EQ_ATTR.
        !          1463: 
        !          1464:    This routine is passed an expression and either AND or IOR.  It returns a
        !          1465:    bitmask indicating which alternatives are present.  */
        !          1466: 
        !          1467: static int
        !          1468: compute_alternative_mask (exp, code)
        !          1469:      rtx exp;
        !          1470:      RTX_CODE code;
        !          1471: {
        !          1472:   if (GET_CODE (exp) == code)
        !          1473:     return compute_alternative_mask (XEXP (exp, 0), code)
        !          1474:           | compute_alternative_mask (XEXP (exp, 1), code);
        !          1475: 
        !          1476:   else if (code == AND && GET_CODE (exp) == NOT
        !          1477:           && GET_CODE (XEXP (exp, 0)) == EQ_ATTR
        !          1478:           && XSTR (XEXP (exp, 0), 0) == alternative_name)
        !          1479:     return 1 << atoi (XSTR (XEXP (exp, 0), 1));
        !          1480: 
        !          1481:   else if (code == IOR && GET_CODE (exp) == EQ_ATTR
        !          1482:           && XSTR (exp, 0) == alternative_name)
        !          1483:     return 1 << atoi (XSTR (exp, 1));
        !          1484: 
        !          1485:   else
        !          1486:     return 0;
        !          1487: }
        !          1488: 
        !          1489: /* Given I, a single-bit mask, return RTX to compare the `alternative'
        !          1490:    attribute with the value represented by that bit.  */
        !          1491: 
        !          1492: static rtx
        !          1493: make_alternative_compare (mask)
        !          1494:      int mask;
        !          1495: {
        !          1496:   rtx newexp;
        !          1497:   int i;
        !          1498:   char *alternative;
        !          1499: 
        !          1500:   /* Find the bit.  */
        !          1501:   for (i = 0; (mask & (1 << i)) == 0; i++)
        !          1502:     ;
        !          1503: 
        !          1504:   alternative = (char *) xmalloc (3);
        !          1505:   sprintf (alternative, "%d", i);
        !          1506: 
        !          1507:   newexp = rtx_alloc (EQ_ATTR);
        !          1508:   XSTR (newexp, 0) = alternative_name;
        !          1509:   XSTR (newexp, 1) = alternative;
        !          1510:   RTX_UNCHANGING_P (newexp) = 1;
        !          1511: 
        !          1512:   return newexp;
        !          1513: }
        !          1514: 
        !          1515: /* If we are processing an (eq_attr "attr" "value") test, we find the value
        !          1516:    of "attr" for this insn code.  From that value, we can compute a test
        !          1517:    showing when the EQ_ATTR will be true.  This routine performs that
        !          1518:    computation.  If a test condition involves an address, we leave the EQ_ATTR
        !          1519:    intact because addresses are only valid for the `length' attribute.  */
        !          1520: 
        !          1521: static rtx
        !          1522: evaluate_eq_attr (exp, value, insn_code, insn_index)
        !          1523:      rtx exp;
        !          1524:      rtx value;
        !          1525:      int insn_code, insn_index;
        !          1526: {
        !          1527:   rtx orexp, andexp;
        !          1528:   rtx right;
        !          1529:   rtx newexp;
        !          1530:   int i;
        !          1531: 
        !          1532:   if (GET_CODE (value) == CONST_STRING)
        !          1533:     {
        !          1534:       if (! strcmp (XSTR (value, 0), XSTR (exp, 1)))
        !          1535:        newexp = true_rtx;
        !          1536:       else
        !          1537:        newexp = false_rtx;
        !          1538:     }
        !          1539:   else if (GET_CODE (value) == COND)
        !          1540:     {
        !          1541:       /* We construct an IOR of all the cases for which the requested attribute
        !          1542:         value is present.  Since we start with FALSE, if it is not present,
        !          1543:         FALSE will be returned.
        !          1544: 
        !          1545:         Each case is the AND of the NOT's of the previous conditions with the
        !          1546:         current condition; in the default case the current condition is TRUE. 
        !          1547: 
        !          1548:         For each possible COND value, call ourselves recursively.
        !          1549: 
        !          1550:         The extra TRUE and FALSE expressions will be eliminated by another
        !          1551:         call to the simplification routine. */
        !          1552: 
        !          1553:       orexp = false_rtx;
        !          1554:       andexp = true_rtx;
        !          1555: 
        !          1556:       for (i = 0; i < XVECLEN (value, 0); i += 2)
        !          1557:        {
        !          1558:          right = insert_right_side (AND, andexp,
        !          1559:                                     XVECEXP (value, 0, i),
        !          1560:                                     insn_code, insn_index);
        !          1561:          right = insert_right_side (AND, right,
        !          1562:                        evaluate_eq_attr (exp, XVECEXP (value, 0, i + 1),
        !          1563:                                           insn_code, insn_index),
        !          1564:                                     insn_code, insn_index);
        !          1565:          orexp = insert_right_side (IOR, orexp, right,
        !          1566:                                     insn_code, insn_index);
        !          1567: 
        !          1568:          /* Add this condition into the AND expression.  */
        !          1569:          newexp = rtx_alloc (NOT);
        !          1570:          XEXP (newexp, 0) = XVECEXP (value, 0, i);
        !          1571:          andexp = insert_right_side (AND, andexp, newexp,
        !          1572:                                      insn_code, insn_index);
        !          1573:        }
        !          1574: 
        !          1575:       /* Handle the default case.  */
        !          1576:       right = insert_right_side (AND, andexp,
        !          1577:                                 evaluate_eq_attr (exp, XEXP (value, 1),
        !          1578:                                                    insn_code, insn_index),
        !          1579:                                 insn_code, insn_index);
        !          1580:       newexp = insert_right_side (IOR, orexp, right, insn_code, insn_index);
        !          1581:     }
        !          1582:   else
        !          1583:     abort ();
        !          1584: 
        !          1585:   /* If uses an address, must return original expression.  */
        !          1586: 
        !          1587:   address_used = 0;
        !          1588:   walk_attr_value (newexp);
        !          1589: 
        !          1590:   if (address_used)
        !          1591:     return exp;
        !          1592:   else
        !          1593:     return newexp;
        !          1594: }
        !          1595: 
        !          1596: /* This routine is called when an AND of a term with a tree of AND's is
        !          1597:    encountered.  If the term or its complement is present in the tree, it
        !          1598:    can be replaced with TRUE or FALSE, respectively.
        !          1599: 
        !          1600:    Note that (eq_attr "att" "v1") and (eq_attr "att" "v2") cannot both
        !          1601:    be true and hence are complementary.  
        !          1602: 
        !          1603:    There is one special case:  If we see
        !          1604:        (and (not (eq_attr "att" "v1"))
        !          1605:             (eq_attr "att" "v2"))
        !          1606:    this can be replaced by (eq_attr "att" "v2").  To do this we need to
        !          1607:    replace the term, not anything in the AND tree.  So we pass a pointer to
        !          1608:    the term.  */
        !          1609: 
        !          1610: static rtx
        !          1611: simplify_and_tree (exp, pterm, insn_code, insn_index)
        !          1612:      rtx exp;
        !          1613:      rtx *pterm;
        !          1614:      int insn_code, insn_index;
        !          1615: {
        !          1616:   rtx left, right;
        !          1617:   rtx newexp;
        !          1618:   rtx temp;
        !          1619:   int left_eliminates_term, right_eliminates_term;
        !          1620: 
        !          1621:   if (GET_CODE (exp) == AND)
        !          1622:     {
        !          1623:       left = simplify_and_tree (XEXP (exp, 0), pterm,  insn_code, insn_index);
        !          1624:       right = simplify_and_tree (XEXP (exp, 1), pterm, insn_code, insn_index);
        !          1625:       if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
        !          1626:        {
        !          1627:          newexp = rtx_alloc (GET_CODE (exp));
        !          1628:          XEXP (newexp, 0) = left;
        !          1629:          XEXP (newexp, 1) = right;
        !          1630: 
        !          1631:          exp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
        !          1632:        }
        !          1633:     }
        !          1634: 
        !          1635:   else if (GET_CODE (exp) == IOR)
        !          1636:     {
        !          1637:       /* For the IOR case, we do the same as above, except that we can
        !          1638:          only eliminate `term' if both sides of the IOR would do so.  */
        !          1639:       temp = *pterm;
        !          1640:       left = simplify_and_tree (XEXP (exp, 0), &temp,  insn_code, insn_index);
        !          1641:       left_eliminates_term = (temp == true_rtx);
        !          1642: 
        !          1643:       temp = *pterm;
        !          1644:       right = simplify_and_tree (XEXP (exp, 1), &temp, insn_code, insn_index);
        !          1645:       right_eliminates_term = (temp == true_rtx);
        !          1646: 
        !          1647:       if (left_eliminates_term && right_eliminates_term)
        !          1648:        *pterm = true_rtx;
        !          1649: 
        !          1650:       if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
        !          1651:        {
        !          1652:          newexp = rtx_alloc (GET_CODE (exp));
        !          1653:          XEXP (newexp, 0) = left;
        !          1654:          XEXP (newexp, 1) = right;
        !          1655: 
        !          1656:          exp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
        !          1657:        }
        !          1658:     }
        !          1659: 
        !          1660:   /* Check for simplifications.  Do some extra checking here since this
        !          1661:      routine is called so many times.  */
        !          1662: 
        !          1663:   if (exp == *pterm)
        !          1664:     return true_rtx;
        !          1665: 
        !          1666:   else if (GET_CODE (exp) == NOT && XEXP (exp, 0) == *pterm)
        !          1667:     return false_rtx;
        !          1668: 
        !          1669:   else if (GET_CODE (*pterm) == NOT && exp == XEXP (*pterm, 0))
        !          1670:     return false_rtx;
        !          1671: 
        !          1672:   else if (GET_CODE (exp) == EQ_ATTR && GET_CODE (*pterm) == EQ_ATTR)
        !          1673:     {
        !          1674:       if (XSTR (exp, 0) != XSTR (*pterm, 0))
        !          1675:        return exp;
        !          1676: 
        !          1677:       if (! strcmp (XSTR (exp, 1), XSTR (*pterm, 1)))
        !          1678:        return true_rtx;
        !          1679:       else
        !          1680:        return false_rtx;
        !          1681:     }
        !          1682: 
        !          1683:   else if (GET_CODE (*pterm) == EQ_ATTR && GET_CODE (exp) == NOT
        !          1684:           && GET_CODE (XEXP (exp, 0)) == EQ_ATTR)
        !          1685:     {
        !          1686:       if (XSTR (*pterm, 0) != XSTR (XEXP (exp, 0), 0))
        !          1687:        return exp;
        !          1688: 
        !          1689:       if (! strcmp (XSTR (*pterm, 1), XSTR (XEXP (exp, 0), 1)))
        !          1690:        return false_rtx;
        !          1691:       else
        !          1692:        return true_rtx;
        !          1693:     }
        !          1694: 
        !          1695:   else if (GET_CODE (exp) == EQ_ATTR && GET_CODE (*pterm) == NOT
        !          1696:           && GET_CODE (XEXP (*pterm, 0)) == EQ_ATTR)
        !          1697:     {
        !          1698:       if (XSTR (exp, 0) != XSTR (XEXP (*pterm, 0), 0))
        !          1699:        return exp;
        !          1700: 
        !          1701:       if (! strcmp (XSTR (exp, 1), XSTR (XEXP (*pterm, 0), 1)))
        !          1702:        return false_rtx;
        !          1703:       else
        !          1704:        *pterm = true_rtx;
        !          1705:     }
        !          1706: 
        !          1707:   else if (GET_CODE (exp) == NOT && GET_CODE (*pterm) == NOT)
        !          1708:     {
        !          1709:       if (rtx_equal_p (XEXP (exp, 0), XEXP (*pterm, 0)))
        !          1710:        return true_rtx;
        !          1711:     }
        !          1712: 
        !          1713:   else if (GET_CODE (exp) == NOT)
        !          1714:     {
        !          1715:       if (rtx_equal_p (XEXP (exp, 0), *pterm))
        !          1716:        return false_rtx;
        !          1717:     }
        !          1718: 
        !          1719:   else if (GET_CODE (*pterm) == NOT)
        !          1720:     {
        !          1721:       if (rtx_equal_p (XEXP (*pterm, 0), exp))
        !          1722:        return false_rtx;
        !          1723:     }
        !          1724: 
        !          1725:   else if (rtx_equal_p (exp, *pterm))
        !          1726:     return true_rtx;
        !          1727: 
        !          1728:   return exp;
        !          1729: }
        !          1730: 
        !          1731: /* Similiar to `simplify_and_tree', but for IOR trees.  */
        !          1732: 
        !          1733: static rtx
        !          1734: simplify_or_tree (exp, pterm, insn_code, insn_index)
        !          1735:      rtx exp;
        !          1736:      rtx *pterm;
        !          1737:      int insn_code, insn_index;
        !          1738: {
        !          1739:   rtx left, right;
        !          1740:   rtx newexp;
        !          1741:   rtx temp;
        !          1742:   int left_eliminates_term, right_eliminates_term;
        !          1743: 
        !          1744:   if (GET_CODE (exp) == IOR)
        !          1745:     {
        !          1746:       left = simplify_or_tree (XEXP (exp, 0), pterm,  insn_code, insn_index);
        !          1747:       right = simplify_or_tree (XEXP (exp, 1), pterm, insn_code, insn_index);
        !          1748:       if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
        !          1749:        {
        !          1750:          newexp = rtx_alloc (GET_CODE (exp));
        !          1751:          XEXP (newexp, 0) = left;
        !          1752:          XEXP (newexp, 1) = right;
        !          1753: 
        !          1754:          exp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
        !          1755:        }
        !          1756:     }
        !          1757: 
        !          1758:   else if (GET_CODE (exp) == AND)
        !          1759:     {
        !          1760:       /* For the AND case, we do the same as above, except that we can
        !          1761:          only eliminate `term' if both sides of the AND would do so.  */
        !          1762:       temp = *pterm;
        !          1763:       left = simplify_or_tree (XEXP (exp, 0), &temp,  insn_code, insn_index);
        !          1764:       left_eliminates_term = (temp == false_rtx);
        !          1765: 
        !          1766:       temp = *pterm;
        !          1767:       right = simplify_or_tree (XEXP (exp, 1), &temp, insn_code, insn_index);
        !          1768:       right_eliminates_term = (temp == false_rtx);
        !          1769: 
        !          1770:       if (left_eliminates_term && right_eliminates_term)
        !          1771:        *pterm = false_rtx;
        !          1772: 
        !          1773:       if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
        !          1774:        {
        !          1775:          newexp = rtx_alloc (GET_CODE (exp));
        !          1776:          XEXP (newexp, 0) = left;
        !          1777:          XEXP (newexp, 1) = right;
        !          1778: 
        !          1779:          exp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
        !          1780:        }
        !          1781:     }
        !          1782: 
        !          1783:   if (rtx_equal_p (exp, *pterm))
        !          1784:     return false_rtx;
        !          1785: 
        !          1786:   else if (GET_CODE (exp) == NOT && rtx_equal_p (XEXP (exp, 0), *pterm))
        !          1787:     return true_rtx;
        !          1788: 
        !          1789:   else if (GET_CODE (*pterm) == NOT && rtx_equal_p (XEXP (*pterm, 0), exp))
        !          1790:     return true_rtx;
        !          1791: 
        !          1792:   else if (GET_CODE (*pterm) == EQ_ATTR && GET_CODE (exp) == NOT
        !          1793:           && GET_CODE (XEXP (exp, 0)) == EQ_ATTR
        !          1794:           && XSTR (*pterm, 0) == XSTR (XEXP (exp, 0), 0))
        !          1795:     *pterm = false_rtx;
        !          1796: 
        !          1797:   else if (GET_CODE (exp) == EQ_ATTR && GET_CODE (*pterm) == NOT
        !          1798:           && GET_CODE (XEXP (*pterm, 0)) == EQ_ATTR
        !          1799:           && XSTR (exp, 0) == XSTR (XEXP (*pterm, 0), 0))
        !          1800:     return false_rtx;
        !          1801: 
        !          1802:   return exp;
        !          1803: }
        !          1804: 
        !          1805: /* Given an expression, see if it can be simplified for a particular insn
        !          1806:    code based on the values of other attributes being tested.  This can
        !          1807:    eliminate nested get_attr_... calls.
        !          1808: 
        !          1809:    Note that if an endless recursion is specified in the patterns, the 
        !          1810:    optimization will loop.  However, it will do so in precisely the cases where
        !          1811:    an infinite recursion loop could occur during compilation.  It's better that
        !          1812:    it occurs here!  */
        !          1813: 
        !          1814: static rtx
        !          1815: simplify_test_exp (exp, insn_code, insn_index)
        !          1816:      rtx exp;
        !          1817:      int insn_code, insn_index;
        !          1818: {
        !          1819:   rtx left, right;
        !          1820:   struct attr_desc *attr;
        !          1821:   struct attr_value *av;
        !          1822:   struct insn_ent *ie;
        !          1823:   int i;
        !          1824:   rtx newexp = exp;
        !          1825: 
        !          1826:   switch (GET_CODE (exp))
        !          1827:     {
        !          1828:     case AND:
        !          1829:       left = SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index);
        !          1830:       right = SIMPLIFY_TEST_EXP (XEXP (exp, 1), insn_code, insn_index);
        !          1831: 
        !          1832:       /* If either side is an IOR and we have (eq_attr "alternative" ..")
        !          1833:         present on both sides, apply the distributive law since this will
        !          1834:         yield simplications.  */
        !          1835:       if ((GET_CODE (left) == IOR || GET_CODE (right) == IOR)
        !          1836:          && compute_alternative_mask (left, IOR)
        !          1837:          && compute_alternative_mask (right, IOR))
        !          1838:        {
        !          1839:          if (GET_CODE (left) == IOR)
        !          1840:            {
        !          1841:              rtx tem = left;
        !          1842:              left = right;
        !          1843:              right = tem;
        !          1844:            }
        !          1845: 
        !          1846:          newexp = rtx_alloc (IOR);
        !          1847:          XEXP (newexp, 0) = rtx_alloc (AND);
        !          1848:          XEXP (newexp, 1) = rtx_alloc (AND);
        !          1849:          XEXP (XEXP (newexp, 0), 0) = XEXP (XEXP (newexp, 1), 0) = left;
        !          1850:          XEXP (XEXP (newexp, 0), 1) = XEXP (right, 0);
        !          1851:          XEXP (XEXP (newexp, 1), 1) = XEXP (right, 1);
        !          1852: 
        !          1853:          return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
        !          1854:        }
        !          1855: 
        !          1856:       /* Try with the term on both sides.  */
        !          1857:       right = simplify_and_tree (right, &left, insn_code, insn_index);
        !          1858:       if (left == XEXP (exp, 0) && right == XEXP (exp, 1))
        !          1859:        left = simplify_and_tree (left, &right, insn_code, insn_index);
        !          1860: 
        !          1861:       if (left == false_rtx || right == false_rtx)
        !          1862:        return false_rtx;
        !          1863:       else if (left == true_rtx)
        !          1864:        return right;
        !          1865:       else if (right == true_rtx)
        !          1866:        return left;
        !          1867: 
        !          1868:       /* See if all or all but one of the insn's alternatives are specified
        !          1869:         in this tree.  Optimize if so.  */
        !          1870: 
        !          1871:       else if (insn_code >= 0
        !          1872:               && (GET_CODE (left) == AND
        !          1873:                   || (GET_CODE (left) == NOT
        !          1874:                       && GET_CODE (XEXP (left, 0)) == EQ_ATTR
        !          1875:                       && XSTR (XEXP (left, 0), 0) == alternative_name)
        !          1876:                   || GET_CODE (right) == AND
        !          1877:                   || (GET_CODE (right) == NOT
        !          1878:                       && GET_CODE (XEXP (right, 0)) == EQ_ATTR
        !          1879:                       && XSTR (XEXP (right, 0), 0) == alternative_name)))
        !          1880:        {
        !          1881:          i = compute_alternative_mask (exp, AND);
        !          1882:          if (i & ~insn_alternatives[insn_code])
        !          1883:            fatal ("Illegal alternative specified for pattern number %d",
        !          1884:                   insn_index);
        !          1885: 
        !          1886:          /* If all alternatives are excluded, this is false. */
        !          1887:          i ^= insn_alternatives[insn_code];
        !          1888:          if (i == 0)
        !          1889:            return false_rtx;
        !          1890:          else if ((i & (i - 1)) == 0 && insn_alternatives[insn_code] > 1)
        !          1891:            {
        !          1892:              /* If just one excluded, AND a comparison with that one to the
        !          1893:                 front of the tree.  The others will be eliminated by
        !          1894:                 optimization.  We do not want to do this if the insn has one
        !          1895:                 alternative and we have tested none of them!  */
        !          1896:              left = make_alternative_compare (i);
        !          1897:              right = simplify_and_tree (exp, &left, insn_code, insn_index);
        !          1898:              newexp = rtx_alloc (AND);
        !          1899:              XEXP (newexp, 0) = left;
        !          1900:              XEXP (newexp, 1) = right;
        !          1901: 
        !          1902:              return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
        !          1903:            }
        !          1904:        }
        !          1905: 
        !          1906:       if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
        !          1907:        {
        !          1908:          newexp = rtx_alloc (AND);
        !          1909:          XEXP (newexp, 0) = left;
        !          1910:          XEXP (newexp, 1) = right;
        !          1911:          return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
        !          1912:        }
        !          1913:       break;
        !          1914: 
        !          1915:     case IOR:
        !          1916:       left = SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index);
        !          1917:       right = SIMPLIFY_TEST_EXP (XEXP (exp, 1), insn_code, insn_index);
        !          1918: 
        !          1919:       right = simplify_or_tree (right, &left, insn_code, insn_index);
        !          1920:       if (left == XEXP (exp, 0) && right == XEXP (exp, 1))
        !          1921:        left = simplify_or_tree (left, &right, insn_code, insn_index);
        !          1922: 
        !          1923:       if (right == true_rtx || left == true_rtx)
        !          1924:        return true_rtx;
        !          1925:       else if (left == false_rtx)
        !          1926:        return right;
        !          1927:       else if (right == false_rtx)
        !          1928:        return left;
        !          1929: 
        !          1930:       /* Test for simple cases where the distributive law is useful.  I.e.,
        !          1931:            convert (ior (and (x) (y))
        !          1932:                         (and (x) (z)))
        !          1933:            to      (and (x)
        !          1934:                         (ior (y) (z)))
        !          1935:        */
        !          1936: 
        !          1937:       else if (GET_CODE (left) == AND && GET_CODE (right) == AND
        !          1938:          && rtx_equal_p (XEXP (left, 0), XEXP (right, 0)))
        !          1939:        {
        !          1940:          newexp = rtx_alloc (IOR);
        !          1941:          XEXP (newexp, 0) = XEXP (left, 1);
        !          1942:          XEXP (newexp, 1) = XEXP (right, 1);
        !          1943: 
        !          1944:          left = XEXP (left, 0);
        !          1945:          right = newexp;
        !          1946:          newexp = rtx_alloc (AND);
        !          1947:          XEXP (newexp, 0) = left;
        !          1948:          XEXP (newexp, 1) = right;
        !          1949:          return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
        !          1950:        }
        !          1951: 
        !          1952:       /* See if all or all but one of the insn's alternatives are specified
        !          1953:         in this tree.  Optimize if so.  */
        !          1954: 
        !          1955:       else if (insn_code >= 0
        !          1956:          && (GET_CODE (left) == IOR
        !          1957:              || (GET_CODE (left) == EQ_ATTR
        !          1958:                  && XSTR (left, 0) == alternative_name)
        !          1959:              || GET_CODE (right) == IOR
        !          1960:              || (GET_CODE (right) == EQ_ATTR
        !          1961:                  && XSTR (right, 0) == alternative_name)))
        !          1962:        {
        !          1963:          i = compute_alternative_mask (exp, IOR);
        !          1964:          if (i & ~insn_alternatives[insn_code])
        !          1965:            fatal ("Illegal alternative specified for pattern number %d",
        !          1966:                   insn_index);
        !          1967: 
        !          1968:          /* If all alternatives are included, this is true. */
        !          1969:          i ^= insn_alternatives[insn_code];
        !          1970:          if (i == 0)
        !          1971:            return true_rtx;
        !          1972:          else if ((i & (i - 1)) == 0 && insn_alternatives[insn_code] > 1)
        !          1973:            {
        !          1974:              /* If just one excluded, IOR a comparison with that one to the
        !          1975:                 front of the tree.  The others will be eliminated by
        !          1976:                 optimization.  We do not want to do this if the insn has one
        !          1977:                 alternative and we have tested none of them!  */
        !          1978:              left = make_alternative_compare (i);
        !          1979:              right = simplify_and_tree (exp, &left, insn_code, insn_index);
        !          1980:              newexp = rtx_alloc (IOR);
        !          1981:              XEXP (newexp, 0) = rtx_alloc (NOT);
        !          1982:              XEXP (XEXP (newexp, 0), 0) = left;
        !          1983:              XEXP (newexp, 1) = right;
        !          1984: 
        !          1985:              return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
        !          1986:            }
        !          1987:        }
        !          1988: 
        !          1989:       if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
        !          1990:        {
        !          1991:          newexp = rtx_alloc (IOR);
        !          1992:          XEXP (newexp, 0) = left;
        !          1993:          XEXP (newexp, 1) = right;
        !          1994:          return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
        !          1995:        }
        !          1996:       break;
        !          1997: 
        !          1998:     case NOT:
        !          1999:       left = SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index);
        !          2000:       if (GET_CODE (left) == NOT)
        !          2001:        return XEXP (left, 0);
        !          2002: 
        !          2003:       if (left == false_rtx)
        !          2004:        return true_rtx;
        !          2005:       else if (left == true_rtx)
        !          2006:        return false_rtx;
        !          2007: 
        !          2008:       /* Try to apply De`Morgan's laws.  */
        !          2009:       else if (GET_CODE (left) == IOR)
        !          2010:        {
        !          2011:          newexp = rtx_alloc (AND);
        !          2012:          XEXP (newexp, 0) = rtx_alloc (NOT);
        !          2013:          XEXP (XEXP (newexp, 0), 0) = XEXP (left, 0);
        !          2014:          XEXP (newexp, 1) = rtx_alloc (NOT);
        !          2015:          XEXP (XEXP (newexp, 1), 0) = XEXP (left, 1);
        !          2016: 
        !          2017:          newexp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
        !          2018:        }
        !          2019:       else if (GET_CODE (left) == AND)
        !          2020:        {
        !          2021:          newexp = rtx_alloc (IOR);
        !          2022:          XEXP (newexp, 0) = rtx_alloc (NOT);
        !          2023:          XEXP (XEXP (newexp, 0), 0) = XEXP (left, 0);
        !          2024:          XEXP (newexp, 1) = rtx_alloc (NOT);
        !          2025:          XEXP (XEXP (newexp, 1), 0) = XEXP (left, 1);
        !          2026: 
        !          2027:          newexp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
        !          2028:        }
        !          2029:       else if (left != XEXP (exp, 0))
        !          2030:        {
        !          2031:          newexp = rtx_alloc (NOT);
        !          2032:          XEXP (newexp, 0) = left;
        !          2033:        }
        !          2034:       break;
        !          2035: 
        !          2036:     case EQ_ATTR:
        !          2037:       /* Look at the value for this insn code in the specified attribute.
        !          2038:         We normally can replace this comparison with the condition that
        !          2039:         would give this insn the values being tested for.   */
        !          2040:       if (XSTR (exp, 0) != alternative_name
        !          2041:          && (attr = find_attr (XSTR (exp, 0), 0)) != NULL)
        !          2042:        for (av = attr->first_value; av; av = av->next)
        !          2043:          for (ie = av->first_insn; ie; ie = ie->next)
        !          2044:            if (ie->insn_code == insn_code)
        !          2045:              return evaluate_eq_attr (exp, av->value, insn_code, insn_index);
        !          2046:     }
        !          2047: 
        !          2048:   /* We have already simplified this expression.  Simplifying it again
        !          2049:      won't buy anything unless we weren't given a valid insn code
        !          2050:      to process (i.e., we are canonicalizing something.).  */
        !          2051:   if (insn_code != -2)
        !          2052:     RTX_UNCHANGING_P (newexp) = 1;
        !          2053: 
        !          2054:   return newexp;
        !          2055: }
        !          2056: 
        !          2057: /* Optimize the attribute lists by seeing if we can determine conditional
        !          2058:    values from the known values of other attributes.  This will save subroutine
        !          2059:    calls during the compilation.  */
        !          2060: 
        !          2061: static void
        !          2062: optimize_attrs ()
        !          2063: {
        !          2064:   struct attr_desc *attr;
        !          2065:   struct attr_value *av;
        !          2066:   struct insn_ent *ie, *nextie;
        !          2067:   rtx newexp;
        !          2068:   int something_changed = 1;
        !          2069: 
        !          2070:   /* Loop until nothing changes for one iteration.  */
        !          2071:   while (something_changed)
        !          2072:     {
        !          2073:       something_changed = 0;
        !          2074:       for (attr = attrs; attr; attr = attr->next)
        !          2075:        for (av = attr->first_value; av; av = av->next)
        !          2076:            for (ie = av->first_insn; ie; ie = nextie)
        !          2077:              {
        !          2078:                nextie = ie->next;
        !          2079:                if (GET_CODE (av->value) != COND)
        !          2080:                  continue;
        !          2081: 
        !          2082:                newexp = simplify_cond (av->value, ie->insn_code,
        !          2083:                                        ie->insn_index);
        !          2084:                if (newexp != av->value)
        !          2085:                  {
        !          2086:                    remove_insn_ent (av, ie);
        !          2087:                    insert_insn_ent (get_attr_value (newexp, attr,
        !          2088:                                                     ie->insn_code), ie);
        !          2089:                    something_changed = 1;
        !          2090:                  }
        !          2091:              }
        !          2092:     }
        !          2093: }
        !          2094: 
        !          2095: /* Create table entries for DEFINE_ATTR.  */
        !          2096: 
        !          2097: static void
        !          2098: gen_attr (exp)
        !          2099:      rtx exp;
        !          2100: {
        !          2101:   struct attr_desc *attr;
        !          2102:   struct attr_value *av;
        !          2103:   char *name_ptr;
        !          2104:   char *p;
        !          2105: 
        !          2106:   /* Make a new attribute structure.  Check for duplicate by looking at
        !          2107:      attr->default_val, since it is initialized by this routine.  */
        !          2108:   attr = find_attr (XSTR (exp, 0), 1);
        !          2109:   if (attr->default_val)
        !          2110:     fatal ("Duplicate definition for `%s' attribute", attr->name);
        !          2111: 
        !          2112:   if (*XSTR (exp, 1) == '\0')
        !          2113:       attr->is_numeric = 1;
        !          2114:   else
        !          2115:     {
        !          2116:       name_ptr = XSTR (exp, 1);
        !          2117:       while ((p = next_comma_elt (&name_ptr)) != NULL)
        !          2118:        {
        !          2119:          av = (struct attr_value *) xmalloc (sizeof (struct attr_value));
        !          2120:          av->value = rtx_alloc (CONST_STRING);
        !          2121:          XSTR (av->value, 0) = p;
        !          2122:          av->next = attr->first_value;
        !          2123:          attr->first_value = av;
        !          2124:          av->first_insn = NULL;
        !          2125:          av->num_insns = 0;
        !          2126:          av->has_asm_insn = 0;
        !          2127:        }
        !          2128:     }
        !          2129: 
        !          2130:   if (! strcmp (attr->name, "length") && ! attr->is_numeric)
        !          2131:     fatal ("`length' attribute must take numeric values");
        !          2132: 
        !          2133:   /* Set up the default value. */
        !          2134:   check_attr_value (XEXP (exp, 2), attr);
        !          2135:   attr->default_val = get_attr_value (XEXP (exp, 2), attr, -2);
        !          2136: }
        !          2137: 
        !          2138: /* Given a pattern for DEFINE_PEEPHOLE or DEFINE_INSN, return the number of
        !          2139:    alternatives in the constraints.  Assume all MATCH_OPERANDs have the same
        !          2140:    number of alternatives as this should be checked elsewhere.  */
        !          2141: 
        !          2142: static int
        !          2143: count_alternatives (exp)
        !          2144:      rtx exp;
        !          2145: {
        !          2146:   int i, j, n;
        !          2147:   char *fmt;
        !          2148:   
        !          2149:   if (GET_CODE (exp) == MATCH_OPERAND)
        !          2150:     return n_comma_elts (XSTR (exp, 2));
        !          2151: 
        !          2152:   for (i = 0, fmt = GET_RTX_FORMAT (GET_CODE (exp));
        !          2153:        i < GET_RTX_LENGTH (GET_CODE (exp)); i++)
        !          2154:     switch (*fmt++)
        !          2155:       {
        !          2156:       case 'e':
        !          2157:       case 'u':
        !          2158:        n = count_alternatives (XEXP (exp, i));
        !          2159:        if (n)
        !          2160:          return n;
        !          2161:        break;
        !          2162: 
        !          2163:       case 'E':
        !          2164:       case 'V':
        !          2165:        if (XVEC (exp, i) != NULL)
        !          2166:          for (j = 0; j < XVECLEN (exp, i); j++)
        !          2167:            {
        !          2168:              n = count_alternatives (XVECEXP (exp, i, j));
        !          2169:              if (n)
        !          2170:                return n;
        !          2171:            }
        !          2172:       }
        !          2173: 
        !          2174:   return 0;
        !          2175: }
        !          2176: 
        !          2177: /* Returns non-zero if the given expression contains an EQ_ATTR with the
        !          2178:    `alternative' attribute.  */
        !          2179: 
        !          2180: static int
        !          2181: compares_alternatives_p (exp)
        !          2182:      rtx exp;
        !          2183: {
        !          2184:   int i, j;
        !          2185:   char *fmt;
        !          2186: 
        !          2187:   if (GET_CODE (exp) == EQ_ATTR && XSTR (exp, 0) == alternative_name)
        !          2188:     return 1;
        !          2189: 
        !          2190:   for (i = 0, fmt = GET_RTX_FORMAT (GET_CODE (exp));
        !          2191:        i < GET_RTX_LENGTH (GET_CODE (exp)); i++)
        !          2192:     switch (*fmt++)
        !          2193:       {
        !          2194:       case 'e':
        !          2195:       case 'u':
        !          2196:        if (compares_alternatives_p (XEXP (exp, i)))
        !          2197:          return 1;
        !          2198:        break;
        !          2199: 
        !          2200:       case 'E':
        !          2201:        for (j = 0; j < XVECLEN (exp, i); j++)
        !          2202:          if (compares_alternatives_p (XVECEXP (exp, i, j)))
        !          2203:            return 1;
        !          2204:        break;
        !          2205:       }
        !          2206: 
        !          2207:   return 0;
        !          2208: }
        !          2209: 
        !          2210: /* Returns non-zero is INNER is contained in EXP.  */
        !          2211: 
        !          2212: static int
        !          2213: contained_in_p (inner, exp)
        !          2214:      rtx inner;
        !          2215:      rtx exp;
        !          2216: {
        !          2217:   int i, j;
        !          2218:   char *fmt;
        !          2219: 
        !          2220:   if (rtx_equal_p (inner, exp))
        !          2221:     return 1;
        !          2222: 
        !          2223:   for (i = 0, fmt = GET_RTX_FORMAT (GET_CODE (exp));
        !          2224:        i < GET_RTX_LENGTH (GET_CODE (exp)); i++)
        !          2225:     switch (*fmt++)
        !          2226:       {
        !          2227:       case 'e':
        !          2228:       case 'u':
        !          2229:        if (contained_in_p (inner, XEXP (exp, i)))
        !          2230:          return 1;
        !          2231:        break;
        !          2232: 
        !          2233:       case 'E':
        !          2234:        for (j = 0; j < XVECLEN (exp, i); j++)
        !          2235:          if (contained_in_p (inner, XVECEXP (exp, i, j)))
        !          2236:            return 1;
        !          2237:        break;
        !          2238:       }
        !          2239: 
        !          2240:   return 0;
        !          2241: }
        !          2242:       
        !          2243: /* Process DEFINE_PEEPHOLE, DEFINE_INSN, and DEFINE_ASM_ATTRIBUTES.  */
        !          2244: 
        !          2245: static void
        !          2246: gen_insn (exp)
        !          2247:      rtx exp;
        !          2248: {
        !          2249:   struct insn_def *id;
        !          2250: 
        !          2251:   id = (struct insn_def *) xmalloc (sizeof (struct insn_def));
        !          2252:   id->next = defs;
        !          2253:   defs = id;
        !          2254:   id->def = exp;
        !          2255: 
        !          2256:   switch (GET_CODE (exp))
        !          2257:     {
        !          2258:     case DEFINE_INSN:
        !          2259:       id->insn_code = insn_code_number++;
        !          2260:       id->insn_index = insn_index_number++;
        !          2261:       id->num_alternatives = count_alternatives (exp);
        !          2262:       if (id->num_alternatives == 0)
        !          2263:        id->num_alternatives = 1;
        !          2264:       id->vec_idx = 4;
        !          2265:       break;
        !          2266: 
        !          2267:     case DEFINE_PEEPHOLE:
        !          2268:       id->insn_code = insn_code_number++;
        !          2269:       id->insn_index = insn_index_number++;
        !          2270:       id->num_alternatives = count_alternatives (exp);
        !          2271:       if (id->num_alternatives == 0)
        !          2272:        id->num_alternatives = 1;
        !          2273:       id->vec_idx = 3;
        !          2274:       break;
        !          2275: 
        !          2276:     case DEFINE_ASM_ATTRIBUTES:
        !          2277:       id->insn_code = -1;
        !          2278:       id->insn_index = -1;
        !          2279:       id->num_alternatives = 1;
        !          2280:       id->vec_idx = 0;
        !          2281:       got_define_asm_attributes = 1;
        !          2282:       break;
        !          2283:     }
        !          2284: }
        !          2285: 
        !          2286: /* Process a DEFINE_DELAY.  Validate the vector length, check if annul
        !          2287:    true or annul false is specified, and make a `struct delay_desc'.  */
        !          2288: 
        !          2289: static void
        !          2290: gen_delay (def)
        !          2291:      rtx def;
        !          2292: {
        !          2293:   struct delay_desc *delay;
        !          2294:   int i;
        !          2295: 
        !          2296:   if (XVECLEN (def, 1) % 3 != 0)
        !          2297:     fatal ("Number of elements in DEFINE_DELAY must be multiple of three.");
        !          2298: 
        !          2299:   for (i = 0; i < XVECLEN (def, 1); i += 3)
        !          2300:     {
        !          2301:       if (XVECEXP (def, 1, i + 1))
        !          2302:        have_annul_true = 1;
        !          2303:       if (XVECEXP (def, 1, i + 2))
        !          2304:        have_annul_false = 1;
        !          2305:     }
        !          2306:   
        !          2307:   delay = (struct delay_desc *) xmalloc (sizeof (struct delay_desc));
        !          2308:   delay->def = def;
        !          2309:   delay->num = ++num_delays;
        !          2310:   delay->next = delays;
        !          2311:   delays = delay;
        !          2312: }
        !          2313: 
        !          2314: /* Process a DEFINE_FUNCTION_UNIT.  
        !          2315: 
        !          2316:    This gives information about a function unit contained in the CPU.
        !          2317:    We fill in a `struct function_unit_op' and a `struct function_unit'
        !          2318:    with information used later by `expand_unit'.  */
        !          2319: 
        !          2320: static void
        !          2321: gen_unit (def)
        !          2322:      rtx def;
        !          2323: {
        !          2324:   struct function_unit *unit;
        !          2325:   struct function_unit_op *op;
        !          2326: 
        !          2327:   /* See if we have already seen this function unit.  If so, check that
        !          2328:      the multipicity and simultaneity values are the same.  If not, make
        !          2329:      a structure for this function unit.  */
        !          2330:   for (unit = units; unit; unit = unit->next)
        !          2331:     if (! strcmp (unit->name, XSTR (def, 0)))
        !          2332:       {
        !          2333:        if (unit->multiplicity != XINT (def, 1)
        !          2334:            || unit->simultaneity != XINT (def, 2))
        !          2335:          fatal ("Differing specifications given for `%s' function unit.",
        !          2336:                 unit->name);
        !          2337:        break;
        !          2338:       }
        !          2339: 
        !          2340:   if (unit == 0)
        !          2341:     {
        !          2342:       unit = (struct function_unit *) xmalloc (sizeof (struct function_unit));
        !          2343:       unit->name = XSTR (def, 0);
        !          2344:       unit->multiplicity = XINT (def, 1);
        !          2345:       unit->simultaneity = XINT (def, 2);
        !          2346:       unit->num = num_units++;
        !          2347:       unit->num_opclasses = 0;
        !          2348:       unit->condexp = false_rtx;
        !          2349:       unit->ops = 0;
        !          2350:       unit->next = units;
        !          2351:       units = unit;
        !          2352:     }
        !          2353: 
        !          2354:   /* Make a new operation class structure entry and initialize it.  */
        !          2355:   op = (struct function_unit_op *) xmalloc (sizeof (struct function_unit_op));
        !          2356:   op->condexp = XEXP (def, 3);
        !          2357:   op->num = unit->num_opclasses++;
        !          2358:   op->ready = XINT (def, 4);
        !          2359:   op->next = unit->ops;
        !          2360:   unit->ops = op;
        !          2361: 
        !          2362:   /* Set our busy expression based on whether or not an optional conflict
        !          2363:      vector was specified.  */
        !          2364:   if (XVEC (def, 6))
        !          2365:     {
        !          2366:       /* Compute the IOR of all the specified expressions.  */
        !          2367:       rtx orexp = false_rtx;
        !          2368:       int i;
        !          2369: 
        !          2370:       for (i = 0; i < XVECLEN (def, 6); i++)
        !          2371:        orexp = insert_right_side (IOR, orexp, XVECEXP (def, 6, i), -2);
        !          2372: 
        !          2373:       op->busyexp = rtx_alloc (IF_THEN_ELSE);
        !          2374:       XEXP (op->busyexp, 0) = orexp;
        !          2375:       XEXP (op->busyexp, 1) = make_numeric_value (XINT (def, 5));
        !          2376:       XEXP (op->busyexp, 2) = make_numeric_value (0);
        !          2377:     }
        !          2378:   else
        !          2379:     op->busyexp = make_numeric_value (XINT (def, 5));
        !          2380: 
        !          2381:   /* Merge our conditional into that of the function unit so we can determine
        !          2382:      which insns are used by the function unit.  */
        !          2383:   unit->condexp = insert_right_side (IOR, unit->condexp, op->condexp, -2);
        !          2384: }
        !          2385: 
        !          2386: /* Given a piece of RTX, print a C expression to test it's truth value.
        !          2387:    We use AND and IOR both for logical and bit-wise operations, so 
        !          2388:    interpret them as logical unless they are inside a comparison expression.
        !          2389:    The second operand of this function will be non-zero in that case.  */
        !          2390: 
        !          2391: static void
        !          2392: write_test_expr (exp, in_comparison)
        !          2393:      rtx exp;
        !          2394:      int in_comparison;
        !          2395: {
        !          2396:   int comparison_operator = 0;
        !          2397:   RTX_CODE code;
        !          2398:   struct attr_desc *attr;
        !          2399: 
        !          2400:   /* In order not to worry about operator precedence, surround our part of
        !          2401:      the expression with parentheses.  */
        !          2402: 
        !          2403:   printf ("(");
        !          2404:   code = GET_CODE (exp);
        !          2405:   switch (code)
        !          2406:     {
        !          2407:     /* Binary operators.  */
        !          2408:     case EQ: case NE:
        !          2409:     case GE: case GT: case GEU: case GTU:
        !          2410:     case LE: case LT: case LEU: case LTU:
        !          2411:       comparison_operator = 1;
        !          2412: 
        !          2413:     case PLUS:   case MINUS:  case MULT:     case DIV:      case MOD:
        !          2414:     case AND:    case IOR:    case XOR:
        !          2415:     case LSHIFT: case ASHIFT: case LSHIFTRT: case ASHIFTRT:
        !          2416:       write_test_expr (XEXP (exp, 0), in_comparison || comparison_operator);
        !          2417:       switch (code)
        !          2418:         {
        !          2419:        case EQ:
        !          2420:          printf (" == ");
        !          2421:          break;
        !          2422:        case NE:
        !          2423:          printf (" != ");
        !          2424:          break;
        !          2425:        case GE:
        !          2426:          printf (" >= ");
        !          2427:          break;
        !          2428:        case GT:
        !          2429:          printf (" > ");
        !          2430:          break;
        !          2431:        case GEU:
        !          2432:          printf (" >= (unsigned) ");
        !          2433:          break;
        !          2434:        case GTU:
        !          2435:          printf (" > (unsigned) ");
        !          2436:          break;
        !          2437:        case LE:
        !          2438:          printf (" <= ");
        !          2439:          break;
        !          2440:        case LT:
        !          2441:          printf (" < ");
        !          2442:          break;
        !          2443:        case LEU:
        !          2444:          printf (" <= (unsigned) ");
        !          2445:          break;
        !          2446:        case LTU:
        !          2447:          printf (" < (unsigned) ");
        !          2448:          break;
        !          2449:        case PLUS:
        !          2450:          printf (" + ");
        !          2451:          break;
        !          2452:        case MINUS:
        !          2453:          printf (" - ");
        !          2454:          break;
        !          2455:        case MULT:
        !          2456:          printf (" * ");
        !          2457:          break;
        !          2458:        case DIV:
        !          2459:          printf (" / ");
        !          2460:          break;
        !          2461:        case MOD:
        !          2462:          printf (" % ");
        !          2463:          break;
        !          2464:        case AND:
        !          2465:          if (in_comparison)
        !          2466:            printf (" & ");
        !          2467:          else
        !          2468:            printf (" && ");
        !          2469:          break;
        !          2470:        case IOR:
        !          2471:          if (in_comparison)
        !          2472:            printf (" | ");
        !          2473:          else
        !          2474:            printf (" || ");
        !          2475:          break;
        !          2476:        case XOR:
        !          2477:          printf (" ^ ");
        !          2478:          break;
        !          2479:        case LSHIFT:
        !          2480:        case ASHIFT:
        !          2481:          printf (" << ");
        !          2482:          break;
        !          2483:        case LSHIFTRT:
        !          2484:        case ASHIFTRT:
        !          2485:          printf (" >> ");
        !          2486:          break;
        !          2487:         }
        !          2488: 
        !          2489:       write_test_expr (XEXP (exp, 1), in_comparison || comparison_operator);
        !          2490:       break;
        !          2491: 
        !          2492:     case NOT:
        !          2493:       /* Special-case (not (eq_attrq "alternative" "x")) */
        !          2494:       if (! in_comparison && GET_CODE (XEXP (exp, 0)) == EQ_ATTR
        !          2495:          && XSTR (XEXP (exp, 0), 0) == alternative_name)
        !          2496:        {
        !          2497:          printf ("which_alternative != %s", XSTR (XEXP (exp, 0), 1));
        !          2498:          break;
        !          2499:        }
        !          2500: 
        !          2501:       /* Otherwise, fall through to normal unary operator.  */
        !          2502: 
        !          2503:     /* Unary operators.  */   
        !          2504:     case ABS:  case NEG:
        !          2505:       switch (code)
        !          2506:        {
        !          2507:        case NOT:
        !          2508:          if (in_comparison)
        !          2509:            printf ("~ ");
        !          2510:          else
        !          2511:            printf ("! ");
        !          2512:          break;
        !          2513:        case ABS:
        !          2514:          printf ("abs ");
        !          2515:          break;
        !          2516:        case NEG:
        !          2517:          printf ("-");
        !          2518:          break;
        !          2519:        }
        !          2520: 
        !          2521:       write_test_expr (XEXP (exp, 0), in_comparison);
        !          2522:       break;
        !          2523: 
        !          2524:     /* Comparison test of an attribute with a value.  Most of these will
        !          2525:        have been removed by optimization.   Handle "alternative"
        !          2526:        specially and give error if EQ_ATTR present inside a comparison.  */
        !          2527:     case EQ_ATTR:
        !          2528:       if (in_comparison)
        !          2529:        fatal ("EQ_ATTR not valid inside comparison");
        !          2530: 
        !          2531:       if (XSTR (exp, 0) == alternative_name)
        !          2532:        {
        !          2533:          printf ("which_alternative == %s", XSTR (exp, 1));
        !          2534:          break;
        !          2535:        }
        !          2536: 
        !          2537:       attr = find_attr (XSTR (exp, 0), 0);
        !          2538:       if (! attr) abort ();
        !          2539:       printf ("get_attr_%s (insn) == ", attr->name);
        !          2540:       write_attr_valueq (attr, XSTR (exp, 1)); 
        !          2541:       break;
        !          2542: 
        !          2543:     /* See if an operand matches a predicate.  */
        !          2544:     case MATCH_OPERAND:
        !          2545:       /* If only a mode is given, just ensure the mode matches the operand.
        !          2546:         If neither a mode nor predicate is given, error.  */
        !          2547:      if (XSTR (exp, 1) == NULL || *XSTR (exp, 1) == '\0')
        !          2548:        {
        !          2549:          if (GET_MODE (exp) == VOIDmode)
        !          2550:            fatal ("Null MATCH_OPERAND specified as test");
        !          2551:          else
        !          2552:            printf ("GET_MODE (operands[%d]) == %smode",
        !          2553:                    XINT (exp, 0), GET_MODE_NAME (GET_MODE (exp)));
        !          2554:        }
        !          2555:       else
        !          2556:        printf ("%s (operands[%d], %smode)",
        !          2557:                XSTR (exp, 1), XINT (exp, 0), GET_MODE_NAME (GET_MODE (exp)));
        !          2558:       break;
        !          2559: 
        !          2560:     /* Constant integer. */
        !          2561:     case CONST_INT:
        !          2562:       printf ("%d", XINT (exp, 0));
        !          2563:       break;
        !          2564: 
        !          2565:     /* A random C expression. */
        !          2566:     case SYMBOL_REF:
        !          2567:       printf ("%s", XSTR (exp, 0));
        !          2568:       break;
        !          2569: 
        !          2570:     /* The address of the branch target.  */
        !          2571:     case MATCH_DUP:
        !          2572:       printf ("insn_addresses[INSN_UID (JUMP_LABEL (insn))]");
        !          2573:       break;
        !          2574: 
        !          2575:     /* The address of the current insn.  It would be more consistent with
        !          2576:        other usage to make this the address of the NEXT insn, but this gets
        !          2577:        too confusing because of the ambiguity regarding the length of the
        !          2578:        current insn.  */
        !          2579:     case PC:
        !          2580:       printf ("insn_current_address");
        !          2581:       break;
        !          2582: 
        !          2583:     default:
        !          2584:       fatal ("bad RTX code `%s' in attribute calculation\n",
        !          2585:             GET_RTX_NAME (code));
        !          2586:     }
        !          2587: 
        !          2588:   printf (")");
        !          2589: }
        !          2590: 
        !          2591: /* Given an attribute value, return the maximum CONST_STRING argument
        !          2592:    encountered.  It is assumed that they are all numeric.  */
        !          2593: 
        !          2594: static int
        !          2595: max_attr_value (exp)
        !          2596:      rtx exp;
        !          2597: {
        !          2598:   int current_max = 0;
        !          2599:   int n;
        !          2600:   int i;
        !          2601: 
        !          2602:   if (GET_CODE (exp) == CONST_STRING)
        !          2603:     return atoi (XSTR (exp, 0));
        !          2604: 
        !          2605:   else if (GET_CODE (exp) == COND)
        !          2606:     {
        !          2607:       for (i = 0; i < XVECLEN (exp, 0); i += 2)
        !          2608:        {
        !          2609:          n = max_attr_value (XVECEXP (exp, 0, i + 1));
        !          2610:          if (n > current_max)
        !          2611:            current_max = n;
        !          2612:        }
        !          2613: 
        !          2614:       n = max_attr_value (XEXP (exp, 1));
        !          2615:       if (n > current_max)
        !          2616:        current_max = n;
        !          2617:     }
        !          2618: 
        !          2619:   else
        !          2620:     abort ();
        !          2621: 
        !          2622:   return current_max;
        !          2623: }
        !          2624: 
        !          2625: /* Scan an attribute value, possibly a conditional, and record what actions
        !          2626:    will be required to do any conditional tests in it.
        !          2627: 
        !          2628:    Specifically, set
        !          2629:        `must_extract'    if we need to extract the insn operands
        !          2630:        `must_constrain'  if we must compute `which_alternative'
        !          2631:        `address_used'    if an address expression was used
        !          2632:  */
        !          2633: 
        !          2634: static void
        !          2635: walk_attr_value (exp)
        !          2636:      rtx exp;
        !          2637: {
        !          2638:   register int i, j;
        !          2639:   register char *fmt;
        !          2640:   RTX_CODE code;
        !          2641: 
        !          2642:   if (exp == NULL)
        !          2643:     return;
        !          2644: 
        !          2645:   code = GET_CODE (exp);
        !          2646:   switch (code)
        !          2647:     {
        !          2648:     case SYMBOL_REF:
        !          2649:       /* Since this is an arbitrary expression, it can look at anything. */
        !          2650:       must_extract = must_constrain = 1;
        !          2651:       return;
        !          2652: 
        !          2653:     case MATCH_OPERAND:
        !          2654:       must_extract = 1;
        !          2655:       return;
        !          2656: 
        !          2657:     case EQ_ATTR:
        !          2658:       if (XSTR (exp, 0) == alternative_name)
        !          2659:        must_extract = must_constrain = 1;
        !          2660:       return;
        !          2661: 
        !          2662:     case MATCH_DUP:
        !          2663:     case PC:
        !          2664:       address_used = 1;
        !          2665:       return;
        !          2666:     }
        !          2667: 
        !          2668:   for (i = 0, fmt = GET_RTX_FORMAT (code); i < GET_RTX_LENGTH (code); i++)
        !          2669:     switch (*fmt++)
        !          2670:       {
        !          2671:       case 'e':
        !          2672:       case 'u':
        !          2673:        walk_attr_value (XEXP (exp, i));
        !          2674:        break;
        !          2675: 
        !          2676:       case 'E':
        !          2677:        if (XVEC (exp, i) != NULL)
        !          2678:          for (j = 0; j < XVECLEN (exp, i); j++)
        !          2679:            walk_attr_value (XVECEXP (exp, i, j));
        !          2680:        break;
        !          2681:       }
        !          2682: }
        !          2683: 
        !          2684: /* Write out a function to obtain the attribute for a given INSN.  */
        !          2685: 
        !          2686: static void
        !          2687: write_attr_get (attr)
        !          2688:      struct attr_desc *attr;
        !          2689: {
        !          2690:   struct attr_value *av, *common_av;
        !          2691: 
        !          2692:   /* Find the most used attribute value.  Handle that as the `default' of the
        !          2693:      switch we will generate. */
        !          2694:   common_av = find_most_used (attr);
        !          2695: 
        !          2696:   /* Write out start of function, then all values with explicit `case' lines,
        !          2697:      then a `default', then the value with the most uses.  */
        !          2698:   if (attr->is_numeric)
        !          2699:     printf ("int\n");
        !          2700:   else
        !          2701:     printf ("enum attr_%s\n", attr->name);
        !          2702: 
        !          2703:   /* If the attribute name starts with a star, the remainder is the name of
        !          2704:      the subroutine to use, instead of `get_attr_...'.  */
        !          2705:   if (attr->name[0] == '*')
        !          2706:     printf ("%s (insn)\n", &attr->name[1]);
        !          2707:   else
        !          2708:     printf ("get_attr_%s (insn)\n", attr->name);
        !          2709:   printf ("     rtx insn;\n");
        !          2710:   printf ("{\n");
        !          2711:   printf ("  switch (recog_memoized (insn))\n");
        !          2712:   printf ("    {\n");
        !          2713: 
        !          2714:   for (av = attr->first_value; av; av = av->next)
        !          2715:     if (av != common_av)
        !          2716:       write_attr_case (attr, av, 1, "return", ";", 4, true_rtx);
        !          2717: 
        !          2718:   write_attr_case (attr, common_av, 0, "return", ";", 4, true_rtx);
        !          2719:   printf ("    }\n}\n\n");
        !          2720: }
        !          2721: 
        !          2722: /* Given an AND tree of known true terms (because we are inside an `if' with
        !          2723:    that as the condition or are in an `else' clause) and an expression,
        !          2724:    replace any known true terms with TRUE.  Use `simplify_and_tree' to do
        !          2725:    the bulk of the work.  */
        !          2726: 
        !          2727: static rtx
        !          2728: eliminate_known_true (known_true, exp, insn_code, insn_index)
        !          2729:      rtx known_true;
        !          2730:      rtx exp;
        !          2731:      int insn_code, insn_index;
        !          2732: {
        !          2733:   rtx term;
        !          2734: 
        !          2735:   known_true = SIMPLIFY_TEST_EXP (known_true, insn_code, insn_index);
        !          2736: 
        !          2737:   if (GET_CODE (known_true) == AND)
        !          2738:     {
        !          2739:       exp = eliminate_known_true (XEXP (known_true, 0), exp,
        !          2740:                                  insn_code, insn_index);
        !          2741:       exp = eliminate_known_true (XEXP (known_true, 1), exp,
        !          2742:                                  insn_code, insn_index);
        !          2743:     }
        !          2744:   else
        !          2745:     {
        !          2746:       term = known_true;
        !          2747:       exp = simplify_and_tree (exp, &term, insn_code, insn_index);
        !          2748:     }
        !          2749: 
        !          2750:   return exp;
        !          2751: }
        !          2752: 
        !          2753: /* Write out a series of tests and assignment statements to perform tests and
        !          2754:    sets of an attribute value.  We are passed an indentation amount and prefix
        !          2755:    and suffix strings to write around each attribute value (e.g., "return"
        !          2756:    and ";").  */
        !          2757: 
        !          2758: static void
        !          2759: write_attr_set (attr, indent, value, prefix, suffix, known_true,
        !          2760:                insn_code, insn_index)
        !          2761:      struct attr_desc *attr;
        !          2762:      int indent;
        !          2763:      rtx value;
        !          2764:      char *prefix;
        !          2765:      char *suffix;
        !          2766:      rtx known_true;
        !          2767:      int insn_code, insn_index;
        !          2768: {
        !          2769:   if (GET_CODE (value) == CONST_STRING)
        !          2770:     {
        !          2771:       write_indent (indent);
        !          2772:       printf ("%s ", prefix);
        !          2773:       write_attr_value (attr, value);
        !          2774:       printf ("%s\n", suffix);
        !          2775:     }
        !          2776:   else if (GET_CODE (value) == COND)
        !          2777:     {
        !          2778:       /* Assume the default value will be the default of the COND unless we
        !          2779:         find an always true expression.  */
        !          2780:       rtx default_val = XEXP (value, 1);
        !          2781:       rtx our_known_true = known_true;
        !          2782:       rtx newexp;
        !          2783:       int first_if = 1;
        !          2784:       int i;
        !          2785: 
        !          2786:       for (i = 0; i < XVECLEN (value, 0); i += 2)
        !          2787:        {
        !          2788:          rtx testexp;
        !          2789:          rtx inner_true;
        !          2790: 
        !          2791:          testexp = eliminate_known_true (our_known_true,
        !          2792:                                          XVECEXP (value, 0, i),
        !          2793:                                          insn_code, insn_index);
        !          2794:          newexp = rtx_alloc (NOT);
        !          2795:          XEXP (newexp, 0) = testexp;
        !          2796:          newexp  = insert_right_side (AND, our_known_true, newexp,
        !          2797:                                       insn_code, insn_index);
        !          2798: 
        !          2799:          /* If the test expression is always true or if the next `known_true'
        !          2800:             expression is always false, this is the last case, so break
        !          2801:             out and let this value be the `else' case.  */
        !          2802:          if (testexp == true_rtx || newexp == false_rtx)
        !          2803:            {
        !          2804:              default_val = XVECEXP (value, 0, i + 1);
        !          2805:              break;
        !          2806:            }
        !          2807: 
        !          2808:          /* Compute the expression to pass to our recursive call as being
        !          2809:             known true.  */
        !          2810:          inner_true = insert_right_side (AND, our_known_true,
        !          2811:                                          testexp, insn_code, insn_index);
        !          2812: 
        !          2813:          /* If this is always false, skip it.  */
        !          2814:          if (inner_true == false_rtx)
        !          2815:            continue;
        !          2816: 
        !          2817:          write_indent (indent);
        !          2818:          printf ("%sif ", first_if ? "" : "else ");
        !          2819:          first_if = 0;
        !          2820:          write_test_expr (testexp, 0);
        !          2821:          printf ("\n");
        !          2822:          write_indent (indent + 2);
        !          2823:          printf ("{\n");
        !          2824: 
        !          2825:          write_attr_set (attr, indent + 4,  
        !          2826:                          XVECEXP (value, 0, i + 1), prefix, suffix,
        !          2827:                          inner_true, insn_code, insn_index);
        !          2828:          write_indent (indent + 2);
        !          2829:          printf ("}\n");
        !          2830:          our_known_true = newexp;
        !          2831:        }
        !          2832: 
        !          2833:       if (! first_if)
        !          2834:        {
        !          2835:          write_indent (indent);
        !          2836:          printf ("else\n");
        !          2837:          write_indent (indent + 2);
        !          2838:          printf ("{\n");
        !          2839:        }
        !          2840: 
        !          2841:       write_attr_set (attr, first_if ? indent : indent + 4, default_val,
        !          2842:                      prefix, suffix, our_known_true, insn_code, insn_index);
        !          2843: 
        !          2844:       if (! first_if)
        !          2845:        {
        !          2846:          write_indent (indent + 2);
        !          2847:          printf ("}\n");
        !          2848:        }
        !          2849:     }
        !          2850:   else
        !          2851:     abort ();
        !          2852: }
        !          2853: 
        !          2854: /* Write out the computation for one attribute value.  */
        !          2855: 
        !          2856: static void
        !          2857: write_attr_case (attr, av, write_case_lines, prefix, suffix, indent, known_true)
        !          2858:      struct attr_desc *attr;
        !          2859:      struct attr_value *av;
        !          2860:      int write_case_lines;
        !          2861:      char *prefix, *suffix;
        !          2862:      int indent;
        !          2863:      rtx known_true;
        !          2864: {
        !          2865:   struct insn_ent *ie;
        !          2866: 
        !          2867:   if (av->num_insns == 0)
        !          2868:     return;
        !          2869: 
        !          2870:   if (av->has_asm_insn)
        !          2871:     {
        !          2872:       write_indent (indent);
        !          2873:       printf ("case -1:\n");
        !          2874:       write_indent (indent + 2);
        !          2875:       printf ("if (GET_CODE (PATTERN (insn)) != ASM_INPUT\n");
        !          2876:       write_indent (indent + 2);
        !          2877:       printf ("    && asm_noperands (PATTERN (insn)) < 0)\n");
        !          2878:       write_indent (indent + 2);
        !          2879:       printf ("  fatal_insn_not_found (insn);\n");
        !          2880:     }
        !          2881: 
        !          2882:   if (write_case_lines)
        !          2883:     {
        !          2884:       for (ie = av->first_insn; ie; ie = ie->next)
        !          2885:        if (ie->insn_code != -1)
        !          2886:          {
        !          2887:            write_indent (indent);
        !          2888:            printf ("case %d:\n", ie->insn_code);
        !          2889:          }
        !          2890:     }
        !          2891:   else
        !          2892:     {
        !          2893:       write_indent (indent);
        !          2894:       printf ("default:\n");
        !          2895:     }
        !          2896: 
        !          2897:   /* See what we have to do to handle output this value.  */
        !          2898:   must_extract = must_constrain = address_used = 0;
        !          2899:   walk_attr_value (av->value);
        !          2900: 
        !          2901:   if (must_extract)
        !          2902:     {
        !          2903:       write_indent (indent + 2);
        !          2904:       printf ("insn_extract (insn);\n");
        !          2905:     }
        !          2906: 
        !          2907:   if (must_constrain)
        !          2908:     {
        !          2909: #ifdef REGISTER_CONSTRAINTS
        !          2910:       write_indent (indent + 2);
        !          2911:       printf ("if (! constrain_operands (INSN_CODE (insn), reload_completed))\n");
        !          2912:       write_indent (indent + 2);
        !          2913:       printf ("  fatal_insn_not_found (insn);\n");
        !          2914: #endif
        !          2915:     }
        !          2916: 
        !          2917:   write_attr_set (attr, indent + 2, av->value, prefix, suffix,
        !          2918:                  known_true, av->first_insn->insn_code,
        !          2919:                  av->first_insn->insn_index);
        !          2920: 
        !          2921:   if (strncmp (prefix, "return", 6))
        !          2922:     {
        !          2923:       write_indent (indent + 2);
        !          2924:       printf ("break;\n");
        !          2925:     }
        !          2926:   printf ("\n");
        !          2927: }
        !          2928: 
        !          2929: /* Utilities to write names in various forms.  */
        !          2930: 
        !          2931: static void
        !          2932: write_attr_valueq (attr, s)
        !          2933:      struct attr_desc *attr;
        !          2934:      char *s;
        !          2935: {
        !          2936:   if (attr->is_numeric)
        !          2937:     printf ("%s", s);
        !          2938:   else
        !          2939:     {
        !          2940:       write_upcase (attr->name);
        !          2941:       printf ("_");
        !          2942:       write_upcase (s);
        !          2943:     }
        !          2944: }
        !          2945: 
        !          2946: static void
        !          2947: write_attr_value (attr, value)
        !          2948:      struct attr_desc *attr;
        !          2949:      rtx value;
        !          2950: {
        !          2951:   if (GET_CODE (value) != CONST_STRING)
        !          2952:     abort ();
        !          2953: 
        !          2954:   write_attr_valueq (attr, XSTR (value, 0));
        !          2955: }
        !          2956: 
        !          2957: static void
        !          2958: write_upcase (str)
        !          2959:      char *str;
        !          2960: {
        !          2961:   while (*str)
        !          2962:     if (*str < 'a' || *str > 'z')
        !          2963:       printf ("%c", *str++);
        !          2964:     else
        !          2965:       printf ("%c", *str++ - 'a' + 'A');
        !          2966: }
        !          2967: 
        !          2968: static void
        !          2969: write_indent (indent)
        !          2970:      int indent;
        !          2971: {
        !          2972:   for (; indent > 8; indent -= 8)
        !          2973:     printf ("\t");
        !          2974: 
        !          2975:   for (; indent; indent--)
        !          2976:     printf (" ");
        !          2977: }
        !          2978: 
        !          2979: /* Write a subroutine that is given an insn that requires a delay slot, a
        !          2980:    delay slot ordinal, and a candidate insn.  It returns non-zero if the
        !          2981:    candidate can be placed in the specified delay slot of the insn.
        !          2982: 
        !          2983:    We can write as many as three subroutines.  `eligible_for_delay'
        !          2984:    handles normal delay slots, `eligible_for_annul_true' indicates that
        !          2985:    the specified insn can be annulled if the branch is true, and likewise
        !          2986:    for `eligible_for_annul_false'.
        !          2987: 
        !          2988:    KIND is a string distingushing these three cases ("delay", "annul_true",
        !          2989:    or "annul_false").  */
        !          2990: 
        !          2991: static void
        !          2992: write_eligible_delay (kind)
        !          2993:      char *kind;
        !          2994: {
        !          2995:   struct delay_desc *delay;
        !          2996:   int max_slots;
        !          2997:   char str[50];
        !          2998:   struct attr_desc *attr;
        !          2999:   struct attr_value *av, *common_av;
        !          3000:   int i;
        !          3001: 
        !          3002:   /* Compute the maximum number of delay slots required.  We use the delay
        !          3003:      ordinal times this number plus one, plus the slot number as an index into
        !          3004:      the appropriate predicate to test.  */
        !          3005: 
        !          3006:   for (delay = delays, max_slots = 0; delay; delay = delay->next)
        !          3007:     if (XVECLEN (delay->def, 1) / 3 > max_slots)
        !          3008:       max_slots = XVECLEN (delay->def, 1) / 3;
        !          3009: 
        !          3010:   /* Write function prelude.  */
        !          3011: 
        !          3012:   printf ("int\n");
        !          3013:   printf ("eligible_for_%s (delay_insn, slot, candidate_insn)\n", kind);
        !          3014:   printf ("     rtx delay_insn;\n");
        !          3015:   printf ("     int slot;\n");
        !          3016:   printf ("     rtx candidate_insn;\n");
        !          3017:   printf ("{\n");
        !          3018:   printf ("  rtx insn;\n");
        !          3019:   printf ("\n");
        !          3020:   printf ("  if (slot >= %d)\n", max_slots);
        !          3021:   printf ("    abort ();\n");
        !          3022:   printf ("\n");
        !          3023: 
        !          3024:   /* If more than one delay type, find out which type the delay insn is.  */
        !          3025: 
        !          3026:   if (num_delays > 1)
        !          3027:     {
        !          3028:       sprintf (str, "*delay_type", kind);
        !          3029:       attr = find_attr (str, 0);
        !          3030:       if (! attr) abort ();
        !          3031:       common_av = find_most_used (attr);
        !          3032: 
        !          3033:       printf ("  insn = delay_insn;\n");
        !          3034:       printf ("  switch (recog_memoized (insn))\n");
        !          3035:       printf ("    {\n");
        !          3036: 
        !          3037:       sprintf (str, " * %d;\n      break;", max_slots);
        !          3038:       for (av = attr->first_value; av; av = av->next)
        !          3039:        if (av != common_av)
        !          3040:          write_attr_case (attr, av, 1, "slot +=", str, 4, true_rtx);
        !          3041: 
        !          3042:       write_attr_case (attr, common_av, 0, "slot +=", str, 4, true_rtx);
        !          3043:       printf ("    }\n\n");
        !          3044: 
        !          3045:       /* Ensure matched.  Otherwise, shouldn't have been called.  */
        !          3046:       printf ("  if (slot < %d)\n", max_slots);
        !          3047:       printf ("    abort ();\n\n");
        !          3048:     }
        !          3049: 
        !          3050:   /* If just one type of delay slot, write simple switch.  */
        !          3051:   if (num_delays == 1 && max_slots == 1)
        !          3052:     {
        !          3053:       printf ("  insn = candidate_insn;\n");
        !          3054:       printf ("  switch (recog_memoized (insn))\n");
        !          3055:       printf ("    {\n");
        !          3056: 
        !          3057:       attr = find_attr ("*delay_1_0", 0);
        !          3058:       if (! attr) abort ();
        !          3059:       common_av = find_most_used (attr);
        !          3060: 
        !          3061:       for (av = attr->first_value; av; av = av->next)
        !          3062:        if (av != common_av)
        !          3063:          write_attr_case (attr, av, 1, "return", ";", 4, true_rtx);
        !          3064: 
        !          3065:       write_attr_case (attr, common_av, 0, "return", ";", 4, true_rtx);
        !          3066:       printf ("    }\n");
        !          3067:     }
        !          3068: 
        !          3069:   else
        !          3070:     {
        !          3071:       /* Write a nested CASE.  The first indicates which condition we need to
        !          3072:         test, and the inner CASE tests the condition.  */
        !          3073:       printf ("  insn = candidate_insn;\n");
        !          3074:       printf ("  switch (slot)\n");
        !          3075:       printf ("    {\n");
        !          3076: 
        !          3077:       for (delay = delays; delay; delay = delay->next)
        !          3078:        for (i = 0; i < XVECLEN (delay->def, 1); i += 3)
        !          3079:          {
        !          3080:            printf ("    case %d:\n",
        !          3081:                    (i / 3) + (num_delays == 1 ? 0 : delay->num * max_slots));
        !          3082:            printf ("      switch (recog_memoized (insn))\n");
        !          3083:            printf ("\t{\n");
        !          3084: 
        !          3085:            sprintf (str, "*%s_%d_%d", kind, delay->num, i / 3);
        !          3086:            attr = find_attr (str, 0);
        !          3087:            if (! attr) abort ();
        !          3088:            common_av = find_most_used (attr);
        !          3089: 
        !          3090:            for (av = attr->first_value; av; av = av->next)
        !          3091:              if (av != common_av)
        !          3092:                write_attr_case (attr, av, 1, "return", ";", 8, true_rtx);
        !          3093: 
        !          3094:            write_attr_case (attr, common_av, 0, "return", ";", 8, true_rtx);
        !          3095:            printf ("      }\n");
        !          3096:          }
        !          3097: 
        !          3098:       printf ("    default:\n");
        !          3099:       printf ("      abort ();\n");     
        !          3100:       printf ("    }\n");
        !          3101:     }
        !          3102: 
        !          3103:   printf ("}\n\n");
        !          3104: }
        !          3105: 
        !          3106: /* Write routines to compute conflict cost for function units.  Then write a
        !          3107:    table describing the available function units.  */
        !          3108: 
        !          3109: static void
        !          3110: write_function_unit_info ()
        !          3111: {
        !          3112:   struct function_unit *unit;
        !          3113:   struct attr_desc *case_attr, *attr;
        !          3114:   struct attr_value *av, *common_av;
        !          3115:   rtx value;
        !          3116:   char *str;
        !          3117:   int using_case;
        !          3118:   int i;
        !          3119: 
        !          3120:   /* Write out conflict routines for function units.  Don't bother writing
        !          3121:      one if there is only one busy value.  */
        !          3122: 
        !          3123:   for (unit = units; unit; unit = unit->next)
        !          3124:     {
        !          3125:       /* See if only one case exists and if there is a constant value for
        !          3126:         that case.  If so, we don't need a function.  */
        !          3127:       str = (char *) xmalloc (strlen (unit->name) + 10);
        !          3128:       sprintf (str, "*%s_cases", unit->name);
        !          3129:       attr = find_attr (str, 0);
        !          3130:       if (! attr) abort ();
        !          3131:       value = find_single_value (attr);
        !          3132:       if (value && GET_CODE (value) == CONST_STRING)
        !          3133:        {
        !          3134:          sprintf (str, "*%s_case_%s", unit->name, XSTR (value, 0));
        !          3135:          attr = find_attr (str, 0);
        !          3136:          if (! attr) abort ();
        !          3137:          value = find_single_value (attr);
        !          3138:          if (value && GET_CODE (value) == CONST_STRING)
        !          3139:            {
        !          3140:              unit->needs_conflict_function = 0;
        !          3141:              unit->default_cost = value;
        !          3142:              continue;
        !          3143:            }
        !          3144:        }
        !          3145: 
        !          3146:       /* The function first computes the case from the candidate insn.  */
        !          3147:       unit->needs_conflict_function = 1;
        !          3148:       unit->default_cost = make_numeric_value (0);
        !          3149: 
        !          3150:       printf ("static int\n");
        !          3151:       printf ("%s_unit_conflict_cost (executing_insn, candidate_insn)\n",
        !          3152:              unit->name);
        !          3153:       printf ("     rtx executing_insn;\n");
        !          3154:       printf ("     rtx candidate_insn;\n");
        !          3155:       printf ("{\n");
        !          3156:       printf ("  rtx insn;\n");
        !          3157:       printf ("  int casenum;\n\n");
        !          3158:       printf ("  insn = candidate_insn;\n");
        !          3159:       printf ("  switch (recog_memoized (insn))\n");
        !          3160:       printf ("    {\n");
        !          3161: 
        !          3162:       /* Write the `switch' statement to get the case value.  */
        !          3163:       sprintf (str, "*%s_cases", unit->name);
        !          3164:       case_attr = find_attr (str, 0);
        !          3165:       if (! case_attr) abort ();
        !          3166:       common_av = find_most_used (case_attr);
        !          3167: 
        !          3168:       for (av = case_attr->first_value; av; av = av->next)
        !          3169:        if (av != common_av)
        !          3170:          write_attr_case (case_attr, av, 1,
        !          3171:                           "casenum =", ";", 4, unit->condexp);
        !          3172: 
        !          3173:       write_attr_case (case_attr, common_av, 0,
        !          3174:                       "casenum =", ";", 4, unit->condexp);
        !          3175:       printf ("    }\n\n");
        !          3176: 
        !          3177:       /* Now write an outer switch statement on each case.  Then write
        !          3178:         the tests on the executing function within each.  */
        !          3179:       printf ("  insn = executing_insn;\n");
        !          3180:       printf ("  switch (casenum)\n");
        !          3181:       printf ("    {\n");
        !          3182: 
        !          3183:       for (i = 0; i < unit->num_opclasses; i++)
        !          3184:        {
        !          3185:          /* Ensure using this case.  */
        !          3186:          using_case = 0;
        !          3187:          for (av = case_attr->first_value; av; av = av->next)
        !          3188:            if (av->num_insns
        !          3189:                && contained_in_p (make_numeric_value (i), av->value))
        !          3190:              using_case = 1;
        !          3191: 
        !          3192:          if (! using_case)
        !          3193:            continue;
        !          3194: 
        !          3195:          printf ("    case %d:\n", i);
        !          3196:          sprintf (str, "*%s_case_%d", unit->name, i);
        !          3197:          attr = find_attr (str, 0);
        !          3198:          if (! attr) abort ();
        !          3199: 
        !          3200:          /* If single value, just write it.  */
        !          3201:          value = find_single_value (attr);
        !          3202:          if (value)
        !          3203:            write_attr_set (attr, 6, value, "return", ";\n", true_rtx, -2);
        !          3204:          else
        !          3205:            {
        !          3206:              common_av = find_most_used (attr);
        !          3207:              printf ("      switch (recog_memoized (insn))\n");
        !          3208:              printf ("\t{\n");
        !          3209: 
        !          3210:              for (av = attr->first_value; av; av = av->next)
        !          3211:                if (av != common_av)
        !          3212:                  write_attr_case (attr, av, 1,
        !          3213:                                   "return", ";", 8, unit->condexp);
        !          3214: 
        !          3215:              write_attr_case (attr, common_av, 0,
        !          3216:                               "return", ";", 8, unit->condexp);
        !          3217:              printf ("      }\n\n");
        !          3218:            }
        !          3219:        }
        !          3220: 
        !          3221:       printf ("    }\n}\n\n");
        !          3222:     }
        !          3223: 
        !          3224:   /* Now that all functions have been written, write the table describing
        !          3225:      the function units.   The name is included for documenation purposes
        !          3226:      only.  */
        !          3227: 
        !          3228:   printf ("struct function_unit_desc function_units[] = {\n");
        !          3229: 
        !          3230:   for (unit = units; unit; unit = unit->next)
        !          3231:     {
        !          3232:       printf ("  {\"%s\", %d, %d, %d, %s, %s_unit_ready_cost, ",
        !          3233:              unit->name, 1 << unit->num, unit->multiplicity,
        !          3234:              unit->simultaneity, XSTR (unit->default_cost, 0), unit->name);
        !          3235: 
        !          3236:       if (unit->needs_conflict_function)
        !          3237:        printf ("%s_unit_conflict_cost", unit->name);
        !          3238:       else
        !          3239:        printf ("0");
        !          3240: 
        !          3241:       printf ("}, \n");
        !          3242:     }
        !          3243: 
        !          3244:   printf ("};\n\n");
        !          3245: }
        !          3246: 
        !          3247: /* This page contains miscellaneous utility routines.  */
        !          3248: 
        !          3249: /* Given a string, return the number of comma-separated elements in it.
        !          3250:    Return 0 for the null string.  */
        !          3251: 
        !          3252: static int
        !          3253: n_comma_elts (s)
        !          3254:      char *s;
        !          3255: {
        !          3256:   int n;
        !          3257: 
        !          3258:   if (*s == '\0')
        !          3259:     return 0;
        !          3260: 
        !          3261:   for (n = 1; *s; s++)
        !          3262:     if (*s == ',')
        !          3263:       n++;
        !          3264: 
        !          3265:   return n;
        !          3266: }
        !          3267: 
        !          3268: /* Given a pointer to a (char *), return a malloc'ed string containing the
        !          3269:    next comma-separated element.  Advance the pointer to after the string
        !          3270:    scanned, or the end-of-string.  Return NULL if at end of string.  */
        !          3271: 
        !          3272: static char *
        !          3273: next_comma_elt (pstr)
        !          3274:      char **pstr;
        !          3275: {
        !          3276:   char *out_str;
        !          3277:   char *p;
        !          3278: 
        !          3279:   if (**pstr == '\0')
        !          3280:     return NULL;
        !          3281: 
        !          3282:   /* Find end of string to compute length.  */
        !          3283:   for (p = *pstr; *p != ',' && *p != '\0'; p++)
        !          3284:     ;
        !          3285: 
        !          3286:   out_str = (char *) xmalloc (p - *pstr + 1);
        !          3287:   for (p = out_str; **pstr != ',' && **pstr != '\0'; (*pstr)++)
        !          3288:     *p++ = **pstr;
        !          3289: 
        !          3290:   *p++ = '\0';
        !          3291:   if (**pstr == ',')
        !          3292:     (*pstr)++;
        !          3293: 
        !          3294:   return out_str;
        !          3295: }
        !          3296: 
        !          3297: /* Return a `struct attr_desc' pointer for a given named attribute.  If CREATE
        !          3298:    is non-zero, build a new attribute, if one does not exist.  */
        !          3299: 
        !          3300: static struct attr_desc *
        !          3301: find_attr (name, create)
        !          3302:      char *name;
        !          3303:      int create;
        !          3304: {
        !          3305:   struct attr_desc *attr;
        !          3306:   char *new_name;
        !          3307: 
        !          3308:   /* Before we resort to using `strcmp', see if the string address matches
        !          3309:      anywhere.  In most cases, it should have been canonicalized to do so.  */
        !          3310:   if (name == alternative_name)
        !          3311:     return NULL;
        !          3312: 
        !          3313:   for (attr = attrs; attr; attr = attr->next)
        !          3314:     if (name == attr->name)
        !          3315:       return attr;
        !          3316: 
        !          3317:   /* Otherwise, do it the slow way.  */
        !          3318:   for (attr = attrs; attr; attr = attr->next)
        !          3319:     if (! strcmp (name, attr->name))
        !          3320:       return attr;
        !          3321: 
        !          3322:   if (! create)
        !          3323:     return NULL;
        !          3324: 
        !          3325:   new_name = (char *) xmalloc (strlen (name) + 1);
        !          3326:   strcpy (new_name, name);
        !          3327: 
        !          3328:   attr = (struct attr_desc *) xmalloc (sizeof (struct attr_desc));
        !          3329:   attr->name = new_name;
        !          3330:   attr->first_value = attr->default_val = NULL;
        !          3331:   attr->is_numeric = attr->is_special = 0;
        !          3332:   attr->next = attrs;
        !          3333:   attrs = attr;
        !          3334: 
        !          3335:   return attr;
        !          3336: }
        !          3337: 
        !          3338: /* Create internal attribute with the given default value.  */
        !          3339: 
        !          3340: static void
        !          3341: make_internal_attr (name, value, special)
        !          3342:      char *name;
        !          3343:      rtx value;
        !          3344:      int special;
        !          3345: {
        !          3346:   struct attr_desc *attr;
        !          3347: 
        !          3348:   attr = find_attr (name, 1);
        !          3349:   if (attr->default_val)
        !          3350:     abort ();
        !          3351: 
        !          3352:   attr->is_numeric = 1;
        !          3353:   attr->is_special = special;
        !          3354:   attr->default_val = get_attr_value (value, attr, -2);
        !          3355: }
        !          3356: 
        !          3357: /* Find the most used value of an attribute.  */
        !          3358: 
        !          3359: static struct attr_value *
        !          3360: find_most_used (attr)
        !          3361:      struct attr_desc *attr;
        !          3362: {
        !          3363:   struct attr_value *av;
        !          3364:   struct attr_value *most_used;
        !          3365:   int nuses;
        !          3366: 
        !          3367:   most_used = NULL;
        !          3368:   nuses = -1;
        !          3369: 
        !          3370:   for (av = attr->first_value; av; av = av->next)
        !          3371:     if (av->num_insns > nuses)
        !          3372:       nuses = av->num_insns, most_used = av;
        !          3373: 
        !          3374:   return most_used;
        !          3375: }
        !          3376: 
        !          3377: /* If an attribute only has a single value used, return it.  Otherwise
        !          3378:    return NULL.  */
        !          3379: 
        !          3380: static rtx
        !          3381: find_single_value (attr)
        !          3382:      struct attr_desc *attr;
        !          3383: {
        !          3384:   struct attr_value *av;
        !          3385:   rtx unique_value;
        !          3386: 
        !          3387:   unique_value = NULL;
        !          3388:   for (av = attr->first_value; av; av = av->next)
        !          3389:     if (av->num_insns)
        !          3390:       {
        !          3391:        if (unique_value)
        !          3392:          return NULL;
        !          3393:        else
        !          3394:          unique_value = av->value;
        !          3395:       }
        !          3396: 
        !          3397:   return unique_value;
        !          3398: }
        !          3399: 
        !          3400: /* Return (attr_value "n") */
        !          3401: 
        !          3402: static rtx
        !          3403: make_numeric_value (n)
        !          3404:      int n;
        !          3405: {
        !          3406:   static rtx int_values[20];
        !          3407:   rtx exp;
        !          3408: 
        !          3409:   if (n < 0)
        !          3410:     abort ();
        !          3411: 
        !          3412:   if (n < 20 && int_values[n])
        !          3413:     return int_values[n];
        !          3414: 
        !          3415:   exp = rtx_alloc (CONST_STRING);
        !          3416:   XSTR (exp, 0) = (char *) xmalloc ((n < 1000 ? 4
        !          3417:                                     : HOST_BITS_PER_INT * 3 / 10 + 3));
        !          3418:   sprintf (XSTR (exp, 0), "%d", n);
        !          3419: 
        !          3420:   if (n < 20)
        !          3421:     int_values[n] = exp;
        !          3422: 
        !          3423:   return exp;
        !          3424: }
        !          3425: 
        !          3426: char *
        !          3427: xrealloc (ptr, size)
        !          3428:      char *ptr;
        !          3429:      unsigned size;
        !          3430: {
        !          3431:   char *result = (char *) realloc (ptr, size);
        !          3432:   if (!result)
        !          3433:     fatal ("virtual memory exhausted");
        !          3434:   return result;
        !          3435: }
        !          3436: 
        !          3437: char *
        !          3438: xmalloc (size)
        !          3439:      unsigned size;
        !          3440: {
        !          3441:   register char *val = (char *) malloc (size);
        !          3442: 
        !          3443:   if (val == 0)
        !          3444:     fatal ("virtual memory exhausted");
        !          3445:   return val;
        !          3446: }
        !          3447: 
        !          3448: static void
        !          3449: fatal (s, a1, a2)
        !          3450:      char *s;
        !          3451: {
        !          3452:   fprintf (stderr, "genattrtab: ");
        !          3453:   fprintf (stderr, s, a1, a2);
        !          3454:   fprintf (stderr, "\n");
        !          3455:   exit (FATAL_EXIT_CODE);
        !          3456: }
        !          3457: 
        !          3458: /* More 'friendly' abort that prints the line and file.
        !          3459:    config.h can #define abort fancy_abort if you like that sort of thing.  */
        !          3460: 
        !          3461: void
        !          3462: fancy_abort ()
        !          3463: {
        !          3464:   fatal ("Internal gcc abort.");
        !          3465: }
        !          3466: 
        !          3467: int
        !          3468: main (argc, argv)
        !          3469:      int argc;
        !          3470:      char **argv;
        !          3471: {
        !          3472:   rtx desc;
        !          3473:   FILE *infile;
        !          3474:   extern rtx read_rtx ();
        !          3475:   register int c;
        !          3476:   struct attr_desc *attr;
        !          3477:   struct attr_value *av;
        !          3478:   struct insn_def *id;
        !          3479:   rtx tem;
        !          3480: 
        !          3481:   obstack_init (rtl_obstack);
        !          3482: 
        !          3483:   if (argc <= 1)
        !          3484:     fatal ("No input file name.");
        !          3485: 
        !          3486:   infile = fopen (argv[1], "r");
        !          3487:   if (infile == 0)
        !          3488:     {
        !          3489:       perror (argv[1]);
        !          3490:       exit (FATAL_EXIT_CODE);
        !          3491:     }
        !          3492: 
        !          3493:   init_rtl ();
        !          3494: 
        !          3495:   /* Set up true and false rtx's */
        !          3496:   true_rtx = rtx_alloc (CONST_INT);
        !          3497:   false_rtx = rtx_alloc (CONST_INT);
        !          3498:   XINT (true_rtx, 0) = 1;
        !          3499:   XINT (false_rtx, 0) = 0;
        !          3500:   RTX_UNCHANGING_P (true_rtx) = RTX_UNCHANGING_P (false_rtx) = 1;
        !          3501: 
        !          3502:   printf ("/* Generated automatically by the program `genattrtab'\n\
        !          3503: from the machine description file `md'.  */\n\n");
        !          3504: 
        !          3505:   /* Read the machine description.  */
        !          3506: 
        !          3507:   while (1)
        !          3508:     {
        !          3509:       c = read_skip_spaces (infile);
        !          3510:       if (c == EOF)
        !          3511:        break;
        !          3512:       ungetc (c, infile);
        !          3513: 
        !          3514:       desc = read_rtx (infile);
        !          3515:       if (GET_CODE (desc) == DEFINE_INSN
        !          3516:          || GET_CODE (desc) == DEFINE_PEEPHOLE
        !          3517:          || GET_CODE (desc) == DEFINE_ASM_ATTRIBUTES)
        !          3518:        gen_insn (desc);
        !          3519: 
        !          3520:       else if (GET_CODE (desc) == DEFINE_EXPAND)
        !          3521:        insn_code_number++, insn_index_number++;
        !          3522: 
        !          3523:       else if (GET_CODE (desc) == DEFINE_SPLIT)
        !          3524:        insn_code_number++, insn_index_number++;
        !          3525: 
        !          3526:       else if (GET_CODE (desc) == DEFINE_ATTR)
        !          3527:        {
        !          3528:          gen_attr (desc);
        !          3529:          insn_index_number++;
        !          3530:        }
        !          3531: 
        !          3532:       else if (GET_CODE (desc) == DEFINE_DELAY)
        !          3533:        {
        !          3534:          gen_delay (desc);
        !          3535:          insn_index_number++;
        !          3536:        }
        !          3537: 
        !          3538:       else if (GET_CODE (desc) == DEFINE_FUNCTION_UNIT)
        !          3539:        {
        !          3540:          gen_unit (desc);
        !          3541:          insn_index_number++;
        !          3542:        }
        !          3543:     }
        !          3544: 
        !          3545:   /* If we didn't have a DEFINE_ASM_ATTRIBUTES, make a null one.  */
        !          3546:   if (! got_define_asm_attributes)
        !          3547:     {
        !          3548:       tem = rtx_alloc (DEFINE_ASM_ATTRIBUTES);
        !          3549:       XVEC (tem, 0) = rtvec_alloc (0);
        !          3550:       gen_insn (tem);
        !          3551:     }
        !          3552: 
        !          3553:   /* Expand DEFINE_DELAY information into new attribute.  */
        !          3554:   if (num_delays)
        !          3555:     expand_delays ();
        !          3556: 
        !          3557:   /* Expand DEFINE_FUNCTION_UNIT information into new attributes.  */
        !          3558:   if (num_units)
        !          3559:     expand_units ();
        !          3560: 
        !          3561:   printf ("#include \"config.h\"\n");
        !          3562:   printf ("#include \"rtl.h\"\n");
        !          3563:   printf ("#include \"insn-config.h\"\n");
        !          3564:   printf ("#include \"recog.h\"\n");
        !          3565:   printf ("#include \"regs.h\"\n");
        !          3566:   printf ("#include \"real.h\"\n");
        !          3567:   printf ("#include \"output.h\"\n");
        !          3568:   printf ("#include \"insn-attr.h\"\n");
        !          3569:   printf ("\n");  
        !          3570:   printf ("#define operands recog_operand\n\n");
        !          3571: 
        !          3572:   /* Make `insn_alternatives'.  */
        !          3573:   insn_alternatives = (int *) xmalloc (insn_code_number * sizeof (int));
        !          3574:   for (id = defs; id; id = id->next)
        !          3575:     if (id->insn_code >= 0)
        !          3576:       insn_alternatives[id->insn_code] = (1 << id->num_alternatives) - 1;
        !          3577: 
        !          3578:   /* Prepare to write out attribute subroutines by checking everything stored
        !          3579:      away and building the attribute cases.  */
        !          3580: 
        !          3581:   check_defs ();
        !          3582:   for (attr = attrs; attr; attr = attr->next)
        !          3583:     {
        !          3584:       check_attr_value (attr->default_val->value, attr);
        !          3585:       fill_attr (attr);
        !          3586:     }
        !          3587: 
        !          3588:   /* Construct extra attributes for `length'.  */
        !          3589:   make_length_attrs ();
        !          3590: 
        !          3591:   /* Perform any possible optimizations to speed up compilation. */
        !          3592:   optimize_attrs ();
        !          3593: 
        !          3594:   /* Now write out all the `gen_attr_...' routines.  Do these before the
        !          3595:      special routines (specifically before write_function_unit_info), so
        !          3596:      that they get defined before they are used.  */
        !          3597: 
        !          3598:   for (attr = attrs; attr; attr = attr->next)
        !          3599:     {
        !          3600:       if (! attr->is_special)
        !          3601:        write_attr_get (attr);
        !          3602:     }
        !          3603: 
        !          3604:   /* Write out delay eligibility information, if DEFINE_DELAY present.
        !          3605:      (The function to compute the number of delay slots will be written
        !          3606:      below.)  */
        !          3607:   if (num_delays)
        !          3608:     {
        !          3609:       write_eligible_delay ("delay");
        !          3610:       if (have_annul_true)
        !          3611:        write_eligible_delay ("annul_true");
        !          3612:       if (have_annul_false)
        !          3613:        write_eligible_delay ("annul_false");
        !          3614:     }
        !          3615: 
        !          3616:   /* Write out information about function units.  */
        !          3617:   if (num_units)
        !          3618:     write_function_unit_info ();
        !          3619: 
        !          3620:   fflush (stdout);
        !          3621:   exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
        !          3622:   /* NOTREACHED */
        !          3623:   return 0;
        !          3624: }

unix.superglobalmegacorp.com

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