|
|
1.1 ! root 1: /* Generate code to initialize optabs from machine description. ! 2: Copyright (C) 1993 Free Software Foundation, Inc. ! 3: ! 4: This file is part of GNU CC. ! 5: ! 6: GNU CC is free software; you can redistribute it and/or modify ! 7: it under the terms of the GNU General Public License as published by ! 8: the Free Software Foundation; either version 2, or (at your option) ! 9: any later version. ! 10: ! 11: GNU CC is distributed in the hope that it will be useful, ! 12: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 14: GNU General Public License for more details. ! 15: ! 16: You should have received a copy of the GNU General Public License ! 17: along with GNU CC; see the file COPYING. If not, write to ! 18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! 19: ! 20: ! 21: #include <stdio.h> ! 22: #include "hconfig.h" ! 23: #include "rtl.h" ! 24: #include "obstack.h" ! 25: #include <ctype.h> ! 26: ! 27: static struct obstack obstack; ! 28: struct obstack *rtl_obstack = &obstack; ! 29: ! 30: #define obstack_chunk_alloc xmalloc ! 31: #define obstack_chunk_free free ! 32: ! 33: extern void free (); ! 34: extern rtx read_rtx (); ! 35: ! 36: char *xmalloc (); ! 37: static void fatal (); ! 38: void fancy_abort (); ! 39: ! 40: /* Many parts of GCC use arrays that are indexed by machine mode and ! 41: contain the insn codes for pattern in the MD file that perform a given ! 42: operation on operands of that mode. ! 43: ! 44: These patterns are present in the MD file with names that contain ! 45: the mode(s) used and the name of the operation. This program ! 46: writes a function `init_all_optabs' that initializes the optabs with ! 47: all the insn codes of the relevant patterns present in the MD file. ! 48: ! 49: This array contains a list of optabs that need to be initialized. Within ! 50: each string, the name of the pattern to be matched against is delimited ! 51: with %( and %). In the string, %a and %b are used to match a short mode ! 52: name (the part of the mode name not including `mode' and converted to ! 53: lower-case). When writing out the initializer, the entire string is ! 54: used. %A and %B are replaced with the full name of the mode; %a and %b ! 55: are replaced with the short form of the name, as above. ! 56: ! 57: If %N is present in the pattern, it means the two modes must be consecutive ! 58: widths in the same mode class (e.g, QImode and HImode). %I means that ! 59: only integer modes should be considered for the next mode, and %F means ! 60: that only float modes should be considered. ! 61: ! 62: For some optabs, we store the operation by RTL codes. These are only ! 63: used for comparisons. In that case, %c and %C are the lower-case and ! 64: upper-case forms of the comparison, respectively. */ ! 65: ! 66: /* The reason we use \% is to avoid sequences of the form %-capletter-% ! 67: which SCCS treats as magic. This gets warnings which you should ignore. */ ! 68: ! 69: char *optabs[] = ! 70: { "extendtab[(int) %B][(int) %A][0] = CODE_FOR_%(extend%a\%b2%)", ! 71: "extendtab[(int) %B][(int) %A][1] = CODE_FOR_%(zero_extend%a\%b2%)", ! 72: "fixtab[(int) %A][(int) %B][0] = CODE_FOR_%(fix%F\%a%I\%b2%)", ! 73: "fixtab[(int) %A][(int) %B][1] = CODE_FOR_%(fixuns%F\%a%b2%)", ! 74: "fixtrunctab[(int) %A][(int) %B][0] = CODE_FOR_%(fix_trunc%F\%a%I\%b2%)", ! 75: "fixtrunctab[(int) %A][(int) %B][1] = CODE_FOR_%(fixuns_trunc%F\%a%I\%b2%)", ! 76: "floattab[(int) %B][(int) %A][0] = CODE_FOR_%(float%I\%a%F\%b2%)", ! 77: "floattab[(int) %B][(int) %A][1] = CODE_FOR_%(floatuns%I\%a%F\%b2%)", ! 78: "add_optab->handlers[(int) %A].insn_code = CODE_FOR_%(add%a3%)", ! 79: "sub_optab->handlers[(int) %A].insn_code = CODE_FOR_%(sub%a3%)", ! 80: "smul_optab->handlers[(int) %A].insn_code = CODE_FOR_%(mul%a3%)", ! 81: "smul_widen_optab->handlers[(int) %B].insn_code = CODE_FOR_%(mul%a%b3%)%N", ! 82: "umul_widen_optab->handlers[(int) %B].insn_code = CODE_FOR_%(umul%a%b3%)%N", ! 83: "sdiv_optab->handlers[(int) %A].insn_code = CODE_FOR_%(div%I\%a3%)", ! 84: "udiv_optab->handlers[(int) %A].insn_code = CODE_FOR_%(udiv%I\%a3%)", ! 85: "sdivmod_optab->handlers[(int) %A].insn_code = CODE_FOR_%(divmod%a4%)", ! 86: "udivmod_optab->handlers[(int) %A].insn_code = CODE_FOR_%(udivmod%a4%)", ! 87: "smod_optab->handlers[(int) %A].insn_code = CODE_FOR_%(mod%a3%)", ! 88: "umod_optab->handlers[(int) %A].insn_code = CODE_FOR_%(umod%a3%)", ! 89: "flodiv_optab->handlers[(int) %A].insn_code = CODE_FOR_%(div%F\%a3%)", ! 90: "ftrunc_optab->handlers[(int) %A].insn_code = CODE_FOR_%(ftrunc%F\%a2%)", ! 91: "and_optab->handlers[(int) %A].insn_code = CODE_FOR_%(and%a3%)", ! 92: "ior_optab->handlers[(int) %A].insn_code = CODE_FOR_%(ior%a3%)", ! 93: "xor_optab->handlers[(int) %A].insn_code = CODE_FOR_%(xor%a3%)", ! 94: "ashl_optab->handlers[(int) %A].insn_code = CODE_FOR_%(ashl%a3%)", ! 95: "ashr_optab->handlers[(int) %A].insn_code = CODE_FOR_%(ashr%a3%)", ! 96: "lshl_optab->handlers[(int) %A].insn_code = CODE_FOR_%(lshl%a3%)", ! 97: "lshr_optab->handlers[(int) %A].insn_code = CODE_FOR_%(lshr%a3%)", ! 98: "rotl_optab->handlers[(int) %A].insn_code = CODE_FOR_%(rotl%a3%)", ! 99: "rotr_optab->handlers[(int) %A].insn_code = CODE_FOR_%(rotr%a3%)", ! 100: "smin_optab->handlers[(int) %A].insn_code = CODE_FOR_%(smin%I\%a3%)", ! 101: "smin_optab->handlers[(int) %A].insn_code = CODE_FOR_%(min%F\%a3%)", ! 102: "smax_optab->handlers[(int) %A].insn_code = CODE_FOR_%(smax%I\%a3%)", ! 103: "smax_optab->handlers[(int) %A].insn_code = CODE_FOR_%(max%F\%a3%)", ! 104: "umin_optab->handlers[(int) %A].insn_code = CODE_FOR_%(umin%I\%a3%)", ! 105: "umax_optab->handlers[(int) %A].insn_code = CODE_FOR_%(umax%I\%a3%)", ! 106: "neg_optab->handlers[(int) %A].insn_code = CODE_FOR_%(neg%a2%)", ! 107: "abs_optab->handlers[(int) %A].insn_code = CODE_FOR_%(abs%a2%)", ! 108: "sqrt_optab->handlers[(int) %A].insn_code = CODE_FOR_%(sqrt%a2%)", ! 109: "sin_optab->handlers[(int) %A].insn_code = CODE_FOR_%(sin%a2%)", ! 110: "cos_optab->handlers[(int) %A].insn_code = CODE_FOR_%(cos%a2%)", ! 111: "strlen_optab->handlers[(int) %A].insn_code = CODE_FOR_%(strlen%a%)", ! 112: "one_cmpl_optab->handlers[(int) %A].insn_code = CODE_FOR_%(one_cmpl%a2%)", ! 113: "ffs_optab->handlers[(int) %A].insn_code = CODE_FOR_%(ffs%a2%)", ! 114: "mov_optab->handlers[(int) %A].insn_code = CODE_FOR_%(mov%a%)", ! 115: "movstrict_optab->handlers[(int) %A].insn_code = CODE_FOR_%(movstrict%a%)", ! 116: "cmp_optab->handlers[(int) %A].insn_code = CODE_FOR_%(cmp%a%)", ! 117: "tst_optab->handlers[(int) %A].insn_code = CODE_FOR_%(tst%a%)", ! 118: "bcc_gen_fctn[(int) %C] = gen_%(b%c%)", ! 119: "setcc_gen_code[(int) %C] = CODE_FOR_%(s%c%)", ! 120: "reload_in_optab[(int) %A] = CODE_FOR_%(reload_in%a%)", ! 121: "reload_out_optab[(int) %A] = CODE_FOR_%(reload_out%a%)", ! 122: "movstr_optab[(int) %A] = CODE_FOR_%(movstr%a%)" }; ! 123: ! 124: /* Allow linking with print-rtl.c. */ ! 125: char **insn_name_ptr; ! 126: ! 127: static void ! 128: gen_insn (insn) ! 129: rtx insn; ! 130: { ! 131: char *name = XSTR (insn, 0); ! 132: int m1, m2, op; ! 133: int pindex; ! 134: int i; ! 135: char *np, *pp, *p, *q; ! 136: struct obstack *obstack_ptr; ! 137: ! 138: /* Don't mention instructions whose names are the null string. ! 139: They are in the machine description just to be recognized. */ ! 140: if (*name == 0) ! 141: return; ! 142: ! 143: /* See if NAME matches one of the patterns we have for the optabs we know ! 144: about. */ ! 145: ! 146: for (pindex = 0; pindex < sizeof optabs / sizeof optabs[0]; pindex++) ! 147: { ! 148: int force_float = 0, force_int = 0; ! 149: int force_consec = 0; ! 150: int matches = 1; ! 151: ! 152: for (pp = optabs[pindex]; pp[0] != '%' || pp[1] != '('; pp++) ! 153: ; ! 154: ! 155: for (pp += 2, np = name; matches && ! (pp[0] == '%' && pp[1] == ')'); ! 156: pp++) ! 157: { ! 158: if (*pp != '%') ! 159: { ! 160: if (*pp != *np++) ! 161: break; ! 162: } ! 163: else ! 164: switch (*++pp) ! 165: { ! 166: case 'N': ! 167: force_consec = 1; ! 168: break; ! 169: case 'I': ! 170: force_int = 1; ! 171: break; ! 172: case 'F': ! 173: force_float = 1; ! 174: break; ! 175: case 'c': ! 176: for (op = 0; op < NUM_RTX_CODE; op++) ! 177: { ! 178: for (p = rtx_name[op], q = np; *p; p++, q++) ! 179: if (*p != *q) ! 180: break; ! 181: ! 182: /* We have to be concerned about matching "gt" and ! 183: missing "gtu", e.g., so verify we have reached the ! 184: end of thing we are to match. We do not have this ! 185: problem with modes since no mode is a prefix of ! 186: another. */ ! 187: if (*p == 0 && *q == 0 && rtx_class[op] == '<') ! 188: break; ! 189: } ! 190: ! 191: if (op == NUM_RTX_CODE) ! 192: matches = 0; ! 193: else ! 194: np += strlen (rtx_name[op]); ! 195: break; ! 196: case 'a': ! 197: case 'b': ! 198: for (i = 0; i < (int) MAX_MACHINE_MODE; i++) ! 199: { ! 200: for (p = mode_name[i], q = np; *p; p++, q++) ! 201: if (tolower (*p) != *q) ! 202: break; ! 203: ! 204: if (*p == 0 ! 205: && (! force_int || mode_class[i] == MODE_INT) ! 206: && (! force_float || mode_class[i] == MODE_FLOAT)) ! 207: break; ! 208: } ! 209: ! 210: if (i == (int) MAX_MACHINE_MODE) ! 211: matches = 0; ! 212: else if (*pp == 'a') ! 213: m1 = i, np += strlen (mode_name[i]); ! 214: else ! 215: m2 = i, np += strlen (mode_name[i]); ! 216: ! 217: force_int = force_float = 0; ! 218: break; ! 219: ! 220: default: ! 221: abort (); ! 222: } ! 223: } ! 224: ! 225: if (matches && pp[0] == '%' && pp[1] == ')' ! 226: && *np == 0 ! 227: && (! force_consec || (int) mode_wider_mode[m1] == m2)) ! 228: break; ! 229: } ! 230: ! 231: if (pindex == sizeof optabs / sizeof optabs[0]) ! 232: return; ! 233: ! 234: /* We found a match. If this pattern is only conditionally present, ! 235: write out the "if" and two extra blanks. */ ! 236: ! 237: if (*XSTR (insn, 2) != 0) ! 238: printf (" if (HAVE_%s)\n ", name); ! 239: ! 240: printf (" "); ! 241: ! 242: /* Now write out the initialization, making all required substitutions. */ ! 243: for (pp = optabs[pindex]; *pp; pp++) ! 244: { ! 245: if (*pp != '%') ! 246: printf ("%c", *pp); ! 247: else ! 248: switch (*++pp) ! 249: { ! 250: case '(': case ')': ! 251: case 'I': case 'F': case 'N': ! 252: break; ! 253: case 'a': ! 254: for (np = mode_name[m1]; *np; np++) ! 255: printf ("%c", tolower (*np)); ! 256: break; ! 257: case 'b': ! 258: for (np = mode_name[m2]; *np; np++) ! 259: printf ("%c", tolower (*np)); ! 260: break; ! 261: case 'A': ! 262: printf ("%smode", mode_name[m1]); ! 263: break; ! 264: case 'B': ! 265: printf ("%smode", mode_name[m2]); ! 266: break; ! 267: case 'c': ! 268: printf ("%s", rtx_name[op]); ! 269: break; ! 270: case 'C': ! 271: for (np = rtx_name[op]; *np; np++) ! 272: printf ("%c", toupper (*np)); ! 273: break; ! 274: } ! 275: } ! 276: ! 277: printf (";\n"); ! 278: } ! 279: ! 280: char * ! 281: xmalloc (size) ! 282: unsigned size; ! 283: { ! 284: register char *val = (char *) malloc (size); ! 285: ! 286: if (val == 0) ! 287: fatal ("virtual memory exhausted"); ! 288: ! 289: return val; ! 290: } ! 291: ! 292: char * ! 293: xrealloc (ptr, size) ! 294: char *ptr; ! 295: unsigned size; ! 296: { ! 297: char *result = (char *) realloc (ptr, size); ! 298: if (!result) ! 299: fatal ("virtual memory exhausted"); ! 300: return result; ! 301: } ! 302: ! 303: static void ! 304: fatal (s, a1, a2) ! 305: char *s; ! 306: { ! 307: fprintf (stderr, "genopinit: "); ! 308: fprintf (stderr, s, a1, a2); ! 309: fprintf (stderr, "\n"); ! 310: exit (FATAL_EXIT_CODE); ! 311: } ! 312: ! 313: /* More 'friendly' abort that prints the line and file. ! 314: config.h can #define abort fancy_abort if you like that sort of thing. */ ! 315: ! 316: void ! 317: fancy_abort () ! 318: { ! 319: fatal ("Internal gcc abort."); ! 320: } ! 321: ! 322: int ! 323: main (argc, argv) ! 324: int argc; ! 325: char **argv; ! 326: { ! 327: rtx desc; ! 328: rtx dummy; ! 329: rtx *insn_ptr; ! 330: FILE *infile; ! 331: register int c; ! 332: ! 333: obstack_init (rtl_obstack); ! 334: ! 335: if (argc <= 1) ! 336: fatal ("No input file name."); ! 337: ! 338: infile = fopen (argv[1], "r"); ! 339: if (infile == 0) ! 340: { ! 341: perror (argv[1]); ! 342: exit (FATAL_EXIT_CODE); ! 343: } ! 344: ! 345: init_rtl (); ! 346: ! 347: printf ("/* Generated automatically by the program `genopinit'\n\ ! 348: from the machine description file `md'. */\n\n"); ! 349: ! 350: printf ("#include \"config.h\"\n"); ! 351: printf ("#include \"rtl.h\"\n"); ! 352: printf ("#include \"flags.h\"\n"); ! 353: printf ("#include \"insn-flags.h\"\n"); ! 354: printf ("#include \"insn-codes.h\"\n"); ! 355: printf ("#include \"insn-config.h\"\n"); ! 356: printf ("#include \"recog.h\"\n"); ! 357: printf ("#include \"expr.h\"\n"); ! 358: printf ("#include \"reload.h\"\n\n"); ! 359: ! 360: printf ("void\ninit_all_optabs ()\n{\n"); ! 361: ! 362: /* Read the machine description. */ ! 363: ! 364: while (1) ! 365: { ! 366: c = read_skip_spaces (infile); ! 367: if (c == EOF) ! 368: break; ! 369: ungetc (c, infile); ! 370: ! 371: desc = read_rtx (infile); ! 372: if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND) ! 373: gen_insn (desc); ! 374: } ! 375: ! 376: printf ("}\n"); ! 377: ! 378: fflush (stdout); ! 379: exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); ! 380: /* NOTREACHED */ ! 381: return 0; ! 382: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.