genconfig.c revision 90075
1254562Scy/* Generate from machine description: 2254562Scy - some #define configuration flags. 3254562Scy Copyright (C) 1987, 1991, 1997, 1998, 4254562Scy 1999, 2000 Free Software Foundation, Inc. 5254562Scy 6254562ScyThis file is part of GCC. 7254562Scy 8254562ScyGCC is free software; you can redistribute it and/or modify it under 9254562Scythe terms of the GNU General Public License as published by the Free 10254562ScySoftware Foundation; either version 2, or (at your option) any later 11254562Scyversion. 12254562Scy 13254562ScyGCC is distributed in the hope that it will be useful, but WITHOUT ANY 14254562ScyWARRANTY; without even the implied warranty of MERCHANTABILITY or 15254562ScyFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16254562Scyfor more details. 17254562Scy 18254562ScyYou should have received a copy of the GNU General Public License 19254562Scyalong with GCC; see the file COPYING. If not, write to the Free 20254562ScySoftware Foundation, 59 Temple Place - Suite 330, Boston, MA 21254562Scy02111-1307, USA. */ 22254562Scy 23254562Scy 24254562Scy#include "hconfig.h" 25254562Scy#include "system.h" 26254562Scy#include "rtl.h" 27254562Scy#include "errors.h" 28254562Scy#include "gensupport.h" 29254562Scy 30254562Scy 31254562Scy/* flags to determine output of machine description dependent #define's. */ 32254562Scystatic int max_recog_operands; /* Largest operand number seen. */ 33254562Scystatic int max_dup_operands; /* Largest number of match_dup in any insn. */ 34254562Scystatic int max_clobbers_per_insn; 35254562Scystatic int have_cc0_flag; 36254562Scystatic int have_cmove_flag; 37254562Scystatic int have_cond_exec_flag; 38254562Scystatic int have_lo_sum_flag; 39254562Scystatic int have_peephole_flag; 40254562Scystatic int have_peephole2_flag; 41254562Scy 42254562Scy/* Maximum number of insns seen in a split. */ 43254562Scystatic int max_insns_per_split = 1; 44254562Scy 45254562Scy/* Maximum number of input insns for peephole2. */ 46254562Scystatic int max_insns_per_peep2; 47254562Scy 48254562Scystatic int clobbers_seen_this_insn; 49254562Scystatic int dup_operands_seen_this_insn; 50254562Scy 51254562Scystatic void walk_insn_part PARAMS ((rtx, int, int)); 52254562Scystatic void gen_insn PARAMS ((rtx)); 53254562Scystatic void gen_expand PARAMS ((rtx)); 54254562Scystatic void gen_split PARAMS ((rtx)); 55254562Scystatic void gen_peephole PARAMS ((rtx)); 56254562Scystatic void gen_peephole2 PARAMS ((rtx)); 57254562Scy 58254562Scy/* RECOG_P will be non-zero if this pattern was seen in a context where it will 59254562Scy be used to recognize, rather than just generate an insn. 60254562Scy 61254562Scy NON_PC_SET_SRC will be non-zero if this pattern was seen in a SET_SRC 62254562Scy of a SET whose destination is not (pc). */ 63254562Scy 64254562Scystatic void 65254562Scywalk_insn_part (part, recog_p, non_pc_set_src) 66254562Scy rtx part; 67254562Scy int recog_p; 68254562Scy int non_pc_set_src; 69254562Scy{ 70254562Scy int i, j; 71254562Scy RTX_CODE code; 72254562Scy const char *format_ptr; 73254562Scy 74254562Scy if (part == 0) 75254562Scy return; 76254562Scy 77254562Scy code = GET_CODE (part); 78254562Scy switch (code) 79254562Scy { 80254562Scy case CLOBBER: 81254562Scy clobbers_seen_this_insn++; 82254562Scy break; 83254562Scy 84254562Scy case MATCH_OPERAND: 85254562Scy if (XINT (part, 0) > max_recog_operands) 86254562Scy max_recog_operands = XINT (part, 0); 87254562Scy return; 88254562Scy 89254562Scy case MATCH_OP_DUP: 90254562Scy case MATCH_PAR_DUP: 91254562Scy ++dup_operands_seen_this_insn; 92254562Scy case MATCH_SCRATCH: 93254562Scy case MATCH_PARALLEL: 94254562Scy case MATCH_OPERATOR: 95254562Scy if (XINT (part, 0) > max_recog_operands) 96 max_recog_operands = XINT (part, 0); 97 /* Now scan the rtl's in the vector inside the MATCH_OPERATOR or 98 MATCH_PARALLEL. */ 99 break; 100 101 case LABEL_REF: 102 if (GET_CODE (XEXP (part, 0)) == MATCH_OPERAND) 103 break; 104 return; 105 106 case MATCH_DUP: 107 ++dup_operands_seen_this_insn; 108 if (XINT (part, 0) > max_recog_operands) 109 max_recog_operands = XINT (part, 0); 110 return; 111 112 case CC0: 113 if (recog_p) 114 have_cc0_flag = 1; 115 return; 116 117 case LO_SUM: 118 if (recog_p) 119 have_lo_sum_flag = 1; 120 return; 121 122 case SET: 123 walk_insn_part (SET_DEST (part), 0, recog_p); 124 walk_insn_part (SET_SRC (part), recog_p, 125 GET_CODE (SET_DEST (part)) != PC); 126 return; 127 128 case IF_THEN_ELSE: 129 /* Only consider this machine as having a conditional move if the 130 two arms of the IF_THEN_ELSE are both MATCH_OPERAND. Otherwise, 131 we have some specific IF_THEN_ELSE construct (like the doz 132 instruction on the RS/6000) that can't be used in the general 133 context we want it for. */ 134 135 if (recog_p && non_pc_set_src 136 && GET_CODE (XEXP (part, 1)) == MATCH_OPERAND 137 && GET_CODE (XEXP (part, 2)) == MATCH_OPERAND) 138 have_cmove_flag = 1; 139 break; 140 141 case COND_EXEC: 142 if (recog_p) 143 have_cond_exec_flag = 1; 144 break; 145 146 case REG: case CONST_INT: case SYMBOL_REF: 147 case PC: 148 return; 149 150 default: 151 break; 152 } 153 154 format_ptr = GET_RTX_FORMAT (GET_CODE (part)); 155 156 for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++) 157 switch (*format_ptr++) 158 { 159 case 'e': 160 case 'u': 161 walk_insn_part (XEXP (part, i), recog_p, non_pc_set_src); 162 break; 163 case 'E': 164 if (XVEC (part, i) != NULL) 165 for (j = 0; j < XVECLEN (part, i); j++) 166 walk_insn_part (XVECEXP (part, i, j), recog_p, non_pc_set_src); 167 break; 168 } 169} 170 171static void 172gen_insn (insn) 173 rtx insn; 174{ 175 int i; 176 177 /* Walk the insn pattern to gather the #define's status. */ 178 clobbers_seen_this_insn = 0; 179 dup_operands_seen_this_insn = 0; 180 if (XVEC (insn, 1) != 0) 181 for (i = 0; i < XVECLEN (insn, 1); i++) 182 walk_insn_part (XVECEXP (insn, 1, i), 1, 0); 183 184 if (clobbers_seen_this_insn > max_clobbers_per_insn) 185 max_clobbers_per_insn = clobbers_seen_this_insn; 186 if (dup_operands_seen_this_insn > max_dup_operands) 187 max_dup_operands = dup_operands_seen_this_insn; 188} 189 190/* Similar but scan a define_expand. */ 191 192static void 193gen_expand (insn) 194 rtx insn; 195{ 196 int i; 197 198 /* Walk the insn pattern to gather the #define's status. */ 199 200 /* Note that we don't bother recording the number of MATCH_DUPs 201 that occur in a gen_expand, because only reload cares about that. */ 202 if (XVEC (insn, 1) != 0) 203 for (i = 0; i < XVECLEN (insn, 1); i++) 204 { 205 /* Compute the maximum SETs and CLOBBERS 206 in any one of the sub-insns; 207 don't sum across all of them. */ 208 clobbers_seen_this_insn = 0; 209 210 walk_insn_part (XVECEXP (insn, 1, i), 0, 0); 211 212 if (clobbers_seen_this_insn > max_clobbers_per_insn) 213 max_clobbers_per_insn = clobbers_seen_this_insn; 214 } 215} 216 217/* Similar but scan a define_split. */ 218 219static void 220gen_split (split) 221 rtx split; 222{ 223 int i; 224 225 /* Look through the patterns that are matched 226 to compute the maximum operand number. */ 227 for (i = 0; i < XVECLEN (split, 0); i++) 228 walk_insn_part (XVECEXP (split, 0, i), 1, 0); 229 /* Look at the number of insns this insn could split into. */ 230 if (XVECLEN (split, 2) > max_insns_per_split) 231 max_insns_per_split = XVECLEN (split, 2); 232} 233 234static void 235gen_peephole (peep) 236 rtx peep; 237{ 238 int i; 239 240 /* Look through the patterns that are matched 241 to compute the maximum operand number. */ 242 for (i = 0; i < XVECLEN (peep, 0); i++) 243 walk_insn_part (XVECEXP (peep, 0, i), 1, 0); 244} 245 246static void 247gen_peephole2 (peep) 248 rtx peep; 249{ 250 int i, n; 251 252 /* Look through the patterns that are matched 253 to compute the maximum operand number. */ 254 for (i = XVECLEN (peep, 0) - 1; i >= 0; --i) 255 walk_insn_part (XVECEXP (peep, 0, i), 1, 0); 256 257 /* Look at the number of insns this insn can be matched from. */ 258 for (i = XVECLEN (peep, 0) - 1, n = 0; i >= 0; --i) 259 if (GET_CODE (XVECEXP (peep, 0, i)) != MATCH_DUP 260 && GET_CODE (XVECEXP (peep, 0, i)) != MATCH_SCRATCH) 261 n++; 262 if (n > max_insns_per_peep2) 263 max_insns_per_peep2 = n; 264} 265 266extern int main PARAMS ((int, char **)); 267 268int 269main (argc, argv) 270 int argc; 271 char **argv; 272{ 273 rtx desc; 274 275 progname = "genconfig"; 276 277 if (argc <= 1) 278 fatal ("no input file name"); 279 280 if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE) 281 return (FATAL_EXIT_CODE); 282 283 puts ("/* Generated automatically by the program `genconfig'"); 284 puts (" from the machine description file `md'. */\n"); 285 puts ("#ifndef GCC_INSN_CONFIG_H"); 286 puts ("#define GCC_INSN_CONFIG_H\n"); 287 288 /* Allow at least 30 operands for the sake of asm constructs. */ 289 /* ??? We *really* ought to reorganize things such that there 290 is no fixed upper bound. */ 291 max_recog_operands = 29; /* We will add 1 later. */ 292 max_dup_operands = 1; 293 294 /* Read the machine description. */ 295 296 while (1) 297 { 298 int line_no, insn_code_number = 0; 299 300 desc = read_md_rtx (&line_no, &insn_code_number); 301 if (desc == NULL) 302 break; 303 304 switch (GET_CODE (desc)) 305 { 306 case DEFINE_INSN: 307 gen_insn (desc); 308 break; 309 310 case DEFINE_EXPAND: 311 gen_expand (desc); 312 break; 313 314 case DEFINE_SPLIT: 315 gen_split (desc); 316 break; 317 318 case DEFINE_PEEPHOLE2: 319 have_peephole2_flag = 1; 320 gen_peephole2 (desc); 321 break; 322 323 case DEFINE_PEEPHOLE: 324 have_peephole_flag = 1; 325 gen_peephole (desc); 326 break; 327 328 default: 329 break; 330 } 331 } 332 333 printf ("#define MAX_RECOG_OPERANDS %d\n", max_recog_operands + 1); 334 printf ("#define MAX_DUP_OPERANDS %d\n", max_dup_operands); 335 336 /* This is conditionally defined, in case the user writes code which emits 337 more splits than we can readily see (and knows s/he does it). */ 338 printf ("#ifndef MAX_INSNS_PER_SPLIT\n"); 339 printf ("#define MAX_INSNS_PER_SPLIT %d\n", max_insns_per_split); 340 printf ("#endif\n"); 341 342 if (have_cc0_flag) 343 printf ("#define HAVE_cc0 1\n"); 344 345 if (have_cmove_flag) 346 printf ("#define HAVE_conditional_move 1\n"); 347 348 if (have_cond_exec_flag) 349 printf ("#define HAVE_conditional_execution 1\n"); 350 351 if (have_lo_sum_flag) 352 printf ("#define HAVE_lo_sum 1\n"); 353 354 if (have_peephole_flag) 355 printf ("#define HAVE_peephole 1\n"); 356 357 if (have_peephole2_flag) 358 { 359 printf ("#define HAVE_peephole2 1\n"); 360 printf ("#define MAX_INSNS_PER_PEEP2 %d\n", max_insns_per_peep2); 361 } 362 363 puts("\n#endif /* GCC_INSN_CONFIG_H */"); 364 365 if (ferror (stdout) || fflush (stdout) || fclose (stdout)) 366 return FATAL_EXIT_CODE; 367 368 return SUCCESS_EXIT_CODE; 369} 370 371/* Define this so we can link with print-rtl.o to get debug_rtx function. */ 372const char * 373get_insn_name (code) 374 int code ATTRIBUTE_UNUSED; 375{ 376 return NULL; 377} 378