00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095 #define ATTR_IND_SIMPLIFIED_P(RTX) (RTX_FLAG((RTX), unchanging))
00096 #define ATTR_CURR_SIMPLIFIED_P(RTX) (RTX_FLAG((RTX), in_struct))
00097 #define ATTR_PERMANENT_P(RTX) (RTX_FLAG((RTX), return_val))
00098
00099 #if 0
00100 #define strcmp_check(S1, S2) ((S1) == (S2) \
00101 ? 0 \
00102 : (gcc_assert (strcmp ((S1), (S2))), 1))
00103 #else
00104 #define strcmp_check(S1, S2) ((S1) != (S2))
00105 #endif
00106
00107 #include "bconfig.h"
00108 #include "system.h"
00109 #include "coretypes.h"
00110 #include "tm.h"
00111 #include "rtl.h"
00112 #include "gensupport.h"
00113 #include "obstack.h"
00114 #include "errors.h"
00115
00116
00117 #define ATTR_NONE 0
00118 #define ATTR_SPECIAL (1 << 0)
00119
00120 static struct obstack obstack1, obstack2;
00121 static struct obstack *hash_obstack = &obstack1;
00122 static struct obstack *temp_obstack = &obstack2;
00123
00124
00125 #define MAX_DIGITS (HOST_BITS_PER_INT * 3 / 10 + 3)
00126
00127
00128
00129
00130
00131
00132
00133
00134 struct insn_def
00135 {
00136 struct insn_def *next;
00137 rtx def;
00138 int insn_code;
00139 int insn_index;
00140 int lineno;
00141 int num_alternatives;
00142 int vec_idx;
00143 };
00144
00145
00146
00147
00148
00149 struct insn_ent
00150 {
00151 struct insn_ent *next;
00152 struct insn_def *def;
00153 };
00154
00155
00156
00157
00158
00159 struct attr_value
00160 {
00161 rtx value;
00162 struct attr_value *next;
00163 struct insn_ent *first_insn;
00164 int num_insns;
00165 int has_asm_insn;
00166 };
00167
00168
00169
00170 struct attr_desc
00171 {
00172 char *name;
00173 struct attr_desc *next;
00174 struct attr_value *first_value;
00175 struct attr_value *default_val;
00176 int lineno : 24;
00177 unsigned is_numeric : 1;
00178 unsigned is_const : 1;
00179 unsigned is_special : 1;
00180 };
00181
00182
00183
00184 struct delay_desc
00185 {
00186 rtx def;
00187 struct delay_desc *next;
00188 int num;
00189 int lineno;
00190 };
00191
00192
00193
00194
00195 #define MAX_ATTRS_INDEX 256
00196 static struct attr_desc *attrs[MAX_ATTRS_INDEX];
00197 static struct insn_def *defs;
00198 static struct delay_desc *delays;
00199
00200
00201
00202 static int insn_code_number;
00203 static int insn_index_number;
00204 static int got_define_asm_attributes;
00205 static int must_extract;
00206 static int must_constrain;
00207 static int address_used;
00208 static int length_used;
00209 static int num_delays;
00210 static int have_annul_true, have_annul_false;
00211 static int num_insn_ents;
00212
00213
00214
00215 static int *insn_n_alternatives;
00216
00217
00218
00219
00220 static int *insn_alternatives;
00221
00222
00223
00224 static rtx true_rtx, false_rtx;
00225
00226
00227
00228 static const char *alternative_name;
00229 static const char *length_str;
00230 static const char *delay_type_str;
00231 static const char *delay_1_0_str;
00232 static const char *num_delay_slots_str;
00233
00234
00235
00236 #define SIMPLIFY_TEST_EXP(EXP,INSN_CODE,INSN_INDEX) \
00237 (ATTR_IND_SIMPLIFIED_P (EXP) || ATTR_CURR_SIMPLIFIED_P (EXP) ? (EXP) \
00238 : simplify_test_exp (EXP, INSN_CODE, INSN_INDEX))
00239
00240 #define DEF_ATTR_STRING(S) (attr_string ((S), strlen (S)))
00241
00242
00243 static char *attr_string (const char *, int);
00244 static char *attr_printf (unsigned int, const char *, ...)
00245 ATTRIBUTE_PRINTF_2;
00246 static rtx make_numeric_value (int);
00247 static struct attr_desc *find_attr (const char **, int);
00248 static rtx mk_attr_alt (int);
00249 static char *next_comma_elt (const char **);
00250 static rtx insert_right_side (enum rtx_code, rtx, rtx, int, int);
00251 static rtx copy_boolean (rtx);
00252 static int compares_alternatives_p (rtx);
00253 static void make_internal_attr (const char *, rtx, int);
00254 static void insert_insn_ent (struct attr_value *, struct insn_ent *);
00255 static void walk_attr_value (rtx);
00256 static int max_attr_value (rtx, int*);
00257 static int min_attr_value (rtx, int*);
00258 static int or_attr_value (rtx, int*);
00259 static rtx simplify_test_exp (rtx, int, int);
00260 static rtx simplify_test_exp_in_temp (rtx, int, int);
00261 static rtx copy_rtx_unchanging (rtx);
00262 static bool attr_alt_subset_p (rtx, rtx);
00263 static bool attr_alt_subset_of_compl_p (rtx, rtx);
00264 static void clear_struct_flag (rtx);
00265 static void write_attr_valueq (struct attr_desc *, const char *);
00266 static struct attr_value *find_most_used (struct attr_desc *);
00267 static void write_attr_set (struct attr_desc *, int, rtx,
00268 const char *, const char *, rtx,
00269 int, int);
00270 static void write_attr_case (struct attr_desc *, struct attr_value *,
00271 int, const char *, const char *, int, rtx);
00272 static void write_attr_value (struct attr_desc *, rtx);
00273 static void write_upcase (const char *);
00274 static void write_indent (int);
00275 static rtx identity_fn (rtx);
00276 static rtx zero_fn (rtx);
00277 static rtx one_fn (rtx);
00278 static rtx max_fn (rtx);
00279 static rtx min_fn (rtx);
00280
00281 #define oballoc(size) obstack_alloc (hash_obstack, size)
00282
00283
00284
00285
00286
00287
00288
00289 struct attr_hash
00290 {
00291 struct attr_hash *next;
00292 int hashcode;
00293 union
00294 {
00295 char *str;
00296 rtx rtl;
00297 } u;
00298 };
00299
00300
00301
00302
00303
00304
00305
00306
00307 #define RTL_HASH_SIZE 4093
00308 static struct attr_hash *attr_hash_table[RTL_HASH_SIZE];
00309
00310
00311
00312 #define RTL_HASH(RTL) ((long) (RTL) & 0777777)
00313
00314
00315
00316 static void
00317 attr_hash_add_rtx (int hashcode, rtx rtl)
00318 {
00319 struct attr_hash *h;
00320
00321 h = obstack_alloc (hash_obstack, sizeof (struct attr_hash));
00322 h->hashcode = hashcode;
00323 h->u.rtl = rtl;
00324 h->next = attr_hash_table[hashcode % RTL_HASH_SIZE];
00325 attr_hash_table[hashcode % RTL_HASH_SIZE] = h;
00326 }
00327
00328
00329
00330 static void
00331 attr_hash_add_string (int hashcode, char *str)
00332 {
00333 struct attr_hash *h;
00334
00335 h = obstack_alloc (hash_obstack, sizeof (struct attr_hash));
00336 h->hashcode = -hashcode;
00337 h->u.str = str;
00338 h->next = attr_hash_table[hashcode % RTL_HASH_SIZE];
00339 attr_hash_table[hashcode % RTL_HASH_SIZE] = h;
00340 }
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352 static rtx
00353 attr_rtx_1 (enum rtx_code code, va_list p)
00354 {
00355 rtx rt_val = NULL_RTX;
00356 int hashcode;
00357 struct attr_hash *h;
00358 struct obstack *old_obstack = rtl_obstack;
00359
00360
00361
00362
00363
00364 if (GET_RTX_CLASS (code) == RTX_UNARY)
00365 {
00366 rtx arg0 = va_arg (p, rtx);
00367
00368
00369 if (! ATTR_PERMANENT_P (arg0))
00370 {
00371 rt_val = rtx_alloc (code);
00372 XEXP (rt_val, 0) = arg0;
00373 return rt_val;
00374 }
00375
00376 hashcode = ((HOST_WIDE_INT) code + RTL_HASH (arg0));
00377 for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next)
00378 if (h->hashcode == hashcode
00379 && GET_CODE (h->u.rtl) == code
00380 && XEXP (h->u.rtl, 0) == arg0)
00381 return h->u.rtl;
00382
00383 if (h == 0)
00384 {
00385 rtl_obstack = hash_obstack;
00386 rt_val = rtx_alloc (code);
00387 XEXP (rt_val, 0) = arg0;
00388 }
00389 }
00390 else if (GET_RTX_CLASS (code) == RTX_BIN_ARITH
00391 || GET_RTX_CLASS (code) == RTX_COMM_ARITH
00392 || GET_RTX_CLASS (code) == RTX_COMPARE
00393 || GET_RTX_CLASS (code) == RTX_COMM_COMPARE)
00394 {
00395 rtx arg0 = va_arg (p, rtx);
00396 rtx arg1 = va_arg (p, rtx);
00397
00398
00399 if (! ATTR_PERMANENT_P (arg0) || ! ATTR_PERMANENT_P (arg1))
00400 {
00401 rt_val = rtx_alloc (code);
00402 XEXP (rt_val, 0) = arg0;
00403 XEXP (rt_val, 1) = arg1;
00404 return rt_val;
00405 }
00406
00407 hashcode = ((HOST_WIDE_INT) code + RTL_HASH (arg0) + RTL_HASH (arg1));
00408 for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next)
00409 if (h->hashcode == hashcode
00410 && GET_CODE (h->u.rtl) == code
00411 && XEXP (h->u.rtl, 0) == arg0
00412 && XEXP (h->u.rtl, 1) == arg1)
00413 return h->u.rtl;
00414
00415 if (h == 0)
00416 {
00417 rtl_obstack = hash_obstack;
00418 rt_val = rtx_alloc (code);
00419 XEXP (rt_val, 0) = arg0;
00420 XEXP (rt_val, 1) = arg1;
00421 }
00422 }
00423 else if (GET_RTX_LENGTH (code) == 1
00424 && GET_RTX_FORMAT (code)[0] == 's')
00425 {
00426 char *arg0 = va_arg (p, char *);
00427
00428 arg0 = DEF_ATTR_STRING (arg0);
00429
00430 hashcode = ((HOST_WIDE_INT) code + RTL_HASH (arg0));
00431 for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next)
00432 if (h->hashcode == hashcode
00433 && GET_CODE (h->u.rtl) == code
00434 && XSTR (h->u.rtl, 0) == arg0)
00435 return h->u.rtl;
00436
00437 if (h == 0)
00438 {
00439 rtl_obstack = hash_obstack;
00440 rt_val = rtx_alloc (code);
00441 XSTR (rt_val, 0) = arg0;
00442 }
00443 }
00444 else if (GET_RTX_LENGTH (code) == 2
00445 && GET_RTX_FORMAT (code)[0] == 's'
00446 && GET_RTX_FORMAT (code)[1] == 's')
00447 {
00448 char *arg0 = va_arg (p, char *);
00449 char *arg1 = va_arg (p, char *);
00450
00451 hashcode = ((HOST_WIDE_INT) code + RTL_HASH (arg0) + RTL_HASH (arg1));
00452 for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next)
00453 if (h->hashcode == hashcode
00454 && GET_CODE (h->u.rtl) == code
00455 && XSTR (h->u.rtl, 0) == arg0
00456 && XSTR (h->u.rtl, 1) == arg1)
00457 return h->u.rtl;
00458
00459 if (h == 0)
00460 {
00461 rtl_obstack = hash_obstack;
00462 rt_val = rtx_alloc (code);
00463 XSTR (rt_val, 0) = arg0;
00464 XSTR (rt_val, 1) = arg1;
00465 }
00466 }
00467 else if (code == CONST_INT)
00468 {
00469 HOST_WIDE_INT arg0 = va_arg (p, HOST_WIDE_INT);
00470 if (arg0 == 0)
00471 return false_rtx;
00472 else if (arg0 == 1)
00473 return true_rtx;
00474 else
00475 goto nohash;
00476 }
00477 else
00478 {
00479 int i;
00480 const char *fmt;
00481 nohash:
00482 rt_val = rtx_alloc (code);
00483
00484 fmt = GET_RTX_FORMAT (code);
00485 for (i = 0; i < GET_RTX_LENGTH (code); i++)
00486 {
00487 switch (*fmt++)
00488 {
00489 case '0':
00490 break;
00491
00492 case 'i':
00493 XINT (rt_val, i) = va_arg (p, int);
00494 break;
00495
00496 case 'w':
00497 XWINT (rt_val, i) = va_arg (p, HOST_WIDE_INT);
00498 break;
00499
00500 case 's':
00501 XSTR (rt_val, i) = va_arg (p, char *);
00502 break;
00503
00504 case 'e':
00505 case 'u':
00506 XEXP (rt_val, i) = va_arg (p, rtx);
00507 break;
00508
00509 case 'E':
00510 XVEC (rt_val, i) = va_arg (p, rtvec);
00511 break;
00512
00513 default:
00514 gcc_unreachable ();
00515 }
00516 }
00517 return rt_val;
00518 }
00519
00520 rtl_obstack = old_obstack;
00521 attr_hash_add_rtx (hashcode, rt_val);
00522 ATTR_PERMANENT_P (rt_val) = 1;
00523 return rt_val;
00524 }
00525
00526 static rtx
00527 attr_rtx (enum rtx_code code, ...)
00528 {
00529 rtx result;
00530 va_list p;
00531
00532 va_start (p, code);
00533 result = attr_rtx_1 (code, p);
00534 va_end (p);
00535 return result;
00536 }
00537
00538
00539
00540
00541
00542
00543 static char *
00544 attr_printf (unsigned int len, const char *fmt, ...)
00545 {
00546 char str[256];
00547 va_list p;
00548
00549 va_start (p, fmt);
00550
00551 gcc_assert (len < sizeof str);
00552
00553 vsprintf (str, fmt, p);
00554 va_end (p);
00555
00556 return DEF_ATTR_STRING (str);
00557 }
00558
00559 static rtx
00560 attr_eq (const char *name, const char *value)
00561 {
00562 return attr_rtx (EQ_ATTR, DEF_ATTR_STRING (name), DEF_ATTR_STRING (value));
00563 }
00564
00565 static const char *
00566 attr_numeral (int n)
00567 {
00568 return XSTR (make_numeric_value (n), 0);
00569 }
00570
00571
00572
00573
00574 static char *
00575 attr_string (const char *str, int len)
00576 {
00577 struct attr_hash *h;
00578 int hashcode;
00579 int i;
00580 char *new_str;
00581
00582
00583 hashcode = (len + 1) * 613 + (unsigned) str[0];
00584 for (i = 1; i < len; i += 2)
00585 hashcode = ((hashcode * 613) + (unsigned) str[i]);
00586 if (hashcode < 0)
00587 hashcode = -hashcode;
00588
00589
00590 for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next)
00591 if (h->hashcode == -hashcode && h->u.str[0] == str[0]
00592 && !strncmp (h->u.str, str, len))
00593 return h->u.str;
00594
00595
00596 new_str = obstack_alloc (hash_obstack, len + 1);
00597 memcpy (new_str, str, len);
00598 new_str[len] = '\0';
00599 attr_hash_add_string (hashcode, new_str);
00600
00601 return new_str;
00602 }
00603
00604
00605
00606
00607
00608 static int
00609 attr_equal_p (rtx x, rtx y)
00610 {
00611 return (x == y || (! (ATTR_PERMANENT_P (x) && ATTR_PERMANENT_P (y))
00612 && rtx_equal_p (x, y)));
00613 }
00614
00615
00616
00617
00618
00619 static rtx
00620 attr_copy_rtx (rtx orig)
00621 {
00622 rtx copy;
00623 int i, j;
00624 RTX_CODE code;
00625 const char *format_ptr;
00626
00627
00628 if (ATTR_PERMANENT_P (orig))
00629 return orig;
00630
00631 code = GET_CODE (orig);
00632
00633 switch (code)
00634 {
00635 case REG:
00636 case CONST_INT:
00637 case CONST_DOUBLE:
00638 case CONST_VECTOR:
00639 case SYMBOL_REF:
00640 case CODE_LABEL:
00641 case PC:
00642 case CC0:
00643 return orig;
00644
00645 default:
00646 break;
00647 }
00648
00649 copy = rtx_alloc (code);
00650 PUT_MODE (copy, GET_MODE (orig));
00651 ATTR_IND_SIMPLIFIED_P (copy) = ATTR_IND_SIMPLIFIED_P (orig);
00652 ATTR_CURR_SIMPLIFIED_P (copy) = ATTR_CURR_SIMPLIFIED_P (orig);
00653 ATTR_PERMANENT_P (copy) = ATTR_PERMANENT_P (orig);
00654
00655 format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
00656
00657 for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
00658 {
00659 switch (*format_ptr++)
00660 {
00661 case 'e':
00662 XEXP (copy, i) = XEXP (orig, i);
00663 if (XEXP (orig, i) != NULL)
00664 XEXP (copy, i) = attr_copy_rtx (XEXP (orig, i));
00665 break;
00666
00667 case 'E':
00668 case 'V':
00669 XVEC (copy, i) = XVEC (orig, i);
00670 if (XVEC (orig, i) != NULL)
00671 {
00672 XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
00673 for (j = 0; j < XVECLEN (copy, i); j++)
00674 XVECEXP (copy, i, j) = attr_copy_rtx (XVECEXP (orig, i, j));
00675 }
00676 break;
00677
00678 case 'n':
00679 case 'i':
00680 XINT (copy, i) = XINT (orig, i);
00681 break;
00682
00683 case 'w':
00684 XWINT (copy, i) = XWINT (orig, i);
00685 break;
00686
00687 case 's':
00688 case 'S':
00689 XSTR (copy, i) = XSTR (orig, i);
00690 break;
00691
00692 default:
00693 gcc_unreachable ();
00694 }
00695 }
00696 return copy;
00697 }
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713 static rtx
00714 check_attr_test (rtx exp, int is_const, int lineno)
00715 {
00716 struct attr_desc *attr;
00717 struct attr_value *av;
00718 const char *name_ptr, *p;
00719 rtx orexp, newexp;
00720
00721 switch (GET_CODE (exp))
00722 {
00723 case EQ_ATTR:
00724
00725 if (XSTR (exp, 1)[0] == '!')
00726 return check_attr_test (attr_rtx (NOT,
00727 attr_eq (XSTR (exp, 0),
00728 &XSTR (exp, 1)[1])),
00729 is_const, lineno);
00730
00731 else if (n_comma_elts (XSTR (exp, 1)) == 1)
00732 {
00733 attr = find_attr (&XSTR (exp, 0), 0);
00734 if (attr == NULL)
00735 {
00736 if (! strcmp (XSTR (exp, 0), "alternative"))
00737 return mk_attr_alt (1 << atoi (XSTR (exp, 1)));
00738 else
00739 fatal ("unknown attribute `%s' in EQ_ATTR", XSTR (exp, 0));
00740 }
00741
00742 if (is_const && ! attr->is_const)
00743 fatal ("constant expression uses insn attribute `%s' in EQ_ATTR",
00744 XSTR (exp, 0));
00745
00746
00747
00748 exp = attr_eq (XSTR (exp, 0), XSTR (exp, 1));
00749
00750
00751
00752
00753 if (attr->is_const)
00754 ATTR_IND_SIMPLIFIED_P (exp) = 1;
00755
00756 if (attr->is_numeric)
00757 {
00758 for (p = XSTR (exp, 1); *p; p++)
00759 if (! ISDIGIT (*p))
00760 fatal ("attribute `%s' takes only numeric values",
00761 XSTR (exp, 0));
00762 }
00763 else
00764 {
00765 for (av = attr->first_value; av; av = av->next)
00766 if (GET_CODE (av->value) == CONST_STRING
00767 && ! strcmp (XSTR (exp, 1), XSTR (av->value, 0)))
00768 break;
00769
00770 if (av == NULL)
00771 fatal ("unknown value `%s' for `%s' attribute",
00772 XSTR (exp, 1), XSTR (exp, 0));
00773 }
00774 }
00775 else
00776 {
00777 if (! strcmp (XSTR (exp, 0), "alternative"))
00778 {
00779 int set = 0;
00780
00781 name_ptr = XSTR (exp, 1);
00782 while ((p = next_comma_elt (&name_ptr)) != NULL)
00783 set |= 1 << atoi (p);
00784
00785 return mk_attr_alt (set);
00786 }
00787 else
00788 {
00789
00790 orexp = false_rtx;
00791 name_ptr = XSTR (exp, 1);
00792 while ((p = next_comma_elt (&name_ptr)) != NULL)
00793 {
00794 newexp = attr_eq (XSTR (exp, 0), p);
00795 orexp = insert_right_side (IOR, orexp, newexp, -2, -2);
00796 }
00797
00798 return check_attr_test (orexp, is_const, lineno);
00799 }
00800 }
00801 break;
00802
00803 case ATTR_FLAG:
00804 break;
00805
00806 case CONST_INT:
00807
00808 if (XWINT (exp, 0))
00809 return true_rtx;
00810 else
00811 return false_rtx;
00812
00813 case IOR:
00814 case AND:
00815 XEXP (exp, 0) = check_attr_test (XEXP (exp, 0), is_const, lineno);
00816 XEXP (exp, 1) = check_attr_test (XEXP (exp, 1), is_const, lineno);
00817 break;
00818
00819 case NOT:
00820 XEXP (exp, 0) = check_attr_test (XEXP (exp, 0), is_const, lineno);
00821 break;
00822
00823 case MATCH_OPERAND:
00824 if (is_const)
00825 fatal ("RTL operator \"%s\" not valid in constant attribute test",
00826 GET_RTX_NAME (GET_CODE (exp)));
00827
00828 ATTR_IND_SIMPLIFIED_P (exp) = 1;
00829 break;
00830
00831 case LE: case LT: case GT: case GE:
00832 case LEU: case LTU: case GTU: case GEU:
00833 case NE: case EQ:
00834 if (GET_CODE (XEXP (exp, 0)) == SYMBOL_REF
00835 && GET_CODE (XEXP (exp, 1)) == SYMBOL_REF)
00836 exp = attr_rtx (GET_CODE (exp),
00837 attr_rtx (SYMBOL_REF, XSTR (XEXP (exp, 0), 0)),
00838 attr_rtx (SYMBOL_REF, XSTR (XEXP (exp, 1), 0)));
00839
00840 ATTR_IND_SIMPLIFIED_P (exp) = 1;
00841 break;
00842
00843 case SYMBOL_REF:
00844 if (is_const)
00845 {
00846
00847
00848 exp = attr_rtx (SYMBOL_REF, XSTR (exp, 0));
00849 ATTR_IND_SIMPLIFIED_P (exp) = 1;
00850 break;
00851 }
00852 default:
00853 fatal ("RTL operator \"%s\" not valid in attribute test",
00854 GET_RTX_NAME (GET_CODE (exp)));
00855 }
00856
00857 return exp;
00858 }
00859
00860
00861
00862
00863
00864
00865
00866 static rtx
00867 check_attr_value (rtx exp, struct attr_desc *attr)
00868 {
00869 struct attr_value *av;
00870 const char *p;
00871 int i;
00872
00873 switch (GET_CODE (exp))
00874 {
00875 case CONST_INT:
00876 if (attr && ! attr->is_numeric)
00877 {
00878 message_with_line (attr->lineno,
00879 "CONST_INT not valid for non-numeric attribute %s",
00880 attr->name);
00881 have_error = 1;
00882 break;
00883 }
00884
00885 if (INTVAL (exp) < 0)
00886 {
00887 message_with_line (attr->lineno,
00888 "negative numeric value specified for attribute %s",
00889 attr->name);
00890 have_error = 1;
00891 break;
00892 }
00893 break;
00894
00895 case CONST_STRING:
00896 if (! strcmp (XSTR (exp, 0), "*"))
00897 break;
00898
00899 if (attr == 0 || attr->is_numeric)
00900 {
00901 p = XSTR (exp, 0);
00902 for (; *p; p++)
00903 if (! ISDIGIT (*p))
00904 {
00905 message_with_line (attr ? attr->lineno : 0,
00906 "non-numeric value for numeric attribute %s",
00907 attr ? attr->name : "internal");
00908 have_error = 1;
00909 break;
00910 }
00911 break;
00912 }
00913
00914 for (av = attr->first_value; av; av = av->next)
00915 if (GET_CODE (av->value) == CONST_STRING
00916 && ! strcmp (XSTR (av->value, 0), XSTR (exp, 0)))
00917 break;
00918
00919 if (av == NULL)
00920 {
00921 message_with_line (attr->lineno,
00922 "unknown value `%s' for `%s' attribute",
00923 XSTR (exp, 0), attr ? attr->name : "internal");
00924 have_error = 1;
00925 }
00926 break;
00927
00928 case IF_THEN_ELSE:
00929 XEXP (exp, 0) = check_attr_test (XEXP (exp, 0),
00930 attr ? attr->is_const : 0,
00931 attr ? attr->lineno : 0);
00932 XEXP (exp, 1) = check_attr_value (XEXP (exp, 1), attr);
00933 XEXP (exp, 2) = check_attr_value (XEXP (exp, 2), attr);
00934 break;
00935
00936 case PLUS:
00937 case MINUS:
00938 case MULT:
00939 case DIV:
00940 case MOD:
00941 if (attr && !attr->is_numeric)
00942 {
00943 message_with_line (attr->lineno,
00944 "invalid operation `%s' for non-numeric attribute value",
00945 GET_RTX_NAME (GET_CODE (exp)));
00946 have_error = 1;
00947 break;
00948 }
00949
00950
00951 case IOR:
00952 case AND:
00953 XEXP (exp, 0) = check_attr_value (XEXP (exp, 0), attr);
00954 XEXP (exp, 1) = check_attr_value (XEXP (exp, 1), attr);
00955 break;
00956
00957 case FFS:
00958 case CLZ:
00959 case CTZ:
00960 case POPCOUNT:
00961 case PARITY:
00962 XEXP (exp, 0) = check_attr_value (XEXP (exp, 0), attr);
00963 break;
00964
00965 case COND:
00966 if (XVECLEN (exp, 0) % 2 != 0)
00967 {
00968 message_with_line (attr->lineno,
00969 "first operand of COND must have even length");
00970 have_error = 1;
00971 break;
00972 }
00973
00974 for (i = 0; i < XVECLEN (exp, 0); i += 2)
00975 {
00976 XVECEXP (exp, 0, i) = check_attr_test (XVECEXP (exp, 0, i),
00977 attr ? attr->is_const : 0,
00978 attr ? attr->lineno : 0);
00979 XVECEXP (exp, 0, i + 1)
00980 = check_attr_value (XVECEXP (exp, 0, i + 1), attr);
00981 }
00982
00983 XEXP (exp, 1) = check_attr_value (XEXP (exp, 1), attr);
00984 break;
00985
00986 case ATTR:
00987 {
00988 struct attr_desc *attr2 = find_attr (&XSTR (exp, 0), 0);
00989 if (attr2 == NULL)
00990 {
00991 message_with_line (attr ? attr->lineno : 0,
00992 "unknown attribute `%s' in ATTR",
00993 XSTR (exp, 0));
00994 have_error = 1;
00995 }
00996 else if (attr && attr->is_const && ! attr2->is_const)
00997 {
00998 message_with_line (attr->lineno,
00999 "non-constant attribute `%s' referenced from `%s'",
01000 XSTR (exp, 0), attr->name);
01001 have_error = 1;
01002 }
01003 else if (attr
01004 && attr->is_numeric != attr2->is_numeric)
01005 {
01006 message_with_line (attr->lineno,
01007 "numeric attribute mismatch calling `%s' from `%s'",
01008 XSTR (exp, 0), attr->name);
01009 have_error = 1;
01010 }
01011 }
01012 break;
01013
01014 case SYMBOL_REF:
01015
01016
01017
01018 return attr_rtx (SYMBOL_REF, XSTR (exp, 0));
01019
01020 default:
01021 message_with_line (attr ? attr->lineno : 0,
01022 "invalid operation `%s' for attribute value",
01023 GET_RTX_NAME (GET_CODE (exp)));
01024 have_error = 1;
01025 break;
01026 }
01027
01028 return exp;
01029 }
01030
01031
01032
01033
01034 static rtx
01035 convert_set_attr_alternative (rtx exp, struct insn_def *id)
01036 {
01037 int num_alt = id->num_alternatives;
01038 rtx condexp;
01039 int i;
01040
01041 if (XVECLEN (exp, 1) != num_alt)
01042 {
01043 message_with_line (id->lineno,
01044 "bad number of entries in SET_ATTR_ALTERNATIVE");
01045 have_error = 1;
01046 return NULL_RTX;
01047 }
01048
01049
01050
01051 condexp = rtx_alloc (COND);
01052 XVEC (condexp, 0) = rtvec_alloc ((num_alt - 1) * 2);
01053
01054 for (i = 0; i < num_alt - 1; i++)
01055 {
01056 const char *p;
01057 p = attr_numeral (i);
01058
01059 XVECEXP (condexp, 0, 2 * i) = attr_eq (alternative_name, p);
01060 XVECEXP (condexp, 0, 2 * i + 1) = XVECEXP (exp, 1, i);
01061 }
01062
01063 XEXP (condexp, 1) = XVECEXP (exp, 1, i);
01064
01065 return attr_rtx (SET, attr_rtx (ATTR, XSTR (exp, 0)), condexp);
01066 }
01067
01068
01069
01070
01071 static rtx
01072 convert_set_attr (rtx exp, struct insn_def *id)
01073 {
01074 rtx newexp;
01075 const char *name_ptr;
01076 char *p;
01077 int n;
01078
01079
01080 n = n_comma_elts (XSTR (exp, 1));
01081 if (n == 1)
01082 return attr_rtx (SET,
01083 attr_rtx (ATTR, XSTR (exp, 0)),
01084 attr_rtx (CONST_STRING, XSTR (exp, 1)));
01085
01086 newexp = rtx_alloc (SET_ATTR_ALTERNATIVE);
01087 XSTR (newexp, 0) = XSTR (exp, 0);
01088 XVEC (newexp, 1) = rtvec_alloc (n);
01089
01090
01091 name_ptr = XSTR (exp, 1);
01092 n = 0;
01093 while ((p = next_comma_elt (&name_ptr)) != NULL)
01094 XVECEXP (newexp, 1, n++) = attr_rtx (CONST_STRING, p);
01095
01096 return convert_set_attr_alternative (newexp, id);
01097 }
01098
01099
01100
01101
01102
01103 static void
01104 check_defs (void)
01105 {
01106 struct insn_def *id;
01107 struct attr_desc *attr;
01108 int i;
01109 rtx value;
01110
01111 for (id = defs; id; id = id->next)
01112 {
01113 if (XVEC (id->def, id->vec_idx) == NULL)
01114 continue;
01115
01116 for (i = 0; i < XVECLEN (id->def, id->vec_idx); i++)
01117 {
01118 value = XVECEXP (id->def, id->vec_idx, i);
01119 switch (GET_CODE (value))
01120 {
01121 case SET:
01122 if (GET_CODE (XEXP (value, 0)) != ATTR)
01123 {
01124 message_with_line (id->lineno, "bad attribute set");
01125 have_error = 1;
01126 value = NULL_RTX;
01127 }
01128 break;
01129
01130 case SET_ATTR_ALTERNATIVE:
01131 value = convert_set_attr_alternative (value, id);
01132 break;
01133
01134 case SET_ATTR:
01135 value = convert_set_attr (value, id);
01136 break;
01137
01138 default:
01139 message_with_line (id->lineno, "invalid attribute code %s",
01140 GET_RTX_NAME (GET_CODE (value)));
01141 have_error = 1;
01142 value = NULL_RTX;
01143 }
01144 if (value == NULL_RTX)
01145 continue;
01146
01147 if ((attr = find_attr (&XSTR (XEXP (value, 0), 0), 0)) == NULL)
01148 {
01149 message_with_line (id->lineno, "unknown attribute %s",
01150 XSTR (XEXP (value, 0), 0));
01151 have_error = 1;
01152 continue;
01153 }
01154
01155 XVECEXP (id->def, id->vec_idx, i) = value;
01156 XEXP (value, 1) = check_attr_value (XEXP (value, 1), attr);
01157 }
01158 }
01159 }
01160
01161
01162
01163
01164
01165
01166 static rtx
01167 make_canonical (struct attr_desc *attr, rtx exp)
01168 {
01169 int i;
01170 rtx newexp;
01171
01172 switch (GET_CODE (exp))
01173 {
01174 case CONST_INT:
01175 exp = make_numeric_value (INTVAL (exp));
01176 break;
01177
01178 case CONST_STRING:
01179 if (! strcmp (XSTR (exp, 0), "*"))
01180 {
01181 if (attr == 0 || attr->default_val == 0)
01182 fatal ("(attr_value \"*\") used in invalid context");
01183 exp = attr->default_val->value;
01184 }
01185 else
01186 XSTR (exp, 0) = DEF_ATTR_STRING (XSTR (exp, 0));
01187
01188 break;
01189
01190 case SYMBOL_REF:
01191 if (!attr->is_const || ATTR_IND_SIMPLIFIED_P (exp))
01192 break;
01193
01194
01195
01196 ATTR_IND_SIMPLIFIED_P (exp) = 1;
01197 exp = check_attr_value (exp, attr);
01198 break;
01199
01200 case IF_THEN_ELSE:
01201 newexp = rtx_alloc (COND);
01202 XVEC (newexp, 0) = rtvec_alloc (2);
01203 XVECEXP (newexp, 0, 0) = XEXP (exp, 0);
01204 XVECEXP (newexp, 0, 1) = XEXP (exp, 1);
01205
01206 XEXP (newexp, 1) = XEXP (exp, 2);
01207
01208 exp = newexp;
01209
01210
01211 case COND:
01212 {
01213 int allsame = 1;
01214 rtx defval;
01215
01216
01217 if (XVECLEN (exp, 0) == 0)
01218 return make_canonical (attr, XEXP (exp, 1));
01219 defval = XEXP (exp, 1) = make_canonical (attr, XEXP (exp, 1));
01220
01221 for (i = 0; i < XVECLEN (exp, 0); i += 2)
01222 {
01223 XVECEXP (exp, 0, i) = copy_boolean (XVECEXP (exp, 0, i));
01224 XVECEXP (exp, 0, i + 1)
01225 = make_canonical (attr, XVECEXP (exp, 0, i + 1));
01226 if (! rtx_equal_p (XVECEXP (exp, 0, i + 1), defval))
01227 allsame = 0;
01228 }
01229 if (allsame)
01230 return defval;
01231 }
01232 break;
01233
01234 default:
01235 break;
01236 }
01237
01238 return exp;
01239 }
01240
01241 static rtx
01242 copy_boolean (rtx exp)
01243 {
01244 if (GET_CODE (exp) == AND || GET_CODE (exp) == IOR)
01245 return attr_rtx (GET_CODE (exp), copy_boolean (XEXP (exp, 0)),
01246 copy_boolean (XEXP (exp, 1)));
01247 if (GET_CODE (exp) == MATCH_OPERAND)
01248 {
01249 XSTR (exp, 1) = DEF_ATTR_STRING (XSTR (exp, 1));
01250 XSTR (exp, 2) = DEF_ATTR_STRING (XSTR (exp, 2));
01251 }
01252 else if (GET_CODE (exp) == EQ_ATTR)
01253 {
01254 XSTR (exp, 0) = DEF_ATTR_STRING (XSTR (exp, 0));
01255 XSTR (exp, 1) = DEF_ATTR_STRING (XSTR (exp, 1));
01256 }
01257
01258 return exp;
01259 }
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270 static struct attr_value *
01271 get_attr_value (rtx value, struct attr_desc *attr, int insn_code)
01272 {
01273 struct attr_value *av;
01274 int num_alt = 0;
01275
01276 value = make_canonical (attr, value);
01277 if (compares_alternatives_p (value))
01278 {
01279 if (insn_code < 0 || insn_alternatives == NULL)
01280 fatal ("(eq_attr \"alternatives\" ...) used in non-insn context");
01281 else
01282 num_alt = insn_alternatives[insn_code];
01283 }
01284
01285 for (av = attr->first_value; av; av = av->next)
01286 if (rtx_equal_p (value, av->value)
01287 && (num_alt == 0 || av->first_insn == NULL
01288 || insn_alternatives[av->first_insn->def->insn_code]))
01289 return av;
01290
01291 av = oballoc (sizeof (struct attr_value));
01292 av->value = value;
01293 av->next = attr->first_value;
01294 attr->first_value = av;
01295 av->first_insn = NULL;
01296 av->num_insns = 0;
01297 av->has_asm_insn = 0;
01298
01299 return av;
01300 }
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316 static void
01317 expand_delays (void)
01318 {
01319 struct delay_desc *delay;
01320 rtx condexp;
01321 rtx newexp;
01322 int i;
01323 char *p;
01324
01325
01326
01327 condexp = rtx_alloc (COND);
01328 XVEC (condexp, 0) = rtvec_alloc (num_delays * 2);
01329 XEXP (condexp, 1) = make_numeric_value (0);
01330
01331 for (i = 0, delay = delays; delay; i += 2, delay = delay->next)
01332 {
01333 XVECEXP (condexp, 0, i) = XEXP (delay->def, 0);
01334 XVECEXP (condexp, 0, i + 1)
01335 = make_numeric_value (XVECLEN (delay->def, 1) / 3);
01336 }
01337
01338 make_internal_attr (num_delay_slots_str, condexp, ATTR_NONE);
01339
01340
01341 if (num_delays > 1)
01342 {
01343 condexp = rtx_alloc (COND);
01344 XVEC (condexp, 0) = rtvec_alloc (num_delays * 2);
01345 XEXP (condexp, 1) = make_numeric_value (0);
01346
01347 for (i = 0, delay = delays; delay; i += 2, delay = delay->next)
01348 {
01349 XVECEXP (condexp, 0, i) = XEXP (delay->def, 0);
01350 XVECEXP (condexp, 0, i + 1) = make_numeric_value (delay->num);
01351 }
01352
01353 make_internal_attr (delay_type_str, condexp, ATTR_SPECIAL);
01354 }
01355
01356
01357
01358
01359 for (delay = delays; delay; delay = delay->next)
01360 {
01361 for (i = 0; i < XVECLEN (delay->def, 1); i += 3)
01362 {
01363 condexp = XVECEXP (delay->def, 1, i);
01364 if (condexp == 0)
01365 condexp = false_rtx;
01366 newexp = attr_rtx (IF_THEN_ELSE, condexp,
01367 make_numeric_value (1), make_numeric_value (0));
01368
01369 p = attr_printf (sizeof "*delay__" + MAX_DIGITS * 2,
01370 "*delay_%d_%d", delay->num, i / 3);
01371 make_internal_attr (p, newexp, ATTR_SPECIAL);
01372
01373 if (have_annul_true)
01374 {
01375 condexp = XVECEXP (delay->def, 1, i + 1);
01376 if (condexp == 0) condexp = false_rtx;
01377 newexp = attr_rtx (IF_THEN_ELSE, condexp,
01378 make_numeric_value (1),
01379 make_numeric_value (0));
01380 p = attr_printf (sizeof "*annul_true__" + MAX_DIGITS * 2,
01381 "*annul_true_%d_%d", delay->num, i / 3);
01382 make_internal_attr (p, newexp, ATTR_SPECIAL);
01383 }
01384
01385 if (have_annul_false)
01386 {
01387 condexp = XVECEXP (delay->def, 1, i + 2);
01388 if (condexp == 0) condexp = false_rtx;
01389 newexp = attr_rtx (IF_THEN_ELSE, condexp,
01390 make_numeric_value (1),
01391 make_numeric_value (0));
01392 p = attr_printf (sizeof "*annul_false__" + MAX_DIGITS * 2,
01393 "*annul_false_%d_%d", delay->num, i / 3);
01394 make_internal_attr (p, newexp, ATTR_SPECIAL);
01395 }
01396 }
01397 }
01398 }
01399
01400
01401
01402
01403
01404 static void
01405 fill_attr (struct attr_desc *attr)
01406 {
01407 struct attr_value *av;
01408 struct insn_ent *ie;
01409 struct insn_def *id;
01410 int i;
01411 rtx value;
01412
01413
01414
01415 if (attr->is_const)
01416 return;
01417
01418 for (id = defs; id; id = id->next)
01419 {
01420
01421
01422 value = NULL;
01423 if (XVEC (id->def, id->vec_idx))
01424 for (i = 0; i < XVECLEN (id->def, id->vec_idx); i++)
01425 if (! strcmp_check (XSTR (XEXP (XVECEXP (id->def, id->vec_idx, i), 0), 0),
01426 attr->name))
01427 value = XEXP (XVECEXP (id->def, id->vec_idx, i), 1);
01428
01429 if (value == NULL)
01430 av = attr->default_val;
01431 else
01432 av = get_attr_value (value, attr, id->insn_code);
01433
01434 ie = oballoc (sizeof (struct insn_ent));
01435 ie->def = id;
01436 insert_insn_ent (av, ie);
01437 }
01438 }
01439
01440
01441
01442
01443
01444
01445
01446
01447 static rtx
01448 substitute_address (rtx exp, rtx (*no_address_fn) (rtx),
01449 rtx (*address_fn) (rtx))
01450 {
01451 int i;
01452 rtx newexp;
01453
01454 if (GET_CODE (exp) == COND)
01455 {
01456
01457 address_used = 0;
01458 for (i = 0; i < XVECLEN (exp, 0); i += 2)
01459 walk_attr_value (XVECEXP (exp, 0, i));
01460
01461 if (address_used)
01462 return (*address_fn) (exp);
01463
01464
01465 newexp = rtx_alloc (COND);
01466 XVEC (newexp, 0) = rtvec_alloc (XVECLEN (exp, 0));
01467 for (i = 0; i < XVECLEN (exp, 0); i += 2)
01468 {
01469 XVECEXP (newexp, 0, i) = XVECEXP (exp, 0, i);
01470 XVECEXP (newexp, 0, i + 1)
01471 = substitute_address (XVECEXP (exp, 0, i + 1),
01472 no_address_fn, address_fn);
01473 }
01474
01475 XEXP (newexp, 1) = substitute_address (XEXP (exp, 1),
01476 no_address_fn, address_fn);
01477
01478 return newexp;
01479 }
01480
01481 else if (GET_CODE (exp) == IF_THEN_ELSE)
01482 {
01483 address_used = 0;
01484 walk_attr_value (XEXP (exp, 0));
01485 if (address_used)
01486 return (*address_fn) (exp);
01487
01488 return attr_rtx (IF_THEN_ELSE,
01489 substitute_address (XEXP (exp, 0),
01490 no_address_fn, address_fn),
01491 substitute_address (XEXP (exp, 1),
01492 no_address_fn, address_fn),
01493 substitute_address (XEXP (exp, 2),
01494 no_address_fn, address_fn));
01495 }
01496
01497 return (*no_address_fn) (exp);
01498 }
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519 static void
01520 make_length_attrs (void)
01521 {
01522 static const char *new_names[] =
01523 {
01524 "*insn_default_length",
01525 "*insn_min_length",
01526 "*insn_variable_length_p",
01527 "*insn_current_length"
01528 };
01529 static rtx (*const no_address_fn[]) (rtx)
01530 = {identity_fn,identity_fn, zero_fn, zero_fn};
01531 static rtx (*const address_fn[]) (rtx)
01532 = {max_fn, min_fn, one_fn, identity_fn};
01533 size_t i;
01534 struct attr_desc *length_attr, *new_attr;
01535 struct attr_value *av, *new_av;
01536 struct insn_ent *ie, *new_ie;
01537
01538
01539
01540 length_attr = find_attr (&length_str, 0);
01541 if (length_attr == 0)
01542 return;
01543
01544 if (! length_attr->is_numeric)
01545 fatal ("length attribute must be numeric");
01546
01547 length_attr->is_const = 0;
01548 length_attr->is_special = 1;
01549
01550
01551 for (i = 0; i < ARRAY_SIZE (new_names); i++)
01552 {
01553 make_internal_attr (new_names[i],
01554 substitute_address (length_attr->default_val->value,
01555 no_address_fn[i], address_fn[i]),
01556 ATTR_NONE);
01557 new_attr = find_attr (&new_names[i], 0);
01558 for (av = length_attr->first_value; av; av = av->next)
01559 for (ie = av->first_insn; ie; ie = ie->next)
01560 {
01561 new_av = get_attr_value (substitute_address (av->value,
01562 no_address_fn[i],
01563 address_fn[i]),
01564 new_attr, ie->def->insn_code);
01565 new_ie = oballoc (sizeof (struct insn_ent));
01566 new_ie->def = ie->def;
01567 insert_insn_ent (new_av, new_ie);
01568 }
01569 }
01570 }
01571
01572
01573
01574 static rtx
01575 identity_fn (rtx exp)
01576 {
01577 return exp;
01578 }
01579
01580 static rtx
01581 zero_fn (rtx exp ATTRIBUTE_UNUSED)
01582 {
01583 return make_numeric_value (0);
01584 }
01585
01586 static rtx
01587 one_fn (rtx exp ATTRIBUTE_UNUSED)
01588 {
01589 return make_numeric_value (1);
01590 }
01591
01592 static rtx
01593 max_fn (rtx exp)
01594 {
01595 int unknown;
01596 return make_numeric_value (max_attr_value (exp, &unknown));
01597 }
01598
01599 static rtx
01600 min_fn (rtx exp)
01601 {
01602 int unknown;
01603 return make_numeric_value (min_attr_value (exp, &unknown));
01604 }
01605
01606 static void
01607 write_length_unit_log (void)
01608 {
01609 struct attr_desc *length_attr = find_attr (&length_str, 0);
01610 struct attr_value *av;
01611 struct insn_ent *ie;
01612 unsigned int length_unit_log, length_or;
01613 int unknown = 0;
01614
01615 if (length_attr == 0)
01616 return;
01617 length_or = or_attr_value (length_attr->default_val->value, &unknown);
01618 for (av = length_attr->first_value; av; av = av->next)
01619 for (ie = av->first_insn; ie; ie = ie->next)
01620 length_or |= or_attr_value (av->value, &unknown);
01621
01622 if (unknown)
01623 length_unit_log = 0;
01624 else
01625 {
01626 length_or = ~length_or;
01627 for (length_unit_log = 0; length_or & 1; length_or >>= 1)
01628 length_unit_log++;
01629 }
01630 printf ("const int length_unit_log = %u;\n", length_unit_log);
01631 }
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641 static rtx
01642 simplify_cond (rtx exp, int insn_code, int insn_index)
01643 {
01644 int i, j;
01645
01646
01647 rtx defval = XEXP (exp, 1);
01648 rtx new_defval = XEXP (exp, 1);
01649 int len = XVECLEN (exp, 0);
01650 rtx *tests = XNEWVEC (rtx, len);
01651 int allsame = 1;
01652 rtx ret;
01653
01654
01655 obstack_finish (rtl_obstack);
01656
01657 memcpy (tests, XVEC (exp, 0)->elem, len * sizeof (rtx));
01658
01659
01660 if (GET_CODE (defval) == COND)
01661 new_defval = simplify_cond (defval, insn_code, insn_index);
01662
01663
01664
01665 for (i = 0; i < len; i += 2)
01666 {
01667 rtx newtest, newval;
01668
01669
01670 newtest = simplify_test_exp_in_temp (tests[i], insn_code, insn_index);
01671 tests[i] = newtest;
01672
01673 newval = tests[i + 1];
01674
01675 if (GET_CODE (newval) == COND)
01676 newval = simplify_cond (newval, insn_code, insn_index);
01677
01678
01679 if (newtest == true_rtx)
01680 {
01681
01682
01683 len = i;
01684 defval = tests[i + 1];
01685 new_defval = newval;
01686 }
01687
01688 else if (newtest == false_rtx)
01689 {
01690
01691 for (j = i; j < len - 2; j++)
01692 tests[j] = tests[j + 2];
01693 i -= 2;
01694 len -= 2;
01695 }
01696
01697 else if (i > 0 && attr_equal_p (newval, tests[i - 1]))
01698 {
01699
01700
01701
01702 tests[i - 2]
01703 = insert_right_side (IOR, tests[i - 2], newtest,
01704 insn_code, insn_index);
01705
01706
01707 for (j = i; j < len - 2; j++)
01708 tests[j] = tests[j + 2];
01709 len -= 2;
01710 i -= 2;
01711 }
01712
01713 else
01714 tests[i + 1] = newval;
01715 }
01716
01717
01718
01719
01720 while (len > 0 && attr_equal_p (tests[len - 1], new_defval))
01721 len -= 2;
01722
01723
01724 if (len != XVECLEN (exp, 0) || new_defval != XEXP (exp, 1))
01725 allsame = 0;
01726 else
01727 for (i = 0; i < len; i++)
01728 if (! attr_equal_p (tests[i], XVECEXP (exp, 0, i)))
01729 {
01730 allsame = 0;
01731 break;
01732 }
01733
01734 if (len == 0)
01735 {
01736 if (GET_CODE (defval) == COND)
01737 ret = simplify_cond (defval, insn_code, insn_index);
01738 else
01739 ret = defval;
01740 }
01741 else if (allsame)
01742 ret = exp;
01743 else
01744 {
01745 rtx newexp = rtx_alloc (COND);
01746
01747 XVEC (newexp, 0) = rtvec_alloc (len);
01748 memcpy (XVEC (newexp, 0)->elem, tests, len * sizeof (rtx));
01749 XEXP (newexp, 1) = new_defval;
01750 ret = newexp;
01751 }
01752 free (tests);
01753 return ret;
01754 }
01755
01756
01757
01758 static void
01759 remove_insn_ent (struct attr_value *av, struct insn_ent *ie)
01760 {
01761 struct insn_ent *previe;
01762
01763 if (av->first_insn == ie)
01764 av->first_insn = ie->next;
01765 else
01766 {
01767 for (previe = av->first_insn; previe->next != ie; previe = previe->next)
01768 ;
01769 previe->next = ie->next;
01770 }
01771
01772 av->num_insns--;
01773 if (ie->def->insn_code == -1)
01774 av->has_asm_insn = 0;
01775
01776 num_insn_ents--;
01777 }
01778
01779
01780
01781 static void
01782 insert_insn_ent (struct attr_value *av, struct insn_ent *ie)
01783 {
01784 ie->next = av->first_insn;
01785 av->first_insn = ie;
01786 av->num_insns++;
01787 if (ie->def->insn_code == -1)
01788 av->has_asm_insn = 1;
01789
01790 num_insn_ents++;
01791 }
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802 static rtx
01803 insert_right_side (enum rtx_code code, rtx exp, rtx term, int insn_code, int insn_index)
01804 {
01805 rtx newexp;
01806
01807
01808 if (code == AND && term == true_rtx)
01809 return exp;
01810 if (code == AND && term == false_rtx)
01811 return false_rtx;
01812 if (code == AND && exp == true_rtx)
01813 return term;
01814 if (code == AND && exp == false_rtx)
01815 return false_rtx;
01816 if (code == IOR && term == true_rtx)
01817 return true_rtx;
01818 if (code == IOR && term == false_rtx)
01819 return exp;
01820 if (code == IOR && exp == true_rtx)
01821 return true_rtx;
01822 if (code == IOR && exp == false_rtx)
01823 return term;
01824 if (attr_equal_p (exp, term))
01825 return exp;
01826
01827 if (GET_CODE (term) == code)
01828 {
01829 exp = insert_right_side (code, exp, XEXP (term, 0),
01830 insn_code, insn_index);
01831 exp = insert_right_side (code, exp, XEXP (term, 1),
01832 insn_code, insn_index);
01833
01834 return exp;
01835 }
01836
01837 if (GET_CODE (exp) == code)
01838 {
01839 rtx new = insert_right_side (code, XEXP (exp, 1),
01840 term, insn_code, insn_index);
01841 if (new != XEXP (exp, 1))
01842
01843 newexp = attr_rtx (code, XEXP (exp, 0), new);
01844 else
01845 newexp = exp;
01846 }
01847 else
01848 {
01849
01850 newexp = attr_rtx (code, exp, term);
01851 }
01852
01853 return simplify_test_exp_in_temp (newexp, insn_code, insn_index);
01854 }
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864 static int
01865 compute_alternative_mask (rtx exp, enum rtx_code code)
01866 {
01867 const char *string;
01868 if (GET_CODE (exp) == code)
01869 return compute_alternative_mask (XEXP (exp, 0), code)
01870 | compute_alternative_mask (XEXP (exp, 1), code);
01871
01872 else if (code == AND && GET_CODE (exp) == NOT
01873 && GET_CODE (XEXP (exp, 0)) == EQ_ATTR
01874 && XSTR (XEXP (exp, 0), 0) == alternative_name)
01875 string = XSTR (XEXP (exp, 0), 1);
01876
01877 else if (code == IOR && GET_CODE (exp) == EQ_ATTR
01878 && XSTR (exp, 0) == alternative_name)
01879 string = XSTR (exp, 1);
01880
01881 else if (GET_CODE (exp) == EQ_ATTR_ALT)
01882 {
01883 if (code == AND && XINT (exp, 1))
01884 return XINT (exp, 0);
01885
01886 if (code == IOR && !XINT (exp, 1))
01887 return XINT (exp, 0);
01888
01889 return 0;
01890 }
01891 else
01892 return 0;
01893
01894 if (string[1] == 0)
01895 return 1 << (string[0] - '0');
01896 return 1 << atoi (string);
01897 }
01898
01899
01900
01901
01902 static rtx
01903 make_alternative_compare (int mask)
01904 {
01905 return mk_attr_alt (mask);
01906 }
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917 static rtx
01918 evaluate_eq_attr (rtx exp, rtx value, int insn_code, int insn_index)
01919 {
01920 rtx orexp, andexp;
01921 rtx right;
01922 rtx newexp;
01923 int i;
01924
01925 switch (GET_CODE (value))
01926 {
01927 case CONST_STRING:
01928 if (! strcmp_check (XSTR (value, 0), XSTR (exp, 1)))
01929 newexp = true_rtx;
01930 else
01931 newexp = false_rtx;
01932 break;
01933
01934 case SYMBOL_REF:
01935 {
01936 char *p;
01937 char string[256];
01938
01939 gcc_assert (GET_CODE (exp) == EQ_ATTR);
01940 gcc_assert (strlen (XSTR (exp, 0)) + strlen (XSTR (exp, 1)) + 2
01941 <= 256);
01942
01943 strcpy (string, XSTR (exp, 0));
01944 strcat (string, "_");
01945 strcat (string, XSTR (exp, 1));
01946 for (p = string; *p; p++)
01947 *p = TOUPPER (*p);
01948
01949 newexp = attr_rtx (EQ, value,
01950 attr_rtx (SYMBOL_REF,
01951 DEF_ATTR_STRING (string)));
01952 break;
01953 }
01954
01955 case COND:
01956
01957
01958
01959
01960
01961
01962
01963
01964
01965
01966
01967
01968 orexp = false_rtx;
01969 andexp = true_rtx;
01970
01971 for (i = 0; i < XVECLEN (value, 0); i += 2)
01972 {
01973 rtx this = simplify_test_exp_in_temp (XVECEXP (value, 0, i),
01974 insn_code, insn_index);
01975
01976 right = insert_right_side (AND, andexp, this,
01977 insn_code, insn_index);
01978 right = insert_right_side (AND, right,
01979 evaluate_eq_attr (exp,
01980 XVECEXP (value, 0,
01981 i + 1),
01982 insn_code, insn_index),
01983 insn_code, insn_index);
01984 orexp = insert_right_side (IOR, orexp, right,
01985 insn_code, insn_index);
01986
01987
01988 newexp = attr_rtx (NOT, this);
01989 andexp = insert_right_side (AND, andexp, newexp,
01990 insn_code, insn_index);
01991 }
01992
01993
01994 right = insert_right_side (AND, andexp,
01995 evaluate_eq_attr (exp, XEXP (value, 1),
01996 insn_code, insn_index),
01997 insn_code, insn_index);
01998 newexp = insert_right_side (IOR, orexp, right, insn_code, insn_index);
01999 break;
02000
02001 default:
02002 gcc_unreachable ();
02003 }
02004
02005
02006
02007
02008 address_used = 0;
02009 walk_attr_value (newexp);
02010
02011 if (address_used)
02012 {
02013 if (! ATTR_IND_SIMPLIFIED_P (exp))
02014 return copy_rtx_unchanging (exp);
02015 return exp;
02016 }
02017 else
02018 return newexp;
02019 }
02020
02021
02022
02023
02024
02025
02026
02027
02028
02029
02030
02031
02032
02033
02034
02035 static rtx
02036 simplify_and_tree (rtx exp, rtx *pterm, int insn_code, int insn_index)
02037 {
02038 rtx left, right;
02039 rtx newexp;
02040 rtx temp;
02041 int left_eliminates_term, right_eliminates_term;
02042
02043 if (GET_CODE (exp) == AND)
02044 {
02045 left = simplify_and_tree (XEXP (exp, 0), pterm, insn_code, insn_index);
02046 right = simplify_and_tree (XEXP (exp, 1), pterm, insn_code, insn_index);
02047 if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
02048 {
02049 newexp = attr_rtx (AND, left, right);
02050
02051 exp = simplify_test_exp_in_temp (newexp, insn_code, insn_index);
02052 }
02053 }
02054
02055 else if (GET_CODE (exp) == IOR)
02056 {
02057
02058
02059 temp = *pterm;
02060 left = simplify_and_tree (XEXP (exp, 0), &temp, insn_code, insn_index);
02061 left_eliminates_term = (temp == true_rtx);
02062
02063 temp = *pterm;
02064 right = simplify_and_tree (XEXP (exp, 1), &temp, insn_code, insn_index);
02065 right_eliminates_term = (temp == true_rtx);
02066
02067 if (left_eliminates_term && right_eliminates_term)
02068 *pterm = true_rtx;
02069
02070 if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
02071 {
02072 newexp = attr_rtx (IOR, left, right);
02073
02074 exp = simplify_test_exp_in_temp (newexp, insn_code, insn_index);
02075 }
02076 }
02077
02078
02079
02080
02081 if (exp == *pterm)
02082 return true_rtx;
02083
02084 else if (GET_CODE (exp) == NOT && XEXP (exp, 0) == *pterm)
02085 return false_rtx;
02086
02087 else if (GET_CODE (*pterm) == NOT && exp == XEXP (*pterm, 0))
02088 return false_rtx;
02089
02090 else if (GET_CODE (exp) == EQ_ATTR_ALT && GET_CODE (*pterm) == EQ_ATTR_ALT)
02091 {
02092 if (attr_alt_subset_p (*pterm, exp))
02093 return true_rtx;
02094
02095 if (attr_alt_subset_of_compl_p (*pterm, exp))
02096 return false_rtx;
02097
02098 if (attr_alt_subset_p (exp, *pterm))
02099 *pterm = true_rtx;
02100
02101 return exp;
02102 }
02103
02104 else if (GET_CODE (exp) == EQ_ATTR && GET_CODE (*pterm) == EQ_ATTR)
02105 {
02106 if (XSTR (exp, 0) != XSTR (*pterm, 0))
02107 return exp;
02108
02109 if (! strcmp_check (XSTR (exp, 1), XSTR (*pterm, 1)))
02110 return true_rtx;
02111 else
02112 return false_rtx;
02113 }
02114
02115 else if (GET_CODE (*pterm) == EQ_ATTR && GET_CODE (exp) == NOT
02116 && GET_CODE (XEXP (exp, 0)) == EQ_ATTR)
02117 {
02118 if (XSTR (*pterm, 0) != XSTR (XEXP (exp, 0), 0))
02119 return exp;
02120
02121 if (! strcmp_check (XSTR (*pterm, 1), XSTR (XEXP (exp, 0), 1)))
02122 return false_rtx;
02123 else
02124 return true_rtx;
02125 }
02126
02127 else if (GET_CODE (exp) == EQ_ATTR && GET_CODE (*pterm) == NOT
02128 && GET_CODE (XEXP (*pterm, 0)) == EQ_ATTR)
02129 {
02130 if (XSTR (exp, 0) != XSTR (XEXP (*pterm, 0), 0))
02131 return exp;
02132
02133 if (! strcmp_check (XSTR (exp, 1), XSTR (XEXP (*pterm, 0), 1)))
02134 return false_rtx;
02135 else
02136 *pterm = true_rtx;
02137 }
02138
02139 else if (GET_CODE (exp) == NOT && GET_CODE (*pterm) == NOT)
02140 {
02141 if (attr_equal_p (XEXP (exp, 0), XEXP (*pterm, 0)))
02142 return true_rtx;
02143 }
02144
02145 else if (GET_CODE (exp) == NOT)
02146 {
02147 if (attr_equal_p (XEXP (exp, 0), *pterm))
02148 return false_rtx;
02149 }
02150
02151 else if (GET_CODE (*pterm) == NOT)
02152 {
02153 if (attr_equal_p (XEXP (*pterm, 0), exp))
02154 return false_rtx;
02155 }
02156
02157 else if (attr_equal_p (exp, *pterm))
02158 return true_rtx;
02159
02160 return exp;
02161 }
02162
02163
02164
02165 static rtx
02166 simplify_or_tree (rtx exp, rtx *pterm, int insn_code, int insn_index)
02167 {
02168 rtx left, right;
02169 rtx newexp;
02170 rtx temp;
02171 int left_eliminates_term, right_eliminates_term;
02172
02173 if (GET_CODE (exp) == IOR)
02174 {
02175 left = simplify_or_tree (XEXP (exp, 0), pterm, insn_code, insn_index);
02176 right = simplify_or_tree (XEXP (exp, 1), pterm, insn_code, insn_index);
02177 if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
02178 {
02179 newexp = attr_rtx (GET_CODE (exp), left, right);
02180
02181 exp = simplify_test_exp_in_temp (newexp, insn_code, insn_index);
02182 }
02183 }
02184
02185 else if (GET_CODE (exp) == AND)
02186 {
02187
02188
02189 temp = *pterm;
02190 left = simplify_or_tree (XEXP (exp, 0), &temp, insn_code, insn_index);
02191 left_eliminates_term = (temp == false_rtx);
02192
02193 temp = *pterm;
02194 right = simplify_or_tree (XEXP (exp, 1), &temp, insn_code, insn_index);
02195 right_eliminates_term = (temp == false_rtx);
02196
02197 if (left_eliminates_term && right_eliminates_term)
02198 *pterm = false_rtx;
02199
02200 if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
02201 {
02202 newexp = attr_rtx (GET_CODE (exp), left, right);
02203
02204 exp = simplify_test_exp_in_temp (newexp, insn_code, insn_index);
02205 }
02206 }
02207
02208 if (attr_equal_p (exp, *pterm))
02209 return false_rtx;
02210
02211 else if (GET_CODE (exp) == NOT && attr_equal_p (XEXP (exp, 0), *pterm))
02212 return true_rtx;
02213
02214 else if (GET_CODE (*pterm) == NOT && attr_equal_p (XEXP (*pterm, 0), exp))
02215 return true_rtx;
02216
02217 else if (GET_CODE (*pterm) == EQ_ATTR && GET_CODE (exp) == NOT
02218 && GET_CODE (XEXP (exp, 0)) == EQ_ATTR
02219 && XSTR (*pterm, 0) == XSTR (XEXP (exp, 0), 0))
02220 *pterm = false_rtx;
02221
02222 else if (GET_CODE (exp) == EQ_ATTR && GET_CODE (*pterm) == NOT
02223 && GET_CODE (XEXP (*pterm, 0)) == EQ_ATTR
02224 && XSTR (exp, 0) == XSTR (XEXP (*pterm, 0), 0))
02225 return false_rtx;
02226
02227 return exp;
02228 }
02229
02230
02231
02232 static int
02233 attr_rtx_cost (rtx x)
02234 {
02235 int cost = 0;
02236 enum rtx_code code;
02237 if (!x)
02238 return 0;
02239 code = GET_CODE (x);
02240 switch (code)
02241 {
02242 case MATCH_OPERAND:
02243 if (XSTR (x, 1)[0])
02244 return 10;
02245 else
02246 return 0;
02247
02248 case EQ_ATTR_ALT:
02249 return 0;
02250
02251 case EQ_ATTR:
02252
02253 if (!strcmp_check (XSTR (x, 0), alternative_name))
02254 return 0;
02255 else
02256 return 5;
02257 default:
02258 {
02259 int i, j;
02260 const char *fmt = GET_RTX_FORMAT (code);
02261 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
02262 {
02263 switch (fmt[i])
02264 {
02265 case 'V':
02266 case 'E':
02267 for (j = 0; j < XVECLEN (x, i); j++)
02268 cost += attr_rtx_cost (XVECEXP (x, i, j));
02269 break;
02270 case 'e':
02271 cost += attr_rtx_cost (XEXP (x, i));
02272 break;
02273 }
02274 }
02275 }
02276 break;
02277 }
02278 return cost;
02279 }
02280
02281
02282
02283
02284
02285 static rtx
02286 simplify_test_exp_in_temp (rtx exp, int insn_code, int insn_index)
02287 {
02288 rtx x;
02289 struct obstack *old;
02290 if (ATTR_IND_SIMPLIFIED_P (exp))
02291 return exp;
02292 old = rtl_obstack;
02293 rtl_obstack = temp_obstack;
02294 x = simplify_test_exp (exp, insn_code, insn_index);
02295 rtl_obstack = old;
02296 if (x == exp || rtl_obstack == temp_obstack)
02297 return x;
02298 return attr_copy_rtx (x);
02299 }
02300
02301
02302
02303 static bool
02304 attr_alt_subset_p (rtx s1, rtx s2)
02305 {
02306 switch ((XINT (s1, 1) << 1) | XINT (s2, 1))
02307 {
02308 case (0 << 1) | 0:
02309 return !(XINT (s1, 0) &~ XINT (s2, 0));
02310
02311 case (0 << 1) | 1:
02312 return !(XINT (s1, 0) & XINT (s2, 0));
02313
02314 case (1 << 1) | 0:
02315 return false;
02316
02317 case (1 << 1) | 1:
02318 return !(XINT (s2, 0) &~ XINT (s1, 0));
02319
02320 default:
02321 gcc_unreachable ();
02322 }
02323 }
02324
02325
02326
02327 static bool
02328 attr_alt_subset_of_compl_p (rtx s1, rtx s2)
02329 {
02330 switch ((XINT (s1, 1) << 1) | XINT (s2, 1))
02331 {
02332 case (0 << 1) | 0:
02333 return !(XINT (s1, 0) & XINT (s2, 0));
02334
02335 case (0 << 1) | 1:
02336 return !(XINT (s1, 0) & ~XINT (s2, 0));
02337
02338 case (1 << 1) | 0:
02339 return !(XINT (s2, 0) &~ XINT (s1, 0));
02340
02341 case (1 << 1) | 1:
02342 return false;
02343
02344 default:
02345 gcc_unreachable ();
02346 }
02347 }
02348
02349
02350
02351 static rtx
02352 attr_alt_intersection (rtx s1, rtx s2)
02353 {
02354 rtx result = rtx_alloc (EQ_ATTR_ALT);
02355
02356 switch ((XINT (s1, 1) << 1) | XINT (s2, 1))
02357 {
02358 case (0 << 1) | 0:
02359 XINT (result, 0) = XINT (s1, 0) & XINT (s2, 0);
02360 break;
02361 case (0 << 1) | 1:
02362 XINT (result, 0) = XINT (s1, 0) & ~XINT (s2, 0);
02363 break;
02364 case (1 << 1) | 0:
02365 XINT (result, 0) = XINT (s2, 0) & ~XINT (s1, 0);
02366 break;
02367 case (1 << 1) | 1:
02368 XINT (result, 0) = XINT (s1, 0) | XINT (s2, 0);
02369 break;
02370 default:
02371 gcc_unreachable ();
02372 }
02373 XINT (result, 1) = XINT (s1, 1) & XINT (s2, 1);
02374
02375 return result;
02376 }
02377
02378
02379
02380 static rtx
02381 attr_alt_union (rtx s1, rtx s2)
02382 {
02383 rtx result = rtx_alloc (EQ_ATTR_ALT);
02384
02385 switch ((XINT (s1, 1) << 1) | XINT (s2, 1))
02386 {
02387 case (0 << 1) | 0:
02388 XINT (result, 0) = XINT (s1, 0) | XINT (s2, 0);
02389 break;
02390 case (0 << 1) | 1:
02391 XINT (result, 0) = XINT (s2, 0) & ~XINT (s1, 0);
02392 break;
02393 case (1 << 1) | 0:
02394 XINT (result, 0) = XINT (s1, 0) & ~XINT (s2, 0);
02395 break;
02396 case (1 << 1) | 1:
02397 XINT (result, 0) = XINT (s1, 0) & XINT (s2, 0);
02398 break;
02399 default:
02400 gcc_unreachable ();
02401 }
02402
02403 XINT (result, 1) = XINT (s1, 1) | XINT (s2, 1);
02404 return result;
02405 }
02406
02407
02408
02409 static rtx
02410 attr_alt_complement (rtx s)
02411 {
02412 rtx result = rtx_alloc (EQ_ATTR_ALT);
02413
02414 XINT (result, 0) = XINT (s, 0);
02415 XINT (result, 1) = 1 - XINT (s, 1);
02416
02417 return result;
02418 }
02419
02420
02421
02422
02423 static rtx
02424 mk_attr_alt (int e)
02425 {
02426 rtx result = rtx_alloc (EQ_ATTR_ALT);
02427
02428 XINT (result, 0) = e;
02429 XINT (result, 1) = 0;
02430
02431 return result;
02432 }
02433
02434
02435
02436
02437
02438
02439
02440
02441
02442
02443 static rtx
02444 simplify_test_exp (rtx exp, int insn_code, int insn_index)
02445 {
02446 rtx left, right;
02447 struct attr_desc *attr;
02448 struct attr_value *av;
02449 struct insn_ent *ie;
02450 int i;
02451 rtx newexp = exp;
02452 bool left_alt, right_alt;
02453
02454
02455 if (ATTR_IND_SIMPLIFIED_P (exp) || ATTR_CURR_SIMPLIFIED_P (exp))
02456 return exp;
02457
02458 switch (GET_CODE (exp))
02459 {
02460 case AND:
02461 left = SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index);
02462 if (left == false_rtx)
02463 return false_rtx;
02464 right = SIMPLIFY_TEST_EXP (XEXP (exp, 1), insn_code, insn_index);
02465 if (right == false_rtx)
02466 return false_rtx;
02467
02468 if (GET_CODE (left) == EQ_ATTR_ALT
02469 && GET_CODE (right) == EQ_ATTR_ALT)
02470 {
02471 exp = attr_alt_intersection (left, right);
02472 return simplify_test_exp (exp, insn_code, insn_index);
02473 }
02474
02475
02476
02477
02478 if ((GET_CODE (left) == IOR || GET_CODE (right) == IOR)
02479 && compute_alternative_mask (left, IOR)
02480 && compute_alternative_mask (right, IOR))
02481 {
02482 if (GET_CODE (left) == IOR)
02483 {
02484 rtx tem = left;
02485 left = right;
02486 right = tem;
02487 }
02488
02489 newexp = attr_rtx (IOR,
02490 attr_rtx (AND, left, XEXP (right, 0)),
02491 attr_rtx (AND, left, XEXP (right, 1)));
02492
02493 return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
02494 }
02495
02496
02497 right = simplify_and_tree (right, &left, insn_code, insn_index);
02498 if (left == XEXP (exp, 0) && right == XEXP (exp, 1))
02499 left = simplify_and_tree (left, &right, insn_code, insn_index);
02500
02501 if (left == false_rtx || right == false_rtx)
02502 return false_rtx;
02503 else if (left == true_rtx)
02504 {
02505 return right;
02506 }
02507 else if (right == true_rtx)
02508 {
02509 return left;
02510 }
02511
02512
02513
02514 if (GET_CODE (left) == NOT)
02515 left_alt = (GET_CODE (XEXP (left, 0)) == EQ_ATTR
02516 && XSTR (XEXP (left, 0), 0) == alternative_name);
02517 else
02518 left_alt = (GET_CODE (left) == EQ_ATTR_ALT
02519 && XINT (left, 1));
02520
02521 if (GET_CODE (right) == NOT)
02522 right_alt = (GET_CODE (XEXP (right, 0)) == EQ_ATTR
02523 && XSTR (XEXP (right, 0), 0) == alternative_name);
02524 else
02525 right_alt = (GET_CODE (right) == EQ_ATTR_ALT
02526 && XINT (right, 1));
02527
02528 if (insn_code >= 0
02529 && (GET_CODE (left) == AND
02530 || left_alt
02531 || GET_CODE (right) == AND
02532 || right_alt))
02533 {
02534 i = compute_alternative_mask (exp, AND);
02535 if (i & ~insn_alternatives[insn_code])
02536 fatal ("invalid alternative specified for pattern number %d",
02537 insn_index);
02538
02539
02540 i ^= insn_alternatives[insn_code];
02541 if (i == 0)
02542 return false_rtx;
02543 else if ((i & (i - 1)) == 0 && insn_alternatives[insn_code] > 1)
02544 {
02545
02546
02547
02548
02549 left = make_alternative_compare (i);
02550 right = simplify_and_tree (exp, &left, insn_code, insn_index);
02551 newexp = attr_rtx (AND, left, right);
02552
02553 return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
02554 }
02555 }
02556
02557 if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
02558 {
02559 newexp = attr_rtx (AND, left, right);
02560 return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
02561 }
02562 break;
02563
02564 case IOR:
02565 left = SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index);
02566 if (left == true_rtx)
02567 return true_rtx;
02568 right = SIMPLIFY_TEST_EXP (XEXP (exp, 1), insn_code, insn_index);
02569 if (right == true_rtx)
02570 return true_rtx;
02571
02572 if (GET_CODE (left) == EQ_ATTR_ALT
02573 && GET_CODE (right) == EQ_ATTR_ALT)
02574 {
02575 exp = attr_alt_union (left, right);
02576 return simplify_test_exp (exp, insn_code, insn_index);
02577 }
02578
02579 right = simplify_or_tree (right, &left, insn_code, insn_index);
02580 if (left == XEXP (exp, 0) && right == XEXP (exp, 1))
02581 left = simplify_or_tree (left, &right, insn_code, insn_index);
02582
02583 if (right == true_rtx || left == true_rtx)
02584 return true_rtx;
02585 else if (left == false_rtx)
02586 {
02587 return right;
02588 }
02589 else if (right == false_rtx)
02590 {
02591 return left;
02592 }
02593
02594
02595
02596
02597
02598
02599
02600
02601 else if (GET_CODE (left) == AND && GET_CODE (right) == AND
02602 && attr_equal_p (XEXP (left, 0), XEXP (right, 0)))
02603 {
02604 newexp = attr_rtx (IOR, XEXP (left, 1), XEXP (right, 1));
02605
02606 left = XEXP (left, 0);
02607 right = newexp;
02608 newexp = attr_rtx (AND, left, right);
02609 return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
02610 }
02611
02612
02613
02614
02615 else if (insn_code >= 0
02616 && (GET_CODE (left) == IOR
02617 || (GET_CODE (left) == EQ_ATTR_ALT
02618 && !XINT (left, 1))
02619 || (GET_CODE (left) == EQ_ATTR
02620 && XSTR (left, 0) == alternative_name)
02621 || GET_CODE (right) == IOR
02622 || (GET_CODE (right) == EQ_ATTR_ALT
02623 && !XINT (right, 1))
02624 || (GET_CODE (right) == EQ_ATTR
02625 && XSTR (right, 0) == alternative_name)))
02626 {
02627 i = compute_alternative_mask (exp, IOR);
02628 if (i & ~insn_alternatives[insn_code])
02629 fatal ("invalid alternative specified for pattern number %d",
02630 insn_index);
02631
02632
02633 i ^= insn_alternatives[insn_code];
02634 if (i == 0)
02635 return true_rtx;
02636 else if ((i & (i - 1)) == 0 && insn_alternatives[insn_code] > 1)
02637 {
02638
02639
02640
02641
02642 left = make_alternative_compare (i);
02643 right = simplify_and_tree (exp, &left, insn_code, insn_index);
02644 newexp = attr_rtx (IOR, attr_rtx (NOT, left), right);
02645
02646 return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
02647 }
02648 }
02649
02650 if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
02651 {
02652 newexp = attr_rtx (IOR, left, right);
02653 return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
02654 }
02655 break;
02656
02657 case NOT:
02658 if (GET_CODE (XEXP (exp, 0)) == NOT)
02659 {
02660 left = SIMPLIFY_TEST_EXP (XEXP (XEXP (exp, 0), 0),
02661 insn_code, insn_index);
02662 return left;
02663 }
02664
02665 left = SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index);
02666 if (GET_CODE (left) == NOT)
02667 return XEXP (left, 0);
02668
02669 if (left == false_rtx)
02670 return true_rtx;
02671 if (left == true_rtx)
02672 return false_rtx;
02673
02674 if (GET_CODE (left) == EQ_ATTR_ALT)
02675 {
02676 exp = attr_alt_complement (left);
02677 return simplify_test_exp (exp, insn_code, insn_index);
02678 }
02679
02680
02681 if (GET_CODE (left) == IOR)
02682 {
02683 newexp = attr_rtx (AND,
02684 attr_rtx (NOT, XEXP (left, 0)),
02685 attr_rtx (NOT, XEXP (left, 1)));
02686
02687 newexp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
02688 }
02689 else if (GET_CODE (left) == AND)
02690 {
02691 newexp = attr_rtx (IOR,
02692 attr_rtx (NOT, XEXP (left, 0)),
02693 attr_rtx (NOT, XEXP (left, 1)));
02694
02695 newexp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
02696 }
02697 else if (left != XEXP (exp, 0))
02698 {
02699 newexp = attr_rtx (NOT, left);
02700 }
02701 break;
02702
02703 case EQ_ATTR_ALT:
02704 if (!XINT (exp, 0))
02705 return XINT (exp, 1) ? true_rtx : false_rtx;
02706 break;
02707
02708 case EQ_ATTR:
02709 if (XSTR (exp, 0) == alternative_name)
02710 {
02711 newexp = mk_attr_alt (1 << atoi (XSTR (exp, 1)));
02712 break;
02713 }
02714
02715
02716
02717
02718 if (insn_code >= 0
02719 && (attr = find_attr (&XSTR (exp, 0), 0)) != NULL)
02720 for (av = attr->first_value; av; av = av->next)
02721 for (ie = av->first_insn; ie; ie = ie->next)
02722 if (ie->def->insn_code == insn_code)
02723 {
02724 rtx x;
02725 x = evaluate_eq_attr (exp, av->value, insn_code, insn_index);
02726 x = SIMPLIFY_TEST_EXP (x, insn_code, insn_index);
02727 if (attr_rtx_cost(x) < 20)
02728 return x;
02729 }
02730 break;
02731
02732 default:
02733 break;
02734 }
02735
02736
02737
02738
02739 if (insn_code != -2
02740 && ! ATTR_IND_SIMPLIFIED_P (newexp))
02741 return copy_rtx_unchanging (newexp);
02742
02743 return newexp;
02744 }
02745
02746
02747
02748
02749
02750 static void
02751 optimize_attrs (void)
02752 {
02753 struct attr_desc *attr;
02754 struct attr_value *av;
02755 struct insn_ent *ie;
02756 rtx newexp;
02757 int i;
02758 struct attr_value_list
02759 {
02760 struct attr_value *av;
02761 struct insn_ent *ie;
02762 struct attr_desc *attr;
02763 struct attr_value_list *next;
02764 };
02765 struct attr_value_list **insn_code_values;
02766 struct attr_value_list *ivbuf;
02767 struct attr_value_list *iv;
02768
02769
02770
02771
02772 if (num_insn_ents == 0)
02773 return;
02774
02775
02776 insn_code_values = XCNEWVEC (struct attr_value_list *, insn_code_number + 2);
02777
02778
02779 insn_code_values += 2;
02780
02781 iv = ivbuf = XNEWVEC (struct attr_value_list, num_insn_ents);
02782
02783 for (i = 0; i < MAX_ATTRS_INDEX; i++)
02784 for (attr = attrs[i]; attr; attr = attr->next)
02785 for (av = attr->first_value; av; av = av->next)
02786 for (ie = av->first_insn; ie; ie = ie->next)
02787 {
02788 iv->attr = attr;
02789 iv->av = av;
02790 iv->ie = ie;
02791 iv->next = insn_code_values[ie->def->insn_code];
02792 insn_code_values[ie->def->insn_code] = iv;
02793 iv++;
02794 }
02795
02796
02797 gcc_assert (iv == ivbuf + num_insn_ents);
02798
02799
02800 for (i = -2; i < insn_code_number; i++)
02801 {
02802
02803
02804 for (iv = insn_code_values[i]; iv; iv = iv->next)
02805 clear_struct_flag (iv->av->value);
02806
02807 for (iv = insn_code_values[i]; iv; iv = iv->next)
02808 {
02809 struct obstack *old = rtl_obstack;
02810
02811 attr = iv->attr;
02812 av = iv->av;
02813 ie = iv->ie;
02814 if (GET_CODE (av->value) != COND)
02815 continue;
02816
02817 rtl_obstack = temp_obstack;
02818 newexp = av->value;
02819 while (GET_CODE (newexp) == COND)
02820 {
02821 rtx newexp2 = simplify_cond (newexp, ie->def->insn_code,
02822 ie->def->insn_index);
02823 if (newexp2 == newexp)
02824 break;
02825 newexp = newexp2;
02826 }
02827
02828 rtl_obstack = old;
02829 if (newexp != av->value)
02830 {
02831 newexp = attr_copy_rtx (newexp);
02832 remove_insn_ent (av, ie);
02833 av = get_attr_value (newexp, attr, ie->def->insn_code);
02834 iv->av = av;
02835 insert_insn_ent (av, ie);
02836 }
02837 }
02838 }
02839
02840 free (ivbuf);
02841 free (insn_code_values - 2);
02842 }
02843
02844
02845
02846 static void
02847 clear_struct_flag (rtx x)
02848 {
02849 int i;
02850 int j;
02851 enum rtx_code code;
02852 const char *fmt;
02853
02854 ATTR_CURR_SIMPLIFIED_P (x) = 0;
02855 if (ATTR_IND_SIMPLIFIED_P (x))
02856 return;
02857
02858 code = GET_CODE (x);
02859
02860 switch (code)
02861 {
02862 case REG:
02863 case CONST_INT:
02864 case CONST_DOUBLE:
02865 case CONST_VECTOR:
02866 case SYMBOL_REF:
02867 case CODE_LABEL:
02868 case PC:
02869 case CC0:
02870 case EQ_ATTR:
02871 case ATTR_FLAG:
02872 return;
02873
02874 default:
02875 break;
02876 }
02877
02878
02879
02880
02881 fmt = GET_RTX_FORMAT (code);
02882 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
02883 {
02884 switch (fmt[i])
02885 {
02886 case 'V':
02887 case 'E':
02888 for (j = 0; j < XVECLEN (x, i); j++)
02889 clear_struct_flag (XVECEXP (x, i, j));
02890 break;
02891
02892 case 'e':
02893 clear_struct_flag (XEXP (x, i));
02894 break;
02895 }
02896 }
02897 }
02898
02899
02900
02901 static void
02902 gen_attr (rtx exp, int lineno)
02903 {
02904 struct attr_desc *attr;
02905 struct attr_value *av;
02906 const char *name_ptr;
02907 char *p;
02908
02909
02910
02911 attr = find_attr (&XSTR (exp, 0), 1);
02912 if (attr->default_val)
02913 {
02914 message_with_line (lineno, "duplicate definition for attribute %s",
02915 attr->name);
02916 message_with_line (attr->lineno, "previous definition");
02917 have_error = 1;
02918 return;
02919 }
02920 attr->lineno = lineno;
02921
02922 if (*XSTR (exp, 1) == '\0')
02923 attr->is_numeric = 1;
02924 else
02925 {
02926 name_ptr = XSTR (exp, 1);
02927 while ((p = next_comma_elt (&name_ptr)) != NULL)
02928 {
02929 av = oballoc (sizeof (struct attr_value));
02930 av->value = attr_rtx (CONST_STRING, p);
02931 av->next = attr->first_value;
02932 attr->first_value = av;
02933 av->first_insn = NULL;
02934 av->num_insns = 0;
02935 av->has_asm_insn = 0;
02936 }
02937 }
02938
02939 if (GET_CODE (XEXP (exp, 2)) == CONST)
02940 {
02941 attr->is_const = 1;
02942 if (attr->is_numeric)
02943 {
02944 message_with_line (lineno,
02945 "constant attributes may not take numeric values");
02946 have_error = 1;
02947 }
02948
02949
02950 XEXP (exp, 2) = XEXP (XEXP (exp, 2), 0);
02951 }
02952
02953 if (! strcmp_check (attr->name, length_str) && ! attr->is_numeric)
02954 {
02955 message_with_line (lineno,
02956 "`length' attribute must take numeric values");
02957 have_error = 1;
02958 }
02959
02960
02961 XEXP (exp, 2) = check_attr_value (XEXP (exp, 2), attr);
02962 attr->default_val = get_attr_value (XEXP (exp, 2), attr, -2);
02963 }
02964
02965
02966
02967
02968
02969 static int
02970 count_alternatives (rtx exp)
02971 {
02972 int i, j, n;
02973 const char *fmt;
02974
02975 if (GET_CODE (exp) == MATCH_OPERAND)
02976 return n_comma_elts (XSTR (exp, 2));
02977
02978 for (i = 0, fmt = GET_RTX_FORMAT (GET_CODE (exp));
02979 i < GET_RTX_LENGTH (GET_CODE (exp)); i++)
02980 switch (*fmt++)
02981 {
02982 case 'e':
02983 case 'u':
02984 n = count_alternatives (XEXP (exp, i));
02985 if (n)
02986 return n;
02987 break;
02988
02989 case 'E':
02990 case 'V':
02991 if (XVEC (exp, i) != NULL)
02992 for (j = 0; j < XVECLEN (exp, i); j++)
02993 {
02994 n = count_alternatives (XVECEXP (exp, i, j));
02995 if (n)
02996 return n;
02997 }
02998 }
02999
03000 return 0;
03001 }
03002
03003
03004
03005
03006 static int
03007 compares_alternatives_p (rtx exp)
03008 {
03009 int i, j;
03010 const char *fmt;
03011
03012 if (GET_CODE (exp) == EQ_ATTR && XSTR (exp, 0) == alternative_name)
03013 return 1;
03014
03015 for (i = 0, fmt = GET_RTX_FORMAT (GET_CODE (exp));
03016 i < GET_RTX_LENGTH (GET_CODE (exp)); i++)
03017 switch (*fmt++)
03018 {
03019 case 'e':
03020 case 'u':
03021 if (compares_alternatives_p (XEXP (exp, i)))
03022 return 1;
03023 break;
03024
03025 case 'E':
03026 for (j = 0; j < XVECLEN (exp, i); j++)
03027 if (compares_alternatives_p (XVECEXP (exp, i, j)))
03028 return 1;
03029 break;
03030 }
03031
03032 return 0;
03033 }
03034
03035
03036
03037 static int
03038 contained_in_p (rtx inner, rtx exp)
03039 {
03040 int i, j;
03041 const char *fmt;
03042
03043 if (rtx_equal_p (inner, exp))
03044 return 1;
03045
03046 for (i = 0, fmt = GET_RTX_FORMAT (GET_CODE (exp));
03047 i < GET_RTX_LENGTH (GET_CODE (exp)); i++)
03048 switch (*fmt++)
03049 {
03050 case 'e':
03051 case 'u':
03052 if (contained_in_p (inner, XEXP (exp, i)))
03053 return 1;
03054 break;
03055
03056 case 'E':
03057 for (j = 0; j < XVECLEN (exp, i); j++)
03058 if (contained_in_p (inner, XVECEXP (exp, i, j)))
03059 return 1;
03060 break;
03061 }
03062
03063 return 0;
03064 }
03065
03066
03067
03068 static void
03069 gen_insn (rtx exp, int lineno)
03070 {
03071 struct insn_def *id;
03072
03073 id = oballoc (sizeof (struct insn_def));
03074 id->next = defs;
03075 defs = id;
03076 id->def = exp;
03077 id->lineno = lineno;
03078
03079 switch (GET_CODE (exp))
03080 {
03081 case DEFINE_INSN:
03082 id->insn_code = insn_code_number;
03083 id->insn_index = insn_index_number;
03084 id->num_alternatives = count_alternatives (exp);
03085 if (id->num_alternatives == 0)
03086 id->num_alternatives = 1;
03087 id->vec_idx = 4;
03088 break;
03089
03090 case DEFINE_PEEPHOLE:
03091 id->insn_code = insn_code_number;
03092 id->insn_index = insn_index_number;
03093 id->num_alternatives = count_alternatives (exp);
03094 if (id->num_alternatives == 0)
03095 id->num_alternatives = 1;
03096 id->vec_idx = 3;
03097 break;
03098
03099 case DEFINE_ASM_ATTRIBUTES:
03100 id->insn_code = -1;
03101 id->insn_index = -1;
03102 id->num_alternatives = 1;
03103 id->vec_idx = 0;
03104 got_define_asm_attributes = 1;
03105 break;
03106
03107 default:
03108 gcc_unreachable ();
03109 }
03110 }
03111
03112
03113
03114
03115 static void
03116 gen_delay (rtx def, int lineno)
03117 {
03118 struct delay_desc *delay;
03119 int i;
03120
03121 if (XVECLEN (def, 1) % 3 != 0)
03122 {
03123 message_with_line (lineno,
03124 "number of elements in DEFINE_DELAY must be multiple of three");
03125 have_error = 1;
03126 return;
03127 }
03128
03129 for (i = 0; i < XVECLEN (def, 1); i += 3)
03130 {
03131 if (XVECEXP (def, 1, i + 1))
03132 have_annul_true = 1;
03133 if (XVECEXP (def, 1, i + 2))
03134 have_annul_false = 1;
03135 }
03136
03137 delay = oballoc (sizeof (struct delay_desc));
03138 delay->def = def;
03139 delay->num = ++num_delays;
03140 delay->next = delays;
03141 delay->lineno = lineno;
03142 delays = delay;
03143 }
03144
03145
03146
03147
03148
03149
03150
03151
03152
03153 static void
03154 write_test_expr (rtx exp, int flags)
03155 {
03156 int comparison_operator = 0;
03157 RTX_CODE code;
03158 struct attr_desc *attr;
03159
03160
03161
03162
03163 printf ("(");
03164 code = GET_CODE (exp);
03165 switch (code)
03166 {
03167
03168 case GEU: case GTU:
03169 case LEU: case LTU:
03170 printf ("(unsigned) ");
03171
03172
03173 case EQ: case NE:
03174 case GE: case GT:
03175 case LE: case LT:
03176 comparison_operator = 1;
03177
03178 case PLUS: case MINUS: case MULT: case DIV: case MOD:
03179 case AND: case IOR: case XOR:
03180 case ASHIFT: case LSHIFTRT: case ASHIFTRT:
03181 write_test_expr (XEXP (exp, 0), flags | comparison_operator);
03182 switch (code)
03183 {
03184 case EQ:
03185 printf (" == ");
03186 break;
03187 case NE:
03188 printf (" != ");
03189 break;
03190 case GE:
03191 printf (" >= ");
03192 break;
03193 case GT:
03194 printf (" > ");
03195 break;
03196 case GEU:
03197 printf (" >= (unsigned) ");
03198 break;
03199 case GTU:
03200 printf (" > (unsigned) ");
03201 break;
03202 case LE:
03203 printf (" <= ");
03204 break;
03205 case LT:
03206 printf (" < ");
03207 break;
03208 case LEU:
03209 printf (" <= (unsigned) ");
03210 break;
03211 case LTU:
03212 printf (" < (unsigned) ");
03213 break;
03214 case PLUS:
03215 printf (" + ");
03216 break;
03217 case MINUS:
03218 printf (" - ");
03219 break;
03220 case MULT:
03221 printf (" * ");
03222 break;
03223 case DIV:
03224 printf (" / ");
03225 break;
03226 case MOD:
03227 printf (" %% ");
03228 break;
03229 case AND:
03230 if (flags & 1)
03231 printf (" & ");
03232 else
03233 printf (" && ");
03234 break;
03235 case IOR:
03236 if (flags & 1)
03237 printf (" | ");
03238 else
03239 printf (" || ");
03240 break;
03241 case XOR:
03242 printf (" ^ ");
03243 break;
03244 case ASHIFT:
03245 printf (" << ");
03246 break;
03247 case LSHIFTRT:
03248 case ASHIFTRT:
03249 printf (" >> ");
03250 break;
03251 default:
03252 gcc_unreachable ();
03253 }
03254
03255 write_test_expr (XEXP (exp, 1), flags | comparison_operator);
03256 break;
03257
03258 case NOT:
03259
03260 if (! (flags & 1) && GET_CODE (XEXP (exp, 0)) == EQ_ATTR
03261 && XSTR (XEXP (exp, 0), 0) == alternative_name)
03262 {
03263 printf ("which_alternative != %s", XSTR (XEXP (exp, 0), 1));
03264 break;
03265 }
03266
03267
03268
03269
03270 case ABS: case NEG:
03271 switch (code)
03272 {
03273 case NOT:
03274 if (flags & 1)
03275 printf ("~ ");
03276 else
03277 printf ("! ");
03278 break;
03279 case ABS:
03280 printf ("abs ");
03281 break;
03282 case NEG:
03283 printf ("-");
03284 break;
03285 default:
03286 gcc_unreachable ();
03287 }
03288
03289 write_test_expr (XEXP (exp, 0), flags);
03290 break;
03291
03292 case EQ_ATTR_ALT:
03293 {
03294 int set = XINT (exp, 0), bit = 0;
03295
03296 if (flags & 1)
03297 fatal ("EQ_ATTR_ALT not valid inside comparison");
03298
03299 if (!set)
03300 fatal ("Empty EQ_ATTR_ALT should be optimized out");
03301
03302 if (!(set & (set - 1)))
03303 {
03304 if (!(set & 0xffff))
03305 {
03306 bit += 16;
03307 set >>= 16;
03308 }
03309 if (!(set & 0xff))
03310 {
03311 bit += 8;
03312 set >>= 8;
03313 }
03314 if (!(set & 0xf))
03315 {
03316 bit += 4;
03317 set >>= 4;
03318 }
03319 if (!(set & 0x3))
03320 {
03321 bit += 2;
03322 set >>= 2;
03323 }
03324 if (!(set & 1))
03325 bit++;
03326
03327 printf ("which_alternative %s= %d",
03328 XINT (exp, 1) ? "!" : "=", bit);
03329 }
03330 else
03331 {
03332 printf ("%s((1 << which_alternative) & 0x%x)",
03333 XINT (exp, 1) ? "!" : "", set);
03334 }
03335 }
03336 break;
03337
03338
03339
03340
03341 case EQ_ATTR:
03342 if (flags & 1)
03343 fatal ("EQ_ATTR not valid inside comparison");
03344
03345 if (XSTR (exp, 0) == alternative_name)
03346 {
03347 printf ("which_alternative == %s", XSTR (exp, 1));
03348 break;
03349 }
03350
03351 attr = find_attr (&XSTR (exp, 0), 0);
03352 gcc_assert (attr);
03353
03354
03355 if (attr->is_const)
03356 {
03357 write_test_expr (evaluate_eq_attr (exp, attr->default_val->value,
03358 -2, -2),
03359 flags);
03360 }
03361 else
03362 {
03363 if (flags & 2)
03364 printf ("attr_%s", attr->name);
03365 else
03366 printf ("get_attr_%s (insn)", attr->name);
03367 printf (" == ");
03368 write_attr_valueq (attr, XSTR (exp, 1));
03369 }
03370 break;
03371
03372
03373 case ATTR_FLAG:
03374 if (flags & 1)
03375 fatal ("ATTR_FLAG not valid inside comparison");
03376 printf ("(flags & ATTR_FLAG_%s) != 0", XSTR (exp, 0));
03377 break;
03378
03379
03380 case MATCH_OPERAND:
03381
03382
03383 if (XSTR (exp, 1) == NULL || *XSTR (exp, 1) == '\0')
03384 {
03385 if (GET_MODE (exp) == VOIDmode)
03386 fatal ("null MATCH_OPERAND specified as test");
03387 else
03388 printf ("GET_MODE (operands[%d]) == %smode",
03389 XINT (exp, 0), GET_MODE_NAME (GET_MODE (exp)));
03390 }
03391 else
03392 printf ("%s (operands[%d], %smode)",
03393 XSTR (exp, 1), XINT (exp, 0), GET_MODE_NAME (GET_MODE (exp)));
03394 break;
03395
03396
03397 case CONST_INT:
03398 printf (HOST_WIDE_INT_PRINT_DEC, XWINT (exp, 0));
03399 break;
03400
03401
03402 case SYMBOL_REF:
03403 print_c_condition (XSTR (exp, 0));
03404 break;
03405
03406
03407 case MATCH_DUP:
03408 printf ("INSN_ADDRESSES_SET_P () ? INSN_ADDRESSES (INSN_UID (GET_CODE (operands[%d]) == LABEL_REF ? XEXP (operands[%d], 0) : operands[%d])) : 0",
03409 XINT (exp, 0), XINT (exp, 0), XINT (exp, 0));
03410 break;
03411
03412 case PC:
03413
03414
03415
03416
03417
03418 printf ("insn_current_reference_address (insn)");
03419 break;
03420
03421 case CONST_STRING:
03422 printf ("%s", XSTR (exp, 0));
03423 break;
03424
03425 case IF_THEN_ELSE:
03426 write_test_expr (XEXP (exp, 0), flags & 2);
03427 printf (" ? ");
03428 write_test_expr (XEXP (exp, 1), flags | 1);
03429 printf (" : ");
03430 write_test_expr (XEXP (exp, 2), flags | 1);
03431 break;
03432
03433 default:
03434 fatal ("bad RTX code `%s' in attribute calculation\n",
03435 GET_RTX_NAME (code));
03436 }
03437
03438 printf (")");
03439 }
03440
03441
03442
03443
03444 static int
03445 max_attr_value (rtx exp, int *unknownp)
03446 {
03447 int current_max;
03448 int i, n;
03449
03450 switch (GET_CODE (exp))
03451 {
03452 case CONST_STRING:
03453 current_max = atoi (XSTR (exp, 0));
03454 break;
03455
03456 case COND:
03457 current_max = max_attr_value (XEXP (exp, 1), unknownp);
03458 for (i = 0; i < XVECLEN (exp, 0); i += 2)
03459 {
03460 n = max_attr_value (XVECEXP (exp, 0, i + 1), unknownp);
03461 if (n > current_max)
03462 current_max = n;
03463 }
03464 break;
03465
03466 case IF_THEN_ELSE:
03467 current_max = max_attr_value (XEXP (exp, 1), unknownp);
03468 n = max_attr_value (XEXP (exp, 2), unknownp);
03469 if (n > current_max)
03470 current_max = n;
03471 break;
03472
03473 default:
03474 *unknownp = 1;
03475 current_max = INT_MAX;
03476 break;
03477 }
03478
03479 return current_max;
03480 }
03481
03482
03483
03484
03485 static int
03486 min_attr_value (rtx exp, int *unknownp)
03487 {
03488 int current_min;
03489 int i, n;
03490
03491 switch (GET_CODE (exp))
03492 {
03493 case CONST_STRING:
03494 current_min = atoi (XSTR (exp, 0));
03495 break;
03496
03497 case COND:
03498 current_min = min_attr_value (XEXP (exp, 1), unknownp);
03499 for (i = 0; i < XVECLEN (exp, 0); i += 2)
03500 {
03501 n = min_attr_value (XVECEXP (exp, 0, i + 1), unknownp);
03502 if (n < current_min)
03503 current_min = n;
03504 }
03505 break;
03506
03507 case IF_THEN_ELSE:
03508 current_min = min_attr_value (XEXP (exp, 1), unknownp);
03509 n = min_attr_value (XEXP (exp, 2), unknownp);
03510 if (n < current_min)
03511 current_min = n;
03512 break;
03513
03514 default:
03515 *unknownp = 1;
03516 current_min = INT_MAX;
03517 break;
03518 }
03519
03520 return current_min;
03521 }
03522
03523
03524
03525
03526
03527 static int
03528 or_attr_value (rtx exp, int *unknownp)
03529 {
03530 int current_or;
03531 int i;
03532
03533 switch (GET_CODE (exp))
03534 {
03535 case CONST_STRING:
03536 current_or = atoi (XSTR (exp, 0));
03537 break;
03538
03539 case COND:
03540 current_or = or_attr_value (XEXP (exp, 1), unknownp);
03541 for (i = 0; i < XVECLEN (exp, 0); i += 2)
03542 current_or |= or_attr_value (XVECEXP (exp, 0, i + 1), unknownp);
03543 break;
03544
03545 case IF_THEN_ELSE:
03546 current_or = or_attr_value (XEXP (exp, 1), unknownp);
03547 current_or |= or_attr_value (XEXP (exp, 2), unknownp);
03548 break;
03549
03550 default:
03551 *unknownp = 1;
03552 current_or = -1;
03553 break;
03554 }
03555
03556 return current_or;
03557 }
03558
03559
03560
03561
03562
03563
03564
03565
03566
03567
03568
03569 static void
03570 walk_attr_value (rtx exp)
03571 {
03572 int i, j;
03573 const char *fmt;
03574 RTX_CODE code;
03575
03576 if (exp == NULL)
03577 return;
03578
03579 code = GET_CODE (exp);
03580 switch (code)
03581 {
03582 case SYMBOL_REF:
03583 if (! ATTR_IND_SIMPLIFIED_P (exp))
03584
03585
03586
03587 must_extract = must_constrain = 1;
03588 return;
03589
03590 case MATCH_OPERAND:
03591 must_extract = 1;
03592 return;
03593
03594 case EQ_ATTR_ALT:
03595 must_extract = must_constrain = 1;
03596 break;
03597
03598 case EQ_ATTR:
03599 if (XSTR (exp, 0) == alternative_name)
03600 must_extract = must_constrain = 1;
03601 else if (strcmp_check (XSTR (exp, 0), length_str) == 0)
03602 length_used = 1;
03603 return;
03604
03605 case MATCH_DUP:
03606 must_extract = 1;
03607 address_used = 1;
03608 return;
03609
03610 case PC:
03611 address_used = 1;
03612 return;
03613
03614 case ATTR_FLAG:
03615 return;
03616
03617 default:
03618 break;
03619 }
03620
03621 for (i = 0, fmt = GET_RTX_FORMAT (code); i < GET_RTX_LENGTH (code); i++)
03622 switch (*fmt++)
03623 {
03624 case 'e':
03625 case 'u':
03626 walk_attr_value (XEXP (exp, i));
03627 break;
03628
03629 case 'E':
03630 if (XVEC (exp, i) != NULL)
03631 for (j = 0; j < XVECLEN (exp, i); j++)
03632 walk_attr_value (XVECEXP (exp, i, j));
03633 break;
03634 }
03635 }
03636
03637
03638
03639 static void
03640 write_attr_get (struct attr_desc *attr)
03641 {
03642 struct attr_value *av, *common_av;
03643
03644
03645
03646 common_av = find_most_used (attr);
03647
03648
03649
03650 if (!attr->is_numeric)
03651 printf ("enum attr_%s\n", attr->name);
03652 else
03653 printf ("int\n");
03654
03655
03656
03657 if (attr->name[0] == '*')
03658 printf ("%s (rtx insn ATTRIBUTE_UNUSED)\n", &attr->name[1]);
03659 else if (attr->is_const == 0)
03660 printf ("get_attr_%s (rtx insn ATTRIBUTE_UNUSED)\n", attr->name);
03661 else
03662 {
03663 printf ("get_attr_%s (void)\n", attr->name);
03664 printf ("{\n");
03665
03666 for (av = attr->first_value; av; av = av->next)
03667 if (av->num_insns == 1)
03668 write_attr_set (attr, 2, av->value, "return", ";",
03669 true_rtx, av->first_insn->def->insn_code,
03670 av->first_insn->def->insn_index);
03671 else if (av->num_insns != 0)
03672 write_attr_set (attr, 2, av->value, "return", ";",
03673 true_rtx, -2, 0);
03674
03675 printf ("}\n\n");
03676 return;
03677 }
03678
03679 printf ("{\n");
03680 printf (" switch (recog_memoized (insn))\n");
03681 printf (" {\n");
03682
03683 for (av = attr->first_value; av; av = av->next)
03684 if (av != common_av)
03685 write_attr_case (attr, av, 1, "return", ";", 4, true_rtx);
03686
03687 write_attr_case (attr, common_av, 0, "return", ";", 4, true_rtx);
03688 printf (" }\n}\n\n");
03689 }
03690
03691
03692
03693
03694
03695
03696 static rtx
03697 eliminate_known_true (rtx known_true, rtx exp, int insn_code, int insn_index)
03698 {
03699 rtx term;
03700
03701 known_true = SIMPLIFY_TEST_EXP (known_true, insn_code, insn_index);
03702
03703 if (GET_CODE (known_true) == AND)
03704 {
03705 exp = eliminate_known_true (XEXP (known_true, 0), exp,
03706 insn_code, insn_index);
03707 exp = eliminate_known_true (XEXP (known_true, 1), exp,
03708 insn_code, insn_index);
03709 }
03710 else
03711 {
03712 term = known_true;
03713 exp = simplify_and_tree (exp, &term, insn_code, insn_index);
03714 }
03715
03716 return exp;
03717 }
03718
03719
03720
03721
03722
03723
03724 static void
03725 write_attr_set (struct attr_desc *attr, int indent, rtx value,
03726 const char *prefix, const char *suffix, rtx known_true,
03727 int insn_code, int insn_index)
03728 {
03729 if (GET_CODE (value) == COND)
03730 {
03731
03732
03733 rtx default_val = XEXP (value, 1);
03734 rtx our_known_true = known_true;
03735 rtx newexp;
03736 int first_if = 1;
03737 int i;
03738
03739 for (i = 0; i < XVECLEN (value, 0); i += 2)
03740 {
03741 rtx testexp;
03742 rtx inner_true;
03743
03744 testexp = eliminate_known_true (our_known_true,
03745 XVECEXP (value, 0, i),
03746 insn_code, insn_index);
03747 newexp = attr_rtx (NOT, testexp);
03748 newexp = insert_right_side (AND, our_known_true, newexp,
03749 insn_code, insn_index);
03750
03751
03752
03753
03754 if (testexp == true_rtx || newexp == false_rtx)
03755 {
03756 default_val = XVECEXP (value, 0, i + 1);
03757 break;
03758 }
03759
03760
03761
03762 inner_true = insert_right_side (AND, our_known_true,
03763 testexp, insn_code, insn_index);
03764
03765
03766 if (inner_true == false_rtx)
03767 continue;
03768
03769 write_indent (indent);
03770 printf ("%sif ", first_if ? "" : "else ");
03771 first_if = 0;
03772 write_test_expr (testexp, 0);
03773 printf ("\n");
03774 write_indent (indent + 2);
03775 printf ("{\n");
03776
03777 write_attr_set (attr, indent + 4,
03778 XVECEXP (value, 0, i + 1), prefix, suffix,
03779 inner_true, insn_code, insn_index);
03780 write_indent (indent + 2);
03781 printf ("}\n");
03782 our_known_true = newexp;
03783 }
03784
03785 if (! first_if)
03786 {
03787 write_indent (indent);
03788 printf ("else\n");
03789 write_indent (indent + 2);
03790 printf ("{\n");
03791 }
03792
03793 write_attr_set (attr, first_if ? indent : indent + 4, default_val,
03794 prefix, suffix, our_known_true, insn_code, insn_index);
03795
03796 if (! first_if)
03797 {
03798 write_indent (indent + 2);
03799 printf ("}\n");
03800 }
03801 }
03802 else
03803 {
03804 write_indent (indent);
03805 printf ("%s ", prefix);
03806 write_attr_value (attr, value);
03807 printf ("%s\n", suffix);
03808 }
03809 }
03810
03811
03812
03813
03814 static void
03815 write_insn_cases (struct insn_ent *ie, int indent)
03816 {
03817 for (; ie != 0; ie = ie->next)
03818 if (ie->def->insn_code != -1)
03819 {
03820 write_indent (indent);
03821 if (GET_CODE (ie->def->def) == DEFINE_PEEPHOLE)
03822 printf ("case %d: /* define_peephole, line %d */\n",
03823 ie->def->insn_code, ie->def->lineno);
03824 else
03825 printf ("case %d: /* %s */\n",
03826 ie->def->insn_code, XSTR (ie->def->def, 0));
03827 }
03828 }
03829
03830
03831
03832 static void
03833 write_attr_case (struct attr_desc *attr, struct attr_value *av,
03834 int write_case_lines, const char *prefix, const char *suffix,
03835 int indent, rtx known_true)
03836 {
03837 if (av->num_insns == 0)
03838 return;
03839
03840 if (av->has_asm_insn)
03841 {
03842 write_indent (indent);
03843 printf ("case -1:\n");
03844 write_indent (indent + 2);
03845 printf ("if (GET_CODE (PATTERN (insn)) != ASM_INPUT\n");
03846 write_indent (indent + 2);
03847 printf (" && asm_noperands (PATTERN (insn)) < 0)\n");
03848 write_indent (indent + 2);
03849 printf (" fatal_insn_not_found (insn);\n");
03850 }
03851
03852 if (write_case_lines)
03853 write_insn_cases (av->first_insn, indent);
03854 else
03855 {
03856 write_indent (indent);
03857 printf ("default:\n");
03858 }
03859
03860
03861 must_extract = must_constrain = address_used = 0;
03862 walk_attr_value (av->value);
03863
03864 if (must_constrain)
03865 {
03866 write_indent (indent + 2);
03867 printf ("extract_constrain_insn_cached (insn);\n");
03868 }
03869 else if (must_extract)
03870 {
03871 write_indent (indent + 2);
03872 printf ("extract_insn_cached (insn);\n");
03873 }
03874
03875 if (av->num_insns == 1)
03876 write_attr_set (attr, indent + 2, av->value, prefix, suffix,
03877 known_true, av->first_insn->def->insn_code,
03878 av->first_insn->def->insn_index);
03879 else
03880 write_attr_set (attr, indent + 2, av->value, prefix, suffix,
03881 known_true, -2, 0);
03882
03883 if (strncmp (prefix, "return", 6))
03884 {
03885 write_indent (indent + 2);
03886 printf ("break;\n");
03887 }
03888 printf ("\n");
03889 }
03890
03891
03892
03893 static int
03894 write_expr_attr_cache (rtx p, struct attr_desc *attr)
03895 {
03896 const char *fmt;
03897 int i, ie, j, je;
03898
03899 if (GET_CODE (p) == EQ_ATTR)
03900 {
03901 if (XSTR (p, 0) != attr->name)
03902 return 0;
03903
03904 if (!attr->is_numeric)
03905 printf (" enum attr_%s ", attr->name);
03906 else
03907 printf (" int ");
03908
03909 printf ("attr_%s = get_attr_%s (insn);\n", attr->name, attr->name);
03910 return 1;
03911 }
03912
03913 fmt = GET_RTX_FORMAT (GET_CODE (p));
03914 ie = GET_RTX_LENGTH (GET_CODE (p));
03915 for (i = 0; i < ie; i++)
03916 {
03917 switch (*fmt++)
03918 {
03919 case 'e':
03920 if (write_expr_attr_cache (XEXP (p, i), attr))
03921 return 1;
03922 break;
03923
03924 case 'E':
03925 je = XVECLEN (p, i);
03926 for (j = 0; j < je; ++j)
03927 if (write_expr_attr_cache (XVECEXP (p, i, j), attr))
03928 return 1;
03929 break;
03930 }
03931 }
03932
03933 return 0;
03934 }
03935
03936
03937
03938 static void
03939 write_attr_valueq (struct attr_desc *attr, const char *s)
03940 {
03941 if (attr->is_numeric)
03942 {
03943 int num = atoi (s);
03944
03945 printf ("%d", num);
03946
03947 if (num > 9 || num < 0)
03948 printf (" /* 0x%x */", num);
03949 }
03950 else
03951 {
03952 write_upcase (attr->name);
03953 printf ("_");
03954 write_upcase (s);
03955 }
03956 }
03957
03958 static void
03959 write_attr_value (struct attr_desc *attr, rtx value)
03960 {
03961 int op;
03962
03963 switch (GET_CODE (value))
03964 {
03965 case CONST_STRING:
03966 write_attr_valueq (attr, XSTR (value, 0));
03967 break;
03968
03969 case CONST_INT:
03970 printf (HOST_WIDE_INT_PRINT_DEC, INTVAL (value));
03971 break;
03972
03973 case SYMBOL_REF:
03974 print_c_condition (XSTR (value, 0));
03975 break;
03976
03977 case ATTR:
03978 {
03979 struct attr_desc *attr2 = find_attr (&XSTR (value, 0), 0);
03980 printf ("get_attr_%s (%s)", attr2->name,
03981 (attr2->is_const ? "" : "insn"));
03982 }
03983 break;
03984
03985 case PLUS:
03986 op = '+';
03987 goto do_operator;
03988 case MINUS:
03989 op = '-';
03990 goto do_operator;
03991 case MULT:
03992 op = '*';
03993 goto do_operator;
03994 case DIV:
03995 op = '/';
03996 goto do_operator;
03997 case MOD:
03998 op = '%';
03999 goto do_operator;
04000
04001 do_operator:
04002 write_attr_value (attr, XEXP (value, 0));
04003 putchar (' ');
04004 putchar (op);
04005 putchar (' ');
04006 write_attr_value (attr, XEXP (value, 1));
04007 break;
04008
04009 default:
04010 gcc_unreachable ();
04011 }
04012 }
04013
04014 static void
04015 write_upcase (const char *str)
04016 {
04017 while (*str)
04018 {
04019
04020 putchar (TOUPPER(*str));
04021 str++;
04022 }
04023 }
04024
04025 static void
04026 write_indent (int indent)
04027 {
04028 for (; indent > 8; indent -= 8)
04029 printf ("\t");
04030
04031 for (; indent; indent--)
04032 printf (" ");
04033 }
04034
04035
04036
04037
04038
04039
04040
04041
04042
04043
04044
04045
04046
04047 static void
04048 write_eligible_delay (const char *kind)
04049 {
04050 struct delay_desc *delay;
04051 int max_slots;
04052 char str[50];
04053 const char *pstr;
04054 struct attr_desc *attr;
04055 struct attr_value *av, *common_av;
04056 int i;
04057
04058
04059
04060
04061
04062 for (delay = delays, max_slots = 0; delay; delay = delay->next)
04063 if (XVECLEN (delay->def, 1) / 3 > max_slots)
04064 max_slots = XVECLEN (delay->def, 1) / 3;
04065
04066
04067
04068 printf ("int\n");
04069 printf ("eligible_for_%s (rtx delay_insn ATTRIBUTE_UNUSED, int slot, rtx candidate_insn, int flags ATTRIBUTE_UNUSED)\n",
04070 kind);
04071 printf ("{\n");
04072 printf (" rtx insn;\n");
04073 printf ("\n");
04074 printf (" gcc_assert (slot < %d);\n", max_slots);
04075 printf ("\n");
04076
04077
04078 printf (" if (!INSN_P (candidate_insn))\n");
04079 printf (" return 0;\n");
04080 printf ("\n");
04081
04082
04083
04084 if (num_delays > 1)
04085 {
04086 attr = find_attr (&delay_type_str, 0);
04087 gcc_assert (attr);
04088 common_av = find_most_used (attr);
04089
04090 printf (" insn = delay_insn;\n");
04091 printf (" switch (recog_memoized (insn))\n");
04092 printf (" {\n");
04093
04094 sprintf (str, " * %d;\n break;", max_slots);
04095 for (av = attr->first_value; av; av = av->next)
04096 if (av != common_av)
04097 write_attr_case (attr, av, 1, "slot +=", str, 4, true_rtx);
04098
04099 write_attr_case (attr, common_av, 0, "slot +=", str, 4, true_rtx);
04100 printf (" }\n\n");
04101
04102
04103 printf (" gcc_assert (slot >= %d);\n\n", max_slots);
04104 }
04105
04106
04107 if (num_delays == 1 && max_slots == 1)
04108 {
04109 printf (" insn = candidate_insn;\n");
04110 printf (" switch (recog_memoized (insn))\n");
04111 printf (" {\n");
04112
04113 attr = find_attr (&delay_1_0_str, 0);
04114 gcc_assert (attr);
04115 common_av = find_most_used (attr);
04116
04117 for (av = attr->first_value; av; av = av->next)
04118 if (av != common_av)
04119 write_attr_case (attr, av, 1, "return", ";", 4, true_rtx);
04120
04121 write_attr_case (attr, common_av, 0, "return", ";", 4, true_rtx);
04122 printf (" }\n");
04123 }
04124
04125 else
04126 {
04127
04128
04129 printf (" insn = candidate_insn;\n");
04130 printf (" switch (slot)\n");
04131 printf (" {\n");
04132
04133 for (delay = delays; delay; delay = delay->next)
04134 for (i = 0; i < XVECLEN (delay->def, 1); i += 3)
04135 {
04136 printf (" case %d:\n",
04137 (i / 3) + (num_delays == 1 ? 0 : delay->num * max_slots));
04138 printf (" switch (recog_memoized (insn))\n");
04139 printf ("\t{\n");
04140
04141 sprintf (str, "*%s_%d_%d", kind, delay->num, i / 3);
04142 pstr = str;
04143 attr = find_attr (&pstr, 0);
04144 gcc_assert (attr);
04145 common_av = find_most_used (attr);
04146
04147 for (av = attr->first_value; av; av = av->next)
04148 if (av != common_av)
04149 write_attr_case (attr, av, 1, "return", ";", 8, true_rtx);
04150
04151 write_attr_case (attr, common_av, 0, "return", ";", 8, true_rtx);
04152 printf (" }\n");
04153 }
04154
04155 printf (" default:\n");
04156 printf (" gcc_unreachable ();\n");
04157 printf (" }\n");
04158 }
04159
04160 printf ("}\n\n");
04161 }
04162
04163
04164
04165
04166
04167
04168
04169 static char *
04170 next_comma_elt (const char **pstr)
04171 {
04172 const char *start;
04173
04174 start = scan_comma_elt (pstr);
04175
04176 if (start == NULL)
04177 return NULL;
04178
04179 return attr_string (start, *pstr - start);
04180 }
04181
04182
04183
04184
04185
04186 static struct attr_desc *
04187 find_attr (const char **name_p, int create)
04188 {
04189 struct attr_desc *attr;
04190 int index;
04191 const char *name = *name_p;
04192
04193
04194
04195 if (name == alternative_name)
04196 return NULL;
04197
04198 index = name[0] & (MAX_ATTRS_INDEX - 1);
04199 for (attr = attrs[index]; attr; attr = attr->next)
04200 if (name == attr->name)
04201 return attr;
04202
04203
04204 for (attr = attrs[index]; attr; attr = attr->next)
04205 if (name[0] == attr->name[0] && ! strcmp (name, attr->name))
04206 {
04207 *name_p = attr->name;
04208 return attr;
04209 }
04210
04211 if (! create)
04212 return NULL;
04213
04214 attr = oballoc (sizeof (struct attr_desc));
04215 attr->name = DEF_ATTR_STRING (name);
04216 attr->first_value = attr->default_val = NULL;
04217 attr->is_numeric = attr->is_const = attr->is_special = 0;
04218 attr->next = attrs[index];
04219 attrs[index] = attr;
04220
04221 *name_p = attr->name;
04222
04223 return attr;
04224 }
04225
04226
04227
04228 static void
04229 make_internal_attr (const char *name, rtx value, int special)
04230 {
04231 struct attr_desc *attr;
04232
04233 attr = find_attr (&name, 1);
04234 gcc_assert (!attr->default_val);
04235
04236 attr->is_numeric = 1;
04237 attr->is_const = 0;
04238 attr->is_special = (special & ATTR_SPECIAL) != 0;
04239 attr->default_val = get_attr_value (value, attr, -2);
04240 }
04241
04242
04243
04244 static struct attr_value *
04245 find_most_used (struct attr_desc *attr)
04246 {
04247 struct attr_value *av;
04248 struct attr_value *most_used;
04249 int nuses;
04250
04251 most_used = NULL;
04252 nuses = -1;
04253
04254 for (av = attr->first_value; av; av = av->next)
04255 if (av->num_insns > nuses)
04256 nuses = av->num_insns, most_used = av;
04257
04258 return most_used;
04259 }
04260
04261
04262
04263 static rtx
04264 make_numeric_value (int n)
04265 {
04266 static rtx int_values[20];
04267 rtx exp;
04268 char *p;
04269
04270 gcc_assert (n >= 0);
04271
04272 if (n < 20 && int_values[n])
04273 return int_values[n];
04274
04275 p = attr_printf (MAX_DIGITS, "%d", n);
04276 exp = attr_rtx (CONST_STRING, p);
04277
04278 if (n < 20)
04279 int_values[n] = exp;
04280
04281 return exp;
04282 }
04283
04284 static rtx
04285 copy_rtx_unchanging (rtx orig)
04286 {
04287 if (ATTR_IND_SIMPLIFIED_P (orig) || ATTR_CURR_SIMPLIFIED_P (orig))
04288 return orig;
04289
04290 ATTR_CURR_SIMPLIFIED_P (orig) = 1;
04291 return orig;
04292 }
04293
04294
04295
04296
04297 static void
04298 write_const_num_delay_slots (void)
04299 {
04300 struct attr_desc *attr = find_attr (&num_delay_slots_str, 0);
04301 struct attr_value *av;
04302
04303 if (attr)
04304 {
04305 printf ("int\nconst_num_delay_slots (rtx insn)\n");
04306 printf ("{\n");
04307 printf (" switch (recog_memoized (insn))\n");
04308 printf (" {\n");
04309
04310 for (av = attr->first_value; av; av = av->next)
04311 {
04312 length_used = 0;
04313 walk_attr_value (av->value);
04314 if (length_used)
04315 write_insn_cases (av->first_insn, 4);
04316 }
04317
04318 printf (" default:\n");
04319 printf (" return 1;\n");
04320 printf (" }\n}\n\n");
04321 }
04322 }
04323
04324
04325
04326
04327
04328 struct insn_reserv
04329 {
04330 struct insn_reserv *next;
04331
04332 const char *name;
04333 int default_latency;
04334 rtx condexp;
04335
04336
04337 int insn_num;
04338
04339
04340
04341 bool bypassed;
04342 };
04343
04344 static struct insn_reserv *all_insn_reservs = 0;
04345 static struct insn_reserv **last_insn_reserv_p = &all_insn_reservs;
04346 static size_t n_insn_reservs;
04347
04348
04349
04350 static void
04351 gen_insn_reserv (rtx def)
04352 {
04353 struct insn_reserv *decl = oballoc (sizeof (struct insn_reserv));
04354
04355 decl->name = DEF_ATTR_STRING (XSTR (def, 0));
04356 decl->default_latency = XINT (def, 1);
04357 decl->condexp = check_attr_test (XEXP (def, 2), 0, 0);
04358 decl->insn_num = n_insn_reservs;
04359 decl->bypassed = false;
04360 decl->next = 0;
04361
04362 *last_insn_reserv_p = decl;
04363 last_insn_reserv_p = &decl->next;
04364 n_insn_reservs++;
04365 }
04366
04367
04368
04369
04370
04371
04372 struct bypass_list
04373 {
04374 struct bypass_list *next;
04375 const char *insn;
04376 };
04377
04378 static struct bypass_list *all_bypasses;
04379 static size_t n_bypasses;
04380
04381 static void
04382 gen_bypass_1 (const char *s, size_t len)
04383 {
04384 struct bypass_list *b;
04385
04386 if (len == 0)
04387 return;
04388
04389 s = attr_string (s, len);
04390 for (b = all_bypasses; b; b = b->next)
04391 if (s == b->insn)
04392 return;
04393
04394 b = oballoc (sizeof (struct bypass_list));
04395 b->insn = s;
04396 b->next = all_bypasses;
04397 all_bypasses = b;
04398 n_bypasses++;
04399 }
04400
04401 static void
04402 gen_bypass (rtx def)
04403 {
04404 const char *p, *base;
04405
04406 for (p = base = XSTR (def, 1); *p; p++)
04407 if (*p == ',')
04408 {
04409 gen_bypass_1 (base, p - base);
04410 do
04411 p++;
04412 while (ISSPACE (*p));
04413 base = p;
04414 }
04415 gen_bypass_1 (base, p - base);
04416 }
04417
04418
04419 static void
04420 process_bypasses (void)
04421 {
04422 struct bypass_list *b;
04423 struct insn_reserv *r;
04424
04425
04426
04427 for (r = all_insn_reservs; r; r = r->next)
04428 for (b = all_bypasses; b; b = b->next)
04429 if (r->name == b->insn)
04430 r->bypassed = true;
04431 }
04432
04433
04434 static void
04435 make_automaton_attrs (void)
04436 {
04437 int i;
04438 struct insn_reserv *decl;
04439 rtx code_exp, lats_exp, byps_exp;
04440
04441 if (n_insn_reservs == 0)
04442 return;
04443
04444 code_exp = rtx_alloc (COND);
04445 lats_exp = rtx_alloc (COND);
04446
04447 XVEC (code_exp, 0) = rtvec_alloc (n_insn_reservs * 2);
04448 XVEC (lats_exp, 0) = rtvec_alloc (n_insn_reservs * 2);
04449
04450 XEXP (code_exp, 1) = make_numeric_value (n_insn_reservs + 1);
04451 XEXP (lats_exp, 1) = make_numeric_value (0);
04452
04453 for (decl = all_insn_reservs, i = 0;
04454 decl;
04455 decl = decl->next, i += 2)
04456 {
04457 XVECEXP (code_exp, 0, i) = decl->condexp;
04458 XVECEXP (lats_exp, 0, i) = decl->condexp;
04459
04460 XVECEXP (code_exp, 0, i+1) = make_numeric_value (decl->insn_num);
04461 XVECEXP (lats_exp, 0, i+1) = make_numeric_value (decl->default_latency);
04462 }
04463
04464 if (n_bypasses == 0)
04465 byps_exp = make_numeric_value (0);
04466 else
04467 {
04468 process_bypasses ();
04469
04470 byps_exp = rtx_alloc (COND);
04471 XVEC (byps_exp, 0) = rtvec_alloc (n_bypasses * 2);
04472 XEXP (byps_exp, 1) = make_numeric_value (0);
04473 for (decl = all_insn_reservs, i = 0;
04474 decl;
04475 decl = decl->next)
04476 if (decl->bypassed)
04477 {
04478 XVECEXP (byps_exp, 0, i) = decl->condexp;
04479 XVECEXP (byps_exp, 0, i+1) = make_numeric_value (1);
04480 i += 2;
04481 }
04482 }
04483
04484 make_internal_attr ("*internal_dfa_insn_code", code_exp, ATTR_NONE);
04485 make_internal_attr ("*insn_default_latency", lats_exp, ATTR_NONE);
04486 make_internal_attr ("*bypass_p", byps_exp, ATTR_NONE);
04487 }
04488
04489 int
04490 main (int argc, char **argv)
04491 {
04492 rtx desc;
04493 struct attr_desc *attr;
04494 struct insn_def *id;
04495 rtx tem;
04496 int i;
04497
04498 progname = "genattrtab";
04499
04500 if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
04501 return (FATAL_EXIT_CODE);
04502
04503 obstack_init (hash_obstack);
04504 obstack_init (temp_obstack);
04505
04506
04507 true_rtx = rtx_alloc (CONST_INT);
04508 XWINT (true_rtx, 0) = 1;
04509 false_rtx = rtx_alloc (CONST_INT);
04510 XWINT (false_rtx, 0) = 0;
04511 ATTR_IND_SIMPLIFIED_P (true_rtx) = ATTR_IND_SIMPLIFIED_P (false_rtx) = 1;
04512 ATTR_PERMANENT_P (true_rtx) = ATTR_PERMANENT_P (false_rtx) = 1;
04513
04514 alternative_name = DEF_ATTR_STRING ("alternative");
04515 length_str = DEF_ATTR_STRING ("length");
04516 delay_type_str = DEF_ATTR_STRING ("*delay_type");
04517 delay_1_0_str = DEF_ATTR_STRING ("*delay_1_0");
04518 num_delay_slots_str = DEF_ATTR_STRING ("*num_delay_slots");
04519
04520 printf ("/* Generated automatically by the program `genattrtab'\n\
04521 from the machine description file `md'. */\n\n");
04522
04523
04524
04525 while (1)
04526 {
04527 int lineno;
04528
04529 desc = read_md_rtx (&lineno, &insn_code_number);
04530 if (desc == NULL)
04531 break;
04532
04533 switch (GET_CODE (desc))
04534 {
04535 case DEFINE_INSN:
04536 case DEFINE_PEEPHOLE:
04537 case DEFINE_ASM_ATTRIBUTES:
04538 gen_insn (desc, lineno);
04539 break;
04540
04541 case DEFINE_ATTR:
04542 gen_attr (desc, lineno);
04543 break;
04544
04545 case DEFINE_DELAY:
04546 gen_delay (desc, lineno);
04547 break;
04548
04549 case DEFINE_INSN_RESERVATION:
04550 gen_insn_reserv (desc);
04551 break;
04552
04553 case DEFINE_BYPASS:
04554 gen_bypass (desc);
04555 break;
04556
04557 default:
04558 break;
04559 }
04560 if (GET_CODE (desc) != DEFINE_ASM_ATTRIBUTES)
04561 insn_index_number++;
04562 }
04563
04564 if (have_error)
04565 return FATAL_EXIT_CODE;
04566
04567 insn_code_number++;
04568
04569
04570 if (! got_define_asm_attributes)
04571 {
04572 tem = rtx_alloc (DEFINE_ASM_ATTRIBUTES);
04573 XVEC (tem, 0) = rtvec_alloc (0);
04574 gen_insn (tem, 0);
04575 }
04576
04577
04578 if (num_delays)
04579 expand_delays ();
04580
04581 printf ("#include \"config.h\"\n");
04582 printf ("#include \"system.h\"\n");
04583 printf ("#include \"coretypes.h\"\n");
04584 printf ("#include \"tm.h\"\n");
04585 printf ("#include \"rtl.h\"\n");
04586 printf ("#include \"tm_p.h\"\n");
04587 printf ("#include \"insn-config.h\"\n");
04588 printf ("#include \"recog.h\"\n");
04589 printf ("#include \"regs.h\"\n");
04590 printf ("#include \"real.h\"\n");
04591 printf ("#include \"output.h\"\n");
04592 printf ("#include \"insn-attr.h\"\n");
04593 printf ("#include \"toplev.h\"\n");
04594 printf ("#include \"flags.h\"\n");
04595 printf ("#include \"function.h\"\n");
04596 printf ("\n");
04597 printf ("#define operands recog_data.operand\n\n");
04598
04599
04600 insn_alternatives = oballoc (insn_code_number * sizeof (int));
04601 for (id = defs; id; id = id->next)
04602 if (id->insn_code >= 0)
04603 insn_alternatives[id->insn_code] = (1 << id->num_alternatives) - 1;
04604
04605
04606 insn_n_alternatives = oballoc (insn_code_number * sizeof (int));
04607 for (id = defs; id; id = id->next)
04608 if (id->insn_code >= 0)
04609 insn_n_alternatives[id->insn_code] = id->num_alternatives;
04610
04611
04612 make_automaton_attrs ();
04613
04614
04615
04616
04617 check_defs ();
04618
04619 for (i = 0; i < MAX_ATTRS_INDEX; i++)
04620 for (attr = attrs[i]; attr; attr = attr->next)
04621 attr->default_val->value
04622 = check_attr_value (attr->default_val->value, attr);
04623
04624 if (have_error)
04625 return FATAL_EXIT_CODE;
04626
04627 for (i = 0; i < MAX_ATTRS_INDEX; i++)
04628 for (attr = attrs[i]; attr; attr = attr->next)
04629 fill_attr (attr);
04630
04631
04632 make_length_attrs ();
04633
04634
04635 optimize_attrs ();
04636
04637
04638
04639
04640 for (i = 0; i < MAX_ATTRS_INDEX; i++)
04641 for (attr = attrs[i]; attr; attr = attr->next)
04642 {
04643 if (! attr->is_special && ! attr->is_const)
04644 write_attr_get (attr);
04645 }
04646
04647
04648
04649
04650 if (num_delays)
04651 {
04652 write_eligible_delay ("delay");
04653 if (have_annul_true)
04654 write_eligible_delay ("annul_true");
04655 if (have_annul_false)
04656 write_eligible_delay ("annul_false");
04657 }
04658
04659
04660 write_const_num_delay_slots ();
04661
04662 write_length_unit_log ();
04663
04664 fflush (stdout);
04665 return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
04666 }