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