|
|
1.1 ! root 1: /* Generate code from machine description to emit insns as rtl. ! 2: Copyright (C) 1987,1988 Free Software Foundation, Inc. ! 3: ! 4: This file is part of GNU CC. ! 5: ! 6: GNU CC is distributed in the hope that it will be useful, ! 7: but WITHOUT ANY WARRANTY. No author or distributor ! 8: accepts responsibility to anyone for the consequences of using it ! 9: or for whether it serves any particular purpose or works at all, ! 10: unless he says so in writing. Refer to the GNU CC General Public ! 11: License for full details. ! 12: ! 13: Everyone is granted permission to copy, modify and redistribute ! 14: GNU CC, but only under the conditions described in the ! 15: GNU CC General Public License. A copy of this license is ! 16: supposed to have been given to you along with GNU CC so you ! 17: can know your rights and responsibilities. It should be in a ! 18: file named COPYING. Among other things, the copyright notice ! 19: and this notice must be preserved on all copies. */ ! 20: ! 21: ! 22: /* This program is used to produce insn-recog.c, which contains ! 23: a function called `recog' plus its subroutines. ! 24: These functions contain a decision tree ! 25: that recognizes whether an rtx, the argument given to recog, ! 26: is a valid instruction. ! 27: ! 28: recog returns -1 if the rtx is not valid. ! 29: If the rtx is valid, recog returns a nonnegative number ! 30: which is the insn code number for the pattern that matched. ! 31: This is the same as the order in the machine description of the ! 32: entry that matched. This number can be used as an index into ! 33: insn_templates and insn_n_operands (found in insn-output.c) ! 34: or as an argument to output_insn_hairy (also in insn-output.c). */ ! 35: ! 36: #include <stdio.h> ! 37: #include "config.h" ! 38: #include "rtl.h" ! 39: #include "obstack.h" ! 40: ! 41: struct obstack obstack; ! 42: struct obstack *rtl_obstack = &obstack; ! 43: ! 44: #define obstack_chunk_alloc xmalloc ! 45: #define obstack_chunk_free free ! 46: extern int xmalloc (); ! 47: extern void free (); ! 48: ! 49: /* Data structure for decision tree for recognizing ! 50: legitimate instructions. */ ! 51: ! 52: struct decision ! 53: { ! 54: int number; ! 55: char *position; ! 56: RTX_CODE code; ! 57: char *exact; ! 58: enum machine_mode mode; ! 59: char *tests; ! 60: int insn_code_number; ! 61: struct decision *next; ! 62: struct decision *success; ! 63: int opno; ! 64: int dupno; ! 65: int dupcount; ! 66: int test_elt_zero_int; ! 67: int elt_zero_int; ! 68: int test_elt_one_int; ! 69: int elt_one_int; ! 70: int ignmode; ! 71: struct decision *afterward; ! 72: int label_needed; ! 73: char *c_test; ! 74: char *reg_class; ! 75: char enforce_mode; ! 76: int veclen; ! 77: int subroutine_number; ! 78: }; ! 79: ! 80: #define SUBROUTINE_THRESHOLD 50 ! 81: ! 82: int next_subroutine_number; ! 83: ! 84: /* ! 85: recognize (top) ! 86: { ! 87: staten: ! 88: x = XVECEXP (top, 0, 3); ! 89: if (test_code (GET_CODE (x)) ! 90: && test_mode (MODE (x)) ! 91: && whatever_else) ! 92: goto statep; ! 93: else if (next one...) ! 94: goto statem: ! 95: goto stater; ! 96: ! 97: statep: ! 98: actions...; ! 99: return 1; ! 100: ! 101: statem: ! 102: x = stack[depth--]; ! 103: more tests...; ! 104: ! 105: stateq: ! 106: stack[++depth] = x; ! 107: x = XEXP (stack[depth], 0); ! 108: more tests...; ! 109: ! 110: stater: ! 111: x = XEXP (stack[depth], 1); ! 112: } ! 113: ! 114: */ ! 115: ! 116: int next_number; ! 117: ! 118: int next_insn_code; ! 119: ! 120: /* Number of MATCH_DUP's seen so far in this instruction. */ ! 121: int dupcount; ! 122: ! 123: struct decision *add_to_sequence (); ! 124: struct decision *try_merge_2 (); ! 125: void write_subroutine (); ! 126: void print_code (); ! 127: void clear_codes (); ! 128: void clear_modes (); ! 129: void change_state (); ! 130: void write_tree (); ! 131: char *copystr (); ! 132: char *concat (); ! 133: void fatal (); ! 134: void mybzero (); ! 135: ! 136: struct decision *first; ! 137: ! 138: /* Construct and return a sequence of decisions ! 139: that will recognize INSN. */ ! 140: ! 141: struct decision * ! 142: make_insn_sequence (insn) ! 143: rtx insn; ! 144: { ! 145: rtx x; ! 146: char *c_test = XSTR (insn, 2); ! 147: struct decision *last; ! 148: ! 149: dupcount = 0; ! 150: ! 151: if (XVECLEN (insn, 1) == 1) ! 152: x = XVECEXP (insn, 1, 0); ! 153: else ! 154: { ! 155: x = rtx_alloc (PARALLEL); ! 156: XVEC (x, 0) = XVEC (insn, 1); ! 157: PUT_MODE (x, VOIDmode); ! 158: } ! 159: ! 160: last = add_to_sequence (x, 0, ""); ! 161: ! 162: if (c_test[0]) ! 163: last->c_test = c_test; ! 164: last->insn_code_number = next_insn_code++; ! 165: ! 166: return first; ! 167: } ! 168: ! 169: struct decision * ! 170: add_to_sequence (pattern, last, position) ! 171: rtx pattern; ! 172: struct decision *last; ! 173: char *position; ! 174: { ! 175: register RTX_CODE code; ! 176: register struct decision *new ! 177: = (struct decision *) xmalloc (sizeof (struct decision)); ! 178: struct decision *this; ! 179: char *newpos; ! 180: register char *fmt; ! 181: register int i; ! 182: int depth; ! 183: int len; ! 184: ! 185: new->number = next_number++; ! 186: new->position = copystr (position); ! 187: new->exact = 0; ! 188: new->next = 0; ! 189: new->success = 0; ! 190: new->insn_code_number = -1; ! 191: new->tests = 0; ! 192: new->opno = -1; ! 193: new->dupno = -1; ! 194: new->dupcount = -1; ! 195: new->test_elt_zero_int = 0; ! 196: new->test_elt_one_int = 0; ! 197: new->elt_zero_int = 0; ! 198: new->elt_one_int = 0; ! 199: new->enforce_mode = 0; ! 200: new->ignmode = 0; ! 201: new->afterward = 0; ! 202: new->label_needed = 0; ! 203: new->c_test = 0; ! 204: new->reg_class = 0; ! 205: new->veclen = 0; ! 206: new->subroutine_number = 0; ! 207: ! 208: this = new; ! 209: ! 210: if (last == 0) ! 211: first = new; ! 212: else ! 213: last->success = new; ! 214: ! 215: depth = strlen (position); ! 216: newpos = (char *) alloca (depth + 2); ! 217: strcpy (newpos, position); ! 218: newpos[depth + 1] = 0; ! 219: ! 220: restart: ! 221: ! 222: if (pattern == 0) ! 223: { ! 224: new->exact = "0"; ! 225: new->code = UNKNOWN; ! 226: new->mode = VOIDmode; ! 227: return new; ! 228: } ! 229: ! 230: switch (GET_MODE (pattern)) ! 231: { ! 232: case 0: ! 233: new->mode = VOIDmode; ! 234: break; ! 235: ! 236: default: ! 237: new->mode = GET_MODE (pattern); ! 238: break; ! 239: } ! 240: ! 241: new->code = code = GET_CODE (pattern);; ! 242: ! 243: switch (code) ! 244: { ! 245: case MATCH_OPERAND: ! 246: new->opno = XINT (pattern, 0); ! 247: new->code = UNKNOWN; ! 248: new->tests = XSTR (pattern, 1); ! 249: if (*new->tests == 0) ! 250: new->tests = 0; ! 251: new->reg_class = XSTR (pattern, 2); ! 252: if (*new->reg_class == 0) ! 253: new->reg_class = 0; ! 254: return new; ! 255: ! 256: case MATCH_DUP: ! 257: new->dupno = XINT (pattern, 0); ! 258: new->dupcount = dupcount++; ! 259: new->code = UNKNOWN; ! 260: return new; ! 261: ! 262: case ADDRESS: ! 263: pattern = XEXP (pattern, 0); ! 264: goto restart; ! 265: ! 266: case PC: ! 267: new->exact = "pc_rtx"; ! 268: return new; ! 269: ! 270: case CC0: ! 271: new->exact = "cc0_rtx"; ! 272: return new; ! 273: ! 274: case CONST_INT: ! 275: if (INTVAL (pattern) == 0) ! 276: { ! 277: new->exact = "const0_rtx"; ! 278: return new; ! 279: } ! 280: if (INTVAL (pattern) == 1) ! 281: { ! 282: new->exact = "const1_rtx"; ! 283: return new; ! 284: } ! 285: break; ! 286: ! 287: case SET: ! 288: newpos[depth] = '0'; ! 289: new = add_to_sequence (SET_DEST (pattern), new, newpos); ! 290: this->success->enforce_mode = 1; ! 291: newpos[depth] = '1'; ! 292: new = add_to_sequence (SET_SRC (pattern), new, newpos); ! 293: return new; ! 294: ! 295: case STRICT_LOW_PART: ! 296: newpos[depth] = '0'; ! 297: new = add_to_sequence (XEXP (pattern, 0), new, newpos); ! 298: this->success->enforce_mode = 1; ! 299: return new; ! 300: ! 301: case SUBREG: ! 302: this->test_elt_one_int = 1; ! 303: this->elt_one_int = XINT (pattern, 1); ! 304: newpos[depth] = '0'; ! 305: new = add_to_sequence (XEXP (pattern, 0), new, newpos); ! 306: this->success->enforce_mode = 1; ! 307: return new; ! 308: ! 309: case ZERO_EXTRACT: ! 310: case SIGN_EXTRACT: ! 311: newpos[depth] = '0'; ! 312: new = add_to_sequence (XEXP (pattern, 0), new, newpos); ! 313: this->success->enforce_mode = 1; ! 314: newpos[depth] = '1'; ! 315: new = add_to_sequence (XEXP (pattern, 1), new, newpos); ! 316: newpos[depth] = '2'; ! 317: new = add_to_sequence (XEXP (pattern, 2), new, newpos); ! 318: return new; ! 319: } ! 320: ! 321: fmt = GET_RTX_FORMAT (code); ! 322: len = GET_RTX_LENGTH (code); ! 323: for (i = 0; i < len; i++) ! 324: { ! 325: newpos[depth] = '0' + i; ! 326: if (fmt[i] == 'e' || fmt[i] == 'u') ! 327: new = add_to_sequence (XEXP (pattern, i), new, newpos); ! 328: else if (fmt[i] == 'i' && i == 0) ! 329: { ! 330: this->test_elt_zero_int = 1; ! 331: this->elt_zero_int = XINT (pattern, i); ! 332: } ! 333: else if (fmt[i] == 'i' && i == 1) ! 334: { ! 335: this->test_elt_one_int = 1; ! 336: this->elt_one_int = XINT (pattern, i); ! 337: } ! 338: else if (fmt[i] == 'E') ! 339: { ! 340: register int j; ! 341: /* We do not handle a vector appearing as other than ! 342: the first item, just because nothing uses them ! 343: and by handling only the special case ! 344: we can use one element in newpos for either ! 345: the item number of a subexpression ! 346: or the element number in a vector. */ ! 347: if (i != 0) ! 348: abort (); ! 349: this->veclen = XVECLEN (pattern, i); ! 350: for (j = 0; j < XVECLEN (pattern, i); j++) ! 351: { ! 352: newpos[depth] = 'a' + j; ! 353: new = add_to_sequence (XVECEXP (pattern, i, j), ! 354: new, newpos); ! 355: } ! 356: } ! 357: else if (fmt[i] != '0') ! 358: abort (); ! 359: } ! 360: return new; ! 361: } ! 362: ! 363: /* Merge two decision trees OLD and ADD, ! 364: modifying OLD destructively, ! 365: and return the merged tree. */ ! 366: ! 367: struct decision * ! 368: merge_trees (old, add) ! 369: register struct decision *old, *add; ! 370: { ! 371: while (add) ! 372: { ! 373: register struct decision *next = add->next; ! 374: add->next = 0; ! 375: if (!try_merge_1 (old, add)) ! 376: old = try_merge_2 (old, add); ! 377: add = next; ! 378: } ! 379: return old; ! 380: } ! 381: ! 382: /* Merge ADD into the next-chain starting with OLD ! 383: only if it overlaps a condition already tested in OLD. ! 384: Returns 1 if successful (OLD is modified), ! 385: 0 if nothing has been done. */ ! 386: ! 387: int ! 388: try_merge_1 (old, add) ! 389: register struct decision *old, *add; ! 390: { ! 391: while (old) ! 392: { ! 393: if ((old->position == add->position ! 394: || (old->position && add->position ! 395: && !strcmp (old->position, add->position))) ! 396: && (old->tests == add->tests ! 397: || (old->tests && add->tests && !strcmp (old->tests, add->tests))) ! 398: && (old->c_test == add->c_test ! 399: || (old->c_test && add->c_test && !strcmp (old->c_test, add->c_test))) ! 400: && old->test_elt_zero_int == add->test_elt_zero_int ! 401: && old->elt_zero_int == add->elt_zero_int ! 402: && old->test_elt_one_int == add->test_elt_one_int ! 403: && old->elt_one_int == add->elt_one_int ! 404: && old->veclen == add->veclen ! 405: && old->dupno == add->dupno ! 406: && old->opno == add->opno ! 407: && (old->tests == 0 ! 408: || (add->enforce_mode ? no_same_mode (old) : old->next == 0)) ! 409: && old->code == add->code ! 410: && old->mode == add->mode) ! 411: { ! 412: old->success = merge_trees (old->success, add->success); ! 413: if (old->insn_code_number >= 0 && add->insn_code_number >= 0) ! 414: fatal ("Two actions at one point in tree."); ! 415: if (old->insn_code_number == -1) ! 416: old->insn_code_number = add->insn_code_number; ! 417: return 1; ! 418: } ! 419: old = old->next; ! 420: } ! 421: return 0; ! 422: } ! 423: ! 424: /* Merge ADD into the next-chain that starts with OLD, ! 425: preferably after something that tests the same place ! 426: that ADD does. ! 427: The next-chain of ADD itself is ignored, and it is set ! 428: up for entering ADD into the new chain. ! 429: Returns the new chain. */ ! 430: ! 431: struct decision * ! 432: try_merge_2 (old, add) ! 433: struct decision *old, *add; ! 434: { ! 435: register struct decision *p; ! 436: struct decision *last = 0; ! 437: struct decision *last_same_place = 0; ! 438: ! 439: /* Put this in after the others that test the same place, ! 440: if there are any. If not, find the last chain element ! 441: and insert there. ! 442: ! 443: One modification: if this one is NOT a MATCH_OPERAND, ! 444: put it before any MATCH_OPERANDS that test the same place. ! 445: ! 446: Another: if enforce_mode (i.e. this is first operand of a SET), ! 447: put this after the last thing that tests the same place for ! 448: the same mode. */ ! 449: ! 450: int operand = 0 != add->tests; ! 451: ! 452: for (p = old; p; p = p->next) ! 453: { ! 454: if (p->position == add->position ! 455: || (p->position && add->position ! 456: && !strcmp (p->position, add->position))) ! 457: { ! 458: last_same_place = p; ! 459: /* If enforce_mode, segregate the modes in numerical order. */ ! 460: if (p->enforce_mode && (int) add->mode < (int) p->mode) ! 461: break; ! 462: /* Keep explicit decompositions before those that test predicates. ! 463: If enforce_mode, do this separately within each mode. */ ! 464: if (! p->enforce_mode || p->mode == add->mode) ! 465: if (!operand && p->tests) ! 466: break; ! 467: } ! 468: /* If this is past the end of the decisions at the same place as ADD, ! 469: stop looking now; add ADD before here. */ ! 470: else if (last_same_place) ! 471: break; ! 472: last = p; ! 473: } ! 474: ! 475: /* Insert before P, which means after LAST. */ ! 476: ! 477: if (last) ! 478: { ! 479: add->next = last->next; ! 480: last->next = add; ! 481: return old; ! 482: } ! 483: ! 484: add->next = old; ! 485: return add; ! 486: } ! 487: ! 488: int ! 489: no_same_mode (node) ! 490: struct decision *node; ! 491: { ! 492: register struct decision *p; ! 493: register enum machine_mode mode = node->mode; ! 494: ! 495: for (p = node->next; p; p = p->next) ! 496: if (p->mode == mode) ! 497: return 0; ! 498: ! 499: return 1; ! 500: } ! 501: ! 502: /* Count the number of subnodes of node NODE, assumed to be the start ! 503: of a next-chain. If the number is high enough, make NODE start ! 504: a separate subroutine in the C code that is generated. */ ! 505: ! 506: int ! 507: break_out_subroutines (node) ! 508: struct decision *node; ! 509: { ! 510: int size = 0; ! 511: struct decision *sub; ! 512: for (sub = node; sub; sub = sub->next) ! 513: size += 1 + break_out_subroutines (sub->success); ! 514: if (size > SUBROUTINE_THRESHOLD) ! 515: { ! 516: node->subroutine_number = ++next_subroutine_number; ! 517: write_subroutine (node); ! 518: size = 1; ! 519: } ! 520: return size; ! 521: } ! 522: ! 523: void ! 524: write_subroutine (tree) ! 525: struct decision *tree; ! 526: { ! 527: printf ("int\nrecog_%d (x0, insn)\n register rtx x0;\n rtx insn;\n{\n", ! 528: tree->subroutine_number); ! 529: printf (" register rtx x1, x2, x3, x4, x5;\n rtx x6, x7, x8, x9, x10, x11;\n"); ! 530: printf (" int tem;\n"); ! 531: write_tree (tree, "", 0, "", 1); ! 532: printf (" ret0: return -1;\n}\n\n"); ! 533: } ! 534: ! 535: /* Write out C code to perform the decisions in the tree. */ ! 536: ! 537: void ! 538: write_tree (tree, prevpos, afterward, afterpos, initial) ! 539: struct decision *tree; ! 540: char *prevpos; ! 541: int afterward; ! 542: char *afterpos; ! 543: int initial; ! 544: { ! 545: register struct decision *p, *p1; ! 546: char *pos; ! 547: register int depth; ! 548: int ignmode; ! 549: enum { NO_SWITCH, CODE_SWITCH, MODE_SWITCH } in_switch = NO_SWITCH; ! 550: char modemap[NUM_MACHINE_MODES]; ! 551: char codemap[NUM_RTX_CODE]; ! 552: ! 553: pos = prevpos; ! 554: ! 555: if (tree->subroutine_number > 0 && ! initial) ! 556: { ! 557: printf (" L%d:\n", tree->number); ! 558: ! 559: if (afterward) ! 560: { ! 561: printf (" tem = recog_%d (x0, insn);\n", ! 562: tree->subroutine_number); ! 563: printf (" if (tem >= 0) return tem;\n"); ! 564: change_state (pos, afterpos); ! 565: printf (" goto L%d;\n", afterward); ! 566: } ! 567: else ! 568: printf (" return recog_%d (x0, insn);\n", ! 569: tree->subroutine_number); ! 570: return; ! 571: } ! 572: ! 573: tree->label_needed = 1; ! 574: for (p = tree; p; p = p->next) ! 575: { ! 576: /* Find the next alternative to p ! 577: that might be true when p is true. ! 578: Test that one next if p's successors fail. ! 579: Note that when the `tests' field is nonzero ! 580: it is up to the specified test-function to compare machine modes ! 581: and some (such as general_operand) don't always do so. ! 582: But when inside a switch-on-modes we ignore this and ! 583: consider all modes mutually exclusive. */ ! 584: for (p1 = p->next; p1; p1 = p1->next) ! 585: if (((p->code == UNKNOWN || p1->code == UNKNOWN || p->code == p1->code) ! 586: && (p->mode == VOIDmode || p1->mode == VOIDmode ! 587: || p->mode == p1->mode ! 588: || (in_switch != MODE_SWITCH && (p->tests || p1->tests)))) ! 589: || strcmp (p1->position, p->position)) ! 590: break; ! 591: p->afterward = p1; ! 592: if (p1) p1->label_needed = 1; ! 593: ! 594: if (in_switch == MODE_SWITCH ! 595: && (p->mode == VOIDmode || (! p->enforce_mode && p->tests != 0))) ! 596: { ! 597: in_switch = NO_SWITCH; ! 598: printf (" }\n"); ! 599: } ! 600: if (in_switch == CODE_SWITCH && p->code == UNKNOWN) ! 601: { ! 602: in_switch = NO_SWITCH; ! 603: printf (" }\n"); ! 604: } ! 605: ! 606: if (p->label_needed) ! 607: printf (" L%d:\n", p->number); ! 608: ! 609: if (p->success == 0 && p->insn_code_number < 0) ! 610: abort (); ! 611: ! 612: change_state (pos, p->position); ! 613: pos = p->position; ! 614: depth = strlen (pos); ! 615: ! 616: ignmode = p->ignmode || pos[depth - 1] == '*' || p->tests; ! 617: ! 618: if (in_switch == NO_SWITCH) ! 619: { ! 620: /* If p and its alternatives all want the same mode, ! 621: reject all others at once, first, then ignore the mode. */ ! 622: if (!ignmode && p->mode != VOIDmode && p->next && same_modes (p, p->mode)) ! 623: { ! 624: printf (" if (GET_MODE (x%d) != %smode)\n", ! 625: depth, GET_MODE_NAME (p->mode)); ! 626: if (afterward) ! 627: { ! 628: printf (" {\n "); ! 629: change_state (pos, afterpos); ! 630: printf (" goto L%d;\n }\n", afterward); ! 631: } ! 632: else ! 633: printf (" goto ret0;\n"); ! 634: clear_modes (p); ! 635: ignmode = 1; ! 636: } ! 637: ! 638: /* If p and its alternatives all want the same code, ! 639: reject all others at once, first, then ignore the code. */ ! 640: if (p->code != UNKNOWN && p->next && same_codes (p, p->code)) ! 641: { ! 642: printf (" if (GET_CODE (x%d) != ", depth); ! 643: print_code (p->code); ! 644: printf (")\n"); ! 645: if (afterward) ! 646: { ! 647: printf (" {"); ! 648: change_state (pos, afterpos); ! 649: printf (" goto L%d; }\n", afterward); ! 650: } ! 651: else ! 652: printf (" goto ret0;\n"); ! 653: clear_codes (p); ! 654: } ! 655: } ! 656: ! 657: /* If p and its alternatives all have different modes ! 658: and there are at least 4 of them, make a switch. */ ! 659: if (in_switch == NO_SWITCH && pos[depth-1] != '*') ! 660: { ! 661: register int i; ! 662: int lose = 0; ! 663: ! 664: mybzero (modemap, sizeof modemap); ! 665: for (p1 = p, i = 0; ! 666: (p1 && p1->mode != VOIDmode ! 667: && (p1->tests == 0 || p1->enforce_mode)); ! 668: p1 = p1->next, i++) ! 669: { ! 670: if (! p->enforce_mode && modemap[(int) p1->mode]) ! 671: { ! 672: lose = 1; ! 673: break; ! 674: } ! 675: modemap[(int) p1->mode] = 1; ! 676: } ! 677: if (!lose && i >= 4) ! 678: { ! 679: in_switch = MODE_SWITCH; ! 680: printf (" switch (GET_MODE (x%d))\n {\n", depth); ! 681: } ! 682: } ! 683: ! 684: if (in_switch == NO_SWITCH) ! 685: { ! 686: register int i; ! 687: mybzero (codemap, sizeof codemap); ! 688: for (p1 = p, i = 0; p1 && p1->code != UNKNOWN; p1 = p1->next, i++) ! 689: { ! 690: if (codemap[(int) p1->code]) ! 691: break; ! 692: codemap[(int) p1->code] = 1; ! 693: } ! 694: if ((p1 == 0 || p1->code == UNKNOWN) && i >= 4) ! 695: { ! 696: in_switch = CODE_SWITCH; ! 697: printf (" switch (GET_CODE (x%d))\n {\n", depth); ! 698: } ! 699: } ! 700: ! 701: if (in_switch == MODE_SWITCH) ! 702: { ! 703: if (modemap[(int) p->mode]) ! 704: { ! 705: printf (" case %smode:\n", GET_MODE_NAME (p->mode)); ! 706: modemap[(int) p->mode] = 0; ! 707: } ! 708: } ! 709: if (in_switch == CODE_SWITCH) ! 710: { ! 711: if (codemap[(int) p->code]) ! 712: { ! 713: printf (" case "); ! 714: print_code (p->code); ! 715: printf (":\n"); ! 716: codemap[(int) p->code] = 0; ! 717: } ! 718: } ! 719: ! 720: printf (" if ("); ! 721: if (p->exact || (p->code != UNKNOWN && in_switch != CODE_SWITCH)) ! 722: { ! 723: if (p->exact) ! 724: printf ("x%d == %s", depth, p->exact); ! 725: else ! 726: { ! 727: printf ("GET_CODE (x%d) == ", depth); ! 728: print_code (p->code); ! 729: } ! 730: printf (" && "); ! 731: } ! 732: if (p->mode && !ignmode && in_switch != MODE_SWITCH) ! 733: printf ("GET_MODE (x%d) == %smode && ", ! 734: depth, GET_MODE_NAME (p->mode)); ! 735: if (p->test_elt_zero_int) ! 736: printf ("XINT (x%d, 0) == %d && ", depth, p->elt_zero_int); ! 737: if (p->veclen) ! 738: printf ("XVECLEN (x%d, 0) == %d && ", depth, p->veclen); ! 739: if (p->test_elt_one_int) ! 740: printf ("XINT (x%d, 1) == %d && ", depth, p->elt_one_int); ! 741: if (p->dupno >= 0) ! 742: printf ("rtx_equal_p (x%d, recog_operand[%d]) && ", depth, p->dupno); ! 743: if (p->tests) ! 744: printf ("%s (x%d, %smode)", p->tests, depth, ! 745: GET_MODE_NAME (p->mode)); ! 746: else ! 747: printf ("1"); ! 748: ! 749: if (p->opno >= 0) ! 750: printf (")\n { recog_operand[%d] = x%d; ", ! 751: p->opno, depth); ! 752: else ! 753: printf (")\n "); ! 754: ! 755: if (p->c_test) ! 756: printf ("if (%s) ", p->c_test); ! 757: ! 758: if (p->insn_code_number >= 0) ! 759: printf ("return %d;", p->insn_code_number); ! 760: else ! 761: printf ("goto L%d;", p->success->number); ! 762: ! 763: if (p->opno >= 0) ! 764: printf (" }\n"); ! 765: else ! 766: printf ("\n"); ! 767: ! 768: /* Now, if inside a switch, branch to next switch member ! 769: that might also need to be tested if this one fails. */ ! 770: ! 771: if (in_switch == CODE_SWITCH) ! 772: { ! 773: /* Find the next alternative to p ! 774: that might be applicable if p was applicable. */ ! 775: for (p1 = p->next; p1; p1 = p1->next) ! 776: if (p1->code == UNKNOWN || p->code == p1->code) ! 777: break; ! 778: if (p1 == 0 || p1->code == UNKNOWN) ! 779: printf (" break;\n"); ! 780: else if (p1 != p->next) ! 781: { ! 782: printf (" goto L%d;\n", p1->number); ! 783: p1->label_needed = 1; ! 784: } ! 785: } ! 786: ! 787: if (in_switch == MODE_SWITCH) ! 788: { ! 789: /* Find the next alternative to p ! 790: that might be applicable if p was applicable. */ ! 791: for (p1 = p->next; p1; p1 = p1->next) ! 792: if (p1->mode == VOIDmode || p->mode == p1->mode) ! 793: break; ! 794: if (p1 == 0 || p1->mode == VOIDmode) ! 795: printf (" break;\n"); ! 796: else if (p1 != p->next) ! 797: { ! 798: printf (" goto L%d;\n", p1->number); ! 799: p1->label_needed = 1; ! 800: } ! 801: } ! 802: } ! 803: ! 804: if (in_switch != NO_SWITCH) ! 805: printf (" }\n"); ! 806: ! 807: if (afterward) ! 808: { ! 809: change_state (pos, afterpos); ! 810: printf (" goto L%d;\n", afterward); ! 811: } ! 812: else ! 813: printf (" goto ret0;\n"); ! 814: ! 815: for (p = tree; p; p = p->next) ! 816: if (p->success) ! 817: { ! 818: { ! 819: pos = p->position; ! 820: write_tree (p->success, pos, ! 821: p->afterward ? p->afterward->number : afterward, ! 822: p->afterward ? pos : afterpos, ! 823: 0); ! 824: } ! 825: } ! 826: } ! 827: ! 828: void ! 829: print_code (code) ! 830: RTX_CODE code; ! 831: { ! 832: register char *p1; ! 833: for (p1 = GET_RTX_NAME (code); *p1; p1++) ! 834: { ! 835: if (*p1 >= 'a' && *p1 <= 'z') ! 836: putchar (*p1 + 'A' - 'a'); ! 837: else ! 838: putchar (*p1); ! 839: } ! 840: } ! 841: ! 842: int ! 843: same_codes (p, code) ! 844: register struct decision *p; ! 845: register RTX_CODE code; ! 846: { ! 847: for (; p; p = p->next) ! 848: if (p->code != code) ! 849: return 0; ! 850: ! 851: return 1; ! 852: } ! 853: ! 854: void ! 855: clear_codes (p) ! 856: register struct decision *p; ! 857: { ! 858: for (; p; p = p->next) ! 859: p->code = UNKNOWN; ! 860: } ! 861: ! 862: int ! 863: same_modes (p, mode) ! 864: register struct decision *p; ! 865: register enum machine_mode mode; ! 866: { ! 867: for (; p; p = p->next) ! 868: if (p->mode != mode || p->tests) ! 869: return 0; ! 870: ! 871: return 1; ! 872: } ! 873: ! 874: void ! 875: clear_modes (p) ! 876: register struct decision *p; ! 877: { ! 878: for (; p; p = p->next) ! 879: p->ignmode = 1; ! 880: } ! 881: ! 882: void ! 883: change_state (oldpos, newpos) ! 884: char *oldpos; ! 885: char *newpos; ! 886: { ! 887: int odepth = strlen (oldpos); ! 888: int depth = odepth; ! 889: int ndepth = strlen (newpos); ! 890: ! 891: /* Pop up as many levels as necessary. */ ! 892: ! 893: while (strncmp (oldpos, newpos, depth)) ! 894: --depth; ! 895: ! 896: /* Go down to desired level. */ ! 897: ! 898: while (depth < ndepth) ! 899: { ! 900: if (newpos[depth] == '*') ! 901: printf (" x%d = recog_addr_dummy;\n XEXP (x%d, 0) = x%d;\n", ! 902: depth + 1, depth + 1, depth); ! 903: else if (newpos[depth] >= 'a' && newpos[depth] <= 'z') ! 904: printf (" x%d = XVECEXP (x%d, 0, %c);\n", ! 905: depth + 1, depth, '0' + newpos[depth] - 'a'); ! 906: else ! 907: printf (" x%d = XEXP (x%d, %c);\n", ! 908: depth + 1, depth, newpos[depth]); ! 909: ++depth; ! 910: } ! 911: } ! 912: ! 913: char * ! 914: copystr (s1) ! 915: char *s1; ! 916: { ! 917: register char *tem; ! 918: ! 919: if (s1 == 0) ! 920: return 0; ! 921: ! 922: tem = (char *) xmalloc (strlen (s1) + 1); ! 923: strcpy (tem, s1); ! 924: ! 925: return tem; ! 926: } ! 927: ! 928: void ! 929: mybzero (b, length) ! 930: register char *b; ! 931: register int length; ! 932: { ! 933: while (length-- > 0) ! 934: *b++ = 0; ! 935: } ! 936: ! 937: char * ! 938: concat (s1, s2) ! 939: char *s1, *s2; ! 940: { ! 941: register char *tem; ! 942: ! 943: if (s1 == 0) ! 944: return s2; ! 945: if (s2 == 0) ! 946: return s1; ! 947: ! 948: tem = (char *) xmalloc (strlen (s1) + strlen (s2) + 2); ! 949: strcpy (tem, s1); ! 950: strcat (tem, " "); ! 951: strcat (tem, s2); ! 952: ! 953: return tem; ! 954: } ! 955: ! 956: int ! 957: xrealloc (ptr, size) ! 958: char *ptr; ! 959: int size; ! 960: { ! 961: int result = realloc (ptr, size); ! 962: if (!result) ! 963: fatal ("virtual memory exhausted"); ! 964: return result; ! 965: } ! 966: ! 967: int ! 968: xmalloc (size) ! 969: { ! 970: register int val = malloc (size); ! 971: ! 972: if (val == 0) ! 973: fatal ("virtual memory exhausted"); ! 974: return val; ! 975: } ! 976: ! 977: void ! 978: fatal (s, a1, a2) ! 979: { ! 980: fprintf (stderr, "genrecog: "); ! 981: fprintf (stderr, s, a1, a2); ! 982: fprintf (stderr, "\n"); ! 983: fprintf (stderr, "after %d instruction definitions\n", ! 984: next_insn_code); ! 985: exit (FATAL_EXIT_CODE); ! 986: } ! 987: ! 988: int ! 989: main (argc, argv) ! 990: int argc; ! 991: char **argv; ! 992: { ! 993: rtx desc; ! 994: struct decision *tree = 0; ! 995: FILE *infile; ! 996: extern rtx read_rtx (); ! 997: register int c; ! 998: ! 999: obstack_init (rtl_obstack); ! 1000: ! 1001: if (argc <= 1) ! 1002: fatal ("No input file name."); ! 1003: ! 1004: infile = fopen (argv[1], "r"); ! 1005: if (infile == 0) ! 1006: { ! 1007: perror (argv[1]); ! 1008: exit (FATAL_EXIT_CODE); ! 1009: } ! 1010: ! 1011: init_rtl (); ! 1012: next_insn_code = 0; ! 1013: ! 1014: printf ("/* Generated automatically by the program `genrecog'\n\ ! 1015: from the machine description file `md'. */\n\n"); ! 1016: ! 1017: /* Read the machine description. */ ! 1018: ! 1019: while (1) ! 1020: { ! 1021: c = read_skip_spaces (infile); ! 1022: if (c == EOF) ! 1023: break; ! 1024: ungetc (c, infile); ! 1025: ! 1026: desc = read_rtx (infile); ! 1027: if (GET_CODE (desc) == DEFINE_INSN) ! 1028: tree = merge_trees (tree, make_insn_sequence (desc)); ! 1029: if (GET_CODE (desc) == DEFINE_PEEPHOLE ! 1030: || GET_CODE (desc) == DEFINE_EXPAND) ! 1031: next_insn_code++; ! 1032: } ! 1033: ! 1034: printf ("#include \"config.h\"\n"); ! 1035: printf ("#include \"rtl.h\"\n"); ! 1036: printf ("#include \"insn-config.h\"\n"); ! 1037: printf ("#include \"recog.h\"\n"); ! 1038: printf ("\n\ ! 1039: /* `recog' contains a decision tree\n\ ! 1040: that recognizes whether the rtx X0 is a valid instruction.\n\ ! 1041: \n\ ! 1042: recog returns -1 if the rtx is not valid.\n\ ! 1043: If the rtx is valid, recog returns a nonnegative number\n\ ! 1044: which is the insn code number for the pattern that matched.\n"); ! 1045: printf (" This is the same as the order in the machine description of\n\ ! 1046: the entry that matched. This number can be used as an index into\n\ ! 1047: insn_templates and insn_n_operands (found in insn-output.c)\n\ ! 1048: or as an argument to output_insn_hairy (also in insn-output.c). */\n\n"); ! 1049: ! 1050: printf ("rtx recog_operand[MAX_RECOG_OPERANDS];\n\n"); ! 1051: printf ("rtx *recog_operand_loc[MAX_RECOG_OPERANDS];\n\n"); ! 1052: printf ("rtx *recog_dup_loc[MAX_DUP_OPERANDS];\n\n"); ! 1053: printf ("char recog_dup_num[MAX_DUP_OPERANDS];\n\n"); ! 1054: printf ("extern rtx recog_addr_dummy;\n\n"); ! 1055: printf ("#define operands recog_operand\n\n"); ! 1056: ! 1057: break_out_subroutines (tree); ! 1058: ! 1059: printf ("int\nrecog (x0, insn)\n register rtx x0;\n rtx insn;\n{\n"); ! 1060: printf (" register rtx x1, x2, x3, x4, x5;\n rtx x6, x7, x8, x9, x10, x11;\n"); ! 1061: printf (" int tem;\n"); ! 1062: ! 1063: write_tree (tree, "", 0, "", 1); ! 1064: printf (" ret0: return -1;\n}\n"); ! 1065: ! 1066: fflush (stdout); ! 1067: exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); ! 1068: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.