genemit.c revision 117395
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, int)); 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_C, 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, lineno) 301 rtx insn; 302 int lineno; 303{ 304 int operands; 305 int i; 306 307 /* See if the pattern for this insn ends with a group of CLOBBERs of (hard) 308 registers or MATCH_SCRATCHes. If so, store away the information for 309 later. */ 310 311 if (XVEC (insn, 1)) 312 { 313 int has_hard_reg = 0; 314 315 for (i = XVECLEN (insn, 1) - 1; i > 0; i--) 316 { 317 if (GET_CODE (XVECEXP (insn, 1, i)) != CLOBBER) 318 break; 319 320 if (GET_CODE (XEXP (XVECEXP (insn, 1, i), 0)) == REG) 321 has_hard_reg = 1; 322 else if (GET_CODE (XEXP (XVECEXP (insn, 1, i), 0)) != MATCH_SCRATCH) 323 break; 324 } 325 326 if (i != XVECLEN (insn, 1) - 1) 327 { 328 struct clobber_pat *p; 329 struct clobber_ent *link 330 = (struct clobber_ent *) xmalloc (sizeof (struct clobber_ent)); 331 int j; 332 333 link->code_number = insn_code_number; 334 335 /* See if any previous CLOBBER_LIST entry is the same as this 336 one. */ 337 338 for (p = clobber_list; p; p = p->next) 339 { 340 if (p->first_clobber != i + 1 341 || XVECLEN (p->pattern, 1) != XVECLEN (insn, 1)) 342 continue; 343 344 for (j = i + 1; j < XVECLEN (insn, 1); j++) 345 { 346 rtx old = XEXP (XVECEXP (p->pattern, 1, j), 0); 347 rtx new = XEXP (XVECEXP (insn, 1, j), 0); 348 349 /* OLD and NEW are the same if both are to be a SCRATCH 350 of the same mode, 351 or if both are registers of the same mode and number. */ 352 if (! (GET_MODE (old) == GET_MODE (new) 353 && ((GET_CODE (old) == MATCH_SCRATCH 354 && GET_CODE (new) == MATCH_SCRATCH) 355 || (GET_CODE (old) == REG && GET_CODE (new) == REG 356 && REGNO (old) == REGNO (new))))) 357 break; 358 } 359 360 if (j == XVECLEN (insn, 1)) 361 break; 362 } 363 364 if (p == 0) 365 { 366 p = (struct clobber_pat *) xmalloc (sizeof (struct clobber_pat)); 367 368 p->insns = 0; 369 p->pattern = insn; 370 p->first_clobber = i + 1; 371 p->next = clobber_list; 372 p->has_hard_reg = has_hard_reg; 373 clobber_list = p; 374 } 375 376 link->next = p->insns; 377 p->insns = link; 378 } 379 } 380 381 /* Don't mention instructions whose names are the null string 382 or begin with '*'. They are in the machine description just 383 to be recognized. */ 384 if (XSTR (insn, 0)[0] == 0 || XSTR (insn, 0)[0] == '*') 385 return; 386 387 printf ("/* %s:%d */\n", read_rtx_filename, lineno); 388 389 /* Find out how many operands this function has, 390 and also whether any of them have register constraints. */ 391 register_constraints = 0; 392 operands = max_operand_vec (insn, 1); 393 if (max_dup_opno >= operands) 394 fatal ("match_dup operand number has no match_operand"); 395 396 /* Output the function name and argument declarations. */ 397 printf ("rtx\ngen_%s (", XSTR (insn, 0)); 398 for (i = 0; i < operands; i++) 399 if (i) 400 printf (", operand%d", i); 401 else 402 printf ("operand%d", i); 403 printf (")\n"); 404 for (i = 0; i < operands; i++) 405 printf (" rtx operand%d;\n", i); 406 printf ("{\n"); 407 408 /* Output code to construct and return the rtl for the instruction body */ 409 410 if (XVECLEN (insn, 1) == 1) 411 { 412 printf (" return "); 413 gen_exp (XVECEXP (insn, 1, 0), DEFINE_INSN, NULL); 414 printf (";\n}\n\n"); 415 } 416 else 417 { 418 printf (" return gen_rtx_PARALLEL (VOIDmode, gen_rtvec (%d", 419 XVECLEN (insn, 1)); 420 421 for (i = 0; i < XVECLEN (insn, 1); i++) 422 { 423 printf (",\n\t\t"); 424 gen_exp (XVECEXP (insn, 1, i), DEFINE_INSN, NULL); 425 } 426 printf ("));\n}\n\n"); 427 } 428} 429 430/* Generate the `gen_...' function for a DEFINE_EXPAND. */ 431 432static void 433gen_expand (expand) 434 rtx expand; 435{ 436 int operands; 437 int i; 438 439 if (strlen (XSTR (expand, 0)) == 0) 440 fatal ("define_expand lacks a name"); 441 if (XVEC (expand, 1) == 0) 442 fatal ("define_expand for %s lacks a pattern", XSTR (expand, 0)); 443 444 /* Find out how many operands this function has, 445 and also whether any of them have register constraints. */ 446 register_constraints = 0; 447 448 operands = max_operand_vec (expand, 1); 449 450 /* Output the function name and argument declarations. */ 451 printf ("rtx\ngen_%s (", XSTR (expand, 0)); 452 for (i = 0; i < operands; i++) 453 if (i) 454 printf (", operand%d", i); 455 else 456 printf ("operand%d", i); 457 printf (")\n"); 458 for (i = 0; i < operands; i++) 459 printf (" rtx operand%d;\n", i); 460 printf ("{\n"); 461 462 /* If we don't have any C code to write, only one insn is being written, 463 and no MATCH_DUPs are present, we can just return the desired insn 464 like we do for a DEFINE_INSN. This saves memory. */ 465 if ((XSTR (expand, 3) == 0 || *XSTR (expand, 3) == '\0') 466 && operands > max_dup_opno 467 && XVECLEN (expand, 1) == 1) 468 { 469 printf (" return "); 470 gen_exp (XVECEXP (expand, 1, 0), DEFINE_EXPAND, NULL); 471 printf (";\n}\n\n"); 472 return; 473 } 474 475 /* For each operand referred to only with MATCH_DUPs, 476 make a local variable. */ 477 for (i = operands; i <= max_dup_opno; i++) 478 printf (" rtx operand%d;\n", i); 479 for (; i <= max_scratch_opno; i++) 480 printf (" rtx operand%d ATTRIBUTE_UNUSED;\n", i); 481 printf (" rtx _val = 0;\n"); 482 printf (" start_sequence ();\n"); 483 484 /* The fourth operand of DEFINE_EXPAND is some code to be executed 485 before the actual construction. 486 This code expects to refer to `operands' 487 just as the output-code in a DEFINE_INSN does, 488 but here `operands' is an automatic array. 489 So copy the operand values there before executing it. */ 490 if (XSTR (expand, 3) && *XSTR (expand, 3)) 491 { 492 printf (" {\n"); 493 if (operands > 0 || max_dup_opno >= 0 || max_scratch_opno >= 0) 494 printf (" rtx operands[%d];\n", 495 MAX (operands, MAX (max_scratch_opno, max_dup_opno) + 1)); 496 /* Output code to copy the arguments into `operands'. */ 497 for (i = 0; i < operands; i++) 498 printf (" operands[%d] = operand%d;\n", i, i); 499 500 /* Output the special code to be executed before the sequence 501 is generated. */ 502 printf ("%s\n", XSTR (expand, 3)); 503 504 /* Output code to copy the arguments back out of `operands' 505 (unless we aren't going to use them at all). */ 506 if (XVEC (expand, 1) != 0) 507 { 508 for (i = 0; i < operands; i++) 509 printf (" operand%d = operands[%d];\n", i, i); 510 for (; i <= max_dup_opno; i++) 511 printf (" operand%d = operands[%d];\n", i, i); 512 for (; i <= max_scratch_opno; i++) 513 printf (" operand%d = operands[%d];\n", i, i); 514 } 515 printf (" }\n"); 516 } 517 518 /* Output code to construct the rtl for the instruction bodies. 519 Use emit_insn to add them to the sequence being accumulated. 520 But don't do this if the user's code has set `no_more' nonzero. */ 521 522 for (i = 0; i < XVECLEN (expand, 1); i++) 523 { 524 rtx next = XVECEXP (expand, 1, i); 525 if ((GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC) 526 || (GET_CODE (next) == PARALLEL 527 && ((GET_CODE (XVECEXP (next, 0, 0)) == SET 528 && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC) 529 || GET_CODE (XVECEXP (next, 0, 0)) == RETURN)) 530 || GET_CODE (next) == RETURN) 531 printf (" emit_jump_insn ("); 532 else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL) 533 || GET_CODE (next) == CALL 534 || (GET_CODE (next) == PARALLEL 535 && GET_CODE (XVECEXP (next, 0, 0)) == SET 536 && GET_CODE (SET_SRC (XVECEXP (next, 0, 0))) == CALL) 537 || (GET_CODE (next) == PARALLEL 538 && GET_CODE (XVECEXP (next, 0, 0)) == CALL)) 539 printf (" emit_call_insn ("); 540 else if (GET_CODE (next) == CODE_LABEL) 541 printf (" emit_label ("); 542 else if (GET_CODE (next) == MATCH_OPERAND 543 || GET_CODE (next) == MATCH_DUP 544 || GET_CODE (next) == MATCH_OPERATOR 545 || GET_CODE (next) == MATCH_OP_DUP 546 || GET_CODE (next) == MATCH_PARALLEL 547 || GET_CODE (next) == MATCH_PAR_DUP 548 || GET_CODE (next) == PARALLEL) 549 printf (" emit ("); 550 else 551 printf (" emit_insn ("); 552 gen_exp (next, DEFINE_EXPAND, NULL); 553 printf (");\n"); 554 if (GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC 555 && GET_CODE (SET_SRC (next)) == LABEL_REF) 556 printf (" emit_barrier ();"); 557 } 558 559 /* Call `get_insns' to extract the list of all the 560 insns emitted within this gen_... function. */ 561 562 printf (" _val = get_insns ();\n"); 563 printf (" end_sequence ();\n"); 564 printf (" return _val;\n}\n\n"); 565} 566 567/* Like gen_expand, but generates insns resulting from splitting SPLIT. */ 568 569static void 570gen_split (split) 571 rtx split; 572{ 573 int i; 574 int operands; 575 const char *const name = 576 ((GET_CODE (split) == DEFINE_PEEPHOLE2) ? "peephole2" : "split"); 577 const char *unused; 578 char *used; 579 580 if (XVEC (split, 0) == 0) 581 fatal ("define_%s (definition %d) lacks a pattern", name, 582 insn_index_number); 583 else if (XVEC (split, 2) == 0) 584 fatal ("define_%s (definition %d) lacks a replacement pattern", name, 585 insn_index_number); 586 587 /* Find out how many operands this function has. */ 588 589 max_operand_vec (split, 2); 590 operands = MAX (max_opno, MAX (max_dup_opno, max_scratch_opno)) + 1; 591 unused = (operands == 0 ? " ATTRIBUTE_UNUSED" : ""); 592 used = xcalloc (1, operands); 593 594 /* Output the prototype, function name and argument declarations. */ 595 if (GET_CODE (split) == DEFINE_PEEPHOLE2) 596 { 597 printf ("extern rtx gen_%s_%d PARAMS ((rtx, rtx *));\n", 598 name, insn_code_number); 599 printf ("rtx\ngen_%s_%d (curr_insn, operands)\n", 600 name, insn_code_number); 601 printf (" rtx curr_insn ATTRIBUTE_UNUSED;\n"); 602 printf (" rtx *operands%s;\n", unused); 603 } 604 else 605 { 606 printf ("extern rtx gen_split_%d PARAMS ((rtx *));\n", insn_code_number); 607 printf ("rtx\ngen_%s_%d (operands)\n", name, insn_code_number); 608 printf (" rtx *operands%s;\n", unused); 609 } 610 printf ("{\n"); 611 612 /* Declare all local variables. */ 613 for (i = 0; i < operands; i++) 614 printf (" rtx operand%d;\n", i); 615 printf (" rtx _val = 0;\n"); 616 617 if (GET_CODE (split) == DEFINE_PEEPHOLE2) 618 output_peephole2_scratches (split); 619 620 printf (" start_sequence ();\n"); 621 622 /* The fourth operand of DEFINE_SPLIT is some code to be executed 623 before the actual construction. */ 624 625 if (XSTR (split, 3)) 626 printf ("%s\n", XSTR (split, 3)); 627 628 /* Output code to copy the arguments back out of `operands' */ 629 for (i = 0; i < operands; i++) 630 printf (" operand%d = operands[%d];\n", i, i); 631 632 /* Output code to construct the rtl for the instruction bodies. 633 Use emit_insn to add them to the sequence being accumulated. 634 But don't do this if the user's code has set `no_more' nonzero. */ 635 636 for (i = 0; i < XVECLEN (split, 2); i++) 637 { 638 rtx next = XVECEXP (split, 2, i); 639 if ((GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC) 640 || (GET_CODE (next) == PARALLEL 641 && GET_CODE (XVECEXP (next, 0, 0)) == SET 642 && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC) 643 || GET_CODE (next) == RETURN) 644 printf (" emit_jump_insn ("); 645 else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL) 646 || GET_CODE (next) == CALL 647 || (GET_CODE (next) == PARALLEL 648 && GET_CODE (XVECEXP (next, 0, 0)) == SET 649 && GET_CODE (SET_SRC (XVECEXP (next, 0, 0))) == CALL) 650 || (GET_CODE (next) == PARALLEL 651 && GET_CODE (XVECEXP (next, 0, 0)) == CALL)) 652 printf (" emit_call_insn ("); 653 else if (GET_CODE (next) == CODE_LABEL) 654 printf (" emit_label ("); 655 else if (GET_CODE (next) == MATCH_OPERAND 656 || GET_CODE (next) == MATCH_OPERATOR 657 || GET_CODE (next) == MATCH_PARALLEL 658 || GET_CODE (next) == MATCH_OP_DUP 659 || GET_CODE (next) == MATCH_DUP 660 || GET_CODE (next) == PARALLEL) 661 printf (" emit ("); 662 else 663 printf (" emit_insn ("); 664 gen_exp (next, GET_CODE (split), used); 665 printf (");\n"); 666 if (GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC 667 && GET_CODE (SET_SRC (next)) == LABEL_REF) 668 printf (" emit_barrier ();"); 669 } 670 671 /* Call `get_insns' to make a list of all the 672 insns emitted within this gen_... function. */ 673 674 printf (" _val = get_insns ();\n"); 675 printf (" end_sequence ();\n"); 676 printf (" return _val;\n}\n\n"); 677 678 free (used); 679} 680 681/* Write a function, `add_clobbers', that is given a PARALLEL of sufficient 682 size for the insn and an INSN_CODE, and inserts the required CLOBBERs at 683 the end of the vector. */ 684 685static void 686output_add_clobbers () 687{ 688 struct clobber_pat *clobber; 689 struct clobber_ent *ent; 690 int i; 691 692 printf ("\n\nvoid\nadd_clobbers (pattern, insn_code_number)\n"); 693 printf (" rtx pattern ATTRIBUTE_UNUSED;\n int insn_code_number;\n"); 694 printf ("{\n"); 695 printf (" switch (insn_code_number)\n"); 696 printf (" {\n"); 697 698 for (clobber = clobber_list; clobber; clobber = clobber->next) 699 { 700 for (ent = clobber->insns; ent; ent = ent->next) 701 printf (" case %d:\n", ent->code_number); 702 703 for (i = clobber->first_clobber; i < XVECLEN (clobber->pattern, 1); i++) 704 { 705 printf (" XVECEXP (pattern, 0, %d) = ", i); 706 gen_exp (XVECEXP (clobber->pattern, 1, i), 707 GET_CODE (clobber->pattern), NULL); 708 printf (";\n"); 709 } 710 711 printf (" break;\n\n"); 712 } 713 714 printf (" default:\n"); 715 printf (" abort ();\n"); 716 printf (" }\n"); 717 printf ("}\n"); 718} 719 720/* Write a function, `added_clobbers_hard_reg_p' this is given an insn_code 721 number that needs clobbers and returns 1 if they include a clobber of a 722 hard reg and 0 if they just clobber SCRATCH. */ 723 724static void 725output_added_clobbers_hard_reg_p () 726{ 727 struct clobber_pat *clobber; 728 struct clobber_ent *ent; 729 int clobber_p, used; 730 731 printf ("\n\nint\nadded_clobbers_hard_reg_p (insn_code_number)\n"); 732 printf (" int insn_code_number;\n"); 733 printf ("{\n"); 734 printf (" switch (insn_code_number)\n"); 735 printf (" {\n"); 736 737 for (clobber_p = 0; clobber_p <= 1; clobber_p++) 738 { 739 used = 0; 740 for (clobber = clobber_list; clobber; clobber = clobber->next) 741 if (clobber->has_hard_reg == clobber_p) 742 for (ent = clobber->insns; ent; ent = ent->next) 743 { 744 printf (" case %d:\n", ent->code_number); 745 used++; 746 } 747 748 if (used) 749 printf (" return %d;\n\n", clobber_p); 750 } 751 752 printf (" default:\n"); 753 printf (" abort ();\n"); 754 printf (" }\n"); 755 printf ("}\n"); 756} 757 758/* Generate code to invoke find_free_register () as needed for the 759 scratch registers used by the peephole2 pattern in SPLIT. */ 760 761static void 762output_peephole2_scratches (split) 763 rtx split; 764{ 765 int i; 766 int insn_nr = 0; 767 768 printf (" HARD_REG_SET _regs_allocated;\n"); 769 printf (" CLEAR_HARD_REG_SET (_regs_allocated);\n"); 770 771 for (i = 0; i < XVECLEN (split, 0); i++) 772 { 773 rtx elt = XVECEXP (split, 0, i); 774 if (GET_CODE (elt) == MATCH_SCRATCH) 775 { 776 int last_insn_nr = insn_nr; 777 int cur_insn_nr = insn_nr; 778 int j; 779 for (j = i + 1; j < XVECLEN (split, 0); j++) 780 if (GET_CODE (XVECEXP (split, 0, j)) == MATCH_DUP) 781 { 782 if (XINT (XVECEXP (split, 0, j), 0) == XINT (elt, 0)) 783 last_insn_nr = cur_insn_nr; 784 } 785 else if (GET_CODE (XVECEXP (split, 0, j)) != MATCH_SCRATCH) 786 cur_insn_nr++; 787 788 printf (" if ((operands[%d] = peep2_find_free_register (%d, %d, \"%s\", %smode, &_regs_allocated)) == NULL_RTX)\n\ 789 return NULL;\n", 790 XINT (elt, 0), 791 insn_nr, last_insn_nr, 792 XSTR (elt, 1), 793 GET_MODE_NAME (GET_MODE (elt))); 794 795 } 796 else if (GET_CODE (elt) != MATCH_DUP) 797 insn_nr++; 798 } 799} 800 801extern int main PARAMS ((int, char **)); 802 803int 804main (argc, argv) 805 int argc; 806 char **argv; 807{ 808 rtx desc; 809 810 progname = "genemit"; 811 812 if (argc <= 1) 813 fatal ("no input file name"); 814 815 if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE) 816 return (FATAL_EXIT_CODE); 817 818 /* Assign sequential codes to all entries in the machine description 819 in parallel with the tables in insn-output.c. */ 820 821 insn_code_number = 0; 822 insn_index_number = 0; 823 824 printf ("/* Generated automatically by the program `genemit'\n\ 825from the machine description file `md'. */\n\n"); 826 827 printf ("#include \"config.h\"\n"); 828 printf ("#include \"system.h\"\n"); 829 printf ("#include \"rtl.h\"\n"); 830 printf ("#include \"tm_p.h\"\n"); 831 printf ("#include \"function.h\"\n"); 832 printf ("#include \"expr.h\"\n"); 833 printf ("#include \"optabs.h\"\n"); 834 printf ("#include \"real.h\"\n"); 835 printf ("#include \"flags.h\"\n"); 836 printf ("#include \"output.h\"\n"); 837 printf ("#include \"insn-config.h\"\n"); 838 printf ("#include \"hard-reg-set.h\"\n"); 839 printf ("#include \"recog.h\"\n"); 840 printf ("#include \"resource.h\"\n"); 841 printf ("#include \"reload.h\"\n"); 842 printf ("#include \"toplev.h\"\n"); 843 printf ("#include \"ggc.h\"\n\n"); 844 printf ("#define FAIL return (end_sequence (), _val)\n"); 845 printf ("#define DONE return (_val = get_insns (), end_sequence (), _val)\n\n"); 846 847 /* Read the machine description. */ 848 849 while (1) 850 { 851 int line_no; 852 853 desc = read_md_rtx (&line_no, &insn_code_number); 854 if (desc == NULL) 855 break; 856 857 switch (GET_CODE (desc)) 858 { 859 case DEFINE_INSN: 860 gen_insn (desc, line_no); 861 break; 862 863 case DEFINE_EXPAND: 864 printf ("/* %s:%d */\n", read_rtx_filename, line_no); 865 gen_expand (desc); 866 break; 867 868 case DEFINE_SPLIT: 869 printf ("/* %s:%d */\n", read_rtx_filename, line_no); 870 gen_split (desc); 871 break; 872 873 case DEFINE_PEEPHOLE2: 874 printf ("/* %s:%d */\n", read_rtx_filename, line_no); 875 gen_split (desc); 876 break; 877 878 default: 879 break; 880 } 881 ++insn_index_number; 882 } 883 884 /* Write out the routines to add CLOBBERs to a pattern and say whether they 885 clobber a hard reg. */ 886 output_add_clobbers (); 887 output_added_clobbers_hard_reg_p (); 888 889 fflush (stdout); 890 return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); 891} 892 893/* Define this so we can link with print-rtl.o to get debug_rtx function. */ 894const char * 895get_insn_name (code) 896 int code ATTRIBUTE_UNUSED; 897{ 898 return NULL; 899} 900