1 /* Generate code from machine description to emit insns as rtl. 2 Copyright (C) 1987, 1988, 1991, 1994, 1995, 1997, 1998, 1999, 2000, 2001, 3 2003, 2004, 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. 4 5 This file is part of GCC. 6 7 GCC is free software; you can redistribute it and/or modify it under 8 the terms of the GNU General Public License as published by the Free 9 Software Foundation; either version 3, or (at your option) any later 10 version. 11 12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 13 WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with GCC; see the file COPYING3. If not see 19 <http://www.gnu.org/licenses/>. */ 20 21 22 #include "bconfig.h" 23 #include "system.h" 24 #include "coretypes.h" 25 #include "tm.h" 26 #include "rtl.h" 27 #include "errors.h" 28 #include "read-md.h" 29 #include "gensupport.h" 30 31 32 static int insn_code_number; 33 static int insn_index_number; 34 35 /* Data structure for recording the patterns of insns that have CLOBBERs. 36 We use this to output a function that adds these CLOBBERs to a 37 previously-allocated PARALLEL expression. */ 38 39 struct clobber_pat 40 { 41 struct clobber_ent *insns; 42 rtx pattern; 43 int first_clobber; 44 struct clobber_pat *next; 45 int has_hard_reg; 46 } *clobber_list; 47 48 /* Records one insn that uses the clobber list. */ 49 50 struct clobber_ent 51 { 52 int code_number; /* Counts only insns. */ 53 struct clobber_ent *next; 54 }; 55 56 static void print_code (RTX_CODE); 57 static void gen_exp (rtx, enum rtx_code, char *); 58 static void gen_insn (rtx, int); 59 static void gen_expand (rtx); 60 static void gen_split (rtx); 61 static void output_add_clobbers (void); 62 static void output_added_clobbers_hard_reg_p (void); 63 static void gen_rtx_scratch (rtx, enum rtx_code); 64 static void output_peephole2_scratches (rtx); 65 66 67 static void 68 print_code (RTX_CODE code) 69 { 70 const char *p1; 71 for (p1 = GET_RTX_NAME (code); *p1; p1++) 72 putchar (TOUPPER(*p1)); 73 } 74 75 static void 76 gen_rtx_scratch (rtx x, enum rtx_code subroutine_type) 77 { 78 if (subroutine_type == DEFINE_PEEPHOLE2) 79 { 80 printf ("operand%d", XINT (x, 0)); 81 } 82 else 83 { 84 printf ("gen_rtx_SCRATCH (%smode)", GET_MODE_NAME (GET_MODE (x))); 85 } 86 } 87 88 /* Print a C expression to construct an RTX just like X, 89 substituting any operand references appearing within. */ 90 91 static void 92 gen_exp (rtx x, enum rtx_code subroutine_type, char *used) 93 { 94 RTX_CODE code; 95 int i; 96 int len; 97 const char *fmt; 98 99 if (x == 0) 100 { 101 printf ("NULL_RTX"); 102 return; 103 } 104 105 code = GET_CODE (x); 106 107 switch (code) 108 { 109 case MATCH_OPERAND: 110 case MATCH_DUP: 111 if (used) 112 { 113 if (used[XINT (x, 0)]) 114 { 115 printf ("copy_rtx (operand%d)", XINT (x, 0)); 116 return; 117 } 118 used[XINT (x, 0)] = 1; 119 } 120 printf ("operand%d", XINT (x, 0)); 121 return; 122 123 case MATCH_OP_DUP: 124 printf ("gen_rtx_fmt_"); 125 for (i = 0; i < XVECLEN (x, 1); i++) 126 printf ("e"); 127 printf (" (GET_CODE (operand%d), ", XINT (x, 0)); 128 if (GET_MODE (x) == VOIDmode) 129 printf ("GET_MODE (operand%d)", XINT (x, 0)); 130 else 131 printf ("%smode", GET_MODE_NAME (GET_MODE (x))); 132 for (i = 0; i < XVECLEN (x, 1); i++) 133 { 134 printf (",\n\t\t"); 135 gen_exp (XVECEXP (x, 1, i), subroutine_type, used); 136 } 137 printf (")"); 138 return; 139 140 case MATCH_OPERATOR: 141 printf ("gen_rtx_fmt_"); 142 for (i = 0; i < XVECLEN (x, 2); i++) 143 printf ("e"); 144 printf (" (GET_CODE (operand%d)", XINT (x, 0)); 145 printf (", %smode", GET_MODE_NAME (GET_MODE (x))); 146 for (i = 0; i < XVECLEN (x, 2); i++) 147 { 148 printf (",\n\t\t"); 149 gen_exp (XVECEXP (x, 2, i), subroutine_type, used); 150 } 151 printf (")"); 152 return; 153 154 case MATCH_PARALLEL: 155 case MATCH_PAR_DUP: 156 printf ("operand%d", XINT (x, 0)); 157 return; 158 159 case MATCH_SCRATCH: 160 gen_rtx_scratch (x, subroutine_type); 161 return; 162 163 case ADDRESS: 164 fatal ("ADDRESS expression code used in named instruction pattern"); 165 166 case PC: 167 printf ("pc_rtx"); 168 return; 169 case RETURN: 170 printf ("ret_rtx"); 171 return; 172 case SIMPLE_RETURN: 173 printf ("simple_return_rtx"); 174 return; 175 case CLOBBER: 176 if (REG_P (XEXP (x, 0))) 177 { 178 printf ("gen_hard_reg_clobber (%smode, %i)", GET_MODE_NAME (GET_MODE (XEXP (x, 0))), 179 REGNO (XEXP (x, 0))); 180 return; 181 } 182 break; 183 184 case CC0: 185 printf ("cc0_rtx"); 186 return; 187 188 case CONST_INT: 189 if (INTVAL (x) == 0) 190 printf ("const0_rtx"); 191 else if (INTVAL (x) == 1) 192 printf ("const1_rtx"); 193 else if (INTVAL (x) == -1) 194 printf ("constm1_rtx"); 195 else if (-MAX_SAVED_CONST_INT <= INTVAL (x) 196 && INTVAL (x) <= MAX_SAVED_CONST_INT) 197 printf ("const_int_rtx[MAX_SAVED_CONST_INT + (%d)]", 198 (int) INTVAL (x)); 199 else if (INTVAL (x) == STORE_FLAG_VALUE) 200 printf ("const_true_rtx"); 201 else 202 { 203 printf ("GEN_INT ("); 204 printf (HOST_WIDE_INT_PRINT_DEC_C, INTVAL (x)); 205 printf (")"); 206 } 207 return; 208 209 case CONST_DOUBLE: 210 case CONST_FIXED: 211 /* These shouldn't be written in MD files. Instead, the appropriate 212 routines in varasm.c should be called. */ 213 gcc_unreachable (); 214 215 default: 216 break; 217 } 218 219 printf ("gen_rtx_"); 220 print_code (code); 221 printf (" (%smode", GET_MODE_NAME (GET_MODE (x))); 222 223 fmt = GET_RTX_FORMAT (code); 224 len = GET_RTX_LENGTH (code); 225 for (i = 0; i < len; i++) 226 { 227 if (fmt[i] == '0') 228 break; 229 printf (",\n\t"); 230 switch (fmt[i]) 231 { 232 case 'e': case 'u': 233 gen_exp (XEXP (x, i), subroutine_type, used); 234 break; 235 236 case 'i': 237 printf ("%u", XINT (x, i)); 238 break; 239 240 case 's': 241 printf ("\"%s\"", XSTR (x, i)); 242 break; 243 244 case 'E': 245 { 246 int j; 247 printf ("gen_rtvec (%d", XVECLEN (x, i)); 248 for (j = 0; j < XVECLEN (x, i); j++) 249 { 250 printf (",\n\t\t"); 251 gen_exp (XVECEXP (x, i, j), subroutine_type, used); 252 } 253 printf (")"); 254 break; 255 } 256 257 default: 258 gcc_unreachable (); 259 } 260 } 261 printf (")"); 262 } 263 264 /* Generate the `gen_...' function for a DEFINE_INSN. */ 265 266 static void 267 gen_insn (rtx insn, int lineno) 268 { 269 struct pattern_stats stats; 270 int i; 271 272 /* See if the pattern for this insn ends with a group of CLOBBERs of (hard) 273 registers or MATCH_SCRATCHes. If so, store away the information for 274 later. */ 275 276 if (XVEC (insn, 1)) 277 { 278 int has_hard_reg = 0; 279 280 for (i = XVECLEN (insn, 1) - 1; i > 0; i--) 281 { 282 if (GET_CODE (XVECEXP (insn, 1, i)) != CLOBBER) 283 break; 284 285 if (REG_P (XEXP (XVECEXP (insn, 1, i), 0))) 286 has_hard_reg = 1; 287 else if (GET_CODE (XEXP (XVECEXP (insn, 1, i), 0)) != MATCH_SCRATCH) 288 break; 289 } 290 291 if (i != XVECLEN (insn, 1) - 1) 292 { 293 struct clobber_pat *p; 294 struct clobber_ent *link = XNEW (struct clobber_ent); 295 int j; 296 297 link->code_number = insn_code_number; 298 299 /* See if any previous CLOBBER_LIST entry is the same as this 300 one. */ 301 302 for (p = clobber_list; p; p = p->next) 303 { 304 if (p->first_clobber != i + 1 305 || XVECLEN (p->pattern, 1) != XVECLEN (insn, 1)) 306 continue; 307 308 for (j = i + 1; j < XVECLEN (insn, 1); j++) 309 { 310 rtx old_rtx = XEXP (XVECEXP (p->pattern, 1, j), 0); 311 rtx new_rtx = XEXP (XVECEXP (insn, 1, j), 0); 312 313 /* OLD and NEW_INSN are the same if both are to be a SCRATCH 314 of the same mode, 315 or if both are registers of the same mode and number. */ 316 if (! (GET_MODE (old_rtx) == GET_MODE (new_rtx) 317 && ((GET_CODE (old_rtx) == MATCH_SCRATCH 318 && GET_CODE (new_rtx) == MATCH_SCRATCH) 319 || (REG_P (old_rtx) && REG_P (new_rtx) 320 && REGNO (old_rtx) == REGNO (new_rtx))))) 321 break; 322 } 323 324 if (j == XVECLEN (insn, 1)) 325 break; 326 } 327 328 if (p == 0) 329 { 330 p = XNEW (struct clobber_pat); 331 332 p->insns = 0; 333 p->pattern = insn; 334 p->first_clobber = i + 1; 335 p->next = clobber_list; 336 p->has_hard_reg = has_hard_reg; 337 clobber_list = p; 338 } 339 340 link->next = p->insns; 341 p->insns = link; 342 } 343 } 344 345 /* Don't mention instructions whose names are the null string 346 or begin with '*'. They are in the machine description just 347 to be recognized. */ 348 if (XSTR (insn, 0)[0] == 0 || XSTR (insn, 0)[0] == '*') 349 return; 350 351 printf ("/* %s:%d */\n", read_md_filename, lineno); 352 353 /* Find out how many operands this function has. */ 354 get_pattern_stats (&stats, XVEC (insn, 1)); 355 if (stats.max_dup_opno > stats.max_opno) 356 fatal ("match_dup operand number has no match_operand"); 357 358 /* Output the function name and argument declarations. */ 359 printf ("rtx\ngen_%s (", XSTR (insn, 0)); 360 if (stats.num_generator_args) 361 for (i = 0; i < stats.num_generator_args; i++) 362 if (i) 363 printf (",\n\trtx operand%d ATTRIBUTE_UNUSED", i); 364 else 365 printf ("rtx operand%d ATTRIBUTE_UNUSED", i); 366 else 367 printf ("void"); 368 printf (")\n"); 369 printf ("{\n"); 370 371 /* Output code to construct and return the rtl for the instruction body. */ 372 373 if (XVECLEN (insn, 1) == 1) 374 { 375 printf (" return "); 376 gen_exp (XVECEXP (insn, 1, 0), DEFINE_INSN, NULL); 377 printf (";\n}\n\n"); 378 } 379 else 380 { 381 char *used = XCNEWVEC (char, stats.num_generator_args); 382 383 printf (" return gen_rtx_PARALLEL (VOIDmode, gen_rtvec (%d", 384 XVECLEN (insn, 1)); 385 386 for (i = 0; i < XVECLEN (insn, 1); i++) 387 { 388 printf (",\n\t\t"); 389 gen_exp (XVECEXP (insn, 1, i), DEFINE_INSN, used); 390 } 391 printf ("));\n}\n\n"); 392 XDELETEVEC (used); 393 } 394 } 395 396 /* Generate the `gen_...' function for a DEFINE_EXPAND. */ 397 398 static void 399 gen_expand (rtx expand) 400 { 401 struct pattern_stats stats; 402 int i; 403 char *used; 404 405 if (strlen (XSTR (expand, 0)) == 0) 406 fatal ("define_expand lacks a name"); 407 if (XVEC (expand, 1) == 0) 408 fatal ("define_expand for %s lacks a pattern", XSTR (expand, 0)); 409 410 /* Find out how many operands this function has. */ 411 get_pattern_stats (&stats, XVEC (expand, 1)); 412 413 /* Output the function name and argument declarations. */ 414 printf ("rtx\ngen_%s (", XSTR (expand, 0)); 415 if (stats.num_generator_args) 416 for (i = 0; i < stats.num_generator_args; i++) 417 if (i) 418 printf (",\n\trtx operand%d", i); 419 else 420 printf ("rtx operand%d", i); 421 else 422 printf ("void"); 423 printf (")\n"); 424 printf ("{\n"); 425 426 /* If we don't have any C code to write, only one insn is being written, 427 and no MATCH_DUPs are present, we can just return the desired insn 428 like we do for a DEFINE_INSN. This saves memory. */ 429 if ((XSTR (expand, 3) == 0 || *XSTR (expand, 3) == '\0') 430 && stats.max_opno >= stats.max_dup_opno 431 && XVECLEN (expand, 1) == 1) 432 { 433 printf (" return "); 434 gen_exp (XVECEXP (expand, 1, 0), DEFINE_EXPAND, NULL); 435 printf (";\n}\n\n"); 436 return; 437 } 438 439 /* For each operand referred to only with MATCH_DUPs, 440 make a local variable. */ 441 for (i = stats.num_generator_args; i <= stats.max_dup_opno; i++) 442 printf (" rtx operand%d;\n", i); 443 for (; i <= stats.max_scratch_opno; i++) 444 printf (" rtx operand%d ATTRIBUTE_UNUSED;\n", i); 445 printf (" rtx _val = 0;\n"); 446 printf (" start_sequence ();\n"); 447 448 /* The fourth operand of DEFINE_EXPAND is some code to be executed 449 before the actual construction. 450 This code expects to refer to `operands' 451 just as the output-code in a DEFINE_INSN does, 452 but here `operands' is an automatic array. 453 So copy the operand values there before executing it. */ 454 if (XSTR (expand, 3) && *XSTR (expand, 3)) 455 { 456 printf (" {\n"); 457 if (stats.num_operand_vars > 0) 458 printf (" rtx operands[%d];\n", stats.num_operand_vars); 459 460 /* Output code to copy the arguments into `operands'. */ 461 for (i = 0; i < stats.num_generator_args; i++) 462 printf (" operands[%d] = operand%d;\n", i, i); 463 464 /* Output the special code to be executed before the sequence 465 is generated. */ 466 print_md_ptr_loc (XSTR (expand, 3)); 467 printf ("%s\n", XSTR (expand, 3)); 468 469 /* Output code to copy the arguments back out of `operands' 470 (unless we aren't going to use them at all). */ 471 if (XVEC (expand, 1) != 0) 472 { 473 for (i = 0; i < stats.num_operand_vars; i++) 474 { 475 printf (" operand%d = operands[%d];\n", i, i); 476 printf (" (void) operand%d;\n", i); 477 } 478 } 479 printf (" }\n"); 480 } 481 482 /* Output code to construct the rtl for the instruction bodies. 483 Use emit_insn to add them to the sequence being accumulated. 484 But don't do this if the user's code has set `no_more' nonzero. */ 485 486 used = XCNEWVEC (char, stats.num_operand_vars); 487 488 for (i = 0; i < XVECLEN (expand, 1); i++) 489 { 490 rtx next = XVECEXP (expand, 1, i); 491 if ((GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC) 492 || (GET_CODE (next) == PARALLEL 493 && ((GET_CODE (XVECEXP (next, 0, 0)) == SET 494 && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC) 495 || ANY_RETURN_P (XVECEXP (next, 0, 0)))) 496 || ANY_RETURN_P (next)) 497 printf (" emit_jump_insn ("); 498 else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL) 499 || GET_CODE (next) == CALL 500 || (GET_CODE (next) == PARALLEL 501 && GET_CODE (XVECEXP (next, 0, 0)) == SET 502 && GET_CODE (SET_SRC (XVECEXP (next, 0, 0))) == CALL) 503 || (GET_CODE (next) == PARALLEL 504 && GET_CODE (XVECEXP (next, 0, 0)) == CALL)) 505 printf (" emit_call_insn ("); 506 else if (LABEL_P (next)) 507 printf (" emit_label ("); 508 else if (GET_CODE (next) == MATCH_OPERAND 509 || GET_CODE (next) == MATCH_DUP 510 || GET_CODE (next) == MATCH_OPERATOR 511 || GET_CODE (next) == MATCH_OP_DUP 512 || GET_CODE (next) == MATCH_PARALLEL 513 || GET_CODE (next) == MATCH_PAR_DUP 514 || GET_CODE (next) == PARALLEL) 515 printf (" emit ("); 516 else 517 printf (" emit_insn ("); 518 gen_exp (next, DEFINE_EXPAND, used); 519 printf (");\n"); 520 if (GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC 521 && GET_CODE (SET_SRC (next)) == LABEL_REF) 522 printf (" emit_barrier ();"); 523 } 524 525 XDELETEVEC (used); 526 527 /* Call `get_insns' to extract the list of all the 528 insns emitted within this gen_... function. */ 529 530 printf (" _val = get_insns ();\n"); 531 printf (" end_sequence ();\n"); 532 printf (" return _val;\n}\n\n"); 533 } 534 535 /* Like gen_expand, but generates insns resulting from splitting SPLIT. */ 536 537 static void 538 gen_split (rtx split) 539 { 540 struct pattern_stats stats; 541 int i; 542 const char *const name = 543 ((GET_CODE (split) == DEFINE_PEEPHOLE2) ? "peephole2" : "split"); 544 const char *unused; 545 char *used; 546 547 if (XVEC (split, 0) == 0) 548 fatal ("define_%s (definition %d) lacks a pattern", name, 549 insn_index_number); 550 else if (XVEC (split, 2) == 0) 551 fatal ("define_%s (definition %d) lacks a replacement pattern", name, 552 insn_index_number); 553 554 /* Find out how many operands this function has. */ 555 556 get_pattern_stats (&stats, XVEC (split, 2)); 557 unused = (stats.num_operand_vars == 0 ? " ATTRIBUTE_UNUSED" : ""); 558 used = XCNEWVEC (char, stats.num_operand_vars); 559 560 /* Output the prototype, function name and argument declarations. */ 561 if (GET_CODE (split) == DEFINE_PEEPHOLE2) 562 { 563 printf ("extern rtx gen_%s_%d (rtx, rtx *);\n", 564 name, insn_code_number); 565 printf ("rtx\ngen_%s_%d (rtx curr_insn ATTRIBUTE_UNUSED, rtx *operands%s)\n", 566 name, insn_code_number, unused); 567 } 568 else 569 { 570 printf ("extern rtx gen_split_%d (rtx, rtx *);\n", insn_code_number); 571 printf ("rtx\ngen_split_%d (rtx curr_insn ATTRIBUTE_UNUSED, rtx *operands%s)\n", 572 insn_code_number, unused); 573 } 574 printf ("{\n"); 575 576 /* Declare all local variables. */ 577 for (i = 0; i < stats.num_operand_vars; i++) 578 printf (" rtx operand%d;\n", i); 579 printf (" rtx _val = 0;\n"); 580 581 if (GET_CODE (split) == DEFINE_PEEPHOLE2) 582 output_peephole2_scratches (split); 583 584 printf (" start_sequence ();\n"); 585 586 /* The fourth operand of DEFINE_SPLIT is some code to be executed 587 before the actual construction. */ 588 589 if (XSTR (split, 3)) 590 { 591 print_md_ptr_loc (XSTR (split, 3)); 592 printf ("%s\n", XSTR (split, 3)); 593 } 594 595 /* Output code to copy the arguments back out of `operands' */ 596 for (i = 0; i < stats.num_operand_vars; i++) 597 { 598 printf (" operand%d = operands[%d];\n", i, i); 599 printf (" (void) operand%d;\n", i); 600 } 601 602 /* Output code to construct the rtl for the instruction bodies. 603 Use emit_insn to add them to the sequence being accumulated. 604 But don't do this if the user's code has set `no_more' nonzero. */ 605 606 for (i = 0; i < XVECLEN (split, 2); i++) 607 { 608 rtx next = XVECEXP (split, 2, i); 609 if ((GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC) 610 || (GET_CODE (next) == PARALLEL 611 && GET_CODE (XVECEXP (next, 0, 0)) == SET 612 && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC) 613 || ANY_RETURN_P (next)) 614 printf (" emit_jump_insn ("); 615 else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL) 616 || GET_CODE (next) == CALL 617 || (GET_CODE (next) == PARALLEL 618 && GET_CODE (XVECEXP (next, 0, 0)) == SET 619 && GET_CODE (SET_SRC (XVECEXP (next, 0, 0))) == CALL) 620 || (GET_CODE (next) == PARALLEL 621 && GET_CODE (XVECEXP (next, 0, 0)) == CALL)) 622 printf (" emit_call_insn ("); 623 else if (LABEL_P (next)) 624 printf (" emit_label ("); 625 else if (GET_CODE (next) == MATCH_OPERAND 626 || GET_CODE (next) == MATCH_OPERATOR 627 || GET_CODE (next) == MATCH_PARALLEL 628 || GET_CODE (next) == MATCH_OP_DUP 629 || GET_CODE (next) == MATCH_DUP 630 || GET_CODE (next) == PARALLEL) 631 printf (" emit ("); 632 else 633 printf (" emit_insn ("); 634 gen_exp (next, GET_CODE (split), used); 635 printf (");\n"); 636 if (GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC 637 && GET_CODE (SET_SRC (next)) == LABEL_REF) 638 printf (" emit_barrier ();"); 639 } 640 641 /* Call `get_insns' to make a list of all the 642 insns emitted within this gen_... function. */ 643 644 printf (" _val = get_insns ();\n"); 645 printf (" end_sequence ();\n"); 646 printf (" return _val;\n}\n\n"); 647 648 free (used); 649 } 650 651 /* Write a function, `add_clobbers', that is given a PARALLEL of sufficient 652 size for the insn and an INSN_CODE, and inserts the required CLOBBERs at 653 the end of the vector. */ 654 655 static void 656 output_add_clobbers (void) 657 { 658 struct clobber_pat *clobber; 659 struct clobber_ent *ent; 660 int i; 661 662 printf ("\n\nvoid\nadd_clobbers (rtx pattern ATTRIBUTE_UNUSED, int insn_code_number)\n"); 663 printf ("{\n"); 664 printf (" switch (insn_code_number)\n"); 665 printf (" {\n"); 666 667 for (clobber = clobber_list; clobber; clobber = clobber->next) 668 { 669 for (ent = clobber->insns; ent; ent = ent->next) 670 printf (" case %d:\n", ent->code_number); 671 672 for (i = clobber->first_clobber; i < XVECLEN (clobber->pattern, 1); i++) 673 { 674 printf (" XVECEXP (pattern, 0, %d) = ", i); 675 gen_exp (XVECEXP (clobber->pattern, 1, i), 676 GET_CODE (clobber->pattern), NULL); 677 printf (";\n"); 678 } 679 680 printf (" break;\n\n"); 681 } 682 683 printf (" default:\n"); 684 printf (" gcc_unreachable ();\n"); 685 printf (" }\n"); 686 printf ("}\n"); 687 } 688 689 /* Write a function, `added_clobbers_hard_reg_p' that is given an insn_code 690 number that will have clobbers added (as indicated by `recog') and returns 691 1 if those include a clobber of a hard reg or 0 if all of them just clobber 692 SCRATCH. */ 693 694 static void 695 output_added_clobbers_hard_reg_p (void) 696 { 697 struct clobber_pat *clobber; 698 struct clobber_ent *ent; 699 int clobber_p, used; 700 701 printf ("\n\nint\nadded_clobbers_hard_reg_p (int insn_code_number)\n"); 702 printf ("{\n"); 703 printf (" switch (insn_code_number)\n"); 704 printf (" {\n"); 705 706 for (clobber_p = 0; clobber_p <= 1; clobber_p++) 707 { 708 used = 0; 709 for (clobber = clobber_list; clobber; clobber = clobber->next) 710 if (clobber->has_hard_reg == clobber_p) 711 for (ent = clobber->insns; ent; ent = ent->next) 712 { 713 printf (" case %d:\n", ent->code_number); 714 used++; 715 } 716 717 if (used) 718 printf (" return %d;\n\n", clobber_p); 719 } 720 721 printf (" default:\n"); 722 printf (" gcc_unreachable ();\n"); 723 printf (" }\n"); 724 printf ("}\n"); 725 } 726 727 /* Generate code to invoke find_free_register () as needed for the 728 scratch registers used by the peephole2 pattern in SPLIT. */ 729 730 static void 731 output_peephole2_scratches (rtx split) 732 { 733 int i; 734 int insn_nr = 0; 735 bool first = true; 736 737 for (i = 0; i < XVECLEN (split, 0); i++) 738 { 739 rtx elt = XVECEXP (split, 0, i); 740 if (GET_CODE (elt) == MATCH_SCRATCH) 741 { 742 int last_insn_nr = insn_nr; 743 int cur_insn_nr = insn_nr; 744 int j; 745 for (j = i + 1; j < XVECLEN (split, 0); j++) 746 if (GET_CODE (XVECEXP (split, 0, j)) == MATCH_DUP) 747 { 748 if (XINT (XVECEXP (split, 0, j), 0) == XINT (elt, 0)) 749 last_insn_nr = cur_insn_nr; 750 } 751 else if (GET_CODE (XVECEXP (split, 0, j)) != MATCH_SCRATCH) 752 cur_insn_nr++; 753 754 if (first) 755 { 756 printf (" HARD_REG_SET _regs_allocated;\n"); 757 printf (" CLEAR_HARD_REG_SET (_regs_allocated);\n"); 758 first = false; 759 } 760 761 printf (" if ((operands[%d] = peep2_find_free_register (%d, %d, \"%s\", %smode, &_regs_allocated)) == NULL_RTX)\n\ 762 return NULL;\n", 763 XINT (elt, 0), 764 insn_nr, last_insn_nr, 765 XSTR (elt, 1), 766 GET_MODE_NAME (GET_MODE (elt))); 767 768 } 769 else if (GET_CODE (elt) != MATCH_DUP) 770 insn_nr++; 771 } 772 } 773 774 int 775 main (int argc, char **argv) 776 { 777 rtx desc; 778 779 progname = "genemit"; 780 781 if (!init_rtx_reader_args (argc, argv)) 782 return (FATAL_EXIT_CODE); 783 784 /* Assign sequential codes to all entries in the machine description 785 in parallel with the tables in insn-output.c. */ 786 787 insn_code_number = 0; 788 insn_index_number = 0; 789 790 printf ("/* Generated automatically by the program `genemit'\n\ 791 from the machine description file `md'. */\n\n"); 792 793 printf ("#include \"config.h\"\n"); 794 printf ("#include \"system.h\"\n"); 795 printf ("#include \"coretypes.h\"\n"); 796 printf ("#include \"tm.h\"\n"); 797 printf ("#include \"rtl.h\"\n"); 798 printf ("#include \"tm_p.h\"\n"); 799 printf ("#include \"function.h\"\n"); 800 printf ("#include \"expr.h\"\n"); 801 printf ("#include \"optabs.h\"\n"); 802 printf ("#include \"dfp.h\"\n"); 803 printf ("#include \"flags.h\"\n"); 804 printf ("#include \"output.h\"\n"); 805 printf ("#include \"insn-config.h\"\n"); 806 printf ("#include \"hard-reg-set.h\"\n"); 807 printf ("#include \"recog.h\"\n"); 808 printf ("#include \"resource.h\"\n"); 809 printf ("#include \"reload.h\"\n"); 810 printf ("#include \"diagnostic-core.h\"\n"); 811 printf ("#include \"regs.h\"\n"); 812 printf ("#include \"tm-constrs.h\"\n"); 813 printf ("#include \"ggc.h\"\n"); 814 printf ("#include \"basic-block.h\"\n"); 815 printf ("#include \"integrate.h\"\n\n"); 816 printf ("#define FAIL return (end_sequence (), _val)\n"); 817 printf ("#define DONE return (_val = get_insns (), end_sequence (), _val)\n\n"); 818 819 /* Read the machine description. */ 820 821 while (1) 822 { 823 int line_no; 824 825 desc = read_md_rtx (&line_no, &insn_code_number); 826 if (desc == NULL) 827 break; 828 829 switch (GET_CODE (desc)) 830 { 831 case DEFINE_INSN: 832 gen_insn (desc, line_no); 833 break; 834 835 case DEFINE_EXPAND: 836 printf ("/* %s:%d */\n", read_md_filename, line_no); 837 gen_expand (desc); 838 break; 839 840 case DEFINE_SPLIT: 841 printf ("/* %s:%d */\n", read_md_filename, line_no); 842 gen_split (desc); 843 break; 844 845 case DEFINE_PEEPHOLE2: 846 printf ("/* %s:%d */\n", read_md_filename, line_no); 847 gen_split (desc); 848 break; 849 850 default: 851 break; 852 } 853 ++insn_index_number; 854 } 855 856 /* Write out the routines to add CLOBBERs to a pattern and say whether they 857 clobber a hard reg. */ 858 output_add_clobbers (); 859 output_added_clobbers_hard_reg_p (); 860 861 fflush (stdout); 862 return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); 863 } 864