Annotation of GNUtools/cc/config/convex/convex.c, revision 1.1

1.1     ! root        1: /* Subroutines for insn-output.c for Convex.
        !             2:    Copyright (C) 1988, 1993 Free Software Foundation, Inc.
        !             3: 
        !             4: This file is part of GNU CC.
        !             5: 
        !             6: GNU CC is free software; you can redistribute it and/or modify
        !             7: it under the terms of the GNU General Public License as published by
        !             8: the Free Software Foundation; either version 1, or (at your option)
        !             9: any later version.
        !            10: 
        !            11: GNU CC is distributed in the hope that it will be useful,
        !            12: but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            14: GNU General Public License for more details.
        !            15: 
        !            16: You should have received a copy of the GNU General Public License
        !            17: along with GNU CC; see the file COPYING.  If not, write to
        !            18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
        !            19: 
        !            20: #include "config.h"
        !            21: #include "tree.h"
        !            22: #include "rtl.h"
        !            23: #include "regs.h"
        !            24: #include "hard-reg-set.h"
        !            25: #include "real.h"
        !            26: #include "insn-config.h"
        !            27: #include "conditions.h"
        !            28: #include "insn-flags.h"
        !            29: #include "insn-attr.h"
        !            30: #include "output.h"
        !            31: #include "expr.h"
        !            32: 
        !            33: #undef NULL
        !            34: #include <stdio.h>
        !            35: 
        !            36: /* Tables used in convex.h */
        !            37: 
        !            38: char regno_ok_for_index_p_base[1 + LAST_VIRTUAL_REGISTER + 1];
        !            39: enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER];
        !            40: enum reg_class reg_class_from_letter[256];
        !            41: 
        !            42: /* Target cpu index. */
        !            43: 
        !            44: int target_cpu;
        !            45: 
        !            46: /* Boolean to keep track of whether the current section is .text or not.
        !            47:    Used by .align handler in convex.h. */
        !            48: 
        !            49: int current_section_is_text;
        !            50: 
        !            51: /* Communication between output_compare and output_condjump. */
        !            52: 
        !            53: static rtx cmp_operand0, cmp_operand1;
        !            54: static char cmp_modech;
        !            55: 
        !            56: /* Forwards */
        !            57: 
        !            58: static rtx frame_argblock;
        !            59: static int frame_argblock_size;
        !            60: static rtx convert_arg_pushes ();
        !            61: static void expand_movstr_call ();
        !            62: 
        !            63: /* Here from OVERRIDE_OPTIONS at startup.  Initialize constant tables. */
        !            64: 
        !            65: init_convex ()
        !            66: {
        !            67:   int regno;
        !            68: 
        !            69:   /* Set A and S reg classes. */
        !            70:   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
        !            71:     if (A_REGNO_P (regno))
        !            72:       {
        !            73:        regno_ok_for_index_p[regno] = 1;
        !            74:        regno_reg_class[regno] = INDEX_REGS;
        !            75:       }
        !            76:     else
        !            77:       {
        !            78:        regno_ok_for_index_p[regno] = 0;
        !            79:        regno_reg_class[regno] = S_REGS;
        !            80:       }
        !            81: 
        !            82:   /* Can't index off the stack pointer, register 0. */
        !            83:   regno_ok_for_index_p[STACK_POINTER_REGNUM] = 0;
        !            84:   regno_reg_class[STACK_POINTER_REGNUM] = SP_REGS;
        !            85: 
        !            86:   /* Can't index off aliases of the stack pointer.  */
        !            87:   regno_ok_for_index_p[VIRTUAL_INCOMING_ARGS_REGNUM] = 1;
        !            88:   regno_ok_for_index_p[VIRTUAL_STACK_VARS_REGNUM] = 1;
        !            89:   regno_ok_for_index_p[VIRTUAL_STACK_DYNAMIC_REGNUM] = 0;
        !            90:   regno_ok_for_index_p[VIRTUAL_OUTGOING_ARGS_REGNUM] = 0;
        !            91: 
        !            92:   /* Can't index off hard reg -1 == pseudos not assigned */
        !            93:   regno_ok_for_index_p[-1] = 0;
        !            94: 
        !            95:   /* Set reg class letters */
        !            96:   reg_class_from_letter['a'] = A_REGS;
        !            97:   reg_class_from_letter['A'] = INDEX_REGS;
        !            98:   reg_class_from_letter['d'] = S_REGS;
        !            99: 
        !           100:   /* Turn off floating point exception enables in the psw. */
        !           101:   psw_disable_float ();
        !           102: }
        !           103: 
        !           104: psw_disable_float ()
        !           105: {
        !           106: #if __convex__ && __GNUC__
        !           107:   register int *p;
        !           108:   asm ("mov fp,%0" : "=a" (p));
        !           109:   while (p)
        !           110:     {
        !           111:       p[1] &= ~0x1000c400;
        !           112:       p = (int *) p[2];
        !           113:     }
        !           114: #endif  
        !           115: }
        !           116: 
        !           117: /* Here to output code for a compare insn.  Output nothing, just
        !           118:    record the operands and their mode. */
        !           119: 
        !           120: char *
        !           121: output_cmp (operand0, operand1, modech)
        !           122:      rtx operand0, operand1;
        !           123:      char modech;
        !           124: {
        !           125:   cmp_operand0 = operand0;
        !           126:   cmp_operand1 = operand1;
        !           127:   cmp_modech = modech;
        !           128:   return "";
        !           129: }
        !           130: 
        !           131: /* Output code for a conditional jump.  The preceding instruction
        !           132:    is necessarily a compare.  Output two instructions, for example
        !           133:        eq.w a1,a2
        !           134:        jbra.t L5
        !           135:    for
        !           136:        (cmpsi a1 a2)
        !           137:        (beq L5)
        !           138:  */
        !           139: 
        !           140: char *
        !           141: output_condjump (label, cond, jbr_sense)
        !           142:      rtx label;
        !           143:      char *cond;
        !           144:      char jbr_sense;
        !           145: {
        !           146:   rtx operands[3];
        !           147:   char cmp_op[4];
        !           148:   char buf[80];
        !           149:   char jbr_regch;
        !           150: 
        !           151:   strcpy (cmp_op, cond);
        !           152: 
        !           153:   /* [BL] mean the value is being compared against immediate 0.
        !           154:      Use neg.x, which produces the same carry that eq.x #0 would if it
        !           155:      existed.  In this case operands[1] is a scratch register, not a
        !           156:      compare operand. */
        !           157: 
        !           158:   if (cmp_modech == 'B' || cmp_modech == 'L')
        !           159:     {
        !           160:       cmp_modech = cmp_modech - 'A' + 'a';
        !           161:       strcpy (cmp_op, "neg");
        !           162:     }
        !           163: 
        !           164:   /* [WH] mean the value being compared resulted from "add.[wh] #-1,rk"
        !           165:      when rk was nonnegative -- we can omit equality compares against -1
        !           166:      or inequality compares against 0. */
        !           167: 
        !           168:   else if (cmp_modech == 'W' || cmp_modech == 'H')
        !           169:     {
        !           170:       if (! strcmp (cmp_op, "eq") && cmp_operand1 == constm1_rtx)
        !           171:        jbr_sense ^= 't' ^ 'f';
        !           172:       else if (! strcmp (cmp_op, "lt") && cmp_operand1 == const0_rtx)
        !           173:        ;
        !           174:       else
        !           175:        cmp_modech = cmp_modech - 'A' + 'a';
        !           176:     }
        !           177: 
        !           178:   /* Constant must be first; swap operands if necessary.
        !           179:      If lt, le, ltu, leu are swapped, change to le, lt, leu, ltu
        !           180:      and reverse the sense of the jump. */
        !           181: 
        !           182:   if (! REG_P (cmp_operand1))
        !           183:     {
        !           184:       operands[0] = cmp_operand1;
        !           185:       operands[1] = cmp_operand0;
        !           186:       if (cmp_op[0] == 'l')
        !           187:        {
        !           188:          cmp_op[1] ^= 'e' ^ 't';
        !           189:          jbr_sense ^= 't' ^ 'f';
        !           190:        }
        !           191:     }
        !           192:   else
        !           193:     {
        !           194:       operands[0] = cmp_operand0;
        !           195:       operands[1] = cmp_operand1;
        !           196:     }
        !           197: 
        !           198:   operands[2] = label;
        !           199: 
        !           200:   if (S_REG_P (operands[1]))
        !           201:     jbr_regch = 's';
        !           202:   else if (A_REG_P (operands[1]))
        !           203:     jbr_regch = 'a';
        !           204:   else
        !           205:     abort ();
        !           206: 
        !           207:   if (cmp_modech == 'W' || cmp_modech == 'H')
        !           208:     sprintf (buf, "jbr%c.%c %%l2", jbr_regch, jbr_sense);
        !           209:   else
        !           210:     sprintf (buf, "%s.%c %%0,%%1\n\tjbr%c.%c %%l2",
        !           211:             cmp_op, cmp_modech, jbr_regch, jbr_sense);
        !           212:   output_asm_insn (buf, operands);
        !           213:   return "";
        !           214: }
        !           215: 
        !           216: /* Return 1 if OP is valid for cmpsf.
        !           217:    In IEEE mode, +/- zero compares are not handled by 
        !           218:      the immediate versions of eq.s and on some machines, lt.s, and le.s.  
        !           219:    So disallow 0.0 as the immediate operand of xx.s compares in IEEE mode. */
        !           220: 
        !           221: int
        !           222: nonmemory_cmpsf_operand (op, mode)
        !           223:      rtx op;
        !           224:      enum machine_mode mode;
        !           225: {
        !           226: #if _IEEE_FLOAT_
        !           227:   if (op == CONST0_RTX (SFmode))
        !           228:     return 0;
        !           229: #endif
        !           230: 
        !           231:   return nonmemory_operand (op, mode);
        !           232: }
        !           233: 
        !           234: /* Convex /bin/as does not like unary minus in some contexts.
        !           235:    Simplify CONST addresses to remove it. */
        !           236: 
        !           237: rtx
        !           238: simplify_for_convex (x)
        !           239:      rtx x;
        !           240: {
        !           241:   switch (GET_CODE (x))
        !           242:     {
        !           243:     case MINUS:
        !           244:       if (GET_CODE (XEXP (x, 1)) == CONST_INT
        !           245:          && INTVAL (XEXP (x, 1)) < 0)
        !           246:        {
        !           247:          PUT_CODE (x, PLUS);
        !           248:          XEXP (x, 1) = GEN_INT (- INTVAL (XEXP (x, 1)));
        !           249:        }
        !           250:       break;
        !           251: 
        !           252:     case CONST:
        !           253:       return simplify_for_convex (XEXP (x, 0));
        !           254:     }
        !           255: 
        !           256:   return x;
        !           257: }
        !           258: 
        !           259: /* Routines to separate CONST_DOUBLEs into component parts. */
        !           260: 
        !           261: int
        !           262: const_double_high_int (x)
        !           263:      rtx x;
        !           264: {
        !           265:   if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
        !           266:     return CONST_DOUBLE_LOW (x);
        !           267:   else
        !           268:     return CONST_DOUBLE_HIGH (x);
        !           269: }
        !           270: 
        !           271: int
        !           272: const_double_low_int (x)
        !           273:      rtx x;
        !           274: {
        !           275:   if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
        !           276:     return CONST_DOUBLE_HIGH (x);
        !           277:   else
        !           278:     return CONST_DOUBLE_LOW (x);
        !           279: }
        !           280: 
        !           281: /* Inline block copy. */
        !           282: 
        !           283: void
        !           284: expand_movstr (operands)
        !           285:      rtx *operands;
        !           286: {
        !           287:   rtx dest = operands[0];
        !           288:   rtx src = operands[1];
        !           289:   int align = INTVAL (operands[3]);
        !           290:   int nregs, maxsize;
        !           291:   unsigned len;
        !           292:   enum machine_mode mode;
        !           293:   rtx reg, load, store, prev_store, prev_store_2;
        !           294:   int size;
        !           295: 
        !           296:   /* Decide how many regs to use, depending on load latency, and what
        !           297:      size pieces to move, depending on whether machine does unaligned
        !           298:      loads and stores efficiently. */
        !           299: 
        !           300:   if (TARGET_C1)
        !           301:     {
        !           302:       /* ld.l latency is 4, no alignment problems. */
        !           303:       nregs = 3, maxsize = 8;
        !           304:     }
        !           305:   else if (TARGET_C2)
        !           306:     {
        !           307:       /* loads are latency 2 if we avoid ld.l not at least word aligned. */
        !           308:       if (align >= 4)
        !           309:        nregs = 2, maxsize = 8;
        !           310:       else
        !           311:        nregs = 2, maxsize = 4;
        !           312:     }
        !           313:   else if (TARGET_C34)
        !           314:     {
        !           315:       /* latency is 4 if aligned, horrible if not. */
        !           316:       nregs = 3, maxsize = align;
        !           317:     }
        !           318:   else if (TARGET_C38)
        !           319:     {
        !           320:       /* latency is 2 if at least word aligned, 3 or 4 if unaligned. */
        !           321:       if (align >= 4)
        !           322:        nregs = 2, maxsize = 8;
        !           323:       else
        !           324:        nregs = 3, maxsize = 8;
        !           325:     }
        !           326:   else
        !           327:     abort ();
        !           328: 
        !           329:   /* Caller is not necessarily prepared for us to fail in this
        !           330:      expansion.  So fall back by generating memcpy call here. */
        !           331: 
        !           332:   if (GET_CODE (operands[2]) != CONST_INT
        !           333:       || (len = INTVAL (operands[2])) > (unsigned) 32 * maxsize)
        !           334:     {
        !           335:       expand_movstr_call (operands);
        !           336:       return;
        !           337:     }
        !           338: 
        !           339:   reg = 0;
        !           340:   prev_store = prev_store_2 = 0;
        !           341: 
        !           342:   while (len > 0)
        !           343:     {
        !           344:       if (len >= 8 && maxsize >= 8)
        !           345:        mode = DImode;
        !           346:       else if (len >= 4 && maxsize >= 4)
        !           347:        mode = SImode;
        !           348:       else if (len >= 2 && maxsize >= 2)
        !           349:        mode = HImode;
        !           350:       else
        !           351:        mode = QImode;
        !           352: 
        !           353:       /* If no temp pseudo to reuse, or not the right mode, make one */
        !           354:       if (! reg || GET_MODE (reg) != mode)
        !           355:        reg = gen_reg_rtx (mode);
        !           356: 
        !           357:       /* Get src and dest in the right mode */
        !           358:       if (GET_MODE (src) != mode)
        !           359:        src = change_address (src, mode, 0),
        !           360:        dest = change_address (dest, mode, 0);
        !           361: 
        !           362:       /* Make load and store patterns for this piece */
        !           363:       load = gen_rtx (SET, VOIDmode, reg, src);
        !           364:       store = gen_rtx (SET, VOIDmode, dest, reg);
        !           365: 
        !           366:       /* Emit the load and the store from last time. 
        !           367:         When we emit a store, we can reuse its temp reg. */
        !           368:       emit_insn (load);
        !           369:       if (prev_store)
        !           370:        {
        !           371:          reg = SET_SRC (prev_store);
        !           372:          emit_insn (prev_store);
        !           373:        }
        !           374:       else
        !           375:        reg = 0;
        !           376: 
        !           377:       /* Queue up the store, for next time or the time after that. */
        !           378:       if (nregs == 2)
        !           379:        prev_store = store;
        !           380:       else
        !           381:        prev_store = prev_store_2, prev_store_2 = store;
        !           382: 
        !           383:       /* Advance to next piece. */
        !           384:       size = GET_MODE_SIZE (mode);
        !           385:       src = adj_offsettable_operand (src, size);
        !           386:       dest = adj_offsettable_operand (dest, size);
        !           387:       len -= size;
        !           388:     }
        !           389: 
        !           390:   /* Finally, emit the last stores. */
        !           391:   if (prev_store)
        !           392:     emit_insn (prev_store);
        !           393:   if (prev_store_2)
        !           394:     emit_insn (prev_store_2);
        !           395: }
        !           396: 
        !           397: static void
        !           398: expand_movstr_call (operands)
        !           399:      rtx *operands;
        !           400: {
        !           401:   emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "memcpy"), 0,
        !           402:                     VOIDmode, 3,
        !           403:                     XEXP (operands[0], 0), Pmode,
        !           404:                     XEXP (operands[1], 0), Pmode,
        !           405:                     operands[2], SImode);
        !           406: }
        !           407: 
        !           408: #if _IEEE_FLOAT_
        !           409: #define MAX_FLOAT 3.4028234663852886e+38
        !           410: #define MIN_FLOAT 1.1754943508222875e-38
        !           411: #else
        !           412: #define MAX_FLOAT 1.7014117331926443e+38
        !           413: #define MIN_FLOAT 2.9387358770557188e-39
        !           414: #endif
        !           415: 
        !           416: void
        !           417: check_float_value (mode, dp)
        !           418:      enum machine_mode mode;
        !           419:      REAL_VALUE_TYPE *dp;
        !           420: {
        !           421:   REAL_VALUE_TYPE d = *dp;
        !           422: 
        !           423:   if (mode == SFmode)
        !           424:     {
        !           425:       if (d > MAX_FLOAT)
        !           426:        {
        !           427:          error ("magnitude of constant too large for `float'");
        !           428:          *dp = MAX_FLOAT;
        !           429:        }
        !           430:       else if (d < -MAX_FLOAT)
        !           431:        {
        !           432:          error ("magnitude of constant too large for `float'");
        !           433:          *dp = -MAX_FLOAT;
        !           434:        }       
        !           435:       else if ((d > 0 && d < MIN_FLOAT) || (d < 0 && d > -MIN_FLOAT))
        !           436:        {
        !           437:          warning ("`float' constant truncated to zero");
        !           438:          *dp = 0.0;
        !           439:        }
        !           440:     }
        !           441: }
        !           442: 
        !           443: /* Output the label at the start of a function.
        !           444:    Precede it with the number of formal args so debuggers will have
        !           445:    some idea of how many args to print. */
        !           446: 
        !           447: void
        !           448: asm_declare_function_name (file, name, decl)
        !           449:     FILE *file;
        !           450:     char *name;
        !           451:     tree decl;
        !           452: {
        !           453:   tree parms;
        !           454:   int nargs = list_length (DECL_ARGUMENTS (decl));
        !           455: 
        !           456:   char *p, c;
        !           457:   extern char *version_string;
        !           458:   static char vers[4];
        !           459:   int i;
        !           460:   
        !           461:   p = version_string;
        !           462:   for (i = 0; i < 3; ) {
        !           463:     c = *p;
        !           464:     if (c - '0' < (unsigned) 10)
        !           465:       vers[i++] = c;
        !           466:     if (c == 0 || c == ' ')
        !           467:       vers[i++] = '0';
        !           468:     else
        !           469:       p++;
        !           470:   }
        !           471:   fprintf (file, "\tds.b \"g%s\"\n", vers);
        !           472: 
        !           473:   if (nargs < 100)
        !           474:     fprintf (file, "\tds.b \"+%02d\\0\"\n", nargs);
        !           475:   else
        !           476:     fprintf (file, "\tds.b \"+00\\0\"\n");
        !           477: 
        !           478:   ASM_OUTPUT_LABEL (file, name);
        !           479: }
        !           480: 
        !           481: /* Print an instruction operand X on file FILE.
        !           482:    CODE is the code from the %-spec that requested printing this operand;
        !           483:    if `%z3' was used to print operand 3, then CODE is 'z'. */
        !           484: /* Convex codes:
        !           485:     %u prints a CONST_DOUBLE's high word
        !           486:     %v prints a CONST_DOUBLE's low word
        !           487:     %z prints a CONST_INT shift count as a multiply operand -- viz. 1 << n.
        !           488:  */
        !           489: 
        !           490: print_operand (file, x, code)
        !           491:      FILE *file;
        !           492:      rtx x;
        !           493:      char code;
        !           494: {
        !           495:   long u[2];
        !           496:   REAL_VALUE_TYPE d;
        !           497: 
        !           498:   switch (GET_CODE (x))
        !           499:     {
        !           500:     case REG:
        !           501:       fprintf (file, "%s", reg_names[REGNO (x)]);
        !           502:       break;
        !           503: 
        !           504:     case MEM:
        !           505:       output_address (XEXP (x, 0));
        !           506:       break;
        !           507: 
        !           508:     case CONST_DOUBLE:
        !           509:       REAL_VALUE_FROM_CONST_DOUBLE (d, x);
        !           510:       switch (GET_MODE (x)) {
        !           511:       case DFmode:
        !           512: #if 0 /* doesn't work, produces dfloats */
        !           513:        REAL_VALUE_TO_TARGET_DOUBLE (d, u); 
        !           514: #else
        !           515:        {
        !           516:          union { double d; int i[2]; } t;
        !           517:          t.d = d;
        !           518:          u[0] = t.i[0];
        !           519:          u[1] = t.i[1];
        !           520:        }
        !           521: #endif
        !           522:        if (code == 'u')
        !           523:          fprintf (file, "#%#x", u[0]);
        !           524:        else if (code == 'v')
        !           525:          fprintf (file, "#%#x", u[1]);
        !           526:        else
        !           527:          outfloat (file, d, "%.17e", "#", "");
        !           528:        break;
        !           529:       case SFmode:
        !           530:        outfloat (file, d, "%.9e", "#", "");
        !           531:        break;
        !           532:       default:
        !           533:        if (code == 'u')
        !           534:          fprintf (file, "#%d", CONST_DOUBLE_HIGH (x));
        !           535:        else
        !           536:          fprintf (file, "#%d", CONST_DOUBLE_LOW (x));
        !           537:       }
        !           538:       break;
        !           539: 
        !           540:     default:
        !           541:       if (code == 'z')
        !           542:        {
        !           543:          if (GET_CODE (x) != CONST_INT)
        !           544:            abort ();
        !           545:          fprintf (file, "#%d", 1 << INTVAL (x));
        !           546:        }
        !           547:       else
        !           548:        {
        !           549:          putc ('#', file);
        !           550:          output_addr_const (file, x);
        !           551:        }
        !           552:     }
        !           553: }
        !           554: 
        !           555: /* Print a memory operand whose address is X, on file FILE. */
        !           556: 
        !           557: print_operand_address (file, addr)
        !           558:      FILE *file;
        !           559:      rtx addr;
        !           560: {
        !           561:   rtx index = 0;
        !           562:   rtx offset = 0;
        !           563: 
        !           564:   if (GET_CODE (addr) == MEM)
        !           565:     {
        !           566:       fprintf (file, "@");
        !           567:       addr = XEXP (addr, 0);
        !           568:     }
        !           569: 
        !           570:   switch (GET_CODE (addr))
        !           571:     {
        !           572:     case REG:
        !           573:       index = addr;
        !           574:       break;
        !           575: 
        !           576:     case PLUS:
        !           577:       index = XEXP (addr, 0);
        !           578:       if (REG_P (index))
        !           579:        offset = XEXP (addr, 1);
        !           580:       else
        !           581:        {
        !           582:          offset = XEXP (addr, 0);
        !           583:          index = XEXP (addr, 1);
        !           584:          if (! REG_P (index))
        !           585:            abort ();
        !           586:         }
        !           587:       break;
        !           588: 
        !           589:     default:
        !           590:       offset = addr;
        !           591:       break;
        !           592:     }
        !           593: 
        !           594:   if (offset)
        !           595:     output_addr_const (file, offset);
        !           596: 
        !           597:   if (index)
        !           598:     fprintf (file, "(%s)", reg_names[REGNO (index)]);
        !           599: }
        !           600: 
        !           601: /* Output a float to FILE, value VALUE, format FMT, preceded by PFX
        !           602:    and followed by SFX. */
        !           603: 
        !           604: outfloat (file, value, fmt, pfx, sfx)
        !           605:      FILE *file;
        !           606:      REAL_VALUE_TYPE value;
        !           607:      char *fmt, *pfx, *sfx;
        !           608: {
        !           609:   char buf[64];
        !           610:   fputs (pfx, file);
        !           611:   REAL_VALUE_TO_DECIMAL (value, fmt, buf);
        !           612:   fputs (buf, file);
        !           613:   fputs (sfx, file);
        !           614: }
        !           615: 
        !           616: /* Here during RTL generation of return.  If we are at the final return
        !           617:    in a function, go through the function and replace pushes with stores
        !           618:    into a frame arg block.  This is similar to what ACCUMULATE_OUTGOING_ARGS
        !           619:    does, but we must index off the frame pointer, not the stack pointer,
        !           620:    and the calling sequence does not require the arg block to be at the
        !           621:    top of the stack.  */
        !           622: 
        !           623: replace_arg_pushes ()
        !           624: {
        !           625:   /* Doesn't work yet. */
        !           626: }
        !           627: 
        !           628: /* Output the insns needed to do a call.  operands[] are
        !           629:      0 - MEM, the place to call
        !           630:      1 - CONST_INT, the number of bytes in the arg list
        !           631:      2 - CONST_INT, the number of arguments
        !           632:      3 - CONST_INT, the number of bytes to pop
        !           633:      4 - address of the arg list.  
        !           634:  */
        !           635: 
        !           636: char *
        !           637: output_call (insn, operands)
        !           638:      rtx insn, *operands;
        !           639: {
        !           640:   if (operands[4] == stack_pointer_rtx)
        !           641:     output_asm_insn ("mov sp,ap", operands);
        !           642:   else
        !           643:     abort ();
        !           644: 
        !           645:   if (TARGET_ARGCOUNT)
        !           646:     output_asm_insn ("pshea %a2", operands);
        !           647: 
        !           648:   output_asm_insn ("calls %0", operands);
        !           649: 
        !           650:   output_asm_insn ("ld.w 12(fp),ap", operands);
        !           651: 
        !           652:   if (operands[4] == stack_pointer_rtx && operands[3] != const0_rtx)
        !           653:     output_asm_insn ("add.w %3,sp", operands);
        !           654: 
        !           655:   return "";
        !           656: }
        !           657: 
        !           658: 
        !           659: /* Here after reloading, before the second scheduling pass. */
        !           660: 
        !           661: emit_ap_optimizations ()
        !           662: {
        !           663:   /* Removed for now. */
        !           664: }
        !           665: 

unix.superglobalmegacorp.com

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