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

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

unix.superglobalmegacorp.com

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