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

1.1       root        1: /* Subroutines for assembler code output on the NS32000.
1.1.1.3 ! root        2:    Copyright (C) 1988, 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: /* Some output-actions in ns32k.md need these.  */
                     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"
                     32: 
                     33: #ifdef OSF_OS
                     34: int ns32k_num_files = 0;
                     35: #endif
                     36: 
                     37: void
                     38: trace (s, s1, s2)
                     39:      char *s, *s1, *s2;
                     40: {
                     41:   fprintf (stderr, s, s1, s2);
                     42: }
                     43: 
                     44: /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */ 
                     45: 
                     46: int
                     47: hard_regno_mode_ok (regno, mode)
                     48:      int regno;
                     49:      enum machine_mode mode;
                     50: {
                     51:   switch (mode)
                     52:     {
                     53:     case QImode:
                     54:     case HImode:
                     55:     case PSImode:
                     56:     case SImode:
                     57:     case PDImode:
                     58:     case VOIDmode:
                     59:     case BLKmode:
                     60:       if (regno < 8 || regno == 16 || regno == 17)
                     61:        return 1;
                     62:       else
                     63:        return 0;
                     64: 
                     65:     case DImode:
                     66:       if (regno < 8 && (regno & 1) == 0)
                     67:        return 1;
                     68:       else
                     69:        return 0;
                     70: 
                     71:     case SFmode:
                     72:     case SCmode:
                     73:       if (TARGET_32081)
                     74:        {
                     75:          if (regno < 16)
                     76:            return 1;
                     77:          else
                     78:            return 0;
                     79:        }
                     80:       else
                     81:        {
                     82:          if (regno < 8)
                     83:            return 1;
                     84:          else 
                     85:            return 0;
                     86:        }
                     87: 
                     88:     case DFmode:
                     89:     case DCmode:
                     90:       if ((regno & 1) == 0)
                     91:        {       
                     92:          if (TARGET_32081)
                     93:            {
                     94:              if (regno < 16)
                     95:                return 1;
                     96:              else
                     97:                return 0;
                     98:            }
                     99:          else
                    100:            {
                    101:              if (regno < 8)
                    102:                return 1;
                    103:              else
                    104:                return 0;
                    105:            }
                    106:        }
                    107:       else
                    108:        return 0;
                    109:     }
                    110: 
                    111:   /* Used to abort here, but simply saying "no" handles TImode
                    112:      much better.  */
                    113:   return 0;
                    114: }
                    115: 
                    116: /* ADDRESS_COST calls this.  This function is not optimal
                    117:    for the 32032 & 32332, but it probably is better than
                    118:    the default. */
                    119: 
                    120: int
                    121: calc_address_cost (operand)
                    122:      rtx operand;
                    123: {
                    124:   int i;
                    125:   int cost = 0;
                    126:   
                    127:   if (GET_CODE (operand) == MEM)
                    128:     cost += 3;
                    129:   if (GET_CODE (operand) == MULT)
                    130:     cost += 2;
                    131: #if 0
                    132:   if (GET_CODE (operand) == REG)
                    133:     cost += 1;                 /* not really, but the documentation
                    134:                                   says different amount of registers
                    135:                                   shouldn't return the same costs */
                    136: #endif
                    137:   switch (GET_CODE (operand))
                    138:     {
                    139:     case REG:
                    140:     case CONST:
                    141:     case CONST_INT:
                    142:     case CONST_DOUBLE:
                    143:     case SYMBOL_REF:
                    144:     case LABEL_REF:
                    145:     case POST_DEC:
                    146:     case PRE_DEC:
                    147:       break;
                    148:     case MULT:
                    149:     case MEM:
                    150:     case PLUS:
                    151:       for (i = 0; i < GET_RTX_LENGTH (GET_CODE (operand)); i++)
                    152:        {
                    153:          cost += calc_address_cost (XEXP (operand, i));
                    154:        }
                    155:     default:
                    156:       break;
                    157:     }
                    158:   return cost;
                    159: }
                    160: 
                    161: /* Return the register class of a scratch register needed to copy IN into
                    162:    or out of a register in CLASS in MODE.  If it can be done directly,
                    163:    NO_REGS is returned.  */
                    164: 
                    165: enum reg_class
                    166: secondary_reload_class (class, mode, in)
                    167:      enum reg_class class;
                    168:      enum machine_mode mode;
                    169:      rtx in;
                    170: {
                    171:   int regno = true_regnum (in);
                    172: 
                    173:   if (regno >= FIRST_PSEUDO_REGISTER)
                    174:     regno = -1;
                    175: 
                    176:   /* We can place anything into GENERAL_REGS and can put GENERAL_REGS
                    177:      into anything.  */
                    178:   if (class == GENERAL_REGS || (regno >= 0 && regno < 8))
                    179:     return NO_REGS;
                    180: 
                    181:   /* Constants, memory, and FP registers can go into FP registers.  */
                    182:   if ((regno == -1 || (regno >= 8 && regno < 16)) && (class == FLOAT_REGS))
                    183:     return NO_REGS;
                    184: 
                    185: #if 0 /* This isn't strictly true (can't move fp to sp or vice versa),
                    186:         so it's cleaner to use PREFERRED_RELOAD_CLASS
                    187:         to make the right things happen.  */
                    188:   if (regno >= 16 && class == GEN_AND_MEM_REGS)
                    189:     return NO_REGS;
                    190: #endif
                    191: 
                    192:   /* Otherwise, we need GENERAL_REGS. */
                    193:   return GENERAL_REGS;
                    194: }
                    195: /* Generate the rtx that comes from an address expression in the md file */
                    196: /* The expression to be build is BASE[INDEX:SCALE].  To recognize this,
                    197:    scale must be converted from an exponent (from ASHIFT) to a
                    198:    multiplier (for MULT). */
                    199: rtx
                    200: gen_indexed_expr (base, index, scale)
                    201:      rtx base, index, scale;
                    202: {
                    203:   rtx addr;
                    204: 
                    205:   /* This generates an illegal addressing mode, if BASE is
                    206:      fp or sp.  This is handled by PRINT_OPERAND_ADDRESS.  */
                    207:   if (GET_CODE (base) != REG && GET_CODE (base) != CONST_INT)
                    208:     base = gen_rtx (MEM, SImode, base);
                    209:   addr = gen_rtx (MULT, SImode, index,
                    210:                  gen_rtx (CONST_INT, VOIDmode, 1 << INTVAL (scale)));
                    211:   addr = gen_rtx (PLUS, SImode, base, addr);
                    212:   return addr;
                    213: }
                    214: 
                    215: /* Return 1 if OP is a valid operand of mode MODE.  This
                    216:    predicate rejects operands which do not have a mode
                    217:    (such as CONST_INT which are VOIDmode).  */
                    218: int
                    219: reg_or_mem_operand (op, mode)
                    220:      register rtx op;
                    221:      enum machine_mode mode;
                    222: {
                    223:   return (GET_MODE (op) == mode
                    224:          && (GET_CODE (op) == REG
                    225:              || GET_CODE (op) == SUBREG
                    226:              || GET_CODE (op) == MEM));
                    227: }
                    228: 
                    229: /* Return the best assembler insn template
                    230:    for moving operands[1] into operands[0] as a fullword.  */
                    231: 
                    232: static char *
                    233: singlemove_string (operands)
                    234:      rtx *operands;
                    235: {
                    236:   if (GET_CODE (operands[1]) == CONST_INT
                    237:       && INTVAL (operands[1]) <= 7
                    238:       && INTVAL (operands[1]) >= -8)
                    239:     return "movqd %1,%0";
                    240:   return "movd %1,%0";
                    241: }
                    242: 
                    243: char *
                    244: output_move_double (operands)
                    245:      rtx *operands;
                    246: {
1.1.1.2   root      247:   enum anon1 { REGOP, OFFSOP, PUSHOP, CNSTOP, RNDOP } optype0, optype1;
1.1       root      248:   rtx latehalf[2];
                    249: 
                    250:   /* First classify both operands.  */
                    251: 
                    252:   if (REG_P (operands[0]))
                    253:     optype0 = REGOP;
                    254:   else if (offsettable_memref_p (operands[0]))
                    255:     optype0 = OFFSOP;
                    256:   else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
1.1.1.2   root      257:     optype0 = PUSHOP;
1.1       root      258:   else
                    259:     optype0 = RNDOP;
                    260: 
                    261:   if (REG_P (operands[1]))
                    262:     optype1 = REGOP;
1.1.1.3 ! root      263:   else if (CONSTANT_P (operands[1])
1.1       root      264:           || GET_CODE (operands[1]) == CONST_DOUBLE)
                    265:     optype1 = CNSTOP;
                    266:   else if (offsettable_memref_p (operands[1]))
                    267:     optype1 = OFFSOP;
                    268:   else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
1.1.1.2   root      269:     optype1 = PUSHOP;
1.1       root      270:   else
                    271:     optype1 = RNDOP;
                    272: 
                    273:   /* Check for the cases that the operand constraints are not
                    274:      supposed to allow to happen.  Abort if we get one,
                    275:      because generating code for these cases is painful.  */
                    276: 
                    277:   if (optype0 == RNDOP || optype1 == RNDOP)
                    278:     abort ();
                    279: 
                    280:   /* Ok, we can do one word at a time.
                    281:      Normally we do the low-numbered word first,
                    282:      but if either operand is autodecrementing then we
                    283:      do the high-numbered word first.
                    284: 
                    285:      In either case, set up in LATEHALF the operands to use
                    286:      for the high-numbered word and in some cases alter the
                    287:      operands in OPERANDS to be suitable for the low-numbered word.  */
                    288: 
                    289:   if (optype0 == REGOP)
                    290:     latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
                    291:   else if (optype0 == OFFSOP)
                    292:     latehalf[0] = adj_offsettable_operand (operands[0], 4);
                    293:   else
                    294:     latehalf[0] = operands[0];
                    295: 
                    296:   if (optype1 == REGOP)
                    297:     latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
                    298:   else if (optype1 == OFFSOP)
                    299:     latehalf[1] = adj_offsettable_operand (operands[1], 4);
                    300:   else if (optype1 == CNSTOP)
1.1.1.3 ! root      301:     split_double (operands[1], &operands[1], &latehalf[1]);
1.1       root      302:   else
                    303:     latehalf[1] = operands[1];
                    304: 
1.1.1.2   root      305:   /* If insn is effectively movd N(sp),tos then we will do the
                    306:      high word first.  We should use the adjusted operand 1 (which is N+4(sp))
                    307:      for the low word as well, to compensate for the first decrement of sp.
                    308:      Given this, it doesn't matter which half we do "first".  */
                    309:   if (optype0 == PUSHOP
                    310:       && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
                    311:       && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
                    312:     operands[1] = latehalf[1];
                    313: 
1.1       root      314:   /* If one or both operands autodecrementing,
                    315:      do the two words, high-numbered first.  */
1.1.1.2   root      316:   else if (optype0 == PUSHOP || optype1 == PUSHOP)
                    317:     {
                    318:       output_asm_insn (singlemove_string (latehalf), latehalf);
                    319:       return singlemove_string (operands);
                    320:     }
                    321: 
                    322:   /* If the first move would clobber the source of the second one,
                    323:      do them in the other order.  */
1.1       root      324: 
1.1.1.2   root      325:   /* Overlapping registers.  */
                    326:   if (optype0 == REGOP && optype1 == REGOP
                    327:       && REGNO (operands[0]) == REGNO (latehalf[1]))
1.1       root      328:     {
1.1.1.2   root      329:       /* Do that word.  */
1.1       root      330:       output_asm_insn (singlemove_string (latehalf), latehalf);
1.1.1.2   root      331:       /* Do low-numbered word.  */
1.1       root      332:       return singlemove_string (operands);
                    333:     }
1.1.1.2   root      334:   /* Loading into a register which overlaps a register used in the address.  */
                    335:   else if (optype0 == REGOP && optype1 != REGOP
                    336:           && reg_overlap_mentioned_p (operands[0], operands[1]))
                    337:     {
                    338:       if (reg_mentioned_p (operands[0], XEXP (operands[1], 0))
                    339:          && reg_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
                    340:        {
                    341:          /* If both halves of dest are used in the src memory address,
1.1.1.3 ! root      342:             load the destination address into the low reg (operands[0]).
1.1.1.2   root      343:             Then it works to load latehalf first.  */
                    344:          rtx xops[2];
1.1.1.3 ! root      345:          xops[0] = XEXP (operands[1], 0);
1.1.1.2   root      346:          xops[1] = operands[0];
1.1.1.3 ! root      347:          output_asm_insn ("addr %a0,%1", xops);
1.1.1.2   root      348:          operands[1] = gen_rtx (MEM, DImode, operands[0]);
                    349:          latehalf[1] = adj_offsettable_operand (operands[1], 4);
                    350:          /* The first half has the overlap, Do the late half first.  */
                    351:          output_asm_insn (singlemove_string (latehalf), latehalf);
                    352:          /* Then clobber.  */
                    353:          return singlemove_string (operands);
                    354:        }
                    355:       if (reg_mentioned_p (operands[0], XEXP (operands[1], 0)))
                    356:        {
                    357:          /* The first half has the overlap, Do the late half first.  */
                    358:          output_asm_insn (singlemove_string (latehalf), latehalf);
                    359:          /* Then clobber.  */
                    360:          return singlemove_string (operands);
                    361:        }
                    362:     }
1.1       root      363: 
1.1.1.2   root      364:   /* Normal case.  Do the two words, low-numbered first.  */
1.1       root      365: 
                    366:   output_asm_insn (singlemove_string (operands), operands);
                    367: 
                    368:   operands[0] = latehalf[0];
                    369:   operands[1] = latehalf[1];
                    370:   return singlemove_string (operands);
                    371: }
                    372: 
                    373: int
                    374: check_reg (oper, reg)
                    375:      rtx oper;
                    376:      int reg;
                    377: {
                    378:   register int i;
                    379: 
                    380:   if (oper == 0)
                    381:     return 0;
                    382:   switch (GET_CODE(oper))
                    383:     {
                    384:     case REG:
                    385:       return (REGNO(oper) == reg) ? 1 : 0;
                    386:     case MEM:
                    387:       return check_reg(XEXP(oper, 0), reg);
                    388:     case PLUS:
                    389:     case MULT:
                    390:       return check_reg(XEXP(oper, 0), reg) || check_reg(XEXP(oper, 1), reg);
                    391:     }
                    392:   return 0;
                    393: }
1.1.1.3 ! root      394: 
        !           395: /* Returns 1 if OP contains a global symbol reference */
        !           396: 
        !           397: int
        !           398: global_symbolic_reference_mentioned_p (op, f)
        !           399:      rtx op;
        !           400:      int f;
        !           401: {
        !           402:   register char *fmt;
        !           403:   register int i;
        !           404: 
        !           405:   if (GET_CODE (op) == SYMBOL_REF)
        !           406:     {
        !           407:       if (! SYMBOL_REF_FLAG (op))
        !           408:        return 1;
        !           409:       else
        !           410:         return 0;
        !           411:     }
        !           412:   else if (f && GET_CODE (op) != CONST)
        !           413:     return 0;
        !           414: 
        !           415:   fmt = GET_RTX_FORMAT (GET_CODE (op));
        !           416:   for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
        !           417:     {
        !           418:       if (fmt[i] == 'E')
        !           419:        {
        !           420:          register int j;
        !           421: 
        !           422:          for (j = XVECLEN (op, i) - 1; j >= 0; j--)
        !           423:            if (global_symbolic_reference_mentioned_p (XVECEXP (op, i, j), 0))
        !           424:              return 1;
        !           425:        }
        !           426:       else if (fmt[i] == 'e' 
        !           427:               && global_symbolic_reference_mentioned_p (XEXP (op, i), 0))
        !           428:        return 1;
        !           429:     }
        !           430: 
        !           431:   return 0;
        !           432: }
        !           433: 
1.1       root      434: 
                    435: /* PRINT_OPERAND is defined to call this function,
                    436:    which is easier to debug than putting all the code in
                    437:    a macro definition in ns32k.h.  */
                    438: 
                    439: void
                    440: print_operand (file, x, code)
                    441:      FILE *file;
                    442:      rtx x;
                    443:      char code;
                    444: {
                    445:   if (code == '$')
                    446:     PUT_IMMEDIATE_PREFIX (file);
                    447:   else if (code == '?')
                    448:     PUT_EXTERNAL_PREFIX (file);
                    449:   else if (GET_CODE (x) == REG)
                    450:     fprintf (file, "%s", reg_names[REGNO (x)]);
                    451:   else if (GET_CODE (x) == MEM)
                    452:     {
                    453:       rtx tmp = XEXP (x, 0);
1.1.1.3 ! root      454:       output_address (XEXP (x, 0));
1.1       root      455:     }
1.1.1.3 ! root      456:   else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != VOIDmode)
1.1       root      457:     {
                    458:       if (GET_MODE (x) == DFmode)
                    459:        { 
                    460:          union { double d; int i[2]; } u;
                    461:          u.i[0] = CONST_DOUBLE_LOW (x); u.i[1] = CONST_DOUBLE_HIGH (x);
                    462:          PUT_IMMEDIATE_PREFIX(file);
                    463: #ifdef SEQUENT_ASM
                    464:          /* Sequent likes it's floating point constants as integers */
                    465:          fprintf (file, "0Dx%08x%08x", u.i[1], u.i[0]);
                    466: #else
                    467: #ifdef ENCORE_ASM
                    468:          fprintf (file, "0f%.20e", u.d); 
                    469: #else
                    470:          fprintf (file, "0d%.20e", u.d); 
                    471: #endif
                    472: #endif
                    473:        }
                    474:       else
                    475:        { 
                    476:          union { double d; int i[2]; } u;
                    477:          u.i[0] = CONST_DOUBLE_LOW (x); u.i[1] = CONST_DOUBLE_HIGH (x);
                    478:          PUT_IMMEDIATE_PREFIX (file);
                    479: #ifdef SEQUENT_ASM
                    480:          /* We have no way of winning if we can't get the bits
                    481:             for a sequent floating point number.  */
                    482: #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
                    483:          abort ();
                    484: #endif
                    485:          {
                    486:            union { float f; long l; } uu;
                    487:            uu.f = u.d;
                    488:            fprintf (file, "0Fx%08x", uu.l);
                    489:          }
                    490: #else
                    491:          fprintf (file, "0f%.20e", u.d); 
                    492: #endif
                    493:        }
                    494:     }
                    495:   else
                    496:     {
                    497: #ifdef NO_IMMEDIATE_PREFIX_IF_SYMBOLIC
                    498:       if (GET_CODE (x) == CONST_INT)
                    499: #endif
                    500:        PUT_IMMEDIATE_PREFIX (file);
                    501:       output_addr_const (file, x);
                    502:     }
                    503: }
                    504: 
                    505: /* PRINT_OPERAND_ADDRESS is defined to call this function,
                    506:    which is easier to debug than putting all the code in
                    507:    a macro definition in ns32k.h .  */
                    508: 
                    509: /* Completely rewritten to get this to work with Gas for PC532 Mach.
                    510:    This function didn't work and I just wasn't able (nor very willing) to
                    511:    figure out how it worked.
                    512:    90-11-25 Tatu Yl|nen <[email protected]> */
                    513: 
                    514: print_operand_address (file, addr)
                    515:      register FILE *file;
                    516:      register rtx addr;
                    517: {
                    518:   static char scales[] = { 'b', 'w', 'd', 0, 'q', };
                    519:   rtx offset, base, indexexp, tmp;
                    520:   int scale;
1.1.1.3 ! root      521:   extern int flag_pic;
1.1       root      522: 
                    523:   if (GET_CODE (addr) == PRE_DEC || GET_CODE (addr) == POST_DEC)
                    524:     {
                    525:       fprintf (file, "tos");
                    526:       return;
                    527:     }
                    528: 
                    529:   offset = NULL;
                    530:   base = NULL;
                    531:   indexexp = NULL;
                    532:   while (addr != NULL)
                    533:     {
                    534:       if (GET_CODE (addr) == PLUS)
                    535:        {
                    536:          if (GET_CODE (XEXP (addr, 0)) == PLUS)
                    537:            {
                    538:              tmp = XEXP (addr, 1);
                    539:              addr = XEXP (addr, 0);
                    540:            }
                    541:          else
                    542:            {
                    543:              tmp = XEXP (addr,0);
                    544:              addr = XEXP (addr,1);
                    545:            }
                    546:        }
                    547:       else
                    548:        {
                    549:          tmp = addr;
                    550:          addr = NULL;
                    551:        }
                    552:       switch (GET_CODE (tmp))
                    553:        {
                    554:        case PLUS:
                    555:          abort ();
                    556:        case MEM:
                    557:          if (base)
                    558:            {
                    559:              indexexp = base;
                    560:              base = tmp;
                    561:            }
                    562:          else
                    563:            base = tmp;
                    564:          break;
                    565:        case REG:
                    566:          if (REGNO (tmp) < 8)
                    567:            if (base)
                    568:              {
                    569:                indexexp = tmp;
                    570:              }
                    571:            else
                    572:              base = tmp;
                    573:          else
                    574:            if (base)
                    575:              {
                    576:                indexexp = base;
                    577:                base = tmp;
                    578:              }
                    579:            else
                    580:              base = tmp;
                    581:          break;
                    582:        case MULT:
                    583:          indexexp = tmp;
                    584:          break;
1.1.1.3 ! root      585:        case SYMBOL_REF:
        !           586:          if (flag_pic && ! CONSTANT_POOL_ADDRESS_P (tmp)
        !           587:              && ! SYMBOL_REF_FLAG (tmp))
        !           588:            {
        !           589:              if (base)
        !           590:                {
        !           591:                  if (indexexp)
        !           592:                    abort ();
        !           593:                  indexexp = base;
        !           594:                }
        !           595:              base = tmp;
        !           596:              break;
        !           597:            }
1.1       root      598:        case CONST:
1.1.1.3 ! root      599:          if (flag_pic && GET_CODE (tmp) == CONST)
        !           600:            {
        !           601:              rtx sym, off, tmp1;
        !           602:              tmp1 = XEXP (tmp,0);
        !           603:              if (GET_CODE (tmp1)  != PLUS)
        !           604:                abort ();
        !           605: 
        !           606:              sym = XEXP (tmp1,0);
        !           607:              if (GET_CODE (sym) != SYMBOL_REF)
        !           608:                {
        !           609:                  off = sym;
        !           610:                  sym = XEXP (tmp1,1);
        !           611:                }
        !           612:              else
        !           613:                off = XEXP (tmp1,1);
        !           614:              if (GET_CODE (sym) == SYMBOL_REF)
        !           615:                {
        !           616:                  if (GET_CODE (off) != CONST_INT)
        !           617:                    abort ();
        !           618: 
        !           619:                  if (CONSTANT_POOL_ADDRESS_P (sym)
        !           620:                      || SYMBOL_REF_FLAG (sym))
        !           621:                    {
        !           622:                      SYMBOL_REF_FLAG (tmp) = 1;
        !           623:                    }
        !           624:                  else
        !           625:                    {
        !           626:                      if (base)
        !           627:                        {
        !           628:                          if (indexexp)
        !           629:                            abort ();
        !           630: 
        !           631:                          indexexp = base;
        !           632:                        }
        !           633: 
        !           634:                      if (offset != 0)
        !           635:                        abort ();
        !           636: 
        !           637:                      base = sym;
        !           638:                      offset = off;
        !           639:                      break;
        !           640:                    }
        !           641:                }
        !           642:            }
1.1       root      643:        case CONST_INT:
                    644:        case LABEL_REF:
                    645:          if (offset)
                    646:            offset = gen_rtx (PLUS, SImode, tmp, offset);
                    647:          else
                    648:            offset = tmp;
                    649:          break;
                    650:        default:
                    651:          abort ();
                    652:        }
                    653:     }
                    654:   if (! offset)
                    655:     offset = const0_rtx;
                    656: 
1.1.1.3 ! root      657:   if (base
        !           658: #ifndef INDEX_RATHER_THAN_BASE
        !           659:       && (flag_pic || TARGET_HIMEM)
        !           660:       && GET_CODE (base) != SYMBOL_REF 
        !           661:       && GET_CODE (offset) != CONST_INT
        !           662: #else
1.1       root      663:   /* This is a re-implementation of the SEQUENT_ADDRESS_BUG fix.  */
1.1.1.3 ! root      664: #endif
        !           665:       && !indexexp && GET_CODE (base) == REG
1.1       root      666:       && REG_OK_FOR_INDEX_P (base))
                    667:     {
                    668:       indexexp = base;
1.1.1.3 ! root      669:       base = NULL;
1.1       root      670:     }
                    671: 
                    672:   /* now, offset, base and indexexp are set */
1.1.1.3 ! root      673: #ifndef BASE_REG_NEEDED
1.1       root      674:   if (! base)
                    675:     {
                    676: #if defined (PC_RELATIVE) || defined (NO_ABSOLUTE_PREFIX_IF_SYMBOLIC)
                    677:       if (GET_CODE (offset) == CONST_INT)
                    678: #endif
                    679:        PUT_ABSOLUTE_PREFIX (file);
                    680:     }
1.1.1.3 ! root      681: #endif
1.1       root      682: 
                    683:   output_addr_const (file, offset);
                    684:   if (base) /* base can be (REG ...) or (MEM ...) */
                    685:     switch (GET_CODE (base))
                    686:       {
                    687:        /* now we must output base.  Possible alternatives are:
                    688:           (rN)       (REG ...)
                    689:           (sp)       (REG ...)
                    690:           (fp)       (REG ...)
                    691:           (pc)       (REG ...)  used for SYMBOL_REF and LABEL_REF, output
                    692:           (disp(fp)) (MEM ...)       just before possible [rX:y]
                    693:           (disp(sp)) (MEM ...)
                    694:           (disp(sb)) (MEM ...)
                    695:           */
                    696:       case REG:
                    697:        fprintf (file, "(%s)", reg_names[REGNO (base)]);
                    698:        break;
1.1.1.3 ! root      699:       case SYMBOL_REF:
        !           700:        if (! flag_pic)
        !           701:          abort ();
        !           702: 
        !           703:         fprintf (file, "(");
        !           704:        output_addr_const (file, base);
        !           705:        fprintf (file, "(sb))");
        !           706:         break;
1.1       root      707:       case MEM:
                    708:        addr = XEXP(base,0);
                    709:        base = NULL;
                    710:        offset = NULL;
                    711:        while (addr != NULL)
                    712:          {
                    713:            if (GET_CODE (addr) == PLUS)
                    714:              {
                    715:                if (GET_CODE (XEXP (addr, 0)) == PLUS)
                    716:                  {
                    717:                    tmp = XEXP (addr, 1);
                    718:                    addr = XEXP (addr, 0);
                    719:                  }
                    720:                else
                    721:                  {
                    722:                    tmp = XEXP (addr, 0);
                    723:                    addr = XEXP (addr, 1);
                    724:                  }
                    725:              }
                    726:            else
                    727:              {
                    728:                tmp = addr;
                    729:                addr = NULL;
                    730:              }
                    731:            switch (GET_CODE (tmp))
                    732:              {
                    733:              case REG:
                    734:                base = tmp;
                    735:                break;
                    736:              case CONST:
                    737:              case CONST_INT:
                    738:              case SYMBOL_REF:
                    739:              case LABEL_REF:
                    740:                if (offset)
                    741:                  offset = gen_rtx (PLUS, SImode, tmp, offset);
                    742:                else
                    743:                  offset = tmp;
                    744:                break;
                    745:              default:
                    746:                abort ();
                    747:              }
                    748:          }
                    749:        if (! offset)
                    750:          offset = const0_rtx;
                    751:        fprintf (file, "(");
                    752:        output_addr_const (file, offset);
                    753:        if (base)
                    754:          fprintf (file, "(%s)", reg_names[REGNO (base)]);
                    755:        else if (TARGET_SB)
                    756:          fprintf (file, "(sb)");
                    757:        else
                    758:          abort ();
                    759:        fprintf (file, ")");
                    760:        break;
                    761:       default:
                    762:        abort ();
                    763:       }
                    764: #ifdef PC_RELATIVE
1.1.1.3 ! root      765:   else if (GET_CODE (offset) != CONST_INT)
        !           766:     fprintf (file, "(pc)");
        !           767: #ifdef BASE_REG_NEEDED
        !           768:   else if (TARGET_SB)
        !           769:     fprintf (file, "(sb)");
        !           770:   else
        !           771:     abort ();
1.1       root      772: #endif
1.1.1.3 ! root      773: #endif /* PC_RELATIVE */
        !           774: 
1.1       root      775:   /* now print index if we have one */
                    776:   if (indexexp)
                    777:     {
                    778:       if (GET_CODE (indexexp) == MULT)
                    779:        {
                    780:          scale = INTVAL (XEXP (indexexp, 1)) >> 1;
                    781:          indexexp = XEXP (indexexp, 0);
                    782:        }
                    783:       else
                    784:        scale = 0;
                    785:       if (GET_CODE (indexexp) != REG || REGNO (indexexp) >= 8)
                    786:        abort ();
                    787: 
                    788: #ifdef UTEK_ASM
                    789:       fprintf (file, "[%c`%s]",
                    790:               scales[scale],
                    791:               reg_names[REGNO (indexexp)]);
                    792: #else
                    793:       fprintf (file, "[%s:%c]",
                    794:               reg_names[REGNO (indexexp)],
                    795:               scales[scale]);
                    796: #endif
                    797:     }
                    798: }
                    799: 
                    800: /* National 32032 shifting is so bad that we can get
                    801:    better performance in many common cases by using other
                    802:    techniques.  */
                    803: char *
                    804: output_shift_insn (operands)
                    805:      rtx *operands;
                    806: {
                    807:   if (GET_CODE (operands[2]) == CONST_INT
                    808:       && INTVAL (operands[2]) > 0
                    809:       && INTVAL (operands[2]) <= 3)
                    810:     if (GET_CODE (operands[0]) == REG)
                    811:       {
                    812:        if (GET_CODE (operands[1]) == REG)
                    813:          {
                    814:            if (REGNO (operands[0]) == REGNO (operands[1]))
                    815:              {
                    816:                if (operands[2] == const1_rtx)
                    817:                  return "addd %0,%0";
                    818:                else if (INTVAL (operands[2]) == 2)
                    819:                  return "addd %0,%0\n\taddd %0,%0";
                    820:              }
                    821:            if (operands[2] == const1_rtx)
                    822:              return "movd %1,%0\n\taddd %0,%0";
                    823:            
                    824:            operands[1] = gen_indexed_expr (const0_rtx, operands[1], operands[2]);
                    825:            return "addr %a1,%0";
                    826:          }
                    827:        if (operands[2] == const1_rtx)
                    828:          return "movd %1,%0\n\taddd %0,%0";
                    829:       }
                    830:     else if (GET_CODE (operands[1]) == REG)
                    831:       {
                    832:        operands[1] = gen_indexed_expr (const0_rtx, operands[1], operands[2]);
                    833:        return "addr %a1,%0";
                    834:       }
                    835:     else if (INTVAL (operands[2]) == 1
                    836:             && GET_CODE (operands[1]) == MEM
                    837:             && rtx_equal_p (operands [0], operands[1]))
                    838:       {
                    839:        rtx temp = XEXP (operands[1], 0);
                    840:        
                    841:        if (GET_CODE (temp) == REG
                    842:            || (GET_CODE (temp) == PLUS
                    843:                && GET_CODE (XEXP (temp, 0)) == REG
                    844:                && GET_CODE (XEXP (temp, 1)) == CONST_INT))
                    845:          return "addd %0,%0";
                    846:       }
                    847:     else return "ashd %2,%0";
                    848:   return "ashd %2,%0";
                    849: }
1.1.1.3 ! root      850: 
        !           851: char *
        !           852: output_move_dconst (n, s)
        !           853:        int n;
        !           854:        char *s;
        !           855: {
        !           856:   static char r[32];
        !           857: 
        !           858:   if (n > -9 && n < 8)
        !           859:     strcpy (r, "movqd ");
        !           860:   else if (n > 0 && n < 256)
        !           861:     strcpy (r, "movzbd ");
        !           862:   else if (n > 0 && n < 65536)
        !           863:     strcpy (r, "movzwd ");
        !           864:   else if (n < 0 && n > -129)
        !           865:     strcpy (r, "movxbd ");
        !           866:   else if (n < 0 && n > -32769)
        !           867:     strcpy (r, "movxwd ");
        !           868:   else
        !           869:     strcpy (r, "movd ");
        !           870:   strcat (r, s);
        !           871:   return r;
        !           872: }

unix.superglobalmegacorp.com

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