118334Speter/* Generate from machine description: 218334Speter - some flags HAVE_... saying which simple standard instructions are 318334Speter available for this machine. 490075Sobrien Copyright (C) 1987, 1991, 1995, 1998, 5132718Skan 1999, 2000, 2003, 2004 Free Software Foundation, Inc. 618334Speter 790075SobrienThis file is part of GCC. 818334Speter 990075SobrienGCC is free software; you can redistribute it and/or modify it under 1090075Sobrienthe terms of the GNU General Public License as published by the Free 1190075SobrienSoftware Foundation; either version 2, or (at your option) any later 1290075Sobrienversion. 1318334Speter 1490075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY 1590075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or 1690075SobrienFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1790075Sobrienfor more details. 1818334Speter 1918334SpeterYou should have received a copy of the GNU General Public License 2090075Sobrienalong with GCC; see the file COPYING. If not, write to the Free 21169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 22169689Skan02110-1301, USA. */ 2318334Speter 2418334Speter 25132718Skan#include "bconfig.h" 2650397Sobrien#include "system.h" 27132718Skan#include "coretypes.h" 28132718Skan#include "tm.h" 2918334Speter#include "rtl.h" 3018334Speter#include "obstack.h" 3190075Sobrien#include "errors.h" 3290075Sobrien#include "gensupport.h" 3318334Speter 3490075Sobrien/* Obstack to remember insns with. */ 3590075Sobrienstatic struct obstack obstack; 3618334Speter 3718334Speter/* Max size of names encountered. */ 3818334Speterstatic int max_id_len; 3918334Speter 4090075Sobrien/* Max operand encountered in a scan over some insn. */ 4190075Sobrienstatic int max_opno; 4250397Sobrien 43132718Skanstatic void max_operand_1 (rtx); 44132718Skanstatic int num_operands (rtx); 45132718Skanstatic void gen_proto (rtx); 46132718Skanstatic void gen_macro (const char *, int, int); 47132718Skanstatic void gen_insn (rtx); 4850397Sobrien 4918334Speter/* Count the number of match_operand's found. */ 5050397Sobrien 5190075Sobrienstatic void 52132718Skanmax_operand_1 (rtx x) 5318334Speter{ 5490075Sobrien RTX_CODE code; 5590075Sobrien int i; 5690075Sobrien int len; 5790075Sobrien const char *fmt; 5818334Speter 5990075Sobrien if (x == 0) 6090075Sobrien return; 6118334Speter 6290075Sobrien code = GET_CODE (x); 6318334Speter 6490075Sobrien if (code == MATCH_OPERAND || code == MATCH_OPERATOR 6590075Sobrien || code == MATCH_PARALLEL) 6690075Sobrien max_opno = MAX (max_opno, XINT (x, 0)); 6790075Sobrien 6890075Sobrien fmt = GET_RTX_FORMAT (code); 6990075Sobrien len = GET_RTX_LENGTH (code); 7090075Sobrien for (i = 0; i < len; i++) 7118334Speter { 7290075Sobrien if (fmt[i] == 'e' || fmt[i] == 'u') 7390075Sobrien max_operand_1 (XEXP (x, i)); 7490075Sobrien else if (fmt[i] == 'E') 7518334Speter { 7690075Sobrien int j; 7790075Sobrien for (j = 0; j < XVECLEN (x, i); j++) 7890075Sobrien max_operand_1 (XVECEXP (x, i, j)); 7918334Speter } 8018334Speter } 8190075Sobrien} 8218334Speter 8390075Sobrienstatic int 84132718Skannum_operands (rtx insn) 8590075Sobrien{ 8690075Sobrien int len = XVECLEN (insn, 1); 8790075Sobrien int i; 8890075Sobrien 8990075Sobrien max_opno = -1; 9090075Sobrien 9190075Sobrien for (i = 0; i < len; i++) 9290075Sobrien max_operand_1 (XVECEXP (insn, 1, i)); 9390075Sobrien 9490075Sobrien return max_opno + 1; 9518334Speter} 9618334Speter 9790075Sobrien/* Print out a wrapper macro for a function which corrects the number 9890075Sobrien of arguments it takes. Any missing arguments are assumed to be at 9990075Sobrien the end. */ 10090075Sobrienstatic void 101132718Skangen_macro (const char *name, int real, int expect) 10290075Sobrien{ 10390075Sobrien int i; 10490075Sobrien 105169689Skan gcc_assert (real <= expect); 106169689Skan gcc_assert (real); 10790075Sobrien 10890075Sobrien /* #define GEN_CALL(A, B, C, D) gen_call((A), (B)) */ 10990075Sobrien fputs ("#define GEN_", stdout); 11090075Sobrien for (i = 0; name[i]; i++) 11190075Sobrien putchar (TOUPPER (name[i])); 11290075Sobrien 11390075Sobrien putchar('('); 11490075Sobrien for (i = 0; i < expect - 1; i++) 11590075Sobrien printf ("%c, ", i + 'A'); 11690075Sobrien printf ("%c) gen_%s (", i + 'A', name); 11790075Sobrien 11890075Sobrien for (i = 0; i < real - 1; i++) 11990075Sobrien printf ("(%c), ", i + 'A'); 12090075Sobrien printf ("(%c))\n", i + 'A'); 12190075Sobrien} 12290075Sobrien 123117395Skan/* Print out prototype information for a generator function. If the 124117395Skan insn pattern has been elided, print out a dummy generator that 125117395Skan does nothing. */ 12650397Sobrien 12718334Speterstatic void 128132718Skangen_proto (rtx insn) 12918334Speter{ 13018334Speter int num = num_operands (insn); 131117395Skan int i; 13290075Sobrien const char *name = XSTR (insn, 0); 133117395Skan int truth = maybe_eval_c_test (XSTR (insn, 2)); 13418334Speter 13590075Sobrien /* Many md files don't refer to the last two operands passed to the 13690075Sobrien call patterns. This means their generator functions will be two 13790075Sobrien arguments too short. Instead of changing every md file to touch 13890075Sobrien those operands, we wrap the prototypes in macros that take the 13990075Sobrien correct number of arguments. */ 14090075Sobrien if (name[0] == 'c' || name[0] == 's') 14190075Sobrien { 14290075Sobrien if (!strcmp (name, "call") 14390075Sobrien || !strcmp (name, "call_pop") 14490075Sobrien || !strcmp (name, "sibcall") 14590075Sobrien || !strcmp (name, "sibcall_pop")) 14690075Sobrien gen_macro (name, num, 4); 14790075Sobrien else if (!strcmp (name, "call_value") 14890075Sobrien || !strcmp (name, "call_value_pop") 14990075Sobrien || !strcmp (name, "sibcall_value") 15090075Sobrien || !strcmp (name, "sibcall_value_pop")) 15190075Sobrien gen_macro (name, num, 5); 15290075Sobrien } 15390075Sobrien 154117395Skan if (truth != 0) 155132718Skan printf ("extern rtx gen_%-*s (", max_id_len, name); 156117395Skan else 157132718Skan printf ("static inline rtx gen_%-*s (", max_id_len, name); 15890075Sobrien 15918334Speter if (num == 0) 160117395Skan fputs ("void", stdout); 16118334Speter else 16218334Speter { 163117395Skan for (i = 1; i < num; i++) 164117395Skan fputs ("rtx, ", stdout); 165132718Skan 166117395Skan fputs ("rtx", stdout); 167117395Skan } 16818334Speter 169132718Skan puts (");"); 170117395Skan 171117395Skan /* Some back ends want to take the address of generator functions, 172117395Skan so we cannot simply use #define for these dummy definitions. */ 173117395Skan if (truth == 0) 174117395Skan { 175117395Skan printf ("static inline rtx\ngen_%s", name); 176117395Skan if (num > 0) 177117395Skan { 178117395Skan putchar ('('); 179117395Skan for (i = 0; i < num-1; i++) 180169689Skan printf ("rtx ARG_UNUSED (%c), ", 'a' + i); 181169689Skan printf ("rtx ARG_UNUSED (%c))\n", 'a' + i); 182117395Skan } 183117395Skan else 184132718Skan puts ("(void)"); 185117395Skan puts ("{\n return 0;\n}"); 18618334Speter } 18718334Speter 18818334Speter} 18918334Speter 19018334Speterstatic void 191132718Skangen_insn (rtx insn) 19218334Speter{ 19390075Sobrien const char *name = XSTR (insn, 0); 19490075Sobrien const char *p; 19518334Speter int len; 196117395Skan int truth = maybe_eval_c_test (XSTR (insn, 2)); 19718334Speter 19818334Speter /* Don't mention instructions whose names are the null string 19918334Speter or begin with '*'. They are in the machine description just 20018334Speter to be recognized. */ 20118334Speter if (name[0] == 0 || name[0] == '*') 20218334Speter return; 20318334Speter 20418334Speter len = strlen (name); 20518334Speter 20618334Speter if (len > max_id_len) 20718334Speter max_id_len = len; 20818334Speter 209117395Skan if (truth == 0) 210132718Skan /* Emit nothing. */; 211117395Skan else if (truth == 1) 212117395Skan printf ("#define HAVE_%s 1\n", name); 21318334Speter else 21418334Speter { 21518334Speter /* Write the macro definition, putting \'s at the end of each line, 21618334Speter if more than one. */ 217117395Skan printf ("#define HAVE_%s (", name); 21818334Speter for (p = XSTR (insn, 2); *p; p++) 21918334Speter { 22096263Sobrien if (IS_VSPACE (*p)) 221117395Skan fputs (" \\\n", stdout); 22218334Speter else 223117395Skan putchar (*p); 22418334Speter } 225117395Skan fputs (")\n", stdout); 22618334Speter } 22718334Speter 22890075Sobrien obstack_grow (&obstack, &insn, sizeof (rtx)); 22918334Speter} 23018334Speter 23118334Speterint 232132718Skanmain (int argc, char **argv) 23318334Speter{ 23418334Speter rtx desc; 23518334Speter rtx dummy; 23690075Sobrien rtx *insns; 23718334Speter rtx *insn_ptr; 23818334Speter 23990075Sobrien progname = "genflags"; 24090075Sobrien obstack_init (&obstack); 24118334Speter 242117395Skan /* We need to see all the possibilities. Elided insns may have 243117395Skan direct calls to their generators in C code. */ 244117395Skan insn_elision = 0; 245117395Skan 24690075Sobrien if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE) 24790075Sobrien return (FATAL_EXIT_CODE); 248132718Skan 24990075Sobrien puts ("/* Generated automatically by the program `genflags'"); 25090075Sobrien puts (" from the machine description file `md'. */\n"); 25190075Sobrien puts ("#ifndef GCC_INSN_FLAGS_H"); 25290075Sobrien puts ("#define GCC_INSN_FLAGS_H\n"); 25318334Speter 25418334Speter /* Read the machine description. */ 25518334Speter 25618334Speter while (1) 25718334Speter { 25890075Sobrien int line_no, insn_code_number = 0; 25990075Sobrien 26090075Sobrien desc = read_md_rtx (&line_no, &insn_code_number); 26190075Sobrien if (desc == NULL) 26218334Speter break; 26318334Speter if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND) 26418334Speter gen_insn (desc); 26518334Speter } 26618334Speter 26718334Speter /* Print out the prototypes now. */ 26850397Sobrien dummy = (rtx) 0; 26990075Sobrien obstack_grow (&obstack, &dummy, sizeof (rtx)); 270169689Skan insns = XOBFINISH (&obstack, rtx *); 27118334Speter 27290075Sobrien for (insn_ptr = insns; *insn_ptr; insn_ptr++) 27318334Speter gen_proto (*insn_ptr); 27418334Speter 27590075Sobrien puts("\n#endif /* GCC_INSN_FLAGS_H */"); 27618334Speter 27790075Sobrien if (ferror (stdout) || fflush (stdout) || fclose (stdout)) 27890075Sobrien return FATAL_EXIT_CODE; 27918334Speter 28090075Sobrien return SUCCESS_EXIT_CODE; 28190075Sobrien} 282