Annotation of GNUtools/cc/config/vax/vax.c, revision 1.1

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: 
        !            33: /* This is like nonimmediate_operand with a restriction on the type of MEM.  */
        !            34: 
        !            35: void
        !            36: split_quadword_operands (operands, low, n)
        !            37:      rtx *operands, *low;
        !            38:      int n;
        !            39: {
        !            40:   int i;
        !            41:   /* Split operands.  */
        !            42: 
        !            43:   low[0] = low[1] = low[2] = 0;
        !            44:   for (i = 0; i < 3; i++)
        !            45:     {
        !            46:       if (low[i])
        !            47:        /* it's already been figured out */;
        !            48:       else if (GET_CODE (operands[i]) == MEM
        !            49:               && (GET_CODE (XEXP (operands[i], 0)) == POST_INC))
        !            50:        {
        !            51:          rtx addr = XEXP (operands[i], 0);
        !            52:          operands[i] = low[i] = gen_rtx (MEM, SImode, addr);
        !            53:          if (which_alternative == 0 && i == 0)
        !            54:            {
        !            55:              addr = XEXP (operands[i], 0);
        !            56:              operands[i+1] = low[i+1] = gen_rtx (MEM, SImode, addr);
        !            57:            }
        !            58:        }
        !            59:       else
        !            60:        {
        !            61:          low[i] = operand_subword (operands[i], 0, 0, DImode);
        !            62:          operands[i] = operand_subword (operands[i], 1, 0, DImode);
        !            63:        }
        !            64:     }
        !            65: }
        !            66: 
        !            67: print_operand_address (file, addr)
        !            68:      FILE *file;
        !            69:      register rtx addr;
        !            70: {
        !            71:   register rtx reg1, reg2, breg, ireg;
        !            72:   rtx offset;
        !            73: 
        !            74:  retry:
        !            75:   switch (GET_CODE (addr))
        !            76:     {
        !            77:     case MEM:
        !            78:       fprintf (file, "*");
        !            79:       addr = XEXP (addr, 0);
        !            80:       goto retry;
        !            81: 
        !            82:     case REG:
        !            83:       fprintf (file, "(%s)", reg_names[REGNO (addr)]);
        !            84:       break;
        !            85: 
        !            86:     case PRE_DEC:
        !            87:       fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
        !            88:       break;
        !            89: 
        !            90:     case POST_INC:
        !            91:       fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
        !            92:       break;
        !            93: 
        !            94:     case PLUS:
        !            95:       /* There can be either two or three things added here.  One must be a
        !            96:         REG.  One can be either a REG or a MULT of a REG and an appropriate
        !            97:         constant, and the third can only be a constant or a MEM.
        !            98: 
        !            99:         We get these two or three things and put the constant or MEM in
        !           100:         OFFSET, the MULT or REG in IREG, and the REG in BREG.  If we have
        !           101:         a register and can't tell yet if it is a base or index register,
        !           102:         put it into REG1.  */
        !           103: 
        !           104:       reg1 = 0; ireg = 0; breg = 0; offset = 0;
        !           105: 
        !           106:       if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
        !           107:          || GET_CODE (XEXP (addr, 0)) == MEM)
        !           108:        {
        !           109:          offset = XEXP (addr, 0);
        !           110:          addr = XEXP (addr, 1);
        !           111:        }
        !           112:       else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
        !           113:               || GET_CODE (XEXP (addr, 1)) == MEM)
        !           114:        {
        !           115:          offset = XEXP (addr, 1);
        !           116:          addr = XEXP (addr, 0);
        !           117:        }
        !           118:       else if (GET_CODE (XEXP (addr, 1)) == MULT)
        !           119:        {
        !           120:          ireg = XEXP (addr, 1);
        !           121:          addr = XEXP (addr, 0);
        !           122:        }
        !           123:       else if (GET_CODE (XEXP (addr, 0)) == MULT)
        !           124:        {
        !           125:          ireg = XEXP (addr, 0);
        !           126:          addr = XEXP (addr, 1);
        !           127:        }
        !           128:       else if (GET_CODE (XEXP (addr, 1)) == REG)
        !           129:        {
        !           130:          reg1 = XEXP (addr, 1);
        !           131:          addr = XEXP (addr, 0);
        !           132:        }
        !           133:       else if (GET_CODE (XEXP (addr, 0)) == REG)
        !           134:        {
        !           135:          reg1 = XEXP (addr, 0);
        !           136:          addr = XEXP (addr, 1);
        !           137:        }
        !           138:       else
        !           139:        abort ();
        !           140: 
        !           141:       if (GET_CODE (addr) == REG)
        !           142:        {
        !           143:          if (reg1)
        !           144:            ireg = addr;
        !           145:          else
        !           146:            reg1 = addr;
        !           147:        }
        !           148:       else if (GET_CODE (addr) == MULT)
        !           149:        ireg = addr;
        !           150:       else if (GET_CODE (addr) == PLUS)
        !           151:        {
        !           152:          if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
        !           153:              || GET_CODE (XEXP (addr, 0)) == MEM)
        !           154:            {
        !           155:              if (offset)
        !           156:                {
        !           157:                  if (GET_CODE (offset) == CONST_INT)
        !           158:                    offset = plus_constant (XEXP (addr, 0), INTVAL (offset));
        !           159:                  else if (GET_CODE (XEXP (addr, 0)) == CONST_INT)
        !           160:                    offset = plus_constant (offset, INTVAL (XEXP (addr, 0)));
        !           161:                  else
        !           162:                    abort ();
        !           163:                }
        !           164:              offset = XEXP (addr, 0);
        !           165:            }
        !           166:          else if (GET_CODE (XEXP (addr, 0)) == REG)
        !           167:            {
        !           168:              if (reg1)
        !           169:                ireg = reg1, breg = XEXP (addr, 0), reg1 = 0;
        !           170:              else
        !           171:                reg1 = XEXP (addr, 0);
        !           172:            }
        !           173:          else if (GET_CODE (XEXP (addr, 0)) == MULT)
        !           174:            {
        !           175:              if (ireg)
        !           176:                abort ();
        !           177:              ireg = XEXP (addr, 0);
        !           178:            }
        !           179:          else
        !           180:            abort ();
        !           181: 
        !           182:          if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
        !           183:              || GET_CODE (XEXP (addr, 1)) == MEM)
        !           184:            {
        !           185:              if (offset)
        !           186:                {
        !           187:                  if (GET_CODE (offset) == CONST_INT)
        !           188:                    offset = plus_constant (XEXP (addr, 1), INTVAL (offset));
        !           189:                  else if (GET_CODE (XEXP (addr, 1)) == CONST_INT)
        !           190:                    offset = plus_constant (offset, INTVAL (XEXP (addr, 1)));
        !           191:                  else
        !           192:                    abort ();
        !           193:                }
        !           194:              offset = XEXP (addr, 1);
        !           195:            }
        !           196:          else if (GET_CODE (XEXP (addr, 1)) == REG)
        !           197:            {
        !           198:              if (reg1)
        !           199:                ireg = reg1, breg = XEXP (addr, 1), reg1 = 0;
        !           200:              else
        !           201:                reg1 = XEXP (addr, 1);
        !           202:            }
        !           203:          else if (GET_CODE (XEXP (addr, 1)) == MULT)
        !           204:            {
        !           205:              if (ireg)
        !           206:                abort ();
        !           207:              ireg = XEXP (addr, 1);
        !           208:            }
        !           209:          else
        !           210:            abort ();
        !           211:        }
        !           212:       else
        !           213:        abort ();
        !           214: 
        !           215:       /* If REG1 is non-zero, figure out if it is a base or index register.  */
        !           216:       if (reg1)
        !           217:        {
        !           218:          if (breg != 0 || (offset && GET_CODE (offset) == MEM))
        !           219:            {
        !           220:              if (ireg)
        !           221:                abort ();
        !           222:              ireg = reg1;
        !           223:            }
        !           224:          else
        !           225:            breg = reg1;
        !           226:        }
        !           227: 
        !           228:       if (offset != 0)
        !           229:        output_address (offset);
        !           230: 
        !           231:       if (breg != 0)
        !           232:        fprintf (file, "(%s)", reg_names[REGNO (breg)]);
        !           233: 
        !           234:       if (ireg != 0)
        !           235:        {
        !           236:          if (GET_CODE (ireg) == MULT)
        !           237:            ireg = XEXP (ireg, 0);
        !           238:          if (GET_CODE (ireg) != REG)
        !           239:            abort ();
        !           240:          fprintf (file, "[%s]", reg_names[REGNO (ireg)]);
        !           241:        }
        !           242:       break;
        !           243: 
        !           244:     default:
        !           245:       output_addr_const (file, addr);
        !           246:     }
        !           247: }
        !           248: 
        !           249: char *
        !           250: rev_cond_name (op)
        !           251:      rtx op;
        !           252: {
        !           253:   switch (GET_CODE (op))
        !           254:     {
        !           255:     case EQ:
        !           256:       return "neq";
        !           257:     case NE:
        !           258:       return "eql";
        !           259:     case LT:
        !           260:       return "geq";
        !           261:     case LE:
        !           262:       return "gtr";
        !           263:     case GT:
        !           264:       return "leq";
        !           265:     case GE:
        !           266:       return "lss";
        !           267:     case LTU:
        !           268:       return "gequ";
        !           269:     case LEU:
        !           270:       return "gtru";
        !           271:     case GTU:
        !           272:       return "lequ";
        !           273:     case GEU:
        !           274:       return "lssu";
        !           275: 
        !           276:     default:
        !           277:       abort ();
        !           278:     }
        !           279: }
        !           280: 
        !           281: int
        !           282: vax_float_literal(c)
        !           283:     register rtx c;
        !           284: {
        !           285:   register enum machine_mode mode;
        !           286:   int i;
        !           287:   union {double d; int i[2];} val;
        !           288: 
        !           289:   if (GET_CODE (c) != CONST_DOUBLE)
        !           290:     return 0;
        !           291: 
        !           292:   mode = GET_MODE (c);
        !           293: 
        !           294:   if (c == const_tiny_rtx[(int) mode][0]
        !           295:       || c == const_tiny_rtx[(int) mode][1]
        !           296:       || c == const_tiny_rtx[(int) mode][2])
        !           297:     return 1;
        !           298: 
        !           299: #if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
        !           300: 
        !           301:   val.i[0] = CONST_DOUBLE_LOW (c);
        !           302:   val.i[1] = CONST_DOUBLE_HIGH (c);
        !           303: 
        !           304:   for (i = 0; i < 7; i ++)
        !           305:     if (val.d == 1 << i || val.d == 1 / (1 << i))
        !           306:       return 1;
        !           307: #endif
        !           308:   return 0;
        !           309: }
        !           310: 
        !           311: 
        !           312: /* Return the cost in cycles of a memory address, relative to register
        !           313:    indirect.
        !           314: 
        !           315:    Each of the following adds the indicated number of cycles:
        !           316: 
        !           317:    1 - symbolic address
        !           318:    1 - pre-decrement
        !           319:    1 - indexing and/or offset(register)
        !           320:    2 - indirect */
        !           321: 
        !           322: 
        !           323: int vax_address_cost(addr)
        !           324:     register rtx addr;
        !           325: {
        !           326:   int reg = 0, indexed = 0, indir = 0, offset = 0, predec = 0;
        !           327:   rtx plus_op0 = 0, plus_op1 = 0;
        !           328:  restart:
        !           329:   switch (GET_CODE (addr))
        !           330:     {
        !           331:     case PRE_DEC:
        !           332:       predec = 1;
        !           333:     case REG:
        !           334:     case SUBREG:
        !           335:     case POST_INC:
        !           336:       reg = 1;
        !           337:       break;
        !           338:     case MULT:
        !           339:       indexed = 1;     /* 2 on VAX 2 */
        !           340:       break;
        !           341:     case CONST_INT:
        !           342:       /* byte offsets cost nothing (on a VAX 2, they cost 1 cycle) */
        !           343:       if (offset == 0)
        !           344:        offset = (unsigned)(INTVAL(addr)+128) > 256;
        !           345:       break;
        !           346:     case CONST:
        !           347:     case SYMBOL_REF:
        !           348:       offset = 1;      /* 2 on VAX 2 */
        !           349:       break;
        !           350:     case LABEL_REF:    /* this is probably a byte offset from the pc */
        !           351:       if (offset == 0)
        !           352:        offset = 1;
        !           353:       break;
        !           354:     case PLUS:
        !           355:       if (plus_op0)
        !           356:        plus_op1 = XEXP (addr, 0);
        !           357:       else
        !           358:        plus_op0 = XEXP (addr, 0);
        !           359:       addr = XEXP (addr, 1);
        !           360:       goto restart;
        !           361:     case MEM:
        !           362:       indir = 2;       /* 3 on VAX 2 */
        !           363:       addr = XEXP (addr, 0);
        !           364:       goto restart;
        !           365:     }
        !           366: 
        !           367:   /* Up to 3 things can be added in an address.  They are stored in
        !           368:      plus_op0, plus_op1, and addr.  */
        !           369: 
        !           370:   if (plus_op0)
        !           371:     {
        !           372:       addr = plus_op0;
        !           373:       plus_op0 = 0;
        !           374:       goto restart;
        !           375:     }
        !           376:   if (plus_op1)
        !           377:     {
        !           378:       addr = plus_op1;
        !           379:       plus_op1 = 0;
        !           380:       goto restart;
        !           381:     }
        !           382:   /* Indexing and register+offset can both be used (except on a VAX 2)
        !           383:      without increasing execution time over either one alone. */
        !           384:   if (reg && indexed && offset)
        !           385:     return reg + indir + offset + predec;
        !           386:   return reg + indexed + indir + offset + predec;
        !           387: }
        !           388: 
        !           389: 
        !           390: /* Cost of an expression on a VAX.  This version has costs tuned for the
        !           391:    CVAX chip (found in the VAX 3 series) with comments for variations on
        !           392:    other models.  */
        !           393: 
        !           394: int
        !           395: vax_rtx_cost (x)
        !           396:     register rtx x;
        !           397: {
        !           398:   register enum rtx_code code = GET_CODE (x);
        !           399:   enum machine_mode mode = GET_MODE (x);
        !           400:   register int c;
        !           401:   int i = 0;                           /* may be modified in switch */
        !           402:   char *fmt = GET_RTX_FORMAT (code);   /* may be modified in switch */
        !           403: 
        !           404:   switch (code)
        !           405:     {
        !           406:     case POST_INC:
        !           407:       return 2;
        !           408:     case PRE_DEC:
        !           409:       return 3;
        !           410:     case MULT:
        !           411:       switch (mode)
        !           412:        {
        !           413:        case DFmode:
        !           414:          c = 16;               /* 4 on VAX 9000 */
        !           415:          break;
        !           416:        case SFmode:
        !           417:          c = 9;                /* 4 on VAX 9000, 12 on VAX 2 */
        !           418:          break;
        !           419:        case DImode:
        !           420:          c = 16;               /* 6 on VAX 9000, 28 on VAX 2 */
        !           421:          break;
        !           422:        case SImode:
        !           423:        case HImode:
        !           424:        case QImode:
        !           425:          c = 10;               /* 3-4 on VAX 9000, 20-28 on VAX 2 */
        !           426:          break;
        !           427:        }
        !           428:       break;
        !           429:     case UDIV:
        !           430:       c = 17;
        !           431:       break;
        !           432:     case DIV:
        !           433:       if (mode == DImode)
        !           434:        c = 30; /* highly variable */
        !           435:       else if (mode == DFmode)
        !           436:        /* divide takes 28 cycles if the result is not zero, 13 otherwise */
        !           437:        c = 24;
        !           438:       else
        !           439:        c = 11;                 /* 25 on VAX 2 */
        !           440:       break;
        !           441:     case MOD:
        !           442:       c = 23;
        !           443:       break;
        !           444:     case UMOD:
        !           445:       c = 29;
        !           446:       break;
        !           447:     case FLOAT:
        !           448:       c = 6 + (mode == DFmode) + (GET_MODE (XEXP (x, 0)) != SImode);
        !           449:       /* 4 on VAX 9000 */
        !           450:       break;
        !           451:     case FIX:
        !           452:       c = 7;                   /* 17 on VAX 2 */
        !           453:       break;
        !           454:     case LSHIFT:
        !           455:     case ASHIFT:
        !           456:     case LSHIFTRT:
        !           457:     case ASHIFTRT:
        !           458:       if (mode == DImode)
        !           459:        c = 12;
        !           460:       else
        !           461:        c = 10;                 /* 6 on VAX 9000 */
        !           462:       break;
        !           463:     case ROTATE:
        !           464:     case ROTATERT:
        !           465:       c = 6;                   /* 5 on VAX 2, 4 on VAX 9000 */
        !           466:       if (GET_CODE (XEXP (x, 1)) == CONST_INT)
        !           467:        fmt = "e";      /* all constant rotate counts are short */
        !           468:       break;
        !           469:     case PLUS:
        !           470:       /* Check for small negative integer operand: subl2 can be used with
        !           471:         a short positive constant instead.  */
        !           472:       if (GET_CODE (XEXP (x, 1)) == CONST_INT)
        !           473:        if ((unsigned)(INTVAL (XEXP (x, 1)) + 63) < 127)
        !           474:          fmt = "e";
        !           475:     case MINUS:
        !           476:       c = (mode == DFmode) ? 13 : 8;   /* 6/8 on VAX 9000, 16/15 on VAX 2 */
        !           477:     case IOR:
        !           478:     case XOR:
        !           479:       c = 3;
        !           480:       break;
        !           481:     case AND:
        !           482:       /* AND is special because the first operand is complemented. */
        !           483:       c = 3;
        !           484:       if (GET_CODE (XEXP (x, 0)) == CONST_INT)
        !           485:        {
        !           486:          if ((unsigned)~INTVAL (XEXP (x, 0)) > 63)
        !           487:            c = 4;
        !           488:          fmt = "e";
        !           489:          i = 1;
        !           490:        }
        !           491:       break;
        !           492:     case NEG:
        !           493:       if (mode == DFmode)
        !           494:        return 9;
        !           495:       else if (mode == SFmode)
        !           496:        return 6;
        !           497:       else if (mode == DImode)
        !           498:        return 4;
        !           499:     case NOT:
        !           500:       return 2;
        !           501:     case ZERO_EXTRACT:
        !           502:     case SIGN_EXTRACT:
        !           503:       c = 15;
        !           504:       break;
        !           505:     case MEM:
        !           506:       if (mode == DImode || mode == DFmode)
        !           507:        c = 5;                          /* 7 on VAX 2 */
        !           508:       else
        !           509:        c = 3;                          /* 4 on VAX 2 */
        !           510:       x = XEXP (x, 0);
        !           511:       if (GET_CODE (x) == REG || GET_CODE (x) == POST_INC)
        !           512:        return c;
        !           513:       return c + vax_address_cost (x);
        !           514:     default:
        !           515:       c = 3;
        !           516:       break;
        !           517:     }
        !           518: 
        !           519: 
        !           520:   /* Now look inside the expression.  Operands which are not registers or
        !           521:      short constants add to the cost.
        !           522: 
        !           523:      FMT and I may have been adjusted in the switch above for instructions
        !           524:      which require special handling */
        !           525: 
        !           526:   while (*fmt++ == 'e')
        !           527:     {
        !           528:       register rtx op = XEXP (x, i++);
        !           529:       code = GET_CODE (op);
        !           530: 
        !           531:       /* A NOT is likely to be found as the first operand of an AND
        !           532:         (in which case the relevant cost is of the operand inside
        !           533:         the not) and not likely to be found anywhere else.  */
        !           534:       if (code == NOT)
        !           535:        op = XEXP (op, 0), code = GET_CODE (op);
        !           536: 
        !           537:       switch (code)
        !           538:        {
        !           539:        case CONST_INT:
        !           540:          if ((unsigned)INTVAL (op) > 63 && GET_MODE (x) != QImode)
        !           541:            c += 1;             /* 2 on VAX 2 */
        !           542:          break;
        !           543:        case CONST:
        !           544:        case LABEL_REF:
        !           545:        case SYMBOL_REF:
        !           546:          c += 1;               /* 2 on VAX 2 */
        !           547:          break;
        !           548:        case CONST_DOUBLE:
        !           549:          if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT)
        !           550:            {
        !           551:              /* Registers are faster than floating point constants -- even
        !           552:                 those constants which can be encoded in a single byte.  */
        !           553:              if (vax_float_literal (op))
        !           554:                c++;
        !           555:              else
        !           556:                c += (GET_MODE (x) == DFmode) ? 3 : 2;
        !           557:            }
        !           558:          else
        !           559:            {
        !           560:              if (CONST_DOUBLE_HIGH (op) != 0
        !           561:                  || (unsigned)CONST_DOUBLE_LOW (op) > 63)
        !           562:                c += 2;
        !           563:            }
        !           564:          break;
        !           565:        case MEM:
        !           566:          c += 1;               /* 2 on VAX 2 */
        !           567:          if (GET_CODE (XEXP (op, 0)) != REG)
        !           568:            c += vax_address_cost (XEXP (op, 0));
        !           569:          break;
        !           570:        case REG:
        !           571:        case SUBREG:
        !           572:          break;
        !           573:        default:
        !           574:          c += 1;
        !           575:          break;
        !           576:        }
        !           577:     }
        !           578:   return c;
        !           579: }
        !           580: 
        !           581: /* Check a `double' value for validity for a particular machine mode.  */
        !           582: 
        !           583: static char *float_strings[] =
        !           584: {
        !           585:    "1.70141173319264430e+38", /* 2^127 (2^24 - 1) / 2^24 */
        !           586:   "-1.70141173319264430e+38",
        !           587:    "2.93873587705571877e-39", /* 2^-128 */
        !           588:   "-2.93873587705571877e-39"
        !           589: };
        !           590: 
        !           591: static REAL_VALUE_TYPE float_values[4];
        !           592: 
        !           593: static int inited_float_values = 0;
        !           594: 
        !           595: 
        !           596: void
        !           597: check_float_value (mode, d)
        !           598:      enum machine_mode mode;
        !           599:      REAL_VALUE_TYPE *d;
        !           600: {
        !           601: 
        !           602:   if (inited_float_values == 0)
        !           603:     {
        !           604:       int i;
        !           605:       for (i = 0; i < 4; i++)
        !           606:        {
        !           607:          float_values[i] = REAL_VALUE_ATOF (float_strings[i], DFmode);
        !           608:        }
        !           609:     inited_float_values = 1;
        !           610:     }
        !           611: 
        !           612:   if ((mode) == SFmode)
        !           613:     {
        !           614:       REAL_VALUE_TYPE r;
        !           615:       bcopy (d, &r, sizeof (REAL_VALUE_TYPE));
        !           616:       if (REAL_VALUES_LESS (float_values[0], r))
        !           617:        {
        !           618:          error ("magnitude of constant too large for `float'");
        !           619:          bcopy (&float_values[0], d, sizeof (REAL_VALUE_TYPE));
        !           620:        }
        !           621:       else if (REAL_VALUES_LESS (r, float_values[1]))
        !           622:        {
        !           623:          error ("magnitude of constant too large for `float'");
        !           624:          bcopy (&float_values[1], d, sizeof (REAL_VALUE_TYPE));
        !           625:        }
        !           626:       else if (REAL_VALUES_LESS (dconst0, r)
        !           627:                && REAL_VALUES_LESS (r, float_values[2]))
        !           628:        {
        !           629:          warning ("`float' constant truncated to zero");
        !           630:          bcopy (&dconst0, d, sizeof (REAL_VALUE_TYPE));
        !           631:        }
        !           632:       else if (REAL_VALUES_LESS (r, dconst0)
        !           633:                && REAL_VALUES_LESS (float_values[3], r))
        !           634:        {
        !           635:          warning ("`float' constant truncated to zero");
        !           636:          bcopy (&dconst0, d, sizeof (REAL_VALUE_TYPE));
        !           637:        }
        !           638:     }
        !           639: }
        !           640: 
        !           641: /* Linked list of all externals that are to be emitted when optimizing
        !           642:    for the global pointer if they haven't been declared by the end of
        !           643:    the program with an appropriate .comm or initialization.  */
        !           644: 
        !           645: struct extern_list {
        !           646:   struct extern_list *next;    /* next external */
        !           647:   char *name;                  /* name of the external */
        !           648: } *extern_head = 0;
        !           649: 
        !           650: /* Return 1 if NAME has already had an external definition;
        !           651:    0 if it has not (so caller should output one).  */
        !           652: 
        !           653: int
        !           654: vms_check_external (name)
        !           655:      char *name;
        !           656: {
        !           657:   register struct extern_list *p;
        !           658: 
        !           659:   for (p = extern_head; p; p = p->next)
        !           660:     if (!strcmp (p->name, name))
        !           661:       return 1;
        !           662: 
        !           663:   p = (struct extern_list *)permalloc ((long) sizeof (struct extern_list));
        !           664:   p->next = extern_head;
        !           665:   p->name = name;
        !           666:   extern_head = p;
        !           667:   return 0;
        !           668: }
        !           669: 
        !           670: #ifdef VMS
        !           671: /* Additional support code for VMS. */
        !           672: 
        !           673: #ifdef QSORT_WORKAROUND
        !           674:   /*
        !           675:        Do not use VAXCRTL's qsort() due to a severe bug:  once you've
        !           676:        sorted something which has a size that's an exact multiple of 4
        !           677:        and is longword aligned, you cannot safely sort anything which
        !           678:        is either not a multiple of 4 in size or not longword aligned.
        !           679:        A static "move-by-longword" optimization flag inside qsort() is
        !           680:        never reset.  This is known of affect VMS V4.6 through VMS V5.5-1.
        !           681: 
        !           682:        In this work-around an insertion sort is used for simplicity.
        !           683:        The qsort code from glibc should probably be used instead.
        !           684:    */
        !           685: void
        !           686: not_qsort (array, count, size, compare)
        !           687:      void *array;
        !           688:      unsigned count, size;
        !           689:      int (*compare)();
        !           690: {
        !           691: 
        !           692:   if (size == sizeof (short))
        !           693:     {
        !           694:       register int i;
        !           695:       register short *next, *prev;
        !           696:       short tmp, *base = array;
        !           697: 
        !           698:       for (next = base, i = count - 1; i > 0; i--)
        !           699:        {
        !           700:          prev = next++;
        !           701:          if ((*compare)(next, prev) < 0)
        !           702:            {
        !           703:              tmp = *next;
        !           704:              do  *(prev + 1) = *prev;
        !           705:                while (--prev >= base ? (*compare)(&tmp, prev) < 0 : 0);
        !           706:              *(prev + 1) = tmp;
        !           707:            }
        !           708:        }
        !           709:     }
        !           710:   else if (size == sizeof (long))
        !           711:     {
        !           712:       register int i;
        !           713:       register long *next, *prev;
        !           714:       long tmp, *base = array;
        !           715: 
        !           716:       for (next = base, i = count - 1; i > 0; i--)
        !           717:        {
        !           718:          prev = next++;
        !           719:          if ((*compare)(next, prev) < 0)
        !           720:            {
        !           721:              tmp = *next;
        !           722:              do  *(prev + 1) = *prev;
        !           723:                while (--prev >= base ? (*compare)(&tmp, prev) < 0 : 0);
        !           724:              *(prev + 1) = tmp;
        !           725:            }
        !           726:        }
        !           727:     }
        !           728:   else  /* arbitrary size */
        !           729:     {
        !           730: #ifdef USE_C_ALLOCA
        !           731:       extern void *alloca ();
        !           732: #endif
        !           733:       register int i;
        !           734:       register char *next, *prev, *tmp = alloca (size), *base = array;
        !           735: 
        !           736:       for (next = base, i = count - 1; i > 0; i--)
        !           737:        {   /* count-1 forward iterations */
        !           738:          prev = next,  next += size;           /* increment front pointer */
        !           739:          if ((*compare)(next, prev) < 0)
        !           740:            {   /* found element out of order; move others up then re-insert */
        !           741:              memcpy (tmp, next, size);         /* save smaller element */
        !           742:              do { memcpy (prev + size, prev, size); /* move larger elem. up */
        !           743:                   prev -= size;                /* decrement back pointer */
        !           744:                 } while (prev >= base ? (*compare)(tmp, prev) < 0 : 0);
        !           745:              memcpy (prev + size, tmp, size);  /* restore small element */
        !           746:            }
        !           747:        }
        !           748: #ifdef USE_C_ALLOCA
        !           749:       alloca (0);
        !           750: #endif
        !           751:     }
        !           752: 
        !           753:   return;
        !           754: }
        !           755: #endif /* QSORT_WORKAROUND */
        !           756: 
        !           757: #endif /* VMS */

unix.superglobalmegacorp.com

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