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