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