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