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