1/* Generate from machine description: 2 - some #define configuration flags. 3 Copyright (C) 1987-2015 Free Software Foundation, Inc. 4 5This file is part of GCC. 6 7GCC is free software; you can redistribute it and/or modify it under 8the terms of the GNU General Public License as published by the Free 9Software Foundation; either version 3, or (at your option) any later 10version. 11 12GCC is distributed in the hope that it will be useful, but WITHOUT ANY 13WARRANTY; without even the implied warranty of MERCHANTABILITY or 14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15for more details. 16 17You should have received a copy of the GNU General Public License 18along with GCC; see the file COPYING3. If not see 19<http://www.gnu.org/licenses/>. */ 20 21 22#include "bconfig.h" 23#include "system.h" 24#include "coretypes.h" 25#include "tm.h" 26#include "rtl.h" 27#include "errors.h" 28#include "gensupport.h" 29 30 31/* flags to determine output of machine description dependent #define's. */ 32static int max_recog_operands; /* Largest operand number seen. */ 33static int max_dup_operands; /* Largest number of match_dup in any insn. */ 34static int max_clobbers_per_insn; 35static int have_cc0_flag; 36static int have_cmove_flag; 37static int have_cond_exec_flag; 38static int have_lo_sum_flag; 39static int have_rotate_flag; 40static int have_rotatert_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 (LABEL_REF_LABEL (part)) == MATCH_OPERAND 102 || GET_CODE (LABEL_REF_LABEL (part)) == 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 ROTATE: 123 if (recog_p) 124 have_rotate_flag = 1; 125 return; 126 127 case ROTATERT: 128 if (recog_p) 129 have_rotatert_flag = 1; 130 return; 131 132 case SET: 133 walk_insn_part (SET_DEST (part), 0, recog_p); 134 walk_insn_part (SET_SRC (part), recog_p, 135 GET_CODE (SET_DEST (part)) != PC); 136 return; 137 138 case IF_THEN_ELSE: 139 /* Only consider this machine as having a conditional move if the 140 two arms of the IF_THEN_ELSE are both MATCH_OPERAND. Otherwise, 141 we have some specific IF_THEN_ELSE construct (like the doz 142 instruction on the RS/6000) that can't be used in the general 143 context we want it for. */ 144 145 if (recog_p && non_pc_set_src 146 && GET_CODE (XEXP (part, 1)) == MATCH_OPERAND 147 && GET_CODE (XEXP (part, 2)) == MATCH_OPERAND) 148 have_cmove_flag = 1; 149 break; 150 151 case COND_EXEC: 152 if (recog_p) 153 have_cond_exec_flag = 1; 154 break; 155 156 case REG: case CONST_INT: case SYMBOL_REF: 157 case PC: 158 return; 159 160 default: 161 break; 162 } 163 164 format_ptr = GET_RTX_FORMAT (GET_CODE (part)); 165 166 for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++) 167 switch (*format_ptr++) 168 { 169 case 'e': 170 case 'u': 171 walk_insn_part (XEXP (part, i), recog_p, non_pc_set_src); 172 break; 173 case 'E': 174 if (XVEC (part, i) != NULL) 175 for (j = 0; j < XVECLEN (part, i); j++) 176 walk_insn_part (XVECEXP (part, i, j), recog_p, non_pc_set_src); 177 break; 178 } 179} 180 181static void 182gen_insn (rtx insn) 183{ 184 int i; 185 186 /* Walk the insn pattern to gather the #define's status. */ 187 clobbers_seen_this_insn = 0; 188 dup_operands_seen_this_insn = 0; 189 if (XVEC (insn, 1) != 0) 190 for (i = 0; i < XVECLEN (insn, 1); i++) 191 walk_insn_part (XVECEXP (insn, 1, i), 1, 0); 192 193 if (clobbers_seen_this_insn > max_clobbers_per_insn) 194 max_clobbers_per_insn = clobbers_seen_this_insn; 195 if (dup_operands_seen_this_insn > max_dup_operands) 196 max_dup_operands = dup_operands_seen_this_insn; 197} 198 199/* Similar but scan a define_expand. */ 200 201static void 202gen_expand (rtx insn) 203{ 204 int i; 205 206 /* Walk the insn pattern to gather the #define's status. */ 207 208 /* Note that we don't bother recording the number of MATCH_DUPs 209 that occur in a gen_expand, because only reload cares about that. */ 210 if (XVEC (insn, 1) != 0) 211 for (i = 0; i < XVECLEN (insn, 1); i++) 212 { 213 /* Compute the maximum SETs and CLOBBERS 214 in any one of the sub-insns; 215 don't sum across all of them. */ 216 clobbers_seen_this_insn = 0; 217 218 walk_insn_part (XVECEXP (insn, 1, i), 0, 0); 219 220 if (clobbers_seen_this_insn > max_clobbers_per_insn) 221 max_clobbers_per_insn = clobbers_seen_this_insn; 222 } 223} 224 225/* Similar but scan a define_split. */ 226 227static void 228gen_split (rtx split) 229{ 230 int i; 231 232 /* Look through the patterns that are matched 233 to compute the maximum operand number. */ 234 for (i = 0; i < XVECLEN (split, 0); i++) 235 walk_insn_part (XVECEXP (split, 0, i), 1, 0); 236 /* Look at the number of insns this insn could split into. */ 237 if (XVECLEN (split, 2) > max_insns_per_split) 238 max_insns_per_split = XVECLEN (split, 2); 239} 240 241static void 242gen_peephole (rtx peep) 243{ 244 int i; 245 246 /* Look through the patterns that are matched 247 to compute the maximum operand number. */ 248 for (i = 0; i < XVECLEN (peep, 0); i++) 249 walk_insn_part (XVECEXP (peep, 0, i), 1, 0); 250} 251 252static void 253gen_peephole2 (rtx peep) 254{ 255 int i, n; 256 257 /* Look through the patterns that are matched 258 to compute the maximum operand number. */ 259 for (i = XVECLEN (peep, 0) - 1; i >= 0; --i) 260 walk_insn_part (XVECEXP (peep, 0, i), 1, 0); 261 262 /* Look at the number of insns this insn can be matched from. */ 263 for (i = XVECLEN (peep, 0) - 1, n = 0; i >= 0; --i) 264 if (GET_CODE (XVECEXP (peep, 0, i)) != MATCH_DUP 265 && GET_CODE (XVECEXP (peep, 0, i)) != MATCH_SCRATCH) 266 n++; 267 if (n > max_insns_per_peep2) 268 max_insns_per_peep2 = n; 269} 270 271int 272main (int argc, char **argv) 273{ 274 rtx desc; 275 276 progname = "genconfig"; 277 278 if (!init_rtx_reader_args (argc, argv)) 279 return (FATAL_EXIT_CODE); 280 281 puts ("/* Generated automatically by the program `genconfig'"); 282 puts (" from the machine description file `md'. */\n"); 283 puts ("#ifndef GCC_INSN_CONFIG_H"); 284 puts ("#define GCC_INSN_CONFIG_H\n"); 285 286 /* Allow at least 30 operands for the sake of asm constructs. */ 287 /* ??? We *really* ought to reorganize things such that there 288 is no fixed upper bound. */ 289 max_recog_operands = 29; /* We will add 1 later. */ 290 max_dup_operands = 1; 291 292 /* Read the machine description. */ 293 294 while (1) 295 { 296 int line_no, insn_code_number = 0; 297 298 desc = read_md_rtx (&line_no, &insn_code_number); 299 if (desc == NULL) 300 break; 301 302 switch (GET_CODE (desc)) 303 { 304 case DEFINE_INSN: 305 gen_insn (desc); 306 break; 307 308 case DEFINE_EXPAND: 309 gen_expand (desc); 310 break; 311 312 case DEFINE_SPLIT: 313 gen_split (desc); 314 break; 315 316 case DEFINE_PEEPHOLE2: 317 have_peephole2_flag = 1; 318 gen_peephole2 (desc); 319 break; 320 321 case DEFINE_PEEPHOLE: 322 have_peephole_flag = 1; 323 gen_peephole (desc); 324 break; 325 326 default: 327 break; 328 } 329 } 330 331 printf ("#define MAX_RECOG_OPERANDS %d\n", max_recog_operands + 1); 332 printf ("#define MAX_DUP_OPERANDS %d\n", max_dup_operands); 333 334 /* This is conditionally defined, in case the user writes code which emits 335 more splits than we can readily see (and knows s/he does it). */ 336 printf ("#ifndef MAX_INSNS_PER_SPLIT\n"); 337 printf ("#define MAX_INSNS_PER_SPLIT %d\n", max_insns_per_split); 338 printf ("#endif\n"); 339 340 if (have_cc0_flag) 341 { 342 printf ("#define HAVE_cc0 1\n"); 343 printf ("#define CC0_P(X) ((X) == cc0_rtx)\n"); 344 } 345 else 346 { 347 /* We output CC0_P this way to make sure that X is declared 348 somewhere. */ 349 printf ("#define CC0_P(X) ((X) ? 0 : 0)\n"); 350 } 351 352 if (have_cmove_flag) 353 printf ("#define HAVE_conditional_move 1\n"); 354 355 if (have_cond_exec_flag) 356 printf ("#define HAVE_conditional_execution 1\n"); 357 358 if (have_lo_sum_flag) 359 printf ("#define HAVE_lo_sum 1\n"); 360 361 if (have_rotate_flag) 362 printf ("#define HAVE_rotate 1\n"); 363 364 if (have_rotatert_flag) 365 printf ("#define HAVE_rotatert 1\n"); 366 367 if (have_peephole_flag) 368 printf ("#define HAVE_peephole 1\n"); 369 370 if (have_peephole2_flag) 371 { 372 printf ("#define HAVE_peephole2 1\n"); 373 printf ("#define MAX_INSNS_PER_PEEP2 %d\n", max_insns_per_peep2); 374 } 375 376 puts ("\n#endif /* GCC_INSN_CONFIG_H */"); 377 378 if (ferror (stdout) || fflush (stdout) || fclose (stdout)) 379 return FATAL_EXIT_CODE; 380 381 return SUCCESS_EXIT_CODE; 382} 383