1 /* Generate from machine description: 2 - some #define configuration flags. 3 Copyright (C) 1987, 1991, 1997, 1998, 1999, 2000, 2003, 2004 4 Free Software Foundation, Inc. 5 6 This file is part of GCC. 7 8 GCC is free software; you can redistribute it and/or modify it under 9 the terms of the GNU General Public License as published by the Free 10 Software Foundation; either version 2, or (at your option) any later 11 version. 12 13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 14 WARRANTY; without even the implied warranty of MERCHANTABILITY or 15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16 for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with GCC; see the file COPYING. If not, write to the Free 20 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 21 02110-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 33 /* flags to determine output of machine description dependent #define's. */ 34 static int max_recog_operands; /* Largest operand number seen. */ 35 static int max_dup_operands; /* Largest number of match_dup in any insn. */ 36 static int max_clobbers_per_insn; 37 static int have_cc0_flag; 38 static int have_cmove_flag; 39 static int have_cond_exec_flag; 40 static int have_lo_sum_flag; 41 static int have_peephole_flag; 42 static int have_peephole2_flag; 43 44 /* Maximum number of insns seen in a split. */ 45 static int max_insns_per_split = 1; 46 47 /* Maximum number of input insns for peephole2. */ 48 static int max_insns_per_peep2; 49 50 static int clobbers_seen_this_insn; 51 static int dup_operands_seen_this_insn; 52 53 static void walk_insn_part (rtx, int, int); 54 static void gen_insn (rtx); 55 static void gen_expand (rtx); 56 static void gen_split (rtx); 57 static void gen_peephole (rtx); 58 static void gen_peephole2 (rtx); 59 60 /* RECOG_P will be nonzero if this pattern was seen in a context where it will 61 be used to recognize, rather than just generate an insn. 62 63 NON_PC_SET_SRC will be nonzero if this pattern was seen in a SET_SRC 64 of a SET whose destination is not (pc). */ 65 66 static void 67 walk_insn_part (rtx part, int recog_p, int non_pc_set_src) 68 { 69 int i, j; 70 RTX_CODE code; 71 const char *format_ptr; 72 73 if (part == 0) 74 return; 75 76 code = GET_CODE (part); 77 switch (code) 78 { 79 case CLOBBER: 80 clobbers_seen_this_insn++; 81 break; 82 83 case MATCH_OPERAND: 84 if (XINT (part, 0) > max_recog_operands) 85 max_recog_operands = XINT (part, 0); 86 return; 87 88 case MATCH_OP_DUP: 89 case MATCH_PAR_DUP: 90 ++dup_operands_seen_this_insn; 91 case MATCH_SCRATCH: 92 case MATCH_PARALLEL: 93 case MATCH_OPERATOR: 94 if (XINT (part, 0) > max_recog_operands) 95 max_recog_operands = XINT (part, 0); 96 /* Now scan the rtl's in the vector inside the MATCH_OPERATOR or 97 MATCH_PARALLEL. */ 98 break; 99 100 case LABEL_REF: 101 if (GET_CODE (XEXP (part, 0)) == MATCH_OPERAND 102 || GET_CODE (XEXP (part, 0)) == MATCH_DUP) 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 171 static void 172 gen_insn (rtx insn) 173 { 174 int i; 175 176 /* Walk the insn pattern to gather the #define's status. */ 177 clobbers_seen_this_insn = 0; 178 dup_operands_seen_this_insn = 0; 179 if (XVEC (insn, 1) != 0) 180 for (i = 0; i < XVECLEN (insn, 1); i++) 181 walk_insn_part (XVECEXP (insn, 1, i), 1, 0); 182 183 if (clobbers_seen_this_insn > max_clobbers_per_insn) 184 max_clobbers_per_insn = clobbers_seen_this_insn; 185 if (dup_operands_seen_this_insn > max_dup_operands) 186 max_dup_operands = dup_operands_seen_this_insn; 187 } 188 189 /* Similar but scan a define_expand. */ 190 191 static void 192 gen_expand (rtx insn) 193 { 194 int i; 195 196 /* Walk the insn pattern to gather the #define's status. */ 197 198 /* Note that we don't bother recording the number of MATCH_DUPs 199 that occur in a gen_expand, because only reload cares about that. */ 200 if (XVEC (insn, 1) != 0) 201 for (i = 0; i < XVECLEN (insn, 1); i++) 202 { 203 /* Compute the maximum SETs and CLOBBERS 204 in any one of the sub-insns; 205 don't sum across all of them. */ 206 clobbers_seen_this_insn = 0; 207 208 walk_insn_part (XVECEXP (insn, 1, i), 0, 0); 209 210 if (clobbers_seen_this_insn > max_clobbers_per_insn) 211 max_clobbers_per_insn = clobbers_seen_this_insn; 212 } 213 } 214 215 /* Similar but scan a define_split. */ 216 217 static void 218 gen_split (rtx split) 219 { 220 int i; 221 222 /* Look through the patterns that are matched 223 to compute the maximum operand number. */ 224 for (i = 0; i < XVECLEN (split, 0); i++) 225 walk_insn_part (XVECEXP (split, 0, i), 1, 0); 226 /* Look at the number of insns this insn could split into. */ 227 if (XVECLEN (split, 2) > max_insns_per_split) 228 max_insns_per_split = XVECLEN (split, 2); 229 } 230 231 static void 232 gen_peephole (rtx peep) 233 { 234 int i; 235 236 /* Look through the patterns that are matched 237 to compute the maximum operand number. */ 238 for (i = 0; i < XVECLEN (peep, 0); i++) 239 walk_insn_part (XVECEXP (peep, 0, i), 1, 0); 240 } 241 242 static void 243 gen_peephole2 (rtx peep) 244 { 245 int i, n; 246 247 /* Look through the patterns that are matched 248 to compute the maximum operand number. */ 249 for (i = XVECLEN (peep, 0) - 1; i >= 0; --i) 250 walk_insn_part (XVECEXP (peep, 0, i), 1, 0); 251 252 /* Look at the number of insns this insn can be matched from. */ 253 for (i = XVECLEN (peep, 0) - 1, n = 0; i >= 0; --i) 254 if (GET_CODE (XVECEXP (peep, 0, i)) != MATCH_DUP 255 && GET_CODE (XVECEXP (peep, 0, i)) != MATCH_SCRATCH) 256 n++; 257 if (n > max_insns_per_peep2) 258 max_insns_per_peep2 = n; 259 } 260 261 int 262 main (int argc, char **argv) 263 { 264 rtx desc; 265 266 progname = "genconfig"; 267 268 if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE) 269 return (FATAL_EXIT_CODE); 270 271 puts ("/* Generated automatically by the program `genconfig'"); 272 puts (" from the machine description file `md'. */\n"); 273 puts ("#ifndef GCC_INSN_CONFIG_H"); 274 puts ("#define GCC_INSN_CONFIG_H\n"); 275 276 /* Allow at least 30 operands for the sake of asm constructs. */ 277 /* ??? We *really* ought to reorganize things such that there 278 is no fixed upper bound. */ 279 max_recog_operands = 29; /* We will add 1 later. */ 280 max_dup_operands = 1; 281 282 /* Read the machine description. */ 283 284 while (1) 285 { 286 int line_no, insn_code_number = 0; 287 288 desc = read_md_rtx (&line_no, &insn_code_number); 289 if (desc == NULL) 290 break; 291 292 switch (GET_CODE (desc)) 293 { 294 case DEFINE_INSN: 295 gen_insn (desc); 296 break; 297 298 case DEFINE_EXPAND: 299 gen_expand (desc); 300 break; 301 302 case DEFINE_SPLIT: 303 gen_split (desc); 304 break; 305 306 case DEFINE_PEEPHOLE2: 307 have_peephole2_flag = 1; 308 gen_peephole2 (desc); 309 break; 310 311 case DEFINE_PEEPHOLE: 312 have_peephole_flag = 1; 313 gen_peephole (desc); 314 break; 315 316 default: 317 break; 318 } 319 } 320 321 printf ("#define MAX_RECOG_OPERANDS %d\n", max_recog_operands + 1); 322 printf ("#define MAX_DUP_OPERANDS %d\n", max_dup_operands); 323 324 /* This is conditionally defined, in case the user writes code which emits 325 more splits than we can readily see (and knows s/he does it). */ 326 printf ("#ifndef MAX_INSNS_PER_SPLIT\n"); 327 printf ("#define MAX_INSNS_PER_SPLIT %d\n", max_insns_per_split); 328 printf ("#endif\n"); 329 330 if (have_cc0_flag) 331 { 332 printf ("#define HAVE_cc0 1\n"); 333 printf ("#define CC0_P(X) ((X) == cc0_rtx)\n"); 334 } 335 else 336 { 337 /* We output CC0_P this way to make sure that X is declared 338 somewhere. */ 339 printf ("#define CC0_P(X) ((X) ? 0 : 0)\n"); 340 } 341 342 if (have_cmove_flag) 343 printf ("#define HAVE_conditional_move 1\n"); 344 345 if (have_cond_exec_flag) 346 printf ("#define HAVE_conditional_execution 1\n"); 347 348 if (have_lo_sum_flag) 349 printf ("#define HAVE_lo_sum 1\n"); 350 351 if (have_peephole_flag) 352 printf ("#define HAVE_peephole 1\n"); 353 354 if (have_peephole2_flag) 355 { 356 printf ("#define HAVE_peephole2 1\n"); 357 printf ("#define MAX_INSNS_PER_PEEP2 %d\n", max_insns_per_peep2); 358 } 359 360 puts("\n#endif /* GCC_INSN_CONFIG_H */"); 361 362 if (ferror (stdout) || fflush (stdout) || fclose (stdout)) 363 return FATAL_EXIT_CODE; 364 365 return SUCCESS_EXIT_CODE; 366 } 367