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