118334Speter/* Generate from machine description: 218334Speter - some #define configuration flags. 3169689Skan Copyright (C) 1987, 1991, 1997, 1998, 1999, 2000, 2003, 2004 4132718Skan Free Software Foundation, Inc. 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 3318334Speter/* flags to determine output of machine description dependent #define's. */ 3418334Speterstatic int max_recog_operands; /* Largest operand number seen. */ 3518334Speterstatic int max_dup_operands; /* Largest number of match_dup in any insn. */ 3618334Speterstatic int max_clobbers_per_insn; 3718334Speterstatic int have_cc0_flag; 3818334Speterstatic int have_cmove_flag; 3990075Sobrienstatic int have_cond_exec_flag; 4018334Speterstatic int have_lo_sum_flag; 4190075Sobrienstatic int have_peephole_flag; 4290075Sobrienstatic int have_peephole2_flag; 4318334Speter 4418334Speter/* Maximum number of insns seen in a split. */ 4518334Speterstatic int max_insns_per_split = 1; 4618334Speter 4790075Sobrien/* Maximum number of input insns for peephole2. */ 4890075Sobrienstatic int max_insns_per_peep2; 4990075Sobrien 5018334Speterstatic int clobbers_seen_this_insn; 5118334Speterstatic int dup_operands_seen_this_insn; 5218334Speter 53132718Skanstatic void walk_insn_part (rtx, int, int); 54132718Skanstatic void gen_insn (rtx); 55132718Skanstatic void gen_expand (rtx); 56132718Skanstatic void gen_split (rtx); 57132718Skanstatic void gen_peephole (rtx); 58132718Skanstatic void gen_peephole2 (rtx); 5918334Speter 60117395Skan/* RECOG_P will be nonzero if this pattern was seen in a context where it will 6118334Speter be used to recognize, rather than just generate an insn. 6218334Speter 63117395Skan NON_PC_SET_SRC will be nonzero if this pattern was seen in a SET_SRC 6418334Speter of a SET whose destination is not (pc). */ 6518334Speter 6618334Speterstatic void 67132718Skanwalk_insn_part (rtx part, int recog_p, int non_pc_set_src) 6818334Speter{ 6990075Sobrien int i, j; 7090075Sobrien RTX_CODE code; 7190075Sobrien const char *format_ptr; 7218334Speter 7318334Speter if (part == 0) 7418334Speter return; 7518334Speter 7618334Speter code = GET_CODE (part); 7718334Speter switch (code) 7818334Speter { 7918334Speter case CLOBBER: 8018334Speter clobbers_seen_this_insn++; 8118334Speter break; 8218334Speter 8318334Speter case MATCH_OPERAND: 8418334Speter if (XINT (part, 0) > max_recog_operands) 8518334Speter max_recog_operands = XINT (part, 0); 8618334Speter return; 8718334Speter 8818334Speter case MATCH_OP_DUP: 8918334Speter case MATCH_PAR_DUP: 9018334Speter ++dup_operands_seen_this_insn; 9118334Speter case MATCH_SCRATCH: 9218334Speter case MATCH_PARALLEL: 9318334Speter case MATCH_OPERATOR: 9418334Speter if (XINT (part, 0) > max_recog_operands) 9518334Speter max_recog_operands = XINT (part, 0); 9618334Speter /* Now scan the rtl's in the vector inside the MATCH_OPERATOR or 9718334Speter MATCH_PARALLEL. */ 9818334Speter break; 9918334Speter 10018334Speter case LABEL_REF: 101169689Skan if (GET_CODE (XEXP (part, 0)) == MATCH_OPERAND 102169689Skan || GET_CODE (XEXP (part, 0)) == MATCH_DUP) 10318334Speter break; 10418334Speter return; 10518334Speter 10618334Speter case MATCH_DUP: 10718334Speter ++dup_operands_seen_this_insn; 10818334Speter if (XINT (part, 0) > max_recog_operands) 10918334Speter max_recog_operands = XINT (part, 0); 11018334Speter return; 11118334Speter 11218334Speter case CC0: 11318334Speter if (recog_p) 11418334Speter have_cc0_flag = 1; 11518334Speter return; 11618334Speter 11718334Speter case LO_SUM: 11818334Speter if (recog_p) 11918334Speter have_lo_sum_flag = 1; 12018334Speter return; 12118334Speter 12218334Speter case SET: 12318334Speter walk_insn_part (SET_DEST (part), 0, recog_p); 12418334Speter walk_insn_part (SET_SRC (part), recog_p, 12518334Speter GET_CODE (SET_DEST (part)) != PC); 12618334Speter return; 12718334Speter 12818334Speter case IF_THEN_ELSE: 12918334Speter /* Only consider this machine as having a conditional move if the 13018334Speter two arms of the IF_THEN_ELSE are both MATCH_OPERAND. Otherwise, 13118334Speter we have some specific IF_THEN_ELSE construct (like the doz 13218334Speter instruction on the RS/6000) that can't be used in the general 13318334Speter context we want it for. */ 13418334Speter 13518334Speter if (recog_p && non_pc_set_src 13618334Speter && GET_CODE (XEXP (part, 1)) == MATCH_OPERAND 13718334Speter && GET_CODE (XEXP (part, 2)) == MATCH_OPERAND) 13818334Speter have_cmove_flag = 1; 13918334Speter break; 14018334Speter 14190075Sobrien case COND_EXEC: 14290075Sobrien if (recog_p) 14390075Sobrien have_cond_exec_flag = 1; 14490075Sobrien break; 14590075Sobrien 14618334Speter case REG: case CONST_INT: case SYMBOL_REF: 14718334Speter case PC: 14818334Speter return; 14950397Sobrien 15050397Sobrien default: 15150397Sobrien break; 15218334Speter } 15318334Speter 15418334Speter format_ptr = GET_RTX_FORMAT (GET_CODE (part)); 15518334Speter 15618334Speter for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++) 15718334Speter switch (*format_ptr++) 15818334Speter { 15918334Speter case 'e': 16018334Speter case 'u': 16118334Speter walk_insn_part (XEXP (part, i), recog_p, non_pc_set_src); 16218334Speter break; 16318334Speter case 'E': 16418334Speter if (XVEC (part, i) != NULL) 16518334Speter for (j = 0; j < XVECLEN (part, i); j++) 16618334Speter walk_insn_part (XVECEXP (part, i, j), recog_p, non_pc_set_src); 16718334Speter break; 16818334Speter } 16918334Speter} 17018334Speter 17118334Speterstatic void 172132718Skangen_insn (rtx insn) 17318334Speter{ 17418334Speter int i; 17518334Speter 17618334Speter /* Walk the insn pattern to gather the #define's status. */ 17718334Speter clobbers_seen_this_insn = 0; 17818334Speter dup_operands_seen_this_insn = 0; 17918334Speter if (XVEC (insn, 1) != 0) 18018334Speter for (i = 0; i < XVECLEN (insn, 1); i++) 18118334Speter walk_insn_part (XVECEXP (insn, 1, i), 1, 0); 18218334Speter 18318334Speter if (clobbers_seen_this_insn > max_clobbers_per_insn) 18418334Speter max_clobbers_per_insn = clobbers_seen_this_insn; 18518334Speter if (dup_operands_seen_this_insn > max_dup_operands) 18618334Speter max_dup_operands = dup_operands_seen_this_insn; 18718334Speter} 18818334Speter 18918334Speter/* Similar but scan a define_expand. */ 19018334Speter 19118334Speterstatic void 192132718Skangen_expand (rtx insn) 19318334Speter{ 19418334Speter int i; 19518334Speter 19618334Speter /* Walk the insn pattern to gather the #define's status. */ 19718334Speter 19818334Speter /* Note that we don't bother recording the number of MATCH_DUPs 19918334Speter that occur in a gen_expand, because only reload cares about that. */ 20018334Speter if (XVEC (insn, 1) != 0) 20118334Speter for (i = 0; i < XVECLEN (insn, 1); i++) 20218334Speter { 20318334Speter /* Compute the maximum SETs and CLOBBERS 20418334Speter in any one of the sub-insns; 20518334Speter don't sum across all of them. */ 20618334Speter clobbers_seen_this_insn = 0; 20718334Speter 20818334Speter walk_insn_part (XVECEXP (insn, 1, i), 0, 0); 20918334Speter 21018334Speter if (clobbers_seen_this_insn > max_clobbers_per_insn) 21118334Speter max_clobbers_per_insn = clobbers_seen_this_insn; 21218334Speter } 21318334Speter} 21418334Speter 21518334Speter/* Similar but scan a define_split. */ 21618334Speter 21718334Speterstatic void 218132718Skangen_split (rtx split) 21918334Speter{ 22018334Speter int i; 22118334Speter 22218334Speter /* Look through the patterns that are matched 22318334Speter to compute the maximum operand number. */ 22418334Speter for (i = 0; i < XVECLEN (split, 0); i++) 22518334Speter walk_insn_part (XVECEXP (split, 0, i), 1, 0); 22618334Speter /* Look at the number of insns this insn could split into. */ 22718334Speter if (XVECLEN (split, 2) > max_insns_per_split) 22818334Speter max_insns_per_split = XVECLEN (split, 2); 22918334Speter} 23018334Speter 23118334Speterstatic void 232132718Skangen_peephole (rtx peep) 23318334Speter{ 23418334Speter int i; 23518334Speter 23618334Speter /* Look through the patterns that are matched 23718334Speter to compute the maximum operand number. */ 23818334Speter for (i = 0; i < XVECLEN (peep, 0); i++) 23918334Speter walk_insn_part (XVECEXP (peep, 0, i), 1, 0); 24018334Speter} 24118334Speter 24290075Sobrienstatic void 243132718Skangen_peephole2 (rtx peep) 24418334Speter{ 24590075Sobrien int i, n; 24618334Speter 24790075Sobrien /* Look through the patterns that are matched 24890075Sobrien to compute the maximum operand number. */ 24990075Sobrien for (i = XVECLEN (peep, 0) - 1; i >= 0; --i) 25090075Sobrien walk_insn_part (XVECEXP (peep, 0, i), 1, 0); 25150397Sobrien 25290075Sobrien /* Look at the number of insns this insn can be matched from. */ 25390075Sobrien for (i = XVECLEN (peep, 0) - 1, n = 0; i >= 0; --i) 25490075Sobrien if (GET_CODE (XVECEXP (peep, 0, i)) != MATCH_DUP 25590075Sobrien && GET_CODE (XVECEXP (peep, 0, i)) != MATCH_SCRATCH) 25690075Sobrien n++; 25790075Sobrien if (n > max_insns_per_peep2) 25890075Sobrien max_insns_per_peep2 = n; 25918334Speter} 26018334Speter 26118334Speterint 262132718Skanmain (int argc, char **argv) 26318334Speter{ 26418334Speter rtx desc; 26518334Speter 26690075Sobrien progname = "genconfig"; 26718334Speter 26890075Sobrien if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE) 26990075Sobrien return (FATAL_EXIT_CODE); 27018334Speter 27190075Sobrien puts ("/* Generated automatically by the program `genconfig'"); 27290075Sobrien puts (" from the machine description file `md'. */\n"); 27390075Sobrien puts ("#ifndef GCC_INSN_CONFIG_H"); 27490075Sobrien puts ("#define GCC_INSN_CONFIG_H\n"); 27518334Speter 27690075Sobrien /* Allow at least 30 operands for the sake of asm constructs. */ 27790075Sobrien /* ??? We *really* ought to reorganize things such that there 27890075Sobrien is no fixed upper bound. */ 27990075Sobrien max_recog_operands = 29; /* We will add 1 later. */ 28018334Speter max_dup_operands = 1; 28118334Speter 28218334Speter /* Read the machine description. */ 28318334Speter 28418334Speter while (1) 28518334Speter { 28690075Sobrien int line_no, insn_code_number = 0; 28790075Sobrien 28890075Sobrien desc = read_md_rtx (&line_no, &insn_code_number); 28990075Sobrien if (desc == NULL) 29018334Speter break; 29190075Sobrien 29290075Sobrien switch (GET_CODE (desc)) 29390075Sobrien { 29490075Sobrien case DEFINE_INSN: 29590075Sobrien gen_insn (desc); 29690075Sobrien break; 29790075Sobrien 29890075Sobrien case DEFINE_EXPAND: 29990075Sobrien gen_expand (desc); 30090075Sobrien break; 30118334Speter 30290075Sobrien case DEFINE_SPLIT: 30390075Sobrien gen_split (desc); 30490075Sobrien break; 30590075Sobrien 30690075Sobrien case DEFINE_PEEPHOLE2: 30790075Sobrien have_peephole2_flag = 1; 30890075Sobrien gen_peephole2 (desc); 30990075Sobrien break; 31090075Sobrien 31190075Sobrien case DEFINE_PEEPHOLE: 31290075Sobrien have_peephole_flag = 1; 31390075Sobrien gen_peephole (desc); 31490075Sobrien break; 31590075Sobrien 31690075Sobrien default: 31790075Sobrien break; 31890075Sobrien } 31918334Speter } 32018334Speter 32190075Sobrien printf ("#define MAX_RECOG_OPERANDS %d\n", max_recog_operands + 1); 32290075Sobrien printf ("#define MAX_DUP_OPERANDS %d\n", max_dup_operands); 32318334Speter 32418334Speter /* This is conditionally defined, in case the user writes code which emits 32518334Speter more splits than we can readily see (and knows s/he does it). */ 32690075Sobrien printf ("#ifndef MAX_INSNS_PER_SPLIT\n"); 32790075Sobrien printf ("#define MAX_INSNS_PER_SPLIT %d\n", max_insns_per_split); 32890075Sobrien printf ("#endif\n"); 32918334Speter 33018334Speter if (have_cc0_flag) 331132718Skan { 332132718Skan printf ("#define HAVE_cc0 1\n"); 333132718Skan printf ("#define CC0_P(X) ((X) == cc0_rtx)\n"); 334132718Skan } 335132718Skan else 336132718Skan { 337169689Skan /* We output CC0_P this way to make sure that X is declared 338169689Skan somewhere. */ 339169689Skan printf ("#define CC0_P(X) ((X) ? 0 : 0)\n"); 340132718Skan } 34118334Speter 34218334Speter if (have_cmove_flag) 34390075Sobrien printf ("#define HAVE_conditional_move 1\n"); 34418334Speter 34590075Sobrien if (have_cond_exec_flag) 34690075Sobrien printf ("#define HAVE_conditional_execution 1\n"); 34790075Sobrien 34818334Speter if (have_lo_sum_flag) 34990075Sobrien printf ("#define HAVE_lo_sum 1\n"); 35018334Speter 35190075Sobrien if (have_peephole_flag) 35290075Sobrien printf ("#define HAVE_peephole 1\n"); 35390075Sobrien 35490075Sobrien if (have_peephole2_flag) 35590075Sobrien { 35690075Sobrien printf ("#define HAVE_peephole2 1\n"); 35790075Sobrien printf ("#define MAX_INSNS_PER_PEEP2 %d\n", max_insns_per_peep2); 35890075Sobrien } 35990075Sobrien 36090075Sobrien puts("\n#endif /* GCC_INSN_CONFIG_H */"); 36190075Sobrien 36290075Sobrien if (ferror (stdout) || fflush (stdout) || fclose (stdout)) 36390075Sobrien return FATAL_EXIT_CODE; 36490075Sobrien 36590075Sobrien return SUCCESS_EXIT_CODE; 36618334Speter} 367