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

1.1     ! root        1: /* Subroutines for gcc2 for pdp11.
        !             2:    Copyright (C) 1994 Free Software Foundation, Inc.
        !             3:    Contributed by Michael K. Gschwind ([email protected]).
        !             4: 
        !             5: This file is part of GNU CC.
        !             6: 
        !             7: GNU CC is free software; you can redistribute it and/or modify
        !             8: it under the terms of the GNU General Public License as published by
        !             9: the Free Software Foundation; either version 1, or (at your option)
        !            10: any later version.
        !            11: 
        !            12: GNU CC is distributed in the hope that it will be useful,
        !            13: but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            15: GNU General Public License for more details.
        !            16: 
        !            17: You should have received a copy of the GNU General Public License
        !            18: along with GNU CC; see the file COPYING.  If not, write to
        !            19: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
        !            20: 
        !            21: #ifndef FILE
        !            22: #include <stdio.h>
        !            23: #endif
        !            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: 
        !            35: /*
        !            36: #define FPU_REG_P(X)   ((X)>=8 && (X)<14)
        !            37: #define CPU_REG_P(X)   ((X)>=0 && (X)<8)
        !            38: */
        !            39: 
        !            40: /* this is the current value returned by the macro FIRST_PARM_OFFSET 
        !            41:    defined in tm.h */
        !            42: int current_first_parm_offset;
        !            43: 
        !            44: /* This is where the condition code register lives.  */
        !            45: /* rtx cc0_reg_rtx; - no longer needed? */
        !            46: 
        !            47: static rtx find_addr_reg (); 
        !            48: 
        !            49: /* Nonzero if OP is a valid second operand for an arithmetic insn.  */
        !            50: 
        !            51: int
        !            52: arith_operand (op, mode)
        !            53:      rtx op;
        !            54:      enum machine_mode mode;
        !            55: {
        !            56:   return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
        !            57: }
        !            58: 
        !            59: int
        !            60: const_immediate_operand (op, mode)
        !            61:      rtx op;
        !            62:      enum machine_mode mode;
        !            63: {
        !            64:   return (GET_CODE (op) == CONST_INT);
        !            65: }
        !            66: 
        !            67: int 
        !            68: immediate15_operand (op, mode)
        !            69:      rtx op;
        !            70:      enum machine_mode mode;
        !            71: {
        !            72:     return (GET_CODE (op) == CONST_INT && ((INTVAL (op) & 0x8000) == 0x0000));
        !            73: }
        !            74: 
        !            75: int
        !            76: expand_shift_operand (op, mode)
        !            77:   rtx op;
        !            78:   enum machine_mode mode;
        !            79: {
        !            80:     return (GET_CODE (op) == CONST_INT 
        !            81:            && abs (INTVAL(op)) > 1 
        !            82:            && abs (INTVAL(op)) <= 4);
        !            83: }
        !            84: 
        !            85: /*
        !            86:    stream is a stdio stream to output the code to.
        !            87:    size is an int: how many units of temporary storage to allocate.
        !            88:    Refer to the array `regs_ever_live' to determine which registers
        !            89:    to save; `regs_ever_live[I]' is nonzero if register number I
        !            90:    is ever used in the function.  This macro is responsible for
        !            91:    knowing which registers should not be saved even if used.  
        !            92: */
        !            93: 
        !            94: void 
        !            95: output_function_prologue(stream, size)
        !            96:   FILE *stream;
        !            97:   int size;
        !            98: {                                                             
        !            99:     extern char call_used_regs[];                                      
        !           100:     extern int frame_pointer_needed;                           
        !           101: 
        !           102:     int fsize = ((size) + 1) & ~1;                                     
        !           103:     int regno, nregs, i;                                               
        !           104:     int offset = 0;
        !           105: 
        !           106:     int via_ac = -1;
        !           107:     
        !           108:     fprintf (stream, "\n\t;    /* function prologue %s*/\n", current_function_name);           
        !           109: 
        !           110:     /* if we are outputting code for main, 
        !           111:        the switch FPU to right mode if TARGET_FPU */
        !           112:     if ( (strcmp ("main", current_function_name) == 0)
        !           113:         && TARGET_FPU)
        !           114:     {
        !           115:        fprintf(stream, "\t;/* switch cpu to double float, single integer */\n");
        !           116:        fprintf(stream, "\tsetd\n");
        !           117:        fprintf(stream, "\tseti\n\n");
        !           118:     }
        !           119:     
        !           120:     if (frame_pointer_needed)                                  
        !           121:     {                                                          
        !           122:        fprintf(stream, "\tmov fp, -(sp)\n");                   
        !           123:        fprintf(stream, "\tmov sp, fp\n");                              
        !           124:     }                                                          
        !           125:     else                                                               
        !           126:     {                                                          
        !           127:        /* DON'T SAVE FP */
        !           128:     }                                                          
        !           129: 
        !           130:     /* make frame */
        !           131:     if (fsize)                                                 
        !           132:        fprintf (stream, "\tsub $%d, sp\n", fsize);                     
        !           133: 
        !           134:     /* save CPU registers  */
        !           135:     for (regno = 0; regno < 8; regno++)                                
        !           136:        if (regs_ever_live[regno] && ! call_used_regs[regno])   
        !           137:            if (! ((regno == FRAME_POINTER_REGNUM)                      
        !           138:                   && frame_pointer_needed))                            
        !           139:                fprintf (stream, "\tmov %s, -(sp)\n", reg_names[regno]);        
        !           140:     /* fpu regs saving */
        !           141:     
        !           142:     /* via_ac specifies the ac to use for saving ac4, ac5 */
        !           143:     via_ac = -1;
        !           144:     
        !           145:     for (regno = 8; regno < FIRST_PSEUDO_REGISTER ; regno++) 
        !           146:     {
        !           147:        /* ac0 - ac3 */                                         
        !           148:        if (LOAD_FPU_REG_P(regno)
        !           149:            && regs_ever_live[regno] 
        !           150:            && ! call_used_regs[regno])
        !           151:        {
        !           152:            fprintf (stream, "\tfstd %s, -(sp)\n", reg_names[regno]);
        !           153:            via_ac = regno;
        !           154:        }
        !           155:        
        !           156:        /* maybe make ac4, ac5 call used regs?? */
        !           157:        /* ac4 - ac5 */
        !           158:        if (NO_LOAD_FPU_REG_P(regno)
        !           159:            && regs_ever_live[regno]
        !           160:            && ! call_used_regs[regno])
        !           161:        {
        !           162:            if (via_ac == -1)
        !           163:                abort();
        !           164:            
        !           165:            fprintf (stream, "\tfldd %s, %s\n", reg_names[regno], reg_names[via_ac]);
        !           166:            fprintf (stream, "\tfstd %s, -(sp)\n", reg_names[via_ac]);
        !           167:        }
        !           168:     }
        !           169: 
        !           170:     fprintf (stream, "\t;/* end of prologue */\n\n");          
        !           171: }
        !           172: 
        !           173: /*
        !           174:    The function epilogue should not depend on the current stack pointer!
        !           175:    It should use the frame pointer only.  This is mandatory because
        !           176:    of alloca; we also take advantage of it to omit stack adjustments
        !           177:    before returning.  */
        !           178: 
        !           179: /* maybe we can make leaf functions faster by switching to the
        !           180:    second register file - this way we don't have to save regs!
        !           181:    leaf functions are ~ 50% of all functions (dynamically!) 
        !           182: 
        !           183:    set/clear bit 11 (dec. 2048) of status word for switching register files - 
        !           184:    but how can we do this? the pdp11/45 manual says bit may only 
        !           185:    be set (p.24), but not cleared!
        !           186: 
        !           187:    switching to kernel is probably more expensive, so we'll leave it 
        !           188:    like this and not use the second set of registers... 
        !           189: 
        !           190:    maybe as option if you want to generate code for kernel mode? */
        !           191: 
        !           192: 
        !           193: void 
        !           194: output_function_epilogue(stream, size)
        !           195:   FILE *stream;
        !           196:   int size;
        !           197: {                                                              
        !           198:     extern char call_used_regs[];                                      
        !           199:     extern int may_call_alloca;
        !           200: 
        !           201:     int fsize = ((size) + 1) & ~1;                                     
        !           202:     int nregs, regno, i, j, k, adjust_fp;                              
        !           203: 
        !           204:     int via_ac;
        !           205:     
        !           206:     fprintf (stream, "\n\t;    /*function epilogue */\n");             
        !           207: 
        !           208:     if (frame_pointer_needed)                                  
        !           209:     {                                                          
        !           210:        /* hope this is safe - m68k does it also .... */                
        !           211:        regs_ever_live[FRAME_POINTER_REGNUM] = 0;                       
        !           212:                                                                
        !           213:        for (i =7, j = 0 ; i >= 0 ; i--)                                
        !           214:            if (regs_ever_live[i] && ! call_used_regs[i])               
        !           215:                j++;
        !           216:        
        !           217:        /* remember # of pushed bytes for CPU regs */
        !           218:        k = 2*j;
        !           219:        
        !           220:        for (i =7 ; i >= 0 ; i--)                                       
        !           221:            if (regs_ever_live[i] && ! call_used_regs[i])               
        !           222:                fprintf(stream, "\tmov %d(fp), %s\n",-fsize-2*j--, reg_names[i]);
        !           223: 
        !           224:        /* get ACs */                                           
        !           225:        via_ac = FIRST_PSEUDO_REGISTER -1;
        !           226:        
        !           227:        for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
        !           228:            if (regs_ever_live[i] && ! call_used_regs[i])
        !           229:            {
        !           230:                via_ac = i;
        !           231:                k += 8;
        !           232:            }
        !           233:        
        !           234:        for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
        !           235:        {
        !           236:            if (LOAD_FPU_REG_P(i)
        !           237:                && regs_ever_live[i]
        !           238:                && ! call_used_regs[i])
        !           239:            {
        !           240:                fprintf(stream, "\tfldd %d(fp), %s\n", -fsize-k, reg_names[i]);
        !           241:                k -= 8;
        !           242:            }
        !           243:            
        !           244:            if (NO_LOAD_FPU_REG_P(i)
        !           245:                && regs_ever_live[i]
        !           246:                && ! call_used_regs[i])
        !           247:            {
        !           248:                if (! LOAD_FPU_REG_P(via_ac))
        !           249:                    abort();
        !           250:                    
        !           251:                fprintf(stream, "\tfldd %d(fp), %s\n", -fsize-k, reg_names[via_ac]);
        !           252:                fprintf(stream, "\tfstd %s, %s\n", reg_names[via_ac], reg_names[i]);
        !           253:                k -= 8;
        !           254:            }
        !           255:        }
        !           256:        
        !           257:        fprintf(stream, "\tmov fp, sp\n");                              
        !           258:        fprintf (stream, "\tmov (sp)+, fp\n");                          
        !           259:     }                                                          
        !           260:     else                                                               
        !           261:     {             
        !           262:        via_ac = FIRST_PSEUDO_REGISTER -1;
        !           263:        
        !           264:        /* get ACs */
        !           265:        for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
        !           266:            if (regs_ever_live[i] && call_used_regs[i])
        !           267:                via_ac = i;
        !           268:        
        !           269:        for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
        !           270:        {
        !           271:            if (LOAD_FPU_REG_P(i)
        !           272:                && regs_ever_live[i]
        !           273:                && ! call_used_regs[i])
        !           274:              fprintf(stream, "\tfldd (sp)+, %s\n", reg_names[i]);
        !           275:            
        !           276:            if (NO_LOAD_FPU_REG_P(i)
        !           277:                && regs_ever_live[i]
        !           278:                && ! call_used_regs[i])
        !           279:            {
        !           280:                if (! LOAD_FPU_REG_P(via_ac))
        !           281:                    abort();
        !           282:                    
        !           283:                fprintf(stream, "\tfldd (sp)+, %s\n", reg_names[via_ac]);
        !           284:                fprintf(stream, "\tfstd %s, %s\n", reg_names[via_ac], reg_names[i]);
        !           285:            }
        !           286:        }
        !           287: 
        !           288:        for (i=7; i >= 0; i--)                                  
        !           289:            if (regs_ever_live[i] && !call_used_regs[i])                
        !           290:                fprintf(stream, "\tmov (sp)+, %s\n", reg_names[i]);     
        !           291:                                                                
        !           292:        if (fsize)                                              
        !           293:            fprintf((stream), "\tadd $%d, sp\n", fsize);                
        !           294:     }                  
        !           295:                                        
        !           296:     fprintf (stream, "\trts pc\n");                                    
        !           297:     fprintf (stream, "\t;/* end of epilogue*/\n\n\n");         
        !           298: }
        !           299:        
        !           300: /* Return the best assembler insn template
        !           301:    for moving operands[1] into operands[0] as a fullword.  */
        !           302: static char *
        !           303: singlemove_string (operands)
        !           304:      rtx *operands;
        !           305: {
        !           306:   if (operands[1] != const0_rtx)
        !           307:     return "mov %1,%0";
        !           308: 
        !           309:   return "clr %0";
        !           310: }
        !           311: 
        !           312: 
        !           313: /* Output assembler code to perform a doubleword move insn
        !           314:    with operands OPERANDS.  */
        !           315: 
        !           316: char *
        !           317: output_move_double (operands)
        !           318:      rtx *operands;
        !           319: {
        !           320:   enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
        !           321:   rtx latehalf[2];
        !           322:   rtx addreg0 = 0, addreg1 = 0;
        !           323: 
        !           324:   /* First classify both operands.  */
        !           325: 
        !           326:   if (REG_P (operands[0]))
        !           327:     optype0 = REGOP;
        !           328:   else if (offsettable_memref_p (operands[0]))
        !           329:     optype0 = OFFSOP;
        !           330:   else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
        !           331:     optype0 = POPOP;
        !           332:   else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
        !           333:     optype0 = PUSHOP;
        !           334:   else if (GET_CODE (operands[0]) == MEM)
        !           335:     optype0 = MEMOP;
        !           336:   else
        !           337:     optype0 = RNDOP;
        !           338: 
        !           339:   if (REG_P (operands[1]))
        !           340:     optype1 = REGOP;
        !           341:   else if (CONSTANT_P (operands[1]))
        !           342: #if 0
        !           343:           || GET_CODE (operands[1]) == CONST_DOUBLE)
        !           344: #endif
        !           345:     optype1 = CNSTOP;
        !           346:   else if (offsettable_memref_p (operands[1]))
        !           347:     optype1 = OFFSOP;
        !           348:   else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
        !           349:     optype1 = POPOP;
        !           350:   else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
        !           351:     optype1 = PUSHOP;
        !           352:   else if (GET_CODE (operands[1]) == MEM)
        !           353:     optype1 = MEMOP;
        !           354:   else
        !           355:     optype1 = RNDOP;
        !           356: 
        !           357:   /* Check for the cases that the operand constraints are not
        !           358:      supposed to allow to happen.  Abort if we get one,
        !           359:      because generating code for these cases is painful.  */
        !           360: 
        !           361:   if (optype0 == RNDOP || optype1 == RNDOP)
        !           362:     abort ();
        !           363: 
        !           364:   /* If one operand is decrementing and one is incrementing
        !           365:      decrement the former register explicitly
        !           366:      and change that operand into ordinary indexing.  */
        !           367: 
        !           368:   if (optype0 == PUSHOP && optype1 == POPOP)
        !           369:     {
        !           370:       operands[0] = XEXP (XEXP (operands[0], 0), 0);
        !           371:       output_asm_insn ("sub $4,%0", operands);
        !           372:       operands[0] = gen_rtx (MEM, SImode, operands[0]);
        !           373:       optype0 = OFFSOP;
        !           374:     }
        !           375:   if (optype0 == POPOP && optype1 == PUSHOP)
        !           376:     {
        !           377:       operands[1] = XEXP (XEXP (operands[1], 0), 0);
        !           378:       output_asm_insn ("sub $4,%1", operands);
        !           379:       operands[1] = gen_rtx (MEM, SImode, operands[1]);
        !           380:       optype1 = OFFSOP;
        !           381:     }
        !           382: 
        !           383:   /* If an operand is an unoffsettable memory ref, find a register
        !           384:      we can increment temporarily to make it refer to the second word.  */
        !           385: 
        !           386:   if (optype0 == MEMOP)
        !           387:     addreg0 = find_addr_reg (XEXP (operands[0], 0));
        !           388: 
        !           389:   if (optype1 == MEMOP)
        !           390:     addreg1 = find_addr_reg (XEXP (operands[1], 0));
        !           391: 
        !           392:   /* Ok, we can do one word at a time.
        !           393:      Normally we do the low-numbered word first,
        !           394:      but if either operand is autodecrementing then we
        !           395:      do the high-numbered word first.
        !           396: 
        !           397:      In either case, set up in LATEHALF the operands to use
        !           398:      for the high-numbered word and in some cases alter the
        !           399:      operands in OPERANDS to be suitable for the low-numbered word.  */
        !           400: 
        !           401:   if (optype0 == REGOP)
        !           402:     latehalf[0] = gen_rtx (REG, HImode, REGNO (operands[0]) + 1);
        !           403:   else if (optype0 == OFFSOP)
        !           404:     latehalf[0] = adj_offsettable_operand (operands[0], 2);
        !           405:   else
        !           406:     latehalf[0] = operands[0];
        !           407: 
        !           408:   if (optype1 == REGOP)
        !           409:     latehalf[1] = gen_rtx (REG, HImode, REGNO (operands[1]) + 1);
        !           410:   else if (optype1 == OFFSOP)
        !           411:     latehalf[1] = adj_offsettable_operand (operands[1], 2);
        !           412:   else if (optype1 == CNSTOP)
        !           413:     {
        !           414:        if (CONSTANT_P (operands[1]))
        !           415:        {
        !           416:            /* now the mess begins, high word is in lower word??? 
        !           417: 
        !           418:               that's what ashc makes me think, but I don't remember :-( */
        !           419:            latehalf[1] = gen_rtx(CONST_INT, VOIDmode, 
        !           420:                                  INTVAL(operands[1])>>16);
        !           421:            operands[1] = gen_rtx(CONST_INT, VOIDmode,
        !           422:                                  INTVAL(operands[1])&0xff);
        !           423:        }
        !           424:       else if (GET_CODE (operands[1]) == CONST_DOUBLE)
        !           425:        {
        !           426:            /* immediate 32 bit values not allowed */
        !           427:            abort();
        !           428:        }
        !           429:     }
        !           430:   else
        !           431:     latehalf[1] = operands[1];
        !           432: 
        !           433:   /* If insn is effectively movd N(sp),-(sp) then we will do the
        !           434:      high word first.  We should use the adjusted operand 1 (which is N+4(sp))
        !           435:      for the low word as well, to compensate for the first decrement of sp.  */
        !           436:   if (optype0 == PUSHOP
        !           437:       && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
        !           438:       && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
        !           439:     operands[1] = latehalf[1];
        !           440: 
        !           441:   /* If one or both operands autodecrementing,
        !           442:      do the two words, high-numbered first.  */
        !           443: 
        !           444:   /* Likewise,  the first move would clobber the source of the second one,
        !           445:      do them in the other order.  This happens only for registers;
        !           446:      such overlap can't happen in memory unless the user explicitly
        !           447:      sets it up, and that is an undefined circumstance.  */
        !           448: 
        !           449:   if (optype0 == PUSHOP || optype1 == PUSHOP
        !           450:       || (optype0 == REGOP && optype1 == REGOP
        !           451:          && REGNO (operands[0]) == REGNO (latehalf[1])))
        !           452:     {
        !           453:       /* Make any unoffsettable addresses point at high-numbered word.  */
        !           454:       if (addreg0)
        !           455:        output_asm_insn ("add $2,%0", &addreg0);
        !           456:       if (addreg1)
        !           457:        output_asm_insn ("add $2,%0", &addreg1);
        !           458: 
        !           459:       /* Do that word.  */
        !           460:       output_asm_insn (singlemove_string (latehalf), latehalf);
        !           461: 
        !           462:       /* Undo the adds we just did.  */
        !           463:       if (addreg0)
        !           464:        output_asm_insn ("sub $2,%0", &addreg0);
        !           465:       if (addreg1)
        !           466:        output_asm_insn ("sub $2,%0", &addreg1);
        !           467: 
        !           468:       /* Do low-numbered word.  */
        !           469:       return singlemove_string (operands);
        !           470:     }
        !           471: 
        !           472:   /* Normal case: do the two words, low-numbered first.  */
        !           473: 
        !           474:   output_asm_insn (singlemove_string (operands), operands);
        !           475: 
        !           476:   /* Make any unoffsettable addresses point at high-numbered word.  */
        !           477:   if (addreg0)
        !           478:     output_asm_insn ("add $2,%0", &addreg0);
        !           479:   if (addreg1)
        !           480:     output_asm_insn ("add $2,%0", &addreg1);
        !           481: 
        !           482:   /* Do that word.  */
        !           483:   output_asm_insn (singlemove_string (latehalf), latehalf);
        !           484: 
        !           485:   /* Undo the adds we just did.  */
        !           486:   if (addreg0)
        !           487:     output_asm_insn ("sub $2,%0", &addreg0);
        !           488:   if (addreg1)
        !           489:     output_asm_insn ("sub $2,%0", &addreg1);
        !           490: 
        !           491:   return "";
        !           492: }
        !           493: /* Output assembler code to perform a quadword move insn
        !           494:    with operands OPERANDS.  */
        !           495: 
        !           496: char *
        !           497: output_move_quad (operands)
        !           498:      rtx *operands;
        !           499: {
        !           500:   enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
        !           501:   rtx latehalf[2];
        !           502:   rtx addreg0 = 0, addreg1 = 0;
        !           503: 
        !           504:   output_asm_insn(";; movdi/df: %1 -> %0", operands);
        !           505:   
        !           506:   if (REG_P (operands[0]))
        !           507:     optype0 = REGOP;
        !           508:   else if (offsettable_memref_p (operands[0]))
        !           509:     optype0 = OFFSOP;
        !           510:   else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
        !           511:     optype0 = POPOP;
        !           512:   else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
        !           513:     optype0 = PUSHOP;
        !           514:   else if (GET_CODE (operands[0]) == MEM)
        !           515:     optype0 = MEMOP;
        !           516:   else
        !           517:     optype0 = RNDOP;
        !           518: 
        !           519:   if (REG_P (operands[1]))
        !           520:     optype1 = REGOP;
        !           521:   else if (CONSTANT_P (operands[1])
        !           522:           || GET_CODE (operands[1]) == CONST_DOUBLE)
        !           523:     optype1 = CNSTOP;
        !           524:   else if (offsettable_memref_p (operands[1]))
        !           525:     optype1 = OFFSOP;
        !           526:   else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
        !           527:     optype1 = POPOP;
        !           528:   else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
        !           529:     optype1 = PUSHOP;
        !           530:   else if (GET_CODE (operands[1]) == MEM)
        !           531:     optype1 = MEMOP;
        !           532:   else
        !           533:     optype1 = RNDOP;
        !           534: 
        !           535:   /* Check for the cases that the operand constraints are not
        !           536:      supposed to allow to happen.  Abort if we get one,
        !           537:      because generating code for these cases is painful.  */
        !           538: 
        !           539:   if (optype0 == RNDOP || optype1 == RNDOP)
        !           540:     abort ();
        !           541:   
        !           542:   /* check if we move a CPU reg to an FPU reg, or vice versa! */
        !           543:   if (optype0 == REGOP && optype1 == REGOP)
        !           544:       /* bogus - 64 bit cannot reside in CPU! */
        !           545:       if (CPU_REG_P(REGNO(operands[0]))
        !           546:          || CPU_REG_P (REGNO(operands[1])))
        !           547:          abort();
        !           548:   
        !           549:   if (optype0 == REGOP || optype1 == REGOP)
        !           550:   {
        !           551:       /* check for use of clrd???? 
        !           552:          if you ever allow ac4 and ac5 (now we require secondary load) 
        !           553:         you must check whether 
        !           554:         you want to load into them or store from them - 
        !           555:         then dump ac0 into $help$ movce ac4/5 to ac0, do the 
        !           556:         store from ac0, and restore ac0 - if you can find 
        !           557:         an unused ac[0-3], use that and you save a store and a load!*/
        !           558: 
        !           559:       if (FPU_REG_P(REGNO(operands[0])))
        !           560:       {
        !           561:          if (GET_CODE(operands[1]) == CONST_DOUBLE)
        !           562:          {
        !           563:              union { double d; int i[2]; } u;
        !           564:              u.i[0] = CONST_DOUBLE_LOW (operands[1]); 
        !           565:              u.i[1] = CONST_DOUBLE_HIGH (operands[1]); 
        !           566:              
        !           567:              if (u.d == 0.0)
        !           568:                  return "clrd %0";
        !           569:          }
        !           570:              
        !           571:          return "ldd %1, %0";
        !           572:       }
        !           573:       
        !           574:       if (FPU_REG_P(REGNO(operands[1])))
        !           575:          return "std %1, %0";
        !           576:   }
        !           577:       
        !           578:   /* If one operand is decrementing and one is incrementing
        !           579:      decrement the former register explicitly
        !           580:      and change that operand into ordinary indexing.  */
        !           581: 
        !           582:   if (optype0 == PUSHOP && optype1 == POPOP)
        !           583:     {
        !           584:       operands[0] = XEXP (XEXP (operands[0], 0), 0);
        !           585:       output_asm_insn ("sub $8,%0", operands);
        !           586:       operands[0] = gen_rtx (MEM, DImode, operands[0]);
        !           587:       optype0 = OFFSOP;
        !           588:     }
        !           589:   if (optype0 == POPOP && optype1 == PUSHOP)
        !           590:     {
        !           591:       operands[1] = XEXP (XEXP (operands[1], 0), 0);
        !           592:       output_asm_insn ("sub $8,%1", operands);
        !           593:       operands[1] = gen_rtx (MEM, SImode, operands[1]);
        !           594:       optype1 = OFFSOP;
        !           595:     }
        !           596: 
        !           597:   /* If an operand is an unoffsettable memory ref, find a register
        !           598:      we can increment temporarily to make it refer to the second word.  */
        !           599: 
        !           600:   if (optype0 == MEMOP)
        !           601:     addreg0 = find_addr_reg (XEXP (operands[0], 0));
        !           602: 
        !           603:   if (optype1 == MEMOP)
        !           604:     addreg1 = find_addr_reg (XEXP (operands[1], 0));
        !           605: 
        !           606:   /* Ok, we can do one word at a time.
        !           607:      Normally we do the low-numbered word first,
        !           608:      but if either operand is autodecrementing then we
        !           609:      do the high-numbered word first.
        !           610: 
        !           611:      In either case, set up in LATEHALF the operands to use
        !           612:      for the high-numbered word and in some cases alter the
        !           613:      operands in OPERANDS to be suitable for the low-numbered word.  */
        !           614: 
        !           615:   if (optype0 == REGOP)
        !           616:     latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 2);
        !           617:   else if (optype0 == OFFSOP)
        !           618:     latehalf[0] = adj_offsettable_operand (operands[0], 4);
        !           619:   else
        !           620:     latehalf[0] = operands[0];
        !           621: 
        !           622:   if (optype1 == REGOP)
        !           623:     latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2);
        !           624:   else if (optype1 == OFFSOP)
        !           625:     latehalf[1] = adj_offsettable_operand (operands[1], 4);
        !           626:   else if (optype1 == CNSTOP)
        !           627:     {
        !           628:       if (GET_CODE (operands[1]) == CONST_DOUBLE)
        !           629:        {
        !           630:            /* floats only. not yet supported!
        !           631: 
        !           632:             -- compute it into PDP float format, - internally,
        !           633:             just use IEEE and ignore possible problems ;-)
        !           634: 
        !           635:             we might get away with it !!!! */
        !           636: 
        !           637:            abort();
        !           638:            
        !           639: #ifndef HOST_WORDS_BIG_ENDIAN
        !           640:          latehalf[1] = gen_rtx (CONST_INT, VOIDmode,
        !           641:                                 CONST_DOUBLE_LOW (operands[1]));
        !           642:          operands[1] = gen_rtx (CONST_INT, VOIDmode,
        !           643:                                 CONST_DOUBLE_HIGH (operands[1]));
        !           644: #else /* HOST_WORDS_BIG_ENDIAN */
        !           645:          latehalf[1] = gen_rtx (CONST_INT, VOIDmode,
        !           646:                                 CONST_DOUBLE_HIGH (operands[1]));
        !           647:          operands[1] = gen_rtx (CONST_INT, VOIDmode,
        !           648:                                 CONST_DOUBLE_LOW (operands[1]));
        !           649: #endif /* HOST_WORDS_BIG_ENDIAN */
        !           650:        }
        !           651:     }
        !           652:   else
        !           653:     latehalf[1] = operands[1];
        !           654: 
        !           655:   /* If insn is effectively movd N(sp),-(sp) then we will do the
        !           656:      high word first.  We should use the adjusted operand 1 (which is N+4(sp))
        !           657:      for the low word as well, to compensate for the first decrement of sp.  */
        !           658:   if (optype0 == PUSHOP
        !           659:       && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
        !           660:       && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
        !           661:     operands[1] = latehalf[1];
        !           662: 
        !           663:   /* If one or both operands autodecrementing,
        !           664:      do the two words, high-numbered first.  */
        !           665: 
        !           666:   /* Likewise,  the first move would clobber the source of the second one,
        !           667:      do them in the other order.  This happens only for registers;
        !           668:      such overlap can't happen in memory unless the user explicitly
        !           669:      sets it up, and that is an undefined circumstance.  */
        !           670: 
        !           671:   if (optype0 == PUSHOP || optype1 == PUSHOP
        !           672:       || (optype0 == REGOP && optype1 == REGOP
        !           673:          && REGNO (operands[0]) == REGNO (latehalf[1])))
        !           674:     {
        !           675:       /* Make any unoffsettable addresses point at high-numbered word.  */
        !           676:       if (addreg0)
        !           677:        output_asm_insn ("add $4,%0", &addreg0);
        !           678:       if (addreg1)
        !           679:        output_asm_insn ("add $4,%0", &addreg1);
        !           680: 
        !           681:       /* Do that word.  */
        !           682:       output_asm_insn(output_move_double(latehalf), latehalf);
        !           683: 
        !           684:       /* Undo the adds we just did.  */
        !           685:       if (addreg0)
        !           686:        output_asm_insn ("sub $4,%0", &addreg0);
        !           687:       if (addreg1)
        !           688:        output_asm_insn ("sub $4,%0", &addreg1);
        !           689: 
        !           690:       /* Do low-numbered word.  */
        !           691:       return output_move_double (operands);
        !           692:     }
        !           693: 
        !           694:   /* Normal case: do the two words, low-numbered first.  */
        !           695: 
        !           696:   output_asm_insn (output_move_double (operands), operands);
        !           697: 
        !           698:   /* Make any unoffsettable addresses point at high-numbered word.  */
        !           699:   if (addreg0)
        !           700:     output_asm_insn ("add $4,%0", &addreg0);
        !           701:   if (addreg1)
        !           702:     output_asm_insn ("add $4,%0", &addreg1);
        !           703: 
        !           704:   /* Do that word.  */
        !           705:   output_asm_insn (output_move_double (latehalf), latehalf);
        !           706: 
        !           707:   /* Undo the adds we just did.  */
        !           708:   if (addreg0)
        !           709:     output_asm_insn ("sub $4,%0", &addreg0);
        !           710:   if (addreg1)
        !           711:     output_asm_insn ("sub $4,%0", &addreg1);
        !           712: 
        !           713:   return "";
        !           714: }
        !           715: 
        !           716: 
        !           717: /* Return a REG that occurs in ADDR with coefficient 1.
        !           718:    ADDR can be effectively incremented by incrementing REG.  */
        !           719: 
        !           720: static rtx
        !           721: find_addr_reg (addr)
        !           722:      rtx addr;
        !           723: {
        !           724:   while (GET_CODE (addr) == PLUS)
        !           725:     {
        !           726:       if (GET_CODE (XEXP (addr, 0)) == REG)
        !           727:        addr = XEXP (addr, 0);
        !           728:       if (GET_CODE (XEXP (addr, 1)) == REG)
        !           729:        addr = XEXP (addr, 1);
        !           730:       if (CONSTANT_P (XEXP (addr, 0)))
        !           731:        addr = XEXP (addr, 1);
        !           732:       if (CONSTANT_P (XEXP (addr, 1)))
        !           733:        addr = XEXP (addr, 0);
        !           734:     }
        !           735:   if (GET_CODE (addr) == REG)
        !           736:     return addr;
        !           737:   return 0;
        !           738: }
        !           739: 
        !           740: /* Output an ascii string.  */
        !           741: output_ascii (file, p, size)
        !           742:      FILE *file;
        !           743:      char *p;
        !           744:      int size;
        !           745: {
        !           746:   int i;
        !           747: 
        !           748:   fprintf (file, "\t.byte \"");
        !           749: 
        !           750:   for (i = 0; i < size; i++)
        !           751:     {
        !           752:       register int c = p[i];
        !           753:       if (c == '\"' || c == '\\')
        !           754:        putc ('\\', file);
        !           755:       if (c >= ' ' && c < 0177)
        !           756:        putc (c, file);
        !           757:       else
        !           758:        {
        !           759:          fprintf (file, "\\%03o", c);
        !           760:          /* After an octal-escape, if a digit follows,
        !           761:             terminate one string constant and start another.
        !           762:             The Vax assembler fails to stop reading the escape
        !           763:             after three digits, so this is the only way we
        !           764:             can get it to parse the data properly.  */
        !           765:          if (i < size - 1 && p[i + 1] >= '0' && p[i + 1] <= '9')
        !           766:            fprintf (file, "\"\n\tstring \"");
        !           767:        }
        !           768:     }
        !           769:   fprintf (file, "\"\n");
        !           770: }
        !           771: 
        !           772: 
        !           773: /* --- stole from out-vax, needs changes */
        !           774: 
        !           775: print_operand_address (file, addr)
        !           776:      FILE *file;
        !           777:      register rtx addr;
        !           778: {
        !           779:   register rtx reg1, reg2, breg, ireg;
        !           780:   rtx offset;
        !           781: 
        !           782:  retry:
        !           783: 
        !           784:   switch (GET_CODE (addr))
        !           785:     {
        !           786:     case MEM:
        !           787:       fprintf (file, "@");
        !           788:       addr = XEXP (addr, 0);
        !           789:       goto retry;
        !           790: 
        !           791:     case REG:
        !           792:       fprintf (file, "(%s)", reg_names[REGNO (addr)]);
        !           793:       break;
        !           794: 
        !           795:     case PRE_DEC:
        !           796:       fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
        !           797:       break;
        !           798: 
        !           799:     case POST_INC:
        !           800:       fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
        !           801:       break;
        !           802: 
        !           803:     case PLUS:
        !           804:       reg1 = 0;        reg2 = 0;
        !           805:       ireg = 0;        breg = 0;
        !           806:       offset = 0;
        !           807:       if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
        !           808:          || GET_CODE (XEXP (addr, 0)) == MEM)
        !           809:        {
        !           810:          offset = XEXP (addr, 0);
        !           811:          addr = XEXP (addr, 1);
        !           812:        }
        !           813:       else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
        !           814:               || GET_CODE (XEXP (addr, 1)) == MEM)
        !           815:        {
        !           816:          offset = XEXP (addr, 1);
        !           817:          addr = XEXP (addr, 0);
        !           818:        }
        !           819:       if (GET_CODE (addr) != PLUS)
        !           820:        ;
        !           821:       else if (GET_CODE (XEXP (addr, 0)) == MULT)
        !           822:        {
        !           823:          reg1 = XEXP (addr, 0);
        !           824:          addr = XEXP (addr, 1);
        !           825:        }
        !           826:       else if (GET_CODE (XEXP (addr, 1)) == MULT)
        !           827:        {
        !           828:          reg1 = XEXP (addr, 1);
        !           829:          addr = XEXP (addr, 0);
        !           830:        }
        !           831:       else if (GET_CODE (XEXP (addr, 0)) == REG)
        !           832:        {
        !           833:          reg1 = XEXP (addr, 0);
        !           834:          addr = XEXP (addr, 1);
        !           835:        }
        !           836:       else if (GET_CODE (XEXP (addr, 1)) == REG)
        !           837:        {
        !           838:          reg1 = XEXP (addr, 1);
        !           839:          addr = XEXP (addr, 0);
        !           840:        }
        !           841:       if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT)
        !           842:        {
        !           843:          if (reg1 == 0)
        !           844:            reg1 = addr;
        !           845:          else
        !           846:            reg2 = addr;
        !           847:          addr = 0;
        !           848:        }
        !           849:       if (offset != 0)
        !           850:        {
        !           851:          if (addr != 0) abort ();
        !           852:          addr = offset;
        !           853:        }
        !           854:       if (reg1 != 0 && GET_CODE (reg1) == MULT)
        !           855:        {
        !           856:          breg = reg2;
        !           857:          ireg = reg1;
        !           858:        }
        !           859:       else if (reg2 != 0 && GET_CODE (reg2) == MULT)
        !           860:        {
        !           861:          breg = reg1;
        !           862:          ireg = reg2;
        !           863:        }
        !           864:       else if (reg2 != 0 || GET_CODE (addr) == MEM)
        !           865:        {
        !           866:          breg = reg2;
        !           867:          ireg = reg1;
        !           868:        }
        !           869:       else
        !           870:        {
        !           871:          breg = reg1;
        !           872:          ireg = reg2;
        !           873:        }
        !           874:       if (addr != 0)
        !           875:        output_address (addr);
        !           876:       if (breg != 0)
        !           877:        {
        !           878:          if (GET_CODE (breg) != REG)
        !           879:            abort ();
        !           880:          fprintf (file, "(%s)", reg_names[REGNO (breg)]);
        !           881:        }
        !           882:       if (ireg != 0)
        !           883:        {
        !           884:          if (GET_CODE (ireg) == MULT)
        !           885:            ireg = XEXP (ireg, 0);
        !           886:          if (GET_CODE (ireg) != REG)
        !           887:            abort ();
        !           888:          abort();
        !           889:          fprintf (file, "[%s]", reg_names[REGNO (ireg)]);
        !           890:        }
        !           891:       break;
        !           892: 
        !           893:     default:
        !           894:       output_addr_const (file, addr);
        !           895:     }
        !           896: }
        !           897: 
        !           898: /* register move costs, indexed by regs */
        !           899: 
        !           900: static int move_costs[N_REG_CLASSES][N_REG_CLASSES] = 
        !           901: {
        !           902:              /* NO  MUL  GEN  LFPU  NLFPU FPU ALL */
        !           903: 
        !           904: /* NO */     {  0,   0,   0,    0,    0,    0,   0},
        !           905: /* MUL */    {  0,   2,   2,   10,   22,   22,  22},
        !           906: /* GEN */    {  0,   2,   2,   10,   22,   22,  22},
        !           907: /* LFPU */   {  0,  10,  10,    2,    2,    2,  10},
        !           908: /* NLFPU */  {  0,  22,  22,    2,    2,    2,  22},
        !           909: /* FPU */    {  0,  22,  22,    2,    2,    2,  22},
        !           910: /* ALL */    {  0,  22,  22,   10,   22,   22,  22}
        !           911: }  ;
        !           912: 
        !           913: 
        !           914: /* -- note that some moves are tremendously expensive, 
        !           915:    because they require lots of tricks! do we have to 
        !           916:    charge the costs incurred by secondary reload class 
        !           917:    -- as we do here with 22 -- or not ? */
        !           918: 
        !           919: int 
        !           920: register_move_cost(c1, c2)
        !           921:   enum reg_class c1, c2;
        !           922: {
        !           923:     return move_costs[(int)c1][(int)c2];
        !           924: }
        !           925: 
        !           926: char *
        !           927: output_jump(pos, neg, length)
        !           928:   int length;
        !           929:   char *pos, *neg;
        !           930: {
        !           931:     static int x = 0;
        !           932:     
        !           933:     static char buf[1000];
        !           934: 
        !           935: #if 0
        !           936: /* currently we don't need this, because the tstdf and cmpdf 
        !           937:    copy the condition code immediately, and other float operations are not 
        !           938:    yet recognized as changing the FCC - if so, then the length-cost of all
        !           939:    jump insns increases by one, because we have to potentially copy the 
        !           940:    FCC! */
        !           941:     if (cc_status.flags & CC_IN_FPU)
        !           942:        output_asm_insn("cfcc", NULL);
        !           943: #endif
        !           944:        
        !           945:     switch (length)
        !           946:     {
        !           947:       case 1:
        !           948:        
        !           949:        strcpy(buf, pos);
        !           950:        strcat(buf, " %l0");
        !           951:        
        !           952:        return buf;
        !           953:        
        !           954:       case 3:
        !           955:        
        !           956:        sprintf(buf, "%s JMP_%d\n\tjmp %%l0\nJMP_%d:", neg, x, x);
        !           957:        
        !           958:        x++;
        !           959:        
        !           960:        return buf;
        !           961:        
        !           962:       default:
        !           963:        
        !           964:        abort();
        !           965:     }
        !           966:     
        !           967: }
        !           968: 
        !           969: void
        !           970: notice_update_cc_on_set(exp, insn)
        !           971:   rtx exp;
        !           972:   rtx insn;
        !           973: {
        !           974:     if (GET_CODE (SET_DEST (exp)) == CC0)
        !           975:     { 
        !           976:        cc_status.flags = 0;                                    
        !           977:        cc_status.value1 = SET_DEST (exp);                      
        !           978:        cc_status.value2 = SET_SRC (exp);                       
        !           979: 
        !           980: /*
        !           981:        if (GET_MODE(SET_SRC(exp)) == DFmode)
        !           982:            cc_status.flags |= CC_IN_FPU;
        !           983: */     
        !           984:     }                                                  
        !           985:     else if ((GET_CODE (SET_DEST (exp)) == REG         
        !           986:              || GET_CODE (SET_DEST (exp)) == MEM)              
        !           987:             && GET_CODE (SET_SRC (exp)) != PC          
        !           988:             && (GET_MODE (SET_DEST(exp)) == HImode             
        !           989:                 || GET_MODE (SET_DEST(exp)) == QImode) 
        !           990:                && (GET_CODE (SET_SRC(exp)) == PLUS             
        !           991:                    || GET_CODE (SET_SRC(exp)) == MINUS 
        !           992:                    || GET_CODE (SET_SRC(exp)) == AND   
        !           993:                    || GET_CODE (SET_SRC(exp)) == IOR   
        !           994:                    || GET_CODE (SET_SRC(exp)) == XOR   
        !           995:                    || GET_CODE (SET_SRC(exp)) == NOT   
        !           996:                    || GET_CODE (SET_SRC(exp)) == NEG   
        !           997:                        || GET_CODE (SET_SRC(exp)) == REG       
        !           998:                    || GET_CODE (SET_SRC(exp)) == MEM)) 
        !           999:     { 
        !          1000:        cc_status.flags = 0;                                    
        !          1001:        cc_status.value1 = SET_SRC (exp);                       
        !          1002:        cc_status.value2 = SET_DEST (exp);                      
        !          1003:        
        !          1004:        if (cc_status.value1 && GET_CODE (cc_status.value1) == REG      
        !          1005:            && cc_status.value2                                 
        !          1006:            && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
        !          1007:            cc_status.value2 = 0;                                       
        !          1008:        if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM      
        !          1009:            && cc_status.value2                                 
        !          1010:            && GET_CODE (cc_status.value2) == MEM)                      
        !          1011:            cc_status.value2 = 0;                                       
        !          1012:     }                                                  
        !          1013:     else if (GET_CODE (SET_SRC (exp)) == CALL)         
        !          1014:     { 
        !          1015:        CC_STATUS_INIT; 
        !          1016:     }
        !          1017:     else if (GET_CODE (SET_DEST (exp)) == REG)                 
        !          1018:        /* what's this ? */                                     
        !          1019:     { 
        !          1020:        if ((cc_status.value1                                   
        !          1021:             && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1)))
        !          1022:            cc_status.value1 = 0;                               
        !          1023:        if ((cc_status.value2                                   
        !          1024:             && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2)))
        !          1025:            cc_status.value2 = 0;                               
        !          1026:     }                                                  
        !          1027:     else if (SET_DEST(exp) == pc_rtx)
        !          1028:     { 
        !          1029:        /* jump */
        !          1030:     }
        !          1031:     else /* if (GET_CODE (SET_DEST (exp)) == MEM)      */      
        !          1032:     {  
        !          1033:        /* the last else is a bit paranoic, but since nearly all instructions 
        !          1034:           play with condition codes, it's reasonable! */
        !          1035: 
        !          1036:        CC_STATUS_INIT; /* paranoia*/ 
        !          1037:     }                  
        !          1038: }
        !          1039: 
        !          1040: 
        !          1041: int simple_memory_operand(op, mode)
        !          1042:   rtx op;
        !          1043:   enum machine_mode mode;
        !          1044: {
        !          1045:     rtx addr, plus0, plus1;
        !          1046:     int offset = 0;
        !          1047: 
        !          1048:     /* Eliminate non-memory operations */
        !          1049:     if (GET_CODE (op) != MEM)
        !          1050:        return FALSE;
        !          1051: 
        !          1052: #if 0
        !          1053:     /* dword operations really put out 2 instructions, so eliminate them.  */
        !          1054:     if (GET_MODE_SIZE (GET_MODE (op)) > (HAVE_64BIT_P () ? 8 : 4))
        !          1055:        return FALSE;
        !          1056: #endif
        !          1057: 
        !          1058:     /* Decode the address now.  */
        !          1059: 
        !          1060:   indirection:
        !          1061:     
        !          1062:     addr = XEXP (op, 0);
        !          1063: 
        !          1064:     switch (GET_CODE (addr))
        !          1065:     {
        !          1066:       case REG:
        !          1067:        /* (R0) - no extra cost */
        !          1068:        return 1;
        !          1069:        
        !          1070:       case PRE_DEC:
        !          1071:       case POST_INC:
        !          1072:        /* -(R0), (R0)+ - cheap! */
        !          1073:        return 0;
        !          1074:        
        !          1075:       case MEM:
        !          1076:        /* cheap - is encoded in addressing mode info! 
        !          1077: 
        !          1078:           -- except for @(R0), which has to be @0(R0) !!! */
        !          1079: 
        !          1080:        if (GET_CODE (XEXP (addr, 0)) == REG)
        !          1081:            return 0;
        !          1082:        
        !          1083:        op=addr;
        !          1084:        goto indirection;
        !          1085:        
        !          1086:       case CONST_INT:
        !          1087:       case LABEL_REF:         
        !          1088:       case CONST:
        !          1089:       case SYMBOL_REF:
        !          1090:        /* @#address - extra cost */
        !          1091:        return 0;
        !          1092: 
        !          1093:       case PLUS:
        !          1094:        /* X(R0) - extra cost */
        !          1095:        return 0;
        !          1096:     }
        !          1097:     
        !          1098:     return FALSE;
        !          1099: }
        !          1100: 
        !          1101: 
        !          1102: /*
        !          1103:  * output a block move:
        !          1104:  *
        !          1105:  * operands[0] ... to
        !          1106:  * operands[1]  ... from
        !          1107:  * operands[2]  ... length
        !          1108:  * operands[3]  ... alignment
        !          1109:  * operands[4]  ... scratch register
        !          1110:  */
        !          1111: 
        !          1112:  
        !          1113: char *
        !          1114: output_block_move(operands)
        !          1115:   rtx *operands;
        !          1116: {
        !          1117:     static int count = 0;
        !          1118:     char buf[200];
        !          1119:     
        !          1120:     if (GET_CODE(operands[2]) == CONST_INT
        !          1121:        && TARGET_TIME)
        !          1122:     {
        !          1123:        if (INTVAL(operands[2]) < 16
        !          1124:            && INTVAL(operands[3]) == 1)
        !          1125:        {
        !          1126:            register int i;
        !          1127:            
        !          1128:            for (i = 1; i <= INTVAL(operands[2]); i++)
        !          1129:                output_asm_insn("movb (%1)+, (%0)+", operands);
        !          1130: 
        !          1131:            return "";
        !          1132:        }
        !          1133:        else if (INTVAL(operands[2]) < 32)
        !          1134:        {
        !          1135:            register int i;
        !          1136:            
        !          1137:            for (i = 1; i <= INTVAL(operands[2])/2; i++)
        !          1138:                output_asm_insn("mov (%1)+, (%0)+", operands);
        !          1139:            
        !          1140:            /* may I assume that moved quantity is 
        !          1141:               multiple of alignment ???
        !          1142: 
        !          1143:               I HOPE SO !
        !          1144:            */
        !          1145: 
        !          1146:            return "";
        !          1147:        }
        !          1148:        
        !          1149: 
        !          1150:        /* can do other clever things, maybe... */
        !          1151:     }
        !          1152: 
        !          1153:     if (CONSTANT_P(operands[2]) )
        !          1154:     {
        !          1155:        /* just move count to scratch */
        !          1156:        output_asm_insn("mov %2, %4", operands);
        !          1157:     }
        !          1158:     else
        !          1159:     {
        !          1160:        /* just clobber the register */
        !          1161:        operands[4] = operands[2];
        !          1162:     }
        !          1163:     
        !          1164: 
        !          1165:     /* switch over alignment */
        !          1166:     switch (INTVAL(operands[3]))
        !          1167:     {
        !          1168:       case 1:
        !          1169:        
        !          1170:        /* 
        !          1171:          x:
        !          1172:          movb (%1)+, (%0)+
        !          1173:          
        !          1174:          if (TARGET_45)
        !          1175:             sob %4,x
        !          1176:          else
        !          1177:             dec %4
        !          1178:             bgt x
        !          1179: 
        !          1180:        */
        !          1181: 
        !          1182:        sprintf(buf, "\nmovestrhi%d:", count);
        !          1183:        output_asm_insn(buf, NULL);
        !          1184:        
        !          1185:        output_asm_insn("movb (%1)+, (%0)+", operands);
        !          1186:        
        !          1187:        if (TARGET_45)
        !          1188:        {
        !          1189:            sprintf(buf, "sob %%4, movestrhi%d", count);
        !          1190:            output_asm_insn(buf, operands);
        !          1191:        }
        !          1192:        else
        !          1193:        {
        !          1194:            output_asm_insn("dec %4", operands);
        !          1195:            
        !          1196:            sprintf(buf, "bgt movestrhi%d", count);
        !          1197:            output_asm_insn(buf, NULL);
        !          1198:        }
        !          1199:        
        !          1200:        count ++;
        !          1201:        break;
        !          1202:        
        !          1203:       case 2:
        !          1204:        
        !          1205:        /* 
        !          1206:           asr %4
        !          1207: 
        !          1208:           x:
        !          1209: 
        !          1210:           mov (%1)+, (%0)+
        !          1211: 
        !          1212:           if (TARGET_45)
        !          1213:             sob %4, x
        !          1214:           else
        !          1215:             dec %4
        !          1216:             bgt x
        !          1217:        */
        !          1218: 
        !          1219:       generate_compact_code:
        !          1220: 
        !          1221:        output_asm_insn("asr %4", operands);
        !          1222: 
        !          1223:        sprintf(buf, "\nmovestrhi%d:", count);
        !          1224:        output_asm_insn(buf, NULL);
        !          1225:        
        !          1226:        output_asm_insn("mov (%1)+, (%0)+", operands);
        !          1227:        
        !          1228:        if (TARGET_45)
        !          1229:        {
        !          1230:            sprintf(buf, "sob %%4, movestrhi%d", count);
        !          1231:            output_asm_insn(buf, operands);
        !          1232:        }
        !          1233:        else
        !          1234:        {
        !          1235:            output_asm_insn("dec %4", operands);
        !          1236:            
        !          1237:            sprintf(buf, "bgt movestrhi%d", count);
        !          1238:            output_asm_insn(buf, NULL);
        !          1239:        }
        !          1240:        
        !          1241:        count ++;
        !          1242:        break;
        !          1243: 
        !          1244:       case 4:
        !          1245:        
        !          1246:        /*
        !          1247: 
        !          1248:           asr %4
        !          1249:           asr %4
        !          1250: 
        !          1251:           x:
        !          1252: 
        !          1253:           mov (%1)+, (%0)+
        !          1254:           mov (%1)+, (%0)+
        !          1255: 
        !          1256:           if (TARGET_45)
        !          1257:             sob %4, x
        !          1258:           else
        !          1259:             dec %4
        !          1260:             bgt x
        !          1261:        */
        !          1262: 
        !          1263:        if (TARGET_SPACE)
        !          1264:            goto generate_compact_code;
        !          1265:        
        !          1266:        output_asm_insn("asr %4", operands);
        !          1267:        output_asm_insn("asr %4", operands);
        !          1268: 
        !          1269:        sprintf(buf, "\nmovestrhi%d:", count);
        !          1270:        output_asm_insn(buf, NULL);
        !          1271:        
        !          1272:        output_asm_insn("mov (%1)+, (%0)+", operands);
        !          1273:        output_asm_insn("mov (%1)+, (%0)+", operands);
        !          1274:        
        !          1275:        if (TARGET_45)
        !          1276:        {
        !          1277:            sprintf(buf, "sob %%4, movestrhi%d", count);
        !          1278:            output_asm_insn(buf, operands);
        !          1279:        }
        !          1280:        else
        !          1281:        {
        !          1282:            output_asm_insn("dec %4", operands);
        !          1283:            
        !          1284:            sprintf(buf, "bgt movestrhi%d", count);
        !          1285:            output_asm_insn(buf, NULL);
        !          1286:        }
        !          1287:        
        !          1288:        count ++;
        !          1289:        break;
        !          1290:        
        !          1291:       default:
        !          1292:        
        !          1293:        /*
        !          1294:           
        !          1295:           asr %4
        !          1296:           asr %4
        !          1297:           asr %4
        !          1298: 
        !          1299:           x:
        !          1300: 
        !          1301:           mov (%1)+, (%0)+
        !          1302:           mov (%1)+, (%0)+
        !          1303:           mov (%1)+, (%0)+
        !          1304:           mov (%1)+, (%0)+
        !          1305:           
        !          1306:           if (TARGET_45)
        !          1307:             sob %4, x
        !          1308:           else
        !          1309:             dec %4
        !          1310:             bgt x
        !          1311:        */
        !          1312: 
        !          1313: 
        !          1314:        if (TARGET_SPACE)
        !          1315:            goto generate_compact_code;
        !          1316:        
        !          1317:        output_asm_insn("asr %4", operands);
        !          1318:        output_asm_insn("asr %4", operands);
        !          1319:        output_asm_insn("asr %4", operands);
        !          1320: 
        !          1321:        sprintf(buf, "\nmovestrhi%d:", count);
        !          1322:        output_asm_insn(buf, NULL);
        !          1323:        
        !          1324:        output_asm_insn("mov (%1)+, (%0)+", operands);
        !          1325:        output_asm_insn("mov (%1)+, (%0)+", operands);
        !          1326:        output_asm_insn("mov (%1)+, (%0)+", operands);
        !          1327:        output_asm_insn("mov (%1)+, (%0)+", operands);
        !          1328:        
        !          1329:        if (TARGET_45)
        !          1330:        {
        !          1331:            sprintf(buf, "sob %%4, movestrhi%d", count);
        !          1332:            output_asm_insn(buf, operands);
        !          1333:        }
        !          1334:        else
        !          1335:        {
        !          1336:            output_asm_insn("dec %4", operands);
        !          1337:            
        !          1338:            sprintf(buf, "bgt movestrhi%d", count);
        !          1339:            output_asm_insn(buf, NULL);
        !          1340:        }
        !          1341:        
        !          1342:        count ++;
        !          1343:        break;
        !          1344:        
        !          1345:        ;
        !          1346:        
        !          1347:     }
        !          1348:     
        !          1349:     return "";
        !          1350: }
        !          1351: 
        !          1352: /* for future use */
        !          1353: int
        !          1354: comparison_operator_index(op)
        !          1355:   rtx op;
        !          1356: {
        !          1357:     switch (GET_CODE(op))
        !          1358:     {
        !          1359:       case NE:
        !          1360:        return 0;
        !          1361:        
        !          1362:       case EQ:
        !          1363:        return 1;
        !          1364:        
        !          1365:       case GE:
        !          1366:        return 2;
        !          1367:        
        !          1368:       case GT:
        !          1369:        return 3;
        !          1370:        
        !          1371:       case LE:
        !          1372:        return 4;
        !          1373:        
        !          1374:       case LT:
        !          1375:        return 5;
        !          1376:        
        !          1377:       case GEU:
        !          1378:        return 6;
        !          1379:        
        !          1380:       case GTU:
        !          1381:        return 7;
        !          1382: 
        !          1383:       case LEU:
        !          1384:        return 8;
        !          1385:        
        !          1386:       case LTU:
        !          1387:        return 9;
        !          1388:        
        !          1389:       default:
        !          1390:        return -1;
        !          1391:     }
        !          1392: }    
        !          1393:        
        !          1394: /* tests whether the rtx is a comparison operator */
        !          1395: int
        !          1396: comp_operator (op, mode)
        !          1397:   rtx op;
        !          1398:   enum machine_mode mode;
        !          1399: {
        !          1400:     return comparison_operator_index(op) >= 0;
        !          1401: }
        !          1402: 
        !          1403:     
        !          1404: int
        !          1405: legitimate_address_p (mode, address)
        !          1406:   enum machine_mode mode;
        !          1407:   rtx address;
        !          1408: {
        !          1409: /* #define REG_OK_STRICT */
        !          1410:     GO_IF_LEGITIMATE_ADDRESS(mode, address, win);
        !          1411:     
        !          1412:     return 0;
        !          1413:     
        !          1414:   win:
        !          1415:     return 1;
        !          1416: 
        !          1417: /* #undef REG_OK_STRICT */
        !          1418: }

unix.superglobalmegacorp.com

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