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

1.1       root        1: /* Subroutines for insn-output.c for Vax.
                      2:    Copyright (C) 1987 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 2, or (at your option)
                      9: any later version.
                     10: 
                     11: GNU CC is distributed in the hope that it will be useful,
                     12: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     14: GNU General Public License for more details.
                     15: 
                     16: You should have received a copy of the GNU General Public License
                     17: along with GNU CC; see the file COPYING.  If not, write to
                     18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
                     19: 
                     20: #include <stdio.h>
                     21: #include "config.h"
                     22: #include "rtl.h"
                     23: #include "regs.h"
                     24: #include "hard-reg-set.h"
                     25: #include "real.h"
                     26: #include "insn-config.h"
                     27: #include "conditions.h"
                     28: #include "insn-flags.h"
                     29: #include "output.h"
                     30: #include "insn-attr.h"
                     31: 
                     32: 
1.1.1.2   root       33: /* This is like nonimmediate_operand with a restriction on the type of MEM.  */
1.1       root       34: 
                     35: void
                     36: split_quadword_operands (operands, low, n)
                     37:      rtx *operands, *low;
                     38: {
                     39:   int i;
                     40:   /* Split operands.  */
                     41: 
                     42:   low[0] = low[1] = low[2] = 0;
                     43:   for (i = 0; i < 3; i++)
                     44:     {
                     45:       if (low[i])
                     46:        /* it's already been figured out */;
                     47:       else if (GET_CODE (operands[i]) == MEM
                     48:               && (GET_CODE (XEXP (operands[i], 0)) == POST_INC))
                     49:        {
                     50:          rtx addr = XEXP (operands[i], 0);
                     51:          operands[i] = low[i] = gen_rtx (MEM, SImode, addr);
                     52:          if (which_alternative == 0 && i == 0)
                     53:            {
                     54:              addr = XEXP (operands[i], 0);
                     55:              operands[i+1] = low[i+1] = gen_rtx (MEM, SImode, addr);
                     56:            }
                     57:        }
                     58:       else
                     59:        {
                     60:          low[i] = operand_subword (operands[i], 0, 0, DImode);
                     61:          operands[i] = operand_subword (operands[i], 1, 0, DImode);
                     62:        }
                     63:     }
                     64: }
                     65: 
                     66: print_operand_address (file, addr)
                     67:      FILE *file;
                     68:      register rtx addr;
                     69: {
                     70:   register rtx reg1, reg2, breg, ireg;
                     71:   rtx offset;
                     72: 
                     73:  retry:
                     74:   switch (GET_CODE (addr))
                     75:     {
                     76:     case MEM:
                     77:       fprintf (file, "*");
                     78:       addr = XEXP (addr, 0);
                     79:       goto retry;
                     80: 
                     81:     case REG:
                     82:       fprintf (file, "(%s)", reg_names[REGNO (addr)]);
                     83:       break;
                     84: 
                     85:     case PRE_DEC:
                     86:       fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
                     87:       break;
                     88: 
                     89:     case POST_INC:
                     90:       fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
                     91:       break;
                     92: 
                     93:     case PLUS:
                     94:       /* There can be either two or three things added here.  One must be a
                     95:         REG.  One can be either a REG or a MULT of a REG and an appropriate
                     96:         constant, and the third can only be a constant or a MEM.
                     97: 
                     98:         We get these two or three things and put the constant or MEM in
                     99:         OFFSET, the MULT or REG in IREG, and the REG in BREG.  If we have
                    100:         a register and can't tell yet if it is a base or index register,
                    101:         put it into REG1.  */
                    102: 
                    103:       reg1 = 0; ireg = 0; breg = 0; offset = 0;
                    104: 
                    105:       if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
                    106:          || GET_CODE (XEXP (addr, 0)) == MEM)
                    107:        {
                    108:          offset = XEXP (addr, 0);
                    109:          addr = XEXP (addr, 1);
                    110:        }
                    111:       else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
                    112:               || GET_CODE (XEXP (addr, 1)) == MEM)
                    113:        {
                    114:          offset = XEXP (addr, 1);
                    115:          addr = XEXP (addr, 0);
                    116:        }
                    117:       else if (GET_CODE (XEXP (addr, 1)) == MULT)
                    118:        {
                    119:          ireg = XEXP (addr, 1);
                    120:          addr = XEXP (addr, 0);
                    121:        }
                    122:       else if (GET_CODE (XEXP (addr, 0)) == MULT)
                    123:        {
                    124:          ireg = XEXP (addr, 0);
                    125:          addr = XEXP (addr, 1);
                    126:        }
                    127:       else if (GET_CODE (XEXP (addr, 1)) == REG)
                    128:        {
                    129:          reg1 = XEXP (addr, 1);
                    130:          addr = XEXP (addr, 0);
                    131:        }
1.1.1.2   root      132:       else if (GET_CODE (XEXP (addr, 0)) == REG)
                    133:        {
                    134:          reg1 = XEXP (addr, 0);
                    135:          addr = XEXP (addr, 1);
                    136:        }
1.1       root      137:       else
                    138:        abort ();
                    139: 
                    140:       if (GET_CODE (addr) == REG)
                    141:        {
                    142:          if (reg1)
                    143:            ireg = addr;
                    144:          else
                    145:            reg1 = addr;
                    146:        }
                    147:       else if (GET_CODE (addr) == MULT)
                    148:        ireg = addr;
                    149:       else if (GET_CODE (addr) == PLUS)
                    150:        {
                    151:          if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
                    152:              || GET_CODE (XEXP (addr, 0)) == MEM)
                    153:            {
                    154:              if (offset)
                    155:                {
                    156:                  if (GET_CODE (offset) == CONST_INT)
                    157:                    offset = plus_constant (XEXP (addr, 0), INTVAL (offset));
                    158:                  else if (GET_CODE (XEXP (addr, 0)) == CONST_INT)
                    159:                    offset = plus_constant (offset, INTVAL (XEXP (addr, 0)));
                    160:                  else
                    161:                    abort ();
                    162:                }
                    163:              offset = XEXP (addr, 0);
                    164:            }
                    165:          else if (GET_CODE (XEXP (addr, 0)) == REG)
                    166:            {
                    167:              if (reg1)
                    168:                ireg = reg1, breg = XEXP (addr, 0), reg1 = 0;
                    169:              else
                    170:                reg1 = XEXP (addr, 0);
                    171:            }
                    172:          else if (GET_CODE (XEXP (addr, 0)) == MULT)
                    173:            {
                    174:              if (ireg)
                    175:                abort ();
                    176:              ireg = XEXP (addr, 0);
                    177:            }
                    178:          else
                    179:            abort ();
                    180: 
                    181:          if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
                    182:              || GET_CODE (XEXP (addr, 1)) == MEM)
                    183:            {
                    184:              if (offset)
                    185:                {
                    186:                  if (GET_CODE (offset) == CONST_INT)
                    187:                    offset = plus_constant (XEXP (addr, 1), INTVAL (offset));
                    188:                  else if (GET_CODE (XEXP (addr, 1)) == CONST_INT)
                    189:                    offset = plus_constant (offset, INTVAL (XEXP (addr, 1)));
                    190:                  else
                    191:                    abort ();
                    192:                }
                    193:              offset = XEXP (addr, 1);
                    194:            }
                    195:          else if (GET_CODE (XEXP (addr, 1)) == REG)
                    196:            {
                    197:              if (reg1)
                    198:                ireg = reg1, breg = XEXP (addr, 1), reg1 = 0;
                    199:              else
                    200:                reg1 = XEXP (addr, 1);
                    201:            }
                    202:          else if (GET_CODE (XEXP (addr, 1)) == MULT)
                    203:            {
                    204:              if (ireg)
                    205:                abort ();
                    206:              ireg = XEXP (addr, 1);
                    207:            }
                    208:          else
                    209:            abort ();
                    210:        }
                    211:       else
                    212:        abort ();
                    213: 
                    214:       /* If REG1 is non-zero, figure out if it is a base or index register.  */
                    215:       if (reg1)
                    216:        {
                    217:          if (breg != 0 || (offset && GET_CODE (offset) == MEM))
                    218:            {
                    219:              if (ireg)
                    220:                abort ();
                    221:              ireg = reg1;
                    222:            }
                    223:          else
                    224:            breg = reg1;
                    225:        }
                    226: 
                    227:       if (offset != 0)
                    228:        output_address (offset);
                    229: 
                    230:       if (breg != 0)
                    231:        fprintf (file, "(%s)", reg_names[REGNO (breg)]);
                    232: 
                    233:       if (ireg != 0)
                    234:        {
                    235:          if (GET_CODE (ireg) == MULT)
                    236:            ireg = XEXP (ireg, 0);
                    237:          if (GET_CODE (ireg) != REG)
                    238:            abort ();
                    239:          fprintf (file, "[%s]", reg_names[REGNO (ireg)]);
                    240:        }
                    241:       break;
                    242: 
                    243:     default:
                    244:       output_addr_const (file, addr);
                    245:     }
                    246: }
                    247: 
                    248: char *
                    249: rev_cond_name (op)
                    250:      rtx op;
                    251: {
                    252:   switch (GET_CODE (op))
                    253:     {
                    254:     case EQ:
                    255:       return "neq";
                    256:     case NE:
                    257:       return "eql";
                    258:     case LT:
                    259:       return "geq";
                    260:     case LE:
                    261:       return "gtr";
                    262:     case GT:
                    263:       return "leq";
                    264:     case GE:
                    265:       return "lss";
                    266:     case LTU:
                    267:       return "gequ";
                    268:     case LEU:
                    269:       return "gtru";
                    270:     case GTU:
                    271:       return "lequ";
                    272:     case GEU:
                    273:       return "lssu";
                    274: 
                    275:     default:
                    276:       abort ();
                    277:     }
                    278: }
1.1.1.3 ! root      279: 
        !           280: int
        !           281: vax_float_literal(c)
        !           282:     register rtx c;
        !           283: {
        !           284:   register enum machine_mode mode;
        !           285:   int i;
        !           286:   union {double d; int i[2];} val;
        !           287: 
        !           288:   if (GET_CODE (c) != CONST_DOUBLE)
        !           289:     return 0;
        !           290: 
        !           291:   mode = GET_MODE (c);
        !           292: 
        !           293:   if (c == const_tiny_rtx[(int) mode][0]
        !           294:       || c == const_tiny_rtx[(int) mode][1]
        !           295:       || c == const_tiny_rtx[(int) mode][2])
        !           296:     return 1;
        !           297: 
        !           298: #if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
        !           299: 
        !           300:   val.i[0] = CONST_DOUBLE_LOW (c);
        !           301:   val.i[1] = CONST_DOUBLE_HIGH (c);
        !           302: 
        !           303:   for (i = 0; i < 7; i ++)
        !           304:     if (val.d == 1 << i || val.d == 1 / (1 << i))
        !           305:       return 1;
        !           306: #endif
        !           307:   return 0;
        !           308: }
        !           309: 
        !           310: 
        !           311: /* Return the cost in cycles of a memory address, relative to register
        !           312:    indirect.
        !           313: 
        !           314:    Each of the following adds the indicated number of cycles:
        !           315: 
        !           316:    1 - symbolic address
        !           317:    1 - pre-decrement
        !           318:    1 - indexing and/or offset(register)
        !           319:    2 - indirect */
        !           320: 
        !           321: 
        !           322: int vax_address_cost(addr)
        !           323:     register rtx addr;
        !           324: {
        !           325:   int reg = 0, indexed = 0, indir = 0, offset = 0, predec = 0;
        !           326:   rtx plus_op0 = 0, plus_op1 = 0;
        !           327:  restart:
        !           328:   switch (GET_CODE (addr))
        !           329:     {
        !           330:     case PRE_DEC:
        !           331:       predec = 1;
        !           332:     case REG:
        !           333:     case SUBREG:
        !           334:     case POST_INC:
        !           335:       reg = 1;
        !           336:       break;
        !           337:     case MULT:
        !           338:       indexed = 1;     /* 2 on VAX 2 */
        !           339:       break;
        !           340:     case CONST_INT:
        !           341:       /* byte offsets cost nothing (on a VAX 2, they cost 1 cycle) */
        !           342:       if (offset == 0)
        !           343:        offset = (unsigned)(INTVAL(addr)+128) > 256;
        !           344:       break;
        !           345:     case CONST:
        !           346:     case SYMBOL_REF:
        !           347:       offset = 1;      /* 2 on VAX 2 */
        !           348:       break;
        !           349:     case LABEL_REF:    /* this is probably a byte offset from the pc */
        !           350:       if (offset == 0)
        !           351:        offset = 1;
        !           352:       break;
        !           353:     case PLUS:
        !           354:       if (plus_op0)
        !           355:        plus_op1 = XEXP (addr, 0);
        !           356:       else
        !           357:        plus_op0 = XEXP (addr, 0);
        !           358:       addr = XEXP (addr, 1);
        !           359:       goto restart;
        !           360:     case MEM:
        !           361:       indir = 2;       /* 3 on VAX 2 */
        !           362:       addr = XEXP (addr, 0);
        !           363:       goto restart;
        !           364:     }
        !           365: 
        !           366:   /* Up to 3 things can be added in an address.  They are stored in
        !           367:      plus_op0, plus_op1, and addr.  */
        !           368: 
        !           369:   if (plus_op0)
        !           370:     {
        !           371:       addr = plus_op0;
        !           372:       plus_op0 = 0;
        !           373:       goto restart;
        !           374:     }
        !           375:   if (plus_op1)
        !           376:     {
        !           377:       addr = plus_op1;
        !           378:       plus_op1 = 0;
        !           379:       goto restart;
        !           380:     }
        !           381:   /* Indexing and register+offset can both be used (except on a VAX 2)
        !           382:      without increasing execution time over either one alone. */
        !           383:   if (reg && indexed && offset)
        !           384:     return reg + indir + offset + predec;
        !           385:   return reg + indexed + indir + offset + predec;
        !           386: }
        !           387: 
        !           388: 
        !           389: /* Cost of an expression on a VAX.  This version has costs tuned for the
        !           390:    CVAX chip (found in the VAX 3 series) with comments for variations on
        !           391:    other models.  */
        !           392: 
        !           393: int
        !           394: vax_rtx_cost (x)
        !           395:     register rtx x;
        !           396: {
        !           397:   register enum rtx_code code = GET_CODE (x);
        !           398:   enum machine_mode mode = GET_MODE (x);
        !           399:   register int c;
        !           400:   int i = 0;                           /* may be modified in switch */
        !           401:   char *fmt = GET_RTX_FORMAT (code);   /* may be modified in switch */
        !           402: 
        !           403:   switch (code)
        !           404:     {
        !           405:     case POST_INC:
        !           406:       return 2;
        !           407:     case PRE_DEC:
        !           408:       return 3;
        !           409:     case MULT:
        !           410:       switch (mode)
        !           411:        {
        !           412:        case DFmode:
        !           413:          c = 16;               /* 4 on VAX 9000 */
        !           414:          break;
        !           415:        case SFmode:
        !           416:          c = 9;                /* 4 on VAX 9000, 12 on VAX 2 */
        !           417:          break;
        !           418:        case DImode:
        !           419:          c = 16;               /* 6 on VAX 9000, 28 on VAX 2 */
        !           420:          break;
        !           421:        case SImode:
        !           422:        case HImode:
        !           423:        case QImode:
        !           424:          c = 10;               /* 3-4 on VAX 9000, 20-28 on VAX 2 */
        !           425:          break;
        !           426:        }
        !           427:       break;
        !           428:     case UDIV:
        !           429:       c = 17;
        !           430:       break;
        !           431:     case DIV:
        !           432:       if (mode == DImode)
        !           433:        c = 30; /* highly variable */
        !           434:       else if (mode == DFmode)
        !           435:        /* divide takes 28 cycles if the result is not zero, 13 otherwise */
        !           436:        c = 24;
        !           437:       else
        !           438:        c = 11;                 /* 25 on VAX 2 */
        !           439:       break;
        !           440:     case MOD:
        !           441:       c = 23;
        !           442:       break;
        !           443:     case UMOD:
        !           444:       c = 29;
        !           445:       break;
        !           446:     case FLOAT:
        !           447:       c = 6 + (mode == DFmode) + (GET_MODE (XEXP (x, 0)) != SImode);
        !           448:       /* 4 on VAX 9000 */
        !           449:       break;
        !           450:     case FIX:
        !           451:       c = 7;                   /* 17 on VAX 2 */
        !           452:       break;
        !           453:     case LSHIFT:
        !           454:     case ASHIFT:
        !           455:     case LSHIFTRT:
        !           456:     case ASHIFTRT:
        !           457:       if (mode == DImode)
        !           458:        c = 12;
        !           459:       else
        !           460:        c = 10;                 /* 6 on VAX 9000 */
        !           461:       break;
        !           462:     case ROTATE:
        !           463:     case ROTATERT:
        !           464:       c = 6;                   /* 5 on VAX 2, 4 on VAX 9000 */
        !           465:       if (GET_CODE (XEXP (x, 1)) == CONST_INT)
        !           466:        fmt = "e";      /* all constant rotate counts are short */
        !           467:       break;
        !           468:     case PLUS:
        !           469:       /* Check for small negative integer operand: subl2 can be used with
        !           470:         a short positive constant instead.  */
        !           471:       if (GET_CODE (XEXP (x, 1)) == CONST_INT)
        !           472:        if ((unsigned)(INTVAL (XEXP (x, 1)) + 63) < 127)
        !           473:          fmt = "e";
        !           474:     case MINUS:
        !           475:       c = (mode == DFmode) ? 13 : 8;   /* 6/8 on VAX 9000, 16/15 on VAX 2 */
        !           476:     case IOR:
        !           477:     case XOR:
        !           478:       c = 3;
        !           479:       break;
        !           480:     case AND:
        !           481:       /* AND is special because the first operand is complemented. */
        !           482:       c = 3;
        !           483:       if (GET_CODE (XEXP (x, 0)) == CONST_INT)
        !           484:        {
        !           485:          if ((unsigned)~INTVAL (XEXP (x, 0)) > 63)
        !           486:            c = 4;
        !           487:          fmt = "e";
        !           488:          i = 1;
        !           489:        }
        !           490:       break;
        !           491:     case NEG:
        !           492:       if (mode == DFmode)
        !           493:        return 9;
        !           494:       else if (mode == SFmode)
        !           495:        return 6;
        !           496:       else if (mode == DImode)
        !           497:        return 4;
        !           498:     case NOT:
        !           499:       return 2;
        !           500:     case ZERO_EXTRACT:
        !           501:     case SIGN_EXTRACT:
        !           502:       c = 15;
        !           503:       break;
        !           504:     case MEM:
        !           505:       if (mode == DImode || mode == DFmode)
        !           506:        c = 5;                          /* 7 on VAX 2 */
        !           507:       else
        !           508:        c = 3;                          /* 4 on VAX 2 */
        !           509:       x = XEXP (x, 0);
        !           510:       if (GET_CODE (x) == REG || GET_CODE (x) == POST_INC)
        !           511:        return c;
        !           512:       return c + vax_address_cost (x);
        !           513:     default:
        !           514:       c = 3;
        !           515:       break;
        !           516:     }
        !           517: 
        !           518: 
        !           519:   /* Now look inside the expression.  Operands which are not registers or
        !           520:      short constants add to the cost.
        !           521: 
        !           522:      FMT and I may have been adjusted in the switch above for instructions
        !           523:      which require special handling */
        !           524: 
        !           525:   while (*fmt++ == 'e')
        !           526:     {
        !           527:       register rtx op = XEXP (x, i++);
        !           528:       code = GET_CODE (op);
        !           529: 
        !           530:       /* A NOT is likely to be found as the first operand of an AND
        !           531:         (in which case the relevant cost is of the operand inside
        !           532:         the not) and not likely to be found anywhere else.  */
        !           533:       if (code == NOT)
        !           534:        op = XEXP (op, 0), code = GET_CODE (op);
        !           535: 
        !           536:       switch (code)
        !           537:        {
        !           538:        case CONST_INT:
        !           539:          if ((unsigned)INTVAL (op) > 63 && GET_MODE (x) != QImode)
        !           540:            c += 1;             /* 2 on VAX 2 */
        !           541:          break;
        !           542:        case CONST:
        !           543:        case LABEL_REF:
        !           544:        case SYMBOL_REF:
        !           545:          c += 1;               /* 2 on VAX 2 */
        !           546:          break;
        !           547:        case CONST_DOUBLE:
        !           548:          if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT)
        !           549:            {
        !           550:              /* Registers are faster than floating point constants -- even
        !           551:                 those constants which can be encoded in a single byte.  */
        !           552:              if (vax_float_literal (op))
        !           553:                c++;
        !           554:              else
        !           555:                c += (GET_MODE (x) == DFmode) ? 3 : 2;
        !           556:            }
        !           557:          else
        !           558:            {
        !           559:              if (CONST_DOUBLE_HIGH (op) != 0
        !           560:                  || (unsigned)CONST_DOUBLE_LOW (op) > 63)
        !           561:                c += 2;
        !           562:            }
        !           563:          break;
        !           564:        case MEM:
        !           565:          c += 1;               /* 2 on VAX 2 */
        !           566:          if (GET_CODE (XEXP (op, 0)) != REG)
        !           567:            c += vax_address_cost (XEXP (op, 0));
        !           568:          break;
        !           569:        case REG:
        !           570:        case SUBREG:
        !           571:          break;
        !           572:        default:
        !           573:          c += 1;
        !           574:          break;
        !           575:        }
        !           576:     }
        !           577:   return c;
        !           578: }

unix.superglobalmegacorp.com

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