Annotation of GNUtools/cc/config/alpha/alpha.c, revision 1.1.1.1

1.1       root        1: /* Subroutines used for code generation on the DEC Alpha.
                      2:    Copyright (C) 1992, 1993 Free Software Foundation, Inc.
                      3:    Contributed by Richard Kenner ([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: 
                     22: #include <stdio.h>
                     23: #include "config.h"
                     24: #include "rtl.h"
                     25: #include "regs.h"
                     26: #include "hard-reg-set.h"
                     27: #include "real.h"
                     28: #include "insn-config.h"
                     29: #include "conditions.h"
                     30: #include "insn-flags.h"
                     31: #include "output.h"
                     32: #include "insn-attr.h"
                     33: #include "flags.h"
                     34: #include "recog.h"
                     35: #include "reload.h"
                     36: #include "expr.h"
                     37: #include "obstack.h"
                     38: #include "tree.h"
                     39: 
                     40: /* Save information from a "cmpxx" operation until the branch or scc is
                     41:    emitted.  */
                     42: 
                     43: rtx alpha_compare_op0, alpha_compare_op1;
                     44: int alpha_compare_fp_p;
                     45: 
                     46: /* Save the name of the current function as used by the assembler.  This
                     47:    is used by the epilogue.  */
                     48: 
                     49: char *alpha_function_name;
                     50: 
                     51: /* Non-zero if inside of a function, because the Alpha asm can't
                     52:    handle .files inside of functions.  */
                     53: 
                     54: static int inside_function = FALSE;
                     55: 
                     56: /* Nonzero if the current function needs gp.  */
                     57: 
                     58: int alpha_function_needs_gp;
                     59: 
                     60: extern char *version_string;
                     61: 
                     62: /* Returns 1 if VALUE is a mask that contains full bytes of zero or ones.  */
                     63: 
                     64: int
                     65: zap_mask (value)
                     66:      HOST_WIDE_INT value;
                     67: {
                     68:   int i;
                     69: 
                     70:   for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR;
                     71:        i++, value >>= 8)
                     72:     if ((value & 0xff) != 0 && (value & 0xff) != 0xff)
                     73:       return 0;
                     74: 
                     75:   return 1;
                     76: }
                     77: 
                     78: /* Returns 1 if OP is either the constant zero or a register.  If a
                     79:    register, it must be in the proper mode unless MODE is VOIDmode.  */
                     80: 
                     81: int
                     82: reg_or_0_operand (op, mode)
                     83:       register rtx op;
                     84:       enum machine_mode mode;
                     85: {
                     86:   return op == const0_rtx || register_operand (op, mode);
                     87: }
                     88: 
                     89: /* Return 1 if OP is a constant in the range of 0-63 (for a shift) or
                     90:    any register.  */
                     91: 
                     92: int
                     93: reg_or_6bit_operand (op, mode)
                     94:      register rtx op;
                     95:      enum machine_mode mode;
                     96: {
                     97:   return ((GET_CODE (op) == CONST_INT
                     98:           && (unsigned HOST_WIDE_INT) INTVAL (op) < 64)
                     99:          || register_operand (op, mode));
                    100: }
                    101: 
                    102: 
                    103: /* Return 1 if OP is an 8-bit constant or any register.  */
                    104: 
                    105: int
                    106: reg_or_8bit_operand (op, mode)
                    107:      register rtx op;
                    108:      enum machine_mode mode;
                    109: {
                    110:   return ((GET_CODE (op) == CONST_INT
                    111:           && (unsigned HOST_WIDE_INT) INTVAL (op) < 0x100)
                    112:          || register_operand (op, mode));
                    113: }
                    114: 
                    115: /* Return 1 if the operand is a valid second operand to an add insn.  */
                    116: 
                    117: int
                    118: add_operand (op, mode)
                    119:      register rtx op;
                    120:      enum machine_mode mode;
                    121: {
                    122:   if (GET_CODE (op) == CONST_INT)
                    123:     return ((unsigned HOST_WIDE_INT) (INTVAL (op) + 0x8000) < 0x10000
                    124:            || ((INTVAL (op) & 0xffff) == 0
                    125:                && (INTVAL (op) >> 31 == -1
                    126:                    || INTVAL (op) >> 31 == 0)));
                    127: 
                    128:   return register_operand (op, mode);
                    129: }
                    130: 
                    131: /* Return 1 if the operand is a valid second operand to a sign-extending
                    132:    add insn.  */
                    133: 
                    134: int
                    135: sext_add_operand (op, mode)
                    136:      register rtx op;
                    137:      enum machine_mode mode;
                    138: {
                    139:   if (GET_CODE (op) == CONST_INT)
                    140:     return ((unsigned HOST_WIDE_INT) INTVAL (op) < 255
                    141:            || (unsigned HOST_WIDE_INT) (- INTVAL (op)) < 255);
                    142: 
                    143:   return register_operand (op, mode);
                    144: }
                    145: 
                    146: /* Return 1 if OP is the constant 4 or 8.  */
                    147: 
                    148: int
                    149: const48_operand (op, mode)
                    150:      register rtx op;
                    151:      enum machine_mode mode;
                    152: {
                    153:   return (GET_CODE (op) == CONST_INT
                    154:          && (INTVAL (op) == 4 || INTVAL (op) == 8));
                    155: }
                    156: 
                    157: /* Return 1 if OP is a valid first operand to an AND insn.  */
                    158: 
                    159: int
                    160: and_operand (op, mode)
                    161:      register rtx op;
                    162:      enum machine_mode mode;
                    163: {
                    164:   if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == VOIDmode)
                    165:     return (zap_mask (CONST_DOUBLE_LOW (op))
                    166:            && zap_mask (CONST_DOUBLE_HIGH (op)));
                    167: 
                    168:   if (GET_CODE (op) == CONST_INT)
                    169:     return ((unsigned HOST_WIDE_INT) INTVAL (op) < 0x100
                    170:            || (unsigned HOST_WIDE_INT) ~ INTVAL (op) < 0x100
                    171:            || zap_mask (INTVAL (op)));
                    172: 
                    173:   return register_operand (op, mode);
                    174: }
                    175: 
                    176: /* Return 1 if OP is a constant that is the width, in bits, of an integral
                    177:    mode smaller than DImode.  */
                    178: 
                    179: int
                    180: mode_width_operand (op, mode)
                    181:      register rtx op;
                    182:      enum machine_mode mode;
                    183: {
                    184:   return (GET_CODE (op) == CONST_INT
                    185:          && (INTVAL (op) == 8 || INTVAL (op) == 16 || INTVAL (op) == 32));
                    186: }
                    187: 
                    188: /* Return 1 if OP is a constant that is the width of an integral machine mode
                    189:    smaller than an integer.  */
                    190: 
                    191: int
                    192: mode_mask_operand (op, mode)
                    193:      register rtx op;
                    194:      enum machine_mode mode;
                    195: {
                    196: #if HOST_BITS_PER_WIDE_INT == 32
                    197:   if (GET_CODE (op) == CONST_DOUBLE)
                    198:     return CONST_DOUBLE_HIGH (op) == 0 && CONST_DOUBLE_LOW (op) == -1;
                    199: #endif
                    200: 
                    201:   if (GET_CODE (op) == CONST_INT)
                    202:     return (INTVAL (op) == 0xff
                    203:            || INTVAL (op) == 0xffff
                    204: #if HOST_BITS_PER_WIDE_INT == 64
                    205:            || INTVAL (op) == 0xffffffff
                    206: #endif
                    207:            );
                    208: }
                    209: 
                    210: /* Return 1 if OP is a multiple of 8 less than 64.  */
                    211: 
                    212: int
                    213: mul8_operand (op, mode)
                    214:      register rtx op;
                    215:      enum machine_mode mode;
                    216: {
                    217:   return (GET_CODE (op) == CONST_INT
                    218:          && (unsigned HOST_WIDE_INT) INTVAL (op) < 64
                    219:          && (INTVAL (op) & 7) == 0);
                    220: }
                    221: 
                    222: /* Return 1 if OP is the constant zero in floating-point.  */
                    223: 
                    224: int
                    225: fp0_operand (op, mode)
                    226:      register rtx op;
                    227:      enum machine_mode mode;
                    228: {
                    229:   return (GET_MODE (op) == mode
                    230:          && GET_MODE_CLASS (mode) == MODE_FLOAT && op == CONST0_RTX (mode));
                    231: }
                    232: 
                    233: /* Return 1 if OP is the floating-point constant zero or a register.  */
                    234: 
                    235: int
                    236: reg_or_fp0_operand (op, mode)
                    237:      register rtx op;
                    238:      enum machine_mode mode;
                    239: {
                    240:   return fp0_operand (op, mode) || register_operand (op, mode);
                    241: }
                    242: 
                    243: /* Return 1 if OP is a register or a constant integer.  */
                    244: 
                    245: 
                    246: int
                    247: reg_or_cint_operand (op, mode)
                    248:     register rtx op;
                    249:     enum machine_mode mode;
                    250: {
                    251:      return GET_CODE (op) == CONST_INT || register_operand (op, mode);
                    252: }
                    253: 
                    254: /* Return 1 if OP is a valid operand for the source of a move insn.  */
                    255: 
                    256: int
                    257: input_operand (op, mode)
                    258:      register rtx op;
                    259:      enum machine_mode mode;
                    260: {
                    261:   if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
                    262:     return 0;
                    263: 
                    264:   if (GET_MODE_CLASS (mode) == MODE_FLOAT && GET_MODE (op) != mode)
                    265:     return 0;
                    266: 
                    267:   switch (GET_CODE (op))
                    268:     {
                    269:     case LABEL_REF:
                    270:     case SYMBOL_REF:
                    271:     case CONST:
                    272:       return mode == DImode;
                    273: 
                    274:     case REG:
                    275:       return 1;
                    276: 
                    277:     case SUBREG:
                    278:       if (register_operand (op, mode))
                    279:        return 1;
                    280:       /* ... fall through ... */
                    281:     case MEM:
                    282:       return mode != HImode && mode != QImode && general_operand (op, mode);
                    283: 
                    284:     case CONST_DOUBLE:
                    285:       return GET_MODE_CLASS (mode) == MODE_FLOAT && op == CONST0_RTX (mode);
                    286: 
                    287:     case CONST_INT:
                    288:       return mode == QImode || mode == HImode || add_operand (op, mode);
                    289:     }
                    290: 
                    291:   return 0;
                    292: }
                    293: 
                    294: /* Return 1 if OP is a SYMBOL_REF for a function known to be in this
                    295:    file.  */
                    296: 
                    297: int
                    298: current_file_function_operand (op, mode)
                    299:      rtx op;
                    300:      enum machine_mode mode;
                    301: {
                    302:   return (GET_CODE (op) == SYMBOL_REF
                    303:          && (SYMBOL_REF_FLAG (op)
                    304:              || op == XEXP (DECL_RTL (current_function_decl), 0)));
                    305: }
                    306: 
                    307: /* Return 1 if OP is a valid Alpha comparison operator.  Here we know which
                    308:    comparisons are valid in which insn.  */
                    309: 
                    310: int
                    311: alpha_comparison_operator (op, mode)
                    312:      register rtx op;
                    313:      enum machine_mode mode;
                    314: {
                    315:   enum rtx_code code = GET_CODE (op);
                    316: 
                    317:   if (mode != GET_MODE (op) || GET_RTX_CLASS (code) != '<')
                    318:     return 0;
                    319: 
                    320:   return (code == EQ || code == LE || code == LT
                    321:          || (mode == DImode && (code == LEU || code == LTU)));
                    322: }
                    323: 
                    324: /* Return 1 if OP is a signed comparison operation.  */
                    325: 
                    326: int
                    327: signed_comparison_operator (op, mode)
                    328:      register rtx op;
                    329:      enum machine_mode mode;
                    330: {
                    331:   switch (GET_CODE (op))
                    332:     {
                    333:     case EQ:  case NE:  case LE:  case LT:  case GE:   case GT:
                    334:       return 1;
                    335:     }
                    336: 
                    337:   return 0;
                    338: }
                    339: 
                    340: /* Return 1 if this is a divide or modulus operator.  */
                    341: 
                    342: int
                    343: divmod_operator (op, mode)
                    344:      register rtx op;
                    345:      enum machine_mode mode;
                    346: {
                    347:   switch (GET_CODE (op))
                    348:     {
                    349:     case DIV:  case MOD:  case UDIV:  case UMOD:
                    350:       return 1;
                    351:     }
                    352: 
                    353:   return 0;
                    354: }
                    355: 
                    356: /* Return 1 if this memory address is a known aligned register plus
                    357:    a constant.  It must be a valid address.  This means that we can do
                    358:    this as an aligned reference plus some offset.
                    359: 
                    360:    Take into account what reload will do.
                    361: 
                    362:    We could say that out-of-range stack slots are alignable, but that would
                    363:    complicate get_aligned_mem and it isn't worth the trouble since few
                    364:    functions have large stack space.  */
                    365: 
                    366: int
                    367: aligned_memory_operand (op, mode)
                    368:      register rtx op;
                    369:      enum machine_mode mode;
                    370: {
                    371:   if (GET_CODE (op) == SUBREG)
                    372:     {
                    373:       if (GET_MODE (op) != mode)
                    374:        return 0;
                    375:       op = SUBREG_REG (op);
                    376:       mode = GET_MODE (op);
                    377:     }
                    378: 
                    379:   if (reload_in_progress && GET_CODE (op) == REG
                    380:       && REGNO (op) >= FIRST_PSEUDO_REGISTER)
                    381:     op = reg_equiv_mem[REGNO (op)];
                    382: 
                    383:   if (GET_CODE (op) != MEM || GET_MODE (op) != mode
                    384:       || ! memory_address_p (mode, XEXP (op, 0)))
                    385:     return 0;
                    386: 
                    387:   op = XEXP (op, 0);
                    388: 
                    389:   if (GET_CODE (op) == PLUS)
                    390:     op = XEXP (op, 0);
                    391: 
                    392:   return (GET_CODE (op) == REG
                    393:          && (REGNO (op) == STACK_POINTER_REGNUM || op == frame_pointer_rtx
                    394:              || (REGNO (op) >= FIRST_VIRTUAL_REGISTER
                    395:                  && REGNO (op) <= LAST_VIRTUAL_REGISTER)));
                    396: }
                    397: 
                    398: /* Similar, but return 1 if OP is a MEM which is not alignable.  */
                    399: 
                    400: int
                    401: unaligned_memory_operand (op, mode)
                    402:      register rtx op;
                    403:      enum machine_mode mode;
                    404: {
                    405:   if (GET_CODE (op) == SUBREG)
                    406:     {
                    407:       if (GET_MODE (op) != mode)
                    408:        return 0;
                    409:       op = SUBREG_REG (op);
                    410:       mode = GET_MODE (op);
                    411:     }
                    412: 
                    413:   if (reload_in_progress && GET_CODE (op) == REG
                    414:       && REGNO (op) >= FIRST_PSEUDO_REGISTER)
                    415:     op = reg_equiv_mem[REGNO (op)];
                    416: 
                    417:   if (GET_CODE (op) != MEM || GET_MODE (op) != mode)
                    418:     return 0;
                    419: 
                    420:   op = XEXP (op, 0);
                    421: 
                    422:   if (! memory_address_p (mode, op))
                    423:     return 1;
                    424: 
                    425:   if (GET_CODE (op) == PLUS)
                    426:     op = XEXP (op, 0);
                    427: 
                    428:   return (GET_CODE (op) != REG
                    429:          || (REGNO (op) != STACK_POINTER_REGNUM && op != frame_pointer_rtx
                    430:              && (REGNO (op) < FIRST_VIRTUAL_REGISTER
                    431:                  || REGNO (op) > LAST_VIRTUAL_REGISTER)));
                    432: }
                    433: 
                    434: /* Return 1 if OP is any memory location.  During reload a pseudo matches.  */
                    435: 
                    436: int
                    437: any_memory_operand (op, mode)
                    438:      register rtx op;
                    439:      enum machine_mode mode;
                    440: {
                    441:   return (GET_CODE (op) == MEM
                    442:          || (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG)
                    443:          || (reload_in_progress && GET_CODE (op) == REG
                    444:              && REGNO (op) >= FIRST_PSEUDO_REGISTER)
                    445:          || (reload_in_progress && GET_CODE (op) == SUBREG
                    446:              && GET_CODE (SUBREG_REG (op)) == REG
                    447:              && REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER));
                    448: }
                    449: 
                    450: /* REF is an alignable memory location.  Place an aligned SImode
                    451:    reference into *PALIGNED_MEM and the number of bits to shift into
                    452:    *PBITNUM.  */
                    453: 
                    454: void
                    455: get_aligned_mem (ref, paligned_mem, pbitnum)
                    456:      rtx ref;
                    457:      rtx *paligned_mem, *pbitnum;
                    458: {
                    459:   rtx base;
                    460:   HOST_WIDE_INT offset = 0;
                    461: 
                    462:   if (GET_CODE (ref) == SUBREG)
                    463:     {
                    464:       offset = SUBREG_WORD (ref) * UNITS_PER_WORD;
                    465:       if (BYTES_BIG_ENDIAN)
                    466:        offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (ref)))
                    467:                   - MIN (UNITS_PER_WORD,
                    468:                          GET_MODE_SIZE (GET_MODE (SUBREG_REG (ref)))));
                    469:       ref = SUBREG_REG (ref);
                    470:     }
                    471: 
                    472:   if (GET_CODE (ref) == REG)
                    473:     ref = reg_equiv_mem[REGNO (ref)];
                    474: 
                    475:   if (reload_in_progress)
                    476:     base = find_replacement (&XEXP (ref, 0));
                    477:   else
                    478:     base = XEXP (ref, 0);
                    479: 
                    480:   if (GET_CODE (base) == PLUS)
                    481:     offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0);
                    482: 
                    483:   *paligned_mem = gen_rtx (MEM, SImode,
                    484:                           plus_constant (base, offset & ~3));
                    485:   MEM_IN_STRUCT_P (*paligned_mem) = MEM_IN_STRUCT_P (ref);
                    486:   MEM_VOLATILE_P (*paligned_mem) = MEM_VOLATILE_P (ref);
                    487:   RTX_UNCHANGING_P (*paligned_mem) = RTX_UNCHANGING_P (ref);
                    488: 
                    489:   *pbitnum = GEN_INT ((offset & 3) * 8);
                    490: }
                    491: 
                    492: /* Similar, but just get the address.  Handle the two reload cases.  */
                    493: 
                    494: rtx
                    495: get_unaligned_address (ref)
                    496:      rtx ref;
                    497: {
                    498:   rtx base;
                    499:   HOST_WIDE_INT offset = 0;
                    500: 
                    501:   if (GET_CODE (ref) == SUBREG)
                    502:     {
                    503:       offset = SUBREG_WORD (ref) * UNITS_PER_WORD;
                    504:       if (BYTES_BIG_ENDIAN)
                    505:        offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (ref)))
                    506:                   - MIN (UNITS_PER_WORD,
                    507:                          GET_MODE_SIZE (GET_MODE (SUBREG_REG (ref)))));
                    508:       ref = SUBREG_REG (ref);
                    509:     }
                    510: 
                    511:   if (GET_CODE (ref) == REG)
                    512:     ref = reg_equiv_mem[REGNO (ref)];
                    513: 
                    514:   if (reload_in_progress)
                    515:     base = find_replacement (&XEXP (ref, 0));
                    516:   else
                    517:     base = XEXP (ref, 0);
                    518: 
                    519:   if (GET_CODE (base) == PLUS)
                    520:     offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0);
                    521: 
                    522:   return plus_constant (base, offset);
                    523: }
                    524: 
                    525: /* Subfunction of the following function.  Update the flags of any MEM
                    526:    found in part of X.  */
                    527: 
                    528: static void
                    529: alpha_set_memflags_1 (x, in_struct_p, volatile_p, unchanging_p)
                    530:      rtx x;
                    531:      int in_struct_p, volatile_p, unchanging_p;
                    532: {
                    533:   int i;
                    534: 
                    535:   switch (GET_CODE (x))
                    536:     {
                    537:     case SEQUENCE:
                    538:     case PARALLEL:
                    539:       for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
                    540:        alpha_set_memflags_1 (XVECEXP (x, 0, i), in_struct_p, volatile_p,
                    541:                              unchanging_p);
                    542:       break;
                    543: 
                    544:     case INSN:
                    545:       alpha_set_memflags_1 (PATTERN (x), in_struct_p, volatile_p,
                    546:                            unchanging_p);
                    547:       break;
                    548: 
                    549:     case SET:
                    550:       alpha_set_memflags_1 (SET_DEST (x), in_struct_p, volatile_p,
                    551:                            unchanging_p);
                    552:       alpha_set_memflags_1 (SET_SRC (x), in_struct_p, volatile_p,
                    553:                            unchanging_p);
                    554:       break;
                    555: 
                    556:     case MEM:
                    557:       MEM_IN_STRUCT_P (x) = in_struct_p;
                    558:       MEM_VOLATILE_P (x) = volatile_p;
                    559:       RTX_UNCHANGING_P (x) = unchanging_p;
                    560:       break;
                    561:     }
                    562: }
                    563: 
                    564: /* Given INSN, which is either an INSN or a SEQUENCE generated to
                    565:    perform a memory operation, look for any MEMs in either a SET_DEST or
                    566:    a SET_SRC and copy the in-struct, unchanging, and volatile flags from
                    567:    REF into each of the MEMs found.  If REF is not a MEM, don't do
                    568:    anything.  */
                    569: 
                    570: void
                    571: alpha_set_memflags (insn, ref)
                    572:      rtx insn;
                    573:      rtx ref;
                    574: {
                    575:   /* Note that it is always safe to get these flags, though they won't
                    576:      be what we think if REF is not a MEM.  */
                    577:   int in_struct_p = MEM_IN_STRUCT_P (ref);
                    578:   int volatile_p = MEM_VOLATILE_P (ref);
                    579:   int unchanging_p = RTX_UNCHANGING_P (ref);
                    580: 
                    581:   if (GET_CODE (ref) != MEM
                    582:       || (! in_struct_p && ! volatile_p && ! unchanging_p))
                    583:     return;
                    584: 
                    585:   alpha_set_memflags_1 (insn, in_struct_p, volatile_p, unchanging_p);
                    586: }
                    587: 
                    588: /* Try to output insns to set TARGET equal to the constant C if it can be
                    589:    done in less than N insns.  Returns 1 if it can be done and the
                    590:    insns have been emitted.  If it would take more than N insns, zero is
                    591:    returned and no insns and emitted.  */
                    592: 
                    593: int
                    594: alpha_emit_set_const (target, c, n)
                    595:      rtx target;
                    596:      HOST_WIDE_INT c;
                    597:      int n;
                    598: {
                    599:   HOST_WIDE_INT new = c;
                    600:   int i, bits;
                    601: 
                    602: #if HOST_BITS_PER_WIDE_INT == 64
                    603:   /* We are only called for SImode and DImode.  If this is SImode, ensure that
                    604:      we are sign extended to a full word.  This does not make any sense when
                    605:      cross-compiling on a narrow machine.  */
                    606: 
                    607:   if (GET_MODE (target) == SImode)
                    608:     c = (c & 0xffffffff) - 2 * (c & 0x80000000);
                    609: #endif
                    610: 
                    611:   /* If this is a sign-extended 32-bit constant, we can do this in at most
                    612:      three insns, so do it if we have enough insns left.  We always have
                    613:      a sign-extended 32-bit constant when compiling on a narrow machine.  */
                    614: 
                    615:   if (HOST_BITS_PER_WIDE_INT != 64
                    616:       || c >> 31 == -1 || c >> 31 == 0)
                    617:     {
                    618:       HOST_WIDE_INT low = (c & 0xffff) - 2 * (c & 0x8000);
                    619:       HOST_WIDE_INT tmp1 = c - low;
                    620:       HOST_WIDE_INT high
                    621:        = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000);
                    622:       HOST_WIDE_INT extra = 0;
                    623: 
                    624:       /* If HIGH will be interpreted as negative but the constant is
                    625:         positive, we must adjust it to do two ldha insns.  */
                    626: 
                    627:       if ((high & 0x8000) != 0 && c >= 0)
                    628:        {
                    629:          extra = 0x4000;
                    630:          tmp1 -= 0x40000000;
                    631:          high = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000);
                    632:        }
                    633: 
                    634:       if (c == low || (low == 0 && extra == 0))
                    635:        {
                    636:          emit_move_insn (target, GEN_INT (c));
                    637:          return 1;
                    638:        }
                    639:       else if (n >= 2 + (extra != 0))
                    640:        {
                    641:          emit_move_insn (target, GEN_INT (low));
                    642:          if (extra != 0)
                    643:            emit_insn (gen_add2_insn (target, GEN_INT (extra << 16)));
                    644: 
                    645:          emit_insn (gen_add2_insn (target, GEN_INT (high << 16)));
                    646:          return 1;
                    647:        }
                    648:     }
                    649: 
                    650:   /* If we couldn't do it that way, try some other methods (that depend on
                    651:      being able to compute in the target's word size).  But if we have no
                    652:      instructions left, don't bother.  Also, don't even try if this is 
                    653:      SImode (in which case we should have already done something, but
                    654:      do a sanity check here).  */
                    655: 
                    656:   if (n == 1 || HOST_BITS_PER_WIDE_INT < 64 || GET_MODE (target) != DImode)
                    657:     return 0;
                    658: 
                    659:   /* First, see if can load a value into the target that is the same as the
                    660:      constant except that all bytes that are 0 are changed to be 0xff.  If we
                    661:      can, then we can do a ZAPNOT to obtain the desired constant.  */
                    662: 
                    663:   for (i = 0; i < 64; i += 8)
                    664:     if ((new & ((HOST_WIDE_INT) 0xff << i)) == 0)
                    665:       new |= (HOST_WIDE_INT) 0xff << i;
                    666: 
                    667:   if (alpha_emit_set_const (target, new, n - 1))
                    668:     {
                    669:       emit_insn (gen_anddi3 (target, target, GEN_INT (c | ~ new)));
                    670:       return 1;
                    671:     }
                    672: 
                    673:   /* Find, see if we can load a related constant and then shift and possibly
                    674:      negate it to get the constant we want.  Try this once each increasing
                    675:      numbers of insns.  */
                    676: 
                    677:   for (i = 1; i < n; i++)
                    678:     {
                    679:       /* First try complementing.  */
                    680:       if (alpha_emit_set_const (target, ~ c, i))
                    681:        {
                    682:          emit_insn (gen_one_cmpldi2 (target, target));
                    683:          return 1;
                    684:        }
                    685: 
                    686:       /* First try to form a constant and do a left shift.  We can do this
                    687:         if some low-order bits are zero; the exact_log2 call below tells
                    688:         us that information.  The bits we are shifting out could be any
                    689:         value, but here we'll just try the 0- and sign-extended forms of
                    690:         the constant.  To try to increase the chance of having the same
                    691:         constant in more than one insn, start at the highest number of
                    692:         bits to shift, but try all possibilities in case a ZAPNOT will
                    693:         be useful.  */
                    694: 
                    695:       if ((bits = exact_log2 (c & - c)) > 0)
                    696:        for (; bits > 0; bits--)
                    697:          if (alpha_emit_set_const (target, c >> bits, i)
                    698:              || alpha_emit_set_const (target,
                    699:                                       ((unsigned HOST_WIDE_INT) c) >> bits,
                    700:                                       i))
                    701:            {
                    702:              emit_insn (gen_ashldi3 (target, target, GEN_INT (bits)));
                    703:              return 1;
                    704:            }
                    705: 
                    706:       /* Now try high-order zero bits.  Here we try the shifted-in bits as
                    707:         all zero and all ones.  */
                    708: 
                    709:       if ((bits = HOST_BITS_PER_WIDE_INT - floor_log2 (c) - 1) > 0)
                    710:        for (; bits > 0; bits--)
                    711:          if (alpha_emit_set_const (target, c << bits, i)
                    712:              || alpha_emit_set_const (target,
                    713:                                       ((c << bits)
                    714:                                        | (((HOST_WIDE_INT) 1 << bits) - 1)),
                    715:                                       i))
                    716:            {
                    717:              emit_insn (gen_lshrdi3 (target, target, GEN_INT (bits)));
                    718:              return 1;
                    719:            }
                    720: 
                    721:       /* Now try high-order 1 bits.  We get that with a sign-extension.
                    722:         But one bit isn't enough here.  */
                    723:       
                    724:       if ((bits = HOST_BITS_PER_WIDE_INT - floor_log2 (~ c) - 2) > 0)
                    725:        for (; bits > 0; bits--)
                    726:          if (alpha_emit_set_const (target, c << bits, i)
                    727:              || alpha_emit_set_const (target,
                    728:                                       ((c << bits)
                    729:                                        | (((HOST_WIDE_INT) 1 << bits) - 1)),
                    730:                                       i))
                    731:            {
                    732:              emit_insn (gen_ashrdi3 (target, target, GEN_INT (bits)));
                    733:              return 1;
                    734:            }
                    735:     }
                    736: 
                    737:   return 0;
                    738: }
                    739: 
                    740: /* Adjust the cost of a scheduling dependency.  Return the new cost of
                    741:    a dependency LINK or INSN on DEP_INSN.  COST is the current cost.  */
                    742: 
                    743: int
                    744: alpha_adjust_cost (insn, link, dep_insn, cost)
                    745:      rtx insn;
                    746:      rtx link;
                    747:      rtx dep_insn;
                    748:      int cost;
                    749: {
                    750:   rtx set;
                    751: 
                    752:   /* If the dependence is an anti-dependence, there is no cost.  For an
                    753:      output dependence, there is sometimes a cost, but it doesn't seem
                    754:      worth handling those few cases.  */
                    755: 
                    756:   if (REG_NOTE_KIND (link) != 0)
                    757:     return 0;
                    758: 
                    759:   /* If INSN is a store insn and DEP_INSN is setting the data being stored,
                    760:      we can sometimes lower the cost.  */
                    761: 
                    762:   if (recog_memoized (insn) >= 0 && get_attr_type (insn) == TYPE_ST
                    763:       && (set = single_set (dep_insn)) != 0
                    764:       && GET_CODE (PATTERN (insn)) == SET
                    765:       && rtx_equal_p (SET_DEST (set), SET_SRC (PATTERN (insn))))
                    766:     switch (get_attr_type (dep_insn))
                    767:       {
                    768:       case TYPE_LD:
                    769:        /* No savings here.  */
                    770:        return cost;
                    771: 
                    772:       case TYPE_IMULL:
                    773:       case TYPE_IMULQ:
                    774:        /* In these cases, we save one cycle.  */
                    775:        return cost - 2;
                    776: 
                    777:       default:
                    778:        /* In all other cases, we save two cycles.  */
                    779:        return MAX (0, cost - 4);
                    780:       }
                    781: 
                    782:   /* Another case that needs adjustment is an arithmetic or logical
                    783:      operation.  It's cost is usually one cycle, but we default it to
                    784:      two in the MD file.  The only case that it is actually two is
                    785:      for the address in loads and stores.  */
                    786: 
                    787:   if (recog_memoized (dep_insn) >= 0
                    788:       && get_attr_type (dep_insn) == TYPE_IADDLOG)
                    789:     switch (get_attr_type (insn))
                    790:       {
                    791:       case TYPE_LD:
                    792:       case TYPE_ST:
                    793:        return cost;
                    794: 
                    795:       default:
                    796:        return 2;
                    797:       }
                    798: 
                    799:   /* The final case is when a compare feeds into an integer branch.  The cost
                    800:      is only one cycle in that case.  */
                    801: 
                    802:   if (recog_memoized (dep_insn) >= 0
                    803:       && get_attr_type (dep_insn) == TYPE_ICMP
                    804:       && recog_memoized (insn) >= 0
                    805:       && get_attr_type (insn) == TYPE_IBR)
                    806:     return 2;
                    807: 
                    808:   /* Otherwise, return the default cost. */
                    809: 
                    810:   return cost;
                    811: }
                    812: 
                    813: /* Print an operand.  Recognize special options, documented below.  */
                    814: 
                    815: void
                    816: print_operand (file, x, code)
                    817:     FILE *file;
                    818:     rtx x;
                    819:     char code;
                    820: {
                    821:   int i;
                    822: 
                    823:   switch (code)
                    824:     {
                    825:     case 'r':
                    826:       /* If this operand is the constant zero, write it as "$31".  */
                    827:       if (GET_CODE (x) == REG)
                    828:        fprintf (file, "%s", reg_names[REGNO (x)]);
                    829:       else if (x == CONST0_RTX (GET_MODE (x)))
                    830:        fprintf (file, "$31");
                    831:       else
                    832:        output_operand_lossage ("invalid %%r value");
                    833: 
                    834:       break;
                    835: 
                    836:     case 'R':
                    837:       /* Similar, but for floating-point.  */
                    838:       if (GET_CODE (x) == REG)
                    839:        fprintf (file, "%s", reg_names[REGNO (x)]);
                    840:       else if (x == CONST0_RTX (GET_MODE (x)))
                    841:        fprintf (file, "$f31");
                    842:       else
                    843:        output_operand_lossage ("invalid %%R value");
                    844: 
                    845:       break;
                    846: 
                    847:     case 'N':
                    848:       /* Write the 1's complement of a constant.  */
                    849:       if (GET_CODE (x) != CONST_INT)
                    850:        output_operand_lossage ("invalid %%N value");
                    851: 
                    852:       fprintf (file, "%ld", ~ INTVAL (x));
                    853:       break;
                    854: 
                    855:     case 'P':
                    856:       /* Write 1 << C, for a constant C.  */
                    857:       if (GET_CODE (x) != CONST_INT)
                    858:        output_operand_lossage ("invalid %%P value");
                    859: 
                    860:       fprintf (file, "%ld", (HOST_WIDE_INT) 1 << INTVAL (x));
                    861:       break;
                    862: 
                    863:     case 'h':
                    864:       /* Write the high-order 16 bits of a constant, sign-extended.  */
                    865:       if (GET_CODE (x) != CONST_INT)
                    866:        output_operand_lossage ("invalid %%h value");
                    867: 
                    868:       fprintf (file, "%ld", INTVAL (x) >> 16);
                    869:       break;
                    870: 
                    871:     case 'L':
                    872:       /* Write the low-order 16 bits of a constant, sign-extended.  */
                    873:       if (GET_CODE (x) != CONST_INT)
                    874:        output_operand_lossage ("invalid %%L value");
                    875: 
                    876:       fprintf (file, "%ld", (INTVAL (x) & 0xffff) - 2 * (INTVAL (x) & 0x8000));
                    877:       break;
                    878: 
                    879:     case 'm':
                    880:       /* Write mask for ZAP insn.  */
                    881:       if (GET_CODE (x) == CONST_DOUBLE)
                    882:        {
                    883:          HOST_WIDE_INT mask = 0;
                    884:          HOST_WIDE_INT value;
                    885: 
                    886:          value = CONST_DOUBLE_LOW (x);
                    887:          for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR;
                    888:               i++, value >>= 8)
                    889:            if (value & 0xff)
                    890:              mask |= (1 << i);
                    891: 
                    892:          value = CONST_DOUBLE_HIGH (x);
                    893:          for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR;
                    894:               i++, value >>= 8)
                    895:            if (value & 0xff)
                    896:              mask |= (1 << (i + sizeof (int)));
                    897: 
                    898:          fprintf (file, "%ld", mask & 0xff);
                    899:        }
                    900: 
                    901:       else if (GET_CODE (x) == CONST_INT)
                    902:        {
                    903:          HOST_WIDE_INT mask = 0, value = INTVAL (x);
                    904: 
                    905:          for (i = 0; i < 8; i++, value >>= 8)
                    906:            if (value & 0xff)
                    907:              mask |= (1 << i);
                    908: 
                    909:          fprintf (file, "%ld", mask);
                    910:        }
                    911:       else
                    912:        output_operand_lossage ("invalid %%m value");
                    913:       break;
                    914: 
                    915:     case 'M':
                    916:       /* 'b', 'w', or 'l' as the value of the constant.  */
                    917:       if (GET_CODE (x) != CONST_INT
                    918:          || (INTVAL (x) != 8 && INTVAL (x) != 16 && INTVAL (x) != 32))
                    919:        output_operand_lossage ("invalid %%M value");
                    920: 
                    921:       fprintf (file, "%s",
                    922:               INTVAL (x) == 8 ? "b" : INTVAL (x) == 16 ? "w" : "l");
                    923:       break;
                    924: 
                    925:     case 'U':
                    926:       /* Similar, except do it from the mask.  */
                    927:       if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xff)
                    928:        fprintf (file, "b");
                    929:       else if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xffff)
                    930:        fprintf (file, "w");
                    931: #if HOST_BITS_PER_WIDE_INT == 32
                    932:       else if (GET_CODE (x) == CONST_DOUBLE
                    933:               && CONST_DOUBLE_HIGH (x) == 0
                    934:               && CONST_DOUBLE_LOW (x) == -1)
                    935:        fprintf (file, "l");
                    936: #else
                    937:       else if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xffffffff)
                    938:        fprintf (file, "l");
                    939: #endif
                    940:       else
                    941:        output_operand_lossage ("invalid %%U value");
                    942:       break;
                    943: 
                    944:     case 's':
                    945:       /* Write the constant value divided by 8.  */
                    946:       if (GET_CODE (x) != CONST_INT
                    947:          && (unsigned HOST_WIDE_INT) INTVAL (x) >= 64
                    948:          && (INTVAL (x) & 7) != 8)
                    949:        output_operand_lossage ("invalid %%s value");
                    950: 
                    951:       fprintf (file, "%ld", INTVAL (x) / 8);
                    952:       break;
                    953: 
                    954:     case 'S':
                    955:       /* Same, except compute (64 - c) / 8 */
                    956: 
                    957:       if (GET_CODE (x) != CONST_INT
                    958:          && (unsigned HOST_WIDE_INT) INTVAL (x) >= 64
                    959:          && (INTVAL (x) & 7) != 8)
                    960:        output_operand_lossage ("invalid %%s value");
                    961: 
                    962:       fprintf (file, "%ld", (64 - INTVAL (x)) / 8);
                    963:       break;
                    964: 
                    965:     case 'C':
                    966:       /* Write out comparison name.  */
                    967:       if (GET_RTX_CLASS (GET_CODE (x)) != '<')
                    968:        output_operand_lossage ("invalid %%C value");
                    969: 
                    970:       if (GET_CODE (x) == LEU)
                    971:        fprintf (file, "ule");
                    972:       else if (GET_CODE (x) == LTU)
                    973:        fprintf (file, "ult");
                    974:       else
                    975:        fprintf (file, "%s", GET_RTX_NAME (GET_CODE (x)));
                    976:       break;
                    977: 
                    978:     case 'D':
                    979:       /* Similar, but write reversed code.  We can't get an unsigned code
                    980:         here.  */
                    981:       if (GET_RTX_CLASS (GET_CODE (x)) != '<')
                    982:        output_operand_lossage ("invalid %%D value");
                    983: 
                    984:       fprintf (file, "%s", GET_RTX_NAME (reverse_condition (GET_CODE (x))));
                    985:       break;
                    986: 
                    987:     case 'E':
                    988:       /* Write the divide or modulus operator.  */
                    989:       switch (GET_CODE (x))
                    990:        {
                    991:        case DIV:
                    992:          fprintf (file, "div%s", GET_MODE (x) == SImode ? "l" : "q");
                    993:          break;
                    994:        case UDIV:
                    995:          fprintf (file, "div%su", GET_MODE (x) == SImode ? "l" : "q");
                    996:          break;
                    997:        case MOD:
                    998:          fprintf (file, "rem%s", GET_MODE (x) == SImode ? "l" : "q");
                    999:          break;
                   1000:        case UMOD:
                   1001:          fprintf (file, "rem%su", GET_MODE (x) == SImode ? "l" : "q");
                   1002:          break;
                   1003:        default:
                   1004:          output_operand_lossage ("invalid %%E value");
                   1005:          break;
                   1006:        }
                   1007:       break;
                   1008: 
                   1009:     case 'A':
                   1010:       /* Write "_u" for unaligned access.  */
                   1011:       if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == AND)
                   1012:        fprintf (file, "_u");
                   1013:       break;
                   1014: 
                   1015:     case 0:
                   1016:       if (GET_CODE (x) == REG)
                   1017:        fprintf (file, "%s", reg_names[REGNO (x)]);
                   1018:       else if (GET_CODE (x) == MEM)
                   1019:        output_address (XEXP (x, 0));
                   1020:       else
                   1021:        output_addr_const (file, x);
                   1022:       break;
                   1023: 
                   1024:     default:
                   1025:       output_operand_lossage ("invalid %%xn code");
                   1026:     }
                   1027: }
                   1028: 
                   1029: /* Do what is necessary for `va_start'.  The argument is ignored;
                   1030:    We look at the current function to determine if stdarg or varargs
                   1031:    is used and fill in an initial va_list.  A pointer to this constructor
                   1032:    is returned.  */
                   1033: 
                   1034: struct rtx_def *
                   1035: alpha_builtin_saveregs (arglist)
                   1036:      tree arglist;
                   1037: {
                   1038:   rtx block, addr, argsize;
                   1039:   tree fntype = TREE_TYPE (current_function_decl);
                   1040:   int stdarg = (TYPE_ARG_TYPES (fntype) != 0
                   1041:                && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
                   1042:                    != void_type_node));
                   1043: 
                   1044:   /* Compute the current position into the args, taking into account
                   1045:      both registers and memory.  */
                   1046: 
                   1047:   argsize = plus_constant (current_function_arg_offset_rtx,
                   1048:                           current_function_args_info * UNITS_PER_WORD);
                   1049: 
                   1050:   /* Allocate the va_list constructor */
                   1051:   block = assign_stack_local (BLKmode, 2 * UNITS_PER_WORD, BITS_PER_WORD);
                   1052:   RTX_UNCHANGING_P (block) = 1;
                   1053:   RTX_UNCHANGING_P (XEXP (block, 0)) = 1;
                   1054: 
                   1055:   /* Store the address of the first integer register in the
                   1056:      __va_base member.   */
                   1057: 
                   1058:   emit_move_insn (change_address (block, DImode, XEXP (block, 0)),
                   1059:                  force_operand (plus_constant (virtual_incoming_args_rtx,
                   1060:                                                6 * UNITS_PER_WORD),
                   1061:                                 NULL_RTX));
                   1062: 
                   1063:   /* Store the argsize as the __va_offset member.  */
                   1064:   emit_move_insn (change_address (block, Pmode,
                   1065:                                  plus_constant (XEXP (block, 0),
                   1066:                                                 UNITS_PER_WORD)),
                   1067:                  force_operand (argsize, NULL_RTX));
                   1068: 
                   1069:   /* Return the address of the va_list constructor, but don't put it in a
                   1070:      register.  Doing so would fail when not optimizing and produce worse
                   1071:      code when optimizing.  */
                   1072:   return XEXP (block, 0);
                   1073: }
                   1074: 
                   1075: /* This page contains routines that are used to determine what the function
                   1076:    prologue and epilogue code will do and write them out.  */
                   1077: 
                   1078: /* Compute the size of the save area in the stack.  */
                   1079: 
                   1080: int
                   1081: alpha_sa_size ()
                   1082: {
                   1083:   int size = 0;
                   1084:   int i;
                   1085: 
                   1086:   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
                   1087:     if (! fixed_regs[i] && ! call_used_regs[i] && regs_ever_live[i])
                   1088:       size++;
                   1089: 
                   1090:   /* If some registers were saved but not reg 26, reg 26 must also
                   1091:      be saved, so leave space for it.  */
                   1092:   if (size != 0 && ! regs_ever_live[26])
                   1093:     size++;
                   1094: 
                   1095:   return size * 8;
                   1096: }
                   1097: 
                   1098: /* Return 1 if this function can directly return via $26.  */
                   1099: 
                   1100: int
                   1101: direct_return ()
                   1102: {
                   1103:   return (reload_completed && alpha_sa_size () == 0
                   1104:          && get_frame_size () == 0
                   1105:          && current_function_pretend_args_size == 0);
                   1106: }
                   1107: 
                   1108: /* Write a version stamp.  Don't write anything if we are running as a
                   1109:    cross-compiler.  Otherwise, use the versions in /usr/include/stamp.h.  */
                   1110: 
                   1111: #ifndef CROSS_COMPILE
                   1112: #include <stamp.h>
                   1113: #endif
                   1114: 
                   1115: void
                   1116: alpha_write_verstamp (file)
                   1117:      FILE *file;
                   1118: {
                   1119: #ifdef MS_STAMP
                   1120:   char *p;
                   1121: 
                   1122:   fprintf (file, "\t.verstamp %d %d ", MS_STAMP, LS_STAMP);
                   1123:   for (p = version_string; *p != ' ' && *p != 0; p++)
                   1124:     fprintf (file, "%c", *p == '.' ? ' ' : *p);
                   1125:   fprintf (file, "\n");
                   1126: #endif
                   1127: }
                   1128: 
                   1129: /* Write code to add constant C to register number IN_REG (possibly 31)
                   1130:    and put the result into OUT_REG.  Write the code to FILE.  */
                   1131: 
                   1132: static void
                   1133: add_long_const (file, c, in_reg, out_reg)
                   1134:      HOST_WIDE_INT c;
                   1135:      int in_reg, out_reg;
                   1136:      FILE *file;
                   1137: {
                   1138:   HOST_WIDE_INT low = (c & 0xffff) - 2 * (c & 0x8000);
                   1139:   HOST_WIDE_INT tmp1 = c - low;
                   1140:   HOST_WIDE_INT high = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000);
                   1141:   HOST_WIDE_INT extra = 0;
                   1142: 
                   1143:   /* We don't have code to write out constants larger than 32 bits.  */
                   1144: #if HOST_BITS_PER_LONG_INT == 64
                   1145:   if ((unsigned HOST_WIDE_INT) c >> 32 != 0)
                   1146:     abort ();
                   1147: #endif
                   1148: 
                   1149:   /* If HIGH will be interpreted as negative, we must adjust it to do two
                   1150:      ldha insns.  Note that we will never be building a negative constant
                   1151:      here.  */
                   1152: 
                   1153:   if (high & 0x8000)
                   1154:     {
                   1155:       extra = 0x4000;
                   1156:       tmp1 -= 0x40000000;
                   1157:       high = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000);
                   1158:     }
                   1159: 
                   1160:   if (low != 0)
                   1161:     {
                   1162:       if (low >= 0 && low < 255)
                   1163:        fprintf (file, "\taddq $%d,%d,$%d\n", in_reg, low, out_reg);
                   1164:       else
                   1165:        fprintf (file, "\tlda $%d,%d($%d)\n", out_reg, low, in_reg);
                   1166:       in_reg = out_reg;
                   1167:     }
                   1168: 
                   1169:   if (extra)
                   1170:     {
                   1171:       fprintf (file, "\tldah $%d,%d($%d)\n", out_reg, extra, in_reg);
                   1172:       in_reg = out_reg;
                   1173:     }
                   1174: 
                   1175:   if (high)
                   1176:     fprintf (file, "\tldah $%d,%d($%d)\n", out_reg, high, in_reg);
                   1177: }
                   1178: 
                   1179: /* Write function prologue.  */
                   1180: 
                   1181: void
                   1182: output_prolog (file, size)
                   1183:      FILE *file;
                   1184:      int size;
                   1185: {
                   1186:   HOST_WIDE_INT frame_size = ((size + current_function_outgoing_args_size
                   1187:                               + current_function_pretend_args_size
                   1188:                               + alpha_sa_size () + 15) & ~15);
                   1189:   HOST_WIDE_INT reg_offset = size + current_function_outgoing_args_size;
                   1190:   HOST_WIDE_INT start_reg_offset = reg_offset;
                   1191:   HOST_WIDE_INT actual_start_reg_offset = start_reg_offset;
                   1192:   rtx insn;
                   1193:   int reg_offset_base_reg = 30;
                   1194:   unsigned reg_mask = 0;
                   1195:   int i;
                   1196: 
                   1197:   /* Ecoff can handle multiple .file directives, put out file and lineno.
                   1198:      We have to do that before the .ent directive as we cannot switch
                   1199:      files within procedures with native ecoff because line numbers are
                   1200:      linked to procedure descriptors.
                   1201:      Outputting the lineno helps debugging of one line functions as they
                   1202:      would otherwise get no line number at all. Please note that we would
                   1203:      like to put out last_linenum from final.c, but it is not accesible.  */
                   1204: 
                   1205:   if (write_symbols == SDB_DEBUG)
                   1206:     {
                   1207:       ASM_OUTPUT_SOURCE_FILENAME (file,
                   1208:                                  DECL_SOURCE_FILE (current_function_decl));
                   1209:       if (debug_info_level != DINFO_LEVEL_TERSE)
                   1210:         ASM_OUTPUT_SOURCE_LINE (file, DECL_SOURCE_LINE (current_function_decl));
                   1211:     }
                   1212: 
                   1213:   /* The assembly language programmer's guide states that the second argument
                   1214:      to the .ent directive, the lex_level, is ignored by the assembler,
                   1215:      so we might as well omit it.  */
                   1216:      
                   1217:   fprintf (file, "\t.ent %s\n", alpha_function_name);
                   1218:   ASM_OUTPUT_LABEL (file, alpha_function_name);
                   1219:   inside_function = TRUE;
                   1220: 
                   1221:   /* Set up offsets to alpha virtual arg/local debugging pointer.  */
                   1222: 
                   1223:   alpha_auto_offset = -frame_size + current_function_pretend_args_size;
                   1224:   alpha_arg_offset = -frame_size + 48;
                   1225: 
                   1226:   /* If we need a GP (we have a LDSYM insn or a CALL_INSN), load it first. 
                   1227:      Even if we are a static function, we still need to do this in case
                   1228:      our address is taken and passed to something like qsort.  */
                   1229: 
                   1230:   alpha_function_needs_gp = 0;
                   1231:   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
                   1232:     if ((GET_CODE (insn) == CALL_INSN)
                   1233:        || (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
                   1234:            && GET_CODE (PATTERN (insn)) != USE
                   1235:            && GET_CODE (PATTERN (insn)) != CLOBBER
                   1236:            && (get_attr_type (insn) == TYPE_LDSYM
                   1237:                || get_attr_type (insn) == TYPE_ISUBR)))
                   1238:       {
                   1239:        alpha_function_needs_gp = 1;
                   1240:        break;
                   1241:       }
                   1242: 
                   1243:   if (alpha_function_needs_gp)
                   1244:     fprintf (file, "\tldgp $29,0($27)\n");
                   1245: 
                   1246:   /* Put a label after the GP load so we can enter the function at it.  */
                   1247:   fprintf (file, "%s..ng:\n", alpha_function_name);
                   1248: 
                   1249:   /* Adjust the stack by the frame size.  If the frame size is > 4096
                   1250:      bytes, we need to be sure we probe somewhere in the first and last
                   1251:      4096 bytes (we can probably get away without the latter test) and
                   1252:      every 8192 bytes in between.  If the frame size is > 32768, we
                   1253:      do this in a loop.  Otherwise, we generate the explicit probe
                   1254:      instructions. 
                   1255: 
                   1256:      Note that we are only allowed to adjust sp once in the prologue.  */
                   1257: 
                   1258:   if (frame_size < 32768)
                   1259:     {
                   1260:       if (frame_size > 4096)
                   1261:        {
                   1262:          int probed = 4096;
                   1263:          int regnum = 2;
                   1264: 
                   1265:          fprintf (file, "\tldq $%d,-%d($30)\n", regnum++, probed);
                   1266: 
                   1267:          while (probed + 8192 < frame_size)
                   1268:            fprintf (file, "\tldq $%d,-%d($30)\n", regnum++, probed += 8192);
                   1269: 
                   1270:          if (probed + 4096 < frame_size)
                   1271:            fprintf (file, "\tldq $%d,-%d($30)\n", regnum++, probed += 4096);
                   1272: 
                   1273:          if (regnum > 9)
                   1274:            abort ();
                   1275:        }
                   1276: 
                   1277:       if (frame_size != 0)
                   1278:        fprintf (file, "\tlda $30,-%d($30)\n", frame_size);
                   1279:     }
                   1280:   else
                   1281:     {
                   1282:       /* Here we generate code to set R4 to SP + 4096 and set R5 to the
                   1283:         number of 8192 byte blocks to probe.  We then probe each block
                   1284:         in the loop and then set SP to the proper location.  If the
                   1285:         amount remaining is > 4096, we have to do one more probe.  */
                   1286: 
                   1287:       HOST_WIDE_INT blocks = (frame_size + 4096) / 8192;
                   1288:       HOST_WIDE_INT leftover = frame_size + 4096 - blocks * 8192;
                   1289: 
                   1290:       add_long_const (file, blocks, 31, 5);
                   1291: 
                   1292:       fprintf (file, "\tlda $4,4096($30)\n");
                   1293:       fprintf (file, "%s..sc:\n", alpha_function_name);
                   1294:       fprintf (file, "\tldq $6,-8192($4)\n");
                   1295:       fprintf (file, "\tsubq $5,1,$5\n");
                   1296:       fprintf (file, "\tlda $4,-8192($4)\n");
                   1297:       fprintf (file, "\tbne $5,%s..sc\n", alpha_function_name);
                   1298:       fprintf (file, "\tlda $30,-%d($4)\n", leftover);
                   1299: 
                   1300:       if (leftover > 4096)
                   1301:        fprintf (file, "\tldq $2,%d($30)\n", leftover - 4096);
                   1302:     }
                   1303: 
                   1304:   /* Describe our frame.  */
                   1305:   fprintf (file, "\t.frame $%d,%d,$26,%d\n", 
                   1306:           frame_pointer_needed ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM,
                   1307:           frame_size, current_function_pretend_args_size);
                   1308:     
                   1309:   /* If reg_offset is "close enough" to 2**15 that one of the offsets would
                   1310:      overflow a store instruction, compute the base of the register save
                   1311:      area into $28.  */
                   1312:   if (reg_offset >= 32768 - alpha_sa_size () && alpha_sa_size () != 0)
                   1313:     {
                   1314:       add_long_const (file, reg_offset, 30, 28);
                   1315:       reg_offset_base_reg = 28;
                   1316:       reg_offset = start_reg_offset = 0;
                   1317:     }
                   1318: 
                   1319:   /* Save register 26 if it is used or if any other register needs to
                   1320:      be saved.  */
                   1321:   if (regs_ever_live[26] || alpha_sa_size () != 0)
                   1322:     {
                   1323:       reg_mask |= 1 << 26;
                   1324:       fprintf (file, "\tstq $26,%d($%d)\n", reg_offset, reg_offset_base_reg);
                   1325:       reg_offset += 8;
                   1326:     }
                   1327: 
                   1328:   /* Now save any other used integer registers required to be saved.  */
                   1329:   for (i = 0; i < 32; i++)
                   1330:     if (! fixed_regs[i] && ! call_used_regs[i] && regs_ever_live[i] && i != 26)
                   1331:       {
                   1332:        reg_mask |= 1 << i;
                   1333:        fprintf (file, "\tstq $%d,%d($%d)\n",
                   1334:                 i, reg_offset, reg_offset_base_reg);
                   1335:        reg_offset += 8;
                   1336:       }
                   1337: 
                   1338:   /* Print the register mask and do floating-point saves.  */
                   1339:   if (reg_mask)
                   1340:     fprintf (file, "\t.mask 0x%x,%d\n", reg_mask,
                   1341:             actual_start_reg_offset - frame_size);
                   1342: 
                   1343:   start_reg_offset = reg_offset;
                   1344:   reg_mask = 0;
                   1345: 
                   1346:   for (i = 0; i < 32; i++)
                   1347:     if (! fixed_regs[i + 32] && ! call_used_regs[i + 32]
                   1348:        && regs_ever_live[i + 32])
                   1349:       {
                   1350:        reg_mask |= 1 << i;
                   1351:        fprintf (file, "\tstt $f%d,%d($%d)\n",
                   1352:                 i, reg_offset, reg_offset_base_reg);
                   1353:        reg_offset += 8;
                   1354:       }
                   1355: 
                   1356:   /* Print the floating-point mask, if we've saved any fp register.  */
                   1357:   if (reg_mask)
                   1358:     fprintf (file, "\t.fmask 0x%x,%d\n", reg_mask, actual_start_reg_offset);
                   1359: 
                   1360:   /* If we need a frame pointer, set it from the stack pointer.  Note that
                   1361:      this must always be the last instruction in the prologue.  */
                   1362:   if (frame_pointer_needed)
                   1363:     fprintf (file, "\tbis $30,$30,$15\n");
                   1364: 
                   1365:   /* End the prologue and say if we used gp.  */
                   1366:   fprintf (file, "\t.prologue %d\n", alpha_function_needs_gp);
                   1367: }
                   1368: 
                   1369: /* Write function epilogue.  */
                   1370: 
                   1371: void
                   1372: output_epilog (file, size)
                   1373:      FILE *file;
                   1374:      int size;
                   1375: {
                   1376:   rtx insn = get_last_insn ();
                   1377:   HOST_WIDE_INT frame_size = ((size + current_function_outgoing_args_size
                   1378:                               + current_function_pretend_args_size
                   1379:                               + alpha_sa_size () + 15) & ~15);
                   1380:   HOST_WIDE_INT reg_offset = size + current_function_outgoing_args_size;
                   1381:   HOST_WIDE_INT frame_size_from_reg_save = frame_size - reg_offset;
                   1382:   int reg_offset_base_reg = 30;
                   1383:   int i;
                   1384: 
                   1385:   /* If the last insn was a BARRIER, we don't have to write anything except
                   1386:      the .end pseudo-op.  */
                   1387:   if (GET_CODE (insn) == NOTE)
                   1388:     insn = prev_nonnote_insn (insn);
                   1389:   if (insn == 0 || GET_CODE (insn) != BARRIER)
                   1390:     {
                   1391:       int fp_offset;
                   1392: 
                   1393:       /* If we have a frame pointer, restore SP from it.  */
                   1394:       if (frame_pointer_needed)
                   1395:        fprintf (file, "\tbis $15,$15,$30\n");
                   1396: 
                   1397:       /* If the register save area is out of range, put its address into
                   1398:         $28.  */
                   1399:       if (reg_offset >= 32768 - alpha_sa_size () && alpha_sa_size () != 0)
                   1400:        {
                   1401:          add_long_const (file, reg_offset, 30, 28);
                   1402:          reg_offset_base_reg = 28;
                   1403:          reg_offset = 0;
                   1404:        }
                   1405: 
                   1406:       /* Restore all the registers, starting with the return address
                   1407:         register.  */
                   1408:       if (regs_ever_live[26] || alpha_sa_size () != 0)
                   1409:        {
                   1410:          fprintf (file, "\tldq $26,%d($%d)\n",
                   1411:                   reg_offset, reg_offset_base_reg);
                   1412:          reg_offset += 8;
                   1413:        }
                   1414: 
                   1415:       /* Now restore any other used integer registers that that we saved,
                   1416:         except for FP if it is being used as FP, since it must be
                   1417:         restored last.  */
                   1418: 
                   1419:       for (i = 0; i < 32; i++)
                   1420:        if (! fixed_regs[i] && ! call_used_regs[i] && regs_ever_live[i]
                   1421:            && i != 26)
                   1422:          {
                   1423:            if (i == FRAME_POINTER_REGNUM && frame_pointer_needed)
                   1424:              fp_offset = reg_offset;
                   1425:            else
                   1426:              fprintf (file, "\tldq $%d,%d($%d)\n",
                   1427:                       i, reg_offset, reg_offset_base_reg);
                   1428:            reg_offset += 8;
                   1429:          }
                   1430: 
                   1431:       for (i = 0; i < 32; i++)
                   1432:        if (! fixed_regs[i + 32] && ! call_used_regs[i + 32]
                   1433:            && regs_ever_live[i + 32])
                   1434:          {
                   1435:            fprintf (file, "\tldt $f%d,%d($%d)\n",
                   1436:                     i, reg_offset, reg_offset_base_reg);
                   1437:            reg_offset += 8;
                   1438:          }
                   1439: 
                   1440:       /* If the stack size is large, compute the size of the stack into
                   1441:         a register because the old FP restore, stack pointer adjust,
                   1442:         and return are required to be consecutive instructions.  
                   1443:         However, if the new stack pointer can be computed by adding the
                   1444:         a constant to the start of the register save area, we can do
                   1445:         it that way.  */
                   1446:       if (frame_size > 32767
                   1447:          && ! (reg_offset_base_reg != 30
                   1448:                && frame_size_from_reg_save < 32768))
                   1449:        add_long_const (file, frame_size, 31, 1);
                   1450: 
                   1451:       /* If we needed a frame pointer and we have to restore it, do it
                   1452:         now.  This must be done in one instruction immediately
                   1453:         before the SP update.  */
                   1454:       if (frame_pointer_needed && regs_ever_live[FRAME_POINTER_REGNUM])
                   1455:        fprintf (file, "\tldq $15,%d($%d)\n", fp_offset, reg_offset_base_reg);
                   1456: 
                   1457:       /* Now update the stack pointer, if needed.  This must be done in
                   1458:         one, stylized, instruction.  */
                   1459:       if (frame_size > 32768)
                   1460:        {
                   1461:          if (reg_offset_base_reg != 30
                   1462:              && frame_size_from_reg_save < 32768)
                   1463:            {
                   1464:              if (frame_size_from_reg_save < 255)
                   1465:                fprintf (file, "\taddq $%d,%d,$30\n",
                   1466:                         reg_offset_base_reg, frame_size_from_reg_save);
                   1467:              else
                   1468:                fprintf (file, "\tlda %30,%d($%d)\n",
                   1469:                         frame_size_from_reg_save, reg_offset_base_reg);
                   1470:            }
                   1471:          else
                   1472:            fprintf (file, "\taddq $1,$30,$30\n");
                   1473:        }
                   1474:       else if (frame_size != 0)
                   1475:        fprintf (file, "\tlda $30,%d($30)\n", frame_size);
                   1476: 
                   1477:       /* Finally return to the caller.  */
                   1478:       fprintf (file, "\tret $31,($26),1\n");
                   1479:     }
                   1480: 
                   1481:   /* End the function.  */
                   1482:   fprintf (file, "\t.end %s\n", alpha_function_name);
                   1483:   inside_function = FALSE;
                   1484: 
                   1485:   /* Show that we know this function if it is called again.  */
                   1486:   SYMBOL_REF_FLAG (XEXP (DECL_RTL (current_function_decl), 0)) = 1;
                   1487: }
                   1488: 
                   1489: /* Debugging support.  */
                   1490: 
                   1491: #include "gstab.h"
                   1492: 
                   1493: /* Count the number of sdb related labels are generated (to find block
                   1494:    start and end boundaries).  */
                   1495: 
                   1496: int sdb_label_count = 0;
                   1497: 
                   1498: /* Next label # for each statement.  */
                   1499: 
                   1500: static int sym_lineno = 0;
                   1501: 
                   1502: /* Count the number of .file directives, so that .loc is up to date.  */
                   1503: 
                   1504: static int num_source_filenames = 0;
                   1505: 
                   1506: /* Name of the file containing the current function.  */
                   1507: 
                   1508: static char *current_function_file = "";
                   1509: 
                   1510: /* Offsets to alpha virtual arg/local debugging pointers.  */
                   1511: 
                   1512: long alpha_arg_offset;
                   1513: long alpha_auto_offset;
                   1514: 
                   1515: /* Emit a new filename to a stream.  */
                   1516: 
                   1517: void
                   1518: alpha_output_filename (stream, name)
                   1519:      FILE *stream;
                   1520:      char *name;
                   1521: {
                   1522:   static int first_time = TRUE;
                   1523:   char ltext_label_name[100];
                   1524: 
                   1525:   if (first_time)
                   1526:     {
                   1527:       first_time = FALSE;
                   1528:       ++num_source_filenames;
                   1529:       current_function_file = name;
                   1530:       fprintf (stream, "\t.file\t%d ", num_source_filenames);
                   1531:       output_quoted_string (stream, name);
                   1532:       fprintf (stream, "\n");
                   1533:       if (!TARGET_GAS && write_symbols == DBX_DEBUG)
                   1534:        fprintf (stream, "\t#@stabs\n");
                   1535:     }
                   1536: 
                   1537:   else if (!TARGET_GAS && write_symbols == DBX_DEBUG)
                   1538:     {
                   1539:       ASM_GENERATE_INTERNAL_LABEL (ltext_label_name, "Ltext", 0);
                   1540:       fprintf (stream, "%s ", ASM_STABS_OP);
                   1541:       output_quoted_string (stream, name);
                   1542:       fprintf (stream, ",%d,0,0,%s\n", N_SOL, &ltext_label_name[1]);
                   1543:     }
                   1544: 
                   1545:   else if (name != current_function_file
                   1546:       && strcmp (name, current_function_file) != 0)
                   1547:     {
                   1548:       if (inside_function && ! TARGET_GAS)
                   1549:        fprintf (stream, "\t#.file\t%d ", num_source_filenames);
                   1550:       else
                   1551:        {
                   1552:          ++num_source_filenames;
                   1553:          current_function_file = name;
                   1554:          fprintf (stream, "\t.file\t%d ", num_source_filenames);
                   1555:        }
                   1556: 
                   1557:       output_quoted_string (stream, name);
                   1558:       fprintf (stream, "\n");
                   1559:     }
                   1560: }
                   1561: 
                   1562: /* Emit a linenumber to a stream.  */
                   1563: 
                   1564: void
                   1565: alpha_output_lineno (stream, line)
                   1566:      FILE *stream;
                   1567:      int line;
                   1568: {
                   1569:   if (! TARGET_GAS && write_symbols == DBX_DEBUG)
                   1570:     {
                   1571:       /* mips-tfile doesn't understand .stabd directives.  */
                   1572:       ++sym_lineno;
                   1573:       fprintf (stream, "$LM%d:\n\t%s %d,0,%d,$LM%d\n",
                   1574:               sym_lineno, ASM_STABN_OP, N_SLINE, line, sym_lineno);
                   1575:     }
                   1576:   else
                   1577:     fprintf (stream, "\n\t.loc\t%d %d\n", num_source_filenames, line);
                   1578: }

unix.superglobalmegacorp.com

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