11debfc3dSmrg /* Generate from machine description:
21debfc3dSmrg - some #define configuration flags.
3*8feb0f0bSmrg Copyright (C) 1987-2020 Free Software Foundation, Inc.
41debfc3dSmrg
51debfc3dSmrg This file is part of GCC.
61debfc3dSmrg
71debfc3dSmrg GCC is free software; you can redistribute it and/or modify it under
81debfc3dSmrg the terms of the GNU General Public License as published by the Free
91debfc3dSmrg Software Foundation; either version 3, or (at your option) any later
101debfc3dSmrg version.
111debfc3dSmrg
121debfc3dSmrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
131debfc3dSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
141debfc3dSmrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
151debfc3dSmrg for more details.
161debfc3dSmrg
171debfc3dSmrg You should have received a copy of the GNU General Public License
181debfc3dSmrg along with GCC; see the file COPYING3. If not see
191debfc3dSmrg <http://www.gnu.org/licenses/>. */
201debfc3dSmrg
211debfc3dSmrg
221debfc3dSmrg #include "bconfig.h"
231debfc3dSmrg #include "system.h"
241debfc3dSmrg #include "coretypes.h"
251debfc3dSmrg #include "tm.h"
261debfc3dSmrg #include "rtl.h"
271debfc3dSmrg #include "errors.h"
281debfc3dSmrg #include "gensupport.h"
291debfc3dSmrg
301debfc3dSmrg
311debfc3dSmrg /* flags to determine output of machine description dependent #define's. */
321debfc3dSmrg static int max_recog_operands; /* Largest operand number seen. */
331debfc3dSmrg static int max_dup_operands; /* Largest number of match_dup in any insn. */
341debfc3dSmrg static int max_clobbers_per_insn;
351debfc3dSmrg static int have_cc0_flag;
361debfc3dSmrg static int have_cmove_flag;
371debfc3dSmrg static int have_cond_exec_flag;
381debfc3dSmrg static int have_lo_sum_flag;
391debfc3dSmrg static int have_rotate_flag;
401debfc3dSmrg static int have_rotatert_flag;
411debfc3dSmrg static int have_peephole_flag;
421debfc3dSmrg static int have_peephole2_flag;
431debfc3dSmrg
441debfc3dSmrg /* Maximum number of insns seen in a split. */
451debfc3dSmrg static int max_insns_per_split = 1;
461debfc3dSmrg
471debfc3dSmrg /* Maximum number of input insns for peephole2. */
481debfc3dSmrg static int max_insns_per_peep2;
491debfc3dSmrg
501debfc3dSmrg static int clobbers_seen_this_insn;
511debfc3dSmrg static int dup_operands_seen_this_insn;
521debfc3dSmrg
531debfc3dSmrg static void walk_insn_part (rtx, int, int);
541debfc3dSmrg
551debfc3dSmrg /* RECOG_P will be nonzero if this pattern was seen in a context where it will
561debfc3dSmrg be used to recognize, rather than just generate an insn.
571debfc3dSmrg
581debfc3dSmrg NON_PC_SET_SRC will be nonzero if this pattern was seen in a SET_SRC
591debfc3dSmrg of a SET whose destination is not (pc). */
601debfc3dSmrg
611debfc3dSmrg static void
walk_insn_part(rtx part,int recog_p,int non_pc_set_src)621debfc3dSmrg walk_insn_part (rtx part, int recog_p, int non_pc_set_src)
631debfc3dSmrg {
641debfc3dSmrg int i, j;
651debfc3dSmrg RTX_CODE code;
661debfc3dSmrg const char *format_ptr;
671debfc3dSmrg
681debfc3dSmrg if (part == 0)
691debfc3dSmrg return;
701debfc3dSmrg
711debfc3dSmrg code = GET_CODE (part);
721debfc3dSmrg switch (code)
731debfc3dSmrg {
741debfc3dSmrg case CLOBBER:
751debfc3dSmrg clobbers_seen_this_insn++;
761debfc3dSmrg break;
771debfc3dSmrg
781debfc3dSmrg case MATCH_OPERAND:
791debfc3dSmrg if (XINT (part, 0) > max_recog_operands)
801debfc3dSmrg max_recog_operands = XINT (part, 0);
811debfc3dSmrg return;
821debfc3dSmrg
831debfc3dSmrg case MATCH_OP_DUP:
841debfc3dSmrg case MATCH_PAR_DUP:
851debfc3dSmrg ++dup_operands_seen_this_insn;
861debfc3dSmrg /* FALLTHRU */
871debfc3dSmrg case MATCH_SCRATCH:
881debfc3dSmrg case MATCH_PARALLEL:
891debfc3dSmrg case MATCH_OPERATOR:
901debfc3dSmrg if (XINT (part, 0) > max_recog_operands)
911debfc3dSmrg max_recog_operands = XINT (part, 0);
921debfc3dSmrg /* Now scan the rtl's in the vector inside the MATCH_OPERATOR or
931debfc3dSmrg MATCH_PARALLEL. */
941debfc3dSmrg break;
951debfc3dSmrg
961debfc3dSmrg case LABEL_REF:
971debfc3dSmrg if (GET_CODE (XEXP (part, 0)) == MATCH_OPERAND
981debfc3dSmrg || GET_CODE (XEXP (part, 0)) == MATCH_DUP)
991debfc3dSmrg break;
1001debfc3dSmrg return;
1011debfc3dSmrg
1021debfc3dSmrg case MATCH_DUP:
1031debfc3dSmrg ++dup_operands_seen_this_insn;
1041debfc3dSmrg if (XINT (part, 0) > max_recog_operands)
1051debfc3dSmrg max_recog_operands = XINT (part, 0);
1061debfc3dSmrg return;
1071debfc3dSmrg
1081debfc3dSmrg case CC0:
1091debfc3dSmrg if (recog_p)
1101debfc3dSmrg have_cc0_flag = 1;
1111debfc3dSmrg return;
1121debfc3dSmrg
1131debfc3dSmrg case LO_SUM:
1141debfc3dSmrg if (recog_p)
1151debfc3dSmrg have_lo_sum_flag = 1;
1161debfc3dSmrg return;
1171debfc3dSmrg
1181debfc3dSmrg case ROTATE:
1191debfc3dSmrg if (recog_p)
1201debfc3dSmrg have_rotate_flag = 1;
1211debfc3dSmrg return;
1221debfc3dSmrg
1231debfc3dSmrg case ROTATERT:
1241debfc3dSmrg if (recog_p)
1251debfc3dSmrg have_rotatert_flag = 1;
1261debfc3dSmrg return;
1271debfc3dSmrg
1281debfc3dSmrg case SET:
1291debfc3dSmrg walk_insn_part (SET_DEST (part), 0, recog_p);
1301debfc3dSmrg walk_insn_part (SET_SRC (part), recog_p,
1311debfc3dSmrg GET_CODE (SET_DEST (part)) != PC);
1321debfc3dSmrg return;
1331debfc3dSmrg
1341debfc3dSmrg case IF_THEN_ELSE:
1351debfc3dSmrg /* Only consider this machine as having a conditional move if the
1361debfc3dSmrg two arms of the IF_THEN_ELSE are both MATCH_OPERAND. Otherwise,
1371debfc3dSmrg we have some specific IF_THEN_ELSE construct (like the doz
1381debfc3dSmrg instruction on the RS/6000) that can't be used in the general
1391debfc3dSmrg context we want it for. */
1401debfc3dSmrg
1411debfc3dSmrg if (recog_p && non_pc_set_src
1421debfc3dSmrg && GET_CODE (XEXP (part, 1)) == MATCH_OPERAND
1431debfc3dSmrg && GET_CODE (XEXP (part, 2)) == MATCH_OPERAND)
1441debfc3dSmrg have_cmove_flag = 1;
1451debfc3dSmrg break;
1461debfc3dSmrg
1471debfc3dSmrg case COND_EXEC:
1481debfc3dSmrg if (recog_p)
1491debfc3dSmrg have_cond_exec_flag = 1;
1501debfc3dSmrg break;
1511debfc3dSmrg
1521debfc3dSmrg case REG: case CONST_INT: case SYMBOL_REF:
1531debfc3dSmrg case PC:
1541debfc3dSmrg return;
1551debfc3dSmrg
1561debfc3dSmrg default:
1571debfc3dSmrg break;
1581debfc3dSmrg }
1591debfc3dSmrg
1601debfc3dSmrg format_ptr = GET_RTX_FORMAT (GET_CODE (part));
1611debfc3dSmrg
1621debfc3dSmrg for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
1631debfc3dSmrg switch (*format_ptr++)
1641debfc3dSmrg {
1651debfc3dSmrg case 'e':
1661debfc3dSmrg case 'u':
1671debfc3dSmrg walk_insn_part (XEXP (part, i), recog_p, non_pc_set_src);
1681debfc3dSmrg break;
1691debfc3dSmrg case 'E':
1701debfc3dSmrg if (XVEC (part, i) != NULL)
1711debfc3dSmrg for (j = 0; j < XVECLEN (part, i); j++)
1721debfc3dSmrg walk_insn_part (XVECEXP (part, i, j), recog_p, non_pc_set_src);
1731debfc3dSmrg break;
1741debfc3dSmrg }
1751debfc3dSmrg }
1761debfc3dSmrg
1771debfc3dSmrg static void
gen_insn(md_rtx_info * info)1781debfc3dSmrg gen_insn (md_rtx_info *info)
1791debfc3dSmrg {
1801debfc3dSmrg int i;
1811debfc3dSmrg
1821debfc3dSmrg /* Walk the insn pattern to gather the #define's status. */
1831debfc3dSmrg rtx insn = info->def;
1841debfc3dSmrg clobbers_seen_this_insn = 0;
1851debfc3dSmrg dup_operands_seen_this_insn = 0;
1861debfc3dSmrg if (XVEC (insn, 1) != 0)
1871debfc3dSmrg for (i = 0; i < XVECLEN (insn, 1); i++)
1881debfc3dSmrg walk_insn_part (XVECEXP (insn, 1, i), 1, 0);
1891debfc3dSmrg
1901debfc3dSmrg if (clobbers_seen_this_insn > max_clobbers_per_insn)
1911debfc3dSmrg max_clobbers_per_insn = clobbers_seen_this_insn;
1921debfc3dSmrg if (dup_operands_seen_this_insn > max_dup_operands)
1931debfc3dSmrg max_dup_operands = dup_operands_seen_this_insn;
1941debfc3dSmrg }
1951debfc3dSmrg
1961debfc3dSmrg /* Similar but scan a define_expand. */
1971debfc3dSmrg
1981debfc3dSmrg static void
gen_expand(md_rtx_info * info)1991debfc3dSmrg gen_expand (md_rtx_info *info)
2001debfc3dSmrg {
2011debfc3dSmrg int i;
2021debfc3dSmrg
2031debfc3dSmrg /* Walk the insn pattern to gather the #define's status. */
2041debfc3dSmrg
2051debfc3dSmrg /* Note that we don't bother recording the number of MATCH_DUPs
2061debfc3dSmrg that occur in a gen_expand, because only reload cares about that. */
2071debfc3dSmrg rtx insn = info->def;
2081debfc3dSmrg if (XVEC (insn, 1) != 0)
2091debfc3dSmrg for (i = 0; i < XVECLEN (insn, 1); i++)
2101debfc3dSmrg {
2111debfc3dSmrg /* Compute the maximum SETs and CLOBBERS
2121debfc3dSmrg in any one of the sub-insns;
2131debfc3dSmrg don't sum across all of them. */
2141debfc3dSmrg clobbers_seen_this_insn = 0;
2151debfc3dSmrg
2161debfc3dSmrg walk_insn_part (XVECEXP (insn, 1, i), 0, 0);
2171debfc3dSmrg
2181debfc3dSmrg if (clobbers_seen_this_insn > max_clobbers_per_insn)
2191debfc3dSmrg max_clobbers_per_insn = clobbers_seen_this_insn;
2201debfc3dSmrg }
2211debfc3dSmrg }
2221debfc3dSmrg
2231debfc3dSmrg /* Similar but scan a define_split. */
2241debfc3dSmrg
2251debfc3dSmrg static void
gen_split(md_rtx_info * info)2261debfc3dSmrg gen_split (md_rtx_info *info)
2271debfc3dSmrg {
2281debfc3dSmrg int i;
2291debfc3dSmrg
2301debfc3dSmrg /* Look through the patterns that are matched
2311debfc3dSmrg to compute the maximum operand number. */
2321debfc3dSmrg rtx split = info->def;
2331debfc3dSmrg for (i = 0; i < XVECLEN (split, 0); i++)
2341debfc3dSmrg walk_insn_part (XVECEXP (split, 0, i), 1, 0);
2351debfc3dSmrg /* Look at the number of insns this insn could split into. */
2361debfc3dSmrg if (XVECLEN (split, 2) > max_insns_per_split)
2371debfc3dSmrg max_insns_per_split = XVECLEN (split, 2);
2381debfc3dSmrg }
2391debfc3dSmrg
2401debfc3dSmrg static void
gen_peephole(md_rtx_info * info)2411debfc3dSmrg gen_peephole (md_rtx_info *info)
2421debfc3dSmrg {
2431debfc3dSmrg int i;
2441debfc3dSmrg
2451debfc3dSmrg /* Look through the patterns that are matched
2461debfc3dSmrg to compute the maximum operand number. */
2471debfc3dSmrg rtx peep = info->def;
2481debfc3dSmrg for (i = 0; i < XVECLEN (peep, 0); i++)
2491debfc3dSmrg walk_insn_part (XVECEXP (peep, 0, i), 1, 0);
2501debfc3dSmrg }
2511debfc3dSmrg
2521debfc3dSmrg static void
gen_peephole2(md_rtx_info * info)2531debfc3dSmrg gen_peephole2 (md_rtx_info *info)
2541debfc3dSmrg {
2551debfc3dSmrg int i, n;
2561debfc3dSmrg
2571debfc3dSmrg /* Look through the patterns that are matched
2581debfc3dSmrg to compute the maximum operand number. */
2591debfc3dSmrg rtx peep = info->def;
2601debfc3dSmrg for (i = XVECLEN (peep, 0) - 1; i >= 0; --i)
2611debfc3dSmrg walk_insn_part (XVECEXP (peep, 0, i), 1, 0);
2621debfc3dSmrg
2631debfc3dSmrg /* Look at the number of insns this insn can be matched from. */
2641debfc3dSmrg for (i = XVECLEN (peep, 0) - 1, n = 0; i >= 0; --i)
2651debfc3dSmrg if (GET_CODE (XVECEXP (peep, 0, i)) != MATCH_DUP
2661debfc3dSmrg && GET_CODE (XVECEXP (peep, 0, i)) != MATCH_SCRATCH)
2671debfc3dSmrg n++;
2681debfc3dSmrg if (n > max_insns_per_peep2)
2691debfc3dSmrg max_insns_per_peep2 = n;
2701debfc3dSmrg }
2711debfc3dSmrg
2721debfc3dSmrg int
main(int argc,const char ** argv)2731debfc3dSmrg main (int argc, const char **argv)
2741debfc3dSmrg {
2751debfc3dSmrg progname = "genconfig";
2761debfc3dSmrg
2771debfc3dSmrg if (!init_rtx_reader_args (argc, argv))
2781debfc3dSmrg return (FATAL_EXIT_CODE);
2791debfc3dSmrg
2801debfc3dSmrg puts ("/* Generated automatically by the program `genconfig'");
2811debfc3dSmrg puts (" from the machine description file `md'. */\n");
2821debfc3dSmrg puts ("#ifndef GCC_INSN_CONFIG_H");
2831debfc3dSmrg puts ("#define GCC_INSN_CONFIG_H\n");
2841debfc3dSmrg
2851debfc3dSmrg /* Allow at least 30 operands for the sake of asm constructs. */
2861debfc3dSmrg /* ??? We *really* ought to reorganize things such that there
2871debfc3dSmrg is no fixed upper bound. */
2881debfc3dSmrg max_recog_operands = 29; /* We will add 1 later. */
2891debfc3dSmrg max_dup_operands = 1;
2901debfc3dSmrg
2911debfc3dSmrg /* Read the machine description. */
2921debfc3dSmrg
2931debfc3dSmrg md_rtx_info info;
2941debfc3dSmrg while (read_md_rtx (&info))
2951debfc3dSmrg switch (GET_CODE (info.def))
2961debfc3dSmrg {
2971debfc3dSmrg case DEFINE_INSN:
2981debfc3dSmrg gen_insn (&info);
2991debfc3dSmrg break;
3001debfc3dSmrg
3011debfc3dSmrg case DEFINE_EXPAND:
3021debfc3dSmrg gen_expand (&info);
3031debfc3dSmrg break;
3041debfc3dSmrg
3051debfc3dSmrg case DEFINE_SPLIT:
3061debfc3dSmrg gen_split (&info);
3071debfc3dSmrg break;
3081debfc3dSmrg
3091debfc3dSmrg case DEFINE_PEEPHOLE2:
3101debfc3dSmrg have_peephole2_flag = 1;
3111debfc3dSmrg gen_peephole2 (&info);
3121debfc3dSmrg break;
3131debfc3dSmrg
3141debfc3dSmrg case DEFINE_PEEPHOLE:
3151debfc3dSmrg have_peephole_flag = 1;
3161debfc3dSmrg gen_peephole (&info);
3171debfc3dSmrg break;
3181debfc3dSmrg
3191debfc3dSmrg default:
3201debfc3dSmrg break;
3211debfc3dSmrg }
3221debfc3dSmrg
3231debfc3dSmrg printf ("#define MAX_RECOG_OPERANDS %d\n", max_recog_operands + 1);
3241debfc3dSmrg printf ("#define MAX_DUP_OPERANDS %d\n", max_dup_operands);
3251debfc3dSmrg
3261debfc3dSmrg /* This is conditionally defined, in case the user writes code which emits
3271debfc3dSmrg more splits than we can readily see (and knows s/he does it). */
3281debfc3dSmrg printf ("#ifndef MAX_INSNS_PER_SPLIT\n");
3291debfc3dSmrg printf ("#define MAX_INSNS_PER_SPLIT %d\n", max_insns_per_split);
3301debfc3dSmrg printf ("#endif\n");
3311debfc3dSmrg
3321debfc3dSmrg if (have_cc0_flag)
3331debfc3dSmrg {
3341debfc3dSmrg printf ("#define HAVE_cc0 1\n");
3351debfc3dSmrg printf ("#define CC0_P(X) ((X) == cc0_rtx)\n");
3361debfc3dSmrg }
3371debfc3dSmrg else
3381debfc3dSmrg {
3391debfc3dSmrg /* We output CC0_P this way to make sure that X is declared
3401debfc3dSmrg somewhere. */
3411debfc3dSmrg printf ("#define HAVE_cc0 0\n");
3421debfc3dSmrg printf ("#define CC0_P(X) ((X) ? 0 : 0)\n");
3431debfc3dSmrg }
3441debfc3dSmrg
3451debfc3dSmrg if (have_cmove_flag)
3461debfc3dSmrg printf ("#define HAVE_conditional_move 1\n");
3471debfc3dSmrg else
3481debfc3dSmrg printf ("#define HAVE_conditional_move 0\n");
3491debfc3dSmrg
3501debfc3dSmrg if (have_cond_exec_flag)
3511debfc3dSmrg printf ("#define HAVE_conditional_execution 1\n");
3521debfc3dSmrg else
3531debfc3dSmrg printf ("#define HAVE_conditional_execution 0\n");
3541debfc3dSmrg
3551debfc3dSmrg if (have_lo_sum_flag)
3561debfc3dSmrg printf ("#define HAVE_lo_sum 1\n");
3571debfc3dSmrg else
3581debfc3dSmrg printf ("#define HAVE_lo_sum 0\n");
3591debfc3dSmrg
3601debfc3dSmrg if (have_rotate_flag)
3611debfc3dSmrg printf ("#define HAVE_rotate 1\n");
3621debfc3dSmrg
3631debfc3dSmrg if (have_rotatert_flag)
3641debfc3dSmrg printf ("#define HAVE_rotatert 1\n");
3651debfc3dSmrg
3661debfc3dSmrg if (have_peephole_flag)
3671debfc3dSmrg printf ("#define HAVE_peephole 1\n");
3681debfc3dSmrg else
3691debfc3dSmrg printf ("#define HAVE_peephole 0\n");
3701debfc3dSmrg
3711debfc3dSmrg if (have_peephole2_flag)
3721debfc3dSmrg {
3731debfc3dSmrg printf ("#define HAVE_peephole2 1\n");
3741debfc3dSmrg printf ("#define MAX_INSNS_PER_PEEP2 %d\n", max_insns_per_peep2);
3751debfc3dSmrg }
3761debfc3dSmrg else
3771debfc3dSmrg {
3781debfc3dSmrg printf ("#define HAVE_peephole2 0\n");
3791debfc3dSmrg printf ("#define MAX_INSNS_PER_PEEP2 0\n");
3801debfc3dSmrg }
3811debfc3dSmrg
3821debfc3dSmrg puts ("\n#endif /* GCC_INSN_CONFIG_H */");
3831debfc3dSmrg
3841debfc3dSmrg if (ferror (stdout) || fflush (stdout) || fclose (stdout))
3851debfc3dSmrg return FATAL_EXIT_CODE;
3861debfc3dSmrg
3871debfc3dSmrg return SUCCESS_EXIT_CODE;
3881debfc3dSmrg }
389