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

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

unix.superglobalmegacorp.com

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