genattr.c revision 225736
1227961Semaste/* Generate attribute information (insn-attr.h) from machine description. 2227961Semaste Copyright (C) 1991, 1994, 1996, 1998, 1999, 2000, 2003, 2004 3227961Semaste Free Software Foundation, Inc. 4227961Semaste Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) 5227961Semaste 6227961SemasteThis file is part of GCC. 7227961Semaste 8227961SemasteGCC is free software; you can redistribute it and/or modify it under 9227961Semastethe terms of the GNU General Public License as published by the Free 10227961SemasteSoftware Foundation; either version 2, or (at your option) any later 11227961Semasteversion. 12227961Semaste 13227961SemasteGCC is distributed in the hope that it will be useful, but WITHOUT ANY 14227961SemasteWARRANTY; without even the implied warranty of MERCHANTABILITY or 15227961SemasteFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16227961Semastefor more details. 17227961Semaste 18227961SemasteYou should have received a copy of the GNU General Public License 19227961Semastealong with GCC; see the file COPYING. If not, write to the Free 20227961SemasteSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 21227961Semaste02110-1301, USA. */ 22227961Semaste 23227961Semaste 24227961Semaste#include "bconfig.h" 25227961Semaste#include "system.h" 26227961Semaste#include "coretypes.h" 27227961Semaste#include "tm.h" 28227961Semaste#include "rtl.h" 29228203Semaste#include "errors.h" 30228203Semaste#include "gensupport.h" 31228203Semaste 32228203Semaste 33228203Semastestatic void write_upcase (const char *); 34228203Semastestatic void gen_attr (rtx); 35228203Semaste 36228203Semastestatic void 37228203Semastewrite_upcase (const char *str) 38227961Semaste{ 39227961Semaste for (; *str; str++) 40227961Semaste putchar (TOUPPER(*str)); 41227961Semaste} 42227961Semaste 43227961Semastestatic void 44227961Semastegen_attr (rtx attr) 45227961Semaste{ 46227961Semaste const char *p, *tag; 47227961Semaste int is_const = GET_CODE (XEXP (attr, 2)) == CONST; 48227961Semaste 49227961Semaste printf ("#define HAVE_ATTR_%s\n", XSTR (attr, 0)); 50227961Semaste 51227961Semaste /* If numeric attribute, don't need to write an enum. */ 52227961Semaste p = XSTR (attr, 1); 53227961Semaste if (*p == '\0') 54227961Semaste printf ("extern int get_attr_%s (%s);\n", XSTR (attr, 0), 55227961Semaste (is_const ? "void" : "rtx")); 56227961Semaste else 57227961Semaste { 58227961Semaste printf ("enum attr_%s {", XSTR (attr, 0)); 59227961Semaste 60227961Semaste while ((tag = scan_comma_elt (&p)) != 0) 61227961Semaste { 62227961Semaste write_upcase (XSTR (attr, 0)); 63227961Semaste putchar ('_'); 64227961Semaste while (tag != p) 65227961Semaste putchar (TOUPPER (*tag++)); 66227961Semaste if (*p == ',') 67237281Sscottl fputs (", ", stdout); 68237281Sscottl } 69227961Semaste 70227961Semaste fputs ("};\n", stdout); 71227961Semaste printf ("extern enum attr_%s get_attr_%s (%s);\n\n", 72227961Semaste XSTR (attr, 0), XSTR (attr, 0), (is_const ? "void" : "rtx")); 73227961Semaste } 74227961Semaste 75227961Semaste /* If `length' attribute, write additional function definitions and define 76227961Semaste variables used by `insn_current_length'. */ 77227961Semaste if (! strcmp (XSTR (attr, 0), "length")) 78237281Sscottl { 79227961Semaste puts ("\ 80255310Sbryanvextern void shorten_branches (rtx);\n\ 81227961Semasteextern int insn_default_length (rtx);\n\ 82227961Semasteextern int insn_min_length (rtx);\n\ 83227961Semasteextern int insn_variable_length_p (rtx);\n\ 84227961Semasteextern int insn_current_length (rtx);\n\n\ 85227961Semaste#include \"insn-addr.h\"\n"); 86227961Semaste } 87227961Semaste} 88227961Semaste 89227961Semasteint 90227961Semastemain (int argc, char **argv) 91227961Semaste{ 92227961Semaste rtx desc; 93227961Semaste int have_delay = 0; 94227961Semaste int have_annul_true = 0; 95228407Sed int have_annul_false = 0; 96227961Semaste int num_insn_reservations = 0; 97227961Semaste int i; 98227961Semaste 99227961Semaste progname = "genattr"; 100237281Sscottl 101227961Semaste if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE) 102255310Sbryanv return (FATAL_EXIT_CODE); 103227961Semaste 104237281Sscottl puts ("/* Generated automatically by the program `genattr'"); 105237281Sscottl puts (" from the machine description file `md'. */\n"); 106237281Sscottl puts ("#ifndef GCC_INSN_ATTR_H"); 107227961Semaste puts ("#define GCC_INSN_ATTR_H\n"); 108227961Semaste 109227961Semaste /* For compatibility, define the attribute `alternative', which is just 110237281Sscottl a reference to the variable `which_alternative'. */ 111237281Sscottl 112237281Sscottl puts ("#define HAVE_ATTR_alternative"); 113237281Sscottl puts ("#define get_attr_alternative(insn) which_alternative"); 114237281Sscottl 115237281Sscottl /* Read the machine description. */ 116237281Sscottl 117237281Sscottl while (1) 118237281Sscottl { 119237281Sscottl int line_no, insn_code_number; 120237281Sscottl 121237281Sscottl desc = read_md_rtx (&line_no, &insn_code_number); 122237281Sscottl if (desc == NULL) 123237281Sscottl break; 124237281Sscottl 125237281Sscottl if (GET_CODE (desc) == DEFINE_ATTR) 126237281Sscottl gen_attr (desc); 127237281Sscottl 128237281Sscottl else if (GET_CODE (desc) == DEFINE_DELAY) 129237281Sscottl { 130237281Sscottl if (! have_delay) 131228407Sed { 132228407Sed printf ("#define DELAY_SLOTS\n"); 133228407Sed printf ("extern int num_delay_slots (rtx);\n"); 134227961Semaste printf ("extern int eligible_for_delay (rtx, int, rtx, int);\n\n"); 135228407Sed printf ("extern int const_num_delay_slots (rtx);\n\n"); 136241737Sed have_delay = 1; 137237281Sscottl } 138227961Semaste 139227961Semaste for (i = 0; i < XVECLEN (desc, 1); i += 3) 140227961Semaste { 141227961Semaste if (XVECEXP (desc, 1, i + 1) && ! have_annul_true) 142227961Semaste { 143228407Sed printf ("#define ANNUL_IFTRUE_SLOTS\n"); 144227961Semaste printf ("extern int eligible_for_annul_true (rtx, int, rtx, int);\n"); 145227961Semaste have_annul_true = 1; 146227961Semaste } 147228407Sed 148227961Semaste if (XVECEXP (desc, 1, i + 2) && ! have_annul_false) 149227961Semaste { 150227961Semaste printf ("#define ANNUL_IFFALSE_SLOTS\n"); 151227961Semaste printf ("extern int eligible_for_annul_false (rtx, int, rtx, int);\n"); 152227961Semaste have_annul_false = 1; 153227961Semaste } 154227961Semaste } 155227961Semaste } 156227961Semaste 157227961Semaste else if (GET_CODE (desc) == DEFINE_INSN_RESERVATION) 158227961Semaste num_insn_reservations++; 159227961Semaste } 160227961Semaste 161227961Semaste if (num_insn_reservations > 0) 162227961Semaste { 163227961Semaste /* Output interface for pipeline hazards recognition based on 164227961Semaste DFA (deterministic finite state automata. */ 165227961Semaste printf ("\n#define INSN_SCHEDULING\n"); 166227961Semaste printf ("\n/* DFA based pipeline interface. */"); 167228407Sed printf ("\n#ifndef AUTOMATON_ALTS\n"); 168227961Semaste printf ("#define AUTOMATON_ALTS 0\n"); 169227961Semaste printf ("#endif\n\n"); 170227961Semaste printf ("\n#ifndef AUTOMATON_STATE_ALTS\n"); 171227961Semaste printf ("#define AUTOMATON_STATE_ALTS 0\n"); 172227961Semaste printf ("#endif\n\n"); 173227961Semaste printf ("#ifndef CPU_UNITS_QUERY\n"); 174227961Semaste printf ("#define CPU_UNITS_QUERY 0\n"); 175227961Semaste printf ("#endif\n\n"); 176227961Semaste /* Interface itself: */ 177227961Semaste printf ("/* Internal insn code number used by automata. */\n"); 178227961Semaste printf ("extern int internal_dfa_insn_code (rtx);\n\n"); 179227961Semaste printf ("/* Insn latency time defined in define_insn_reservation. */\n"); 180227961Semaste printf ("extern int insn_default_latency (rtx);\n\n"); 181227961Semaste printf ("/* Return nonzero if there is a bypass for given insn\n"); 182227961Semaste printf (" which is a data producer. */\n"); 183227961Semaste printf ("extern int bypass_p (rtx);\n\n"); 184227961Semaste printf ("/* Insn latency time on data consumed by the 2nd insn.\n"); 185227961Semaste printf (" Use the function if bypass_p returns nonzero for\n"); 186227961Semaste printf (" the 1st insn. */\n"); 187227961Semaste printf ("extern int insn_latency (rtx, rtx);\n\n"); 188227961Semaste printf ("\n#if AUTOMATON_ALTS\n"); 189227961Semaste printf ("/* The following function returns number of alternative\n"); 190227961Semaste printf (" reservations of given insn. It may be used for better\n"); 191227961Semaste printf (" insns scheduling heuristics. */\n"); 192227961Semaste printf ("extern int insn_alts (rtx);\n\n"); 193227961Semaste printf ("#endif\n\n"); 194227961Semaste printf ("/* Maximal possible number of insns waiting results being\n"); 195227961Semaste printf (" produced by insns whose execution is not finished. */\n"); 196227961Semaste printf ("extern const int max_insn_queue_index;\n\n"); 197227961Semaste printf ("/* Pointer to data describing current state of DFA. */\n"); 198227961Semaste printf ("typedef void *state_t;\n\n"); 199227961Semaste printf ("/* Size of the data in bytes. */\n"); 200227961Semaste printf ("extern int state_size (void);\n\n"); 201227961Semaste printf ("/* Initiate given DFA state, i.e. Set up the state\n"); 202227961Semaste printf (" as all functional units were not reserved. */\n"); 203227961Semaste printf ("extern void state_reset (state_t);\n"); 204227961Semaste printf ("/* The following function returns negative value if given\n"); 205227961Semaste printf (" insn can be issued in processor state described by given\n"); 206227961Semaste printf (" DFA state. In this case, the DFA state is changed to\n"); 207237281Sscottl printf (" reflect the current and future reservations by given\n"); 208237281Sscottl printf (" insn. Otherwise the function returns minimal time\n"); 209237281Sscottl printf (" delay to issue the insn. This delay may be zero\n"); 210227961Semaste printf (" for superscalar or VLIW processors. If the second\n"); 211227961Semaste printf (" parameter is NULL the function changes given DFA state\n"); 212227961Semaste printf (" as new processor cycle started. */\n"); 213227961Semaste printf ("extern int state_transition (state_t, rtx);\n"); 214227961Semaste printf ("\n#if AUTOMATON_STATE_ALTS\n"); 215227961Semaste printf ("/* The following function returns number of possible\n"); 216227961Semaste printf (" alternative reservations of given insn in given\n"); 217227961Semaste printf (" DFA state. It may be used for better insns scheduling\n"); 218227961Semaste printf (" heuristics. By default the function is defined if\n"); 219227961Semaste printf (" macro AUTOMATON_STATE_ALTS is defined because its\n"); 220227961Semaste printf (" implementation may require much memory. */\n"); 221227961Semaste printf ("extern int state_alts (state_t, rtx);\n"); 222227961Semaste printf ("#endif\n\n"); 223227961Semaste printf ("extern int min_issue_delay (state_t, rtx);\n"); 224227961Semaste printf ("/* The following function returns nonzero if no one insn\n"); 225227961Semaste printf (" can be issued in current DFA state. */\n"); 226227961Semaste printf ("extern int state_dead_lock_p (state_t);\n"); 227256113Semaste printf ("/* The function returns minimal delay of issue of the 2nd\n"); 228227961Semaste printf (" insn after issuing the 1st insn in given DFA state.\n"); 229227961Semaste printf (" The 1st insn should be issued in given state (i.e.\n"); 230227961Semaste printf (" state_transition should return negative value for\n"); 231227961Semaste printf (" the insn and the state). Data dependencies between\n"); 232227961Semaste printf (" the insns are ignored by the function. */\n"); 233227961Semaste printf 234227961Semaste ("extern int min_insn_conflict_delay (state_t, rtx, rtx);\n"); 235227961Semaste printf ("/* The following function outputs reservations for given\n"); 236227961Semaste printf (" insn as they are described in the corresponding\n"); 237227961Semaste printf (" define_insn_reservation. */\n"); 238227961Semaste printf ("extern void print_reservation (FILE *, rtx);\n"); 239227961Semaste printf ("\n#if CPU_UNITS_QUERY\n"); 240227961Semaste printf ("/* The following function returns code of functional unit\n"); 241227961Semaste printf (" with given name (see define_cpu_unit). */\n"); 242227961Semaste printf ("extern int get_cpu_unit_code (const char *);\n"); 243228407Sed printf ("/* The following function returns nonzero if functional\n"); 244241737Sed printf (" unit with given code is currently reserved in given\n"); 245237281Sscottl printf (" DFA state. */\n"); 246227961Semaste printf ("extern int cpu_unit_reservation_p (state_t, int);\n"); 247227961Semaste printf ("#endif\n\n"); 248237281Sscottl printf ("/* Clean insn code cache. It should be called if there\n"); 249237281Sscottl printf (" is a chance that condition value in a\n"); 250227961Semaste printf (" define_insn_reservation will be changed after\n"); 251227961Semaste printf (" last call of dfa_start. */\n"); 252237281Sscottl printf ("extern void dfa_clean_insn_cache (void);\n\n"); 253227961Semaste printf ("extern void dfa_clear_single_insn_cache (rtx);\n\n"); 254227961Semaste printf ("/* Initiate and finish work with DFA. They should be\n"); 255227961Semaste printf (" called as the first and the last interface\n"); 256227961Semaste printf (" functions. */\n"); 257237281Sscottl printf ("extern void dfa_start (void);\n"); 258227961Semaste printf ("extern void dfa_finish (void);\n"); 259227961Semaste } 260227961Semaste else 261227961Semaste { 262227961Semaste /* Otherwise we do no scheduling, but we need these typedefs 263237281Sscottl in order to avoid uglifying other code with more ifdefs. */ 264237281Sscottl printf ("typedef void *state_t;\n\n"); 265237281Sscottl } 266237281Sscottl 267237281Sscottl /* Output flag masks for use by reorg. 268237281Sscottl 269237281Sscottl Flags are used to hold branch direction and prediction information 270237281Sscottl for use by eligible_for_... */ 271237281Sscottl printf("\n#define ATTR_FLAG_forward\t0x1\n"); 272237281Sscottl printf("#define ATTR_FLAG_backward\t0x2\n"); 273237281Sscottl printf("#define ATTR_FLAG_likely\t0x4\n"); 274237281Sscottl printf("#define ATTR_FLAG_very_likely\t0x8\n"); 275237281Sscottl printf("#define ATTR_FLAG_unlikely\t0x10\n"); 276237281Sscottl printf("#define ATTR_FLAG_very_unlikely\t0x20\n"); 277237281Sscottl 278237281Sscottl puts("\n#endif /* GCC_INSN_ATTR_H */"); 279237281Sscottl 280237281Sscottl if (ferror (stdout) || fflush (stdout) || fclose (stdout)) 281237281Sscottl return FATAL_EXIT_CODE; 282237281Sscottl 283237281Sscottl return SUCCESS_EXIT_CODE; 284237281Sscottl} 285237281Sscottl