Annotation of gcc/genattrtab.c, revision 1.1.1.2

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

unix.superglobalmegacorp.com

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