📄 genemit.c
字号:
printf ("rtx\ngen_%s (", XSTR (expand, 0)); for (i = 0; i < operands; i++) printf (i ? ", operand%d" : "operand%d", i); printf (")\n"); for (i = 0; i < operands; i++) printf (" rtx operand%d;\n", i); printf ("{\n"); /* If we don't have any C code to write, only one insn is being written, and no MATCH_DUPs are present, we can just return the desired insn like we do for a DEFINE_INSN. This saves memory. */ if ((XSTR (expand, 3) == 0 || *XSTR (expand, 3) == '\0') && operands > max_dup_opno && XVECLEN (expand, 1) == 1) { printf (" return "); gen_exp (XVECEXP (expand, 1, 0)); printf (";\n}\n\n"); return; } /* For each operand referred to only with MATCH_DUPs, make a local variable. */ for (i = operands; i <= max_dup_opno; i++) printf (" rtx operand%d;\n", i); if (operands > 0 || max_dup_opno >= 0) printf (" rtx operands[%d];\n", MAX (operands, max_dup_opno + 1)); printf (" rtx _val = 0;\n"); printf (" start_sequence ();\n"); /* The fourth operand of DEFINE_EXPAND is some code to be executed before the actual construction. This code expects to refer to `operands' just as the output-code in a DEFINE_INSN does, but here `operands' is an automatic array. So copy the operand values there before executing it. */ if (XSTR (expand, 3) && *XSTR (expand, 3)) { /* Output code to copy the arguments into `operands'. */ for (i = 0; i < operands; i++) printf (" operands[%d] = operand%d;\n", i, i); /* Output the special code to be executed before the sequence is generated. */ printf ("%s\n", XSTR (expand, 3)); /* Output code to copy the arguments back out of `operands' (unless we aren't going to use them at all). */ if (XVEC (expand, 1) != 0) { for (i = 0; i < operands; i++) printf (" operand%d = operands[%d];\n", i, i); for (; i <= max_dup_opno; i++) printf (" operand%d = operands[%d];\n", i, i); } } /* Output code to construct the rtl for the instruction bodies. Use emit_insn to add them to the sequence being accumulated. But don't do this if the user's code has set `no_more' nonzero. */ for (i = 0; i < XVECLEN (expand, 1); i++) { rtx next = XVECEXP (expand, 1, i); if ((GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC) || (GET_CODE (next) == PARALLEL && GET_CODE (XVECEXP (next, 0, 0)) == SET && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC) || GET_CODE (next) == RETURN) printf (" emit_jump_insn ("); else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL) || GET_CODE (next) == CALL || (GET_CODE (next) == PARALLEL && GET_CODE (XVECEXP (next, 0, 0)) == SET && GET_CODE (SET_SRC (XVECEXP (next, 0, 0))) == CALL) || (GET_CODE (next) == PARALLEL && GET_CODE (XVECEXP (next, 0, 0)) == CALL)) printf (" emit_call_insn ("); else if (GET_CODE (next) == CODE_LABEL) printf (" emit_label ("); else if (GET_CODE (next) == MATCH_OPERAND || GET_CODE (next) == MATCH_OPERATOR || GET_CODE (next) == MATCH_PARALLEL || GET_CODE (next) == MATCH_OP_DUP || GET_CODE (next) == MATCH_DUP || GET_CODE (next) == PARALLEL) printf (" emit ("); else printf (" emit_insn ("); gen_exp (next); printf (");\n"); if (GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC && GET_CODE (SET_SRC (next)) == LABEL_REF) printf (" emit_barrier ();"); } /* Call `gen_sequence' to make a SEQUENCE out of all the insns emitted within this gen_... function. */ printf (" _done:\n"); printf (" _val = gen_sequence ();\n"); printf (" _fail:\n"); printf (" end_sequence ();\n"); printf (" return _val;\n}\n\n");}/* Like gen_expand, but generates a SEQUENCE. */static voidgen_split (split) rtx split;{ register int i; int operands; if (XVEC (split, 0) == 0) fatal ("define_split (definition %d) lacks a pattern", insn_index_number); else if (XVEC (split, 2) == 0) fatal ("define_split (definition %d) lacks a replacement pattern", insn_index_number); /* Find out how many operands this function has. */ max_operand_vec (split, 2); operands = MAX (max_opno, max_dup_opno) + 1; /* Output the function name and argument declarations. */ printf ("rtx\ngen_split_%d (operands)\n rtx *operands;\n", insn_code_number); printf ("{\n"); /* Declare all local variables. */ for (i = 0; i < operands; i++) printf (" rtx operand%d;\n", i); printf (" rtx _val = 0;\n"); printf (" start_sequence ();\n"); /* The fourth operand of DEFINE_SPLIT is some code to be executed before the actual construction. */ if (XSTR (split, 3)) printf ("%s\n", XSTR (split, 3)); /* Output code to copy the arguments back out of `operands' */ for (i = 0; i < operands; i++) printf (" operand%d = operands[%d];\n", i, i); /* Output code to construct the rtl for the instruction bodies. Use emit_insn to add them to the sequence being accumulated. But don't do this if the user's code has set `no_more' nonzero. */ for (i = 0; i < XVECLEN (split, 2); i++) { rtx next = XVECEXP (split, 2, i); if ((GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC) || (GET_CODE (next) == PARALLEL && GET_CODE (XVECEXP (next, 0, 0)) == SET && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC) || GET_CODE (next) == RETURN) printf (" emit_jump_insn ("); else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL) || GET_CODE (next) == CALL || (GET_CODE (next) == PARALLEL && GET_CODE (XVECEXP (next, 0, 0)) == SET && GET_CODE (SET_SRC (XVECEXP (next, 0, 0))) == CALL) || (GET_CODE (next) == PARALLEL && GET_CODE (XVECEXP (next, 0, 0)) == CALL)) printf (" emit_call_insn ("); else if (GET_CODE (next) == CODE_LABEL) printf (" emit_label ("); else if (GET_CODE (next) == MATCH_OPERAND || GET_CODE (next) == MATCH_OPERATOR || GET_CODE (next) == MATCH_PARALLEL || GET_CODE (next) == MATCH_OP_DUP || GET_CODE (next) == MATCH_DUP || GET_CODE (next) == PARALLEL) printf (" emit ("); else printf (" emit_insn ("); gen_exp (next); printf (");\n"); if (GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC && GET_CODE (SET_SRC (next)) == LABEL_REF) printf (" emit_barrier ();"); } /* Call `gen_sequence' to make a SEQUENCE out of all the insns emitted within this gen_... function. */ printf (" _done:\n"); printf (" _val = gen_sequence ();\n"); printf (" _fail:\n"); printf (" end_sequence ();\n"); printf (" return _val;\n}\n\n");}/* Write a function, `add_clobbers', that is given a PARALLEL of sufficient size for the insn and an INSN_CODE, and inserts the required CLOBBERs at the end of the vector. */static voidoutput_add_clobbers (){ struct clobber_pat *clobber; struct clobber_ent *ent; int i; printf ("\n\nvoid\nadd_clobbers (pattern, insn_code_number)\n"); printf (" rtx pattern;\n int insn_code_number;\n"); printf ("{\n"); printf (" int i;\n\n"); printf (" switch (insn_code_number)\n"); printf (" {\n"); for (clobber = clobber_list; clobber; clobber = clobber->next) { for (ent = clobber->insns; ent; ent = ent->next) printf (" case %d:\n", ent->code_number); for (i = clobber->first_clobber; i < XVECLEN (clobber->pattern, 1); i++) { printf (" XVECEXP (pattern, 0, %d) = ", i); gen_exp (XVECEXP (clobber->pattern, 1, i)); printf (";\n"); } printf (" break;\n\n"); } printf (" default:\n"); printf (" abort ();\n"); printf (" }\n"); printf ("}\n");}/* Write a function, init_mov_optab, that is called to set up entries in mov_optab for EXTRA_CC_MODES. */static voidoutput_init_mov_optab (){#ifdef EXTRA_CC_NAMES static char *cc_names[] = { EXTRA_CC_NAMES }; char *p; int i; printf ("\nvoid\ninit_mov_optab ()\n{\n"); for (i = 0; i < sizeof cc_names / sizeof cc_names[0]; i++) { printf ("#ifdef HAVE_mov"); for (p = cc_names[i]; *p; p++) printf ("%c", *p >= 'A' && *p <= 'Z' ? *p - 'A' + 'a' : *p); printf ("\n"); printf (" if (HAVE_mov"); for (p = cc_names[i]; *p; p++) printf ("%c", *p >= 'A' && *p <= 'Z' ? *p - 'A' + 'a' : *p); printf (")\n"); printf (" mov_optab->handlers[(int) %smode].insn_code = CODE_FOR_mov", cc_names[i]); for (p = cc_names[i]; *p; p++) printf ("%c", *p >= 'A' && *p <= 'Z' ? *p - 'A' + 'a' : *p); printf (";\n#endif\n"); } printf ("}\n");#endif}char *xmalloc (size) unsigned size;{ register char *val = (char *) malloc (size); if (val == 0) fatal ("virtual memory exhausted"); return val;}char *xrealloc (ptr, size) char *ptr; unsigned size;{ char *result = (char *) realloc (ptr, size); if (!result) fatal ("virtual memory exhausted"); return result;}static voidfatal (s, a1, a2) char *s;{ fprintf (stderr, "genemit: "); fprintf (stderr, s, a1, a2); fprintf (stderr, "\n"); exit (FATAL_EXIT_CODE);}/* More 'friendly' abort that prints the line and file. config.h can #define abort fancy_abort if you like that sort of thing. */voidfancy_abort (){ fatal ("Internal gcc abort.");}intmain (argc, argv) int argc; char **argv;{ rtx desc; FILE *infile; register int c; obstack_init (rtl_obstack); if (argc <= 1) fatal ("No input file name."); infile = fopen (argv[1], "r"); if (infile == 0) { perror (argv[1]); exit (FATAL_EXIT_CODE); } init_rtl (); /* Assign sequential codes to all entries in the machine description in parallel with the tables in insn-output.c. */ insn_code_number = 0; insn_index_number = 0; printf ("/* Generated automatically by the program `genemit'\n\from the machine description file `md'. */\n\n"); printf ("#include \"config.h\"\n"); printf ("#include \"rtl.h\"\n"); printf ("#include \"expr.h\"\n"); printf ("#include \"real.h\"\n"); printf ("#include \"output.h\"\n"); printf ("#include \"insn-config.h\"\n\n"); printf ("#include \"insn-flags.h\"\n\n"); printf ("#include \"insn-codes.h\"\n\n"); printf ("extern char *insn_operand_constraint[][MAX_RECOG_OPERANDS];\n\n"); printf ("extern rtx recog_operand[];\n"); printf ("#define operands emit_operand\n\n"); printf ("#define FAIL goto _fail\n\n"); printf ("#define DONE goto _done\n\n"); /* Read the machine description. */ while (1) { c = read_skip_spaces (infile); if (c == EOF) break; ungetc (c, infile); desc = read_rtx (infile); if (GET_CODE (desc) == DEFINE_INSN) { gen_insn (desc); ++insn_code_number; } if (GET_CODE (desc) == DEFINE_EXPAND) { gen_expand (desc); ++insn_code_number; } if (GET_CODE (desc) == DEFINE_SPLIT) { gen_split (desc); ++insn_code_number; } if (GET_CODE (desc) == DEFINE_PEEPHOLE) { ++insn_code_number; } ++insn_index_number; } /* Write out the routine to add CLOBBERs to a pattern. */ output_add_clobbers (); /* Write the routine to initialize mov_optab for the EXTRA_CC_MODES. */ output_init_mov_optab (); fflush (stdout); exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); /* NOTREACHED */ return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -