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

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

unix.superglobalmegacorp.com

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