|
|
1.1 ! root 1: /* Generate code from to output assembler insns as recognized from rtl. ! 2: Copyright (C) 1987, 1988, 1992 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: /* This program reads the machine description for the compiler target machine ! 22: and produces a file containing these things: ! 23: ! 24: 1. An array of strings `insn_template' which is indexed by insn code number ! 25: and contains the template for output of that insn, ! 26: ! 27: 2. An array of functions `insn_outfun' which, indexed by the insn code ! 28: number, gives the function that returns a template to use for output of ! 29: that insn. This is used only in the cases where the template is not ! 30: constant. These cases are specified by a * or @ at the beginning of the ! 31: template string in the machine description. They are identified for the ! 32: sake of other parts of the compiler by a zero element in `insn_template'. ! 33: ! 34: 3. An array of functions `insn_gen_function' which, indexed ! 35: by insn code number, gives the function to generate a body ! 36: for that pattern, given operands as arguments. ! 37: ! 38: 4. An array of strings `insn_name' which, indexed by insn code number, ! 39: gives the name for that pattern. Nameless patterns are given a name. ! 40: ! 41: 5. An array of ints `insn_n_operands' which is indexed by insn code number ! 42: and contains the number of distinct operands in the pattern for that insn, ! 43: ! 44: 6. An array of ints `insn_n_dups' which is indexed by insn code number ! 45: and contains the number of match_dup's that appear in the insn's pattern. ! 46: This says how many elements of `recog_dup_loc' are significant ! 47: after an insn has been recognized. ! 48: ! 49: 7. An array of arrays of operand constraint strings, ! 50: `insn_operand_constraint', ! 51: indexed first by insn code number and second by operand number, ! 52: containing the constraint for that operand. ! 53: ! 54: This array is generated only if register constraints appear in ! 55: match_operand rtx's. ! 56: ! 57: 8. An array of arrays of chars which indicate which operands of ! 58: which insn patterns appear within ADDRESS rtx's. This array is ! 59: called `insn_operand_address_p' and is generated only if there ! 60: are *no* register constraints in the match_operand rtx's. ! 61: ! 62: 9. An array of arrays of machine modes, `insn_operand_mode', ! 63: indexed first by insn code number and second by operand number, ! 64: containing the machine mode that that operand is supposed to have. ! 65: Also `insn_operand_strict_low', which is nonzero for operands ! 66: contained in a STRICT_LOW_PART. ! 67: ! 68: 10. An array of arrays of int-valued functions, `insn_operand_predicate', ! 69: indexed first by insn code number and second by operand number, ! 70: containing the match_operand predicate for this operand. ! 71: ! 72: 11. An array of ints, `insn_n_alternatives', that gives the number ! 73: of alternatives in the constraints of each pattern. ! 74: ! 75: The code number of an insn is simply its position in the machine description; ! 76: code numbers are assigned sequentially to entries in the description, ! 77: starting with code number 0. ! 78: ! 79: Thus, the following entry in the machine description ! 80: ! 81: (define_insn "clrdf" ! 82: [(set (match_operand:DF 0 "general_operand" "") ! 83: (const_int 0))] ! 84: "" ! 85: "clrd %0") ! 86: ! 87: assuming it is the 25th entry present, would cause ! 88: insn_template[24] to be "clrd %0", and insn_n_operands[24] to be 1. ! 89: It would not make an case in output_insn_hairy because the template ! 90: given in the entry is a constant (it does not start with `*'). */ ! 91: ! 92: #include <stdio.h> ! 93: #include "config.h" ! 94: #include "rtl.h" ! 95: #include "obstack.h" ! 96: ! 97: /* No instruction can have more operands than this. ! 98: Sorry for this arbitrary limit, but what machine will ! 99: have an instruction with this many operands? */ ! 100: ! 101: #define MAX_MAX_OPERANDS 40 ! 102: ! 103: static struct obstack obstack; ! 104: struct obstack *rtl_obstack = &obstack; ! 105: ! 106: #define obstack_chunk_alloc xmalloc ! 107: #define obstack_chunk_free free ! 108: ! 109: extern void free (); ! 110: ! 111: char *xmalloc (); ! 112: static void fatal (); ! 113: void fancy_abort (); ! 114: static void error (); ! 115: static void mybcopy (); ! 116: static void mybzero (); ! 117: static int n_occurrences (); ! 118: ! 119: /* insns in the machine description are assigned sequential code numbers ! 120: that are used by insn-recog.c (produced by genrecog) to communicate ! 121: to insn-output.c (produced by this program). */ ! 122: ! 123: static int next_code_number; ! 124: ! 125: /* This counts all definitions in the md file, ! 126: for the sake of error messages. */ ! 127: ! 128: static int next_index_number; ! 129: ! 130: /* Record in this chain all information that we will output, ! 131: associated with the code number of the insn. */ ! 132: ! 133: struct data ! 134: { ! 135: int code_number; ! 136: int index_number; ! 137: char *name; ! 138: char *template; /* string such as "movl %1,%0" */ ! 139: int n_operands; /* Number of operands this insn recognizes */ ! 140: int n_dups; /* Number times match_dup appears in pattern */ ! 141: int n_alternatives; /* Number of alternatives in each constraint */ ! 142: struct data *next; ! 143: char *constraints[MAX_MAX_OPERANDS]; ! 144: /* Number of alternatives in constraints of operand N. */ ! 145: int op_n_alternatives[MAX_MAX_OPERANDS]; ! 146: char *predicates[MAX_MAX_OPERANDS]; ! 147: char address_p[MAX_MAX_OPERANDS]; ! 148: enum machine_mode modes[MAX_MAX_OPERANDS]; ! 149: char strict_low[MAX_MAX_OPERANDS]; ! 150: char outfun; /* Nonzero means this has an output function */ ! 151: }; ! 152: ! 153: /* This variable points to the first link in the chain. */ ! 154: ! 155: struct data *insn_data; ! 156: ! 157: /* Pointer to the last link in the chain, so new elements ! 158: can be added at the end. */ ! 159: ! 160: struct data *end_of_insn_data; ! 161: ! 162: /* Nonzero if any match_operand has a constraint string; ! 163: implies that REGISTER_CONSTRAINTS will be defined ! 164: for this machine description. */ ! 165: ! 166: int have_constraints; ! 167: ! 168: static void ! 169: output_prologue () ! 170: { ! 171: ! 172: printf ("/* Generated automatically by the program `genoutput'\n\ ! 173: from the machine description file `md'. */\n\n"); ! 174: ! 175: printf ("#include \"config.h\"\n"); ! 176: printf ("#include \"rtl.h\"\n"); ! 177: printf ("#include \"regs.h\"\n"); ! 178: printf ("#include \"hard-reg-set.h\"\n"); ! 179: printf ("#include \"real.h\"\n"); ! 180: printf ("#include \"insn-config.h\"\n\n"); ! 181: printf ("#include \"conditions.h\"\n"); ! 182: printf ("#include \"insn-flags.h\"\n"); ! 183: printf ("#include \"insn-attr.h\"\n\n"); ! 184: printf ("#include \"insn-codes.h\"\n\n"); ! 185: printf ("#include \"recog.h\"\n\n"); ! 186: ! 187: printf ("#include <stdio.h>\n"); ! 188: printf ("#include \"output.h\"\n"); ! 189: } ! 190: ! 191: static void ! 192: output_epilogue () ! 193: { ! 194: register struct data *d; ! 195: ! 196: printf ("\nchar * const insn_template[] =\n {\n"); ! 197: for (d = insn_data; d; d = d->next) ! 198: { ! 199: if (d->template) ! 200: printf (" \"%s\",\n", d->template); ! 201: else ! 202: printf (" 0,\n"); ! 203: } ! 204: printf (" };\n"); ! 205: ! 206: printf ("\nchar *(*const insn_outfun[])() =\n {\n"); ! 207: for (d = insn_data; d; d = d->next) ! 208: { ! 209: if (d->outfun) ! 210: printf (" output_%d,\n", d->code_number); ! 211: else ! 212: printf (" 0,\n"); ! 213: } ! 214: printf (" };\n"); ! 215: ! 216: printf ("\nrtx (*const insn_gen_function[]) () =\n {\n"); ! 217: for (d = insn_data; d; d = d->next) ! 218: { ! 219: if (d->name) ! 220: printf (" gen_%s,\n", d->name); ! 221: else ! 222: printf (" 0,\n"); ! 223: } ! 224: printf (" };\n"); ! 225: ! 226: printf ("\nchar *insn_name[] =\n {\n"); ! 227: { ! 228: int offset = 0; ! 229: int next; ! 230: char * last_name = 0; ! 231: char * next_name; ! 232: register struct data *n; ! 233: ! 234: for (n = insn_data, next = 0; n; n = n->next, next++) ! 235: if (n->name) ! 236: { ! 237: next_name = n->name; ! 238: break; ! 239: } ! 240: ! 241: for (d = insn_data; d; d = d->next) ! 242: { ! 243: if (d->name) ! 244: { ! 245: printf (" \"%s\",\n", d->name); ! 246: offset = 0; ! 247: last_name = d->name; ! 248: next_name = 0; ! 249: for (n = d->next, next = 1; n; n = n->next, next++) ! 250: if (n->name) ! 251: { ! 252: next_name = n->name; ! 253: break; ! 254: } ! 255: } ! 256: else ! 257: { ! 258: offset++; ! 259: if (next_name && (last_name == 0 || offset > next / 2)) ! 260: printf (" \"%s-%d\",\n", next_name, next - offset); ! 261: else ! 262: printf (" \"%s+%d\",\n", last_name, offset); ! 263: } ! 264: } ! 265: } ! 266: printf (" };\n"); ! 267: printf ("char **insn_name_ptr = insn_name;\n"); ! 268: ! 269: printf ("\nconst int insn_n_operands[] =\n {\n"); ! 270: for (d = insn_data; d; d = d->next) ! 271: printf (" %d,\n", d->n_operands); ! 272: printf (" };\n"); ! 273: ! 274: printf ("\nconst int insn_n_dups[] =\n {\n"); ! 275: for (d = insn_data; d; d = d->next) ! 276: printf (" %d,\n", d->n_dups); ! 277: printf (" };\n"); ! 278: ! 279: if (have_constraints) ! 280: { ! 281: printf ("\nchar *const insn_operand_constraint[][MAX_RECOG_OPERANDS] =\n {\n"); ! 282: for (d = insn_data; d; d = d->next) ! 283: { ! 284: register int i; ! 285: printf (" {"); ! 286: for (i = 0; i < d->n_operands; i++) ! 287: { ! 288: if (d->constraints[i] == 0) ! 289: printf (" \"\","); ! 290: else ! 291: printf (" \"%s\",", d->constraints[i]); ! 292: } ! 293: if (d->n_operands == 0) ! 294: printf (" 0"); ! 295: printf (" },\n"); ! 296: } ! 297: printf (" };\n"); ! 298: } ! 299: else ! 300: { ! 301: printf ("\nconst char insn_operand_address_p[][MAX_RECOG_OPERANDS] =\n {\n"); ! 302: for (d = insn_data; d; d = d->next) ! 303: { ! 304: register int i; ! 305: printf (" {"); ! 306: for (i = 0; i < d->n_operands; i++) ! 307: printf (" %d,", d->address_p[i]); ! 308: if (d->n_operands == 0) ! 309: printf (" 0"); ! 310: printf (" },\n"); ! 311: } ! 312: printf (" };\n"); ! 313: } ! 314: ! 315: printf ("\nconst enum machine_mode insn_operand_mode[][MAX_RECOG_OPERANDS] =\n {\n"); ! 316: for (d = insn_data; d; d = d->next) ! 317: { ! 318: register int i; ! 319: printf (" {"); ! 320: for (i = 0; i < d->n_operands; i++) ! 321: printf (" %smode,", GET_MODE_NAME (d->modes[i])); ! 322: if (d->n_operands == 0) ! 323: printf (" VOIDmode"); ! 324: printf (" },\n"); ! 325: } ! 326: printf (" };\n"); ! 327: ! 328: printf ("\nconst char insn_operand_strict_low[][MAX_RECOG_OPERANDS] =\n {\n"); ! 329: for (d = insn_data; d; d = d->next) ! 330: { ! 331: register int i; ! 332: printf (" {"); ! 333: for (i = 0; i < d->n_operands; i++) ! 334: printf (" %d,", d->strict_low[i]); ! 335: if (d->n_operands == 0) ! 336: printf (" 0"); ! 337: printf (" },\n"); ! 338: } ! 339: printf (" };\n"); ! 340: ! 341: { ! 342: /* We need to define all predicates used. Keep a list of those we ! 343: have defined so far. There normally aren't very many predicates used, ! 344: so a linked list should be fast enough. */ ! 345: struct predicate { char *name; struct predicate *next; } *predicates = 0; ! 346: struct predicate *p; ! 347: int i; ! 348: ! 349: printf ("\n"); ! 350: for (d = insn_data; d; d = d->next) ! 351: for (i = 0; i < d->n_operands; i++) ! 352: if (d->predicates[i] && d->predicates[i][0]) ! 353: { ! 354: for (p = predicates; p; p = p->next) ! 355: if (! strcmp (p->name, d->predicates[i])) ! 356: break; ! 357: ! 358: if (p == 0) ! 359: { ! 360: printf ("extern int %s ();\n", d->predicates[i]); ! 361: p = (struct predicate *) alloca (sizeof (struct predicate)); ! 362: p->name = d->predicates[i]; ! 363: p->next = predicates; ! 364: predicates = p; ! 365: } ! 366: } ! 367: ! 368: printf ("\nint (*const insn_operand_predicate[][MAX_RECOG_OPERANDS])() =\n {\n"); ! 369: for (d = insn_data; d; d = d->next) ! 370: { ! 371: printf (" {"); ! 372: for (i = 0; i < d->n_operands; i++) ! 373: printf (" %s,", ((d->predicates[i] && d->predicates[i][0]) ! 374: ? d->predicates[i] : "0")); ! 375: if (d->n_operands == 0) ! 376: printf (" 0"); ! 377: printf (" },\n"); ! 378: } ! 379: printf (" };\n"); ! 380: } ! 381: ! 382: printf ("\nconst int insn_n_alternatives[] =\n {\n"); ! 383: for (d = insn_data; d; d = d->next) ! 384: printf (" %d,\n", d->n_alternatives); ! 385: printf(" };\n"); ! 386: } ! 387: ! 388: /* scan_operands (X) stores in max_opno the largest operand ! 389: number present in X, if that is larger than the previous ! 390: value of max_opno. It stores all the constraints in `constraints' ! 391: and all the machine modes in `modes'. ! 392: ! 393: THIS_ADDRESS_P is nonzero if the containing rtx was an ADDRESS. ! 394: THIS_STRICT_LOW is nonzero if the containing rtx was a STRICT_LOW_PART. */ ! 395: ! 396: static int max_opno; ! 397: static int num_dups; ! 398: static char *constraints[MAX_MAX_OPERANDS]; ! 399: static int op_n_alternatives[MAX_MAX_OPERANDS]; ! 400: static char *predicates[MAX_MAX_OPERANDS]; ! 401: static char address_p[MAX_MAX_OPERANDS]; ! 402: static enum machine_mode modes[MAX_MAX_OPERANDS]; ! 403: static char strict_low[MAX_MAX_OPERANDS]; ! 404: static char seen[MAX_MAX_OPERANDS]; ! 405: ! 406: static void ! 407: scan_operands (part, this_address_p, this_strict_low) ! 408: rtx part; ! 409: int this_address_p; ! 410: int this_strict_low; ! 411: { ! 412: register int i, j; ! 413: register char *format_ptr; ! 414: int opno; ! 415: ! 416: if (part == 0) ! 417: return; ! 418: ! 419: switch (GET_CODE (part)) ! 420: { ! 421: case MATCH_OPERAND: ! 422: opno = XINT (part, 0); ! 423: if (opno > max_opno) ! 424: max_opno = opno; ! 425: if (max_opno >= MAX_MAX_OPERANDS) ! 426: { ! 427: error ("Too many operands (%d) in definition %d.\n", ! 428: max_opno + 1, next_index_number); ! 429: return; ! 430: } ! 431: if (seen[opno]) ! 432: error ("Definition %d specified operand number %d more than once.\n", ! 433: next_index_number, opno); ! 434: seen[opno] = 1; ! 435: modes[opno] = GET_MODE (part); ! 436: strict_low[opno] = this_strict_low; ! 437: predicates[opno] = XSTR (part, 1); ! 438: constraints[opno] = XSTR (part, 2); ! 439: if (XSTR (part, 2) != 0 && *XSTR (part, 2) != 0) ! 440: { ! 441: op_n_alternatives[opno] = n_occurrences (',', XSTR (part, 2)) + 1; ! 442: have_constraints = 1; ! 443: } ! 444: address_p[opno] = this_address_p; ! 445: return; ! 446: ! 447: case MATCH_SCRATCH: ! 448: opno = XINT (part, 0); ! 449: if (opno > max_opno) ! 450: max_opno = opno; ! 451: if (max_opno >= MAX_MAX_OPERANDS) ! 452: { ! 453: error ("Too many operands (%d) in definition %d.\n", ! 454: max_opno + 1, next_index_number); ! 455: return; ! 456: } ! 457: if (seen[opno]) ! 458: error ("Definition %d specified operand number %d more than once.\n", ! 459: next_index_number, opno); ! 460: seen[opno] = 1; ! 461: modes[opno] = GET_MODE (part); ! 462: strict_low[opno] = 0; ! 463: predicates[opno] = "scratch_operand"; ! 464: constraints[opno] = XSTR (part, 1); ! 465: if (XSTR (part, 1) != 0 && *XSTR (part, 1) != 0) ! 466: { ! 467: op_n_alternatives[opno] = n_occurrences (',', XSTR (part, 1)) + 1; ! 468: have_constraints = 1; ! 469: } ! 470: address_p[opno] = 0; ! 471: return; ! 472: ! 473: case MATCH_OPERATOR: ! 474: case MATCH_PARALLEL: ! 475: opno = XINT (part, 0); ! 476: if (opno > max_opno) ! 477: max_opno = opno; ! 478: if (max_opno >= MAX_MAX_OPERANDS) ! 479: { ! 480: error ("Too many operands (%d) in definition %d.\n", ! 481: max_opno + 1, next_index_number); ! 482: return; ! 483: } ! 484: if (seen[opno]) ! 485: error ("Definition %d specified operand number %d more than once.\n", ! 486: next_index_number, opno); ! 487: seen[opno] = 1; ! 488: modes[opno] = GET_MODE (part); ! 489: strict_low[opno] = 0; ! 490: predicates[opno] = XSTR (part, 1); ! 491: constraints[opno] = 0; ! 492: address_p[opno] = 0; ! 493: for (i = 0; i < XVECLEN (part, 2); i++) ! 494: scan_operands (XVECEXP (part, 2, i), 0, 0); ! 495: return; ! 496: ! 497: case MATCH_DUP: ! 498: case MATCH_OP_DUP: ! 499: ++num_dups; ! 500: return; ! 501: ! 502: case ADDRESS: ! 503: scan_operands (XEXP (part, 0), 1, 0); ! 504: return; ! 505: ! 506: case STRICT_LOW_PART: ! 507: scan_operands (XEXP (part, 0), 0, 1); ! 508: return; ! 509: } ! 510: ! 511: format_ptr = GET_RTX_FORMAT (GET_CODE (part)); ! 512: ! 513: for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++) ! 514: switch (*format_ptr++) ! 515: { ! 516: case 'e': ! 517: scan_operands (XEXP (part, i), 0, 0); ! 518: break; ! 519: case 'E': ! 520: if (XVEC (part, i) != NULL) ! 521: for (j = 0; j < XVECLEN (part, i); j++) ! 522: scan_operands (XVECEXP (part, i, j), 0, 0); ! 523: break; ! 524: } ! 525: } ! 526: ! 527: /* Process an assembler template from a define_insn or a define_peephole. ! 528: It is either the assembler code template, a list of assembler code ! 529: templates, or C code to generate the assembler code template. */ ! 530: ! 531: static void ! 532: process_template (d, template) ! 533: struct data *d; ! 534: char *template; ! 535: { ! 536: register char *cp; ! 537: register int i; ! 538: ! 539: /* We need to consider only the instructions whose assembler code template ! 540: starts with a * or @. These are the ones where C code is run to decide ! 541: on a template to use. So for all others just return now. */ ! 542: ! 543: if (template[0] != '*' && template[0] != '@') ! 544: { ! 545: d->template = template; ! 546: d->outfun = 0; ! 547: return; ! 548: } ! 549: ! 550: d->template = 0; ! 551: d->outfun = 1; ! 552: ! 553: printf ("\nstatic char *\n"); ! 554: printf ("output_%d (operands, insn)\n", d->code_number); ! 555: printf (" rtx *operands;\n"); ! 556: printf (" rtx insn;\n"); ! 557: printf ("{\n"); ! 558: ! 559: /* If the assembler code template starts with a @ it is a newline-separated ! 560: list of assembler code templates, one for each alternative. So produce ! 561: a routine to select the correct one. */ ! 562: ! 563: if (template[0] == '@') ! 564: { ! 565: ! 566: printf (" static /*const*/ char *const strings_%d[] = {\n", ! 567: d->code_number); ! 568: ! 569: for (i = 0, cp = &template[1]; *cp; ) ! 570: { ! 571: while (*cp == '\n' || *cp == ' ' || *cp== '\t') ! 572: cp++; ! 573: ! 574: printf (" \""); ! 575: while (*cp != '\n' && *cp != '\0') ! 576: putchar (*cp++); ! 577: ! 578: printf ("\",\n"); ! 579: i++; ! 580: } ! 581: ! 582: printf (" };\n"); ! 583: printf (" return strings_%d[which_alternative];\n", d->code_number); ! 584: ! 585: if (i != d->n_alternatives) ! 586: fatal ("Insn pattern %d has %d alternatives but %d assembler choices", ! 587: d->index_number, d->n_alternatives, i); ! 588: ! 589: } ! 590: else ! 591: { ! 592: /* The following is done in a funny way to get around problems in ! 593: VAX-11 "C" on VMS. It is the equivalent of: ! 594: printf ("%s\n", &template[1])); */ ! 595: cp = &template[1]; ! 596: while (*cp) putchar (*cp++); ! 597: putchar ('\n'); ! 598: } ! 599: ! 600: printf ("}\n"); ! 601: } ! 602: ! 603: /* Check insn D for consistency in number of constraint alternatives. */ ! 604: ! 605: static void ! 606: validate_insn_alternatives (d) ! 607: struct data *d; ! 608: { ! 609: register int n = 0, start; ! 610: /* Make sure all the operands have the same number of ! 611: alternatives in their constraints. ! 612: Let N be that number. */ ! 613: for (start = 0; start < d->n_operands; start++) ! 614: if (d->op_n_alternatives[start] > 0) ! 615: { ! 616: if (n == 0) ! 617: n = d->op_n_alternatives[start]; ! 618: else if (n != d->op_n_alternatives[start]) ! 619: error ("wrong number of alternatives in operand %d of insn number %d", ! 620: start, d->index_number); ! 621: } ! 622: /* Record the insn's overall number of alternatives. */ ! 623: d->n_alternatives = n; ! 624: } ! 625: ! 626: /* Look at a define_insn just read. Assign its code number. ! 627: Record on insn_data the template and the number of arguments. ! 628: If the insn has a hairy output action, output a function for now. */ ! 629: ! 630: static void ! 631: gen_insn (insn) ! 632: rtx insn; ! 633: { ! 634: register struct data *d = (struct data *) xmalloc (sizeof (struct data)); ! 635: register int i; ! 636: ! 637: d->code_number = next_code_number++; ! 638: d->index_number = next_index_number; ! 639: if (XSTR (insn, 0)[0]) ! 640: d->name = XSTR (insn, 0); ! 641: else ! 642: d->name = 0; ! 643: ! 644: /* Build up the list in the same order as the insns are seen ! 645: in the machine description. */ ! 646: d->next = 0; ! 647: if (end_of_insn_data) ! 648: end_of_insn_data->next = d; ! 649: else ! 650: insn_data = d; ! 651: ! 652: end_of_insn_data = d; ! 653: ! 654: max_opno = -1; ! 655: num_dups = 0; ! 656: ! 657: mybzero (constraints, sizeof constraints); ! 658: mybzero (op_n_alternatives, sizeof op_n_alternatives); ! 659: mybzero (predicates, sizeof predicates); ! 660: mybzero (address_p, sizeof address_p); ! 661: mybzero (modes, sizeof modes); ! 662: mybzero (strict_low, sizeof strict_low); ! 663: mybzero (seen, sizeof seen); ! 664: ! 665: for (i = 0; i < XVECLEN (insn, 1); i++) ! 666: scan_operands (XVECEXP (insn, 1, i), 0, 0); ! 667: ! 668: d->n_operands = max_opno + 1; ! 669: d->n_dups = num_dups; ! 670: ! 671: mybcopy (constraints, d->constraints, sizeof constraints); ! 672: mybcopy (op_n_alternatives, d->op_n_alternatives, sizeof op_n_alternatives); ! 673: mybcopy (predicates, d->predicates, sizeof predicates); ! 674: mybcopy (address_p, d->address_p, sizeof address_p); ! 675: mybcopy (modes, d->modes, sizeof modes); ! 676: mybcopy (strict_low, d->strict_low, sizeof strict_low); ! 677: ! 678: validate_insn_alternatives (d); ! 679: process_template (d, XSTR (insn, 3)); ! 680: } ! 681: ! 682: /* Look at a define_peephole just read. Assign its code number. ! 683: Record on insn_data the template and the number of arguments. ! 684: If the insn has a hairy output action, output it now. */ ! 685: ! 686: static void ! 687: gen_peephole (peep) ! 688: rtx peep; ! 689: { ! 690: register struct data *d = (struct data *) xmalloc (sizeof (struct data)); ! 691: register int i; ! 692: ! 693: d->code_number = next_code_number++; ! 694: d->index_number = next_index_number; ! 695: d->name = 0; ! 696: ! 697: /* Build up the list in the same order as the insns are seen ! 698: in the machine description. */ ! 699: d->next = 0; ! 700: if (end_of_insn_data) ! 701: end_of_insn_data->next = d; ! 702: else ! 703: insn_data = d; ! 704: ! 705: end_of_insn_data = d; ! 706: ! 707: max_opno = -1; ! 708: mybzero (constraints, sizeof constraints); ! 709: mybzero (op_n_alternatives, sizeof op_n_alternatives); ! 710: mybzero (predicates, sizeof predicates); ! 711: mybzero (address_p, sizeof address_p); ! 712: mybzero (modes, sizeof modes); ! 713: mybzero (strict_low, sizeof strict_low); ! 714: mybzero (seen, sizeof seen); ! 715: ! 716: /* Get the number of operands by scanning all the ! 717: patterns of the peephole optimizer. ! 718: But ignore all the rest of the information thus obtained. */ ! 719: for (i = 0; i < XVECLEN (peep, 0); i++) ! 720: scan_operands (XVECEXP (peep, 0, i), 0, 0); ! 721: ! 722: d->n_operands = max_opno + 1; ! 723: d->n_dups = 0; ! 724: ! 725: mybcopy (constraints, d->constraints, sizeof constraints); ! 726: mybcopy (op_n_alternatives, d->op_n_alternatives, sizeof op_n_alternatives); ! 727: mybzero (d->predicates, sizeof predicates); ! 728: mybzero (d->address_p, sizeof address_p); ! 729: mybzero (d->modes, sizeof modes); ! 730: mybzero (d->strict_low, sizeof strict_low); ! 731: ! 732: validate_insn_alternatives (d); ! 733: process_template (d, XSTR (peep, 2)); ! 734: } ! 735: ! 736: /* Process a define_expand just read. Assign its code number, ! 737: only for the purposes of `insn_gen_function'. */ ! 738: ! 739: static void ! 740: gen_expand (insn) ! 741: rtx insn; ! 742: { ! 743: register struct data *d = (struct data *) xmalloc (sizeof (struct data)); ! 744: register int i; ! 745: ! 746: d->code_number = next_code_number++; ! 747: d->index_number = next_index_number; ! 748: if (XSTR (insn, 0)[0]) ! 749: d->name = XSTR (insn, 0); ! 750: else ! 751: d->name = 0; ! 752: ! 753: /* Build up the list in the same order as the insns are seen ! 754: in the machine description. */ ! 755: d->next = 0; ! 756: if (end_of_insn_data) ! 757: end_of_insn_data->next = d; ! 758: else ! 759: insn_data = d; ! 760: ! 761: end_of_insn_data = d; ! 762: ! 763: max_opno = -1; ! 764: num_dups = 0; ! 765: ! 766: /* Scan the operands to get the specified predicates and modes, ! 767: since expand_binop needs to know them. */ ! 768: ! 769: mybzero (constraints, sizeof constraints); ! 770: mybzero (op_n_alternatives, sizeof op_n_alternatives); ! 771: mybzero (predicates, sizeof predicates); ! 772: mybzero (address_p, sizeof address_p); ! 773: mybzero (modes, sizeof modes); ! 774: mybzero (strict_low, sizeof strict_low); ! 775: mybzero (seen, sizeof seen); ! 776: ! 777: if (XVEC (insn, 1)) ! 778: for (i = 0; i < XVECLEN (insn, 1); i++) ! 779: scan_operands (XVECEXP (insn, 1, i), 0, 0); ! 780: ! 781: d->n_operands = max_opno + 1; ! 782: d->n_dups = num_dups; ! 783: ! 784: mybcopy (constraints, d->constraints, sizeof constraints); ! 785: mybcopy (op_n_alternatives, d->op_n_alternatives, sizeof op_n_alternatives); ! 786: mybcopy (predicates, d->predicates, sizeof predicates); ! 787: mybcopy (address_p, d->address_p, sizeof address_p); ! 788: mybcopy (modes, d->modes, sizeof modes); ! 789: mybcopy (strict_low, d->strict_low, sizeof strict_low); ! 790: ! 791: d->template = 0; ! 792: d->outfun = 0; ! 793: validate_insn_alternatives (d); ! 794: } ! 795: ! 796: /* Process a define_split just read. Assign its code number, ! 797: only for reasons of consistency and to simplify genrecog. */ ! 798: ! 799: ! 800: static void ! 801: gen_split (split) ! 802: rtx split; ! 803: { ! 804: register struct data *d = (struct data *) xmalloc (sizeof (struct data)); ! 805: register int i; ! 806: ! 807: d->code_number = next_code_number++; ! 808: d->index_number = next_index_number; ! 809: d->name = 0; ! 810: ! 811: /* Build up the list in the same order as the insns are seen ! 812: in the machine description. */ ! 813: d->next = 0; ! 814: if (end_of_insn_data) ! 815: end_of_insn_data->next = d; ! 816: else ! 817: insn_data = d; ! 818: ! 819: end_of_insn_data = d; ! 820: ! 821: max_opno = -1; ! 822: num_dups = 0; ! 823: ! 824: mybzero (constraints, sizeof constraints); ! 825: mybzero (op_n_alternatives, sizeof op_n_alternatives); ! 826: mybzero (predicates, sizeof predicates); ! 827: mybzero (address_p, sizeof address_p); ! 828: mybzero (modes, sizeof modes); ! 829: mybzero (strict_low, sizeof strict_low); ! 830: mybzero (seen, sizeof seen); ! 831: ! 832: /* Get the number of operands by scanning all the ! 833: patterns of the split patterns. ! 834: But ignore all the rest of the information thus obtained. */ ! 835: for (i = 0; i < XVECLEN (split, 0); i++) ! 836: scan_operands (XVECEXP (split, 0, i), 0, 0); ! 837: ! 838: d->n_operands = max_opno + 1; ! 839: ! 840: mybzero (d->constraints, sizeof constraints); ! 841: mybzero (d->op_n_alternatives, sizeof op_n_alternatives); ! 842: mybzero (d->predicates, sizeof predicates); ! 843: mybzero (d->address_p, sizeof address_p); ! 844: mybzero (d->modes, sizeof modes); ! 845: mybzero (d->strict_low, sizeof strict_low); ! 846: ! 847: d->n_dups = 0; ! 848: d->template = 0; ! 849: d->outfun = 0; ! 850: } ! 851: ! 852: char * ! 853: xmalloc (size) ! 854: unsigned size; ! 855: { ! 856: register char *val = (char *) malloc (size); ! 857: ! 858: if (val == 0) ! 859: fatal ("virtual memory exhausted"); ! 860: return val; ! 861: } ! 862: ! 863: char * ! 864: xrealloc (ptr, size) ! 865: char *ptr; ! 866: unsigned size; ! 867: { ! 868: char *result = (char *) realloc (ptr, size); ! 869: if (!result) ! 870: fatal ("virtual memory exhausted"); ! 871: return result; ! 872: } ! 873: ! 874: static void ! 875: mybzero (b, length) ! 876: register char *b; ! 877: register unsigned length; ! 878: { ! 879: while (length-- > 0) ! 880: *b++ = 0; ! 881: } ! 882: ! 883: static void ! 884: mybcopy (b1, b2, length) ! 885: register char *b1; ! 886: register char *b2; ! 887: register unsigned length; ! 888: { ! 889: while (length-- > 0) ! 890: *b2++ = *b1++; ! 891: } ! 892: ! 893: static void ! 894: fatal (s, a1, a2, a3, a4) ! 895: char *s; ! 896: { ! 897: fprintf (stderr, "genoutput: "); ! 898: fprintf (stderr, s, a1, a2, a3, a4); ! 899: fprintf (stderr, "\n"); ! 900: exit (FATAL_EXIT_CODE); ! 901: } ! 902: ! 903: /* More 'friendly' abort that prints the line and file. ! 904: config.h can #define abort fancy_abort if you like that sort of thing. */ ! 905: ! 906: void ! 907: fancy_abort () ! 908: { ! 909: fatal ("Internal gcc abort."); ! 910: } ! 911: ! 912: static void ! 913: error (s, a1, a2) ! 914: char *s; ! 915: { ! 916: fprintf (stderr, "genoutput: "); ! 917: fprintf (stderr, s, a1, a2); ! 918: fprintf (stderr, "\n"); ! 919: } ! 920: ! 921: int ! 922: main (argc, argv) ! 923: int argc; ! 924: char **argv; ! 925: { ! 926: rtx desc; ! 927: FILE *infile; ! 928: extern rtx read_rtx (); ! 929: register int c; ! 930: ! 931: obstack_init (rtl_obstack); ! 932: ! 933: if (argc <= 1) ! 934: fatal ("No input file name."); ! 935: ! 936: infile = fopen (argv[1], "r"); ! 937: if (infile == 0) ! 938: { ! 939: perror (argv[1]); ! 940: exit (FATAL_EXIT_CODE); ! 941: } ! 942: ! 943: init_rtl (); ! 944: ! 945: output_prologue (); ! 946: next_code_number = 0; ! 947: next_index_number = 0; ! 948: have_constraints = 0; ! 949: ! 950: /* Read the machine description. */ ! 951: ! 952: while (1) ! 953: { ! 954: c = read_skip_spaces (infile); ! 955: if (c == EOF) ! 956: break; ! 957: ungetc (c, infile); ! 958: ! 959: desc = read_rtx (infile); ! 960: if (GET_CODE (desc) == DEFINE_INSN) ! 961: gen_insn (desc); ! 962: if (GET_CODE (desc) == DEFINE_PEEPHOLE) ! 963: gen_peephole (desc); ! 964: if (GET_CODE (desc) == DEFINE_EXPAND) ! 965: gen_expand (desc); ! 966: if (GET_CODE (desc) == DEFINE_SPLIT) ! 967: gen_split (desc); ! 968: next_index_number++; ! 969: } ! 970: ! 971: output_epilogue (); ! 972: ! 973: fflush (stdout); ! 974: exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); ! 975: /* NOTREACHED */ ! 976: return 0; ! 977: } ! 978: ! 979: static int ! 980: n_occurrences (c, s) ! 981: char c; ! 982: char *s; ! 983: { ! 984: int n = 0; ! 985: while (*s) ! 986: n += (*s++ == c); ! 987: return n; ! 988: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.