Annotation of GNUtools/cc/config/pyr/pyr.c, revision 1.1

1.1     ! root        1: /* Subroutines for insn-output.c for Pyramid 90x, 9000, and MIServer Series.
        !             2:    Copyright (C) 1989, 1991 Free Software Foundation, Inc.
        !             3: 
        !             4: This file is part of GNU CC.
        !             5: 
        !             6: GNU CC is free software; you can redistribute it and/or modify
        !             7: it under the terms of the GNU General Public License as published by
        !             8: the Free Software Foundation; either version 2, or (at your option)
        !             9: any later version.
        !            10: 
        !            11: GNU CC is distributed in the hope that it will be useful,
        !            12: but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            14: GNU General Public License for more details.
        !            15: 
        !            16: You should have received a copy of the GNU General Public License
        !            17: along with GNU CC; see the file COPYING.  If not, write to
        !            18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
        !            19: 
        !            20: /* Some output-actions in pyr.md need these.  */
        !            21: #include <stdio.h>
        !            22: #include "config.h"
        !            23: #include "rtl.h"
        !            24: #include "regs.h"
        !            25: #include "hard-reg-set.h"
        !            26: #include "real.h"
        !            27: #include "insn-config.h"
        !            28: #include "conditions.h"
        !            29: #include "insn-flags.h"
        !            30: #include "output.h"
        !            31: #include "insn-attr.h"
        !            32: #include "tree.h"
        !            33: 
        !            34: /*
        !            35:  * Do FUNCTION_ARG.
        !            36:  * This cannot be defined as a macro on pyramids, because Pyramid Technology's
        !            37:  * C compiler dies on (several equivalent definitions of) this macro.
        !            38:  * The only way around this cc bug was to make this a function.
        !            39:  * While it would be possible to use a macro version for gcc, it seems
        !            40:  * more reliable to have a single version of the code.
        !            41:  */
        !            42: void *
        !            43: pyr_function_arg(cum, mode, type, named)
        !            44:   CUMULATIVE_ARGS cum;
        !            45:   enum machine_mode mode;
        !            46:   tree type;
        !            47: {
        !            48:   return (void *)(FUNCTION_ARG_HELPER (cum, mode,type,named));
        !            49: }
        !            50: 
        !            51: /* Do the hard part of PARAM_SAFE_FOR_REG_P.
        !            52:  * This cannot be defined as a macro on pyramids, because Pyramid Technology's
        !            53:  * C compiler dies on (several equivalent definitions of) this macro.
        !            54:  * The only way around this cc bug was to make this a function.
        !            55:  */
        !            56: int
        !            57: inner_param_safe_helper (type)
        !            58:     tree type;
        !            59: {
        !            60:   return (INNER_PARAM_SAFE_HELPER(type));
        !            61: }
        !            62: 
        !            63: 
        !            64: /* Return 1 if OP is a non-indexed operand of mode MODE.
        !            65:    This is either a register reference, a memory reference,
        !            66:    or a constant.  In the case of a memory reference, the address
        !            67:    is checked to make sure it isn't indexed.
        !            68: 
        !            69:    Register and memory references must have mode MODE in order to be valid,
        !            70:    but some constants have no machine mode and are valid for any mode.
        !            71: 
        !            72:    If MODE is VOIDmode, OP is checked for validity for whatever mode
        !            73:    it has.
        !            74: 
        !            75:    The main use of this function is as a predicate in match_operand
        !            76:    expressions in the machine description.
        !            77: 
        !            78:    It is  useful to compare this with general_operand().  They should
        !            79:    be identical except for one line.
        !            80: 
        !            81:    This function seems necessary because of the non-orthogonality of
        !            82:    Pyramid insns.
        !            83:    For any 2-operand insn, and any combination of operand modes,
        !            84:    if indexing is valid for the isn's second operand, it is invalid
        !            85:    for the first operand to be indexed. */
        !            86: 
        !            87: extern int volatile_ok;
        !            88: 
        !            89: int
        !            90: nonindexed_operand (op, mode)
        !            91:     register rtx op;
        !            92:     enum machine_mode mode;
        !            93: {
        !            94:   register RTX_CODE code = GET_CODE (op);
        !            95:   int mode_altering_drug = 0;
        !            96: 
        !            97:   if (mode == VOIDmode)
        !            98:     mode = GET_MODE (op);
        !            99: 
        !           100:   /* Don't accept CONST_INT or anything similar
        !           101:      if the caller wants something floating.  */
        !           102:   if (GET_MODE (op) == VOIDmode && mode != VOIDmode
        !           103:       && GET_MODE_CLASS (mode) != MODE_INT)
        !           104:     return 0;
        !           105: 
        !           106:   if (CONSTANT_P (op))
        !           107:     return ((GET_MODE (op) == VOIDmode || GET_MODE (op) == mode)
        !           108:            && LEGITIMATE_CONSTANT_P (op));
        !           109: 
        !           110:   /* Except for certain constants with VOIDmode, already checked for,
        !           111:      OP's mode must match MODE if MODE specifies a mode.  */
        !           112: 
        !           113:   if (GET_MODE (op) != mode)
        !           114:     return 0;
        !           115: 
        !           116:   while (code == SUBREG)
        !           117:     {
        !           118:       op = SUBREG_REG (op);
        !           119:       code = GET_CODE (op);
        !           120: #if 0
        !           121:       /* No longer needed, since (SUBREG (MEM...))
        !           122:         will load the MEM into a reload reg in the MEM's own mode.  */
        !           123:       mode_altering_drug = 1;
        !           124: #endif
        !           125:     }
        !           126:   if (code == REG)
        !           127:     return 1;
        !           128:   if (code == CONST_DOUBLE)
        !           129:     return LEGITIMATE_CONSTANT_P (op);
        !           130:   if (code == MEM)
        !           131:     {
        !           132:       register rtx y = XEXP (op, 0);
        !           133:       if (! volatile_ok && MEM_VOLATILE_P (op))
        !           134:        return 0;
        !           135:     GO_IF_NONINDEXED_ADDRESS (y, win);
        !           136:     }
        !           137:   return 0;
        !           138: 
        !           139:  win:
        !           140:   if (mode_altering_drug)
        !           141:     return ! mode_dependent_address_p (XEXP (op, 0));
        !           142:   return 1;
        !           143: }
        !           144: 
        !           145: /* Return non-zero if the rtx OP has an immediate component.  An
        !           146:    immediate component or additive term equal to zero is rejected
        !           147:    due to assembler problems.  */
        !           148: 
        !           149: int
        !           150: has_direct_base (op)
        !           151:      rtx op;
        !           152: {
        !           153:   if ((CONSTANT_ADDRESS_P (op)
        !           154:        && op != const0_rtx)
        !           155:       || (GET_CODE (op) == PLUS
        !           156:          && ((CONSTANT_ADDRESS_P (XEXP (op, 1))
        !           157:               && XEXP (op, 1) != const0_rtx)
        !           158:              || (CONSTANT_ADDRESS_P (XEXP (op, 0))
        !           159:                  && XEXP (op, 0) != const0_rtx))))
        !           160:     return 1;
        !           161: 
        !           162:   return 0;
        !           163: }
        !           164: 
        !           165: /* Return zero if the rtx OP has a (scaled) index.  */
        !           166: 
        !           167: int
        !           168: has_index (op)
        !           169:      rtx op;
        !           170: {
        !           171:   if (GET_CODE (op) == PLUS
        !           172:       && (GET_CODE (XEXP (op, 0)) == MULT
        !           173:          || (GET_CODE (XEXP (op, 1)) == MULT)))
        !           174:     return 1;
        !           175:   else
        !           176:     return 0;
        !           177: }
        !           178: 
        !           179: int swap_operands;
        !           180: 
        !           181: /* weird_memory_memory -- return 1 if OP1 and OP2 can be compared (or
        !           182:    exchanged with xchw) with one instruction.  If the operands need to
        !           183:    be swapped, set the global variable SWAP_OPERANDS.  This function
        !           184:    silently assumes that both OP0 and OP1 are valid memory references.
        !           185:    */
        !           186: 
        !           187: int
        !           188: weird_memory_memory (op0, op1)
        !           189:      rtx op0, op1;
        !           190: {
        !           191:   RTX_CODE code0, code1;
        !           192: 
        !           193:   op0 = XEXP (op0, 0);
        !           194:   op1 = XEXP (op1, 0);
        !           195:   code0 = GET_CODE (op0);
        !           196:   code1 = GET_CODE (op1);
        !           197: 
        !           198:   swap_operands = 0;
        !           199: 
        !           200:   if (code1 == REG || code1 == SUBREG)
        !           201:     {
        !           202:       return 1;
        !           203:     }
        !           204:   if (code0 == REG || code0 == SUBREG)
        !           205:     {
        !           206:       swap_operands = 1;
        !           207:       return 1;
        !           208:     }
        !           209:   if (has_direct_base (op0) && has_direct_base (op1))
        !           210:     {
        !           211:       if (has_index (op1))
        !           212:        {
        !           213:          if (has_index (op0))
        !           214:            return 0;
        !           215:          swap_operands = 1;
        !           216:        }
        !           217: 
        !           218:       return 1;
        !           219:     }
        !           220:   return 0;
        !           221: }
        !           222: 
        !           223: int
        !           224: signed_comparison (x, mode)
        !           225:      rtx x;
        !           226:      enum machine_mode mode;
        !           227: {
        !           228:   return ! TRULY_UNSIGNED_COMPARE_P (GET_CODE (x));
        !           229: }
        !           230: 
        !           231: extern rtx force_reg ();
        !           232: rtx test_op0, test_op1;
        !           233: enum machine_mode test_mode;
        !           234: 
        !           235: /* Sign-extend or zero-extend constant X from FROM_MODE to TO_MODE.  */
        !           236: 
        !           237: rtx
        !           238: extend_const (x, extop, from_mode, to_mode)
        !           239:     rtx x;
        !           240:     RTX_CODE extop;
        !           241:     enum machine_mode from_mode, to_mode;
        !           242: {
        !           243:   int val;
        !           244:   int negative;
        !           245:   if (from_mode == to_mode)
        !           246:     return x;
        !           247:   if (GET_CODE (x) != CONST_INT)
        !           248:     abort ();
        !           249:   val = INTVAL (x);
        !           250:   negative = val & (1 << (GET_MODE_BITSIZE (from_mode) - 1));
        !           251:   if (GET_MODE_BITSIZE (from_mode) == HOST_BITS_PER_INT)
        !           252:     abort ();
        !           253:   if (negative && extop == SIGN_EXTEND)
        !           254:     val = val | ((-1) << (GET_MODE_BITSIZE (from_mode)));
        !           255:   else
        !           256:     val = val & ~((-1) << (GET_MODE_BITSIZE (from_mode)));
        !           257:   if (GET_MODE_BITSIZE (to_mode) == HOST_BITS_PER_INT)
        !           258:     return gen_rtx (CONST_INT, VOIDmode, val);
        !           259:   return gen_rtx (CONST_INT, VOIDmode,
        !           260:                  val & ~((-1) << (GET_MODE_BITSIZE (to_mode))));
        !           261: }
        !           262: 
        !           263: rtx
        !           264: ensure_extended (op, extop, from_mode)
        !           265:      rtx op;
        !           266:      RTX_CODE extop;
        !           267:      enum machine_mode from_mode;
        !           268: {
        !           269:   if (GET_CODE (op) == CONST_INT)
        !           270:     return extend_const (op, extop, from_mode, SImode);
        !           271:   else
        !           272:     return force_reg (SImode, gen_rtx (extop, SImode, op));
        !           273: }
        !           274: 
        !           275: /* Emit rtl for a branch, as well as any delayed (integer) compare insns.
        !           276:    The compare insn to perform is determined by the global variables
        !           277:    test_op0 and test_op1.  */
        !           278: 
        !           279: void
        !           280: extend_and_branch (extop)
        !           281:      RTX_CODE extop;
        !           282: {
        !           283:   rtx op0, op1;
        !           284:   RTX_CODE code0, code1;
        !           285: 
        !           286:   op0 = test_op0, op1 = test_op1;
        !           287:   if (op0 == 0)
        !           288:     return;
        !           289: 
        !           290:   code0 = GET_CODE (op0);
        !           291:   if (op1 != 0)
        !           292:     code1 = GET_CODE (op1);
        !           293:   test_op0 = test_op1 = 0;
        !           294: 
        !           295:   if (op1 == 0)
        !           296:     {
        !           297:       op0 = ensure_extended (op0, extop, test_mode);
        !           298:       emit_insn (gen_rtx (SET, VOIDmode, cc0_rtx, op0));
        !           299:     }
        !           300:   else
        !           301:     {
        !           302:       if (CONSTANT_P (op0) && CONSTANT_P (op1))
        !           303:        {
        !           304:          op0 = ensure_extended (op0, extop, test_mode);
        !           305:          op1 = ensure_extended (op1, extop, test_mode);
        !           306:        }
        !           307:       else if (extop == ZERO_EXTEND && test_mode == HImode)
        !           308:        {
        !           309:          /* Pyramids have no unsigned "cmphi" instructions.  We need to
        !           310:             zero extend unsigned halfwords into temporary registers. */
        !           311:          op0 = ensure_extended (op0, extop, test_mode);
        !           312:          op1 = ensure_extended (op1, extop, test_mode);
        !           313:        }
        !           314:       else if (CONSTANT_P (op0))
        !           315:        {
        !           316:          op0 = ensure_extended (op0, extop, test_mode);
        !           317:          op1 = ensure_extended (op1, extop, test_mode);
        !           318:        }
        !           319:       else if (CONSTANT_P (op1))
        !           320:        {
        !           321:          op1 = ensure_extended (op1, extop, test_mode);
        !           322:          op0 = ensure_extended (op0, extop, test_mode);
        !           323:        }
        !           324:       else if ((code0 == REG || code0 == SUBREG)
        !           325:               && (code1 == REG || code1 == SUBREG))
        !           326:        {
        !           327:          /* I could do this case without extension, by using the virtual
        !           328:             register address (but that would lose for global regs).  */
        !           329:          op0 = ensure_extended (op0, extop, test_mode);
        !           330:          op1 = ensure_extended (op1, extop, test_mode);
        !           331:        }
        !           332:       else if (code0 == MEM && code1 == MEM)
        !           333:        {
        !           334:          /* Load into a reg if the address combination can't be handled
        !           335:             directly.  */
        !           336:          if (! weird_memory_memory (op0, op1))
        !           337:            op0 = force_reg (test_mode, op0);
        !           338:        }
        !           339: 
        !           340:       emit_insn (gen_rtx (SET, VOIDmode, cc0_rtx,
        !           341:                          gen_rtx (COMPARE, VOIDmode, op0, op1)));
        !           342:     }
        !           343: }
        !           344: 
        !           345: /* Return non-zero if the two single-word moves with operands[0]
        !           346:    and operands[1] for the first single-word move, and operands[2]
        !           347:    and operands[3] for the second single-word move, is possible to
        !           348:    combine to a double word move.
        !           349: 
        !           350:    The criterion is whether the operands are in consecutive memory cells,
        !           351:    registers, etc.  */
        !           352: 
        !           353: int
        !           354: movdi_possible (operands)
        !           355:      rtx operands[];
        !           356: {
        !           357:   int cnst_diff0, cnst_diff1;
        !           358:   RTX_CODE code0 = GET_CODE (operands[0]);
        !           359:   RTX_CODE code1 = GET_CODE (operands[1]);
        !           360: 
        !           361:   /* Don't dare to combine (possibly overlapping) memory -> memory moves.  */
        !           362:   /* It would be possible to detect the cases where we dare, by using
        !           363:      constant_diff (operands[0], operands[1])!!!  */
        !           364:   if (code0 == MEM && code1 == MEM)
        !           365:     return 0;
        !           366: 
        !           367:   cnst_diff0 = consecutive_operands (operands[0], operands[2]);
        !           368:   if (cnst_diff0 == 0)
        !           369:     return 0;
        !           370: 
        !           371:   cnst_diff1 = consecutive_operands (operands[1], operands[3]);
        !           372:   if (cnst_diff1 == 0)
        !           373:     return 0;
        !           374: 
        !           375:   if (cnst_diff0 & cnst_diff1)
        !           376:     {
        !           377:       /* The source and destination operands are consecutive.  */
        !           378: 
        !           379:       /* If the first move writes into the source of the second move,
        !           380:         we cannot combine.  */
        !           381:       if ((code0 == REG
        !           382:           && reg_overlap_mentioned_p (operands[0], operands[3]))
        !           383:          || (code0 == SUBREG
        !           384:              && subreg_overlap_mentioned_p (operands[0], operands[3])))
        !           385:          return 0;
        !           386: 
        !           387:       if (cnst_diff0 & 1)
        !           388:        /* operands[0],[1] has higher addresses than operands[2],[3].  */
        !           389:        swap_operands = 0;
        !           390:       else
        !           391:        /* operands[0],[1] has lower addresses than operands[2],[3].  */
        !           392:        swap_operands = 1;
        !           393:       return 1;
        !           394:     }
        !           395:   return 0;
        !           396: }
        !           397: 
        !           398: /* Like reg_overlap_mentioned_p, but accepts a subreg rtx instead
        !           399:    of a reg.  */
        !           400: 
        !           401: int
        !           402: subreg_overlap_mentioned_p (subreg, x)
        !           403:      rtx subreg, x;
        !           404: {
        !           405:   rtx reg = SUBREG_REG (subreg);
        !           406:   int regno = REGNO (reg) + SUBREG_WORD (subreg);
        !           407:   int endregno = regno + HARD_REGNO_NREGS (regno, GET_MODE (subreg));
        !           408:   return refers_to_regno_p (regno, endregno, x, 0);
        !           409: }
        !           410: 
        !           411: /* Return 1 if OP0 is a consecutive operand to OP1, 2 if OP1 is a
        !           412:    consecutive operand to OP0.
        !           413: 
        !           414:    This function is used to determine if addresses are consecutive,
        !           415:    and therefore possible to combine to fewer instructions.  */
        !           416: 
        !           417: int
        !           418: consecutive_operands (op0, op1)
        !           419:      rtx op0, op1;
        !           420: {
        !           421:   RTX_CODE code0, code1;
        !           422:   int cnst_diff;
        !           423:   int regno_off0, regno_off1;
        !           424: 
        !           425:   code0 = GET_CODE (op0);
        !           426:   code1 = GET_CODE (op1);
        !           427: 
        !           428:   regno_off0 = 0;
        !           429:   if (code0 == SUBREG)
        !           430:     {
        !           431:       if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0))) <= UNITS_PER_WORD)
        !           432:        return 0;
        !           433:       regno_off0 = SUBREG_WORD (op0);
        !           434:       op0 = SUBREG_REG (op0);
        !           435:       code0 = REG;
        !           436:     }
        !           437: 
        !           438:   regno_off1 = 0;
        !           439:   if (code1 == SUBREG)
        !           440:     {
        !           441:       if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (op1))) <= UNITS_PER_WORD)
        !           442:        return 0;
        !           443:       regno_off1 = SUBREG_WORD (op1);
        !           444:       op1 = SUBREG_REG (op1);
        !           445:       code1 = REG;
        !           446:     }
        !           447: 
        !           448:   if (code0 != code1)
        !           449:     return 0;
        !           450: 
        !           451:   switch (code0)
        !           452:     {
        !           453:     case CONST_INT:
        !           454:       /* Cannot permit any symbolic constants, even if the consecutive
        !           455:         operand is 0, since a movl really performs sign extension.  */
        !           456:       if (code1 != CONST_INT)
        !           457:        return 0;
        !           458:       if ((INTVAL (op0) == 0 && INTVAL (op1) == 0)
        !           459:          || (INTVAL (op0) == -1 && INTVAL (op1) == -1))
        !           460:        return 3;
        !           461:       if ((INTVAL (op0) == 0 && INTVAL (op1) > 0)
        !           462:          || (INTVAL (op0) == -1 && INTVAL (op1) < 0))
        !           463:        return 2;
        !           464:       if ((INTVAL (op1) == 0 && INTVAL (op0) > 0)
        !           465:          || (INTVAL (op1) == -1 && INTVAL (op0) < 0))
        !           466:        return 1;
        !           467:       break;
        !           468: 
        !           469:     case REG:
        !           470:       regno_off0 = REGNO (op0) + regno_off0;
        !           471:       regno_off1 = REGNO (op1) + regno_off1;
        !           472: 
        !           473:       cnst_diff = regno_off0 - regno_off1;
        !           474:       if (cnst_diff == 1)
        !           475:        {
        !           476:          /* movl with the highest numbered parameter (local) register as
        !           477:             source or destination, doesn't wrap to the lowest numbered local
        !           478:             (temporary) register.  */
        !           479: 
        !           480:          if (regno_off0 % 16 != 0)
        !           481:            return 1;
        !           482:          else
        !           483:            return 0;
        !           484:        }
        !           485:       else if (cnst_diff == -1)
        !           486:        {
        !           487:          if (regno_off1 % 16 != 0)
        !           488:            return 2;
        !           489:          else
        !           490:            return 0;
        !           491:        }
        !           492:       break;
        !           493: 
        !           494:     case MEM:
        !           495:       op0 = XEXP (op0, 0);
        !           496:       op1 = XEXP (op1, 0);
        !           497:       if (GET_CODE (op0) == CONST)
        !           498:        op0 = XEXP (op0, 0);
        !           499:       if (GET_CODE (op1) == CONST)
        !           500:        op1 = XEXP (op1, 0);
        !           501: 
        !           502:       cnst_diff = constant_diff (op0, op1);
        !           503:       if (cnst_diff)
        !           504:        {
        !           505:          if (cnst_diff == 4)
        !           506:            return 1;
        !           507:          else if (cnst_diff == -4)
        !           508:            return 2;
        !           509:        }
        !           510:       break;
        !           511:     }
        !           512:   return 0;
        !           513: }
        !           514: 
        !           515: /* Return the constant difference of the rtx expressions OP0 and OP1,
        !           516:    or 0 if they don't have a constant difference.
        !           517: 
        !           518:    This function is used to determine if addresses are consecutive,
        !           519:    and therefore possible to combine to fewer instructions.  */
        !           520: 
        !           521: int
        !           522: constant_diff (op0, op1)
        !           523:      rtx op0, op1;
        !           524: {
        !           525:   RTX_CODE code0, code1;
        !           526:   int cnst_diff;
        !           527: 
        !           528:   code0 = GET_CODE (op0);
        !           529:   code1 = GET_CODE (op1);
        !           530: 
        !           531:   if (code0 != code1)
        !           532:     {
        !           533:       if (code0 == PLUS)
        !           534:        {
        !           535:          if (GET_CODE (XEXP (op0, 1)) == CONST_INT
        !           536:              && rtx_equal_p (op1, XEXP (op0, 0)))
        !           537:            return INTVAL (XEXP (op0, 1));
        !           538:        }
        !           539:       else if (code1 == PLUS)
        !           540:        {
        !           541:          if (GET_CODE (XEXP (op1, 1)) == CONST_INT
        !           542:              && rtx_equal_p (op0, XEXP (op1, 0)))
        !           543:            return -INTVAL (XEXP (op1, 1));
        !           544:        }
        !           545:       return 0;
        !           546:     }
        !           547: 
        !           548:   if (code0 == CONST_INT)
        !           549:     return INTVAL (op0) - INTVAL (op1);
        !           550: 
        !           551:   if (code0 == PLUS)
        !           552:     {
        !           553:       cnst_diff = constant_diff (XEXP (op0, 0), XEXP (op1, 0));
        !           554:       if (cnst_diff)
        !           555:        return (rtx_equal_p (XEXP (op0, 1), XEXP (op1, 1)))
        !           556:          ? cnst_diff : 0;
        !           557:       cnst_diff = constant_diff (XEXP (op0, 1), XEXP (op1, 1));
        !           558:       if (cnst_diff)
        !           559:        return (rtx_equal_p (XEXP (op0, 0), XEXP (op1, 0)))
        !           560:          ? cnst_diff : 0;
        !           561:     }
        !           562: 
        !           563:   return 0;
        !           564: }
        !           565: 
        !           566: int
        !           567: already_sign_extended (insn, from_mode, op)
        !           568:      rtx insn;
        !           569:      enum machine_mode from_mode;
        !           570:      rtx op;
        !           571: {
        !           572:   rtx xinsn, xdest, xsrc;
        !           573: 
        !           574:   for (;;)
        !           575:     {
        !           576:       insn = PREV_INSN (insn);
        !           577:       if (insn == 0)
        !           578:        return 0;
        !           579:       if (GET_CODE (insn) == NOTE || GET_CODE (insn) == JUMP_INSN)
        !           580:        continue;
        !           581:       if (GET_CODE (insn) == CALL_INSN && ! call_used_regs[REGNO (op)])
        !           582:        continue;
        !           583:       if (GET_CODE (insn) != INSN)
        !           584:        return 0;
        !           585:       xinsn = PATTERN (insn);
        !           586: 
        !           587:       if (GET_CODE (xinsn) != SET)
        !           588:        return 0;
        !           589: 
        !           590:       xdest = SET_DEST (xinsn);
        !           591:       xsrc = SET_SRC (xinsn);
        !           592: 
        !           593:       if (GET_CODE (xdest) == SUBREG)
        !           594:        abort ();
        !           595: 
        !           596:       if ( ! REG_P (xdest))
        !           597:        continue;
        !           598: 
        !           599:       if (REGNO (op) == REGNO (xdest)
        !           600:          && ((GET_CODE (xsrc) == SIGN_EXTEND
        !           601:           && GET_MODE (XEXP (xsrc, 0)) == from_mode)
        !           602:          || (GET_CODE (xsrc) == MEM
        !           603:              && GET_MODE (xsrc) == from_mode)))
        !           604:        return 1;
        !           605: 
        !           606:       /* The register is modified by another operation.  */
        !           607:       if (reg_overlap_mentioned_p (xdest, op))
        !           608:        return 0;
        !           609:     }
        !           610: }
        !           611: 
        !           612: char *
        !           613: output_move_double (operands)
        !           614:      rtx *operands;
        !           615: {
        !           616:   if (GET_CODE (operands[1]) == CONST_DOUBLE)
        !           617:     {
        !           618:       if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT)
        !           619:        {
        !           620:          /* In an integer, the low-order word is in CONST_DOUBLE_LOW.  */
        !           621:          rtx const_op = operands[1];
        !           622:          if ((CONST_DOUBLE_HIGH (const_op) == 0
        !           623:               && CONST_DOUBLE_LOW (const_op) >= 0)
        !           624:              || (CONST_DOUBLE_HIGH (const_op) == -1
        !           625:                  && CONST_DOUBLE_LOW (const_op) < 0))
        !           626:            {
        !           627:              operands[1] = gen_rtx (CONST_INT, VOIDmode,
        !           628:                                     CONST_DOUBLE_LOW (const_op));
        !           629:              return "movl %1,%0";
        !           630:            }
        !           631:          operands[1] = gen_rtx (CONST_INT, VOIDmode,
        !           632:                                 CONST_DOUBLE_HIGH (const_op));
        !           633:          output_asm_insn ("movw %1,%0", operands);
        !           634:          operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
        !           635:          operands[1] = gen_rtx (CONST_INT, VOIDmode,
        !           636:                                 CONST_DOUBLE_LOW (const_op));
        !           637:          return "movw %1,%0";
        !           638:        }
        !           639:       else
        !           640:        {
        !           641:          /* In a real, the low-address word is in CONST_DOUBLE_LOW.  */
        !           642:          rtx const_op = operands[1];
        !           643:          if ((CONST_DOUBLE_LOW (const_op) == 0
        !           644:               && CONST_DOUBLE_HIGH (const_op) >= 0)
        !           645:              || (CONST_DOUBLE_LOW (const_op) == -1
        !           646:                  && CONST_DOUBLE_HIGH (const_op) < 0))
        !           647:            {
        !           648:              operands[1] = gen_rtx (CONST_INT, VOIDmode,
        !           649:                                     CONST_DOUBLE_HIGH (const_op));
        !           650:              return "movl %1,%0";
        !           651:            }
        !           652:          operands[1] = gen_rtx (CONST_INT, VOIDmode,
        !           653:                                 CONST_DOUBLE_LOW (const_op));
        !           654:          output_asm_insn ("movw %1,%0", operands);
        !           655:          operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
        !           656:          operands[1] = gen_rtx (CONST_INT, VOIDmode,
        !           657:                                 CONST_DOUBLE_HIGH (const_op));
        !           658:          return "movw %1,%0";
        !           659:        }
        !           660:     }
        !           661: 
        !           662:   return "movl %1,%0";
        !           663: }
        !           664: 
        !           665: /* Output a shift insns, after having reduced integer arguments to
        !           666:    avoid as warnings.  */
        !           667: 
        !           668: char *
        !           669: output_shift (pattern, op2, mod)
        !           670:      char *pattern;
        !           671:      rtx op2;
        !           672:      int mod;
        !           673: {
        !           674:   if (GET_CODE (op2) == CONST_INT)
        !           675:     {
        !           676:       int cnt = INTVAL (op2) % mod;
        !           677:       if (cnt == 0)
        !           678:        {
        !           679:          cc_status = cc_prev_status;
        !           680:          return "";
        !           681:        }
        !           682:       op2 = gen_rtx (CONST_INT, VOIDmode, cnt);
        !           683:     }
        !           684:   return pattern;
        !           685: }
        !           686: 
        !           687: /* Return non-zero if the code of this rtx pattern is a relop.  */
        !           688: 
        !           689: int
        !           690: relop (op, mode)
        !           691:      rtx op;
        !           692:      enum machine_mode mode;
        !           693: {
        !           694:   switch (GET_CODE (op))
        !           695:     {
        !           696:     case EQ:
        !           697:     case NE:
        !           698:     case LT:
        !           699:     case LE:
        !           700:     case GE:
        !           701:     case GT:
        !           702:     case LTU:
        !           703:     case LEU:
        !           704:     case GEU:
        !           705:     case GTU:
        !           706:       return 1;
        !           707:     }
        !           708:   return 0;
        !           709: }
        !           710: 
        !           711: void
        !           712: notice_update_cc (EXP, INSN)
        !           713:      rtx EXP, INSN;
        !           714: {
        !           715:   switch (GET_CODE (EXP))
        !           716:     {
        !           717:     case SET:
        !           718:       switch (GET_CODE (SET_DEST (EXP)))
        !           719:        {
        !           720:        case CC0:
        !           721:          cc_status.mdep = 0;
        !           722:          cc_status.flags = 0;
        !           723:          cc_status.value1 = 0;
        !           724:          cc_status.value2 = SET_SRC (EXP);
        !           725:          break;
        !           726: 
        !           727:        case PC:
        !           728:          break;
        !           729: 
        !           730:        case REG:
        !           731:          switch (GET_CODE (SET_SRC (EXP)))
        !           732:            {
        !           733:            case CALL:
        !           734:              goto call;
        !           735:            case MEM:
        !           736:              if (GET_MODE (SET_SRC (EXP)) == QImode
        !           737:                  || GET_MODE (SET_SRC (EXP)) == HImode)
        !           738:                {
        !           739:                  cc_status.mdep = 0;
        !           740:                  cc_status.flags = CC_NO_OVERFLOW;
        !           741:                  cc_status.value1 = SET_DEST (EXP);
        !           742:                  cc_status.value2 = SET_SRC (EXP);
        !           743:                  break;
        !           744:                }
        !           745:              /* else: Fall through.  */
        !           746:            case CONST_INT:
        !           747:            case SYMBOL_REF:
        !           748:            case LABEL_REF:
        !           749:            case CONST:
        !           750:            case CONST_DOUBLE:
        !           751:            case REG:
        !           752:              if (cc_status.value1
        !           753:                  && reg_overlap_mentioned_p (SET_DEST (EXP),
        !           754:                                              cc_status.value1))
        !           755:                cc_status.value1 = 0;
        !           756:              if (cc_status.value2
        !           757:                  && reg_overlap_mentioned_p (SET_DEST (EXP),
        !           758:                                              cc_status.value2))
        !           759:                cc_status.value2 = 0;
        !           760:              break;
        !           761: 
        !           762:            case UDIV:
        !           763:            case UMOD:
        !           764:              cc_status.mdep = CC_VALID_FOR_UNSIGNED;
        !           765:              cc_status.flags = CC_NO_OVERFLOW;
        !           766:              cc_status.value1 = SET_DEST (EXP);
        !           767:              cc_status.value2 = SET_SRC (EXP);
        !           768:              break;
        !           769:            default:
        !           770:              cc_status.mdep = 0;
        !           771:              cc_status.flags = CC_NO_OVERFLOW;
        !           772:              cc_status.value1 = SET_DEST (EXP);
        !           773:              cc_status.value2 = SET_SRC (EXP);
        !           774:              break;
        !           775:            }
        !           776:          break;
        !           777: 
        !           778:        case MEM:
        !           779:          switch (GET_CODE (SET_SRC (EXP)))
        !           780:            {
        !           781:            case REG:
        !           782:              if (GET_MODE (SET_SRC (EXP)) == QImode
        !           783:                  || GET_MODE (SET_SRC (EXP)) == HImode)
        !           784:                {
        !           785:                  cc_status.flags = CC_NO_OVERFLOW;
        !           786:                  cc_status.value1 = SET_DEST (EXP);
        !           787:                  cc_status.value2 = SET_SRC (EXP);
        !           788:                  cc_status.mdep = 0;
        !           789:                  break;
        !           790:                }
        !           791:              /* else: Fall through.  */
        !           792:            case CONST_INT:
        !           793:            case SYMBOL_REF:
        !           794:            case LABEL_REF:
        !           795:            case CONST:
        !           796:            case CONST_DOUBLE:
        !           797:            case MEM:
        !           798:              /* Need to forget cc_status about memory positions each
        !           799:                 time a memory store is made, even if the memory store
        !           800:                 insns in question doesn't modify the condition codes.  */
        !           801:              if (cc_status.value1 &&
        !           802:                  GET_CODE (cc_status.value1) == MEM)
        !           803:                cc_status.value1 = 0;
        !           804:              if (cc_status.value2 &&
        !           805:                  GET_CODE (cc_status.value2) == MEM)
        !           806:                cc_status.value2 = 0;
        !           807:              break;
        !           808:            case SIGN_EXTEND:
        !           809:            case FLOAT_EXTEND:
        !           810:            case FLOAT_TRUNCATE:
        !           811:            case FLOAT:
        !           812:            case FIX:
        !           813:              cc_status.flags = CC_NO_OVERFLOW;
        !           814:              cc_status.value1 = SET_DEST (EXP);
        !           815:              cc_status.value2 = SET_SRC (EXP);
        !           816:              cc_status.mdep = 0;
        !           817:              break;
        !           818: 
        !           819:            default:
        !           820:              abort ();
        !           821:            }
        !           822:          break;
        !           823: 
        !           824:        default:
        !           825:          abort ();
        !           826:        }
        !           827:       break;
        !           828: 
        !           829:     case CALL:
        !           830:     call:
        !           831:       CC_STATUS_INIT;
        !           832:       break;
        !           833:       /* Do calls preserve the condition codes?  (At least forget
        !           834:         cc_status expressions if they refer to registers
        !           835:         not preserved across calls.  Also forget expressions
        !           836:         about memory contents.)  */
        !           837:       if (cc_status.value1
        !           838:          && (refers_to_regno_p (PYR_TREG (0), PYR_TREG (15),
        !           839:                                 cc_status.value1, 0)
        !           840:              || GET_CODE (cc_status.value1) == MEM))
        !           841:        cc_status.value1 = 0;
        !           842:       if (cc_status.value2
        !           843:          && (refers_to_regno_p (PYR_TREG (0), PYR_TREG (15),
        !           844:                                 cc_status.value2, 0)
        !           845:              || GET_CODE (cc_status.value2) == MEM))
        !           846:        cc_status.value2 = 0;
        !           847:       break;
        !           848: 
        !           849:     default:
        !           850:       CC_STATUS_INIT;
        !           851:     }
        !           852: }
        !           853: 
        !           854: void
        !           855: forget_cc_if_dependent (op)
        !           856:      rtx op;
        !           857: {
        !           858:   cc_status = cc_prev_status;
        !           859:   if (cc_status.value1 && reg_overlap_mentioned_p (op, cc_status.value1))
        !           860:     cc_status.value1 = 0;
        !           861:   if (cc_status.value2 && reg_overlap_mentioned_p (op, cc_status.value2))
        !           862:     cc_status.value2 = 0;
        !           863: }

unix.superglobalmegacorp.com

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