175592Sru/* Generate from machine description: 275592Sru - some #define configuration flags. 394427Sru Copyright (C) 1987, 1991, 1997, 1998, 1999, 2000, 2003, 2004 4151504Sru Free Software Foundation, Inc. 5114412Sru 6291738SbdreweryThis file is part of GCC. 7291738Sbdrewery 8291738SbdreweryGCC is free software; you can redistribute it and/or modify it under 975592Sruthe terms of the GNU General Public License as published by the Free 1075592SruSoftware Foundation; either version 2, or (at your option) any later 1175592Sruversion. 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 33/* flags to determine output of machine description dependent #define's. */ 34static int max_recog_operands; /* Largest operand number seen. */ 35static int max_dup_operands; /* Largest number of match_dup in any insn. */ 36static int max_clobbers_per_insn; 37static int have_cc0_flag; 38static int have_cmove_flag; 39static int have_cond_exec_flag; 40static int have_lo_sum_flag; 41static int have_peephole_flag; 42static int have_peephole2_flag; 43 44/* Maximum number of insns seen in a split. */ 45static int max_insns_per_split = 1; 46 47/* Maximum number of input insns for peephole2. */ 48static int max_insns_per_peep2; 49 50static int clobbers_seen_this_insn; 51static int dup_operands_seen_this_insn; 52 53static void walk_insn_part (rtx, int, int); 54static void gen_insn (rtx); 55static void gen_expand (rtx); 56static void gen_split (rtx); 57static void gen_peephole (rtx); 58static 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 66static void 67walk_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 171static void 172gen_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 191static void 192gen_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 217static void 218gen_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 231static void 232gen_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 242static void 243gen_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 261int 262main (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