Annotation of gcc/config/pyr/pyr.c, revision 1.1.1.2

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

unix.superglobalmegacorp.com

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