Annotation of gcc/config/out-tahoe.c, revision 1.1

1.1     ! root        1: /* Subroutines for insn-output.c for Tahoe.
        !             2:    Copyright (C) 1989 Free Software Foundation, Inc.
        !             3: 
        !             4: This file is part of GNU CC.
        !             5: 
        !             6: GNU CC is free software; you can redistribute it and/or modify
        !             7: it under the terms of the GNU General Public License as published by
        !             8: the Free Software Foundation; either version 1, or (at your option)
        !             9: any later version.
        !            10: 
        !            11: GNU CC is distributed in the hope that it will be useful,
        !            12: but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            14: GNU General Public License for more details.
        !            15: 
        !            16: You should have received a copy of the GNU General Public License
        !            17: along with GNU CC; see the file COPYING.  If not, write to
        !            18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
        !            19: 
        !            20: 
        !            21: /*
        !            22:  * File: output-tahoe.c
        !            23:  *
        !            24:  * This port made at the University of Buffalo by Devon Bowen,
        !            25:  * Dale Wiles and Kevin Zachmann.
        !            26:  *
        !            27:  * Mail bugs reports or fixes to:      [email protected]
        !            28:  */
        !            29: 
        !            30: 
        !            31: /* most of the print_operand_address function was taken from the vax   */
        !            32: /* since the modes are basically the same. I had to add a special case,        */
        !            33: /* though, for symbol references with offsets.                         */
        !            34: 
        !            35: #include <stdio.h>
        !            36: 
        !            37: print_operand_address (file, addr)
        !            38:      FILE *file;
        !            39:      register rtx addr;
        !            40: {
        !            41:   register rtx reg1, reg2, breg, ireg;
        !            42:   rtx offset;
        !            43:   static char *reg_name[] = REGISTER_NAMES;
        !            44: 
        !            45:  retry:
        !            46:   switch (GET_CODE (addr))
        !            47:     {
        !            48:     case MEM:
        !            49:       fprintf (file, "*");
        !            50:       addr = XEXP (addr, 0);
        !            51:       goto retry;
        !            52: 
        !            53:     case REG:
        !            54:       fprintf (file, "(%s)", reg_name [REGNO (addr)]);
        !            55:       break;
        !            56: 
        !            57:     case PRE_DEC:
        !            58:       fprintf (file, "-(%s)", reg_name [REGNO (XEXP (addr, 0))]);
        !            59:       break;
        !            60: 
        !            61:     case POST_INC:
        !            62:       fprintf (file, "(%s)+", reg_name [REGNO (XEXP (addr, 0))]);
        !            63:       break;
        !            64: 
        !            65:     case PLUS:
        !            66:       reg1 = 0;        reg2 = 0;
        !            67:       ireg = 0;        breg = 0;
        !            68:       offset = 0;
        !            69: 
        !            70:       if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
        !            71:          && GET_CODE (XEXP (addr, 1)) == CONST_INT)
        !            72:        output_addr_const (file, addr);
        !            73: 
        !            74:       if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
        !            75:          && GET_CODE (XEXP (addr, 0)) == CONST_INT)
        !            76:        output_addr_const (file, addr);
        !            77: 
        !            78:       if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
        !            79:          || GET_CODE (XEXP (addr, 0)) == MEM)
        !            80:        {
        !            81:          offset = XEXP (addr, 0);
        !            82:          addr = XEXP (addr, 1);
        !            83:        }
        !            84:       else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
        !            85:               || GET_CODE (XEXP (addr, 1)) == MEM)
        !            86:        {
        !            87:          offset = XEXP (addr, 1);
        !            88:          addr = XEXP (addr, 0);
        !            89:        }
        !            90:       if (GET_CODE (addr) != PLUS)
        !            91:        ;
        !            92:       else if (GET_CODE (XEXP (addr, 0)) == MULT)
        !            93:        {
        !            94:          reg1 = XEXP (addr, 0);
        !            95:          addr = XEXP (addr, 1);
        !            96:        }
        !            97:       else if (GET_CODE (XEXP (addr, 1)) == MULT)
        !            98:        {
        !            99:          reg1 = XEXP (addr, 1);
        !           100:          addr = XEXP (addr, 0);
        !           101:        }
        !           102:       else if (GET_CODE (XEXP (addr, 0)) == REG)
        !           103:        {
        !           104:          reg1 = XEXP (addr, 0);
        !           105:          addr = XEXP (addr, 1);
        !           106:        }
        !           107:       else if (GET_CODE (XEXP (addr, 1)) == REG)
        !           108:        {
        !           109:          reg1 = XEXP (addr, 1);
        !           110:          addr = XEXP (addr, 0);
        !           111:        }
        !           112:       if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT)
        !           113:        {
        !           114:          if (reg1 == 0)
        !           115:            reg1 = addr;
        !           116:          else
        !           117:            reg2 = addr;
        !           118:          addr = 0;
        !           119:        }
        !           120:       if (offset != 0)
        !           121:        {
        !           122:          if (addr != 0) abort ();
        !           123:          addr = offset;
        !           124:        }
        !           125:       if (reg1 != 0 && GET_CODE (reg1) == MULT)
        !           126:        {
        !           127:          breg = reg2;
        !           128:          ireg = reg1;
        !           129:        }
        !           130:       else if (reg2 != 0 && GET_CODE (reg2) == MULT)
        !           131:        {
        !           132:          breg = reg1;
        !           133:          ireg = reg2;
        !           134:        }
        !           135:       else if (reg2 != 0 || GET_CODE (addr) == MEM)
        !           136:        {
        !           137:          breg = reg2;
        !           138:          ireg = reg1;
        !           139:        }
        !           140:       else
        !           141:        {
        !           142:          breg = reg1;
        !           143:          ireg = reg2;
        !           144:        }
        !           145:       if (addr != 0)
        !           146:        output_address (offset);
        !           147:       if (breg != 0)
        !           148:        {
        !           149:          if (GET_CODE (breg) != REG)
        !           150:            abort ();
        !           151:          fprintf (file, "(%s)", reg_name[REGNO (breg)]);
        !           152:        }
        !           153:       if (ireg != 0)
        !           154:        {
        !           155:          if (GET_CODE (ireg) == MULT)
        !           156:            ireg = XEXP (ireg, 0);
        !           157:          if (GET_CODE (ireg) != REG)
        !           158:            abort ();
        !           159:          fprintf (file, "[%s]", reg_name[REGNO (ireg)]);
        !           160:        }
        !           161:       break;
        !           162: 
        !           163:     default:
        !           164:       output_addr_const (file, addr);
        !           165:     }
        !           166: }
        !           167: 
        !           168: 
        !           169: /* Do a quick check and find out what the best way to do the */
        !           170: /* mini-move is. Could be a push or a move.....                     */
        !           171: 
        !           172: static char *
        !           173: singlemove_string (operands)
        !           174:      rtx *operands;
        !           175: {
        !           176:   if (GET_CODE (operands[0]) == MEM
        !           177:       && GET_CODE (XEXP (operands[0],0)) == PRE_DEC)
        !           178:     return "pushl %1";
        !           179:   return "movl %1,%0";
        !           180: }
        !           181: 
        !           182: 
        !           183: /* given the rtx for an address, return true if the given */
        !           184: /* register number is used in the address somewhere.     */
        !           185: 
        !           186: int
        !           187: regisused (addr,regnum)
        !           188:      rtx addr;
        !           189:      int regnum;
        !           190: {
        !           191:   if (GET_CODE (addr) == REG)
        !           192:     {
        !           193:       if (REGNO (addr) == regnum)
        !           194:        return (1);
        !           195:       else
        !           196:        return (0);
        !           197:     }
        !           198: 
        !           199:   if (GET_CODE (addr) == MEM)
        !           200:     return regisused (XEXP (addr,0),regnum);
        !           201: 
        !           202:   if (GET_CODE (addr) == MULT || GET_CODE (addr) == PLUS)
        !           203:     return (regisused (XEXP (addr,0),regnum)
        !           204:            || regisused (XEXP (addr,1),regnum));
        !           205: 
        !           206:   return 0;
        !           207: }
        !           208: 
        !           209: 
        !           210: /* Given some rtx, traverse it and return the register used in a */
        !           211: /* index. If no index is found, return 0.                       */
        !           212: 
        !           213: rtx
        !           214: index_reg (addr)
        !           215:      rtx addr;
        !           216: {
        !           217:   rtx temp;
        !           218: 
        !           219:   if (GET_CODE (addr) == MEM)
        !           220:     return index_reg (XEXP (addr,0));
        !           221: 
        !           222:   if (GET_CODE (addr) == MULT)
        !           223:     {
        !           224:       if (GET_CODE (XEXP (addr,0)) == REG)
        !           225:        return XEXP (addr,0);
        !           226:       else
        !           227:        return XEXP (addr,1);
        !           228:     }
        !           229: 
        !           230:   if (GET_CODE (addr) == PLUS)
        !           231:     {
        !           232:       if (temp = index_reg (XEXP (addr,0)))
        !           233:        return temp;
        !           234:       else
        !           235:        return index_reg (XEXP (addr,1));
        !           236:     }
        !           237: 
        !           238:   return 0;
        !           239: }
        !           240: 
        !           241: 
        !           242: /* simulate the move double by generating two movl's. You have */
        !           243: /* to be careful about mixing modes here. A future improvement */
        !           244: /* would be to allow immediate doubles.                               */
        !           245: 
        !           246: char *
        !           247: output_move_double (operands)
        !           248:      rtx *operands;
        !           249: {
        !           250:   enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, INDOP, CNSTOP, RNDOP } optype0, optype1;
        !           251:   rtx latehalf[2];
        !           252:   rtx shftreg0 = 0, shftreg1 = 0;
        !           253:   rtx temp0 = 0, temp1 = 0;
        !           254:   rtx addreg0 = 0, addreg1 = 0;
        !           255:   int dohighfirst = 0;
        !           256: 
        !           257:   /* First classify both operands. */
        !           258: 
        !           259:   if (REG_P (operands[0]))
        !           260:     optype0 = REGOP;
        !           261:   else if ((GET_CODE (operands[0])==MEM) && (shftreg0=index_reg (operands[0])))
        !           262:     optype0 = INDOP;
        !           263:   else if (offsettable_memref_p (operands[0]))
        !           264:     optype0 = OFFSOP;
        !           265:   else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
        !           266:     {
        !           267:       optype0 = PUSHOP;
        !           268:       dohighfirst++;
        !           269:     }
        !           270:   else if (GET_CODE (operands[0]) == MEM)
        !           271:     optype0 = MEMOP;
        !           272:   else
        !           273:     optype0 = RNDOP;
        !           274: 
        !           275:   if (REG_P (operands[1]))
        !           276:     optype1 = REGOP;
        !           277:   else if ((GET_CODE (operands[1])==MEM) && (shftreg1=index_reg (operands[1])))
        !           278:     optype1 = INDOP;
        !           279:   else if (offsettable_memref_p (operands[1]))
        !           280:     optype1 = OFFSOP;
        !           281:   else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
        !           282:     optype1 = POPOP; 
        !           283:   else if (GET_CODE (operands[1]) == MEM)
        !           284:     optype1 = MEMOP;
        !           285:   else if (GET_CODE (operands[1]) == CONST_DOUBLE || CONSTANT_P (operands[1]))
        !           286:     optype1 = CNSTOP;
        !           287:   else
        !           288:     optype1 = RNDOP;
        !           289: 
        !           290:   /* set up for the high byte move for operand zero */
        !           291: 
        !           292:   switch (optype0)
        !           293:     {
        !           294: 
        !           295:       /* if it's a register, just use the next highest in the */
        !           296:       /* high address move.                                    */
        !           297: 
        !           298:     case REGOP:
        !           299:       latehalf[0] = gen_rtx (REG,SImode,REGNO (operands[0])+1);
        !           300:       break;
        !           301: 
        !           302:       /* for an offsettable address, use the gcc function to  */
        !           303:       /* modify the operand to get an offset of 4 higher for  */
        !           304:       /* the second move.                                      */
        !           305: 
        !           306:     case OFFSOP:
        !           307:       latehalf[0] = adj_offsettable_operand (operands[0], 4);
        !           308:       break;
        !           309: 
        !           310:       /* if the operand is MEMOP type, it must be a pointer    */
        !           311:       /* to a pointer. So just remember to increase the mem    */
        !           312:       /* location and use the same operand.                    */
        !           313: 
        !           314:     case MEMOP:
        !           315:       latehalf[0] = operands[0];
        !           316:       addreg0 = XEXP (operands[0],0);
        !           317:       break;
        !           318: 
        !           319:       /* if we're dealing with a push instruction, just leave */
        !           320:       /* the operand alone since it auto-increments.           */
        !           321: 
        !           322:     case PUSHOP:
        !           323:       latehalf[0] = operands[0];
        !           324:       break;
        !           325: 
        !           326:       /* YUCK! Indexed addressing!! If the address is considered   */
        !           327:       /* offsettable, go use the offset in the high part. Otherwise */
        !           328:       /* find what exactly is being added to the mutiplication. If */
        !           329:       /* it's a mem reference, increment that with the high part   */
        !           330:       /* being unchanged to cause the shift. If it's a reg, do the */
        !           331:       /* same. If you can't identify it, abort. Remember that the  */
        !           332:       /* shift register was already set during identification.     */
        !           333: 
        !           334:     case INDOP:
        !           335:       if (offsettable_memref_p (operands[0]))
        !           336:        {
        !           337:          latehalf[0] = adj_offsettable_operand (operands[0],4);
        !           338:          break;
        !           339:        }
        !           340: 
        !           341:       latehalf[0] = operands[0];
        !           342: 
        !           343:       temp0 = XEXP (XEXP (operands[0],0),0);
        !           344:       if (GET_CODE (temp0) == MULT)
        !           345:        {
        !           346:          temp1 = temp0;
        !           347:          temp0 = XEXP (XEXP (operands[0],0),1);
        !           348:        }
        !           349:       else
        !           350:        {
        !           351:          temp1 = XEXP (XEXP (operands[0],0),1);
        !           352:          if (GET_CODE (temp1) != MULT)
        !           353:            abort ();
        !           354:        }
        !           355: 
        !           356:       if (GET_CODE (temp0) == MEM)
        !           357:        addreg0 = temp0;
        !           358:       else if (GET_CODE (temp0) == REG)
        !           359:        addreg0 = temp0;
        !           360:       else
        !           361:        abort ();
        !           362: 
        !           363:       break;
        !           364: 
        !           365:       /* if we don't know the operand type, print a friendly  */
        !           366:       /* little error message...   8-)                 */
        !           367: 
        !           368:     case RNDOP:
        !           369:       default:
        !           370:       abort ();
        !           371:     }
        !           372: 
        !           373:   /* do the same setup for operand one */
        !           374: 
        !           375:   switch (optype1)
        !           376:     {
        !           377: 
        !           378:     case REGOP:
        !           379:       latehalf[1] = gen_rtx (REG,SImode,REGNO (operands[1])+1);
        !           380:       break;
        !           381: 
        !           382:     case OFFSOP:
        !           383:       latehalf[1] = adj_offsettable_operand (operands[1], 4);
        !           384:       break;
        !           385: 
        !           386:     case MEMOP:
        !           387:       latehalf[1] = operands[1];
        !           388:       addreg1 = XEXP (operands[1],0);
        !           389:       break;
        !           390: 
        !           391:     case POPOP:
        !           392:       latehalf[1] = operands[1];
        !           393:       break;
        !           394: 
        !           395:     case INDOP:
        !           396:       if (offsettable_memref_p (operands[1]))
        !           397:        {
        !           398:          latehalf[1] = adj_offsettable_operand (operands[1],4);
        !           399:          break;
        !           400:        }
        !           401: 
        !           402:       latehalf[1] = operands[1];
        !           403: 
        !           404:       temp0 = XEXP (XEXP (operands[1],0),0);
        !           405:       if (GET_CODE (temp0) == MULT)
        !           406:        {
        !           407:          temp1 = temp0;
        !           408:          temp0 = XEXP (XEXP (operands[1],0),1);
        !           409:        }
        !           410:       else
        !           411:        {
        !           412:          temp1 = XEXP (XEXP (operands[1],0),1);
        !           413:          if (GET_CODE (temp1) != MULT)
        !           414:            abort ();
        !           415:        }
        !           416: 
        !           417:       if (GET_CODE (temp0) == MEM)
        !           418:        addreg1 = temp0;
        !           419:       else if (GET_CODE (temp0) == REG)
        !           420:        addreg1 = temp0;
        !           421:       else
        !           422:        abort ();
        !           423: 
        !           424:       break;
        !           425: 
        !           426:     case CNSTOP:
        !           427:       /* Since this machine is big-endian,
        !           428:         the late half must be the low-order word for an integer,
        !           429:         or the latter word for a float.  */
        !           430:       if (GET_CODE (operands[1]) == CONST_DOUBLE)
        !           431:        {
        !           432:          if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_FLOAT)
        !           433:            {
        !           434:              latehalf[1] = gen_rtx (CONST_INT, VOIDmode,
        !           435:                                     CONST_DOUBLE_HIGH (operands[1]));
        !           436:              operands[1] = gen_rtx (CONST_INT, VOIDmode,
        !           437:                                     CONST_DOUBLE_LOW (operands[1]));
        !           438:            }
        !           439:          else
        !           440:            {
        !           441:              latehalf[1] = gen_rtx (CONST_INT, VOIDmode,
        !           442:                                     CONST_DOUBLE_LOW (operands[1]));
        !           443:              operands[1] = gen_rtx (CONST_INT, VOIDmode,
        !           444:                                     CONST_DOUBLE_HIGH (operands[1]));
        !           445:            }
        !           446:        }
        !           447:       else
        !           448:        {
        !           449:          latehalf[1] = operands[1];
        !           450:          operands[1] = const0_rtx;
        !           451:        }
        !           452:       break;
        !           453: 
        !           454:     case RNDOP:
        !           455:     default:
        !           456:       abort ();
        !           457:     }
        !           458: 
        !           459: 
        !           460:   /* double the register used for shifting in both of the operands */
        !           461:   /* but make sure the same register isn't doubled twice!         */
        !           462: 
        !           463:   if (shftreg0 && shftreg1 && rtx_equal_p (shftreg0, shftreg1))
        !           464:     output_asm_insn ("addl2 %0,%0", &shftreg0);
        !           465:   else
        !           466:     {
        !           467:       if (shftreg0)
        !           468:        output_asm_insn ("addl2 %0,%0", &shftreg0);
        !           469:       if (shftreg1)
        !           470:        output_asm_insn ("addl2 %0,%0", &shftreg1);
        !           471:     }
        !           472: 
        !           473:   /* if the destination is a register and that register is needed in  */
        !           474:   /* the source addressing mode, swap the order of the moves since we */
        !           475:   /* don't want this destroyed til last. If both regs are used, not   */
        !           476:   /* much we can do, so abort. If these becomes a problem, maybe we   */
        !           477:   /* can do it on the stack?                                         */
        !           478: 
        !           479:   if (GET_CODE (operands[0])==REG && regisused (operands[1],REGNO (operands[0])))
        !           480:     if (regisused (latehalf[1],REGNO (latehalf[0])))
        !           481:       8;
        !           482:     else
        !           483:       dohighfirst++;
        !           484: 
        !           485:   /* if we're pushing, do the high address part first. */
        !           486: 
        !           487:   if (dohighfirst)
        !           488:     {
        !           489: 
        !           490:       if (addreg0 && addreg1 && (rtx_equal_p (addreg0,addreg1)))
        !           491:        output_asm_insn ("addl2 $4,%0", &addreg0);
        !           492:       else
        !           493:        {
        !           494:          if (addreg0)
        !           495:            output_asm_insn ("addl2 $4,%0", &addreg0);
        !           496:          if (addreg1)
        !           497:            output_asm_insn ("addl2 $4,%0", &addreg1);
        !           498:        }
        !           499: 
        !           500:       output_asm_insn (singlemove_string (latehalf), latehalf);
        !           501: 
        !           502:       if (addreg0 && addreg1 && (rtx_equal_p (addreg0,addreg1)))
        !           503:        output_asm_insn ("subl2 $4,%0", &addreg0);
        !           504:       else
        !           505:        {
        !           506:          if (addreg0)
        !           507:            output_asm_insn ("subl2 $4,%0", &addreg0);
        !           508:          if (addreg1)
        !           509:            output_asm_insn ("subl2 $4,%0", &addreg1);
        !           510:        }
        !           511: 
        !           512:       return singlemove_string (operands);
        !           513:     }
        !           514: 
        !           515:   output_asm_insn (singlemove_string (operands), operands);
        !           516: 
        !           517:   if (addreg0 && addreg1 && (rtx_equal_p (addreg0,addreg1)))
        !           518:     output_asm_insn ("addl2 $4,%0", &addreg0);
        !           519:   else
        !           520:     {
        !           521:       if (addreg0)
        !           522:        output_asm_insn ("addl2 $4,%0", &addreg0);
        !           523:       if (addreg1)
        !           524:        output_asm_insn ("addl2 $4,%0", &addreg1);
        !           525:     }
        !           526: 
        !           527:   output_asm_insn (singlemove_string (latehalf), latehalf);
        !           528: 
        !           529:   if (addreg0 && addreg1 && (rtx_equal_p (addreg0,addreg1)))
        !           530:     output_asm_insn ("subl2 $4,%0", &addreg0);
        !           531:   else
        !           532:     {
        !           533:       if (addreg0)
        !           534:        output_asm_insn ("subl2 $4,%0", &addreg0);
        !           535:       if (addreg1)
        !           536:        output_asm_insn ("subl2 $4,%0", &addreg1);
        !           537:     }
        !           538: 
        !           539:   if (shftreg0 && shftreg1 && (rtx_equal_p (shftreg0,shftreg1)))
        !           540:     output_asm_insn ("shar $1,%0,%0", &shftreg0);
        !           541:   else
        !           542:     {
        !           543:       if (shftreg0)
        !           544:        output_asm_insn ("shar $1,%0,%0", &shftreg0);
        !           545:       if (shftreg1)
        !           546:        output_asm_insn ("shar $1,%0,%0", &shftreg1);
        !           547:     }
        !           548: 
        !           549:   return "";
        !           550: }

unix.superglobalmegacorp.com

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