GCC后端及汇编发布(32)

9.6.1.4.    输出属性

虽然我们已经构建了属性相关的数据,为了流水线危险识别器的使用,它们需要被输出为接受指令rtx对象,并返回指令的属性值的函数。这些函数被输出到文件insn-attrtab.c中,并将作为gcc源代码的一部分,来产生执行映像。

 

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     }

 

上面在6197行,is_special为需要特殊处理的属性所设置——它们将不产生普通的属性值提取器。下面是设置了is_special的属性的列表:

*delay_type(它是整个系统范围内的单件)

*delay_`delay-no`_`slot-no`(对于每个define_delay 模式,它对应每个槽(slot))

*annul_true_`delay-no`_`slot-no`(对于每个define_delay 模式,它对应每个槽(slot))

*annul_false_`delay-no`_`slot-no`(对于每个define_delay 模式,它对应每个槽(slot))

*`unit-name`_cost_`op-num`(发布指令在单元上的代价)

*`unit-name`_block_`op-num`(发布指令在单元上的延迟)

*`unit-name`_cases(单件,用于所有单元的case表达式,参见expand_units

对于包含常量内容的属性,设置is_const

在6203行,INSN_ATLS_FUNC_NAME被定义为“insn_alts”,其关联的属性在make_insn_alts_attr中构建,这个属性描述了define_insn_reservation中替代的数目。

write_attr_get对给定的指令写出提取属性值的函数。

 

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 }

 

在5037行,注意write_attr_set为包含常量,并且其名字开头没有‘*’的属性所调用。不过在进入write_attr_get之前,这种类型的属性已经被滤掉了(参见main的6197行)。write_attr_set将不会在这里被调用。

在5047行的FFS代表“查找第一个设置比特”的操作。在这里,对于使用FFS最多的指令,我们不尝试识别它。在4版本,移走了对于FFS的特殊处理。不管怎样,对于其它指令,识别是必须的。看到在5067行输出的recog_memoized,这个函数是由genrecog(参见genrecog工具)输出的recog的一个封装。其返回值是输入指令对象的指令编码。

对于每个属性值,write_attr_case输出其计算过程。

 

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 }

 

上面在5211行,只要该属性具有在某些汇编语句中设置的值,就要设置域has_asm_insn(不管在其他多少地方,这个值被重新设置)。对于汇编语句,其指令编码为-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 testexpression 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 }

 

虽然我们在上面章节中进行了简化,不过这个简化基本上是对应条件测试的。在simplify_cond中,在简化之后,我们将检查相邻的条件测试是否相同,如果相同就合并它们。考虑以下例子。

cond [ cond1

           val1

      cond2

       val2

      cond3

           val1]

如果cond1能与cond3合并就再好不过了。不过这不是必然的。因此这里不尝试这样做。那么,考虑以下例子:

cond [ cond1

           val1

      cond2

       val2

      NOT (AND (cond1, cond2))

           Val3 ]

第三个条件在其位置上总是true。我们应该移除这个条件,并把关联的值作为缺省值。

最后的例子,(eq_attr "att""v1")及(eq_attr"att" "v2"),在任一点上,都不可能同时为true,因而是互补的。如果这一项或其互补出现在树中,它可以为TRUE或FALSE所分别替代。

还有一个特殊的案例:如果我们看到

(and (not (eq_attr"att" "v1"))

     (eq_attr "att" "v2"))

这可以为(eq_attr "att""v2")所替代。

注意5135,5136行的newexp,以及5150行的inner_true。在5136及5150行,记得insert_right_side将在simplify_test_exp_in_temp中调用来简化所构造的表达式。

同样注意在5160行,write_test_expr被用于输出测试语句,因为我们不需要考虑嵌套的COND的情形(这个测试必须是简单的判断。为了包容复杂的情形,它可以包括一个COND对象作为其值)。而在5165行,write_attr_set则用于输出关联的属性值。

 

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 }

 

注意由下面eliminate_known_true传给simplify_and_treepterm等于known_true,对象known_true被确信为,在当前条件下,其评估为true。如果pterm或其互补出现在这个树里,它可以分别为TRUE或FALSE所替代。

 

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 }

 

回到write_attr_set,在5160行,write_test_expr给定一段RTX,输出一个C表达式来测试其真假值。在这里,在write_attr_set中参数exptextexp——消除已知真值后的测试。

 

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         caseLE:

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         caseXOR:

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    caseABS:  caseNEG:

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 forbackward branches, 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 }

 

我们可以看到在insn-attrtab.c中,由这个工具输出的gen_attr_*函数。通常,输出的函数将是如下的形式(绿色的内容不是输出的)。

 

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;

  }

}

你可能感兴趣的:(汇编,struct,gcc,tree,delay,subroutine)