9.6.1.4. Outputattributes
Though we have created attributes related data, for using bypipeline hazards recognizer, they are needed be output as functions whichaccept rtx object of the instructions, and return attributes’ value for theinstruction. These functions are output into file insn-attrtab.c, and will becompiled as part of source code of the gcc to produce the executive file.
main (continued)
6190 /* Now write outall the `gen_attr_...' routines. Do these before the
6191 special routines (specifically beforewrite_function_unit_info), so
6192 that they get defined before they areused. */
6193
6194 for (i = 0; i < MAX_ATTRS_INDEX; i++)
6195 for (attr =attrs[i];attr; attr = attr->next)
6196 {
6197 if (! attr->is_special && !attr->is_const)
6198 {
6199 int insn_alts_p;
6200
6201 insn_alts_p
6202 = (attr->name [0] == '*'
6203 && strcmp(&attr->name[1], INSN_ALTS_FUNC_NAME) == 0);
6204 if(insn_alts_p)
6205 printf ("\n#ifAUTOMATON_ALTS\n");
6206 write_attr_get (attr);
6207 if (insn_alts_p)
6208 printf ("#endif\n\n");
6209 }
6210 }
Above at line 6197, is_special is set for attributes needed specialtreatment – they will not produce the normal attribute value fetchers.Following is the list of attributes having is_special set:
*delay_type (it is singleton across the system)
*delay_`delay-no`_`slot-no` (it is per slot for every define_delaypattern)
*annul_true_`delay-no`_`slot-no` (it is per slot for everydefine_delay pattern)
*annul_false_`delay-no`_`slot-no` (it is per slot for everydefine_delay pattern)
*`unit-name`_cost_`op-num` (issue cost of the instruction upon theunit)
*`unit-name`_block_`op-num` (issue delay of the instruction upon theunit)
*`unit-name`_cases (singleton, and case expression for all units,see expand_units)
For attributes containing constant content, is_const is set.
At line 6203, INSN_ATLS_FUNC_NAME is defined as “insn_alts”, theattribute associated is created in make_insn_alts_attr, and the attributedescribes the number of alternatives in define_insn_reservation.
write_attr_get writes out a function to fetch the value of the attribute for giveninstruction.
5004 static void
5005 write_attr_get (structattr_desc *attr) in genattrtab.c
5006 {
5007 struct attr_value*av, *common_av;
5008
5009 /* Find the mostused attribute value. Handle that as the `default' of the
5010 switch we will generate. */
5011 common_av = find_most_used (attr);
5012
5013 /* Write out startof function, then all values with explicit `case' lines,
5014 then a `default', then the value with themost uses. */
5015 if (attr->static_p)
5016 printf ("static ");
5017 if (!attr->is_numeric)
5018 printf ("enum attr_%s\n",attr->name);
5019 else if (attr->unsigned_p)
5020 printf ("unsigned int\n");
5021 else
5022 printf ("int\n");
5023
5024 /* If the attributename starts with a star, the remainder is the name of
5025 the subroutine to use, instead of`get_attr_...'. */
5026 if (attr->name[0] == '*')
5027 printf ("%s (rtx insnATTRIBUTE_UNUSED)\n", &attr->name[1]);
5028 else if (attr->is_const == 0)
5029 printf ("get_attr_%s (rtx insnATTRIBUTE_UNUSED)\n", attr->name);
5030 else
5031 {
5032 printf ("get_attr_%s (void)\n",attr->name);
5033 printf ("{\n");
5034
5035 for (av =attr->first_value; av; av = av->next)
5036 if (av->num_insns != 0)
5037 write_attr_set (attr, 2, av->value,"return", ";",
5038 true_rtx, av->first_insn->insn_code,
5039 av->first_insn->insn_index);
5040
5041 printf ("}\n\n");
5042 return;
5043 }
5044
5045 printf ("{\n");
5046
5047 if (GET_CODE (common_av->value) == FFS)
5048 {
5049 rtx p = XEXP (common_av->value, 0);
5050
5051 /* No need toemit code to abort if the insn is unrecognized; the
5052 other get_attr_foo functions will do thatwhen we call them. */
5053
5054 write_toplevel_expr (p);
5055
5056 printf ("\n if (accum && accum == (accum &-accum))\n");
5057 printf (" {\n");
5058 printf (" int i;\n");
5059 printf (" for (i = 0; accum >>= 1; ++i)continue;\n");
5060 printf (" accum = i;\n");
5061 printf (" }\n else\n");
5062 printf (" accum = ~accum;\n");
5063 printf (" return accum;\n}\n\n");
5064 }
5065 else
5066 {
5067 printf (" switch (recog_memoized (insn))\n");
5068 printf (" {\n");
5069
5070 for (av =attr->first_value; av; av = av->next)
5071 if (av != common_av)
5072 write_attr_case (attr, av, 1, "return", ";", 4, true_rtx);
5073
5074 write_attr_case (attr, common_av, 0, "return", ";", 4, true_rtx);
5075 printf (" }\n}\n\n");
5076 }
5077 }
At line 5037, notice that write_attr_set is invoked for attributes ofconstant and haven’t “*” at beginning of their names. However, before entering write_attr_get,attributes of this kind have been filtered out (see line 6197 in main). write_attr_set will not be invoked here.
FFS at line 5047 means the operation of “find first bit set”. Here,for instruction using FFS mostly, we don’t attempt to recognize it. In releaseV4, the special treatment for FFS is removed. Anyway, for other instructions,recognition is must. See recog_memoized outputat line 5067, this function is a wrapper for recog which is output by genrecog(3. Tool of genrecog). The returned value isthe insn code of the instruction object input.
For every attribute value, write_attr_case writes out the computation.
5201 static void
5202 write_attr_case (struct attr_desc *attr, struct attr_value*av, in genattrtab.c
5203 int write_case_lines, const char *prefix, constchar *suffix,
5204 int indent, rtx known_true)
5205 {
5206 struct insn_ent*ie;
5207
5208 if (av->num_insns == 0)
5209 return;
5210
5211 if (av->has_asm_insn)
5212 {
5213 write_indent (indent);
5214 printf ("case -1:\n");
5215 write_indent (indent + 2);
5216 printf ("if (GET_CODE (PATTERN (insn))!= ASM_INPUT\n");
5217 write_indent (indent + 2);
5218 printf (" && asm_noperands (PATTERN (insn))< 0)\n");
5219 write_indent (indent + 2);
5220 printf (" fatal_insn_not_found (insn);\n");
5221 }
5222
5223 if (write_case_lines)
5224 {
5225 for (ie =av->first_insn; ie; ie = ie->next)
5226 if (ie->insn_code != -1)
5227 {
5228 write_indent (indent);
5229 printf ("case %d:\n",ie->insn_code);
5230 }
5231 }
5232 else
5233 {
5234 write_indent (indent);
5235 printf ("default:\n");
5236 }
5237
5238 /* See what we haveto do to output this value. */
5239 must_extract = must_constrain = address_used= 0;
5240 walk_attr_value (av->value);
5241
5242 if (must_constrain)
5243 {
5244 write_indent (indent + 2);
5245 printf ("extract_constrain_insn_cached(insn);\n");
5246 }
5247 else if (must_extract)
5248 {
5249 write_indent (indent + 2);
5250 printf ("extract_insn_cached(insn);\n");
5251 }
5252
5253 write_attr_set (attr, indent + 2, av->value, prefix, suffix,
5254 known_true,av->first_insn->insn_code,
5255 av->first_insn->insn_index);
5256
5257 if (strncmp (prefix, "return", 6))
5258 {
5259 write_indent (indent + 2);
5260 printf ("break;\n");
5261 }
5262 printf ("\n");
5263 }
Above at line 5211, field has_asm_insn is set as long as the attribute has valueset in certain asm statement (no matter how many other places this value setagain). And for the asm statement, its insn code is -1.
5112 static void
5113 write_attr_set (structattr_desc *attr, int indent, rtx value, ingenattrtab.c
5114 constchar *prefix, const char *suffix, rtxknown_true,
5115 intinsn_code, int insn_index)
5116 {
5117 if (GET_CODE (value) == COND)
5118 {
5119 /* Assume the default value will be thedefault of the COND unless we
5120 find an always true expression. */
5121 rtx default_val = XEXP (value, 1);
5122 rtx our_known_true = known_true;
5123 rtx newexp;
5124 int first_if = 1;
5125 int i;
5126
5127 for (i = 0; i < XVECLEN (value, 0); i += 2)
5128 {
5129 rtx testexp;
5130 rtx inner_true;
5131
5132 testexp = eliminate_known_true (our_known_true,
5133 XVECEXP(value, 0, i),
5134 insn_code,insn_index);
5135 newexp = attr_rtx(NOT, testexp);
5136 newexp = insert_right_side (AND, our_known_true, newexp,
5137 insn_code,insn_index);
5138
5139 /* If the test expression is always true or if the next`known_true'
5140 expression is always false, this is thelast case, so break
5141 out and let this value be the `else'case. */
5142 if (testexp == true_rtx || newexp == false_rtx)
5143 {
5144 default_val = XVECEXP (value, 0, i +1);
5145 break;
5146 }
5147
5148 /* Compute theexpression to pass to our recursive call as being
5149 known true. */
5150 inner_true = insert_right_side (AND, our_known_true,
5151 testexp,insn_code, insn_index);
5152
5153 /* If this is always false, skip it. */
5154 if (inner_true == false_rtx)
5155 continue;
5156
5157 write_indent (indent);
5158 printf ("%sif ", first_if ?"" : "else ");
5159 first_if = 0;
5160 write_test_expr (testexp, 0);
5161 printf ("\n");
5162 write_indent (indent + 2);
5163 printf ("{\n");
5164
5165 write_attr_set (attr, indent + 4,
5166 XVECEXP (value, 0, i + 1),prefix, suffix,
5167 inner_true, insn_code,insn_index);
5168 write_indent (indent + 2);
5169 printf ("}\n");
5170 our_known_true = newexp;
5171 }
5172
5173 if (! first_if)
5174 {
5175 write_indent (indent);
5176 printf ("else\n");
5177 write_indent (indent + 2);
5178 printf ("{\n");
5179 }
5180
5181 write_attr_set (attr, first_if ? indent : indent + 4, default_val,
5182 prefix, suffix, our_known_true,insn_code, insn_index);
5183
5184 if (! first_if)
5185 {
5186 write_indent (indent + 2);
5187 printf ("}\n");
5188 }
5189 }
5190 else
5191 {
5192 write_indent (indent);
5193 printf ("%s ", prefix);
5194 write_attr_value (attr, value);
5195 printf ("%s\n", suffix);
5196 }
5197 }
Though we do simplification in above section, however thissimplification is mostly per conditional test. In simplify_cond, aftersimplification, we will check if adjacent conditional test are same, and mergethem if so. Consider following example.
cond [ cond1
val1
cond2
val2
cond3
val1]
It prefers if cond1 and cond3 can be merged. But it is notnecessary. So here don’t try to do that. However, conside another example inbelow:
cond [ cond1
val1
cond2
val2
NOT (AND (cond1, cond2))
Val3 ]
The third condition is always true in its position. We should removethis conditon and make the value associated as default value.
The last example, (eq_attr "att" "v1") and(eq_attr "att" "v2") cannot both be true for certaininstruction at any point of time and hence are complementary. If the term orits complement is present in the tree, it can be replaced with TRUE or FALSE,respectively.
There is one special case: if we see
(and (not (eq_attr "att""v1"))
(eq_attr "att" "v2"))
this can be replaced by (eq_attr "att" "v2").
Pay attention to newexp at line 5135, 5136, and inner_trueat line 5150. At line 5136 and 5150, remember that insert_right_side willinvoke simplify_test_exp_in_temp to simplify the expression constructed.
Also notice that at line 5160 write_test_expr is used to output testingstatement, as we needn’t consider nesting COND case (the testing must be simplejudgement. To accomendate complex case, it can include a COND object as itsvalue). While at line 5165, write_attr_set is used to output associatedattribute value.
5084 static rtx
5085 eliminate_known_true (rtx known_true,rtx exp, int insn_code, int insn_index) ingenattrtab.c
5086 {
5087 rtx term;
5088
5089 known_true = SIMPLIFY_TEST_EXP (known_true, insn_code, insn_index);
5090
5091 if (GET_CODE (known_true) == AND)
5092 {
5093 exp = eliminate_known_true (XEXP (known_true, 0), exp,
5094 insn_code,insn_index);
5095 exp = eliminate_known_true (XEXP (known_true, 1), exp,
5096 insn_code,insn_index);
5097 }
5098 else
5099 {
5100 term = known_true;
5101 exp = simplify_and_tree (exp, &term, insn_code, insn_index);
5102 }
5103
5104 return exp;
5105 }
Notice that pterm passed in simplify_and_tree below by eliminate_known_true,is same as known_truewhich is believed to be evaluated as true for current condition. If pterm orits complement is present in the tree, it can be replaced with TRUE or FALSE,respectively.
2889 static rtx
2890 simplify_and_tree (rtx exp, rtx *pterm,int insn_code, int insn_index) in genattrtab.c
2891 {
2892 rtx left, right;
2893 rtx newexp;
2894 rtx temp;
2895 int left_eliminates_term,right_eliminates_term;
2896
2897 if (GET_CODE (exp) == AND)
2898 {
2899 left = simplify_and_tree (XEXP (exp, 0), pterm, insn_code, insn_index);
2900 right = simplify_and_tree (XEXP (exp, 1), pterm, insn_code, insn_index);
2901 if (left != XEXP (exp, 0) || right != XEXP (exp,1))
2902 {
2903 newexp = attr_rtx(AND, left, right);
2904
2905 exp = simplify_test_exp_in_temp (newexp, insn_code, insn_index);
2906 }
2907 }
2908
2909 else if (GET_CODE (exp) == IOR)
2910 {
2911 /* For the IORcase, we do the same as above, except that we can
2912 only eliminate `term' if both sides ofthe IOR would do so. */
2913 temp = *pterm;
2914 left = simplify_and_tree (XEXP (exp, 0), &temp, insn_code, insn_index);
2915 left_eliminates_term = (temp == true_rtx);
2916
2917 temp = *pterm;
2918 right = simplify_and_tree (XEXP (exp, 1), &temp, insn_code, insn_index);
2919 right_eliminates_term = (temp == true_rtx);
2920
2921 if (left_eliminates_term &&right_eliminates_term)
2922 *pterm = true_rtx;
2923
2924 if (left != XEXP (exp, 0) || right != XEXP (exp,1))
2925 {
2926 newexp = attr_rtx(IOR, left, right);
2927
2928 exp = simplify_test_exp_in_temp (newexp, insn_code, insn_index);
2929 }
2930 }
2931
2932 /* Check forsimplifications. Do some extra checking here since this
2933 routine is called so many times. */
2934
2935 if (exp == *pterm)
2936 return true_rtx;
2937
2938 else if (GET_CODE (exp) == NOT && XEXP (exp,0) == *pterm)
2939 return false_rtx;
2940
2941 else if (GET_CODE (*pterm) == NOT &&exp == XEXP (*pterm, 0))
2942 return false_rtx;
2943
2944 else if (GET_CODE (exp) == EQ_ATTR_ALT&& GET_CODE (*pterm) == EQ_ATTR_ALT)
2945 {
2946 if (attr_alt_subset_p (*pterm, exp))
2947 return true_rtx;
2948
2949 if (attr_alt_subset_of_compl_p (*pterm,exp))
2950 return false_rtx;
2951
2952 if (attr_alt_subset_p (exp, *pterm))
2953 *pterm = true_rtx;
2954
2955 return exp;
2956 }
2957
2958 else if (GET_CODE (exp) == EQ_ATTR &&GET_CODE (*pterm) == EQ_ATTR)
2959 {
2960 if(XSTR (exp, 0) != XSTR (*pterm, 0))
2961 returnexp;
2962
2963 if (! strcmp_check (XSTR (exp, 1), XSTR(*pterm, 1)))
2964 return true_rtx;
2965 else
2966 return false_rtx;
2967 }
2968
2969 else if (GET_CODE (*pterm) == EQ_ATTR&& GET_CODE (exp) == NOT
2970 && GET_CODE (XEXP (exp, 0)) ==EQ_ATTR)
2971 {
2972 if (XSTR (*pterm, 0) != XSTR (XEXP (exp,0), 0))
2973 returnexp;
2974
2975 if (! strcmp_check (XSTR (*pterm, 1), XSTR(XEXP (exp, 0), 1)))
2976 return false_rtx;
2977 else
2978 return true_rtx;
2979 }
2980
2981 else if (GET_CODE (exp) == EQ_ATTR &&GET_CODE (*pterm) == NOT
2982 && GET_CODE (XEXP(*pterm, 0)) == EQ_ATTR)
2983 {
2984 if (XSTR (exp, 0) != XSTR (XEXP(*pterm, 0), 0))
2985 returnexp;
2986
2987 if (! strcmp_check (XSTR (exp, 1), XSTR (XEXP(*pterm, 0), 1)))
2988 return false_rtx;
2989 else
2990 *pterm = true_rtx;
2991 }
2992
2993 else if (GET_CODE (exp) == NOT &&GET_CODE (*pterm) == NOT)
2994 {
2995 if (attr_equal_p (XEXP (exp, 0), XEXP (*pterm, 0)))
2996 return true_rtx;
2997 }
2998
2999 else if (GET_CODE (exp) == NOT)
3000 {
3001 if (attr_equal_p (XEXP (exp, 0), *pterm))
3002 return false_rtx;
3003 }
3004
3005 else if (GET_CODE (*pterm) == NOT)
3006 {
3007 if (attr_equal_p (XEXP (*pterm, 0), exp))
3008 return false_rtx;
3009 }
3010
3011 else if (attr_equal_p (exp, *pterm))
3012 return true_rtx;
3013
3014 return exp;
3015 }
Back write_attr_set, at line 5160, write_test_exprgiven a piece of RTX, prints a C expression to test its truth value. Theparameter exphere is the textexpin write_attr_set – the testing after known true eliminated.
4559 static void
4560 write_test_expr (rtx exp, int flags) in genattrtab.c
4561 {
4562 int comparison_operator = 0;
4563 RTX_CODE code;
4564 struct attr_desc*attr;
4565
4566 /* In order not toworry about operator precedence, surround our part of
4567 the expression with parentheses. */
4568
4569 printf ("(");
4570 code = GET_CODE (exp);
4571 switch (code)
4572 {
4573 /* Binaryoperators. */
4574 case EQ: case NE:
4575 case GE: case GT: case GEU: case GTU:
4576 case LE: case LT: case LEU: case LTU:
4577 comparison_operator = 1;
4578
4579 casePLUS: caseMINUS: caseMULT: caseDIV: caseMOD:
4580 caseAND: caseIOR: caseXOR:
4581 caseASHIFT: caseLSHIFTRT: case ASHIFTRT:
4582 write_test_expr (XEXP (exp, 0), flags | comparison_operator);
4583 switch(code)
4584 {
4585 caseEQ:
4586 printf (" == ");
4587 break;
4588 caseNE:
4589 printf (" != ");
4590 break;
4591 caseGE:
4592 printf (" >= ");
4593 break;
4594 caseGT:
4595 printf (" > ");
4596 break;
4597 caseGEU:
4598 printf (" >= (unsigned) ");
4599 break;
4600 caseGTU:
4601 printf (" > (unsigned) ");
4602 break;
4603 case LE:
4604 printf (" <= ");
4605 break;
4606 caseLT:
4607 printf (" < ");
4608 break;
4609 caseLEU:
4610 printf (" <= (unsigned) ");
4611 break;
4612 caseLTU:
4613 printf (" < (unsigned) ");
4614 break;
4615 casePLUS:
4616 printf (" + ");
4617 break;
4618 caseMINUS:
4619 printf (" - ");
4620 break;
4621 caseMULT:
4622 printf (" * ");
4623 break;
4624 caseDIV:
4625 printf (" / ");
4626 break;
4627 caseMOD:
4628 printf (" %% ");
4629 break;
4630 caseAND:
4631 if (flags & 1)
4632 printf (" & ");
4633 else
4634 printf (" && ");
4635 break;
4636 caseIOR:
4637 if (flags & 1)
4638 printf (" | ");
4639 else
4640 printf (" || ");
4641 break;
4642 case XOR:
4643 printf (" ^ ");
4644 break;
4645 caseASHIFT:
4646 printf (" << ");
4647 break;
4648 caseLSHIFTRT:
4649 caseASHIFTRT:
4650 printf (" >> ");
4651 break;
4652 default:
4653 abort ();
4654 }
4655
4656 write_test_expr (XEXP (exp, 1), flags | comparison_operator);
4657 break;
4658
4659 case NOT:
4660 /* Special-case (not (eq_attrq "alternative""x")) */
4661 if (! (flags & 1) && GET_CODE(XEXP (exp, 0)) == EQ_ATTR
4662 && XSTR (XEXP (exp, 0), 0) == alternative_name)
4663 {
4664 printf ("which_alternative != %s",XSTR (XEXP (exp, 0), 1));
4665 break;
4666 }
4667
4668 /* Otherwise,fall through to normal unary operator. */
4669
4670 /* Unaryoperators. */
4671 case ABS: case NEG:
4672 switch(code)
4673 {
4674 caseNOT:
4675 if (flags & 1)
4676 printf ("~ ");
4677 else
4678 printf ("! ");
4679 break;
4680 caseABS:
4681 printf ("abs ");
4682 break;
4683 caseNEG:
4684 printf ("-");
4685 break;
4686 default:
4687 abort ();
4688 }
4689
4690 write_test_expr (XEXP (exp, 0), flags);
4691 break;
4692
4693 caseEQ_ATTR_ALT:
4694 {
4695 intset = XINT (exp, 0), bit = 0;
4696
4697 if(flags & 1)
4698 fatal ("EQ_ATTR_ALT not valid insidecomparison");
4699
4700 if(!set)
4701 fatal ("Empty EQ_ATTR_ALT should beoptimized out");
4702
4703 if(!(set & (set - 1)))
4704 {
4705 if (!(set & 0xffff))
4706 {
4707 bit += 16;
4708 set >>= 16;
4709 }
4710 if (!(set & 0xff))
4711 {
4712 bit += 8;
4713 set >>= 8;
4714 }
4715 if (!(set & 0xf))
4716 {
4717 bit += 4;
4718 set >>= 4;
4719 }
4720 if (!(set & 0x3))
4721 {
4722 bit += 2;
4723 set >>= 2;
4724 }
4725 if (!(set & 1))
4726 bit++;
4727
4728 printf ("which_alternative %s=%d",
4729 XINT (exp, 1) ? "!" : "=", bit);
4730 }
4731 else
4732 {
4733 printf ("%s((1 <<which_alternative) & 0x%x)",
4734 XINT (exp, 1) ? "!" : "", set);
4735 }
4736 }
4737 break;
4738
4739 /* Comparisontest of an attribute with a value. Most of these will
4740 have been removed by optimization. Handle"alternative"
4741 specially and give error if EQ_ATTRpresent inside a comparison. */
4742 caseEQ_ATTR:
4743 if (flags & 1)
4744 fatal ("EQ_ATTR not valid insidecomparison");
4745
4746 if (XSTR (exp, 0) == alternative_name)
4747 {
4748 printf ("which_alternative == %s",XSTR (exp, 1));
4749 break;
4750 }
4751
4752 attr = find_attr(&XSTR (exp, 0), 0);
4753 if (! attr)
4754 abort ();
4755
4756 /* Now is the time to expand the value of aconstant attribute. */
4757 if (attr->is_const)
4758 {
4759 write_test_expr (evaluate_eq_attr (exp, attr->default_val->value,
4760 -2, -2),
4761 flags);
4762 }
4763 else
4764 {
4765 if (flags & 2)
4766 printf ("attr_%s",attr->name);
4767 else
4768 printf ("get_attr_%s (insn)",attr->name);
4769 printf(" == ");
4770 write_attr_valueq (attr, XSTR (exp, 1));
4771 }
4772 break;
4773
4774 /* Comparison test of flags fordefine_delays. */
4775 case ATTR_FLAG:
4776 if (flags & 1)
4777 fatal ("ATTR_FLAG not valid insidecomparison");
4778 printf("(flags & ATTR_FLAG_%s) != 0", XSTR (exp, 0));
4779 break;
4780
4781 /* See if an operand matches a predicate. */
4782 caseMATCH_OPERAND:
4783 /* If only a mode is given, just ensure themode matches the operand.
4784 If neither a mode nor predicate isgiven, error. */
4785 if (XSTR (exp, 1) == NULL || *XSTR (exp,1) == '\0')
4786 {
4787 if (GET_MODE (exp) == VOIDmode)
4788 fatal ("null MATCH_OPERAND specifiedas test");
4789 else
4790 printf ("GET_MODE (operands[%d]) ==%smode",
4791 XINT (exp,0), GET_MODE_NAME (GET_MODE (exp)));
4792 }
4793 else
4794 printf ("%s (operands[%d],%smode)",
4795 XSTR (exp, 1), XINT (exp,0), GET_MODE_NAME (GET_MODE (exp)));
4796 break;
4797
4798 caseMATCH_INSN:
4799 printf ("%s (insn)", XSTR (exp,0));
4800 break;
4801
4802 /* Constantinteger. */
4803 caseCONST_INT:
4804 printf (HOST_WIDE_INT_PRINT_DEC, XWINT (exp,0));
4805 break;
4806
4807 /* A random Cexpression. */
4808 caseSYMBOL_REF:
4809 printf ("%s", XSTR (exp, 0));
4810 break;
4811
4812 /* The address ofthe branch target. */
4813 caseMATCH_DUP:
4814 printf ("I
4815 NSN_ADDRESSES_SET_P() ? INSN_ADDRESSES (INSN_UID (GET_CODE (operands[%d]) == LABEL_REF ? XEXP(operands[%d], 0) : operands[%d])) : 0",
4816 XINT (exp, 0), XINT (exp, 0), XINT (exp, 0));
4817 break;
4818
4819 case PC:
4820 /* The addressof the current insn. We implement this actually as the
4821 address of the current insn for backwardbranches, but the last
4822 address of the next insn for forward branches,and both with
4823 adjustments that account for the worst-casepossible stretching of
4824 intervening alignments between this insn andits destination. */
4825 printf("insn_current_reference_address (insn)");
4826 break;
4827
4828 caseCONST_STRING:
4829 printf ("%s", XSTR (exp, 0));
4830 break;
4831
4832 caseIF_THEN_ELSE:
4833 write_test_expr (XEXP (exp, 0), flags & 2);
4834 printf (" ? ");
4835 write_test_expr (XEXP (exp, 1), flags | 1);
4836 printf (" : ");
4837 write_test_expr (XEXP (exp, 2), flags | 1);
4838 break;
4839
4840 default:
4841 fatal ("bad RTX code `%s' inattribute calculation\n",
4842 GET_RTX_NAME (code));
4843 }
4844
4845 printf (")");
4846 }
We can see the output gen_attr_* functions in insn-attrtab.c whichgenerated by this tool. Generally, the functions output will be in form asfollowing (content in green is not output).
get_attr_`attr-name`(rtx insn ATTRIBUTE_UNUSED)
{
switch(recog_memoized (insn))
{
case insn-code-n: //first attribute value expression
case insn-code-p:
… // other insn for the same attribute value
extract_constrain_insn_cached(insn); // usedaccording to attr characteristic.
extract_insn_cached(insn); // used according to attr characteristic.
if(`attr-test-1` ) // for attribute value of cond
{
returnattr-val-1;
}
else if (…) // for attribute value of cond
…
else // for attribute value of cond
…
break;
… // other insn
break;
case insn-code-s: // second attribute valueexpression
… // other insn for the same attribute value
extract_constrain_insn_cached(insn); // usedaccording to attr characteristic.
extract_insn_cached(insn); //used according to attr characteristic.
returnattr-val-q; // for simple attrinute value
break;
}
}