|
|
1.1 ! root 1: /* Generate attribute information (insn-attr.h) from machine description. ! 2: Copyright (C) 1991 Free Software Foundation, Inc. ! 3: Contributed by Richard Kenner ([email protected]) ! 4: ! 5: This file is part of GNU CC. ! 6: ! 7: GNU CC is free software; you can redistribute it and/or modify ! 8: it under the terms of the GNU General Public License as published by ! 9: the Free Software Foundation; either version 2, or (at your option) ! 10: any later version. ! 11: ! 12: GNU CC is distributed in the hope that it will be useful, ! 13: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 15: GNU General Public License for more details. ! 16: ! 17: You should have received a copy of the GNU General Public License ! 18: along with GNU CC; see the file COPYING. If not, write to ! 19: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! 20: ! 21: ! 22: #include <stdio.h> ! 23: #include "hconfig.h" ! 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 PROTO((void *)); ! 34: extern int atoi PROTO((char *)); ! 35: extern rtx read_rtx PROTO((FILE *)); ! 36: ! 37: char *xmalloc PROTO((unsigned)); ! 38: static void fatal (); ! 39: void fancy_abort PROTO((void)); ! 40: ! 41: /* A range of values. */ ! 42: ! 43: struct range ! 44: { ! 45: int min; ! 46: int max; ! 47: }; ! 48: ! 49: /* Record information about each function unit mentioned in a ! 50: DEFINE_FUNCTION_UNIT. */ ! 51: ! 52: struct function_unit ! 53: { ! 54: char *name; /* Function unit name. */ ! 55: struct function_unit *next; /* Next function unit. */ ! 56: int multiplicity; /* Number of units of this type. */ ! 57: int simultaneity; /* Maximum number of simultaneous insns ! 58: on this function unit or 0 if unlimited. */ ! 59: struct range ready_cost; /* Range of ready cost values. */ ! 60: struct range issue_delay; /* Range of issue delay values. */ ! 61: }; ! 62: ! 63: static void ! 64: extend_range (range, min, max) ! 65: struct range *range; ! 66: int min; ! 67: int max; ! 68: { ! 69: if (range->min > min) range->min = min; ! 70: if (range->max < max) range->max = max; ! 71: } ! 72: ! 73: static void ! 74: init_range (range) ! 75: struct range *range; ! 76: { ! 77: range->min = 100000; ! 78: range->max = -1; ! 79: } ! 80: ! 81: static void ! 82: write_upcase (str) ! 83: char *str; ! 84: { ! 85: for (; *str; str++) ! 86: if (*str >= 'a' && *str <= 'z') ! 87: printf ("%c", *str - 'a' + 'A'); ! 88: else ! 89: printf ("%c", *str); ! 90: } ! 91: ! 92: static void ! 93: gen_attr (attr) ! 94: rtx attr; ! 95: { ! 96: char *p; ! 97: ! 98: printf ("#define HAVE_ATTR_%s\n", XSTR (attr, 0)); ! 99: ! 100: /* If numeric attribute, don't need to write an enum. */ ! 101: if (*XSTR (attr, 1) == '\0') ! 102: printf ("extern int get_attr_%s ();\n", XSTR (attr, 0)); ! 103: else ! 104: { ! 105: printf ("enum attr_%s {", XSTR (attr, 0)); ! 106: write_upcase (XSTR (attr, 0)); ! 107: printf ("_"); ! 108: ! 109: for (p = XSTR (attr, 1); *p != '\0'; p++) ! 110: { ! 111: if (*p == ',') ! 112: { ! 113: printf (", "); ! 114: write_upcase (XSTR (attr, 0)); ! 115: printf ("_"); ! 116: } ! 117: else if (*p >= 'a' && *p <= 'z') ! 118: printf ("%c", *p - 'a' + 'A'); ! 119: else ! 120: printf ("%c", *p); ! 121: } ! 122: ! 123: printf ("};\n"); ! 124: printf ("extern enum attr_%s get_attr_%s ();\n\n", ! 125: XSTR (attr, 0), XSTR (attr, 0)); ! 126: } ! 127: ! 128: /* If `length' attribute, write additional function definitions and define ! 129: variables used by `insn_current_length'. */ ! 130: if (! strcmp (XSTR (attr, 0), "length")) ! 131: { ! 132: printf ("extern void init_lengths ();\n"); ! 133: printf ("extern void shorten_branches PROTO((rtx));\n"); ! 134: printf ("extern int insn_default_length PROTO((rtx));\n"); ! 135: printf ("extern int insn_variable_length_p PROTO((rtx));\n"); ! 136: printf ("extern int insn_current_length PROTO((rtx));\n\n"); ! 137: printf ("extern int *insn_addresses;\n"); ! 138: printf ("extern int insn_current_address;\n\n"); ! 139: } ! 140: } ! 141: ! 142: static void ! 143: write_units (num_units, multiplicity, simultaneity, ! 144: ready_cost, issue_delay, blockage) ! 145: int num_units; ! 146: struct range *multiplicity; ! 147: struct range *simultaneity; ! 148: struct range *ready_cost; ! 149: struct range *issue_delay; ! 150: struct range *blockage; ! 151: { ! 152: int i, q_size; ! 153: ! 154: printf ("#define INSN_SCHEDULING\n\n"); ! 155: printf ("extern int result_ready_cost PROTO((rtx));\n"); ! 156: printf ("extern int function_units_used PROTO((rtx));\n\n"); ! 157: printf ("extern struct function_unit_desc\n"); ! 158: printf ("{\n"); ! 159: printf (" char *name;\n"); ! 160: printf (" int bitmask;\n"); ! 161: printf (" int multiplicity;\n"); ! 162: printf (" int simultaneity;\n"); ! 163: printf (" int default_cost;\n"); ! 164: printf (" int max_issue_delay;\n"); ! 165: printf (" int (*ready_cost_function) ();\n"); ! 166: printf (" int (*conflict_cost_function) ();\n"); ! 167: printf (" int max_blockage;\n"); ! 168: printf (" unsigned int (*blockage_range_function) ();\n"); ! 169: printf (" int (*blockage_function) ();\n"); ! 170: printf ("} function_units[];\n\n"); ! 171: printf ("#define FUNCTION_UNITS_SIZE %d\n", num_units); ! 172: printf ("#define MIN_MULTIPLICITY %d\n", multiplicity->min); ! 173: printf ("#define MAX_MULTIPLICITY %d\n", multiplicity->max); ! 174: printf ("#define MIN_SIMULTANEITY %d\n", simultaneity->min); ! 175: printf ("#define MAX_SIMULTANEITY %d\n", simultaneity->max); ! 176: printf ("#define MIN_READY_COST %d\n", ready_cost->min); ! 177: printf ("#define MAX_READY_COST %d\n", ready_cost->max); ! 178: printf ("#define MIN_ISSUE_DELAY %d\n", issue_delay->min); ! 179: printf ("#define MAX_ISSUE_DELAY %d\n", issue_delay->max); ! 180: printf ("#define MIN_BLOCKAGE %d\n", blockage->min); ! 181: printf ("#define MAX_BLOCKAGE %d\n", blockage->max); ! 182: for (i = 0; (1 << i) < blockage->max; i++) ! 183: ; ! 184: printf ("#define BLOCKAGE_BITS %d\n", i + 1); ! 185: ! 186: /* INSN_QUEUE_SIZE is a power of two larger than MAX_BLOCKAGE and ! 187: MAX_READY_COST. This is the longest time an isnsn may be queued. */ ! 188: i = MAX (blockage->max, ready_cost->max); ! 189: for (q_size = 1; q_size <= i; q_size <<= 1) ! 190: ; ! 191: printf ("#define INSN_QUEUE_SIZE %d\n", q_size); ! 192: } ! 193: ! 194: char * ! 195: xmalloc (size) ! 196: unsigned size; ! 197: { ! 198: register char *val = (char *) malloc (size); ! 199: ! 200: if (val == 0) ! 201: fatal ("virtual memory exhausted"); ! 202: return val; ! 203: } ! 204: ! 205: char * ! 206: xrealloc (ptr, size) ! 207: char *ptr; ! 208: unsigned size; ! 209: { ! 210: char * result = (char *) realloc (ptr, size); ! 211: if (!result) ! 212: fatal ("virtual memory exhausted"); ! 213: return result; ! 214: } ! 215: ! 216: static void ! 217: fatal (s, a1, a2) ! 218: char *s; ! 219: { ! 220: fprintf (stderr, "genattr: "); ! 221: fprintf (stderr, s, a1, a2); ! 222: fprintf (stderr, "\n"); ! 223: exit (FATAL_EXIT_CODE); ! 224: } ! 225: ! 226: /* More 'friendly' abort that prints the line and file. ! 227: config.h can #define abort fancy_abort if you like that sort of thing. */ ! 228: ! 229: void ! 230: fancy_abort () ! 231: { ! 232: fatal ("Internal gcc abort."); ! 233: } ! 234: ! 235: int ! 236: main (argc, argv) ! 237: int argc; ! 238: char **argv; ! 239: { ! 240: rtx desc; ! 241: FILE *infile; ! 242: register int c; ! 243: int have_delay = 0; ! 244: int have_annul_true = 0; ! 245: int have_annul_false = 0; ! 246: int num_units = 0; ! 247: struct range all_simultaneity, all_multiplicity; ! 248: struct range all_ready_cost, all_issue_delay, all_blockage; ! 249: struct function_unit *units = 0, *unit; ! 250: int i; ! 251: ! 252: init_range (&all_multiplicity); ! 253: init_range (&all_simultaneity); ! 254: init_range (&all_ready_cost); ! 255: init_range (&all_issue_delay); ! 256: init_range (&all_blockage); ! 257: ! 258: obstack_init (rtl_obstack); ! 259: ! 260: if (argc <= 1) ! 261: fatal ("No input file name."); ! 262: ! 263: infile = fopen (argv[1], "r"); ! 264: if (infile == 0) ! 265: { ! 266: perror (argv[1]); ! 267: exit (FATAL_EXIT_CODE); ! 268: } ! 269: ! 270: init_rtl (); ! 271: ! 272: printf ("/* Generated automatically by the program `genattr'\n\ ! 273: from the machine description file `md'. */\n\n"); ! 274: ! 275: /* For compatibility, define the attribute `alternative', which is just ! 276: a reference to the variable `which_alternative'. */ ! 277: ! 278: printf("#ifndef PROTO\n"); ! 279: printf("#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)\n"); ! 280: printf("#define PROTO(ARGS) ARGS\n"); ! 281: printf("#else\n"); ! 282: printf("#define PROTO(ARGS) ()\n"); ! 283: printf("#endif\n"); ! 284: printf("#endif\n"); ! 285: ! 286: printf ("#define HAVE_ATTR_alternative\n"); ! 287: printf ("#define get_attr_alternative(insn) which_alternative\n"); ! 288: ! 289: /* Read the machine description. */ ! 290: ! 291: while (1) ! 292: { ! 293: c = read_skip_spaces (infile); ! 294: if (c == EOF) ! 295: break; ! 296: ungetc (c, infile); ! 297: ! 298: desc = read_rtx (infile); ! 299: if (GET_CODE (desc) == DEFINE_ATTR) ! 300: gen_attr (desc); ! 301: ! 302: else if (GET_CODE (desc) == DEFINE_DELAY) ! 303: { ! 304: if (! have_delay) ! 305: { ! 306: printf ("#define DELAY_SLOTS\n"); ! 307: printf ("extern int num_delay_slots PROTO((rtx));\n"); ! 308: printf ("extern int eligible_for_delay PROTO((rtx, int, rtx, int));\n\n"); ! 309: printf ("extern int const_num_delay_slots PROTO((rtx));\n\n"); ! 310: have_delay = 1; ! 311: } ! 312: ! 313: for (i = 0; i < XVECLEN (desc, 1); i += 3) ! 314: { ! 315: if (XVECEXP (desc, 1, i + 1) && ! have_annul_true) ! 316: { ! 317: printf ("#define ANNUL_IFTRUE_SLOTS\n"); ! 318: printf ("extern int eligible_for_annul_true ();\n"); ! 319: have_annul_true = 1; ! 320: } ! 321: ! 322: if (XVECEXP (desc, 1, i + 2) && ! have_annul_false) ! 323: { ! 324: printf ("#define ANNUL_IFFALSE_SLOTS\n"); ! 325: printf ("extern int eligible_for_annul_false ();\n"); ! 326: have_annul_false = 1; ! 327: } ! 328: } ! 329: } ! 330: ! 331: else if (GET_CODE (desc) == DEFINE_FUNCTION_UNIT) ! 332: { ! 333: char *name = XSTR (desc, 0); ! 334: int multiplicity = XINT (desc, 1); ! 335: int simultaneity = XINT (desc, 2); ! 336: int ready_cost = MAX (XINT (desc, 4), 1); ! 337: int issue_delay = MAX (XINT (desc, 5), 1); ! 338: int issueexp_p = (XVEC (desc, 6) != 0); ! 339: ! 340: for (unit = units; unit; unit = unit->next) ! 341: if (strcmp (unit->name, name) == 0) ! 342: break; ! 343: ! 344: if (unit == 0) ! 345: { ! 346: int len = strlen (name) + 1; ! 347: unit = (struct function_unit *) ! 348: alloca (sizeof (struct function_unit)); ! 349: unit->name = (char *) alloca (len); ! 350: bcopy (name, unit->name, len); ! 351: unit->multiplicity = multiplicity; ! 352: unit->simultaneity = simultaneity; ! 353: unit->ready_cost.min = unit->ready_cost.max = ready_cost; ! 354: unit->issue_delay.min = unit->issue_delay.max = issue_delay; ! 355: unit->next = units; ! 356: units = unit; ! 357: num_units++; ! 358: ! 359: extend_range (&all_multiplicity, multiplicity, multiplicity); ! 360: extend_range (&all_simultaneity, simultaneity, simultaneity); ! 361: } ! 362: else if (unit->multiplicity != multiplicity ! 363: || unit->simultaneity != simultaneity) ! 364: fatal ("Differing specifications given for `%s' function unit.", ! 365: unit->name); ! 366: ! 367: extend_range (&unit->ready_cost, ready_cost, ready_cost); ! 368: extend_range (&unit->issue_delay, ! 369: issueexp_p ? 1 : issue_delay, issue_delay); ! 370: extend_range (&all_ready_cost, ! 371: unit->ready_cost.min, unit->ready_cost.max); ! 372: extend_range (&all_issue_delay, ! 373: unit->issue_delay.min, unit->issue_delay.max); ! 374: } ! 375: } ! 376: ! 377: if (num_units > 0) ! 378: { ! 379: /* Compute the range of blockage cost values. See genattrtab.c ! 380: for the derivation. BLOCKAGE (E,C) when SIMULTANEITY is zero is ! 381: ! 382: MAX (ISSUE-DELAY (E,C), ! 383: READY-COST (E) - (READY-COST (C) - 1)) ! 384: ! 385: and otherwise ! 386: ! 387: MAX (ISSUE-DELAY (E,C), ! 388: READY-COST (E) - (READY-COST (C) - 1), ! 389: READY-COST (E) - FILL-TIME) */ ! 390: ! 391: for (unit = units; unit; unit = unit->next) ! 392: { ! 393: struct range blockage; ! 394: int max_issue_time = MAX (unit->issue_delay.max, 1); ! 395: ! 396: blockage = unit->issue_delay; ! 397: blockage.max = MAX (unit->ready_cost.max ! 398: - (unit->ready_cost.min - 1), ! 399: blockage.max); ! 400: blockage.min = MAX (1, blockage.min); ! 401: ! 402: if (unit->simultaneity != 0) ! 403: { ! 404: int fill_time = ((unit->simultaneity - 1) ! 405: * unit->issue_delay.min); ! 406: blockage.min = MAX (unit->ready_cost.min - fill_time, ! 407: blockage.min); ! 408: blockage.max = MAX (unit->ready_cost.max - fill_time, ! 409: blockage.max); ! 410: } ! 411: extend_range (&all_blockage, blockage.min, blockage.max); ! 412: } ! 413: ! 414: write_units (num_units, &all_multiplicity, &all_simultaneity, ! 415: &all_ready_cost, &all_issue_delay, &all_blockage); ! 416: } ! 417: ! 418: /* Output flag masks for use by reorg. ! 419: ! 420: Flags are used to hold branch direction and prediction information ! 421: for use by eligible_for_... */ ! 422: printf("\n#define ATTR_FLAG_forward 0x1\n"); ! 423: printf("#define ATTR_FLAG_backward 0x2\n"); ! 424: printf("#define ATTR_FLAG_likely 0x4\n"); ! 425: printf("#define ATTR_FLAG_very_likely 0x8\n"); ! 426: printf("#define ATTR_FLAG_unlikely 0x10\n"); ! 427: printf("#define ATTR_FLAG_very_unlikely 0x20\n"); ! 428: ! 429: fflush (stdout); ! 430: exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); ! 431: /* NOTREACHED */ ! 432: return 0; ! 433: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.