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