|
|
1.1 ! root 1: /* Subroutines used by or related to instruction recognition. ! 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: #include "config.h" ! 23: #include "rtl.h" ! 24: #include <stdio.h> ! 25: #include "insn-config.h" ! 26: #include "recog.h" ! 27: #include "regs.h" ! 28: #include "hard-reg-set.h" ! 29: ! 30: static int inequality_comparisons_p (); ! 31: ! 32: /* Nonzero means allow operands to be volatile. ! 33: This is 1 if you use recog_memoized, 0 if you don't. ! 34: init_recog and recog_memoized are responsible for setting it. ! 35: This way of handling it is not really clean and will be change later. */ ! 36: ! 37: int volatile_ok; ! 38: ! 39: rtx recog_addr_dummy; ! 40: ! 41: /* On return from `constrain_operands', indicate which alternative ! 42: was satisfied. */ ! 43: ! 44: int which_alternative; ! 45: ! 46: /* Initialize data used by the function `recog'. ! 47: This must be called once in the compilation of a function ! 48: before any insn recognition may be done in the function. */ ! 49: ! 50: void ! 51: init_recog () ! 52: { ! 53: volatile_ok = 0; ! 54: recog_addr_dummy = gen_rtx (MEM, VOIDmode, 0); ! 55: } ! 56: ! 57: /* Try recognizing the instruction INSN, ! 58: and return the code number that results. ! 59: Remeber the code so that repeated calls do not ! 60: need to spend the time for actual rerecognition. ! 61: ! 62: This function is the normal interface to instruction recognition. ! 63: The automatically-generated function `recog' is normally called ! 64: through this one. (The only exception is in combine.c.) */ ! 65: ! 66: int ! 67: recog_memoized (insn) ! 68: rtx insn; ! 69: { ! 70: volatile_ok = 1; ! 71: if (INSN_CODE (insn) < 0) ! 72: INSN_CODE (insn) = recog (PATTERN (insn), insn); ! 73: return INSN_CODE (insn); ! 74: } ! 75: ! 76: /* Return 1 if the insn following INSN does not contain ! 77: any ordered tests applied to the condition codes. ! 78: EQ and NE tests do not count. */ ! 79: ! 80: int ! 81: next_insn_tests_no_inequality (insn) ! 82: rtx insn; ! 83: { ! 84: register rtx next = NEXT_INSN (insn); ! 85: ! 86: return ((GET_CODE (next) == JUMP_INSN ! 87: || GET_CODE (next) == INSN ! 88: || GET_CODE (next) == CALL_INSN) ! 89: && ! inequality_comparisons_p (PATTERN (next))); ! 90: } ! 91: ! 92: static int ! 93: inequality_comparisons_p (x) ! 94: rtx x; ! 95: { ! 96: register char *fmt; ! 97: register int len, i; ! 98: register enum rtx_code code = GET_CODE (x); ! 99: ! 100: switch (code) ! 101: { ! 102: case REG: ! 103: case PC: ! 104: case CC0: ! 105: case CONST_INT: ! 106: case CONST_DOUBLE: ! 107: case CONST: ! 108: case LABEL_REF: ! 109: case SYMBOL_REF: ! 110: return 0; ! 111: ! 112: case LT: ! 113: case LTU: ! 114: case GT: ! 115: case GTU: ! 116: case LE: ! 117: case LEU: ! 118: case GE: ! 119: case GEU: ! 120: return (XEXP (x, 0) == cc0_rtx || XEXP (x, 1) == cc0_rtx); ! 121: } ! 122: ! 123: len = GET_RTX_LENGTH (code); ! 124: fmt = GET_RTX_FORMAT (code); ! 125: ! 126: for (i = 0; i < len; i++) ! 127: { ! 128: if (fmt[i] == 'e') ! 129: { ! 130: if (inequality_comparisons_p (XEXP (x, i))) ! 131: return 1; ! 132: } ! 133: else if (fmt[i] == 'E') ! 134: { ! 135: register int j; ! 136: for (j = XVECLEN (x, i) - 1; j >= 0; j--) ! 137: if (inequality_comparisons_p (XVECEXP (x, i, j))) ! 138: return 1; ! 139: } ! 140: } ! 141: ! 142: return 0; ! 143: } ! 144: ! 145: /* Return 1 if OP is a valid general operand for machine mode MODE. ! 146: This is either a register reference, a memory reference, ! 147: or a constant. In the case of a memory reference, the address ! 148: is checked for general validity for the target machine. ! 149: ! 150: Register and memory references must have mode MODE in order to be valid, ! 151: but some constants have no machine mode and are valid for any mode. ! 152: ! 153: If MODE is VOIDmode, OP is checked for validity for whatever mode ! 154: it has. ! 155: ! 156: The main use of this function is as a predicate in match_operand ! 157: expressions in the machine description. */ ! 158: ! 159: int ! 160: general_operand (op, mode) ! 161: register rtx op; ! 162: enum machine_mode mode; ! 163: { ! 164: register enum rtx_code code = GET_CODE (op); ! 165: int mode_altering_drug = 0; ! 166: ! 167: if (mode == VOIDmode) ! 168: mode = GET_MODE (op); ! 169: ! 170: if (CONSTANT_P (op)) ! 171: return ((GET_MODE (op) == VOIDmode || GET_MODE (op) == mode) ! 172: && LEGITIMATE_CONSTANT_P (op)); ! 173: ! 174: /* Except for certain constants with VOIDmode, already checked for, ! 175: OP's mode must match MODE if MODE specifies a mode. */ ! 176: ! 177: if (GET_MODE (op) != mode) ! 178: return 0; ! 179: ! 180: while (code == SUBREG) ! 181: { ! 182: op = SUBREG_REG (op); ! 183: code = GET_CODE (op); ! 184: mode_altering_drug = 1; ! 185: } ! 186: if (code == REG) ! 187: return 1; ! 188: if (code == CONST_DOUBLE) ! 189: return LEGITIMATE_CONSTANT_P (op); ! 190: if (code == MEM) ! 191: { ! 192: register rtx y = XEXP (op, 0); ! 193: if (! volatile_ok && op->volatil) ! 194: return 0; ! 195: GO_IF_LEGITIMATE_ADDRESS (mode, y, win); ! 196: } ! 197: return 0; ! 198: ! 199: win: ! 200: if (mode_altering_drug) ! 201: return ! mode_dependent_address_p (XEXP (op, 0)); ! 202: return 1; ! 203: } ! 204: ! 205: /* Return 1 if OP is a valid memory address for a memory reference ! 206: of mode MODE. ! 207: ! 208: The main use of this function is as a predicate in match_operand ! 209: expressions in the machine description. */ ! 210: ! 211: int ! 212: address_operand (op, mode) ! 213: register rtx op; ! 214: enum machine_mode mode; ! 215: { ! 216: return memory_address_p (mode, op); ! 217: } ! 218: ! 219: /* Return 1 if OP is a register reference of mode MODE. ! 220: If MODE is VOIDmode, accept a register in any mode. ! 221: ! 222: The main use of this function is as a predicate in match_operand ! 223: expressions in the machine description. */ ! 224: ! 225: int ! 226: register_operand (op, mode) ! 227: register rtx op; ! 228: enum machine_mode mode; ! 229: { ! 230: if (GET_MODE (op) != mode && mode != VOIDmode) ! 231: return 0; ! 232: ! 233: while (GET_CODE (op) == SUBREG) ! 234: op = SUBREG_REG (op); ! 235: ! 236: return GET_CODE (op) == REG; ! 237: } ! 238: ! 239: /* Return 1 if OP is a valid immediate operand for mode MODE. ! 240: ! 241: The main use of this function is as a predicate in match_operand ! 242: expressions in the machine description. */ ! 243: ! 244: int ! 245: immediate_operand (op, mode) ! 246: register rtx op; ! 247: enum machine_mode mode; ! 248: { ! 249: return ((CONSTANT_P (op) ! 250: || (GET_CODE (op) == CONST_DOUBLE ! 251: && (GET_MODE (op) == mode || mode == VOIDmode))) ! 252: && LEGITIMATE_CONSTANT_P (op)); ! 253: } ! 254: ! 255: /* Return 1 if OP is a register reference or immediate value of mode MODE. */ ! 256: ! 257: int ! 258: nonmemory_operand (op, mode) ! 259: register rtx op; ! 260: enum machine_mode mode; ! 261: { ! 262: if (CONSTANT_P (op) ! 263: || (GET_CODE (op) == CONST_DOUBLE ! 264: && (GET_MODE (op) == mode || mode == VOIDmode))) ! 265: return LEGITIMATE_CONSTANT_P (op); ! 266: ! 267: if (GET_MODE (op) != mode && mode != VOIDmode) ! 268: return 0; ! 269: ! 270: while (GET_CODE (op) == SUBREG) ! 271: op = SUBREG_REG (op); ! 272: ! 273: return GET_CODE (op) == REG; ! 274: } ! 275: ! 276: /* Return 1 if OP is a valid operand that stands for pushing a ! 277: value of mode MODE onto the stack. ! 278: ! 279: The main use of this function is as a predicate in match_operand ! 280: expressions in the machine description. */ ! 281: ! 282: int ! 283: push_operand (op, mode) ! 284: rtx op; ! 285: enum machine_mode mode; ! 286: { ! 287: if (GET_CODE (op) != MEM) ! 288: return 0; ! 289: ! 290: if (GET_MODE (op) != mode) ! 291: return 0; ! 292: ! 293: op = XEXP (op, 0); ! 294: ! 295: #ifdef STACK_GROWS_DOWNWARD ! 296: if (GET_CODE (op) != PRE_DEC) ! 297: return 0; ! 298: #else ! 299: if (GET_CODE (op) != PRE_INC) ! 300: return 0; ! 301: #endif ! 302: return REGNO (XEXP (op, 0)) == STACK_POINTER_REGNUM; ! 303: } ! 304: ! 305: /* Return 1 if ADDR is a valid memory address for mode MODE. */ ! 306: ! 307: int ! 308: memory_address_p (mode, addr) ! 309: enum machine_mode mode; ! 310: register rtx addr; ! 311: { ! 312: GO_IF_LEGITIMATE_ADDRESS (mode, addr, win); ! 313: return 0; ! 314: ! 315: win: ! 316: return 1; ! 317: } ! 318: ! 319: /* Return 1 if OP is a valid memory reference with mode MODE, ! 320: including a valid address. ! 321: ! 322: The main use of this function is as a predicate in match_operand ! 323: expressions in the machine description. */ ! 324: ! 325: int ! 326: memory_operand (op, mode) ! 327: register rtx op; ! 328: enum machine_mode mode; ! 329: { ! 330: return GET_CODE (op) == MEM && general_operand (op, mode); ! 331: } ! 332: ! 333: /* If BODY is an insn body that uses ASM_OPERANDS, ! 334: return the number of operands (both input and output) in the insn. ! 335: Otherwise return 0. */ ! 336: ! 337: int ! 338: asm_noperands (body) ! 339: rtx body; ! 340: { ! 341: int noperands; ! 342: ! 343: if (GET_CODE (body) == SET && GET_CODE (SET_SRC (body)) == ASM_OPERANDS) ! 344: /* Single output operand: BODY is (set OUTPUT (asm_operands ...)). */ ! 345: return XVECLEN (SET_SRC (body), 3) + 1; ! 346: else if (GET_CODE (body) == PARALLEL ! 347: && GET_CODE (XVECEXP (body, 0, 0)) == SET ! 348: && GET_CODE (SET_SRC (XVECEXP (body, 0, 0))) == ASM_OPERANDS) ! 349: /* Multiple outputs: BODY is ! 350: (parallel [(set OUTPUT0 (asm_operands ...)) ...]). */ ! 351: return XVECLEN (SET_SRC (XVECEXP (body, 0, 0)), 3) + XVECLEN (body, 0); ! 352: else ! 353: return 0; ! 354: } ! 355: ! 356: /* Assuming BODY is an insn body that uses ASM_OPERANDS, ! 357: copy its operands (both input and output) into the vector OPERANDS, ! 358: the locations of the operands within the insn into the vector OPERAND_LOCS, ! 359: and the constraints for the operands into CONSTRAINTS. ! 360: Write the modes of the operands into MODES. ! 361: Return the assembler-template. ! 362: ! 363: If MODES, OPERAND_LOCS, CONSTRAINTS or OPERANDS is 0, ! 364: we don't store that info. */ ! 365: ! 366: char * ! 367: decode_asm_operands (body, operands, operand_locs, constraints, modes) ! 368: rtx body; ! 369: rtx *operands; ! 370: rtx **operand_locs; ! 371: char **constraints; ! 372: enum machine_mode *modes; ! 373: { ! 374: register int i; ! 375: int noperands; ! 376: char *template; ! 377: ! 378: if (GET_CODE (body) == SET && GET_CODE (SET_SRC (body)) == ASM_OPERANDS) ! 379: { ! 380: rtx asmop = SET_SRC (body); ! 381: /* Single output operand: BODY is (set OUTPUT (asm_operands ....)). */ ! 382: ! 383: noperands = XVECLEN (asmop, 3) + 1; ! 384: ! 385: /* The input operands are found in the 1st element vector. */ ! 386: /* Constraints for inputs are in the 2nd element vector. */ ! 387: for (i = 1; i < noperands; i++) ! 388: { ! 389: if (operand_locs) ! 390: operand_locs[i] = &XVECEXP (asmop, 3, i - 1); ! 391: if (operands) ! 392: operands[i] = XVECEXP (asmop, 3, i - 1); ! 393: if (constraints) ! 394: constraints[i] = XSTR (XVECEXP (asmop, 4, i - 1), 0); ! 395: if (modes) ! 396: modes[i] = GET_MODE (XVECEXP (asmop, 4, i - 1)); ! 397: } ! 398: ! 399: /* The output is in the SET. ! 400: Its constraint is in the ASM_OPERANDS itself. */ ! 401: if (operands) ! 402: operands[0] = SET_DEST (body); ! 403: if (operand_locs) ! 404: operand_locs[0] = &SET_DEST (body); ! 405: if (constraints) ! 406: constraints[0] = XSTR (asmop, 1); ! 407: if (modes) ! 408: modes[0] = GET_MODE (SET_DEST (body)); ! 409: template = XSTR (asmop, 0); ! 410: } ! 411: else ! 412: { ! 413: rtx asmop = SET_SRC (XVECEXP (body, 0, 0)); ! 414: int nout = XVECLEN (body, 0); ! 415: int nin = XVECLEN (asmop, 3); ! 416: ! 417: noperands = XVECLEN (asmop, 3) + XVECLEN (body, 0); ! 418: ! 419: /* The input operands are found in the 1st element vector. */ ! 420: /* Constraints for inputs are in the 2nd element vector. */ ! 421: for (i = 0; i < nin; i++) ! 422: { ! 423: if (operand_locs) ! 424: operand_locs[i + nout] = &XVECEXP (asmop, 3, i); ! 425: if (operands) ! 426: operands[i + nout] = XVECEXP (asmop, 3, i); ! 427: if (constraints) ! 428: constraints[i + nout] = XSTR (XVECEXP (asmop, 4, i), 0); ! 429: if (modes) ! 430: modes[i + nout] = GET_MODE (XVECEXP (asmop, 4, i)); ! 431: } ! 432: /* The outputs are in the SETs. ! 433: Their constraints are in the ASM_OPERANDS itself. */ ! 434: for (i = 0; i < nout; i++) ! 435: { ! 436: if (operands) ! 437: operands[i] = SET_DEST (XVECEXP (body, 0, i)); ! 438: if (operand_locs) ! 439: operand_locs[i] = &SET_DEST (XVECEXP (body, 0, i)); ! 440: if (constraints) ! 441: constraints[i] = XSTR (SET_SRC (XVECEXP (body, 0, i)), 1); ! 442: if (modes) ! 443: modes[i] = GET_MODE (SET_DEST (XVECEXP (body, 0, i))); ! 444: } ! 445: template = XSTR (asmop, 0); ! 446: } ! 447: ! 448: return template; ! 449: } ! 450: ! 451: extern rtx plus_constant (); ! 452: extern rtx copy_rtx (); ! 453: ! 454: /* Given an rtx *P, if it is a sum containing an integer constant term, ! 455: return the location (type rtx *) of the pointer to that constant term. ! 456: Otherwise, return a null pointer. */ ! 457: ! 458: static rtx * ! 459: find_constant_term_loc (p) ! 460: rtx *p; ! 461: { ! 462: register rtx *tem; ! 463: register enum rtx_code code = GET_CODE (*p); ! 464: ! 465: /* If *P IS such a constant term, P is its location. */ ! 466: ! 467: if (code == CONST_INT || code == SYMBOL_REF || code == LABEL_REF ! 468: || code == CONST) ! 469: return p; ! 470: ! 471: /* Otherwise, if not a sum, it has no constant term. */ ! 472: ! 473: if (GET_CODE (*p) != PLUS) ! 474: return 0; ! 475: ! 476: /* If one of the summands is constant, return its location. */ ! 477: ! 478: if (XEXP (*p, 0) && CONSTANT_P (XEXP (*p, 0)) ! 479: && XEXP (*p, 1) && CONSTANT_P (XEXP (*p, 1))) ! 480: return p; ! 481: ! 482: /* Otherwise, check each summand for containing a constant term. */ ! 483: ! 484: if (XEXP (*p, 0) != 0) ! 485: { ! 486: tem = find_constant_term_loc (&XEXP (*p, 0)); ! 487: if (tem != 0) ! 488: return tem; ! 489: } ! 490: ! 491: if (XEXP (*p, 1) != 0) ! 492: { ! 493: tem = find_constant_term_loc (&XEXP (*p, 1)); ! 494: if (tem != 0) ! 495: return tem; ! 496: } ! 497: ! 498: return 0; ! 499: } ! 500: ! 501: /* Return 1 if OP is a memory reference ! 502: whose address contains no side effects ! 503: and remains valid after the addition ! 504: of a positive integer less than the ! 505: size of the object being referenced. ! 506: ! 507: We assume that the original address is valid and do not check it. */ ! 508: ! 509: int ! 510: offsetable_memref_p (op) ! 511: rtx op; ! 512: { ! 513: return ((GET_CODE (op) == MEM) ! 514: && offsetable_address_p (GET_MODE (op), XEXP (op, 0))); ! 515: } ! 516: ! 517: /* Return 1 if Y is a memory address which contains no side effects ! 518: and would remain valid for mode MODE ! 519: after the addition of a positive integer less than the ! 520: size of that mode. ! 521: ! 522: We assume that the original address is valid and do not check it. */ ! 523: ! 524: int ! 525: offsetable_address_p (mode, y) ! 526: enum machine_mode mode; ! 527: register rtx y; ! 528: { ! 529: register enum rtx_code ycode = GET_CODE (y); ! 530: register rtx z; ! 531: rtx y1 = y; ! 532: rtx *y2; ! 533: ! 534: if (CONSTANT_ADDRESS_P (y)) ! 535: return 1; ! 536: ! 537: /* If the expression contains a constant term, ! 538: see if it remains valid when max possible offset is added. */ ! 539: ! 540: if ((ycode == PLUS) && (y2 = find_constant_term_loc (&y1))) ! 541: { ! 542: int old = INTVAL (y1 = *y2); ! 543: int good; ! 544: INTVAL (y1) += GET_MODE_SIZE (mode) - 1; ! 545: good = memory_address_p (mode, y); ! 546: /* In any case, restore old contents of memory. */ ! 547: INTVAL (y1) = old; ! 548: return good; ! 549: } ! 550: ! 551: if (ycode == PRE_DEC || ycode == PRE_INC ! 552: || ycode == POST_DEC || ycode == POST_INC) ! 553: return 0; ! 554: ! 555: /* The offset added here is chosen as the maximum offset that ! 556: any instruction could need to add when operating on something ! 557: of the specified mode. We assume that if Y and Y+c are ! 558: valid addresses then so is Y+d for all 0<d<c. */ ! 559: ! 560: z = plus_constant (y, GET_MODE_SIZE (mode) - 1); ! 561: ! 562: return memory_address_p (mode, z); ! 563: } ! 564: ! 565: /* Return 1 if ADDR is an address-expression whose effect depends ! 566: on the mode of the memory reference it is used in. ! 567: ! 568: Autoincrement addressing is a typical example of mode-dependence ! 569: because the amount of the increment depends on the mode. */ ! 570: ! 571: int ! 572: mode_dependent_address_p (addr) ! 573: rtx addr; ! 574: { ! 575: GO_IF_MODE_DEPENDENT_ADDRESS (addr, win); ! 576: return 0; ! 577: win: ! 578: return 1; ! 579: } ! 580: ! 581: /* Return 1 if OP is a general operand ! 582: other than a memory ref with a mode dependent address. */ ! 583: ! 584: int ! 585: mode_independent_operand (mode, op) ! 586: rtx op; ! 587: { ! 588: rtx addr; ! 589: ! 590: if (! general_operand (mode, op)) ! 591: return 0; ! 592: ! 593: if (GET_CODE (op) != MEM) ! 594: return 1; ! 595: ! 596: addr = XEXP (op, 0); ! 597: GO_IF_MODE_DEPENDENT_ADDRESS (addr, lose); ! 598: return 1; ! 599: lose: ! 600: return 0; ! 601: } ! 602: ! 603: /* Given an operand OP that is a valid memory reference ! 604: which satisfies offsetable_memref_p, ! 605: return a new memory reference whose address has been adjusted by OFFSET. ! 606: OFFSET should be positive and less than the size of the object referenced. ! 607: */ ! 608: ! 609: rtx ! 610: adj_offsetable_operand (op, offset) ! 611: rtx op; ! 612: int offset; ! 613: { ! 614: register enum rtx_code code = GET_CODE (op); ! 615: ! 616: if (code == MEM) ! 617: { ! 618: register rtx y = XEXP (op, 0); ! 619: ! 620: if (CONSTANT_ADDRESS_P (y)) ! 621: return gen_rtx (MEM, GET_MODE (op), plus_constant (y, offset)); ! 622: ! 623: if (GET_CODE (y) == PLUS) ! 624: { ! 625: rtx z = y; ! 626: register rtx *const_loc; ! 627: ! 628: op = copy_rtx (op); ! 629: z = XEXP (op, 0); ! 630: const_loc = find_constant_term_loc (&z); ! 631: if (const_loc) ! 632: { ! 633: *const_loc = plus_constant (*const_loc, offset); ! 634: return op; ! 635: } ! 636: } ! 637: ! 638: return gen_rtx (MEM, GET_MODE (op), plus_constant (y, offset)); ! 639: } ! 640: abort (); ! 641: } ! 642: ! 643: #ifdef REGISTER_CONSTRAINTS ! 644: ! 645: /* Check the operands of an insn (found in recog_operands) ! 646: against the insn's operand constraints (found via INSN_CODE_NUM) ! 647: and return 1 if they are valid. ! 648: ! 649: WHICH_ALTERNATIVE is set to a number which indicates which ! 650: alternative of constraints was matched: 0 for the first alternative, ! 651: 1 for the next, etc. ! 652: ! 653: In addition, when two operands are match ! 654: and it happens that the output operand is (reg) while the ! 655: input operand is --(reg) or ++(reg) (a pre-inc or pre-dec), ! 656: make the output operand look like the input. ! 657: This is because the output operand is the one the template will print. ! 658: ! 659: This is used in final, just before printing the assembler code. */ ! 660: ! 661: struct funny_match ! 662: { ! 663: int this, other; ! 664: }; ! 665: ! 666: int ! 667: constrain_operands (insn_code_num) ! 668: int insn_code_num; ! 669: { ! 670: char *constraints[MAX_RECOG_OPERANDS]; ! 671: register int c; ! 672: int noperands = insn_n_operands[insn_code_num]; ! 673: ! 674: struct funny_match funny_match[MAX_RECOG_OPERANDS]; ! 675: int funny_match_index; ! 676: ! 677: if (noperands == 0) ! 678: return 1; ! 679: ! 680: for (c = 0; c < noperands; c++) ! 681: constraints[c] = insn_operand_constraint[insn_code_num][c]; ! 682: ! 683: which_alternative = 0; ! 684: ! 685: while (*constraints[0]) ! 686: { ! 687: register int opno; ! 688: int lose = 0; ! 689: funny_match_index = 0; ! 690: ! 691: for (opno = 0; opno < noperands; opno++) ! 692: { ! 693: register rtx op = recog_operand[opno]; ! 694: register char *p = constraints[opno]; ! 695: int win = 0; ! 696: int val; ! 697: ! 698: /* `alter_subreg' should already have converted any SUBREG ! 699: that appears at the level of an operand. */ ! 700: while (GET_CODE (op) == SUBREG) ! 701: abort (); ! 702: ! 703: while (*p && (c = *p++) != ',') ! 704: switch (c) ! 705: { ! 706: case '=': ! 707: case '+': ! 708: case '?': ! 709: case '#': ! 710: case '!': ! 711: case '*': ! 712: case '%': ! 713: break; ! 714: ! 715: case '0': ! 716: case '1': ! 717: case '2': ! 718: case '3': ! 719: case '4': ! 720: /* This operand must be the same as a previous one. */ ! 721: /* This kind of constraint is used for instructions such ! 722: as add when they take only two operands. */ ! 723: /* Note that the lower-numbered operand is passed first. */ ! 724: val = operands_match_p (recog_operand[c - '0'], ! 725: recog_operand[opno]); ! 726: if (val != 0) ! 727: win = 1; ! 728: /* If output is *x and input is *--x, ! 729: arrange later to change the output to *--x as well, ! 730: since the output op is the one that will be printed. */ ! 731: if (val == 2) ! 732: { ! 733: funny_match[funny_match_index].this = opno; ! 734: funny_match[funny_match_index++].other = c - '0'; ! 735: } ! 736: break; ! 737: ! 738: case 'p': ! 739: /* p is used for address_operands, and everything ! 740: that must be checked was checked already. */ ! 741: win = 1; ! 742: break; ! 743: ! 744: /* No need to check general_operand again; ! 745: it was done in insn-recog.c. */ ! 746: case 'g': ! 747: /* Anything goes unless it is a REG and really has a hard reg ! 748: but the hard reg is not in the class GENERAL_REGS. */ ! 749: if (GENERAL_REGS == ALL_REGS ! 750: || GET_CODE (op) != REG ! 751: || (REGNO (op) >= FIRST_PSEUDO_REGISTER ! 752: && reg_renumber[REGNO (op)] < 0) ! 753: || reg_renumbered_fits_class_p (op, GENERAL_REGS, 0, ! 754: GET_MODE (op))) ! 755: win = 1; ! 756: break; ! 757: ! 758: case 'r': ! 759: if (GET_CODE (op) == REG ! 760: && (GENERAL_REGS == ALL_REGS ! 761: || reg_renumbered_fits_class_p (op, GENERAL_REGS, ! 762: 0, GET_MODE (op)))) ! 763: win = 1; ! 764: break; ! 765: ! 766: case 'm': ! 767: if (GET_CODE (op) == MEM) ! 768: win = 1; ! 769: break; ! 770: ! 771: case '<': ! 772: if (GET_CODE (op) == MEM ! 773: && (GET_CODE (XEXP (op, 0)) == PRE_DEC ! 774: || GET_CODE (XEXP (op, 0)) == POST_DEC)) ! 775: win = 1; ! 776: break; ! 777: ! 778: case '>': ! 779: if (GET_CODE (op) == MEM ! 780: && (GET_CODE (XEXP (op, 0)) == PRE_INC ! 781: || GET_CODE (XEXP (op, 0)) == POST_INC)) ! 782: win = 1; ! 783: break; ! 784: ! 785: case 'F': ! 786: if (GET_CODE (op) == CONST_DOUBLE) ! 787: win = 1; ! 788: break; ! 789: ! 790: case 'G': ! 791: case 'H': ! 792: if (GET_CODE (op) == CONST_DOUBLE ! 793: && CONST_DOUBLE_OK_FOR_LETTER_P (op, c)) ! 794: win = 1; ! 795: break; ! 796: ! 797: case 's': ! 798: if (GET_CODE (op) == CONST_INT) ! 799: break; ! 800: case 'i': ! 801: if (CONSTANT_P (op)) ! 802: win = 1; ! 803: break; ! 804: ! 805: case 'n': ! 806: if (GET_CODE (op) == CONST_INT) ! 807: win = 1; ! 808: break; ! 809: ! 810: case 'I': ! 811: case 'J': ! 812: case 'K': ! 813: case 'L': ! 814: case 'M': ! 815: if (GET_CODE (op) == CONST_INT ! 816: && CONST_OK_FOR_LETTER_P (INTVAL (op), c)) ! 817: win = 1; ! 818: break; ! 819: ! 820: case 'o': ! 821: if (offsetable_memref_p (op)) ! 822: win = 1; ! 823: break; ! 824: ! 825: default: ! 826: if (GET_CODE (op) == REG ! 827: && reg_renumbered_fits_class_p (op, ! 828: REG_CLASS_FROM_LETTER (c), ! 829: 0, GET_MODE (op))) ! 830: win = 1; ! 831: } ! 832: ! 833: constraints[opno] = p; ! 834: /* If this operand did not win somehow, ! 835: this alternative loses. */ ! 836: if (! win) ! 837: lose = 1; ! 838: } ! 839: /* This alternative won; the operands are ok. ! 840: Change whichever operands this alternative says to change. */ ! 841: if (! lose) ! 842: { ! 843: while (--funny_match_index >= 0) ! 844: { ! 845: recog_operand[funny_match[funny_match_index].other] ! 846: = recog_operand[funny_match[funny_match_index].this]; ! 847: } ! 848: return 1; ! 849: } ! 850: ! 851: which_alternative++; ! 852: } ! 853: return 0; ! 854: } ! 855: ! 856: /* Return 1 iff OPERAND (assumed to be a REG rtx) ! 857: is a hard reg in class CLASS when its regno is offsetted by OFFSET ! 858: and changed to mode MODE, ! 859: or is a pseudo reg allocated into such a hard reg. ! 860: If REG occupies multiple hard regs, all of them must by in CLASS. */ ! 861: ! 862: int ! 863: reg_renumbered_fits_class_p (operand, class, offset, mode) ! 864: rtx operand; ! 865: register enum reg_class class; ! 866: int offset; ! 867: enum machine_mode mode; ! 868: { ! 869: if (GET_CODE (operand) == REG) ! 870: { ! 871: register int regno = REGNO (operand); ! 872: if (reg_renumber[regno] >= 0) ! 873: regno = reg_renumber[regno]; ! 874: if (regno < FIRST_PSEUDO_REGISTER ! 875: && TEST_HARD_REG_BIT (reg_class_contents[(int) class], ! 876: regno + offset)) ! 877: { ! 878: register int sr; ! 879: regno += offset; ! 880: for (sr = HARD_REGNO_NREGS (regno, mode) - 1; ! 881: sr > 0; sr--) ! 882: if (! TEST_HARD_REG_BIT (reg_class_contents[(int) class], ! 883: regno + sr)) ! 884: break; ! 885: return sr == 0; ! 886: } ! 887: } ! 888: return 0; ! 889: } ! 890: ! 891: #endif /* REGISTER_CONSTRAINTS */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.