Annotation of gcc/config/sparc/sparc.c, revision 1.1.1.1

1.1       root        1: /* Subroutines for insn-output.c for Sun SPARC.
                      2:    Copyright (C) 1987, 1988, 1989, 1992 Free Software Foundation, Inc.
                      3:    Contributed by Michael Tiemann ([email protected])
                      4: 
                      5: This file is part of GNU CC.
                      6: 
                      7: GNU CC is free software; you can redistribute it and/or modify
                      8: it under the terms of the GNU General Public License as published by
                      9: the Free Software Foundation; either version 2, or (at your option)
                     10: any later version.
                     11: 
                     12: GNU CC is distributed in the hope that it will be useful,
                     13: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     15: GNU General Public License for more details.
                     16: 
                     17: You should have received a copy of the GNU General Public License
                     18: along with GNU CC; see the file COPYING.  If not, write to
                     19: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
                     20: 
                     21: #include <stdio.h>
                     22: #include "config.h"
                     23: #include "tree.h"
                     24: #include "rtl.h"
                     25: #include "regs.h"
                     26: #include "hard-reg-set.h"
                     27: #include "real.h"
                     28: #include "insn-config.h"
                     29: #include "conditions.h"
                     30: #include "insn-flags.h"
                     31: #include "output.h"
                     32: #include "insn-attr.h"
                     33: #include "flags.h"
                     34: #include "expr.h"
                     35: #include "recog.h"
                     36: 
                     37: /* Global variables for machine-dependent things.  */
                     38: 
                     39: /* Save the operands last given to a compare for use when we
                     40:    generate a scc or bcc insn.  */
                     41: 
                     42: rtx sparc_compare_op0, sparc_compare_op1;
                     43: 
                     44: /* We may need an epilogue if we spill too many registers.
                     45:    If this is non-zero, then we branch here for the epilogue.  */
                     46: static rtx leaf_label;
                     47: 
                     48: #ifdef LEAF_REGISTERS
                     49: 
                     50: /* Vector to say how input registers are mapped to output
                     51:    registers.  FRAME_POINTER_REGNUM cannot be remapped by
                     52:    this function to eliminate it.  You must use -fomit-frame-pointer
                     53:    to get that.  */
                     54: char leaf_reg_remap[] =
                     55: { 0, 1, 2, 3, 4, 5, 6, 7,
                     56:   -1, -1, -1, -1, -1, -1, 14, -1,
                     57:   -1, -1, -1, -1, -1, -1, -1, -1,
                     58:   8, 9, 10, 11, 12, 13, -1, 15,
                     59: 
                     60:   32, 33, 34, 35, 36, 37, 38, 39,
                     61:   40, 41, 42, 43, 44, 45, 46, 47,
                     62:   48, 49, 50, 51, 52, 53, 54, 55,
                     63:   56, 57, 58, 59, 60, 61, 62, 63};
                     64: 
                     65: char leaf_reg_backmap[] =
                     66: { 0, 1, 2, 3, 4, 5, 6, 7,
                     67:   24, 25, 26, 27, 28, 29, 14, 31,
                     68:   -1, -1, -1, -1, -1, -1, -1, -1,
                     69:   -1, -1, -1, -1, -1, -1, -1, -1,
                     70: 
                     71:   32, 33, 34, 35, 36, 37, 38, 39,
                     72:   40, 41, 42, 43, 44, 45, 46, 47,
                     73:   48, 49, 50, 51, 52, 53, 54, 55,
                     74:   56, 57, 58, 59, 60, 61, 62, 63};
                     75: #endif
                     76: 
                     77: /* Global variables set by FUNCTION_PROLOGUE.  */
                     78: /* Size of frame.  Need to know this to emit return insns from
                     79:    leaf procedures.  */
                     80: int apparent_fsize;
                     81: int actual_fsize;
                     82: 
                     83: /* Name of where we pretend to think the frame pointer points.
                     84:    Normally, this is "%fp", but if we are in a leaf procedure,
                     85:    this is "%sp+something".  */
                     86: char *frame_base_name;
                     87: 
                     88: static rtx find_addr_reg ();
                     89: 
                     90: /* Return non-zero only if OP is a register of mode MODE,
                     91:    or const0_rtx.  */
                     92: int
                     93: reg_or_0_operand (op, mode)
                     94:      rtx op;
                     95:      enum machine_mode mode;
                     96: {
                     97:   if (op == const0_rtx || register_operand (op, mode))
                     98:     return 1;
                     99:   if (GET_CODE (op) == CONST_DOUBLE
                    100:       && CONST_DOUBLE_HIGH (op) == 0
                    101:       && CONST_DOUBLE_LOW (op) == 0)
                    102:     return 1;
                    103:   return 0;
                    104: }
                    105: 
                    106: /* Nonzero if OP can appear as the dest of a RESTORE insn.  */
                    107: int
                    108: restore_operand (op, mode)
                    109:      rtx op;
                    110:      enum machine_mode mode;
                    111: {
                    112:   return (GET_CODE (op) == REG && GET_MODE (op) == mode
                    113:          && (REGNO (op) < 8 || (REGNO (op) >= 24 && REGNO (op) < 32)));
                    114: }
                    115: 
                    116: /* Call insn on SPARC can take a PC-relative constant address, or any regular
                    117:    memory address.  */
                    118: 
                    119: int
                    120: call_operand (op, mode)
                    121:      rtx op;
                    122:      enum machine_mode mode;
                    123: {
                    124:   if (GET_CODE (op) != MEM)
                    125:     abort ();
                    126:   op = XEXP (op, 0);
                    127:   return (CONSTANT_P (op) || memory_address_p (Pmode, op));
                    128: }
                    129: 
                    130: int
                    131: call_operand_address (op, mode)
                    132:      rtx op;
                    133:      enum machine_mode mode;
                    134: {
                    135:   return (CONSTANT_P (op) || memory_address_p (Pmode, op));
                    136: }
                    137: 
                    138: /* Returns 1 if OP is either a symbol reference or a sum of a symbol
                    139:    reference and a constant.  */
                    140: 
                    141: int
                    142: symbolic_operand (op, mode)
                    143:      register rtx op;
                    144:      enum machine_mode mode;
                    145: {
                    146:   switch (GET_CODE (op))
                    147:     {
                    148:     case SYMBOL_REF:
                    149:     case LABEL_REF:
                    150:       return 1;
                    151: 
                    152:     case CONST:
                    153:       op = XEXP (op, 0);
                    154:       return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
                    155:               || GET_CODE (XEXP (op, 0)) == LABEL_REF)
                    156:              && GET_CODE (XEXP (op, 1)) == CONST_INT);
                    157: 
                    158:       /* ??? This clause seems to be irrelevant.  */
                    159:     case CONST_DOUBLE:
                    160:       return GET_MODE (op) == mode;
                    161: 
                    162:     default:
                    163:       return 0;
                    164:     }
                    165: }
                    166: 
                    167: /* Return truth value of statement that OP is a symbolic memory
                    168:    operand of mode MODE.  */
                    169: 
                    170: int
                    171: symbolic_memory_operand (op, mode)
                    172:      rtx op;
                    173:      enum machine_mode mode;
                    174: {
                    175:   if (GET_CODE (op) == SUBREG)
                    176:     op = SUBREG_REG (op);
                    177:   if (GET_CODE (op) != MEM)
                    178:     return 0;
                    179:   op = XEXP (op, 0);
                    180:   return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST
                    181:          || GET_CODE (op) == HIGH || GET_CODE (op) == LABEL_REF);
                    182: }
                    183: 
                    184: /* Return 1 if the operand is either a register or a memory operand that is
                    185:    not symbolic.  */
                    186: 
                    187: int
                    188: reg_or_nonsymb_mem_operand (op, mode)
                    189:     register rtx op;
                    190:     enum machine_mode mode;
                    191: {
                    192:   if (register_operand (op, mode))
                    193:     return 1;
                    194: 
                    195:   if (memory_operand (op, mode) && ! symbolic_memory_operand (op, mode))
                    196:     return 1;
                    197: 
                    198:   return 0;
                    199: }
                    200: 
                    201: int
                    202: sparc_operand (op, mode)
                    203:      rtx op;
                    204:      enum machine_mode mode;
                    205: {
                    206:   if (register_operand (op, mode))
                    207:     return 1;
                    208:   if (GET_CODE (op) == CONST_INT)
                    209:     return SMALL_INT (op);
                    210:   if (GET_MODE (op) != mode)
                    211:     return 0;
                    212:   if (GET_CODE (op) == SUBREG)
                    213:     op = SUBREG_REG (op);
                    214:   if (GET_CODE (op) != MEM)
                    215:     return 0;
                    216: 
                    217:   op = XEXP (op, 0);
                    218:   if (GET_CODE (op) == LO_SUM)
                    219:     return (GET_CODE (XEXP (op, 0)) == REG
                    220:            && symbolic_operand (XEXP (op, 1), Pmode));
                    221:   return memory_address_p (mode, op);
                    222: }
                    223: 
                    224: int
                    225: move_operand (op, mode)
                    226:      rtx op;
                    227:      enum machine_mode mode;
                    228: {
                    229:   if (mode == DImode && arith_double_operand (op, mode))
                    230:     return 1;
                    231:   if (register_operand (op, mode))
                    232:     return 1;
                    233:   if (GET_CODE (op) == CONST_INT)
                    234:     return (SMALL_INT (op) || (INTVAL (op) & 0x3ff) == 0);
                    235: 
                    236:   if (GET_MODE (op) != mode)
                    237:     return 0;
                    238:   if (GET_CODE (op) == SUBREG)
                    239:     op = SUBREG_REG (op);
                    240:   if (GET_CODE (op) != MEM)
                    241:     return 0;
                    242:   op = XEXP (op, 0);
                    243:   if (GET_CODE (op) == LO_SUM)
                    244:     return (register_operand (XEXP (op, 0), Pmode)
                    245:            && CONSTANT_P (XEXP (op, 1)));
                    246:   return memory_address_p (mode, op);
                    247: }
                    248: 
                    249: int
                    250: move_pic_label (op, mode)
                    251:      rtx op;
                    252:      enum machine_mode mode;
                    253: {
                    254:   /* Special case for PIC.  */
                    255:   if (flag_pic && GET_CODE (op) == LABEL_REF)
                    256:     return 1;
                    257:   return 0;
                    258: }
                    259: 
                    260: /* The rtx for the global offset table which is a special form
                    261:    that *is* a position independent symbolic constant.  */
                    262: rtx pic_pc_rtx;
                    263: 
                    264: /* Ensure that we are not using patterns that are not OK with PIC.  */
                    265: 
                    266: int
                    267: check_pic (i)
                    268:      int i;
                    269: {
                    270:   switch (flag_pic)
                    271:     {
                    272:     case 1:
                    273:       if (GET_CODE (recog_operand[i]) == SYMBOL_REF
                    274:          || (GET_CODE (recog_operand[i]) == CONST
                    275:              && ! rtx_equal_p (pic_pc_rtx, recog_operand[i])))
                    276:        abort ();
                    277:     case 2:
                    278:     default:
                    279:       return 1;
                    280:     }
                    281: }
                    282: 
                    283: /* Return true if X is an address which needs a temporary register when 
                    284:    reloaded while generating PIC code.  */
                    285: 
                    286: int
                    287: pic_address_needs_scratch (x)
                    288:      rtx x;
                    289: {
                    290:   /* An address which is a symbolic plus a non SMALL_INT needs a temp reg.  */
                    291:   if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS
                    292:       && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
                    293:       && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
                    294:       && ! SMALL_INT (XEXP (XEXP (x, 0), 1)))
                    295:     return 1;
                    296: 
                    297:   return 0;
                    298: }
                    299: 
                    300: int
                    301: memop (op, mode)
                    302:      rtx op;
                    303:      enum machine_mode mode;
                    304: {
                    305:   if (GET_CODE (op) == MEM)
                    306:     return (mode == VOIDmode || mode == GET_MODE (op));
                    307:   return 0;
                    308: }
                    309: 
                    310: /* Return truth value of whether OP is EQ or NE.  */
                    311: 
                    312: int
                    313: eq_or_neq (op, mode)
                    314:      rtx op;
                    315:      enum machine_mode mode;
                    316: {
                    317:   return (GET_CODE (op) == EQ || GET_CODE (op) == NE);
                    318: }
                    319: 
                    320: /* Return 1 if this is a comparison operator, but not an EQ, NE, GEU,
                    321:    or LTU for non-floating-point.  We handle those specially.  */
                    322: 
                    323: int
                    324: normal_comp_operator (op, mode)
                    325:      rtx op;
                    326:      enum machine_mode mode;
                    327: {
                    328:   enum rtx_code code = GET_CODE (op);
                    329: 
                    330:   if (GET_RTX_CLASS (code) != '<')
                    331:     return 0;
                    332: 
                    333:   if (GET_MODE (XEXP (op, 0)) == CCFPmode
                    334:       || GET_MODE (XEXP (op, 0)) == CCFPEmode)
                    335:     return 1;
                    336: 
                    337:   return (code != NE && code != EQ && code != GEU && code != LTU);
                    338: }
                    339: 
                    340: /* Return 1 if this is a comparison operator.  This allows the use of
                    341:    MATCH_OPERATOR to recognize all the branch insns.  */
                    342: 
                    343: int
                    344: noov_compare_op (op, mode)
                    345:     register rtx op;
                    346:     enum machine_mode mode;
                    347: {
                    348:   enum rtx_code code = GET_CODE (op);
                    349: 
                    350:   if (GET_RTX_CLASS (code) != '<')
                    351:     return 0;
                    352: 
                    353:   if (GET_MODE (XEXP (op, 0)) == CC_NOOVmode)
                    354:     /* These are the only branches which work with CC_NOOVmode.  */
                    355:     return (code == EQ || code == NE || code == GE || code == LT);
                    356:   return 1;
                    357: }
                    358: 
                    359: /* Return 1 if this is a SIGN_EXTEND or ZERO_EXTEND operation.  */
                    360: 
                    361: int
                    362: extend_op (op, mode)
                    363:      rtx op;
                    364:      enum machine_mode mode;
                    365: {
                    366:   return GET_CODE (op) == SIGN_EXTEND || GET_CODE (op) == ZERO_EXTEND;
                    367: }
                    368: 
                    369: /* Return nonzero if OP is an operator of mode MODE which can set
                    370:    the condition codes explicitly.  We do not include PLUS and MINUS
                    371:    because these require CC_NOOVmode, which we handle explicitly.  */
                    372: 
                    373: int
                    374: cc_arithop (op, mode)
                    375:      rtx op;
                    376:      enum machine_mode mode;
                    377: {
                    378:   if (GET_CODE (op) == AND
                    379:       || GET_CODE (op) == IOR
                    380:       || GET_CODE (op) == XOR)
                    381:     return 1;
                    382: 
                    383:   return 0;
                    384: }
                    385: 
                    386: /* Return nonzero if OP is an operator of mode MODE which can bitwise
                    387:    complement its second operand and set the condition codes explicitly.  */
                    388: 
                    389: int
                    390: cc_arithopn (op, mode)
                    391:      rtx op;
                    392:      enum machine_mode mode;
                    393: {
                    394:   /* XOR is not here because combine canonicalizes (xor (not ...) ...)
                    395:      and (xor ... (not ...)) to (not (xor ...)).   */
                    396:   return (GET_CODE (op) == AND
                    397:          || GET_CODE (op) == IOR);
                    398: }
                    399: 
                    400: /* Return true if OP is a register, or is a CONST_INT that can fit in a 13
                    401:    bit immediate field.  This is an acceptable SImode operand for most 3
                    402:    address instructions.  */
                    403: 
                    404: int
                    405: arith_operand (op, mode)
                    406:      rtx op;
                    407:      enum machine_mode mode;
                    408: {
                    409:   return (register_operand (op, mode)
                    410:          || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
                    411: }
                    412: 
                    413: /* Return true if OP is a register, or is a CONST_INT or CONST_DOUBLE that
                    414:    can fit in a 13 bit immediate field.  This is an acceptable DImode operand
                    415:    for most 3 address instructions.  */
                    416: 
                    417: int
                    418: arith_double_operand (op, mode)
                    419:      rtx op;
                    420:      enum machine_mode mode;
                    421: {
                    422:   return (register_operand (op, mode)
                    423:          || (GET_CODE (op) == CONST_DOUBLE
                    424:              && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
                    425:              && (unsigned) (CONST_DOUBLE_LOW (op) + 0x1000) < 0x2000
                    426:              && ((CONST_DOUBLE_HIGH (op) == -1
                    427:                   && (CONST_DOUBLE_LOW (op) & 0x1000) == 0x1000)
                    428:                  || (CONST_DOUBLE_HIGH (op) == 0
                    429:                      && (CONST_DOUBLE_LOW (op) & 0x1000) == 0)))
                    430:          || (GET_CODE (op) == CONST_INT
                    431:              && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
                    432:              && (unsigned) (INTVAL (op) + 0x1000) < 0x2000));
                    433: }
                    434: 
                    435: /* Return truth value of whether OP is a integer which fits the
                    436:    range constraining immediate operands in most three-address insns,
                    437:    which have a 13 bit immediate field.  */
                    438: 
                    439: int
                    440: small_int (op, mode)
                    441:      rtx op;
                    442:      enum machine_mode mode;
                    443: {
                    444:   return (GET_CODE (op) == CONST_INT && SMALL_INT (op));
                    445: }
                    446: 
                    447: /* Return truth value of statement that OP is a call-clobbered register.  */
                    448: int
                    449: clobbered_register (op, mode)
                    450:      rtx op;
                    451:      enum machine_mode mode;
                    452: {
                    453:   return (GET_CODE (op) == REG && call_used_regs[REGNO (op)]);
                    454: }
                    455: 
                    456: /* X and Y are two things to compare using CODE.  Emit the compare insn and
                    457:    return the rtx for register 0 in the proper mode.  */
                    458: 
                    459: rtx
                    460: gen_compare_reg (code, x, y)
                    461:      enum rtx_code code;
                    462:      rtx x, y;
                    463: {
                    464:   enum machine_mode mode = SELECT_CC_MODE (code, x, y);
                    465:   rtx cc_reg = gen_rtx (REG, mode, 0);
                    466: 
                    467:   emit_insn (gen_rtx (SET, VOIDmode, cc_reg,
                    468:                      gen_rtx (COMPARE, mode, x, y)));
                    469: 
                    470:   return cc_reg;
                    471: }
                    472: 
                    473: /* Return nonzero if a return peephole merging return with
                    474:    setting of output register is ok.  */
                    475: int
                    476: leaf_return_peephole_ok ()
                    477: {
                    478:   return (actual_fsize == 0);
                    479: }
                    480: 
                    481: /* Return nonzero if TRIAL can go into the function epilogue's
                    482:    delay slot.  SLOT is the slot we are trying to fill.  */
                    483: 
                    484: int
                    485: eligible_for_epilogue_delay (trial, slot)
                    486:      rtx trial;
                    487:      int slot;
                    488: {
                    489:   rtx pat, src;
                    490: 
                    491:   if (slot >= 1)
                    492:     return 0;
                    493:   if (GET_CODE (trial) != INSN
                    494:       || GET_CODE (PATTERN (trial)) != SET)
                    495:     return 0;
                    496:   if (get_attr_length (trial) != 1)
                    497:     return 0;
                    498: 
                    499:   /* In the case of a true leaf function, anything can go into the delay slot.
                    500:      A delay slot only exists however if the frame size is zero, otherwise
                    501:      we will put an insn to adjust the stack after the return.  */
                    502:   if (leaf_function)
                    503:     {
                    504:       if (leaf_return_peephole_ok ())
                    505:        return (get_attr_in_uncond_branch_delay (trial) == IN_BRANCH_DELAY_TRUE);
                    506:       return 0;
                    507:     }
                    508: 
                    509:   /* Otherwise, only operations which can be done in tandem with
                    510:      a `restore' insn can go into the delay slot.  */
                    511:   pat = PATTERN (trial);
                    512:   if (GET_CODE (SET_DEST (pat)) != REG
                    513:       || REGNO (SET_DEST (pat)) == 0
                    514:       || REGNO (SET_DEST (pat)) >= 32
                    515:       || REGNO (SET_DEST (pat)) < 24)
                    516:     return 0;
                    517: 
                    518:   src = SET_SRC (pat);
                    519:   if (arith_operand (src, GET_MODE (src)))
                    520:     return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (SImode);
                    521:   if (arith_double_operand (src, GET_MODE (src)))
                    522:     return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (DImode);
                    523:   if (GET_CODE (src) == PLUS)
                    524:     {
                    525:       if (register_operand (XEXP (src, 0), SImode)
                    526:          && arith_operand (XEXP (src, 1), SImode))
                    527:        return 1;
                    528:       if (register_operand (XEXP (src, 1), SImode)
                    529:          && arith_operand (XEXP (src, 0), SImode))
                    530:        return 1;
                    531:       if (register_operand (XEXP (src, 0), DImode)
                    532:          && arith_double_operand (XEXP (src, 1), DImode))
                    533:        return 1;
                    534:       if (register_operand (XEXP (src, 1), DImode)
                    535:          && arith_double_operand (XEXP (src, 0), DImode))
                    536:        return 1;
                    537:     }
                    538:   if (GET_CODE (src) == MINUS
                    539:       && register_operand (XEXP (src, 0), SImode)
                    540:       && small_int (XEXP (src, 1), VOIDmode))
                    541:     return 1;
                    542:   if (GET_CODE (src) == MINUS
                    543:       && register_operand (XEXP (src, 0), DImode)
                    544:       && !register_operand (XEXP (src, 1), DImode)
                    545:       && arith_double_operand (XEXP (src, 1), DImode))
                    546:     return 1;
                    547:   return 0;
                    548: }
                    549: 
                    550: int
                    551: short_branch (uid1, uid2)
                    552:      int uid1, uid2;
                    553: {
                    554:   unsigned int delta = insn_addresses[uid1] - insn_addresses[uid2];
                    555:   if (delta + 1024 < 2048)
                    556:     return 1;
                    557:   /* warning ("long branch, distance %d", delta); */
                    558:   return 0;
                    559: }
                    560: 
                    561: /* Return non-zero if REG is not used after INSN.
                    562:    We assume REG is a reload reg, and therefore does
                    563:    not live past labels or calls or jumps.  */
                    564: int
                    565: reg_unused_after (reg, insn)
                    566:      rtx reg;
                    567:      rtx insn;
                    568: {
                    569:   enum rtx_code code, prev_code = UNKNOWN;
                    570: 
                    571:   while (insn = NEXT_INSN (insn))
                    572:     {
                    573:       if (prev_code == CALL_INSN && call_used_regs[REGNO (reg)])
                    574:        return 1;
                    575: 
                    576:       code = GET_CODE (insn);
                    577:       if (GET_CODE (insn) == CODE_LABEL)
                    578:        return 1;
                    579: 
                    580:       if (GET_RTX_CLASS (code) == 'i')
                    581:        {
                    582:          rtx set = single_set (insn);
                    583:          int in_src = set && reg_overlap_mentioned_p (reg, SET_SRC (set));
                    584:          if (set && in_src)
                    585:            return 0;
                    586:          if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
                    587:            return 1;
                    588:          if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
                    589:            return 0;
                    590:        }
                    591:       prev_code = code;
                    592:     }
                    593:   return 1;
                    594: }
                    595: 
                    596: /* Legitimize PIC addresses.  If the address is already position-independent,
                    597:    we return ORIG.  Newly generated position-independent addresses go into a
                    598:    reg.  This is REG if non zero, otherwise we allocate register(s) as
                    599:    necessary.  If this is called during reload, and we need a second temp
                    600:    register, then we use SCRATCH, which is provided via the
                    601:    SECONDARY_INPUT_RELOAD_CLASS mechanism.  */
                    602: 
                    603: rtx
                    604: legitimize_pic_address (orig, mode, reg, scratch)
                    605:      rtx orig;
                    606:      enum machine_mode mode;
                    607:      rtx reg, scratch;
                    608: {
                    609:   if (GET_CODE (orig) == SYMBOL_REF)
                    610:     {
                    611:       rtx pic_ref, address;
                    612:       rtx insn;
                    613: 
                    614:       if (reg == 0)
                    615:        {
                    616:          if (reload_in_progress || reload_completed)
                    617:            abort ();
                    618:          else
                    619:            reg = gen_reg_rtx (Pmode);
                    620:        }
                    621: 
                    622:       if (flag_pic == 2)
                    623:        {
                    624:          /* If not during reload, allocate another temp reg here for loading
                    625:             in the address, so that these instructions can be optimized
                    626:             properly.  */
                    627:          rtx temp_reg = ((reload_in_progress || reload_completed)
                    628:                          ? reg : gen_reg_rtx (Pmode));
                    629: 
                    630:          /* Must put the SYMBOL_REF inside an UNSPEC here so that cse
                    631:             won't get confused into thinking that these two instructions
                    632:             are loading in the true address of the symbol.  If in the
                    633:             future a PIC rtx exists, that should be used instead.  */
                    634:          emit_insn (gen_rtx (SET, VOIDmode, temp_reg,
                    635:                              gen_rtx (HIGH, Pmode,
                    636:                                       gen_rtx (UNSPEC, Pmode,
                    637:                                                gen_rtvec (1, orig),
                    638:                                                0))));
                    639:          emit_insn (gen_rtx (SET, VOIDmode, temp_reg,
                    640:                              gen_rtx (LO_SUM, Pmode, temp_reg,
                    641:                                       gen_rtx (UNSPEC, Pmode,
                    642:                                                gen_rtvec (1, orig),
                    643:                                                0))));
                    644:          address = temp_reg;
                    645:        }
                    646:       else
                    647:        address = orig;
                    648: 
                    649:       pic_ref = gen_rtx (MEM, Pmode,
                    650:                         gen_rtx (PLUS, Pmode,
                    651:                                  pic_offset_table_rtx, address));
                    652:       current_function_uses_pic_offset_table = 1;
                    653:       RTX_UNCHANGING_P (pic_ref) = 1;
                    654:       insn = emit_move_insn (reg, pic_ref);
                    655:       /* Put a REG_EQUAL note on this insn, so that it can be optimized
                    656:         by loop.  */
                    657:       REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, orig,
                    658:                                  REG_NOTES (insn));
                    659:       return reg;
                    660:     }
                    661:   else if (GET_CODE (orig) == CONST)
                    662:     {
                    663:       rtx base, offset;
                    664: 
                    665:       if (GET_CODE (XEXP (orig, 0)) == PLUS
                    666:          && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
                    667:        return orig;
                    668: 
                    669:       if (reg == 0)
                    670:        {
                    671:          if (reload_in_progress || reload_completed)
                    672:            abort ();
                    673:          else
                    674:            reg = gen_reg_rtx (Pmode);
                    675:        }
                    676: 
                    677:       if (GET_CODE (XEXP (orig, 0)) == PLUS)
                    678:        {
                    679:          base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode,
                    680:                                         reg, 0);
                    681:          offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
                    682:                                         base == reg ? 0 : reg, 0);
                    683:        }
                    684:       else
                    685:        abort ();
                    686: 
                    687:       if (GET_CODE (offset) == CONST_INT)
                    688:        {
                    689:          if (SMALL_INT (offset))
                    690:            return plus_constant_for_output (base, INTVAL (offset));
                    691:          else if (! reload_in_progress && ! reload_completed)
                    692:            offset = force_reg (Pmode, offset);
                    693:          /* We can't create any new registers during reload, so use the
                    694:             SCRATCH reg provided by the reload_insi pattern.  */
                    695:          else if (scratch)
                    696:            {
                    697:              emit_move_insn (scratch, offset);
                    698:              offset = scratch;
                    699:            }
                    700:          else
                    701:            /* If we reach here, then the SECONDARY_INPUT_RELOAD_CLASS
                    702:               macro needs to be adjusted so that a scratch reg is provided
                    703:               for this address.  */
                    704:            abort ();
                    705:        }
                    706:       return gen_rtx (PLUS, Pmode, base, offset);
                    707:     }
                    708:   else if (GET_CODE (orig) == LABEL_REF)
                    709:     current_function_uses_pic_offset_table = 1;
                    710: 
                    711:   return orig;
                    712: }
                    713: 
                    714: /* Set up PIC-specific rtl.  This should not cause any insns
                    715:    to be emitted.  */
                    716: 
                    717: void
                    718: initialize_pic ()
                    719: {
                    720: }
                    721: 
                    722: /* Emit special PIC prologues and epilogues.  */
                    723: 
                    724: void
                    725: finalize_pic ()
                    726: {
                    727:   /* The table we use to reference PIC data.  */
                    728:   rtx global_offset_table;
                    729:   /* Labels to get the PC in the prologue of this function.  */
                    730:   rtx l1, l2;
                    731:   rtx seq;
                    732:   int orig_flag_pic = flag_pic;
                    733: 
                    734:   if (current_function_uses_pic_offset_table == 0)
                    735:     return;
                    736: 
                    737:   if (! flag_pic)
                    738:     abort ();
                    739: 
                    740:   flag_pic = 0;
                    741:   l1 = gen_label_rtx ();
                    742:   l2 = gen_label_rtx ();
                    743: 
                    744:   start_sequence ();
                    745: 
                    746:   emit_label (l1);
                    747:   /* Note that we pun calls and jumps here!  */
                    748:   emit_jump_insn (gen_rtx (PARALLEL, VOIDmode,
                    749:                          gen_rtvec (2,
                    750:                                     gen_rtx (SET, VOIDmode, pc_rtx, gen_rtx (LABEL_REF, VOIDmode, l2)),
                    751:                                     gen_rtx (SET, VOIDmode, gen_rtx (REG, SImode, 15), gen_rtx (LABEL_REF, VOIDmode, l2)))));
                    752:   emit_label (l2);
                    753: 
                    754:   /* Initialize every time through, since we can't easily
                    755:      know this to be permanent.  */
                    756:   global_offset_table = gen_rtx (SYMBOL_REF, Pmode, "_GLOBAL_OFFSET_TABLE_");
                    757:   pic_pc_rtx = gen_rtx (CONST, Pmode,
                    758:                        gen_rtx (MINUS, Pmode,
                    759:                                 global_offset_table,
                    760:                                 gen_rtx (CONST, Pmode,
                    761:                                          gen_rtx (MINUS, Pmode,
                    762:                                                   gen_rtx (LABEL_REF, VOIDmode, l1),
                    763:                                                   pc_rtx))));
                    764: 
                    765:   emit_insn (gen_rtx (SET, VOIDmode, pic_offset_table_rtx,
                    766:                      gen_rtx (HIGH, Pmode, pic_pc_rtx)));
                    767:   emit_insn (gen_rtx (SET, VOIDmode,
                    768:                      pic_offset_table_rtx,
                    769:                      gen_rtx (LO_SUM, Pmode,
                    770:                               pic_offset_table_rtx, pic_pc_rtx)));
                    771:   emit_insn (gen_rtx (SET, VOIDmode,
                    772:                      pic_offset_table_rtx,
                    773:                      gen_rtx (PLUS, Pmode,
                    774:                               pic_offset_table_rtx, gen_rtx (REG, Pmode, 15))));
                    775:   /* emit_insn (gen_rtx (ASM_INPUT, VOIDmode, "!#PROLOGUE# 1")); */
                    776:   LABEL_PRESERVE_P (l1) = 1;
                    777:   LABEL_PRESERVE_P (l2) = 1;
                    778:   flag_pic = orig_flag_pic;
                    779: 
                    780:   seq = gen_sequence ();
                    781:   end_sequence ();
                    782:   emit_insn_after (seq, get_insns ());
                    783: 
                    784:   /* Need to emit this whether or not we obey regdecls,
                    785:      since setjmp/longjmp can cause life info to screw up.  */
                    786:   emit_insn (gen_rtx (USE, VOIDmode, pic_offset_table_rtx));
                    787: }
                    788: 
                    789: /* For the SPARC, REG and REG+CONST is cost 0, REG+REG is cost 1,
                    790:    and addresses involving symbolic constants are cost 2.
                    791: 
                    792:    We make REG+REG slightly more expensive because it might keep
                    793:    a register live for longer than we might like.
                    794: 
                    795:    PIC addresses are very expensive.
                    796: 
                    797:    It is no coincidence that this has the same structure
                    798:    as GO_IF_LEGITIMATE_ADDRESS.  */
                    799: int
                    800: sparc_address_cost (X)
                    801:      rtx X;
                    802: {
                    803: #if 0
                    804:   /* Handled before calling here.  */
                    805:   if (GET_CODE (X) == REG)
                    806:     { return 1; }
                    807: #endif
                    808:   if (GET_CODE (X) == PLUS)
                    809:     {
                    810:       if (GET_CODE (XEXP (X, 0)) == REG
                    811:          && GET_CODE (XEXP (X, 1)) == REG)
                    812:        return 2;
                    813:       return 1;
                    814:     }
                    815:   else if (GET_CODE (X) == LO_SUM)
                    816:     return 1;
                    817:   else if (GET_CODE (X) == HIGH)
                    818:     return 2;
                    819:   return 4;
                    820: }
                    821: 
                    822: /* Emit insns to move operands[1] into operands[0].
                    823: 
                    824:    Return 1 if we have written out everything that needs to be done to
                    825:    do the move.  Otherwise, return 0 and the caller will emit the move
                    826:    normally.
                    827: 
                    828:    SCRATCH_REG if non zero can be used as a scratch register for the move
                    829:    operation.  It is provided by a SECONDARY_RELOAD_* macro if needed.  */
                    830: 
                    831: int
                    832: emit_move_sequence (operands, mode, scratch_reg)
                    833:      rtx *operands;
                    834:      enum machine_mode mode;
                    835:      rtx scratch_reg;
                    836: {
                    837:   register rtx operand0 = operands[0];
                    838:   register rtx operand1 = operands[1];
                    839: 
                    840:   /* Handle most common case first: storing into a register.  */
                    841:   if (register_operand (operand0, mode))
                    842:     {
                    843:       if (register_operand (operand1, mode)
                    844:          || (GET_CODE (operand1) == CONST_INT && SMALL_INT (operand1))
                    845:          || (GET_CODE (operand1) == CONST_DOUBLE
                    846:              && arith_double_operand (operand1, DImode))
                    847:          || (GET_CODE (operand1) == HIGH && GET_MODE (operand1) != DImode)
                    848:          /* Only `general_operands' can come here, so MEM is ok.  */
                    849:          || GET_CODE (operand1) == MEM)
                    850:        {
                    851:          /* Run this case quickly.  */
                    852:          emit_insn (gen_rtx (SET, VOIDmode, operand0, operand1));
                    853:          return 1;
                    854:        }
                    855:     }
                    856:   else if (GET_CODE (operand0) == MEM)
                    857:     {
                    858:       if (register_operand (operand1, mode) || operand1 == const0_rtx)
                    859:        {
                    860:          /* Run this case quickly.  */
                    861:          emit_insn (gen_rtx (SET, VOIDmode, operand0, operand1));
                    862:          return 1;
                    863:        }
                    864:       if (! reload_in_progress)
                    865:        {
                    866:          operands[0] = validize_mem (operand0);
                    867:          operands[1] = operand1 = force_reg (mode, operand1);
                    868:        }
                    869:     }
                    870: 
                    871:   /* Simplify the source if we need to.  Must handle DImode HIGH operators
                    872:      here because such a move needs a clobber added.  */
                    873:   if ((GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode))
                    874:       || (GET_CODE (operand1) == HIGH && GET_MODE (operand1) == DImode))
                    875:     {
                    876:       if (flag_pic && symbolic_operand (operand1, mode))
                    877:        {
                    878:          rtx temp_reg = reload_in_progress ? operand0 : 0;
                    879: 
                    880:          operands[1] = legitimize_pic_address (operand1, mode, temp_reg,
                    881:                                                scratch_reg);
                    882:        }
                    883:       else if (GET_CODE (operand1) == CONST_INT
                    884:               ? (! SMALL_INT (operand1)
                    885:                  && (INTVAL (operand1) & 0x3ff) != 0)
                    886:               : (GET_CODE (operand1) == CONST_DOUBLE
                    887:                  ? ! arith_double_operand (operand1, DImode)
                    888:                  : 1))
                    889:        {
                    890:          /* For DImode values, temp must be operand0 because of the way
                    891:             HI and LO_SUM work.  The LO_SUM operator only copies half of
                    892:             the LSW from the dest of the HI operator.  If the LO_SUM dest is
                    893:             not the same as the HI dest, then the MSW of the LO_SUM dest will
                    894:             never be set.
                    895: 
                    896:             ??? The real problem here is that the ...(HI:DImode pattern emits
                    897:             multiple instructions, and the ...(LO_SUM:DImode pattern emits
                    898:             one instruction.  This fails, because the compiler assumes that
                    899:             LO_SUM copies all bits of the first operand to its dest.  Better
                    900:             would be to have the HI pattern emit one instruction and the
                    901:             LO_SUM pattern multiple instructions.  Even better would be
                    902:             to use four rtl insns.  */
                    903:          rtx temp = ((reload_in_progress || mode == DImode)
                    904:                      ? operand0 : gen_reg_rtx (mode));
                    905: 
                    906:          emit_insn (gen_rtx (SET, VOIDmode, temp,
                    907:                              gen_rtx (HIGH, mode, operand1)));
                    908:          operands[1] = gen_rtx (LO_SUM, mode, temp, operand1);
                    909:        }
                    910:     }
                    911: 
                    912:   if (GET_CODE (operand1) == LABEL_REF && flag_pic)
                    913:     {
                    914:       /* The procedure for doing this involves using a call instruction to
                    915:         get the pc into o7.  We need to indicate this explicitly because
                    916:         the tablejump pattern assumes that it can use this value also.  */
                    917:       emit_insn (gen_rtx (PARALLEL, VOIDmode,
                    918:                          gen_rtvec (2,
                    919:                                     gen_rtx (SET, VOIDmode, operand0,
                    920:                                              operand1),
                    921:                                     gen_rtx (SET, VOIDmode,
                    922:                                              gen_rtx (REG, mode, 15),
                    923:                                              pc_rtx))));
                    924:       return 1;
                    925:     }
                    926: 
                    927:   /* Now have insn-emit do whatever it normally does.  */
                    928:   return 0;
                    929: }
                    930: 
                    931: /* Return the best assembler insn template
                    932:    for moving operands[1] into operands[0] as a fullword.  */
                    933: 
                    934: char *
                    935: singlemove_string (operands)
                    936:      rtx *operands;
                    937: {
                    938:   if (GET_CODE (operands[0]) == MEM)
                    939:     {
                    940:       if (GET_CODE (operands[1]) != MEM)
                    941:        return "st %r1,%0";
                    942:       else
                    943:        abort ();
                    944:     }
                    945:   else if (GET_CODE (operands[1]) == MEM)
                    946:     return "ld %1,%0";
                    947:   else if (GET_CODE (operands[1]) == CONST_DOUBLE)
                    948:     {
                    949:       int i;
                    950:       union real_extract u;
                    951:       union float_extract { float f; int i; } v;
                    952: 
                    953:       /* Must be SFmode, otherwise this doesn't make sense.  */
                    954:       if (GET_MODE (operands[1]) != SFmode)
                    955:        abort ();
                    956: 
                    957:       bcopy (&CONST_DOUBLE_LOW (operands[1]), &u, sizeof u);
                    958:       v.f = REAL_VALUE_TRUNCATE (SFmode, u.d);
                    959:       i = v.i;
                    960: 
                    961:       operands[1] = gen_rtx (CONST_INT, VOIDmode, i);
                    962: 
                    963:       if (CONST_OK_FOR_LETTER_P (i, 'I'))
                    964:        return "mov %1,%0";
                    965:       else if ((i & 0x000003FF) != 0)
                    966:        return "sethi %%hi(%a1),%0\n\tor %0,%%lo(%a1),%0";
                    967:       else
                    968:        return "sethi %%hi(%a1),%0";
                    969:     }
                    970:   else if (GET_CODE (operands[1]) == CONST_INT
                    971:           && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
                    972:     {
                    973:       int i = INTVAL (operands[1]);
                    974: 
                    975:       /* If all low order 10 bits are clear, then we only need a single
                    976:         sethi insn to load the constant.  */
                    977:       if ((i & 0x000003FF) != 0)
                    978:        return "sethi %%hi(%a1),%0\n\tor %0,%%lo(%a1),%0";
                    979:       else
                    980:        return "sethi %%hi(%a1),%0";
                    981:     }
                    982:   /* Operand 1 must be a register, or a 'I' type CONST_INT.  */
                    983:   return "mov %1,%0";
                    984: }
                    985: 
                    986: /* Return non-zero if it is OK to assume that the given memory operand is
                    987:    aligned at least to a 8-byte boundary.  This should only be called
                    988:    for memory accesses whose size is 8 bytes or larger.  */
                    989: 
                    990: int
                    991: mem_aligned_8 (mem)
                    992:      register rtx mem;
                    993: {
                    994:   register rtx addr;
                    995:   register rtx base;
                    996:   register rtx offset;
                    997: 
                    998:   if (GET_CODE (mem) != MEM)
                    999:     return 0;  /* It's gotta be a MEM! */
                   1000: 
                   1001:   addr = XEXP (mem, 0);
                   1002: 
                   1003:   /* Now that all misaligned double parms are copied on function entry,
                   1004:      we can assume any 64-bit object is 64-bit aligned except those which
                   1005:      are at unaligned offsets from the stack or frame pointer.  If the
                   1006:      TARGET_UNALIGNED_DOUBLES switch is given, we do not make this
                   1007:      assumption.  */
                   1008: 
                   1009:   /* See what register we use in the address.  */
                   1010:   base = 0;
                   1011:   if (GET_CODE (addr) == PLUS)
                   1012:     {
                   1013:       if (GET_CODE (XEXP (addr, 0)) == REG
                   1014:          && GET_CODE (XEXP (addr, 1)) == CONST_INT)
                   1015:        {
                   1016:          base = XEXP (addr, 0);
                   1017:          offset = XEXP (addr, 1);
                   1018:        }
                   1019:     }
                   1020:   else if (GET_CODE (addr) == REG)
                   1021:     {
                   1022:       base = addr;
                   1023:       offset = const0_rtx;
                   1024:     }
                   1025: 
                   1026:   /* If it's the stack or frame pointer, check offset alignment.
                   1027:      We can have improper alignment in the function entry code.  */
                   1028:   if (base
                   1029:       && (REGNO (base) == FRAME_POINTER_REGNUM
                   1030:          || REGNO (base) == STACK_POINTER_REGNUM))
                   1031:     {
                   1032:       if ((INTVAL (offset) & 0x7) == 0)
                   1033:        return 1;
                   1034:     }
                   1035:   /* Anything else we know is properly aligned unless TARGET_UNALIGNED_DOUBLES
                   1036:      is true, in which case we can only assume that an access is aligned if
                   1037:      it is to an aggregate, it is to a constant address, or the address
                   1038:      involves a LO_SUM.  */
                   1039:   else if (! TARGET_UNALIGNED_DOUBLES || MEM_IN_STRUCT_P (mem)
                   1040:           || CONSTANT_P (addr) || GET_CODE (addr) == LO_SUM)
                   1041:     return 1;
                   1042: 
                   1043:   /* An obviously unaligned address.  */
                   1044:   return 0;
                   1045: }
                   1046: 
                   1047: enum optype { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP };
                   1048: 
                   1049: /* Output assembler code to perform a doubleword move insn
                   1050:    with operands OPERANDS.  This is very similar to the following
                   1051:    output_move_quad function.  */
                   1052: 
                   1053: char *
                   1054: output_move_double (operands)
                   1055:      rtx *operands;
                   1056: {
                   1057:   register rtx op0 = operands[0];
                   1058:   register rtx op1 = operands[1];
                   1059:   register enum optype optype0;
                   1060:   register enum optype optype1;
                   1061:   rtx latehalf[2];
                   1062:   rtx addreg0 = 0;
                   1063:   rtx addreg1 = 0;
                   1064: 
                   1065:   /* First classify both operands.  */
                   1066: 
                   1067:   if (REG_P (op0))
                   1068:     optype0 = REGOP;
                   1069:   else if (offsettable_memref_p (op0))
                   1070:     optype0 = OFFSOP;
                   1071:   else if (GET_CODE (op0) == MEM)
                   1072:     optype0 = MEMOP;
                   1073:   else
                   1074:     optype0 = RNDOP;
                   1075: 
                   1076:   if (REG_P (op1))
                   1077:     optype1 = REGOP;
                   1078:   else if (CONSTANT_P (op1))
                   1079:     optype1 = CNSTOP;
                   1080:   else if (offsettable_memref_p (op1))
                   1081:     optype1 = OFFSOP;
                   1082:   else if (GET_CODE (op1) == MEM)
                   1083:     optype1 = MEMOP;
                   1084:   else
                   1085:     optype1 = RNDOP;
                   1086: 
                   1087:   /* Check for the cases that the operand constraints are not
                   1088:      supposed to allow to happen.  Abort if we get one,
                   1089:      because generating code for these cases is painful.  */
                   1090: 
                   1091:   if (optype0 == RNDOP || optype1 == RNDOP
                   1092:       || (optype0 == MEM && optype1 == MEM))
                   1093:     abort ();
                   1094: 
                   1095:   /* If an operand is an unoffsettable memory ref, find a register
                   1096:      we can increment temporarily to make it refer to the second word.  */
                   1097: 
                   1098:   if (optype0 == MEMOP)
                   1099:     addreg0 = find_addr_reg (XEXP (op0, 0));
                   1100: 
                   1101:   if (optype1 == MEMOP)
                   1102:     addreg1 = find_addr_reg (XEXP (op1, 0));
                   1103: 
                   1104:   /* Ok, we can do one word at a time.
                   1105:      Set up in LATEHALF the operands to use for the
                   1106:      high-numbered (least significant) word and in some cases alter the
                   1107:      operands in OPERANDS to be suitable for the low-numbered word.  */
                   1108: 
                   1109:   if (optype0 == REGOP)
                   1110:     latehalf[0] = gen_rtx (REG, SImode, REGNO (op0) + 1);
                   1111:   else if (optype0 == OFFSOP)
                   1112:     latehalf[0] = adj_offsettable_operand (op0, 4);
                   1113:   else
                   1114:     latehalf[0] = op0;
                   1115: 
                   1116:   if (optype1 == REGOP)
                   1117:     latehalf[1] = gen_rtx (REG, SImode, REGNO (op1) + 1);
                   1118:   else if (optype1 == OFFSOP)
                   1119:     latehalf[1] = adj_offsettable_operand (op1, 4);
                   1120:   else if (optype1 == CNSTOP)
                   1121:     split_double (op1, &operands[1], &latehalf[1]);
                   1122:   else
                   1123:     latehalf[1] = op1;
                   1124: 
                   1125:   /* Easy case: try moving both words at once.  Check for moving between
                   1126:      an even/odd register pair and a memory location.  */
                   1127:   if ((optype0 == REGOP && optype1 != REGOP && optype1 != CNSTOP
                   1128:        && (REGNO (op0) & 1) == 0)
                   1129:       || (optype0 != REGOP && optype0 != CNSTOP && optype1 == REGOP
                   1130:          && (REGNO (op1) & 1) == 0))
                   1131:     {
                   1132:       register rtx mem;
                   1133: 
                   1134:       if (optype0 == REGOP)
                   1135:        mem = op1;
                   1136:       else
                   1137:        mem = op0;
                   1138: 
                   1139:       if (mem_aligned_8 (mem))
                   1140:        return (mem == op1 ? "ldd %1,%0" : "std %1,%0");
                   1141:     }
                   1142: 
                   1143:   /* If the first move would clobber the source of the second one,
                   1144:      do them in the other order.  */
                   1145: 
                   1146:   /* Overlapping registers.  */
                   1147:   if (optype0 == REGOP && optype1 == REGOP
                   1148:       && REGNO (op0) == REGNO (latehalf[1]))
                   1149:     {
                   1150:       /* Do that word.  */
                   1151:       output_asm_insn (singlemove_string (latehalf), latehalf);
                   1152:       /* Do low-numbered word.  */
                   1153:       return singlemove_string (operands);
                   1154:     }
                   1155:   /* Loading into a register which overlaps a register used in the address.  */
                   1156:   else if (optype0 == REGOP && optype1 != REGOP
                   1157:           && reg_overlap_mentioned_p (op0, op1))
                   1158:     {
                   1159:       /* ??? This fails if the address is a double register address, each
                   1160:         of which is clobbered by operand 0.  */
                   1161:       /* Do the late half first.  */
                   1162:       output_asm_insn (singlemove_string (latehalf), latehalf);
                   1163:       /* Then clobber.  */
                   1164:       return singlemove_string (operands);
                   1165:     }
                   1166: 
                   1167:   /* Normal case: do the two words, low-numbered first.  */
                   1168: 
                   1169:   output_asm_insn (singlemove_string (operands), operands);
                   1170: 
                   1171:   /* Make any unoffsettable addresses point at high-numbered word.  */
                   1172:   if (addreg0)
                   1173:     output_asm_insn ("add %0,0x4,%0", &addreg0);
                   1174:   if (addreg1)
                   1175:     output_asm_insn ("add %0,0x4,%0", &addreg1);
                   1176: 
                   1177:   /* Do that word.  */
                   1178:   output_asm_insn (singlemove_string (latehalf), latehalf);
                   1179: 
                   1180:   /* Undo the adds we just did.  */
                   1181:   if (addreg0)
                   1182:     output_asm_insn ("add %0,-0x4,%0", &addreg0);
                   1183:   if (addreg1)
                   1184:     output_asm_insn ("add %0,-0x4,%0", &addreg1);
                   1185: 
                   1186:   return "";
                   1187: }
                   1188: 
                   1189: /* Output assembler code to perform a quadword move insn
                   1190:    with operands OPERANDS.  This is very similar to the preceding
                   1191:    output_move_double function.  */
                   1192: 
                   1193: char *
                   1194: output_move_quad (operands)
                   1195:      rtx *operands;
                   1196: {
                   1197:   register rtx op0 = operands[0];
                   1198:   register rtx op1 = operands[1];
                   1199:   register enum optype optype0;
                   1200:   register enum optype optype1;
                   1201:   rtx wordpart[4][2];
                   1202:   rtx addreg0 = 0;
                   1203:   rtx addreg1 = 0;
                   1204: 
                   1205:   /* First classify both operands.  */
                   1206: 
                   1207:   if (REG_P (op0))
                   1208:     optype0 = REGOP;
                   1209:   else if (offsettable_memref_p (op0))
                   1210:     optype0 = OFFSOP;
                   1211:   else if (GET_CODE (op0) == MEM)
                   1212:     optype0 = MEMOP;
                   1213:   else
                   1214:     optype0 = RNDOP;
                   1215: 
                   1216:   if (REG_P (op1))
                   1217:     optype1 = REGOP;
                   1218:   else if (CONSTANT_P (op1))
                   1219:     optype1 = CNSTOP;
                   1220:   else if (offsettable_memref_p (op1))
                   1221:     optype1 = OFFSOP;
                   1222:   else if (GET_CODE (op1) == MEM)
                   1223:     optype1 = MEMOP;
                   1224:   else
                   1225:     optype1 = RNDOP;
                   1226: 
                   1227:   /* Check for the cases that the operand constraints are not
                   1228:      supposed to allow to happen.  Abort if we get one,
                   1229:      because generating code for these cases is painful.  */
                   1230: 
                   1231:   if (optype0 == RNDOP || optype1 == RNDOP
                   1232:       || (optype0 == MEM && optype1 == MEM))
                   1233:     abort ();
                   1234: 
                   1235:   /* If an operand is an unoffsettable memory ref, find a register
                   1236:      we can increment temporarily to make it refer to the later words.  */
                   1237: 
                   1238:   if (optype0 == MEMOP)
                   1239:     addreg0 = find_addr_reg (XEXP (op0, 0));
                   1240: 
                   1241:   if (optype1 == MEMOP)
                   1242:     addreg1 = find_addr_reg (XEXP (op1, 0));
                   1243: 
                   1244:   /* Ok, we can do one word at a time.
                   1245:      Set up in wordpart the operands to use for each word of the arguments.  */
                   1246: 
                   1247:   if (optype0 == REGOP)
                   1248:     {
                   1249:       wordpart[0][0] = gen_rtx (REG, SImode, REGNO (op0) + 0);
                   1250:       wordpart[1][0] = gen_rtx (REG, SImode, REGNO (op0) + 1);
                   1251:       wordpart[2][0] = gen_rtx (REG, SImode, REGNO (op0) + 2);
                   1252:       wordpart[3][0] = gen_rtx (REG, SImode, REGNO (op0) + 3);
                   1253:     }
                   1254:   else if (optype0 == OFFSOP)
                   1255:     {
                   1256:       wordpart[0][0] = adj_offsettable_operand (op0, 0);
                   1257:       wordpart[1][0] = adj_offsettable_operand (op0, 4);
                   1258:       wordpart[2][0] = adj_offsettable_operand (op0, 8);
                   1259:       wordpart[3][0] = adj_offsettable_operand (op0, 12);
                   1260:     }
                   1261:   else
                   1262:     {
                   1263:       wordpart[0][0] = op0;
                   1264:       wordpart[1][0] = op0;
                   1265:       wordpart[2][0] = op0;
                   1266:       wordpart[3][0] = op0;
                   1267:     }
                   1268: 
                   1269:   if (optype1 == REGOP)
                   1270:     {
                   1271:       wordpart[0][1] = gen_rtx (REG, SImode, REGNO (op1) + 0);
                   1272:       wordpart[1][1] = gen_rtx (REG, SImode, REGNO (op1) + 1);
                   1273:       wordpart[2][1] = gen_rtx (REG, SImode, REGNO (op1) + 2);
                   1274:       wordpart[3][1] = gen_rtx (REG, SImode, REGNO (op1) + 3);
                   1275:     }
                   1276:   else if (optype1 == OFFSOP)
                   1277:     {
                   1278:       wordpart[0][1] = adj_offsettable_operand (op1, 0);
                   1279:       wordpart[1][1] = adj_offsettable_operand (op1, 4);
                   1280:       wordpart[2][1] = adj_offsettable_operand (op1, 8);
                   1281:       wordpart[3][1] = adj_offsettable_operand (op1, 12);
                   1282:     }
                   1283:   else if (optype1 == CNSTOP)
                   1284:     {
                   1285:       /* This case isn't implemented yet, because there is no internal
                   1286:         representation for quad-word constants, and there is no split_quad
                   1287:         function.  */
                   1288: #if 0
                   1289:       split_quad (op1, &wordpart[0][1], &wordpart[1][1],
                   1290:                  &wordpart[2][1], &wordpart[3][1]);
                   1291: #else
                   1292:       abort ();
                   1293: #endif
                   1294:     }
                   1295:   else
                   1296:     {
                   1297:       wordpart[0][1] = op1;
                   1298:       wordpart[1][1] = op1;
                   1299:       wordpart[2][1] = op1;
                   1300:       wordpart[3][1] = op1;
                   1301:     }
                   1302: 
                   1303:   /* Easy case: try moving the quad as two pairs.  Check for moving between
                   1304:      an even/odd register pair and a memory location.  */
                   1305:   /* ??? Should also handle the case of non-offsettable addresses here.
                   1306:      We can at least do the first pair as a ldd/std, and then do the third
                   1307:      and fourth words individually.  */
                   1308:   if ((optype0 == REGOP && optype1 == OFFSOP && (REGNO (op0) & 1) == 0)
                   1309:       || (optype0 == OFFSOP && optype1 == REGOP && (REGNO (op1) & 1) == 0))
                   1310:     {
                   1311:       rtx mem;
                   1312: 
                   1313:       if (optype0 == REGOP)
                   1314:        mem = op1;
                   1315:       else
                   1316:        mem = op0;
                   1317: 
                   1318:       if (mem_aligned_8 (mem))
                   1319:        {
                   1320:          operands[2] = adj_offsettable_operand (mem, 8);
                   1321:          if (mem == op1)
                   1322:            return "ldd %1,%0;ldd %2,%S0";
                   1323:          else
                   1324:            return "std %1,%0;std %S1,%2";
                   1325:        }
                   1326:     }
                   1327: 
                   1328:   /* If the first move would clobber the source of the second one,
                   1329:      do them in the other order.  */
                   1330: 
                   1331:   /* Overlapping registers.  */
                   1332:   if (optype0 == REGOP && optype1 == REGOP
                   1333:       && (REGNO (op0) == REGNO (wordpart[1][3])
                   1334:          || REGNO (op0) == REGNO (wordpart[1][2])
                   1335:          || REGNO (op0) == REGNO (wordpart[1][1])))
                   1336:     {
                   1337:       /* Do fourth word.  */
                   1338:       output_asm_insn (singlemove_string (wordpart[3]), wordpart[3]);
                   1339:       /* Do the third word.  */
                   1340:       output_asm_insn (singlemove_string (wordpart[2]), wordpart[2]);
                   1341:       /* Do the second word.  */
                   1342:       output_asm_insn (singlemove_string (wordpart[1]), wordpart[1]);
                   1343:       /* Do lowest-numbered word.  */
                   1344:       return singlemove_string (wordpart[0]);
                   1345:     }
                   1346:   /* Loading into a register which overlaps a register used in the address.  */
                   1347:   if (optype0 == REGOP && optype1 != REGOP
                   1348:       && reg_overlap_mentioned_p (op0, op1))
                   1349:     {
                   1350:       /* ??? Not implemented yet.  This is a bit complicated, because we
                   1351:         must load which ever part overlaps the address last.  If the address
                   1352:         is a double-reg address, then there are two parts which need to
                   1353:         be done last, which is impossible.  We would need a scratch register
                   1354:         in that case.  */
                   1355:       abort ();
                   1356:     }
                   1357: 
                   1358:   /* Normal case: move the four words in lowest to higest address order.  */
                   1359: 
                   1360:   output_asm_insn (singlemove_string (wordpart[0]), wordpart[0]);
                   1361: 
                   1362:   /* Make any unoffsettable addresses point at the second word.  */
                   1363:   if (addreg0)
                   1364:     output_asm_insn ("add %0,0x4,%0", &addreg0);
                   1365:   if (addreg1)
                   1366:     output_asm_insn ("add %0,0x4,%0", &addreg1);
                   1367: 
                   1368:   /* Do the second word.  */
                   1369:   output_asm_insn (singlemove_string (wordpart[1]), wordpart[1]);
                   1370: 
                   1371:   /* Make any unoffsettable addresses point at the third word.  */
                   1372:   if (addreg0)
                   1373:     output_asm_insn ("add %0,0x4,%0", &addreg0);
                   1374:   if (addreg1)
                   1375:     output_asm_insn ("add %0,0x4,%0", &addreg1);
                   1376: 
                   1377:   /* Do the third word.  */
                   1378:   output_asm_insn (singlemove_string (wordpart[2]), wordpart[2]);
                   1379: 
                   1380:   /* Make any unoffsettable addresses point at the fourth word.  */
                   1381:   if (addreg0)
                   1382:     output_asm_insn ("add %0,0x4,%0", &addreg0);
                   1383:   if (addreg1)
                   1384:     output_asm_insn ("add %0,0x4,%0", &addreg1);
                   1385: 
                   1386:   /* Do the fourth word.  */
                   1387:   output_asm_insn (singlemove_string (wordpart[3]), wordpart[3]);
                   1388: 
                   1389:   /* Undo the adds we just did.  */
                   1390:   if (addreg0)
                   1391:     output_asm_insn ("add %0,-0xc,%0", &addreg0);
                   1392:   if (addreg1)
                   1393:     output_asm_insn ("add %0,-0xc,%0", &addreg1);
                   1394: 
                   1395:   return "";
                   1396: }
                   1397: 
                   1398: /* Output assembler code to perform a doubleword move insn with operands
                   1399:    OPERANDS, one of which must be a floating point register.  */
                   1400: 
                   1401: char *
                   1402: output_fp_move_double (operands)
                   1403:      rtx *operands;
                   1404: {
                   1405:   if (FP_REG_P (operands[0]))
                   1406:     {
                   1407:       if (FP_REG_P (operands[1]))
                   1408:        return "fmovs %1,%0\n\tfmovs %R1,%R0";
                   1409:       else if (GET_CODE (operands[1]) == REG)
                   1410:        abort ();
                   1411:       else
                   1412:        return output_move_double (operands);
                   1413:     }
                   1414:   else if (FP_REG_P (operands[1]))
                   1415:     {
                   1416:       if (GET_CODE (operands[0]) == REG)
                   1417:        abort ();
                   1418:       else
                   1419:        return output_move_double (operands);
                   1420:     }
                   1421:   else abort ();
                   1422: }
                   1423: 
                   1424: /* Output assembler code to perform a quadword move insn with operands
                   1425:    OPERANDS, one of which must be a floating point register.  */
                   1426: 
                   1427: char *
                   1428: output_fp_move_quad (operands)
                   1429:      rtx *operands;
                   1430: {
                   1431:   register rtx op0 = operands[0];
                   1432:   register rtx op1 = operands[1];
                   1433: 
                   1434:   if (FP_REG_P (op0))
                   1435:     {
                   1436:       if (FP_REG_P (op1))
                   1437:        return "fmovs %1,%0\n\tfmovs %R1,%R0\n\tfmovs %S1,%S0\n\tfmovs %T1,%T0";
                   1438:       else if (GET_CODE (op1) == REG)
                   1439:        abort ();
                   1440:       else
                   1441:        return output_move_quad (operands);
                   1442:     }
                   1443:   else if (FP_REG_P (op1))
                   1444:     {
                   1445:       if (GET_CODE (op0) == REG)
                   1446:        abort ();
                   1447:       else
                   1448:        return output_move_quad (operands);
                   1449:     }
                   1450:   else
                   1451:     abort ();
                   1452: }
                   1453: 
                   1454: /* Return a REG that occurs in ADDR with coefficient 1.
                   1455:    ADDR can be effectively incremented by incrementing REG.  */
                   1456: 
                   1457: static rtx
                   1458: find_addr_reg (addr)
                   1459:      rtx addr;
                   1460: {
                   1461:   while (GET_CODE (addr) == PLUS)
                   1462:     {
                   1463:       /* We absolutely can not fudge the frame pointer here, because the
                   1464:         frame pointer must always be 8 byte aligned.  It also confuses
                   1465:         debuggers.  */
                   1466:       if (GET_CODE (XEXP (addr, 0)) == REG
                   1467:          && REGNO (XEXP (addr, 0)) != FRAME_POINTER_REGNUM)
                   1468:        addr = XEXP (addr, 0);
                   1469:       else if (GET_CODE (XEXP (addr, 1)) == REG
                   1470:               && REGNO (XEXP (addr, 1)) != FRAME_POINTER_REGNUM)
                   1471:        addr = XEXP (addr, 1);
                   1472:       else if (CONSTANT_P (XEXP (addr, 0)))
                   1473:        addr = XEXP (addr, 1);
                   1474:       else if (CONSTANT_P (XEXP (addr, 1)))
                   1475:        addr = XEXP (addr, 0);
                   1476:       else
                   1477:        abort ();
                   1478:     }
                   1479:   if (GET_CODE (addr) == REG)
                   1480:     return addr;
                   1481:   abort ();
                   1482: }
                   1483: 
                   1484: void
                   1485: output_sized_memop (opname, mode, signedp)
                   1486:      char *opname;
                   1487:      enum machine_mode mode;
                   1488:      int signedp;
                   1489: {
                   1490:   static char *ld_size_suffix_u[] = { "ub", "uh", "", "?", "d" };
                   1491:   static char *ld_size_suffix_s[] = { "sb", "sh", "", "?", "d" };
                   1492:   static char *st_size_suffix[] = { "b", "h", "", "?", "d" };
                   1493:   char **opnametab, *modename;
                   1494: 
                   1495:   if (opname[0] == 'l')
                   1496:     if (signedp)
                   1497:       opnametab = ld_size_suffix_s;
                   1498:     else
                   1499:       opnametab = ld_size_suffix_u;
                   1500:   else
                   1501:     opnametab = st_size_suffix;
                   1502:   modename = opnametab[GET_MODE_SIZE (mode) >> 1];
                   1503: 
                   1504:   fprintf (asm_out_file, "\t%s%s", opname, modename);
                   1505: }
                   1506: 
                   1507: void
                   1508: output_move_with_extension (operands)
                   1509:      rtx *operands;
                   1510: {
                   1511:   if (GET_MODE (operands[2]) == HImode)
                   1512:     output_asm_insn ("sll %2,0x10,%0", operands);
                   1513:   else if (GET_MODE (operands[2]) == QImode)
                   1514:     output_asm_insn ("sll %2,0x18,%0", operands);
                   1515:   else
                   1516:     abort ();
                   1517: }
                   1518: 
                   1519: #if 0
                   1520: /* ??? These are only used by the movstrsi pattern, but we get better code
                   1521:    in general without that, because emit_block_move can do just as good a
                   1522:    job as this function does when alignment and size are known.  When they
                   1523:    aren't known, a call to strcpy may be faster anyways, because it is
                   1524:    likely to be carefully crafted assembly language code, and below we just
                   1525:    do a byte-wise copy.
                   1526: 
                   1527:    Also, emit_block_move expands into multiple read/write RTL insns, which
                   1528:    can then be optimized, whereas our movstrsi pattern can not be optimized
                   1529:    at all.  */
                   1530: 
                   1531: /* Load the address specified by OPERANDS[3] into the register
                   1532:    specified by OPERANDS[0].
                   1533: 
                   1534:    OPERANDS[3] may be the result of a sum, hence it could either be:
                   1535: 
                   1536:    (1) CONST
                   1537:    (2) REG
                   1538:    (2) REG + CONST_INT
                   1539:    (3) REG + REG + CONST_INT
                   1540:    (4) REG + REG  (special case of 3).
                   1541: 
                   1542:    Note that (3) is not a legitimate address.
                   1543:    All cases are handled here.  */
                   1544: 
                   1545: void
                   1546: output_load_address (operands)
                   1547:      rtx *operands;
                   1548: {
                   1549:   rtx base, offset;
                   1550: 
                   1551:   if (CONSTANT_P (operands[3]))
                   1552:     {
                   1553:       output_asm_insn ("set %3,%0", operands);
                   1554:       return;
                   1555:     }
                   1556: 
                   1557:   if (REG_P (operands[3]))
                   1558:     {
                   1559:       if (REGNO (operands[0]) != REGNO (operands[3]))
                   1560:        output_asm_insn ("mov %3,%0", operands);
                   1561:       return;
                   1562:     }
                   1563: 
                   1564:   if (GET_CODE (operands[3]) != PLUS)
                   1565:     abort ();
                   1566: 
                   1567:   base = XEXP (operands[3], 0);
                   1568:   offset = XEXP (operands[3], 1);
                   1569: 
                   1570:   if (GET_CODE (base) == CONST_INT)
                   1571:     {
                   1572:       rtx tmp = base;
                   1573:       base = offset;
                   1574:       offset = tmp;
                   1575:     }
                   1576: 
                   1577:   if (GET_CODE (offset) != CONST_INT)
                   1578:     {
                   1579:       /* Operand is (PLUS (REG) (REG)).  */
                   1580:       base = operands[3];
                   1581:       offset = const0_rtx;
                   1582:     }
                   1583: 
                   1584:   if (REG_P (base))
                   1585:     {
                   1586:       operands[6] = base;
                   1587:       operands[7] = offset;
                   1588:       if (SMALL_INT (offset))
                   1589:        output_asm_insn ("add %6,%7,%0", operands);
                   1590:       else
                   1591:        output_asm_insn ("set %7,%0\n\tadd %0,%6,%0", operands);
                   1592:     }
                   1593:   else if (GET_CODE (base) == PLUS)
                   1594:     {
                   1595:       operands[6] = XEXP (base, 0);
                   1596:       operands[7] = XEXP (base, 1);
                   1597:       operands[8] = offset;
                   1598: 
                   1599:       if (SMALL_INT (offset))
                   1600:        output_asm_insn ("add %6,%7,%0\n\tadd %0,%8,%0", operands);
                   1601:       else
                   1602:        output_asm_insn ("set %8,%0\n\tadd %0,%6,%0\n\tadd %0,%7,%0", operands);
                   1603:     }
                   1604:   else
                   1605:     abort ();
                   1606: }
                   1607: 
                   1608: /* Output code to place a size count SIZE in register REG.
                   1609:    ALIGN is the size of the unit of transfer.
                   1610: 
                   1611:    Because block moves are pipelined, we don't include the
                   1612:    first element in the transfer of SIZE to REG.  */
                   1613: 
                   1614: static void
                   1615: output_size_for_block_move (size, reg, align)
                   1616:      rtx size, reg;
                   1617:      rtx align;
                   1618: {
                   1619:   rtx xoperands[3];
                   1620: 
                   1621:   xoperands[0] = reg;
                   1622:   xoperands[1] = size;
                   1623:   xoperands[2] = align;
                   1624:   if (GET_CODE (size) == REG)
                   1625:     output_asm_insn ("sub %1,%2,%0", xoperands);
                   1626:   else
                   1627:     {
                   1628:       xoperands[1]
                   1629:        = gen_rtx (CONST_INT, VOIDmode, INTVAL (size) - INTVAL (align));
                   1630:       output_asm_insn ("set %1,%0", xoperands);
                   1631:     }
                   1632: }
                   1633: 
                   1634: /* Emit code to perform a block move.
                   1635: 
                   1636:    OPERANDS[0] is the destination.
                   1637:    OPERANDS[1] is the source.
                   1638:    OPERANDS[2] is the size.
                   1639:    OPERANDS[3] is the alignment safe to use.
                   1640:    OPERANDS[4] is a register we can safely clobber as a temp.  */
                   1641: 
                   1642: char *
                   1643: output_block_move (operands)
                   1644:      rtx *operands;
                   1645: {
                   1646:   /* A vector for our computed operands.  Note that load_output_address
                   1647:      makes use of (and can clobber) up to the 8th element of this vector.  */
                   1648:   rtx xoperands[10];
                   1649:   rtx zoperands[10];
                   1650:   static int movstrsi_label = 0;
                   1651:   int i;
                   1652:   rtx temp1 = operands[4];
                   1653:   rtx sizertx = operands[2];
                   1654:   rtx alignrtx = operands[3];
                   1655:   int align = INTVAL (alignrtx);
                   1656:   char label3[30], label5[30];
                   1657: 
                   1658:   xoperands[0] = operands[0];
                   1659:   xoperands[1] = operands[1];
                   1660:   xoperands[2] = temp1;
                   1661: 
                   1662:   /* We can't move more than this many bytes at a time because we have only
                   1663:      one register, %g1, to move them through.  */
                   1664:   if (align > UNITS_PER_WORD)
                   1665:     {
                   1666:       align = UNITS_PER_WORD;
                   1667:       alignrtx = gen_rtx (CONST_INT, VOIDmode, UNITS_PER_WORD);
                   1668:     }
                   1669: 
                   1670:   /* We consider 8 ld/st pairs, for a total of 16 inline insns to be
                   1671:      reasonable here.  (Actually will emit a maximum of 18 inline insns for
                   1672:      the case of size == 31 and align == 4).  */
                   1673: 
                   1674:   if (GET_CODE (sizertx) == CONST_INT && (INTVAL (sizertx) / align) <= 8
                   1675:       && memory_address_p (QImode, plus_constant_for_output (xoperands[0],
                   1676:                                                             INTVAL (sizertx)))
                   1677:       && memory_address_p (QImode, plus_constant_for_output (xoperands[1],
                   1678:                                                             INTVAL (sizertx))))
                   1679:     {
                   1680:       int size = INTVAL (sizertx);
                   1681:       int offset = 0;
                   1682: 
                   1683:       /* We will store different integers into this particular RTX.  */
                   1684:       xoperands[2] = rtx_alloc (CONST_INT);
                   1685:       PUT_MODE (xoperands[2], VOIDmode);
                   1686: 
                   1687:       /* This case is currently not handled.  Abort instead of generating
                   1688:         bad code.  */
                   1689:       if (align > 4)
                   1690:        abort ();
                   1691: 
                   1692:       if (align >= 4)
                   1693:        {
                   1694:          for (i = (size >> 2) - 1; i >= 0; i--)
                   1695:            {
                   1696:              INTVAL (xoperands[2]) = (i << 2) + offset;
                   1697:              output_asm_insn ("ld [%a1+%2],%%g1\n\tst %%g1,[%a0+%2]",
                   1698:                               xoperands);
                   1699:            }
                   1700:          offset += (size & ~0x3);
                   1701:          size = size & 0x3;
                   1702:          if (size == 0)
                   1703:            return "";
                   1704:        }
                   1705: 
                   1706:       if (align >= 2)
                   1707:        {
                   1708:          for (i = (size >> 1) - 1; i >= 0; i--)
                   1709:            {
                   1710:              INTVAL (xoperands[2]) = (i << 1) + offset;
                   1711:              output_asm_insn ("lduh [%a1+%2],%%g1\n\tsth %%g1,[%a0+%2]",
                   1712:                               xoperands);
                   1713:            }
                   1714:          offset += (size & ~0x1);
                   1715:          size = size & 0x1;
                   1716:          if (size == 0)
                   1717:            return "";
                   1718:        }
                   1719: 
                   1720:       if (align >= 1)
                   1721:        {
                   1722:          for (i = size - 1; i >= 0; i--)
                   1723:            {
                   1724:              INTVAL (xoperands[2]) = i + offset;
                   1725:              output_asm_insn ("ldub [%a1+%2],%%g1\n\tstb %%g1,[%a0+%2]",
                   1726:                               xoperands);
                   1727:            }
                   1728:          return "";
                   1729:        }
                   1730: 
                   1731:       /* We should never reach here.  */
                   1732:       abort ();
                   1733:     }
                   1734: 
                   1735:   /* If the size isn't known to be a multiple of the alignment,
                   1736:      we have to do it in smaller pieces.  If we could determine that
                   1737:      the size was a multiple of 2 (or whatever), we could be smarter
                   1738:      about this.  */
                   1739:   if (GET_CODE (sizertx) != CONST_INT)
                   1740:     align = 1;
                   1741:   else
                   1742:     {
                   1743:       int size = INTVAL (sizertx);
                   1744:       while (size % align)
                   1745:        align >>= 1;
                   1746:     }
                   1747: 
                   1748:   if (align != INTVAL (alignrtx))
                   1749:     alignrtx = gen_rtx (CONST_INT, VOIDmode, align);
                   1750: 
                   1751:   xoperands[3] = gen_rtx (CONST_INT, VOIDmode, movstrsi_label++);
                   1752:   xoperands[4] = gen_rtx (CONST_INT, VOIDmode, align);
                   1753:   xoperands[5] = gen_rtx (CONST_INT, VOIDmode, movstrsi_label++);
                   1754: 
                   1755:   ASM_GENERATE_INTERNAL_LABEL (label3, "Lm", INTVAL (xoperands[3]));
                   1756:   ASM_GENERATE_INTERNAL_LABEL (label5, "Lm", INTVAL (xoperands[5]));
                   1757: 
                   1758:   /* This is the size of the transfer.  Emit code to decrement the size
                   1759:      value by ALIGN, and store the result in the temp1 register.  */
                   1760:   output_size_for_block_move (sizertx, temp1, alignrtx);
                   1761: 
                   1762:   /* Must handle the case when the size is zero or negative, so the first thing
                   1763:      we do is compare the size against zero, and only copy bytes if it is
                   1764:      zero or greater.  Note that we have already subtracted off the alignment
                   1765:      once, so we must copy 1 alignment worth of bytes if the size is zero
                   1766:      here.
                   1767: 
                   1768:      The SUN assembler complains about labels in branch delay slots, so we
                   1769:      do this before outputting the load address, so that there will always
                   1770:      be a harmless insn between the branch here and the next label emitted
                   1771:      below.  */
                   1772: 
                   1773:   {
                   1774:     char pattern[100];
                   1775: 
                   1776:     sprintf (pattern, "cmp %%2,0\n\tbl %s", &label5[1]);
                   1777:     output_asm_insn (pattern, xoperands);
                   1778:   }
                   1779: 
                   1780:   zoperands[0] = operands[0];
                   1781:   zoperands[3] = plus_constant_for_output (operands[0], align);
                   1782:   output_load_address (zoperands);
                   1783: 
                   1784:   /* ??? This might be much faster if the loops below were preconditioned
                   1785:      and unrolled.
                   1786: 
                   1787:      That is, at run time, copy enough bytes one at a time to ensure that the
                   1788:      target and source addresses are aligned to the the largest possible
                   1789:      alignment.  Then use a preconditioned unrolled loop to copy say 16
                   1790:      bytes at a time.  Then copy bytes one at a time until finish the rest.  */
                   1791: 
                   1792:   /* Output the first label separately, so that it is spaced properly.  */
                   1793: 
                   1794:   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "Lm", INTVAL (xoperands[3]));
                   1795: 
                   1796:   {
                   1797:     char pattern[200];
                   1798:     register char *ld_suffix = (align == 1) ? "ub" : (align == 2) ? "uh" : "";
                   1799:     register char *st_suffix = (align == 1) ? "b" : (align == 2) ? "h" : "";
                   1800: 
                   1801:     sprintf (pattern, "ld%s [%%1+%%2],%%%%g1\n\tsubcc %%2,%%4,%%2\n\tbge %s\n\tst%s %%%%g1,[%%0+%%2]\n%s:", ld_suffix, &label3[1], st_suffix, &label5[1]);
                   1802:     output_asm_insn (pattern, xoperands);
                   1803:   }
                   1804: 
                   1805:   return "";
                   1806: }
                   1807: #endif
                   1808: 
                   1809: /* Output reasonable peephole for set-on-condition-code insns.
                   1810:    Note that these insns assume a particular way of defining
                   1811:    labels.  Therefore, *both* sparc.h and this function must
                   1812:    be changed if a new syntax is needed.    */
                   1813: 
                   1814: char *
                   1815: output_scc_insn (operands, insn)
                   1816:      rtx operands[];
                   1817:      rtx insn;
                   1818: {
                   1819:   static char string[100];
                   1820:   rtx label = 0, next = insn;
                   1821:   int need_label = 0;
                   1822: 
                   1823:   /* Try doing a jump optimization which jump.c can't do for us
                   1824:      because we did not expose that setcc works by using branches.
                   1825: 
                   1826:      If this scc insn is followed by an unconditional branch, then have
                   1827:      the jump insn emitted here jump to that location, instead of to
                   1828:      the end of the scc sequence as usual.  */
                   1829: 
                   1830:   do
                   1831:     {
                   1832:       if (GET_CODE (next) == CODE_LABEL)
                   1833:        label = next;
                   1834:       next = NEXT_INSN (next);
                   1835:       if (next == 0)
                   1836:        break;
                   1837:     }
                   1838:   while (GET_CODE (next) == NOTE || GET_CODE (next) == CODE_LABEL);
                   1839: 
                   1840:   /* If we are in a sequence, and the following insn is a sequence also,
                   1841:      then just following the current insn's next field will take us to the
                   1842:      first insn of the next sequence, which is the wrong place.  We don't
                   1843:      want to optimize with a branch that has had its delay slot filled.
                   1844:      Avoid this by verifying that NEXT_INSN (PREV_INSN (next)) == next
                   1845:      which fails only if NEXT is such a branch.  */
                   1846: 
                   1847:   if (next && GET_CODE (next) == JUMP_INSN && simplejump_p (next)
                   1848:       && (! final_sequence || NEXT_INSN (PREV_INSN (next)) == next))
                   1849:     label = JUMP_LABEL (next);
                   1850:   /* If not optimizing, jump label fields are not set.  To be safe, always
                   1851:      check here to whether label is still zero.  */
                   1852:   if (label == 0)
                   1853:     {
                   1854:       label = gen_label_rtx ();
                   1855:       need_label = 1;
                   1856:     }
                   1857: 
                   1858:   LABEL_NUSES (label) += 1;
                   1859: 
                   1860:   operands[2] = label;
                   1861: 
                   1862:   /* If we are in a delay slot, assume it is the delay slot of an fpcc
                   1863:      insn since our type isn't allowed anywhere else.  */
                   1864: 
                   1865:   /* ??? Fpcc instructions no longer have delay slots, so this code is
                   1866:      probably obsolete.  */
                   1867: 
                   1868:   /* The fastest way to emit code for this is an annulled branch followed
                   1869:      by two move insns.  This will take two cycles if the branch is taken,
                   1870:      and three cycles if the branch is not taken.
                   1871: 
                   1872:      However, if we are in the delay slot of another branch, this won't work,
                   1873:      because we can't put a branch in the delay slot of another branch.
                   1874:      The above sequence would effectively take 3 or 4 cycles respectively
                   1875:      since a no op would have be inserted between the two branches.
                   1876:      In this case, we want to emit a move, annulled branch, and then the
                   1877:      second move.  This sequence always takes 3 cycles, and hence is faster
                   1878:      when we are in a branch delay slot.  */
                   1879: 
                   1880:   if (final_sequence)
                   1881:     {
                   1882:       strcpy (string, "mov 0,%0\n\t");
                   1883:       strcat (string, output_cbranch (operands[1], 2, 0, 1, 0));
                   1884:       strcat (string, "\n\tmov 1,%0");
                   1885:     }
                   1886:   else
                   1887:     {
                   1888:       strcpy (string, output_cbranch (operands[1], 2, 0, 1, 0));
                   1889:       strcat (string, "\n\tmov 1,%0\n\tmov 0,%0");
                   1890:     }
                   1891: 
                   1892:   if (need_label)
                   1893:     strcat (string, "\n%l2:");
                   1894: 
                   1895:   return string;
                   1896: }
                   1897: 
                   1898: /* Vectors to keep interesting information about registers where
                   1899:    it can easily be got.  */
                   1900: 
                   1901: /* Modes for condition codes.  */
                   1902: #define C_MODES                                                \
                   1903:   ((1 << (int) CCmode) | (1 << (int) CC_NOOVmode)      \
                   1904:    | (1 << (int) CCFPmode) | (1 << (int) CCFPEmode))
                   1905: 
                   1906: /* Modes for single-word (and smaller) quantities.  */
                   1907: #define S_MODES                                                                \
                   1908:  ((1 << (int) QImode) | (1 << (int) HImode) | (1 << (int) SImode)      \
                   1909:   | (1 << (int) QFmode) | (1 << (int) HFmode) | (1 << (int) SFmode)    \
                   1910:   | (1 << (int) CQImode) | (1 << (int) CHImode))
                   1911: 
                   1912: /* Modes for double-word (and smaller) quantities.  */
                   1913: #define D_MODES                                                \
                   1914:  (S_MODES | (1 << (int) DImode) | (1 << (int) DFmode)  \
                   1915:   | (1 << (int) CSImode) | (1 << (int) SCmode))
                   1916: 
                   1917: /* Modes for quad-word quantities.  */
                   1918: #define T_MODES                                                \
                   1919:  (D_MODES | (1 << (int) TImode) | (1 << (int) TFmode)  \
                   1920:   | (1 << (int) DCmode) | (1 << (int) CDImode))
                   1921: 
                   1922: /* Modes for single-float quantities.  We must allow any single word or
                   1923:    smaller quantity.  This is because the fix/float conversion instructions
                   1924:    take integer inputs/outputs from the float registers.  */
                   1925: #define SF_MODES (S_MODES)
                   1926: 
                   1927: /* Modes for double-float quantities.  */
                   1928: #define DF_MODES (SF_MODES | (1 << (int) DFmode) | (1 << (int) SCmode))
                   1929: 
                   1930: /* Modes for quad-float quantities.  */
                   1931: #define TF_MODES (DF_MODES | (1 << (int) TFmode) | (1 << (int) DCmode))
                   1932: 
                   1933: /* Value is 1 if register/mode pair is acceptable on sparc.
                   1934:    The funny mixture of D and T modes is because integer operations
                   1935:    do not specially operate on tetra quantities, so non-quad-aligned
                   1936:    registers can hold quadword quantities (except %o4 and %i4 because
                   1937:    they cross fixed registers.  */
                   1938: 
                   1939: int hard_regno_mode_ok[] = {
                   1940:   C_MODES, S_MODES, T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES,
                   1941:   T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, D_MODES, S_MODES,
                   1942:   T_MODES, S_MODES, T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES,
                   1943:   T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, D_MODES, S_MODES,
                   1944: 
                   1945:   TF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES,
                   1946:   TF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES,
                   1947:   TF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES,
                   1948:   TF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES};
                   1949: 
                   1950: #ifdef __GNUC__
                   1951: inline
                   1952: #endif
                   1953: static int
                   1954: save_regs (file, low, high, base, offset, n_fregs)
                   1955:      FILE *file;
                   1956:      int low, high;
                   1957:      char *base;
                   1958:      int offset;
                   1959:      int n_fregs;
                   1960: {
                   1961:   int i;
                   1962: 
                   1963:   for (i = low; i < high; i += 2)
                   1964:     {
                   1965:       if (regs_ever_live[i] && ! call_used_regs[i])
                   1966:        if (regs_ever_live[i+1] && ! call_used_regs[i+1])
                   1967:          fprintf (file, "\tstd %s,[%s+%d]\n",
                   1968:                   reg_names[i], base, offset + 4 * n_fregs),
                   1969:          n_fregs += 2;
                   1970:        else
                   1971:          fprintf (file, "\tst %s,[%s+%d]\n",
                   1972:                   reg_names[i], base, offset + 4 * n_fregs),
                   1973:          n_fregs += 2;
                   1974:       else if (regs_ever_live[i+1] && ! call_used_regs[i+1])
                   1975:        fprintf (file, "\tst %s,[%s+%d]\n",
                   1976:                 reg_names[i+1], base, offset + 4 * n_fregs),
                   1977:        n_fregs += 2;
                   1978:     }
                   1979:   return n_fregs;
                   1980: }
                   1981: 
                   1982: #ifdef __GNUC__
                   1983: inline
                   1984: #endif
                   1985: static int
                   1986: restore_regs (file, low, high, base, offset, n_fregs)
                   1987:      FILE *file;
                   1988:      int low, high;
                   1989:      char *base;
                   1990:      int offset;
                   1991: {
                   1992:   int i;
                   1993: 
                   1994:   for (i = low; i < high; i += 2)
                   1995:     {
                   1996:       if (regs_ever_live[i] && ! call_used_regs[i])
                   1997:        if (regs_ever_live[i+1] && ! call_used_regs[i+1])
                   1998:          fprintf (file, "\tldd [%s+%d], %s\n",
                   1999:                   base, offset + 4 * n_fregs, reg_names[i]),
                   2000:          n_fregs += 2;
                   2001:        else
                   2002:          fprintf (file, "\tld [%s+%d],%s\n",
                   2003:                   base, offset + 4 * n_fregs, reg_names[i]),
                   2004:          n_fregs += 2;
                   2005:       else if (regs_ever_live[i+1] && ! call_used_regs[i+1])
                   2006:        fprintf (file, "\tld [%s+%d],%s\n",
                   2007:                 base, offset + 4 * n_fregs, reg_names[i+1]),
                   2008:        n_fregs += 2;
                   2009:     }
                   2010:   return n_fregs;
                   2011: }
                   2012: 
                   2013: /* Static variables we want to share between prologue and epilogue.  */
                   2014: 
                   2015: /* Number of live floating point registers needed to be saved.  */
                   2016: static int num_fregs;
                   2017: 
                   2018: int
                   2019: compute_frame_size (size, leaf_function)
                   2020:      int size;
                   2021:      int leaf_function;
                   2022: {
                   2023:   int fregs_ever_live = 0;
                   2024:   int n_fregs = 0, i;
                   2025:   int outgoing_args_size = (current_function_outgoing_args_size
                   2026:                            + REG_PARM_STACK_SPACE (current_function_decl));
                   2027: 
                   2028:   apparent_fsize = ((size) + 7 - STARTING_FRAME_OFFSET) & -8;
                   2029:   for (i = 32; i < FIRST_PSEUDO_REGISTER; i += 2)
                   2030:     fregs_ever_live |= regs_ever_live[i]|regs_ever_live[i+1];
                   2031: 
                   2032:   if (TARGET_EPILOGUE && fregs_ever_live)
                   2033:     {
                   2034:       for (i = 32; i < FIRST_PSEUDO_REGISTER; i += 2)
                   2035:        if ((regs_ever_live[i] && ! call_used_regs[i])
                   2036:            || (regs_ever_live[i+1] && ! call_used_regs[i+1]))
                   2037:          n_fregs += 2;
                   2038:     }
                   2039: 
                   2040:   /* Set up values for use in `function_epilogue'.  */
                   2041:   num_fregs = n_fregs;
                   2042: 
                   2043:   apparent_fsize += (outgoing_args_size+7) & -8;
                   2044:   if (leaf_function && n_fregs == 0
                   2045:       && apparent_fsize == (REG_PARM_STACK_SPACE (current_function_decl)
                   2046:                            - STARTING_FRAME_OFFSET))
                   2047:     apparent_fsize = 0;
                   2048: 
                   2049:   actual_fsize = apparent_fsize + n_fregs*4;
                   2050: 
                   2051:   /* Make sure nothing can clobber our register windows.
                   2052:      If a SAVE must be done, or there is a stack-local variable,
                   2053:      the register window area must be allocated.  */
                   2054:   if (leaf_function == 0 || size > 0)
                   2055:     actual_fsize += (16 * UNITS_PER_WORD)+8;
                   2056: 
                   2057:   return actual_fsize;
                   2058: }
                   2059: 
                   2060: /* Output code for the function prologue.  */
                   2061: 
                   2062: void
                   2063: output_function_prologue (file, size, leaf_function)
                   2064:      FILE *file;
                   2065:      int size;
                   2066:      int leaf_function;
                   2067: {
                   2068:   /* ??? This should be %sp+actual_fsize for a leaf function.  I think it
                   2069:      works only because it is never used.  */
                   2070:   if (leaf_function)
                   2071:     frame_base_name = "%sp+80";
                   2072:   else
                   2073:     frame_base_name = "%fp";
                   2074: 
                   2075:   /* Need to use actual_fsize, since we are also allocating
                   2076:      space for our callee (and our own register save area).  */
                   2077:   actual_fsize = compute_frame_size (size, leaf_function);
                   2078: 
                   2079:   fprintf (file, "\t!#PROLOGUE# 0\n");
                   2080:   if (actual_fsize == 0)
                   2081:     /* do nothing.  */ ;
                   2082:   else if (actual_fsize <= 4096)
                   2083:     {
                   2084:       if (! leaf_function)
                   2085:        fprintf (file, "\tsave %%sp,-%d,%%sp\n", actual_fsize);
                   2086:       else
                   2087:        fprintf (file, "\tadd %%sp,-%d,%%sp\n", actual_fsize);
                   2088:     }
                   2089:   else if (actual_fsize <= 8192)
                   2090:     {
                   2091:       /* For frames in the range 4097..8192, we can use just two insns.  */
                   2092:       if (! leaf_function)
                   2093:        {
                   2094:          fprintf (file, "\tsave %%sp,-4096,%%sp\n");
                   2095:          fprintf (file, "\tadd %%sp,-%d,%%sp\n", actual_fsize - 4096);
                   2096:        }
                   2097:       else
                   2098:        {
                   2099:          fprintf (file, "\tadd %%sp,-4096,%%sp\n");
                   2100:          fprintf (file, "\tadd %%sp,-%d,%%sp\n", actual_fsize - 4096);
                   2101:        }
                   2102:     }
                   2103:   else
                   2104:     {
                   2105:       if (! leaf_function)
                   2106:        {
                   2107:          fprintf (file, "\tsethi %%hi(-%d),%%g1\n", actual_fsize);
                   2108:          if ((actual_fsize & 0x3ff) != 0)
                   2109:            fprintf (file, "\tor %%g1,%%lo(-%d),%%g1\n", actual_fsize);
                   2110:          fprintf (file, "\tsave %%sp,%%g1,%%sp\n");
                   2111:        }
                   2112:       else
                   2113:        {
                   2114:          fprintf (file, "\tsethi %%hi(-%d),%%g1\n", actual_fsize);
                   2115:          if ((actual_fsize & 0x3ff) != 0)
                   2116:            fprintf (file, "\tor %%g1,%%lo(-%d),%%g1\n", actual_fsize);
                   2117:          fprintf (file, "\tadd %%sp,%%g1,%%sp\n");
                   2118:        }
                   2119:     }
                   2120: 
                   2121:   /* If doing anything with PIC, do it now.  */
                   2122:   if (! flag_pic)
                   2123:     fprintf (file, "\t!#PROLOGUE# 1\n");
                   2124: 
                   2125:   /* Figure out where to save any special registers.  */
                   2126:   if (num_fregs)
                   2127:     {
                   2128:       int offset, n_fregs = num_fregs;
                   2129: 
                   2130:       /* ??? This should always be -apparent_fsize.  */
                   2131:       if (! leaf_function)
                   2132:        offset = -apparent_fsize;
                   2133:       else
                   2134:        offset = 0;
                   2135: 
                   2136:       if (TARGET_EPILOGUE && ! leaf_function)
                   2137:        n_fregs = save_regs (file, 0, 16, frame_base_name, offset, 0);
                   2138:       else if (leaf_function)
                   2139:        n_fregs = save_regs (file, 0, 32, frame_base_name, offset, 0);
                   2140:       if (TARGET_EPILOGUE)
                   2141:        save_regs (file, 32, FIRST_PSEUDO_REGISTER,
                   2142:                   frame_base_name, offset, n_fregs);
                   2143:     }
                   2144: 
                   2145:   leaf_label = 0;
                   2146:   if (leaf_function && actual_fsize != 0)
                   2147:     {
                   2148:       /* warning ("leaf procedure with frame size %d", actual_fsize); */
                   2149:       if (! TARGET_EPILOGUE)
                   2150:        leaf_label = gen_label_rtx ();
                   2151:     }
                   2152: }
                   2153: 
                   2154: /* Output code for the function epilogue.  */
                   2155: 
                   2156: void
                   2157: output_function_epilogue (file, size, leaf_function)
                   2158:      FILE *file;
                   2159:      int size;
                   2160:      int leaf_function;
                   2161: {
                   2162:   char *ret;
                   2163: 
                   2164:   if (leaf_label)
                   2165:     {
                   2166:       emit_label_after (leaf_label, get_last_insn ());
                   2167:       final_scan_insn (get_last_insn (), file, 0, 0, 1);
                   2168:     }
                   2169: 
                   2170:   if (num_fregs)
                   2171:     {
                   2172:       int offset, n_fregs = num_fregs;
                   2173: 
                   2174:       /* ??? This should always be -apparent_fsize.  */
                   2175:       if (! leaf_function)
                   2176:        offset = -apparent_fsize;
                   2177:       else
                   2178:        offset = 0;
                   2179: 
                   2180:       if (TARGET_EPILOGUE && ! leaf_function)
                   2181:        n_fregs = restore_regs (file, 0, 16, frame_base_name, offset, 0);
                   2182:       else if (leaf_function)
                   2183:        n_fregs = restore_regs (file, 0, 32, frame_base_name, offset, 0);
                   2184:       if (TARGET_EPILOGUE)
                   2185:        restore_regs (file, 32, FIRST_PSEUDO_REGISTER,
                   2186:                      frame_base_name, offset, n_fregs);
                   2187:     }
                   2188: 
                   2189:   /* Work out how to skip the caller's unimp instruction if required.  */
                   2190:   if (leaf_function)
                   2191:     ret = (current_function_returns_struct ? "jmp %o7+12" : "retl");
                   2192:   else
                   2193:     ret = (current_function_returns_struct ? "jmp %i7+12" : "ret");
                   2194: 
                   2195:   if (TARGET_EPILOGUE || leaf_label)
                   2196:     {
                   2197:       int old_target_epilogue = TARGET_EPILOGUE;
                   2198:       target_flags &= ~old_target_epilogue;
                   2199: 
                   2200:       if (! leaf_function)
                   2201:        {
                   2202:          /* If we wound up with things in our delay slot, flush them here.  */
                   2203:          if (current_function_epilogue_delay_list)
                   2204:            {
                   2205:              rtx insn = emit_jump_insn_after (gen_rtx (RETURN, VOIDmode),
                   2206:                                               get_last_insn ());
                   2207:              PATTERN (insn) = gen_rtx (PARALLEL, VOIDmode,
                   2208:                                        gen_rtvec (2,
                   2209:                                                   PATTERN (XEXP (current_function_epilogue_delay_list, 0)),
                   2210:                                                   PATTERN (insn)));
                   2211:              final_scan_insn (insn, file, 1, 0, 1);
                   2212:            }
                   2213:          else
                   2214:            fprintf (file, "\t%s\n\trestore\n", ret);
                   2215:        }
                   2216:       /* All of the following cases are for leaf functions.  */
                   2217:       else if (current_function_epilogue_delay_list)
                   2218:        {
                   2219:          /* eligible_for_epilogue_delay_slot ensures that if this is a
                   2220:             leaf function, then we will only have insn in the delay slot
                   2221:             if the frame size is zero, thus no adjust for the stack is
                   2222:             needed here.  */
                   2223:          if (actual_fsize != 0)
                   2224:            abort ();
                   2225:          fprintf (file, "\t%s\n", ret);
                   2226:          final_scan_insn (XEXP (current_function_epilogue_delay_list, 0),
                   2227:                           file, 1, 0, 1);
                   2228:        }
                   2229:       /* Output 'nop' instead of 'sub %sp,-0,%sp' when no frame, so as to
                   2230:         avoid generating confusing assembly language output.  */
                   2231:       else if (actual_fsize == 0)
                   2232:        fprintf (file, "\t%s\n\tnop\n", ret);
                   2233:       else if (actual_fsize <= 4096)
                   2234:        fprintf (file, "\t%s\n\tsub %%sp,-%d,%%sp\n", ret, actual_fsize);
                   2235:       else if (actual_fsize <= 8192)
                   2236:        fprintf (file, "\tsub %%sp,-4096,%%sp\n\t%s\n\tsub %%sp,-%d,%%sp\n",
                   2237:                 ret, actual_fsize - 4096);
                   2238:       else if ((actual_fsize & 0x3ff) == 0)
                   2239:        fprintf (file, "\tsethi %%hi(%d),%%g1\n\t%s\n\tadd %%sp,%%g1,%%sp\n",
                   2240:                 actual_fsize, ret);
                   2241:       else              
                   2242:        fprintf (file, "\tsethi %%hi(%d),%%g1\n\tor %%g1,%%lo(%d),%%g1\n\t%s\n\tadd %%sp,%%g1,%%sp\n",
                   2243:                 actual_fsize, actual_fsize, ret);
                   2244:       target_flags |= old_target_epilogue;
                   2245:     }
                   2246: }
                   2247: 
                   2248: /* Do what is necessary for `va_start'.  The argument is ignored;
                   2249:    We look at the current function to determine if stdarg or varargs
                   2250:    is used and return the address of the first unnamed parameter.  */
                   2251: 
                   2252: rtx
                   2253: sparc_builtin_saveregs (arglist)
                   2254:      tree arglist;
                   2255: {
                   2256:   tree fntype = TREE_TYPE (current_function_decl);
                   2257:   int stdarg = (TYPE_ARG_TYPES (fntype) != 0
                   2258:                && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
                   2259:                    != void_type_node));
                   2260:   int first_reg = current_function_args_info;
                   2261:   rtx address;
                   2262:   int regno;
                   2263: 
                   2264: #if 0 /* This code seemed to have no effect except to make
                   2265:         varargs not work right when va_list wasn't the first arg.  */
                   2266:   if (! stdarg)
                   2267:     first_reg = 0;
                   2268: #endif
                   2269: 
                   2270:   for (regno = first_reg; regno < NPARM_REGS; regno++)
                   2271:     emit_move_insn (gen_rtx (MEM, word_mode,
                   2272:                             gen_rtx (PLUS, Pmode,
                   2273:                                      frame_pointer_rtx,
                   2274:                                      GEN_INT (STACK_POINTER_OFFSET
                   2275:                                               + UNITS_PER_WORD * regno))),
                   2276:                    gen_rtx (REG, word_mode, BASE_INCOMING_ARG_REG (word_mode)
                   2277:                             + regno));
                   2278: 
                   2279:   address = gen_rtx (PLUS, Pmode,
                   2280:                     frame_pointer_rtx,
                   2281:                     GEN_INT (STACK_POINTER_OFFSET
                   2282:                              + UNITS_PER_WORD * first_reg));
                   2283: 
                   2284:   return address;
                   2285: }
                   2286: 
                   2287: /* Return the string to output a conditional branch to LABEL, which is
                   2288:    the operand number of the label.  OP is the conditional expression.  The
                   2289:    mode of register 0 says what kind of comparison we made.
                   2290: 
                   2291:    REVERSED is non-zero if we should reverse the sense of the comparison.
                   2292: 
                   2293:    ANNUL is non-zero if we should generate an annulling branch.
                   2294: 
                   2295:    NOOP is non-zero if we have to follow this branch by a noop.  */
                   2296: 
                   2297: char *
                   2298: output_cbranch (op, label, reversed, annul, noop)
                   2299:      rtx op;
                   2300:      int label;
                   2301:      int reversed, annul, noop;
                   2302: {
                   2303:   static char string[20];
                   2304:   enum rtx_code code = GET_CODE (op);
                   2305:   enum machine_mode mode = GET_MODE (XEXP (op, 0));
                   2306:   static char labelno[] = " %lX";
                   2307: 
                   2308:   /* ??? FP branches can not be preceded by another floating point insn.
                   2309:      Because there is currently no concept of pre-delay slots, we can fix
                   2310:      this only by always emitting a nop before a floating point branch.  */
                   2311: 
                   2312:   if (mode == CCFPmode || mode == CCFPEmode)
                   2313:     strcpy (string, "nop\n\t");
                   2314: 
                   2315:   /* If not floating-point or if EQ or NE, we can just reverse the code.  */
                   2316:   if (reversed
                   2317:       && ((mode != CCFPmode && mode != CCFPEmode) || code == EQ || code == NE))
                   2318:     code = reverse_condition (code), reversed = 0;
                   2319: 
                   2320:   /* Start by writing the branch condition.  */
                   2321:   switch (code)
                   2322:     {
                   2323:     case NE:
                   2324:       if (mode == CCFPmode || mode == CCFPEmode)
                   2325:        strcat (string, "fbne");
                   2326:       else
                   2327:        strcpy (string, "bne");
                   2328:       break;
                   2329: 
                   2330:     case EQ:
                   2331:       if (mode == CCFPmode || mode == CCFPEmode)
                   2332:        strcat (string, "fbe");
                   2333:       else
                   2334:        strcpy (string, "be");
                   2335:       break;
                   2336: 
                   2337:     case GE:
                   2338:       if (mode == CCFPmode || mode == CCFPEmode)
                   2339:        {
                   2340:          if (reversed)
                   2341:            strcat (string, "fbul");
                   2342:          else
                   2343:            strcat (string, "fbge");
                   2344:        }
                   2345:       else if (mode == CC_NOOVmode)
                   2346:        strcpy (string, "bpos");
                   2347:       else
                   2348:        strcpy (string, "bge");
                   2349:       break;
                   2350: 
                   2351:     case GT:
                   2352:       if (mode == CCFPmode || mode == CCFPEmode)
                   2353:        {
                   2354:          if (reversed)
                   2355:            strcat (string, "fbule");
                   2356:          else
                   2357:            strcat (string, "fbg");
                   2358:        }
                   2359:       else
                   2360:        strcpy (string, "bg");
                   2361:       break;
                   2362: 
                   2363:     case LE:
                   2364:       if (mode == CCFPmode || mode == CCFPEmode)
                   2365:        {
                   2366:          if (reversed)
                   2367:            strcat (string, "fbug");
                   2368:          else
                   2369:            strcat (string, "fble");
                   2370:        }
                   2371:       else
                   2372:        strcpy (string, "ble");
                   2373:       break;
                   2374: 
                   2375:     case LT:
                   2376:       if (mode == CCFPmode || mode == CCFPEmode)
                   2377:        {
                   2378:          if (reversed)
                   2379:            strcat (string, "fbuge");
                   2380:          else
                   2381:            strcat (string, "fbl");
                   2382:        }
                   2383:       else if (mode == CC_NOOVmode)
                   2384:        strcpy (string, "bneg");
                   2385:       else
                   2386:        strcpy (string, "bl");
                   2387:       break;
                   2388: 
                   2389:     case GEU:
                   2390:       strcpy (string, "bgeu");
                   2391:       break;
                   2392: 
                   2393:     case GTU:
                   2394:       strcpy (string, "bgu");
                   2395:       break;
                   2396: 
                   2397:     case LEU:
                   2398:       strcpy (string, "bleu");
                   2399:       break;
                   2400: 
                   2401:     case LTU:
                   2402:       strcpy (string, "blu");
                   2403:       break;
                   2404:     }
                   2405: 
                   2406:   /* Now add the annulling, the label, and a possible noop.  */
                   2407:   if (annul)
                   2408:     strcat (string, ",a");
                   2409: 
                   2410:   labelno[3] = label + '0';
                   2411:   strcat (string, labelno);
                   2412: 
                   2413:   if (noop)
                   2414:     strcat (string, "\n\tnop");
                   2415: 
                   2416:   return string;
                   2417: }
                   2418: 
                   2419: /* Output assembler code to return from a function.  */
                   2420: 
                   2421: char *
                   2422: output_return (operands)
                   2423:      rtx *operands;
                   2424: {
                   2425:   if (leaf_label)
                   2426:     {
                   2427:       operands[0] = leaf_label;
                   2428:       return "b,a %l0";
                   2429:     }
                   2430:   else if (leaf_function)
                   2431:     {
                   2432:       /* If we didn't allocate a frame pointer for the current function,
                   2433:         the stack pointer might have been adjusted.  Output code to
                   2434:         restore it now.  */
                   2435: 
                   2436:       operands[0] = gen_rtx (CONST_INT, VOIDmode, actual_fsize);
                   2437: 
                   2438:       /* Use sub of negated value in first two cases instead of add to
                   2439:         allow actual_fsize == 4096.  */
                   2440: 
                   2441:       if (actual_fsize <= 4096)
                   2442:        {
                   2443:          if (current_function_returns_struct)
                   2444:            return "jmp %%o7+12\n\tsub %%sp,-%0,%%sp";
                   2445:          else
                   2446:            return "retl\n\tsub %%sp,-%0,%%sp";
                   2447:        }
                   2448:       else if (actual_fsize <= 8192)
                   2449:        {
                   2450:          operands[0] = gen_rtx (CONST_INT, VOIDmode, actual_fsize - 4096);
                   2451:          if (current_function_returns_struct)
                   2452:            return "sub %%sp,-4096,%%sp\n\tjmp %%o7+12\n\tsub %%sp,-%0,%%sp";
                   2453:          else
                   2454:            return "sub %%sp,-4096,%%sp\n\tretl\n\tsub %%sp,-%0,%%sp";
                   2455:        }
                   2456:       else if (current_function_returns_struct)
                   2457:        {
                   2458:          if ((actual_fsize & 0x3ff) != 0)
                   2459:            return "sethi %%hi(%a0),%%g1\n\tor %%g1,%%lo(%a0),%%g1\n\tjmp %%o7+12\n\tadd %%sp,%%g1,%%sp";
                   2460:          else
                   2461:            return "sethi %%hi(%a0),%%g1\n\tjmp %%o7+12\n\tadd %%sp,%%g1,%%sp";
                   2462:        }
                   2463:       else
                   2464:        {
                   2465:          if ((actual_fsize & 0x3ff) != 0)
                   2466:            return "sethi %%hi(%a0),%%g1\n\tor %%g1,%%lo(%a0),%%g1\n\tretl\n\tadd %%sp,%%g1,%%sp";
                   2467:          else
                   2468:            return "sethi %%hi(%a0),%%g1\n\tretl\n\tadd %%sp,%%g1,%%sp";
                   2469:        }
                   2470:     }
                   2471:   else
                   2472:     {
                   2473:       if (current_function_returns_struct)
                   2474:        return "jmp %%i7+12\n\trestore";
                   2475:       else
                   2476:        return "ret\n\trestore";
                   2477:     }
                   2478: }
                   2479: 
                   2480: /* Leaf functions and non-leaf functions have different needs.  */
                   2481: 
                   2482: static int
                   2483: reg_leaf_alloc_order[] = REG_LEAF_ALLOC_ORDER;
                   2484: 
                   2485: static int
                   2486: reg_nonleaf_alloc_order[] = REG_ALLOC_ORDER;
                   2487: 
                   2488: static int *reg_alloc_orders[] = {
                   2489:   reg_leaf_alloc_order,
                   2490:   reg_nonleaf_alloc_order};
                   2491: 
                   2492: void
                   2493: order_regs_for_local_alloc ()
                   2494: {
                   2495:   static int last_order_nonleaf = 1;
                   2496: 
                   2497:   if (regs_ever_live[15] != last_order_nonleaf)
                   2498:     {
                   2499:       last_order_nonleaf = !last_order_nonleaf;
                   2500:       bcopy (reg_alloc_orders[last_order_nonleaf], reg_alloc_order,
                   2501:             FIRST_PSEUDO_REGISTER * sizeof (int));
                   2502:     }
                   2503: }
                   2504: 
                   2505: /* Return 1 if REGNO (reg1) is even and REGNO (reg1) == REGNO (reg2) - 1.
                   2506:    This makes them candidates for using ldd and std insns. 
                   2507: 
                   2508:    Note reg1 and reg2 *must* be hard registers.  To be sure we will
                   2509:    abort if we are passed pseudo registers.  */
                   2510: 
                   2511: int
                   2512: registers_ok_for_ldd_peep (reg1, reg2)
                   2513:      rtx reg1, reg2;
                   2514: {
                   2515: 
                   2516:   /* We might have been passed a SUBREG.  */
                   2517:   if (GET_CODE (reg1) != REG || GET_CODE (reg2) != REG) 
                   2518:     return 0;
                   2519: 
                   2520:   if (REGNO (reg1) % 2 != 0)
                   2521:     return 0;
                   2522: 
                   2523:   return (REGNO (reg1) == REGNO (reg2) - 1);
                   2524:   
                   2525: }
                   2526: 
                   2527: /* Return 1 if addr1 and addr2 are suitable for use in an ldd or 
                   2528:    std insn.
                   2529: 
                   2530:    This can only happen when addr1 and addr2 are consecutive memory
                   2531:    locations (addr1 + 4 == addr2).  addr1 must also be aligned on a 
                   2532:    64 bit boundary (addr1 % 8 == 0).  
                   2533: 
                   2534:    We know %sp and %fp are kept aligned on a 64 bit boundary.  Other
                   2535:    registers are assumed to *never* be properly aligned and are 
                   2536:    rejected.
                   2537: 
                   2538:    Knowing %sp and %fp are kept aligned on a 64 bit boundary, we 
                   2539:    need only check that the offset for addr1 % 8 == 0.  */
                   2540: 
                   2541: int
                   2542: addrs_ok_for_ldd_peep (addr1, addr2)
                   2543:       rtx addr1, addr2;
                   2544: {
                   2545:   int reg1, offset1;
                   2546: 
                   2547:   /* Extract a register number and offset (if used) from the first addr.  */
                   2548:   if (GET_CODE (addr1) == PLUS)
                   2549:     {
                   2550:       /* If not a REG, return zero.  */
                   2551:       if (GET_CODE (XEXP (addr1, 0)) != REG)
                   2552:        return 0;
                   2553:       else
                   2554:        {
                   2555:           reg1 = REGNO (XEXP (addr1, 0));
                   2556:          /* The offset must be constant!  */
                   2557:          if (GET_CODE (XEXP (addr1, 1)) != CONST_INT)
                   2558:             return 0;
                   2559:           offset1 = INTVAL (XEXP (addr1, 1));
                   2560:        }
                   2561:     }
                   2562:   else if (GET_CODE (addr1) != REG)
                   2563:     return 0;
                   2564:   else
                   2565:     {
                   2566:       reg1 = REGNO (addr1);
                   2567:       /* This was a simple (mem (reg)) expression.  Offset is 0.  */
                   2568:       offset1 = 0;
                   2569:     }
                   2570: 
                   2571:   /* Make sure the second address is a (mem (plus (reg) (const_int).  */
                   2572:   if (GET_CODE (addr2) != PLUS)
                   2573:     return 0;
                   2574: 
                   2575:   if (GET_CODE (XEXP (addr2, 0)) != REG
                   2576:       || GET_CODE (XEXP (addr2, 1)) != CONST_INT)
                   2577:     return 0;
                   2578: 
                   2579:   /* Only %fp and %sp are allowed.  Additionally both addresses must
                   2580:      use the same register.  */
                   2581:   if (reg1 != FRAME_POINTER_REGNUM && reg1 != STACK_POINTER_REGNUM)
                   2582:     return 0;
                   2583: 
                   2584:   if (reg1 != REGNO (XEXP (addr2, 0)))
                   2585:     return 0;
                   2586: 
                   2587:   /* The first offset must be evenly divisible by 8 to ensure the 
                   2588:      address is 64 bit aligned.  */
                   2589:   if (offset1 % 8 != 0)
                   2590:     return 0;
                   2591: 
                   2592:   /* The offset for the second addr must be 4 more than the first addr.  */
                   2593:   if (INTVAL (XEXP (addr2, 1)) != offset1 + 4)
                   2594:     return 0;
                   2595: 
                   2596:   /* All the tests passed.  addr1 and addr2 are valid for ldd and std
                   2597:      instructions.  */
                   2598:   return 1;
                   2599: }
                   2600: 
                   2601: /* Return 1 if reg is a pseudo, or is the first register in 
                   2602:    a hard register pair.  This makes it a candidate for use in
                   2603:    ldd and std insns.  */
                   2604: 
                   2605: int
                   2606: register_ok_for_ldd (reg)
                   2607:      rtx reg;
                   2608: {
                   2609: 
                   2610:   /* We might have been passed a SUBREG.  */
                   2611:   if (GET_CODE (reg) != REG) 
                   2612:     return 0;
                   2613: 
                   2614:   if (REGNO (reg) < FIRST_PSEUDO_REGISTER)
                   2615:     return (REGNO (reg) % 2 == 0);
                   2616:   else 
                   2617:     return 1;
                   2618: 
                   2619: }
                   2620: 
                   2621: /* Print operand X (an rtx) in assembler syntax to file FILE.
                   2622:    CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
                   2623:    For `%' followed by punctuation, CODE is the punctuation and X is null.  */
                   2624: 
                   2625: void
                   2626: print_operand (file, x, code)
                   2627:      FILE *file;
                   2628:      rtx x;
                   2629:      int code;
                   2630: {
                   2631:   switch (code)
                   2632:     {
                   2633:     case '#':
                   2634:       /* Output a 'nop' if there's nothing for the delay slot.  */
                   2635:       if (dbr_sequence_length () == 0)
                   2636:        fputs ("\n\tnop", file);
                   2637:       return;
                   2638:     case '*':
                   2639:       /* Output an annul flag if there's nothing for the delay slot and we
                   2640:         are optimizing.  This is always used with '(' below.  */
                   2641:       /* Sun OS 4.1.1 dbx can't handle an annulled unconditional branch;
                   2642:         this is a dbx bug.  So, we only do this when optimizing.  */
                   2643:       if (dbr_sequence_length () == 0 && optimize)
                   2644:        fputs (",a", file);
                   2645:       return;
                   2646:     case '(':
                   2647:       /* Output a 'nop' if there's nothing for the delay slot and we are
                   2648:         not optimizing.  This is always used with '*' above.  */
                   2649:       if (dbr_sequence_length () == 0 && ! optimize)
                   2650:        fputs ("\n\tnop", file);
                   2651:       return;
                   2652:     case 'Y':
                   2653:       /* Adjust the operand to take into account a RESTORE operation.  */
                   2654:       if (GET_CODE (x) != REG)
                   2655:        output_operand_lossage ("Invalid %%Y operand");
                   2656:       else if (REGNO (x) < 8)
                   2657:        fputs (reg_names[REGNO (x)], file);
                   2658:       else if (REGNO (x) >= 24 && REGNO (x) < 32)
                   2659:        fputs (reg_names[REGNO (x)-16], file);
                   2660:       else
                   2661:        output_operand_lossage ("Invalid %%Y operand");
                   2662:       return;
                   2663:     case 'R':
                   2664:       /* Print out the second register name of a register pair or quad.
                   2665:         I.e., R (%o0) => %o1.  */
                   2666:       fputs (reg_names[REGNO (x)+1], file);
                   2667:       return;
                   2668:     case 'S':
                   2669:       /* Print out the third register name of a register quad.
                   2670:         I.e., S (%o0) => %o2.  */
                   2671:       fputs (reg_names[REGNO (x)+2], file);
                   2672:       return;
                   2673:     case 'T':
                   2674:       /* Print out the fourth register name of a register quad.
                   2675:         I.e., T (%o0) => %o3.  */
                   2676:       fputs (reg_names[REGNO (x)+3], file);
                   2677:       return;
                   2678:     case 'm':
                   2679:       /* Print the operand's address only.  */
                   2680:       output_address (XEXP (x, 0));
                   2681:       return;
                   2682:     case 'r':
                   2683:       /* In this case we need a register.  Use %g0 if the
                   2684:         operand is const0_rtx.  */
                   2685:       if (x == const0_rtx
                   2686:          || (GET_MODE (x) != VOIDmode && x == CONST0_RTX (GET_MODE (x))))
                   2687:        {
                   2688:          fputs ("%g0", file);
                   2689:          return;
                   2690:        }
                   2691:       else
                   2692:        break;
                   2693: 
                   2694:     case  'A':
                   2695:       switch (GET_CODE (x))
                   2696:        {
                   2697:        case IOR: fputs ("or", file); break;
                   2698:        case AND: fputs ("and", file); break;
                   2699:        case XOR: fputs ("xor", file); break;
                   2700:        default: output_operand_lossage ("Invalid %%A operand");
                   2701:        }
                   2702:       return;
                   2703: 
                   2704:     case 'B':
                   2705:       switch (GET_CODE (x))
                   2706:        {
                   2707:        case IOR: fputs ("orn", file); break;
                   2708:        case AND: fputs ("andn", file); break;
                   2709:        case XOR: fputs ("xnor", file); break;
                   2710:        default: output_operand_lossage ("Invalid %%B operand");
                   2711:        }
                   2712:       return;
                   2713: 
                   2714:     case 'b':
                   2715:       {
                   2716:        /* Print a sign-extended character.  */
                   2717:        int i = INTVAL (x) & 0xff;
                   2718:        if (i & 0x80)
                   2719:          i |= 0xffffff00;
                   2720:        fprintf (file, "%d", i);
                   2721:        return;
                   2722:       }
                   2723: 
                   2724:     case 0:
                   2725:       /* Do nothing special.  */
                   2726:       break;
                   2727: 
                   2728:     default:
                   2729:       /* Undocumented flag.  */
                   2730:       output_operand_lossage ("invalid operand output code");
                   2731:     }
                   2732: 
                   2733:   if (GET_CODE (x) == REG)
                   2734:     fputs (reg_names[REGNO (x)], file);
                   2735:   else if (GET_CODE (x) == MEM)
                   2736:     {
                   2737:       fputc ('[', file);
                   2738:       if (CONSTANT_P (XEXP (x, 0)))
                   2739:        /* Poor Sun assembler doesn't understand absolute addressing.  */
                   2740:        fputs ("%g0+", file);
                   2741:       output_address (XEXP (x, 0));
                   2742:       fputc (']', file);
                   2743:     }
                   2744:   else if (GET_CODE (x) == HIGH)
                   2745:     {
                   2746:       fputs ("%hi(", file);
                   2747:       output_addr_const (file, XEXP (x, 0));
                   2748:       fputc (')', file);
                   2749:     }
                   2750:   else if (GET_CODE (x) == LO_SUM)
                   2751:     {
                   2752:       print_operand (file, XEXP (x, 0), 0);
                   2753:       fputs ("+%lo(", file);
                   2754:       output_addr_const (file, XEXP (x, 1));
                   2755:       fputc (')', file);
                   2756:     }
                   2757:   else if (GET_CODE (x) == CONST_DOUBLE
                   2758:           && (GET_MODE (x) == VOIDmode
                   2759:               || GET_MODE_CLASS (GET_MODE (x)) == MODE_INT))
                   2760:     {
                   2761:       if (CONST_DOUBLE_HIGH (x) == 0)
                   2762:        fprintf (file, "%u", CONST_DOUBLE_LOW (x));
                   2763:       else if (CONST_DOUBLE_HIGH (x) == -1
                   2764:               && CONST_DOUBLE_LOW (x) < 0)
                   2765:        fprintf (file, "%d", CONST_DOUBLE_LOW (x));
                   2766:       else
                   2767:        output_operand_lossage ("long long constant not a valid immediate operand");
                   2768:     }
                   2769:   else if (GET_CODE (x) == CONST_DOUBLE)
                   2770:     output_operand_lossage ("floating point constant not a valid immediate operand");
                   2771:   else { output_addr_const (file, x); }
                   2772: }
                   2773: 
                   2774: /* This function outputs assembler code for VALUE to FILE, where VALUE is
                   2775:    a 64 bit (DImode) value.  */
                   2776: 
                   2777: /* ??? If there is a 64 bit counterpart to .word that the assembler
                   2778:    understands, then using that would simply this code greatly.  */
                   2779: 
                   2780: void
                   2781: output_double_int (file, value)
                   2782:      FILE *file;
                   2783:      rtx value;
                   2784: {
                   2785:   if (GET_CODE (value) == CONST_INT)
                   2786:     {
                   2787:       if (INTVAL (value) < 0)
                   2788:        ASM_OUTPUT_INT (file, constm1_rtx);
                   2789:       else
                   2790:        ASM_OUTPUT_INT (file, const0_rtx);
                   2791:       ASM_OUTPUT_INT (file, value);
                   2792:     }
                   2793:   else if (GET_CODE (value) == CONST_DOUBLE)
                   2794:     {
                   2795:       ASM_OUTPUT_INT (file, gen_rtx (CONST_INT, VOIDmode,
                   2796:                                     CONST_DOUBLE_HIGH (value)));
                   2797:       ASM_OUTPUT_INT (file, gen_rtx (CONST_INT, VOIDmode,
                   2798:                                     CONST_DOUBLE_LOW (value)));
                   2799:     }
                   2800:   else if (GET_CODE (value) == SYMBOL_REF
                   2801:           || GET_CODE (value) == CONST
                   2802:           || GET_CODE (value) == PLUS)
                   2803:     {
                   2804:       /* Addresses are only 32 bits.  */
                   2805:       ASM_OUTPUT_INT (file, const0_rtx);
                   2806:       ASM_OUTPUT_INT (file, value);
                   2807:     }
                   2808:   else
                   2809:     abort ();
                   2810: }
                   2811: 
                   2812: #ifndef CHAR_TYPE_SIZE
                   2813: #define CHAR_TYPE_SIZE BITS_PER_UNIT
                   2814: #endif
                   2815: 
                   2816: #ifndef SHORT_TYPE_SIZE
                   2817: #define SHORT_TYPE_SIZE (BITS_PER_UNIT * 2)
                   2818: #endif
                   2819: 
                   2820: #ifndef INT_TYPE_SIZE
                   2821: #define INT_TYPE_SIZE BITS_PER_WORD
                   2822: #endif
                   2823: 
                   2824: #ifndef LONG_TYPE_SIZE
                   2825: #define LONG_TYPE_SIZE BITS_PER_WORD
                   2826: #endif
                   2827: 
                   2828: #ifndef LONG_LONG_TYPE_SIZE
                   2829: #define LONG_LONG_TYPE_SIZE (BITS_PER_WORD * 2)
                   2830: #endif
                   2831: 
                   2832: #ifndef FLOAT_TYPE_SIZE
                   2833: #define FLOAT_TYPE_SIZE BITS_PER_WORD
                   2834: #endif
                   2835: 
                   2836: #ifndef DOUBLE_TYPE_SIZE
                   2837: #define DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
                   2838: #endif
                   2839: 
                   2840: #ifndef LONG_DOUBLE_TYPE_SIZE
                   2841: #define LONG_DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
                   2842: #endif
                   2843: 
                   2844: unsigned long
                   2845: sparc_type_code (type)
                   2846:      register tree type;
                   2847: {
                   2848:   register unsigned long qualifiers = 0;
                   2849:   register unsigned shift = 6;
                   2850: 
                   2851:   for (;;)
                   2852:     {
                   2853:       switch (TREE_CODE (type))
                   2854:        {
                   2855:        case ERROR_MARK:
                   2856:          return qualifiers;
                   2857:   
                   2858:        case ARRAY_TYPE:
                   2859:          qualifiers |= (3 << shift);
                   2860:          shift += 2;
                   2861:          type = TREE_TYPE (type);
                   2862:          break;
                   2863: 
                   2864:        case FUNCTION_TYPE:
                   2865:        case METHOD_TYPE:
                   2866:          qualifiers |= (2 << shift);
                   2867:          shift += 2;
                   2868:          type = TREE_TYPE (type);
                   2869:          break;
                   2870: 
                   2871:        case POINTER_TYPE:
                   2872:        case REFERENCE_TYPE:
                   2873:        case OFFSET_TYPE:
                   2874:          qualifiers |= (1 << shift);
                   2875:          shift += 2;
                   2876:          type = TREE_TYPE (type);
                   2877:          break;
                   2878: 
                   2879:        case RECORD_TYPE:
                   2880:          return (qualifiers | 8);
                   2881: 
                   2882:        case UNION_TYPE:
                   2883:          return (qualifiers | 9);
                   2884: 
                   2885:        case ENUMERAL_TYPE:
                   2886:          return (qualifiers | 10);
                   2887: 
                   2888:        case VOID_TYPE:
                   2889:          return (qualifiers | 16);
                   2890: 
                   2891:        case INTEGER_TYPE:
                   2892:          /* Carefully distinguish all the standard types of C,
                   2893:             without messing up if the language is not C.
                   2894:             Note that we check only for the names that contain spaces;
                   2895:             other names might occur by coincidence in other languages.  */
                   2896:          if (TYPE_NAME (type) != 0
                   2897:              && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
                   2898:              && DECL_NAME (TYPE_NAME (type)) != 0
                   2899:              && TREE_CODE (DECL_NAME (TYPE_NAME (type))) == IDENTIFIER_NODE)
                   2900:            {
                   2901:              char *name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
                   2902:   
                   2903:              if (!strcmp (name, "unsigned char"))
                   2904:                return (qualifiers | 12);
                   2905:              if (!strcmp (name, "signed char"))
                   2906:                return (qualifiers | 2);
                   2907:              if (!strcmp (name, "unsigned int"))
                   2908:                return (qualifiers | 14);
                   2909:              if (!strcmp (name, "short int"))
                   2910:                return (qualifiers | 3);
                   2911:              if (!strcmp (name, "short unsigned int"))
                   2912:                return (qualifiers | 13);
                   2913:              if (!strcmp (name, "long int"))
                   2914:                return (qualifiers | 5);
                   2915:              if (!strcmp (name, "long unsigned int"))
                   2916:                return (qualifiers | 15);
                   2917:              if (!strcmp (name, "long long int"))
                   2918:                return (qualifiers | 5);        /* Who knows? */
                   2919:              if (!strcmp (name, "long long unsigned int"))
                   2920:                return (qualifiers | 15);       /* Who knows? */
                   2921:            }
                   2922:   
                   2923:          /* Most integer types will be sorted out above, however, for the
                   2924:             sake of special `array index' integer types, the following code
                   2925:             is also provided.  */
                   2926:   
                   2927:          if (TYPE_PRECISION (type) == INT_TYPE_SIZE)
                   2928:            return (qualifiers | (TREE_UNSIGNED (type) ? 14 : 4));
                   2929:   
                   2930:          if (TYPE_PRECISION (type) == LONG_TYPE_SIZE)
                   2931:            return (qualifiers | (TREE_UNSIGNED (type) ? 15 : 5));
                   2932:   
                   2933:          if (TYPE_PRECISION (type) == LONG_LONG_TYPE_SIZE)
                   2934:            return (qualifiers | (TREE_UNSIGNED (type) ? 15 : 5));
                   2935:   
                   2936:          if (TYPE_PRECISION (type) == SHORT_TYPE_SIZE)
                   2937:            return (qualifiers | (TREE_UNSIGNED (type) ? 13 : 3));
                   2938:   
                   2939:          if (TYPE_PRECISION (type) == CHAR_TYPE_SIZE)
                   2940:            return (qualifiers | (TREE_UNSIGNED (type) ? 12 : 2));
                   2941:   
                   2942:          abort ();
                   2943:   
                   2944:        case REAL_TYPE:
                   2945:          /* Carefully distinguish all the standard types of C,
                   2946:             without messing up if the language is not C.  */
                   2947:          if (TYPE_NAME (type) != 0
                   2948:              && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
                   2949:              && DECL_NAME (TYPE_NAME (type)) != 0
                   2950:              && TREE_CODE (DECL_NAME (TYPE_NAME (type))) == IDENTIFIER_NODE)
                   2951:            {
                   2952:              char *name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
                   2953:   
                   2954:              if (!strcmp (name, "long double"))
                   2955:                return (qualifiers | 7);        /* Who knows? */
                   2956:            }
                   2957:   
                   2958:          if (TYPE_PRECISION (type) == DOUBLE_TYPE_SIZE)
                   2959:            return (qualifiers | 7);
                   2960:          if (TYPE_PRECISION (type) == FLOAT_TYPE_SIZE)
                   2961:            return (qualifiers | 6);
                   2962:          if (TYPE_PRECISION (type) == LONG_DOUBLE_TYPE_SIZE)
                   2963:            return (qualifiers | 7);    /* Who knows? */
                   2964:          abort ();
                   2965:   
                   2966:        case COMPLEX_TYPE:      /* GNU Fortran COMPLEX type.  */
                   2967:          /* ??? We need to distinguish between double and float complex types,
                   2968:             but I don't know how yet because I can't reach this code from
                   2969:             existing front-ends.  */
                   2970:          return (qualifiers | 7);      /* Who knows? */
                   2971: 
                   2972:        case CHAR_TYPE:         /* GNU Pascal CHAR type.  Not used in C.  */
                   2973:        case BOOLEAN_TYPE:      /* GNU Fortran BOOLEAN type.  */
                   2974:        case FILE_TYPE:         /* GNU Pascal FILE type.  */
                   2975:        case STRING_TYPE:       /* GNU Fortran STRING type. */
                   2976:        case LANG_TYPE:         /* ? */
                   2977:          abort ();
                   2978:   
                   2979:        default:
                   2980:          abort ();             /* Not a type! */
                   2981:         }
                   2982:     }
                   2983: }
                   2984: 
                   2985: /* Subroutines to support a flat (single) register window calling
                   2986:    convention.  */
                   2987: 
                   2988: /* Single-register window sparc stack frames look like:
                   2989: 
                   2990:              Before call                       After call
                   2991:         +-----------------------+      +-----------------------+
                   2992:    high |                      |       |                       |
                   2993:    mem. |                      |       |                       |
                   2994:         |  caller's temps.     |       |  caller's temps.      |
                   2995:        |                       |       |                       |
                   2996:         +-----------------------+      +-----------------------+
                   2997:        |                       |       |                       |
                   2998:         |  arguments on stack.  |      |  arguments on stack.  |
                   2999:        |                       |FP+92->|                       |
                   3000:         +-----------------------+      +-----------------------+
                   3001:        |  6 words to save      |       |  6 words to save      |
                   3002:        |  arguments passed     |       |  arguments passed     |
                   3003:        |  in registers, even   |       |  in registers, even   |
                   3004:  SP+68->|  if not passed.       |FP+68->|  if not passed.      |
                   3005:        +-----------------------+       +-----------------------+
                   3006:        | 1 word struct addr    |FP+64->| 1 word struct addr    |
                   3007:        +-----------------------+       +-----------------------+
                   3008:        |                       |       |                       |
                   3009:        | 16 word reg save area |       | 16 word reg save area |
                   3010:     SP->|                      |   FP->|                       |
                   3011:        +-----------------------+       +-----------------------+
                   3012:                                        | 4 word area for       |
                   3013:                                 FP-16->| fp/alu reg moves      |
                   3014:                                        +-----------------------+
                   3015:                                        |                       |
                   3016:                                        |  local variables      |
                   3017:                                        |                       |
                   3018:                                        +-----------------------+
                   3019:                                        |                       |
                   3020:                                         |  fp register save     |
                   3021:                                        |                       |
                   3022:                                        +-----------------------+
                   3023:                                        |                       |
                   3024:                                         |  gp register save     |
                   3025:                                         |                      |
                   3026:                                        +-----------------------+
                   3027:                                        |                       |
                   3028:                                         |  alloca allocations   |
                   3029:                                        |                       |
                   3030:                                        +-----------------------+
                   3031:                                        |                       |
                   3032:                                         |  arguments on stack   |
                   3033:                                 SP+92->|                       |
                   3034:                                        +-----------------------+
                   3035:                                         |  6 words to save      |
                   3036:                                        |  arguments passed     |
                   3037:                                         |  in registers, even   |
                   3038:    low                           SP+68->|  if not passed.       |
                   3039:    memory                              +-----------------------+
                   3040:                                 SP+64->| 1 word struct addr    |
                   3041:                                        +-----------------------+
                   3042:                                        |                       |
                   3043:                                        I 16 word reg save area |
                   3044:                                    SP->|                       |
                   3045:                                        +-----------------------+  */
                   3046: 
                   3047: /* Structure to be filled in by sparc_frw_compute_frame_size with register
                   3048:    save masks, and offsets for the current function.  */
                   3049: 
                   3050: struct sparc_frame_info
                   3051: {
                   3052:   unsigned long total_size;    /* # bytes that the entire frame takes up.  */
                   3053:   unsigned long var_size;      /* # bytes that variables take up.  */
                   3054:   unsigned long args_size;     /* # bytes that outgoing arguments take up.  */
                   3055:   unsigned long extra_size;    /* # bytes of extra gunk.  */
                   3056:   unsigned int  gp_reg_size;   /* # bytes needed to store gp regs.  */
                   3057:   unsigned int  fp_reg_size;   /* # bytes needed to store fp regs.  */
                   3058:   unsigned long mask;          /* Mask of saved gp registers.  */
                   3059:   unsigned long fmask;         /* Mask of saved fp registers.  */
                   3060:   unsigned long gp_sp_offset;  /* Offset from new sp to store gp regs.  */
                   3061:   unsigned long fp_sp_offset;  /* Offset from new sp to store fp regs.  */
                   3062:   int          initialized;    /* Nonzero if frame size already calculated.  */
                   3063: };
                   3064: 
                   3065: /* Current frame information calculated by sparc_frw_compute_frame_size.  */
                   3066: struct sparc_frame_info current_frame_info;
                   3067: 
                   3068: /* Zero structure to initialize current_frame_info.  */
                   3069: struct sparc_frame_info zero_frame_info;
                   3070: 
                   3071: /* Tell prologue and epilogue if register REGNO should be saved / restored.  */
                   3072: 
                   3073: #define MUST_SAVE_REGISTER(regno) \
                   3074:  ((regs_ever_live[regno] && !call_used_regs[regno])            \
                   3075:   || (regno == FRAME_POINTER_REGNUM && frame_pointer_needed)   \
                   3076:   || (regno == 15 && regs_ever_live[15]))
                   3077: 
                   3078: /* Return the bytes needed to compute the frame pointer from the current
                   3079:    stack pointer.  */
                   3080: 
                   3081: unsigned long
                   3082: sparc_frw_compute_frame_size (size)
                   3083:      int size;                 /* # of var. bytes allocated.  */
                   3084: {
                   3085:   int regno;
                   3086:   unsigned long total_size;    /* # bytes that the entire frame takes up.  */
                   3087:   unsigned long var_size;      /* # bytes that variables take up.  */
                   3088:   unsigned long args_size;     /* # bytes that outgoing arguments take up.  */
                   3089:   unsigned long extra_size;    /* # extra bytes.  */
                   3090:   unsigned int  gp_reg_size;   /* # bytes needed to store gp regs.  */
                   3091:   unsigned int  fp_reg_size;   /* # bytes needed to store fp regs.  */
                   3092:   unsigned long mask;          /* Mask of saved gp registers.  */
                   3093:   unsigned long fmask;         /* Mask of saved fp registers.  */
                   3094: 
                   3095:   /* This is the size of the 16 word reg save area, 1 word struct addr
                   3096:      area, and 4 word fp/alu register copy area.  */
                   3097:   extra_size    = -STARTING_FRAME_OFFSET + FIRST_PARM_OFFSET(0);
                   3098:   var_size      = size;
                   3099:   /* Also include the size needed for the 6 parameter registers.  */
                   3100:   args_size     = current_function_outgoing_args_size + 24;
                   3101:   total_size    = var_size + args_size + extra_size;
                   3102:   gp_reg_size   = 0;
                   3103:   fp_reg_size   = 0;
                   3104:   mask          = 0;
                   3105:   fmask                 = 0;
                   3106: 
                   3107:   /* Calculate space needed for gp registers.  */
                   3108:   for (regno = 1; regno <= 31; regno++)
                   3109:     {
                   3110:       if (MUST_SAVE_REGISTER (regno))
                   3111:        {
                   3112:          if ((regno & 0x1) == 0 && MUST_SAVE_REGISTER (regno+1))
                   3113:            {
                   3114:              if (gp_reg_size % 8 != 0)
                   3115:                gp_reg_size += UNITS_PER_WORD;
                   3116:              gp_reg_size += 2 * UNITS_PER_WORD;
                   3117:              mask |= 3 << regno;
                   3118:              regno++;
                   3119:            }
                   3120:          else
                   3121:            {
                   3122:              gp_reg_size += UNITS_PER_WORD;
                   3123:              mask |= 1 << regno;
                   3124:            }
                   3125:        }
                   3126:     }
                   3127:   /* Add extra word in case we have to align the space to a double word
                   3128:      boundary.  */
                   3129:   if (gp_reg_size != 0)
                   3130:     gp_reg_size += UNITS_PER_WORD;
                   3131: 
                   3132:   /* Calculate space needed for fp registers.  */
                   3133:   for (regno = 32; regno <= 63; regno++)
                   3134:     {
                   3135:       if (regs_ever_live[regno] && !call_used_regs[regno])
                   3136:        {
                   3137:          fp_reg_size += UNITS_PER_WORD;
                   3138:          fmask |= 1 << (regno - 32);
                   3139:        }
                   3140:     }
                   3141: 
                   3142:   total_size += gp_reg_size + fp_reg_size;
                   3143: 
                   3144:   if (total_size == extra_size)
                   3145:     total_size = extra_size = 0;
                   3146: 
                   3147:   total_size = SPARC_STACK_ALIGN (total_size);
                   3148: 
                   3149:   /* Save other computed information.  */
                   3150:   current_frame_info.total_size  = total_size;
                   3151:   current_frame_info.var_size    = var_size;
                   3152:   current_frame_info.args_size   = args_size;
                   3153:   current_frame_info.extra_size  = extra_size;
                   3154:   current_frame_info.gp_reg_size = gp_reg_size;
                   3155:   current_frame_info.fp_reg_size = fp_reg_size;
                   3156:   current_frame_info.mask       = mask;
                   3157:   current_frame_info.fmask      = fmask;
                   3158:   current_frame_info.initialized = reload_completed;
                   3159: 
                   3160:   if (mask)
                   3161:     {
                   3162:       unsigned long offset = args_size;
                   3163:       if (extra_size)
                   3164:        offset += FIRST_PARM_OFFSET(0);
                   3165:       current_frame_info.gp_sp_offset = offset;
                   3166:     }
                   3167: 
                   3168:   if (fmask)
                   3169:     {
                   3170:       unsigned long offset = args_size + gp_reg_size;
                   3171:       if (extra_size)
                   3172:        offset += FIRST_PARM_OFFSET(0);
                   3173:       current_frame_info.fp_sp_offset = offset;
                   3174:     }
                   3175: 
                   3176:   /* Ok, we're done.  */
                   3177:   return total_size;
                   3178: }
                   3179: 
                   3180: /* Common code to save/restore registers.  */
                   3181: 
                   3182: void
                   3183: sparc_frw_save_restore (file, word_op, doubleword_op)
                   3184:      FILE *file;               /* Stream to write to.  */
                   3185:      char *word_op;            /* Operation to do for one word.  */
                   3186:      char *doubleword_op;      /* Operation to do for doubleword.  */
                   3187: {
                   3188:   int regno;
                   3189:   unsigned long mask     = current_frame_info.mask;
                   3190:   unsigned long fmask    = current_frame_info.fmask;
                   3191:   unsigned long gp_offset;
                   3192:   unsigned long fp_offset;
                   3193:   unsigned long max_offset;
                   3194:   char *base_reg;
                   3195: 
                   3196:   if (mask == 0 && fmask == 0)
                   3197:     return;
                   3198: 
                   3199:   base_reg   = reg_names[STACK_POINTER_REGNUM];
                   3200:   gp_offset  = current_frame_info.gp_sp_offset;
                   3201:   fp_offset  = current_frame_info.fp_sp_offset;
                   3202:   max_offset = (gp_offset > fp_offset) ? gp_offset : fp_offset;
                   3203: 
                   3204:   /* Deal with calling functions with a large structure.  */
                   3205:   if (max_offset >= 4096)
                   3206:     {
                   3207:       char *temp = "%g2";
                   3208:       fprintf (file, "\tset %ld,%s\n", max_offset, temp);
                   3209:       fprintf (file, "\tadd %s,%s,%s\n", temp, base_reg, temp);
                   3210:       base_reg = temp;
                   3211:       gp_offset = max_offset - gp_offset;
                   3212:       fp_offset = max_offset - fp_offset;
                   3213:     }
                   3214: 
                   3215:   /* Save registers starting from high to low.  The debuggers prefer
                   3216:      at least the return register be stored at func+4, and also it
                   3217:      allows us not to need a nop in the epilog if at least one
                   3218:      register is reloaded in addition to return address.  */
                   3219: 
                   3220:   if (mask || frame_pointer_needed)
                   3221:     {
                   3222:       for (regno = 1; regno <= 31; regno++)
                   3223:        {
                   3224:          if ((mask & (1L << regno)) != 0
                   3225:              || (regno == FRAME_POINTER_REGNUM && frame_pointer_needed))
                   3226:            {
                   3227:              if ((regno & 0x1) == 0 && ((mask & (1L << regno+1)) != 0))
                   3228:                {
                   3229:                  if (gp_offset % 8 != 0)
                   3230:                    gp_offset += UNITS_PER_WORD;
                   3231:                  
                   3232:                  if (word_op[0] == 's')
                   3233:                    fprintf (file, "\t%s %s,[%s+%d]\n",
                   3234:                             doubleword_op, reg_names[regno],
                   3235:                             base_reg, gp_offset);
                   3236:                  else
                   3237:                    fprintf (file, "\t%s [%s+%d],%s\n",
                   3238:                             doubleword_op, base_reg, gp_offset,
                   3239:                             reg_names[regno]);
                   3240: 
                   3241:                  gp_offset += 2 * UNITS_PER_WORD;
                   3242:                  regno++;
                   3243:                }
                   3244:              else
                   3245:                {
                   3246:                  if (word_op[0] == 's')
                   3247:                    fprintf (file, "\t%s %s,[%s+%d]\n",
                   3248:                             word_op, reg_names[regno],
                   3249:                             base_reg, gp_offset);
                   3250:                  else
                   3251:                    fprintf (file, "\t%s [%s+%d],%s\n",
                   3252:                             word_op, base_reg, gp_offset, reg_names[regno]);
                   3253: 
                   3254:                  gp_offset += UNITS_PER_WORD;
                   3255:                }
                   3256:            }
                   3257:        }
                   3258:     }
                   3259: 
                   3260:   if (fmask)
                   3261:     {
                   3262:       for (regno = 32; regno <= 63; regno++)
                   3263:        {
                   3264:          if ((fmask & (1L << (regno - 32))) != 0)
                   3265:            {
                   3266:              if (word_op[0] == 's')
                   3267:                fprintf (file, "\t%s %s,[%s+%d]\n",
                   3268:                         word_op, reg_names[regno],
                   3269:                         base_reg, gp_offset);
                   3270:              else
                   3271:                fprintf (file, "\t%s [%s+%d],%s\n",
                   3272:                         word_op, base_reg, gp_offset, reg_names[regno]);
                   3273: 
                   3274:              fp_offset += UNITS_PER_WORD;
                   3275:            }
                   3276:        }
                   3277:     }
                   3278: }
                   3279: 
                   3280: /* Set up the stack and frame (if desired) for the function.  */
                   3281: 
                   3282: void
                   3283: sparc_frw_output_function_prologue (file, size, ignored)
                   3284:      FILE *file;
                   3285:      int size;
                   3286: {
                   3287:   extern char call_used_regs[];
                   3288:   int tsize;
                   3289:   char *sp_str = reg_names[STACK_POINTER_REGNUM];
                   3290: 
                   3291:   /* ??? This should be %sp+actual_fsize for a leaf function.  I think it
                   3292:      works only because it is never used.  */
                   3293:   frame_base_name
                   3294:     = (!frame_pointer_needed) ? "%sp+80" : reg_names[FRAME_POINTER_REGNUM];
                   3295: 
                   3296:   fprintf (file, "\t!#PROLOGUE# 0\n");
                   3297: 
                   3298:   size = SPARC_STACK_ALIGN (size);
                   3299:   tsize = (! current_frame_info.initialized
                   3300:           ? sparc_frw_compute_frame_size (size)
                   3301:           : current_frame_info.total_size);
                   3302: 
                   3303:   if (tsize > 0)
                   3304:     {
                   3305:       if (tsize <= 4095)
                   3306:        fprintf (file,
                   3307:                 "\tsub %s,%d,%s\t\t!# vars= %d, regs= %d/%d, args = %d, extra= %d\n",
                   3308:                 sp_str, tsize, sp_str, current_frame_info.var_size,
                   3309:                 current_frame_info.gp_reg_size / 4,
                   3310:                 current_frame_info.fp_reg_size / 8,
                   3311:                 current_function_outgoing_args_size,
                   3312:                 current_frame_info.extra_size);
                   3313:       else
                   3314:        fprintf (file,
                   3315:                 "\tset %d,%s\n\tsub\t%s,%s,%s\t\t!# vars= %d, regs= %d/%d, args = %d, sfo= %d\n",
                   3316:                 tsize, "%g1", sp_str, "%g1",
                   3317:                 sp_str, current_frame_info.var_size,
                   3318:                 current_frame_info.gp_reg_size / 4,
                   3319:                 current_frame_info.fp_reg_size / 8,
                   3320:                 current_function_outgoing_args_size,
                   3321:                 current_frame_info.extra_size);
                   3322:     }
                   3323: 
                   3324:   sparc_frw_save_restore (file, "st", "std");
                   3325: 
                   3326:   if (frame_pointer_needed)
                   3327:     {
                   3328:       if (tsize <= 4095)
                   3329:        fprintf (file, "\tadd %s,%d,%s\t!# set up frame pointer\n", sp_str,
                   3330:                 tsize, frame_base_name);
                   3331:       else
                   3332:        fprintf (file, "\tadd %s,%s,%s\t!# set up frame pointer\n", sp_str,
                   3333:                 "%g1", frame_base_name);
                   3334:     }
                   3335: }
                   3336: 
                   3337: /* Do any necessary cleanup after a function to restore stack, frame,
                   3338:    and regs. */
                   3339: 
                   3340: void
                   3341: sparc_frw_output_function_epilogue (file, size, ignored1, ignored2)
                   3342:      FILE *file;
                   3343:      int size;
                   3344: {
                   3345:   extern FILE *asm_out_data_file, *asm_out_file;
                   3346:   extern char call_used_regs[];
                   3347:   extern int frame_pointer_needed;
                   3348:   int tsize;
                   3349:   char *sp_str = reg_names[STACK_POINTER_REGNUM];
                   3350:   char *t1_str = "%g1";
                   3351:   rtx epilogue_delay = current_function_epilogue_delay_list;
                   3352:   int noepilogue = FALSE;
                   3353: 
                   3354:   /* The epilogue does not depend on any registers, but the stack
                   3355:      registers, so we assume that if we have 1 pending nop, it can be
                   3356:      ignored, and 2 it must be filled (2 nops occur for integer
                   3357:      multiply and divide).  */
                   3358: 
                   3359:   size = SPARC_STACK_ALIGN (size);
                   3360:   tsize = (!current_frame_info.initialized
                   3361:           ? sparc_frw_compute_frame_size (size)
                   3362:           : current_frame_info.total_size);
                   3363: 
                   3364:   if (tsize == 0 && epilogue_delay == 0)
                   3365:     {
                   3366:       rtx insn = get_last_insn ();
                   3367: 
                   3368:       /* If the last insn was a BARRIER, we don't have to write any code
                   3369:         because a jump (aka return) was put there.  */
                   3370:       if (GET_CODE (insn) == NOTE)
                   3371:        insn = prev_nonnote_insn (insn);
                   3372:       if (insn && GET_CODE (insn) == BARRIER)
                   3373:        noepilogue = TRUE;
                   3374:     }
                   3375: 
                   3376:   if (!noepilogue)
                   3377:     {
                   3378:       /* In the reload sequence, we don't need to fill the load delay
                   3379:         slots for most of the loads, also see if we can fill the final
                   3380:         delay slot if not otherwise filled by the reload sequence.  */
                   3381: 
                   3382:       if (tsize > 4095)
                   3383:        fprintf (file, "\tset %d,%s\n", tsize, t1_str);
                   3384: 
                   3385:       if (frame_pointer_needed)
                   3386:        {
                   3387:          char *fp_str = reg_names[FRAME_POINTER_REGNUM];
                   3388:          if (tsize > 4095)
                   3389:            fprintf (file,"\tsub %s,%s,%s\t\t!# sp not trusted  here\n",
                   3390:                     fp_str, t1_str, sp_str);
                   3391:          else
                   3392:            fprintf (file,"\tsub %s,%d,%s\t\t!# sp not trusted  here\n",
                   3393:                     fp_str, tsize, sp_str);
                   3394:        }
                   3395: 
                   3396:       sparc_frw_save_restore (file, "ld", "ldd");
                   3397: 
                   3398:       if (current_function_returns_struct)
                   3399:        fprintf (file, "\tjmp %%o7+12\n");
                   3400:       else
                   3401:        fprintf (file, "\tretl\n");
                   3402: 
                   3403:       /* If the only register saved is the return address, we need a
                   3404:         nop, unless we have an instruction to put into it.  Otherwise
                   3405:         we don't since reloading multiple registers doesn't reference
                   3406:         the register being loaded.  */
                   3407: 
                   3408:       if (epilogue_delay)
                   3409:        {
                   3410:          if (tsize)
                   3411:            abort ();
                   3412:          final_scan_insn (XEXP (epilogue_delay, 0), file, 1, -2, 1);
                   3413:        }
                   3414: 
                   3415:       else if (tsize > 4095)
                   3416:        fprintf (file, "\tadd %s,%s,%s\n", sp_str, t1_str, sp_str);
                   3417: 
                   3418:       else if (tsize > 0)
                   3419:        fprintf (file, "\tadd %s,%d,%s\n", sp_str, tsize, sp_str);
                   3420: 
                   3421:       else
                   3422:        fprintf (file, "\tnop\n");
                   3423:     }
                   3424: 
                   3425:   /* Reset state info for each function.  */
                   3426:   current_frame_info = zero_frame_info;
                   3427: }
                   3428: 
                   3429: /* Define the number of delay slots needed for the function epilogue.
                   3430: 
                   3431:    On the sparc, we need a slot if either no stack has been allocated,
                   3432:    or the only register saved is the return register.  */
                   3433: 
                   3434: int
                   3435: sparc_frw_epilogue_delay_slots ()
                   3436: {
                   3437:   if (!current_frame_info.initialized)
                   3438:     (void) sparc_frw_compute_frame_size (get_frame_size ());
                   3439: 
                   3440:   if (current_frame_info.total_size == 0)
                   3441:     return 1;
                   3442: 
                   3443:   return 0;
                   3444: }
                   3445: 
                   3446: /* Return true is TRIAL is a valid insn for the epilogue delay slot.
                   3447:    Any single length instruction which doesn't reference the stack or frame
                   3448:    pointer is OK.  */
                   3449: 
                   3450: int
                   3451: sparc_frw_eligible_for_epilogue_delay (trial, slot)
                   3452:      rtx trial;
                   3453:      int slot;
                   3454: {
                   3455:   if (get_attr_length (trial) == 1
                   3456:       && ! reg_mentioned_p (stack_pointer_rtx, PATTERN (trial))
                   3457:       && ! reg_mentioned_p (frame_pointer_rtx, PATTERN (trial)))
                   3458:     return 1;
                   3459:   return 0;
                   3460: }

unix.superglobalmegacorp.com

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