genattr.c revision 50397
198943Sluigi/* Generate attribute information (insn-attr.h) from machine description. 298943Sluigi Copyright (C) 1991, 1994, 1996, 1998 Free Software Foundation, Inc. 398943Sluigi Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) 498943Sluigi 598943SluigiThis file is part of GNU CC. 698943Sluigi 798943SluigiGNU CC is free software; you can redistribute it and/or modify 898943Sluigiit under the terms of the GNU General Public License as published by 998943Sluigithe Free Software Foundation; either version 2, or (at your option) 1098943Sluigiany later version. 1198943Sluigi 1298943SluigiGNU CC is distributed in the hope that it will be useful, 1398943Sluigibut WITHOUT ANY WARRANTY; without even the implied warranty of 1498943SluigiMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1598943SluigiGNU General Public License for more details. 1698943Sluigi 1798943SluigiYou should have received a copy of the GNU General Public License 1898943Sluigialong with GNU CC; see the file COPYING. If not, write to 1998943Sluigithe Free Software Foundation, 59 Temple Place - Suite 330, 2098943SluigiBoston, MA 02111-1307, USA. */ 2198943Sluigi 2298943Sluigi 2398943Sluigi#include "hconfig.h" 2498943Sluigi#ifdef __STDC__ 2598943Sluigi#include <stdarg.h> 2698943Sluigi#else 2798943Sluigi#include <varargs.h> 2898943Sluigi#endif 2998943Sluigi#include "system.h" 3098943Sluigi#include "rtl.h" 3198943Sluigi#include "obstack.h" 3298943Sluigi 3398943Sluigistatic struct obstack obstack; 3498943Sluigistruct obstack *rtl_obstack = &obstack; 3598943Sluigi 3698943Sluigi#define obstack_chunk_alloc xmalloc 3798943Sluigi#define obstack_chunk_free free 3898943Sluigi 3998943Sluigichar *xmalloc PROTO((unsigned)); 4098943Sluigistatic void fatal PVPROTO ((char *, ...)) ATTRIBUTE_PRINTF_1; 4198943Sluigivoid fancy_abort PROTO((void)); 4298943Sluigi 4399603Sbde/* Define this so we can link with print-rtl.o to get debug_rtx function. */ 4498943Sluigichar **insn_name_ptr = 0; 4598943Sluigi 4698943Sluigi/* A range of values. */ 4798943Sluigi 4898943Sluigistruct range 4998943Sluigi{ 5098943Sluigi int min; 5198943Sluigi int max; 5298943Sluigi}; 5398943Sluigi 5498943Sluigi/* Record information about each function unit mentioned in a 5598943Sluigi DEFINE_FUNCTION_UNIT. */ 5698943Sluigi 5798943Sluigistruct function_unit 5898943Sluigi{ 5998943Sluigi char *name; /* Function unit name. */ 6098943Sluigi struct function_unit *next; /* Next function unit. */ 6198943Sluigi int multiplicity; /* Number of units of this type. */ 6298943Sluigi int simultaneity; /* Maximum number of simultaneous insns 6398943Sluigi on this function unit or 0 if unlimited. */ 6498943Sluigi struct range ready_cost; /* Range of ready cost values. */ 6598943Sluigi struct range issue_delay; /* Range of issue delay values. */ 6698943Sluigi}; 6798943Sluigi 68101628Sluigistatic void extend_range PROTO((struct range *, int, int)); 6998943Sluigistatic void init_range PROTO((struct range *)); 7098943Sluigistatic void write_upcase PROTO((char *)); 7198943Sluigistatic void gen_attr PROTO((rtx)); 7298943Sluigistatic void write_units PROTO((int, struct range *, struct range *, 7398943Sluigi struct range *, struct range *, 7498943Sluigi struct range *)); 7598943Sluigistatic void 7698943Sluigiextend_range (range, min, max) 7798943Sluigi struct range *range; 7898943Sluigi int min; 7998943Sluigi int max; 8098943Sluigi{ 8198943Sluigi if (range->min > min) range->min = min; 8298943Sluigi if (range->max < max) range->max = max; 8398943Sluigi} 8498943Sluigi 8598943Sluigistatic void 8698943Sluigiinit_range (range) 8798943Sluigi struct range *range; 8898943Sluigi{ 8998943Sluigi range->min = 100000; 9098943Sluigi range->max = -1; 9198943Sluigi} 9298943Sluigi 9398943Sluigistatic void 9498943Sluigiwrite_upcase (str) 9598943Sluigi char *str; 9698943Sluigi{ 9798943Sluigi for (; *str; str++) 9898943Sluigi if (*str >= 'a' && *str <= 'z') 9998943Sluigi printf ("%c", *str - 'a' + 'A'); 10098943Sluigi else 10198943Sluigi printf ("%c", *str); 10298943Sluigi} 10398943Sluigi 10498943Sluigistatic void 10598943Sluigigen_attr (attr) 10698943Sluigi rtx attr; 10798943Sluigi{ 10898943Sluigi char *p; 10998943Sluigi 11098943Sluigi printf ("#define HAVE_ATTR_%s\n", XSTR (attr, 0)); 11198943Sluigi 11298943Sluigi /* If numeric attribute, don't need to write an enum. */ 11398943Sluigi if (*XSTR (attr, 1) == '\0') 11498943Sluigi printf ("extern int get_attr_%s ();\n", XSTR (attr, 0)); 11598943Sluigi else 11698943Sluigi { 11798943Sluigi printf ("enum attr_%s {", XSTR (attr, 0)); 11898943Sluigi write_upcase (XSTR (attr, 0)); 11998943Sluigi printf ("_"); 12098943Sluigi 12198943Sluigi for (p = XSTR (attr, 1); *p != '\0'; p++) 12298943Sluigi { 12398943Sluigi if (*p == ',') 12498943Sluigi { 12598943Sluigi printf (", "); 12698943Sluigi write_upcase (XSTR (attr, 0)); 12798943Sluigi printf ("_"); 12898943Sluigi } 12998943Sluigi else if (*p >= 'a' && *p <= 'z') 13098943Sluigi printf ("%c", *p - 'a' + 'A'); 13198943Sluigi else 13298943Sluigi printf ("%c", *p); 13398943Sluigi } 13498943Sluigi 13598943Sluigi printf ("};\n"); 13698943Sluigi printf ("extern enum attr_%s get_attr_%s ();\n\n", 13798943Sluigi XSTR (attr, 0), XSTR (attr, 0)); 13898943Sluigi } 13998943Sluigi 14098943Sluigi /* If `length' attribute, write additional function definitions and define 14198943Sluigi variables used by `insn_current_length'. */ 14298943Sluigi if (! strcmp (XSTR (attr, 0), "length")) 14398943Sluigi { 14498943Sluigi printf ("extern void init_lengths ();\n"); 14598943Sluigi printf ("extern void shorten_branches PROTO((rtx));\n"); 14698943Sluigi printf ("extern int insn_default_length PROTO((rtx));\n"); 14798943Sluigi printf ("extern int insn_variable_length_p PROTO((rtx));\n"); 14898943Sluigi printf ("extern int insn_current_length PROTO((rtx));\n\n"); 14998943Sluigi printf ("extern int *insn_addresses;\n"); 15098943Sluigi printf ("extern int insn_current_address;\n\n"); 15198943Sluigi } 15298943Sluigi} 15398943Sluigi 15498943Sluigistatic void 15598943Sluigiwrite_units (num_units, multiplicity, simultaneity, 15698943Sluigi ready_cost, issue_delay, blockage) 15798943Sluigi int num_units; 15898943Sluigi struct range *multiplicity; 15998943Sluigi struct range *simultaneity; 16098943Sluigi struct range *ready_cost; 16198943Sluigi struct range *issue_delay; 16298943Sluigi struct range *blockage; 16398943Sluigi{ 16498943Sluigi int i, q_size; 16598943Sluigi 16698943Sluigi printf ("#define INSN_SCHEDULING\n\n"); 16798943Sluigi printf ("extern int result_ready_cost PROTO((rtx));\n"); 16898943Sluigi printf ("extern int function_units_used PROTO((rtx));\n\n"); 16998943Sluigi printf ("extern struct function_unit_desc\n"); 17098943Sluigi printf ("{\n"); 17198943Sluigi printf (" char *name;\n"); 17298943Sluigi printf (" int bitmask;\n"); 17398943Sluigi printf (" int multiplicity;\n"); 17498943Sluigi printf (" int simultaneity;\n"); 17598943Sluigi printf (" int default_cost;\n"); 17698943Sluigi printf (" int max_issue_delay;\n"); 17798943Sluigi printf (" int (*ready_cost_function) ();\n"); 17898943Sluigi printf (" int (*conflict_cost_function) ();\n"); 17998943Sluigi printf (" int max_blockage;\n"); 18098943Sluigi printf (" unsigned int (*blockage_range_function) ();\n"); 181101641Sluigi printf (" int (*blockage_function) ();\n"); 182101641Sluigi printf ("} function_units[];\n\n"); 18398943Sluigi printf ("#define FUNCTION_UNITS_SIZE %d\n", num_units); 18498943Sluigi printf ("#define MIN_MULTIPLICITY %d\n", multiplicity->min); 18598943Sluigi printf ("#define MAX_MULTIPLICITY %d\n", multiplicity->max); 18698943Sluigi printf ("#define MIN_SIMULTANEITY %d\n", simultaneity->min); 18798943Sluigi printf ("#define MAX_SIMULTANEITY %d\n", simultaneity->max); 18898943Sluigi printf ("#define MIN_READY_COST %d\n", ready_cost->min); 18998943Sluigi printf ("#define MAX_READY_COST %d\n", ready_cost->max); 19098943Sluigi printf ("#define MIN_ISSUE_DELAY %d\n", issue_delay->min); 19198943Sluigi printf ("#define MAX_ISSUE_DELAY %d\n", issue_delay->max); 19298943Sluigi printf ("#define MIN_BLOCKAGE %d\n", blockage->min); 19398943Sluigi printf ("#define MAX_BLOCKAGE %d\n", blockage->max); 19498943Sluigi for (i = 0; (1 << i) < blockage->max; i++) 19598943Sluigi ; 19698943Sluigi printf ("#define BLOCKAGE_BITS %d\n", i + 1); 19798943Sluigi 19898943Sluigi /* INSN_QUEUE_SIZE is a power of two larger than MAX_BLOCKAGE and 19998943Sluigi MAX_READY_COST. This is the longest time an isnsn may be queued. */ 20098943Sluigi i = MAX (blockage->max, ready_cost->max); 20198943Sluigi for (q_size = 1; q_size <= i; q_size <<= 1) 20298943Sluigi ; 20398943Sluigi printf ("#define INSN_QUEUE_SIZE %d\n", q_size); 20498943Sluigi} 20598943Sluigi 20698943Sluigichar * 20798943Sluigixmalloc (size) 20898943Sluigi unsigned size; 20998943Sluigi{ 21098943Sluigi register char *val = (char *) malloc (size); 21198943Sluigi 21298943Sluigi if (val == 0) 21398943Sluigi fatal ("virtual memory exhausted"); 21498943Sluigi return val; 21598943Sluigi} 21698943Sluigi 21798943Sluigichar * 21898943Sluigixrealloc (ptr, size) 21998943Sluigi char *ptr; 22098943Sluigi unsigned size; 22198943Sluigi{ 22298943Sluigi char * result = (char *) realloc (ptr, size); 22398943Sluigi if (!result) 22498943Sluigi fatal ("virtual memory exhausted"); 22598943Sluigi return result; 226101978Sluigi} 22798943Sluigi 22898943Sluigistatic void 22998943Sluigifatal VPROTO ((char *format, ...)) 23098943Sluigi{ 23198943Sluigi#ifndef __STDC__ 23298943Sluigi char *format; 23398943Sluigi#endif 23498943Sluigi va_list ap; 23598943Sluigi 23698943Sluigi VA_START (ap, format); 23798943Sluigi 23898943Sluigi#ifndef __STDC__ 23998943Sluigi format = va_arg (ap, char *); 24098943Sluigi#endif 24198943Sluigi 24298943Sluigi fprintf (stderr, "genattr: "); 24398943Sluigi vfprintf (stderr, format, ap); 24498943Sluigi va_end (ap); 245101978Sluigi fprintf (stderr, "\n"); 24698943Sluigi exit (FATAL_EXIT_CODE); 24798943Sluigi} 24898943Sluigi 24998943Sluigi/* More 'friendly' abort that prints the line and file. 25098943Sluigi config.h can #define abort fancy_abort if you like that sort of thing. */ 25198943Sluigi 25298943Sluigivoid 25398943Sluigifancy_abort () 25498943Sluigi{ 25598943Sluigi fatal ("Internal gcc abort."); 25698943Sluigi} 25798943Sluigi 25898943Sluigiint 25998943Sluigimain (argc, argv) 26098943Sluigi int argc; 26199475Sluigi char **argv; 26298943Sluigi{ 26398943Sluigi rtx desc; 26498943Sluigi FILE *infile; 26598943Sluigi register int c; 26698943Sluigi int have_delay = 0; 26798943Sluigi int have_annul_true = 0; 26898943Sluigi int have_annul_false = 0; 26998943Sluigi int num_units = 0; 27098943Sluigi struct range all_simultaneity, all_multiplicity; 27198943Sluigi struct range all_ready_cost, all_issue_delay, all_blockage; 27298943Sluigi struct function_unit *units = 0, *unit; 27398943Sluigi int i; 27498943Sluigi 27598943Sluigi init_range (&all_multiplicity); 27698943Sluigi init_range (&all_simultaneity); 27798943Sluigi init_range (&all_ready_cost); 27898943Sluigi init_range (&all_issue_delay); 27998943Sluigi init_range (&all_blockage); 28098943Sluigi 28198943Sluigi obstack_init (rtl_obstack); 28298943Sluigi 28398943Sluigi if (argc <= 1) 28499475Sluigi fatal ("No input file name."); 28598943Sluigi 28698943Sluigi infile = fopen (argv[1], "r"); 28798943Sluigi if (infile == 0) 28898943Sluigi { 28998943Sluigi perror (argv[1]); 29098943Sluigi exit (FATAL_EXIT_CODE); 29198943Sluigi } 29298943Sluigi 29398943Sluigi init_rtl (); 29498943Sluigi 29598943Sluigi printf ("/* Generated automatically by the program `genattr'\n\ 29698943Sluigifrom the machine description file `md'. */\n\n"); 29798943Sluigi 29898943Sluigi /* For compatibility, define the attribute `alternative', which is just 29998943Sluigi a reference to the variable `which_alternative'. */ 30098943Sluigi 30198943Sluigi printf ("#define HAVE_ATTR_alternative\n"); 30298943Sluigi printf ("#define get_attr_alternative(insn) which_alternative\n"); 30398943Sluigi 30498943Sluigi /* Read the machine description. */ 30598943Sluigi 30698943Sluigi while (1) 30798943Sluigi { 30898943Sluigi c = read_skip_spaces (infile); 30998943Sluigi if (c == EOF) 31098943Sluigi break; 31198943Sluigi ungetc (c, infile); 31298943Sluigi 31398943Sluigi desc = read_rtx (infile); 31498943Sluigi if (GET_CODE (desc) == DEFINE_ATTR) 31598943Sluigi gen_attr (desc); 31698943Sluigi 31798943Sluigi else if (GET_CODE (desc) == DEFINE_DELAY) 31898943Sluigi { 31998943Sluigi if (! have_delay) 32098943Sluigi { 32198943Sluigi printf ("#define DELAY_SLOTS\n"); 32298943Sluigi printf ("extern int num_delay_slots PROTO((rtx));\n"); 32399909Sluigi printf ("extern int eligible_for_delay PROTO((rtx, int, rtx, int));\n\n"); 32498943Sluigi printf ("extern int const_num_delay_slots PROTO((rtx));\n\n"); 32598943Sluigi have_delay = 1; 32698943Sluigi } 32798943Sluigi 32898943Sluigi for (i = 0; i < XVECLEN (desc, 1); i += 3) 32998943Sluigi { 330101641Sluigi if (XVECEXP (desc, 1, i + 1) && ! have_annul_true) 331101641Sluigi { 332101641Sluigi printf ("#define ANNUL_IFTRUE_SLOTS\n"); 333101641Sluigi printf ("extern int eligible_for_annul_true ();\n"); 33498943Sluigi have_annul_true = 1; 33598943Sluigi } 33698943Sluigi 33798943Sluigi if (XVECEXP (desc, 1, i + 2) && ! have_annul_false) 33898943Sluigi { 33998943Sluigi printf ("#define ANNUL_IFFALSE_SLOTS\n"); 34098943Sluigi printf ("extern int eligible_for_annul_false ();\n"); 34198943Sluigi have_annul_false = 1; 34298943Sluigi } 34398943Sluigi } 34498943Sluigi } 34598943Sluigi 34698943Sluigi else if (GET_CODE (desc) == DEFINE_FUNCTION_UNIT) 34798943Sluigi { 34898943Sluigi char *name = XSTR (desc, 0); 34998943Sluigi int multiplicity = XINT (desc, 1); 35098943Sluigi int simultaneity = XINT (desc, 2); 35198943Sluigi int ready_cost = MAX (XINT (desc, 4), 1); 35298943Sluigi int issue_delay = MAX (XINT (desc, 5), 1); 35398943Sluigi int issueexp_p = (XVEC (desc, 6) != 0); 35498943Sluigi 35598943Sluigi for (unit = units; unit; unit = unit->next) 35698943Sluigi if (strcmp (unit->name, name) == 0) 35798943Sluigi break; 35898943Sluigi 35998943Sluigi if (unit == 0) 36098943Sluigi { 36198943Sluigi int len = strlen (name) + 1; 36298943Sluigi unit = (struct function_unit *) 36398943Sluigi alloca (sizeof (struct function_unit)); 36498943Sluigi unit->name = (char *) alloca (len); 36598943Sluigi bcopy (name, unit->name, len); 36698943Sluigi unit->multiplicity = multiplicity; 36798943Sluigi unit->simultaneity = simultaneity; 36898943Sluigi unit->ready_cost.min = unit->ready_cost.max = ready_cost; 36998943Sluigi unit->issue_delay.min = unit->issue_delay.max = issue_delay; 37098943Sluigi unit->next = units; 37198943Sluigi units = unit; 37298943Sluigi num_units++; 37398943Sluigi 37498943Sluigi extend_range (&all_multiplicity, multiplicity, multiplicity); 37598943Sluigi extend_range (&all_simultaneity, simultaneity, simultaneity); 37698943Sluigi } 37798943Sluigi else if (unit->multiplicity != multiplicity 37898943Sluigi || unit->simultaneity != simultaneity) 37998943Sluigi fatal ("Differing specifications given for `%s' function unit.", 38098943Sluigi unit->name); 38198943Sluigi 38298943Sluigi extend_range (&unit->ready_cost, ready_cost, ready_cost); 38398943Sluigi extend_range (&unit->issue_delay, 38498943Sluigi issueexp_p ? 1 : issue_delay, issue_delay); 38598943Sluigi extend_range (&all_ready_cost, 38698943Sluigi unit->ready_cost.min, unit->ready_cost.max); 38798943Sluigi extend_range (&all_issue_delay, 38898943Sluigi unit->issue_delay.min, unit->issue_delay.max); 38998943Sluigi } 39098943Sluigi } 39198943Sluigi 39298943Sluigi if (num_units > 0) 39398943Sluigi { 39498943Sluigi /* Compute the range of blockage cost values. See genattrtab.c 39598943Sluigi for the derivation. BLOCKAGE (E,C) when SIMULTANEITY is zero is 39698943Sluigi 39798943Sluigi MAX (ISSUE-DELAY (E,C), 39898943Sluigi READY-COST (E) - (READY-COST (C) - 1)) 39998943Sluigi 40098943Sluigi and otherwise 40198943Sluigi 40298943Sluigi MAX (ISSUE-DELAY (E,C), 40398943Sluigi READY-COST (E) - (READY-COST (C) - 1), 40498943Sluigi READY-COST (E) - FILL-TIME) */ 40598943Sluigi 40698943Sluigi for (unit = units; unit; unit = unit->next) 40798943Sluigi { 40898943Sluigi struct range blockage; 40998943Sluigi 41098943Sluigi blockage = unit->issue_delay; 41198943Sluigi blockage.max = MAX (unit->ready_cost.max 41298943Sluigi - (unit->ready_cost.min - 1), 41398943Sluigi blockage.max); 41498943Sluigi blockage.min = MAX (1, blockage.min); 41598943Sluigi 41698943Sluigi if (unit->simultaneity != 0) 41798943Sluigi { 41898943Sluigi int fill_time = ((unit->simultaneity - 1) 41998943Sluigi * unit->issue_delay.min); 42098943Sluigi blockage.min = MAX (unit->ready_cost.min - fill_time, 42198943Sluigi blockage.min); 422101628Sluigi blockage.max = MAX (unit->ready_cost.max - fill_time, 42398943Sluigi blockage.max); 42498943Sluigi } 42598943Sluigi extend_range (&all_blockage, blockage.min, blockage.max); 42698943Sluigi } 427101628Sluigi 428101628Sluigi write_units (num_units, &all_multiplicity, &all_simultaneity, 42998943Sluigi &all_ready_cost, &all_issue_delay, &all_blockage); 43098943Sluigi } 431101628Sluigi 43298943Sluigi /* Output flag masks for use by reorg. 433101628Sluigi 434101628Sluigi Flags are used to hold branch direction and prediction information 43598943Sluigi for use by eligible_for_... */ 43698943Sluigi printf("\n#define ATTR_FLAG_forward\t0x1\n"); 43798943Sluigi printf("#define ATTR_FLAG_backward\t0x2\n"); 43898943Sluigi printf("#define ATTR_FLAG_likely\t0x4\n"); 439101628Sluigi printf("#define ATTR_FLAG_very_likely\t0x8\n"); 44098943Sluigi printf("#define ATTR_FLAG_unlikely\t0x10\n"); 441101628Sluigi printf("#define ATTR_FLAG_very_unlikely\t0x20\n"); 442101628Sluigi 443101628Sluigi fflush (stdout); 44498943Sluigi exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); 445101628Sluigi /* NOTREACHED */ 446101628Sluigi return 0; 447101628Sluigi} 448101628Sluigi