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

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

unix.superglobalmegacorp.com

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