|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.