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