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