Annotation of gcc/config/i860.c, revision 1.1.1.3

1.1       root        1: /* Subroutines for insn-output.c for Intel 860
                      2:    Copyright (C) 1989, 1991 Free Software Foundation, Inc.
                      3:    Derived from sparc.c.
                      4: 
                      5:    Written by Richard Stallman ([email protected]).
                      6: 
                      7:    Hacked substantially by Ron Guilmette ([email protected]) to cater
                      8:    to the whims of the System V Release 4 assembler.
                      9: 
                     10: This file is part of GNU CC.
                     11: 
                     12: GNU CC is free software; you can redistribute it and/or modify
                     13: it under the terms of the GNU General Public License as published by
                     14: the Free Software Foundation; either version 2, or (at your option)
                     15: any later version.
                     16: 
                     17: GNU CC is distributed in the hope that it will be useful,
                     18: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     19: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     20: GNU General Public License for more details.
                     21: 
                     22: You should have received a copy of the GNU General Public License
                     23: along with GNU CC; see the file COPYING.  If not, write to
                     24: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
                     25: 
                     26: 
                     27: #include "config.h"
                     28: #include "flags.h"
                     29: #include "rtl.h"
                     30: #include "regs.h"
                     31: #include "hard-reg-set.h"
                     32: #include "real.h"
                     33: #include "insn-config.h"
                     34: #include "conditions.h"
                     35: #include "insn-flags.h"
                     36: #include "output.h"
                     37: #include "recog.h"
                     38: #include "insn-attr.h"
                     39: 
                     40: #include <stdio.h>
                     41: 
                     42: static rtx find_addr_reg ();
                     43: 
                     44: #ifndef I860_REG_PREFIX
                     45: #define I860_REG_PREFIX ""
                     46: #endif
                     47: 
                     48: char *i860_reg_prefix = I860_REG_PREFIX;
                     49: 
                     50: /* Save information from a "cmpxx" operation until the branch is emitted.  */
                     51: 
                     52: rtx i860_compare_op0, i860_compare_op1;
                     53: 
                     54: /* Return non-zero if this pattern, can be evaluated safely, even if it
                     55:    was not asked for.  */
                     56: int
                     57: safe_insn_src_p (op, mode)
                     58:      rtx op;
                     59:      enum machine_mode mode;
                     60: {
                     61:   /* Just experimenting.  */
                     62: 
                     63:   /* No floating point src is safe if it contains an arithmetic
                     64:      operation, since that operation may trap.  */
                     65:   switch (GET_CODE (op))
                     66:     {
                     67:     case CONST_INT:
                     68:     case LABEL_REF:
                     69:     case SYMBOL_REF:
                     70:     case CONST:
                     71:       return 1;
                     72: 
                     73:     case REG:
                     74:       return 1;
                     75: 
                     76:     case MEM:
                     77:       return CONSTANT_ADDRESS_P (XEXP (op, 0));
                     78: 
                     79:       /* We never need to negate or complement constants.  */
                     80:     case NEG:
                     81:       return (mode != SFmode && mode != DFmode);
                     82:     case NOT:
                     83:     case ZERO_EXTEND:
                     84:       return 1;
                     85: 
                     86:     case EQ:
                     87:     case NE:
                     88:     case LT:
                     89:     case GT:
                     90:     case LE:
                     91:     case GE:
                     92:     case LTU:
                     93:     case GTU:
                     94:     case LEU:
                     95:     case GEU:
                     96:     case MINUS:
                     97:     case PLUS:
                     98:       return (mode != SFmode && mode != DFmode);
                     99:     case AND:
                    100:     case IOR:
                    101:     case XOR:
                    102:     case LSHIFT:
                    103:     case ASHIFT:
                    104:     case ASHIFTRT:
                    105:     case LSHIFTRT:
                    106:       if ((GET_CODE (XEXP (op, 0)) == CONST_INT && ! SMALL_INT (XEXP (op, 0)))
                    107:          || (GET_CODE (XEXP (op, 1)) == CONST_INT && ! SMALL_INT (XEXP (op, 1))))
                    108:        return 0;
                    109:       return 1;
                    110: 
                    111:     default:
                    112:       return 0;
                    113:     }
                    114: }
                    115: 
                    116: /* Return 1 if REG is clobbered in IN.
                    117:    Return 2 if REG is used in IN. 
                    118:    Return 3 if REG is both used and clobbered in IN.
                    119:    Return 0 if neither.  */
                    120: 
                    121: static int
                    122: reg_clobbered_p (reg, in)
                    123:      rtx reg;
                    124:      rtx in;
                    125: {
                    126:   register enum rtx_code code;
                    127: 
                    128:   if (in == 0)
                    129:     return 0;
                    130: 
                    131:   code = GET_CODE (in);
                    132: 
                    133:   if (code == SET || code == CLOBBER)
                    134:     {
                    135:       rtx dest = SET_DEST (in);
                    136:       int set = 0;
                    137:       int used = 0;
                    138: 
                    139:       while (GET_CODE (dest) == STRICT_LOW_PART
                    140:             || GET_CODE (dest) == SUBREG
                    141:             || GET_CODE (dest) == SIGN_EXTRACT
                    142:             || GET_CODE (dest) == ZERO_EXTRACT)
                    143:        dest = XEXP (dest, 0);
                    144: 
                    145:       if (dest == reg)
                    146:        set = 1;
                    147:       else if (GET_CODE (dest) == REG
                    148:               && refers_to_regno_p (REGNO (reg),
                    149:                                     REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
                    150:                                     SET_DEST (in), 0))
                    151:        {
                    152:          set = 1;
                    153:          /* Anything that sets just part of the register
                    154:             is considered using as well as setting it.
                    155:             But note that a straight SUBREG of a single-word value
                    156:             clobbers the entire value.   */
                    157:          if (dest != SET_DEST (in)
                    158:              && ! (GET_CODE (SET_DEST (in)) == SUBREG
                    159:                    || UNITS_PER_WORD >= GET_MODE_SIZE (GET_MODE (dest))))
                    160:            used = 1;
                    161:        }
                    162: 
                    163:       if (code == SET)
                    164:        {
                    165:          if (set)
                    166:            used = refers_to_regno_p (REGNO (reg),
                    167:                                      REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
                    168:                                      SET_SRC (in), 0);
                    169:          else
                    170:            used = refers_to_regno_p (REGNO (reg),
                    171:                                      REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
                    172:                                      in, 0);
                    173:        }
                    174: 
                    175:       return set + used * 2;
                    176:     }
                    177: 
                    178:   if (refers_to_regno_p (REGNO (reg),
                    179:                         REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
                    180:                         in, 0))
                    181:     return 2;
                    182:   return 0;
                    183: }
                    184: 
                    185: /* Return non-zero if OP can be written to without screwing up
                    186:    GCC's model of what's going on.  It is assumed that this operand
                    187:    appears in the dest position of a SET insn in a conditional
                    188:    branch's delay slot.  AFTER is the label to start looking from.  */
                    189: int
                    190: operand_clobbered_before_used_after (op, after)
                    191:      rtx op;
                    192:      rtx after;
                    193: {
                    194:   /* Just experimenting.  */
                    195:   if (GET_CODE (op) == CC0)
                    196:     return 1;
                    197:   if (GET_CODE (op) == REG)
                    198:     {
                    199:       rtx insn;
                    200: 
                    201:       if (op == stack_pointer_rtx)
                    202:        return 0;
                    203: 
                    204:       /* Scan forward from the label, to see if the value of OP
                    205:         is clobbered before the first use.  */
                    206: 
                    207:       for (insn = NEXT_INSN (after); insn; insn = NEXT_INSN (insn))
                    208:        {
                    209:          if (GET_CODE (insn) == NOTE)
                    210:            continue;
                    211:          if (GET_CODE (insn) == INSN
                    212:              || GET_CODE (insn) == JUMP_INSN
                    213:              || GET_CODE (insn) == CALL_INSN)
                    214:            {
                    215:              switch (reg_clobbered_p (op, PATTERN (insn)))
                    216:                {
                    217:                default:
                    218:                  return 0;
                    219:                case 1:
                    220:                  return 1;
                    221:                case 0:
                    222:                  break;
                    223:                }
                    224:            }
                    225:          /* If we reach another label without clobbering OP,
                    226:             then we cannot safely write it here.  */
                    227:          else if (GET_CODE (insn) == CODE_LABEL)
                    228:            return 0;
                    229:          if (GET_CODE (insn) == JUMP_INSN)
                    230:            {
                    231:              if (condjump_p (insn))
                    232:                return 0;
                    233:              /* This is a jump insn which has already
                    234:                 been mangled.  We can't tell what it does.  */
                    235:              if (GET_CODE (PATTERN (insn)) == PARALLEL)
                    236:                return 0;
                    237:              if (! JUMP_LABEL (insn))
                    238:                return 0;
                    239:              /* Keep following jumps.  */
                    240:              insn = JUMP_LABEL (insn);
                    241:            }
                    242:        }
                    243:       return 1;
                    244:     }
                    245: 
                    246:   /* In both of these cases, the first insn executed
                    247:      for this op will be a orh whatever%h,%?r0,%?r31,
                    248:      which is tolerable.  */
                    249:   if (GET_CODE (op) == MEM)
                    250:     return (CONSTANT_ADDRESS_P (XEXP (op, 0)));
                    251: 
                    252:   return 0;
                    253: }
                    254: 
                    255: /* Return non-zero if this pattern, as a source to a "SET",
                    256:    is known to yield an instruction of unit size.  */
                    257: int
                    258: single_insn_src_p (op, mode)
                    259:      rtx op;
                    260:      enum machine_mode mode;
                    261: {
                    262:   switch (GET_CODE (op))
                    263:     {
                    264:     case CONST_INT:
                    265:       /* This is not always a single insn src, technically,
                    266:         but output_delayed_branch knows how to deal with it.  */
                    267:       return 1;
                    268: 
                    269:     case SYMBOL_REF:
                    270:     case CONST:
                    271:       /* This is not a single insn src, technically,
                    272:         but output_delayed_branch knows how to deal with it.  */
                    273:       return 1;
                    274: 
                    275:     case REG:
                    276:       return 1;
                    277: 
                    278:     case MEM:
                    279:       return 1;
                    280: 
                    281:       /* We never need to negate or complement constants.  */
                    282:     case NEG:
                    283:       return (mode != DFmode);
                    284:     case NOT:
                    285:     case ZERO_EXTEND:
                    286:       return 1;
                    287: 
                    288:     case PLUS:
                    289:     case MINUS:
                    290:       /* Detect cases that require multiple instructions.  */
                    291:       if (CONSTANT_P (XEXP (op, 1))
                    292:          && !(GET_CODE (XEXP (op, 1)) == CONST_INT
                    293:               && SMALL_INT (XEXP (op, 1))))
                    294:        return 0;
                    295:     case EQ:
                    296:     case NE:
                    297:     case LT:
                    298:     case GT:
                    299:     case LE:
                    300:     case GE:
                    301:     case LTU:
                    302:     case GTU:
                    303:     case LEU:
                    304:     case GEU:
                    305:       /* Not doing floating point, since they probably
                    306:         take longer than the branch slot they might fill.  */
                    307:       return (mode != SFmode && mode != DFmode);
                    308: 
                    309:     case AND:
                    310:       if (GET_CODE (XEXP (op, 1)) == NOT)
                    311:        {
                    312:          rtx arg = XEXP (XEXP (op, 1), 0);
                    313:          if (CONSTANT_P (arg)
                    314:              && !(GET_CODE (arg) == CONST_INT
                    315:                   && (SMALL_INT (arg)
                    316:                       || INTVAL (arg) & 0xffff == 0)))
                    317:            return 0;
                    318:        }
                    319:     case IOR:
                    320:     case XOR:
                    321:       /* Both small and round numbers take one instruction;
                    322:         others take two.  */
                    323:       if (CONSTANT_P (XEXP (op, 1))
                    324:          && !(GET_CODE (XEXP (op, 1)) == CONST_INT
                    325:               && (SMALL_INT (XEXP (op, 1))
                    326:                   || INTVAL (XEXP (op, 1)) & 0xffff == 0)))
                    327:        return 0;
                    328: 
                    329:     case LSHIFT:
                    330:     case ASHIFT:
                    331:     case ASHIFTRT:
                    332:     case LSHIFTRT:
                    333:       return 1;
                    334: 
                    335:     case SUBREG:
                    336:       if (SUBREG_WORD (op) != 0)
                    337:        return 0;
                    338:       return single_insn_src_p (SUBREG_REG (op), mode);
                    339: 
                    340:       /* Not doing floating point, since they probably
                    341:         take longer than the branch slot they might fill.  */
                    342:     case FLOAT_EXTEND:
                    343:     case FLOAT_TRUNCATE:
                    344:     case FLOAT:
                    345:     case FIX:
                    346:     case UNSIGNED_FLOAT:
                    347:     case UNSIGNED_FIX:
                    348:       return 0;
                    349: 
                    350:     default:
                    351:       return 0;
                    352:     }
                    353: }
                    354: 
                    355: /* Nonzero only if this *really* is a single insn operand.  */
                    356: int
                    357: strict_single_insn_op_p (op, mode)
                    358:      rtx op;
                    359:      enum machine_mode mode;
                    360: {
                    361:   if (mode == VOIDmode)
                    362:     mode = GET_MODE (op);
                    363: 
                    364:   switch (GET_CODE (op))
                    365:     {
                    366:     case CC0:
                    367:       return 1;
                    368: 
                    369:     case CONST_INT:
                    370:       if (SMALL_INT (op))
                    371:        return 1;
                    372:       /* We can put this set insn into delay slot, because this is one
                    373:         insn; `orh'.  */
                    374:       if ((INTVAL (op) & 0xffff) == 0)
                    375:        return 1;
                    376:       return 0;
                    377: 
                    378:     case SYMBOL_REF:
                    379:       return 0;
                    380: 
                    381:     case REG:
                    382: #if 0
                    383:       /* This loses when moving an freg to a general reg.  */
                    384:       return HARD_REGNO_NREGS (REGNO (op), mode) == 1;
                    385: #endif
                    386:       return (mode != DFmode && mode != DImode);
                    387: 
                    388:     case MEM:
                    389:       if (! CONSTANT_ADDRESS_P (XEXP (op, 0)))
                    390:        return (mode != DFmode && mode != DImode);
                    391:       return 0;
                    392: 
                    393:       /* We never need to negate or complement constants.  */
                    394:     case NEG:
                    395:       return (mode != DFmode);
                    396:     case NOT:
                    397:     case ZERO_EXTEND:
                    398:       return 1;
                    399: 
                    400:     case PLUS:
                    401:     case MINUS:
                    402:       /* Detect cases that require multiple instructions.  */
                    403:       if (CONSTANT_P (XEXP (op, 1))
                    404:          && !(GET_CODE (XEXP (op, 1)) == CONST_INT
                    405:               && SMALL_INT (XEXP (op, 1))))
                    406:        return 0;
                    407:     case EQ:
                    408:     case NE:
                    409:     case LT:
                    410:     case GT:
                    411:     case LE:
                    412:     case GE:
                    413:     case LTU:
                    414:     case GTU:
                    415:     case LEU:
                    416:     case GEU:
                    417:       return 1;
                    418: 
                    419:     case AND:
                    420:       if (GET_CODE (XEXP (op, 1)) == NOT)
                    421:        {
                    422:          rtx arg = XEXP (XEXP (op, 1), 0);
                    423:          if (CONSTANT_P (arg)
                    424:              && !(GET_CODE (arg) == CONST_INT
                    425:                   && (SMALL_INT (arg)
                    426:                       || INTVAL (arg) & 0xffff == 0)))
                    427:            return 0;
                    428:        }
                    429:     case IOR:
                    430:     case XOR:
                    431:       /* Both small and round numbers take one instruction;
                    432:         others take two.  */
                    433:       if (CONSTANT_P (XEXP (op, 1))
                    434:          && !(GET_CODE (XEXP (op, 1)) == CONST_INT
                    435:               && (SMALL_INT (XEXP (op, 1))
                    436:                   || INTVAL (XEXP (op, 1)) & 0xffff == 0)))
                    437:        return 0;
                    438: 
                    439:     case LSHIFT:
                    440:     case ASHIFT:
                    441:     case ASHIFTRT:
                    442:     case LSHIFTRT:
                    443:       return 1;
                    444: 
                    445:     case SUBREG:
                    446:       if (SUBREG_WORD (op) != 0)
                    447:        return 0;
                    448:       return strict_single_insn_op_p (SUBREG_REG (op), mode);
                    449: 
                    450:     case SIGN_EXTEND:
                    451:       if (GET_CODE (XEXP (op, 0)) == MEM
                    452:          && ! CONSTANT_ADDRESS_P (XEXP (XEXP (op, 0), 0)))
                    453:        return 1;
                    454:       return 0;
                    455: 
                    456:       /* Not doing floating point, since they probably
                    457:         take longer than the branch slot they might fill.  */
                    458:     case FLOAT_EXTEND:
                    459:     case FLOAT_TRUNCATE:
                    460:     case FLOAT:
                    461:     case FIX:
                    462:     case UNSIGNED_FLOAT:
                    463:     case UNSIGNED_FIX:
                    464:       return 0;
                    465: 
                    466:     default:
                    467:       return 0;
                    468:     }
                    469: }
                    470: 
                    471: /* Return truth value of whether OP is a relational operator.  */
                    472: int
                    473: relop (op, mode)
                    474:      rtx op;
                    475:      enum machine_mode mode;
                    476: {
                    477:   switch (GET_CODE (op))
                    478:     {
                    479:     case EQ:
                    480:     case NE:
                    481:     case GT:
                    482:     case GE:
                    483:     case LT:
                    484:     case LE:
                    485:     case GTU:
                    486:     case GEU:
                    487:     case LTU:
                    488:     case LEU:
                    489:       return 1;
                    490:     }
                    491:   return 0;
                    492: }
                    493: 
                    494: /* Return non-zero only if OP is a register of mode MODE,
                    495:    or const0_rtx.  */
                    496: int
                    497: reg_or_0_operand (op, mode)
                    498:      rtx op;
                    499:      enum machine_mode mode;
                    500: {
                    501:   return (op == const0_rtx || register_operand (op, mode)
                    502:          || op == CONST0_RTX (mode));
                    503: }
                    504: 
                    505: /* Return truth value of whether OP can be used as an operands in a three
                    506:    address add/subtract insn (such as add %o1,7,%l2) of mode MODE.  */
                    507: 
                    508: int
                    509: arith_operand (op, mode)
                    510:      rtx op;
                    511:      enum machine_mode mode;
                    512: {
                    513:   return (register_operand (op, mode)
                    514:          || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
                    515: }
                    516: 
                    517: /* Return 1 if OP is a valid first operand for a logical insn of mode MODE.  */
                    518: 
                    519: int
                    520: logic_operand (op, mode)
                    521:      rtx op;
                    522:      enum machine_mode mode;
                    523: {
                    524:   return (register_operand (op, mode)
                    525:          || (GET_CODE (op) == CONST_INT && LOGIC_INT (op)));
                    526: }
                    527: 
                    528: /* Return 1 if OP is a valid first operand for a shift insn of mode MODE.  */
                    529: 
                    530: int
                    531: shift_operand (op, mode)
                    532:      rtx op;
                    533:      enum machine_mode mode;
                    534: {
                    535:   return (register_operand (op, mode)
                    536:           || (GET_CODE (op) == CONST_INT));
                    537: }
                    538: 
                    539: /* Return 1 if OP is a valid first operand for either a logical insn
                    540:    or an add insn of mode MODE.  */
                    541: 
                    542: int
                    543: compare_operand (op, mode)
                    544:      rtx op;
                    545:      enum machine_mode mode;
                    546: {
                    547:   return (register_operand (op, mode)
                    548:          || (GET_CODE (op) == CONST_INT && SMALL_INT (op) && LOGIC_INT (op)));
                    549: }
                    550: 
                    551: /* Return truth value of whether OP can be used as the 5-bit immediate
                    552:    operand of a bte or btne insn.  */
                    553: 
                    554: int
                    555: bte_operand (op, mode)
                    556:      rtx op;
                    557:      enum machine_mode mode;
                    558: {
                    559:   return (register_operand (op, mode)
                    560:          || (GET_CODE (op) == CONST_INT
                    561:              && (unsigned) INTVAL (op) < 0x20));
                    562: }
                    563: 
                    564: /* Return 1 if OP is an indexed memory reference of mode MODE.  */
                    565: 
                    566: int
                    567: indexed_operand (op, mode)
                    568:      rtx op;
                    569:      enum machine_mode mode;
                    570: {
                    571:   return (GET_CODE (op) == MEM && GET_MODE (op) == mode
                    572:          && GET_CODE (XEXP (op, 0)) == PLUS
                    573:          && GET_MODE (XEXP (op, 0)) == SImode
                    574:          && register_operand (XEXP (XEXP (op, 0), 0), SImode)
                    575:          && register_operand (XEXP (XEXP (op, 0), 1), SImode));
                    576: }
                    577: 
                    578: /* Return 1 if OP is a suitable source operand for a load insn
                    579:    with mode MODE.  */
                    580: 
                    581: int
                    582: load_operand (op, mode)
                    583:      rtx op;
                    584:      enum machine_mode mode;
                    585: {
                    586:   return (memory_operand (op, mode) || indexed_operand (op, mode));
                    587: }
                    588: 
                    589: /* Return truth value of whether OP is a integer which fits the
                    590:    range constraining immediate operands in add/subtract insns.  */
                    591: 
                    592: int
                    593: small_int (op, mode)
                    594:      rtx op;
                    595:      enum machine_mode mode;
                    596: {
                    597:   return (GET_CODE (op) == CONST_INT && SMALL_INT (op));
                    598: }
                    599: 
                    600: /* Return truth value of whether OP is a integer which fits the
                    601:    range constraining immediate operands in logic insns.  */
                    602: 
                    603: int
                    604: logic_int (op, mode)
                    605:      rtx op;
                    606:      enum machine_mode mode;
                    607: {
                    608:   return (GET_CODE (op) == CONST_INT && LOGIC_INT (op));
                    609: }
                    610: 
                    611: /* Return the best assembler insn template
                    612:    for moving operands[1] into operands[0] as a fullword.  */
                    613: 
                    614: static char *
                    615: singlemove_string (operands)
                    616:      rtx *operands;
                    617: {
                    618:   if (GET_CODE (operands[0]) == MEM)
                    619:     {
                    620:       if (GET_CODE (operands[1]) != MEM)
                    621:        if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
                    622:          {
                    623:            if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
                    624:                   && (cc_prev_status.flags & CC_HI_R31_ADJ)
                    625:                   && cc_prev_status.mdep == XEXP (operands[0], 0)))
                    626:              {
                    627:                CC_STATUS_INIT;
                    628:                output_asm_insn ("orh %h0,%?r0,%?r31", operands);
                    629:              }
                    630:            cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
                    631:            cc_status.mdep = XEXP (operands[0], 0);
                    632:            return "st.l %r1,%L0(%?r31)";
                    633:          }
                    634:        else
                    635:          return "st.l %r1,%0";
                    636:       else
                    637:        abort ();
                    638: #if 0
                    639:        {
                    640:          rtx xoperands[2];
                    641: 
                    642:          cc_status.flags &= ~CC_F0_IS_0;
                    643:          xoperands[0] = gen_rtx (REG, SFmode, 32);
                    644:          xoperands[1] = operands[1];
                    645:          output_asm_insn (singlemove_string (xoperands), xoperands);
                    646:          xoperands[1] = xoperands[0];
                    647:          xoperands[0] = operands[0];
                    648:          output_asm_insn (singlemove_string (xoperands), xoperands);
                    649:          return "";
                    650:        }
                    651: #endif
                    652:     }
                    653:   if (GET_CODE (operands[1]) == MEM)
                    654:     {
                    655:       if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
                    656:        {
                    657:          if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
                    658:                 && (cc_prev_status.flags & CC_HI_R31_ADJ)
                    659:                 && cc_prev_status.mdep == XEXP (operands[1], 0)))
                    660:            {
                    661:              CC_STATUS_INIT;
                    662:              output_asm_insn ("orh %h1,%?r0,%?r31", operands);
                    663:            }
                    664:          cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
                    665:          cc_status.mdep = XEXP (operands[1], 0);
                    666:          return "ld.l %L1(%?r31),%0";
                    667:        }
                    668:       return "ld.l %m1,%0";
                    669:     }
                    670:  if (GET_CODE (operands[1]) == CONST_INT)
                    671:    {
1.1.1.3 ! root      672:      if (operands[1] == const0_rtx)
        !           673:       return "mov %?r0,%0";
1.1       root      674:      if((INTVAL (operands[1]) & 0xffff0000) == 0)
                    675:       return "or %L1,%?r0,%0";
1.1.1.3 ! root      676:      if((INTVAL (operands[1]) & 0xffff8000) == 0xffff8000)
        !           677:       return "adds %1,%?r0,%0";
1.1       root      678:      if((INTVAL (operands[1]) & 0x0000ffff) == 0)
                    679:       return "orh %H1,%?r0,%0";
                    680:    }
                    681:   return "mov %1,%0";
                    682: }
                    683: 
                    684: /* Output assembler code to perform a doubleword move insn
                    685:    with operands OPERANDS.  */
                    686: 
                    687: char *
                    688: output_move_double (operands)
                    689:      rtx *operands;
                    690: {
                    691:   enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
                    692:   rtx latehalf[2];
                    693:   rtx addreg0 = 0, addreg1 = 0;
                    694: 
                    695:   /* First classify both operands.  */
                    696: 
                    697:   if (REG_P (operands[0]))
                    698:     optype0 = REGOP;
                    699:   else if (offsettable_memref_p (operands[0]))
                    700:     optype0 = OFFSOP;
                    701:   else if (GET_CODE (operands[0]) == MEM)
                    702:     optype0 = MEMOP;
                    703:   else
                    704:     optype0 = RNDOP;
                    705: 
                    706:   if (REG_P (operands[1]))
                    707:     optype1 = REGOP;
                    708:   else if (CONSTANT_P (operands[1]))
                    709:     optype1 = CNSTOP;
                    710:   else if (offsettable_memref_p (operands[1]))
                    711:     optype1 = OFFSOP;
                    712:   else if (GET_CODE (operands[1]) == MEM)
                    713:     optype1 = MEMOP;
                    714:   else
                    715:     optype1 = RNDOP;
                    716: 
                    717:   /* Check for the cases that the operand constraints are not
                    718:      supposed to allow to happen.  Abort if we get one,
                    719:      because generating code for these cases is painful.  */
                    720: 
                    721:   if (optype0 == RNDOP || optype1 == RNDOP)
                    722:     abort ();
                    723: 
                    724:   /* If an operand is an unoffsettable memory ref, find a register
                    725:      we can increment temporarily to make it refer to the second word.  */
                    726: 
                    727:   if (optype0 == MEMOP)
                    728:     addreg0 = find_addr_reg (XEXP (operands[0], 0));
                    729: 
                    730:   if (optype1 == MEMOP)
                    731:     addreg1 = find_addr_reg (XEXP (operands[1], 0));
                    732: 
                    733: /* ??? Perhaps in some cases move double words
                    734:    if there is a spare pair of floating regs.  */
                    735: 
                    736:   /* Ok, we can do one word at a time.
                    737:      Normally we do the low-numbered word first,
                    738:      but if either operand is autodecrementing then we
                    739:      do the high-numbered word first.
                    740: 
                    741:      In either case, set up in LATEHALF the operands to use
                    742:      for the high-numbered word and in some cases alter the
                    743:      operands in OPERANDS to be suitable for the low-numbered word.  */
                    744: 
                    745:   if (optype0 == REGOP)
                    746:     latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
                    747:   else if (optype0 == OFFSOP)
                    748:     latehalf[0] = adj_offsettable_operand (operands[0], 4);
                    749:   else
                    750:     latehalf[0] = operands[0];
                    751: 
                    752:   if (optype1 == REGOP)
                    753:     latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
                    754:   else if (optype1 == OFFSOP)
                    755:     latehalf[1] = adj_offsettable_operand (operands[1], 4);
                    756:   else if (optype1 == CNSTOP)
                    757:     {
                    758:       if (GET_CODE (operands[1]) == CONST_DOUBLE)
                    759:        split_double (operands[1], &operands[1], &latehalf[1]);
                    760:       else if (CONSTANT_P (operands[1]))
                    761:        latehalf[1] = const0_rtx;
                    762:     }
                    763:   else
                    764:     latehalf[1] = operands[1];
                    765: 
                    766:   /* If the first move would clobber the source of the second one,
                    767:      do them in the other order.
                    768: 
                    769:      RMS says "This happens only for registers;
                    770:      such overlap can't happen in memory unless the user explicitly
                    771:      sets it up, and that is an undefined circumstance."
                    772: 
                    773:      but it happens on the sparc when loading parameter registers,
                    774:      so I am going to define that circumstance, and make it work
                    775:      as expected.  */
                    776: 
                    777:   if (optype0 == REGOP && optype1 == REGOP
                    778:       && REGNO (operands[0]) == REGNO (latehalf[1]))
                    779:     {
                    780:       CC_STATUS_PARTIAL_INIT;
                    781:       /* Make any unoffsettable addresses point at high-numbered word.  */
                    782:       if (addreg0)
                    783:        output_asm_insn ("adds 0x4,%0,%0", &addreg0);
                    784:       if (addreg1)
                    785:        output_asm_insn ("adds 0x4,%0,%0", &addreg1);
                    786: 
                    787:       /* Do that word.  */
                    788:       output_asm_insn (singlemove_string (latehalf), latehalf);
                    789: 
                    790:       /* Undo the adds we just did.  */
                    791:       if (addreg0)
                    792:        output_asm_insn ("adds -0x4,%0,%0", &addreg0);
                    793:       if (addreg1)
                    794:        output_asm_insn ("adds -0x4,%0,%0", &addreg1);
                    795: 
                    796:       /* Do low-numbered word.  */
                    797:       return singlemove_string (operands);
                    798:     }
                    799:   else if (optype0 == REGOP && optype1 != REGOP
                    800:           && reg_overlap_mentioned_p (operands[0], operands[1]))
                    801:     {
                    802:       /* Do the late half first.  */
                    803:       output_asm_insn (singlemove_string (latehalf), latehalf);
                    804:       /* Then clobber.  */
                    805:       return singlemove_string (operands);
                    806:     }
                    807: 
                    808:   /* Normal case: do the two words, low-numbered first.  */
                    809: 
                    810:   output_asm_insn (singlemove_string (operands), operands);
                    811: 
                    812:   CC_STATUS_PARTIAL_INIT;
                    813:   /* Make any unoffsettable addresses point at high-numbered word.  */
                    814:   if (addreg0)
                    815:     output_asm_insn ("adds 0x4,%0,%0", &addreg0);
                    816:   if (addreg1)
                    817:     output_asm_insn ("adds 0x4,%0,%0", &addreg1);
                    818: 
                    819:   /* Do that word.  */
                    820:   output_asm_insn (singlemove_string (latehalf), latehalf);
                    821: 
                    822:   /* Undo the adds we just did.  */
                    823:   if (addreg0)
                    824:     output_asm_insn ("adds -0x4,%0,%0", &addreg0);
                    825:   if (addreg1)
                    826:     output_asm_insn ("adds -0x4,%0,%0", &addreg1);
                    827: 
                    828:   return "";
                    829: }
                    830: 
                    831: char *
                    832: output_fp_move_double (operands)
                    833:      rtx *operands;
                    834: {
                    835:   /* If the source operand is any sort of zero, use f0 instead.  */
                    836: 
                    837:   if (operands[1] == CONST0_RTX (GET_MODE (operands[1])))
                    838:     operands[1] = gen_rtx (REG, DFmode, F0_REGNUM);
                    839: 
                    840:   if (FP_REG_P (operands[0]))
                    841:     {
                    842:       if (FP_REG_P (operands[1]))
                    843:        return "fmov.dd %1,%0";
                    844:       if (GET_CODE (operands[1]) == REG)
                    845:        {
                    846:          output_asm_insn ("ixfr %1,%0", operands);
                    847:          operands[0] = gen_rtx (REG, VOIDmode, REGNO (operands[0]) + 1);
                    848:          operands[1] = gen_rtx (REG, VOIDmode, REGNO (operands[1]) + 1);
                    849:          return "ixfr %1,%0";
                    850:        }
                    851:       if (operands[1] == CONST0_RTX (DFmode))
                    852:        return "fmov.dd f0,%0";
                    853:       if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
                    854:        {
                    855:          if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
                    856:                 && (cc_prev_status.flags & CC_HI_R31_ADJ)
                    857:                 && cc_prev_status.mdep == XEXP (operands[1], 0)))
                    858:            {
                    859:              CC_STATUS_INIT;
                    860:              output_asm_insn ("orh %h1,%?r0,%?r31", operands);
                    861:            }
                    862:          cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
                    863:          cc_status.mdep = XEXP (operands[1], 0);
                    864:          return "fld.d %L1(%?r31),%0";
                    865:        }
                    866:       return "fld.d %1,%0";
                    867:     }
                    868:   else if (FP_REG_P (operands[1]))
                    869:     {
                    870:       if (GET_CODE (operands[0]) == REG)
                    871:        {
                    872:          output_asm_insn ("fxfr %1,%0", operands);
                    873:          operands[0] = gen_rtx (REG, VOIDmode, REGNO (operands[0]) + 1);
                    874:          operands[1] = gen_rtx (REG, VOIDmode, REGNO (operands[1]) + 1);
                    875:          return "fxfr %1,%0";
                    876:        }
                    877:       if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
                    878:        {
                    879:          if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
                    880:                 && (cc_prev_status.flags & CC_HI_R31_ADJ)
                    881:                 && cc_prev_status.mdep == XEXP (operands[0], 0)))
                    882:            {
                    883:              CC_STATUS_INIT;
                    884:              output_asm_insn ("orh %h0,%?r0,%?r31", operands);
                    885:            }
                    886:          cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
                    887:          cc_status.mdep = XEXP (operands[0], 0);
                    888:          return "fst.d %1,%L0(%?r31)";
                    889:        }
                    890:       return "fst.d %1,%0";
                    891:     }
                    892:   else
                    893:     abort ();
                    894:   /* NOTREACHED */
                    895:   return NULL;
                    896: }
                    897: 
                    898: /* Return a REG that occurs in ADDR with coefficient 1.
                    899:    ADDR can be effectively incremented by incrementing REG.  */
                    900: 
                    901: static rtx
                    902: find_addr_reg (addr)
                    903:      rtx addr;
                    904: {
                    905:   while (GET_CODE (addr) == PLUS)
                    906:     {
                    907:       if (GET_CODE (XEXP (addr, 0)) == REG)
                    908:        addr = XEXP (addr, 0);
                    909:       else if (GET_CODE (XEXP (addr, 1)) == REG)
                    910:        addr = XEXP (addr, 1);
                    911:       else if (CONSTANT_P (XEXP (addr, 0)))
                    912:        addr = XEXP (addr, 1);
                    913:       else if (CONSTANT_P (XEXP (addr, 1)))
                    914:        addr = XEXP (addr, 0);
                    915:       else
                    916:        abort ();
                    917:     }
                    918:   if (GET_CODE (addr) == REG)
                    919:     return addr;
                    920:   abort ();
                    921:   /* NOTREACHED */
                    922:   return NULL;
                    923: }
                    924: 
                    925: /* Return a template for a load instruction with mode MODE and
                    926:    arguments from the string ARGS.
                    927: 
                    928:    This string is in static storage.   */
                    929: 
                    930: static char *
                    931: load_opcode (mode, args, reg)
                    932:      enum machine_mode mode;
                    933:      char *args;
                    934:      rtx reg;
                    935: {
                    936:   static char buf[30];
                    937:   char *opcode;
                    938: 
                    939:   switch (mode)
                    940:     {
                    941:     case QImode:
                    942:       opcode = "ld.b";
                    943:       break;
                    944: 
                    945:     case HImode:
                    946:       opcode = "ld.s";
                    947:       break;
                    948: 
                    949:     case SImode:
                    950:     case SFmode:
                    951:       if (FP_REG_P (reg))
                    952:        opcode = "fld.l";
                    953:       else
                    954:        opcode = "ld.l";
                    955:       break;
                    956: 
                    957:     case DImode:
                    958:       if (!FP_REG_P (reg))
                    959:        abort ();
                    960:     case DFmode:
                    961:       opcode = "fld.d";
                    962:       break;
                    963: 
                    964:     default:
                    965:       abort ();
                    966:     }
                    967: 
                    968:   sprintf (buf, "%s %s", opcode, args);
                    969:   return buf;
                    970: }
                    971: 
                    972: /* Return a template for a store instruction with mode MODE and
                    973:    arguments from the string ARGS.
                    974: 
                    975:    This string is in static storage.   */
                    976: 
                    977: static char *
                    978: store_opcode (mode, args, reg)
                    979:      enum machine_mode mode;
                    980:      char *args;
                    981:      rtx reg;
                    982: {
                    983:   static char buf[30];
                    984:   char *opcode;
                    985: 
                    986:   switch (mode)
                    987:     {
                    988:     case QImode:
                    989:       opcode = "st.b";
                    990:       break;
                    991: 
                    992:     case HImode:
                    993:       opcode = "st.s";
                    994:       break;
                    995: 
                    996:     case SImode:
                    997:     case SFmode:
                    998:       if (FP_REG_P (reg))
                    999:        opcode = "fst.l";
                   1000:       else
                   1001:        opcode = "st.l";
                   1002:       break;
                   1003: 
                   1004:     case DImode:
                   1005:       if (!FP_REG_P (reg))
                   1006:        abort ();
                   1007:     case DFmode:
                   1008:       opcode = "fst.d";
                   1009:       break;
                   1010: 
                   1011:     default:
                   1012:       abort ();
                   1013:     }
                   1014: 
                   1015:   sprintf (buf, "%s %s", opcode, args);
                   1016:   return buf;
                   1017: }
                   1018: 
                   1019: /* Output a store-in-memory whose operands are OPERANDS[0,1].
                   1020:    OPERANDS[0] is a MEM, and OPERANDS[1] is a reg or zero.
                   1021: 
                   1022:    This function returns a template for an insn.
                   1023:    This is in static storage.
                   1024: 
                   1025:    It may also output some insns directly.
                   1026:    It may alter the values of operands[0] and operands[1].  */
                   1027: 
                   1028: char *
                   1029: output_store (operands)
                   1030:      rtx *operands;
                   1031: {
                   1032:   enum machine_mode mode = GET_MODE (operands[0]);
                   1033:   rtx address = XEXP (operands[0], 0);
                   1034:   char *string;
                   1035: 
                   1036:   cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
                   1037:   cc_status.mdep = address;
                   1038: 
                   1039:   if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
                   1040:         && (cc_prev_status.flags & CC_HI_R31_ADJ)
                   1041:         && address == cc_prev_status.mdep))
                   1042:     {
                   1043:       CC_STATUS_INIT;
                   1044:       output_asm_insn ("orh %h0,%?r0,%?r31", operands);
                   1045:       cc_prev_status.mdep = address;
                   1046:     }
                   1047: 
                   1048:   /* Store zero in two parts when appropriate.  */
                   1049:   if (mode == DFmode && operands[1] == CONST0_RTX (DFmode))
                   1050:     return store_opcode (DFmode, "%r1,%L0(%?r31)", operands[1]);
                   1051: 
                   1052:   /* Code below isn't smart enough to move a doubleword in two parts,
                   1053:      so use output_move_double to do that in the cases that require it.  */
                   1054:   if ((mode == DImode || mode == DFmode)
                   1055:       && ! FP_REG_P (operands[1]))
                   1056:     return output_move_double (operands);
                   1057: 
                   1058:   return store_opcode (mode, "%r1,%L0(%?r31)", operands[1]);
                   1059: }
                   1060: 
                   1061: /* Output a load-from-memory whose operands are OPERANDS[0,1].
                   1062:    OPERANDS[0] is a reg, and OPERANDS[1] is a mem.
                   1063: 
                   1064:    This function returns a template for an insn.
                   1065:    This is in static storage.
                   1066: 
                   1067:    It may also output some insns directly.
                   1068:    It may alter the values of operands[0] and operands[1].  */
                   1069: 
                   1070: char *
                   1071: output_load (operands)
                   1072:      rtx *operands;
                   1073: {
                   1074:   enum machine_mode mode = GET_MODE (operands[0]);
                   1075:   rtx address = XEXP (operands[1], 0);
                   1076: 
                   1077:   /* We don't bother trying to see if we know %hi(address).
                   1078:      This is because we are doing a load, and if we know the
                   1079:      %hi value, we probably also know that value in memory.  */
                   1080:   cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
                   1081:   cc_status.mdep = address;
                   1082: 
                   1083:   if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
                   1084:         && (cc_prev_status.flags & CC_HI_R31_ADJ)
                   1085:         && address == cc_prev_status.mdep
                   1086:         && cc_prev_status.mdep == cc_status.mdep))
                   1087:     {
                   1088:       CC_STATUS_INIT;
                   1089:       output_asm_insn ("orh %h1,%?r0,%?r31", operands);
                   1090:       cc_prev_status.mdep = address;
                   1091:     }
                   1092: 
                   1093:   /* Code below isn't smart enough to move a doubleword in two parts,
                   1094:      so use output_move_double to do that in the cases that require it.  */
                   1095:   if ((mode == DImode || mode == DFmode)
                   1096:       && ! FP_REG_P (operands[0]))
                   1097:     return output_move_double (operands);
                   1098: 
                   1099:   return load_opcode (mode, "%L1(%?r31),%0", operands[0]);
                   1100: }
                   1101: 
                   1102: #if 0
                   1103: /* Load the address specified by OPERANDS[3] into the register
                   1104:    specified by OPERANDS[0].
                   1105: 
                   1106:    OPERANDS[3] may be the result of a sum, hence it could either be:
                   1107: 
                   1108:    (1) CONST
                   1109:    (2) REG
                   1110:    (2) REG + CONST_INT
                   1111:    (3) REG + REG + CONST_INT
                   1112:    (4) REG + REG  (special case of 3).
                   1113: 
                   1114:    Note that (3) is not a legitimate address.
                   1115:    All cases are handled here.  */
                   1116: 
                   1117: void
                   1118: output_load_address (operands)
                   1119:      rtx *operands;
                   1120: {
                   1121:   rtx base, offset;
                   1122: 
                   1123:   if (CONSTANT_P (operands[3]))
                   1124:     {
                   1125:       output_asm_insn ("mov %3,%0", operands);
                   1126:       return;
                   1127:     }
                   1128: 
                   1129:   if (REG_P (operands[3]))
                   1130:     {
                   1131:       if (REGNO (operands[0]) != REGNO (operands[3]))
                   1132:        output_asm_insn ("shl %?r0,%3,%0", operands);
                   1133:       return;
                   1134:     }
                   1135: 
                   1136:   if (GET_CODE (operands[3]) != PLUS)
                   1137:     abort ();
                   1138: 
                   1139:   base = XEXP (operands[3], 0);
                   1140:   offset = XEXP (operands[3], 1);
                   1141: 
                   1142:   if (GET_CODE (base) == CONST_INT)
                   1143:     {
                   1144:       rtx tmp = base;
                   1145:       base = offset;
                   1146:       offset = tmp;
                   1147:     }
                   1148: 
                   1149:   if (GET_CODE (offset) != CONST_INT)
                   1150:     {
                   1151:       /* Operand is (PLUS (REG) (REG)).  */
                   1152:       base = operands[3];
                   1153:       offset = const0_rtx;
                   1154:     }
                   1155: 
                   1156:   if (REG_P (base))
                   1157:     {
                   1158:       operands[6] = base;
                   1159:       operands[7] = offset;
                   1160:       CC_STATUS_PARTIAL_INIT;
                   1161:       if (SMALL_INT (offset))
                   1162:        output_asm_insn ("adds %7,%6,%0", operands);
                   1163:       else
                   1164:        output_asm_insn ("mov %7,%0\n\tadds %0,%6,%0", operands);
                   1165:     }
                   1166:   else if (GET_CODE (base) == PLUS)
                   1167:     {
                   1168:       operands[6] = XEXP (base, 0);
                   1169:       operands[7] = XEXP (base, 1);
                   1170:       operands[8] = offset;
                   1171: 
                   1172:       CC_STATUS_PARTIAL_INIT;
                   1173:       if (SMALL_INT (offset))
                   1174:        output_asm_insn ("adds %6,%7,%0\n\tadds %8,%0,%0", operands);
                   1175:       else
                   1176:        output_asm_insn ("mov %8,%0\n\tadds %0,%6,%0\n\tadds %0,%7,%0", operands);
                   1177:     }
                   1178:   else
                   1179:     abort ();
                   1180: }
                   1181: #endif
                   1182: 
                   1183: /* Output code to place a size count SIZE in register REG.
                   1184:    Because block moves are pipelined, we don't include the
                   1185:    first element in the transfer of SIZE to REG.
                   1186:    For this, we subtract ALIGN.  (Actually, I think it is not
                   1187:    right to subtract on this machine, so right now we don't.)  */
                   1188: 
                   1189: static void
                   1190: output_size_for_block_move (size, reg, align)
                   1191:      rtx size, reg, align;
                   1192: {
                   1193:   rtx xoperands[3];
                   1194: 
                   1195:   xoperands[0] = reg;
                   1196:   xoperands[1] = size;
                   1197:   xoperands[2] = align;
                   1198: 
                   1199: #if 1
                   1200:   cc_status.flags &= ~ CC_KNOW_HI_R31;
1.1.1.3 ! root     1201:   output_asm_insn (singlemove_string (xoperands), xoperands);
1.1       root     1202: #else
                   1203:   if (GET_CODE (size) == REG)
                   1204:     output_asm_insn ("sub %2,%1,%0", xoperands);
                   1205:   else
                   1206:     {
                   1207:       xoperands[1]
                   1208:        = gen_rtx (CONST_INT, VOIDmode, INTVAL (size) - INTVAL (align));
                   1209:       cc_status.flags &= ~ CC_KNOW_HI_R31;
                   1210:       output_asm_insn ("mov %1,%0", xoperands);
                   1211:     }
                   1212: #endif
                   1213: }
                   1214: 
                   1215: /* Emit code to perform a block move.
                   1216: 
                   1217:    OPERANDS[0] is the destination.
                   1218:    OPERANDS[1] is the source.
                   1219:    OPERANDS[2] is the size.
                   1220:    OPERANDS[3] is the known safe alignment.
                   1221:    OPERANDS[4..6] are pseudos we can safely clobber as temps.  */
                   1222: 
                   1223: char *
                   1224: output_block_move (operands)
                   1225:      rtx *operands;
                   1226: {
                   1227:   /* A vector for our computed operands.  Note that load_output_address
                   1228:      makes use of (and can clobber) up to the 8th element of this vector.  */
                   1229:   rtx xoperands[10];
                   1230:   rtx zoperands[10];
                   1231:   static int movstrsi_label = 0;
                   1232:   int i, j;
                   1233:   rtx temp1 = operands[4];
                   1234:   rtx alignrtx = operands[3];
                   1235:   int align = INTVAL (alignrtx);
                   1236:   int chunk_size;
                   1237: 
                   1238:   xoperands[0] = operands[0];
                   1239:   xoperands[1] = operands[1];
                   1240:   xoperands[2] = temp1;
                   1241: 
                   1242:   /* We can't move more than four bytes at a time
                   1243:      because we have only one register to move them through.  */
                   1244:   if (align > 4)
                   1245:     {
                   1246:       align = 4;
                   1247:       alignrtx = gen_rtx (CONST_INT, VOIDmode, 4);
                   1248:     }
                   1249: 
                   1250:   /* Recognize special cases of block moves.  These occur
                   1251:      when GNU C++ is forced to treat something as BLKmode
                   1252:      to keep it in memory, when its mode could be represented
                   1253:      with something smaller.
                   1254: 
                   1255:      We cannot do this for global variables, since we don't know
                   1256:      what pages they don't cross.  Sigh.  */
                   1257:   if (GET_CODE (operands[2]) == CONST_INT
                   1258:       && ! CONSTANT_ADDRESS_P (operands[0])
                   1259:       && ! CONSTANT_ADDRESS_P (operands[1]))
                   1260:     {
                   1261:       int size = INTVAL (operands[2]);
                   1262:       rtx op0 = xoperands[0];
                   1263:       rtx op1 = xoperands[1];
                   1264: 
                   1265:       if ((align & 3) == 0 && (size & 3) == 0 && (size >> 2) <= 16)
                   1266:        {
                   1267:          if (memory_address_p (SImode, plus_constant (op0, size))
                   1268:              && memory_address_p (SImode, plus_constant (op1, size)))
                   1269:            {
                   1270:              cc_status.flags &= ~CC_KNOW_HI_R31;
                   1271:              for (i = (size>>2)-1; i >= 0; i--)
                   1272:                {
                   1273:                  xoperands[0] = plus_constant (op0, i * 4);
                   1274:                  xoperands[1] = plus_constant (op1, i * 4);
                   1275:                  output_asm_insn ("ld.l %a1,%?r31\n\tst.l %?r31,%a0",
                   1276:                                   xoperands);
                   1277:                }
                   1278:              return "";
                   1279:            }
                   1280:        }
                   1281:       else if ((align & 1) == 0 && (size & 1) == 0 && (size >> 1) <= 16)
                   1282:        {
                   1283:          if (memory_address_p (HImode, plus_constant (op0, size))
                   1284:              && memory_address_p (HImode, plus_constant (op1, size)))
                   1285:            {
                   1286:              cc_status.flags &= ~CC_KNOW_HI_R31;
                   1287:              for (i = (size>>1)-1; i >= 0; i--)
                   1288:                {
                   1289:                  xoperands[0] = plus_constant (op0, i * 2);
                   1290:                  xoperands[1] = plus_constant (op1, i * 2);
                   1291:                  output_asm_insn ("ld.s %a1,%?r31\n\tst.s %?r31,%a0",
                   1292:                                   xoperands);
                   1293:                }
                   1294:              return "";
                   1295:            }
                   1296:        }
                   1297:       else if (size <= 16)
                   1298:        {
                   1299:          if (memory_address_p (QImode, plus_constant (op0, size))
                   1300:              && memory_address_p (QImode, plus_constant (op1, size)))
                   1301:            {
                   1302:              cc_status.flags &= ~CC_KNOW_HI_R31;
                   1303:              for (i = size-1; i >= 0; i--)
                   1304:                {
                   1305:                  xoperands[0] = plus_constant (op0, i);
                   1306:                  xoperands[1] = plus_constant (op1, i);
                   1307:                  output_asm_insn ("ld.b %a1,%?r31\n\tst.b %?r31,%a0",
                   1308:                                   xoperands);
                   1309:                }
                   1310:              return "";
                   1311:            }
                   1312:        }
                   1313:     }
                   1314: 
                   1315:   /* Since we clobber untold things, nix the condition codes.  */
                   1316:   CC_STATUS_INIT;
                   1317: 
                   1318:   /* This is the size of the transfer.
                   1319:      Either use the register which already contains the size,
                   1320:      or use a free register (used by no operands).  */
                   1321:   output_size_for_block_move (operands[2], operands[4], alignrtx);
                   1322: 
                   1323: #if 0
                   1324:   /* Also emit code to decrement the size value by ALIGN.  */
                   1325:   zoperands[0] = operands[0];
                   1326:   zoperands[3] = plus_constant (operands[0], align);
                   1327:   output_load_address (zoperands);
                   1328: #endif
                   1329: 
                   1330:   /* Generate number for unique label.  */
                   1331: 
                   1332:   xoperands[3] = gen_rtx (CONST_INT, VOIDmode, movstrsi_label++);
                   1333: 
                   1334:   /* Calculate the size of the chunks we will be trying to move first.  */
                   1335: 
                   1336: #if 0
                   1337:   if ((align & 3) == 0)
                   1338:     chunk_size = 4;
                   1339:   else if ((align & 1) == 0)
                   1340:     chunk_size = 2;
                   1341:   else
                   1342: #endif
                   1343:     chunk_size = 1;
                   1344: 
                   1345:   /* Copy the increment (negative) to a register for bla insn.  */
                   1346: 
                   1347:   xoperands[4] = gen_rtx (CONST_INT, VOIDmode, - chunk_size);
                   1348:   xoperands[5] = operands[5];
                   1349:   output_asm_insn ("adds %4,%?r0,%5", xoperands);
                   1350: 
                   1351:   /* Predecrement the loop counter.  This happens again also in the `bla'
1.1.1.2   root     1352:      instruction which precedes the loop, but we need to have it done
                   1353:      two times before we enter the loop because of the bizarre semantics
1.1       root     1354:      of the bla instruction.  */
                   1355: 
                   1356:   output_asm_insn ("adds %5,%2,%2", xoperands);
                   1357: 
                   1358:   /* Check for the case where the original count was less than or equal to
                   1359:      zero.  Avoid going through the loop at all if the original count was
                   1360:      indeed less than or equal to zero.  Note that we treat the count as
                   1361:      if it were a signed 32-bit quantity here, rather than an unsigned one,
                   1362:      even though we really shouldn't.  We have to do this because of the
                   1363:      semantics of the `ble' instruction, which assume that the count is
                   1364:      a signed 32-bit value.  Anyway, in practice it won't matter because
                   1365:      nobody is going to try to do a memcpy() of more than half of the
                   1366:      entire address space (i.e. 2 gigabytes) anyway.  */
                   1367: 
                   1368:   output_asm_insn ("bc .Le%3", xoperands);
                   1369: 
                   1370:   /* Make available a register which is a temporary.  */
                   1371: 
                   1372:   xoperands[6] = operands[6];
                   1373: 
                   1374:   /* Now the actual loop.
                   1375:      In xoperands, elements 1 and 0 are the input and output vectors.
                   1376:      Element 2 is the loop index.  Element 5 is the increment.  */
                   1377: 
                   1378:   output_asm_insn ("subs %1,%5,%1", xoperands);
                   1379:   output_asm_insn ("bla %5,%2,.Lm%3", xoperands);
                   1380:   output_asm_insn ("adds %0,%2,%6", xoperands);
                   1381:   output_asm_insn ("\n.Lm%3:", xoperands);         /* Label for bla above.  */
                   1382:   output_asm_insn ("\n.Ls%3:",  xoperands);        /* Loop start label. */
                   1383:   output_asm_insn ("adds %5,%6,%6", xoperands);
                   1384: 
                   1385:   /* NOTE:  The code here which is supposed to handle the cases where the
                   1386:      sources and destinations are known to start on a 4 or 2 byte boundary
                   1387:      are currently broken.  They fail to do anything about the overflow
                   1388:      bytes which might still need to be copied even after we have copied
                   1389:      some number of words or halfwords.  Thus, for now we use the lowest
                   1390:      common denominator, i.e. the code which just copies some number of
                   1391:      totally unaligned individual bytes.  (See the calculation of
                   1392:      chunk_size above.  */
                   1393: 
                   1394:   if (chunk_size == 4)
                   1395:     {
                   1396:       output_asm_insn ("ld.l %2(%1),%?r31", xoperands);
                   1397:       output_asm_insn ("bla %5,%2,.Ls%3", xoperands);
                   1398:       output_asm_insn ("st.l %?r31,8(%6)", xoperands);
                   1399:     }
                   1400:   else if (chunk_size == 2)
                   1401:     {
                   1402:       output_asm_insn ("ld.s %2(%1),%?r31", xoperands);
                   1403:       output_asm_insn ("bla %5,%2,.Ls%3", xoperands);
                   1404:       output_asm_insn ("st.s %?r31,4(%6)", xoperands);
                   1405:     }
                   1406:   else /* chunk_size == 1 */
                   1407:     {
                   1408:       output_asm_insn ("ld.b %2(%1),%?r31", xoperands);
                   1409:       output_asm_insn ("bla %5,%2,.Ls%3", xoperands);
                   1410:       output_asm_insn ("st.b %?r31,2(%6)", xoperands);
                   1411:     }
                   1412:   output_asm_insn ("\n.Le%3:", xoperands);         /* Here if count <= 0.  */
                   1413: 
                   1414:   return "";
                   1415: }
                   1416: 
                   1417: /* Output a delayed branch insn with the delay insn in its
                   1418:    branch slot.  The delayed branch insn template is in TEMPLATE,
                   1419:    with operands OPERANDS.  The insn in its delay slot is INSN.
                   1420: 
                   1421:    As a special case, since we know that all memory transfers are via
                   1422:    ld/st insns, if we see a (MEM (SYMBOL_REF ...)) we divide the memory
                   1423:    reference around the branch as
                   1424: 
                   1425:        orh ha%x,%?r0,%?r31
                   1426:        b ...
                   1427:        ld/st l%x(%?r31),...
                   1428: 
                   1429:    As another special case, we handle loading (SYMBOL_REF ...) and
                   1430:    other large constants around branches as well:
                   1431: 
                   1432:        orh h%x,%?r0,%0
                   1433:        b ...
                   1434:        or l%x,%0,%1
                   1435: 
                   1436:    */
                   1437: 
                   1438: char *
                   1439: output_delayed_branch (template, operands, insn)
                   1440:      char *template;
                   1441:      rtx *operands;
                   1442:      rtx insn;
                   1443: {
                   1444:   rtx src = XVECEXP (PATTERN (insn), 0, 1);
                   1445:   rtx dest = XVECEXP (PATTERN (insn), 0, 0);
                   1446: 
                   1447:   /* See if we are doing some branch together with setting some register
                   1448:      to some 32-bit value which does (or may) have some of the high-order
                   1449:      16 bits set.  If so, we need to set the register in two stages.  One
                   1450:      stage must be done before the branch, and the other one can be done
                   1451:      in the delay slot.  */
                   1452: 
                   1453:   if ( (GET_CODE (src) == CONST_INT
                   1454:        && ((unsigned) INTVAL (src) & (unsigned) 0xffff0000) != (unsigned) 0)
                   1455:       || (GET_CODE (src) == SYMBOL_REF)
                   1456:       || (GET_CODE (src) == LABEL_REF)
                   1457:       || (GET_CODE (src) == CONST))
                   1458:     {
                   1459:       rtx xoperands[2];
                   1460:       xoperands[0] = dest;
                   1461:       xoperands[1] = src;
                   1462: 
                   1463:       CC_STATUS_PARTIAL_INIT;
                   1464:       /* Output the `orh' insn.  */
                   1465:       output_asm_insn ("orh %H1,%?r0,%0", xoperands);
                   1466: 
                   1467:       /* Output the branch instruction next.  */
                   1468:       output_asm_insn (template, operands);
                   1469: 
                   1470:       /* Now output the `or' insn.  */
                   1471:       output_asm_insn ("or %L1,%0,%0", xoperands);
                   1472:     }
                   1473:   else if ((GET_CODE (src) == MEM
                   1474:            && CONSTANT_ADDRESS_P (XEXP (src, 0)))
                   1475:           || (GET_CODE (dest) == MEM
                   1476:               && CONSTANT_ADDRESS_P (XEXP (dest, 0))))
                   1477:     {
                   1478:       rtx xoperands[2];
                   1479:       char *split_template;
                   1480:       xoperands[0] = dest;
                   1481:       xoperands[1] = src;
                   1482: 
                   1483:       /* Output the `orh' insn.  */
                   1484:       if (GET_CODE (src) == MEM)
                   1485:        {
                   1486:          if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
                   1487:                 && (cc_prev_status.flags & CC_HI_R31_ADJ)
                   1488:                 && cc_prev_status.mdep == XEXP (operands[1], 0)))
                   1489:            {
                   1490:              CC_STATUS_INIT;
                   1491:              output_asm_insn ("orh %h1,%?r0,%?r31", xoperands);
                   1492:            }
                   1493:          split_template = load_opcode (GET_MODE (dest),
                   1494:                                        "%L1(%?r31),%0", dest);
                   1495:        }
                   1496:       else
                   1497:        {
                   1498:          if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
                   1499:                 && (cc_prev_status.flags & CC_HI_R31_ADJ)
                   1500:                 && cc_prev_status.mdep == XEXP (operands[0], 0)))
                   1501:            {
                   1502:              CC_STATUS_INIT;
                   1503:              output_asm_insn ("orh %h0,%?r0,%?r31", xoperands);
                   1504:            }
                   1505:          split_template = store_opcode (GET_MODE (dest),
                   1506:                                         "%r1,%L0(%?r31)", src);
                   1507:        }
                   1508: 
                   1509:       /* Output the branch instruction next.  */
                   1510:       output_asm_insn (template, operands);
                   1511: 
                   1512:       /* Now output the load or store.
                   1513:         No need to do a CC_STATUS_INIT, because we are branching anyway.  */
                   1514:       output_asm_insn (split_template, xoperands);
                   1515:     }
                   1516:   else
                   1517:     {
                   1518:       int insn_code_number;
                   1519:       rtx pat = gen_rtx (SET, VOIDmode, dest, src);
                   1520:       rtx delay_insn = gen_rtx (INSN, VOIDmode, 0, 0, 0, pat, -1, 0, 0);
                   1521:       int i;
                   1522: 
                   1523:       /* Output the branch instruction first.  */
                   1524:       output_asm_insn (template, operands);
                   1525: 
                   1526:       /* Now recognize the insn which we put in its delay slot.
1.1.1.2   root     1527:         We must do this after outputting the branch insn,
1.1       root     1528:         since operands may just be a pointer to `recog_operand'.  */
                   1529:       INSN_CODE (delay_insn) = insn_code_number = recog (pat, delay_insn);
                   1530:       if (insn_code_number == -1)
                   1531:        abort ();
                   1532: 
                   1533:       for (i = 0; i < insn_n_operands[insn_code_number]; i++)
                   1534:        {
                   1535:          if (GET_CODE (recog_operand[i]) == SUBREG)
                   1536:            recog_operand[i] = alter_subreg (recog_operand[i]);
                   1537:        }
                   1538: 
                   1539:       insn_extract (delay_insn);
                   1540:       if (! constrain_operands (insn_code_number, 1))
                   1541:        fatal_insn_not_found (delay_insn);
                   1542: 
                   1543:       template = insn_template[insn_code_number];
                   1544:       if (template == 0)
                   1545:        template = (*insn_outfun[insn_code_number]) (recog_operand, delay_insn);
                   1546:       output_asm_insn (template, recog_operand);
                   1547:     }
                   1548:   CC_STATUS_INIT;
                   1549:   return "";
                   1550: }
                   1551: 
                   1552: /* Output a newly constructed insn DELAY_INSN.  */
                   1553: char *
                   1554: output_delay_insn (delay_insn)
                   1555:      rtx delay_insn;
                   1556: {
                   1557:   char *template;
                   1558:   int insn_code_number;
                   1559:   int i;
                   1560: 
                   1561:   /* Now recognize the insn which we put in its delay slot.
1.1.1.2   root     1562:      We must do this after outputting the branch insn,
1.1       root     1563:      since operands may just be a pointer to `recog_operand'.  */
                   1564:   insn_code_number = recog_memoized (delay_insn);
                   1565:   if (insn_code_number == -1)
                   1566:     abort ();
                   1567: 
                   1568:   /* Extract the operands of this delay insn.  */
                   1569:   INSN_CODE (delay_insn) = insn_code_number;
                   1570:   insn_extract (delay_insn);
                   1571: 
1.1.1.2   root     1572:   /* It is possible that this insn has not been properly scanned by final
1.1       root     1573:      yet.  If this insn's operands don't appear in the peephole's
                   1574:      actual operands, then they won't be fixed up by final, so we
                   1575:      make sure they get fixed up here.  -- This is a kludge.  */
                   1576:   for (i = 0; i < insn_n_operands[insn_code_number]; i++)
                   1577:     {
                   1578:       if (GET_CODE (recog_operand[i]) == SUBREG)
                   1579:        recog_operand[i] = alter_subreg (recog_operand[i]);
                   1580:     }
                   1581: 
                   1582: #ifdef REGISTER_CONSTRAINTS
                   1583:   if (! constrain_operands (insn_code_number))
                   1584:     abort ();
                   1585: #endif
                   1586: 
                   1587:   cc_prev_status = cc_status;
                   1588: 
                   1589:   /* Update `cc_status' for this instruction.
                   1590:      The instruction's output routine may change it further.
                   1591:      If the output routine for a jump insn needs to depend
                   1592:      on the cc status, it should look at cc_prev_status.  */
                   1593: 
                   1594:   NOTICE_UPDATE_CC (PATTERN (delay_insn), delay_insn);
                   1595: 
                   1596:   /* Now get the template for what this insn would
                   1597:      have been, without the branch.  */
                   1598: 
                   1599:   template = insn_template[insn_code_number];
                   1600:   if (template == 0)
                   1601:     template = (*insn_outfun[insn_code_number]) (recog_operand, delay_insn);
                   1602:   output_asm_insn (template, recog_operand);
                   1603:   return "";
                   1604: }
                   1605: 
                   1606: /* Special routine to convert an SFmode value represented as a
                   1607:    CONST_DOUBLE into its equivalent unsigned long bit pattern.
                   1608:    We convert the value from a double precision floating-point
                   1609:    value to single precision first, and thence to a bit-wise
                   1610:    equivalent unsigned long value.  This routine is used when
                   1611:    generating an immediate move of an SFmode value directly
                   1612:    into a general register because the svr4 assembler doesn't
                   1613:    grok floating literals in instruction operand contexts.  */
                   1614: 
                   1615: unsigned long
                   1616: sfmode_constant_to_ulong (x)
                   1617:      rtx x;
                   1618: {
1.1.1.2   root     1619:   REAL_VALUE_TYPE d;
1.1       root     1620:   union { float f; unsigned long i; } u2;
                   1621: 
                   1622:   if (GET_CODE (x) != CONST_DOUBLE || GET_MODE (x) != SFmode)
                   1623:     abort ();
                   1624: 
1.1.1.2   root     1625: #if TARGET_FLOAT_FORMAT != HOST_FLOAT_FORMAT
1.1.1.3 ! root     1626:  error IEEE emulation needed
1.1       root     1627: #endif
1.1.1.2   root     1628:   REAL_VALUE_FROM_CONST_DOUBLE (d, x);
                   1629:   u2.f = d;
1.1       root     1630:   return u2.i;
                   1631: }
                   1632: 
                   1633: /* This function generates the assembly code for function entry.
                   1634:    The macro FUNCTION_PROLOGUE in i860.h is defined to call this function.
                   1635: 
                   1636:    ASM_FILE is a stdio stream to output the code to.
                   1637:    SIZE is an int: how many units of temporary storage to allocate.
                   1638: 
                   1639:    Refer to the array `regs_ever_live' to determine which registers
                   1640:    to save; `regs_ever_live[I]' is nonzero if register number I
                   1641:    is ever used in the function.  This macro is responsible for
                   1642:    knowing which registers should not be saved even if used.
                   1643: 
                   1644:    NOTE: `frame_lower_bytes' is the count of bytes which will lie
                   1645:    between the new `fp' value and the new `sp' value after the
                   1646:    prologue is done.  `frame_upper_bytes' is the count of bytes
                   1647:    that will lie between the new `fp' and the *old* `sp' value
                   1648:    after the new `fp' is setup (in the prologue).  The upper
                   1649:    part of each frame always includes at least 2 words (8 bytes)
                   1650:    to hold the saved frame pointer and the saved return address.
                   1651: 
                   1652:    The svr4 ABI for the i860 now requires that the values of the
                   1653:    stack pointer and frame pointer registers be kept aligned to
                   1654:    16-byte boundaries at all times.  We obey that restriction here.
                   1655: 
                   1656:    The svr4 ABI for the i860 is entirely vague when it comes to specifying
                   1657:    exactly where the "preserved" registers should be saved.  The native
                   1658:    svr4 C compiler I now have doesn't help to clarify the requirements
                   1659:    very much because it is plainly out-of-date and non-ABI-compliant
                   1660:    (in at least one important way, i.e. how it generates function
                   1661:    epilogues).
                   1662: 
                   1663:    The native svr4 C compiler saves the "preserved" registers (i.e.
                   1664:    r4-r15 and f2-f7) in the lower part of a frame (i.e. at negative
                   1665:    offsets from the frame pointer).
                   1666: 
                   1667:    Previous versions of GCC also saved the "preserved" registers in the
1.1.1.2   root     1668:    "negative" part of the frame, but they saved them using positive
1.1       root     1669:    offsets from the (adjusted) stack pointer (after it had been adjusted
                   1670:    to allocate space for the new frame).  That's just plain wrong
                   1671:    because if the current function calls alloca(), the stack pointer
                   1672:    will get moved, and it will be impossible to restore the registers
                   1673:    properly again after that.
                   1674: 
                   1675:    Both compilers handled parameter registers (i.e. r16-r27 and f8-f15)
                   1676:    by copying their values either into various "preserved" registers or
                   1677:    into stack slots in the lower part of the current frame (as seemed
                   1678:    appropriate, depending upon subsequent usage of these values).
                   1679: 
                   1680:    Here we want to save the preserved registers at some offset from the
                   1681:    frame pointer register so as to avoid any possible problems arising
                   1682:    from calls to alloca().  We can either save them at small positive
                   1683:    offsets from the frame pointer, or at small negative offsets from
                   1684:    the frame pointer.  If we save them at small negative offsets from
                   1685:    the frame pointer (i.e. in the lower part of the frame) then we
                   1686:    must tell the rest of GCC (via STARTING_FRAME_OFFSET) exactly how
                   1687:    many bytes of space we plan to use in the lower part of the frame
                   1688:    for this purpose.  Since other parts of the compiler reference the
                   1689:    value of STARTING_FRAME_OFFSET long before final() calls this function,
                   1690:    we would have to go ahead and assume the worst-case storage requirements
                   1691:    for saving all of the "preserved" registers (and use that number, i.e.
                   1692:    `80', to define STARTING_FRAME_OFFSET) if we wanted to save them in
                   1693:    the lower part of the frame.  That could potentially be very wasteful,
                   1694:    and that wastefulness could really hamper people compiling for embedded
                   1695:    i860 targets with very tight limits on stack space.  Thus, we choose
                   1696:    here to save the preserved registers in the upper part of the
                   1697:    frame, so that we can decide at the very last minute how much (or how
                   1698:    little) space we must allocate for this purpose.
                   1699: 
                   1700:    To satisfy the needs of the svr4 ABI "tdesc" scheme, preserved
                   1701:    registers must always be saved so that the saved values of registers
                   1702:    with higher numbers are at higher addresses.  We obey that restriction
                   1703:    here.
                   1704: 
                   1705:    There are two somewhat different ways that you can generate prologues
                   1706:    here... i.e. pedantically ABI-compliant, and the "other" way.  The
1.1.1.2   root     1707:    "other" way is more consistent with what is currently generated by the
1.1       root     1708:    "native" svr4 C compiler for the i860.  That's important if you want
                   1709:    to use the current (as of 8/91) incarnation of svr4 SDB for the i860.
                   1710:    The SVR4 SDB for the i860 insists on having function prologues be
                   1711:    non-ABI-compliant!
                   1712: 
                   1713:    To get fully ABI-compliant prologues, define I860_STRICT_ABI_PROLOGUES
                   1714:    in the i860svr4.h file.  (By default this is *not* defined).
                   1715: 
                   1716:    The differences between the ABI-compliant and non-ABI-compliant prologues
                   1717:    are that (a) the ABI version seems to require the use of *signed*
                   1718:    (rather than unsigned) adds and subtracts, and (b) the ordering of
                   1719:    the various steps (e.g. saving preserved registers, saving the
                   1720:    return address, setting up the new frame pointer value) is different.
                   1721: 
                   1722:    For strict ABI compliance, it seems to be the case that the very last
                   1723:    thing that is supposed to happen in the prologue is getting the frame
                   1724:    pointer set to its new value (but only after everything else has
                   1725:    already been properly setup).  We do that here, but only if the symbol
                   1726:    I860_STRICT_ABI_PROLOGUES is defined.
                   1727: */
                   1728: 
                   1729: #ifndef STACK_ALIGNMENT
                   1730: #define STACK_ALIGNMENT        16
                   1731: #endif
                   1732: 
                   1733: extern char call_used_regs[];
                   1734: extern int leaf_function_p ();
                   1735: 
                   1736: char *current_function_original_name;
                   1737: 
                   1738: static int must_preserve_r1;
                   1739: static unsigned must_preserve_bytes;
                   1740: 
                   1741: void
                   1742: function_prologue (asm_file, local_bytes)
                   1743:      register FILE *asm_file;
                   1744:      register unsigned local_bytes;
                   1745: {
                   1746:   register unsigned frame_lower_bytes;
                   1747:   register unsigned frame_upper_bytes;
                   1748:   register unsigned total_fsize;
                   1749:   register unsigned preserved_reg_bytes = 0;
                   1750:   register unsigned i;
                   1751:   register unsigned preserved_so_far = 0;
                   1752: 
                   1753:   must_preserve_r1 = (optimize < 2 || ! leaf_function_p ());
                   1754:   must_preserve_bytes = 4 + (must_preserve_r1 ? 4 : 0);
                   1755: 
                   1756:   /* Count registers that need preserving.  Ignore r0.  It never needs
                   1757:      preserving.  */
                   1758: 
                   1759:   for (i = 1; i < FIRST_PSEUDO_REGISTER; i++)
                   1760:     {
                   1761:       if (regs_ever_live[i] && ! call_used_regs[i])
                   1762:         preserved_reg_bytes += 4;
                   1763:     }
                   1764: 
                   1765:   /* Round-up the frame_lower_bytes so that it's a multiple of 16. */
                   1766: 
                   1767:   frame_lower_bytes = (local_bytes + STACK_ALIGNMENT - 1) & -STACK_ALIGNMENT;
                   1768: 
                   1769:   /* The upper part of each frame will contain the saved fp,
                   1770:      the saved r1, and stack slots for all of the other "preserved"
                   1771:      registers that we find we will need to save & restore. */
                   1772: 
                   1773:   frame_upper_bytes = must_preserve_bytes + preserved_reg_bytes;
                   1774: 
                   1775:   /* Round-up the frame_upper_bytes so that it's a multiple of 16. */
                   1776: 
                   1777:   frame_upper_bytes
                   1778:     = (frame_upper_bytes + STACK_ALIGNMENT - 1) & -STACK_ALIGNMENT;
                   1779: 
                   1780:   total_fsize = frame_upper_bytes + frame_lower_bytes;
                   1781: 
                   1782: #ifndef I860_STRICT_ABI_PROLOGUES
                   1783: 
                   1784:   /* There are two kinds of function prologues.
                   1785:      You use the "small" version if the total frame size is
                   1786:      small enough so that it can fit into an immediate 16-bit
                   1787:      value in one instruction.  Otherwise, you use the "large"
                   1788:      version of the function prologue.  */
                   1789: 
                   1790:   if (total_fsize > 0x7fff)
                   1791:     {
                   1792:       /* Adjust the stack pointer.  The ABI sez to do this using `adds',
                   1793:         but the native C compiler on svr4 uses `addu'.  */
                   1794: 
                   1795:       fprintf (asm_file, "\taddu -%d,%ssp,%ssp\n",
                   1796:        frame_upper_bytes, i860_reg_prefix, i860_reg_prefix);
                   1797: 
                   1798:       /* Save the old frame pointer.  */
                   1799: 
                   1800:       fprintf (asm_file, "\tst.l %sfp,0(%ssp)\n",
                   1801:        i860_reg_prefix, i860_reg_prefix);
                   1802: 
                   1803:       /* Setup the new frame pointer.  The ABI sez to do this after
                   1804:         preserving registers (using adds), but that's not what the
                   1805:         native C compiler on svr4 does.  */
                   1806: 
                   1807:       fprintf (asm_file, "\taddu 0,%ssp,%sfp\n",
                   1808:        i860_reg_prefix, i860_reg_prefix);
                   1809: 
                   1810:       /* Get the value of frame_lower_bytes into r31.  */
                   1811: 
                   1812:       fprintf (asm_file, "\torh %d,%sr0,%sr31\n",
                   1813:        frame_lower_bytes >> 16, i860_reg_prefix, i860_reg_prefix);
                   1814:       fprintf (asm_file, "\tor %d,%sr31,%sr31\n",
                   1815:        frame_lower_bytes & 0xffff, i860_reg_prefix, i860_reg_prefix);
                   1816: 
                   1817:       /* Now re-adjust the stack pointer using the value in r31.
                   1818:         The ABI sez to do this with `subs' but SDB may prefer `subu'.  */
                   1819: 
                   1820:       fprintf (asm_file, "\tsubu %ssp,%sr31,%ssp\n",
                   1821:        i860_reg_prefix, i860_reg_prefix, i860_reg_prefix);
                   1822: 
                   1823:       /* Preserve registers.  The ABI sez to do this before setting
                   1824:         up the new frame pointer, but that's not what the native
                   1825:         C compiler on svr4 does.  */
                   1826: 
                   1827:       for (i = 1; i < 32; i++)
                   1828:         if (regs_ever_live[i] && ! call_used_regs[i])
                   1829:           fprintf (asm_file, "\tst.l %s%s,%d(%sfp)\n",
                   1830:            i860_reg_prefix, reg_names[i],
                   1831:            must_preserve_bytes  + (4 * preserved_so_far++),
                   1832:            i860_reg_prefix);
                   1833: 
                   1834:       for (i = 32; i < 64; i++)
                   1835:         if (regs_ever_live[i] && ! call_used_regs[i])
                   1836:           fprintf (asm_file, "\tfst.l %s%s,%d(%sfp)\n",
                   1837:            i860_reg_prefix, reg_names[i],
                   1838:            must_preserve_bytes + (4 * preserved_so_far++),
                   1839:            i860_reg_prefix);
                   1840: 
                   1841:       /* Save the return address.  */
                   1842: 
                   1843:       if (must_preserve_r1)
                   1844:         fprintf (asm_file, "\tst.l %sr1,4(%sfp)\n",
                   1845:          i860_reg_prefix, i860_reg_prefix);
                   1846:     }
                   1847:   else
                   1848:     {
                   1849:       /* Adjust the stack pointer.  The ABI sez to do this using `adds',
                   1850:         but the native C compiler on svr4 uses `addu'.  */
                   1851: 
                   1852:       fprintf (asm_file, "\taddu -%d,%ssp,%ssp\n",
                   1853:        total_fsize, i860_reg_prefix, i860_reg_prefix);
                   1854: 
                   1855:       /* Save the old frame pointer.  */
                   1856: 
                   1857:       fprintf (asm_file, "\tst.l %sfp,%d(%ssp)\n",
                   1858:        i860_reg_prefix, frame_lower_bytes, i860_reg_prefix);
                   1859: 
                   1860:       /* Setup the new frame pointer.  The ABI sez to do this after
                   1861:         preserving registers and after saving the return address,
                   1862:        (and its saz to do this using adds), but that's not what the
                   1863:         native C compiler on svr4 does.  */
                   1864: 
                   1865:       fprintf (asm_file, "\taddu %d,%ssp,%sfp\n",
                   1866:        frame_lower_bytes, i860_reg_prefix, i860_reg_prefix);
                   1867: 
                   1868:       /* Preserve registers.  The ABI sez to do this before setting
                   1869:         up the new frame pointer, but that's not what the native
                   1870:         compiler on svr4 does.  */
                   1871: 
                   1872:       for (i = 1; i < 32; i++)
                   1873:         if (regs_ever_live[i] && ! call_used_regs[i])
                   1874:           fprintf (asm_file, "\tst.l %s%s,%d(%sfp)\n",
                   1875:            i860_reg_prefix, reg_names[i],
                   1876:            must_preserve_bytes + (4 * preserved_so_far++),
                   1877:            i860_reg_prefix);
                   1878: 
                   1879:       for (i = 32; i < 64; i++)
                   1880:         if (regs_ever_live[i] && ! call_used_regs[i])
                   1881:           fprintf (asm_file, "\tfst.l %s%s,%d(%sfp)\n",
                   1882:            i860_reg_prefix, reg_names[i],
                   1883:            must_preserve_bytes + (4 * preserved_so_far++),
                   1884:            i860_reg_prefix);
                   1885: 
                   1886:       /* Save the return address.  The ABI sez to do this earlier,
                   1887:         and also via an offset from %sp, but the native C compiler
                   1888:         on svr4 does it later (i.e. now) and uses an offset from
                   1889:         %fp.  */
                   1890: 
                   1891:       if (must_preserve_r1)
                   1892:         fprintf (asm_file, "\tst.l %sr1,4(%sfp)\n",
                   1893:          i860_reg_prefix, i860_reg_prefix);
                   1894:     }
                   1895: 
                   1896: #else /* defined(I860_STRICT_ABI_PROLOGUES) */
                   1897: 
                   1898:   /* There are two kinds of function prologues.
                   1899:      You use the "small" version if the total frame size is
                   1900:      small enough so that it can fit into an immediate 16-bit
                   1901:      value in one instruction.  Otherwise, you use the "large"
                   1902:      version of the function prologue.  */
                   1903: 
                   1904:   if (total_fsize > 0x7fff)
                   1905:     {
                   1906:       /* Adjust the stack pointer (thereby allocating a new frame).  */
                   1907: 
                   1908:       fprintf (asm_file, "\tadds -%d,%ssp,%ssp\n",
                   1909:        frame_upper_bytes, i860_reg_prefix, i860_reg_prefix);
                   1910: 
                   1911:       /* Save the caller's frame pointer.  */
                   1912: 
                   1913:       fprintf (asm_file, "\tst.l %sfp,0(%ssp)\n",
                   1914:        i860_reg_prefix, i860_reg_prefix);
                   1915: 
                   1916:       /* Save return address.  */
                   1917: 
                   1918:       if (must_preserve_r1)
                   1919:         fprintf (asm_file, "\tst.l %sr1,4(%ssp)\n",
                   1920:          i860_reg_prefix, i860_reg_prefix);
                   1921: 
                   1922:       /* Get the value of frame_lower_bytes into r31 for later use.  */
                   1923: 
                   1924:       fprintf (asm_file, "\torh %d,%sr0,%sr31\n",
                   1925:        frame_lower_bytes >> 16, i860_reg_prefix, i860_reg_prefix);
                   1926:       fprintf (asm_file, "\tor %d,%sr31,%sr31\n",
                   1927:        frame_lower_bytes & 0xffff, i860_reg_prefix, i860_reg_prefix);
                   1928: 
                   1929:       /* Now re-adjust the stack pointer using the value in r31.  */
                   1930: 
                   1931:       fprintf (asm_file, "\tsubs %ssp,%sr31,%ssp\n",
                   1932:        i860_reg_prefix, i860_reg_prefix, i860_reg_prefix);
                   1933: 
                   1934:       /* Pre-compute value to be used as the new frame pointer.  */
                   1935: 
                   1936:       fprintf (asm_file, "\tadds %ssp,%sr31,%sr31\n",
                   1937:        i860_reg_prefix, i860_reg_prefix, i860_reg_prefix);
                   1938: 
                   1939:       /* Preserve registers.  */
                   1940: 
                   1941:       for (i = 1; i < 32; i++)
                   1942:         if (regs_ever_live[i] && ! call_used_regs[i])
                   1943:           fprintf (asm_file, "\tst.l %s%s,%d(%sr31)\n",
                   1944:            i860_reg_prefix, reg_names[i],
                   1945:            must_preserve_bytes + (4 * preserved_so_far++),
                   1946:            i860_reg_prefix);
                   1947: 
                   1948:       for (i = 32; i < 64; i++)
                   1949:         if (regs_ever_live[i] && ! call_used_regs[i])
                   1950:           fprintf (asm_file, "\tfst.l %s%s,%d(%sr31)\n",
                   1951:            i860_reg_prefix, reg_names[i],
                   1952:            must_preserve_bytes + (4 * preserved_so_far++),
                   1953:            i860_reg_prefix);
                   1954: 
                   1955:       /* Actually set the new value of the frame pointer.  */
                   1956: 
                   1957:       fprintf (asm_file, "\tmov %sr31,%sfp\n",
                   1958:        i860_reg_prefix, i860_reg_prefix);
                   1959:     }
                   1960:   else
                   1961:     {
                   1962:       /* Adjust the stack pointer.  */
                   1963: 
                   1964:       fprintf (asm_file, "\tadds -%d,%ssp,%ssp\n",
                   1965:        total_fsize, i860_reg_prefix, i860_reg_prefix);
                   1966: 
                   1967:       /* Save the caller's frame pointer.  */
                   1968: 
                   1969:       fprintf (asm_file, "\tst.l %sfp,%d(%ssp)\n",
                   1970:        i860_reg_prefix, frame_lower_bytes, i860_reg_prefix);
                   1971: 
                   1972:       /* Save the return address.  */
                   1973: 
                   1974:       if (must_preserve_r1)
                   1975:         fprintf (asm_file, "\tst.l %sr1,%d(%ssp)\n",
                   1976:          i860_reg_prefix, frame_lower_bytes + 4, i860_reg_prefix);
                   1977: 
                   1978:       /* Preserve registers.  */
                   1979: 
                   1980:       for (i = 1; i < 32; i++)
                   1981:         if (regs_ever_live[i] && ! call_used_regs[i])
                   1982:           fprintf (asm_file, "\tst.l %s%s,%d(%ssp)\n",
                   1983:            i860_reg_prefix, reg_names[i],
                   1984:            frame_lower_bytes + must_preserve_bytes + (4 * preserved_so_far++),
                   1985:            i860_reg_prefix);
                   1986: 
                   1987:       for (i = 32; i < 64; i++)
                   1988:         if (regs_ever_live[i] && ! call_used_regs[i])
                   1989:           fprintf (asm_file, "\tfst.l %s%s,%d(%ssp)\n",
                   1990:            i860_reg_prefix, reg_names[i],
                   1991:            frame_lower_bytes + must_preserve_bytes + (4 * preserved_so_far++),
                   1992:            i860_reg_prefix);
                   1993: 
                   1994:       /* Setup the new frame pointer.  */
                   1995: 
                   1996:       fprintf (asm_file, "\tadds %d,%ssp,%sfp\n",
                   1997:        frame_lower_bytes, i860_reg_prefix, i860_reg_prefix);
                   1998:     }
                   1999: #endif /* defined(I860_STRICT_ABI_PROLOGUES) */
                   2000: 
                   2001: #ifdef ASM_OUTPUT_PROLOGUE_SUFFIX
                   2002:   ASM_OUTPUT_PROLOGUE_SUFFIX (asm_file);
                   2003: #endif /* defined(ASM_OUTPUT_PROLOGUE_SUFFIX) */
                   2004: }
                   2005: 
                   2006: /* This function generates the assembly code for function exit.
                   2007:    The macro FUNCTION_EPILOGUE in i860.h is defined to call this function.
                   2008: 
                   2009:    ASM_FILE is a stdio stream to output the code to.
                   2010:    SIZE is an int: how many units of temporary storage to allocate.
                   2011: 
                   2012:    The function epilogue should not depend on the current stack pointer!
                   2013:    It should use the frame pointer only.  This is mandatory because
                   2014:    of alloca; we also take advantage of it to omit stack adjustments
                   2015:    before returning.
                   2016: 
                   2017:    Note that when we go to restore the preserved register values we must
                   2018:    not try to address their slots by using offsets from the stack pointer.
                   2019:    That's because the stack pointer may have been moved during the function
                   2020:    execution due to a call to alloca().  Rather, we must restore all
                   2021:    preserved registers via offsets from the frame pointer value.
                   2022: 
                   2023:    Note also that when the current frame is being "popped" (by adjusting
                   2024:    the value of the stack pointer) on function exit, we must (for the
                   2025:    sake of alloca) set the new value of the stack pointer based upon
                   2026:    the current value of the frame pointer.  We can't just add what we
                   2027:    believe to be the (static) frame size to the stack pointer because
                   2028:    if we did that, and alloca() had been called during this function,
                   2029:    we would end up returning *without* having fully deallocated all of
                   2030:    the space grabbed by alloca.  If that happened, and a function
                   2031:    containing one or more alloca() calls was called over and over again,
                   2032:    then the stack would grow without limit!
                   2033: 
                   2034:    Finally note that the epilogues generated here are completely ABI
                   2035:    compliant.  They go out of their way to insure that the value in
                   2036:    the frame pointer register is never less than the value in the stack
                   2037:    pointer register.  It's not clear why this relationship needs to be
                   2038:    maintained at all times, but maintaining it only costs one extra
                   2039:    instruction, so what the hell.
                   2040: */
                   2041: 
1.1.1.3 ! root     2042: /* This corresponds to a version 4 TDESC structure. Lower numbered
        !          2043:    versions successively omit the last word of the structure. We
        !          2044:    don't try to handle version 5 here. */
        !          2045: 
        !          2046: typedef struct TDESC_flags {
        !          2047:        int version:4;
        !          2048:        int reg_packing:1;
        !          2049:        int callable_block:1;
        !          2050:        int reserved:4;
        !          2051:        int fregs:6;    /* fp regs 2-7 */
        !          2052:        int iregs:16;   /* regs 0-15 */
        !          2053: } TDESC_flags;
        !          2054: 
        !          2055: typedef struct TDESC {
        !          2056:        TDESC_flags flags;
        !          2057:        int integer_reg_offset;         /* same as must_preserve_bytes */
        !          2058:        int floating_point_reg_offset;
        !          2059:        unsigned int positive_frame_size;       /* same as frame_upper_bytes */
        !          2060:        unsigned int negative_frame_size;       /* same as frame_lower_bytes */
        !          2061: } TDESC;
        !          2062: 
1.1       root     2063: void
                   2064: function_epilogue (asm_file, local_bytes)
                   2065:      register FILE *asm_file;
                   2066:      register unsigned local_bytes;
                   2067: {
                   2068:   register unsigned frame_upper_bytes;
1.1.1.3 ! root     2069:   register unsigned frame_lower_bytes;
1.1       root     2070:   register unsigned preserved_reg_bytes = 0;
                   2071:   register unsigned i;
                   2072:   register unsigned restored_so_far = 0;
1.1.1.3 ! root     2073:   register unsigned int_restored;
        !          2074:   register unsigned mask;
        !          2075:   unsigned intflags=0;
        !          2076:   register TDESC_flags *flags = (TDESC_flags *) &intflags;
        !          2077: 
        !          2078:   flags->version = 4;
        !          2079:   flags->reg_packing = 1;
        !          2080:   flags->iregs = 8;    /* old fp always gets saved */
        !          2081: 
        !          2082:   /* Round-up the frame_lower_bytes so that it's a multiple of 16. */
        !          2083: 
        !          2084:   frame_lower_bytes = (local_bytes + STACK_ALIGNMENT - 1) & -STACK_ALIGNMENT;
1.1       root     2085: 
                   2086:   /* Count the number of registers that were preserved in the prologue.
                   2087:      Ignore r0.  It is never preserved.  */
                   2088: 
                   2089:   for (i = 1; i < FIRST_PSEUDO_REGISTER; i++)
                   2090:     {
                   2091:       if (regs_ever_live[i] && ! call_used_regs[i])
                   2092:         preserved_reg_bytes += 4;
                   2093:     }
                   2094: 
                   2095:   /* The upper part of each frame will contain only saved fp,
                   2096:      the saved r1, and stack slots for all of the other "preserved"
                   2097:      registers that we find we will need to save & restore. */
                   2098: 
                   2099:   frame_upper_bytes = must_preserve_bytes + preserved_reg_bytes;
                   2100: 
                   2101:   /* Round-up frame_upper_bytes so that t is a multiple of 16. */
                   2102: 
                   2103:   frame_upper_bytes
                   2104:     = (frame_upper_bytes + STACK_ALIGNMENT - 1) & -STACK_ALIGNMENT;
                   2105: 
                   2106:   /* Restore all of the "preserved" registers that need restoring.  */
                   2107: 
1.1.1.3 ! root     2108:   mask = 2;
        !          2109: 
        !          2110:   for (i = 1; i < 32; i++, mask<<=1)
        !          2111:     if (regs_ever_live[i] && ! call_used_regs[i]) {
1.1       root     2112:       fprintf (asm_file, "\tld.l %d(%sfp),%s%s\n",
                   2113:        must_preserve_bytes + (4 * restored_so_far++),
                   2114:        i860_reg_prefix, i860_reg_prefix, reg_names[i]);
1.1.1.3 ! root     2115:       if (i > 3 && i < 16)
        !          2116:        flags->iregs |= mask;
        !          2117:     }
1.1       root     2118: 
1.1.1.3 ! root     2119:   int_restored = restored_so_far;
        !          2120:   mask = 1;
        !          2121: 
        !          2122:   for (i = 32; i < 64; i++) {
        !          2123:     if (regs_ever_live[i] && ! call_used_regs[i]) {
1.1       root     2124:       fprintf (asm_file, "\tfld.l %d(%sfp),%s%s\n",
                   2125:        must_preserve_bytes + (4 * restored_so_far++),
                   2126:        i860_reg_prefix, i860_reg_prefix, reg_names[i]);
1.1.1.3 ! root     2127:       if (i > 33 & i < 40)
        !          2128:        flags->fregs |= mask;
        !          2129:     }
        !          2130:     if (i > 33 && i < 40)
        !          2131:       mask<<=1;
        !          2132:   }
1.1       root     2133: 
                   2134:   /* Get the value we plan to use to restore the stack pointer into r31.  */
                   2135: 
                   2136:   fprintf (asm_file, "\tadds %d,%sfp,%sr31\n",
                   2137:     frame_upper_bytes, i860_reg_prefix, i860_reg_prefix);
                   2138: 
                   2139:   /* Restore the return address and the old frame pointer.  */
                   2140: 
1.1.1.3 ! root     2141:   if (must_preserve_r1) {
1.1       root     2142:     fprintf (asm_file, "\tld.l 4(%sfp),%sr1\n",
                   2143:       i860_reg_prefix, i860_reg_prefix);
1.1.1.3 ! root     2144:     flags->iregs |= 2;
        !          2145:   }
1.1       root     2146: 
                   2147:   fprintf (asm_file, "\tld.l 0(%sfp),%sfp\n",
                   2148:     i860_reg_prefix, i860_reg_prefix);
                   2149: 
                   2150:   /* Return and restore the old stack pointer value.  */
                   2151: 
                   2152:   fprintf (asm_file, "\tbri %sr1\n\tmov %sr31,%ssp\n",
                   2153:     i860_reg_prefix, i860_reg_prefix, i860_reg_prefix);
1.1.1.3 ! root     2154: 
        !          2155: #ifdef OUTPUT_TDESC    /* Output an ABI-compliant TDESC entry */
        !          2156:   if (! frame_lower_bytes) {
        !          2157:     flags->version--;
        !          2158:     if (! frame_upper_bytes) {
        !          2159:       flags->version--;
        !          2160:       if (restored_so_far == int_restored)     /* No FP saves */
        !          2161:        flags->version--;
        !          2162:     }
        !          2163:   }
        !          2164:   assemble_name(asm_file,current_function_original_name);
        !          2165:   fputs(".TDESC:\n", asm_file);
        !          2166:   fprintf(asm_file, "%s 0x%0x\n", ASM_LONG, intflags);
        !          2167:   fprintf(asm_file, "%s %d\n", ASM_LONG,
        !          2168:        int_restored ? must_preserve_bytes : 0);
        !          2169:   if (flags->version > 1) {
        !          2170:     fprintf(asm_file, "%s %d\n", ASM_LONG,
        !          2171:        (restored_so_far == int_restored) ? 0 : must_preserve_bytes +
        !          2172:          (4 * int_restored));
        !          2173:     if (flags->version > 2) {
        !          2174:       fprintf(asm_file, "%s %d\n", ASM_LONG, frame_upper_bytes);
        !          2175:       if (flags->version > 3)
        !          2176:        fprintf(asm_file, "%s %d\n", ASM_LONG, frame_lower_bytes);
        !          2177:     }
        !          2178:   }
        !          2179:   tdesc_section();
        !          2180:   fprintf(asm_file, "%s ", ASM_LONG);
        !          2181:   assemble_name(asm_file, current_function_original_name);
        !          2182:   fprintf(asm_file, "\n%s ", ASM_LONG);
        !          2183:   assemble_name(asm_file, current_function_original_name);
        !          2184:   fputs(".TDESC\n", asm_file);
        !          2185:   text_section();
        !          2186: #endif
1.1       root     2187: }

unix.superglobalmegacorp.com

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