genattr.c revision 96489
1/* Generate attribute information (insn-attr.h) from machine description. 2 Copyright (C) 1991, 1994, 1996, 1998, 1999, 2000 Free Software Foundation, Inc. 3 Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) 4 5This file is part of GCC. 6 7GCC is free software; you can redistribute it and/or modify it under 8the terms of the GNU General Public License as published by the Free 9Software Foundation; either version 2, or (at your option) any later 10version. 11 12GCC is distributed in the hope that it will be useful, but WITHOUT ANY 13WARRANTY; without even the implied warranty of MERCHANTABILITY or 14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15for more details. 16 17You should have received a copy of the GNU General Public License 18along with GCC; see the file COPYING. If not, write to the Free 19Software Foundation, 59 Temple Place - Suite 330, Boston, MA 2002111-1307, USA. */ 21 22 23#include "hconfig.h" 24#include "system.h" 25#include "rtl.h" 26#include "errors.h" 27#include "gensupport.h" 28 29 30/* A range of values. */ 31 32struct range 33{ 34 int min; 35 int max; 36}; 37 38/* Record information about each function unit mentioned in a 39 DEFINE_FUNCTION_UNIT. */ 40 41struct function_unit 42{ 43 char *name; /* Function unit name. */ 44 struct function_unit *next; /* Next function unit. */ 45 int multiplicity; /* Number of units of this type. */ 46 int simultaneity; /* Maximum number of simultaneous insns 47 on this function unit or 0 if unlimited. */ 48 struct range ready_cost; /* Range of ready cost values. */ 49 struct range issue_delay; /* Range of issue delay values. */ 50}; 51 52static void extend_range PARAMS ((struct range *, int, int)); 53static void init_range PARAMS ((struct range *)); 54static void write_upcase PARAMS ((const char *)); 55static void gen_attr PARAMS ((rtx)); 56static void write_units PARAMS ((int, struct range *, struct range *, 57 struct range *, struct range *, 58 struct range *)); 59static void 60extend_range (range, min, max) 61 struct range *range; 62 int min; 63 int max; 64{ 65 if (range->min > min) range->min = min; 66 if (range->max < max) range->max = max; 67} 68 69static void 70init_range (range) 71 struct range *range; 72{ 73 range->min = 100000; 74 range->max = -1; 75} 76 77static void 78write_upcase (str) 79 const char *str; 80{ 81 for (; *str; str++) 82 putchar (TOUPPER(*str)); 83} 84 85static void 86gen_attr (attr) 87 rtx attr; 88{ 89 const char *p; 90 int is_const = GET_CODE (XEXP (attr, 2)) == CONST; 91 92 printf ("#define HAVE_ATTR_%s\n", XSTR (attr, 0)); 93 94 /* If numeric attribute, don't need to write an enum. */ 95 if (*XSTR (attr, 1) == '\0') 96 printf ("extern int get_attr_%s PARAMS ((%s));\n", XSTR (attr, 0), 97 (is_const ? "void" : "rtx")); 98 else 99 { 100 printf ("enum attr_%s {", XSTR (attr, 0)); 101 write_upcase (XSTR (attr, 0)); 102 printf ("_"); 103 104 for (p = XSTR (attr, 1); *p != '\0'; p++) 105 { 106 if (*p == ',') 107 { 108 printf (", "); 109 write_upcase (XSTR (attr, 0)); 110 printf ("_"); 111 } 112 else 113 putchar (TOUPPER(*p)); 114 } 115 116 printf ("};\n"); 117 printf ("extern enum attr_%s get_attr_%s PARAMS ((%s));\n\n", 118 XSTR (attr, 0), XSTR (attr, 0), (is_const ? "void" : "rtx")); 119 } 120 121 /* If `length' attribute, write additional function definitions and define 122 variables used by `insn_current_length'. */ 123 if (! strcmp (XSTR (attr, 0), "length")) 124 { 125 printf ("extern void shorten_branches PARAMS ((rtx));\n"); 126 printf ("extern int insn_default_length PARAMS ((rtx));\n"); 127 printf ("extern int insn_variable_length_p PARAMS ((rtx));\n"); 128 printf ("extern int insn_current_length PARAMS ((rtx));\n\n"); 129 printf ("#include \"insn-addr.h\"\n\n"); 130 } 131} 132 133static void 134write_units (num_units, multiplicity, simultaneity, 135 ready_cost, issue_delay, blockage) 136 int num_units; 137 struct range *multiplicity; 138 struct range *simultaneity; 139 struct range *ready_cost; 140 struct range *issue_delay; 141 struct range *blockage; 142{ 143 int i, q_size; 144 145 printf ("#define INSN_SCHEDULING\n\n"); 146 printf ("extern int result_ready_cost PARAMS ((rtx));\n"); 147 printf ("extern int function_units_used PARAMS ((rtx));\n\n"); 148 printf ("extern const struct function_unit_desc\n"); 149 printf ("{\n"); 150 printf (" const char *const name;\n"); 151 printf (" const int bitmask;\n"); 152 printf (" const int multiplicity;\n"); 153 printf (" const int simultaneity;\n"); 154 printf (" const int default_cost;\n"); 155 printf (" const int max_issue_delay;\n"); 156 printf (" int (*const ready_cost_function) PARAMS ((rtx));\n"); 157 printf (" int (*const conflict_cost_function) PARAMS ((rtx, rtx));\n"); 158 printf (" const int max_blockage;\n"); 159 printf (" unsigned int (*const blockage_range_function) PARAMS ((rtx));\n"); 160 printf (" int (*const blockage_function) PARAMS ((rtx, rtx));\n"); 161 printf ("} function_units[];\n\n"); 162 printf ("#define FUNCTION_UNITS_SIZE %d\n", num_units); 163 printf ("#define MIN_MULTIPLICITY %d\n", multiplicity->min); 164 printf ("#define MAX_MULTIPLICITY %d\n", multiplicity->max); 165 printf ("#define MIN_SIMULTANEITY %d\n", simultaneity->min); 166 printf ("#define MAX_SIMULTANEITY %d\n", simultaneity->max); 167 printf ("#define MIN_READY_COST %d\n", ready_cost->min); 168 printf ("#define MAX_READY_COST %d\n", ready_cost->max); 169 printf ("#define MIN_ISSUE_DELAY %d\n", issue_delay->min); 170 printf ("#define MAX_ISSUE_DELAY %d\n", issue_delay->max); 171 printf ("#define MIN_BLOCKAGE %d\n", blockage->min); 172 printf ("#define MAX_BLOCKAGE %d\n", blockage->max); 173 for (i = 0; (1 << i) < blockage->max; i++) 174 ; 175 printf ("#define BLOCKAGE_BITS %d\n", i + 1); 176 177 /* INSN_QUEUE_SIZE is a power of two larger than MAX_BLOCKAGE and 178 MAX_READY_COST. This is the longest time an isnsn may be queued. */ 179 i = MAX (blockage->max, ready_cost->max); 180 for (q_size = 1; q_size <= i; q_size <<= 1) 181 ; 182 printf ("#define INSN_QUEUE_SIZE %d\n", q_size); 183} 184 185extern int main PARAMS ((int, char **)); 186 187int 188main (argc, argv) 189 int argc; 190 char **argv; 191{ 192 rtx desc; 193 int have_delay = 0; 194 int have_annul_true = 0; 195 int have_annul_false = 0; 196 int num_units = 0; 197 struct range all_simultaneity, all_multiplicity; 198 struct range all_ready_cost, all_issue_delay, all_blockage; 199 struct function_unit *units = 0, *unit; 200 int i; 201 202 init_range (&all_multiplicity); 203 init_range (&all_simultaneity); 204 init_range (&all_ready_cost); 205 init_range (&all_issue_delay); 206 init_range (&all_blockage); 207 208 progname = "genattr"; 209 210 if (argc <= 1) 211 fatal ("no input file name"); 212 213 if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE) 214 return (FATAL_EXIT_CODE); 215 216 puts ("/* Generated automatically by the program `genattr'"); 217 puts (" from the machine description file `md'. */\n"); 218 puts ("#ifndef GCC_INSN_ATTR_H"); 219 puts ("#define GCC_INSN_ATTR_H\n"); 220 221 /* For compatibility, define the attribute `alternative', which is just 222 a reference to the variable `which_alternative'. */ 223 224 puts ("#define HAVE_ATTR_alternative"); 225 puts ("#define get_attr_alternative(insn) which_alternative"); 226 227 /* Read the machine description. */ 228 229 while (1) 230 { 231 int line_no, insn_code_number; 232 233 desc = read_md_rtx (&line_no, &insn_code_number); 234 if (desc == NULL) 235 break; 236 237 if (GET_CODE (desc) == DEFINE_ATTR) 238 gen_attr (desc); 239 240 else if (GET_CODE (desc) == DEFINE_DELAY) 241 { 242 if (! have_delay) 243 { 244 printf ("#define DELAY_SLOTS\n"); 245 printf ("extern int num_delay_slots PARAMS ((rtx));\n"); 246 printf ("extern int eligible_for_delay PARAMS ((rtx, int, rtx, int));\n\n"); 247 printf ("extern int const_num_delay_slots PARAMS ((rtx));\n\n"); 248 have_delay = 1; 249 } 250 251 for (i = 0; i < XVECLEN (desc, 1); i += 3) 252 { 253 if (XVECEXP (desc, 1, i + 1) && ! have_annul_true) 254 { 255 printf ("#define ANNUL_IFTRUE_SLOTS\n"); 256 printf ("extern int eligible_for_annul_true PARAMS ((rtx, int, rtx, int));\n"); 257 have_annul_true = 1; 258 } 259 260 if (XVECEXP (desc, 1, i + 2) && ! have_annul_false) 261 { 262 printf ("#define ANNUL_IFFALSE_SLOTS\n"); 263 printf ("extern int eligible_for_annul_false PARAMS ((rtx, int, rtx, int));\n"); 264 have_annul_false = 1; 265 } 266 } 267 } 268 269 else if (GET_CODE (desc) == DEFINE_FUNCTION_UNIT) 270 { 271 const char *name = XSTR (desc, 0); 272 int multiplicity = XINT (desc, 1); 273 int simultaneity = XINT (desc, 2); 274 int ready_cost = MAX (XINT (desc, 4), 1); 275 int issue_delay = MAX (XINT (desc, 5), 1); 276 int issueexp_p = (XVEC (desc, 6) != 0); 277 278 for (unit = units; unit; unit = unit->next) 279 if (strcmp (unit->name, name) == 0) 280 break; 281 282 if (unit == 0) 283 { 284 unit = (struct function_unit *) 285 xmalloc (sizeof (struct function_unit)); 286 unit->name = xstrdup (name); 287 unit->multiplicity = multiplicity; 288 unit->simultaneity = simultaneity; 289 unit->ready_cost.min = unit->ready_cost.max = ready_cost; 290 unit->issue_delay.min = unit->issue_delay.max = issue_delay; 291 unit->next = units; 292 units = unit; 293 num_units++; 294 295 extend_range (&all_multiplicity, multiplicity, multiplicity); 296 extend_range (&all_simultaneity, simultaneity, simultaneity); 297 } 298 else if (unit->multiplicity != multiplicity 299 || unit->simultaneity != simultaneity) 300 fatal ("Differing specifications given for `%s' function unit", 301 unit->name); 302 303 extend_range (&unit->ready_cost, ready_cost, ready_cost); 304 extend_range (&unit->issue_delay, 305 issueexp_p ? 1 : issue_delay, issue_delay); 306 extend_range (&all_ready_cost, 307 unit->ready_cost.min, unit->ready_cost.max); 308 extend_range (&all_issue_delay, 309 unit->issue_delay.min, unit->issue_delay.max); 310 } 311 } 312 313 if (num_units > 0) 314 { 315 /* Compute the range of blockage cost values. See genattrtab.c 316 for the derivation. BLOCKAGE (E,C) when SIMULTANEITY is zero is 317 318 MAX (ISSUE-DELAY (E,C), 319 READY-COST (E) - (READY-COST (C) - 1)) 320 321 and otherwise 322 323 MAX (ISSUE-DELAY (E,C), 324 READY-COST (E) - (READY-COST (C) - 1), 325 READY-COST (E) - FILL-TIME) */ 326 327 for (unit = units; unit; unit = unit->next) 328 { 329 struct range blockage; 330 331 blockage = unit->issue_delay; 332 blockage.max = MAX (unit->ready_cost.max 333 - (unit->ready_cost.min - 1), 334 blockage.max); 335 blockage.min = MAX (1, blockage.min); 336 337 if (unit->simultaneity != 0) 338 { 339 int fill_time = ((unit->simultaneity - 1) 340 * unit->issue_delay.min); 341 blockage.min = MAX (unit->ready_cost.min - fill_time, 342 blockage.min); 343 blockage.max = MAX (unit->ready_cost.max - fill_time, 344 blockage.max); 345 } 346 extend_range (&all_blockage, blockage.min, blockage.max); 347 } 348 349 write_units (num_units, &all_multiplicity, &all_simultaneity, 350 &all_ready_cost, &all_issue_delay, &all_blockage); 351 } 352 353 /* Output flag masks for use by reorg. 354 355 Flags are used to hold branch direction and prediction information 356 for use by eligible_for_... */ 357 printf("\n#define ATTR_FLAG_forward\t0x1\n"); 358 printf("#define ATTR_FLAG_backward\t0x2\n"); 359 printf("#define ATTR_FLAG_likely\t0x4\n"); 360 printf("#define ATTR_FLAG_very_likely\t0x8\n"); 361 printf("#define ATTR_FLAG_unlikely\t0x10\n"); 362 printf("#define ATTR_FLAG_very_unlikely\t0x20\n"); 363 364 puts("\n#endif /* GCC_INSN_ATTR_H */"); 365 366 if (ferror (stdout) || fflush (stdout) || fclose (stdout)) 367 return FATAL_EXIT_CODE; 368 369 return SUCCESS_EXIT_CODE; 370} 371 372/* Define this so we can link with print-rtl.o to get debug_rtx function. */ 373const char * 374get_insn_name (code) 375 int code ATTRIBUTE_UNUSED; 376{ 377 return NULL; 378} 379