Annotation of researchv10dc/cmd/gcc/recog.c, revision 1.1

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 */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.