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

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

unix.superglobalmegacorp.com

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