1/* Generate attribute information (insn-attr.h) from machine description. 2 Copyright (C) 1991, 1994, 1996, 1998, 1999, 2000, 2003, 2004 3 Free Software Foundation, Inc. 4 Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) 5 6This file is part of GCC. 7 8GCC is free software; you can redistribute it and/or modify it under 9the terms of the GNU General Public License as published by the Free 10Software Foundation; either version 2, or (at your option) any later 11version. 12 13GCC is distributed in the hope that it will be useful, but WITHOUT ANY 14WARRANTY; without even the implied warranty of MERCHANTABILITY or 15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16for more details. 17 18You should have received a copy of the GNU General Public License 19along with GCC; see the file COPYING. If not, write to the Free 20Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 2102110-1301, USA. */ 22 23 24#include "bconfig.h" 25#include "system.h" 26#include "coretypes.h" 27#include "tm.h" 28#include "rtl.h" 29#include "errors.h" 30#include "gensupport.h" 31 32 33static void write_upcase (const char *); 34static void gen_attr (rtx); 35 36static void 37write_upcase (const char *str) 38{ 39 for (; *str; str++) 40 putchar (TOUPPER(*str)); 41} 42 43static void 44gen_attr (rtx attr) 45{ 46 const char *p, *tag; 47 int is_const = GET_CODE (XEXP (attr, 2)) == CONST; 48 49 printf ("#define HAVE_ATTR_%s\n", XSTR (attr, 0)); 50 51 /* If numeric attribute, don't need to write an enum. */ 52 p = XSTR (attr, 1); 53 if (*p == '\0') 54 printf ("extern int get_attr_%s (%s);\n", XSTR (attr, 0), 55 (is_const ? "void" : "rtx")); 56 else 57 { 58 printf ("enum attr_%s {", XSTR (attr, 0)); 59 60 while ((tag = scan_comma_elt (&p)) != 0) 61 { 62 write_upcase (XSTR (attr, 0)); 63 putchar ('_'); 64 while (tag != p) 65 putchar (TOUPPER (*tag++)); 66 if (*p == ',') 67 fputs (", ", stdout); 68 } 69 70 fputs ("};\n", stdout); 71 printf ("extern enum attr_%s get_attr_%s (%s);\n\n", 72 XSTR (attr, 0), XSTR (attr, 0), (is_const ? "void" : "rtx")); 73 } 74 75 /* If `length' attribute, write additional function definitions and define 76 variables used by `insn_current_length'. */ 77 if (! strcmp (XSTR (attr, 0), "length")) 78 { 79 puts ("\ 80extern void shorten_branches (rtx);\n\ 81extern int insn_default_length (rtx);\n\ 82extern int insn_min_length (rtx);\n\ 83extern int insn_variable_length_p (rtx);\n\ 84extern int insn_current_length (rtx);\n\n\ 85#include \"insn-addr.h\"\n"); 86 } 87} 88 89int 90main (int argc, char **argv) 91{ 92 rtx desc; 93 int have_delay = 0; 94 int have_annul_true = 0; 95 int have_annul_false = 0; 96 int num_insn_reservations = 0; 97 int i; 98 99 progname = "genattr"; 100 101 if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE) 102 return (FATAL_EXIT_CODE); 103 104 puts ("/* Generated automatically by the program `genattr'"); 105 puts (" from the machine description file `md'. */\n"); 106 puts ("#ifndef GCC_INSN_ATTR_H"); 107 puts ("#define GCC_INSN_ATTR_H\n"); 108 109 /* For compatibility, define the attribute `alternative', which is just 110 a reference to the variable `which_alternative'. */ 111 112 puts ("#define HAVE_ATTR_alternative"); 113 puts ("#define get_attr_alternative(insn) which_alternative"); 114 115 /* Read the machine description. */ 116 117 while (1) 118 { 119 int line_no, insn_code_number; 120 121 desc = read_md_rtx (&line_no, &insn_code_number); 122 if (desc == NULL) 123 break; 124 125 if (GET_CODE (desc) == DEFINE_ATTR) 126 gen_attr (desc); 127 128 else if (GET_CODE (desc) == DEFINE_DELAY) 129 { 130 if (! have_delay) 131 { 132 printf ("#define DELAY_SLOTS\n"); 133 printf ("extern int num_delay_slots (rtx);\n"); 134 printf ("extern int eligible_for_delay (rtx, int, rtx, int);\n\n"); 135 printf ("extern int const_num_delay_slots (rtx);\n\n"); 136 have_delay = 1; 137 } 138 139 for (i = 0; i < XVECLEN (desc, 1); i += 3) 140 { 141 if (XVECEXP (desc, 1, i + 1) && ! have_annul_true) 142 { 143 printf ("#define ANNUL_IFTRUE_SLOTS\n"); 144 printf ("extern int eligible_for_annul_true (rtx, int, rtx, int);\n"); 145 have_annul_true = 1; 146 } 147 148 if (XVECEXP (desc, 1, i + 2) && ! have_annul_false) 149 { 150 printf ("#define ANNUL_IFFALSE_SLOTS\n"); 151 printf ("extern int eligible_for_annul_false (rtx, int, rtx, int);\n"); 152 have_annul_false = 1; 153 } 154 } 155 } 156 157 else if (GET_CODE (desc) == DEFINE_INSN_RESERVATION) 158 num_insn_reservations++; 159 } 160 161 if (num_insn_reservations > 0) 162 { 163 /* Output interface for pipeline hazards recognition based on 164 DFA (deterministic finite state automata. */ 165 printf ("\n#define INSN_SCHEDULING\n"); 166 printf ("\n/* DFA based pipeline interface. */"); 167 printf ("\n#ifndef AUTOMATON_ALTS\n"); 168 printf ("#define AUTOMATON_ALTS 0\n"); 169 printf ("#endif\n\n"); 170 printf ("\n#ifndef AUTOMATON_STATE_ALTS\n"); 171 printf ("#define AUTOMATON_STATE_ALTS 0\n"); 172 printf ("#endif\n\n"); 173 printf ("#ifndef CPU_UNITS_QUERY\n"); 174 printf ("#define CPU_UNITS_QUERY 0\n"); 175 printf ("#endif\n\n"); 176 /* Interface itself: */ 177 printf ("/* Internal insn code number used by automata. */\n"); 178 printf ("extern int internal_dfa_insn_code (rtx);\n\n"); 179 printf ("/* Insn latency time defined in define_insn_reservation. */\n"); 180 printf ("extern int insn_default_latency (rtx);\n\n"); 181 printf ("/* Return nonzero if there is a bypass for given insn\n"); 182 printf (" which is a data producer. */\n"); 183 printf ("extern int bypass_p (rtx);\n\n"); 184 printf ("/* Insn latency time on data consumed by the 2nd insn.\n"); 185 printf (" Use the function if bypass_p returns nonzero for\n"); 186 printf (" the 1st insn. */\n"); 187 printf ("extern int insn_latency (rtx, rtx);\n\n"); 188 printf ("\n#if AUTOMATON_ALTS\n"); 189 printf ("/* The following function returns number of alternative\n"); 190 printf (" reservations of given insn. It may be used for better\n"); 191 printf (" insns scheduling heuristics. */\n"); 192 printf ("extern int insn_alts (rtx);\n\n"); 193 printf ("#endif\n\n"); 194 printf ("/* Maximal possible number of insns waiting results being\n"); 195 printf (" produced by insns whose execution is not finished. */\n"); 196 printf ("extern const int max_insn_queue_index;\n\n"); 197 printf ("/* Pointer to data describing current state of DFA. */\n"); 198 printf ("typedef void *state_t;\n\n"); 199 printf ("/* Size of the data in bytes. */\n"); 200 printf ("extern int state_size (void);\n\n"); 201 printf ("/* Initiate given DFA state, i.e. Set up the state\n"); 202 printf (" as all functional units were not reserved. */\n"); 203 printf ("extern void state_reset (state_t);\n"); 204 printf ("/* The following function returns negative value if given\n"); 205 printf (" insn can be issued in processor state described by given\n"); 206 printf (" DFA state. In this case, the DFA state is changed to\n"); 207 printf (" reflect the current and future reservations by given\n"); 208 printf (" insn. Otherwise the function returns minimal time\n"); 209 printf (" delay to issue the insn. This delay may be zero\n"); 210 printf (" for superscalar or VLIW processors. If the second\n"); 211 printf (" parameter is NULL the function changes given DFA state\n"); 212 printf (" as new processor cycle started. */\n"); 213 printf ("extern int state_transition (state_t, rtx);\n"); 214 printf ("\n#if AUTOMATON_STATE_ALTS\n"); 215 printf ("/* The following function returns number of possible\n"); 216 printf (" alternative reservations of given insn in given\n"); 217 printf (" DFA state. It may be used for better insns scheduling\n"); 218 printf (" heuristics. By default the function is defined if\n"); 219 printf (" macro AUTOMATON_STATE_ALTS is defined because its\n"); 220 printf (" implementation may require much memory. */\n"); 221 printf ("extern int state_alts (state_t, rtx);\n"); 222 printf ("#endif\n\n"); 223 printf ("extern int min_issue_delay (state_t, rtx);\n"); 224 printf ("/* The following function returns nonzero if no one insn\n"); 225 printf (" can be issued in current DFA state. */\n"); 226 printf ("extern int state_dead_lock_p (state_t);\n"); 227 printf ("/* The function returns minimal delay of issue of the 2nd\n"); 228 printf (" insn after issuing the 1st insn in given DFA state.\n"); 229 printf (" The 1st insn should be issued in given state (i.e.\n"); 230 printf (" state_transition should return negative value for\n"); 231 printf (" the insn and the state). Data dependencies between\n"); 232 printf (" the insns are ignored by the function. */\n"); 233 printf 234 ("extern int min_insn_conflict_delay (state_t, rtx, rtx);\n"); 235 printf ("/* The following function outputs reservations for given\n"); 236 printf (" insn as they are described in the corresponding\n"); 237 printf (" define_insn_reservation. */\n"); 238 printf ("extern void print_reservation (FILE *, rtx);\n"); 239 printf ("\n#if CPU_UNITS_QUERY\n"); 240 printf ("/* The following function returns code of functional unit\n"); 241 printf (" with given name (see define_cpu_unit). */\n"); 242 printf ("extern int get_cpu_unit_code (const char *);\n"); 243 printf ("/* The following function returns nonzero if functional\n"); 244 printf (" unit with given code is currently reserved in given\n"); 245 printf (" DFA state. */\n"); 246 printf ("extern int cpu_unit_reservation_p (state_t, int);\n"); 247 printf ("#endif\n\n"); 248 printf ("/* Clean insn code cache. It should be called if there\n"); 249 printf (" is a chance that condition value in a\n"); 250 printf (" define_insn_reservation will be changed after\n"); 251 printf (" last call of dfa_start. */\n"); 252 printf ("extern void dfa_clean_insn_cache (void);\n\n"); 253 printf ("extern void dfa_clear_single_insn_cache (rtx);\n\n"); 254 printf ("/* Initiate and finish work with DFA. They should be\n"); 255 printf (" called as the first and the last interface\n"); 256 printf (" functions. */\n"); 257 printf ("extern void dfa_start (void);\n"); 258 printf ("extern void dfa_finish (void);\n"); 259 } 260 else 261 { 262 /* Otherwise we do no scheduling, but we need these typedefs 263 in order to avoid uglifying other code with more ifdefs. */ 264 printf ("typedef void *state_t;\n\n"); 265 } 266 267 /* Output flag masks for use by reorg. 268 269 Flags are used to hold branch direction and prediction information 270 for use by eligible_for_... */ 271 printf("\n#define ATTR_FLAG_forward\t0x1\n"); 272 printf("#define ATTR_FLAG_backward\t0x2\n"); 273 printf("#define ATTR_FLAG_likely\t0x4\n"); 274 printf("#define ATTR_FLAG_very_likely\t0x8\n"); 275 printf("#define ATTR_FLAG_unlikely\t0x10\n"); 276 printf("#define ATTR_FLAG_very_unlikely\t0x20\n"); 277 278 puts("\n#endif /* GCC_INSN_ATTR_H */"); 279 280 if (ferror (stdout) || fflush (stdout) || fclose (stdout)) 281 return FATAL_EXIT_CODE; 282 283 return SUCCESS_EXIT_CODE; 284} 285