10. Toolof genopinit
10.1. Overview
This tool will output insn-opinit.c from machine description file. The file provides function init_all_optabs whichbinds builtin functions with enum insn_code. And by this value, it indicateswhether the instruction is supported or not.
10.2. Program Entry
333 main (int argc, char **argv) ingenopinit.c
334 {
335 rtx desc;
336
337 progname= "genopinit";
338
339 if (argc <= 1)
340 fatal ("no input file name");
341
342 if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
343 return (FATAL_EXIT_CODE);
344
345 printf ("/* Generated automatically by the program `genopinit'\n\
346 from the machine description file `md'. */\n\n");
347
348 printf ("#include\"config.h\"\n");
349 printf("#include \"system.h\"\n");
350 printf ("#include \"coretypes.h\"\n");
351 printf ("#include \"tm.h\"\n");
352 printf ("#include \"rtl.h\"\n");
353 printf ("#include \"flags.h\"\n");
354 printf ("#include \"insn-config.h\"\n");
355 printf ("#include \"recog.h\"\n");
356 printf ("#include \"expr.h\"\n");
357 printf ("#include\"optabs.h\"\n");
358 printf ("#include\"reload.h\"\n\n");
359
360 printf("void\ninit_all_optabs (void)\n{\n");
361
362 puts ("\
363 #ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC\n\
364 int i, j;\n\
365 #endif\n");
366
367 /* Read the machine description. */
368
369 while (1)
370 {
371 int line_no, insn_code_number = 0;
372
373 desc = read_md_rtx (&line_no,&insn_code_number);
374 if (desc == NULL)
375 break;
376
377 if (GET_CODE (desc) ==DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
378 gen_insn (desc);
379 }
380
381 puts ("\
382 \n\
383 #ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC\n\
384 /* This flag says the same insns that convertto a signed fixnum\n\
385 also convert validly to an unsigned one. */\n\
386 for (i = 0; i <NUM_MACHINE_MODES; i++)\n\
387 for (j = 0; j <NUM_MACHINE_MODES; j++)\n\
388 ufixtrunc_optab->handlers[i][j].insn_code\n\
389 =sfixtrunc_optab->handlers[i][j].insn_code;\n\
390 #endif\n\
391 }");
392
393 fflush (stdout);
394 return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
395 }
Every rtx object of define_insn or define_expand pattern will behandled by gen_insn.
162 static void
163 gen_insn (rtx insn) in genopinit.c
164 {
165 const char *name = XSTR (insn, 0);
166 int m1 = 0, m2 = 0, op = 0;
167 size_t pindex;
168 int i;
169 const char *np, *pp, *p, *q;
170
171 /* Don't mention instructions whose names arethe null string.
172 They are in the machine description just tobe recognized. */
173 if (*name == 0)
174 return;
175
176 /* See if NAME matches one of the patterns wehave for the optabs we know
177 about. */
178
179 for (pindex = 0; pindex < ARRAY_SIZE(optabs);pindex++)
180 {
181 int force_float = 0, force_int = 0, force_partial_int = 0;
182 int force_consec = 0;
183 int matches = 1;
184
185 for (pp = optabs[pindex]; pp[0] != '$' ||pp[1] != '('; pp++)
186 ;
187
188 for (pp += 2, np = name; matches&& ! (pp[0] == '$' && pp[1] == ')');
189 pp++)
190 {
191 if (*pp != '$')
192 {
193 if (*pp != *np++)
194 break;
195 }
196 else
197 switch (*++pp)
198 {
199 case'N':
200 force_consec = 1;
201 break;
202 case'I':
203 force_int = 1;
204 break;
205 case'P':
206 force_partial_int = 1;
207 break;
208 case'F':
209 force_float = 1;
210 break;
211 case'V':
212 break;
213 case'c':
214 for(op = 0; op < NUM_RTX_CODE; op++)
215 {
216 for(p = GET_RTX_NAME(op), q = np; *p; p++, q++)
217 if (*p != *q)
218 break;
219
220 /* Wehave to be concerned about matching "gt" and
221 missing "gtu", e.g.,so verify we have reached the
222 end of thing we are tomatch. */
223 if (*p == 0 && *q == 0&& GET_RTX_CLASS(op) == '<')
224 break;
225 }
226
227 if (op == NUM_RTX_CODE)
228 matches = 0;
229 else
230 np += strlen (GET_RTX_NAME(op));
231 break;
232 case'a':
233 case'b':
234 /* Thisloop will stop at the first prefix match, so
235 look through the modes in reverseorder, in case
236 there are extra CC modes and CCis a prefix of the
237 CC modes (as it should be). */
238 for(i = (MAX_MACHINE_MODE) - 1; i >= 0; i--)
239 {
240 for(p = GET_MODE_NAME(i), q = np; *p; p++, q++)
241 if (TOLOWER (*p) != *q)
242 break;
243
244 if (*p == 0
245 && (! force_int ||mode_class[i] == MODE_INT
246 || mode_class[i] ==MODE_VECTOR_INT)
247 && (!force_partial_int
248 || mode_class[i] ==MODE_INT
249 || mode_class[i] == MODE_PARTIAL_INT
250 || mode_class[i] ==MODE_VECTOR_INT)
251 && (! force_float ||mode_class[i] == MODE_FLOAT
252 || mode_class[i] ==MODE_VECTOR_FLOAT))
253 break;
254 }
255
256 if (i < 0)
257 matches = 0;
258 else if (*pp == 'a')
259 m1 = i, np += strlen (GET_MODE_NAME(i));
260 else
261 m2 = i, np += strlen (GET_MODE_NAME(i));
262
263 force_int = force_partial_int =force_float = 0;
264 break;
265
266 default:
267 abort ();
268 }
269 }
270
271 if (matches && pp[0] == '$' && pp[1] == ')'
272 && *np == 0
273 && (! force_consec || (int) GET_MODE_WIDER_MODE(m1) == m2))
274 break;
275 }
Data optabshas following definition.
61 static const char * const optabs[] = in genopinit.c
62 {"sext_optab->handlers[$B][$A].insn_code =CODE_FOR_$(extend$a$b2$)",
63 "zext_optab->handlers[$B][$A].insn_code =CODE_FOR_$(zero_extend$a$b2$)",
64 "sfix_optab->handlers[$B][$A].insn_code =CODE_FOR_$(fix$F$a$I$b2$)",
65 "ufix_optab->handlers[$B][$A].insn_code =CODE_FOR_$(fixuns$F$a$b2$)",
66 "sfixtrunc_optab->handlers[$B][$A].insn_code =CODE_FOR_$(fix_trunc$F$a$I$b2$)",
67 "ufixtrunc_optab->handlers[$B][$A].insn_code =CODE_FOR_$(fixuns_trunc$F$a$I$b2$)",
68 …
Take content at line 62 above as example, in gen_insn, line 185 will scan thestring till arrive “$(“. Then FORloop at line 188 will examine sub-string “extend$a$b2$”. Next at line 193, seeif the name of define_insn or define_expand matches “extend” or not. For i386system, to match these sub-strings, we take following define_insn pattern asexample.
3227 (define_expand"extendsidi2" in i386.c
3228 [(parallel [(set (match_operand:DI 0"register_operand" "")
3229 (sign_extend:DI (match_operand:SI 1 "register_operand" "")))
3230 (clobber (reg:CC 17))
3231 (clobber (match_scratch:SI 2 ""))])]
3232 ""
3233 {
3234 if (TARGET_64BIT)
3235 {
3236 emit_insn (gen_extendsidi2_rex64(operands[0], operands[1]));
3237 DONE;
3238 }
3239 })
After matching, we come to following sub-string “$a$b2$”.
In the string, “$a” and “$b” are used to match a short mode name(the part of the mode name not including “mode” and converted to lower-case).When writing out the initializer, the entire string is used. “$A” and “$B” arereplaced with the full name of the mode; “$a” and “$b” are replaced with theshort form of the name, as above. If “$N” is present in the pattern, it meansthe two modes must be consecutive widths in the same mode class (e.g, QImodeand HImode). “$I” means that only full integer modes should be considered forthe next mode, and “$F” means that only float modes should be considered. “$P”means that both full and partial integer modes should be considered. “$V” meansto emit 'v' if the first mode is MODE_FLOAT mode.
gen_insn (continued)
277 if (pindex == ARRAY_SIZE (optabs))
278 return;
279
280 /* We found a match. If this pattern is onlyconditionally present,
281 write out the "if" and two extrablanks. */
282
283 if (*XSTR (insn, 2) != 0)
284 printf (" if(HAVE_%s)\n ", name);
285
286 printf (" ");
287
288 /* Now write out the initialization, makingall required substitutions. */
289 for (pp = optabs[pindex]; *pp; pp++)
290 {
291 if (*pp != '$')
292 putchar (*pp);
293 else
294 switch (*++pp)
295 {
296 case '(': case ')':
297 case 'I': case'F': case'N':
298 break;
299 case 'V':
300 if (GET_MODE_CLASS (m1) ==MODE_FLOAT)
301 printf ("v");
302 break;
303 case 'a':
304 for(np = GET_MODE_NAME(m1); *np; np++)
305 putchar (TOLOWER (*np));
306 break;
307 case 'b':
308 for(np = GET_MODE_NAME(m2); *np; np++)
309 putchar (TOLOWER (*np));
310 break;
311 case 'A':
312 printf ("%smode",GET_MODE_NAME(m1));
313 break;
314 case 'B':
315 printf ("%smode",GET_MODE_NAME(m2));
316 break;
317 case'c':
318 printf ("%s",GET_RTX_NAME(op));
319 break;
320 case 'C':
321 for(np = GET_RTX_NAME(op); *np; np++)
322 putchar (TOUPPER (*np));
323 break;
324 }
325 }
326
327 printf (";\n");
328 }
Notice that at line 284, the macro HAVE_`insn-name` is output in 12. Tool of genflags, refer to this section fordetail of the macros. Only when the macros equate to 1, it will asign the insnnumber to corresponding optab.
Then FOR loop at line 289outputs the initialization code for the optab. For our example, sext_optabis defined as convert_optab_table[CTI_sext],which has definition convert_optab. The structuredefines some sort of conversion operation between modes.
For our example, we will get following code fragment.
sext_optab->handlers[SImode][HImode].insn_code = CODE_FOR_extendhisi2;
sext_optab->handlers[HImode][QImode].insn_code= CODE_FOR_extendqihi2;
sext_optab->handlers[SImode][QImode].insn_code =CODE_FOR_extendqisi2;
Above handlershas definition of optab_handler, the insn_codeslot is the enuminsn_code that says how to generate an instruction for this operationon a particular machine mode. It is CODE_FOR_nothing if there is no such instructionon the target machine. The enum insn_code is output by gencodes (13. Tool of gencodes).