现在所有的表已经就绪。事实上,我们可以看到状态与触发迁移的指令间的关系,以及指令间资源竞争关系(通过发布延迟)都被封装入这些表中。同时指令间潜在的依赖关系(通过阻塞代价及就绪代价),以及某个branch/jump指令输出的delay slot的细节,都已经以属性提取函数的形式,连同其它工具生成的属性访问器,输出了。
现在可以为流水线危险识别器生成接口了。
write_automata (continued)
9885 output_chip_definitions ();
9886 output_max_insn_queue_index_def();
9887 output_internal_min_issue_delay_func();
9888 output_internal_trans_func();
9889 /* Cache of insndfa codes: */
9890 fprintf (output_file, "\nstatic int *%s;\n",DFA_INSN_CODES_VARIABLE_NAME);
9891 fprintf (output_file, "\nstatic int %s;\n\n",
9892 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9893 output_dfa_insn_code_func();
9894 output_trans_func();
9895 fprintf (output_file, "\n#if %s\n\n",AUTOMATON_STATE_ALTS_MACRO_NAME);
9896 output_internal_state_alts_func();
9897 output_state_alts_func();
9898 fprintf (output_file, "\n#endif /* #if %s*/\n\n",
9899 AUTOMATON_STATE_ALTS_MACRO_NAME);
9900 output_min_issue_delay_func();
9901 output_internal_dead_lock_func();
9902 output_dead_lock_func();
9903 output_size_func();
9904 output_internal_reset_func();
9905 output_reset_func();
9906 output_min_insn_conflict_delay_func();
9907 output_internal_insn_latency_func();
9908 output_insn_latency_func();
9909 output_print_reservation_func();
9910 /* Output functionget_cpu_unit_code. */
9911 fprintf (output_file, "\n#if %s\n\n",CPU_UNITS_QUERY_MACRO_NAME);
9912 output_get_cpu_unit_code_func();
9913 output_cpu_unit_reservation_p();
9914 fprintf (output_file, "\n#endif /* #if %s*/\n\n",
9915 CPU_UNITS_QUERY_MACRO_NAME);
9916 output_dfa_clean_insn_cache_func();
9917 output_dfa_start_func();
9918 output_dfa_finish_func();
为了找出下一个运行的合适的指令,流水线危险器维护一个伪CPU来模拟指令的发布,这由output_chip_definitions来定义。
7413 static void
7414 output_chip_definitions (void) in genautomata.c
7415 {
7416 automaton_tautomaton;
7417
7418 fprintf (output_file, "struct %s\n{\n",CHIP_NAME);
7419 for(automaton = description->first_automaton;
7420 automaton != NULL;
7421 automaton = automaton->next_automaton)
7422 {
7423 fprintf (output_file, " ");
7424 output_state_member_type (output_file,automaton);
7425 fprintf (output_file, " ");
7426 output_chip_member_name (output_file,automaton);
7427 fprintf (output_file, ";\n");
7428 }
7429 fprintf (output_file, "};\n\n");
7430 #if 0
7431 fprintf (output_file, "static struct %s%s;\n\n", CHIP_NAME, CHIP_NAME);
7432 #endif
7433 }
在这里,输出以下内容(绿色部分不是工具产生的),假定自动机的状态的数目不会超过65536,并且自动机没有命名。
struct DFA_chip
{
unsigned short automaton_state_0;
… // variables for other automatons
}
这个伪CPU的定义十分简单,它仅包含保存自动机状态的变量。识别器的复杂性隐藏在状态及连接它们的arc后面(参考自动机的生成)。
虽然观点不一样,类似于define_function_unit,确定给定指令的发布延迟也是自动机同样重要的部分。在这里,首先找出在该系统中最大的休眠时间。这很简单。
8110 static void
8111 output_max_insn_queue_index_def (void) in genautomata.c
8112 {
8113 int i, max, latency;
8114 decl_t decl;
8115
8116 max = description->max_insn_reserv_cycles;
8117 for (i = 0; i < description->decls_num; i++)
8118 {
8119 decl = description->decls [i];
8120 if(decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8121 {
8122 latency = DECL_INSN_RESERV(decl)->default_latency;
8123 if (latency > max)
8124 max = latency;
8125 }
8126 else if (decl->mode == dm_bypass)
8127 {
8128 latency = DECL_BYPASS (decl)->latency;
8129 if (latency > max)
8130 max = latency;
8131 }
8132 }
8133 for (i = 0; (1 << i) <= max; i++)
8134 ;
8135 if(i < 0)
8136 abort ();
8137 fprintf (output_file, "\nint max_insn_queue_index =%d;\n\n", (1 << i) - 1);
8138 }
在8122行,default_latency被定义在define_insn_reservation模式里,来描述指令的休眠时间。另外,我们已经看到define_bypass被用来描述给定指令对(instruction pair)休眠时间的例外。output_max_insn_queue_index_def找出已经遇到的最大休眠时间并输出这个值。
8235 static void
8236 output_internal_min_issue_delay_func (void) ingenautomata.c
8237 {
8238 fprintf (output_file,
8239 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
8240 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8241 CHIP_NAME, CHIP_PARAMETER_NAME);
8242 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
8243 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
8244 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8245 output_insn_code_cases(output_automata_list_min_issue_delay_code);
8246 fprintf (output_file,
8247 "\n default:\n %s = -1;\n break;\n }\n",
8248 RESULT_VARIABLE_NAME);
8249 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
8250 fprintf (output_file, "}\n\n");
8251 }
在输出发布延迟表一节,我们已经输出了表示发布延迟的表。对于某些现代CPU,它们包含一些可以并行执行的功能单元,或换句话来说多个指令可能可以被同时发布。在机器描述文件中,这样的功能单元将被定义作自动机。那么在自动机的生成一节,状态及表示状态迁移的arc,已经为这些自动机所创建。因为这些自动机可能被同时运行,所以给定指令的最小发布延迟应该是,该指令在这些自动机上最小发布延迟中最大的一个。
8134 static void
8135 output_insn_code_cases (void(*output_automata_list_code) in genautomata.c
8136 (automata_list_el_t))
8137 {
8138 decl_t decl, decl2;
8139 int i, j;
8140
8141 for (i = 0; i < description->decls_num; i++)
8142 {
8143 decl = description->decls [i];
8144 if (decl->mode == dm_insn_reserv)
8145 DECL_INSN_RESERV (decl)->processed_p =FALSE;
8146 }
8147 for (i = 0; i< description->decls_num;i++)
8148 {
8149 decl = description->decls [i];
8150 if (decl->mode == dm_insn_reserv
8151 && !DECL_INSN_RESERV(decl)->processed_p)
8152 {
8153 for (j =i; j < description->decls_num;j++)
8154 {
8155 decl2 = description->decls [j];
8156 if (decl2->mode == dm_insn_reserv
8157 && (DECL_INSN_RESERV(decl2)->important_automata_list
8158 == DECL_INSN_RESERV(decl)->important_automata_list))
8159 {
8160 DECL_INSN_RESERV(decl2)->processed_p = TRUE;
8161 fprintf (output_file, " case %d: /* %s */\n",
8162 DECL_INSN_RESERV(decl2)->insn_num,
8163 DECL_INSN_RESERV(decl2)->name);
8164 }
8165 }
8166 (*output_automata_list_code)
8167 (DECL_INSN_RESERV(decl)->important_automata_list);
8168 }
8169 }
8170 }
在8157行,important_automata_list记录了目前为止所产生的,涉及该指令的自动机。因此在8147及8153行的FOR循环找出在同一个自动机列表中的所有的指令,作为case的操作数。
8184 static void
8185 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list) in genautomata.c
8186 {
8187 automata_list_el_t el;
8188 automaton_t automaton;
8189
8190 for (el = automata_list; el != NULL; el =el->next_automata_list_el)
8191 {
8192 automaton = el->automaton;
8193 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8194 output_min_issue_delay_vect_name (output_file,automaton);
8195 fprintf (output_file,
8196 (automaton->min_issue_delay_table_compression_factor != 1
8197 ? " [(" : " ["));
8198 output_translate_vect_name (output_file,automaton);
8199 fprintf (output_file, " [%s] + ",INTERNAL_INSN_CODE_NAME);
8200 fprintf (output_file, "%s->",CHIP_PARAMETER_NAME);
8201 output_chip_member_name (output_file,automaton);
8202 fprintf (output_file, " * %d",automaton->insn_equiv_classes_num);
8203 if(automaton->min_issue_delay_table_compression_factor == 1)
8204 fprintf (output_file, "];\n");
8205 else
8206 {
8207 fprintf (output_file, ") /%d];\n",
8208 automaton->min_issue_delay_table_compression_factor);
8209 fprintf (output_file, " %s = (%s >> (8 - (",
8210 TEMPORARY_VARIABLE_NAME,TEMPORARY_VARIABLE_NAME);
8211 output_translate_vect_name (output_file,automaton);
8212 fprintf
8213 (output_file, " [%s] %% %d + 1) * %d)) &%d;\n",
8214 INTERNAL_INSN_CODE_NAME,
8215 automaton->min_issue_delay_table_compression_factor,
8216 8 /automaton->min_issue_delay_table_compression_factor,
8217 (1 << (8 / automaton->min_issue_delay_table_compression_factor))
8218 - 1);
8219 }
8220 if (el == automata_list)
8221 fprintf (output_file, " %s = %s;\n",
8222 RESULT_VARIABLE_NAME,TEMPORARY_VARIABLE_NAME);
8223 else
8224 {
8225 fprintf (output_file, " if (%s > %s)\n",
8226 TEMPORARY_VARIABLE_NAME,RESULT_VARIABLE_NAME);
8227 fprintf (output_file, " %s = %s;\n",
8228 RESULT_VARIABLE_NAME,TEMPORARY_VARIABLE_NAME);
8229 }
8230 }
8231 fprintf (output_file, " break;\n\n");
8232 }
对于出现在同一个自动机集合中的指令,output_automata_list_min_issue_delay_code将输出以下的代码(假定min_issue_delay_table_compression_factor不等于1)。现在我们得到如下internal_min_issue_delay的定义(红色部分不是工具输出的)。
1 static int
2 internal_min_issue_delay (int insn_code,struct DFA_chip * chip ATTRIBUTE_UNUSED)
3 {
4 int temp ATTRIBUTE_UNUSED;
5 int res =-1;
6
7 switch (insn_code)
8 {
9 case insn-x: // for instructions reserve same automaton list.
10 …
11 case insn-y:
12 // forfirst automaton
13 temp = min_issue_delay_0[(translate_0[insn_code] +
14 chip->automaton_state_0 * `insn_equiv_classes_num0`)/
15 `min_issue_delay_table_compression_factor0`];
16 temp = (temp >> (8–(translate_0[insn_code]%%`min_issue_delay_table_compression_factor0`
17 + 1) * 8 / `min_issue_delay_table_compression_factor0`))& -1;
18 res =temp;
19
20 // for other automaton n, not appear in ourassuming example
21 temp =min_issue_delay_n [(translate_n[insn_code] +
22 chip->automaton_state_n * `insn_equiv_classes_numn`)/
23 `min_issue_delay_table_compression_factorn`];
24 temp = (temp >>(8–(translate_n[insn_code]%%`min_issue_delay_table_compression_factorn`
25 + 1) * 8 / `min_issue_delay_table_compression_factorn`))& -1;
26 if(temp > res)
27 res = temp;
28 …
29 break;
30 … //instructions reserve other automaton list, not appear in our assuming example
31 default:
32 res =-1;
33 break;
34 }
35 return res;
36 }
上面vector translate_`x`把指令编码映射到自动机的等效指令类别编码。在这里,我们假定min_issue_delay_table_compression_factor`x`大于1,那么多个最小发布延迟可以被保存入一个字节中。24行获取了对应的数据,看到计算得到的位置,必须与填充时得到的位置相同(参考输出发布延迟表)。看到这个函数,给定一条指令,找出在该指令所使用的自动机中,所面临的最大的最小发布延迟。
接下来,我们需要输出用于状态迁移的函数——自动机的引擎!
8348 static void
8349 output_internal_trans_func (void) ingenautomata.c
8350 {
8351 fprintf (output_file,
8352 "static int\n%s (int %s, struct %s*%s ATTRIBUTE_UNUSED)\n",
8353 INTERNAL_TRANSITION_FUNC_NAME,INTERNAL_INSN_CODE_NAME,
8354 CHIP_NAME, CHIP_PARAMETER_NAME);
8355 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n",TEMPORARY_VARIABLE_NAME);
8356 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8357 output_insn_code_cases(output_automata_list_transition_code);
8358 fprintf (output_file, "\n default:\n return -1;\n }\n");
8359 fprintf (output_file, "}\n\n");
8360 }
至于output_insn_code_cases,我们已经看到它将找出具有相同自动机列表的指令,并且output_automata_list_transition_code为每个有资格的指令组所调用。
8255 static void
8256 output_automata_list_transition_code (automata_list_el_t automata_list) ingenautomata.c
8257 {
8258 automata_list_el_t el, next_el;
8259
8260 fprintf (output_file, " {\n");
8261 if (automata_list != NULL && automata_list->next_automata_list_el!= NULL)
8262 for (el = automata_list;; el = next_el)
8263 {
8264 next_el = el->next_automata_list_el;
8265 if (next_el == NULL)
8266 break;
8267 fprintf (output_file, " ");
8268 output_state_member_type (output_file,el->automaton);
8269 fprintf (output_file, " ");
8270 output_temp_chip_member_name (output_file,el->automaton);
8271 fprintf (output_file,";\n");
8272 }
8273 for (el = automata_list; el != NULL; el =el->next_automata_list_el)
8274 if (comb_vect_p(el->automaton->trans_table))
8275 {
8276 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8277 output_trans_base_vect_name(output_file,el->automaton);
8278 fprintf (output_file, " [%s->",CHIP_PARAMETER_NAME);
8279 output_chip_member_name (output_file,el->automaton);
8280 fprintf (output_file, "] + ");
8281 output_translate_vect_name(output_file,el->automaton);
8282 fprintf (output_file, " [%s];\n",INTERNAL_INSN_CODE_NAME);
8283 fprintf (output_file, " if (");
8284 output_trans_check_vect_name(output_file,el->automaton);
8285 fprintf (output_file, " [%s] !=%s->",
8286 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
8287 output_chip_member_name (output_file,el->automaton);
8288 fprintf (output_file, ")\n");
8289 fprintf (output_file, " return %s (%s, %s);\n",
8290 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME,INTERNAL_INSN_CODE_NAME,
8291 CHIP_PARAMETER_NAME);
8292 fprintf (output_file, " else\n");
8293 fprintf (output_file, " ");
8294 if (el->next_automata_list_el != NULL)
8295 output_temp_chip_member_name (output_file,el->automaton);
8296 else
8297 {
8298 fprintf (output_file, "%s->",CHIP_PARAMETER_NAME);
8299 output_chip_member_name (output_file,el->automaton);
8300 }
8301 fprintf (output_file, " = ");
8302 output_trans_comb_vect_name(output_file,el->automaton);
8303 fprintf (output_file, " [%s];\n",TEMPORARY_VARIABLE_NAME);
8304 }
8305 else
8306 {
8307 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8308 output_trans_full_vect_name(output_file,el->automaton);
8309 fprintf (output_file, " [");
8310 output_translate_vect_name(output_file,el->automaton);
8311 fprintf (output_file, " [%s] + ",INTERNAL_INSN_CODE_NAME);
8312 fprintf (output_file, "%s->",CHIP_PARAMETER_NAME);
8313 output_chip_member_name (output_file,el->automaton);
8314 fprintf (output_file, " * %d];\n",
8315 el->automaton->insn_equiv_classes_num);
8316 fprintf (output_file, " if (%s >= %d)\n",
8317 TEMPORARY_VARIABLE_NAME,el->automaton->achieved_states_num);
8318 fprintf (output_file, " return %s (%s, %s);\n",
8319 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8320 CHIP_PARAMETER_NAME);
8321 fprintf (output_file, " else\n ");
8322 if (el->next_automata_list_el != NULL)
8323 output_temp_chip_member_name (output_file,el->automaton);
8324 else
8325 {
8326 fprintf (output_file, "%s->",CHIP_PARAMETER_NAME);
8327 output_chip_member_name (output_file,el->automaton);
8328 }
8329 fprintf (output_file, " = %s;\n",TEMPORARY_VARIABLE_NAME);
8330 }
8331 if(automata_list != NULL && automata_list->next_automata_list_el !=NULL)
8332 for (el = automata_list;; el = next_el)
8333 {
8334 next_el = el->next_automata_list_el;
8335 if (next_el == NULL)
8336 break;
8337 fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
8338 output_chip_member_name (output_file,el->automaton);
8339 fprintf (output_file, " = ");
8340 output_temp_chip_member_name (output_file,el->automaton);
8341 fprintf (output_file, ";\n");
8342 }
8343 fprintf (output_file, " return -1;\n");
8344 fprintf (output_file, " }\n");
8345 }
我们得到如下的internal_state_transition的定义(红色部分不是工具输出的),假定向量transition_x没有被合并(transition_x参考输出状态迁移表)。
1 static int
2 internal_state_transition (intinsn_code, struct DFA_chip *chip ATTRIBUTE_UNUSED)
3 {
4 int temp ATTRIBUTE_UNUSED;
5 switch(insn_code)
6 {
7 caseinsn-x: // for instructions reserve same automaton list.
8 …
9 caseinsn-y:
10 {
11 unsigned short _automaton_state_0;
12 … // declaration for other automatons
13 temp= transitions_0 [translate_0 [insn_code] + chip->automaton_state_0 *
14 ` insn_equiv_classes_num0`];
15 if (temp >= ` achieved_states_num0` )
16 return internal_min_issue_delay(insn_code, chip);
17 else
18 _automaton_state_0 = transitions_0 [temp];
19 … // statement for other automatons
20 //statement for last automatons
21 temp= transitions_n [translate_n [insn_code] + chip->automaton_state_n *
22 ` insn_equiv_classes_numn`];
23 if (temp >= ` achieved_states_numn` )
24 return internal_min_issue_delay(insn_code, chip);
25 else
26 chip->automaton_state_n = transitions_n [temp];
27
28 chip->automaton_state_0 = _automaton_state_0;
29 … // statement for other automatons
30 return-1;
31 }
32 … // instructions reserve other automaton list, not appear inour assuming example
33 default:
34 return -1;
35 }
36 }
向量translate_x与自动机一一对应。它把指令编码映射到指令等效类别的编码。并且向量transition_x以指令等效类别编码为索引记录了目标状态(记得相同等效类别的指令具有相同的状态迁移)。注意到transition_x的未填充的成员被undefined_vect_el_value所占据,在output_trans_table中它被定义为achieved_states_num。在这个情形下,这意味着该指令不能发布,并且如上面23行所示,internal_min_issue_delay被调用来找出该指令的最小发布延迟。
给定一条指令,在系统中直接使用它并不方便,因为经过编译遍的处理,作为优化的结果它会改变形式。因此这个系统为每条指令分配唯一的编号。在编译过程中,它是系统范围内指令的识别符。dfa_insn_code,给定一条指令,返回其指令编号(编码)。
8392 static void
8393 output_dfa_insn_code_func (void) ingenautomata.c
8394 {
8395 /* Emacs c-modegets really confused if there's a { or } in column 0
8396 inside a string, so don't do that. */
8397 fprintf (output_file, "\
8398 static void\n\
8399 dfa_insn_code_enlarge (int uid)\n\
8400 {\n\
8401 int i = %s;\n\
8402 %s = 2 * uid;\n\
8403 %s = xrealloc (%s,\n\
8404 %s * sizeof(int));\n\
8405 for (; i <%s; i++)\n\
8406 %s[i] = -1;\n}\n\n",
8407 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8408 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8409 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8410 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8411 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8412 DFA_INSN_CODES_VARIABLE_NAME);
8413 fprintf (output_file, "\
8414 static inlineint\n%s (rtx %s)\n\
8415 {\n\
8416 int uid = INSN_UID (%s);\n\
8417 int %s;\n\n",
8418 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
8419 INSN_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME);
8420
8421 fprintf (output_file,
8422 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
8423 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8424 fprintf (output_file, " %s = %s[uid];\n",
8425 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8426 fprintf (output_file, "\
8427 if (%s < 0)\n\
8428 {\n\
8429 %s = %s (%s);\n\
8430 %s[uid] = %s;\n\
8431 }\n",
8432 INTERNAL_INSN_CODE_NAME,
8433 INTERNAL_INSN_CODE_NAME,
8434 INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
8435 DFA_INSN_CODES_VARIABLE_NAME, INTERNAL_INSN_CODE_NAME);
8436 fprintf (output_file, " return %s;\n}\n\n",INTERNAL_INSN_CODE_NAME);
8437 }
输出函数看起来如下。
1 static void
2 dfa_insn_code_enlarge (intuid)
3 {
4 int i = dfa_insn_codes_length;
5 dfa_insn_codes_length= 2 * uid;
6 dfa_insn_codes = xrealloc (dfa_insn_codes,
7 dfa_insn_codes_length *sizeof(int));
8 for (; i< dfa_insn_codes_length; i++)
9 dfa_insn_codes[i]= -1;
10 }
11
12 staticinline int
13 dfa_insn_code (rtx insn)
14 {
15 int uid = INSN_UID (insn);
16 int insn_code;
17
18 if (uid >= dfa_insn_codes_length)
19 dfa_insn_code_enlarge (uid);
20 insn_code = dfa_insn_codes [uid];
21 if (insn_code < 0)
22 {
23 insn_code = internal_dfa_insn_code (insn);
24 dfa_insn_codes [uid] = insn_code;
25 }
26 return insn_code;
27 }
上面在23行,internal_dfa_insn_code由属性“*internal_dfa_insn_code”所产生。这个属性的内容是一个包含了所有预订指令的COND,其中每一个跳转的测试部分来自预订模式定义的测试部分,而其内容是指令编号。
在输出函数state_transition一节,产生了internal_state_transition,它接受insn_code及状态作为参数。不过它不是可以接受指令本身的理想的接口,这里对它进行进一步封装。
8440 static void
8441 output_trans_func (void) in genautomata.c
8442 {
8443 fprintf (output_file, "int\n%s (%s %s, rtx%s)\n",
8444 TRANSITION_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8445 INSN_PARAMETER_NAME);
8446 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8447 output_internal_insn_code_evaluation(INSN_PARAMETER_NAME,
8448 INTERNAL_INSN_CODE_NAME,-1);
8449 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8450 INTERNAL_TRANSITION_FUNC_NAME,INTERNAL_INSN_CODE_NAME, STATE_NAME);
8451 }
下面是输出的函数。
1 int
2 state_transition(state_t state, rtx insn)
3 {
4 intinsn_code;
5 if (insn!= 0)
6 {
7 insn_code = dfa_insn_code (insn);
8 if(insn_code > DFA__ADVANCE_CYCLE)
9 return -1;
10 }
11 else
12 insn_code = DFA__ADVANCE_CYCLE;
13 return internal_state_transition(insn_code, state);
14 }
我们已经看到state_alts域记录了指定状态上指定指令的非确定性程度,在这里输出的函数用于调试目的。
8515 static void
8516 output_internal_state_alts_func (void) n genautomata.c
8517 {
8518 fprintf (output_file,
8519 "static int\n%s (int %s, struct %s *%s)\n",
8520 INTERNAL_STATE_ALTS_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8521 CHIP_NAME, CHIP_PARAMETER_NAME);
8522 fprintf (output_file, "{\n int %s;\n", RESULT_VARIABLE_NAME);
8523 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8524 output_insn_code_cases(output_automata_list_state_alts_code);
8525 fprintf (output_file,
8526 "\n default:\n %s = 0;\n break;\n }\n",
8527 RESULT_VARIABLE_NAME);
8528 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
8529 fprintf (output_file, "}\n\n");
8530 }
同样指令被依据所预订的自动机列表来分组。
8455 static void
8456 output_automata_list_state_alts_code (automata_list_el_t automata_list) in genautomata.c
8457 {
8458 automata_list_el_t el;
8459 automaton_t automaton;
8460
8461 fprintf (output_file," {\n");
8462 for (el = automata_list; el != NULL; el =el->next_automata_list_el)
8463 if (comb_vect_p(el->automaton->state_alts_table))
8464 {
8465 fprintf (output_file, " int %s;\n",TEMPORARY_VARIABLE_NAME);
8466 break;
8467 }
8468 for (el = automata_list; el != NULL; el =el->next_automata_list_el)
8469 {
8470 automaton = el->automaton;
8471 if (comb_vect_p(automaton->state_alts_table))
8472 {
8473 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8474 output_state_alts_base_vect_name (output_file,automaton);
8475 fprintf (output_file, " [%s->",CHIP_PARAMETER_NAME);
8476 output_chip_member_name (output_file,automaton);
8477 fprintf (output_file, "] + ");
8478 output_translate_vect_name(output_file,automaton);
8479 fprintf (output_file, " [%s];\n",INTERNAL_INSN_CODE_NAME);
8480 fprintf (output_file, " if (");
8481 output_state_alts_check_vect_name(output_file,automaton);
8482 fprintf (output_file, " [%s] !=%s->",
8483 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
8484 output_chip_member_name (output_file,automaton);
8485 fprintf (output_file, ")\n");
8486 fprintf (output_file, " return 0;\n");
8487 fprintf (output_file, " else\n");
8488 fprintf (output_file,
8489 (el == automata_list
8490 ? " %s = " : " %s += "),
8491 RESULT_VARIABLE_NAME);
8492 output_state_alts_comb_vect_name (output_file,automaton);
8493 fprintf (output_file, " [%s];\n",TEMPORARY_VARIABLE_NAME);
8494 }
8495 else
8496 {
8497 fprintf (output_file,
8498 (el == automata_list
8499 ? "\n %s = " : " %s += "),
8500 RESULT_VARIABLE_NAME);
8501 output_state_alts_full_vect_name (output_file,automaton);
8502 fprintf (output_file, " [");
8503 output_translate_vect_name(output_file,automaton);
8504 fprintf (output_file, " [%s] + ",INTERNAL_INSN_CODE_NAME);
8505 fprintf (output_file, "%s->",CHIP_PARAMETER_NAME);
8506 output_chip_member_name (output_file,automaton);
8507 fprintf (output_file, " * %d];\n",
8508 automaton->insn_equiv_classes_num);
8509 }
8510 }
8511 fprintf (output_file, " break;\n }\n\n");
8512 }
输出的函数看起来如下(红色部分不是工具输出的)。
1 static int
2 internal_state_alts (intinsn_code, struct DFA_chip *chip)
3 {
4 int res;
5 switch(insn_code)
6 {
7 caseinsn-x: // for instructions reserve same automaton list.
8 …
9 caseinsn-y:
10 temp = base_state_alts_0[chip->automaton_state_0]+ translate_0[insn_code];
11 if (check_state_alts_0[temp] != chip->automaton_state_0)
12 return 0;
13 else
14 res = state_alts_0[temp];
15 … // for other automaton in list, notpresent in our example
16 //last automaton in list, not present in our example
17 temp = base_state_alts_n[chip->automaton_state_n]+ translate_n[insn_code];
18 if (check_state_alts_n[temp] != chip->automaton_state_n)
19 return 0;
20 else
21 res += state_alts_n[temp];
22 break;
23 … // instructions reserve other automaton list, notappear in our assuming example
24 default:
25 res = 0;
26 break;
27 }
28 return res;
29 }
向量state_alts_`n`记录了预订替代的数目,它们可以用于从给定状态由给定指令触发的迁移。internal_state_alts计算出给定指令的自动机列表的预订替代的总数。我们已经看到在输出函数internal_state_transition(参见输出函数internal_state_transition一节)里,chip的automaton_state_`x`保存了该指令的等效类别编号,这也同样记录在check_state_alts_`x`里,如果预订替代数目出现在state_alts_`n`中。看到在这里我们假定使用合并向量。
接下来,需要输出internal_state_alts的一个封装。
8533 static void
8534 output_state_alts_func (void) in genautomata.c
8535 {
8536 fprintf (output_file, "int\n%s (%s, %s)\n\t%s%s;\n\trtx %s;\n",
8537 STATE_ALTS_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
8538 STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
8539 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8540 output_internal_insn_code_evaluation(INSN_PARAMETER_NAME,
8541 INTERNAL_INSN_CODE_NAME,0);
8542 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8543 INTERNAL_STATE_ALTS_FUNC_NAME,INTERNAL_INSN_CODE_NAME, STATE_NAME);
8544 }
8375 static void
8376 output_internal_insn_code_evaluation (const char *insn_name, ingenautomata.c
8377 const char *insn_code_name,
8378 int code)
8379 {
8380 fprintf (output_file, "\n if (%s != 0)\n {\n", insn_name);
8381 fprintf (output_file, " %s = %s (%s);\n", insn_code_name,
8382 DFA_INSN_CODE_FUNC_NAME, insn_name);
8383 fprintf (output_file, " if (%s > %s)\n return %d;\n",
8384 insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
8385 fprintf (output_file, " }\n else\n %s = %s;\n\n",
8386 insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
8387 }
至于这个输出函数,其定义如下。
1 int
2 state_alts (state,insn)
3 state_tstate;
4 rtx insn;
5 {
6 intinsn_code;
7 if (insn!= 0)
8 {
9 insn_code = dfa_insn_code (insn);
10 if (insn_code > DFA__ADVANCE_CYCLE)
11 return 0;
12 }
13 else
14 insn_code = DFA__ADVANCE_CYCLE;
15 return internal_state_alts(insn_code, state);
16 }
DFA__ADVANCE_CYCLE已经被定义作指令的数目(指令编号advance_cycle_insn_decl)。注意到insn_code也是从0到指令数目减一的序列号。
这个函数是对internal_min_issue_delay(参考输出函数internal_min_issue_delay)的封装。
8547 static void
8548 output_min_issue_delay_func (void) ingenautomata.c
8549 {
8550 fprintf (output_file, "int\n%s (%s %s, rtx%s)\n",
8551 MIN_ISSUE_DELAY_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8552 INSN_PARAMETER_NAME);
8553 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8554 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
8555 fprintf (output_file, " %s = %s (%s);\n",INTERNAL_INSN_CODE_NAME,
8556 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8557 fprintf (output_file, " if (%s > %s)\n return 0;\n",
8558 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8559 fprintf (output_file, " }\n else\n %s = %s;\n",
8560 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8561 fprintf (output_file, "\n return %s (%s, %s);\n",
8562 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME,INTERNAL_INSN_CODE_NAME,
8563 STATE_NAME);
8564 fprintf (output_file, "}\n\n");
8565 }
1 int
2 min_issue_delay(state_t state, rtx insn)
3 {
4 intinsn_code;
5 if (insn!= 0)
6 {
7 insn_code = dfa_insn_code (insn);
8 if(insn_code > DFA__ADVANCE_CYCLE)
9 return 0;
10 }
11 else
12 insn_code = DFA__ADVANCE_CYCLE;
13
14 return internal_min_issue_delay(insn_code, state);
15 }