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

1.1       root        1: /* Subroutines used for code generation on AMD Am29000.
1.1.1.3 ! root        2:    Copyright (C) 1987, 1988, 1990, 1991, 1992 Free Software Foundation, Inc.
1.1       root        3:    Contributed by Richard Kenner ([email protected])
                      4: 
                      5: This file is part of GNU CC.
                      6: 
                      7: GNU CC is free software; you can redistribute it and/or modify
                      8: it under the terms of the GNU General Public License as published by
                      9: the Free Software Foundation; either version 2, or (at your option)
                     10: any later version.
                     11: 
                     12: GNU CC is distributed in the hope that it will be useful,
                     13: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     15: GNU General Public License for more details.
                     16: 
                     17: You should have received a copy of the GNU General Public License
                     18: along with GNU CC; see the file COPYING.  If not, write to
                     19: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
                     20: 
                     21: #include <stdio.h>
                     22: #include "config.h"
                     23: #include "rtl.h"
                     24: #include "regs.h"
                     25: #include "hard-reg-set.h"
                     26: #include "real.h"
                     27: #include "insn-config.h"
                     28: #include "conditions.h"
                     29: #include "insn-flags.h"
                     30: #include "output.h"
                     31: #include "insn-attr.h"
                     32: #include "flags.h"
                     33: #include "recog.h"
                     34: #include "expr.h"
                     35: #include "obstack.h"
                     36: #include "tree.h"
1.1.1.3 ! root       37: #include "reload.h"
1.1       root       38: 
                     39: #define min(A,B)       ((A) < (B) ? (A) : (B))
                     40: 
                     41: /* This gives the size in words of the register stack for the current
                     42:    procedure.  */
                     43: 
                     44: static int a29k_regstack_size;
                     45: 
                     46: /* This points to the last insn of the insn prologue.  It is set when
                     47:    an insn without a filled delay slot is found near the start of the
                     48:    function.  */
                     49: 
                     50: static char *a29k_last_prologue_insn;
                     51: 
                     52: /* This points to the first insn that will be in the epilogue.  It is null if
                     53:    no epilogue is required.  */
                     54: 
                     55: static char *a29k_first_epilogue_insn;
                     56: 
                     57: /* This is nonzero if a a29k_first_epilogue_insn was put in a delay slot.  It
                     58:    indicates that an intermediate label needs to be written.  */
                     59: 
                     60: static int a29k_first_epilogue_insn_used;
                     61: 
                     62: /* Location to hold the name of the current function.  We need this prolog to
                     63:    contain the tag words prior to the declaration.  So the name must be stored
                     64:    away.  */
                     65: 
                     66: char *a29k_function_name;
                     67: 
                     68: /* Mapping of registers to debug register numbers.  The only change is
                     69:    for the frame pointer and the register numbers used for the incoming
                     70:    arguments.  */
                     71: 
                     72: int a29k_debug_reg_map[FIRST_PSEUDO_REGISTER];
                     73: 
                     74: /* Save information from a "cmpxx" operation until the branch or scc is
                     75:    emitted.  */
                     76: 
                     77: rtx a29k_compare_op0, a29k_compare_op1;
                     78: int a29k_compare_fp_p;
                     79: 
                     80: /* Gives names for registers.  */
                     81: extern char *reg_names[];
                     82: 
                     83: /* Returns 1 if OP is a 8-bit constant. */
                     84: 
                     85: int
                     86: cint_8_operand (op, mode)
                     87:      register rtx op;
                     88:      enum machine_mode mode;
                     89: {
                     90:   return GET_CODE (op) == CONST_INT && (INTVAL (op) & 0xffffff00) == 0;
                     91: }
                     92: 
                     93: /* Returns 1 if OP is a 16-bit constant.  */
                     94: 
                     95: int
                     96: cint_16_operand (op, mode)
                     97:      rtx op;
                     98:      enum machine_mode mode;
                     99: {
                    100:   return GET_CODE (op) == CONST_INT && (INTVAL (op) & 0xffff0000) == 0;
                    101: }
                    102: 
1.1.1.3 ! root      103: /* Returns 1 if OP is a constant that cannot be moved in a single insn.  */
1.1       root      104: 
                    105: int
                    106: long_const_operand (op, mode)
                    107:      register rtx op;
                    108:      enum machine_mode mode;
                    109: {
                    110:   if (! CONSTANT_P (op))
                    111:     return 0;
                    112: 
                    113:   if (TARGET_29050 && GET_CODE (op) == CONST_INT
                    114:       && (INTVAL (op) & 0xffff) == 0)
                    115:     return 0;
                    116: 
                    117:   return (GET_CODE (op) != CONST_INT
                    118:          || ((INTVAL (op) & 0xffff0000) != 0
                    119:              && (INTVAL (op) & 0xffff0000) != 0xffff0000
                    120:              && INTVAL (op) != 0x80000000));
                    121: }
                    122: 
                    123: /* The following four functions detect constants of 0, 8, 16, and 24 used as
                    124:    a position in ZERO_EXTRACT operations.  They can either be the appropriate
                    125:    constant integer or a shift (which will be produced by combine).  */
                    126: 
                    127: static int
                    128: shift_constant_operand (op, mode, val)
                    129:      rtx op;
                    130:      enum machine_mode mode;
                    131:      int val;
                    132: {
                    133:   return ((GET_CODE (op) == CONST_INT && INTVAL (op) == val)
                    134:          || (GET_CODE (op) == ASHIFT
                    135:              && GET_CODE (XEXP (op, 0)) == CONST_INT
                    136:              && INTVAL (XEXP (op, 0)) == val / 8
                    137:              && GET_CODE (XEXP (op, 1)) == CONST_INT
                    138:              && INTVAL (XEXP (op, 1)) == 3));
                    139: }
                    140: 
                    141: int
                    142: const_0_operand (op, mode)
                    143:      rtx op;
                    144:      enum machine_mode mode;
                    145: {
                    146:   return shift_constant_operand (op, mode, 0);
                    147: }
                    148: 
                    149: int
                    150: const_8_operand (op, mode)
                    151:      rtx op;
                    152:      enum machine_mode mode;
                    153: {
                    154:   return shift_constant_operand (op, mode, 8);
                    155: }
                    156: 
                    157: int
                    158: const_16_operand (op, mode)
                    159:      rtx op;
1.1.1.3 ! root      160:      enum machine_mode mode;
1.1       root      161: {
                    162:   return shift_constant_operand (op, mode, 16);
                    163: }
                    164: 
                    165: int
                    166: const_24_operand (op, mode)
                    167:      rtx op;
1.1.1.3 ! root      168:      enum machine_mode mode;
1.1       root      169: {
                    170:   return shift_constant_operand (op, mode, 24);
                    171: }
                    172: 
                    173: /* Returns 1 if OP is a floating-point constant of the proper mode.  */
                    174: 
                    175: int
                    176: float_const_operand (op, mode)
                    177:      rtx op;
                    178:      enum machine_mode mode;
                    179: {
                    180:   return GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == mode;
                    181: }
                    182: 
                    183: /* Returns 1 if OP is a floating-point constant of the proper mode or a
                    184:    general-purpose register.  */
                    185: 
                    186: int
1.1.1.2   root      187: gpc_reg_or_float_constant_operand (op, mode)
1.1       root      188:      rtx op;
                    189:      enum machine_mode mode;
                    190: {
1.1.1.2   root      191:   return float_const_operand (op, mode) || gpc_reg_operand (op, mode);
1.1       root      192: }
                    193: 
                    194: /* Returns 1 if OP is an integer constant of the proper mode or a
                    195:    general-purpose register.  */
                    196: 
                    197: int
1.1.1.2   root      198: gpc_reg_or_integer_constant_operand (op, mode)
1.1       root      199:      rtx op;
                    200:      enum machine_mode mode;
                    201: {
                    202:   return ((GET_MODE (op) == VOIDmode
                    203:           && (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE))
1.1.1.2   root      204:          || gpc_reg_operand (op, mode));
1.1       root      205: }
                    206:      
                    207: /* Returns 1 if OP is a special machine register.  */
                    208: 
                    209: int
                    210: spec_reg_operand (op, mode)
                    211:      rtx op;
                    212:      enum machine_mode mode;
                    213: {
1.1.1.3 ! root      214:   if (GET_CODE (op) != REG || GET_MODE (op) != mode)
        !           215:     return 0;
        !           216: 
        !           217:   switch (GET_MODE_CLASS (mode))
        !           218:     {
        !           219:     case MODE_PARTIAL_INT:
        !           220:       return REGNO (op) >= R_BP && REGNO (op) <= R_CR;
        !           221:     case MODE_INT:
        !           222:       return REGNO (op) >= R_Q && REGNO (op) <= R_EXO;
        !           223:     detault:
        !           224:       return 0;
        !           225:     }
1.1       root      226: }
                    227: 
                    228: /* Returns 1 if OP is an accumulator register.  */
                    229: 
                    230: int
                    231: accum_reg_operand (op, mode)
                    232:      rtx op;
                    233:      enum machine_mode mode;
                    234: {
                    235:   return (GET_CODE (op) == REG
                    236:          && REGNO (op) >= R_ACC (0) && REGNO (op) <= R_ACC (3));
                    237: }
                    238: 
                    239: /* Returns 1 if OP is a normal data register.  */
                    240: 
                    241: int
1.1.1.2   root      242: gpc_reg_operand (op, mode)
1.1       root      243:      rtx op;
                    244:      enum machine_mode mode;
                    245: {
                    246:   int regno;
                    247: 
                    248:   if (GET_MODE (op) != mode && mode != VOIDmode)
                    249:     return 0;
                    250: 
                    251:   if (GET_CODE (op) == REG)
                    252:     regno = REGNO (op);
                    253:   else if (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG)
                    254:     {
                    255:       regno = REGNO (SUBREG_REG (op));
                    256:       if (regno < FIRST_PSEUDO_REGISTER)
                    257:        regno += SUBREG_WORD (op);
                    258:     }
                    259:   else
                    260:     return 0;
                    261: 
                    262:   return regno >= FIRST_PSEUDO_REGISTER || regno < R_BP;
                    263: }
                    264: 
                    265: /* Returns 1 if OP is either an 8-bit constant integer or a general register.
                    266:    If a register, it must be in the proper mode unless MODE is VOIDmode.  */
                    267: 
                    268: int
                    269: srcb_operand (op, mode)
                    270:       register rtx op;
                    271:       enum machine_mode mode;
                    272: {
                    273:   if (GET_CODE (op) == CONST_INT
                    274:       && (mode == QImode
                    275:          || (INTVAL (op) & 0xffffff00) == 0))
                    276:     return 1;
                    277: 
                    278:   if (GET_MODE (op) != mode && mode != VOIDmode)
                    279:     return 0;
                    280: 
1.1.1.2   root      281:   return gpc_reg_operand (op, mode);
1.1       root      282: }
                    283: 
                    284: /* Return 1 if OP is either an immediate or a general register.  This is used
                    285:    for the input operand of mtsr/mtrsim.  */
                    286: 
                    287: int
1.1.1.2   root      288: gpc_reg_or_immediate_operand (op, mode)
1.1       root      289:      rtx op;
1.1.1.3 ! root      290:      enum machine_mode mode;
1.1       root      291: {
1.1.1.2   root      292:   return gpc_reg_operand (op, mode) || immediate_operand (op, mode);
1.1       root      293: }
                    294: 
                    295: /* Return 1 if OP can be used as the second operand of and AND insn.  This
                    296:    includes srcb_operand and a constant whose complement fits in 8 bits.  */
                    297: 
                    298: int
                    299: and_operand (op, mode)
                    300:      rtx op;
1.1.1.3 ! root      301:      enum machine_mode mode;
1.1       root      302: {
                    303:   return (srcb_operand (op, mode)
                    304:          || (GET_CODE (op) == CONST_INT
                    305:              && ((unsigned) ((~ INTVAL (op)) & GET_MODE_MASK (mode)) < 256)));
                    306: }
                    307: 
                    308: /* Return 1 if OP can be used as the second operand of an ADD insn.
                    309:    This is the same as above, except we use negative, rather than
                    310:    complement.   */
                    311: 
                    312: int
                    313: add_operand (op, mode)
                    314:      rtx op;
1.1.1.3 ! root      315:      enum machine_mode mode;
1.1       root      316: {
                    317:   return (srcb_operand (op, mode)
                    318:          || (GET_CODE (op) == CONST_INT
                    319:              && ((unsigned) ((- INTVAL (op)) & GET_MODE_MASK (mode)) < 256)));
                    320: }
1.1.1.3 ! root      321: 
        !           322: /* Return 1 if OP is a valid address in a CALL_INSN.  These are a SYMBOL_REF
        !           323:    to the current function, all SYMBOL_REFs if TARGET_SMALL_MEMORY, or
        !           324:    a sufficiently-small constant.  */
        !           325: 
        !           326: int
        !           327: call_operand (op, mode)
        !           328:      rtx op;
        !           329:      enum machine_mode mode;
        !           330: {
        !           331:   switch (GET_CODE (op))
        !           332:     {
        !           333:     case SYMBOL_REF:
        !           334:       return (TARGET_SMALL_MEMORY
        !           335:              || ! strcmp (XSTR (op, 0), current_function_name));
        !           336: 
        !           337:     case CONST_INT:
        !           338:       return (unsigned HOST_WIDE_INT) INTVAL (op) < 0x40000;
        !           339: 
        !           340:     default:
        !           341:       return 0;
        !           342:     }
        !           343: }
1.1       root      344: 
                    345: /* Return 1 if OP can be used as the input operand for a move insn.  */
                    346: 
                    347: int
                    348: in_operand (op, mode)
                    349:      rtx op;
                    350:      enum machine_mode mode;
                    351: {
                    352:   rtx orig_op = op;
                    353: 
                    354:   if (! general_operand (op, mode))
                    355:     return 0;
                    356: 
                    357:   while (GET_CODE (op) == SUBREG)
                    358:     op = SUBREG_REG (op);
                    359: 
                    360:   switch (GET_CODE (op))
                    361:     {
                    362:     case REG:
                    363:       return 1;
                    364: 
                    365:     case MEM:
                    366:       return (GET_MODE_SIZE (mode) >= UNITS_PER_WORD || TARGET_DW_ENABLE);
                    367: 
                    368:     case CONST_INT:
1.1.1.3 ! root      369:       if (GET_MODE_CLASS (mode) != MODE_INT
        !           370:          && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
1.1       root      371:        return 0;
                    372: 
                    373:       return 1;
                    374: 
                    375:     case CONST:
                    376:     case SYMBOL_REF:
                    377:     case LABEL_REF:
                    378:       return (GET_MODE (op) == mode
                    379:              || mode == SImode || mode == HImode || mode == QImode);
                    380: 
                    381:     case CONST_DOUBLE:
                    382:       return ((GET_MODE_CLASS (mode) == MODE_FLOAT
                    383:               && mode == GET_MODE (op))
                    384:              || (GET_MODE (op) == VOIDmode
                    385:                  && GET_MODE_CLASS (mode) == MODE_INT));
                    386: 
                    387:     default:
                    388:       return 0;
                    389:     }
                    390: }
                    391: 
                    392: /* Return 1 if OP can be used as the output operand for a move insn.  */
                    393: 
                    394: int
                    395: out_operand (op, mode)
                    396:      rtx op;
                    397:      enum machine_mode mode;
                    398: {
                    399:   rtx orig_op = op;
                    400: 
                    401:   if (! general_operand (op, mode))
                    402:     return 0;
                    403: 
                    404:   while (GET_CODE (op) == SUBREG)
                    405:     op = SUBREG_REG (op);
                    406: 
                    407:   if (GET_CODE (op) == REG)
1.1.1.3 ! root      408:     return (gpc_reg_operand (orig_op, mode)
        !           409:            || spec_reg_operand (orig_op, mode)
1.1       root      410:            || (GET_MODE_CLASS (mode) == MODE_FLOAT
                    411:                && accum_reg_operand (orig_op, mode)));
                    412: 
                    413:   else if (GET_CODE (op) == MEM)
1.1.1.3 ! root      414:     return (GET_MODE_SIZE (mode) >= UNITS_PER_WORD || TARGET_DW_ENABLE);
1.1       root      415:   else
                    416:     return 0;
                    417: }
                    418: 
1.1.1.3 ! root      419: /* Return 1 if OP is an item in memory, given that we are in reload.  */
1.1       root      420: 
                    421: int
1.1.1.3 ! root      422: reload_memory_operand (op, mode)
1.1       root      423:      rtx op;
                    424:      enum machine_mode mode;
                    425: {
1.1.1.3 ! root      426:   int regno = true_regnum (op);
        !           427: 
        !           428:   return (! CONSTANT_P (op)
        !           429:          && (regno == -1
        !           430:              || (GET_CODE (op) == REG
        !           431:                  && REGNO (op) >= FIRST_PSEUDO_REGISTER)));
        !           432: }
        !           433: 
        !           434: /* Given an object for which reload_memory_operand is true, return the address
        !           435:    of the operand, taking into account anything that reload may do.  */
        !           436: 
        !           437: rtx
        !           438: a29k_get_reloaded_address (op)
        !           439:      rtx op;
        !           440: {
        !           441:   if (GET_CODE (op) == SUBREG)
        !           442:     {
        !           443:       if (SUBREG_WORD (op) != 0)
        !           444:        abort ();
        !           445: 
        !           446:       op = SUBREG_REG (op);
        !           447:     }
        !           448: 
        !           449:   if (GET_CODE (op) == REG)
        !           450:     op = reg_equiv_mem[REGNO (op)];
        !           451: 
        !           452:   return find_replacement (&XEXP (op, 0));
        !           453: }
        !           454: 
        !           455: /* Subfunction of the following function.  Update the flags of any MEM
        !           456:    found in part of X.  */
        !           457: 
        !           458: static void
        !           459: a29k_set_memflags_1 (x, in_struct_p, volatile_p, unchanging_p)
        !           460:      rtx x;
        !           461:      int in_struct_p, volatile_p, unchanging_p;
        !           462: {
        !           463:   int i;
        !           464: 
        !           465:   switch (GET_CODE (x))
        !           466:     {
        !           467:     case SEQUENCE:
        !           468:     case PARALLEL:
        !           469:       for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
        !           470:        a29k_set_memflags_1 (XVECEXP (x, 0, i), in_struct_p, volatile_p,
        !           471:                             unchanging_p);
        !           472:       break;
        !           473: 
        !           474:     case INSN:
        !           475:       a29k_set_memflags_1 (PATTERN (x), in_struct_p, volatile_p,
        !           476:                           unchanging_p);
        !           477:       break;
        !           478: 
        !           479:     case SET:
        !           480:       a29k_set_memflags_1 (SET_DEST (x), in_struct_p, volatile_p,
        !           481:                           unchanging_p);
        !           482:       a29k_set_memflags_1 (SET_SRC (x), in_struct_p, volatile_p, unchanging_p);
        !           483:       break;
        !           484: 
        !           485:     case MEM:
        !           486:       MEM_IN_STRUCT_P (x) = in_struct_p;
        !           487:       MEM_VOLATILE_P (x) = volatile_p;
        !           488:       RTX_UNCHANGING_P (x) = unchanging_p;
        !           489:       break;
        !           490:     }
1.1       root      491: }
                    492: 
1.1.1.3 ! root      493: /* Given INSN, which is either an INSN or a SEQUENCE generated to
        !           494:    perform a memory operation, look for any MEMs in either a SET_DEST or
        !           495:    a SET_SRC and copy the in-struct, unchanging, and volatile flags from
        !           496:    REF into each of the MEMs found.  If REF is not a MEM, don't do
        !           497:    anything.  */
        !           498: 
        !           499: void
        !           500: a29k_set_memflags (insn, ref)
        !           501:      rtx insn;
        !           502:      rtx ref;
        !           503: {
        !           504:   /* Note that it is always safe to get these flags, though they won't
        !           505:      be what we think if REF is not a MEM.  */
        !           506:   int in_struct_p = MEM_IN_STRUCT_P (ref);
        !           507:   int volatile_p = MEM_VOLATILE_P (ref);
        !           508:   int unchanging_p = RTX_UNCHANGING_P (ref);
        !           509: 
        !           510:   if (GET_CODE (ref) != MEM
        !           511:       || (! in_struct_p && ! volatile_p && ! unchanging_p))
        !           512:     return;
        !           513: 
        !           514:   a29k_set_memflags_1 (insn, in_struct_p, volatile_p, unchanging_p);
        !           515: }
        !           516: 
1.1       root      517: /* Return 1 if OP is a comparison operator that we have in floating-point.  */
                    518: 
                    519: int
                    520: fp_comparison_operator (op, mode)
                    521:      rtx op;
                    522:      enum machine_mode mode;
                    523: {
                    524:   return ((mode == VOIDmode || mode == GET_MODE (op))
                    525:          && (GET_CODE (op) == EQ || GET_CODE (op) == GT ||
                    526:              GET_CODE (op) == GE));
                    527: }
                    528: 
                    529: /* Return 1 if OP is a valid branch comparison.  */
                    530: 
                    531: int
                    532: branch_operator (op, mode)
                    533:      rtx op;
                    534:      enum machine_mode mode;
                    535: {
                    536:   return ((mode == VOIDmode || mode == GET_MODE (op))
                    537:          && (GET_CODE (op) == GE || GET_CODE (op) == LT));
                    538: }
                    539: 
                    540: /* Return 1 if OP is a load multiple operation.  It is known to be a
                    541:    PARALLEL and the first three sections will be tested.  */
                    542: 
                    543: int
                    544: load_multiple_operation (op, mode)
                    545:      rtx op;
                    546:      enum machine_mode mode;
                    547: {
                    548:   int count = XVECLEN (op, 0) - 2;
                    549:   int dest_regno;
                    550:   rtx src_addr;
                    551:   int i;
                    552: 
                    553:   /* Perform a quick check so we don't blow up below.  */
                    554:   if (count <= 1
                    555:       || GET_CODE (XVECEXP (op, 0, 0)) != SET
                    556:       || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG
                    557:       || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM)
                    558:     return 0;
                    559: 
                    560:   dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
                    561:   src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0);
                    562: 
                    563:   for (i = 1; i < count; i++)
                    564:     {
                    565:       rtx elt = XVECEXP (op, 0, i + 2);
                    566: 
                    567:       if (GET_CODE (elt) != SET
                    568:          || GET_CODE (SET_DEST (elt)) != REG
                    569:          || GET_MODE (SET_DEST (elt)) != SImode
                    570:          || REGNO (SET_DEST (elt)) != dest_regno + i
                    571:          || GET_CODE (SET_SRC (elt)) != MEM
                    572:          || GET_MODE (SET_SRC (elt)) != SImode
                    573:          || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS
                    574:          || ! rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr)
                    575:          || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT
                    576:          || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != i * 4)
                    577:        return 0;
                    578:     }
                    579: 
                    580:   return 1;
                    581: }
                    582: 
                    583: /* Similar, but tests for store multiple.  */
                    584: 
                    585: int
                    586: store_multiple_operation (op, mode)
                    587:      rtx op;
                    588:      enum machine_mode mode;
                    589: {
                    590:   int num_special = TARGET_NO_STOREM_BUG ? 2 : 1;
                    591:   int count = XVECLEN (op, 0) - num_special;
                    592:   int src_regno;
                    593:   rtx dest_addr;
                    594:   int i;
                    595: 
                    596:   /* Perform a quick check so we don't blow up below.  */
                    597:   if (count <= 1
                    598:       || GET_CODE (XVECEXP (op, 0, 0)) != SET
                    599:       || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM
                    600:       || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG)
                    601:     return 0;
                    602: 
                    603:   src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0)));
                    604:   dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0);
                    605: 
                    606:   for (i = 1; i < count; i++)
                    607:     {
                    608:       rtx elt = XVECEXP (op, 0, i + num_special);
                    609: 
                    610:       if (GET_CODE (elt) != SET
                    611:          || GET_CODE (SET_SRC (elt)) != REG
                    612:          || GET_MODE (SET_SRC (elt)) != SImode
                    613:          || REGNO (SET_SRC (elt)) != src_regno + i
                    614:          || GET_CODE (SET_DEST (elt)) != MEM
                    615:          || GET_MODE (SET_DEST (elt)) != SImode
                    616:          || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS
                    617:          || ! rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr)
                    618:          || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT
                    619:          || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != i * 4)
                    620:        return 0;
                    621:     }
                    622: 
                    623:   return 1;
                    624: }
                    625: 
                    626: /* Given a special register REG and MASK, a value being masked against a
                    627:    quantity to which the special register is set, return 1 if the masking
                    628:    operation is built-in to the setting of that special register.  */
                    629: 
                    630: int
                    631: masks_bits_for_special (reg, mask)
                    632:      rtx reg;
                    633:      rtx mask;
                    634: {
                    635:    int needed_mask_value;
                    636: 
                    637:   if (GET_CODE (reg) != REG || GET_CODE (mask) != CONST_INT)
                    638:     abort ();
                    639: 
                    640:   switch (REGNO (reg))
                    641:     {
                    642:     case R_BP:
                    643:     case R_INT:
                    644:       needed_mask_value = 3;
                    645:       break;
                    646: 
                    647:     case R_FC:
                    648:       needed_mask_value = 31;
                    649:       break;
                    650: 
                    651:     case R_CR:
                    652:     case R_LRU:
                    653:       needed_mask_value = 255;
                    654:       break;
                    655: 
                    656:     case R_FPE:
                    657:       needed_mask_value = 511;
                    658:       break;
                    659: 
                    660:     case R_MMU:
                    661:       needed_mask_value = 0x3ff;
                    662:       break;
                    663: 
                    664:     case R_OPS:
                    665:     case R_CPS:
                    666:     case R_RBP:
                    667:     case R_FPS:
                    668:       needed_mask_value = 0xffff;
                    669:       break;
                    670: 
                    671:     case R_VAB:
                    672:       needed_mask_value = 0xffff0000;
                    673:       break;
                    674: 
                    675:     case R_Q:
                    676:     case R_CFG:
                    677:     case R_CHA:
                    678:     case R_CHD:
                    679:     case R_CHC:
                    680:     case R_TMC:
                    681:     case R_TMR:
                    682:     case R_PC0:
                    683:     case R_PC1:
                    684:     case R_PC2:
                    685:       return 0;
                    686: 
                    687:     default:
                    688:       abort ();
                    689:     }
                    690: 
                    691:    return (INTVAL (mask) & ~ needed_mask_value) == 0;
                    692: }
                    693: 
                    694: /* Return nonzero if this label is that of the return point, but there is
                    695:    a non-null epilogue.  */
                    696: 
                    697: int
                    698: epilogue_operand (op, mode)
                    699:      rtx op;
                    700:      enum machine_mode mode;
                    701: {
                    702:   return next_active_insn (op) == 0 && a29k_first_epilogue_insn != 0;
                    703: }
                    704: 
                    705: /* Return the register class of a scratch register needed to copy IN into
                    706:    or out of a register in CLASS in MODE.  If it can be done directly,
                    707:    NO_REGS is returned.  */
                    708: 
                    709: enum reg_class
                    710: secondary_reload_class (class, mode, in)
                    711:      enum reg_class class;
                    712:      enum machine_mode mode;
                    713:      rtx in;
                    714: {
                    715:   int regno = -1;
1.1.1.3 ! root      716:   enum rtx_code code = GET_CODE (in);
1.1       root      717: 
1.1.1.3 ! root      718:   if (! CONSTANT_P (in))
        !           719:     {
        !           720:       regno = true_regnum (in);
        !           721: 
        !           722:       /* A pseudo is the same as memory.  */
        !           723:       if (regno == -1 || regno >= FIRST_PSEUDO_REGISTER)
        !           724:        code = MEM;
        !           725:     }
        !           726: 
        !           727:   /* If we are transferring between memory and a multi-word mode, we need
        !           728:      CR.  */
        !           729: 
        !           730:   if (code == MEM && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
        !           731:     return CR_REGS;
1.1       root      732: 
1.1.1.3 ! root      733:   /* If between memory and a mode smaller than a word without DW being
        !           734:      enabled, we need BP.  */
        !           735: 
        !           736:   if (code == MEM && ! TARGET_DW_ENABLE
        !           737:       && GET_MODE_SIZE (mode) < UNITS_PER_WORD)
        !           738:     return BP_REGS;
        !           739: 
        !           740:   /* Otherwise, we can place anything into GENERAL_REGS and can put
        !           741:      GENERAL_REGS into anything.  */
1.1       root      742:   if (class == GENERAL_REGS || (regno != -1 && regno < R_BP))
                    743:     return NO_REGS;
                    744: 
                    745:   /* We can place 16-bit constants into a special register.  */
1.1.1.3 ! root      746:   if (code == CONST_INT
        !           747:       && (GET_MODE_BITSIZE (mode) <= 16 || (unsigned) INTVAL (in) <= 65535)
1.1       root      748:       && (class == BP_REGS || class == Q_REGS || class == SPECIAL_REGS))
                    749:     return NO_REGS;
                    750: 
                    751:   /* Otherwise, we need GENERAL_REGS.  */
                    752:   return GENERAL_REGS;
                    753: }
                    754: 
                    755: /* START is the zero-based incoming argument register index used (0 is 160,
                    756:    i.e., the first incoming argument register) and COUNT is the number used.
                    757: 
                    758:    Mark the corresponding incoming registers as neither fixed nor call used.
                    759:    For each register used for incoming arguments, we have one less local
                    760:    register that can be used.  So also mark some high-numbered registers as
                    761:    fixed.
                    762: 
                    763:    Return the first register number to use for the argument.  */
                    764: 
                    765: int
                    766: incoming_reg (start, count)
                    767:      int start;
                    768:      int count;
                    769: {
                    770:   int i;
                    771: 
                    772:   if (! TARGET_NO_REUSE_ARGS)
                    773:     /* Mark all the used registers as not fixed and saved over calls.  */
                    774:     for (i = R_AR (start); i < R_AR (16) && i < R_AR (start + count); i++)
                    775:       {
                    776:        fixed_regs[i] = call_used_regs[i] = call_fixed_regs[i] = 0;
                    777:        CLEAR_HARD_REG_BIT (fixed_reg_set, i);
                    778:        CLEAR_HARD_REG_BIT (call_used_reg_set, i);
                    779:        CLEAR_HARD_REG_BIT (call_fixed_reg_set, i);
                    780:       }
                    781: 
                    782:   /* Shorten the maximum size of the frame.  */
                    783:   for (i = R_AR (0) - start - count; i < R_AR (0) - start; i++)
                    784:     {
                    785:       fixed_regs[i] = call_used_regs[i] = call_fixed_regs[i] = 1;
                    786:       SET_HARD_REG_BIT (fixed_reg_set, i);
                    787:       SET_HARD_REG_BIT (call_used_reg_set, i);
                    788:       SET_HARD_REG_BIT (call_fixed_reg_set, i);
                    789:     }
                    790: 
                    791:   return R_AR (start);
                    792: }
                    793: 
                    794: /* These routines are used in finding insns to fill delay slots in the
                    795:    epilogue.  */
                    796: 
                    797: /* Return 1 if the current function will adjust the register stack.  */
                    798: 
                    799: int
                    800: needs_regstack_p ()
                    801: {
                    802:   int i;
                    803:   rtx insn;
                    804: 
                    805:   if (frame_pointer_needed)
                    806:     return 1;
                    807: 
                    808:   /* If any local register is used, we need to adjust the regstack.  */
                    809:   for (i = R_LR (127); i >= R_LR (0); i --)
                    810:     if (regs_ever_live[i])
                    811:       return 1;
                    812: 
                    813:   /* We need a register stack if we make any calls.  */
                    814:   for (insn = get_insns (); insn; insn = next_insn (insn))
                    815:     if (GET_CODE (insn) == CALL_INSN
                    816:        || (GET_CODE (insn) == INSN
                    817:            && GET_CODE (PATTERN (insn)) == SEQUENCE
                    818:            && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == CALL_INSN))
                    819:       return 1;
                    820: 
                    821:   /* Otherwise, we don't.  */
                    822:   return 0;
                    823: }
                    824: 
                    825: /* Return 1 if X uses a local register.  */
                    826: 
                    827: int
                    828: uses_local_reg_p (x)
                    829:      rtx x;
                    830: {
                    831:   char *fmt;
                    832:   int i, j;
                    833: 
                    834:   switch (GET_CODE (x))
                    835:     {
                    836:     case REG:
                    837:       return REGNO (x) >= R_LR (0) && REGNO (x) <= R_FP;
                    838: 
                    839:     case CONST_INT:
                    840:     case CONST:
                    841:     case PC:
                    842:     case CC0:
                    843:     case LABEL_REF:
                    844:     case SYMBOL_REF:
                    845:       return 0;
                    846:     }
                    847: 
                    848:   fmt = GET_RTX_FORMAT (GET_CODE (x));
                    849:   for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
                    850:     {
                    851:       if (fmt[i] == 'e')
                    852:        {
                    853:          if (uses_local_reg_p (XEXP (x, i)))
                    854:            return 1;
                    855:        }
                    856:       else if (fmt[i] == 'E')
                    857:        {
                    858:          for (j = XVECLEN (x, i) - 1; j >= 0; j--)
                    859:            if (uses_local_reg_p (XVECEXP (x, i, j)))
                    860:              return 1;
                    861:        }
                    862:     }
                    863: 
                    864:   return 0;
                    865: }
                    866: 
                    867: /* Returns 1 if this function is known to have a null epilogue.  */
                    868: 
                    869: int
                    870: null_epilogue ()
                    871: {
                    872:   return (reload_completed && ! needs_regstack_p ()
                    873:          && get_frame_size () == 0
                    874:          && current_function_pretend_args_size == 0);
                    875: }
                    876: 
                    877: /* Write out the assembler form of an operand.  Recognize the following
                    878:    special options:
                    879: 
                    880:        %N means write the low-order 8 bits of the negative of the constant
                    881:        %Q means write a QImode operand (truncate constants to 8 bits)
                    882:        %M means write the low-order 16 bits of the constant
1.1.1.3 ! root      883:        %m means write the low-order 16 bits shifted left 16 bits
1.1       root      884:        %C means write the low-order 8 bits of the complement of the constant
                    885:        %b means write `f' is this is a reversed condition, `t' otherwise
                    886:        %B means write `t' is this is a reversed condition, `f' otherwise
                    887:        %J means write the 29k opcode part for a comparison operation
                    888:        %e means write the label with an extra `X' is this is the epilogue
                    889:                       otherwise the normal label name
                    890:        %E means write nothing if this insn has a delay slot,
                    891:                       a nop unless this is the epilogue label, in which case
                    892:                       write the first epilogue insn
                    893:        %F means write just the normal operand if the insn has a delay slot;
                    894:                       otherwise, this is a recursive call so output the
                    895:                       symbol + 4 and write the first prologue insn in the
                    896:                       delay slot.
                    897:        %L means write the register number plus one ("low order" register)
                    898:                       or the low-order part of a multi-word constant
                    899:        %O means write the register number plus two
                    900:        %P means write the register number plus three ("low order" of TImode)
                    901:        %S means write the number of words in the mode of the operand,
                    902:                       minus one (for CR)
                    903:         %V means write the number of elements in a PARALLEL minus 1
                    904:        %# means write nothing if we have a delay slot, "\n\tnop" otherwise
                    905:        %* means write the register name for TPC.  */
                    906: 
                    907: void
                    908: print_operand (file, x, code)
                    909:      FILE *file;
                    910:      rtx x;
                    911:      char code;
                    912: {
                    913:   char buf[100];
                    914: 
                    915:   /* These macros test for integers and extract the low-order bits.  */
                    916: #define INT_P(X)  \
                    917: ((GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST_DOUBLE)   \
                    918:  && GET_MODE (X) == VOIDmode)
                    919: 
                    920: #define INT_LOWPART(X) \
                    921:   (GET_CODE (X) == CONST_INT ? INTVAL (X) : CONST_DOUBLE_LOW (X))
                    922: 
                    923:   switch (code)
                    924:     {
                    925:     case 'Q':
                    926:       if (GET_CODE (x) == REG)
                    927:        break;
                    928:       else if (! INT_P (x))
                    929:        output_operand_lossage ("invalid %%Q value");
                    930:       fprintf (file, "%d", INT_LOWPART (x) & 0xff);
                    931:       return;
                    932: 
                    933:     case 'C':
                    934:       if (! INT_P (x))
                    935:        output_operand_lossage ("invalid %%C value");
                    936:       fprintf (file, "%d", (~ INT_LOWPART (x)) & 0xff);
                    937:       return;
                    938: 
                    939:     case 'N':
                    940:       if (! INT_P (x))
                    941:        output_operand_lossage ("invalid %%N value");
                    942:       fprintf (file, "%d", (- INT_LOWPART (x)) & 0xff);
                    943:       return;
                    944: 
                    945:     case 'M':
                    946:       if (! INT_P (x))
                    947:        output_operand_lossage ("invalid %%M value");
                    948:       fprintf (file, "%d", INT_LOWPART (x) & 0xffff);
                    949:       return;
                    950: 
1.1.1.3 ! root      951:     case 'm':
        !           952:       if (! INT_P (x))
        !           953:        output_operand_lossage ("invalid %%m value");
        !           954:       fprintf (file, "%d", (INT_LOWPART (x) & 0xffff) << 16);
1.1       root      955:       return;
1.1.1.3 ! root      956: 
1.1       root      957:     case 'b':
                    958:       if (GET_CODE (x) == GE)
                    959:        fprintf (file, "f");
                    960:       else
                    961:        fprintf (file, "t");
                    962:       return;
                    963: 
                    964:     case 'B':
                    965:       if (GET_CODE (x) == GE)
                    966:        fprintf (file, "t");
                    967:       else
                    968:        fprintf (file, "f");
                    969:       return;
                    970: 
                    971:     case 'J':
                    972:       /* It so happens that the RTX names for the conditions are the same as
                    973:         the 29k's insns except for "ne", which requires "neq".  */
                    974:       fprintf (file, GET_RTX_NAME (GET_CODE (x)));
                    975:       if (GET_CODE (x) == NE)
                    976:        fprintf (file, "q");
                    977:       return;
                    978: 
                    979:     case 'e':
                    980:       if (optimize && flag_delayed_branch
                    981:          && a29k_last_prologue_insn == 0 && epilogue_operand (x, VOIDmode)
                    982:          && dbr_sequence_length () == 0)
                    983:        {
                    984:          /* We need to output the label number of the last label in the
                    985:             function, which is not necessarily X since there might be
                    986:             a USE insn in between.  First go forward to the last insn, then
                    987:             back up to a label.  */
                    988:          while (NEXT_INSN (x) != 0)
                    989:            x = NEXT_INSN (x);
                    990: 
                    991:          while (GET_CODE (x) != CODE_LABEL)
                    992:            x = PREV_INSN (x);
                    993: 
                    994:          ASM_GENERATE_INTERNAL_LABEL (buf, "LX", CODE_LABEL_NUMBER (x));
                    995:          assemble_name (file, buf);
                    996:        }
                    997:       else
                    998:        output_asm_label (x);
                    999:       return;
                   1000: 
                   1001:     case 'E':
                   1002:       if (dbr_sequence_length ())
                   1003:        ;
                   1004:       else if (a29k_last_prologue_insn)
                   1005:        {
                   1006:          fprintf (file, "\n\t%s", a29k_last_prologue_insn);
                   1007:          a29k_last_prologue_insn = 0;
                   1008:        }
                   1009:       else if (optimize && flag_delayed_branch
                   1010:               && epilogue_operand (x, VOIDmode))
                   1011:        {
                   1012:          fprintf (file, "\n\t%s", a29k_first_epilogue_insn);
                   1013:          a29k_first_epilogue_insn_used = 1;
                   1014:        }
                   1015:       else
                   1016:        fprintf (file, "\n\tnop");
                   1017:       return;
                   1018:       
                   1019:     case 'F':
                   1020:       output_addr_const (file, x);
1.1.1.2   root     1021:       if (dbr_sequence_length () == 0)
                   1022:        {
1.1.1.3 ! root     1023:          if (GET_CODE (x) == SYMBOL_REF
        !          1024:              && ! strcmp (XSTR (x, 0), current_function_name))
1.1.1.2   root     1025:            fprintf (file, "+4\n\t%s,%d",
                   1026:                     a29k_regstack_size >= 64 ? "const gr121" : "sub gr1,gr1",
                   1027:                     a29k_regstack_size * 4);
                   1028:          else
                   1029:            fprintf (file, "\n\tnop");
                   1030:        }
1.1       root     1031:       return;
                   1032: 
                   1033:     case 'L':
                   1034:       if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode)
                   1035:        {
                   1036:          union real_extract u;
                   1037: 
                   1038:          bcopy (&CONST_DOUBLE_LOW (x), &u, sizeof u);
                   1039:          fprintf (file, "$double1(%.20e)", u.d);
                   1040:        }
                   1041:       else if (GET_CODE (x) == REG)
                   1042:        fprintf (file, "%s", reg_names[REGNO (x) + 1]);
                   1043:       else
                   1044:        output_operand_lossage ("invalid %%L value");
                   1045:       return;
                   1046: 
                   1047:     case 'O':
                   1048:       if (GET_CODE (x) != REG)
                   1049:        output_operand_lossage ("invalid %%O value");
                   1050:       fprintf (file, "%s", reg_names[REGNO (x) + 2]);
                   1051:       return;
                   1052: 
                   1053:     case 'P':
                   1054:       if (GET_CODE (x) != REG)
                   1055:        output_operand_lossage ("invalid %%P value");
                   1056:       fprintf (file, "%s", reg_names[REGNO (x) + 3]);
                   1057:       return;
                   1058: 
                   1059:     case 'S':
                   1060:       fprintf (file, "%d", (GET_MODE_SIZE (GET_MODE (x)) / UNITS_PER_WORD)-1);
                   1061:       return;
                   1062: 
                   1063:     case 'V':
                   1064:       if (GET_CODE (x) != PARALLEL)
                   1065:        output_operand_lossage ("invalid %%V value");
                   1066:       fprintf (file, "%d", XVECLEN (x, 0) - 2);
                   1067:       return;
                   1068: 
                   1069:     case '#':
                   1070:       if (dbr_sequence_length () == 0)
                   1071:        {
                   1072:          if (a29k_last_prologue_insn)
                   1073:            {
                   1074:              fprintf (file, "\n\t%s", a29k_last_prologue_insn);
                   1075:              a29k_last_prologue_insn = 0;
                   1076:            }
                   1077:          else
                   1078:            fprintf (file, "\n\tnop");
                   1079:        }
                   1080:       return;
                   1081: 
                   1082:     case '*':
                   1083:       fprintf (file, "%s", reg_names [R_TPC]);
                   1084:       return;
                   1085:     }
                   1086: 
                   1087:   if (GET_CODE (x) == REG)
                   1088:     fprintf (file, "%s", reg_names [REGNO (x)]);
                   1089: 
                   1090:   else if (GET_CODE (x) == MEM)
                   1091:     output_address (XEXP (x, 0));
                   1092: 
                   1093:   else if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == SUBREG
                   1094:           && GET_CODE (SUBREG_REG (XEXP (x, 0))) == CONST_DOUBLE)
                   1095:     {
                   1096:       union real_extract u;
                   1097: 
                   1098:       if (GET_MODE (SUBREG_REG (XEXP (x, 0))) == SFmode)
                   1099:        fprintf (file, "$float");
                   1100:       else
                   1101:        fprintf (file, "$double%d", SUBREG_WORD (XEXP (x, 0)));
                   1102:       bcopy (&CONST_DOUBLE_LOW (SUBREG_REG (XEXP (x, 0))), &u, sizeof u);
                   1103:       fprintf (file, "(%.20e)", u.d);
                   1104:     }
                   1105: 
                   1106:   else if (GET_CODE (x) == CONST_DOUBLE
                   1107:           && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
                   1108:     {
                   1109:       union real_extract u;
                   1110: 
                   1111:       bcopy (&CONST_DOUBLE_LOW (x), &u, sizeof u);
                   1112:       fprintf (file, "$%s(%.20e)",
                   1113:               GET_MODE (x) == SFmode ? "float" : "double0", u.d);
                   1114:     }
                   1115: 
                   1116:   else
                   1117:     output_addr_const (file, x);
                   1118: }
                   1119: 
                   1120: /* This page contains routines to output function prolog and epilog code. */
                   1121: 
                   1122: /* Output function prolog code to file FILE.  Memory stack size is SIZE.
                   1123: 
                   1124:    Also sets register names for incoming arguments and frame pointer.  */
                   1125: 
                   1126: void
                   1127: output_prolog (file, size)
                   1128:      FILE *file;
                   1129:      int size;
                   1130: {
                   1131:   int makes_calls = 0;
                   1132:   int arg_count = 0;
                   1133:   rtx insn;
                   1134:   int i;
                   1135:   unsigned int tag_word;
                   1136: 
                   1137:   /* See if we make any calls.  We need to set lr1 if so.  */
                   1138:   for (insn = get_insns (); insn; insn = next_insn (insn))
                   1139:     if (GET_CODE (insn) == CALL_INSN
                   1140:        || (GET_CODE (insn) == INSN
                   1141:            && GET_CODE (PATTERN (insn)) == SEQUENCE
                   1142:            && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == CALL_INSN))
                   1143:       {
                   1144:        makes_calls = 1;
                   1145:        break;
                   1146:       }
                   1147: 
                   1148:   /* Find the highest local register used.  */
                   1149:   for (i = R_LR (127); i >= R_LR (0); i--)
                   1150:     if (regs_ever_live[i])
                   1151:       break;
                   1152: 
                   1153:   a29k_regstack_size = i - (R_LR (0) - 1);
                   1154: 
                   1155:   /* If calling routines, ensure we count lr0 & lr1.  */
                   1156:   if (makes_calls && a29k_regstack_size < 2)
                   1157:     a29k_regstack_size = 2;
                   1158: 
                   1159:   /* Count frame pointer and align to 8 byte boundary (even number of
                   1160:      registers).  */
                   1161:   a29k_regstack_size += frame_pointer_needed;
                   1162:   if (a29k_regstack_size & 1) a29k_regstack_size++;
                   1163: 
                   1164:   /* See how many incoming arguments we have in registers.  */
                   1165:   for (i = R_AR (0); i < R_AR (16); i++)
                   1166:     if (! fixed_regs[i])
                   1167:       arg_count++;
                   1168: 
                   1169:   /* The argument count includes the caller's lr0 and lr1.  */
                   1170:   arg_count += 2;
                   1171: 
                   1172:   /* Set the names and numbers of the frame pointer and incoming argument
                   1173:      registers.  */
                   1174: 
                   1175:   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
                   1176:     a29k_debug_reg_map[i] = i;
                   1177: 
                   1178:   reg_names[FRAME_POINTER_REGNUM] = reg_names[R_LR (a29k_regstack_size - 1)];
                   1179:   a29k_debug_reg_map[FRAME_POINTER_REGNUM] = R_LR (a29k_regstack_size - 1);
                   1180: 
                   1181:   for (i = 0; i < 16; i++)
                   1182:     {
                   1183:       reg_names[R_AR (i)] = reg_names[R_LR (a29k_regstack_size + i + 2)];
                   1184:       a29k_debug_reg_map[R_AR (i)] = R_LR (a29k_regstack_size + i + 2);
                   1185:     }
                   1186: 
                   1187:   /* Compute memory stack size.  Add in number of bytes that the we should
                   1188:      push and pretend the caller did and the size of outgoing arguments.
                   1189:      Then round to a doubleword boundary.  */
                   1190:   size += (current_function_pretend_args_size
                   1191:           + current_function_outgoing_args_size);
                   1192:   size = (size + 7) & ~7;
                   1193: 
                   1194:   /* Write header words.  See if one or two word form.  */
                   1195:   tag_word = (frame_pointer_needed ? 0x400000 : 0) + (arg_count << 16);
                   1196: 
                   1197:   if (size / 8 > 0xff)
                   1198:     fprintf (file, "\t.word %d, 0x%0x\n", (size / 8) << 2,
                   1199:             0x800000 + tag_word);
                   1200:   else
                   1201:     fprintf (file, "\t.word 0x%0x\n", tag_word + ((size / 8) << 3));
                   1202: 
                   1203:   /* Define the function name.  */
                   1204:   assemble_name (file, a29k_function_name);
                   1205:   fprintf (file, ":\n");
                   1206: 
                   1207:   /* Push the register stack by the proper amount.  There are two possible
                   1208:      ways to do this.  */
                   1209:   if (a29k_regstack_size >= 256/4)
                   1210:     fprintf (file, "\tconst %s,%d\n\tsub gr1,gr1,%s\n",
                   1211:             reg_names[R_TAV], a29k_regstack_size * 4, reg_names[R_TAV]);
                   1212:   else if (a29k_regstack_size)
                   1213:     fprintf (file, "\tsub gr1,gr1,%d\n", a29k_regstack_size * 4);
                   1214: 
                   1215:   /* Test that the registers are available.  */
                   1216:   if (a29k_regstack_size)
                   1217:     fprintf (file, "\tasgeu V_%sSPILL,gr1,%s\n",
                   1218:             TARGET_KERNEL_REGISTERS ? "K" : "", reg_names[R_RAB]);
                   1219: 
                   1220:   /* Set up frame pointer, if one is needed.  */
                   1221:   if (frame_pointer_needed)
                   1222:     fprintf (file, "\tsll %s,%s,0\n", reg_names[FRAME_POINTER_REGNUM],
                   1223:             reg_names[R_MSP]);
                   1224: 
                   1225:   /* Make room for any frame space.  There are three ways to do this.  */
                   1226:   if (size >= 256)
                   1227:     {
                   1228:       fprintf (file, "\tconst %s,%d\n", reg_names[R_TAV], size);
                   1229:       if (size >= 65536)
                   1230:        fprintf (file, "\tconsth %s,%d\n", reg_names[R_TAV], size);
                   1231:       if (TARGET_STACK_CHECK)
                   1232:        fprintf (file, "\tcall %s,__msp_check\n", reg_names[R_TPC]);
                   1233:       fprintf (file, "\tsub %s,%s,%s\n",
                   1234:               reg_names[R_MSP], reg_names[R_MSP], reg_names[R_TAV]);
                   1235:     }
                   1236:   else if (size)
                   1237:     {
                   1238:       if (TARGET_STACK_CHECK)
                   1239:        fprintf (file, "\tcall %s,__msp_check\n", reg_names[R_TPC]);
                   1240:       fprintf (file, "\tsub %s,%s,%d\n",
                   1241:               reg_names[R_MSP], reg_names[R_MSP], size);
                   1242:     }
                   1243: 
                   1244:   /* If this routine will make calls, set lr1.  If we see an insn that
                   1245:      can use a delay slot before a call or jump, save this insn for that
                   1246:      slot (this condition is equivalent to seeing if we have an insn that
                   1247:      needs delay slots before an insn that has a filled delay slot).  */
                   1248:   a29k_last_prologue_insn = 0;
                   1249:   if (makes_calls)
                   1250:     {
                   1251:       i = (a29k_regstack_size + arg_count) * 4;
                   1252:       if (i >= 256)
                   1253:        fprintf (file, "\tconst %s,%d\n\tadd lr1,gr1,%s\n",
                   1254:                 reg_names[R_TAV], i, reg_names[R_TAV]);
                   1255:       else
                   1256:        {
                   1257:          if (optimize && flag_delayed_branch)
                   1258:            for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
                   1259:              {
                   1260:                if (GET_CODE (insn) == CODE_LABEL
                   1261:                    || (GET_CODE (insn) == INSN
                   1262:                        && GET_CODE (PATTERN (insn)) == SEQUENCE))
                   1263:                  break;
                   1264: 
                   1265:                if (GET_CODE (insn) == NOTE
                   1266:                    || (GET_CODE (insn) == INSN
                   1267:                        && (GET_CODE (PATTERN (insn)) == USE
                   1268:                            || GET_CODE (PATTERN (insn)) == CLOBBER)))
                   1269:                  continue;
                   1270: 
                   1271:                if (num_delay_slots (insn) > 0)
                   1272:                  {
                   1273:                    a29k_last_prologue_insn = (char *) oballoc (100);
                   1274:                    sprintf (a29k_last_prologue_insn, "add lr1,gr1,%d", i);
                   1275:                    break;
                   1276:                  }
                   1277:              }
                   1278: 
                   1279:          if (a29k_last_prologue_insn == 0)
                   1280:            fprintf (file, "\tadd lr1,gr1,%d\n", i);
                   1281:        }
                   1282:     }
                   1283: 
                   1284:   /* Compute the first insn of the epilogue.  */
                   1285:   a29k_first_epilogue_insn_used = 0;
                   1286: 
                   1287:   if (size == 0 && a29k_regstack_size == 0 && ! frame_pointer_needed)
                   1288:     a29k_first_epilogue_insn = 0;
                   1289:   else
                   1290:     a29k_first_epilogue_insn = (char *) oballoc (100);
                   1291: 
                   1292:   if (frame_pointer_needed)
                   1293:     sprintf (a29k_first_epilogue_insn, "sll %s,%s,0",
                   1294:             reg_names[R_MSP], reg_names[FRAME_POINTER_REGNUM]);
                   1295:   else if (a29k_regstack_size)
                   1296:     {
                   1297:       if (a29k_regstack_size >= 256 / 4)
                   1298:        sprintf (a29k_first_epilogue_insn, "const %s,%d",
                   1299:                 reg_names[R_TAV], a29k_regstack_size * 4);
                   1300:       else
                   1301:        sprintf (a29k_first_epilogue_insn, "add gr1,gr1,%d",
                   1302:                 a29k_regstack_size * 4);
                   1303:     }
                   1304:   else if (size)
                   1305:     {
                   1306:       if (size >= 256)
                   1307:        sprintf (a29k_first_epilogue_insn, "const %s,%d",
                   1308:                 reg_names[R_TAV], size);
                   1309:       else
                   1310:        sprintf (a29k_first_epilogue_insn, "add %s,%s,%d",
                   1311:                 reg_names[R_MSP], reg_names[R_MSP], size);
                   1312:     }
                   1313: }
                   1314: 
                   1315: /* Call this after writing what might be the first instruction of the
                   1316:    epilogue.  If that first insn was used in a delay slot, an intermediate
                   1317:    label is written.  */
                   1318: 
                   1319: static void
                   1320: check_epilogue_internal_label (file)
                   1321:      FILE *file;
                   1322: {
                   1323:   rtx insn;
                   1324: 
                   1325:   if (! a29k_first_epilogue_insn_used)
                   1326:     return;
                   1327: 
                   1328:   for (insn = get_last_insn ();
                   1329:        GET_CODE (insn) != CODE_LABEL;
                   1330:        insn = PREV_INSN (insn))
                   1331:     ;
                   1332: 
                   1333:   ASM_OUTPUT_INTERNAL_LABEL (file, "LX", CODE_LABEL_NUMBER (insn));
                   1334:   a29k_first_epilogue_insn_used = 0;
                   1335: }
                   1336: 
                   1337: /* Output the epilog of the last procedure to file FILE.  SIZE is the memory
                   1338:    stack size.  The register stack size is in the variable
                   1339:    A29K_REGSTACK_SIZE.  */
                   1340: 
                   1341: void
                   1342: output_epilog (file, size)
                   1343:      FILE *file;
                   1344:      int size;
                   1345: {
                   1346:   rtx insn;
                   1347:   int locals_unavailable = 0;  /* True until after first insn
                   1348:                                   after gr1 update. */
                   1349: 
                   1350:   /* If we hit a BARRIER before a real insn or CODE_LABEL, we don't
                   1351:      need to do anything because we are never jumped to.  */
                   1352:   insn = get_last_insn ();
                   1353:   if (GET_CODE (insn) == NOTE)
                   1354:     insn = prev_nonnote_insn (insn);
                   1355: 
                   1356:   if (insn && GET_CODE (insn) == BARRIER)
                   1357:     return;
                   1358: 
                   1359:   /* If a frame pointer was needed we must restore the memory stack pointer
                   1360:      before adjusting the register stack.  */
                   1361:   if (frame_pointer_needed)
                   1362:     {
                   1363:       fprintf (file, "\tsll %s,%s,0\n",
                   1364:               reg_names[R_MSP], reg_names[FRAME_POINTER_REGNUM]);
                   1365:       check_epilogue_internal_label (file);
                   1366:     }
                   1367: 
                   1368:   /* Restore the register stack.  There are two ways to do this.  */
                   1369:   if (a29k_regstack_size)
                   1370:     {
                   1371:       if (a29k_regstack_size >= 256/4)
                   1372:        {
                   1373:          fprintf (file, "\tconst %s,%d\n",
                   1374:                   reg_names[R_TAV], a29k_regstack_size * 4);
                   1375:          check_epilogue_internal_label (file);
                   1376:          fprintf (file, "\tadd gr1,gr1,%s\n", reg_names[R_TAV]);
                   1377:        }
                   1378:       else
                   1379:        {
                   1380:          fprintf (file, "\tadd gr1,gr1,%d\n", a29k_regstack_size * 4);
                   1381:          check_epilogue_internal_label (file);
                   1382:        }
                   1383:       locals_unavailable = 1;
                   1384:     }
                   1385: 
                   1386:   /* Restore the memory stack pointer if there is no frame pointer.
                   1387:      Adjust the size to include any pretend arguments and pushed
                   1388:      arguments and round to doubleword boundary.  */
                   1389:   size += (current_function_pretend_args_size
                   1390:           + current_function_outgoing_args_size);
                   1391:   size = (size + 7) & ~7;
                   1392: 
                   1393:   if (size && ! frame_pointer_needed)
                   1394:     {
                   1395:       if (size >= 256)
                   1396:        {
                   1397:          fprintf (file, "\tconst %s,%d\n", reg_names[R_TAV], size);
                   1398:          check_epilogue_internal_label (file);
                   1399:          locals_unavailable = 0;
                   1400:          if (size >= 65536)
                   1401:            fprintf (file, "\tconsth %s,%d\n", reg_names[R_TAV], size);
                   1402:          fprintf (file, "\tadd %s,%s,%s\n",
                   1403:                   reg_names[R_MSP], reg_names[R_MSP], reg_names[R_TAV]);
                   1404:        }
                   1405:       else
                   1406:        {
                   1407:          fprintf (file, "\tadd %s,%s,%d\n",
                   1408:                   reg_names[R_MSP], reg_names[R_MSP], size);
                   1409:          check_epilogue_internal_label (file);
                   1410:          locals_unavailable = 0;
                   1411:        }
                   1412:     }
                   1413: 
                   1414:   if (locals_unavailable)
                   1415:     {
                   1416:       /* If we have an insn for this delay slot, write it.  */
                   1417:       if (current_function_epilogue_delay_list)
                   1418:        final_scan_insn (XEXP (current_function_epilogue_delay_list, 0),
                   1419:                         file, 1, -2, 1);
                   1420:       else
                   1421:        fprintf (file, "\tnop\n");
                   1422:     }
                   1423: 
                   1424:   fprintf (file, "\tjmpi lr0\n");
                   1425:   if (a29k_regstack_size)
                   1426:     fprintf (file, "\tasleu V_%sFILL,lr1,%s\n",
                   1427:             TARGET_KERNEL_REGISTERS ? "K" : "", reg_names[R_RFB]);
                   1428:   else if (current_function_epilogue_delay_list)
                   1429:     final_scan_insn (XEXP (current_function_epilogue_delay_list, 0),
                   1430:                     file, 1, -2, 1);
                   1431:   else
                   1432:     fprintf (file, "\tnop\n");
                   1433: }

unix.superglobalmegacorp.com

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