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

1.1       root        1: /* Subroutines used for code generation on intel 80960.
1.1.1.4 ! root        2:    Copyright (C) 1992, 1995 Free Software Foundation, Inc.
1.1       root        3:    Contributed by Steven McGeady, Intel Corp.
                      4:    Additional Work by Glenn Colon-Bonet, Jonathan Shapiro, Andy Wilson
                      5:    Converted to GCC 2.0 by Jim Wilson and Michael Tiemann, Cygnus Support.
                      6: 
                      7: This file is part of GNU CC.
                      8: 
                      9: GNU CC is free software; you can redistribute it and/or modify
                     10: it under the terms of the GNU General Public License as published by
                     11: the Free Software Foundation; either version 2, or (at your option)
                     12: any later version.
                     13: 
                     14: GNU CC is distributed in the hope that it will be useful,
                     15: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     16: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     17: GNU General Public License for more details.
                     18: 
                     19: You should have received a copy of the GNU General Public License
                     20: along with GNU CC; see the file COPYING.  If not, write to
1.1.1.4 ! root       21: the Free Software Foundation, 59 Temple Place - Suite 330,
        !            22: Boston, MA 02111-1307, USA.  */
1.1       root       23: 
                     24: #include <stdio.h>
                     25: 
                     26: #include "config.h"
                     27: #include "rtl.h"
                     28: #include "regs.h"
                     29: #include "hard-reg-set.h"
                     30: #include "real.h"
                     31: #include "insn-config.h"
                     32: #include "conditions.h"
                     33: #include "insn-flags.h"
                     34: #include "output.h"
                     35: #include "insn-attr.h"
                     36: #include "flags.h"
                     37: #include "tree.h"
                     38: #include "insn-codes.h"
                     39: #include "assert.h"
                     40: #include "expr.h"
                     41: #include "function.h"
                     42: #include "recog.h"
                     43: #include <math.h>
                     44: 
                     45: /* Save the operands last given to a compare for use when we
                     46:    generate a scc or bcc insn.  */
                     47: 
                     48: rtx i960_compare_op0, i960_compare_op1;
                     49: 
                     50: /* Used to implement #pragma align/noalign.  Initialized by OVERRIDE_OPTIONS
                     51:    macro in i960.h.  */
                     52: 
                     53: static int i960_maxbitalignment;
                     54: static int i960_last_maxbitalignment;
                     55: 
                     56: /* Used to implement switching between MEM and ALU insn types, for better
                     57:    C series performance.  */
                     58: 
                     59: enum insn_types i960_last_insn_type;
                     60: 
                     61: /* The leaf-procedure return register.  Set only if this is a leaf routine.  */
                     62: 
                     63: static int i960_leaf_ret_reg;
                     64: 
                     65: /* True if replacing tail calls with jumps is OK.  */
                     66: 
                     67: static int tail_call_ok;
                     68: 
                     69: /* A string containing a list of insns to emit in the epilogue so as to
                     70:    restore all registers saved by the prologue.  Created by the prologue
                     71:    code as it saves registers away.  */
                     72: 
                     73: char epilogue_string[1000];
                     74: 
                     75: /* A unique number (per function) for return labels.  */
                     76: 
                     77: static int ret_label = 0;
                     78: 
1.1.1.3   root       79: /* This is true if FNDECL is either a varargs or a stdarg function.
                     80:    This is used to help identify functions that use an argument block.  */
                     81: 
                     82: #define VARARGS_STDARG_FUNCTION(FNDECL)        \
                     83: ((TYPE_ARG_TYPES (TREE_TYPE (FNDECL)) != 0                                                   \
                     84:   && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (TREE_TYPE (FNDECL)))) != void_type_node))    \
                     85:  || current_function_varargs)
                     86: 
1.1       root       87: /* Handle pragmas for compatibility with Intel's compilers.  */
                     88: 
                     89: /* ??? This is incomplete, since it does not handle all pragmas that the
1.1.1.4 ! root       90:    intel compilers understand.  */
1.1       root       91: 
                     92: void
1.1.1.4 ! root       93: process_pragma (finput)
        !            94:      FILE *finput;
1.1       root       95: {
1.1.1.4 ! root       96:   int c;
1.1       root       97:   int i;
                     98: 
1.1.1.4 ! root       99:   c = getc (finput);
        !           100:   while (c == ' ' || c == '\t')
        !           101:     c = getc (finput);
        !           102: 
        !           103:   if (c == 'a'
        !           104:       && getc (finput) == 'l'
        !           105:       && getc (finput) == 'i'
        !           106:       && getc (finput) == 'g'
        !           107:       && getc (finput) == 'n'
        !           108:       && ((c = getc (finput)) == ' ' || c == '\t' || c == '\n'))
        !           109:     {
        !           110:       char buf[20];
        !           111:       char *s = buf;
        !           112:       int align;
        !           113: 
        !           114:       while (c == ' ' || c == '\t')
        !           115:        c = getc (finput);
        !           116:       if (c == '(')
        !           117:        c = getc (finput);
        !           118:       while (c >= '0' && c <= '9')
        !           119:        {
        !           120:          if (s < buf + sizeof buf - 1)
        !           121:            *s++ = c;
        !           122:          c = getc (finput);
        !           123:        }
        !           124:       *s = '\0';
1.1       root      125: 
1.1.1.4 ! root      126:       align = atoi (buf);
        !           127:       switch (align)
        !           128:        {
        !           129:        case 0:
        !           130:          /* Return to last alignment.  */
        !           131:          align = i960_last_maxbitalignment / 8;
        !           132:          /* Fall through.  */
        !           133:        case 16:
        !           134:        case 8:
        !           135:        case 4:
        !           136:        case 2:
        !           137:        case 1:
        !           138:          i960_last_maxbitalignment = i960_maxbitalignment;
        !           139:          i960_maxbitalignment = align * 8;
        !           140:          break;
1.1       root      141: 
1.1.1.4 ! root      142:        default:
        !           143:          /* Silently ignore bad values.  */
        !           144:          break;
        !           145:        }
1.1       root      146: 
1.1.1.4 ! root      147:       /* NOTE: ic960 R3.0 pragma align definition:
1.1       root      148: 
1.1.1.4 ! root      149:         #pragma align [(size)] | (identifier=size[,...])
        !           150:         #pragma noalign [(identifier)[,...]]
1.1       root      151: 
1.1.1.4 ! root      152:         (all parens are optional)
1.1       root      153: 
1.1.1.4 ! root      154:         - size is [1,2,4,8,16]
        !           155:         - noalign means size==1
        !           156:         - applies only to component elements of a struct (and union?)
        !           157:         - identifier applies to structure tag (only)
        !           158:         - missing identifier means next struct
1.1       root      159: 
1.1.1.4 ! root      160:         - alignment rules for bitfields need more investigation  */
        !           161:     }
1.1       root      162: 
                    163:   /* Should be pragma 'far' or equivalent for callx/balx here.  */
1.1.1.4 ! root      164: 
        !           165:   ungetc (c, finput);
1.1       root      166: }
                    167: 
                    168: /* Initialize variables before compiling any files.  */
                    169: 
                    170: void
                    171: i960_initialize ()
                    172: {
                    173:   if (TARGET_IC_COMPAT2_0)
                    174:     {
                    175:       i960_maxbitalignment = 8;
                    176:       i960_last_maxbitalignment = 128;
                    177:     }
                    178:   else
                    179:     {
                    180:       i960_maxbitalignment = 128;
                    181:       i960_last_maxbitalignment = 8;
                    182:     }
                    183: }
                    184: 
                    185: /* Return true if OP can be used as the source of an fp move insn.  */
                    186: 
                    187: int
                    188: fpmove_src_operand (op, mode)
                    189:      rtx op;
                    190:      enum machine_mode mode;
                    191: {
                    192:   return (GET_CODE (op) == CONST_DOUBLE || general_operand (op, mode));
                    193: }
                    194: 
                    195: #if 0
                    196: /* Return true if OP is a register or zero.  */
                    197: 
                    198: int
                    199: reg_or_zero_operand (op, mode)
                    200:      rtx op;
                    201:      enum machine_mode mode;
                    202: {
                    203:   return register_operand (op, mode) || op == const0_rtx;
                    204: }
                    205: #endif
                    206: 
                    207: /* Return truth value of whether OP can be used as an operands in a three
                    208:    address arithmetic insn (such as add %o1,7,%l2) of mode MODE.  */
                    209: 
                    210: int
                    211: arith_operand (op, mode)
                    212:      rtx op;
                    213:      enum machine_mode mode;
                    214: {
                    215:   return (register_operand (op, mode) || literal (op, mode));
                    216: }
                    217: 
                    218: /* Return true if OP is a register or a valid floating point literal.  */
                    219: 
                    220: int
                    221: fp_arith_operand (op, mode)
                    222:      rtx op;
                    223:      enum machine_mode mode;
                    224: {
                    225:   return (register_operand (op, mode) || fp_literal (op, mode));
                    226: }
                    227: 
                    228: /* Return true is OP is a register or a valid signed integer literal.  */
                    229: 
                    230: int
                    231: signed_arith_operand (op, mode)
                    232:      rtx op;
                    233:      enum machine_mode mode;
                    234: {
                    235:   return (register_operand (op, mode) || signed_literal (op, mode));
                    236: }
                    237: 
                    238: /* Return truth value of whether OP is a integer which fits the
                    239:    range constraining immediate operands in three-address insns.  */
                    240: 
                    241: int
                    242: literal (op, mode)
                    243:      rtx op;
                    244:      enum machine_mode mode;
                    245: {
                    246:   return ((GET_CODE (op) == CONST_INT) && INTVAL(op) >= 0 && INTVAL(op) < 32);
                    247: }
                    248: 
                    249: /* Return true if OP is a float constant of 1.  */
                    250: 
                    251: int
                    252: fp_literal_one (op, mode)
                    253:      rtx op;
                    254:      enum machine_mode mode;
                    255: {
1.1.1.4 ! root      256:   return (TARGET_NUMERICS && mode == GET_MODE (op) && op == CONST1_RTX (mode));
1.1       root      257: }
                    258: 
                    259: /* Return true if OP is a float constant of 0.  */
                    260: 
                    261: int
                    262: fp_literal_zero (op, mode)
                    263:      rtx op;
                    264:      enum machine_mode mode;
                    265: {
1.1.1.4 ! root      266:   return (TARGET_NUMERICS && mode == GET_MODE (op) && op == CONST0_RTX (mode));
1.1       root      267: }
                    268: 
                    269: /* Return true if OP is a valid floating point literal.  */
                    270: 
                    271: int
                    272: fp_literal(op, mode)
                    273:      rtx op;
                    274:      enum machine_mode mode;
                    275: {
                    276:   return fp_literal_zero (op, mode) || fp_literal_one (op, mode);
                    277: }
                    278: 
                    279: /* Return true if OP is a valid signed immediate constant.  */
                    280: 
                    281: int
                    282: signed_literal(op, mode)
                    283:      rtx op;
                    284:      enum machine_mode mode;
                    285: {
                    286:   return ((GET_CODE (op) == CONST_INT) && INTVAL(op) > -32 && INTVAL(op) < 32);
                    287: }
                    288: 
                    289: /* Return truth value of statement that OP is a symbolic memory
                    290:    operand of mode MODE.  */
                    291: 
                    292: int
                    293: symbolic_memory_operand (op, mode)
                    294:      rtx op;
                    295:      enum machine_mode mode;
                    296: {
                    297:   if (GET_CODE (op) == SUBREG)
                    298:     op = SUBREG_REG (op);
                    299:   if (GET_CODE (op) != MEM)
                    300:     return 0;
                    301:   op = XEXP (op, 0);
                    302:   return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST
                    303:          || GET_CODE (op) == HIGH || GET_CODE (op) == LABEL_REF);
                    304: }
                    305: 
                    306: /* Return truth value of whether OP is EQ or NE.  */
                    307: 
                    308: int
                    309: eq_or_neq (op, mode)
                    310:      rtx op;
                    311:      enum machine_mode mode;
                    312: {
                    313:   return (GET_CODE (op) == EQ || GET_CODE (op) == NE);
                    314: }
                    315: 
                    316: /* OP is an integer register or a constant.  */
                    317: 
                    318: int
                    319: arith32_operand (op, mode)
                    320:      rtx op;
                    321:      enum machine_mode mode;
                    322: {
                    323:   if (register_operand (op, mode))
                    324:     return 1;
                    325:   return (CONSTANT_P (op));
                    326: }
                    327: 
                    328: /* Return true if OP is an integer constant which is a power of 2.  */
                    329: 
                    330: int
                    331: power2_operand (op,mode)
                    332:      rtx op;
                    333:      enum machine_mode mode;
                    334: {
                    335:   if (GET_CODE (op) != CONST_INT)
                    336:     return 0;
                    337: 
                    338:   return exact_log2 (INTVAL (op)) >= 0;
                    339: }
                    340: 
                    341: /* Return true if OP is an integer constant which is the complement of a
                    342:    power of 2.  */
                    343: 
                    344: int
                    345: cmplpower2_operand (op, mode)
                    346:      rtx op;
                    347:      enum machine_mode mode;
                    348: {
                    349:   if (GET_CODE (op) != CONST_INT)
                    350:     return 0;
                    351: 
                    352:   return exact_log2 (~ INTVAL (op)) >= 0;
                    353: }
                    354: 
                    355: /* If VAL has only one bit set, return the index of that bit.  Otherwise
                    356:    return -1.  */
                    357: 
                    358: int
                    359: bitpos (val)
                    360:      unsigned int val;
                    361: {
                    362:   register int i;
                    363: 
                    364:   for (i = 0; val != 0; i++, val >>= 1)
                    365:     {
                    366:       if (val & 1)
                    367:        {
                    368:          if (val != 1)
                    369:            return -1;
                    370:          return i;
                    371:        }
                    372:     }
                    373:   return -1;
                    374: }
                    375: 
                    376: /* Return non-zero if OP is a mask, i.e. all one bits are consecutive.
                    377:    The return value indicates how many consecutive non-zero bits exist
                    378:    if this is a mask.  This is the same as the next function, except that
                    379:    it does not indicate what the start and stop bit positions are.  */
                    380: 
                    381: int
                    382: is_mask (val)
                    383:      unsigned int val;
                    384: {
                    385:   register int start, end, i;
                    386: 
                    387:   start = -1;
                    388:   for (i = 0; val != 0; val >>= 1, i++)
                    389:     {
                    390:       if (val & 1)
                    391:        {
                    392:          if (start < 0)
                    393:            start = i;
                    394: 
                    395:          end = i;
                    396:          continue;
                    397:        }
                    398:       /* Still looking for the first bit.  */
                    399:       if (start < 0)
                    400:        continue;
                    401: 
                    402:       /* We've seen the start of a bit sequence, and now a zero.  There
                    403:         must be more one bits, otherwise we would have exited the loop.
                    404:         Therefore, it is not a mask.  */
                    405:       if (val)
                    406:        return 0;
                    407:     }
                    408: 
                    409:   /* The bit string has ones from START to END bit positions only.  */
                    410:   return end - start + 1;
                    411: }
                    412: 
                    413: /* If VAL is a mask, then return nonzero, with S set to the starting bit
                    414:    position and E set to the ending bit position of the mask.  The return
                    415:    value indicates how many consecutive bits exist in the mask.  This is
                    416:    the same as the previous function, except that it also indicates the
                    417:    start and end bit positions of the mask.  */
                    418: 
                    419: int
                    420: bitstr (val, s, e)
                    421:      unsigned int val;
                    422:      int *s, *e;
                    423: {
                    424:   register int start, end, i;
                    425: 
                    426:   start = -1;
                    427:   end = -1;
                    428:   for (i = 0; val != 0; val >>= 1, i++)
                    429:     {
                    430:       if (val & 1)
                    431:        {
                    432:          if (start < 0)
                    433:            start = i;
                    434: 
                    435:          end = i;
                    436:          continue;
                    437:        }
                    438: 
                    439:       /* Still looking for the first bit.  */
                    440:       if (start < 0)
                    441:        continue;
                    442: 
                    443:       /* We've seen the start of a bit sequence, and now a zero.  There
                    444:         must be more one bits, otherwise we would have exited the loop.
                    445:         Therefor, it is not a mask.  */
                    446:       if (val)
                    447:        {
                    448:          start = -1;
                    449:          end = -1;
                    450:          break;
                    451:        }
                    452:     }
                    453: 
                    454:   /* The bit string has ones from START to END bit positions only.  */
                    455:   *s = start;
                    456:   *e = end;
                    457:   return ((start < 0) ? 0 : end - start + 1);
                    458: }
                    459: 
                    460: /* Return the machine mode to use for a comparison.  */
                    461: 
                    462: enum machine_mode
                    463: select_cc_mode (op, x)
                    464:      RTX_CODE op;
                    465:      rtx x;
                    466: {
                    467:   if (op == GTU || op == LTU || op == GEU || op == LEU)
                    468:     return CC_UNSmode;
                    469:   return CCmode;
                    470: }
                    471: 
                    472: /* X and Y are two things to compare using CODE.  Emit the compare insn and
                    473:    return the rtx for register 36 in the proper mode.  */
                    474: 
                    475: rtx
                    476: gen_compare_reg (code, x, y)
                    477:      enum rtx_code code;
                    478:      rtx x, y;
                    479: {
                    480:   rtx cc_reg;
                    481:   enum machine_mode ccmode = SELECT_CC_MODE (code, x, y);
                    482:   enum machine_mode mode
                    483:     = GET_MODE (x) == VOIDmode ? GET_MODE (y) : GET_MODE (x);
                    484: 
                    485:   if (mode == SImode)
                    486:     {
                    487:       if (! arith_operand (x, mode))
                    488:        x = force_reg (SImode, x);
                    489:       if (! arith_operand (y, mode))
                    490:        y = force_reg (SImode, y);
                    491:     }
                    492: 
                    493:   cc_reg = gen_rtx (REG, ccmode, 36);
                    494:   emit_insn (gen_rtx (SET, VOIDmode, cc_reg,
                    495:                      gen_rtx (COMPARE, ccmode, x, y)));
                    496: 
                    497:   return cc_reg;
                    498: }
                    499: 
                    500: /* For the i960, REG is cost 1, REG+immed CONST is cost 2, REG+REG is cost 2,
                    501:    REG+nonimmed CONST is cost 4.  REG+SYMBOL_REF, SYMBOL_REF, and similar
                    502:    are 4.  Indexed addresses are cost 6.  */
                    503: 
                    504: /* ??? Try using just RTX_COST, i.e. not defining ADDRESS_COST.  */
                    505: 
                    506: int
                    507: i960_address_cost (x)
                    508:      rtx x;
                    509: {
                    510: #if 0
                    511:   /* Handled before calling here.  */
                    512:   if (GET_CODE (x) == REG)
                    513:     return 1;
                    514: #endif
                    515:   if (GET_CODE (x) == PLUS)
                    516:     {
                    517:       rtx base = XEXP (x, 0);
                    518:       rtx offset = XEXP (x, 1);
                    519: 
                    520:       if (GET_CODE (base) == SUBREG)
                    521:        base = SUBREG_REG (base);
                    522:       if (GET_CODE (offset) == SUBREG)
                    523:        offset = SUBREG_REG (offset);
                    524: 
                    525:       if (GET_CODE (base) == REG)
                    526:        {
                    527:          if (GET_CODE (offset) == REG)
                    528:            return 2;
                    529:          if (GET_CODE (offset) == CONST_INT)
                    530:            {
                    531:              if ((unsigned)INTVAL (offset) < 2047)
                    532:                return 2;
                    533:              return 4;
                    534:            }
                    535:          if (CONSTANT_P (offset))
                    536:            return 4;
                    537:        }
                    538:       if (GET_CODE (base) == PLUS || GET_CODE (base) == MULT)
                    539:        return 6;
                    540: 
                    541:       /* This is an invalid address.  The return value doesn't matter, but
                    542:         for convenience we make this more expensive than anything else.  */
                    543:       return 12;
                    544:     }
                    545:   if (GET_CODE (x) == MULT)
                    546:     return 6;
                    547: 
                    548:   /* Symbol_refs and other unrecognized addresses are cost 4.  */
                    549:   return 4;
                    550: }
                    551: 
                    552: /* Emit insns to move operands[1] into operands[0].
                    553: 
                    554:    Return 1 if we have written out everything that needs to be done to
                    555:    do the move.  Otherwise, return 0 and the caller will emit the move
                    556:    normally.  */
                    557: 
                    558: int
                    559: emit_move_sequence (operands, mode)
                    560:      rtx *operands;
                    561:      enum machine_mode mode;
                    562: {
                    563:   /* We can only store registers to memory.  */
                    564: 
1.1.1.4 ! root      565:   if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) != REG)
        !           566:     operands[1] = force_reg (mode, operands[1]);
        !           567: 
        !           568:   /* Storing multi-word values in unaligned hard registers to memory may
        !           569:      require a scratch since we have to store them a register at a time and
        !           570:      adding 4 to the memory address may not yield a valid insn.  */
        !           571:   /* ??? We don't always need the scratch, but that would complicate things.
        !           572:      Maybe later.  */
        !           573:   if (GET_MODE_SIZE (mode) > UNITS_PER_WORD
        !           574:       && GET_CODE (operands[0]) == MEM
        !           575:       && GET_CODE (operands[1]) == REG
        !           576:       && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER
        !           577:       && ! HARD_REGNO_MODE_OK (REGNO (operands[1]), mode))
        !           578:     {
        !           579:       emit_insn (gen_rtx (PARALLEL, VOIDmode,
        !           580:                          gen_rtvec (2,
        !           581:                                     gen_rtx (SET, VOIDmode,
        !           582:                                              operands[0], operands[1]),
        !           583:                                     gen_rtx (CLOBBER, VOIDmode,
        !           584:                                              gen_rtx (SCRATCH, Pmode)))));
        !           585:       return 1;
        !           586:     }
1.1       root      587: 
                    588:   return 0;
                    589: }
1.1.1.4 ! root      590: 
        !           591: /* Output assembler to move a double word value.  */
        !           592: 
        !           593: char *
        !           594: i960_output_move_double (dst, src)
        !           595:      rtx dst, src;
        !           596: {
        !           597:   rtx operands[5];
        !           598: 
        !           599:   if (GET_CODE (dst) == REG
        !           600:       && GET_CODE (src) == REG)
        !           601:     {
        !           602:       if ((REGNO (src) & 1)
        !           603:          || (REGNO (dst) & 1))
        !           604:        {
        !           605:          /* We normally copy the low-numbered register first.  However, if
        !           606:             the second source register is the same as the first destination
        !           607:             register, we must copy in the opposite order.  */
        !           608:          if (REGNO (src) + 1 == REGNO (dst))
        !           609:            return "mov %D1,%D0\n\tmov  %1,%0";
        !           610:          else
        !           611:            return "mov %1,%0\n\tmov    %D1,%D0";
        !           612:        }
        !           613:       else
        !           614:        return "movl    %1,%0";
        !           615:     }
        !           616:   else if (GET_CODE (dst) == REG
        !           617:           && GET_CODE (src) == CONST_INT
        !           618:           && CONST_OK_FOR_LETTER_P (INTVAL (src), 'I'))
        !           619:     {
        !           620:       if (REGNO (dst) & 1)
        !           621:        return "mov     %1,%0\n\tmov    0,%D0";
        !           622:       else
        !           623:        return "movl    %1,%0";
        !           624:     }
        !           625:   else if (GET_CODE (dst) == REG
        !           626:           && GET_CODE (src) == MEM)
        !           627:     {
        !           628:       if (REGNO (dst) & 1)
        !           629:        {
        !           630:          /* One can optimize a few cases here, but you have to be
        !           631:             careful of clobbering registers used in the address and
        !           632:             edge conditions.  */
        !           633:          operands[0] = dst;
        !           634:          operands[1] = src;
        !           635:          operands[2] = gen_rtx (REG, Pmode, REGNO (dst) + 1);
        !           636:          operands[3] = gen_rtx (MEM, word_mode, operands[2]);
        !           637:          operands[4] = adj_offsettable_operand (operands[3], UNITS_PER_WORD);
        !           638:          output_asm_insn ("lda %1,%2\n\tld     %3,%0\n\tld     %4,%D0", operands);
        !           639:          return "";
        !           640:        }
        !           641:       else
        !           642:        return "ldl     %1,%0";
        !           643:     }
        !           644:   else if (GET_CODE (dst) == MEM
        !           645:           && GET_CODE (src) == REG)
        !           646:     {
        !           647:       if (REGNO (src) & 1)
        !           648:        {
        !           649:          /* This is handled by emit_move_sequence so we shouldn't get here.  */
        !           650:          abort ();
        !           651:        }
        !           652:       return "stl      %1,%0";
        !           653:     }
        !           654:   else
        !           655:     abort ();
        !           656: }
        !           657: 
        !           658: /* Output assembler to move a quad word value.  */
        !           659: 
        !           660: char *
        !           661: i960_output_move_quad (dst, src)
        !           662:      rtx dst, src;
        !           663: {
        !           664:   rtx operands[7];
        !           665: 
        !           666:   if (GET_CODE (dst) == REG
        !           667:       && GET_CODE (src) == REG)
        !           668:     {
        !           669:       if ((REGNO (src) & 3)
        !           670:          || (REGNO (dst) & 3))
        !           671:        {
        !           672:          /* We normally copy starting with the low numbered register.
        !           673:             However, if there is an overlap such that the first dest reg
        !           674:             is <= the last source reg but not < the first source reg, we
        !           675:             must copy in the opposite order.  */
        !           676:          if (REGNO (dst) <= REGNO (src) + 3
        !           677:              && REGNO (dst) >= REGNO (src))
        !           678:            return "mov %F1,%F0\n\tmov  %E1,%E0\n\tmov  %D1,%D0\n\tmov  %1,%0";
        !           679:          else
        !           680:            return "mov %1,%0\n\tmov    %D1,%D0\n\tmov  %E1,%E0\n\tmov  %F1,%F0";
        !           681:        }
        !           682:       else
        !           683:        return "movq    %1,%0";
        !           684:     }
        !           685:   else if (GET_CODE (dst) == REG
        !           686:           && GET_CODE (src) == CONST_INT
        !           687:           && CONST_OK_FOR_LETTER_P (INTVAL (src), 'I'))
        !           688:     {
        !           689:       if (REGNO (dst) & 3)
        !           690:        return "mov     %1,%0\n\tmov    0,%D0\n\tmov    0,%E0\n\tmov    0,%F0";
        !           691:       else
        !           692:        return "movq    %1,%0";
        !           693:     }
        !           694:   else if (GET_CODE (dst) == REG
        !           695:           && GET_CODE (src) == MEM)
        !           696:     {
        !           697:       if (REGNO (dst) & 3)
        !           698:        {
        !           699:          /* One can optimize a few cases here, but you have to be
        !           700:             careful of clobbering registers used in the address and
        !           701:             edge conditions.  */
        !           702:          operands[0] = dst;
        !           703:          operands[1] = src;
        !           704:          operands[2] = gen_rtx (REG, Pmode, REGNO (dst) + 3);
        !           705:          operands[3] = gen_rtx (MEM, word_mode, operands[2]);
        !           706:          operands[4] = adj_offsettable_operand (operands[3], UNITS_PER_WORD);
        !           707:          operands[5] = adj_offsettable_operand (operands[4], UNITS_PER_WORD);
        !           708:          operands[6] = adj_offsettable_operand (operands[5], UNITS_PER_WORD);
        !           709:          output_asm_insn ("lda %1,%2\n\tld     %3,%0\n\tld     %4,%D0\n\tld    %5,%E0\n\tld    %6,%F0", operands);
        !           710:          return "";
        !           711:        }
        !           712:       else
        !           713:        return "ldq     %1,%0";
        !           714:     }
        !           715:   else if (GET_CODE (dst) == MEM
        !           716:           && GET_CODE (src) == REG)
        !           717:     {
        !           718:       if (REGNO (src) & 3)
        !           719:        {
        !           720:          /* This is handled by emit_move_sequence so we shouldn't get here.  */
        !           721:          abort ();
        !           722:        }
        !           723:       return "stq      %1,%0";
        !           724:     }
        !           725:   else
        !           726:     abort ();
        !           727: }
1.1       root      728: 
1.1.1.4 ! root      729: /* Emit insns to load a constant to non-floating point registers.
        !           730:    Uses several strategies to try to use as few insns as possible.  */
1.1       root      731: 
                    732: char *
                    733: i960_output_ldconst (dst, src)
                    734:      register rtx dst, src;
                    735: {
                    736:   register int rsrc1;
                    737:   register unsigned rsrc2;
                    738:   enum machine_mode mode = GET_MODE (dst);
                    739:   rtx operands[4];
                    740: 
                    741:   operands[0] = operands[2] = dst;
                    742:   operands[1] = operands[3] = src;
                    743: 
                    744:   /* Anything that isn't a compile time constant, such as a SYMBOL_REF,
                    745:      must be a ldconst insn.  */
                    746: 
                    747:   if (GET_CODE (src) != CONST_INT && GET_CODE (src) != CONST_DOUBLE)
                    748:     {
                    749:       output_asm_insn ("ldconst        %1,%0", operands);
                    750:       return "";
                    751:     }
1.1.1.4 ! root      752:   else if (mode == XFmode)
1.1       root      753:     {
1.1.1.4 ! root      754:       REAL_VALUE_TYPE d;
        !           755:       long value_long[3];
        !           756:       int i;
        !           757: 
        !           758:       if (fp_literal_zero (src, XFmode))
        !           759:        return "movt    0,%0";
1.1       root      760: 
1.1.1.4 ! root      761:       REAL_VALUE_FROM_CONST_DOUBLE (d, src);
        !           762:       REAL_VALUE_TO_TARGET_LONG_DOUBLE (d, value_long);
        !           763: 
        !           764:       output_asm_insn ("# ldconst      %1,%0",operands);
        !           765: 
        !           766:       for (i = 0; i < 3; i++)
1.1       root      767:        {
1.1.1.4 ! root      768:          operands[0] = gen_rtx (REG, SImode, REGNO (dst) + i);
        !           769:          operands[1] = GEN_INT (value_long[i]);
        !           770:          output_asm_insn (i960_output_ldconst (operands[0], operands[1]),
        !           771:                           operands);
1.1       root      772:        }
                    773: 
1.1.1.4 ! root      774:       return ""; 
        !           775:    }
        !           776:   else if (mode == DFmode)
        !           777:     {
        !           778:       rtx first, second;
        !           779: 
        !           780:       if (fp_literal_zero (src, DFmode))
        !           781:        return "movl    0,%0";
        !           782: 
1.1       root      783:       split_double (src, &first, &second);
                    784: 
                    785:       output_asm_insn ("# ldconst      %1,%0",operands);
                    786: 
                    787:       operands[0] = gen_rtx (REG, SImode, REGNO (dst));
                    788:       operands[1] = first;
                    789:       output_asm_insn (i960_output_ldconst (operands[0], operands[1]),
                    790:                      operands);
                    791:       operands[0] = gen_rtx (REG, SImode, REGNO (dst) + 1);
                    792:       operands[1] = second;
                    793:       output_asm_insn (i960_output_ldconst (operands[0], operands[1]),
                    794:                      operands);
                    795:       return "";
1.1.1.4 ! root      796:     }
        !           797:   else if (mode == SFmode)
        !           798:     {
        !           799:       REAL_VALUE_TYPE d;
        !           800:       long value;
        !           801: 
        !           802:       REAL_VALUE_FROM_CONST_DOUBLE (d, src);
        !           803:       REAL_VALUE_TO_TARGET_SINGLE (d, value);
        !           804: 
        !           805:       output_asm_insn ("# ldconst      %1,%0",operands);
        !           806:       operands[0] = gen_rtx (REG, SImode, REGNO (dst));
        !           807:       operands[1] = gen_rtx (CONST_INT, VOIDmode, value);
        !           808:       output_asm_insn (i960_output_ldconst (operands[0], operands[1]),
        !           809:                      operands);
        !           810:       return "";
1.1       root      811:     }
                    812:   else if (mode == TImode)
                    813:     {
                    814:       /* ??? This is currently not handled at all.  */
                    815:       abort ();
                    816: 
                    817:       /* Note: lowest order word goes in lowest numbered reg.  */
                    818:       rsrc1 = INTVAL (src);
                    819:       if (rsrc1 >= 0 && rsrc1 < 32)
                    820:        return "movq    %1,%0";
                    821:       else
                    822:        output_asm_insn ("movq\t0,%0\t# ldconstq %1,%0",operands);
                    823:       /* Go pick up the low-order word.  */
                    824:     }
                    825:   else if (mode == DImode)
                    826:     {
                    827:       rtx upperhalf, lowerhalf, xoperands[2];
                    828: 
1.1.1.4 ! root      829:       if (GET_CODE (src) == CONST_DOUBLE || GET_CODE (src) == CONST_INT)
        !           830:        split_double (src, &lowerhalf, &upperhalf);
        !           831: 
1.1       root      832:       else
                    833:        abort ();
                    834: 
                    835:       /* Note: lowest order word goes in lowest numbered reg.  */
                    836:       /* Numbers from 0 to 31 can be handled with a single insn.  */
                    837:       rsrc1 = INTVAL (lowerhalf);
                    838:       if (upperhalf == const0_rtx && rsrc1 >= 0 && rsrc1 < 32)
                    839:        return "movl    %1,%0";
                    840: 
                    841:       /* Output the upper half with a recursive call.  */
                    842:       xoperands[0] = gen_rtx (REG, SImode, REGNO (dst) + 1);
                    843:       xoperands[1] = upperhalf;
                    844:       output_asm_insn (i960_output_ldconst (xoperands[0], xoperands[1]),
                    845:                       xoperands);
                    846:       /* The lower word is emitted as normally.  */
                    847:     }
                    848:   else
                    849:     {
                    850:       rsrc1 = INTVAL (src);
                    851:       if (mode == QImode)
                    852:        {
                    853:          if (rsrc1 > 0xff)
                    854:            rsrc1 &= 0xff;
                    855:        }
                    856:       else if (mode == HImode)
                    857:        {
                    858:          if (rsrc1 > 0xffff)
                    859:            rsrc1 &= 0xffff;
                    860:        }
                    861:     }
                    862: 
                    863:   if (rsrc1 >= 0)
                    864:     {
                    865:       /* ldconst       0..31,X         ->      mov     0..31,X  */
                    866:       if (rsrc1 < 32)
                    867:        {
                    868:          if (i960_last_insn_type == I_TYPE_REG && TARGET_C_SERIES)
                    869:            return "lda %1,%0";
                    870:          return "mov   %1,%0";
                    871:        }
                    872: 
                    873:       /* ldconst       32..63,X        ->      add     31,nn,X  */
                    874:       if (rsrc1 < 63)
                    875:        {
                    876:          if (i960_last_insn_type == I_TYPE_REG && TARGET_C_SERIES)
                    877:            return "lda %1,%0";
                    878:          operands[1] = gen_rtx (CONST_INT, VOIDmode, rsrc1 - 31);
                    879:          output_asm_insn ("addo\t31,%1,%0\t# ldconst %3,%0", operands);
                    880:          return "";
                    881:        }
                    882:     }
                    883:   else if (rsrc1 < 0)
                    884:     {
                    885:       /* ldconst       -1..-31         ->      sub     0,0..31,X  */
                    886:       if (rsrc1 >= -31)
                    887:        {
                    888:          /* return 'sub -(%1),0,%0' */
                    889:          operands[1] = gen_rtx (CONST_INT, VOIDmode, - rsrc1);
                    890:          output_asm_insn ("subo\t%1,0,%0\t# ldconst %3,%0", operands);
                    891:          return "";
                    892:        }
                    893:       
                    894:       /* ldconst       -32             ->      not     31,X  */
                    895:       if (rsrc1 == -32)
                    896:        {
                    897:          operands[1] = gen_rtx (CONST_INT, VOIDmode, ~rsrc1);
                    898:          output_asm_insn ("not\t%1,%0  # ldconst %3,%0", operands);
                    899:          return "";
                    900:        }
                    901:     }
                    902: 
                    903:   /* If const is a single bit.  */
                    904:   if (bitpos (rsrc1) >= 0)
                    905:     {
                    906:       operands[1] = gen_rtx (CONST_INT, VOIDmode, bitpos (rsrc1));
                    907:       output_asm_insn ("setbit\t%1,0,%0\t# ldconst %3,%0", operands);
                    908:       return "";
                    909:     }
                    910: 
                    911:   /* If const is a bit string of less than 6 bits (1..31 shifted).  */
                    912:   if (is_mask (rsrc1))
                    913:     {
                    914:       int s, e;
                    915: 
                    916:       if (bitstr (rsrc1, &s, &e) < 6)
                    917:        {
                    918:          rsrc2 = ((unsigned int) rsrc1) >> s;
                    919:          operands[1] = gen_rtx (CONST_INT, VOIDmode, rsrc2);
                    920:          operands[2] = gen_rtx (CONST_INT, VOIDmode, s);
                    921:          output_asm_insn ("shlo\t%2,%1,%0\t# ldconst %3,%0", operands);
                    922:          return "";
                    923:        }
                    924:     }
                    925: 
                    926:   /* Unimplemented cases:
                    927:      const is in range 0..31 but rotated around end of word:
                    928:      ror       31,3,g0 -> ldconst 0xe0000003,g0
                    929:    
                    930:      and any 2 instruction cases that might be worthwhile  */
                    931:   
                    932:   output_asm_insn ("ldconst    %1,%0", operands);
                    933:   return "";
                    934: }
                    935: 
                    936: /* Determine if there is an opportunity for a bypass optimization.
                    937:    Bypass succeeds on the 960K* if the destination of the previous
                    938:    instruction is the second operand of the current instruction.
                    939:    Bypass always succeeds on the C*.
                    940:  
                    941:    Return 1 if the pattern should interchange the operands.
                    942: 
                    943:    CMPBR_FLAG is true if this is for a compare-and-branch insn.
                    944:    OP1 and OP2 are the two source operands of a 3 operand insn.  */
                    945: 
                    946: int
                    947: i960_bypass (insn, op1, op2, cmpbr_flag)
                    948:      register rtx insn, op1, op2;
                    949:      int cmpbr_flag;
                    950: {
                    951:   register rtx prev_insn, prev_dest;
                    952: 
                    953:   if (TARGET_C_SERIES)
                    954:     return 0;
                    955: 
                    956:   /* Can't do this if op1 isn't a register.  */
                    957:   if (! REG_P (op1))
                    958:     return 0;
                    959: 
                    960:   /* Can't do this for a compare-and-branch if both ops aren't regs.  */
                    961:   if (cmpbr_flag && ! REG_P (op2))
                    962:     return 0;
                    963: 
                    964:   prev_insn = prev_real_insn (insn);
                    965: 
                    966:   if (prev_insn && GET_CODE (prev_insn) == INSN
                    967:       && GET_CODE (PATTERN (prev_insn)) == SET)
                    968:     {
                    969:       prev_dest = SET_DEST (PATTERN (prev_insn));
                    970:       if ((GET_CODE (prev_dest) == REG && REGNO (prev_dest) == REGNO (op1))
                    971:          || (GET_CODE (prev_dest) == SUBREG
                    972:              && GET_CODE (SUBREG_REG (prev_dest)) == REG
                    973:              && REGNO (SUBREG_REG (prev_dest)) == REGNO (op1)))
                    974:        return 1;
                    975:     }
                    976:   return 0;
                    977: }
                    978: 
                    979: /* Output the code which declares the function name.  This also handles
                    980:    leaf routines, which have special requirements, and initializes some
                    981:    global variables.  */
                    982: 
                    983: void
                    984: i960_function_name_declare (file, name, fndecl)
                    985:      FILE *file;
                    986:      char *name;
                    987:      tree fndecl;
                    988: {
                    989:   register int i, j;
                    990:   int leaf_proc_ok;
                    991:   rtx insn;
                    992: 
                    993:   /* Increment global return label.  */
                    994: 
                    995:   ret_label++;
                    996: 
                    997:   /* Compute whether tail calls and leaf routine optimizations can be performed
                    998:      for this function.  */
                    999: 
                   1000:   if (TARGET_TAILCALL)
                   1001:     tail_call_ok = 1;
                   1002:   else
                   1003:     tail_call_ok = 0;
                   1004: 
                   1005:   if (TARGET_LEAFPROC)
                   1006:     leaf_proc_ok = 1;
                   1007:   else
                   1008:     leaf_proc_ok = 0;
                   1009: 
1.1.1.4 ! root     1010:   /* Even if nobody uses extra parms, can't have leafproc or tail calls if
1.1       root     1011:      argblock, because argblock uses g14 implicitly.  */
                   1012: 
1.1.1.3   root     1013:   if (current_function_args_size != 0 || VARARGS_STDARG_FUNCTION (fndecl))
1.1       root     1014:     {
                   1015:       tail_call_ok = 0;
                   1016:       leaf_proc_ok = 0;
                   1017:     }
                   1018:       
                   1019:   /* See if caller passes in an address to return value. */
                   1020: 
                   1021:   if (aggregate_value_p (DECL_RESULT (fndecl)))
                   1022:     {
                   1023:       tail_call_ok = 0;
                   1024:       leaf_proc_ok = 0;
                   1025:     }
                   1026: 
                   1027:   /* Can not use tail calls or make this a leaf routine if there is a non
                   1028:      zero frame size.  */
                   1029: 
                   1030:   if (get_frame_size () != 0)
                   1031:     leaf_proc_ok = 0;
                   1032: 
                   1033:   /* I don't understand this condition, and do not think that it is correct.
                   1034:      Apparently this is just checking whether the frame pointer is used, and
                   1035:      we can't trust regs_ever_live[fp] since it is (almost?) always set.  */
                   1036: 
                   1037:   if (tail_call_ok)
                   1038:     for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
                   1039:       if (GET_CODE (insn) == INSN
                   1040:          && reg_mentioned_p (frame_pointer_rtx, insn))
                   1041:        {
                   1042:          tail_call_ok = 0;
                   1043:          break;
                   1044:        }
                   1045: 
                   1046:   /* Check for CALL insns.  Can not be a leaf routine if there are any.  */
                   1047: 
                   1048:   if (leaf_proc_ok)
                   1049:     for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
                   1050:       if (GET_CODE (insn) == CALL_INSN)
                   1051:        {
                   1052:          leaf_proc_ok = 0;
                   1053:          break;
                   1054:        }
                   1055: 
                   1056:   /* Can not be a leaf routine if any non-call clobbered registers are
                   1057:      used in this function.  */
                   1058: 
                   1059:   if (leaf_proc_ok)
                   1060:     for (i = 0, j = 0; i < FIRST_PSEUDO_REGISTER; i++)
                   1061:       if (regs_ever_live[i]
                   1062:          && ((! call_used_regs[i]) || (i > 7 && i < 12)))
                   1063:        {
                   1064:          /* Global registers.  */
                   1065:          if (i < 16 && i > 7 && i != 13)
                   1066:            leaf_proc_ok = 0;
                   1067:          /* Local registers.  */
                   1068:          else if (i < 32)
                   1069:            leaf_proc_ok = 0;
                   1070:        }
                   1071: 
                   1072:   /* Now choose a leaf return register, if we can find one, and if it is
                   1073:      OK for this to be a leaf routine.  */
                   1074: 
                   1075:   i960_leaf_ret_reg = -1;
                   1076: 
                   1077:   if (optimize && leaf_proc_ok)
                   1078:     {
                   1079:       for (i960_leaf_ret_reg = -1, i = 0; i < 8; i++)
                   1080:        if (regs_ever_live[i] == 0)
                   1081:          {
                   1082:            i960_leaf_ret_reg = i;
                   1083:            regs_ever_live[i] = 1;
                   1084:            break;
                   1085:          }
                   1086:     }
                   1087: 
                   1088:   /* Do this after choosing the leaf return register, so it will be listed
                   1089:      if one was chosen.  */
                   1090: 
1.1.1.3   root     1091:   fprintf (file, "\t#  Function '%s'\n", (name[0] == '*' ? &name[1] : name));
1.1       root     1092:   fprintf (file, "\t#  Registers used: ");
                   1093: 
                   1094:   for (i = 0, j = 0; i < FIRST_PSEUDO_REGISTER; i++)
                   1095:     {
                   1096:       if (regs_ever_live[i])
                   1097:        {
                   1098:          fprintf (file, "%s%s ", reg_names[i], call_used_regs[i] ? "" : "*");
                   1099: 
                   1100:          if (i > 15 && j == 0)
                   1101:            {
                   1102:              fprintf (file,"\n\t#\t\t   ");
                   1103:              j++;
                   1104:             }
                   1105:         }
                   1106:     }
                   1107: 
                   1108:   fprintf (file, "\n");
                   1109: 
                   1110:   if (i960_leaf_ret_reg >= 0)
                   1111:     {
                   1112:       /* Make it a leaf procedure.  */
                   1113: 
                   1114:       if (TREE_PUBLIC (fndecl))
1.1.1.3   root     1115:        fprintf (file,"\t.globl\t%s.lf\n", (name[0] == '*' ? &name[1] : name));
1.1       root     1116: 
1.1.1.3   root     1117:       fprintf (file, "\t.leafproc\t");
                   1118:       assemble_name (file, name);
                   1119:       fprintf (file, ",%s.lf\n", (name[0] == '*' ? &name[1] : name));
                   1120:       ASM_OUTPUT_LABEL (file, name);
1.1       root     1121:       fprintf (file, "\tlda    LR%d,g14\n", ret_label);
1.1.1.3   root     1122:       fprintf (file, "%s.lf:\n", (name[0] == '*' ? &name[1] : name));
1.1       root     1123:       fprintf (file, "\tmov    g14,g%d\n", i960_leaf_ret_reg);
                   1124: 
                   1125:       if (TARGET_C_SERIES)
                   1126:        {
                   1127:          fprintf (file, "\tlda    0,g14\n");
                   1128:          i960_last_insn_type = I_TYPE_MEM;
                   1129:        }
                   1130:       else
                   1131:        {
                   1132:          fprintf (file, "\tmov    0,g14\n");
                   1133:          i960_last_insn_type = I_TYPE_REG;
                   1134:        }
                   1135:     }
                   1136:   else
                   1137:     {
                   1138:       ASM_OUTPUT_LABEL (file, name);
                   1139:       i960_last_insn_type = I_TYPE_CTRL; 
                   1140:     }
                   1141: }
                   1142: 
                   1143: /* Compute and return the frame size.  */
                   1144: 
                   1145: int
                   1146: compute_frame_size (size)
                   1147:      int size;
                   1148: {
                   1149:   int actual_fsize;
1.1.1.3   root     1150:   int outgoing_args_size = current_function_outgoing_args_size;
1.1       root     1151: 
                   1152:   /* The STARTING_FRAME_OFFSET is totally hidden to us as far
                   1153:      as size is concerned.  */
                   1154:   actual_fsize = (size + 15) & -16;
                   1155:   actual_fsize += (outgoing_args_size + 15) & -16;
                   1156: 
                   1157:   return actual_fsize;
                   1158: }
                   1159: 
                   1160: /* Output code for the function prologue.  */
                   1161: 
                   1162: void
                   1163: i960_function_prologue (file, size)
                   1164:      FILE *file;
                   1165:      unsigned int size;
                   1166: {
                   1167:   register int i, j, nr;
                   1168:   int n_iregs = 0;
                   1169:   int rsize = 0;
                   1170:   int actual_fsize, offset;
                   1171:   char tmpstr[1000];
                   1172:   /* -1 if reg must be saved on proc entry, 0 if available, 1 if saved
                   1173:      somewhere.  */
                   1174:   int regs[FIRST_PSEUDO_REGISTER];
                   1175: 
                   1176:   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
                   1177:     if (regs_ever_live[i]
                   1178:        && ((! call_used_regs[i]) || (i > 7 && i < 12)))
                   1179:       {
                   1180:        regs[i] = -1;
                   1181:         /* Count global registers that need saving.  */
                   1182:        if (i < 16)
                   1183:          n_iregs++;
                   1184:       }
                   1185:     else
                   1186:       regs[i] = 0;
                   1187: 
                   1188:   epilogue_string[0] = '\0';
                   1189: 
                   1190:   if (profile_flag || profile_block_flag)
                   1191:     {
                   1192:       /* When profiling, we may use registers 20 to 27 to save arguments, so
                   1193:         they can't be used here for saving globals.  J is the number of
                   1194:         argument registers the mcount call will save.  */
                   1195:       for (j = 7; j >= 0 && ! regs_ever_live[j]; j--)
                   1196:        ;
                   1197: 
                   1198:       for (i = 20; i <= j + 20; i++)
                   1199:        regs[i] = -1;
                   1200:     }
                   1201: 
                   1202:   /* First look for local registers to save globals in.  */
                   1203:   for (i = 0; i < 16; i++)
                   1204:     {
                   1205:       if (regs[i] == 0)
                   1206:        continue;
                   1207: 
                   1208:       /* Start at r4, not r3.  */
                   1209:       for (j = 20; j < 32; j++)
                   1210:        {
                   1211:          if (regs[j] != 0)
                   1212:            continue;
                   1213: 
                   1214:          regs[i] = 1;
                   1215:          regs[j] = -1;
                   1216:          regs_ever_live[j] = 1;
                   1217:          nr = 1;
                   1218:          if (i <= 14 && i % 2 == 0 && j <= 30 && j % 2 == 0
                   1219:              && regs[i+1] != 0 && regs[j+1] == 0)
                   1220:            {
                   1221:              nr = 2;
                   1222:              regs[i+1] = 1;
                   1223:              regs[j+1] = -1;
                   1224:              regs_ever_live[j+1] = 1;
                   1225:            }
                   1226:          if (nr == 2 && i <= 12 && i % 4 == 0 && j <= 28 && j % 4 == 0
                   1227:              && regs[i+2] != 0 && regs[j+2] == 0)
                   1228:            {
                   1229:              nr = 3;
                   1230:              regs[i+2] = 1;
                   1231:              regs[j+2] = -1;
                   1232:              regs_ever_live[j+2] = 1;
                   1233:            }
                   1234:          if (nr == 3 && regs[i+3] != 0 && regs[j+3] == 0)
                   1235:            {
                   1236:              nr = 4;
                   1237:              regs[i+3] = 1;
                   1238:              regs[j+3] = -1;
                   1239:              regs_ever_live[j+3] = 1;
                   1240:            }
                   1241: 
                   1242:          fprintf (file, "\tmov%s       %s,%s\n",
                   1243:                   ((nr == 4) ? "q" :
                   1244:                    (nr == 3) ? "t" :
                   1245:                    (nr == 2) ? "l" : ""),
                   1246:                   reg_names[i], reg_names[j]);
                   1247:          sprintf (tmpstr, "\tmov%s     %s,%s\n",
                   1248:                   ((nr == 4) ? "q" :
                   1249:                    (nr == 3) ? "t" :
                   1250:                    (nr == 2) ? "l" : ""),
                   1251:                   reg_names[j], reg_names[i]);
                   1252:          strcat (epilogue_string, tmpstr);
                   1253: 
                   1254:          n_iregs -= nr;
                   1255:          i += nr-1;
                   1256:          break;
                   1257:        }
                   1258:     }
                   1259: 
                   1260:   /* N_iregs is now the number of global registers that haven't been saved
                   1261:      yet.  */
                   1262: 
                   1263:   rsize = (n_iregs * 4);
                   1264:   actual_fsize = compute_frame_size (size) + rsize;
                   1265: #if 0
                   1266:   /* ??? The 1.2.1 compiler does this also.  This is meant to round the frame
                   1267:      size up to the nearest multiple of 16.  I don't know whether this is
                   1268:      necessary, or even desirable.
                   1269: 
                   1270:      The frame pointer must be aligned, but the call instruction takes care of
                   1271:      that.  If we leave the stack pointer unaligned, we may save a little on
                   1272:      dynamic stack allocation.  And we don't lose, at least according to the
                   1273:      i960CA manual.  */
                   1274:   actual_fsize = (actual_fsize + 15) & ~0xF;
                   1275: #endif
                   1276: 
                   1277:   /* Allocate space for register save and locals.  */
                   1278:   if (actual_fsize > 0)
                   1279:     {
                   1280:       if (actual_fsize < 32)
                   1281:        fprintf (file, "\taddo  %d,sp,sp\n", actual_fsize);
                   1282:       else
                   1283:        fprintf (file, "\tlda\t%d(sp),sp\n", actual_fsize);
                   1284:     }
                   1285: 
                   1286:   /* Take hardware register save area created by the call instruction
1.1.1.3   root     1287:      into account, but store them before the argument block area.  */
                   1288:   offset = 64 + actual_fsize - compute_frame_size (0) - rsize;
1.1       root     1289:   /* Save registers on stack if needed.  */
                   1290:   for (i = 0, j = n_iregs; j > 0 && i < 16; i++)
                   1291:     {
                   1292:       if (regs[i] != -1)
                   1293:        continue;
                   1294: 
                   1295:       nr = 1;
                   1296: 
                   1297:       if (i <= 14 && i % 2 == 0 && regs[i+1] == -1 && offset % 2 == 0)
                   1298:        nr = 2;
                   1299: 
                   1300:       if (nr == 2 && i <= 12 && i % 4 == 0 && regs[i+2] == -1
                   1301:          && offset % 4 == 0)
                   1302:        nr = 3;
                   1303: 
                   1304:       if (nr == 3 && regs[i+3] == -1)
                   1305:        nr = 4;
                   1306: 
                   1307:       fprintf (file,"\tst%s    %s,%d(fp)\n",
                   1308:               ((nr == 4) ? "q" :
                   1309:                (nr == 3) ? "t" :
                   1310:                (nr == 2) ? "l" : ""),
                   1311:               reg_names[i], offset);
                   1312:       sprintf (tmpstr,"\tld%s  %d(fp),%s\n",
                   1313:               ((nr == 4) ? "q" :
                   1314:                (nr == 3) ? "t" :
                   1315:                (nr == 2) ? "l" : ""),
                   1316:               offset, reg_names[i]);
                   1317:       strcat (epilogue_string, tmpstr);
                   1318:       i += nr-1;
                   1319:       j -= nr;
                   1320:       offset += nr * 4;
                   1321:     }
                   1322: 
                   1323:   if (actual_fsize == 0 && size == 0 && rsize == 0)
                   1324:     return;
                   1325: 
                   1326:   fprintf (file, "\t#Prologue stats:\n");
                   1327:   fprintf (file, "\t#  Total Frame Size: %d bytes\n", actual_fsize);
                   1328: 
                   1329:   if (size)
                   1330:     fprintf (file, "\t#  Local Variable Size: %d bytes\n", size);
                   1331:   if (rsize)
                   1332:     fprintf (file, "\t#  Register Save Size: %d regs, %d bytes\n",
                   1333:             n_iregs, rsize);
                   1334:   fprintf (file, "\t#End Prologue#\n");
                   1335: }
                   1336: 
                   1337: /* Output code for the function profiler.  */
                   1338: 
                   1339: void
                   1340: output_function_profiler (file, labelno)
                   1341:      FILE *file;
                   1342:      int labelno;
                   1343: {
                   1344:   /* The last used parameter register.  */
                   1345:   int last_parm_reg;
                   1346:   int i, j, increment;
1.1.1.3   root     1347:   int varargs_stdarg_function
                   1348:     = VARARGS_STDARG_FUNCTION (current_function_decl);
1.1       root     1349: 
                   1350:   /* Figure out the last used parameter register.  The proper thing to do
                   1351:      is to walk incoming args of the function.  A function might have live
                   1352:      parameter registers even if it has no incoming args.  Note that we
                   1353:      don't have to save parameter registers g8 to g11 because they are
                   1354:      call preserved.  */
                   1355: 
                   1356:   /* See also output_function_prologue, which tries to use local registers
                   1357:      for preserved call-saved global registers.  */
                   1358: 
                   1359:   for (last_parm_reg = 7;
                   1360:        last_parm_reg >= 0 && ! regs_ever_live[last_parm_reg];
                   1361:        last_parm_reg--)
                   1362:     ;
                   1363: 
                   1364:   /* Save parameter registers in regs r4 (20) to r11 (27).  */
                   1365: 
                   1366:   for (i = 0, j = 4; i <= last_parm_reg; i += increment, j += increment)
                   1367:     {
                   1368:       if (i % 4 == 0 && (last_parm_reg - i) >= 3)
                   1369:        increment = 4;
                   1370:       else if (i % 4 == 0 && (last_parm_reg - i) >= 2)
                   1371:        increment = 3;
                   1372:       else if (i % 2 == 0 && (last_parm_reg - i) >= 1)
                   1373:        increment = 2;
                   1374:       else
                   1375:        increment = 1;
                   1376: 
                   1377:       fprintf (file, "\tmov%s  g%d,r%d\n",
                   1378:               (increment == 4 ? "q" : increment == 3 ? "t"
                   1379:                : increment == 2 ? "l": ""), i, j);
                   1380:       }
                   1381: 
                   1382:   /* If this function uses the arg pointer, then save it in r3 and then
                   1383:      set it to zero.  */
                   1384: 
1.1.1.3   root     1385:   if (current_function_args_size != 0 || varargs_stdarg_function)
1.1       root     1386:     fprintf (file, "\tmov      g14,r3\n\tmov   0,g14\n");
                   1387: 
                   1388:   /* Load location address into g0 and call mcount.  */
                   1389: 
                   1390:   fprintf (file, "\tlda\tLP%d,g0\n\tcallx\tmcount\n", labelno);
                   1391: 
                   1392:   /* If this function uses the arg pointer, restore it.  */
                   1393: 
1.1.1.3   root     1394:   if (current_function_args_size != 0 || varargs_stdarg_function)
1.1       root     1395:     fprintf (file, "\tmov      r3,g14\n");
                   1396: 
                   1397:   /* Restore parameter registers.  */
                   1398: 
                   1399:   for (i = 0, j = 4; i <= last_parm_reg; i += increment, j += increment)
                   1400:     {
                   1401:       if (i % 4 == 0 && (last_parm_reg - i) >= 3)
                   1402:        increment = 4;
                   1403:       else if (i % 4 == 0 && (last_parm_reg - i) >= 2)
                   1404:        increment = 3;
                   1405:       else if (i % 2 == 0 && (last_parm_reg - i) >= 1)
                   1406:        increment = 2;
                   1407:       else
                   1408:        increment = 1;
                   1409: 
                   1410:       fprintf (file, "\tmov%s  r%d,g%d\n",
                   1411:               (increment == 4 ? "q" : increment == 3 ? "t"
                   1412:                : increment == 2 ? "l": ""), j, i);
                   1413:     }
                   1414: }
                   1415: 
                   1416: /* Output code for the function epilogue.  */
                   1417: 
                   1418: void
                   1419: i960_function_epilogue (file, size)
                   1420:      FILE *file;
                   1421:      unsigned int size;
                   1422: {
                   1423:   if (i960_leaf_ret_reg >= 0)
                   1424:     {
                   1425:       fprintf (file, "LR%d:    ret\n", ret_label);
                   1426:       return;
                   1427:     }
                   1428: 
                   1429:   if (*epilogue_string == 0)
                   1430:     {
                   1431:       register rtx tmp;
                   1432:        
                   1433:       /* Emit a return insn, but only if control can fall through to here.  */
                   1434: 
                   1435:       tmp = get_last_insn ();
                   1436:       while (tmp)
                   1437:        {
                   1438:          if (GET_CODE (tmp) == BARRIER)
                   1439:            return;
                   1440:          if (GET_CODE (tmp) == CODE_LABEL)
                   1441:            break;
                   1442:          if (GET_CODE (tmp) == JUMP_INSN)
                   1443:            {
                   1444:              if (GET_CODE (PATTERN (tmp)) == RETURN)
                   1445:                return;
                   1446:              break;
                   1447:            }
                   1448:          if (GET_CODE (tmp) == NOTE)
                   1449:            {
                   1450:              tmp = PREV_INSN (tmp);
                   1451:              continue;
                   1452:            }
                   1453:          break;
                   1454:        }
                   1455:       fprintf (file, "LR%d:    ret\n", ret_label);
                   1456:       return;
                   1457:     }
                   1458: 
                   1459:   fprintf (file, "LR%d:\n", ret_label);
                   1460: 
                   1461:   fprintf (file, "\t#EPILOGUE#\n");
                   1462: 
                   1463:   /* Output the string created by the prologue which will restore all
                   1464:      registers saved by the prologue.  */
                   1465: 
                   1466:   if (epilogue_string[0] != '\0')
                   1467:     fprintf (file, "%s", epilogue_string);
                   1468: 
1.1.1.4 ! root     1469:   /* Must clear g14 on return if this function set it.
        !          1470:      Only varargs/stdarg functions modify g14.  */
1.1       root     1471: 
1.1.1.4 ! root     1472:   if (VARARGS_STDARG_FUNCTION (current_function_decl))
1.1       root     1473:     fprintf (file, "\tmov      0,g14\n");
                   1474: 
                   1475:   fprintf (file, "\tret\n");
                   1476:   fprintf (file, "\t#End Epilogue#\n");
                   1477: }
                   1478: 
                   1479: /* Output code for a call insn.  */
                   1480: 
                   1481: char *
                   1482: i960_output_call_insn (target, argsize_rtx, arg_pointer, insn)
                   1483:      register rtx target, argsize_rtx, arg_pointer, insn;
                   1484: {
                   1485:   int argsize = INTVAL (argsize_rtx);
                   1486:   rtx nexti = next_real_insn (insn);
                   1487:   rtx operands[2];
1.1.1.3   root     1488:   int varargs_stdarg_function
                   1489:     = VARARGS_STDARG_FUNCTION (current_function_decl);
1.1       root     1490: 
                   1491:   operands[0] = target;
                   1492:   operands[1] = arg_pointer;
                   1493: 
1.1.1.3   root     1494:   if (current_function_args_size != 0 || varargs_stdarg_function)
1.1       root     1495:     output_asm_insn ("mov      g14,r3", operands);
                   1496: 
                   1497:   if (argsize > 48)
                   1498:     output_asm_insn ("lda      %a1,g14", operands);
1.1.1.3   root     1499:   else if (current_function_args_size != 0 || varargs_stdarg_function)
1.1       root     1500:     output_asm_insn ("mov      0,g14", operands);
                   1501: 
                   1502:   /* The code used to assume that calls to SYMBOL_REFs could not be more
                   1503:      than 24 bits away (b vs bx, callj vs callx).  This is not true.  This
                   1504:      feature is now implemented by relaxing in the GNU linker.  It can convert
                   1505:      bx to b if in range, and callx to calls/call/balx/bal as appropriate.  */
                   1506: 
                   1507:   /* Nexti could be zero if the called routine is volatile.  */
                   1508:   if (optimize && (*epilogue_string == 0) && argsize == 0 && tail_call_ok 
                   1509:       && (nexti == 0 || GET_CODE (PATTERN (nexti)) == RETURN))
                   1510:     {
                   1511:       /* Delete following return insn.  */
                   1512:       if (nexti && no_labels_between_p (insn, nexti))
                   1513:        delete_insn (nexti);
                   1514:       output_asm_insn ("bx     %0", operands);
                   1515:       return "# notreached";
                   1516:     }
                   1517: 
                   1518:   output_asm_insn ("callx      %0", operands);
                   1519: 
1.1.1.4 ! root     1520:   /* If the caller sets g14 to the address of the argblock, then the caller
        !          1521:      must clear it after the return.  */
        !          1522: 
1.1.1.3   root     1523:   if (current_function_args_size != 0 || varargs_stdarg_function)
1.1       root     1524:     output_asm_insn ("mov      r3,g14", operands);
1.1.1.4 ! root     1525:   else if (argsize > 48)
        !          1526:     output_asm_insn ("mov      0,g14", operands);
1.1       root     1527: 
                   1528:   return "";
                   1529: }
                   1530: 
                   1531: /* Output code for a return insn.  */
                   1532: 
                   1533: char *
                   1534: i960_output_ret_insn (insn)
                   1535:      register rtx insn;
                   1536: {
                   1537:   static char lbuf[20];
                   1538:   
                   1539:   if (*epilogue_string != 0)
                   1540:     {
                   1541:       if (! TARGET_CODE_ALIGN && next_real_insn (insn) == 0)
                   1542:        return "";
                   1543: 
                   1544:       sprintf (lbuf, "b        LR%d", ret_label);
                   1545:       return lbuf;
                   1546:     }
                   1547: 
1.1.1.4 ! root     1548:   /* Must clear g14 on return if this function set it.
        !          1549:      Only varargs/stdarg functions modify g14.  */
        !          1550: 
        !          1551:   if (VARARGS_STDARG_FUNCTION (current_function_decl))
1.1       root     1552:     output_asm_insn ("mov      0,g14", 0);
                   1553: 
                   1554:   if (i960_leaf_ret_reg >= 0)
                   1555:     {
                   1556:       sprintf (lbuf, "bx       (%s)", reg_names[i960_leaf_ret_reg]);
                   1557:       return lbuf;
                   1558:     }
                   1559:   return "ret";
                   1560: }
                   1561: 
                   1562: #if 0
                   1563: /* Return a character string representing the branch prediction
                   1564:    opcode to be tacked on an instruction.  This must at least
                   1565:    return a null string.  */
                   1566: 
                   1567: char *
                   1568: i960_br_predict_opcode (lab_ref, insn)
                   1569:      rtx lab_ref, insn;
                   1570: {
                   1571:   if (TARGET_BRANCH_PREDICT)
                   1572:     {
                   1573:       unsigned long label_uid;
                   1574:       
                   1575:       if (GET_CODE (lab_ref) == CODE_LABEL)
                   1576:        label_uid = INSN_UID (lab_ref);
                   1577:       else if (GET_CODE (lab_ref) == LABEL_REF)
                   1578:        label_uid = INSN_UID (XEXP (lab_ref, 0));
                   1579:       else
                   1580:        return ".f";
                   1581: 
                   1582:       /* If not optimizing, then the insn_addresses array will not be
                   1583:         valid.  In this case, always return ".t" since most branches
                   1584:         are taken.  If optimizing, return .t for backward branches
                   1585:         and .f for forward branches.  */
                   1586:       if (! optimize
                   1587:          || insn_addresses[label_uid] < insn_addresses[INSN_UID (insn)])
                   1588:        return ".t";
                   1589:       return ".f";
                   1590:     }
                   1591:     
                   1592:   return "";
                   1593: }
                   1594: #endif
                   1595: 
                   1596: /* Print the operand represented by rtx X formatted by code CODE.  */
                   1597: 
                   1598: void
                   1599: i960_print_operand (file, x, code)
                   1600:      FILE *file;
                   1601:      rtx x;
                   1602:      char code;
                   1603: {
                   1604:   enum rtx_code rtxcode = GET_CODE (x);
                   1605: 
                   1606:   if (rtxcode == REG)
                   1607:     {
                   1608:       switch (code)
                   1609:        {
                   1610:        case 'D':
1.1.1.4 ! root     1611:          /* Second reg of a double or quad.  */
1.1       root     1612:          fprintf (file, "%s", reg_names[REGNO (x)+1]);
                   1613:          break;
                   1614: 
1.1.1.4 ! root     1615:        case 'E':
        !          1616:          /* Third reg of a quad.  */
        !          1617:          fprintf (file, "%s", reg_names[REGNO (x)+2]);
        !          1618:          break;
        !          1619: 
        !          1620:        case 'F':
        !          1621:          /* Fourth reg of a quad.  */
        !          1622:          fprintf (file, "%s", reg_names[REGNO (x)+3]);
        !          1623:          break;
        !          1624: 
1.1       root     1625:        case 0:
                   1626:          fprintf (file, "%s", reg_names[REGNO (x)]);
                   1627:          break;
                   1628: 
                   1629:        default:
                   1630:          abort ();
                   1631:        }
                   1632:       return;
                   1633:     }
                   1634:   else if (rtxcode == MEM)
                   1635:     {
                   1636:       output_address (XEXP (x, 0));
                   1637:       return;
                   1638:     }
                   1639:   else if (rtxcode == CONST_INT)
                   1640:     {
                   1641:       if (INTVAL (x) > 9999 || INTVAL (x) < -999)
                   1642:        fprintf (file, "0x%x", INTVAL (x));
                   1643:       else
                   1644:        fprintf (file, "%d", INTVAL (x));
                   1645:       return;
                   1646:     }
                   1647:   else if (rtxcode == CONST_DOUBLE)
                   1648:     {
1.1.1.4 ! root     1649:       REAL_VALUE_TYPE d;
        !          1650:       char dstr[30];
1.1       root     1651: 
1.1.1.4 ! root     1652:       if (x == CONST0_RTX (GET_MODE (x)))
1.1       root     1653:        {
                   1654:          fprintf (file, "0f0.0");
                   1655:          return;
                   1656:        }
1.1.1.4 ! root     1657:       else if (x == CONST1_RTX (GET_MODE (x)))
1.1       root     1658:        {
                   1659:          fprintf (file, "0f1.0");
                   1660:          return;
                   1661:        }
                   1662: 
                   1663:       REAL_VALUE_FROM_CONST_DOUBLE (d, x);
1.1.1.4 ! root     1664:       REAL_VALUE_TO_DECIMAL (d, "%#g", dstr);
        !          1665:       fprintf (file, "0f%s", dstr);
1.1       root     1666:       return;
                   1667:     }
                   1668: 
                   1669:   switch(code)
                   1670:     {
                   1671:     case 'B':
                   1672:       /* Branch or jump, depending on assembler.  */
                   1673:       if (TARGET_ASM_COMPAT)
                   1674:        fputs ("j", file);
                   1675:       else
                   1676:        fputs ("b", file);
                   1677:       break;
                   1678: 
                   1679:     case 'S':
                   1680:       /* Sign of condition.  */
                   1681:       if ((rtxcode == EQ) || (rtxcode == NE) || (rtxcode == GTU)
                   1682:          || (rtxcode == LTU) || (rtxcode == GEU) || (rtxcode == LEU))
                   1683:        fputs ("o", file);
                   1684:       else if ((rtxcode == GT) || (rtxcode == LT)
                   1685:          || (rtxcode == GE) || (rtxcode == LE))
                   1686:        fputs ("i", file);
                   1687:       else
                   1688:        abort();
                   1689:       break;
                   1690: 
                   1691:     case 'I':
                   1692:       /* Inverted condition.  */
                   1693:       rtxcode = reverse_condition (rtxcode);
                   1694:       goto normal;
                   1695: 
                   1696:     case 'X':
                   1697:       /* Inverted condition w/ reversed operands.  */
                   1698:       rtxcode = reverse_condition (rtxcode);
                   1699:       /* Fallthrough.  */
                   1700: 
                   1701:     case 'R':
                   1702:       /* Reversed operand condition.  */
                   1703:       rtxcode = swap_condition (rtxcode);
                   1704:       /* Fallthrough.  */
                   1705: 
                   1706:     case 'C':
                   1707:       /* Normal condition.  */
                   1708:     normal:
                   1709:       if (rtxcode == EQ)  { fputs ("e", file); return; }
                   1710:       else if (rtxcode == NE)  { fputs ("ne", file); return; }
                   1711:       else if (rtxcode == GT)  { fputs ("g", file); return; }
                   1712:       else if (rtxcode == GTU) { fputs ("g", file); return; }
                   1713:       else if (rtxcode == LT)  { fputs ("l", file); return; }
                   1714:       else if (rtxcode == LTU) { fputs ("l", file); return; }
                   1715:       else if (rtxcode == GE)  { fputs ("ge", file); return; }
                   1716:       else if (rtxcode == GEU) { fputs ("ge", file); return; }
                   1717:       else if (rtxcode == LE)  { fputs ("le", file); return; }
                   1718:       else if (rtxcode == LEU) { fputs ("le", file); return; }
                   1719:       else abort ();
                   1720:       break;
                   1721: 
                   1722:     case 0:
                   1723:       output_addr_const (file, x);
                   1724:       break;
                   1725: 
                   1726:     default:
                   1727:       abort ();
                   1728:     }
                   1729: 
                   1730:   return;
                   1731: }
                   1732: 
                   1733: /* Print a memory address as an operand to reference that memory location.
                   1734: 
                   1735:    This is exactly the same as legitimate_address_p, except that it the prints
                   1736:    addresses instead of recognizing them.  */
                   1737: 
                   1738: void
                   1739: i960_print_operand_addr (file, addr)
                   1740:      FILE *file;
                   1741:      register rtx addr;
                   1742: {
                   1743:   rtx breg, ireg;
                   1744:   rtx scale, offset;
                   1745: 
                   1746:   ireg = 0;
                   1747:   breg = 0;
                   1748:   offset = 0;
                   1749:   scale = const1_rtx;
                   1750: 
                   1751:   if (GET_CODE (addr) == REG)
                   1752:     breg = addr;
                   1753:   else if (CONSTANT_P (addr))
                   1754:     offset = addr;
                   1755:   else if (GET_CODE (addr) == PLUS)
                   1756:     {
                   1757:       rtx op0, op1;
                   1758: 
                   1759:       op0 = XEXP (addr, 0);
                   1760:       op1 = XEXP (addr, 1);
                   1761: 
                   1762:       if (GET_CODE (op0) == REG)
                   1763:        {
                   1764:          breg = op0;
                   1765:          if (GET_CODE (op1) == REG)
                   1766:            ireg = op1;
                   1767:          else if (CONSTANT_P (op1))
                   1768:            offset = op1;
                   1769:          else
                   1770:            abort ();
                   1771:        }
                   1772:       else if (GET_CODE (op0) == PLUS)
                   1773:        {
                   1774:          if (GET_CODE (XEXP (op0, 0)) == MULT)
                   1775:            {
                   1776:              ireg = XEXP (XEXP (op0, 0), 0);
                   1777:              scale = XEXP (XEXP (op0, 0), 1);
                   1778:              if (GET_CODE (XEXP (op0, 1)) == REG)
                   1779:                {
                   1780:                  breg = XEXP (op0, 1);
                   1781:                  offset = op1;
                   1782:                }
                   1783:              else
                   1784:                abort ();
                   1785:            }
                   1786:          else if (GET_CODE (XEXP (op0, 0)) == REG)
                   1787:            {
                   1788:              breg = XEXP (op0, 0);
                   1789:              if (GET_CODE (XEXP (op0, 1)) == REG)
                   1790:                {
                   1791:                  ireg = XEXP (op0, 1);
                   1792:                  offset = op1;
                   1793:                }
                   1794:              else
                   1795:                abort ();
                   1796:            }
                   1797:          else
                   1798:            abort ();
                   1799:        }
                   1800:       else if (GET_CODE (op0) == MULT)
                   1801:        {
                   1802:          ireg = XEXP (op0, 0);
                   1803:          scale = XEXP (op0, 1);
                   1804:          if (GET_CODE (op1) == REG)
                   1805:            breg = op1;
                   1806:          else if (CONSTANT_P (op1))
                   1807:            offset = op1;
                   1808:          else
                   1809:            abort ();
                   1810:        }
                   1811:       else
                   1812:        abort ();
                   1813:     }
                   1814:   else if (GET_CODE (addr) == MULT)
                   1815:     {
                   1816:       ireg = XEXP (addr, 0);
                   1817:       scale = XEXP (addr, 1);
                   1818:     }
                   1819:   else
                   1820:     abort ();
                   1821: 
                   1822:   if (offset)
                   1823:     output_addr_const (file, offset);
                   1824:   if (breg)
                   1825:     fprintf (file, "(%s)", reg_names[REGNO (breg)]);
                   1826:   if (ireg)
                   1827:     fprintf (file, "[%s*%d]", reg_names[REGNO (ireg)], INTVAL (scale));
                   1828: }
                   1829: 
                   1830: /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
                   1831:    that is a valid memory address for an instruction.
                   1832:    The MODE argument is the machine mode for the MEM expression
                   1833:    that wants to use this address.
                   1834: 
                   1835:        On 80960, legitimate addresses are:
                   1836:                base                            ld      (g0),r0
                   1837:                disp    (12 or 32 bit)          ld      foo,r0
                   1838:                base + index                    ld      (g0)[g1*1],r0
                   1839:                base + displ                    ld      0xf00(g0),r0
                   1840:                base + index*scale + displ      ld      0xf00(g0)[g1*4],r0
                   1841:                index*scale + base              ld      (g0)[g1*4],r0
                   1842:                index*scale + displ             ld      0xf00[g1*4],r0
                   1843:                index*scale                     ld      [g1*4],r0
                   1844:                index + base + displ            ld      0xf00(g0)[g1*1],r0
                   1845: 
                   1846:        In each case, scale can be 1, 2, 4, 8, or 16.  */
                   1847: 
                   1848: /* This is exactly the same as i960_print_operand_addr, except that
                   1849:    it recognizes addresses instead of printing them.
                   1850: 
                   1851:    It only recognizes address in canonical form.  LEGITIMIZE_ADDRESS should
                   1852:    convert common non-canonical forms to canonical form so that they will
                   1853:    be recognized.  */
                   1854: 
                   1855: /* These two macros allow us to accept either a REG or a SUBREG anyplace
                   1856:    where a register is valid.  */
                   1857: 
                   1858: #define RTX_OK_FOR_BASE_P(X, STRICT)                                   \
                   1859:   ((GET_CODE (X) == REG                                                        \
                   1860:     && (STRICT ? REG_OK_FOR_BASE_P_STRICT (X) : REG_OK_FOR_BASE_P (X)))        \
                   1861:    || (GET_CODE (X) == SUBREG                                          \
                   1862:        && GET_CODE (SUBREG_REG (X)) == REG                             \
                   1863:        && (STRICT ? REG_OK_FOR_BASE_P_STRICT (SUBREG_REG (X))          \
                   1864:           : REG_OK_FOR_BASE_P (SUBREG_REG (X)))))
                   1865: 
                   1866: #define RTX_OK_FOR_INDEX_P(X, STRICT)                                  \
                   1867:   ((GET_CODE (X) == REG                                                        \
                   1868:     && (STRICT ? REG_OK_FOR_INDEX_P_STRICT (X) : REG_OK_FOR_INDEX_P (X)))\
                   1869:    || (GET_CODE (X) == SUBREG                                          \
                   1870:        && GET_CODE (SUBREG_REG (X)) == REG                             \
                   1871:        && (STRICT ? REG_OK_FOR_INDEX_P_STRICT (SUBREG_REG (X))         \
                   1872:           : REG_OK_FOR_INDEX_P (SUBREG_REG (X)))))
                   1873: 
                   1874: int
                   1875: legitimate_address_p (mode, addr, strict)
                   1876:      enum machine_mode mode;
                   1877:      register rtx addr;
                   1878:      int strict;
                   1879: {
                   1880:   if (RTX_OK_FOR_BASE_P (addr, strict))
                   1881:     return 1;
                   1882:   else if (CONSTANT_P (addr))
                   1883:     return 1;
                   1884:   else if (GET_CODE (addr) == PLUS)
                   1885:     {
                   1886:       rtx op0, op1;
                   1887: 
                   1888:       if (! TARGET_COMPLEX_ADDR && ! reload_completed)
                   1889:        return 0;
                   1890: 
                   1891:       op0 = XEXP (addr, 0);
                   1892:       op1 = XEXP (addr, 1);
                   1893: 
                   1894:       if (RTX_OK_FOR_BASE_P (op0, strict))
                   1895:        {
                   1896:          if (RTX_OK_FOR_INDEX_P (op1, strict))
                   1897:            return 1;
                   1898:          else if (CONSTANT_P (op1))
                   1899:            return 1;
                   1900:          else
                   1901:            return 0;
                   1902:        }
                   1903:       else if (GET_CODE (op0) == PLUS)
                   1904:        {
                   1905:          if (GET_CODE (XEXP (op0, 0)) == MULT)
                   1906:            {
                   1907:              if (! (RTX_OK_FOR_INDEX_P (XEXP (XEXP (op0, 0), 0), strict)
                   1908:                     && SCALE_TERM_P (XEXP (XEXP (op0, 0), 1))))
                   1909:                return 0;
                   1910: 
                   1911:              if (RTX_OK_FOR_BASE_P (XEXP (op0, 1), strict)
                   1912:                  && CONSTANT_P (op1))
                   1913:                return 1;
                   1914:              else
                   1915:                return 0;
                   1916:            }
                   1917:          else if (RTX_OK_FOR_BASE_P (XEXP (op0, 0), strict))
                   1918:            {
                   1919:              if (RTX_OK_FOR_INDEX_P (XEXP (op0, 1), strict)
                   1920:                  && CONSTANT_P (op1))
                   1921:                return 1;
                   1922:              else
                   1923:                return 0;
                   1924:            }
                   1925:          else
                   1926:            return 0;
                   1927:        }
                   1928:       else if (GET_CODE (op0) == MULT)
                   1929:        {
                   1930:          if (! (RTX_OK_FOR_INDEX_P (XEXP (op0, 0), strict)
                   1931:                 && SCALE_TERM_P (XEXP (op0, 1))))
                   1932:            return 0;
                   1933: 
                   1934:          if (RTX_OK_FOR_BASE_P (op1, strict))
                   1935:            return 1;
                   1936:          else if (CONSTANT_P (op1))
                   1937:            return 1;
                   1938:          else
                   1939:            return 0;
                   1940:        }
                   1941:       else
                   1942:        return 0;
                   1943:     }
                   1944:   else if (GET_CODE (addr) == MULT)
                   1945:     {
                   1946:       if (! TARGET_COMPLEX_ADDR && ! reload_completed)
                   1947:        return 0;
                   1948: 
                   1949:       return (RTX_OK_FOR_INDEX_P (XEXP (addr, 0), strict)
                   1950:              && SCALE_TERM_P (XEXP (addr, 1)));
                   1951:     }
                   1952:   else
                   1953:     return 0;
                   1954: }
                   1955: 
                   1956: /* Try machine-dependent ways of modifying an illegitimate address
                   1957:    to be legitimate.  If we find one, return the new, valid address.
                   1958:    This macro is used in only one place: `memory_address' in explow.c.
                   1959: 
                   1960:    This converts some non-canonical addresses to canonical form so they
                   1961:    can be recognized.  */
                   1962: 
                   1963: rtx
                   1964: legitimize_address (x, oldx, mode)
                   1965:      register rtx x;
                   1966:      register rtx oldx;
                   1967:      enum machine_mode mode;
                   1968: { 
                   1969:   if (GET_CODE (x) == SYMBOL_REF)
                   1970:     {
                   1971:       abort ();
                   1972:       x = copy_to_reg (x);
                   1973:     }
                   1974: 
                   1975:   if (! TARGET_COMPLEX_ADDR && ! reload_completed)
                   1976:     return x;
                   1977: 
                   1978:   /* Canonicalize (plus (mult (reg) (const)) (plus (reg) (const)))
                   1979:      into (plus (plus (mult (reg) (const)) (reg)) (const)).  This can be
                   1980:      created by virtual register instantiation, register elimination, and
                   1981:      similar optimizations.  */
                   1982:   if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == MULT
                   1983:       && GET_CODE (XEXP (x, 1)) == PLUS)
                   1984:     x = gen_rtx (PLUS, Pmode,
                   1985:                 gen_rtx (PLUS, Pmode, XEXP (x, 0), XEXP (XEXP (x, 1), 0)),
                   1986:                 XEXP (XEXP (x, 1), 1));
                   1987: 
                   1988:   /* Canonicalize (plus (plus (mult (reg) (const)) (plus (reg) (const))) const)
                   1989:      into (plus (plus (mult (reg) (const)) (reg)) (const)).  */
                   1990:   else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == PLUS
                   1991:           && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
                   1992:           && GET_CODE (XEXP (XEXP (x, 0), 1)) == PLUS
                   1993:           && CONSTANT_P (XEXP (x, 1)))
                   1994:     {
                   1995:       rtx constant, other;
                   1996: 
                   1997:       if (GET_CODE (XEXP (x, 1)) == CONST_INT)
                   1998:        {
                   1999:          constant = XEXP (x, 1);
                   2000:          other = XEXP (XEXP (XEXP (x, 0), 1), 1);
                   2001:        }
                   2002:       else if (GET_CODE (XEXP (XEXP (XEXP (x, 0), 1), 1)) == CONST_INT)
                   2003:        {
                   2004:          constant = XEXP (XEXP (XEXP (x, 0), 1), 1);
                   2005:          other = XEXP (x, 1);
                   2006:        }
                   2007:       else
                   2008:        constant = 0;
                   2009: 
                   2010:       if (constant)
                   2011:        x = gen_rtx (PLUS, Pmode,
                   2012:                     gen_rtx (PLUS, Pmode, XEXP (XEXP (x, 0), 0),
                   2013:                              XEXP (XEXP (XEXP (x, 0), 1), 0)),
                   2014:                     plus_constant (other, INTVAL (constant)));
                   2015:     }
                   2016: 
                   2017:   return x;
                   2018: }
                   2019: 
                   2020: #if 0
                   2021: /* Return the most stringent alignment that we are willing to consider
                   2022:    objects of size SIZE and known alignment ALIGN as having. */
                   2023:    
                   2024: int
                   2025: i960_alignment (size, align)
                   2026:      int size;
                   2027:      int align;
                   2028: {
                   2029:   int i;
                   2030: 
                   2031:   if (! TARGET_STRICT_ALIGN)
                   2032:     if (TARGET_IC_COMPAT2_0 || align >= 4)
                   2033:       {
                   2034:        i = i960_object_bytes_bitalign (size) / BITS_PER_UNIT;
                   2035:        if (i > align)
                   2036:          align = i;
                   2037:       }
                   2038: 
                   2039:   return align;
                   2040: }
                   2041: #endif
                   2042: 
                   2043: /* Modes for condition codes.  */
                   2044: #define C_MODES                \
                   2045:   ((1 << (int) CCmode) | (1 << (int) CC_UNSmode) | (1<< (int) CC_CHKmode))
                   2046: 
                   2047: /* Modes for single-word (and smaller) quantities.  */
                   2048: #define S_MODES                                                \
                   2049:  (~C_MODES                                             \
                   2050:   & ~ ((1 << (int) DImode) | (1 << (int) TImode)       \
1.1.1.4 ! root     2051:        | (1 << (int) DFmode) | (1 << (int) XFmode)))
1.1       root     2052: 
                   2053: /* Modes for double-word (and smaller) quantities.  */
                   2054: #define D_MODES                                        \
                   2055:   (~C_MODES                                    \
1.1.1.4 ! root     2056:    & ~ ((1 << (int) TImode) | (1 << (int) XFmode)))
1.1       root     2057: 
                   2058: /* Modes for quad-word quantities.  */
                   2059: #define T_MODES (~C_MODES)
                   2060: 
                   2061: /* Modes for single-float quantities.  */
                   2062: #define SF_MODES ((1 << (int) SFmode))
                   2063: 
                   2064: /* Modes for double-float quantities.  */
                   2065: #define DF_MODES (SF_MODES | (1 << (int) DFmode) | (1 << (int) SCmode))
                   2066: 
                   2067: /* Modes for quad-float quantities.  */
1.1.1.4 ! root     2068: #define XF_MODES (DF_MODES | (1 << (int) XFmode) | (1 << (int) DCmode))
1.1       root     2069: 
                   2070: unsigned int hard_regno_mode_ok[FIRST_PSEUDO_REGISTER] = {
                   2071:   T_MODES, S_MODES, D_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES,
                   2072:   T_MODES, S_MODES, D_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES,
                   2073:   T_MODES, S_MODES, D_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES,
                   2074:   T_MODES, S_MODES, D_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES,
                   2075: 
1.1.1.4 ! root     2076:   XF_MODES, XF_MODES, XF_MODES, XF_MODES, C_MODES};
1.1       root     2077: 
                   2078: 
                   2079: /* Return the minimum alignment of an expression rtx X in bytes.  This takes
                   2080:    advantage of machine specific facts, such as knowing that the frame pointer
                   2081:    is always 16 byte aligned.  */
                   2082: 
                   2083: int
                   2084: i960_expr_alignment (x, size)
                   2085:      rtx x;
                   2086:      int size;
                   2087: {
                   2088:   int align = 1;
                   2089: 
                   2090:   if (x == 0)
                   2091:     return 1;
                   2092: 
                   2093:   switch (GET_CODE(x))
                   2094:     {
                   2095:     case CONST_INT:
                   2096:       align = INTVAL(x);
                   2097: 
                   2098:       if ((align & 0xf) == 0)
                   2099:        align = 16;
                   2100:       else if ((align & 0x7) == 0)
                   2101:        align = 8;
                   2102:       else if ((align & 0x3) == 0)
                   2103:        align = 4;
                   2104:       else if ((align & 0x1) == 0)
                   2105:        align = 2;
                   2106:       else
                   2107:        align = 1;
                   2108:       break;
                   2109: 
                   2110:     case PLUS:
                   2111:       align = MIN (i960_expr_alignment (XEXP (x, 0), size),
                   2112:                   i960_expr_alignment (XEXP (x, 1), size));
                   2113:       break;
                   2114: 
                   2115:     case SYMBOL_REF:
                   2116:       /* If this is a valid program, objects are guaranteed to be
                   2117:         correctly aligned for whatever size the reference actually is. */
                   2118:       align = i960_object_bytes_bitalign (size) / BITS_PER_UNIT;
                   2119:       break;
                   2120: 
                   2121:     case REG:
                   2122:       if (REGNO (x) == FRAME_POINTER_REGNUM)
                   2123:        align = 16;
                   2124:       break;
                   2125: 
                   2126:     case ASHIFT:
                   2127:       align = i960_expr_alignment (XEXP (x, 0));
                   2128: 
                   2129:       if (GET_CODE (XEXP (x, 1)) == CONST_INT)
                   2130:        {
                   2131:          align = align << INTVAL (XEXP (x, 1));
                   2132:          align = MIN (align, 16);
                   2133:        }
                   2134:       break;
                   2135: 
                   2136:     case MULT:
                   2137:       align = (i960_expr_alignment (XEXP (x, 0), size) *
                   2138:               i960_expr_alignment (XEXP (x, 1), size));
                   2139: 
                   2140:       align = MIN (align, 16);
                   2141:       break;
                   2142:     }
                   2143: 
                   2144:   return align;
                   2145: }
                   2146: 
                   2147: /* Return true if it is possible to reference both BASE and OFFSET, which
                   2148:    have alignment at least as great as 4 byte, as if they had alignment valid
                   2149:    for an object of size SIZE.  */
                   2150: 
                   2151: int
                   2152: i960_improve_align (base, offset, size)
                   2153:      rtx base;
                   2154:      rtx offset;
                   2155:      int size;
                   2156: {
                   2157:   int i, j;
                   2158: 
                   2159:   /* We have at least a word reference to the object, so we know it has to
                   2160:      be aligned at least to 4 bytes.  */
                   2161: 
                   2162:   i = MIN (i960_expr_alignment (base, 4),
                   2163:           i960_expr_alignment (offset, 4));
                   2164: 
                   2165:   i = MAX (i, 4);
                   2166: 
                   2167:   /* We know the size of the request.  If strict align is not enabled, we
                   2168:      can guess that the alignment is OK for the requested size.  */
                   2169: 
                   2170:   if (! TARGET_STRICT_ALIGN)
                   2171:     if ((j = (i960_object_bytes_bitalign (size) / BITS_PER_UNIT)) > i)
                   2172:       i = j;
                   2173: 
                   2174:   return (i >= size);
                   2175: }
                   2176: 
                   2177: /* Return true if it is possible to access BASE and OFFSET, which have 4 byte
                   2178:    (SImode) alignment as if they had 16 byte (TImode) alignment.  */
                   2179: 
                   2180: int
                   2181: i960_si_ti (base, offset)
                   2182:      rtx base;
                   2183:      rtx offset;
                   2184: {
                   2185:   return i960_improve_align (base, offset, 16);
                   2186: }
                   2187: 
                   2188: /* Return true if it is possible to access BASE and OFFSET, which have 4 byte
                   2189:    (SImode) alignment as if they had 8 byte (DImode) alignment.  */
                   2190: 
                   2191: int
                   2192: i960_si_di (base, offset)
                   2193:      rtx base;
                   2194:      rtx offset;
                   2195: {
                   2196:   return i960_improve_align (base, offset, 8);
                   2197: }
                   2198: 
                   2199: /* Return raw values of size and alignment (in words) for the data
                   2200:    type being accessed.  These values will be rounded by the caller.  */
                   2201: 
                   2202: static void 
                   2203: i960_arg_size_and_align (mode, type, size_out, align_out)
                   2204:      enum machine_mode mode;
                   2205:      tree type;
                   2206:      int *size_out;
                   2207:      int *align_out;
                   2208: {
                   2209:   int size, align;
                   2210: 
                   2211:   /* Use formal alignment requirements of type being passed, except make
                   2212:      it at least a word.  If we don't have a type, this is a library call,
                   2213:      and the parm has to be of scalar type.  In this case, consider its
                   2214:      formal alignment requirement to be its size in words.  */
                   2215: 
                   2216:   if (mode == BLKmode)
                   2217:     size = (int_size_in_bytes (type) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
                   2218:   else if (mode == VOIDmode)
                   2219:     {
                   2220:       /* End of parm list.  */
                   2221:       assert (type != 0 && TYPE_MODE (type) == VOIDmode);
                   2222:       size = 1;
                   2223:     }
                   2224:   else
                   2225:     size = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
                   2226: 
                   2227:   if (type == 0)
1.1.1.4 ! root     2228:     {
        !          2229:       /* ??? This is a hack to properly correct the alignment of XFmode
        !          2230:         values without affecting anything else.  */
        !          2231:       if (size == 3)
        !          2232:        align = 4;
        !          2233:       else
        !          2234:        align = size;
        !          2235:     }
1.1       root     2236:   else if (TYPE_ALIGN (type) >= BITS_PER_WORD)
                   2237:     align = TYPE_ALIGN (type) / BITS_PER_WORD;
                   2238:   else
                   2239:     align = 1;
                   2240: 
                   2241:   *size_out  = size;
                   2242:   *align_out = align;
                   2243: }
                   2244: 
                   2245: /* On the 80960 the first 12 args are in registers and the rest are pushed.
                   2246:    Any arg that is bigger than 4 words is placed on the stack and all
                   2247:    subsequent arguments are placed on the stack.
                   2248: 
                   2249:    Additionally, parameters with an alignment requirement stronger than
1.1.1.4 ! root     2250:    a word must be aligned appropriately.  Note that this means that a
        !          2251:    64 bit object with a 32 bit alignment is not 64 bit aligned and may be
        !          2252:    passed in an odd/even register pair.  */
1.1       root     2253: 
                   2254: /* Update CUM to advance past an argument described by MODE and TYPE.  */
                   2255: 
                   2256: void
                   2257: i960_function_arg_advance (cum, mode, type, named)
                   2258:      CUMULATIVE_ARGS *cum;
                   2259:      enum machine_mode mode;
                   2260:      tree type;
                   2261:      int named;
                   2262: {
                   2263:   int size, align;
                   2264: 
                   2265:   i960_arg_size_and_align (mode, type, &size, &align);
                   2266: 
1.1.1.3   root     2267:   if (size > 4 || cum->ca_nstackparms != 0
1.1       root     2268:       || (size + ROUND_PARM (cum->ca_nregparms, align)) > NPARM_REGS
                   2269:       || MUST_PASS_IN_STACK (mode, type))
1.1.1.4 ! root     2270:     {
        !          2271:       /* Indicate that all the registers are in use, even if all are not,
        !          2272:         so va_start will compute the right value.  */
        !          2273:       cum->ca_nregparms = NPARM_REGS;
        !          2274:       cum->ca_nstackparms = ROUND_PARM (cum->ca_nstackparms, align) + size;
        !          2275:     }
1.1       root     2276:   else
                   2277:     cum->ca_nregparms = ROUND_PARM (cum->ca_nregparms, align) + size;
                   2278: }
                   2279: 
                   2280: /* Return the register that the argument described by MODE and TYPE is
                   2281:    passed in, or else return 0 if it is passed on the stack.  */
                   2282: 
                   2283: rtx
                   2284: i960_function_arg (cum, mode, type, named)
                   2285:      CUMULATIVE_ARGS *cum;
                   2286:      enum machine_mode mode;
                   2287:      tree type;
                   2288:      int named;
                   2289: {
                   2290:   rtx ret;
                   2291:   int size, align;
                   2292: 
                   2293:   i960_arg_size_and_align (mode, type, &size, &align);
                   2294: 
1.1.1.3   root     2295:   if (size > 4 || cum->ca_nstackparms != 0
1.1       root     2296:       || (size + ROUND_PARM (cum->ca_nregparms, align)) > NPARM_REGS
                   2297:       || MUST_PASS_IN_STACK (mode, type))
                   2298:     {
                   2299:       cum->ca_nstackparms = ROUND_PARM (cum->ca_nstackparms, align);
                   2300:       ret = 0;
                   2301:     }
                   2302:   else
                   2303:     {
                   2304:       cum->ca_nregparms = ROUND_PARM (cum->ca_nregparms, align);
                   2305:       ret = gen_rtx (REG, mode, cum->ca_nregparms);
                   2306:     }
                   2307: 
                   2308:   return ret;
                   2309: }
                   2310: 
                   2311: /* Floating-point support.  */
                   2312: 
                   2313: void
1.1.1.4 ! root     2314: i960_output_long_double (file, value)
1.1       root     2315:      FILE *file;
1.1.1.4 ! root     2316:      REAL_VALUE_TYPE value;
1.1       root     2317: {
1.1.1.4 ! root     2318:   long value_long[3];
        !          2319:   char dstr[30];
        !          2320: 
        !          2321:   REAL_VALUE_TO_TARGET_LONG_DOUBLE (value, value_long);
        !          2322:   REAL_VALUE_TO_DECIMAL (value, "%.20g", dstr);
        !          2323: 
        !          2324:   fprintf (file,
        !          2325:           "\t.word\t0x%08lx\t\t# %s\n\t.word\t0x%08lx\n\t.word\t0x%08lx\n",
        !          2326:           value_long[0], dstr, value_long[1], value_long[2]);
        !          2327:   fprintf (file, "\t.word\t0x0\n");
1.1       root     2328: }
                   2329: 
                   2330: void
1.1.1.4 ! root     2331: i960_output_double (file, value)
        !          2332:      FILE *file;
        !          2333:      REAL_VALUE_TYPE value;
        !          2334: {
        !          2335:   long value_long[2];
        !          2336:   char dstr[30];
        !          2337: 
        !          2338:   REAL_VALUE_TO_TARGET_DOUBLE (value, value_long);
        !          2339:   REAL_VALUE_TO_DECIMAL (value, "%.20g", dstr);
        !          2340: 
        !          2341:   fprintf (file, "\t.word\t0x%08lx\t\t# %s\n\t.word\t0x%08lx\n",
        !          2342:           value_long[0], dstr, value_long[1]);
        !          2343: }
        !          2344:   
        !          2345: void
1.1       root     2346: i960_output_float (file, value)
                   2347:      FILE *file;
1.1.1.4 ! root     2348:      REAL_VALUE_TYPE value;
1.1       root     2349: {
1.1.1.4 ! root     2350:   long value_long;
        !          2351:   char dstr[30];
        !          2352: 
        !          2353:   REAL_VALUE_TO_TARGET_SINGLE (value, value_long);
        !          2354:   REAL_VALUE_TO_DECIMAL (value, "%.12g", dstr);
        !          2355: 
        !          2356:   fprintf (file, "\t.word\t0x%08lx\t\t# %s (float)\n", value_long, dstr);
1.1       root     2357: }
                   2358: 
                   2359: /* Return the number of bits that an object of size N bytes is aligned to.  */
                   2360: 
                   2361: int
                   2362: i960_object_bytes_bitalign (n)
                   2363:      int n;
                   2364: {
                   2365:   if (n > 8)      n = 128;
                   2366:   else if (n > 4) n = 64;
                   2367:   else if (n > 2) n = 32;
                   2368:   else if (n > 1) n = 16;
                   2369:   else            n = 8;
                   2370: 
                   2371:   return n;
                   2372: }
                   2373: 
1.1.1.4 ! root     2374: /* Compute the alignment for an aggregate type TSIZE.
        !          2375:    Alignment is MAX (greatest member alignment,
        !          2376:                      MIN (pragma align, structure size alignment)).  */
1.1       root     2377: 
                   2378: int
                   2379: i960_round_align (align, tsize)
                   2380:      int align;
                   2381:      tree tsize;
                   2382: {
1.1.1.4 ! root     2383:   int new_align;
1.1       root     2384: 
                   2385:   if (TREE_CODE (tsize) != INTEGER_CST)
                   2386:     return align;
                   2387: 
1.1.1.4 ! root     2388:   new_align = i960_object_bytes_bitalign (TREE_INT_CST_LOW (tsize)
        !          2389:                                          / BITS_PER_UNIT);
        !          2390:   /* Handle #pragma align.  */
        !          2391:   if (new_align > i960_maxbitalignment)
        !          2392:     new_align = i960_maxbitalignment;
        !          2393: 
        !          2394:   if (align < new_align)
        !          2395:     align = new_align;
        !          2396: 
1.1       root     2397:   return align;
                   2398: }
                   2399: 
                   2400: /* Do any needed setup for a varargs function.  For the i960, we must
                   2401:    create a register parameter block if one doesn't exist, and then copy
                   2402:    all register parameters to memory.  */
                   2403: 
                   2404: void
                   2405: i960_setup_incoming_varargs (cum, mode, type, pretend_size, no_rtl)
                   2406:      CUMULATIVE_ARGS *cum;
                   2407:      enum machine_mode mode;
                   2408:      tree type;
                   2409:      int *pretend_size;
                   2410:      int no_rtl;
                   2411: {
1.1.1.4 ! root     2412:   /* Note: for a varargs fn with only a va_alist argument, this is 0.  */
        !          2413:   int first_reg = cum->ca_nregparms;
1.1       root     2414: 
1.1.1.4 ! root     2415:   /* Copy only unnamed register arguments to memory.  If there are
        !          2416:      any stack parms, there are no unnamed arguments in registers, and
        !          2417:      an argument block was already allocated by the caller.
        !          2418:      Remember that any arg bigger than 4 words is passed on the stack as
        !          2419:      are all subsequent args.
        !          2420: 
        !          2421:      If there are no stack arguments but there are exactly NPARM_REGS
        !          2422:      registers, either there were no extra arguments or the caller
        !          2423:      allocated an argument block. */
        !          2424: 
        !          2425:   if (cum->ca_nstackparms == 0 && first_reg < NPARM_REGS && !no_rtl)
        !          2426:     {
        !          2427:       rtx label = gen_label_rtx ();
        !          2428:       rtx regblock;
        !          2429: 
        !          2430:       /* If arg_pointer_rtx == 0, no arguments were passed on the stack
        !          2431:         and we need to allocate a chunk to save the registers (if any
        !          2432:         arguments were passed on the stack the caller would allocate the
        !          2433:         48 bytes as well).  We must allocate all 48 bytes (12*4) because
        !          2434:         va_start assumes it.  */
        !          2435:       emit_insn (gen_cmpsi (arg_pointer_rtx, const0_rtx));
        !          2436:       emit_jump_insn (gen_bne (label));
        !          2437:       emit_insn (gen_rtx (SET, VOIDmode, arg_pointer_rtx,
        !          2438:                          stack_pointer_rtx));
        !          2439:       emit_insn (gen_rtx (SET, VOIDmode, stack_pointer_rtx,
        !          2440:                          memory_address (SImode,
        !          2441:                                          plus_constant (stack_pointer_rtx,
        !          2442:                                                         48))));
        !          2443:       emit_label (label);
        !          2444: 
        !          2445:       /* ??? Note that we unnecessarily store one extra register for stdarg
        !          2446:         fns.  We could optimize this, but it's kept as for now.  */
        !          2447:       regblock = gen_rtx (MEM, BLKmode,
        !          2448:                          plus_constant (arg_pointer_rtx,
        !          2449:                                         first_reg * 4));
        !          2450:       move_block_from_reg (first_reg, regblock,
        !          2451:                           NPARM_REGS - first_reg,
        !          2452:                           (NPARM_REGS - first_reg) * UNITS_PER_WORD);
1.1       root     2453:     }
                   2454: }
                   2455: 
                   2456: /* Calculate the final size of the reg parm stack space for the current
                   2457:    function, based on how many bytes would be allocated on the stack.  */
                   2458: 
                   2459: int
                   2460: i960_final_reg_parm_stack_space (const_size, var_size)
                   2461:      int const_size;
                   2462:      tree var_size;
                   2463: {
                   2464:   if (var_size || const_size > 48)
                   2465:     return 48;
                   2466:   else
                   2467:     return 0;
                   2468: }
                   2469: 
                   2470: /* Calculate the size of the reg parm stack space.  This is a bit complicated
                   2471:    on the i960.  */
                   2472: 
                   2473: int
                   2474: i960_reg_parm_stack_space (fndecl)
                   2475:      tree fndecl;
                   2476: {
                   2477:   /* In this case, we are called from emit_library_call, and we don't need
                   2478:      to pretend we have more space for parameters than what's apparent.  */
                   2479:   if (fndecl == 0)
                   2480:     return 0;
                   2481: 
                   2482:   /* In this case, we are called from locate_and_pad_parms when we're
                   2483:      not IN_REGS, so we have an arg block.  */
                   2484:   if (fndecl != current_function_decl)
                   2485:     return 48;
                   2486: 
                   2487:   /* Otherwise, we have an arg block if the current function has more than
                   2488:      48 bytes of parameters.  */
1.1.1.3   root     2489:   if (current_function_args_size != 0 || VARARGS_STDARG_FUNCTION (fndecl))
1.1       root     2490:     return 48;
                   2491:   else
                   2492:     return 0;
                   2493: }
                   2494: 
                   2495: /* Return the register class of a scratch register needed to copy IN into
                   2496:    or out of a register in CLASS in MODE.  If it can be done directly,
                   2497:    NO_REGS is returned.  */
                   2498: 
                   2499: enum reg_class
                   2500: secondary_reload_class (class, mode, in)
                   2501:      enum reg_class class;
                   2502:      enum machine_mode mode;
                   2503:      rtx in;
                   2504: {
                   2505:   int regno = -1;
                   2506: 
                   2507:   if (GET_CODE (in) == REG || GET_CODE (in) == SUBREG)
                   2508:     regno = true_regnum (in);
                   2509: 
                   2510:   /* We can place anything into LOCAL_OR_GLOBAL_REGS and can put
                   2511:      LOCAL_OR_GLOBAL_REGS into anything.  */
                   2512:   if (class == LOCAL_OR_GLOBAL_REGS || class == LOCAL_REGS
                   2513:       || class == GLOBAL_REGS || (regno >= 0 && regno < 32))
                   2514:     return NO_REGS;
                   2515: 
                   2516:   /* We can place any hard register, 0.0, and 1.0 into FP_REGS.  */
                   2517:   if (class == FP_REGS
                   2518:       && ((regno >= 0 && regno < FIRST_PSEUDO_REGISTER)
                   2519:          || in == CONST0_RTX (mode) || in == CONST1_RTX (mode)))
                   2520:     return NO_REGS;
                   2521: 
                   2522:   return LOCAL_OR_GLOBAL_REGS;
                   2523: }
                   2524: 
                   2525: /* Look at the opcode P, and set i96_last_insn_type to indicate which
                   2526:    function unit it executed on.  */
                   2527: 
                   2528: /* ??? This would make more sense as an attribute.  */
                   2529: 
                   2530: void
                   2531: i960_scan_opcode (p)
                   2532:      char *p;
                   2533: {
                   2534:   switch (*p)
                   2535:     {
                   2536:     case 'a':
                   2537:     case 'd':
                   2538:     case 'e':
                   2539:     case 'm':
                   2540:     case 'n':
                   2541:     case 'o':
                   2542:     case 'r':
                   2543:       /* Ret is not actually of type REG, but it won't matter, because no
                   2544:         insn will ever follow it.  */
                   2545:     case 'u':
                   2546:     case 'x':
                   2547:       i960_last_insn_type = I_TYPE_REG;
                   2548:       break;
                   2549: 
                   2550:     case 'b':
                   2551:       if (p[1] == 'x' || p[3] == 'x')
                   2552:         i960_last_insn_type = I_TYPE_MEM;
                   2553:       i960_last_insn_type = I_TYPE_CTRL;
                   2554:       break;
                   2555: 
                   2556:     case 'f':
                   2557:     case 't':
                   2558:       i960_last_insn_type = I_TYPE_CTRL;
                   2559:       break;
                   2560: 
                   2561:     case 'c':
                   2562:       if (p[1] == 'a')
                   2563:        {
                   2564:          if (p[4] == 'x')
                   2565:            i960_last_insn_type = I_TYPE_MEM;
                   2566:          else
                   2567:            i960_last_insn_type = I_TYPE_CTRL;
                   2568:        }
                   2569:       else if (p[1] == 'm')
                   2570:        {
                   2571:          if (p[3] == 'd')
                   2572:            i960_last_insn_type = I_TYPE_REG;
                   2573:          else if (p[4] == 'b' || p[4] == 'j')
                   2574:            i960_last_insn_type = I_TYPE_CTRL;
                   2575:          else
                   2576:            i960_last_insn_type = I_TYPE_REG;
                   2577:        }
                   2578:       else
                   2579:         i960_last_insn_type = I_TYPE_REG;
                   2580:       break;
                   2581: 
                   2582:     case 'l':
                   2583:       i960_last_insn_type = I_TYPE_MEM;
                   2584:       break;
                   2585: 
                   2586:     case 's':
                   2587:       if (p[1] == 't')
                   2588:         i960_last_insn_type = I_TYPE_MEM;
                   2589:       else
                   2590:         i960_last_insn_type = I_TYPE_REG;
                   2591:       break;
                   2592:     }
                   2593: }

unix.superglobalmegacorp.com

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