|
|
1.1 root 1: /* Generate code from machine description to emit insns as rtl. 1.1.1.5 ! root 2: Copyright (C) 1987, 1988, 1991, 1994 Free Software Foundation, Inc. 1.1 root 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> 1.1.1.3 root 22: #include "hconfig.h" 1.1 root 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 (); 1.1.1.2 root 33: extern rtx read_rtx (); 1.1 root 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: { 1.1.1.2 root 51: struct clobber_ent *insns; 1.1 root 52: rtx pattern; 53: int first_clobber; 54: struct clobber_pat *next; 55: } *clobber_list; 56: 1.1.1.2 root 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: 1.1 root 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)); 1.1.1.3 root 86: if (code == MATCH_DUP || code == MATCH_OP_DUP || code == MATCH_PAR_DUP) 1.1 root 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: { 1.1.1.3 root 149: printf ("NULL_RTX"); 1.1 root 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: 1.1.1.3 root 185: case MATCH_PAR_DUP: 1.1 root 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) 1.1.1.3 root 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 (); 1.1 root 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; 1.1.1.5 ! root 239: printf (",\n\t"); 1.1 root 240: if (fmt[i] == 'e' || fmt[i] == 'u') 241: gen_exp (XEXP (x, i)); 242: else if (fmt[i] == 'i') 1.1.1.3 root 243: printf ("%u", XINT (x, i)); 1.1 root 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: { 1.1.1.2 root 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)); 1.1 root 325: 1.1.1.2 root 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; 1.1 root 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); 1.1.1.4 root 533: printf (" rtx _val = 0;\n"); 1.1 root 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; 1.1.1.2 root 603: struct clobber_ent *ent; 1.1 root 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: { 1.1.1.2 root 615: for (ent = clobber->insns; ent; ent = ent->next) 616: printf (" case %d:\n", ent->code_number); 1.1 root 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: 1.1.1.2 root 625: printf (" break;\n\n"); 1.1 root 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.