1238106Sdes/* Generate attribute information (insn-attr.h) from machine description. 2238106Sdes Copyright (C) 1991, 1994, 1996, 1998, 1999, 2000, 2003, 2004, 2007, 2008 3238106Sdes Free Software Foundation, Inc. 4238106Sdes Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) 5238106Sdes 6238106SdesThis file is part of GCC. 7238106Sdes 8238106SdesGCC is free software; you can redistribute it and/or modify it under 9238106Sdesthe terms of the GNU General Public License as published by the Free 10238106SdesSoftware Foundation; either version 3, or (at your option) any later 11238106Sdesversion. 12238106Sdes 13238106SdesGCC is distributed in the hope that it will be useful, but WITHOUT ANY 14238106SdesWARRANTY; without even the implied warranty of MERCHANTABILITY or 15238106SdesFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16238106Sdesfor more details. 17238106Sdes 18238106SdesYou should have received a copy of the GNU General Public License 19238106Sdesalong with GCC; see the file COPYING3. If not see 20238106Sdes<http://www.gnu.org/licenses/>. */ 21238106Sdes 22238106Sdes 23238106Sdes#include "bconfig.h" 24269257Sdes#include "system.h" 25269257Sdes#include "coretypes.h" 26269257Sdes#include "tm.h" 27269257Sdes#include "rtl.h" 28269257Sdes#include "errors.h" 29269257Sdes#include "gensupport.h" 30269257Sdes 31269257Sdes 32269257Sdesstatic void write_upcase (const char *); 33269257Sdesstatic void gen_attr (rtx); 34238106Sdes 35238106Sdesstatic void 36238106Sdeswrite_upcase (const char *str) 37238106Sdes{ 38238106Sdes for (; *str; str++) 39238106Sdes putchar (TOUPPER(*str)); 40238106Sdes} 41238106Sdes 42238106Sdesstatic void 43238106Sdesgen_attr (rtx attr) 44238106Sdes{ 45238106Sdes const char *p, *tag; 46238106Sdes int is_const = GET_CODE (XEXP (attr, 2)) == CONST; 47238106Sdes 48238106Sdes printf ("#define HAVE_ATTR_%s\n", XSTR (attr, 0)); 49269257Sdes 50238106Sdes /* If numeric attribute, don't need to write an enum. */ 51238106Sdes p = XSTR (attr, 1); 52238106Sdes if (*p == '\0') 53238106Sdes printf ("extern int get_attr_%s (%s);\n", XSTR (attr, 0), 54238106Sdes (is_const ? "void" : "rtx")); 55238106Sdes else 56238106Sdes { 57238106Sdes printf ("enum attr_%s {", XSTR (attr, 0)); 58238106Sdes 59238106Sdes while ((tag = scan_comma_elt (&p)) != 0) 60238106Sdes { 61238106Sdes write_upcase (XSTR (attr, 0)); 62238106Sdes putchar ('_'); 63238106Sdes while (tag != p) 64238106Sdes putchar (TOUPPER (*tag++)); 65238106Sdes if (*p == ',') 66238106Sdes fputs (", ", stdout); 67238106Sdes } 68238106Sdes 69238106Sdes fputs ("};\n", stdout); 70238106Sdes printf ("extern enum attr_%s get_attr_%s (%s);\n\n", 71238106Sdes XSTR (attr, 0), XSTR (attr, 0), (is_const ? "void" : "rtx")); 72238106Sdes } 73238106Sdes 74238106Sdes /* If `length' attribute, write additional function definitions and define 75238106Sdes variables used by `insn_current_length'. */ 76238106Sdes if (! strcmp (XSTR (attr, 0), "length")) 77238106Sdes { 78238106Sdes puts ("\ 79238106Sdesextern void shorten_branches (rtx);\n\ 80238106Sdesextern int insn_default_length (rtx);\n\ 81238106Sdesextern int insn_min_length (rtx);\n\ 82238106Sdesextern int insn_variable_length_p (rtx);\n\ 83238106Sdesextern int insn_current_length (rtx);\n\n\ 84238106Sdes#include \"insn-addr.h\"\n"); 85238106Sdes } 86238106Sdes} 87238106Sdes 88238106Sdesint 89238106Sdesmain (int argc, char **argv) 90238106Sdes{ 91238106Sdes rtx desc; 92238106Sdes int have_delay = 0; 93238106Sdes int have_annul_true = 0; 94238106Sdes int have_annul_false = 0; 95238106Sdes int num_insn_reservations = 0; 96238106Sdes int i; 97238106Sdes 98238106Sdes progname = "genattr"; 99238106Sdes 100238106Sdes if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE) 101238106Sdes return (FATAL_EXIT_CODE); 102238106Sdes 103238106Sdes puts ("/* Generated automatically by the program `genattr'"); 104238106Sdes puts (" from the machine description file `md'. */\n"); 105238106Sdes puts ("#ifndef GCC_INSN_ATTR_H"); 106238106Sdes puts ("#define GCC_INSN_ATTR_H\n"); 107238106Sdes 108238106Sdes /* For compatibility, define the attribute `alternative', which is just 109238106Sdes a reference to the variable `which_alternative'. */ 110238106Sdes 111238106Sdes puts ("#define HAVE_ATTR_alternative"); 112238106Sdes puts ("#define get_attr_alternative(insn) which_alternative"); 113238106Sdes 114238106Sdes /* Read the machine description. */ 115238106Sdes 116238106Sdes while (1) 117238106Sdes { 118238106Sdes int line_no, insn_code_number; 119238106Sdes 120238106Sdes desc = read_md_rtx (&line_no, &insn_code_number); 121238106Sdes if (desc == NULL) 122238106Sdes break; 123238106Sdes 124238106Sdes if (GET_CODE (desc) == DEFINE_ATTR) 125238106Sdes gen_attr (desc); 126238106Sdes 127238106Sdes else if (GET_CODE (desc) == DEFINE_DELAY) 128238106Sdes { 129238106Sdes if (! have_delay) 130238106Sdes { 131238106Sdes printf ("#define DELAY_SLOTS\n"); 132238106Sdes printf ("extern int num_delay_slots (rtx);\n"); 133238106Sdes printf ("extern int eligible_for_delay (rtx, int, rtx, int);\n\n"); 134238106Sdes printf ("extern int const_num_delay_slots (rtx);\n\n"); 135238106Sdes have_delay = 1; 136238106Sdes } 137238106Sdes 138238106Sdes for (i = 0; i < XVECLEN (desc, 1); i += 3) 139238106Sdes { 140238106Sdes if (XVECEXP (desc, 1, i + 1) && ! have_annul_true) 141238106Sdes { 142238106Sdes printf ("#define ANNUL_IFTRUE_SLOTS\n"); 143238106Sdes printf ("extern int eligible_for_annul_true (rtx, int, rtx, int);\n"); 144238106Sdes have_annul_true = 1; 145238106Sdes } 146238106Sdes 147238106Sdes if (XVECEXP (desc, 1, i + 2) && ! have_annul_false) 148238106Sdes { 149238106Sdes printf ("#define ANNUL_IFFALSE_SLOTS\n"); 150238106Sdes printf ("extern int eligible_for_annul_false (rtx, int, rtx, int);\n"); 151238106Sdes have_annul_false = 1; 152238106Sdes } 153238106Sdes } 154238106Sdes } 155238106Sdes 156238106Sdes else if (GET_CODE (desc) == DEFINE_INSN_RESERVATION) 157238106Sdes num_insn_reservations++; 158238106Sdes } 159238106Sdes 160238106Sdes if (num_insn_reservations > 0) 161238106Sdes { 162238106Sdes /* Output interface for pipeline hazards recognition based on 163238106Sdes DFA (deterministic finite state automata. */ 164238106Sdes printf ("\n#define INSN_SCHEDULING\n"); 165238106Sdes printf ("\n/* DFA based pipeline interface. */"); 166238106Sdes printf ("\n#ifndef AUTOMATON_ALTS\n"); 167238106Sdes printf ("#define AUTOMATON_ALTS 0\n"); 168238106Sdes printf ("#endif\n\n"); 169238106Sdes printf ("\n#ifndef AUTOMATON_STATE_ALTS\n"); 170238106Sdes printf ("#define AUTOMATON_STATE_ALTS 0\n"); 171238106Sdes printf ("#endif\n\n"); 172238106Sdes printf ("#ifndef CPU_UNITS_QUERY\n"); 173238106Sdes printf ("#define CPU_UNITS_QUERY 0\n"); 174238106Sdes printf ("#endif\n\n"); 175238106Sdes /* Interface itself: */ 176238106Sdes printf ("/* Internal insn code number used by automata. */\n"); 177238106Sdes printf ("extern int internal_dfa_insn_code (rtx);\n\n"); 178238106Sdes printf ("/* Insn latency time defined in define_insn_reservation. */\n"); 179238106Sdes printf ("extern int insn_default_latency (rtx);\n\n"); 180238106Sdes printf ("/* Return nonzero if there is a bypass for given insn\n"); 181238106Sdes printf (" which is a data producer. */\n"); 182238106Sdes printf ("extern int bypass_p (rtx);\n\n"); 183238106Sdes printf ("/* Insn latency time on data consumed by the 2nd insn.\n"); 184238106Sdes printf (" Use the function if bypass_p returns nonzero for\n"); 185238106Sdes printf (" the 1st insn. */\n"); 186238106Sdes printf ("extern int insn_latency (rtx, rtx);\n\n"); 187238106Sdes printf ("/* Maximal insn latency time possible of all bypasses for this insn.\n"); 188238106Sdes printf (" Use the function if bypass_p returns nonzero for\n"); 189238106Sdes printf (" the 1st insn. */\n"); 190238106Sdes printf ("extern int maximal_insn_latency (rtx);\n\n"); 191238106Sdes printf ("\n#if AUTOMATON_ALTS\n"); 192238106Sdes printf ("/* The following function returns number of alternative\n"); 193238106Sdes printf (" reservations of given insn. It may be used for better\n"); 194238106Sdes printf (" insns scheduling heuristics. */\n"); 195238106Sdes printf ("extern int insn_alts (rtx);\n\n"); 196238106Sdes printf ("#endif\n\n"); 197238106Sdes printf ("/* Maximal possible number of insns waiting results being\n"); 198238106Sdes printf (" produced by insns whose execution is not finished. */\n"); 199238106Sdes printf ("extern const int max_insn_queue_index;\n\n"); 200238106Sdes printf ("/* Pointer to data describing current state of DFA. */\n"); 201238106Sdes printf ("typedef void *state_t;\n\n"); 202238106Sdes printf ("/* Size of the data in bytes. */\n"); 203238106Sdes printf ("extern int state_size (void);\n\n"); 204238106Sdes printf ("/* Initiate given DFA state, i.e. Set up the state\n"); 205238106Sdes printf (" as all functional units were not reserved. */\n"); 206238106Sdes printf ("extern void state_reset (state_t);\n"); 207238106Sdes printf ("/* The following function returns negative value if given\n"); 208238106Sdes printf (" insn can be issued in processor state described by given\n"); 209238106Sdes printf (" DFA state. In this case, the DFA state is changed to\n"); 210238106Sdes printf (" reflect the current and future reservations by given\n"); 211238106Sdes printf (" insn. Otherwise the function returns minimal time\n"); 212238106Sdes printf (" delay to issue the insn. This delay may be zero\n"); 213238106Sdes printf (" for superscalar or VLIW processors. If the second\n"); 214238106Sdes printf (" parameter is NULL the function changes given DFA state\n"); 215238106Sdes printf (" as new processor cycle started. */\n"); 216238106Sdes printf ("extern int state_transition (state_t, rtx);\n"); 217238106Sdes printf ("\n#if AUTOMATON_STATE_ALTS\n"); 218238106Sdes printf ("/* The following function returns number of possible\n"); 219238106Sdes printf (" alternative reservations of given insn in given\n"); 220238106Sdes printf (" DFA state. It may be used for better insns scheduling\n"); 221238106Sdes printf (" heuristics. By default the function is defined if\n"); 222238106Sdes printf (" macro AUTOMATON_STATE_ALTS is defined because its\n"); 223238106Sdes printf (" implementation may require much memory. */\n"); 224238106Sdes printf ("extern int state_alts (state_t, rtx);\n"); 225238106Sdes printf ("#endif\n\n"); 226238106Sdes printf ("extern int min_issue_delay (state_t, rtx);\n"); 227238106Sdes printf ("/* The following function returns nonzero if no one insn\n"); 228238106Sdes printf (" can be issued in current DFA state. */\n"); 229238106Sdes printf ("extern int state_dead_lock_p (state_t);\n"); 230238106Sdes printf ("/* The function returns minimal delay of issue of the 2nd\n"); 231238106Sdes printf (" insn after issuing the 1st insn in given DFA state.\n"); 232238106Sdes printf (" The 1st insn should be issued in given state (i.e.\n"); 233269257Sdes printf (" state_transition should return negative value for\n"); 234238106Sdes printf (" the insn and the state). Data dependencies between\n"); 235238106Sdes printf (" the insns are ignored by the function. */\n"); 236238106Sdes printf 237238106Sdes ("extern int min_insn_conflict_delay (state_t, rtx, rtx);\n"); 238238106Sdes printf ("/* The following function outputs reservations for given\n"); 239238106Sdes printf (" insn as they are described in the corresponding\n"); 240238106Sdes printf (" define_insn_reservation. */\n"); 241238106Sdes printf ("extern void print_reservation (FILE *, rtx);\n"); 242238106Sdes printf ("\n#if CPU_UNITS_QUERY\n"); 243238106Sdes printf ("/* The following function returns code of functional unit\n"); 244238106Sdes printf (" with given name (see define_cpu_unit). */\n"); 245238106Sdes printf ("extern int get_cpu_unit_code (const char *);\n"); 246238106Sdes printf ("/* The following function returns nonzero if functional\n"); 247238106Sdes printf (" unit with given code is currently reserved in given\n"); 248238106Sdes printf (" DFA state. */\n"); 249238106Sdes printf ("extern int cpu_unit_reservation_p (state_t, int);\n"); 250238106Sdes printf ("#endif\n\n"); 251238106Sdes printf ("/* The following function returns true if insn\n"); 252238106Sdes printf (" has a dfa reservation. */\n"); 253238106Sdes printf ("extern bool insn_has_dfa_reservation_p (rtx);\n\n"); 254238106Sdes printf ("/* Clean insn code cache. It should be called if there\n"); 255238106Sdes printf (" is a chance that condition value in a\n"); 256238106Sdes printf (" define_insn_reservation will be changed after\n"); 257238106Sdes printf (" last call of dfa_start. */\n"); 258238106Sdes printf ("extern void dfa_clean_insn_cache (void);\n\n"); 259269257Sdes printf ("extern void dfa_clear_single_insn_cache (rtx);\n\n"); 260238106Sdes printf ("/* Initiate and finish work with DFA. They should be\n"); 261238106Sdes printf (" called as the first and the last interface\n"); 262238106Sdes printf (" functions. */\n"); 263238106Sdes printf ("extern void dfa_start (void);\n"); 264238106Sdes printf ("extern void dfa_finish (void);\n"); 265238106Sdes } 266238106Sdes else 267238106Sdes { 268238106Sdes /* Otherwise we do no scheduling, but we need these typedefs 269238106Sdes in order to avoid uglifying other code with more ifdefs. */ 270238106Sdes printf ("typedef void *state_t;\n\n"); 271238106Sdes } 272238106Sdes 273238106Sdes /* Output flag masks for use by reorg. 274238106Sdes 275238106Sdes Flags are used to hold branch direction and prediction information 276238106Sdes for use by eligible_for_... */ 277238106Sdes printf("\n#define ATTR_FLAG_forward\t0x1\n"); 278238106Sdes printf("#define ATTR_FLAG_backward\t0x2\n"); 279238106Sdes printf("#define ATTR_FLAG_likely\t0x4\n"); 280238106Sdes printf("#define ATTR_FLAG_very_likely\t0x8\n"); 281238106Sdes printf("#define ATTR_FLAG_unlikely\t0x10\n"); 282238106Sdes printf("#define ATTR_FLAG_very_unlikely\t0x20\n"); 283238106Sdes 284238106Sdes puts("\n#endif /* GCC_INSN_ATTR_H */"); 285238106Sdes 286238106Sdes if (ferror (stdout) || fflush (stdout) || fclose (stdout)) 287238106Sdes return FATAL_EXIT_CODE; 288238106Sdes 289238106Sdes return SUCCESS_EXIT_CODE; 290238106Sdes} 291238106Sdes