Annotation of GNUtools/cc/config/pyr/pyr.c, revision 1.1.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.