genattr.c revision 169690
178064Sume/* Generate attribute information (insn-attr.h) from machine description. 278064Sume Copyright (C) 1991, 1994, 1996, 1998, 1999, 2000, 2003, 2004 378064Sume Free Software Foundation, Inc. 478064Sume Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) 578064Sume 678064SumeThis file is part of GCC. 778064Sume 878064SumeGCC is free software; you can redistribute it and/or modify it under 978064Sumethe terms of the GNU General Public License as published by the Free 1078064SumeSoftware Foundation; either version 2, or (at your option) any later 1178064Sumeversion. 1278064Sume 1378064SumeGCC is distributed in the hope that it will be useful, but WITHOUT ANY 1478064SumeWARRANTY; without even the implied warranty of MERCHANTABILITY or 1578064SumeFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1678064Sumefor more details. 1778064Sume 1878064SumeYou should have received a copy of the GNU General Public License 1978064Sumealong with GCC; see the file COPYING. If not, write to the Free 2078064SumeSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 2178064Sume02110-1301, USA. */ 2278064Sume 2378064Sume 2478064Sume#include "bconfig.h" 2578064Sume#include "system.h" 2678064Sume#include "coretypes.h" 2778064Sume#include "tm.h" 2878064Sume#include "rtl.h" 2978064Sume#include "errors.h" 3078064Sume#include "gensupport.h" 3178064Sume 3278064Sume 3378064Sumestatic void write_upcase (const char *); 3478064Sumestatic void gen_attr (rtx); 3578064Sume 3678064Sumestatic void 3778064Sumewrite_upcase (const char *str) 3878064Sume{ 3978064Sume for (; *str; str++) 4078064Sume putchar (TOUPPER(*str)); 4178064Sume} 4278064Sume 4378064Sumestatic void 4478064Sumegen_attr (rtx attr) 4578064Sume{ 4678064Sume const char *p, *tag; 4778064Sume int is_const = GET_CODE (XEXP (attr, 2)) == CONST; 4878064Sume 4978064Sume printf ("#define HAVE_ATTR_%s\n", XSTR (attr, 0)); 5078064Sume 5178064Sume /* If numeric attribute, don't need to write an enum. */ 5278064Sume p = XSTR (attr, 1); 5378064Sume if (*p == '\0') 5478064Sume printf ("extern int get_attr_%s (%s);\n", XSTR (attr, 0), 5578064Sume (is_const ? "void" : "rtx")); 5678064Sume else 5778064Sume { 5878064Sume printf ("enum attr_%s {", XSTR (attr, 0)); 5978064Sume 6078064Sume while ((tag = scan_comma_elt (&p)) != 0) 6178064Sume { 6278064Sume write_upcase (XSTR (attr, 0)); 6378064Sume putchar ('_'); 6478064Sume while (tag != p) 6578064Sume putchar (TOUPPER (*tag++)); 6678064Sume if (*p == ',') 67173412Skevlo fputs (", ", stdout); 6878064Sume } 6978064Sume 7078064Sume fputs ("};\n", stdout); 7178064Sume printf ("extern enum attr_%s get_attr_%s (%s);\n\n", 7278064Sume XSTR (attr, 0), XSTR (attr, 0), (is_const ? "void" : "rtx")); 73173412Skevlo } 7478064Sume 7578064Sume /* If `length' attribute, write additional function definitions and define 7678064Sume variables used by `insn_current_length'. */ 7778064Sume if (! strcmp (XSTR (attr, 0), "length")) 7878064Sume { 79127141Sru puts ("\ 8078064Sumeextern void shorten_branches (rtx);\n\ 8178064Sumeextern int insn_default_length (rtx);\n\ 8278064Sumeextern int insn_min_length (rtx);\n\ 83124524Sumeextern int insn_variable_length_p (rtx);\n\ 8478064Sumeextern int insn_current_length (rtx);\n\n\ 8578064Sume#include \"insn-addr.h\"\n"); 86222732Shrs } 8778064Sume} 8878064Sume 8978064Sumeint 90124524Sumemain (int argc, char **argv) 9178064Sume{ 9278064Sume rtx desc; 9378064Sume int have_delay = 0; 9478064Sume int have_annul_true = 0; 9578064Sume int have_annul_false = 0; 9678064Sume int num_insn_reservations = 0; 97204407Suqs int i; 9878064Sume 99204407Suqs progname = "genattr"; 10078064Sume 10178064Sume if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE) 10278064Sume return (FATAL_EXIT_CODE); 10378064Sume 10478064Sume puts ("/* Generated automatically by the program `genattr'"); 10578064Sume puts (" from the machine description file `md'. */\n"); 106254462Shrs puts ("#ifndef GCC_INSN_ATTR_H"); 10778064Sume puts ("#define GCC_INSN_ATTR_H\n"); 10878064Sume 10978064Sume /* For compatibility, define the attribute `alternative', which is just 11078064Sume a reference to the variable `which_alternative'. */ 11178064Sume 11278064Sume puts ("#define HAVE_ATTR_alternative"); 11378064Sume puts ("#define get_attr_alternative(insn) which_alternative"); 114118660Sume 11578064Sume /* Read the machine description. */ 11678064Sume 11778064Sume while (1) 11878064Sume { 11978064Sume int line_no, insn_code_number; 12078064Sume 12178064Sume desc = read_md_rtx (&line_no, &insn_code_number); 12278064Sume if (desc == NULL) 123118660Sume break; 12478064Sume 12578064Sume if (GET_CODE (desc) == DEFINE_ATTR) 12678064Sume gen_attr (desc); 12778064Sume 12878064Sume else if (GET_CODE (desc) == DEFINE_DELAY) 12978064Sume { 13078064Sume if (! have_delay) 13178064Sume { 13278064Sume printf ("#define DELAY_SLOTS\n"); 133222732Shrs printf ("extern int num_delay_slots (rtx);\n"); 13478064Sume printf ("extern int eligible_for_delay (rtx, int, rtx, int);\n\n"); 13578064Sume printf ("extern int const_num_delay_slots (rtx);\n\n"); 13678064Sume have_delay = 1; 13778064Sume } 138204407Suqs 13978064Sume for (i = 0; i < XVECLEN (desc, 1); i += 3) 14078064Sume { 141254462Shrs if (XVECEXP (desc, 1, i + 1) && ! have_annul_true) 14278064Sume { 14378064Sume printf ("#define ANNUL_IFTRUE_SLOTS\n"); 14478064Sume printf ("extern int eligible_for_annul_true (rtx, int, rtx, int);\n"); 145222732Shrs have_annul_true = 1; 14678064Sume } 14778064Sume 14878064Sume if (XVECEXP (desc, 1, i + 2) && ! have_annul_false) 14978064Sume { 15078064Sume printf ("#define ANNUL_IFFALSE_SLOTS\n"); 15178064Sume printf ("extern int eligible_for_annul_false (rtx, int, rtx, int);\n"); 15278064Sume have_annul_false = 1; 15378064Sume } 15478064Sume } 155118660Sume } 15678064Sume 15778064Sume else if (GET_CODE (desc) == DEFINE_INSN_RESERVATION) 15878064Sume num_insn_reservations++; 159118660Sume } 16078064Sume 161254462Shrs if (num_insn_reservations > 0) 162254462Shrs { 16378064Sume /* Output interface for pipeline hazards recognition based on 164118660Sume DFA (deterministic finite state automata. */ 16578064Sume printf ("\n#define INSN_SCHEDULING\n"); 16678064Sume printf ("\n/* DFA based pipeline interface. */"); 16778064Sume printf ("\n#ifndef AUTOMATON_ALTS\n"); 168254462Shrs printf ("#define AUTOMATON_ALTS 0\n"); 16978064Sume printf ("#endif\n\n"); 17078064Sume printf ("\n#ifndef AUTOMATON_STATE_ALTS\n"); 17178064Sume printf ("#define AUTOMATON_STATE_ALTS 0\n"); 17278064Sume printf ("#endif\n\n"); 173222732Shrs printf ("#ifndef CPU_UNITS_QUERY\n"); 17478064Sume printf ("#define CPU_UNITS_QUERY 0\n"); 17578064Sume 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