Annotation of GNUtools/cc/config/vax/vax.c, revision 1.1.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.