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

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

unix.superglobalmegacorp.com

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