118334Speter/* Generate attribute information (insn-attr.h) from machine description. 2169689Skan Copyright (C) 1991, 1994, 1996, 1998, 1999, 2000, 2003, 2004 3132718Skan Free Software Foundation, Inc. 418334Speter Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) 518334Speter 690075SobrienThis file is part of GCC. 718334Speter 890075SobrienGCC is free software; you can redistribute it and/or modify it under 990075Sobrienthe terms of the GNU General Public License as published by the Free 1090075SobrienSoftware Foundation; either version 2, or (at your option) any later 1190075Sobrienversion. 1218334Speter 1390075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY 1490075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or 1590075SobrienFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1690075Sobrienfor more details. 1718334Speter 1818334SpeterYou should have received a copy of the GNU General Public License 1990075Sobrienalong with GCC; see the file COPYING. If not, write to the Free 20169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 21169689Skan02110-1301, USA. */ 2218334Speter 2318334Speter 24132718Skan#include "bconfig.h" 2550397Sobrien#include "system.h" 26132718Skan#include "coretypes.h" 27132718Skan#include "tm.h" 2818334Speter#include "rtl.h" 2990075Sobrien#include "errors.h" 3090075Sobrien#include "gensupport.h" 3118334Speter 3218334Speter 33132718Skanstatic void write_upcase (const char *); 34132718Skanstatic void gen_attr (rtx); 3518334Speter 3618334Speterstatic void 37132718Skanwrite_upcase (const char *str) 3818334Speter{ 3918334Speter for (; *str; str++) 4090075Sobrien putchar (TOUPPER(*str)); 4118334Speter} 4218334Speter 4318334Speterstatic void 44132718Skangen_attr (rtx attr) 4518334Speter{ 46117395Skan const char *p, *tag; 47132718Skan int is_const = GET_CODE (XEXP (attr, 2)) == CONST; 4818334Speter 4918334Speter printf ("#define HAVE_ATTR_%s\n", XSTR (attr, 0)); 5018334Speter 5118334Speter /* If numeric attribute, don't need to write an enum. */ 52117395Skan p = XSTR (attr, 1); 53117395Skan if (*p == '\0') 54132718Skan printf ("extern int get_attr_%s (%s);\n", XSTR (attr, 0), 5590075Sobrien (is_const ? "void" : "rtx")); 5618334Speter else 5718334Speter { 5818334Speter printf ("enum attr_%s {", XSTR (attr, 0)); 5918334Speter 60117395Skan while ((tag = scan_comma_elt (&p)) != 0) 6118334Speter { 62117395Skan write_upcase (XSTR (attr, 0)); 63117395Skan putchar ('_'); 64117395Skan while (tag != p) 65117395Skan putchar (TOUPPER (*tag++)); 6618334Speter if (*p == ',') 67117395Skan fputs (", ", stdout); 6818334Speter } 6918334Speter 70117395Skan fputs ("};\n", stdout); 71132718Skan printf ("extern enum attr_%s get_attr_%s (%s);\n\n", 7290075Sobrien XSTR (attr, 0), XSTR (attr, 0), (is_const ? "void" : "rtx")); 7318334Speter } 7418334Speter 7518334Speter /* If `length' attribute, write additional function definitions and define 7618334Speter variables used by `insn_current_length'. */ 7718334Speter if (! strcmp (XSTR (attr, 0), "length")) 7818334Speter { 79117395Skan puts ("\ 80132718Skanextern void shorten_branches (rtx);\n\ 81132718Skanextern int insn_default_length (rtx);\n\ 82169689Skanextern int insn_min_length (rtx);\n\ 83132718Skanextern int insn_variable_length_p (rtx);\n\ 84132718Skanextern int insn_current_length (rtx);\n\n\ 85117395Skan#include \"insn-addr.h\"\n"); 8618334Speter } 8718334Speter} 8818334Speter 8918334Speterint 90132718Skanmain (int argc, char **argv) 9118334Speter{ 9218334Speter rtx desc; 9318334Speter int have_delay = 0; 9418334Speter int have_annul_true = 0; 9518334Speter int have_annul_false = 0; 96117395Skan int num_insn_reservations = 0; 9718334Speter int i; 9818334Speter 9990075Sobrien progname = "genattr"; 10018334Speter 10190075Sobrien if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE) 10290075Sobrien return (FATAL_EXIT_CODE); 10318334Speter 10490075Sobrien puts ("/* Generated automatically by the program `genattr'"); 10590075Sobrien puts (" from the machine description file `md'. */\n"); 10690075Sobrien puts ("#ifndef GCC_INSN_ATTR_H"); 10790075Sobrien puts ("#define GCC_INSN_ATTR_H\n"); 10818334Speter 10918334Speter /* For compatibility, define the attribute `alternative', which is just 11018334Speter a reference to the variable `which_alternative'. */ 11118334Speter 11290075Sobrien puts ("#define HAVE_ATTR_alternative"); 11390075Sobrien puts ("#define get_attr_alternative(insn) which_alternative"); 114132718Skan 11518334Speter /* Read the machine description. */ 11618334Speter 11718334Speter while (1) 11818334Speter { 11990075Sobrien int line_no, insn_code_number; 12090075Sobrien 12190075Sobrien desc = read_md_rtx (&line_no, &insn_code_number); 12290075Sobrien if (desc == NULL) 12318334Speter break; 12418334Speter 12518334Speter if (GET_CODE (desc) == DEFINE_ATTR) 12618334Speter gen_attr (desc); 12718334Speter 12818334Speter else if (GET_CODE (desc) == DEFINE_DELAY) 12918334Speter { 13018334Speter if (! have_delay) 13118334Speter { 13218334Speter printf ("#define DELAY_SLOTS\n"); 133132718Skan printf ("extern int num_delay_slots (rtx);\n"); 134132718Skan printf ("extern int eligible_for_delay (rtx, int, rtx, int);\n\n"); 135132718Skan printf ("extern int const_num_delay_slots (rtx);\n\n"); 13618334Speter have_delay = 1; 13718334Speter } 13818334Speter 13918334Speter for (i = 0; i < XVECLEN (desc, 1); i += 3) 14018334Speter { 14118334Speter if (XVECEXP (desc, 1, i + 1) && ! have_annul_true) 14218334Speter { 14318334Speter printf ("#define ANNUL_IFTRUE_SLOTS\n"); 144132718Skan printf ("extern int eligible_for_annul_true (rtx, int, rtx, int);\n"); 14518334Speter have_annul_true = 1; 14618334Speter } 14718334Speter 14818334Speter if (XVECEXP (desc, 1, i + 2) && ! have_annul_false) 14918334Speter { 15018334Speter printf ("#define ANNUL_IFFALSE_SLOTS\n"); 151132718Skan printf ("extern int eligible_for_annul_false (rtx, int, rtx, int);\n"); 15218334Speter have_annul_false = 1; 15318334Speter } 15418334Speter } 15518334Speter } 15618334Speter 157117395Skan else if (GET_CODE (desc) == DEFINE_INSN_RESERVATION) 158117395Skan num_insn_reservations++; 15918334Speter } 16018334Speter 161169689Skan if (num_insn_reservations > 0) 16218334Speter { 163117395Skan /* Output interface for pipeline hazards recognition based on 164117395Skan DFA (deterministic finite state automata. */ 165169689Skan printf ("\n#define INSN_SCHEDULING\n"); 166117395Skan printf ("\n/* DFA based pipeline interface. */"); 167132718Skan printf ("\n#ifndef AUTOMATON_ALTS\n"); 168132718Skan printf ("#define AUTOMATON_ALTS 0\n"); 169132718Skan printf ("#endif\n\n"); 170117395Skan printf ("\n#ifndef AUTOMATON_STATE_ALTS\n"); 171117395Skan printf ("#define AUTOMATON_STATE_ALTS 0\n"); 172117395Skan printf ("#endif\n\n"); 173117395Skan printf ("#ifndef CPU_UNITS_QUERY\n"); 174117395Skan printf ("#define CPU_UNITS_QUERY 0\n"); 175117395Skan printf ("#endif\n\n"); 176117395Skan /* Interface itself: */ 177169689Skan printf ("/* Internal insn code number used by automata. */\n"); 178169689Skan printf ("extern int internal_dfa_insn_code (rtx);\n\n"); 179117395Skan printf ("/* Insn latency time defined in define_insn_reservation. */\n"); 180132718Skan printf ("extern int insn_default_latency (rtx);\n\n"); 181117395Skan printf ("/* Return nonzero if there is a bypass for given insn\n"); 182117395Skan printf (" which is a data producer. */\n"); 183132718Skan printf ("extern int bypass_p (rtx);\n\n"); 184117395Skan printf ("/* Insn latency time on data consumed by the 2nd insn.\n"); 185117395Skan printf (" Use the function if bypass_p returns nonzero for\n"); 186117395Skan printf (" the 1st insn. */\n"); 187132718Skan printf ("extern int insn_latency (rtx, rtx);\n\n"); 188132718Skan printf ("\n#if AUTOMATON_ALTS\n"); 189117395Skan printf ("/* The following function returns number of alternative\n"); 190117395Skan printf (" reservations of given insn. It may be used for better\n"); 191117395Skan printf (" insns scheduling heuristics. */\n"); 192132718Skan printf ("extern int insn_alts (rtx);\n\n"); 193132718Skan printf ("#endif\n\n"); 194117395Skan printf ("/* Maximal possible number of insns waiting results being\n"); 195117395Skan printf (" produced by insns whose execution is not finished. */\n"); 196169689Skan printf ("extern const int max_insn_queue_index;\n\n"); 197117395Skan printf ("/* Pointer to data describing current state of DFA. */\n"); 198117395Skan printf ("typedef void *state_t;\n\n"); 199117395Skan printf ("/* Size of the data in bytes. */\n"); 200132718Skan printf ("extern int state_size (void);\n\n"); 201117395Skan printf ("/* Initiate given DFA state, i.e. Set up the state\n"); 202117395Skan printf (" as all functional units were not reserved. */\n"); 203132718Skan printf ("extern void state_reset (state_t);\n"); 204117395Skan printf ("/* The following function returns negative value if given\n"); 205117395Skan printf (" insn can be issued in processor state described by given\n"); 206117395Skan printf (" DFA state. In this case, the DFA state is changed to\n"); 207117395Skan printf (" reflect the current and future reservations by given\n"); 208117395Skan printf (" insn. Otherwise the function returns minimal time\n"); 209117395Skan printf (" delay to issue the insn. This delay may be zero\n"); 210117395Skan printf (" for superscalar or VLIW processors. If the second\n"); 211117395Skan printf (" parameter is NULL the function changes given DFA state\n"); 212117395Skan printf (" as new processor cycle started. */\n"); 213132718Skan printf ("extern int state_transition (state_t, rtx);\n"); 214117395Skan printf ("\n#if AUTOMATON_STATE_ALTS\n"); 215117395Skan printf ("/* The following function returns number of possible\n"); 216117395Skan printf (" alternative reservations of given insn in given\n"); 217117395Skan printf (" DFA state. It may be used for better insns scheduling\n"); 218117395Skan printf (" heuristics. By default the function is defined if\n"); 219117395Skan printf (" macro AUTOMATON_STATE_ALTS is defined because its\n"); 220117395Skan printf (" implementation may require much memory. */\n"); 221132718Skan printf ("extern int state_alts (state_t, rtx);\n"); 222117395Skan printf ("#endif\n\n"); 223132718Skan printf ("extern int min_issue_delay (state_t, rtx);\n"); 224117395Skan printf ("/* The following function returns nonzero if no one insn\n"); 225117395Skan printf (" can be issued in current DFA state. */\n"); 226132718Skan printf ("extern int state_dead_lock_p (state_t);\n"); 227117395Skan printf ("/* The function returns minimal delay of issue of the 2nd\n"); 228117395Skan printf (" insn after issuing the 1st insn in given DFA state.\n"); 229117395Skan printf (" The 1st insn should be issued in given state (i.e.\n"); 230117395Skan printf (" state_transition should return negative value for\n"); 231117395Skan printf (" the insn and the state). Data dependencies between\n"); 232117395Skan printf (" the insns are ignored by the function. */\n"); 233117395Skan printf 234132718Skan ("extern int min_insn_conflict_delay (state_t, rtx, rtx);\n"); 235117395Skan printf ("/* The following function outputs reservations for given\n"); 236117395Skan printf (" insn as they are described in the corresponding\n"); 237117395Skan printf (" define_insn_reservation. */\n"); 238132718Skan printf ("extern void print_reservation (FILE *, rtx);\n"); 239117395Skan printf ("\n#if CPU_UNITS_QUERY\n"); 240117395Skan printf ("/* The following function returns code of functional unit\n"); 241117395Skan printf (" with given name (see define_cpu_unit). */\n"); 242132718Skan printf ("extern int get_cpu_unit_code (const char *);\n"); 243117395Skan printf ("/* The following function returns nonzero if functional\n"); 244117395Skan printf (" unit with given code is currently reserved in given\n"); 245117395Skan printf (" DFA state. */\n"); 246132718Skan printf ("extern int cpu_unit_reservation_p (state_t, int);\n"); 247117395Skan printf ("#endif\n\n"); 248132718Skan printf ("/* Clean insn code cache. It should be called if there\n"); 249132718Skan printf (" is a chance that condition value in a\n"); 250132718Skan printf (" define_insn_reservation will be changed after\n"); 251132718Skan printf (" last call of dfa_start. */\n"); 252132718Skan printf ("extern void dfa_clean_insn_cache (void);\n\n"); 253169689Skan printf ("extern void dfa_clear_single_insn_cache (rtx);\n\n"); 254117395Skan printf ("/* Initiate and finish work with DFA. They should be\n"); 255117395Skan printf (" called as the first and the last interface\n"); 256117395Skan printf (" functions. */\n"); 257132718Skan printf ("extern void dfa_start (void);\n"); 258132718Skan printf ("extern void dfa_finish (void);\n"); 25918334Speter } 260117395Skan else 261117395Skan { 262117395Skan /* Otherwise we do no scheduling, but we need these typedefs 263117395Skan in order to avoid uglifying other code with more ifdefs. */ 264117395Skan printf ("typedef void *state_t;\n\n"); 265117395Skan } 26618334Speter 267132718Skan /* Output flag masks for use by reorg. 26818334Speter 26918334Speter Flags are used to hold branch direction and prediction information 27018334Speter for use by eligible_for_... */ 27118334Speter printf("\n#define ATTR_FLAG_forward\t0x1\n"); 27218334Speter printf("#define ATTR_FLAG_backward\t0x2\n"); 27318334Speter printf("#define ATTR_FLAG_likely\t0x4\n"); 27418334Speter printf("#define ATTR_FLAG_very_likely\t0x8\n"); 27518334Speter printf("#define ATTR_FLAG_unlikely\t0x10\n"); 27618334Speter printf("#define ATTR_FLAG_very_unlikely\t0x20\n"); 27718334Speter 27890075Sobrien puts("\n#endif /* GCC_INSN_ATTR_H */"); 27990075Sobrien 28090075Sobrien if (ferror (stdout) || fflush (stdout) || fclose (stdout)) 28190075Sobrien return FATAL_EXIT_CODE; 28290075Sobrien 28390075Sobrien return SUCCESS_EXIT_CODE; 28418334Speter} 285