Annotation of GNUtools/cc/config/clipper/clipper.c, revision 1.1.1.1

1.1       root        1: /* Subroutines for insn-output.c for Clipper
                      2:    Copyright (C) 1987, 1988, 1991 Free Software Foundation, Inc.
                      3: 
                      4:    Contributed by Holger Teutsch ([email protected])
                      5: 
                      6: This file is part of GNU CC.
                      7: 
                      8: GNU CC is free software; you can redistribute it and/or modify
                      9: it under the terms of the GNU General Public License as published by
                     10: the Free Software Foundation; either version 2, or (at your option)
                     11: any later version.
                     12: 
                     13: GNU CC is distributed in the hope that it will be useful,
                     14: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     15: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     16: GNU General Public License for more details.
                     17: 
                     18: You should have received a copy of the GNU General Public License
                     19: along with GNU CC; see the file COPYING.  If not, write to
                     20: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
                     21: 
                     22: #include <stdio.h>
                     23: #include "config.h"
                     24: #include "rtl.h"
                     25: #include "regs.h"
                     26: #include "hard-reg-set.h"
                     27: #include "real.h"
                     28: #include "insn-config.h"
                     29: #include "conditions.h"
                     30: #include "insn-flags.h"
                     31: #include "output.h"
                     32: #include "insn-attr.h"
                     33: #include "tree.h"
                     34: #include "c-tree.h"
                     35: #include "expr.h"
                     36: #include "flags.h"
                     37: #include "machmode.h"
                     38: 
                     39: extern char regs_ever_live[];
                     40: 
                     41: extern int frame_pointer_needed;
                     42: 
                     43: static int frame_size;
                     44: 
                     45: /*
                     46:  * compute size of a clipper stack frame where 'lsize' is the required
                     47:  * space for local variables.
                     48:  */
                     49: 
                     50: int
                     51: clipper_frame_size (lsize)
                     52:      int lsize;
                     53: {
                     54:   int i,size;                          /* total size of frame */
                     55:   int save_size;
                     56:   save_size = 0;                       /* compute size for reg saves */
                     57: 
                     58:   for (i = 16; i < 32; i++)
                     59:     if (regs_ever_live[i] && !call_used_regs[i])
                     60:       save_size += 8;
                     61: 
                     62:   for (i = 0; i < 16; i++)
                     63:     if (regs_ever_live[i] && !call_used_regs[i])
                     64:       save_size += 4;
                     65: 
                     66:   size = lsize + save_size;
                     67: 
                     68:   size = (size + 7) & ~7;              /* align to 64 Bit */
                     69:   return size;
                     70: }
                     71: 
                     72: /*
                     73:  * prologue and epilogue output
                     74:  * function is entered with pc pushed, i.e. stack is 32 bit aligned
                     75:  *
                     76:  * current_function_args_size == 0 means that the current function's args
                     77:  * are passed totally in registers i.e fp is not used as ap.
                     78:  * If frame_size is also 0 the current function does not push anything and
                     79:  * can run with misaligned stack -> subq $4,sp / add $4,sp on entry and exit
                     80:  * can be omitted.
                     81:  *
                     82:  */
                     83: void
                     84: output_function_prologue (file, lsize)
                     85:      FILE *file;
                     86:      int lsize;                                /* size for locals */
                     87: {
                     88:   int i, offset;
                     89:   int size;
                     90: 
                     91:   frame_size = size = clipper_frame_size (lsize);
                     92: 
                     93:   if (frame_pointer_needed)
                     94:     {
                     95:       fputs ("\tpushw  fp,sp\n", file);
                     96:       fputs ("\tmovw   sp,fp\n", file);
                     97:     }
                     98:   else if (size != 0 || current_function_args_size != 0)
                     99:     {
                    100:       size += 4;                       /* keep stack aligned */
                    101:       frame_size = size;               /* must push data or access args */
                    102:     }
                    103: 
                    104:   if (size)
                    105:     {
                    106:       if (size < 16)
                    107:        fprintf (file, "\tsubq   $%d,sp\n", size);
                    108:       else
                    109:        fprintf (file, "\tsubi   $%d,sp\n", size);
                    110: 
                    111:       /* register save slots are relative to sp, because we have small positive
                    112:         displacements and this works whether we have a frame pointer or not */
                    113: 
                    114:       offset = 0;
                    115:       for (i = 16; i < 32; i++)
                    116:        if (regs_ever_live[i] && !call_used_regs[i])
                    117:          {
                    118:            if (offset == 0)
                    119:              fprintf (file, "\tstord  f%d,(sp)\n", i-16);
                    120:            else
                    121:              fprintf (file, "\tstord  f%d,%d(sp)\n", i-16, offset);
                    122:            offset += 8;
                    123:          }
                    124: 
                    125:       for (i = 0; i < 16; i++)
                    126:        if (regs_ever_live[i] && !call_used_regs[i])
                    127:          {
                    128:            if (offset == 0)
                    129:              fprintf (file, "\tstorw  r%d,(sp)\n", i);
                    130:            else
                    131:              fprintf (file, "\tstorw  r%d,%d(sp)\n", i, offset);
                    132:            offset += 4;
                    133:          }
                    134:     }
                    135: }
                    136: 
                    137: void
                    138: output_function_epilogue (file, size)
                    139:      FILE *file;
                    140:      int size;                         /* ignored */
                    141: {
                    142:   int i, offset;
                    143: 
                    144:   if (frame_pointer_needed)
                    145:     {
                    146:       offset = -frame_size;
                    147: 
                    148:       for (i = 16; i < 32; i++)
                    149:        if (regs_ever_live[i] && !call_used_regs[i])
                    150:          {
                    151:            fprintf (file, "\tloadd  %d(fp),f%d\n", offset, i-16);
                    152:            offset += 8;
                    153:          }
                    154: 
                    155:       for (i = 0; i < 16; i++)
                    156:        if (regs_ever_live[i] && !call_used_regs[i])
                    157:          {
                    158:            fprintf (file, "\tloadw  %d(fp),r%d\n", offset, i);
                    159:            offset += 4;
                    160:          }
                    161: 
                    162:       fputs ("\tmovw   fp,sp\n\tpopw   sp,fp\n\tret    sp\n",
                    163:             file);
                    164:     }
                    165: 
                    166:   else                                 /* no frame pointer */
                    167:     {
                    168:       offset = 0;
                    169: 
                    170:       for (i = 16; i < 32; i++)
                    171:        if (regs_ever_live[i] && !call_used_regs[i])
                    172:          {
                    173:            if (offset == 0)
                    174:              fprintf (file, "\tloadd  (sp),f%d\n", i-16);
                    175:            else
                    176:              fprintf (file, "\tloadd  %d(sp),f%d\n", offset, i-16);
                    177:            offset += 8;
                    178:          }
                    179: 
                    180:       for (i = 0; i < 16; i++)
                    181:        if (regs_ever_live[i] && !call_used_regs[i])
                    182:          {
                    183:            if (offset == 0)
                    184:              fprintf (file, "\tloadw  (sp),r%d\n", i);
                    185:            else
                    186:              fprintf (file, "\tloadw  %d(sp),r%d\n", offset, i);
                    187:            offset += 4;
                    188:          }
                    189: 
                    190:       if (frame_size > 0)
                    191:        {
                    192:          if (frame_size < 16)
                    193:            fprintf (file, "\taddq   $%d,sp\n", frame_size);
                    194:          else
                    195:            fprintf (file, "\taddi   $%d,sp\n", frame_size);
                    196:        }
                    197: 
                    198:       fputs ("\tret    sp\n", file);
                    199:     }
                    200: }
                    201: 
                    202: /*
                    203:  * blockmove
                    204:  *
                    205:  * clipper_movstr ()
                    206:  */
                    207: void
                    208: clipper_movstr (operands)
                    209:      rtx *operands;
                    210: {
                    211:   rtx dst,src,cnt,tmp,top,bottom,xops[3];
                    212:   int align;
                    213:   int fixed;
                    214: 
                    215:   extern FILE *asm_out_file;
                    216: 
                    217:   dst = operands[0];
                    218:   src = operands[1];
                    219:   /* don't change this operands[2]; gcc 2.3.3 doesn't honor clobber note */
                    220:   align = INTVAL (operands[3]);
                    221:   tmp = operands[4];
                    222:   cnt = operands[5];
                    223: 
                    224:   if (GET_CODE (operands[2]) == CONST_INT) /* fixed size move */
                    225:     {
                    226:       if ((fixed = INTVAL (operands[2])) <= 0)
                    227:        abort ();
                    228: 
                    229:       if (fixed <16)
                    230:        output_asm_insn ("loadq  %2,%5", operands);
                    231:       else
                    232:        output_asm_insn ("loadi  %2,%5", operands);
                    233:     }
                    234:   else
                    235:     {
                    236:       fixed = 0;
                    237:       bottom = (rtx)gen_label_rtx ();  /* need a bottom label */
                    238:       xops[0] = cnt; xops[1] = bottom;
                    239:       output_asm_insn ("movw   %2,%5", operands); /* count is scratch reg 5 */
                    240:       output_asm_insn ("brle   %l1", xops);
                    241:     }
                    242: 
                    243: 
                    244:   top = (rtx)gen_label_rtx ();         /* top of loop label */
                    245:   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (top));
                    246: 
                    247: 
                    248:   xops[0] = src; xops[1] = tmp; xops[2] = dst;
                    249: 
                    250:   if (fixed && (align & 0x3) == 0)     /* word aligned move with known size */
                    251:     {
                    252:       if (fixed >= 4)
                    253:        {
                    254:          rtx xops1[2];
                    255:          output_asm_insn(
                    256:            "loadw  %a0,%1\n\taddq   $4,%0\n\tstorw  %1,%a2\n\taddq   $4,%2",
                    257:                          xops);
                    258: 
                    259:          xops1[0] = cnt; xops1[1] = top;
                    260:          output_asm_insn ("subq   $4,%0\n\tbrgt   %l1", xops1);
                    261:        }
                    262: 
                    263:       if (fixed & 0x2)
                    264:        {
                    265:          output_asm_insn ("loadh  %a0,%1\n\tstorh  %1,%a2", xops);
                    266:          if (fixed & 0x1)
                    267:            output_asm_insn ("loadb  2%a0,%1\n\tstorb  %1,2%a2", xops);
                    268:        }
                    269:       else
                    270:        if (fixed & 0x1)
                    271:          output_asm_insn ("loadb  %a0,%1\n\tstorb  %1,%a2", xops);
                    272:     }
                    273:   else
                    274:     {
                    275:       output_asm_insn(
                    276:          "loadb  %a0,%1\n\taddq   $1,%0\n\tstorb  %1,%a2\n\taddq   $1,%2",
                    277:                      xops);
                    278: 
                    279:       xops[0] = cnt; xops[1] = top;
                    280:       output_asm_insn ("subq   $1,%0\n\tbrgt   %l1", xops);
                    281:     }
                    282: 
                    283:   if (fixed == 0)
                    284:     ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (bottom));
                    285: }
                    286: 
                    287: 
                    288: print_operand_address (file, addr)
                    289:      FILE *file;
                    290:      register rtx addr;
                    291: {
                    292:   rtx op0,op1;
                    293: 
                    294:  retry:
                    295:   switch (GET_CODE (addr))
                    296:     {
                    297:     case REG:
                    298:       fprintf (file, "(%s)", reg_names[REGNO (addr)]);
                    299:       break;
                    300: 
                    301:     case PLUS:
                    302:       /* can be 'symbol + reg' or 'reg + reg' */
                    303: 
                    304:       op0 = XEXP (addr, 0);
                    305:       op1 = XEXP (addr, 1);
                    306: 
                    307:       if (GET_CODE (op0) == REG && GET_CODE (op1) == REG)
                    308:        {
                    309:          fprintf (file, "[%s](%s)",
                    310:                   reg_names[REGNO (op0)], reg_names[REGNO (op1)]);
                    311:          break;
                    312:        }
                    313: 
                    314:       if (GET_CODE (op0) == REG && CONSTANT_ADDRESS_P (op1))
                    315:        {
                    316:          output_addr_const (file, op1);
                    317:          fprintf (file, "(%s)", reg_names[REGNO (op0)]);
                    318:          break;
                    319:        }
                    320: 
                    321:       if (GET_CODE (op1) == REG && CONSTANT_ADDRESS_P (op0))
                    322:        {
                    323:          output_addr_const (file, op0);
                    324:          fprintf (file, "(%s)", reg_names[REGNO (op1)]);
                    325:          break;
                    326:        }
                    327:       abort ();                                /* Oh no */
                    328: 
                    329:     default:
                    330:       output_addr_const (file, addr);
                    331:     }
                    332: }
                    333: 
                    334: 
                    335: char *
                    336: rev_cond_name (op)
                    337:      rtx op;
                    338: {
                    339:   switch (GET_CODE (op))
                    340:     {
                    341:     case EQ:
                    342:       return "ne";
                    343:     case NE:
                    344:       return "eq";
                    345:     case LT:
                    346:       return "ge";
                    347:     case LE:
                    348:       return "gt";
                    349:     case GT:
                    350:       return "le";
                    351:     case GE:
                    352:       return "lt";
                    353:     case LTU:
                    354:       return "geu";
                    355:     case LEU:
                    356:       return "gtu";
                    357:     case GTU:
                    358:       return "leu";
                    359:     case GEU:
                    360:       return "ltu";
                    361: 
                    362:     default:
                    363:       abort ();
                    364:     }
                    365: }
                    366: 
                    367: 
                    368: /* Do what is necessary for `va_start'.  The argument is ignored;
                    369:    We fill in an initial va_list.  A pointer to this constructor
                    370:    is returned. */
                    371: 
                    372: 
                    373: struct rtx_def *
                    374: clipper_builtin_saveregs (arglist)
                    375:      tree arglist;
                    376: {
                    377:   extern int current_function_varargs;
                    378:   rtx block, addr, argsize, scratch, r0_addr,r1_addr,f0_addr,f1_addr;
                    379: 
                    380:   /* Allocate the va_list constructor + save area for r0,r1,f0,f1 */
                    381: 
                    382:   block = assign_stack_local (BLKmode,
                    383:                              (6 + 6) * UNITS_PER_WORD, 2 * BITS_PER_WORD);
                    384: 
                    385:   RTX_UNCHANGING_P (block) = 1;
                    386:   RTX_UNCHANGING_P (XEXP (block, 0)) = 1;
                    387: 
                    388:   addr = copy_to_reg (XEXP (block, 0));
                    389: 
                    390:   f0_addr =  gen_rtx (PLUS, Pmode, addr, gen_rtx (CONST_INT, Pmode, 24));
                    391:   f1_addr =  gen_rtx (PLUS, Pmode, addr, gen_rtx (CONST_INT, Pmode, 32));
                    392:   r0_addr =  gen_rtx (PLUS, Pmode, addr, gen_rtx (CONST_INT, Pmode, 40));
                    393:   r1_addr =  gen_rtx (PLUS, Pmode, addr, gen_rtx (CONST_INT, Pmode, 44));
                    394: 
                    395: 
                    396:   /* Store float regs  */
                    397: 
                    398:   emit_move_insn (gen_rtx (MEM, DFmode, f0_addr), gen_rtx (REG, DFmode, 16));
                    399:   emit_move_insn (gen_rtx (MEM, DFmode, f1_addr), gen_rtx (REG, DFmode, 17));
                    400: 
                    401:   /* Store int regs  */
                    402: 
                    403:   emit_move_insn (gen_rtx (MEM, SImode, r0_addr), gen_rtx (REG, SImode, 0));
                    404:   emit_move_insn (gen_rtx (MEM, SImode, r1_addr), gen_rtx (REG, SImode, 1));
                    405: 
                    406:   /* Store the arg pointer in the __va_stk member.  */
                    407: 
                    408:   emit_move_insn (gen_rtx (MEM, SImode, addr),
                    409:                  copy_to_reg (virtual_incoming_args_rtx));
                    410:                  
                    411: 
                    412:   /* now move addresses of the saved regs into the pointer array */
                    413: 
                    414:   scratch = gen_reg_rtx (Pmode);
                    415: 
                    416:   emit_move_insn (scratch, r0_addr);
                    417:   emit_move_insn (gen_rtx (MEM, SImode,
                    418:                           gen_rtx (PLUS, Pmode, addr,
                    419:                                    gen_rtx (CONST_INT, Pmode, 4))),
                    420:                  scratch);
                    421:                  
                    422:   emit_move_insn (scratch, f0_addr);
                    423:   emit_move_insn (gen_rtx (MEM, SImode,
                    424:                           gen_rtx (PLUS, Pmode, addr,
                    425:                                    gen_rtx (CONST_INT, Pmode, 8))),
                    426:                  scratch);
                    427:                  
                    428:   emit_move_insn (scratch, r1_addr);
                    429:   emit_move_insn (gen_rtx (MEM, SImode,
                    430:                           gen_rtx (PLUS, Pmode, addr,
                    431:                                    gen_rtx (CONST_INT, Pmode, 12))),
                    432:                  scratch);
                    433:                  
                    434:   emit_move_insn (scratch, f1_addr);
                    435:   emit_move_insn (gen_rtx (MEM, SImode,
                    436:                           gen_rtx (PLUS, Pmode, addr,
                    437:                                    gen_rtx (CONST_INT, Pmode, 16))),
                    438:                  scratch);
                    439: 
                    440:   /* Return the address of the va_list constructor, but don't put it in a
                    441:      register.  This fails when not optimizing and produces worse code when
                    442:      optimizing.  */
                    443: 
                    444:   return XEXP (block, 0);
                    445: }
                    446: 
                    447: 
                    448: /* Return truth value of whether OP can be used as an word register
                    449:    operand. Reject (SUBREG:SI (REG:SF )) */
                    450: 
                    451: int
                    452: int_reg_operand (op, mode)
                    453:      rtx op;
                    454:      enum machine_mode mode;
                    455: {
                    456:   return (register_operand (op, mode) &&
                    457:          (GET_CODE (op) != SUBREG ||
                    458:           GET_MODE_CLASS (GET_MODE (SUBREG_REG (op))) == MODE_INT));
                    459: }
                    460: 
                    461: /* Return truth value of whether OP can be used as a float register
                    462:    operand. Reject (SUBREG:SF (REG:SI )) )) */
                    463: 
                    464: int
                    465: fp_reg_operand (op, mode)
                    466:      rtx op;
                    467:      enum machine_mode mode;
                    468: {
                    469:   return (register_operand (op, mode) &&
                    470:          (GET_CODE (op) != SUBREG ||
                    471:           GET_MODE_CLASS (GET_MODE (SUBREG_REG (op))) == MODE_FLOAT));
                    472: }
                    473: 

unix.superglobalmegacorp.com

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